diff mbox

[U-Boot] Tegra30: Cardhu: Add pad config tables/code based on pinmux code

Message ID 1362613874-24846-1-git-send-email-twarren@nvidia.com
State Accepted
Delegated to: Tom Warren
Headers show

Commit Message

Tom Warren March 6, 2013, 11:51 p.m. UTC
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, only SDIO1CFG is changed as per the TRM to work with
the SD-card slot on Cardhu.

Thanks to StephenW for the suggestion/original idea.

Signed-off-by: Tom Warren <twarren@nvidia.com>
---
 arch/arm/cpu/tegra30-common/pinmux.c           |  210 +++++++++++++++++++++---
 arch/arm/include/asm/arch-tegra30/gp_padctrl.h |    8 +-
 arch/arm/include/asm/arch-tegra30/pinmux.h     |   68 ++++++++-
 board/nvidia/cardhu/cardhu.c                   |    6 +-
 board/nvidia/cardhu/pinmux-config-cardhu.h     |   21 ++-
 5 files changed, 278 insertions(+), 35 deletions(-)

Comments

Stephen Warren March 7, 2013, 8:27 p.m. UTC | #1
On 03/06/2013 04:51 PM, Tom Warren wrote:
> 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, only SDIO1CFG is changed as per the TRM to work with
> the SD-card slot on Cardhu.
> 
> Thanks to StephenW for the suggestion/original idea.

As a general rule, I'd expect the pinmux driver implementation to be a
separate patch from the changes to the Cardhu board file to use the new
features, but I guess you're replacing an existing
pinmux_sdio_pad_cfg(), so that isn't possible. So it's fine.

> diff --git a/board/nvidia/cardhu/pinmux-config-cardhu.h b/board/nvidia/cardhu/pinmux-config-cardhu.h

> +static struct padctrl_config cardhu_padctrl[] = {
> +	/* (_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */
> +	DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \
> +		SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE),
> +};
> +#endif	/* _PINMUX_CONFIG_CARDHU_H_ */

I didn't quite get why there wasn't an SDIO3 entry in that table, since
the original pinmux_sdio_pad_cfg() set up both SDIO1 and SDIO3 pin
groups, and SDIO3 appears to be used on Cardhu for SDIO-based WiFi.

Aside from that,
Reviewed-by: Stephen Warren <swarren@nvidia.com>
Tom Warren March 7, 2013, 9:13 p.m. UTC | #2
Stephen,

On Thu, Mar 7, 2013 at 1:27 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
> On 03/06/2013 04:51 PM, Tom Warren wrote:
>> 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, only SDIO1CFG is changed as per the TRM to work with
>> the SD-card slot on Cardhu.
>>
>> Thanks to StephenW for the suggestion/original idea.
>
> As a general rule, I'd expect the pinmux driver implementation to be a
> separate patch from the changes to the Cardhu board file to use the new
> features, but I guess you're replacing an existing
> pinmux_sdio_pad_cfg(), so that isn't possible. So it's fine.
OK. Thanks.

>
>> diff --git a/board/nvidia/cardhu/pinmux-config-cardhu.h b/board/nvidia/cardhu/pinmux-config-cardhu.h
>
>> +static struct padctrl_config cardhu_padctrl[] = {
>> +     /* (_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */
>> +     DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \
>> +             SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE),
>> +};
>> +#endif       /* _PINMUX_CONFIG_CARDHU_H_ */
>
> I didn't quite get why there wasn't an SDIO3 entry in that table, since
> the original pinmux_sdio_pad_cfg() set up both SDIO1 and SDIO3 pin
> groups, and SDIO3 appears to be used on Cardhu for SDIO-based WiFi.

