Merge branch 'master' of git://git.denx.de/u-boot-uniphier

This commit is contained in:
Tom Rini 2016-02-29 10:50:01 -05:00
commit 9902c113ad
67 changed files with 2957 additions and 838 deletions

View File

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

View File

@ -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 {

View File

@ -51,6 +51,10 @@
status = "okay";
};
&sd {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

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

View File

@ -53,6 +53,10 @@
status = "okay";
};
&sd {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

@ -69,6 +69,10 @@
status = "okay";
};
&sd {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

@ -54,6 +54,14 @@
status = "okay";
};
&sd {
status = "okay";
};
&sd1 {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

@ -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;
};

View File

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

View File

@ -47,6 +47,14 @@
status = "okay";
};
&emmc {
status = "okay";
};
&sd {
status = "okay";
};
/* for U-Boot only */
/ {
soc {

View File

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

View File

@ -52,6 +52,10 @@
status = "okay";
};
&sd {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

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

View File

@ -51,6 +51,10 @@
status = "okay";
};
&sd {
status = "okay";
};
&usb0 {
status = "okay";
};

View File

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

View File

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

View File

@ -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;
};

View File

@ -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;
};

View File

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

View File

@ -1,2 +1,4 @@
#ifndef CONFIG_ARCH_UNIPHIER
#include <asm/arch/gpio.h>
#endif
#include <asm-generic/gpio.h>

View File

@ -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"

View File

@ -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/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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;
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]);
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(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))
;

View File

@ -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;
}

View File

@ -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;
}

View File

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

View File

@ -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);
enum dram_freq freq_e;
enum dram_size size_e;
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);
if (!ddr3plus) {
pr_err("DDR3 standard is not supported\n");
return -EINVAL;
}
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);
if (freq == 1333) {
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);
} else if (freq == 1600) {
if (size == 1)
writel(0x002B0617, dramcont + UMC_SPCCTLA);
else if (size == 2)
writel(0x003F0617, dramcont + UMC_SPCCTLA);
writel(0x00ff0008, dramcont + UMC_SPCCTLB);
writel(0x000c00ae, dramcont + UMC_RDATACTL_D0);
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(0x04060806, dramcont + UMC_WDATACTL_D0);
writel(0x04a02000, dramcont + UMC_DATASET);
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(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);
void __iomem *phy_base = dc_base + 0x00001000;
int ret;
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
umc_dram_init_poll(dramcont0);
umc_dram_init_poll(dramcont1);
writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
cpu_relax();
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
writel(0x00000101, dc_base + UMC_DIOCTLA);
ph1_ld4_ddrphy_init(phy0_0, freq, size_ch0);
ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
if (ret)
return ret;
ddrphy_prepare_training(phy0_0, 0);
ddrphy_training(phy0_0);
ddrphy_prepare_training(phy_base, umc_get_rank(ch));
ret = ddrphy_training(phy_base);
if (ret)
return ret;
writel(0x00000101, dramcont1 + UMC_DIOCTLA);
return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
ph1_ld4_ddrphy_init(phy1_0, freq, size_ch1);
int ph1_ld4_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;
ddrphy_prepare_training(phy1_0, 1);
ddrphy_training(phy1_0);
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;
}
umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
ca_base += 0x00001000;
dc_base += 0x00200000;
}
umc_start_ssif(ssif_base);
return 0;
}
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;
}
}

View File

@ -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;
switch (size / (width / 16)) {
case SZ_128M:
dram_size = DRAM_SZ_128M;
break;
case SZ_256M:
dram_size = DRAM_SZ_256M;
break;
case SZ_512M:
dram_size = DRAM_SZ_512M;
break;
default:
printf("unsupported DRAM size\n");
if (freq != 1600) {
pr_err("Unsupported DDR frequency %d MHz\n", freq);
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);
if (ddr3plus) {
pr_err("DDR3+ is not supported\n");
return -EINVAL;
}
switch (size) {
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 (per 16bit)\n", size);
return -EINVAL;
}
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;
void __iomem *phy_base = dc_base + 0x00001000;
int nr_phy = width / 16;
int phy, ret;
if (bd->dram_freq != 1600) {
pr_err("Unsupported DDR configuration\n");
return -EINVAL;
writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
cpu_relax();
for (phy = 0; phy < nr_phy; phy++) {
writel(0x00000100 | ((1 << (phy + 1)) - 1),
dc_base + UMC_DIOCTLA);
ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
if (ret)
return ret;
ddrphy_prepare_training(phy_base, phy);
ret = ddrphy_training(phy_base);
if (ret)
return ret;
phy_base += 0x00001000;
}
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
umc_dram_init_poll(dramcont0);
umc_dram_init_poll(dramcont1);
return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16),
ddr3plus);
}
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
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;
ph1_pro4_ddrphy_init(phy0_0, bd->dram_freq, bd->dram_ch0_size);
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;
}
ddrphy_prepare_training(phy0_0, 0);
ddrphy_training(phy0_0);
writel(0x00000103, dramcont0 + UMC_DIOCTLA);
ph1_pro4_ddrphy_init(phy0_1, bd->dram_freq, bd->dram_ch0_size);
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);
ret = umc_dramcont_init(dramcont0, ca_base0, bd->dram_ch0_size,
bd->dram_ch0_width);
if (ret)
return ret;
ret = umc_dramcont_init(dramcont1, ca_base1, bd->dram_ch1_size,
bd->dram_ch1_width);
if (ret)
return ret;
ca_base += 0x00001000;
dc_base += 0x00200000;
}
umc_start_ssif(ssif_base);

View File

@ -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
enum dram_freq freq_e;
enum dram_size size_e;
writel(0x5101046A, dramcont + UMC_INITCTLA);
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;
}
if (size == 1)
writel(0x27028B0A, dramcont + UMC_INITCTLB);
else if (size == 2)
writel(0x38028B0A, dramcont + UMC_INITCTLB);
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(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);
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);
void __iomem *phy_base = dc_base + 0x00001000;
int ret;
umc_dram_init_start(dramcont0);
umc_dram_init_start(dramcont1);
umc_dram_init_poll(dramcont0);
umc_dram_init_poll(dramcont1);
writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
cpu_relax();
writel(0x00000101, dramcont0 + UMC_DIOCTLA);
writel(0x00000101, dc_base + UMC_DIOCTLA);
ph1_sld8_ddrphy_init(phy0_0, freq, size_ch0);
ret = ph1_ld4_ddrphy_init(phy_base, freq, ddr3plus);
if (ret)
return ret;
ddrphy_prepare_training(phy0_0, 0);
ddrphy_training(phy0_0);
ddrphy_prepare_training(phy_base, umc_get_rank(ch));
ret = ddrphy_training(phy_base);
if (ret)
return ret;
writel(0x00000101, dramcont1 + UMC_DIOCTLA);
return umc_dramcont_init(dc_base, ca_base, freq, size, ddr3plus);
}
ph1_sld8_ddrphy_init(phy1_0, freq, size_ch1);
int ph1_sld8_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;
ddrphy_prepare_training(phy1_0, 1);
ddrphy_training(phy1_0);
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;
}
umc_dramcont_init(dramcont0, ca_base0, size_ch0, freq);
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq);
ca_base += 0x00001000;
dc_base += 0x00200000;
}
umc_start_ssif(ssif_base);
return 0;
}
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;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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++;
}
}

View File

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

View File

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

View File

@ -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:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,
};

View File

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

View File

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

751
drivers/mmc/uniphier-sd.c Normal file
View File

@ -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),
};

View File

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