Skip to contentSkip to conversation

EXYNOS5: Enable DWMMC, add FDT support for DWMMC and

PATCH Superseded Amar 4 participants 23 messages Apr 3, 2013 – Apr 23, 2013

Subsystems (5)

v8 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Amar

author
#0 lore raw

v8 cover EXYNOS5: Enable DWMMC, add FDT support for DWMMC and

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
1)Updated to use the macro DWMCI_CTRL_SEND_AS_CCSD instead of the hard coded value (1 << 10).
2)In the file exynos_dw_mmc.c, replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the purpose.
3)In the file exynos_dw_mmc.c, computation of FSYS block clock divisor (pre-ratio) value is added.
4)Removed the new function exynos5_mmc_set_clk_div() from clock.c.

Changes since V4:
1)Updated the function dwmci_send_cmd() to use get_timer() instead of using mdelay(1).
2)Replaced the function call 'exynos_dwmmc_init(0, 8);' with the function exynos_dwmmc_add_port() in smdk5250.c.
3)The function get_irom_func(int index) has been added to avoid type casting@many places.
4)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing so user can specify which boot partition to be accessed (opened / closed).

Changes since V5:
1)Added the 'removable' flag to mmc device node. 2)Changed the mmc clock value from 50MHz to 52MHz in the function exynos_dwmci_add_port() present in file drivers/mmc/exynos_dw_mmc.c. 3)Enabled CONFIG_LCD only for non-FDT operation. 4)Removed the function call i2c_init() present inside the function board_i2c_init().

Changes since V6:
1)Re-based to the patch "SMDK5250: Add PMIC voltage settings".

Changes since V7:
1)Re-based to the patch
"Exynos: pwm: Remove dead code of function exynos5_get_pwm_clk". 2)In file dw_mmc.c, updated the function dwmci_setup_bus() to return 0 if (freq == 0).This is to avoid the run time exception "raise:Signal # 8 caught".
3)In the files drivers/mmc/mmc.c and common/cmd_mmc.c, the piece of code involved in EMMC open/close and resize of EMMC boot partition has been made conditional and is enabled only if the macro CONFIG_SUPPORT_EMMC_BOOT is defined.
4)The macros FSYS1_MMC0_DIV_MASK and FSYS1_MMC0_DIV_VAL are made local to file clock_init.c.

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 FDT support for DWMMC
EXYNOS5: DWMMC: Initialise the local variable to avoid unwanted
results.
SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT
MMC: APIs to support resize of EMMC boot partition
SMDK5250: Enable EMMC booting
COMMON: MMC: Command to support EMMC booting and to resize EMMC boot
partition

 arch/arm/cpu/armv7/exynos/clock.c         |   4 +-
 arch/arm/dts/exynos5250.dtsi              |  33 +++
 arch/arm/include/asm/arch-exynos/dwmmc.h  |  11 +-
 board/samsung/dts/exynos5250-smdk5250.dts |  24 ++
 board/samsung/smdk5250/Makefile           |   4 +
 board/samsung/smdk5250/clock_init.c       |  18 ++
 board/samsung/smdk5250/clock_init.h       |   5 +
 board/samsung/smdk5250/exynos5-dt.c       | 423 ++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c         | 223 ++++------------
 board/samsung/smdk5250/spl_boot.c         |  52 +++-
 common/cmd_mmc.c                          | 110 +++++++-
 doc/device-tree-bindings/exynos/dwmmc.txt |  54 ++++
 drivers/mmc/dw_mmc.c                      |  28 +-
 drivers/mmc/exynos_dw_mmc.c               | 127 ++++++++-
 drivers/mmc/mmc.c                         | 134 ++++++++++
 drivers/video/exynos_fb.c                 |   4 +-
 include/configs/exynos5250-dt.h           |   8 +
 include/dwmmc.h                           |   3 +
 include/fdtdec.h                          |   1 +
 include/mmc.h                             |  26 ++
 lib/fdtdec.c                              |   1 +
 21 files changed, 1087 insertions(+), 206 deletions(-)
 create mode 100644 board/samsung/smdk5250/exynos5-dt.c
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
Signature · 1 line
1.8.0
author
#1 lore raw

PATCH v8 1/9 FDT: Add compatible string for DWMMC

Add required compatible information for DWMMC driver.

---
Changes since V1:
No change.

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

Changes since V3:
No change.

Changes since V4:
No change.

Changes since V5:
No change.

Changes since V6:
No change.

Changes since V7:
No change.

 include/fdtdec.h | 1 +
 lib/fdtdec.c     | 1 +
 2 files changed, 2 insertions(+)
include/fdtdec.h +1 -0
index a83b160..5ab3d59 100644
@@ -89,6 +89,7 @@ enum fdt_compat_id {
 	COMPAT_SAMSUNG_EXYNOS5_DP,	/* Exynos Display port controller */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
 	COMPAT_MAXIM_98095_CODEC,	/* MAX98095 Codec */
+	COMPAT_SAMSUNG_EXYNOS5_DWMMC,	/* Exynos5 DWMMC controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 0f34bdc..c187133 100644
@@ -64,6 +64,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
 	COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
+	COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.8.0
author
#2 lore raw

PATCH v8 2/9 EXYNOS5: FDT: Add DWMMC device node data

In reply to Amar

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

---
Changes since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
No change.

Changes since V4:
1)Updated the doc/device-tree-bindings/exynos/dwmmc.txt with more information regarding the property 'samsung,timing'. 2)Replaced the name 'dwmmc' with 'mmc'.

Changes since V5:
1)Added the 'removable' flag to mmc device node.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/dts/exynos5250.dtsi              | 33 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 24 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 54 +++++++++++++++++++++++++++++++
 3 files changed, 111 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
arch/arm/dts/exynos5250.dtsi +33 -0
index df4b231..cee4fe8 100644
@@ -169,4 +169,37 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 	};
+
+	mmc at 12200000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12200000 0x1000>;
+		interrupts = <0 75 0>;
+	};
+
+	mmc at 12210000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12210000 0x1000>;
+		interrupts = <0 76 0>;
+	};
+
+	mmc at 12220000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12220000 0x1000>;
+		interrupts = <0 77 0>;
+	};
+
+	mmc at 12230000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "samsung,exynos5250-dwmmc";
+		reg = <0x12230000 0x1000>;
+		interrupts = <0 78 0>;
+	};
+
 };
board/samsung/dts/exynos5250-smdk5250.dts +24 -0
index 8da973b..93375a6 100644
@@ -30,6 +30,10 @@
 		spi2 = "/spi at 12d40000";
 		spi3 = "/spi at 131a0000";
 		spi4 = "/spi at 131b0000";
+		mmc0 = "/mmc at 12200000";
+		mmc1 = "/mmc at 12210000";
+		mmc2 = "/mmc at 12220000";
+		mmc3 = "/mmc at 12230000";
 	};
 
 	sromc at 12250000 {
@@ -119,4 +123,24 @@
 		samsung,ycbcr-coeff = <0>;
 		samsung,color-depth = <1>;
 	};
+
+	mmc at 12200000 {
+		samsung,bus-width = <8>;
+		samsung,timing = <1 3 3>;
+		samsung,removable = <0>;
+	};
+
+	mmc at 12210000 {
+		status = "disabled";
+	};
+
+	mmc at 12220000 {
+		samsung,bus-width = <4>;
+		samsung,timing = <1 2 3>;
+		samsung,removable = <1>;
+	};
+
+	mmc at 12230000 {
+		status = "disabled";
+	};
 };
doc/device-tree-bindings/exynos/dwmmc.txt new file +54 -0

54 lines not on this page · raw message

Signature · 1 line
1.8.0
author
#3 lore raw

PATCH v8 3/9 DWMMC: Initialise dwmci and resolve EMMC read write issues

In reply to Amar

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 since V1:
1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header file.

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

Changes since V3:

	1)Updated to use the macro DWMCI_CTRL_SEND_AS_CCSD instead of
	the hard coded value (1 << 10).

Changes since V4:
1)Updated the function dwmci_send_cmd() to use get_timer() instead of using mdelay(1).

Changes since V5:
1)Updated in response to review comments.

Changes since V6:
No change.

Changes since V7:

	1)Updated the function dwmci_setup_bus() to return 0 if (freq == 0). 
	This is to avoid the run time exception "raise:Signal # 8 caught".
 drivers/mmc/dw_mmc.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
drivers/mmc/dw_mmc.c +18 -10
index 4070d4e..963a515 100644
@@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	unsigned int timeout = 100000;
 	u32 retry = 10000;
 	u32 mask, ctrl;
+	ulong start = get_timer(0);
 
 	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
-		if (timeout == 0) {
+		if (get_timer(start) > timeout) {
 			printf("Timeout on data busy\n");
 			return TIMEOUT;
 		}
-		timeout--;
 	}
 
 	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -143,7 +143,6 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	if (data)
 		dwmci_prepare_data(host, data);
 
-
 	dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
 	if (data)
@@ -231,9 +230,8 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	int timeout = 10000;
 	unsigned long sclk;
 
-	if (freq == host->clock)
+	if ((freq == host->clock) || (freq == 0))
 		return 0;
-
 	/*
 	 * If host->mmc_clk didn't define,
 	 * then assume that host->bus_hz is source clock value.
@@ -314,7 +312,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 +321,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 |= DWMCI_CTRL_SEND_AS_CCSD;
+	dwmci_writel(host, DWMCI_CTRL, ier);
+
 	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
 	dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -332,11 +338,13 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
 	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
-	if (host->fifoth_val)
+	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) |
-			TX_WMARK(fifo_size/2);
+	} else {
+		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+			TX_WMARK(fifo_size / 2);
+	}
 	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
 
 	dwmci_writel(host, DWMCI_CLKENA, 0);
Signature · 1 line
1.8.0
#4 lore raw

PATCH v8 3/9 DWMMC: Initialise dwmci and resolve EMMC read write issues

Hi Amar,

I'm not sure that need to enable the auto-stop command feature. why do you enable this feature? Is there any benefit? Is it related with read/write issue?

Best Regards,
Jaehoon Chung

Quoted 117 lines · Amar

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 since V1:
1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header file.

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

Changes since V3:

	1)Updated to use the macro DWMCI_CTRL_SEND_AS_CCSD instead of
	the hard coded value (1 << 10).

Changes since V4:
1)Updated the function dwmci_send_cmd() to use get_timer() instead of using mdelay(1).

Changes since V5:
1)Updated in response to review comments.

Changes since V6:
No change.

Changes since V7:

	1)Updated the function dwmci_setup_bus() to return 0 if (freq == 0). 
	This is to avoid the run time exception "raise:Signal # 8 caught".
 drivers/mmc/dw_mmc.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
drivers/mmc/dw_mmc.c +18 -10
index 4070d4e..963a515 100644
@@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	unsigned int timeout = 100000;
 	u32 retry = 10000;
 	u32 mask, ctrl;
+	ulong start = get_timer(0);
 
 	while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
-		if (timeout == 0) {
+		if (get_timer(start) > timeout) {
 			printf("Timeout on data busy\n");
 			return TIMEOUT;
 		}
-		timeout--;
 	}
 
 	dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -143,7 +143,6 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	if (data)
 		dwmci_prepare_data(host, data);
 
-
 	dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
 	if (data)
@@ -231,9 +230,8 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
 	int timeout = 10000;
 	unsigned long sclk;
 
-	if (freq == host->clock)
+	if ((freq == host->clock) || (freq == 0))
 		return 0;
-
 	/*
 	 * If host->mmc_clk didn't define,
 	 * then assume that host->bus_hz is source clock value.
@@ -314,7 +312,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 +321,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 |= DWMCI_CTRL_SEND_AS_CCSD;
+	dwmci_writel(host, DWMCI_CTRL, ier);
+
 	dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
 	dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -332,11 +338,13 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
 	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
-	if (host->fifoth_val)
+	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) |
-			TX_WMARK(fifo_size/2);
+	} else {
+		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+			TX_WMARK(fifo_size / 2);
+	}
 	dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
 
 	dwmci_writel(host, DWMCI_CLKENA, 0);
#5 lore raw

PATCH v8 3/9 DWMMC: Initialise dwmci and resolve EMMC read write issues

Hi Jaehoon,

Auto-stop command is not related to read/write issue.
Today, I commented the 'auto-stop command' enable code and tested, SD/EMMC read write and EMMC boot work fine.
Hence enabling Auto-stop command is not required.
I shall update the same in next patchset.

Thanks & Regards
Amarendra Reddy

Quoted 138 lines · Jaehoon Chung

Hi Amar,

I'm not sure that need to enable the auto-stop command feature. why do you enable this feature? Is there any benefit? Is it related with read/write issue?

Best Regards,
Jaehoon Chung

Quoted 10 lines · Amar

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 since V1:
1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header

file.

Quoted 12 lines

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

Changes since V3:
1)Updated to use the macro DWMCI_CTRL_SEND_AS_CCSD instead of the hard coded value (1 << 10).

Changes since V4:
1)Updated the function dwmci_send_cmd() to use get_timer() instead of using mdelay(1).

Quoted 8 lines

Changes since V5:
1)Updated in response to review comments.

Changes since V6:
No change.

Changes since V7:

      1)Updated the function dwmci_setup_bus() to return 0 if (freq ==

0).

drivers/mmc/dw_mmc.c static int dwmci_send_cmd(struct mmc *mmc, struct

Quoted 10 lines

This is to avoid the run time exception "raise:Signal # 8 caught".

 drivers/mmc/dw_mmc.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)
drivers/mmc/dw_mmc.c +0 -0
index 4070d4e..963a515 100644
@@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct

mmc_cmd *cmd,

drivers/mmc/dw_mmc.c static int dwmci_send_cmd(struct mmc *mmc, struct

Quoted 16 lines
drivers/mmc/dw_mmc.c +2 -2
      unsigned int timeout = 100000;
      u32 retry = 10000;
      u32 mask, ctrl;
+     ulong start = get_timer(0);
 
      while (dwmci_readl(host, DWMCI_STATUS) & DWMCI_BUSY) {
-             if (timeout == 0) {
+             if (get_timer(start) > timeout) {
                      printf("Timeout on data busy\n");
                      return TIMEOUT;
              }
-             timeout--;
      }
 
      dwmci_writel(host, DWMCI_RINTSTS, DWMCI_INTMSK_ALL);
@@ -143,7 +143,6 @@ static int dwmci_send_cmd(struct mmc *mmc, struct

mmc_cmd *cmd,

drivers/mmc/dw_mmc.c static int dwmci_setup_bus(struct dwmci_host *host,

Quoted 8 lines
drivers/mmc/dw_mmc.c +0 -1
      if (data)
              dwmci_prepare_data(host, data);
 
-
      dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
      if (data)
@@ -231,9 +230,8 @@ static int dwmci_setup_bus(struct dwmci_host *host,

u32 freq)

Quoted 43 lines
drivers/mmc/dw_mmc.c +12 -4
      int timeout = 10000;
      unsigned long sclk;
 
-     if (freq == host->clock)
+     if ((freq == host->clock) || (freq == 0))
              return 0;
-
      /*
       * If host->mmc_clk didn't define,
       * then assume that host->bus_hz is source clock value.
@@ -314,7 +312,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 +321,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 |= DWMCI_CTRL_SEND_AS_CCSD;
+     dwmci_writel(host, DWMCI_CTRL, ier);
+
      dwmci_writel(host, DWMCI_RINTSTS, 0xFFFFFFFF);
      dwmci_writel(host, DWMCI_INTMASK, 0);
 
@@ -332,11 +338,13 @@ static int dwmci_init(struct mmc *mmc)
      dwmci_writel(host, DWMCI_BMOD, 1);
 
      fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
-     if (host->fifoth_val)
+     fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
+     if (host->fifoth_val) {
              fifoth_val = host->fifoth_val;

drivers/mmc/dw_mmc.c static int dwmci_init(struct mmc *mmc) · line 350

Quoted 10 lines
drivers/mmc/dw_mmc.c +4 -3
-     else
-             fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-                     TX_WMARK(fifo_size/2);
+     } else {
+             fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size / 2 - 1) |
+                     TX_WMARK(fifo_size / 2);
+     }
      dwmci_writel(host, DWMCI_FIFOTH, fifoth_val);
 
      dwmci_writel(host, DWMCI_CLKENA, 0);

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

author
#6 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

In reply to Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the purpose. 2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int bus_width)" with int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will use exynos_dwmmc_add_port() for every channel enabled in device node.
2)Changed the computation method of mmc clock divisor.
3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within the function.

Changes since V5:
1)Updated in response to review comments and changed the mmc clock value from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127 ++++++++++++++++++++++++++++---
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -7
index 8acdf9b..3b147b8 100644
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x)	((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel);
drivers/mmc/exynos_dw_mmc.c +117 -10

156 lines not on this page · raw message

include/dwmmc.h +3 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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 +146,7 @@ struct dwmci_host {
 	unsigned int bus_hz;
 	int dev_index;
 	int buswidth;
+	u32 clksel_val;
 	u32 fifoth_val;
 	struct mmc *mmc;
 
Signature · 1 line
1.8.0
#7 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Quoted 80 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the purpose. 2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int bus_width)" with int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will use exynos_dwmmc_add_port() for every channel enabled in device node.
2)Changed the computation method of mmc clock divisor.
3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within the function.

Changes since V5:
1)Updated in response to review comments and changed the mmc clock value from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127 ++++++++++++++++++++++++++++---
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -7
index 8acdf9b..3b147b8 100644
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x)	((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)	((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel);
drivers/mmc/exynos_dw_mmc.c +3 -1
index 72a31b7..4238dd9 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Best Regards,
Jaehoon Chung

Quoted 160 lines
drivers/mmc/exynos_dw_mmc.c +108 -8
+/*
+ * 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)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -	mmc channel number.
+ * regbase -	register base address of mmc channel specified in 'index'.
+ * bus_width -	operating bus width of mmc channel specified in 'index'.
+ * clksel -	value to be written into CLKSEL register in case of FDT.
+ *		NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel)
 {
 	struct dwmci_host *host = NULL;
+	unsigned int div;
+	unsigned long freq, sclk;
 	host = malloc(sizeof(struct dwmci_host));
 	if (!host) {
 		printf("dwmci_host malloc fail!\n");
 		return 1;
 	}
+	/* request mmc clock vlaue of 52MHz.  */
+	freq = 52000000;
+	sclk = get_mmc_clk(index);
+	div = DIV_ROUND_UP(sclk, freq);
+	/* set the clock divisor for mmc */
+	set_mmc_clk(index, div);
 
-	host->name = EXYNOS_NAME;
+	host->name = "EXYNOS DWMMC";
 	host->ioaddr = (void *)regbase;
 	host->buswidth = bus_width;
+
+	if (clksel) {
+		host->clksel_val = clksel;
+	} else {
+		if (0 == index)
+			host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+		if (2 == index)
+			host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+	}
+
 	host->clksel = exynos_dwmci_clksel;
 	host->dev_index = index;
+	host->mmc_clk = exynos_dwmci_get_clk;
+	/* Add the mmc channel to be registered with mmc core */
+	if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+		debug("dwmmc%d registration failed\n", index);
+		return -1;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+	int index, bus_width;
+	int node_list[DWMMC_MAX_CH_NUM];
+	int err = 0, dev_id, flag, count, i;
+	u32 clksel_val, base, timing[3];
+
+	count = fdtdec_find_aliases_for_id(blob, "mmc",
+				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;
 
-	add_dwmci(host, 52000000, 400000);
+		/* 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;
+		}
+
+		clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+				DWMCI_SET_DRV_CLK(timing[1]) |
+				DWMCI_SET_DIV_RATIO(timing[2]));
+		/* Initialise each mmc channel */
+		err = exynos_dwmci_add_port(index, base, bus_width, clksel_val);
+		if (err)
+			debug("dwmmc Channel-%d init failed\n", index);
+	}
 	return 0;
 }
-
+#endif
include/dwmmc.h +3 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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 +146,7 @@ struct dwmci_host {
 	unsigned int bus_hz;
 	int dev_index;
 	int buswidth;
+	u32 clksel_val;
 	u32 fifoth_val;
 	struct mmc *mmc;
 
#8 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Jaehoon,

Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 102 lines · Jaehoon Chung
Quoted 19 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Quoted 7 lines

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the purpose. 2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int

bus_width)" with

Quoted 3 lines

int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will

use

Quoted 1 line

exynos_dwmmc_add_port() for every channel enabled in

device node.

Quoted 2 lines

2)Changed the computation method of mmc clock divisor. 3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within

the function.

Quoted 3 lines

Changes since V5:
1)Updated in response to review comments and changed the mmc clock

value

Quoted 10 lines

from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127

++++++++++++++++++++++++++++---

Review

Quoted 4 lines
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 8 lines

index 8acdf9b..3b147b8 100644

arch/arm/include/asm/arch-exynos/dwmmc.h +0 -1
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)       ((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);

arch/arm/include/asm/arch-exynos/dwmmc.h line 33

Quoted 10 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -6
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel);

Quoted 13 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
index 72a31b7..4238dd9 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Quoted 3 lines

Best Regards,
Jaehoon Chung

The above values of CLKSEL work fine for Exynos5 (5250 & 5410) and is tested.

The above CLKSEL values donot hold good for Exynos4 series. Exynos4 has "Mobile Storage Host" with only one port.
But this file 'drivers/mmc/exynos_dw_mmc.c' is specific to Exynos5 series and gets compiled only when CONFIG_EXYNOS_DWMMC is defined.

Quoted 170 lines
Quoted 15 lines
drivers/mmc/exynos_dw_mmc.c +7 -4
+/*
+ * 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)

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+{
+     return get_mmc_clk(dev_index);
 }
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -   mmc channel number.
+ * regbase - register base address of mmc channel specified in 'index'.
+ * bus_width -       operating bus width of mmc channel specified in

'index'.

drivers/mmc/exynos_dw_mmc.c

Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+ * clksel -  value to be written into CLKSEL register in case of FDT.
+ *           NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 55 lines
drivers/mmc/exynos_dw_mmc.c +42 -1
 {
      struct dwmci_host *host = NULL;
+     unsigned int div;
+     unsigned long freq, sclk;
      host = malloc(sizeof(struct dwmci_host));
      if (!host) {
              printf("dwmci_host malloc fail!\n");
              return 1;
      }
+     /* request mmc clock vlaue of 52MHz.  */
+     freq = 52000000;
+     sclk = get_mmc_clk(index);
+     div = DIV_ROUND_UP(sclk, freq);
+     /* set the clock divisor for mmc */
+     set_mmc_clk(index, div);
 
-     host->name = EXYNOS_NAME;
+     host->name = "EXYNOS DWMMC";
      host->ioaddr = (void *)regbase;
      host->buswidth = bus_width;
+
+     if (clksel) {
+             host->clksel_val = clksel;
+     } else {
+             if (0 == index)
+                     host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+             if (2 == index)
+                     host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+     }
+
      host->clksel = exynos_dwmci_clksel;
      host->dev_index = index;
