[U-Boot] [PATCHv5 00/14] mmc: exynos: code cleanup and support DDR mode

If card and host are supported DDR mode, then it can be used the DDR mode. This patch-set has dependency about beomho's patch-set. (Based-on u-boot-samsung repository)
It's result for loading image.
sdhci controller ->5260488 bytes read in 259 ms (19.4 MiB/s) dwmmc controller without DDR mode -> 5260488 bytes read in 202 ms (24.8 MiB/s) dwmmc controller with DDR mode -> 5260488 bytes read in 118 ms (42.5 MiB/s)
Download the 400M image with lthor. sdhci controller -> 59.4sec (Avg 6.95 MB/s) dwmmc controller without DDR mode -> 61.6sec (Avg 6.72MB/s) dwmmc controller with DDR mode -> 60.4sec (Avg 6.85MB/s)
Beomho Seo (3): arm: exynos: pinmux: add sdmmc4 gpio configratuion arm: exynos: clock: Remove exynos4x12_set_mmc_clk function board: trats2: Enable device tree on Trats2
Jaehoon Chung (11): ARM: exynos: board: change the mmc/sd init sequence ARM: exynos: clock: modify the set_mmc_clk for exynos4 ARM: dts: exynos: rename from EXYNOS5_DWMMC to EXYNOS_DWMMC mmc: exynos_dw_mmc: restore the property into host mmc: remove the unnecessary define and fix the wrong bit control mmc: support the DDR mode for eMMC mmc: dw_mmc: support the DDR mode ARM: dts: exnyos: enable dw-mmc controller mmc: exynos_dw_mmc: enable the DDR mode ARM: exynos4: enable the dwmmc configuration mmc: s5p_sdhci: add the s5p_sdhci_core_init function
arch/arm/cpu/armv7/exynos/clock.c | 45 ++----- arch/arm/cpu/armv7/exynos/pinmux.c | 35 ++++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/dts/exynos5.dtsi | 8 +- arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- doc/device-tree-bindings/exynos/dwmmc.txt | 8 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 205 +++++++++++++++++++---------- drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++--- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/fdtdec.h | 2 +- include/mmc.h | 25 ++-- lib/fdtdec.c | 2 +- 17 files changed, 275 insertions(+), 171 deletions(-)

From: Beomho Seo beomho.seo@samsung.com
For use dwmmc controller at exynos4, add SDMMC4 gpio configuration.
Signed-off-by: Beomho Seo beomho.seo@samsung.com Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Piotr Wilczek p.wilczek@samsung.com Cc: Lukasz Majewski l.majewski@samsung.com Cc: Piotr Wilczek p.wilczek@samsung.com Cc: Minkyu Kang mk7.kang@samsung.com --- arch/arm/cpu/armv7/exynos/pinmux.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index ee7c2e5..86a0c75 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -573,15 +573,26 @@ static void exynos4_i2c_config(int peripheral, int flags) static int exynos4_mmc_config(int peripheral, int flags) { int i, start = 0, start_ext = 0; + unsigned int func, ext_func;
switch (peripheral) { case PERIPH_ID_SDMMC0: start = EXYNOS4_GPIO_K00; start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); break; case PERIPH_ID_SDMMC2: start = EXYNOS4_GPIO_K20; start_ext = EXYNOS4_GPIO_K33; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC4: + start = EXYNOS4_GPIO_K00; + start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x3); + ext_func = S5P_GPIO_FUNC(0x4); break; default: return -1; @@ -589,13 +600,14 @@ static int exynos4_mmc_config(int peripheral, int flags) for (i = start; i < (start + 7); i++) { if (i == (start + 2)) continue; - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); + gpio_cfg_pin(i, func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } + /* SDMMC2 do not use 8bit mode at exynos4 */ if (flags & PINMUX_FLAG_8BIT_MODE) { for (i = start_ext; i < (start_ext + 4); i++) { - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x3)); + gpio_cfg_pin(i, ext_func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } @@ -676,15 +688,26 @@ static void exynos4x12_i2c_config(int peripheral, int flags) static int exynos4x12_mmc_config(int peripheral, int flags) { int i, start = 0, start_ext = 0; + unsigned int func, ext_func;
switch (peripheral) { case PERIPH_ID_SDMMC0: start = EXYNOS4X12_GPIO_K00; start_ext = EXYNOS4X12_GPIO_K13; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); break; case PERIPH_ID_SDMMC2: start = EXYNOS4X12_GPIO_K20; start_ext = EXYNOS4X12_GPIO_K33; + func = S5P_GPIO_FUNC(0x2); + ext_func = S5P_GPIO_FUNC(0x3); + break; + case PERIPH_ID_SDMMC4: + start = EXYNOS4_GPIO_K00; + start_ext = EXYNOS4_GPIO_K13; + func = S5P_GPIO_FUNC(0x3); + ext_func = S5P_GPIO_FUNC(0x4); break; default: return -1; @@ -692,13 +715,13 @@ static int exynos4x12_mmc_config(int peripheral, int flags) for (i = start; i < (start + 7); i++) { if (i == (start + 2)) continue; - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x2)); + gpio_cfg_pin(i, func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } if (flags & PINMUX_FLAG_8BIT_MODE) { for (i = start_ext; i < (start_ext + 4); i++) { - gpio_cfg_pin(i, S5P_GPIO_FUNC(0x3)); + gpio_cfg_pin(i, ext_func); gpio_set_pull(i, S5P_GPIO_PULL_NONE); gpio_set_drv(i, S5P_GPIO_DRV_4X); } @@ -759,10 +782,10 @@ static int exynos4_pinmux_config(int peripheral, int flags) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC4: return exynos4_mmc_config(peripheral, flags); case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC3: - case PERIPH_ID_SDMMC4: debug("SDMMC device %d not implemented\n", peripheral); return -1; default: @@ -794,10 +817,10 @@ static int exynos4x12_pinmux_config(int peripheral, int flags) break; case PERIPH_ID_SDMMC0: case PERIPH_ID_SDMMC2: + case PERIPH_ID_SDMMC4: return exynos4x12_mmc_config(peripheral, flags); case PERIPH_ID_SDMMC1: case PERIPH_ID_SDMMC3: - case PERIPH_ID_SDMMC4: debug("SDMMC device %d not implemented\n", peripheral); return -1; default:

From: Beomho Seo beomho.seo@samsung.com
exynos4x12_set_mmc_clk function have been removed. Because, exynos4x12_clock and exynos4_clock return same div_fsys* value.
Signed-off-by: Beomho Seo beomho.seo@samsung.com Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Piotr Wilczek p.wilczek@samsung.com Cc: Lukasz Majewski l.majewski@samsung.com Cc: Piotr Wilczek p.wilczek@samsung.com Cc: Minkyu Kang mk7.kang@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 1fea4d6..2c2029a 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -893,30 +893,6 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) (div & 0xff) << ((dev_index << 4) + 8)); }
-/* exynos4x12: set the mmc clock */ -static void exynos4x12_set_mmc_clk(int dev_index, unsigned int div) -{ - struct exynos4x12_clock *clk = - (struct exynos4x12_clock *)samsung_get_base_clock(); - unsigned int addr; - - /* - * CLK_DIV_FSYS1 - * MMC0_PRE_RATIO [15:8], MMC1_PRE_RATIO [31:24] - * CLK_DIV_FSYS2 - * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] - */ - if (dev_index < 2) { - addr = (unsigned int)&clk->div_fsys1; - } else { - addr = (unsigned int)&clk->div_fsys2; - dev_index -= 2; - } - - clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), - (div & 0xff) << ((dev_index << 4) + 8)); -} - /* exynos5: set the mmc clock */ static void exynos5_set_mmc_clk(int dev_index, unsigned int div) { @@ -1612,10 +1588,7 @@ void set_mmc_clk(int dev_index, unsigned int div) else exynos5_set_mmc_clk(dev_index, div); } else { - if (proid_is_exynos4412()) - exynos4x12_set_mmc_clk(dev_index, div); - else - exynos4_set_mmc_clk(dev_index, div); + exynos4_set_mmc_clk(dev_index, div); } }

