mmc: exynos: code cleanup and support DDR mode
Subsystems (3)
v3 cover 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 (10):
ARM: exynos: board: change the mmc/sd init sequence
ARM: exynos: clock: modify the set_mmc_clk for exynos4
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 | 18 ++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 209 ++++++++++++++++++++------------ drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++---- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/mmc.h | 25 ++-- 13 files changed, 250 insertions(+), 163 deletions(-)
Signature · 1 line
1.7.9.5
PATCH v3 1/13 arm: exynos: pinmux: add sdmmc4 gpio configratuion
From: Beomho Seo <[email protected]>
For use dwmmc controller at exynos4, add SDMMC4 gpio configuration. In case SDMMC2, do not use 8 bit mode at exynos4.
--- arch/arm/cpu/armv7/exynos/pinmux.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
arch/arm/cpu/armv7/exynos/pinmux.c +15 -3
@@ -632,16 +632,27 @@ static int exynos4_mmc_config(int peripheral, int flags)struct exynos4_gpio_part2 *gpio2 = (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2 ();struct s5p_gpio_bank *bank, *bank_ext; +unsigned int func, func_ext;int i;switch (peripheral) {case PERIPH_ID_SDMMC0 : bank = &gpio2->k0; bank_ext = &gpio2->k1; + func =GPIO_FUNC (0x2 ); + func_ext =GPIO_FUNC (0x3 );break ;case PERIPH_ID_SDMMC2 : bank = &gpio2->k2; bank_ext = &gpio2->k3; + func =GPIO_FUNC (0x2 ); + func_ext =GPIO_FUNC (0x3 ); +break ; +case PERIPH_ID_SDMMC4 : + bank = &gpio2->k0; + bank_ext = &gpio2->k1; + func =GPIO_FUNC (0x3 ); + func_ext =GPIO_FUNC (0x4 );break ;default :return -1 ;
@@ -649,13 +660,14 @@ static int exynos4_mmc_config(int peripheral, int flags)for (i =0 ; i <7 ; i++) {if (i ==2 )continue ; -s5p_gpio_cfg_pin (bank, i,GPIO_FUNC (0x2 )); +s5p_gpio_cfg_pin (bank, i, func);s5p_gpio_set_pull (bank, i,GPIO_PULL_NONE );s5p_gpio_set_drv (bank, i,GPIO_DRV_4X ); } +/* SDMMC2 do not use 8bit mode@exynos4 */ if (flags &PINMUX_FLAG_8BIT_MODE ) {for (i =3 ; i <7 ; i++) { -s5p_gpio_cfg_pin (bank_ext, i,GPIO_FUNC (0x3 )); +s5p_gpio_cfg_pin (bank_ext, i, func_ext);s5p_gpio_set_pull (bank_ext, i,GPIO_PULL_NONE );s5p_gpio_set_drv (bank_ext, i,GPIO_DRV_4X ); }
@@ -722,10 +734,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 :
Signature · 1 line
1.7.9.5
PATCH v3 1/13 arm: exynos: pinmux: add sdmmc4 gpio configratuion
Dear Beonho and Jaehoon,
Quoted 67 lines · Jaehoon Chung
From: Beomho Seo <[email protected]>
For use dwmmc controller at exynos4, add SDMMC4 gpio configuration. In case SDMMC2, do not use 8 bit mode at exynos4.
Signed-off-by Beomho Seo <[email protected]>Signed-off-by Jaehoon Chung <[email protected]>Tested-by Piotr Wilczek <[email protected]>Cc Lukasz Majewski <[email protected]>Cc Piotr Wilczek <[email protected]>Cc Minkyu Kang <[email protected]>--- arch/arm/cpu/armv7/exynos/pinmux.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)arch/arm/cpu/armv7/exynos/pinmux.c +14
-2@@ -632,16 +632,27 @@ static int exynos4_mmc_config(int peripheral, int flags)struct exynos4_gpio_part2 *gpio2 = (struct exynos4_gpio_part2 *)samsung_get_base_gpio_part2 ();struct s5p_gpio_bank *bank, *bank_ext; +unsigned int func, func_ext;int i;switch (peripheral) {case PERIPH_ID_SDMMC0 : bank = &gpio2->k0; bank_ext = &gpio2->k1; + func =GPIO_FUNC (0x2 ); + func_ext =GPIO_FUNC (0x3 );break ;case PERIPH_ID_SDMMC2 : bank = &gpio2->k2; bank_ext = &gpio2->k3; + func =GPIO_FUNC (0x2 ); + func_ext =GPIO_FUNC (0x3 ); +break ; +case PERIPH_ID_SDMMC4 : + bank = &gpio2->k0; + bank_ext = &gpio2->k1; + func =GPIO_FUNC (0x3 ); + func_ext =GPIO_FUNC (0x4 );break ;default :return -1 ;@@ -649,13 +660,14 @@ static int exynos4_mmc_config(int peripheral, int flags)for (i =0 ; i <7 ; i++) {if (i ==2 )continue ; -s5p_gpio_cfg_pin (bank, i,GPIO_FUNC (0x2 )); +s5p_gpio_cfg_pin (bank, i, func);s5p_gpio_set_pull (bank, i,GPIO_PULL_NONE );s5p_gpio_set_drv (bank, i,GPIO_DRV_4X ); } +/* SDMMC2 do not use 8bit mode at exynos4 */ if (flags &PINMUX_FLAG_8BIT_MODE ) {for (i =3 ; i <7 ; i++) { -s5p_gpio_cfg_pin (bank_ext, i,GPIO_FUNC (0x3 )); +s5p_gpio_cfg_pin (bank_ext, i, func_ext);s5p_gpio_set_pull (bank_ext, i,GPIO_PULL_NONE );s5p_gpio_set_drv (bank_ext, i,GPIO_DRV_4X ); }@@ -722,10 +734,10 @@ static int exynos4_pinmux_config(int peripheral, int flags)break ;
arch/arm/cpu/armv7/exynos/pinmux.c static int exynos4_pinmux_config(int peripheral, int flags) · line 743
Quoted 10 lines
arch/arm/cpu/armv7/exynos/pinmux.c +1
-1case 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 :
Since GIPO API was changed, please rebase this patch.
Thanks,
Minkyu Kang.
PATCH v3 2/13 arm: exynos: clock: Remove exynos4x12_set_mmc_clk function
In reply to Jaehoon ChungFrom: Beomho Seo <[email protected]>
exynos4x12_set_mmc_clk function have been removed.
Because, exynos4x12_clock and exynos4_clock return same div_fsys* value.
--- arch/arm/cpu/armv7/exynos/clock.c | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-)
arch/arm/cpu/armv7/exynos/clock.c +1 -28
@@ -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); } }
Signature · 1 line
1.7.9.5
PATCH v3 3/13 board: trats2: Enable device tree on Trats2
In reply to Jaehoon ChungFrom: Beomho Seo <[email protected]>
This patch add dwmmc emmc controller node on exynos4 and exynos4412 device tree.
--- arch/arm/dts/exynos4.dtsi | 8 ++++++++ arch/arm/dts/exynos4412-trats2.dts | 8 ++++++++ 2 files changed, 16 insertions(+)
arch/arm/dts/exynos4.dtsi +8 -0
@@ -128,6 +128,14 @@ interrupts = <0 78 0>; }; + dwmmc at 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>;
arch/arm/dts/exynos4412-trats2.dts +8 -0
@@ -31,6 +31,7 @@ console = "/serial at 13820000"; mmc0 = "sdhci at 12510000"; mmc2 = "sdhci at 12530000"; + mmc4 = "dwmmc at 12550000"; }; i2c at 138d0000 {
@@ -431,4 +432,11 @@ sdhci at 12540000 { status = "disabled"; }; + + dwmmc at 12550000 { + samsung,bus-width = <8>; + samsung,timing = <0 1 0>; + pwr-gpios = <&gpio 0x2004002 0>; + index = <4>; + }; };
Signature · 1 line
1.7.9.5
PATCH v3 4/13 ARM: exynos: board: change the mmc/sd init sequence
In reply to Jaehoon ChungExynos4 can be used the dwmmc controller for eMMC. Then it needs to check dwmmc_init() at first.
--- board/samsung/common/board.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
board/samsung/common/board.c +6 -7
@@ -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
Signature · 1 line
1.7.9.5
PATCH v3 5/13 ARM: exynos: clock: modify the set_mmc_clk for exynos4
In reply to Jaehoon ChungModified 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)
--- arch/arm/cpu/armv7/exynos/clock.c | 16 +++++++++++----- arch/arm/include/asm/arch-exynos/clk.h | 5 +++++ 2 files changed, 16 insertions(+), 5 deletions(-)
arch/arm/cpu/armv7/exynos/clock.c +11 -5
@@ -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 */
arch/arm/include/asm/arch-exynos/clk.h +5 -0
@@ -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 ,
Signature · 1 line
1.7.9.5
PATCH v3 6/13 mmc: exynos_dw_mmc: restore the property into host
In reply to Jaehoon ChungRestore the platdata(property of dt) into host struct. Then data's information is maintained and reused anywhere.
--- drivers/mmc/exynos_dw_mmc.c | 208 +++++++++++++++++++++++++++---------------- include/dwmmc.h | 2 + 2 files changed, 132 insertions(+), 78 deletions(-)
drivers/mmc/exynos_dw_mmc.c +130 -78
@@ -14,6 +14,7 @@#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
@@ -45,6 +46,13 @@ unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) & DWMCI_DIVRATIO_MASK) + 1; sclk =get_mmc_clk (host->dev_index); +/* +* Assume to know divider value. +* When clock unit is broken, need to set "host->div" +*/ +if (host->div) + sclk /= (host->div +1 ); +return sclk / clk_div; }
@@ -61,26 +69,17 @@ 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);/*
@@ -94,19 +93,15 @@ int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)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) +if (index ==2 ) host->clksel_val =DWMMC_MMC2_CLKSEL_VAL ; }
@@ -121,77 +116,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) +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, compat_id; -u32 clksel_val, base, timing[3 ]; +int index, flag =0 , err =0 ; - compat_id =COMPAT_SAMSUNG_EXYNOS_DWMMC ; + index = host->dev_index; - count =fdtdec_find_aliases_for_id (blob,"mmc" , - compat_id, node_list,DWMMC_MAX_CH_NUM ); + 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; + } -for (i =0 ; i < count; i++) { -int node = node_list[i]; -struct fdt_gpio_state pwr_gpio; +return exynos_dwmci_core_init (host, index); +} -if (node <=0 ) -continue ; +static int exynos_dwmci_get_config (const void *blob,int node, +struct dwmci_host *host) +{ +int err =0 ; +u32 base, clksel_val, timing[3 ]; -/* Extract device id for each mmc channel */ - dev_id =pinmux_decode_periph_id (blob, node); +/* Extract device id for each mmc channel */ + host->dev_id =pinmux_decode_periph_id (blob, node); -/* 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 ; +/* 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 ; + } -fdtdec_decode_gpio (blob, node,"pwr-gpios" , &pwr_gpio); -if (fdt_gpio_isvalid (&pwr_gpio)) -gpio_direction_output (pwr_gpio.gpio,1 ); + 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 ; -/* config pinmux for each mmc channel */ - err =exynos_pinmux_config (dev_id, flag); -if (err) { -debug ("DWMMC not configured\n" ); -return err; - } +/* 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; - index =fdtdec_get_int (blob, node,"index" , dev_id); -if (index == dev_id) - index = dev_id -PERIPH_ID_SDMMC0 ; +/* 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 ; + } -/* 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 ); + 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
include/dwmmc.h +2 -0
@@ -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;
Signature · 1 line
1.7.9.5
PATCH v3 7/13 mmc: remove the unnecessary define and fix the wrong bit control
In reply to Jaehoon Chung--- drivers/mmc/mmc.c | 2 +- include/mmc.h | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-)
drivers/mmc/mmc.c +1 -1
@@ -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 ;
include/mmc.h +6 -12
@@ -31,15 +31,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
@@ -97,9 +94,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
Signature · 1 line
1.7.9.5
PATCH v3 8/13 mmc: support the DDR mode for eMMC
In reply to Jaehoon Chung--- drivers/mmc/mmc.c | 16 +++++++++++++--- include/mmc.h | 7 +++++++ 2 files changed, 20 insertions(+), 3 deletions(-)
drivers/mmc/mmc.c +13 -3
@@ -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++) {
include/mmc.h +7 -0
@@ -37,6 +37,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
@@ -168,10 +169,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@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)
Signature · 1 line
1.7.9.5
PATCH v3 9/13 mmc: dw_mmc: support the DDR mode
In reply to Jaehoon ChungSupport the DDR mode at dw-mmc controller
--- drivers/mmc/dw_mmc.c | 12 ++++++++++-- include/dwmmc.h | 3 +++ 2 files changed, 13 insertions(+), 2 deletions(-)
drivers/mmc/dw_mmc.c +10 -2
@@ -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); }
include/dwmmc.h +3 -0
@@ -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)
Signature · 1 line
1.7.9.5
PATCH v3 10/13 ARM: dts: exnyos: enable dw-mmc controller
In reply to Jaehoon ChungEnabled the dw-mmc controller.
--- arch/arm/dts/exynos4412-trats2.dts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/arm/dts/exynos4412-trats2.dts +5 -1
@@ -417,6 +417,7 @@ samsung,bus-width = <8>; samsung,timing = <1 3 3>; pwr-gpios = <&gpio 0x2004002 0>; + status = "disabled"; }; sdhci at 12520000 {
@@ -435,7 +436,10 @@ dwmmc at 12550000 { samsung,bus-width = <8>; - samsung,timing = <0 1 0>; + samsung,timing = <2 1 0>; + fifoth_val = <0x203f0040>; + bus_hz = <400000000>; + div = <0x3>; pwr-gpios = <&gpio 0x2004002 0>; index = <4>; };
Signature · 1 line
1.7.9.5
PATCH v3 11/13 mmc: exynos_dw_mmc: enable the DDR mode
In reply to Jaehoon ChungSet the ddr mode capability by default.
--- drivers/mmc/exynos_dw_mmc.c | 1 + 1 file changed, 1 insertion(+)
drivers/mmc/exynos_dw_mmc.c +1 -0
@@ -105,6 +105,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;
Signature · 1 line
1.7.9.5
PATCH v3 12/13 ARM: exynos4: enable the dwmmc configuration
In reply to Jaehoon Chung--- include/configs/exynos4-dt.h | 3 +++ 1 file changed, 3 insertions(+)
include/configs/exynos4-dt.h +3 -0
@@ -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 */
Signature · 1 line
1.7.9.5
PATCH v3 13/13 mmc: s5p_sdhci: add the s5p_sdhci_core_init function
In reply to Jaehoon ChungTo 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".
--- drivers/mmc/s5p_sdhci.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-)
drivers/mmc/s5p_sdhci.c +17 -25
@@ -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)
Signature · 1 line
1.7.9.5
v3 cover mmc: exynos: code cleanup and support DDR mode
In reply to Jaehoon ChungDear, All.
Did you have any comment?
Best Regards,
Jaehoon Chung
Quoted 47 lines · Jaehoon Chung
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: Removeexynos4x12_set_mmc_clkfunction
board: trats2: Enable device tree on Trats2Jaehoon Chung (10):
ARM: exynos: board: change the mmc/sd init sequence
ARM: exynos: clock: modify theset_mmc_clkfor exynos4
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 thes5p_sdhci_core_initfunctionarch/arm/cpu/armv7/exynos/clock.c | 45 ++----- arch/arm/cpu/armv7/exynos/pinmux.c | 18 ++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 209 ++++++++++++++++++++------------ drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++---- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/mmc.h | 25 ++-- 13 files changed, 250 insertions(+), 163 deletions(-)
v3 cover mmc: exynos: code cleanup and support DDR mode
Hi, All.
If didn't have any other comment, could you apply this patch? I want to merge this patch at mainline.
Best Regards,
Jaehoon Chung
Quoted 61 lines · Jaehoon Chung
Dear, All.
Did you have any comment?
Best Regards,
Jaehoon ChungQuoted 32 lines · Jaehoon Chung
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: Removeexynos4x12_set_mmc_clkfunction
board: trats2: Enable device tree on Trats2Jaehoon Chung (10):
ARM: exynos: board: change the mmc/sd init sequence
ARM: exynos: clock: modify theset_mmc_clkfor exynos4
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 thes5p_sdhci_core_initfunctionQuoted 15 lines
arch/arm/cpu/armv7/exynos/clock.c | 45 ++----- arch/arm/cpu/armv7/exynos/pinmux.c | 18 ++- arch/arm/dts/exynos4.dtsi | 8 ++ arch/arm/dts/exynos4412-trats2.dts | 12 ++ arch/arm/include/asm/arch-exynos/clk.h | 5 + board/samsung/common/board.c | 13 +- drivers/mmc/dw_mmc.c | 12 +- drivers/mmc/exynos_dw_mmc.c | 209 ++++++++++++++++++++------------ drivers/mmc/mmc.c | 16 ++- drivers/mmc/s5p_sdhci.c | 42 +++---- include/configs/exynos4-dt.h | 3 + include/dwmmc.h | 5 + include/mmc.h | 25 ++-- 13 files changed, 250 insertions(+), 163 deletions(-)_______________________________________________
U-Boot mailing list
U-Boot at lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot
v3 cover mmc: exynos: code cleanup and support DDR mode
Dear Pantelis Antoniou,
Quoted 8 lines · Jaehoon Chung
Hi, All.
If didn't have any other comment, could you apply this patch? I want to merge this patch at mainline.
Best Regards,
Jaehoon Chung
If you are OK then, I want to pick up this patchset to samsung tree. This patchset has been including samsung related features.
Thanks,
Minkyu Kang.