+     host->mmc_clk = exynos_dwmci_get_clk;
+     /* Add the mmc channel to be registered with mmc core */
+     if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+             debug("dwmmc%d registration failed\n", index);
+             return -1;
+     }
+     return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+     int index, bus_width;
+     int node_list[DWMMC_MAX_CH_NUM];
+     int err = 0, dev_id, flag, count, i;
+     u32 clksel_val, base, timing[3];
+
+     count = fdtdec_find_aliases_for_id(blob, "mmc",
+                             COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+                             DWMMC_MAX_CH_NUM);
+
+     for (i = 0; i < count; i++) {
+             int node = node_list[i];

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+
+             if (node <= 0)
+                     continue;
 
-     add_dwmci(host, 52000000, 400000);
+             /* 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);

Quoted 27 lines
drivers/mmc/exynos_dw_mmc.c +27 -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);

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +10 -0
+             if (err) {
+                     debug("Can't get sdr-timings for divider\n");
+                     return -1;
+             }
+
+             clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                             DWMCI_SET_DRV_CLK(timing[1]) |
+                             DWMCI_SET_DIV_RATIO(timing[2]));
+             /* Initialise each mmc channel */
+             err = exynos_dwmci_add_port(index, base, bus_width,

clksel_val);

Quoted 22 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
+             if (err)
+                     debug("dwmmc Channel-%d init failed\n", index);
+     }
      return 0;
 }
-
+#endif
include/dwmmc.h +2 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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)

include/dwmmc.h struct dwmci_host { · line 152

Quoted 7 lines
include/dwmmc.h +1 -0
@@ -144,6 +146,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

#9 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Quoted 115 lines · Amarendra Reddy

Hi Jaehoon,

Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 102 lines · Jaehoon Chung
Quoted 19 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Quoted 7 lines

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the purpose. 2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int

bus_width)" with

Quoted 3 lines

int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will

use

Quoted 1 line

exynos_dwmmc_add_port() for every channel enabled in

device node.

Quoted 2 lines

2)Changed the computation method of mmc clock divisor. 3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within

the function.

Quoted 3 lines

Changes since V5:
1)Updated in response to review comments and changed the mmc clock

value

Quoted 10 lines

from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127

++++++++++++++++++++++++++++---

Review

Quoted 4 lines
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 8 lines

index 8acdf9b..3b147b8 100644

arch/arm/include/asm/arch-exynos/dwmmc.h +0 -1
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)       ((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);

arch/arm/include/asm/arch-exynos/dwmmc.h line 33

Quoted 10 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -6
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel);

Quoted 13 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
index 72a31b7..4238dd9 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Quoted 3 lines

Best Regards,
Jaehoon Chung

Quoted 7 lines

The above values of CLKSEL work fine for Exynos5 (5250 & 5410) and is tested.

The above CLKSEL values donot hold good for Exynos4 series. Exynos4 has "Mobile Storage Host" with only one port.
But this file 'drivers/mmc/exynos_dw_mmc.c' is specific to Exynos5 series and gets compiled only when CONFIG_EXYNOS_DWMMC is defined.

No, driver/mmc/exynos_dw_mmc.c isn't specific to Exynos5 series. We can use this controller at the exynos4.
Then we need to consider how get the clksel value according to SoC.

Best Regards,
Jaehoon Chung

Quoted 179 lines
Quoted 154 lines
Quoted 16 lines
drivers/mmc/exynos_dw_mmc.c +7 -4
+/*
+ * 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)

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+{
+     return get_mmc_clk(dev_index);
 }
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -   mmc channel number.
+ * regbase - register base address of mmc channel specified in 'index'.
+ * bus_width -       operating bus width of mmc channel specified in

'index'.

drivers/mmc/exynos_dw_mmc.c

Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+ * clksel -  value to be written into CLKSEL register in case of FDT.
+ *           NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 55 lines
drivers/mmc/exynos_dw_mmc.c +42 -1
 {
      struct dwmci_host *host = NULL;
+     unsigned int div;
+     unsigned long freq, sclk;
      host = malloc(sizeof(struct dwmci_host));
      if (!host) {
              printf("dwmci_host malloc fail!\n");
              return 1;
      }
+     /* request mmc clock vlaue of 52MHz.  */
+     freq = 52000000;
+     sclk = get_mmc_clk(index);
+     div = DIV_ROUND_UP(sclk, freq);
+     /* set the clock divisor for mmc */
+     set_mmc_clk(index, div);
 
-     host->name = EXYNOS_NAME;
+     host->name = "EXYNOS DWMMC";
      host->ioaddr = (void *)regbase;
      host->buswidth = bus_width;
+
+     if (clksel) {
+             host->clksel_val = clksel;
+     } else {
+             if (0 == index)
+                     host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+             if (2 == index)
+                     host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+     }
+
      host->clksel = exynos_dwmci_clksel;
      host->dev_index = index;
+     host->mmc_clk = exynos_dwmci_get_clk;
+     /* Add the mmc channel to be registered with mmc core */
+     if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+             debug("dwmmc%d registration failed\n", index);
+             return -1;
+     }
+     return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+     int index, bus_width;
+     int node_list[DWMMC_MAX_CH_NUM];
+     int err = 0, dev_id, flag, count, i;
+     u32 clksel_val, base, timing[3];
+
+     count = fdtdec_find_aliases_for_id(blob, "mmc",
+                             COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+                             DWMMC_MAX_CH_NUM);
+
+     for (i = 0; i < count; i++) {
+             int node = node_list[i];

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+
+             if (node <= 0)
+                     continue;
 
-     add_dwmci(host, 52000000, 400000);
+             /* 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);

Quoted 27 lines
drivers/mmc/exynos_dw_mmc.c +27 -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);

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +10 -0
+             if (err) {
+                     debug("Can't get sdr-timings for divider\n");
+                     return -1;
+             }
+
+             clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                             DWMCI_SET_DRV_CLK(timing[1]) |
+                             DWMCI_SET_DIV_RATIO(timing[2]));
+             /* Initialise each mmc channel */
+             err = exynos_dwmci_add_port(index, base, bus_width,

clksel_val);

Quoted 18 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
+             if (err)
+                     debug("dwmmc Channel-%d init failed\n", index);
+     }
      return 0;
 }
-
+#endif
include/dwmmc.h +2 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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)
 
Quoted 17 lines

include/dwmmc.h struct dwmci_host { · line 152

Quoted 11 lines
include/dwmmc.h +1 -0
 #define DWMCI_IDMAC_OWN              (1 << 31)
 #define DWMCI_IDMAC_CH               (1 << 4)
@@ -144,6 +146,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

#10 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Jaehoon,

Please find my response below.

Thanks & Regards
Amarendra Reddy

Quoted 125 lines · Jaehoon Chung
Quoted 32 lines · Amarendra Reddy

Hi Jaehoon,

Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 23 lines · Jaehoon Chung
Quoted 22 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the

purpose.

Quoted 9 lines
Quoted 9 lines
Quoted 4 lines

2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int

bus_width)" with

Quoted 3 lines

int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will

use

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

exynos_dwmmc_add_port() for every channel enabled in

device node.

Quoted 2 lines

2)Changed the computation method of mmc clock divisor. 3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within

the function.

Quoted 3 lines

Changes since V5:
1)Updated in response to review comments and changed the mmc

clock

Quoted 66 lines
Quoted 62 lines

value

Quoted 10 lines

from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127

++++++++++++++++++++++++++++---

Review

Quoted 4 lines
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 8 lines

index 8acdf9b..3b147b8 100644

arch/arm/include/asm/arch-exynos/dwmmc.h +0 -1
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)       ((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);

arch/arm/include/asm/arch-exynos/dwmmc.h line 33

Quoted 10 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -6
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel);

Quoted 13 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
index 72a31b7..4238dd9 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Quoted 3 lines

Best Regards,
Jaehoon Chung

Quoted 7 lines

The above values of CLKSEL work fine for Exynos5 (5250 & 5410) and is tested.

The above CLKSEL values donot hold good for Exynos4 series. Exynos4 has "Mobile Storage Host" with only one port.
But this file 'drivers/mmc/exynos_dw_mmc.c' is specific to Exynos5 series and gets compiled only when CONFIG_EXYNOS_DWMMC is defined.

Quoted 7 lines

No, driver/mmc/exynos_dw_mmc.c isn't specific to Exynos5 series. We can use this controller at the exynos4.
Then we need to consider how get the clksel value according to SoC.

Best Regards,
Jaehoon Chung

OK. Then I shall add the macro for supporting exynos4 also as shown below

#define EXYNOS4_DWMMC_MMC0_CLKSEL_VAL           0x00000000 (reset value)
#define EXYNOS5_DWMMC_MMC0_CLKSEL_VAL           0x03030001
#define EXYNOS5_DWMMC_MMC2_CLKSEL_VAL           0x03020001

In Exynos4, Mobile Storage Host has only one channel.

The the below function will be updated as below
int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) {
......
......

        if (clksel) {
                host->clksel_val = clksel;
        } else {
                if (0 == index) {
                        if(cpu_is_exynos5())
                                     host->clksel_val =
EXYNOS5_DWMMC_MMC0_CLKSEL_VAL;
                        else
                                     host->clksel_val =

EXYNOS4_DWMMC_MMC0_CLKSEL_VAL; /* Exynos4 MSH has only one channel */

                }

                if (2 == index)
                        host->clksel_val = EXYNOS5_DWMMC_MMC2_CLKSEL_VAL;
        }

........
........
}

Is it OK. Please comment on the above.

Thanks & Regards
Amarendra Reddy

Quoted 183 lines
Quoted 11 lines
Quoted 11 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 11 lines
drivers/mmc/exynos_dw_mmc.c +4 -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);

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/mmc/exynos_dw_mmc.c +5 -1
+     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);
 }
 
Quoted 5 lines
Quoted 5 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 5 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -   mmc channel number.
+ * regbase - register base address of mmc channel specified in

'index'.

Quoted 154 lines
Quoted 129 lines

drivers/mmc/exynos_dw_mmc.c line 53

Quoted 1 line
drivers/mmc/exynos_dw_mmc.c +1 -0
+ * bus_width -       operating bus width of mmc channel specified in

'index'.

drivers/mmc/exynos_dw_mmc.c

Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+ * clksel -  value to be written into CLKSEL register in case of FDT.
+ *           NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 55 lines
drivers/mmc/exynos_dw_mmc.c +42 -1
 {
      struct dwmci_host *host = NULL;
+     unsigned int div;
+     unsigned long freq, sclk;
      host = malloc(sizeof(struct dwmci_host));
      if (!host) {
              printf("dwmci_host malloc fail!\n");
              return 1;
      }
+     /* request mmc clock vlaue of 52MHz.  */
+     freq = 52000000;
+     sclk = get_mmc_clk(index);
+     div = DIV_ROUND_UP(sclk, freq);
+     /* set the clock divisor for mmc */
+     set_mmc_clk(index, div);
 
-     host->name = EXYNOS_NAME;
+     host->name = "EXYNOS DWMMC";
      host->ioaddr = (void *)regbase;
      host->buswidth = bus_width;
+
+     if (clksel) {
+             host->clksel_val = clksel;
+     } else {
+             if (0 == index)
+                     host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+             if (2 == index)
+                     host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+     }
+
      host->clksel = exynos_dwmci_clksel;
      host->dev_index = index;
+     host->mmc_clk = exynos_dwmci_get_clk;
+     /* Add the mmc channel to be registered with mmc core */
+     if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+             debug("dwmmc%d registration failed\n", index);
+             return -1;
+     }
+     return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+     int index, bus_width;
+     int node_list[DWMMC_MAX_CH_NUM];
+     int err = 0, dev_id, flag, count, i;
+     u32 clksel_val, base, timing[3];
+
+     count = fdtdec_find_aliases_for_id(blob, "mmc",
+                             COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+                             DWMMC_MAX_CH_NUM);
+
+     for (i = 0; i < count; i++) {
+             int node = node_list[i];

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+
+             if (node <= 0)
+                     continue;
 
-     add_dwmci(host, 52000000, 400000);
+             /* 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);

Quoted 27 lines
drivers/mmc/exynos_dw_mmc.c +27 -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);

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +10 -0
+             if (err) {
+                     debug("Can't get sdr-timings for divider\n");
+                     return -1;
+             }
+
+             clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                             DWMCI_SET_DRV_CLK(timing[1]) |
+                             DWMCI_SET_DIV_RATIO(timing[2]));
+             /* Initialise each mmc channel */
+             err = exynos_dwmci_add_port(index, base, bus_width,

clksel_val);

Quoted 18 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
+             if (err)
+                     debug("dwmmc Channel-%d init failed\n", index);
+     }
      return 0;
 }
