diff options
| author | Tom Warren <twarren@nvidia.com> | 2013-03-06 16:16:22 -0700 | 
|---|---|---|
| committer | Tom Warren <twarren@nvidia.com> | 2013-03-14 11:06:43 -0700 | 
| commit | 8ca79b2ff467bda3bc1cfe7fe566f0c1189881dc (patch) | |
| tree | 7cc9230b3f5f27c89df60bcb20c41c24bcbbb160 | |
| parent | 8b7776b9f95d542d0e81357c4f8aa32f7bf466e5 (diff) | |
| download | olio-uboot-2014.01-8ca79b2ff467bda3bc1cfe7fe566f0c1189881dc.tar.xz olio-uboot-2014.01-8ca79b2ff467bda3bc1cfe7fe566f0c1189881dc.zip | |
Tegra30: Cardhu: Add pad config tables/code based on pinmux code
Pad config registers exist in APB_MISC_GP space, and control slew
rate, drive strengh, schmidt, high-speed, and low-power modes for
all of the pingroups in Tegra30. This builds off of the pinmux
way of constructing init tables to configure select pads (SDIOCFG,
for instance) during pinmux_init().
Currently, only SDIO1CFG is changed as per the TRM to work with
the SD-card slot on Cardhu.
Thanks to StephenW for the suggestion/original idea.
Signed-off-by: Tom Warren <twarren@nvidia.com>
Reviewed-by: Stephen Warren <swarren@nvidia.com>
| -rw-r--r-- | arch/arm/cpu/tegra30-common/pinmux.c | 190 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-tegra30/gp_padctrl.h | 6 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-tegra30/pinmux.h | 67 | ||||
| -rw-r--r-- | board/nvidia/cardhu/cardhu.c | 6 | ||||
| -rw-r--r-- | board/nvidia/cardhu/pinmux-config-cardhu.h | 21 | 
5 files changed, 285 insertions, 5 deletions
| diff --git a/arch/arm/cpu/tegra30-common/pinmux.c b/arch/arm/cpu/tegra30-common/pinmux.c index 122665fd3..eecf0580b 100644 --- a/arch/arm/cpu/tegra30-common/pinmux.c +++ b/arch/arm/cpu/tegra30-common/pinmux.c @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms and conditions of the GNU General Public License, @@ -38,6 +38,19 @@ struct tegra_pingroup_desc {  #define PMUX_LOCK_SHIFT		7  #define PMUX_IO_RESET_SHIFT	8 +#define PGRP_HSM_SHIFT		2 +#define PGRP_SCHMT_SHIFT	3 +#define PGRP_LPMD_SHIFT		4 +#define PGRP_LPMD_MASK		(3 << PGRP_LPMD_SHIFT) +#define PGRP_DRVDN_SHIFT	12 +#define PGRP_DRVDN_MASK		(0x7F << PGRP_DRVDN_SHIFT) +#define PGRP_DRVUP_SHIFT	20 +#define PGRP_DRVUP_MASK		(0x7F << PGRP_DRVUP_SHIFT) +#define PGRP_SLWR_SHIFT		28 +#define PGRP_SLWR_MASK		(3 << PGRP_SLWR_SHIFT) +#define PGRP_SLWF_SHIFT		30 +#define PGRP_SLWF_MASK		(3 << PGRP_SLWF_SHIFT) +  /* Convenient macro for defining pin group properties */  #define PIN(pg_name, vdd, f0, f1, f2, f3, iod)	\  	{						\ @@ -504,3 +517,178 @@ void pinmux_config_table(struct pingroup_config *config, int len)  	for (i = 0; i < len; i++)  		pinmux_config_pingroup(&config[i]);  } + +static int padgrp_set_drvup_slwf(enum pdrive_pingrp pad, +				int slwf) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_slwf = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check on pad and slwf */ +	assert(pmux_padgrp_isvalid(pad)); +	assert(pmux_pad_slw_isvalid(slwf)); + +	/* NONE means unspecified/do not change/use POR value */ +	if (slwf == PGRP_SLWF_NONE) +		return 0; + +	reg = readl(pad_slwf); +	reg &= ~PGRP_SLWF_MASK; +	reg |= (slwf << PGRP_SLWF_SHIFT); +	writel(reg, pad_slwf); + +	return 0; +} + +static int padgrp_set_drvdn_slwr(enum pdrive_pingrp pad, int slwr) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_slwr = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check on pad and slwr */ +	assert(pmux_padgrp_isvalid(pad)); +	assert(pmux_pad_slw_isvalid(slwr)); + +	/* NONE means unspecified/do not change/use POR value */ +	if (slwr == PGRP_SLWR_NONE) +		return 0; + +	reg = readl(pad_slwr); +	reg &= ~PGRP_SLWR_MASK; +	reg |= (slwr << PGRP_SLWR_SHIFT); +	writel(reg, pad_slwr); + +	return 0; +} + +static int padgrp_set_drvup(enum pdrive_pingrp pad, int drvup) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_drvup = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check on pad and drvup */ +	assert(pmux_padgrp_isvalid(pad)); +	assert(pmux_pad_drv_isvalid(drvup)); + +	/* NONE means unspecified/do not change/use POR value */ +	if (drvup == PGRP_DRVUP_NONE) +		return 0; + +	reg = readl(pad_drvup); +	reg &= ~PGRP_DRVUP_MASK; +	reg |= (drvup << PGRP_DRVUP_SHIFT); +	writel(reg, pad_drvup); + +	return 0; +} + +static int padgrp_set_drvdn(enum pdrive_pingrp pad, int drvdn) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_drvdn = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check on pad and drvdn */ +	assert(pmux_padgrp_isvalid(pad)); +	assert(pmux_pad_drv_isvalid(drvdn)); + +	/* NONE means unspecified/do not change/use POR value */ +	if (drvdn == PGRP_DRVDN_NONE) +		return 0; + +	reg = readl(pad_drvdn); +	reg &= ~PGRP_DRVDN_MASK; +	reg |= (drvdn << PGRP_DRVDN_SHIFT); +	writel(reg, pad_drvdn); + +	return 0; +} + +static int padgrp_set_lpmd(enum pdrive_pingrp pad, enum pgrp_lpmd lpmd) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_lpmd = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check pad and lpmd value */ +	assert(pmux_padgrp_isvalid(pad)); +	assert(pmux_pad_lpmd_isvalid(lpmd)); + +	/* NONE means unspecified/do not change/use POR value */ +	if (lpmd == PGRP_LPMD_NONE) +		return 0; + +	reg = readl(pad_lpmd); +	reg &= ~PGRP_LPMD_MASK; +	reg |= (lpmd << PGRP_LPMD_SHIFT); +	writel(reg, pad_lpmd); + +	return 0; +} + +static int padgrp_set_schmt(enum pdrive_pingrp pad, enum pgrp_schmt schmt) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_schmt = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check pad */ +	assert(pmux_padgrp_isvalid(pad)); + +	reg = readl(pad_schmt); +	reg &= ~(1 << PGRP_SCHMT_SHIFT); +	if (schmt == PGRP_SCHMT_ENABLE) +		reg |= (0x1 << PGRP_SCHMT_SHIFT); +	writel(reg, pad_schmt); + +	return 0; +} +static int padgrp_set_hsm(enum pdrive_pingrp pad, +			enum pgrp_hsm hsm) +{ +	struct pmux_tri_ctlr *pmt = +			(struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; +	u32 *pad_hsm = &pmt->pmt_drive[pad]; +	u32 reg; + +	/* Error check pad */ +	assert(pmux_padgrp_isvalid(pad)); + +	reg = readl(pad_hsm); +	reg &= ~(1 << PGRP_HSM_SHIFT); +	if (hsm == PGRP_HSM_ENABLE) +		reg |= (0x1 << PGRP_HSM_SHIFT); +	writel(reg, pad_hsm); + +	return 0; +} + +void padctrl_config_pingroup(struct padctrl_config *config) +{ +	enum pdrive_pingrp pad = config->padgrp; + +	padgrp_set_drvup_slwf(pad, config->slwf); +	padgrp_set_drvdn_slwr(pad, config->slwr); +	padgrp_set_drvup(pad, config->drvup); +	padgrp_set_drvdn(pad, config->drvdn); +	padgrp_set_lpmd(pad, config->lpmd); +	padgrp_set_schmt(pad, config->schmt); +	padgrp_set_hsm(pad, config->hsm); +} + +void padgrp_config_table(struct padctrl_config *config, int len) +{ +	int i; + +	for (i = 0; i < len; i++) +		padctrl_config_pingroup(&config[i]); +} diff --git a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h index 9b383d0e7..23d184f2d 100644 --- a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h +++ b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h @@ -56,4 +56,10 @@ struct apb_misc_gp_ctlr {  	u32	sdio1cfg;	/* 0xEC: APB_MISC_GP_SDIO1CFGPADCTRL */  }; +/* SDMMC1/3 settings from section 24.6 of T30 TRM */ +#define SDIOCFG_DRVUP_SLWF	1 +#define SDIOCFG_DRVDN_SLWR	1 +#define SDIOCFG_DRVUP		0x2E +#define SDIOCFG_DRVDN		0x2A +  #endif	/* _TEGRA30_GP_PADCTRL_H_ */ diff --git a/arch/arm/include/asm/arch-tegra30/pinmux.h b/arch/arm/include/asm/arch-tegra30/pinmux.h index 341951bfc..a9e1b462c 100644 --- a/arch/arm/include/asm/arch-tegra30/pinmux.h +++ b/arch/arm/include/asm/arch-tegra30/pinmux.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms and conditions of the GNU General Public License, @@ -531,6 +531,63 @@ enum pmux_vddio {  	PMUX_VDDIO_NONE  }; +#define PGRP_SLWF_NONE	-1 +#define PGRP_SLWF_MAX	3 +#define	PGRP_SLWR_NONE	PGRP_SLWF_NONE +#define PGRP_SLWR_MAX	PGRP_SLWF_MAX + +#define PGRP_DRVUP_NONE	-1 +#define PGRP_DRVUP_MAX	127 +#define	PGRP_DRVDN_NONE	PGRP_DRVUP_NONE +#define PGRP_DRVDN_MAX	PGRP_DRVUP_MAX + +/* return 1 if a padgrp is in range */ +#define pmux_padgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PDRIVE_PINGROUP_COUNT)) + +/* return 1 if a slew-rate rising/falling edge value is in range */ +#define pmux_pad_slw_isvalid(slw) (((slw) >= 0) && ((slw) <= PGRP_SLWF_MAX)) + +/* return 1 if a driver output pull-up/down strength code value is in range */ +#define pmux_pad_drv_isvalid(drv) (((drv) >= 0) && ((drv) <= PGRP_DRVUP_MAX)) + +/* return 1 if a low-power mode value is in range */ +#define pmux_pad_lpmd_isvalid(lpm) (((lpm) >= 0) && ((lpm) <= PGRP_LPMD_X)) + +/* Defines a pin group cfg's low-power mode select */ +enum pgrp_lpmd { +	PGRP_LPMD_X8 = 0, +	PGRP_LPMD_X4, +	PGRP_LPMD_X2, +	PGRP_LPMD_X, +	PGRP_LPMD_NONE = -1, +}; + +/* Defines whether a pin group cfg's schmidt is enabled or not */ +enum pgrp_schmt { +	PGRP_SCHMT_DISABLE = 0, +	PGRP_SCHMT_ENABLE = 1, +}; + +/* Defines whether a pin group cfg's high-speed mode is enabled or not */ +enum pgrp_hsm { +	PGRP_HSM_DISABLE = 0, +	PGRP_HSM_ENABLE = 1, +}; + +/* + * This defines the configuration for a pin group's pad control config + */ +struct padctrl_config { +	enum pdrive_pingrp padgrp;	/* pin group PDRIVE_PINGRP_x */ +	int slwf;			/* falling edge slew         */ +	int slwr;			/* rising edge slew          */ +	int drvup;			/* pull-up drive strength    */ +	int drvdn;			/* pull-down drive strength  */ +	enum pgrp_lpmd lpmd;		/* low-power mode selection  */ +	enum pgrp_schmt schmt;		/* schmidt enable            */ +	enum pgrp_hsm hsm;		/* high-speed mode enable    */ +}; +  /* t30 pin drive group and pin mux registers */  #define PDRIVE_PINGROUP_OFFSET	(0x868 >> 2)  #define PMUX_OFFSET	((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ @@ -600,4 +657,12 @@ void pinmux_config_table(struct pingroup_config *config, int len);  /* Set a group of pins from a table */  void pinmux_init(void); +/** + * Set the GP pad configs + * + * @param config	List of config items + * @param len		Number of config items in list + */ +void padgrp_config_table(struct padctrl_config *config, int len); +  #endif	/* _TEGRA30_PINMUX_H_ */ diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c index df4cb6b72..08e9b7bd5 100644 --- a/board/nvidia/cardhu/cardhu.c +++ b/board/nvidia/cardhu/cardhu.c @@ -1,5 +1,5 @@  /* - *  (C) Copyright 2010-2012 + *  (C) Copyright 2010-2013   *  NVIDIA Corporation <www.nvidia.com>   *   * See file CREDITS for list of people who contributed to this @@ -23,6 +23,7 @@  #include <common.h>  #include <asm/arch/pinmux.h> +#include <asm/arch/gp_padctrl.h>  #include "pinmux-config-cardhu.h"  /* @@ -36,4 +37,7 @@ void pinmux_init(void)  	pinmux_config_table(unused_pins_lowpower,  		ARRAY_SIZE(unused_pins_lowpower)); + +	/* Initialize any non-default pad configs (APB_MISC_GP regs) */ +	padgrp_config_table(cardhu_padctrl, ARRAY_SIZE(cardhu_padctrl));  } diff --git a/board/nvidia/cardhu/pinmux-config-cardhu.h b/board/nvidia/cardhu/pinmux-config-cardhu.h index 8428bba78..51d2b9425 100644 --- a/board/nvidia/cardhu/pinmux-config-cardhu.h +++ b/board/nvidia/cardhu/pinmux-config-cardhu.h @@ -1,5 +1,5 @@  /* - * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved. + * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms and conditions of the GNU General Public License, @@ -53,6 +53,18 @@  		.ioreset	= PMUX_PIN_IO_RESET_##_ioreset	\  	} +#define DEFAULT_PADCFG(_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) \ +	{							\ +		.padgrp		= PDRIVE_PINGROUP_##_padgrp,	\ +		.slwf		= _slwf,			\ +		.slwr		= _slwr,			\ +		.drvup		= _drvup,			\ +		.drvdn		= _drvdn,			\ +		.lpmd		= PGRP_LPMD_##_lpmd,		\ +		.schmt		= PGRP_SCHMT_##_schmt,		\ +		.hsm		= PGRP_HSM_##_hsm,		\ +	} +  static struct pingroup_config tegra3_pinmux_common[] = {  	/* SDMMC1 pinmux */  	DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT), @@ -326,4 +338,9 @@ static struct pingroup_config unused_pins_lowpower[] = {  	DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, TRISTATE, OUTPUT),  }; -#endif /* _PINMUX_CONFIG_CARDHU_H_ */ +static struct padctrl_config cardhu_padctrl[] = { +	/* (_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */ +	DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \ +		SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE), +}; +#endif	/* _PINMUX_CONFIG_CARDHU_H_ */ |