From 7786710adb76720be8e693c4efcea039af7ae086 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Tue, 7 Mar 2023 13:26:46 -0800 Subject: [PATCH 01/58] rockchip: sdhci: rk3568: fix clock setting logic mmc->tran_speed is max clock, but currently rk3568_sdhci_set_ios_post uses it if its != 0, regardless of mmc->clock value, and it breaks eMMC controller. Without this patch 'mmc dev 0; mmc dev 1; mmc dev 0' is enough for breaking eMMC, since first initialization sets mmc->mmc_tran speed to non-zero value (26MHz in my case), and on subsequent re-init when mmc layer asks for 400KHz it sets 26MHz instead. Fix it by using MAX(mmc->tran_speed, mmc->clock) Signed-off-by: Vasily Khoruzhick Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index e1409dd2c74..fef23f593e8 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -401,11 +401,11 @@ static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host) static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; - uint clock = mmc->tran_speed; + uint clock = mmc->clock; u32 reg, vendor_reg; - if (!clock) - clock = mmc->clock; + if (mmc->tran_speed && mmc->clock > mmc->tran_speed) + clock = mmc->tran_speed; rk3568_sdhci_emmc_set_clock(host, clock); From 6a89465f3f298d2f71ee59456de7436b0d0ae033 Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Wed, 1 Mar 2023 18:31:14 +0100 Subject: [PATCH 02/58] rockchip: puma-rk3399: enforce ENV_IS_NOWHERE with Kconfig select Instead of letting the compiler error out if CONFIG_ENV_IS_NOWHERE is not selected by the user, let's just enforce it when the user builds for Puma RK3399 so that no check needs to be performed by the compiler and the configuration is always valid. Suggested-by: Tom Rini Cc: Quentin Schulz Signed-off-by: Quentin Schulz Reviewed-by: Kever Yang --- board/theobroma-systems/puma_rk3399/Kconfig | 1 + board/theobroma-systems/puma_rk3399/puma-rk3399.c | 4 ---- configs/puma-rk3399_defconfig | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/board/theobroma-systems/puma_rk3399/Kconfig b/board/theobroma-systems/puma_rk3399/Kconfig index 15af55574c0..cc745f56b57 100644 --- a/board/theobroma-systems/puma_rk3399/Kconfig +++ b/board/theobroma-systems/puma_rk3399/Kconfig @@ -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 diff --git a/board/theobroma-systems/puma_rk3399/puma-rk3399.c b/board/theobroma-systems/puma_rk3399/puma-rk3399.c index 97f398bd754..614a60ee8f9 100644 --- a/board/theobroma-systems/puma_rk3399/puma-rk3399.c +++ b/board/theobroma-systems/puma_rk3399/puma-rk3399.c @@ -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 = diff --git a/configs/puma-rk3399_defconfig b/configs/puma-rk3399_defconfig index 9e3e23f825c..59017b26944 100644 --- a/configs/puma-rk3399_defconfig +++ b/configs/puma-rk3399_defconfig @@ -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 From c3328c3ba8c9c1718247456053bd61876672c0fa Mon Sep 17 00:00:00 2001 From: Quentin Schulz Date: Wed, 1 Mar 2023 18:31:15 +0100 Subject: [PATCH 03/58] rockchip: ringneck-px30: enforce ENV_IS_NOWHERE with Kconfig select Instead of letting the compiler error out if CONFIG_ENV_IS_NOWHERE is not selected by the user, let's just enforce it when the user builds for Ringneck PX30 so that no check needs to be performed by the compiler and the configuration is always valid. Suggested-by: Tom Rini Cc: Quentin Schulz Signed-off-by: Quentin Schulz Reviewed-by: Kever Yang --- board/theobroma-systems/ringneck_px30/Kconfig | 1 + board/theobroma-systems/ringneck_px30/ringneck-px30.c | 4 ---- configs/ringneck-px30_defconfig | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/board/theobroma-systems/ringneck_px30/Kconfig b/board/theobroma-systems/ringneck_px30/Kconfig index 24d94807db8..c33253bdad8 100644 --- a/board/theobroma-systems/ringneck_px30/Kconfig +++ b/board/theobroma-systems/ringneck_px30/Kconfig @@ -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 diff --git a/board/theobroma-systems/ringneck_px30/ringneck-px30.c b/board/theobroma-systems/ringneck_px30/ringneck-px30.c index 47d1a40ef7c..bb1bb4acf5c 100644 --- a/board/theobroma-systems/ringneck_px30/ringneck-px30.c +++ b/board/theobroma-systems/ringneck_px30/ringneck-px30.c @@ -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 = diff --git a/configs/ringneck-px30_defconfig b/configs/ringneck-px30_defconfig index 91706d8def2..e9234efc2a0 100644 --- a/configs/ringneck-px30_defconfig +++ b/configs/ringneck-px30_defconfig @@ -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 From cf8658cdac13b0067a909450ab25cf3e3eef2d60 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Thu, 2 Mar 2023 15:12:57 +0800 Subject: [PATCH 04/58] board: rockchip: Add rk3588 evb rk3588 evb1 v10 is a evalution board from Rockchip, it is a dev board for rockchip and also a reference board for board vendors. Hardware: SoC: RK3588 DRAM: LPDDR4X 8GB Debug: UART2 via USB PCIe: 3x4 *1 SATA *2 HDMI out *2 HDMI IN *1 USB2.0 Host *2 USB3.0 Host *1 Type C *1 MIPI DSI panel dts Sync from Linux v6.2. Signed-off-by: Kever Yang Reviewed-by: Jagan Teki --- arch/arm/dts/Makefile | 1 + arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi | 21 ++++ arch/arm/dts/rk3588-evb1-v10.dts | 129 +++++++++++++++++++++++ arch/arm/mach-rockchip/rk3588/Kconfig | 7 ++ board/rockchip/evb_rk3588/Kconfig | 15 +++ board/rockchip/evb_rk3588/MAINTAINERS | 7 ++ board/rockchip/evb_rk3588/Makefile | 6 ++ board/rockchip/evb_rk3588/evb-rk3588.c | 39 +++++++ configs/evb-rk3588_defconfig | 69 ++++++++++++ doc/board/rockchip/rockchip.rst | 10 ++ include/configs/evb_rk3588.h | 15 +++ 11 files changed, 319 insertions(+) create mode 100644 arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi create mode 100644 arch/arm/dts/rk3588-evb1-v10.dts create mode 100644 board/rockchip/evb_rk3588/Kconfig create mode 100644 board/rockchip/evb_rk3588/MAINTAINERS create mode 100644 board/rockchip/evb_rk3588/Makefile create mode 100644 board/rockchip/evb_rk3588/evb-rk3588.c create mode 100644 configs/evb-rk3588_defconfig create mode 100644 include/configs/evb_rk3588.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 337bee7e1ec..62009e621e2 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -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) += \ diff --git a/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi b/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi new file mode 100644 index 00000000000..bd2e2594863 --- /dev/null +++ b/arch/arm/dts/rk3588-evb1-v10-u-boot.dtsi @@ -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; +}; diff --git a/arch/arm/dts/rk3588-evb1-v10.dts b/arch/arm/dts/rk3588-evb1-v10.dts new file mode 100644 index 00000000000..b91af0204db --- /dev/null +++ b/arch/arm/dts/rk3588-evb1-v10.dts @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2021 Rockchip Electronics Co., Ltd. + * + */ + +/dts-v1/; + +#include +#include +#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 = ; + 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"; +}; diff --git a/arch/arm/mach-rockchip/rk3588/Kconfig b/arch/arm/mach-rockchip/rk3588/Kconfig index aee71ca1dab..3596b82f1f1 100644 --- a/arch/arm/mach-rockchip/rk3588/Kconfig +++ b/arch/arm/mach-rockchip/rk3588/Kconfig @@ -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 diff --git a/board/rockchip/evb_rk3588/Kconfig b/board/rockchip/evb_rk3588/Kconfig new file mode 100644 index 00000000000..d38efe61d83 --- /dev/null +++ b/board/rockchip/evb_rk3588/Kconfig @@ -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 diff --git a/board/rockchip/evb_rk3588/MAINTAINERS b/board/rockchip/evb_rk3588/MAINTAINERS new file mode 100644 index 00000000000..7b7df3c5a8a --- /dev/null +++ b/board/rockchip/evb_rk3588/MAINTAINERS @@ -0,0 +1,7 @@ +EVB-RK3588 +M: Kever Yang +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 diff --git a/board/rockchip/evb_rk3588/Makefile b/board/rockchip/evb_rk3588/Makefile new file mode 100644 index 00000000000..240d2ec597e --- /dev/null +++ b/board/rockchip/evb_rk3588/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (c) 2023 Rockchip Electronics Co,. Ltd. +# + +obj-y += evb-rk3588.o diff --git a/board/rockchip/evb_rk3588/evb-rk3588.c b/board/rockchip/evb_rk3588/evb-rk3588.c new file mode 100644 index 00000000000..caf94d8d29c --- /dev/null +++ b/board/rockchip/evb_rk3588/evb-rk3588.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2023 Rockchip Electronics Co,. Ltd. + */ + +#include +#include + +#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 diff --git a/configs/evb-rk3588_defconfig b/configs/evb-rk3588_defconfig new file mode 100644 index 00000000000..ddeadb8a760 --- /dev/null +++ b/configs/evb-rk3588_defconfig @@ -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 diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst index b5563b8f7f9..af6e466de1e 100644 --- a/doc/board/rockchip/rockchip.rst +++ b/doc/board/rockchip/rockchip.rst @@ -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 -------- diff --git a/include/configs/evb_rk3588.h b/include/configs/evb_rk3588.h new file mode 100644 index 00000000000..4568e2cace6 --- /dev/null +++ b/include/configs/evb_rk3588.h @@ -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 + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + +#endif From f7ad2912c697a634fc3ffafc06aa697d8706bca8 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 28 Feb 2023 21:38:25 +0000 Subject: [PATCH 05/58] rockchip: Use an external TPL binary on RK3588 There is no support to initialize DRAM on RK3588 SoCs using U-Boot TPL and instead an external TPL binary must be used to generate a bootable u-boot-rockchip.bin image. Enable ROCKCHIP_EXTERNAL_TPL by default for RK3588, add build steps for RK3588 to documentation and clean up CONFIG_BINMAN_FDT options. Signed-off-by: Jonas Karlman Reviewed-by: Jagan Teki --- arch/arm/mach-rockchip/Kconfig | 2 +- configs/neu6a-io-rk3588_defconfig | 1 - configs/rock-3a-rk3568_defconfig | 1 - configs/rock5b-rk3588_defconfig | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 0390431601f..e5ac58ae60b 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -428,7 +428,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 diff --git a/configs/neu6a-io-rk3588_defconfig b/configs/neu6a-io-rk3588_defconfig index c9b22525315..fb1ce4c1746 100644 --- a/configs/neu6a-io-rk3588_defconfig +++ b/configs/neu6a-io-rk3588_defconfig @@ -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 diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig index e7538321832..af1374549dd 100644 --- a/configs/rock-3a-rk3568_defconfig +++ b/configs/rock-3a-rk3568_defconfig @@ -69,5 +69,4 @@ CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550_MEM32=y CONFIG_SYSRESET=y -# CONFIG_BINMAN_FDT is not set CONFIG_ERRNO_STR=y diff --git a/configs/rock5b-rk3588_defconfig b/configs/rock5b-rk3588_defconfig index f3026c7ea16..66199387195 100644 --- a/configs/rock5b-rk3588_defconfig +++ b/configs/rock5b-rk3588_defconfig @@ -68,5 +68,4 @@ 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 From 24fea3f8372f7ca9694afda5ec6049b1721c1d06 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Thu, 23 Feb 2023 19:28:51 +0000 Subject: [PATCH 06/58] rockchip: rk3288: Use ft_system_setup instead of ft_board_setup ft_board_setup() should be availble for use in board files but using it in the rk3288 machine file blocks this functionality. ft_system_setup() is the more appropriate function to use in a machine definition. Signed-off-by: John Keeping Reviewed-by: Kever Yang --- arch/arm/mach-rockchip/Kconfig | 2 +- arch/arm/mach-rockchip/rk3288/rk3288.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index e5ac58ae60b..39cf4b99393 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -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 diff --git a/arch/arm/mach-rockchip/rk3288/rk3288.c b/arch/arm/mach-rockchip/rk3288/rk3288.c index 3ad2887575d..26c7e41cd89 100644 --- a/arch/arm/mach-rockchip/rk3288/rk3288.c +++ b/arch/arm/mach-rockchip/rk3288/rk3288.c @@ -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); From 4f51064533ff8f27d2859a4ad0c4c367ec28e712 Mon Sep 17 00:00:00 2001 From: Jianqun Xu Date: Wed, 15 Mar 2023 17:32:15 +0200 Subject: [PATCH 07/58] pinctrl: rockchip: support rk3588 pinctrl Add support for Rockchip rk3588 variant of pinctrl. The driver is adapted from the Linux driver. Signed-off-by: Jianqun Xu [eugen.hristev@collabora.com: port to latest U-boot, bring more changes from Linux use translated pull values table] Signed-off-by: Eugen Hristev Reviewed-by: Kever Yang Tested-by: Jonas Karlman Reviewed-by: Jonas Karlman --- drivers/pinctrl/rockchip/Makefile | 1 + drivers/pinctrl/rockchip/pinctrl-rk3588.c | 353 ++++++++++++++++++++ drivers/pinctrl/rockchip/pinctrl-rockchip.h | 187 +++++++++++ 3 files changed, 541 insertions(+) create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3588.c diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile index 90461ae8819..c91f650b043 100644 --- a/drivers/pinctrl/rockchip/Makefile +++ b/drivers/pinctrl/rockchip/Makefile @@ -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 diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3588.c b/drivers/pinctrl/rockchip/pinctrl-rk3588.c new file mode 100644 index 00000000000..548cf09bcca --- /dev/null +++ b/drivers/pinctrl/rockchip/pinctrl-rk3588.c @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-rockchip.h" +#include + +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, ®map, ®, &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, ®map, ®, &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, ®map, ®, &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, +}; diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h index 8dfaba5c74d..df7bc684d29 100644 --- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h @@ -9,6 +9,171 @@ #include #include +#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. From 35e9e8aebfbd55eddec39d32921dff76a5141922 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:31:57 +0100 Subject: [PATCH 08/58] arm: dts: rockchip: rk3288: move io-domains nodes In order to better compare the Linux rk3288.dtsi version with the U-Boot version move the io-domains nodes. Signed-off-by: Johan Jonker Reviewed-by: John Keeping Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- arch/arm/dts/rk3288-miqi.dtsi | 27 +++++++++++-------------- arch/arm/dts/rk3288-phycore-som.dtsi | 30 +++++++++++++--------------- arch/arm/dts/rk3288-popmetal.dtsi | 30 +++++++++++++--------------- arch/arm/dts/rk3288-veyron.dtsi | 28 ++++++++++++-------------- arch/arm/dts/rk3288.dtsi | 5 +++++ 5 files changed, 58 insertions(+), 62 deletions(-) diff --git a/arch/arm/dts/rk3288-miqi.dtsi b/arch/arm/dts/rk3288-miqi.dtsi index cb80cbf27df..00c8613d6d7 100644 --- a/arch/arm/dts/rk3288-miqi.dtsi +++ b/arch/arm/dts/rk3288-miqi.dtsi @@ -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; diff --git a/arch/arm/dts/rk3288-phycore-som.dtsi b/arch/arm/dts/rk3288-phycore-som.dtsi index 821525f7148..70c00308d73 100644 --- a/arch/arm/dts/rk3288-phycore-som.dtsi +++ b/arch/arm/dts/rk3288-phycore-som.dtsi @@ -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>; diff --git a/arch/arm/dts/rk3288-popmetal.dtsi b/arch/arm/dts/rk3288-popmetal.dtsi index 0253933a117..d732a70678b 100644 --- a/arch/arm/dts/rk3288-popmetal.dtsi +++ b/arch/arm/dts/rk3288-popmetal.dtsi @@ -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 { diff --git a/arch/arm/dts/rk3288-veyron.dtsi b/arch/arm/dts/rk3288-veyron.dtsi index 35db8827431..434b0d494e5 100644 --- a/arch/arm/dts/rk3288-veyron.dtsi +++ b/arch/arm/dts/rk3288-veyron.dtsi @@ -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"; }; diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index 8c394c1e539..9cfb86f9f05 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -762,6 +762,11 @@ grf: syscon@ff770000 { compatible = "rockchip,rk3288-grf", "syscon"; reg = <0xff770000 0x1000>; + + io_domains: io-domains { + compatible = "rockchip,rk3288-io-voltage-domain"; + status = "disabled"; + }; }; wdt: watchdog@ff800000 { From da5ae37fcd5d10324ac181b545082107b3ccaa82 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:33:25 +0100 Subject: [PATCH 09/58] arm: dts: rockchip: rk3288: partial sync grf and pmu nodes In order to better compare the Linux rk3288.dtsi version 6.3 -rc2 with the U-Boot version partial sync the grf and pmu nodes. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- arch/arm/dts/rk3288.dtsi | 269 +++++++++++++++++++++++++-------------- 1 file changed, 173 insertions(+), 96 deletions(-) diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index 9cfb86f9f05..f06d1f5bcc0 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) #include #include @@ -7,13 +7,16 @@ #include #include #include -#include -#include "skeleton.dtsi" +#include / { + #address-cells = <1>; + #size-cells = <1>; + compatible = "rockchip,rk3288"; interrupt-parent = <&gic>; + aliases { ethernet0 = &gmac; i2c0 = &i2c0; @@ -732,8 +735,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 = ; + 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 = ; + 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 = ; + 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 = ; + 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 = ; + mode-recovery = ; + mode-bootloader = ; + mode-loader = ; + }; }; sgrf: syscon@ff740000 { @@ -760,13 +883,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 { @@ -1246,39 +1414,6 @@ interrupts = ; }; - 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>; @@ -1865,62 +2000,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 = ; - clocks = <&cru ACLK_GPU>; - }; - - pd_hevc { - reg = ; - clocks = <&cru ACLK_HEVC>, - <&cru SCLK_HEVC_CABAC>, - <&cru SCLK_HEVC_CORE>, - <&cru HCLK_HEVC>; - }; - - pd_vio { - reg = ; - 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 = ; - clocks = <&cru ACLK_VCODEC>, - <&cru HCLK_VCODEC>; - }; - }; }; From e2b57ffbafd044c40491fa4f74b049026cdca116 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:33:38 +0100 Subject: [PATCH 10/58] video: rockchip: rk_vop: add rk3288-dp compare string In the current rk3288.dtsi file the compatible string for the DisplayPort(DP) node ends with "edp". The string in the binding ends with "dp" which conflicts with "cdn-dp" as a search term. Add "rk3288-dp" as compare string to select vop_id. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- drivers/video/rockchip/rk_vop.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/video/rockchip/rk_vop.c b/drivers/video/rockchip/rk_vop.c index bc98ab6875a..e21ac7e3036 100644 --- a/drivers/video/rockchip/rk_vop.c +++ b/drivers/video/rockchip/rk_vop.c @@ -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; From bf13676e0b0cbdc343dce276c20a2fdb5540ab44 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:33:50 +0100 Subject: [PATCH 11/58] arm: dts: rockchip: rk3288: partial sync edp node The rk3288 edp node has a phy node in Linux with a clock property while current U-Boot driver expects this clock on position index 1. Move U-Boot-specific DT clock properties to rk3288-u-boot.dtsi and partially sync the edp node. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- arch/arm/dts/rk3288-u-boot.dtsi | 5 +++++ arch/arm/dts/rk3288.dtsi | 19 ++++++++++++------- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/arch/arm/dts/rk3288-u-boot.dtsi b/arch/arm/dts/rk3288-u-boot.dtsi index 18941621530..19206988845 100644 --- a/arch/arm/dts/rk3288-u-boot.dtsi +++ b/arch/arm/dts/rk3288-u-boot.dtsi @@ -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; }; diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index f06d1f5bcc0..9f924466542 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -1177,19 +1177,24 @@ }; edp: dp@ff970000 { - compatible = "rockchip,rk3288-edp"; + compatible = "rockchip,rk3288-dp"; reg = <0xff970000 0x4000>; interrupts = ; - 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 { From 7c1ee7a8488386e827c274d86297af415e49c02a Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:34:01 +0100 Subject: [PATCH 12/58] arm: dts: rockchip: rk3288: partial sync vop/lvds/mipi/hdmi nodes In order to better compare the Linux rk3288.dtsi version 6.3 -rc2 with the U-Boot version partial sync the vop/lvds/mipi/hdmi nodes. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- arch/arm/dts/rk3288.dtsi | 60 ++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index 9f924466542..f24e9ba52e6 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -1021,7 +1021,7 @@ vopb: vop@ff930000 { compatible = "rockchip,rk3288-vop"; - reg = <0xff930000 0x19c>; + reg = <0xff930000 0x19c>, <0xff931000 0x1000>; interrupts = ; clocks = <&cru ACLK_VOP0>, <&cru DCLK_VOP0>, <&cru HCLK_VOP0>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; @@ -1035,25 +1035,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>; + }; }; }; @@ -1070,7 +1070,7 @@ vopl: vop@ff940000 { compatible = "rockchip,rk3288-vop"; - reg = <0xff940000 0x19c>; + reg = <0xff940000 0x19c>, <0xff941000 0x1000>; interrupts = ; clocks = <&cru ACLK_VOP1>, <&cru DCLK_VOP1>, <&cru HCLK_VOP1>; clock-names = "aclk_vop", "dclk_vop", "hclk_vop"; @@ -1084,25 +1084,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>; + }; }; }; @@ -1118,11 +1118,11 @@ }; mipi_dsi: mipi@ff960000 { - compatible = "rockchip,rk3288_mipi_dsi"; + compatible = "rockchip,rk3288-mipi-dsi", "snps,dw-mipi-dsi"; reg = <0xff960000 0x4000>; interrupts = ; - 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"; @@ -1148,7 +1148,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>; @@ -1216,8 +1216,8 @@ #sound-dai-cells = <0>; rockchip,grf = <&grf>; interrupts = ; - 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"; From 2c2d782556e4f5d9483679d1293d8436892e9fed Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:34:13 +0100 Subject: [PATCH 13/58] clk: rockchip: clk_rk3288: add PCLK_RKPWM The rk3288 pwm nodes synced from Linux make use of PCLK_RKPWM instead of PCLK_PWM. They have the same pclk_cpu parent, so add PCLK_RKPWM to rk3288_clk_get_rate(). Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Tested-by: Simon Glass # chromebook-jerry Reviewed-by: Kever Yang --- drivers/clk/rockchip/clk_rk3288.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c index 3b29992c3e5..ef744c06f3e 100644 --- a/drivers/clk/rockchip/clk_rk3288.c +++ b/drivers/clk/rockchip/clk_rk3288.c @@ -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); From ba607e2b9a6264ffd0528c1b5b516251d7e7cf2d Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Wed, 15 Mar 2023 19:34:24 +0100 Subject: [PATCH 14/58] arm: dts: rockchip: rk3288: partial sync pwm nodes In order to better compare the Linux rk3288.dtsi version 6.3 -rc2 with the U-Boot version partial sync the pwm nodes. Signed-off-by: Johan Jonker Reviewed-by: Kever Yang --- arch/arm/dts/rk3288.dtsi | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/arch/arm/dts/rk3288.dtsi b/arch/arm/dts/rk3288.dtsi index f24e9ba52e6..dd1d989793f 100644 --- a/arch/arm/dts/rk3288.dtsi +++ b/arch/arm/dts/rk3288.dtsi @@ -675,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"; }; @@ -687,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"; }; @@ -699,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"; }; From 3c4549771dd0352e893a0bc9d2344cd8ecd8033d Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:02:18 +0100 Subject: [PATCH 15/58] rockchip: gpio: rk_gpio: use ROCKCHIP_GPIOS_PER_BANK as divider The current divider to calculate the bank ID can change. Given the Rockchip TRM not all gpio-banks have 32 pins per bank. The "gpio-ranges" syntax allows multiple items with variable number of pins. Use a constant ROCKCHIP_GPIOS_PER_BANK as fixed divider. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- drivers/gpio/rk_gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index f7ad4d68b45..0a2acf1857a 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -160,7 +160,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, '@'); From fed814c088985229d306e8def017fd9ae17a6b62 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:05:27 +0100 Subject: [PATCH 16/58] arm: dts: rockchip: rk3066a-u-boot: add gpio-ranges The gpio node names are made generic, but without gpio bank ID. Add gpio-ranges to rk3066a-u-boot.dtsi for now till a better method is found. Disable gpio6 as the driver gives an error code on return as status. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- arch/arm/dts/rk3066a-u-boot.dtsi | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/arch/arm/dts/rk3066a-u-boot.dtsi b/arch/arm/dts/rk3066a-u-boot.dtsi index bc6e609d02b..06f405ca2c5 100644 --- a/arch/arm/dts/rk3066a-u-boot.dtsi +++ b/arch/arm/dts/rk3066a-u-boot.dtsi @@ -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"; +}; + From e16be4dd8b5cdb9bcad296f3f459963201d85653 Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:05:43 +0100 Subject: [PATCH 17/58] arm: dts: rockchip: rk3188-u-boot: add gpio-ranges The gpio node names are made generic, but without gpio bank ID. Add gpio-ranges to rk3188-u-boot.dtsi for now till a better method is found. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- arch/arm/dts/rk3188-u-boot.dtsi | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/arch/arm/dts/rk3188-u-boot.dtsi b/arch/arm/dts/rk3188-u-boot.dtsi index 735776c16b8..176f9e65c26 100644 --- a/arch/arm/dts/rk3188-u-boot.dtsi +++ b/arch/arm/dts/rk3188-u-boot.dtsi @@ -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 { From 98125086d676f00f5fa4b56e27de98534025f91c Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:05:57 +0100 Subject: [PATCH 18/58] arm: dts: rockchip: sync rk3066/rk3188 DT files from linux-next v6.2-rc4 Sync rk3066/rk3188 DT files from Linux. This is the state as of linux-next v6.2-rc4. New nfc node for MK808 rk3066a. CRU nodes now have a clock property. To prefend dtoc errors a fixed clock must also be included for tpl/spl in the rk3xxx-u-boot.dtsi file. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- arch/arm/dts/rk3066a-mk808.dts | 27 ++++++++++++++++++++++++++- arch/arm/dts/rk3066a.dtsi | 3 ++- arch/arm/dts/rk3188-radxarock.dts | 26 ++++++++++++++------------ arch/arm/dts/rk3188.dtsi | 27 ++++++++++++++++----------- arch/arm/dts/rk3xxx-u-boot.dtsi | 4 ++++ arch/arm/dts/rk3xxx.dtsi | 9 +++++++-- 6 files changed, 69 insertions(+), 27 deletions(-) diff --git a/arch/arm/dts/rk3066a-mk808.dts b/arch/arm/dts/rk3066a-mk808.dts index 667d57a4ff4..06790f05b39 100644 --- a/arch/arm/dts/rk3066a-mk808.dts +++ b/arch/arm/dts/rk3066a-mk808.dts @@ -32,7 +32,7 @@ keyup-threshold-microvolt = <2500000>; poll-interval = <100>; - recovery { + button-recovery { label = "recovery"; linux,code = ; 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 { diff --git a/arch/arm/dts/rk3066a.dtsi b/arch/arm/dts/rk3066a.dtsi index c25b9695db4..de9915d946f 100644 --- a/arch/arm/dts/rk3066a.dtsi +++ b/arch/arm/dts/rk3066a.dtsi @@ -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>, diff --git a/arch/arm/dts/rk3188-radxarock.dts b/arch/arm/dts/rk3188-radxarock.dts index e7138a4ae0b..118deacd38c 100644 --- a/arch/arm/dts/rk3188-radxarock.dts +++ b/arch/arm/dts/rk3188-radxarock.dts @@ -6,7 +6,6 @@ /dts-v1/; #include #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 = ; 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 = ; + mdio { + #address-cells = <1>; + #size-cells = <0>; + + phy0: ethernet-phy@0 { + reg = <0>; + interrupt-parent = <&gpio3>; + interrupts = ; + }; }; }; diff --git a/arch/arm/dts/rk3188.dtsi b/arch/arm/dts/rk3188.dtsi index 9a80f83a1ae..44b54af0bbf 100644 --- a/arch/arm/dts/rk3188.dtsi +++ b/arch/arm/dts/rk3188.dtsi @@ -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 = ; @@ -236,7 +237,7 @@ #interrupt-cells = <2>; }; - gpio1: gpio1@2003c000 { + gpio1: gpio@2003c000 { compatible = "rockchip,gpio-bank"; reg = <0x2003c000 0x100>; interrupts = ; @@ -249,7 +250,7 @@ #interrupt-cells = <2>; }; - gpio2: gpio2@2003e000 { + gpio2: gpio@2003e000 { compatible = "rockchip,gpio-bank"; reg = <0x2003e000 0x100>; interrupts = ; @@ -262,7 +263,7 @@ #interrupt-cells = <2>; }; - gpio3: gpio3@20080000 { + gpio3: gpio@20080000 { compatible = "rockchip,gpio-bank"; reg = <0x20080000 0x100>; interrupts = ; @@ -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 = ; - 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>; diff --git a/arch/arm/dts/rk3xxx-u-boot.dtsi b/arch/arm/dts/rk3xxx-u-boot.dtsi index f50bacdb842..6af6a451ea7 100644 --- a/arch/arm/dts/rk3xxx-u-boot.dtsi +++ b/arch/arm/dts/rk3xxx-u-boot.dtsi @@ -33,3 +33,7 @@ &uart2 { clock-frequency = <24000000>; }; + +&xin24m { + bootph-all; +}; diff --git a/arch/arm/dts/rk3xxx.dtsi b/arch/arm/dts/rk3xxx.dtsi index 616a828e0c6..cb4e42ede56 100644 --- a/arch/arm/dts/rk3xxx.dtsi +++ b/arch/arm/dts/rk3xxx.dtsi @@ -76,6 +76,13 @@ reg = <0x1013c200 0x20>; interrupts = ; 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 = ; - #address-cells = <1>; - #size-cells = <0>; rockchip,grf = <&grf>; From f1088af5747894c99fb60a84cedac99b7151abaa Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:06:11 +0100 Subject: [PATCH 19/58] rockchip: configs: mk808: change CONFIG_TPL_TEXT_BASE Currently the Rockchip rk3066a u-boot-tpl.bin file needs to add the characters "RK30", while the other SoCs replace the first 4 bytes. Bring this in line with the rest by lowering CONFIG_TPL_TEXT_BASE and update rockchip.rst instructions. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- configs/mk808_defconfig | 2 +- doc/board/rockchip/rockchip.rst | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig index c080706d971..5a264eb9e17 100644 --- a/configs/mk808_defconfig +++ b/configs/mk808_defconfig @@ -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 diff --git a/doc/board/rockchip/rockchip.rst b/doc/board/rockchip/rockchip.rst index af6e466de1e..1dccb17d725 100644 --- a/doc/board/rockchip/rockchip.rst +++ b/doc/board/rockchip/rockchip.rst @@ -390,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 @@ -416,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 From df2af4083cadec1a0b40e614d0a5bea9a82d359d Mon Sep 17 00:00:00 2001 From: Johan Jonker Date: Sun, 19 Mar 2023 16:06:23 +0100 Subject: [PATCH 20/58] rockchip: configs: mk808: enable usb support Enable usb support in the mk808_defconfig. Signed-off-by: Johan Jonker Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- configs/mk808_defconfig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/configs/mk808_defconfig b/configs/mk808_defconfig index 5a264eb9e17..b7dcd163e4d 100644 --- a/configs/mk808_defconfig +++ b/configs/mk808_defconfig @@ -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 From 88b962f3934a29c825cde579844642d8a57fd212 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Sun, 19 Mar 2023 18:39:51 +0000 Subject: [PATCH 21/58] gpio: rockchip: Add support for RK3568 and RK3588 banks The GPIO V2 controller on RK3568 and RK3588 works very similar to prior generation, main difference is the use of a write mask in the upper 16 bits and register address offset have changed. GPIO_VER_ID is a new register at 0x0078 that is used to determine when the driver should use new or old register offsets and values. Earlier generation return 0x0 from this offset. Refactor code and add support for the GPIO V2 controller used in RK3568 and RK3588. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/gpio/rk_gpio.c | 126 +++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 43 deletions(-) diff --git a/drivers/gpio/rk_gpio.c b/drivers/gpio/rk_gpio.c index 0a2acf1857a..4a6ae554bf7 100644 --- a/drivers/gpio/rk_gpio.c +++ b/drivers/gpio/rk_gpio.c @@ -13,29 +13,74 @@ #include #include #include +#include #include #include -#include +#include +#include + +#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(®s->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(®s->swport_dr, mask, value ? mask : 0); - setbits_le32(®s->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(®s->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(®s->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(®s->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 @@ -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; } From cf8b415d5cdf11d30eb619e1972ef7a6b4e315e2 Mon Sep 17 00:00:00 2001 From: Jonathan Liu Date: Thu, 23 Mar 2023 21:35:58 +1100 Subject: [PATCH 22/58] ram: rk3399: add missing high row detection For 2 GB LPDDR4 single-rank RAM with 16 rows, the Rockchip ddr init bin prints: "Bus Width=32 Col=10 Bank=8 Row=16 CS=1 Die Bus-Width=16 Size=2048MB" U-Boot TPL prints: "BW=32 Col=10 Bk=8 CS0 Row=16/15 CS=1 Die BW=16 Size=2048MB" Add missing high row detection so that U-Boot TPL prints Row=16, same as the Rockchip ddr init bin: "BW=32 Col=10 Bk=8 CS0 Row=16 CS=1 Die BW=16 Size=2048MB" Signed-off-by: Jonathan Liu Reviewed-by: Kever Yang --- drivers/ram/rockchip/sdram_rk3399.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ram/rockchip/sdram_rk3399.c b/drivers/ram/rockchip/sdram_rk3399.c index 963a05c244a..89932452520 100644 --- a/drivers/ram/rockchip/sdram_rk3399.c +++ b/drivers/ram/rockchip/sdram_rk3399.c @@ -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); From bf57dd5889beae9ff871a657f43ed72345ab2e6c Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Fri, 24 Mar 2023 13:53:06 -0500 Subject: [PATCH 23/58] drivers: phy: add Innosilicon DSI-DPHY driver Add support for the Innosilicon DSI-DPHY driver for Rockchip SOCs. The driver was ported from Linux and tested on a Rockchip RK3566 based device to query the panel ID via a DSI command. Signed-off-by: Chris Morgan Reviewed-by: Kever Yang --- drivers/phy/rockchip/Kconfig | 8 + drivers/phy/rockchip/Makefile | 1 + .../phy/rockchip/phy-rockchip-inno-dsidphy.c | 680 ++++++++++++++++++ 3 files changed, 689 insertions(+) create mode 100644 drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c diff --git a/drivers/phy/rockchip/Kconfig b/drivers/phy/rockchip/Kconfig index 13057639403..f87ca8c3106 100644 --- a/drivers/phy/rockchip/Kconfig +++ b/drivers/phy/rockchip/Kconfig @@ -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 diff --git a/drivers/phy/rockchip/Makefile b/drivers/phy/rockchip/Makefile index a236877234b..25a803a8a86 100644 --- a/drivers/phy/rockchip/Makefile +++ b/drivers/phy/rockchip/Makefile @@ -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 diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c new file mode 100644 index 00000000000..9ed7af0d6ef --- /dev/null +++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c @@ -0,0 +1,680 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Rockchip Electronics Co. Ltd. + * + * Author: Wyon Bi + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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), +}; From 6fa83833b01c9fcd8297b71c8465df3c7fe6db31 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Fri, 24 Mar 2023 13:53:07 -0500 Subject: [PATCH 24/58] rockchip: video: Add support for RK3568 DSI Host Add support for DSI Host controller on Rockchip RK3568. This driver is heavily based on the Rockchip dw_mipi_dsi_rockchip.c driver in Linux and the stm32_dsi.c driver in U-Boot. It should be easy to add support for other SoCs as the only missing component from the mainline driver is setting the VOP big or VOP little (which the rk3568 does not have). Driver was tested for use in sending commands to a DSI panel in order to obtain the panel ID. Signed-off-by: Chris Morgan Reviewed-by: Kever Yang --- drivers/video/dw_mipi_dsi.c | 9 + drivers/video/rockchip/Kconfig | 8 + drivers/video/rockchip/Makefile | 1 + drivers/video/rockchip/dw_mipi_dsi_rockchip.c | 898 ++++++++++++++++++ 4 files changed, 916 insertions(+) create mode 100644 drivers/video/rockchip/dw_mipi_dsi_rockchip.c diff --git a/drivers/video/dw_mipi_dsi.c b/drivers/video/dw_mipi_dsi.c index 6d9c5a94761..a4606923ffc 100644 --- a/drivers/video/dw_mipi_dsi.c +++ b/drivers/video/dw_mipi_dsi.c @@ -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); diff --git a/drivers/video/rockchip/Kconfig b/drivers/video/rockchip/Kconfig index b03866347b0..01804dcb1cc 100644 --- a/drivers/video/rockchip/Kconfig +++ b/drivers/video/rockchip/Kconfig @@ -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 diff --git a/drivers/video/rockchip/Makefile b/drivers/video/rockchip/Makefile index 9aced5ef3f4..8128289cc82 100644 --- a/drivers/video/rockchip/Makefile +++ b/drivers/video/rockchip/Makefile @@ -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 diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c new file mode 100644 index 00000000000..ca548a60b75 --- /dev/null +++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c @@ -0,0 +1,898 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Author(s): Chris Morgan + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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), +}; From 999680c4ed80e21e014e94c9bdb79c45a5a5a853 Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 27 Mar 2023 12:01:08 +0100 Subject: [PATCH 25/58] rockchip: misc: fix misc_read() return check misc_read() is documented to return the number of bytes read or a negative error value. The Rockchip drivers currently do not implement this correctly and instead return zero on success or a negative error value. In preparation for fixing the drivers, fix the condition here to only error on negative values. Suggested-by: Jonas Karlman Signed-off-by: John Keeping Reviewed-by: Simon Glass Reviewed-by: Kever Yang --- arch/arm/mach-rockchip/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-rockchip/misc.c b/arch/arm/mach-rockchip/misc.c index 849014d2fb7..7d03f0c2b67 100644 --- a/arch/arm/mach-rockchip/misc.c +++ b/arch/arm/mach-rockchip/misc.c @@ -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; From a48d13535a40b818f76c659602be70db6ebaa07a Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 27 Mar 2023 12:01:09 +0100 Subject: [PATCH 26/58] rockchip: efuse: fix misc_read() return values The documentation for misc_read() says: Return: number of bytes read if OK (may be 0 if EOF), -ve on error The Rockchip efuse driver implements this so it should return the number of bytes read rather than zero on success. Fix this so that the driver follows the usual contract for read operations. Reviewed-by: Simon Glass Reviewed-by: Jonas Karlman Signed-off-by: John Keeping Reviewed-by: Kever Yang --- drivers/misc/rockchip-efuse.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/misc/rockchip-efuse.c b/drivers/misc/rockchip-efuse.c index 60931a51312..2f96b79ea40 100644 --- a/drivers/misc/rockchip-efuse.c +++ b/drivers/misc/rockchip-efuse.c @@ -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 = { From 9fea3696efceb8223f8e1121077763f1295cc65f Mon Sep 17 00:00:00 2001 From: John Keeping Date: Mon, 27 Mar 2023 12:01:10 +0100 Subject: [PATCH 27/58] rockchip: otp: fix misc_read() return values The documentation for misc_read() says: Return: number of bytes read if OK (may be 0 if EOF), -ve on error The Rockchip efuse driver implements this so it should return the number of bytes read rather than zero on success. Fix this so that the driver follows the usual contract for read operations. Reviewed-by: Simon Glass Reviewed-by: Jonas Karlman Signed-off-by: John Keeping Reviewed-by: Kever Yang --- drivers/misc/rockchip-otp.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/misc/rockchip-otp.c b/drivers/misc/rockchip-otp.c index c19cd5ce625..4814e0e501c 100644 --- a/drivers/misc/rockchip-otp.c +++ b/drivers/misc/rockchip-otp.c @@ -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 = { From f1e190a192d933f4155e5ea847e64171fb765289 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:14 +0000 Subject: [PATCH 28/58] rockchip: rk3588-rock-5b: Fix sdmmc boot Running U-Boot from a SD-card on ROCK 5 Model B fails to load atf using DMA and prints debug_uart messages. U-Boot SPL 2023.04-rc3 (Mar 12 2023 - 00:30:16 +0000) Trying to boot from MMC1 ## Checking hash(es) for config config-1 ... OK ## Checking hash(es) for Image atf-1 ... sha256 error! Bad hash value for 'hash' hash node in 'atf-1' image node mmc_load_image_raw_sector: mmc block read error SPL: failed to boot from all boot devices ### ERROR ### Please RESET the board ### Use fifo-mode to disable DMA in SPL, add same-as-spl to boot-order and remove DEBUG_UART_ANNOUNCE option to fix this. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- arch/arm/dts/rk3588-rock-5b-u-boot.dtsi | 3 ++- configs/rock5b-rk3588_defconfig | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi index bee4c32e896..b61d6e0fdbf 100644 --- a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi +++ b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi @@ -11,12 +11,13 @@ }; chosen { - u-boot,spl-boot-order = &sdmmc; + u-boot,spl-boot-order = "same-as-spl", &sdmmc; }; }; &sdmmc { bus-width = <4>; bootph-pre-ram; + u-boot,spl-fifo-mode; status = "okay"; }; diff --git a/configs/rock5b-rk3588_defconfig b/configs/rock5b-rk3588_defconfig index 66199387195..3fcc6a26bb5 100644 --- a/configs/rock5b-rk3588_defconfig +++ b/configs/rock5b-rk3588_defconfig @@ -66,6 +66,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_ERRNO_STR=y From 9f412347beb2ad566fa38e8c3e96cc5bd07d36f5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:15 +0000 Subject: [PATCH 29/58] rockchip: rk35xx: Fix boot with a large fdt blob The TF-A blobs used to boot RK3568 and RK3588 boards is based on atf v2.3. Mainline atf v2.3 contains an issue that could lead to a crash when it fails to parse the fdt blob being passed as the platform param. An issue that was fixed in atf v2.4. The vendor TF-A seem to suffer from a similar issue, and this prevents booting when fdt blob is large enough to trigger this condition. Fix this by implying SPL_ATF_NO_PLATFORM_PARAM to let u-boot pass a NULL pointer instead of the fdt blob as the platform param. This fixes booting Radxa ROCK 3A after recent sync of device tree. Fixes: 073d911ae64a ("rockchip: rk3568-rock-3a: Sync device tree from linux") Signed-off-by: Jonas Karlman --- arch/arm/mach-rockchip/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 39cf4b99393..50edef0d13d 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -288,6 +288,7 @@ 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 ROCKCHIP_OTP imply MISC_INIT_R @@ -309,6 +310,7 @@ 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 ROCKCHIP_OTP imply MISC_INIT_R From e1962a9efec99152f55665eb2501005551747979 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:17 +0000 Subject: [PATCH 30/58] rockchip: rk35xx: Enable fdtoverlay and kernel compression Add fdtoverlay_addr_r, kernel_comp_addr_r and imply use of OF_LIBFDT_OVERLAY on RK3568 and RK3588 to support fdtoverlay and kernel compression. Signed-off-by: Jonas Karlman Reviewed-by: Simon Glass --- arch/arm/mach-rockchip/Kconfig | 2 ++ include/configs/rk3568_common.h | 7 ++++++- include/configs/rk3588_common.h | 7 ++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 50edef0d13d..ce632f757ff 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -290,6 +290,7 @@ config ROCKCHIP_RK3568 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 @@ -312,6 +313,7 @@ config ROCKCHIP_RK3588 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 help diff --git a/include/configs/rk3568_common.h b/include/configs/rk3568_common.h index a5e1dde5088..d6b5e7d8902 100644 --- a/include/configs/rk3568_common.h +++ b/include/configs/rk3568_common.h @@ -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 #define CFG_EXTRA_ENV_SETTINGS \ diff --git a/include/configs/rk3588_common.h b/include/configs/rk3588_common.h index abd20139aaf..b9f42717b75 100644 --- a/include/configs/rk3588_common.h +++ b/include/configs/rk3588_common.h @@ -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 #define CFG_EXTRA_ENV_SETTINGS \ From 22297581187c346740d5af4ee603701142b58fd6 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:18 +0000 Subject: [PATCH 31/58] clk: scmi: Add Kconfig option for SPL Building U-Boot SPL with CLK_SCMI and SCMI_FIRMWARE Kconfig options enabled and SPL_FIRMWARE disabled result in the following error. drivers/clk/clk_scmi.o: in function `scmi_clk_gate': drivers/clk/clk_scmi.c:84: undefined reference to `devm_scmi_process_msg' drivers/clk/clk_scmi.c:88: undefined reference to `scmi_to_linux_errno' drivers/clk/clk_scmi.o: in function `scmi_clk_get_rate': drivers/clk/clk_scmi.c:113: undefined reference to `devm_scmi_process_msg' drivers/clk/clk_scmi.c:117: undefined reference to `scmi_to_linux_errno' drivers/clk/clk_scmi.o: in function `scmi_clk_set_rate': drivers/clk/clk_scmi.c:139: undefined reference to `devm_scmi_process_msg' drivers/clk/clk_scmi.c:143: undefined reference to `scmi_to_linux_errno' drivers/clk/clk_scmi.o: in function `scmi_clk_probe': drivers/clk/clk_scmi.c:157: undefined reference to `devm_scmi_of_get_channel' make[1]: *** [scripts/Makefile.spl:527: spl/u-boot-spl] Error 1 make: *** [Makefile:2043: spl/u-boot-spl] Error 2 Add Kconfig option so that CLK_SCMI can be disabled in SPL to fix this. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/clk/Kconfig | 8 ++++++++ drivers/clk/Makefile | 2 +- drivers/firmware/scmi/scmi_agent-uclass.c | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 42280cbf83a..19269c7fd4d 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -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 diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index c274cda77c6..c1347774b58 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -39,7 +39,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 diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c index 9a32678617d..54d563d929b 100644 --- a/drivers/firmware/scmi/scmi_agent-uclass.c +++ b/drivers/firmware/scmi/scmi_agent-uclass.c @@ -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: From 6737771600d4fd8eb48663ea8da37f3f4f49aad5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:20 +0000 Subject: [PATCH 32/58] rockchip: rk3588: Add support for sdmmc clocks in SPL Booting from sdmmc on RK3588 currently works because of a workaround in the device tree, clocks are reordered so that the driver use ciu-sample instead of ciu, and the BootRom initializes sdmmc clocks before SPL is loaded into DRAM. The sdmmc clocks are normally controlled by TF-A using SCMI. However, there is a need to control these clocks in SPL, before TF-A has started. This adds a rk3588_scru driver to control the sdmmc clocks in SPL before TF-A has started, using scru regs. It also adds a small glue driver to bind the scmi clock node to the rk3588_scru driver in SPL. Fixes: 7a474df74023 ("clk: rockchip: Add rk3588 clk support") Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- arch/arm/include/asm/arch-rockchip/clock.h | 1 - .../include/asm/arch-rockchip/cru_rk3588.h | 19 ++- drivers/clk/rockchip/clk_rk3588.c | 125 ++++++++++++++++++ 3 files changed, 143 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/arch-rockchip/clock.h b/arch/arm/include/asm/arch-rockchip/clock.h index 90e66c7da04..f002ebcb7ac 100644 --- a/arch/arm/include/asm/arch-rockchip/clock.h +++ b/arch/arm/include/asm/arch-rockchip/clock.h @@ -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 diff --git a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h index 3ea59e90086..7f4a9085392 100644 --- a/arch/arm/include/asm/arch-rockchip/cru_rk3588.h +++ b/arch/arm/include/asm/arch-rockchip/cru_rk3588.h @@ -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 diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c index a7df553e875..41e31b61a55 100644 --- a/drivers/clk/rockchip/clk_rk3588.c +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -1994,3 +1995,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 From 58c23015c99ef86daecbc44dd6c2bc23803435e1 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:21 +0000 Subject: [PATCH 33/58] rockchip: rk3588: Sync sdmmc node from linux-next Sync the sdmmc node from linux-next, include required nodes in SPL and imply Kconfig options required for functional sdmmc clk in SPL and U-Boot proper. This make it possible for both SPL and U-Boot proper to configure sdmmc clocks. In SPL, before TF-A is loaded, scru regs is configured, in U-Boot proper a SCMI message is sent to TF-A. Fixes: 95c8656b72dc ("ARM: dts: rockchip: rk3588s-u-boot: Add sdmmc node") Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- .../dts/rk3588-edgeble-neu6a-io-u-boot.dtsi | 2 -- arch/arm/dts/rk3588-rock-5b-u-boot.dtsi | 2 -- arch/arm/dts/rk3588s-u-boot.dtsi | 27 +++++++++---------- arch/arm/dts/rk3588s.dtsi | 15 +++++++++++ arch/arm/mach-rockchip/Kconfig | 2 ++ 5 files changed, 30 insertions(+), 18 deletions(-) diff --git a/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi b/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi index 3235bd36e4c..373f369c655 100644 --- a/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi +++ b/arch/arm/dts/rk3588-edgeble-neu6a-io-u-boot.dtsi @@ -18,7 +18,5 @@ &sdmmc { bus-width = <4>; - bootph-all; - u-boot,spl-fifo-mode; status = "okay"; }; diff --git a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi index b61d6e0fdbf..4c6f0311d6a 100644 --- a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi +++ b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi @@ -17,7 +17,5 @@ &sdmmc { bus-width = <4>; - bootph-pre-ram; - u-boot,spl-fifo-mode; status = "okay"; }; diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 1e225d71efc..3cb22f35420 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -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 = ; - 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>; @@ -60,6 +46,19 @@ status = "okay"; }; +&scmi { + bootph-pre-ram; +}; + +&scmi_clk { + bootph-pre-ram; +}; + +&sdmmc { + bootph-pre-ram; + u-boot,spl-fifo-mode; +}; + &uart2 { clock-frequency = <24000000>; bootph-pre-ram; diff --git a/arch/arm/dts/rk3588s.dtsi b/arch/arm/dts/rk3588s.dtsi index 005cde61b4b..fca8503aed8 100644 --- a/arch/arm/dts/rk3588s.dtsi +++ b/arch/arm/dts/rk3588s.dtsi @@ -1099,6 +1099,21 @@ }; }; + sdmmc: mmc@fe2c0000 { + compatible = "rockchip,rk3588-dw-mshc", "rockchip,rk3288-dw-mshc"; + reg = <0x0 0xfe2c0000 0x0 0x4000>; + interrupts = ; + 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>; diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index ce632f757ff..327779a7981 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -316,6 +316,8 @@ config ROCKCHIP_RK3588 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, From 518fa3441e1f04806e6151baae4dd4c694a46948 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:23 +0000 Subject: [PATCH 34/58] pinctrl: rockchip: Fix IO mux selection on RK3568 IO mux selection is not working correctly for all pins. Sync mux route data from linux to add any missing and update wrong trigger pins to fix this. Also apply the pull-up fix needed for GPIO0 D3-D6. Fixes: 1977d746aa54 ("rockchip: rk3568: add rk3568 pinctrl driver") Signed-off-by: Jonas Karlman --- drivers/pinctrl/rockchip/pinctrl-rk3568.c | 66 +++++++++++++---------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3568.c b/drivers/pinctrl/rockchip/pinctrl-rk3568.c index 935aed9efc6..314edb5a606 100644 --- a/drivers/pinctrl/rockchip/pinctrl-rk3568.c +++ b/drivers/pinctrl/rockchip/pinctrl-rk3568.c @@ -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); From 45717d6efd7ad3acc4a49490746221bae00d7c15 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Mon, 17 Apr 2023 19:07:25 +0000 Subject: [PATCH 35/58] clk: rockchip: rk3568: Add dummy I2S1_MCLKOUT_TX clock support A RK3568 device tree pmic node can reference the I2S1_MCLKOUT_TX clock in assigned-clocks, add dummy support to set parent of this clock to the rk3568 cru driver. Fixes probe of pmic driver and missing regulators on affected boards, rk3568-evb and rk3568-rock-3a. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/clk/rockchip/clk_rk3568.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/rockchip/clk_rk3568.c b/drivers/clk/rockchip/clk_rk3568.c index 1c6adc56f91..cefc263971a 100644 --- a/drivers/clk/rockchip/clk_rk3568.c +++ b/drivers/clk/rockchip/clk_rk3568.c @@ -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; } From 5891282bf399b073eb747269117732a7de2845ed Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 13 Apr 2023 09:13:02 -0500 Subject: [PATCH 36/58] rockchip: rng: add trngv1 for rk3588 This adds support for the TRNG found in the RK3588 SoC to the rockchip_rng driver so that it can be used for things such as seeding randomness to Linux. Changes in V3: - Moved notes from commit to cover letter. - Added Reviewed-By tag. Changes in V2: - Modified Kconfig to note that the Rockchip RNG driver supports all versions of the hardware (v1, v2, and the trng in the rk3588). Signed-off-by: Lin Jinhan Signed-off-by: Chris Morgan Reviewed-by: Kever Yang --- drivers/rng/Kconfig | 5 +- drivers/rng/rockchip_rng.c | 120 ++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/drivers/rng/Kconfig b/drivers/rng/Kconfig index 5dcf68176af..5deb5db5b71 100644 --- a/drivers/rng/Kconfig +++ b/drivers/rng/Kconfig @@ -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" diff --git a/drivers/rng/rockchip_rng.c b/drivers/rng/rockchip_rng.c index 800150f1147..705b424cf3d 100644 --- a/drivers/rng/rockchip_rng.c +++ b/drivers/rng/rockchip_rng.c @@ -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, }, {}, }; From f89167bb74086fddc95290a6171e4dd9953b34c2 Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 13 Apr 2023 09:13:03 -0500 Subject: [PATCH 37/58] ARM: dts: rockchip: rk3588s-u-boot: Add rng node Add a node for the trng found on RK3588 SoCs. Changes in V3: - Added Reviewed-By tag. Changes in V2: - None Signed-off-by: Chris Morgan Reviewed-by: Kever Yang Acked-by: Sughosh Ganu --- arch/arm/dts/rk3588s-u-boot.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 3cb22f35420..76a8ffe8c33 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -29,6 +29,12 @@ reg = <0x07 0x10>; }; }; + + rng: rng@fe378000 { + compatible = "rockchip,trngv1"; + reg = <0x0 0xfe378000 0x0 0x200>; + status = "disabled"; + }; }; &xin24m { From 7774b7929961ec5b69cec95a0acc51d10e7564ed Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:23 +0000 Subject: [PATCH 38/58] mmc: sdhci: Fix HISPD bit handling for MMC HS 52MHz mode Set High Speed Enable bit for MMC High Speed (52MHz) mode. Fixes: f12341a95295 ("mmc: sdhci: Fix HISPD bit handling") Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/sdhci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index c6b250b9a1b..1389c18533f 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -682,6 +682,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 || From c1425ed8f873a1739874639bc120aab89a443539 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:24 +0000 Subject: [PATCH 39/58] mmc: sdhci: Set UHS Mode Select field for UHS SDR25 mode Set correct UHS Mode Select field value for UHS SDR25 (50MHz) mode. Fixes: d1c0a2200afb ("mmc: sdhci: Add support for HOST_CONTROL2 and setting UHS timings") Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/sdhci.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 1389c18533f..86f81f5dfaf 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -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; From b8c394b7268d5a8f927b30296ffe9cb4d71b06fc Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:26 +0000 Subject: [PATCH 40/58] mmc: rockchip_sdhci: Fix use of device private data The device private data is misused in rockchip_sdhci_of_to_plat and rockchip_sdhci_execute_tuning. In these functions dev_get_priv is assigned to struct sdhci_host: struct sdhci_host *host = dev_get_priv(dev); Instead, the sdhci host should refer to host in struct rockchip_sdhc: struct rockchip_sdhc *priv = dev_get_priv(dev); struct sdhci_host *host = &priv->host; Because host is the first member in struct rockchip_sdhc this is not a real problem, lets fix it anyway and also use priv name consistently. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index fef23f593e8..3fac2352cfb 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -450,7 +450,8 @@ static int rockchip_sdhci_set_ios_post(struct sdhci_host *host) 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; @@ -531,9 +532,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 +548,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); @@ -566,7 +567,7 @@ static int rockchip_sdhci_probe(struct udevice *dev) 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; @@ -580,8 +581,9 @@ static int rockchip_sdhci_probe(struct udevice *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; From 0030d4971561c20edf66a76952ba32e5adf77ff5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:27 +0000 Subject: [PATCH 41/58] mmc: rockchip_sdhci: Remove unneeded emmc_phy_init Remove the unneeded emmc_phy_init now that the no-inverter flag is handled correctly after commit 2321a991bbb5 ("rockchip: sdhci: rk3568: bypass DLL when clk <= 52 MHz"). Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 3fac2352cfb..e64c0fdb4cc 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -112,7 +112,6 @@ struct rockchip_sdhc { }; struct sdhci_data { - int (*emmc_phy_init)(struct udevice *dev); int (*get_phy)(struct udevice *dev); /** @@ -154,11 +153,6 @@ struct sdhci_data { int (*set_enhanced_strobe)(struct sdhci_host *host); }; -static int rk3399_emmc_phy_init(struct udevice *dev) -{ - return 0; -} - static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock) { u32 caldone, dllrdy, freqsel; @@ -294,18 +288,6 @@ 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) { struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host); @@ -557,12 +539,6 @@ 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; @@ -605,7 +581,6 @@ 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, @@ -613,7 +588,6 @@ static const struct sdhci_data rk3399_data = { 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, }; From 7e74522d5fbf2409974300d5de3e67e9c536a181 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:29 +0000 Subject: [PATCH 42/58] mmc: rockchip_sdhci: Add set_clock and config_dll sdhci_ops Add support for the set_clock and config_dll sdhci_ops. Use of these ops will allow configuration of DLL while the output clock is disabled. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index e64c0fdb4cc..4a41e727017 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -139,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 * @@ -430,6 +433,15 @@ 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 rockchip_sdhc *priv = dev_get_priv(mmc->dev); @@ -491,6 +503,17 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) 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); @@ -503,9 +526,11 @@ static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host) } 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, }; From b8a63c869cafc1509193b6b7544c03fcdd0265ca Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Thu, 20 Apr 2023 15:55:15 +0000 Subject: [PATCH 43/58] mmc: rockchip_sdhci: Use set_clock and config_dll sdhci_ops Change to configure clock and DLL in set_clock and config_dll ops instead of in the set_ios_post ops. With this change the output clock is turned off while configuring DLL parameters, according to the design recommendations. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 4a41e727017..fdf48f4066c 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -291,18 +291,24 @@ static int rk3399_sdhci_set_ios_post(struct sdhci_host *host) 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) +{ int val, ret; u32 extra; - 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 */ @@ -386,14 +392,8 @@ static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host) static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; - uint clock = mmc->clock; u32 reg, vendor_reg; - if (mmc->tran_speed && mmc->clock > mmc->tran_speed) - clock = mmc->tran_speed; - - 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; @@ -614,6 +614,8 @@ static const struct sdhci_data rk3399_data = { static const struct sdhci_data rk3568_data = { .get_phy = rk3568_emmc_get_phy, .set_ios_post = rk3568_sdhci_set_ios_post, + .set_clock = rk3568_sdhci_set_clock, + .config_dll = rk3568_sdhci_config_dll, .set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe, }; From ba9f5e541d78b7200fc7fa56e4e056c3b92ea451 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:31 +0000 Subject: [PATCH 44/58] mmc: rockchip_sdhci: Refactor execute tuning error handling Check return value from mmc_send_cmd and clear HOST_CONTROL2 when there is an error. Also skip enable of interrupt signaling and remove a delay, a delay is already happening in sdhci_send_command. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index fdf48f4066c..e56043fce88 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -449,17 +449,16 @@ static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode) 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); @@ -469,36 +468,24 @@ 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; } From 6de4438576ed5c8e099b52f5ee6ad549dca6aa9d Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:33 +0000 Subject: [PATCH 45/58] mmc: rockchip_sdhci: Update speed mode controls in set_ios_post Refactor set_ios_post ops to correctly set UHS Speed Select field values according to TRM. Also set or unset Enhanced Strobe Enable bit and eMMC Card present bit in set_ios_post, the Enhanced Strobe Enable bit was never unset after switching to HS400ES mode. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 70 ++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index e56043fce88..8e29430a483 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -372,20 +372,6 @@ static int rk3568_emmc_get_phy(struct udevice *dev) 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; } @@ -394,22 +380,52 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) struct mmc *mmc = host->mmc; u32 reg, vendor_reg; - 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; - reg |= DWCMSHC_CTRL_HS400; - sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); + reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); + reg &= ~SDHCI_CTRL_UHS_MASK; - 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); + 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; + break; + default: + reg |= SDHCI_CTRL_UHS_SDR12; } + sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); + + vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK) + + DWCMSHC_EMMC_CONTROL; + reg = sdhci_readw(host, vendor_reg); + + 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, vendor_reg); + return 0; } From 667576c59d492116b0c4ffc0194b3b86b84c85e3 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:34 +0000 Subject: [PATCH 46/58] mmc: rockchip_sdhci: Remove empty get_phy and set_enhanced_strobe ops Remove empty implementations of get_phy and set_enhanced_strobe ops. Change driver set_enhanced_strobe to return 0 in order to allow missing implementation of the ops. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 8e29430a483..9716fbb54dd 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -365,16 +365,6 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab return 0; } -static int rk3568_emmc_get_phy(struct udevice *dev) -{ - return 0; -} - -static int rk3568_sdhci_set_enhanced_strobe(struct sdhci_host *host) -{ - return 0; -} - static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; @@ -525,7 +515,7 @@ 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 = { @@ -615,11 +605,9 @@ static const struct sdhci_data rk3399_data = { }; static const struct sdhci_data rk3568_data = { - .get_phy = rk3568_emmc_get_phy, .set_ios_post = rk3568_sdhci_set_ios_post, .set_clock = rk3568_sdhci_set_clock, .config_dll = rk3568_sdhci_config_dll, - .set_enhanced_strobe = rk3568_sdhci_set_enhanced_strobe, }; static const struct udevice_id sdhci_ids[] = { From 8874c417ab87e559c018461effca1191e1c45fe5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:35 +0000 Subject: [PATCH 47/58] mmc: rockchip_sdhci: Rearrange and simplify used regs and flags This rearrange and remove duplicate defines to make the code cleaner. There is no need to read vendor area1 and use an offset each time, it is easier and clearer to just use the reg offset defined in TRM, same as the other vendor regs. This also removes use of the misspelled const for the RK3588 CMDOUT reg, it will be re-added when support for RK3588 is introduced. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 40 ++++++++++++------------------------ 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 9716fbb54dd..bcf65e09174 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -47,46 +47,36 @@ #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_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_RXCLK_NO_INVERTER BIT(29) +#define DLL_RXCLK_ORI_GATE BIT(31) #define DLL_TXCLK_TAPNUM_DEFAULT 0xA - +#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) #define DLL_STRBIN_TAPNUM_DEFAULT 0x8 #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_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)) @@ -328,8 +318,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab 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_NO_INVERTER; sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); extra = DWCMSHC_EMMC_DLL_DLYENA | @@ -346,10 +335,9 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab * 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); /* * Before switching to hs400es mode, the driver will enable @@ -368,7 +356,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) { struct mmc *mmc = host->mmc; - u32 reg, vendor_reg; + u32 reg; reg = sdhci_readw(host, SDHCI_HOST_CONTROL2); reg &= ~SDHCI_CTRL_UHS_MASK; @@ -400,9 +388,7 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) sdhci_writew(host, reg, SDHCI_HOST_CONTROL2); - vendor_reg = (sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK) - + DWCMSHC_EMMC_CONTROL; - reg = sdhci_readw(host, vendor_reg); + reg = sdhci_readw(host, DWCMSHC_EMMC_EMMC_CTRL); if (IS_MMC(mmc)) reg |= DWCMSHC_CARD_IS_EMMC; @@ -414,7 +400,7 @@ static int rk3568_sdhci_set_ios_post(struct sdhci_host *host) else reg &= ~DWCMSHC_ENHANCED_STROBE; - sdhci_writew(host, reg, vendor_reg); + sdhci_writew(host, reg, DWCMSHC_EMMC_EMMC_CTRL); return 0; } From d2cece03003ea811a42d471a4733276391f4e1bf Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:37 +0000 Subject: [PATCH 48/58] mmc: rockchip_sdhci: Fix HS400 and HS400ES mode on RK3568 Adjust tap number for transmit clock, tap number and delay number for strobe input to fix HS400 modes on RK3568. New values have been picked from vendor kernel and u-boot and have successfully been tested with rock-3a-rk3568_defconfig and CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_HS400_SUPPORT=y CONFIG_MMC_HS400_ES_SUPPORT=y CONFIG_MMC_SPEED_MODE_SET=y using the following command to switch mode and then read 512 MiB of data from eMMC into memory, => mmc dev 0 0 && mmc info && mmc read 10000000 2000 10000 for each of the modes below. 0 = MMC legacy 1 = MMC High Speed (26MHz) 3 = MMC High Speed (52MHz) 4 = MMC DDR52 (52MHz) 10 = HS200 (200MHz) 11 = HS400 (200MHz) 12 = HS400ES (200MHz) Signed-off-by: Yifeng Zhao Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index bcf65e09174..12a616d3dfb 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -69,13 +69,13 @@ #define DWCMSHC_EMMC_DLL_DLYENA BIT(27) #define DLL_RXCLK_NO_INVERTER BIT(29) #define DLL_RXCLK_ORI_GATE BIT(31) -#define DLL_TXCLK_TAPNUM_DEFAULT 0xA +#define DLL_TXCLK_TAPNUM_DEFAULT 0x10 #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) -#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#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_LOCK_WO_TMOUT(x) \ ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ From 72b05764c38539558a46a15a6b005326af5785e7 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:38 +0000 Subject: [PATCH 49/58] rockchip: rk3568-rock-3a: Enable support for more eMMC modes Add supported mmc modes to rk3568-rock-3a device tree. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- arch/arm/dts/rk3568-rock-3a-u-boot.dtsi | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi index 9ef1e847706..10226b029ba 100644 --- a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi +++ b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi @@ -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"; }; From a3cab289f6fcb8e014260d278913d20575f16811 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:39 +0000 Subject: [PATCH 50/58] mmc: rockchip_sdhci: Add support for RK3588 Add support for RK3588 to the rockchip sdhci driver. Use driver data to handle differences between RK3568 and RK3588: - Set "Receive original clock source is auto gating" for RK3588. - Set "Receive clock source is no-inverted" only on RK3568 and "Transmit clock source is invertion of original clock input" for RK3588. - Use different txclk_tapnum for HS400 modes on RK3588. - Configure the CMDOUT reg for HS400 modes for RK3588. This is based on the mainline linux and vendor kernel driver and have successfully been tested with rock5b-rk3588_defconfig and CONFIG_MMC_HS200_SUPPORT=y CONFIG_MMC_HS400_SUPPORT=y CONFIG_MMC_HS400_ES_SUPPORT=y CONFIG_MMC_SPEED_MODE_SET=y using the following command to switch mode and then read 512 MiB of data from eMMC into memory, => mmc dev 0 0 && mmc info && mmc read 10000000 2000 10000 for each of the modes below. 0 = MMC legacy 1 = MMC High Speed (26MHz) 3 = MMC High Speed (52MHz) 4 = MMC DDR52 (52MHz) 10 = HS200 (200MHz) 11 = HS400 (200MHz) 12 = HS400ES (200MHz) Signed-off-by: Yifeng Zhao Signed-off-by: Jonas Karlman Reviewed-by: Shawn Lin Reviewed-by: Kever Yang --- drivers/mmc/rockchip_sdhci.c | 57 +++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 12a616d3dfb..2857dcc9ec4 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -56,6 +56,7 @@ #define DWCMSHC_EMMC_DLL_RXCLK 0x804 #define DWCMSHC_EMMC_DLL_TXCLK 0x808 #define DWCMSHC_EMMC_DLL_STRBIN 0x80c +#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) @@ -70,18 +71,27 @@ #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 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_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; @@ -144,6 +154,10 @@ struct sdhci_data { * Return: 0 if successful, -ve on error */ int (*set_enhanced_strobe)(struct sdhci_host *host); + + 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,8 +308,11 @@ static void rk3568_sdhci_set_clock(struct sdhci_host *host, u32 div) 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 (!enable) return 0; @@ -318,12 +335,28 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab if (ret) return ret; - extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_NO_INVERTER; + 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 | @@ -339,6 +372,7 @@ static int rk3568_sdhci_config_dll(struct sdhci_host *host, u32 clock, bool enab sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK); 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 @@ -594,6 +628,17 @@ static const struct sdhci_data rk3568_data = { .set_ios_post = rk3568_sdhci_set_ios_post, .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[] = { @@ -605,6 +650,10 @@ static const struct udevice_id sdhci_ids[] = { .compatible = "rockchip,rk3568-dwcmshc", .data = (ulong)&rk3568_data, }, + { + .compatible = "rockchip,rk3588-dwcmshc", + .data = (ulong)&rk3588_data, + }, { } }; From b564aa27405f79271dfbe35b7ec5041ea46bf1d1 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:41 +0000 Subject: [PATCH 51/58] rockchip: rk3588-rock-5b: Include eMMC node in SPL dtb Add sdhci node to SPL and u-boot,spl-boot-order. Also add more supported mmc modes and pinctrl. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- arch/arm/dts/rk3588-rock-5b-u-boot.dtsi | 12 ++++++++++-- arch/arm/dts/rk3588s-u-boot.dtsi | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi index 4c6f0311d6a..85075bf435f 100644 --- a/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi +++ b/arch/arm/dts/rk3588-rock-5b-u-boot.dtsi @@ -7,11 +7,11 @@ / { aliases { - mmc0 = &sdmmc; + mmc1 = &sdmmc; }; chosen { - u-boot,spl-boot-order = "same-as-spl", &sdmmc; + u-boot,spl-boot-order = "same-as-spl", &sdmmc, &sdhci; }; }; @@ -19,3 +19,11 @@ bus-width = <4>; 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>; +}; diff --git a/arch/arm/dts/rk3588s-u-boot.dtsi b/arch/arm/dts/rk3588s-u-boot.dtsi index 76a8ffe8c33..5201ba246d8 100644 --- a/arch/arm/dts/rk3588s-u-boot.dtsi +++ b/arch/arm/dts/rk3588s-u-boot.dtsi @@ -65,6 +65,10 @@ u-boot,spl-fifo-mode; }; +&sdhci { + bootph-pre-ram; +}; + &uart2 { clock-frequency = <24000000>; bootph-pre-ram; From bdbfd589745f1a7042144a222fa1e741066cc839 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:42 +0000 Subject: [PATCH 52/58] clk: rockchip: rk3588: Add limited TMCLK_EMMC clock support The device tree sdhci node reference the TMCLK_EMMC clock, add limited support this clock to rk3588 cru driver. Fixes probe of sdhci driver. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- drivers/clk/rockchip/clk_rk3588.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/rockchip/clk_rk3588.c b/drivers/clk/rockchip/clk_rk3588.c index 41e31b61a55..d0cc19b4788 100644 --- a/drivers/clk/rockchip/clk_rk3588.c +++ b/drivers/clk/rockchip/clk_rk3588.c @@ -1553,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; @@ -1702,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; From 3cd664dc92ca832506f1a4e7769cb5ee6a88137d Mon Sep 17 00:00:00 2001 From: Peter Geis Date: Tue, 18 Apr 2023 16:46:44 +0000 Subject: [PATCH 53/58] mmc: sdhci: Allow disabling of SDMA in SPL Rockchip emmc devices have a similar issue to Rockchip dwmmc devices, where performing DMA to SRAM later causes issues with suspend/resume. Allow us to toggle SDMA in SPL for sdhci similar to ADMA support, so we can ensure DMA is not used when loading the SRAM code. Signed-off-by: Peter Geis Reviewed-by: Jaehoon Chung Reviewed-by: Kever Yang [jonas@kwiboo.se: add Kconfig default value and fix ADMA typo] Signed-off-by: Jonas Karlman --- drivers/mmc/Kconfig | 8 ++++++++ drivers/mmc/sdhci.c | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index 59fb0fb50fb..de01b9687ba 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -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 diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 86f81f5dfaf..9cbe126106c 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -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 @@ -877,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 { @@ -887,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; } From 2cc6cde647e2cf61a29f389e8d263bf19672f0f5 Mon Sep 17 00:00:00 2001 From: Jonas Karlman Date: Tue, 18 Apr 2023 16:46:45 +0000 Subject: [PATCH 54/58] mmc: rockchip_sdhci: Limit number of blocks read in a single command Using DMA to load TF-A into SRAM fails when booting from eMMC on RK3588. ## Checking hash(es) for Image atf-3 ... sha256 error! Bad hash value for 'hash' hash node in 'atf-3' image node spl_load_simple_fit: can't load image loadables index 2 (ret = -1) mmc_load_image_raw_sector: mmc block read error Fix this by using PIO mode in SPL and limit the number of blocks used in a single read command to avoid triggering Data End Bit Error interrupt. Signed-off-by: Jonas Karlman Reviewed-by: Kever Yang --- configs/rock5b-rk3588_defconfig | 1 + drivers/mmc/rockchip_sdhci.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/configs/rock5b-rk3588_defconfig b/configs/rock5b-rk3588_defconfig index 3fcc6a26bb5..d3136ac850f 100644 --- a/configs/rock5b-rk3588_defconfig +++ b/configs/rock5b-rk3588_defconfig @@ -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 diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c index 2857dcc9ec4..4f110976f4e 100644 --- a/drivers/mmc/rockchip_sdhci.c +++ b/drivers/mmc/rockchip_sdhci.c @@ -589,6 +589,14 @@ 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); } From 0d368701e2db3f3d29785baef02265f9a0cbd933 Mon Sep 17 00:00:00 2001 From: FUKAUMI Naoki Date: Thu, 20 Apr 2023 12:00:38 +0000 Subject: [PATCH 55/58] configs: rockchip: rock-3a: make usb host work add support for USB host function on ROCK 3A Signed-off-by: FUKAUMI Naoki Reviewed-by: Kever Yang --- configs/rock-3a-rk3568_defconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig index af1374549dd..1eb12e80d17 100644 --- a/configs/rock-3a-rk3568_defconfig +++ b/configs/rock-3a-rk3568_defconfig @@ -39,6 +39,7 @@ 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_SPL_DOS_PARTITION is not set CONFIG_SPL_OF_CONTROL=y @@ -58,6 +59,8 @@ 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 @@ -69,4 +72,12 @@ CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYS_NS16550_MEM32=y CONFIG_SYSRESET=y +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 From fecdeeaec18fea00f18e767dc1d44359752e968b Mon Sep 17 00:00:00 2001 From: FUKAUMI Naoki Date: Thu, 20 Apr 2023 12:00:39 +0000 Subject: [PATCH 56/58] configs: rockchip: radxa-cm3-io, rock-3a: enable commands for i2c/pmic/regulator enable commands for i2c/pmic/regulator and relevant configs. also drop configs for unused regulators. Signed-off-by: FUKAUMI Naoki Reviewed-by: Kever Yang --- configs/radxa-cm3-io-rk3566_defconfig | 8 ++++++-- configs/rock-3a-rk3568_defconfig | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/configs/radxa-cm3-io-rk3566_defconfig b/configs/radxa-cm3-io-rk3566_defconfig index 2100cf2cb2c..9b99181714e 100644 --- a/configs/radxa-cm3-io-rk3566_defconfig +++ b/configs/radxa-cm3-io-rk3566_defconfig @@ -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 diff --git a/configs/rock-3a-rk3568_defconfig b/configs/rock-3a-rk3568_defconfig index 1eb12e80d17..f0db15baa30 100644 --- a/configs/rock-3a-rk3568_defconfig +++ b/configs/rock-3a-rk3568_defconfig @@ -41,6 +41,8 @@ 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 @@ -64,7 +66,6 @@ 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 From 7911f409ff20dce5995cc1b703a6e30c94022f6b Mon Sep 17 00:00:00 2001 From: FUKAUMI Naoki Date: Thu, 20 Apr 2023 12:00:40 +0000 Subject: [PATCH 57/58] arm: dts: rockchip: radxa-cm3-io, rock-3a: enable regulators for usb enable regulators for usb host function Signed-off-by: FUKAUMI Naoki Reviewed-by: Kever Yang --- arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi | 4 ++++ arch/arm/dts/rk3568-rock-3a-u-boot.dtsi | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi b/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi index 4e791738335..d183e935754 100644 --- a/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi +++ b/arch/arm/dts/rk3566-radxa-cm3-io-u-boot.dtsi @@ -16,3 +16,7 @@ bootph-all; status = "okay"; }; + +&vcc5v0_usb30 { + regulator-boot-on; +}; diff --git a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi index 10226b029ba..801c91af5b4 100644 --- a/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi +++ b/arch/arm/dts/rk3568-rock-3a-u-boot.dtsi @@ -34,3 +34,11 @@ bootph-all; status = "okay"; }; + +&vcc5v0_usb_host { + regulator-boot-on; +}; + +&vcc5v0_usb_hub { + regulator-boot-on; +}; From a1c68192549246fe80a6f931986b8e9d5651cb16 Mon Sep 17 00:00:00 2001 From: FUKAUMI Naoki Date: Thu, 20 Apr 2023 12:00:41 +0000 Subject: [PATCH 58/58] configs: rockchip: radxa-cm3-io: drop CONFIG_USB_DWC3_GENERIC it's not used by rk35xx Signed-off-by: FUKAUMI Naoki --- configs/radxa-cm3-io-rk3566_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/configs/radxa-cm3-io-rk3566_defconfig b/configs/radxa-cm3-io-rk3566_defconfig index 9b99181714e..1df9cab79d5 100644 --- a/configs/radxa-cm3-io-rk3566_defconfig +++ b/configs/radxa-cm3-io-rk3566_defconfig @@ -77,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