Skip to contentSkip to conversation

EXYNOS5: Enable DWMMC, add FDT support for DWMMC and enable EMMC boot

PATCH Superseded Amar 4 participants 35 messages Jan 21, 2013 – Feb 15, 2013

Subsystems (5)

v5 of 9 Superseded Latest is v9 →

lore
Share & tools
lore

Amar

author
#0 lore raw

v5 cover EXYNOS5: Enable DWMMC, add FDT support for DWMMC and enable EMMC boot

This patch set enables and initialises DWMMC for Exynos5250 on SMDK5250. Adds driver changes required for DWMMC.
Adds FDT support for DWMMC.
Adds EMMC boot support for SMDK5250.

This patch set is based on:
"EXYNOS: mmc: support DesignWare Controller for Samsung-SoC", which is merged in u-boot-mmc.
"Exynos: clock: support get_mmc_clk for exynos".
"Add DT based ethernet driver for SMDK5250".
"SMDK5250: Add FDT support" present at the following link
http://comments.gmane.org/gmane.comp.boot-loaders.u-boot/149991

Changes 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)Replaced the device node name 'dwmmc' with 'mmc'. 2)Updated the function dwmci_send_cmd() to use get_timer() instead of using mdelay(1) in the file drivers/mmc/dw_mmc.c. 3)Replaced 'unsigned int exynos_dwmmc_init()' with
'int exynos_dwmci_add_port(int, u32, int, u32)'.
4)The functions dram_init(), dram_init_banksize() and board_uart_init() are updated to use for loop.
5)Replaced the functions mmc_boot_open() & mmc_boot_close() with a
single function mmc_boot_part_access().
6)Added new patch which adds FDT and non-FDT support for I2C. 7)Updated in response to review comments.

Amar (10):
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
EXYNOS5: I2C: Added FDT and non-FDT support for I2C

 arch/arm/cpu/armv7/exynos/clock.c         |   4 +-
 arch/arm/dts/exynos5250.dtsi              |  31 +++++
 arch/arm/include/asm/arch-exynos/clk.h    |   3 +
 arch/arm/include/asm/arch-exynos/dwmmc.h  |  11 +-
 board/samsung/dts/exynos5250-smdk5250.dts |  22 ++++
 board/samsung/smdk5250/Makefile           |   4 +
 board/samsung/smdk5250/clock_init.c       |  15 +++
 board/samsung/smdk5250/clock_init.h       |   5 +
 board/samsung/smdk5250/exynos5-dt.c       | 211 ++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c         | 170 ++++++++----------------
 board/samsung/smdk5250/spl_boot.c         |  52 +++++++-
 common/cmd_mmc.c                          |  98 +++++++++++++-
 doc/device-tree-bindings/exynos/dwmmc.txt |  49 +++++++
 drivers/i2c/s3c24x0_i2c.c                 |  13 +-
 drivers/mmc/dw_mmc.c                      |  23 +++-
 drivers/mmc/exynos_dw_mmc.c               | 127 ++++++++++++++++--
 drivers/mmc/mmc.c                         | 117 +++++++++++++++++
 include/configs/exynos5250-dt.h           |   6 +
 include/dwmmc.h                           |   3 +
 include/fdtdec.h                          |   1 +
 include/mmc.h                             |  24 ++++
 lib/fdtdec.c                              |   1 +
 22 files changed, 843 insertions(+), 147 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 v5 1/10 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.

 include/fdtdec.h | 1 +
 lib/fdtdec.c     | 1 +
 2 files changed, 2 insertions(+)
include/fdtdec.h +1 -0
index f77d195..fb4c33f 100644
@@ -79,6 +79,7 @@ enum fdt_compat_id {
 	COMPAT_SAMSUNG_EXYNOS_EHCI,	/* Exynos EHCI controller */
 	COMPAT_SAMSUNG_EXYNOS_USB_PHY,	/* Exynos phy controller for usb2.0 */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
+	COMPAT_SAMSUNG_EXYNOS5_DWMMC,	/* Exynos5 DWMMC controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 16921e1..1a4763e 100644
@@ -54,6 +54,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
 	COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
+	COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
Signature · 1 line
1.8.0
#2 lore raw

PATCH v5 1/10 FDT: Add compatible string for DWMMC

Quoted 47 lines · Amar

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.

 include/fdtdec.h | 1 +
 lib/fdtdec.c     | 1 +
 2 files changed, 2 insertions(+)
include/fdtdec.h +1 -0
index f77d195..fb4c33f 100644
@@ -79,6 +79,7 @@ enum fdt_compat_id {
 	COMPAT_SAMSUNG_EXYNOS_EHCI,	/* Exynos EHCI controller */
 	COMPAT_SAMSUNG_EXYNOS_USB_PHY,	/* Exynos phy controller for usb2.0 */
 	COMPAT_MAXIM_MAX77686_PMIC,	/* MAX77686 PMIC */
+	COMPAT_SAMSUNG_EXYNOS5_DWMMC,	/* Exynos5 DWMMC controller */
 
 	COMPAT_COUNT,
 };
lib/fdtdec.c +1 -0
index 16921e1..1a4763e 100644
@@ -54,6 +54,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
 	COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
 	COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
 	COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
+	COMPAT(SAMSUNG_EXYNOS5_DWMMC, "samsung,exynos5250-dwmmc"),
 };
 
 const char *fdtdec_get_compatible(enum fdt_compat_id id)
author
#3 lore raw

PATCH v5 2/10 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'.

 arch/arm/dts/exynos5250.dtsi              | 31 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 22 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 49 +++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
arch/arm/dts/exynos5250.dtsi +31 -0
index ed8c8dd..6c08eb7 100644
@@ -151,4 +151,35 @@
 		};
 	};
 
+	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 +22 -0
index cbfab6f..1d3e42b 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 {
@@ -66,4 +70,22 @@
 			compatible = "maxim,max77686_pmic";
 		};
 	};
+
+	mmc at 12200000 {
+		samsung,bus-width = <8>;
+		samsung,timing = <1 3 3>;
+	};
+
+	mmc at 12210000 {
+		status = "disabled";
+	};
+
+	mmc at 12220000 {
+		samsung,bus-width = <4>;
+		samsung,timing = <1 2 3>;
+	};
+
+	mmc at 12230000 {
+		status = "disabled";
+	};
 };
doc/device-tree-bindings/exynos/dwmmc.txt new file +49 -0

49 lines not on this page · raw message

Signature · 1 line
1.8.0
#4 lore raw

PATCH v5 2/10 EXYNOS5: FDT: Add DWMMC device node data

Quoted 163 lines · 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'.

 arch/arm/dts/exynos5250.dtsi              | 31 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 22 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 49 +++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
arch/arm/dts/exynos5250.dtsi +31 -0
index ed8c8dd..6c08eb7 100644
@@ -151,4 +151,35 @@
 		};
 	};
 
+	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 +22 -0
index cbfab6f..1d3e42b 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 {
@@ -66,4 +70,22 @@
 			compatible = "maxim,max77686_pmic";
 		};
 	};
+
+	mmc at 12200000 {
+		samsung,bus-width = <8>;
+		samsung,timing = <1 3 3>;
+	};
+
+	mmc at 12210000 {
+		status = "disabled";
+	};
+
+	mmc at 12220000 {
+		samsung,bus-width = <4>;
+		samsung,timing = <1 2 3>;
+	};
+
+	mmc at 12230000 {
+		status = "disabled";
+	};
 };
doc/device-tree-bindings/exynos/dwmmc.txt new file +49 -0
new file mode 100644
index 0000000..0054ace
@@ -0,0 +1,49 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1)
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+	- samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+	region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the devices
+	supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+	. Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+	Drv/sample clock selection register of corresponding channel.
+	. It is comprised of 3 values corresponding to the 3 fileds
+	  'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL register.
+	. SelClk_sample: Select sample clock among 8 shifted clocks.
+	. SelClk_drv: Select drv clock among 8 shifted clocks.
+	. DIVRATIO: Clock Divide ratio select.
+	. The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc at 12200000 {
+	samsung,bus-width = <8>;
+	samsung,timing = <1 3 3>;
+}
+In the above example,
+	. The bus width is 8
+	. Timing is comprised of 3 values as explained below
+		1 - SelClk_sample
+		3 - SelClk_drv
+		3 - DIVRATIO
#5 lore raw

PATCH v5 2/10 EXYNOS5: FDT: Add DWMMC device node data

In reply to Amar

Hi Amar,

Quoted 5 lines · Amar

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

Can I suggest in a later patch you add a removable flag, so we can mark devices which cannot be removed (and can be assumed to be present). I believe that there is some overhead involved in detecting an MMC (we have to try SD first, and fail).

Quoted 160 lines

---
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'.

 arch/arm/dts/exynos5250.dtsi              | 31 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 22 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 49 +++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
arch/arm/dts/exynos5250.dtsi +31 -0
index ed8c8dd..6c08eb7 100644
@@ -151,4 +151,35 @@
                };
        };
 
+       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 +22 -0
index cbfab6f..1d3e42b 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 {
@@ -66,4 +70,22 @@
                        compatible = "maxim,max77686_pmic";
                };
        };
+
+       mmc at 12200000 {
+               samsung,bus-width = <8>;
+               samsung,timing = <1 3 3>;
+       };
+
+       mmc at 12210000 {
+               status = "disabled";
+       };
+
+       mmc at 12220000 {
+               samsung,bus-width = <4>;
+               samsung,timing = <1 2 3>;
+       };
+
+       mmc at 12230000 {
+               status = "disabled";
+       };
 };
doc/device-tree-bindings/exynos/dwmmc.txt new file +49 -1
new file mode 100644
index 0000000..0054ace
@@ -0,0 +1,49 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture (CE-ATA-version 1.1)
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+       - samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+       region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the devices
+       supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+       . Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+       Drv/sample clock selection register of corresponding channel.
+       . It is comprised of 3 values corresponding to the 3 fileds
+         'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL register.
+       . SelClk_sample: Select sample clock among 8 shifted clocks.
+       . SelClk_drv: Select drv clock among 8 shifted clocks.
+       . DIVRATIO: Clock Divide ratio select.
+       . The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc at 12200000 {
+       samsung,bus-width = <8>;
+       samsung,timing = <1 3 3>;
+}
+In the above example,
+       . The bus width is 8
+       . Timing is comprised of 3 values as explained below
+               1 - SelClk_sample
+               3 - SelClk_drv
+               3 - DIVRATIO
--

1.8.0

#6 lore raw

PATCH v5 2/10 EXYNOS5: FDT: Add DWMMC device node data

Hi Simon,

You mean to add "removable" flag in device node ?
Are you referring to the overhead involved during MMC boot, and a SD card is not present on the board ?
Can you please elaborate on the above.

