- Add rk3588 evb support;
- Update pinctrl for rk3568 and rk3588;
- Update rk3288 dts;
- Update mmc support for rk3568 and rk3588;
- Add rng support for rk3588;
- Add DSI support for rk3568;
- Some other misc fixes in dts, config, driver;
This commit is contained in:
Tom Rini 2023-04-23 12:15:56 -04:00
commit 328fdeb9c9
76 changed files with 3589 additions and 523 deletions

View file

@ -171,6 +171,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3568) += \
dtb-$(CONFIG_ROCKCHIP_RK3588) += \
rk3588-edgeble-neu6a-io.dtb \
rk3588-evb1-v10.dtb \
rk3588-rock-5b.dtb
dtb-$(CONFIG_ROCKCHIP_RV1108) += \

View file

@ -32,7 +32,7 @@
keyup-threshold-microvolt = <2500000>;
poll-interval = <100>;
recovery {
button-recovery {
label = "recovery";
linux,code = <KEY_VENDOR>;
press-threshold-microvolt = <0>;
@ -157,7 +157,32 @@
pinctrl-0 = <&sd1_clk &sd1_cmd &sd1_bus4>;
pinctrl-names = "default";
vmmc-supply = <&vcc_wifi>;
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
brcmf: wifi@1 {
compatible = "brcm,bcm4329-fmac";
reg = <1>;
};
};
&nfc {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
nand@0 {
reg = <0>;
label = "rk-nand";
nand-bus-width = <8>;
nand-ecc-mode = "hw";
nand-ecc-step-size = <1024>;
nand-ecc-strength = <40>;
nand-is-boot-medium;
rockchip,boot-blks = <8>;
rockchip,boot-ecc-strength = <24>;
};
};
&pinctrl {

View file

@ -2,3 +2,28 @@
#include "rockchip-u-boot.dtsi"
#include "rk3xxx-u-boot.dtsi"
&gpio0 {
gpio-ranges = <&pinctrl 0 0 32>;
};
&gpio1 {
gpio-ranges = <&pinctrl 0 32 32>;
};
&gpio2 {
gpio-ranges = <&pinctrl 0 64 32>;
};
&gpio3 {
gpio-ranges = <&pinctrl 0 96 32>;
};
&gpio4 {
gpio-ranges = <&pinctrl 0 128 32>;
};
&gpio6 {
status = "disabled";
};

View file

@ -202,8 +202,9 @@
cru: clock-controller@20000000 {
compatible = "rockchip,rk3066a-cru";
reg = <0x20000000 0x1000>;
clocks = <&xin24m>;
clock-names = "xin24m";
rockchip,grf = <&grf>;
#clock-cells = <1>;
#reset-cells = <1>;
assigned-clocks = <&cru PLL_CPLL>, <&cru PLL_GPLL>,

View file

@ -6,7 +6,6 @@
/dts-v1/;
#include <dt-bindings/input/input.h>
#include "rk3188.dtsi"
#include "rk3188-radxarock-u-boot.dtsi"
/ {
model = "Radxa Rock";
@ -25,7 +24,7 @@
compatible = "gpio-keys";
autorepeat;
power {
key-power {
gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
linux,code = <KEY_POWER>;
label = "GPIO Key Power";
@ -72,7 +71,7 @@
#sound-dai-cells = <0>;
};
ir_recv: gpio-ir-receiver {
ir_recv: ir-receiver {
compatible = "gpio-ir-receiver";
gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
@ -127,18 +126,21 @@
};
&emac {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&phy_int>;
phy = <&phy0>;
phy-supply = <&vcc_rmii>;
pinctrl-names = "default";
pinctrl-0 = <&emac_xfer>, <&emac_mdio>, <&phy_int>;
status = "okay";
phy0: ethernet-phy@0 {
reg = <0>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PD2 IRQ_TYPE_LEVEL_LOW>;
mdio {
#address-cells = <1>;
#size-cells = <0>;
phy0: ethernet-phy@0 {
reg = <0>;
interrupt-parent = <&gpio3>;
interrupts = <RK_PD2 IRQ_TYPE_LEVEL_LOW>;
};
};
};

View file

@ -12,6 +12,19 @@
&gpio0 {
compatible = "rockchip,gpio-bank";
gpio-ranges = <&pinctrl 0 0 32>;
};
&gpio1 {
gpio-ranges = <&pinctrl 0 32 32>;
};
&gpio2 {
gpio-ranges = <&pinctrl 0 64 32>;
};
&gpio3 {
gpio-ranges = <&pinctrl 0 96 32>;
};
&pmu {

View file

@ -54,7 +54,7 @@
};
};
cpu0_opp_table: opp_table0 {
cpu0_opp_table: opp-table-0 {
compatible = "operating-points-v2";
opp-shared;
@ -195,8 +195,9 @@
cru: clock-controller@20000000 {
compatible = "rockchip,rk3188-cru";
reg = <0x20000000 0x1000>;
clocks = <&xin24m>;
clock-names = "xin24m";
rockchip,grf = <&grf>;
#clock-cells = <1>;
#reset-cells = <1>;
};
@ -223,7 +224,7 @@
#size-cells = <1>;
ranges;
gpio0: gpio0@2000a000 {
gpio0: gpio@2000a000 {
compatible = "rockchip,rk3188-gpio-bank0";
reg = <0x2000a000 0x100>;
interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
@ -236,7 +237,7 @@
#interrupt-cells = <2>;
};
gpio1: gpio1@2003c000 {
gpio1: gpio@2003c000 {
compatible = "rockchip,gpio-bank";
reg = <0x2003c000 0x100>;
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
@ -249,7 +250,7 @@
#interrupt-cells = <2>;
};
gpio2: gpio2@2003e000 {
gpio2: gpio@2003e000 {
compatible = "rockchip,gpio-bank";
reg = <0x2003e000 0x100>;
interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
@ -262,7 +263,7 @@
#interrupt-cells = <2>;
};
gpio3: gpio3@20080000 {
gpio3: gpio@20080000 {
compatible = "rockchip,gpio-bank";
reg = <0x20080000 0x100>;
interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
@ -275,15 +276,15 @@
#interrupt-cells = <2>;
};
pcfg_pull_up: pcfg_pull_up {
pcfg_pull_up: pcfg-pull-up {
bias-pull-up;
};
pcfg_pull_down: pcfg_pull_down {
pcfg_pull_down: pcfg-pull-down {
bias-pull-down;
};
pcfg_pull_none: pcfg_pull_none {
pcfg_pull_none: pcfg-pull-none {
bias-disable;
};
@ -378,7 +379,7 @@
rockchip,pins = <2 RK_PD3 1 &pcfg_pull_none>;
};
lcdc1_rgb24: ldcd1-rgb24 {
lcdc1_rgb24: lcdc1-rgb24 {
rockchip,pins = <2 RK_PA0 1 &pcfg_pull_none>,
<2 RK_PA1 1 &pcfg_pull_none>,
<2 RK_PA2 1 &pcfg_pull_none>,
@ -606,7 +607,6 @@
&global_timer {
interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
status = "disabled";
};
&local_timer {
@ -641,6 +641,11 @@
&grf {
compatible = "rockchip,rk3188-grf", "syscon", "simple-mfd";
io_domains: io-domains {
compatible = "rockchip,rk3188-io-voltage-domain";
status = "disabled";
};
usbphy: usbphy {
compatible = "rockchip,rk3188-usb-phy";
#address-cells = <1>;

View file

@ -18,21 +18,6 @@
clock-output-names = "ext_gmac";
};
io_domains: io-domains {
compatible = "rockchip,rk3288-io-voltage-domain";
rockchip,grf = <&grf>;
audio-supply = <&vcca_33>;
flash0-supply = <&vcc_flash>;
flash1-supply = <&vcc_lan>;
gpio30-supply = <&vcc_io>;
gpio1830-supply = <&vcc_io>;
lcdc-supply = <&vcc_io>;
sdcard-supply = <&vccio_sd>;
wifi-supply = <&vcc_18>;
};
leds {
compatible = "gpio-leds";
@ -277,6 +262,18 @@
status = "okay";
};
&io_domains {
audio-supply = <&vcca_33>;
flash0-supply = <&vcc_flash>;
flash1-supply = <&vcc_lan>;
gpio30-supply = <&vcc_io>;
gpio1830-supply = <&vcc_io>;
lcdc-supply = <&vcc_io>;
sdcard-supply = <&vccio_sd>;
wifi-supply = <&vcc_18>;
status = "okay";
};
&pinctrl {
pcfg_output_high: pcfg-output-high {
output-high;

View file

@ -71,22 +71,6 @@
clock-output-names = "ext_gmac";
};
io_domains: io_domains {
compatible = "rockchip,rk3288-io-voltage-domain";
status = "okay";
sdcard-supply = <&vdd_io_sd>;
flash0-supply = <&vdd_emmc_io>;
flash1-supply = <&vdd_misc_1v8>;
gpio1830-supply = <&vdd_3v3_io>;
gpio30-supply = <&vdd_3v3_io>;
bb-supply = <&vdd_3v3_io>;
dvp-supply = <&vdd_3v3_io>;
lcdc-supply = <&vdd_3v3_io>;
wifi-supply = <&vdd_3v3_io>;
audio-supply = <&vdd_3v3_io>;
};
leds: user-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@ -197,6 +181,20 @@
ddc-i2c-bus = <&i2c5>;
};
&io_domains {
audio-supply = <&vdd_3v3_io>;
bb-supply = <&vdd_3v3_io>;
dvp-supply = <&vdd_3v3_io>;
flash0-supply = <&vdd_emmc_io>;
flash1-supply = <&vdd_misc_1v8>;
gpio1830-supply = <&vdd_3v3_io>;
gpio30-supply = <&vdd_3v3_io>;
lcdc-supply = <&vdd_3v3_io>;
sdcard-supply = <&vdd_io_sd>;
wifi-supply = <&vdd_3v3_io>;
status = "okay";
};
&i2c0 {
status = "okay";
clock-frequency = <400000>;

View file

@ -71,22 +71,6 @@
};
};
io_domains: io-domains {
compatible = "rockchip,rk3288-io-voltage-domain";
rockchip,grf = <&grf>;
audio-supply = <&vcca_33>;
bb-supply = <&vcc_io>;
dvp-supply = <&vcc18_dvp>;
flash0-supply = <&vcc_flash>;
flash1-supply = <&vcc_lan>;
gpio30-supply = <&vcc_io>;
gpio1830-supply = <&vcc_io>;
lcdc-supply = <&vcc_io>;
sdcard-supply = <&vccio_sd>;
wifi-supply = <&vccio_wl>;
};
ir: ir-receiver {
compatible = "gpio-ir-receiver";
gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
@ -443,6 +427,20 @@
status = "okay";
};
&io_domains {
audio-supply = <&vcca_33>;
bb-supply = <&vcc_io>;
dvp-supply = <&vcc18_dvp>;
flash0-supply = <&vcc_flash>;
flash1-supply = <&vcc_lan>;
gpio30-supply = <&vcc_io>;
gpio1830-supply = <&vcc_io>;
lcdc-supply = <&vcc_io>;
sdcard-supply = <&vccio_sd>;
wifi-supply = <&vccio_wl>;
status = "okay";
};
&pinctrl {
ak8963 {
comp_int: comp-int {

View file

@ -91,6 +91,11 @@
bootph-all;
};
&edp {
clocks = <&cru SCLK_EDP>, <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>;
clock-names = "clk_edp", "clk_edp_24m", "pclk_edp";
};
&gpio7 {
bootph-all;
};

View file

@ -198,21 +198,6 @@
/* 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 {
@ -503,6 +488,19 @@
clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>, <&cru SCLK_I2S0_OUT>;
};
&io_domains {
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>;
status = "okay";
};
&wdt {
status = "okay";
};

View file

@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0+
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
@ -7,13 +7,16 @@
#include <dt-bindings/clock/rk3288-cru.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/thermal/thermal.h>
#include <dt-bindings/video/rk3288.h>
#include "skeleton.dtsi"
#include <dt-bindings/soc/rockchip,boot-mode.h>
/ {
#address-cells = <1>;
#size-cells = <1>;
compatible = "rockchip,rk3288";
interrupt-parent = <&gic>;
aliases {
ethernet0 = &gmac;
i2c0 = &i2c0;
@ -672,9 +675,7 @@
#pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pwm0_pin>;
clocks = <&cru PCLK_PWM>;
clock-names = "pwm";
rockchip,grf = <&grf>;
clocks = <&cru PCLK_RKPWM>;
status = "disabled";
};
@ -684,9 +685,7 @@
#pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pwm1_pin>;
clocks = <&cru PCLK_PWM>;
clock-names = "pwm";
rockchip,grf = <&grf>;
clocks = <&cru PCLK_RKPWM>;
status = "disabled";
};
@ -696,21 +695,17 @@
#pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pwm2_pin>;
clocks = <&cru PCLK_PWM>;
clock-names = "pwm";
rockchip,grf = <&grf>;
clocks = <&cru PCLK_RKPWM>;
status = "disabled";
};
pwm3: pwm@ff680030 {
compatible = "rockchip,rk3288-pwm";
reg = <0xff680030 0x10>;
#pwm-cells = <2>;
#pwm-cells = <3>;
pinctrl-names = "default";
pinctrl-0 = <&pwm3_pin>;
clocks = <&cru PCLK_PWM>;
clock-names = "pwm";
rockchip,grf = <&grf>;
clocks = <&cru PCLK_RKPWM>;
status = "disabled";
};
@ -732,8 +727,128 @@
};
pmu: power-management@ff730000 {
compatible = "rockchip,rk3288-pmu", "syscon";
compatible = "rockchip,rk3288-pmu", "syscon", "simple-mfd";
reg = <0xff730000 0x100>;
power: power-controller {
compatible = "rockchip,rk3288-power-controller";
#power-domain-cells = <1>;
#address-cells = <1>;
#size-cells = <0>;
assigned-clocks = <&cru SCLK_EDP_24M>;
assigned-clock-parents = <&xin24m>;
/*
* Note: Although SCLK_* are the working clocks
* of device without including on the NOC, needed for
* synchronous reset.
*
* The clocks on the which NOC:
* ACLK_IEP/ACLK_VIP/ACLK_VOP0 are on ACLK_VIO0_NIU.
* ACLK_ISP/ACLK_VOP1 are on ACLK_VIO1_NIU.
* ACLK_RGA is on ACLK_RGA_NIU.
* The others (HCLK_*,PLCK_*) are on HCLK_VIO_NIU.
*
* Which clock are device clocks:
* clocks devices
* *_IEP IEP:Image Enhancement Processor
* *_ISP ISP:Image Signal Processing
* *_VIP VIP:Video Input Processor
* *_VOP* VOP:Visual Output Processor
* *_RGA RGA
* *_EDP* EDP
* *_LVDS_* LVDS
* *_HDMI HDMI
* *_MIPI_* MIPI
*/
power-domain@RK3288_PD_VIO {
reg = <RK3288_PD_VIO>;
clocks = <&cru ACLK_IEP>,
<&cru ACLK_ISP>,
<&cru ACLK_RGA>,
<&cru ACLK_VIP>,
<&cru ACLK_VOP0>,
<&cru ACLK_VOP1>,
<&cru DCLK_VOP0>,
<&cru DCLK_VOP1>,
<&cru HCLK_IEP>,
<&cru HCLK_ISP>,
<&cru HCLK_RGA>,
<&cru HCLK_VIP>,
<&cru HCLK_VOP0>,
<&cru HCLK_VOP1>,
<&cru PCLK_EDP_CTRL>,
<&cru PCLK_HDMI_CTRL>,
<&cru PCLK_LVDS_PHY>,
<&cru PCLK_MIPI_CSI>,
<&cru PCLK_MIPI_DSI0>,
<&cru PCLK_MIPI_DSI1>,
<&cru SCLK_EDP_24M>,
<&cru SCLK_EDP>,
<&cru SCLK_ISP_JPE>,
<&cru SCLK_ISP>,
<&cru SCLK_RGA>;
pm_qos = <&qos_vio0_iep>,
<&qos_vio1_vop>,
<&qos_vio1_isp_w0>,
<&qos_vio1_isp_w1>,
<&qos_vio0_vop>,
<&qos_vio0_vip>,
<&qos_vio2_rga_r>,
<&qos_vio2_rga_w>,
<&qos_vio1_isp_r>;
#power-domain-cells = <0>;
};
/*
* Note: The following 3 are HEVC(H.265) clocks,
* and on the ACLK_HEVC_NIU (NOC).
*/
power-domain@RK3288_PD_HEVC {
reg = <RK3288_PD_HEVC>;
clocks = <&cru ACLK_HEVC>,
<&cru SCLK_HEVC_CABAC>,
<&cru SCLK_HEVC_CORE>;
pm_qos = <&qos_hevc_r>,
<&qos_hevc_w>;
#power-domain-cells = <0>;
};
/*
* Note: ACLK_VCODEC/HCLK_VCODEC are VCODEC
* (video endecoder & decoder) clocks that on the
* ACLK_VCODEC_NIU and HCLK_VCODEC_NIU (NOC).
*/
power-domain@RK3288_PD_VIDEO {
reg = <RK3288_PD_VIDEO>;
clocks = <&cru ACLK_VCODEC>,
<&cru HCLK_VCODEC>;
pm_qos = <&qos_video>;
#power-domain-cells = <0>;
};
/*
* Note: ACLK_GPU is the GPU clock,
* and on the ACLK_GPU_NIU (NOC).
*/
power-domain@RK3288_PD_GPU {
reg = <RK3288_PD_GPU>;
clocks = <&cru ACLK_GPU>;
pm_qos = <&qos_gpu_r>,
<&qos_gpu_w>;
#power-domain-cells = <0>;
};
};
reboot-mode {
compatible = "syscon-reboot-mode";
offset = <0x94>;
mode-normal = <BOOT_NORMAL>;
mode-recovery = <BOOT_RECOVERY>;
mode-bootloader = <BOOT_FASTBOOT>;
mode-loader = <BOOT_BL_DOWNLOAD>;
};
};
sgrf: syscon@ff740000 {
@ -760,8 +875,58 @@
};
grf: syscon@ff770000 {
compatible = "rockchip,rk3288-grf", "syscon";
compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd";
reg = <0xff770000 0x1000>;
edp_phy: edp-phy {
compatible = "rockchip,rk3288-dp-phy";
clocks = <&cru SCLK_EDP_24M>;
clock-names = "24m";
#phy-cells = <0>;
status = "disabled";
};
io_domains: io-domains {
compatible = "rockchip,rk3288-io-voltage-domain";
status = "disabled";
};
usbphy: usbphy {
compatible = "rockchip,rk3288-usb-phy";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
usbphy0: usb-phy@320 {
#phy-cells = <0>;
reg = <0x320>;
clocks = <&cru SCLK_OTGPHY0>;
clock-names = "phyclk";
#clock-cells = <0>;
resets = <&cru SRST_USBOTG_PHY>;
reset-names = "phy-reset";
};
usbphy1: usb-phy@334 {
#phy-cells = <0>;
reg = <0x334>;
clocks = <&cru SCLK_OTGPHY1>;
clock-names = "phyclk";
#clock-cells = <0>;
resets = <&cru SRST_USBHOST0_PHY>;
reset-names = "phy-reset";
};
usbphy2: usb-phy@348 {
#phy-cells = <0>;
reg = <0x348>;
clocks = <&cru SCLK_OTGPHY2>;
clock-names = "phyclk";
#clock-cells = <0>;
resets = <&cru SRST_USBHOST1_PHY>;
reset-names = "phy-reset";
};
};
};
wdt: watchdog@ff800000 {
@ -848,7 +1013,7 @@
vopb: vop@ff930000 {
compatible = "rockchip,rk3288-vop";
reg = <0xff930000 0x19c>;
reg = <0xff930000 0x19c>, <0xff931000 0x1000>;
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>;
clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
@ -862,25 +1027,25 @@
#address-cells = <1>;
#size-cells = <0>;
vopb_out_edp: endpoint@0 {
vopb_out_hdmi: endpoint@0 {
reg = <0>;
remote-endpoint = <&edp_in_vopb>;
};
vopb_out_hdmi: endpoint@1 {
reg = <1>;
remote-endpoint = <&hdmi_in_vopb>;
};
vopb_out_lvds: endpoint@2 {
reg = <2>;
remote-endpoint = <&lvds_in_vopb>;
vopb_out_edp: endpoint@1 {
reg = <1>;
remote-endpoint = <&edp_in_vopb>;
};
vopb_out_mipi: endpoint@3 {
reg = <3>;
vopb_out_mipi: endpoint@2 {
reg = <2>;
remote-endpoint = <&mipi_in_vopb>;
};
vopb_out_lvds: endpoint@3 {
reg = <3>;
remote-endpoint = <&lvds_in_vopb>;
};
};
};
@ -897,7 +1062,7 @@
vopl: vop@ff940000 {
compatible = "rockchip,rk3288-vop";
reg = <0xff940000 0x19c>;
reg = <0xff940000 0x19c>, <0xff941000 0x1000>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>;
clock-names = "aclk_vop", "dclk_vop", "hclk_vop";
@ -911,25 +1076,25 @@
#address-cells = <1>;
#size-cells = <0>;
vopl_out_edp: endpoint@0 {
vopl_out_hdmi: endpoint@0 {
reg = <0>;
remote-endpoint = <&edp_in_vopl>;
};
vopl_out_hdmi: endpoint@1 {
reg = <1>;
remote-endpoint = <&hdmi_in_vopl>;
};
vopl_out_lvds: endpoint@2 {
reg = <2>;
remote-endpoint = <&lvds_in_vopl>;
vopl_out_edp: endpoint@1 {
reg = <1>;
remote-endpoint = <&edp_in_vopl>;
};
vopl_out_mipi: endpoint@3 {
reg = <3>;
vopl_out_mipi: endpoint@2 {
reg = <2>;
remote-endpoint = <&mipi_in_vopl>;
};
vopl_out_lvds: endpoint@3 {
reg = <3>;
remote-endpoint = <&lvds_in_vopl>;
};
};
};
@ -945,11 +1110,11 @@
};
mipi_dsi: mipi@ff960000 {
compatible = "rockchip,rk3288_mipi_dsi";
compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi";
reg = <0xff960000 0x4000>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_MIPI_DSI0>;
clock-names = "pclk_mipi";
clocks = <&cru SCLK_MIPIDSI_24M>, <&cru PCLK_MIPI_DSI0>;
clock-names = "ref", "pclk";
power-domains = <&power RK3288_PD_VIO>;
rockchip,grf = <&grf>;
status = "disabled";
@ -975,7 +1140,7 @@
reg = <0xff96c000 0x4000>;
clocks = <&cru PCLK_LVDS_PHY>;
clock-names = "pclk_lvds";
pinctrl-names = "default";
pinctrl-names = "lcdc";
pinctrl-0 = <&lcdc_ctl>;
power-domains = <&power RK3288_PD_VIO>;
rockchip,grf = <&grf>;
@ -1004,19 +1169,24 @@
};
edp: dp@ff970000 {
compatible = "rockchip,rk3288-edp";
compatible = "rockchip,rk3288-dp";
reg = <0xff970000 0x4000>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_EDP>, <&cru SCLK_EDP_24M>, <&cru PCLK_EDP_CTRL>;
clock-names = "clk_edp", "clk_edp_24m", "pclk_edp";
resets = <&cru SRST_EDP>;
reset-names = "edp";
rockchip,grf = <&grf>;
clocks = <&cru SCLK_EDP>, <&cru PCLK_EDP_CTRL>;
clock-names = "dp", "pclk";
phys = <&edp_phy>;
phy-names = "dp";
power-domains = <&power RK3288_PD_VIO>;
resets = <&cru SRST_EDP>;
reset-names = "dp";
rockchip,grf = <&grf>;
status = "disabled";
ports {
edp_in: port {
#address-cells = <1>;
#size-cells = <0>;
edp_in: port@0 {
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
edp_in_vopb: endpoint@0 {
@ -1038,8 +1208,8 @@
#sound-dai-cells = <0>;
rockchip,grf = <&grf>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>;
clock-names = "iahb", "isfr";
clocks = <&cru PCLK_HDMI_CTRL>, <&cru SCLK_HDMI_HDCP>, <&cru SCLK_HDMI_CEC>;
clock-names = "iahb", "isfr", "cec";
power-domains = <&power RK3288_PD_VIO>;
status = "disabled";
@ -1241,39 +1411,6 @@
interrupts = <GIC_PPI 9 0xf04>;
};
cpuidle: cpuidle {
compatible = "rockchip,rk3288-cpuidle";
};
usbphy: phy {
compatible = "rockchip,rk3288-usb-phy";
rockchip,grf = <&grf>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
usbphy0: usb-phy0 {
#phy-cells = <0>;
reg = <0x320>;
clocks = <&cru SCLK_OTGPHY0>;
clock-names = "phyclk";
};
usbphy1: usb-phy1 {
#phy-cells = <0>;
reg = <0x334>;
clocks = <&cru SCLK_OTGPHY1>;
clock-names = "phyclk";
};
usbphy2: usb-phy2 {
#phy-cells = <0>;
reg = <0x348>;
clocks = <&cru SCLK_OTGPHY2>;
clock-names = "phyclk";
};
};
pinctrl: pinctrl {
compatible = "rockchip,rk3288-pinctrl";
rockchip,grf = <&grf>;
@ -1860,62 +1997,4 @@
};
};
};
power: power-controller {
compatible = "rockchip,rk3288-power-controller";
#power-domain-cells = <1>;
rockchip,pmu = <&pmu>;
#address-cells = <1>;
#size-cells = <0>;
pd_gpu {
reg = <RK3288_PD_GPU>;
clocks = <&cru ACLK_GPU>;
};
pd_hevc {
reg = <RK3288_PD_HEVC>;
clocks = <&cru ACLK_HEVC>,
<&cru SCLK_HEVC_CABAC>,
<&cru SCLK_HEVC_CORE>,
<&cru HCLK_HEVC>;
};
pd_vio {
reg = <RK3288_PD_VIO>;
clocks = <&cru ACLK_IEP>,
<&cru ACLK_ISP>,
<&cru ACLK_RGA>,
<&cru ACLK_VIP>,
<&cru ACLK_VOP0>,
<&cru ACLK_VOP1>,
<&cru DCLK_VOP0>,
<&cru DCLK_VOP1>,
<&cru HCLK_IEP>,
<&cru HCLK_ISP>,
<&cru HCLK_RGA>,
<&cru HCLK_VIP>,
<&cru HCLK_VOP0>,
<&cru HCLK_VOP1>,
<&cru PCLK_EDP_CTRL>,
<&cru PCLK_HDMI_CTRL>,
<&cru PCLK_LVDS_PHY>,
<&cru PCLK_MIPI_CSI>,
<&cru PCLK_MIPI_DSI0>,
<&cru PCLK_MIPI_DSI1>,
<&cru SCLK_EDP_24M>,
<&cru SCLK_EDP>,
<&cru SCLK_HDMI_CEC>,
<&cru SCLK_HDMI_HDCP>,
<&cru SCLK_ISP_JPE>,
<&cru SCLK_ISP>,
<&cru SCLK_RGA>;
};
pd_video {
reg = <RK3288_PD_VIDEO>;
clocks = <&cru ACLK_VCODEC>,
<&cru HCLK_VCODEC>;
};
};
};

View file

@ -16,3 +16,7 @@
bootph-all;
status = "okay";
};
&vcc5v0_usb30 {
regulator-boot-on;
};

View file

@ -13,6 +13,14 @@
};
};
&sdhci {
cap-mmc-highspeed;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
};
&sdmmc2 {
status = "disabled";
};
@ -26,3 +34,11 @@
bootph-all;
status = "okay";
};
&vcc5v0_usb_host {
regulator-boot-on;
};
&vcc5v0_usb_hub {
regulator-boot-on;
};

View file

@ -18,7 +18,5 @@
&sdmmc {
bus-width = <4>;
bootph-all;
u-boot,spl-fifo-mode;
status = "okay";
};

View file

@ -0,0 +1,21 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
*/
#include "rk3588-u-boot.dtsi"
/ {
aliases {
mmc0 = &sdmmc;
mmc1 = &sdhci;
};
chosen {
u-boot,spl-boot-order = &sdhci;
};
};
&sdhci {
bootph-all;
};

View file

@ -0,0 +1,129 @@
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
*
*/
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
#include "rk3588.dtsi"
/ {
model = "Rockchip RK3588 EVB1 V10 Board";
compatible = "rockchip,rk3588-evb1-v10", "rockchip,rk3588";
aliases {
mmc0 = &sdhci;
serial2 = &uart2;
};
chosen {
stdout-path = "serial2:1500000n8";
};
backlight: backlight {
compatible = "pwm-backlight";
power-supply = <&vcc12v_dcin>;
pwms = <&pwm2 0 25000 0>;
};
vcc12v_dcin: vcc12v-dcin-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <12000000>;
regulator-max-microvolt = <12000000>;
};
vcc5v0_sys: vcc5v0-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
regulator-boot-on;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
vin-supply = <&vcc12v_dcin>;
};
};
&gmac0 {
clock_in_out = "output";
phy-handle = <&rgmii_phy>;
phy-mode = "rgmii-rxid";
pinctrl-0 = <&gmac0_miim
&gmac0_tx_bus2
&gmac0_rx_bus2
&gmac0_rgmii_clk
&gmac0_rgmii_bus>;
pinctrl-names = "default";
rx_delay = <0x00>;
tx_delay = <0x43>;
status = "okay";
};
&i2c2 {
status = "okay";
hym8563: rtc@51 {
compatible = "haoyu,hym8563";
reg = <0x51>;
#clock-cells = <0>;
clock-output-names = "hym8563";
pinctrl-names = "default";
pinctrl-0 = <&hym8563_int>;
interrupt-parent = <&gpio0>;
interrupts = <RK_PD4 IRQ_TYPE_LEVEL_LOW>;
wakeup-source;
};
};
&mdio0 {
rgmii_phy: ethernet-phy@1 {
/* RTL8211F */
compatible = "ethernet-phy-id001c.c916";
reg = <0x1>;
pinctrl-names = "default";
pinctrl-0 = <&rtl8211f_rst>;
reset-assert-us = <20000>;
reset-deassert-us = <100000>;
reset-gpios = <&gpio4 RK_PB3 GPIO_ACTIVE_LOW>;
};
};
&pinctrl {
rtl8211f {
rtl8211f_rst: rtl8211f-rst {
rockchip,pins = <4 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
hym8563 {
hym8563_int: hym8563-int {
rockchip,pins = <0 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
};
};
};
&pwm2 {
status = "okay";
};
&sdhci {
bus-width = <8>;
no-sdio;
no-sd;
non-removable;
max-frequency = <200000000>;
mmc-hs400-1_8v;
mmc-hs400-enhanced-strobe;
status = "okay";
};
&uart2 {
pinctrl-0 = <&uart2m0_xfer>;
status = "okay";
};

View file

@ -7,16 +7,23 @@
/ {
aliases {
mmc0 = &sdmmc;
mmc1 = &sdmmc;
};
chosen {
u-boot,spl-boot-order = &sdmmc;
u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdhci;
};
};
&sdmmc {
bus-width = <4>;
bootph-pre-ram;
status = "okay";
};
&sdhci {
cap-mmc-highspeed;
mmc-ddr-1_8v;
mmc-hs200-1_8v;
pinctrl-names = "default";
pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_data_strobe &emmc_rstnout>;
};

View file

@ -18,20 +18,6 @@
reg = <0x0 0xfd58a000 0x0 0x2000>;
};
sdmmc: mmc@fe2c0000 {
compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x0 0xfe2c0000 0x0 0x4000>;
interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>,
<&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>;
clock-names = "ciu-drive", "ciu-sample", "biu", "ciu";
fifo-depth = <0x100>;
max-frequency = <200000000>;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
status = "disabled";
};
otp: nvmem@fecc0000 {
compatible = "rockchip,rk3588-otp";
reg = <0x0 0xfecc0000 0x0 0x400>;
@ -43,6 +29,12 @@
reg = <0x07 0x10>;
};
};
rng: rng@fe378000 {
compatible = "rockchip,trngv1";
reg = <0x0 0xfe378000 0x0 0x200>;
status = "disabled";
};
};
&xin24m {
@ -60,6 +52,23 @@
status = "okay";
};
&scmi {
bootph-pre-ram;
};
&scmi_clk {
bootph-pre-ram;
};
&sdmmc {
bootph-pre-ram;
u-boot,spl-fifo-mode;
};
&sdhci {
bootph-pre-ram;
};
&uart2 {
clock-frequency = <24000000>;
bootph-pre-ram;

View file

@ -1099,6 +1099,21 @@
};
};
sdmmc: mmc@fe2c0000 {
compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc";
reg = <0x0 0xfe2c0000 0x0 0x4000>;
interrupts = <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH 0>;
clocks = <&scmi_clk SCMI_HCLK_SD>, <&scmi_clk SCMI_CCLK_SD>,
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
fifo-depth = <0x100>;
max-frequency = <200000000>;
pinctrl-names = "default";
pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_det &sdmmc_bus4>;
power-domains = <&power RK3588_PD_SDMMC>;
status = "disabled";
};
sdhci: mmc@fe2e0000 {
compatible = "rockchip,rk3588-dwcmshc";
reg = <0x0 0xfe2e0000 0x0 0x10000>;

View file

@ -33,3 +33,7 @@
&uart2 {
clock-frequency = <24000000>;
};
&xin24m {
bootph-all;
};

View file

@ -76,6 +76,13 @@
reg = <0x1013c200 0x20>;
interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
clocks = <&cru CORE_PERI>;
status = "disabled";
/* The clock source and the sched_clock provided by the arm_global_timer
* on Rockchip rk3066a/rk3188 are quite unstable because their rates
* depend on the CPU frequency.
* Keep the arm_global_timer disabled in order to have the
* DW_APB_TIMER (rk3066a) or ROCKCHIP_TIMER (rk3188) selected by default.
*/
};
local_timer: local-timer@1013c600 {
@ -186,8 +193,6 @@
compatible = "snps,arc-emac";
reg = <0x10204000 0x3c>;
interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
rockchip,grf = <&grf>;

View file

@ -194,6 +194,5 @@ int rockchip_get_clk(struct udevice **devp);
* Return: 0 success, or error value
*/
int rockchip_reset_bind(struct udevice *pdev, u32 reg_offset, u32 reg_number);
int rockchip_get_scmi_clk(struct udevice **devp);
#endif

View file

@ -11,12 +11,12 @@
#define KHz 1000
#define OSC_HZ (24 * MHz)
#define CPU_PVTPLL_HZ (1008 * MHz)
#define LPLL_HZ (816 * MHz)
#define GPLL_HZ (1188 * MHz)
#define CPLL_HZ (1500 * MHz)
#define NPLL_HZ (850 * MHz)
#define PPLL_HZ (1100 * MHz)
#define SPLL_HZ (702 * MHz)
/* RK3588 pll id */
enum rk3588_pll_id {
@ -447,5 +447,22 @@ enum {
CLK_I2C0_SEL_MASK = 1 << CLK_I2C0_SEL_SHIFT,
CLK_I2C_SEL_200M = 0,
CLK_I2C_SEL_100M,
/* SECURECRU_CLKSEL_CON01 */
SCMI_HCLK_SD_SEL_SHIFT = 2,
SCMI_HCLK_SD_SEL_MASK = 3 << SCMI_HCLK_SD_SEL_SHIFT,
SCMI_HCLK_SD_SEL_150M = 0,
SCMI_HCLK_SD_SEL_100M,
SCMI_HCLK_SD_SEL_50M,
SCMI_HCLK_SD_SEL_24M,
/* SECURECRU_CLKSEL_CON03 */
SCMI_CCLK_SD_SEL_SHIFT = 12,
SCMI_CCLK_SD_SEL_MASK = 3 << SCMI_CCLK_SD_SEL_SHIFT,
SCMI_CCLK_SD_SEL_GPLL = 0,
SCMI_CCLK_SD_SEL_SPLL,
SCMI_CCLK_SD_SEL_24M,
SCMI_CCLK_SD_DIV_SHIFT = 6,
SCMI_CCLK_SD_DIV_MASK = 0x3f << SCMI_CCLK_SD_DIV_SHIFT,
};
#endif

View file

@ -119,7 +119,7 @@ config ROCKCHIP_RK322X
config ROCKCHIP_RK3288
bool "Support Rockchip RK3288"
select CPU_V7A
select OF_BOARD_SETUP
select OF_SYSTEM_SETUP
select SKIP_LOWLEVEL_INIT_ONLY
select SUPPORT_SPL
select SPL
@ -288,7 +288,9 @@ config ROCKCHIP_RK3568
select BOARD_LATE_INIT
select DM_REGULATOR_FIXED
select DM_RESET
imply SPL_ATF_NO_PLATFORM_PARAM if SPL_ATF
imply ROCKCHIP_COMMON_BOARD
imply OF_LIBFDT_OVERLAY
imply ROCKCHIP_OTP
imply MISC_INIT_R
help
@ -309,9 +311,13 @@ config ROCKCHIP_RK3588
select REGMAP
select SYSCON
select BOARD_LATE_INIT
imply SPL_ATF_NO_PLATFORM_PARAM if SPL_ATF
imply ROCKCHIP_COMMON_BOARD
imply OF_LIBFDT_OVERLAY
imply ROCKCHIP_OTP
imply MISC_INIT_R
imply CLK_SCMI
imply SCMI_FIRMWARE
help
The Rockchip RK3588 is a ARM-based SoC with quad-core Cortex-A76 and
quad-core Cortex-A55 including NEON and GPU, 6TOPS NPU, Mali-G610 MP4,
@ -428,7 +434,7 @@ config TPL_ROCKCHIP_COMMON_BOARD
config ROCKCHIP_EXTERNAL_TPL
bool "Use external TPL binary"
default y if ROCKCHIP_RK3568
default y if ROCKCHIP_RK3568 || ROCKCHIP_RK3588
help
Some Rockchip SoCs require an external TPL to initialize DRAM.
Enable this option and build with ROCKCHIP_TPL=/path/to/ddr.bin to

View file

@ -83,7 +83,7 @@ int rockchip_cpuid_from_efuse(const u32 cpuid_offset,
/* read the cpu_id range from the efuses */
ret = misc_read(dev, cpuid_offset, cpuid, cpuid_length);
if (ret) {
if (ret < 0) {
debug("%s: reading cpuid from the efuses failed\n",
__func__);
return -1;

View file

@ -138,7 +138,7 @@ static int ft_rk3288w_setup(void *blob)
return ret;
}
int ft_board_setup(void *blob, struct bd_info *bd)
int ft_system_setup(void *blob, struct bd_info *bd)
{
if (soc_is_rk3288w())
return ft_rk3288w_setup(blob);

View file

@ -1,5 +1,11 @@
if ROCKCHIP_RK3588
config TARGET_EVB_RK3588
bool "Rockchip EVB1 v10"
select BOARD_LATE_INIT
help
RK3588 EVB is a evaluation board for Rockchp RK3588.
config TARGET_RK3588_NEU6
bool "Edgeble Neural Compute Module 6(Neu6) SoM"
select BOARD_LATE_INIT
@ -51,6 +57,7 @@ config SYS_MALLOC_F_LEN
default 0x80000
source board/edgeble/neural-compute-module-6/Kconfig
source board/rockchip/evb_rk3588/Kconfig
source board/radxa/rock5b-rk3588/Kconfig
endif

View file

@ -0,0 +1,15 @@
if TARGET_EVB_RK3588
config SYS_BOARD
default "evb_rk3588"
config SYS_VENDOR
default "rockchip"
config SYS_CONFIG_NAME
default "evb_rk3588"
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
endif

View file

@ -0,0 +1,7 @@
EVB-RK3588
M: Kever Yang <kever.yang@rock-chips.com>
S: Maintained
F: board/rockchip/evb_rk3588
F: include/configs/evb_rk3588.h
F: configs/evb-rk3588_defconfig
F: arch/arm/dts/rk3588-evb-u-boot.dtsi

View file

@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (c) 2023 Rockchip Electronics Co,. Ltd.
#
obj-y += evb-rk3588.o

View file

@ -0,0 +1,39 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2023 Rockchip Electronics Co,. Ltd.
*/
#include <fdtdec.h>
#include <fdt_support.h>
#ifdef CONFIG_OF_BOARD_SETUP
static int rk3588_add_reserved_memory_fdt_nodes(void *new_blob)
{
struct fdt_memory gap1 = {
.start = 0x3fc000000,
.end = 0x3fc4fffff,
};
struct fdt_memory gap2 = {
.start = 0x3fff00000,
.end = 0x3ffffffff,
};
unsigned long flags = FDTDEC_RESERVED_MEMORY_NO_MAP;
unsigned int ret;
/*
* Inject the reserved-memory nodes into the DTS
*/
ret = fdtdec_add_reserved_memory(new_blob, "gap1", &gap1, NULL, 0,
NULL, flags);
if (ret)
return ret;
return fdtdec_add_reserved_memory(new_blob, "gap2", &gap2, NULL, 0,
NULL, flags);
}
int ft_board_setup(void *blob, struct bd_info *bd)
{
return rk3588_add_reserved_memory_fdt_nodes(blob);
}
#endif

View file

@ -11,6 +11,7 @@ config SYS_CONFIG_NAME
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select ENV_IS_NOWHERE
config ENV_SIZE
default 0x4000

View file

@ -136,10 +136,6 @@ int mmc_get_env_dev(void)
return CONFIG_SYS_MMC_ENV_DEV;
}
#if !IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
#error Please enable CONFIG_ENV_IS_NOWHERE
#endif
enum env_location arch_env_get_location(enum env_operation op, int prio)
{
const char *boot_device =

View file

@ -11,6 +11,7 @@ config SYS_CONFIG_NAME
config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select ENV_IS_NOWHERE
config ENV_SIZE
default 0x3000

View file

@ -118,10 +118,6 @@ int mmc_get_env_dev(void)
return CONFIG_SYS_MMC_ENV_DEV;
}
#if !IS_ENABLED(CONFIG_ENV_IS_NOWHERE)
#error Please enable CONFIG_ENV_IS_NOWHERE
#endif
enum env_location arch_env_get_location(enum env_operation op, int prio)
{
const char *boot_device =

View file

@ -0,0 +1,69 @@
CONFIG_ARM=y
CONFIG_SKIP_LOWLEVEL_INIT=y
CONFIG_COUNTER_FREQUENCY=24000000
CONFIG_ARCH_ROCKCHIP=y
CONFIG_TEXT_BASE=0x00a00000
CONFIG_SPL_LIBCOMMON_SUPPORT=y
CONFIG_SPL_LIBGENERIC_SUPPORT=y
CONFIG_NR_DRAM_BANKS=2
CONFIG_HAS_CUSTOM_SYS_INIT_SP_ADDR=y
CONFIG_CUSTOM_SYS_INIT_SP_ADDR=0xc00000
CONFIG_DEFAULT_DEVICE_TREE="rk3588-evb1-v10"
CONFIG_DM_RESET=y
CONFIG_ROCKCHIP_RK3588=y
CONFIG_SPL_ROCKCHIP_COMMON_BOARD=y
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
CONFIG_SPL_STACK_R_ADDR=0x600000
CONFIG_TARGET_EVB_RK3588=y
CONFIG_SPL_STACK=0x400000
CONFIG_DEBUG_UART_BASE=0xFEB50000
CONFIG_DEBUG_UART_CLOCK=24000000
CONFIG_SYS_LOAD_ADDR=0xc00800
CONFIG_DEBUG_UART=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_SPL_LOAD_FIT=y
CONFIG_OF_BOARD_SETUP=y
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3588-evb1-v10.dtb"
# CONFIG_DISPLAY_CPUINFO is not set
CONFIG_DISPLAY_BOARDINFO_LATE=y
CONFIG_SPL_MAX_SIZE=0x20000
CONFIG_SPL_PAD_TO=0x7f8000
CONFIG_SPL_HAS_BSS_LINKER_SECTION=y
CONFIG_SPL_BSS_START_ADDR=0x4000000
CONFIG_SPL_BSS_MAX_SIZE=0x4000
# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set
# CONFIG_SPL_SHARES_INIT_SP_ADDR is not set
CONFIG_SPL_STACK_R=y
CONFIG_SPL_ATF=y
CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
# CONFIG_CMD_SETEXPR is not set
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_NET_RANDOM_ETHADDR=y
CONFIG_SPL_REGMAP=y
CONFIG_SPL_SYSCON=y
CONFIG_SPL_CLK=y
CONFIG_ROCKCHIP_GPIO=y
CONFIG_SYS_I2C_ROCKCHIP=y
CONFIG_MISC=y
CONFIG_SUPPORT_EMMC_RPMB=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
CONFIG_REGULATOR_PWM=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_SPL_RAM=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_DEBUG_UART_ANNOUNCE=y
CONFIG_SYSRESET=y
CONFIG_ERRNO_STR=y

View file

@ -18,7 +18,7 @@ CONFIG_SPL_TEXT_BASE=0x60000000
CONFIG_DM_RESET=y
CONFIG_ROCKCHIP_RK3066=y
# CONFIG_ROCKCHIP_STIMER is not set
CONFIG_TPL_TEXT_BASE=0x10080C04
CONFIG_TPL_TEXT_BASE=0x10080c00
CONFIG_TPL_STACK=0x1008FFFF
CONFIG_TARGET_MK808=y
CONFIG_SPL_STACK_R_ADDR=0x70000000
@ -53,6 +53,9 @@ CONFIG_SYS_PBSIZE=276
# CONFIG_BOOTM_VXWORKS is not set
CONFIG_CMD_GPT=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
CONFIG_CMD_ROCKUSB=y
CONFIG_CMD_USB_MASS_STORAGE=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_CACHE=y
CONFIG_CMD_TIME=y
@ -78,6 +81,7 @@ CONFIG_TPL_SYSCON=y
CONFIG_CLK=y
CONFIG_SPL_CLK=y
CONFIG_TPL_CLK=y
CONFIG_FASTBOOT_BUF_ADDR=0x80000000
CONFIG_ROCKCHIP_GPIO=y
# CONFIG_SPL_DM_I2C is not set
CONFIG_LED=y
@ -106,6 +110,12 @@ CONFIG_TIMER=y
CONFIG_SPL_TIMER=y
CONFIG_TPL_TIMER=y
CONFIG_DESIGNWARE_APB_TIMER=y
CONFIG_USB=y
CONFIG_USB_DWC2=y
CONFIG_ROCKCHIP_USB2_PHY=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DWC2_OTG=y
CONFIG_USB_FUNCTION_ROCKUSB=y
CONFIG_SPL_TINY_MEMSET=y
CONFIG_ERRNO_STR=y
# CONFIG_TPL_OF_LIBFDT is not set

View file

@ -62,5 +62,4 @@ CONFIG_SPL_RAM=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYSRESET=y
# CONFIG_BINMAN_FDT is not set
CONFIG_ERRNO_STR=y

View file

@ -55,7 +55,6 @@ CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_ENV_IS_IN_SPI_FLASH=y
CONFIG_ENV_SPI_MAX_HZ=50000000

View file

@ -37,9 +37,12 @@ CONFIG_SPL_BSS_MAX_SIZE=0x4000
CONFIG_SPL_STACK_R=y
CONFIG_SPL_ATF=y
CONFIG_CMD_GPT=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
@ -60,8 +63,9 @@ CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
CONFIG_REGULATOR_PWM=y
CONFIG_DM_REGULATOR_GPIO=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_RK8XX=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_SPL_RAM=y
CONFIG_BAUDRATE=1500000
@ -73,5 +77,4 @@ CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_USB_DWC3_GENERIC=y
CONFIG_ERRNO_STR=y

View file

@ -68,7 +68,6 @@ CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
CONFIG_OF_SPL_REMOVE_PROPS="interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents"
CONFIG_ENV_OVERWRITE=y
CONFIG_ENV_IS_NOWHERE=y
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
CONFIG_SPL_DM_SEQ_ALIAS=y

View file

@ -39,7 +39,10 @@ CONFIG_SPL_ATF=y
CONFIG_CMD_GPT=y
CONFIG_CMD_I2C=y
CONFIG_CMD_MMC=y
CONFIG_CMD_USB=y
# CONFIG_CMD_SETEXPR is not set
CONFIG_CMD_PMIC=y
CONFIG_CMD_REGULATOR=y
# CONFIG_SPL_DOS_PARTITION is not set
CONFIG_SPL_OF_CONTROL=y
CONFIG_OF_LIVE=y
@ -58,10 +61,11 @@ CONFIG_MMC_SDHCI_SDMA=y
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_RK8XX=y
CONFIG_SPL_PMIC_RK8XX=y
CONFIG_REGULATOR_PWM=y
CONFIG_REGULATOR_RK8XX=y
CONFIG_PWM_ROCKCHIP=y
CONFIG_SPL_RAM=y
@ -69,5 +73,12 @@ CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_SYS_NS16550_MEM32=y
CONFIG_SYSRESET=y
# CONFIG_BINMAN_FDT is not set
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_GENERIC=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_OHCI_GENERIC=y
CONFIG_USB_DWC3=y
CONFIG_ERRNO_STR=y

View file

@ -58,6 +58,7 @@ CONFIG_MMC_DW=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_SDMA=y
# CONFIG_SPL_MMC_SDHCI_SDMA is not set
CONFIG_MMC_SDHCI_ROCKCHIP=y
CONFIG_ETH_DESIGNWARE=y
CONFIG_GMAC_ROCKCHIP=y
@ -66,7 +67,5 @@ CONFIG_PWM_ROCKCHIP=y
CONFIG_SPL_RAM=y
CONFIG_BAUDRATE=1500000
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_DEBUG_UART_ANNOUNCE=y
CONFIG_SYSRESET=y
# CONFIG_BINMAN_FDT is not set
CONFIG_ERRNO_STR=y

View file

@ -91,6 +91,7 @@ List of mainline supported Rockchip boards:
- Rockchip Evb-RK3568 (evb-rk3568)
* rk3588
- Rockchip EVB (evb-rk3588)
- Edgeble Neural Compute Module 6 SoM - Neu6a (neu6a-io-rk3588)
- Radxa ROCK 5B (rock5b-rk3588)
@ -185,6 +186,15 @@ To build rk3568 boards:
make evb-rk3568_defconfig
make CROSS_COMPILE=aarch64-linux-gnu-
To build rk3588 boards:
.. code-block:: bash
export BL31=../rkbin/bin/rk35/rk3588_bl31_v1.33.elf
export ROCKCHIP_TPL=../rkbin/bin/rk35/rk3588_ddr_lp4_2112MHz_lp5_2736MHz_v1.09.bin
make evb-rk3588_defconfig
make CROSS_COMPILE=aarch64-linux-gnu-
Flashing
--------
@ -380,9 +390,8 @@ Program with commands in a bash script ./flash.sh:
#!/bin/sh
printf "RK30" > tplspl.bin
dd if=u-boot-tpl.bin >> tplspl.bin
truncate -s %2048 tplspl.bin
printf "RK30" | dd conv=notrunc bs=4 count=1 of=u-boot-tpl.bin
truncate -s %2048 u-boot-tpl.bin
truncate -s %2048 u-boot-spl.bin
../tools/boot_merger --verbose config-flash.ini
../tools/upgrade_tool ul ./RK30xxLoader_uboot.bin
@ -406,7 +415,7 @@ config-flash.ini:
NUM=2
LOADER1=FlashData
LOADER2=FlashBoot
FlashData=tplspl.bin
FlashData=u-boot-tpl.bin
FlashBoot=u-boot-spl.bin
[OUTPUT]
PATH=RK30xxLoader_uboot.bin

View file

@ -166,6 +166,14 @@ config CLK_SCMI
by a SCMI agent based on SCMI clock protocol communication
with a SCMI server.
config SPL_CLK_SCMI
bool "Enable SCMI clock driver in SPL"
depends on SCMI_FIRMWARE && SPL_FIRMWARE
help
Enable this option if you want to support clock devices exposed
by a SCMI agent based on SCMI clock protocol communication
with a SCMI server in SPL.
config CLK_HSDK
bool "Enable cgu clock driver for HSDK boards"
depends on CLK && TARGET_HSDK

View file

@ -40,7 +40,7 @@ obj-$(CONFIG_CLK_MVEBU) += mvebu/
obj-$(CONFIG_CLK_OCTEON) += clk_octeon.o
obj-$(CONFIG_CLK_OWL) += owl/
obj-$(CONFIG_CLK_RENESAS) += renesas/
obj-$(CONFIG_CLK_SCMI) += clk_scmi.o
obj-$(CONFIG_$(SPL_TPL_)CLK_SCMI) += clk_scmi.o
obj-$(CONFIG_CLK_SIFIVE) += sifive/
obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_VERSACLOCK) += clk_versaclock.o

View file

@ -778,6 +778,7 @@ static ulong rk3288_clk_get_rate(struct clk *clk)
case PCLK_I2C5:
return gclk_rate;
case PCLK_PWM:
case PCLK_RKPWM:
return PD_BUS_PCLK_HZ;
case SCLK_SARADC:
new_rate = rockchip_saradc_get_clk(priv->cru);

View file

@ -2838,6 +2838,8 @@ static int rk3568_clk_set_parent(struct clk *clk, struct clk *parent)
case ACLK_RKVDEC_PRE:
case CLK_RKVDEC_CORE:
return rk3568_rkvdec_set_parent(clk, parent);
case I2S1_MCLKOUT_TX:
break;
default:
return -ENOENT;
}

View file

@ -9,6 +9,7 @@
#include <clk-uclass.h>
#include <dm.h>
#include <errno.h>
#include <scmi_protocols.h>
#include <syscon.h>
#include <asm/arch-rockchip/cru_rk3588.h>
#include <asm/arch-rockchip/clock.h>
@ -1552,6 +1553,7 @@ static ulong rk3588_clk_get_rate(struct clk *clk)
case DCLK_DECOM:
rate = rk3588_mmc_get_clk(priv, clk->id);
break;
case TMCLK_EMMC:
case TCLK_WDT0:
rate = OSC_HZ;
break;
@ -1701,6 +1703,7 @@ static ulong rk3588_clk_set_rate(struct clk *clk, ulong rate)
case DCLK_DECOM:
ret = rk3588_mmc_set_clk(priv, clk->id, rate);
break;
case TMCLK_EMMC:
case TCLK_WDT0:
ret = OSC_HZ;
break;
@ -1994,3 +1997,127 @@ U_BOOT_DRIVER(rockchip_rk3588_cru) = {
.bind = rk3588_clk_bind,
.probe = rk3588_clk_probe,
};
#ifdef CONFIG_SPL_BUILD
#define SCRU_BASE 0xfd7d0000
static ulong rk3588_scru_clk_get_rate(struct clk *clk)
{
u32 con, div, sel, parent;
switch (clk->id) {
case SCMI_CCLK_SD:
con = readl(SCRU_BASE + RK3588_CLKSEL_CON(3));
sel = (con & SCMI_CCLK_SD_SEL_MASK) >> SCMI_CCLK_SD_SEL_SHIFT;
div = (con & SCMI_CCLK_SD_DIV_MASK) >> SCMI_CCLK_SD_DIV_SHIFT;
if (sel == SCMI_CCLK_SD_SEL_GPLL)
parent = GPLL_HZ;
else if (sel == SCMI_CCLK_SD_SEL_SPLL)
parent = SPLL_HZ;
else
parent = OSC_HZ;
return DIV_TO_RATE(parent, div);
case SCMI_HCLK_SD:
con = readl(SCRU_BASE + RK3588_CLKSEL_CON(1));
sel = (con & SCMI_HCLK_SD_SEL_MASK) >> SCMI_HCLK_SD_SEL_SHIFT;
if (sel == SCMI_HCLK_SD_SEL_150M)
return 150 * MHz;
else if (sel == SCMI_HCLK_SD_SEL_100M)
return 100 * MHz;
else if (sel == SCMI_HCLK_SD_SEL_50M)
return 50 * MHz;
else
return OSC_HZ;
default:
return -ENOENT;
}
}
static ulong rk3588_scru_clk_set_rate(struct clk *clk, ulong rate)
{
u32 div, sel;
switch (clk->id) {
case SCMI_CCLK_SD:
if ((OSC_HZ % rate) == 0) {
sel = SCMI_CCLK_SD_SEL_24M;
div = DIV_ROUND_UP(OSC_HZ, rate);
} else if ((SPLL_HZ % rate) == 0) {
sel = SCMI_CCLK_SD_SEL_SPLL;
div = DIV_ROUND_UP(SPLL_HZ, rate);
} else {
sel = SCMI_CCLK_SD_SEL_GPLL;
div = DIV_ROUND_UP(GPLL_HZ, rate);
}
rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(3),
SCMI_CCLK_SD_SEL_MASK | SCMI_CCLK_SD_DIV_MASK,
sel << SCMI_CCLK_SD_SEL_SHIFT |
(div - 1) << SCMI_CCLK_SD_DIV_SHIFT);
break;
case SCMI_HCLK_SD:
if (rate >= 150 * MHz)
sel = SCMI_HCLK_SD_SEL_150M;
else if (rate >= 100 * MHz)
sel = SCMI_HCLK_SD_SEL_100M;
else if (rate >= 50 * MHz)
sel = SCMI_HCLK_SD_SEL_50M;
else
sel = SCMI_HCLK_SD_SEL_24M;
rk_clrsetreg(SCRU_BASE + RK3588_CLKSEL_CON(1),
SCMI_HCLK_SD_SEL_MASK,
sel << SCMI_HCLK_SD_SEL_SHIFT);
break;
default:
return -ENOENT;
}
return rk3588_scru_clk_get_rate(clk);
}
static const struct clk_ops rk3588_scru_clk_ops = {
.get_rate = rk3588_scru_clk_get_rate,
.set_rate = rk3588_scru_clk_set_rate,
};
U_BOOT_DRIVER(rockchip_rk3588_scru) = {
.name = "rockchip_rk3588_scru",
.id = UCLASS_CLK,
.ops = &rk3588_scru_clk_ops,
};
static int rk3588_scmi_spl_glue_bind(struct udevice *dev)
{
ofnode node;
u32 protocol_id;
const char *name;
dev_for_each_subnode(node, dev) {
if (!ofnode_is_enabled(node))
continue;
if (ofnode_read_u32(node, "reg", &protocol_id))
continue;
if (protocol_id != SCMI_PROTOCOL_ID_CLOCK)
continue;
name = ofnode_get_name(node);
return device_bind_driver_to_node(dev, "rockchip_rk3588_scru",
name, node, NULL);
}
return -ENOENT;
}
static const struct udevice_id rk3588_scmi_spl_glue_ids[] = {
{ .compatible = "arm,scmi-smc" },
{ }
};
U_BOOT_DRIVER(rk3588_scmi_spl_glue) = {
.name = "rk3588_scmi_spl_glue",
.id = UCLASS_NOP,
.of_match = rk3588_scmi_spl_glue_ids,
.bind = rk3588_scmi_spl_glue_bind,
};
#endif

View file

@ -75,7 +75,7 @@ static int scmi_bind_protocols(struct udevice *dev)
name = ofnode_get_name(node);
switch (protocol_id) {
case SCMI_PROTOCOL_ID_CLOCK:
if (IS_ENABLED(CONFIG_CLK_SCMI))
if (CONFIG_IS_ENABLED(CLK_SCMI))
drv = DM_DRIVER_GET(scmi_clock);
break;
case SCMI_PROTOCOL_ID_RESET_DOMAIN:

View file

@ -13,29 +13,74 @@
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch-rockchip/clock.h>
#include <asm/arch-rockchip/hardware.h>
#include <asm/arch-rockchip/gpio.h>
#include <dm/pinctrl.h>
#include <dt-bindings/clock/rk3288-cru.h>
#include <dm/read.h>
#include <dt-bindings/pinctrl/rockchip.h>
#define SWPORT_DR 0x0000
#define SWPORT_DDR 0x0004
#define EXT_PORT 0x0050
#define SWPORT_DR_L 0x0000
#define SWPORT_DR_H 0x0004
#define SWPORT_DDR_L 0x0008
#define SWPORT_DDR_H 0x000C
#define EXT_PORT_V2 0x0070
#define VER_ID_V2 0x0078
enum {
ROCKCHIP_GPIOS_PER_BANK = 32,
};
#define OFFSET_TO_BIT(bit) (1UL << (bit))
struct rockchip_gpio_priv {
struct rockchip_gpio_regs *regs;
void __iomem *regs;
struct udevice *pinctrl;
int bank;
char name[2];
u32 version;
};
static int rockchip_gpio_get_value(struct udevice *dev, unsigned offset)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
u32 mask = BIT(offset), data;
if (priv->version)
data = readl(priv->regs + EXT_PORT_V2);
else
data = readl(priv->regs + EXT_PORT);
return (data & mask) ? 1 : 0;
}
static int rockchip_gpio_set_value(struct udevice *dev, unsigned offset,
int value)
{
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
u32 mask = BIT(offset), data = value ? mask : 0;
if (priv->version && offset >= 16)
rk_clrsetreg(priv->regs + SWPORT_DR_H, mask >> 16, data >> 16);
else if (priv->version)
rk_clrsetreg(priv->regs + SWPORT_DR_L, mask, data);
else
clrsetbits_le32(priv->regs + SWPORT_DR, mask, data);
return 0;
}
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;
u32 mask = BIT(offset);
clrbits_le32(&regs->swport_ddr, OFFSET_TO_BIT(offset));
if (priv->version && offset >= 16)
rk_clrreg(priv->regs + SWPORT_DDR_H, mask >> 16);
else if (priv->version)
rk_clrreg(priv->regs + SWPORT_DDR_L, mask);
else
clrbits_le32(priv->regs + SWPORT_DDR, mask);
return 0;
}
@ -44,52 +89,42 @@ 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);
u32 mask = BIT(offset);
clrsetbits_le32(&regs->swport_dr, mask, value ? mask : 0);
setbits_le32(&regs->swport_ddr, mask);
rockchip_gpio_set_value(dev, offset, value);
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) ? 1 : 0;
}
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);
if (priv->version && offset >= 16)
rk_setreg(priv->regs + SWPORT_DDR_H, mask >> 16);
else if (priv->version)
rk_setreg(priv->regs + SWPORT_DDR_L, mask);
else
setbits_le32(priv->regs + SWPORT_DDR, mask);
return 0;
}
static int rockchip_gpio_get_function(struct udevice *dev, unsigned offset)
{
#ifdef CONFIG_SPL_BUILD
return -ENODATA;
#else
struct rockchip_gpio_priv *priv = dev_get_priv(dev);
struct rockchip_gpio_regs *regs = priv->regs;
bool is_output;
u32 mask = BIT(offset), data;
int ret;
ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
if (ret)
return ret;
is_output = readl(&regs->swport_ddr) & OFFSET_TO_BIT(offset);
if (CONFIG_IS_ENABLED(PINCTRL)) {
ret = pinctrl_get_gpio_mux(priv->pinctrl, priv->bank, offset);
if (ret < 0)
return ret;
else if (ret != RK_FUNC_GPIO)
return GPIOF_FUNC;
}
return is_output ? GPIOF_OUTPUT : GPIOF_INPUT;
#endif
if (priv->version && offset >= 16)
data = readl(priv->regs + SWPORT_DDR_H) << 16;
else if (priv->version)
data = readl(priv->regs + SWPORT_DDR_L);
else
data = readl(priv->regs + SWPORT_DDR);
return (data & mask) ? GPIOF_OUTPUT : GPIOF_INPUT;
}
/* Simple SPL interface to GPIOs */
@ -147,9 +182,12 @@ static int rockchip_gpio_probe(struct udevice *dev)
int ret;
priv->regs = dev_read_addr_ptr(dev);
ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
if (ret)
return ret;
if (CONFIG_IS_ENABLED(PINCTRL)) {
ret = uclass_first_device_err(UCLASS_PINCTRL, &priv->pinctrl);
if (ret)
return ret;
}
/*
* If "gpio-ranges" is present in the devicetree use it to parse
@ -160,7 +198,7 @@ static int rockchip_gpio_probe(struct udevice *dev)
0, &args);
if (!ret || ret != -ENOENT) {
uc_priv->gpio_count = args.args[2];
priv->bank = args.args[1] / args.args[2];
priv->bank = args.args[1] / ROCKCHIP_GPIOS_PER_BANK;
} else {
uc_priv->gpio_count = ROCKCHIP_GPIOS_PER_BANK;
end = strrchr(dev->name, '@');
@ -170,6 +208,8 @@ static int rockchip_gpio_probe(struct udevice *dev)
priv->name[0] = 'A' + priv->bank;
uc_priv->bank_name = priv->name;
priv->version = readl(priv->regs + VER_ID_V2);
return 0;
}

View file

@ -73,7 +73,7 @@ static int dump_efuse(struct cmd_tbl *cmdtp, int flag,
for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
if (ret < 0)
if (ret <= 0)
return 0;
print_buffer(i, data, 1, sizeof(data), sizeof(data));
@ -238,8 +238,10 @@ static int rockchip_efuse_read(struct udevice *dev, int offset,
offset += data->offset;
if (data->block_size <= 1)
return data->read(dev, offset, buf, size);
if (data->block_size <= 1) {
ret = data->read(dev, offset, buf, size);
goto done;
}
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
@ -255,7 +257,9 @@ static int rockchip_efuse_read(struct udevice *dev, int offset,
memcpy(buf, buffer + block_offset, size);
free(buffer);
return ret;
done:
return ret < 0 ? ret : size;
}
static const struct misc_ops rockchip_efuse_ops = {

View file

@ -89,7 +89,7 @@ static int dump_otp(struct cmd_tbl *cmdtp, int flag,
for (i = 0; true; i += sizeof(data)) {
ret = misc_read(dev, i, &data, sizeof(data));
if (ret < 0)
if (ret <= 0)
return 0;
print_buffer(i, data, 1, sizeof(data), sizeof(data));
@ -249,8 +249,10 @@ static int rockchip_otp_read(struct udevice *dev, int offset,
offset += data->offset;
if (data->block_size <= 1)
return data->read(dev, offset, buf, size);
if (data->block_size <= 1) {
ret = data->read(dev, offset, buf, size);
goto done;
}
block_start = offset / data->block_size;
block_offset = offset % data->block_size;
@ -266,7 +268,9 @@ static int rockchip_otp_read(struct udevice *dev, int offset,
memcpy(buf, buffer + block_offset, size);
free(buffer);
return ret;
done:
return ret < 0 ? ret : size;
}
static const struct misc_ops rockchip_otp_ops = {

View file

@ -476,6 +476,14 @@ config MMC_SDHCI_SDMA
This enables support for the SDMA (Single Operation DMA) defined
in the SD Host Controller Standard Specification Version 1.00 .
config SPL_MMC_SDHCI_SDMA
bool "Support SDHCI SDMA in SPL"
depends on SPL_MMC && MMC_SDHCI
default y if MMC_SDHCI_SDMA
help
This enables support for the SDMA (Single Operation DMA) defined
in the SD Host Controller Standard Specification Version 1.00 in SPL.
config MMC_SDHCI_ADMA
bool "Support SDHCI ADMA2"
depends on MMC_SDHCI

View file

@ -47,51 +47,51 @@
#define ARASAN_VENDOR_REGISTER 0x78
#define ARASAN_VENDOR_ENHANCED_STROBE BIT(0)
/* DWC IP vendor area 1 pointer */
#define DWCMSHC_P_VENDOR_AREA1 0xe8
#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
/* Offset inside the vendor area 1 */
#define DWCMSHC_EMMC_CONTROL 0x2c
/* Rockchip specific Registers */
#define DWCMSHC_EMMC_EMMC_CTRL 0x52c
#define DWCMSHC_CARD_IS_EMMC BIT(0)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
/* Rockchip specific Registers */
#define DWCMSHC_EMMC_DLL_CTRL 0x800
#define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1)
#define DWCMSHC_EMMC_DLL_RXCLK 0x804
#define DWCMSHC_EMMC_DLL_TXCLK 0x808
#define DWCMSHC_EMMC_DLL_STRBIN 0x80c
#define DECMSHC_EMMC_DLL_CMDOUT 0x810
#define DWCMSHC_EMMC_DLL_CMDOUT 0x810
#define DWCMSHC_EMMC_DLL_STATUS0 0x840
#define DWCMSHC_EMMC_DLL_STATUS1 0x844
#define DWCMSHC_EMMC_DLL_START BIT(0)
#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
#define DWCMSHC_EMMC_DLL_START_POINT 16
#define DWCMSHC_EMMC_DLL_START_DEFAULT 5
#define DWCMSHC_EMMC_DLL_INC_VALUE 2
#define DWCMSHC_EMMC_DLL_INC 8
#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
#define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
#define DLL_TXCLK_TAPNUM_DEFAULT 0xA
#define DLL_STRBIN_TAPNUM_DEFAULT 0x8
#define DLL_RXCLK_NO_INVERTER BIT(29)
#define DLL_RXCLK_ORI_GATE BIT(31)
#define DLL_TXCLK_TAPNUM_DEFAULT 0x10
#define DLL_TXCLK_TAPNUM_90_DEGREES 0x9
#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
#define DLL_TXCLK_NO_INVERTER BIT(29)
#define DLL_STRBIN_TAPNUM_DEFAULT 0x4
#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
#define DLL_STRBIN_DELAY_NUM_OFFSET 16
#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16
#define DLL_STRBIN_DELAY_NUM_DEFAULT 0x10
#define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
#define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
#define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
#define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
#define DLL_CMDOUT_BOTH_CLK_EDGE BIT(30)
#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
#define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
#define DLL_RXCLK_NO_INVERTER 1
#define DLL_RXCLK_INVERTER 0
#define DLL_RXCLK_ORI_GATE BIT(31)
#define DWCMSHC_ENHANCED_STROBE BIT(8)
#define DLL_LOCK_WO_TMOUT(x) \
((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
(((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
#define ROCKCHIP_MAX_CLKS 3
#define FLAG_INVERTER_FLAG_IN_RXCLK BIT(0)
struct rockchip_sdhc_plat {
struct mmc_config cfg;
struct mmc mmc;
@ -112,7 +112,6 @@ struct rockchip_sdhc {
};
struct sdhci_data {
int (*emmc_phy_init)(struct udevice *dev);
int (*get_phy)(struct udevice *dev);
/**
@ -140,6 +139,9 @@ struct sdhci_data {
*/
int (*set_ios_post)(struct sdhci_host *host);
void (*set_clock)(struct sdhci_host *host, u32 div);
int (*config_dll)(struct sdhci_host *host, u32 clock, bool enable);
/**
* set_enhanced_strobe() - Set HS400 Enhanced Strobe config
*
@ -152,12 +154,11 @@ struct sdhci_data {
* Return: 0 if successful, -ve on error
*/
int (*set_enhanced_strobe)(struct sdhci_host *host);
};
static int rk3399_emmc_phy_init(struct udevice *dev)
{
return 0;
}
u32 flags;
u8 hs200_txclk_tapnum;
u8 hs400_txclk_tapnum;
};
static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
{
@ -294,30 +295,27 @@ static int rk3399_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
static int rk3568_emmc_phy_init(struct udevice *dev)
{
struct rockchip_sdhc *prv = dev_get_priv(dev);
struct sdhci_host *host = &prv->host;
u32 extra;
extra = DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
return 0;
}
static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
static void rk3568_sdhci_set_clock(struct sdhci_host *host, u32 div)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
struct mmc *mmc = host->mmc;
ulong rate;
rate = clk_set_rate(&priv->emmc_clk, mmc->clock);
if (IS_ERR_VALUE(rate))
printf("%s: Set clock rate failed: %ld\n", __func__, (long)rate);
}
static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
struct mmc *mmc = host->mmc;
int val, ret;
u32 extra;
u32 extra, txclk_tapnum;
if (clock > host->max_clk)
clock = host->max_clk;
if (clock)
clk_set_rate(&priv->emmc_clk, clock);
sdhci_set_clock(host->mmc, clock);
if (!enable)
return 0;
if (clock >= 100 * MHz) {
/* reset DLL */
@ -337,13 +335,28 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
if (ret)
return ret;
extra = DWCMSHC_EMMC_DLL_DLYENA |
DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
if (data->flags & FLAG_INVERTER_FLAG_IN_RXCLK)
extra |= DLL_RXCLK_NO_INVERTER;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
txclk_tapnum = data->hs200_txclk_tapnum;
if (mmc->selected_mode == MMC_HS_400 ||
mmc->selected_mode == MMC_HS_400_ES) {
txclk_tapnum = data->hs400_txclk_tapnum;
extra = DLL_CMDOUT_SRC_CLK_NEG |
DLL_CMDOUT_BOTH_CLK_EDGE |
DWCMSHC_EMMC_DLL_DLYENA |
DLL_CMDOUT_TAPNUM_90_DEGREES |
DLL_CMDOUT_TAPNUM_FROM_SW;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CMDOUT);
}
extra = DWCMSHC_EMMC_DLL_DLYENA |
DLL_TXCLK_TAPNUM_DEFAULT |
DLL_TXCLK_TAPNUM_FROM_SW;
DLL_TXCLK_TAPNUM_FROM_SW |
DLL_TXCLK_NO_INVERTER |
txclk_tapnum;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
extra = DWCMSHC_EMMC_DLL_DLYENA |
@ -355,11 +368,11 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
* Disable DLL and reset both of sample and drive clock.
* The bypass bit and start bit need to be set if DLL is not locked.
*/
sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START,
DWCMSHC_EMMC_DLL_CTRL);
extra = DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START;
sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CMDOUT);
/*
* Before switching to hs400es mode, the driver will enable
* enhanced strobe first. PHY needs to configure the parameters
@ -374,57 +387,55 @@ static int rk3568_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clo
return 0;
}
static int rk3568_emmc_get_phy(struct udevice *dev)
{
return 0;
}
static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host)
{
struct mmc *mmc = host->mmc;
u32 vendor;
int reg;
reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
+ DWCMSHC_EMMC_CONTROL;
vendor = sdhci_readl(host, reg);
if (mmc->selected_mode == MMC_HS_400_ES)
vendor |= DWCMSHC_ENHANCED_STROBE;
else
vendor &= ~DWCMSHC_ENHANCED_STROBE;
sdhci_writel(host, vendor, reg);
return 0;
}
static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
{
struct mmc *mmc = host->mmc;
uint clock = mmc->tran_speed;
u32 reg, vendor_reg;
u32 reg;
if (!clock)
clock = mmc->clock;
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
reg &= ~SDHCI_CTRL_UHS_MASK;
rk3568_sdhci_emmc_set_clock(host, clock);
if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
reg &= ~SDHCI_CTRL_UHS_MASK;
switch (mmc->selected_mode) {
case UHS_SDR25:
case MMC_HS:
case MMC_HS_52:
reg |= SDHCI_CTRL_UHS_SDR25;
break;
case UHS_SDR50:
reg |= SDHCI_CTRL_UHS_SDR50;
break;
case UHS_DDR50:
case MMC_DDR_52:
reg |= SDHCI_CTRL_UHS_DDR50;
break;
case UHS_SDR104:
case MMC_HS_200:
reg |= SDHCI_CTRL_UHS_SDR104;
break;
case MMC_HS_400:
case MMC_HS_400_ES:
reg |= DWCMSHC_CTRL_HS400;
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK)
+ DWCMSHC_EMMC_CONTROL;
/* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
reg = sdhci_readw(host, vendor_reg);
reg |= DWCMSHC_CARD_IS_EMMC;
sdhci_writew(host, reg, vendor_reg);
} else {
sdhci_set_uhs_timing(host);
break;
default:
reg |= SDHCI_CTRL_UHS_SDR12;
}
sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
reg = sdhci_readw(host, DWCMSHC_EMMC_EMMC_CTRL);
if (IS_MMC(mmc))
reg |= DWCMSHC_CARD_IS_EMMC;
else
reg &= ~DWCMSHC_CARD_IS_EMMC;
if (mmc->selected_mode == MMC_HS_400_ES)
reg |= DWCMSHC_ENHANCED_STROBE;
else
reg &= ~DWCMSHC_ENHANCED_STROBE;
sdhci_writew(host, reg, DWCMSHC_EMMC_EMMC_CTRL);
return 0;
}
@ -448,23 +459,32 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
return 0;
}
static void rockchip_sdhci_set_clock(struct sdhci_host *host, u32 div)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
if (data->set_clock)
data->set_clock(host, div);
}
static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
{
struct sdhci_host *host = dev_get_priv(mmc->dev);
struct rockchip_sdhc *priv = dev_get_priv(mmc->dev);
struct sdhci_host *host = &priv->host;
char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
struct mmc_cmd cmd;
u32 ctrl, blk_size;
int ret = 0;
int ret;
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl |= SDHCI_CTRL_EXEC_TUNING;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_INT_ENABLE);
sdhci_writel(host, SDHCI_INT_DATA_AVAIL, SDHCI_SIGNAL_ENABLE);
blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 64);
if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && host->mmc->bus_width == 8)
if (opcode == MMC_CMD_SEND_TUNING_BLOCK_HS200 && mmc->bus_width == 8)
blk_size = SDHCI_MAKE_BLKSZ(SDHCI_DEFAULT_BOUNDARY_ARG, 128);
sdhci_writew(host, blk_size, SDHCI_BLOCK_SIZE);
sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE);
@ -474,40 +494,39 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
cmd.cmdarg = 0;
do {
if (tuning_loop_counter-- == 0)
break;
mmc_send_cmd(mmc, &cmd, NULL);
if (opcode == MMC_CMD_SEND_TUNING_BLOCK)
/*
* For tuning command, do not do busy loop. As tuning
* is happening (CLK-DATA latching for setup/hold time
* requirements), give time to complete
*/
udelay(1);
ret = mmc_send_cmd(mmc, &cmd, NULL);
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
if (ret || tuning_loop_counter-- == 0)
break;
} while (ctrl & SDHCI_CTRL_EXEC_TUNING);
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
printf("%s:Tuning failed\n", __func__);
ret = -EIO;
}
if (ret || tuning_loop_counter < 0 || !(ctrl & SDHCI_CTRL_TUNED_CLK)) {
if (!ret)
ret = -EIO;
printf("%s: Tuning failed: %d\n", __func__, ret);
if (tuning_loop_counter < 0) {
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
sdhci_writel(host, ctrl, SDHCI_HOST_CONTROL2);
ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
}
/* Enable only interrupts served by the SD controller */
sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK, SDHCI_INT_ENABLE);
/* Mask all sdhci interrupt sources */
sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
return ret;
}
static int rockchip_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enable)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
if (data->config_dll)
return data->config_dll(host, clock, enable);
return 0;
}
static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
@ -516,13 +535,15 @@ static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
if (data->set_enhanced_strobe)
return data->set_enhanced_strobe(host);
return -ENOTSUPP;
return 0;
}
static struct sdhci_ops rockchip_sdhci_ops = {
.set_ios_post = rockchip_sdhci_set_ios_post,
.platform_execute_tuning = &rockchip_sdhci_execute_tuning,
.set_control_reg = rockchip_sdhci_set_control_reg,
.set_ios_post = rockchip_sdhci_set_ios_post,
.set_clock = rockchip_sdhci_set_clock,
.platform_execute_tuning = rockchip_sdhci_execute_tuning,
.config_dll = rockchip_sdhci_config_dll,
.set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
};
@ -531,9 +552,9 @@ static int rockchip_sdhci_probe(struct udevice *dev)
struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(dev);
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
struct rockchip_sdhc *prv = dev_get_priv(dev);
struct rockchip_sdhc *priv = dev_get_priv(dev);
struct mmc_config *cfg = &plat->cfg;
struct sdhci_host *host = &prv->host;
struct sdhci_host *host = &priv->host;
struct clk clk;
int ret;
@ -547,8 +568,8 @@ static int rockchip_sdhci_probe(struct udevice *dev)
printf("%s fail to get clk\n", __func__);
}
prv->emmc_clk = clk;
prv->dev = dev;
priv->emmc_clk = clk;
priv->dev = dev;
if (data->get_phy) {
ret = data->get_phy(dev);
@ -556,17 +577,11 @@ static int rockchip_sdhci_probe(struct udevice *dev)
return ret;
}
if (data->emmc_phy_init) {
ret = data->emmc_phy_init(dev);
if (ret)
return ret;
}
host->ops = &rockchip_sdhci_ops;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD;
host->mmc = &plat->mmc;
host->mmc->priv = &prv->host;
host->mmc->priv = &priv->host;
host->mmc->dev = dev;
upriv->mmc = host->mmc;
@ -574,14 +589,23 @@ static int rockchip_sdhci_probe(struct udevice *dev)
if (ret)
return ret;
/*
* Reading more than 4 blocks with a single CMD18 command in PIO mode
* triggers Data End Bit Error on RK3568 and RK3588. Limit to reading
* max 4 blocks in one command when using PIO mode.
*/
if (!(host->flags & USE_DMA))
cfg->b_max = 4;
return sdhci_probe(dev);
}
static int rockchip_sdhci_of_to_plat(struct udevice *dev)
{
struct rockchip_sdhc_plat *plat = dev_get_plat(dev);
struct sdhci_host *host = dev_get_priv(dev);
struct rockchip_sdhc *priv = dev_get_priv(dev);
struct mmc_config *cfg = &plat->cfg;
struct sdhci_host *host = &priv->host;
int ret;
host->name = dev->name;
@ -603,17 +627,26 @@ static int rockchip_sdhci_bind(struct udevice *dev)
static const struct sdhci_data rk3399_data = {
.get_phy = rk3399_emmc_get_phy,
.emmc_phy_init = rk3399_emmc_phy_init,
.set_control_reg = rk3399_sdhci_set_control_reg,
.set_ios_post = rk3399_sdhci_set_ios_post,
.set_enhanced_strobe = rk3399_sdhci_set_enhanced_strobe,
};
static const struct sdhci_data rk3568_data = {
.get_phy = rk3568_emmc_get_phy,
.emmc_phy_init = rk3568_emmc_phy_init,
.set_ios_post = rk3568_sdhci_set_ios_post,
.set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe,
.set_clock = rk3568_sdhci_set_clock,
.config_dll = rk3568_sdhci_config_dll,
.flags = FLAG_INVERTER_FLAG_IN_RXCLK,
.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
.hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
};
static const struct sdhci_data rk3588_data = {
.set_ios_post = rk3568_sdhci_set_ios_post,
.set_clock = rk3568_sdhci_set_clock,
.config_dll = rk3568_sdhci_config_dll,
.hs200_txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT,
.hs400_txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES,
};
static const struct udevice_id sdhci_ids[] = {
@ -625,6 +658,10 @@ static const struct udevice_id sdhci_ids[] = {
.compatible = "rockchip,rk3568-dwcmshc",
.data = (ulong)&rk3568_data,
},
{
.compatible = "rockchip,rk3588-dwcmshc",
.data = (ulong)&rk3588_data,
},
{ }
};

View file

@ -70,7 +70,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host, struct mmc_data *data)
}
}
#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
static void sdhci_prepare_dma(struct sdhci_host *host, struct mmc_data *data,
int *is_aligned, int trans_bytes)
{
@ -177,7 +177,7 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data)
}
} while (!(stat & SDHCI_INT_DATA_END));
#if (defined(CONFIG_MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
#if (CONFIG_IS_ENABLED(MMC_SDHCI_SDMA) || CONFIG_IS_ENABLED(MMC_SDHCI_ADMA))
dma_unmap_single(host->start_addr, data->blocks * data->blocksize,
mmc_get_dma_dir(data));
#endif
@ -518,6 +518,10 @@ void sdhci_set_uhs_timing(struct sdhci_host *host)
reg &= ~SDHCI_CTRL_UHS_MASK;
switch (mmc->selected_mode) {
case UHS_SDR25:
case MMC_HS:
reg |= SDHCI_CTRL_UHS_SDR25;
break;
case UHS_SDR50:
case MMC_HS_52:
reg |= SDHCI_CTRL_UHS_SDR50;
@ -682,6 +686,7 @@ static int sdhci_set_ios(struct mmc *mmc)
if (!no_hispd_bit) {
if (mmc->selected_mode == MMC_HS ||
mmc->selected_mode == SD_HS ||
mmc->selected_mode == MMC_HS_52 ||
mmc->selected_mode == MMC_DDR_52 ||
mmc->selected_mode == MMC_HS_200 ||
mmc->selected_mode == MMC_HS_400 ||
@ -872,7 +877,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
#endif
debug("%s, caps: 0x%x\n", __func__, caps);
#ifdef CONFIG_MMC_SDHCI_SDMA
#if CONFIG_IS_ENABLED(MMC_SDHCI_SDMA)
if ((caps & SDHCI_CAN_DO_SDMA)) {
host->flags |= USE_SDMA;
} else {
@ -882,7 +887,7 @@ int sdhci_setup_cfg(struct mmc_config *cfg, struct sdhci_host *host,
#endif
#if CONFIG_IS_ENABLED(MMC_SDHCI_ADMA)
if (!(caps & SDHCI_CAN_DO_ADMA2)) {
printf("%s: Your controller doesn't support SDMA!!\n",
printf("%s: Your controller doesn't support ADMA!!\n",
__func__);
return -EINVAL;
}

View file

@ -4,6 +4,14 @@
menu "Rockchip PHY driver"
config PHY_ROCKCHIP_INNO_DSIDPHY
bool "Rockchip INNO DSIDPHY Driver"
depends on ARCH_ROCKCHIP
select PHY
select MIPI_DPHY_HELPERS
help
Support for Rockchip MIPI DPHY with Innosilicon IP block.
config PHY_ROCKCHIP_INNO_USB2
bool "Rockchip INNO USB2PHY Driver"
depends on ARCH_ROCKCHIP

View file

@ -8,3 +8,4 @@ obj-$(CONFIG_PHY_ROCKCHIP_NANENG_COMBOPHY) += phy-rockchip-naneng-combphy.o
obj-$(CONFIG_PHY_ROCKCHIP_PCIE) += phy-rockchip-pcie.o
obj-$(CONFIG_PHY_ROCKCHIP_SNPS_PCIE3) += phy-rockchip-snps-pcie3.o
obj-$(CONFIG_PHY_ROCKCHIP_TYPEC) += phy-rockchip-typec.o
obj-$(CONFIG_PHY_ROCKCHIP_INNO_DSIDPHY) += phy-rockchip-inno-dsidphy.o

View file

@ -0,0 +1,680 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018 Rockchip Electronics Co. Ltd.
*
* Author: Wyon Bi <bivvy.bi@rock-chips.com>
*/
#include <dm.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <div64.h>
#include <generic-phy.h>
#include <linux/kernel.h>
#include <linux/iopoll.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/math64.h>
#include <phy-mipi-dphy.h>
#include <reset.h>
#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))
/*
* The offset address[7:0] is distributed two parts, one from the bit7 to bit5
* is the first address, the other from the bit4 to bit0 is the second address.
* when you configure the registers, you must set both of them. The Clock Lane
* and Data Lane use the same registers with the same second address, but the
* first address is different.
*/
#define FIRST_ADDRESS(x) (((x) & 0x7) << 5)
#define SECOND_ADDRESS(x) (((x) & 0x1f) << 0)
#define PHY_REG(first, second) (FIRST_ADDRESS(first) | \
SECOND_ADDRESS(second))
/* Analog Register Part: reg00 */
#define BANDGAP_POWER_MASK BIT(7)
#define BANDGAP_POWER_DOWN BIT(7)
#define BANDGAP_POWER_ON 0
#define LANE_EN_MASK GENMASK(6, 2)
#define LANE_EN_CK BIT(6)
#define LANE_EN_3 BIT(5)
#define LANE_EN_2 BIT(4)
#define LANE_EN_1 BIT(3)
#define LANE_EN_0 BIT(2)
#define POWER_WORK_MASK GENMASK(1, 0)
#define POWER_WORK_ENABLE UPDATE(1, 1, 0)
#define POWER_WORK_DISABLE UPDATE(2, 1, 0)
/* Analog Register Part: reg01 */
#define REG_SYNCRST_MASK BIT(2)
#define REG_SYNCRST_RESET BIT(2)
#define REG_SYNCRST_NORMAL 0
#define REG_LDOPD_MASK BIT(1)
#define REG_LDOPD_POWER_DOWN BIT(1)
#define REG_LDOPD_POWER_ON 0
#define REG_PLLPD_MASK BIT(0)
#define REG_PLLPD_POWER_DOWN BIT(0)
#define REG_PLLPD_POWER_ON 0
/* Analog Register Part: reg03 */
#define REG_FBDIV_HI_MASK BIT(5)
#define REG_FBDIV_HI(x) UPDATE((x >> 8), 5, 5)
#define REG_PREDIV_MASK GENMASK(4, 0)
#define REG_PREDIV(x) UPDATE(x, 4, 0)
/* Analog Register Part: reg04 */
#define REG_FBDIV_LO_MASK GENMASK(7, 0)
#define REG_FBDIV_LO(x) UPDATE(x, 7, 0)
/* Analog Register Part: reg05 */
#define SAMPLE_CLOCK_PHASE_MASK GENMASK(6, 4)
#define SAMPLE_CLOCK_PHASE(x) UPDATE(x, 6, 4)
#define CLOCK_LANE_SKEW_PHASE_MASK GENMASK(2, 0)
#define CLOCK_LANE_SKEW_PHASE(x) UPDATE(x, 2, 0)
/* Analog Register Part: reg06 */
#define DATA_LANE_3_SKEW_PHASE_MASK GENMASK(6, 4)
#define DATA_LANE_3_SKEW_PHASE(x) UPDATE(x, 6, 4)
#define DATA_LANE_2_SKEW_PHASE_MASK GENMASK(2, 0)
#define DATA_LANE_2_SKEW_PHASE(x) UPDATE(x, 2, 0)
/* Analog Register Part: reg07 */
#define DATA_LANE_1_SKEW_PHASE_MASK GENMASK(6, 4)
#define DATA_LANE_1_SKEW_PHASE(x) UPDATE(x, 6, 4)
#define DATA_LANE_0_SKEW_PHASE_MASK GENMASK(2, 0)
#define DATA_LANE_0_SKEW_PHASE(x) UPDATE(x, 2, 0)
/* Analog Register Part: reg08 */
#define PLL_POST_DIV_ENABLE_MASK BIT(5)
#define PLL_POST_DIV_ENABLE BIT(5)
#define SAMPLE_CLOCK_DIRECTION_MASK BIT(4)
#define SAMPLE_CLOCK_DIRECTION_REVERSE BIT(4)
#define SAMPLE_CLOCK_DIRECTION_FORWARD 0
#define LOWFRE_EN_MASK BIT(5)
#define PLL_OUTPUT_FREQUENCY_DIV_BY_1 0
#define PLL_OUTPUT_FREQUENCY_DIV_BY_2 1
/* Analog Register Part: reg0b */
#define CLOCK_LANE_VOD_RANGE_SET_MASK GENMASK(3, 0)
#define CLOCK_LANE_VOD_RANGE_SET(x) UPDATE(x, 3, 0)
#define VOD_MIN_RANGE 0x1
#define VOD_MID_RANGE 0x3
#define VOD_BIG_RANGE 0x7
#define VOD_MAX_RANGE 0xf
/* Analog Register Part: reg1E */
#define PLL_MODE_SEL_MASK GENMASK(6, 5)
#define PLL_MODE_SEL_LVDS_MODE 0
#define PLL_MODE_SEL_MIPI_MODE BIT(5)
/* Digital Register Part: reg00 */
#define REG_DIG_RSTN_MASK BIT(0)
#define REG_DIG_RSTN_NORMAL BIT(0)
#define REG_DIG_RSTN_RESET 0
/* Digital Register Part: reg01 */
#define INVERT_TXCLKESC_MASK BIT(1)
#define INVERT_TXCLKESC_ENABLE BIT(1)
#define INVERT_TXCLKESC_DISABLE 0
#define INVERT_TXBYTECLKHS_MASK BIT(0)
#define INVERT_TXBYTECLKHS_ENABLE BIT(0)
#define INVERT_TXBYTECLKHS_DISABLE 0
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg05 */
#define T_LPX_CNT_MASK GENMASK(5, 0)
#define T_LPX_CNT(x) UPDATE(x, 5, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg06 */
#define T_HS_ZERO_CNT_HI_MASK BIT(7)
#define T_HS_ZERO_CNT_HI(x) UPDATE(x, 7, 7)
#define T_HS_PREPARE_CNT_MASK GENMASK(6, 0)
#define T_HS_PREPARE_CNT(x) UPDATE(x, 6, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg07 */
#define T_HS_ZERO_CNT_LO_MASK GENMASK(5, 0)
#define T_HS_ZERO_CNT_LO(x) UPDATE(x, 5, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg08 */
#define T_HS_TRAIL_CNT_MASK GENMASK(6, 0)
#define T_HS_TRAIL_CNT(x) UPDATE(x, 6, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg09 */
#define T_HS_EXIT_CNT_LO_MASK GENMASK(4, 0)
#define T_HS_EXIT_CNT_LO(x) UPDATE(x, 4, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0a */
#define T_CLK_POST_CNT_LO_MASK GENMASK(3, 0)
#define T_CLK_POST_CNT_LO(x) UPDATE(x, 3, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0c */
#define LPDT_TX_PPI_SYNC_MASK BIT(2)
#define LPDT_TX_PPI_SYNC_ENABLE BIT(2)
#define LPDT_TX_PPI_SYNC_DISABLE 0
#define T_WAKEUP_CNT_HI_MASK GENMASK(1, 0)
#define T_WAKEUP_CNT_HI(x) UPDATE(x, 1, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0d */
#define T_WAKEUP_CNT_LO_MASK GENMASK(7, 0)
#define T_WAKEUP_CNT_LO(x) UPDATE(x, 7, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg0e */
#define T_CLK_PRE_CNT_MASK GENMASK(3, 0)
#define T_CLK_PRE_CNT(x) UPDATE(x, 3, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg10 */
#define T_CLK_POST_CNT_HI_MASK GENMASK(7, 6)
#define T_CLK_POST_CNT_HI(x) UPDATE(x, 7, 6)
#define T_TA_GO_CNT_MASK GENMASK(5, 0)
#define T_TA_GO_CNT(x) UPDATE(x, 5, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg11 */
#define T_HS_EXIT_CNT_HI_MASK BIT(6)
#define T_HS_EXIT_CNT_HI(x) UPDATE(x, 6, 6)
#define T_TA_SURE_CNT_MASK GENMASK(5, 0)
#define T_TA_SURE_CNT(x) UPDATE(x, 5, 0)
/* Clock/Data0/Data1/Data2/Data3 Lane Register Part: reg12 */
#define T_TA_WAIT_CNT_MASK GENMASK(5, 0)
#define T_TA_WAIT_CNT(x) UPDATE(x, 5, 0)
/* LVDS Register Part: reg00 */
#define LVDS_DIGITAL_INTERNAL_RESET_MASK BIT(2)
#define LVDS_DIGITAL_INTERNAL_RESET_DISABLE BIT(2)
#define LVDS_DIGITAL_INTERNAL_RESET_ENABLE 0
/* LVDS Register Part: reg01 */
#define LVDS_DIGITAL_INTERNAL_ENABLE_MASK BIT(7)
#define LVDS_DIGITAL_INTERNAL_ENABLE BIT(7)
#define LVDS_DIGITAL_INTERNAL_DISABLE 0
/* LVDS Register Part: reg03 */
#define MODE_ENABLE_MASK GENMASK(2, 0)
#define TTL_MODE_ENABLE BIT(2)
#define LVDS_MODE_ENABLE BIT(1)
#define MIPI_MODE_ENABLE BIT(0)
/* LVDS Register Part: reg0b */
#define LVDS_LANE_EN_MASK GENMASK(7, 3)
#define LVDS_DATA_LANE0_EN BIT(7)
#define LVDS_DATA_LANE1_EN BIT(6)
#define LVDS_DATA_LANE2_EN BIT(5)
#define LVDS_DATA_LANE3_EN BIT(4)
#define LVDS_CLK_LANE_EN BIT(3)
#define LVDS_PLL_POWER_MASK BIT(2)
#define LVDS_PLL_POWER_OFF BIT(2)
#define LVDS_PLL_POWER_ON 0
#define LVDS_BANDGAP_POWER_MASK BIT(0)
#define LVDS_BANDGAP_POWER_DOWN BIT(0)
#define LVDS_BANDGAP_POWER_ON 0
#define DSI_PHY_RSTZ 0xa0
#define PHY_ENABLECLK BIT(2)
#define DSI_PHY_STATUS 0xb0
#define PHY_LOCK BIT(0)
#define PSEC_PER_SEC 1000000000000LL
#define msleep(a) udelay(a * 1000)
enum phy_max_rate {
MAX_1GHZ,
MAX_2_5GHZ,
};
struct clk_hw {
struct clk_core *core;
struct clk *clk;
const struct clk_init_data *init;
};
struct inno_video_phy_plat_data {
const struct inno_mipi_dphy_timing *inno_mipi_dphy_timing_table;
const unsigned int num_timings;
enum phy_max_rate max_rate;
};
struct inno_dsidphy {
struct udevice *dev;
struct clk *ref_clk;
struct clk *pclk_phy;
struct clk *pclk_host;
const struct inno_video_phy_plat_data *pdata;
void __iomem *phy_base;
void __iomem *host_base;
struct reset_ctl *rst;
struct phy_configure_opts_mipi_dphy dphy_cfg;
struct clk *pll_clk;
struct {
struct clk_hw hw;
u8 prediv;
u16 fbdiv;
unsigned long rate;
} pll;
};
enum {
REGISTER_PART_ANALOG,
REGISTER_PART_DIGITAL,
REGISTER_PART_CLOCK_LANE,
REGISTER_PART_DATA0_LANE,
REGISTER_PART_DATA1_LANE,
REGISTER_PART_DATA2_LANE,
REGISTER_PART_DATA3_LANE,
REGISTER_PART_LVDS,
};
struct inno_mipi_dphy_timing {
unsigned long rate;
u8 lpx;
u8 hs_prepare;
u8 clk_lane_hs_zero;
u8 data_lane_hs_zero;
u8 hs_trail;
};
static const
struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_1ghz[] = {
{ 110000000, 0x0, 0x20, 0x16, 0x02, 0x22},
{ 150000000, 0x0, 0x06, 0x16, 0x03, 0x45},
{ 200000000, 0x0, 0x18, 0x17, 0x04, 0x0b},
{ 250000000, 0x0, 0x05, 0x17, 0x05, 0x16},
{ 300000000, 0x0, 0x51, 0x18, 0x06, 0x2c},
{ 400000000, 0x0, 0x64, 0x19, 0x07, 0x33},
{ 500000000, 0x0, 0x20, 0x1b, 0x07, 0x4e},
{ 600000000, 0x0, 0x6a, 0x1d, 0x08, 0x3a},
{ 700000000, 0x0, 0x3e, 0x1e, 0x08, 0x6a},
{ 800000000, 0x0, 0x21, 0x1f, 0x09, 0x29},
{1000000000, 0x0, 0x09, 0x20, 0x09, 0x27},
};
static const
struct inno_mipi_dphy_timing inno_mipi_dphy_timing_table_max_2_5ghz[] = {
{ 110000000, 0x02, 0x7f, 0x16, 0x02, 0x02},
{ 150000000, 0x02, 0x7f, 0x16, 0x03, 0x02},
{ 200000000, 0x02, 0x7f, 0x17, 0x04, 0x02},
{ 250000000, 0x02, 0x7f, 0x17, 0x05, 0x04},
{ 300000000, 0x02, 0x7f, 0x18, 0x06, 0x04},
{ 400000000, 0x03, 0x7e, 0x19, 0x07, 0x04},
{ 500000000, 0x03, 0x7c, 0x1b, 0x07, 0x08},
{ 600000000, 0x03, 0x70, 0x1d, 0x08, 0x10},
{ 700000000, 0x05, 0x40, 0x1e, 0x08, 0x30},
{ 800000000, 0x05, 0x02, 0x1f, 0x09, 0x30},
{1000000000, 0x05, 0x08, 0x20, 0x09, 0x30},
{1200000000, 0x06, 0x03, 0x32, 0x14, 0x0f},
{1400000000, 0x09, 0x03, 0x32, 0x14, 0x0f},
{1600000000, 0x0d, 0x42, 0x36, 0x0e, 0x0f},
{1800000000, 0x0e, 0x47, 0x7a, 0x0e, 0x0f},
{2000000000, 0x11, 0x64, 0x7a, 0x0e, 0x0b},
{2200000000, 0x13, 0x64, 0x7e, 0x15, 0x0b},
{2400000000, 0x13, 0x33, 0x7f, 0x15, 0x6a},
{2500000000, 0x15, 0x54, 0x7f, 0x15, 0x6a},
};
static void phy_update_bits(struct inno_dsidphy *inno,
u8 first, u8 second, u8 mask, u8 val)
{
u32 reg = PHY_REG(first, second) << 2;
unsigned int tmp, orig;
orig = readl(inno->phy_base + reg);
tmp = orig & ~mask;
tmp |= val & mask;
writel(tmp, inno->phy_base + reg);
}
static unsigned long inno_dsidphy_pll_calc_rate(struct inno_dsidphy *inno,
unsigned long rate)
{
unsigned long prate;
unsigned long best_freq = 0;
unsigned long fref, fout;
u8 min_prediv, max_prediv;
u8 _prediv, best_prediv = 1;
u16 _fbdiv, best_fbdiv = 1;
u32 min_delta = UINT_MAX;
/*
* Upstream Linux tries to read the ref_clk, while the BSP
* U-Boot hard-codes this as 24MHz. Try the first, and if that
* fails do the second.
*/
prate = clk_get_rate(inno->ref_clk);
if (IS_ERR_VALUE(prate))
prate = 24000000;
/*
* The PLL output frequency can be calculated using a simple formula:
* PLL_Output_Frequency = (FREF / PREDIV * FBDIV) / 2
* PLL_Output_Frequency: it is equal to DDR-Clock-Frequency * 2
*/
fref = prate / 2;
if (rate > 1000000000UL)
fout = 1000000000UL;
else
fout = rate;
/* 5Mhz < Fref / prediv < 40MHz */
min_prediv = DIV_ROUND_UP(fref, 40000000);
max_prediv = fref / 5000000;
for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
u64 tmp;
u32 delta;
tmp = (u64)fout * _prediv;
do_div(tmp, fref);
_fbdiv = tmp;
/*
* The possible settings of feedback divider are
* 12, 13, 14, 16, ~ 511
*/
if (_fbdiv == 15)
continue;
if (_fbdiv < 12 || _fbdiv > 511)
continue;
tmp = (u64)_fbdiv * fref;
do_div(tmp, _prediv);
delta = abs(fout - tmp);
if (!delta) {
best_prediv = _prediv;
best_fbdiv = _fbdiv;
best_freq = tmp;
break;
} else if (delta < min_delta) {
best_prediv = _prediv;
best_fbdiv = _fbdiv;
best_freq = tmp;
min_delta = delta;
}
}
if (best_freq) {
inno->pll.prediv = best_prediv;
inno->pll.fbdiv = best_fbdiv;
inno->pll.rate = best_freq;
}
return best_freq;
}
static void inno_dsidphy_mipi_mode_enable(struct inno_dsidphy *inno)
{
struct phy_configure_opts_mipi_dphy *cfg = &inno->dphy_cfg;
const struct inno_mipi_dphy_timing *timings;
u32 t_txbyteclkhs, t_txclkesc;
u32 txbyteclkhs, txclkesc, esc_clk_div;
u32 hs_exit, clk_post, clk_pre, wakeup, lpx, ta_go, ta_sure, ta_wait;
u32 hs_prepare, hs_trail, hs_zero, clk_lane_hs_zero, data_lane_hs_zero;
unsigned int i;
timings = inno->pdata->inno_mipi_dphy_timing_table;
inno_dsidphy_pll_calc_rate(inno, cfg->hs_clk_rate);
/* Select MIPI mode */
phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
MODE_ENABLE_MASK, MIPI_MODE_ENABLE);
/* Configure PLL */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
REG_PREDIV_MASK, REG_PREDIV(inno->pll.prediv));
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x03,
REG_FBDIV_HI_MASK, REG_FBDIV_HI(inno->pll.fbdiv));
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x04,
REG_FBDIV_LO_MASK, REG_FBDIV_LO(inno->pll.fbdiv));
if (inno->pdata->max_rate == MAX_2_5GHZ) {
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x08,
PLL_POST_DIV_ENABLE_MASK, PLL_POST_DIV_ENABLE);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x0b,
CLOCK_LANE_VOD_RANGE_SET_MASK,
CLOCK_LANE_VOD_RANGE_SET(VOD_MAX_RANGE));
}
/* Enable PLL and LDO */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
REG_LDOPD_MASK | REG_PLLPD_MASK,
REG_LDOPD_POWER_ON | REG_PLLPD_POWER_ON);
/* Reset analog */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
REG_SYNCRST_MASK, REG_SYNCRST_RESET);
udelay(1);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
REG_SYNCRST_MASK, REG_SYNCRST_NORMAL);
/* Reset digital */
phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
REG_DIG_RSTN_MASK, REG_DIG_RSTN_RESET);
udelay(1);
phy_update_bits(inno, REGISTER_PART_DIGITAL, 0x00,
REG_DIG_RSTN_MASK, REG_DIG_RSTN_NORMAL);
txbyteclkhs = inno->pll.rate / 8;
t_txbyteclkhs = div_u64(PSEC_PER_SEC, txbyteclkhs);
esc_clk_div = DIV_ROUND_UP(txbyteclkhs, 20000000);
txclkesc = txbyteclkhs / esc_clk_div;
t_txclkesc = div_u64(PSEC_PER_SEC, txclkesc);
/*
* The value of counter for HS Ths-exit
* Ths-exit = Tpin_txbyteclkhs * value
*/
hs_exit = DIV_ROUND_UP(cfg->hs_exit, t_txbyteclkhs);
/*
* The value of counter for HS Tclk-post
* Tclk-post = Tpin_txbyteclkhs * value
*/
clk_post = DIV_ROUND_UP(cfg->clk_post, t_txbyteclkhs);
/*
* The value of counter for HS Tclk-pre
* Tclk-pre = Tpin_txbyteclkhs * value
*/
clk_pre = DIV_ROUND_UP(cfg->clk_pre, BITS_PER_BYTE);
/*
* The value of counter for HS Tta-go
* Tta-go for turnaround
* Tta-go = Ttxclkesc * value
*/
ta_go = DIV_ROUND_UP(cfg->ta_go, t_txclkesc);
/*
* The value of counter for HS Tta-sure
* Tta-sure for turnaround
* Tta-sure = Ttxclkesc * value
*/
ta_sure = DIV_ROUND_UP(cfg->ta_sure, t_txclkesc);
/*
* The value of counter for HS Tta-wait
* Tta-wait for turnaround
* Tta-wait = Ttxclkesc * value
*/
ta_wait = DIV_ROUND_UP(cfg->ta_get, t_txclkesc);
for (i = 0; i < inno->pdata->num_timings; i++)
if (inno->pll.rate <= timings[i].rate)
break;
if (i == inno->pdata->num_timings)
--i;
/*
* The value of counter for HS Tlpx Time
* Tlpx = Tpin_txbyteclkhs * (2 + value)
*/
if (inno->pdata->max_rate == MAX_1GHZ) {
lpx = DIV_ROUND_UP(cfg->lpx, t_txbyteclkhs);
if (lpx >= 2)
lpx -= 2;
} else {
lpx = timings[i].lpx;
}
hs_prepare = timings[i].hs_prepare;
hs_trail = timings[i].hs_trail;
clk_lane_hs_zero = timings[i].clk_lane_hs_zero;
data_lane_hs_zero = timings[i].data_lane_hs_zero;
wakeup = 0x3ff;
for (i = REGISTER_PART_CLOCK_LANE; i <= REGISTER_PART_DATA3_LANE; i++) {
if (i == REGISTER_PART_CLOCK_LANE)
hs_zero = clk_lane_hs_zero;
else
hs_zero = data_lane_hs_zero;
phy_update_bits(inno, i, 0x05, T_LPX_CNT_MASK,
T_LPX_CNT(lpx));
phy_update_bits(inno, i, 0x06, T_HS_PREPARE_CNT_MASK,
T_HS_PREPARE_CNT(hs_prepare));
if (inno->pdata->max_rate == MAX_2_5GHZ)
phy_update_bits(inno, i, 0x06, T_HS_ZERO_CNT_HI_MASK,
T_HS_ZERO_CNT_HI(hs_zero >> 6));
phy_update_bits(inno, i, 0x07, T_HS_ZERO_CNT_LO_MASK,
T_HS_ZERO_CNT_LO(hs_zero));
phy_update_bits(inno, i, 0x08, T_HS_TRAIL_CNT_MASK,
T_HS_TRAIL_CNT(hs_trail));
if (inno->pdata->max_rate == MAX_2_5GHZ)
phy_update_bits(inno, i, 0x11, T_HS_EXIT_CNT_HI_MASK,
T_HS_EXIT_CNT_HI(hs_exit >> 5));
phy_update_bits(inno, i, 0x09, T_HS_EXIT_CNT_LO_MASK,
T_HS_EXIT_CNT_LO(hs_exit));
if (inno->pdata->max_rate == MAX_2_5GHZ)
phy_update_bits(inno, i, 0x10, T_CLK_POST_CNT_HI_MASK,
T_CLK_POST_CNT_HI(clk_post >> 4));
phy_update_bits(inno, i, 0x0a, T_CLK_POST_CNT_LO_MASK,
T_CLK_POST_CNT_LO(clk_post));
phy_update_bits(inno, i, 0x0e, T_CLK_PRE_CNT_MASK,
T_CLK_PRE_CNT(clk_pre));
phy_update_bits(inno, i, 0x0c, T_WAKEUP_CNT_HI_MASK,
T_WAKEUP_CNT_HI(wakeup >> 8));
phy_update_bits(inno, i, 0x0d, T_WAKEUP_CNT_LO_MASK,
T_WAKEUP_CNT_LO(wakeup));
phy_update_bits(inno, i, 0x10, T_TA_GO_CNT_MASK,
T_TA_GO_CNT(ta_go));
phy_update_bits(inno, i, 0x11, T_TA_SURE_CNT_MASK,
T_TA_SURE_CNT(ta_sure));
phy_update_bits(inno, i, 0x12, T_TA_WAIT_CNT_MASK,
T_TA_WAIT_CNT(ta_wait));
}
/* Enable all lanes on analog part */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
LANE_EN_MASK, LANE_EN_CK | LANE_EN_3 | LANE_EN_2 |
LANE_EN_1 | LANE_EN_0);
}
static int inno_dsidphy_power_on(struct phy *phy)
{
struct inno_dsidphy *inno = dev_get_priv(phy->dev);
clk_prepare_enable(inno->pclk_phy);
clk_prepare_enable(inno->ref_clk);
/* Bandgap power on */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
BANDGAP_POWER_MASK, BANDGAP_POWER_ON);
/* Enable power work */
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
POWER_WORK_MASK, POWER_WORK_ENABLE);
inno_dsidphy_mipi_mode_enable(inno);
return 0;
}
static int inno_dsidphy_power_off(struct phy *phy)
{
struct inno_dsidphy *inno = dev_get_priv(phy->dev);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00, LANE_EN_MASK, 0);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x01,
REG_LDOPD_MASK | REG_PLLPD_MASK,
REG_LDOPD_POWER_DOWN | REG_PLLPD_POWER_DOWN);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
POWER_WORK_MASK, POWER_WORK_DISABLE);
phy_update_bits(inno, REGISTER_PART_ANALOG, 0x00,
BANDGAP_POWER_MASK, BANDGAP_POWER_DOWN);
phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b, LVDS_LANE_EN_MASK, 0);
phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,
LVDS_DIGITAL_INTERNAL_ENABLE_MASK,
LVDS_DIGITAL_INTERNAL_DISABLE);
phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,
LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,
LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);
clk_disable_unprepare(inno->ref_clk);
clk_disable_unprepare(inno->pclk_phy);
return 0;
}
static int inno_dsidphy_configure(struct phy *phy, void *params)
{
struct inno_dsidphy *inno = dev_get_priv(phy->dev);
struct phy_configure_opts_mipi_dphy *config = params;
int ret;
ret = phy_mipi_dphy_config_validate(config);
if (ret)
return ret;
memcpy(&inno->dphy_cfg, config, sizeof(inno->dphy_cfg));
return 0;
}
static const struct phy_ops inno_dsidphy_ops = {
.configure = inno_dsidphy_configure,
.power_on = inno_dsidphy_power_on,
.power_off = inno_dsidphy_power_off,
};
static const struct inno_video_phy_plat_data max_1ghz_video_phy_plat_data = {
.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_1ghz,
.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_1ghz),
.max_rate = MAX_1GHZ,
};
static const struct inno_video_phy_plat_data max_2_5ghz_video_phy_plat_data = {
.inno_mipi_dphy_timing_table = inno_mipi_dphy_timing_table_max_2_5ghz,
.num_timings = ARRAY_SIZE(inno_mipi_dphy_timing_table_max_2_5ghz),
.max_rate = MAX_2_5GHZ,
};
static int inno_dsidphy_probe(struct udevice *dev)
{
struct inno_dsidphy *inno = dev_get_priv(dev);
int ret;
inno->dev = dev;
inno->pdata = (const struct inno_video_phy_plat_data *)dev_get_driver_data(dev);
inno->phy_base = dev_read_addr_ptr(dev);
if (IS_ERR(inno->phy_base))
return PTR_ERR(inno->phy_base);
inno->ref_clk = devm_clk_get(dev, "ref");
if (IS_ERR(inno->ref_clk)) {
ret = PTR_ERR(inno->ref_clk);
dev_err(dev, "failed to get ref clock: %d\n", ret);
return ret;
}
inno->pclk_phy = devm_clk_get(dev, "pclk");
if (IS_ERR(inno->pclk_phy)) {
ret = PTR_ERR(inno->pclk_phy);
dev_err(dev, "failed to get phy pclk: %d\n", ret);
return ret;
}
inno->rst = devm_reset_control_get(dev, "apb");
if (IS_ERR(inno->rst)) {
ret = PTR_ERR(inno->rst);
dev_err(dev, "failed to get system reset control: %d\n", ret);
return ret;
}
return 0;
}
static const struct udevice_id inno_dsidphy_of_match[] = {
{
.compatible = "rockchip,px30-dsi-dphy",
.data = (long)&max_1ghz_video_phy_plat_data,
}, {
.compatible = "rockchip,rk3128-dsi-dphy",
.data = (long)&max_1ghz_video_phy_plat_data,
}, {
.compatible = "rockchip,rk3368-dsi-dphy",
.data = (long)&max_1ghz_video_phy_plat_data,
}, {
.compatible = "rockchip,rk3568-dsi-dphy",
.data = (long)&max_2_5ghz_video_phy_plat_data,
},
{}
};
U_BOOT_DRIVER(rockchip_inno_dsidphy) = {
.name = "rockchip-inno-dsidphy",
.id = UCLASS_PHY,
.of_match = inno_dsidphy_of_match,
.probe = inno_dsidphy_probe,
.ops = &inno_dsidphy_ops,
.priv_auto = sizeof(struct inno_dsidphy),
};