-
+#endif
include/dwmmc.h +2 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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)
 
Quoted 17 lines

include/dwmmc.h struct dwmci_host { · line 152

Quoted 11 lines
include/dwmmc.h +1 -0
 #define DWMCI_IDMAC_OWN              (1 << 31)
 #define DWMCI_IDMAC_CH               (1 << 4)
@@ -144,6 +146,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

#11 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Quoted 171 lines · Amarendra Reddy

Hi Jaehoon,

Please find my response below.

Thanks & Regards
Amarendra Reddy

Quoted 125 lines · Jaehoon Chung
Quoted 32 lines · Amarendra Reddy

Hi Jaehoon,

Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 23 lines · Jaehoon Chung
Quoted 22 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the

purpose.

Quoted 9 lines
Quoted 9 lines
Quoted 4 lines

2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int

bus_width)" with

Quoted 3 lines

int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT boards. ii)In FDT case, exynos_dwmmc_init(const void *blob) will

use

Quoted 8 lines
Quoted 8 lines
Quoted 1 line

exynos_dwmmc_add_port() for every channel enabled in

device node.

Quoted 2 lines

2)Changed the computation method of mmc clock divisor. 3)Updated exynos_dwmmc_init() to compute the 'clksel_val' within

the function.

Quoted 3 lines

Changes since V5:
1)Updated in response to review comments and changed the mmc

clock

Quoted 66 lines
Quoted 62 lines

value

Quoted 10 lines

from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127

++++++++++++++++++++++++++++---

Review

Quoted 4 lines
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 8 lines

index 8acdf9b..3b147b8 100644

arch/arm/include/asm/arch-exynos/dwmmc.h +0 -1
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)       ((x) << 24)
 
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);

arch/arm/include/asm/arch-exynos/dwmmc.h line 33

Quoted 10 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -6
-
-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);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel);

Quoted 13 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
index 72a31b7..4238dd9 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Quoted 3 lines

Best Regards,
Jaehoon Chung

Quoted 7 lines

The above values of CLKSEL work fine for Exynos5 (5250 & 5410) and is tested.

The above CLKSEL values donot hold good for Exynos4 series. Exynos4 has "Mobile Storage Host" with only one port.
But this file 'drivers/mmc/exynos_dw_mmc.c' is specific to Exynos5 series and gets compiled only when CONFIG_EXYNOS_DWMMC is defined.

Quoted 7 lines

No, driver/mmc/exynos_dw_mmc.c isn't specific to Exynos5 series. We can use this controller at the exynos4.
Then we need to consider how get the clksel value according to SoC.

Best Regards,
Jaehoon Chung

OK. Then I shall add the macro for supporting exynos4 also as shown below

#define EXYNOS4_DWMMC_MMC0_CLKSEL_VAL           0x00000000 (reset value)
#define EXYNOS5_DWMMC_MMC0_CLKSEL_VAL           0x03030001
#define EXYNOS5_DWMMC_MMC2_CLKSEL_VAL           0x03020001

In Exynos4, Mobile Storage Host has only one channel.

The the below function will be updated as below
int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32 clksel) {
......
......

        if (clksel) {
                host->clksel_val = clksel;
        } else {
                if (0 == index) {
                        if(cpu_is_exynos5())
                                     host->clksel_val =
EXYNOS5_DWMMC_MMC0_CLKSEL_VAL;
                        else
                                     host->clksel_val =

EXYNOS4_DWMMC_MMC0_CLKSEL_VAL; /* Exynos4 MSH has only one channel */

                }

                if (2 == index)
                        host->clksel_val = EXYNOS5_DWMMC_MMC2_CLKSEL_VAL;
        }
Quoted 5 lines

........
........
}

Is it OK. Please comment on the above.

Well...if you want to set the CLKSEL,i will modify for exynos4 in future. How about this? (I think you're only working for the exynos5)

Best Regards,
Jaehoon Chung

Quoted 195 lines

Thanks & Regards
Amarendra Reddy

Quoted 21 lines
Quoted 11 lines
Quoted 11 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 11 lines
drivers/mmc/exynos_dw_mmc.c +4 -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);

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/mmc/exynos_dw_mmc.c +5 -1
+     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);
 }
 
Quoted 162 lines
Quoted 5 lines
Quoted 5 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 5 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc core.
+ * index -   mmc channel number.
+ * regbase - register base address of mmc channel specified in

'index'.

Quoted 154 lines
Quoted 129 lines

drivers/mmc/exynos_dw_mmc.c line 53

Quoted 1 line
drivers/mmc/exynos_dw_mmc.c +1 -0
+ * bus_width -       operating bus width of mmc channel specified in

'index'.

drivers/mmc/exynos_dw_mmc.c

Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+ * clksel -  value to be written into CLKSEL register in case of FDT.
+ *           NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 55 lines
drivers/mmc/exynos_dw_mmc.c +42 -1
 {
      struct dwmci_host *host = NULL;
+     unsigned int div;
+     unsigned long freq, sclk;
      host = malloc(sizeof(struct dwmci_host));
      if (!host) {
              printf("dwmci_host malloc fail!\n");
              return 1;
      }
+     /* request mmc clock vlaue of 52MHz.  */
+     freq = 52000000;
+     sclk = get_mmc_clk(index);
+     div = DIV_ROUND_UP(sclk, freq);
+     /* set the clock divisor for mmc */
+     set_mmc_clk(index, div);
 
-     host->name = EXYNOS_NAME;
+     host->name = "EXYNOS DWMMC";
      host->ioaddr = (void *)regbase;
      host->buswidth = bus_width;
+
+     if (clksel) {
+             host->clksel_val = clksel;
+     } else {
+             if (0 == index)
+                     host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+             if (2 == index)
+                     host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+     }
+
      host->clksel = exynos_dwmci_clksel;
      host->dev_index = index;
+     host->mmc_clk = exynos_dwmci_get_clk;
+     /* Add the mmc channel to be registered with mmc core */
+     if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+             debug("dwmmc%d registration failed\n", index);
+             return -1;
+     }
+     return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
+{
+     int index, bus_width;
+     int node_list[DWMMC_MAX_CH_NUM];
+     int err = 0, dev_id, flag, count, i;
+     u32 clksel_val, base, timing[3];
+
+     count = fdtdec_find_aliases_for_id(blob, "mmc",
+                             COMPAT_SAMSUNG_EXYNOS5_DWMMC, node_list,
+                             DWMMC_MAX_CH_NUM);
+
+     for (i = 0; i < count; i++) {
+             int node = node_list[i];

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+
+             if (node <= 0)
+                     continue;
 
-     add_dwmci(host, 52000000, 400000);
+             /* 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);

Quoted 27 lines
drivers/mmc/exynos_dw_mmc.c +27 -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);

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +10 -0
+             if (err) {
+                     debug("Can't get sdr-timings for divider\n");
+                     return -1;
+             }
+
+             clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                             DWMCI_SET_DRV_CLK(timing[1]) |
+                             DWMCI_SET_DIV_RATIO(timing[2]));
+             /* Initialise each mmc channel */
+             err = exynos_dwmci_add_port(index, base, bus_width,

clksel_val);

Quoted 18 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
+             if (err)
+                     debug("dwmmc Channel-%d init failed\n", index);
+     }
      return 0;
 }
-
+#endif
include/dwmmc.h +2 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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)
 
Quoted 17 lines

include/dwmmc.h struct dwmci_host { · line 152

Quoted 11 lines
include/dwmmc.h +1 -0
 #define DWMCI_IDMAC_OWN              (1 << 31)
 #define DWMCI_IDMAC_CH               (1 << 4)
@@ -144,6 +146,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

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

#12 lore raw

PATCH v8 4/9 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Jaehoon,

Please find my response below

Thanks & Regards
Amarendra

Quoted 185 lines · Jaehoon Chung
Quoted 38 lines · Amarendra Reddy

Hi Jaehoon,

Please find my response below.

Thanks & Regards
Amarendra Reddy

Quoted 29 lines · Jaehoon Chung
Quoted 28 lines · Amarendra Reddy

Hi Jaehoon,

Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 19 lines · Jaehoon Chung
Quoted 18 lines · Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch

set.

Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

Changes since V3:
1)Replaced the new function exynos5_mmc_set_clk_div() with the existing function set_mmc_clk(). set_mmc_clk() will do the

Quoted 8 lines
Quoted 8 lines

purpose.

Quoted 7 lines
Quoted 7 lines
Quoted 4 lines

2)Computation of FSYS block clock divisor (pre-ratio) is added.

Changes since V4:
1)Replaced "unsigned int exynos_dwmmc_init(int index, int

bus_width)" with

Quoted 2 lines

int exynos_dwmci_add_port(int, u32, inth, u32)
i)exynos_dwmmc_add_port() will be used by non-FDT

boards.

Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line

ii)In FDT case, exynos_dwmmc_init(const void *blob)

will

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

use

Quoted 1 line

exynos_dwmmc_add_port() for every channel enabled in

device node.

Quoted 2 lines

2)Changed the computation method of mmc clock divisor. 3)Updated exynos_dwmmc_init() to compute the 'clksel_val'

within

Quoted 29 lines
Quoted 29 lines
Quoted 4 lines
Quoted 4 lines

the function.

Quoted 3 lines

Changes since V5:
1)Updated in response to review comments and changed the mmc

clock

Quoted 24 lines
Quoted 24 lines

value

Quoted 10 lines

from 50MHz to 52MHz.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/include/asm/arch-exynos/dwmmc.h |  11 +--
 drivers/mmc/exynos_dw_mmc.c              | 127

++++++++++++++++++++++++++++---

Review

Quoted 4 lines
 include/dwmmc.h                          |   3 +
 3 files changed, 124 insertions(+), 17 deletions(-)
(quoted diff) +0 -0

b/arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 7 lines

index 8acdf9b..3b147b8 100644

arch/arm/include/asm/arch-exynos/dwmmc.h +0 -0
@@ -27,10 +27,7 @@
 #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
 #define DWMCI_SET_DIV_RATIO(x)       ((x) << 24)
 
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 3 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +0 -3
-int exynos_dwmci_init(u32 regbase, int bus_width, int index);
-
-static inline unsigned int exynos_dwmmc_init(int index, int

bus_width)

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 10 lines

arch/arm/include/asm/arch-exynos/dwmmc.h

Quoted 8 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -4
-{
-     unsigned int base = samsung_get_base_mmc() + (0x10000 * index);
-     return exynos_dwmci_init(base, bus_width, index);
-}
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob);
+#endif
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel);

Review

Quoted 1 line
(quoted diff) +0 -0

b/drivers/mmc/exynos_dw_mmc.c

Quoted 29 lines
Quoted 29 lines
Quoted 29 lines
Quoted 28 lines
Quoted 12 lines

index 72a31b7..4238dd9 100644

drivers/mmc/exynos_dw_mmc.c +3 -1
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>

drivers/mmc/exynos_dw_mmc.c line 34

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +6 -1
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-static char *EXYNOS_NAME = "EXYNOS DWMMC";
+#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

I known that CLKSEL's value is SoC specific. All exynos series are working fine? I didn't think so.

Best Regards,
Jaehoon Chung

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

The above values of CLKSEL work fine for Exynos5 (5250 & 5410) and is tested.

