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 config ARCH_UNIPHIER
bool "Socionext UniPhier SoCs" bool "Socionext UniPhier SoCs"
select CLK_UNIPHIER select CLK_UNIPHIER
select CPU_V7
select SUPPORT_SPL select SUPPORT_SPL
select SPL select SPL
select OF_CONTROL select OF_CONTROL
select SPL_OF_CONTROL select SPL_OF_CONTROL
select DM select DM
select SPL_DM select SPL_DM
select DM_GPIO
select DM_SERIAL select DM_SERIAL
select DM_I2C select DM_I2C
select DM_MMC
help help
Support for UniPhier SoC family developed by Socionext Inc. Support for UniPhier SoC family developed by Socionext Inc.
(formerly, System LSI Business Division of Panasonic Corporation) (formerly, System LSI Business Division of Panasonic Corporation)

View File

@ -23,12 +23,6 @@
ranges; ranges;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
extbus: extbus {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
};
serial0: serial@54006800 { serial0: serial@54006800 {
compatible = "socionext,uniphier-uart"; compatible = "socionext,uniphier-uart";
status = "disabled"; status = "disabled";
@ -69,9 +63,16 @@
clocks = <&uart_clk>; clocks = <&uart_clk>;
}; };
system-bus-controller@58c00000 { system_bus: system-bus@58c00000 {
compatible = "socionext,uniphier-system-bus-controller"; compatible = "socionext,uniphier-system-bus";
reg = <0x58c00000 0x400>, <0x59800000 0x2000>; reg = <0x58c00000 0x400>;
#address-cells = <2>;
#size-cells = <1>;
};
smpctrl@59800000 {
compatible = "socionext,uniphier-smpctrl";
reg = <0x59801000 0x400>;
}; };
mio: mioctrl@59810000 { mio: mioctrl@59810000 {

View File

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

View File

@ -56,6 +56,118 @@
cache-level = <2>; 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 { i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c"; compatible = "socionext,uniphier-i2c";
status = "disabled"; status = "disabled";
@ -108,6 +220,31 @@
clock-frequency = <100000>; 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 { usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci"; compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled"; status = "disabled";

View File

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

View File

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

View File

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

View File

@ -64,6 +64,10 @@
status = "okay"; status = "okay";
}; };
&emmc {
status = "okay";
};
&usb0 { &usb0 {
status = "okay"; status = "okay";
}; };
@ -91,6 +95,14 @@
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&mio {
u-boot,dm-pre-reloc;
};
&emmc {
u-boot,dm-pre-reloc;
};
&pinctrl { &pinctrl {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
@ -98,3 +110,7 @@
&pinctrl_uart0 { &pinctrl_uart0 {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&pinctrl_emmc {
u-boot,dm-pre-reloc;
};

View File

@ -64,6 +64,209 @@
cache-level = <2>; 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 { i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c"; compatible = "socionext,uniphier-fi2c";
status = "disabled"; status = "disabled";
@ -140,6 +343,43 @@
clock-frequency = <400000>; 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 { usb2: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci"; compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled"; status = "disabled";

View File

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

View File

@ -76,6 +76,209 @@
cache-level = <3>; 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 { i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c"; compatible = "socionext,uniphier-fi2c";
status = "disabled"; status = "disabled";
@ -152,6 +355,30 @@
clock-frequency = <400000>; 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 { usb0: usb@65a00000 {
compatible = "socionext,uniphier-xhci", "generic-xhci"; compatible = "socionext,uniphier-xhci", "generic-xhci";
status = "disabled"; status = "disabled";

View File

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

View File

@ -62,12 +62,6 @@
ranges; ranges;
interrupt-parent = <&intc>; interrupt-parent = <&intc>;
extbus: extbus {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
};
timer@20000200 { timer@20000200 {
compatible = "arm,cortex-a9-global-timer"; compatible = "arm,cortex-a9-global-timer";
reg = <0x20000200 0x20>; reg = <0x20000200 0x20>;
@ -117,6 +111,118 @@
clock-frequency = <36864000>; 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 { i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c"; compatible = "socionext,uniphier-i2c";
status = "disabled"; status = "disabled";
@ -172,10 +278,16 @@
clock-frequency = <400000>; clock-frequency = <400000>;
}; };
system-bus-controller-misc@59800000 { system_bus: system-bus@58c00000 {
compatible = "socionext,uniphier-system-bus-controller-misc", compatible = "socionext,uniphier-system-bus";
"syscon"; reg = <0x58c00000 0x400>;
reg = <0x59800000 0x2000>; #address-cells = <2>;
#size-cells = <1>;
};
smpctrl@59800000 {
compatible = "socionext,uniphier-smpctrl";
reg = <0x59801000 0x400>;
}; };
mio: mioctrl@59810000 { mio: mioctrl@59810000 {
@ -186,6 +298,25 @@
clocks = <&sysctrl 10>, <&sysctrl 18>; 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 { usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci"; compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled"; status = "disabled";

View File

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

View File

@ -56,6 +56,118 @@
cache-level = <2>; 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 { i2c0: i2c@58400000 {
compatible = "socionext,uniphier-i2c"; compatible = "socionext,uniphier-i2c";
status = "disabled"; status = "disabled";
@ -108,6 +220,31 @@
clock-frequency = <100000>; 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 { usb0: usb@5a800100 {
compatible = "socionext,uniphier-ehci", "generic-ehci"; compatible = "socionext,uniphier-ehci", "generic-ehci";
status = "disabled"; status = "disabled";

View File

@ -12,6 +12,11 @@
function = "emmc"; function = "emmc";
}; };
pinctrl_emmc_1v8: emmc_grp_1v8 {
groups = "emmc", "emmc_dat8";
function = "emmc";
};
pinctrl_i2c0: i2c0_grp { pinctrl_i2c0: i2c0_grp {
groups = "i2c0"; groups = "i2c0";
function = "i2c0"; function = "i2c0";
@ -37,11 +42,21 @@
function = "sd"; function = "sd";
}; };
pinctrl_sd_1v8: sd_grp_1v8 {
groups = "sd";
function = "sd";
};
pinctrl_sd1: sd1_grp { pinctrl_sd1: sd1_grp {
groups = "sd1"; groups = "sd1";
function = "sd1"; function = "sd1";
}; };
pinctrl_sd1_1v8: sd1_grp_1v8 {
groups = "sd1";
function = "sd1";
};
pinctrl_uart0: uart0_grp { pinctrl_uart0: uart0_grp {
groups = "uart0"; groups = "uart0";
function = "uart0"; function = "uart0";

View File

@ -52,6 +52,10 @@
status = "okay"; status = "okay";
}; };
&emmc {
status = "okay";
};
&usb0 { &usb0 {
status = "okay"; status = "okay";
}; };
@ -71,6 +75,14 @@
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&mio {
u-boot,dm-pre-reloc;
};
&emmc {
u-boot,dm-pre-reloc;
};
&pinctrl { &pinctrl {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
@ -78,3 +90,7 @@
&pinctrl_uart2 { &pinctrl_uart2 {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&pinctrl_emmc {
u-boot,dm-pre-reloc;
};

View File

@ -41,6 +41,10 @@
status = "okay"; status = "okay";
}; };
&emmc {
status = "okay";
};
&usb0 { &usb0 {
status = "okay"; status = "okay";
}; };
@ -56,6 +60,14 @@
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&mio {
u-boot,dm-pre-reloc;
};
&emmc {
u-boot,dm-pre-reloc;
};
&pinctrl { &pinctrl {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
@ -63,3 +75,7 @@
&pinctrl_uart2 { &pinctrl_uart2 {
u-boot,dm-pre-reloc; u-boot,dm-pre-reloc;
}; };
&pinctrl_emmc {
u-boot,dm-pre-reloc;
};

View File

@ -78,6 +78,202 @@
cache-level = <2>; 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 { i2c0: i2c@58780000 {
compatible = "socionext,uniphier-fi2c"; compatible = "socionext,uniphier-fi2c";
status = "disabled"; status = "disabled";
@ -163,6 +359,30 @@
clock-frequency = <400000>; 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 { usb0: usb@65a00000 {
compatible = "socionext,uniphier-xhci", "generic-xhci"; compatible = "socionext,uniphier-xhci", "generic-xhci";
status = "disabled"; status = "disabled";

View File

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

View File

@ -3,54 +3,52 @@ if ARCH_UNIPHIER
config SYS_CONFIG_NAME config SYS_CONFIG_NAME
default "uniphier" default "uniphier"
choice
prompt "UniPhier SoC select"
default ARCH_UNIPHIER_PH1_PRO4
config ARCH_UNIPHIER_PH1_SLD3 config ARCH_UNIPHIER_PH1_SLD3
bool "UniPhier PH1-sLD3 SoC" bool "UniPhier PH1-sLD3 SoC"
help select CPU_V7
This enables support for UniPhier PH1-sLD3 SoC.
config ARCH_UNIPHIER_PH1_LD4 config ARCH_UNIPHIER_LD4_SLD8
bool "UniPhier PH1-LD4 SoC" bool "UniPhier PH1-LD4/PH1-sLD8 SoC"
depends on !ARCH_UNIPHIER_PH1_SLD3 select CPU_V7
help
This enables support for UniPhier PH1-LD4 SoC.
config ARCH_UNIPHIER_PH1_PRO4 config ARCH_UNIPHIER_PH1_PRO4
bool "UniPhier PH1-Pro4 SoC" bool "UniPhier PH1-Pro4 SoC"
depends on !ARCH_UNIPHIER_PH1_SLD3 && \ select CPU_V7
!ARCH_UNIPHIER_PH1_LD4 && \
!ARCH_UNIPHIER_PH1_SLD8 config ARCH_UNIPHIER_PRO5_PXS2_LD6B
help bool "UniPhier PH1-Pro5/ProXstream2/PH1-LD6b SoC"
This enables support for UniPhier PH1-Pro4 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 config ARCH_UNIPHIER_PH1_SLD8
bool "UniPhier PH1-sLD8 SoC" bool "Enable UniPhier PH1-sLD8 SoC support"
depends on !ARCH_UNIPHIER_PH1_SLD3 depends on ARCH_UNIPHIER_LD4_SLD8
help default y
This enables support for UniPhier PH1-sLD8 SoC.
config ARCH_UNIPHIER_PH1_PRO5 config ARCH_UNIPHIER_PH1_PRO5
bool "UniPhier PH1-Pro5 SoC" bool "Enable UniPhier PH1-Pro5 SoC support"
depends on !ARCH_UNIPHIER_PH1_SLD3 && \ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
!ARCH_UNIPHIER_PH1_LD4 && \ default y
!ARCH_UNIPHIER_PH1_SLD8
help
This enables support for UniPhier PH1-Pro5 SoC.
config ARCH_UNIPHIER_PROXSTREAM2 config ARCH_UNIPHIER_PROXSTREAM2
bool "UniPhier ProXstream2 SoC" bool "Enable UniPhier ProXstream2 SoC support"
depends on !ARCH_UNIPHIER_PH1_SLD3 && \ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
!ARCH_UNIPHIER_PH1_LD4 && \ default y
!ARCH_UNIPHIER_PH1_SLD8
help
This enables support for UniPhier ProXstream2 SoC.
config ARCH_UNIPHIER_PH1_LD6B config ARCH_UNIPHIER_PH1_LD6B
bool "UniPhier PH1-LD6b SoC" bool "Enable UniPhier PH1-LD6b SoC support"
depends on !ARCH_UNIPHIER_PH1_SLD3 && \ depends on ARCH_UNIPHIER_PRO5_PXS2_LD6B
!ARCH_UNIPHIER_PH1_LD4 && \ default y
!ARCH_UNIPHIER_PH1_SLD8
help
This enables support for UniPhier PH1-LD6b SoC.
config MICRO_SUPPORT_CARD config MICRO_SUPPORT_CARD
bool "Use Micro Support Card" bool "Use Micro Support Card"

View File

@ -4,16 +4,11 @@
ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_BUILD
obj-y += lowlevel_init.o
obj-y += init/ bcu/ memconf/ pll/ early-clk/ early-pinctrl/ obj-y += init/ bcu/ memconf/ pll/ early-clk/ early-pinctrl/
obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/ obj-$(CONFIG_MICRO_SUPPORT_CARD) += sbc/
obj-$(CONFIG_DEBUG_LL) += debug_ll.o
else else
obj-y += late_lowlevel_init.o
obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o obj-$(CONFIG_BOARD_EARLY_INIT_F) += board_early_init_f.o
obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o obj-$(CONFIG_DISPLAY_CPUINFO) += cpu_info.o
obj-$(CONFIG_MISC_INIT_F) += print_misc_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_EARLY_INIT_R) += board_early_init_r.o
obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o obj-$(CONFIG_BOARD_LATE_INIT) += board_late_init.o
obj-y += reset.o obj-y += reset.o
obj-y += cache_uniphier.o
obj-y += pinctrl/ clk/ obj-y += pinctrl/ clk/
endif endif
obj-y += timer.o
obj-y += boards.o obj-y += boards.o
obj-y += soc_info.o obj-y += soc_info.o
obj-y += boot-mode/ obj-y += boot-mode/
obj-y += dram/ obj-y += dram/
obj-$(CONFIG_MICRO_SUPPORT_CARD) += micro-support-card.o 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/serial_reg.h>
#include <linux/linkage.h> #include <linux/linkage.h>
#include "bcu/bcu-regs.h" #include "../bcu/bcu-regs.h"
#include "sc-regs.h" #include "../sc-regs.h"
#include "sg-regs.h" #include "../sg-regs.h"
#if !defined(CONFIG_DEBUG_SEMIHOSTING) #if !defined(CONFIG_DEBUG_SEMIHOSTING)
#include CONFIG_DEBUG_LL_INCLUDE #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 */ writel(0x11111111, BCSCR5); /* 0xe0000000-0Xffffffff: IPPC/IPPD-bus */
/* Specify DDR channel */ /* 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 */ writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
shift -= 32; shift -= 32;

View File

@ -26,7 +26,7 @@ int ph1_sld3_bcu_init(const struct uniphier_board_data *bd)
writel(0x24440000, BCSCR5); writel(0x24440000, BCSCR5);
/* Specify DDR channel */ /* 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 */ writel(ch(shift), BCIPPCCHR2); /* 0x80000000-0x9fffffff */
shift -= 32; shift -= 32;

View File

@ -14,106 +14,154 @@ DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3) #if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD3)
static const struct uniphier_board_data ph1_sld3_data = { static const struct uniphier_board_data ph1_sld3_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1600,
.dram_ch0_size = 0x20000000, .dram_nr_ch = 3,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xc0000000, .base = 0x80000000,
.dram_ch1_size = 0x20000000, .size = 0x20000000,
.dram_ch1_width = 16, .width = 32,
.dram_ch2_base = 0xc0000000, },
.dram_ch2_size = 0x10000000, .dram_ch[1] = {
.dram_ch2_width = 16, .base = 0xc0000000,
.dram_freq = 1600, .size = 0x20000000,
.width = 16,
},
.dram_ch[2] = {
.base = 0xc0000000,
.size = 0x10000000,
.width = 16,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD4)
static const struct uniphier_board_data ph1_ld4_data = { static const struct uniphier_board_data ph1_ld4_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1600,
.dram_ch0_size = 0x10000000, .dram_nr_ch = 2,
.dram_ch0_width = 16, .dram_ddr3plus = true,
.dram_ch1_base = 0x90000000, .dram_ch[0] = {
.dram_ch1_size = 0x10000000, .base = 0x80000000,
.dram_ch1_width = 16, .size = 0x10000000,
.dram_freq = 1600, .width = 16,
},
.dram_ch[1] = {
.base = 0x90000000,
.size = 0x10000000,
.width = 16,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4) #if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO4)
/* 1GB RAM board */ /* 1GB RAM board */
static const struct uniphier_board_data ph1_pro4_data = { static const struct uniphier_board_data ph1_pro4_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1600,
.dram_ch0_size = 0x20000000, .dram_nr_ch = 2,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xa0000000, .base = 0x80000000,
.dram_ch1_size = 0x20000000, .size = 0x20000000,
.dram_ch1_width = 32, .width = 32,
.dram_freq = 1600, },
.dram_ch[1] = {
.base = 0xa0000000,
.size = 0x20000000,
.width = 32,
},
}; };
/* 2GB RAM board */ /* 2GB RAM board */
static const struct uniphier_board_data ph1_pro4_2g_data = { static const struct uniphier_board_data ph1_pro4_2g_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1600,
.dram_ch0_size = 0x40000000, .dram_nr_ch = 2,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xc0000000, .base = 0x80000000,
.dram_ch1_size = 0x40000000, .size = 0x40000000,
.dram_ch1_width = 32, .width = 32,
.dram_freq = 1600, },
.dram_ch[1] = {
.base = 0xc0000000,
.size = 0x40000000,
.width = 32,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8) #if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD8)
static const struct uniphier_board_data ph1_sld8_data = { static const struct uniphier_board_data ph1_sld8_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1333,
.dram_ch0_size = 0x10000000, .dram_nr_ch = 2,
.dram_ch0_width = 16, .dram_ddr3plus = true,
.dram_ch1_base = 0x90000000, .dram_ch[0] = {
.dram_ch1_size = 0x10000000, .base = 0x80000000,
.dram_ch1_width = 16, .size = 0x10000000,
.dram_freq = 1333, .width = 16,
},
.dram_ch[1] = {
.base = 0x90000000,
.size = 0x10000000,
.width = 16,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5) #if defined(CONFIG_ARCH_UNIPHIER_PH1_PRO5)
static const struct uniphier_board_data ph1_pro5_data = { static const struct uniphier_board_data ph1_pro5_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1866,
.dram_ch0_size = 0x20000000, .dram_nr_ch = 2,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xa0000000, .base = 0x80000000,
.dram_ch1_size = 0x20000000, .size = 0x20000000,
.dram_ch1_width = 32, .width = 32,
.dram_freq = 1866, },
.dram_ch[1] = {
.base = 0xa0000000,
.size = 0x20000000,
.width = 32,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) #if defined(CONFIG_ARCH_UNIPHIER_PROXSTREAM2)
static const struct uniphier_board_data proxstream2_data = { static const struct uniphier_board_data proxstream2_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 2133,
.dram_ch0_size = 0x40000000, .dram_nr_ch = 3,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xc0000000, .base = 0x80000000,
.dram_ch1_size = 0x20000000, .size = 0x40000000,
.dram_ch1_width = 32, .width = 32,
.dram_ch2_base = 0xe0000000, },
.dram_ch2_size = 0x20000000, .dram_ch[1] = {
.dram_ch2_width = 16, .base = 0xc0000000,
.dram_freq = 2133, .size = 0x20000000,
.width = 32,
},
.dram_ch[2] = {
.base = 0xe0000000,
.size = 0x20000000,
.width = 16,
},
}; };
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B)
static const struct uniphier_board_data ph1_ld6b_data = { static const struct uniphier_board_data ph1_ld6b_data = {
.dram_ch0_base = 0x80000000, .dram_freq = 1866,
.dram_ch0_size = 0x40000000, .dram_nr_ch = 3,
.dram_ch0_width = 32, .dram_ch[0] = {
.dram_ch1_base = 0xc0000000, .base = 0x80000000,
.dram_ch1_size = 0x20000000, .size = 0x40000000,
.dram_ch1_width = 32, .width = 32,
.dram_ch2_base = 0xe0000000, },
.dram_ch2_size = 0x20000000, .dram_ch[1] = {
.dram_ch2_width = 16, .base = 0xc0000000,
.dram_freq = 1866, .size = 0x20000000,
.width = 32,
},
.dram_ch[2] = {
.base = 0xe0000000,
.size = 0x20000000,
.width = 16,
},
}; };
#endif #endif

View File

@ -5,7 +5,9 @@
*/ */
#include <common.h> #include <common.h>
#include <mmc.h>
#include <spl.h> #include <spl.h>
#include <linux/err.h>
#include "../sbc/sbc-regs.h" #include "../sbc/sbc-regs.h"
#include "../soc-info.h" #include "../soc-info.h"
@ -52,3 +54,65 @@ u32 spl_boot_device(void)
return ret == BOOT_DEVICE_USB ? BOOT_DEVICE_NOR : ret; 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)"); puts("PH1-LD6b (MN2WS0320)");
break; break;
case 0x31: case 0x31:
puts("PH1-sLD11 ()"); puts("PH1-LD11 ()");
break; break;
case 0x32: case 0x32:
puts("PH1-LD10 ()"); puts("PH1-LD20 ()");
break; break;
default: default:
printf("Unknown Processor ID (0x%x)\n", revision); 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 \ obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD4) += umc-ph1-ld4.o \
ddrphy-training.o ddrphy-ph1-ld4.o ddrphy-training.o ddrphy-ph1-ld4.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_PRO4) += umc-ph1-pro4.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 \ 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_PROXSTREAM2) += umc-proxstream2.o
obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD6B) += umc-proxstream2.o obj-$(CONFIG_ARCH_UNIPHIER_PH1_LD6B) += umc-proxstream2.o

View File

@ -4,31 +4,52 @@
* SPDX-License-Identifier: GPL-2.0+ * SPDX-License-Identifier: GPL-2.0+
*/ */
#include <common.h>
#include <linux/err.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/io.h> #include <linux/io.h>
#include "ddrphy-regs.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; 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]); writel(0x0300c473, &phy->pgcr[1]);
if (freq == 1333) { writel(ddrphy_ptr0[freq_e], &phy->ptr[0]);
writel(0x0a806844, &phy->ptr[0]); writel(ddrphy_ptr1[freq_e], &phy->ptr[1]);
writel(0x208e0124, &phy->ptr[1]);
} else {
writel(0x0c807d04, &phy->ptr[0]);
writel(0x2710015E, &phy->ptr[1]);
}
writel(0x00083DEF, &phy->ptr[2]); writel(0x00083DEF, &phy->ptr[2]);
if (freq == 1333) { writel(ddrphy_ptr3[freq_e], &phy->ptr[3]);
writel(0x0f051616, &phy->ptr[3]); writel(ddrphy_ptr4[freq_e], &phy->ptr[4]);
writel(0x06ae08d6, &phy->ptr[4]);
} else {
writel(0x12061A80, &phy->ptr[3]);
writel(0x08027100, &phy->ptr[4]);
}
writel(0xF004001A, &phy->dsgcr); writel(0xF004001A, &phy->dsgcr);
/* change the value of the on-die pull-up/pull-down registors */ /* 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(tmp, &phy->dxccr);
writel(0x0000040B, &phy->dcr); writel(0x0000040B, &phy->dcr);
if (freq == 1333) { writel(ddrphy_dtpr0[freq_e], &phy->dtpr[0]);
writel(0x85589955, &phy->dtpr[0]); writel(ddrphy_dtpr1[freq_e], &phy->dtpr[1]);
if (size == 1) writel(ddrphy_dtpr2[freq_e], &phy->dtpr[2]);
writel(0x1a8253c0, &phy->dtpr[1]); writel(ddrphy_mr0[freq_e], &phy->mr0);
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(0x00000006, &phy->mr1); writel(0x00000006, &phy->mr1);
if (freq == 1333) writel(ddrphy_mr2[freq_e], &phy->mr2);
writel(0x00000290, &phy->mr2); writel(ddr3plus ? 0x00000800 : 0x00000000, &phy->mr3);
else
writel(0x00000298, &phy->mr2);
writel(0x00000800, &phy->mr3);
while (!(readl(&phy->pgsr[0]) & PGSR0_IDONE)) 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/bitops.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <linux/types.h>
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
@ -169,9 +170,7 @@ struct ddrphy {
#define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy)) #define DDRPHY_BASE(ch, phy) (0x5bc01000 + 0x200000 * (ch) + 0x1000 * (phy))
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, int size); int ph1_ld4_ddrphy_init(struct ddrphy __iomem *phy, int freq, bool ddr3plus);
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);
void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank); void ddrphy_prepare_training(struct ddrphy __iomem *phy, int rank);
int ddrphy_training(struct ddrphy __iomem *phy); int ddrphy_training(struct ddrphy __iomem *phy);
#endif #endif

View File

@ -8,11 +8,40 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <asm/processor.h>
#include "../init.h" #include "../init.h"
#include "ddrphy-regs.h" #include "ddrphy-regs.h"
#include "umc-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) static void umc_start_ssif(void __iomem *ssif_base)
{ {
writel(0x00000000, ssif_base + 0x0000b004); writel(0x00000000, ssif_base + 0x0000b004);
@ -47,130 +76,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST); writel(0x00000001, ssif_base + UMC_DMDRST);
} }
static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
int size, int freq) int freq, unsigned long size, bool ddr3plus)
{ {
if (freq == 1333) { enum dram_freq freq_e;
writel(0x45990b11, dramcont + UMC_CMDCTLA); enum dram_size size_e;
writel(0x16958924, dramcont + UMC_CMDCTLB);
writel(0x5101046A, dramcont + UMC_INITCTLA);
if (size == 1) if (!ddr3plus) {
writel(0x27028B0A, dramcont + UMC_INITCTLB); pr_err("DDR3 standard is not supported\n");
else if (size == 2) return -EINVAL;
writel(0x38028B0A, dramcont + UMC_INITCTLB);
writel(0x000FF0FF, dramcont + UMC_INITCTLC);
writel(0x00000b51, dramcont + UMC_DRMMR0);
} else if (freq == 1600) {
writel(0x36BB0F17, dramcont + UMC_CMDCTLA);
writel(0x18C6AA24, dramcont + UMC_CMDCTLB);
writel(0x5101387F, dramcont + UMC_INITCTLA);
if (size == 1)
writel(0x2F030D3F, dramcont + UMC_INITCTLB);
else if (size == 2)
writel(0x43030D3F, dramcont + UMC_INITCTLB);
writel(0x00FF00FF, dramcont + UMC_INITCTLC);
writel(0x00000d71, dramcont + UMC_DRMMR0);
} }
writel(0x00000006, dramcont + UMC_DRMMR1); switch (freq) {
case 1333:
if (freq == 1333) freq_e = DRAM_FREQ_1333M;
writel(0x00000290, dramcont + UMC_DRMMR2); break;
else if (freq == 1600) case 1600:
writel(0x00000298, dramcont + UMC_DRMMR2); freq_e = DRAM_FREQ_1600M;
break;
writel(0x00000800, dramcont + UMC_DRMMR3); default:
pr_err("unsupported DRAM frequency %d MHz\n", freq);
if (freq == 1333) { return -EINVAL;
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);
} }
writel(0x04060806, dramcont + UMC_WDATACTL_D0); switch (size) {
writel(0x04a02000, dramcont + UMC_DATASET); 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(0x00000000, ca_base + 0x2300);
writel(0x00400020, dramcont + UMC_DCCGCTL); writel(0x00400020, dc_base + UMC_DCCGCTL);
writel(0x00000003, dramcont + 0x7000); writel(0x00000003, dc_base + 0x7000);
writel(0x0000000f, dramcont + 0x8000); writel(0x0000000f, dc_base + 0x8000);
writel(0x000000c3, dramcont + 0x8004); writel(0x000000c3, dc_base + 0x8004);
writel(0x00000071, dramcont + 0x8008); writel(0x00000071, dc_base + 0x8008);
writel(0x0000003b, dramcont + UMC_DICGCTLA); writel(0x0000003b, dc_base + UMC_DICGCTLA);
writel(0x020a0808, dramcont + UMC_DICGCTLB); writel(0x020a0808, dc_base + UMC_DICGCTLB);
writel(0x00000004, dramcont + UMC_FLOWCTLG); writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20); writel(0x80000201, ca_base + 0xc20);
writel(0x0801e01e, dramcont + UMC_FLOWCTLA); writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
writel(0x00200000, dramcont + UMC_FLOWCTLB); writel(0x00200000, dc_base + UMC_FLOWCTLB);
writel(0x00004444, dramcont + UMC_FLOWCTLC); writel(0x00004444, dc_base + UMC_FLOWCTLC);
writel(0x200a0a00, dramcont + UMC_SPCSETB); writel(0x200a0a00, dc_base + UMC_SPCSETB);
writel(0x00000000, dramcont + UMC_SPCSETD); writel(0x00000000, dc_base + UMC_SPCSETD);
writel(0x00000520, dramcont + UMC_DFICUPDCTLA); 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 *phy_base = dc_base + 0x00001000;
void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); int ret;
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
umc_dram_init_start(dramcont0); writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
umc_dram_init_start(dramcont1); while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
umc_dram_init_poll(dramcont0); cpu_relax();
umc_dram_init_poll(dramcont1);
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_prepare_training(phy_base, umc_get_rank(ch));
ddrphy_training(phy0_0); 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); for (ch = 0; ch < DRAM_CH_NR; ch++) {
ddrphy_training(phy1_0); 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); ca_base += 0x00001000;
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); dc_base += 0x00200000;
}
umc_start_ssif(ssif_base); umc_start_ssif(ssif_base);
return 0; 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/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <asm/processor.h>
#include "../init.h" #include "../init.h"
#include "ddrphy-regs.h" #include "ddrphy-regs.h"
#include "umc-regs.h" #include "umc-regs.h"
#define DRAM_CH_NR 2
enum dram_size { enum dram_size {
DRAM_SZ_128M, DRAM_SZ_128M,
DRAM_SZ_256M, DRAM_SZ_256M,
@ -20,14 +23,13 @@ enum dram_size {
DRAM_SZ_NR, DRAM_SZ_NR,
}; };
static u32 umc_initctlb[DRAM_SZ_NR] = {0x43030d3f, 0x43030d3f, 0x7b030d3f};
static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617}; static u32 umc_spcctla[DRAM_SZ_NR] = {0x002b0617, 0x003f0617, 0x00770617};
static void umc_start_ssif(void __iomem *ssif_base) 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(0xffffffff, ssif_base + 0x0000c004);
writel(0x07ffffff, ssif_base + 0x0000c008); writel(0x000fffcf, ssif_base + 0x0000c008);
writel(0x00000001, ssif_base + 0x0000b000); writel(0x00000001, ssif_base + 0x0000b000);
writel(0x00000001, ssif_base + 0x0000c000); writel(0x00000001, ssif_base + 0x0000c000);
@ -66,121 +68,117 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST); writel(0x00000001, ssif_base + UMC_DMDRST);
} }
static int umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
int size, int width) int freq, unsigned long size, bool ddr3plus)
{ {
enum dram_size dram_size; enum dram_size size_e;
switch (size / (width / 16)) { if (freq != 1600) {
case SZ_128M: pr_err("Unsupported DDR frequency %d MHz\n", freq);
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");
return -EINVAL; return -EINVAL;
} }
writel(0x66bb0f17, dramcont + UMC_CMDCTLA); if (ddr3plus) {
writel(0x18c6aa44, dramcont + UMC_CMDCTLB); pr_err("DDR3+ is not supported\n");
writel(0x5101387f, dramcont + UMC_INITCTLA); return -EINVAL;
writel(umc_initctlb[dram_size], dramcont + UMC_INITCTLB); }
writel(0x00ff00ff, dramcont + UMC_INITCTLC);
writel(0x00000d71, dramcont + UMC_DRMMR0); switch (size) {
writel(0x00000006, dramcont + UMC_DRMMR1); case SZ_128M:
writel(0x00000298, dramcont + UMC_DRMMR2); size_e = DRAM_SZ_128M;
writel(0x00000000, dramcont + UMC_DRMMR3); break;
writel(umc_spcctla[dram_size], dramcont + UMC_SPCCTLA); case SZ_256M:
writel(0x00ff0008, dramcont + UMC_SPCCTLB); size_e = DRAM_SZ_256M;
writel(0x000c00ae, dramcont + UMC_RDATACTL_D0); break;
writel(0x000c00ae, dramcont + UMC_RDATACTL_D1); case SZ_512M:
writel(0x04060802, dramcont + UMC_WDATACTL_D0); size_e = DRAM_SZ_512M;
writel(0x04060802, dramcont + UMC_WDATACTL_D1); break;
writel(0x04a02000, dramcont + UMC_DATASET); 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(0x00000000, ca_base + 0x2300);
writel(0x00400020, dramcont + UMC_DCCGCTL); writel(0x00400020, dc_base + UMC_DCCGCTL);
writel(0x0000000f, dramcont + 0x7000); writel(0x0000000f, dc_base + 0x7000);
writel(0x0000000f, dramcont + 0x8000); writel(0x0000000f, dc_base + 0x8000);
writel(0x000000c3, dramcont + 0x8004); writel(0x000000c3, dc_base + 0x8004);
writel(0x00000071, dramcont + 0x8008); writel(0x00000071, dc_base + 0x8008);
writel(0x00000004, dramcont + UMC_FLOWCTLG); writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x00000000, dramcont + 0x0060); writel(0x00000000, dc_base + 0x0060);
writel(0x80000201, ca_base + 0xc20); writel(0x80000201, ca_base + 0xc20);
writel(0x0801e01e, dramcont + UMC_FLOWCTLA); writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
writel(0x00200000, dramcont + UMC_FLOWCTLB); writel(0x00200000, dc_base + UMC_FLOWCTLB);
writel(0x00004444, dramcont + UMC_FLOWCTLC); writel(0x00004444, dc_base + UMC_FLOWCTLC);
writel(0x200a0a00, dramcont + UMC_SPCSETB); writel(0x200a0a00, dc_base + UMC_SPCSETB);
writel(0x00010000, dramcont + UMC_SPCSETD); writel(0x00010000, dc_base + UMC_SPCSETD);
writel(0x80000020, dramcont + UMC_DFICUPDCTLA); writel(0x80000020, dc_base + UMC_DFICUPDCTLA);
return 0; 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 *phy_base = dc_base + 0x00001000;
void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); int nr_phy = width / 16;
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1); int phy, ret;
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
void __iomem *phy0_1 = (void __iomem *)DDRPHY_BASE(0, 1);
void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
void __iomem *phy1_1 = (void __iomem *)DDRPHY_BASE(1, 1);
int ret;
if (bd->dram_freq != 1600) { writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
pr_err("Unsupported DDR configuration\n"); while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
return -EINVAL; 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); return umc_dramcont_init(dc_base, ca_base, freq, size / (width / 16),
umc_dram_init_start(dramcont1); ddr3plus);
umc_dram_init_poll(dramcont0); }
umc_dram_init_poll(dramcont1);
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); ca_base += 0x00001000;
ddrphy_training(phy0_0); dc_base += 0x00200000;
}
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;
umc_start_ssif(ssif_base); umc_start_ssif(ssif_base);

View File

@ -8,11 +8,43 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/sizes.h> #include <linux/sizes.h>
#include <asm/processor.h>
#include "../init.h" #include "../init.h"
#include "ddrphy-regs.h" #include "ddrphy-regs.h"
#include "umc-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) static void umc_start_ssif(void __iomem *ssif_base)
{ {
writel(0x00000000, ssif_base + 0x0000b004); writel(0x00000000, ssif_base + 0x0000b004);
@ -47,110 +79,116 @@ static void umc_start_ssif(void __iomem *ssif_base)
writel(0x00000001, ssif_base + UMC_DMDRST); writel(0x00000001, ssif_base + UMC_DMDRST);
} }
static void umc_dramcont_init(void __iomem *dramcont, void __iomem *ca_base, static int umc_dramcont_init(void __iomem *dc_base, void __iomem *ca_base,
int size, int freq) int freq, unsigned long size, bool ddr3plus)
{ {
#ifdef CONFIG_DDR_STANDARD enum dram_freq freq_e;
writel(0x55990b11, dramcont + UMC_CMDCTLA); enum dram_size size_e;
writel(0x16958944, dramcont + UMC_CMDCTLB);
#else
writel(0x45990b11, dramcont + UMC_CMDCTLA);
writel(0x16958924, dramcont + UMC_CMDCTLB);
#endif
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) switch (size) {
writel(0x27028B0A, dramcont + UMC_INITCTLB); case 0:
else if (size == 2) return 0;
writel(0x38028B0A, dramcont + UMC_INITCTLB); 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((ddr3plus ? umc_cmdctla_plus : umc_cmdctla)[freq_e],
writel(0x00000b51, dramcont + UMC_DRMMR0); dc_base + UMC_CMDCTLA);
writel(0x00000006, dramcont + UMC_DRMMR1); writel((ddr3plus ? umc_cmdctlb_plus : umc_cmdctlb)[freq_e],
writel(0x00000290, dramcont + UMC_DRMMR2); dc_base + UMC_CMDCTLB);
writel(umc_spcctla[freq_e][size_e], dc_base + UMC_SPCCTLA);
#ifdef CONFIG_DDR_STANDARD writel(umc_spcctlb[freq_e], dc_base + UMC_SPCCTLB);
writel(0x00000000, dramcont + UMC_DRMMR3); writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
#else writel(0x04060806, dc_base + UMC_WDATACTL_D0);
writel(0x00000800, dramcont + UMC_DRMMR3); writel(0x04a02000, dc_base + UMC_DATASET);
#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(0x00000000, ca_base + 0x2300); writel(0x00000000, ca_base + 0x2300);
writel(0x00400020, dramcont + UMC_DCCGCTL); writel(0x00400020, dc_base + UMC_DCCGCTL);
writel(0x00000003, dramcont + 0x7000); writel(0x00000003, dc_base + 0x7000);
writel(0x0000004f, dramcont + 0x8000); writel(0x0000004f, dc_base + 0x8000);
writel(0x000000c3, dramcont + 0x8004); writel(0x000000c3, dc_base + 0x8004);
writel(0x00000077, dramcont + 0x8008); writel(0x00000077, dc_base + 0x8008);
writel(0x0000003b, dramcont + UMC_DICGCTLA); writel(0x0000003b, dc_base + UMC_DICGCTLA);
writel(0x020a0808, dramcont + UMC_DICGCTLB); writel(0x020a0808, dc_base + UMC_DICGCTLB);
writel(0x00000004, dramcont + UMC_FLOWCTLG); writel(0x00000004, dc_base + UMC_FLOWCTLG);
writel(0x80000201, ca_base + 0xc20); writel(0x80000201, ca_base + 0xc20);
writel(0x0801e01e, dramcont + UMC_FLOWCTLA); writel(0x0801e01e, dc_base + UMC_FLOWCTLA);
writel(0x00200000, dramcont + UMC_FLOWCTLB); writel(0x00200000, dc_base + UMC_FLOWCTLB);
writel(0x00004444, dramcont + UMC_FLOWCTLC); writel(0x00004444, dc_base + UMC_FLOWCTLC);
writel(0x200a0a00, dramcont + UMC_SPCSETB); writel(0x200a0a00, dc_base + UMC_SPCSETB);
writel(0x00000000, dramcont + UMC_SPCSETD); writel(0x00000000, dc_base + UMC_SPCSETD);
writel(0x00000520, dramcont + UMC_DFICUPDCTLA); 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 *phy_base = dc_base + 0x00001000;
void __iomem *ca_base0 = (void __iomem *)UMC_CA_BASE(0); int ret;
void __iomem *ca_base1 = (void __iomem *)UMC_CA_BASE(1);
void __iomem *dramcont0 = (void __iomem *)UMC_DRAMCONT_BASE(0);
void __iomem *dramcont1 = (void __iomem *)UMC_DRAMCONT_BASE(1);
void __iomem *phy0_0 = (void __iomem *)DDRPHY_BASE(0, 0);
void __iomem *phy1_0 = (void __iomem *)DDRPHY_BASE(1, 0);
umc_dram_init_start(dramcont0); writel(UMC_INITSET_INIT1EN, dc_base + UMC_INITSET);
umc_dram_init_start(dramcont1); while (readl(dc_base + UMC_INITSET) & UMC_INITSTAT_INIT1ST)
umc_dram_init_poll(dramcont0); cpu_relax();
umc_dram_init_poll(dramcont1);
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_prepare_training(phy_base, umc_get_rank(ch));
ddrphy_training(phy0_0); 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); for (ch = 0; ch < DRAM_CH_NR; ch++) {
ddrphy_training(phy1_0); 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); ca_base += 0x00001000;
umc_dramcont_init(dramcont1, ca_base1, size_ch1, freq); dc_base += 0x00200000;
}
umc_start_ssif(ssif_base); umc_start_ssif(ssif_base);
return 0; 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 "ddrmphy-regs.h"
#include "umc-regs.h" #include "umc-regs.h"
#define CH_NR 3 #define DRAM_CH_NR 3
enum dram_freq { enum dram_freq {
FREQ_1866M, DRAM_FREQ_1866M,
FREQ_2133M, DRAM_FREQ_2133M,
FREQ_NR, DRAM_FREQ_NR,
}; };
enum dram_size { enum dram_size {
SIZE_0, DRAM_SZ_256M,
SIZE_512M, DRAM_SZ_512M,
SIZE_1G, DRAM_SZ_NR,
SIZE_NR,
}; };
static u32 ddrphy_pgcr2[FREQ_NR] = {0x00FC7E5D, 0x00FC90AB}; static u32 ddrphy_pgcr2[DRAM_FREQ_NR] = {0x00FC7E5D, 0x00FC90AB};
static u32 ddrphy_ptr0[FREQ_NR] = {0x0EA09205, 0x10C0A6C6}; static u32 ddrphy_ptr0[DRAM_FREQ_NR] = {0x0EA09205, 0x10C0A6C6};
static u32 ddrphy_ptr1[FREQ_NR] = {0x0DAC041B, 0x0FA104B1}; static u32 ddrphy_ptr1[DRAM_FREQ_NR] = {0x0DAC041B, 0x0FA104B1};
static u32 ddrphy_ptr3[FREQ_NR] = {0x15171e45, 0x18182357}; static u32 ddrphy_ptr3[DRAM_FREQ_NR] = {0x15171e45, 0x18182357};
static u32 ddrphy_ptr4[FREQ_NR] = {0x0e9ad8e9, 0x10b34157}; static u32 ddrphy_ptr4[DRAM_FREQ_NR] = {0x0e9ad8e9, 0x10b34157};
static u32 ddrphy_dtpr0[FREQ_NR] = {0x35a00d88, 0x39e40e88}; static u32 ddrphy_dtpr0[DRAM_FREQ_NR] = {0x35a00d88, 0x39e40e88};
static u32 ddrphy_dtpr1[FREQ_NR] = {0x2288cc2c, 0x228a04d0}; static u32 ddrphy_dtpr1[DRAM_FREQ_NR] = {0x2288cc2c, 0x228a04d0};
static u32 ddrphy_dtpr2[FREQ_NR] = {0x50005e00, 0x50006a00}; static u32 ddrphy_dtpr2[DRAM_FREQ_NR] = {0x50005e00, 0x50006a00};
static u32 ddrphy_dtpr3[FREQ_NR] = {0x0010cb49, 0x0010ec89}; static u32 ddrphy_dtpr3[DRAM_FREQ_NR] = {0x0010cb49, 0x0010ec89};
static u32 ddrphy_mr0[FREQ_NR] = {0x00000115, 0x00000125}; static u32 ddrphy_mr0[DRAM_FREQ_NR] = {0x00000115, 0x00000125};
static u32 ddrphy_mr2[FREQ_NR] = {0x000002a0, 0x000002a8}; static u32 ddrphy_mr2[DRAM_FREQ_NR] = {0x000002a0, 0x000002a8};
/* dependent on package and board design */ /* 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 ch2 is a different generation UMC core.
* The register spec is different, unfortunately. * The register spec is different, unfortunately.
*/ */
static u32 umc_cmdctlb_ch01[FREQ_NR] = {0x13E87C44, 0x18F88C44}; static u32 umc_cmdctlb_ch01[DRAM_FREQ_NR] = {0x13E87C44, 0x18F88C44};
static u32 umc_cmdctlb_ch2[FREQ_NR] = {0x19E8DC44, 0x1EF8EC44}; static u32 umc_cmdctlb_ch2[DRAM_FREQ_NR] = {0x19E8DC44, 0x1EF8EC44};
static u32 umc_spcctla[FREQ_NR][SIZE_NR] = { static u32 umc_spcctla[DRAM_FREQ_NR][DRAM_SZ_NR] = {
{0x00000000, 0x004A071D, 0x0078071D}, {0x004A071D, 0x0078071D},
{0x00000000, 0x0055081E, 0x0089081E}, {0x0055081E, 0x0089081E},
}; };
static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B}; static u32 umc_spcctlb[] = {0x00FF000A, 0x00FF000B};
@ -344,7 +343,7 @@ static int __ddrphy_training(void __iomem *phy_base,
do { do {
if (--timeout < 0) { if (--timeout < 0) {
printf("%s: error: timeout during DDR training\n", pr_err("%s: error: timeout during DDR training\n",
__func__); __func__);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
@ -354,7 +353,7 @@ static int __ddrphy_training(void __iomem *phy_base,
for (s = seq; s->description; s++) { for (s = seq; s->description; s++) {
if (pgsr0 & s->err_flag) { if (pgsr0 & s->err_flag) {
printf("%s: error: %s failed\n", __func__, pr_err("%s: error: %s failed\n", __func__,
s->description); s->description);
return -EIO; return -EIO;
} }
@ -405,12 +404,12 @@ static int ddrphy_training(void __iomem *phy_base)
} }
/* UMC */ /* 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; u32 val;
int latency; 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_RADLTY_MASK) >> UMC_RDATACTL_RADLTY_SHIFT;
latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >> latency += (val & UMC_RDATACTL_RAD2LTY_MASK) >>
UMC_RDATACTL_RAD2LTY_SHIFT; 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; val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
} }
writel(val, umc_dc_base + UMC_RDATACTL_D0); writel(val, dc_base + UMC_RDATACTL_D0);
writel(val, umc_dc_base + UMC_RDATACTL_D1); 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 */ /* 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; u32 tmp;
tmp = readl(umc_dc_base + UMC_SPCSETB); tmp = readl(dc_base + UMC_SPCSETB);
tmp &= ~UMC_SPCSETB_AREFMD_MASK; tmp &= ~UMC_SPCSETB_AREFMD_MASK;
if (enable) if (enable)
@ -447,7 +446,7 @@ void umc_refresh_ctrl(void __iomem *umc_dc_base, int enable)
else else
tmp |= UMC_SPCSETB_AREFMD_REG; tmp |= UMC_SPCSETB_AREFMD_REG;
writel(tmp, umc_dc_base + UMC_SPCSETB); writel(tmp, dc_base + UMC_SPCSETB);
udelay(1); udelay(1);
} }
@ -459,20 +458,35 @@ static void umc_ud_init(void __iomem *umc_base, int ch)
writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0); writel(0x00000033, umc_base + UMC_PAIR1DOFF_D0);
} }
static void umc_dc_init(void __iomem *umc_dc_base, enum dram_freq freq, static int umc_dc_init(void __iomem *dc_base, enum dram_freq freq,
enum dram_size size, int ch, int width) unsigned long size, int width, int ch)
{ {
enum dram_size size_e;
int latency; int latency;
u32 val; 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], 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)], writel(umc_spcctla[freq][size_e], dc_base + UMC_SPCCTLA);
umc_dc_base + UMC_SPCCTLA); writel(umc_spcctlb[freq], dc_base + UMC_SPCCTLB);
writel(umc_spcctlb[freq], umc_dc_base + UMC_SPCCTLB);
val = 0x000e000e; val = 0x000e000e;
latency = 12; 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; val |= latency << UMC_RDATACTL_RADLTY_SHIFT;
} }
writel(val, umc_dc_base + UMC_RDATACTL_D0); writel(val, dc_base + UMC_RDATACTL_D0);
if (width >= 32) 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) if (width >= 32)
writel(0x04060A02, umc_dc_base + UMC_WDATACTL_D1); writel(0x04060A02, dc_base + UMC_WDATACTL_D1);
writel(0x04000000, umc_dc_base + UMC_DATASET); writel(0x04000000, dc_base + UMC_DATASET);
writel(0x00400020, umc_dc_base + UMC_DCCGCTL); writel(0x00400020, dc_base + UMC_DCCGCTL);
writel(0x00000084, umc_dc_base + UMC_FLOWCTLG); writel(0x00000084, dc_base + UMC_FLOWCTLG);
writel(0x00000000, umc_dc_base + UMC_ACSSETA); writel(0x00000000, dc_base + UMC_ACSSETA);
writel(ch == 2 ? umc_flowctla_ch2[freq] : umc_flowctla_ch01[freq], 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(0x00004400, dc_base + UMC_FLOWCTLC);
writel(0x200A0A00, umc_dc_base + UMC_SPCSETB); writel(0x200A0A00, dc_base + UMC_SPCSETB);
writel(0x00000520, umc_dc_base + UMC_DFICUPDCTLA); writel(0x00000520, dc_base + UMC_DFICUPDCTLA);
writel(0x0000000D, umc_dc_base + UMC_RESPCTL); writel(0x0000000D, dc_base + UMC_RESPCTL);
if (ch != 2) { if (ch != 2) {
writel(0x00202000, umc_dc_base + UMC_FLOWCTLB); writel(0x00202000, dc_base + UMC_FLOWCTLB);
writel(0xFDBFFFFF, umc_dc_base + UMC_FLOWCTLOB0); writel(0xFDBFFFFF, dc_base + UMC_FLOWCTLOB0);
writel(0xFFFFFFFF, umc_dc_base + UMC_FLOWCTLOB1); writel(0xFFFFFFFF, dc_base + UMC_FLOWCTLOB1);
writel(0x00080700, umc_dc_base + UMC_BSICMAPSET); writel(0x00080700, dc_base + UMC_BSICMAPSET);
} else { } else {
writel(0x00200000, umc_dc_base + UMC_FLOWCTLB); writel(0x00200000, dc_base + UMC_FLOWCTLB);
writel(0x00000000, umc_dc_base + UMC_BSICMAPSET); writel(0x00000000, dc_base + UMC_BSICMAPSET);
} }
writel(0x00000000, umc_dc_base + UMC_ERRMASKA); writel(0x00000000, dc_base + UMC_ERRMASKA);
writel(0x00000000, umc_dc_base + UMC_ERRMASKB); writel(0x00000000, dc_base + UMC_ERRMASKB);
return 0;
} }
static int umc_init(void __iomem *umc_base, enum dram_freq freq, int ch, static int umc_ch_init(void __iomem *umc_ch_base, enum dram_freq freq,
enum dram_size size, int width) unsigned long size, unsigned int width, int ch)
{ {
void __iomem *umc_dc_base = umc_base + 0x00011000; void __iomem *dc_base = umc_ch_base + 0x00011000;
void __iomem *phy_base = umc_base + 0x00030000; void __iomem *phy_base = umc_ch_base + 0x00030000;
int ret; int ret;
writel(0x00000002, umc_dc_base + UMC_INITSET); writel(0x00000002, dc_base + UMC_INITSET);
while (readl(umc_dc_base + UMC_INITSTAT) & BIT(2)) while (readl(dc_base + UMC_INITSTAT) & BIT(2))
cpu_relax(); cpu_relax();
/* deassert PHY reset signals */ /* deassert PHY reset signals */
writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST, 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); 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) if (ret)
return 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);
ret = ddrphy_training(phy_base); if (ret)
if (ret) return ret;
return ret;
}
udelay(1); udelay(1);
/* match the system latency between UMC and PHY */ /* 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)); ddrphy_get_system_latency(phy_base, width));
udelay(1); udelay(1);
/* stop auto refresh before clearing FIFO in PHY */ /* 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); ddrphy_fifo_reset(phy_base);
umc_refresh_ctrl(umc_dc_base, 1); umc_refresh_ctrl(dc_base, 1);
udelay(10); udelay(10);
@ -585,43 +601,34 @@ static void um_init(void __iomem *um_base)
int proxstream2_umc_init(const struct uniphier_board_data *bd) int proxstream2_umc_init(const struct uniphier_board_data *bd)
{ {
void __iomem *um_base = (void __iomem *)0x5b600000; void __iomem *um_base = (void __iomem *)0x5b600000;
void __iomem *umc_ch0_base = (void __iomem *)0x5b800000; void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
void __iomem *umc_ch1_base = (void __iomem *)0x5ba00000;
void __iomem *umc_ch2_base = (void __iomem *)0x5bc00000;
enum dram_freq freq; enum dram_freq freq;
int ret; int ch, ret;
switch (bd->dram_freq) { switch (bd->dram_freq) {
case 1866: case 1866:
freq = FREQ_1866M; freq = DRAM_FREQ_1866M;
break; break;
case 2133: case 2133:
freq = FREQ_2133M; freq = DRAM_FREQ_2133M;
break; break;
default: default:
printf("unsupported DRAM frequency %d MHz\n", bd->dram_freq); pr_err("unsupported DRAM frequency %d MHz\n", bd->dram_freq);
return -EINVAL; return -EINVAL;
} }
ret = umc_init(umc_ch0_base, freq, 0, bd->dram_ch0_size / SZ_256M, for (ch = 0; ch < bd->dram_nr_ch; ch++) {
bd->dram_ch0_width); unsigned long size = bd->dram_ch[ch].size;
if (ret) { unsigned int width = bd->dram_ch[ch].width;
printf("failed to initialize UMC ch0\n");
return ret;
}
ret = umc_init(umc_ch1_base, freq, 1, bd->dram_ch1_size / SZ_256M, ret = umc_ch_init(umc_ch_base, freq, size / (width / 16),
bd->dram_ch1_width); width, ch);
if (ret) { if (ret) {
printf("failed to initialize UMC ch1\n"); pr_err("failed to initialize UMC ch%d\n", ch);
return ret; return ret;
} }
ret = umc_init(umc_ch2_base, freq, 2, bd->dram_ch2_size / SZ_256M, umc_ch_base += 0x00200000;
bd->dram_ch2_width);
if (ret) {
printf("failed to initialize UMC ch2\n");
return ret;
} }
um_init(um_base); um_init(um_base);

View File

@ -9,10 +9,7 @@
#ifndef ARCH_UMC_REGS_H #ifndef ARCH_UMC_REGS_H
#define ARCH_UMC_REGS_H #define ARCH_UMC_REGS_H
#define UMC_BASE 0x5b800000 #include <linux/bitops.h>
/* SSIF registers */
#define UMC_SSIF_BASE UMC_BASE
#define UMC_CPURST 0x00000700 #define UMC_CPURST 0x00000700
#define UMC_IDSRST 0x0000070C #define UMC_IDSRST 0x0000070C
@ -48,23 +45,14 @@
#define UMC_CLKEN_SSIF_RC 0x0000C080 #define UMC_CLKEN_SSIF_RC 0x0000C080
#define UMC_CLKEN_SSIF_DST 0x0000C084 #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_CMDCTLA 0x00000000
#define UMC_CMDCTLB 0x00000004 #define UMC_CMDCTLB 0x00000004
#define UMC_INITCTLA 0x00000008
#define UMC_INITCTLB 0x0000000C
#define UMC_INITCTLC 0x00000010
#define UMC_INITSET 0x00000014 #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_INITSTAT 0x00000018
#define UMC_DRMMR0 0x0000001C #define UMC_INITSTAT_INIT1ST BIT(1) /* init without power-on wait */
#define UMC_DRMMR1 0x00000020 #define UMC_INITSTAT_INIT0ST BIT(0) /* init with power-on wait */
#define UMC_DRMMR2 0x00000024
#define UMC_DRMMR3 0x00000028
#define UMC_SPCCTLA 0x00000030 #define UMC_SPCCTLA 0x00000030
#define UMC_SPCCTLB 0x00000034 #define UMC_SPCCTLB 0x00000034
#define UMC_SPCSETA 0x00000038 #define UMC_SPCSETA 0x00000038
@ -116,30 +104,4 @@
#define UMC_BITPERPIXELMODE_D0 0x010 #define UMC_BITPERPIXELMODE_D0 0x010
#define UMC_PAIR1DOFF_D0 0x054 #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 #endif

View File

@ -32,7 +32,7 @@ int dram_init(void)
gd->ram_size = fdt32_to_cpu(*(val + 1)); 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; return 0;
} }
@ -54,6 +54,7 @@ void dram_init_banksize(void)
gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++); gd->bd->bi_dram[i].size = fdt32_to_cpu(*val++);
debug("DRAM bank %d: start = %08lx, size = %08lx\n", 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 #ifndef __MACH_INIT_H
#define __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 { struct uniphier_board_data {
unsigned long dram_ch0_base; unsigned int dram_freq;
unsigned long dram_ch0_size; unsigned int dram_nr_ch;
unsigned long dram_ch0_width; bool dram_ddr3plus;
unsigned long dram_ch1_base; struct uniphier_dram_ch dram_ch[UNIPHIER_MAX_NR_DRAM_CH];
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;
}; };
const struct uniphier_board_data *uniphier_get_board_param(void); 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); tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK);
switch (bd->dram_ch2_width) { switch (bd->dram_ch[2].width) {
case 16: case 16:
tmp |= SG_MEMCONF_CH2_NUM_1; tmp |= SG_MEMCONF_CH2_NUM_1;
size_per_word = bd->dram_ch2_size; size_per_word = bd->dram_ch[2].size;
break; break;
case 32: case 32:
tmp |= SG_MEMCONF_CH2_NUM_2; tmp |= SG_MEMCONF_CH2_NUM_2;
size_per_word = bd->dram_ch2_size >> 1; size_per_word = bd->dram_ch[2].size >> 1;
break; break;
default: default:
pr_err("error: unsupported DRAM Ch2 width\n"); 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); tmp &= ~(SG_MEMCONF_CH2_SZ_MASK | SG_MEMCONF_CH2_NUM_MASK);
switch (bd->dram_ch2_width) { switch (bd->dram_ch[2].width) {
case 16: case 16:
tmp |= SG_MEMCONF_CH2_NUM_1; tmp |= SG_MEMCONF_CH2_NUM_1;
size_per_word = bd->dram_ch2_size; size_per_word = bd->dram_ch[2].size;
break; break;
case 32: case 32:
tmp |= SG_MEMCONF_CH2_NUM_2; tmp |= SG_MEMCONF_CH2_NUM_2;
size_per_word = bd->dram_ch2_size >> 1; size_per_word = bd->dram_ch[2].size >> 1;
break; break;
default: default:
pr_err("error: unsupported DRAM Ch2 width\n"); 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); tmp &= ~(SG_MEMCONF_CH0_SZ_MASK | SG_MEMCONF_CH0_NUM_MASK);
switch (bd->dram_ch0_width) { switch (bd->dram_ch[0].width) {
case 16: case 16:
tmp |= SG_MEMCONF_CH0_NUM_1; tmp |= SG_MEMCONF_CH0_NUM_1;
size_per_word = bd->dram_ch0_size; size_per_word = bd->dram_ch[0].size;
break; break;
case 32: case 32:
tmp |= SG_MEMCONF_CH0_NUM_2; tmp |= SG_MEMCONF_CH0_NUM_2;
size_per_word = bd->dram_ch0_size >> 1; size_per_word = bd->dram_ch[0].size >> 1;
break; break;
default: default:
pr_err("error: unsupported DRAM Ch0 width\n"); 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); tmp &= ~(SG_MEMCONF_CH1_SZ_MASK | SG_MEMCONF_CH1_NUM_MASK);
switch (bd->dram_ch1_width) { switch (bd->dram_ch[1].width) {
case 16: case 16:
tmp |= SG_MEMCONF_CH1_NUM_1; tmp |= SG_MEMCONF_CH1_NUM_1;
size_per_word = bd->dram_ch1_size; size_per_word = bd->dram_ch[1].size;
break; break;
case 32: case 32:
tmp |= SG_MEMCONF_CH1_NUM_2; tmp |= SG_MEMCONF_CH1_NUM_2;
size_per_word = bd->dram_ch1_size >> 1; size_per_word = bd->dram_ch[1].size >> 1;
break; break;
default: default:
pr_err("error: unsupported DRAM Ch1 width\n"); pr_err("error: unsupported DRAM Ch1 width\n");
@ -94,7 +94,7 @@ int memconf_init(const struct uniphier_board_data *bd)
return -EINVAL; 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; tmp |= SG_MEMCONF_SPARSEMEM;
else else
tmp &= ~SG_MEMCONF_SPARSEMEM; tmp &= ~SG_MEMCONF_SPARSEMEM;

View File

@ -142,7 +142,8 @@ static void detect_num_flash_banks(void)
memory_bank; memory_bank;
debug("flash bank found: base = 0x%lx, size = 0x%lx\n", 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++; 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 mux_bits, unsigned reg_stride)
{ {
unsigned shift = pin * mux_bits % 32; 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 mask = (1U << mux_bits) - 1;
u32 tmp; u32 tmp;

View File

@ -15,8 +15,8 @@ enum uniphier_soc_id {
SOC_UNIPHIER_PH1_PRO5, SOC_UNIPHIER_PH1_PRO5,
SOC_UNIPHIER_PROXSTREAM2, SOC_UNIPHIER_PROXSTREAM2,
SOC_UNIPHIER_PH1_LD6B, SOC_UNIPHIER_PH1_LD6B,
SOC_UNIPHIER_PH1_SLD11, SOC_UNIPHIER_PH1_LD11,
SOC_UNIPHIER_PH1_LD10, SOC_UNIPHIER_PH1_LD20,
SOC_UNIPHIER_UNKNOWN, SOC_UNIPHIER_UNKNOWN,
}; };
@ -28,8 +28,8 @@ enum uniphier_soc_id {
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_PRO5) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_PRO5) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PROXSTREAM2) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD6B) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD6B) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_SLD11) + \ IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD11) + \
IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD10) IS_ENABLED(CONFIG_ARCH_UNIPHIER_PH1_LD20)
#define UNIPHIER_MULTI_SOC ((UNIPHIER_NR_ENABLED_SOCS) > 1) #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) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD6B)
return SOC_UNIPHIER_PH1_LD6B; return SOC_UNIPHIER_PH1_LD6B;
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_SLD11) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD11)
return SOC_UNIPHIER_PH1_SLD11; return SOC_UNIPHIER_PH1_LD11;
#endif #endif
#if defined(CONFIG_ARCH_UNIPHIER_PH1_LD10) #if defined(CONFIG_ARCH_UNIPHIER_PH1_LD20)
return SOC_UNIPHIER_PH1_LD10; return SOC_UNIPHIER_PH1_LD20;
#endif #endif
return SOC_UNIPHIER_UNKNOWN; return SOC_UNIPHIER_UNKNOWN;

View File

@ -52,14 +52,14 @@ enum uniphier_soc_id uniphier_get_soc_type(void)
ret = SOC_UNIPHIER_PH1_LD6B; ret = SOC_UNIPHIER_PH1_LD6B;
break; break;
#endif #endif
#ifdef CONFIG_ARCH_UNIPHIER_PH1_SLD11 #ifdef CONFIG_ARCH_UNIPHIER_PH1_LD11
case 0x31: case 0x31:
ret = SOC_UNIPHIER_PH1_SLD11; ret = SOC_UNIPHIER_PH1_LD11;
break; break;
#endif #endif
#ifdef CONFIG_ARCH_UNIPHIER_PH1_LD10 #ifdef CONFIG_ARCH_UNIPHIER_PH1_LD20
case 0x32: case 0x32:
ret = SOC_UNIPHIER_PH1_LD10; ret = SOC_UNIPHIER_PH1_LD20;
break; break;
#endif #endif
default: default:

View File

@ -1,8 +1,7 @@
CONFIG_ARM=y CONFIG_ARM=y
CONFIG_ARCH_UNIPHIER=y CONFIG_ARCH_UNIPHIER=y
CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_ARCH_UNIPHIER_PH1_LD4=y CONFIG_ARCH_UNIPHIER_LD4_SLD8=y
CONFIG_ARCH_UNIPHIER_PH1_SLD8=y
CONFIG_MICRO_SUPPORT_CARD=y CONFIG_MICRO_SUPPORT_CARD=y
CONFIG_SYS_TEXT_BASE=0x84000000 CONFIG_SYS_TEXT_BASE=0x84000000
CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-ld4-ref" CONFIG_DEFAULT_DEVICE_TREE="uniphier-ph1-ld4-ref"
@ -13,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set # CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set # CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8

View File

@ -12,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set # CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set # CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 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_ARM=y
CONFIG_ARCH_UNIPHIER=y CONFIG_ARCH_UNIPHIER=y
CONFIG_SYS_MALLOC_F_LEN=0x2000 CONFIG_SYS_MALLOC_F_LEN=0x2000
CONFIG_ARCH_UNIPHIER_PROXSTREAM2=y CONFIG_ARCH_UNIPHIER_PRO5_PXS2_LD6B=y
CONFIG_ARCH_UNIPHIER_PH1_LD6B=y
CONFIG_MICRO_SUPPORT_CARD=y CONFIG_MICRO_SUPPORT_CARD=y
CONFIG_SYS_TEXT_BASE=0x84000000 CONFIG_SYS_TEXT_BASE=0x84000000
CONFIG_DEFAULT_DEVICE_TREE="uniphier-proxstream2-vodka" CONFIG_DEFAULT_DEVICE_TREE="uniphier-proxstream2-vodka"
@ -13,12 +12,15 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set # CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set # CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_SIMPLE_BUS=y CONFIG_SPL_SIMPLE_BUS=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8

View File

@ -11,11 +11,14 @@ CONFIG_CMD_NAND=y
CONFIG_CMD_I2C=y CONFIG_CMD_I2C=y
CONFIG_CMD_USB=y CONFIG_CMD_USB=y
# CONFIG_CMD_FPGA is not set # CONFIG_CMD_FPGA is not set
CONFIG_CMD_GPIO=y
CONFIG_CMD_TFTPPUT=y CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_PING=y CONFIG_CMD_PING=y
CONFIG_CMD_TIME=y CONFIG_CMD_TIME=y
# CONFIG_CMD_MISC is not set # CONFIG_CMD_MISC is not set
CONFIG_NET_RANDOM_ETHADDR=y CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_GPIO_UNIPHIER=y
CONFIG_MMC_UNIPHIER=y
CONFIG_NAND_DENALI=y CONFIG_NAND_DENALI=y
CONFIG_SYS_NAND_DENALI_64BIT=y CONFIG_SYS_NAND_DENALI_64BIT=y
CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8 CONFIG_NAND_DENALI_SPARE_AREA_SKIP_BYTES=8

View File

@ -45,8 +45,8 @@ PH1-Pro4 reference board:
$ make CROSS_COMPILE=arm-linux-gnueabi- $ make CROSS_COMPILE=arm-linux-gnueabi-
PH1-Pro5 4KBOX Board: PH1-Pro5 4KBOX Board:
$ make uniphier_pro5_defconfig $ make uniphier_pxs2_ld6b_defconfig
$ make CROSS_COMPILE=arm-linux-gnueabi- $ make CROSS_COMPILE=arm-linux-gnueabi- DEVICE_TREE=uniphier-ph1-pro5-4kbox
ProXstream2 Gentil board: ProXstream2 Gentil board:
$ make uniphier_pxs2_ld6b_defconfig $ make uniphier_pxs2_ld6b_defconfig
@ -78,6 +78,20 @@ directory, and then run the following command at the U-Boot command line:
=> run nandupdate => 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 UniPhier specific commands
-------------------------- --------------------------
@ -93,8 +107,10 @@ Supported devices
- UART (on-chip) - UART (on-chip)
- NAND - NAND
- SD/eMMC
- USB 2.0 (EHCI) - USB 2.0 (EHCI)
- USB 3.0 (xHCI) - USB 3.0 (xHCI)
- GPIO
- LAN (on-board SMSC9118) - LAN (on-board SMSC9118)
- I2C - I2C
- EEPROM (connected to the on-board I2C bus) - 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. of 'anonymous' GPIOs that do not belong to any device or bank.
Select a suitable value depending on your needs. 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 config VYBRID_GPIO
bool "Vybrid GPIO driver" bool "Vybrid GPIO driver"
depends on DM depends on DM

View File

@ -43,6 +43,7 @@ oby-$(CONFIG_SX151X) += sx151x.o
obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o obj-$(CONFIG_SUNXI_GPIO) += sunxi_gpio.o
obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o obj-$(CONFIG_LPC32XX_GPIO) += lpc32xx_gpio.o
obj-$(CONFIG_STM32_GPIO) += stm32_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_ZYNQ_GPIO) += zynq_gpio.o
obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o
obj-$(CONFIG_HIKEY_GPIO) += hi6220_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 help
Support for Arasan SDHCI host controller on Zynq/ZynqMP ARM SoCs platform 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 endmenu

View File

@ -41,6 +41,7 @@ obj-$(CONFIG_SH_SDHI) += sh_sdhi.o
obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o
obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o obj-$(CONFIG_SPEAR_SDHCI) += spear_sdhci.o
obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o
obj-$(CONFIG_MMC_UNIPHIER) += uniphier-sd.o
obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o
ifdef CONFIG_SPL_BUILD 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 #define CONFIG_CONS_INDEX 1
/* /* #define CONFIG_ENV_IS_NOWHERE */
* 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_IN_NAND */ /* #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_SIZE 0x2000
#define CONFIG_ENV_OFFSET 0x0
/* #define CONFIG_ENV_OFFSET_REDUND (CONFIG_ENV_OFFSET + CONFIG_ENV_SIZE) */ /* #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 */ /* Time clock 1MHz */
#define CONFIG_SYS_TIMER_RATE 1000000 #define CONFIG_SYS_TIMER_RATE 1000000
@ -146,6 +146,11 @@
#define CONFIG_FAT_WRITE #define CONFIG_FAT_WRITE
#define CONFIG_DOS_PARTITION #define CONFIG_DOS_PARTITION
/* SD/MMC */
#define CONFIG_CMD_MMC
#define CONFIG_SUPPORT_EMMC_BOOT
#define CONFIG_GENERIC_MMC
/* memtest works on */ /* memtest works on */
#define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE #define CONFIG_SYS_MEMTEST_START CONFIG_SYS_SDRAM_BASE
#define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x01000000) #define CONFIG_SYS_MEMTEST_END (CONFIG_SYS_SDRAM_BASE + 0x01000000)
@ -228,6 +233,13 @@
"netdev=eth0\0" \ "netdev=eth0\0" \
"verify=n\0" \ "verify=n\0" \
"nor_base=0x42000000\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 &&" \ "nandupdate=nand erase 0 0x00100000 &&" \
"tftpboot u-boot-spl.bin &&" \ "tftpboot u-boot-spl.bin &&" \
"nand write $loadaddr 0 0x00010000 &&" \ "nand write $loadaddr 0 0x00010000 &&" \
@ -259,6 +271,7 @@
#define CONFIG_SPL_FRAMEWORK #define CONFIG_SPL_FRAMEWORK
#define CONFIG_SPL_SERIAL_SUPPORT #define CONFIG_SPL_SERIAL_SUPPORT
#define CONFIG_SPL_NAND_SUPPORT #define CONFIG_SPL_NAND_SUPPORT
#define CONFIG_SPL_MMC_SUPPORT
#define CONFIG_SPL_LIBCOMMON_SUPPORT /* for mem_malloc_init */ #define CONFIG_SPL_LIBCOMMON_SUPPORT /* for mem_malloc_init */
#define CONFIG_SPL_LIBGENERIC_SUPPORT #define CONFIG_SPL_LIBGENERIC_SUPPORT
@ -266,6 +279,7 @@
#define CONFIG_SPL_BOARD_INIT #define CONFIG_SPL_BOARD_INIT
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x10000 #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x10000
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x80
#define CONFIG_SPL_MAX_FOOTPRINT 0x10000 #define CONFIG_SPL_MAX_FOOTPRINT 0x10000