The previous code did check for SDMMC1 or SDMMC3, but on Cardhu,
SDMMC1 is called out in the dts file, and SDMMC3 isn't (you had said
earlier when reviewing some Ventana changes that leaving out a SDIO
WIFI node was ok as U-Boot wouldn't be using it, so I didn't add it to
Cardhu). So the old code would only have called the pad init code for
SDMMC1 and SDMMC4, and SDMMC4 would have been rejected since it's not
SDIO.  So I only added SDIO1 to the table.  I can add an entry for
SDIO3 (even if it's not in the dts file for Cardhu), since it does no
harm to set those pad cfg registers as per the TRM (I assume the TRM
is calling out cal numbers that will work with both an SD-card slot
and a WIFI device?).

Let me know if you'd like to see either the WIFI node added to the
Cardhu DT file, or the SDIO3 entry added to the cardhu_padctrl table,
or both.

Tom
>
> Aside from that,
> Reviewed-by: Stephen Warren <swarren@nvidia.com>
Stephen Warren March 7, 2013, 9:18 p.m. UTC | #3
On 03/07/2013 02:13 PM, Tom Warren wrote:
> Stephen,
> 
> On Thu, Mar 7, 2013 at 1:27 PM, Stephen Warren <swarren@wwwdotorg.org> wrote:
>> On 03/06/2013 04:51 PM, Tom Warren wrote:
>>> 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, only SDIO1CFG is changed as per the TRM to work with
>>> the SD-card slot on Cardhu.
...
>> I didn't quite get why there wasn't an SDIO3 entry in that table, since
>> the original pinmux_sdio_pad_cfg() set up both SDIO1 and SDIO3 pin
>> groups, and SDIO3 appears to be used on Cardhu for SDIO-based WiFi.
> 
> The previous code did check for SDMMC1 or SDMMC3, but on Cardhu,
> SDMMC1 is called out in the dts file, and SDMMC3 isn't (you had said
> earlier when reviewing some Ventana changes that leaving out a SDIO
> WIFI node was ok as U-Boot wouldn't be using it, so I didn't add it to
> Cardhu). So the old code would only have called the pad init code for
> SDMMC1 and SDMMC4, and SDMMC4 would have been rejected since it's not
> SDIO.  So I only added SDIO1 to the table.  I can add an entry for
> SDIO3 (even if it's not in the dts file for Cardhu), since it does no
> harm to set those pad cfg registers as per the TRM (I assume the TRM
> is calling out cal numbers that will work with both an SD-card slot
> and a WIFI device?).
> 
> Let me know if you'd like to see either the WIFI node added to the
> Cardhu DT file, or the SDIO3 entry added to the cardhu_padctrl table,
> or both.

Ah OK, now I understand. This is fine for now; we can add the extra
table entries if we need them. The kernel does set them up for its own
use of WiFi.
diff mbox

Patch

diff --git a/arch/arm/cpu/tegra30-common/pinmux.c b/arch/arm/cpu/tegra30-common/pinmux.c
index 9ba0ec8..5a5862a 100644
--- a/arch/arm/cpu/tegra30-common/pinmux.c
+++ b/arch/arm/cpu/tegra30-common/pinmux.c
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -39,6 +39,19 @@  struct tegra_pingroup_desc {
 #define PMUX_LOCK_SHIFT		7
 #define PMUX_IO_RESET_SHIFT	8
 
+#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)	\
 	{						\
@@ -506,28 +519,177 @@  void pinmux_config_table(struct pingroup_config *config, int len)
 		pinmux_config_pingroup(&config[i]);
 }
 
-void pinmux_sdio_pad_cfg(void)
+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 apb_misc_gp_ctlr *const gpc =
-		(struct apb_misc_gp_ctlr *)NV_PA_APB_MISC_GP_BASE;
-	u32 val, padcfg, padmask;
-
-	/*
-	 * Set pads as per T30 TRM, section 24.6.1.2.
-	 * Slam both SDIO1CFG and SDIO3CFG in the APB_MISC_GP space
-	 * since we can't parse the MMC cfg this early.
-	 */
-	padcfg = (GP_SDIOCFG_DRVUP_SLWF | GP_SDIOCFG_DRVDN_SLWR | \
-		GP_SDIOCFG_DRVUP | GP_SDIOCFG_DRVDN);
-	padmask = 0x00000FFF;
-
-	val = readl(&gpc->sdio1cfg);
-	val &= padmask;
-	val |= padcfg;
-	writel(val, &gpc->sdio1cfg);
-
-	val = readl(&gpc->sdio3cfg);
-	val &= padmask;
-	val |= padcfg;
-	writel(val, &gpc->sdio3cfg);
+	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));
+
+	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));
+
+	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-tegra30/gp_padctrl.h b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h
index 48b9a3b..23d184f 100644
--- a/arch/arm/include/asm/arch-tegra30/gp_padctrl.h
+++ b/arch/arm/include/asm/arch-tegra30/gp_padctrl.h
@@ -57,9 +57,9 @@  struct apb_misc_gp_ctlr {
 };
 
 /* 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)
+#define SDIOCFG_DRVUP_SLWF	1
+#define SDIOCFG_DRVDN_SLWR	1
+#define SDIOCFG_DRVUP		0x2E
+#define SDIOCFG_DRVDN		0x2A
 
 #endif	/* _TEGRA30_GP_PADCTRL_H_ */
