public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and
@ 2012-12-31 10:58 Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC Amar
                   ` (8 more replies)
  0 siblings, 9 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch set enables and initialises DWMMC for Exynos5250 on SMDK5250.
Adds driver changes required for DWMMC.
Adds FDT support for DWMMC.
Adds EMMC boot support 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" present at the following link 
http://comments.gmane.org/gmane.comp.boot-loaders.u-boot/149991

Changes from V1:
        1)Corrected in response to review comments.
        2)Created separate board files for FDT and non-FDT versions.
        3)Added binding file for DWMMC device node.
	4)Removed the propname 'index' from device node.
	5)Prefixed the vendor name 'samsung' before propname in device node.
	6)Ensured to have same signature for the function exynos_dwmci_init() 
	for both FDT and non-FDT versions.
        7)EMMC clock setting has been moved from spl_boot.c to clock_init.c.

Changes from V2:
        1)Updation of commit message and resubmition of proper patch set.

Amar (9):
  FDT: Add compatible string for DWMMC
  EXYNOS5: FDT: Add DWMMC device node data
  DWMMC: Initialise dwmci and resolve EMMC read write issues
  EXYNOS5: DWMMC: Added dt support for DWMMC
  EXYNOS5: DWMMC: API to set mmc clock divisor
  SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT
  MMC: APIs to support creation of boot partition
  SMDK5250: Enable EMMC booting
  COMMON: MMC: Command to support EMMC booting and boot partition
    creation

 arch/arm/cpu/armv7/exynos/clock.c         |  38 ++++-
 arch/arm/dts/exynos5250.dtsi              |  32 ++++
 arch/arm/include/asm/arch-exynos/clk.h    |   4 +
 arch/arm/include/asm/arch-exynos/dwmmc.h  |   4 +
 board/samsung/dts/exynos5250-smdk5250.dts |  22 +++
 board/samsung/smdk5250/Makefile           |   4 +
 board/samsung/smdk5250/clock_init.c       |  15 ++
 board/samsung/smdk5250/clock_init.h       |   5 +
 board/samsung/smdk5250/exynos5-dt.c       | 242 ++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c         |  99 ++++++------
 board/samsung/smdk5250/spl_boot.c         |  52 ++++++-
 common/cmd_mmc.c                          |  84 ++++++++++-
 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, 827 insertions(+), 75 deletions(-)
 create mode 100644 board/samsung/smdk5250/exynos5-dt.c
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt

-- 
1.8.0

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
@ 2012-12-31 10:58 ` Amar
  2012-12-31 12:35   ` Kyungmin Park
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 2/9] EXYNOS5: FDT: Add DWMMC device node data Amar
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

Add required compatible information for DWMMC driver.

Changes from V1:
	No change.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Amar <amarendra.xt@samsung.com>
Acked-by: Simon Glass <sjg@chromium.org>
---
 include/fdtdec.h | 1 +
 lib/fdtdec.c     | 1 +
 2 files changed, 2 insertions(+)

diff --git a/include/fdtdec.h b/include/fdtdec.h
index ce10bf4..dcd4142 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -76,6 +76,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 aa75710..646d5d6 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)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 2/9] EXYNOS5: FDT: Add DWMMC device node data
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC Amar
@ 2012-12-31 10:58 ` Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues Amar
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch adds DWMMC device node data for exynos5.
This patch also adds binding file for DWMMC device node.

Changes from V1:
	1)Added binding file for DWMMC device node at the location
	"doc/device-tree-bindings/exynos/dwmmc.txt".
	2)Removed the propname 'index' from device node.
	3)Prefixed the vendor name 'samsung' before propname in device node.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Amar <amarendra.xt@samsung.com>X
---
 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 at 12200000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+	};
+
+	dwmmc at 12210000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12210000 0x1000>;
+		interrupts = <0 76 0>;
+	};
+
+	dwmmc at 12220000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12220000 0x1000>;
+		interrupts = <0 77 0>;
+	};
+
+	dwmmc at 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 at 12d40000";
 		spi3 = "/spi at 131a0000";
 		spi4 = "/spi at 131b0000";
+		dwmmc0 = "/dwmmc at 12200000";
+		dwmmc1 = "/dwmmc at 12210000";
+		dwmmc2 = "/dwmmc at 12220000";
+		dwmmc3 = "/dwmmc at 12230000";
 	};
 
 	sromc at 12250000 {
@@ -59,4 +63,22 @@
 			compatible = "wolfson,wm8994-codec";
 		};
 	};
+
+	dwmmc at 12200000 {
+		samsung,bus-width = <8>;
+		samsung,timing = <1 3 3>;
+	};
+
+	dwmmc at 12210000 {
+		status = "disabled";
+	};
+
+	dwmmc at 12220000 {
+		samsung,bus-width = <4>;
+		samsung,timing = <1 2 3>;
+	};
+
+	dwmmc at 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.
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 2/9] EXYNOS5: FDT: Add DWMMC device node data Amar
@ 2012-12-31 10:58 ` Amar
  2013-01-02  5:12   ` Jaehoon Chung
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC Amar
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch enumerates dwmci and set auto stop command during
dwmci initialisation.
EMMC read/write is not happening in current implementation
due to improper fifo size computation. Hence Modified the fifo size
computation to resolve EMMC read write issues.

Changes from V1:
	1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header file.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Amar <amarendra.xt@samsung.com>
---
 drivers/mmc/dw_mmc.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 4070d4e..d8fa1a2 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -136,6 +136,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 			return TIMEOUT;
 		}
 		timeout--;
+		mdelay(1);
 	}
 
 	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -314,7 +315,7 @@ static void dwmci_set_ios(struct mmc *mmc)
 static int dwmci_init(struct mmc *mmc)
 {
 	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
-	u32 fifo_size, fifoth_val;
+	u32 fifo_size, fifoth_val, ier;
 
 	dwmci_writel(host, DWMCI_PWREN, 1);
 
@@ -323,6 +324,14 @@ static int dwmci_init(struct mmc *mmc)
 		return -1;
 	}
 
+	/* Enumerate at 400KHz */
+	dwmci_setup_bus(host, mmc->f_min);
+
+	/* Set auto stop command */
+	ier = dwmci_readl(host, DWMCI_CTRL);
+	ier |= (1<<10);
+	dwmci_writel(host, DWMCI_CTRL, ier);
+
 	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
 	dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -332,10 +341,11 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
 	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+	fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
 	if (host->fifoth_val)
 		fifoth_val = host->fifoth_val;
 	else