Thanks & Regards
Amarendra Reddy

Quoted 188 lines · Simon Glass

Hi Amar,

Quoted 5 lines · Amar

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

Can I suggest in a later patch you add a removable flag, so we can mark devices which cannot be removed (and can be assumed to be present). I believe that there is some overhead involved in detecting an MMC (we have to try SD first, and fail).

Quoted 6 lines

---
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.

Quoted 7 lines

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

Changes since V3:
No change.

Quoted 8 lines

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'.

 arch/arm/dts/exynos5250.dtsi              | 31 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 22 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 49

+++++++++++++++++++++++++++++++

Review

Quoted 44 lines
 3 files changed, 102 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
arch/arm/dts/exynos5250.dtsi +31 -0
index ed8c8dd..6c08eb7 100644
@@ -151,4 +151,35 @@
                };
        };
 
+       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>;
+       };
 };
(quoted diff) +0 -0

b/board/samsung/dts/exynos5250-smdk5250.dts

Review

Quoted 38 lines

index cbfab6f..1d3e42b 100644

board/samsung/dts/exynos5250-smdk5250.dts +22 -0
@@ -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 {
@@ -66,4 +70,22 @@
                        compatible = "maxim,max77686_pmic";
                };
        };
+
+       mmc at 12200000 {
+               samsung,bus-width = <8>;
+               samsung,timing = <1 3 3>;
+       };
+
+       mmc at 12210000 {
+               status = "disabled";
+       };
+
+       mmc at 12220000 {
+               samsung,bus-width = <4>;
+               samsung,timing = <1 2 3>;
+       };
+
+       mmc at 12230000 {
+               status = "disabled";
+       };
 };
(quoted diff) +0 -0

b/doc/device-tree-bindings/exynos/dwmmc.txt

doc/device-tree-bindings/exynos/dwmmc.txt line 7

Quoted 12 lines

new file mode 100644
index 0000000..0054ace

doc/device-tree-bindings/exynos/dwmmc.txt new file +7 -0
@@ -0,0 +1,49 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture (CE-ATA-version

1.1)

doc/device-tree-bindings/exynos/dwmmc.txt

Quoted 10 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +10 -0
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+       - samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory

mapped

Quoted 5 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +5 -0
+       region.
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:

doc/device-tree-bindings/exynos/dwmmc.txt

Quoted 10 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +10 -0
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the devices
+       supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+       . Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+       Drv/sample clock selection register of corresponding channel.
+       . It is comprised of 3 values corresponding to the 3 fileds
+         'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL

register.

Quoted 18 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +17 -1
+       . SelClk_sample: Select sample clock among 8 shifted clocks.
+       . SelClk_drv: Select drv clock among 8 shifted clocks.
+       . DIVRATIO: Clock Divide ratio select.
+       . The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc at 12200000 {
+       samsung,bus-width = <8>;
+       samsung,timing = <1 3 3>;
+}
+In the above example,
+       . The bus width is 8
+       . Timing is comprised of 3 values as explained below
+               1 - SelClk_sample
+               3 - SelClk_drv
+               3 - DIVRATIO
--
Quoted 2 lines

1.8.0

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

#7 lore raw

PATCH v5 2/10 EXYNOS5: FDT: Add DWMMC device node data

Hi Amarendra,

Quoted 3 lines · Amarendra Reddy

Hi Simon,

You mean to add "removable" flag in device node ?

Yes

Quoted 3 lines

Are you referring to the overhead involved during MMC boot, and a SD card is not present on the board ?
Can you please elaborate on the above.

#8 lore raw

PATCH v5 2/10 EXYNOS5: FDT: Add DWMMC device node data

Hi Simon,

Please find my response below.

Thanks & Regards
Amarendra

Quoted 15 lines · Simon Glass

Hi Amarendra,

Quoted 3 lines · Amarendra Reddy

Hi Simon,

You mean to add "removable" flag in device node ?

Yes

Quoted 1 line

Are you referring to the overhead involved during MMC boot, and a SD

card is

Quoted 2 lines

not present on the board ?
Can you please elaborate on the above.

Quoted 8 lines

From my investigation of the mmc code some months back I found that for the eMMC case we are probing for an SD card, and when that fails, trying eMMC. If we can specify which it is (which we can in the case of a soldered-down device) then we might save that wasted time.

Regards,
Simon

Ok, I will add the flag 'removable' to mmc device node.

Quoted 201 lines
Quoted 43 lines

Thanks & Regards
Amarendra Reddy

Quoted 38 lines · Simon Glass

Hi Amar,

Quoted 5 lines · Amar

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

Can I suggest in a later patch you add a removable flag, so we can mark devices which cannot be removed (and can be assumed to be present). I believe that there is some overhead involved in detecting an MMC (we have to try SD first, and fail).

Quoted 21 lines

---
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'.

Quoted 8 lines
Quoted 8 lines

Review

Quoted 8 lines
 arch/arm/dts/exynos5250.dtsi              | 31 +++++++++++++++++++
 board/samsung/dts/exynos5250-smdk5250.dts | 22 ++++++++++++++
 doc/device-tree-bindings/exynos/dwmmc.txt | 49
+++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+)
 create mode 100644 doc/device-tree-bindings/exynos/dwmmc.txt
(quoted diff) +0 -0

b/arch/arm/dts/exynos5250.dtsi

Quoted 84 lines
Quoted 84 lines
Quoted 84 lines

index ed8c8dd..6c08eb7 100644

arch/arm/dts/exynos5250.dtsi +31 -0
@@ -151,4 +151,35 @@
                };
        };
 
+       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 +22 -0
index cbfab6f..1d3e42b 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 {
@@ -66,4 +70,22 @@
                        compatible = "maxim,max77686_pmic";
                };
        };
+
+       mmc at 12200000 {
+               samsung,bus-width = <8>;
+               samsung,timing = <1 3 3>;
+       };
+
+       mmc at 12210000 {
+               status = "disabled";
+       };
+
+       mmc at 12220000 {
+               samsung,bus-width = <4>;
+               samsung,timing = <1 2 3>;
+       };
+
+       mmc at 12230000 {
+               status = "disabled";
+       };
 };
doc/device-tree-bindings/exynos/dwmmc.txt new file +0 -0
new file mode 100644
index 0000000..0054ace
Quoted 8 lines
Quoted 8 lines

doc/device-tree-bindings/exynos/dwmmc.txt line 7

Quoted 8 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +7 -0
@@ -0,0 +1,49 @@
+* Exynos 5250 DWC_mobile_storage
+
+The Exynos 5250 provides DWC_mobile_storage interface which supports
+. Embedded Multimedia Cards (EMMC-version 4.5)
+. Secure Digital memory (SD mem-version 2.0)
+. Secure Digital I/O (SDIO-version 3.0)
+. Consumer Electronics Advanced Transport Architecture

(CE-ATA-version

Quoted 13 lines
Quoted 13 lines
Quoted 13 lines

1.1)

doc/device-tree-bindings/exynos/dwmmc.txt new file +10 -0
+
+The Exynos 5250 DWC_mobile_storage provides four channels.
+SOC specific and Board specific properties are channel specific.
+
+Required SoC Specific Properties:
+
+- compatible: should be
+       - samsung,exynos5250-dwmmc: for exynos5250 platforms
+
+- reg: physical base address of the controller and length of memory

mapped
+ region.

Quoted 8 lines
Quoted 8 lines

doc/device-tree-bindings/exynos/dwmmc.txt

Quoted 8 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +8 -0
+
+- interrupts: The interrupt number to the cpu.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- samsung,bus-width: The width of the bus used to interface the

devices

Quoted 33 lines
Quoted 31 lines
Quoted 25 lines
doc/device-tree-bindings/exynos/dwmmc.txt new file +6 -0
+       supported by DWC_mobile_storage (SD-MMC/EMMC/SDIO).
+       . Typically the bus width is 4 or 8.
+- samsung,timing: The timing values to be written into the
+       Drv/sample clock selection register of corresponding channel.
+       . It is comprised of 3 values corresponding to the 3 fileds
+         'SelClk_sample', 'SelClk_drv' and 'DIVRATIO' of CLKSEL

register.

doc/device-tree-bindings/exynos/dwmmc.txt new file +17 -1
+       . SelClk_sample: Select sample clock among 8 shifted clocks.
+       . SelClk_drv: Select drv clock among 8 shifted clocks.
+       . DIVRATIO: Clock Divide ratio select.
+       . The above 3 values are used by the clock phase shifter.
+
+Example:
+
+mmc at 12200000 {
+       samsung,bus-width = <8>;
+       samsung,timing = <1 3 3>;
+}
+In the above example,
+       . The bus width is 8
+       . Timing is comprised of 3 values as explained below
+               1 - SelClk_sample
+               3 - SelClk_drv
+               3 - DIVRATIO
--
Quoted 2 lines

1.8.0

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

author
#9 lore raw

PATCH v5 3/10 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).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +16 -7
index 4070d4e..391ed93 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)
@@ -314,7 +313,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 +322,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 +339,13 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
 	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+	fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
 	if (host->fifoth_val)
 		fifoth_val = host->fifoth_val;
-	else
-		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-			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
#10 lore raw

PATCH v5 3/10 DWMMC: Initialise dwmci and resolve EMMC read write issues

Hi Amar,

Quoted 30 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).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +0 -0
index 4070d4e..391ed93 100644

drivers/mmc/dw_mmc.c static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, · line 129

Quoted 1 line
drivers/mmc/dw_mmc.c +0 -0
@@ -129,13 +129,13 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
 	unsigned int timeout = 100000;

We can remove the timeout value.
If you remove this, it looks good to me.

Best Regards,
Jaehoon Chung

Quoted 64 lines
drivers/mmc/dw_mmc.c +16 -7
 	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)
@@ -314,7 +313,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 +322,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 +339,13 @@ static int dwmci_init(struct mmc *mmc)
 	dwmci_writel(host, DWMCI_BMOD, 1);
 
 	fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+	fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
 	if (host->fifoth_val)
 		fifoth_val = host->fifoth_val;
-	else
-		fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-			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);
#11 lore raw

PATCH v5 3/10 DWMMC: Initialise dwmci and resolve EMMC read write issues

Hi Jaehoon,
The 'timeout' value cant be removed as it is being used.

Thanks & Regards
Amarendra

Quoted 115 lines · Jaehoon Chung

Hi Amar,

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 10 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

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

Quoted 10 lines

of using mdelay(1).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +0 -0
index 4070d4e..391ed93 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 mmc_cmd *cmd, · line 129

Quoted 1 line
drivers/mmc/dw_mmc.c +0 -0
      unsigned int timeout = 100000;

We can remove the timeout value.
If you remove this, it looks good to me.

