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 {
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;
iomux_v3_cfg_t *sd3_pads_200mhz = NULL;
iomux_v3_cfg_t *sd3_pads_100mhz = NULL;
iomux_v3_cfg_t *sd3_pads_50mhz = NULL;
iomux_v3_cfg_t *sd_pads_200mhz;
iomux_v3_cfg_t *sd_pads_100mhz;
iomux_v3_cfg_t *sd_pads_50mhz;
u32 sd3_pads_200mhz_cnt;
u32 sd3_pads_100mhz_cnt;
u32 sd3_pads_50mhz_cnt;
u32 sd_pads_200mhz_cnt;
u32 sd_pads_100mhz_cnt;
u32 sd_pads_50mhz_cnt;
if (cpu_is_mx6q()) {
sd3_pads_200mhz = mx6q_sd3_200mhz;
sd3_pads_100mhz = mx6q_sd3_100mhz;
sd3_pads_50mhz = mx6q_sd3_50mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
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;
switch (index) {
case 2:
if (cpu_is_mx6q()) {
sd_pads_200mhz = mx6q_sd3_200mhz;
sd_pads_100mhz = mx6q_sd3_100mhz;
sd_pads_50mhz = mx6q_sd3_50mhz;
u32 sd4_pads_200mhz_cnt;
u32 sd4_pads_100mhz_cnt;
u32 sd4_pads_50mhz_cnt;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
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()) {
sd4_pads_200mhz = mx6q_sd4_200mhz;
sd4_pads_100mhz = mx6q_sd4_100mhz;
sd4_pads_50mhz = mx6q_sd4_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd3_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);
sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd4_100mhz);
sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd4_50mhz);
} else if (cpu_is_mx6dl()) {
sd4_pads_200mhz = mx6dl_sd4_200mhz;
sd4_pads_100mhz = mx6dl_sd4_100mhz;
sd4_pads_50mhz = mx6dl_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);
} else if (cpu_is_mx6dl()) {
sd_pads_200mhz = mx6dl_sd4_200mhz;
sd_pads_100mhz = mx6dl_sd4_100mhz;
sd_pads_50mhz = mx6dl_sd4_50mhz;
sd4_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz);
sd4_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz);
sd4_pads_50mhz_cnt = ARRAY_SIZE(mx6dl_sd4_50mhz);
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd4_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd4_100mhz);
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 (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(sd4_pads_200mhz,
sd4_pads_200mhz_cnt);
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(sd4_pads_100mhz,
sd4_pads_100mhz_cnt);
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(sd4_pads_50mhz,
sd4_pads_50mhz_cnt);
return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd_pads_50mhz_cnt);
}
}
......@@ -291,7 +264,7 @@ static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
.support_8bit = 1,
.keep_power_at_suspend = 1,
.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*/
......@@ -299,7 +272,7 @@ static const struct esdhc_platform_data mx6_arm2_sd4_data __initconst = {
.always_present = 1,
.support_8bit = 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)
......
......@@ -208,57 +208,63 @@ static void __init imx6q_add_android_device_buttons(void)
static void __init imx6q_add_android_device_buttons(void) {}
#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;
iomux_v3_cfg_t *sd3_pads_200mhz = NULL;
iomux_v3_cfg_t *sd3_pads_100mhz = NULL;
iomux_v3_cfg_t *sd3_pads_50mhz = NULL;
iomux_v3_cfg_t *sd_pads_200mhz;
iomux_v3_cfg_t *sd_pads_100mhz;
iomux_v3_cfg_t *sd_pads_50mhz;
u32 sd3_pads_200mhz_cnt;
u32 sd3_pads_100mhz_cnt;
u32 sd3_pads_50mhz_cnt;
u32 sd_pads_200mhz_cnt;
u32 sd_pads_100mhz_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()) {
sd3_pads_200mhz = mx6q_sd3_200mhz;
sd3_pads_100mhz = mx6q_sd3_100mhz;
sd3_pads_50mhz = mx6q_sd3_50mhz;
sd_pads_200mhz = mx6q_sd3_200mhz;
sd_pads_100mhz = mx6q_sd3_100mhz;
sd_pads_50mhz = mx6q_sd3_50mhz;
sd3_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
sd3_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
sd3_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
sd_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;
sd_pads_200mhz = mx6dl_sd3_200mhz;
sd_pads_100mhz = mx6dl_sd3_100mhz;
sd_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);
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6dl_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6dl_sd3_100mhz);
sd_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);
BUG_ON(!sd_pads_200mhz);
pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_200mhz,
sd3_pads_200mhz_cnt);
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(!sd3_pads_100mhz);
BUG_ON(!sd_pads_100mhz);
pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_100mhz,
sd3_pads_100mhz_cnt);
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(!sd3_pads_50mhz);
BUG_ON(!sd_pads_50mhz);
pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(sd3_pads_50mhz,
sd3_pads_50mhz_cnt);
return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd_pads_50mhz_cnt);
}
}
......@@ -269,7 +275,7 @@ static const struct esdhc_platform_data mx6q_sabreauto_sd3_data __initconst = {
.support_18v = 1,
.support_8bit = 1,
.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 = {
......
......@@ -349,59 +349,64 @@ enum sd_pad_mode {
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;
if (clock > 100000000) {
if (pad_mode == SD_PAD_MODE_HIGH_SPEED)
return 0;
pad_mode = SD_PAD_MODE_HIGH_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_200mhz,
ARRAY_SIZE(mx6q_sd3_200mhz));
} else if (clock > 52000000) {
if (pad_mode == SD_PAD_MODE_MED_SPEED)
return 0;
pad_mode = SD_PAD_MODE_MED_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_100mhz,
ARRAY_SIZE(mx6q_sd3_100mhz));
} else {
if (pad_mode == SD_PAD_MODE_LOW_SPEED)
return 0;
pad_mode = SD_PAD_MODE_LOW_SPEED;
return mxc_iomux_v3_setup_multiple_pads(mx6q_sd3_50mhz,
ARRAY_SIZE(mx6q_sd3_50mhz));
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 2:
sd_pads_200mhz = mx6q_sd3_200mhz;
sd_pads_100mhz = mx6q_sd3_100mhz;
sd_pads_50mhz = mx6q_sd3_50mhz;
sd_pads_200mhz_cnt = ARRAY_SIZE(mx6q_sd3_200mhz);
sd_pads_100mhz_cnt = ARRAY_SIZE(mx6q_sd3_100mhz);
sd_pads_50mhz_cnt = ARRAY_SIZE(mx6q_sd3_50mhz);
break;
case 3:
sd_pads_200mhz = mx6q_sd4_200mhz;
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 (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(mx6q_sd4_200mhz,
ARRAY_SIZE(mx6q_sd4_200mhz));
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(mx6q_sd4_100mhz,
ARRAY_SIZE(mx6q_sd4_100mhz));
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(mx6q_sd4_50mhz,
ARRAY_SIZE(mx6q_sd4_50mhz));
return mxc_iomux_v3_setup_multiple_pads(sd_pads_50mhz,
sd_pads_50mhz_cnt);
}
}
......@@ -409,14 +414,14 @@ static const struct esdhc_platform_data mx6q_sabrelite_sd3_data __initconst = {
.cd_gpio = MX6Q_SABRELITE_SD3_CD,
.wp_gpio = MX6Q_SABRELITE_SD3_WP,
.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 = {
.cd_gpio = MX6Q_SABRELITE_SD4_CD,
.wp_gpio = MX6Q_SABRELITE_SD4_WP,
.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
......
......@@ -133,12 +133,91 @@ static int max17135_regulator_init(struct max17135 *max17135);
struct clk *extern_audio_root;
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 = {
.cd_gpio = MX6_ARM2_SD1_CD,
.wp_gpio = MX6_ARM2_SD1_WP,
.support_8bit = 1,
.support_18v = 1,
.keep_power_at_suspend = 1,
.delay_line = 0,
.platform_pad_change = plt_sd_pad_change,
};
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,
.keep_power_at_suspend = 1,
.delay_line = 0,
.support_18v = 1,
.platform_pad_change = plt_sd_pad_change,
};
static const struct esdhc_platform_data mx6_arm2_sd3_data __initconst = {
.cd_gpio = MX6_ARM2_SD3_CD,
.wp_gpio = -1,
.keep_power_at_suspend = 1,
.delay_line = 0,
.support_18v = 1,
.platform_pad_change = plt_sd_pad_change,
};
#define mV_to_uV(mV) (mV * 1000)
......
......@@ -50,36 +50,36 @@ static iomux_v3_cfg_t mx6sl_arm2_pads[] = {
MX6SL_PAD_HSIC_DAT__USB_H_DATA,
/* SD1 */
MX6SL_PAD_SD1_CLK__USDHC1_CLK,
MX6SL_PAD_SD1_CMD__USDHC1_CMD,
MX6SL_PAD_SD1_DAT0__USDHC1_DAT0,
MX6SL_PAD_SD1_DAT1__USDHC1_DAT1,
MX6SL_PAD_SD1_DAT2__USDHC1_DAT2,
MX6SL_PAD_SD1_DAT3__USDHC1_DAT3,
MX6SL_PAD_SD1_DAT4__USDHC1_DAT4,
MX6SL_PAD_SD1_DAT5__USDHC1_DAT5,
MX6SL_PAD_SD1_DAT6__USDHC1_DAT6,
MX6SL_PAD_SD1_DAT7__USDHC1_DAT7,
MX6SL_PAD_SD1_CLK__USDHC1_CLK_50MHZ,
MX6SL_PAD_SD1_CMD__USDHC1_CMD_50MHZ,
MX6SL_PAD_SD1_DAT0__USDHC1_DAT0_50MHZ,
MX6SL_PAD_SD1_DAT1__USDHC1_DAT1_50MHZ,
MX6SL_PAD_SD1_DAT2__USDHC1_DAT2_50MHZ,
MX6SL_PAD_SD1_DAT3__USDHC1_DAT3_50MHZ,
MX6SL_PAD_SD1_DAT4__USDHC1_DAT4_50MHZ,
MX6SL_PAD_SD1_DAT5__USDHC1_DAT5_50MHZ,
MX6SL_PAD_SD1_DAT6__USDHC1_DAT6_50MHZ,
MX6SL_PAD_SD1_DAT7__USDHC1_DAT7_50MHZ,
/* SD1 CD & WP */
MX6SL_PAD_KEY_ROW7__GPIO_4_7,
MX6SL_PAD_KEY_COL7__GPIO_4_6,
/* SD2 */
MX6SL_PAD_SD2_CLK__USDHC2_CLK,
MX6SL_PAD_SD2_CMD__USDHC2_CMD,
MX6SL_PAD_SD2_DAT0__USDHC2_DAT0,
MX6SL_PAD_SD2_DAT1__USDHC2_DAT1,
MX6SL_PAD_SD2_DAT2__USDHC2_DAT2,
MX6SL_PAD_SD2_DAT3__USDHC2_DAT3,
MX6SL_PAD_SD2_CLK__USDHC2_CLK_50MHZ,
MX6SL_PAD_SD2_CMD__USDHC2_CMD_50MHZ,
MX6SL_PAD_SD2_DAT0__USDHC2_DAT0_50MHZ,
MX6SL_PAD_SD2_DAT1__USDHC2_DAT1_50MHZ,
MX6SL_PAD_SD2_DAT2__USDHC2_DAT2_50MHZ,
MX6SL_PAD_SD2_DAT3__USDHC2_DAT3_50MHZ,
/* SD2 CD & WP */
MX6SL_PAD_SD2_DAT7__GPIO_5_0,
MX6SL_PAD_SD2_DAT6__GPIO_4_29,
/* SD3 */
MX6SL_PAD_SD3_CLK__USDHC3_CLK,
MX6SL_PAD_SD3_CMD__USDHC3_CMD,
MX6SL_PAD_SD3_DAT0__USDHC3_DAT0,
MX6SL_PAD_SD3_DAT1__USDHC3_DAT1,
MX6SL_PAD_SD3_DAT2__USDHC3_DAT2,
MX6SL_PAD_SD3_DAT3__USDHC3_DAT3,
MX6SL_PAD_SD3_CLK__USDHC3_CLK_50MHZ,
MX6SL_PAD_SD3_CMD__USDHC3_CMD_50MHZ,
MX6SL_PAD_SD3_DAT0__USDHC3_DAT0_50MHZ,
MX6SL_PAD_SD3_DAT1__USDHC3_DAT1_50MHZ,
MX6SL_PAD_SD3_DAT2__USDHC3_DAT2_50MHZ,
MX6SL_PAD_SD3_DAT3__USDHC3_DAT3_50MHZ,
/* SD3 CD */
MX6SL_PAD_REF_CLK_32K__GPIO_3_22,
......@@ -318,4 +318,38 @@ static iomux_v3_cfg_t mx6sl_arm2_elan_pads[] = {
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
......@@ -35,6 +35,6 @@ struct esdhc_platform_data {
unsigned int support_8bit;
unsigned int keep_power_at_suspend;
unsigned int delay_line;
int (*platform_pad_change)(int clock);
int (*platform_pad_change)(unsigned int index, int clock);
};
#endif /* __ASM_ARCH_IMX_ESDHC_H */
......@@ -13,6 +13,7 @@
#ifndef _DRIVERS_MMC_SDHCI_ESDHC_H
#define _DRIVERS_MMC_SDHCI_ESDHC_H
#include <linux/platform_device.h>
/*
* Ops and quirks for the Freescale eSDHC controller.
......@@ -52,6 +53,7 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
u32 temp;
struct esdhc_platform_data *boarddata;
int ddr_mode = 0;
struct platform_device *pdev = to_platform_device(host->mmc->parent);
boarddata = host->mmc->parent->platform_data;
if (cpu_is_mx6q() || cpu_is_mx6dl()) {
......@@ -94,8 +96,10 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
* board needs to reconfig its pad for
* corresponding sd bus frequency
*/
if (boarddata->platform_pad_change)
boarddata->platform_pad_change(clock);
if (boarddata->platform_pad_change) {
BUG_ON(!pdev);
boarddata->platform_pad_change(pdev->id, clock);
}
out:
host->clock = clock;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment