From 01f4ee9ab134a100c733eafdb84ffa233634b26a Mon Sep 17 00:00:00 2001 From: "Ye.Li" Date: Mon, 27 Jan 2014 13:44:56 +0800 Subject: ENGR00293946 ARM:imx6 Add dynamical USDHC/ESDHC pads settings Add a interface "board_mmc_io_switch" for ESDHC/USDHC to switch its pads settings. The BSP which supports this feature must implement this function. Add it for all imx6 series boards. Signed-off-by: Ye.Li (cherry picked from commit 58e999dae8ac0156804ff77c10a7c5ca27d43b50) --- board/freescale/mx6q_arm2/mx6q_arm2.c | 66 ++++++++++++++++++++++- board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c | 65 +++++++++++++++++++++- board/freescale/mx6q_sabreauto/mx6q_sabreauto.c | 65 +++++++++++++++++++++- board/freescale/mx6q_sabrelite/mx6q_sabrelite.c | 57 +++++++++++++++++++- board/freescale/mx6q_sabresd/mx6q_sabresd.c | 65 +++++++++++++++++++++- board/freescale/mx6sl_arm2/mx6sl_arm2.c | 61 ++++++++++++++++++++- board/freescale/mx6sl_evk/mx6sl_evk.c | 61 ++++++++++++++++++++- drivers/mmc/imx_esdhc.c | 15 ++++++ 8 files changed, 448 insertions(+), 7 deletions(-) diff --git a/board/freescale/mx6q_arm2/mx6q_arm2.c b/board/freescale/mx6q_arm2/mx6q_arm2.c index d6d7257..f65572c 100644 --- a/board/freescale/mx6q_arm2/mx6q_arm2.c +++ b/board/freescale/mx6q_arm2/mx6q_arm2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -734,6 +734,19 @@ iomux_v3_cfg_t usdhc4_pads[] = { MX6DL_PAD_SD4_DAT7__USDHC4_DAT7, }; #endif + +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -770,6 +783,57 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + case 3: + count = sizeof(usdhc4_pads) / sizeof(usdhc4_pads[0]); + usdhc_switch_pad(usdhc4_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c b/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c index 6677ad4..f587d71 100644 --- a/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c +++ b/board/freescale/mx6q_hdmidongle/mx6q_hdmidongle.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2012-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -982,6 +982,18 @@ iomux_v3_cfg_t usdhc4_pads[] = { }; #endif +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -1022,6 +1034,57 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + case 3: + count = sizeof(usdhc4_pads) / sizeof(usdhc4_pads[0]); + usdhc_switch_pad(usdhc4_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c b/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c index 00ef2ed..91be2a2 100644 --- a/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c +++ b/board/freescale/mx6q_sabreauto/mx6q_sabreauto.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -814,6 +814,18 @@ iomux_v3_cfg_t usdhc4_pads[] = { }; #endif +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -850,6 +862,57 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + case 3: + count = sizeof(usdhc4_pads) / sizeof(usdhc4_pads[0]); + usdhc_switch_pad(usdhc4_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6q_sabrelite/mx6q_sabrelite.c b/board/freescale/mx6q_sabrelite/mx6q_sabrelite.c index 1b0679d..879934c 100644 --- a/board/freescale/mx6q_sabrelite/mx6q_sabrelite.c +++ b/board/freescale/mx6q_sabrelite/mx6q_sabrelite.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2011-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -354,6 +354,18 @@ iomux_v3_cfg_t mx6q_usdhc4_pads[] = { MX6Q_PAD_SD4_DAT3__USDHC4_DAT3, }; +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -387,6 +399,49 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(mx6q_usdhc3_pads) / sizeof(mx6q_usdhc3_pads[0]); + usdhc_switch_pad(mx6q_usdhc3_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(mx6q_usdhc4_pads) / sizeof(mx6q_usdhc4_pads[0]); + usdhc_switch_pad(mx6q_usdhc4_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6q_sabresd/mx6q_sabresd.c b/board/freescale/mx6q_sabresd/mx6q_sabresd.c index 6f866aa..b1daa07 100644 --- a/board/freescale/mx6q_sabresd/mx6q_sabresd.c +++ b/board/freescale/mx6q_sabresd/mx6q_sabresd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2012-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -1030,6 +1030,18 @@ iomux_v3_cfg_t usdhc4_pads[] = { }; #endif +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -1070,6 +1082,57 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + case 3: + count = sizeof(usdhc4_pads) / sizeof(usdhc4_pads[0]); + usdhc_switch_pad(usdhc4_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6sl_arm2/mx6sl_arm2.c b/board/freescale/mx6sl_arm2/mx6sl_arm2.c index 0e4027e..4bc9c14 100644 --- a/board/freescale/mx6sl_arm2/mx6sl_arm2.c +++ b/board/freescale/mx6sl_arm2/mx6sl_arm2.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -197,6 +197,18 @@ iomux_v3_cfg_t usdhc3_pads[] = { MX6SL_PAD_SD3_DAT3__USDHC3_DAT3, }; +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -229,6 +241,53 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/board/freescale/mx6sl_evk/mx6sl_evk.c b/board/freescale/mx6sl_evk/mx6sl_evk.c index 8af6b75..9d1d40a 100644 --- a/board/freescale/mx6sl_evk/mx6sl_evk.c +++ b/board/freescale/mx6sl_evk/mx6sl_evk.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Freescale Semiconductor, Inc. + * Copyright (C) 2010-2014 Freescale Semiconductor, Inc. * * See file CREDITS for list of people who contributed to this * project. @@ -191,6 +191,18 @@ iomux_v3_cfg_t usdhc3_pads[] = { MX6SL_PAD_SD3_DAT3__USDHC3_DAT3, }; +#define USDHC_PAD_CTRL_DEFAULT (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_LOW | \ + PAD_CTL_DSE_80ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_100MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_MED | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + +#define USDHC_PAD_CTRL_200MHZ (PAD_CTL_PKE | PAD_CTL_PUE | \ + PAD_CTL_PUS_47K_UP | PAD_CTL_SPEED_HIGH | \ + PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) + int usdhc_gpio_init(bd_t *bis) { s32 status = 0; @@ -222,6 +234,53 @@ int usdhc_gpio_init(bd_t *bis) return status; } +static void usdhc_switch_pad(iomux_v3_cfg_t *pad_list, unsigned count, + iomux_v3_cfg_t *new_pad_list, iomux_v3_cfg_t pad_val) +{ + u32 i; + + for (i = 0; i < count; i++) { + new_pad_list[i] = pad_list[i] & (~MUX_PAD_CTRL_MASK); + new_pad_list[i] |= MUX_PAD_CTRL(pad_val); + } +} + +int board_mmc_io_switch(u32 index, u32 clock) +{ + iomux_v3_cfg_t new_pads[14]; + u32 count; + iomux_v3_cfg_t pad_ctrl = USDHC_PAD_CTRL_DEFAULT; + + if (clock >= 200000000) + pad_ctrl = USDHC_PAD_CTRL_200MHZ; + else if (clock == 100000000) + pad_ctrl = USDHC_PAD_CTRL_100MHZ; + + switch (index) { + case 0: + count = sizeof(usdhc1_pads) / sizeof(usdhc1_pads[0]); + usdhc_switch_pad(usdhc1_pads, count, new_pads, pad_ctrl); + break; + case 1: + count = sizeof(usdhc2_pads) / sizeof(usdhc2_pads[0]); + usdhc_switch_pad(usdhc2_pads, count, new_pads, pad_ctrl); + break; + case 2: + count = sizeof(usdhc3_pads) / sizeof(usdhc3_pads[0]); + usdhc_switch_pad(usdhc3_pads, count, new_pads, pad_ctrl); + break; + default: + printf("Warning: you configured more USDHC controllers" + "(%d) then supported by the board (%d)\n", + index+1, CONFIG_SYS_FSL_USDHC_NUM); + return -1; + } + + mxc_iomux_v3_setup_multiple_pads(new_pads, count); + + return 0; +} + int board_mmc_init(bd_t *bis) { if (!usdhc_gpio_init(bis)) diff --git a/drivers/mmc/imx_esdhc.c b/drivers/mmc/imx_esdhc.c index fe1fb2f..a1c4d9b 100644 --- a/drivers/mmc/imx_esdhc.c +++ b/drivers/mmc/imx_esdhc.c @@ -537,12 +537,27 @@ static void esdhc_dll_setup(struct mmc *mmc) } } +/* + * CPU and board-specific Ethernet initializations. Aliased function + * signals caller to move on + */ +static int __def_mmc_io_switch(u32 index, u32 clock) +{ + return -1; +} + +int board_mmc_io_switch(u32 index, u32 clock) + __attribute__((weak, alias("__def_mmc_io_switch"))); + static void esdhc_set_ios(struct mmc *mmc) { struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; struct fsl_esdhc *regs = (struct fsl_esdhc *)cfg->esdhc_base; u32 tmp; + /* Set the io pad*/ + board_mmc_io_switch(mmc->block_dev.dev, mmc->clock); + /* Set the clock speed */ set_sysctl(mmc, mmc->clock); -- cgit v1.1