[U-Boot] [PATCH V2 0/9] EXYNOS5: Enable dwmmc

This patch set enables and initialises dwmmc for Exynos5250 on SMDK5250. Adds driver changes required for dwmmc. Adds dt support for dwmmc. Adds EMMC booting feature for SMDK5250.
This patch set is based on: "EXYNOS: mmc: support DesignWare Controller for Samsung-SoC", which is merged in u-boot-mmc "Exynos: clock: support get_mmc_clk for exynos" "Add DT based ethernet driver for SMDK5250" "SMDK5250: Add FDT support"
Changes from V1: 1)Corrected in response to review comments. 2)Created separate board files for dt and not-dt versions. 3)Added binding file for DWMMC device node. 4)Moved dwmmc clock setting from spl_boot.c to clock_init.c.
Amar (9): FDT: Add compatible string for DWMMC EXYNOS5: FDT: Add DWMMC device node data DWMMC: Initialise dwmci and resolved the boot partition write issue EXYNOS5: DWMMC: Added dt support for DWMMC EXYNOS5: DWMMC: API to set mmc clock divisor SMDK5250: Enable DWMMC MMC: APIs to support creation of boot partition SMDK5250: Enable EMMC booting COMMON: MMC: Command to support EMMC booting
arch/arm/cpu/armv7/exynos/clock.c | 38 ++++- arch/arm/dts/exynos5250.dtsi | 32 ++++ arch/arm/include/asm/arch-exynos/clk.h | 3 + arch/arm/include/asm/arch-exynos/dwmmc.h | 12 +- board/samsung/dts/exynos5250-smdk5250.dts | 22 +++ board/samsung/smdk5250/Makefile | 4 + board/samsung/smdk5250/clock_init.c | 18 +++ board/samsung/smdk5250/clock_init.h | 5 + board/samsung/smdk5250/exynos5-dt.c | 235 ++++++++++++++++++++++++++++++ board/samsung/smdk5250/smdk5250.c | 76 +++------- board/samsung/smdk5250/spl_boot.c | 52 ++++++- common/cmd_mmc.c | 85 ++++++++++- doc/device-tree-bindings/exynos/dwmmc.txt | 29 ++++ drivers/mmc/dw_mmc.c | 14 +- drivers/mmc/exynos_dw_mmc.c | 116 ++++++++++++++- drivers/mmc/mmc.c | 118 +++++++++++++++ include/configs/exynos5250-dt.h | 2 + include/dwmmc.h | 4 + include/fdtdec.h | 1 + include/mmc.h | 16 ++ lib/fdtdec.c | 1 + 21 files changed, 806 insertions(+), 77 deletions(-) create mode 100644 board/samsung/smdk5250/exynos5-dt.c create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt

Hi all,
Please ignore the below patch set. This patch set was meant for internal review.
This has been posted by mistake. Sorry for the trouble.
Thanks & Regards Amarendra Reddy On 28 December 2012 21:22, Amar amarendra.xt@samsung.com wrote:
This patch set enables and initialises dwmmc for Exynos5250 on SMDK5250. Adds driver changes required for dwmmc. Adds dt support for dwmmc. Adds EMMC booting feature for SMDK5250.
This patch set is based on: "EXYNOS: mmc: support DesignWare Controller for Samsung-SoC", which is merged in u-boot-mmc "Exynos: clock: support get_mmc_clk for exynos" "Add DT based ethernet driver for SMDK5250" "SMDK5250: Add FDT support"
Changes from V1: 1)Corrected in response to review comments. 2)Created separate board files for dt and not-dt versions. 3)Added binding file for DWMMC device node. 4)Moved dwmmc clock setting from spl_boot.c to clock_init.c.
Amar (9): FDT: Add compatible string for DWMMC EXYNOS5: FDT: Add DWMMC device node data DWMMC: Initialise dwmci and resolved the boot partition write issue EXYNOS5: DWMMC: Added dt support for DWMMC EXYNOS5: DWMMC: API to set mmc clock divisor SMDK5250: Enable DWMMC MMC: APIs to support creation of boot partition SMDK5250: Enable EMMC booting COMMON: MMC: Command to support EMMC booting
arch/arm/cpu/armv7/exynos/clock.c | 38 ++++- arch/arm/dts/exynos5250.dtsi | 32 ++++ arch/arm/include/asm/arch-exynos/clk.h | 3 + arch/arm/include/asm/arch-exynos/dwmmc.h | 12 +- board/samsung/dts/exynos5250-smdk5250.dts | 22 +++ board/samsung/smdk5250/Makefile | 4 + board/samsung/smdk5250/clock_init.c | 18 +++ board/samsung/smdk5250/clock_init.h | 5 + board/samsung/smdk5250/exynos5-dt.c | 235 ++++++++++++++++++++++++++++++ board/samsung/smdk5250/smdk5250.c | 76 +++------- board/samsung/smdk5250/spl_boot.c | 52 ++++++- common/cmd_mmc.c | 85 ++++++++++- doc/device-tree-bindings/exynos/dwmmc.txt | 29 ++++ drivers/mmc/dw_mmc.c | 14 +- drivers/mmc/exynos_dw_mmc.c | 116 ++++++++++++++- drivers/mmc/mmc.c | 118 +++++++++++++++ include/configs/exynos5250-dt.h | 2 + include/dwmmc.h | 4 + include/fdtdec.h | 1 + include/mmc.h | 16 ++ lib/fdtdec.c | 1 + 21 files changed, 806 insertions(+), 77 deletions(-) create mode 100644 board/samsung/smdk5250/exynos5-dt.c create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
-- 1.8.0
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Add required compatible information for DWMMC driver.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com Signed-off-by: Amar amarendra.xt@samsung.com --- include/fdtdec.h | 1 + lib/fdtdec.c | 1 + 2 files changed, 2 insertions(+)
diff --git a/include/fdtdec.h b/include/fdtdec.h index 539bb1b..f09c281 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -74,6 +74,7 @@ enum fdt_compat_id { COMPAT_SAMSUNG_EXYNOS5_SOUND, /* Exynos Sound */ COMPAT_WOLFSON_WM8994_CODEC, /* Wolfson WM8994 Sound Codec */ COMPAT_SAMSUNG_EXYNOS_SPI, /* Exynos SPI */ + COMPAT_SAMSUNG_EXYNOS5_DWMMC, /* Exynos5 DWMMC controller */
COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 44c249d..6597661 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -51,6 +51,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"), COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"), COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"), + COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"), };
const char *fdtdec_get_compatible(enum fdt_compat_id id)

