From 477393e7875cf4261f107fdfb8887309ea7fc3f7 Mon Sep 17 00:00:00 2001 From: Tom Warren Date: Mon, 11 Mar 2013 16:43:49 -0700 Subject: [PATCH] Tegra114: Dalmore: 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, no padcfg entries exist. SDIO3CFG will be added when the MMC driver is added as per the TRM to work with the SD-card slot on Dalmore E1611. Signed-off-by: Tom Warren Reviewed-by: Stephen Warren --- arch/arm/cpu/tegra114-common/pinmux.c | 194 +++++++++++++++++++ arch/arm/include/asm/arch-tegra114/pinmux.h | 100 ++++++++-- board/nvidia/dalmore/pinmux-config-dalmore.h | 12 ++ 3 files changed, 292 insertions(+), 14 deletions(-) diff --git a/arch/arm/cpu/tegra114-common/pinmux.c b/arch/arm/cpu/tegra114-common/pinmux.c index 16368c5bc1..4983a05090 100644 --- a/arch/arm/cpu/tegra114-common/pinmux.c +++ b/arch/arm/cpu/tegra114-common/pinmux.c @@ -39,6 +39,19 @@ struct tegra_pingroup_desc { #define PMUX_IO_RESET_SHIFT 8 #define PMUX_RCV_SEL_SHIFT 9 +#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) \ { \ @@ -544,3 +557,184 @@ 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)); + + /* NONE means unspecified/do not change/use POR value */ + if (schmt == PGRP_SCHMT_NONE) + return 0; + + 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)); + + /* NONE means unspecified/do not change/use POR value */ + if (hsm == PGRP_HSM_NONE) + return 0; + + 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-tegra114/pinmux.h b/arch/arm/include/asm/arch-tegra114/pinmux.h index 53905cb8e9..9c22c08b6e 100644 --- a/arch/arm/include/asm/arch-tegra114/pinmux.h +++ b/arch/arm/include/asm/arch-tegra114/pinmux.h @@ -215,34 +215,35 @@ enum pdrive_pingrp { PDRIVE_PINGROUP_AT5, PDRIVE_PINGROUP_CDEV1, PDRIVE_PINGROUP_CDEV2, - PDRIVE_PINGROUP_CSUS, - PDRIVE_PINGROUP_DAP1, + PDRIVE_PINGROUP_DAP1 = 10, /* offset 0x890 */ PDRIVE_PINGROUP_DAP2, PDRIVE_PINGROUP_DAP3, PDRIVE_PINGROUP_DAP4, PDRIVE_PINGROUP_DBG, - PDRIVE_PINGROUP_SDIO3, + PDRIVE_PINGROUP_SDIO3 = 18, /* offset 0x8B0 */ PDRIVE_PINGROUP_SPI, PDRIVE_PINGROUP_UAA, PDRIVE_PINGROUP_UAB, PDRIVE_PINGROUP_UART2, PDRIVE_PINGROUP_UART3, - PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8ec */ - PDRIVE_PINGROUP_CRT = 36, /* offset 0x8f8 */ - PDRIVE_PINGROUP_DDC, + PDRIVE_PINGROUP_SDIO1 = 33, /* offset 0x8EC */ + PDRIVE_PINGROUP_DDC = 37, /* offset 0x8FC */ PDRIVE_PINGROUP_GMA, - PDRIVE_PINGROUP_GME, + PDRIVE_PINGROUP_GME = 42, /* offset 0x910 */ PDRIVE_PINGROUP_GMF, PDRIVE_PINGROUP_GMG, PDRIVE_PINGROUP_GMH, PDRIVE_PINGROUP_OWR, PDRIVE_PINGROUP_UAD, - PDRIVE_PINGROUP_GPV, PDRIVE_PINGROUP_DEV3 = 49, /* offset 0x92c */ PDRIVE_PINGROUP_CEC = 52, /* offset 0x938 */ - PDRIVE_PINGROUP_AT6, + PDRIVE_PINGROUP_AT6 = 75, /* offset 0x994 */ PDRIVE_PINGROUP_DAP5, PDRIVE_PINGROUP_VBUS, + PDRIVE_PINGROUP_AO3, + PDRIVE_PINGROUP_HVC, + PDRIVE_PINGROUP_SDIO4, + PDRIVE_PINGROUP_AO0, PDRIVE_PINGROUP_COUNT, }; @@ -470,10 +471,73 @@ enum pmux_vddio { PMUX_VDDIO_NONE }; -/* T114 pin drive group and pin mux registers */ -#define PDRIVE_PINGROUP_OFFSET (0x868 >> 2) -#define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ - PDRIVE_PINGROUP_COUNT) +#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 + +#define PGRP_SCHMT_NONE -1 +#define PGRP_HSM_NONE PGRP_SCHMT_NONE + +/* 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) == PGRP_SLWF_NONE) || \ + (((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) == PGRP_DRVUP_NONE) || \ + (((drv) >= 0) && ((drv) <= PGRP_DRVUP_MAX))) + +/* return 1 if a low-power mode value is in range */ +#define pmux_pad_lpmd_isvalid(lpm) (((lpm) == PGRP_LPMD_NONE) || \ + (((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 */ +}; + +/* t114 pin drive group and pin mux registers */ +#define PDRIVE_PINGROUP_OFFSET (0x868 >> 2) +#define PMUX_OFFSET ((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \ + PDRIVE_PINGROUP_COUNT) struct pmux_tri_ctlr { uint pmt_reserved0; /* ABP_MISC_PP_ reserved offset 00 */ uint pmt_reserved1; /* ABP_MISC_PP_ reserved offset 04 */ @@ -541,4 +605,12 @@ void pinmux_config_table(struct pingroup_config *config, int len); /* Set a group of pins from a table */ void pinmux_init(void); -#endif /* _TEGRA114_PINMUX_H_ */ +/** + * 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 /* _TEGRA114_PINMUX_H_ */ diff --git a/board/nvidia/dalmore/pinmux-config-dalmore.h b/board/nvidia/dalmore/pinmux-config-dalmore.h index cb48b3ba1f..3ef6f4eaf6 100644 --- a/board/nvidia/dalmore/pinmux-config-dalmore.h +++ b/board/nvidia/dalmore/pinmux-config-dalmore.h @@ -79,6 +79,18 @@ #define USB_PINMUX CEC_PINMUX +#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 tegra114_pinmux_common[] = { /* EXTPERIPH1 pinmux */ DEFAULT_PINMUX(CLK1_OUT, EXTPERIPH1, NORMAL, NORMAL, OUTPUT), -- 2.25.1