Best Regards,
Jaehoon Chung

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

Quoted 15 lines
drivers/mmc/dw_mmc.c +2 -2
      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,

Quoted 39 lines
drivers/mmc/dw_mmc.c +10 -2
      if (data)
              dwmci_prepare_data(host, data);
 
-
      dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
      if (data)
@@ -314,7 +313,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 +322,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 +339,13 @@ static int dwmci_init(struct mmc *mmc)
      dwmci_writel(host, DWMCI_BMOD, 1);
 
      fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+     fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
      if (host->fifoth_val)
              fifoth_val = host->fifoth_val;

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

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

#12 lore raw

PATCH v5 3/10 DWMMC: Initialise dwmci and resolve EMMC read write issues

Quoted 2 lines · Amarendra Reddy

Hi Jaehoon,
The 'timeout' value cant be removed as it is being used.

Sorry..i missed it.

Quoted 129 lines

Thanks & Regards
Amarendra

Quoted 107 lines · Jaehoon Chung

Hi Amar,

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 10 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

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

Quoted 10 lines

of using mdelay(1).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +0 -0
index 4070d4e..391ed93 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 mmc_cmd *cmd, · line 129

Quoted 1 line
drivers/mmc/dw_mmc.c +0 -0
      unsigned int timeout = 100000;

We can remove the timeout value.
If you remove this, it looks good to me.

Best Regards,
Jaehoon Chung

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

Quoted 15 lines
drivers/mmc/dw_mmc.c +2 -2
      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,

Quoted 47 lines
drivers/mmc/dw_mmc.c +14 -5
      if (data)
              dwmci_prepare_data(host, data);
 
-
      dwmci_writel(host, DWMCI_CMDARG, cmd->cmdarg);
 
      if (data)
@@ -314,7 +313,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 +322,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 +339,13 @@ static int dwmci_init(struct mmc *mmc)
      dwmci_writel(host, DWMCI_BMOD, 1);
 
      fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+     fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
      if (host->fifoth_val)
              fifoth_val = host->fifoth_val;
-     else
-             fifoth_val = MSIZE(0x2) | RX_WMARK(fifo_size/2 -1) |
-                     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);
 
Quoted 8 lines

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

Quoted 2 lines
drivers/mmc/dw_mmc.c +0 -0
      dwmci_writel(host, DWMCI_CLKENA, 0);

_______________________________________________
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

#13 lore raw

PATCH v5 3/10 DWMMC: Initialise dwmci and resolve EMMC read write issues

In reply to Amar
Quoted 7 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.

(nit below if you resend for other reason)

Quoted 39 lines

---
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).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +8 -0
index 4070d4e..391ed93 100644
@@ -323,6 +322,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);
 

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

Quoted 6 lines
drivers/mmc/dw_mmc.c +1 -0
@@ -332,11 +339,13 @@ static int dwmci_init(struct mmc *mmc)
        dwmci_writel(host, DWMCI_BMOD, 1);
 
        fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+       fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
        if (host->fifoth_val)
                fifoth_val = host->fifoth_val;

should be {} around this I think.

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

1.8.0

#14 lore raw

PATCH v5 3/10 DWMMC: Initialise dwmci and resolve EMMC read write issues

Hi Simon,

Please find the response below.

Thanks & Regards
Amarendra

Quoted 56 lines · Simon Glass
Quoted 7 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.

(nit below if you resend for other reason)

Quoted 3 lines

---
Changes since V1:
1)Created the macros RX_WMARK_SHIFT and RX_WMARK_MASK in header

file.

Quoted 10 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

Quoted 28 lines

of using mdelay(1).

 drivers/mmc/dw_mmc.c | 23 ++++++++++++++++-------
 1 file changed, 16 insertions(+), 7 deletions(-)
drivers/mmc/dw_mmc.c +8 -0
index 4070d4e..391ed93 100644
@@ -323,6 +322,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 +339,13 @@ static int dwmci_init(struct mmc *mmc)
        dwmci_writel(host, DWMCI_BMOD, 1);
 
Quoted 7 lines

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

Quoted 4 lines
drivers/mmc/dw_mmc.c +1 -0
        fifo_size = dwmci_readl(host, DWMCI_FIFOTH);
+       fifo_size = ((fifo_size & RX_WMARK_MASK) >> RX_WMARK_SHIFT) + 1;
        if (host->fifoth_val)
                fifoth_val = host->fifoth_val;

should be {} around this I think.

Ok will be updated in next version patchset.

Quoted 19 lines
Quoted 12 lines
drivers/mmc/dw_mmc.c +4 -4
-       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);
--
Quoted 2 lines

1.8.0

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

author
#15 lore raw

PATCH v5 4/10 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.

 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
#16 lore raw

PATCH v5 4/10 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi,

Quoted 6 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.

See below for nit/question.

Quoted 103 lines

---
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.

 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 +27 -7
index 72a31b7..1d09e56 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-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
 
+/*
+ * 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)
 {

drivers/mmc/exynos_dw_mmc.c line 69

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
        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 50MHz.  */
+       freq = 50000000;

Should this be 52MHz?

drivers/mmc/exynos_dw_mmc.c line 79

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

{} around if() part since you have it for else.

Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+               host->clksel_val = clksel;
+       else {
+               if (0 == index)
+                       host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;

drivers/mmc/exynos_dw_mmc.c line 93

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +8 -0
+               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)) {
+               printf("dwmmc%d registration failed\n", index);

Should this be debug()?

Quoted 95 lines
drivers/mmc/exynos_dw_mmc.c +67 -2
+               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 -1
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;
 
--
Quoted 2 lines

1.8.0

Regards,
Simon

#17 lore raw

PATCH v5 4/10 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Simon,

Please find the responses below.

Thanks & Regards
Amarendra

Quoted 139 lines · Simon Glass

Hi,

Quoted 6 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.

See below for nit/question.

Quoted 9 lines

---
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.

Quoted 6 lines

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 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 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
 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 23 lines
drivers/mmc/exynos_dw_mmc.c +9 -2
index 72a31b7..1d09e56 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-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

drivers/mmc/exynos_dw_mmc.c line 33

Quoted 10 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 4 lines
drivers/mmc/exynos_dw_mmc.c +2 -1
+       dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val);
+}
 
-       dwmci_writel(host, DWMCI_CLKSEL, val);

drivers/mmc/exynos_dw_mmc.c

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +7 -1
+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'.

drivers/mmc/exynos_dw_mmc.c

Quoted 5 lines
drivers/mmc/exynos_dw_mmc.c +5 -0
+ * 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)

drivers/mmc/exynos_dw_mmc.c line 69

Quoted 11 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
 {
        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 50MHz.  */
+       freq = 50000000;
Quoted 2 lines

Should this be 52MHz?

Ok shall change it to 52MHz.

Quoted 6 lines
Quoted 6 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+       sclk = get_mmc_clk(index);
+       div = DIV_ROUND_UP(sclk, freq);
+       /* set the clock divisor for mmc */
+       set_mmc_clk(index, div);
 
Quoted 10 lines

drivers/mmc/exynos_dw_mmc.c line 79

Quoted 6 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
-       host->name = EXYNOS_NAME;
+       host->name = "EXYNOS DWMMC";
        host->ioaddr = (void *)regbase;
        host->buswidth = bus_width;
+
+       if (clksel)

{} around if() part since you have it for else.

Ok will put {} around if() part.

Quoted 15 lines
Quoted 4 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+               host->clksel_val = clksel;
+       else {
+               if (0 == index)
+                       host->clksel_val = DWMMC_MMC0_CLKSEL_VAL;

drivers/mmc/exynos_dw_mmc.c line 93

Quoted 10 lines
drivers/mmc/exynos_dw_mmc.c +8 -0
+               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)) {
+               printf("dwmmc%d registration failed\n", index);
Quoted 2 lines

Should this be debug()?

I think it should be printf(), because if the mmc channel registration fails, then this failure information needs to be conveyed to the user. This will happen if printf() is used.
If debug() is used, then the statement will be printed only when the DEBUG is defined.

Quoted 19 lines
drivers/mmc/exynos_dw_mmc.c +19 -0
+               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 29 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 +3 -1
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;
 
--
Quoted 2 lines

1.8.0

Regards,

Quoted 6 lines

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

#18 lore raw

PATCH v5 4/10 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Amarendra,

Quoted 188 lines · Amarendra Reddy

Hi Simon,

Please find the responses below.

Thanks & Regards
Amarendra

Quoted 135 lines · Simon Glass

Hi,

Quoted 6 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.

See below for nit/question.

Quoted 120 lines

---
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.

 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 +22 -7
index 72a31b7..1d09e56 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-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
 
+/*
+ * 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;
drivers/mmc/exynos_dw_mmc.c +2 -0
+       unsigned int div;
+       unsigned long freq, sclk;
        host = malloc(sizeof(struct dwmci_host));
Quoted 8 lines

drivers/mmc/exynos_dw_mmc.c line 69

Quoted 6 lines
        if (!host) {
                printf("dwmci_host malloc fail!\n");
                return 1;
        }
drivers/mmc/exynos_dw_mmc.c +2 -0
+       /* request mmc clock vlaue of 50MHz.  */
+       freq = 50000000;

Should this be 52MHz?

Ok shall change it to 52MHz.

Quoted 7 lines
Quoted 7 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+       sclk = get_mmc_clk(index);
+       div = DIV_ROUND_UP(sclk, freq);
+       /* set the clock divisor for mmc */
+       set_mmc_clk(index, div);
Quoted 9 lines

drivers/mmc/exynos_dw_mmc.c line 79

Quoted 6 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
-       host->name = EXYNOS_NAME;
+       host->name = "EXYNOS DWMMC";
        host->ioaddr = (void *)regbase;
        host->buswidth = bus_width;
+
+       if (clksel)

{} around if() part since you have it for else.

Ok will put {} around if() part.

Quoted 16 lines
Quoted 15 lines
drivers/mmc/exynos_dw_mmc.c +12 -0
+               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)) {
+               printf("dwmmc%d registration failed\n", index);
Quoted 7 lines
Quoted 1 line

Should this be debug()?

I think it should be printf(), because if the mmc channel registration fails, then this failure information needs to be conveyed to the user. This will happen if printf() is used.
If debug() is used, then the statement will be printed only when the DEBUG is defined.

It's a tricky point, and it depends on what else you have in terns of error reporting. This is not a user-facing function, but something called by the internals of your code. I think as a general principle errors should be reported by the commands that started the operation.

In this case exynos_dwmci_add_port() already has an error return code, and its caller can presumable report the error, although it would not include the 'dwmmc' text.

The problem with putting printf()s in drivers is that it can make it impossible to silently do something. For example if I want to write a command to check for a valid partition on an MMC device, and all of the MMC, partition and filesystem code prints out errors along the way, it can make for very confusing output, and can make it impossible to write a higher-level function which silently checks for the valid partition.

So in general I think we should try to keep printf() out of drivers. We have talked on the list about some sort of dynamic verbosity, and someone may look at that at some point, but at the moment we just have printf() and debug().

Regards,
Simon

Quoted 109 lines
Quoted 107 lines
drivers/mmc/exynos_dw_mmc.c +26 -1
+               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);

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