From: Beomho Seo beomho.seo@samsung.com
This patch add dwmmc emmc controller node on exynos4 and exynos4412 device tree.
Signed-off-by: Beomho Seo beomho.seo@samsung.com Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Piotr Wilczek p.wilczek@samsung.com Cc: Lukasz Majewski l.majewski@samsung.com Cc: Piotr Wilczek p.wilczek@samsung.com Cc: Minkyu Kang mk7.kang@samsung.com --- arch/arm/dts/exynos4.dtsi | 8 ++++++++ arch/arm/dts/exynos4412-trats2.dts | 8 ++++++++ 2 files changed, 16 insertions(+)
diff --git a/arch/arm/dts/exynos4.dtsi b/arch/arm/dts/exynos4.dtsi index 71dc7eb..110eb43 100644 --- a/arch/arm/dts/exynos4.dtsi +++ b/arch/arm/dts/exynos4.dtsi @@ -128,6 +128,14 @@ interrupts = <0 78 0>; };
+ dwmmc@12550000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,exynos-dwmmc"; + reg = <0x12550000 0x1000>; + interrupts = <0 131 0>; + }; + gpio: gpio { gpio-controller; #gpio-cells = <2>; diff --git a/arch/arm/dts/exynos4412-trats2.dts b/arch/arm/dts/exynos4412-trats2.dts index 1596f83..5269ae6 100644 --- a/arch/arm/dts/exynos4412-trats2.dts +++ b/arch/arm/dts/exynos4412-trats2.dts @@ -31,6 +31,7 @@ console = "/serial@13820000"; mmc0 = "sdhci@12510000"; mmc2 = "sdhci@12530000"; + mmc4 = "dwmmc@12550000"; };
i2c@138d0000 { @@ -431,4 +432,11 @@ sdhci@12540000 { status = "disabled"; }; + + dwmmc@12550000 { + samsung,bus-width = <8>; + samsung,timing = <0 1 0>; + pwr-gpios = <&gpio 0xB2 0>; + index = <4>; + }; };

