mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +00:00
Merge tag 'u-boot-rockchip-20210121' of https://gitlab.denx.de/u-boot/custodians/u-boot-rockchip
- New board: rk3328 NanoPi R2S board; - Fix init voltage for some rk3399 boards; - enable rng for rk3399 by default; - set default to SPI bus 1 for SPI-flash for some board; - add dwc PCIe controller driver on rockchip platform;
This commit is contained in:
commit
184aa65041
25 changed files with 1594 additions and 19 deletions
|
@ -110,6 +110,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3308) += \
|
|||
|
||||
dtb-$(CONFIG_ROCKCHIP_RK3328) += \
|
||||
rk3328-evb.dtb \
|
||||
rk3328-nanopi-r2s.dtb \
|
||||
rk3328-roc-cc.dtb \
|
||||
rk3328-rock64.dtb \
|
||||
rk3328-rock-pi-e.dtb
|
||||
|
|
40
arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi
Normal file
40
arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi
Normal file
|
@ -0,0 +1,40 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* (C) Copyright 2018-2019 Rockchip Electronics Co., Ltd
|
||||
* (C) Copyright 2020 David Bauer
|
||||
*/
|
||||
|
||||
#include "rk3328-u-boot.dtsi"
|
||||
#include "rk3328-sdram-ddr4-666.dtsi"
|
||||
/ {
|
||||
chosen {
|
||||
u-boot,spl-boot-order = "same-as-spl", &sdmmc, &emmc;
|
||||
};
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&sdmmc0m1_gpio {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&pcfg_pull_up_4ma {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
/* Need this and all the pinctrl/gpio stuff above to set pinmux */
|
||||
&vcc_sd {
|
||||
u-boot,dm-spl;
|
||||
};
|
||||
|
||||
&gmac2io {
|
||||
snps,reset-gpio = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
|
||||
snps,reset-active-low;
|
||||
snps,reset-delays-us = <0 10000 50000>;
|
||||
};
|
370
arch/arm/dts/rk3328-nanopi-r2s.dts
Normal file
370
arch/arm/dts/rk3328-nanopi-r2s.dts
Normal file
|
@ -0,0 +1,370 @@
|
|||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2020 David Bauer <mail@david-bauer.net>
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include "rk3328.dtsi"
|
||||
|
||||
/ {
|
||||
model = "FriendlyElec NanoPi R2S";
|
||||
compatible = "friendlyarm,nanopi-r2s", "rockchip,rk3328";
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial2:1500000n8";
|
||||
};
|
||||
|
||||
gmac_clk: gmac-clock {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <125000000>;
|
||||
clock-output-names = "gmac_clkin";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
keys {
|
||||
compatible = "gpio-keys";
|
||||
pinctrl-0 = <&reset_button_pin>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
reset {
|
||||
label = "reset";
|
||||
gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
|
||||
linux,code = <KEY_RESTART>;
|
||||
debounce-interval = <50>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-0 = <&lan_led_pin>, <&sys_led_pin>, <&wan_led_pin>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
lan_led: led-0 {
|
||||
gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
|
||||
label = "nanopi-r2s:green:lan";
|
||||
};
|
||||
|
||||
sys_led: led-1 {
|
||||
gpios = <&gpio0 RK_PA2 GPIO_ACTIVE_HIGH>;
|
||||
label = "nanopi-r2s:red:sys";
|
||||
};
|
||||
|
||||
wan_led: led-2 {
|
||||
gpios = <&gpio2 RK_PC2 GPIO_ACTIVE_HIGH>;
|
||||
label = "nanopi-r2s:green:wan";
|
||||
};
|
||||
};
|
||||
|
||||
vcc_io_sdio: sdmmcio-regulator {
|
||||
compatible = "regulator-gpio";
|
||||
enable-active-high;
|
||||
gpios = <&gpio1 RK_PD4 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-0 = <&sdio_vcc_pin>;
|
||||
pinctrl-names = "default";
|
||||
regulator-name = "vcc_io_sdio";
|
||||
regulator-always-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-settling-time-us = <5000>;
|
||||
regulator-type = "voltage";
|
||||
startup-delay-us = <2000>;
|
||||
states = <1800000 0x1
|
||||
3300000 0x0>;
|
||||
vin-supply = <&vcc_io_33>;
|
||||
};
|
||||
|
||||
vcc_sd: sdmmc-regulator {
|
||||
compatible = "regulator-fixed";
|
||||
gpio = <&gpio0 RK_PD6 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-0 = <&sdmmc0m1_gpio>;
|
||||
pinctrl-names = "default";
|
||||
regulator-name = "vcc_sd";
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc_io_33>;
|
||||
};
|
||||
|
||||
vdd_5v: vdd-5v {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd_5v";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
};
|
||||
};
|
||||
|
||||
&cpu0 {
|
||||
cpu-supply = <&vdd_arm>;
|
||||
};
|
||||
|
||||
&cpu1 {
|
||||
cpu-supply = <&vdd_arm>;
|
||||
};
|
||||
|
||||
&cpu2 {
|
||||
cpu-supply = <&vdd_arm>;
|
||||
};
|
||||
|
||||
&cpu3 {
|
||||
cpu-supply = <&vdd_arm>;
|
||||
};
|
||||
|
||||
&gmac2io {
|
||||
assigned-clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_EXT>;
|
||||
assigned-clock-parents = <&gmac_clk>, <&gmac_clk>;
|
||||
clock_in_out = "input";
|
||||
phy-handle = <&rtl8211e>;
|
||||
phy-mode = "rgmii";
|
||||
phy-supply = <&vcc_io_33>;
|
||||
pinctrl-0 = <&rgmiim1_pins>;
|
||||
pinctrl-names = "default";
|
||||
rx_delay = <0x18>;
|
||||
snps,aal;
|
||||
tx_delay = <0x24>;
|
||||
status = "okay";
|
||||
|
||||
mdio {
|
||||
compatible = "snps,dwmac-mdio";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
rtl8211e: ethernet-phy@1 {
|
||||
compatible = "ethernet-phy-id001c.c915",
|
||||
"ethernet-phy-ieee802.3-c22";
|
||||
reg = <1>;
|
||||
pinctrl-0 = <ð_phy_reset_pin>;
|
||||
pinctrl-names = "default";
|
||||
reset-assert-us = <10000>;
|
||||
reset-deassert-us = <50000>;
|
||||
reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c1 {
|
||||
status = "okay";
|
||||
|
||||
rk805: pmic@18 {
|
||||
compatible = "rockchip,rk805";
|
||||
reg = <0x18>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "xin32k", "rk805-clkout2";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
pinctrl-0 = <&pmic_int_l>;
|
||||
pinctrl-names = "default";
|
||||
rockchip,system-power-controller;
|
||||
wakeup-source;
|
||||
|
||||
vcc1-supply = <&vdd_5v>;
|
||||
vcc2-supply = <&vdd_5v>;
|
||||
vcc3-supply = <&vdd_5v>;
|
||||
vcc4-supply = <&vdd_5v>;
|
||||
vcc5-supply = <&vcc_io_33>;
|
||||
vcc6-supply = <&vdd_5v>;
|
||||
|
||||
regulators {
|
||||
vdd_log: DCDC_REG1 {
|
||||
regulator-name = "vdd_log";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <712500>;
|
||||
regulator-max-microvolt = <1450000>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <1000000>;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_arm: DCDC_REG2 {
|
||||
regulator-name = "vdd_arm";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <712500>;
|
||||
regulator-max-microvolt = <1450000>;
|
||||
regulator-ramp-delay = <12500>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <950000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_ddr: DCDC_REG3 {
|
||||
regulator-name = "vcc_ddr";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_io_33: DCDC_REG4 {
|
||||
regulator-name = "vcc_io_33";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_18: LDO_REG1 {
|
||||
regulator-name = "vcc_18";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <1800000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc18_emmc: LDO_REG2 {
|
||||
regulator-name = "vcc18_emmc";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <1800000>;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_10: LDO_REG3 {
|
||||
regulator-name = "vdd_10";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1000000>;
|
||||
regulator-max-microvolt = <1000000>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <1000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&io_domains {
|
||||
pmuio-supply = <&vcc_io_33>;
|
||||
vccio1-supply = <&vcc_io_33>;
|
||||
vccio2-supply = <&vcc18_emmc>;
|
||||
vccio3-supply = <&vcc_io_sdio>;
|
||||
vccio4-supply = <&vcc_18>;
|
||||
vccio5-supply = <&vcc_io_33>;
|
||||
vccio6-supply = <&vcc_io_33>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
button {
|
||||
reset_button_pin: reset-button-pin {
|
||||
rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
ethernet-phy {
|
||||
eth_phy_reset_pin: eth-phy-reset-pin {
|
||||
rockchip,pins = <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
lan_led_pin: lan-led-pin {
|
||||
rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
sys_led_pin: sys-led-pin {
|
||||
rockchip,pins = <0 RK_PA2 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
wan_led_pin: wan-led-pin {
|
||||
rockchip,pins = <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
pmic {
|
||||
pmic_int_l: pmic-int-l {
|
||||
rockchip,pins = <1 RK_PD0 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
};
|
||||
|
||||
sd {
|
||||
sdio_vcc_pin: sdio-vcc-pin {
|
||||
rockchip,pins = <1 RK_PD4 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pwm2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
bus-width = <4>;
|
||||
cap-sd-highspeed;
|
||||
disable-wp;
|
||||
pinctrl-0 = <&sdmmc0_clk>, <&sdmmc0_cmd>, <&sdmmc0_dectn>, <&sdmmc0_bus4>;
|
||||
pinctrl-names = "default";
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
sd-uhs-sdr50;
|
||||
sd-uhs-sdr104;
|
||||
vmmc-supply = <&vcc_sd>;
|
||||
vqmmc-supply = <&vcc_io_sdio>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&tsadc {
|
||||
rockchip,hw-tshut-mode = <0>;
|
||||
rockchip,hw-tshut-polarity = <0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&u2phy {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&u2phy_host {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&u2phy_otg {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb20_otg {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&usb_host0_ehci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_host0_ohci {
|
||||
status = "okay";
|
||||
};
|
|
@ -13,10 +13,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
&rng {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
@ -38,6 +34,10 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
&vdd_center {
|
||||
regulator-init-microvolt = <900000>;
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
u-boot,dm-pre-reloc;
|
||||
bus-width = <4>;
|
||||
|
|
|
@ -11,3 +11,7 @@
|
|||
u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
|
||||
};
|
||||
};
|
||||
|
||||
&vdd_log {
|
||||
regulator-init-microvolt = <950000>;
|
||||
};
|
||||
|
|
|
@ -11,3 +11,7 @@
|
|||
u-boot,spl-boot-order = "same-as-spl", &sdhci, &sdmmc;
|
||||
};
|
||||
};
|
||||
|
||||
&vdd_log {
|
||||
regulator-init-microvolt = <950000>;
|
||||
};
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
u-boot,dm-pre-reloc;
|
||||
};
|
||||
|
||||
&rng {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdhci {
|
||||
max-frequency = <25000000>;
|
||||
u-boot,dm-pre-reloc;
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
};
|
||||
|
||||
aliases {
|
||||
spi0 = &spi1;
|
||||
spi1 = &spi5;
|
||||
spi5 = &spi5;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,10 +7,6 @@
|
|||
#include "rk3399-sdram-lpddr4-100.dtsi"
|
||||
|
||||
/ {
|
||||
aliases {
|
||||
spi0 = &spi1;
|
||||
};
|
||||
|
||||
chosen {
|
||||
u-boot,spl-boot-order = "same-as-spl", &spi_flash, &sdhci, &sdmmc;
|
||||
};
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
};
|
||||
};
|
||||
|
||||
&rng {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
spi_flash: flash@0 {
|
||||
u-boot,dm-pre-reloc;
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
rng: rng@ff8b8000 {
|
||||
compatible = "rockchip,cryptov1-rng";
|
||||
reg = <0x0 0xff8b8000 0x0 0x1000>;
|
||||
status = "disabled";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dmc: dmc {
|
||||
|
|
|
@ -5,6 +5,13 @@ F: board/rockchip/evb_rk3328
|
|||
F: include/configs/evb_rk3328.h
|
||||
F: configs/evb-rk3328_defconfig
|
||||
|
||||
NANOPI-R2S-RK3328
|
||||
M: David Bauer <mail@david-bauer.net>
|
||||
S: Maintained
|
||||
F: configs/nanopi-r2s-rk3328_defconfig
|
||||
F: arch/arm/dts/rk3328-nanopi-r2s-u-boot.dtsi
|
||||
F: arch/arm/dts/rk3328-nanopi-r2s.dts
|
||||
|
||||
ROC-RK3328-CC
|
||||
M: Loic Devulder <ldevulder@suse.com>
|
||||
M: Chen-Yu Tsai <wens@csie.org>
|
||||
|
|
|
@ -35,6 +35,8 @@ CONFIG_MMC_DW=y
|
|||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_DM_RNG=y
|
||||
CONFIG_RNG_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_SPEED=20000000
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
|
|
98
configs/nanopi-r2s-rk3328_defconfig
Normal file
98
configs/nanopi-r2s-rk3328_defconfig
Normal file
|
@ -0,0 +1,98 @@
|
|||
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
|
||||
CONFIG_TPL_LIBCOMMON_SUPPORT=y
|
||||
CONFIG_TPL_LIBGENERIC_SUPPORT=y
|
||||
CONFIG_SPL_DRIVERS_MISC_SUPPORT=y
|
||||
CONFIG_SPL_STACK_R_ADDR=0x600000
|
||||
CONFIG_NR_DRAM_BANKS=1
|
||||
CONFIG_DEBUG_UART_BASE=0xFF130000
|
||||
CONFIG_DEBUG_UART_CLOCK=24000000
|
||||
CONFIG_SYSINFO=y
|
||||
CONFIG_DEBUG_UART=y
|
||||
CONFIG_TPL_SYS_MALLOC_F_LEN=0x800
|
||||
# CONFIG_ANDROID_BOOT_IMAGE is not set
|
||||
CONFIG_FIT=y
|
||||
CONFIG_FIT_VERBOSE=y
|
||||
CONFIG_SPL_LOAD_FIT=y
|
||||
CONFIG_DEFAULT_FDT_FILE="rockchip/rk3328-nanopi-r2s.dtb"
|
||||
CONFIG_MISC_INIT_R=y
|
||||
# CONFIG_DISPLAY_CPUINFO is not set
|
||||
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
|
||||
CONFIG_CMD_GPT=y
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
CONFIG_CMD_TIME=y
|
||||
CONFIG_SPL_OF_CONTROL=y
|
||||
CONFIG_TPL_OF_CONTROL=y
|
||||
CONFIG_DEFAULT_DEVICE_TREE="rk3328-nanopi-r2s"
|
||||
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
|
||||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_TPL_DM=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_SPL_REGMAP=y
|
||||
CONFIG_TPL_REGMAP=y
|
||||
CONFIG_SYSCON=y
|
||||
CONFIG_SPL_SYSCON=y
|
||||
CONFIG_TPL_SYSCON=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_SPL_CLK=y
|
||||
CONFIG_FASTBOOT_BUF_ADDR=0x800800
|
||||
CONFIG_FASTBOOT_CMD_OEM_FORMAT=y
|
||||
CONFIG_ROCKCHIP_GPIO=y
|
||||
CONFIG_SYS_I2C_ROCKCHIP=y
|
||||
CONFIG_MMC_DW=y
|
||||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_SPEED=20000000
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
CONFIG_GMAC_ROCKCHIP=y
|
||||
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_DM_REGULATOR_FIXED=y
|
||||
CONFIG_SPL_DM_REGULATOR_FIXED=y
|
||||
CONFIG_REGULATOR_RK8XX=y
|
||||
CONFIG_PWM_ROCKCHIP=y
|
||||
CONFIG_RAM=y
|
||||
CONFIG_SPL_RAM=y
|
||||
CONFIG_TPL_RAM=y
|
||||
CONFIG_DM_RESET=y
|
||||
CONFIG_BAUDRATE=1500000
|
||||
CONFIG_DEBUG_UART_SHIFT=2
|
||||
CONFIG_SYSRESET=y
|
||||
# CONFIG_TPL_SYSRESET is not set
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
CONFIG_USB_XHCI_DWC3=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_GENERIC=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_OHCI_GENERIC=y
|
||||
CONFIG_USB_DWC2=y
|
||||
CONFIG_USB_DWC3=y
|
||||
# CONFIG_USB_DWC3_GADGET is not set
|
||||
CONFIG_USB_GADGET=y
|
||||
CONFIG_USB_GADGET_DWC2_OTG=y
|
||||
CONFIG_SPL_TINY_MEMSET=y
|
||||
CONFIG_TPL_TINY_MEMSET=y
|
||||
CONFIG_ERRNO_STR=y
|
|
@ -44,6 +44,7 @@ CONFIG_ENV_OVERWRITE=y
|
|||
CONFIG_ENV_IS_IN_MMC=y
|
||||
CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
||||
CONFIG_SYS_MMC_ENV_DEV=1
|
||||
CONFIG_SPL_DM_SEQ_ALIAS=y
|
||||
CONFIG_ROCKCHIP_GPIO=y
|
||||
CONFIG_SYS_I2C_ROCKCHIP=y
|
||||
CONFIG_MISC=y
|
||||
|
@ -53,6 +54,7 @@ CONFIG_MMC_DW_ROCKCHIP=y
|
|||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_SDMA=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_BUS=1
|
||||
CONFIG_SF_DEFAULT_SPEED=20000000
|
||||
CONFIG_SPI_FLASH_GIGADEVICE=y
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
|
|
|
@ -42,6 +42,7 @@ CONFIG_MMC_DW=y
|
|||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_BUS=1
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
|
|
|
@ -41,6 +41,7 @@ CONFIG_MMC_DW=y
|
|||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_BUS=1
|
||||
CONFIG_SPI_FLASH_WINBOND=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_ETH_DESIGNWARE=y
|
||||
|
|
|
@ -39,6 +39,8 @@ CONFIG_MMC_DW_ROCKCHIP=y
|
|||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_SDMA=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_DM_RNG=y
|
||||
CONFIG_RNG_ROCKCHIP=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_NVME=y
|
||||
CONFIG_PCI=y
|
||||
|
|
|
@ -42,6 +42,8 @@ CONFIG_MMC_DW=y
|
|||
CONFIG_MMC_DW_ROCKCHIP=y
|
||||
CONFIG_MMC_SDHCI=y
|
||||
CONFIG_MMC_SDHCI_ROCKCHIP=y
|
||||
CONFIG_DM_RNG=y
|
||||
CONFIG_RNG_ROCKCHIP=y
|
||||
CONFIG_SF_DEFAULT_BUS=1
|
||||
CONFIG_SPI_FLASH_GIGADEVICE=y
|
||||
CONFIG_DM_ETH=y
|
||||
|
|
|
@ -281,6 +281,15 @@ config PCIE_ROCKCHIP
|
|||
Say Y here if you want to enable PCIe controller support on
|
||||
Rockchip SoCs.
|
||||
|
||||
config PCIE_DW_ROCKCHIP
|
||||
bool "Rockchip DesignWare based PCIe controller"
|
||||
depends on ARCH_ROCKCHIP
|
||||
select DM_PCI
|
||||
select PHY_ROCKCHIP_SNPS_PCIE3
|
||||
help
|
||||
Say Y here if you want to enable DW PCIe controller support on
|
||||
Rockchip SoCs.
|
||||
|
||||
config PCI_BRCMSTB
|
||||
bool "Broadcom STB PCIe controller"
|
||||
depends on DM_PCI
|
||||
|
|
|
@ -48,5 +48,6 @@ 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
|
||||
obj-$(CONFIG_PCIE_DW_ROCKCHIP) += pcie_dw_rockchip.o
|
||||
obj-$(CONFIG_PCI_BRCMSTB) += pcie_brcmstb.o
|
||||
obj-$(CONFIG_PCI_OCTEONTX) += pci_octeontx.o
|
||||
|
|
877
drivers/pci/pcie_dw_rockchip.c
Normal file
877
drivers/pci/pcie_dw_rockchip.c
Normal file
|
@ -0,0 +1,877 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Rockchip DesignWare based PCIe host controller driver
|
||||
*
|
||||
* Copyright (c) 2021 Rockchip, Inc.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <pci.h>
|
||||
#include <power-domain.h>
|
||||
#include <reset.h>
|
||||
#include <syscon.h>
|
||||
#include <asm/arch-rockchip/clock.h>
|
||||
#include <asm/io.h>
|
||||
#include <asm-generic/gpio.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/delay.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
DECLARE_GLOBAL_DATA_PTR;
|
||||
|
||||
/**
|
||||
* struct rk_pcie - RK DW PCIe controller state
|
||||
*
|
||||
* @vpcie3v3: The 3.3v power supply for slot
|
||||
* @dbi_base: The base address of dwc core regs
|
||||
* @apb_base: The base address of vendor regs
|
||||
* @cfg_base: The base address of config header space
|
||||
* @cfg_size: The size of the configuration space which is needed
|
||||
* as it gets written into the PCIE_ATU_LIMIT register
|
||||
* @first_busno: This driver supports multiple PCIe controllers.
|
||||
* first_busno stores the bus number of the PCIe root-port
|
||||
* number which may vary depending on the PCIe setup
|
||||
* (PEX switches etc).
|
||||
* @rst_gpio: The #PERST signal for slot
|
||||
* @io: The IO space for EP's BAR
|
||||
* @mem: The memory space for EP's BAR
|
||||
*/
|
||||
struct rk_pcie {
|
||||
struct udevice *dev;
|
||||
struct udevice *vpcie3v3;
|
||||
void *dbi_base;
|
||||
void *apb_base;
|
||||
void *cfg_base;
|
||||
fdt_size_t cfg_size;
|
||||
struct phy phy;
|
||||
struct clk_bulk clks;
|
||||
int first_busno;
|
||||
struct reset_ctl_bulk rsts;
|
||||
struct gpio_desc rst_gpio;
|
||||
struct pci_region io;
|
||||
struct pci_region mem;
|
||||
};
|
||||
|
||||
/* Parameters for the waiting for iATU enabled routine */
|
||||
#define PCIE_CLIENT_GENERAL_DEBUG 0x104
|
||||
#define PCIE_CLIENT_HOT_RESET_CTRL 0x180
|
||||
#define PCIE_LTSSM_ENABLE_ENHANCE BIT(4)
|
||||
#define PCIE_CLIENT_LTSSM_STATUS 0x300
|
||||
#define SMLH_LINKUP BIT(16)
|
||||
#define RDLH_LINKUP BIT(17)
|
||||
#define PCIE_CLIENT_DBG_FIFO_MODE_CON 0x310
|
||||
#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
|
||||
#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
|
||||
#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
|
||||
#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
|
||||
#define PCIE_CLIENT_DBG_FIFO_STATUS 0x350
|
||||
#define PCIE_CLIENT_DBG_TRANSITION_DATA 0xffff0000
|
||||
#define PCIE_CLIENT_DBF_EN 0xffff0003
|
||||
|
||||
/* PCI DBICS registers */
|
||||
#define PCIE_LINK_STATUS_REG 0x80
|
||||
#define PCIE_LINK_STATUS_SPEED_OFF 16
|
||||
#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF)
|
||||
#define PCIE_LINK_STATUS_WIDTH_OFF 20
|
||||
#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF)
|
||||
|
||||
#define PCIE_LINK_CAPABILITY 0x7c
|
||||
#define PCIE_LINK_CTL_2 0xa0
|
||||
#define TARGET_LINK_SPEED_MASK 0xf
|
||||
#define LINK_SPEED_GEN_1 0x1
|
||||
#define LINK_SPEED_GEN_2 0x2
|
||||
#define LINK_SPEED_GEN_3 0x3
|
||||
|
||||
#define PCIE_MISC_CONTROL_1_OFF 0x8bc
|
||||
#define PCIE_DBI_RO_WR_EN BIT(0)
|
||||
|
||||
#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c
|
||||
#define PORT_LOGIC_SPEED_CHANGE BIT(17)
|
||||
|
||||
/*
|
||||
* iATU Unroll-specific register definitions
|
||||
* From 4.80 core version the address translation will be made by unroll.
|
||||
* The registers are offset from atu_base
|
||||
*/
|
||||
#define PCIE_ATU_UNR_REGION_CTRL1 0x00
|
||||
#define PCIE_ATU_UNR_REGION_CTRL2 0x04
|
||||
#define PCIE_ATU_UNR_LOWER_BASE 0x08
|
||||
#define PCIE_ATU_UNR_UPPER_BASE 0x0c
|
||||
#define PCIE_ATU_UNR_LIMIT 0x10
|
||||
#define PCIE_ATU_UNR_LOWER_TARGET 0x14
|
||||
#define PCIE_ATU_UNR_UPPER_TARGET 0x18
|
||||
|
||||
#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
|
||||
#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
|
||||
#define PCIE_ATU_TYPE_MEM (0x0 << 0)
|
||||
#define PCIE_ATU_TYPE_IO (0x2 << 0)
|
||||
#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
|
||||
#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
|
||||
#define PCIE_ATU_ENABLE (0x1 << 31)
|
||||
#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
|
||||
#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
|
||||
#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
|
||||
#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
|
||||
|
||||
/* Register address builder */
|
||||
#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \
|
||||
((0x3 << 20) | ((region) << 9))
|
||||
|
||||
/* Parameters for the waiting for iATU enabled routine */
|
||||
#define LINK_WAIT_MAX_IATU_RETRIES 5
|
||||
#define LINK_WAIT_IATU_US 10000
|
||||
|
||||
/* Parameters for the waiting for #perst signal */
|
||||
#define PERST_WAIT_MS 1000
|
||||
|
||||
static int rk_pcie_read(void __iomem *addr, int size, u32 *val)
|
||||
{
|
||||
if ((uintptr_t)addr & (size - 1)) {
|
||||
*val = 0;
|
||||
return PCIBIOS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (size == 4) {
|
||||
*val = readl(addr);
|
||||
} else if (size == 2) {
|
||||
*val = readw(addr);
|
||||
} else if (size == 1) {
|
||||
*val = readb(addr);
|
||||
} else {
|
||||
*val = 0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rk_pcie_write(void __iomem *addr, int size, u32 val)
|
||||
{
|
||||
if ((uintptr_t)addr & (size - 1))
|
||||
return PCIBIOS_UNSUPPORTED;
|
||||
|
||||
if (size == 4)
|
||||
writel(val, addr);
|
||||
else if (size == 2)
|
||||
writew(val, addr);
|
||||
else if (size == 1)
|
||||
writeb(val, addr);
|
||||
else
|
||||
return -ENODEV;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 __rk_pcie_read_apb(struct rk_pcie *rk_pcie, void __iomem *base,
|
||||
u32 reg, size_t size)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
ret = rk_pcie_read(base + reg, size, &val);
|
||||
if (ret)
|
||||
dev_err(rk_pcie->dev, "Read APB address failed\n");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __rk_pcie_write_apb(struct rk_pcie *rk_pcie, void __iomem *base,
|
||||
u32 reg, size_t size, u32 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = rk_pcie_write(base + reg, size, val);
|
||||
if (ret)
|
||||
dev_err(rk_pcie->dev, "Write APB address failed\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_readl_apb() - Read vendor regs
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @reg: Offset of regs
|
||||
*/
|
||||
static inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
|
||||
{
|
||||
return __rk_pcie_read_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4);
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_writel_apb() - Write vendor regs
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @reg: Offset of regs
|
||||
* @val: Value to be writen
|
||||
*/
|
||||
static inline void rk_pcie_writel_apb(struct rk_pcie *rk_pcie, u32 reg,
|
||||
u32 val)
|
||||
{
|
||||
__rk_pcie_write_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4, val);
|
||||
}
|
||||
|
||||
static int rk_pcie_get_link_speed(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
|
||||
PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF;
|
||||
}
|
||||
|
||||
static int rk_pcie_get_link_width(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
return (readl(rk_pcie->dbi_base + PCIE_LINK_STATUS_REG) &
|
||||
PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF;
|
||||
}
|
||||
|
||||
static void rk_pcie_writel_ob_unroll(struct rk_pcie *rk_pcie, u32 index,
|
||||
u32 reg, u32 val)
|
||||
{
|
||||
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
|
||||
void __iomem *base = rk_pcie->dbi_base;
|
||||
|
||||
writel(val, base + offset + reg);
|
||||
}
|
||||
|
||||
static u32 rk_pcie_readl_ob_unroll(struct rk_pcie *rk_pcie, u32 index, u32 reg)
|
||||
{
|
||||
u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
|
||||
void __iomem *base = rk_pcie->dbi_base;
|
||||
|
||||
return readl(base + offset + reg);
|
||||
}
|
||||
|
||||
static inline void rk_pcie_dbi_write_enable(struct rk_pcie *rk_pcie, bool en)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
|
||||
|
||||
if (en)
|
||||
val |= PCIE_DBI_RO_WR_EN;
|
||||
else
|
||||
val &= ~PCIE_DBI_RO_WR_EN;
|
||||
writel(val, rk_pcie->dbi_base + PCIE_MISC_CONTROL_1_OFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_pcie_setup_host() - Setup the PCIe controller for RC opertaion
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
*
|
||||
* Configure the host BARs of the PCIe controller root port so that
|
||||
* PCI(e) devices may access the system memory.
|
||||
*/
|
||||
static void rk_pcie_setup_host(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
rk_pcie_dbi_write_enable(rk_pcie, true);
|
||||
|
||||
/* setup RC BARs */
|
||||
writel(PCI_BASE_ADDRESS_MEM_TYPE_64,
|
||||
rk_pcie->dbi_base + PCI_BASE_ADDRESS_0);
|
||||
writel(0x0, rk_pcie->dbi_base + PCI_BASE_ADDRESS_1);
|
||||
|
||||
/* setup interrupt pins */
|
||||
clrsetbits_le32(rk_pcie->dbi_base + PCI_INTERRUPT_LINE,
|
||||
0xff00, 0x100);
|
||||
|
||||
/* setup bus numbers */
|
||||
clrsetbits_le32(rk_pcie->dbi_base + PCI_PRIMARY_BUS,
|
||||
0xffffff, 0x00ff0100);
|
||||
|
||||
/* setup command register */
|
||||
clrsetbits_le32(rk_pcie->dbi_base + PCI_PRIMARY_BUS,
|
||||
0xffff,
|
||||
PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
|
||||
PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
|
||||
|
||||
/* program correct class for RC */
|
||||
writew(PCI_CLASS_BRIDGE_PCI, rk_pcie->dbi_base + PCI_CLASS_DEVICE);
|
||||
/* Better disable write permission right after the update */
|
||||
|
||||
setbits_le32(rk_pcie->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL,
|
||||
PORT_LOGIC_SPEED_CHANGE)
|
||||
|
||||
rk_pcie_dbi_write_enable(rk_pcie, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_configure() - Configure link capabilities and speed
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @cap_speed: The capabilities and speed to configure
|
||||
*
|
||||
* Configure the link capabilities and speed in the PCIe root complex.
|
||||
*/
|
||||
static void rk_pcie_configure(struct rk_pcie *pci, u32 cap_speed)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
rk_pcie_dbi_write_enable(pci, true);
|
||||
|
||||
clrsetbits_le32(pci->dbi_base + PCIE_LINK_CAPABILITY,
|
||||
TARGET_LINK_SPEED_MASK, cap_speed);
|
||||
|
||||
clrsetbits_le32(pci->dbi_base + PCIE_LINK_CTL_2,
|
||||
TARGET_LINK_SPEED_MASK, cap_speed);
|
||||
|
||||
rk_pcie_dbi_write_enable(pci, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @index: ATU region index
|
||||
* @type: ATU accsess type
|
||||
* @cpu_addr: the physical address for the translation entry
|
||||
* @pci_addr: the pcie bus address for the translation entry
|
||||
* @size: the size of the translation entry
|
||||
*
|
||||
* Return: 0 is successful and -1 is failure
|
||||
*/
|
||||
static int rk_pcie_prog_outbound_atu_unroll(struct rk_pcie *pci, int index,
|
||||
int type, u64 cpu_addr,
|
||||
u64 pci_addr, u32 size)
|
||||
{
|
||||
u32 retries, val;
|
||||
|
||||
dev_dbg(pci->dev, "ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n",
|
||||
index, type, cpu_addr, pci_addr, size);
|
||||
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
|
||||
lower_32_bits(cpu_addr));
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
|
||||
upper_32_bits(cpu_addr));
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
|
||||
lower_32_bits(cpu_addr + size - 1));
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
|
||||
lower_32_bits(pci_addr));
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
|
||||
upper_32_bits(pci_addr));
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
|
||||
type);
|
||||
rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
|
||||
PCIE_ATU_ENABLE);
|
||||
|
||||
/*
|
||||
* Make sure ATU enable takes effect before any subsequent config
|
||||
* and I/O accesses.
|
||||
*/
|
||||
for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
|
||||
val = rk_pcie_readl_ob_unroll(pci, index,
|
||||
PCIE_ATU_UNR_REGION_CTRL2);
|
||||
if (val & PCIE_ATU_ENABLE)
|
||||
return 0;
|
||||
|
||||
udelay(LINK_WAIT_IATU_US);
|
||||
}
|
||||
dev_err(pci->dev, "outbound iATU is not being enabled\n");
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_dw_addr_valid() - Check for valid bus address
|
||||
*
|
||||
* @d: The PCI device to access
|
||||
* @first_busno: Bus number of the PCIe controller root complex
|
||||
*
|
||||
* Return 1 (true) if the PCI device can be accessed by this controller.
|
||||
*
|
||||
* Return: 1 on valid, 0 on invalid
|
||||
*/
|
||||
static int rk_pcie_addr_valid(pci_dev_t d, int first_busno)
|
||||
{
|
||||
if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0))
|
||||
return 0;
|
||||
if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_cfg_address() - Configure the PCIe controller config space access
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @d: PCI device to access
|
||||
* @where: Offset in the configuration space
|
||||
*
|
||||
* Configures the PCIe controller to access the configuration space of
|
||||
* a specific PCIe device and returns the address to use for this
|
||||
* access.
|
||||
*
|
||||
* Return: Address that can be used to access the configation space
|
||||
* of the requested device / offset
|
||||
*/
|
||||
static uintptr_t set_cfg_address(struct rk_pcie *pcie,
|
||||
pci_dev_t d, uint where)
|
||||
{
|
||||
int rel_bus = PCI_BUS(d) - pcie->first_busno;
|
||||
uintptr_t va_address;
|
||||
u32 atu_type;
|
||||
int ret;
|
||||
|
||||
/* Use dbi_base for own configuration read and write */
|
||||
if (!rel_bus) {
|
||||
va_address = (uintptr_t)pcie->dbi_base;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (rel_bus == 1)
|
||||
/*
|
||||
* For local bus whose primary bus number is root bridge,
|
||||
* change TLP Type field to 4.
|
||||
*/
|
||||
atu_type = PCIE_ATU_TYPE_CFG0;
|
||||
else
|
||||
/* Otherwise, change TLP Type field to 5. */
|
||||
atu_type = PCIE_ATU_TYPE_CFG1;
|
||||
|
||||
/*
|
||||
* Not accessing root port configuration space?
|
||||
* Region #0 is used for Outbound CFG space access.
|
||||
* Direction = Outbound
|
||||
* Region Index = 0
|
||||
*/
|
||||
d = PCI_MASK_BUS(d);
|
||||
d = PCI_ADD_BUS(rel_bus, d);
|
||||
ret = rk_pcie_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1,
|
||||
atu_type, (u64)pcie->cfg_base,
|
||||
d << 8, pcie->cfg_size);
|
||||
if (ret)
|
||||
return (uintptr_t)ret;
|
||||
|
||||
va_address = (uintptr_t)pcie->cfg_base;
|
||||
|
||||
out:
|
||||
va_address += where & ~0x3;
|
||||
|
||||
return va_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_pcie_rd_conf() - Read from configuration space
|
||||
*
|
||||
* @bus: Pointer to the PCI bus
|
||||
* @bdf: Identifies the PCIe device to access
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @valuep: A pointer at which to store the read value
|
||||
* @size: Indicates the size of access to perform
|
||||
*
|
||||
* Read a value of size @size from offset @offset within the configuration
|
||||
* space of the device identified by the bus, device & function numbers in @bdf
|
||||
* on the PCI bus @bus.
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int rockchip_pcie_rd_conf(const struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong *valuep,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct rk_pcie *pcie = dev_get_priv(bus);
|
||||
uintptr_t va_address;
|
||||
ulong value;
|
||||
|
||||
debug("PCIE CFG read: bdf=%2x:%2x:%2x\n",
|
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
|
||||
|
||||
if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
|
||||
debug("- out of range\n");
|
||||
*valuep = pci_get_ff(size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_address = set_cfg_address(pcie, bdf, offset);
|
||||
|
||||
value = readl(va_address);
|
||||
|
||||
debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
|
||||
*valuep = pci_conv_32_to_size(value, offset, size);
|
||||
|
||||
return rk_pcie_prog_outbound_atu_unroll(pcie,
|
||||
PCIE_ATU_REGION_INDEX1,
|
||||
PCIE_ATU_TYPE_IO,
|
||||
pcie->io.phys_start,
|
||||
pcie->io.bus_start,
|
||||
pcie->io.size);
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_pcie_wr_conf() - Write to configuration space
|
||||
*
|
||||
* @bus: Pointer to the PCI bus
|
||||
* @bdf: Identifies the PCIe device to access
|
||||
* @offset: The offset into the device's configuration space
|
||||
* @value: The value to write
|
||||
* @size: Indicates the size of access to perform
|
||||
*
|
||||
* Write the value @value of size @size from offset @offset within the
|
||||
* configuration space of the device identified by the bus, device & function
|
||||
* numbers in @bdf on the PCI bus @bus.
|
||||
*
|
||||
* Return: 0 on success
|
||||
*/
|
||||
static int rockchip_pcie_wr_conf(struct udevice *bus, pci_dev_t bdf,
|
||||
uint offset, ulong value,
|
||||
enum pci_size_t size)
|
||||
{
|
||||
struct rk_pcie *pcie = dev_get_priv(bus);
|
||||
uintptr_t va_address;
|
||||
ulong old;
|
||||
|
||||
debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d)\n",
|
||||
PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf));
|
||||
debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value);
|
||||
|
||||
if (!rk_pcie_addr_valid(bdf, pcie->first_busno)) {
|
||||
debug("- out of range\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
va_address = set_cfg_address(pcie, bdf, offset);
|
||||
|
||||
old = readl(va_address);
|
||||
value = pci_conv_size_to_32(old, value, offset, size);
|
||||
writel(value, va_address);
|
||||
|
||||
return rk_pcie_prog_outbound_atu_unroll(pcie,
|
||||
PCIE_ATU_REGION_INDEX1,
|
||||
PCIE_ATU_TYPE_IO,
|
||||
pcie->io.phys_start,
|
||||
pcie->io.bus_start,
|
||||
pcie->io.size);
|
||||
|
||||
}
|
||||
|
||||
static void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0,
|
||||
PCIE_CLIENT_DBG_TRANSITION_DATA);
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1,
|
||||
PCIE_CLIENT_DBG_TRANSITION_DATA);
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0,
|
||||
PCIE_CLIENT_DBG_TRANSITION_DATA);
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1,
|
||||
PCIE_CLIENT_DBG_TRANSITION_DATA);
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
|
||||
PCIE_CLIENT_DBF_EN);
|
||||
}
|
||||
|
||||
static void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
u32 loop;
|
||||
|
||||
debug("ltssm = 0x%x\n",
|
||||
rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
|
||||
for (loop = 0; loop < 64; loop++)
|
||||
debug("fifo_status = 0x%x\n",
|
||||
rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_STATUS));
|
||||
}
|
||||
|
||||
static inline void rk_pcie_link_status_clear(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG, 0x0);
|
||||
}
|
||||
|
||||
static inline void rk_pcie_disable_ltssm(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
rk_pcie_writel_apb(rk_pcie, 0x0, 0xc0008);
|
||||
}
|
||||
|
||||
static inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
|
||||
{
|
||||
rk_pcie_writel_apb(rk_pcie, 0x0, 0xc000c);
|
||||
}
|
||||
|
||||
static int is_link_up(struct rk_pcie *priv)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS);
|
||||
if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000 &&
|
||||
(val & GENMASK(5, 0)) == 0x11)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rk_pcie_link_up() - Wait for the link to come up
|
||||
*
|
||||
* @rk_pcie: Pointer to the PCI controller state
|
||||
* @cap_speed: Desired link speed
|
||||
*
|
||||
* Return: 1 (true) for active line and negetive (false) for no link (timeout)
|
||||
*/
|
||||
static int rk_pcie_link_up(struct rk_pcie *priv, u32 cap_speed)
|
||||
{
|
||||
int retries;
|
||||
|
||||
if (is_link_up(priv)) {
|
||||
printf("PCI Link already up before configuration!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* DW pre link configurations */
|
||||
rk_pcie_configure(priv, cap_speed);
|
||||
|
||||
/* Rest the device */
|
||||
if (dm_gpio_is_valid(&priv->rst_gpio)) {
|
||||
dm_gpio_set_value(&priv->rst_gpio, 0);
|
||||
/*
|
||||
* Minimal is 100ms from spec but we see
|
||||
* some wired devices need much more, such as 600ms.
|
||||
* Add a enough delay to cover all cases.
|
||||
*/
|
||||
msleep(PERST_WAIT_MS);
|
||||
dm_gpio_set_value(&priv->rst_gpio, 1);
|
||||
}
|
||||
|
||||
rk_pcie_disable_ltssm(priv);
|
||||
rk_pcie_link_status_clear(priv);
|
||||
rk_pcie_enable_debug(priv);
|
||||
|
||||
/* Enable LTSSM */
|
||||
rk_pcie_enable_ltssm(priv);
|
||||
|
||||
for (retries = 0; retries < 5; retries++) {
|
||||
if (is_link_up(priv)) {
|
||||
dev_info(priv->dev, "PCIe Link up, LTSSM is 0x%x\n",
|
||||
rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
|
||||
rk_pcie_debug_dump(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_info(priv->dev, "PCIe Linking... LTSSM is 0x%x\n",
|
||||
rk_pcie_readl_apb(priv, PCIE_CLIENT_LTSSM_STATUS));
|
||||
rk_pcie_debug_dump(priv);
|
||||
msleep(1000);
|
||||
}
|
||||
|
||||
dev_err(priv->dev, "PCIe-%d Link Fail\n", dev_seq(priv->dev));
|
||||
/* Link maybe in Gen switch recovery but we need to wait more 1s */
|
||||
msleep(1000);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static int rockchip_pcie_init_port(struct udevice *dev)
|
||||
{
|
||||
int ret;
|
||||
u32 val;
|
||||
struct rk_pcie *priv = dev_get_priv(dev);
|
||||
|
||||
/* Set power and maybe external ref clk input */
|
||||
if (priv->vpcie3v3) {
|
||||
ret = regulator_set_value(priv->vpcie3v3, 3300000);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "failed to enable vpcie3v3 (ret=%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
msleep(1000);
|
||||
|
||||
ret = generic_phy_init(&priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to init phy (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = generic_phy_power_on(&priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to power on phy (ret=%d)\n", ret);
|
||||
goto err_exit_phy;
|
||||
}
|
||||
|
||||
ret = reset_deassert_bulk(&priv->rsts);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to deassert resets (ret=%d)\n", ret);
|
||||
goto err_power_off_phy;
|
||||
}
|
||||
|
||||
ret = clk_enable_bulk(&priv->clks);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to enable clks (ret=%d)\n", ret);
|
||||
goto err_deassert_bulk;
|
||||
}
|
||||
|
||||
/* LTSSM EN ctrl mode */
|
||||
val = rk_pcie_readl_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL);
|
||||
val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
|
||||
rk_pcie_writel_apb(priv, PCIE_CLIENT_HOT_RESET_CTRL, val);
|
||||
|
||||
/* Set RC mode */
|
||||
rk_pcie_writel_apb(priv, 0x0, 0xf00040);
|
||||
rk_pcie_setup_host(priv);
|
||||
|
||||
ret = rk_pcie_link_up(priv, LINK_SPEED_GEN_3);
|
||||
if (ret < 0)
|
||||
goto err_link_up;
|
||||
|
||||
return 0;
|
||||
err_link_up:
|
||||
clk_disable_bulk(&priv->clks);
|
||||
err_deassert_bulk:
|
||||
reset_assert_bulk(&priv->rsts);
|
||||
err_power_off_phy:
|
||||
generic_phy_power_off(&priv->phy);
|
||||
err_exit_phy:
|
||||
generic_phy_exit(&priv->phy);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_pcie_parse_dt(struct udevice *dev)
|
||||
{
|
||||
struct rk_pcie *priv = dev_get_priv(dev);
|
||||
int ret;
|
||||
|
||||
priv->dbi_base = (void *)dev_read_addr_index(dev, 0);
|
||||
if (!priv->dbi_base)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(dev, "DBI address is 0x%p\n", priv->dbi_base);
|
||||
|
||||
priv->apb_base = (void *)dev_read_addr_index(dev, 1);
|
||||
if (!priv->apb_base)
|
||||
return -ENODEV;
|
||||
|
||||
dev_dbg(dev, "APB address is 0x%p\n", priv->apb_base);
|
||||
|
||||
ret = gpio_request_by_name(dev, "reset-gpios", 0,
|
||||
&priv->rst_gpio, GPIOD_IS_OUT);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to find reset-gpios property\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = reset_get_bulk(dev, &priv->rsts);
|
||||
if (ret) {
|
||||
dev_err(dev, "Can't get reset: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_bulk(dev, &priv->clks);
|
||||
if (ret) {
|
||||
dev_err(dev, "Can't get clock: %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 = generic_phy_get_by_index(dev, 0, &priv->phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to get pcie phy (ret=%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* rockchip_pcie_probe() - Probe the PCIe bus for active link
|
||||
*
|
||||
* @dev: A pointer to the device being operated on
|
||||
*
|
||||
* Probe for an active link on the PCIe bus and configure the controller
|
||||
* to enable this port.
|
||||
*
|
||||
* Return: 0 on success, else -ENODEV
|
||||
*/
|
||||
static int rockchip_pcie_probe(struct udevice *dev)
|
||||
{
|
||||
struct rk_pcie *priv = dev_get_priv(dev);
|
||||
struct udevice *ctlr = pci_get_controller(dev);
|
||||
struct pci_controller *hose = dev_get_uclass_priv(ctlr);
|
||||
int reti = 0;
|
||||
|
||||
priv->first_busno = dev_seq(dev);
|
||||
priv->dev = dev;
|
||||
|
||||
ret = rockchip_pcie_parse_dt(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = rockchip_pcie_init_port(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_info(dev, "PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n",
|
||||
dev_seq(dev), rk_pcie_get_link_speed(priv),
|
||||
rk_pcie_get_link_width(priv),
|
||||
hose->first_busno);
|
||||
|
||||
for (ret = 0; ret < hose->region_count; ret++) {
|
||||
if (hose->regions[ret].flags == PCI_REGION_IO) {
|
||||
priv->io.phys_start = hose->regions[ret].phys_start; /* IO base */
|
||||
priv->io.bus_start = hose->regions[ret].bus_start; /* IO_bus_addr */
|
||||
priv->io.size = hose->regions[ret].size; /* IO size */
|
||||
} else if (hose->regions[ret].flags == PCI_REGION_MEM) {
|
||||
priv->mem.phys_start = hose->regions[ret].phys_start; /* MEM base */
|
||||
priv->mem.bus_start = hose->regions[ret].bus_start; /* MEM_bus_addr */
|
||||
priv->mem.size = hose->regions[ret].size; /* MEM size */
|
||||
} else if (hose->regions[ret].flags == PCI_REGION_SYS_MEMORY) {
|
||||
priv->cfg_base = (void *)(priv->io.phys_start - priv->io.size);
|
||||
priv->cfg_size = priv->io.size;
|
||||
} else {
|
||||
dev_err(dev, "invalid flags type!\n");
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(dev, "Config space: [0x%p - 0x%p, size 0x%llx]\n",
|
||||
priv->cfg_base, priv->cfg_base + priv->cfg_size,
|
||||
priv->cfg_size);
|
||||
|
||||
dev_dbg(dev, "IO space: [0x%llx - 0x%llx, size 0x%lx]\n",
|
||||
priv->io.phys_start, priv->io.phys_start + priv->io.size,
|
||||
priv->io.size);
|
||||
|
||||
dev_dbg(dev, "IO bus: [0x%lx - 0x%lx, size 0x%lx]\n",
|
||||
priv->io.bus_start, priv->io.bus_start + priv->io.size,
|
||||
priv->io.size);
|
||||
|
||||
dev_dbg(dev, "MEM space: [0x%llx - 0x%llx, size 0x%lx]\n",
|
||||
priv->mem.phys_start, priv->mem.phys_start + priv->mem.size,
|
||||
priv->mem.size);
|
||||
|
||||
dev_dbg(dev, "MEM bus: [0x%lx - 0x%lx, size 0x%lx]\n",
|
||||
priv->mem.bus_start, priv->mem.bus_start + priv->mem.size,
|
||||
priv->mem.size);
|
||||
|
||||
return rk_pcie_prog_outbound_atu_unroll(priv,
|
||||
PCIE_ATU_REGION_INDEX0,
|
||||
PCIE_ATU_TYPE_MEM,
|
||||
priv->mem.phys_start,
|
||||
priv->mem.bus_start,
|
||||
priv->mem.size);
|
||||
}
|
||||
|
||||
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,rk3568-pcie" },
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(rockchip_dw_pcie) = {
|
||||
.name = "pcie_dw_rockchip",
|
||||
.id = UCLASS_PCI,
|
||||
.of_match = rockchip_pcie_ids,
|
||||
.ops = &rockchip_pcie_ops,
|
||||
.probe = rockchip_pcie_probe,
|
||||
.priv_auto = sizeof(struct rk_pcie),
|
||||
};
|
|
@ -18,6 +18,15 @@ config PHY_ROCKCHIP_PCIE
|
|||
help
|
||||
Enable this to support the Rockchip PCIe PHY.
|
||||
|
||||
config PHY_ROCKCHIP_SNPS_PCIE3
|
||||
bool "Rockchip Snps PCIe3 PHY Driver"
|
||||
depends on PHY && ARCH_ROCKCHIP
|
||||
help
|
||||
Support for Rockchip PCIe3 PHY with Synopsys IP block.
|
||||
It could support PCIe Gen3 single root complex, and could
|
||||
also be able splited into multiple combinations of lanes.
|
||||
|
||||
|
||||
config PHY_ROCKCHIP_TYPEC
|
||||
bool "Rockchip TYPEC PHY Driver"
|
||||
depends on ARCH_ROCKCHIP
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
|
||||
obj-$(CONFIG_PHY_ROCKCHIP_INNO_USB2) += phy-rockchip-inno-usb2.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
|
||||
|
|
157
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
Normal file
157
drivers/phy/rockchip/phy-rockchip-snps-pcie3.c
Normal file
|
@ -0,0 +1,157 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Rockchip PCIE3.0 phy driver
|
||||
*
|
||||
* Copyright (C) 2021 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <clk.h>
|
||||
#include <dm.h>
|
||||
#include <generic-phy.h>
|
||||
#include <regmap.h>
|
||||
#include <reset-uclass.h>
|
||||
#include <syscon.h>
|
||||
#include <asm/io.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/lists.h>
|
||||
|
||||
#define GRF_PCIE30PHY_CON1 0x4
|
||||
#define GRF_PCIE30PHY_CON6 0x18
|
||||
#define GRF_PCIE30PHY_CON9 0x24
|
||||
|
||||
/**
|
||||
* struct rockchip_p3phy_priv - RK DW PCIe PHY state
|
||||
*
|
||||
* @mmio: The base address of PHY internal registers
|
||||
* @phy_grf: The regmap for controlling pipe signal
|
||||
* @p30phy: The reset signal for PHY
|
||||
* @ref_clk_m: The reference clock of M for PHY
|
||||
* @ref_clk_n: The reference clock of N for PHY
|
||||
* @pclk: The clock for accessing PHY blocks
|
||||
*/
|
||||
struct rockchip_p3phy_priv {
|
||||
void __iomem *mmio;
|
||||
struct regmap *phy_grf;
|
||||
struct reset_ctl p30phy;
|
||||
struct clk ref_clk_m;
|
||||
struct clk ref_clk_n;
|
||||
struct clk pclk;
|
||||
};
|
||||
|
||||
static int rochchip_p3phy_init(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
|
||||
int ret;
|
||||
|
||||
ret = clk_enable(&priv->ref_clk_m);
|
||||
if (ret < 0 && ret != -ENOSYS)
|
||||
return ret;
|
||||
|
||||
ret = clk_enable(&priv->ref_clk_n);
|
||||
if (ret < 0 && ret != -ENOSYS)
|
||||
goto err_ref;
|
||||
|
||||
ret = clk_enable(&priv->pclk);
|
||||
if (ret < 0 && ret != -ENOSYS)
|
||||
goto err_pclk;
|
||||
|
||||
reset_assert(&priv->p30phy);
|
||||
udelay(1);
|
||||
|
||||
/* Deassert PCIe PMA output clamp mode */
|
||||
regmap_write(priv->phy_grf, GRF_PCIE30PHY_CON9,
|
||||
(0x1 << 15) | (0x1 << 31));
|
||||
|
||||
reset_deassert(&priv->p30phy);
|
||||
udelay(1);
|
||||
|
||||
return 0;
|
||||
err_pclk:
|
||||
clk_disable(&priv->ref_clk_n);
|
||||
err_ref:
|
||||
clk_disable(&priv->ref_clk_m);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rochchip_p3phy_exit(struct phy *phy)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = dev_get_priv(phy->dev);
|
||||
|
||||
clk_disable(&priv->ref_clk_m);
|
||||
clk_disable(&priv->ref_clk_n);
|
||||
clk_disable(&priv->pclk);
|
||||
reset_assert(&priv->p30phy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_p3phy_probe(struct udevice *dev)
|
||||
{
|
||||
struct rockchip_p3phy_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *syscon;
|
||||
int ret;
|
||||
|
||||
priv->mmio = (void __iomem *)dev_read_addr(dev);
|
||||
if ((fdt_addr_t)priv->mmio == FDT_ADDR_T_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
|
||||
"rockchip,phy-grf", &syscon);
|
||||
if (ret) {
|
||||
pr_err("unable to find syscon device for rockchip,phy-grf\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->phy_grf = syscon_get_regmap(syscon);
|
||||
if (IS_ERR(priv->phy_grf)) {
|
||||
dev_err(dev, "failed to find rockchip,phy_grf regmap\n");
|
||||
return PTR_ERR(priv->phy_grf);
|
||||
}
|
||||
|
||||
ret = reset_get_by_name(dev, "phy", &priv->p30phy);
|
||||
if (ret) {
|
||||
dev_err(dev, "no phy reset control specified\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "refclk_m", &priv->ref_clk_m);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to find ref clock M\n");
|
||||
return PTR_ERR(&priv->ref_clk_m);
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "refclk_n", &priv->ref_clk_n);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to find ref clock N\n");
|
||||
return PTR_ERR(&priv->ref_clk_n);
|
||||
}
|
||||
|
||||
ret = clk_get_by_name(dev, "pclk", &priv->pclk);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to find pclk\n");
|
||||
return PTR_ERR(&priv->pclk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct phy_ops rochchip_p3phy_ops = {
|
||||
.init = rochchip_p3phy_init,
|
||||
.exit = rochchip_p3phy_exit,
|
||||
};
|
||||
|
||||
static const struct udevice_id rockchip_p3phy_of_match[] = {
|
||||
{ .compatible = "rockchip,rk3568-pcie3-phy" },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(rockchip_pcie3phy) = {
|
||||
.name = "rockchip_pcie3phy",
|
||||
.id = UCLASS_PHY,
|
||||
.of_match = rockchip_p3phy_of_match,
|
||||
.ops = &rochchip_p3phy_ops,
|
||||
.probe = rockchip_p3phy_probe,
|
||||
.priv_auto = sizeof(struct rockchip_p3phy_priv),
|
||||
};
|
Loading…
Reference in a new issue