drivers/mmc/exynos_dw_mmc.c +4 -1
+               if (err)
+                       debug("dwmmc Channel-%d init failed\n", index);
+       }
        return 0;
 }
-
+#endif
include/dwmmc.h +3 -1
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;
 
--

1.8.0

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

#19 lore raw

PATCH v5 4/10 EXYNOS5: DWMMC: Added FDT support for DWMMC

Hi Simon,
Thanks for the response.
Please find my response below.

Thanks & Regards
Amarendra

Quoted 227 lines · Simon Glass

Hi Amarendra,

Quoted 12 lines · Amarendra Reddy

Hi Simon,

Please find the responses below.

Thanks & Regards
Amarendra

Quoted 4 lines · Simon Glass

Hi,

On Tue, Jan 22, 2013 at 12:43 AM, Amar <[email protected]>

Quoted 11 lines · wrote:
Quoted 11 lines
Quoted 6 lines

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.

See below for nit/question.

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

---
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.

Quoted 11 lines
Quoted 11 lines
Quoted 11 lines

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.

Quoted 8 lines
Quoted 8 lines
Quoted 8 lines

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

Quoted 5 lines
Quoted 5 lines
Quoted 5 lines

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

Quoted 17 lines
Quoted 17 lines
Quoted 17 lines

the function.

 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 +0 -0
index 8acdf9b..3b147b8 100644
@@ -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

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 2 lines
Quoted 2 lines

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

Quoted 2 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +0 -2
-{
-       unsigned int base = samsung_get_base_mmc() + (0x10000 *

index);

Quoted 50 lines
Quoted 50 lines
Quoted 50 lines
arch/arm/include/asm/arch-exynos/dwmmc.h +4 -2
-       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 +18 -6
index 72a31b7..1d09e56 100644
@@ -19,39 +19,146 @@
  */
 
 #include <common.h>
-#include <malloc.h>
 #include <dwmmc.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <malloc.h>
 #include <asm/arch/dwmmc.h>
 #include <asm/arch/clk.h>
+#include <asm/arch/pinmux.h>
 
-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
 
+/*
+ * 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);
 }
 
Quoted 7 lines
Quoted 7 lines
Quoted 7 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'.
+ * bus_width - operating bus width of mmc channel specified in

'index'.

Quoted 1 line
Quoted 1 line
Quoted 1 line

+ * clksel - value to be written into CLKSEL register in case of

FDT.

Quoted 54 lines
Quoted 16 lines
Quoted 6 lines

+ * 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;

drivers/mmc/exynos_dw_mmc.c line 69

Quoted 9 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+       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 50MHz.  */
+       freq = 50000000;
Quoted 1 line

Should this be 52MHz?

Ok shall change it to 52MHz.

Quoted 7 lines
Quoted 7 lines
drivers/mmc/exynos_dw_mmc.c +4 -0
+       sclk = get_mmc_clk(index);
+       div = DIV_ROUND_UP(sclk, freq);
+       /* set the clock divisor for mmc */
+       set_mmc_clk(index, div);
Quoted 9 lines

drivers/mmc/exynos_dw_mmc.c line 79

Quoted 6 lines
drivers/mmc/exynos_dw_mmc.c +3 -1
-       host->name = EXYNOS_NAME;
+       host->name = "EXYNOS DWMMC";
        host->ioaddr = (void *)regbase;
        host->buswidth = bus_width;
+
+       if (clksel)

{} around if() part since you have it for else.

Ok will put {} around if() part.

Quoted 16 lines
Quoted 15 lines
drivers/mmc/exynos_dw_mmc.c +12 -0
+               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)) {
+               printf("dwmmc%d registration failed\n", index);
Quoted 6 lines
Quoted 1 line

Should this be debug()?

I think it should be printf(), because if the mmc channel registration fails, then this failure information needs to be conveyed to the user. This will happen if printf() is used.
If debug() is used, then the statement will be printed only when the

DEBUG

Quoted 1 line

is defined.

It's a tricky point, and it depends on what else you have in terns of error reporting. This is not a user-facing function, but something called by the internals of your code. I think as a general principle errors should be reported by the commands that started the operation.

In this case exynos_dwmci_add_port() already has an error return code, and its caller can presumable report the error, although it would not include the 'dwmmc' text.

The problem with putting printf()s in drivers is that it can make it impossible to silently do something. For example if I want to write a command to check for a valid partition on an MMC device, and all of the MMC, partition and filesystem code prints out errors along the way, it can make for very confusing output, and can make it impossible to write a higher-level function which silently checks for the valid partition.

Quoted 9 lines

So in general I think we should try to keep printf() out of drivers. We have talked on the list about some sort of dynamic verbosity, and someone may look at that at some point, but at the moment we just have printf() and debug().

Regards,
Simon

Ok, will replace the printf() with debug() in the driver file drivers/mmc/exynos_dw_mmc.c.

author
#20 lore raw

PATCH v5 5/10 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.

 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 956427c..edce21c 100644
@@ -490,7 +490,7 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)
 		(struct exynos4_clock *)samsung_get_base_clock();
 	unsigned long uclk, sclk;
 	unsigned int sel, ratio, pre_ratio;
-	int shift;
+	int shift = 0;
 
 	sel = readl(&clk->src_fsys);
 	sel = (sel >> (dev_index << 2)) & 0xf;
@@ -539,7 +539,7 @@ static unsigned long exynos5_get_mmc_clk(int dev_index)
 		(struct exynos5_clock *)samsung_get_base_clock();
 	unsigned long uclk, sclk;
 	unsigned int sel, ratio, pre_ratio;
-	int shift;
+	int shift = 0;
 
 	sel = readl(&clk->src_fsys);
 	sel = (sel >> (dev_index << 2)) & 0xf;
Signature · 1 line
1.8.0
#21 lore raw

PATCH v5 5/10 EXYNOS5: DWMMC: Initialise the local variable to avoid unwanted results.

Quoted 6 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().

Quoted 45 lines

---
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.

 arch/arm/cpu/armv7/exynos/clock.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm/cpu/armv7/exynos/clock.c +2 -3
index 956427c..edce21c 100644
@@ -490,7 +490,7 @@ static unsigned long exynos4_get_mmc_clk(int dev_index)
                (struct exynos4_clock *)samsung_get_base_clock();
        unsigned long uclk, sclk;
        unsigned int sel, ratio, pre_ratio;
-       int shift;
+       int shift = 0;
 
        sel = readl(&clk->src_fsys);
        sel = (sel >> (dev_index << 2)) & 0xf;
@@ -539,7 +539,7 @@ static unsigned long exynos5_get_mmc_clk(int dev_index)
                (struct exynos5_clock *)samsung_get_base_clock();
        unsigned long uclk, sclk;
        unsigned int sel, ratio, pre_ratio;
-       int shift;
+       int shift = 0;
 
        sel = readl(&clk->src_fsys);
        sel = (sel >> (dev_index << 2)) & 0xf;
--

1.8.0

author
#22 lore raw

PATCH v5 6/10 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().

 board/samsung/smdk5250/Makefile     |   4 +
 board/samsung/smdk5250/exynos5-dt.c | 211 ++++++++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c   | 170 ++++++++++-------------------
 include/configs/exynos5250-dt.h     |   6 +
 4 files changed, 279 insertions(+), 112 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 +211 -0

211 lines not on this page · raw message

board/samsung/smdk5250/smdk5250.c +58 -112

233 lines not on this page · raw message

include/configs/exynos5250-dt.h +6 -0
index cabd2f2..3fa86b2 100644
@@ -95,6 +95,8 @@
 #define CONFIG_MMC
 #define CONFIG_SDHCI
 #define CONFIG_S5P_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_EXYNOS_DWMMC
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
@@ -210,6 +212,10 @@
 
 #define CONFIG_DOS_PARTITION
 
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
 #define CONFIG_IRAM_STACK	0x02050000
 
 #define CONFIG_SYS_INIT_SP_ADDR	(CONFIG_SYS_LOAD_ADDR - 0x1000000)
Signature · 1 line
1.8.0
#23 lore raw

PATCH v5 6/10 SMDK5250: Initialise and Enable DWMMC, support FDT and non-FDT

Hi Amar,

Quoted 15 lines · 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.

Quoted 7 lines

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.

This looks OK to me. It could perhaps be separated into a patch to create the exynos5-dt.c file, and a separate one to enable the mmc, but I think this is fine.

I am a little concerned at the possible code duplication between smdk250.c and exynos5-dt.c - if this becomes a problem later perhaps you could create a common file for things like board_uart_init().

Quoted 532 lines

---
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().

 board/samsung/smdk5250/Makefile     |   4 +
 board/samsung/smdk5250/exynos5-dt.c | 211 ++++++++++++++++++++++++++++++++++++
 board/samsung/smdk5250/smdk5250.c   | 170 ++++++++++-------------------
 include/configs/exynos5250-dt.h     |   6 +
 4 files changed, 279 insertions(+), 112 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 +211 -0
new file mode 100644
index 0000000..a4b0e10
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <asm/io.h>
+#include <i2c.h>
+#include <netdev.h>
+#include <spi.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/dwmmc.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/mmc.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch/sromc.h>
+#include <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+       gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
+#ifdef CONFIG_EXYNOS_SPI
+       spi_init();
+#endif
+       return 0;
+}
+
+int dram_init(void)
+{
+       int i;
+       u32 addr;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+       }
+       return 0;
+}
+
+#if defined(CONFIG_POWER)
+int power_init_board(void)
+{
+       if (pmic_init(I2C_PMIC)) {
+               debug("Could not initialise PMIC\n");
+               return -1;
+       } else
+               return 0;
+}
+#endif
+
+void dram_init_banksize(void)
+{
+       int i;
+       u32 addr, size;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+
+               gd->bd->bi_dram[i].start = addr;
+               gd->bd->bi_dram[i].size = size;
+       }
+}
+
+static int decode_sromc(const void *blob, struct fdt_sromc *config)
+{
+       int err;
+       int node;
+
+       node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
+       if (node < 0) {
+               debug("Could not find SROMC node\n");
+               return node;
+       }
+
+       config->bank = fdtdec_get_int(blob, node, "bank", 0);
+       config->width = fdtdec_get_int(blob, node, "width", 2);
+
+       err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
+                       FDT_SROM_TIMING_COUNT);
+       if (err < 0) {
+               debug("Could not decode SROMC configuration"
+                                       "Error: %s\n", fdt_strerror(err));
+               return -FDT_ERR_NOTFOUND;
+       }
+       return 0;
+}
+
+int board_eth_init(bd_t *bis)
+{
+#ifdef CONFIG_SMC911X
+       u32 smc_bw_conf, smc_bc_conf;
+       struct fdt_sromc config;
+       fdt_addr_t base_addr;
+       int node;
+
+       node = decode_sromc(gd->fdt_blob, &config);
+       if (node < 0) {
+               debug("%s: Could not find sromc configuration\n", __func__);
+               return 0;
+       }
+       node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
+       if (node < 0) {
+               debug("%s: Could not find lan9215 configuration\n", __func__);
+               return 0;
+       }
+
+       /* We now have a node, so any problems from now on are errors */
+       base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
+       if (base_addr == FDT_ADDR_T_NONE) {
+               debug("%s: Could not find lan9215 address\n", __func__);
+               return -1;
+       }
+
+       /* Ethernet needs data bus width of 16 bits */
+       if (config.width != 2) {
+               debug("%s: Unsupported bus width %d\n", __func__,
+                       config.width);
+               return -1;
+       }
+       smc_bw_conf = SROMC_DATA16_WIDTH(config.bank)
+                       | SROMC_BYTE_ENABLE(config.bank);
+
+       smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS])   |
+                       SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) |
+                       SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) |
+                       SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) |
+                       SROMC_BC_TAH(config.timing[FDT_SROM_TAH])   |
+                       SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) |
+                       SROMC_BC_PMC(config.timing[FDT_SROM_PMC]);
+
+       /* Select and configure the SROMC bank */
+       exynos_pinmux_config(PERIPH_ID_SROMC, config.bank);
+       s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf);
+       return smc911x_initialize(0, base_addr);
+#endif
+       return 0;
+}
+
+#ifdef CONFIG_DISPLAY_BOARDINFO
+int checkboard(void)
+{
+       printf("\nBoard: SMDK5250\n");
+
+       return 0;
+}
+#endif
+
+#ifdef CONFIG_GENERIC_MMC
+int board_mmc_init(bd_t *bis)
+{
+       int ret;
+       /* dwmmc initializattion for available channels */
+       ret = exynos_dwmmc_init(gd->fdt_blob);
+       if (ret)
+               debug("dwmmc init failed\n");
+
+       return ret;
+}
+#endif
+
+static int board_uart_init(void)
+{
+       int err, uart_id, ret = 0;
+
+       for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+               err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+               if (err) {
+                       debug("UART%d not configured\n",
+                                        (uart_id - PERIPH_ID_UART0));
+                       ret |= err;
+               }
+       }
+       return ret;
+}
+
+#ifdef CONFIG_BOARD_EARLY_INIT_F
+int board_early_init_f(void)
+{
+       int err;
+       err = board_uart_init();
+       if (err) {
+               debug("UART init failed\n");
+               return err;
+       }
+#ifdef CONFIG_SYS_I2C_INIT_BOARD
+       board_i2c_init(gd->fdt_blob);
+#endif
+       return err;
+}
+#endif
board/samsung/smdk5250/smdk5250.c +58 -112
index 7a5f132..e3a2593 100644
@@ -28,6 +28,7 @@
 #include <netdev.h>
 #include <spi.h>
 #include <asm/arch/cpu.h>
+#include <asm/arch/dwmmc.h>
 #include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
 #include <asm/arch/pinmux.h>
@@ -68,80 +69,40 @@ int board_init(void)
 
 int dram_init(void)
 {
-       gd->ram_size    = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_2, PHYS_SDRAM_2_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_3, PHYS_SDRAM_3_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_4, PHYS_SDRAM_4_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_5, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_6, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_7, PHYS_SDRAM_7_SIZE)
-                       + get_ram_size((long *)PHYS_SDRAM_8, PHYS_SDRAM_8_SIZE);
+       int i;
+       u32 addr;
+
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE);
+       }
        return 0;
 }
 
 #if defined(CONFIG_POWER)
 int power_init_board(void)
 {
-       if (pmic_init(I2C_PMIC))
+       if (pmic_init(I2C_PMIC)) {
+               debug("Could not initialise PMIC\n");
                return -1;
-       else
+       } else
                return 0;
 }
 #endif
 
 void dram_init_banksize(void)
 {
-       gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
-       gd->bd->bi_dram[0].size = get_ram_size((long *)PHYS_SDRAM_1,
-                                                       PHYS_SDRAM_1_SIZE);
-       gd->bd->bi_dram[1].start = PHYS_SDRAM_2;
-       gd->bd->bi_dram[1].size = get_ram_size((long *)PHYS_SDRAM_2,
-                                                       PHYS_SDRAM_2_SIZE);
-       gd->bd->bi_dram[2].start = PHYS_SDRAM_3;
-       gd->bd->bi_dram[2].size = get_ram_size((long *)PHYS_SDRAM_3,
-                                                       PHYS_SDRAM_3_SIZE);
-       gd->bd->bi_dram[3].start = PHYS_SDRAM_4;
-       gd->bd->bi_dram[3].size = get_ram_size((long *)PHYS_SDRAM_4,
-                                                       PHYS_SDRAM_4_SIZE);
-       gd->bd->bi_dram[4].start = PHYS_SDRAM_5;
-       gd->bd->bi_dram[4].size = get_ram_size((long *)PHYS_SDRAM_5,
-                                                       PHYS_SDRAM_5_SIZE);
-       gd->bd->bi_dram[5].start = PHYS_SDRAM_6;
-       gd->bd->bi_dram[5].size = get_ram_size((long *)PHYS_SDRAM_6,
-                                                       PHYS_SDRAM_6_SIZE);
-       gd->bd->bi_dram[6].start = PHYS_SDRAM_7;
-       gd->bd->bi_dram[6].size = get_ram_size((long *)PHYS_SDRAM_7,
-                                                       PHYS_SDRAM_7_SIZE);
-       gd->bd->bi_dram[7].start = PHYS_SDRAM_8;
-       gd->bd->bi_dram[7].size = get_ram_size((long *)PHYS_SDRAM_8,
-                                                       PHYS_SDRAM_8_SIZE);
-}
+       int i;
+       u32 addr, size;
 
-#ifdef CONFIG_OF_CONTROL
-static int decode_sromc(const void *blob, struct fdt_sromc *config)
-{
-       int err;
-       int node;
+       for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+               addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE);
+               size = get_ram_size((long *)addr, SDRAM_BANK_SIZE);
 
-       node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC);
-       if (node < 0) {
-               debug("Could not find SROMC node\n");
-               return node;
+               gd->bd->bi_dram[i].start = addr;
+               gd->bd->bi_dram[i].size = size;
        }
-
-       config->bank = fdtdec_get_int(blob, node, "bank", 0);
-       config->width = fdtdec_get_int(blob, node, "width", 2);
-
-       err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing,
-                       FDT_SROM_TIMING_COUNT);
-       if (err < 0) {
-               debug("Could not decode SROMC configuration\n");
-               return -FDT_ERR_NOTFOUND;
-       }
-
-       return 0;
 }
-#endif
 
 int board_eth_init(bd_t *bis)
 {
@@ -149,27 +110,7 @@ int board_eth_init(bd_t *bis)
        u32 smc_bw_conf, smc_bc_conf;
        struct fdt_sromc config;
        fdt_addr_t base_addr;
-       int node;
 
-#ifdef CONFIG_OF_CONTROL
-       node = decode_sromc(gd->fdt_blob, &config);
-       if (node < 0) {
-               debug("%s: Could not find sromc configuration\n", __func__);
-               return 0;
-       }
-       node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215);
-       if (node < 0) {
-               debug("%s: Could not find lan9215 configuration\n", __func__);
-               return 0;
-       }
-
-       /* We now have a node, so any problems from now on are errors */
-       base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg");
-       if (base_addr == FDT_ADDR_T_NONE) {
-               debug("%s: Could not find lan9215 address\n", __func__);
-               return -1;
-       }
-#else
        /* Non-FDT configuration - bank number and timing parameters*/
        config.bank = CONFIG_ENV_SROM_BANK;
        config.width = 2;
@@ -182,7 +123,6 @@ int board_eth_init(bd_t *bis)
        config.timing[FDT_SROM_TACP] = 0x09;
        config.timing[FDT_SROM_PMC] = 0x01;
        base_addr = CONFIG_SMC911X_BASE;
-#endif
 
        /* Ethernet needs data bus width of 16 bits */
        if (config.width != 2) {
@@ -221,48 +161,54 @@ int checkboard(void)
 #ifdef CONFIG_GENERIC_MMC
 int board_mmc_init(bd_t *bis)
 {
-       int err;
+       int err, ret = 0, index, bus_width;
+       u32 base;
 
        err = exynos_pinmux_config(PERIPH_ID_SDMMC0, PINMUX_FLAG_8BIT_MODE);
-       if (err) {
+       if (err)
                debug("SDMMC0 not configured\n");
-               return err;
-       }
-
-       err = s5p_mmc_init(0, 8);
-       return err;
+       ret |= err;
+
+       /*EMMC: dwmmc Channel-0 with 8 bit bus width */
+       index = 0;
+       base =  samsung_get_base_mmc() + (0x10000 * index);
+       bus_width = 8;
+       err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+       if (err)
+               debug("dwmmc Channel-0 init failed\n");
+       ret |= err;
+
+       err = exynos_pinmux_config(PERIPH_ID_SDMMC2, PINMUX_FLAG_NONE);
+       if (err)
+               debug("SDMMC2 not configured\n");
+       ret |= err;
+
+       /*SD: dwmmc Channel-2 with 4 bit bus width */
+       index = 2;
+       base = samsung_get_base_mmc() + (0x10000 * index);
+       bus_width = 4;
+       err = exynos_dwmci_add_port(index, base, bus_width, (u32)NULL);
+       if (err)
+               debug("dwmmc Channel-2 init failed\n");
+       ret |= err;
+
+       return ret;
 }
 #endif
 
 static int board_uart_init(void)
 {
-       int err;
-
-       err = exynos_pinmux_config(PERIPH_ID_UART0, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART0 not configured\n");
-               return err;
-       }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART1, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART1 not configured\n");
-               return err;
+       int err, uart_id, ret = 0;
+
+       for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) {
+               err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE);
+               if (err) {
+                       debug("UART%d not configured\n",
+                                        (uart_id - PERIPH_ID_UART0));
+                       ret |= err;
+               }
        }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART2, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART2 not configured\n");
-               return err;
-       }
-
-       err = exynos_pinmux_config(PERIPH_ID_UART3, PINMUX_FLAG_NONE);
-       if (err) {
-               debug("UART3 not configured\n");
-               return err;
-       }
-
-       return 0;
+       return ret;
 }
 
 #ifdef CONFIG_BOARD_EARLY_INIT_F
@@ -275,7 +221,7 @@ int board_early_init_f(void)
                return err;
        }
 #ifdef CONFIG_SYS_I2C_INIT_BOARD
-       board_i2c_init(gd->fdt_blob);
+       board_i2c_init(NULL);
 #endif
        return err;
 }
include/configs/exynos5250-dt.h +6 -1
index cabd2f2..3fa86b2 100644
@@ -95,6 +95,8 @@
 #define CONFIG_MMC
 #define CONFIG_SDHCI
 #define CONFIG_S5P_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_EXYNOS_DWMMC
 
 #define CONFIG_BOARD_EARLY_INIT_F
 
@@ -210,6 +212,10 @@
 
 #define CONFIG_DOS_PARTITION
 
+#define CONFIG_EFI_PARTITION
+#define CONFIG_CMD_PART
+#define CONFIG_PARTITION_UUIDS
+
 #define CONFIG_IRAM_STACK      0x02050000
 
 #define CONFIG_SYS_INIT_SP_ADDR        (CONFIG_SYS_LOAD_ADDR - 0x1000000)
--

1.8.0

author
#24 lore raw

PATCH v5 7/10 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().

 drivers/mmc/mmc.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/mmc.h     |  24 +++++++++++
 2 files changed, 141 insertions(+)
drivers/mmc/mmc.c +117 -0
index 72e8ce6..c152934 100644
@@ -1327,3 +1327,120 @@ int mmc_initialize(bd_t *bis)
 
 	return 0;
 }
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+				unsigned long rpmbsize)
+{
+	int err;
+	struct mmc_cmd cmd;
+
+	/* Only use this command for raw EMMC moviNAND */
+	/* Enter backdoor mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG1;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+		return err;
+	}
+
+	/* Boot partition changing mode */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = MMC_CMD62_ARG2;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+		return err;
+	}
+	/* boot partition size is multiple of 128KB */
+	bootsize = ((bootsize*1024)/128);
+
+	/* Arg: boot partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = bootsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+		return err;
+	}
+	/* RPMB partition size is multiple of 128KB */
+	rpmbsize = ((rpmbsize*1024)/128);
+	/* Arg: RPMB partition size */
+	cmd.cmdidx = MMC_CMD_RES_MAN;
+	cmd.resp_type = MMC_RSP_R1b;
+	cmd.cmdarg = rpmbsize;
+
+	err = mmc_send_cmd(mmc, &cmd, NULL);
+	if (err) {
+		debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+		return err;
+	}
+	return 0;
+}
+
+/* This function shall form and send the commands to open / close the
+ * boot partition specified by user.
+ *
+ * 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)
+ */
+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 failure:"
+					"Error1 = %d\n", part_num, err);
+		} else {
+			debug("mmc boot partition#%d close failure:"
+					"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 failure:"
+					"Error2 = %d\n", part_num, err);
+			return err;
+		}
+	}
+	return 0;
+}
include/mmc.h +24 -0
index a13e2bd..fcd9c54 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;
@@ -275,6 +296,9 @@ int board_mmc_getcd(struct mmc *mmc);
 int mmc_switch_part(int dev_num, unsigned int part_num);
 int mmc_getcd(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+					unsigned long rpmbsize);
+int mmc_boot_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
#25 lore raw

PATCH v5 7/10 MMC: APIs to support resize of EMMC boot partition

Hi Amar,

Quoted 28 lines · 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().

 drivers/mmc/mmc.c | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/mmc.h     |  24 +++++++++++
 2 files changed, 141 insertions(+)
drivers/mmc/mmc.c +0 -0
index 72e8ce6..c152934 100644
@@ -1327,3 +1327,120 @@ int mmc_initialize(bd_t *bis)
 
        return 0;

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1338

Quoted 10 lines
drivers/mmc/mmc.c +9 -0
 }
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+                               unsigned long rpmbsize)
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Only use this command for raw EMMC moviNAND */
+       /* Enter backdoor mode */

Should probably join these two comments.

Quoted 12 lines
drivers/mmc/mmc.c +12 -0
+       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;

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1360

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

space around * and /
plus remove outer ()

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1373

Quoted 13 lines
drivers/mmc/mmc.c +13 -0
+
+       /* 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);

and here

Quoted 4 lines
drivers/mmc/mmc.c +4 -0
+       /* Arg: RPMB partition size */
+       cmd.cmdidx = MMC_CMD_RES_MAN;
+       cmd.resp_type = MMC_RSP_R1b;
+       cmd.cmdarg = rpmbsize;

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1387

Quoted 10 lines
drivers/mmc/mmc.c +10 -0
+
+       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

/*
* This function...

Quoted 18 lines
drivers/mmc/mmc.c +18 -0
+ * boot partition specified by user.
+ *
+ * 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)
+ */
+int mmc_boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access)
+{
+       int err;
+       struct mmc_cmd cmd;

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1415

Quoted 10 lines
drivers/mmc/mmc.c +10 -0
+
+       /* 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);

You can remove outer (). Might be nice to put () around the << sub-expressions:

       cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
                       (EXT_CSD_PART_CONF << 16) |
Quoted 9 lines
drivers/mmc/mmc.c +9 -0
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               if (access) {
+                       debug("mmc boot partition#%d open failure:"
+                                       "Error1 = %d\n", part_num, err);
+               } else {
+                       debug("mmc boot partition#%d close failure:"
+                                       "Error = %d\n", part_num, err);

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1434

Quoted 10 lines
drivers/mmc/mmc.c +10 -0
+               }
+               return err;
+       }
+
+       if (access) {
+               /* 4bit transfer mode at booting time. */
+               cmd.cmdidx = MMC_CMD_SWITCH;
+               cmd.resp_type = MMC_RSP_R1b;
+
+               cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24|

Same here. Also space before |, and below

Quoted 66 lines
drivers/mmc/mmc.c +12 -0
+                               EXT_CSD_BOOT_BUS_WIDTH << 16|
+                               ((1<<0) << 8));
+
+               err = mmc_send_cmd(mmc, &cmd, NULL);
+               if (err) {
+                       debug("mmc boot partition#%d open failure:"
+                                       "Error2 = %d\n", part_num, err);
+                       return err;
+               }
+       }
+       return 0;
+}
include/mmc.h +21 -0
index a13e2bd..fcd9c54 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;

include/mmc.h int board_mmc_getcd(struct mmc *mmc); · line 298

Quoted 3 lines
include/mmc.h +0 -0
@@ -275,6 +296,9 @@ int board_mmc_getcd(struct mmc *mmc);
 int mmc_switch_part(int dev_num, unsigned int part_num);
 int mmc_getcd(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;

Could you please add full comments for these functions?

Quoted 9 lines
include/mmc.h +3 -1
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+                                       unsigned long rpmbsize);
+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)
--

1.8.0

Regards,
Simon

#26 lore raw

PATCH v5 7/10 MMC: APIs to support resize of EMMC boot partition

Hi Simon,

Please find the responses below.

Thanks & Regards
Amarendra Reddy

Quoted 68 lines · Simon Glass

Hi Amar,

Quoted 1 line · Amar

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

of EMMC.

Quoted 6 lines

---
Changes since V1:
New patch.

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)Replaced the functions mmc_boot_open() & mmc_boot_close() with

a

Quoted 3 lines

single function mmc_boot_part_access().

 drivers/mmc/mmc.c | 117

++++++++++++++++++++++++++++++++++++++++++++++++++++++

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1331

Quoted 13 lines
 include/mmc.h     |  24 +++++++++++
 2 files changed, 141 insertions(+)
drivers/mmc/mmc.c +2 -0
index 72e8ce6..c152934 100644
@@ -1327,3 +1327,120 @@ int mmc_initialize(bd_t *bis)
 
        return 0;
 }
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long

bootsize,

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1338

Quoted 7 lines
drivers/mmc/mmc.c +7 -0
+                               unsigned long rpmbsize)
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Only use this command for raw EMMC moviNAND */
+       /* Enter backdoor mode */

Should probably join these two comments.
Ok.

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

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

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

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

Quoted 8 lines

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1360

Quoted 4 lines
drivers/mmc/mmc.c +4 -0
+               return err;
+       }
+       /* boot partition size is multiple of 128KB */
+       bootsize = ((bootsize*1024)/128);

space around * and /
plus remove outer ()

Ok.

Quoted 11 lines

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

Quoted 10 lines
drivers/mmc/mmc.c +9 -0
+
+       /* 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);

Quoted 7 lines

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1373

Quoted 4 lines
drivers/mmc/mmc.c +4 -0
+               return err;
+       }
+       /* RPMB partition size is multiple of 128KB */
+       rpmbsize = ((rpmbsize*1024)/128);

and here

Ok.

Quoted 74 lines

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

Quoted 9 lines
drivers/mmc/mmc.c +8 -0
+       /* 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);

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1387

Quoted 6 lines
drivers/mmc/mmc.c +6 -0
+               return err;
+       }
+       return 0;
+}
+
+/* This function shall form and send the commands to open / close the

/*
* This function...

Ok.

Quoted 5 lines
drivers/mmc/mmc.c +5 -0
+ * boot partition specified by user.
+ *
+ * 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

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

Quoted 10 lines
drivers/mmc/mmc.c +10 -0
+ *     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)
+ */
+int mmc_boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32

access)

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis)

Quoted 5 lines
drivers/mmc/mmc.c +5 -0
+{
+       int err;
+       struct mmc_cmd cmd;
+
+       /* Boot ack enable, boot partition enable , boot partition

access */

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1415

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

You can remove outer (). Might be nice to put () around the << sub-expressions:

       cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) |
                       (EXT_CSD_PART_CONF << 16) |

Ok.

Quoted 13 lines
drivers/mmc/mmc.c +13 -0
+
+       err = mmc_send_cmd(mmc, &cmd, NULL);
+       if (err) {
+               if (access) {
+                       debug("mmc boot partition#%d open failure:"
+                                       "Error1 = %d\n", part_num, err);
+               } else {
+                       debug("mmc boot partition#%d close failure:"
+                                       "Error = %d\n", part_num, err);
+               }
+               return err;
+       }
+
Quoted 9 lines

drivers/mmc/mmc.c int mmc_initialize(bd_t *bis) · line 1434

Quoted 6 lines
drivers/mmc/mmc.c +6 -0
+       if (access) {
+               /* 4bit transfer mode at booting time. */
+               cmd.cmdidx = MMC_CMD_SWITCH;
+               cmd.resp_type = MMC_RSP_R1b;
+
+               cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24|

Same here. Also space before |, and below

Ok.

Quoted 58 lines
Quoted 58 lines
drivers/mmc/mmc.c +12 -0
+                               EXT_CSD_BOOT_BUS_WIDTH << 16|
+                               ((1<<0) << 8));
+
+               err = mmc_send_cmd(mmc, &cmd, NULL);
+               if (err) {
+                       debug("mmc boot partition#%d open failure:"
+                                       "Error2 = %d\n", part_num, err);
+                       return err;
+               }
+       }
+       return 0;
+}
include/mmc.h +16 -0
index a13e2bd..fcd9c54 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)
 
Quoted 15 lines

include/mmc.h int board_mmc_getcd(struct mmc *mmc); · line 298

Quoted 12 lines
include/mmc.h +5 -0
+/* 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;
@@ -275,6 +296,9 @@ int board_mmc_getcd(struct mmc *mmc);
 int mmc_switch_part(int dev_num, unsigned int part_num);
 int mmc_getcd(struct mmc *mmc);
 void spl_mmc_load(void) __noreturn;

Could you please add full comments for these functions?

Ok.

Quoted 20 lines

include/mmc.h int board_mmc_getcd(struct mmc *mmc); · line 299

Quoted 2 lines
include/mmc.h +1 -0
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long

bootsize,

include/mmc.h int board_mmc_getcd(struct mmc *mmc); · line 301

Quoted 2 lines
include/mmc.h +2 -0
+                                       unsigned long rpmbsize);
+int mmc_boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32

access);

Quoted 6 lines
include/mmc.h +0 -1
 #ifdef CONFIG_GENERIC_MMC
 #define mmc_host_is_spi(mmc)   ((mmc)->host_caps & MMC_MODE_SPI)
--

1.8.0

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

author
#27 lore raw

PATCH v5 8/10 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.

 arch/arm/include/asm/arch-exynos/clk.h |  3 ++
 board/samsung/smdk5250/clock_init.c    | 15 ++++++++++
 board/samsung/smdk5250/clock_init.h    |  5 ++++
 board/samsung/smdk5250/spl_boot.c      | 52 ++++++++++++++++++++++++++++++----
 4 files changed, 69 insertions(+), 6 deletions(-)
arch/arm/include/asm/arch-exynos/clk.h +3 -0
index 1935b0b..a4d5b4e 100644
@@ -29,6 +29,9 @@
 #define VPLL	4
 #define BPLL	5
 
+#define FSYS1_MMC0_DIV_MASK	0xff0f
+#define FSYS1_MMC0_DIV_VAL	0x0701
+
 unsigned long get_pll_clk(int pllreg);
 unsigned long get_arm_clk(void);
 unsigned long get_i2c_clk(void);
board/samsung/smdk5250/clock_init.c +15 -0
index c009ae5..154993c 100644
@@ -28,6 +28,7 @@
 #include <asm/arch/clk.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/spl.h>
+#include <asm/arch/dwmmc.h>
 
 #include "clock_init.h"
 #include "setup.h"
@@ -664,3 +665,17 @@ void clock_init_dp_clock(void)
 	/* We run DP at 267 Mhz */
 	setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
 }
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz.
+ */
+void emmc_boot_clk_div_set(void)
+{
+	struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+	unsigned int div_mmc;
+
+	div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK;
+	div_mmc |= FSYS1_MMC0_DIV_VAL;
+	writel(div_mmc, (unsigned int) &clk->div_fsys1);
+}
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
#28 lore raw

PATCH v5 8/10 SMDK5250: Enable EMMC booting

Quoted 3 lines · Amar

This patch adds support for EMMC booting on SMDK5250.

Quoted 174 lines

---
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.

 arch/arm/include/asm/arch-exynos/clk.h |  3 ++
 board/samsung/smdk5250/clock_init.c    | 15 ++++++++++
 board/samsung/smdk5250/clock_init.h    |  5 ++++
 board/samsung/smdk5250/spl_boot.c      | 52 ++++++++++++++++++++++++++++++----
 4 files changed, 69 insertions(+), 6 deletions(-)
arch/arm/include/asm/arch-exynos/clk.h +3 -0
index 1935b0b..a4d5b4e 100644
@@ -29,6 +29,9 @@
 #define VPLL   4
 #define BPLL   5
 
+#define FSYS1_MMC0_DIV_MASK    0xff0f
+#define FSYS1_MMC0_DIV_VAL     0x0701
+
 unsigned long get_pll_clk(int pllreg);
 unsigned long get_arm_clk(void);
 unsigned long get_i2c_clk(void);
board/samsung/smdk5250/clock_init.c +15 -0
index c009ae5..154993c 100644
@@ -28,6 +28,7 @@
 #include <asm/arch/clk.h>
 #include <asm/arch/clock.h>
 #include <asm/arch/spl.h>
+#include <asm/arch/dwmmc.h>
 
 #include "clock_init.h"
 #include "setup.h"
@@ -664,3 +665,17 @@ void clock_init_dp_clock(void)
        /* We run DP at 267 Mhz */
        setbits_le32(&clk->div_disp1_0, CLK_DIV_DISP1_0_FIMD1);
 }
+
+/*
+ * Set clock divisor value for booting from EMMC.
+ * Set DWMMC channel-0 clk div to operate mmc0 device at 50MHz.
+ */
+void emmc_boot_clk_div_set(void)
+{
+       struct exynos5_clock *clk = (struct exynos5_clock *)EXYNOS5_CLOCK_BASE;
+       unsigned int div_mmc;
+
+       div_mmc = readl((unsigned int) &clk->div_fsys1) & ~FSYS1_MMC0_DIV_MASK;
+       div_mmc |= FSYS1_MMC0_DIV_VAL;
+       writel(div_mmc, (unsigned int) &clk->div_fsys1);
+}
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 -7
index d8f3c1e..4ddbd4a 100644
@@ -23,15 +23,42 @@
 #include<common.h>
 #include<config.h>
 
+#include <asm/arch-exynos/dmc.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/clk.h>
+
+#include "clock_init.h"
+
+/* Index into irom ptr table */
+enum index {
+       MMC_INDEX,
+       EMMC44_INDEX,
+       EMMC44_END_INDEX,
+       SPI_INDEX,
+};
+
+/* IROM Function Pointers Table */
+u32 irom_ptr_table[] = {
+       [MMC_INDEX] = 0x02020030,       /* iROM Function Pointer-SDMMC boot */
+       [EMMC44_INDEX] = 0x02020044,    /* iROM Function Pointer-EMMC4.4 boot*/
+       [EMMC44_END_INDEX] = 0x02020048,/* iROM Function Pointer
+                                               -EMMC4.4 end boot operation */
+       [SPI_INDEX] = 0x02020058,       /* iROM Function Pointer-SPI boot */
+       };
+
 enum boot_mode {
        BOOT_MODE_MMC = 4,
        BOOT_MODE_SERIAL = 20,
+       BOOT_MODE_EMMC = 8,     /* EMMC4.4 */
        /* Boot based on Operating Mode pin settings */
        BOOT_MODE_OM = 32,
        BOOT_MODE_USB,  /* Boot using USB download */
 };
 
-       typedef u32 (*spi_copy_func_t)(u32 offset, u32 nblock, u32 dst);
+void *get_irom_func(int index)
+{
+       return (void *) *(u32 *)irom_ptr_table[index];
+}
 
 /*
 * Copy U-boot from mmc to RAM:
@@ -40,23 +67,36 @@ enum boot_mode {
 */
 void copy_uboot_to_ram(void)
 {
-       spi_copy_func_t spi_copy;
        enum boot_mode bootmode;
-       u32 (*copy_bl2)(u32, u32, u32);
-
+       u32 (*spi_copy)(u32 offset, u32 nblock, u32 dst);
+       u32 (*copy_bl2)(u32 offset, u32 nblock, u32 dst);
+       u32 (*copy_bl2_from_emmc)(u32 nblock, u32 dst);
+       void (*end_bootop_from_emmc)(void);
+       /* read Operation Mode ststus register to find the bootmode */
        bootmode = readl(EXYNOS5_POWER_BASE) & OM_STAT;
 
        switch (bootmode) {
        case BOOT_MODE_SERIAL:
-               spi_copy = *(spi_copy_func_t *)EXYNOS_COPY_SPI_FNPTR_ADDR;
+               spi_copy = get_irom_func(SPI_INDEX);
                spi_copy(SPI_FLASH_UBOOT_POS, CONFIG_BL2_SIZE,
                                                CONFIG_SYS_TEXT_BASE);
                break;
        case BOOT_MODE_MMC:
-               copy_bl2 = (void *) *(u32 *)COPY_BL2_FNPTR_ADDR;
+               copy_bl2 = get_irom_func(MMC_INDEX);
                copy_bl2(BL2_START_OFFSET, BL2_SIZE_BLOC_COUNT,
                                                CONFIG_SYS_TEXT_BASE);
                break;
+       case BOOT_MODE_EMMC:
+               /* Set the FSYS1 clock divisor value for EMMC boot */
+               emmc_boot_clk_div_set();
+
+               copy_bl2_from_emmc = get_irom_func(EMMC44_INDEX);
+               end_bootop_from_emmc = get_irom_func(EMMC44_END_INDEX);
+
+               copy_bl2_from_emmc(BL2_SIZE_BLOC_COUNT, CONFIG_SYS_TEXT_BASE);
+               end_bootop_from_emmc();
+               break;
+
        default:
                break;
        }
--

1.8.0

author
#29 lore raw

PATCH v5 9/10 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).

 common/cmd_mmc.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)
common/cmd_mmc.c +97 -1
index 7dacd51..d036d34 100644
@@ -147,6 +147,31 @@ U_BOOT_CMD(
 	"- display info of the current MMC device"
 );
 
+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 after all"
+						"images are written\n");
+		printf("!EMMC boot partition has continuity at image"
+						"writing time.\n");
+		printf("!So, Do not close boot partition, Before, all"
+						"images are written.\n");
+		return 0;
+	} else 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;
+	}
+}
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
 	enum mmc_state state;
@@ -248,6 +273,71 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 				curr_device, mmc->part_num);
 
 		return 0;
+	} else if ((strcmp(argv[1], "open") == 0) ||
+			(strcmp(argv[1], "close") == 0)) {
+		int dev;
+		struct mmc *mmc;
+		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;
+		}
 	}
 
 	state = MMC_INVALID;
@@ -317,5 +407,11 @@ U_BOOT_CMD(
 	"mmc rescan\n"
 	"mmc part - lists available partition on current mmc device\n"
 	"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
-	"mmc list - lists available devices");
+	"mmc list - lists available devices\n"
+	"mmc open <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
Signature · 1 line
1.8.0
#30 lore raw

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

Hi Amar,

Quoted 1 line · Amar

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

(Minor nit below)

Quoted 34 lines

---
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).

 common/cmd_mmc.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 97 insertions(+), 1 deletion(-)
common/cmd_mmc.c +3 -0
index 7dacd51..d036d34 100644
@@ -147,6 +147,31 @@ U_BOOT_CMD(
        "- display info of the current MMC device"
 );
 
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32 access)
+{
+       int err;

common/cmd_mmc.c U_BOOT_CMD( · line 162

Quoted 10 lines
common/cmd_mmc.c +10 -0
+       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 after all"
+                                               "images are written\n");
+               printf("!EMMC boot partition has continuity at image"
+                                               "writing time.\n");
+               printf("!So, Do not close boot partition, Before, all"
+                                               "images are written.\n");

So, do not close the boot partition before all images are written

Quoted 101 lines
common/cmd_mmc.c +84 -2
+               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;
+       }
+}
+
 static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        enum mmc_state state;
@@ -248,6 +273,71 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
                                curr_device, mmc->part_num);
 
                return 0;
+       } else if ((strcmp(argv[1], "open") == 0) ||
+                       (strcmp(argv[1], "close") == 0)) {
+               int dev;
+               struct mmc *mmc;
+               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 at slot %x\n", dev);
+                       return 1;
+               }
+
+               if (IS_SD(mmc)) {
+                       printf("It is not a EMMC device\n");
+                       return 1;
+               }
+
+               if (0 == mmc_boot_partition_size_change(mmc,
+                                               bootsize, rpmbsize)) {
+                       printf("EMMC boot partition Size %d MB\n", bootsize);
+                       printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+                       return 0;
+               } else {
+                       printf("EMMC boot partition Size change Failed.\n");
+                       return 1;
+               }
        }
 
        state = MMC_INVALID;
@@ -317,5 +407,11 @@ U_BOOT_CMD(
        "mmc rescan\n"
        "mmc part - lists available partition on current mmc device\n"
        "mmc dev [dev] [part] - show or set current mmc device [partition]\n"
-       "mmc list - lists available devices");
+       "mmc list - lists available devices\n"
+       "mmc open <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
--
Quoted 2 lines

1.8.0

Regards,
Simon

#31 lore raw

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

Hi Simon,

Please find the response below.

Thanks & Regards
Amarendra Reddy

Quoted 47 lines · Simon Glass

Hi Amar,

Quoted 1 line · Amar

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

partitions on EMMC.

(Minor nit below)

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 2 lines
 common/cmd_mmc.c | 98

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

common/cmd_mmc.c U_BOOT_CMD( · line 150

Quoted 11 lines
 1 file changed, 97 insertions(+), 1 deletion(-)
common/cmd_mmc.c +1 -0
index 7dacd51..d036d34 100644
@@ -147,6 +147,31 @@ U_BOOT_CMD(
        "- display info of the current MMC device"
 );
 
+static int boot_part_access(struct mmc *mmc, u32 ack, u32 part_num, u32

access)

Quoted 16 lines

common/cmd_mmc.c U_BOOT_CMD( · line 162

Quoted 12 lines
common/cmd_mmc.c +12 -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 after all"
+                                               "images are written\n");
+               printf("!EMMC boot partition has continuity at image"
+                                               "writing time.\n");
+               printf("!So, Do not close boot partition, Before, all"
+                                               "images are written.\n");

So, do not close the boot partition before all images are written

Ok. will update the sentence.

Quoted 126 lines

common/cmd_mmc.c U_BOOT_CMD(

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

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);

common/cmd_mmc.c U_BOOT_CMD(

Quoted 5 lines
common/cmd_mmc.c +4 -0
+               return 1;
+       }
+}
+
 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,6 +273,71 @@ static int do_mmcops(cmd_tbl_t *cmdtp, int flag,

int argc, char * const argv[])

Quoted 17 lines
common/cmd_mmc.c +14 -0
                                curr_device, mmc->part_num);
 
                return 0;
+       } 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)) {

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");

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

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

part*/

Quoted 17 lines
common/cmd_mmc.c +17 -0
+               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 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[])

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

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

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 409

Quoted 9 lines
common/cmd_mmc.c +2 -0
+                       return 1;
+               }
        }
 
        state = MMC_INVALID;
@@ -317,5 +407,11 @@ 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 4 lines
common/cmd_mmc.c +3 -1
-       "mmc list - lists available devices");
+       "mmc list - lists available devices\n"
+       "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( · line 414

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"

common/cmd_mmc.c U_BOOT_CMD( · line 415

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 416

Quoted 1 line
common/cmd_mmc.c +1 -0
+       " - change sizes of boot and RPMB partions of specified

device\n");

Quoted 4 lines
common/cmd_mmc.c +0 -1
 #endif
--

1.8.0

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

author
#32 lore raw

PATCH v5 10/10 EXYNOS5: I2C: Added FDT and non-FDT support for I2C

In reply to Amar

This patch adds FDT and non-FDT support for I2C, and initialise the I2C channels.

---
Changes since V4:
New patch.

 drivers/i2c/s3c24x0_i2c.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/i2c/s3c24x0_i2c.c +11 -2
index 769a2ba..f2a035c 100644
@@ -524,11 +524,12 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 		 len) != 0);
 }
 
-#ifdef CONFIG_OF_CONTROL
 void board_i2c_init(const void *blob)
 {
+	int i;
+#ifdef CONFIG_OF_CONTROL
 	int node_list[CONFIG_MAX_I2C_NUM];
-	int count, i;
+	int count;
 
 	count = fdtdec_find_aliases_for_id(blob, "i2c",
 		COMPAT_SAMSUNG_S3C2440_I2C, node_list,
@@ -548,8 +549,16 @@ void board_i2c_init(const void *blob)
 		bus->bus_num = i2c_busses++;
 		exynos_pinmux_config(bus->id, 0);
 	}
+#else
+	for (i = 0; i < CONFIG_MAX_I2C_NUM; i++) {
+		exynos_pinmux_config((PERIPH_ID_I2C0 + i),
+					PINMUX_FLAG_NONE);
+	}
+#endif
+	i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 }
 
+#ifdef CONFIG_OF_CONTROL
 static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
 {
 	if (bus_idx < i2c_busses)
Signature · 1 line
1.8.0
#33 lore raw

PATCH v5 10/10 EXYNOS5: I2C: Added FDT and non-FDT support for I2C

Hi Amar,

Quoted 31 lines · Amar

This patch adds FDT and non-FDT support for I2C, and initialise the I2C channels.

---
Changes since V4:
New patch.

 drivers/i2c/s3c24x0_i2c.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/i2c/s3c24x0_i2c.c +3 -2
index 769a2ba..f2a035c 100644
@@ -524,11 +524,12 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
                 len) != 0);
 }
 
-#ifdef CONFIG_OF_CONTROL
 void board_i2c_init(const void *blob)
 {
+       int i;
+#ifdef CONFIG_OF_CONTROL
        int node_list[CONFIG_MAX_I2C_NUM];
-       int count, i;
+       int count;
 
        count = fdtdec_find_aliases_for_id(blob, "i2c",
                COMPAT_SAMSUNG_S3C2440_I2C, node_list,

drivers/i2c/s3c24x0_i2c.c void board_i2c_init(const void *blob) · line 558

Quoted 10 lines
drivers/i2c/s3c24x0_i2c.c +7 -0
@@ -548,8 +549,16 @@ void board_i2c_init(const void *blob)
                bus->bus_num = i2c_busses++;
                exynos_pinmux_config(bus->id, 0);
        }
+#else
+       for (i = 0; i < CONFIG_MAX_I2C_NUM; i++) {
+               exynos_pinmux_config((PERIPH_ID_I2C0 + i),
+                                       PINMUX_FLAG_NONE);
+       }
+#endif
+       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);

I suggest this goes up one line, since it shouldn't be needed in the FDT case, right?

Quoted 9 lines
drivers/i2c/s3c24x0_i2c.c +1 -1
 }
 
+#ifdef CONFIG_OF_CONTROL
 static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx)
 {
        if (bus_idx < i2c_busses)
--

1.8.0

Regards,
Simon

#34 lore raw

PATCH v5 10/10 EXYNOS5: I2C: Added FDT and non-FDT support for I2C

Hi Simon,

Please find the response below.

Thanks & Regards
Amarendra Reddy

Quoted 32 lines · Simon Glass

Hi Amar,

drivers/i2c/s3c24x0_i2c.c int i2c_write(uchar chip, uint addr, int alen,

Quoted 16 lines · Amar

This patch adds FDT and non-FDT support for I2C, and initialise the I2C channels.

---
Changes since V4:
New patch.

 drivers/i2c/s3c24x0_i2c.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/i2c/s3c24x0_i2c.c +0 -0
index 769a2ba..f2a035c 100644
@@ -524,11 +524,12 @@ int i2c_write(uchar chip, uint addr, int alen,

uchar *buffer, int len)

Quoted 12 lines
drivers/i2c/s3c24x0_i2c.c +3 -2
                 len) != 0);
 }
 
-#ifdef CONFIG_OF_CONTROL
 void board_i2c_init(const void *blob)
 {
+       int i;
+#ifdef CONFIG_OF_CONTROL
        int node_list[CONFIG_MAX_I2C_NUM];
-       int count, i;
+       int count;
 
Quoted 16 lines

drivers/i2c/s3c24x0_i2c.c void board_i2c_init(const void *blob) · line 558

Quoted 13 lines
drivers/i2c/s3c24x0_i2c.c +7 -0
        count = fdtdec_find_aliases_for_id(blob, "i2c",
                COMPAT_SAMSUNG_S3C2440_I2C, node_list,
@@ -548,8 +549,16 @@ void board_i2c_init(const void *blob)
                bus->bus_num = i2c_busses++;
                exynos_pinmux_config(bus->id, 0);
        }
+#else
+       for (i = 0; i < CONFIG_MAX_I2C_NUM; i++) {
+               exynos_pinmux_config((PERIPH_ID_I2C0 + i),
+                                       PINMUX_FLAG_NONE);
+       }
+#endif
+       i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);

I suggest this goes up one line, since it shouldn't be needed in the FDT case, right?

Actually the function i2c_init() need not be called here. Only the pinmux configuration need to be done here. Hence i2c_init() call will be removed here.
i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE) is called from arch/arm/lib/board.c which initialises I2C.

Quoted 9 lines

}

+#ifdef CONFIG_OF_CONTROL
static struct s3c24x0_i2c_bus *get_bus(unsigned int bus_idx) {
if (bus_idx < i2c_busses)
--
1.8.0

Regards,

Quoted 6 lines

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