From 20e18e051fc42774c27f07200a389edfd4606c67 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 21 Sep 2011 12:40:06 +0000 Subject: [PATCH] tegra2: Add more pinmux functions This adds support for changing pinmux functions of pin groups. This is done by defining a PMUX_FUNC_... enum which can be used to select the function for each group using pinmux_set_func(). It is also possible to enable pullup/pulldown, and the existing tristate functionality is retained. Also provided is a means of configuring a list of pingroups by providing a configuration table to pinmux_config_table(). Signed-off-by: Simon Glass Tested-by: Tom Warren --- arch/arm/cpu/armv7/tegra2/pinmux.c | 522 +++++++++++++++++++++- arch/arm/include/asm/arch-tegra2/pinmux.h | 192 +++++++- board/nvidia/common/board.c | 42 +- 3 files changed, 707 insertions(+), 49 deletions(-) diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/armv7/tegra2/pinmux.c index 01a3d841b8..b053f90608 100644 --- a/arch/arm/cpu/armv7/tegra2/pinmux.c +++ b/arch/arm/cpu/armv7/tegra2/pinmux.c @@ -27,9 +27,463 @@ #include +/* + * This defines the order of the pin mux control bits in the registers. For + * some reason there is no correspendence between the tristate, pin mux and + * pullup/pulldown registers. + */ +enum pmux_ctlid { + /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */ + MUXCTL_UAA, + MUXCTL_UAB, + MUXCTL_UAC, + MUXCTL_UAD, + MUXCTL_UDA, + MUXCTL_RESERVED5, + MUXCTL_ATE, + MUXCTL_RM, + + MUXCTL_ATB, + MUXCTL_RESERVED9, + MUXCTL_ATD, + MUXCTL_ATC, + MUXCTL_ATA, + MUXCTL_KBCF, + MUXCTL_KBCE, + MUXCTL_SDMMC1, + + /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */ + MUXCTL_GMA, + MUXCTL_GMC, + MUXCTL_HDINT, + MUXCTL_SLXA, + MUXCTL_OWC, + MUXCTL_SLXC, + MUXCTL_SLXD, + MUXCTL_SLXK, + + MUXCTL_UCA, + MUXCTL_UCB, + MUXCTL_DTA, + MUXCTL_DTB, + MUXCTL_RESERVED28, + MUXCTL_DTC, + MUXCTL_DTD, + MUXCTL_DTE, + + /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */ + MUXCTL_DDC, + MUXCTL_CDEV1, + MUXCTL_CDEV2, + MUXCTL_CSUS, + MUXCTL_I2CP, + MUXCTL_KBCA, + MUXCTL_KBCB, + MUXCTL_KBCC, + + MUXCTL_IRTX, + MUXCTL_IRRX, + MUXCTL_DAP1, + MUXCTL_DAP2, + MUXCTL_DAP3, + MUXCTL_DAP4, + MUXCTL_GMB, + MUXCTL_GMD, + + /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */ + MUXCTL_GME, + MUXCTL_GPV, + MUXCTL_GPU, + MUXCTL_SPDO, + MUXCTL_SPDI, + MUXCTL_SDB, + MUXCTL_SDC, + MUXCTL_SDD, + + MUXCTL_SPIH, + MUXCTL_SPIG, + MUXCTL_SPIF, + MUXCTL_SPIE, + MUXCTL_SPID, + MUXCTL_SPIC, + MUXCTL_SPIB, + MUXCTL_SPIA, + + /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */ + MUXCTL_LPW0, + MUXCTL_LPW1, + MUXCTL_LPW2, + MUXCTL_LSDI, + MUXCTL_LSDA, + MUXCTL_LSPI, + MUXCTL_LCSN, + MUXCTL_LDC, + + MUXCTL_LSCK, + MUXCTL_LSC0, + MUXCTL_LSC1, + MUXCTL_LHS, + MUXCTL_LVS, + MUXCTL_LM0, + MUXCTL_LM1, + MUXCTL_LVP0, + + /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */ + MUXCTL_LD0, + MUXCTL_LD1, + MUXCTL_LD2, + MUXCTL_LD3, + MUXCTL_LD4, + MUXCTL_LD5, + MUXCTL_LD6, + MUXCTL_LD7, + + MUXCTL_LD8, + MUXCTL_LD9, + MUXCTL_LD10, + MUXCTL_LD11, + MUXCTL_LD12, + MUXCTL_LD13, + MUXCTL_LD14, + MUXCTL_LD15, + + /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */ + MUXCTL_LD16, + MUXCTL_LD17, + MUXCTL_LHP1, + MUXCTL_LHP2, + MUXCTL_LVP1, + MUXCTL_LHP0, + MUXCTL_RESERVED102, + MUXCTL_LPP, + + MUXCTL_LDI, + MUXCTL_PMC, + MUXCTL_CRTP, + MUXCTL_PTA, + MUXCTL_RESERVED108, + MUXCTL_KBCD, + MUXCTL_GPU7, + MUXCTL_DTF, + + MUXCTL_NONE = -1, +}; + +/* + * And this defines the order of the pullup/pulldown controls which are again + * in a different order + */ +enum pmux_pullid { + /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */ + PUCTL_ATA, + PUCTL_ATB, + PUCTL_ATC, + PUCTL_ATD, + PUCTL_ATE, + PUCTL_DAP1, + PUCTL_DAP2, + PUCTL_DAP3, + + PUCTL_DAP4, + PUCTL_DTA, + PUCTL_DTB, + PUCTL_DTC, + PUCTL_DTD, + PUCTL_DTE, + PUCTL_DTF, + PUCTL_GPV, + + /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */ + PUCTL_RM, + PUCTL_I2CP, + PUCTL_PTA, + PUCTL_GPU7, + PUCTL_KBCA, + PUCTL_KBCB, + PUCTL_KBCC, + PUCTL_KBCD, + + PUCTL_SPDI, + PUCTL_SPDO, + PUCTL_GPSLXAU, + PUCTL_CRTP, + PUCTL_SLXC, + PUCTL_SLXD, + PUCTL_SLXK, + + /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */ + PUCTL_CDEV1, + PUCTL_CDEV2, + PUCTL_SPIA, + PUCTL_SPIB, + PUCTL_SPIC, + PUCTL_SPID, + PUCTL_SPIE, + PUCTL_SPIF, + + PUCTL_SPIG, + PUCTL_SPIH, + PUCTL_IRTX, + PUCTL_IRRX, + PUCTL_GME, + PUCTL_RESERVED45, + PUCTL_XM2D, + PUCTL_XM2C, + + /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */ + PUCTL_UAA, + PUCTL_UAB, + PUCTL_UAC, + PUCTL_UAD, + PUCTL_UCA, + PUCTL_UCB, + PUCTL_LD17, + PUCTL_LD19_18, + + PUCTL_LD21_20, + PUCTL_LD23_22, + PUCTL_LS, + PUCTL_LC, + PUCTL_CSUS, + PUCTL_DDRC, + PUCTL_SDC, + PUCTL_SDD, + + /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */ + PUCTL_KBCF, + PUCTL_KBCE, + PUCTL_PMCA, + PUCTL_PMCB, + PUCTL_PMCC, + PUCTL_PMCD, + PUCTL_PMCE, + PUCTL_CK32, + + PUCTL_UDA, + PUCTL_SDMMC1, + PUCTL_GMA, + PUCTL_GMB, + PUCTL_GMC, + PUCTL_GMD, + PUCTL_DDC, + PUCTL_OWC, + + PUCTL_NONE = -1 +}; + +struct tegra_pingroup_desc { + const char *name; + enum pmux_func funcs[4]; + enum pmux_func func_safe; + enum pmux_vddio vddio; + enum pmux_ctlid ctl_id; + enum pmux_pullid pull_id; +}; + + +/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */ +#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5) + +/* Mask value for a tristate (within TRISTATE_REG(id)) */ +#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f)) + +/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */ +#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4) + +/* Converts a PUCTL id to a shift position */ +#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f) + +/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */ +#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4) + +/* Converts a MUXCTL id to a shift position */ +#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f) + +/* Convenient macro for defining pin group properties */ +#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd) \ + { \ + .vddio = PMUX_VDDIO_ ## vdd, \ + .funcs = { \ + PMUX_FUNC_ ## f0, \ + PMUX_FUNC_ ## f1, \ + PMUX_FUNC_ ## f2, \ + PMUX_FUNC_ ## f3, \ + }, \ + .func_safe = PMUX_FUNC_ ## f_safe, \ + .ctl_id = mux, \ + .pull_id = pupd \ + } + +/* A normal pin group where the mux name and pull-up name match */ +#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe) \ + PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \ + MUXCTL_ ## pg_name, PUCTL_ ## pg_name) + +/* A pin group where the pull-up name doesn't have a 1-1 mapping */ +#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd) \ + PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \ + MUXCTL_ ## pg_name, PUCTL_ ## pupd) + +/* A pin group number which is not used */ +#define PIN_RESERVED \ + PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE) + +const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { + PIN(ATA, NAND, IDE, NAND, GMI, RSVD, IDE), + PIN(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE), + PIN(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE), + PIN(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE), + PIN(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC), + PIN(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC), + PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, + PLLC_OUT1), + PIN(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1), + + PIN(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2), + PIN(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3), + PIN(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4), + PIN(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4), + PIN(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1), + PIN(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1), + PIN(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1), + PIN(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1), + + PINP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4, + GPSLXAU), + PIN(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE), + PIN(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4), + PIN(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB), + PIN(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB), + PIN(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC), + PIN(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC), + PINP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, NONE), + + PIN(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4), + PIN(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4), + PIN(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC), + PIN(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC), + PIN(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3), + PIN(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4), + PIN(SDMMC1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2), + PIN(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR), + + PIN(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI), + PIN(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC), + PIN(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM), + PIN_RESERVED, + PINP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, CRTP), + PIN(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4), + PIN(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4), + PIN(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE), + + PIN(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2), + PIN(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2), + PIN(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), + PIN(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), + PIN(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), + PIN(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI), + PIN(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI), + PIN(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4), + + PIN(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT), + PIN(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT), + PIN(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS), + PIN(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS), + PIN(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4), + PIN(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF), + PIN(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4), + PIN(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4), + + PIN_RESERVED, + PIN(ATE, NAND, IDE, NAND, GMI, RSVD, IDE), + PIN(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC), + PIN_RESERVED, + PIN_RESERVED, + PIN(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI), + PIN(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI), + PIN(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4), + + /* 64 */ + PINP(LD0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD1, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD2, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD3, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD4, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD5, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD6, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD7, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + + PINP(LD8, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD9, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD10, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD11, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD12, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD13, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD14, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD15, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + + PINP(LD16, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), + PINP(LD17, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD17), + PINP(LHP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20), + PINP(LHP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18), + PINP(LHP2, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18), + PINP(LVP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LC), + PINP(LVP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20), + PINP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI , LC), + + PINP(LM0, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LC), + PINP(LM1, LCD, DISPA, DISPB, RSVD, CRT, RSVD3, LC), + PINP(LVS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), + PINP(LSC0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), + PINP(LSC1, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), + PINP(LSCK, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), + PINP(LDC, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS), + PINP(LCSN, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LS), + + /* 96 */ + PINP(LSPI, LCD, DISPA, DISPB, XIO, HDMI, DISPA, LC), + PINP(LSDA, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), + PINP(LSDI, LCD, DISPA, DISPB, SPI3, RSVD, DISPA, LS), + PINP(LPW0, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), + PINP(LPW1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS), + PINP(LPW2, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), + PINP(LDI, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22), + PINP(LHS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), + + PINP(LPP, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22), + PIN_RESERVED, + PIN(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC), + PIN(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK), + PIN(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4), + PIN(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2), + PIN(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD), + PINP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, NONE), + + /* these pin groups only have pullup and pull down control */ + PINALL(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), + PINALL(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, + PUCTL_NONE), +}; + void pinmux_set_tristate(enum pmux_pingrp pin, int enable) { - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)]; u32 reg; @@ -50,3 +504,69 @@ void pinmux_tristate_disable(enum pmux_pingrp pin) { pinmux_set_tristate(pin, 0); } + +void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id; + u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)]; + u32 mask_bit; + u32 reg; + mask_bit = PULL_SHIFT(pull_id); + + reg = readl(pull); + reg &= ~(0x3 << mask_bit); + reg |= pupd << mask_bit; + writel(reg, pull); +} + +void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func) +{ + struct pmux_tri_ctlr *pmt = + (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; + enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id; + u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)]; + u32 mask_bit; + int i, mux = -1; + u32 reg; + + assert(pmux_func_isvalid(func)); + + /* Handle special values */ + if (func >= PMUX_FUNC_RSVD1) { + mux = (func - PMUX_FUNC_RSVD1) & 0x3; + } else { + /* Search for the appropriate function */ + for (i = 0; i < 4; i++) { + if (tegra_soc_pingroups[pin].funcs[i] == func) { + mux = i; + break; + } + } + } + assert(mux != -1); + + mask_bit = MUXCTL_SHIFT(mux_id); + reg = readl(muxctl); + reg &= ~(0x3 << mask_bit); + reg |= mux << mask_bit; + writel(reg, muxctl); +} + +void pinmux_config_pingroup(struct pingroup_config *config) +{ + enum pmux_pingrp pin = config->pingroup; + + pinmux_set_func(pin, config->func); + pinmux_set_pullupdown(pin, config->pull); + pinmux_set_tristate(pin, config->tristate); +} + +void pinmux_config_table(struct pingroup_config *config, int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_pingroup(&config[i]); +} diff --git a/arch/arm/include/asm/arch-tegra2/pinmux.h b/arch/arm/include/asm/arch-tegra2/pinmux.h index e8ef632715..469d742cc3 100644 --- a/arch/arm/include/asm/arch-tegra2/pinmux.h +++ b/arch/arm/include/asm/arch-tegra2/pinmux.h @@ -24,7 +24,14 @@ #ifndef _PINMUX_H_ #define _PINMUX_H_ -/* Pin groups which we can set to tristate or normal */ +/* + * Pin groups which we adjust. There are three basic attributes of each pin + * group which use this enum: + * + * - function + * - pullup / pulldown + * - tristate or normal + */ enum pmux_pingrp { /* APB_MISC_PP_TRISTATE_REG_A_0 */ PINGRP_ATA, @@ -155,37 +162,169 @@ enum pmux_pingrp { PINGRP_UDA, PINGRP_CRTP, PINGRP_SDB, + + /* these pin groups only have pullup and pull down control */ + PINGRP_FIRST_NO_MUX, + PINGRP_CK32 = PINGRP_FIRST_NO_MUX, + PINGRP_DDRC, + PINGRP_PMCA, + PINGRP_PMCB, + PINGRP_PMCC, + PINGRP_PMCD, + PINGRP_PMCE, + PINGRP_XM2C, + PINGRP_XM2D, + + PINGRP_COUNT, +}; + +/* + * Functions which can be assigned to each of the pin groups. The values here + * bear no relation to the values programmed into pinmux registers and are + * purely a convenience. The translation is done through a table search. + */ +enum pmux_func { + PMUX_FUNC_AHB_CLK, + PMUX_FUNC_APB_CLK, + PMUX_FUNC_AUDIO_SYNC, + PMUX_FUNC_CRT, + PMUX_FUNC_DAP1, + PMUX_FUNC_DAP2, + PMUX_FUNC_DAP3, + PMUX_FUNC_DAP4, + PMUX_FUNC_DAP5, + PMUX_FUNC_DISPA, + PMUX_FUNC_DISPB, + PMUX_FUNC_EMC_TEST0_DLL, + PMUX_FUNC_EMC_TEST1_DLL, + PMUX_FUNC_GMI, + PMUX_FUNC_GMI_INT, + PMUX_FUNC_HDMI, + PMUX_FUNC_I2C, + PMUX_FUNC_I2C2, + PMUX_FUNC_I2C3, + PMUX_FUNC_IDE, + PMUX_FUNC_IRDA, + PMUX_FUNC_KBC, + PMUX_FUNC_MIO, + PMUX_FUNC_MIPI_HS, + PMUX_FUNC_NAND, + PMUX_FUNC_OSC, + PMUX_FUNC_OWR, + PMUX_FUNC_PCIE, + PMUX_FUNC_PLLA_OUT, + PMUX_FUNC_PLLC_OUT1, + PMUX_FUNC_PLLM_OUT1, + PMUX_FUNC_PLLP_OUT2, + PMUX_FUNC_PLLP_OUT3, + PMUX_FUNC_PLLP_OUT4, + PMUX_FUNC_PWM, + PMUX_FUNC_PWR_INTR, + PMUX_FUNC_PWR_ON, + PMUX_FUNC_RTCK, + PMUX_FUNC_SDIO1, + PMUX_FUNC_SDIO2, + PMUX_FUNC_SDIO3, + PMUX_FUNC_SDIO4, + PMUX_FUNC_SFLASH, + PMUX_FUNC_SPDIF, + PMUX_FUNC_SPI1, + PMUX_FUNC_SPI2, + PMUX_FUNC_SPI2_ALT, + PMUX_FUNC_SPI3, + PMUX_FUNC_SPI4, + PMUX_FUNC_TRACE, + PMUX_FUNC_TWC, + PMUX_FUNC_UARTA, + PMUX_FUNC_UARTB, + PMUX_FUNC_UARTC, + PMUX_FUNC_UARTD, + PMUX_FUNC_UARTE, + PMUX_FUNC_ULPI, + PMUX_FUNC_VI, + PMUX_FUNC_VI_SENSOR_CLK, + PMUX_FUNC_XIO, + PMUX_FUNC_SAFE, + + /* These don't have a name, but can be used in the table */ + PMUX_FUNC_RSVD1, + PMUX_FUNC_RSVD2, + PMUX_FUNC_RSVD3, + PMUX_FUNC_RSVD4, + PMUX_FUNC_RSVD, /* Not valid and should not be used */ + + PMUX_FUNC_COUNT, + + PMUX_FUNC_NONE = -1, }; +/* return 1 if a pmux_func is in range */ +#define pmux_func_isvalid(func) ((func) >= 0 && (func) < PMUX_FUNC_COUNT && \ + (func) != PMUX_FUNC_RSVD) + +/* The pullup/pulldown state of a pin group */ +enum pmux_pull { + PMUX_PULL_NORMAL = 0, + PMUX_PULL_DOWN, + PMUX_PULL_UP, +}; + +/* Defines whether a pin group is tristated or in normal operation */ +enum pmux_tristate { + PMUX_TRI_NORMAL = 0, + PMUX_TRI_TRISTATE = 1, +}; -#define TEGRA_TRISTATE_REGS 4 +/* Available power domains used by pin groups */ +enum pmux_vddio { + PMUX_VDDIO_BB = 0, + PMUX_VDDIO_LCD, + PMUX_VDDIO_VI, + PMUX_VDDIO_UART, + PMUX_VDDIO_DDR, + PMUX_VDDIO_NAND, + PMUX_VDDIO_SYS, + PMUX_VDDIO_AUDIO, + PMUX_VDDIO_SD, + + PMUX_VDDIO_NONE +}; + +enum { + PMUX_TRISTATE_REGS = 4, + PMUX_MUX_REGS = 7, + PMUX_PULL_REGS = 5, +}; /* APB MISC Pin Mux and Tristate (APB_MISC_PP_) registers */ struct pmux_tri_ctlr { uint pmt_reserved0; /* ABP_MISC_PP_ reserved offset 00 */ uint pmt_reserved1; /* ABP_MISC_PP_ reserved offset 04 */ - uint pmt_strap_opt_a; /* _STRAPPING_OPT_A_0, offset 08 */ + uint pmt_strap_opt_a; /* _STRAPPING_OPT_A_0, offset 08 */ uint pmt_reserved2; /* ABP_MISC_PP_ reserved offset 0C */ uint pmt_reserved3; /* ABP_MISC_PP_ reserved offset 10 */ - uint pmt_tri[TEGRA_TRISTATE_REGS]; /* _TRI_STATE_REG_A/B/C/D_0 14-20 */ - uint pmt_cfg_ctl; /* _CONFIG_CTL_0, offset 24 */ + uint pmt_tri[PMUX_TRISTATE_REGS];/* _TRI_STATE_REG_A/B/C/D_0 14-20 */ + uint pmt_cfg_ctl; /* _CONFIG_CTL_0, offset 24 */ uint pmt_reserved[22]; /* ABP_MISC_PP_ reserved offs 28-7C */ - uint pmt_ctl_a; /* _PINGRP_MUX_CTL_A_0, offset 80 */ - uint pmt_ctl_b; /* _PINGRP_MUX_CTL_B_0, offset 84 */ - uint pmt_ctl_c; /* _PINGRP_MUX_CTL_C_0, offset 88 */ - uint pmt_ctl_d; /* _PINGRP_MUX_CTL_D_0, offset 8C */ - uint pmt_ctl_e; /* _PINGRP_MUX_CTL_E_0, offset 90 */ - uint pmt_ctl_f; /* _PINGRP_MUX_CTL_F_0, offset 94 */ - uint pmt_ctl_g; /* _PINGRP_MUX_CTL_G_0, offset 98 */ + uint pmt_ctl[PMUX_MUX_REGS]; /* _PIN_MUX_CTL_A-G_0, offset 80 */ + uint pmt_reserved4; /* ABP_MISC_PP_ reserved offset 9c */ + uint pmt_pull[PMUX_PULL_REGS]; /* APB_MISC_PP_PULLUPDOWN_REG_A-E */ }; -/* Converts a pin group to a tristate register: 0=A, 1=B, 2=C, 3=D */ -#define TRISTATE_REG(id) ((id) >> 5) - -/* Mask value for a tristate (within TRISTATE_REG(id)) */ -#define TRISTATE_MASK(id) (1 << ((id) & 0x1f)) +/* + * This defines the configuration for a pin, including the function assigned, + * pull up/down settings and tristate settings. Having set up one of these + * you can call pinmux_config_pingroup() to configure a pin in one step. Also + * available is pinmux_config_table() to configure a list of pins. + */ +struct pingroup_config { + enum pmux_pingrp pingroup; /* pin group PINGRP_... */ + enum pmux_func func; /* function to assign FUNC_... */ + enum pmux_pull pull; /* pull up/down/normal PMUX_PULL_...*/ + enum pmux_tristate tristate; /* tristate or normal PMUX_TRI_... */ +}; /* Set a pin group to tristate */ void pinmux_tristate_enable(enum pmux_pingrp pin); @@ -193,4 +332,23 @@ void pinmux_tristate_enable(enum pmux_pingrp pin); /* Set a pin group to normal (non tristate) */ void pinmux_tristate_disable(enum pmux_pingrp pin); +/* Set the pull up/down feature for a pin group */ +void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd); + +/* Set the mux function for a pin group */ +void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func); + +/* Set the complete configuration for a pin group */ +void pinmux_config_pingroup(struct pingroup_config *config); + +void pinmux_set_tristate(enum pmux_pingrp pin, int enable); + +/** + * Configuure a list of pin groups + * + * @param config List of config items + * @param len Number of config items in list + */ +void pinmux_config_table(struct pingroup_config *config, int len); + #endif /* PINMUX_H */ diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c index 35ff2ef03c..5ba7bda33f 100644 --- a/board/nvidia/common/board.c +++ b/board/nvidia/common/board.c @@ -86,21 +86,15 @@ static void clock_init_uart(void) */ static void pin_mux_uart(void) { - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - u32 reg; - #if defined(CONFIG_TEGRA2_ENABLE_UARTA) - reg = readl(&pmt->pmt_ctl_c); - reg &= 0xFFF0FFFF; /* IRRX_/IRTX_SEL [19:16] = 00 UARTA */ - writel(reg, &pmt->pmt_ctl_c); + pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA); + pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA); pinmux_tristate_disable(PINGRP_IRRX); pinmux_tristate_disable(PINGRP_IRTX); #endif /* CONFIG_TEGRA2_ENABLE_UARTA */ #if defined(CONFIG_TEGRA2_ENABLE_UARTD) - reg = readl(&pmt->pmt_ctl_b); - reg &= 0xFFFFFFF3; /* GMC_SEL [3:2] = 00, UARTD */ - writel(reg, &pmt->pmt_ctl_b); + pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); pinmux_tristate_disable(PINGRP_GMC); #endif /* CONFIG_TEGRA2_ENABLE_UARTD */ @@ -123,33 +117,19 @@ static void clock_init_mmc(void) */ static void pin_mux_mmc(void) { - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - u32 reg; - - /* SDMMC4 */ - /* config 2, x8 on 2nd set of pins */ - reg = readl(&pmt->pmt_ctl_a); - reg |= (3 << 16); /* ATB_SEL [17:16] = 11 SDIO4 */ - writel(reg, &pmt->pmt_ctl_a); - reg = readl(&pmt->pmt_ctl_b); - reg |= (3 << 0); /* GMA_SEL [1:0] = 11 SDIO4 */ - writel(reg, &pmt->pmt_ctl_b); - reg = readl(&pmt->pmt_ctl_d); - reg |= (3 << 0); /* GME_SEL [1:0] = 11 SDIO4 */ - writel(reg, &pmt->pmt_ctl_d); + /* SDMMC4: config 3, x8 on 2nd set of pins */ + pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); + pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4); + pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4); pinmux_tristate_disable(PINGRP_ATB); pinmux_tristate_disable(PINGRP_GMA); pinmux_tristate_disable(PINGRP_GME); - /* SDMMC3 */ - /* SDIO3_CLK, SDIO3_CMD, SDIO3_DAT[3:0] */ - reg = readl(&pmt->pmt_ctl_d); - reg &= 0xFFFF03FF; - reg |= (2 << 10); /* SDB_SEL [11:10] = 01 SDIO3 */ - reg |= (2 << 12); /* SDC_SEL [13:12] = 01 SDIO3 */ - reg |= (2 << 14); /* SDD_SEL [15:14] = 01 SDIO3 */ - writel(reg, &pmt->pmt_ctl_d); + /* SDMMC3: SDIO3_CLK, SDIO3_CMD, SDIO3_DAT[3:0] */ + pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); + pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3); + pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3); pinmux_tristate_disable(PINGRP_SDC); pinmux_tristate_disable(PINGRP_SDD); -- 2.25.1