Exynos4 can be used the dwmmc controller for eMMC. Then it needs to check dwmmc_init() at first.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Reviewed-by: Lukasz Majewski l.majewski@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- board/samsung/common/board.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c index de154e0..9dc7c83 100644 --- a/board/samsung/common/board.c +++ b/board/samsung/common/board.c @@ -243,13 +243,6 @@ int board_eth_init(bd_t *bis) int board_mmc_init(bd_t *bis) { int ret; - -#ifdef CONFIG_SDHCI - /* mmc initializattion for available channels */ - ret = exynos_mmc_init(gd->fdt_blob); - if (ret) - debug("mmc init failed\n"); -#endif #ifdef CONFIG_DWMMC /* dwmmc initializattion for available channels */ ret = exynos_dwmmc_init(gd->fdt_blob); @@ -257,6 +250,12 @@ int board_mmc_init(bd_t *bis) debug("dwmmc init failed\n"); #endif
+#ifdef CONFIG_SDHCI + /* mmc initializattion for available channels */ + ret = exynos_mmc_init(gd->fdt_blob); + if (ret) + debug("mmc init failed\n"); +#endif return ret; } #endif

Modified the mmc_set_clock for eynos4. The goal of this patch is that fsys-div register should be reset. And retore the div-value, not using the value of lowlevel_init. (For using SDMMC4, this patch is needs)
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 16 +++++++++++----- arch/arm/include/asm/arch-exynos/clk.h | 5 +++++ 2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 2c2029a..400d134 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -869,7 +869,7 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) { struct exynos4_clock *clk = (struct exynos4_clock *)samsung_get_base_clock(); - unsigned int addr; + unsigned int addr, clear_bit, set_bit;
/* * CLK_DIV_FSYS1 @@ -877,20 +877,26 @@ static void exynos4_set_mmc_clk(int dev_index, unsigned int div) * CLK_DIV_FSYS2 * MMC2_PRE_RATIO [15:8], MMC3_PRE_RATIO [31:24] * CLK_DIV_FSYS3 - * MMC4_PRE_RATIO [15:8] + * MMC4_RATIO [3:0] */ if (dev_index < 2) { addr = (unsigned int)&clk->div_fsys1; - } else if (dev_index == 4) { + clear_bit = MASK_PRE_RATIO(dev_index); + set_bit = SET_PRE_RATIO(dev_index, div); + } else if (dev_index == 4) { addr = (unsigned int)&clk->div_fsys3; dev_index -= 4; + /* MMC4 is controlled with the MMC4_RATIO value */ + clear_bit = MASK_RATIO(dev_index); + set_bit = SET_RATIO(dev_index, div); } else { addr = (unsigned int)&clk->div_fsys2; dev_index -= 2; + clear_bit = MASK_PRE_RATIO(dev_index); + set_bit = SET_PRE_RATIO(dev_index, div); }
- clrsetbits_le32(addr, 0xff << ((dev_index << 4) + 8), - (div & 0xff) << ((dev_index << 4) + 8)); + clrsetbits_le32(addr, clear_bit, set_bit); }
/* exynos5: set the mmc clock */ diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h index cdeef32..ffbc07e 100644 --- a/arch/arm/include/asm/arch-exynos/clk.h +++ b/arch/arm/include/asm/arch-exynos/clk.h @@ -16,6 +16,11 @@ #define BPLL 5 #define RPLL 6
+#define MASK_PRE_RATIO(x) (0xff << ((x << 4) + 8)) +#define MASK_RATIO(x) (0xf << (x << 4)) +#define SET_PRE_RATIO(x, y) ((y & 0xff) << ((x << 4) + 8)) +#define SET_RATIO(x, y) ((y & 0xf) << (x << 4)) + enum pll_src_bit { EXYNOS_SRC_MPLL = 6, EXYNOS_SRC_EPLL,

Exynos serise can be supported the dw-mmc controller. So, it's good that used the general prefix as "_EXYNOS_DWMMC".
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com --- arch/arm/dts/exynos5.dtsi | 8 ++++---- doc/device-tree-bindings/exynos/dwmmc.txt | 8 ++++---- include/fdtdec.h | 2 +- lib/fdtdec.c | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/arch/arm/dts/exynos5.dtsi b/arch/arm/dts/exynos5.dtsi index f8c8741..a2b533a 100644 --- a/arch/arm/dts/exynos5.dtsi +++ b/arch/arm/dts/exynos5.dtsi @@ -136,7 +136,7 @@ mmc@12200000 { #address-cells = <1>; #size-cells = <0>; - compatible = "samsung,exynos5250-dwmmc"; + compatible = "samsung,exynos-dwmmc"; reg = <0x12200000 0x1000>; interrupts = <0 75 0>; }; @@ -144,7 +144,7 @@ mmc@12210000 { #address-cells = <1>; #size-cells = <0>; - compatible = "samsung,exynos5250-dwmmc"; + compatible = "samsung,exynos-dwmmc"; reg = <0x12210000 0x1000>; interrupts = <0 76 0>; }; @@ -152,7 +152,7 @@ mmc@12220000 { #address-cells = <1>; #size-cells = <0>; - compatible = "samsung,exynos5250-dwmmc"; + compatible = "samsung,exynos-dwmmc"; reg = <0x12220000 0x1000>; interrupts = <0 77 0>; }; @@ -160,7 +160,7 @@ mmc@12230000 { #address-cells = <1>; #size-cells = <0>; - compatible = "samsung,exynos5250-dwmmc"; + compatible = "samsung,exynos-dwmmc"; reg = <0x12230000 0x1000>; interrupts = <0 78 0>; }; diff --git a/doc/device-tree-bindings/exynos/dwmmc.txt b/doc/device-tree-bindings/exynos/dwmmc.txt index 566da3b..694d195 100644 --- a/doc/device-tree-bindings/exynos/dwmmc.txt +++ b/doc/device-tree-bindings/exynos/dwmmc.txt @@ -1,18 +1,18 @@ -* Exynos 5250 DWC_mobile_storage +* Exynos DWC_mobile_storage
-The Exynos 5250 provides DWC_mobile_storage interface which supports +The Exynos provides DWC_mobile_storage interface which supports . Embedded Multimedia Cards (EMMC-version 4.5) . Secure Digital memory (SD mem-version 2.0) . Secure Digital I/O (SDIO-version 3.0) . Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1)
-The Exynos 5250 DWC_mobile_storage provides four channels. +The Exynos DWC_mobile_storage provides four channels. SOC specific and Board specific properties are channel specific.
Required SoC Specific Properties:
- compatible: should be - - samsung,exynos5250-dwmmc: for exynos5250 platforms + - samsung,exynos-dwmmc: for exynos platforms
- reg: physical base address of the controller and length of memory mapped region. diff --git a/include/fdtdec.h b/include/fdtdec.h index 3196cf6..8c751fd 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -81,7 +81,7 @@ enum fdt_compat_id { COMPAT_SAMSUNG_EXYNOS_FIMD, /* Exynos Display controller */ COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */ COMPAT_SAMSUNG_EXYNOS5_DP, /* Exynos Display port controller */ - COMPAT_SAMSUNG_EXYNOS5_DWMMC, /* Exynos5 DWMMC controller */ + COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */ COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */ COMPAT_SAMSUNG_EXYNOS_SERIAL, /* Exynos UART */ COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 8ecb80f..35e91b4 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -55,7 +55,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"), COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"), COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"), - COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"), + COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"), COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"), COMPAT(SAMSUNG_EXYNOS_SERIAL, "samsung,exynos4210-uart"), COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),

Restore the platdata(property of dt) into host struct. Then data's information is maintained and reused anywhere.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/exynos_dw_mmc.c | 204 +++++++++++++++++++++++++++---------------- include/dwmmc.h | 2 + 2 files changed, 133 insertions(+), 73 deletions(-)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index de8cdcc..28941ad 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -13,6 +13,8 @@ #include <asm/arch/dwmmc.h> #include <asm/arch/clk.h> #include <asm/arch/pinmux.h> +#include <asm/gpio.h> +#include <asm-generic/errno.h>
#define DWMMC_MAX_CH_NUM 4 #define DWMMC_MAX_FREQ 52000000 @@ -44,7 +46,11 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) & DWMCI_DIVRATIO_MASK) + 1; sclk = get_mmc_clk(host->dev_index);
- return sclk / clk_div; + /* + * Assume to know divider value. + * When clock unit is broken, need to set "host->div" + */ + return sclk / clk_div / (host->div + 1); }
static void exynos_dwmci_board_init(struct dwmci_host *host) @@ -60,45 +66,32 @@ static void exynos_dwmci_board_init(struct dwmci_host *host) } }
-/* - * This function adds the mmc channel to be registered with mmc core. - * index - mmc channel number. - * regbase - register base address of mmc channel specified in 'index'. - * bus_width - operating bus width of mmc channel specified in 'index'. - * clksel - value to be written into CLKSEL register in case of FDT. - * NULL in case od non-FDT. - */ -int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) +static int exynos_dwmci_core_init(struct dwmci_host *host, int index) { - struct dwmci_host *host = NULL; unsigned int div; unsigned long freq, sclk; - host = malloc(sizeof(struct dwmci_host)); - if (!host) { - printf("dwmci_host malloc fail!\n"); - return 1; - } + + if (host->bus_hz) + freq = host->bus_hz; + else + freq = DWMMC_MAX_FREQ; + /* request mmc clock vlaue of 52MHz. */ - freq = 52000000; sclk = get_mmc_clk(index); div = DIV_ROUND_UP(sclk, freq); /* set the clock divisor for mmc */ set_mmc_clk(index, div);
host->name = "EXYNOS DWMMC"; - host->ioaddr = (void *)regbase; - host->buswidth = bus_width; #ifdef CONFIG_EXYNOS5420 host->quirks = DWMCI_QUIRK_DISABLE_SMU; #endif host->board_init = exynos_dwmci_board_init;
- if (clksel) { - host->clksel_val = clksel; - } else { - if (0 == index) + if (!host->clksel_val) { + if (index == 0) host->clksel_val = DWMMC_MMC0_CLKSEL_VAL; - if (2 == index) + else if (index == 2) host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; }
@@ -113,69 +106,134 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) return 0; }
+/* + * This function adds the mmc channel to be registered with mmc core. + * index - mmc channel number. + * regbase - register base address of mmc channel specified in 'index'. + * bus_width - operating bus width of mmc channel specified in 'index'. + * clksel - value to be written into CLKSEL register in case of FDT. + * NULL in case od non-FDT. + */ +int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) +{ + struct dwmci_host *host = NULL; + + host = malloc(sizeof(struct dwmci_host)); + if (!host) { + error("dwmci_host malloc fail!\n"); + return -ENOMEM; + } + + host->ioaddr = (void *)regbase; + host->buswidth = bus_width; + + if (clksel) + host->clksel_val = clksel; + + return exynos_dwmci_core_init(host, index); +} + #ifdef CONFIG_OF_CONTROL -int exynos_dwmmc_init(const void *blob) +static struct dwmci_host dwmci_host[DWMMC_MAX_CH_NUM]; + +static int do_dwmci_init(struct dwmci_host *host) { - int index, bus_width; - int node_list[DWMMC_MAX_CH_NUM]; - int err = 0, dev_id, flag, count, i; - u32 clksel_val, base, timing[3]; + int index, flag, err;
- count = fdtdec_find_aliases_for_id(blob, "mmc", - COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list, - DWMMC_MAX_CH_NUM); + index = host->dev_index;
- for (i = 0; i < count; i++) { - int node = node_list[i]; + flag = host->buswidth == 8 ? PINMUX_FLAG_8BIT_MODE : PINMUX_FLAG_NONE; + err = exynos_pinmux_config(host->dev_id, flag); + if (err) { + debug("DWMMC not configure\n"); + return err; + }
- if (node <= 0) - continue; + return exynos_dwmci_core_init(host, index); +}
- /* Extract device id for each mmc channel */ - dev_id = pinmux_decode_periph_id(blob, node); +static int exynos_dwmci_get_config(const void *blob, int node, + struct dwmci_host *host) +{ + int err = 0; + u32 base, clksel_val, timing[3];
- /* Get the bus width from the device node */ - bus_width = fdtdec_get_int(blob, node, "samsung,bus-width", 0); - if (bus_width <= 0) { - debug("DWMMC: Can't get bus-width\n"); - return -1; - } - if (8 == bus_width) - flag = PINMUX_FLAG_8BIT_MODE; - else - flag = PINMUX_FLAG_NONE; + /* Extract device id for each mmc channel */ + host->dev_id = pinmux_decode_periph_id(blob, node);
- /* config pinmux for each mmc channel */ - err = exynos_pinmux_config(dev_id, flag); - if (err) { - debug("DWMMC not configured\n"); - return err; - } + /* Get the bus width from the device node */ + host->buswidth = fdtdec_get_int(blob, node, "samsung,bus-width", 0); + if (host->buswidth <= 0) { + debug("DWMMC: Can't get bus-width\n"); + return -EINVAL; + }
- index = dev_id - PERIPH_ID_SDMMC0; + host->dev_index = fdtdec_get_int(blob, node, "index", host->dev_id); + if (host->dev_index == host->dev_id) + host->dev_index = host->dev_id - PERIPH_ID_SDMMC0;
- /* Get the base address from the device node */ - base = fdtdec_get_addr(blob, node, "reg"); - if (!base) { - debug("DWMMC: Can't get base address\n"); - return -1; - } - /* Extract the timing info from the node */ - err = fdtdec_get_int_array(blob, node, "samsung,timing", - timing, 3); + /* Set the base address from the device node */ + base = fdtdec_get_addr(blob, node, "reg"); + if (!base) { + debug("DWMMC: Can't get base address\n"); + return -EINVAL; + } + host->ioaddr = (void *)base; + + /* Extract the timing info from the node */ + err = fdtdec_get_int_array(blob, node, "samsung,timing", timing, 3); + if (err) { + debug("Can't get sdr-timings for devider\n"); + return -EINVAL; + } + + clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | + DWMCI_SET_DRV_CLK(timing[1]) | + DWMCI_SET_DIV_RATIO(timing[2])); + if (clksel_val) + host->clksel_val = clksel_val; + + host->fifoth_val = fdtdec_get_int(blob, node, "fifoth_val", 0); + host->bus_hz = fdtdec_get_int(blob, node, "bus_hz", 0); + host->div = fdtdec_get_int(blob, node, "div", 0); + + return 0; +} + +static int exynos_dwmci_process_node(const void *blob, + int node_list[], int count) +{ + struct dwmci_host *host; + int i, node, err; + + for (i = 0; i < count; i++) { + node = node_list[i]; + if (node <= 0) + continue; + host = &dwmci_host[i]; + err = exynos_dwmci_get_config(blob, node, host); if (err) { - debug("Can't get sdr-timings for divider\n"); - return -1; + debug("%s: failed to decode dev %d\n", __func__, i); + return err; }
- clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | - DWMCI_SET_DRV_CLK(timing[1]) | - DWMCI_SET_DIV_RATIO(timing[2])); - /* Initialise each mmc channel */ - err = exynos_dwmci_add_port(index, base, bus_width, clksel_val); - if (err) - debug("dwmmc Channel-%d init failed\n", index); + do_dwmci_init(host); } return 0; } + +int exynos_dwmmc_init(const void *blob) +{ + int compat_id; + int node_list[DWMMC_MAX_CH_NUM]; + int err = 0, count; + + compat_id = COMPAT_SAMSUNG_EXYNOS_DWMMC; + + count = fdtdec_find_aliases_for_id(blob, "mmc", + compat_id, node_list, DWMMC_MAX_CH_NUM); + err = exynos_dwmci_process_node(blob, node_list, count); + + return err; +} #endif diff --git a/include/dwmmc.h b/include/dwmmc.h index c9bdf51..14c7db8 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -134,7 +134,9 @@ struct dwmci_host { unsigned int version; unsigned int clock; unsigned int bus_hz; + unsigned int div; int dev_index; + int dev_id; int buswidth; u32 clksel_val; u32 fifoth_val;

Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Reviewed-by: Lukasz Majeski l.majewski@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/mmc.c | 2 +- include/mmc.h | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 16051e5..dd6a6ef 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -514,7 +514,7 @@ static int mmc_change_freq(struct mmc *mmc) return 0;
/* High Speed is set, there are two types: 52MHz and 26MHz */ - if (cardtype & MMC_HS_52MHZ) + if (cardtype & EXT_CSD_CARD_TYPE_52) mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; else mmc->card_caps |= MMC_MODE_HS; diff --git a/include/mmc.h b/include/mmc.h index bc11f45..d5a896f 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -32,15 +32,12 @@ #define MMC_VERSION_4_41 (MMC_VERSION_MMC | 0x429) #define MMC_VERSION_4_5 (MMC_VERSION_MMC | 0x405)
-#define MMC_MODE_HS 0x001 -#define MMC_MODE_HS_52MHz 0x010 -#define MMC_MODE_4BIT 0x100 -#define MMC_MODE_8BIT 0x200 -#define MMC_MODE_SPI 0x400 -#define MMC_MODE_HC 0x800 - -#define MMC_MODE_MASK_WIDTH_BITS (MMC_MODE_4BIT | MMC_MODE_8BIT) -#define MMC_MODE_WIDTH_BITS_SHIFT 8 +#define MMC_MODE_HS (1 << 0) +#define MMC_MODE_HS_52MHz (1 << 1) +#define MMC_MODE_4BIT (1 << 2) +#define MMC_MODE_8BIT (1 << 3) +#define MMC_MODE_SPI (1 << 4) +#define MMC_MODE_HC (1 << 5)
#define SD_DATA_4BIT 0x00040000
@@ -98,9 +95,6 @@ #define SD_HIGHSPEED_BUSY 0x00020000 #define SD_HIGHSPEED_SUPPORTED 0x00020000
-#define MMC_HS_TIMING 0x00000100 -#define MMC_HS_52MHZ 0x2 - #define OCR_BUSY 0x80000000 #define OCR_HCS 0x40000000 #define OCR_VOLTAGE_MASK 0x007FFF80

Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/mmc.c | 16 +++++++++++++--- include/mmc.h | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index dd6a6ef..08187d5 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -158,6 +158,9 @@ int mmc_set_blocklen(struct mmc *mmc, int len) { struct mmc_cmd cmd;
+ if (mmc->card_caps & MMC_MODE_DDR_52MHz) + return 0; + cmd.cmdidx = MMC_CMD_SET_BLOCKLEN; cmd.resp_type = MMC_RSP_R1; cmd.cmdarg = len; @@ -514,10 +517,13 @@ static int mmc_change_freq(struct mmc *mmc) return 0;
/* High Speed is set, there are two types: 52MHz and 26MHz */ - if (cardtype & EXT_CSD_CARD_TYPE_52) + if (cardtype & EXT_CSD_CARD_TYPE_52) { + if (cardtype & EXT_CSD_CARD_TYPE_DDR_52) + mmc->card_caps |= MMC_MODE_DDR_52MHz; mmc->card_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS; - else + } else { mmc->card_caps |= MMC_MODE_HS; + }
return 0; } @@ -1054,6 +1060,8 @@ static int mmc_startup(struct mmc *mmc)
/* An array of possible bus widths in order of preference */ static unsigned ext_csd_bits[] = { + EXT_CSD_DDR_BUS_WIDTH_8, + EXT_CSD_DDR_BUS_WIDTH_4, EXT_CSD_BUS_WIDTH_8, EXT_CSD_BUS_WIDTH_4, EXT_CSD_BUS_WIDTH_1, @@ -1061,13 +1069,15 @@ static int mmc_startup(struct mmc *mmc)
/* An array to map CSD bus widths to host cap bits */ static unsigned ext_to_hostcaps[] = { + [EXT_CSD_DDR_BUS_WIDTH_4] = MMC_MODE_DDR_52MHz, + [EXT_CSD_DDR_BUS_WIDTH_8] = MMC_MODE_DDR_52MHz, [EXT_CSD_BUS_WIDTH_4] = MMC_MODE_4BIT, [EXT_CSD_BUS_WIDTH_8] = MMC_MODE_8BIT, };
/* An array to map chosen bus width to an integer */ static unsigned widths[] = { - 8, 4, 1, + 8, 4, 8, 4, 1, };
for (idx=0; idx < ARRAY_SIZE(ext_csd_bits); idx++) { diff --git a/include/mmc.h b/include/mmc.h index d5a896f..aa2d1ca 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -38,6 +38,7 @@ #define MMC_MODE_8BIT (1 << 3) #define MMC_MODE_SPI (1 << 4) #define MMC_MODE_HC (1 << 5) +#define MMC_MODE_DDR_52MHz (1 << 6)
#define SD_DATA_4BIT 0x00040000
@@ -169,10 +170,16 @@
#define EXT_CSD_CARD_TYPE_26 (1 << 0) /* Card can run at 26MHz */ #define EXT_CSD_CARD_TYPE_52 (1 << 1) /* Card can run at 52MHz */ +#define EXT_CSD_CARD_TYPE_DDR_1_8V (1 << 2) +#define EXT_CSD_CARD_TYPE_DDR_1_2V (1 << 3) +#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \ + | EXT_CSD_CARD_TYPE_DDR_1_2V)
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */ #define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */ #define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */ +#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */ +#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
#define EXT_CSD_BOOT_ACK_ENABLE (1 << 6) #define EXT_CSD_BOOT_PARTITION_ENABLE (1 << 3)

Hi,
On 05/16/2014 06:59 AM, Jaehoon Chung wrote:
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com
What platforms did you test DDR mode on? I tried this on an Freescale i.MX6 based platform but the driver returned error code COM_ERR (-18) when trying to switch to any of the DDR modes. I guess the fsl_esdhc.c driver needs some adaptation for DDR to work.
Best regards, -- Hector Palacios

Hi, Hector.
On 05/21/2014 01:37 AM, Hector Palacios wrote:
Hi,
On 05/16/2014 06:59 AM, Jaehoon Chung wrote:
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com
What platforms did you test DDR mode on?
I have tested DDR mode with exynos board.
I tried this on an Freescale i.MX6 based platform but the driver returned error code COM_ERR (-18) when trying to switch to any of the DDR modes. I guess the fsl_esdhc.c driver needs some adaptation for DDR to work.
I didn't know how work DDR mode at fsl_esdhc.c.(If you share the host controller TRM, it's helpful to me.) Host controller also need to change the DDR mode.
I wonder your board didn't work not to enable the DDR mode?
Best Regards, Jaehoon Chung
Best regards,
Hector Palacios

On 05/21/2014 04:20 AM, Jaehoon Chung wrote:
Hi, Hector.
On 05/21/2014 01:37 AM, Hector Palacios wrote:
Hi,
On 05/16/2014 06:59 AM, Jaehoon Chung wrote:
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com
What platforms did you test DDR mode on?
I have tested DDR mode with exynos board.
I tried this on an Freescale i.MX6 based platform but the driver returned error code COM_ERR (-18) when trying to switch to any of the DDR modes. I guess the fsl_esdhc.c driver needs some adaptation for DDR to work.
I didn't know how work DDR mode at fsl_esdhc.c.(If you share the host controller TRM, it's helpful to me.) Host controller also need to change the DDR mode.
I wonder your board didn't work not to enable the DDR mode?
Thank you, yes the fsl_esdhc.c driver does not yet support enabling of DDR mode. I think it should be easy to implement, I believe it is just a question of changing the clock frequency.
Best regards, -- Hector Palacios

On 05/21/2014 08:52 PM, Hector Palacios wrote:
On 05/21/2014 04:20 AM, Jaehoon Chung wrote:
Hi, Hector.
On 05/21/2014 01:37 AM, Hector Palacios wrote:
Hi,
On 05/16/2014 06:59 AM, Jaehoon Chung wrote:
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com
What platforms did you test DDR mode on?
I have tested DDR mode with exynos board.
I tried this on an Freescale i.MX6 based platform but the driver returned error code COM_ERR (-18) when trying to switch to any of the DDR modes. I guess the fsl_esdhc.c driver needs some adaptation for DDR to work.
I didn't know how work DDR mode at fsl_esdhc.c.(If you share the host controller TRM, it's helpful to me.) Host controller also need to change the DDR mode.
I wonder your board didn't work not to enable the DDR mode?
Thank you, yes the fsl_esdhc.c driver does not yet support enabling of DDR mode. I think it should be easy to implement, I believe it is just a question of changing the clock frequency.
I need to change the clock frequency, too. I guess that if controller support the DDR mode, there is a register relevant to DDR mode.
Best Regards, Jaehoon Chung
Best regards,
Hector Palacios

Support the DDR mode at dw-mmc controller
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/dw_mmc.c | 12 ++++++++++-- include/dwmmc.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index eb4e2be..5bf36a0 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -284,8 +284,8 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
static void dwmci_set_ios(struct mmc *mmc) { - struct dwmci_host *host = mmc->priv; - u32 ctype; + struct dwmci_host *host = (struct dwmci_host *)mmc->priv; + u32 ctype, regs;
debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
@@ -304,6 +304,14 @@ static void dwmci_set_ios(struct mmc *mmc)
dwmci_writel(host, DWMCI_CTYPE, ctype);
+ regs = dwmci_readl(host, DWMCI_UHS_REG); + if (mmc->card_caps & MMC_MODE_DDR_52MHz) + regs |= DWMCI_DDR_MODE; + else + regs &= DWMCI_DDR_MODE; + + dwmci_writel(host, DWMCI_UHS_REG, regs); + if (host->clksel) host->clksel(host); } diff --git a/include/dwmmc.h b/include/dwmmc.h index 14c7db8..b67f11b 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -123,6 +123,9 @@ #define DWMCI_BMOD_IDMAC_FB (1 << 1) #define DWMCI_BMOD_IDMAC_EN (1 << 7)
+/* UHS register */ +#define DWMCI_DDR_MODE (1 << 16) + /* quirks */ #define DWMCI_QUIRK_DISABLE_SMU (1 << 0)