-		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
+		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 - 1) |
 			TX_WMARK(fifo_size/2);
 	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
 
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (2 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues Amar
@ 2012-12-31 10:58 ` Amar
  2013-01-02  5:20   ` Jaehoon Chung
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor Amar
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch adds FDT support for DWMMC, by reading the DWMMC node data
from the device tree and initialising DWMMC channels as per data
obtained from the node.

Changes from V1:
	1)Updated code to have same signature for the function
	exynos_dwmci_init() for both FDT and non-FDT versions.
	2)Updated code to pass device_id parameter to the function
	exynos5_mmc_set_clk_div() instead of index.
	3)Updated code to decode the value of "samsung,width" from FDT.
	4)Channel index is computed instead of getting from FDT.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

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 |   4 ++
 drivers/mmc/exynos_dw_mmc.c              | 116 +++++++++++++++++++++++++++++--
 include/dwmmc.h                          |   4 ++
 3 files changed, 117 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h
index 8acdf9b..40dcc7b 100644
--- a/arch/arm/include/asm/arch-exynos/dwmmc.h
+++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
@@ -29,8 +29,12 @@
 
 int exynos_dwmci_init(u32 regbase, int bus_width, int index);
 
+#ifdef CONFIG_OF_CONTROL
+unsigned int exynos_dwmmc_init(const void *blob);
+#else
 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);
 }
+#endif
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;
 
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (3 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC Amar
@ 2012-12-31 10:58 ` Amar
  2013-01-02  3:31   ` Jaehoon Chung
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 6/9] SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT Amar
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This API computes the divisor value based on MPLL clock and
writes it into the FSYS1 register.

Changes from V1:
	1)Updated the function exynos5_mmc_set_clk_div() to receive
	'device_i'd as input parameter instead of 'index'.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Amar <amarendra.xt@samsung.com>
---
 arch/arm/cpu/armv7/exynos/clock.c      | 38 ++++++++++++++++++++++++++++++++--
 arch/arm/include/asm/arch-exynos/clk.h |  4 ++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
index 973b84e..cd42689 100644
--- a/arch/arm/cpu/armv7/exynos/clock.c
+++ b/arch/arm/cpu/armv7/exynos/clock.c
@@ -490,7 +490,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;
@@ -539,7 +539,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;
@@ -659,6 +659,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 1935b0b..2fd7c3e 100644
--- a/arch/arm/include/asm/arch-exynos/clk.h
+++ b/arch/arm/include/asm/arch-exynos/clk.h
@@ -29,6 +29,9 @@
 #define VPLL	4
 #define BPLL	5
 
+#define FSYS1_MMC0_DIV_MASK	0xff0f
+#define FSYS1_MMC0_DIV_VAL	0x0701
+
 unsigned long get_pll_clk(int pllreg);
 unsigned long get_arm_clk(void);
 unsigned long get_i2c_clk(void);
@@ -36,6 +39,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);
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 6/9] SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (4 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor Amar
@ 2012-12-31 10:58 ` Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 7/9] MMC: APIs to support resize of EMMC boot partition Amar
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch enables and initialises DWMMC for SMDK5250.
Supports both FDT and non-FDT. This patch creates a new file
'exynos5-dt.c' meant for FDT support.
        exynos5-dt.c:   This file shall contain all code which supports FDT.
                        Any addition of FDT support for any module needs to be
                        added in this file.
        smdk5250.c:     This file shall contain the code which supports non-FDT.
                        version. Any addition of non-FDT support for any module
                        needs to be added in this file.
                        May be, the file smdk5250.c can be removed in near future
                        when non-FDT is not required.

The Makefile is updated to compile only one of the files
exynos5-dt.c / smdk5250.c based on FDT configuration.

NOTE:
Please note that all additions corresponding to FDT need to be added into the
file exynos5-dt.c.
At same time if non-FDT support is required then add the corresponding
updations into smdk5250.c.

Changes from V1:
        1)A new file 'exynos5-dt.c' is created meant for FDT support
        2)Makefile is updated to compile only one of the files
        exynos5-dt.c / smdk5250.c based on FDT configuration

Changes from V2:
        1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Amar <amarendra.xt@samsung.com>
---
 board/samsung/smdk5250/Makefile     |   4 +
 board/samsung/smdk5250/exynos5-dt.c | 242 ++++++++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c   |  97 +++++++--------
 include/configs/exynos5250-dt.h     |   2 +
 include/i2c.h                       |   2 +
 5 files changed, 292 insertions(+), 55 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..da539ca
--- /dev/null
+++ b/board/samsung/smdk5250/exynos5-dt.c
@@ -0,0 +1,242 @@
+/*
+ * 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 <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+	gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
+#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;
+}
+
+#if defined(CONFIG_POWER)
+int power_init_board(void)
+{
+	if (pmic_init(I2C_PMIC))
+		return -1;
+	else
+		return 0;
+}
+#endif
+
+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 73c3ec0..e0fec11 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>
@@ -95,59 +96,13 @@ 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
 	u32 smc_bw_conf, smc_bc_conf;
 	struct fdt_sromc config;
 	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;
@@ -160,7 +115,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) {
@@ -199,16 +153,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
 
@@ -243,6 +212,24 @@ static int board_uart_init(void)
 	return 0;
 }
 
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+static int board_i2c_init(void)
+{
+	int i, err;
+
+	for (i = 0; i < CONFIG_MAX_I2C_NUM; i++) {
+		err = exynos_pinmux_config((PERIPH_ID_I2C0 + i),
+						PINMUX_FLAG_NONE);
+		if (err) {
+			debug("I2C%d not configured\n", (PERIPH_ID_I2C0 + i));
+			return err;
+		}
+	}
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+	return 0;
+}
+#endif
+
 #ifdef CONFIG_BOARD_EARLY_INIT_F
 int board_early_init_f(void)
 {
@@ -253,7 +240,7 @@ int board_early_init_f(void)
 		return err;
 	}
 #ifdef CONFIG_SYS_I2C_INIT_BOARD
-	board_i2c_init(gd->fdt_blob);
+	board_i2c_init();
 #endif
 	return err;
 }
diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h
index 59182f4..6ce73dc 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
 
diff --git a/include/i2c.h b/include/i2c.h
index c60d075..0944141 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -263,6 +263,7 @@ extern int get_multi_sda_pin(void);
 extern int multi_i2c_init(void);
 #endif
 
+#ifdef CONFIG_OF_CONTROL
 /**
  * Get FDT values for i2c bus.
  *
@@ -270,6 +271,7 @@ extern int multi_i2c_init(void);
  * @return the number of I2C bus
  */
 void board_i2c_init(const void *blob);
+#endif
 
 /**
  * Find the I2C bus number by given a FDT I2C node.
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 7/9] MMC: APIs to support resize of EMMC boot partition
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (5 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 6/9] SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT Amar
@ 2012-12-31 10:58 ` Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 8/9] SMDK5250: Enable EMMC booting Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 9/9] COMMON: MMC: Command to support EMMC booting and to Amar
  8 siblings, 0 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch adds APIs to open, close and to resize boot partiton for EMMC.

