]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - arch/arm/mach-tegra/pinmux-common.c
imx: spl: Partially revert "spl: eMMC/SD: Provide one __weak spl_boot_mode() function"
[people/ms/u-boot.git] / arch / arm / mach-tegra / pinmux-common.c
index 5d4d2e9c30021b8f6ae501a2b4c95125ef37f566..5862c4ac3dc6f719d868790657356fc833b7436d 100644 (file)
         ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH))
 #endif
 
-#define _R(offset)     (u32 *)(NV_PA_APB_MISC_BASE + (offset))
+#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
+/* return 1 if a pin_e_io_hv is in range */
+#define pmux_pin_e_io_hv_isvalid(e_io_hv) \
+       (((e_io_hv) >= PMUX_PIN_E_IO_HV_NORMAL) && \
+        ((e_io_hv) <= PMUX_PIN_E_IO_HV_HIGH))
+#endif
+
+#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
+#define pmux_lpmd_isvalid(lpm) \
+       (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X))
+#endif
+
+#if defined(TEGRA_PMX_PINS_HAVE_SCHMT) || defined(TEGRA_PMX_GRPS_HAVE_SCHMT)
+#define pmux_schmt_isvalid(schmt) \
+       (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE))
+#endif
+
+#if defined(TEGRA_PMX_PINS_HAVE_HSM) || defined(TEGRA_PMX_GRPS_HAVE_HSM)
+#define pmux_hsm_isvalid(hsm) \
+       (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE))
+#endif
+
+#define _R(offset)     (u32 *)((unsigned long)NV_PA_APB_MISC_BASE + (offset))
 
 #if defined(CONFIG_TEGRA20)
 
 
 #endif /* CONFIG_TEGRA20 */
 
-#define DRV_REG(group) _R(0x868 + ((group) * 4))
+#define DRV_REG(group) _R(TEGRA_PMX_SOC_DRV_GROUP_BASE_REG + ((group) * 4))
 
+#define MIPIPADCTRL_REG(group) _R(TEGRA_PMX_SOC_MIPIPADCTRL_BASE_REG + ((group) * 4))
+
+/*
+ * We could force arch-tegraNN/pinmux.h to define all of these. However,
+ * that's a lot of defines, and for now it's manageable to just put a
+ * special case here. It's possible this decision will change with future
+ * SoCs.
+ */
+#ifdef CONFIG_TEGRA210
+#define IO_SHIFT       6
+#define LOCK_SHIFT     7
+#ifdef TEGRA_PMX_PINS_HAVE_HSM
+#define HSM_SHIFT      9
+#endif
+#define E_IO_HV_SHIFT  10
+#define OD_SHIFT       11
+#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
+#define SCHMT_SHIFT    12
+#endif
+#else
 #define IO_SHIFT       5
 #define OD_SHIFT       6
 #define LOCK_SHIFT     7
 #define IO_RESET_SHIFT 8
 #define RCV_SEL_SHIFT  9
+#endif
 
 #ifdef TEGRA_PMX_SOC_HAS_IO_CLAMPING
 /* This register/field only exists on Tegra114 and later */
@@ -309,6 +352,81 @@ static void pinmux_set_rcv_sel(enum pmux_pingrp pin,
 }
 #endif
 
+#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
+static void pinmux_set_e_io_hv(enum pmux_pingrp pin,
+                               enum pmux_pin_e_io_hv e_io_hv)
+{
+       u32 *reg = REG(pin);
+       u32 val;
+
+       if (e_io_hv == PMUX_PIN_E_IO_HV_DEFAULT)
+               return;
+
+       /* Error check on pin and e_io_hv */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_pin_e_io_hv_isvalid(e_io_hv));
+
+       val = readl(reg);
+       if (e_io_hv == PMUX_PIN_E_IO_HV_HIGH)
+               val |= (1 << E_IO_HV_SHIFT);
+       else
+               val &= ~(1 << E_IO_HV_SHIFT);
+       writel(val, reg);
+
+       return;
+}
+#endif
+
+#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
+static void pinmux_set_schmt(enum pmux_pingrp pin, enum pmux_schmt schmt)
+{
+       u32 *reg = REG(grp);
+       u32 val;
+
+       /* NONE means unspecified/do not change/use POR value */
+       if (schmt == PMUX_SCHMT_NONE)
+               return;
+
+       /* Error check pad */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_schmt_isvalid(schmt));
+
+       val = readl(reg);
+       if (schmt == PMUX_SCHMT_ENABLE)
+               val |= (1 << SCHMT_SHIFT);
+       else
+               val &= ~(1 << SCHMT_SHIFT);
+       writel(val, reg);
+
+       return;
+}
+#endif
+
+#ifdef TEGRA_PMX_PINS_HAVE_HSM
+static void pinmux_set_hsm(enum pmux_pingrp pin, enum pmux_hsm hsm)
+{
+       u32 *reg = REG(grp);
+       u32 val;
+
+       /* NONE means unspecified/do not change/use POR value */
+       if (hsm == PMUX_HSM_NONE)
+               return;
+
+       /* Error check pad */
+       assert(pmux_pingrp_isvalid(pin));
+       assert(pmux_hsm_isvalid(hsm));
+
+       val = readl(reg);
+       if (hsm == PMUX_HSM_ENABLE)
+               val |= (1 << HSM_SHIFT);
+       else
+               val &= ~(1 << HSM_SHIFT);
+       writel(val, reg);
+
+       return;
+}
+#endif
+
 static void pinmux_config_pingrp(const struct pmux_pingrp_config *config)
 {
        enum pmux_pingrp pin = config->pingrp;
@@ -331,6 +449,15 @@ static void pinmux_config_pingrp(const struct pmux_pingrp_config *config)
 #ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL
        pinmux_set_rcv_sel(pin, config->rcv_sel);
 #endif
+#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV
+       pinmux_set_e_io_hv(pin, config->e_io_hv);
+#endif
+#ifdef TEGRA_PMX_PINS_HAVE_SCHMT
+       pinmux_set_schmt(pin, config->schmt);
+#endif
+#ifdef TEGRA_PMX_PINS_HAVE_HSM
+       pinmux_set_hsm(pin, config->hsm);
+#endif
 }
 
 void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config,
