summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2016-02-29 10:50:01 -0500
committerTom Rini <trini@konsulko.com>2016-02-29 10:50:01 -0500
commit9902c113ade2c9af701785b982a1a4db4a2395ec (patch)
tree3604a5a7f6ace6bddc8f78abdd59e44b12ee5f72
parente5e88c65965b7c7e2d5dabd458b0e57dde2d6c17 (diff)
parent11d3ede42ceccef9b5941ea7907f398cb97ed361 (diff)
Merge branch 'master' of git://git.denx.de/u-boot-uniphier
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/dts/uniphier-common32.dtsi19
-rw-r--r--arch/arm/dts/uniphier-ph1-ld4-ref.dts4
-rw-r--r--arch/arm/dts/uniphier-ph1-ld4.dtsi137
-rw-r--r--arch/arm/dts/uniphier-ph1-ld6b-ref.dts4
-rw-r--r--arch/arm/dts/uniphier-ph1-pro4-ace.dts4
-rw-r--r--arch/arm/dts/uniphier-ph1-pro4-ref.dts8
-rw-r--r--arch/arm/dts/uniphier-ph1-pro4-sanji.dts16
-rw-r--r--arch/arm/dts/uniphier-ph1-pro4.dtsi240
-rw-r--r--arch/arm/dts/uniphier-ph1-pro5-4kbox.dts8
-rw-r--r--arch/arm/dts/uniphier-ph1-pro5.dtsi227
-rw-r--r--arch/arm/dts/uniphier-ph1-sld3-ref.dts4
-rw-r--r--arch/arm/dts/uniphier-ph1-sld3.dtsi151
-rw-r--r--arch/arm/dts/uniphier-ph1-sld8-ref.dts4
-rw-r--r--arch/arm/dts/uniphier-ph1-sld8.dtsi137
-rw-r--r--arch/arm/dts/uniphier-pinctrl.dtsi15
-rw-r--r--arch/arm/dts/uniphier-proxstream2-gentil.dts16
-rw-r--r--arch/arm/dts/uniphier-proxstream2-vodka.dts16
-rw-r--r--arch/arm/dts/uniphier-proxstream2.dtsi220
-rw-r--r--arch/arm/include/asm/gpio.h2
-rw-r--r--arch/arm/mach-uniphier/Kconfig66
-rw-r--r--arch/arm/mach-uniphier/Makefile9
-rw-r--r--arch/arm/mach-uniphier/arm32/Makefile13
-rw-r--r--arch/arm/mach-uniphier/arm32/arm-mpcore.h (renamed from arch/arm/mach-uniphier/arm-mpcore.h)0
-rw-r--r--arch/arm/mach-uniphier/arm32/cache_uniphier.c (renamed from arch/arm/mach-uniphier/cache_uniphier.c)0
-rw-r--r--arch/arm/mach-uniphier/arm32/debug_ll.S (renamed from arch/arm/mach-uniphier/debug_ll.S)6
-rw-r--r--arch/arm/mach-uniphier/arm32/late_lowlevel_init.S (renamed from arch/arm/mach-uniphier/late_lowlevel_init.S)0
-rw-r--r--arch/arm/mach-uniphier/arm32/lowlevel_init.S (renamed from arch/arm/mach-uniphier/lowlevel_init.S)0
-rw-r--r--arch/arm/mach-uniphier/arm32/ssc-regs.h (renamed from arch/arm/mach-uniphier/ssc-regs.h)0
-rw-r--r--arch/arm/mach-uniphier/arm32/timer.c (renamed from arch/arm/mach-uniphier/timer.c)0
-rw-r--r--arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c2
-rw-r--r--arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c2
-rw-r--r--arch/arm/mach-uniphier/boards.c178
-rw-r--r--arch/arm/mach-uniphier/boot-mode/boot-mode.c64
-rw-r--r--arch/arm/mach-uniphier/cpu_info.c4
-rw-r--r--arch/arm/mach-uniphier/dram/Makefile4
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c80
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c67
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c78
-rw-r--r--arch/arm/mach-uniphier/dram/ddrphy-regs.h5
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-ld4.c225
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-pro4.c182
-rw-r--r--arch/arm/mach-uniphier/dram/umc-ph1-sld8.c218
-rw-r--r--arch/arm/mach-uniphier/dram/umc-proxstream2.c217
-rw-r--r--arch/arm/mach-uniphier/dram/umc-regs.h48
-rw-r--r--arch/arm/mach-uniphier/dram_init.c5
-rw-r--r--arch/arm/mach-uniphier/init.h24
-rw-r--r--arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c6
-rw-r--r--arch/arm/mach-uniphier/memconf/memconf-proxstream2.c6
-rw-r--r--arch/arm/mach-uniphier/memconf/memconf.c14
-rw-r--r--arch/arm/mach-uniphier/micro-support-card.c3
-rw-r--r--arch/arm/mach-uniphier/sg-regs.h2
-rw-r--r--arch/arm/mach-uniphier/soc-info.h16
-rw-r--r--arch/arm/mach-uniphier/soc_info.c8
-rw-r--r--configs/uniphier_ld4_sld8_defconfig6
-rw-r--r--configs/uniphier_pro4_defconfig3
-rw-r--r--configs/uniphier_pro5_defconfig30
-rw-r--r--configs/uniphier_pxs2_ld6b_defconfig6
-rw-r--r--configs/uniphier_sld3_defconfig3
-rw-r--r--doc/README.uniphier20
-rw-r--r--drivers/gpio/Kconfig6
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-uniphier.c147
-rw-r--r--drivers/mmc/Kconfig6
-rw-r--r--drivers/mmc/Makefile1
-rw-r--r--drivers/mmc/uniphier-sd.c751
-rw-r--r--include/configs/uniphier.h26
67 files changed, 2956 insertions, 837 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d8b63e9407..6e5544f9d7 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -690,15 +690,16 @@ config TARGET_COLIBRI_PXA270
config ARCH_UNIPHIER
bool "Socionext UniPhier SoCs"
select CLK_UNIPHIER
- select CPU_V7
select SUPPORT_SPL
select SPL
select OF_CONTROL
select SPL_OF_CONTROL
select DM
select SPL_DM
+ select DM_GPIO
select DM_SERIAL
select DM_I2C
+ select DM_MMC
help
Support for UniPhier SoC family developed by Socionext Inc.
(formerly, System LSI Business Division of Panasonic Corporation)
diff --git a/arch/arm/dts/uniphier-common32.dtsi b/arch/arm/dts/uniphier-common32.dtsi
index 59511bde94..7d59112ddd 100644
--- a/arch/arm/dts/uniphier-common32.dtsi
+++ b/arch/arm/dts/uniphier-common32.dtsi
@@ -23,12 +23,6 @@
ranges;
interrupt-parent = <&intc>;
- extbus: extbus {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <1>;
- };
-
serial0: serial@54006800 {
compatible = "socionext,uniphier-uart";
status = "disabled";
@@ -69,9 +63,16 @@
clocks = <&uart_clk>;
};
- system-bus-controller@58c00000 {
- compatible = "socionext,uniphier-system-bus-controller";
- reg = <0x58c00000 0x400>, <0x59800000 0x2000>;
+ system_bus: system-bus@58c00000 {
+ compatible = "socionext,uniphier-system-bus";
+ reg = <0x58c00000 0x400>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ smpctrl@59800000 {
+ compatible = "socionext,uniphier-smpctrl";
+ reg = <0x59801000 0x400>;
};
mio: mioctrl@59810000 {
diff --git a/arch/arm/dts/uniphier-ph1-ld4-ref.dts b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
index f62916da39..d7b000796e 100644
--- a/arch/arm/dts/uniphier-ph1-ld4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld4-ref.dts
@@ -51,6 +51,10 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-ld4.dtsi b/arch/arm/dts/uniphier-ph1-ld4.dtsi
index 7c8759f929..5ae029ea97 100644
--- a/arch/arm/dts/uniphier-ph1-ld4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-ld4.dtsi
@@ -56,6 +56,118 @@
cache-level = <2>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port11x: gpio@55000060 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000060 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port16x: gpio@55000088 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000088 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c";
status = "disabled";
@@ -108,6 +220,31 @@
clock-frequency = <100000>;
};
+ sd: sdhc@5a400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a400000 0x200>;
+ interrupts = <0 76 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd>;
+ pinctrl-1 = <&pinctrl_sd_1v8>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
+ emmc: sdhc@5a500000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a500000 0x200>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_emmc>;
+ pinctrl-1 = <&pinctrl_emmc_1v8>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
index dca408bb70..13a29fdfaa 100644
--- a/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-ld6b-ref.dts
@@ -53,6 +53,10 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ace.dts b/arch/arm/dts/uniphier-ph1-pro4-ace.dts
index 6e741ea45b..37e0853365 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ace.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ace.dts
@@ -69,6 +69,10 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-pro4-ref.dts b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
index 202a642a4d..07a9783357 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-ref.dts
@@ -54,6 +54,14 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
+&sd1 {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
index 91a71ef469..82e2bd02c7 100644
--- a/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
+++ b/arch/arm/dts/uniphier-ph1-pro4-sanji.dts
@@ -64,6 +64,10 @@
status = "okay";
};
+&emmc {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
@@ -91,6 +95,14 @@
u-boot,dm-pre-reloc;
};
+&mio {
+ u-boot,dm-pre-reloc;
+};
+
+&emmc {
+ u-boot,dm-pre-reloc;
+};
+
&pinctrl {
u-boot,dm-pre-reloc;
};
@@ -98,3 +110,7 @@
&pinctrl_uart0 {
u-boot,dm-pre-reloc;
};
+
+&pinctrl_emmc {
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/uniphier-ph1-pro4.dtsi b/arch/arm/dts/uniphier-ph1-pro4.dtsi
index cb5b8f1a86..d5767b6252 100644
--- a/arch/arm/dts/uniphier-ph1-pro4.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro4.dtsi
@@ -64,6 +64,209 @@
cache-level = <2>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port11x: gpio@55000060 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000060 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port17x: gpio@550000a0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port18x: gpio@550000a8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port19x: gpio@550000b0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port20x: gpio@550000b8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port21x: gpio@550000c0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port22x: gpio@550000c8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port23x: gpio@550000d0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port24x: gpio@550000d8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port25x: gpio@550000e0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port26x: gpio@550000e8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port27x: gpio@550000f0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port28x: gpio@550000f8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port29x: gpio@55000100 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000100 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port30x: gpio@55000108 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000108 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c";
status = "disabled";
@@ -140,6 +343,43 @@
clock-frequency = <400000>;
};
+ sd: sdhc@5a400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a400000 0x200>;
+ interrupts = <0 76 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd>;
+ pinctrl-1 = <&pinctrl_sd_1v8>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
+ emmc: sdhc@5a500000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a500000 0x200>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_emmc>;
+ pinctrl-1 = <&pinctrl_emmc_1v8>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
+ sd1: sdhc@5a600000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a600000 0x200>;
+ interrupts = <0 85 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd1>;
+ pinctrl-1 = <&pinctrl_sd1_1v8>;
+ clocks = <&mio 2>;
+ bus-width = <4>;
+ };
+
usb2: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
index 02a3362e74..cbdc3ebbff 100644
--- a/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
+++ b/arch/arm/dts/uniphier-ph1-pro5-4kbox.dts
@@ -47,6 +47,14 @@
status = "okay";
};
+&emmc {
+ status = "okay";
+};
+
+&sd {
+ status = "okay";
+};
+
/* for U-Boot only */
/ {
soc {
diff --git a/arch/arm/dts/uniphier-ph1-pro5.dtsi b/arch/arm/dts/uniphier-ph1-pro5.dtsi
index 087b25a950..bd1b4b1b66 100644
--- a/arch/arm/dts/uniphier-ph1-pro5.dtsi
+++ b/arch/arm/dts/uniphier-ph1-pro5.dtsi
@@ -76,6 +76,209 @@
cache-level = <3>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port11x: gpio@55000060 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000060 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port17x: gpio@550000a0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port18x: gpio@550000a8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port19x: gpio@550000b0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port20x: gpio@550000b8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port21x: gpio@550000c0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port22x: gpio@550000c8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port23x: gpio@550000d0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port24x: gpio@550000d8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port25x: gpio@550000e0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port26x: gpio@550000e8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port27x: gpio@550000f0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port28x: gpio@550000f8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port29x: gpio@55000100 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000100 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port30x: gpio@55000108 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000108 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c";
status = "disabled";
@@ -152,6 +355,30 @@
clock-frequency = <400000>;
};
+ emmc: sdhc@68400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x68400000 0x800>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
+ sd: sdhc@68800000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x68800000 0x800>;
+ interrupts = <0 76 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd>;
+ pinctrl-1 = <&pinctrl_sd_1v8>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
usb0: usb@65a00000 {
compatible = "socionext,uniphier-xhci", "generic-xhci";
status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-sld3-ref.dts b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
index ff17945e90..c7213c9ff4 100644
--- a/arch/arm/dts/uniphier-ph1-sld3-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld3-ref.dts
@@ -52,6 +52,10 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-sld3.dtsi b/arch/arm/dts/uniphier-ph1-sld3.dtsi
index 85dde66f07..789713db12 100644
--- a/arch/arm/dts/uniphier-ph1-sld3.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld3.dtsi
@@ -62,12 +62,6 @@
ranges;
interrupt-parent = <&intc>;
- extbus: extbus {
- compatible = "simple-bus";
- #address-cells = <2>;
- #size-cells = <1>;
- };
-
timer@20000200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0x20000200 0x20>;
@@ -117,6 +111,118 @@
clock-frequency = <36864000>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port11x: gpio@55000060 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000060 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port16x: gpio@55000088 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000088 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c";
status = "disabled";
@@ -172,10 +278,16 @@
clock-frequency = <400000>;
};
- system-bus-controller-misc@59800000 {
- compatible = "socionext,uniphier-system-bus-controller-misc",
- "syscon";
- reg = <0x59800000 0x2000>;
+ system_bus: system-bus@58c00000 {
+ compatible = "socionext,uniphier-system-bus";
+ reg = <0x58c00000 0x400>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ };
+
+ smpctrl@59800000 {
+ compatible = "socionext,uniphier-smpctrl";
+ reg = <0x59801000 0x400>;
};
mio: mioctrl@59810000 {
@@ -186,6 +298,25 @@
clocks = <&sysctrl 10>, <&sysctrl 18>;
};
+ emmc: sdhc@5a400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a400000 0x200>;
+ interrupts = <0 78 4>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
+ sd: sdhc@5a500000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a500000 0x200>;
+ interrupts = <0 76 4>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled";
diff --git a/arch/arm/dts/uniphier-ph1-sld8-ref.dts b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
index b5b6f65d36..ec5c5bdadc 100644
--- a/arch/arm/dts/uniphier-ph1-sld8-ref.dts
+++ b/arch/arm/dts/uniphier-ph1-sld8-ref.dts
@@ -51,6 +51,10 @@
status = "okay";
};
+&sd {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
diff --git a/arch/arm/dts/uniphier-ph1-sld8.dtsi b/arch/arm/dts/uniphier-ph1-sld8.dtsi
index f93db83661..61e0b45781 100644
--- a/arch/arm/dts/uniphier-ph1-sld8.dtsi
+++ b/arch/arm/dts/uniphier-ph1-sld8.dtsi
@@ -56,6 +56,118 @@
cache-level = <2>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port11x: gpio@55000060 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000060 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port16x: gpio@55000088 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000088 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c";
status = "disabled";
@@ -108,6 +220,31 @@
clock-frequency = <100000>;
};
+ sd: sdhc@5a400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a400000 0x200>;
+ interrupts = <0 76 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd>;
+ pinctrl-1 = <&pinctrl_sd_1v8>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
+ emmc: sdhc@5a500000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ interrupts = <0 78 4>;
+ reg = <0x5a500000 0x200>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_emmc>;
+ pinctrl-1 = <&pinctrl_emmc_1v8>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled";
diff --git a/arch/arm/dts/uniphier-pinctrl.dtsi b/arch/arm/dts/uniphier-pinctrl.dtsi
index b1691d0679..494139a05d 100644
--- a/arch/arm/dts/uniphier-pinctrl.dtsi
+++ b/arch/arm/dts/uniphier-pinctrl.dtsi
@@ -12,6 +12,11 @@
function = "emmc";
};
+ pinctrl_emmc_1v8: emmc_grp_1v8 {
+ groups = "emmc", "emmc_dat8";
+ function = "emmc";
+ };
+
pinctrl_i2c0: i2c0_grp {
groups = "i2c0";
function = "i2c0";
@@ -37,11 +42,21 @@
function = "sd";
};
+ pinctrl_sd_1v8: sd_grp_1v8 {
+ groups = "sd";
+ function = "sd";
+ };
+
pinctrl_sd1: sd1_grp {
groups = "sd1";
function = "sd1";
};
+ pinctrl_sd1_1v8: sd1_grp_1v8 {
+ groups = "sd1";
+ function = "sd1";
+ };
+
pinctrl_uart0: uart0_grp {
groups = "uart0";
function = "uart0";
diff --git a/arch/arm/dts/uniphier-proxstream2-gentil.dts b/arch/arm/dts/uniphier-proxstream2-gentil.dts
index dc0def30fd..eb1d2bcc63 100644
--- a/arch/arm/dts/uniphier-proxstream2-gentil.dts
+++ b/arch/arm/dts/uniphier-proxstream2-gentil.dts
@@ -52,6 +52,10 @@
status = "okay";
};
+&emmc {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
@@ -71,6 +75,14 @@
u-boot,dm-pre-reloc;
};
+&mio {
+ u-boot,dm-pre-reloc;
+};
+
+&emmc {
+ u-boot,dm-pre-reloc;
+};
+
&pinctrl {
u-boot,dm-pre-reloc;
};
@@ -78,3 +90,7 @@
&pinctrl_uart2 {
u-boot,dm-pre-reloc;
};
+
+&pinctrl_emmc {
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/uniphier-proxstream2-vodka.dts b/arch/arm/dts/uniphier-proxstream2-vodka.dts
index 3703ad36a5..e7d5db8894 100644
--- a/arch/arm/dts/uniphier-proxstream2-vodka.dts
+++ b/arch/arm/dts/uniphier-proxstream2-vodka.dts
@@ -41,6 +41,10 @@
status = "okay";
};
+&emmc {
+ status = "okay";
+};
+
&usb0 {
status = "okay";
};
@@ -56,6 +60,14 @@
u-boot,dm-pre-reloc;
};
+&mio {
+ u-boot,dm-pre-reloc;
+};
+
+&emmc {
+ u-boot,dm-pre-reloc;
+};
+
&pinctrl {
u-boot,dm-pre-reloc;
};
@@ -63,3 +75,7 @@
&pinctrl_uart2 {
u-boot,dm-pre-reloc;
};
+
+&pinctrl_emmc {
+ u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/uniphier-proxstream2.dtsi b/arch/arm/dts/uniphier-proxstream2.dtsi
index 2d324f95a4..12968bdd17 100644
--- a/arch/arm/dts/uniphier-proxstream2.dtsi
+++ b/arch/arm/dts/uniphier-proxstream2.dtsi
@@ -78,6 +78,202 @@
cache-level = <2>;
};
+ port0x: gpio@55000008 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000008 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port1x: gpio@55000010 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000010 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port2x: gpio@55000018 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000018 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port3x: gpio@55000020 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000020 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port4: gpio@55000028 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000028 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port5x: gpio@55000030 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000030 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port6x: gpio@55000038 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000038 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port7x: gpio@55000040 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000040 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port8x: gpio@55000048 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000048 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port9x: gpio@55000050 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000050 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port10x: gpio@55000058 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000058 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port12x: gpio@55000068 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000068 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port13x: gpio@55000070 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000070 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port14x: gpio@55000078 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000078 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port15x: gpio@55000080 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000080 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port16x: gpio@55000088 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x55000088 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port17x: gpio@550000a0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port18x: gpio@550000a8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000a8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port19x: gpio@550000b0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port20x: gpio@550000b8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000b8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port21x: gpio@550000c0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port22x: gpio@550000c8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000c8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port23x: gpio@550000d0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port24x: gpio@550000d8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000d8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port25x: gpio@550000e0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port26x: gpio@550000e8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000e8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port27x: gpio@550000f0 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f0 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ port28x: gpio@550000f8 {
+ compatible = "socionext,uniphier-gpio";
+ reg = <0x550000f8 0x8>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c";
status = "disabled";
@@ -163,6 +359,30 @@
clock-frequency = <400000>;
};
+ emmc: sdhc@5a000000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a000000 0x800>;
+ interrupts = <0 78 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_emmc>;
+ clocks = <&mio 1>;
+ bus-width = <8>;
+ non-removable;
+ };
+
+ sd: sdhc@5a400000 {
+ compatible = "socionext,uniphier-sdhc";
+ status = "disabled";
+ reg = <0x5a400000 0x800>;
+ interrupts = <0 76 4>;
+ pinctrl-names = "default", "1.8v";
+ pinctrl-0 = <&pinctrl_sd>;
+ pinctrl-1 = <&pinctrl_sd_1v8>;
+ clocks = <&mio 0>;
+ bus-width = <4>;
+ };
+
usb0: usb@65a00000 {
compatible = "socionext,uniphier-xhci", "generic-xhci";
status = "disabled";
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index d49ad080e2..fe4419cae4 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -1,2 +1,4 @@
+#ifndef CONFIG_ARCH_UNIPHIER
#include <asm/arch/gpio.h>
+#endif
#include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-uniphier/Kconfig b/arch/arm/mach-uniphier/Kconfig
index 03256be403..660f83c855 100644
--- a/arch/arm/mach-uniphier/Kconfig
+++ b/arch/arm/mach-uniphier/Kconfig
@@ -3,54 +3,52 @@ if ARCH_UNIPHIER
config SYS_CONFIG_NAME
default "uniphier"
+choice
+ prompt "UniPhier SoC select"
+ default ARCH_UNIPHIER_PH1_PRO4
+
config ARCH_UNIPHIER_PH1_SLD3
bool "UniPhier PH1-sLD3 SoC"
- help
- This enables support for UniPhier PH1-sLD3 SoC.
+ select CPU_V7
-config ARCH_UNIPHIER_PH1_LD4
- bool "UniPhier PH1-LD4 SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3
- help
- This enables support for UniPhier PH1-LD4 SoC.
+config ARCH_UNIPHIER_LD4_SLD8
+ bool "UniPhier PH1-LD4/PH1-sLD8 SoC"
+ select CPU_V7
config ARCH_UNIPHIER_PH1_PRO4
bool "UniPhier PH1-Pro4 SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3 && \
- !ARCH_UNIPHIER_PH1_LD4 && \
- !ARCH_UNIPHIER_PH1_SLD8
- help
- This enables support for UniPhier PH1-Pro4 SoC.
+ select CPU_V7
+
+config ARCH_UNIPHIER_PRO5_PXS2_LD6B
+ bool "UniPhier PH1-Pro5/ProXstream2/PH1-LD6b SoC"
+ select CPU_V7
+
+endchoice
+
+config ARCH_UNIPHIER_PH1_LD4
+ bool "Enable UniPhier PH1-LD4 SoC support"
+ depends on ARCH_UNIPHIER_LD4_SLD8
+ default y
config ARCH_UNIPHIER_PH1_SLD8
- bool "UniPhier PH1-sLD8 SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3
- help
- This enables support for UniPhier PH1-sLD8 SoC.
+ bool "Enable UniPhier PH1-sLD8 SoC support"
+ depends on ARCH_UNIPHIER_LD4_SLD8
+ default y
config ARCH_UNIPHIER_PH1_PRO5
- bool "UniPhier PH1-Pro5 SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3 && \
- !ARCH_UNIPHIER_PH1_LD4 && \
- !ARCH_UNIPHIER_PH1_SLD8
- help
- This enables support for UniPhier PH1-Pro5 SoC.
+ bool "Enable UniPhier PH1-Pro5 SoC support"
+ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
+ default y
config ARCH_UNIPHIER_PROXSTREAM2
- bool "UniPhier ProXstream2 SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3 && \
- !ARCH_UNIPHIER_PH1_LD4 && \
- !ARCH_UNIPHIER_PH1_SLD8
- help
- This enables support for UniPhier ProXstream2 SoC.
+ bool "Enable UniPhier ProXstream2 SoC support"
+ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
+ default y
config ARCH_UNIPHIER_PH1_LD6B
- bool "UniPhier PH1-LD6b SoC"
- depends on !ARCH_UNIPHIER_PH1_SLD3 && \
- !ARCH_UNIPHIER_PH1_LD4 && \
- !ARCH_UNIPHIER_PH1_SLD8
- help
- This enables support for UniPhier PH1-LD6b SoC.
+ bool "Enable UniPhier PH1-LD6b SoC support"
+ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
+ default y
config MICRO_SUPPORT_CARD
bool "Use Micro Support Card"
diff --git a/arch/arm/mach-uniphier/Makefile b/arch/arm/mach-uniphier/Makefile
index e65d602350..1a8c649964 100644
--- a/arch/arm/mach-uniphier/Makefile
+++ b/arch/arm/mach-uniphier/Makefile
@@ -4,16 +4,11 @@
ifdef CONFIG_SPL_BUILD
-obj-y += lowlevel_init.o
-
obj-y += init/ bcu/ memconf/ pll/ early-clk/ early-pinctrl/
obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/
-obj-$(CONFIG_DEBUG_LL) += debug_ll.o
-
else
-obj-y += late_lowlevel_init.o
obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o
obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o
obj-$(CONFIG_MISC_INIT_F) += print_misc_info.o
@@ -22,16 +17,16 @@ obj-y += board_common.o
obj-$(CONFIG_BOARD_EARLY_INIT_R) += board_early_init_r.o
obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o
obj-y += reset.o
-obj-y += cache_uniphier.o
obj-y += pinctrl/ clk/
endif
-obj-y += timer.o
obj-y += boards.o
obj-y += soc_info.o
obj-y += boot-mode/
obj-y += dram/
obj-$(CONFIG_MICRO_SUPPORT_CARD) += micro-support-card.o
+
+obj-$(CONFIG_CPU_V7) += arm32/
diff --git a/arch/arm/mach-uniphier/arm32/Makefile b/arch/arm/mach-uniphier/arm32/Makefile
new file mode 100644
index 0000000000..376c06b597
--- /dev/null
+++ b/arch/arm/mach-uniphier/arm32/Makefile
@@ -0,0 +1,13 @@
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y += lowlevel_init.o
+obj-$(CONFIG_DEBUG_LL) += debug_ll.o
+else
+obj-y += late_lowlevel_init.o
+obj-y += cache_uniphier.o
+endif
+
+obj-y += timer.o
diff --git a/arch/arm/mach-uniphier/arm-mpcore.h b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
index cf7cd46c10..cf7cd46c10 100644
--- a/arch/arm/mach-uniphier/arm-mpcore.h
+++ b/arch/arm/mach-uniphier/arm32/arm-mpcore.h
diff --git a/arch/arm/mach-uniphier/cache_uniphier.c b/arch/arm/mach-uniphier/arm32/cache_uniphier.c
index 4398114658..4398114658 100644
--- a/arch/arm/mach-uniphier/cache_uniphier.c
+++ b/arch/arm/mach-uniphier/arm32/cache_uniphier.c
diff --git a/arch/arm/mach-uniphier/debug_ll.S b/arch/arm/mach-uniphier/arm32/debug_ll.S
index 6aa5f897a1..a70954cbee 100644
--- a/arch/arm/mach-uniphier/debug_ll.S
+++ b/arch/arm/mach-uniphier/arm32/debug_ll.S
@@ -9,9 +9,9 @@
#include <linux/serial_reg.h>
#include <linux/linkage.h>
-#include "bcu/bcu-regs.h"
-#include "sc-regs.h"
-#include "sg-regs.h"
+#include "../bcu/bcu-regs.h"
+#include "../sc-regs.h"
+#include "../sg-regs.h"
#if !defined(CONFIG_DEBUG_SEMIHOSTING)
#include CONFIG_DEBUG_LL_INCLUDE
diff --git a/arch/arm/mach-uniphier/late_lowlevel_init.S b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
index cce91dfac7..cce91dfac7 100644
--- a/arch/arm/mach-uniphier/late_lowlevel_init.S
+++ b/arch/arm/mach-uniphier/arm32/late_lowlevel_init.S
diff --git a/arch/arm/mach-uniphier/lowlevel_init.S b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
index dd03ad8143..dd03ad8143 100644
--- a/arch/arm/mach-uniphier/lowlevel_init.S
+++ b/arch/arm/mach-uniphier/arm32/lowlevel_init.S
diff --git a/arch/arm/mach-uniphier/ssc-regs.h b/arch/arm/mach-uniphier/arm32/ssc-regs.h
index 02fca3b6f6..02fca3b6f6 100644
--- a/arch/arm/mach-uniphier/ssc-regs.h
+++ b/arch/arm/mach-uniphier/arm32/ssc-regs.h
diff --git a/arch/arm/mach-uniphier/timer.c b/arch/arm/mach-uniphier/arm32/timer.c
index a34e30b72b..a34e30b72b 100644
--- a/arch/arm/mach-uniphier/timer.c
+++ b/arch/arm/mach-uniphier/arm32/timer.c
diff --git a/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c b/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c
index f82c7d1f8e..bbe8a74ce3 100644
--- a/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c
+++ b/arch/arm/mach-uniphier/bcu/bcu-ph1-ld4.c
@@ -22,7 +22,7 @@ int ph1_ld4_bcu_init(const struct uniphier_board_data *bd)
writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */
/* Specify DDR channel */
- shift = (bd->dram_ch1_base - bd->dram_ch0_base) / 0x04000000 * 4;
+ shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4;
writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
shift -= 32;
diff --git a/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c b/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c
index 75ccd155b0..b7497e9e57 100644
--- a/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c
+++ b/arch/arm/mach-uniphier/bcu/bcu-ph1-sld3.c
@@ -26,7 +26,7 @@ int ph1_sld3_bcu_init(const struct uniphier_board_data *bd)
writel(0x24440000, BCSCR5);
/* Specify DDR channel */
- shift = (bd->dram_ch1_base - bd->dram_ch0_base) / 0x04000000 * 4;
+ shift = (bd->dram_ch[1].base - bd->dram_ch[0].base) / 0x04000000 * 4;
writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
shift -= 32;
diff --git a/arch/arm/mach-uniphier/boards.c b/arch/arm/mach-uniphier/boards.c
index d70c712206..408aff0cd0 100644
--- a/arch/arm/mach-uniphier/boards.c
+++ b/arch/arm/mach-uniphier/boards.c
@@ -14,106 +14,154 @@ DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3)
static const struct uniphier_board_data ph1_sld3_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x20000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xc0000000,
- .dram_ch1_size = 0x20000000,
- .dram_ch1_width = 16,
- .dram_ch2_base = 0xc0000000,
- .dram_ch2_size = 0x10000000,
- .dram_ch2_width = 16,
- .dram_freq = 1600,
+ .dram_freq = 1600,
+ .dram_nr_ch = 3,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xc0000000,
+ .size = 0x20000000,
+ .width = 16,
+ },
+ .dram_ch[2] = {
+ .base = 0xc0000000,
+ .size = 0x10000000,
+ .width = 16,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4)
static const struct uniphier_board_data ph1_ld4_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x10000000,
- .dram_ch0_width = 16,
- .dram_ch1_base = 0x90000000,
- .dram_ch1_size = 0x10000000,
- .dram_ch1_width = 16,
- .dram_freq = 1600,
+ .dram_freq = 1600,
+ .dram_nr_ch = 2,
+ .dram_ddr3plus = true,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x10000000,
+ .width = 16,
+ },
+ .dram_ch[1] = {
+ .base = 0x90000000,
+ .size = 0x10000000,
+ .width = 16,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4)
/* 1GB RAM board */
static const struct uniphier_board_data ph1_pro4_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x20000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xa0000000,
- .dram_ch1_size = 0x20000000,
- .dram_ch1_width = 32,
- .dram_freq = 1600,
+ .dram_freq = 1600,
+ .dram_nr_ch = 2,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xa0000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
};
/* 2GB RAM board */
static const struct uniphier_board_data ph1_pro4_2g_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x40000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xc0000000,
- .dram_ch1_size = 0x40000000,
- .dram_ch1_width = 32,
- .dram_freq = 1600,
+ .dram_freq = 1600,
+ .dram_nr_ch = 2,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x40000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xc0000000,
+ .size = 0x40000000,
+ .width = 32,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8)
static const struct uniphier_board_data ph1_sld8_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x10000000,
- .dram_ch0_width = 16,
- .dram_ch1_base = 0x90000000,
- .dram_ch1_size = 0x10000000,
- .dram_ch1_width = 16,
- .dram_freq = 1333,
+ .dram_freq = 1333,
+ .dram_nr_ch = 2,
+ .dram_ddr3plus = true,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x10000000,
+ .width = 16,
+ },
+ .dram_ch[1] = {
+ .base = 0x90000000,
+ .size = 0x10000000,
+ .width = 16,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5)
static const struct uniphier_board_data ph1_pro5_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x20000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xa0000000,
- .dram_ch1_size = 0x20000000,
- .dram_ch1_width = 32,
- .dram_freq = 1866,
+ .dram_freq = 1866,
+ .dram_nr_ch = 2,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xa0000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2)
static const struct uniphier_board_data proxstream2_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x40000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xc0000000,
- .dram_ch1_size = 0x20000000,
- .dram_ch1_width = 32,
- .dram_ch2_base = 0xe0000000,
- .dram_ch2_size = 0x20000000,
- .dram_ch2_width = 16,
- .dram_freq = 2133,
+ .dram_freq = 2133,
+ .dram_nr_ch = 3,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x40000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xc0000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
+ .dram_ch[2] = {
+ .base = 0xe0000000,
+ .size = 0x20000000,
+ .width = 16,
+ },
};
#endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B)
static const struct uniphier_board_data ph1_ld6b_data = {
- .dram_ch0_base = 0x80000000,
- .dram_ch0_size = 0x40000000,
- .dram_ch0_width = 32,
- .dram_ch1_base = 0xc0000000,
- .dram_ch1_size = 0x20000000,
- .dram_ch1_width = 32,
- .dram_ch2_base = 0xe0000000,
- .dram_ch2_size = 0x20000000,
- .dram_ch2_width = 16,
- .dram_freq = 1866,
+ .dram_freq = 1866,
+ .dram_nr_ch = 3,
+ .dram_ch[0] = {
+ .base = 0x80000000,
+ .size = 0x40000000,
+ .width = 32,
+ },
+ .dram_ch[1] = {
+ .base = 0xc0000000,
+ .size = 0x20000000,
+ .width = 32,
+ },
+ .dram_ch[2] = {
+ .base = 0xe0000000,
+ .size = 0x20000000,
+ .width = 16,
+ },
};
#endif
diff --git a/arch/arm/mach-uniphier/boot-mode/boot-mode.c b/arch/arm/mach-uniphier/boot-mode/boot-mode.c
index 935e551472..cf39bf57e9 100644
--- a/arch/arm/mach-uniphier/boot-mode/boot-mode.c
+++ b/arch/arm/mach-uniphier/boot-mode/boot-mode.c
@@ -5,7 +5,9 @@
*/
#include <common.h>
+#include <mmc.h>
#include <spl.h>
+#include <linux/err.h>
#include "../sbc/sbc-regs.h"
#include "../soc-info.h"
@@ -52,3 +54,65 @@ u32 spl_boot_device(void)
return ret == BOOT_DEVICE_USB ? BOOT_DEVICE_NOR : ret;
}
+
+u32 spl_boot_mode(void)
+{
+ struct mmc *mmc;
+
+ /*
+ * work around a bug in the Boot ROM of PH1-sLD3, LD4, Pro4, and sLD8:
+ *
+ * The boot ROM in these SoCs breaks the PARTITION_CONFIG [179] of
+ * Extended CSD register; when switching to the Boot Partition 1, the
+ * Boot ROM should issue the SWITCH command (CMD6) with Set Bits for
+ * the Access Bits, but in fact it uses Write Byte for the Access Bits.
+ * As a result, the BOOT_PARTITION_ENABLE field of the PARTITION_CONFIG
+ * is lost. This bug was fixed for PH1-Pro5 and later SoCs.
+ *
+ * Fixup mmc->part_config here because it is used to determine the
+ * partition which the U-Boot image is read from.
+ */
+ mmc = find_mmc_device(0);
+ mmc->part_config &= ~EXT_CSD_BOOT_PART_NUM(PART_ACCESS_MASK);
+ mmc->part_config |= EXT_CSD_BOOT_PARTITION_ENABLE;
+
+ return MMCSD_MODE_EMMCBOOT;
+}
+
+#if defined(CONFIG_DM_MMC) && !defined(CONFIG_SPL_BUILD)
+static int find_first_mmc_device(void)
+{
+ struct mmc *mmc;
+ int i;
+
+ for (i = 0; (mmc = find_mmc_device(i)); i++) {
+ if (!mmc_init(mmc) && IS_MMC(mmc))
+ return i;
+ }
+
+ return -ENODEV;
+}
+
+int mmc_get_env_dev(void)
+{
+ return find_first_mmc_device();
+}
+
+static int do_mmcsetn(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int dev;
+
+ dev = find_first_mmc_device();
+ if (dev < 0)
+ return CMD_RET_FAILURE;
+
+ setenv_ulong("mmc_first_dev", dev);
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ mmcsetn, 1, 1, do_mmcsetn,
+ "Set the first MMC (not SD) dev number to \"mmc_first_dev\" enviroment",
+ ""
+);
+#endif
diff --git a/arch/arm/mach-uniphier/cpu_info.c b/arch/arm/mach-uniphier/cpu_info.c
index 4e9d01bafd..aae8d1fabd 100644
--- a/arch/arm/mach-uniphier/cpu_info.c
+++ b/arch/arm/mach-uniphier/cpu_info.c
@@ -45,10 +45,10 @@ int print_cpuinfo(void)
puts("PH1-LD6b (MN2WS0320)");
break;
case 0x31:
- puts("PH1-sLD11 ()");
+ puts("PH1-LD11 ()");
break;
case 0x32:
- puts("PH1-LD10 ()");
+ puts("PH1-LD20 ()");
break;
default:
printf("Unknown Processor ID (0x%x)\n", revision);
diff --git a/arch/arm/mach-uniphier/dram/Makefile b/arch/arm/mach-uniphier/dram/Makefile
index a0a6003065..3d1553cbe1 100644
--- a/arch/arm/mach-uniphier/dram/Makefile
+++ b/arch/arm/mach-uniphier/dram/Makefile
@@ -7,9 +7,9 @@ ifdef CONFIG_SPL_BUILD
obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD4) += umc-ph1-ld4.o \
ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_PRO4) += umc-ph1-pro4.o \
- ddrphy-training.o ddrphy-ph1-pro4.o
+ ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_SLD8) += umc-ph1-sld8.o \
- ddrphy-training.o ddrphy-ph1-sld8.o
+ ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) += umc-proxstream2.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD6B) += umc-proxstream2.o
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
index d2bc5a15d4..eb9bf24da0 100644
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
+++ b/arch/arm/mach-uniphier/dram/ddrphy-ph1-ld4.c
@@ -4,31 +4,52 @@
* SPDX-License-Identifier: GPL-2.0+
*/
+#include <common.h>
+#include <linux/err.h>
#include <linux/types.h>
#include <linux/io.h>
#include "ddrphy-regs.h"
-int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0a806844, 0x0c807d04};
+static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x208e0124, 0x2710015E};
+static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x0f051616, 0x12061A80};
+static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x06ae08d6, 0x08027100};
+static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x85589955, 0x999cbb66};
+static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x1a8363c0, 0x1a878400};
+static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x5002c200, 0xa00214f8};
+static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000b51, 0x00000d71};
+static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x00000290, 0x00000298};
+
+int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus)
{
+ enum dram_freq freq_e;
u32 tmp;
- writel(0x0300c473, &phy->pgcr[1]);
- if (freq == 1333) {
- writel(0x0a806844, &phy->ptr[0]);
- writel(0x208e0124, &phy->ptr[1]);
- } else {
- writel(0x0c807d04, &phy->ptr[0]);
- writel(0x2710015E, &phy->ptr[1]);
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ printf("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
}
+
+ writel(0x0300c473, &phy->pgcr[1]);
+ writel(ddrphy_ptr0[freq_e], &phy->ptr[0]);
+ writel(ddrphy_ptr1[freq_e], &phy->ptr[1]);
writel(0x00083DEF, &phy->ptr[2]);
- if (freq == 1333) {
- writel(0x0f051616, &phy->ptr[3]);
- writel(0x06ae08d6, &phy->ptr[4]);
- } else {
- writel(0x12061A80, &phy->ptr[3]);
- writel(0x08027100, &phy->ptr[4]);
- }
+ writel(ddrphy_ptr3[freq_e], &phy->ptr[3]);
+ writel(ddrphy_ptr4[freq_e], &phy->ptr[4]);
writel(0xF004001A, &phy->dsgcr);
/* change the value of the on-die pull-up/pull-down registors */
@@ -38,30 +59,13 @@ int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
writel(tmp, &phy->dxccr);
writel(0x0000040B, &phy->dcr);
- if (freq == 1333) {
- writel(0x85589955, &phy->dtpr[0]);
- if (size == 1)
- writel(0x1a8253c0, &phy->dtpr[1]);
- else
- writel(0x1a8363c0, &phy->dtpr[1]);
- writel(0x5002c200, &phy->dtpr[2]);
- writel(0x00000b51, &phy->mr0);
- } else {
- writel(0x999cbb66, &phy->dtpr[0]);
- if (size == 1)
- writel(0x1a82dbc0, &phy->dtpr[1]);
- else
- writel(0x1a878400, &phy->dtpr[1]);
- writel(0xa00214f8, &phy->dtpr[2]);
- writel(0x00000d71, &phy->mr0);
- }
+ writel(ddrphy_dtpr0[freq_e], &phy->dtpr[0]);
+ writel(ddrphy_dtpr1[freq_e], &phy->dtpr[1]);
+ writel(ddrphy_dtpr2[freq_e], &phy->dtpr[2]);
+ writel(ddrphy_mr0[freq_e], &phy->mr0);
writel(0x00000006, &phy->mr1);
- if (freq == 1333)
- writel(0x00000290, &phy->mr2);
- else
- writel(0x00000298, &phy->mr2);
-
- writel(0x00000800, &phy->mr3);
+ writel(ddrphy_mr2[freq_e], &phy->mr2);
+ writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3);
while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
;
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c
deleted file mode 100644
index 9fb34f79a7..0000000000
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-pro4.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include "ddrphy-regs.h"
-
-int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
-{
- u32 tmp;
-
- writel(0x0300c473, &phy->pgcr[1]);
- if (freq == 1333) {
- writel(0x0a806844, &phy->ptr[0]);
- writel(0x208e0124, &phy->ptr[1]);
- } else {
- writel(0x0c807d04, &phy->ptr[0]);
- writel(0x2710015E, &phy->ptr[1]);
- }
- writel(0x00083DEF, &phy->ptr[2]);
- if (freq == 1333) {
- writel(0x0f051616, &phy->ptr[3]);
- writel(0x06ae08d6, &phy->ptr[4]);
- } else {
- writel(0x12061A80, &phy->ptr[3]);
- writel(0x08027100, &phy->ptr[4]);
- }
- writel(0xF004001A, &phy->dsgcr);
-
- /* change the value of the on-die pull-up/pull-down registors */
- tmp = readl(&phy->dxccr);
- tmp &= ~0x0ee0;
- tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
- writel(tmp, &phy->dxccr);
-
- writel(0x0000040B, &phy->dcr);
- if (freq == 1333) {
- writel(0x85589955, &phy->dtpr[0]);
- writel(0x1a8363c0, &phy->dtpr[1]);
- writel(0x5002c200, &phy->dtpr[2]);
- writel(0x00000b51, &phy->mr0);
- } else {
- writel(0x999cbb66, &phy->dtpr[0]);
- writel(0x1a878400, &phy->dtpr[1]);
- writel(0xa00214f8, &phy->dtpr[2]);
- writel(0x00000d71, &phy->mr0);
- }
- writel(0x00000006, &phy->mr1);
- if (freq == 1333)
- writel(0x00000290, &phy->mr2);
- else
- writel(0x00000298, &phy->mr2);
-
- writel(0x00000000, &phy->mr3);
-
- while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
- ;
-
- writel(0x0300C473, &phy->pgcr[1]);
- writel(0x0000005D, &phy->zq[0].cr[1]);
-
- return 0;
-}
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c b/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c
deleted file mode 100644
index 651069073c..0000000000
--- a/arch/arm/mach-uniphier/dram/ddrphy-ph1-sld8.c
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Masahiro Yamada <yamada.masahiro@socionext.com>
- *
- * SPDX-License-Identifier: GPL-2.0+
- */
-
-#include <config.h>
-#include <linux/types.h>
-#include <linux/io.h>
-
-#include "ddrphy-regs.h"
-
-int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size)
-{
- u32 tmp;
-
- writel(0x0300c473, &phy->pgcr[1]);
- if (freq == 1333) {
- writel(0x0a806844, &phy->ptr[0]);
- writel(0x208e0124, &phy->ptr[1]);
- } else {
- writel(0x0c807d04, &phy->ptr[0]);
- writel(0x2710015E, &phy->ptr[1]);
- }
- writel(0x00083DEF, &phy->ptr[2]);
- if (freq == 1333) {
- writel(0x0f051616, &phy->ptr[3]);
- writel(0x06ae08d6, &phy->ptr[4]);
- } else {
- writel(0x12061A80, &phy->ptr[3]);
- writel(0x08027100, &phy->ptr[4]);
- }
- writel(0xF004001A, &phy->dsgcr);
-
- /* change the value of the on-die pull-up/pull-down registors */
- tmp = readl(&phy->dxccr);
- tmp &= ~0x0ee0;
- tmp |= DXCCR_DQSNRES_688_OHM | DXCCR_DQSRES_688_OHM;
- writel(tmp, &phy->dxccr);
-
- writel(0x0000040B, &phy->dcr);
- if (freq == 1333) {
- writel(0x85589955, &phy->dtpr[0]);
- if (size == 1)
- writel(0x1a8363c0, &phy->dtpr[1]);
- else
- writel(0x1a8363c0, &phy->dtpr[1]);
- writel(0x5002c200, &phy->dtpr[2]);
- writel(0x00000b51, &phy->mr0);
- } else {
- writel(0x999cbb66, &phy->dtpr[0]);
- if (size == 1)
- writel(0x1a878400, &phy->dtpr[1]);
- else
- writel(0x1a878400, &phy->dtpr[1]);
- writel(0xa00214f8, &phy->dtpr[2]);
- writel(0x00000d71, &phy->mr0);
- }
- writel(0x00000006, &phy->mr1);
- if (freq == 1333)
- writel(0x00000290, &phy->mr2);
- else
- writel(0x00000298, &phy->mr2);
-
-#ifdef CONFIG_DDR_STANDARD
- writel(0x00000000, &phy->mr3);
-#else
- writel(0x00000800, &phy->mr3);
-#endif
-
- while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE))
- ;
-
- writel(0x0300C473, &phy->pgcr[1]);
- writel(0x0000005D, &phy->zq[0].cr[1]);
-
- return 0;
-}
diff --git a/arch/arm/mach-uniphier/dram/ddrphy-regs.h b/arch/arm/mach-uniphier/dram/ddrphy-regs.h
index 03aedc2e63..87f6d0d3a2 100644
--- a/arch/arm/mach-uniphier/dram/ddrphy-regs.h
+++ b/arch/arm/mach-uniphier/dram/ddrphy-regs.h
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/compiler.h>
+#include <linux/types.h>
#ifndef __ASSEMBLY__
@@ -169,9 +170,7 @@ struct ddrphy {
#define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy))
#ifndef __ASSEMBLY__
-int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
-int ph1_pro4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
-int ph1_sld8_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size);
+int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus);
void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank);
int ddrphy_training(struct ddrphy __iomem *phy);
#endif
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
index ffd7aa97b2..72447cc776 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-ld4.c
@@ -8,11 +8,40 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+enum dram_size {
+ DRAM_SZ_128M,
+ DRAM_SZ_256M,
+ DRAM_SZ_NR,
+};
+
+static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x36bb0f17};
+static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6aa24};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x00240512, 0x00350512},
+ {0x002b0617, 0x003f0617},
+};
+static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008};
+static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ae};
+
+static int umc_get_rank(int ch)
+{
+ return ch; /* ch0: rank0, ch1: rank1 for this SoC */
+}
+
static void umc_start_ssif(void __iomem *ssif_base)
{
writel(0x00000000, ssif_base + 0x0000b004);
@@ -47,130 +76,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int freq)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
- if (freq == 1333) {
- writel(0x45990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958924, dramcont + UMC_CMDCTLB);
- writel(0x5101046A, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x27028B0A, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x38028B0A, dramcont + UMC_INITCTLB);
-
- writel(0x000FF0FF, dramcont + UMC_INITCTLC);
- writel(0x00000b51, dramcont + UMC_DRMMR0);
- } else if (freq == 1600) {
- writel(0x36BB0F17, dramcont + UMC_CMDCTLA);
- writel(0x18C6AA24, dramcont + UMC_CMDCTLB);
- writel(0x5101387F, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x2F030D3F, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x43030D3F, dramcont + UMC_INITCTLB);
-
- writel(0x00FF00FF, dramcont + UMC_INITCTLC);
- writel(0x00000d71, dramcont + UMC_DRMMR0);
- }
-
- writel(0x00000006, dramcont + UMC_DRMMR1);
-
- if (freq == 1333)
- writel(0x00000290, dramcont + UMC_DRMMR2);
- else if (freq == 1600)
- writel(0x00000298, dramcont + UMC_DRMMR2);
-
- writel(0x00000800, dramcont + UMC_DRMMR3);
+ enum dram_freq freq_e;
+ enum dram_size size_e;
- if (freq == 1333) {
- if (size == 1)
- writel(0x00240512, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x00350512, dramcont + UMC_SPCCTLA);
+ if (!ddr3plus) {
+ pr_err("DDR3 standard is not supported\n");
+ return -EINVAL;
+ }
- writel(0x00ff0006, dramcont + UMC_SPCCTLB);
- writel(0x000a00ac, dramcont + UMC_RDATACTL_D0);
- } else if (freq == 1600) {
- if (size == 1)
- writel(0x002B0617, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x003F0617, dramcont + UMC_SPCCTLA);
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ pr_err("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
- writel(0x00ff0008, dramcont + UMC_SPCCTLB);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_128M:
+ size_e = DRAM_SZ_128M;
+ break;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx\n", size);
+ return -EINVAL;
}
- writel(0x04060806, dramcont + UMC_WDATACTL_D0);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ writel(umc_cmdctla_plus[freq_e], dc_base + UMC_CMDCTLA);
+ writel(umc_cmdctlb_plus[freq_e], dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB);
+ writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
+ writel(0x04060806, dc_base + UMC_WDATACTL_D0);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x00000003, dramcont + 0x7000);
- writel(0x0000000f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000071, dramcont + 0x8008);
- writel(0x0000003b, dramcont + UMC_DICGCTLA);
- writel(0x020a0808, dramcont + UMC_DICGCTLB);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000003, dc_base + 0x7000);
+ writel(0x0000000f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000071, dc_base + 0x8008);
+ writel(0x0000003b, dc_base + UMC_DICGCTLA);
+ writel(0x020a0808, dc_base + UMC_DICGCTLB);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00000000, dramcont + UMC_SPCSETD);
- writel(0x00000520, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00000000, dc_base + UMC_SPCSETD);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+
+ return 0;
}
-static int umc_init_sub(int freq, int size_ch0, int size_ch1)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus, int ch)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
- void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
- void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
- void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
- void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
-
- umc_dram_init_start(dramcont0);
- umc_dram_init_start(dramcont1);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
-
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
-
- ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int ret;
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ writel(0x00000101, dc_base + UMC_DIOCTLA);
- ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- ddrphy_prepare_training(phy1_0, 1);
- ddrphy_training(phy1_0);
-
- umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
- umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
-
- umc_start_ssif(ssif_base);
+ ddrphy_prepare_training(phy_base, umc_get_rank(ch));
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- return 0;
+ return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
int ph1_ld4_umc_init(const struct uniphier_board_data *bd)
{
- if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) &&
- (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) &&
- (bd->dram_freq == 1333 || bd->dram_freq == 1600) &&
- bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) {
- return umc_init_sub(bd->dram_freq,
- bd->dram_ch0_size / SZ_128M,
- bd->dram_ch1_size / SZ_128M);
- } else {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ddr3plus, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
}
+
+ umc_start_ssif(ssif_base);
+
+ return 0;
}
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
index 261f7cfce7..23fb7b9f53 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-pro4.c
@@ -8,11 +8,14 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
enum dram_size {
DRAM_SZ_128M,
DRAM_SZ_256M,
@@ -20,14 +23,13 @@ enum dram_size {
DRAM_SZ_NR,
};
-static u32 umc_initctlb[DRAM_SZ_NR] = {0x43030d3f, 0x43030d3f, 0x7b030d3f};
static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617};
static void umc_start_ssif(void __iomem *ssif_base)
{
- writel(0x00000001, ssif_base + 0x0000b004);
+ writel(0x00000000, ssif_base + 0x0000b004);
writel(0xffffffff, ssif_base + 0x0000c004);
- writel(0x07ffffff, ssif_base + 0x0000c008);
+ writel(0x000fffcf, ssif_base + 0x0000c008);
writel(0x00000001, ssif_base + 0x0000b000);
writel(0x00000001, ssif_base + 0x0000c000);
@@ -66,121 +68,117 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int width)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
- enum dram_size dram_size;
+ enum dram_size size_e;
+
+ if (freq != 1600) {
+ pr_err("Unsupported DDR frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ if (ddr3plus) {
+ pr_err("DDR3+ is not supported\n");
+ return -EINVAL;
+ }
- switch (size / (width / 16)) {
+ switch (size) {
case SZ_128M:
- dram_size = DRAM_SZ_128M;
+ size_e = DRAM_SZ_128M;
break;
case SZ_256M:
- dram_size = DRAM_SZ_256M;
+ size_e = DRAM_SZ_256M;
break;
case SZ_512M:
- dram_size = DRAM_SZ_512M;
+ size_e = DRAM_SZ_512M;
break;
default:
- printf("unsupported DRAM size\n");
+ pr_err("unsupported DRAM size 0x%08lx (per 16bit)\n", size);
return -EINVAL;
}
- writel(0x66bb0f17, dramcont + UMC_CMDCTLA);
- writel(0x18c6aa44, dramcont + UMC_CMDCTLB);
- writel(0x5101387f, dramcont + UMC_INITCTLA);
- writel(umc_initctlb[dram_size], dramcont + UMC_INITCTLB);
- writel(0x00ff00ff, dramcont + UMC_INITCTLC);
- writel(0x00000d71, dramcont + UMC_DRMMR0);
- writel(0x00000006, dramcont + UMC_DRMMR1);
- writel(0x00000298, dramcont + UMC_DRMMR2);
- writel(0x00000000, dramcont + UMC_DRMMR3);
- writel(umc_spcctla[dram_size], dramcont + UMC_SPCCTLA);
- writel(0x00ff0008, dramcont + UMC_SPCCTLB);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
- writel(0x000c00ae, dramcont + UMC_RDATACTL_D1);
- writel(0x04060802, dramcont + UMC_WDATACTL_D0);
- writel(0x04060802, dramcont + UMC_WDATACTL_D1);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ writel(0x66bb0f17, dc_base + UMC_CMDCTLA);
+ writel(0x18c6aa44, dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[size_e], dc_base + UMC_SPCCTLA);
+ writel(0x00ff0008, dc_base + UMC_SPCCTLB);
+ writel(0x000c00ae, dc_base + UMC_RDATACTL_D0);
+ writel(0x000c00ae, dc_base + UMC_RDATACTL_D1);
+ writel(0x04060802, dc_base + UMC_WDATACTL_D0);
+ writel(0x04060802, dc_base + UMC_WDATACTL_D1);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x0000000f, dramcont + 0x7000);
- writel(0x0000000f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000071, dramcont + 0x8008);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
- writel(0x00000000, dramcont + 0x0060);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x0000000f, dc_base + 0x7000);
+ writel(0x0000000f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000071, dc_base + 0x8008);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
+ writel(0x00000000, dc_base + 0x0060);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00010000, dramcont + UMC_SPCSETD);
- writel(0x80000020, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00010000, dc_base + UMC_SPCSETD);
+ writel(0x80000020, dc_base + UMC_DFICUPDCTLA);
return 0;
}
-int ph1_pro4_umc_init(const struct uniphier_board_data *bd)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, unsigned int width,
+ bool ddr3plus)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
- void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
- void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
- void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
- void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1);
- void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
- void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1);
- int ret;
-
- if (bd->dram_freq != 1600) {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
- }
-
- umc_dram_init_start(dramcont0);
- umc_dram_init_start(dramcont1);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
-
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int nr_phy = width / 16;
+ int phy, ret;
- ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch0_size);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ for (phy = 0; phy < nr_phy; phy++) {
+ writel(0x00000100 | ((1 << (phy + 1)) - 1),
+ dc_base + UMC_DIOCTLA);
- writel(0x00000103, dramcont0 + UMC_DIOCTLA);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch0_size);
+ ddrphy_prepare_training(phy_base, phy);
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- ddrphy_prepare_training(phy0_1, 1);
- ddrphy_training(phy0_1);
-
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
-
- ph1_pro4_ddrphy_init(phy1_0, bd->dram_freq, bd->dram_ch1_size);
-
- ddrphy_prepare_training(phy1_0, 0);
- ddrphy_training(phy1_0);
-
- writel(0x00000103, dramcont1 + UMC_DIOCTLA);
-
- ph1_pro4_ddrphy_init(phy1_1, bd->dram_freq, bd->dram_ch1_size);
-
- ddrphy_prepare_training(phy1_1, 1);
- ddrphy_training(phy1_1);
+ phy_base += 0x00001000;
+ }
- ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch0_size,
- bd->dram_ch0_width);
- if (ret)
- return ret;
+ return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16),
+ ddr3plus);
+}
- ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch1_size,
- bd->dram_ch1_width);
- if (ret)
- return ret;
+int ph1_pro4_umc_init(const struct uniphier_board_data *bd)
+{
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ch[ch].width,
+ bd->dram_ddr3plus);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
+ }
umc_start_ssif(ssif_base);
diff --git a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
index 09f9ccfb43..6cacd25e7c 100644
--- a/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
+++ b/arch/arm/mach-uniphier/dram/umc-ph1-sld8.c
@@ -8,11 +8,43 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sizes.h>
+#include <asm/processor.h>
#include "../init.h"
#include "ddrphy-regs.h"
#include "umc-regs.h"
+#define DRAM_CH_NR 2
+
+enum dram_freq {
+ DRAM_FREQ_1333M,
+ DRAM_FREQ_1600M,
+ DRAM_FREQ_NR,
+};
+
+enum dram_size {
+ DRAM_SZ_128M,
+ DRAM_SZ_256M,
+ DRAM_SZ_512M,
+ DRAM_SZ_NR,
+};
+
+static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x55990b11, 0x66bb0f17};
+static u32 umc_cmdctla_plus[DRAM_FREQ_NR] = {0x45990b11, 0x46bb0f17};
+static u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x16958944, 0x18c6ab44};
+static u32 umc_cmdctlb_plus[DRAM_FREQ_NR] = {0x16958924, 0x18c6ab24};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x00240512, 0x00350512, 0x00000000}, /* no data for 1333MHz,128MB */
+ {0x002b0617, 0x003f0617, 0x00670617},
+};
+static u32 umc_spcctlb[DRAM_FREQ_NR] = {0x00ff0006, 0x00ff0008};
+static u32 umc_rdatactl[DRAM_FREQ_NR] = {0x000a00ac, 0x000c00ac};
+
+static int umc_get_rank(int ch)
+{
+ return ch; /* ch0: rank0, ch1: rank1 for this SoC */
+}
+
static void umc_start_ssif(void __iomem *ssif_base)
{
writel(0x00000000, ssif_base + 0x0000b004);
@@ -47,110 +79,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST);
}
-static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base,
- int size, int freq)
+static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus)
{
-#ifdef CONFIG_DDR_STANDARD
- writel(0x55990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958944, dramcont + UMC_CMDCTLB);
-#else
- writel(0x45990b11, dramcont + UMC_CMDCTLA);
- writel(0x16958924, dramcont + UMC_CMDCTLB);
-#endif
-
- writel(0x5101046A, dramcont + UMC_INITCTLA);
-
- if (size == 1)
- writel(0x27028B0A, dramcont + UMC_INITCTLB);
- else if (size == 2)
- writel(0x38028B0A, dramcont + UMC_INITCTLB);
-
- writel(0x00FF00FF, dramcont + UMC_INITCTLC);
- writel(0x00000b51, dramcont + UMC_DRMMR0);
- writel(0x00000006, dramcont + UMC_DRMMR1);
- writel(0x00000290, dramcont + UMC_DRMMR2);
-
-#ifdef CONFIG_DDR_STANDARD
- writel(0x00000000, dramcont + UMC_DRMMR3);
-#else
- writel(0x00000800, dramcont + UMC_DRMMR3);
-#endif
-
- if (size == 1)
- writel(0x00240512, dramcont + UMC_SPCCTLA);
- else if (size == 2)
- writel(0x00350512, dramcont + UMC_SPCCTLA);
-
- writel(0x00ff0006, dramcont + UMC_SPCCTLB);
- writel(0x000a00ac, dramcont + UMC_RDATACTL_D0);
- writel(0x04060806, dramcont + UMC_WDATACTL_D0);
- writel(0x04a02000, dramcont + UMC_DATASET);
+ enum dram_freq freq_e;
+ enum dram_size size_e;
+
+ switch (freq) {
+ case 1333:
+ freq_e = DRAM_FREQ_1333M;
+ break;
+ case 1600:
+ freq_e = DRAM_FREQ_1600M;
+ break;
+ default:
+ pr_err("unsupported DRAM frequency %d MHz\n", freq);
+ return -EINVAL;
+ }
+
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_128M:
+ size_e = DRAM_SZ_128M;
+ break;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ case SZ_512M:
+ size_e = DRAM_SZ_512M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx\n", size);
+ return -EINVAL;
+ }
+
+ writel((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e],
+ dc_base + UMC_CMDCTLA);
+ writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e],
+ dc_base + UMC_CMDCTLB);
+ writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB);
+ writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
+ writel(0x04060806, dc_base + UMC_WDATACTL_D0);
+ writel(0x04a02000, dc_base + UMC_DATASET);
writel(0x00000000, ca_base + 0x2300);
- writel(0x00400020, dramcont + UMC_DCCGCTL);
- writel(0x00000003, dramcont + 0x7000);
- writel(0x0000004f, dramcont + 0x8000);
- writel(0x000000c3, dramcont + 0x8004);
- writel(0x00000077, dramcont + 0x8008);
- writel(0x0000003b, dramcont + UMC_DICGCTLA);
- writel(0x020a0808, dramcont + UMC_DICGCTLB);
- writel(0x00000004, dramcont + UMC_FLOWCTLG);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000003, dc_base + 0x7000);
+ writel(0x0000004f, dc_base + 0x8000);
+ writel(0x000000c3, dc_base + 0x8004);
+ writel(0x00000077, dc_base + 0x8008);
+ writel(0x0000003b, dc_base + UMC_DICGCTLA);
+ writel(0x020a0808, dc_base + UMC_DICGCTLB);
+ writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20);
- writel(0x0801e01e, dramcont + UMC_FLOWCTLA);
- writel(0x00200000, dramcont + UMC_FLOWCTLB);
- writel(0x00004444, dramcont + UMC_FLOWCTLC);
- writel(0x200a0a00, dramcont + UMC_SPCSETB);
- writel(0x00000000, dramcont + UMC_SPCSETD);
- writel(0x00000520, dramcont + UMC_DFICUPDCTLA);
+ writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00004444, dc_base + UMC_FLOWCTLC);
+ writel(0x200a0a00, dc_base + UMC_SPCSETB);
+ writel(0x00000000, dc_base + UMC_SPCSETD);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+
+ return 0;
}
-static int umc_init_sub(int freq, int size_ch0, int size_ch1)
+static int umc_ch_init(void __iomem *dc_base, void __iomem *ca_base,
+ int freq, unsigned long size, bool ddr3plus, int ch)
{
- void __iomem *ssif_base = (void __iomem *)UMC_SSIF_BASE;
- void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0);
- void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
- void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
- void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
- void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
- void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
-
- umc_dram_init_start(dramcont0);
- umc_dram_init_start(dramcont1);
- umc_dram_init_poll(dramcont0);
- umc_dram_init_poll(dramcont1);
+ void __iomem *phy_base = dc_base + 0x00001000;
+ int ret;
- writel(0x00000101, dramcont0 + UMC_DIOCTLA);
+ writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
+ cpu_relax();
- ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0);
+ writel(0x00000101, dc_base + UMC_DIOCTLA);
- ddrphy_prepare_training(phy0_0, 0);
- ddrphy_training(phy0_0);
+ ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
+ if (ret)
+ return ret;
- writel(0x00000101, dramcont1 + UMC_DIOCTLA);
+ ddrphy_prepare_training(phy_base, umc_get_rank(ch));
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
- ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1);
-
- ddrphy_prepare_training(phy1_0, 1);
- ddrphy_training(phy1_0);
-
- umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
- umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
-
- umc_start_ssif(ssif_base);
-
- return 0;
+ return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
int ph1_sld8_umc_init(const struct uniphier_board_data *bd)
{
- if ((bd->dram_ch0_size == SZ_128M || bd->dram_ch0_size == SZ_256M) &&
- (bd->dram_ch1_size == SZ_128M || bd->dram_ch1_size == SZ_256M) &&
- bd->dram_freq == 1333 &&
- bd->dram_ch0_width == 16 && bd->dram_ch1_width == 16) {
- return umc_init_sub(bd->dram_freq,
- bd->dram_ch0_size / SZ_128M,
- bd->dram_ch1_size / SZ_128M);
- } else {
- pr_err("Unsupported DDR configuration\n");
- return -EINVAL;
+ void __iomem *umc_base = (void __iomem *)0x5b800000;
+ void __iomem *ca_base = umc_base + 0x00001000;
+ void __iomem *dc_base = umc_base + 0x00400000;
+ void __iomem *ssif_base = umc_base;
+ int ch, ret;
+
+ for (ch = 0; ch < DRAM_CH_NR; ch++) {
+ ret = umc_ch_init(dc_base, ca_base, bd->dram_freq,
+ bd->dram_ch[ch].size,
+ bd->dram_ddr3plus, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
+
+ ca_base += 0x00001000;
+ dc_base += 0x00200000;
}
+
+ umc_start_ssif(ssif_base);
+
+ return 0;
}
diff --git a/arch/arm/mach-uniphier/dram/umc-proxstream2.c b/arch/arm/mach-uniphier/dram/umc-proxstream2.c
index 6e7fa885c4..50c023825e 100644
--- a/arch/arm/mach-uniphier/dram/umc-proxstream2.c
+++ b/arch/arm/mach-uniphier/dram/umc-proxstream2.c
@@ -18,46 +18,45 @@
#include "ddrmphy-regs.h"
#include "umc-regs.h"
-#define CH_NR 3
+#define DRAM_CH_NR 3
enum dram_freq {
- FREQ_1866M,
- FREQ_2133M,
- FREQ_NR,
+ DRAM_FREQ_1866M,
+ DRAM_FREQ_2133M,
+ DRAM_FREQ_NR,
};
enum dram_size {
- SIZE_0,
- SIZE_512M,
- SIZE_1G,
- SIZE_NR,
+ DRAM_SZ_256M,
+ DRAM_SZ_512M,
+ DRAM_SZ_NR,
};
-static u32 ddrphy_pgcr2[FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
-static u32 ddrphy_ptr0[FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
-static u32 ddrphy_ptr1[FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
-static u32 ddrphy_ptr3[FREQ_NR] = {0x15171e45, 0x18182357};
-static u32 ddrphy_ptr4[FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
-static u32 ddrphy_dtpr0[FREQ_NR] = {0x35a00d88, 0x39e40e88};
-static u32 ddrphy_dtpr1[FREQ_NR] = {0x2288cc2c, 0x228a04d0};
-static u32 ddrphy_dtpr2[FREQ_NR] = {0x50005e00, 0x50006a00};
-static u32 ddrphy_dtpr3[FREQ_NR] = {0x0010cb49, 0x0010ec89};
-static u32 ddrphy_mr0[FREQ_NR] = {0x00000115, 0x00000125};
-static u32 ddrphy_mr2[FREQ_NR] = {0x000002a0, 0x000002a8};
+static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
+static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
+static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
+static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357};
+static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
+static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88};
+static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0};
+static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00};
+static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89};
+static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125};
+static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8};
/* dependent on package and board design */
-static u32 ddrphy_acbdlr0[CH_NR] = {0x0000000c, 0x0000000c, 0x00000009};
+static u32 ddrphy_acbdlr0[DRAM_CH_NR] = {0x0000000c, 0x0000000c, 0x00000009};
-static u32 umc_cmdctla[FREQ_NR] = {0x66DD131D, 0x77EE1722};
+static u32 umc_cmdctla[DRAM_FREQ_NR] = {0x66DD131D, 0x77EE1722};
/*
* The ch2 is a different generation UMC core.
* The register spec is different, unfortunately.
*/
-static u32 umc_cmdctlb_ch01[FREQ_NR] = {0x13E87C44, 0x18F88C44};
-static u32 umc_cmdctlb_ch2[FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
-static u32 umc_spcctla[FREQ_NR][SIZE_NR] = {
- {0x00000000, 0x004A071D, 0x0078071D},
- {0x00000000, 0x0055081E, 0x0089081E},
+static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44};
+static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
+static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
+ {0x004A071D, 0x0078071D},
+ {0x0055081E, 0x0089081E},
};
static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B};
@@ -344,7 +343,7 @@ static int __ddrphy_training(void __iomem *phy_base,
do {
if (--timeout < 0) {
- printf("%s: error: timeout during DDR training\n",
+ pr_err("%s: error: timeout during DDR training\n",
__func__);
return -ETIMEDOUT;
}
@@ -354,7 +353,7 @@ static int __ddrphy_training(void __iomem *phy_base,
for (s = seq; s->description; s++) {
if (pgsr0 & s->err_flag) {
- printf("%s: error: %s failed\n", __func__,
+ pr_err("%s: error: %s failed\n", __func__,
s->description);
return -EIO;
}
@@ -405,12 +404,12 @@ static int ddrphy_training(void __iomem *phy_base)
}
/* UMC */
-static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency)
+static void umc_set_system_latency(void __iomem *dc_base, int phy_latency)
{
u32 val;
int latency;
- val = readl(umc_dc_base + UMC_RDATACTL_D0);
+ val = readl(dc_base + UMC_RDATACTL_D0);
latency = (val & UMC_RDATACTL_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT;
latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >>
UMC_RDATACTL_RAD2LTY_SHIFT;
@@ -428,18 +427,18 @@ static void umc_set_system_latency(void __iomem *umc_dc_base, int phy_latency)
val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
}
- writel(val, umc_dc_base + UMC_RDATACTL_D0);
- writel(val, umc_dc_base + UMC_RDATACTL_D1);
+ writel(val, dc_base + UMC_RDATACTL_D0);
+ writel(val, dc_base + UMC_RDATACTL_D1);
- readl(umc_dc_base + UMC_RDATACTL_D1); /* relax */
+ readl(dc_base + UMC_RDATACTL_D1); /* relax */
}
/* enable/disable auto refresh */
-void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable)
+void umc_refresh_ctrl(void __iomem *dc_base, int enable)
{
u32 tmp;
- tmp = readl(umc_dc_base + UMC_SPCSETB);
+ tmp = readl(dc_base + UMC_SPCSETB);
tmp &= ~UMC_SPCSETB_AREFMD_MASK;
if (enable)
@@ -447,7 +446,7 @@ void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable)
else
tmp |= UMC_SPCSETB_AREFMD_REG;
- writel(tmp, umc_dc_base + UMC_SPCSETB);
+ writel(tmp, dc_base + UMC_SPCSETB);
udelay(1);
}
@@ -459,20 +458,35 @@ static void umc_ud_init(void __iomem *umc_base, int ch)
writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0);
}
-static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq,
- enum dram_size size, int ch, int width)
+static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
+ unsigned long size, int width, int ch)
{
+ enum dram_size size_e;
int latency;
u32 val;
- writel(umc_cmdctla[freq], umc_dc_base + UMC_CMDCTLA);
+ switch (size) {
+ case 0:
+ return 0;
+ case SZ_256M:
+ size_e = DRAM_SZ_256M;
+ break;
+ case SZ_512M:
+ size_e = DRAM_SZ_512M;
+ break;
+ default:
+ pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
+ size, ch);
+ return -EINVAL;
+ }
+
+ writel(umc_cmdctla[freq], dc_base + UMC_CMDCTLA);
writel(ch == 2 ? umc_cmdctlb_ch2[freq] : umc_cmdctlb_ch01[freq],
- umc_dc_base + UMC_CMDCTLB);
+ dc_base + UMC_CMDCTLB);
- writel(umc_spcctla[freq][size / (width / 16)],
- umc_dc_base + UMC_SPCCTLA);
- writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB);
+ writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA);
+ writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB);
val = 0x000e000e;
latency = 12;
@@ -487,54 +501,56 @@ static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq,
val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
}
- writel(val, umc_dc_base + UMC_RDATACTL_D0);
+ writel(val, dc_base + UMC_RDATACTL_D0);
if (width >= 32)
- writel(val, umc_dc_base + UMC_RDATACTL_D1);
+ writel(val, dc_base + UMC_RDATACTL_D1);
- writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D0);
+ writel(0x04060A02, dc_base + UMC_WDATACTL_D0);
if (width >= 32)
- writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D1);
- writel(0x04000000, umc_dc_base + UMC_DATASET);
- writel(0x00400020, umc_dc_base + UMC_DCCGCTL);
- writel(0x00000084, umc_dc_base + UMC_FLOWCTLG);
- writel(0x00000000, umc_dc_base + UMC_ACSSETA);
+ writel(0x04060A02, dc_base + UMC_WDATACTL_D1);
+ writel(0x04000000, dc_base + UMC_DATASET);
+ writel(0x00400020, dc_base + UMC_DCCGCTL);
+ writel(0x00000084, dc_base + UMC_FLOWCTLG);
+ writel(0x00000000, dc_base + UMC_ACSSETA);
writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq],
- umc_dc_base + UMC_FLOWCTLA);
+ dc_base + UMC_FLOWCTLA);
- writel(0x00004400, umc_dc_base + UMC_FLOWCTLC);
- writel(0x200A0A00, umc_dc_base + UMC_SPCSETB);
- writel(0x00000520, umc_dc_base + UMC_DFICUPDCTLA);
- writel(0x0000000D, umc_dc_base + UMC_RESPCTL);
+ writel(0x00004400, dc_base + UMC_FLOWCTLC);
+ writel(0x200A0A00, dc_base + UMC_SPCSETB);
+ writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
+ writel(0x0000000D, dc_base + UMC_RESPCTL);
if (ch != 2) {
- writel(0x00202000, umc_dc_base + UMC_FLOWCTLB);
- writel(0xFDBFFFFF, umc_dc_base + UMC_FLOWCTLOB0);
- writel(0xFFFFFFFF, umc_dc_base + UMC_FLOWCTLOB1);
- writel(0x00080700, umc_dc_base + UMC_BSICMAPSET);
+ writel(0x00202000, dc_base + UMC_FLOWCTLB);
+ writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0);
+ writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1);
+ writel(0x00080700, dc_base + UMC_BSICMAPSET);
} else {
- writel(0x00200000, umc_dc_base + UMC_FLOWCTLB);
- writel(0x00000000, umc_dc_base + UMC_BSICMAPSET);
+ writel(0x00200000, dc_base + UMC_FLOWCTLB);
+ writel(0x00000000, dc_base + UMC_BSICMAPSET);
}
- writel(0x00000000, umc_dc_base + UMC_ERRMASKA);
- writel(0x00000000, umc_dc_base + UMC_ERRMASKB);
+ writel(0x00000000, dc_base + UMC_ERRMASKA);
+ writel(0x00000000, dc_base + UMC_ERRMASKB);
+
+ return 0;
}
-static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch,
- enum dram_size size, int width)
+static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq,
+ unsigned long size, unsigned int width, int ch)
{
- void __iomem *umc_dc_base = umc_base + 0x00011000;
- void __iomem *phy_base = umc_base + 0x00030000;
+ void __iomem *dc_base = umc_ch_base + 0x00011000;
+ void __iomem *phy_base = umc_ch_base + 0x00030000;
int ret;
- writel(0x00000002, umc_dc_base + UMC_INITSET);
- while (readl(umc_dc_base + UMC_INITSTAT) & BIT(2))
+ writel(0x00000002, dc_base + UMC_INITSET);
+ while (readl(dc_base + UMC_INITSTAT) & BIT(2))
cpu_relax();
/* deassert PHY reset signals */
writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
- umc_dc_base + UMC_DIOCTLA);
+ dc_base + UMC_DIOCTLA);
ddrphy_init(phy_base, freq, width, ch);
@@ -546,28 +562,28 @@ static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch,
if (ret)
return ret;
- umc_dc_init(umc_dc_base, freq, size, ch, width);
+ ret = umc_dc_init(dc_base, freq, size, width, ch);
+ if (ret)
+ return ret;
- umc_ud_init(umc_base, ch);
+ umc_ud_init(umc_ch_base, ch);
- if (size) {
- ret = ddrphy_training(phy_base);
- if (ret)
- return ret;
- }
+ ret = ddrphy_training(phy_base);
+ if (ret)
+ return ret;
udelay(1);
/* match the system latency between UMC and PHY */
- umc_set_system_latency(umc_dc_base,
+ umc_set_system_latency(dc_base,
ddrphy_get_system_latency(phy_base, width));
udelay(1);
/* stop auto refresh before clearing FIFO in PHY */
- umc_refresh_ctrl(umc_dc_base, 0);
+ umc_refresh_ctrl(dc_base, 0);
ddrphy_fifo_reset(phy_base);
- umc_refresh_ctrl(umc_dc_base, 1);
+ umc_refresh_ctrl(dc_base, 1);
udelay(10);
@@ -585,43 +601,34 @@ static void um_init(void __iomem *um_base)
int proxstream2_umc_init(const struct uniphier_board_data *bd)
{
void __iomem *um_base = (void __iomem *)0x5b600000;
- void __iomem *umc_ch0_base = (void __iomem *)0x5b800000;
- void __iomem *umc_ch1_base = (void __iomem *)0x5ba00000;
- void __iomem *umc_ch2_base = (void __iomem *)0x5bc00000;
+ void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
enum dram_freq freq;
- int ret;
+ int ch, ret;
switch (bd->dram_freq) {
case 1866:
- freq = FREQ_1866M;
+ freq = DRAM_FREQ_1866M;
break;
case 2133:
- freq = FREQ_2133M;
+ freq = DRAM_FREQ_2133M;
break;
default:
- printf("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
+ pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
return -EINVAL;
}
- ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch0_size / SZ_256M,
- bd->dram_ch0_width);
- if (ret) {
- printf("failed to initialize UMC ch0\n");
- return ret;
- }
+ for (ch = 0; ch < bd->dram_nr_ch; ch++) {
+ unsigned long size = bd->dram_ch[ch].size;
+ unsigned int width = bd->dram_ch[ch].width;
- ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch1_size / SZ_256M,
- bd->dram_ch1_width);
- if (ret) {
- printf("failed to initialize UMC ch1\n");
- return ret;
- }
+ ret = umc_ch_init(umc_ch_base, freq, size / (width / 16),
+ width, ch);
+ if (ret) {
+ pr_err("failed to initialize UMC ch%d\n", ch);
+ return ret;
+ }
- ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch2_size / SZ_256M,
- bd->dram_ch2_width);
- if (ret) {
- printf("failed to initialize UMC ch2\n");
- return ret;
+ umc_ch_base += 0x00200000;
}
um_init(um_base);
diff --git a/arch/arm/mach-uniphier/dram/umc-regs.h b/arch/arm/mach-uniphier/dram/umc-regs.h
index a6957a4a51..cc2dd27abf 100644
--- a/arch/arm/mach-uniphier/dram/umc-regs.h
+++ b/arch/arm/mach-uniphier/dram/umc-regs.h
@@ -9,10 +9,7 @@
#ifndef ARCH_UMC_REGS_H
#define ARCH_UMC_REGS_H
-#define UMC_BASE 0x5b800000
-
-/* SSIF registers */
-#define UMC_SSIF_BASE UMC_BASE
+#include <linux/bitops.h>
#define UMC_CPURST 0x00000700
#define UMC_IDSRST 0x0000070C
@@ -48,23 +45,14 @@
#define UMC_CLKEN_SSIF_RC 0x0000C080
#define UMC_CLKEN_SSIF_DST 0x0000C084
-/* CA registers */
-#define UMC_CA_BASE(ch) (UMC_BASE + 0x00001000 + 0x00001000 * (ch))
-
-/* DRAM controller registers */
-#define UMC_DRAMCONT_BASE(ch) (UMC_BASE + 0x00400000 + 0x00200000 * (ch))
-
#define UMC_CMDCTLA 0x00000000
#define UMC_CMDCTLB 0x00000004
-#define UMC_INITCTLA 0x00000008
-#define UMC_INITCTLB 0x0000000C
-#define UMC_INITCTLC 0x00000010
#define UMC_INITSET 0x00000014
+#define UMC_INITSET_INIT1EN BIT(1) /* init without power-on wait */
+#define UMC_INITSET_INIT0EN BIT(0) /* init with power-on wait */
#define UMC_INITSTAT 0x00000018
-#define UMC_DRMMR0 0x0000001C
-#define UMC_DRMMR1 0x00000020
-#define UMC_DRMMR2 0x00000024
-#define UMC_DRMMR3 0x00000028
+#define UMC_INITSTAT_INIT1ST BIT(1) /* init without power-on wait */
+#define UMC_INITSTAT_INIT0ST BIT(0) /* init with power-on wait */
#define UMC_SPCCTLA 0x00000030
#define UMC_SPCCTLB 0x00000034
#define UMC_SPCSETA 0x00000038
@@ -116,30 +104,4 @@
#define UMC_BITPERPIXELMODE_D0 0x010
#define UMC_PAIR1DOFF_D0 0x054
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-static inline void umc_polling(u32 address, u32 expval, u32 mask)
-{
- u32 nmask = ~mask;
- u32 data;
- do {
- data = readl(address) & nmask;
- } while (data != expval);
-}
-
-static inline void umc_dram_init_start(void __iomem *dramcont)
-{
- writel(0x00000002, dramcont + UMC_INITSET);
-}
-
-static inline void umc_dram_init_poll(void __iomem *dramcont)
-{
- while ((readl(dramcont + UMC_INITSTAT) & 0x00000002))
- ;
-}
-
-#endif
-
#endif
diff --git a/arch/arm/mach-uniphier/dram_init.c b/arch/arm/mach-uniphier/dram_init.c
index 32cc448aeb..cffdfc9841 100644
--- a/arch/arm/mach-uniphier/dram_init.c
+++ b/arch/arm/mach-uniphier/dram_init.c
@@ -32,7 +32,7 @@ int dram_init(void)
gd->ram_size = fdt32_to_cpu(*(val + 1));
- debug("DRAM size = %08lx\n", gd->ram_size);
+ debug("DRAM size = %08lx\n", (unsigned long)gd->ram_size);
return 0;
}
@@ -54,6 +54,7 @@ void dram_init_banksize(void)
gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++);
debug("DRAM bank %d: start = %08lx, size = %08lx\n",
- i, gd->bd->bi_dram[i].start, gd->bd->bi_dram[i].size);
+ i, (unsigned long)gd->bd->bi_dram[i].start,
+ (unsigned long)gd->bd->bi_dram[i].size);
}
}
diff --git a/arch/arm/mach-uniphier/init.h b/arch/arm/mach-uniphier/init.h
index 0a47e70dcf..e969fd0c4e 100644
--- a/arch/arm/mach-uniphier/init.h
+++ b/arch/arm/mach-uniphier/init.h
@@ -7,17 +7,21 @@
#ifndef __MACH_INIT_H
#define __MACH_INIT_H
+#include <linux/types.h>
+
+#define UNIPHIER_MAX_NR_DRAM_CH 3
+
+struct uniphier_dram_ch {
+ unsigned long base;
+ unsigned long size;
+ unsigned int width;
+};
+
struct uniphier_board_data {
- unsigned long dram_ch0_base;
- unsigned long dram_ch0_size;
- unsigned long dram_ch0_width;
- unsigned long dram_ch1_base;
- unsigned long dram_ch1_size;
- unsigned long dram_ch1_width;
- unsigned long dram_ch2_base;
- unsigned long dram_ch2_size;
- unsigned long dram_ch2_width;
- unsigned int dram_freq;
+ unsigned int dram_freq;
+ unsigned int dram_nr_ch;
+ bool dram_ddr3plus;
+ struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH];
};
const struct uniphier_board_data *uniphier_get_board_param(void);
diff --git a/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c b/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c
index 9718cc560f..6fdf910895 100644
--- a/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c
+++ b/arch/arm/mach-uniphier/memconf/memconf-ph1-sld3.c
@@ -21,14 +21,14 @@ int ph1_sld3_memconf_init(const struct uniphier_board_data *bd)
tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK);
- switch (bd->dram_ch2_width) {
+ switch (bd->dram_ch[2].width) {
case 16:
tmp |= SG_MEMCONF_CH2_NUM_1;
- size_per_word = bd->dram_ch2_size;
+ size_per_word = bd->dram_ch[2].size;
break;
case 32:
tmp |= SG_MEMCONF_CH2_NUM_2;
- size_per_word = bd->dram_ch2_size >> 1;
+ size_per_word = bd->dram_ch[2].size >> 1;
break;
default:
pr_err("error: unsupported DRAM Ch2 width\n");
diff --git a/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c b/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c
index 9a91fb33ef..c47fe0ae53 100644
--- a/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c
+++ b/arch/arm/mach-uniphier/memconf/memconf-proxstream2.c
@@ -21,14 +21,14 @@ int proxstream2_memconf_init(const struct uniphier_board_data *bd)
tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK);
- switch (bd->dram_ch2_width) {
+ switch (bd->dram_ch[2].width) {
case 16:
tmp |= SG_MEMCONF_CH2_NUM_1;
- size_per_word = bd->dram_ch2_size;
+ size_per_word = bd->dram_ch[2].size;
break;
case 32:
tmp |= SG_MEMCONF_CH2_NUM_2;
- size_per_word = bd->dram_ch2_size >> 1;
+ size_per_word = bd->dram_ch[2].size >> 1;
break;
default:
pr_err("error: unsupported DRAM Ch2 width\n");
diff --git a/arch/arm/mach-uniphier/memconf/memconf.c b/arch/arm/mach-uniphier/memconf/memconf.c
index f2a0eaf3f5..3d4b50456b 100644
--- a/arch/arm/mach-uniphier/memconf/memconf.c
+++ b/arch/arm/mach-uniphier/memconf/memconf.c
@@ -21,14 +21,14 @@ int memconf_init(const struct uniphier_board_data *bd)
tmp &= ~(SG_MEMCONF_CH0_SZ_MASK | SG_MEMCONF_CH0_NUM_MASK);
- switch (bd->dram_ch0_width) {
+ switch (bd->dram_ch[0].width) {
case 16:
tmp |= SG_MEMCONF_CH0_NUM_1;
- size_per_word = bd->dram_ch0_size;
+ size_per_word = bd->dram_ch[0].size;
break;
case 32:
tmp |= SG_MEMCONF_CH0_NUM_2;
- size_per_word = bd->dram_ch0_size >> 1;
+ size_per_word = bd->dram_ch[0].size >> 1;
break;
default:
pr_err("error: unsupported DRAM Ch0 width\n");
@@ -59,14 +59,14 @@ int memconf_init(const struct uniphier_board_data *bd)
tmp &= ~(SG_MEMCONF_CH1_SZ_MASK | SG_MEMCONF_CH1_NUM_MASK);
- switch (bd->dram_ch1_width) {
+ switch (bd->dram_ch[1].width) {
case 16:
tmp |= SG_MEMCONF_CH1_NUM_1;
- size_per_word = bd->dram_ch1_size;
+ size_per_word = bd->dram_ch[1].size;
break;
case 32:
tmp |= SG_MEMCONF_CH1_NUM_2;
- size_per_word = bd->dram_ch1_size >> 1;
+ size_per_word = bd->dram_ch[1].size >> 1;
break;
default:
pr_err("error: unsupported DRAM Ch1 width\n");
@@ -94,7 +94,7 @@ int memconf_init(const struct uniphier_board_data *bd)
return -EINVAL;
}
- if (bd->dram_ch0_base + bd->dram_ch0_size < bd->dram_ch1_base)
+ if (bd->dram_ch[0].base + bd->dram_ch[0].size < bd->dram_ch[1].base)
tmp |= SG_MEMCONF_SPARSEMEM;
else
tmp &= ~SG_MEMCONF_SPARSEMEM;
diff --git a/arch/arm/mach-uniphier/micro-support-card.c b/arch/arm/mach-uniphier/micro-support-card.c
index f777ac1ffe..f7a37e3e4c 100644
--- a/arch/arm/mach-uniphier/micro-support-card.c
+++ b/arch/arm/mach-uniphier/micro-support-card.c
@@ -142,7 +142,8 @@ static void detect_num_flash_banks(void)
memory_bank;
debug("flash bank found: base = 0x%lx, size = 0x%lx\n",
- memory_bank->base, memory_bank->size);
+ (unsigned long)memory_bank->base,
+ (unsigned long)memory_bank->size);
cfi_flash_num_flash_banks++;
}
}
diff --git a/arch/arm/mach-uniphier/sg-regs.h b/arch/arm/mach-uniphier/sg-regs.h
index 678d437fc9..3a535c70b2 100644
--- a/arch/arm/mach-uniphier/sg-regs.h
+++ b/arch/arm/mach-uniphier/sg-regs.h
@@ -105,7 +105,7 @@ static inline void sg_set_pinsel(unsigned pin, unsigned muxval,
unsigned mux_bits, unsigned reg_stride)
{
unsigned shift = pin * mux_bits % 32;
- unsigned reg = SG_PINCTRL_BASE + pin * mux_bits / 32 * reg_stride;
+ unsigned long reg = SG_PINCTRL_BASE + pin * mux_bits / 32 * reg_stride;
u32 mask = (1U << mux_bits) - 1;
u32 tmp;
diff --git a/arch/arm/mach-uniphier/soc-info.h b/arch/arm/mach-uniphier/soc-info.h
index 3cfd1e9d6e..606094c80f 100644
--- a/arch/arm/mach-uniphier/soc-info.h
+++ b/arch/arm/mach-uniphier/soc-info.h
@@ -15,8 +15,8 @@ enum uniphier_soc_id {
SOC_UNIPHIER_PH1_PRO5,
SOC_UNIPHIER_PROXSTREAM2,
SOC_UNIPHIER_PH1_LD6B,
- SOC_UNIPHIER_PH1_SLD11,
- SOC_UNIPHIER_PH1_LD10,
+ SOC_UNIPHIER_PH1_LD11,
+ SOC_UNIPHIER_PH1_LD20,
SOC_UNIPHIER_UNKNOWN,
};
@@ -28,8 +28,8 @@ enum uniphier_soc_id {
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_PRO5) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD6B) + \
- IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_SLD11) + \
- IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD10)
+ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD11) + \
+ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD20)
#define UNIPHIER_MULTI_SOC ((UNIPHIER_NR_ENABLED_SOCS) > 1)
@@ -59,11 +59,11 @@ static inline enum uniphier_soc_id uniphier_get_soc_type(void)
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B)
return SOC_UNIPHIER_PH1_LD6B;
#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD11)
- return SOC_UNIPHIER_PH1_SLD11;
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD11)
+ return SOC_UNIPHIER_PH1_LD11;
#endif
-#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD10)
- return SOC_UNIPHIER_PH1_LD10;
+#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD20)
+ return SOC_UNIPHIER_PH1_LD20;
#endif
return SOC_UNIPHIER_UNKNOWN;
diff --git a/arch/arm/mach-uniphier/soc_info.c b/arch/arm/mach-uniphier/soc_info.c
index fd799ca39a..3cfc183723 100644
--- a/arch/arm/mach-uniphier/soc_info.c
+++ b/arch/arm/mach-uniphier/soc_info.c
@@ -52,14 +52,14 @@ enum uniphier_soc_id uniphier_get_soc_type(void)
ret = SOC_UNIPHIER_PH1_LD6B;
break;
#endif
-#ifdef CONFIG_ARCH_UNIPHIER_PH1_SLD11
+#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD11
case 0x31:
- ret = SOC_UNIPHIER_PH1_SLD11;
+ ret = SOC_UNIPHIER_PH1_LD11;
break;
#endif
-#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD10
+#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD20
case 0x32:
- ret = SOC_UNIPHIER_PH1_LD10;
+ ret = SOC_UNIPHIER_PH1_LD20;
break;
#endif
default:
diff --git a/configs/uniphier_ld4_sld8_defconfig b/configs/uniphier_ld4_sld8_defconfig
index 535f96fb63..4d7afb82c7 100644
--- a/configs/uniphier_ld4_sld8_defconfig
+++ b/configs/uniphier_ld4_sld8_defconfig
@@ -1,8 +1,7 @@
CONFIG_ARM=y
CONFIG_ARCH_UNIPHIER=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_ARCH_UNIPHIER_PH1_LD4=y
-CONFIG_ARCH_UNIPHIER_PH1_SLD8=y
+CONFIG_ARCH_UNIPHIER_LD4_SLD8=y
CONFIG_MICRO_SUPPORT_CARD=y
CONFIG_SYS_TEXT_BASE=0x84000000
CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-ld4-ref"
@@ -13,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_GPIO_UNIPHIER=y
+CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pro4_defconfig b/configs/uniphier_pro4_defconfig
index 2361db6ab5..45ef8837e2 100644
--- a/configs/uniphier_pro4_defconfig
+++ b/configs/uniphier_pro4_defconfig
@@ -12,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_GPIO_UNIPHIER=y
+CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_pro5_defconfig b/configs/uniphier_pro5_defconfig
deleted file mode 100644
index be0d7b5390..0000000000
--- a/configs/uniphier_pro5_defconfig
+++ /dev/null
@@ -1,30 +0,0 @@
-CONFIG_ARM=y
-CONFIG_ARCH_UNIPHIER=y
-CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_ARCH_UNIPHIER_PH1_PRO5=y
-CONFIG_MICRO_SUPPORT_CARD=y
-CONFIG_SYS_TEXT_BASE=0x84000000
-CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-pro5-4kbox"
-CONFIG_HUSH_PARSER=y
-# CONFIG_CMD_XIMG is not set
-# CONFIG_CMD_ENV_EXISTS is not set
-CONFIG_CMD_NAND=y
-CONFIG_CMD_I2C=y
-CONFIG_CMD_USB=y
-# CONFIG_CMD_FPGA is not set
-CONFIG_CMD_TFTPPUT=y
-CONFIG_CMD_PING=y
-CONFIG_CMD_TIME=y
-# CONFIG_CMD_MISC is not set
-CONFIG_NET_RANDOM_ETHADDR=y
-CONFIG_SPL_SIMPLE_BUS=y
-CONFIG_NAND_DENALI=y
-CONFIG_SYS_NAND_DENALI_64BIT=y
-CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
-CONFIG_SPL_NAND_DENALI=y
-CONFIG_PINCTRL=y
-CONFIG_SPL_PINCTRL=y
-CONFIG_UNIPHIER_SERIAL=y
-CONFIG_USB=y
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_STORAGE=y
diff --git a/configs/uniphier_pxs2_ld6b_defconfig b/configs/uniphier_pxs2_ld6b_defconfig
index f8cb794b8f..4a8d70b801 100644
--- a/configs/uniphier_pxs2_ld6b_defconfig
+++ b/configs/uniphier_pxs2_ld6b_defconfig
@@ -1,8 +1,7 @@
CONFIG_ARM=y
CONFIG_ARCH_UNIPHIER=y
CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_ARCH_UNIPHIER_PROXSTREAM2=y
-CONFIG_ARCH_UNIPHIER_PH1_LD6B=y
+CONFIG_ARCH_UNIPHIER_PRO5_PXS2_LD6B=y
CONFIG_MICRO_SUPPORT_CARD=y
CONFIG_SYS_TEXT_BASE=0x84000000
CONFIG_DEFAULT_DEVICE_TREE="uniphier-proxstream2-vodka"
@@ -13,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y
+CONFIG_GPIO_UNIPHIER=y
+CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/configs/uniphier_sld3_defconfig b/configs/uniphier_sld3_defconfig
index e369c45e82..5f0d678c66 100644
--- a/configs/uniphier_sld3_defconfig
+++ b/configs/uniphier_sld3_defconfig
@@ -11,11 +11,14 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set
+CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_GPIO_UNIPHIER=y
+CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8
diff --git a/doc/README.uniphier b/doc/README.uniphier
index bcf0ac3d4b..6c3b0924b2 100644
--- a/doc/README.uniphier
+++ b/doc/README.uniphier
@@ -45,8 +45,8 @@ PH1-Pro4 reference board:
$ make CROSS_COMPILE=arm-linux-gnueabi-
PH1-Pro5 4KBOX Board:
- $ make uniphier_pro5_defconfig
- $ make CROSS_COMPILE=arm-linux-gnueabi-
+ $ make uniphier_pxs2_ld6b_defconfig
+ $ make CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=uniphier-ph1-pro5-4kbox
ProXstream2 Gentil board:
$ make uniphier_pxs2_ld6b_defconfig
@@ -78,6 +78,20 @@ directory, and then run the following command at the U-Boot command line:
=> run nandupdate
+Burn U-Boot images to eMMC
+--------------------------
+
+Write two files to the Boot partition 1 of the eMMC device as follows:
+ - spl/u-boot-spl.bin at the offset address 0x00000000
+ - u-boot.img at the offset address 0x00010000
+
+If a TFTP server is available, the images can be easily updated.
+Just copy the u-boot-spl-dtb.bin and u-boot-dtb.img to the TFTP public
+directory, and then run the following command at the U-Boot command line:
+
+ => run emmcupdate
+
+
UniPhier specific commands
--------------------------
@@ -93,8 +107,10 @@ Supported devices
- UART (on-chip)
- NAND
+ - SD/eMMC
- USB 2.0 (EHCI)
- USB 3.0 (xHCI)
+ - GPIO
- LAN (on-board SMSC9118)
- I2C
- EEPROM (connected to the on-board I2C bus)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 845dc725c5..94fabb9e18 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -76,6 +76,12 @@ config SANDBOX_GPIO_COUNT
of 'anonymous' GPIOs that do not belong to any device or bank.
Select a suitable value depending on your needs.
+config GPIO_UNIPHIER
+ bool "UniPhier GPIO"
+ depends on ARCH_UNIPHIER
+ help
+ Say yes here to support UniPhier GPIOs.
+
config VYBRID_GPIO
bool "Vybrid GPIO driver"
depends on DM
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 845a6d4493..ca8c4879e4 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -43,6 +43,7 @@ oby-$(CONFIG_SX151X) += sx151x.o
obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o
obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o
obj-$(CONFIG_STM32_GPIO) += stm32_gpio.o
+obj-$(CONFIG_GPIO_UNIPHIER) += gpio-uniphier.o
obj-$(CONFIG_ZYNQ_GPIO) += zynq_gpio.o
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o
diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
new file mode 100644
index 0000000000..80bb16ec06
--- /dev/null
+++ b/drivers/gpio/gpio-uniphier.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm/device.h>
+#include <mapmem.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+
+#define UNIPHIER_GPIO_PORTS_PER_BANK 8
+
+#define UNIPHIER_GPIO_REG_DATA 0 /* data */
+#define UNIPHIER_GPIO_REG_DIR 4 /* direction (1:in, 0:out) */
+
+struct uniphier_gpio_priv {
+ void __iomem *base;
+ char bank_name[16];
+};
+
+static void uniphier_gpio_offset_write(struct udevice *dev, unsigned offset,
+ unsigned reg, int value)
+{
+ struct uniphier_gpio_priv *priv = dev_get_priv(dev);
+ u32 tmp;
+
+ tmp = readl(priv->base + reg);
+ if (value)
+ tmp |= BIT(offset);
+ else
+ tmp &= ~BIT(offset);
+ writel(tmp, priv->base + reg);
+}
+
+static int uniphier_gpio_offset_read(struct udevice *dev, unsigned offset,
+ unsigned reg)
+{
+ struct uniphier_gpio_priv *priv = dev_get_priv(dev);
+
+ return !!(readl(priv->base + reg) & BIT(offset));
+}
+
+static int uniphier_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+ uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 1);
+
+ return 0;
+}
+
+static int uniphier_gpio_direction_output(struct udevice *dev, unsigned offset,
+ int value)
+{
+ uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value);
+ uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DIR, 0);
+
+ return 0;
+}
+
+static int uniphier_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+ return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DATA);
+}
+
+static int uniphier_gpio_set_value(struct udevice *dev, unsigned offset,
+ int value)
+{
+ uniphier_gpio_offset_write(dev, offset, UNIPHIER_GPIO_REG_DATA, value);
+
+ return 0;
+}
+
+static int uniphier_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+ return uniphier_gpio_offset_read(dev, offset, UNIPHIER_GPIO_REG_DIR) ?
+ GPIOF_INPUT : GPIOF_OUTPUT;
+}
+
+static const struct dm_gpio_ops uniphier_gpio_ops = {
+ .direction_input = uniphier_gpio_direction_input,
+ .direction_output = uniphier_gpio_direction_output,
+ .get_value = uniphier_gpio_get_value,
+ .set_value = uniphier_gpio_set_value,
+ .get_function = uniphier_gpio_get_function,
+};
+
+static int uniphier_gpio_probe(struct udevice *dev)
+{
+ struct uniphier_gpio_priv *priv = dev_get_priv(dev);
+ struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+ DECLARE_GLOBAL_DATA_PTR;
+ fdt_addr_t addr;
+ fdt_size_t size;
+ unsigned int tmp;
+
+ addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg",
+ &size);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->base = map_sysmem(addr, size);
+ if (!priv->base)
+ return -ENOMEM;
+
+ uc_priv->gpio_count = UNIPHIER_GPIO_PORTS_PER_BANK;
+
+ tmp = (addr & 0xfff);
+
+ /* Unfortunately, there is a register hole at offset 0x90-0x9f. */
+ if (tmp > 0x90)
+ tmp -= 0x10;
+
+ snprintf(priv->bank_name, sizeof(priv->bank_name) - 1,
+ "port%d-", (tmp - 8) / 8);
+
+ uc_priv->bank_name = priv->bank_name;
+
+ return 0;
+}
+
+static int uniphier_gpio_remove(struct udevice *dev)
+{
+ struct uniphier_gpio_priv *priv = dev_get_priv(dev);
+
+ unmap_sysmem(priv->base);
+
+ return 0;
+}
+
+/* .data = the number of GPIO banks */
+static const struct udevice_id uniphier_gpio_match[] = {
+ { .compatible = "socionext,uniphier-gpio" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(uniphier_gpio) = {
+ .name = "uniphier_gpio",
+ .id = UCLASS_GPIO,
+ .of_match = uniphier_gpio_match,
+ .probe = uniphier_gpio_probe,
+ .remove = uniphier_gpio_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_gpio_priv),
+ .ops = &uniphier_gpio_ops,
+};
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index 9d3f7e908f..dc8532fe93 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -43,4 +43,10 @@ config ZYNQ_SDHCI
help
Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform
+config MMC_UNIPHIER
+ bool "UniPhier SD/MMC Host Controller support"
+ depends on ARCH_UNIPHIER
+ help
+ This selects support for the SD/MMC Host Controller on UniPhier SoCs.
+
endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index c9c3e3e938..b85e4bfb77 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
+obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
ifdef CONFIG_SPL_BUILD
diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c
new file mode 100644
index 0000000000..3bc4d942a0
--- /dev/null
+++ b/drivers/mmc/uniphier-sd.c
@@ -0,0 +1,751 @@
+/*
+ * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <fdtdec.h>
+#include <mapmem.h>
+#include <mmc.h>
+#include <dm/device.h>
+#include <linux/compat.h>
+#include <linux/io.h>
+#include <asm/unaligned.h>
+#include <asm/dma-mapping.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define UNIPHIER_SD_CMD 0x000 /* command */
+#define UNIPHIER_SD_CMD_NOSTOP BIT(14) /* No automatic CMD12 issue */
+#define UNIPHIER_SD_CMD_MULTI BIT(13) /* multiple block transfer */
+#define UNIPHIER_SD_CMD_RD BIT(12) /* 1: read, 0: write */
+#define UNIPHIER_SD_CMD_DATA BIT(11) /* data transfer */
+#define UNIPHIER_SD_CMD_APP BIT(6) /* ACMD preceded by CMD55 */
+#define UNIPHIER_SD_CMD_NORMAL (0 << 8)/* auto-detect of resp-type */
+#define UNIPHIER_SD_CMD_RSP_NONE (3 << 8)/* response: none */
+#define UNIPHIER_SD_CMD_RSP_R1 (4 << 8)/* response: R1, R5, R6, R7 */
+#define UNIPHIER_SD_CMD_RSP_R1B (5 << 8)/* response: R1b, R5b */
+#define UNIPHIER_SD_CMD_RSP_R2 (6 << 8)/* response: R2 */
+#define UNIPHIER_SD_CMD_RSP_R3 (7 << 8)/* response: R3, R4 */
+#define UNIPHIER_SD_ARG 0x008 /* command argument */
+#define UNIPHIER_SD_STOP 0x010 /* stop action control */
+#define UNIPHIER_SD_STOP_SEC BIT(8) /* use sector count */
+#define UNIPHIER_SD_STOP_STP BIT(0) /* issue CMD12 */
+#define UNIPHIER_SD_SECCNT 0x014 /* sector counter */
+#define UNIPHIER_SD_RSP10 0x018 /* response[39:8] */
+#define UNIPHIER_SD_RSP32 0x020 /* response[71:40] */
+#define UNIPHIER_SD_RSP54 0x028 /* response[103:72] */
+#define UNIPHIER_SD_RSP76 0x030 /* response[127:104] */
+#define UNIPHIER_SD_INFO1 0x038 /* IRQ status 1 */
+#define UNIPHIER_SD_INFO1_CD BIT(5) /* state of card detect */
+#define UNIPHIER_SD_INFO1_INSERT BIT(4) /* card inserted */
+#define UNIPHIER_SD_INFO1_REMOVE BIT(3) /* card removed */
+#define UNIPHIER_SD_INFO1_CMP BIT(2) /* data complete */
+#define UNIPHIER_SD_INFO1_RSP BIT(0) /* response complete */
+#define UNIPHIER_SD_INFO2 0x03c /* IRQ status 2 */
+#define UNIPHIER_SD_INFO2_ERR_ILA BIT(15) /* illegal access err */
+#define UNIPHIER_SD_INFO2_CBSY BIT(14) /* command busy */
+#define UNIPHIER_SD_INFO2_BWE BIT(9) /* write buffer ready */
+#define UNIPHIER_SD_INFO2_BRE BIT(8) /* read buffer ready */
+#define UNIPHIER_SD_INFO2_DAT0 BIT(7) /* SDDAT0 */
+#define UNIPHIER_SD_INFO2_ERR_RTO BIT(6) /* response time out */
+#define UNIPHIER_SD_INFO2_ERR_ILR BIT(5) /* illegal read err */
+#define UNIPHIER_SD_INFO2_ERR_ILW BIT(4) /* illegal write err */
+#define UNIPHIER_SD_INFO2_ERR_TO BIT(3) /* time out error */
+#define UNIPHIER_SD_INFO2_ERR_END BIT(2) /* END bit error */
+#define UNIPHIER_SD_INFO2_ERR_CRC BIT(1) /* CRC error */
+#define UNIPHIER_SD_INFO2_ERR_IDX BIT(0) /* cmd index error */
+#define UNIPHIER_SD_INFO1_MASK 0x040
+#define UNIPHIER_SD_INFO2_MASK 0x044
+#define UNIPHIER_SD_CLKCTL 0x048 /* clock divisor */
+#define UNIPHIER_SD_CLKCTL_DIV_MASK 0x104ff
+#define UNIPHIER_SD_CLKCTL_DIV1024 BIT(16) /* SDCLK = CLK / 1024 */
+#define UNIPHIER_SD_CLKCTL_DIV512 BIT(7) /* SDCLK = CLK / 512 */
+#define UNIPHIER_SD_CLKCTL_DIV256 BIT(6) /* SDCLK = CLK / 256 */
+#define UNIPHIER_SD_CLKCTL_DIV128 BIT(5) /* SDCLK = CLK / 128 */
+#define UNIPHIER_SD_CLKCTL_DIV64 BIT(4) /* SDCLK = CLK / 64 */
+#define UNIPHIER_SD_CLKCTL_DIV32 BIT(3) /* SDCLK = CLK / 32 */
+#define UNIPHIER_SD_CLKCTL_DIV16 BIT(2) /* SDCLK = CLK / 16 */
+#define UNIPHIER_SD_CLKCTL_DIV8 BIT(1) /* SDCLK = CLK / 8 */
+#define UNIPHIER_SD_CLKCTL_DIV4 BIT(0) /* SDCLK = CLK / 4 */
+#define UNIPHIER_SD_CLKCTL_DIV2 0 /* SDCLK = CLK / 2 */
+#define UNIPHIER_SD_CLKCTL_DIV1 BIT(10) /* SDCLK = CLK */
+#define UNIPHIER_SD_CLKCTL_OFFEN BIT(9) /* stop SDCLK when unused */
+#define UNIPHIER_SD_CLKCTL_SCLKEN BIT(8) /* SDCLK output enable */
+#define UNIPHIER_SD_SIZE 0x04c /* block size */
+#define UNIPHIER_SD_OPTION 0x050
+#define UNIPHIER_SD_OPTION_WIDTH_MASK (5 << 13)
+#define UNIPHIER_SD_OPTION_WIDTH_1 (4 << 13)
+#define UNIPHIER_SD_OPTION_WIDTH_4 (0 << 13)
+#define UNIPHIER_SD_OPTION_WIDTH_8 (1 << 13)
+#define UNIPHIER_SD_BUF 0x060 /* read/write buffer */
+#define UNIPHIER_SD_EXTMODE 0x1b0
+#define UNIPHIER_SD_EXTMODE_DMA_EN BIT(1) /* transfer 1: DMA, 0: pio */
+#define UNIPHIER_SD_SOFT_RST 0x1c0
+#define UNIPHIER_SD_SOFT_RST_RSTX BIT(0) /* reset deassert */
+#define UNIPHIER_SD_VERSION 0x1c4 /* version register */
+#define UNIPHIER_SD_VERSION_IP 0xff /* IP version */
+#define UNIPHIER_SD_HOST_MODE 0x1c8
+#define UNIPHIER_SD_IF_MODE 0x1cc
+#define UNIPHIER_SD_IF_MODE_DDR BIT(0) /* DDR mode */
+#define UNIPHIER_SD_VOLT 0x1e4 /* voltage switch */
+#define UNIPHIER_SD_VOLT_MASK (3 << 0)
+#define UNIPHIER_SD_VOLT_OFF (0 << 0)
+#define UNIPHIER_SD_VOLT_330 (1 << 0)/* 3.3V signal */
+#define UNIPHIER_SD_VOLT_180 (2 << 0)/* 1.8V signal */
+#define UNIPHIER_SD_DMA_MODE 0x410
+#define UNIPHIER_SD_DMA_MODE_DIR_RD BIT(16) /* 1: from device, 0: to dev */
+#define UNIPHIER_SD_DMA_MODE_ADDR_INC BIT(0) /* 1: address inc, 0: fixed */
+#define UNIPHIER_SD_DMA_CTL 0x414
+#define UNIPHIER_SD_DMA_CTL_START BIT(0) /* start DMA (auto cleared) */
+#define UNIPHIER_SD_DMA_RST 0x418
+#define UNIPHIER_SD_DMA_RST_RD BIT(9)
+#define UNIPHIER_SD_DMA_RST_WR BIT(8)
+#define UNIPHIER_SD_DMA_INFO1 0x420
+#define UNIPHIER_SD_DMA_INFO1_END_RD2 BIT(20) /* DMA from device is complete*/
+#define UNIPHIER_SD_DMA_INFO1_END_RD BIT(17) /* Don't use! Hardware bug */
+#define UNIPHIER_SD_DMA_INFO1_END_WR BIT(16) /* DMA to device is complete */
+#define UNIPHIER_SD_DMA_INFO1_MASK 0x424
+#define UNIPHIER_SD_DMA_INFO2 0x428
+#define UNIPHIER_SD_DMA_INFO2_ERR_RD BIT(17)
+#define UNIPHIER_SD_DMA_INFO2_ERR_WR BIT(16)
+#define UNIPHIER_SD_DMA_INFO2_MASK 0x42c
+#define UNIPHIER_SD_DMA_ADDR_L 0x440
+#define UNIPHIER_SD_DMA_ADDR_H 0x444
+
+/* alignment required by the DMA engine of this controller */
+#define UNIPHIER_SD_DMA_MINALIGN 0x10
+
+struct uniphier_sd_priv {
+ struct mmc_config cfg;
+ struct mmc *mmc;
+ struct udevice *dev;
+ void __iomem *regbase;
+ unsigned long mclk;
+ unsigned int version;
+ u32 caps;
+#define UNIPHIER_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */
+#define UNIPHIER_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */
+#define UNIPHIER_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */
+};
+
+static dma_addr_t __dma_map_single(void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ unsigned long addr = (unsigned long)ptr;
+
+ if (dir == DMA_FROM_DEVICE)
+ invalidate_dcache_range(addr, addr + size);
+ else
+ flush_dcache_range(addr, addr + size);
+
+ return addr;
+}
+
+static void __dma_unmap_single(dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ if (dir != DMA_TO_DEVICE)
+ invalidate_dcache_range(addr, addr + size);
+}
+
+static int uniphier_sd_check_error(struct uniphier_sd_priv *priv)
+{
+ u32 info2 = readl(priv->regbase + UNIPHIER_SD_INFO2);
+
+ if (info2 & UNIPHIER_SD_INFO2_ERR_RTO) {
+ /*
+ * TIMEOUT must be returned for unsupported command. Do not
+ * display error log since this might be a part of sequence to
+ * distinguish between SD and MMC.
+ */
+ return TIMEOUT;
+ }
+
+ if (info2 & UNIPHIER_SD_INFO2_ERR_TO) {
+ dev_err(priv->dev, "timeout error\n");
+ return -ETIMEDOUT;
+ }
+
+ if (info2 & (UNIPHIER_SD_INFO2_ERR_END | UNIPHIER_SD_INFO2_ERR_CRC |
+ UNIPHIER_SD_INFO2_ERR_IDX)) {
+ dev_err(priv->dev, "communication out of sync\n");
+ return -EILSEQ;
+ }
+
+ if (info2 & (UNIPHIER_SD_INFO2_ERR_ILA | UNIPHIER_SD_INFO2_ERR_ILR |
+ UNIPHIER_SD_INFO2_ERR_ILW)) {
+ dev_err(priv->dev, "illegal access\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_wait_for_irq(struct uniphier_sd_priv *priv,
+ unsigned int reg, u32 flag)
+{
+ long wait = 1000000;
+ int ret;
+
+ while (!(readl(priv->regbase + reg) & flag)) {
+ if (wait-- < 0) {
+ dev_err(priv->dev, "timeout\n");
+ return -ETIMEDOUT;
+ }
+
+ ret = uniphier_sd_check_error(priv);
+ if (ret)
+ return ret;
+
+ udelay(1);
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_pio_read_one_block(struct mmc *mmc, u32 **pbuf,
+ uint blocksize)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+ int i, ret;
+
+ /* wait until the buffer is filled with data */
+ ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2,
+ UNIPHIER_SD_INFO2_BRE);
+ if (ret)
+ return ret;
+
+ /*
+ * Clear the status flag _before_ read the buffer out because
+ * UNIPHIER_SD_INFO2_BRE is edge-triggered, not level-triggered.
+ */
+ writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+ if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
+ for (i = 0; i < blocksize / 4; i++)
+ *(*pbuf)++ = readl(priv->regbase + UNIPHIER_SD_BUF);
+ } else {
+ for (i = 0; i < blocksize / 4; i++)
+ put_unaligned(readl(priv->regbase + UNIPHIER_SD_BUF),
+ (*pbuf)++);
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_pio_write_one_block(struct mmc *mmc, const u32 **pbuf,
+ uint blocksize)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+ int i, ret;
+
+ /* wait until the buffer becomes empty */
+ ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO2,
+ UNIPHIER_SD_INFO2_BWE);
+ if (ret)
+ return ret;
+
+ writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+ if (likely(IS_ALIGNED((unsigned long)*pbuf, 4))) {
+ for (i = 0; i < blocksize / 4; i++)
+ writel(*(*pbuf)++, priv->regbase + UNIPHIER_SD_BUF);
+ } else {
+ for (i = 0; i < blocksize / 4; i++)
+ writel(get_unaligned((*pbuf)++),
+ priv->regbase + UNIPHIER_SD_BUF);
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_pio_xfer(struct mmc *mmc, struct mmc_data *data)
+{
+ u32 *dest = (u32 *)data->dest;
+ const u32 *src = (const u32 *)data->src;
+ int i, ret;
+
+ for (i = 0; i < data->blocks; i++) {
+ if (data->flags & MMC_DATA_READ)
+ ret = uniphier_sd_pio_read_one_block(mmc, &dest,
+ data->blocksize);
+ else
+ ret = uniphier_sd_pio_write_one_block(mmc, &src,
+ data->blocksize);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void uniphier_sd_dma_start(struct uniphier_sd_priv *priv,
+ dma_addr_t dma_addr)
+{
+ u32 tmp;
+
+ writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO1);
+ writel(0, priv->regbase + UNIPHIER_SD_DMA_INFO2);
+
+ /* enable DMA */
+ tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+ tmp |= UNIPHIER_SD_EXTMODE_DMA_EN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+
+ writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_L);
+
+ /* suppress the warning "right shift count >= width of type" */
+ dma_addr >>= min_t(int, 32, 8 * sizeof(dma_addr));
+
+ writel(dma_addr & U32_MAX, priv->regbase + UNIPHIER_SD_DMA_ADDR_H);
+
+ writel(UNIPHIER_SD_DMA_CTL_START, priv->regbase + UNIPHIER_SD_DMA_CTL);
+}
+
+static int uniphier_sd_dma_wait_for_irq(struct uniphier_sd_priv *priv, u32 flag,
+ unsigned int blocks)
+{
+ long wait = 1000000 + 10 * blocks;
+
+ while (!(readl(priv->regbase + UNIPHIER_SD_DMA_INFO1) & flag)) {
+ if (wait-- < 0) {
+ dev_err(priv->dev, "timeout during DMA\n");
+ return -ETIMEDOUT;
+ }
+
+ udelay(10);
+ }
+
+ if (readl(priv->regbase + UNIPHIER_SD_DMA_INFO2)) {
+ dev_err(priv->dev, "error during DMA\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_dma_xfer(struct mmc *mmc, struct mmc_data *data)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+ size_t len = data->blocks * data->blocksize;
+ void *buf;
+ enum dma_data_direction dir;
+ dma_addr_t dma_addr;
+ u32 poll_flag, tmp;
+ int ret;
+
+ tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+
+ if (data->flags & MMC_DATA_READ) {
+ buf = data->dest;
+ dir = DMA_FROM_DEVICE;
+ poll_flag = UNIPHIER_SD_DMA_INFO1_END_RD2;
+ tmp |= UNIPHIER_SD_DMA_MODE_DIR_RD;
+ } else {
+ buf = (void *)data->src;
+ dir = DMA_TO_DEVICE;
+ poll_flag = UNIPHIER_SD_DMA_INFO1_END_WR;
+ tmp &= ~UNIPHIER_SD_DMA_MODE_DIR_RD;
+ }
+
+ writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+
+ dma_addr = __dma_map_single(buf, len, dir);
+
+ uniphier_sd_dma_start(priv, dma_addr);
+
+ ret = uniphier_sd_dma_wait_for_irq(priv, poll_flag, data->blocks);
+
+ __dma_unmap_single(dma_addr, len, dir);
+
+ return ret;
+}
+
+/* check if the address is DMA'able */
+static bool uniphier_sd_addr_is_dmaable(unsigned long addr)
+{
+ if (!IS_ALIGNED(addr, UNIPHIER_SD_DMA_MINALIGN))
+ return false;
+
+#if defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARM64) && \
+ defined(CONFIG_SPL_BUILD)
+ /*
+ * For UniPhier ARMv7 SoCs, the stack is allocated in the locked ways
+ * of L2, which is unreachable from the DMA engine.
+ */
+ if (addr < CONFIG_SPL_STACK)
+ return false;
+#endif
+
+ return true;
+}
+
+static int uniphier_sd_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+ int ret;
+ u32 tmp;
+
+ if (readl(priv->regbase + UNIPHIER_SD_INFO2) & UNIPHIER_SD_INFO2_CBSY) {
+ dev_err(priv->dev, "command busy\n");
+ return -EBUSY;
+ }
+
+ /* clear all status flags */
+ writel(0, priv->regbase + UNIPHIER_SD_INFO1);
+ writel(0, priv->regbase + UNIPHIER_SD_INFO2);
+
+ /* disable DMA once */
+ tmp = readl(priv->regbase + UNIPHIER_SD_EXTMODE);
+ tmp &= ~UNIPHIER_SD_EXTMODE_DMA_EN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_EXTMODE);
+
+ writel(cmd->cmdarg, priv->regbase + UNIPHIER_SD_ARG);
+
+ tmp = cmd->cmdidx;
+
+ if (data) {
+ writel(data->blocksize, priv->regbase + UNIPHIER_SD_SIZE);
+ writel(data->blocks, priv->regbase + UNIPHIER_SD_SECCNT);
+
+ /* Do not send CMD12 automatically */
+ tmp |= UNIPHIER_SD_CMD_NOSTOP | UNIPHIER_SD_CMD_DATA;
+
+ if (data->blocks > 1)
+ tmp |= UNIPHIER_SD_CMD_MULTI;
+
+ if (data->flags & MMC_DATA_READ)
+ tmp |= UNIPHIER_SD_CMD_RD;
+ }
+
+ /*
+ * Do not use the response type auto-detection on this hardware.
+ * CMD8, for example, has different response types on SD and eMMC,
+ * while this controller always assumes the response type for SD.
+ * Set the response type manually.
+ */
+ switch (cmd->resp_type) {
+ case MMC_RSP_NONE:
+ tmp |= UNIPHIER_SD_CMD_RSP_NONE;
+ break;
+ case MMC_RSP_R1:
+ tmp |= UNIPHIER_SD_CMD_RSP_R1;
+ break;
+ case MMC_RSP_R1b:
+ tmp |= UNIPHIER_SD_CMD_RSP_R1B;
+ break;
+ case MMC_RSP_R2:
+ tmp |= UNIPHIER_SD_CMD_RSP_R2;
+ break;
+ case MMC_RSP_R3:
+ tmp |= UNIPHIER_SD_CMD_RSP_R3;
+ break;
+ default:
+ dev_err(priv->dev, "unknown response type\n");
+ return -EINVAL;
+ }
+
+ dev_dbg(priv->dev, "sending CMD%d (SD_CMD=%08x, SD_ARG=%08x)\n",
+ cmd->cmdidx, tmp, cmd->cmdarg);
+ writel(tmp, priv->regbase + UNIPHIER_SD_CMD);
+
+ ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1,
+ UNIPHIER_SD_INFO1_RSP);
+ if (ret)
+ return ret;
+
+ if (cmd->resp_type & MMC_RSP_136) {
+ u32 rsp_127_104 = readl(priv->regbase + UNIPHIER_SD_RSP76);
+ u32 rsp_103_72 = readl(priv->regbase + UNIPHIER_SD_RSP54);
+ u32 rsp_71_40 = readl(priv->regbase + UNIPHIER_SD_RSP32);
+ u32 rsp_39_8 = readl(priv->regbase + UNIPHIER_SD_RSP10);
+
+ cmd->response[0] = (rsp_127_104 & 0xffffff) << 8 |
+ (rsp_103_72 & 0xff);
+ cmd->response[1] = (rsp_103_72 & 0xffffff) << 8 |
+ (rsp_71_40 & 0xff);
+ cmd->response[2] = (rsp_71_40 & 0xffffff) << 8 |
+ (rsp_39_8 & 0xff);
+ cmd->response[3] = (rsp_39_8 & 0xffffff) << 8;
+ } else {
+ /* bit 39-8 */
+ cmd->response[0] = readl(priv->regbase + UNIPHIER_SD_RSP10);
+ }
+
+ if (data) {
+ /* use DMA if the HW supports it and the buffer is aligned */
+ if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL &&
+ uniphier_sd_addr_is_dmaable((long)data->src))
+ ret = uniphier_sd_dma_xfer(mmc, data);
+ else
+ ret = uniphier_sd_pio_xfer(mmc, data);
+
+ ret = uniphier_sd_wait_for_irq(priv, UNIPHIER_SD_INFO1,
+ UNIPHIER_SD_INFO1_CMP);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static void uniphier_sd_set_bus_width(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ u32 val, tmp;
+
+ switch (mmc->bus_width) {
+ case 1:
+ val = UNIPHIER_SD_OPTION_WIDTH_1;
+ break;
+ case 4:
+ val = UNIPHIER_SD_OPTION_WIDTH_4;
+ break;
+ case 8:
+ val = UNIPHIER_SD_OPTION_WIDTH_8;
+ break;
+ default:
+ BUG();
+ break;
+ }
+
+ tmp = readl(priv->regbase + UNIPHIER_SD_OPTION);
+ tmp &= ~UNIPHIER_SD_OPTION_WIDTH_MASK;
+ tmp |= val;
+ writel(tmp, priv->regbase + UNIPHIER_SD_OPTION);
+}
+
+static void uniphier_sd_set_ddr_mode(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ u32 tmp;
+
+ tmp = readl(priv->regbase + UNIPHIER_SD_IF_MODE);
+ if (mmc->ddr_mode)
+ tmp |= UNIPHIER_SD_IF_MODE_DDR;
+ else
+ tmp &= ~UNIPHIER_SD_IF_MODE_DDR;
+ writel(tmp, priv->regbase + UNIPHIER_SD_IF_MODE);
+}
+
+static void uniphier_sd_set_clk_rate(struct uniphier_sd_priv *priv,
+ struct mmc *mmc)
+{
+ unsigned int divisor;
+ u32 val, tmp;
+
+ if (!mmc->clock)
+ return;
+
+ divisor = DIV_ROUND_UP(priv->mclk, mmc->clock);
+
+ if (divisor <= 1)
+ val = UNIPHIER_SD_CLKCTL_DIV1;
+ else if (divisor <= 2)
+ val = UNIPHIER_SD_CLKCTL_DIV2;
+ else if (divisor <= 4)
+ val = UNIPHIER_SD_CLKCTL_DIV4;
+ else if (divisor <= 8)
+ val = UNIPHIER_SD_CLKCTL_DIV8;
+ else if (divisor <= 16)
+ val = UNIPHIER_SD_CLKCTL_DIV16;
+ else if (divisor <= 32)
+ val = UNIPHIER_SD_CLKCTL_DIV32;
+ else if (divisor <= 64)
+ val = UNIPHIER_SD_CLKCTL_DIV64;
+ else if (divisor <= 128)
+ val = UNIPHIER_SD_CLKCTL_DIV128;
+ else if (divisor <= 256)
+ val = UNIPHIER_SD_CLKCTL_DIV256;
+ else if (divisor <= 512 || !(priv->caps & UNIPHIER_SD_CAP_DIV1024))
+ val = UNIPHIER_SD_CLKCTL_DIV512;
+ else
+ val = UNIPHIER_SD_CLKCTL_DIV1024;
+
+ tmp = readl(priv->regbase + UNIPHIER_SD_CLKCTL);
+
+ /* stop the clock before changing its rate to avoid a glitch signal */
+ tmp &= ~UNIPHIER_SD_CLKCTL_SCLKEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+
+ tmp &= ~UNIPHIER_SD_CLKCTL_DIV_MASK;
+ tmp |= val | UNIPHIER_SD_CLKCTL_OFFEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+
+ tmp |= UNIPHIER_SD_CLKCTL_SCLKEN;
+ writel(tmp, priv->regbase + UNIPHIER_SD_CLKCTL);
+}
+
+static void uniphier_sd_set_ios(struct mmc *mmc)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+
+ dev_dbg(priv->dev, "clock %uHz, DDRmode %d, width %u\n",
+ mmc->clock, mmc->ddr_mode, mmc->bus_width);
+
+ uniphier_sd_set_bus_width(priv, mmc);
+ uniphier_sd_set_ddr_mode(priv, mmc);
+ uniphier_sd_set_clk_rate(priv, mmc);
+
+ udelay(1000);
+}
+
+static int uniphier_sd_init(struct mmc *mmc)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+ u32 tmp;
+
+ /* soft reset of the host */
+ tmp = readl(priv->regbase + UNIPHIER_SD_SOFT_RST);
+ tmp &= ~UNIPHIER_SD_SOFT_RST_RSTX;
+ writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+ tmp |= UNIPHIER_SD_SOFT_RST_RSTX;
+ writel(tmp, priv->regbase + UNIPHIER_SD_SOFT_RST);
+
+ /* FIXME: implement eMMC hw_reset */
+
+ writel(UNIPHIER_SD_STOP_SEC, priv->regbase + UNIPHIER_SD_STOP);
+
+ /*
+ * Connected to 32bit AXI.
+ * This register dropped backward compatibility at version 0x10.
+ * Write an appropriate value depending on the IP version.
+ */
+ writel(priv->version >= 0x10 ? 0x00000101 : 0x00000000,
+ priv->regbase + UNIPHIER_SD_HOST_MODE);
+
+ if (priv->caps & UNIPHIER_SD_CAP_DMA_INTERNAL) {
+ tmp = readl(priv->regbase + UNIPHIER_SD_DMA_MODE);
+ tmp |= UNIPHIER_SD_DMA_MODE_ADDR_INC;
+ writel(tmp, priv->regbase + UNIPHIER_SD_DMA_MODE);
+ }
+
+ return 0;
+}
+
+static int uniphier_sd_getcd(struct mmc *mmc)
+{
+ struct uniphier_sd_priv *priv = mmc->priv;
+
+ if (priv->caps & UNIPHIER_SD_CAP_NONREMOVABLE)
+ return 1;
+
+ return !!(readl(priv->regbase + UNIPHIER_SD_INFO1) &
+ UNIPHIER_SD_INFO1_CD);
+}
+
+static const struct mmc_ops uniphier_sd_ops = {
+ .send_cmd = uniphier_sd_send_cmd,
+ .set_ios = uniphier_sd_set_ios,
+ .init = uniphier_sd_init,
+ .getcd = uniphier_sd_getcd,
+};
+
+int uniphier_sd_probe(struct udevice *dev)
+{
+ struct uniphier_sd_priv *priv = dev_get_priv(dev);
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ fdt_addr_t base;
+ fdt_size_t size;
+ struct udevice *clk_dev;
+ int clk_id;
+ int ret;
+
+ priv->dev = dev;
+
+ base = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+ priv->regbase = map_sysmem(base, size);
+ if (!priv->regbase)
+ return -ENOMEM;
+
+ clk_id = clk_get_by_index(dev, 0, &clk_dev);
+ if (clk_id < 0) {
+ dev_err(dev, "failed to get host clock\n");
+ return clk_id;
+ }
+
+ /* set to max rate */
+ priv->mclk = clk_set_periph_rate(clk_dev, clk_id, ULONG_MAX);
+ if (IS_ERR_VALUE(priv->mclk)) {
+ dev_err(dev, "failed to set rate for host clock\n");
+ return priv->mclk;
+ }
+
+ ret = clk_enable(clk_dev, clk_id);
+ if (ret) {
+ dev_err(dev, "failed to enable host clock\n");
+ return ret;
+ }
+
+ priv->cfg.name = dev->name;
+ priv->cfg.ops = &uniphier_sd_ops;
+ priv->cfg.host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+ switch (fdtdec_get_int(gd->fdt_blob, dev->of_offset, "bus-width", 1)) {
+ case 8:
+ priv->cfg.host_caps |= MMC_MODE_8BIT;
+ break;
+ case 4:
+ priv->cfg.host_caps |= MMC_MODE_4BIT;
+ break;
+ case 1:
+ break;
+ default:
+ dev_err(dev, "Invalid \"bus-width\" value\n");
+ return -EINVAL;
+ }
+
+ if (fdt_get_property(gd->fdt_blob, dev->of_offset, "non-removable",
+ NULL))
+ priv->caps |= UNIPHIER_SD_CAP_NONREMOVABLE;
+
+ priv->version = readl(priv->regbase + UNIPHIER_SD_VERSION) &
+ UNIPHIER_SD_VERSION_IP;
+ dev_dbg(dev, "version %x\n", priv->version);
+ if (priv->version >= 0x10) {
+ priv->caps |= UNIPHIER_SD_CAP_DMA_INTERNAL;
+ priv->caps |= UNIPHIER_SD_CAP_DIV1024;
+ }
+
+ priv->cfg.voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
+ priv->cfg.f_min = priv->mclk /
+ (priv->caps & UNIPHIER_SD_CAP_DIV1024 ? 1024 : 512);
+ priv->cfg.f_max = priv->mclk;
+ priv->cfg.b_max = U32_MAX; /* max value of UNIPHIER_SD_SECCNT */
+
+ priv->mmc = mmc_create(&priv->cfg, priv);
+ if (!priv->mmc)
+ return -EIO;
+
+ upriv->mmc = priv->mmc;
+
+ return 0;
+}
+
+int uniphier_sd_remove(struct udevice *dev)
+{
+ struct uniphier_sd_priv *priv = dev_get_priv(dev);
+
+ unmap_sysmem(priv->regbase);
+ mmc_destroy(priv->mmc);
+
+ return 0;
+}
+
+static const struct udevice_id uniphier_sd_match[] = {
+ { .compatible = "socionext,uniphier-sdhc" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(uniphier_mmc) = {
+ .name = "uniphier-mmc",
+ .id = UCLASS_MMC,
+ .of_match = uniphier_sd_match,
+ .probe = uniphier_sd_probe,
+ .remove = uniphier_sd_remove,
+ .priv_auto_alloc_size = sizeof(struct uniphier_sd_priv),
+};
diff --git a/include/configs/uniphier.h b/include/configs/uniphier.h
index fcec0c0ae2..b1c8ccb7b9 100644
--- a/include/configs/uniphier.h
+++ b/include/configs/uniphier.h
@@ -99,16 +99,16 @@
#define CONFIG_CONS_INDEX 1
-/*
- * For NAND booting the environment is embedded in the U-Boot image. Please take
- * look at the file board/amcc/canyonlands/u-boot-nand.lds for details.
- */
+/* #define CONFIG_ENV_IS_NOWHERE */
/* #define CONFIG_ENV_IS_IN_NAND */
-#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_IS_IN_MMC
+#define CONFIG_ENV_OFFSET 0x80000
#define CONFIG_ENV_SIZE 0x2000
-#define CONFIG_ENV_OFFSET 0x0
/* #define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) */
+#define CONFIG_SYS_MMC_ENV_DEV 0
+#define CONFIG_SYS_MMC_ENV_PART 1
+
/* Time clock 1MHz */
#define CONFIG_SYS_TIMER_RATE 1000000
@@ -146,6 +146,11 @@
#define CONFIG_FAT_WRITE
#define CONFIG_DOS_PARTITION
+/* SD/MMC */
+#define CONFIG_CMD_MMC
+#define CONFIG_SUPPORT_EMMC_BOOT
+#define CONFIG_GENERIC_MMC
+
/* memtest works on */
#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x01000000)
@@ -228,6 +233,13 @@
"netdev=eth0\0" \
"verify=n\0" \
"nor_base=0x42000000\0" \
+ "emmcupdate=mmcsetn &&" \
+ "mmc partconf $mmc_first_dev 0 1 1 &&" \
+ "mmc erase 0 800 &&" \
+ "tftpboot u-boot-spl.bin &&" \
+ "mmc write $loadaddr 0 80 &&" \
+ "tftpboot u-boot.img &&" \
+ "mmc write $loadaddr 80 780\0" \
"nandupdate=nand erase 0 0x00100000 &&" \
"tftpboot u-boot-spl.bin &&" \
"nand write $loadaddr 0 0x00010000 &&" \
@@ -259,6 +271,7 @@
#define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT
+#define CONFIG_SPL_MMC_SUPPORT
#define CONFIG_SPL_LIBCOMMON_SUPPORT /* for mem_malloc_init */
#define CONFIG_SPL_LIBGENERIC_SUPPORT
@@ -266,6 +279,7 @@
#define CONFIG_SPL_BOARD_INIT
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x10000
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x80
#define CONFIG_SPL_MAX_FOOTPRINT 0x10000