Changes from V1:
	New patch.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

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 72e8ce6..8175b49 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -1327,3 +1327,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@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)
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 8/9] SMDK5250: Enable EMMC booting
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (6 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 7/9] MMC: APIs to support resize of EMMC boot partition Amar
@ 2012-12-31 10:58 ` Amar
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 9/9] COMMON: MMC: Command to support EMMC booting and to Amar
  8 siblings, 0 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch adds support for EMMC booting on SMDK5250.

Changes from V1:
	1)Updated spl_boot.c file to maintain irom pointer table
	instead of using the #define values defined in header file.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Amar <amarendra.xt@samsung.com>
---
 board/samsung/smdk5250/clock_init.c | 15 +++++++++++
 board/samsung/smdk5250/clock_init.h |  5 ++++
 board/samsung/smdk5250/spl_boot.c   | 52 ++++++++++++++++++++++++++++++++-----
 3 files changed, 65 insertions(+), 7 deletions(-)

diff --git a/board/samsung/smdk5250/clock_init.c b/board/samsung/smdk5250/clock_init.c
index c009ae5..154993c 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,17 @@ 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 div_mmc;
+
+	div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK;
+	div_mmc |= FSYS1_MMC0_DIV_VAL;
+	writel(div_mmc, (unsigned int) &clk->div_fsys1);
+}
diff --git a/board/samsung/smdk5250/clock_init.h b/board/samsung/smdk5250/clock_init.h
index f751bcb..20a1d47 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..906e197 100644
--- a/board/samsung/smdk5250/spl_boot.c
+++ b/board/samsung/smdk5250/spl_boot.c
@@ -23,16 +23,38 @@
 #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 */
+u32 irom_ptr_table[] = {
+	[MMC_INDEX] = 0x02020030,	/* iROM Function Pointer-SDMMC boot */
+	[EMMC44_INDEX] = 0x02020044,	/* iROM Function Pointer-EMMC4.4 boot*/
+	[EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
+						-EMMC4.4 end boot operation */
+	[SPI_INDEX] = 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 +62,39 @@ 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);
+	/* read Operation Mode ststus register to find the bootmode */
 	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:
+		/* Set the FSYS1 clock divisor value for EMMC boot */
+		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;
 	}
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 9/9] COMMON: MMC: Command to support EMMC booting and to
  2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
                   ` (7 preceding siblings ...)
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 8/9] SMDK5250: Enable EMMC booting Amar
@ 2012-12-31 10:58 ` Amar
  8 siblings, 0 replies; 21+ messages in thread
From: Amar @ 2012-12-31 10:58 UTC (permalink / raw)
  To: u-boot

This patch adds commands to open, close and resize boot partitions on EMMC.

Changes from V1:
	1)Combined the common piece of code between 'open' and 'close'
	operations.

Changes from V2:
	1)Updation of commit message and resubmition of proper patch set.

Signed-off-by: Amar <amarendra.xt@samsung.com>
---
 common/cmd_mmc.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 7dacd51..1dabb5b 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -248,6 +248,84 @@ 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);
+
+		u32 bootsize = simple_strtoul(argv[3], NULL, 10);
+		u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
+		struct mmc *mmc = find_mmc_device(dev);
+		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;
+		}
 	}
 
 	state = MMC_INVALID;
@@ -317,5 +395,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
-- 
1.8.0

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC Amar
@ 2012-12-31 12:35   ` Kyungmin Park
  0 siblings, 0 replies; 21+ messages in thread
From: Kyungmin Park @ 2012-12-31 12:35 UTC (permalink / raw)
  To: u-boot

Hi,


On Mon, Dec 31, 2012 at 7:58 PM, Amar <amarendra.xt@samsung.com> wrote:
> Add required compatible information for DWMMC driver.
>
> Changes from V1:
>         No change.
>
> Changes from V2:
>         1)Updation of commit message and resubmition of proper patch set.
>
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> Signed-off-by: Amar <amarendra.xt@samsung.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
>  include/fdtdec.h | 1 +
>  lib/fdtdec.c     | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/include/fdtdec.h b/include/fdtdec.h
> index ce10bf4..dcd4142 100644
> --- a/include/fdtdec.h
> +++ b/include/fdtdec.h
> @@ -76,6 +76,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 */

You already know that exynos4 series also have DWMMC controller and
it's strange to use this value at exynos4 series.
so can you use 'SAMSUNG_EXYNOS_DWMMC'?

Thank you,
Kyungmin Park
>
>         COMPAT_COUNT,
>  };
> diff --git a/lib/fdtdec.c b/lib/fdtdec.c
> index aa75710..646d5d6 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)
> --
> 1.8.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor Amar
@ 2013-01-02  3:31   ` Jaehoon Chung
  2013-01-03  6:24     ` Amarendra Reddy
  0 siblings, 1 reply; 21+ messages in thread
From: Jaehoon Chung @ 2013-01-02  3:31 UTC (permalink / raw)
  To: u-boot

Hi Amar,