The above CLKSEL values donot hold good for Exynos4 series. Exynos4 has "Mobile Storage Host" with only one port.
But this file 'drivers/mmc/exynos_dw_mmc.c' is specific to Exynos5

series

Quoted 10 lines
Quoted 8 lines
Quoted 1 line

and gets compiled only when CONFIG_EXYNOS_DWMMC is defined.

No, driver/mmc/exynos_dw_mmc.c isn't specific to Exynos5 series. We can use this controller at the exynos4.
Then we need to consider how get the clksel value according to SoC.

Best Regards,
Jaehoon Chung

OK. Then I shall add the macro for supporting exynos4 also as shown below

Quoted 8 lines
#define EXYNOS4_DWMMC_MMC0_CLKSEL_VAL           0x00000000 (reset value)
#define EXYNOS5_DWMMC_MMC0_CLKSEL_VAL           0x03030001
#define EXYNOS5_DWMMC_MMC2_CLKSEL_VAL           0x03020001

In Exynos4, Mobile Storage Host has only one channel.

The the below function will be updated as below
int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 13 lines

{
......
......

        if (clksel) {
                host->clksel_val = clksel;
        } else {
                if (0 == index) {
                        if(cpu_is_exynos5())
                                     host->clksel_val =
EXYNOS5_DWMMC_MMC0_CLKSEL_VAL;
                        else
                                     host->clksel_val =
Quoted 1 line

EXYNOS4_DWMMC_MMC0_CLKSEL_VAL; /* Exynos4 MSH has only one channel

*/

Quoted 10 lines
                }

                if (2 == index)
                        host->clksel_val = EXYNOS5_DWMMC_MMC2_CLKSEL_VAL;
        }

........
........
}

Quoted 5 lines
Quoted 1 line

Is it OK. Please comment on the above.

Well...if you want to set the CLKSEL,i will modify for exynos4 in future. How about this? (I think you're only working for the exynos5)

Ok fine, that will be really good. Hence right now I will not set CLKSEL

for exynos4 in the file 'drivers/mmc/exynos_dw_mmc.c'.

Best Regards,

Quoted 202 lines

Jaehoon Chung

Quoted 25 lines

Thanks & Regards
Amarendra Reddy

Quoted 21 lines
Quoted 11 lines
Quoted 11 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 11 lines
drivers/mmc/exynos_dw_mmc.c +4 -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);

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/mmc/exynos_dw_mmc.c +5 -1
+     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);
 }
 
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 3 lines
drivers/mmc/exynos_dw_mmc.c +2 -1
-int exynos_dwmci_init(u32 regbase, int bus_width, int index)
+/*
+ * This function adds the mmc channel to be registered with mmc

core.

Quoted 6 lines
Quoted 6 lines
Quoted 2 lines
Quoted 2 lines

drivers/mmc/exynos_dw_mmc.c line 52

Quoted 2 lines
drivers/mmc/exynos_dw_mmc.c +2 -0
+ * index -   mmc channel number.
+ * regbase - register base address of mmc channel specified in

'index'.

Quoted 3 lines
Quoted 3 lines

drivers/mmc/exynos_dw_mmc.c line 53

Quoted 1 line
drivers/mmc/exynos_dw_mmc.c +1 -0
+ * bus_width -       operating bus width of mmc channel specified in

'index'.

Quoted 1 line
drivers/mmc/exynos_dw_mmc.c +1 -0
+ * clksel -  value to be written into CLKSEL register in case of

FDT.

Quoted 47 lines
Quoted 47 lines
Quoted 47 lines
Quoted 47 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 3 lines
drivers/mmc/exynos_dw_mmc.c +3 -0
+ *           NULL in case od non-FDT.
+ */
+int exynos_dwmci_add_port(int index, u32 regbase, int bus_width, u32

clksel)

Quoted 43 lines
drivers/mmc/exynos_dw_mmc.c +30 -1
 {
      struct dwmci_host *host = NULL;
+     unsigned int div;
+     unsigned long freq, sclk;
      host = malloc(sizeof(struct dwmci_host));
      if (!host) {
              printf("dwmci_host malloc fail!\n");
              return 1;
      }
+     /* request mmc clock vlaue of 52MHz.  */
+     freq = 52000000;
+     sclk = get_mmc_clk(index);
+     div = DIV_ROUND_UP(sclk, freq);
+     /* set the clock divisor for mmc */
+     set_mmc_clk(index, div);
 
-     host->name = EXYNOS_NAME;
+     host->name = "EXYNOS DWMMC";
      host->ioaddr = (void *)regbase;
      host->buswidth = bus_width;
+
+     if (clksel) {
+             host->clksel_val = clksel;
+     } else {
+             if (0 == index)
+                     host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;
+             if (2 == index)
+                     host->clksel_val = DWMMC_MMC2_CLKSEL_VAL;
+     }
+
      host->clksel = exynos_dwmci_clksel;
      host->dev_index = index;
+     host->mmc_clk = exynos_dwmci_get_clk;
+     /* Add the mmc channel to be registered with mmc core */
+     if (add_dwmci(host, DWMMC_MAX_FREQ, DWMMC_MIN_FREQ)) {
+             debug("dwmmc%d registration failed\n", index);
+             return -1;
+     }
+     return 0;
+}
+
+#ifdef CONFIG_OF_CONTROL
+int exynos_dwmmc_init(const void *blob)
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 8 lines
drivers/mmc/exynos_dw_mmc.c +8 -0
+{
+     int index, bus_width;
+     int node_list[DWMMC_MAX_CH_NUM];
+     int err = 0, dev_id, flag, count, i;
+     u32 clksel_val, base, timing[3];
+
+     count = fdtdec_find_aliases_for_id(blob, "mmc",
+                             COMPAT_SAMSUNG_EXYNOS5_DWMMC,

node_list,

Quoted 33 lines
Quoted 33 lines
Quoted 33 lines
Quoted 33 lines
Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+                             DWMMC_MAX_CH_NUM);
+
+     for (i = 0; i < count; i++) {
+             int node = node_list[i];

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+
+             if (node <= 0)
+                     continue;
 
-     add_dwmci(host, 52000000, 400000);
+             /* 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);

Quoted 18 lines
drivers/mmc/exynos_dw_mmc.c +18 -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;
+
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 8 lines
drivers/mmc/exynos_dw_mmc.c +8 -0
+             /* 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",

Quoted 65 lines
Quoted 50 lines
Quoted 50 lines
Quoted 47 lines

drivers/mmc/exynos_dw_mmc.c

Quoted 11 lines
drivers/mmc/exynos_dw_mmc.c +11 -0
+                                     timing, 3);
+             if (err) {
+                     debug("Can't get sdr-timings for divider\n");
+                     return -1;
+             }
+
+             clksel_val = (DWMCI_SET_SAMPLE_CLK(timing[0]) |
+                             DWMCI_SET_DRV_CLK(timing[1]) |
+                             DWMCI_SET_DIV_RATIO(timing[2]));
+             /* Initialise each mmc channel */
+             err = exynos_dwmci_add_port(index, base, bus_width,

clksel_val);

Quoted 22 lines
drivers/mmc/exynos_dw_mmc.c +4 -1
+             if (err)
+                     debug("dwmmc Channel-%d init failed\n", index);
+     }
      return 0;
 }
-
+#endif
include/dwmmc.h +2 -0
index c8b1d40..e142f3e 100644
@@ -123,6 +123,8 @@
 #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)

include/dwmmc.h struct dwmci_host { · line 152

Quoted 7 lines
include/dwmmc.h +1 -0
@@ -144,6 +146,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

Quoted 7 lines
Quoted 5 lines

_______________________________________________
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

author
#13 lore raw

PATCH v8 5/9 EXYNOS5: DWMMC: Initialise the local variable to avoid unwanted results.

In reply to Amar

This patch initialises the local variable 'shift' to zero. The uninitialised local variable 'shift' had garbage value and was resulting in unwnated results in the functions exynos5_get_mmc_clk() and exynos4_get_mmc_clk().

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

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

Changes since V3:
1)Removed the new API exynos5_mmc_set_clk_div() from clock.c, because existing API set_mmc_clk() can be used to set mmc clock.

Changes since V4:
1)Updated the subject line to reflect the changes present in this patch. 2)Changes of the file arch/arm/include/asm/arch-exynos/clk.h which were present in this patch, have been moved out of this patch.

Changes since V5:
No change.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/cpu/armv7/exynos/clock.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/exynos/clock.c +2 -2
index 223660a..cf3247a 100644
@@ -613,7 +613,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;
@@ -662,7 +662,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;
Signature · 1 line
1.8.0
#14 lore raw

PATCH v8 5/9 EXYNOS5: DWMMC: Initialise the local variable to avoid unwanted results.

Quoted 59 lines · Amar

This patch initialises the local variable 'shift' to zero. The uninitialised local variable 'shift' had garbage value and was resulting in unwnated results in the functions exynos5_get_mmc_clk() and exynos4_get_mmc_clk().

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

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

Changes since V3:
1)Removed the new API exynos5_mmc_set_clk_div() from clock.c, because existing API set_mmc_clk() can be used to set mmc clock.

Changes since V4:
1)Updated the subject line to reflect the changes present in this patch. 2)Changes of the file arch/arm/include/asm/arch-exynos/clk.h which were present in this patch, have been moved out of this patch.

Changes since V5:
No change.

Changes since V6:
No change.

Changes since V7:
No change.

 arch/arm/cpu/armv7/exynos/clock.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/exynos/clock.c +2 -2
index 223660a..cf3247a 100644
@@ -613,7 +613,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;
@@ -662,7 +662,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;
author
#15 lore raw

PATCH v8 6/9 SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT

In reply to Amar

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 since 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 since V2:
1)Updation of commit message and resubmition of proper patch set.

Changes since V3:
No change.

Changes since V4:
1)Replaced the function call 'exynos_dwmmc_init(0, 8);' with the function exynos_dwmmc_add_port() in smdk5250.c. 2)dram_init() is updated to use for loop to compute the ram size. 3)dram_init_banksize() is updated to use for loop to initialise the dram bank size.
4)board_uart_init() is updated to use for loop to initialise UARTS. 5)In non-FDT case NULL is passed as parameter to board_i2c_init().

Changes since V5:
1)Enabled CONFIG_LCD only for non-FDT operation.

Changes since V6:

	1)Re-based.

Changes since V7:
1)Re-based.
2)Because of creation of new file 'exynos5-dt.c' meant for FDT support,
the exynos_fb.c had to be updated to support non-FDT and FDT for LCD. If exynos_fb.c is not updated as per this patch the compilation fails.
3)Added the macro CONFIG_SUPPORT_EMMC_BOOT in exynos5250-dt.h.

 board/samsung/smdk5250/Makefile     |   4 +
 board/samsung/smdk5250/exynos5-dt.c | 423 ++++++++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c   | 223 +++++--------------
 drivers/video/exynos_fb.c           |   4 +-
 include/configs/exynos5250-dt.h     |   8 +
 5 files changed, 493 insertions(+), 169 deletions(-)
 create mode 100644 board/samsung/smdk5250/exynos5-dt.c
board/samsung/smdk5250/Makefile +4 -0
index 47c6a5a..ecca9f3 100644
@@ -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
board/samsung/smdk5250/exynos5-dt.c new file +423 -0

423 lines not on this page · raw message

board/samsung/smdk5250/smdk5250.c +56 -167

312 lines not on this page · raw message

drivers/video/exynos_fb.c +2 -2
index dfe329f..d3bb7f4 100644
@@ -331,10 +331,10 @@ void lcd_ctrl_init(void *lcdbase)
 #ifdef CONFIG_OF_CONTROL
 	if (exynos_fimd_parse_dt(gd->fdt_blob))
 		debug("Can't get proper panel info\n");
-#endif
+#else
 	/* initialize parameters which is specific to panel. */
 	init_panel_info(&panel_info);
