diff options
24 files changed, 1106 insertions, 19 deletions
diff --git a/arch/arm/dts/rk3328-rock64-u-boot.dtsi b/arch/arm/dts/rk3328-rock64-u-boot.dtsi index 8318bf4e60..f076075076 100644 --- a/arch/arm/dts/rk3328-rock64-u-boot.dtsi +++ b/arch/arm/dts/rk3328-rock64-u-boot.dtsi @@ -11,6 +11,22 @@ }; }; +&gpio0 { + u-boot,dm-spl; +}; + +&pinctrl { + u-boot,dm-spl; +}; + +&sdmmc0m1_gpio { + u-boot,dm-spl; +}; + +&pcfg_pull_up_4ma { + u-boot,dm-spl; +}; + &usb_host0_xhci { vbus-supply = <&vcc_host_5v>; status = "okay"; @@ -25,3 +41,8 @@ /delete-property/ regulator-always-on; /delete-property/ regulator-boot-on; }; + +/* Need this and all the pinctrl/gpio stuff above to set pinmux */ +&vcc_sd { + u-boot,dm-spl; +}; diff --git a/arch/arm/dts/rk3399-u-boot.dtsi b/arch/arm/dts/rk3399-u-boot.dtsi index 9bb130a92a..8237782408 100644 --- a/arch/arm/dts/rk3399-u-boot.dtsi +++ b/arch/arm/dts/rk3399-u-boot.dtsi @@ -8,6 +8,7 @@ aliases { mmc0 = &sdhci; mmc1 = &sdmmc; + pci0 = &pcie0; }; cic: syscon@ff620000 { @@ -91,6 +92,9 @@ &sdmmc { u-boot,dm-pre-reloc; + + /* mmc to sram can't do dma, prevent aborts transferring TF-A parts */ + u-boot,spl-fifo-mode; }; &spi1 { diff --git a/arch/arm/mach-rockchip/spl-boot-order.c b/arch/arm/mach-rockchip/spl-boot-order.c index c2e4023007..94673f34c9 100644 --- a/arch/arm/mach-rockchip/spl-boot-order.c +++ b/arch/arm/mach-rockchip/spl-boot-order.c @@ -99,6 +99,12 @@ __weak const char *board_spl_was_booted_from(void) void board_boot_order(u32 *spl_boot_list) { + /* In case of no fdt (or only platdata), use spl_boot_device() */ + if (!CONFIG_IS_ENABLED(OF_CONTROL) || CONFIG_IS_ENABLED(OF_PLATDATA)) { + spl_boot_list[0] = spl_boot_device(); + return; + } + const void *blob = gd->fdt_blob; int chosen_node = fdt_path_offset(blob, "/chosen"); int idx = 0; diff --git a/arch/arm/mach-rockchip/spl.c b/arch/arm/mach-rockchip/spl.c index ec2f66d188..46b32eb345 100644 --- a/arch/arm/mach-rockchip/spl.c +++ b/arch/arm/mach-rockchip/spl.c @@ -53,7 +53,8 @@ u32 spl_boot_device(void) #if defined(CONFIG_TARGET_CHROMEBOOK_JERRY) || \ defined(CONFIG_TARGET_CHROMEBIT_MICKEY) || \ - defined(CONFIG_TARGET_CHROMEBOOK_MINNIE) + defined(CONFIG_TARGET_CHROMEBOOK_MINNIE) || \ + defined(CONFIG_TARGET_CHROMEBOOK_SPEEDY) return BOOT_DEVICE_SPI; #endif if (CONFIG_IS_ENABLED(ROCKCHIP_BACK_TO_BROM)) diff --git a/board/google/veyron/veyron.c b/board/google/veyron/veyron.c index 6d84a326a3..391d973c0b 100644 --- a/board/google/veyron/veyron.c +++ b/board/google/veyron/veyron.c @@ -71,7 +71,7 @@ static int veyron_init(void) } #endif -int board_early_init_f(void) +int board_early_init_r(void) { struct udevice *dev; int ret; diff --git a/board/theobroma-systems/puma_rk3399/fit_spl_atf.sh b/board/theobroma-systems/puma_rk3399/fit_spl_atf.sh index 420e7daf4c..c9396577a9 100755 --- a/board/theobroma-systems/puma_rk3399/fit_spl_atf.sh +++ b/board/theobroma-systems/puma_rk3399/fit_spl_atf.sh @@ -69,7 +69,7 @@ cat << __HEADER_EOF }; fdt { description = "RK3399-Q7 (Puma) flat device-tree"; - data = /incbin/("u-boot.dtb"); + data = /incbin/("$1"); type = "flat_dt"; compression = "none"; }; diff --git a/board/vamrs/rock960_rk3399/rock960-rk3399.c b/board/vamrs/rock960_rk3399/rock960-rk3399.c index 68a127b9ac..a7fc38d42f 100644 --- a/board/vamrs/rock960_rk3399/rock960-rk3399.c +++ b/board/vamrs/rock960_rk3399/rock960-rk3399.c @@ -2,3 +2,27 @@ /* * Copyright (C) 2018 Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> */ + +#include <common.h> +#include <syscon.h> +#include <asm/io.h> +#include <asm/arch-rockchip/clock.h> +#include <asm/arch-rockchip/grf_rk3399.h> +#include <asm/arch-rockchip/hardware.h> +#include <linux/bitops.h> + +#ifdef CONFIG_MISC_INIT_R +int misc_init_r(void) +{ + struct rk3399_grf_regs *grf = + syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + /** + * Some SSD's to work on rock960 would require explicit + * domain voltage change, so BT565 is in 1.8v domain + */ + rk_setreg(&grf->io_vsel, BIT(0)); + + return 0; +} +#endif diff --git a/configs/chromebit_mickey_defconfig b/configs/chromebit_mickey_defconfig index b1ad7bdd1d..23efafb0d2 100644 --- a/configs/chromebit_mickey_defconfig +++ b/configs/chromebit_mickey_defconfig @@ -19,6 +19,7 @@ CONFIG_USE_PREBOOT=y CONFIG_DEFAULT_FDT_FILE="rk3288-veyron-mickey.dtb" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_BOARD_EARLY_INIT_R=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 @@ -72,8 +73,7 @@ CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_SPL_PINCTRL=y -# CONFIG_SPL_PINMUX is not set -CONFIG_SPL_PINCONF=y +# CONFIG_SPL_PINCTRL_FULL is not set CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set CONFIG_PMIC_RK8XX=y diff --git a/configs/chromebook_jerry_defconfig b/configs/chromebook_jerry_defconfig index 16eee2238b..443e3cdace 100644 --- a/configs/chromebook_jerry_defconfig +++ b/configs/chromebook_jerry_defconfig @@ -20,7 +20,7 @@ CONFIG_LOG=y CONFIG_DEFAULT_FDT_FILE="rk3288-veyron-jerry.dtb" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y -CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_BOARD_EARLY_INIT_R=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 @@ -75,8 +75,7 @@ CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_SPL_PINCTRL=y -# CONFIG_SPL_PINMUX is not set -CONFIG_SPL_PINCONF=y +# CONFIG_SPL_PINCTRL_FULL is not set CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set CONFIG_PMIC_RK8XX=y diff --git a/configs/chromebook_minnie_defconfig b/configs/chromebook_minnie_defconfig index 2c0415431f..99ac0e0674 100644 --- a/configs/chromebook_minnie_defconfig +++ b/configs/chromebook_minnie_defconfig @@ -20,6 +20,7 @@ CONFIG_SILENT_CONSOLE=y CONFIG_DEFAULT_FDT_FILE="rk3288-veyron-minnie.dtb" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_BOARD_EARLY_INIT_R=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 @@ -74,8 +75,7 @@ CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_SPL_PINCTRL=y -# CONFIG_SPL_PINMUX is not set -CONFIG_SPL_PINCONF=y +# CONFIG_SPL_PINCTRL_FULL is not set CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set CONFIG_PMIC_RK8XX=y diff --git a/configs/chromebook_speedy_defconfig b/configs/chromebook_speedy_defconfig index b4116a34e6..5a5152541b 100644 --- a/configs/chromebook_speedy_defconfig +++ b/configs/chromebook_speedy_defconfig @@ -20,7 +20,7 @@ CONFIG_SILENT_CONSOLE=y CONFIG_DEFAULT_FDT_FILE="rk3288-veyron-speedy.dtb" # CONFIG_DISPLAY_CPUINFO is not set CONFIG_DISPLAY_BOARDINFO_LATE=y -CONFIG_BOARD_EARLY_INIT_F=y +CONFIG_BOARD_EARLY_INIT_R=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x2000 @@ -74,6 +74,7 @@ CONFIG_SPI_FLASH_GIGADEVICE=y CONFIG_PINCTRL=y CONFIG_PINCONF=y CONFIG_SPL_PINCTRL=y +# CONFIG_SPL_PINCTRL_FULL is not set CONFIG_DM_PMIC=y # CONFIG_SPL_PMIC_CHILDREN is not set CONFIG_PMIC_RK8XX=y diff --git a/configs/nanopc-t4-rk3399_defconfig b/configs/nanopc-t4-rk3399_defconfig index ae865908d8..3bb5b498f2 100644 --- a/configs/nanopc-t4-rk3399_defconfig +++ b/configs/nanopc-t4-rk3399_defconfig @@ -18,6 +18,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y @@ -34,10 +35,13 @@ CONFIG_MMC_SDHCI_ROCKCHIP=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y +CONFIG_NVME=y +CONFIG_PCI=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RESET=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y diff --git a/configs/roc-pc-mezzanine-rk3399_defconfig b/configs/roc-pc-mezzanine-rk3399_defconfig index 1879944bc5..7f55307676 100644 --- a/configs/roc-pc-mezzanine-rk3399_defconfig +++ b/configs/roc-pc-mezzanine-rk3399_defconfig @@ -19,6 +19,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y @@ -36,11 +37,14 @@ CONFIG_SPI_FLASH_WINBOND=y CONFIG_DM_ETH=y CONFIG_ETH_DESIGNWARE=y CONFIG_GMAC_ROCKCHIP=y +CONFIG_NVME=y +CONFIG_PCI=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y CONFIG_RAM_RK3399_LPDDR4=y +CONFIG_DM_RESET=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_ROCKCHIP_SPI=y diff --git a/configs/rock64-rk3328_defconfig b/configs/rock64-rk3328_defconfig index 7d096d38c6..0bc2198f5c 100644 --- a/configs/rock64-rk3328_defconfig +++ b/configs/rock64-rk3328_defconfig @@ -1,6 +1,7 @@ CONFIG_ARM=y CONFIG_ARCH_ROCKCHIP=y CONFIG_SYS_TEXT_BASE=0x00200000 +CONFIG_SPL_GPIO_SUPPORT=y CONFIG_ENV_OFFSET=0x3F8000 CONFIG_ROCKCHIP_RK3328=y CONFIG_TPL_ROCKCHIP_COMMON_BOARD=y @@ -25,6 +26,8 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_TPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_STACK_R=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_POWER_SUPPORT=y CONFIG_SPL_ATF=y CONFIG_SPL_ATF_NO_PLATFORM_PARAM=y CONFIG_CMD_BOOTZ=y @@ -36,7 +39,7 @@ CONFIG_CMD_TIME=y CONFIG_SPL_OF_CONTROL=y CONFIG_TPL_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="rk3328-rock64" -CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" CONFIG_TPL_OF_PLATDATA=y CONFIG_ENV_IS_IN_MMC=y CONFIG_SYS_RELOC_GD_ENV_ADDR=y @@ -64,7 +67,9 @@ CONFIG_PINCTRL=y CONFIG_SPL_PINCTRL=y CONFIG_DM_PMIC=y CONFIG_PMIC_RK8XX=y +CONFIG_SPL_DM_REGULATOR=y CONFIG_REGULATOR_PWM=y +CONFIG_SPL_DM_REGULATOR_FIXED=y CONFIG_DM_REGULATOR_FIXED=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y diff --git a/configs/rock960-rk3399_defconfig b/configs/rock960-rk3399_defconfig index 045d989a19..64517f9623 100644 --- a/configs/rock960-rk3399_defconfig +++ b/configs/rock960-rk3399_defconfig @@ -9,6 +9,7 @@ CONFIG_DEBUG_UART_BASE=0xFF1A0000 CONFIG_DEBUG_UART_CLOCK=24000000 CONFIG_DEBUG_UART=y CONFIG_DEFAULT_FDT_FILE="rockchip/rk3399-rock960.dtb" +CONFIG_MISC_INIT_R=y CONFIG_DISPLAY_BOARDINFO_LATE=y # CONFIG_SPL_RAW_IMAGE_SUPPORT is not set CONFIG_SPL_STACK_R=y @@ -19,6 +20,7 @@ CONFIG_CMD_BOOTZ=y CONFIG_CMD_GPT=y CONFIG_CMD_MMC=y CONFIG_CMD_USB=y +CONFIG_CMD_PCI=y # CONFIG_CMD_SETEXPR is not set CONFIG_CMD_TIME=y CONFIG_CMD_PMIC=y @@ -36,10 +38,13 @@ CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_SDMA=y CONFIG_MMC_SDHCI_ROCKCHIP=y CONFIG_DM_ETH=y +CONFIG_NVME=y +CONFIG_PCI=y CONFIG_PMIC_RK8XX=y CONFIG_REGULATOR_PWM=y CONFIG_REGULATOR_RK8XX=y CONFIG_PWM_ROCKCHIP=y +CONFIG_DM_RESET=y CONFIG_BAUDRATE=1500000 CONFIG_DEBUG_UART_SHIFT=2 CONFIG_SYSRESET=y diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig index 8074e4665a..53abce0057 100644 --- a/configs/rockpro64-rk3399_defconfig +++ b/configs/rockpro64-rk3399_defconfig @@ -58,5 +58,12 @@ CONFIG_USB_ETHER_ASIX88179=y CONFIG_USB_ETHER_MCS7830=y CONFIG_USB_ETHER_RTL8152=y CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_USB_KEYBOARD=y CONFIG_SPL_TINY_MEMSET=y CONFIG_ERRNO_STR=y +CONFIG_DM_VIDEO=y +CONFIG_VIDEO_BPP16=y +CONFIG_VIDEO_BPP32=y +CONFIG_DISPLAY=y +CONFIG_VIDEO_ROCKCHIP=y +CONFIG_DISPLAY_ROCKCHIP_HDMI=y diff --git a/drivers/clk/rockchip/clk_rk3399.c b/drivers/clk/rockchip/clk_rk3399.c index e009f1cf6c..6a78837619 100644 --- a/drivers/clk/rockchip/clk_rk3399.c +++ b/drivers/clk/rockchip/clk_rk3399.c @@ -1074,12 +1074,166 @@ static int __maybe_unused rk3399_clk_set_parent(struct clk *clk, return -ENOENT; } +static int rk3399_clk_enable(struct clk *clk) +{ + struct rk3399_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case SCLK_MAC: + rk_clrreg(&priv->cru->clkgate_con[5], BIT(5)); + break; + case SCLK_MAC_RX: + rk_clrreg(&priv->cru->clkgate_con[5], BIT(8)); + break; + case SCLK_MAC_TX: + rk_clrreg(&priv->cru->clkgate_con[5], BIT(9)); + break; + case SCLK_MACREF: + rk_clrreg(&priv->cru->clkgate_con[5], BIT(7)); + break; + case SCLK_MACREF_OUT: + rk_clrreg(&priv->cru->clkgate_con[5], BIT(6)); + break; + case ACLK_GMAC: + rk_clrreg(&priv->cru->clkgate_con[32], BIT(0)); + break; + case PCLK_GMAC: + rk_clrreg(&priv->cru->clkgate_con[32], BIT(2)); + break; + case SCLK_USB3OTG0_REF: + rk_clrreg(&priv->cru->clkgate_con[12], BIT(1)); + break; + case SCLK_USB3OTG1_REF: + rk_clrreg(&priv->cru->clkgate_con[12], BIT(2)); + break; + case SCLK_USB3OTG0_SUSPEND: + rk_clrreg(&priv->cru->clkgate_con[12], BIT(3)); + break; + case SCLK_USB3OTG1_SUSPEND: + rk_clrreg(&priv->cru->clkgate_con[12], BIT(4)); + break; + case ACLK_USB3OTG0: + rk_clrreg(&priv->cru->clkgate_con[30], BIT(1)); + break; + case ACLK_USB3OTG1: + rk_clrreg(&priv->cru->clkgate_con[30], BIT(2)); + break; + case ACLK_USB3_RKSOC_AXI_PERF: + rk_clrreg(&priv->cru->clkgate_con[30], BIT(3)); + break; + case ACLK_USB3: + rk_clrreg(&priv->cru->clkgate_con[12], BIT(0)); + break; + case ACLK_USB3_GRF: + rk_clrreg(&priv->cru->clkgate_con[30], BIT(4)); + break; + case HCLK_HOST0: + rk_clrreg(&priv->cru->clksel_con[20], BIT(5)); + break; + case HCLK_HOST0_ARB: + rk_clrreg(&priv->cru->clksel_con[20], BIT(6)); + break; + case HCLK_HOST1: + rk_clrreg(&priv->cru->clksel_con[20], BIT(7)); + break; + case HCLK_HOST1_ARB: + rk_clrreg(&priv->cru->clksel_con[20], BIT(8)); + break; + case SCLK_PCIEPHY_REF: + rk_clrreg(&priv->cru->clksel_con[18], BIT(10)); + break; + default: + debug("%s: unsupported clk %ld\n", __func__, clk->id); + return -ENOENT; + } + + return 0; +} + +static int rk3399_clk_disable(struct clk *clk) +{ + struct rk3399_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case SCLK_MAC: + rk_setreg(&priv->cru->clkgate_con[5], BIT(5)); + break; + case SCLK_MAC_RX: + rk_setreg(&priv->cru->clkgate_con[5], BIT(8)); + break; + case SCLK_MAC_TX: + rk_setreg(&priv->cru->clkgate_con[5], BIT(9)); + break; + case SCLK_MACREF: + rk_setreg(&priv->cru->clkgate_con[5], BIT(7)); + break; + case SCLK_MACREF_OUT: + rk_setreg(&priv->cru->clkgate_con[5], BIT(6)); + break; + case ACLK_GMAC: + rk_setreg(&priv->cru->clkgate_con[32], BIT(0)); + break; + case PCLK_GMAC: + rk_setreg(&priv->cru->clkgate_con[32], BIT(2)); + break; + case SCLK_USB3OTG0_REF: + rk_setreg(&priv->cru->clkgate_con[12], BIT(1)); + break; + case SCLK_USB3OTG1_REF: + rk_setreg(&priv->cru->clkgate_con[12], BIT(2)); + break; + case SCLK_USB3OTG0_SUSPEND: + rk_setreg(&priv->cru->clkgate_con[12], BIT(3)); + break; + case SCLK_USB3OTG1_SUSPEND: + rk_setreg(&priv->cru->clkgate_con[12], BIT(4)); + break; + case ACLK_USB3OTG0: + rk_setreg(&priv->cru->clkgate_con[30], BIT(1)); + break; + case ACLK_USB3OTG1: + rk_setreg(&priv->cru->clkgate_con[30], BIT(2)); + break; + case ACLK_USB3_RKSOC_AXI_PERF: + rk_setreg(&priv->cru->clkgate_con[30], BIT(3)); + break; + case ACLK_USB3: + rk_setreg(&priv->cru->clkgate_con[12], BIT(0)); + break; + case ACLK_USB3_GRF: + rk_setreg(&priv->cru->clkgate_con[30], BIT(4)); + break; + case HCLK_HOST0: + rk_setreg(&priv->cru->clksel_con[20], BIT(5)); + break; + case HCLK_HOST0_ARB: + rk_setreg(&priv->cru->clksel_con[20], BIT(6)); + break; + case HCLK_HOST1: + rk_setreg(&priv->cru->clksel_con[20], BIT(7)); + break; + case HCLK_HOST1_ARB: + rk_setreg(&priv->cru->clksel_con[20], BIT(8)); + break; + case SCLK_PCIEPHY_REF: + rk_clrreg(&priv->cru->clksel_con[18], BIT(10)); + break; + default: + debug("%s: unsupported clk %ld\n", __func__, clk->id); + return -ENOENT; + } + + return 0; +} + static struct clk_ops rk3399_clk_ops = { .get_rate = rk3399_clk_get_rate, .set_rate = rk3399_clk_set_rate, #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) .set_parent = rk3399_clk_set_parent, #endif + .enable = rk3399_clk_enable, + .disable = rk3399_clk_disable, }; #ifdef CONFIG_SPL_BUILD diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 6fc26884e2..6d8c22aacf 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -197,4 +197,12 @@ config PCIE_MEDIATEK Say Y here if you want to enable Gen2 PCIe controller, which could be found on MT7623 SoC family. +config PCIE_ROCKCHIP + bool "Enable Rockchip PCIe driver" + select DM_PCI + default y if ROCKCHIP_RK3399 + help + Say Y here if you want to enable PCIe controller support on + Rockchip SoCs. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index c051ecc9f3..955351c5c2 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -43,3 +43,4 @@ obj-$(CONFIG_PCI_PHYTIUM) += pcie_phytium.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o obj-$(CONFIG_PCIE_MEDIATEK) += pcie_mediatek.o +obj-$(CONFIG_PCIE_ROCKCHIP) += pcie_rockchip.o pcie_rockchip_phy.o diff --git a/drivers/pci/pcie_rockchip.c b/drivers/pci/pcie_rockchip.c new file mode 100644 index 0000000000..82a8396e42 --- /dev/null +++ b/drivers/pci/pcie_rockchip.c @@ -0,0 +1,491 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Rockchip AXI PCIe host controller driver + * + * Copyright (c) 2016 Rockchip, Inc. + * Copyright (c) 2020 Amarula Solutions(India) + * Copyright (c) 2020 Jagan Teki <jagan@amarulasolutions.com> + * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se> + * Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org> + * + * Bits taken from Linux Rockchip PCIe host controller. + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <pci.h> +#include <power-domain.h> +#include <power/regulator.h> +#include <reset.h> +#include <syscon.h> +#include <asm/io.h> +#include <asm-generic/gpio.h> +#include <asm/arch-rockchip/clock.h> +#include <linux/iopoll.h> + +#include "pcie_rockchip.h" + +DECLARE_GLOBAL_DATA_PTR; + +static int rockchip_pcie_off_conf(pci_dev_t bdf, uint offset) +{ + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + unsigned int func = PCI_FUNC(bdf); + + return (bus << 20) | (dev << 15) | (func << 12) | (offset & ~0x3); +} + +static int rockchip_pcie_rd_conf(const struct udevice *udev, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct rockchip_pcie *priv = dev_get_priv(udev); + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + int where = rockchip_pcie_off_conf(bdf, offset); + ulong value; + + if (bus == priv->first_busno && dev == 0) { + value = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + where); + *valuep = pci_conv_32_to_size(value, offset, size); + return 0; + } + + if ((bus == priv->first_busno + 1) && dev == 0) { + value = readl(priv->axi_base + where); + *valuep = pci_conv_32_to_size(value, offset, size); + return 0; + } + + *valuep = pci_get_ff(size); + + return 0; +} + +static int rockchip_pcie_wr_conf(struct udevice *udev, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct rockchip_pcie *priv = dev_get_priv(udev); + unsigned int bus = PCI_BUS(bdf); + unsigned int dev = PCI_DEV(bdf); + int where = rockchip_pcie_off_conf(bdf, offset); + ulong old; + + if (bus == priv->first_busno && dev == 0) { + old = readl(priv->apb_base + PCIE_RC_NORMAL_BASE + where); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, priv->apb_base + PCIE_RC_NORMAL_BASE + where); + return 0; + } + + if ((bus == priv->first_busno + 1) && dev == 0) { + old = readl(priv->axi_base + where); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, priv->axi_base + where); + return 0; + } + + return 0; +} + +static int rockchip_pcie_atr_init(struct rockchip_pcie *priv) +{ + struct udevice *ctlr = pci_get_controller(priv->dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + u64 addr, size, offset; + u32 type; + int i, region; + + /* Use region 0 to map PCI configuration space. */ + writel(25 - 1, priv->apb_base + PCIE_ATR_OB_ADDR0(0)); + writel(0, priv->apb_base + PCIE_ATR_OB_ADDR1(0)); + writel(PCIE_ATR_HDR_CFG_TYPE0 | PCIE_ATR_HDR_RID, + priv->apb_base + PCIE_ATR_OB_DESC0(0)); + writel(0, priv->apb_base + PCIE_ATR_OB_DESC1(0)); + + for (i = 0; i < hose->region_count; i++) { + if (hose->regions[i].flags == PCI_REGION_SYS_MEMORY) + continue; + + if (hose->regions[i].flags == PCI_REGION_IO) + type = PCIE_ATR_HDR_IO; + else + type = PCIE_ATR_HDR_MEM; + + /* Only support identity mappings. */ + if (hose->regions[i].bus_start != + hose->regions[i].phys_start) + return -EINVAL; + + /* Only support mappings aligned on a region boundary. */ + addr = hose->regions[i].bus_start; + if (addr & (PCIE_ATR_OB_REGION_SIZE - 1)) + return -EINVAL; + + /* Mappings should lie between AXI and APB regions. */ + size = hose->regions[i].size; + if (addr < (u64)priv->axi_base + PCIE_ATR_OB_REGION0_SIZE) + return -EINVAL; + if (addr + size > (u64)priv->apb_base) + return -EINVAL; + + offset = addr - (u64)priv->axi_base - PCIE_ATR_OB_REGION0_SIZE; + region = 1 + (offset / PCIE_ATR_OB_REGION_SIZE); + while (size > 0) { + writel(32 - 1, + priv->apb_base + PCIE_ATR_OB_ADDR0(region)); + writel(0, priv->apb_base + PCIE_ATR_OB_ADDR1(region)); + writel(type | PCIE_ATR_HDR_RID, + priv->apb_base + PCIE_ATR_OB_DESC0(region)); + writel(0, priv->apb_base + PCIE_ATR_OB_DESC1(region)); + + addr += PCIE_ATR_OB_REGION_SIZE; + size -= PCIE_ATR_OB_REGION_SIZE; + region++; + } + } + + /* Passthrough inbound translations unmodified. */ + writel(32 - 1, priv->apb_base + PCIE_ATR_IB_ADDR0(2)); + writel(0, priv->apb_base + PCIE_ATR_IB_ADDR1(2)); + + return 0; +} + +static int rockchip_pcie_init_port(struct udevice *dev) +{ + struct rockchip_pcie *priv = dev_get_priv(dev); + struct rockchip_pcie_phy *phy = pcie_get_phy(priv); + struct rockchip_pcie_phy_ops *ops = phy_get_ops(phy); + u32 cr, val, status; + int ret; + + if (dm_gpio_is_valid(&priv->ep_gpio)) + dm_gpio_set_value(&priv->ep_gpio, 0); + + ret = reset_assert(&priv->aclk_rst); + if (ret) { + dev_err(dev, "failed to assert aclk reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_assert(&priv->pclk_rst); + if (ret) { + dev_err(dev, "failed to assert pclk reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_assert(&priv->pm_rst); + if (ret) { + dev_err(dev, "failed to assert pm reset (ret=%d)\n", ret); + return ret; + } + + ret = ops->init(phy); + if (ret) { + dev_err(dev, "failed to init phy (ret=%d)\n", ret); + goto err_exit_phy; + } + + ret = reset_assert(&priv->core_rst); + if (ret) { + dev_err(dev, "failed to assert core reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + ret = reset_assert(&priv->mgmt_rst); + if (ret) { + dev_err(dev, "failed to assert mgmt reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + ret = reset_assert(&priv->mgmt_sticky_rst); + if (ret) { + dev_err(dev, "failed to assert mgmt-sticky reset (ret=%d)\n", + ret); + goto err_exit_phy; + } + + ret = reset_assert(&priv->pipe_rst); + if (ret) { + dev_err(dev, "failed to assert pipe reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + udelay(10); + + ret = reset_deassert(&priv->pm_rst); + if (ret) { + dev_err(dev, "failed to deassert pm reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + ret = reset_deassert(&priv->aclk_rst); + if (ret) { + dev_err(dev, "failed to deassert aclk reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + ret = reset_deassert(&priv->pclk_rst); + if (ret) { + dev_err(dev, "failed to deassert pclk reset (ret=%d)\n", ret); + goto err_exit_phy; + } + + /* Select GEN1 for now */ + cr = PCIE_CLIENT_GEN_SEL_1; + /* Set Root complex mode */ + cr |= PCIE_CLIENT_CONF_ENABLE | PCIE_CLIENT_MODE_RC; + writel(cr, priv->apb_base + PCIE_CLIENT_CONFIG); + + ret = ops->power_on(phy); + if (ret) { + dev_err(dev, "failed to power on phy (ret=%d)\n", ret); + goto err_power_off_phy; + } + + ret = reset_deassert(&priv->mgmt_sticky_rst); + if (ret) { + dev_err(dev, "failed to deassert mgmt-sticky reset (ret=%d)\n", + ret); + goto err_power_off_phy; + } + + ret = reset_deassert(&priv->core_rst); + if (ret) { + dev_err(dev, "failed to deassert core reset (ret=%d)\n", ret); + goto err_power_off_phy; + } + + ret = reset_deassert(&priv->mgmt_rst); + if (ret) { + dev_err(dev, "failed to deassert mgmt reset (ret=%d)\n", ret); + goto err_power_off_phy; + } + + ret = reset_deassert(&priv->pipe_rst); + if (ret) { + dev_err(dev, "failed to deassert pipe reset (ret=%d)\n", ret); + goto err_power_off_phy; + } + + /* Enable Gen1 training */ + writel(PCIE_CLIENT_LINK_TRAIN_ENABLE, + priv->apb_base + PCIE_CLIENT_CONFIG); + + if (dm_gpio_is_valid(&priv->ep_gpio)) + dm_gpio_set_value(&priv->ep_gpio, 1); + + ret = readl_poll_sleep_timeout + (priv->apb_base + PCIE_CLIENT_BASIC_STATUS1, + status, PCIE_LINK_UP(status), 20, 500 * 1000); + if (ret) { + dev_err(dev, "PCIe link training gen1 timeout!\n"); + goto err_power_off_phy; + } + + /* Initialize Root Complex registers. */ + writel(PCIE_LM_VENDOR_ROCKCHIP, priv->apb_base + PCIE_LM_VENDOR_ID); + writel(PCI_CLASS_BRIDGE_PCI << 16, + priv->apb_base + PCIE_RC_BASE + PCI_CLASS_REVISION); + writel(PCIE_LM_RCBARPIE | PCIE_LM_RCBARPIS, + priv->apb_base + PCIE_LM_RCBAR); + + if (dev_read_bool(dev, "aspm-no-l0s")) { + val = readl(priv->apb_base + PCIE_RC_PCIE_LCAP); + val &= ~PCIE_RC_PCIE_LCAP_APMS_L0S; + writel(val, priv->apb_base + PCIE_RC_PCIE_LCAP); + } + + /* Configure Address Translation. */ + ret = rockchip_pcie_atr_init(priv); + if (ret) { + dev_err(dev, "PCIE-%d: ATR init failed\n", dev->seq); + goto err_power_off_phy; + } + + return 0; + +err_power_off_phy: + ops->power_off(phy); +err_exit_phy: + ops->exit(phy); + return ret; +} + +static int rockchip_pcie_set_vpcie(struct udevice *dev) +{ + struct rockchip_pcie *priv = dev_get_priv(dev); + int ret; + + if (!IS_ERR(priv->vpcie3v3)) { + ret = regulator_set_enable(priv->vpcie3v3, true); + if (ret) { + dev_err(dev, "failed to enable vpcie3v3 (ret=%d)\n", + ret); + return ret; + } + } + + ret = regulator_set_enable(priv->vpcie1v8, true); + if (ret) { + dev_err(dev, "failed to enable vpcie1v8 (ret=%d)\n", ret); + goto err_disable_3v3; + } + + ret = regulator_set_enable(priv->vpcie0v9, true); + if (ret) { + dev_err(dev, "failed to enable vpcie0v9 (ret=%d)\n", ret); + goto err_disable_1v8; + } + + return 0; + +err_disable_1v8: + regulator_set_enable(priv->vpcie1v8, false); +err_disable_3v3: + if (!IS_ERR(priv->vpcie3v3)) + regulator_set_enable(priv->vpcie3v3, false); + return ret; +} + +static int rockchip_pcie_parse_dt(struct udevice *dev) +{ + struct rockchip_pcie *priv = dev_get_priv(dev); + int ret; + + priv->axi_base = dev_read_addr_name(dev, "axi-base"); + if (!priv->axi_base) + return -ENODEV; + + priv->apb_base = dev_read_addr_name(dev, "apb-base"); + if (!priv->axi_base) + return -ENODEV; + + ret = gpio_request_by_name(dev, "ep-gpios", 0, + &priv->ep_gpio, GPIOD_IS_OUT); + if (ret) { + dev_err(dev, "failed to find ep-gpios property\n"); + return ret; + } + + ret = reset_get_by_name(dev, "core", &priv->core_rst); + if (ret) { + dev_err(dev, "failed to get core reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "mgmt", &priv->mgmt_rst); + if (ret) { + dev_err(dev, "failed to get mgmt reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "mgmt-sticky", &priv->mgmt_sticky_rst); + if (ret) { + dev_err(dev, "failed to get mgmt-sticky reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "pipe", &priv->pipe_rst); + if (ret) { + dev_err(dev, "failed to get pipe reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "pm", &priv->pm_rst); + if (ret) { + dev_err(dev, "failed to get pm reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "pclk", &priv->pclk_rst); + if (ret) { + dev_err(dev, "failed to get pclk reset (ret=%d)\n", ret); + return ret; + } + + ret = reset_get_by_name(dev, "aclk", &priv->aclk_rst); + if (ret) { + dev_err(dev, "failed to get aclk reset (ret=%d)\n", ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vpcie3v3-supply", + &priv->vpcie3v3); + if (ret && ret != -ENOENT) { + dev_err(dev, "failed to get vpcie3v3 supply (ret=%d)\n", ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vpcie1v8-supply", + &priv->vpcie1v8); + if (ret) { + dev_err(dev, "failed to get vpcie1v8 supply (ret=%d)\n", ret); + return ret; + } + + ret = device_get_supply_regulator(dev, "vpcie0v9-supply", + &priv->vpcie0v9); + if (ret) { + dev_err(dev, "failed to get vpcie0v9 supply (ret=%d)\n", ret); + return ret; + } + + return 0; +} + +static int rockchip_pcie_probe(struct udevice *dev) +{ + struct rockchip_pcie *priv = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + int ret; + + priv->first_busno = dev->seq; + priv->dev = dev; + + ret = rockchip_pcie_parse_dt(dev); + if (ret) + return ret; + + ret = rockchip_pcie_phy_get(dev); + if (ret) + return ret; + + ret = rockchip_pcie_set_vpcie(dev); + if (ret) + return ret; + + ret = rockchip_pcie_init_port(dev); + if (ret) + return ret; + + dev_info(dev, "PCIE-%d: Link up (Bus%d)\n", + dev->seq, hose->first_busno); + + return 0; +} + +static const struct dm_pci_ops rockchip_pcie_ops = { + .read_config = rockchip_pcie_rd_conf, + .write_config = rockchip_pcie_wr_conf, +}; + +static const struct udevice_id rockchip_pcie_ids[] = { + { .compatible = "rockchip,rk3399-pcie" }, + { } +}; + +U_BOOT_DRIVER(rockchip_pcie) = { + .name = "rockchip_pcie", + .id = UCLASS_PCI, + .of_match = rockchip_pcie_ids, + .ops = &rockchip_pcie_ops, + .probe = rockchip_pcie_probe, + .priv_auto_alloc_size = sizeof(struct rockchip_pcie), +}; diff --git a/drivers/pci/pcie_rockchip.h b/drivers/pci/pcie_rockchip.h new file mode 100644 index 0000000000..c3a0a2846d --- /dev/null +++ b/drivers/pci/pcie_rockchip.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Rockchip PCIe Headers + * + * Copyright (c) 2016 Rockchip, Inc. + * Copyright (c) 2020 Amarula Solutions(India) + * Copyright (c) 2020 Jagan Teki <jagan@amarulasolutions.com> + * Copyright (c) 2019 Patrick Wildt <patrick@blueri.se> + * + */ + +#define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val)) +#define HIWORD_UPDATE_BIT(val) HIWORD_UPDATE(val, val) + +#define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) +#define PCIE_CLIENT_BASE 0x0 +#define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) +#define PCIE_CLIENT_CONF_ENABLE HIWORD_UPDATE_BIT(0x0001) +#define PCIE_CLIENT_LINK_TRAIN_ENABLE HIWORD_UPDATE_BIT(0x0002) +#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040) +#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0) +#define PCIE_CLIENT_BASIC_STATUS1 0x0048 +#define PCIE_CLIENT_LINK_STATUS_UP GENMASK(21, 20) +#define PCIE_CLIENT_LINK_STATUS_MASK GENMASK(21, 20) +#define PCIE_LINK_UP(x) \ + (((x) & PCIE_CLIENT_LINK_STATUS_MASK) == PCIE_CLIENT_LINK_STATUS_UP) +#define PCIE_RC_NORMAL_BASE 0x800000 +#define PCIE_LM_BASE 0x900000 +#define PCIE_LM_VENDOR_ID (PCIE_LM_BASE + 0x44) +#define PCIE_LM_VENDOR_ROCKCHIP 0x1d87 +#define PCIE_LM_RCBAR (PCIE_LM_BASE + 0x300) +#define PCIE_LM_RCBARPIE BIT(19) +#define PCIE_LM_RCBARPIS BIT(20) +#define PCIE_RC_BASE 0xa00000 +#define PCIE_RC_CONFIG_DCR (PCIE_RC_BASE + 0x0c4) +#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18 +#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26 +#define PCIE_RC_PCIE_LCAP (PCIE_RC_BASE + 0x0cc) +#define PCIE_RC_PCIE_LCAP_APMS_L0S BIT(10) +#define PCIE_ATR_BASE 0xc00000 +#define PCIE_ATR_OB_ADDR0(i) (PCIE_ATR_BASE + 0x000 + (i) * 0x20) +#define PCIE_ATR_OB_ADDR1(i) (PCIE_ATR_BASE + 0x004 + (i) * 0x20) +#define PCIE_ATR_OB_DESC0(i) (PCIE_ATR_BASE + 0x008 + (i) * 0x20) +#define PCIE_ATR_OB_DESC1(i) (PCIE_ATR_BASE + 0x00c + (i) * 0x20) +#define PCIE_ATR_IB_ADDR0(i) (PCIE_ATR_BASE + 0x800 + (i) * 0x8) +#define PCIE_ATR_IB_ADDR1(i) (PCIE_ATR_BASE + 0x804 + (i) * 0x8) +#define PCIE_ATR_HDR_MEM 0x2 +#define PCIE_ATR_HDR_IO 0x6 +#define PCIE_ATR_HDR_CFG_TYPE0 0xa +#define PCIE_ATR_HDR_CFG_TYPE1 0xb +#define PCIE_ATR_HDR_RID BIT(23) + +#define PCIE_ATR_OB_REGION0_SIZE (32 * 1024 * 1024) +#define PCIE_ATR_OB_REGION_SIZE (1 * 1024 * 1024) + +/* + * The higher 16-bit of this register is used for write protection + * only if BIT(x + 16) set to 1 the BIT(x) can be written. + */ +#define HIWORD_UPDATE_MASK(val, mask, shift) \ + ((val) << (shift) | (mask) << ((shift) + 16)) + +#define PHY_CFG_DATA_SHIFT 7 +#define PHY_CFG_ADDR_SHIFT 1 +#define PHY_CFG_DATA_MASK 0xf +#define PHY_CFG_ADDR_MASK 0x3f +#define PHY_CFG_RD_MASK 0x3ff +#define PHY_CFG_WR_ENABLE 1 +#define PHY_CFG_WR_DISABLE 1 +#define PHY_CFG_WR_SHIFT 0 +#define PHY_CFG_WR_MASK 1 +#define PHY_CFG_PLL_LOCK 0x10 +#define PHY_CFG_CLK_TEST 0x10 +#define PHY_CFG_CLK_SCC 0x12 +#define PHY_CFG_SEPE_RATE BIT(3) +#define PHY_CFG_PLL_100M BIT(3) +#define PHY_PLL_LOCKED BIT(9) +#define PHY_PLL_OUTPUT BIT(10) +#define PHY_LANE_IDLE_OFF 0x1 +#define PHY_LANE_IDLE_MASK 0x1 +#define PHY_LANE_IDLE_A_SHIFT 3 +#define PHY_LANE_IDLE_B_SHIFT 4 +#define PHY_LANE_IDLE_C_SHIFT 5 +#define PHY_LANE_IDLE_D_SHIFT 6 + +#define PCIE_PHY_CONF 0xe220 +#define PCIE_PHY_STATUS 0xe2a4 +#define PCIE_PHY_LANEOFF 0xe214 + +struct rockchip_pcie_phy { + void *reg_base; + struct clk refclk; + struct reset_ctl phy_rst; + struct rockchip_pcie_phy_ops *ops; +}; + +struct rockchip_pcie_phy_ops { + int (*init)(struct rockchip_pcie_phy *phy); + int (*exit)(struct rockchip_pcie_phy *phy); + int (*power_on)(struct rockchip_pcie_phy *phy); + int (*power_off)(struct rockchip_pcie_phy *phy); +}; + +struct rockchip_pcie { + fdt_addr_t axi_base; + fdt_addr_t apb_base; + int first_busno; + struct udevice *dev; + struct rockchip_pcie_phy rk_phy; + struct rockchip_pcie_phy *phy; + + /* resets */ + struct reset_ctl core_rst; + struct reset_ctl mgmt_rst; + struct reset_ctl mgmt_sticky_rst; + struct reset_ctl pipe_rst; + struct reset_ctl pm_rst; + struct reset_ctl pclk_rst; + struct reset_ctl aclk_rst; + + /* gpio */ + struct gpio_desc ep_gpio; + + /* vpcie regulators */ + struct udevice *vpcie12v; + struct udevice *vpcie3v3; + struct udevice *vpcie1v8; + struct udevice *vpcie0v9; +}; + +int rockchip_pcie_phy_get(struct udevice *dev); + +inline struct rockchip_pcie_phy *pcie_get_phy(struct rockchip_pcie *pcie) +{ + return pcie->phy; +} + +inline +struct rockchip_pcie_phy_ops *phy_get_ops(struct rockchip_pcie_phy *phy) +{ + return (struct rockchip_pcie_phy_ops *)phy->ops; +} diff --git a/drivers/pci/pcie_rockchip_phy.c b/drivers/pci/pcie_rockchip_phy.c new file mode 100644 index 0000000000..47f5d6c7e3 --- /dev/null +++ b/drivers/pci/pcie_rockchip_phy.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Rockchip PCIe PHY driver + * + * Copyright (c) 2016 Rockchip, Inc. + * Copyright (c) 2020 Amarula Solutions(India) + */ + +#include <common.h> +#include <clk.h> +#include <dm.h> +#include <dm/device_compat.h> +#include <reset.h> +#include <syscon.h> +#include <asm/gpio.h> +#include <asm/io.h> +#include <linux/iopoll.h> +#include <asm/arch-rockchip/clock.h> + +#include "pcie_rockchip.h" + +DECLARE_GLOBAL_DATA_PTR; + +static void phy_wr_cfg(struct rockchip_pcie_phy *phy, u32 addr, u32 data) +{ + u32 reg; + + reg = HIWORD_UPDATE_MASK(data, PHY_CFG_DATA_MASK, PHY_CFG_DATA_SHIFT); + reg |= HIWORD_UPDATE_MASK(addr, PHY_CFG_ADDR_MASK, PHY_CFG_ADDR_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_CONF); + + udelay(1); + + reg = HIWORD_UPDATE_MASK(PHY_CFG_WR_ENABLE, + PHY_CFG_WR_MASK, + PHY_CFG_WR_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_CONF); + + udelay(1); + + reg = HIWORD_UPDATE_MASK(PHY_CFG_WR_DISABLE, + PHY_CFG_WR_MASK, + PHY_CFG_WR_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_CONF); +} + +static int rockchip_pcie_phy_power_on(struct rockchip_pcie_phy *phy) +{ + int ret = 0; + u32 reg, status; + + ret = reset_deassert(&phy->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + return ret; + } + + reg = HIWORD_UPDATE_MASK(PHY_CFG_PLL_LOCK, + PHY_CFG_ADDR_MASK, + PHY_CFG_ADDR_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_CONF); + + reg = HIWORD_UPDATE_MASK(!PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_LANEOFF); + + ret = -EINVAL; + ret = readl_poll_sleep_timeout(phy->reg_base + PCIE_PHY_STATUS, + status, + status & PHY_PLL_LOCKED, + 20 * 1000, + 50); + if (ret) { + dev_err(&phy->dev, "pll lock timeout!\n"); + goto err_pll_lock; + } + + phy_wr_cfg(phy, PHY_CFG_CLK_TEST, PHY_CFG_SEPE_RATE); + phy_wr_cfg(phy, PHY_CFG_CLK_SCC, PHY_CFG_PLL_100M); + + ret = -ETIMEDOUT; + ret = readl_poll_sleep_timeout(phy->reg_base + PCIE_PHY_STATUS, + status, + !(status & PHY_PLL_OUTPUT), + 20 * 1000, + 50); + if (ret) { + dev_err(&phy->dev, "pll output enable timeout!\n"); + goto err_pll_lock; + } + + reg = HIWORD_UPDATE_MASK(PHY_CFG_PLL_LOCK, + PHY_CFG_ADDR_MASK, + PHY_CFG_ADDR_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_CONF); + + ret = -EINVAL; + ret = readl_poll_sleep_timeout(phy->reg_base + PCIE_PHY_STATUS, + status, + status & PHY_PLL_LOCKED, + 20 * 1000, + 50); + if (ret) { + dev_err(&phy->dev, "pll relock timeout!\n"); + goto err_pll_lock; + } + + return 0; + +err_pll_lock: + reset_assert(&phy->phy_rst); + return ret; +} + +static int rockchip_pcie_phy_power_off(struct rockchip_pcie_phy *phy) +{ + int ret; + u32 reg; + + reg = HIWORD_UPDATE_MASK(PHY_LANE_IDLE_OFF, + PHY_LANE_IDLE_MASK, + PHY_LANE_IDLE_A_SHIFT); + writel(reg, phy->reg_base + PCIE_PHY_LANEOFF); + + ret = reset_assert(&phy->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + return ret; + } + + return 0; +} + +static int rockchip_pcie_phy_init(struct rockchip_pcie_phy *phy) +{ + int ret; + + ret = clk_enable(&phy->refclk); + if (ret) { + dev_err(dev, "failed to enable refclk clock\n"); + return ret; + } + + ret = reset_assert(&phy->phy_rst); + if (ret) { + dev_err(dev, "failed to assert phy reset\n"); + goto err_reset; + } + + return 0; + +err_reset: + clk_disable(&phy->refclk); + return ret; +} + +static int rockchip_pcie_phy_exit(struct rockchip_pcie_phy *phy) +{ + clk_disable(&phy->refclk); + + return 0; +} + +static struct rockchip_pcie_phy_ops pcie_phy_ops = { + .init = rockchip_pcie_phy_init, + .power_on = rockchip_pcie_phy_power_on, + .power_off = rockchip_pcie_phy_power_off, + .exit = rockchip_pcie_phy_exit, +}; + +int rockchip_pcie_phy_get(struct udevice *dev) +{ + struct rockchip_pcie *priv = dev_get_priv(dev); + struct rockchip_pcie_phy *phy_priv = &priv->rk_phy; + ofnode phy_node; + u32 phandle; + int ret; + + phandle = dev_read_u32_default(dev, "phys", 0); + phy_node = ofnode_get_by_phandle(phandle); + if (!ofnode_valid(phy_node)) { + dev_err(dev, "failed to found pcie-phy\n"); + return -ENODEV; + } + + phy_priv->reg_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + ret = clk_get_by_index_nodev(phy_node, 0, &phy_priv->refclk); + if (ret) { + dev_err(dev, "failed to get refclk clock phandle\n"); + return ret; + } + + ret = reset_get_by_index_nodev(phy_node, 0, &phy_priv->phy_rst); + if (ret) { + dev_err(dev, "failed to get phy reset phandle\n"); + return ret; + } + + phy_priv->ops = &pcie_phy_ops; + priv->phy = phy_priv; + + return 0; +} diff --git a/include/configs/rockpro64_rk3399.h b/include/configs/rockpro64_rk3399.h index 5f52c1e4f6..7a72cf6049 100644 --- a/include/configs/rockpro64_rk3399.h +++ b/include/configs/rockpro64_rk3399.h @@ -6,6 +6,11 @@ #ifndef __ROCKPRO64_RK3399_H #define __ROCKPRO64_RK3399_H +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdin=serial,usbkbd\0" \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + #include <configs/rk3399_common.h> #define CONFIG_SYS_MMC_ENV_DEV 0 diff --git a/tools/rkcommon.c b/tools/rkcommon.c index 8f281f5901..61c392e27d 100644 --- a/tools/rkcommon.c +++ b/tools/rkcommon.c @@ -133,7 +133,7 @@ static int rkcommon_get_aligned_size(struct image_tool_params *params, int rkcommon_check_params(struct image_tool_params *params) { - int i; + int i, size; /* * If this is a operation (list or extract), the don't require @@ -153,17 +153,17 @@ int rkcommon_check_params(struct image_tool_params *params) spl_params.boot_file += 1; } - spl_params.init_size = - rkcommon_get_aligned_size(params, spl_params.init_file); - if (spl_params.init_size < 0) + size = rkcommon_get_aligned_size(params, spl_params.init_file); + if (size < 0) return EXIT_FAILURE; + spl_params.init_size = size; /* Boot file is optional, and only for back-to-bootrom functionality. */ if (spl_params.boot_file) { - spl_params.boot_size = - rkcommon_get_aligned_size(params, spl_params.boot_file); - if (spl_params.boot_size < 0) + size = rkcommon_get_aligned_size(params, spl_params.boot_file); + if (size < 0) return EXIT_FAILURE; + spl_params.boot_size = size; } if (spl_params.init_size > rkcommon_get_spl_size(params)) { |