Merge git://git.denx.de/u-boot-rockchip

This commit is contained in:
Tom Rini 2015-09-03 14:57:09 -04:00
commit c9feb427ab
108 changed files with 11350 additions and 42 deletions

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

View 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

View 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();

View 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 \

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

1473
arch/arm/dts/rk3288.dtsi Normal file

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,7 @@
#
# (C) Copyright 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += firefly-rk3288.o

View file

@ -0,0 +1,7 @@
/*
* (C) Copyright 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>

View file

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

View file

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

View file

@ -0,0 +1,7 @@
#
# (C) Copyright 2015 Google, Inc
#
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += jerry.o

View file

@ -0,0 +1,7 @@
/*
* (C) Copyright 2015 Google, Inc
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>

View file

@ -4,4 +4,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += early_init.o
obj-$(CONFIG_X86) += early_init.o

View 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, "", "", },
};

View file

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

View file

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

247
doc/README.rockchip Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,4 +6,5 @@
#
obj-$(CONFIG_CLK) += clk-uclass.o
obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o
obj-$(CONFIG_SANDBOX) += clk_sandbox.o

618
drivers/clk/clk_rk3288.c Normal file
View file

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

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

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

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

View 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

View 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

123
drivers/gpio/rk_gpio.c Normal file
View file

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

View 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

View 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

391
drivers/i2c/rk_i2c.c Normal file
View file

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

View 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

View 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

View 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

View 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

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

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

View 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(',');

View file

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

View 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

View 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

View 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) = {

View file

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

View file

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

View 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

View 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

View file

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

View 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

View 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

View file

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

View 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

View 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

View file

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

View 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

View 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

374
drivers/spi/rk_spi.c Normal file
View file

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

124
drivers/spi/rk_spi.h Normal file
View file

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

View file

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

View file

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

View file

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

View 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 */

View file

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

View file

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

View file

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

View file

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

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

View 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

View file

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

Some files were not shown because too many files have changed in this diff Show more