Merge git://git.denx.de/u-boot-rockchip
authorTom Rini <trini@konsulko.com>
Thu, 3 Sep 2015 18:57:09 +0000 (14:57 -0400)
committerTom Rini <trini@konsulko.com>
Thu, 3 Sep 2015 18:57:09 +0000 (14:57 -0400)
108 files changed:
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/cpu/armv7/cpu.c
arch/arm/dts/Makefile
arch/arm/dts/cros-ec-sbs.dtsi [new file with mode: 0644]
arch/arm/dts/rk3288-firefly.dts [new file with mode: 0644]
arch/arm/dts/rk3288-firefly.dtsi [new file with mode: 0644]
arch/arm/dts/rk3288-jerry.dts [new file with mode: 0644]
arch/arm/dts/rk3288-thermal.dtsi [new file with mode: 0644]
arch/arm/dts/rk3288-veyron-chromebook.dtsi [new file with mode: 0644]
arch/arm/dts/rk3288-veyron.dtsi [new file with mode: 0644]
arch/arm/dts/rk3288.dtsi [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/clock.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/cru_rk3288.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/ddr_rk3288.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/gpio.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/grf_rk3288.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/hardware.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/i2c.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/periph.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/pmu_rk3288.h [new file with mode: 0644]
arch/arm/include/asm/arch-rockchip/sdram.h [new file with mode: 0644]
arch/arm/lib/Makefile
arch/arm/mach-rockchip/Kconfig [new file with mode: 0644]
arch/arm/mach-rockchip/Makefile [new file with mode: 0644]
arch/arm/mach-rockchip/board-spl.c [new file with mode: 0644]
arch/arm/mach-rockchip/board.c [new file with mode: 0644]
arch/arm/mach-rockchip/common.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/Kconfig [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/Makefile [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/reset_rk3288.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/sdram_rk3288.c [new file with mode: 0644]
arch/arm/mach-rockchip/rk3288/syscon_rk3288.c [new file with mode: 0644]
board/firefly/firefly-rk3288/Kconfig [new file with mode: 0644]
board/firefly/firefly-rk3288/MAINTAINERS [new file with mode: 0644]
board/firefly/firefly-rk3288/Makefile [new file with mode: 0644]
board/firefly/firefly-rk3288/firefly-rk3288.c [new file with mode: 0644]
board/google/chromebook_jerry/Kconfig [new file with mode: 0644]
board/google/chromebook_jerry/MAINTAINERS [new file with mode: 0644]
board/google/chromebook_jerry/Makefile [new file with mode: 0644]
board/google/chromebook_jerry/jerry.c [new file with mode: 0644]
board/google/common/Makefile
common/image.c
configs/chromebook_jerry_defconfig [new file with mode: 0644]
configs/firefly-rk3288_defconfig [new file with mode: 0644]
doc/README.rockchip [new file with mode: 0644]
doc/device-tree-bindings/clock/rockchip,rk3188-cru.txt [new file with mode: 0644]
doc/device-tree-bindings/clock/rockchip,rk3288-cru.txt [new file with mode: 0644]
doc/device-tree-bindings/clock/rockchip,rk3288-dmc.txt [new file with mode: 0644]
doc/device-tree-bindings/clock/rockchip.txt [new file with mode: 0644]
doc/device-tree-bindings/pinctrl/rockchip,pinctrl.txt [new file with mode: 0644]
doc/device-tree-bindings/thermal/rockchip-thermal.txt [new file with mode: 0644]
drivers/clk/Makefile
drivers/clk/clk_rk3288.c [new file with mode: 0644]
drivers/core/device.c
drivers/core/root.c
drivers/core/uclass.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/rk_gpio.c [new file with mode: 0644]
drivers/i2c/Kconfig
drivers/i2c/Makefile
drivers/i2c/rk_i2c.c [new file with mode: 0644]
drivers/led/Kconfig
drivers/led/Makefile
drivers/mmc/Kconfig
drivers/mmc/Makefile
drivers/mmc/dw_mmc.c
drivers/mmc/exynos_dw_mmc.c
drivers/mmc/mmc.c
drivers/mmc/rockchip_dw_mmc.c [new file with mode: 0644]
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/pinctrl-uclass.c
drivers/pinctrl/rockchip/Makefile [new file with mode: 0644]
drivers/pinctrl/rockchip/pinctrl_rk3288.c [new file with mode: 0644]
drivers/power/pmic/Kconfig
drivers/power/pmic/Makefile
drivers/power/pmic/act8846.c [new file with mode: 0644]
drivers/power/regulator/Kconfig
drivers/power/regulator/Makefile
drivers/power/regulator/act8846.c [new file with mode: 0644]
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/serial_rockchip.c [new file with mode: 0644]
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/rk_spi.c [new file with mode: 0644]
drivers/spi/rk_spi.h [new file with mode: 0644]
include/configs/chromebook_jerry.h [new file with mode: 0644]
include/configs/firefly-rk3288.h [new file with mode: 0644]
include/configs/rk3288_common.h [new file with mode: 0644]
include/dm/pinctrl.h
include/dt-bindings/clock/rk3288-cru.h [new file with mode: 0644]
include/dt-bindings/clock/rockchip,rk808.h [new file with mode: 0644]
include/dt-bindings/pinctrl/rockchip.h [new file with mode: 0644]
include/dt-bindings/power-domain/rk3288.h [new file with mode: 0644]
include/dwmmc.h
include/image.h
include/power/act8846_pmic.h [new file with mode: 0644]
tools/Makefile
tools/imagetool.h
tools/mkimage.c
tools/rkcommon.c [new file with mode: 0644]
tools/rkcommon.h [new file with mode: 0644]
tools/rkimage.c [new file with mode: 0644]
tools/rksd.c [new file with mode: 0644]
tools/rkspi.c [new file with mode: 0644]

index 5feef97..c598f5e 100644 (file)
@@ -733,6 +733,14 @@ config TARGET_STM32F429_DISCOVERY
        bool "Support STM32F429 Discovery"
        select CPU_V7M
 
+config ARCH_ROCKCHIP
+       bool "Support Rockchip SoCs"
+       select SUPPORT_SPL
+       select SPL
+       select OF_CONTROL
+       select CPU_V7
+       select DM
+
 endchoice
 
 source "arch/arm/mach-at91/Kconfig"
@@ -767,6 +775,8 @@ source "arch/arm/mach-orion5x/Kconfig"
 
 source "arch/arm/cpu/armv7/rmobile/Kconfig"
 
+source "arch/arm/mach-rockchip/Kconfig"
+
 source "arch/arm/cpu/armv7/s5pc1xx/Kconfig"
 
 source "arch/arm/mach-socfpga/Kconfig"
index e84d6d3..1eca815 100644 (file)
@@ -55,6 +55,7 @@ machine-$(CONFIG_ARCH_NOMADIK)                += nomadik
 # TODO: rename CONFIG_ORION5X -> CONFIG_ARCH_ORION5X
 machine-$(CONFIG_ORION5X)              += orion5x
 machine-$(CONFIG_ARCH_SOCFPGA)         += socfpga
+machine-$(CONFIG_ARCH_ROCKCHIP)                += rockchip
 machine-$(CONFIG_TEGRA)                        += tegra
 machine-$(CONFIG_ARCH_UNIPHIER)                += uniphier
 machine-$(CONFIG_ARCH_VERSATILE)       += versatile
index 0b0e500..6eac5ef 100644 (file)
@@ -36,12 +36,6 @@ int cleanup_before_linux_select(int flags)
        disable_interrupts();
 #endif
 
-       /*
-        * Turn off I-cache and invalidate it
-        */
-       icache_disable();
-       invalidate_icache_all();
-
        if (flags & CBL_DISABLE_CACHES) {
                /*
                * turn off D-cache
@@ -61,7 +55,16 @@ int cleanup_before_linux_select(int flags)
                * to avoid coherency problems for kernel
                */
                invalidate_dcache_all();
+
+               icache_disable();
+               invalidate_icache_all();
        } else {
+               /*
+                * Turn off I-cache and invalidate it
+                */
+               icache_disable();
+               invalidate_icache_all();
+
                flush_dcache_all();
                invalidate_icache_all();
                icache_enable();
index c97f39d..3babe65 100644 (file)
@@ -15,6 +15,9 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \
        exynos5420-peach-pit.dtb \
        exynos5800-peach-pi.dtb \
        exynos5422-odroidxu3.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += \
+       rk3288-firefly.dtb \
+       rk3288-jerry.dtb
 dtb-$(CONFIG_TEGRA) += tegra20-harmony.dtb \
        tegra20-medcom-wide.dtb \
        tegra20-paz00.dtb \
diff --git a/arch/arm/dts/cros-ec-sbs.dtsi b/arch/arm/dts/cros-ec-sbs.dtsi
new file mode 100644 (file)
index 0000000..3f35d20
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Smart battery dts fragment for devices that use cros-ec-sbs
+ *
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+*/
+
+&i2c_tunnel {
+       battery: sbs-battery@b {
+               compatible = "sbs,sbs-battery";
+               reg = <0xb>;
+               sbs,i2c-retry-count = <2>;
+               sbs,poll-retry-count = <1>;
+       };
+};
diff --git a/arch/arm/dts/rk3288-firefly.dts b/arch/arm/dts/rk3288-firefly.dts
new file mode 100644 (file)
index 0000000..aed8d3a
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+/dts-v1/;
+#include "rk3288-firefly.dtsi"
+
+/ {
+       model = "Firefly-RK3288";
+       compatible = "firefly,firefly-rk3288", "rockchip,rk3288";
+
+       chosen {
+               stdout-path = &uart2;
+       };
+
+       config {
+               u-boot,dm-pre-reloc;
+               u-boot,boot-led = "firefly:green:power";
+       };
+};
+
+&dmc {
+       rockchip,num-channels = <2>;
+       rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+               0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+               0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+               0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+               0x5 0x0>;
+       rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+               0xa60 0x40 0x10 0x0>;
+       rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+       rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+};
+
+&ir {
+       gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+};
+
+&pinctrl {
+       u-boot,dm-pre-reloc;
+       act8846 {
+               pmic_vsel: pmic-vsel {
+                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_output_low>;
+               };
+       };
+
+       ir {
+               ir_int: ir-int {
+                       rockchip,pins = <7 0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
+
+&pwm1 {
+       status = "okay";
+};
+
+&uart2 {
+       u-boot,dm-pre-reloc;
+       reg-shift = <2>;
+};
+
+&sdmmc {
+       u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+       u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+       u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288-firefly.dtsi b/arch/arm/dts/rk3288-firefly.dtsi
new file mode 100644 (file)
index 0000000..5aec1b8
--- /dev/null
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2014, 2015 FUKAUMI Naoki <naobsd@gmail.com>
+ *
+ * SPDX-License-Identifier:     GPL-2.0+ X11
+ */
+
+#include "rk3288.dtsi"
+
+/ {
+       memory {
+               reg = <0 0x80000000>;
+       };
+
+       ext_gmac: external-gmac-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <125000000>;
+               clock-output-names = "ext_gmac";
+       };
+
+       ir: ir-receiver {
+               compatible = "gpio-ir-receiver";
+               pinctrl-names = "default";
+               pinctrl-0 = <&ir_int>;
+       };
+
+       keys: gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@0 {
+                       gpio-key,wakeup = <1>;
+                       gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+                       label = "GPIO Power";
+                       linux,code = <116>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pwr_key>;
+               };
+       };
+
+       leds {
+               u-boot,dm-pre-reloc;
+               compatible = "gpio-leds";
+
+               work {
+                       u-boot,dm-pre-reloc;
+                       gpios = <&gpio8 1 GPIO_ACTIVE_LOW>;
+                       label = "firefly:blue:user";
+                       linux,default-trigger = "rc-feedback";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&work_led>;
+               };
+
+               power {
+                       u-boot,dm-pre-reloc;
+                       gpios = <&gpio8 2 GPIO_ACTIVE_LOW>;
+                       label = "firefly:green:power";
+                       linux,default-trigger = "default-on";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&power_led>;
+               };
+       };
+
+       vcc_sys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vcc_sd: sdmmc-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sdmmc_pwr>;
+               regulator-name = "vcc_sd";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               startup-delay-us = <100000>;
+               vin-supply = <&vcc_io>;
+       };
+
+       vcc_flash: flash-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_flash";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_io>;
+       };
+
+       vcc_5v: usb-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vcc_host_5v: usb-host-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 14 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&host_vbus_drv>;
+               regulator-name = "vcc_host_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vcc_5v>;
+       };
+
+       vcc_otg_5v: usb-otg-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&otg_vbus_drv>;
+               regulator-name = "vcc_otg_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vcc_5v>;
+       };
+};
+
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+};
+
+&emmc {
+       broken-cd;
+       bus-width = <8>;
+       cap-mmc-highspeed;
+       disable-wp;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_clk>, <&emmc_cmd>, <&emmc_pwr>, <&emmc_bus8>;
+       vmmc-supply = <&vcc_io>;
+       vqmmc-supply = <&vcc_flash>;
+       status = "okay";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c5>;
+       status = "okay";
+};
+
+&i2c0 {
+       clock-frequency = <400000>;
+       status = "okay";
+
+       vdd_cpu: syr827@40 {
+               compatible = "silergy,syr827";
+               fcs,suspend-voltage-selector = <1>;
+               reg = <0x40>;
+               regulator-name = "vdd_cpu";
+               regulator-min-microvolt = <850000>;
+               regulator-max-microvolt = <1350000>;
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       vdd_gpu: syr828@41 {
+               compatible = "silergy,syr828";
+               fcs,suspend-voltage-selector = <1>;
+               reg = <0x41>;
+               regulator-name = "vdd_gpu";
+               regulator-min-microvolt = <850000>;
+               regulator-max-microvolt = <1350000>;
+               regulator-always-on;
+               vin-supply = <&vcc_sys>;
+       };
+
+       hym8563: hym8563@51 {
+               compatible = "haoyu,hym8563";
+               reg = <0x51>;
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               clock-output-names = "xin32k";
+               interrupt-parent = <&gpio7>;
+               interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&rtc_int>;
+       };
+
+       act8846: act8846@5a {
+               compatible = "active-semi,act8846";
+               reg = <0x5a>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_vsel>, <&pwr_hold>;
+               system-power-controller;
+
+               regulators {
+                       vcc_ddr: REG1 {
+                               regulator-name = "vcc_ddr";
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               regulator-always-on;
+                       };
+
+                       vcc_io: REG2 {
+                               regulator-name = "vcc_io";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd_log: REG3 {
+                               regulator-name = "vdd_log";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       vcc_20: REG4 {
+                               regulator-name = "vcc_20";
+                               regulator-min-microvolt = <2000000>;
+                               regulator-max-microvolt = <2000000>;
+                               regulator-always-on;
+                       };
+
+                       vccio_sd: REG5 {
+                               regulator-name = "vccio_sd";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-always-on;
+                       };
+
+                       vdd10_lcd: REG6 {
+                               regulator-name = "vdd10_lcd";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       vcca_18: REG7 {
+                               regulator-name = "vcca_18";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                       };
+
+                       vcca_33: REG8 {
+                               regulator-name = "vcca_33";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vcc_lan: REG9 {
+                               regulator-name = "vcc_lan";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       vdd_10: REG10 {
+                               regulator-name = "vdd_10";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-always-on;
+                       };
+
+                       vcc_18: REG11 {
+                               regulator-name = "vcc_18";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       vcc18_lcd: REG12 {
+                               regulator-name = "vcc18_lcd";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+};
+
+&i2c2 {
+       status = "okay";
+};
+
+&i2c4 {
+       status = "okay";
+};
+
+&i2c5 {
+       status = "okay";
+};
+
+&pinctrl {
+       pcfg_output_high: pcfg-output-high {
+               output-high;
+       };
+
+       pcfg_output_low: pcfg-output-low {
+               output-low;
+       };
+
+       act8846 {
+               pwr_hold: pwr-hold {
+                       rockchip,pins = <0 1 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       gmac {
+               phy_int: phy-int {
+                       rockchip,pins = <0 9 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               phy_pmeb: phy-pmeb {
+                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               phy_rst: phy-rst {
+                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       hym8563 {
+               rtc_int: rtc-int {
+                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       keys {
+               pwr_key: pwr-key {
+                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       leds {
+               power_led: power-led {
+                       rockchip,pins = <8 2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               work_led: work-led {
+                       rockchip,pins = <8 1 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdmmc {
+               sdmmc_pwr: sdmmc-pwr {
+                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       usb_host {
+               host_vbus_drv: host-vbus-drv {
+                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               usbhub_rst: usbhub-rst {
+                       rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       usb_otg {
+               otg_vbus_drv: otg-vbus-drv {
+                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&saradc {
+       vref-supply = <&vcc_18>;
+       status = "okay";
+};
+
+&sdio0 {
+       broken-cd;
+       bus-width = <4>;
+       disable-wp;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio0_bus4>, <&sdio0_cmd>, <&sdio0_clk>;
+       vmmc-supply = <&vcc_18>;
+       status = "disabled";
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       card-detect-delay = <200>;
+       disable-wp;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>;
+       vmmc-supply = <&vcc_sd>;
+       status = "okay";
+};
+
+&spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi0_clk>, <&spi0_cs0>, <&spi0_tx>, <&spi0_rx>, <&spi0_cs1>;
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_xfer>, <&uart0_cts>, <&uart0_rts>;
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
+
+&usb_host1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&usbhub_rst>;
+       status = "okay";
+};
+
+&usb_otg {
+       status = "okay";
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
+
+&wdt {
+       status = "okay";
+};
diff --git a/arch/arm/dts/rk3288-jerry.dts b/arch/arm/dts/rk3288-jerry.dts
new file mode 100644 (file)
index 0000000..da37ea8
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Google Veyron Jerry Rev 3+ board device tree source
+ *
+ * Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+/dts-v1/;
+#include "rk3288-veyron-chromebook.dtsi"
+#include "cros-ec-sbs.dtsi"
+
+/ {
+       model = "Google Jerry";
+       compatible = "google,veyron-jerry-rev7", "google,veyron-jerry-rev6",
+                    "google,veyron-jerry-rev5", "google,veyron-jerry-rev4",
+                    "google,veyron-jerry-rev3", "google,veyron-jerry",
+                    "google,veyron", "rockchip,rk3288";
+
+        chosen {
+                stdout-path = &uart2;
+        };
+
+       panel_regulator: panel-regualtor {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&lcd_enable_h>;
+               regulator-name = "panel_regulator";
+               vin-supply = <&vcc33_sys>;
+       };
+
+       vcc18_lcd: vcc18-lcd {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&avdd_1v8_disp_en>;
+               regulator-name = "vcc18_lcd";
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc18_wl>;
+       };
+
+       backlight_regulator: backlight-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bl_pwr_en>;
+               regulator-name = "backlight_regulator";
+               vin-supply = <&vcc33_sys>;
+               startup-delay-us = <15000>;
+       };
+};
+
+&gpio_keys {
+       power {
+               gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&backlight {
+       power-supply = <&backlight_regulator>;
+};
+
+&panel {
+       power-supply= <&panel_regulator>;
+};
+
+&rk808 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pmic_int_l &dvs_1 &dvs_2>;
+       dvs-gpios = <&gpio7 12 GPIO_ACTIVE_HIGH>,
+                   <&gpio7 15 GPIO_ACTIVE_HIGH>;
+
+       regulators {
+               mic_vcc: LDO_REG2 {
+                       regulator-always-on;
+                       regulator-boot-on;
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+                       regulator-name = "mic_vcc";
+                       regulator-suspend-mem-disabled;
+               };
+       };
+};
+
+&sdmmc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd_disabled &sdmmc_cd_gpio
+                       &sdmmc_bus4>;
+       disable-wp;
+};
+
+&vcc_5v {
+       enable-active-high;
+       gpio = <&gpio7 21 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&drv_5v>;
+};
+
+&vcc50_hdmi {
+       enable-active-high;
+       gpio = <&gpio5 19 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&vcc50_hdmi_en>;
+};
+
+&edp {
+       pinctrl-names = "default";
+       pinctrl-0 = <&edp_hpd>;
+};
+
+&pinctrl {
+       backlight {
+               bl_pwr_en: bl_pwr_en {
+                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       buck-5v {
+               drv_5v: drv-5v {
+                       rockchip,pins = <7 21 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       edp {
+               edp_hpd: edp_hpd {
+                       rockchip,pins = <7 11 RK_FUNC_2 &pcfg_pull_down>;
+               };
+       };
+
+       emmc {
+               /* Make sure eMMC is not in reset */
+               emmc_deassert_reset: emmc-deassert-reset {
+                       rockchip,pins = <2 9 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       hdmi {
+               vcc50_hdmi_en: vcc50-hdmi-en {
+                       rockchip,pins = <5 19 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       lcd {
+               lcd_enable_h: lcd-en {
+                       rockchip,pins = <7 14 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               avdd_1v8_disp_en: avdd-1v8-disp-en {
+                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       pmic {
+               dvs_1: dvs-1 {
+                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+
+               dvs_2: dvs-2 {
+                       rockchip,pins = <7 15 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+};
+
+&i2c4 {
+       status = "okay";
+
+       /*
+        * Trackpad pin control is shared between Elan and Synaptics devices
+        * so we have to pull it up to the bus level.
+        */
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c4_xfer &trackpad_int>;
+
+       trackpad@15 {
+               compatible = "elan,i2c_touchpad";
+               interrupt-parent = <&gpio7>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               /*
+                * Remove the inherited pinctrl settings to avoid clashing
+                * with bus-wide ones.
+                */
+               /delete-property/pinctrl-names;
+               /delete-property/pinctrl-0;
+               reg = <0x15>;
+               vcc-supply = <&vcc33_io>;
+               wakeup-source;
+       };
+
+       trackpad@2c {
+               compatible = "hid-over-i2c";
+               interrupt-parent = <&gpio7>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               reg = <0x2c>;
+               hid-descr-addr = <0x0020>;
+               vcc-supply = <&vcc33_io>;
+               wakeup-source;
+       };
+};
diff --git a/arch/arm/dts/rk3288-thermal.dtsi b/arch/arm/dts/rk3288-thermal.dtsi
new file mode 100644 (file)
index 0000000..59482c1
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Device Tree Source for RK3288 SoC thermal
+ *
+ * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+reserve_thermal: reserve_thermal {
+       polling-delay-passive = <1000>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+                       /* sensor       ID */
+       thermal-sensors = <&tsadc       0>;
+
+};
+
+cpu_thermal: cpu_thermal {
+       polling-delay-passive = <100>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+                       /* sensor       ID */
+       thermal-sensors = <&tsadc       1>;
+       linux,hwmon;
+
+       trips {
+               cpu_alert0: cpu_alert0 {
+                       temperature = <70000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu_alert1: cpu_alert1 {
+                       temperature = <75000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "passive";
+               };
+               cpu_crit: cpu_crit {
+                       temperature = <100000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&cpu_alert0>;
+                       cooling-device =
+                               <&cpu0 THERMAL_NO_LIMIT 6>;
+               };
+               map1 {
+                       trip = <&cpu_alert1>;
+                       cooling-device =
+                               <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+               };
+       };
+};
+
+gpu_thermal: gpu_thermal {
+       polling-delay-passive = <100>; /* milliseconds */
+       polling-delay = <5000>; /* milliseconds */
+
+                       /* sensor       ID */
+       thermal-sensors = <&tsadc       2>;
+       linux,hwmon;
+
+       trips {
+               gpu_alert0: gpu_alert0 {
+                       temperature = <80000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "passive";
+               };
+               gpu_crit: gpu_crit {
+                       temperature = <100000>; /* millicelsius */
+                       hysteresis = <2000>; /* millicelsius */
+                       type = "critical";
+               };
+       };
+
+       cooling-maps {
+               map0 {
+                       trip = <&gpu_alert0>;
+                       cooling-device =
+                               <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+               };
+       };
+};
diff --git a/arch/arm/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/dts/rk3288-veyron-chromebook.dtsi
new file mode 100644 (file)
index 0000000..6d619c9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Google Veyron (and derivatives) board device tree source
+ *
+ * Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <dt-bindings/clock/rockchip,rk808.h>
+#include <dt-bindings/input/input.h>
+#include "rk3288-veyron.dtsi"
+
+/ {
+       aliases {
+               i2c20 = &i2c_tunnel;
+       };
+
+       gpio_keys: gpio-keys {
+               pinctrl-0 = <&pwr_key_h &ap_lid_int_l>;
+               lid {
+                       label = "Lid";
+                       gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+                       linux,code = <0>; /* SW_LID */
+                       linux,input-type = <5>; /* EV_SW */
+                       debounce-interval = <1>;
+                       gpio-key,wakeup;
+                };
+       };
+
+       gpio-charger {
+               compatible = "gpio-charger";
+               gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ac_present_ap>;
+               charger-type = "mains";
+       };
+
+       /* A non-regulated voltage from power supply or battery */
+       vccsys: vccsys {
+               compatible = "regulator-fixed";
+               regulator-name = "vccsys";
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
+       vcc33_sys: vcc33-sys {
+               vin-supply = <&vccsys>;
+       };
+
+       vcc_5v: vcc-5v {
+               vin-supply = <&vccsys>;
+       };
+
+       /* This turns on vbus for host1 (dwc2) */
+       vcc5_host1: vcc5-host1-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 11 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&host1_pwr_en>;
+               regulator-name = "vcc5_host1";
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       /* This turns on vbus for otg for host mode (dwc2) */
+       vcc5v_otg: vcc5v-otg-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&usbotg_pwren_h>;
+               regulator-name = "vcc5_host2";
+               regulator-always-on;
+               regulator-boot-on;
+       };
+};
+
+&rk808 {
+       regulators {
+               vcc33_ccd: LDO_REG8 {
+                       regulator-always-on;
+                       regulator-boot-on;
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-name = "vcc33_ccd";
+                       regulator-suspend-mem-disabled;
+               };
+       };
+};
+
+&spi0 {
+       status = "okay";
+
+       cros_ec: ec@0 {
+               compatible = "google,cros-ec-spi";
+               spi-max-frequency = <3000000>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ec_int>;
+               reg = <0>;
+               google,cros-ec-spi-pre-delay = <30>;
+
+               i2c_tunnel: i2c-tunnel {
+                       compatible = "google,cros-ec-i2c-tunnel";
+                       google,remote-bus = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+};
+
+&i2c4 {
+       trackpad@15 {
+               compatible = "elan,i2c_touchpad";
+               interrupt-parent = <&gpio7>;
+               interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&trackpad_int>;
+               reg = <0x15>;
+               vcc-supply = <&vcc33_io>;
+               wakeup-source;
+       };
+};
+
+&pinctrl {
+       pinctrl-0 = <
+               /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
+               &global_pwroff
+
+               /* Wake only */
+               &suspend_l_wake
+               &bt_dev_wake_awake
+       >;
+       pinctrl-1 = <
+               /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
+               &global_pwroff
+
+               /* Sleep only */
+               &suspend_l_sleep
+               &bt_dev_wake_sleep
+       >;
+
+       buttons {
+               ap_lid_int_l: ap-lid-int-l {
+                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       charger {
+               ac_present_ap: ac-present-ap {
+                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       cros-ec {
+               ec_int: ec-int {
+                       rockchip,pins = <7 7 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdmmc {
+               sdmmc_wp_gpio: sdmmc-wp-gpio {
+                       rockchip,pins = <7 10 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       suspend {
+               suspend_l_wake: suspend-l-wake {
+                       rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_output_low>;
+               };
+
+               suspend_l_sleep: suspend-l-sleep {
+                       rockchip,pins = <0 17 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       trackpad {
+               trackpad_int: trackpad-int {
+                       rockchip,pins = <7 3 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       usb-host {
+               host1_pwr_en: host1-pwr-en {
+                       rockchip,pins = <0 11 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               usbotg_pwren_h: usbotg-pwren-h {
+                       rockchip,pins = <0 12 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+#include "cros-ec-keyboard.dtsi"
diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi
new file mode 100644 (file)
index 0000000..7e37158
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * Google Veyron (and derivatives) board device tree source
+ *
+ * Copyright 2014 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <dt-bindings/clock/rockchip,rk808.h>
+#include <dt-bindings/input/input.h>
+#include "rk3288.dtsi"
+
+/ {
+       memory {
+               reg = <0x0 0x80000000>;
+       };
+
+       chosen {
+               stdout-path = &uart2;
+       };
+
+       config {
+               u-boot,dm-pre-reloc;
+               u-boot,boot0 = &spi_flash;
+       };
+
+       firmware {
+               chromeos {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&fw_wp_ap>;
+                       write-protect-gpio = <&gpio7 6 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               brightness-levels = <
+                         0   1   2   3   4   5   6   7
+                         8   9  10  11  12  13  14  15
+                        16  17  18  19  20  21  22  23
+                        24  25  26  27  28  29  30  31
+                        32  33  34  35  36  37  38  39
+                        40  41  42  43  44  45  46  47
+                        48  49  50  51  52  53  54  55
+                        56  57  58  59  60  61  62  63
+                        64  65  66  67  68  69  70  71
+                        72  73  74  75  76  77  78  79
+                        80  81  82  83  84  85  86  87
+                        88  89  90  91  92  93  94  95
+                        96  97  98  99 100 101 102 103
+                       104 105 106 107 108 109 110 111
+                       112 113 114 115 116 117 118 119
+                       120 121 122 123 124 125 126 127
+                       128 129 130 131 132 133 134 135
+                       136 137 138 139 140 141 142 143
+                       144 145 146 147 148 149 150 151
+                       152 153 154 155 156 157 158 159
+                       160 161 162 163 164 165 166 167
+                       168 169 170 171 172 173 174 175
+                       176 177 178 179 180 181 182 183
+                       184 185 186 187 188 189 190 191
+                       192 193 194 195 196 197 198 199
+                       200 201 202 203 204 205 206 207
+                       208 209 210 211 212 213 214 215
+                       216 217 218 219 220 221 222 223
+                       224 225 226 227 228 229 230 231
+                       232 233 234 235 236 237 238 239
+                       240 241 242 243 244 245 246 247
+                       248 249 250 251 252 253 254 255>;
+               default-brightness-level = <128>;
+               enable-gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+               backlight-boot-off;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bl_en>;
+               pwms = <&pwm0 0 1000000 0>;
+       };
+
+       panel: panel {
+               compatible ="cnm,n116bgeea2","simple-panel";
+               status = "okay";
+               power-supply = <&vcc33_lcd>;
+               backlight = <&backlight>;
+       };
+
+       gpio_keys: gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwr_key_h>;
+               power {
+                       label = "Power";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+                       linux,code = <KEY_POWER>;
+                       debounce-interval = <100>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       gpio-restart {
+               compatible = "gpio-restart";
+               gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ap_warm_reset_h>;
+               priority = /bits/ 8 <200>;
+       };
+
+       sound {
+               compatible = "rockchip,rockchip-audio-max98090";
+               rockchip,model = "ROCKCHIP-I2S";
+               rockchip,i2s-controller = <&i2s>;
+               rockchip,audio-codec = <&max98090>;
+               rockchip,hp-det-gpios = <&gpio6 5 GPIO_ACTIVE_HIGH>;
+               rockchip,mic-det-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+               rockchip,headset-codec = <&headsetcodec>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&mic_det>, <&hp_det>;
+       };
+
+       vdd_logic: pwm-regulator {
+               compatible = "pwm-regulator";
+               pwms = <&pwm1 0 2000 0>;
+
+               voltage-table = <1350000 0>,
+                               <1300000 10>,
+                               <1250000 20>,
+                               <1200000 31>,
+                               <1150000 41>,
+                               <1100000 52>,
+                               <1050000 62>,
+                               <1000000 72>,
+                               < 950000 83>;
+
+               regulator-min-microvolt = <950000>;
+               regulator-max-microvolt = <1350000>;
+               regulator-name = "vdd_logic";
+               regulator-ramp-delay = <4000>;
+       };
+
+       vcc33_sys: vcc33-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc33_sys";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vccsys>;
+       };
+
+       vcc_5v: vcc-5v {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_5v";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       vcc50_hdmi: vcc50-hdmi {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc50_hdmi";
+               regulator-always-on;
+               regulator-boot-on;
+               vin-supply = <&vcc_5v>;
+       };
+
+       bt_regulator: bt-regulator {
+               /*
+                * On the module itself this is one of these (depending
+                * on the actual card pouplated):
+                * - BT_I2S_WS_BT_RFDISABLE_L
+                * - No connect
+                */
+
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bt_enable_l>;
+               regulator-name = "bt_regulator";
+       };
+
+       wifi_regulator: wifi-regulator {
+               /*
+                * On the module itself this is one of these (depending
+                * on the actual card populated):
+                * - SDIO_RESET_L_WL_REG_ON
+                * - PDN (power down when low)
+                */
+
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio4 28 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&wifi_enable_h>;
+               regulator-name = "wifi_regulator";
+
+               /* Faux input supply.  See bt_regulator description. */
+               vin-supply = <&bt_regulator>;
+       };
+
+       io-domains {
+               compatible = "rockchip,rk3288-io-voltage-domain";
+               rockchip,grf = <&grf>;
+
+               audio-supply = <&vcc18_codec>;
+               bb-supply = <&vcc33_io>;
+               dvp-supply = <&vcc_18>;
+               flash0-supply = <&vcc18_flashio>;
+               gpio1830-supply = <&vcc33_io>;
+               gpio30-supply = <&vcc33_io>;
+               lcdc-supply = <&vcc33_lcd>;
+               sdcard-supply = <&vccio_sd>;
+               wifi-supply = <&vcc18_wl>;
+       };
+};
+
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+};
+
+&dmc {
+       logic-supply = <&vdd_logic>;
+       rockchip,odt-disable-freq = <333000000>;
+       rockchip,dll-disable-freq = <333000000>;
+       rockchip,sr-enable-freq = <333000000>;
+       rockchip,pd-enable-freq = <666000000>;
+       rockchip,auto-self-refresh-cnt = <0>;
+       rockchip,auto-power-down-cnt = <64>;
+       rockchip,ddr-speed-bin = <21>;
+       rockchip,trcd = <10>;
+       rockchip,trp = <10>;
+       operating-points = <
+               /* KHz    uV */
+               200000 1050000
+               333000 1100000
+               533000 1150000
+               666000 1200000
+       >;
+       rockchip,num-channels = <2>;
+       rockchip,pctl-timing = <0x29a 0xc8 0x1f8 0x42 0x4e 0x4 0xea 0xa
+               0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+               0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+               0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+               0x5 0x0>;
+       rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+               0xa60 0x40 0x10 0x0>;
+       rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+       rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+};
+
+&efuse {
+       status = "okay";
+};
+
+&emmc {
+       broken-cd;
+       bus-width = <8>;
+       cap-mmc-highspeed;
+       mmc-hs200-1_8v;
+       disable-wp;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8 &emmc_deassert_reset>;
+       status = "okay";
+};
+
+&sdio0 {
+       broken-cd;
+       bus-width = <4>;
+       cap-sd-highspeed;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       cap-sdio-irq;
+       card-external-vcc-supply = <&wifi_regulator>;
+       clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>, <&cru SCLK_SDIO0_DRV>,
+                <&cru SCLK_SDIO0_SAMPLE>, <&rk808 RK808_CLKOUT1>;
+       clock-names = "biu", "ciu", "ciu_drv", "ciu_sample", "card_ext_clock";
+       keep-power-in-suspend;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdio0_clk &sdio0_cmd &sdio0_bus4>;
+       status = "okay";
+       vmmc-supply = <&vcc33_sys>;
+       vqmmc-supply = <&vcc18_wl>;
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       card-detect-delay = <200>;
+       cd-gpios = <&gpio7 5 GPIO_ACTIVE_LOW>;
+       num-slots = <1>;
+       status = "okay";
+       vmmc-supply = <&vcc33_sd>;
+       vqmmc-supply = <&vccio_sd>;
+};
+
+&spi2 {
+       status = "okay";
+       u-boot,dm-pre-reloc;
+
+       spi_flash: spiflash@0 {
+               u-boot,dm-pre-reloc;
+               compatible = "spidev", "spi-flash";
+               spi-max-frequency = <20000000>; /* Reduce for Dediprog em100 pro */
+               reg = <0>;
+       };
+};
+
+&i2c0 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+       i2c-scl-falling-time-ns = <50>;         /* 2.5ns measured */
+       i2c-scl-rising-time-ns = <100>;         /* 45ns measured */
+
+       rk808: pmic@1b {
+               compatible = "rockchip,rk808";
+               clock-output-names = "xin32k", "wifibt_32kin";
+               interrupt-parent = <&gpio0>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int_l>;
+               reg = <0x1b>;
+               rockchip,system-power-controller;
+               wakeup-source;
+               #clock-cells = <1>;
+
+               vcc1-supply = <&vcc33_sys>;
+               vcc2-supply = <&vcc33_sys>;
+               vcc3-supply = <&vcc33_sys>;
+               vcc4-supply = <&vcc33_sys>;
+               vcc6-supply = <&vcc_5v>;
+               vcc7-supply = <&vcc33_sys>;
+               vcc8-supply = <&vcc33_sys>;
+               vcc9-supply = <&vcc_5v>;
+               vcc10-supply = <&vcc33_sys>;
+               vcc11-supply = <&vcc_5v>;
+               vcc12-supply = <&vcc_18>;
+
+               vddio-supply = <&vcc33_io>;
+
+               regulators {
+                       vdd_cpu: DCDC_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1450000>;
+                               regulator-name = "vdd_arm";
+                               regulator-ramp-delay = <6001>;
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vdd_gpu: DCDC_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1250000>;
+                               regulator-name = "vdd_gpu";
+                               regulator-ramp-delay = <6001>;
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vcc135_ddr: DCDC_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc135_ddr";
+                               regulator-suspend-mem-enabled;
+                       };
+
+                       /*
+                        * vcc_18 has several aliases.  (vcc18_flashio and
+                        * vcc18_wl).  We'll add those aliases here just to
+                        * make it easier to follow the schematic.  The signals
+                        * are actually hooked together and only separated for
+                        * power measurement purposes).
+                        */
+                       vcc18_wl: vcc18_flashio: vcc_18: DCDC_REG4 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc_18";
+                               regulator-suspend-mem-microvolt = <1800000>;
+                       };
+
+                       /*
+                        * Note that both vcc33_io and vcc33_pmuio are always
+                        * powered together. To simplify the logic in the dts
+                        * we just refer to vcc33_io every time something is
+                        * powered from vcc33_pmuio. In fact, on later boards
+                        * (such as danger) they're the same net.
+                        */
+                       vcc33_io: LDO_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33_io";
+                               regulator-suspend-mem-microvolt = <3300000>;
+                       };
+
+                       vdd_10: LDO_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-name = "vdd_10";
+                               regulator-suspend-mem-microvolt = <1000000>;
+                       };
+
+                       vccio_sd: LDO_REG4 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vccio_sd";
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vcc33_sd: LDO_REG5 {
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33_sd";
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vcc18_codec: LDO_REG6 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18_codec";
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vdd10_lcd_pwren_h: LDO_REG7 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-name = "vdd10_lcd_pwren_h";
+                               regulator-suspend-mem-disabled;
+                       };
+
+                       vcc33_lcd: SWITCH_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc33_lcd";
+                               regulator-suspend-mem-disabled;
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+       i2c-scl-falling-time-ns = <50>;         /* 2.5ns measured */
+       i2c-scl-rising-time-ns = <100>;         /* 40ns measured */
+
+       tpm: tpm@20 {
+               compatible = "infineon,slb9645tt";
+               reg = <0x20>;
+               powered-while-suspended;
+       };
+};
+
+&i2c2 {
+       status = "okay";
+
+       /* 100kHz since 4.7k resistors don't rise fast enough */
+       clock-frequency = <100000>;
+       i2c-scl-falling-time-ns = <50>;         /* 10ns measured */
+       i2c-scl-rising-time-ns = <800>;         /* 600ns measured */
+
+       max98090: max98090@10 {
+               compatible = "maxim,max98090";
+               reg = <0x10>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&int_codec>;
+       };
+};
+
+&i2c3 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+};
+
+&i2c4 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+       i2c-scl-falling-time-ns = <50>;         /* 11ns measured */
+       i2c-scl-rising-time-ns = <300>;         /* 225ns measured */
+
+       headsetcodec: ts3a227e@3b {
+               compatible = "ti,ts3a227e";
+               reg = <0x3b>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ts3a227e_int_l>;
+               ti,micbias = <7>;               /* MICBIAS = 2.8V */
+       };
+};
+
+&i2c5 {
+       status = "okay";
+
+       clock-frequency = <100000>;
+       i2c-scl-falling-time-ns = <300>;
+       i2c-scl-rising-time-ns = <1000>;
+};
+
+&i2s {
+       status = "okay";
+       clock-names = "i2s_hclk", "i2s_clk", "i2s_clk_out";
+       clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>, <&cru SCLK_I2S0_OUT>;
+};
+
+&wdt {
+       status = "okay";
+};
+
+&pwm0 {
+       status = "okay";
+};
+
+&pwm1 {
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+
+       /* Pins don't include flow control by default; add that in */
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+       /* We need to go faster than 24MHz, so adjust clock parents / rates */
+       assigned-clocks = <&cru SCLK_UART0>;
+       assigned-clock-rates = <48000000>;
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+       u-boot,dm-pre-reloc;
+       reg-shift = <2>;
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
+
+&edp {
+       status = "okay";
+       rockchip,panel = <&panel>;
+};
+
+&hdmi {
+       status = "okay";
+};
+
+&hdmi_audio {
+       status = "okay";
+};
+
+&gpu {
+       status = "okay";
+};
+
+&tsadc {
+       tsadc-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
+       tsadc-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+       status = "okay";
+};
+
+&pinctrl {
+       u-boot,dm-pre-reloc;
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <
+               /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
+               &global_pwroff
+
+               /* Wake only */
+               &bt_dev_wake_awake
+       >;
+       pinctrl-1 = <
+               /* Common for sleep and wake, but no owners */
+               &ddr0_retention
+               &ddrio_pwroff
+               &global_pwroff
+
+               /* Sleep only */
+               &bt_dev_wake_sleep
+       >;
+
+       /* Add this for sdmmc pins to SD card */
+       pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+               drive-strength = <8>;
+       };
+
+       pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+               bias-pull-up;
+               drive-strength = <8>;
+       };
+
+       pcfg_output_high: pcfg-output-high {
+               output-high;
+       };
+
+       pcfg_output_low: pcfg-output-low {
+               output-low;
+       };
+
+       backlight {
+               bl_en: bl-en {
+                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       buttons {
+               pwr_key_h: pwr-key-h {
+                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       codec {
+               hp_det: hp-det {
+                       rockchip,pins = <6 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+               int_codec: int-codec {
+                       rockchip,pins = <6 7 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+               mic_det: mic-det {
+                       rockchip,pins = <6 11 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       emmc {
+               /* Make sure eMMC is not in reset */
+               emmc_deassert_reset: emmc-deassert-reset {
+                       rockchip,pins = <7 12 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               /*
+                * We run eMMC at max speed; bump up drive strength.
+                * We also have external pulls, so disable the internal ones.
+                */
+               emmc_clk: emmc-clk {
+                       rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+               };
+
+               emmc_cmd: emmc-cmd {
+                       rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+               };
+
+               emmc_bus8: emmc-bus8 {
+                       rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 1 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 2 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 3 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 4 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 5 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 6 RK_FUNC_2 &pcfg_pull_none_drv_8ma>,
+                                       <3 7 RK_FUNC_2 &pcfg_pull_none_drv_8ma>;
+               };
+       };
+
+       headset {
+               ts3a227e_int_l: ts3a227e-int-l {
+                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       pmic {
+               pmic_int_l: pmic-int-l {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       reboot {
+               ap_warm_reset_h: ap-warm-reset-h {
+                       rockchip,pins = <RK_GPIO0 13 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdio0 {
+               wifi_enable_h: wifienable-h {
+                       rockchip,pins = <4 28 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               /* NOTE: mislabelled on schematic; should be bt_enable_h */
+               bt_enable_l: bt-enable-l {
+                       rockchip,pins = <4 29 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               /*
+                * We run sdio0 at max speed; bump up drive strength.
+                * We also have external pulls, so disable the internal ones.
+                */
+               sdio0_bus4: sdio0-bus4 {
+                       rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <4 21 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <4 22 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <4 23 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               sdio0_cmd: sdio0-cmd {
+                       rockchip,pins = <4 24 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               sdio0_clk: sdio0-clk {
+                       rockchip,pins = <4 25 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               /*
+                * These pins are only present on very new veyron boards; on
+                * older boards bt_dev_wake is simply always high.  Note that
+                * gpio4_26 is a NC on old veyron boards, so it doesn't hurt
+                * to map this pin everywhere
+                */
+               bt_dev_wake_sleep: bt-dev-wake-sleep {
+                       rockchip,pins = <4 26 RK_FUNC_GPIO &pcfg_output_low>;
+               };
+
+               bt_dev_wake_awake: bt-dev-wake-awake {
+                       rockchip,pins = <4 26 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       sdmmc {
+               /*
+                * We run sdmmc at max speed; bump up drive strength.
+                * We also have external pulls, so disable the internal ones.
+                */
+               sdmmc_bus4: sdmmc-bus4 {
+                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <6 17 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <6 18 RK_FUNC_1 &pcfg_pull_none_drv_8ma>,
+                                       <6 19 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               sdmmc_clk: sdmmc-clk {
+                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               sdmmc_cmd: sdmmc-cmd {
+                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
+               };
+
+               /*
+                * Builtin CD line is hooked to ground to prevent JTAG at boot
+                * (and also to get the voltage rail correct).  Make we
+                * configure gpio6_C6 as GPIO so dw_mmc builtin CD doesn't
+                * think there's a card inserted
+                */
+               sdmmc_cd_disabled: sdmmc-cd-disabled {
+                       rockchip,pins = <6 22 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               /* This is where we actually hook up CD */
+               sdmmc_cd_gpio: sdmmc-cd-gpio {
+                       rockchip,pins = <7 5 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       tpm {
+               tpm_int_h: tpm-int-h {
+                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       write-protect {
+               fw_wp_ap: fw-wp-ap {
+                       rockchip,pins = <7 6 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&usbphy {
+       status = "okay";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+       needs-reset-on-resume;
+};
+
+&usb_host1 {
+       status = "okay";
+};
+
+&usb_otg {
+       dr_mode = "host";
+       status = "okay";
+       assigned-clocks = <&cru SCLK_USBPHY480M_SRC>;
+       assigned-clock-parents = <&cru SCLK_OTGPHY0>;
+};
+
+&sdmmc {
+       u-boot,dm-pre-reloc;
+};
+
+&gpio3 {
+       u-boot,dm-pre-reloc;
+};
+
+&gpio8 {
+       u-boot,dm-pre-reloc;
+};
diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi
new file mode 100644 (file)
index 0000000..0f49709
--- /dev/null
@@ -0,0 +1,1473 @@
+/*
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/clock/rk3288-cru.h>
+#include <dt-bindings/power-domain/rk3288.h>
+#include <dt-bindings/thermal/thermal.h>
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "rockchip,rk3288";
+
+       interrupt-parent = <&gic>;
+       aliases {
+               gpio0 = &gpio0;
+               gpio1 = &gpio1;
+               gpio2 = &gpio2;
+               gpio3 = &gpio3;
+               gpio4 = &gpio4;
+               gpio5 = &gpio5;
+               gpio6 = &gpio6;
+               gpio7 = &gpio7;
+               gpio8 = &gpio8;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+               i2c4 = &i2c4;
+               i2c5 = &i2c5;
+               mmc0 = &emmc;
+               mmc1 = &sdmmc;
+               mmc2 = &sdio0;
+               mmc3 = &sdio1;
+               mshc0 = &emmc;
+               mshc1 = &sdmmc;
+               mshc2 = &sdio0;
+               mshc3 = &sdio1;
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               serial3 = &uart3;
+               serial4 = &uart4;
+               spi0 = &spi0;
+               spi1 = &spi1;
+               spi2 = &spi2;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               enable-method = "rockchip,rk3066-smp";
+               rockchip,pmu = <&pmu>;
+
+               cpu0: cpu@500 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a12";
+                       reg = <0x500>;
+                       operating-points = <
+                               /* KHz    uV */
+                               1800000 1400000
+                               1704000 1350000
+                               1608000 1300000
+                               1512000 1250000
+                               1416000 1200000
+                               1200000 1100000
+                               1008000 1050000
+                                816000 1000000
+                                696000  950000
+                                600000  900000
+                                408000  900000
+                                216000  900000
+                                126000  900000
+                       >;
+                       #cooling-cells = <2>; /* min followed by max */
+                       clock-latency = <40000>;
+                       clocks = <&cru ARMCLK>;
+                       resets = <&cru SRST_CORE0>;
+               };
+               cpu@501 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a12";
+                       reg = <0x501>;
+                       resets = <&cru SRST_CORE1>;
+               };
+               cpu@502 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a12";
+                       reg = <0x502>;
+                       resets = <&cru SRST_CORE2>;
+               };
+               cpu@503 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a12";
+                       reg = <0x503>;
+                       resets = <&cru SRST_CORE3>;
+               };
+       };
+
+       amba {
+               compatible = "arm,amba-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               dmac_peri: dma-controller@ff250000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       broken-no-flushp;
+                       reg = <0xff250000 0x4000>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       clocks = <&cru ACLK_DMAC2>;
+                       clock-names = "apb_pclk";
+               };
+
+               dmac_bus_ns: dma-controller@ff600000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       broken-no-flushp;
+                       reg = <0xff600000 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       clocks = <&cru ACLK_DMAC1>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               dmac_bus_s: dma-controller@ffb20000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       broken-no-flushp;
+                       reg = <0xffb20000 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       clocks = <&cru ACLK_DMAC1>;
+                       clock-names = "apb_pclk";
+               };
+       };
+
+       xin24m: oscillator {
+               compatible = "fixed-clock";
+               clock-frequency = <24000000>;
+               clock-output-names = "xin24m";
+               #clock-cells = <0>;
+       };
+
+       timer {
+               arm,use-physical-timer;
+               compatible = "arm,armv7-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clock-frequency = <24000000>;
+               always-on;
+       };
+
+       display-subsystem {
+               compatible = "rockchip,display-subsystem";
+               ports = <&vopl_out>, <&vopb_out>;
+       };
+
+       sdmmc: dwmmc@ff0c0000 {
+               compatible = "rockchip,rk3288-dw-mshc";
+               clock-freq-min-max = <400000 150000000>;
+               clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
+                        <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
+               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               fifo-depth = <0x100>;
+               interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+               reg = <0xff0c0000 0x4000>;
+               status = "disabled";
+       };
+
+       sdio0: dwmmc@ff0d0000 {
+               compatible = "rockchip,rk3288-dw-mshc";
+               clock-freq-min-max = <400000 150000000>;
+               clocks = <&cru HCLK_SDIO0>, <&cru SCLK_SDIO0>,
+                        <&cru SCLK_SDIO0_DRV>, <&cru SCLK_SDIO0_SAMPLE>;
+               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               fifo-depth = <0x100>;
+               interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+               reg = <0xff0d0000 0x4000>;
+               status = "disabled";
+       };
+
+       sdio1: dwmmc@ff0e0000 {
+               compatible = "rockchip,rk3288-dw-mshc";
+               clock-freq-min-max = <400000 150000000>;
+               clocks = <&cru HCLK_SDIO1>, <&cru SCLK_SDIO1>,
+                        <&cru SCLK_SDIO1_DRV>, <&cru SCLK_SDIO1_SAMPLE>;
+               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               fifo-depth = <0x100>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               reg = <0xff0e0000 0x4000>;
+               status = "disabled";
+       };
+
+       emmc: dwmmc@ff0f0000 {
+               compatible = "rockchip,rk3288-dw-mshc";
+               clock-freq-min-max = <400000 150000000>;
+               clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>,
+                        <&cru SCLK_EMMC_DRV>, <&cru SCLK_EMMC_SAMPLE>;
+               clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
+               fifo-depth = <0x100>;
+               interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+               reg = <0xff0f0000 0x4000>;
+               status = "disabled";
+       };
+
+       saradc: saradc@ff100000 {
+               compatible = "rockchip,saradc";
+               reg = <0xff100000 0x100>;
+               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+               #io-channel-cells = <1>;
+               clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+               clock-names = "saradc", "apb_pclk";
+               status = "disabled";
+       };
+
+       spi0: spi@ff110000 {
+               compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
+               clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
+               clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 11>, <&dmac_peri 12>;
+               dma-names = "tx", "rx";
+               interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
+               reg = <0xff110000 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       spi1: spi@ff120000 {
+               compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
+               clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
+               clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 13>, <&dmac_peri 14>;
+               dma-names = "tx", "rx";
+               interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
+               reg = <0xff120000 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       spi2: spi@ff130000 {
+               compatible = "rockchip,rk3288-spi", "rockchip,rk3066-spi";
+               clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
+               clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac_peri 15>, <&dmac_peri 16>;
+               dma-names = "tx", "rx";
+               interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
+               reg = <0xff130000 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@ff140000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff140000 0x1000>;
+               interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C1>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c1_xfer>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@ff150000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff150000 0x1000>;
+               interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C3>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c3_xfer>;
+               status = "disabled";
+       };
+
+       i2c4: i2c@ff160000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff160000 0x1000>;
+               interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C4>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c4_xfer>;
+               status = "disabled";
+       };
+
+       i2c5: i2c@ff170000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff170000 0x1000>;
+               interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C5>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c5_xfer>;
+               status = "disabled";
+       };
+       uart0: serial@ff180000 {
+               compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+               reg = <0xff180000 0x100>;
+               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+               clock-names = "baudclk", "apb_pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart0_xfer>;
+               status = "disabled";
+       };
+
+       uart1: serial@ff190000 {
+               compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+               reg = <0xff190000 0x100>;
+               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+               clock-names = "baudclk", "apb_pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart1_xfer>;
+               status = "disabled";
+       };
+
+       uart2: serial@ff690000 {
+               compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+               reg = <0xff690000 0x100>;
+               interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+               clock-names = "baudclk", "apb_pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart2_xfer>;
+               status = "disabled";
+       };
+       uart3: serial@ff1b0000 {
+               compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+               reg = <0xff1b0000 0x100>;
+               interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART3>, <&cru PCLK_UART3>;
+               clock-names = "baudclk", "apb_pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart3_xfer>;
+               status = "disabled";
+       };
+
+       uart4: serial@ff1c0000 {
+               compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
+               reg = <0xff1c0000 0x100>;
+               interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <4>;
+               clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
+               clock-names = "baudclk", "apb_pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart4_xfer>;
+               status = "disabled";
+       };
+       thermal: thermal-zones {
+               #include "rk3288-thermal.dtsi"
+       };
+
+       tsadc: tsadc@ff280000 {
+               compatible = "rockchip,rk3288-tsadc";
+               reg = <0xff280000 0x100>;
+               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+               clock-names = "tsadc", "apb_pclk";
+               resets = <&cru SRST_TSADC>;
+               reset-names = "tsadc-apb";
+               pinctrl-names = "otp_out";
+               pinctrl-0 = <&otp_out>;
+               #thermal-sensor-cells = <1>;
+               hw-shut-temp = <125000>;
+               status = "disabled";
+       };
+
+       gmac: ethernet@ff290000 {
+               compatible = "rockchip,rk3288-gmac";
+               reg = <0xff290000 0x10000>;
+               interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "macirq";
+               rockchip,grf = <&grf>;
+               clocks = <&cru SCLK_MAC>,
+                       <&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>,
+                       <&cru SCLK_MACREF>, <&cru SCLK_MACREF_OUT>,
+                       <&cru ACLK_GMAC>, <&cru PCLK_GMAC>;
+               clock-names = "stmmaceth",
+                       "mac_clk_rx", "mac_clk_tx",
+                       "clk_mac_ref", "clk_mac_refout",
+                       "aclk_mac", "pclk_mac";
+       };
+
+       usb_host0_ehci: usb@ff500000 {
+               compatible = "generic-ehci";
+               reg = <0xff500000 0x100>;
+               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru HCLK_USBHOST0>;
+               clock-names = "usbhost";
+               phys = <&usbphy1>;
+               phy-names = "usb";
+               status = "disabled";
+       };
+
+       /* NOTE: ohci@ff520000 doesn't actually work on hardware */
+
+       usb_host1: usb@ff540000 {
+               compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb",
+                               "snps,dwc2";
+               reg = <0xff540000 0x40000>;
+               interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru HCLK_USBHOST1>;
+               clock-names = "otg";
+               phys = <&usbphy2>;
+               phy-names = "usb2-phy";
+               status = "disabled";
+       };
+
+       usb_otg: usb@ff580000 {
+               compatible = "rockchip,rk3288-usb", "rockchip,rk3066-usb",
+                               "snps,dwc2";
+               reg = <0xff580000 0x40000>;
+               interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru HCLK_OTG0>;
+               clock-names = "otg";
+               phys = <&usbphy0>;
+               phy-names = "usb2-phy";
+               status = "disabled";
+       };
+
+       usb_hsic: usb@ff5c0000 {
+               compatible = "generic-ehci";
+               reg = <0xff5c0000 0x100>;
+               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru HCLK_HSIC>;
+               clock-names = "usbhost";
+               status = "disabled";
+       };
+
+       dmc: dmc@ff610000 {
+               u-boot,dm-pre-reloc;
+               compatible = "rockchip,rk3288-dmc", "syscon";
+               rockchip,cru = <&cru>;
+               rockchip,grf = <&grf>;
+               rockchip,pmu = <&pmu>;
+               rockchip,sgrf = <&sgrf>;
+               rockchip,noc = <&noc>;
+               reg = <0xff610000 0x3fc
+                      0xff620000 0x294
+                      0xff630000 0x3fc
+                      0xff640000 0x294>;
+               rockchip,sram = <&ddr_sram>;
+               clocks = <&cru PCLK_DDRUPCTL0>, <&cru PCLK_PUBL0>,
+                        <&cru PCLK_DDRUPCTL1>, <&cru PCLK_PUBL1>,
+                        <&cru ARMCLK>;
+               clock-names = "pclk_ddrupctl0", "pclk_publ0",
+                             "pclk_ddrupctl1", "pclk_publ1",
+                             "arm_clk";
+       };
+
+       i2c0: i2c@ff650000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff650000 0x1000>;
+               interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c0_xfer>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@ff660000 {
+               compatible = "rockchip,rk3288-i2c";
+               reg = <0xff660000 0x1000>;
+               interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-names = "i2c";
+               clocks = <&cru PCLK_I2C2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c2_xfer>;
+               status = "disabled";
+       };
+
+       pwm0: pwm@ff680000 {
+               compatible = "rockchip,rk3288-pwm";
+               reg = <0xff680000 0x10>;
+               #pwm-cells = <3>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm0_pin>;
+               clocks = <&cru PCLK_PWM>;
+               clock-names = "pwm";
+               rockchip,grf = <&grf>;
+               status = "disabled";
+       };
+
+       pwm1: pwm@ff680010 {
+               compatible = "rockchip,rk3288-pwm";
+               reg = <0xff680010 0x10>;
+               #pwm-cells = <3>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm1_pin>;
+               clocks = <&cru PCLK_PWM>;
+               clock-names = "pwm";
+               rockchip,grf = <&grf>;
+               status = "disabled";
+       };
+
+       pwm2: pwm@ff680020 {
+               compatible = "rockchip,rk3288-pwm";
+               reg = <0xff680020 0x10>;
+               #pwm-cells = <3>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm2_pin>;
+               clocks = <&cru PCLK_PWM>;
+               clock-names = "pwm";
+               rockchip,grf = <&grf>;
+               status = "disabled";
+       };
+
+       pwm3: pwm@ff680030 {
+               compatible = "rockchip,rk3288-pwm";
+               reg = <0xff680030 0x10>;
+               #pwm-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm3_pin>;
+               clocks = <&cru PCLK_PWM>;
+               clock-names = "pwm";
+               rockchip,grf = <&grf>;
+               status = "disabled";
+       };
+
+       bus_intmem@ff700000 {
+               compatible = "mmio-sram";
+               reg = <0xff700000 0x18000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0 0xff700000 0x18000>;
+               smp-sram@0 {
+                       compatible = "rockchip,rk3066-smp-sram";
+                       reg = <0x00 0x10>;
+               };
+               ddr_sram: ddr-sram@1000 {
+                       compatible = "rockchip,rk3288-ddr-sram";
+                       reg = <0x1000 0x4000>;
+               };
+       };
+
+       sram@ff720000 {
+               compatible = "rockchip,rk3288-pmu-sram", "mmio-sram";
+               reg = <0xff720000 0x1000>;
+       };
+
+       pmu: power-management@ff730000 {
+               u-boot,dm-pre-reloc;
+               compatible = "rockchip,rk3288-pmu", "syscon";
+               reg = <0xff730000 0x100>;
+       };
+
+       sgrf: syscon@ff740000 {
+               u-boot,dm-pre-reloc;
+               compatible = "rockchip,rk3288-sgrf", "syscon";
+               reg = <0xff740000 0x1000>;
+       };
+
+       cru: clock-controller@ff760000 {
+               compatible = "rockchip,rk3288-cru";
+               reg = <0xff760000 0x1000>;
+               rockchip,grf = <&grf>;
+               u-boot,dm-pre-reloc;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>,
+                                 <&cru PLL_GPLL>, <&cru PLL_CPLL>,
+                                 <&cru PLL_NPLL>, <&cru ACLK_CPU>,
+                                 <&cru HCLK_CPU>, <&cru PCLK_CPU>,
+                                 <&cru ACLK_PERI>, <&cru HCLK_PERI>,
+                                 <&cru PCLK_PERI>;
+               assigned-clock-rates = <0>, <0>,
+                                      <594000000>, <400000000>,
+                                      <500000000>, <300000000>,
+                                      <150000000>, <75000000>,
+                                      <300000000>, <150000000>,
+                                      <75000000>;
+               assigned-clock-parents = <&cru PLL_NPLL>, <&cru PLL_GPLL>;
+       };
+
+       grf: syscon@ff770000 {
+               u-boot,dm-pre-reloc;
+               compatible = "rockchip,rk3288-grf", "syscon";
+               reg = <0xff770000 0x1000>;
+       };
+
+       wdt: watchdog@ff800000 {
+               compatible = "rockchip,rk3288-wdt", "snps,dw-wdt";
+               reg = <0xff800000 0x100>;
+               clocks = <&cru PCLK_WDT>;
+               interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+               status = "disabled";
+       };
+
+       i2s: i2s@ff890000 {
+               compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
+               reg = <0xff890000 0x10000>;
+               interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               dmas = <&dmac_bus_s 0>, <&dmac_bus_s 1>;
+               dma-names = "tx", "rx";
+               clock-names = "i2s_hclk", "i2s_clk";
+               clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s0_bus>;
+               status = "disabled";
+       };
+
+       vopb: vop@ff930000 {
+               compatible = "rockchip,rk3288-vop";
+               reg = <0xff930000 0x19c>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
+               clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+               resets = <&cru SRST_LCDC0_AXI>, <&cru SRST_LCDC0_AHB>, <&cru SRST_LCDC0_DCLK>;
+               reset-names = "axi", "ahb", "dclk";
+               iommus = <&vopb_mmu>;
+               power-domains = <&power RK3288_PD_VIO>;
+               status = "disabled";
+               vopb_out: port {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       vopb_out_edp: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&edp_in_vopb>;
+                       };
+                       vopb_out_hdmi: endpoint@1 {
+                               reg = <1>;
+                               remote-endpoint = <&hdmi_in_vopb>;
+                       };
+               };
+       };
+
+       vopb_mmu: iommu@ff930300 {
+               compatible = "rockchip,iommu";
+               reg = <0xff930300 0x100>;
+               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vopb_mmu";
+               power-domains = <&power RK3288_PD_VIO>;
+               #iommu-cells = <0>;
+               status = "disabled";
+       };
+
+       vopl: vop@ff940000 {
+               compatible = "rockchip,rk3288-vop";
+               reg = <0xff940000 0x19c>;
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
+               clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
+               resets = <&cru SRST_LCDC1_AXI>, <&cru SRST_LCDC1_AHB>, <&cru SRST_LCDC1_DCLK>;
+               reset-names = "axi", "ahb", "dclk";
+               iommus = <&vopl_mmu>;
+               power-domains = <&power RK3288_PD_VIO>;
+               status = "disabled";
+               vopl_out: port {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       vopl_out_edp: endpoint@0 {
+                               reg = <0>;
+                               remote-endpoint = <&edp_in_vopl>;
+                       };
+                       vopl_out_hdmi: endpoint@1 {
+                               reg = <1>;
+                               remote-endpoint = <&hdmi_in_vopl>;
+                       };
+
+               };
+       };
+
+       vopl_mmu: iommu@ff940300 {
+               compatible = "rockchip,iommu";
+               reg = <0xff940300 0x100>;
+               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vopl_mmu";
+               power-domains = <&power RK3288_PD_VIO>;
+               #iommu-cells = <0>;
+               status = "disabled";
+       };
+
+       edp: edp@ff970000 {
+               compatible = "rockchip,rk3288-edp";
+               reg = <0xff970000 0x4000>;
+               interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_EDP>, <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>;
+               rockchip,grf = <&grf>;
+               clock-names = "clk_edp", "clk_edp_24m", "pclk_edp";
+               resets = <&cru 111>;
+               reset-names = "edp";
+               power-domains = <&power RK3288_PD_VIO>;
+               status = "disabled";
+               ports {
+                       edp_in: port {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               edp_in_vopb: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&vopb_out_edp>;
+                               };
+                               edp_in_vopl: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&vopl_out_edp>;
+                               };
+                       };
+               };
+       };
+
+       hdmi: hdmi@ff980000 {
+               compatible = "rockchip,rk3288-dw-hdmi";
+               reg = <0xff980000 0x20000>;
+               reg-io-width = <4>;
+               ddc-i2c-bus = <&i2c5>;
+               rockchip,grf = <&grf>;
+               interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru  PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>;
+               clock-names = "iahb", "isfr";
+               status = "disabled";
+               ports {
+                       hdmi_in: port {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               hdmi_in_vopb: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&vopb_out_hdmi>;
+                               };
+                               hdmi_in_vopl: endpoint@1 {
+                                       reg = <1>;
+                                       remote-endpoint = <&vopl_out_hdmi>;
+                               };
+                       };
+               };
+       };
+
+       hdmi_audio: hdmi_audio {
+               compatible = "rockchip,rk3288-hdmi-audio";
+               i2s-controller = <&i2s>;
+               status = "disable";
+       };
+
+       vpu: video-codec@ff9a0000 {
+               compatible = "rockchip,rk3288-vpu";
+               reg = <0xff9a0000 0x800>;
+               interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
+                               <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vepu", "vdpu";
+               clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>;
+               clock-names = "aclk_vcodec", "hclk_vcodec";
+               power-domains = <&power RK3288_PD_VIDEO>;
+               iommus = <&vpu_mmu>;
+       };
+
+       vpu_mmu: iommu@ff9a0800 {
+               compatible = "rockchip,iommu";
+               reg = <0xff9a0800 0x100>;
+               interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "vpu_mmu";
+               power-domains = <&power RK3288_PD_VIDEO>;
+               #iommu-cells = <0>;
+       };
+
+       gpu: gpu@ffa30000 {
+               compatible = "arm,malit764",
+                            "arm,malit76x",
+                            "arm,malit7xx",
+                            "arm,mali-midgard";
+               reg = <0xffa30000 0x10000>;
+               interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "JOB", "MMU", "GPU";
+               clocks = <&cru ACLK_GPU>;
+               clock-names = "aclk_gpu";
+               operating-points = <
+                       /* KHz uV */
+                       100000 950000
+                       200000 950000
+                       300000 1000000
+                       400000 1100000
+                       /* 500000 1200000 - See crosbug.com/p/33857 */
+                       600000 1250000
+               >;
+               power-domains = <&power RK3288_PD_GPU>;
+               status = "disabled";
+       };
+
+       noc: syscon@ffac0000 {
+               u-boot,dm-pre-reloc;
+               compatible = "rockchip,rk3288-noc", "syscon";
+               reg = <0xffac0000 0x2000>;
+       };
+
+       efuse: efuse@ffb40000 {
+               compatible = "rockchip,rk3288-efuse";
+               reg = <0xffb40000 0x10000>;
+               status = "disabled";
+       };
+
+       gic: interrupt-controller@ffc01000 {
+               compatible = "arm,gic-400";
+               interrupt-controller;
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+
+               reg = <0xffc01000 0x1000>,
+                     <0xffc02000 0x1000>,
+                     <0xffc04000 0x2000>,
+                     <0xffc06000 0x2000>;
+               interrupts = <GIC_PPI 9 0xf04>;
+       };
+
+       cpuidle: cpuidle {
+               compatible = "rockchip,rk3288-cpuidle";
+       };
+
+       usbphy: phy {
+               compatible = "rockchip,rk3288-usb-phy";
+               rockchip,grf = <&grf>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               status = "disabled";
+
+               usbphy0: usb-phy0 {
+                       #phy-cells = <0>;
+                       reg = <0x320>;
+                       clocks = <&cru SCLK_OTGPHY0>;
+                       clock-names = "phyclk";
+               };
+
+               usbphy1: usb-phy1 {
+                       #phy-cells = <0>;
+                       reg = <0x334>;
+                       clocks = <&cru SCLK_OTGPHY1>;
+                       clock-names = "phyclk";
+               };
+
+               usbphy2: usb-phy2 {
+                       #phy-cells = <0>;
+                       reg = <0x348>;
+                       clocks = <&cru SCLK_OTGPHY2>;
+                       clock-names = "phyclk";
+               };
+       };
+
+       pinctrl: pinctrl {
+               compatible = "rockchip,rk3288-pinctrl";
+               rockchip,grf = <&grf>;
+               rockchip,pmu = <&pmu>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gpio0: gpio0@ff750000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg =   <0xff750000 0x100>;
+                       interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO0>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio1@ff780000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff780000 0x100>;
+                       interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO1>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio2@ff790000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff790000 0x100>;
+                       interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO2>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio3@ff7a0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7a0000 0x100>;
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO3>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio4: gpio4@ff7b0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7b0000 0x100>;
+                       interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO4>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio5: gpio5@ff7c0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7c0000 0x100>;
+                       interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO5>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio6: gpio6@ff7d0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7d0000 0x100>;
+                       interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO6>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio7: gpio7@ff7e0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7e0000 0x100>;
+                       interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO7>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio8: gpio8@ff7f0000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0xff7f0000 0x100>;
+                       interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO8>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               pcfg_pull_up: pcfg-pull-up {
+                       bias-pull-up;
+               };
+
+               pcfg_pull_down: pcfg-pull-down {
+                       bias-pull-down;
+               };
+
+               pcfg_pull_none: pcfg-pull-none {
+                       bias-disable;
+               };
+
+               pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+                       bias-disable;
+                       drive-strength = <12>;
+               };
+
+               sleep {
+                       global_pwroff: global-pwroff {
+                               rockchip,pins = <0 0 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       ddrio_pwroff: ddrio-pwroff {
+                               rockchip,pins = <0 1 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       ddr0_retention: ddr0-retention {
+                               rockchip,pins = <0 2 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       ddr1_retention: ddr1-retention {
+                               rockchip,pins = <0 3 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+               };
+
+               i2c0 {
+                       i2c0_xfer: i2c0-xfer {
+                               rockchip,pins = <0 15 RK_FUNC_1 &pcfg_pull_none>,
+                                               <0 16 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c1 {
+                       i2c1_xfer: i2c1-xfer {
+                               rockchip,pins = <8 4 RK_FUNC_1 &pcfg_pull_none>,
+                                               <8 5 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c2 {
+                       i2c2_xfer: i2c2-xfer {
+                               rockchip,pins = <6 9 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 10 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c3 {
+                       i2c3_xfer: i2c3-xfer {
+                               rockchip,pins = <2 16 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 17 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c4 {
+                       i2c4_xfer: i2c4-xfer {
+                               rockchip,pins = <7 17 RK_FUNC_1 &pcfg_pull_none>,
+                                               <7 18 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c5 {
+                       i2c5_xfer: i2c5-xfer {
+                               rockchip,pins = <7 19 RK_FUNC_1 &pcfg_pull_none>,
+                                               <7 20 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2s0 {
+                       i2s0_bus: i2s0-bus {
+                               rockchip,pins = <6 0 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 1 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 2 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 3 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 4 RK_FUNC_1 &pcfg_pull_none>,
+                                               <6 8 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               sdmmc {
+                       sdmmc_clk: sdmmc-clk {
+                               rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       sdmmc_cmd: sdmmc-cmd {
+                               rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdmmc_cd: sdmcc-cd {
+                               rockchip,pins = <6 22 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdmmc_bus1: sdmmc-bus1 {
+                               rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdmmc_bus4: sdmmc-bus4 {
+                               rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up>,
+                                               <6 17 RK_FUNC_1 &pcfg_pull_up>,
+                                               <6 18 RK_FUNC_1 &pcfg_pull_up>,
+                                               <6 19 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+               };
+
+               sdio0 {
+                       sdio0_bus1: sdio0-bus1 {
+                               rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_bus4: sdio0-bus4 {
+                               rockchip,pins = <4 20 RK_FUNC_1 &pcfg_pull_up>,
+                                               <4 21 RK_FUNC_1 &pcfg_pull_up>,
+                                               <4 22 RK_FUNC_1 &pcfg_pull_up>,
+                                               <4 23 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_cmd: sdio0-cmd {
+                               rockchip,pins = <4 24 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_clk: sdio0-clk {
+                               rockchip,pins = <4 25 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       sdio0_cd: sdio0-cd {
+                               rockchip,pins = <4 26 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_wp: sdio0-wp {
+                               rockchip,pins = <4 27 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_pwr: sdio0-pwr {
+                               rockchip,pins = <4 28 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_bkpwr: sdio0-bkpwr {
+                               rockchip,pins = <4 29 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+
+                       sdio0_int: sdio0-int {
+                               rockchip,pins = <4 30 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+               };
+
+               sdio1 {
+                       sdio1_bus1: sdio1-bus1 {
+                               rockchip,pins = <3 24 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_bus4: sdio1-bus4 {
+                               rockchip,pins = <3 24 RK_FUNC_4 &pcfg_pull_up>,
+                                               <3 25 RK_FUNC_4 &pcfg_pull_up>,
+                                               <3 26 RK_FUNC_4 &pcfg_pull_up>,
+                                               <3 27 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_cd: sdio1-cd {
+                               rockchip,pins = <3 28 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_wp: sdio1-wp {
+                               rockchip,pins = <3 29 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_bkpwr: sdio1-bkpwr {
+                               rockchip,pins = <3 30 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_int: sdio1-int {
+                               rockchip,pins = <3 31 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_cmd: sdio1-cmd {
+                               rockchip,pins = <4 6 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+
+                       sdio1_clk: sdio1-clk {
+                               rockchip,pins = <4 7 RK_FUNC_4 &pcfg_pull_none>;
+                       };
+
+                       sdio1_pwr: sdio1-pwr {
+                               rockchip,pins = <4 9 RK_FUNC_4 &pcfg_pull_up>;
+                       };
+               };
+
+               emmc {
+                       emmc_clk: emmc-clk {
+                               rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none>;
+                       };
+
+                       emmc_cmd: emmc-cmd {
+                               rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+
+                       emmc_pwr: emmc-pwr {
+                               rockchip,pins = <3 9 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+
+                       emmc_bus1: emmc-bus1 {
+                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+
+                       emmc_bus4: emmc-bus4 {
+                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 1 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 2 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 3 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+
+                       emmc_bus8: emmc-bus8 {
+                               rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 1 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 2 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 3 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 4 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 5 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 6 RK_FUNC_2 &pcfg_pull_up>,
+                                               <3 7 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+               };
+
+               spi0 {
+                       spi0_clk: spi0-clk {
+                               rockchip,pins = <5 12 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi0_cs0: spi0-cs0 {
+                               rockchip,pins = <5 13 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi0_tx: spi0-tx {
+                               rockchip,pins = <5 14 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi0_rx: spi0-rx {
+                               rockchip,pins = <5 15 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi0_cs1: spi0-cs1 {
+                               rockchip,pins = <5 16 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+               };
+               spi1 {
+                       spi1_clk: spi1-clk {
+                               rockchip,pins = <7 12 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+                       spi1_cs0: spi1-cs0 {
+                               rockchip,pins = <7 13 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+                       spi1_rx: spi1-rx {
+                               rockchip,pins = <7 14 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+                       spi1_tx: spi1-tx {
+                               rockchip,pins = <7 15 RK_FUNC_2 &pcfg_pull_up>;
+                       };
+               };
+
+               spi2 {
+                       spi2_cs1: spi2-cs1 {
+                               rockchip,pins = <8 3 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi2_clk: spi2-clk {
+                               rockchip,pins = <8 6 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi2_cs0: spi2-cs0 {
+                               rockchip,pins = <8 7 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi2_rx: spi2-rx {
+                               rockchip,pins = <8 8 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+                       spi2_tx: spi2-tx {
+                               rockchip,pins = <8 9 RK_FUNC_1 &pcfg_pull_up>;
+                       };
+               };
+
+               uart0 {
+                       uart0_xfer: uart0-xfer {
+                               rockchip,pins = <4 16 RK_FUNC_1 &pcfg_pull_up>,
+                                               <4 17 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart0_cts: uart0-cts {
+                               rockchip,pins = <4 18 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart0_rts: uart0-rts {
+                               rockchip,pins = <4 19 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               uart1 {
+                       uart1_xfer: uart1-xfer {
+                               rockchip,pins = <5 8 RK_FUNC_1 &pcfg_pull_up>,
+                                               <5 9 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart1_cts: uart1-cts {
+                               rockchip,pins = <5 10 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart1_rts: uart1-rts {
+                               rockchip,pins = <5 11 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               uart2 {
+                       uart2_xfer: uart2-xfer {
+                               rockchip,pins = <7 22 RK_FUNC_1 &pcfg_pull_up>,
+                                               <7 23 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+                       /* no rts / cts for uart2 */
+               };
+
+               uart3 {
+                       uart3_xfer: uart3-xfer {
+                               rockchip,pins = <7 7 RK_FUNC_1 &pcfg_pull_up>,
+                                               <7 8 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart3_cts: uart3-cts {
+                               rockchip,pins = <7 9 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+
+                       uart3_rts: uart3-rts {
+                               rockchip,pins = <7 10 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               uart4 {
+                       uart4_xfer: uart4-xfer {
+                               rockchip,pins = <5 12 3 &pcfg_pull_up>,
+                                               <5 13 3 &pcfg_pull_none>;
+                       };
+
+                       uart4_cts: uart4-cts {
+                               rockchip,pins = <5 14 3 &pcfg_pull_none>;
+                       };
+
+                       uart4_rts: uart4-rts {
+                               rockchip,pins = <5 15 3 &pcfg_pull_none>;
+                       };
+               };
+
+               tsadc {
+                       otp_out: otp-out {
+                               rockchip,pins = <0 10 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm0 {
+                       pwm0_pin: pwm0-pin {
+                               rockchip,pins = <7 0 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm1 {
+                       pwm1_pin: pwm1-pin {
+                               rockchip,pins = <7 1 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm2 {
+                       pwm2_pin: pwm2-pin {
+                               rockchip,pins = <7 22 RK_FUNC_3 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm3 {
+                       pwm3_pin: pwm3-pin {
+                               rockchip,pins = <7 23 RK_FUNC_3 &pcfg_pull_none>;
+                       };
+               };
+
+               gmac {
+                       rgmii_pins: rgmii-pins {
+                               rockchip,pins = <3 30 3 &pcfg_pull_none>,
+                                               <3 31 3 &pcfg_pull_none>,
+                                               <3 26 3 &pcfg_pull_none>,
+                                               <3 27 3 &pcfg_pull_none>,
+                                               <3 28 3 &pcfg_pull_none_12ma>,
+                                               <3 29 3 &pcfg_pull_none_12ma>,
+                                               <3 24 3 &pcfg_pull_none_12ma>,
+                                               <3 25 3 &pcfg_pull_none_12ma>,
+                                               <4 0 3 &pcfg_pull_none>,
+                                               <4 5 3 &pcfg_pull_none>,
+                                               <4 6 3 &pcfg_pull_none>,
+                                               <4 9 3 &pcfg_pull_none_12ma>,
+                                               <4 4 3 &pcfg_pull_none_12ma>,
+                                               <4 1 3 &pcfg_pull_none>,
+                                               <4 3 3 &pcfg_pull_none>;
+                       };
+
+                       rmii_pins: rmii-pins {
+                               rockchip,pins = <3 30 3 &pcfg_pull_none>,
+                                               <3 31 3 &pcfg_pull_none>,
+                                               <3 28 3 &pcfg_pull_none>,
+                                               <3 29 3 &pcfg_pull_none>,
+                                               <4 0 3 &pcfg_pull_none>,
+                                               <4 5 3 &pcfg_pull_none>,
+                                               <4 4 3 &pcfg_pull_none>,
+                                               <4 1 3 &pcfg_pull_none>,
+                                               <4 2 3 &pcfg_pull_none>,
+                                               <4 3 3 &pcfg_pull_none>;
+                       };
+               };
+       };
+
+       power: power-controller {
+               compatible = "rockchip,rk3288-power-controller";
+               #power-domain-cells = <1>;
+               rockchip,pmu = <&pmu>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               pd_gpu {
+                       reg = <RK3288_PD_GPU>;
+                       clocks = <&cru ACLK_GPU>;
+               };
+
+               pd_hevc {
+                       reg = <RK3288_PD_HEVC>;
+                       clocks = <&cru ACLK_HEVC>,
+                                <&cru SCLK_HEVC_CABAC>,
+                                <&cru SCLK_HEVC_CORE>,
+                                <&cru HCLK_HEVC>;
+               };
+
+               pd_vio {
+                       reg = <RK3288_PD_VIO>;
+                       clocks = <&cru ACLK_IEP>,
+                                <&cru ACLK_ISP>,
+                                <&cru ACLK_RGA>,
+                                <&cru ACLK_VIP>,
+                                <&cru ACLK_VOP0>,
+                                <&cru ACLK_VOP1>,
+                                <&cru DCLK_VOP0>,
+                                <&cru DCLK_VOP1>,
+                                <&cru HCLK_IEP>,
+                                <&cru HCLK_ISP>,
+                                <&cru HCLK_RGA>,
+                                <&cru HCLK_VIP>,
+                                <&cru HCLK_VOP0>,
+                                <&cru HCLK_VOP1>,
+                                <&cru PCLK_EDP_CTRL>,
+                                <&cru PCLK_HDMI_CTRL>,
+                                <&cru PCLK_LVDS_PHY>,
+                                <&cru PCLK_MIPI_CSI>,
+                                <&cru PCLK_MIPI_DSI0>,
+                                <&cru PCLK_MIPI_DSI1>,
+                                <&cru SCLK_EDP_24M>,
+                                <&cru SCLK_EDP>,
+                                <&cru SCLK_HDMI_CEC>,
+                                <&cru SCLK_HDMI_HDCP>,
+                                <&cru SCLK_ISP_JPE>,
+                                <&cru SCLK_ISP>,
+                                <&cru SCLK_RGA>;
+               };
+
+               pd_video {
+                       reg = <RK3288_PD_VIDEO>;
+                       clocks = <&cru ACLK_VCODEC>,
+                                <&cru HCLK_VCODEC>;
+               };
+       };
+};
diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h
new file mode 100644 (file)
index 0000000..8a0376c
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_CLOCK_H
+#define _ASM_ARCH_CLOCK_H
+
+/* define pll mode */
+#define RKCLK_PLL_MODE_SLOW            0
+#define RKCLK_PLL_MODE_NORMAL          1
+
+enum {
+       ROCKCHIP_SYSCON_NOC,
+       ROCKCHIP_SYSCON_GRF,
+       ROCKCHIP_SYSCON_SGRF,
+       ROCKCHIP_SYSCON_PMU,
+};
+
+/* Standard Rockchip clock numbers */
+enum rk_clk_id {
+       CLK_OSC,
+       CLK_ARM,
+       CLK_DDR,
+       CLK_CODEC,
+       CLK_GENERAL,
+       CLK_NEW,
+
+       CLK_COUNT,
+};
+
+static inline int rk_pll_id(enum rk_clk_id clk_id)
+{
+       return clk_id - 1;
+}
+
+/**
+ * clk_get_divisor() - Calculate the required clock divisior
+ *
+ * Given an input rate and a required output_rate, calculate the Rockchip
+ * divisor needed to achieve this.
+ *
+ * @input_rate:                Input clock rate in Hz
+ * @output_rate:       Output clock rate in Hz
+ * @return divisor register value to use
+ */
+static inline u32 clk_get_divisor(ulong input_rate, uint output_rate)
+{
+       uint clk_div;
+
+       clk_div = input_rate / output_rate;
+       clk_div = (clk_div + 1) & 0xfffe;
+
+       return clk_div;
+}
+
+/**
+ * rockchip_get_cru() - get a pointer to the clock/reset unit registers
+ *
+ * @return pointer to registers, or -ve error on error
+ */
+void *rockchip_get_cru(void);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3288.h b/arch/arm/include/asm/arch-rockchip/cru_rk3288.h
new file mode 100644 (file)
index 0000000..7ebcc40
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ * Peter, Software Engineering, <superpeter.cai@gmail.com>.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+#ifndef _ASM_ARCH_CRU_RK3288_H
+#define _ASM_ARCH_CRU_RK3288_H
+
+#define OSC_HZ         (24 * 1000 * 1000)
+
+#define APLL_HZ                (1800 * 1000000)
+#define GPLL_HZ                (594 * 1000000)
+#define CPLL_HZ                (384 * 1000000)
+#define NPLL_HZ                (384 * 1000000)
+
+/* The SRAM is clocked off aclk_bus, so we want to max it out for boot speed */
+#define PD_BUS_ACLK_HZ 297000000
+#define PD_BUS_HCLK_HZ 148500000
+#define PD_BUS_PCLK_HZ 74250000
+
+#define PERI_ACLK_HZ   148500000
+#define PERI_HCLK_HZ   148500000
+#define PERI_PCLK_HZ   74250000
+
+struct rk3288_cru {
+       struct rk3288_pll {
+               u32 con0;
+               u32 con1;
+               u32 con2;
+               u32 con3;
+       } pll[5];
+       u32 cru_mode_con;
+       u32 reserved0[3];
+       u32 cru_clksel_con[43];
+       u32 reserved1[21];
+       u32 cru_clkgate_con[19];
+       u32 reserved2;
+       u32 cru_glb_srst_fst_value;
+       u32 cru_glb_srst_snd_value;
+       u32 cru_softrst_con[12];
+       u32 cru_misc_con;
+       u32 cru_glb_cnt_th;
+       u32 cru_glb_rst_con;
+       u32 reserved3;
+       u32 cru_glb_rst_st;
+       u32 reserved4;
+       u32 cru_sdmmc_con[2];
+       u32 cru_sdio0_con[2];
+       u32 cru_sdio1_con[2];
+       u32 cru_emmc_con[2];
+};
+check_member(rk3288_cru, cru_emmc_con[1], 0x021c);
+
+/* CRU_CLKSEL11_CON */
+enum {
+       HSICPHY_DIV_SHIFT       = 8,
+       HSICPHY_DIV_MASK        = 0x3f,
+
+       MMC0_PLL_SHIFT          = 6,
+       MMC0_PLL_MASK           = 3,
+       MMC0_PLL_SELECT_CODEC   = 0,
+       MMC0_PLL_SELECT_GENERAL,
+       MMC0_PLL_SELECT_24MHZ,
+
+       MMC0_DIV_SHIFT          = 0,
+       MMC0_DIV_MASK           = 0x3f,
+};
+
+/* CRU_CLKSEL12_CON */
+enum {
+       EMMC_PLL_SHIFT          = 0xe,
+       EMMC_PLL_MASK           = 3,
+       EMMC_PLL_SELECT_CODEC   = 0,
+       EMMC_PLL_SELECT_GENERAL,
+       EMMC_PLL_SELECT_24MHZ,
+
+       EMMC_DIV_SHIFT          = 8,
+       EMMC_DIV_MASK           = 0x3f,
+
+       SDIO0_PLL_SHIFT         = 6,
+       SDIO0_PLL_MASK          = 3,
+       SDIO0_PLL_SELECT_CODEC  = 0,
+       SDIO0_PLL_SELECT_GENERAL,
+       SDIO0_PLL_SELECT_24MHZ,
+
+       SDIO0_DIV_SHIFT         = 0,
+       SDIO0_DIV_MASK          = 0x3f,
+};
+
+/* CRU_CLKSEL25_CON */
+enum {
+       SPI1_PLL_SHIFT          = 0xf,
+       SPI1_PLL_MASK           = 1,
+       SPI1_PLL_SELECT_CODEC   = 0,
+       SPI1_PLL_SELECT_GENERAL,
+
+       SPI1_DIV_SHIFT          = 8,
+       SPI1_DIV_MASK           = 0x7f,
+
+       SPI0_PLL_SHIFT          = 7,
+       SPI0_PLL_MASK           = 1,
+       SPI0_PLL_SELECT_CODEC   = 0,
+       SPI0_PLL_SELECT_GENERAL,
+
+       SPI0_DIV_SHIFT          = 0,
+       SPI0_DIV_MASK           = 0x7f,
+};
+
+/* CRU_CLKSEL39_CON */
+enum {
+       ACLK_HEVC_PLL_SHIFT     = 0xe,
+       ACLK_HEVC_PLL_MASK      = 3,
+       ACLK_HEVC_PLL_SELECT_CODEC = 0,
+       ACLK_HEVC_PLL_SELECT_GENERAL,
+       ACLK_HEVC_PLL_SELECT_NEW,
+
+       ACLK_HEVC_DIV_SHIFT     = 8,
+       ACLK_HEVC_DIV_MASK      = 0x1f,
+
+       SPI2_PLL_SHIFT          = 7,
+       SPI2_PLL_MASK           = 1,
+       SPI2_PLL_SELECT_CODEC   = 0,
+       SPI2_PLL_SELECT_GENERAL,
+
+       SPI2_DIV_SHIFT          = 0,
+       SPI2_DIV_MASK           = 0x7f,
+};
+
+/* CRU_MODE_CON */
+enum {
+       NPLL_WORK_SHIFT         = 0xe,
+       NPLL_WORK_MASK          = 3,
+       NPLL_WORK_SLOW          = 0,
+       NPLL_WORK_NORMAL,
+       NPLL_WORK_DEEP,
+
+       GPLL_WORK_SHIFT         = 0xc,
+       GPLL_WORK_MASK          = 3,
+       GPLL_WORK_SLOW          = 0,
+       GPLL_WORK_NORMAL,
+       GPLL_WORK_DEEP,
+
+       CPLL_WORK_SHIFT         = 8,
+       CPLL_WORK_MASK          = 3,
+       CPLL_WORK_SLOW          = 0,
+       CPLL_WORK_NORMAL,
+       CPLL_WORK_DEEP,
+
+       DPLL_WORK_SHIFT         = 4,
+       DPLL_WORK_MASK          = 3,
+       DPLL_WORK_SLOW          = 0,
+       DPLL_WORK_NORMAL,
+       DPLL_WORK_DEEP,
+
+       APLL_WORK_SHIFT         = 0,
+       APLL_WORK_MASK          = 3,
+       APLL_WORK_SLOW          = 0,
+       APLL_WORK_NORMAL,
+       APLL_WORK_DEEP,
+};
+
+/* CRU_APLL_CON0 */
+enum {
+       CLKR_SHIFT              = 8,
+       CLKR_MASK               = 0x3f,
+
+       CLKOD_SHIFT             = 0,
+       CLKOD_MASK              = 0xf,
+};
+
+/* CRU_APLL_CON1 */
+enum {
+       LOCK_SHIFT              = 0x1f,
+       LOCK_MASK               = 1,
+       LOCK_UNLOCK             = 0,
+       LOCK_LOCK,
+
+       CLKF_SHIFT              = 0,
+       CLKF_MASK               = 0x1fff,
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h b/arch/arm/include/asm/arch-rockchip/ddr_rk3288.h
new file mode 100644 (file)
index 0000000..fccabcd
--- /dev/null
@@ -0,0 +1,484 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_DDR_RK3288_H
+#define _ASM_ARCH_DDR_RK3288_H
+
+struct rk3288_ddr_pctl {
+       u32 scfg;
+       u32 sctl;
+       u32 stat;
+       u32 intrstat;
+       u32 reserved0[12];
+       u32 mcmd;
+       u32 powctl;
+       u32 powstat;
+       u32 cmdtstat;
+       u32 tstaten;
+       u32 reserved1[3];
+       u32 mrrcfg0;
+       u32 mrrstat0;
+       u32 mrrstat1;
+       u32 reserved2[4];
+       u32 mcfg1;
+       u32 mcfg;
+       u32 ppcfg;
+       u32 mstat;
+       u32 lpddr2zqcfg;
+       u32 reserved3;
+       u32 dtupdes;
+       u32 dtuna;
+       u32 dtune;
+       u32 dtuprd0;
+       u32 dtuprd1;
+       u32 dtuprd2;
+       u32 dtuprd3;
+       u32 dtuawdt;
+       u32 reserved4[3];
+       u32 togcnt1u;
+       u32 tinit;
+       u32 trsth;
+       u32 togcnt100n;
+       u32 trefi;
+       u32 tmrd;
+       u32 trfc;
+       u32 trp;
+       u32 trtw;
+       u32 tal;
+       u32 tcl;
+       u32 tcwl;
+       u32 tras;
+       u32 trc;
+       u32 trcd;
+       u32 trrd;
+       u32 trtp;
+       u32 twr;
+       u32 twtr;
+       u32 texsr;
+       u32 txp;
+       u32 txpdll;
+       u32 tzqcs;
+       u32 tzqcsi;
+       u32 tdqs;
+       u32 tcksre;
+       u32 tcksrx;
+       u32 tcke;
+       u32 tmod;
+       u32 trstl;
+       u32 tzqcl;
+       u32 tmrr;
+       u32 tckesr;
+       u32 tdpd;
+       u32 reserved5[14];
+       u32 ecccfg;
+       u32 ecctst;
+       u32 eccclr;
+       u32 ecclog;
+       u32 reserved6[28];
+       u32 dtuwactl;
+       u32 dturactl;
+       u32 dtucfg;
+       u32 dtuectl;
+       u32 dtuwd0;
+       u32 dtuwd1;
+       u32 dtuwd2;
+       u32 dtuwd3;
+       u32 dtuwdm;
+       u32 dturd0;
+       u32 dturd1;
+       u32 dturd2;
+       u32 dturd3;
+       u32 dtulfsrwd;
+       u32 dtulfsrrd;
+       u32 dtueaf;
+       u32 dfitctrldelay;
+       u32 dfiodtcfg;
+       u32 dfiodtcfg1;
+       u32 dfiodtrankmap;
+       u32 dfitphywrdata;
+       u32 dfitphywrlat;
+       u32 reserved7[2];
+       u32 dfitrddataen;
+       u32 dfitphyrdlat;
+       u32 reserved8[2];
+       u32 dfitphyupdtype0;
+       u32 dfitphyupdtype1;
+       u32 dfitphyupdtype2;
+       u32 dfitphyupdtype3;
+       u32 dfitctrlupdmin;
+       u32 dfitctrlupdmax;
+       u32 dfitctrlupddly;
+       u32 reserved9;
+       u32 dfiupdcfg;
+       u32 dfitrefmski;
+       u32 dfitctrlupdi;
+       u32 reserved10[4];
+       u32 dfitrcfg0;
+       u32 dfitrstat0;
+       u32 dfitrwrlvlen;
+       u32 dfitrrdlvlen;
+       u32 dfitrrdlvlgateen;
+       u32 dfiststat0;
+       u32 dfistcfg0;
+       u32 dfistcfg1;
+       u32 reserved11;
+       u32 dfitdramclken;
+       u32 dfitdramclkdis;
+       u32 dfistcfg2;
+       u32 dfistparclr;
+       u32 dfistparlog;
+       u32 reserved12[3];
+       u32 dfilpcfg0;
+       u32 reserved13[3];
+       u32 dfitrwrlvlresp0;
+       u32 dfitrwrlvlresp1;
+       u32 dfitrwrlvlresp2;
+       u32 dfitrrdlvlresp0;
+       u32 dfitrrdlvlresp1;
+       u32 dfitrrdlvlresp2;
+       u32 dfitrwrlvldelay0;
+       u32 dfitrwrlvldelay1;
+       u32 dfitrwrlvldelay2;
+       u32 dfitrrdlvldelay0;
+       u32 dfitrrdlvldelay1;
+       u32 dfitrrdlvldelay2;
+       u32 dfitrrdlvlgatedelay0;
+       u32 dfitrrdlvlgatedelay1;
+       u32 dfitrrdlvlgatedelay2;
+       u32 dfitrcmd;
+       u32 reserved14[46];
+       u32 ipvr;
+       u32 iptr;
+};
+check_member(rk3288_ddr_pctl, iptr, 0x03fc);
+
+struct rk3288_ddr_publ_datx {
+       u32 dxgcr;
+       u32 dxgsr[2];
+       u32 dxdllcr;
+       u32 dxdqtr;
+       u32 dxdqstr;
+       u32 reserved[10];
+};
+
+struct rk3288_ddr_publ {
+       u32 ridr;
+       u32 pir;
+       u32 pgcr;
+       u32 pgsr;
+       u32 dllgcr;
+       u32 acdllcr;
+       u32 ptr[3];
+       u32 aciocr;
+       u32 dxccr;
+       u32 dsgcr;
+       u32 dcr;
+       u32 dtpr[3];
+       u32 mr[4];
+       u32 odtcr;
+       u32 dtar;
+       u32 dtdr[2];
+       u32 reserved1[24];
+       u32 dcuar;
+       u32 dcudr;
+       u32 dcurr;
+       u32 dculr;
+       u32 dcugcr;
+       u32 dcutpr;
+       u32 dcusr[2];
+       u32 reserved2[8];
+       u32 bist[17];
+       u32 reserved3[15];
+       u32 zq0cr[2];
+       u32 zq0sr[2];
+       u32 zq1cr[2];
+       u32 zq1sr[2];
+       u32 zq2cr[2];
+       u32 zq2sr[2];
+       u32 zq3cr[2];
+       u32 zq3sr[2];
+       struct rk3288_ddr_publ_datx datx8[4];
+};
+check_member(rk3288_ddr_publ, datx8[3].dxdqstr, 0x0294);
+
+struct rk3288_msch {
+       u32 coreid;
+       u32 revisionid;
+       u32 ddrconf;
+       u32 ddrtiming;
+       u32 ddrmode;
+       u32 readlatency;
+       u32 reserved1[8];
+       u32 activate;
+       u32 devtodev;
+};
+check_member(rk3288_msch, devtodev, 0x003c);
+
+/* PCT_DFISTCFG0 */
+#define DFI_INIT_START                 (1 << 0)
+
+/* PCT_DFISTCFG1 */
+#define DFI_DRAM_CLK_SR_EN             (1 << 0)
+#define DFI_DRAM_CLK_DPD_EN            (1 << 1)
+
+/* PCT_DFISTCFG2 */
+#define DFI_PARITY_INTR_EN             (1 << 0)
+#define DFI_PARITY_EN                  (1 << 1)
+
+/* PCT_DFILPCFG0 */
+#define TLP_RESP_TIME_SHIFT            16
+#define LP_SR_EN                       (1 << 8)
+#define LP_PD_EN                       (1 << 0)
+
+/* PCT_DFITCTRLDELAY */
+#define TCTRL_DELAY_TIME_SHIFT         0
+
+/* PCT_DFITPHYWRDATA */
+#define TPHY_WRDATA_TIME_SHIFT         0
+
+/* PCT_DFITPHYRDLAT */
+#define TPHY_RDLAT_TIME_SHIFT          0
+
+/* PCT_DFITDRAMCLKDIS */
+#define TDRAM_CLK_DIS_TIME_SHIFT       0
+
+/* PCT_DFITDRAMCLKEN */
+#define TDRAM_CLK_EN_TIME_SHIFT                0
+
+/* PCTL_DFIODTCFG */
+#define RANK0_ODT_WRITE_SEL            (1 << 3)
+#define RANK1_ODT_WRITE_SEL            (1 << 11)
+
+/* PCTL_DFIODTCFG1 */
+#define ODT_LEN_BL8_W_SHIFT            16
+
+/* PUBL_ACDLLCR */
+#define ACDLLCR_DLLDIS                 (1 << 31)
+#define ACDLLCR_DLLSRST                        (1 << 30)
+
+/* PUBL_DXDLLCR */
+#define DXDLLCR_DLLDIS                 (1 << 31)
+#define DXDLLCR_DLLSRST                        (1 << 30)
+
+/* PUBL_DLLGCR */
+#define DLLGCR_SBIAS                   (1 << 30)
+
+/* PUBL_DXGCR */
+#define DQSRTT                         (1 << 9)
+#define DQRTT                          (1 << 10)
+
+/* PIR */
+#define PIR_INIT                       (1 << 0)
+#define PIR_DLLSRST                    (1 << 1)
+#define PIR_DLLLOCK                    (1 << 2)
+#define PIR_ZCAL                       (1 << 3)
+#define PIR_ITMSRST                    (1 << 4)
+#define PIR_DRAMRST                    (1 << 5)
+#define PIR_DRAMINIT                   (1 << 6)
+#define PIR_QSTRN                      (1 << 7)
+#define PIR_RVTRN                      (1 << 8)
+#define PIR_ICPC                       (1 << 16)
+#define PIR_DLLBYP                     (1 << 17)
+#define PIR_CTLDINIT                   (1 << 18)
+#define PIR_CLRSR                      (1 << 28)
+#define PIR_LOCKBYP                    (1 << 29)
+#define PIR_ZCALBYP                    (1 << 30)
+#define PIR_INITBYP                    (1u << 31)
+
+/* PGCR */
+#define PGCR_DFTLMT_SHIFT              3
+#define PGCR_DFTCMP_SHIFT              2
+#define PGCR_DQSCFG_SHIFT              1
+#define PGCR_ITMDMD_SHIFT              0
+
+/* PGSR */
+#define PGSR_IDONE                     (1 << 0)
+#define PGSR_DLDONE                    (1 << 1)
+#define PGSR_ZCDONE                    (1 << 2)
+#define PGSR_DIDONE                    (1 << 3)
+#define PGSR_DTDONE                    (1 << 4)
+#define PGSR_DTERR                     (1 << 5)
+#define PGSR_DTIERR                    (1 << 6)
+#define PGSR_DFTERR                    (1 << 7)
+#define PGSR_RVERR                     (1 << 8)
+#define PGSR_RVEIRR                    (1 << 9)
+
+/* PTR0 */
+#define PRT_ITMSRST_SHIFT              18
+#define PRT_DLLLOCK_SHIFT              6
+#define PRT_DLLSRST_SHIFT              0
+
+/* PTR1 */
+#define PRT_DINIT0_SHIFT               0
+#define PRT_DINIT1_SHIFT               19
+
+/* PTR2 */
+#define PRT_DINIT2_SHIFT               0
+#define PRT_DINIT3_SHIFT               17
+
+/* DCR */
+#define DDRMD_LPDDR                    0
+#define DDRMD_DDR                      1
+#define DDRMD_DDR2                     2
+#define DDRMD_DDR3                     3
+#define DDRMD_LPDDR2_LPDDR3            4
+#define DDRMD_MASK                     7
+#define DDRMD_SHIFT                    0
+#define PDQ_MASK                       7
+#define PDQ_SHIFT                      4
+
+/* DXCCR */
+#define DQSNRES_MASK                   0xf
+#define DQSNRES_SHIFT                  8
+#define DQSRES_MASK                    0xf
+#define DQSRES_SHIFT                   4
+
+/* DTPR */
+#define TDQSCKMAX_SHIFT                        27
+#define TDQSCKMAX_MASK                 7
+#define TDQSCK_SHIFT                   24
+#define TDQSCK_MASK                    7
+
+/* DSGCR */
+#define DQSGX_SHIFT                    5
+#define DQSGX_MASK                     7
+#define DQSGE_SHIFT                    8
+#define DQSGE_MASK                     7
+
+/* SCTL */
+#define INIT_STATE                     0
+#define CFG_STATE                      1
+#define GO_STATE                       2
+#define SLEEP_STATE                    3
+#define WAKEUP_STATE                   4
+
+/* STAT */
+#define LP_TRIG_SHIFT                  4
+#define LP_TRIG_MASK                   7
+#define PCTL_STAT_MSK                  7
+#define INIT_MEM                       0
+#define CONFIG                         1
+#define CONFIG_REQ                     2
+#define ACCESS                         3
+#define ACCESS_REQ                     4
+#define LOW_POWER                      5
+#define LOW_POWER_ENTRY_REQ            6
+#define LOW_POWER_EXIT_REQ             7
+
+/* ZQCR*/
+#define PD_OUTPUT_SHIFT                        0
+#define PU_OUTPUT_SHIFT                        5
+#define PD_ONDIE_SHIFT                 10
+#define PU_ONDIE_SHIFT                 15
+#define ZDEN_SHIFT                     28
+
+/* DDLGCR */
+#define SBIAS_BYPASS                   (1 << 23)
+
+/* MCFG */
+#define MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT        24
+#define PD_IDLE_SHIFT                  8
+#define MDDR_EN                                (2 << 22)
+#define LPDDR2_EN                      (3 << 22)
+#define DDR2_EN                                (0 << 5)
+#define DDR3_EN                                (1 << 5)
+#define LPDDR2_S2                      (0 << 6)
+#define LPDDR2_S4                      (1 << 6)
+#define MDDR_LPDDR2_BL_2               (0 << 20)
+#define MDDR_LPDDR2_BL_4               (1 << 20)
+#define MDDR_LPDDR2_BL_8               (2 << 20)
+#define MDDR_LPDDR2_BL_16              (3 << 20)
+#define DDR2_DDR3_BL_4                 0
+#define DDR2_DDR3_BL_8                 1
+#define TFAW_SHIFT                     18
+#define PD_EXIT_SLOW                   (0 << 17)
+#define PD_EXIT_FAST                   (1 << 17)
+#define PD_TYPE_SHIFT                  16
+#define BURSTLENGTH_SHIFT              20
+
+/* POWCTL */
+#define POWER_UP_START                 (1 << 0)
+
+/* POWSTAT */
+#define POWER_UP_DONE                  (1 << 0)
+
+/* MCMD */
+enum {
+       DESELECT_CMD                    = 0,
+       PREA_CMD,
+       REF_CMD,
+       MRS_CMD,
+       ZQCS_CMD,
+       ZQCL_CMD,
+       RSTL_CMD,
+       MRR_CMD                         = 8,
+       DPDE_CMD,
+};
+
+#define LPDDR2_MA_SHIFT                        4
+#define LPDDR2_MA_MASK                 0xff
+#define LPDDR2_OP_SHIFT                        12
+#define LPDDR2_OP_MASK                 0xff
+
+#define START_CMD                      (1u << 31)
+
+/* DEVTODEV */
+#define BUSWRTORD_SHIFT                        4
+#define BUSRDTOWR_SHIFT                        2
+#define BUSRDTORD_SHIFT                        0
+
+/* mr1 for ddr3 */
+#define DDR3_DLL_DISABLE               1
+
+/*
+ *TODO(sjg@chromium.org): We use a PMU register to store SDRAM information for
+ * passing from SPL to U-Boot. It would probably be better to use a normal C
+ * structure in SRAM.
+ *
+ * sys_reg bitfield struct
+ * [31] row_3_4_ch1
+ * [30] row_3_4_ch0
+ * [29:28] chinfo
+ * [27] rank_ch1
+ * [26:25] col_ch1
+ * [24] bk_ch1
+ * [23:22] cs0_row_ch1
+ * [21:20] cs1_row_ch1
+ * [19:18] bw_ch1
+ * [17:16] dbw_ch1;
+ * [15:13] ddrtype
+ * [12] channelnum
+ * [11] rank_ch0
+ * [10:9] col_ch0
+ * [8] bk_ch0
+ * [7:6] cs0_row_ch0
+ * [5:4] cs1_row_ch0
+ * [3:2] bw_ch0
+ * [1:0] dbw_ch0
+*/
+#define SYS_REG_DDRTYPE_SHIFT          13
+#define SYS_REG_DDRTYPE_MASK           7
+#define SYS_REG_NUM_CH_SHIFT           12
+#define SYS_REG_NUM_CH_MASK            1
+#define SYS_REG_ROW_3_4_SHIFT(ch)      (30 + (ch))
+#define SYS_REG_ROW_3_4_MASK           1
+#define SYS_REG_CHINFO_SHIFT(ch)       (28 + (ch))
+#define SYS_REG_RANK_SHIFT(ch)         (11 + (ch) * 16)
+#define SYS_REG_RANK_MASK              1
+#define SYS_REG_COL_SHIFT(ch)          (9 + (ch) * 16)
+#define SYS_REG_COL_MASK               3
+#define SYS_REG_BK_SHIFT(ch)           (8 + (ch) * 16)
+#define SYS_REG_BK_MASK                        1
+#define SYS_REG_CS0_ROW_SHIFT(ch)      (6 + (ch) * 16)
+#define SYS_REG_CS0_ROW_MASK           3
+#define SYS_REG_CS1_ROW_SHIFT(ch)      (4 + (ch) * 16)
+#define SYS_REG_CS1_ROW_MASK           3
+#define SYS_REG_BW_SHIFT(ch)           (2 + (ch) * 16)
+#define SYS_REG_BW_MASK                        3
+#define SYS_REG_DBW_SHIFT(ch)          ((ch) * 16)
+#define SYS_REG_DBW_MASK               3
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/gpio.h b/arch/arm/include/asm/arch-rockchip/gpio.h
new file mode 100644 (file)
index 0000000..e39218d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_GPIO_H
+#define _ASM_ARCH_GPIO_H
+
+struct rockchip_gpio_regs {
+       u32 swport_dr;
+       u32 swport_ddr;
+       u32 reserved0[(0x30 - 0x08) / 4];
+       u32 inten;
+       u32 intmask;
+       u32 inttype_level;
+       u32 int_polarity;
+       u32 int_status;
+       u32 int_rawstatus;
+       u32 debounce;
+       u32 porta_eoi;
+       u32 ext_port;
+       u32 reserved1[(0x60 - 0x54) / 4];
+       u32 ls_sync;
+};
+check_member(rockchip_gpio_regs, ls_sync, 0x60);
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/grf_rk3288.h b/arch/arm/include/asm/arch-rockchip/grf_rk3288.h
new file mode 100644 (file)
index 0000000..0117a17
--- /dev/null
@@ -0,0 +1,768 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_GRF_RK3288_H
+#define _ASM_ARCH_GRF_RK3288_H
+
+struct rk3288_grf_gpio_lh {
+       u32 l;
+       u32 h;
+};
+
+struct rk3288_grf {
+       u32 reserved[3];
+       u32 gpio1d_iomux;
+       u32 gpio2a_iomux;
+       u32 gpio2b_iomux;
+
+       u32 gpio2c_iomux;
+       u32 reserved2;
+       u32 gpio3a_iomux;
+       u32 gpio3b_iomux;
+
+       u32 gpio3c_iomux;
+       u32 gpio3dl_iomux;
+       u32 gpio3dh_iomux;
+       u32 gpio4al_iomux;
+
+       u32 gpio4ah_iomux;
+       u32 gpio4bl_iomux;
+       u32 reserved3;
+       u32 gpio4c_iomux;
+
+       u32 gpio4d_iomux;
+       u32 reserved4;
+       u32 gpio5b_iomux;
+       u32 gpio5c_iomux;
+
+       u32 reserved5;
+       u32 gpio6a_iomux;
+       u32 gpio6b_iomux;
+       u32 gpio6c_iomux;
+       u32 reserved6;
+       u32 gpio7a_iomux;
+       u32 gpio7b_iomux;
+       u32 gpio7cl_iomux;
+       u32 gpio7ch_iomux;
+       u32 reserved7;
+       u32 gpio8a_iomux;
+       u32 gpio8b_iomux;
+       u32 reserved8[30];
+       struct rk3288_grf_gpio_lh gpio_sr[8];
+       u32 gpio1_p[8][4];
+       u32 gpio1_e[8][4];
+       u32 gpio_smt;
+       u32 soc_con0;
+       u32 soc_con1;
+       u32 soc_con2;
+       u32 soc_con3;
+       u32 soc_con4;
+       u32 soc_con5;
+       u32 soc_con6;
+       u32 soc_con7;
+       u32 soc_con8;
+       u32 soc_con9;
+       u32 soc_con10;
+       u32 soc_con11;
+       u32 soc_con12;
+       u32 soc_con13;
+       u32 soc_con14;
+       u32 soc_status[22];
+       u32 reserved9[2];
+       u32 peridmac_con[4];
+       u32 ddrc0_con0;
+       u32 ddrc1_con0;
+       u32 cpu_con[5];
+       u32 reserved10[3];
+       u32 cpu_status0;
+       u32 reserved11;
+       u32 uoc0_con[5];
+       u32 uoc1_con[5];
+       u32 uoc2_con[4];
+       u32 uoc3_con[2];
+       u32 uoc4_con[2];
+       u32 pvtm_con[3];
+       u32 pvtm_status[3];
+       u32 io_vsel;
+       u32 saradc_testbit;
+       u32 tsadc_testbit_l;
+       u32 tsadc_testbit_h;
+       u32 os_reg[4];
+       u32 reserved12;
+       u32 soc_con15;
+       u32 soc_con16;
+};
+
+struct rk3288_sgrf {
+       u32 soc_con0;
+       u32 soc_con1;
+       u32 soc_con2;
+       u32 soc_con3;
+       u32 soc_con4;
+       u32 soc_con5;
+       u32 reserved1[(0x20-0x18)/4];
+       u32 busdmac_con[2];
+       u32 reserved2[(0x40-0x28)/4];
+       u32 cpu_con[3];
+       u32 reserved3[(0x50-0x4c)/4];
+       u32 soc_con6;
+       u32 soc_con7;
+       u32 soc_con8;
+       u32 soc_con9;
+       u32 soc_con10;
+       u32 soc_con11;
+       u32 soc_con12;
+       u32 soc_con13;
+       u32 soc_con14;
+       u32 soc_con15;
+       u32 soc_con16;
+       u32 soc_con17;
+       u32 soc_con18;
+       u32 soc_con19;
+       u32 soc_con20;
+       u32 soc_con21;
+       u32 reserved4[(0x100-0x90)/4];
+       u32 soc_status[2];
+       u32 reserved5[(0x120-0x108)/4];
+       u32 fast_boot_addr;
+};
+
+/* GRF_GPIO1D_IOMUX */
+enum {
+       GPIO1D3_SHIFT           = 6,
+       GPIO1D3_MASK            = 1,
+       GPIO1D3_GPIO            = 0,
+       GPIO1D3_LCDC0_DCLK,
+
+       GPIO1D2_SHIFT           = 4,
+       GPIO1D2_MASK            = 1,
+       GPIO1D2_GPIO            = 0,
+       GPIO1D2_LCDC0_DEN,
+
+       GPIO1D1_SHIFT           = 2,
+       GPIO1D1_MASK            = 1,
+       GPIO1D1_GPIO            = 0,
+       GPIO1D1_LCDC0_VSYNC,
+
+       GPIO1D0_SHIFT           = 0,
+       GPIO1D0_MASK            = 1,
+       GPIO1D0_GPIO            = 0,
+       GPIO1D0_LCDC0_HSYNC,
+};
+
+/* GRF_GPIO2C_IOMUX */
+enum {
+       GPIO2C1_SHIFT           = 2,
+       GPIO2C1_MASK            = 1,
+       GPIO2C1_GPIO            = 0,
+       GPIO2C1_I2C3CAM_SDA,
+
+       GPIO2C0_SHIFT           = 0,
+       GPIO2C0_MASK            = 1,
+       GPIO2C0_GPIO            = 0,
+       GPIO2C0_I2C3CAM_SCL,
+};
+
+/* GRF_GPIO3A_IOMUX */
+enum {
+       GPIO3A7_SHIFT           = 14,
+       GPIO3A7_MASK            = 3,
+       GPIO3A7_GPIO            = 0,
+       GPIO3A7_FLASH0_DATA7,
+       GPIO3A7_EMMC_DATA7,
+
+       GPIO3A6_SHIFT           = 12,
+       GPIO3A6_MASK            = 3,
+       GPIO3A6_GPIO            = 0,
+       GPIO3A6_FLASH0_DATA6,
+       GPIO3A6_EMMC_DATA6,
+
+       GPIO3A5_SHIFT           = 10,
+       GPIO3A5_MASK            = 3,
+       GPIO3A5_GPIO            = 0,
+       GPIO3A5_FLASH0_DATA5,
+       GPIO3A5_EMMC_DATA5,
+
+       GPIO3A4_SHIFT           = 8,
+       GPIO3A4_MASK            = 3,
+       GPIO3A4_GPIO            = 0,
+       GPIO3A4_FLASH0_DATA4,
+       GPIO3A4_EMMC_DATA4,
+
+       GPIO3A3_SHIFT           = 6,
+       GPIO3A3_MASK            = 3,
+       GPIO3A3_GPIO            = 0,
+       GPIO3A3_FLASH0_DATA3,
+       GPIO3A3_EMMC_DATA3,
+
+       GPIO3A2_SHIFT           = 4,
+       GPIO3A2_MASK            = 3,
+       GPIO3A2_GPIO            = 0,
+       GPIO3A2_FLASH0_DATA2,
+       GPIO3A2_EMMC_DATA2,
+
+       GPIO3A1_SHIFT           = 2,
+       GPIO3A1_MASK            = 3,
+       GPIO3A1_GPIO            = 0,
+       GPIO3A1_FLASH0_DATA1,
+       GPIO3A1_EMMC_DATA1,
+
+       GPIO3A0_SHIFT           = 0,
+       GPIO3A0_MASK            = 3,
+       GPIO3A0_GPIO            = 0,
+       GPIO3A0_FLASH0_DATA0,
+       GPIO3A0_EMMC_DATA0,
+};
+
+/* GRF_GPIO3B_IOMUX */
+enum {
+       GPIO3B7_SHIFT           = 14,
+       GPIO3B7_MASK            = 1,
+       GPIO3B7_GPIO            = 0,
+       GPIO3B7_FLASH0_CSN1,
+
+       GPIO3B6_SHIFT           = 12,
+       GPIO3B6_MASK            = 1,
+       GPIO3B6_GPIO            = 0,
+       GPIO3B6_FLASH0_CSN0,
+
+       GPIO3B5_SHIFT           = 10,
+       GPIO3B5_MASK            = 1,
+       GPIO3B5_GPIO            = 0,
+       GPIO3B5_FLASH0_WRN,
+
+       GPIO3B4_SHIFT           = 8,
+       GPIO3B4_MASK            = 1,
+       GPIO3B4_GPIO            = 0,
+       GPIO3B4_FLASH0_CLE,
+
+       GPIO3B3_SHIFT           = 6,
+       GPIO3B3_MASK            = 1,
+       GPIO3B3_GPIO            = 0,
+       GPIO3B3_FLASH0_ALE,
+
+       GPIO3B2_SHIFT           = 4,
+       GPIO3B2_MASK            = 1,
+       GPIO3B2_GPIO            = 0,
+       GPIO3B2_FLASH0_RDN,
+
+       GPIO3B1_SHIFT           = 2,
+       GPIO3B1_MASK            = 3,
+       GPIO3B1_GPIO            = 0,
+       GPIO3B1_FLASH0_WP,
+       GPIO3B1_EMMC_PWREN,
+
+       GPIO3B0_SHIFT           = 0,
+       GPIO3B0_MASK            = 1,
+       GPIO3B0_GPIO            = 0,
+       GPIO3B0_FLASH0_RDY,
+};
+
+/* GRF_GPIO3C_IOMUX */
+enum {
+       GPIO3C2_SHIFT           = 4,
+       GPIO3C2_MASK            = 3,
+       GPIO3C2_GPIO            = 0,
+       GPIO3C2_FLASH0_DQS,
+       GPIO3C2_EMMC_CLKOUT,
+
+       GPIO3C1_SHIFT           = 2,
+       GPIO3C1_MASK            = 3,
+       GPIO3C1_GPIO            = 0,
+       GPIO3C1_FLASH0_CSN3,
+       GPIO3C1_EMMC_RSTNOUT,
+
+       GPIO3C0_SHIFT           = 0,
+       GPIO3C0_MASK            = 3,
+       GPIO3C0_GPIO            = 0,
+       GPIO3C0_FLASH0_CSN2,
+       GPIO3C0_EMMC_CMD,
+};
+
+/* GRF_GPIO4C_IOMUX */
+enum {
+       GPIO4C7_SHIFT           = 14,
+       GPIO4C7_MASK            = 1,
+       GPIO4C7_GPIO            = 0,
+       GPIO4C7_SDIO0_DATA3,
+
+       GPIO4C6_SHIFT           = 12,
+       GPIO4C6_MASK            = 1,
+       GPIO4C6_GPIO            = 0,
+       GPIO4C6_SDIO0_DATA2,
+
+       GPIO4C5_SHIFT           = 10,
+       GPIO4C5_MASK            = 1,
+       GPIO4C5_GPIO            = 0,
+       GPIO4C5_SDIO0_DATA1,
+
+       GPIO4C4_SHIFT           = 8,
+       GPIO4C4_MASK            = 1,
+       GPIO4C4_GPIO            = 0,
+       GPIO4C4_SDIO0_DATA0,
+
+       GPIO4C3_SHIFT           = 6,
+       GPIO4C3_MASK            = 1,
+       GPIO4C3_GPIO            = 0,
+       GPIO4C3_UART0BT_RTSN,
+
+       GPIO4C2_SHIFT           = 4,
+       GPIO4C2_MASK            = 1,
+       GPIO4C2_GPIO            = 0,
+       GPIO4C2_UART0BT_CTSN,
+
+       GPIO4C1_SHIFT           = 2,
+       GPIO4C1_MASK            = 1,
+       GPIO4C1_GPIO            = 0,
+       GPIO4C1_UART0BT_SOUT,
+
+       GPIO4C0_SHIFT           = 0,
+       GPIO4C0_MASK            = 1,
+       GPIO4C0_GPIO            = 0,
+       GPIO4C0_UART0BT_SIN,
+};
+
+/* GRF_GPIO5B_IOMUX */
+enum {
+       GPIO5B7_SHIFT           = 14,
+       GPIO5B7_MASK            = 3,
+       GPIO5B7_GPIO            = 0,
+       GPIO5B7_SPI0_RXD,
+       GPIO5B7_TS0_DATA7,
+       GPIO5B7_UART4EXP_SIN,
+
+       GPIO5B6_SHIFT           = 12,
+       GPIO5B6_MASK            = 3,
+       GPIO5B6_GPIO            = 0,
+       GPIO5B6_SPI0_TXD,
+       GPIO5B6_TS0_DATA6,
+       GPIO5B6_UART4EXP_SOUT,
+
+       GPIO5B5_SHIFT           = 10,
+       GPIO5B5_MASK            = 3,
+       GPIO5B5_GPIO            = 0,
+       GPIO5B5_SPI0_CSN0,
+       GPIO5B5_TS0_DATA5,
+       GPIO5B5_UART4EXP_RTSN,
+
+       GPIO5B4_SHIFT           = 8,
+       GPIO5B4_MASK            = 3,
+       GPIO5B4_GPIO            = 0,
+       GPIO5B4_SPI0_CLK,
+       GPIO5B4_TS0_DATA4,
+       GPIO5B4_UART4EXP_CTSN,
+
+       GPIO5B3_SHIFT           = 6,
+       GPIO5B3_MASK            = 3,
+       GPIO5B3_GPIO            = 0,
+       GPIO5B3_UART1BB_RTSN,
+       GPIO5B3_TS0_DATA3,
+
+       GPIO5B2_SHIFT           = 4,
+       GPIO5B2_MASK            = 3,
+       GPIO5B2_GPIO            = 0,
+       GPIO5B2_UART1BB_CTSN,
+       GPIO5B2_TS0_DATA2,
+
+       GPIO5B1_SHIFT           = 2,
+       GPIO5B1_MASK            = 3,
+       GPIO5B1_GPIO            = 0,
+       GPIO5B1_UART1BB_SOUT,
+       GPIO5B1_TS0_DATA1,
+
+       GPIO5B0_SHIFT           = 0,
+       GPIO5B0_MASK            = 3,
+       GPIO5B0_GPIO            = 0,
+       GPIO5B0_UART1BB_SIN,
+       GPIO5B0_TS0_DATA0,
+};
+
+/* GRF_GPIO5C_IOMUX */
+enum {
+       GPIO5C3_SHIFT           = 6,
+       GPIO5C3_MASK            = 1,
+       GPIO5C3_GPIO            = 0,
+       GPIO5C3_TS0_ERR,
+
+       GPIO5C2_SHIFT           = 4,
+       GPIO5C2_MASK            = 1,
+       GPIO5C2_GPIO            = 0,
+       GPIO5C2_TS0_CLK,
+
+       GPIO5C1_SHIFT           = 2,
+       GPIO5C1_MASK            = 1,
+       GPIO5C1_GPIO            = 0,
+       GPIO5C1_TS0_VALID,
+
+       GPIO5C0_SHIFT           = 0,
+       GPIO5C0_MASK            = 3,
+       GPIO5C0_GPIO            = 0,
+       GPIO5C0_SPI0_CSN1,
+       GPIO5C0_TS0_SYNC,
+};
+
+/* GRF_GPIO6B_IOMUX */
+enum {
+       GPIO6B3_SHIFT           = 6,
+       GPIO6B3_MASK            = 1,
+       GPIO6B3_GPIO            = 0,
+       GPIO6B3_SPDIF_TX,
+
+       GPIO6B2_SHIFT           = 4,
+       GPIO6B2_MASK            = 1,
+       GPIO6B2_GPIO            = 0,
+       GPIO6B2_I2C1AUDIO_SCL,
+
+       GPIO6B1_SHIFT           = 2,
+       GPIO6B1_MASK            = 1,
+       GPIO6B1_GPIO            = 0,
+       GPIO6B1_I2C1AUDIO_SDA,
+
+       GPIO6B0_SHIFT           = 0,
+       GPIO6B0_MASK            = 1,
+       GPIO6B0_GPIO            = 0,
+       GPIO6B0_I2S_CLK,
+};
+
+/* GRF_GPIO6C_IOMUX */
+enum {
+       GPIO6C6_SHIFT           = 12,
+       GPIO6C6_MASK            = 1,
+       GPIO6C6_GPIO            = 0,
+       GPIO6C6_SDMMC0_DECTN,
+
+       GPIO6C5_SHIFT           = 10,
+       GPIO6C5_MASK            = 1,
+       GPIO6C5_GPIO            = 0,
+       GPIO6C5_SDMMC0_CMD,
+
+       GPIO6C4_SHIFT           = 8,
+       GPIO6C4_MASK            = 3,
+       GPIO6C4_GPIO            = 0,
+       GPIO6C4_SDMMC0_CLKOUT,
+       GPIO6C4_JTAG_TDO,
+
+       GPIO6C3_SHIFT           = 6,
+       GPIO6C3_MASK            = 3,
+       GPIO6C3_GPIO            = 0,
+       GPIO6C3_SDMMC0_DATA3,
+       GPIO6C3_JTAG_TCK,
+
+       GPIO6C2_SHIFT           = 4,
+       GPIO6C2_MASK            = 3,
+       GPIO6C2_GPIO            = 0,
+       GPIO6C2_SDMMC0_DATA2,
+       GPIO6C2_JTAG_TDI,
+
+       GPIO6C1_SHIFT           = 2,
+       GPIO6C1_MASK            = 3,
+       GPIO6C1_GPIO            = 0,
+       GPIO6C1_SDMMC0_DATA1,
+       GPIO6C1_JTAG_TRSTN,
+
+       GPIO6C0_SHIFT           = 0,
+       GPIO6C0_MASK            = 3,
+       GPIO6C0_GPIO            = 0,
+       GPIO6C0_SDMMC0_DATA0,
+       GPIO6C0_JTAG_TMS,
+};
+
+/* GRF_GPIO7A_IOMUX */
+enum {
+       GPIO7A7_SHIFT           = 14,
+       GPIO7A7_MASK            = 3,
+       GPIO7A7_GPIO            = 0,
+       GPIO7A7_UART3GPS_SIN,
+       GPIO7A7_GPS_MAG,
+       GPIO7A7_HSADCT1_DATA0,
+
+       GPIO7A1_SHIFT           = 2,
+       GPIO7A1_MASK            = 1,
+       GPIO7A1_GPIO            = 0,
+       GPIO7A1_PWM_1,
+
+       GPIO7A0_SHIFT           = 0,
+       GPIO7A0_MASK            = 3,
+       GPIO7A0_GPIO            = 0,
+       GPIO7A0_PWM_0,
+       GPIO7A0_VOP0_PWM,
+       GPIO7A0_VOP1_PWM,
+};
+
+/* GRF_GPIO7B_IOMUX */
+enum {
+       GPIO7B7_SHIFT           = 14,
+       GPIO7B7_MASK            = 3,
+       GPIO7B7_GPIO            = 0,
+       GPIO7B7_ISP_SHUTTERTRIG,
+       GPIO7B7_SPI1_TXD,
+
+       GPIO7B6_SHIFT           = 12,
+       GPIO7B6_MASK            = 3,
+       GPIO7B6_GPIO            = 0,
+       GPIO7B6_ISP_PRELIGHTTRIG,
+       GPIO7B6_SPI1_RXD,
+
+       GPIO7B5_SHIFT           = 10,
+       GPIO7B5_MASK            = 3,
+       GPIO7B5_GPIO            = 0,
+       GPIO7B5_ISP_FLASHTRIGOUT,
+       GPIO7B5_SPI1_CSN0,
+
+       GPIO7B4_SHIFT           = 8,
+       GPIO7B4_MASK            = 3,
+       GPIO7B4_GPIO            = 0,
+       GPIO7B4_ISP_SHUTTEREN,
+       GPIO7B4_SPI1_CLK,
+
+       GPIO7B3_SHIFT           = 6,
+       GPIO7B3_MASK            = 3,
+       GPIO7B3_GPIO            = 0,
+       GPIO7B3_USB_DRVVBUS1,
+       GPIO7B3_EDP_HOTPLUG,
+
+       GPIO7B2_SHIFT           = 4,
+       GPIO7B2_MASK            = 3,
+       GPIO7B2_GPIO            = 0,
+       GPIO7B2_UART3GPS_RTSN,
+       GPIO7B2_USB_DRVVBUS0,
+
+       GPIO7B1_SHIFT           = 2,
+       GPIO7B1_MASK            = 3,
+       GPIO7B1_GPIO            = 0,
+       GPIO7B1_UART3GPS_CTSN,
+       GPIO7B1_GPS_RFCLK,
+       GPIO7B1_GPST1_CLK,
+
+       GPIO7B0_SHIFT           = 0,
+       GPIO7B0_MASK            = 3,
+       GPIO7B0_GPIO            = 0,
+       GPIO7B0_UART3GPS_SOUT,
+       GPIO7B0_GPS_SIG,
+       GPIO7B0_HSADCT1_DATA1,
+};
+
+/* GRF_GPIO7CL_IOMUX */
+enum {
+       GPIO7C3_SHIFT           = 12,
+       GPIO7C3_MASK            = 3,
+       GPIO7C3_GPIO            = 0,
+       GPIO7C3_I2C5HDMI_SDA,
+       GPIO7C3_EDPHDMII2C_SDA,
+
+       GPIO7C2_SHIFT           = 8,
+       GPIO7C2_MASK            = 1,
+       GPIO7C2_GPIO            = 0,
+       GPIO7C2_I2C4TP_SCL,
+
+       GPIO7C1_SHIFT           = 4,
+       GPIO7C1_MASK            = 1,
+       GPIO7C1_GPIO            = 0,
+       GPIO7C1_I2C4TP_SDA,
+
+       GPIO7C0_SHIFT           = 0,
+       GPIO7C0_MASK            = 3,
+       GPIO7C0_GPIO            = 0,
+       GPIO7C0_ISP_FLASHTRIGIN,
+       GPIO7C0_EDPHDMI_CECINOUTT1,
+};
+
+/* GRF_GPIO7CH_IOMUX */
+enum {
+       GPIO7C7_SHIFT           = 12,
+       GPIO7C7_MASK            = 7,
+       GPIO7C7_GPIO            = 0,
+       GPIO7C7_UART2DBG_SOUT,
+       GPIO7C7_UART2DBG_SIROUT,
+       GPIO7C7_PWM_3,
+       GPIO7C7_EDPHDMI_CECINOUT,
+
+       GPIO7C6_SHIFT           = 8,
+       GPIO7C6_MASK            = 3,
+       GPIO7C6_GPIO            = 0,
+       GPIO7C6_UART2DBG_SIN,
+       GPIO7C6_UART2DBG_SIRIN,
+       GPIO7C6_PWM_2,
+
+       GPIO7C4_SHIFT           = 0,
+       GPIO7C4_MASK            = 3,
+       GPIO7C4_GPIO            = 0,
+       GPIO7C4_I2C5HDMI_SCL,
+       GPIO7C4_EDPHDMII2C_SCL,
+};
+
+/* GRF_GPIO8A_IOMUX */
+enum {
+       GPIO8A7_SHIFT           = 14,
+       GPIO8A7_MASK            = 3,
+       GPIO8A7_GPIO            = 0,
+       GPIO8A7_SPI2_CSN0,
+       GPIO8A7_SC_DETECT,
+       GPIO8A7_RESERVE,
+
+       GPIO8A6_SHIFT           = 12,
+       GPIO8A6_MASK            = 3,
+       GPIO8A6_GPIO            = 0,
+       GPIO8A6_SPI2_CLK,
+       GPIO8A6_SC_IO,
+       GPIO8A6_RESERVE,
+
+       GPIO8A5_SHIFT           = 10,
+       GPIO8A5_MASK            = 3,
+       GPIO8A5_GPIO            = 0,
+       GPIO8A5_I2C2SENSOR_SCL,
+       GPIO8A5_SC_CLK,
+
+       GPIO8A4_SHIFT           = 8,
+       GPIO8A4_MASK            = 3,
+       GPIO8A4_GPIO            = 0,
+       GPIO8A4_I2C2SENSOR_SDA,
+       GPIO8A4_SC_RST,
+
+       GPIO8A3_SHIFT           = 6,
+       GPIO8A3_MASK            = 3,
+       GPIO8A3_GPIO            = 0,
+       GPIO8A3_SPI2_CSN1,
+       GPIO8A3_SC_IOT1,
+
+       GPIO8A2_SHIFT           = 4,
+       GPIO8A2_MASK            = 1,
+       GPIO8A2_GPIO            = 0,
+       GPIO8A2_SC_DETECTT1,
+
+       GPIO8A1_SHIFT           = 2,
+       GPIO8A1_MASK            = 3,
+       GPIO8A1_GPIO            = 0,
+       GPIO8A1_PS2_DATA,
+       GPIO8A1_SC_VCC33V,
+
+       GPIO8A0_SHIFT           = 0,
+       GPIO8A0_MASK            = 3,
+       GPIO8A0_GPIO            = 0,
+       GPIO8A0_PS2_CLK,
+       GPIO8A0_SC_VCC18V,
+};
+
+/* GRF_GPIO8B_IOMUX */
+enum {
+       GPIO8B1_SHIFT           = 2,
+       GPIO8B1_MASK            = 3,
+       GPIO8B1_GPIO            = 0,
+       GPIO8B1_SPI2_TXD,
+       GPIO8B1_SC_CLK,
+
+       GPIO8B0_SHIFT           = 0,
+       GPIO8B0_MASK            = 3,
+       GPIO8B0_GPIO            = 0,
+       GPIO8B0_SPI2_RXD,
+       GPIO8B0_SC_RST,
+};
+
+/* GRF_SOC_CON0 */
+enum {
+       PAUSE_MMC_PERI_SHIFT    = 0xf,
+       PAUSE_MMC_PERI_MASK     = 1,
+
+       PAUSE_EMEM_PERI_SHIFT   = 0xe,
+       PAUSE_EMEM_PERI_MASK    = 1,
+
+       PAUSE_USB_PERI_SHIFT    = 0xd,
+       PAUSE_USB_PERI_MASK     = 1,
+
+       GRF_FORCE_JTAG_SHIFT    = 0xc,
+       GRF_FORCE_JTAG_MASK     = 1,
+
+       GRF_CORE_IDLE_REQ_MODE_SEL1_SHIFT = 0xb,
+       GRF_CORE_IDLE_REQ_MODE_SEL1_MASK = 1,
+
+       GRF_CORE_IDLE_REQ_MODE_SEL0_SHIFT = 0xa,
+       GRF_CORE_IDLE_REQ_MODE_SEL0_MASK = 1,
+
+       DDR1_16BIT_EN_SHIFT     = 9,
+       DDR1_16BIT_EN_MASK      = 1,
+
+       DDR0_16BIT_EN_SHIFT     = 8,
+       DDR0_16BIT_EN_MASK      = 1,
+
+       VCODEC_SHIFT            = 7,
+       VCODEC_MASK             = 1,
+       VCODEC_SELECT_VEPU_ACLK = 0,
+       VCODEC_SELECT_VDPU_ACLK,
+
+       UPCTL1_C_ACTIVE_IN_SHIFT = 6,
+       UPCTL1_C_ACTIVE_IN_MASK = 1,
+       UPCTL1_C_ACTIVE_IN_MAY  = 0,
+       UPCTL1_C_ACTIVE_IN_WILL,
+
+       UPCTL0_C_ACTIVE_IN_SHIFT = 5,
+       UPCTL0_C_ACTIVE_IN_MASK = 1,
+       UPCTL0_C_ACTIVE_IN_MAY  = 0,
+       UPCTL0_C_ACTIVE_IN_WILL,
+
+       MSCH1_MAINDDR3_SHIFT    = 4,
+       MSCH1_MAINDDR3_MASK     = 1,
+       MSCH1_MAINDDR3_DDR3     = 1,
+
+       MSCH0_MAINDDR3_SHIFT    = 3,
+       MSCH0_MAINDDR3_MASK     = 1,
+       MSCH0_MAINDDR3_DDR3     = 1,
+
+       MSCH1_MAINPARTIALPOP_SHIFT = 2,
+       MSCH1_MAINPARTIALPOP_MASK = 1,
+
+       MSCH0_MAINPARTIALPOP_SHIFT = 1,
+       MSCH0_MAINPARTIALPOP_MASK = 1,
+};
+
+/* GRF_SOC_CON2 */
+enum {
+       UPCTL1_LPDDR3_ODT_EN_SHIFT = 0xd,
+       UPCTL1_LPDDR3_ODT_EN_MASK = 1,
+       UPCTL1_LPDDR3_ODT_EN_ODT = 1,
+
+       UPCTL1_BST_DIABLE_SHIFT = 0xc,
+       UPCTL1_BST_DIABLE_MASK  = 1,
+       UPCTL1_BST_DIABLE_DISABLE = 1,
+
+       LPDDR3_EN1_SHIFT        = 0xb,
+       LPDDR3_EN1_MASK         = 1,
+       LPDDR3_EN1_LPDDR3       = 1,
+
+       UPCTL0_LPDDR3_ODT_EN_SHIFT = 0xa,
+       UPCTL0_LPDDR3_ODT_EN_MASK = 1,
+       UPCTL0_LPDDR3_ODT_EN_ODT_ENABLE = 1,
+
+       UPCTL0_BST_DIABLE_SHIFT = 9,
+       UPCTL0_BST_DIABLE_MASK  = 1,
+       UPCTL0_BST_DIABLE_DISABLE = 1,
+
+       LPDDR3_EN0_SHIFT        = 8,
+       LPDDR3_EN0_MASK         = 1,
+       LPDDR3_EN0_LPDDR3       = 1,
+
+       GRF_POC_FLASH0_CTRL_SHIFT = 7,
+       GRF_POC_FLASH0_CTRL_MASK = 1,
+       GRF_POC_FLASH0_CTRL_GPIO3C_3 = 0,
+       GRF_POC_FLASH0_CTRL_GRF_IO_VSEL,
+
+       SIMCARD_MUX_SHIFT       = 6,
+       SIMCARD_MUX_MASK        = 1,
+       SIMCARD_MUX_USE_A       = 1,
+       SIMCARD_MUX_USE_B       = 0,
+
+       GRF_SPDIF_2CH_EN_SHIFT  = 1,
+       GRF_SPDIF_2CH_EN_MASK   = 1,
+       GRF_SPDIF_2CH_EN_8CH    = 0,
+       GRF_SPDIF_2CH_EN_2CH,
+
+       PWM_SHIFT               = 0,
+       PWM_MASK                = 1,
+       PWM_RK                  = 1,
+       PWM_PWM                 = 0,
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/hardware.h b/arch/arm/include/asm/arch-rockchip/hardware.h
new file mode 100644 (file)
index 0000000..d5af5b8
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_HARDWARE_H
+#define _ASM_ARCH_HARDWARE_H
+
+#define RK_CLRSETBITS(clr, set)                ((((clr) | (set)) << 16) | set)
+#define RK_SETBITS(set)                        RK_CLRSETBITS(0, set)
+#define RK_CLRBITS(clr)                        RK_CLRSETBITS(clr, 0)
+
+#define TIMER7_BASE            0xff810020
+
+#define rk_clrsetreg(addr, clr, set)   writel((clr) << 16 | (set), addr)
+#define rk_clrreg(addr, clr)           writel((clr) << 16, addr)
+#define rk_setreg(addr, set)           writel(set, addr)
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/i2c.h b/arch/arm/include/asm/arch-rockchip/i2c.h
new file mode 100644 (file)
index 0000000..d81f8ff
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Jaehoon Chung <jh80.chung@samsung.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __ASM_ARCH_I2C_H
+#define __ASM_ARCH_I2C_H
+
+struct i2c_regs {
+       u32 con;
+       u32 clkdiv;
+       u32 mrxaddr;
+       u32 mrxraddr;
+       u32 mtxcnt;
+       u32 mrxcnt;
+       u32 ien;
+       u32 ipd;
+       u32 fcnt;
+       u32 reserved0[0x37];
+       u32 txdata[8];
+       u32 reserved1[0x38];
+       u32 rxdata[8];
+};
+
+/* Control register */
+#define I2C_CON_EN             (1 << 0)
+#define I2C_CON_MOD(mod)       ((mod) << 1)
+#define I2C_MODE_TX            0x00
+#define I2C_MODE_TRX           0x01
+#define I2C_MODE_RX            0x02
+#define I2C_MODE_RRX           0x03
+#define I2C_CON_MASK           (3 << 1)
+
+#define I2C_CON_START          (1 << 3)
+#define I2C_CON_STOP           (1 << 4)
+#define I2C_CON_LASTACK                (1 << 5)
+#define I2C_CON_ACTACK         (1 << 6)
+
+/* Clock dividor register */
+#define I2C_CLKDIV_VAL(divl, divh) \
+       (((divl) & 0xffff) | (((divh) << 16) & 0xffff0000))
+
+/* the slave address accessed  for master rx mode */
+#define I2C_MRXADDR_SET(vld, addr)     (((vld) << 24) | (addr))
+
+/* the slave register address accessed  for master rx mode */
+#define I2C_MRXRADDR_SET(vld, raddr)   (((vld) << 24) | (raddr))
+
+/* interrupt enable register */
+#define I2C_BTFIEN             (1 << 0)
+#define I2C_BRFIEN             (1 << 1)
+#define I2C_MBTFIEN            (1 << 2)
+#define I2C_MBRFIEN            (1 << 3)
+#define I2C_STARTIEN           (1 << 4)
+#define I2C_STOPIEN            (1 << 5)
+#define I2C_NAKRCVIEN          (1 << 6)
+
+/* interrupt pending register */
+#define I2C_BTFIPD              (1 << 0)
+#define I2C_BRFIPD              (1 << 1)
+#define I2C_MBTFIPD             (1 << 2)
+#define I2C_MBRFIPD             (1 << 3)
+#define I2C_STARTIPD            (1 << 4)
+#define I2C_STOPIPD             (1 << 5)
+#define I2C_NAKRCVIPD           (1 << 6)
+#define I2C_IPD_ALL_CLEAN       0x7f
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/periph.h b/arch/arm/include/asm/arch-rockchip/periph.h
new file mode 100644 (file)
index 0000000..fa6069b
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_PERIPH_H
+#define _ASM_ARCH_PERIPH_H
+
+/*
+ * The peripherals supported by the hardware. This is used to specify clocks
+ * and pinctrl settings. Some SoCs will not support all of these, but it
+ * provides a common reference for common drivers to use.
+ */
+enum periph_id {
+       PERIPH_ID_PWM0,
+       PERIPH_ID_PWM1,
+       PERIPH_ID_PWM2,
+       PERIPH_ID_PWM3,
+       PERIPH_ID_PWM4,
+       PERIPH_ID_I2C0,
+       PERIPH_ID_I2C1,
+       PERIPH_ID_I2C2,
+       PERIPH_ID_I2C3,
+       PERIPH_ID_I2C4,
+       PERIPH_ID_I2C5,
+       PERIPH_ID_SPI0,
+       PERIPH_ID_SPI1,
+       PERIPH_ID_SPI2,
+       PERIPH_ID_UART0,
+       PERIPH_ID_UART1,
+       PERIPH_ID_UART2,
+       PERIPH_ID_UART3,
+       PERIPH_ID_UART4,
+       PERIPH_ID_LCDC0,
+       PERIPH_ID_LCDC1,
+       PERIPH_ID_SDMMC0,
+       PERIPH_ID_SDMMC1,
+       PERIPH_ID_SDMMC2,
+       PERIPH_ID_HDMI,
+
+       PERIPH_ID_COUNT,
+
+       /* Some aliases */
+       PERIPH_ID_EMMC = PERIPH_ID_SDMMC0,
+       PERIPH_ID_SDCARD = PERIPH_ID_SDMMC1,
+       PERIPH_ID_UART_BT = PERIPH_ID_UART0,
+       PERIPH_ID_UART_BB = PERIPH_ID_UART1,
+       PERIPH_ID_UART_DBG = PERIPH_ID_UART2,
+       PERIPH_ID_UART_GPS = PERIPH_ID_UART3,
+       PERIPH_ID_UART_EXP = PERIPH_ID_UART4,
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/pmu_rk3288.h b/arch/arm/include/asm/arch-rockchip/pmu_rk3288.h
new file mode 100644 (file)
index 0000000..12fa685
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _ASM_ARCH_PMU_RK3288_H
+#define _ASM_ARCH_PMU_RK3288_H
+
+struct rk3288_pmu {
+       u32 wakeup_cfg[2];
+       u32 pwrdn_con;
+       u32 pwrdn_st;
+
+       u32 idle_req;
+       u32 idle_st;
+       u32 pwrmode_con;
+       u32 pwr_state;
+
+       u32 osc_cnt;
+       u32 pll_cnt;
+       u32 stabl_cnt;
+       u32 ddr0io_pwron_cnt;
+
+       u32 ddr1io_pwron_cnt;
+       u32 core_pwrdn_cnt;
+       u32 core_pwrup_cnt;
+       u32 gpu_pwrdn_cnt;
+
+       u32 gpu_pwrup_cnt;
+       u32 wakeup_rst_clr_cnt;
+       u32 sft_con;
+       u32 ddr_sref_st;
+
+       u32 int_con;
+       u32 int_st;
+       u32 boot_addr_sel;
+       u32 grf_con;
+
+       u32 gpio_sr;
+       u32 gpio0pull[3];
+
+       u32 gpio0drv[3];
+       u32 gpio_op;
+
+       u32 gpio0_sel18;        /* 0x80 */
+       u32 gpio0a_iomux;
+       u32 gpio0b_iomux;
+       u32 gpio0c_iomux;
+       u32 gpio0d_iomux;
+       u32 sys_reg[4];
+};
+check_member(rk3288_pmu, sys_reg[3], 0x00a0);
+
+/* PMU_GPIO0_B_IOMUX */
+enum {
+       GPIO0_B7_SHIFT          = 14,
+       GPIO0_B7_MASK           = 1,
+       GPIO0_B7_GPIOB7         = 0,
+       GPIO0_B7_I2C0PMU_SDA,
+
+       GPIO0_B5_SHIFT          = 10,
+       GPIO0_B5_MASK           = 1,
+       GPIO0_B5_GPIOB5         = 0,
+       GPIO0_B5_CLK_27M,
+
+       GPIO0_B2_SHIFT          = 4,
+       GPIO0_B2_MASK           = 1,
+       GPIO0_B2_GPIOB2         = 0,
+       GPIO0_B2_TSADC_INT,
+};
+
+/* PMU_GPIO0_C_IOMUX */
+enum {
+       GPIO0_C1_SHIFT          = 2,
+       GPIO0_C1_MASK           = 3,
+       GPIO0_C1_GPIOC1         = 0,
+       GPIO0_C1_TEST_CLKOUT,
+       GPIO0_C1_CLKT1_27M,
+
+       GPIO0_C0_SHIFT          = 0,
+       GPIO0_C0_MASK           = 1,
+       GPIO0_C0_GPIOC0         = 0,
+       GPIO0_C0_I2C0PMU_SCL,
+};
+
+#endif
diff --git a/arch/arm/include/asm/arch-rockchip/sdram.h b/arch/arm/include/asm/arch-rockchip/sdram.h
new file mode 100644 (file)
index 0000000..d3de42d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#ifndef _ASM_ARCH_RK3288_SDRAM_H__
+#define _ASM_ARCH_RK3288_SDRAM_H__
+
+enum {
+       DDR3 = 3,
+       LPDDR3 = 6,
+       UNUSED = 0xFF,
+};
+
+struct rk3288_sdram_channel {
+       u8 rank;
+       u8 col;
+       u8 bk;
+       u8 bw;
+       u8 dbw;
+       u8 row_3_4;
+       u8 cs0_row;
+       u8 cs1_row;
+};
+
+struct rk3288_sdram_pctl_timing {
+       u32 togcnt1u;
+       u32 tinit;
+       u32 trsth;
+       u32 togcnt100n;
+       u32 trefi;
+       u32 tmrd;
+       u32 trfc;
+       u32 trp;
+       u32 trtw;
+       u32 tal;
+       u32 tcl;
+       u32 tcwl;
+       u32 tras;
+       u32 trc;
+       u32 trcd;
+       u32 trrd;
+       u32 trtp;
+       u32 twr;
+       u32 twtr;
+       u32 texsr;
+       u32 txp;
+       u32 txpdll;
+       u32 tzqcs;
+       u32 tzqcsi;
+       u32 tdqs;
+       u32 tcksre;
+       u32 tcksrx;
+       u32 tcke;
+       u32 tmod;
+       u32 trstl;
+       u32 tzqcl;
+       u32 tmrr;
+       u32 tckesr;
+       u32 tdpd;
+};
+check_member(rk3288_sdram_pctl_timing, tdpd, 0x144 - 0xc0);
+
+struct rk3288_sdram_phy_timing {
+       u32 dtpr0;
+       u32 dtpr1;
+       u32 dtpr2;
+       u32 mr[4];
+};
+
+struct rk3288_base_params {
+       u32 noc_timing;
+       u32 noc_activate;
+       u32 ddrconfig;
+       u32 ddr_freq;
+       u32 dramtype;
+       u32 stride;
+       u32 odt;
+};
+
+struct rk3288_sdram_params {
+       struct rk3288_sdram_channel ch[2];
+       struct rk3288_sdram_pctl_timing pctl_timing;
+       struct rk3288_sdram_phy_timing phy_timing;
+       struct rk3288_base_params base;
+       int num_channels;
+};
+
+#endif
index 51497cc..f717103 100644 (file)
@@ -48,7 +48,9 @@ obj-y += interrupts_64.o
 else
 obj-y  += interrupts.o
 endif
+ifndef CONFIG_RESET
 obj-y  += reset.o
+endif
 
 obj-y  += cache.o
 ifndef CONFIG_ARM64
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
new file mode 100644 (file)
index 0000000..ab50f4e
--- /dev/null
@@ -0,0 +1,41 @@
+if ARCH_ROCKCHIP
+
+config ROCKCHIP_RK3288
+       bool "Support Rockchip RK3288"
+       help
+         The Rockchip RK3288 is a ARM-based SoC with a quad-core Cortex-A17
+         including NEON and GPU, 1MB L2 cache, Mali-T7 graphics, two
+         video interfaces supporting HDMI and eDP, several DDR3 options
+         and video codec support. Peripherals include Gigabit Ethernet,
+         USB2 host and OTG, SDIO, I2S, UART,s, SPI, I2C and PWMs.
+
+config SYS_MALLOC_F
+       default y
+
+config SYS_MALLOC_F_LEN
+       default 0x800
+
+config SPL_DM
+       default y
+
+config DM_SERIAL
+       default y
+
+config DM_SPI
+       default y
+
+config DM_SPI_FLASH
+       default y
+
+config DM_I2C
+       default y
+
+config DM_GPIO
+       default y
+
+config ROCKCHIP_SERIAL
+       default y
+
+source "arch/arm/mach-rockchip/rk3288/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile
new file mode 100644 (file)
index 0000000..5a4e383
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Copyright (c) 2014 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+ifdef CONFIG_SPL_BUILD
+obj-y += board-spl.o
+else
+obj-y += board.o
+endif
+obj-y += common.o
+obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/
diff --git a/arch/arm/mach-rockchip/board-spl.c b/arch/arm/mach-rockchip/board-spl.c
new file mode 100644 (file)
index 0000000..a241d96
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <debug_uart.h>
+#include <dm.h>
+#include <fdtdec.h>
+#include <led.h>
+#include <malloc.h>
+#include <ram.h>
+#include <spl.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/sdram.h>
+#include <dm/pinctrl.h>
+#include <dm/root.h>
+#include <dm/test.h>
+#include <dm/util.h>
+#include <power/regulator.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 spl_boot_device(void)
+{
+       const void *blob = gd->fdt_blob;
+       struct udevice *dev;
+       const char *bootdev;
+       int node;
+       int ret;
+
+       bootdev = fdtdec_get_config_string(blob, "u-boot,boot0");
+       debug("Boot device %s\n", bootdev);
+       if (!bootdev)
+               goto fallback;
+
+       node = fdt_path_offset(blob, bootdev);
+       if (node < 0) {
+               debug("node=%d\n", node);
+               goto fallback;
+       }
+       ret = device_get_global_by_of_offset(node, &dev);
+       if (ret) {
+               debug("device at node %s/%d not found: %d\n", bootdev, node,
+                     ret);
+               goto fallback;
+       }
+       debug("Found device %s\n", dev->name);
+       switch (device_get_uclass_id(dev)) {
+       case UCLASS_SPI_FLASH:
+               return BOOT_DEVICE_SPI;
+       case UCLASS_MMC:
+               return BOOT_DEVICE_MMC1;
+       default:
+               debug("Booting from device uclass '%s' not supported\n",
+                     dev_get_uclass_name(dev));
+       }
+
+fallback:
+       return BOOT_DEVICE_MMC1;
+}
+
+u32 spl_boot_mode(void)
+{
+       return MMCSD_MODE_RAW;
+}
+
+/* read L2 control register (L2CTLR) */
+static inline uint32_t read_l2ctlr(void)
+{
+       uint32_t val = 0;
+
+       asm volatile ("mrc p15, 1, %0, c9, c0, 2" : "=r" (val));
+
+       return val;
+}
+
+/* write L2 control register (L2CTLR) */
+static inline void write_l2ctlr(uint32_t val)
+{
+       /*
+        * Note: L2CTLR can only be written when the L2 memory system
+        * is idle, ie before the MMU is enabled.
+        */
+       asm volatile("mcr p15, 1, %0, c9, c0, 2" : : "r" (val) : "memory");
+       isb();
+}
+
+static void configure_l2ctlr(void)
+{
+       uint32_t l2ctlr;
+
+       l2ctlr = read_l2ctlr();
+       l2ctlr &= 0xfffc0000; /* clear bit0~bit17 */
+
+       /*
+       * Data RAM write latency: 2 cycles
+       * Data RAM read latency: 2 cycles
+       * Data RAM setup latency: 1 cycle
+       * Tag RAM write latency: 1 cycle
+       * Tag RAM read latency: 1 cycle
+       * Tag RAM setup latency: 1 cycle
+       */
+       l2ctlr |= (1 << 3 | 1 << 0);
+       write_l2ctlr(l2ctlr);
+}
+
+struct rk3288_timer {
+       u32 timer_load_count0;
+       u32 timer_load_count1;
+       u32 timer_curr_value0;
+       u32 timer_curr_value1;
+       u32 timer_ctrl_reg;
+       u32 timer_int_status;
+};
+
+void init_timer(void)
+{
+       struct rk3288_timer * const timer7_ptr = (void *)TIMER7_BASE;
+
+       writel(0xffffffff, &timer7_ptr->timer_load_count0);
+       writel(0xffffffff, &timer7_ptr->timer_load_count1);
+       writel(1, &timer7_ptr->timer_ctrl_reg);
+}
+
+static int configure_emmc(struct udevice *pinctrl)
+{
+       struct gpio_desc desc;
+       int ret;
+
+       pinctrl_request_noflags(pinctrl, PERIPH_ID_EMMC);
+
+       /*
+        * TODO(sjg@chromium.org): Pick this up from device tree or perhaps
+        * use the EMMC_PWREN setting.
+        */
+       ret = dm_gpio_lookup_name("D9", &desc);
+       if (ret) {
+               debug("gpio ret=%d\n", ret);
+               return ret;
+       }
+       ret = dm_gpio_request(&desc, "emmc_pwren");
+       if (ret) {
+               debug("gpio_request ret=%d\n", ret);
+               return ret;
+       }
+       ret = dm_gpio_set_dir_flags(&desc, GPIOD_IS_OUT);
+       if (ret) {
+               debug("gpio dir ret=%d\n", ret);
+               return ret;
+       }
+       ret = dm_gpio_set_value(&desc, 1);
+       if (ret) {
+               debug("gpio value ret=%d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void board_init_f(ulong dummy)
+{
+       struct udevice *pinctrl;
+       struct udevice *dev;
+       int ret;
+
+       /* Example code showing how to enable the debug UART on RK3288 */
+#ifdef EARLY_UART
+#include <asm/arch/grf_rk3288.h>
+       /* Enable early UART on the RK3288 */
+#define GRF_BASE       0xff770000
+       struct rk3288_grf * const grf = (void *)GRF_BASE;
+
+       rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C7_MASK << GPIO7C7_SHIFT |
+                    GPIO7C6_MASK << GPIO7C6_SHIFT,
+                    GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
+                    GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
+       /*
+        * Debug UART can be used from here if required:
+        *
+        * debug_uart_init();
+        * printch('a');
+        * printhex8(0x1234);
+        * printascii("string");
+        */
+       debug_uart_init();
+#endif
+
+       ret = spl_init();
+       if (ret) {
+               debug("spl_init() failed: %d\n", ret);
+               hang();
+       }
+
+       init_timer();
+       configure_l2ctlr();
+
+       ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+       if (ret) {
+               debug("CLK init failed: %d\n", ret);
+               return;
+       }
+
+       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+       if (ret) {
+               debug("Pinctrl init failed: %d\n", ret);
+               return;
+       }
+
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret) {
+               debug("DRAM init failed: %d\n", ret);
+               return;
+       }
+}
+
+static int setup_led(void)
+{
+#ifdef CONFIG_SPL_LED
+       struct udevice *dev;
+       char *led_name;
+       int ret;
+
+       led_name = fdtdec_get_config_string(gd->fdt_blob, "u-boot,boot-led");
+       if (!led_name)
+               return 0;
+       ret = led_get_by_label(led_name, &dev);
+       if (ret) {
+               debug("%s: get=%d\n", __func__, ret);
+               return ret;
+       }
+       ret = led_set_on(dev, 1);
+       if (ret)
+               return ret;
+#endif
+
+       return 0;
+}
+
+void spl_board_init(void)
+{
+       struct udevice *pinctrl;
+       int ret;
+
+       ret = setup_led();
+
+       if (ret) {
+               debug("LED ret=%d\n", ret);
+               hang();
+       }
+
+       ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
+       if (ret) {
+               debug("%s: Cannot find pinctrl device\n", __func__);
+               goto err;
+       }
+       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_SDCARD);
+       if (ret) {
+               debug("%s: Failed to set up SD card\n", __func__);
+               goto err;
+       }
+       ret = configure_emmc(pinctrl);
+       if (ret) {
+               debug("%s: Failed to set up eMMC\n", __func__);
+               goto err;
+       }
+
+       /* Enable debug UART */
+       ret = pinctrl_request_noflags(pinctrl, PERIPH_ID_UART_DBG);
+       if (ret) {
+               debug("%s: Failed to set up console UART\n", __func__);
+               goto err;
+       }
+
+       preloader_console_init();
+       return;
+err:
+       printf("spl_board_init: Error %d\n", ret);
+
+       /* No way to report error here */
+       hang();
+}
diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
new file mode 100644 (file)
index 0000000..688bc0f
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ram.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+int board_init(void)
+{
+       return 0;
+}
+
+int dram_init(void)
+{
+       struct ram_info ram;
+       struct udevice *dev;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret) {
+               debug("DRAM init failed: %d\n", ret);
+               return ret;
+       }
+       ret = ram_get_info(dev, &ram);
+       if (ret) {
+               debug("Cannot get DRAM size: %d\n", ret);
+               return ret;
+       }
+       debug("SDRAM base=%lx, size=%x\n", ram.base, ram.size);
+       gd->ram_size = ram.size;
+
+       return 0;
+}
+
+#ifndef CONFIG_SYS_DCACHE_OFF
+void enable_caches(void)
+{
+       /* Enable D-cache. I-cache is already enabled in start.S */
+       dcache_enable();
+}
+#endif
diff --git a/arch/arm/mach-rockchip/common.c b/arch/arm/mach-rockchip/common.c
new file mode 100644 (file)
index 0000000..fc7ac72
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <linux/err.h>
+
+void *rockchip_get_cru(void)
+{
+       struct udevice *dev;
+       fdt_addr_t addr;
+       int ret;
+
+       ret = uclass_get_device(UCLASS_CLK, 0, &dev);
+       if (ret)
+               return ERR_PTR(ret);
+
+       addr = dev_get_addr(dev);
+       if (addr == FDT_ADDR_T_NONE)
+               return ERR_PTR(-EINVAL);
+
+       return (void *)addr;
+}
diff --git a/arch/arm/mach-rockchip/rk3288/Kconfig b/arch/arm/mach-rockchip/rk3288/Kconfig
new file mode 100644 (file)
index 0000000..4d0f1b5
--- /dev/null
@@ -0,0 +1,26 @@
+if ROCKCHIP_RK3288
+
+config TARGET_FIREFLY_RK3288
+       bool "Firefly-RK3288"
+       help
+         Firefly is a RK3288-based development board with 2 USB ports,
+         HDMI, VGA, micro-SD card, audio, WiFi  and Gigabit Ethernet, It
+         also includes on-board eMMC and 1GB of SDRAM. Expansion connectors
+         provide access to display pins, I2C, SPI, UART and GPIOs.
+
+config TARGET_CHROMEBOOK_JERRY
+       bool "Google/Rockchip Veyron-Jerry Chromebook"
+       help
+         Jerry is a RK3288-based clamshell device with 2 USB 3.0 ports,
+         HDMI, an 11.9 inch EDP display, micro-SD card, touchpad and
+         WiFi. It includes a Chrome OS EC (Cortex-M3) to provide access to
+         the keyboard and battery functions.
+
+config SYS_SOC
+       default "rockchip"
+
+source "board/google/chromebook_jerry/Kconfig"
+
+source "board/firefly/firefly-rk3288/Kconfig"
+
+endif
diff --git a/arch/arm/mach-rockchip/rk3288/Makefile b/arch/arm/mach-rockchip/rk3288/Makefile
new file mode 100644 (file)
index 0000000..6f62375
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Copyright (c) 2015 Google, Inc
+#
+# SPDX-License-Identifier:      GPL-2.0+
+#
+
+obj-y += reset_rk3288.o
+obj-y += sdram_rk3288.o
+obj-y += syscon_rk3288.o
diff --git a/arch/arm/mach-rockchip/rk3288/reset_rk3288.c b/arch/arm/mach-rockchip/rk3288/reset_rk3288.c
new file mode 100644 (file)
index 0000000..7affd11
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <reset.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
+#include <asm/arch/hardware.h>
+#include <linux/err.h>
+
+int rk3288_reset_request(struct udevice *dev, enum reset_t type)
+{
+       struct rk3288_cru *cru = rockchip_get_cru();
+
+       if (IS_ERR(cru))
+               return PTR_ERR(cru);
+       switch (type) {
+       case RESET_WARM:
+               writel(RK_CLRBITS(0xffff), &cru->cru_mode_con);
+               writel(0xeca8, &cru->cru_glb_srst_snd_value);
+               break;
+       case RESET_COLD:
+               writel(RK_CLRBITS(0xffff), &cru->cru_mode_con);
+               writel(0xfdb9, &cru->cru_glb_srst_fst_value);
+               break;
+       default:
+               return -EPROTONOSUPPORT;
+       }
+
+       return -EINPROGRESS;
+}
+
+static struct reset_ops rk3288_reset = {
+       .request        = rk3288_reset_request,
+};
+
+U_BOOT_DRIVER(reset_rk3288) = {
+       .name   = "rk3288_reset",
+       .id     = UCLASS_RESET,
+       .ops    = &rk3288_reset,
+};
diff --git a/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c b/arch/arm/mach-rockchip/rk3288/sdram_rk3288.c
new file mode 100644 (file)
index 0000000..09017cc
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Copyright 2014 Rockchip Inc.
+ *
+ * SPDX-License-Identifier:     GPL-2.0
+ *
+ * Adapted from coreboot.
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <ram.h>
+#include <regmap.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
+#include <asm/arch/ddr_rk3288.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <asm/arch/sdram.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct chan_info {
+       struct rk3288_ddr_pctl *pctl;
+       struct rk3288_ddr_publ *publ;
+       struct rk3288_msch *msch;
+};
+
+struct dram_info {
+       struct chan_info chan[2];
+       struct ram_info info;
+       struct udevice *ddr_clk;
+       struct rk3288_cru *cru;
+       struct rk3288_grf *grf;
+       struct rk3288_sgrf *sgrf;
+       struct rk3288_pmu *pmu;
+};
+
+#ifdef CONFIG_SPL_BUILD
+static void copy_to_reg(u32 *dest, const u32 *src, u32 n)
+{
+       int i;
+
+       for (i = 0; i < n / sizeof(u32); i++) {
+               writel(*src, dest);
+               src++;
+               dest++;
+       }
+}
+
+static void ddr_reset(struct rk3288_cru *cru, u32 ch, u32 ctl, u32 phy)
+{
+       u32 phy_ctl_srstn_shift = 4 + 5 * ch;
+       u32 ctl_psrstn_shift = 3 + 5 * ch;
+       u32 ctl_srstn_shift = 2 + 5 * ch;
+       u32 phy_psrstn_shift = 1 + 5 * ch;
+       u32 phy_srstn_shift = 5 * ch;
+
+       rk_clrsetreg(&cru->cru_softrst_con[10],
+                    1 << phy_ctl_srstn_shift | 1 << ctl_psrstn_shift |
+                    1 << ctl_srstn_shift | 1 << phy_psrstn_shift |
+                    1 << phy_srstn_shift,
+                    phy << phy_ctl_srstn_shift | ctl << ctl_psrstn_shift |
+                    ctl << ctl_srstn_shift | phy << phy_psrstn_shift |
+                    phy << phy_srstn_shift);
+}
+
+static void ddr_phy_ctl_reset(struct rk3288_cru *cru, u32 ch, u32 n)
+{
+       u32 phy_ctl_srstn_shift = 4 + 5 * ch;
+
+       rk_clrsetreg(&cru->cru_softrst_con[10],
+                    1 << phy_ctl_srstn_shift, n << phy_ctl_srstn_shift);
+}
+
+static void phy_pctrl_reset(struct rk3288_cru *cru,
+                           struct rk3288_ddr_publ *publ,
+                           u32 channel)
+{
+       int i;
+
+       ddr_reset(cru, channel, 1, 1);
+       udelay(1);
+       clrbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
+       for (i = 0; i < 4; i++)
+               clrbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
+
+       udelay(10);
+       setbits_le32(&publ->acdllcr, ACDLLCR_DLLSRST);
+       for (i = 0; i < 4; i++)
+               setbits_le32(&publ->datx8[i].dxdllcr, DXDLLCR_DLLSRST);
+
+       udelay(10);
+       ddr_reset(cru, channel, 1, 0);
+       udelay(10);
+       ddr_reset(cru, channel, 0, 0);
+       udelay(10);
+}
+
+static void phy_dll_bypass_set(struct rk3288_ddr_publ *publ,
+       u32 freq)
+{
+       int i;
+       if (freq <= 250000000) {
+               if (freq <= 150000000)
+                       clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+               else
+                       setbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+               setbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
+               for (i = 0; i < 4; i++)
+                       setbits_le32(&publ->datx8[i].dxdllcr,
+                                    DXDLLCR_DLLDIS);
+
+               setbits_le32(&publ->pir, PIR_DLLBYP);
+       } else {
+               clrbits_le32(&publ->dllgcr, SBIAS_BYPASS);
+               clrbits_le32(&publ->acdllcr, ACDLLCR_DLLDIS);
+               for (i = 0; i < 4; i++) {
+                       clrbits_le32(&publ->datx8[i].dxdllcr,
+                                    DXDLLCR_DLLDIS);
+               }
+
+               clrbits_le32(&publ->pir, PIR_DLLBYP);
+       }
+}
+
+static void dfi_cfg(struct rk3288_ddr_pctl *pctl, u32 dramtype)
+{
+       writel(DFI_INIT_START, &pctl->dfistcfg0);
+       writel(DFI_DRAM_CLK_SR_EN | DFI_DRAM_CLK_DPD_EN,
+              &pctl->dfistcfg1);
+       writel(DFI_PARITY_INTR_EN | DFI_PARITY_EN, &pctl->dfistcfg2);
+       writel(7 << TLP_RESP_TIME_SHIFT | LP_SR_EN | LP_PD_EN,
+              &pctl->dfilpcfg0);
+
+       writel(2 << TCTRL_DELAY_TIME_SHIFT, &pctl->dfitctrldelay);
+       writel(1 << TPHY_WRDATA_TIME_SHIFT, &pctl->dfitphywrdata);
+       writel(0xf << TPHY_RDLAT_TIME_SHIFT, &pctl->dfitphyrdlat);
+       writel(2 << TDRAM_CLK_DIS_TIME_SHIFT, &pctl->dfitdramclkdis);
+       writel(2 << TDRAM_CLK_EN_TIME_SHIFT, &pctl->dfitdramclken);
+       writel(1, &pctl->dfitphyupdtype0);
+
+       /* cs0 and cs1 write odt enable */
+       writel((RANK0_ODT_WRITE_SEL | RANK1_ODT_WRITE_SEL),
+              &pctl->dfiodtcfg);
+       /* odt write length */
+       writel(7 << ODT_LEN_BL8_W_SHIFT, &pctl->dfiodtcfg1);
+       /* phyupd and ctrlupd disabled */
+       writel(0, &pctl->dfiupdcfg);
+}
+
+static void ddr_set_enable(struct rk3288_grf *grf, uint channel, bool enable)
+{
+       uint val = 0;
+
+       if (enable) {
+               val = 1 << (channel ? DDR1_16BIT_EN_SHIFT :
+                               DDR0_16BIT_EN_SHIFT);
+       }
+       rk_clrsetreg(&grf->soc_con0,
+                    1 << (channel ? DDR1_16BIT_EN_SHIFT : DDR0_16BIT_EN_SHIFT),
+                    val);
+}
+
+static void ddr_set_ddr3_mode(struct rk3288_grf *grf, uint channel,
+                             bool ddr3_mode)
+{
+       uint mask, val;
+
+       mask = 1 << (channel ? MSCH1_MAINDDR3_SHIFT : MSCH0_MAINDDR3_SHIFT);
+       val = ddr3_mode << (channel ? MSCH1_MAINDDR3_SHIFT :
+                                       MSCH0_MAINDDR3_SHIFT);
+       rk_clrsetreg(&grf->soc_con0, mask, val);
+}
+
+static void ddr_set_en_bst_odt(struct rk3288_grf *grf, uint channel,
+                              bool enable, bool enable_bst, bool enable_odt)
+{
+       uint mask;
+       bool disable_bst = !enable_bst;
+
+       mask = channel ?
+               (1 << LPDDR3_EN1_SHIFT | 1 << UPCTL1_BST_DIABLE_SHIFT |
+                       1 << UPCTL1_LPDDR3_ODT_EN_SHIFT) :
+               (1 << LPDDR3_EN0_SHIFT | 1 << UPCTL0_BST_DIABLE_SHIFT |
+                       1 << UPCTL0_LPDDR3_ODT_EN_SHIFT);
+       rk_clrsetreg(&grf->soc_con2, mask,
+                    enable << (channel ? LPDDR3_EN1_SHIFT : LPDDR3_EN0_SHIFT) |
+                    disable_bst << (channel ? UPCTL1_BST_DIABLE_SHIFT :
+                               UPCTL0_BST_DIABLE_SHIFT) |
+                    enable_odt << (channel ? UPCTL1_LPDDR3_ODT_EN_SHIFT :
+                               UPCTL0_LPDDR3_ODT_EN_SHIFT));
+}
+
+static void pctl_cfg(u32 channel, struct rk3288_ddr_pctl *pctl,
+                    const struct rk3288_sdram_params *sdram_params,
+                    struct rk3288_grf *grf)
+{
+       unsigned int burstlen;
+
+       burstlen = (sdram_params->base.noc_timing >> 18) & 0x7;
+       copy_to_reg(&pctl->togcnt1u, &sdram_params->pctl_timing.togcnt1u,
+                   sizeof(sdram_params->pctl_timing));
+       switch (sdram_params->base.dramtype) {
+       case LPDDR3:
+               writel(sdram_params->pctl_timing.tcl - 1,
+                      &pctl->dfitrddataen);
+               writel(sdram_params->pctl_timing.tcwl,
+                      &pctl->dfitphywrlat);
+               burstlen >>= 1;
+               writel(LPDDR2_S4 | 0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT |
+                      LPDDR2_EN | burstlen << BURSTLENGTH_SHIFT |
+                      (6 - 4) << TFAW_SHIFT | PD_EXIT_FAST |
+                      1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+                      &pctl->mcfg);
+               ddr_set_ddr3_mode(grf, channel, false);
+               ddr_set_enable(grf, channel, true);
+               ddr_set_en_bst_odt(grf, channel, true, false,
+                                  sdram_params->base.odt);
+               break;
+       case DDR3:
+               if (sdram_params->phy_timing.mr[1] & DDR3_DLL_DISABLE) {
+                       writel(sdram_params->pctl_timing.tcl - 3,
+                              &pctl->dfitrddataen);
+               } else {
+                       writel(sdram_params->pctl_timing.tcl - 2,
+                              &pctl->dfitrddataen);
+               }
+               writel(sdram_params->pctl_timing.tcwl - 1,
+                      &pctl->dfitphywrlat);
+               writel(0 << MDDR_LPDDR2_CLK_STOP_IDLE_SHIFT | DDR3_EN |
+                      DDR2_DDR3_BL_8 | (6 - 4) << TFAW_SHIFT | PD_EXIT_SLOW |
+                      1 << PD_TYPE_SHIFT | 0 << PD_IDLE_SHIFT,
+                      &pctl->mcfg);
+               ddr_set_ddr3_mode(grf, channel, true);
+               ddr_set_enable(grf, channel, true);
+
+               ddr_set_en_bst_odt(grf, channel, false, true, false);
+               break;
+       }
+
+       setbits_le32(&pctl->scfg, 1);
+}
+
+static void phy_cfg(const struct chan_info *chan, u32 channel,
+                   const struct rk3288_sdram_params *sdram_params)
+{
+       struct rk3288_ddr_publ *publ = chan->publ;
+       struct rk3288_msch *msch = chan->msch;
+       uint ddr_freq_mhz = sdram_params->base.ddr_freq / 1000000;
+       u32 dinit2, tmp;
+       int i;
+
+       dinit2 = DIV_ROUND_UP(ddr_freq_mhz * 200000, 1000);
+       /* DDR PHY Timing */
+       copy_to_reg(&publ->dtpr[0], &sdram_params->phy_timing.dtpr0,
+                   sizeof(sdram_params->phy_timing));
+       writel(sdram_params->base.noc_timing, &msch->ddrtiming);
+       writel(0x3f, &msch->readlatency);
+       writel(sdram_params->base.noc_activate, &msch->activate);
+       writel(2 << BUSWRTORD_SHIFT | 2 << BUSRDTOWR_SHIFT |
+              1 << BUSRDTORD_SHIFT, &msch->devtodev);
+       writel(DIV_ROUND_UP(ddr_freq_mhz * 5120, 1000) << PRT_DLLLOCK_SHIFT |
+              DIV_ROUND_UP(ddr_freq_mhz * 50, 1000) << PRT_DLLSRST_SHIFT |
+              8 << PRT_ITMSRST_SHIFT, &publ->ptr[0]);
+       writel(DIV_ROUND_UP(ddr_freq_mhz * 500000, 1000) << PRT_DINIT0_SHIFT |
+              DIV_ROUND_UP(ddr_freq_mhz * 400, 1000) << PRT_DINIT1_SHIFT,
+              &publ->ptr[1]);
+       writel(min(dinit2, 0x1ffffU) << PRT_DINIT2_SHIFT |
+              DIV_ROUND_UP(ddr_freq_mhz * 1000, 1000) << PRT_DINIT3_SHIFT,
+              &publ->ptr[2]);
+
+       switch (sdram_params->base.dramtype) {
+       case LPDDR3:
+               clrsetbits_le32(&publ->pgcr, 0x1F,
+                               0 << PGCR_DFTLMT_SHIFT |
+                               0 << PGCR_DFTCMP_SHIFT |
+                               1 << PGCR_DQSCFG_SHIFT |
+                               0 << PGCR_ITMDMD_SHIFT);
+               /* DDRMODE select LPDDR3 */
+               clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT,
+                               DDRMD_LPDDR2_LPDDR3 << DDRMD_SHIFT);
+               clrsetbits_le32(&publ->dxccr,
+                               DQSNRES_MASK << DQSNRES_SHIFT |
+                               DQSRES_MASK << DQSRES_SHIFT,
+                               4 << DQSRES_SHIFT | 0xc << DQSNRES_SHIFT);
+               tmp = readl(&publ->dtpr[1]);
+               tmp = ((tmp >> TDQSCKMAX_SHIFT) & TDQSCKMAX_MASK) -
+                       ((tmp >> TDQSCK_SHIFT) & TDQSCK_MASK);
+               clrsetbits_le32(&publ->dsgcr,
+                               DQSGE_MASK << DQSGE_SHIFT |
+                               DQSGX_MASK << DQSGX_SHIFT,
+                               tmp << DQSGE_SHIFT | tmp << DQSGX_SHIFT);
+               break;
+       case DDR3:
+               clrbits_le32(&publ->pgcr, 0x1f);
+               clrsetbits_le32(&publ->dcr, DDRMD_MASK << DDRMD_SHIFT,
+                               DDRMD_DDR3 << DDRMD_SHIFT);
+               break;
+       }
+       if (sdram_params->base.odt) {
+               /*dynamic RTT enable */
+               for (i = 0; i < 4; i++)
+                       setbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
+       } else {
+               /*dynamic RTT disable */
+               for (i = 0; i < 4; i++)
+                       clrbits_le32(&publ->datx8[i].dxgcr, DQSRTT | DQRTT);
+       }
+}
+
+static void phy_init(struct rk3288_ddr_publ *publ)
+{
+       setbits_le32(&publ->pir, PIR_INIT | PIR_DLLSRST
+               | PIR_DLLLOCK | PIR_ZCAL | PIR_ITMSRST | PIR_CLRSR);
+       udelay(1);
+       while ((readl(&publ->pgsr) &
+               (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE)) !=
+               (PGSR_IDONE | PGSR_DLDONE | PGSR_ZCDONE))
+               ;
+}
+
+static void send_command(struct rk3288_ddr_pctl *pctl, u32 rank,
+                        u32 cmd, u32 arg)
+{
+       writel((START_CMD | (rank << 20) | arg | cmd), &pctl->mcmd);
+       udelay(1);
+       while (readl(&pctl->mcmd) & START_CMD)
+               ;
+}
+
+static inline void send_command_op(struct rk3288_ddr_pctl *pctl,
+                                  u32 rank, u32 cmd, u32 ma, u32 op)
+{
+       send_command(pctl, rank, cmd, (ma & LPDDR2_MA_MASK) << LPDDR2_MA_SHIFT |
+                    (op & LPDDR2_OP_MASK) << LPDDR2_OP_SHIFT);
+}
+
+static void memory_init(struct rk3288_ddr_publ *publ,
+                       u32 dramtype)
+{
+       setbits_le32(&publ->pir,
+                    (PIR_INIT | PIR_DRAMINIT | PIR_LOCKBYP
+                     | PIR_ZCALBYP | PIR_CLRSR | PIR_ICPC
+                     | (dramtype == DDR3 ? PIR_DRAMRST : 0)));
+       udelay(1);
+       while ((readl(&publ->pgsr) & (PGSR_IDONE | PGSR_DLDONE))
+               != (PGSR_IDONE | PGSR_DLDONE))
+               ;
+}
+
+static void move_to_config_state(struct rk3288_ddr_publ *publ,
+                                struct rk3288_ddr_pctl *pctl)
+{
+       unsigned int state;
+
+       while (1) {
+               state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+               switch (state) {
+               case LOW_POWER:
+                       writel(WAKEUP_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MSK)
+                               != ACCESS)
+                               ;
+                       /* wait DLL lock */
+                       while ((readl(&publ->pgsr) & PGSR_DLDONE)
+                               != PGSR_DLDONE)
+                               ;
+                       /* if at low power state,need wakeup first,
+                        * and then enter the config
+                        * so here no break.
+                        */
+               case ACCESS:
+                       /* no break */
+               case INIT_MEM:
+                       writel(CFG_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+                               ;
+                       break;
+               case CONFIG:
+                       return;
+               default:
+                       break;
+               }
+       }
+}
+
+static void set_bandwidth_ratio(const struct chan_info *chan, u32 channel,
+                               u32 n, struct rk3288_grf *grf)
+{
+       struct rk3288_ddr_pctl *pctl = chan->pctl;
+       struct rk3288_ddr_publ *publ = chan->publ;
+       struct rk3288_msch *msch = chan->msch;
+
+       if (n == 1) {
+               setbits_le32(&pctl->ppcfg, 1);
+               writel(RK_SETBITS(1 << (8 + channel)), &grf->soc_con0);
+               setbits_le32(&msch->ddrtiming, 1 << 31);
+               /* Data Byte disable*/
+               clrbits_le32(&publ->datx8[2].dxgcr, 1);
+               clrbits_le32(&publ->datx8[3].dxgcr, 1);
+               /*disable DLL */
+               setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
+               setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
+       } else {
+               clrbits_le32(&pctl->ppcfg, 1);
+               writel(RK_CLRBITS(1 << (8 + channel)), &grf->soc_con0);
+               clrbits_le32(&msch->ddrtiming, 1 << 31);
+               /* Data Byte enable*/
+               setbits_le32(&publ->datx8[2].dxgcr, 1);
+               setbits_le32(&publ->datx8[3].dxgcr, 1);
+
+               /*enable DLL */
+               clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLDIS);
+               clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLDIS);
+               /* reset DLL */
+               clrbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
+               clrbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
+               udelay(10);
+               setbits_le32(&publ->datx8[2].dxdllcr, DXDLLCR_DLLSRST);
+               setbits_le32(&publ->datx8[3].dxdllcr, DXDLLCR_DLLSRST);
+       }
+       setbits_le32(&pctl->dfistcfg0, 1 << 2);
+}
+
+static int data_training(const struct chan_info *chan, u32 channel,
+                        const struct rk3288_sdram_params *sdram_params)
+{
+       unsigned int j;
+       int ret = 0;
+       u32 rank;
+       int i;
+       u32 step[2] = { PIR_QSTRN, PIR_RVTRN };
+       struct rk3288_ddr_publ *publ = chan->publ;
+       struct rk3288_ddr_pctl *pctl = chan->pctl;
+
+       /* disable auto refresh */
+       writel(0, &pctl->trefi);
+
+       if (sdram_params->base.dramtype != LPDDR3)
+               setbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
+       rank = sdram_params->ch[channel].rank | 1;
+       for (j = 0; j < ARRAY_SIZE(step); j++) {
+               /*
+                * trigger QSTRN and RVTRN
+                * clear DTDONE status
+                */
+               setbits_le32(&publ->pir, PIR_CLRSR);
+
+               /* trigger DTT */
+               setbits_le32(&publ->pir,
+                            PIR_INIT | step[j] | PIR_LOCKBYP | PIR_ZCALBYP |
+                            PIR_CLRSR);
+               udelay(1);
+               /* wait echo byte DTDONE */
+               while ((readl(&publ->datx8[0].dxgsr[0]) & rank)
+                       != rank)
+                       ;
+               while ((readl(&publ->datx8[1].dxgsr[0]) & rank)
+                       != rank)
+                       ;
+               if (!(readl(&pctl->ppcfg) & 1)) {
+                       while ((readl(&publ->datx8[2].dxgsr[0])
+                               & rank) != rank)
+                               ;
+                       while ((readl(&publ->datx8[3].dxgsr[0])
+                               & rank) != rank)
+                               ;
+               }
+               if (readl(&publ->pgsr) &
+                   (PGSR_DTERR | PGSR_RVERR | PGSR_RVEIRR)) {
+                       ret = -1;
+                       break;
+               }
+       }
+       /* send some auto refresh to complement the lost while DTT */
+       for (i = 0; i < (rank > 1 ? 8 : 4); i++)
+               send_command(pctl, rank, REF_CMD, 0);
+
+       if (sdram_params->base.dramtype != LPDDR3)
+               clrbits_le32(&publ->pgcr, 1 << PGCR_DQSCFG_SHIFT);
+
+       /* resume auto refresh */
+       writel(sdram_params->pctl_timing.trefi, &pctl->trefi);
+
+       return ret;
+}
+
+static void move_to_access_state(const struct chan_info *chan)
+{
+       struct rk3288_ddr_publ *publ = chan->publ;
+       struct rk3288_ddr_pctl *pctl = chan->pctl;
+       unsigned int state;
+
+       while (1) {
+               state = readl(&pctl->stat) & PCTL_STAT_MSK;
+
+               switch (state) {
+               case LOW_POWER:
+                       if (((readl(&pctl->stat) >> LP_TRIG_SHIFT) &
+                                       LP_TRIG_MASK) == 1)
+                               return;
+
+                       writel(WAKEUP_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != ACCESS)
+                               ;
+                       /* wait DLL lock */
+                       while ((readl(&publ->pgsr) & PGSR_DLDONE)
+                               != PGSR_DLDONE)
+                               ;
+                       break;
+               case INIT_MEM:
+                       writel(CFG_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) != CONFIG)
+                               ;
+               case CONFIG:
+                       writel(GO_STATE, &pctl->sctl);
+                       while ((readl(&pctl->stat) & PCTL_STAT_MSK) == CONFIG)
+                               ;
+                       break;
+               case ACCESS:
+                       return;
+               default:
+                       break;
+               }
+       }
+}
+
+static void dram_cfg_rbc(const struct chan_info *chan, u32 chnum,
+                        const struct rk3288_sdram_params *sdram_params)
+{
+       struct rk3288_ddr_publ *publ = chan->publ;
+
+       if (sdram_params->ch[chnum].bk == 3)
+               clrsetbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT,
+                               1 << PDQ_SHIFT);
+       else
+               clrbits_le32(&publ->dcr, PDQ_MASK << PDQ_SHIFT);
+
+       writel(sdram_params->base.ddrconfig, &chan->msch->ddrconf);
+}
+
+static void dram_all_config(const struct dram_info *dram,
+                           const struct rk3288_sdram_params *sdram_params)
+{
+       unsigned int chan;
+       u32 sys_reg = 0;
+
+       sys_reg |= sdram_params->base.dramtype << SYS_REG_DDRTYPE_SHIFT;
+       sys_reg |= (sdram_params->num_channels - 1) << SYS_REG_NUM_CH_SHIFT;
+       for (chan = 0; chan < sdram_params->num_channels; chan++) {
+               const struct rk3288_sdram_channel *info =
+                       &sdram_params->ch[chan];
+
+               sys_reg |= info->row_3_4 << SYS_REG_ROW_3_4_SHIFT(chan);
+               sys_reg |= chan << SYS_REG_CHINFO_SHIFT(chan);
+               sys_reg |= (info->rank - 1) << SYS_REG_RANK_SHIFT(chan);
+               sys_reg |= (info->col - 9) << SYS_REG_COL_SHIFT(chan);
+               sys_reg |= info->bk == 3 ? 1 << SYS_REG_BK_SHIFT(chan) : 0;
+               sys_reg |= (info->cs0_row - 13) << SYS_REG_CS0_ROW_SHIFT(chan);
+               sys_reg |= (info->cs1_row - 13) << SYS_REG_CS1_ROW_SHIFT(chan);
+               sys_reg |= info->bw << SYS_REG_BW_SHIFT(chan);
+               sys_reg |= info->dbw << SYS_REG_DBW_SHIFT(chan);
+
+               dram_cfg_rbc(&dram->chan[chan], chan, sdram_params);
+       }
+       writel(sys_reg, &dram->pmu->sys_reg[2]);
+       writel(RK_CLRSETBITS(0x1F, sdram_params->base.stride),
+              &dram->sgrf->soc_con2);
+}
+
+static int sdram_init(const struct dram_info *dram,
+                     const struct rk3288_sdram_params *sdram_params)
+{
+       int channel;
+       int zqcr;
+       int ret;
+
+       debug("%s start\n", __func__);
+       if ((sdram_params->base.dramtype == DDR3 &&
+            sdram_params->base.ddr_freq > 800000000) ||
+           (sdram_params->base.dramtype == LPDDR3 &&
+            sdram_params->base.ddr_freq > 533000000)) {
+               debug("SDRAM frequency is too high!");
+               return -E2BIG;
+       }
+
+       debug("ddr clk %s\n", dram->ddr_clk->name);
+       ret = clk_set_rate(dram->ddr_clk, sdram_params->base.ddr_freq);
+       debug("ret=%d\n", ret);
+       if (ret) {
+               debug("Could not set DDR clock\n");
+               return ret;
+       }
+
+       for (channel = 0; channel < 2; channel++) {
+               const struct chan_info *chan = &dram->chan[channel];
+               struct rk3288_ddr_pctl *pctl = chan->pctl;
+               struct rk3288_ddr_publ *publ = chan->publ;
+
+               phy_pctrl_reset(dram->cru, publ, channel);
+               phy_dll_bypass_set(publ, sdram_params->base.ddr_freq);
+
+               if (channel >= sdram_params->num_channels)
+                       continue;
+
+               dfi_cfg(pctl, sdram_params->base.dramtype);
+
+               pctl_cfg(channel, pctl, sdram_params, dram->grf);
+
+               phy_cfg(chan, channel, sdram_params);
+
+               phy_init(publ);
+
+               writel(POWER_UP_START, &pctl->powctl);
+               while (!(readl(&pctl->powstat) & POWER_UP_DONE))
+                       ;
+
+               memory_init(publ, sdram_params->base.dramtype);
+               move_to_config_state(publ, pctl);
+
+               if (sdram_params->base.dramtype == LPDDR3) {
+                       send_command(pctl, 3, DESELECT_CMD, 0);
+                       udelay(1);
+                       send_command(pctl, 3, PREA_CMD, 0);
+                       udelay(1);
+                       send_command_op(pctl, 3, MRS_CMD, 63, 0xfc);
+                       udelay(1);
+                       send_command_op(pctl, 3, MRS_CMD, 1,
+                                       sdram_params->phy_timing.mr[1]);
+                       udelay(1);
+                       send_command_op(pctl, 3, MRS_CMD, 2,
+                                       sdram_params->phy_timing.mr[2]);
+                       udelay(1);
+                       send_command_op(pctl, 3, MRS_CMD, 3,
+                                       sdram_params->phy_timing.mr[3]);
+                       udelay(1);
+               }
+
+               set_bandwidth_ratio(chan, channel,
+                                   sdram_params->ch[channel].bw, dram->grf);
+               /*
+                * set cs
+                * CS0, n=1
+                * CS1, n=2
+                * CS0 & CS1, n = 3
+                */
+               clrsetbits_le32(&publ->pgcr, 0xF << 18,
+                               (sdram_params->ch[channel].rank | 1) << 18);
+               /* DS=40ohm,ODT=155ohm */
+               zqcr = 1 << ZDEN_SHIFT | 2 << PU_ONDIE_SHIFT |
+                       2 << PD_ONDIE_SHIFT | 0x19 << PU_OUTPUT_SHIFT |
+                       0x19 << PD_OUTPUT_SHIFT;
+               writel(zqcr, &publ->zq1cr[0]);
+               writel(zqcr, &publ->zq0cr[0]);
+
+               if (sdram_params->base.dramtype == LPDDR3) {
+                       /* LPDDR2/LPDDR3 need to wait DAI complete, max 10us */
+                       udelay(10);
+                       send_command_op(pctl,
+                                       sdram_params->ch[channel].rank | 1,
+                                       MRS_CMD, 11,
+                                       sdram_params->base.odt ? 3 : 0);
+                       if (channel == 0) {
+                               writel(0, &pctl->mrrcfg0);
+                               send_command_op(pctl, 1, MRR_CMD, 8, 0);
+                               /* S8 */
+                               if ((readl(&pctl->mrrstat0) & 0x3) != 3) {
+                                       debug("failed!");
+                                       return -EREMOTEIO;
+                               }
+                       }
+               }
+
+               if (-1 == data_training(chan, channel, sdram_params)) {
+                       if (sdram_params->base.dramtype == LPDDR3) {
+                               ddr_phy_ctl_reset(dram->cru, channel, 1);
+                               udelay(10);
+                               ddr_phy_ctl_reset(dram->cru, channel, 0);
+                               udelay(10);
+                       }
+                       debug("failed!");
+                       return -EIO;
+               }
+
+               if (sdram_params->base.dramtype == LPDDR3) {
+                       u32 i;
+                       writel(0, &pctl->mrrcfg0);
+                       for (i = 0; i < 17; i++)
+                               send_command_op(pctl, 1, MRR_CMD, i, 0);
+               }
+               move_to_access_state(chan);
+       }
+       dram_all_config(dram, sdram_params);
+       debug("%s done\n", __func__);
+
+       return 0;
+}
+#endif
+
+size_t sdram_size_mb(struct rk3288_pmu *pmu)
+{
+       u32 rank, col, bk, cs0_row, cs1_row, bw, row_3_4;
+       size_t chipsize_mb = 0;
+       size_t size_mb = 0;
+       u32 ch;
+       u32 sys_reg = readl(&pmu->sys_reg[2]);
+       u32 chans;
+
+       chans = 1 + ((sys_reg >> SYS_REG_NUM_CH_SHIFT) & SYS_REG_NUM_CH_MASK);
+
+       for (ch = 0; ch < chans; ch++) {
+               rank = 1 + (sys_reg >> SYS_REG_RANK_SHIFT(ch) &
+                       SYS_REG_RANK_MASK);
+               col = 9 + (sys_reg >> SYS_REG_COL_SHIFT(ch) & SYS_REG_COL_MASK);
+               bk = sys_reg & (1 << SYS_REG_BK_SHIFT(ch)) ? 3 : 0;
+               cs0_row = 13 + (sys_reg >> SYS_REG_CS0_ROW_SHIFT(ch) &
+                               SYS_REG_CS0_ROW_MASK);
+               cs1_row = 13 + (sys_reg >> SYS_REG_CS1_ROW_SHIFT(ch) &
+                               SYS_REG_CS1_ROW_MASK);
+               bw = (sys_reg >> SYS_REG_BW_SHIFT(ch)) &
+                       SYS_REG_BW_MASK;
+               row_3_4 = sys_reg >> SYS_REG_ROW_3_4_SHIFT(ch) &
+                       SYS_REG_ROW_3_4_MASK;
+
+               chipsize_mb = (1 << (cs0_row + col + bk + bw - 20));
+
+               if (rank > 1)
+                       chipsize_mb += chipsize_mb >>
+                               (cs0_row - cs1_row);
+               if (row_3_4)
+                       chipsize_mb = chipsize_mb * 3 / 4;
+               size_mb += chipsize_mb;
+       }
+
+       /*
+       * we use the 0x00000000~0xfeffffff space since 0xff000000~0xffffffff
+       * is SoC register space (i.e. reserved)
+       */
+       size_mb = min(size_mb, 0xff000000 >> 20);
+
+       return size_mb;
+}
+
+#ifdef CONFIG_SPL_BUILD
+static int setup_sdram(struct udevice *dev)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+       struct rk3288_sdram_params params;
+       const void *blob = gd->fdt_blob;
+       int node = dev->of_offset;
+       int i, ret;
+
+       params.num_channels = fdtdec_get_int(blob, node,
+                                            "rockchip,num-channels", 1);
+       for (i = 0; i < params.num_channels; i++) {
+               ret = fdtdec_get_byte_array(blob, node,
+                                           "rockchip,sdram-channel",
+                                           (u8 *)&params.ch[i],
+                                           sizeof(params.ch[i]));
+               if (ret) {
+                       debug("%s: Cannot read rockchip,sdram-channel\n",
+                             __func__);
+                       return -EINVAL;
+               }
+       }
+       ret = fdtdec_get_int_array(blob, node, "rockchip,pctl-timing",
+                                  (u32 *)&params.pctl_timing,
+                                  sizeof(params.pctl_timing) / sizeof(u32));
+       if (ret) {
+               debug("%s: Cannot read rockchip,pctl-timing\n", __func__);
+               return -EINVAL;
+       }
+       ret = fdtdec_get_int_array(blob, node, "rockchip,phy-timing",
+                                  (u32 *)&params.phy_timing,
+                                  sizeof(params.phy_timing) / sizeof(u32));
+       if (ret) {
+               debug("%s: Cannot read rockchip,phy-timing\n", __func__);
+               return -EINVAL;
+       }
+       ret = fdtdec_get_int_array(blob, node, "rockchip,sdram-params",
+                                  (u32 *)&params.base,
+                                  sizeof(params.base) / sizeof(u32));
+       if (ret) {
+               debug("%s: Cannot read rockchip,sdram-params\n", __func__);
+               return -EINVAL;
+       }
+
+       return sdram_init(priv, &params);
+}
+#endif
+
+static int rk3288_dmc_probe(struct udevice *dev)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+       struct regmap *map;
+       int ret;
+
+       map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_NOC);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+       priv->chan[0].msch = regmap_get_range(map, 0);
+       priv->chan[1].msch = (struct rk3288_msch *)
+                       (regmap_get_range(map, 0) + 0x80);
+
+       map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_GRF);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+       priv->grf = regmap_get_range(map, 0);
+
+       map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_SGRF);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+       priv->sgrf = regmap_get_range(map, 0);
+
+       map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_PMU);
+       if (IS_ERR(map))
+               return PTR_ERR(map);
+       priv->pmu = regmap_get_range(map, 0);
+
+       ret = regmap_init_mem(dev, &map);
+       if (ret)
+               return ret;
+       priv->chan[0].pctl = regmap_get_range(map, 0);
+       priv->chan[0].publ = regmap_get_range(map, 1);
+       priv->chan[1].pctl = regmap_get_range(map, 2);
+       priv->chan[1].publ = regmap_get_range(map, 3);
+
+       ret = uclass_get_device(UCLASS_CLK, CLK_DDR, &priv->ddr_clk);
+       if (ret)
+               return ret;
+
+       priv->cru = rockchip_get_cru();
+       if (IS_ERR(priv->cru))
+               return PTR_ERR(priv->cru);
+#ifdef CONFIG_SPL_BUILD
+       ret = setup_sdram(dev);
+       if (ret)
+               return ret;
+#endif
+       priv->info.base = 0;
+       priv->info.size = sdram_size_mb(priv->pmu) << 20;
+
+       return 0;
+}
+
+static int rk3288_dmc_get_info(struct udevice *dev, struct ram_info *info)
+{
+       struct dram_info *priv = dev_get_priv(dev);
+
+       *info = priv->info;
+
+       return 0;
+}
+
+static struct ram_ops rk3288_dmc_ops = {
+       .get_info = rk3288_dmc_get_info,
+};
+
+static const struct udevice_id rk3288_dmc_ids[] = {
+       { .compatible = "rockchip,rk3288-dmc" },
+       { }
+};
+
+U_BOOT_DRIVER(dmc_rk3288) = {
+       .name = "rk3288_dmc",
+       .id = UCLASS_RAM,
+       .of_match = rk3288_dmc_ids,
+       .ops = &rk3288_dmc_ops,
+       .probe = rk3288_dmc_probe,
+       .priv_auto_alloc_size = sizeof(struct dram_info),
+};
diff --git a/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c b/arch/arm/mach-rockchip/rk3288/syscon_rk3288.c
new file mode 100644 (file)
index 0000000..c9f7c4e
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+
+static const struct udevice_id rk3288_syscon_ids[] = {
+       { .compatible = "rockchip,rk3288-noc", .data = ROCKCHIP_SYSCON_NOC },
+       { .compatible = "rockchip,rk3288-grf", .data = ROCKCHIP_SYSCON_GRF },
+       { .compatible = "rockchip,rk3288-sgrf", .data = ROCKCHIP_SYSCON_SGRF },
+       { .compatible = "rockchip,rk3288-pmu", .data = ROCKCHIP_SYSCON_PMU },
+       { }
+};
+
+U_BOOT_DRIVER(syscon_rk3288) = {
+       .name = "rk3288_syscon",
+       .id = UCLASS_SYSCON,
+       .of_match = rk3288_syscon_ids,
+};
diff --git a/board/firefly/firefly-rk3288/Kconfig b/board/firefly/firefly-rk3288/Kconfig
new file mode 100644 (file)
index 0000000..1c2bca8
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_FIREFLY_RK3288
+
+config SYS_BOARD
+       default "firefly-rk3288"
+
+config SYS_VENDOR
+       default "firefly"
+
+config SYS_CONFIG_NAME
+       default "firefly-rk3288"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+       def_bool y
+
+endif
diff --git a/board/firefly/firefly-rk3288/MAINTAINERS b/board/firefly/firefly-rk3288/MAINTAINERS
new file mode 100644 (file)
index 0000000..42db0bd
--- /dev/null
@@ -0,0 +1,6 @@
+FIREFLY
+M:     Simon Glass <sjg@chromium.org>
+S:     Maintained
+F:     board/firefly/firefly-rk3288
+F:     include/configs/firefly-rk3288.h
+F:     configs/firefly-rk3288_defconfig
diff --git a/board/firefly/firefly-rk3288/Makefile b/board/firefly/firefly-rk3288/Makefile
new file mode 100644 (file)
index 0000000..6716845
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += firefly-rk3288.o
diff --git a/board/firefly/firefly-rk3288/firefly-rk3288.c b/board/firefly/firefly-rk3288/firefly-rk3288.c
new file mode 100644 (file)
index 0000000..5119e95
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
diff --git a/board/google/chromebook_jerry/Kconfig b/board/google/chromebook_jerry/Kconfig
new file mode 100644 (file)
index 0000000..3640513
--- /dev/null
@@ -0,0 +1,15 @@
+if TARGET_CHROMEBOOK_JERRY
+
+config SYS_BOARD
+       default "chromebook_jerry"
+
+config SYS_VENDOR
+       default "google"
+
+config SYS_CONFIG_NAME
+       default "chromebook_jerry"
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+       def_bool y
+
+endif
diff --git a/board/google/chromebook_jerry/MAINTAINERS b/board/google/chromebook_jerry/MAINTAINERS
new file mode 100644 (file)
index 0000000..b01b6cd
--- /dev/null
@@ -0,0 +1,6 @@
+CHROMEBOOK JERRY BOARD
+M:     Simon Glass <sjg@chromium.org>
+S:     Maintained
+F:     board/google/chromebook_jerry/
+F:     include/configs/chromebook_jerry.h
+F:     configs/chromebook_jerry_defconfig
diff --git a/board/google/chromebook_jerry/Makefile b/board/google/chromebook_jerry/Makefile
new file mode 100644 (file)
index 0000000..d29a063
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# (C) Copyright 2015 Google, Inc
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-y  += jerry.o
diff --git a/board/google/chromebook_jerry/jerry.c b/board/google/chromebook_jerry/jerry.c
new file mode 100644 (file)
index 0000000..5119e95
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
index b38bc14..2de2799 100644 (file)
@@ -4,4 +4,4 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-y += early_init.o
+obj-$(CONFIG_X86) += early_init.o
index 678588d..1325e07 100644 (file)
@@ -155,6 +155,9 @@ static const table_entry_t uimage_type[] = {
        {       IH_TYPE_ATMELIMAGE, "atmelimage", "ATMEL ROM-Boot Image",},
        {       IH_TYPE_X86_SETUP,  "x86_setup",  "x86 setup.bin",    },
        {       IH_TYPE_LPC32XXIMAGE, "lpc32xximage",  "LPC32XX Boot Image", },
+       {       IH_TYPE_RKIMAGE,    "rkimage",    "Rockchip Boot Image" },
+       {       IH_TYPE_RKSD,       "rksd",       "Rockchip SD Boot Image" },
+       {       IH_TYPE_RKSPI,      "rkspi",      "Rockchip SPI Boot Image" },
        {       -1,                 "",           "",                   },
 };
 
diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig
new file mode 100644 (file)
index 0000000..389dfd2
--- /dev/null
@@ -0,0 +1,43 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_CHROMEBOOK_JERRY=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-jerry"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_RESET=y
+CONFIG_LED=y
+CONFIG_SPL_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_SIMPLE=y
+CONFIG_SPL_PINCTRL=y
+CONFIG_SPL_PINCTRL_SIMPLE=y
+CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/configs/firefly-rk3288_defconfig b/configs/firefly-rk3288_defconfig
new file mode 100644 (file)
index 0000000..5fe90b5
--- /dev/null
@@ -0,0 +1,42 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ROCKCHIP=y
+CONFIG_SYS_MALLOC_F_LEN=0x2000
+CONFIG_ROCKCHIP_RK3288=y
+CONFIG_TARGET_FIREFLY_RK3288=y
+CONFIG_DEFAULT_DEVICE_TREE="rk3288-firefly"
+CONFIG_SPL_STACK_R=y
+CONFIG_SPL_STACK_R_ADDR=0x80000
+# CONFIG_CMD_IMLS is not set
+# CONFIG_CMD_SETEXPR is not set
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_SPL_OF_CONTROL=y
+CONFIG_CLK=y
+CONFIG_SPL_CLK=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_RESET=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_DEBUG_UART=y
+CONFIG_DEBUG_UART_BASE=0xff690000
+CONFIG_DEBUG_UART_CLOCK=24000000
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_I2C_ROCKCHIP=y
+CONFIG_PINCTRL=y
+CONFIG_SPL_PINCTRL=y
+# CONFIG_PINCTRL_FULL is not set
+# CONFIG_SPL_PINCTRL_FULL is not set
+CONFIG_ROCKCHIP_PINCTRL=y
+CONFIG_ROCKCHIP_GPIO=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_RAM=y
+CONFIG_SPL_RAM=y
+CONFIG_DM_MMC=y
+CONFIG_ROCKCHIP_DWMMC=y
+CONFIG_USE_PRIVATE_LIBGCC=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_ERRNO_STR=y
diff --git a/doc/README.rockchip b/doc/README.rockchip
new file mode 100644 (file)
index 0000000..87ce9d2
--- /dev/null
@@ -0,0 +1,247 @@
+#
+# Copyright (C) 2015 Google. Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+U-Boot on Rockchip
+==================
+
+There are several repositories available with versions of U-Boot that support
+many Rockchip devices [1] [2].
+
+The current mainline support is experimental only and is not useful for
+anything. It should provide a base on which to build.
+
+So far only support for the RK3288 is provided.
+
+
+Prerequisites
+=============
+
+You will need:
+
+   - Firefly RK3288 baord
+   - Power connection to 5V using the supplied micro-USB power cable
+   - Separate USB serial cable attached to your computer and the Firefly
+        (connect to the micro-USB connector below the logo)
+   - rkflashtool [3]
+   - openssl (sudo apt-get install openssl)
+   - Serial UART connection [4]
+   - Suitable ARM cross compiler, e.g.:
+        sudo apt-get install gcc-4.7-arm-linux-gnueabi
+
+
+Building
+========
+
+At present three RK3288 boards are supported:
+
+   - Firefly RK3288 - use firefly-rk3288 configuration
+   - Radxa Rock 2 - also uses firefly-rk3288 configuration
+   - Haier Chromebook - use chromebook_jerry configuration
+
+For example:
+
+   CROSS_COMPILE=arm-linux-gnueabi- make O=firefly firefly-rk3288_defconfig all
+
+(or you can use another cross compiler if you prefer)
+
+Note that the Radxa Rock 2 uses the Firefly configuration for now as
+device tree files are not yet available for the Rock 2. Clearly the two
+have hardware differences, so this approach will break down as more drivers
+are added.
+
+
+Writing to the board with USB
+=============================
+
+For USB to work you must get your board into ROM boot mode, either by erasing
+your MMC or (perhaps) holding the recovery button when you boot the board.
+To erase your MMC, you can boot into Linux and type (as root)
+
+   dd if=/dev/zero of=/dev/mmcblk0 bs=1M
+
+Connect your board's OTG port to your computer.
+
+To create a suitable image and write it to the board:
+
+   ./firefly-rk3288/tools/mkimage -T rkimage -d \
+       ./firefly-rk3288/spl/u-boot-spl-dtb.bin out && \
+   cat out | openssl rc4 -K 7c4e0304550509072d2c7b38170d1711 | rkflashtool l
+
+If all goes well you should something like:
+
+   U-Boot SPL 2015.07-rc1-00383-ge345740-dirty (Jun 03 2015 - 10:06:49)
+   Card did not respond to voltage select!
+   spl: mmc init failed with error: -17
+   ### ERROR ### Please RESET the board ###
+
+You will need to reset the board before each time you try. Yes, that's all
+it does so far. If support for the Rockchip USB protocol or DFU were added
+in SPL then we could in principle load U-Boot and boot to a prompt from USB
+as several other platforms do. However it does not seem to be possible to
+use the existing boot ROM code from SPL.
+
+
+Booting from an SD card
+=======================
+
+To write an image that boots from an SD card (assumed to be /dev/sdc):
+
+   ./firefly-rk3288/tools/mkimage -T rksd -d \
+       firefly-rk3288/spl/u-boot-spl-dtb.bin out && \
+   sudo dd if=out of=/dev/sdc seek=64 && \
+   sudo dd if=firefly-rk3288/u-boot-dtb.img of=/dev/sdc seek=256
+
+This puts the Rockchip header and SPL image first and then places the U-Boot
+image at block 256 (i.e. 128KB from the start of the SD card). This
+corresponds with this setting in U-Boot:
+
+   #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR     256
+
+Put this SD (or micro-SD) card into your board and reset it. You should see
+something like:
+
+   U-Boot SPL 2015.07-rc1-00383-ge345740-dirty (Jun 03 2015 - 11:04:40)
+
+
+   U-Boot 2015.07-rc1-00383-ge345740-dirty (Jun 03 2015 - 11:04:40)
+
+   DRAM:  2 GiB
+   MMC:
+   Using default environment
+
+   In:    serial@ff690000
+   Out:   serial@ff690000
+   Err:   serial@ff690000
+   =>
+
+
+Booting from SPI
+================
+
+To write an image that boots from SPI flash (e.g. for the Haier Chromebook):
+
+   ./chromebook_jerry/tools/mkimage -T rkspi -d chromebook_jerry/spl/u-boot-spl-dtb.bin out
+   dd if=spl.bin of=out.bin bs=128K conv=sync
+   cat chromebook_jerry/u-boot-dtb.img out.bin
+   dd if=out.bin of=out.bin.pad bs=4M conv=sync
+
+This converts the SPL image to the required SPI format by adding the Rockchip
+header and skipping every 2KB block. Then the U-Boot image is written at
+offset 128KB and the whole image is padded to 4MB which is the SPI flash size.
+The position of U-Boot is controlled with this setting in U-Boot:
+
+   #define CONFIG_SYS_SPI_U_BOOT_OFFS  (128 << 10)
+
+If you have a Dediprog em100pro connected then you can write the image with:
+
+      sudo em100 -s -c GD25LQ32 -d out.bin.pad -r
+
+When booting you should see something like:
+
+   U-Boot SPL 2015.07-rc2-00215-g9a58220-dirty (Jun 23 2015 - 12:11:32)
+
+
+   U-Boot 2015.07-rc2-00215-g9a58220-dirty (Jun 23 2015 - 12:11:32 -0600)
+
+   Model: Google Jerry
+   DRAM:  2 GiB
+   MMC:
+   Using default environment
+
+   In:    serial@ff690000
+   Out:   serial@ff690000
+   Err:   serial@ff690000
+   =>
+
+
+Future work
+===========
+
+Immediate priorities are:
+
+- GPIO (driver exists but is lightly tested)
+- I2C (driver exists but is non-functional)
+- USB host
+- USB device
+- PMIC and regulators (only ACT8846 is supported at present)
+- LCD and HDMI
+- Run CPU at full speed
+- Ethernet
+- NAND flash
+- Support for other Rockchip parts
+- Boot U-Boot proper over USB OTG (at present only SPL works)
+
+
+Development Notes
+=================
+
+There are plenty of patches in the links below to help with this work.
+
+[1] https://github.com/rkchrome/uboot.git
+[2] https://github.com/linux-rockchip/u-boot-rockchip.git branch u-boot-rk3288
+[3] https://github.com/linux-rockchip/rkflashtool.git
+[4] http://wiki.t-firefly.com/index.php/Firefly-RK3288/Serial_debug/en
+
+rkimage
+-------
+
+rkimage.c produces an SPL image suitable for sending directly to the boot ROM
+over USB OTG. This is a very simple format - just the string RK32 (as 4 bytes)
+followed by u-boot-spl-dtb.bin.
+
+The boot ROM loads image to 0xff704000 which is in the internal SRAM. The SRAM
+starts at 0xff700000 and extends to 0xff718000 where we put the stack.
+
+rksd
+----
+
+rksd.c produces an image consisting of 32KB of empty space, a header and
+u-boot-spl-dtb.bin. The header is defined by 'struct header0_info' although
+most of the fields are unused by U-Boot. We just need to specify the
+signature, a flag and the block offset and size of the SPL image.
+
+The header occupies a single block but we pad it out to 4 blocks. The header
+is encoding using RC4 with the key 7c4e0304550509072d2c7b38170d1711. The SPL
+image can be encoded too but we don't do that.
+
+The maximum size of u-boot-spl-dtb.bin which the boot ROM will read is 32KB,
+or 0x40 blocks. This is a severe and annoying limitation. There may be a way
+around this limitation, since there is plenty of SRAM, but at present the
+board refuses to boot if this limit is exceeded.
+
+The image produced is padded up to a block boundary (512 bytes). It should be
+written to the start of an SD card using dd.
+
+Since this image is set to load U-Boot from the SD card at block offset,
+CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR, dd should be used to write
+u-boot-dtb.img to the SD card at that offset. See above for instructions.
+
+rkspi
+-----
+
+rkspi.c produces an image consisting of a header and u-boot-spl-dtb.bin. The
+resulting image is then spread out so that only the first 2KB of each 4KB
+sector is used. The header is the same as with rksd and the maximum size is
+also 32KB (before spreading). The image should be written to the start of
+SPI flash.
+
+See above for instructions on how to write a SPI image.
+
+
+Device tree and driver model
+----------------------------
+
+Where possible driver model is used to provide a structure to the
+functionality. Device tree is used for configuration. However these have an
+overhead and in SPL with a 32KB size limit some shortcuts have been taken.
+In general all Rockchip drivers should use these features, with SPL-specific
+modifications where required.
+
+
+--
+Simon Glass <sjg@chromium.org>
+24 June 2015
diff --git a/doc/device-tree-bindings/clock/rockchip,rk3188-cru.txt b/doc/device-tree-bindings/clock/rockchip,rk3188-cru.txt
new file mode 100644 (file)
index 0000000..0c2bf5e
--- /dev/null
@@ -0,0 +1,61 @@
+* Rockchip RK3188/RK3066 Clock and Reset Unit
+
+The RK3188/RK3066 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3188-cru", "rockchip,rk3188a-cru" or
+                       "rockchip,rk3066a-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3188-cru.h and
+dt-bindings/clock/rk3066-cru.h headers and can be used in device tree sources.
+Similar macros exist for the reset sources in these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "xin27m" - 27mhz crystal input on rk3066 - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_cif0" - external camera clock - optional,
+ - "ext_rmii" - external RMII clock - optional,
+ - "ext_jtag" - externalJTAG clock - optional
+
+Example: Clock controller node:
+
+       cru: cru@20000000 {
+               compatible = "rockchip,rk3188-cru";
+               reg = <0x20000000 0x1000>;
+               rockchip,grf = <&grf>;
+
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+       uart0: serial@10124000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10124000 0x400>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <1>;
+               clocks = <&cru SCLK_UART0>;
+       };
diff --git a/doc/device-tree-bindings/clock/rockchip,rk3288-cru.txt b/doc/device-tree-bindings/clock/rockchip,rk3288-cru.txt
new file mode 100644 (file)
index 0000000..c9fbb76
--- /dev/null
@@ -0,0 +1,61 @@
+* Rockchip RK3288 Clock and Reset Unit
+
+The RK3288 clock controller generates and supplies clock to various
+controllers within the SoC and also implements a reset controller for SoC
+peripherals.
+
+Required Properties:
+
+- compatible: should be "rockchip,rk3288-cru"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- #clock-cells: should be 1.
+- #reset-cells: should be 1.
+
+Optional Properties:
+
+- rockchip,grf: phandle to the syscon managing the "general register files"
+  If missing pll rates are not changable, due to the missing pll lock status.
+
+Each clock is assigned an identifier and client nodes can use this identifier
+to specify the clock which they consume. All available clocks are defined as
+preprocessor macros in the dt-bindings/clock/rk3288-cru.h headers and can be
+used in device tree sources. Similar macros exist for the reset sources in
+these files.
+
+External clocks:
+
+There are several clocks that are generated outside the SoC. It is expected
+that they are defined using standard clock bindings with following
+clock-output-names:
+ - "xin24m" - crystal input - required,
+ - "xin32k" - rtc clock - optional,
+ - "ext_i2s" - external I2S clock - optional,
+ - "ext_hsadc" - external HSADC clock - optional,
+ - "ext_edp_24m" - external display port clock - optional,
+ - "ext_vip" - external VIP clock - optional,
+ - "ext_isp" - external ISP clock - optional,
+ - "ext_jtag" - external JTAG clock - optional
+
+Example: Clock controller node:
+
+       cru: cru@20000000 {
+               compatible = "rockchip,rk3188-cru";
+               reg = <0x20000000 0x1000>;
+               rockchip,grf = <&grf>;
+
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+       };
+
+Example: UART controller node that consumes the clock generated by the clock
+  controller:
+
+       uart0: serial@10124000 {
+               compatible = "snps,dw-apb-uart";
+               reg = <0x10124000 0x400>;
+               interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+               reg-shift = <2>;
+               reg-io-width = <1>;
+               clocks = <&cru SCLK_UART0>;
+       };
diff --git a/doc/device-tree-bindings/clock/rockchip,rk3288-dmc.txt b/doc/device-tree-bindings/clock/rockchip,rk3288-dmc.txt
new file mode 100644 (file)
index 0000000..2ca9db7
--- /dev/null
@@ -0,0 +1,155 @@
+Rockchip Dynamic Memory Controller Driver
+Required properties:
+- compatible: "rockchip,rk3288-dmc", "syscon"
+- rockchip,cru: this driver should access cru regs, so need get cru here
+- rockchip,grf: this driver should access grf regs, so need get grf here
+- rockchip,pmu: this driver should access pmu regs, so need get pmu here
+- rockchip,sgrf: this driver should access sgrf regs, so need get sgrf here
+- rockchip,noc: this driver should access noc regs, so need get noc here
+- reg: dynamic ram protocol controller(PCTL) address and phy controller(PHYCTL) address
+- clock: must include clock specifiers corresponding to entries in the clock-names property.
+- clock-output-names: from common clock binding to override the default output clock name
+    Must contain
+      pclk_ddrupctl0: support clock for access protocol controller registers of channel 0
+      pclk_publ0: support clock for access phy controller registers of channel 0
+      pclk_ddrupctl1: support clock for access protocol controller registers of channel 1
+      pclk_publ1: support clock for access phy controller registers of channel 1
+      arm_clk: for get arm frequency
+-logic-supply: this driver should adjust VDD_LOGIC according to dmc frequency, so need get logic-supply here
+-timings:
+    Must contain
+      rockchip,odt-disable-freq: if ddr clock frequency low than odt-disable-freq,this driver should disable DDR ODT
+      rockchip,dll-disable-freq: if ddr clock frequency low than dll-disable-freq,this driver should disable DDR DLL
+      rockchip,sr-enable-freq: if ddr clock frequency high than sr-enable-freq,this driver should enable the automatic self refresh function
+      rockchip,pd-enable-freq: if ddr clock frequency high than pd-enable-freq,this driver should enable the automatic power down function
+      rockchip,auto-self-refresh-cnt: Self Refresh idle period. Memories are placed into Self-Refresh mode if the NIF is idle in Access state for auto-self-refresh-cnt * 32 * n_clk cycles.The automatic self refresh function is disabled when auto-self-refresh-cnt=0.
+      rockchip,auto-power-down-cnt: Power-down idle period. Memories are placed into power-down mode if the NIF is idle for auto-power-down-cnt n_clk cycles.The automatic power down function is disabled when auto-power-down-cnt=0.
+      rockchip,ddr-speed-bin: DDR3 type,AC timing parameters from the memory data-sheet
+        0.DDR3_800D (5-5-5)
+        1.DDR3_800E (6-6-6)
+        2.DDR3_1066E (6-6-6)
+        3.DDR3_1066F (7-7-7)
+        4.DDR3_1066G (8-8-8)
+        5.DDR3_1333F (7-7-7)
+        6.DDR3_1333G (8-8-8)
+        7.DDR3_1333H (9-9-9)
+        8.DDR3_1333J (10-10-10)
+        9.DDR3_1600G (8-8-8)
+        10.DDR3_1600H (9-9-9)
+        11.DDR3_1600J (10-10-10)
+        12.DDR3_1600K (11-11-11)
+        13.DDR3_1866J (10-10-10)
+        14.DDR3_1866K (11-11-11)
+        15.DDR3_1866L (12-12-12)
+        16.DDR3_1866M (13-13-13)
+        17.DDR3_2133K (11-11-11)
+        18.DDR3_2133L (12-12-12)
+        19.DDR3_2133M (13-13-13)
+        20.DDR3_2133N (14-14-14)
+        21.DDR3_DEFAULT
+      rockchip,trcd: tRCD,AC timing parameters from the memory data-sheet
+      rockchip,trp: tRP,AC timing parameters from the memory data-sheet
+-rockchip,num-channels: number of SDRAM channels (1 or 2)
+-rockchip,pctl-timing: parameters for the SDRAM setup, in this order:
+       togcnt1u
+       tinit
+       trsth
+       togcnt100n
+       trefi
+       tmrd
+       trfc
+       trp
+       trtw
+       tal
+       tcl
+       tcwl
+       tras
+       trc
+       trcd
+       trrd
+       trtp
+       twr
+       twtr
+       texsr
+       txp
+       txpdll
+       tzqcs
+       tzqcsi
+       tdqs
+       tcksre
+       tcksrx
+       tcke
+       tmod
+       trstl
+       tzqcl
+       tmrr
+       tckesr
+       tdpd
+-rockchip,phy-timing: PHY timing information in this order:
+       dtpr0
+       dtpr1
+       dtpr2
+       mr0..mr3
+-rockchip,sdram-channel: SDRAM channel information, each 8 bits. Both channels
+will be set up the same. The parameters are in this order:
+       rank
+       col
+       bk
+       bw
+       dbw
+       row_3_4
+       cs0_row
+       cs1_row
+- rockchip,sdram-params: SDRAM base parameters, in this order:
+       NOC timing      - value for ddrtiming register
+       NOC activate    - value for activate register
+       ddrconf         - value for ddrconf register
+       DDR frequency in MHz
+       DRAM type (3=DDR3, 6=LPDDR3)
+       stride          - stride value for soc_con2 register
+       odt             - 1 to enable DDR ODT, 0 to disable
+
+Example:
+       dmc: dmc@ff610000 {
+               compatible = "rockchip,rk3288-dmc", "syscon";
+               rockchip,cru = <&cru>;
+               rockchip,grf = <&grf>;
+               rockchip,pmu = <&pmu>;
+               rockchip,sgrf = <&sgrf>;
+               rockchip,noc = <&noc>;
+               reg = <0xff610000 0x3fc
+                      0xff620000 0x294
+                      0xff630000 0x3fc
+                      0xff640000 0x294>;
+               clocks = <&cru PCLK_DDRUPCTL0>, <&cru PCLK_PUBL0>,
+                        <&cru PCLK_DDRUPCTL1>, <&cru PCLK_PUBL1>,
+                        <&cru ARMCLK>;
+               clock-names = "pclk_ddrupctl0", "pclk_publ0",
+                             "pclk_ddrupctl1", "pclk_publ1",
+                             "arm_clk";
+       };
+
+       &dmc {
+               logic-supply = <&vdd_logic>;
+               timings {
+                       rockchip,odt-disable-freq = <333000000>;
+                       rockchip,dll-disable-freq = <333000000>;
+                       rockchip,sr-enable-freq = <333000000>;
+                       rockchip,pd-enable-freq = <666000000>;
+                       rockchip,auto-self-refresh-cnt = <0>;
+                       rockchip,auto-power-down-cnt = <64>;
+                       rockchip,ddr-speed-bin = <21>;
+                       rockchip,trcd = <10>;
+                       rockchip,trp = <10>;
+               };
+               rockchip,num-channels = <2>;
+               rockchip,pctl-timing = <0x29a 0x1f4 0xc8 0x42 0x4e 0x4 0xea 0xa
+                       0x5 0x0 0xa 0x7 0x19 0x24 0xa 0x7
+                       0x5 0xa 0x5 0x200 0x5 0x10 0x40 0x0
+                       0x1 0x7 0x7 0x4 0xc 0x43 0x100 0x0
+                       0x5 0x0>;
+               rockchip,phy-timing = <0x48f9aab4 0xea0910 0x1002c200
+                       0xa60 0x40 0x10 0x0>;
+               rockchip,sdram-channel = /bits/ 8 <0x1 0xa 0x3 0x2 0x1 0x0 0xf 0xf>;
+               rockchip,sdram-params = <0x30B25564 0x627 3 666000000 3 9 1>;
+       };
diff --git a/doc/device-tree-bindings/clock/rockchip.txt b/doc/device-tree-bindings/clock/rockchip.txt
new file mode 100644 (file)
index 0000000..22f6769
--- /dev/null
@@ -0,0 +1,77 @@
+Device Tree Clock bindings for arch-rockchip
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+== Gate clocks ==
+
+These bindings are deprecated!
+Please use the soc specific CRU bindings instead.
+
+The gate registers form a continuos block which makes the dt node
+structure a matter of taste, as either all gates can be put into
+one gate clock spanning all registers or they can be divided into
+the 10 individual gates containing 16 clocks each.
+The code supports both approaches.
+
+Required properties:
+- compatible : "rockchip,rk2928-gate-clk"
+- reg : shall be the control register address(es) for the clock.
+- #clock-cells : from common clock binding; shall be set to 1
+- clock-output-names : the corresponding gate names that the clock controls
+- clocks : should contain the parent clock for each individual gate,
+  therefore the number of clocks elements should match the number of
+  clock-output-names
+
+Example using multiple gate clocks:
+
+               clk_gates0: gate-clk@200000d0 {
+                       compatible = "rockchip,rk2928-gate-clk";
+                       reg = <0x200000d0 0x4>;
+                       clocks = <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>,
+                                <&dummy>, <&dummy>;
+
+                       clock-output-names =
+                               "gate_core_periph", "gate_cpu_gpll",
+                               "gate_ddrphy", "gate_aclk_cpu",
+                               "gate_hclk_cpu", "gate_pclk_cpu",
+                               "gate_atclk_cpu", "gate_i2s0",
+                               "gate_i2s0_frac", "gate_i2s1",
+                               "gate_i2s1_frac", "gate_i2s2",
+                               "gate_i2s2_frac", "gate_spdif",
+                               "gate_spdif_frac", "gate_testclk";
+
+                       #clock-cells = <1>;
+               };
+
+               clk_gates1: gate-clk@200000d4 {
+                       compatible = "rockchip,rk2928-gate-clk";
+                       reg = <0x200000d4 0x4>;
+                       clocks = <&xin24m>, <&xin24m>,
+                                <&xin24m>, <&dummy>,
+                                <&dummy>, <&xin24m>,
+                                <&xin24m>, <&dummy>,
+                                <&xin24m>, <&dummy>,
+                                <&xin24m>, <&dummy>,
+                                <&xin24m>, <&dummy>,
+                                <&xin24m>, <&dummy>;
+
+                       clock-output-names =
+                               "gate_timer0", "gate_timer1",
+                               "gate_timer2", "gate_jtag",
+                               "gate_aclk_lcdc1_src", "gate_otgphy0",
+                               "gate_otgphy1", "gate_ddr_gpll",
+                               "gate_uart0", "gate_frac_uart0",
+                               "gate_uart1", "gate_frac_uart1",
+                               "gate_uart2", "gate_frac_uart2",
+                               "gate_uart3", "gate_frac_uart3";
+
+                       #clock-cells = <1>;
+               };
diff --git a/doc/device-tree-bindings/pinctrl/rockchip,pinctrl.txt b/doc/device-tree-bindings/pinctrl/rockchip,pinctrl.txt
new file mode 100644 (file)
index 0000000..388b213
--- /dev/null
@@ -0,0 +1,157 @@
+* Rockchip Pinmux Controller
+
+The Rockchip Pinmux Controller, enables the IC
+to share one PAD to several functional blocks. The sharing is done by
+multiplexing the PAD input/output signals. For each PAD there are several
+muxing options with option 0 being the use as a GPIO.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The Rockchip pin configuration node is a node of a group of pins which can be
+used for a specific device or function. This node represents both mux and
+config of the pins in that group. The 'pins' selects the function mode(also
+named pin mode) this pin can work on and the 'config' configures various pad
+settings such as pull-up, etc.
+
+The pins are grouped into up to 5 individual pin banks which need to be
+defined as gpio sub-nodes of the pinmux controller.
+
+Required properties for iomux controller:
+  - compatible: one of "rockchip,rk2928-pinctrl", "rockchip,rk3066a-pinctrl"
+                      "rockchip,rk3066b-pinctrl", "rockchip,rk3188-pinctrl"
+                      "rockchip,rk3288-pinctrl"
+  - rockchip,grf: phandle referencing a syscon providing the
+        "general register files"
+
+Optional properties for iomux controller:
+  - rockchip,pmu: phandle referencing a syscon providing the pmu registers
+        as some SoCs carry parts of the iomux controller registers there.
+        Required for at least rk3188 and rk3288.
+
+Deprecated properties for iomux controller:
+  - reg: first element is the general register space of the iomux controller
+        It should be large enough to contain also separate pull registers.
+        second element is the separate pull register space of the rk3188.
+        Use rockchip,grf and rockchip,pmu described above instead.
+
+Required properties for gpio sub nodes:
+  - compatible: "rockchip,gpio-bank"
+  - reg: register of the gpio bank (different than the iomux registerset)
+  - interrupts: base interrupt of the gpio bank in the interrupt controller
+  - clocks: clock that drives this bank
+  - gpio-controller: identifies the node as a gpio controller and pin bank.
+  - #gpio-cells: number of cells in GPIO specifier. Since the generic GPIO
+    binding is used, the amount of cells must be specified as 2. See generic
+    GPIO binding documentation for description of particular cells.
+  - interrupt-controller: identifies the controller node as interrupt-parent.
+  - #interrupt-cells: the value of this property should be 2 and the interrupt
+    cells should use the standard two-cell scheme described in
+    bindings/interrupt-controller/interrupts.txt
+
+Deprecated properties for gpio sub nodes:
+  - compatible: "rockchip,rk3188-gpio-bank0"
+  - reg: second element: separate pull register for rk3188 bank0, use
+        rockchip,pmu described above instead
+
+Required properties for pin configuration node:
+  - rockchip,pins: 3 integers array, represents a group of pins mux and config
+    setting. The format is rockchip,pins = <PIN_BANK PIN_BANK_IDX MUX &phandle>.
+    The MUX 0 means gpio and MUX 1 to N mean the specific device function.
+    The phandle of a node containing the generic pinconfig options
+    to use, as described in pinctrl-bindings.txt in this directory.
+
+Examples:
+
+#include <dt-bindings/pinctrl/rockchip.h>
+
+...
+
+pinctrl@20008000 {
+       compatible = "rockchip,rk3066a-pinctrl";
+       rockchip,grf = <&grf>;
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+       ranges;
+
+       gpio0: gpio0@20034000 {
+               compatible = "rockchip,gpio-bank";
+               reg = <0x20034000 0x100>;
+               interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clk_gates8 9>;
+
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               interrupt-controller;
+               #interrupt-cells = <2>;
+       };
+
+       ...
+
+       pcfg_pull_default: pcfg_pull_default {
+               bias-pull-pin-default
+       };
+
+       uart2 {
+               uart2_xfer: uart2-xfer {
+                       rockchip,pins = <RK_GPIO1 8 1 &pcfg_pull_default>,
+                                       <RK_GPIO1 9 1 &pcfg_pull_default>;
+               };
+       };
+};
+
+uart2: serial@20064000 {
+       compatible = "snps,dw-apb-uart";
+       reg = <0x20064000 0x400>;
+       interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+       reg-shift = <2>;
+       reg-io-width = <1>;
+       clocks = <&mux_uart2>;
+       status = "okay";
+
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_xfer>;
+};
+
+Example for rk3188:
+
+       pinctrl@20008000 {
+               compatible = "rockchip,rk3188-pinctrl";
+               rockchip,grf = <&grf>;
+               rockchip,pmu = <&pmu>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               gpio0: gpio0@0x2000a000 {
+                       compatible = "rockchip,rk3188-gpio-bank0";
+                       reg = <0x2000a000 0x100>;
+                       interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 9>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio1@0x2003c000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x2003c000 0x100>;
+                       interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clk_gates8 10>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               ...
+
+       };
diff --git a/doc/device-tree-bindings/thermal/rockchip-thermal.txt b/doc/device-tree-bindings/thermal/rockchip-thermal.txt
new file mode 100644 (file)
index 0000000..ef802de
--- /dev/null
@@ -0,0 +1,68 @@
+* Temperature Sensor ADC (TSADC) on rockchip SoCs
+
+Required properties:
+- compatible : "rockchip,rk3288-tsadc"
+- reg : physical base address of the controller and length of memory mapped
+       region.
+- interrupts : The interrupt number to the cpu. The interrupt specifier format
+              depends on the interrupt controller.
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Shall be "tsadc" for the converter-clock, and "apb_pclk" for
+               the peripheral clock.
+- resets : Must contain an entry for each entry in reset-names.
+          See ../reset/reset.txt for details.
+- reset-names : Must include the name "tsadc-apb".
+- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- rockchip,hw-tshut-temp : The hardware-controlled shutdown temperature value.
+- rockchip,hw-tshut-mode : The hardware-controlled shutdown mode 0:CRU 1:GPIO.
+- rockchip,hw-tshut-polarity : The hardware-controlled active polarity 0:LOW
+                              1:HIGH.
+
+Exiample:
+tsadc: tsadc@ff280000 {
+       compatible = "rockchip,rk3288-tsadc";
+       reg = <0xff280000 0x100>;
+       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+       clocks = <&cru SCLK_TSADC>, <&cru PCLK_TSADC>;
+       clock-names = "tsadc", "apb_pclk";
+       resets = <&cru SRST_TSADC>;
+       reset-names = "tsadc-apb";
+       pinctrl-names = "default";
+       pinctrl-0 = <&otp_out>;
+       #thermal-sensor-cells = <1>;
+       rockchip,hw-tshut-temp = <95000>;
+       rockchip,hw-tshut-mode = <0>;
+       rockchip,hw-tshut-polarity = <0>;
+};
+
+Example: referring to thermal sensors:
+thermal-zones {
+       cpu_thermal: cpu_thermal {
+               polling-delay-passive = <1000>; /* milliseconds */
+               polling-delay = <5000>; /* milliseconds */
+
+               /* sensor       ID */
+               thermal-sensors = <&tsadc       1>;
+
+               trips {
+                       cpu_alert0: cpu_alert {
+                               temperature = <70000>; /* millicelsius */
+                               hysteresis = <2000>; /* millicelsius */
+                               type = "passive";
+                       };
+                       cpu_crit: cpu_crit {
+                               temperature = <90000>; /* millicelsius */
+                               hysteresis = <2000>; /* millicelsius */
+                               type = "critical";
+                       };
+               };
+
+               cooling-maps {
+                       map0 {
+                               trip = <&cpu_alert0>;
+                               cooling-device =
+                                   <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                       };
+               };
+       };
+};
index bb89fb9..008ec10 100644 (file)
@@ -6,4 +6,5 @@
 #
 
 obj-$(CONFIG_CLK) += clk-uclass.o
+obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
 obj-$(CONFIG_SANDBOX) += clk_sandbox.o
diff --git a/drivers/clk/clk_rk3288.c b/drivers/clk/clk_rk3288.c
new file mode 100644 (file)
index 0000000..54d4930
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cru_rk3288.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <dm/lists.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk3288_clk_plat {
+       enum rk_clk_id clk_id;
+};
+
+struct rk3288_clk_priv {
+       struct rk3288_grf *grf;
+       struct rk3288_cru *cru;
+       ulong rate;
+};
+
+struct pll_div {
+       u32 nr;
+       u32 nf;
+       u32 no;
+};
+
+enum {
+       VCO_MAX_HZ      = 2200U * 1000000,
+       VCO_MIN_HZ      = 440 * 1000000,
+       OUTPUT_MAX_HZ   = 2200U * 1000000,
+       OUTPUT_MIN_HZ   = 27500000,
+       FREF_MAX_HZ     = 2200U * 1000000,
+       FREF_MIN_HZ     = 269 * 1000000,
+};
+
+enum {
+       /* PLL CON0 */
+       PLL_OD_MASK             = 0x0f,
+
+       /* PLL CON1 */
+       PLL_NF_MASK             = 0x1fff,
+
+       /* PLL CON2 */
+       PLL_BWADJ_MASK          = 0x0fff,
+
+       /* PLL CON3 */
+       PLL_RESET_SHIFT         = 5,
+
+       /* CLKSEL1: pd bus clk pll sel: codec or general */
+       PD_BUS_SEL_PLL_MASK     = 15,
+       PD_BUS_SEL_CPLL         = 0,
+       PD_BUS_SEL_GPLL,
+
+       /* pd bus pclk div: pclk = pd_bus_aclk /(div + 1) */
+       PD_BUS_PCLK_DIV_SHIFT   = 12,
+       PD_BUS_PCLK_DIV_MASK    = 7,
+
+       /* pd bus hclk div: aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 */
+       PD_BUS_HCLK_DIV_SHIFT   = 8,
+       PD_BUS_HCLK_DIV_MASK    = 3,
+
+       /* pd bus aclk div: pd_bus_aclk = pd_bus_src_clk /(div0 * div1) */
+       PD_BUS_ACLK_DIV0_SHIFT  = 3,
+       PD_BUS_ACLK_DIV0_MASK   = 0x1f,
+       PD_BUS_ACLK_DIV1_SHIFT  = 0,
+       PD_BUS_ACLK_DIV1_MASK   = 0x7,
+
+       /*
+        * CLKSEL10
+        * peripheral bus pclk div:
+        * aclk_bus: pclk_bus = 1:1 or 2:1 or 4:1 or 8:1
+        */
+       PERI_PCLK_DIV_SHIFT     = 12,
+       PERI_PCLK_DIV_MASK      = 7,
+
+       /* peripheral bus hclk div: aclk_bus: hclk_bus = 1:1 or 2:1 or 4:1 */
+       PERI_HCLK_DIV_SHIFT     = 8,
+       PERI_HCLK_DIV_MASK      = 3,
+
+       /*
+        * peripheral bus aclk div:
+        *    aclk_periph = periph_clk_src / (peri_aclk_div_con + 1)
+        */
+       PERI_ACLK_DIV_SHIFT     = 0,
+       PERI_ACLK_DIV_MASK      = 0x1f,
+
+       /* CLKSEL37 */
+       DPLL_MODE_MASK          = 0x3,
+       DPLL_MODE_SHIFT         = 4,
+       DPLL_MODE_SLOW          = 0,
+       DPLL_MODE_NORM,
+
+       CPLL_MODE_MASK          = 3,
+       CPLL_MODE_SHIFT         = 8,
+       CPLL_MODE_SLOW          = 0,
+       CPLL_MODE_NORM,
+
+       GPLL_MODE_MASK          = 3,
+       GPLL_MODE_SHIFT         = 12,
+       GPLL_MODE_SLOW          = 0,
+       GPLL_MODE_NORM,
+
+       NPLL_MODE_MASK          = 3,
+       NPLL_MODE_SHIFT         = 14,
+       NPLL_MODE_SLOW          = 0,
+       NPLL_MODE_NORM,
+
+       SOCSTS_DPLL_LOCK        = 1 << 5,
+       SOCSTS_APLL_LOCK        = 1 << 6,
+       SOCSTS_CPLL_LOCK        = 1 << 7,
+       SOCSTS_GPLL_LOCK        = 1 << 8,
+       SOCSTS_NPLL_LOCK        = 1 << 9,
+};
+
+#define RATE_TO_DIV(input_rate, output_rate) \
+       ((input_rate) / (output_rate) - 1);
+
+#define DIV_TO_RATE(input_rate, div)   ((input_rate) / ((div) + 1))
+
+#define PLL_DIVISORS(hz, _nr, _no) {\
+       .nr = _nr, .nf = (u32)((u64)hz * _nr * _no / OSC_HZ), .no = _no};\
+       _Static_assert(((u64)hz * _nr * _no / OSC_HZ) * OSC_HZ /\
+                      (_nr * _no) == hz, #hz "Hz cannot be hit with PLL "\
+                      "divisors on line " __stringify(__LINE__));
+
+/* Keep divisors as low as possible to reduce jitter and power usage */
+static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 1);
+static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2);
+static const struct pll_div cpll_init_cfg = PLL_DIVISORS(CPLL_HZ, 1, 2);
+
+static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id,
+                        const struct pll_div *div)
+{
+       int pll_id = rk_pll_id(clk_id);
+       struct rk3288_pll *pll = &cru->pll[pll_id];
+       /* All PLLs have same VCO and output frequency range restrictions. */
+       uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
+       uint output_hz = vco_hz / div->no;
+
+       debug("PLL at %p: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
+             pll, div->nf, div->nr, div->no, vco_hz, output_hz);
+       assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+              output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
+              (div->no == 1 || !(div->no % 2)));
+
+       /* enter rest */
+       rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);
+
+       rk_clrsetreg(&pll->con0,
+                    CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK,
+                    ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
+       rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
+       rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);
+
+       udelay(10);
+
+       /* return form rest */
+       rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);
+
+       return 0;
+}
+
+static inline unsigned int log2(unsigned int value)
+{
+       return fls(value) - 1;
+}
+
+static int rkclk_configure_ddr(struct rk3288_cru *cru, struct rk3288_grf *grf,
+                              unsigned int hz)
+{
+       static const struct pll_div dpll_cfg[] = {
+               {.nf = 25, .nr = 2, .no = 1},
+               {.nf = 400, .nr = 9, .no = 2},
+               {.nf = 500, .nr = 9, .no = 2},
+               {.nf = 100, .nr = 3, .no = 1},
+       };
+       int cfg;
+
+       debug("%s: cru=%p, grf=%p, hz=%u\n", __func__, cru, grf, hz);
+       switch (hz) {
+       case 300000000:
+               cfg = 0;
+               break;
+       case 533000000: /* actually 533.3P MHz */
+               cfg = 1;
+               break;
+       case 666000000: /* actually 666.6P MHz */
+               cfg = 2;
+               break;
+       case 800000000:
+               cfg = 3;
+               break;
+       default:
+               debug("Unsupported SDRAM frequency, add to clock.c!");
+               return -EINVAL;
+       }
+
+       /* pll enter slow-mode */
+       rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
+                    DPLL_MODE_SLOW << DPLL_MODE_SHIFT);
+
+       rkclk_set_pll(cru, CLK_DDR, &dpll_cfg[cfg]);
+
+       /* wait for pll lock */
+       while (!(readl(&grf->soc_status[1]) & SOCSTS_DPLL_LOCK))
+               udelay(1);
+
+       /* PLL enter normal-mode */
+       rk_clrsetreg(&cru->cru_mode_con, DPLL_MODE_MASK << DPLL_MODE_SHIFT,
+                    DPLL_MODE_NORM << DPLL_MODE_SHIFT);
+
+       return 0;
+}
+
+#ifdef CONFIG_SPL_BUILD
+static void rkclk_init(struct rk3288_cru *cru, struct rk3288_grf *grf)
+{
+       u32 aclk_div;
+       u32 hclk_div;
+       u32 pclk_div;
+
+       /* pll enter slow-mode */
+       rk_clrsetreg(&cru->cru_mode_con,
+                    GPLL_MODE_MASK << GPLL_MODE_SHIFT |
+                    CPLL_MODE_MASK << CPLL_MODE_SHIFT,
+                    GPLL_MODE_SLOW << GPLL_MODE_SHIFT |
+                    CPLL_MODE_SLOW << CPLL_MODE_SHIFT);
+
+       /* init pll */
+       rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
+       rkclk_set_pll(cru, CLK_CODEC, &cpll_init_cfg);
+
+       /* waiting for pll lock */
+       while ((readl(&grf->soc_status[1]) &
+                       (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK)) !=
+                       (SOCSTS_CPLL_LOCK | SOCSTS_GPLL_LOCK))
+               udelay(1);
+
+       /*
+        * pd_bus clock pll source selection and
+        * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+        */
+       aclk_div = GPLL_HZ / PD_BUS_ACLK_HZ - 1;
+       assert((aclk_div + 1) * PD_BUS_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+       hclk_div = PD_BUS_ACLK_HZ / PD_BUS_HCLK_HZ - 1;
+       assert((hclk_div + 1) * PD_BUS_HCLK_HZ ==
+               PD_BUS_ACLK_HZ && (hclk_div < 0x4) && (hclk_div != 0x2));
+
+       pclk_div = PD_BUS_ACLK_HZ / PD_BUS_PCLK_HZ - 1;
+       assert((pclk_div + 1) * PD_BUS_PCLK_HZ ==
+               PD_BUS_ACLK_HZ && pclk_div < 0x7);
+
+       rk_clrsetreg(&cru->cru_clksel_con[1],
+                    PD_BUS_PCLK_DIV_MASK << PD_BUS_PCLK_DIV_SHIFT |
+                    PD_BUS_HCLK_DIV_MASK << PD_BUS_HCLK_DIV_SHIFT |
+                    PD_BUS_ACLK_DIV0_MASK << PD_BUS_ACLK_DIV0_SHIFT |
+                    PD_BUS_ACLK_DIV1_MASK << PD_BUS_ACLK_DIV1_SHIFT,
+                    pclk_div << PD_BUS_PCLK_DIV_SHIFT |
+                    hclk_div << PD_BUS_HCLK_DIV_SHIFT |
+                    aclk_div << PD_BUS_ACLK_DIV0_SHIFT |
+                    0 << 0);
+
+       /*
+        * peri clock pll source selection and
+        * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+        */
+       aclk_div = GPLL_HZ / PERI_ACLK_HZ - 1;
+       assert((aclk_div + 1) * PERI_ACLK_HZ == GPLL_HZ && aclk_div < 0x1f);
+
+       hclk_div = log2(PERI_ACLK_HZ / PERI_HCLK_HZ);
+       assert((1 << hclk_div) * PERI_HCLK_HZ ==
+               PERI_ACLK_HZ && (hclk_div < 0x4));
+
+       pclk_div = log2(PERI_ACLK_HZ / PERI_PCLK_HZ);
+       assert((1 << pclk_div) * PERI_PCLK_HZ ==
+               PERI_ACLK_HZ && (pclk_div < 0x4));
+
+       rk_clrsetreg(&cru->cru_clksel_con[10],
+                    PERI_PCLK_DIV_MASK << PERI_PCLK_DIV_SHIFT |
+                    PERI_HCLK_DIV_MASK << PERI_HCLK_DIV_SHIFT |
+                    PERI_ACLK_DIV_MASK << PERI_ACLK_DIV_SHIFT,
+                    pclk_div << PERI_PCLK_DIV_SHIFT |
+                    hclk_div << PERI_HCLK_DIV_SHIFT |
+                    aclk_div << PERI_ACLK_DIV_SHIFT);
+
+       /* PLL enter normal-mode */
+       rk_clrsetreg(&cru->cru_mode_con,
+                    GPLL_MODE_MASK << GPLL_MODE_SHIFT |
+                    CPLL_MODE_MASK << CPLL_MODE_SHIFT,
+                    GPLL_MODE_NORM << GPLL_MODE_SHIFT |
+                    GPLL_MODE_NORM << CPLL_MODE_SHIFT);
+}
+#endif
+
+/* Get pll rate by id */
+static uint32_t rkclk_pll_get_rate(struct rk3288_cru *cru,
+                                  enum rk_clk_id clk_id)
+{
+       uint32_t nr, no, nf;
+       uint32_t con;
+       int pll_id = rk_pll_id(clk_id);
+       struct rk3288_pll *pll = &cru->pll[pll_id];
+       static u8 clk_shift[CLK_COUNT] = {
+               0xff, APLL_WORK_SHIFT, DPLL_WORK_SHIFT, CPLL_WORK_SHIFT,
+               GPLL_WORK_SHIFT, NPLL_WORK_SHIFT
+       };
+       uint shift;
+
+       con = readl(&cru->cru_mode_con);
+       shift = clk_shift[clk_id];
+       switch ((con >> shift) & APLL_WORK_MASK) {
+       case APLL_WORK_SLOW:
+               return OSC_HZ;
+       case APLL_WORK_NORMAL:
+               /* normal mode */
+               con = readl(&pll->con0);
+               no = ((con >> CLKOD_SHIFT) & CLKOD_MASK) + 1;
+               nr = ((con >> CLKR_SHIFT) & CLKR_MASK) + 1;
+               con = readl(&pll->con1);
+               nf = ((con >> CLKF_SHIFT) & CLKF_MASK) + 1;
+
+               return (24 * nf / (nr * no)) * 1000000;
+       case APLL_WORK_DEEP:
+       default:
+               return 32768;
+       }
+}
+
+static ulong rk3288_clk_get_rate(struct udevice *dev)
+{
+       struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+       struct rk3288_clk_priv *priv = dev_get_priv(dev);
+
+       debug("%s\n", dev->name);
+       return rkclk_pll_get_rate(priv->cru, plat->clk_id);
+}
+
+static ulong rk3288_clk_set_rate(struct udevice *dev, ulong rate)
+{
+       struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+       struct rk3288_clk_priv *priv = dev_get_priv(dev);
+
+       debug("%s\n", dev->name);
+       switch (plat->clk_id) {
+       case CLK_DDR:
+               rkclk_configure_ddr(priv->cru, priv->grf, rate);
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return 0;
+}
+
+static ulong rockchip_mmc_get_clk(struct rk3288_cru *cru, uint clk_general_rate,
+                                 enum periph_id periph)
+{
+       uint src_rate;
+       uint div, mux;
+       u32 con;
+
+       switch (periph) {
+       case PERIPH_ID_EMMC:
+               con = readl(&cru->cru_clksel_con[12]);
+               mux = (con >> EMMC_PLL_SHIFT) & EMMC_PLL_MASK;
+               div = (con >> EMMC_DIV_SHIFT) & EMMC_DIV_MASK;
+               break;
+       case PERIPH_ID_SDCARD:
+               con = readl(&cru->cru_clksel_con[12]);
+               mux = (con >> MMC0_PLL_SHIFT) & MMC0_PLL_MASK;
+               div = (con >> MMC0_DIV_SHIFT) & MMC0_DIV_MASK;
+               break;
+       case PERIPH_ID_SDMMC2:
+               con = readl(&cru->cru_clksel_con[12]);
+               mux = (con >> SDIO0_PLL_SHIFT) & SDIO0_PLL_MASK;
+               div = (con >> SDIO0_DIV_SHIFT) & SDIO0_DIV_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       src_rate = mux == EMMC_PLL_SELECT_24MHZ ? OSC_HZ : clk_general_rate;
+       return DIV_TO_RATE(src_rate, div);
+}
+
+static ulong rockchip_mmc_set_clk(struct rk3288_cru *cru, uint clk_general_rate,
+                                 enum periph_id periph, uint freq)
+{
+       int src_clk_div;
+       int mux;
+
+       debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate);
+       src_clk_div = RATE_TO_DIV(clk_general_rate, freq);
+
+       if (src_clk_div > 0x3f) {
+               src_clk_div = RATE_TO_DIV(OSC_HZ, freq);
+               mux = EMMC_PLL_SELECT_24MHZ;
+               assert((int)EMMC_PLL_SELECT_24MHZ ==
+                      (int)MMC0_PLL_SELECT_24MHZ);
+       } else {
+               mux = EMMC_PLL_SELECT_GENERAL;
+               assert((int)EMMC_PLL_SELECT_GENERAL ==
+                      (int)MMC0_PLL_SELECT_GENERAL);
+       }
+       switch (periph) {
+       case PERIPH_ID_EMMC:
+               rk_clrsetreg(&cru->cru_clksel_con[12],
+                            EMMC_PLL_MASK << EMMC_PLL_SHIFT |
+                            EMMC_DIV_MASK << EMMC_DIV_SHIFT,
+                            mux << EMMC_PLL_SHIFT |
+                            (src_clk_div - 1) << EMMC_DIV_SHIFT);
+               break;
+       case PERIPH_ID_SDCARD:
+               rk_clrsetreg(&cru->cru_clksel_con[11],
+                            MMC0_PLL_MASK << MMC0_PLL_SHIFT |
+                            MMC0_DIV_MASK << MMC0_DIV_SHIFT,
+                            mux << MMC0_PLL_SHIFT |
+                            (src_clk_div - 1) << MMC0_DIV_SHIFT);
+               break;
+       case PERIPH_ID_SDMMC2:
+               rk_clrsetreg(&cru->cru_clksel_con[12],
+                            SDIO0_PLL_MASK << SDIO0_PLL_SHIFT |
+                            SDIO0_DIV_MASK << SDIO0_DIV_SHIFT,
+                            mux << SDIO0_PLL_SHIFT |
+                            (src_clk_div - 1) << SDIO0_DIV_SHIFT);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return rockchip_mmc_get_clk(cru, clk_general_rate, periph);
+}
+
+static ulong rockchip_spi_get_clk(struct rk3288_cru *cru, uint clk_general_rate,
+                                 enum periph_id periph)
+{
+       uint div, mux;
+       u32 con;
+
+       switch (periph) {
+       case PERIPH_ID_SPI0:
+               con = readl(&cru->cru_clksel_con[25]);
+               mux = (con >> SPI0_PLL_SHIFT) & SPI0_PLL_MASK;
+               div = (con >> SPI0_DIV_SHIFT) & SPI0_DIV_MASK;
+               break;
+       case PERIPH_ID_SPI1:
+               con = readl(&cru->cru_clksel_con[25]);
+               mux = (con >> SPI1_PLL_SHIFT) & SPI1_PLL_MASK;
+               div = (con >> SPI1_DIV_SHIFT) & SPI1_DIV_MASK;
+               break;
+       case PERIPH_ID_SPI2:
+               con = readl(&cru->cru_clksel_con[39]);
+               mux = (con >> SPI2_PLL_SHIFT) & SPI2_PLL_MASK;
+               div = (con >> SPI2_DIV_SHIFT) & SPI2_DIV_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+       assert(mux == SPI0_PLL_SELECT_GENERAL);
+
+       return DIV_TO_RATE(clk_general_rate, div);
+}
+
+static ulong rockchip_spi_set_clk(struct rk3288_cru *cru, uint clk_general_rate,
+                                 enum periph_id periph, uint freq)
+{
+       int src_clk_div;
+
+       debug("%s: clk_general_rate=%u\n", __func__, clk_general_rate);
+       src_clk_div = RATE_TO_DIV(clk_general_rate, freq);
+       switch (periph) {
+       case PERIPH_ID_SPI0:
+               rk_clrsetreg(&cru->cru_clksel_con[25],
+                            SPI0_PLL_MASK << SPI0_PLL_SHIFT |
+                            SPI0_DIV_MASK << SPI0_DIV_SHIFT,
+                            SPI0_PLL_SELECT_GENERAL << SPI0_PLL_SHIFT |
+                            src_clk_div << SPI0_DIV_SHIFT);
+               break;
+       case PERIPH_ID_SPI1:
+               rk_clrsetreg(&cru->cru_clksel_con[25],
+                            SPI1_PLL_MASK << SPI1_PLL_SHIFT |
+                            SPI1_DIV_MASK << SPI1_DIV_SHIFT,
+                            SPI1_PLL_SELECT_GENERAL << SPI1_PLL_SHIFT |
+                            src_clk_div << SPI1_DIV_SHIFT);
+               break;
+       case PERIPH_ID_SPI2:
+               rk_clrsetreg(&cru->cru_clksel_con[39],
+                            SPI2_PLL_MASK << SPI2_PLL_SHIFT |
+                            SPI2_DIV_MASK << SPI2_DIV_SHIFT,
+                            SPI2_PLL_SELECT_GENERAL << SPI2_PLL_SHIFT |
+                            src_clk_div << SPI2_DIV_SHIFT);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return rockchip_spi_get_clk(cru, clk_general_rate, periph);
+}
+
+ulong rk3288_set_periph_rate(struct udevice *dev, int periph, ulong rate)
+{
+       struct rk3288_clk_priv *priv = dev_get_priv(dev);
+       ulong new_rate;
+
+       switch (periph) {
+       case PERIPH_ID_EMMC:
+       case PERIPH_ID_SDCARD:
+               new_rate = rockchip_mmc_set_clk(priv->cru, clk_get_rate(dev),
+                                               periph, rate);
+               break;
+       case PERIPH_ID_SPI0:
+       case PERIPH_ID_SPI1:
+       case PERIPH_ID_SPI2:
+               new_rate = rockchip_spi_set_clk(priv->cru, clk_get_rate(dev),
+                                               periph, rate);
+               break;
+       default:
+               return -ENOENT;
+       }
+
+       return new_rate;
+}
+
+static struct clk_ops rk3288_clk_ops = {
+       .get_rate       = rk3288_clk_get_rate,
+       .set_rate       = rk3288_clk_set_rate,
+       .set_periph_rate = rk3288_set_periph_rate,
+};
+
+static int rk3288_clk_probe(struct udevice *dev)
+{
+       struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+       struct rk3288_clk_priv *priv = dev_get_priv(dev);
+
+       if (plat->clk_id != CLK_OSC) {
+               struct rk3288_clk_priv *parent_priv = dev_get_priv(dev->parent);
+
+               priv->cru = parent_priv->cru;
+               priv->grf = parent_priv->grf;
+               return 0;
+       }
+       priv->cru = (struct rk3288_cru *)dev_get_addr(dev);
+       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+#ifdef CONFIG_SPL_BUILD
+       rkclk_init(priv->cru, priv->grf);
+#endif
+
+       return 0;
+}
+
+static const char *const clk_name[CLK_COUNT] = {
+       "osc",
+       "apll",
+       "dpll",
+       "cpll",
+       "gpll",
+       "mpll",
+};
+
+static int rk3288_clk_bind(struct udevice *dev)
+{
+       struct rk3288_clk_plat *plat = dev_get_platdata(dev);
+       int pll, ret;
+
+       /* We only need to set up the root clock */
+       if (dev->of_offset == -1) {
+               plat->clk_id = CLK_OSC;
+               return 0;
+       }
+
+       /* Create devices for P main clocks */
+       for (pll = 1; pll < CLK_COUNT; pll++) {
+               struct udevice *child;
+               struct rk3288_clk_plat *cplat;
+
+               debug("%s %s\n", __func__, clk_name[pll]);
+               ret = device_bind_driver(dev, "clk_rk3288", clk_name[pll],
+                                        &child);
+               if (ret)
+                       return ret;
+               cplat = dev_get_platdata(child);
+               cplat->clk_id = pll;
+       }
+
+       /* The reset driver does not have a device node, so bind it here */
+       ret = device_bind_driver(gd->dm_root, "rk3288_reset", "reset", &dev);
+       if (ret)
+               debug("Warning: No RK3288 reset driver: ret=%d\n", ret);
+
+       return 0;
+}
+
+static const struct udevice_id rk3288_clk_ids[] = {
+       { .compatible = "rockchip,rk3288-cru" },
+       { }
+};
+
+U_BOOT_DRIVER(clk_rk3288) = {
+       .name           = "clk_rk3288",
+       .id             = UCLASS_CLK,
+       .of_match       = rk3288_clk_ids,
+       .priv_auto_alloc_size = sizeof(struct rk3288_clk_priv),
+       .platdata_auto_alloc_size = sizeof(struct rk3288_clk_plat),
+       .ops            = &rk3288_clk_ops,
+       .bind           = rk3288_clk_bind,
+       .probe          = rk3288_clk_probe,
+};
index a6cd936..0ccd443 100644 (file)
@@ -39,8 +39,10 @@ int device_bind(struct udevice *parent, const struct driver *drv,
                return -EINVAL;
 
        ret = uclass_get(drv->id, &uc);
-       if (ret)
+       if (ret) {
+               debug("Missing uclass for driver %s\n", drv->name);
                return ret;
+       }
 
        dev = calloc(1, sizeof(struct udevice));
        if (!dev)
index 78ab00c..bdb394a 100644 (file)
@@ -162,8 +162,11 @@ int dm_scan_fdt_node(struct udevice *parent, const void *blob, int offset,
                        continue;
                }
                err = lists_bind_fdt(parent, blob, offset, NULL);
-               if (err && !ret)
+               if (err && !ret) {
                        ret = err;
+                       debug("%s: ret=%d\n", fdt_get_name(blob, offset, NULL),
+                             ret);
+               }
        }
 
        if (ret)
index f63ff59..e800c28 100644 (file)
@@ -58,7 +58,12 @@ static int uclass_add(enum uclass_id id, struct uclass **ucp)
        if (!uc_drv) {
                debug("Cannot find uclass for id %d: please add the UCLASS_DRIVER() declaration for this UCLASS_... id\n",
                      id);
-               return -ENOENT;
+               /*
+                * Use a strange error to make this case easier to find. When
+                * a uclass is not available it can prevent driver model from
+                * starting up and this failure is otherwise hard to debug.
+                */
+               return -EPFNOSUPPORT;
        }
        uc = calloc(1, sizeof(*uc));
        if (!uc)
index 9a5d29d..ef57a89 100644 (file)
@@ -28,6 +28,15 @@ config LPC32XX_GPIO
        help
          Support for the LPC32XX GPIO driver.
 
+config ROCKCHIP_GPIO
+       bool "Rockchip GPIO driver"
+       depends on DM_GPIO
+       help
+         Support GPIO access on Rockchip SoCs. The GPIOs are arranged into
+         a number of banks (different for each SoC type) each with 32 GPIOs.
+         The GPIOs for a device are defined in the device tree with one node
+         for each bank.
+
 config SANDBOX_GPIO
        bool "Enable sandbox GPIO driver"
        depends on SANDBOX && DM && DM_GPIO
index ba18594..c58aa4d 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_MXC_GPIO)        += mxc_gpio.o
 obj-$(CONFIG_MXS_GPIO) += mxs_gpio.o
 obj-$(CONFIG_PCA953X)          += pca953x.o
 obj-$(CONFIG_PCA9698)          += pca9698.o
+obj-$(CONFIG_ROCKCHIP_GPIO)    += rk_gpio.o
 obj-$(CONFIG_S5P)              += s5p_gpio.o
 obj-$(CONFIG_SANDBOX_GPIO)     += sandbox.o
 obj-$(CONFIG_SPEAR_GPIO)       += spear_gpio.o
diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c
new file mode 100644 (file)
index 0000000..fbdf9f3
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ * Peter, Software Engineering, <superpeter.cai@gmail.com>.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/errno.h>
+#include <asm/gpio.h>
+#include <asm/io.h>
+#include <dt-bindings/gpio/gpio.h>
+
+enum {
+       ROCKCHIP_GPIOS_PER_BANK         = 32,
+};
+
+#define OFFSET_TO_BIT(bit)     (1UL << (bit))
+
+struct rockchip_gpio_priv {
+       struct rockchip_gpio_regs *regs;
+       char name[2];
+};
+
+static int rockchip_gpio_direction_input(struct udevice *dev, unsigned offset)
+{
+       struct rockchip_gpio_priv *priv = dev_get_priv(dev);
+       struct rockchip_gpio_regs *regs = priv->regs;
+
+       clrbits_le32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
+
+       return 0;
+}
+
+static int rockchip_gpio_direction_output(struct udevice *dev, unsigned offset,
+                                         int value)
+{
+       struct rockchip_gpio_priv *priv = dev_get_priv(dev);
+       struct rockchip_gpio_regs *regs = priv->regs;
+       int mask = OFFSET_TO_BIT(offset);
+
+       clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
+       setbits_le32(&regs->swport_ddr, mask);
+
+       return 0;
+}
+
+static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
+{
+       struct rockchip_gpio_priv *priv = dev_get_priv(dev);
+       struct rockchip_gpio_regs *regs = priv->regs;
+
+       return readl(&regs->ext_port) & OFFSET_TO_BIT(offset);
+}
+
+static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
+                                  int value)
+{
+       struct rockchip_gpio_priv *priv = dev_get_priv(dev);
+       struct rockchip_gpio_regs *regs = priv->regs;
+       int mask = OFFSET_TO_BIT(offset);
+
+       clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
+
+       return 0;
+}
+
+static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
+{
+       return -ENOSYS;
+}
+
+static int rockchip_gpio_xlate(struct udevice *dev, struct gpio_desc *desc,
+                           struct fdtdec_phandle_args *args)
+{
+       desc->offset = args->args[0];
+       desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0;
+
+       return 0;
+}
+
+static int rockchip_gpio_probe(struct udevice *dev)
+{
+       struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
+       struct rockchip_gpio_priv *priv = dev_get_priv(dev);
+       char *end;
+       int bank;
+
+       priv->regs = (struct rockchip_gpio_regs *)dev_get_addr(dev);
+       uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
+       end = strrchr(dev->name, '@');
+       bank = trailing_strtoln(dev->name, end);
+       priv->name[0] = 'A' + bank;
+       uc_priv->bank_name = priv->name;
+
+       return 0;
+}
+
+static const struct dm_gpio_ops gpio_rockchip_ops = {
+       .direction_input        = rockchip_gpio_direction_input,
+       .direction_output       = rockchip_gpio_direction_output,
+       .get_value              = rockchip_gpio_get_value,
+       .set_value              = rockchip_gpio_set_value,
+       .get_function           = rockchip_gpio_get_function,
+       .xlate                  = rockchip_gpio_xlate,
+};
+
+static const struct udevice_id rockchip_gpio_ids[] = {
+       { .compatible = "rockchip,gpio-bank" },
+       { }
+};
+
+U_BOOT_DRIVER(gpio_rockchip) = {
+       .name   = "gpio_rockchip",
+       .id     = UCLASS_GPIO,
+       .of_match = rockchip_gpio_ids,
+       .ops    = &gpio_rockchip_ops,
+       .priv_auto_alloc_size = sizeof(struct rockchip_gpio_priv),
+       .probe  = rockchip_gpio_probe,
+};
index c40bd5c..14adda2 100644 (file)
@@ -58,6 +58,15 @@ config DM_I2C_GPIO
          bindings are supported.
          Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
 
+config SYS_I2C_ROCKCHIP
+       bool "Rockchip I2C driver"
+       depends on DM_I2C
+       help
+         Add support for the Rockchip I2C driver. This is used with various
+         Rockchip parts such as RK3126, RK3128, RK3036 and RK3288. All chips
+         have several I2C ports and all are provided, controled by the
+         device tree.
+
 config SYS_I2C_SANDBOX
        bool "Sandbox I2C driver"
        depends on SANDBOX && DM_I2C
index 9b45248..8ce294b 100644 (file)
@@ -31,6 +31,7 @@ obj-$(CONFIG_SYS_I2C_OMAP24XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_OMAP34XX) += omap24xx_i2c.o
 obj-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o
 obj-$(CONFIG_SYS_I2C_RCAR) += rcar_i2c.o
+obj-$(CONFIG_SYS_I2C_ROCKCHIP) += rk_i2c.o
 obj-$(CONFIG_SYS_I2C_S3C24X0) += s3c24x0_i2c.o
 obj-$(CONFIG_SYS_I2C_SANDBOX) += sandbox_i2c.o i2c-emul-uclass.o
 obj-$(CONFIG_SYS_I2C_SH) += sh_i2c.o
diff --git a/drivers/i2c/rk_i2c.c b/drivers/i2c/rk_i2c.c
new file mode 100644 (file)
index 0000000..ebdba35
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2014 Rockchip Electronics
+ * Peter, Software Engineering, <superpeter.cai@gmail.com>.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <i2c.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/periph.h>
+#include <dm/pinctrl.h>
+#include <linux/sizes.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* i2c timerout */
+#define I2C_TIMEOUT_MS         100
+#define I2C_RETRY_COUNT                3
+
+/* rk i2c fifo max transfer bytes */
+#define RK_I2C_FIFO_SIZE       32
+
+struct rk_i2c {
+       struct udevice *clk;
+       struct udevice *pinctrl;
+       struct i2c_regs *regs;
+       unsigned int speed;
+       enum periph_id id;
+};
+
+static inline void rk_i2c_get_div(int div, int *divh, int *divl)
+{
+       *divl = div / 2;
+       if (div % 2 == 0)
+               *divh = div / 2;
+       else
+               *divh = DIV_ROUND_UP(div, 2);
+}
+
+/*
+ * SCL Divisor = 8 * (CLKDIVL+1 + CLKDIVH+1)
+ * SCL = PCLK / SCLK Divisor
+ * i2c_rate = PCLK
+ */
+static void rk_i2c_set_clk(struct rk_i2c *i2c, uint32_t scl_rate)
+{
+       uint32_t i2c_rate;
+       int div, divl, divh;
+
+       /* First get i2c rate from pclk */
+       i2c_rate = clk_get_periph_rate(i2c->clk, i2c->id);
+
+       div = DIV_ROUND_UP(i2c_rate, scl_rate * 8) - 2;
+       divh = 0;
+       divl = 0;
+       if (div >= 0)
+               rk_i2c_get_div(div, &divh, &divl);
+       writel(I2C_CLKDIV_VAL(divl, divh), &i2c->regs->clkdiv);
+
+       debug("rk_i2c_set_clk: i2c rate = %d, scl rate = %d\n", i2c_rate,
+             scl_rate);
+       debug("set i2c clk div = %d, divh = %d, divl = %d\n", div, divh, divl);
+       debug("set clk(I2C_CLKDIV: 0x%08x)\n", readl(&i2c->regs->clkdiv));
+}
+
+static void rk_i2c_show_regs(struct i2c_regs *regs)
+{
+#ifdef DEBUG
+       uint i;
+
+       debug("i2c_con: 0x%08x\n", readl(&regs->con));
+       debug("i2c_clkdiv: 0x%08x\n", readl(&regs->clkdiv));
+       debug("i2c_mrxaddr: 0x%08x\n", readl(&regs->mrxaddr));
+       debug("i2c_mrxraddR: 0x%08x\n", readl(&regs->mrxraddr));
+       debug("i2c_mtxcnt: 0x%08x\n", readl(&regs->mtxcnt));
+       debug("i2c_mrxcnt: 0x%08x\n", readl(&regs->mrxcnt));
+       debug("i2c_ien: 0x%08x\n", readl(&regs->ien));
+       debug("i2c_ipd: 0x%08x\n", readl(&regs->ipd));
+       debug("i2c_fcnt: 0x%08x\n", readl(&regs->fcnt));
+       for (i = 0; i < 8; i++)
+               debug("i2c_txdata%d: 0x%08x\n", i, readl(&regs->txdata[i]));
+       for (i = 0; i < 8; i++)
+               debug("i2c_rxdata%d: 0x%08x\n", i, readl(&regs->rxdata[i]));
+#endif
+}
+
+static int rk_i2c_send_start_bit(struct rk_i2c *i2c)
+{
+       struct i2c_regs *regs = i2c->regs;
+       ulong start;
+
+       debug("I2c Send Start bit.\n");
+       writel(I2C_IPD_ALL_CLEAN, &regs->ipd);
+
+       writel(I2C_CON_EN | I2C_CON_START, &regs->con);
+       writel(I2C_STARTIEN, &regs->ien);
+
+       start = get_timer(0);
+       while (1) {
+               if (readl(&regs->ipd) & I2C_STARTIPD) {
+                       writel(I2C_STARTIPD, &regs->ipd);
+                       break;
+               }
+               if (get_timer(start) > I2C_TIMEOUT_MS) {
+                       debug("I2C Send Start Bit Timeout\n");
+                       rk_i2c_show_regs(regs);
+                       return -ETIMEDOUT;
+               }
+               udelay(1);
+       }
+
+       return 0;
+}
+
+static int rk_i2c_send_stop_bit(struct rk_i2c *i2c)
+{
+       struct i2c_regs *regs = i2c->regs;
+       ulong start;
+
+       debug("I2c Send Stop bit.\n");
+       writel(I2C_IPD_ALL_CLEAN, &regs->ipd);
+
+       writel(I2C_CON_EN | I2C_CON_STOP, &regs->con);
+       writel(I2C_CON_STOP, &regs->ien);
+
+       start = get_timer(0);
+       while (1) {
+               if (readl(&regs->ipd) & I2C_STOPIPD) {
+                       writel(I2C_STOPIPD, &regs->ipd);
+                       break;
+               }
+               if (get_timer(start) > I2C_TIMEOUT_MS) {
+                       debug("I2C Send Start Bit Timeout\n");
+                       rk_i2c_show_regs(regs);
+                       return -ETIMEDOUT;
+               }
+               udelay(1);
+       }
+
+       return 0;
+}
+
+static inline void rk_i2c_disable(struct rk_i2c *i2c)
+{
+       writel(0, &i2c->regs->con);
+}
+
+static int rk_i2c_read(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len,
+                      uchar *buf, uint b_len)
+{
+       struct i2c_regs *regs = i2c->regs;
+       uchar *pbuf = buf;
+       uint bytes_remain_len = b_len;
+       uint bytes_xferred = 0;
+       uint words_xferred = 0;
+       ulong start;
+       uint con = 0;
+       uint rxdata;
+       uint i, j;
+       int err;
+
+       debug("rk_i2c_read: chip = %d, reg = %d, r_len = %d, b_len = %d\n",
+             chip, reg, r_len, b_len);
+
+       err = rk_i2c_send_start_bit(i2c);
+       if (err)
+               return err;
+
+       writel(I2C_MRXADDR_SET(1, chip << 1 | 1), &regs->mrxaddr);
+       if (r_len == 0) {
+               writel(0, &regs->mrxraddr);
+       } else if (r_len < 4) {
+               writel(I2C_MRXRADDR_SET(r_len, reg), &regs->mrxraddr);
+       } else {
+               debug("I2C Read: addr len %d not supported\n", r_len);
+               return -EIO;
+       }
+
+       while (bytes_remain_len) {
+               if (bytes_remain_len > RK_I2C_FIFO_SIZE) {
+                       con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX);
+                       bytes_xferred = 32;
+               } else {
+                       con = I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TRX) |
+                               I2C_CON_LASTACK;
+                       bytes_xferred = bytes_remain_len;
+               }
+               words_xferred = DIV_ROUND_UP(bytes_xferred, 4);
+
+               writel(con, &regs->con);
+               writel(bytes_xferred, &regs->mrxcnt);
+               writel(I2C_MBRFIEN | I2C_NAKRCVIEN, &regs->ien);
+
+               start = get_timer(0);
+               while (1) {
+                       if (readl(&regs->ipd) & I2C_NAKRCVIPD) {
+                               writel(I2C_NAKRCVIPD, &regs->ipd);
+                               err = -EREMOTEIO;
+                       }
+                       if (readl(&regs->ipd) & I2C_MBRFIPD) {
+                               writel(I2C_MBRFIPD, &regs->ipd);
+                               break;
+                       }
+                       if (get_timer(start) > I2C_TIMEOUT_MS) {
+                               debug("I2C Read Data Timeout\n");
+                               err =  -ETIMEDOUT;
+                               rk_i2c_show_regs(regs);
+                               goto i2c_exit;
+                       }
+                       udelay(1);
+               }
+
+               for (i = 0; i < words_xferred; i++) {
+                       rxdata = readl(&regs->rxdata[i]);
+                       debug("I2c Read RXDATA[%d] = 0x%x\n", i, rxdata);
+                       for (j = 0; j < 4; j++) {
+                               if ((i * 4 + j) == bytes_xferred)
+                                       break;
+                               *pbuf++ = (rxdata >> (j * 8)) & 0xff;
+                       }
+               }
+
+               bytes_remain_len -= bytes_xferred;
+               debug("I2C Read bytes_remain_len %d\n", bytes_remain_len);
+       }
+
+i2c_exit:
+       rk_i2c_send_stop_bit(i2c);
+       rk_i2c_disable(i2c);
+
+       return err;
+}
+
+static int rk_i2c_write(struct rk_i2c *i2c, uchar chip, uint reg, uint r_len,
+                       uchar *buf, uint b_len)
+{
+       struct i2c_regs *regs = i2c->regs;
+       int err;
+       uchar *pbuf = buf;
+       uint bytes_remain_len = b_len + r_len + 1;
+       uint bytes_xferred = 0;
+       uint words_xferred = 0;
+       ulong start;
+       uint txdata;
+       uint i, j;
+
+       debug("rk_i2c_write: chip = %d, reg = %d, r_len = %d, b_len = %d\n",
+             chip, reg, r_len, b_len);
+       err = rk_i2c_send_start_bit(i2c);
+       if (err)
+               return err;
+
+       while (bytes_remain_len) {
+               if (bytes_remain_len > RK_I2C_FIFO_SIZE)
+                       bytes_xferred = 32;
+               else
+                       bytes_xferred = bytes_remain_len;
+               words_xferred = DIV_ROUND_UP(bytes_xferred, 4);
+
+               for (i = 0; i < words_xferred; i++) {
+                       txdata = 0;
+                       for (j = 0; j < 4; j++) {
+                               if ((i * 4 + j) == bytes_xferred)
+                                       break;
+
+                               if (i == 0 && j == 0) {
+                                       txdata |= (chip << 1);
+                               } else if (i == 0 && j <= r_len) {
+                                       txdata |= (reg &
+                                               (0xff << ((j - 1) * 8))) << 8;
+                               } else {
+                                       txdata |= (*pbuf++)<<(j * 8);
+                               }
+                               writel(txdata, &regs->txdata[i]);
+                       }
+                       debug("I2c Write TXDATA[%d] = 0x%x\n", i, txdata);
+               }
+
+               writel(I2C_CON_EN | I2C_CON_MOD(I2C_MODE_TX), &regs->con);
+               writel(bytes_xferred, &regs->mtxcnt);
+               writel(I2C_MBTFIEN | I2C_NAKRCVIEN, &regs->ien);
+
+               start = get_timer(0);
+               while (1) {
+                       if (readl(&regs->ipd) & I2C_NAKRCVIPD) {
+                               writel(I2C_NAKRCVIPD, &regs->ipd);
+                               err = -EREMOTEIO;
+                       }
+                       if (readl(&regs->ipd) & I2C_MBTFIPD) {
+                               writel(I2C_MBTFIPD, &regs->ipd);
+                               break;
+                       }
+                       if (get_timer(start) > I2C_TIMEOUT_MS) {
+                               debug("I2C Write Data Timeout\n");
+                               err =  -ETIMEDOUT;
+                               rk_i2c_show_regs(regs);
+                               goto i2c_exit;
+                       }
+                       udelay(1);
+               }
+
+               bytes_remain_len -= bytes_xferred;
+               debug("I2C Write bytes_remain_len %d\n", bytes_remain_len);
+       }
+
+i2c_exit:
+       rk_i2c_send_stop_bit(i2c);
+       rk_i2c_disable(i2c);
+
+       return err;
+}
+
+static int rockchip_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
+                            int nmsgs)
+{
+       struct rk_i2c *i2c = dev_get_priv(bus);
+       int ret;
+
+       debug("i2c_xfer: %d messages\n", nmsgs);
+       for (; nmsgs > 0; nmsgs--, msg++) {
+               debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+               if (msg->flags & I2C_M_RD) {
+                       ret = rk_i2c_read(i2c, msg->addr, 0, 0, msg->buf,
+                                         msg->len);
+               } else {
+                       ret = rk_i2c_write(i2c, msg->addr, 0, 0, msg->buf,
+                                          msg->len);
+               }
+               if (ret) {
+                       debug("i2c_write: error sending\n");
+                       return -EREMOTEIO;
+               }
+       }
+
+       return 0;
+}
+
+int rockchip_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+{
+       struct rk_i2c *i2c = dev_get_priv(bus);
+
+       rk_i2c_set_clk(i2c, speed);
+
+       return 0;
+}
+
+static int rockchip_i2c_probe(struct udevice *bus)
+{
+       struct rk_i2c *i2c = dev_get_priv(bus);
+       int ret;
+
+       ret = uclass_get_device(UCLASS_PINCTRL, 0, &i2c->pinctrl);
+       if (ret)
+               return ret;
+       ret = uclass_get_device(UCLASS_CLK, 0, &i2c->clk);
+       if (ret)
+               return ret;
+       ret = pinctrl_get_periph_id(i2c->pinctrl, bus);
+       if (ret < 0)
+               return ret;
+       i2c->id = ret;
+       i2c->regs = (void *)dev_get_addr(bus);
+       return pinctrl_request(i2c->pinctrl, i2c->id, 0);
+}
+
+static const struct dm_i2c_ops rockchip_i2c_ops = {
+       .xfer           = rockchip_i2c_xfer,
+       .set_bus_speed  = rockchip_i2c_set_bus_speed,
+};
+
+static const struct udevice_id rockchip_i2c_ids[] = {
+       { .compatible = "rockchip,rk3288-i2c" },
+       { }
+};
+
+U_BOOT_DRIVER(i2c_rockchip) = {
+       .name   = "i2c_rockchip",
+       .id     = UCLASS_I2C,
+       .of_match = rockchip_i2c_ids,
+       .probe  = rockchip_i2c_probe,
+       .priv_auto_alloc_size = sizeof(struct rk_i2c),
+       .ops    = &rockchip_i2c_ops,
+};
index 2987337..fe74403 100644 (file)
@@ -11,7 +11,7 @@ config LED
 
 config SPL_LED
        bool "Enable LED support in SPL"
-       depends on LED
+       depends on SPL && SPL_DM
        help
          The LED subsystem adds a small amount of overhead to the image.
          If this is acceptable and you have a need to use LEDs in SPL,
@@ -27,4 +27,11 @@ config LED_GPIO
          The GPIO driver must used driver model. LEDs are configured using
          the device tree.
 
+config SPL_LED_GPIO
+       bool "LED support for GPIO-connected LEDs in SPL"
+        depends on SPL_LED && DM_GPIO
+       help
+         This option is an SPL-variant of the LED_GPIO option.
+         See the help of LED_GPIO for details.
+
 endmenu
index 990129e..02367fd 100644 (file)
@@ -5,5 +5,5 @@
 # SPDX-License-Identifier:     GPL-2.0+
 #
 
-obj-$(CONFIG_LED) += led-uclass.o
-obj-$(CONFIG_LED_GPIO) += led_gpio.o
+obj-y += led-uclass.o
+obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o
index 3e835f7..6277f92 100644 (file)
@@ -10,6 +10,15 @@ config DM_MMC
          appear as block devices in U-Boot and can support filesystems such
          as EXT4 and FAT.
 
+config ROCKCHIP_DWMMC
+       bool "Rockchip SD/MMC controller support"
+       depends on DM_MMC && OF_CONTROL
+       help
+         This enables support for the Rockchip SD/MMM controller, which is
+         based on Designware IP. The device is compatible with at least
+         SD 3.0, SDIO 3.0 and MMC 4.5 and supports common eMMC chips as well
+         as removeable SD and micro-SD cards.
+
 config SH_SDHI
        bool "SuperH/Renesas ARM SoCs on-chip SDHI host controller support"
        depends on RMOBILE
index cae207c..99d0295 100644 (file)
@@ -29,6 +29,7 @@ obj-$(CONFIG_MXS_MMC) += mxsmmc.o
 obj-$(CONFIG_OMAP_HSMMC) += omap_hsmmc.o
 obj-$(CONFIG_X86) += pci_mmc.o
 obj-$(CONFIG_PXA_MMC_GENERIC) += pxa_mmc_gen.o
+obj-$(CONFIG_ROCKCHIP_DWMMC) += rockchip_dw_mmc.o
 obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb.o
 obj-$(CONFIG_S3C_SDI) += s3c_sdi.o
 obj-$(CONFIG_S5P_SDHCI) += s5p_sdhci.o
index 77b87e0..1117fed 100644 (file)
@@ -266,7 +266,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
         * host->bus_hz should be set by user.
         */
        if (host->get_mmc_clk)
-               sclk = host->get_mmc_clk(host);
+               sclk = host->get_mmc_clk(host, freq);
        else if (host->bus_hz)
                sclk = host->bus_hz;
        else {
index cde2ba7..863bbb3 100644 (file)
@@ -39,7 +39,7 @@ static void exynos_dwmci_clksel(struct dwmci_host *host)
        dwmci_writel(host, DWMCI_CLKSEL, priv->sdr_timing);
 }
 
-unsigned int exynos_dwmci_get_clk(struct dwmci_host *host)
+unsigned int exynos_dwmci_get_clk(struct dwmci_host *host, uint freq)
 {
        unsigned long sclk;
        int8_t clk_div;
index f12546a..371c1ec 100644 (file)
@@ -10,6 +10,8 @@
 #include <config.h>
 #include <common.h>
 #include <command.h>
+#include <dm.h>
+#include <dm/device-internal.h>
 #include <errno.h>
 #include <mmc.h>
 #include <part.h>
@@ -1759,10 +1761,44 @@ static void do_preinit(void)
        }
 }
 
+#if defined(CONFIG_DM_MMC) && defined(CONFIG_SPL_BUILD)
+static int mmc_probe(bd_t *bis)
+{
+       return 0;
+}
+#elif defined(CONFIG_DM_MMC)
+static int mmc_probe(bd_t *bis)
+{
+       int ret;
+       struct uclass *uc;
+       struct udevice *m;
+
+       ret = uclass_get(UCLASS_MMC, &uc);
+       if (ret)
+               return ret;
+
+       uclass_foreach_dev(m, uc) {
+               ret = device_probe(m);
+               if (ret)
+                       printf("%s - probe failed: %d\n", m->name, ret);
+       }
+
+       return 0;
+}
+#else
+static int mmc_probe(bd_t *bis)
+{
+       if (board_mmc_init(bis) < 0)
+               cpu_mmc_init(bis);
+
+       return 0;
+}
+#endif
 
 int mmc_initialize(bd_t *bis)
 {
        static int initialized = 0;
+       int ret;
        if (initialized)        /* Avoid initializing mmc multiple times */
                return 0;
        initialized = 1;
@@ -1770,10 +1806,9 @@ int mmc_initialize(bd_t *bis)
        INIT_LIST_HEAD (&mmc_devices);
        cur_dev_num = 0;
 
-#ifndef CONFIG_DM_MMC
-       if (board_mmc_init(bis) < 0)
-               cpu_mmc_init(bis);
-#endif
+       ret = mmc_probe(bis);
+       if (ret)
+               return ret;
 
 #ifndef CONFIG_SPL_BUILD
        print_mmc_devices(',');
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
new file mode 100644 (file)
index 0000000..f11c8e0
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <dwmmc.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <linux/err.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rockchip_dwmmc_priv {
+       struct udevice *clk;
+       struct rk3288_grf *grf;
+       struct dwmci_host host;
+};
+
+static uint rockchip_dwmmc_get_mmc_clk(struct dwmci_host *host, uint freq)
+{
+       struct udevice *dev = host->priv;
+       struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+       int ret;
+
+       ret = clk_set_periph_rate(priv->clk, PERIPH_ID_SDMMC0 + host->dev_index,
+                                 freq);
+       if (ret < 0) {
+               debug("%s: err=%d\n", __func__, ret);
+               return ret;
+       }
+
+       return freq;
+}
+
+static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
+{
+       struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+       struct dwmci_host *host = &priv->host;
+
+       host->name = dev->name;
+       host->ioaddr = (void *)dev_get_addr(dev);
+       host->buswidth = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                                       "bus-width", 4);
+       host->get_mmc_clk = rockchip_dwmmc_get_mmc_clk;
+       host->priv = dev;
+
+       /* TODO(sjg@chromium.org): Remove the need for this hack */
+       host->dev_index = (ulong)host->ioaddr == 0xff0f0000 ? 0 : 1;
+
+       return 0;
+}
+
+static int rockchip_dwmmc_probe(struct udevice *dev)
+{
+       struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+       struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
+       struct dwmci_host *host = &priv->host;
+       u32 minmax[2];
+       int ret;
+
+       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+       if (IS_ERR(priv->grf))
+               return PTR_ERR(priv->grf);
+       ret = uclass_get_device(UCLASS_CLK, CLK_GENERAL, &priv->clk);
+       if (ret)
+               return ret;
+
+       ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+                                  "clock-freq-min-max", minmax, 2);
+       if (!ret)
+               ret = add_dwmci(host, minmax[1], minmax[0]);
+       if (ret)
+               return ret;
+
+       upriv->mmc = host->mmc;
+
+       return 0;
+}
+
+static const struct udevice_id rockchip_dwmmc_ids[] = {
+       { .compatible = "rockchip,rk3288-dw-mshc" },
+       { }
+};
+
+U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
+       .name           = "rockchip_dwmmc",
+       .id             = UCLASS_MMC,
+       .of_match       = rockchip_dwmmc_ids,
+       .ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
+       .probe          = rockchip_dwmmc_probe,
+       .priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
+};
index 30b8e45..b8146df 100644 (file)
@@ -47,7 +47,10 @@ config PINMUX
        default y
        help
          This option enables pin multiplexing through the generic pinctrl
-         framework.
+         framework. Most SoCs have their own own multiplexing arrangement
+         where a single pin can be used for several functions. An SoC pinctrl
+         driver allows the required function to be selected for each pin.
+         The driver is typically controlled by the device tree.
 
 config PINCONF
        bool "Support pin configuration controllers"
@@ -86,6 +89,12 @@ config SPL_PINMUX
        help
          This option is an SPL-variant of the PINMUX option.
          See the help of PINMUX for details.
+         The pinctrl subsystem can add a substantial overhead to the SPL
+         image since it typically requires quite a few tables either in the
+         driver or in the device tree. If this is acceptable and you need
+         to adjust pin multiplexing in SPL in order to boot into U-Boot,
+         enable this option. You will need to enable device tree in SPL
+         for this to work.
 
 config SPL_PINCONF
        bool "Support pin configuration controllers in SPL"
@@ -96,6 +105,15 @@ config SPL_PINCONF
 
 if PINCTRL || SPL_PINCTRL
 
+config ROCKCHIP_PINCTRL
+       bool "Rockchip pin control driver"
+       depends on DM
+       help
+         Support pin multiplexing control on Rockchip SoCs. The driver is
+         controlled by a device tree node which contains both the GPIO
+         definitions and pin control functions for each available multiplex
+         function.
+
 config PINCTRL_SANDBOX
        bool "Sandbox pinctrl driver"
        depends on SANDBOX
index 35decf4..f537df4 100644 (file)
@@ -1,4 +1,5 @@
 obj-y                                  += pinctrl-uclass.o
 obj-$(CONFIG_$(SPL_)PINCTRL_GENERIC)   += pinctrl-generic.o
 
+obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
 obj-$(CONFIG_PINCTRL_SANDBOX)  += pinctrl-sandbox.o
index d96c201..58001ef 100644 (file)
@@ -11,6 +11,7 @@
 #include <dm/device.h>
 #include <dm/lists.h>
 #include <dm/pinctrl.h>
+#include <dm/root.h>
 #include <dm/uclass.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -159,7 +160,8 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename)
 
 static int pinconfig_post_bind(struct udevice *dev)
 {
-       return 0;
+       /* Scan the bus for devices */
+       return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false);
 }
 #endif
 
@@ -205,6 +207,31 @@ int pinctrl_select_state(struct udevice *dev, const char *statename)
        return 0;
 }
 
+int pinctrl_request(struct udevice *dev, int func, int flags)
+{
+       struct pinctrl_ops *ops = pinctrl_get_ops(dev);
+
+       if (!ops->request)
+               return -ENOSYS;
+
+       return ops->request(dev, func, flags);
+}
+
+int pinctrl_request_noflags(struct udevice *dev, int func)
+{
+       return pinctrl_request(dev, func, 0);
+}
+
+int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph)
+{
+       struct pinctrl_ops *ops = pinctrl_get_ops(dev);
+
+       if (!ops->get_periph_id)
+               return -ENOSYS;
+
+       return ops->get_periph_id(dev, periph);
+}
+
 /**
  * pinconfig_post-bind() - post binding for PINCTRL uclass
  * Recursively bind child nodes as pinconfig devices in case of full pinctrl.
@@ -222,15 +249,10 @@ static int pinctrl_post_bind(struct udevice *dev)
        }
 
        /*
-        * If set_state callback is set, we assume this pinctrl driver is the
-        * full implementation.  In this case, its child nodes should be bound
-        * so that peripheral devices can easily search in parent devices
-        * during later DT-parsing.
+        * The pinctrl driver child nodes should be bound so that peripheral
+        * devices can easily search in parent devices during later DT-parsing.
         */
-       if (ops->set_state)
-               return pinconfig_post_bind(dev);
-
-       return 0;
+       return pinconfig_post_bind(dev);
 }
 
 UCLASS_DRIVER(pinctrl) = {
diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile
new file mode 100644 (file)
index 0000000..251bace
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2015 Google, Inc
+# Written by Simon Glass <sjg@chromium.org>
+#
+# SPDX-License-Identifier:     GPL-2.0+
+#
+
+obj-$(CONFIG_ROCKCHIP_PINCTRL) += pinctrl_rk3288.o
diff --git a/drivers/pinctrl/rockchip/pinctrl_rk3288.c b/drivers/pinctrl/rockchip/pinctrl_rk3288.c
new file mode 100644 (file)
index 0000000..5205498
--- /dev/null
@@ -0,0 +1,441 @@
+/*
+ * Pinctrl driver for Rockchip SoCs
+ * Copyright (c) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/grf_rk3288.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/periph.h>
+#include <asm/arch/pmu_rk3288.h>
+#include <dm/pinctrl.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct rk3288_pinctrl_priv {
+       struct rk3288_grf *grf;
+       struct rk3288_pmu *pmu;
+};
+
+static void pinctrl_rk3288_pwm_config(struct rk3288_grf *grf, int pwm_id)
+{
+       switch (pwm_id) {
+       case PERIPH_ID_PWM0:
+               rk_clrsetreg(&grf->gpio7a_iomux, GPIO7A0_MASK << GPIO7A0_SHIFT,
+                            GPIO7A0_PWM_0 << GPIO7A0_SHIFT);
+               break;
+       case PERIPH_ID_PWM1:
+               rk_clrsetreg(&grf->gpio7a_iomux, GPIO7A1_MASK << GPIO7A1_SHIFT,
+                            GPIO7A1_PWM_1 << GPIO7A1_SHIFT);
+               break;
+       case PERIPH_ID_PWM2:
+               rk_clrsetreg(&grf->gpio7a_iomux, GPIO7C6_MASK << GPIO7C6_SHIFT,
+                            GPIO7C6_PWM_2 << GPIO7C6_SHIFT);
+               break;
+       case PERIPH_ID_PWM3:
+               rk_clrsetreg(&grf->gpio7a_iomux, GPIO7C7_MASK << GPIO7C6_SHIFT,
+                            GPIO7C7_PWM_3 << GPIO7C7_SHIFT);
+               break;
+       default:
+               debug("pwm id = %d iomux error!\n", pwm_id);
+               break;
+       }
+}
+
+static void pinctrl_rk3288_i2c_config(struct rk3288_grf *grf,
+                                     struct rk3288_pmu *pmu, int i2c_id)
+{
+       switch (i2c_id) {
+       case PERIPH_ID_I2C0:
+               clrsetbits_le32(&pmu->gpio0b_iomux,
+                               GPIO0_B7_MASK << GPIO0_B7_SHIFT,
+                               GPIO0_B7_I2C0PMU_SDA << GPIO0_B7_SHIFT);
+               clrsetbits_le32(&pmu->gpio0b_iomux,
+                               GPIO0_C0_MASK << GPIO0_C0_SHIFT,
+                               GPIO0_C0_I2C0PMU_SCL << GPIO0_C0_SHIFT);
+               break;
+       case PERIPH_ID_I2C1:
+               rk_clrsetreg(&grf->gpio8a_iomux,
+                            GPIO8A4_MASK << GPIO8A4_SHIFT |
+                            GPIO8A5_MASK << GPIO8A5_SHIFT,
+                            GPIO8A4_I2C2SENSOR_SDA << GPIO8A4_SHIFT |
+                            GPIO8A5_I2C2SENSOR_SCL << GPIO8A5_SHIFT);
+               break;
+       case PERIPH_ID_I2C2:
+               rk_clrsetreg(&grf->gpio6b_iomux,
+                            GPIO6B1_MASK << GPIO6B1_SHIFT |
+                            GPIO6B2_MASK << GPIO6B2_SHIFT,
+                            GPIO6B1_I2C1AUDIO_SDA << GPIO6B1_SHIFT |
+                            GPIO6B2_I2C1AUDIO_SCL << GPIO6B2_SHIFT);
+               break;
+       case PERIPH_ID_I2C3:
+               rk_clrsetreg(&grf->gpio2c_iomux,
+                            GPIO2C1_MASK << GPIO2C1_SHIFT |
+                            GPIO2C0_MASK << GPIO2C0_SHIFT,
+                            GPIO2C1_I2C3CAM_SDA << GPIO2C1_SHIFT |
+                            GPIO2C0_I2C3CAM_SCL << GPIO2C0_SHIFT);
+               break;
+       case PERIPH_ID_I2C4:
+               rk_clrsetreg(&grf->gpio7cl_iomux,
+                            GPIO7C1_MASK << GPIO7C1_SHIFT |
+                            GPIO7C2_MASK << GPIO7C2_SHIFT,
+                            GPIO7C1_I2C4TP_SDA << GPIO7C1_SHIFT |
+                            GPIO7C2_I2C4TP_SCL << GPIO7C2_SHIFT);
+               break;
+       case PERIPH_ID_I2C5:
+               rk_clrsetreg(&grf->gpio7cl_iomux,
+                            GPIO7C3_MASK << GPIO7C3_SHIFT,
+                            GPIO7C3_I2C5HDMI_SDA << GPIO7C3_SHIFT);
+               rk_clrsetreg(&grf->gpio7ch_iomux,
+                            GPIO7C4_MASK << GPIO7C4_SHIFT,
+                            GPIO7C4_I2C5HDMI_SCL << GPIO7C4_SHIFT);
+               break;
+       default:
+               debug("i2c id = %d iomux error!\n", i2c_id);
+               break;
+       }
+}
+
+static void pinctrl_rk3288_lcdc_config(struct rk3288_grf *grf, int lcd_id)
+{
+       switch (lcd_id) {
+       case PERIPH_ID_LCDC0:
+               rk_clrsetreg(&grf->gpio1d_iomux,
+                            GPIO1D3_MASK << GPIO1D0_SHIFT |
+                            GPIO1D2_MASK << GPIO1D2_SHIFT |
+                            GPIO1D1_MASK << GPIO1D1_SHIFT |
+                            GPIO1D0_MASK << GPIO1D0_SHIFT,
+                            GPIO1D3_LCDC0_DCLK << GPIO1D3_SHIFT |
+                            GPIO1D2_LCDC0_DEN << GPIO1D2_SHIFT |
+                            GPIO1D1_LCDC0_VSYNC << GPIO1D1_SHIFT |
+                            GPIO1D0_LCDC0_HSYNC << GPIO1D0_SHIFT);
+               break;
+       default:
+               debug("lcdc id = %d iomux error!\n", lcd_id);
+               break;
+       }
+}
+
+static int pinctrl_rk3288_spi_config(struct rk3288_grf *grf,
+                                    enum periph_id spi_id, int cs)
+{
+       switch (spi_id) {
+       case PERIPH_ID_SPI0:
+               switch (cs) {
+               case 0:
+                       rk_clrsetreg(&grf->gpio5b_iomux,
+                                    GPIO5B5_MASK << GPIO5B5_SHIFT,
+                                    GPIO5B5_SPI0_CSN0 << GPIO5B5_SHIFT);
+                       break;
+               case 1:
+                       rk_clrsetreg(&grf->gpio5c_iomux,
+                                    GPIO5C0_MASK << GPIO5C0_SHIFT,
+                                    GPIO5C0_SPI0_CSN1 << GPIO5C0_SHIFT);
+                       break;
+               default:
+                       goto err;
+               }
+               rk_clrsetreg(&grf->gpio5b_iomux,
+                            GPIO5B7_MASK << GPIO5B7_SHIFT |
+                            GPIO5B6_MASK << GPIO5B6_SHIFT |
+                            GPIO5B4_MASK << GPIO5B4_SHIFT,
+                            GPIO5B7_SPI0_RXD << GPIO5B7_SHIFT |
+                            GPIO5B6_SPI0_TXD << GPIO5B6_SHIFT |
+                            GPIO5B4_SPI0_CLK << GPIO5B4_SHIFT);
+               break;
+       case PERIPH_ID_SPI1:
+               if (cs != 0)
+                       goto err;
+               rk_clrsetreg(&grf->gpio7b_iomux,
+                            GPIO7B6_MASK << GPIO7B6_SHIFT |
+                            GPIO7B7_MASK << GPIO7B7_SHIFT |
+                            GPIO7B5_MASK << GPIO7B5_SHIFT |
+                            GPIO7B4_MASK << GPIO7B4_SHIFT,
+                            GPIO7B6_SPI1_RXD << GPIO7B6_SHIFT |
+                            GPIO7B7_SPI1_TXD << GPIO7B7_SHIFT |
+                            GPIO7B5_SPI1_CSN0 << GPIO7B5_SHIFT |
+                            GPIO7B4_SPI1_CLK << GPIO7B4_SHIFT);
+               break;
+       case PERIPH_ID_SPI2:
+               switch (cs) {
+               case 0:
+                       rk_clrsetreg(&grf->gpio8a_iomux,
+                                    GPIO8A7_MASK << GPIO8A7_SHIFT,
+                                    GPIO8A7_SPI2_CSN0 << GPIO8A7_SHIFT);
+                       break;
+               case 1:
+                       rk_clrsetreg(&grf->gpio8a_iomux,
+                                    GPIO8A3_MASK << GPIO8A3_SHIFT,
+                                    GPIO8A3_SPI2_CSN1 << GPIO8A3_SHIFT);
+                       break;
+               default:
+                       goto err;
+               }
+               rk_clrsetreg(&grf->gpio8b_iomux,
+                            GPIO8B1_MASK << GPIO8B1_SHIFT |
+                            GPIO8B0_MASK << GPIO8B0_SHIFT,
+                            GPIO8B1_SPI2_TXD << GPIO8B1_SHIFT |
+                            GPIO8B0_SPI2_RXD << GPIO8B0_SHIFT);
+               rk_clrsetreg(&grf->gpio8a_iomux,
+                            GPIO8A6_MASK << GPIO8A6_SHIFT,
+                            GPIO8A6_SPI2_CLK << GPIO8A6_SHIFT);
+               break;
+       default:
+               goto err;
+       }
+
+       return 0;
+err:
+       debug("rkspi: periph%d cs=%d not supported", spi_id, cs);
+       return -ENOENT;
+}
+
+static void pinctrl_rk3288_uart_config(struct rk3288_grf *grf, int uart_id)
+{
+       switch (uart_id) {
+       case PERIPH_ID_UART_BT:
+               rk_clrsetreg(&grf->gpio4c_iomux,
+                            GPIO4C3_MASK << GPIO4C3_SHIFT |
+                            GPIO4C2_MASK << GPIO4C2_SHIFT |
+                            GPIO4C1_MASK << GPIO4C1_SHIFT |
+                            GPIO4C0_MASK << GPIO4C0_SHIFT,
+                            GPIO4C3_UART0BT_RTSN << GPIO4C3_SHIFT |
+                            GPIO4C2_UART0BT_CTSN << GPIO4C2_SHIFT |
+                            GPIO4C1_UART0BT_SOUT << GPIO4C1_SHIFT |
+                            GPIO4C0_UART0BT_SIN << GPIO4C0_SHIFT);
+               break;
+       case PERIPH_ID_UART_BB:
+               rk_clrsetreg(&grf->gpio5b_iomux,
+                            GPIO5B3_MASK << GPIO5B3_SHIFT |
+                            GPIO5B2_MASK << GPIO5B2_SHIFT |
+                            GPIO5B1_MASK << GPIO5B1_SHIFT |
+                            GPIO5B0_MASK << GPIO5B0_SHIFT,
+                            GPIO5B3_UART1BB_RTSN << GPIO5B3_SHIFT |
+                            GPIO5B2_UART1BB_CTSN << GPIO5B2_SHIFT |
+                            GPIO5B1_UART1BB_SOUT << GPIO5B1_SHIFT |
+                            GPIO5B0_UART1BB_SIN << GPIO5B0_SHIFT);
+               break;
+       case PERIPH_ID_UART_DBG:
+               rk_clrsetreg(&grf->gpio7ch_iomux,
+                            GPIO7C7_MASK << GPIO7C7_SHIFT |
+                            GPIO7C6_MASK << GPIO7C6_SHIFT,
+                            GPIO7C7_UART2DBG_SOUT << GPIO7C7_SHIFT |
+                            GPIO7C6_UART2DBG_SIN << GPIO7C6_SHIFT);
+               break;
+       case PERIPH_ID_UART_GPS:
+               rk_clrsetreg(&grf->gpio7b_iomux,
+                            GPIO7B2_MASK << GPIO7B2_SHIFT |
+                            GPIO7B1_MASK << GPIO7B1_SHIFT |
+                            GPIO7B0_MASK << GPIO7B0_SHIFT,
+                            GPIO7B2_UART3GPS_RTSN << GPIO7B2_SHIFT |
+                            GPIO7B1_UART3GPS_CTSN << GPIO7B1_SHIFT |
+                            GPIO7B0_UART3GPS_SOUT << GPIO7B0_SHIFT);
+               rk_clrsetreg(&grf->gpio7a_iomux,
+                            GPIO7A7_MASK << GPIO7A7_SHIFT,
+                            GPIO7A7_UART3GPS_SIN << GPIO7A7_SHIFT);
+               break;
+       case PERIPH_ID_UART_EXP:
+               rk_clrsetreg(&grf->gpio5b_iomux,
+                            GPIO5B5_MASK << GPIO5B5_SHIFT |
+                            GPIO5B4_MASK << GPIO5B4_SHIFT |
+                            GPIO5B6_MASK << GPIO5B6_SHIFT |
+                            GPIO5B7_MASK << GPIO5B7_SHIFT,
+                            GPIO5B5_UART4EXP_RTSN << GPIO5B5_SHIFT |
+                            GPIO5B4_UART4EXP_CTSN << GPIO5B4_SHIFT |
+                            GPIO5B6_UART4EXP_SOUT << GPIO5B6_SHIFT |
+                            GPIO5B7_UART4EXP_SIN << GPIO5B7_SHIFT);
+               break;
+       default:
+               debug("uart id = %d iomux error!\n", uart_id);
+               break;
+       }
+}
+
+static void pinctrl_rk3288_sdmmc_config(struct rk3288_grf *grf, int mmc_id)
+{
+       switch (mmc_id) {
+       case PERIPH_ID_EMMC:
+               rk_clrsetreg(&grf->gpio3a_iomux, 0xffff,
+                            GPIO3A7_EMMC_DATA7 << GPIO3A7_SHIFT |
+                            GPIO3A6_EMMC_DATA6 << GPIO3A6_SHIFT |
+                            GPIO3A5_EMMC_DATA5 << GPIO3A5_SHIFT |
+                            GPIO3A4_EMMC_DATA4 << GPIO3A4_SHIFT |
+                            GPIO3A3_EMMC_DATA3 << GPIO3A3_SHIFT |
+                            GPIO3A2_EMMC_DATA2 << GPIO3A2_SHIFT |
+                            GPIO3A1_EMMC_DATA1 << GPIO3A1_SHIFT |
+                            GPIO3A0_EMMC_DATA0 << GPIO3A0_SHIFT);
+               rk_clrsetreg(&grf->gpio3b_iomux, GPIO3B1_MASK << GPIO3B1_SHIFT,
+                            GPIO3B1_EMMC_PWREN << GPIO3B1_SHIFT);
+               rk_clrsetreg(&grf->gpio3c_iomux,
+                            GPIO3C0_MASK << GPIO3C0_SHIFT,
+                            GPIO3C0_EMMC_CMD << GPIO3C0_SHIFT);
+               break;
+       case PERIPH_ID_SDCARD:
+               rk_clrsetreg(&grf->gpio6c_iomux, 0xffff,
+                            GPIO6C6_SDMMC0_DECTN << GPIO6C6_SHIFT |
+                            GPIO6C5_SDMMC0_CMD << GPIO6C5_SHIFT |
+                            GPIO6C4_SDMMC0_CLKOUT << GPIO6C4_SHIFT |
+                            GPIO6C3_SDMMC0_DATA3 << GPIO6C3_SHIFT |
+                            GPIO6C2_SDMMC0_DATA2 << GPIO6C2_SHIFT |
+                            GPIO6C1_SDMMC0_DATA1 << GPIO6C1_SHIFT |
+                            GPIO6C0_SDMMC0_DATA0 << GPIO6C0_SHIFT);
+
+               /* use sdmmc0 io, disable JTAG function */
+               rk_clrsetreg(&grf->soc_con0, 1 << GRF_FORCE_JTAG_SHIFT, 0);
+               break;
+       default:
+               debug("mmc id = %d iomux error!\n", mmc_id);
+               break;
+       }
+}
+
+static void pinctrl_rk3288_hdmi_config(struct rk3288_grf *grf, int hdmi_id)
+{
+       switch (hdmi_id) {
+       case PERIPH_ID_HDMI:
+               rk_clrsetreg(&grf->gpio7cl_iomux, GPIO7C3_MASK << GPIO7C3_SHIFT,
+                            GPIO7C3_EDPHDMII2C_SDA << GPIO7C3_SHIFT);
+               rk_clrsetreg(&grf->gpio7ch_iomux, GPIO7C4_MASK << GPIO7C4_SHIFT,
+                            GPIO7C4_EDPHDMII2C_SCL << GPIO7C4_SHIFT);
+               break;
+       default:
+               debug("hdmi id = %d iomux error!\n", hdmi_id);
+               break;
+       }
+}
+
+static int rk3288_pinctrl_request(struct udevice *dev, int func, int flags)
+{
+       struct rk3288_pinctrl_priv *priv = dev_get_priv(dev);
+
+       debug("%s: func=%x, flags=%x\n", __func__, func, flags);
+       switch (func) {
+       case PERIPH_ID_PWM0:
+       case PERIPH_ID_PWM1:
+       case PERIPH_ID_PWM2:
+       case PERIPH_ID_PWM3:
+       case PERIPH_ID_PWM4:
+               pinctrl_rk3288_pwm_config(priv->grf, func);
+               break;
+       case PERIPH_ID_I2C0:
+       case PERIPH_ID_I2C1:
+       case PERIPH_ID_I2C2:
+       case PERIPH_ID_I2C3:
+       case PERIPH_ID_I2C4:
+       case PERIPH_ID_I2C5:
+               pinctrl_rk3288_i2c_config(priv->grf, priv->pmu, func);
+               break;
+       case PERIPH_ID_SPI0:
+       case PERIPH_ID_SPI1:
+       case PERIPH_ID_SPI2:
+               pinctrl_rk3288_spi_config(priv->grf, func, flags);
+               break;
+       case PERIPH_ID_UART0:
+       case PERIPH_ID_UART1:
+       case PERIPH_ID_UART2:
+       case PERIPH_ID_UART3:
+       case PERIPH_ID_UART4:
+               pinctrl_rk3288_uart_config(priv->grf, func);
+               break;
+       case PERIPH_ID_LCDC0:
+       case PERIPH_ID_LCDC1:
+               pinctrl_rk3288_lcdc_config(priv->grf, func);
+               break;
+       case PERIPH_ID_SDMMC0:
+       case PERIPH_ID_SDMMC1:
+               pinctrl_rk3288_sdmmc_config(priv->grf, func);
+               break;
+       case PERIPH_ID_HDMI:
+               pinctrl_rk3288_hdmi_config(priv->grf, func);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int rk3288_pinctrl_get_periph_id(struct udevice *dev,
+                                       struct udevice *periph)
+{
+       u32 cell[3];
+       int ret;
+
+       ret = fdtdec_get_int_array(gd->fdt_blob, periph->of_offset,
+                                  "interrupts", cell, ARRAY_SIZE(cell));
+       if (ret < 0)
+               return -EINVAL;
+
+       switch (cell[1]) {
+       case 44:
+               return PERIPH_ID_SPI0;
+       case 45:
+               return PERIPH_ID_SPI1;
+       case 46:
+               return PERIPH_ID_SPI2;
+       case 60:
+               return PERIPH_ID_I2C0;
+       case 62: /* Note strange order */
+               return PERIPH_ID_I2C1;
+       case 61:
+               return PERIPH_ID_I2C2;
+       case 63:
+               return PERIPH_ID_I2C3;
+       case 64:
+               return PERIPH_ID_I2C4;
+       case 65:
+               return PERIPH_ID_I2C5;
+       }
+
+       return -ENOENT;
+}
+
+static int rk3288_pinctrl_set_state_simple(struct udevice *dev,
+                                          struct udevice *periph)
+{
+       int func;
+
+       func = rk3288_pinctrl_get_periph_id(dev, periph);
+       if (func < 0)
+               return func;
+       return rk3288_pinctrl_request(dev, func, 0);
+}
+
+static struct pinctrl_ops rk3288_pinctrl_ops = {
+       .set_state_simple       = rk3288_pinctrl_set_state_simple,
+       .request        = rk3288_pinctrl_request,
+       .get_periph_id  = rk3288_pinctrl_get_periph_id,
+};
+
+static int rk3288_pinctrl_probe(struct udevice *dev)
+{
+       struct rk3288_pinctrl_priv *priv = dev_get_priv(dev);
+
+       priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
+       priv->pmu = syscon_get_first_range(ROCKCHIP_SYSCON_PMU);
+       debug("%s: grf=%p, pmu=%p\n", __func__, priv->grf, priv->pmu);
+
+       return 0;
+}
+
+static const struct udevice_id rk3288_pinctrl_ids[] = {
+       { .compatible = "rockchip,rk3288-pinctrl" },
+       { }
+};
+
+U_BOOT_DRIVER(pinctrl_rk3288) = {
+       .name           = "pinctrl_rk3288",
+       .id             = UCLASS_PINCTRL,
+       .of_match       = rk3288_pinctrl_ids,
+       .priv_auto_alloc_size = sizeof(struct rk3288_pinctrl_priv),
+       .ops            = &rk3288_pinctrl_ops,
+       .probe          = rk3288_pinctrl_probe,
+};
index fc6a374..547fd1a 100644 (file)
@@ -10,6 +10,15 @@ config DM_PMIC
        - 'drivers/power/pmic/pmic-uclass.c'
        - 'include/power/pmic.h'
 
+config PMIC_ACT8846
+       bool "Enable support for the active-semi 8846 PMIC"
+       depends on DM_PMIC && DM_I2C
+       ---help---
+       This PMIC includes 4 DC/DC step-down buck regulators and 8 low-dropout
+       regulators (LDOs). It also provides some GPIO, reset and battery
+       functions. It uses an I2C interface and is designed for use with
+       tablets and smartphones.
+
 config DM_PMIC_PFUZE100
        bool "Enable Driver Model for PMIC PFUZE100"
        depends on DM_PMIC
index e7a7617..00fde71 100644 (file)
@@ -9,6 +9,7 @@ obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
 obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
 obj-$(CONFIG_DM_PMIC_PFUZE100) += pfuze100.o
 obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
+obj-$(CONFIG_PMIC_ACT8846) += act8846.o
 obj-$(CONFIG_PMIC_TPS65090) += tps65090.o
 obj-$(CONFIG_PMIC_S5M8767) += s5m8767.o
 
diff --git a/drivers/power/pmic/act8846.c b/drivers/power/pmic/act8846.c
new file mode 100644 (file)
index 0000000..ff096b3
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdtdec.h>
+#include <libfdt.h>
+#include <power/act8846_pmic.h>
+#include <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct pmic_child_info pmic_children_info[] = {
+       { .prefix = "REG", .driver = "act8846_reg"},
+       { },
+};
+
+static int act8846_reg_count(struct udevice *dev)
+{
+       return ACT8846_NUM_OF_REGS;
+}
+
+static int act8846_write(struct udevice *dev, uint reg, const uint8_t *buff,
+                         int len)
+{
+       if (dm_i2c_write(dev, reg, buff, len)) {
+               debug("write error to device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int act8846_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
+{
+       if (dm_i2c_read(dev, reg, buff, len)) {
+               debug("read error from device: %p register: %#x!", dev, reg);
+               return -EIO;
+       }
+
+       return 0;
+}
+
+static int act8846_bind(struct udevice *dev)
+{
+       const void *blob = gd->fdt_blob;
+       int regulators_node;
+       int children;
+
+       regulators_node = fdt_subnode_offset(blob, dev->of_offset,
+                                            "regulators");
+       if (regulators_node <= 0) {
+               debug("%s: %s regulators subnode not found!", __func__,
+                     dev->name);
+               return -ENXIO;
+       }
+
+       debug("%s: '%s' - found regulators subnode\n", __func__, dev->name);
+
+       children = pmic_bind_children(dev, regulators_node, pmic_children_info);
+       if (!children)
+               debug("%s: %s - no child found\n", __func__, dev->name);
+
+       /* Always return success for this device */
+       return 0;
+}
+
+static struct dm_pmic_ops act8846_ops = {
+       .reg_count = act8846_reg_count,
+       .read = act8846_read,
+       .write = act8846_write,
+};
+
+static const struct udevice_id act8846_ids[] = {
+       { .compatible = "active-semi,act8846" },
+       { }
+};
+
+U_BOOT_DRIVER(pmic_act8846) = {
+       .name = "act8846 pmic",
+       .id = UCLASS_PMIC,
+       .of_match = act8846_ids,
+       .bind = act8846_bind,
+       .ops = &act8846_ops,
+};
index 77d64e4..434dd02 100644 (file)
@@ -16,6 +16,15 @@ config DM_REGULATOR
        for this purpose if PMIC I/O driver is implemented or dm_scan_fdt_node()
        otherwise. Detailed information can be found in the header file.
 
+config REGULATOR_ACT8846
+       bool "Enable driver for ACT8846 regulator"
+       depends on DM_REGULATOR && PMIC_ACT8846
+       ---help---
+       Enable support for the regulator functions of the ACT8846 PMIC. The
+       driver implements get/set api for the various BUCKS and LDOS supported
+       by the PMIC device. This driver is controlled by a device tree node
+       which includes voltage limits.
+
 config DM_REGULATOR_PFUZE100
        bool "Enable Driver Model for REGULATOR PFUZE100"
        depends on DM_REGULATOR && DM_PMIC_PFUZE100
index 7035936..c85978e 100644 (file)
@@ -6,6 +6,7 @@
 #
 
 obj-$(CONFIG_DM_REGULATOR) += regulator-uclass.o
+obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
 obj-$(CONFIG_DM_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_DM_REGULATOR_PFUZE100) += pfuze100.o
 obj-$(CONFIG_DM_REGULATOR_FIXED) += fixed.o
diff --git a/drivers/power/regulator/act8846.c b/drivers/power/regulator/act8846.c
new file mode 100644 (file)
index 0000000..255f8b0
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Based on Rockchip's drivers/power/pmic/pmic_act8846.c:
+ * Copyright (C) 2012 rockchips
+ * zyw <zyw@rock-chips.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <power/act8846_pmic.h>
+#include <power/pmic.h>
+#include <power/regulator.h>
+
+static const u16 voltage_map[] = {
+       600, 625, 650, 675, 700, 725, 750, 775,
+       800, 825, 850, 875, 900, 925, 950, 975,
+       1000, 1025, 1050, 1075, 1100, 1125, 1150, 1175,
+       1200, 1250, 1300, 1350, 1400, 1450, 1500, 1550,
+       1600, 1650, 1700, 1750, 1800, 1850, 1900, 1950,
+       2000, 2050, 2100, 2150, 2200, 2250, 2300, 2350,
+       2400, 2500, 2600, 2700, 2800, 2900, 3000, 3100,
+       3200, 3300, 3400, 3500, 3600, 3700, 3800, 3900,
+};
+
+enum {
+       REG_SYS0,
+       REG_SYS1,
+       REG1_VOL        = 0x10,
+       REG1_CTL        = 0X11,
+       REG2_VOL0       = 0x20,
+       REG2_VOL1,
+       REG2_CTL,
+       REG3_VOL0       = 0x30,
+       REG3_VOL1,
+       REG3_CTL,
+       REG4_VOL0       = 0x40,
+       REG4_VOL1,
+       REG4_CTL,
+       REG5_VOL        = 0x50,
+       REG5_CTL,
+       REG6_VOL        = 0X58,
+       REG6_CTL,
+       REG7_VOL        = 0x60,
+       REG7_CTL,
+       REG8_VOL        = 0x68,
+       REG8_CTL,
+       REG9_VOL        = 0x70,
+       REG9_CTL,
+       REG10_VOL       = 0x80,
+       REG10_CTL,
+       REG11_VOL       = 0x90,
+       REG11_CTL,
+       REG12_VOL       = 0xa0,
+       REG12_CTL,
+       REG13           = 0xb1,
+};
+
+static const u8 addr_vol[] = {
+       0, REG1_VOL, REG2_VOL0, REG3_VOL0, REG4_VOL0,
+       REG5_VOL, REG6_VOL, REG7_VOL, REG8_VOL, REG9_VOL,
+       REG10_VOL, REG11_VOL, REG12_VOL,
+};
+
+static const u8 addr_ctl[] = {
+       0, REG1_CTL, REG2_CTL, REG3_CTL, REG4_CTL,
+       REG5_CTL, REG6_CTL, REG7_CTL, REG8_CTL, REG9_CTL,
+       REG10_CTL, REG11_CTL, REG12_CTL,
+};
+
+static int check_volt_table(const u16 *volt_table, int uvolt)
+{
+       int i;
+
+       for (i = VOL_MIN_IDX; i < VOL_MAX_IDX; i++) {
+               if (uvolt <= (volt_table[i] * 1000))
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int reg_get_value(struct udevice *dev)
+{
+       int reg = dev->driver_data;
+       int ret;
+
+       ret = pmic_reg_read(dev->parent, reg);
+       if (ret < 0)
+               return ret;
+
+       return voltage_map[ret & LDO_VOL_MASK] * 1000;
+}
+
+static int reg_set_value(struct udevice *dev, int uvolt)
+{
+       int reg = dev->driver_data;
+       int val;
+
+       val = check_volt_table(voltage_map, uvolt);
+       if (val < 0)
+               return val;
+
+       return pmic_clrsetbits(dev->parent, addr_vol[reg], LDO_VOL_MASK, val);
+}
+
+static int reg_set_enable(struct udevice *dev, bool enable)
+{
+       int reg = dev->driver_data;
+
+       return pmic_clrsetbits(dev->parent, addr_ctl[reg], LDO_EN_MASK,
+                              enable ? LDO_EN_MASK : 0);
+}
+
+static bool reg_get_enable(struct udevice *dev)
+{
+       int reg = dev->driver_data;
+       int ret;
+
+       ret = pmic_reg_read(dev->parent, reg);
+       if (ret < 0)
+               return ret;
+
+       return ret & LDO_EN_MASK ? true : false;
+}
+
+static int act8846_reg_probe(struct udevice *dev)
+{
+       struct dm_regulator_uclass_platdata *uc_pdata;
+       int reg = dev->driver_data;
+
+       uc_pdata = dev_get_uclass_platdata(dev);
+
+       uc_pdata->type = reg <= 4 ? REGULATOR_TYPE_BUCK : REGULATOR_TYPE_LDO;
+       uc_pdata->mode_count = 0;
+
+       return 0;
+}
+
+static const struct dm_regulator_ops act8846_reg_ops = {
+       .get_value  = reg_get_value,
+       .set_value  = reg_set_value,
+       .get_enable = reg_get_enable,
+       .set_enable = reg_set_enable,
+};
+
+U_BOOT_DRIVER(act8846_buck) = {
+       .name = "act8846_reg",
+       .id = UCLASS_REGULATOR,
+       .ops = &act8846_reg_ops,
+       .probe = act8846_reg_probe,
+};
index 002f1da..ccb80d2 100644 (file)
@@ -109,6 +109,15 @@ config DEBUG_UART_SHIFT
          value. Use this value to specify the shift to use, where 0=byte
          registers, 2=32-bit word registers, etc.
 
+config ROCKCHIP_SERIAL
+       bool "Rockchip on-chip UART support"
+       depends on ARCH_UNIPHIER && DM_SERIAL
+       help
+         Select this to enable a debug UART for Rockchip devices. This uses
+         the ns16550 driver. You will need to #define CONFIG_SYS_NS16550 in
+         your board config header. The clock input is automatically set to
+         use the oscillator (24MHz).
+
 config SANDBOX_SERIAL
        bool "Sandbox UART support"
        depends on SANDBOX
index 1d1f036..869ea7b 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o
 obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o
 obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o
 obj-$(CONFIG_MXS_AUART) += mxs_auart.o
+obj-$(CONFIG_ROCKCHIP_SERIAL) += serial_rockchip.o
 obj-$(CONFIG_ARC_SERIAL) += serial_arc.o
 obj-$(CONFIG_TEGRA_SERIAL) += serial_tegra.o
 obj-$(CONFIG_UNIPHIER_SERIAL) += serial_uniphier.o
diff --git a/drivers/serial/serial_rockchip.c b/drivers/serial/serial_rockchip.c
new file mode 100644 (file)
index 0000000..0e7bbfc
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <ns16550.h>
+#include <serial.h>
+#include <asm/arch/clock.h>
+
+static const struct udevice_id rockchip_serial_ids[] = {
+       { .compatible = "rockchip,rk3288-uart" },
+       { }
+};
+
+static int rockchip_serial_ofdata_to_platdata(struct udevice *dev)
+{
+       struct ns16550_platdata *plat = dev_get_platdata(dev);
+       int ret;
+
+       ret = ns16550_serial_ofdata_to_platdata(dev);
+       if (ret)
+               return ret;
+
+       /* Do all Rockchip parts use 24MHz? */
+       plat->clock = 24 * 1000000;
+
+       return 0;
+}
+
+U_BOOT_DRIVER(serial_ns16550) = {
+       .name   = "serial_rockchip",
+       .id     = UCLASS_SERIAL,
+       .of_match = rockchip_serial_ids,
+       .ofdata_to_platdata = rockchip_serial_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct ns16550_platdata),
+       .priv_auto_alloc_size = sizeof(struct NS16550),
+       .probe = ns16550_serial_probe,
+       .ops    = &ns16550_serial_ops,
+       .flags  = DM_FLAG_PRE_RELOC,
+};
index c84a7b7..8e04fce 100644 (file)
@@ -58,6 +58,14 @@ config ICH_SPI
          access the SPI NOR flash on platforms embedding this Intel
          ICH IP core.
 
+config ROCKCHIP_SPI
+       bool "Rockchip SPI driver"
+       help
+         Enable the Rockchip SPI driver, used to access SPI NOR flash and
+         other SPI peripherals (such as the Chrome OS EC) on Rockchip SoCs.
+         This uses driver model and requires a device tree binding to
+         operate.
+
 config SANDBOX_SPI
        bool "Sandbox SPI driver"
        depends on SANDBOX && DM
index ee88aa1..de241be 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
 obj-$(CONFIG_MXC_SPI) += mxc_spi.o
 obj-$(CONFIG_MXS_SPI) += mxs_spi.o
 obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o
 obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
 obj-$(CONFIG_SH_SPI) += sh_spi.o
 obj-$(CONFIG_SH_QSPI) += sh_qspi.o
diff --git a/drivers/spi/rk_spi.c b/drivers/spi/rk_spi.c
new file mode 100644 (file)
index 0000000..5e0c6ad
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * spi driver for rockchip
+ *
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2013 Rockchip Electronics
+ * Peter, Software Engineering, <superpeter.cai@gmail.com>.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/periph.h>
+#include <dm/pinctrl.h>
+#include "rk_spi.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Change to 1 to output registers at the start of each transaction */
+#define DEBUG_RK_SPI   0
+
+struct rockchip_spi_platdata {
+       enum periph_id periph_id;
+       struct udevice *pinctrl;
+       s32 frequency;          /* Default clock frequency, -1 for none */
+       fdt_addr_t base;
+       uint deactivate_delay_us;       /* Delay to wait after deactivate */
+};
+
+struct rockchip_spi_priv {
+       struct rockchip_spi *regs;
+       struct udevice *clk_gpll;
+       unsigned int max_freq;
+       unsigned int mode;
+       enum periph_id periph_id;       /* Peripheral ID for this device */
+       ulong last_transaction_us;      /* Time of last transaction end */
+       u8 bits_per_word;               /* max 16 bits per word */
+       u8 n_bytes;
+       unsigned int speed_hz;
+       unsigned int tmode;
+       uint input_rate;
+};
+
+#define SPI_FIFO_DEPTH         32
+
+static void rkspi_dump_regs(struct rockchip_spi *regs)
+{
+       debug("ctrl0: \t\t0x%08x\n", readl(&regs->ctrlr0));
+       debug("ctrl1: \t\t0x%08x\n", readl(&regs->ctrlr1));
+       debug("ssienr: \t\t0x%08x\n", readl(&regs->enr));
+       debug("ser: \t\t0x%08x\n", readl(&regs->ser));
+       debug("baudr: \t\t0x%08x\n", readl(&regs->baudr));
+       debug("txftlr: \t\t0x%08x\n", readl(&regs->txftlr));
+       debug("rxftlr: \t\t0x%08x\n", readl(&regs->rxftlr));
+       debug("txflr: \t\t0x%08x\n", readl(&regs->txflr));
+       debug("rxflr: \t\t0x%08x\n", readl(&regs->rxflr));
+       debug("sr: \t\t0x%08x\n", readl(&regs->sr));
+       debug("imr: \t\t0x%08x\n", readl(&regs->imr));
+       debug("isr: \t\t0x%08x\n", readl(&regs->isr));
+       debug("dmacr: \t\t0x%08x\n", readl(&regs->dmacr));
+       debug("dmatdlr: \t0x%08x\n", readl(&regs->dmatdlr));
+       debug("dmardlr: \t0x%08x\n", readl(&regs->dmardlr));
+}
+
+static void rkspi_enable_chip(struct rockchip_spi *regs, bool enable)
+{
+       writel(enable ? 1 : 0, &regs->enr);
+}
+
+static void rkspi_set_clk(struct rockchip_spi_priv *priv, uint speed)
+{
+       uint clk_div;
+
+       clk_div = clk_get_divisor(priv->input_rate, speed);
+       debug("spi speed %u, div %u\n", speed, clk_div);
+
+       writel(clk_div, &priv->regs->baudr);
+}
+
+static int rkspi_wait_till_not_busy(struct rockchip_spi *regs)
+{
+       unsigned long start;
+
+       start = get_timer(0);
+       while (readl(&regs->sr) & SR_BUSY) {
+               if (get_timer(start) > ROCKCHIP_SPI_TIMEOUT_MS) {
+                       debug("RK SPI: Status keeps busy for 1000us after a read/write!\n");
+                       return -ETIMEDOUT;
+               }
+       }
+
+       return 0;
+}
+
+static void spi_cs_activate(struct rockchip_spi *regs, uint cs)
+{
+       debug("activate cs%u\n", cs);
+       writel(1 << cs, &regs->ser);
+}
+
+static void spi_cs_deactivate(struct rockchip_spi *regs, uint cs)
+{
+       debug("deactivate cs%u\n", cs);
+       writel(0, &regs->ser);
+}
+
+static int rockchip_spi_ofdata_to_platdata(struct udevice *bus)
+{
+       struct rockchip_spi_platdata *plat = bus->platdata;
+       const void *blob = gd->fdt_blob;
+       int node = bus->of_offset;
+       int ret;
+
+       plat->base = dev_get_addr(bus);
+       ret = uclass_get_device(UCLASS_PINCTRL, 0, &plat->pinctrl);
+       if (ret)
+               return ret;
+       ret = pinctrl_get_periph_id(plat->pinctrl, bus);
+
+       if (ret < 0) {
+               debug("%s: Could not get peripheral ID for %s: %d\n", __func__,
+                     bus->name, ret);
+               return -FDT_ERR_NOTFOUND;
+       }
+       plat->periph_id = ret;
+
+       plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+                                       50000000);
+       plat->deactivate_delay_us = fdtdec_get_int(blob, node,
+                                       "spi-deactivate-delay", 0);
+       debug("%s: base=%x, periph_id=%d, max-frequency=%d, deactivate_delay=%d\n",
+             __func__, plat->base, plat->periph_id, plat->frequency,
+             plat->deactivate_delay_us);
+
+       return 0;
+}
+
+static int rockchip_spi_probe(struct udevice *bus)
+{
+       struct rockchip_spi_platdata *plat = dev_get_platdata(bus);
+       struct rockchip_spi_priv *priv = dev_get_priv(bus);
+       int ret;
+
+       debug("%s: probe\n", __func__);
+       priv->regs = (struct rockchip_spi *)plat->base;
+
+       priv->last_transaction_us = timer_get_us();
+       priv->max_freq = plat->frequency;
+       priv->periph_id = plat->periph_id;
+       ret = uclass_get_device(UCLASS_CLK, CLK_GENERAL, &priv->clk_gpll);
+       if (ret) {
+               debug("%s: Failed to find CLK_GENERAL: %d\n", __func__, ret);
+               return ret;
+       }
+
+       /*
+        * Use 99 MHz as our clock since it divides nicely into 594 MHz which
+        * is the assumed speed for CLK_GENERAL.
+        */
+       ret = clk_set_periph_rate(priv->clk_gpll, plat->periph_id, 99000000);
+       if (ret < 0) {
+               debug("%s: Failed to set clock: %d\n", __func__, ret);
+               return ret;
+       }
+       priv->input_rate = ret;
+       debug("%s: rate = %u\n", __func__, priv->input_rate);
+       priv->bits_per_word = 8;
+       priv->tmode = TMOD_TR; /* Tx & Rx */
+
+       return 0;
+}
+
+static int rockchip_spi_claim_bus(struct udevice *dev)
+{
+       struct udevice *bus = dev->parent;
+       struct rockchip_spi_platdata *plat = dev_get_platdata(bus);
+       struct rockchip_spi_priv *priv = dev_get_priv(bus);
+       struct rockchip_spi *regs = priv->regs;
+       struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+       u8 spi_dfs, spi_tf;
+       uint ctrlr0;
+       int ret;
+
+       /* Disable the SPI hardware */
+       rkspi_enable_chip(regs, 0);
+
+       switch (priv->bits_per_word) {
+       case 8:
+               priv->n_bytes = 1;
+               spi_dfs = DFS_8BIT;
+               spi_tf = HALF_WORD_OFF;
+               break;
+       case 16:
+               priv->n_bytes = 2;
+               spi_dfs = DFS_16BIT;
+               spi_tf = HALF_WORD_ON;
+               break;
+       default:
+               debug("%s: unsupported bits: %dbits\n", __func__,
+                     priv->bits_per_word);
+               return -EPROTONOSUPPORT;
+       }
+
+       rkspi_set_clk(priv, priv->speed_hz);
+
+       /* Operation Mode */
+       ctrlr0 = OMOD_MASTER << OMOD_SHIFT;
+
+       /* Data Frame Size */
+       ctrlr0 |= spi_dfs & DFS_MASK << DFS_SHIFT;
+
+       /* set SPI mode 0..3 */
+       if (priv->mode & SPI_CPOL)
+               ctrlr0 |= SCOL_HIGH << SCOL_SHIFT;
+       if (priv->mode & SPI_CPHA)
+               ctrlr0 |= SCPH_TOGSTA << SCPH_SHIFT;
+
+       /* Chip Select Mode */
+       ctrlr0 |= CSM_KEEP << CSM_SHIFT;
+
+       /* SSN to Sclk_out delay */
+       ctrlr0 |= SSN_DELAY_ONE << SSN_DELAY_SHIFT;
+
+       /* Serial Endian Mode */
+       ctrlr0 |= SEM_LITTLE << SEM_SHIFT;
+
+       /* First Bit Mode */
+       ctrlr0 |= FBM_MSB << FBM_SHIFT;
+
+       /* Byte and Halfword Transform */
+       ctrlr0 |= (spi_tf & HALF_WORD_MASK) << HALF_WORD_TX_SHIFT;
+
+       /* Rxd Sample Delay */
+       ctrlr0 |= 0 << RXDSD_SHIFT;
+
+       /* Frame Format */
+       ctrlr0 |= FRF_SPI << FRF_SHIFT;
+
+       /* Tx and Rx mode */
+       ctrlr0 |= (priv->tmode & TMOD_MASK) << TMOD_SHIFT;
+
+       writel(ctrlr0, &regs->ctrlr0);
+
+       ret = pinctrl_request(plat->pinctrl, priv->periph_id, slave_plat->cs);
+       if (ret) {
+               debug("%s: Cannot request pinctrl: %d\n", __func__, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rockchip_spi_release_bus(struct udevice *dev)
+{
+       return 0;
+}
+
+static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen,
+                          const void *dout, void *din, unsigned long flags)
+{
+       struct udevice *bus = dev->parent;
+       struct rockchip_spi_priv *priv = dev_get_priv(bus);
+       struct rockchip_spi *regs = priv->regs;
+       struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
+       int len = bitlen >> 3;
+       const u8 *out = dout;
+       u8 *in = din;
+       int toread, towrite;
+       int ret;
+
+       debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din,
+             len, flags);
+       if (DEBUG_RK_SPI)
+               rkspi_dump_regs(regs);
+
+       /* Assert CS before transfer */
+       if (flags & SPI_XFER_BEGIN)
+               spi_cs_activate(regs, slave_plat->cs);
+
+       while (len > 0) {
+               int todo = min(len, 0xffff);
+
+               rkspi_enable_chip(regs, true);
+               writel(todo - 1, &regs->ctrlr1);
+               rkspi_enable_chip(regs, true);
+
+               toread = todo;
+               towrite = todo;
+               while (toread || towrite) {
+                       u32 status = readl(&regs->sr);
+
+                       if (towrite && !(status & SR_TF_FULL)) {
+                               writel(out ? *out++ : 0, regs->txdr);
+                               towrite--;
+                       }
+                       if (toread && !(status & SR_RF_EMPT)) {
+                               u32 byte = readl(regs->rxdr);
+
+                               if (in)
+                                       *in++ = byte;
+                               toread--;
+                       }
+               }
+               ret = rkspi_wait_till_not_busy(regs);
+               if (ret)
+                       break;
+               len -= todo;
+       }
+
+       /* Deassert CS after transfer */
+       if (flags & SPI_XFER_END)
+               spi_cs_deactivate(regs, slave_plat->cs);
+
+       rkspi_enable_chip(regs, false);
+
+       return ret;
+}
+
+static int rockchip_spi_set_speed(struct udevice *bus, uint speed)
+{
+       struct rockchip_spi_priv *priv = dev_get_priv(bus);
+
+       if (speed > ROCKCHIP_SPI_MAX_RATE)
+               return -EINVAL;
+       if (speed > priv->max_freq)
+               speed = priv->max_freq;
+       priv->speed_hz = speed;
+
+       return 0;
+}
+
+static int rockchip_spi_set_mode(struct udevice *bus, uint mode)
+{
+       struct rockchip_spi_priv *priv = dev_get_priv(bus);
+
+       priv->mode = mode;
+
+       return 0;
+}
+
+static const struct dm_spi_ops rockchip_spi_ops = {
+       .claim_bus      = rockchip_spi_claim_bus,
+       .release_bus    = rockchip_spi_release_bus,
+       .xfer           = rockchip_spi_xfer,
+       .set_speed      = rockchip_spi_set_speed,
+       .set_mode       = rockchip_spi_set_mode,
+       /*
+        * cs_info is not needed, since we require all chip selects to be
+        * in the device tree explicitly
+        */
+};
+
+static const struct udevice_id rockchip_spi_ids[] = {
+       { .compatible = "rockchip,rk3288-spi" },
+       { }
+};
+
+U_BOOT_DRIVER(rockchip_spi) = {
+       .name   = "rockchip_spi",
+       .id     = UCLASS_SPI,
+       .of_match = rockchip_spi_ids,
+       .ops    = &rockchip_spi_ops,
+       .ofdata_to_platdata = rockchip_spi_ofdata_to_platdata,
+       .platdata_auto_alloc_size = sizeof(struct rockchip_spi_platdata),
+       .priv_auto_alloc_size = sizeof(struct rockchip_spi_priv),
+       .probe  = rockchip_spi_probe,
+};
diff --git a/drivers/spi/rk_spi.h b/drivers/spi/rk_spi.h
new file mode 100644 (file)
index 0000000..f1ac812
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * SPI driver for rockchip
+ *
+ * (C) Copyright 2015 Google, Inc
+ *
+ * (C) Copyright 2008-2013 Rockchip Electronics
+ * Peter, Software Engineering, <superpeter.cai@gmail.com>.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __RK_SPI_H
+#define __RK_SPI_H
+
+struct rockchip_spi {
+       u32 ctrlr0;
+       u32 ctrlr1;
+       u32 enr;
+       u32 ser;
+       u32 baudr;
+       u32 txftlr;
+       u32 rxftlr;
+       u32 txflr;
+       u32 rxflr;
+       u32 sr;
+       u32 ipr;
+       u32 imr;
+       u32 isr;
+       u32 risr;
+       u32 icr;
+       u32 dmacr;
+       u32 dmatdlr;
+       u32 dmardlr;            /* 0x44 */
+       u32 reserved[0xef];
+       u32 txdr[0x100];        /* 0x400 */
+       u32 rxdr[0x100];        /* 0x800 */
+};
+
+/* CTRLR0 */
+enum {
+       DFS_SHIFT       = 0,    /* Data Frame Size */
+       DFS_MASK        = 3,
+       DFS_4BIT        = 0,
+       DFS_8BIT,
+       DFS_16BIT,
+       DFS_RESV,
+
+       CFS_SHIFT       = 2,    /* Control Frame Size */
+       CFS_MASK        = 0xf,
+
+       SCPH_SHIFT      = 6,    /* Serial Clock Phase */
+       SCPH_MASK       = 1,
+       SCPH_TOGMID     = 0,    /* SCLK toggles in middle of first data bit */
+       SCPH_TOGSTA,            /* SCLK toggles at start of first data bit */
+
+       SCOL_SHIFT      = 7,    /* Serial Clock Polarity */
+       SCOL_MASK       = 1,
+       SCOL_LOW        = 0,    /* Inactive state of serial clock is low */
+       SCOL_HIGH,              /* Inactive state of serial clock is high */
+
+       CSM_SHIFT       = 8,    /* Chip Select Mode */
+       CSM_MASK        = 0x3,
+       CSM_KEEP        = 0,    /* ss_n stays low after each frame  */
+       CSM_HALF,               /* ss_n high for half sclk_out cycles */
+       CSM_ONE,                /* ss_n high for one sclk_out cycle */
+       CSM_RESV,
+
+       SSN_DELAY_SHIFT = 10,   /* SSN to Sclk_out delay */
+       SSN_DELAY_MASK  = 1,
+       SSN_DELAY_HALF  = 0,    /* 1/2 sclk_out cycle */
+       SSN_DELAY_ONE   = 1,    /* 1 sclk_out cycle */
+
+       SEM_SHIFT       = 11,   /* Serial Endian Mode */
+       SEM_MASK        = 1,
+       SEM_LITTLE      = 0,    /* little endian */
+       SEM_BIG,                /* big endian */
+
+       FBM_SHIFT       = 12,   /* First Bit Mode */
+       FBM_MASK        = 1,
+       FBM_MSB         = 0,    /* first bit is MSB */
+       FBM_LSB,                /* first bit in LSB */
+
+       HALF_WORD_TX_SHIFT = 13,        /* Byte and Halfword Transform */
+       HALF_WORD_MASK  = 1,
+       HALF_WORD_ON    = 0,    /* apb 16bit write/read, spi 8bit write/read */
+       HALF_WORD_OFF,          /* apb 8bit write/read, spi 8bit write/read */
+
+       RXDSD_SHIFT     = 14,   /* Rxd Sample Delay, in cycles */
+       RXDSD_MASK      = 3,
+
+       FRF_SHIFT       = 16,   /* Frame Format */
+       FRF_MASK        = 3,
+       FRF_SPI         = 0,    /* Motorola SPI */
+       FRF_SSP,                        /* Texas Instruments SSP*/
+       FRF_MICROWIRE,          /* National Semiconductors Microwire */
+       FRF_RESV,
+
+       TMOD_SHIFT      = 18,   /* Transfer Mode */
+       TMOD_MASK       = 3,
+       TMOD_TR         = 0,    /* xmit & recv */
+       TMOD_TO,                /* xmit only */
+       TMOD_RO,                /* recv only */
+       TMOD_RESV,
+
+       OMOD_SHIFT      = 20,   /* Operation Mode */
+       OMOD_MASK       = 1,
+       OMOD_MASTER     = 0,    /* Master Mode */
+       OMOD_SLAVE,             /* Slave Mode */
+};
+
+/* SR */
+enum {
+       SR_MASK         = 0x7f,
+       SR_BUSY         = 1 << 0,
+       SR_TF_FULL      = 1 << 1,
+       SR_TF_EMPT      = 1 << 2,
+       SR_RF_EMPT      = 1 << 3,
+       SR_RF_FULL      = 1 << 4,
+};
+
+#define ROCKCHIP_SPI_TIMEOUT_MS                1000
+#define ROCKCHIP_SPI_MAX_RATE          48000000
+
+#endif /* __RK_SPI_H */
diff --git a/include/configs/chromebook_jerry.h b/include/configs/chromebook_jerry.h
new file mode 100644 (file)
index 0000000..a22b123
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_SPI_SUPPORT
+#define CONFIG_SPL_SPI_FLASH_SUPPORT
+#define CONFIG_SPL_SPI_LOAD
+
+#endif
diff --git a/include/configs/firefly-rk3288.h b/include/configs/firefly-rk3288.h
new file mode 100644 (file)
index 0000000..a82adc8
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#include <configs/rk3288_common.h>
+
+#define CONFIG_SPL_MMC_SUPPORT
+
+#endif
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
new file mode 100644 (file)
index 0000000..e8aec28
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __CONFIG_RK3288_COMMON_H
+#define __CONFIG_RK3288_COMMON_H
+
+#include <asm/arch/hardware.h>
+
+#define CONFIG_SYS_NO_FLASH
+#define CONFIG_NR_DRAM_BANKS           1
+#define CONFIG_ENV_IS_NOWHERE
+#define CONFIG_ENV_SIZE                        0x2000
+#define CONFIG_SYS_GENERIC_BOARD
+#define CONFIG_SYS_MAXARGS             16
+#define CONFIG_BAUDRATE                        115200
+#define CONFIG_SYS_MALLOC_LEN          (32 << 20)
+#define CONFIG_SYS_CBSIZE              1024
+#define CONFIG_SKIP_LOWLEVEL_INIT
+#define CONFIG_SYS_THUMB_BUILD
+#define CONFIG_OF_LIBFDT
+#define CONFIG_DISPLAY_BOARDINFO
+
+#define CONFIG_SYS_TIMER_RATE          (24 * 1000 * 1000)
+#define CONFIG_SYS_TIMER_COUNTER       (TIMER7_BASE + 8)
+
+#define CONFIG_SPL_FRAMEWORK
+#define CONFIG_SPL_LIBCOMMON_SUPPORT
+#define CONFIG_SPL_LIBGENERIC_SUPPORT
+#define CONFIG_SPL_SERIAL_SUPPORT
+#define CONFIG_SYS_NS16550
+#define CONFIG_SYS_NS16550_MEM32
+#define CONFIG_SPL_BOARD_INIT
+
+#ifdef CONFIG_SPL_BUILD
+#define CONFIG_SYS_MALLOC_SIMPLE
+#endif
+
+#define CONFIG_SYS_TEXT_BASE           0x00100000
+#define CONFIG_SYS_INIT_SP_ADDR                0x00100000
+#define CONFIG_SYS_LOAD_ADDR           0x00800800
+#define CONFIG_SPL_STACK               0xff718000
+#define CONFIG_SPL_TEXT_BASE           0xff704004
+
+/* MMC/SD IP block */
+#define CONFIG_MMC
+#define CONFIG_GENERIC_MMC
+#define CONFIG_CMD_MMC
+#define CONFIG_SDHCI
+#define CONFIG_DWMMC
+#define CONFIG_BOUNCE_BUFFER
+
+#define CONFIG_DOS_PARTITION
+#define CONFIG_CMD_FAT
+#define CONFIG_FAT_WRITE
+#define CONFIG_CMD_EXT2
+#define CONFIG_CMD_EXT4
+#define CONFIG_CMD_FS_GENERIC
+#define CONFIG_PARTITION_UUIDS
+#define CONFIG_CMD_PART
+
+/* RAW SD card / eMMC locations. */
+#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR        256
+#define CONFIG_SYS_SPI_U_BOOT_OFFS     (128 << 10)
+
+/* FAT sd card locations. */
+#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION     1
+#define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME                "u-boot.img"
+
+#define CONFIG_SPL_PINCTRL_SUPPORT
+#define CONFIG_SPL_GPIO_SUPPORT
+#define CONFIG_SPL_RAM_SUPPORT
+#define CONFIG_SPL_DRIVERS_MISC_SUPPORT
+
+#define CONFIG_CMD_CACHE
+#define CONFIG_CMD_TIME
+
+#define CONFIG_SYS_SDRAM_BASE          0
+#define CONFIG_NR_DRAM_BANKS           1
+#define SDRAM_BANK_SIZE                        (2UL << 30)
+
+#define CONFIG_SPI_FLASH
+#define CONFIG_SPI
+#define CONFIG_CMD_SF
+#define CONFIG_CMD_SPI
+#define CONFIG_SPI_FLASH_GIGADEVICE
+#define CONFIG_SF_DEFAULT_SPEED 20000000
+
+#define CONFIG_CMD_I2C
+
+#ifndef CONFIG_SPL_BUILD
+#include <config_distro_defaults.h>
+
+#define ENV_MEM_LAYOUT_SETTINGS \
+       "scriptaddr=0x00000000\0" \
+       "pxefile_addr_r=0x00100000\0" \
+       "fdt_addr_r=0x01f00000\0" \
+       "kernel_addr_r=0x02000000\0" \
+       "ramdisk_addr_r=0x04000000\0"
+
+/* First try to boot from SD (index 0), then eMMC (index 1 */
+#define BOOT_TARGET_DEVICES(func) \
+       func(MMC, mmc, 0) \
+       func(MMC, mmc, 1)
+
+#include <config_distro_bootcmd.h>
+
+/* Linux fails to load the fdt if it's loaded above 512M on a Rock 2 board, so
+ * limit the fdt reallocation to that */
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       "fdt_high=0x1fffffff\0" \
+       ENV_MEM_LAYOUT_SETTINGS \
+       BOOTENV
+#endif
+
+#endif
index bc6fdb4..f6025f6 100644 (file)
@@ -87,7 +87,33 @@ struct pinctrl_ops {
        int (*pinconf_group_set)(struct udevice *dev, unsigned group_selector,
                                 unsigned param, unsigned argument);
        int (*set_state)(struct udevice *dev, struct udevice *config);
+
+       /* for pinctrl-simple */
        int (*set_state_simple)(struct udevice *dev, struct udevice *periph);
+       /**
+        * request() - Request a particular pinctrl function
+        *
+        * This activates the selected function.
+        *
+        * @dev:        Device to adjust (UCLASS_PINCTRL)
+        * @func:       Function number (driver-specific)
+        * @return 0 if OK, -ve on error
+        */
+       int (*request)(struct udevice *dev, int func, int flags);
+
+       /**
+       * get_periph_id() - get the peripheral ID for a device
+       *
+       * This generally looks at the peripheral's device tree node to work
+       * out the peripheral ID. The return value is normally interpreted as
+       * enum periph_id. so long as this is defined by the platform (which it
+       * should be).
+       *
+       * @dev:         Pinctrl device to use for decoding
+       * @periph:      Device to check
+       * @return peripheral ID of @periph, or -ENOENT on error
+       */
+       int (*get_periph_id)(struct udevice *dev, struct udevice *periph);
 };
 
 #define pinctrl_get_ops(dev)   ((struct pinctrl_ops *)(dev)->driver->ops)
@@ -224,4 +250,38 @@ static inline int pinctrl_select_state(struct udevice *dev,
 }
 #endif
 
+/**
+ * pinctrl_request() - Request a particular pinctrl function
+ *
+ * @dev:       Device to check (UCLASS_PINCTRL)
+ * @func:      Function number (driver-specific)
+ * @flags:     Flags (driver-specific)
+ * @return 0 if OK, -ve on error
+ */
+int pinctrl_request(struct udevice *dev, int func, int flags);
+
+/**
+ * pinctrl_request_noflags() - Request a particular pinctrl function
+ *
+ * This is similar to pinctrl_request() but uses 0 for @flags.
+ *
+ * @dev:       Device to check (UCLASS_PINCTRL)
+ * @func:      Function number (driver-specific)
+ * @return 0 if OK, -ve on error
+ */
+int pinctrl_request_noflags(struct udevice *dev, int func);
+
+/**
+ * pinctrl_get_periph_id() - get the peripheral ID for a device
+ *
+ * This generally looks at the peripheral's device tree node to work out the
+ * peripheral ID. The return value is normally interpreted as enum periph_id.
+ * so long as this is defined by the platform (which it should be).
+ *
+ * @dev:       Pinctrl device to use for decoding
+ * @periph:    Device to check
+ * @return peripheral ID of @periph, or -ENOENT on error
+ */
+int pinctrl_get_periph_id(struct udevice *dev, struct udevice *periph);
+
 #endif /* __PINCTRL_H */
diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h
new file mode 100644 (file)
index 0000000..216eee5
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2014 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+/* core clocks */
+#define PLL_APLL               1
+#define PLL_DPLL               2
+#define PLL_CPLL               3
+#define PLL_GPLL               4
+#define PLL_NPLL               5
+#define ARMCLK                 6
+
+/* sclk gates (special clocks) */
+#define SCLK_GPU               64
+#define SCLK_SPI0              65
+#define SCLK_SPI1              66
+#define SCLK_SPI2              67
+#define SCLK_SDMMC             68
+#define SCLK_SDIO0             69
+#define SCLK_SDIO1             70
+#define SCLK_EMMC              71
+#define SCLK_TSADC             72
+#define SCLK_SARADC            73
+#define SCLK_PS2C              74
+#define SCLK_NANDC0            75
+#define SCLK_NANDC1            76
+#define SCLK_UART0             77
+#define SCLK_UART1             78
+#define SCLK_UART2             79
+#define SCLK_UART3             80
+#define SCLK_UART4             81
+#define SCLK_I2S0              82
+#define SCLK_SPDIF             83
+#define SCLK_SPDIF8CH          84
+#define SCLK_TIMER0            85
+#define SCLK_TIMER1            86
+#define SCLK_TIMER2            87
+#define SCLK_TIMER3            88
+#define SCLK_TIMER4            89
+#define SCLK_TIMER5            90
+#define SCLK_TIMER6            91
+#define SCLK_HSADC             92
+#define SCLK_OTGPHY0           93
+#define SCLK_OTGPHY1           94
+#define SCLK_OTGPHY2           95
+#define SCLK_OTG_ADP           96
+#define SCLK_HSICPHY480M       97
+#define SCLK_HSICPHY12M                98
+#define SCLK_MACREF            99
+#define SCLK_LCDC_PWM0         100
+#define SCLK_LCDC_PWM1         101
+#define SCLK_MAC_RX            102
+#define SCLK_MAC_TX            103
+#define SCLK_EDP_24M           104
+#define SCLK_EDP               105
+#define SCLK_RGA               106
+#define SCLK_ISP               107
+#define SCLK_ISP_JPE           108
+#define SCLK_HDMI_HDCP         109
+#define SCLK_HDMI_CEC          110
+#define SCLK_HEVC_CABAC                111
+#define SCLK_HEVC_CORE         112
+#define SCLK_I2S0_OUT          113
+#define SCLK_SDMMC_DRV         114
+#define SCLK_SDIO0_DRV         115
+#define SCLK_SDIO1_DRV         116
+#define SCLK_EMMC_DRV          117
+#define SCLK_SDMMC_SAMPLE      118
+#define SCLK_SDIO0_SAMPLE      119
+#define SCLK_SDIO1_SAMPLE      120
+#define SCLK_EMMC_SAMPLE       121
+#define SCLK_USBPHY480M_SRC    122
+#define SCLK_PVTM_CORE         123
+#define SCLK_PVTM_GPU          124
+
+#define SCLK_MAC               151
+#define SCLK_MACREF_OUT                152
+
+#define DCLK_VOP0              190
+#define DCLK_VOP1              191
+
+/* aclk gates */
+#define ACLK_GPU               192
+#define ACLK_DMAC1             193
+#define ACLK_DMAC2             194
+#define ACLK_MMU               195
+#define ACLK_GMAC              196
+#define ACLK_VOP0              197
+#define ACLK_VOP1              198
+#define ACLK_CRYPTO            199
+#define ACLK_RGA               200
+#define ACLK_RGA_NIU           201
+#define ACLK_IEP               202
+#define ACLK_VIO0_NIU          203
+#define ACLK_VIP               204
+#define ACLK_ISP               205
+#define ACLK_VIO1_NIU          206
+#define ACLK_HEVC              207
+#define ACLK_VCODEC            208
+#define ACLK_CPU               209
+#define ACLK_PERI              210
+
+/* pclk gates */
+#define PCLK_GPIO0             320
+#define PCLK_GPIO1             321
+#define PCLK_GPIO2             322
+#define PCLK_GPIO3             323
+#define PCLK_GPIO4             324
+#define PCLK_GPIO5             325
+#define PCLK_GPIO6             326
+#define PCLK_GPIO7             327
+#define PCLK_GPIO8             328
+#define PCLK_GRF               329
+#define PCLK_SGRF              330
+#define PCLK_PMU               331
+#define PCLK_I2C0              332
+#define PCLK_I2C1              333
+#define PCLK_I2C2              334
+#define PCLK_I2C3              335
+#define PCLK_I2C4              336
+#define PCLK_I2C5              337
+#define PCLK_SPI0              338
+#define PCLK_SPI1              339
+#define PCLK_SPI2              340
+#define PCLK_UART0             341
+#define PCLK_UART1             342
+#define PCLK_UART2             343
+#define PCLK_UART3             344
+#define PCLK_UART4             345
+#define PCLK_TSADC             346
+#define PCLK_SARADC            347
+#define PCLK_SIM               348
+#define PCLK_GMAC              349
+#define PCLK_PWM               350
+#define PCLK_RKPWM             351
+#define PCLK_PS2C              352
+#define PCLK_TIMER             353
+#define PCLK_TZPC              354
+#define PCLK_EDP_CTRL          355
+#define PCLK_MIPI_DSI0         356
+#define PCLK_MIPI_DSI1         357
+#define PCLK_MIPI_CSI          358
+#define PCLK_LVDS_PHY          359
+#define PCLK_HDMI_CTRL         360
+#define PCLK_VIO2_H2P          361
+#define PCLK_CPU               362
+#define PCLK_PERI              363
+#define PCLK_DDRUPCTL0         364
+#define PCLK_PUBL0             365
+#define PCLK_DDRUPCTL1         366
+#define PCLK_PUBL1             367
+#define PCLK_WDT               368
+
+/* hclk gates */
+#define HCLK_GPS               448
+#define HCLK_OTG0              449
+#define HCLK_USBHOST0          450
+#define HCLK_USBHOST1          451
+#define HCLK_HSIC              452
+#define HCLK_NANDC0            453
+#define HCLK_NANDC1            454
+#define HCLK_TSP               455
+#define HCLK_SDMMC             456
+#define HCLK_SDIO0             457
+#define HCLK_SDIO1             458
+#define HCLK_EMMC              459
+#define HCLK_HSADC             460
+#define HCLK_CRYPTO            461
+#define HCLK_I2S0              462
+#define HCLK_SPDIF             463
+#define HCLK_SPDIF8CH          464
+#define HCLK_VOP0              465
+#define HCLK_VOP1              466
+#define HCLK_ROM               467
+#define HCLK_IEP               468
+#define HCLK_ISP               469
+#define HCLK_RGA               470
+#define HCLK_VIO_AHB_ARBI      471
+#define HCLK_VIO_NIU           472
+#define HCLK_VIP               473
+#define HCLK_VIO2_H2P          474
+#define HCLK_HEVC              475
+#define HCLK_VCODEC            476
+#define HCLK_CPU               477
+#define HCLK_PERI              478
+
+#define CLK_NR_CLKS            (HCLK_PERI + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0             0
+#define SRST_CORE1             1
+#define SRST_CORE2             2
+#define SRST_CORE3             3
+#define SRST_CORE0_PO          4
+#define SRST_CORE1_PO          5
+#define SRST_CORE2_PO          6
+#define SRST_CORE3_PO          7
+#define SRST_PDCORE_STRSYS     8
+#define SRST_PDBUS_STRSYS      9
+#define SRST_L2C               10
+#define SRST_TOPDBG            11
+#define SRST_CORE0_DBG         12
+#define SRST_CORE1_DBG         13
+#define SRST_CORE2_DBG         14
+#define SRST_CORE3_DBG         15
+
+#define SRST_PDBUG_AHB_ARBITOR 16
+#define SRST_EFUSE256          17
+#define SRST_DMAC1             18
+#define SRST_INTMEM            19
+#define SRST_ROM               20
+#define SRST_SPDIF8CH          21
+#define SRST_TIMER             22
+#define SRST_I2S0              23
+#define SRST_SPDIF             24
+#define SRST_TIMER0            25
+#define SRST_TIMER1            26
+#define SRST_TIMER2            27
+#define SRST_TIMER3            28
+#define SRST_TIMER4            29
+#define SRST_TIMER5            30
+#define SRST_EFUSE             31
+
+#define SRST_GPIO0             32
+#define SRST_GPIO1             33
+#define SRST_GPIO2             34
+#define SRST_GPIO3             35
+#define SRST_GPIO4             36
+#define SRST_GPIO5             37
+#define SRST_GPIO6             38
+#define SRST_GPIO7             39
+#define SRST_GPIO8             40
+#define SRST_I2C0              42
+#define SRST_I2C1              43
+#define SRST_I2C2              44
+#define SRST_I2C3              45
+#define SRST_I2C4              46
+#define SRST_I2C5              47
+
+#define SRST_DWPWM             48
+#define SRST_MMC_PERI          49
+#define SRST_PERIPH_MMU                50
+#define SRST_DAP               51
+#define SRST_DAP_SYS           52
+#define SRST_TPIU              53
+#define SRST_PMU_APB           54
+#define SRST_GRF               55
+#define SRST_PMU               56
+#define SRST_PERIPH_AXI                57
+#define SRST_PERIPH_AHB                58
+#define SRST_PERIPH_APB                59
+#define SRST_PERIPH_NIU                60
+#define SRST_PDPERI_AHB_ARBI   61
+#define SRST_EMEM              62
+#define SRST_USB_PERI          63
+
+#define SRST_DMAC2             64
+#define SRST_MAC               66
+#define SRST_GPS               67
+#define SRST_RKPWM             69
+#define SRST_CCP               71
+#define SRST_USBHOST0          72
+#define SRST_HSIC              73
+#define SRST_HSIC_AUX          74
+#define SRST_HSIC_PHY          75
+#define SRST_HSADC             76
+#define SRST_NANDC0            77
+#define SRST_NANDC1            78
+
+#define SRST_TZPC              80
+#define SRST_SPI0              83
+#define SRST_SPI1              84
+#define SRST_SPI2              85
+#define SRST_SARADC            87
+#define SRST_PDALIVE_NIU       88
+#define SRST_PDPMU_INTMEM      89
+#define SRST_PDPMU_NIU         90
+#define SRST_SGRF              91
+
+#define SRST_VIO_ARBI          96
+#define SRST_RGA_NIU           97
+#define SRST_VIO0_NIU_AXI      98
+#define SRST_VIO_NIU_AHB       99
+#define SRST_LCDC0_AXI         100
+#define SRST_LCDC0_AHB         101
+#define SRST_LCDC0_DCLK                102
+#define SRST_VIO1_NIU_AXI      103
+#define SRST_VIP               104
+#define SRST_RGA_CORE          105
+#define SRST_IEP_AXI           106
+#define SRST_IEP_AHB           107
+#define SRST_RGA_AXI           108
+#define SRST_RGA_AHB           109
+#define SRST_ISP               110
+#define SRST_EDP               111
+
+#define SRST_VCODEC_AXI                112
+#define SRST_VCODEC_AHB                113
+#define SRST_VIO_H2P           114
+#define SRST_MIPIDSI0          115
+#define SRST_MIPIDSI1          116
+#define SRST_MIPICSI           117
+#define SRST_LVDS_PHY          118
+#define SRST_LVDS_CON          119
+#define SRST_GPU               120
+#define SRST_HDMI              121
+#define SRST_CORE_PVTM         124
+#define SRST_GPU_PVTM          125
+
+#define SRST_MMC0              128
+#define SRST_SDIO0             129
+#define SRST_SDIO1             130
+#define SRST_EMMC              131
+#define SRST_USBOTG_AHB                132
+#define SRST_USBOTG_PHY                133
+#define SRST_USBOTG_CON                134
+#define SRST_USBHOST0_AHB      135
+#define SRST_USBHOST0_PHY      136
+#define SRST_USBHOST0_CON      137
+#define SRST_USBHOST1_AHB      138
+#define SRST_USBHOST1_PHY      139
+#define SRST_USBHOST1_CON      140
+#define SRST_USB_ADP           141
+#define SRST_ACC_EFUSE         142
+
+#define SRST_CORESIGHT         144
+#define SRST_PD_CORE_AHB_NOC   145
+#define SRST_PD_CORE_APB_NOC   146
+#define SRST_PD_CORE_MP_AXI    147
+#define SRST_GIC               148
+#define SRST_LCDC_PWM0         149
+#define SRST_LCDC_PWM1         150
+#define SRST_VIO0_H2P_BRG      151
+#define SRST_VIO1_H2P_BRG      152
+#define SRST_RGA_H2P_BRG       153
+#define SRST_HEVC              154
+#define SRST_TSADC             159
+
+#define SRST_DDRPHY0           160
+#define SRST_DDRPHY0_APB       161
+#define SRST_DDRCTRL0          162
+#define SRST_DDRCTRL0_APB      163
+#define SRST_DDRPHY0_CTRL      164
+#define SRST_DDRPHY1           165
+#define SRST_DDRPHY1_APB       166
+#define SRST_DDRCTRL1          167
+#define SRST_DDRCTRL1_APB      168
+#define SRST_DDRPHY1_CTRL      169
+#define SRST_DDRMSCH0          170
+#define SRST_DDRMSCH1          171
+#define SRST_CRYPTO            174
+#define SRST_C2C_HOST          175
+
+#define SRST_LCDC1_AXI         176
+#define SRST_LCDC1_AHB         177
+#define SRST_LCDC1_DCLK                178
+#define SRST_UART0             179
+#define SRST_UART1             180
+#define SRST_UART2             181
+#define SRST_UART3             182
+#define SRST_UART4             183
+#define SRST_SIMC              186
+#define SRST_PS2C              187
+#define SRST_TSP               188
+#define SRST_TSP_CLKIN0                189
+#define SRST_TSP_CLKIN1                190
+#define SRST_TSP_27M           191
diff --git a/include/dt-bindings/clock/rockchip,rk808.h b/include/dt-bindings/clock/rockchip,rk808.h
new file mode 100644 (file)
index 0000000..1a87343
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * This header provides constants clk index RK808 pmic clkout
+ */
+#ifndef _CLK_ROCKCHIP_RK808
+#define _CLK_ROCKCHIP_RK808
+
+/* CLOCKOUT index */
+#define RK808_CLKOUT0          0
+#define RK808_CLKOUT1          1
+
+#endif
diff --git a/include/dt-bindings/pinctrl/rockchip.h b/include/dt-bindings/pinctrl/rockchip.h
new file mode 100644 (file)
index 0000000..56887e1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Header providing constants for Rockchip pinctrl bindings.
+ *
+ * Copyright (c) 2013 MundoReader S.L.
+ * Author: Heiko Stuebner <heiko@sntech.de>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
+#define __DT_BINDINGS_ROCKCHIP_PINCTRL_H__
+
+#define RK_GPIO0       0
+#define RK_GPIO1       1
+#define RK_GPIO2       2
+#define RK_GPIO3       3
+#define RK_GPIO4       4
+#define RK_GPIO6       6
+
+#define RK_FUNC_GPIO   0
+#define RK_FUNC_1      1
+#define RK_FUNC_2      2
+#define RK_FUNC_3      3
+#define RK_FUNC_4      4
+
+#endif
diff --git a/include/dt-bindings/power-domain/rk3288.h b/include/dt-bindings/power-domain/rk3288.h
new file mode 100644 (file)
index 0000000..ca68c11
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __DT_BINDINGS_POWER_DOMAIN_RK3288_H__
+#define __DT_BINDINGS_POWER_DOMAIN_RK3288_H__
+
+/* RK3288 power domain index */
+#define RK3288_PD_GPU          0
+#define RK3288_PD_VIO          1
+#define RK3288_PD_VIDEO        2
+#define RK3288_PD_HEVC         3
+#define RK3288_PD_PERI         4
+
+#endif
index 7a7555a..25cf42c 100644 (file)
@@ -163,7 +163,21 @@ struct dwmci_host {
 
        void (*clksel)(struct dwmci_host *host);
        void (*board_init)(struct dwmci_host *host);
-       unsigned int (*get_mmc_clk)(struct dwmci_host *host);
+
+       /**
+        * Get / set a particular MMC clock frequency
+        *
+        * This is used to request the current clock frequency of the clock
+        * that drives the DWMMC peripheral. The caller will then use this
+        * information to work out the divider it needs to achieve the
+        * required MMC bus clock frequency. If you want to handle the
+        * clock external to DWMMC, use @freq to select the frequency and
+        * return that value too. Then DWMMC will put itself in bypass mode.
+        *
+        * @host:       DWMMC host
+        * @freq:       Frequency the host is trying to achieve
+        */
+       unsigned int (*get_mmc_clk)(struct dwmci_host *host, uint freq);
 
        struct mmc_config cfg;
 };
index 63c3d37..8a864ae 100644 (file)
@@ -245,8 +245,11 @@ struct lmb;
 #define IH_TYPE_X86_SETUP      20      /* x86 setup.bin Image          */
 #define IH_TYPE_LPC32XXIMAGE   21      /* x86 setup.bin Image          */
 #define IH_TYPE_LOADABLE       22      /* A list of typeless images    */
+#define IH_TYPE_RKIMAGE                23      /* Rockchip Boot Image          */
+#define IH_TYPE_RKSD           24      /* Rockchip SD card             */
+#define IH_TYPE_RKSPI          25      /* Rockchip SPI image           */
 
-#define IH_TYPE_COUNT          23      /* Number of image types */
+#define IH_TYPE_COUNT          26      /* Number of image types */
 
 /*
  * Compression Types
diff --git a/include/power/act8846_pmic.h b/include/power/act8846_pmic.h
new file mode 100644 (file)
index 0000000..a811f28
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _PMIC_ACT8846_H_
+#define _PMIC_ACT8846_H_
+
+#include <asm/gpio.h>
+
+#define ACT8846_NUM_OF_REGS    12
+
+#define BUCK_VOL_MASK 0x3f
+#define LDO_VOL_MASK 0x3f
+
+#define BUCK_EN_MASK 0x80
+#define LDO_EN_MASK 0x80
+
+#define VOL_MIN_IDX 0x00
+#define VOL_MAX_IDX 0x3f
+
+struct  act8846_reg_table {
+       char    *name;
+       char    reg_ctl;
+       char    reg_vol;
+};
+
+struct pmic_act8846 {
+       struct pmic *pmic;
+       int node;       /*device tree node*/
+       struct gpio_desc pwr_hold;
+       struct udevice *dev;
+};
+
+#endif
index f673258..9082bda 100644 (file)
@@ -64,6 +64,8 @@ RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \
                                        rsa-sign.o rsa-verify.o rsa-checksum.o \
                                        rsa-mod-exp.o)
 
+ROCKCHIP_OBS = lib/rc4.o rkcommon.o rkimage.o rksd.o
+
 # common objs for dumpimage and mkimage
 dumpimage-mkimage-objs := aisimage.o \
                        atmelimage.o \
@@ -90,6 +92,7 @@ dumpimage-mkimage-objs := aisimage.o \
                        os_support.o \
                        pblimage.o \
                        pbl_crc32.o \
+                       $(ROCKCHIP_OBS) \
                        socfpgaimage.o \
                        lib/sha1.o \
                        lib/sha256.o \
index 99bbf2f..ad2deb5 100644 (file)
@@ -60,6 +60,7 @@ struct image_tool_params {
        const char *comment;    /* Comment to add to signature node */
        int require_keys;       /* 1 to mark signing keys as 'required' */
        int file_size;          /* Total size of output file */
+       int orig_file_size;     /* Original size for file before padding */
 };
 
 /*
index e81d455..c50af05 100644 (file)
@@ -488,12 +488,6 @@ copy_file (int ifd, const char *datafile, int pad)
        int size;
        struct image_type_params *tparams = imagetool_get_type(params.type);
 
-       if (pad >= sizeof(zeros)) {
-               fprintf(stderr, "%s: Can't pad to %d\n",
-                       params.cmdname, pad);
-               exit(EXIT_FAILURE);
-       }
-
        memset(zeros, 0, sizeof(zeros));
 
        if (params.vflag) {
@@ -563,11 +557,18 @@ copy_file (int ifd, const char *datafile, int pad)
                        exit (EXIT_FAILURE);
                }
        } else if (pad > 1) {
-               if (write(ifd, (char *)&zeros, pad) != pad) {
-                       fprintf(stderr, "%s: Write error on %s: %s\n",
-                               params.cmdname, params.imagefile,
-                               strerror(errno));
-                       exit(EXIT_FAILURE);
+               while (pad > 0) {
+                       int todo = sizeof(zeros);
+
+                       if (todo > pad)
+                               todo = pad;
+                       if (write(ifd, (char *)&zeros, todo) != todo) {
+                               fprintf(stderr, "%s: Write error on %s: %s\n",
+                                       params.cmdname, params.imagefile,
+                                       strerror(errno));
+                               exit(EXIT_FAILURE);
+                       }
+                       pad -= todo;
                }
        }
 
diff --git a/tools/rkcommon.c b/tools/rkcommon.c
new file mode 100644 (file)
index 0000000..4389622
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * (C) Copyright 2015 Google,  Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * Helper functions for Rockchip images
+ */
+
+#include "imagetool.h"
+#include <image.h>
+#include <rc4.h>
+#include "mkimage.h"
+#include "rkcommon.h"
+
+enum {
+       RK_SIGNATURE            = 0x0ff0aa55,
+};
+
+/**
+ * struct header0_info - header block for boot ROM
+ *
+ * This is stored at SD card block 64 (where each block is 512 bytes, or at
+ * the start of SPI flash. It is encoded with RC4.
+ *
+ * @signature:         Signature (must be RKSD_SIGNATURE)
+ * @disable_rc4:       0 to use rc4 for boot image,  1 to use plain binary
+ * @code1_offset:      Offset in blocks of the SPL code from this header
+ *                     block. E.g. 4 means 2KB after the start of this header.
+ * Other fields are not used by U-Boot
+ */
+struct header0_info {
+       uint32_t signature;
+       uint8_t reserved[4];
+       uint32_t disable_rc4;
+       uint16_t code1_offset;
+       uint16_t code2_offset;
+       uint8_t reserved1[490];
+       uint16_t usflashdatasize;
+       uint16_t ucflashbootsize;
+       uint8_t reserved2[2];
+};
+
+static unsigned char rc4_key[16] = {
+       124, 78, 3, 4, 85, 5, 9, 7,
+       45, 44, 123, 56, 23, 13, 23, 17
+};
+
+int rkcommon_set_header(void *buf, uint file_size)
+{
+       struct header0_info *hdr;
+
+       if (file_size > RK_MAX_CODE1_SIZE)
+               return -ENOSPC;
+
+       memset(buf,  '\0', RK_CODE1_OFFSET * RK_BLK_SIZE);
+       hdr = (struct header0_info *)buf;
+       hdr->signature = RK_SIGNATURE;
+       hdr->disable_rc4 = 1;
+       hdr->code1_offset = RK_CODE1_OFFSET;
+       hdr->code2_offset = 8;
+
+       hdr->usflashdatasize = (file_size + RK_BLK_SIZE - 1) / RK_BLK_SIZE;
+       hdr->usflashdatasize = (hdr->usflashdatasize + 3) & ~3;
+       hdr->ucflashbootsize = hdr->usflashdatasize;
+
+       debug("size=%x, %x\n", params->file_size, hdr->usflashdatasize);
+
+       rc4_encode(buf, RK_BLK_SIZE, rc4_key);
+
+       return 0;
+}
diff --git a/tools/rkcommon.h b/tools/rkcommon.h
new file mode 100644 (file)
index 0000000..57fd726
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2015 Google,  Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _RKCOMMON_H
+#define _RKCOMMON_H
+
+enum {
+       RK_BLK_SIZE             = 512,
+       RK_CODE1_OFFSET         = 4,
+       RK_MAX_CODE1_SIZE       = 32 << 10,
+};
+
+/**
+ * rkcommon_set_header() - set up the header for a Rockchip boot image
+ *
+ * This sets up a 2KB header which can be interpreted by the Rockchip boot ROM.
+ *
+ * @buf:       Pointer to header place (must be at least 2KB in size)
+ * @file_size: Size of the file we want the boot ROM to load, in bytes
+ * @return 0 if OK, -ENOSPC if too large
+ */
+int rkcommon_set_header(void *buf, uint file_size);
+
+#endif
diff --git a/tools/rkimage.c b/tools/rkimage.c
new file mode 100644 (file)
index 0000000..7b292f4
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * (C) Copyright 2015 Google, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * See README.rockchip for details of the rkimage format
+ */
+
+#include "imagetool.h"
+#include <image.h>
+
+static uint32_t header;
+
+static int rkimage_check_params(struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rkimage_verify_header(unsigned char *buf, int size,
+                                struct image_tool_params *params)
+{
+       return 0;
+}
+
+static void rkimage_print_header(const void *buf)
+{
+}
+
+static void rkimage_set_header(void *buf, struct stat *sbuf, int ifd,
+                              struct image_tool_params *params)
+{
+       memcpy(buf, "RK32", 4);
+}
+
+static int rkimage_extract_subimage(void *buf, struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rkimage_check_image_type(uint8_t type)
+{
+       if (type == IH_TYPE_RKIMAGE)
+               return EXIT_SUCCESS;
+       else
+               return EXIT_FAILURE;
+}
+
+/*
+ * rk_image parameters
+ */
+U_BOOT_IMAGE_TYPE(
+       rkimage,
+       "Rockchip Boot Image support",
+       4,
+       &header,
+       rkimage_check_params,
+       rkimage_verify_header,
+       rkimage_print_header,
+       rkimage_set_header,
+       rkimage_extract_subimage,
+       rkimage_check_image_type,
+       NULL,
+       NULL
+);
diff --git a/tools/rksd.c b/tools/rksd.c
new file mode 100644 (file)
index 0000000..a8dbe98
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2015 Google,  Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * See README.rockchip for details of the rksd format
+ */
+
+#include "imagetool.h"
+#include <image.h>
+#include <rc4.h>
+#include "mkimage.h"
+#include "rkcommon.h"
+
+enum {
+       RKSD_SPL_HDR_START      = RK_CODE1_OFFSET * RK_BLK_SIZE,
+       RKSD_SPL_START          = RKSD_SPL_HDR_START + 4,
+       RKSD_HEADER_LEN         = RKSD_SPL_START,
+};
+
+static char dummy_hdr[RKSD_HEADER_LEN];
+
+static int rksd_check_params(struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rksd_verify_header(unsigned char *buf,  int size,
+                                struct image_tool_params *params)
+{
+       return 0;
+}
+
+static void rksd_print_header(const void *buf)
+{
+}
+
+static void rksd_set_header(void *buf,  struct stat *sbuf,  int ifd,
+                              struct image_tool_params *params)
+{
+       unsigned int size;
+       int ret;
+
+       size = params->file_size - RKSD_SPL_HDR_START;
+       ret = rkcommon_set_header(buf, size);
+       if (ret) {
+               /* TODO(sjg@chromium.org): This method should return an error */
+               printf("Warning: SPL image is too large (size %#x) and will not boot\n",
+                      size);
+       }
+
+       memcpy(buf + RKSD_SPL_HDR_START, "RK32", 4);
+}
+
+static int rksd_extract_subimage(void *buf,  struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rksd_check_image_type(uint8_t type)
+{
+       if (type == IH_TYPE_RKSD)
+               return EXIT_SUCCESS;
+       else
+               return EXIT_FAILURE;
+}
+
+/* We pad the file out to a fixed size - this method returns that size */
+static int rksd_vrec_header(struct image_tool_params *params,
+                           struct image_type_params *tparams)
+{
+       int pad_size;
+
+       pad_size = RKSD_SPL_HDR_START + RK_MAX_CODE1_SIZE;
+       debug("pad_size %x\n", pad_size);
+
+       return pad_size - params->file_size;
+}
+
+/*
+ * rk_sd parameters
+ */
+U_BOOT_IMAGE_TYPE(
+       rksd,
+       "Rockchip SD Boot Image support",
+       RKSD_HEADER_LEN,
+       dummy_hdr,
+       rksd_check_params,
+       rksd_verify_header,
+       rksd_print_header,
+       rksd_set_header,
+       rksd_extract_subimage,
+       rksd_check_image_type,
+       NULL,
+       rksd_vrec_header
+);
diff --git a/tools/rkspi.c b/tools/rkspi.c
new file mode 100644 (file)
index 0000000..a3c4c73
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * (C) Copyright 2015 Google,  Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ *
+ * See README.rockchip for details of the rkspi format
+ */
+
+#include "imagetool.h"
+#include <image.h>
+#include <rc4.h>
+#include "mkimage.h"
+#include "rkcommon.h"
+
+enum {
+       RKSPI_SPL_HDR_START     = RK_CODE1_OFFSET * RK_BLK_SIZE,
+       RKSPI_SPL_START         = RKSPI_SPL_HDR_START + 4,
+       RKSPI_HEADER_LEN        = RKSPI_SPL_START,
+       RKSPI_SECT_LEN          = RK_BLK_SIZE * 4,
+};
+
+static char dummy_hdr[RKSPI_HEADER_LEN];
+
+static int rkspi_check_params(struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rkspi_verify_header(unsigned char *buf, int size,
+                              struct image_tool_params *params)
+{
+       return 0;
+}
+
+static void rkspi_print_header(const void *buf)
+{
+}
+
+static void rkspi_set_header(void *buf, struct stat *sbuf, int ifd,
+                            struct image_tool_params *params)
+{
+       int sector;
+       unsigned int size;
+       int ret;
+
+       size = params->orig_file_size;
+       ret = rkcommon_set_header(buf, size);
+       debug("size %x\n", size);
+       if (ret) {
+               /* TODO(sjg@chromium.org): This method should return an error */
+               printf("Warning: SPL image is too large (size %#x) and will not boot\n",
+                      size);
+       }
+
+       memcpy(buf + RKSPI_SPL_HDR_START, "RK32", 4);
+
+       /*
+        * Spread the image out so we only use the first 2KB of each 4KB
+        * region. This is a feature of the SPI format required by the Rockchip
+        * boot ROM. Its rationale is unknown.
+        */
+       for (sector = size / RKSPI_SECT_LEN - 1; sector >= 0; sector--) {
+               printf("sector %u\n", sector);
+               memmove(buf + sector * RKSPI_SECT_LEN * 2,
+                       buf + sector * RKSPI_SECT_LEN,
+                       RKSPI_SECT_LEN);
+               memset(buf + sector * RKSPI_SECT_LEN * 2 + RKSPI_SECT_LEN,
+                      '\0', RKSPI_SECT_LEN);
+       }
+}
+
+static int rkspi_extract_subimage(void *buf, struct image_tool_params *params)
+{
+       return 0;
+}
+
+static int rkspi_check_image_type(uint8_t type)
+{
+       if (type == IH_TYPE_RKSPI)
+               return EXIT_SUCCESS;
+       else
+               return EXIT_FAILURE;
+}
+
+/* We pad the file out to a fixed size - this method returns that size */
+static int rkspi_vrec_header(struct image_tool_params *params,
+                            struct image_type_params *tparams)
+{
+       int pad_size;
+
+       pad_size = (RK_MAX_CODE1_SIZE + 0x7ff) / 0x800 * 0x800;
+       params->orig_file_size = pad_size;
+
+       /* We will double the image size due to the SPI format */
+       pad_size *= 2;
+       pad_size += RKSPI_SPL_HDR_START;
+       debug("pad_size %x\n", pad_size);
+
+       return pad_size - params->file_size;
+}
+
+/*
+ * rk_spi parameters
+ */
+U_BOOT_IMAGE_TYPE(
+       rkspi,
+       "Rockchip SPI Boot Image support",
+       RKSPI_HEADER_LEN,
+       dummy_hdr,
+       rkspi_check_params,
+       rkspi_verify_header,
+       rkspi_print_header,
+       rkspi_set_header,
+       rkspi_extract_subimage,
+       rkspi_check_image_type,
+       NULL,
+       rkspi_vrec_header
+);