On 12/31/2012 07:58 PM, Amar wrote:
> This API computes the divisor value based on MPLL clock and
> writes it into the FSYS1 register.
> 
> Changes from V1:
> 	1)Updated the function exynos5_mmc_set_clk_div() to receive
> 	'device_i'd as input parameter instead of 'index'.
> 
> Changes from V2:
> 	1)Updation of commit message and resubmition of proper patch set.
> 
> Signed-off-by: Amar <amarendra.xt@samsung.com>
> ---
>  arch/arm/cpu/armv7/exynos/clock.c      | 38 ++++++++++++++++++++++++++++++++--
>  arch/arm/include/asm/arch-exynos/clk.h |  4 ++++
>  2 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c
> index 973b84e..cd42689 100644
> --- a/arch/arm/cpu/armv7/exynos/clock.c
> +++ b/arch/arm/cpu/armv7/exynos/clock.c
> @@ -490,7 +490,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;
> @@ -539,7 +539,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;
> @@ -659,6 +659,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)
Why return the int type?
> +{
> +	struct exynos5_clock *clk =
> +		(struct exynos5_clock *)samsung_get_base_clock();
> +	unsigned int addr;
> +	unsigned int clock;
> +	unsigned int tmp;
> +	unsigned int i;
Can't use unsigned int addr, clock....? We can save the line.
> +
> +	/* 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;
FSYS1_MMC0_DIV_MASK? then case of MMC2?
It is wrong macro name..You also used the clk->div_fsys2..
> +	for (i = 0; i <= 0xf; i++) {
> +		if ((clock / (i + 1)) <= 400) {
> +			writel(tmp | i << 0, addr);
> +			break;
> +		}
> +	}
> +	return 0;
> +}
I didn't understand this function(exynos5_mmc_set_clk_div?).
What purpose? I think good that proper to use the "div" as argument.
void exynos5_mmc_set_clk(int dev_id, unsigned int div).
> +
>  /* 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 1935b0b..2fd7c3e 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -29,6 +29,9 @@
>  #define VPLL	4
>  #define BPLL	5
>  
> +#define FSYS1_MMC0_DIV_MASK	0xff0f
> +#define FSYS1_MMC0_DIV_VAL	0x0701
> +
>  unsigned long get_pll_clk(int pllreg);
>  unsigned long get_arm_clk(void);
>  unsigned long get_i2c_clk(void);
> @@ -36,6 +39,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);
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues Amar
@ 2013-01-02  5:12   ` Jaehoon Chung
  2013-01-03  7:45     ` Amarendra Reddy
  0 siblings, 1 reply; 21+ messages in thread
From: Jaehoon Chung @ 2013-01-02  5:12 UTC (permalink / raw)
  To: u-boot

On 12/31/2012 07:58 PM, Amar wrote:
> This patch enumerates dwmci and set auto stop command during
> dwmci initialisation.
> EMMC read/write is not happening in current implementation
> due to improper fifo size computation. Hence Modified the fifo size
> computation to resolve EMMC read write issues.
What issue for read/write?
> 
> Changes from V1:
> 	1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header file.
> 
> Changes from V2:
> 	1)Updation of commit message and resubmition of proper patch set.
> 
> Signed-off-by: Amar <amarendra.xt@samsung.com>
> ---
>  drivers/mmc/dw_mmc.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 4070d4e..d8fa1a2 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -136,6 +136,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
>  			return TIMEOUT;
>  		}
>  		timeout--;
> +		mdelay(1);
Why add the mdelay(1)? Could you explain to me?
>  	}
>  
>  	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
> @@ -314,7 +315,7 @@ static void dwmci_set_ios(struct mmc *mmc)
>  static int dwmci_init(struct mmc *mmc)
>  {
>  	struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
> -	u32 fifo_size, fifoth_val;
> +	u32 fifo_size, fifoth_val, ier;
>  
>  	dwmci_writel(host, DWMCI_PWREN, 1);
>  
> @@ -323,6 +324,14 @@ static int dwmci_init(struct mmc *mmc)
>  		return -1;
>  	}
>  
> +	/* Enumerate at 400KHz */
> +	dwmci_setup_bus(host, mmc->f_min);
> +
> +	/* Set auto stop command */
> +	ier = dwmci_readl(host, DWMCI_CTRL);
> +	ier |= (1<<10);
Use the define..ex) define DWMCI_CTRL_AUTO_STOP_CMD 	BIT(10)
> +	dwmci_writel(host, DWMCI_CTRL, ier);
If set to auto stop command, then you didn't see any problem?

Best Regards,
Jaehoon Chung
> +
>  	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
>  	dwmci_writel(host, DWMCI_INTMASK, 0);
>  
> @@ -332,10 +341,11 @@ static int dwmci_init(struct mmc *mmc)
>  	dwmci_writel(host, DWMCI_BMOD, 1);
>  
>  	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
> +	fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
>  	if (host->fifoth_val)
>  		fifoth_val = host->fifoth_val;
>  	else
> -		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
> +		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 - 1) |
>  			TX_WMARK(fifo_size/2);
>  	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
>  
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC
  2012-12-31 10:58 ` [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC Amar
@ 2013-01-02  5:20   ` Jaehoon Chung
  2013-01-03  4:32     ` Amarendra Reddy
  0 siblings, 1 reply; 21+ messages in thread
From: Jaehoon Chung @ 2013-01-02  5:20 UTC (permalink / raw)
  To: u-boot

On 12/31/2012 07:58 PM, Amar wrote:
> This patch adds FDT support for DWMMC, by reading the DWMMC node data
> from the device tree and initialising DWMMC channels as per data
> obtained from the node.
> 
> Changes from V1:
> 	1)Updated code to have same signature for the function
> 	exynos_dwmci_init() for both FDT and non-FDT versions.
> 	2)Updated code to pass device_id parameter to the function
> 	exynos5_mmc_set_clk_div() instead of index.
> 	3)Updated code to decode the value of "samsung,width" from FDT.
> 	4)Channel index is computed instead of getting from FDT.
> 
> Changes from V2:
> 	1)Updation of commit message and resubmition of proper patch set.
> 
> 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 |   4 ++
>  drivers/mmc/exynos_dw_mmc.c              | 116 +++++++++++++++++++++++++++++--
>  include/dwmmc.h                          |   4 ++
>  3 files changed, 117 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h b/arch/arm/include/asm/arch-exynos/dwmmc.h
> index 8acdf9b..40dcc7b 100644
> --- a/arch/arm/include/asm/arch-exynos/dwmmc.h
> +++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
> @@ -29,8 +29,12 @@
>  
>  int exynos_dwmci_init(u32 regbase, int bus_width, int index);
>  
> +#ifdef CONFIG_OF_CONTROL
> +unsigned int exynos_dwmmc_init(const void *blob);
> +#else
>  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);
>  }
> +#endif
> 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;
Is it right at every case?
> +
> +	/* 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;
>  
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC
  2013-01-02  5:20   ` Jaehoon Chung
@ 2013-01-03  4:32     ` Amarendra Reddy
  2013-01-03  6:48       ` Jaehoon Chung
  0 siblings, 1 reply; 21+ messages in thread
From: Amarendra Reddy @ 2013-01-03  4:32 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,
Thanks for the comments.
Please find my response below.

Thanks & Regards
Amarendra

On 2 January 2013 10:50, Jaehoon Chung <jh80.chung@samsung.com> wrote:

>  On 12/31/2012 07:58 PM, Amar wrote:
> > This patch adds FDT support for DWMMC, by reading the DWMMC node data
> > from the device tree and initialising DWMMC channels as per data
> > obtained from the node.
> >
> > Changes from V1:
> >       1)Updated code to have same signature for the function
> >       exynos_dwmci_init() for both FDT and non-FDT versions.
> >       2)Updated code to pass device_id parameter to the function
> >       exynos5_mmc_set_clk_div() instead of index.
> >       3)Updated code to decode the value of "samsung,width" from FDT.
> >       4)Channel index is computed instead of getting from FDT.
> >
> > Changes from V2:
> >       1)Updation of commit message and resubmition of proper patch set.
> >
> > 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 |   4 ++
> >  drivers/mmc/exynos_dw_mmc.c              | 116
> +++++++++++++++++++++++++++++--
> >  include/dwmmc.h                          |   4 ++
> >  3 files changed, 117 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/arch-exynos/dwmmc.h
> b/arch/arm/include/asm/arch-exynos/dwmmc.h
> > index 8acdf9b..40dcc7b 100644
> > --- a/arch/arm/include/asm/arch-exynos/dwmmc.h
> > +++ b/arch/arm/include/asm/arch-exynos/dwmmc.h
> > @@ -29,8 +29,12 @@
> >
> >  int exynos_dwmci_init(u32 regbase, int bus_width, int index);
> >
> > +#ifdef CONFIG_OF_CONTROL
> > +unsigned int exynos_dwmmc_init(const void *blob);
> > +#else
> >  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);
> >  }
> > +#endif
> > 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;
> Is it right at every case?
>

Yes, it is right in every case.

Consider the finction "int exynos_dwmci_init(u32 regbase, int bus_width,
int index)"
If the input argument 'index' is between (0-3), then the statement "dev_id
= index + PERIPH_ID_SDMMC0;" works good.

So, the function exynos_dwmci_init(u32 regbase, int bus_width, int index)
is being called as below
1) FDT Case:
The function exynos_dwmmc_init() calls exynos_dwmmc_init()
The dev_id is extracted from arch/arm/dts/exynos5250.dtsi. The dev_id is
nothing but the interrupt number.
dwmmc0 - dev_id = 75
dwmmc1 - dev_id = 76
dwmmc2 - dev_id = 77
dwmmc3 - dev_id = 78

At same time the enum values are (Refer
"arch/arm/include/asm/arch-exynos/periph.h")
PERIPH_ID_SDMMC0 = 75,
PERIPH_ID_SDMMC1,
PERIPH_ID_SDMMC2,
PERIPH_ID_SDMMC3,

 Here "index = dev_id - PERIPH_ID_SDMMC0" works good for all channels
(mmc0 - mmc3)

As proper values are mentioned in arch/arm/dts/exynos5250.dtsi, proper
values of "index" (i.e 0 - 3) will be computed here.

2) Non-FDT case:
The function board_mmc_init() calls exynos_dwmmc_init() as shown below
int board_mmc_init(bd_t *bis)
{
 ....
 ....
        /*EMMC: dwmmc Channel-0 with 8 bit bus width */
        err = exynos_dwmmc_init(0, 8);
}
Here the coder shall ensure to pass proper index number (0 to 3) for porper
working.