This patch adds DWMMC device node data for exynos5. This patch also adds binding file for DWMMC device node.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com Signed-off-by: Amar amarendra.xt@samsung.com --- arch/arm/dts/exynos5250.dtsi | 32 +++++++++++++++++++++++++++++++ board/samsung/dts/exynos5250-smdk5250.dts | 22 +++++++++++++++++++++ doc/device-tree-bindings/exynos/dwmmc.txt | 29 ++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
diff --git a/arch/arm/dts/exynos5250.dtsi b/arch/arm/dts/exynos5250.dtsi index 1008797..b701ae5 100644 --- a/arch/arm/dts/exynos5250.dtsi +++ b/arch/arm/dts/exynos5250.dtsi @@ -138,4 +138,36 @@ reg = <0x131b0000 0x30>; interrupts = <0 130 0>; }; + + dwmmc@12200000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,exynos5250-dwmmc"; + reg = <0x12200000 0x1000>; + interrupts = <0 75 0>; + }; + + dwmmc@12210000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,exynos5250-dwmmc"; + reg = <0x12210000 0x1000>; + interrupts = <0 76 0>; + }; + + dwmmc@12220000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,exynos5250-dwmmc"; + reg = <0x12220000 0x1000>; + interrupts = <0 77 0>; + }; + + dwmmc@12230000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "samsung,exynos5250-dwmmc"; + reg = <0x12230000 0x1000>; + interrupts = <0 78 0>; + }; }; diff --git a/board/samsung/dts/exynos5250-smdk5250.dts b/board/samsung/dts/exynos5250-smdk5250.dts index a8e62da..9baf622 100644 --- a/board/samsung/dts/exynos5250-smdk5250.dts +++ b/board/samsung/dts/exynos5250-smdk5250.dts @@ -30,6 +30,10 @@ spi2 = "/spi@12d40000"; spi3 = "/spi@131a0000"; spi4 = "/spi@131b0000"; + dwmmc0 = "/dwmmc@12200000"; + dwmmc1 = "/dwmmc@12210000"; + dwmmc2 = "/dwmmc@12220000"; + dwmmc3 = "/dwmmc@12230000"; };
sromc@12250000 { @@ -59,4 +63,22 @@ compatible = "wolfson,wm8994-codec"; }; }; + + dwmmc@12200000 { + samsung,bus-width = <8>; + samsung,timing = <1 3 3>; + }; + + dwmmc@12210000 { + status = "disabled"; + }; + + dwmmc@12220000 { + samsung,bus-width = <4>; + samsung,timing = <1 2 3>; + }; + + dwmmc@12230000 { + status = "disabled"; + }; }; diff --git a/doc/device-tree-bindings/exynos/dwmmc.txt b/doc/device-tree-bindings/exynos/dwmmc.txt new file mode 100644 index 0000000..6232ad6 --- /dev/null +++ b/doc/device-tree-bindings/exynos/dwmmc.txt @@ -0,0 +1,29 @@ +* Exynos 5250 DWC_mobile_storage + +The Exynos 5250 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. +SOC specific and Board specific properties are channel specific. + +Required SoC Specific Properties: + +- compatible: should be + - samsung,exynos5250-dwmmc: for exynos5250 platforms + +- reg: physical base address of the controller and length of memory mapped + region. + +- interrupts: The interrupt number to the cpu. + +Required Board Specific Properties: + +- #address-cells: should be 1. +- #size-cells: should be 0. +- samsung,bus-width: The width of the bus used to interface the devices + supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO). +- samsung,timing: The timing values to be written into the + Drv/sample clock selection register of corresponding channel.

