* [U-Boot] [PATCH v2 1/6] Tegra30: fdt: Add SDMMC (sdhci) nodes for T30 boards (Cardhu for now)
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 2/6] Tegra: MMC: Added/update SDMMC registers/base addresses for T20/T30 Tom Warren
` (4 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
Took these values directly from the kernel dts files.
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2:
- no change
arch/arm/dts/tegra30.dtsi | 32 ++++++++++++++++++++++++++++++++
board/nvidia/dts/tegra30-cardhu.dts | 15 +++++++++++++++
2 files changed, 47 insertions(+), 0 deletions(-)
diff --git a/arch/arm/dts/tegra30.dtsi b/arch/arm/dts/tegra30.dtsi
index 9483e80..ccf154f 100644
--- a/arch/arm/dts/tegra30.dtsi
+++ b/arch/arm/dts/tegra30.dtsi
@@ -184,4 +184,36 @@
clocks = <&tegra_car 105>;
status = "disabled";
};
+
+ sdhci at 78000000 {
+ compatible = "nvidia,tegra30-sdhci";
+ reg = <0x78000000 0x200>;
+ interrupts = <0 14 0x04>;
+ clocks = <&tegra_car 14>;
+ status = "disabled";
+ };
+
+ sdhci at 78000200 {
+ compatible = "nvidia,tegra30-sdhci";
+ reg = <0x78000200 0x200>;
+ interrupts = <0 15 0x04>;
+ clocks = <&tegra_car 9>;
+ status = "disabled";
+ };
+
+ sdhci at 78000400 {
+ compatible = "nvidia,tegra30-sdhci";
+ reg = <0x78000400 0x200>;
+ interrupts = <0 19 0x04>;
+ clocks = <&tegra_car 69>;
+ status = "disabled";
+ };
+
+ sdhci at 78000600 {
+ compatible = "nvidia,tegra30-sdhci";
+ reg = <0x78000600 0x200>;
+ interrupts = <0 31 0x04>;
+ clocks = <&tegra_car 15>;
+ status = "disabled";
+ };
};
diff --git a/board/nvidia/dts/tegra30-cardhu.dts b/board/nvidia/dts/tegra30-cardhu.dts
index 48039c9..4d22b48 100644
--- a/board/nvidia/dts/tegra30-cardhu.dts
+++ b/board/nvidia/dts/tegra30-cardhu.dts
@@ -12,6 +12,8 @@
i2c2 = "/i2c at 7000c400";
i2c3 = "/i2c at 7000c500";
i2c4 = "/i2c at 7000c700";
+ sdhci0 = "/sdhci at 78000600";
+ sdhci1 = "/sdhci at 78000000";
};
memory {
@@ -48,4 +50,17 @@
status = "okay";
spi-max-frequency = <25000000>;
};
+
+ sdhci at 78000000 {
+ status = "okay";
+ cd-gpios = <&gpio 69 1>; /* gpio PI5 */
+ wp-gpios = <&gpio 155 0>; /* gpio PT3 */
+ power-gpios = <&gpio 31 0>; /* gpio PD7 */
+ bus-width = <4>;
+ };
+
+ sdhci at 78000600 {
+ status = "okay";
+ bus-width = <8>;
+ };
};
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 2/6] Tegra: MMC: Added/update SDMMC registers/base addresses for T20/T30
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 1/6] Tegra30: fdt: Add SDMMC (sdhci) nodes for T30 boards (Cardhu for now) Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines Tom Warren
` (3 subsequent siblings)
5 siblings, 0 replies; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
Removed SDMMC base addresses from tegra.h since they're no longer used.
Added pad control settings for T30 from the TRM, and added additional
vendor-specific SD/MMC registers and bus power defines.
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2:
- change pad_init_mmc prototype
- remove all TEGRA_SDMMCx_BASE defines
arch/arm/include/asm/arch-tegra/tegra_mmc.h | 35 +++++++++++++++++++----
arch/arm/include/asm/arch-tegra30/gp_padctrl.h | 6 ++++
2 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/arch/arm/include/asm/arch-tegra/tegra_mmc.h b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
index bd18f5f..2a3f830 100644
--- a/arch/arm/include/asm/arch-tegra/tegra_mmc.h
+++ b/arch/arm/include/asm/arch-tegra/tegra_mmc.h
@@ -22,10 +22,7 @@
#ifndef __TEGRA_MMC_H_
#define __TEGRA_MMC_H_
-#define TEGRA_SDMMC1_BASE 0xC8000000
-#define TEGRA_SDMMC2_BASE 0xC8000200
-#define TEGRA_SDMMC3_BASE 0xC8000400
-#define TEGRA_SDMMC4_BASE 0xC8000600
+#include <fdtdec.h>
#define MAX_HOSTS 4 /* Max number of 'hosts'/controllers */
@@ -64,12 +61,30 @@ struct tegra_mmc {
unsigned char admaerr; /* offset 54h */
unsigned char res4[3]; /* RESERVED, offset 55h-57h */
unsigned long admaaddr; /* offset 58h-5Fh */
- unsigned char res5[0x9c]; /* RESERVED, offset 60h-FBh */
+ unsigned char res5[0xa0]; /* RESERVED, offset 60h-FBh */
unsigned short slotintstatus; /* offset FCh */
unsigned short hcver; /* HOST Version */
- unsigned char res6[0x100]; /* RESERVED, offset 100h-1FFh */
+ unsigned int venclkctl; /* _VENDOR_CLOCK_CNTRL_0, 100h */
+ unsigned int venspictl; /* _VENDOR_SPI_CNTRL_0, 104h */
+ unsigned int venspiintsts; /* _VENDOR_SPI_INT_STATUS_0, 108h */
+ unsigned int venceatactl; /* _VENDOR_CEATA_CNTRL_0, 10Ch */
+ unsigned int venbootctl; /* _VENDOR_BOOT_CNTRL_0, 110h */
+ unsigned int venbootacktout; /* _VENDOR_BOOT_ACK_TIMEOUT, 114h */
+ unsigned int venbootdattout; /* _VENDOR_BOOT_DAT_TIMEOUT, 118h */
+ unsigned int vendebouncecnt; /* _VENDOR_DEBOUNCE_COUNT_0, 11Ch */
+ unsigned int venmiscctl; /* _VENDOR_MISC_CNTRL_0, 120h */
+ unsigned int res6[47]; /* 0x124 ~ 0x1DC */
+ unsigned int sdmemcmppadctl; /* _SDMEMCOMPPADCTRL_0, 1E0h */
+ unsigned int autocalcfg; /* _AUTO_CAL_CONFIG_0, 1E4h */
+ unsigned int autocalintval; /* _AUTO_CAL_INTERVAL_0, 1E8h */
+ unsigned int autocalsts; /* _AUTO_CAL_STATUS_0, 1ECh */
};
+#define TEGRA_MMC_PWRCTL_SD_BUS_POWER (1 << 0)
+#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8 (5 << 1)
+#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0 (6 << 1)
+#define TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3 (7 << 1)
+
#define TEGRA_MMC_HOSTCTL_DMASEL_MASK (3 << 3)
#define TEGRA_MMC_HOSTCTL_DMASEL_SDMA (0 << 3)
#define TEGRA_MMC_HOSTCTL_DMASEL_ADMA2_32BIT (2 << 3)
@@ -119,6 +134,12 @@ struct tegra_mmc {
#define TEGRA_MMC_NORINTSIGEN_XFER_COMPLETE (1 << 1)
+/* SDMMC1/3 settings from section 24.6 of T30 TRM */
+#define MEMCOMP_PADCTRL_VREF 7
+#define AUTO_CAL_ENABLED (1 << 29)
+#define AUTO_CAL_PD_OFFSET (0x70 << 8)
+#define AUTO_CAL_PU_OFFSET (0x62 << 0)
+
struct mmc_host {
struct tegra_mmc *reg;
int id; /* device id/number, 0-3 */
@@ -132,5 +153,7 @@ struct mmc_host {
unsigned int clock; /* Current clock (MHz) */
};
+void pad_init_mmc(struct mmc_host *host);
+
#endif /* __ASSEMBLY__ */
#endif /* __TEGRA_MMC_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h
index 9b383d0..48b9a3b 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 GP_SDIOCFG_DRVUP_SLWF (1 << 30)
+#define GP_SDIOCFG_DRVDN_SLWR (1 << 28)
+#define GP_SDIOCFG_DRVUP (0x2E << 20)
+#define GP_SDIOCFG_DRVDN (0x2A << 12)
+
#endif /* _TEGRA30_GP_PADCTRL_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 1/6] Tegra30: fdt: Add SDMMC (sdhci) nodes for T30 boards (Cardhu for now) Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 2/6] Tegra: MMC: Added/update SDMMC registers/base addresses for T20/T30 Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
2013-03-05 17:55 ` Stephen Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 4/6] mmc: Tegra: Add SD bus power/voltage function and MMC pad init call Tom Warren
` (2 subsequent siblings)
5 siblings, 1 reply; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
T30 requires specific SDMMC pad programming, and bus power-rail bringup.
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2:
- rewrite pad_init_mmc to use mmc_id instead of SDMMC base address
- add PMU-specific comments to board_sdmmc_voltage_init sequence
board/nvidia/cardhu/cardhu.c | 51 ++++++++++++++++++++++++++++++++++++++
board/nvidia/common/board.c | 55 +++++++++++++++++++++++++++++++++++++++++-
2 files changed, 105 insertions(+), 1 deletions(-)
diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index df4cb6b..1889998 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -24,6 +24,10 @@
#include <common.h>
#include <asm/arch/pinmux.h>
#include "pinmux-config-cardhu.h"
+#include <i2c.h>
+
+#define PMU_I2C_ADDRESS 0x2D
+#define MAX_I2C_RETRY 3
/*
* Routine: pinmux_init
@@ -37,3 +41,50 @@ void pinmux_init(void)
pinmux_config_table(unused_pins_lowpower,
ARRAY_SIZE(unused_pins_lowpower));
}
+
+#if defined(CONFIG_TEGRA_MMC)
+/*
+ * Do I2C/PMU writes to bring up SD card bus power
+ *
+ */
+void board_sdmmc_voltage_init(void)
+{
+ uchar reg, data_buffer[1];
+ int i;
+
+ i2c_set_bus_num(0); /* PMU is on bus 0 */
+
+ /* TPS659110: LDO5_REG = 3.3v, ACTIVE to SDMMC1 */
+ data_buffer[0] = 0x65;
+ reg = 0x32;
+
+ for (i = 0; i < MAX_I2C_RETRY; ++i) {
+ if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1))
+ udelay(100);
+ }
+
+ /* TPS659110: GPIO7_REG = PDEN, output a 1 to EN_3V3_SYS */
+ data_buffer[0] = 0x09;
+ reg = 0x67;
+
+ for (i = 0; i < MAX_I2C_RETRY; ++i) {
+ if (i2c_write(PMU_I2C_ADDRESS, reg, 1, data_buffer, 1))
+ udelay(100);
+ }
+}
+
+/*
+ * Routine: pin_mux_mmc
+ * Description: setup the MMC muxes, power rails, etc.
+ */
+void pin_mux_mmc(void)
+{
+ /*
+ * NOTE: We don't do mmc-specific pin muxes here.
+ * They were done globally in pinmux_init().
+ */
+
+ /* Bring up the SDIO1 power rail */
+ board_sdmmc_voltage_init();
+}
+#endif /* MMC */
diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
index babbe08..8c9040d 100644
--- a/board/nvidia/common/board.c
+++ b/board/nvidia/common/board.c
@@ -49,6 +49,8 @@
#include <asm/arch-tegra/usb.h>
#endif
#ifdef CONFIG_TEGRA_MMC
+#include <asm/arch/gp_padctrl.h>
+#include <asm/arch-tegra/tegra_mmc.h>
#include <asm/arch-tegra/mmc.h>
#endif
#include <i2c.h>
@@ -245,4 +247,55 @@ int board_mmc_init(bd_t *bd)
return 0;
}
-#endif
+
+void pad_init_mmc(struct mmc_host *host)
+{
+#if defined(CONFIG_TEGRA30)
+ struct apb_misc_gp_ctlr *const gpc =
+ (struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
+ enum periph_id id;
+ u32 val, padcfg, padmask;
+
+ id = host->mmc_id;
+
+ debug("%s: sdmmc address = %08x, id = %d\n", __func__,
+ (unsigned int)host->reg, id);
+
+ /* Set the pad drive strength for SDMMC1 or 3 only */
+ if (id != PERIPH_ID_SDMMC1 && id != PERIPH_ID_SDMMC3) {
+ debug("%s: settings are only valid for SDMMC1/SDMMC3!\n",
+ __func__);
+ return;
+ }
+
+ /* Set pads as per T30 TRM, section 24.6.1.2 */
+ padcfg = (GP_SDIOCFG_DRVUP_SLWF | GP_SDIOCFG_DRVDN_SLWR | \
+ GP_SDIOCFG_DRVUP | GP_SDIOCFG_DRVDN);
+ padmask = 0x00000FFF;
+
+ if (id == PERIPH_ID_SDMMC1) {
+ val = readl(&gpc->sdio1cfg);
+ val &= padmask;
+ val |= padcfg;
+ writel(val, &gpc->sdio1cfg);
+ debug(" wrote 0x%08X to %p\n", val, &gpc->sdio1cfg);
+ } else {
+ val = readl(&gpc->sdio3cfg);
+ val &= padmask;
+ val |= padcfg;
+ writel(val, &gpc->sdio3cfg);
+ debug(" wrote 0x%08X to %p\n", val, &gpc->sdio3cfg);
+ }
+
+ val = readl(&host->reg->sdmemcmppadctl);
+ val &= 0xFFFFFFF0;
+ val |= MEMCOMP_PADCTRL_VREF;
+ writel(val, &host->reg->sdmemcmppadctl);
+
+ val = readl(&host->reg->autocalcfg);
+ val &= 0xFFFF0000;
+ val |= AUTO_CAL_PU_OFFSET | AUTO_CAL_PD_OFFSET | AUTO_CAL_ENABLED;
+ writel(val, &host->reg->autocalcfg);
+#endif /* T30 */
+}
+#endif /* MMC */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines
2013-03-05 16:29 ` [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines Tom Warren
@ 2013-03-05 17:55 ` Stephen Warren
2013-03-05 18:23 ` Tom Warren
0 siblings, 1 reply; 10+ messages in thread
From: Stephen Warren @ 2013-03-05 17:55 UTC (permalink / raw)
To: u-boot
On 03/05/2013 09:29 AM, Tom Warren wrote:
> T30 requires specific SDMMC pad programming, and bus power-rail bringup.
> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
> +void pad_init_mmc(struct mmc_host *host)
> + if (id == PERIPH_ID_SDMMC1) {
> + val = readl(&gpc->sdio1cfg);
> + val &= padmask;
> + val |= padcfg;
> + writel(val, &gpc->sdio1cfg);
> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio1cfg);
> + } else {
> + val = readl(&gpc->sdio3cfg);
> + val &= padmask;
> + val |= padcfg;
> + writel(val, &gpc->sdio3cfg);
> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio3cfg);
> + }
This isn't generic enough, although the problems may not show up for the
SDMMC1/3 controllers since it looks like those controllers always use a
specific set of pins; the pinmux HW doesn't allow those controllers to
be routed to different places.
However, SDMMC1 and SDMMC4 would also need entries in the above if
statement for it to be complete. Those controllers can definitely be
switched between different sets of pins. This function would then
somehow have to know which set of pins to apply the pinmux configuration
to, which would imply searching through the pinmux registers to find the
pins which have their mux function set to point at the controller in
question.
This implies that configuring the pinmux here isn't the right way to do
this. As I wrote in my immediately previous email, I think the pingroup
drive registers (named "*cfg") should be initialized based on a table
provided by the board file (and later by DT; the values are already part
of the DT pinctrl bindings). The table or DT content will be
board-specific, and hence able to describe which pingroup should be
configured based on the board design.
^ permalink raw reply [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines
2013-03-05 17:55 ` Stephen Warren
@ 2013-03-05 18:23 ` Tom Warren
2013-03-05 19:10 ` Stephen Warren
0 siblings, 1 reply; 10+ messages in thread
From: Tom Warren @ 2013-03-05 18:23 UTC (permalink / raw)
To: u-boot
On Tue, Mar 5, 2013 at 10:55 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 03/05/2013 09:29 AM, Tom Warren wrote:
>> T30 requires specific SDMMC pad programming, and bus power-rail bringup.
>
>> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
>
>> +void pad_init_mmc(struct mmc_host *host)
>
>> + if (id == PERIPH_ID_SDMMC1) {
>> + val = readl(&gpc->sdio1cfg);
>> + val &= padmask;
>> + val |= padcfg;
>> + writel(val, &gpc->sdio1cfg);
>> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio1cfg);
>> + } else {
>> + val = readl(&gpc->sdio3cfg);
>> + val &= padmask;
>> + val |= padcfg;
>> + writel(val, &gpc->sdio3cfg);
>> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio3cfg);
>> + }
>
> This isn't generic enough, although the problems may not show up for the
> SDMMC1/3 controllers since it looks like those controllers always use a
> specific set of pins; the pinmux HW doesn't allow those controllers to
> be routed to different places.
>
> However, SDMMC1 and SDMMC4 would also need entries in the above if
SDMMC1 is already there. I assume you mean SDMMC2.
> statement for it to be complete. Those controllers can definitely be
> switched between different sets of pins. This function would then
> somehow have to know which set of pins to apply the pinmux configuration
> to, which would imply searching through the pinmux registers to find the
> pins which have their mux function set to point at the controller in
> question.
Read the SDMMC section of the T30 TRM (24.6.1.2 - 5), and you'll see
that there is no config info given for SDMMC2 or SDMMC4 GP regs.
SDIO1CFG covers SDMMC1, SDIO3CFG covers SDMMC3 thru DAT3, and SDIO2CFG
covers the other 4 DAT pins, which are unused for SDIO on Cardhu. So
there will never be a need to write to any GP SDIOxCFG registers for
SDMMC2 or SDMMC4 on Tegra30, at least as per this section of the TRM.
Note that it seems SDMMC2 doesn't even have a 'cfg' pingroup register
called out in Table 29, and SDMMC4 is split between 3 different
gm[abcd]cfg groups. So the above code covers all SDIO pad cfg
settings as per the TRM.
>
> This implies that configuring the pinmux here isn't the right way to do
> this.
Disagree, see above.
> As I wrote in my immediately previous email, I think the pingroup
> drive registers (named "*cfg") should be initialized based on a table
> provided by the board file (and later by DT; the values are already part
> of the DT pinctrl bindings). The table or DT content will be
> board-specific, and hence able to describe which pingroup should be
> configured based on the board design.
That's certainly doable, and probably a good idea if there were any
other code that requires pad cfg to be tuned, but I don't see that in
the TRM anywhere. This patchset is specifically to enable MMC on
Tegra30. Adding pad_cfg_ctrl tables/macros, and code to handle them is
something I see happening in a separate patchset, if at all, since I
don't see any other pad cfg registers that ever need writing (beyond
SDMMC1/3).
^ permalink raw reply [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines
2013-03-05 18:23 ` Tom Warren
@ 2013-03-05 19:10 ` Stephen Warren
0 siblings, 0 replies; 10+ messages in thread
From: Stephen Warren @ 2013-03-05 19:10 UTC (permalink / raw)
To: u-boot
On 03/05/2013 11:23 AM, Tom Warren wrote:
> On Tue, Mar 5, 2013 at 10:55 AM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 03/05/2013 09:29 AM, Tom Warren wrote:
>>> T30 requires specific SDMMC pad programming, and bus power-rail bringup.
>>
>>> diff --git a/board/nvidia/common/board.c b/board/nvidia/common/board.c
>>
>>> +void pad_init_mmc(struct mmc_host *host)
>>
>>> + if (id == PERIPH_ID_SDMMC1) {
>>> + val = readl(&gpc->sdio1cfg);
>>> + val &= padmask;
>>> + val |= padcfg;
>>> + writel(val, &gpc->sdio1cfg);
>>> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio1cfg);
>>> + } else {
>>> + val = readl(&gpc->sdio3cfg);
>>> + val &= padmask;
>>> + val |= padcfg;
>>> + writel(val, &gpc->sdio3cfg);
>>> + debug(" wrote 0x%08X to %p\n", val, &gpc->sdio3cfg);
>>> + }
>>
>> This isn't generic enough, although the problems may not show up for the
>> SDMMC1/3 controllers since it looks like those controllers always use a
>> specific set of pins; the pinmux HW doesn't allow those controllers to
>> be routed to different places.
>>
>> However, SDMMC1 and SDMMC4 would also need entries in the above if
>
> SDMMC1 is already there. I assume you mean SDMMC2.
Yes.
>> statement for it to be complete. Those controllers can definitely be
>> switched between different sets of pins. This function would then
>> somehow have to know which set of pins to apply the pinmux configuration
>> to, which would imply searching through the pinmux registers to find the
>> pins which have their mux function set to point at the controller in
>> question.
>
> Read the SDMMC section of the T30 TRM (24.6.1.2 - 5), and you'll see
> that there is no config info given for SDMMC2 or SDMMC4 GP regs.
The SDMMC section doesn't mandate a specific configuration. However,
almost all pins that are affected by the pinmux are included in some
group that has a "cfg" register with those exact same set of fields.
Hence, it is almost always possible to set some value in those fields.
We just didn't document what those values were for SDMMC2 and SDMMC4.
> SDIO1CFG covers SDMMC1, SDIO3CFG covers SDMMC3 thru DAT3, and SDIO2CFG
> covers the other 4 DAT pins, which are unused for SDIO on Cardhu. So
> there will never be a need to write to any GP SDIOxCFG registers for
> SDMMC2 or SDMMC4 on Tegra30, at least as per this section of the TRM.
That doesn't follow.
First off, Cardhu is not the only Tegra30 board, so you can't generalize
based on which SDMMC controllers are used on Cardhu.
Second, Cardhu does actually use all of SDMMC1, SDMMC2, SDMMC4; the
other controller is for SDIO for WiFi. Admittedly it's fairly unlikely
we'll support SDIO-based WiFi in U-Boot, but we likely do want to at
least not preclude support for that due to the way the pinmux register
logic is written. Besides, we might also want to assume that U-Boot sets
up 100% of the pinmux registers; that's certainly the approach already
taken for the mux registers.
> Note that it seems SDMMC2 doesn't even have a 'cfg' pingroup register
> called out in Table 29, and SDMMC4 is split between 3 different
> gm[abcd]cfg groups. So the above code covers all SDIO pad cfg
> settings as per the TRM.
That's exactly my point. The pinmux can route the signals from the other
two SDMMC controllers to different sets of pins. Those different sets of
pins are in different pin groups for the "cfg" registers. Hence, if you
extend this code in question to support all SDMMC controllers, as we
will almost certainly have to do for complete board support, we can't
hard-code what "cfg" registers we choose to write to here, since the
register is board-specific due to the pinmux configuration being
board-specific.
>> As I wrote in my immediately previous email, I think the pingroup
>> drive registers (named "*cfg") should be initialized based on a table
>> provided by the board file (and later by DT; the values are already part
>> of the DT pinctrl bindings). The table or DT content will be
>> board-specific, and hence able to describe which pingroup should be
>> configured based on the board design.
>
> That's certainly doable, and probably a good idea if there were any
> other code that requires pad cfg to be tuned, but I don't see that in
> the TRM anywhere.
The TRM is notoriously incomplete.
> This patchset is specifically to enable MMC on
> Tegra30. Adding pad_cfg_ctrl tables/macros, and code to handle them is
> something I see happening in a separate patchset, if at all, since I
> don't see any other pad cfg registers that ever need writing (beyond
> SDMMC1/3).
Again, the "cfg" registers are part of the pinmux HW, not MMC. If
there's a need to write to them, the pinmux driver needs to do it. We
shouldn't have the MMC driver randomly trample on registers owned by
other code.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [U-Boot] [PATCH v2 4/6] mmc: Tegra: Add SD bus power/voltage function and MMC pad init call.
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
` (2 preceding siblings ...)
2013-03-05 16:29 ` [U-Boot] [PATCH v2 3/6] Tegra30: MMC: Add SD bus power-rail and SDMMC pad init routines Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 5/6] Tegra30: mmc: Add Tegra30 SDMMC compatible entry to fdtdec & driver Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 6/6] Tegra30: MMC: Enable DT MMC driver support for Tegra30 Cardhu boards Tom Warren
5 siblings, 0 replies; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
Tegra30 requires the SD Bus Voltage & Power bits be set in the SD
Power Control register. Tegra20 works w/o them set, but do it anyway
for those SoCs as it's part of the SD spec. Also call a common
board pad init routine (pad_init_mmc) in mmc_reset(), used by
Tegra30 only for now.
Note that Tegra20 SD/MMC HW differs enough from Tegra20 that a
new compatible entry is used in the fdt compat_names/id tables.
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2:
- pass mmc 'host' struct to pad_init_mmc
- probe for Tegra30 SDMMC id in tegra_mmc_init
drivers/mmc/tegra_mmc.c | 63 +++++++++++++++++++++++++++++++++++++++++------
1 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c
index 6063d08..8f5f1a5 100644
--- a/drivers/mmc/tegra_mmc.c
+++ b/drivers/mmc/tegra_mmc.c
@@ -21,7 +21,6 @@
#include <bouncebuf.h>
#include <common.h>
-#include <fdtdec.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
@@ -38,6 +37,38 @@ struct mmc_host mmc_host[MAX_HOSTS];
#error "Please enable device tree support to use this driver"
#endif
+static void mmc_set_power(struct mmc_host *host, unsigned short power)
+{
+ u8 pwr = 0;
+ debug("%s: power = %x\n", __func__, power);
+
+ if (power != (unsigned short)-1) {
+ switch (1 << power) {
+ case MMC_VDD_165_195:
+ pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V1_8;
+ break;
+ case MMC_VDD_29_30:
+ case MMC_VDD_30_31:
+ pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_0;
+ break;
+ case MMC_VDD_32_33:
+ case MMC_VDD_33_34:
+ pwr = TEGRA_MMC_PWRCTL_SD_BUS_VOLTAGE_V3_3;
+ break;
+ }
+ }
+ debug("%s: pwr = %X\n", __func__, pwr);
+
+ /* Set the bus voltage first (if any) */
+ writeb(pwr, &host->reg->pwrcon);
+ if (pwr == 0)
+ return;
+
+ /* Now enable bus power */
+ pwr |= TEGRA_MMC_PWRCTL_SD_BUS_POWER;
+ writeb(pwr, &host->reg->pwrcon);
+}
+
static void mmc_prepare_data(struct mmc_host *host, struct mmc_data *data,
struct bounce_buffer *bbstate)
{
@@ -334,8 +365,7 @@ static void mmc_change_clock(struct mmc_host *host, uint clock)
debug(" mmc_change_clock called\n");
/*
- * Change Tegra SDMMCx clock divisor here. Source is 216MHz,
- * PLLP_OUT0
+ * Change Tegra SDMMCx clock divisor here. Source is PLLP_OUT0
*/
if (clock == 0)
goto out;
@@ -410,7 +440,7 @@ static void mmc_set_ios(struct mmc *mmc)
debug("mmc_set_ios: hostctl = %08X\n", ctrl);
}
-static void mmc_reset(struct mmc_host *host)
+static void mmc_reset(struct mmc_host *host, struct mmc *mmc)
{
unsigned int timeout;
debug(" mmc_reset called\n");
@@ -436,6 +466,14 @@ static void mmc_reset(struct mmc_host *host)
timeout--;
udelay(1000);
}
+
+ /* Set SD bus voltage & enable bus power */
+ mmc_set_power(host, fls(mmc->voltages) - 1);
+ debug("%s: power control = %02X, host control = %02X\n", __func__,
+ readb(&host->reg->pwrcon), readb(&host->reg->hostctl));
+
+ /* Make sure SDIO pads are set up */
+ pad_init_mmc(host);
}
static int mmc_core_init(struct mmc *mmc)
@@ -444,7 +482,7 @@ static int mmc_core_init(struct mmc *mmc)
unsigned int mask;
debug(" mmc_core_init called\n");
- mmc_reset(host);
+ mmc_reset(host, mmc);
host->version = readw(&host->reg->hcver);
debug("host version = %x\n", host->version);
@@ -641,12 +679,21 @@ void tegra_mmc_init(void)
const void *blob = gd->fdt_blob;
debug("%s entry\n", __func__);
+ /* See if any Tegra30 MMC controllers are present */
count = fdtdec_find_aliases_for_id(blob, "sdhci",
- COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS);
- debug("%s: count of sdhci nodes is %d\n", __func__, count);
+ COMPAT_NVIDIA_TEGRA30_SDMMC, node_list, MAX_HOSTS);
+ debug("%s: count of T30 sdhci nodes is %d\n", __func__, count);
+ if (process_nodes(blob, node_list, count)) {
+ printf("%s: Error processing T30 mmc node(s)!\n", __func__);
+ return;
+ }
+ /* Now look for any Tegra20 MMC controllers */
+ count = fdtdec_find_aliases_for_id(blob, "sdhci",
+ COMPAT_NVIDIA_TEGRA20_SDMMC, node_list, MAX_HOSTS);
+ debug("%s: count of T20 sdhci nodes is %d\n", __func__, count);
if (process_nodes(blob, node_list, count)) {
- printf("%s: Error processing mmc node(s)!\n", __func__);
+ printf("%s: Error processing T20 mmc node(s)!\n", __func__);
return;
}
}
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 5/6] Tegra30: mmc: Add Tegra30 SDMMC compatible entry to fdtdec & driver
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
` (3 preceding siblings ...)
2013-03-05 16:29 ` [U-Boot] [PATCH v2 4/6] mmc: Tegra: Add SD bus power/voltage function and MMC pad init call Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
2013-03-05 16:29 ` [U-Boot] [PATCH v2 6/6] Tegra30: MMC: Enable DT MMC driver support for Tegra30 Cardhu boards Tom Warren
5 siblings, 0 replies; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
Tegra30 SD/MMC controller differs enough from Tegra20 that it
needs its own entry in the compat_names/compat_id tables and in
the Tegra MMC driver.
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2: new
include/fdtdec.h | 3 ++-
lib/fdtdec.c | 1 +
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 32730d2..2189483 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -71,7 +71,8 @@ enum fdt_compat_id {
COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */
COMPAT_NVIDIA_TEGRA20_PWM, /* Tegra 2 PWM controller */
COMPAT_NVIDIA_TEGRA20_DC, /* Tegra 2 Display controller */
- COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra SDMMC controller */
+ COMPAT_NVIDIA_TEGRA30_SDMMC, /* Tegra30 SDMMC controller */
+ COMPAT_NVIDIA_TEGRA20_SDMMC, /* Tegra20 SDMMC controller */
COMPAT_NVIDIA_TEGRA20_SFLASH, /* Tegra 2 SPI flash controller */
COMPAT_NVIDIA_TEGRA20_SLINK, /* Tegra 2 SPI SLINK controller */
COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 000130f..43f29f5 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -46,6 +46,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
COMPAT(NVIDIA_TEGRA20_PWM, "nvidia,tegra20-pwm"),
COMPAT(NVIDIA_TEGRA20_DC, "nvidia,tegra20-dc"),
+ COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"),
COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"),
COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"),
COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"),
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread* [U-Boot] [PATCH v2 6/6] Tegra30: MMC: Enable DT MMC driver support for Tegra30 Cardhu boards
2013-03-05 16:29 [U-Boot] [PATCH v2 0/6] Tegra30: MMC: Add DT-based MMC driver for Tegra30/Cardhu Tom Warren
` (4 preceding siblings ...)
2013-03-05 16:29 ` [U-Boot] [PATCH v2 5/6] Tegra30: mmc: Add Tegra30 SDMMC compatible entry to fdtdec & driver Tom Warren
@ 2013-03-05 16:29 ` Tom Warren
5 siblings, 0 replies; 10+ messages in thread
From: Tom Warren @ 2013-03-05 16:29 UTC (permalink / raw)
To: u-boot
Tested on my Cardhu-A04 tablet, eMMC and SD-Card work fine, can load
a kernel off of an SD card OK, card detect works, and the env is now
stored in eMMC (end of the 2nd 'boot' sector, same as Tegra20).
Signed-off-by: Tom Warren <twarren@nvidia.com>
---
v2:
- no change
include/configs/cardhu.h | 20 +++++++++++++++++++-
include/configs/tegra30-common.h | 3 +++
2 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/include/configs/cardhu.h b/include/configs/cardhu.h
index 1616b39..18c7eb8 100644
--- a/include/configs/cardhu.h
+++ b/include/configs/cardhu.h
@@ -47,7 +47,25 @@
#define CONFIG_SYS_I2C_SPEED 100000
#define CONFIG_CMD_I2C
-#define CONFIG_ENV_IS_NOWHERE
+/* SD/MMC */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_TEGRA_MMC
+#define CONFIG_CMD_MMC
+
+#define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_FS_EXT4
+#define CONFIG_FS_FAT
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_FAT
+#define CONFIG_CMD_FS_GENERIC
+
+/* Environment in eMMC, at the end of 2nd "boot sector" */
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET ((512 * 1024) - CONFIG_ENV_SIZE)
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_SYS_MMC_ENV_PART 2
/* SPI */
#define CONFIG_TEGRA_SLINK
diff --git a/include/configs/tegra30-common.h b/include/configs/tegra30-common.h
index 04517e1..bd1dfe8 100644
--- a/include/configs/tegra30-common.h
+++ b/include/configs/tegra30-common.h
@@ -86,4 +86,7 @@
/* Total I2C ports on Tegra30 */
#define TEGRA_I2C_NUM_CONTROLLERS 5
+/* Misc utility code */
+#define CONFIG_BOUNCE_BUFFER
+
#endif /* _TEGRA30_COMMON_H_ */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 10+ messages in thread