View file

@ -15,5 +15,6 @@ obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o
obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o
obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o
obj-$(CONFIG_ROCKCHIP_RK3568) += pinctrl-rk3568.o
obj-$(CONFIG_ROCKCHIP_RK3588) += pinctrl-rk3588.o
obj-$(CONFIG_ROCKCHIP_RV1108) += pinctrl-rv1108.o
obj-$(CONFIG_ROCKCHIP_RV1126) += pinctrl-rv1126.o

View file

@ -13,6 +13,12 @@
#include "pinctrl-rockchip.h"
static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_PMUGRF(RK_GPIO0, RK_PB7, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(1, 0, 0)), /* PWM0 IO mux selection M0 */
MR_PMUGRF(RK_GPIO0, RK_PC7, RK_FUNC_2, 0x0110, RK_GENMASK_VAL(1, 0, 1)), /* PWM0 IO mux selection M1 */
MR_PMUGRF(RK_GPIO0, RK_PC0, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(3, 2, 0)), /* PWM1 IO mux selection M0 */
MR_PMUGRF(RK_GPIO0, RK_PB5, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(3, 2, 1)), /* PWM1 IO mux selection M1 */
MR_PMUGRF(RK_GPIO0, RK_PC1, RK_FUNC_1, 0x0110, RK_GENMASK_VAL(5, 4, 0)), /* PWM2 IO mux selection M0 */
MR_PMUGRF(RK_GPIO0, RK_PB6, RK_FUNC_4, 0x0110, RK_GENMASK_VAL(5, 4, 1)), /* PWM2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PB3, RK_FUNC_2, 0x0300, RK_GENMASK_VAL(0, 0, 0)), /* CAN0 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_4, 0x0300, RK_GENMASK_VAL(0, 0, 1)), /* CAN0 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_3, 0x0300, RK_GENMASK_VAL(2, 2, 0)), /* CAN1 IO mux selection M0 */
@ -33,30 +39,22 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO2, RK_PB1, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(2, 2, 1)), /* I2C4 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB4, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(4, 4, 0)), /* I2C5 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PD0, RK_FUNC_2, 0x0304, RK_GENMASK_VAL(4, 4, 1)), /* I2C5 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 0)), /* PWM4 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(6, 6, 1)), /* PWM4 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 0)), /* PWM5 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(8, 8, 1)), /* PWM5 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 0)), /* PWM6 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(10, 10, 1)), /* PWM6 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 0)), /* PWM7 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(12, 12, 1)), /* PWM7 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB1, RK_FUNC_5, 0x0304, RK_GENMASK_VAL(14, 14, 0)), /* PWM8 IO mux selection M0 */
MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_4, 0x0304, RK_GENMASK_VAL(14, 14, 1)), /* PWM8 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB2, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(0, 0, 0)), /* PWM9 IO mux selection M0 */
MR_TOPGRF(RK_GPIO1, RK_PD6, RK_FUNC_4, 0x0308, RK_GENMASK_VAL(0, 0, 1)), /* PWM9 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(2, 2, 0)), /* PWM10 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PA1, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(2, 2, 1)), /* PWM10 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB6, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(4, 4, 0)), /* PWM11 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC0, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(4, 4, 1)), /* PWM11 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PB7, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(6, 6, 0)), /* PWM12 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(6, 6, 1)), /* PWM12 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PC0, RK_FUNC_2, 0x0308, RK_GENMASK_VAL(8, 8, 0)), /* PWM13 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC6, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(8, 8, 1)), /* PWM13 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 0)), /* PWM14 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(10, 10, 1)), /* PWM14 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PC5, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 0)), /* PWM15 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC3, RK_FUNC_1, 0x0308, RK_GENMASK_VAL(12, 12, 1)), /* PWM15 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_3, 0x0308, RK_GENMASK_VAL(14, 14, 0)), /* SDMMC2 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PA5, RK_FUNC_5, 0x0308, RK_GENMASK_VAL(14, 14, 1)), /* SDMMC2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PB5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(0, 0, 0)), /* SPI0 IO mux selection M0 */
@ -68,7 +66,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO4, RK_PB3, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(6, 6, 0)), /* SPI3 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(6, 6, 1)), /* SPI3 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PB4, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(8, 8, 0)), /* UART1 IO mux selection M0 */
MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_4, 0x030c, RK_GENMASK_VAL(8, 8, 1)), /* UART1 IO mux selection M1 */
MR_TOPGRF(RK_GPIO0, RK_PD1, RK_FUNC_1, 0x030c, RK_GENMASK_VAL(10, 10, 0)), /* UART2 IO mux selection M0 */
MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(10, 10, 1)), /* UART2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA1, RK_FUNC_2, 0x030c, RK_GENMASK_VAL(12, 12, 0)), /* UART3 IO mux selection M0 */
@ -81,7 +79,7 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO1, RK_PD5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(2, 2, 1)), /* UART6 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PA6, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(5, 4, 0)), /* UART7 IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 1)), /* UART7 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PD2, RK_FUNC_1, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
MR_TOPGRF(RK_GPIO4, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(5, 4, 2)), /* UART7 IO mux selection M2 */
MR_TOPGRF(RK_GPIO2, RK_PC5, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(6, 6, 0)), /* UART8 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PD7, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(6, 6, 1)), /* UART8 IO mux selection M1 */
MR_TOPGRF(RK_GPIO2, RK_PB0, RK_FUNC_3, 0x0310, RK_GENMASK_VAL(9, 8, 0)), /* UART9 IO mux selection M0 */
@ -94,8 +92,11 @@ static struct rockchip_mux_route_data rk3568_mux_route_data[] = {
MR_TOPGRF(RK_GPIO4, RK_PB6, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(12, 12, 1)), /* I2S2 IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PA2, RK_FUNC_4, 0x0310, RK_GENMASK_VAL(14, 14, 0)), /* I2S3 IO mux selection M0 */
MR_TOPGRF(RK_GPIO4, RK_PC2, RK_FUNC_5, 0x0310, RK_GENMASK_VAL(14, 14, 1)), /* I2S3 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(0, 0, 0)), /* PDM IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(0, 0, 1)), /* PDM IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PA4, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
MR_TOPGRF(RK_GPIO1, RK_PA6, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(1, 0, 0)), /* PDM IO mux selection M0 */
MR_TOPGRF(RK_GPIO3, RK_PD6, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
MR_TOPGRF(RK_GPIO4, RK_PA0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(1, 0, 1)), /* PDM IO mux selection M1 */
MR_TOPGRF(RK_GPIO3, RK_PC4, RK_FUNC_5, 0x0314, RK_GENMASK_VAL(1, 0, 2)), /* PDM IO mux selection M2 */
MR_TOPGRF(RK_GPIO0, RK_PA5, RK_FUNC_3, 0x0314, RK_GENMASK_VAL(3, 2, 0)), /* PCIE20 IO mux selection M0 */
MR_TOPGRF(RK_GPIO2, RK_PD0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 1)), /* PCIE20 IO mux selection M1 */
MR_TOPGRF(RK_GPIO1, RK_PB0, RK_FUNC_4, 0x0314, RK_GENMASK_VAL(3, 2, 2)), /* PCIE20 IO mux selection M2 */
@ -237,6 +238,15 @@ static int rk3568_set_pull(struct rockchip_pin_bank *bank,
return ret;
}
/*
* In the TRM, pull-up being 1 for everything except the GPIO0_D3-D6,
* where that pull up value becomes 3.
*/
if (bank->bank_num == 0 && pin_num >= 27 && pin_num <= 30) {
if (ret == 1)
ret = 3;
}
/* enable the write to the equivalent lower bits */
data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);