diff --git a/arch/arm/include/asm/arch-tegra30/pinmux.h b/arch/arm/include/asm/arch-tegra30/pinmux.h
index 0a341b4..a9e1b46 100644
--- a/arch/arm/include/asm/arch-tegra30/pinmux.h
+++ b/arch/arm/include/asm/arch-tegra30/pinmux.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -531,6 +531,63 @@  enum pmux_vddio {
 	PMUX_VDDIO_NONE
 };
 
+#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
+
+/* 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) >= 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) >= 0) && ((drv) <= PGRP_DRVUP_MAX))
+
+/* return 1 if a low-power mode value is in range */
+#define pmux_pad_lpmd_isvalid(lpm) (((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    */
+};
+
 /* t30 pin drive group and pin mux registers */
 #define PDRIVE_PINGROUP_OFFSET	(0x868 >> 2)
 #define PMUX_OFFSET	((0x3000 >> 2) - PDRIVE_PINGROUP_OFFSET - \
@@ -600,7 +657,12 @@  void pinmux_config_table(struct pingroup_config *config, int len);
 /* Set a group of pins from a table */
 void pinmux_init(void);
 
-/* Set the GP pad cfg as per the TRM for SDIO */
-void pinmux_sdio_pad_cfg(void);
+/**
+ * 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	/* _TEGRA30_PINMUX_H_ */
diff --git a/board/nvidia/cardhu/cardhu.c b/board/nvidia/cardhu/cardhu.c
index ae9afba..3544b41 100644
--- a/board/nvidia/cardhu/cardhu.c
+++ b/board/nvidia/cardhu/cardhu.c
@@ -1,5 +1,5 @@ 
 /*
- *  (C) Copyright 2010-2012
+ *  (C) Copyright 2010-2013
  *  NVIDIA Corporation <www.nvidia.com>
  *
  * See file CREDITS for list of people who contributed to this
@@ -23,6 +23,7 @@ 
 
 #include <common.h>
 #include <asm/arch/pinmux.h>
+#include <asm/arch/gp_padctrl.h>
 #include "pinmux-config-cardhu.h"
 #include <i2c.h>
 
@@ -41,7 +42,8 @@  void pinmux_init(void)
 	pinmux_config_table(unused_pins_lowpower,
 		ARRAY_SIZE(unused_pins_lowpower));
 
-	pinmux_sdio_pad_cfg();
+	/* Initialize any non-default pad configs (APB_MISC_GP regs) */
+	padgrp_config_table(cardhu_padctrl, ARRAY_SIZE(cardhu_padctrl));
 }
 
 #if defined(CONFIG_TEGRA_MMC)
diff --git a/board/nvidia/cardhu/pinmux-config-cardhu.h b/board/nvidia/cardhu/pinmux-config-cardhu.h
index 8428bba..51d2b94 100644
--- a/board/nvidia/cardhu/pinmux-config-cardhu.h
+++ b/board/nvidia/cardhu/pinmux-config-cardhu.h
@@ -1,5 +1,5 @@ 
 /*
- * Copyright (c) 2010-2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -53,6 +53,18 @@ 
 		.ioreset	= PMUX_PIN_IO_RESET_##_ioreset	\
 	}
 
+#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 tegra3_pinmux_common[] = {
 	/* SDMMC1 pinmux */
 	DEFAULT_PINMUX(SDMMC1_CLK, SDMMC1, NORMAL, NORMAL, INPUT),
@@ -326,4 +338,9 @@  static struct pingroup_config unused_pins_lowpower[] = {
 	DEFAULT_PINMUX(GMI_DQS, NAND, NORMAL, TRISTATE, OUTPUT),
 };
 
-#endif /* _PINMUX_CONFIG_CARDHU_H_ */
+static struct padctrl_config cardhu_padctrl[] = {
+	/* (_padgrp, _slwf, _slwr, _drvup, _drvdn, _lpmd, _schmt, _hsm) */
+	DEFAULT_PADCFG(SDIO1, SDIOCFG_DRVUP_SLWF, SDIOCFG_DRVDN_SLWR, \
+		SDIOCFG_DRVUP, SDIOCFG_DRVDN, NONE, DISABLE, DISABLE),
+};
+#endif	/* _PINMUX_CONFIG_CARDHU_H_ */