Enabled the dw-mmc controller.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- arch/arm/dts/exynos4412-trats2.dts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/arch/arm/dts/exynos4412-trats2.dts b/arch/arm/dts/exynos4412-trats2.dts index 5269ae6..cc58c87 100644 --- a/arch/arm/dts/exynos4412-trats2.dts +++ b/arch/arm/dts/exynos4412-trats2.dts @@ -417,6 +417,7 @@ samsung,bus-width = <8>; samsung,timing = <1 3 3>; pwr-gpios = <&gpio 0xB2 0>; + status = "disabled"; };
sdhci@12520000 { @@ -435,8 +436,11 @@
dwmmc@12550000 { samsung,bus-width = <8>; - samsung,timing = <0 1 0>; + samsung,timing = <2 1 0>; pwr-gpios = <&gpio 0xB2 0>; + fifoth_val = <0x203f0040>; + bus_hz = <400000000>; + div = <0x3>; index = <4>; }; };

Set the ddr mode capability by default.
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/exynos_dw_mmc.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 28941ad..d96dfe1 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -95,6 +95,7 @@ static int exynos_dwmci_core_init(struct dwmci_host *host, int index) host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; }
+ host->caps = MMC_MODE_DDR_52MHz; host->clksel = exynos_dwmci_clksel; host->dev_index = index; host->get_mmc_clk = exynos_dwmci_get_clk;

Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- include/configs/exynos4-dt.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/exynos4-dt.h b/include/configs/exynos4-dt.h index cbd2d20..0c560ae 100644 --- a/include/configs/exynos4-dt.h +++ b/include/configs/exynos4-dt.h @@ -44,6 +44,9 @@ #define CONFIG_S5P_SDHCI #define CONFIG_SDHCI #define CONFIG_MMC_SDMA +#define CONFIG_DWMMC +#define CONFIG_EXYNOS_DWMMC +#define CONFIG_BOUNCE_BUFFER #define CONFIG_MMC_DEFAULT_DEV 0
/* PWM */