This patch adds dt support for DWMMC, by reading the dwmmc node data from the device tree and initialising dwmmc channels as per data obtained from the node.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com Signed-off-by: Amar amarendra.xt@samsung.com --- arch/arm/include/asm/arch-exynos/dwmmc.h | 12 ++-- drivers/mmc/exynos_dw_mmc.c | 116 +++++++++++++++++++++++++++++-- include/dwmmc.h | 4 ++ 3 files changed, 119 insertions(+), 13 deletions(-)
diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h index 8acdf9b..39cd4c7 100644 --- a/arch/arm/include/asm/arch-exynos/dwmmc.h +++ b/arch/arm/include/asm/arch-exynos/dwmmc.h @@ -27,10 +27,10 @@ #define DWMCI_SET_DRV_CLK(x) ((x) << 16) #define DWMCI_SET_DIV_RATIO(x) ((x) << 24)
-int exynos_dwmci_init(u32 regbase, int bus_width, int index); +#define FSYS1_MMC0_DIV_VAL 0x0701 + +#ifdef CONFIG_OF_CONTROL +unsigned int exynos_dwmmc_init(const void *blob); +#endif
-static inline unsigned int exynos_dwmmc_init(int index, int bus_width) -{ - unsigned int base = samsung_get_base_mmc() + (0x10000 * index); - return exynos_dwmci_init(base, bus_width, index); -} +int exynos_dwmci_init(u32 regbase, int bus_width, int index); diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index 72a31b7..541889f 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -19,39 +19,141 @@ */
#include <common.h> -#include <malloc.h> #include <dwmmc.h> +#include <fdtdec.h> +#include <libfdt.h> +#include <malloc.h> #include <asm/arch/dwmmc.h> #include <asm/arch/clk.h> +#include <asm/arch/pinmux.h> + +#define DWMMC_MAX_CH_NUM 4 +#define DWMMC_MAX_FREQ 52000000 +#define DWMMC_MIN_FREQ 400000 +#define DWMMC_MMC0_CLKSEL_VAL 0x03030001 +#define DWMMC_MMC2_CLKSEL_VAL 0x03020001
static char *EXYNOS_NAME = "EXYNOS DWMMC"; +u32 timing[3];
+/* + * Function used as callback function to initialise the + * CLKSEL register for every mmc channel. + */ static void exynos_dwmci_clksel(struct dwmci_host *host) { - u32 val; - val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) | - DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(0); + dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val); +}
- dwmci_writel(host, DWMCI_CLKSEL, val); +unsigned int exynos_dwmci_get_clk(int dev_index) +{ + return get_mmc_clk(dev_index); }
int exynos_dwmci_init(u32 regbase, int bus_width, int index) { struct dwmci_host *host = NULL; + int dev_id = 0; host = malloc(sizeof(struct dwmci_host)); if (!host) { printf("dwmci_host malloc fail!\n"); return 1; } + /* Convert index into corresponding peripheral ID */ + dev_id = index + PERIPH_ID_SDMMC0; + + /* set the clock divisor - clk_div_fsys for mmc */ + if (exynos5_mmc_set_clk_div(dev_id)) { + debug("mmc clock div set failed\n"); + return -1; + }
host->name = EXYNOS_NAME; host->ioaddr = (void *)regbase; host->buswidth = bus_width; +#ifdef CONFIG_OF_CONTROL + host->clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) | + DWMCI_SET_DRV_CLK(timing[1]) | + DWMCI_SET_DIV_RATIO(timing[2])); +#else + if (0 == index) + host->clksel_val = DWMMC_MMC0_CLKSEL_VAL; + if (2 == index) + host->clksel_val = DWMMC_MMC2_CLKSEL_VAL; +#endif host->clksel = exynos_dwmci_clksel; host->dev_index = index; - - add_dwmci(host, 52000000, 400000); + host->mmc_clk = exynos_dwmci_get_clk; + /* Add the mmc chennel to be registered with mmc core */ + add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ);
return 0; }
+#ifdef CONFIG_OF_CONTROL +unsigned int exynos_dwmmc_init(const void *blob) +{ + u32 base; + int index, bus_width; + int node_list[DWMMC_MAX_CH_NUM]; + int err = 0; + int dev_id, flag; + int count, i; + + count = fdtdec_find_aliases_for_id(blob, "dwmmc", + COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list, + DWMMC_MAX_CH_NUM); + + for (i = 0; i < count; i++) { + int node = node_list[i]; + + if (node <= 0) + continue; + + /* Extract device id for each mmc channel */ + 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; + + /* config pinmux for each mmc channel */ + err = exynos_pinmux_config(dev_id, flag); + if (err) { + debug("DWMMC not configured\n"); + return err; + } + + index = 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); + if (err) { + debug("Can't get sdr-timings for divider\n"); + return -1; + } + /* Initialise each mmc channel */ + err = exynos_dwmci_init(base, bus_width, index); + if (err) { + debug("Can't do dwmci init\n"); + return -1; + } + } + + return 0; +} +#endif diff --git a/include/dwmmc.h b/include/dwmmc.h index c8b1d40..4a42849 100644 --- a/include/dwmmc.h +++ b/include/dwmmc.h @@ -123,6 +123,9 @@ #define MSIZE(x) ((x) << 28) #define RX_WMARK(x) ((x) << 16) #define TX_WMARK(x) (x) +#define RX_WMARK_SHIFT 16 +#define RX_WMARK_MASK (0xfff << RX_WMARK_SHIFT) +
#define DWMCI_IDMAC_OWN (1 << 31) #define DWMCI_IDMAC_CH (1 << 4) @@ -144,6 +147,7 @@ struct dwmci_host { unsigned int bus_hz; int dev_index; int buswidth; + u32 clksel_val; u32 fifoth_val; struct mmc *mmc;

