Commit d95ecbd6 authored by Ryan QIAN's avatar Ryan QIAN Committed by Jason Liu

ENGR00213944-02: mmc: sdhci: [MX6] support SD v3.0 memory cards.

- Add variable pad speed setting per SD clk freq.
- Add SD3.0 support on SD1, SD2, and SD3.
- Enhance drive strength on SD pad to improve its compatibility.
- change the definition of pad speed changing interface
- combine pad speed setting for different SD host controllers into one function.
Signed-off-by: default avatarRyan QIAN <b32804@freescale.com>
Acked-by: Lily Zhang
parent a4c1285d
...@@ -176,111 +176,84 @@ enum sd_pad_mode { ...@@ -176,111 +176,84 @@ enum sd_pad_mode {
SD_PAD_MODE_HIGH_SPEED, SD_PAD_MODE_HIGH_SPEED,
}; };
static int plt_sd3_pad_change(int clock) static int plt_sd_pad_change(unsigned int index, int clock)
{ {
/* LOW speed is the default state of SD pads */
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
iomux_v3_cfg_t *sd3_pads_200mhz = NULL; iomux_v3_cfg_t *sd_pads_200mhz;
iomux_v3_cfg_t *sd3_pads_100mhz = NULL; iomux_v3_cfg_t *sd_pads_100mhz;
iomux_v3_cfg_t *sd3_pads_50mhz = NULL; iomux_v3_cfg_t *sd_pads_50mhz;
u32 sd3_pads_200mhz_cnt; u32 sd_pads_200mhz_cnt;
u32 sd3_pads_100mhz_cnt; u32 sd_pads_100mhz_cnt;
u32 sd3_pads_50mhz_cnt; u32 sd_pads_50mhz_cnt;
if (cpu_is_mx6q()) { switch (index) {
sd3_pads_200mhz = mx6q_sd3_200mhz; case 2:
sd3_pads_100mhz = mx6q_sd3_100mhz; if (cpu_is_mx6q()) {
sd3_pads_50mhz = mx6q_sd3_50mhz; sd_pads_200mhz = mx6q_sd3_200mhz;
sd_pads_100mhz = mx6q_sd3_100mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz); sd_pads_50mhz = mx6q_sd3_50mhz;
sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
} else if (cpu_is_mx6dl()) {
sd3_pads_200mhz = mx6dl_sd3_200mhz;
sd3_pads_100mhz = mx6dl_sd3_100mhz;
sd3_pads_50mhz = mx6dl_sd3_50mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz);
}
if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0;
BUG_ON(!sd3_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_200mhz,
sd3_pads_200mhz_cnt);
} else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0;
BUG_ON(!sd3_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_100mhz,
sd3_pads_100mhz_cnt);
} else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0;
BUG_ON(!sd3_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_50mhz,
sd3_pads_50mhz_cnt);
}
}
static int plt_sd4_pad_change(int clock)
{
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
iomux_v3_cfg_t *sd4_pads_200mhz = NULL;
iomux_v3_cfg_t *sd4_pads_100mhz = NULL;
iomux_v3_cfg_t *sd4_pads_50mhz = NULL;
u32 sd4_pads_200mhz_cnt; sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
u32 sd4_pads_100mhz_cnt; sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
u32 sd4_pads_50mhz_cnt; sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
} else if (cpu_is_mx6dl()) {
sd_pads_200mhz = mx6dl_sd3_200mhz;
sd_pads_100mhz = mx6dl_sd3_100mhz;
sd_pads_50mhz = mx6dl_sd3_50mhz;
if (cpu_is_mx6q()) { sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
sd4_pads_200mhz = mx6q_sd4_200mhz; sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
sd4_pads_100mhz = mx6q_sd4_100mhz; sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz);
sd4_pads_50mhz = mx6q_sd4_50mhz; }
break;
case 3:
if (cpu_is_mx6q()) {
sd_pads_200mhz = mx6q_sd4_200mhz;
sd_pads_100mhz = mx6q_sd4_100mhz;
sd_pads_50mhz = mx6q_sd4_50mhz;
sd4_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz); sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz);
sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz); sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz);
sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz); sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz);
} else if (cpu_is_mx6dl()) { } else if (cpu_is_mx6dl()) {
sd4_pads_200mhz = mx6dl_sd4_200mhz; sd_pads_200mhz = mx6dl_sd4_200mhz;
sd4_pads_100mhz = mx6dl_sd4_100mhz; sd_pads_100mhz = mx6dl_sd4_100mhz;
sd4_pads_50mhz = mx6dl_sd4_50mhz; sd_pads_50mhz = mx6dl_sd4_50mhz;
sd4_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz); sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz);
sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz); sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz);
sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd4_50mhz); sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd4_50mhz);
}
break;
default:
printk(KERN_ERR "no such SD host controller index %d\n", index);
return -EINVAL;
} }
if (clock > 100000000) { if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED) if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED; pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd4_pads_200mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
sd4_pads_200mhz_cnt); sd_pads_200mhz_cnt);
} else if (clock > 52000000) { } else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED) if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED; pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd4_pads_100mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
sd4_pads_100mhz_cnt); sd_pads_100mhz_cnt);
} else { } else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED) if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED; pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd4_pads_50mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd4_pads_50mhz_cnt); sd_pads_50mhz_cnt);
} }
} }
...@@ -291,7 +264,7 @@ static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = { ...@@ -291,7 +264,7 @@ static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
.support_8bit = 1, .support_8bit = 1,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.delay_line = 0, .delay_line = 0,
.platform_pad_change = plt_sd3_pad_change, .platform_pad_change = plt_sd_pad_change,
}; };
/* No card detect signal for SD4 on ARM2 board*/ /* No card detect signal for SD4 on ARM2 board*/
...@@ -299,7 +272,7 @@ static const struct esdhc_platform_data mx6_arm2_sd4_data __initconst = { ...@@ -299,7 +272,7 @@ static const struct esdhc_platform_data mx6_arm2_sd4_data __initconst = {
.always_present = 1, .always_present = 1,
.support_8bit = 1, .support_8bit = 1,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.platform_pad_change = plt_sd4_pad_change, .platform_pad_change = plt_sd_pad_change,
}; };
static int __init gpmi_nand_platform_init(void) static int __init gpmi_nand_platform_init(void)
......
...@@ -208,57 +208,63 @@ static void __init imx6q_add_android_device_buttons(void) ...@@ -208,57 +208,63 @@ static void __init imx6q_add_android_device_buttons(void)
static void __init imx6q_add_android_device_buttons(void) {} static void __init imx6q_add_android_device_buttons(void) {}
#endif #endif
static int plt_sd3_pad_change(int clock) static int plt_sd_pad_change(unsigned int index, int clock)
{ {
/* LOW speed is the default state of SD pads */
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
iomux_v3_cfg_t *sd3_pads_200mhz = NULL; iomux_v3_cfg_t *sd_pads_200mhz;
iomux_v3_cfg_t *sd3_pads_100mhz = NULL; iomux_v3_cfg_t *sd_pads_100mhz;
iomux_v3_cfg_t *sd3_pads_50mhz = NULL; iomux_v3_cfg_t *sd_pads_50mhz;
u32 sd3_pads_200mhz_cnt; u32 sd_pads_200mhz_cnt;
u32 sd3_pads_100mhz_cnt; u32 sd_pads_100mhz_cnt;
u32 sd3_pads_50mhz_cnt; u32 sd_pads_50mhz_cnt;
if (index != 2) {
printk(KERN_ERR"no such SD host controller index %d\n", index);
return -EINVAL;
}
if (cpu_is_mx6q()) { if (cpu_is_mx6q()) {
sd3_pads_200mhz = mx6q_sd3_200mhz; sd_pads_200mhz = mx6q_sd3_200mhz;
sd3_pads_100mhz = mx6q_sd3_100mhz; sd_pads_100mhz = mx6q_sd3_100mhz;
sd3_pads_50mhz = mx6q_sd3_50mhz; sd_pads_50mhz = mx6q_sd3_50mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz); sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz); sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz); sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
} else if (cpu_is_mx6dl()) { } else if (cpu_is_mx6dl()) {
sd3_pads_200mhz = mx6dl_sd3_200mhz; sd_pads_200mhz = mx6dl_sd3_200mhz;
sd3_pads_100mhz = mx6dl_sd3_100mhz; sd_pads_100mhz = mx6dl_sd3_100mhz;
sd3_pads_50mhz = mx6dl_sd3_50mhz; sd_pads_50mhz = mx6dl_sd3_50mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz); sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz); sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz); sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_50mhz);
} }
if (clock > 100000000) { if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED) if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0; return 0;
BUG_ON(!sd3_pads_200mhz); BUG_ON(!sd_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED; pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_200mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
sd3_pads_200mhz_cnt); sd_pads_200mhz_cnt);
} else if (clock > 52000000) { } else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED) if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0; return 0;
BUG_ON(!sd3_pads_100mhz); BUG_ON(!sd_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED; pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_100mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
sd3_pads_100mhz_cnt); sd_pads_100mhz_cnt);
} else { } else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED) if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0; return 0;
BUG_ON(!sd3_pads_50mhz); BUG_ON(!sd_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED; pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_50mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd3_pads_50mhz_cnt); sd_pads_50mhz_cnt);
} }
} }
...@@ -269,7 +275,7 @@ static const struct esdhc_platform_data mx6q_sabreauto_sd3_data __initconst = { ...@@ -269,7 +275,7 @@ static const struct esdhc_platform_data mx6q_sabreauto_sd3_data __initconst = {
.support_18v = 1, .support_18v = 1,
.support_8bit = 1, .support_8bit = 1,
.delay_line = 0, .delay_line = 0,
.platform_pad_change = plt_sd3_pad_change, .platform_pad_change = plt_sd_pad_change,
}; };
static const struct esdhc_platform_data mx6q_sabreauto_sd1_data __initconst = { static const struct esdhc_platform_data mx6q_sabreauto_sd1_data __initconst = {
......
...@@ -349,59 +349,64 @@ enum sd_pad_mode { ...@@ -349,59 +349,64 @@ enum sd_pad_mode {
SD_PAD_MODE_HIGH_SPEED, SD_PAD_MODE_HIGH_SPEED,
}; };
static int plt_sd3_pad_change(int clock) static int plt_sd_pad_change(unsigned int index, int clock)
{ {
/* LOW speed is the default state of SD pads */
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED; static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
if (clock > 100000000) { iomux_v3_cfg_t *sd_pads_200mhz;
if (pad_mode == SD_PAD_MODE_HIGH_SPEED) iomux_v3_cfg_t *sd_pads_100mhz;
return 0; iomux_v3_cfg_t *sd_pads_50mhz;
pad_mode = SD_PAD_MODE_HIGH_SPEED; u32 sd_pads_200mhz_cnt;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_200mhz, u32 sd_pads_100mhz_cnt;
ARRAY_SIZE(mx6q_sd3_200mhz)); u32 sd_pads_50mhz_cnt;
} else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED) switch (index) {
return 0; case 2:
sd_pads_200mhz = mx6q_sd3_200mhz;
pad_mode = SD_PAD_MODE_MED_SPEED; sd_pads_100mhz = mx6q_sd3_100mhz;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_100mhz, sd_pads_50mhz = mx6q_sd3_50mhz;
ARRAY_SIZE(mx6q_sd3_100mhz));
} else { sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
if (pad_mode == SD_PAD_MODE_LOW_SPEED) sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
return 0; sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
break;
pad_mode = SD_PAD_MODE_LOW_SPEED; case 3:
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_50mhz, sd_pads_200mhz = mx6q_sd4_200mhz;
ARRAY_SIZE(mx6q_sd3_50mhz)); sd_pads_100mhz = mx6q_sd4_100mhz;
sd_pads_50mhz = mx6q_sd4_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd4_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz);
break;
default:
printk(KERN_ERR "no such SD host controller index %d\n", index);
return -EINVAL;
} }
}
static int plt_sd4_pad_change(int clock)
{
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
if (clock > 100000000) { if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED) if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED; pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_200mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
ARRAY_SIZE(mx6q_sd4_200mhz)); sd_pads_200mhz_cnt);
} else if (clock > 52000000) { } else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED) if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED; pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_100mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
ARRAY_SIZE(mx6q_sd4_100mhz)); sd_pads_100mhz_cnt);
} else { } else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED) if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0; return 0;
BUG_ON(!sd_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED; pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd4_50mhz, return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
ARRAY_SIZE(mx6q_sd4_50mhz)); sd_pads_50mhz_cnt);
} }
} }
...@@ -409,14 +414,14 @@ static const struct esdhc_platform_data mx6q_sabrelite_sd3_data __initconst = { ...@@ -409,14 +414,14 @@ static const struct esdhc_platform_data mx6q_sabrelite_sd3_data __initconst = {
.cd_gpio = MX6Q_SABRELITE_SD3_CD, .cd_gpio = MX6Q_SABRELITE_SD3_CD,
.wp_gpio = MX6Q_SABRELITE_SD3_WP, .wp_gpio = MX6Q_SABRELITE_SD3_WP,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.platform_pad_change = plt_sd3_pad_change, .platform_pad_change = plt_sd_pad_change,
}; };
static const struct esdhc_platform_data mx6q_sabrelite_sd4_data __initconst = { static const struct esdhc_platform_data mx6q_sabrelite_sd4_data __initconst = {
.cd_gpio = MX6Q_SABRELITE_SD4_CD, .cd_gpio = MX6Q_SABRELITE_SD4_CD,
.wp_gpio = MX6Q_SABRELITE_SD4_WP, .wp_gpio = MX6Q_SABRELITE_SD4_WP,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.platform_pad_change = plt_sd4_pad_change, .platform_pad_change = plt_sd_pad_change,
}; };
static const struct anatop_thermal_platform_data static const struct anatop_thermal_platform_data
......
...@@ -133,12 +133,91 @@ static int max17135_regulator_init(struct max17135 *max17135); ...@@ -133,12 +133,91 @@ static int max17135_regulator_init(struct max17135 *max17135);
struct clk *extern_audio_root; struct clk *extern_audio_root;
extern int __init mx6sl_arm2_init_pfuze100(u32 int_gpio); extern int __init mx6sl_arm2_init_pfuze100(u32 int_gpio);
enum sd_pad_mode {
SD_PAD_MODE_LOW_SPEED,
SD_PAD_MODE_MED_SPEED,
SD_PAD_MODE_HIGH_SPEED,
};
static int plt_sd_pad_change(unsigned int index, int clock)
{
/* LOW speed is the default state of SD pads */
static enum sd_pad_mode pad_mode = SD_PAD_MODE_LOW_SPEED;
iomux_v3_cfg_t *sd_pads_200mhz;
iomux_v3_cfg_t *sd_pads_100mhz;
iomux_v3_cfg_t *sd_pads_50mhz;
u32 sd_pads_200mhz_cnt;
u32 sd_pads_100mhz_cnt;
u32 sd_pads_50mhz_cnt;
switch (index) {
case 0:
sd_pads_200mhz = mx6sl_sd1_200mhz;
sd_pads_100mhz = mx6sl_sd1_100mhz;
sd_pads_50mhz = mx6sl_sd1_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd1_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd1_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd1_50mhz);
break;
case 1:
sd_pads_200mhz = mx6sl_sd2_200mhz;
sd_pads_100mhz = mx6sl_sd2_100mhz;
sd_pads_50mhz = mx6sl_sd2_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd2_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd2_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd2_50mhz);
break;
case 2:
sd_pads_200mhz = mx6sl_sd3_200mhz;
sd_pads_100mhz = mx6sl_sd3_100mhz;
sd_pads_50mhz = mx6sl_sd3_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6sl_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6sl_sd3_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6sl_sd3_50mhz);
break;
default:
printk(KERN_ERR "no such SD host controller index %d\n", index);
return -EINVAL;
}
if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0;
BUG_ON(!sd_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd_pads_200mhz,
sd_pads_200mhz_cnt);
} else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0;
BUG_ON(!sd_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd_pads_100mhz,
sd_pads_100mhz_cnt);
} else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0;
BUG_ON(!sd_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd_pads_50mhz_cnt);
}
}
static const struct esdhc_platform_data mx6_arm2_sd1_data __initconst = { static const struct esdhc_platform_data mx6_arm2_sd1_data __initconst = {
.cd_gpio = MX6_ARM2_SD1_CD, .cd_gpio = MX6_ARM2_SD1_CD,
.wp_gpio = MX6_ARM2_SD1_WP, .wp_gpio = MX6_ARM2_SD1_WP,
.support_8bit = 1, .support_8bit = 1,
.support_18v = 1,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.delay_line = 0, .delay_line = 0,
.platform_pad_change = plt_sd_pad_change,
}; };
static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = { static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = {
...@@ -146,12 +225,17 @@ static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = { ...@@ -146,12 +225,17 @@ static const struct esdhc_platform_data mx6_arm2_sd2_data __initconst = {
.wp_gpio = MX6_ARM2_SD2_WP, .wp_gpio = MX6_ARM2_SD2_WP,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.delay_line = 0, .delay_line = 0,
.support_18v = 1,
.platform_pad_change = plt_sd_pad_change,
}; };
static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = { static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
.cd_gpio = MX6_ARM2_SD3_CD, .cd_gpio = MX6_ARM2_SD3_CD,
.wp_gpio = -1,
.keep_power_at_suspend = 1, .keep_power_at_suspend = 1,
.delay_line = 0, .delay_line = 0,
.support_18v = 1,
.platform_pad_change = plt_sd_pad_change,
}; };
#define mV_to_uV(mV) (mV * 1000) #define mV_to_uV(mV) (mV * 1000)
......
...@@ -50,36 +50,36 @@ static iomux_v3_cfg_t mx6sl_arm2_pads[] = { ...@@ -50,36 +50,36 @@ static iomux_v3_cfg_t mx6sl_arm2_pads[] = {
MX6SL_PAD_HSIC_DAT__USB_H_DATA, MX6SL_PAD_HSIC_DAT__USB_H_DATA,
/* SD1 */ /* SD1 */
MX6SL_PAD_SD1_CLK__USDHC1_CLK, MX6SL_PAD_SD1_CLK__USDHC1_CLK_50MHZ,
MX6SL_PAD_SD1_CMD__USDHC1_CMD, MX6SL_PAD_SD1_CMD__USDHC1_CMD_50MHZ,
MX6SL_PAD_SD1_DAT0__USDHC1_DAT0, MX6SL_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ,
MX6SL_PAD_SD1_DAT1__USDHC1_DAT1, MX6SL_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ,
MX6SL_PAD_SD1_DAT2__USDHC1_DAT2, MX6SL_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ,
MX6SL_PAD_SD1_DAT3__USDHC1_DAT3, MX6SL_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ,
MX6SL_PAD_SD1_DAT4__USDHC1_DAT4, MX6SL_PAD_SD1_DAT4__USDHC1_DAT4_50MHZ,
MX6SL_PAD_SD1_DAT5__USDHC1_DAT5, MX6SL_PAD_SD1_DAT5__USDHC1_DAT5_50MHZ,
MX6SL_PAD_SD1_DAT6__USDHC1_DAT6, MX6SL_PAD_SD1_DAT6__USDHC1_DAT6_50MHZ,
MX6SL_PAD_SD1_DAT7__USDHC1_DAT7, MX6SL_PAD_SD1_DAT7__USDHC1_DAT7_50MHZ,
/* SD1 CD & WP */ /* SD1 CD & WP */
MX6SL_PAD_KEY_ROW7__GPIO_4_7, MX6SL_PAD_KEY_ROW7__GPIO_4_7,
MX6SL_PAD_KEY_COL7__GPIO_4_6, MX6SL_PAD_KEY_COL7__GPIO_4_6,
/* SD2 */ /* SD2 */
MX6SL_PAD_SD2_CLK__USDHC2_CLK, MX6SL_PAD_SD2_CLK__USDHC2_CLK_50MHZ,
MX6SL_PAD_SD2_CMD__USDHC2_CMD, MX6SL_PAD_SD2_CMD__USDHC2_CMD_50MHZ,
MX6SL_PAD_SD2_DAT0__USDHC2_DAT0, MX6SL_PAD_SD2_DAT0__USDHC2_DAT0_50MHZ,
MX6SL_PAD_SD2_DAT1__USDHC2_DAT1, MX6SL_PAD_SD2_DAT1__USDHC2_DAT1_50MHZ,
MX6SL_PAD_SD2_DAT2__USDHC2_DAT2, MX6SL_PAD_SD2_DAT2__USDHC2_DAT2_50MHZ,
MX6SL_PAD_SD2_DAT3__USDHC2_DAT3, MX6SL_PAD_SD2_DAT3__USDHC2_DAT3_50MHZ,
/* SD2 CD & WP */ /* SD2 CD & WP */
MX6SL_PAD_SD2_DAT7__GPIO_5_0, MX6SL_PAD_SD2_DAT7__GPIO_5_0,
MX6SL_PAD_SD2_DAT6__GPIO_4_29, MX6SL_PAD_SD2_DAT6__GPIO_4_29,
/* SD3 */ /* SD3 */
MX6SL_PAD_SD3_CLK__USDHC3_CLK, MX6SL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
MX6SL_PAD_SD3_CMD__USDHC3_CMD, MX6SL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
MX6SL_PAD_SD3_DAT0__USDHC3_DAT0, MX6SL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
MX6SL_PAD_SD3_DAT1__USDHC3_DAT1, MX6SL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
MX6SL_PAD_SD3_DAT2__USDHC3_DAT2, MX6SL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
MX6SL_PAD_SD3_DAT3__USDHC3_DAT3, MX6SL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
/* SD3 CD */ /* SD3 CD */
MX6SL_PAD_REF_CLK_32K__GPIO_3_22, MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
...@@ -318,4 +318,38 @@ static iomux_v3_cfg_t mx6sl_arm2_elan_pads[] = { ...@@ -318,4 +318,38 @@ static iomux_v3_cfg_t mx6sl_arm2_elan_pads[] = {
MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */ MX6SL_PAD_KEY_COL6__GPIO_4_4, /* RST */
}; };
#define MX6SL_USDHC_8BIT_PAD_SETTING(id, speed) \
mx6sl_sd##id##_##speed##mhz[] = { \
MX6SL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
MX6SL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT4__USDHC##id##_DAT4_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT5__USDHC##id##_DAT5_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT6__USDHC##id##_DAT6_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT7__USDHC##id##_DAT7_##speed##MHZ, \
}
#define MX6SL_USDHC_4BIT_PAD_SETTING(id, speed) \
mx6sl_sd##id##_##speed##mhz[] = { \
MX6SL_PAD_SD##id##_CLK__USDHC##id##_CLK_##speed##MHZ, \
MX6SL_PAD_SD##id##_CMD__USDHC##id##_CMD_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT0__USDHC##id##_DAT0_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT1__USDHC##id##_DAT1_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT2__USDHC##id##_DAT2_##speed##MHZ, \
MX6SL_PAD_SD##id##_DAT3__USDHC##id##_DAT3_##speed##MHZ, \
}
static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 50);
static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 100);
static iomux_v3_cfg_t MX6SL_USDHC_8BIT_PAD_SETTING(1, 200);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 50);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 100);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(2, 200);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 50);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 100);
static iomux_v3_cfg_t MX6SL_USDHC_4BIT_PAD_SETTING(3, 200);
#endif #endif
...@@ -35,6 +35,6 @@ struct esdhc_platform_data { ...@@ -35,6 +35,6 @@ struct esdhc_platform_data {
unsigned int support_8bit; unsigned int support_8bit;
unsigned int keep_power_at_suspend; unsigned int keep_power_at_suspend;