To reuse the code, added the s5p_sdhci_core_init function. Before applied this patch, didn't use the 8-bit mode at exynos baord. Because it didn't set "MMC_MODE_8BIT".
Signed-off-by: Jaehoon Chung jh80.chung@samsung.com Tested-by: Lukasz Majewski l.majewski@samsung.com Acked-by: Lukasz Majewski l.majewski@samsung.com --- drivers/mmc/s5p_sdhci.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-)
diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index ccae4cc..2ff0ec2 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -65,17 +65,9 @@ static void s5p_sdhci_set_control_reg(struct sdhci_host *host) sdhci_writel(host, ctrl, SDHCI_CONTROL2); }
-int s5p_sdhci_init(u32 regbase, int index, int bus_width) +static int s5p_sdhci_core_init(struct sdhci_host *host) { - struct sdhci_host *host = NULL; - host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); - if (!host) { - printf("sdhci__host malloc fail!\n"); - return 1; - } - host->name = S5P_NAME; - host->ioaddr = (void *)regbase;
host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR | @@ -85,15 +77,28 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width)
host->set_control_reg = &s5p_sdhci_set_control_reg; host->set_clock = set_mmc_clk; - host->index = index;
host->host_caps = MMC_MODE_HC; - if (bus_width == 8) + if (host->bus_width == 8) host->host_caps |= MMC_MODE_8BIT;
return add_sdhci(host, 52000000, 400000); }
+int s5p_sdhci_init(u32 regbase, int index, int bus_width) +{ + struct sdhci_host *host = malloc(sizeof(struct sdhci_host)); + if (!host) { + printf("sdhci__host malloc fail!\n"); + return 1; + } + host->ioaddr = (void *)regbase; + host->index = index; + host->bus_width = bus_width; + + return s5p_sdhci_core_init(host); +} + #ifdef CONFIG_OF_CONTROL struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS];
@@ -126,20 +131,7 @@ static int do_sdhci_init(struct sdhci_host *host) } }
- host->name = S5P_NAME; - - host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | - SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR | - SDHCI_QUIRK_WAIT_SEND_CMD; - host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; - host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - - host->set_control_reg = &s5p_sdhci_set_control_reg; - host->set_clock = set_mmc_clk; - - host->host_caps = MMC_MODE_HC; - - return add_sdhci(host, 52000000, 400000); + return s5p_sdhci_core_init(host); }
static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host)