-
+#endif
 	panel_width = panel_info.vl_width;
 	panel_height = panel_info.vl_height;
 
include/configs/exynos5250-dt.h +8 -0
index 496a194..e026362 100644
@@ -100,6 +100,10 @@
 #define CONFIG_MMC
 #define CONFIG_SDHCI
 #define CONFIG_S5P_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_EXYNOS_DWMMC
+#define CONFIG_SUPPORT_EMMC_BOOT
+
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
@@ -220,6 +224,10 @@
 #define SPI_FLASH_UBOOT_POS		(CONFIG_SEC_FW_SIZE + CONFIG_BL1_SIZE)
 
 #define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
 
 #define CONFIG_IRAM_STACK	0x02050000
 
Signature · 1 line
1.8.0
author
#16 lore raw

PATCH v8 7/9 MMC: APIs to support resize of EMMC boot partition

In reply to Amar

This patch adds APIs to access(open / close) and to resize boot partiton of EMMC.

---
Changes since V1:
New patch.

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

Changes since V3:
No change.

Changes since V4:
1)Replaced the functions mmc_boot_open() & mmc_boot_close() with a single function mmc_boot_part_access().

Changes since V5:
1)Updated in response to review comments.

Changes since V6:
1)Added spaces around << operator, in response to review comments.

Changes since V7:
1)In the file drivers/mmc/mmc.c, the piece of code involved in open/close and resize of EMMC boot partition has been made conditional and is enabled only if the macro CONFIG_SUPPORT_EMMC_BOOT is defined.

 drivers/mmc/mmc.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/mmc.h     |  26 +++++++++++
 2 files changed, 160 insertions(+)
drivers/mmc/mmc.c +134 -0
index d732581..a6a04e6 100644
@@ -1352,3 +1352,137 @@ int mmc_initialize(bd_t *bis)
 
 	return 0;
 }
+
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+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;
+}
+
+/*
+ * This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * Input Parameters:
+ * ack: 0x0 - No boot acknowledge sent (default)
+ *	0x1 - Boot acknowledge sent during boot operation
+ * part_num: User selects boot data that will be sent to master
+ *	0x0 - Device not boot enabled (default)
+ *	0x1 - Boot partition 1 enabled for boot
+ *	0x2 - Boot partition 2 enabled for boot
+ * access: User selects partitions to access
+ *	0x0 : No access to boot partition (default)
+ *	0x1 : R/W boot partition 1
+ *	0x2 : R/W boot partition 2
+ *	0x3 : R/W Replay Protected Memory Block (RPMB)
+ *
+ * Returns 0 on success.
+ */
+int mmc_boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access)
+{
+	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(ack) |
+			EXT_CSD_BOOT_PART_NUM(part_num) |
+			EXT_CSD_PARTITION_ACCESS(access)) << 8);
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		if (access) {
+			debug("mmc boot partition#%d open fail:Error1 = %d\n",
+			      part_num, err);
+		} else {
+			debug("mmc boot partition#%d close fail:Error = %d\n",
+			      part_num, err);
+		}
+		return err;
+	}
+
+	if (access) {
+		/* 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 partition#%d open fail:Error2 = %d\n",
+			      part_num, err);
+			return err;
+		}
+	}
+	return 0;
+}
+#endif
include/mmc.h +26 -0
index de6d497..ab93576 100644
@@ -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,16 @@
 #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 EXT_CSD_BOOT_ACK(x)		(x << 6)
+#define EXT_CSD_BOOT_PART_NUM(x)	(x << 3)
+#define EXT_CSD_PARTITION_ACCESS(x)	(x << 0)
+
+
 #define R1_ILLEGAL_COMMAND		(1 << 22)
 #define R1_APP_CMD			(1 << 5)
 
@@ -201,6 +217,11 @@
 #define PART_ACCESS_MASK	(0x7)
 #define PART_SUPPORT		(0x1)
 
+/* The number of MMC physical partitions.  These consist of:
+ * boot partitions (2), general purpose partitions (4) in MMC v4.4.
+ */
+#define MMC_NUM_BOOT_PARTITION	2
+
 struct mmc_cid {
 	unsigned long psn;
 	unsigned short oid;
@@ -277,6 +298,11 @@ int mmc_switch_part(int dev_num, unsigned int part_num);
 int mmc_getcd(struct mmc *mmc);
 int mmc_getwp(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;
+/* Function to change the size of boot partition and rpmb partitions */
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+					unsigned long rpmbsize);
+/* Function to send commands to open/close the specified boot partition */
+int mmc_boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access);
 
 #ifdef CONFIG_GENERIC_MMC
 #define mmc_host_is_spi(mmc)	((mmc)->host_caps & MMC_MODE_SPI)
Signature · 1 line
1.8.0
author
#17 lore raw

PATCH v8 8/9 SMDK5250: Enable EMMC booting

In reply to Amar

This patch adds support for EMMC booting on SMDK5250.

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

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

Changes since V3:
No change.

Changes since V4:
1)The function get_irom_func(int index) has been added to avoid type casting at many places.
2)The changes to file arch/arm/include/asm/arch-exynos/clk.h are included in this patch file.

Changes since V5:
No change.

Changes since V6:
No change.

Changes since V7:
1)The macros FSYS1_MMC0_DIV_MASK and FSYS1_MMC0_DIV_VAL are made local to file clock_init.c.

 board/samsung/smdk5250/clock_init.c | 18 +++++++++++++
 board/samsung/smdk5250/clock_init.h |  5 ++++
 board/samsung/smdk5250/spl_boot.c   | 52 ++++++++++++++++++++++++++++++++-----
 3 files changed, 69 insertions(+), 6 deletions(-)
board/samsung/smdk5250/clock_init.c +18 -0
index 5b9e82f..b288e66 100644
@@ -28,10 +28,14 @@
 #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"
 
+#define FSYS1_MMC0_DIV_MASK	0xff0f
+#define FSYS1_MMC0_DIV_VAL	0x0701
+
 DECLARE_GLOBAL_DATA_PTR;
 
 struct arm_clk_ratios arm_clk_ratios[] = {
@@ -664,3 +668,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);
+}
board/samsung/smdk5250/clock_init.h +5 -0
index f751bcb..20a1d47 100644
@@ -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
board/samsung/smdk5250/spl_boot.c +46 -6

84 lines not on this page · raw message

Signature · 1 line
1.8.0
author
#18 lore raw

PATCH v8 9/9 COMMON: MMC: Command to support EMMC booting and to resize EMMC boot partition

In reply to Amar

This patch adds commands to access(open/close) and resize boot partitions on EMMC.

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

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

Changes since V3:
No change.

Changes since V4:
1)Added a new funtion boot_part_access() to combine the common parts of 'mmc open' and 'mmc close' functionalities.
2)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing so user can specify which boot partition to be accessed (opened / closed).

Changes since V5:
1)Updated minor nits in response to review comments.

Changes since V6:
No change.

Changes since V7:
1)The piece of code involved in open/close and resize of EMMC boot partition has been made conditional and is enabled only if the macro CONFIG_SUPPORT_EMMC_BOOT is defined.

 common/cmd_mmc.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 108 insertions(+), 2 deletions(-)
common/cmd_mmc.c +108 -2
index 8c53a10..c5f60a2 100644
@@ -147,6 +147,36 @@ U_BOOT_CMD(
 	"- display info of the current MMC device"
 );
 
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access)
+{
+	int err;
+	err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+	if ((err == 0) && (access != 0)) {
+		printf("\t\t\t!!!Notice!!!\n");
+
+		printf("!You must close EMMC boot Partition");
+		printf("after all images are written\n");
+
+		printf("!EMMC boot partition has continuity");
+		printf("at image writing time.\n");
+
+		printf("!So, do not close the boot partition");
+		printf("before all images are written.\n");
+		return 0;
+	} else if ((err == 0) && (access == 0))
+		return 0;
+	else if ((err != 0) && (access != 0)) {
+		printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+		return 1;
+	} else {
+		printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+		return 1;
+	}
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	enum mmc_state state;
@@ -248,8 +278,75 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 				curr_device, mmc->part_num);
 
 		return 0;
-	}
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	} else if ((strcmp(argv[1], "open") == 0) ||
+			(strcmp(argv[1], "close") == 0)) {
+		int dev;
+		struct mmc *mmc;
+		u32 ack, part_num, access = 0;
+
+		if (argc == 4) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			part_num = simple_strtoul(argv[3], 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 ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
+			printf("Invalid boot partition number:\n");
+			printf("Boot partition number cannot be <= 0\n");
+			printf("EMMC44 supports only 2 boot partitions\n");
+			return 1;
+		}
+
+		if (strcmp(argv[1], "open") == 0)
+			access = part_num; /* enable R/W access to boot part*/
+		if (strcmp(argv[1], "close") == 0)
+			access = 0; /* No access to boot partition */
+
+		/* acknowledge to be sent during boot operation */
+		ack = 1;
+		return boot_part_access(mmc, ack, part_num, access);
+
+	} 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@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;
+		}
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+	}
 	state = MMC_INVALID;
 	if (argc == 5 && strcmp(argv[1], "read") == 0)
 		state = MMC_READ;
@@ -324,5 +421,14 @@ 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"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	"mmc open <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and enable R/W access of boot_part\n"
+	"mmc close <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and disable access to boot_part\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
+	);
+#endif /* !CONFIG_GENERIC_MMC */
Signature · 1 line
1.8.0
#19 lore raw

PATCH v8 9/9 COMMON: MMC: Command to support EMMC booting and to resize EMMC boot partition

Hi Amar,

Quoted 40 lines · Amar

This patch adds commands to access(open/close) and resize boot partitions on EMMC.

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

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

Changes since V3:
No change.

Changes since V4:
1)Added a new funtion boot_part_access() to combine the common parts of 'mmc open' and 'mmc close' functionalities.
2)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing so user can specify which boot partition to be accessed (opened / closed).

Changes since V5:
1)Updated minor nits in response to review comments.

Changes since V6:
No change.

Changes since V7:
1)The piece of code involved in open/close and resize of EMMC boot partition has been made conditional and is enabled only if the macro CONFIG_SUPPORT_EMMC_BOOT is defined.

 common/cmd_mmc.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 108 insertions(+), 2 deletions(-)
common/cmd_mmc.c +0 -0
index 8c53a10..c5f60a2 100644

common/cmd_mmc.c U_BOOT_CMD( · line 151

Quoted 5 lines
common/cmd_mmc.c +2 -0
@@ -147,6 +147,36 @@ U_BOOT_CMD(
 	"- display info of the current MMC device"
 );
 
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access)

Why do you use u32? I know that just used 8bit.

Quoted 55 lines
common/cmd_mmc.c +46 -1
+{
+	int err;
+	err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+	if ((err == 0) && (access != 0)) {
+		printf("\t\t\t!!!Notice!!!\n");
+
+		printf("!You must close EMMC boot Partition");
+		printf("after all images are written\n");
+
+		printf("!EMMC boot partition has continuity");
+		printf("at image writing time.\n");
+
+		printf("!So, do not close the boot partition");
+		printf("before all images are written.\n");
+		return 0;
+	} else if ((err == 0) && (access == 0))
+		return 0;
+	else if ((err != 0) && (access != 0)) {
+		printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+		return 1;
+	} else {
+		printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+		return 1;
+	}
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	enum mmc_state state;
@@ -248,8 +278,75 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 				curr_device, mmc->part_num);
 
 		return 0;
-	}
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	} else if ((strcmp(argv[1], "open") == 0) ||
+			(strcmp(argv[1], "close") == 0)) {
+		int dev;
+		struct mmc *mmc;
+		u32 ack, part_num, access = 0;
+
+		if (argc == 4) {
+			dev = simple_strtoul(argv[2], NULL, 10);
+			part_num = simple_strtoul(argv[3], 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;
+		}

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 309

Quoted 10 lines
common/cmd_mmc.c +10 -0
+
+		if (IS_SD(mmc)) {
+			printf("SD device cannot be opened/closed\n");
+			return 1;
+		}
+
+		if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
+			printf("Invalid boot partition number:\n");
+			printf("Boot partition number cannot be <= 0\n");
+			printf("EMMC44 supports only 2 boot partitions\n");

What means? EMMC44 supports only 2 boot partitions?

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 315

Quoted 6 lines
common/cmd_mmc.c +6 -0
+			return 1;
+		}
+
+		if (strcmp(argv[1], "open") == 0)
+			access = part_num; /* enable R/W access to boot part*/
+		if (strcmp(argv[1], "close") == 0)

else if?

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 319

Quoted 4 lines
common/cmd_mmc.c +4 -0
+			access = 0; /* No access to boot partition */
+
+		/* acknowledge to be sent during boot operation */
+		ack = 1;

ack is always set to 1? then Can't initialize ack value as 1. Otherwise, boot_part_access(mmc, 1, part_num, access)?

Best Regards,
Jaehoon Chung

Quoted 50 lines
common/cmd_mmc.c +40 -1
+		return boot_part_access(mmc, ack, part_num, access);
+
+	} 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;
+		}
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+	}
 	state = MMC_INVALID;
 	if (argc == 5 && strcmp(argv[1], "read") == 0)
 		state = MMC_READ;
@@ -324,5 +421,14 @@ 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"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+	"mmc open <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and enable R/W access of boot_part\n"
+	"mmc close <dev> <boot_partition>\n"
+	" - Enable boot_part for booting and disable access to boot_part\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
+	);
+#endif /* !CONFIG_GENERIC_MMC */
#20 lore raw

PATCH v8 9/9 COMMON: MMC: Command to support EMMC booting and to resize EMMC boot partition

Hi Jaehoon,

Please find the responses below

Thanks & Regards
Amarendra Reddy

Quoted 51 lines · Jaehoon Chung

Hi Amar,

Quoted 1 line · Amar

This patch adds commands to access(open/close) and resize boot

partitions on EMMC.

Quoted 7 lines

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

Quoted 8 lines

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

Changes since V3:
No change.

Changes since V4:
1)Added a new funtion boot_part_access() to combine the common

parts of

Quoted 3 lines

'mmc open' and 'mmc close' functionalities.
2)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing

so user

Quoted 11 lines

can specify which boot partition to be accessed (opened / closed).

Changes since V5:
1)Updated minor nits in response to review comments.

Changes since V6:
No change.

Changes since V7:
1)The piece of code involved in open/close and resize of EMMC boot partition has been made conditional and is enabled only if the

macro

Quoted 3 lines

CONFIG_SUPPORT_EMMC_BOOT is defined.

 common/cmd_mmc.c | 110

++++++++++++++++++++++++++++++++++++++++++++++++++++++-

Quoted 10 lines
 1 file changed, 108 insertions(+), 2 deletions(-)
common/cmd_mmc.c +0 -0
index 8c53a10..c5f60a2 100644
@@ -147,6 +147,36 @@ U_BOOT_CMD(
      "- display info of the current MMC device"
 );
 
Quoted 5 lines

common/cmd_mmc.c U_BOOT_CMD( · line 151

Quoted 2 lines
common/cmd_mmc.c +2 -0
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32

access)
Why do you use u32? I know that just used 8bit.

Yes, just 8bit would suffice. I will update it.

Quoted 65 lines

+{

Quoted 18 lines
common/cmd_mmc.c +18 -0
+     int err;
+     err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+     if ((err == 0) && (access != 0)) {
+             printf("\t\t\t!!!Notice!!!\n");
+
+             printf("!You must close EMMC boot Partition");
+             printf("after all images are written\n");
+
+             printf("!EMMC boot partition has continuity");
+             printf("at image writing time.\n");
+
+             printf("!So, do not close the boot partition");
+             printf("before all images are written.\n");
+             return 0;
+     } else if ((err == 0) && (access == 0))
+             return 0;
+     else if ((err != 0) && (access != 0)) {

common/cmd_mmc.c U_BOOT_CMD(

Quoted 10 lines
common/cmd_mmc.c +9 -0
+             printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+             return 1;
+     } else {
+             printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+             return 1;
+     }
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const

argv[])

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

Quoted 3 lines
common/cmd_mmc.c +0 -0
 {
      enum mmc_state state;
@@ -248,8 +278,75 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

Quoted 20 lines
common/cmd_mmc.c +15 -1
                              curr_device, mmc->part_num);
 
              return 0;
-     }
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     } else if ((strcmp(argv[1], "open") == 0) ||
+                     (strcmp(argv[1], "close") == 0)) {
+             int dev;
+             struct mmc *mmc;
+             u32 ack, part_num, access = 0;
+
+             if (argc == 4) {
+                     dev = simple_strtoul(argv[2], NULL, 10);
+                     part_num = simple_strtoul(argv[3], NULL, 10);
+             } else {
+                     return CMD_RET_USAGE;
+             }
 
+             mmc = find_mmc_device(dev);
+             if (!mmc) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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 ((part_num <= 0) || (part_num >

MMC_NUM_BOOT_PARTITION)) {

Quoted 5 lines

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 309

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     printf("Invalid boot partition number:\n");
+                     printf("Boot partition number cannot be <= 0\n");
+                     printf("EMMC44 supports only 2 boot partitions\n");

What means? EMMC44 supports only 2 boot partitions?

As per the eMMC 4.4 specification, eMMC 4.4 has 1 RPMB partition, 2 Boot partitions and 4 General Purpose partitions.
As there are only 2 Boot partitions, we restrict the user not to use an invalid partition number.

Quoted 9 lines

+ return 1;

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 4 lines
common/cmd_mmc.c +4 -0
+             }
+
+             if (strcmp(argv[1], "open") == 0)
+                     access = part_num; /* enable R/W access to boot

part*/

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 315

Quoted 1 line
common/cmd_mmc.c +1 -0
+             if (strcmp(argv[1], "close") == 0)

else if?

Even 'else if' is fine, but I wanted to explicitly check the string in both cases.

Quoted 8 lines

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 319

Quoted 4 lines
common/cmd_mmc.c +4 -0
+                     access = 0; /* No access to boot partition */
+
+             /* acknowledge to be sent during boot operation */
+             ack = 1;

ack is always set to 1? then Can't initialize ack value as 1. Otherwise, boot_part_access(mmc, 1, part_num, access)?

As per JEDEC Standard 'ack' can be 0 / 1.

Right now we are always using ack=1.
Is it OK to use "boot_part_access(mmc, 1, part_num, access)" with a hardcoded value '1' in the function call ?

Best Regards,

Quoted 64 lines

Jaehoon Chung

Quoted 11 lines
common/cmd_mmc.c +11 -0
+             return boot_part_access(mmc, ack, part_num, access);
+
+     } 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);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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)) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 340

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC boot partition Size %d MB\n",

bootsize);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 341

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC RPMB partition Size %d MB\n",

rpmbsize);

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     return 0;
+             } else {
+                     printf("EMMC boot partition Size change

Failed.\n");

common/cmd_mmc.c U_BOOT_CMD( · line 423

Quoted 11 lines
common/cmd_mmc.c +4 -0
+                     return 1;
+             }
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+     }
      state = MMC_INVALID;
      if (argc == 5 && strcmp(argv[1], "read") == 0)
              state = MMC_READ;
@@ -324,5 +421,14 @@ 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"

common/cmd_mmc.c U_BOOT_CMD(

Quoted 5 lines
common/cmd_mmc.c +4 -1
-     "mmc list - lists available devices");
+     "mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     "mmc open <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and enable R/W access of

boot_part\n"

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+     "mmc close <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and disable access to boot_part\n"
+     "mmc bootpart <device num> <boot part size MB> <RPMB part size

MB>\n"

common/cmd_mmc.c U_BOOT_CMD( · line 434

Quoted 5 lines
common/cmd_mmc.c +3 -0
+     " - change sizes of boot and RPMB partions of specified device\n"
 #endif
+     );
+#endif /* !CONFIG_GENERIC_MMC */

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

#21 lore raw

PATCH v8 9/9 COMMON: MMC: Command to support EMMC booting and to resize EMMC boot partition

Dear Amarendra,

Quoted 149 lines · Amarendra Reddy

Hi Jaehoon,

Please find the responses below

Thanks & Regards
Amarendra Reddy

Quoted 51 lines · Jaehoon Chung

Hi Amar,

Quoted 1 line · Amar

This patch adds commands to access(open/close) and resize boot

partitions on EMMC.

Quoted 7 lines

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

Quoted 8 lines

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

Changes since V3:
No change.

Changes since V4:
1)Added a new funtion boot_part_access() to combine the common

parts of

Quoted 3 lines

'mmc open' and 'mmc close' functionalities.
2)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing

so user

Quoted 11 lines

can specify which boot partition to be accessed (opened / closed).

Changes since V5:
1)Updated minor nits in response to review comments.

Changes since V6:
No change.

Changes since V7:
1)The piece of code involved in open/close and resize of EMMC boot partition has been made conditional and is enabled only if the

macro

Quoted 3 lines

CONFIG_SUPPORT_EMMC_BOOT is defined.

 common/cmd_mmc.c | 110

++++++++++++++++++++++++++++++++++++++++++++++++++++++-

Quoted 10 lines
 1 file changed, 108 insertions(+), 2 deletions(-)
common/cmd_mmc.c +0 -0
index 8c53a10..c5f60a2 100644
@@ -147,6 +147,36 @@ U_BOOT_CMD(
      "- display info of the current MMC device"
 );
 
Quoted 5 lines

common/cmd_mmc.c U_BOOT_CMD( · line 151

Quoted 2 lines
common/cmd_mmc.c +2 -0
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32

access)
Why do you use u32? I know that just used 8bit.

Yes, just 8bit would suffice. I will update it.

Quoted 65 lines

+{

Quoted 18 lines
common/cmd_mmc.c +18 -0
+     int err;
+     err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+     if ((err == 0) && (access != 0)) {
+             printf("\t\t\t!!!Notice!!!\n");
+
+             printf("!You must close EMMC boot Partition");
+             printf("after all images are written\n");
+
+             printf("!EMMC boot partition has continuity");
+             printf("at image writing time.\n");
+
+             printf("!So, do not close the boot partition");
+             printf("before all images are written.\n");
+             return 0;
+     } else if ((err == 0) && (access == 0))
+             return 0;
+     else if ((err != 0) && (access != 0)) {

common/cmd_mmc.c U_BOOT_CMD(

Quoted 10 lines
common/cmd_mmc.c +9 -0
+             printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+             return 1;
+     } else {
+             printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+             return 1;
+     }
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const

argv[])

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

Quoted 3 lines
common/cmd_mmc.c +0 -0
 {
      enum mmc_state state;
@@ -248,8 +278,75 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

Quoted 20 lines
common/cmd_mmc.c +15 -1
                              curr_device, mmc->part_num);
 
              return 0;
-     }
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     } else if ((strcmp(argv[1], "open") == 0) ||
+                     (strcmp(argv[1], "close") == 0)) {
+             int dev;
+             struct mmc *mmc;
+             u32 ack, part_num, access = 0;
+
+             if (argc == 4) {
+                     dev = simple_strtoul(argv[2], NULL, 10);
+                     part_num = simple_strtoul(argv[3], NULL, 10);
+             } else {
+                     return CMD_RET_USAGE;
+             }
 
+             mmc = find_mmc_device(dev);
+             if (!mmc) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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 ((part_num <= 0) || (part_num >

MMC_NUM_BOOT_PARTITION)) {

Quoted 5 lines

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 309

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     printf("Invalid boot partition number:\n");
+                     printf("Boot partition number cannot be <= 0\n");
+                     printf("EMMC44 supports only 2 boot partitions\n");

What means? EMMC44 supports only 2 boot partitions?

As per the eMMC 4.4 specification, eMMC 4.4 has 1 RPMB partition, 2 Boot partitions and 4 General Purpose partitions.
As there are only 2 Boot partitions, we restrict the user not to use an invalid partition number.

Quoted 5 lines

+ return 1;

Quoted 4 lines
common/cmd_mmc.c +4 -0
+             }
+
+             if (strcmp(argv[1], "open") == 0)
+                     access = part_num; /* enable R/W access to boot
Quoted 7 lines
Quoted 4 lines

part*/

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 315

Quoted 1 line
common/cmd_mmc.c +1 -0
+             if (strcmp(argv[1], "close") == 0)

else if?

Even 'else if' is fine, but I wanted to explicitly check the string in both cases.

Why? I think, It doesn't make sense.

Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
common/cmd_mmc.c +4 -0
+                     access = 0; /* No access to boot partition */
+
+             /* acknowledge to be sent during boot operation */
+             ack = 1;
Quoted 7 lines
Quoted 4 lines

ack is always set to 1? then Can't initialize ack value as 1. Otherwise, boot_part_access(mmc, 1, part_num, access)?

As per JEDEC Standard 'ack' can be 0 / 1.

Right now we are always using ack=1.
Is it OK to use "boot_part_access(mmc, 1, part_num, access)" with a hardcoded value '1' in the function call ?

Yes, It's a constant.

Quoted 69 lines

Best Regards,

Quoted 59 lines

Jaehoon Chung

Quoted 11 lines
common/cmd_mmc.c +11 -0
+             return boot_part_access(mmc, ack, part_num, access);
+
+     } 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);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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)) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 340

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC boot partition Size %d MB\n",

bootsize);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 341

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC RPMB partition Size %d MB\n",

rpmbsize);

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     return 0;
+             } else {
+                     printf("EMMC boot partition Size change

Failed.\n");

common/cmd_mmc.c U_BOOT_CMD( · line 423

Quoted 11 lines
common/cmd_mmc.c +4 -0
+                     return 1;
+             }
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+     }
      state = MMC_INVALID;
      if (argc == 5 && strcmp(argv[1], "read") == 0)
              state = MMC_READ;
@@ -324,5 +421,14 @@ 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"

common/cmd_mmc.c U_BOOT_CMD(

Quoted 5 lines
common/cmd_mmc.c +4 -1
-     "mmc list - lists available devices");
+     "mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     "mmc open <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and enable R/W access of

boot_part\n"

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+     "mmc close <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and disable access to boot_part\n"
+     "mmc bootpart <device num> <boot part size MB> <RPMB part size

MB>\n"

common/cmd_mmc.c U_BOOT_CMD( · line 434

Quoted 5 lines
common/cmd_mmc.c +3 -0
+     " - change sizes of boot and RPMB partions of specified device\n"
 #endif
+     );
+#endif /* !CONFIG_GENERIC_MMC */
Quoted 5 lines

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

Quoted 5 lines

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

Thanks,
Minkyu Kang.

#22 lore raw

PATCH v8 9/9 COMMON: MMC: Command to support EMMC booting and to resize EMMC boot partition

Dear Minkyu,

Thankyou for the review comments.
Please find my responses below.

Thanks & Regards
Amarendra Reddy

Quoted 179 lines · Minkyu Kang

Dear Amarendra,

Quoted 35 lines · Amarendra Reddy

Hi Jaehoon,

Please find the responses below

Thanks & Regards
Amarendra Reddy

Quoted 26 lines · Jaehoon Chung

Hi Amar,

Quoted 1 line · Amar

This patch adds commands to access(open/close) and resize boot

partitions on EMMC.

Quoted 7 lines

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

Quoted 8 lines

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

Changes since V3:
No change.

Changes since V4:
1)Added a new funtion boot_part_access() to combine the common

parts of

Quoted 3 lines

'mmc open' and 'mmc close' functionalities.
2)Used the generic function "mmc_boot_part_access()" instead of two functions "mmc_boot_open()" and "mmc_boot_close()". By doing

so user

Quoted 1 line

can specify which boot partition to be accessed (opened /

closed).

Quoted 9 lines
Quoted 9 lines
Quoted 9 lines

Changes since V5:
1)Updated minor nits in response to review comments.

Changes since V6:
No change.

Changes since V7:
1)The piece of code involved in open/close and resize of EMMC

boot

Quoted 16 lines
Quoted 16 lines
Quoted 1 line

partition has been made conditional and is enabled only if the

macro

Quoted 3 lines

CONFIG_SUPPORT_EMMC_BOOT is defined.

 common/cmd_mmc.c | 110

++++++++++++++++++++++++++++++++++++++++++++++++++++++-

Quoted 10 lines
 1 file changed, 108 insertions(+), 2 deletions(-)
common/cmd_mmc.c +0 -0
index 8c53a10..c5f60a2 100644
@@ -147,6 +147,36 @@ U_BOOT_CMD(
      "- display info of the current MMC device"
 );
 
Quoted 2 lines
Quoted 2 lines

common/cmd_mmc.c U_BOOT_CMD( · line 151

Quoted 2 lines
common/cmd_mmc.c +2 -0
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num,

u32

Quoted 18 lines
Quoted 3 lines

access)
Why do you use u32? I know that just used 8bit.

Yes, just 8bit would suffice. I will update it.

Quoted 12 lines

+{

Quoted 11 lines
common/cmd_mmc.c +11 -0
+     int err;
+     err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+     if ((err == 0) && (access != 0)) {
+             printf("\t\t\t!!!Notice!!!\n");
+
+             printf("!You must close EMMC boot Partition");
+             printf("after all images are written\n");
+
+             printf("!EMMC boot partition has continuity");
+             printf("at image writing time.\n");
Quoted 8 lines
Quoted 8 lines

common/cmd_mmc.c U_BOOT_CMD(

Quoted 8 lines
common/cmd_mmc.c +8 -0
+
+             printf("!So, do not close the boot partition");
+             printf("before all images are written.\n");
+             return 0;
+     } else if ((err == 0) && (access == 0))
+             return 0;
+     else if ((err != 0) && (access != 0)) {
+             printf("EMMC boot partition-%d OPEN Failed.\n",

part_num);

Quoted 3 lines
Quoted 3 lines

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+             return 1;
+     } else {
+             printf("EMMC boot partition-%d CLOSE Failed.\n",

part_num);

Quoted 6 lines
Quoted 6 lines

common/cmd_mmc.c U_BOOT_CMD(

Quoted 6 lines
common/cmd_mmc.c +5 -0
+             return 1;
+     }
+}
+#endif
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *

const

Quoted 36 lines
Quoted 36 lines

argv[])

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

Quoted 3 lines
common/cmd_mmc.c +0 -0
 {
      enum mmc_state state;
@@ -248,8 +278,75 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

Quoted 20 lines
common/cmd_mmc.c +15 -1
                              curr_device, mmc->part_num);
 
              return 0;
-     }
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     } else if ((strcmp(argv[1], "open") == 0) ||
+                     (strcmp(argv[1], "close") == 0)) {
+             int dev;
+             struct mmc *mmc;
+             u32 ack, part_num, access = 0;
+
+             if (argc == 4) {
+                     dev = simple_strtoul(argv[2], NULL, 10);
+                     part_num = simple_strtoul(argv[3], NULL, 10);
+             } else {
+                     return CMD_RET_USAGE;
+             }
 
+             mmc = find_mmc_device(dev);
+             if (!mmc) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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 ((part_num <= 0) || (part_num >

MMC_NUM_BOOT_PARTITION)) {

Quoted 3 lines
Quoted 3 lines

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     printf("Invalid boot partition number:\n");
+                     printf("Boot partition number cannot be <= 0\n");
+                     printf("EMMC44 supports only 2 boot

partitions\n");

Quoted 13 lines
Quoted 2 lines

What means? EMMC44 supports only 2 boot partitions?

As per the eMMC 4.4 specification, eMMC 4.4 has 1 RPMB partition, 2 Boot partitions and 4 General Purpose partitions.
As there are only 2 Boot partitions, we restrict the user not to use an invalid partition number.

Quoted 5 lines

+ return 1;

Quoted 4 lines
common/cmd_mmc.c +4 -0
+             }
+
+             if (strcmp(argv[1], "open") == 0)
+                     access = part_num; /* enable R/W access to boot
Quoted 6 lines
Quoted 4 lines

part*/

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 315

Quoted 1 line
common/cmd_mmc.c +1 -0
+             if (strcmp(argv[1], "close") == 0)

else if?

Even 'else if' is fine, but I wanted to explicitly check the string in

both

Quoted 1 line

cases.

Why? I think, It doesn't make sense.
OK. I will replace the above with 'else if'.

Quoted 9 lines
Quoted 9 lines

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) · line 319

Quoted 6 lines
common/cmd_mmc.c +4 -0
+                     access = 0; /* No access to boot partition */
+
+             /* acknowledge to be sent during boot operation */
+             ack = 1;

ack is always set to 1? then Can't initialize ack value as 1. Otherwise, boot_part_access(mmc, 1, part_num, access)?

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

As per JEDEC Standard 'ack' can be 0 / 1.

Right now we are always using ack=1.
Is it OK to use "boot_part_access(mmc, 1, part_num, access)" with a hardcoded value '1' in the function call ?

Yes, It's a constant.

I meant from uboot coding standard point of view.
Ok. I shall use 'boot_part_access(mmc, 1, part_num, access)' in next patchset.

Quoted 80 lines
Quoted 53 lines

Best Regards,

Quoted 51 lines

Jaehoon Chung

Quoted 11 lines
common/cmd_mmc.c +11 -0
+             return boot_part_access(mmc, ack, part_num, access);
+
+     } 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);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])

Quoted 10 lines
common/cmd_mmc.c +10 -0
+                     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)) {

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 340

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC boot partition Size %d MB\n",

bootsize);

common/cmd_mmc.c static int do_mmcops(cmd_tbl_t *cmdtp, int flag, · line 341

Quoted 1 line
common/cmd_mmc.c +1 -0
+                     printf("EMMC RPMB partition Size %d MB\n",

rpmbsize);

common/cmd_mmc.c U_BOOT_CMD(

Quoted 3 lines
common/cmd_mmc.c +3 -0
+                     return 0;
+             } else {
+                     printf("EMMC boot partition Size change

Failed.\n");

common/cmd_mmc.c U_BOOT_CMD( · line 423

Quoted 11 lines
common/cmd_mmc.c +4 -0
+                     return 1;
+             }
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+     }
      state = MMC_INVALID;
      if (argc == 5 && strcmp(argv[1], "read") == 0)
              state = MMC_READ;
@@ -324,5 +421,14 @@ 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"

common/cmd_mmc.c U_BOOT_CMD(

Quoted 5 lines
common/cmd_mmc.c +4 -1
-     "mmc list - lists available devices");
+     "mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+     "mmc open <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and enable R/W access of

boot_part\n"

Quoted 2 lines
common/cmd_mmc.c +2 -0
+     "mmc close <dev> <boot_partition>\n"
+     " - Enable boot_part for booting and disable access to

boot_part\n"

Quoted 16 lines
Quoted 8 lines

common/cmd_mmc.c U_BOOT_CMD( · line 430

Quoted 1 line
common/cmd_mmc.c +1 -0
+     "mmc bootpart <device num> <boot part size MB> <RPMB part size

MB>\n"

common/cmd_mmc.c U_BOOT_CMD( · line 434

Quoted 5 lines
common/cmd_mmc.c +3 -0
+     " - change sizes of boot and RPMB partions of specified device\n"
 #endif
+     );
+#endif /* !CONFIG_GENERIC_MMC */
Quoted 5 lines

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

Quoted 5 lines

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

Thanks,
Minkyu Kang.