This API computes the divisor value based on MPLL clock and writes it into the FSYS1 register.
Signed-off-by: Amar amarendra.xt@samsung.com --- arch/arm/cpu/armv7/exynos/clock.c | 38 ++++++++++++++++++++++++++++++++-- arch/arm/include/asm/arch-exynos/clk.h | 3 +++ 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index 731bbff..bc8e585 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -379,7 +379,7 @@ static unsigned long exynos4_get_mmc_clk(int dev_index) (struct exynos4_clock *)samsung_get_base_clock(); unsigned long uclk, sclk; unsigned int sel, ratio, pre_ratio; - int shift; + int shift = 0;
sel = readl(&clk->src_fsys); sel = (sel >> (dev_index << 2)) & 0xf; @@ -428,7 +428,7 @@ static unsigned long exynos5_get_mmc_clk(int dev_index) (struct exynos5_clock *)samsung_get_base_clock(); unsigned long uclk, sclk; unsigned int sel, ratio, pre_ratio; - int shift; + int shift = 0;
sel = readl(&clk->src_fsys); sel = (sel >> (dev_index << 2)) & 0xf; @@ -526,6 +526,40 @@ static void exynos5_set_mmc_clk(int dev_index, unsigned int div) writel(val, addr); }
+/* exynos5: set the mmc clock div ratio in fsys1 */ +int exynos5_mmc_set_clk_div(int dev_id) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int addr; + unsigned int clock; + unsigned int tmp; + unsigned int i; + + /* get mpll clock */ + clock = get_pll_clk(MPLL) / 1000000; + + /* + * CLK_DIV_FSYS1 + * MMC0_PRE_RATIO [15:8], MMC0_RATIO [3:0] + * CLK_DIV_FSYS2 + * MMC2_PRE_RATIO [15:8], MMC2_RATIO [3:0] + */ + if (dev_id <= PERIPH_ID_SDMMC1) + addr = (unsigned int)&clk->div_fsys1; + else + addr = (unsigned int)&clk->div_fsys2; + + tmp = readl(addr) & ~FSYS1_MMC0_DIV_MASK; + for (i = 0; i <= 0xf; i++) { + if ((clock / (i + 1)) <= 400) { + writel(tmp | i << 0, addr); + break; + } + } + return 0; +} + /* get_lcd_clk: return lcd clock frequency */ static unsigned long exynos4_get_lcd_clk(void) { diff --git a/arch/arm/include/asm/arch-exynos/clk.h b/arch/arm/include/asm/arch-exynos/clk.h index ff155d8..3eaa041 100644 --- a/arch/arm/include/asm/arch-exynos/clk.h +++ b/arch/arm/include/asm/arch-exynos/clk.h @@ -29,6 +29,8 @@ #define VPLL 4 #define BPLL 5
+#define FSYS1_MMC0_DIV_MASK 0xff0f + unsigned long get_pll_clk(int pllreg); unsigned long get_arm_clk(void); unsigned long get_i2c_clk(void); @@ -36,6 +38,7 @@ unsigned long get_pwm_clk(void); unsigned long get_uart_clk(int dev_index); unsigned long get_mmc_clk(int deV_index); void set_mmc_clk(int dev_index, unsigned int div); +int exynos5_mmc_set_clk_div(int dev_index); unsigned long get_lcd_clk(void); void set_lcd_clk(void); void set_mipi_clk(void);

This patch enables DWMMC for SMDK5250. Supports both dt and non-dt versions. Two files are maintained, one for dt version(smdk5250.c) and the other for non-dt version(exynos5-dt.c).
Signed-off-by: Amar amarendra.xt@samsung.com --- board/samsung/smdk5250/Makefile | 4 + board/samsung/smdk5250/exynos5-dt.c | 235 ++++++++++++++++++++++++++++++++++++ board/samsung/smdk5250/smdk5250.c | 76 ++++-------- include/configs/exynos5250-dt.h | 2 + 4 files changed, 264 insertions(+), 53 deletions(-) create mode 100644 board/samsung/smdk5250/exynos5-dt.c
diff --git a/board/samsung/smdk5250/Makefile b/board/samsung/smdk5250/Makefile index 47c6a5a..ecca9f3 100644 --- a/board/samsung/smdk5250/Makefile +++ b/board/samsung/smdk5250/Makefile @@ -32,8 +32,12 @@ COBJS += tzpc_init.o COBJS += smdk5250_spl.o
ifndef CONFIG_SPL_BUILD +ifdef CONFIG_OF_CONTROL +COBJS += exynos5-dt.o +else COBJS += smdk5250.o endif +endif
ifdef CONFIG_SPL_BUILD COBJS += spl_boot.o diff --git a/board/samsung/smdk5250/exynos5-dt.c b/board/samsung/smdk5250/exynos5-dt.c new file mode 100644 index 0000000..4b7e383 --- /dev/null +++ b/board/samsung/smdk5250/exynos5-dt.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2012 Samsung Electronics + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <fdtdec.h> +#include <asm/io.h> +#include <i2c.h> +#include <netdev.h> +#include <spi.h> +#include <asm/arch/cpu.h> +#include <asm/arch/dwmmc.h> +#include <asm/arch/gpio.h> +#include <asm/arch/mmc.h> +#include <asm/arch/pinmux.h> +#include <asm/arch/sromc.h> +#include <pmic.h> + +DECLARE_GLOBAL_DATA_PTR; + +int board_init(void) +{ + gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); +#if defined(CONFIG_PMIC) + pmic_init(); +#endif +#ifdef CONFIG_EXYNOS_SPI + spi_init(); +#endif + return 0; +} + +int dram_init(void) +{ + gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE) + + get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE) + + get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE) + + get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE) + + get_ram_size((long *)PHYS_SDRAM_5, PHYS_SDRAM_7_SIZE) + + get_ram_size((long *)PHYS_SDRAM_6, PHYS_SDRAM_7_SIZE) + + get_ram_size((long *)PHYS_SDRAM_7, PHYS_SDRAM_7_SIZE) + + get_ram_size((long *)PHYS_SDRAM_8, PHYS_SDRAM_8_SIZE); + return 0; +} + +void dram_init_banksize(void) +{ + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1, + PHYS_SDRAM_1_SIZE); + gd->bd->bi_dram[1].start = PHYS_SDRAM_2; + gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2, + PHYS_SDRAM_2_SIZE); + gd->bd->bi_dram[2].start = PHYS_SDRAM_3; + gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3, + PHYS_SDRAM_3_SIZE); + gd->bd->bi_dram[3].start = PHYS_SDRAM_4; + gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4, + PHYS_SDRAM_4_SIZE); + gd->bd->bi_dram[4].start = PHYS_SDRAM_5; + gd->bd->bi_dram[4].size = get_ram_size((long *)PHYS_SDRAM_5, + PHYS_SDRAM_5_SIZE); + gd->bd->bi_dram[5].start = PHYS_SDRAM_6; + gd->bd->bi_dram[5].size = get_ram_size((long *)PHYS_SDRAM_6, + PHYS_SDRAM_6_SIZE); + gd->bd->bi_dram[6].start = PHYS_SDRAM_7; + gd->bd->bi_dram[6].size = get_ram_size((long *)PHYS_SDRAM_7, + PHYS_SDRAM_7_SIZE); + gd->bd->bi_dram[7].start = PHYS_SDRAM_8; + gd->bd->bi_dram[7].size = get_ram_size((long *)PHYS_SDRAM_8, + PHYS_SDRAM_8_SIZE); +} + +static int decode_sromc(const void *blob, struct fdt_sromc *config) +{ + int err; + int node; + + node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC); + if (node < 0) { + debug("Could not find SROMC node\n"); + return node; + } + + config->bank = fdtdec_get_int(blob, node, "bank", 0); + config->width = fdtdec_get_int(blob, node, "width", 2); + + err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing, + FDT_SROM_TIMING_COUNT); + if (err < 0) { + debug("Could not decode SROMC configuration\n"); + return -FDT_ERR_NOTFOUND; + } + + return 0; +} + +int board_eth_init(bd_t *bis) +{ +#ifdef CONFIG_SMC911X + u32 smc_bw_conf, smc_bc_conf; + struct fdt_sromc config; + fdt_addr_t base_addr; + int node; + + node = decode_sromc(gd->fdt_blob, &config); + if (node < 0) { + debug("%s: Could not find sromc configuration\n", __func__); + return 0; + } + node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215); + if (node < 0) { + debug("%s: Could not find lan9215 configuration\n", __func__); + return 0; + } + + /* We now have a node, so any problems from now on are errors */ + base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg"); + if (base_addr == FDT_ADDR_T_NONE) { + debug("%s: Could not find lan9215 address\n", __func__); + return -1; + } + + /* Ethernet needs data bus width of 16 bits */ + if (config.width != 2) { + debug("%s: Unsupported bus width %d\n", __func__, + config.width); + return -1; + } + smc_bw_conf = SROMC_DATA16_WIDTH(config.bank) + | SROMC_BYTE_ENABLE(config.bank); + + smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) |\ + SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |\ + SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |\ + SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |\ + SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) |\ + SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |\ + SROMC_BC_PMC(config.timing[FDT_SROM_PMC]); + + /* Select and configure the SROMC bank */ + exynos_pinmux_config(PERIPH_ID_SROMC, config.bank); + s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf); + return smc911x_initialize(0, base_addr); +#endif + return 0; +} + +#ifdef CONFIG_DISPLAY_BOARDINFO +int checkboard(void) +{ + printf("\nBoard: SMDK5250\n"); + + return 0; +} +#endif + +#ifdef CONFIG_GENERIC_MMC +int board_mmc_init(bd_t *bis) +{ + int ret = 0; + + /* dwmmc initializattion for available channels */ + ret = exynos_dwmmc_init(gd->fdt_blob); + if (ret) + debug("dwmmc init failed\n"); + + return ret; +} +#endif + +static int board_uart_init(void) +{ + int err; + + err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE); + if (err) { + debug("UART0 not configured\n"); + return err; + } + + err = exynos_pinmux_config(PERIPH_ID_UART1, PINMUX_FLAG_NONE); + if (err) { + debug("UART1 not configured\n"); + return err; + } + + err = exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE); + if (err) { + debug("UART2 not configured\n"); + return err; + } + + err = exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE); + if (err) { + debug("UART3 not configured\n"); + return err; + } + + return 0; +} + +#ifdef CONFIG_BOARD_EARLY_INIT_F +int board_early_init_f(void) +{ + int err; + err = board_uart_init(); + if (err) { + debug("UART init failed\n"); + return err; + } +#ifdef CONFIG_SYS_I2C_INIT_BOARD + board_i2c_init(gd->fdt_blob); +#endif + return err; +} +#endif diff --git a/board/samsung/smdk5250/smdk5250.c b/board/samsung/smdk5250/smdk5250.c index 4d24978..7f503e0 100644 --- a/board/samsung/smdk5250/smdk5250.c +++ b/board/samsung/smdk5250/smdk5250.c @@ -27,6 +27,7 @@ #include <netdev.h> #include <spi.h> #include <asm/arch/cpu.h> +#include <asm/arch/dwmmc.h> #include <asm/arch/gpio.h> #include <asm/arch/mmc.h> #include <asm/arch/pinmux.h> @@ -88,32 +89,6 @@ void dram_init_banksize(void) PHYS_SDRAM_8_SIZE); }
-#ifdef CONFIG_OF_CONTROL -static int decode_sromc(const void *blob, struct fdt_sromc *config) -{ - int err; - int node; - - node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC); - if (node < 0) { - debug("Could not find SROMC node\n"); - return node; - } - - config->bank = fdtdec_get_int(blob, node, "bank", 0); - config->width = fdtdec_get_int(blob, node, "width", 2); - - err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing, - FDT_SROM_TIMING_COUNT); - if (err < 0) { - debug("Could not decode SROMC configuration\n"); - return -FDT_ERR_NOTFOUND; - } - - return 0; -} -#endif - int board_eth_init(bd_t *bis) { #ifdef CONFIG_SMC911X @@ -122,25 +97,6 @@ int board_eth_init(bd_t *bis) fdt_addr_t base_addr; int node;
-#ifdef CONFIG_OF_CONTROL - node = decode_sromc(gd->fdt_blob, &config); - if (node < 0) { - debug("%s: Could not find sromc configuration\n", __func__); - return 0; - } - node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215); - if (node < 0) { - debug("%s: Could not find lan9215 configuration\n", __func__); - return 0; - } - - /* We now have a node, so any problems from now on are errors */ - base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg"); - if (base_addr == FDT_ADDR_T_NONE) { - debug("%s: Could not find lan9215 address\n", __func__); - return -1; - } -#else /* Non-FDT configuration - bank number and timing parameters*/ config.bank = CONFIG_ENV_SROM_BANK; config.width = 2; @@ -153,7 +109,6 @@ int board_eth_init(bd_t *bis) config.timing[FDT_SROM_TACP] = 0x09; config.timing[FDT_SROM_PMC] = 0x01; base_addr = CONFIG_SMC911X_BASE; -#endif
/* Ethernet needs data bus width of 16 bits */ if (config.width != 2) { @@ -192,16 +147,31 @@ int checkboard(void) #ifdef CONFIG_GENERIC_MMC int board_mmc_init(bd_t *bis) { - int err; + int err = 0, ret = 0;
err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE); - if (err) { + if (err) debug("SDMMC0 not configured\n"); - return err; - } - - err = s5p_mmc_init(0, 8); - return err; + ret |= err; + + /*EMMC: dwmmc Channel-0 with 8 bit bus width */ + err = exynos_dwmmc_init(0, 8); + if (err) + debug("dwmmc Channel-0 init failed\n"); + ret |= err; + + err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE); + if (err) + debug("SDMMC2 not configured\n"); + ret |= err; + + /*SD: dwmmc Channel-2 with 4 bit bus width */ + err = exynos_dwmmc_init(2, 4); + if (err) + debug("dwmmc Channel-2 init failed\n"); + ret |= err; + + return ret; } #endif
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 12f555c..015d510 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -84,6 +84,8 @@ #define CONFIG_MMC #define CONFIG_SDHCI #define CONFIG_S5P_SDHCI +#define CONFIG_DWMMC +#define CONFIG_EXYNOS_DWMMC
#define CONFIG_BOARD_EARLY_INIT_F

This patch adds APIs to open, close and to create boot partiton for EMMC.
Signed-off-by: Amar amarendra.xt@samsung.com --- drivers/mmc/mmc.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/mmc.h | 16 ++++++++ 2 files changed, 134 insertions(+)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 5ffd8c5..9496bb9 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1302,3 +1302,121 @@ int mmc_initialize(bd_t *bis)
return 0; } + +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) +{ + int err; + struct mmc_cmd cmd; + + /* Only use this command for raw EMMC moviNAND */ + /* Enter backdoor mode */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = MMC_CMD62_ARG1; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error1 = %d\n", err); + return err; + } + + /* Boot partition changing mode */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = MMC_CMD62_ARG2; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error2 = %d\n", err); + return err; + } + /* boot partition size is multiple of 128KB */ + bootsize = ((bootsize*1024)/128); + + /* Arg: boot partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = bootsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error3 = %d\n", err); + return err; + } + /* RPMB partition size is multiple of 128KB */ + rpmbsize = ((rpmbsize*1024)/128); + /* Arg: RPMB partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = rpmbsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error4 = %d\n", err); + return err; + } + return 0; +} + +int mmc_boot_open(struct mmc *mmc) +{ + int err; + struct mmc_cmd cmd; + + /* Boot ack enable, boot partition enable , boot partition access */ + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24 | + EXT_CSD_PART_CONF << 16 | + (EXT_CSD_BOOT_ACK_ENABLE | + EXT_CSD_BOOT_PARTITION_ENABLE | + EXT_CSD_PARTITION_ACCESS_ENABLE) << 8); + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_open: Error1 = %d\n", err); + return err; + } + + /* 4bit transfer mode at booting time. */ + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24| + EXT_CSD_BOOT_BUS_WIDTH << 16| + ((1<<0) << 8)); + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_open: Error2 = %d\n", err); + return err; + } + + return 0; +} + +int mmc_boot_close(struct mmc *mmc) +{ + int err; + struct mmc_cmd cmd; + + /* Boot ack enable, boot partition enable , boot partition access */ + cmd.cmdidx = MMC_CMD_SWITCH; + cmd.resp_type = MMC_RSP_R1b; + + cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24| + EXT_CSD_PART_CONF << 16| + (EXT_CSD_BOOT_ACK_ENABLE | + EXT_CSD_BOOT_PARTITION_ENABLE | + EXT_CSD_PARTITION_ACCESS_DISABLE) << 8); + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_close: Error = %d\n", err); + return err; + } + + return 0; +} diff --git a/include/mmc.h b/include/mmc.h index a13e2bd..999f0a3 100644 --- a/include/mmc.h +++ b/include/mmc.h @@ -86,6 +86,11 @@ #define MMC_CMD_APP_CMD 55 #define MMC_CMD_SPI_READ_OCR 58 #define MMC_CMD_SPI_CRC_ON_OFF 59 +#define MMC_CMD_RES_MAN 62 + +#define MMC_CMD62_ARG1 0xefac62ec +#define MMC_CMD62_ARG2 0xcbaea7 +
#define SD_CMD_SEND_RELATIVE_ADDR 3 #define SD_CMD_SWITCH_FUNC 6 @@ -153,6 +158,7 @@ */ #define EXT_CSD_PARTITIONING_SUPPORT 160 /* RO */ #define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */ +#define EXT_CSD_BOOT_BUS_WIDTH 177 #define EXT_CSD_PART_CONF 179 /* R/W */ #define EXT_CSD_BUS_WIDTH 183 /* R/W */ #define EXT_CSD_HS_TIMING 185 /* R/W */ @@ -177,6 +183,12 @@ #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_BOOT_ACK_ENABLE (1<<6) +#define EXT_CSD_BOOT_PARTITION_ENABLE (1<<3) +#define EXT_CSD_PARTITION_ACCESS_ENABLE (1<<0) +#define EXT_CSD_PARTITION_ACCESS_DISABLE (0<<0) + + #define R1_ILLEGAL_COMMAND (1 << 22) #define R1_APP_CMD (1 << 5)
@@ -275,6 +287,10 @@ int board_mmc_getcd(struct mmc *mmc); int mmc_switch_part(int dev_num, unsigned int part_num); int mmc_getcd(struct mmc *mmc); void spl_mmc_load(void) __noreturn; +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize); +int mmc_boot_open(struct mmc *mmc); +int mmc_boot_close(struct mmc *mmc);
#ifdef CONFIG_GENERIC_MMC #define mmc_host_is_spi(mmc) ((mmc)->host_caps & MMC_MODE_SPI)

Dear Amar,
In message 1356709972-26549-8-git-send-email-amarendra.xt@samsung.com you wrote:
This patch adds APIs to open, close and to create boot partiton for EMMC.
Signed-off-by: Amar amarendra.xt@samsung.com
drivers/mmc/mmc.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ include/mmc.h | 16 ++++++++ 2 files changed, 134 insertions(+)
See my previous comment to patch # 9 of this series. Should we not rather strive t come up with a more generic handling of partitions on storage devices? I don't want to jhave (E)MMC partitioon handling here, USB partitions there, (P)ATA and SATA and ... all in different implementations...
If we support creation and manipulation of partitions, this should be done in common code.
Best regards,
Wolfgang Denk

This patch adds support for EMMC booting on SMDK5250.
Signed-off-by: Amar amarendra.xt@samsung.com --- board/samsung/smdk5250/clock_init.c | 18 +++++++++++++ board/samsung/smdk5250/clock_init.h | 5 ++++ board/samsung/smdk5250/spl_boot.c | 52 ++++++++++++++++++++++++++++++++----- 3 files changed, 69 insertions(+), 6 deletions(-)
diff --git a/board/samsung/smdk5250/clock_init.c b/board/samsung/smdk5250/clock_init.c index c009ae5..90d2199 100644 --- a/board/samsung/smdk5250/clock_init.c +++ b/board/samsung/smdk5250/clock_init.c @@ -28,6 +28,7 @@ #include <asm/arch/clk.h> #include <asm/arch/clock.h> #include <asm/arch/spl.h> +#include <asm/arch/dwmmc.h>
#include "clock_init.h" #include "setup.h" @@ -664,3 +665,20 @@ void clock_init_dp_clock(void) /* We run DP at 267 Mhz */ setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1); } + +/* + * Set clock divisor value for booting from emmc. + * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz. + */ +void emmc_boot_clk_div_set(void) +{ + struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE; + unsigned int addr; + unsigned int div_mmc; + + addr = (unsigned int) &clk->div_fsys1; + + div_mmc = readl(addr) & ~FSYS1_MMC0_DIV_MASK; + div_mmc |= FSYS1_MMC0_DIV_VAL; + writel(div_mmc, addr); +} diff --git a/board/samsung/smdk5250/clock_init.h b/board/samsung/smdk5250/clock_init.h index f751bcb..9b156f7 100644 --- a/board/samsung/smdk5250/clock_init.h +++ b/board/samsung/smdk5250/clock_init.h @@ -146,4 +146,9 @@ struct mem_timings *clock_get_mem_timings(void); * Initialize clock for the device */ void system_clock_init(void); + +/* + * Set clock divisor value for booting from emmc. + */ +void emmc_boot_clk_div_set(void); #endif diff --git a/board/samsung/smdk5250/spl_boot.c b/board/samsung/smdk5250/spl_boot.c index d8f3c1e..e94677b 100644 --- a/board/samsung/smdk5250/spl_boot.c +++ b/board/samsung/smdk5250/spl_boot.c @@ -23,16 +23,41 @@ #include<common.h> #include<config.h>
+#include <asm/arch-exynos/dmc.h> +#include <asm/arch/clock.h> +#include <asm/arch/clk.h> + +#include "clock_init.h" + +/* Index into irom ptr table */ +enum index { + MMC_INDEX, + EMMC44_INDEX, + EMMC44_END_INDEX, + SPI_INDEX, +}; + +/* IROM Function Pointers Table */ +void (*irom_ptr_table[])(void) = { + [MMC_INDEX] = (void *)0x02020030, /* iROM Function Pointer + -SDMMC boot */ + [EMMC44_INDEX] = (void *)0x02020044, /* iROM Function Pointer + -EMMC 4.4 boot */ + [EMMC44_END_INDEX] = (void *)0x02020048,/* iROM Function Pointer + -EMMC 4.4 end boot opration */ + [SPI_INDEX] = (void *)0x02020058, /* iROM Function Pointer + -SPI boot */ + }; + enum boot_mode { BOOT_MODE_MMC = 4, BOOT_MODE_SERIAL = 20, + BOOT_MODE_EMMC = 8, /* EMMC4.4 */ /* Boot based on Operating Mode pin settings */ BOOT_MODE_OM = 32, BOOT_MODE_USB, /* Boot using USB download */ };
- typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst); - /* * Copy U-boot from mmc to RAM: * COPY_BL2_FNPTR_ADDR: Address in iRAM, which Contains @@ -40,23 +65,38 @@ enum boot_mode { */ void copy_uboot_to_ram(void) { - spi_copy_func_t spi_copy; enum boot_mode bootmode; - u32 (*copy_bl2)(u32, u32, u32); + u32 (*spi_copy)(u32 offset, u32 nblock, u32 dst); + u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst); + u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst); + void (*end_bootop_from_emmc)(void);
bootmode = readl(EXYNOS5_POWER_BASE) & OM_STAT;
switch (bootmode) { case BOOT_MODE_SERIAL: - spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR; + spi_copy = (void *) *(u32 *)irom_ptr_table[SPI_INDEX]; spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE, CONFIG_SYS_TEXT_BASE); break; case BOOT_MODE_MMC: - copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR; + copy_bl2 = (void *) *(u32 *)irom_ptr_table[MMC_INDEX]; copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); break; + case BOOT_MODE_EMMC: + emmc_boot_clk_div_set(); + + copy_bl2_from_emmc = + (void *) *(u32 *)irom_ptr_table[EMMC44_INDEX]; + end_bootop_from_emmc = + (void *) *(u32 *)irom_ptr_table[EMMC44_END_INDEX]; + + copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE); + end_bootop_from_emmc(); + + break; + default: break; }

This patch adds commands to open, close and create partitions on EMMC
Signed-off-by: Amar amarendra.xt@samsung.com --- common/cmd_mmc.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c index 62a1c22..355ab8e 100644 --- a/common/cmd_mmc.c +++ b/common/cmd_mmc.c @@ -248,6 +248,85 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) curr_device, mmc->part_num);
return 0; + } else if ((strcmp(argv[1], "open") == 0) || + (strcmp(argv[1], "close") == 0)) { + int dev; + struct mmc *mmc; + + if (argc == 2) + dev = curr_device; + else if (argc == 3) + dev = simple_strtoul(argv[2], NULL, 10); + else + return CMD_RET_USAGE; + + mmc = find_mmc_device(dev); + if (!mmc) { + printf("no mmc device at slot %x\n", dev); + return 1; + } + + if (IS_SD(mmc)) { + printf("SD device cannot be opened/closed\n"); + return 1; + } + + if (strcmp(argv[1], "open") == 0) { + if (!(mmc_boot_open(mmc))) { + printf("EMMC OPEN Success.\n"); + printf("\t\t\t!!!Notice!!!\n"); + printf("!You must close EMMC" + " boot Partition after all" + " images are written\n"); + printf("!EMMC boot partition" + " has continuity at" + " image writing time.\n"); + printf("!So, Do not close boot" + " partition, Before, all" + " images are written.\n"); + return 0; + } else { + printf("EMMC OPEN Failed.\n"); + return 1; + } + } + + if (strcmp(argv[1], "close") == 0) { + if (!(mmc_boot_close(mmc))) { + printf("EMMC CLOSE Success.\n"); + return 0; + } else { + printf("EMMC CLOSE Failed.\n"); + return 1; + } + } + } else if (strcmp(argv[1], "bootpart") == 0) { + int dev; + dev = simple_strtoul(argv[2], NULL, 10); + + struct mmc *mmc = find_mmc_device(dev); + u32 bootsize = simple_strtoul(argv[3], NULL, 10); + u32 rpmbsize = simple_strtoul(argv[4], NULL, 10); + + if (!mmc) { + printf("no mmc device at slot %x\n", dev); + return 1; + } + + if (IS_SD(mmc)) { + printf("It is not a EMMC device\n"); + return 1; + } + + if (0 == mmc_boot_partition_size_change(mmc, + bootsize, rpmbsize)) { + printf("EMMC boot partition Size %d MB\n", bootsize); + printf("EMMC RPMB partition Size %d MB\n", rpmbsize); + return 0; + } else { + printf("EMMC boot partition Size change Failed.\n"); + return 1; + } }
if (strcmp(argv[1], "read") == 0) @@ -318,5 +397,9 @@ U_BOOT_CMD( "mmc rescan\n" "mmc part - lists available partition on current mmc device\n" "mmc dev [dev] [part] - show or set current mmc device [partition]\n" - "mmc list - lists available devices"); + "mmc list - lists available devices\n" + "mmc open <device num> - opens the specified device\n" + "mmc close <device num> - closes the specified device\n" + "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n" + " - change sizes of boot and RPMB partions of specified device\n"); #endif

Dear Amar,
In message 1356709972-26549-10-git-send-email-amarendra.xt@samsung.com you wrote:
This patch adds commands to open, close and create partitions on EMMC
In which way are partitions on MC devices special, compare to partitions on other storage devies?
I mean, does it reeally make sense to create a (E?) MMC specific command here, instead of providing general partition support hat can also be used on other storage devices?
Best regards,
Wolfgang Denk

Dear Wolfgang,
Thanks for the review comments. I would like to clarify that this patch resizes EMMC partitions. But does not create partitions. I think the statement *"..close and create partitions on EMMC"* was misleading, which I corrected in latest patch set.
The EMMC4.4 chips are provided with 2 boot partitons and 1 RPMB partition. This patch merely deals with resizing Boot partitions & RPMB partition, by sending proper commands to EMMC chip.
Thanks & Regards Amarendra Reddy.
On 28 December 2012 21:11, Wolfgang Denk wd@denx.de wrote:
Dear Amar,
In message 1356709972-26549-10-git-send-email-amarendra.xt@samsung.com you wrote:
This patch adds commands to open, close and create partitions on EMMC
In which way are partitions on MC devices special, compare to partitions on other storage devies?
I mean, does it reeally make sense to create a (E?) MMC specific command here, instead of providing general partition support hat can also be used on other storage devices?
Best regards,
Wolfgang Denk
-- DENX Software Engineering GmbH, MD: Wolfgang Denk & Detlev Zundel HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de "Never face facts; if you do, you'll never get up in the morning."
- Marlo Thomas
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot

Dear Amarendra Reddy,
In message CAPbRUm=2t8=mOJZEWV98eQ15nV8Rqo0SbJXWM7mzJ+ZFT2qe9A@mail.gmail.com you wrote:
Thanks for the review comments. I would like to clarify that this patch resizes EMMC partitions. But does not create partitions. I think the statement *"..close and create partitions on EMMC"* was misleading, which I corrected in latest patch set.
The EMMC4.4 chips are provided with 2 boot partitons and 1 RPMB partition. This patch merely deals with resizing Boot partitions & RPMB partition, by sending proper commands to EMMC chip.
I see, but I still think that instead of adding (E)MMC specific partition handling, we should instead start and add a generc command to create/change/delete partitions, and then provide the (E)MMC specific implementation for it. This way we can later add partition handling for other storage media if someone needs this. Otherwise we would have a growing number of completely separate implementations, with incomplatible user interfaces and all the other maintenance nightmares this would cause.
That means the core of your implementation will remain the same, just the command interface should be made generic so it can be extended to add support for other storage devices.
Best regards,
Wolfgang Denk
participants (3)
-
Amar
-
Amarendra Reddy
-
Wolfgang Denk