On 16/05/14 13:59, Jaehoon Chung wrote:
If card and host are supported DDR mode, then it can be used the DDR mode. This patch-set has dependency about beomho's patch-set. (Based-on u-boot-samsung repository)
It's result for loading image.
sdhci controller ->5260488 bytes read in 259 ms (19.4 MiB/s) dwmmc controller without DDR mode -> 5260488 bytes read in 202 ms (24.8 MiB/s) dwmmc controller with DDR mode -> 5260488 bytes read in 118 ms (42.5 MiB/s)
Download the 400M image with lthor. sdhci controller -> 59.4sec (Avg 6.95 MB/s) dwmmc controller without DDR mode -> 61.6sec (Avg 6.72MB/s) dwmmc controller with DDR mode -> 60.4sec (Avg 6.85MB/s)
Beomho Seo (3): arm: exynos: pinmux: add sdmmc4 gpio configratuion arm: exynos: clock: Remove exynos4x12_set_mmc_clk function board: trats2: Enable device tree on Trats2
Jaehoon Chung (11): ARM: exynos: board: change the mmc/sd init sequence ARM: exynos: clock: modify the set_mmc_clk for exynos4 ARM: dts: exynos: rename from EXYNOS5_DWMMC to EXYNOS_DWMMC mmc: exynos_dw_mmc: restore the property into host mmc: remove the unnecessary define and fix the wrong bit control mmc: support the DDR mode for eMMC mmc: dw_mmc: support the DDR mode ARM: dts: exnyos: enable dw-mmc controller mmc: exynos_dw_mmc: enable the DDR mode ARM: exynos4: enable the dwmmc configuration mmc: s5p_sdhci: add the s5p_sdhci_core_init function
arch/arm/cpu/armv7/exynos/clock.c | 45 ++----- arch/arm/cpu/armv7/exynos/pinmux.c | 35 ++++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/dts/exynos5.dtsi | 8 +- arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- doc/device-tree-bindings/exynos/dwmmc.txt | 8 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 205 +++++++++++++++++++---------- drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++--- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/fdtdec.h | 2 +- include/mmc.h | 25 ++-- lib/fdtdec.c | 2 +- 17 files changed, 275 insertions(+), 171 deletions(-)
applied to u-boot-samsung.
Thanks, Minkyu Kang.

Hi,
Thanks Minkyu!
To Pantelis,
There are the patches related with mmc. So i think you need to check also.(To prevent conflict).
Best Regards, Jaehoon Chung
On 05/16/2014 03:53 PM, Minkyu Kang wrote:
On 16/05/14 13:59, Jaehoon Chung wrote:
If card and host are supported DDR mode, then it can be used the DDR mode. This patch-set has dependency about beomho's patch-set. (Based-on u-boot-samsung repository)
It's result for loading image.
sdhci controller ->5260488 bytes read in 259 ms (19.4 MiB/s) dwmmc controller without DDR mode -> 5260488 bytes read in 202 ms (24.8 MiB/s) dwmmc controller with DDR mode -> 5260488 bytes read in 118 ms (42.5 MiB/s)
Download the 400M image with lthor. sdhci controller -> 59.4sec (Avg 6.95 MB/s) dwmmc controller without DDR mode -> 61.6sec (Avg 6.72MB/s) dwmmc controller with DDR mode -> 60.4sec (Avg 6.85MB/s)
Beomho Seo (3): arm: exynos: pinmux: add sdmmc4 gpio configratuion arm: exynos: clock: Remove exynos4x12_set_mmc_clk function board: trats2: Enable device tree on Trats2
Jaehoon Chung (11): ARM: exynos: board: change the mmc/sd init sequence ARM: exynos: clock: modify the set_mmc_clk for exynos4 ARM: dts: exynos: rename from EXYNOS5_DWMMC to EXYNOS_DWMMC mmc: exynos_dw_mmc: restore the property into host mmc: remove the unnecessary define and fix the wrong bit control mmc: support the DDR mode for eMMC mmc: dw_mmc: support the DDR mode ARM: dts: exnyos: enable dw-mmc controller mmc: exynos_dw_mmc: enable the DDR mode ARM: exynos4: enable the dwmmc configuration mmc: s5p_sdhci: add the s5p_sdhci_core_init function
arch/arm/cpu/armv7/exynos/clock.c | 45 ++----- arch/arm/cpu/armv7/exynos/pinmux.c | 35 ++++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/dts/exynos5.dtsi | 8 +- arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- doc/device-tree-bindings/exynos/dwmmc.txt | 8 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 205 +++++++++++++++++++---------- drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++--- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/fdtdec.h | 2 +- include/mmc.h | 25 ++-- lib/fdtdec.c | 2 +- 17 files changed, 275 insertions(+), 171 deletions(-)
applied to u-boot-samsung.
Thanks, Minkyu Kang. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (3)
-
Hector Palacios
-
Jaehoon Chung
-
Minkyu Kang