@@ -352,19 +479,16 @@ void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config,
 #define pmux_drv_isvalid(drv) \
        (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX))
 
-#define pmux_lpmd_isvalid(lpm) \
-       (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X))
-
-#define pmux_schmt_isvalid(schmt) \
-       (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE))
-
-#define pmux_hsm_isvalid(hsm) \
-       (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE))
-
+#ifdef TEGRA_PMX_GRPS_HAVE_HSM
 #define HSM_SHIFT      2
+#endif
+#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
 #define SCHMT_SHIFT    3
+#endif
+#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
 #define LPMD_SHIFT     4
 #define LPMD_MASK      (3 << LPMD_SHIFT)
+#endif
 /*
  * Note that the following DRV* and SLW* defines are accurate for many drive
  * groups on many SoCs. We really need a per-group data structure to solve
@@ -473,6 +597,7 @@ static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn)
        return;
 }
 
+#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
 static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd)
 {
        u32 *reg = DRV_REG(grp);
@@ -493,7 +618,9 @@ static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd)
 
        return;
 }
+#endif
 
+#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
 static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt)
 {
        u32 *reg = DRV_REG(grp);
@@ -516,7 +643,9 @@ static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt)
 
        return;
 }
+#endif
 
+#ifdef TEGRA_PMX_GRPS_HAVE_HSM
 static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm)
 {
        u32 *reg = DRV_REG(grp);
@@ -539,6 +668,7 @@ static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm)
 
        return;
 }
+#endif
 
 static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config)
 {
@@ -548,9 +678,15 @@ static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config)
        pinmux_set_drvdn_slwr(grp, config->slwr);
        pinmux_set_drvup(grp, config->drvup);
        pinmux_set_drvdn(grp, config->drvdn);
+#ifdef TEGRA_PMX_GRPS_HAVE_LPMD
        pinmux_set_lpmd(grp, config->lpmd);
+#endif
+#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT
        pinmux_set_schmt(grp, config->schmt);
+#endif
+#ifdef TEGRA_PMX_GRPS_HAVE_HSM
        pinmux_set_hsm(grp, config->hsm);
+#endif
 }
 
 void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config,
@@ -561,4 +697,59 @@ void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config,
        for (i = 0; i < len; i++)
                pinmux_config_drvgrp(&config[i]);
 }
-#endif /* TEGRA_PMX_HAS_DRVGRPS */
+#endif /* TEGRA_PMX_SOC_HAS_DRVGRPS */
+
+#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS
+
+#define pmux_mipipadctrlgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_MIPIPADCTRLGRP_COUNT))
+
+static void pinmux_mipipadctrl_set_func(enum pmux_mipipadctrlgrp grp,
+       enum pmux_func func)
+{
+       u32 *reg = MIPIPADCTRL_REG(grp);
+       int i, mux = -1;
+       u32 val;
+
+       if (func == PMUX_FUNC_DEFAULT)
+               return;
+
+       /* Error check grp and func */
+       assert(pmux_mipipadctrlgrp_isvalid(grp));
+       assert(pmux_func_isvalid(func));
+
+       if (func >= PMUX_FUNC_RSVD1) {
+               mux = (func - PMUX_FUNC_RSVD1) & 1;
+       } else {
+               /* Search for the appropriate function */
+               for (i = 0; i < 2; i++) {
+                       if (tegra_soc_mipipadctrl_groups[grp].funcs[i]
+                           == func) {
+                               mux = i;
+                               break;
+                       }
+               }
+       }
+       assert(mux != -1);
+
+       val = readl(reg);
+       val &= ~(1 << 1);
+       val |= (mux << 1);
+       writel(val, reg);
+}
+
+static void pinmux_config_mipipadctrlgrp(const struct pmux_mipipadctrlgrp_config *config)
+{
+       enum pmux_mipipadctrlgrp grp = config->grp;
+
+       pinmux_mipipadctrl_set_func(grp, config->func);
+}
+
+void pinmux_config_mipipadctrlgrp_table(
+       const struct pmux_mipipadctrlgrp_config *config, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               pinmux_config_mipipadctrlgrp(&config[i]);
+}
+#endif /* TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS */