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