>  > +
> > +     /* 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;
> >
> >
>
>  _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2013-01-02  3:31   ` Jaehoon Chung
@ 2013-01-03  6:24     ` Amarendra Reddy
  2013-01-03  6:45       ` Jaehoon Chung
  0 siblings, 1 reply; 21+ messages in thread
From: Amarendra Reddy @ 2013-01-03  6:24 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon

Thanks for the comments.
Please find my response below.

Than

On 2 January 2013 09:01, Jaehoon Chung <jh80.chung@samsung.com> wrote:

> Hi Amar,
>
> On 12/31/2012 07:58 PM, Amar wrote:
> > This API computes the divisor value based on MPLL clock and
> > writes it into the FSYS1 register.
> >
> > Changes from V1:
> >       1)Updated the function exynos5_mmc_set_clk_div() to receive
> >       'device_i'd as input parameter instead of 'index'.
> >
> > Changes from V2:
> >       1)Updation of commit message and resubmition of proper patch set.
> >
> > Signed-off-by: Amar <amarendra.xt@samsung.com>
> > ---
> >  arch/arm/cpu/armv7/exynos/clock.c      | 38
> ++++++++++++++++++++++++++++++++--
> >  arch/arm/include/asm/arch-exynos/clk.h |  4 ++++
> >  2 files changed, 40 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm/cpu/armv7/exynos/clock.c
> b/arch/arm/cpu/armv7/exynos/clock.c
> > index 973b84e..cd42689 100644
> > --- a/arch/arm/cpu/armv7/exynos/clock.c
> > +++ b/arch/arm/cpu/armv7/exynos/clock.c
> > @@ -490,7 +490,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;
> > @@ -539,7 +539,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;
> > @@ -659,6 +659,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)
> Why return the int type?
>
Yes, not required to return. I will update.

> > +{
> > +     struct exynos5_clock *clk =
> > +             (struct exynos5_clock *)samsung_get_base_clock();
> > +     unsigned int addr;
> > +     unsigned int clock;
> > +     unsigned int tmp;
> > +     unsigned int i;
> Can't use unsigned int addr, clock....? We can save the line.
>
Ok.

> > +
> > +     /* 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;
> FSYS1_MMC0_DIV_MASK? then case of MMC2?
> It is wrong macro name..You also used the clk->div_fsys2..
>
Yes, will change the macro name.

> > +     for (i = 0; i <= 0xf; i++) {
> > +             if ((clock / (i + 1)) <= 400) {
> > +                     writel(tmp | i << 0, addr);
> > +                     break;
> > +             }
> > +     }
> > +     return 0;
> > +}
> I didn't understand this function(exynos5_mmc_set_clk_div?).
> What purpose? I think good that proper to use the "div" as argument.
> void exynos5_mmc_set_clk(int dev_id, unsigned int div).


For fixing dwmmc driver, I referred to working code from
"chromiumos/src/third_party/u-boot".
In chromium uboot, during mhci init, the function "clock_set_mshci()" is
called which is in "arch/arm/cpu/armv7/exynos5/clock.c"

Our function "*exynos5_mmc_set_clk_div()"* is same as "*clock_set_mshci()".*

Now coming to 'div' as argument .... we have the below scenarios / questions
1-> What is the value of 'div' to be passed from calling function ?
2-> The value of 'div' needs to be computed in calling function.
3-> As per my understanding, 'div' value depends on values of MPLL clock
and FSYS1/2.
4-> *Question:* Is it OK to put the piece of code which accesses MPLL,
FSYS1, FSYS2 in drivers/mmc/exynos_dw_mmc.c. ?
5-> If we compute 'div' value in "drivers/mmc/exynos_dw_mmc.c", then
there will be duplication of code (Read of FSYS1/2).

Please comment on the above.

> +
>  /* 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 1935b0b..2fd7c3e 100644
> --- a/arch/arm/include/asm/arch-exynos/clk.h
> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> @@ -29,6 +29,9 @@
>  #define VPLL 4
>  #define BPLL 5
>
> +#define FSYS1_MMC0_DIV_MASK  0xff0f
> +#define FSYS1_MMC0_DIV_VAL   0x0701
> +
>  unsigned long get_pll_clk(int pllreg);
>  unsigned long get_arm_clk(void);
>  unsigned long get_i2c_clk(void);
> @@ -36,6 +39,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);
>

 _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2013-01-03  6:24     ` Amarendra Reddy
@ 2013-01-03  6:45       ` Jaehoon Chung
  2013-01-03 11:16         ` Amarendra Reddy
  0 siblings, 1 reply; 21+ messages in thread
From: Jaehoon Chung @ 2013-01-03  6:45 UTC (permalink / raw)
  To: u-boot

Hi Amar,

..snip..
>> I didn't understand this function(exynos5_mmc_set_clk_div?).
>> What purpose? I think good that proper to use the "div" as argument.
>> void exynos5_mmc_set_clk(int dev_id, unsigned int div).
> 
> 
> For fixing dwmmc driver, I referred to working code from
> "chromiumos/src/third_party/u-boot".
> In chromium uboot, during mhci init, the function "clock_set_mshci()" is
> called which is in "arch/arm/cpu/armv7/exynos5/clock.c"
> 
> Our function "*exynos5_mmc_set_clk_div()"* is same as "*clock_set_mshci()".*
> 
> Now coming to 'div' as argument .... we have the below scenarios / questions
> 1-> What is the value of 'div' to be passed from calling function ?
It will be the pre_ratio's value for FSYSx register.

> 2-> The value of 'div' needs to be computed in calling function.
It will be computed before called this function. For example, in dw_mmc.c or exynos_dw_mc.c

> 3-> As per my understanding, 'div' value depends on values of MPLL clock
> and FSYS1/2.
Right..but it will be changed the source clock. MMC/SD can use the every source clock.

> 4-> *Question:* Is it OK to put the piece of code which accesses MPLL,
> FSYS1, FSYS2 in drivers/mmc/exynos_dw_mmc.c. ?
Sure..we can use the get_mmc_clk/set_mmc_clk. then we can get source clock value.
and compute the div value for request clock.

> 5-> If we compute 'div' value in "drivers/mmc/exynos_dw_mmc.c", then
> there will be duplication of code (Read of FSYS1/2).
What code is duplication? Could you explain to me more?
Only need to compute the div value in exynos_dw_mmc.c.
why need to compute into here?

Best Regards,
Jaehoon Chung
> 
> Please comment on the above.
> 
>> +
>>  /* 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 1935b0b..2fd7c3e 100644
>> --- a/arch/arm/include/asm/arch-exynos/clk.h
>> +++ b/arch/arm/include/asm/arch-exynos/clk.h
>> @@ -29,6 +29,9 @@
>>  #define VPLL 4
>>  #define BPLL 5
>>
>> +#define FSYS1_MMC0_DIV_MASK  0xff0f
>> +#define FSYS1_MMC0_DIV_VAL   0x0701
>> +
>>  unsigned long get_pll_clk(int pllreg);
>>  unsigned long get_arm_clk(void);
>>  unsigned long get_i2c_clk(void);
>> @@ -36,6 +39,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);
>>
> 
>  _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
>>
> 
> 
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC
  2013-01-03  4:32     ` Amarendra Reddy
@ 2013-01-03  6:48       ` Jaehoon Chung
  0 siblings, 0 replies; 21+ messages in thread
From: Jaehoon Chung @ 2013-01-03  6:48 UTC (permalink / raw)
  To: u-boot

Hi Amar,

..snip..
>>>  }
>>>
>>>  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;
>> Is it right at every case?
>>
> 
> Yes, it is right in every case.
> 
> Consider the finction "int exynos_dwmci_init(u32 regbase, int bus_width,
> int index)"
> If the input argument 'index' is between (0-3), then the statement "dev_id
> = index + PERIPH_ID_SDMMC0;" works good.
> 
> So, the function exynos_dwmci_init(u32 regbase, int bus_width, int index)
> is being called as below
> 1) FDT Case:
> The function exynos_dwmmc_init() calls exynos_dwmmc_init()
> The dev_id is extracted from arch/arm/dts/exynos5250.dtsi. The dev_id is
> nothing but the interrupt number.
> dwmmc0 - dev_id = 75
> dwmmc1 - dev_id = 76
> dwmmc2 - dev_id = 77
> dwmmc3 - dev_id = 78
> 
> At same time the enum values are (Refer
> "arch/arm/include/asm/arch-exynos/periph.h")
> PERIPH_ID_SDMMC0 = 75,
> PERIPH_ID_SDMMC1,
> PERIPH_ID_SDMMC2,
> PERIPH_ID_SDMMC3,
> 
>  Here "index = dev_id - PERIPH_ID_SDMMC0" works good for all channels
> (mmc0 - mmc3)
> 
> As proper values are mentioned in arch/arm/dts/exynos5250.dtsi, proper
> values of "index" (i.e 0 - 3) will be computed here.
> 
> 2) Non-FDT case:
> The function board_mmc_init() calls exynos_dwmmc_init() as shown below
> int board_mmc_init(bd_t *bis)
> {
>  ....
>  ....
>         /*EMMC: dwmmc Channel-0 with 8 bit bus width */
>         err = exynos_dwmmc_init(0, 8);
> }
> Here the coder shall ensure to pass proper index number (0 to 3) for porper
> working.

Sorry, i confused the dev_id and dev_index..Thank you for explanation.