View file

@ -0,0 +1,353 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2021 Rockchip Electronics Co., Ltd
*/
#include <common.h>
#include <dm.h>
#include <dm/pinctrl.h>
#include <regmap.h>
#include <syscon.h>
#include "pinctrl-rockchip.h"
#include <dt-bindings/pinctrl/rockchip.h>
static int rk3588_set_mux(struct rockchip_pin_bank *bank, int pin, int mux)
{
struct rockchip_pinctrl_priv *priv = bank->priv;
struct regmap *regmap;
int iomux_num = (pin / 8);
int reg, ret, mask;
u8 bit;
u32 data;
debug("setting mux of GPIO%d-%d to %d\n", bank->bank_num, pin, mux);
regmap = priv->regmap_base;
reg = bank->iomux[iomux_num].offset;
if ((pin % 8) >= 4)
reg += 0x4;
bit = (pin % 4) * 4;
mask = 0xf;
if (bank->bank_num == 0) {
if (pin >= RK_PB4 && pin <= RK_PD7) {
if (mux < 8) {
reg += 0x4000 - 0xC; /* PMU2_IOC_BASE */
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
} else {
u32 reg0 = 0;
reg0 = reg + 0x4000 - 0xC; /* PMU2_IOC_BASE */
data = (mask << (bit + 16));
data |= 8 << bit;
ret = regmap_write(regmap, reg0, data);
reg0 = reg + 0x8000; /* BUS_IOC_BASE */
data = (mask << (bit + 16));
data |= mux << bit;
regmap = priv->regmap_base;
regmap_write(regmap, reg0, data);
}
} else {
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
ret = regmap_write(regmap, reg, data);
}
return ret;
} else if (bank->bank_num > 0) {
reg += 0x8000; /* BUS_IOC_BASE */
}
data = (mask << (bit + 16));
data |= (mux & mask) << bit;
return regmap_write(regmap, reg, data);
}
#define RK3588_PMU1_IOC_REG (0x0000)
#define RK3588_PMU2_IOC_REG (0x4000)
#define RK3588_BUS_IOC_REG (0x8000)
#define RK3588_VCCIO1_4_IOC_REG (0x9000)
#define RK3588_VCCIO3_5_IOC_REG (0xA000)
#define RK3588_VCCIO2_IOC_REG (0xB000)
#define RK3588_VCCIO6_IOC_REG (0xC000)
#define RK3588_EMMC_IOC_REG (0xD000)
static const u32 rk3588_ds_regs[][2] = {
{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0010},
{RK_GPIO0_A4, RK3588_PMU1_IOC_REG + 0x0014},
{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0018},
{RK_GPIO0_B4, RK3588_PMU2_IOC_REG + 0x0014},
{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0018},
{RK_GPIO0_C4, RK3588_PMU2_IOC_REG + 0x001C},
{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0020},
{RK_GPIO0_D4, RK3588_PMU2_IOC_REG + 0x0024},
{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0020},
{RK_GPIO1_A4, RK3588_VCCIO1_4_IOC_REG + 0x0024},
{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0028},
{RK_GPIO1_B4, RK3588_VCCIO1_4_IOC_REG + 0x002C},
{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0030},
{RK_GPIO1_C4, RK3588_VCCIO1_4_IOC_REG + 0x0034},
{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x0038},
{RK_GPIO1_D4, RK3588_VCCIO1_4_IOC_REG + 0x003C},
{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0040},
{RK_GPIO2_A4, RK3588_VCCIO3_5_IOC_REG + 0x0044},
{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0048},
{RK_GPIO2_B4, RK3588_VCCIO3_5_IOC_REG + 0x004C},
{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0050},
{RK_GPIO2_C4, RK3588_VCCIO3_5_IOC_REG + 0x0054},
{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x0058},
{RK_GPIO2_D4, RK3588_EMMC_IOC_REG + 0x005C},
{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0060},
{RK_GPIO3_A4, RK3588_VCCIO3_5_IOC_REG + 0x0064},
{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0068},
{RK_GPIO3_B4, RK3588_VCCIO3_5_IOC_REG + 0x006C},
{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0070},
{RK_GPIO3_C4, RK3588_VCCIO3_5_IOC_REG + 0x0074},
{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x0078},
{RK_GPIO3_D4, RK3588_VCCIO3_5_IOC_REG + 0x007C},
{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0080},
{RK_GPIO4_A4, RK3588_VCCIO6_IOC_REG + 0x0084},
{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0088},
{RK_GPIO4_B4, RK3588_VCCIO6_IOC_REG + 0x008C},
{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0090},
{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0090},
{RK_GPIO4_C4, RK3588_VCCIO3_5_IOC_REG + 0x0094},
{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x0098},
{RK_GPIO4_D4, RK3588_VCCIO2_IOC_REG + 0x009C},
};
static const u32 rk3588_p_regs[][2] = {
{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0020},
{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0024},
{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0028},
{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x002C},
{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0030},
{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0110},
{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0114},
{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0118},
{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x011C},
{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0120},
{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0120},
{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0124},
{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0128},
{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x012C},
{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0130},
{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0134},
{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0138},
{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x013C},
{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0140},
{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0144},
{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0148},
{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0148},
{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x014C},
};
static const u32 rk3588_smt_regs[][2] = {
{RK_GPIO0_A0, RK3588_PMU1_IOC_REG + 0x0030},
{RK_GPIO0_B0, RK3588_PMU1_IOC_REG + 0x0034},
{RK_GPIO0_B5, RK3588_PMU2_IOC_REG + 0x0040},
{RK_GPIO0_C0, RK3588_PMU2_IOC_REG + 0x0044},
{RK_GPIO0_D0, RK3588_PMU2_IOC_REG + 0x0048},
{RK_GPIO1_A0, RK3588_VCCIO1_4_IOC_REG + 0x0210},
{RK_GPIO1_B0, RK3588_VCCIO1_4_IOC_REG + 0x0214},
{RK_GPIO1_C0, RK3588_VCCIO1_4_IOC_REG + 0x0218},
{RK_GPIO1_D0, RK3588_VCCIO1_4_IOC_REG + 0x021C},
{RK_GPIO2_A0, RK3588_EMMC_IOC_REG + 0x0220},
{RK_GPIO2_A6, RK3588_VCCIO3_5_IOC_REG + 0x0220},
{RK_GPIO2_B0, RK3588_VCCIO3_5_IOC_REG + 0x0224},
{RK_GPIO2_C0, RK3588_VCCIO3_5_IOC_REG + 0x0228},
{RK_GPIO2_D0, RK3588_EMMC_IOC_REG + 0x022C},
{RK_GPIO3_A0, RK3588_VCCIO3_5_IOC_REG + 0x0230},
{RK_GPIO3_B0, RK3588_VCCIO3_5_IOC_REG + 0x0234},
{RK_GPIO3_C0, RK3588_VCCIO3_5_IOC_REG + 0x0238},
{RK_GPIO3_D0, RK3588_VCCIO3_5_IOC_REG + 0x023C},
{RK_GPIO4_A0, RK3588_VCCIO6_IOC_REG + 0x0240},
{RK_GPIO4_B0, RK3588_VCCIO6_IOC_REG + 0x0244},
{RK_GPIO4_C0, RK3588_VCCIO6_IOC_REG + 0x0248},
{RK_GPIO4_C2, RK3588_VCCIO3_5_IOC_REG + 0x0248},
{RK_GPIO4_D0, RK3588_VCCIO2_IOC_REG + 0x024C},
};
#define RK3588_PULL_BITS_PER_PIN 2
#define RK3588_PULL_PINS_PER_REG 8
static void rk3588_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
struct rockchip_pinctrl_priv *info = bank->priv;
u8 bank_num = bank->bank_num;
u32 pin = bank_num * 32 + pin_num;
int i;
for (i = ARRAY_SIZE(rk3588_p_regs) - 1; i >= 0; i--) {
if (pin >= rk3588_p_regs[i][0]) {
*reg = rk3588_p_regs[i][1];
break;
}
}
assert(i >= 0);
*regmap = info->regmap_base;
*bit = pin_num % RK3588_PULL_PINS_PER_REG;
*bit *= RK3588_PULL_BITS_PER_PIN;
}
#define RK3588_DRV_BITS_PER_PIN 4
#define RK3588_DRV_PINS_PER_REG 4
static void rk3588_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
struct rockchip_pinctrl_priv *info = bank->priv;
u8 bank_num = bank->bank_num;
u32 pin = bank_num * 32 + pin_num;
int i;
for (i = ARRAY_SIZE(rk3588_ds_regs) - 1; i >= 0; i--) {
if (pin >= rk3588_ds_regs[i][0]) {
*reg = rk3588_ds_regs[i][1];
break;
}
}
assert(i >= 0);
*regmap = info->regmap_base;
*bit = pin_num % RK3588_DRV_PINS_PER_REG;
*bit *= RK3588_DRV_BITS_PER_PIN;
}
#define RK3588_SMT_BITS_PER_PIN 1
#define RK3588_SMT_PINS_PER_REG 8
static int rk3588_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank,
int pin_num, struct regmap **regmap,
int *reg, u8 *bit)
{
struct rockchip_pinctrl_priv *info = bank->priv;
u8 bank_num = bank->bank_num;
u32 pin = bank_num * 32 + pin_num;
int i;
for (i = ARRAY_SIZE(rk3588_smt_regs) - 1; i >= 0; i--) {
if (pin >= rk3588_smt_regs[i][0]) {
*reg = rk3588_smt_regs[i][1];
break;
}
}
assert(i >= 0);
*regmap = info->regmap_base;
*bit = pin_num % RK3588_SMT_PINS_PER_REG;
*bit *= RK3588_SMT_BITS_PER_PIN;
return 0;
}
static int rk3588_set_pull(struct rockchip_pin_bank *bank,
int pin_num, int pull)
{
struct regmap *regmap;
int reg, translated_pull;
u8 bit, type;
u32 data;
rk3588_calc_pull_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
type = bank->pull_type[pin_num / 8];
translated_pull = rockchip_translate_pull_value(type, pull);
if (translated_pull < 0) {
debug("unsupported pull setting %d\n", pull);
return -EINVAL;
}
/* enable the write to the equivalent lower bits */
data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16);
data |= (translated_pull << bit);
return regmap_write(regmap, reg, data);
}
static int rk3588_set_drive(struct rockchip_pin_bank *bank,
int pin_num, int strength)
{
struct regmap *regmap;
int reg;
u32 data;
u8 bit;
rk3588_calc_drv_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
/* enable the write to the equivalent lower bits */
data = ((1 << RK3588_DRV_BITS_PER_PIN) - 1) << (bit + 16);
data |= (strength << bit);
return regmap_write(regmap, reg, data);
}
static int rk3588_set_schmitt(struct rockchip_pin_bank *bank,
int pin_num, int enable)
{
struct regmap *regmap;
int reg;
u32 data;
u8 bit;
rk3588_calc_schmitt_reg_and_bit(bank, pin_num, &regmap, &reg, &bit);
/* enable the write to the equivalent lower bits */
data = ((1 << RK3588_SMT_BITS_PER_PIN) - 1) << (bit + 16);
data |= (enable << bit);
return regmap_write(regmap, reg, data);
}
static struct rockchip_pin_bank rk3588_pin_banks[] = {
RK3588_PIN_BANK_FLAGS(0, 32, "gpio0",
IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
RK3588_PIN_BANK_FLAGS(1, 32, "gpio1",
IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
RK3588_PIN_BANK_FLAGS(2, 32, "gpio2",
IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
RK3588_PIN_BANK_FLAGS(3, 32, "gpio3",
IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
RK3588_PIN_BANK_FLAGS(4, 32, "gpio4",
IOMUX_WIDTH_4BIT, PULL_TYPE_IO_1V8_ONLY),
};
static const struct rockchip_pin_ctrl rk3588_pin_ctrl = {
.pin_banks = rk3588_pin_banks,
.nr_banks = ARRAY_SIZE(rk3588_pin_banks),
.nr_pins = 160,
.set_mux = rk3588_set_mux,
.set_pull = rk3588_set_pull,
.set_drive = rk3588_set_drive,
.set_schmitt = rk3588_set_schmitt,
};
static const struct udevice_id rk3588_pinctrl_ids[] = {
{
.compatible = "rockchip,rk3588-pinctrl",
.data = (ulong)&rk3588_pin_ctrl
},
{ }
};
U_BOOT_DRIVER(pinctrl_rk3588) = {
.name = "rockchip_rk3588_pinctrl",
.id = UCLASS_PINCTRL,
.of_match = rk3588_pinctrl_ids,
.priv_auto = sizeof(struct rockchip_pinctrl_priv),
.ops = &rockchip_pinctrl_ops,
#if CONFIG_IS_ENABLED(OF_REAL)
.bind = dm_scan_fdt_dev,
#endif
.probe = rockchip_pinctrl_probe,
};

View file

@ -9,6 +9,171 @@
#include <linux/bitops.h>
#include <linux/types.h>
#define RK_GPIO0_A0 0
#define RK_GPIO0_A1 1
#define RK_GPIO0_A2 2
#define RK_GPIO0_A3 3
#define RK_GPIO0_A4 4
#define RK_GPIO0_A5 5
#define RK_GPIO0_A6 6
#define RK_GPIO0_A7 7
#define RK_GPIO0_B0 8
#define RK_GPIO0_B1 9
#define RK_GPIO0_B2 10
#define RK_GPIO0_B3 11
#define RK_GPIO0_B4 12
#define RK_GPIO0_B5 13
#define RK_GPIO0_B6 14
#define RK_GPIO0_B7 15
#define RK_GPIO0_C0 16
#define RK_GPIO0_C1 17
#define RK_GPIO0_C2 18
#define RK_GPIO0_C3 19
#define RK_GPIO0_C4 20
#define RK_GPIO0_C5 21
#define RK_GPIO0_C6 22
#define RK_GPIO0_C7 23
#define RK_GPIO0_D0 24
#define RK_GPIO0_D1 25
#define RK_GPIO0_D2 26
#define RK_GPIO0_D3 27
#define RK_GPIO0_D4 28
#define RK_GPIO0_D5 29
#define RK_GPIO0_D6 30
#define RK_GPIO0_D7 31
#define RK_GPIO1_A0 32
#define RK_GPIO1_A1 33
#define RK_GPIO1_A2 34
#define RK_GPIO1_A3 35
#define RK_GPIO1_A4 36
#define RK_GPIO1_A5 37
#define RK_GPIO1_A6 38
#define RK_GPIO1_A7 39
#define RK_GPIO1_B0 40
#define RK_GPIO1_B1 41
#define RK_GPIO1_B2 42
#define RK_GPIO1_B3 43
#define RK_GPIO1_B4 44
#define RK_GPIO1_B5 45
#define RK_GPIO1_B6 46
#define RK_GPIO1_B7 47
#define RK_GPIO1_C0 48
#define RK_GPIO1_C1 49
#define RK_GPIO1_C2 50
#define RK_GPIO1_C3 51
#define RK_GPIO1_C4 52
#define RK_GPIO1_C5 53
#define RK_GPIO1_C6 54
#define RK_GPIO1_C7 55
#define RK_GPIO1_D0 56
#define RK_GPIO1_D1 57
#define RK_GPIO1_D2 58
#define RK_GPIO1_D3 59
#define RK_GPIO1_D4 60
#define RK_GPIO1_D5 61
#define RK_GPIO1_D6 62
#define RK_GPIO1_D7 63
#define RK_GPIO2_A0 64
#define RK_GPIO2_A1 65
#define RK_GPIO2_A2 66
#define RK_GPIO2_A3 67
#define RK_GPIO2_A4 68
#define RK_GPIO2_A5 69
#define RK_GPIO2_A6 70
#define RK_GPIO2_A7 71
#define RK_GPIO2_B0 72
#define RK_GPIO2_B1 73
#define RK_GPIO2_B2 74
#define RK_GPIO2_B3 75
#define RK_GPIO2_B4 76
#define RK_GPIO2_B5 77
#define RK_GPIO2_B6 78
#define RK_GPIO2_B7 79
#define RK_GPIO2_C0 80
#define RK_GPIO2_C1 81
#define RK_GPIO2_C2 82
#define RK_GPIO2_C3 83
#define RK_GPIO2_C4 84
#define RK_GPIO2_C5 85
#define RK_GPIO2_C6 86
#define RK_GPIO2_C7 87
#define RK_GPIO2_D0 88
#define RK_GPIO2_D1 89
#define RK_GPIO2_D2 90
#define RK_GPIO2_D3 91
#define RK_GPIO2_D4 92
#define RK_GPIO2_D5 93
#define RK_GPIO2_D6 94
#define RK_GPIO2_D7 95
#define RK_GPIO3_A0 96
#define RK_GPIO3_A1 97
#define RK_GPIO3_A2 98
#define RK_GPIO3_A3 99
#define RK_GPIO3_A4 100
#define RK_GPIO3_A5 101
#define RK_GPIO3_A6 102
#define RK_GPIO3_A7 103
#define RK_GPIO3_B0 104
#define RK_GPIO3_B1 105
#define RK_GPIO3_B2 106
#define RK_GPIO3_B3 107
#define RK_GPIO3_B4 108
#define RK_GPIO3_B5 109
#define RK_GPIO3_B6 110
#define RK_GPIO3_B7 111
#define RK_GPIO3_C0 112
#define RK_GPIO3_C1 113
#define RK_GPIO3_C2 114
#define RK_GPIO3_C3 115
#define RK_GPIO3_C4 116
#define RK_GPIO3_C5 117
#define RK_GPIO3_C6 118
#define RK_GPIO3_C7 119
#define RK_GPIO3_D0 120
#define RK_GPIO3_D1 121
#define RK_GPIO3_D2 122
#define RK_GPIO3_D3 123
#define RK_GPIO3_D4 124
#define RK_GPIO3_D5 125
#define RK_GPIO3_D6 126
#define RK_GPIO3_D7 127
#define RK_GPIO4_A0 128
#define RK_GPIO4_A1 129
#define RK_GPIO4_A2 130
#define RK_GPIO4_A3 131
#define RK_GPIO4_A4 132
#define RK_GPIO4_A5 133
#define RK_GPIO4_A6 134
#define RK_GPIO4_A7 135
#define RK_GPIO4_B0 136
#define RK_GPIO4_B1 137
#define RK_GPIO4_B2 138
#define RK_GPIO4_B3 139
#define RK_GPIO4_B4 140
#define RK_GPIO4_B5 141
#define RK_GPIO4_B6 142
#define RK_GPIO4_B7 143
#define RK_GPIO4_C0 144
#define RK_GPIO4_C1 145
#define RK_GPIO4_C2 146
#define RK_GPIO4_C3 147
#define RK_GPIO4_C4 148
#define RK_GPIO4_C5 149
#define RK_GPIO4_C6 150
#define RK_GPIO4_C7 151
#define RK_GPIO4_D0 152
#define RK_GPIO4_D1 153
#define RK_GPIO4_D2 154
#define RK_GPIO4_D3 155
#define RK_GPIO4_D4 156
#define RK_GPIO4_D5 157
#define RK_GPIO4_D6 158
#define RK_GPIO4_D7 159
#define RK_GENMASK_VAL(h, l, v) \
(GENMASK(((h) + 16), ((l) + 16)) | (((v) << (l)) & GENMASK((h), (l))))
@ -180,6 +345,25 @@ struct rockchip_pin_bank {
}, \
}
#define PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(id, pins, label, iom0, iom1, \
iom2, iom3, pull0, pull1, \
pull2, pull3) \
{ \
.bank_num = id, \
.nr_pins = pins, \
.name = label, \
.iomux = { \
{ .type = iom0, .offset = -1 }, \
{ .type = iom1, .offset = -1 }, \
{ .type = iom2, .offset = -1 }, \
{ .type = iom3, .offset = -1 }, \
}, \
.pull_type[0] = pull0, \
.pull_type[1] = pull1, \
.pull_type[2] = pull2, \
.pull_type[3] = pull3, \
}
#define PIN_BANK_DRV_FLAGS_PULL_FLAGS(id, pins, label, drv0, drv1, \
drv2, drv3, pull0, pull1, \
pull2, pull3) \
@ -274,6 +458,9 @@ struct rockchip_pin_bank {
#define MR_PMUGRF(ID, PIN, FUNC, REG, VAL) \
PIN_BANK_MUX_ROUTE_FLAGS(ID, PIN, FUNC, REG, VAL, ROUTE_TYPE_PMUGRF)
#define RK3588_PIN_BANK_FLAGS(ID, PIN, LABEL, M, P) \
PIN_BANK_IOMUX_FLAGS_PULL_FLAGS(ID, PIN, LABEL, M, M, M, M, P, P, P, P)
/**
* struct rockchip_mux_recalced_data: recalculate a pin iomux data.
* @num: bank number.

View file

@ -2749,6 +2749,8 @@ static u64 dram_detect_cap(struct dram_info *dram,
/* detect cs1 row */
sdram_detect_cs1_row(cap_info, params->base.dramtype);
sdram_detect_high_row(cap_info);
/* detect die bw */
sdram_detect_dbw(cap_info, params->base.dramtype);

View file

@ -58,8 +58,9 @@ config RNG_ROCKCHIP
bool "Enable random number generator for rockchip crypto rng"
depends on ARCH_ROCKCHIP && DM_RNG
help
Enable random number generator for rockchip.This driver is
support rng module of crypto v1 and crypto v2.
Enable random number generator for rockchip. This driver
supports the rng module of crypto v1, crypto v2, and the
trng module of the rk3588 series.
config RNG_IPROC200
bool "Broadcom iProc RNG200 random number generator"

View file

@ -43,9 +43,41 @@
#define CRYPTO_V2_RNG_DOUT_0 0x0410
/* end of CRYPTO V2 register define */
/* start of TRNG V1 register define */
#define TRNG_V1_CTRL 0x0000
#define TRNG_V1_CTRL_NOP _SBF(0, 0x00)
#define TRNG_V1_CTRL_RAND _SBF(0, 0x01)
#define TRNG_V1_CTRL_SEED _SBF(0, 0x02)
#define TRNG_V1_MODE 0x0008
#define TRNG_V1_MODE_128_BIT _SBF(3, 0x00)
#define TRNG_V1_MODE_256_BIT _SBF(3, 0x01)
#define TRNG_V1_IE 0x0010
#define TRNG_V1_IE_GLBL_EN BIT(31)
#define TRNG_V1_IE_SEED_DONE_EN BIT(1)
#define TRNG_V1_IE_RAND_RDY_EN BIT(0)
#define TRNG_V1_ISTAT 0x0014
#define TRNG_V1_ISTAT_RAND_RDY BIT(0)
/* RAND0 ~ RAND7 */
#define TRNG_V1_RAND0 0x0020
#define TRNG_V1_RAND7 0x003C
#define TRNG_V1_AUTO_RQSTS 0x0060
#define TRNG_V1_VERSION 0x00F0
#define TRNG_v1_VERSION_CODE 0x46BC
/* end of TRNG V1 register define */
#define RK_RNG_TIME_OUT 50000 /* max 50ms */
#define trng_write(pdata, pos, val) writel(val, (pdata)->base + (pos))
#define trng_read(pdata, pos) readl((pdata)->base + (pos))
struct rk_rng_soc_data {
int (*rk_rng_init)(struct udevice *dev);
int (*rk_rng_read)(struct udevice *dev, void *data, size_t len);
};
@ -75,7 +107,7 @@ static int rk_rng_read_regs(fdt_addr_t addr, void *buf, size_t size)
return 0;
}
static int rk_v1_rng_read(struct udevice *dev, void *data, size_t len)
static int rk_cryptov1_rng_read(struct udevice *dev, void *data, size_t len)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
u32 reg = 0;
@ -106,7 +138,7 @@ exit:
return 0;
}
static int rk_v2_rng_read(struct udevice *dev, void *data, size_t len)
static int rk_cryptov2_rng_read(struct udevice *dev, void *data, size_t len)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
u32 reg = 0;
@ -140,6 +172,63 @@ exit:
return retval;
}
static int rk_trngv1_init(struct udevice *dev)
{
u32 status, version;
u32 auto_reseed_cnt = 1000;
struct rk_rng_plat *pdata = dev_get_priv(dev);
version = trng_read(pdata, TRNG_V1_VERSION);
if (version != TRNG_v1_VERSION_CODE) {
printf("wrong trng version, expected = %08x, actual = %08x",
TRNG_V1_VERSION, version);
return -EFAULT;
}
/* wait in case of RND_RDY triggered at firs power on */
readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, status,
(status & TRNG_V1_ISTAT_RAND_RDY),
RK_RNG_TIME_OUT);
/* clear RAND_RDY flag for first power on */
trng_write(pdata, TRNG_V1_ISTAT, status);
/* auto reseed after (auto_reseed_cnt * 16) byte rand generate */
trng_write(pdata, TRNG_V1_AUTO_RQSTS, auto_reseed_cnt);
return 0;
}
static int rk_trngv1_rng_read(struct udevice *dev, void *data, size_t len)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
u32 reg = 0;
int retval;
if (len > RK_HW_RNG_MAX)
return -EINVAL;
trng_write(pdata, TRNG_V1_MODE, TRNG_V1_MODE_256_BIT);
trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_RAND);
retval = readl_poll_timeout(pdata->base + TRNG_V1_ISTAT, reg,
(reg & TRNG_V1_ISTAT_RAND_RDY),
RK_RNG_TIME_OUT);
/* clear ISTAT */
trng_write(pdata, TRNG_V1_ISTAT, reg);
if (retval)
goto exit;
rk_rng_read_regs(pdata->base + TRNG_V1_RAND0, data, len);
exit:
/* close TRNG */
trng_write(pdata, TRNG_V1_CTRL, TRNG_V1_CTRL_NOP);
return retval;
}
static int rockchip_rng_read(struct udevice *dev, void *data, size_t len)
{
unsigned char *buf = data;
@ -184,18 +273,27 @@ static int rockchip_rng_of_to_plat(struct udevice *dev)
static int rockchip_rng_probe(struct udevice *dev)
{
struct rk_rng_plat *pdata = dev_get_priv(dev);
int ret = 0;
pdata->soc_data = (struct rk_rng_soc_data *)dev_get_driver_data(dev);
return 0;
if (pdata->soc_data->rk_rng_init)
ret = pdata->soc_data->rk_rng_init(dev);
return ret;
}
static const struct rk_rng_soc_data rk_rng_v1_soc_data = {
.rk_rng_read = rk_v1_rng_read,
static const struct rk_rng_soc_data rk_cryptov1_soc_data = {
.rk_rng_read = rk_cryptov1_rng_read,
};
static const struct rk_rng_soc_data rk_rng_v2_soc_data = {
.rk_rng_read = rk_v2_rng_read,
static const struct rk_rng_soc_data rk_cryptov2_soc_data = {
.rk_rng_read = rk_cryptov2_rng_read,
};
static const struct rk_rng_soc_data rk_trngv1_soc_data = {
.rk_rng_init = rk_trngv1_init,
.rk_rng_read = rk_trngv1_rng_read,
};
static const struct dm_rng_ops rockchip_rng_ops = {
@ -205,11 +303,15 @@ static const struct dm_rng_ops rockchip_rng_ops = {
static const struct udevice_id rockchip_rng_match[] = {
{
.compatible = "rockchip,cryptov1-rng",
.data = (ulong)&rk_rng_v1_soc_data,
.data = (ulong)&rk_cryptov1_soc_data,
},
{
.compatible = "rockchip,cryptov2-rng",
.data = (ulong)&rk_rng_v2_soc_data,
.data = (ulong)&rk_cryptov2_soc_data,
},
{
.compatible = "rockchip,trngv1",
.data = (ulong)&rk_trngv1_soc_data,
},
{},
};

View file

@ -806,6 +806,15 @@ static int dw_mipi_dsi_init(struct udevice *dev,
return -EINVAL;
}
/*
* The Rockchip based devices don't have px_clk, so simply move
* on.
*/
if (IS_ENABLED(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI)) {
dw_mipi_dsi_bridge_set(dsi, timings);
return 0;
}
ret = clk_get_by_name(device->dev, "px_clk", &clk);
if (ret) {
dev_err(device->dev, "peripheral clock get error %d\n", ret);

View file

@ -69,4 +69,12 @@ config DISPLAY_ROCKCHIP_MIPI
support. The mipi controller and dphy on rk3288& rk3399 support
16,18, 24 bits per pixel with up to 2k resolution ratio.
config DISPLAY_ROCKCHIP_DW_MIPI
bool "Rockchip Designware MIPI"
depends on VIDEO_ROCKCHIP
select VIDEO_DW_MIPI_DSI
help
Select the Designware MIPI DSI controller in use on some Rockchip
SOCs.
endif

View file

@ -15,4 +15,5 @@ obj-$(CONFIG_DISPLAY_ROCKCHIP_HDMI) += rk_hdmi.o $(obj-hdmi-y)
obj-mipi-$(CONFIG_ROCKCHIP_RK3288) += rk3288_mipi.o
obj-mipi-$(CONFIG_ROCKCHIP_RK3399) += rk3399_mipi.o
obj-$(CONFIG_DISPLAY_ROCKCHIP_MIPI) += rk_mipi.o $(obj-mipi-y)
obj-$(CONFIG_DISPLAY_ROCKCHIP_DW_MIPI) += dw_mipi_dsi_rockchip.o
endif

View file

@ -0,0 +1,898 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Author(s): Chris Morgan <macromorgan@hotmail.com>
*
* This MIPI DSI controller driver is heavily based on the Linux Kernel
* driver from drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c and the
* U-Boot driver from drivers/video/stm32/stm32_dsi.c.
*/
#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
#include <clk.h>
#include <dm.h>
#include <div64.h>
#include <dsi_host.h>
#include <generic-phy.h>
#include <mipi_dsi.h>
#include <panel.h>
#include <phy-mipi-dphy.h>
#include <reset.h>
#include <video_bridge.h>
#include <dm/device_compat.h>
#include <dm/lists.h>
#include <linux/iopoll.h>
#include <common.h>
#include <log.h>
#include <video.h>
#include <asm/io.h>
#include <dm/device-internal.h>
#include <linux/bitops.h>
#define USEC_PER_SEC 1000000L
/*
* DSI wrapper registers & bit definitions
* Note: registers are named as in the Reference Manual
*/
#define DSI_WCR 0x0404 /* Wrapper Control Reg */
#define WCR_DSIEN BIT(3) /* DSI ENable */
#define DSI_PHY_TST_CTRL0 0xb4
#define PHY_TESTCLK BIT(1)
#define PHY_UNTESTCLK 0
#define PHY_TESTCLR BIT(0)
#define PHY_UNTESTCLR 0
#define DSI_PHY_TST_CTRL1 0xb8
#define PHY_TESTEN BIT(16)
#define PHY_UNTESTEN 0
#define PHY_TESTDOUT(n) (((n) & 0xff) << 8)
#define PHY_TESTDIN(n) (((n) & 0xff) << 0)
#define BYPASS_VCO_RANGE BIT(7)
#define VCO_RANGE_CON_SEL(val) (((val) & 0x7) << 3)
#define VCO_IN_CAP_CON_DEFAULT (0x0 << 1)
#define VCO_IN_CAP_CON_LOW (0x1 << 1)
#define VCO_IN_CAP_CON_HIGH (0x2 << 1)
#define REF_BIAS_CUR_SEL BIT(0)
#define CP_CURRENT_3UA 0x1
#define CP_CURRENT_4_5UA 0x2
#define CP_CURRENT_7_5UA 0x6
#define CP_CURRENT_6UA 0x9
#define CP_CURRENT_12UA 0xb
#define CP_CURRENT_SEL(val) ((val) & 0xf)
#define CP_PROGRAM_EN BIT(7)
#define LPF_RESISTORS_15_5KOHM 0x1
#define LPF_RESISTORS_13KOHM 0x2
#define LPF_RESISTORS_11_5KOHM 0x4
#define LPF_RESISTORS_10_5KOHM 0x8
#define LPF_RESISTORS_8KOHM 0x10
#define LPF_PROGRAM_EN BIT(6)
#define LPF_RESISTORS_SEL(val) ((val) & 0x3f)
#define HSFREQRANGE_SEL(val) (((val) & 0x3f) << 1)
#define INPUT_DIVIDER(val) (((val) - 1) & 0x7f)
#define LOW_PROGRAM_EN 0
#define HIGH_PROGRAM_EN BIT(7)
#define LOOP_DIV_LOW_SEL(val) (((val) - 1) & 0x1f)
#define LOOP_DIV_HIGH_SEL(val) ((((val) - 1) >> 5) & 0xf)
#define PLL_LOOP_DIV_EN BIT(5)
#define PLL_INPUT_DIV_EN BIT(4)
#define POWER_CONTROL BIT(6)
#define INTERNAL_REG_CURRENT BIT(3)
#define BIAS_BLOCK_ON BIT(2)
#define BANDGAP_ON BIT(0)
#define TER_RESISTOR_HIGH BIT(7)
#define TER_RESISTOR_LOW 0
#define LEVEL_SHIFTERS_ON BIT(6)
#define TER_CAL_DONE BIT(5)
#define SETRD_MAX (0x7 << 2)
#define POWER_MANAGE BIT(1)
#define TER_RESISTORS_ON BIT(0)
#define BIASEXTR_SEL(val) ((val) & 0x7)
#define BANDGAP_SEL(val) ((val) & 0x7)
#define TLP_PROGRAM_EN BIT(7)
#define THS_PRE_PROGRAM_EN BIT(7)
#define THS_ZERO_PROGRAM_EN BIT(6)
#define PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL 0x10
#define PLL_CP_CONTROL_PLL_LOCK_BYPASS 0x11
#define PLL_LPF_AND_CP_CONTROL 0x12
#define PLL_INPUT_DIVIDER_RATIO 0x17
#define PLL_LOOP_DIVIDER_RATIO 0x18
#define PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL 0x19
#define BANDGAP_AND_BIAS_CONTROL 0x20
#define TERMINATION_RESISTER_CONTROL 0x21
#define AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY 0x22
#define HS_RX_CONTROL_OF_LANE_CLK 0x34
#define HS_RX_CONTROL_OF_LANE_0 0x44
#define HS_RX_CONTROL_OF_LANE_1 0x54
#define HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL 0x60
#define HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL 0x61
#define HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL 0x62
#define HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL 0x63
#define HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL 0x64
#define HS_TX_CLOCK_LANE_POST_TIME_CONTROL 0x65
#define HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL 0x70
#define HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL 0x71
#define HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL 0x72
#define HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL 0x73
#define HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL 0x74
#define HS_RX_DATA_LANE_THS_SETTLE_CONTROL 0x75
#define HS_RX_CONTROL_OF_LANE_2 0x84
#define HS_RX_CONTROL_OF_LANE_3 0x94
#define RK3568_GRF_VO_CON2 0x0368
#define RK3568_DSI0_SKEWCALHS (0x1f << 11)
#define RK3568_DSI0_FORCETXSTOPMODE (0xf << 4)
#define RK3568_DSI0_TURNDISABLE BIT(2)
#define RK3568_DSI0_FORCERXMODE BIT(0)
/*
* Note these registers do not appear in the datasheet, they are
* however present in the BSP driver which is where these values
* come from. Name GRF_VO_CON3 is assumed.
*/
#define RK3568_GRF_VO_CON3 0x36c
#define RK3568_DSI1_SKEWCALHS (0x1f << 11)
#define RK3568_DSI1_FORCETXSTOPMODE (0xf << 4)
#define RK3568_DSI1_TURNDISABLE BIT(2)
#define RK3568_DSI1_FORCERXMODE BIT(0)
#define HIWORD_UPDATE(val, mask) (val | (mask) << 16)
/* Timeout for regulator on/off, pll lock/unlock & fifo empty */
#define TIMEOUT_US 200000
enum {
BANDGAP_97_07,
BANDGAP_98_05,
BANDGAP_99_02,
BANDGAP_100_00,
BANDGAP_93_17,
BANDGAP_94_15,
BANDGAP_95_12,
BANDGAP_96_10,
};
enum {
BIASEXTR_87_1,
BIASEXTR_91_5,
BIASEXTR_95_9,
BIASEXTR_100,
BIASEXTR_105_94,
BIASEXTR_111_88,
BIASEXTR_118_8,
BIASEXTR_127_7,
};
struct rockchip_dw_dsi_chip_data {
u32 reg;
u32 lcdsel_grf_reg;
u32 lcdsel_big;
u32 lcdsel_lit;
u32 enable_grf_reg;
u32 enable;
u32 lanecfg1_grf_reg;
u32 lanecfg1;
u32 lanecfg2_grf_reg;
u32 lanecfg2;
unsigned int flags;
unsigned int max_data_lanes;
};
struct dw_rockchip_dsi_priv {
struct mipi_dsi_device device;
void __iomem *base;
struct udevice *panel;
/* Optional external dphy */
struct phy phy;
struct phy_configure_opts_mipi_dphy phy_opts;
struct clk *pclk;
struct clk *ref;
struct reset_ctl *rst;
unsigned int lane_mbps; /* per lane */
u16 input_div;
u16 feedback_div;
const struct rockchip_dw_dsi_chip_data *cdata;
struct udevice *dsi_host;
};
static inline void dsi_write(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 val)
{
writel(val, dsi->base + reg);
}
static inline u32 dsi_read(struct dw_rockchip_dsi_priv *dsi, u32 reg)
{
return readl(dsi->base + reg);
}
static inline void dsi_set(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
{
dsi_write(dsi, reg, dsi_read(dsi, reg) | mask);
}
static inline void dsi_clear(struct dw_rockchip_dsi_priv *dsi, u32 reg, u32 mask)
{
dsi_write(dsi, reg, dsi_read(dsi, reg) & ~mask);
}
static inline void dsi_update_bits(struct dw_rockchip_dsi_priv *dsi, u32 reg,
u32 mask, u32 val)
{
dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
}
static void dw_mipi_dsi_phy_write(struct dw_rockchip_dsi_priv *dsi,
u8 test_code,
u8 test_data)
{
/*
* With the falling edge on TESTCLK, the TESTDIN[7:0] signal content
* is latched internally as the current test code. Test data is
* programmed internally by rising edge on TESTCLK.
*/
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_TESTEN | PHY_TESTDOUT(0) |
PHY_TESTDIN(test_code));
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_UNTESTCLK | PHY_UNTESTCLR);
dsi_write(dsi, DSI_PHY_TST_CTRL1, PHY_UNTESTEN | PHY_TESTDOUT(0) |
PHY_TESTDIN(test_data));
dsi_write(dsi, DSI_PHY_TST_CTRL0, PHY_TESTCLK | PHY_UNTESTCLR);
}
struct dphy_pll_parameter_map {
unsigned int max_mbps;
u8 hsfreqrange;
u8 icpctrl;
u8 lpfctrl;
};
/* The table is based on 27MHz DPHY pll reference clock. */
static const struct dphy_pll_parameter_map dppa_map[] = {
{ 89, 0x00, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
{ 99, 0x10, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
{ 109, 0x20, CP_CURRENT_3UA, LPF_RESISTORS_13KOHM },
{ 129, 0x01, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 139, 0x11, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 149, 0x21, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 169, 0x02, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
{ 179, 0x12, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
{ 199, 0x22, CP_CURRENT_6UA, LPF_RESISTORS_13KOHM },
{ 219, 0x03, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
{ 239, 0x13, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
{ 249, 0x23, CP_CURRENT_4_5UA, LPF_RESISTORS_13KOHM },
{ 269, 0x04, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
{ 299, 0x14, CP_CURRENT_6UA, LPF_RESISTORS_11_5KOHM },
{ 329, 0x05, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 359, 0x15, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 399, 0x25, CP_CURRENT_3UA, LPF_RESISTORS_15_5KOHM },
{ 449, 0x06, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 499, 0x16, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 549, 0x07, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
{ 599, 0x17, CP_CURRENT_7_5UA, LPF_RESISTORS_10_5KOHM },
{ 649, 0x08, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 699, 0x18, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 749, 0x09, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 799, 0x19, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 849, 0x29, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 899, 0x39, CP_CURRENT_7_5UA, LPF_RESISTORS_11_5KOHM },
{ 949, 0x0a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
{ 999, 0x1a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
{1049, 0x2a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
{1099, 0x3a, CP_CURRENT_12UA, LPF_RESISTORS_8KOHM },
{1149, 0x0b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1199, 0x1b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1249, 0x2b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1299, 0x3b, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1349, 0x0c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1399, 0x1c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1449, 0x2c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM },
{1500, 0x3c, CP_CURRENT_12UA, LPF_RESISTORS_10_5KOHM }
};
static int max_mbps_to_parameter(unsigned int max_mbps)
{
int i;
for (i = 0; i < ARRAY_SIZE(dppa_map); i++)
if (dppa_map[i].max_mbps >= max_mbps)
return i;
return -EINVAL;
}
/*
* ns2bc - Nanoseconds to byte clock cycles
*/
static inline unsigned int ns2bc(struct dw_rockchip_dsi_priv *dsi, int ns)
{
return DIV_ROUND_UP(ns * dsi->lane_mbps / 8, 1000);
}
/*
* ns2ui - Nanoseconds to UI time periods
*/
static inline unsigned int ns2ui(struct dw_rockchip_dsi_priv *dsi, int ns)
{
return DIV_ROUND_UP(ns * dsi->lane_mbps, 1000);
}
static int dsi_phy_init(void *priv_data)
{
struct mipi_dsi_device *device = priv_data;
struct udevice *dev = device->dev;
struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
int ret, i, vco;
if (&dsi->phy) {
ret = generic_phy_configure(&dsi->phy, &dsi->phy_opts);
if (ret) {
dev_err(dsi->dsi_host,
"Configure external dphy fail %d\n",
ret);
return ret;
}
ret = generic_phy_power_on(&dsi->phy);
if (ret) {
dev_err(dsi->dsi_host,
"Generic phy power on fail %d\n", ret);
return ret;
}
return 0;
}
/*
* Get vco from frequency(lane_mbps)
* vco frequency table
* 000 - between 80 and 200 MHz
* 001 - between 200 and 300 MHz
* 010 - between 300 and 500 MHz
* 011 - between 500 and 700 MHz
* 100 - between 700 and 900 MHz
* 101 - between 900 and 1100 MHz
* 110 - between 1100 and 1300 MHz
* 111 - between 1300 and 1500 MHz
*/
vco = (dsi->lane_mbps < 200) ? 0 : (dsi->lane_mbps + 100) / 200;
i = max_mbps_to_parameter(dsi->lane_mbps);
if (i < 0) {
dev_err(dsi->dsi_host,
"failed to get parameter for %dmbps clock\n",
dsi->lane_mbps);
return i;
}
dw_mipi_dsi_phy_write(dsi, PLL_BIAS_CUR_SEL_CAP_VCO_CONTROL,
BYPASS_VCO_RANGE |
VCO_RANGE_CON_SEL(vco) |
VCO_IN_CAP_CON_LOW |
REF_BIAS_CUR_SEL);
dw_mipi_dsi_phy_write(dsi, PLL_CP_CONTROL_PLL_LOCK_BYPASS,
CP_CURRENT_SEL(dppa_map[i].icpctrl));
dw_mipi_dsi_phy_write(dsi, PLL_LPF_AND_CP_CONTROL,
CP_PROGRAM_EN | LPF_PROGRAM_EN |
LPF_RESISTORS_SEL(dppa_map[i].lpfctrl));
dw_mipi_dsi_phy_write(dsi, HS_RX_CONTROL_OF_LANE_0,
HSFREQRANGE_SEL(dppa_map[i].hsfreqrange));
dw_mipi_dsi_phy_write(dsi, PLL_INPUT_DIVIDER_RATIO,
INPUT_DIVIDER(dsi->input_div));
dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
LOOP_DIV_LOW_SEL(dsi->feedback_div) |
LOW_PROGRAM_EN);
/*
* We need set PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL immediately
* to make the configured LSB effective according to IP simulation
* and lab test results.
* Only in this way can we get correct mipi phy pll frequency.
*/
dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, PLL_LOOP_DIVIDER_RATIO,
LOOP_DIV_HIGH_SEL(dsi->feedback_div) |
HIGH_PROGRAM_EN);
dw_mipi_dsi_phy_write(dsi, PLL_INPUT_AND_LOOP_DIVIDER_RATIOS_CONTROL,
PLL_LOOP_DIV_EN | PLL_INPUT_DIV_EN);
dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
LOW_PROGRAM_EN | BIASEXTR_SEL(BIASEXTR_127_7));
dw_mipi_dsi_phy_write(dsi, AFE_BIAS_BANDGAP_ANALOG_PROGRAMMABILITY,
HIGH_PROGRAM_EN | BANDGAP_SEL(BANDGAP_96_10));
dw_mipi_dsi_phy_write(dsi, BANDGAP_AND_BIAS_CONTROL,
POWER_CONTROL | INTERNAL_REG_CURRENT |
BIAS_BLOCK_ON | BANDGAP_ON);
dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
TER_RESISTOR_LOW | TER_CAL_DONE |
SETRD_MAX | TER_RESISTORS_ON);
dw_mipi_dsi_phy_write(dsi, TERMINATION_RESISTER_CONTROL,
TER_RESISTOR_HIGH | LEVEL_SHIFTERS_ON |
SETRD_MAX | POWER_MANAGE |
TER_RESISTORS_ON);
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_REQUEST_STATE_TIME_CONTROL,
TLP_PROGRAM_EN | ns2bc(dsi, 500));
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_PREPARE_STATE_TIME_CONTROL,
THS_PRE_PROGRAM_EN | ns2ui(dsi, 40));
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_HS_ZERO_STATE_TIME_CONTROL,
THS_ZERO_PROGRAM_EN | ns2bc(dsi, 300));
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_TRAIL_STATE_TIME_CONTROL,
THS_PRE_PROGRAM_EN | ns2ui(dsi, 100));
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_EXIT_STATE_TIME_CONTROL,
BIT(5) | ns2bc(dsi, 100));
dw_mipi_dsi_phy_write(dsi, HS_TX_CLOCK_LANE_POST_TIME_CONTROL,
BIT(5) | (ns2bc(dsi, 60) + 7));
dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_REQUEST_STATE_TIME_CONTROL,
TLP_PROGRAM_EN | ns2bc(dsi, 500));
dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_PREPARE_STATE_TIME_CONTROL,
THS_PRE_PROGRAM_EN | (ns2ui(dsi, 50) + 20));
dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_HS_ZERO_STATE_TIME_CONTROL,
THS_ZERO_PROGRAM_EN | (ns2bc(dsi, 140) + 2));
dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_TRAIL_STATE_TIME_CONTROL,
THS_PRE_PROGRAM_EN | (ns2ui(dsi, 60) + 8));
dw_mipi_dsi_phy_write(dsi, HS_TX_DATA_LANE_EXIT_STATE_TIME_CONTROL,
BIT(5) | ns2bc(dsi, 100));
return ret;
}
static void dsi_phy_post_set_mode(void *priv_data, unsigned long mode_flags)
{
struct mipi_dsi_device *device = priv_data;
struct udevice *dev = device->dev;
struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
dev_dbg(dev, "Set mode %p enable %ld\n", dsi,
mode_flags & MIPI_DSI_MODE_VIDEO);
if (!dsi)
return;
/*
* DSI wrapper must be enabled in video mode & disabled in command mode.
* If wrapper is enabled in command mode, the display controller
* register access will hang. Note that this was carried over from the
* stm32 dsi driver and is unknown if necessary for Rockchip.
*/
if (mode_flags & MIPI_DSI_MODE_VIDEO)
dsi_set(dsi, DSI_WCR, WCR_DSIEN);
else
dsi_clear(dsi, DSI_WCR, WCR_DSIEN);
}
static int
dw_mipi_dsi_get_lane_mbps(void *priv_data, struct display_timing *timings,
u32 lanes, u32 format, unsigned int *lane_mbps)
{
struct mipi_dsi_device *device = priv_data;
struct udevice *dev = device->dev;
struct dw_rockchip_dsi_priv *dsi = dev_get_priv(dev);
int bpp;
unsigned long mpclk, tmp;
unsigned int target_mbps = 1000;
unsigned int max_mbps = dppa_map[ARRAY_SIZE(dppa_map) - 1].max_mbps;
unsigned long best_freq = 0;
unsigned long fvco_min, fvco_max, fin, fout;
unsigned int min_prediv, max_prediv;
unsigned int _prediv, best_prediv;
unsigned long _fbdiv, best_fbdiv;
unsigned long min_delta = ULONG_MAX;
unsigned int pllref_clk;
bpp = mipi_dsi_pixel_format_to_bpp(format);
if (bpp < 0) {
dev_err(dsi->dsi_host,
"failed to get bpp for pixel format %d\n",
format);
return bpp;
}
mpclk = DIV_ROUND_UP(timings->pixelclock.typ, 1000);
if (mpclk) {
/* take 1 / 0.8, since mbps must big than bandwidth of RGB */
tmp = (mpclk * (bpp / lanes) * 10 / 8) / 1000;
if (tmp < max_mbps)
target_mbps = tmp;
else
dev_err(dsi->dsi_host,
"DPHY clock frequency is out of range\n");
}
/* for external phy only the mipi_dphy_config is necessary */
if (&dsi->phy) {
phy_mipi_dphy_get_default_config(timings->pixelclock.typ * 10 / 8,
bpp, lanes,
&dsi->phy_opts);
dsi->lane_mbps = target_mbps;
*lane_mbps = dsi->lane_mbps;
return 0;
}
pllref_clk = clk_get_rate(dsi->ref);
fout = target_mbps * USEC_PER_SEC;
/* constraint: 5Mhz <= Fref / N <= 40MHz */
min_prediv = DIV_ROUND_UP(fin, 40 * USEC_PER_SEC);
max_prediv = fin / (5 * USEC_PER_SEC);
/* constraint: 80MHz <= Fvco <= 1500Mhz */
fvco_min = 80 * USEC_PER_SEC;
fvco_max = 1500 * USEC_PER_SEC;
for (_prediv = min_prediv; _prediv <= max_prediv; _prediv++) {
u64 tmp;
u32 delta;
/* Fvco = Fref * M / N */
tmp = (u64)fout * _prediv;
do_div(tmp, fin);
_fbdiv = tmp;
/*
* Due to the use of a "by 2 pre-scaler," the range of the
* feedback multiplication value M is limited to even division
* numbers, and m must be greater than 6, not bigger than 512.
*/
if (_fbdiv < 6 || _fbdiv > 512)
continue;
_fbdiv += _fbdiv % 2;
tmp = (u64)_fbdiv * fin;
do_div(tmp, _prediv);
if (tmp < fvco_min || tmp > fvco_max)
continue;
delta = abs(fout - tmp);
if (delta < min_delta) {
best_prediv = _prediv;
best_fbdiv = _fbdiv;
min_delta = delta;
best_freq = tmp;
}
}
if (best_freq) {
dsi->lane_mbps = DIV_ROUND_UP(best_freq, USEC_PER_SEC);
*lane_mbps = dsi->lane_mbps;
dsi->input_div = best_prediv;
dsi->feedback_div = best_fbdiv;
} else {
dev_err(dsi->dsi_host, "Can not find best_freq for DPHY\n");
return -EINVAL;
}
return 0;
}
struct hstt {
unsigned int maxfreq;
struct mipi_dsi_phy_timing timing;
};
#define HSTT(_maxfreq, _c_lp2hs, _c_hs2lp, _d_lp2hs, _d_hs2lp) \
{ \
.maxfreq = _maxfreq, \
.timing = { \
.clk_lp2hs = _c_lp2hs, \
.clk_hs2lp = _c_hs2lp, \
.data_lp2hs = _d_lp2hs, \
.data_hs2lp = _d_hs2lp, \
} \
}
/*
* Table A-3 High-Speed Transition Times
* (Note spacing is deliberate for readability).
*/
static struct hstt hstt_table[] = {
HSTT( 90, 32, 20, 26, 13),
HSTT( 100, 35, 23, 28, 14),
HSTT( 110, 32, 22, 26, 13),
HSTT( 130, 31, 20, 27, 13),
HSTT( 140, 33, 22, 26, 14),
HSTT( 150, 33, 21, 26, 14),
HSTT( 170, 32, 20, 27, 13),
HSTT( 180, 36, 23, 30, 15),
HSTT( 200, 40, 22, 33, 15),
HSTT( 220, 40, 22, 33, 15),
HSTT( 240, 44, 24, 36, 16),
HSTT( 250, 48, 24, 38, 17),
HSTT( 270, 48, 24, 38, 17),
HSTT( 300, 50, 27, 41, 18),
HSTT( 330, 56, 28, 45, 18),
HSTT( 360, 59, 28, 48, 19),
HSTT( 400, 61, 30, 50, 20),
HSTT( 450, 67, 31, 55, 21),
HSTT( 500, 73, 31, 59, 22),
HSTT( 550, 79, 36, 63, 24),
HSTT( 600, 83, 37, 68, 25),
HSTT( 650, 90, 38, 73, 27),
HSTT( 700, 95, 40, 77, 28),
HSTT( 750, 102, 40, 84, 28),
HSTT( 800, 106, 42, 87, 30),
HSTT( 850, 113, 44, 93, 31),
HSTT( 900, 118, 47, 98, 32),
HSTT( 950, 124, 47, 102, 34),
HSTT(1000, 130, 49, 107, 35),
HSTT(1050, 135, 51, 111, 37),
HSTT(1100, 139, 51, 114, 38),
HSTT(1150, 146, 54, 120, 40),
HSTT(1200, 153, 57, 125, 41),
HSTT(1250, 158, 58, 130, 42),
HSTT(1300, 163, 58, 135, 44),
HSTT(1350, 168, 60, 140, 45),
HSTT(1400, 172, 64, 144, 47),
HSTT(1450, 176, 65, 148, 48),
HSTT(1500, 181, 66, 153, 50)
};
static int dw_mipi_dsi_rockchip_get_timing(void *priv_data,
unsigned int lane_mbps,
struct mipi_dsi_phy_timing *timing)
{
int i;
for (i = 0; i < ARRAY_SIZE(hstt_table); i++)
if (lane_mbps < hstt_table[i].maxfreq)
break;
if (i == ARRAY_SIZE(hstt_table))
i--;
*timing = hstt_table[i].timing;
return 0;
}
static const struct mipi_dsi_phy_ops dsi_rockchip_phy_ops = {
.init = dsi_phy_init,
.get_lane_mbps = dw_mipi_dsi_get_lane_mbps,
.get_timing = dw_mipi_dsi_rockchip_get_timing,
.post_set_mode = dsi_phy_post_set_mode,
};
static int dw_mipi_dsi_rockchip_attach(struct udevice *dev)
{
struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
struct mipi_dsi_device *device = &priv->device;
struct mipi_dsi_panel_plat *mplat;
struct display_timing timings;
int ret;
ret = uclass_first_device_err(UCLASS_PANEL, &priv->panel);
if (ret) {
dev_err(dev, "panel device error %d\n", ret);
return ret;
}
mplat = dev_get_plat(priv->panel);
mplat->device = &priv->device;
device->lanes = mplat->lanes;
device->format = mplat->format;
device->mode_flags = mplat->mode_flags;
ret = panel_get_display_timing(priv->panel, &timings);
if (ret) {
ret = ofnode_decode_display_timing(dev_ofnode(priv->panel),
0, &timings);
if (ret) {
dev_err(dev, "decode display timing error %d\n", ret);
return ret;
}
}
ret = uclass_get_device(UCLASS_DSI_HOST, 0, &priv->dsi_host);
if (ret) {
dev_err(dev, "No video dsi host detected %d\n", ret);
return ret;
}
ret = dsi_host_init(priv->dsi_host, device, &timings, 4,
&dsi_rockchip_phy_ops);
if (ret) {
dev_err(dev, "failed to initialize mipi dsi host\n");
return ret;
}
return 0;
}
static int dw_mipi_dsi_rockchip_set_bl(struct udevice *dev, int percent)
{
struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
int ret;
/*
* Allow backlight to be optional, since this driver may be
* used to simply detect a panel rather than bring one up.
*/
ret = panel_enable_backlight(priv->panel);
if ((ret) && (ret != -ENOSYS)) {
dev_err(dev, "panel %s enable backlight error %d\n",
priv->panel->name, ret);
return ret;
}
ret = dsi_host_enable(priv->dsi_host);
if (ret) {
dev_err(dev, "failed to enable mipi dsi host\n");
return ret;
}
return 0;
}
static void dw_mipi_dsi_rockchip_config(struct dw_rockchip_dsi_priv *dsi)
{
if (dsi->cdata->lanecfg1_grf_reg)
dsi_write(dsi, dsi->cdata->lanecfg1_grf_reg,
dsi->cdata->lanecfg1);
if (dsi->cdata->lanecfg2_grf_reg)
dsi_write(dsi, dsi->cdata->lanecfg2_grf_reg,
dsi->cdata->lanecfg2);
if (dsi->cdata->enable_grf_reg)
dsi_write(dsi, dsi->cdata->enable_grf_reg,
dsi->cdata->enable);
}
static int dw_mipi_dsi_rockchip_bind(struct udevice *dev)
{
int ret;
ret = device_bind_driver_to_node(dev, "dw_mipi_dsi", "dsihost",
dev_ofnode(dev), NULL);
if (ret) {
dev_err(dev, "failed to bind driver to node\n");
return ret;
}
return dm_scan_fdt_dev(dev);
}
static int dw_mipi_dsi_rockchip_probe(struct udevice *dev)
{
struct dw_rockchip_dsi_priv *priv = dev_get_priv(dev);
struct mipi_dsi_device *device = &priv->device;
int ret, i;
const struct rockchip_dw_dsi_chip_data *cdata =
(const struct rockchip_dw_dsi_chip_data *)dev_get_driver_data(dev);
device->dev = dev;
priv->base = (void *)dev_read_addr(dev);
if ((fdt_addr_t)priv->base == FDT_ADDR_T_NONE) {
dev_err(dev, "dsi dt register address error\n");
return -EINVAL;
}
i = 0;
while (cdata[i].reg) {
if (cdata[i].reg == (fdt_addr_t)priv->base) {
priv->cdata = &cdata[i];
break;
}
i++;
}
if (!priv->cdata) {
dev_err(dev, "no dsi-config for %s node\n", dev->name);
return -EINVAL;
}
/*
* Get an optional external dphy. The external dphy stays as
* NULL if it's not initialized.
*/
ret = generic_phy_get_by_name(dev, "dphy", &priv->phy);
if ((ret) && (ret != -ENODEV)) {
dev_err(dev, "failed to get mipi dphy: %d\n", ret);
return -EINVAL;
}
priv->pclk = devm_clk_get(dev, "pclk");
if (IS_ERR(priv->pclk)) {
dev_err(dev, "peripheral clock get error %d\n", ret);
return ret;
}
/* Get a ref clock only if not using an external phy. */
if (&priv->phy) {
dev_dbg(dev, "setting priv->ref to NULL\n");
priv->ref = NULL;
} else {
priv->ref = devm_clk_get(dev, "ref");
if (ret) {
dev_err(dev, "pll reference clock get error %d\n", ret);
return ret;
}
}
priv->rst = devm_reset_control_get_by_index(device->dev, 0);
if (IS_ERR(priv->rst)) {
dev_err(dev, "missing dsi hardware reset\n");
return ret;
}
/* Reset */
reset_deassert(priv->rst);
dw_mipi_dsi_rockchip_config(priv);
return 0;
}
struct video_bridge_ops dw_mipi_dsi_rockchip_ops = {
.attach = dw_mipi_dsi_rockchip_attach,
.set_backlight = dw_mipi_dsi_rockchip_set_bl,
};
static const struct rockchip_dw_dsi_chip_data rk3568_chip_data[] = {
{
.reg = 0xfe060000,
.lanecfg1_grf_reg = RK3568_GRF_VO_CON2,
.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI0_SKEWCALHS |
RK3568_DSI0_FORCETXSTOPMODE |
RK3568_DSI0_TURNDISABLE |
RK3568_DSI0_FORCERXMODE),
.max_data_lanes = 4,
},
{
.reg = 0xfe070000,
.lanecfg1_grf_reg = RK3568_GRF_VO_CON3,
.lanecfg1 = HIWORD_UPDATE(0, RK3568_DSI1_SKEWCALHS |
RK3568_DSI1_FORCETXSTOPMODE |
RK3568_DSI1_TURNDISABLE |
RK3568_DSI1_FORCERXMODE),
.max_data_lanes = 4,
},
{ /* sentinel */ }
};
static const struct udevice_id dw_mipi_dsi_rockchip_dt_ids[] = {
{ .compatible = "rockchip,rk3568-mipi-dsi",
.data = (long)&rk3568_chip_data,
},
{ /* sentinel */ }
};
U_BOOT_DRIVER(dw_mipi_dsi_rockchip) = {
.name = "dw-mipi-dsi-rockchip",
.id = UCLASS_VIDEO_BRIDGE,
.of_match = dw_mipi_dsi_rockchip_dt_ids,
.bind = dw_mipi_dsi_rockchip_bind,
.probe = dw_mipi_dsi_rockchip_probe,
.ops = &dw_mipi_dsi_rockchip_ops,
.priv_auto = sizeof(struct dw_rockchip_dsi_priv),
};

View file

@ -307,7 +307,8 @@ static int rk_display_init(struct udevice *dev, ulong fbbase, ofnode ep_node)
__func__, dev_read_name(dev));
return -EINVAL;
}
if (strstr(compat, "edp")) {
if (strstr(compat, "edp") ||
strstr(compat, "rk3288-dp")) {
vop_id = VOP_MODE_EDP;
} else if (strstr(compat, "mipi")) {
vop_id = VOP_MODE_MIPI;

View file

@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (c) 2023 Rockchip Electronics Co., Ltd.
*/
#ifndef __EVB_RK3588_H
#define __EVB_RK3588_H
#include <configs/rk3588_common.h>
#define ROCKCHIP_DEVICE_SETTINGS \
"stdout=serial,vidconsole\0" \
"stderr=serial,vidconsole\0"
#endif

View file

@ -17,10 +17,15 @@
#define ENV_MEM_LAYOUT_SETTINGS \
"scriptaddr=0x00c00000\0" \
"script_offset_f=0xffe000\0" \
"script_size_f=0x2000\0" \
"pxefile_addr_r=0x00e00000\0" \
"fdt_addr_r=0x0a100000\0" \
"fdtoverlay_addr_r=0x02000000\0" \
"kernel_addr_r=0x02080000\0" \
"ramdisk_addr_r=0x0a200000\0"
"ramdisk_addr_r=0x0a200000\0" \
"kernel_comp_addr_r=0x08000000\0" \
"kernel_comp_size=0x2000000\0"
#include <config_distro_bootcmd.h>
#define CFG_EXTRA_ENV_SETTINGS \

View file

@ -16,10 +16,15 @@
#define ENV_MEM_LAYOUT_SETTINGS \
"scriptaddr=0x00c00000\0" \
"script_offset_f=0xffe000\0" \
"script_size_f=0x2000\0" \
"pxefile_addr_r=0x00e00000\0" \
"fdt_addr_r=0x0a100000\0" \
"fdtoverlay_addr_r=0x02000000\0" \
"kernel_addr_r=0x02080000\0" \
"ramdisk_addr_r=0x0a200000\0"
"ramdisk_addr_r=0x0a200000\0" \
"kernel_comp_addr_r=0x08000000\0" \
"kernel_comp_size=0x2000000\0"
#include <config_distro_bootcmd.h>
#define CFG_EXTRA_ENV_SETTINGS \