blob: 40301e13c29df3019da84e858aff5f645bb87046 [file] [log] [blame]
/*
* Copyright (c) 2011 The Chromium OS Authors.
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* Tegra20 pin multiplexing functions */
#include <common.h>
#include <asm/io.h>
#include <asm/arch/tegra.h>
#include <asm/arch/pinmux.h>
/*
* 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_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) \
{ \
.funcs = { \
PMUX_FUNC_ ## f0, \
PMUX_FUNC_ ## f1, \
PMUX_FUNC_ ## f2, \
PMUX_FUNC_ ## f3, \
}, \
.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, UARTB, 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;
u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)];
u32 reg;
reg = readl(tri);
if (enable)
reg |= TRISTATE_MASK(pin);
else
reg &= ~TRISTATE_MASK(pin);
writel(reg, tri);
}
void pinmux_tristate_enable(enum pmux_pingrp pin)
{
pinmux_set_tristate(pin, 1);
}
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(const 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(const struct pingroup_config *config, int len)
{
int i;
for (i = 0; i < len; i++)
pinmux_config_pingroup(&config[i]);
}