Best Regards,
Jaehoon Chung
> 
> 
>>  > +
>>> +     /* 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;
>>>
>>>
>>
>>  _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot
>>
> 
> 
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
> 

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues
  2013-01-02  5:12   ` Jaehoon Chung
@ 2013-01-03  7:45     ` Amarendra Reddy
  0 siblings, 0 replies; 21+ messages in thread
From: Amarendra Reddy @ 2013-01-03  7:45 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,

Thanks for the comments.
Please find the response below.

Thanks & Regards
Amarendra Reddy


On 2 January 2013 10:42, Jaehoon Chung <jh80.chung@samsung.com> wrote:

> On 12/31/2012 07:58 PM, Amar wrote:
> > This patch enumerates dwmci and set auto stop command during
> > dwmci initialisation.
> > EMMC read/write is not happening in current implementation
> > due to improper fifo size computation. Hence Modified the fifo size
> > computation to resolve EMMC read write issues.
> What issue for read/write?

After bootup, the command 'mmcinfo' was working fine. It displays the EMMC
device properties(Manufacturer,OEM, SD version ... ) properly.
But the EMMC read / write was not happening. Then I referred to chromium
uboot working code and observed that FIFO size configuraion is missing in
our code.
After configuring FIFO size, read / write happened properly. That is what I
meant.

>
> Changes from V1:
>       1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header
file.
>
> Changes from V2:
>       1)Updation of commit message and resubmition of proper patch set.
>
> Signed-off-by: Amar <amarendra.xt@samsung.com>
> ---
>  drivers/mmc/dw_mmc.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
> index 4070d4e..d8fa1a2 100644
> --- a/drivers/mmc/dw_mmc.c
> +++ b/drivers/mmc/dw_mmc.c
> @@ -136,6 +136,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct
mmc_cmd *cmd,
>                       return TIMEOUT;
>               }
>               timeout--;
> +             mdelay(1);

> Why add the mdelay(1)? Could you explain to me?

Again this one also I added after referring to chromium uboot working code.

Without mdelay(), there was a problem while writing into EMMC boot
partitions.
*Problem Description:* When I write into EMMC boot partition,
-> It fails in first attempt and displays the error *"Timeout on data
busy". *
-> Immediately it retries and succeeds in second attempt.

To avoid the above problem I added mdelay().


> >       }
> >
> >       dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
> > @@ -314,7 +315,7 @@ static void dwmci_set_ios(struct mmc *mmc)
> >  static int dwmci_init(struct mmc *mmc)
> >  {
> >       struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
> > -     u32 fifo_size, fifoth_val;
> > +     u32 fifo_size, fifoth_val, ier;
> >
> >       dwmci_writel(host, DWMCI_PWREN, 1);
> >
> > @@ -323,6 +324,14 @@ static int dwmci_init(struct mmc *mmc)
> >               return -1;
> >       }
> >
> > +     /* Enumerate at 400KHz */
> > +     dwmci_setup_bus(host, mmc->f_min);
> > +
> > +     /* Set auto stop command */
> > +     ier = dwmci_readl(host, DWMCI_CTRL);
> > +     ier |= (1<<10);
> Use the define..ex) define DWMCI_CTRL_AUTO_STOP_CMD     BIT(10)
>
Ok.

> > +     dwmci_writel(host, DWMCI_CTRL, ier);
> If set to auto stop command, then you didn't see any problem?
>
Actually, it works fine even without setting auto stop command.
Initially I referred to the working code from chromium uboot, and tried to
maintain all our dwmci init code inline with chromium uboot.
Hence I added "set auto command".


> Best Regards,
> Jaehoon Chung
> > +
> >       dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
> >       dwmci_writel(host, DWMCI_INTMASK, 0);
> >
> > @@ -332,10 +341,11 @@ static int dwmci_init(struct mmc *mmc)
> >       dwmci_writel(host, DWMCI_BMOD, 1);
> >
> >       fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
> > +     fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
> >       if (host->fifoth_val)
> >               fifoth_val = host->fifoth_val;
> >       else
> > -             fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
> > +             fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 - 1) |
> >                       TX_WMARK(fifo_size/2);
> >       dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
> >
> >
>
>  _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2013-01-03  6:45       ` Jaehoon Chung
@ 2013-01-03 11:16         ` Amarendra Reddy
  2013-01-03 14:34           ` Amarendra Reddy
  0 siblings, 1 reply; 21+ messages in thread
From: Amarendra Reddy @ 2013-01-03 11:16 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,
Thanks for the comments.
Please find my response below.

Thanks & Regards
Amarendra



On 3 January 2013 12:15, Jaehoon Chung <jh80.chung@samsung.com> wrote:

> Hi Amar,
>
> ..snip..
> >> I didn't understand this function(exynos5_mmc_set_clk_div?).
> >> What purpose? I think good that proper to use the "div" as argument.
> >> void exynos5_mmc_set_clk(int dev_id, unsigned int div).
> >
> >
> > For fixing dwmmc driver, I referred to working code from
> > "chromiumos/src/third_party/u-boot".
> > In chromium uboot, during mhci init, the function "clock_set_mshci()" is
> > called which is in "arch/arm/cpu/armv7/exynos5/clock.c"
> >
> > Our function "*exynos5_mmc_set_clk_div()"* is same as
> "*clock_set_mshci()".*
> >
> > Now coming to 'div' as argument .... we have the below scenarios /
> questions
> > 1-> What is the value of 'div' to be passed from calling function ?
> It will be the pre_ratio's value for FSYSx register.
>
OK.

>
> > 2-> The value of 'div' needs to be computed in calling function.
> It will be computed before called this function. For example, in dw_mmc.c
> or exynos_dw_mc.c
>


> OK.
> > 3-> As per my understanding, 'div' value depends on values of MPLL clock
> > and FSYS1/2.
> Right..but it will be changed the source clock. MMC/SD can use the every
> source clock.
>
> OK.

> > 4-> *Question:* Is it OK to put the piece of code which accesses MPLL,
> > FSYS1, FSYS2 in drivers/mmc/exynos_dw_mmc.c. ?
> Sure..we can use the get_mmc_clk/set_mmc_clk. then we can get source clock
> value.
> and compute the div value for request clock.
>


> OK. I will change accordingly.
> > 5-> If we compute 'div' value in "drivers/mmc/exynos_dw_mmc.c", then
> > there will be duplication of code (Read of FSYS1/2).
> What code is duplication? Could you explain to me more?
> Only need to compute the div value in exynos_dw_mmc.c.
> why need to compute into here?
> Sorry..there is no duplication. I thought that reading fsys1/2 will be
> done at two places.
> Best Regards,
> Jaehoon Chung
>  >
> > Please comment on the above.
> >
> >> +
> >>  /* 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 1935b0b..2fd7c3e 100644
> >> --- a/arch/arm/include/asm/arch-exynos/clk.h
> >> +++ b/arch/arm/include/asm/arch-exynos/clk.h
> >> @@ -29,6 +29,9 @@
> >>  #define VPLL 4
> >>  #define BPLL 5
> >>
> >> +#define FSYS1_MMC0_DIV_MASK  0xff0f
> >> +#define FSYS1_MMC0_DIV_VAL   0x0701
> >> +
> >>  unsigned long get_pll_clk(int pllreg);
> >>  unsigned long get_arm_clk(void);
> >>  unsigned long get_i2c_clk(void);
> >> @@ -36,6 +39,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);
> >>
> >
> >  _______________________________________________
> >> U-Boot mailing list
> >> U-Boot at lists.denx.de
> >> http://lists.denx.de/mailman/listinfo/u-boot
> >>
> >
> >
> >
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot at lists.denx.de
> > http://lists.denx.de/mailman/listinfo/u-boot
> >
>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor
  2013-01-03 11:16         ` Amarendra Reddy
@ 2013-01-03 14:34           ` Amarendra Reddy
  0 siblings, 0 replies; 21+ messages in thread
From: Amarendra Reddy @ 2013-01-03 14:34 UTC (permalink / raw)
  To: u-boot

Hi Jaehoon,
 Thanks for the comments.
Please find my response below.

Thanks & Regards
Amarendra


On 3 January 2013 16:46, Amarendra Reddy <amar.lavanuru@gmail.com> wrote:

> Hi Jaehoon,
>  Thanks for the comments.
> Please find my response below.
>
> Thanks & Regards
> Amarendra
>
>
>
>  On 3 January 2013 12:15, Jaehoon Chung <jh80.chung@samsung.com> wrote:
>
>> Hi Amar,
>>
>> ..snip..
>> >> I didn't understand this function(exynos5_mmc_set_clk_div?).
>> >> What purpose? I think good that proper to use the "div" as argument.
>> >> void exynos5_mmc_set_clk(int dev_id, unsigned int div).
>> >
>> >
>> > For fixing dwmmc driver, I referred to working code from
>> > "chromiumos/src/third_party/u-boot".
>> > In chromium uboot, during mhci init, the function "clock_set_mshci()" is
>> > called which is in "arch/arm/cpu/armv7/exynos5/clock.c"
>> >
>> > Our function "*exynos5_mmc_set_clk_div()"* is same as
>> "*clock_set_mshci()".*
>> >
>> > Now coming to 'div' as argument .... we have the below scenarios /
>> questions
>> > 1-> What is the value of 'div' to be passed from calling function ?
>> It will be the pre_ratio's value for FSYSx register.
>>
> OK.
>
>>
>> > 2-> The value of 'div' needs to be computed in calling function.
>> It will be computed before called this function. For example, in dw_mmc.c
>> or exynos_dw_mc.c
>>
>
>
>> OK.
>>
>> > 3-> As per my understanding, 'div' value depends on values of MPLL clock
>> > and FSYS1/2.
>> Right..but it will be changed the source clock. MMC/SD can use the every
>> source clock.
>>
>> OK.
>
>> > 4-> *Question:* Is it OK to put the piece of code which accesses MPLL,
>> > FSYS1, FSYS2 in drivers/mmc/exynos_dw_mmc.c. ?
>> Sure..we can use the get_mmc_clk/set_mmc_clk. then we can get source
>> clock value.
>> and compute the div value for request clock.
>>
>
>
>> OK. I will change accordingly.
>>
>> Ok, using the existing function "set_mmc_clk()" will do the job.
I will remove the new function "exynos5_mmc_set_clk_div()" in next patch.


>   > 5-> If we compute 'div' value in "drivers/mmc/exynos_dw_mmc.c", then
>> > there will be duplication of code (Read of FSYS1/2).
>> What code is duplication? Could you explain to me more?
>> Only need to compute the div value in exynos_dw_mmc.c.
>> why need to compute into here?
>> Sorry..there is no duplication. I thought that reading fsys1/2 will be
>> done at two places.
>>  Best Regards,
>> Jaehoon Chung
>>  >
>> > Please comment on the above.
>> >
>> >> +
>> >>  /* 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 1935b0b..2fd7c3e 100644
>> >> --- a/arch/arm/include/asm/arch-exynos/clk.h
>> >> +++ b/arch/arm/include/asm/arch-exynos/clk.h
>> >> @@ -29,6 +29,9 @@
>> >>  #define VPLL 4
>> >>  #define BPLL 5
>> >>
>> >> +#define FSYS1_MMC0_DIV_MASK  0xff0f
>> >> +#define FSYS1_MMC0_DIV_VAL   0x0701
>> >> +
>> >>  unsigned long get_pll_clk(int pllreg);
>> >>  unsigned long get_arm_clk(void);
>> >>  unsigned long get_i2c_clk(void);
>> >> @@ -36,6 +39,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);
>> >>
>> >
>> >  _______________________________________________
>> >> U-Boot mailing list
>> >> U-Boot at lists.denx.de
>> >> http://lists.denx.de/mailman/listinfo/u-boot
>> >>
>> >
>> >
>> >
>> > _______________________________________________
>> > U-Boot mailing list
>> > U-Boot at lists.denx.de
>> > http://lists.denx.de/mailman/listinfo/u-boot
>> >
>>
>>
>

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2013-01-03 14:34 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-31 10:58 [U-Boot] [PATCH V3 0/9] EXYNOS5: Enable DWMMC, add FDT support for DWMMC and Amar
2012-12-31 10:58 ` [U-Boot] [PATCH V3 1/9] FDT: Add compatible string for DWMMC Amar
2012-12-31 12:35   ` Kyungmin Park
2012-12-31 10:58 ` [U-Boot] [PATCH V3 2/9] EXYNOS5: FDT: Add DWMMC device node data Amar
2012-12-31 10:58 ` [U-Boot] [PATCH V3 3/9] DWMMC: Initialise dwmci and resolve EMMC read write issues Amar
2013-01-02  5:12   ` Jaehoon Chung
2013-01-03  7:45     ` Amarendra Reddy
2012-12-31 10:58 ` [U-Boot] [PATCH V3 4/9] EXYNOS5: DWMMC: Added FDT support for DWMMC Amar
2013-01-02  5:20   ` Jaehoon Chung
2013-01-03  4:32     ` Amarendra Reddy
2013-01-03  6:48       ` Jaehoon Chung
2012-12-31 10:58 ` [U-Boot] [PATCH V3 5/9] EXYNOS5: DWMMC: API to set mmc clock divisor Amar
2013-01-02  3:31   ` Jaehoon Chung
2013-01-03  6:24     ` Amarendra Reddy
2013-01-03  6:45       ` Jaehoon Chung
2013-01-03 11:16         ` Amarendra Reddy
2013-01-03 14:34           ` Amarendra Reddy
2012-12-31 10:58 ` [U-Boot] [PATCH V3 6/9] SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT Amar
2012-12-31 10:58 ` [U-Boot] [PATCH V3 7/9] MMC: APIs to support resize of EMMC boot partition Amar
2012-12-31 10:58 ` [U-Boot] [PATCH V3 8/9] SMDK5250: Enable EMMC booting Amar
2012-12-31 10:58 ` [U-Boot] [PATCH V3 9/9] COMMON: MMC: Command to support EMMC booting and to Amar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox