From f01b7cd3cc23b5a7af3b2bf9ae5f9cf3291912a7 Mon Sep 17 00:00:00 2001 From: Tianling Shen Date: Sun, 20 Jun 2021 13:04:24 +0800 Subject: [PATCH] sunxi: add support for OrangePi 3 Specifications: SoC Allwinner H6 @ 1.8 Ghz DRAM 1Gb/2Gb LPDDR3 Power DC 5V @ 2A, mircoUSB (OTG) Video HDMI (Type 2.0A - full) Audio 3.5mm headphone plug, HDMI, on-board microphone Network 10/100/1000Mbps Ethernet (Realtek RTL8211) Storage 8G eMMC Flash (optional), microSD USB 4 USB3.0 Host, 1 USB2.0 Host, 1 USB2.0 OTG Debug Serial UART Flashing instructions: Standard sunxi SD card installation procedure - copy image to SD card, insert into SD card slot on the device and boot. Notice: Wirless is not working for now. Signed-off-by: Tianling Shen --- .../boot/arm-trusted-firmware-sunxi/Makefile | 14 +- package/boot/aw-el2-barebone/Makefile | 41 + package/boot/uboot-sunxi/Makefile | 16 +- ...to-load-standalone-hypervisor-in-FIT.patch | 60 + ...nxi-h5-add-support-for-nanopi-r1s-h5.patch | 2 +- ...254-ARM-dts-sunxi-h6-Update-DT-files.patch | 1358 +++++++++++++++++ ...55-sunxi-Add-support-for-Orange-Pi-3.patch | 412 +++++ target/linux/sunxi/Makefile | 4 +- target/linux/sunxi/config-5.4 | 2 + target/linux/sunxi/cortexa53/config-5.4 | 29 + target/linux/sunxi/cortexa53/target.mk | 2 +- .../drivers/pci/controller/dwc/pcie-sunxi.c | 589 +++++++ target/linux/sunxi/image/cortexa53.mk | 8 + ...6-Add-thermal-sensor-and-thermal-zon.patch | 69 + ...-allwinner-h6-Add-clock-to-CPU-cores.patch | 57 + ...6-Add-thermal-trip-points-cooling-ma.patch | 83 + ...6-Add-CPU-Operating-Performance-Poin.patch | 153 ++ ...sigma-delta-modulation-for-audio-PLL.patch | 74 + ...lwinner-h6-Add-pin-configs-for-uart1.patch | 33 + ...s-allwinner-h6-add-USB3-device-nodes.patch | 59 + ...-sun50i-h6-Add-HDMI-sound-card-nodes.patch | 66 + ...lwinner-Add-ARM-Mali-GPU-node-for-H6.patch | 35 + ...nner-Add-GPU-operating-points-for-H6.patch | 96 ++ ...ner-orange-pi-3-Enable-UART1-Bluetoo.patch | 62 + ...ner-orange-pi-3-Enable-USB-3.0-host-.patch | 39 + ...llwinner-h6-orangepi-3-Add-eMMC-node.patch | 34 + ...6-Enable-CPU-opp-tables-for-Orange-P.patch | 52 + ...dwmac-sun8i-Fix-probe-error-handling.patch | 87 ++ ...un8i-Balance-syscon-deinitialization.patch | 205 +++ ...-dwmac-sun8i-Add-a-shutdown-callback.patch | 42 + ...devm_regulator_get-for-PHY-regulator.patch | 69 + ...me-PHY-regulator-variable-to-regulat.patch | 95 ++ ...support-for-enabling-a-regulator-for.patch | 86 ++ ...llwinner-orange-pi-3-Enable-ethernet.patch | 100 ++ ...h6-orangepi-3-add-status-LED-aliases.patch | 34 + .../800-add-wrapped-PCIe-for-sunxi.patch | 89 ++ ...llwinner-Enable-PCIe-for-Orange-Pi-3.patch | 44 + 37 files changed, 4294 insertions(+), 6 deletions(-) create mode 100644 package/boot/aw-el2-barebone/Makefile create mode 100644 package/boot/uboot-sunxi/patches/103-sunxi-allow-to-load-standalone-hypervisor-in-FIT.patch create mode 100644 package/boot/uboot-sunxi/patches/254-ARM-dts-sunxi-h6-Update-DT-files.patch create mode 100644 package/boot/uboot-sunxi/patches/255-sunxi-Add-support-for-Orange-Pi-3.patch create mode 100644 target/linux/sunxi/files/drivers/pci/controller/dwc/pcie-sunxi.c create mode 100644 target/linux/sunxi/patches-5.4/019-v5.6-arm64-dts-allwinner-h6-Add-thermal-sensor-and-thermal-zon.patch create mode 100644 target/linux/sunxi/patches-5.4/020-v5.8-arm64-dts-allwinner-h6-Add-clock-to-CPU-cores.patch create mode 100644 target/linux/sunxi/patches-5.4/021-v5.8-arm64-dts-allwinner-h6-Add-thermal-trip-points-cooling-ma.patch create mode 100644 target/linux/sunxi/patches-5.4/022-v5.8-arm64-dts-allwinner-h6-Add-CPU-Operating-Performance-Poin.patch create mode 100644 target/linux/sunxi/patches-5.4/320-v5.5-clk-sunxi-ng-h6-Use-sigma-delta-modulation-for-audio-PLL.patch create mode 100644 target/linux/sunxi/patches-5.4/444-0001-v5.5-arm64-dts-allwinner-h6-Add-pin-configs-for-uart1.patch create mode 100644 target/linux/sunxi/patches-5.4/444-0002-v5.5-arm64-dts-allwinner-h6-add-USB3-device-nodes.patch create mode 100644 target/linux/sunxi/patches-5.4/444-0003-arm64-dts-sun50i-h6-Add-HDMI-sound-card-nodes.patch create mode 100644 target/linux/sunxi/patches-5.4/444-0004-arm64-dts-allwinner-Add-ARM-Mali-GPU-node-for-H6.patch create mode 100644 target/linux/sunxi/patches-5.4/444-0005-arm64-dts-allwinner-Add-GPU-operating-points-for-H6.patch create mode 100644 target/linux/sunxi/patches-5.4/445-0003-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-UART1-Bluetoo.patch create mode 100644 target/linux/sunxi/patches-5.4/445-0004-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-USB-3.0-host-.patch create mode 100644 target/linux/sunxi/patches-5.4/445-0005-v5.7-arm64-dts-allwinner-h6-orangepi-3-Add-eMMC-node.patch create mode 100644 target/linux/sunxi/patches-5.4/445-0006-v5.8-arm64-dts-allwinner-h6-Enable-CPU-opp-tables-for-Orange-P.patch create mode 100644 target/linux/sunxi/patches-5.4/600-0001-v5.11-net-stmmac-dwmac-sun8i-Fix-probe-error-handling.patch create mode 100644 target/linux/sunxi/patches-5.4/600-0002-v5.11-net-stmmac-dwmac-sun8i-Balance-syscon-deinitialization.patch create mode 100644 target/linux/sunxi/patches-5.4/600-0003-v5.12-net-stmmac-dwmac-sun8i-Add-a-shutdown-callback.patch create mode 100644 target/linux/sunxi/patches-5.4/601-0001-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regulator.patch create mode 100644 target/linux/sunxi/patches-5.4/601-0002-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-regulat.patch create mode 100644 target/linux/sunxi/patches-5.4/601-0003-net-stmmac-sun8i-Add-support-for-enabling-a-regulator-for.patch create mode 100644 target/linux/sunxi/patches-5.4/601-0004-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch create mode 100644 target/linux/sunxi/patches-5.4/601-0005-arm64-dts-allwinner-h6-orangepi-3-add-status-LED-aliases.patch create mode 100644 target/linux/sunxi/patches-5.4/800-add-wrapped-PCIe-for-sunxi.patch create mode 100644 target/linux/sunxi/patches-5.4/801-arm64-dts-allwinner-Enable-PCIe-for-Orange-Pi-3.patch diff --git a/package/boot/arm-trusted-firmware-sunxi/Makefile b/package/boot/arm-trusted-firmware-sunxi/Makefile index 0abfbae750..58d07bb126 100644 --- a/package/boot/arm-trusted-firmware-sunxi/Makefile +++ b/package/boot/arm-trusted-firmware-sunxi/Makefile @@ -19,12 +19,13 @@ PKG_MIRROR_HASH:=b212d369a5286ebbf6a5616486efa05fa54d4294fd6e9ba2e54fdfae9eda918 PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=license.md +PKG_CONFIG_DEPENDS:=ARM_TRUSTED_FIRMWARE_SUNXI_WRAPPED_PCIE + PKG_MAINTAINER:=Hauke Mehrtens include $(INCLUDE_DIR)/trusted-firmware-a.mk include $(INCLUDE_DIR)/package.mk - define Package/arm-trusted-firmware-sunxi/Default SECTION:=boot CATEGORY:=Boot Loaders @@ -42,11 +43,22 @@ define Package/arm-trusted-firmware-sunxi-h6 VARIANT:=sun50i_h6 endef +define Package/arm-trusted-firmware-sunxi-h6/config +config ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE + depends on PACKAGE_arm-trusted-firmware-sunxi-h6 + bool "Enable sunxi wrapped PCIe driver support" +endef + export GCC_HONOUR_COPTS=s MAKE_VARS = \ CROSS_COMPILE="$(TARGET_CROSS)" +ifneq ($(CONFIG_ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE),) +MAKE_FLAGS += \ + PRELOADED_BL33_BASE=0x40010000 +endif + MAKE_FLAGS += \ PLAT=$(BUILD_VARIANT) \ bl31 diff --git a/package/boot/aw-el2-barebone/Makefile b/package/boot/aw-el2-barebone/Makefile new file mode 100644 index 0000000000..396afff5c3 --- /dev/null +++ b/package/boot/aw-el2-barebone/Makefile @@ -0,0 +1,41 @@ +# SPDX-License-Identifier: GPL-3.0-only +# +# Copyright (C) 2021 ImmortalWrt.org + +include $(TOPDIR)/rules.mk + +PKG_NAME:=aw-el2-barebone +PKG_RELEASE:=$(AUTORELEASE) + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=https://github.com/Icenowy/aw-el2-barebone +PKG_SOURCE_DATE:=2020-03-30 +PKG_SOURCE_VERSION:=b40bcb75cfa0acfaea84a5234fb225240b32b749 +PKG_MIRROR_HASH:=aeb70287e0b35736f806ed20bad84d6a6cae977f70cad63ce8139cdfcc181108 + +PKG_LICENSE:=GPL-2.0 +PKG_LICENSE_FILES:=LICENSE + +PKG_MAINTAINER:=Tianling Shen + +include $(INCLUDE_DIR)/package.mk + +define Package/aw-el2-barebone + SECTION:=boot + CATEGORY:=Boot Loaders + TITLE:=Allwinner SoCs' 64-bit EL2 barebone + DEPENDS:=@TARGET_sunxi_cortexa53 +endef + +MAKE_VARS = \ + CROSS_COMPILE="$(TARGET_CROSS)" + +define Build/InstallDev + $(INSTALL_DIR) $(STAGING_DIR_IMAGE) + $(CP) $(PKG_BUILD_DIR)/el2-bb.bin $(STAGING_DIR_IMAGE)/hyp.bin +endef + +define Package/aw-el2-barebone/install +endef + +$(eval $(call BuildPackage,aw-el2-barebone)) diff --git a/package/boot/uboot-sunxi/Makefile b/package/boot/uboot-sunxi/Makefile index 5c27407d15..23c2c14e9c 100644 --- a/package/boot/uboot-sunxi/Makefile +++ b/package/boot/uboot-sunxi/Makefile @@ -237,6 +237,18 @@ define U-Boot/orangepi_2 BUILD_DEVICES:=xunlong_orangepi-2 endef +define U-Boot/orangepi_3 + BUILD_SUBTARGET:=cortexa53 + NAME:=Orange Pi 3 (H6) + DEPENDS:=+PACKAGE_u-boot-orangepi_3:arm-trusted-firmware-sunxi-h6 \ + +@PACKAGE_u-boot-orangepi_3:ARM_TRUSTED_FIRMAWRE_SUNXI_WRAPPED_PCIE \ + +PACKAGE_u-boot-orangepi_3:aw-el2-barebone + BUILD_DEVICES:=xunlong_orangepi-3 + UENV:=h6 + ATF:=h6 + HYP:=1 +endef + define U-Boot/pangolin BUILD_SUBTARGET:=cortexa7 NAME:=Theobroma A31-yQ7 devboard @@ -375,6 +387,7 @@ UBOOT_TARGETS := \ orangepi_pc_plus \ orangepi_plus \ orangepi_2 \ + orangepi_3 \ orangepi_pc2 \ pangolin \ pine64_plus \ @@ -385,7 +398,8 @@ UBOOT_TARGETS := \ UBOOT_CONFIGURE_VARS += USE_PRIVATE_LIBGCC=yes UBOOT_MAKE_FLAGS += \ - BL31=$(STAGING_DIR_IMAGE)/bl31_sun50i_$(ATF).bin + BL31=$(STAGING_DIR_IMAGE)/bl31_sun50i_$(ATF).bin \ + $(if $(HYP),HYP=$(STAGING_DIR_IMAGE)/hyp.bin) define Build/InstallDev $(INSTALL_DIR) $(STAGING_DIR_IMAGE) diff --git a/package/boot/uboot-sunxi/patches/103-sunxi-allow-to-load-standalone-hypervisor-in-FIT.patch b/package/boot/uboot-sunxi/patches/103-sunxi-allow-to-load-standalone-hypervisor-in-FIT.patch new file mode 100644 index 0000000000..86f7b9e473 --- /dev/null +++ b/package/boot/uboot-sunxi/patches/103-sunxi-allow-to-load-standalone-hypervisor-in-FIT.patch @@ -0,0 +1,60 @@ +From 5c6e0b11d5ba2f0570a3c148977d75884bf2b889 Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Sun, 29 Mar 2020 10:55:22 +0800 +Subject: [PATCH] sunxi: allow to load standalone hypervisor in FIT + +Signed-off-by: Icenowy Zheng +--- + board/sunxi/mksunxi_fit_atf.sh | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +--- a/board/sunxi/mksunxi_fit_atf.sh ++++ b/board/sunxi/mksunxi_fit_atf.sh +@@ -6,6 +6,7 @@ + # usage: $0 [ [&2 +@@ -13,6 +14,10 @@ if [ ! -f $BL31 ]; then + BL31=/dev/null + fi + ++if [ ! -f $HYP ]; then ++ HYP= ++fi ++ + if grep -q "^CONFIG_MACH_SUN50I_H6=y" .config; then + BL31_ADDR=0x104000 + else +@@ -46,6 +51,19 @@ cat << __HEADER_EOF + }; + __HEADER_EOF + ++if [ "x$HYP" != "x" ]; then ++cat << __HYP_EOF ++ hyp { ++ description = "Standalone Hypervisor"; ++ data = /incbin/("$HYP"); ++ type = "firmware"; ++ arch = "arm64"; ++ compression = "none"; ++ load = <0x40010000>; ++ }; ++__HYP_EOF ++fi ++ + cnt=1 + for dtname in $* + do +@@ -74,7 +92,7 @@ do + config_$cnt { + description = "$(basename $dtname .dtb)"; + firmware = "uboot"; +- loadables = "atf"; ++ loadables = "atf"$([ "x$HYP" != "x" ] && echo ", \"hyp\""); + fdt = "fdt_$cnt"; + }; + __CONF_SECTION_EOF diff --git a/package/boot/uboot-sunxi/patches/253-sunxi-h5-add-support-for-nanopi-r1s-h5.patch b/package/boot/uboot-sunxi/patches/253-sunxi-h5-add-support-for-nanopi-r1s-h5.patch index 27bf5e66cd..000ee23994 100644 --- a/package/boot/uboot-sunxi/patches/253-sunxi-h5-add-support-for-nanopi-r1s-h5.patch +++ b/package/boot/uboot-sunxi/patches/253-sunxi-h5-add-support-for-nanopi-r1s-h5.patch @@ -1,6 +1,6 @@ --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile -@@ -555,6 +555,7 @@ dtb-$(CONFIG_MACH_SUN8I_V3S) += \ +@@ -555,6 +555,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \ sun50i-h5-libretech-all-h5-cc.dtb \ sun50i-h5-nanopi-neo2.dtb \ sun50i-h5-nanopi-neo-plus2.dtb \ diff --git a/package/boot/uboot-sunxi/patches/254-ARM-dts-sunxi-h6-Update-DT-files.patch b/package/boot/uboot-sunxi/patches/254-ARM-dts-sunxi-h6-Update-DT-files.patch new file mode 100644 index 0000000000..b50c3a01dd --- /dev/null +++ b/package/boot/uboot-sunxi/patches/254-ARM-dts-sunxi-h6-Update-DT-files.patch @@ -0,0 +1,1358 @@ +From 750cabc87bfdfa81019dfaf9ef0400db2368f9d1 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 6 Jan 2021 18:02:56 +0100 +Subject: [PATCH] ARM: dts: sunxi: h6: Update DT files + +Updated H6 DT files are based on Linux 5.11-rc1 release. + +Signed-off-by: Jernej Skrabec +Reviewed-by: Andre Przywara +Signed-off-by: Andre Przywara +--- + arch/arm/dts/sun50i-h6-beelink-gs1.dts | 70 +++- + arch/arm/dts/sun50i-h6-cpu-opp.dtsi | 117 ++++++ + arch/arm/dts/sun50i-h6-orangepi-lite2.dts | 71 +++- + arch/arm/dts/sun50i-h6-orangepi-one-plus.dts | 41 +- + arch/arm/dts/sun50i-h6-orangepi.dtsi | 72 +++- + arch/arm/dts/sun50i-h6-pine-h64.dts | 102 +++-- + arch/arm/dts/sun50i-h6.dtsi | 394 +++++++++++++++++-- + 7 files changed, 794 insertions(+), 73 deletions(-) + create mode 100644 arch/arm/dts/sun50i-h6-cpu-opp.dtsi + +--- a/arch/arm/dts/sun50i-h6-beelink-gs1.dts ++++ b/arch/arm/dts/sun50i-h6-beelink-gs1.dts +@@ -1,11 +1,10 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (C) 2019 Clément Péron +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2019 Clément Péron + + /dts-v1/; + + #include "sun50i-h6.dtsi" ++#include "sun50i-h6-cpu-opp.dtsi" + + #include + +@@ -25,6 +24,7 @@ + connector { + compatible = "hdmi-connector"; + type = "a"; ++ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + + port { + hdmi_con_in: endpoint { +@@ -33,6 +33,13 @@ + }; + }; + ++ ext_osc32k: ext_osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "ext_osc32k"; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -51,12 +58,38 @@ + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; ++ ++ sound-spdif { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "sun50i-h6-spdif"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdca>; + }; + + &de { + status = "okay"; + }; + ++&dwc3 { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -64,12 +97,17 @@ + &emac { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_aldo2>; + status = "okay"; + }; + ++&gpu { ++ mali-supply = <®_dcdcc>; ++ status = "okay"; ++}; ++ + &hdmi { + status = "okay"; + }; +@@ -201,13 +239,16 @@ + reg_dcdca: dcdca { + regulator-always-on; + regulator-min-microvolt = <810000>; +- regulator-max-microvolt = <1080000>; ++ regulator-max-microvolt = <1160000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-cpu"; + }; + + reg_dcdcc: dcdcc { ++ regulator-enable-ramp-delay = <32000>; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-gpu"; + }; + +@@ -232,6 +273,11 @@ + }; + }; + ++&r_ir { ++ linux,rc-map-name = "rc-beelink-gs1"; ++ status = "okay"; ++}; ++ + &r_pio { + /* + * PL0 and PL1 are used for PMIC I2C +@@ -243,6 +289,14 @@ + vcc-pm-supply = <®_aldo1>; + }; + ++&rtc { ++ clocks = <&ext_osc32k>; ++}; ++ ++&spdif { ++ status = "okay"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; +@@ -258,3 +312,7 @@ + usb0_vbus-supply = <®_vcc5v>; + status = "okay"; + }; ++ ++&usb3phy { ++ status = "okay"; ++}; +--- /dev/null ++++ b/arch/arm/dts/sun50i-h6-cpu-opp.dtsi +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2020 Ondrej Jirman ++// Copyright (C) 2020 Clément Péron ++ ++/ { ++ cpu_opp_table: cpu-opp-table { ++ compatible = "allwinner,sun50i-h6-operating-points"; ++ nvmem-cells = <&cpu_speed_grade>; ++ opp-shared; ++ ++ opp@480000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <480000000>; ++ ++ opp-microvolt-speed0 = <880000 880000 1200000>; ++ opp-microvolt-speed1 = <820000 820000 1200000>; ++ opp-microvolt-speed2 = <820000 820000 1200000>; ++ }; ++ ++ opp@720000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <720000000>; ++ ++ opp-microvolt-speed0 = <880000 880000 1200000>; ++ opp-microvolt-speed1 = <820000 820000 1200000>; ++ opp-microvolt-speed2 = <820000 820000 1200000>; ++ }; ++ ++ opp@816000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <816000000>; ++ ++ opp-microvolt-speed0 = <880000 880000 1200000>; ++ opp-microvolt-speed1 = <820000 820000 1200000>; ++ opp-microvolt-speed2 = <820000 820000 1200000>; ++ }; ++ ++ opp@888000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <888000000>; ++ ++ opp-microvolt-speed0 = <880000 880000 1200000>; ++ opp-microvolt-speed1 = <820000 820000 1200000>; ++ opp-microvolt-speed2 = <820000 820000 1200000>; ++ }; ++ ++ opp@1080000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1080000000>; ++ ++ opp-microvolt-speed0 = <940000 940000 1200000>; ++ opp-microvolt-speed1 = <880000 880000 1200000>; ++ opp-microvolt-speed2 = <880000 880000 1200000>; ++ }; ++ ++ opp@1320000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1320000000>; ++ ++ opp-microvolt-speed0 = <1000000 1000000 1200000>; ++ opp-microvolt-speed1 = <940000 940000 1200000>; ++ opp-microvolt-speed2 = <940000 940000 1200000>; ++ }; ++ ++ opp@1488000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1488000000>; ++ ++ opp-microvolt-speed0 = <1060000 1060000 1200000>; ++ opp-microvolt-speed1 = <1000000 1000000 1200000>; ++ opp-microvolt-speed2 = <1000000 1000000 1200000>; ++ }; ++ ++ opp@1608000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1608000000>; ++ ++ opp-microvolt-speed0 = <1090000 1090000 1200000>; ++ opp-microvolt-speed1 = <1030000 1030000 1200000>; ++ opp-microvolt-speed2 = <1030000 1030000 1200000>; ++ }; ++ ++ opp@1704000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1704000000>; ++ ++ opp-microvolt-speed0 = <1120000 1120000 1200000>; ++ opp-microvolt-speed1 = <1060000 1060000 1200000>; ++ opp-microvolt-speed2 = <1060000 1060000 1200000>; ++ }; ++ ++ opp@1800000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1800000000>; ++ ++ opp-microvolt-speed0 = <1160000 1160000 1200000>; ++ opp-microvolt-speed1 = <1100000 1100000 1200000>; ++ opp-microvolt-speed2 = <1100000 1100000 1200000>; ++ }; ++ }; ++}; ++ ++&cpu0 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu1 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu2 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu3 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; +--- a/arch/arm/dts/sun50i-h6-orangepi-lite2.dts ++++ b/arch/arm/dts/sun50i-h6-orangepi-lite2.dts +@@ -1,11 +1,74 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (C) 2018 Jagan Teki +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2018 Jagan Teki + + #include "sun50i-h6-orangepi.dtsi" + + / { + model = "OrangePi Lite2"; + compatible = "xunlong,orangepi-lite2", "allwinner,sun50i-h6"; ++ ++ aliases { ++ serial1 = &uart1; /* BT-UART */ ++ }; ++ ++ wifi_pwrseq: wifi_pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rtc 1>; ++ clock-names = "ext_clock"; ++ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ ++ post-power-on-delay-ms = <200>; ++ }; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_cldo2>; ++ vqmmc-supply = <®_bldo3>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++ ++ brcm: sdio-wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ interrupt-parent = <&r_pio>; ++ interrupts = <1 0 IRQ_TYPE_LEVEL_LOW>; /* PM0 */ ++ interrupt-names = "host-wake"; ++ }; ++}; ++ ++®_cldo2 { ++ /* ++ * This regulator is connected with CLDO3. ++ * Before the kernel can support synchronized ++ * enable of coupled regulators, keep them ++ * both always on as a ugly hack. ++ */ ++ regulator-always-on; ++}; ++ ++®_cldo3 { ++ /* ++ * This regulator is connected with CLDO2. ++ * See the comments for CLDO2. ++ */ ++ regulator-always-on; ++}; ++ ++/* There's the BT part of the AP6255 connected to that UART */ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4345c5"; ++ clocks = <&rtc 1>; ++ clock-names = "lpo"; ++ device-wakeup-gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; /* PM2 */ ++ host-wakeup-gpios = <&r_pio 1 1 GPIO_ACTIVE_HIGH>; /* PM1 */ ++ shutdown-gpios = <&r_pio 1 4 GPIO_ACTIVE_HIGH>; /* PM4 */ ++ max-speed = <1500000>; ++ }; + }; +--- a/arch/arm/dts/sun50i-h6-orangepi-one-plus.dts ++++ b/arch/arm/dts/sun50i-h6-orangepi-one-plus.dts +@@ -1,12 +1,43 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (C) 2018 Amarula Solutions +- * Author: Jagan Teki +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2018 Amarula Solutions ++// Author: Jagan Teki + + #include "sun50i-h6-orangepi.dtsi" + + / { + model = "OrangePi One Plus"; + compatible = "xunlong,orangepi-one-plus", "allwinner,sun50i-h6"; ++ ++ aliases { ++ ethernet0 = &emac; ++ }; ++ ++ reg_gmac_3v3: gmac-3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-gmac-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <100000>; ++ enable-active-high; ++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ ++ vin-supply = <®_aldo2>; ++ }; ++}; ++ ++&emac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rgmii_pins>; ++ phy-mode = "rgmii-id"; ++ phy-handle = <&ext_rgmii_phy>; ++ phy-supply = <®_gmac_3v3>; ++ allwinner,rx-delay-ps = <200>; ++ allwinner,tx-delay-ps = <200>; ++ status = "okay"; ++}; ++ ++&mdio { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ }; + }; +--- a/arch/arm/dts/sun50i-h6-orangepi.dtsi ++++ b/arch/arm/dts/sun50i-h6-orangepi.dtsi +@@ -1,8 +1,6 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (C) 2018 Amarula Solutions +- * Author: Jagan Teki +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2018 Amarula Solutions ++// Author: Jagan Teki + + /dts-v1/; + +@@ -22,6 +20,25 @@ + stdout-path = "serial0:115200n8"; + }; + ++ connector { ++ compatible = "hdmi-connector"; ++ type = "a"; ++ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++ ext_osc32k: ext_osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "ext_osc32k"; ++ }; ++ + leds { + compatible = "gpio-leds"; + +@@ -47,6 +64,10 @@ + }; + }; + ++&de { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -55,6 +76,21 @@ + status = "okay"; + }; + ++&gpu { ++ mali-supply = <®_dcdcc>; ++ status = "okay"; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; +@@ -70,6 +106,12 @@ + status = "okay"; + }; + ++&pio { ++ vcc-pc-supply = <®_bldo2>; ++ vcc-pd-supply = <®_cldo1>; ++ vcc-pg-supply = <®_aldo1>; ++}; ++ + &r_i2c { + status = "okay"; + +@@ -163,6 +205,7 @@ + }; + + reg_dcdcc: dcdcc { ++ regulator-enable-ramp-delay = <32000>; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; + regulator-name = "vdd-gpu"; +@@ -189,6 +232,18 @@ + }; + }; + ++&r_ir { ++ status = "okay"; ++}; ++ ++&r_pio { ++ vcc-pm-supply = <®_bldo3>; ++}; ++ ++&rtc { ++ clocks = <&ext_osc32k>; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; +@@ -196,7 +251,12 @@ + }; + + &usb2otg { +- dr_mode = "otg"; ++ /* ++ * OrangePi Lite 2 and One Plus, where this DT is used, don't ++ * have a controllable VBUS even though they do have an ID pin. ++ * Using it as anything but a USB host is unsafe. ++ */ ++ dr_mode = "host"; + status = "okay"; + }; + +--- a/arch/arm/dts/sun50i-h6-pine-h64.dts ++++ b/arch/arm/dts/sun50i-h6-pine-h64.dts +@@ -1,30 +1,38 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (c) 2017 Icenowy Zheng +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (c) 2017 Icenowy Zheng + + /dts-v1/; + + #include "sun50i-h6.dtsi" ++#include "sun50i-h6-cpu-opp.dtsi" + + #include + + / { +- model = "Pine H64"; ++ model = "Pine H64 model A"; + compatible = "pine64,pine-h64", "allwinner,sun50i-h6"; + + aliases { + ethernet0 = &emac; + serial0 = &uart0; ++ spi0 = &spi0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + +- connector { ++ ext_osc32k: ext_osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "ext_osc32k"; ++ }; ++ ++ hdmi_connector: connector { + compatible = "hdmi-connector"; + type = "a"; ++ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ + + port { + hdmi_con_in: endpoint { +@@ -52,6 +60,16 @@ + }; + }; + ++ reg_gmac_3v3: gmac-3v3 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-gmac-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <100000>; ++ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ + reg_usb_vbus: vbus { + compatible = "regulator-fixed"; + regulator-name = "usb-vbus"; +@@ -63,25 +81,35 @@ + }; + }; + ++&cpu0 { ++ cpu-supply = <®_dcdca>; ++}; ++ ++&de { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ehci3 { ++ status = "okay"; ++}; ++ + &emac { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; +- phy-mode = "rgmii"; ++ phy-mode = "rgmii-id"; + phy-handle = <&ext_rgmii_phy>; +- phy-supply = <®_aldo2>; ++ phy-supply = <®_gmac_3v3>; + allwinner,rx-delay-ps = <200>; + allwinner,tx-delay-ps = <200>; + status = "okay"; + }; + +-&mdio { +- ext_rgmii_phy: ethernet-phy@1 { +- compatible = "ethernet-phy-ieee802.3-c22"; +- reg = <1>; +- }; +-}; +- +-&de { ++&gpu { ++ mali-supply = <®_dcdcc>; + status = "okay"; + }; + +@@ -95,12 +123,11 @@ + }; + }; + +-&ehci0 { +- status = "okay"; +-}; +- +-&ehci3 { +- status = "okay"; ++&mdio { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ }; + }; + + &mmc0 { +@@ -216,13 +243,16 @@ + reg_dcdca: dcdca { + regulator-always-on; + regulator-min-microvolt = <810000>; +- regulator-max-microvolt = <1080000>; ++ regulator-max-microvolt = <1160000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-cpu"; + }; + + reg_dcdcc: dcdcc { ++ regulator-enable-ramp-delay = <32000>; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-gpu"; + }; + +@@ -255,10 +285,36 @@ + }; + }; + ++&r_ir { ++ status = "okay"; ++}; ++ + &r_pio { + vcc-pm-supply = <®_aldo1>; + }; + ++&rtc { ++ clocks = <&ext_osc32k>; ++}; ++ ++/* ++ * The CS pin is shared with the MMC2 CMD pin, so we cannot have the SPI ++ * flash and eMMC at the same time, as one of them would fail probing. ++ * Disable SPI0 in here, to prefer the more useful eMMC. U-Boot can ++ * fix this up in no eMMC is connected. ++ */ ++&spi0 { ++ pinctrl-0 = <&spi0_pins>, <&spi0_cs_pin>; ++ pinctrl-names = "default"; ++ status = "disabled"; ++ ++ flash@0 { ++ compatible = "winbond,w25q128", "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <4000000>; ++ }; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_ph_pins>; +--- a/arch/arm/dts/sun50i-h6.dtsi ++++ b/arch/arm/dts/sun50i-h6.dtsi +@@ -1,7 +1,5 @@ +-// SPDX-License-Identifier: (GPL-2.0+ or MIT) +-/* +- * Copyright (C) 2017 Icenowy Zheng +- */ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2017 Icenowy Zheng + + #include + #include +@@ -11,6 +9,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -26,6 +25,9 @@ + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu1: cpu@1 { +@@ -33,6 +35,9 @@ + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu2: cpu@2 { +@@ -40,6 +45,9 @@ + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu3: cpu@3 { +@@ -47,6 +55,9 @@ + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + }; + +@@ -56,14 +67,6 @@ + status = "disabled"; + }; + +- iosc: internal-osc-clk { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <16000000>; +- clock-accuracy = <300000000>; +- clock-output-names = "iosc"; +- }; +- + osc24M: osc24M_clk { + #clock-cells = <0>; + compatible = "fixed-clock"; +@@ -71,11 +74,13 @@ + clock-output-names = "osc24M"; + }; + +- osc32k: osc32k_clk { +- #clock-cells = <0>; +- compatible = "fixed-clock"; +- clock-frequency = <32768>; +- clock-output-names = "osc32k"; ++ pmu { ++ compatible = "arm,cortex-a53-pmu"; ++ interrupts = , ++ , ++ , ++ ; ++ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>; + }; + + psci { +@@ -85,6 +90,7 @@ + + timer { + compatible = "arm,armv8-timer"; ++ arm,no-tick-in-suspend; + interrupts = , + ; ++ iommus = <&iommu 0>; + + ports { + #address-cells = <1>; +@@ -155,6 +162,30 @@ + resets = <&ccu RST_BUS_VE>; + interrupts = ; + allwinner,sram = <&ve_sram 1>; ++ iommus = <&iommu 3>; ++ }; ++ ++ gpu: gpu@1800000 { ++ compatible = "allwinner,sun50i-h6-mali", ++ "arm,mali-t720"; ++ reg = <0x01800000 0x4000>; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; ++ clocks = <&ccu CLK_GPU>, <&ccu CLK_BUS_GPU>; ++ clock-names = "core", "bus"; ++ resets = <&ccu RST_BUS_GPU>; ++ status = "disabled"; ++ }; ++ ++ crypto: crypto@1904000 { ++ compatible = "allwinner,sun50i-h6-crypto"; ++ reg = <0x01904000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_CE>, <&ccu CLK_CE>, <&ccu CLK_MBUS_CE>; ++ clock-names = "bus", "mod", "ram"; ++ resets = <&ccu RST_BUS_CE>; + }; + + syscon: syscon@3000000 { +@@ -197,7 +228,7 @@ + ccu: clock@3001000 { + compatible = "allwinner,sun50i-h6-ccu"; + reg = <0x03001000 0x1000>; +- clocks = <&osc24M>, <&osc32k>, <&iosc>; ++ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>; + clock-names = "hosc", "losc", "iosc"; + #clock-cells = <1>; + #reset-cells = <1>; +@@ -215,9 +246,29 @@ + #dma-cells = <1>; + }; + +- sid: sid@3006000 { ++ msgbox: mailbox@3003000 { ++ compatible = "allwinner,sun50i-h6-msgbox", ++ "allwinner,sun6i-a31-msgbox"; ++ reg = <0x03003000 0x1000>; ++ clocks = <&ccu CLK_BUS_MSGBOX>; ++ resets = <&ccu RST_BUS_MSGBOX>; ++ interrupts = ; ++ #mbox-cells = <1>; ++ }; ++ ++ sid: efuse@3006000 { + compatible = "allwinner,sun50i-h6-sid"; + reg = <0x03006000 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ ths_calibration: thermal-sensor-calibration@14 { ++ reg = <0x14 0x8>; ++ }; ++ ++ cpu_speed_grade: cpu-speed-grade@1c { ++ reg = <0x1c 0x4>; ++ }; + }; + + watchdog: watchdog@30090a0 { +@@ -225,10 +276,21 @@ + "allwinner,sun6i-a31-wdt"; + reg = <0x030090a0 0x20>; + interrupts = ; ++ clocks = <&osc24M>; + /* Broken on some H6 boards */ + status = "disabled"; + }; + ++ pwm: pwm@300a000 { ++ compatible = "allwinner,sun50i-h6-pwm"; ++ reg = <0x0300a000 0x400>; ++ clocks = <&osc24M>, <&ccu CLK_BUS_PWM>; ++ clock-names = "mod", "bus"; ++ resets = <&ccu RST_BUS_PWM>; ++ #pwm-cells = <3>; ++ status = "disabled"; ++ }; ++ + pio: pinctrl@300b000 { + compatible = "allwinner,sun50i-h6-pinctrl"; + reg = <0x0300b000 0x400>; +@@ -236,7 +298,7 @@ + , + , + ; +- clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>; ++ clocks = <&ccu CLK_APB1>, <&osc24M>, <&rtc 0>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; +@@ -256,6 +318,21 @@ + function = "hdmi"; + }; + ++ i2c0_pins: i2c0-pins { ++ pins = "PD25", "PD26"; ++ function = "i2c0"; ++ }; ++ ++ i2c1_pins: i2c1-pins { ++ pins = "PH5", "PH6"; ++ function = "i2c1"; ++ }; ++ ++ i2c2_pins: i2c2-pins { ++ pins = "PD23", "PD24"; ++ function = "i2c2"; ++ }; ++ + mmc0_pins: mmc0-pins { + pins = "PF0", "PF1", "PF2", "PF3", + "PF4", "PF5"; +@@ -264,10 +341,7 @@ + bias-pull-up; + }; + +- /* +- * /omit-if-no-ref/ isn't supported by U-boot +- * keep this comment to avoid bad sync with Linux +- */ ++ /omit-if-no-ref/ + mmc1_pins: mmc1-pins { + pins = "PG0", "PG1", "PG2", "PG3", + "PG4", "PG5"; +@@ -285,10 +359,50 @@ + bias-pull-up; + }; + ++ /omit-if-no-ref/ ++ spi0_pins: spi0-pins { ++ pins = "PC0", "PC2", "PC3"; ++ function = "spi0"; ++ }; ++ ++ /* pin shared with MMC2-CMD (eMMC) */ ++ /omit-if-no-ref/ ++ spi0_cs_pin: spi0-cs-pin { ++ pins = "PC5"; ++ function = "spi0"; ++ }; ++ ++ /omit-if-no-ref/ ++ spi1_pins: spi1-pins { ++ pins = "PH4", "PH5", "PH6"; ++ function = "spi1"; ++ }; ++ ++ /omit-if-no-ref/ ++ spi1_cs_pin: spi1-cs-pin { ++ pins = "PH3"; ++ function = "spi1"; ++ }; ++ ++ spdif_tx_pin: spdif-tx-pin { ++ pins = "PH7"; ++ function = "spdif"; ++ }; ++ + uart0_ph_pins: uart0-ph-pins { + pins = "PH0", "PH1"; + function = "uart0"; + }; ++ ++ uart1_pins: uart1-pins { ++ pins = "PG6", "PG7"; ++ function = "uart1"; ++ }; ++ ++ uart1_rts_cts_pins: uart1-rts-cts-pins { ++ pins = "PG8", "PG9"; ++ function = "uart1"; ++ }; + }; + + gic: interrupt-controller@3021000 { +@@ -302,6 +416,15 @@ + #interrupt-cells = <3>; + }; + ++ iommu: iommu@30f0000 { ++ compatible = "allwinner,sun50i-h6-iommu"; ++ reg = <0x030f0000 0x10000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_IOMMU>; ++ resets = <&ccu RST_BUS_IOMMU>; ++ #iommu-cells = <1>; ++ }; ++ + mmc0: mmc@4020000 { + compatible = "allwinner,sun50i-h6-mmc", + "allwinner,sun50i-a64-mmc"; +@@ -394,6 +517,78 @@ + status = "disabled"; + }; + ++ i2c0: i2c@5002000 { ++ compatible = "allwinner,sun50i-h6-i2c", ++ "allwinner,sun6i-a31-i2c"; ++ reg = <0x05002000 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2C0>; ++ resets = <&ccu RST_BUS_I2C0>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ i2c1: i2c@5002400 { ++ compatible = "allwinner,sun50i-h6-i2c", ++ "allwinner,sun6i-a31-i2c"; ++ reg = <0x05002400 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2C1>; ++ resets = <&ccu RST_BUS_I2C1>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c1_pins>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ i2c2: i2c@5002800 { ++ compatible = "allwinner,sun50i-h6-i2c", ++ "allwinner,sun6i-a31-i2c"; ++ reg = <0x05002800 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2C2>; ++ resets = <&ccu RST_BUS_I2C2>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi0: spi@5010000 { ++ compatible = "allwinner,sun50i-h6-spi", ++ "allwinner,sun8i-h3-spi"; ++ reg = <0x05010000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>; ++ clock-names = "ahb", "mod"; ++ dmas = <&dma 22>, <&dma 22>; ++ dma-names = "rx", "tx"; ++ resets = <&ccu RST_BUS_SPI0>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ spi1: spi@5011000 { ++ compatible = "allwinner,sun50i-h6-spi", ++ "allwinner,sun8i-h3-spi"; ++ reg = <0x05011000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>; ++ clock-names = "ahb", "mod"; ++ dmas = <&dma 23>, <&dma 23>; ++ dma-names = "rx", "tx"; ++ resets = <&ccu RST_BUS_SPI1>; ++ status = "disabled"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ + emac: ethernet@5020000 { + compatible = "allwinner,sun50i-h6-emac", + "allwinner,sun50i-a64-emac"; +@@ -414,6 +609,34 @@ + }; + }; + ++ i2s1: i2s@5091000 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-h6-i2s"; ++ reg = <0x05091000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>; ++ clock-names = "apb", "mod"; ++ dmas = <&dma 4>, <&dma 4>; ++ resets = <&ccu RST_BUS_I2S1>; ++ dma-names = "rx", "tx"; ++ status = "disabled"; ++ }; ++ ++ spdif: spdif@5093000 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-h6-spdif"; ++ reg = <0x05093000 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>; ++ clock-names = "apb", "spdif"; ++ resets = <&ccu RST_BUS_SPDIF>; ++ dmas = <&dma 2>; ++ dma-names = "tx"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdif_tx_pin>; ++ status = "disabled"; ++ }; ++ + usb2otg: usb@5100000 { + compatible = "allwinner,sun50i-h6-musb", + "allwinner,sun8i-a33-musb"; +@@ -470,6 +693,38 @@ + status = "disabled"; + }; + ++ dwc3: usb@5200000 { ++ compatible = "snps,dwc3"; ++ reg = <0x05200000 0x10000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_XHCI>, ++ <&ccu CLK_BUS_XHCI>, ++ <&rtc 0>; ++ clock-names = "ref", "bus_early", "suspend"; ++ resets = <&ccu RST_BUS_XHCI>; ++ /* ++ * The datasheet of the chip doesn't declare the ++ * peripheral function, and there's no boards known ++ * to have a USB Type-B port routed to the port. ++ * In addition, no one has tested the peripheral ++ * function yet. ++ * So set the dr_mode to "host" in the DTSI file. ++ */ ++ dr_mode = "host"; ++ phys = <&usb3phy>; ++ phy-names = "usb3-phy"; ++ status = "disabled"; ++ }; ++ ++ usb3phy: phy@5210000 { ++ compatible = "allwinner,sun50i-h6-usb3-phy"; ++ reg = <0x5210000 0x10000>; ++ clocks = <&ccu CLK_USB_PHY1>; ++ resets = <&ccu RST_USB_PHY1>; ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ + ehci3: usb@5311000 { + compatible = "allwinner,sun50i-h6-ehci", "generic-ehci"; + reg = <0x05311000 0x100>; +@@ -480,6 +735,7 @@ + resets = <&ccu RST_BUS_OHCI3>, + <&ccu RST_BUS_EHCI3>; + phys = <&usb2phy 3>; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -491,6 +747,7 @@ + <&ccu CLK_USB_OHCI3>; + resets = <&ccu RST_BUS_OHCI3>; + phys = <&usb2phy 3>; ++ phy-names = "usb"; + status = "disabled"; + }; + +@@ -507,7 +764,7 @@ + resets = <&ccu RST_BUS_HDMI_SUB>, <&ccu RST_BUS_HDCP>; + reset-names = "ctrl", "hdcp"; + phys = <&hdmi_phy>; +- phy-names = "hdmi-phy"; ++ phy-names = "phy"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pins>; + status = "disabled"; +@@ -549,7 +806,6 @@ + "tcon-tv0"; + clock-output-names = "tcon-top-tv0"; + resets = <&ccu RST_BUS_TCON_TOP>; +- reset-names = "rst"; + #clock-cells = <1>; + + ports { +@@ -636,10 +892,19 @@ + }; + }; + ++ rtc: rtc@7000000 { ++ compatible = "allwinner,sun50i-h6-rtc"; ++ reg = <0x07000000 0x400>; ++ interrupts = , ++ ; ++ clock-output-names = "osc32k", "osc32k-out", "iosc"; ++ #clock-cells = <1>; ++ }; ++ + r_ccu: clock@7010000 { + compatible = "allwinner,sun50i-h6-r-ccu"; + reg = <0x07010000 0x400>; +- clocks = <&osc24M>, <&osc32k>, <&iosc>, ++ clocks = <&osc24M>, <&rtc 0>, <&rtc 2>, + <&ccu CLK_PLL_PERIPH0>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; + #clock-cells = <1>; +@@ -651,6 +916,7 @@ + "allwinner,sun6i-a31-wdt"; + reg = <0x07020400 0x20>; + interrupts = ; ++ clocks = <&osc24M>; + }; + + r_intc: interrupt-controller@7021000 { +@@ -667,7 +933,7 @@ + reg = <0x07022000 0x400>; + interrupts = , + ; +- clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&osc32k>; ++ clocks = <&r_ccu CLK_R_APB1>, <&osc24M>, <&rtc 0>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; +@@ -678,10 +944,30 @@ + pins = "PL0", "PL1"; + function = "s_i2c"; + }; ++ ++ r_ir_rx_pin: r-ir-rx-pin { ++ pins = "PL9"; ++ function = "s_cir_rx"; ++ }; ++ }; ++ ++ r_ir: ir@7040000 { ++ compatible = "allwinner,sun50i-h6-ir", ++ "allwinner,sun6i-a31-ir"; ++ reg = <0x07040000 0x400>; ++ interrupts = ; ++ clocks = <&r_ccu CLK_R_APB1_IR>, ++ <&r_ccu CLK_IR>; ++ clock-names = "apb", "ir"; ++ resets = <&r_ccu RST_R_APB1_IR>; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&r_ir_rx_pin>; ++ status = "disabled"; + }; + + r_i2c: i2c@7081400 { +- compatible = "allwinner,sun6i-a31-i2c"; ++ compatible = "allwinner,sun50i-h6-i2c", ++ "allwinner,sun6i-a31-i2c"; + reg = <0x07081400 0x400>; + interrupts = ; + clocks = <&r_ccu CLK_R_APB2_I2C>; +@@ -692,5 +978,55 @@ + #address-cells = <1>; + #size-cells = <0>; + }; ++ ++ ths: thermal-sensor@5070400 { ++ compatible = "allwinner,sun50i-h6-ths"; ++ reg = <0x05070400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>; ++ clock-names = "bus"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration>; ++ nvmem-cell-names = "calibration"; ++ #thermal-sensor-cells = <1>; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 0>; ++ ++ trips { ++ cpu_alert: cpu-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu-crit { ++ temperature = <100000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ gpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 1>; ++ }; + }; + }; diff --git a/package/boot/uboot-sunxi/patches/255-sunxi-Add-support-for-Orange-Pi-3.patch b/package/boot/uboot-sunxi/patches/255-sunxi-Add-support-for-Orange-Pi-3.patch new file mode 100644 index 0000000000..33d9a4f4fc --- /dev/null +++ b/package/boot/uboot-sunxi/patches/255-sunxi-Add-support-for-Orange-Pi-3.patch @@ -0,0 +1,412 @@ +From c81877a919d2ae214650b4f10b862dd62f0284a7 Mon Sep 17 00:00:00 2001 +From: Andre Heider +Date: Fri, 1 Oct 2021 19:29:00 +0100 +Subject: [PATCH] sunxi: Add support for Orange Pi 3 + +dts file is taken from Linux 5.11-rc1 tag. + +The Bluetooth controller of this device ships with a default address, +use the new CONFIG_FIXUP_BDADDR option to fix it up. + +Signed-off-by: Andre Heider +Acked-by: Maxime Ripard +[Updated OrangePi 3 DT, rebase and config update] +Signed-off-by: Jernej Skrabec +Reviewed-by: Andre Przywara +Signed-off-by: Andre Przywara +--- + arch/arm/dts/Makefile | 1 + + arch/arm/dts/sun50i-h6-orangepi-3.dts | 345 ++++++++++++++++++++++++++ + board/sunxi/MAINTAINERS | 5 + + configs/orangepi_3_defconfig | 12 + + 4 files changed, 363 insertions(+) + create mode 100644 arch/arm/dts/sun50i-h6-orangepi-3.dts + create mode 100644 configs/orangepi_3_defconfig + +--- a/arch/arm/dts/Makefile ++++ b/arch/arm/dts/Makefile +@@ -562,6 +562,7 @@ dtb-$(CONFIG_MACH_SUN50I_H5) += \ + sun50i-h5-orangepi-zero-plus2.dtb + dtb-$(CONFIG_MACH_SUN50I_H6) += \ + sun50i-h6-beelink-gs1.dtb \ ++ sun50i-h6-orangepi-3.dtb \ + sun50i-h6-orangepi-lite2.dtb \ + sun50i-h6-orangepi-one-plus.dtb \ + sun50i-h6-pine-h64.dtb +--- /dev/null ++++ b/arch/arm/dts/sun50i-h6-orangepi-3.dts +@@ -0,0 +1,345 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2019 Ondřej Jirman ++ ++/dts-v1/; ++ ++#include "sun50i-h6.dtsi" ++#include "sun50i-h6-cpu-opp.dtsi" ++ ++#include ++ ++/ { ++ model = "OrangePi 3"; ++ compatible = "xunlong,orangepi-3", "allwinner,sun50i-h6"; ++ ++ aliases { ++ serial0 = &uart0; ++ serial1 = &uart1; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ connector { ++ compatible = "hdmi-connector"; ++ ddc-en-gpios = <&pio 7 2 GPIO_ACTIVE_HIGH>; /* PH2 */ ++ type = "a"; ++ ++ port { ++ hdmi_con_in: endpoint { ++ remote-endpoint = <&hdmi_out_con>; ++ }; ++ }; ++ }; ++ ++ ext_osc32k: ext_osc32k_clk { ++ #clock-cells = <0>; ++ compatible = "fixed-clock"; ++ clock-frequency = <32768>; ++ clock-output-names = "ext_osc32k"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ power { ++ label = "orangepi:red:power"; ++ gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */ ++ default-state = "on"; ++ }; ++ ++ status { ++ label = "orangepi:green:status"; ++ gpios = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ ++ }; ++ }; ++ ++ reg_vcc5v: vcc5v { ++ /* board wide 5V supply directly from the DC jack */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ reg_vcc33_wifi: vcc33-wifi { ++ /* Always on 3.3V regulator for WiFi and BT */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc33-wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-always-on; ++ vin-supply = <®_vcc5v>; ++ }; ++ ++ reg_vcc_wifi_io: vcc-wifi-io { ++ /* Always on 1.8V/300mA regulator for WiFi and BT IO */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-wifi-io"; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-always-on; ++ vin-supply = <®_vcc33_wifi>; ++ }; ++ ++ wifi_pwrseq: wifi-pwrseq { ++ compatible = "mmc-pwrseq-simple"; ++ clocks = <&rtc 1>; ++ clock-names = "ext_clock"; ++ reset-gpios = <&r_pio 1 3 GPIO_ACTIVE_LOW>; /* PM3 */ ++ post-power-on-delay-ms = <200>; ++ }; ++}; ++ ++&cpu0 { ++ cpu-supply = <®_dcdca>; ++}; ++ ++&de { ++ status = "okay"; ++}; ++ ++&dwc3 { ++ status = "okay"; ++}; ++ ++&ehci0 { ++ status = "okay"; ++}; ++ ++&ehci3 { ++ status = "okay"; ++}; ++ ++&gpu { ++ mali-supply = <®_dcdcc>; ++ status = "okay"; ++}; ++ ++&hdmi { ++ status = "okay"; ++}; ++ ++&hdmi_out { ++ hdmi_out_con: endpoint { ++ remote-endpoint = <&hdmi_con_in>; ++ }; ++}; ++ ++&mmc0 { ++ vmmc-supply = <®_cldo1>; ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&mmc1 { ++ vmmc-supply = <®_vcc33_wifi>; ++ vqmmc-supply = <®_vcc_wifi_io>; ++ mmc-pwrseq = <&wifi_pwrseq>; ++ bus-width = <4>; ++ non-removable; ++ status = "okay"; ++ ++ brcm: sdio-wifi@1 { ++ reg = <1>; ++ compatible = "brcm,bcm4329-fmac"; ++ interrupt-parent = <&r_pio>; ++ interrupts = <1 0 IRQ_TYPE_LEVEL_LOW>; /* PM0 */ ++ interrupt-names = "host-wake"; ++ }; ++}; ++ ++&mmc2 { ++ vmmc-supply = <®_cldo1>; ++ vqmmc-supply = <®_bldo2>; ++ cap-mmc-hw-reset; ++ non-removable; ++ bus-width = <8>; ++ status = "okay"; ++}; ++ ++&ohci0 { ++ status = "okay"; ++}; ++ ++&ohci3 { ++ status = "okay"; ++}; ++ ++&pio { ++ vcc-pc-supply = <®_bldo2>; ++ vcc-pd-supply = <®_cldo1>; ++ vcc-pg-supply = <®_vcc_wifi_io>; ++}; ++ ++&r_i2c { ++ status = "okay"; ++ ++ axp805: pmic@36 { ++ compatible = "x-powers,axp805", "x-powers,axp806"; ++ reg = <0x36>; ++ interrupt-parent = <&r_intc>; ++ interrupts = <0 IRQ_TYPE_LEVEL_LOW>; ++ interrupt-controller; ++ #interrupt-cells = <1>; ++ x-powers,self-working-mode; ++ vina-supply = <®_vcc5v>; ++ vinb-supply = <®_vcc5v>; ++ vinc-supply = <®_vcc5v>; ++ vind-supply = <®_vcc5v>; ++ vine-supply = <®_vcc5v>; ++ aldoin-supply = <®_vcc5v>; ++ bldoin-supply = <®_vcc5v>; ++ cldoin-supply = <®_vcc5v>; ++ ++ regulators { ++ reg_aldo1: aldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc-pl-led-ir"; ++ }; ++ ++ reg_aldo2: aldo2 { ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-audio-tv-ephy-mac"; ++ }; ++ ++ /* ALDO3 is shorted to CLDO1 */ ++ reg_aldo3: aldo3 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-1"; ++ }; ++ ++ reg_bldo1: bldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc18-dram-bias-pll"; ++ }; ++ ++ reg_bldo2: bldo2 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc-efuse-pcie-hdmi-pc"; ++ }; ++ ++ bldo3 { ++ /* unused */ ++ }; ++ ++ bldo4 { ++ /* unused */ ++ }; ++ ++ reg_cldo1: cldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc33-io-pd-emmc-sd-usb-uart-2"; ++ }; ++ ++ cldo2 { ++ /* unused */ ++ }; ++ ++ cldo3 { ++ /* unused */ ++ }; ++ ++ reg_dcdca: dcdca { ++ regulator-always-on; ++ regulator-min-microvolt = <800000>; ++ regulator-max-microvolt = <1160000>; ++ regulator-ramp-delay = <2500>; ++ regulator-name = "vdd-cpu"; ++ }; ++ ++ reg_dcdcc: dcdcc { ++ regulator-enable-ramp-delay = <32000>; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <1080000>; ++ regulator-ramp-delay = <2500>; ++ regulator-name = "vdd-gpu"; ++ }; ++ ++ reg_dcdcd: dcdcd { ++ regulator-always-on; ++ regulator-min-microvolt = <960000>; ++ regulator-max-microvolt = <960000>; ++ regulator-name = "vdd-sys"; ++ }; ++ ++ reg_dcdce: dcdce { ++ regulator-always-on; ++ regulator-min-microvolt = <1200000>; ++ regulator-max-microvolt = <1200000>; ++ regulator-name = "vcc-dram"; ++ }; ++ ++ sw { ++ /* unused */ ++ }; ++ }; ++ }; ++}; ++ ++&r_ir { ++ status = "okay"; ++}; ++ ++&rtc { ++ clocks = <&ext_osc32k>; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_ph_pins>; ++ status = "okay"; ++}; ++ ++/* There's the BT part of the AP6256 connected to that UART */ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4345c5"; ++ clocks = <&rtc 1>; ++ clock-names = "lpo"; ++ device-wakeup-gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; /* PM2 */ ++ host-wakeup-gpios = <&r_pio 1 1 GPIO_ACTIVE_HIGH>; /* PM1 */ ++ shutdown-gpios = <&r_pio 1 4 GPIO_ACTIVE_HIGH>; /* PM4 */ ++ max-speed = <1500000>; ++ }; ++}; ++ ++&usb2otg { ++ /* ++ * This board doesn't have a controllable VBUS even though it ++ * does have an ID pin. Using it as anything but a USB host is ++ * unsafe. ++ */ ++ dr_mode = "host"; ++ status = "okay"; ++}; ++ ++&usb2phy { ++ usb0_id_det-gpios = <&pio 2 15 GPIO_ACTIVE_HIGH>; /* PC15 */ ++ usb0_vbus-supply = <®_vcc5v>; ++ usb3_vbus-supply = <®_vcc5v>; ++ status = "okay"; ++}; ++ ++&usb3phy { ++ status = "okay"; ++}; +--- a/board/sunxi/MAINTAINERS ++++ b/board/sunxi/MAINTAINERS +@@ -385,6 +385,11 @@ M: Icenowy Zheng + S: Maintained + F: configs/teres_i_defconfig + ++ORANGEPI 3 BOARD ++M: Andre Heider ++S: Maintained ++F: configs/orangepi_3_defconfig ++ + ORANGEPI LITE2 BOARD + M: Jagan Teki + S: Maintained +--- /dev/null ++++ b/configs/orangepi_3_defconfig +@@ -0,0 +1,12 @@ ++CONFIG_ARM=y ++CONFIG_ARCH_SUNXI=y ++CONFIG_SPL=y ++CONFIG_MACH_SUN50I_H6=y ++CONFIG_SUNXI_DRAM_H6_LPDDR3=y ++CONFIG_MMC0_CD_PIN="PF6" ++CONFIG_MMC_SUNXI_SLOT_EXTRA=2 ++CONFIG_BLUETOOTH_DT_DEVICE_FIXUP="brcm,bcm4345c5" ++CONFIG_DEFAULT_DEVICE_TREE="sun50i-h6-orangepi-3" ++# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set ++CONFIG_USB_EHCI_HCD=y ++CONFIG_USB_OHCI_HCD=y diff --git a/target/linux/sunxi/Makefile b/target/linux/sunxi/Makefile index 6b92599928..4350e4bd19 100644 --- a/target/linux/sunxi/Makefile +++ b/target/linux/sunxi/Makefile @@ -6,8 +6,8 @@ include $(TOPDIR)/rules.mk ARCH:=arm BOARD:=sunxi -BOARDNAME:=Allwinner A1x/A20/A3x/H3/H5/R40 -FEATURES:=fpu usb ext4 display rtc squashfs +BOARDNAME:=Allwinner A1x/A20/A3x/H3/H5/H6/R40 +FEATURES:=fpu usb ext4 display pci pcie rtc squashfs SUBTARGETS:=cortexa8 cortexa7 cortexa53 KERNEL_PATCHVER:=5.4 diff --git a/target/linux/sunxi/config-5.4 b/target/linux/sunxi/config-5.4 index 55436323cc..c1b939d4ef 100644 --- a/target/linux/sunxi/config-5.4 +++ b/target/linux/sunxi/config-5.4 @@ -115,6 +115,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_STAT=y CONFIG_CPU_HAS_ASID=y @@ -552,6 +553,7 @@ CONFIG_TOUCHSCREEN_PROPERTIES=y CONFIG_TOUCHSCREEN_SUN4I=y CONFIG_TREE_RCU=y CONFIG_TREE_SRCU=y +# CONFIG_UCLAMP_TASK is not set CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h" CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_USB=y diff --git a/target/linux/sunxi/cortexa53/config-5.4 b/target/linux/sunxi/cortexa53/config-5.4 index 1d8fd49d43..97c4baf64e 100644 --- a/target/linux/sunxi/cortexa53/config-5.4 +++ b/target/linux/sunxi/cortexa53/config-5.4 @@ -52,6 +52,7 @@ CONFIG_ARCH_USE_QUEUED_RWLOCKS=y CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y CONFIG_ARCH_WANT_FRAME_POINTERS=y CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y +CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM=y CONFIG_ARM64=y CONFIG_ARM64_4K_PAGES=y CONFIG_ARM64_CONT_SHIFT=4 @@ -67,7 +68,10 @@ CONFIG_ARM64_VA_BITS_39=y CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y CONFIG_ARM_AMBA=y CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND=y +CONFIG_ARM_GIC_V2M=y +CONFIG_ARM_GIC_V3_ITS_PCI=y CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y +CONFIG_BLK_MQ_PCI=y CONFIG_CAVIUM_TX2_ERRATUM_219=y CONFIG_DMA_DIRECT_REMAP=y CONFIG_DRM_RCAR_WRITEBACK=y @@ -99,6 +103,10 @@ CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_HAVE_PATA_PLATFORM=y CONFIG_HOLES_IN_ZONE=y +CONFIG_HOTPLUG_PCI=y +# CONFIG_HOTPLUG_PCI_CPCI is not set +# CONFIG_HOTPLUG_PCI_PCIE is not set +# CONFIG_HOTPLUG_PCI_SHPC is not set CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INLINE_READ_LOCK=y CONFIG_INLINE_READ_LOCK_BH=y @@ -129,6 +137,24 @@ CONFIG_MUSB_PIO_ONLY=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NO_IOPORT_MAP=y CONFIG_NOP_USB_XCEIV=y +CONFIG_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEASPM=y +# CONFIG_PCIEASPM_DEBUG is not set +CONFIG_PCIEASPM_DEFAULT=y +# CONFIG_PCIEASPM_PERFORMANCE is not set +# CONFIG_PCIEASPM_POWERSAVE is not set +# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_DW=y +CONFIG_PCIE_DW_HOST=y +CONFIG_PCIE_PME=y +CONFIG_PCIE_SUNXI=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_IRQ_DOMAIN=y +CONFIG_PCI_STUB=y CONFIG_PINCTRL_SUN50I_A64=y CONFIG_PINCTRL_SUN50I_A64_R=y CONFIG_PINCTRL_SUN50I_H5=y @@ -136,7 +162,9 @@ CONFIG_PINCTRL_SUN50I_H6=y CONFIG_PINCTRL_SUN50I_H6_R=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y +CONFIG_RAS=y CONFIG_RODATA_FULL_DEFAULT_ENABLED=y +# CONFIG_SENSORS_DRIVETEMP is not set # CONFIG_SND_SUN50I_CODEC_ANALOG is not set CONFIG_SOUND_OSS_CORE_PRECLAIM=y CONFIG_SPARSEMEM=y @@ -157,5 +185,6 @@ CONFIG_USB_MUSB_DUAL_ROLE=y CONFIG_USB_MUSB_HDRC=y # CONFIG_USB_MUSB_HOST is not set CONFIG_USB_MUSB_SUNXI=y +CONFIG_USB_PHY=y CONFIG_VMAP_STACK=y CONFIG_ZONE_DMA32=y diff --git a/target/linux/sunxi/cortexa53/target.mk b/target/linux/sunxi/cortexa53/target.mk index 9e3a4064be..2cfec0b5e5 100644 --- a/target/linux/sunxi/cortexa53/target.mk +++ b/target/linux/sunxi/cortexa53/target.mk @@ -5,6 +5,6 @@ include $(TOPDIR)/rules.mk ARCH:=aarch64 -BOARDNAME:=Allwinner A64/H5 +BOARDNAME:=Allwinner A64/H5/H6 CPU_TYPE:=cortex-a53 KERNELNAME:=Image dtbs diff --git a/target/linux/sunxi/files/drivers/pci/controller/dwc/pcie-sunxi.c b/target/linux/sunxi/files/drivers/pci/controller/dwc/pcie-sunxi.c new file mode 100644 index 0000000000..c3375df2d9 --- /dev/null +++ b/target/linux/sunxi/files/drivers/pci/controller/dwc/pcie-sunxi.c @@ -0,0 +1,589 @@ +// SPDX-License-Identifier : GPL-2.0 +/* + * PCIe RC driver for Allwinner DW PCIe controllers + * + * Copyright (C) 2018 Icenowy Zheng + * + * Copyright (C) 2016 Allwinner Co., Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcie-designware.h" + +#define PCIE_RC_LCR 0x7c +#define USER_DEFINED_REGISTER_LIST 0x1000 +#define PCIE_LTSSM_ENABLE 0x1000 +#define PCIE_INT_PENDING 0x1018 +#define PCIE_ADDR_PAGE_CFG 0x1020 +#define PCIE_AWMISC_INF0_CTRL 0x1030 +#define PCIE_ARMISC_INF0_CTRL 0x1034 +#define PCIE_LINK_STATUS 0x143C +#define PCIE_PHY_CFG 0x1800 +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 +#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf +#define SYS_CLK 0 +#define PAD_CLK 1 +#define RDLH_LINK_UP BIT(1) +#define SMLH_LINK_UP BIT(0) +#define PCIE_LINK_TRAINING BIT(0) +#define PCIE_LINK_UP_MASK (0x3 << 16) +#define LINK_WAIT_MAX_RETRIES 10 +#define LINK_WAIT_USLEEP_MIN 90000 +#define LINK_WAIT_USLEEP_MAX 100000 + +#define PERST_DELAY_US 1000 + +#define PCIE_BAR_NUM 6 +#define PCIE_MEM_FLAGS 0x4 +#define PCIE_IO_FLAGS 0x1 +#define PCIE_BAR_REG 0x4 +#define HIGH16_MASK GENMASK(31, 16) +#define LOW16_MASK GENMASK(15, 0) + +#define to_sunxi_pcie(x) dev_get_drvdata((x)->dev) + +struct sunxi_pcie { + struct dw_pcie *pci; + int link_irq; + int msi_irq; + int speed_gen; + int io_voltage; + struct clk *pcie_ref; + struct clk *pcie_axi; + struct clk *pcie_aux; + struct clk *pcie_bus; + struct reset_control *pcie_power_rst; + struct reset_control *pcie_bus_rst; + struct regulator *reg_vcc; + struct regulator *reg_vdd; + struct regulator *reg_slot; + struct gpio_desc *perst_gpio; +}; + +static void sunxi_pcie_perst_gpio_assert(struct sunxi_pcie *pcie) +{ + gpiod_set_value_cansleep(pcie->perst_gpio, 1); + usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); +} + +static void sunxi_pcie_perst_gpio_deassert(struct sunxi_pcie *pcie) +{ + gpiod_set_value_cansleep(pcie->perst_gpio, 0); + usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500); +} + +static void sunxi_pcie_clk_select(struct dw_pcie *pci, int status) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_PHY_CFG); + val &= ~(0x1 << 31); + val |= status << 31; + dw_pcie_writel_dbi(pci, PCIE_PHY_CFG, val); +} + +static void sunxi_pcie_ltssm_enable(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_LTSSM_ENABLE); + val |= PCIE_LINK_TRAINING; + dw_pcie_writel_dbi(pci, PCIE_LTSSM_ENABLE, val); +} + +static void sunxi_pcie_irqpending(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_INT_PENDING); + val &= ~(0x3<<16); + dw_pcie_writel_dbi(pci, PCIE_INT_PENDING, val); +} + +static void sunxi_pcie_phy_cfg(struct dw_pcie *pci, int enable) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_PHY_CFG); + if (enable) + val |= 0x1<<0; + else + val &= ~(0x1<<0); + dw_pcie_writel_dbi(pci, PCIE_PHY_CFG, val); +} + +static void sunxi_pcie_irqmask(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_INT_PENDING); + val |= 0x3<<16; + dw_pcie_writel_dbi(pci, PCIE_INT_PENDING, val); +} + +static void sunxi_pcie_ltssm_disable(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_LTSSM_ENABLE); + val &= ~PCIE_LINK_TRAINING; + dw_pcie_writel_dbi(pci, PCIE_LTSSM_ENABLE, val); +} + +static int sunxi_pcie_wait_for_speed_change(struct dw_pcie *pci) +{ + u32 tmp; + unsigned int retries; + + for (retries = 0; retries < 200; retries++) { + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + /* Test if the speed change finished. */ + if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) + return 0; + usleep_range(100, 1000); + } + + dev_err(pci->dev, "Speed change timeout\n"); + return -EINVAL; +} + +static int sunxi_pcie_link_up_status(struct dw_pcie *pci) +{ + u32 rc; + int ret; + + rc = dw_pcie_readl_dbi(pci, PCIE_LINK_STATUS); + if ((rc & RDLH_LINK_UP) && (rc & SMLH_LINK_UP)) + ret = 1; + else + ret = 0; + + return ret; +} + +static int sunxi_pcie_speed_change(struct dw_pcie *pci, int gen) +{ + int val; + int ret; + + if (gen == 2) { + val = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); + val &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; + val |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; + dw_pcie_writel_dbi(pci, PCIE_RC_LCR, val); + + /* + * Start Directed Speed Change so the best possible + * speed both link partners support can be negotiated. + */ + val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + val |= PORT_LOGIC_SPEED_CHANGE; + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); + ret = sunxi_pcie_wait_for_speed_change(pci); + + if (!ret) + dev_info(pci->dev, "PCI-e speed of Gen%d\n", gen); + else + dev_info(pci->dev, "PCI-e speed of Gen1\n"); + } else { + dev_info(pci->dev, "PCI-e speed of Gen1\n"); + } + + return 0; +} + +static int sunxi_pcie_establish_link(struct dw_pcie *pci) +{ + struct sunxi_pcie *pcie = to_sunxi_pcie(pci); + + if (dw_pcie_link_up(pci)) { + dev_err(pcie->pci->dev, "link is already up\n"); + return 0; + } + + sunxi_pcie_ltssm_enable(pci); + dw_pcie_wait_for_link(pci); + + return 0; +} + +static int sunxi_pcie_reset_deassert(struct sunxi_pcie *pcie) +{ + int ret; + + ret = reset_control_deassert(pcie->pcie_bus_rst); + if (ret) { + dev_err(pcie->pci->dev, "unable to deassert bus reset\n"); + return ret; + } + usleep_range(1000, 2000); + + if (pcie->io_voltage < 2000000) + sunxi_pcie_phy_cfg(pcie->pci, 1); + else + sunxi_pcie_phy_cfg(pcie->pci, 0); + + usleep_range(1000, 2000); + ret = reset_control_deassert(pcie->pcie_power_rst); + if (ret) { + dev_err(pcie->pci->dev, "unable to deassert power reset\n"); + goto bus_reset_assert; + } + + return 0; + +bus_reset_assert: + reset_control_assert(pcie->pcie_bus_rst); + return ret; +} + +static int sunxi_pcie_clk_setup(struct sunxi_pcie *pcie) +{ + int ret; + + ret = clk_prepare_enable(pcie->pcie_ref); + if (ret) { + dev_err(pcie->pci->dev, "unable to enable pcie_ref clock\n"); + return ret; + } + + ret = clk_prepare_enable(pcie->pcie_axi); + if (ret) { + dev_err(pcie->pci->dev, "unable to enable pcie_axi clock\n"); + goto disable_ref; + } + + ret = clk_prepare_enable(pcie->pcie_aux); + if (ret) { + dev_err(pcie->pci->dev, "unable to enable pcie_aux clock\n"); + goto disable_axi; + } + + ret = clk_prepare_enable(pcie->pcie_bus); + if (ret) { + dev_err(pcie->pci->dev, "unable to enable pcie_bus clock\n"); + goto disable_aux; + } + + return 0; + +disable_aux: + clk_disable_unprepare(pcie->pcie_aux); +disable_axi: + clk_disable_unprepare(pcie->pcie_axi); +disable_ref: + clk_disable_unprepare(pcie->pcie_ref); + + return ret; +} + +static int sunxi_pcie_regulator_enable(struct sunxi_pcie *pcie) +{ + int ret; + + ret = regulator_enable(pcie->reg_vcc); + if (ret) + return ret; + + pcie->io_voltage = regulator_get_voltage(pcie->reg_vcc); + if (pcie->io_voltage < 0) { + ret = pcie->io_voltage; + goto disable_vcc; + } + + ret = regulator_enable(pcie->reg_vdd); + if (ret) + goto disable_vcc; + + ret = regulator_enable(pcie->reg_slot); + if (ret) + goto disable_vdd; + + return 0; + +disable_vdd: + regulator_disable(pcie->reg_vdd); +disable_vcc: + regulator_disable(pcie->reg_vcc); + + return ret; +} + +static irqreturn_t sunxi_pcie_msi_irq_handler(int irq, void *arg) +{ + struct sunxi_pcie *pcie = (struct sunxi_pcie *)arg; + + return dw_handle_msi_irq(&pcie->pci->pp); +} + +static irqreturn_t sunxi_pcie_linkup_handler(int irq, void *arg) +{ + struct sunxi_pcie *pcie = (struct sunxi_pcie *)arg; + + sunxi_pcie_irqpending(pcie->pci); + + return IRQ_HANDLED; +} + +static int sunxi_pcie_get_clk_rst(struct platform_device *pdev, + struct sunxi_pcie *pcie) +{ + struct device *dev = &pdev->dev; + + pcie->pcie_ref = devm_clk_get(dev, "ref"); + if (IS_ERR(pcie->pcie_ref)) { + dev_err(dev, "failed to get pcie ref clk\n"); + return PTR_ERR(pcie->pcie_ref); + } + + pcie->pcie_axi = devm_clk_get(dev, "axi"); + if (IS_ERR(pcie->pcie_axi)) { + dev_err(dev, "failed to get pcie axi clk\n"); + return PTR_ERR(pcie->pcie_axi); + } + + pcie->pcie_aux = devm_clk_get(dev, "aux"); + if (IS_ERR(pcie->pcie_aux)) { + dev_err(dev, "failed to get pcie aux clk\n"); + return PTR_ERR(pcie->pcie_aux); + } + + pcie->pcie_bus = devm_clk_get(dev, "bus"); + if (IS_ERR(pcie->pcie_bus)) { + dev_err(dev, "failed to get pcie bus clk\n"); + return PTR_ERR(pcie->pcie_bus); + } + + pcie->pcie_bus_rst = devm_reset_control_get(dev, "bus"); + if (IS_ERR(pcie->pcie_bus_rst)) { + dev_err(dev, "failed to get pcie bus reset\n"); + return PTR_ERR(pcie->pcie_bus_rst); + } + + pcie->pcie_power_rst = devm_reset_control_get(dev, "power"); + if (IS_ERR(pcie->pcie_power_rst)) { + dev_err(dev, "failed to get pcie power reset\n"); + return PTR_ERR(pcie->pcie_power_rst); + } + + return 0; +} + +static int sunxi_pcie_get_regulator(struct platform_device *pdev, + struct sunxi_pcie *pcie) +{ + struct device *dev = &pdev->dev; + + pcie->reg_vcc = devm_regulator_get(dev, "vcc"); + if (IS_ERR(pcie->reg_vcc)) { + dev_err(dev, "failed to get pcie vcc supply\n"); + return PTR_ERR(pcie->reg_vcc); + } + + pcie->reg_vdd = devm_regulator_get(dev, "vdd"); + if (IS_ERR(pcie->reg_vdd)) { + dev_err(dev, "failed to get pcie vdd supply\n"); + return PTR_ERR(pcie->reg_vdd); + } + + pcie->reg_slot = devm_regulator_get(dev, "slot"); + if (IS_ERR(pcie->reg_slot)) { + dev_err(dev, "failed to get pcie slot supply\n"); + return PTR_ERR(pcie->reg_slot); + } + + return 0; +} + +static int sunxi_pcie_host_init(struct pcie_port *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct sunxi_pcie *pcie = to_sunxi_pcie(pci); + + sunxi_pcie_ltssm_disable(pci); + sunxi_pcie_clk_select(pci, PAD_CLK); + + dw_pcie_setup_rc(pp); + + dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, pp->mem_base, + pp->mem_bus_addr, pp->mem_size); + if (pci->num_viewport > 2) + dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2, + PCIE_ATU_TYPE_IO, pp->io_base, + pp->io_bus_addr, pp->io_size); + + sunxi_pcie_establish_link(pci); + if (IS_ENABLED(CONFIG_PCI_MSI)) + dw_pcie_msi_init(pp); + + sunxi_pcie_speed_change(pci, pcie->speed_gen); + + return 0; +} + +static const struct dw_pcie_host_ops sunxi_pcie_host_ops = { + .host_init = sunxi_pcie_host_init, +}; + +static const struct dw_pcie_ops sunxi_pcie_ops = { + .link_up = sunxi_pcie_link_up_status, +}; + +static int sunxi_add_pcie_port(struct sunxi_pcie *pcie, + struct platform_device *pdev) +{ + int ret; + struct pcie_port *pp = &pcie->pci->pp; + + if (IS_ENABLED(CONFIG_PCI_MSI)) { + pp->msi_irq = platform_get_irq_byname(pdev, "msi"); + if (pp->msi_irq < 0) + return pp->msi_irq; + + ret = devm_request_irq(&pdev->dev, pp->msi_irq, + sunxi_pcie_msi_irq_handler, + IRQF_SHARED, "sunxi-pcie-msi", pcie); + if (ret) { + dev_err(&pdev->dev, "failed to request MSI IRQ\n"); + return ret; + } + } + + pp->root_bus_nr = -1; + pp->ops = &sunxi_pcie_host_ops; + + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(&pdev->dev, "failed to initialize host\n"); + return ret; + } + + return 0; +} + +static int sunxi_pcie_probe(struct platform_device *pdev) +{ + struct sunxi_pcie *sunxi_pcie; + struct dw_pcie *pci; + struct resource *dbi_res; + int ret; + + sunxi_pcie = devm_kzalloc(&pdev->dev, sizeof(*sunxi_pcie), + GFP_KERNEL); + if (!sunxi_pcie) + return -ENOMEM; + + pci = devm_kzalloc(&pdev->dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + sunxi_pcie->pci = pci; + + pci->dev = &pdev->dev; + pci->ops = &sunxi_pcie_ops; + + platform_set_drvdata(pdev, sunxi_pcie); + + dbi_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); + if (!dbi_res) + return -ENODEV; + + pci->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_res); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + + ret = sunxi_pcie_get_clk_rst(pdev, sunxi_pcie); + if (ret) + return ret; + + ret = sunxi_pcie_get_regulator(pdev, sunxi_pcie); + if (ret) + return ret; + + sunxi_pcie->perst_gpio = devm_gpiod_get_optional(&pdev->dev, "perst", GPIOD_OUT_LOW); + if (IS_ERR(sunxi_pcie->perst_gpio)) + return PTR_ERR(sunxi_pcie->perst_gpio); + + ret = of_property_read_u32(pdev->dev.of_node, "max-link-speed", &sunxi_pcie->speed_gen); + if (ret) { + dev_info(&pdev->dev, "No speed generation info specified, fallback to Gen1\n"); + sunxi_pcie->speed_gen = 0x1; + } + + ret = sunxi_pcie_regulator_enable(sunxi_pcie); + if (ret) + return ret; + + ret = sunxi_pcie_clk_setup(sunxi_pcie); + if (ret) + return ret; + + ret = sunxi_pcie_reset_deassert(sunxi_pcie); + if (ret) + return ret; + + sunxi_pcie_perst_gpio_deassert(sunxi_pcie); + + sunxi_pcie_irqmask(pci); + sunxi_pcie->link_irq = platform_get_irq_byname(pdev, "linkup"); + ret = devm_request_irq(&pdev->dev, sunxi_pcie->link_irq, + sunxi_pcie_linkup_handler, + IRQF_SHARED, "sunxi-pcie-linkup", sunxi_pcie); + if (ret) { + dev_err(&pdev->dev, "failed to request linkup IRQ\n"); + return ret; + } + + ret = sunxi_add_pcie_port(sunxi_pcie, pdev); + if (ret < 0) + return ret; + + return 0; +} + +static int sunxi_pcie_remove(struct platform_device *pdev) +{ + struct sunxi_pcie *pcie = platform_get_drvdata(pdev); + + sunxi_pcie_perst_gpio_assert(pcie); + reset_control_assert(pcie->pcie_bus_rst); + reset_control_assert(pcie->pcie_power_rst); + clk_disable_unprepare(pcie->pcie_ref); + clk_disable_unprepare(pcie->pcie_axi); + clk_disable_unprepare(pcie->pcie_aux); + clk_disable_unprepare(pcie->pcie_bus); + + return 0; +} + +static const struct of_device_id sunxi_pcie_of_match[] = { + { .compatible = "allwinner,sun50i-h6-pcie", }, + {}, +}; +MODULE_DEVICE_TABLE(of, sunxi_pcie_of_match); + +static struct platform_driver sunxi_pcie_driver = { + .driver = { + .name = "sunxi-pcie", + .suppress_bind_attrs = true, + .of_match_table = sunxi_pcie_of_match, + }, + .remove = sunxi_pcie_remove, + .probe = sunxi_pcie_probe, +}; +builtin_platform_driver(sunxi_pcie_driver); diff --git a/target/linux/sunxi/image/cortexa53.mk b/target/linux/sunxi/image/cortexa53.mk index ecd8f5358c..1acc862d0c 100644 --- a/target/linux/sunxi/image/cortexa53.mk +++ b/target/linux/sunxi/image/cortexa53.mk @@ -94,6 +94,14 @@ define Device/pine64_sopine-baseboard endef TARGET_DEVICES += pine64_sopine-baseboard +define Device/xunlong_orangepi-3 + $(Device/sun50i-h6) + DEVICE_VENDOR := Xunlong + DEVICE_MODEL := Orange Pi 3 + SUNXI_DTS_DIR := allwinner/ +endef +TARGET_DEVICES += xunlong_orangepi-3 + define Device/xunlong_orangepi-one-plus $(Device/sun50i-h6) DEVICE_VENDOR := Xunlong diff --git a/target/linux/sunxi/patches-5.4/019-v5.6-arm64-dts-allwinner-h6-Add-thermal-sensor-and-thermal-zon.patch b/target/linux/sunxi/patches-5.4/019-v5.6-arm64-dts-allwinner-h6-Add-thermal-sensor-and-thermal-zon.patch new file mode 100644 index 0000000000..d9e33aa32a --- /dev/null +++ b/target/linux/sunxi/patches-5.4/019-v5.6-arm64-dts-allwinner-h6-Add-thermal-sensor-and-thermal-zon.patch @@ -0,0 +1,69 @@ +From d7cfb661b206c0f9e66c9cdb3634f416c4283449 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Thu, 19 Dec 2019 09:28:22 -0800 +Subject: arm64: dts: allwinner: h6: Add thermal sensor and thermal zones + +There are two sensors, one for CPU, one for GPU. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Vasily Khoruzhick +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 33 ++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -219,6 +220,12 @@ + sid: efuse@3006000 { + compatible = "allwinner,sun50i-h6-sid"; + reg = <0x03006000 0x400>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ ++ ths_calibration: thermal-sensor-calibration@14 { ++ reg = <0x14 0x8>; ++ }; + }; + + watchdog: watchdog@30090a0 { +@@ -808,5 +815,31 @@ + #address-cells = <1>; + #size-cells = <0>; + }; ++ ++ ths: thermal-sensor@5070400 { ++ compatible = "allwinner,sun50i-h6-ths"; ++ reg = <0x05070400 0x100>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>; ++ clock-names = "bus"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration>; ++ nvmem-cell-names = "calibration"; ++ #thermal-sensor-cells = <1>; ++ }; ++ }; ++ ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 0>; ++ }; ++ ++ gpu-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 1>; ++ }; + }; + }; diff --git a/target/linux/sunxi/patches-5.4/020-v5.8-arm64-dts-allwinner-h6-Add-clock-to-CPU-cores.patch b/target/linux/sunxi/patches-5.4/020-v5.8-arm64-dts-allwinner-h6-Add-clock-to-CPU-cores.patch new file mode 100644 index 0000000000..586ea2f0c8 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/020-v5.8-arm64-dts-allwinner-h6-Add-clock-to-CPU-cores.patch @@ -0,0 +1,57 @@ +From 8a3a9535189d908f7e325238c9f09069d4fe9b8f Mon Sep 17 00:00:00 2001 +From: Yangtao Li +Date: Mon, 20 Apr 2020 15:00:13 +0200 +Subject: arm64: dts: allwinner: h6: Add clock to CPU cores +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The ARM CPU cores are fed by the CPU clock from the CCU. Add a +reference to the clock for each CPU core, along with the clock +transition latency. + +Signed-off-by: Yangtao Li +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -27,6 +27,8 @@ + device_type = "cpu"; + reg = <0>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + cpu1: cpu@1 { +@@ -34,6 +36,8 @@ + device_type = "cpu"; + reg = <1>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + cpu2: cpu@2 { +@@ -41,6 +45,8 @@ + device_type = "cpu"; + reg = <2>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ + }; + + cpu3: cpu@3 { +@@ -48,6 +54,8 @@ + device_type = "cpu"; + reg = <3>; + enable-method = "psci"; ++ clocks = <&ccu CLK_CPUX>; ++ clock-latency-ns = <244144>; /* 8 32k periods */ + }; + }; + diff --git a/target/linux/sunxi/patches-5.4/021-v5.8-arm64-dts-allwinner-h6-Add-thermal-trip-points-cooling-ma.patch b/target/linux/sunxi/patches-5.4/021-v5.8-arm64-dts-allwinner-h6-Add-thermal-trip-points-cooling-ma.patch new file mode 100644 index 0000000000..cd183fe40c --- /dev/null +++ b/target/linux/sunxi/patches-5.4/021-v5.8-arm64-dts-allwinner-h6-Add-thermal-trip-points-cooling-ma.patch @@ -0,0 +1,83 @@ +From 9f8a93b742e99dd93ca888161909e7245f1c7269 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Mon, 20 Apr 2020 15:00:14 +0200 +Subject: arm64: dts: allwinner: h6: Add thermal trip points/cooling map +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This enables passive cooling by down-regulating CPU voltage +and frequency. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 28 ++++++++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -29,6 +29,7 @@ + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu1: cpu@1 { +@@ -38,6 +39,7 @@ + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu2: cpu@2 { +@@ -47,6 +49,7 @@ + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + + cpu3: cpu@3 { +@@ -56,6 +59,7 @@ + enable-method = "psci"; + clocks = <&ccu CLK_CPUX>; + clock-latency-ns = <244144>; /* 8 32k periods */ ++ #cooling-cells = <2>; + }; + }; + +@@ -842,6 +846,30 @@ + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&ths 0>; ++ ++ trips { ++ cpu_alert: cpu-alert { ++ temperature = <85000>; ++ hysteresis = <2000>; ++ type = "passive"; ++ }; ++ ++ cpu-crit { ++ temperature = <100000>; ++ hysteresis = <0>; ++ type = "critical"; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu_alert>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; + }; + + gpu-thermal { diff --git a/target/linux/sunxi/patches-5.4/022-v5.8-arm64-dts-allwinner-h6-Add-CPU-Operating-Performance-Poin.patch b/target/linux/sunxi/patches-5.4/022-v5.8-arm64-dts-allwinner-h6-Add-CPU-Operating-Performance-Poin.patch new file mode 100644 index 0000000000..92b984de14 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/022-v5.8-arm64-dts-allwinner-h6-Add-CPU-Operating-Performance-Poin.patch @@ -0,0 +1,153 @@ +From 905434e0b544ee220bcce6da16a6857c0274b8ba Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Mon, 20 Apr 2020 15:00:15 +0200 +Subject: arm64: dts: allwinner: h6: Add CPU Operating Performance Points table +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add an Operating Performance Points table for the CPU cores to +enable Dynamic Voltage & Frequency Scaling on the H6. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +--- + .../boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi | 117 +++++++++++++++++++++ + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 4 + + 2 files changed, 121 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi + +--- /dev/null ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-cpu-opp.dtsi +@@ -0,0 +1,117 @@ ++// SPDX-License-Identifier: (GPL-2.0+ OR MIT) ++// Copyright (C) 2020 Ondrej Jirman ++// Copyright (C) 2020 Clément Péron ++ ++/ { ++ cpu_opp_table: cpu-opp-table { ++ compatible = "allwinner,sun50i-h6-operating-points"; ++ nvmem-cells = <&cpu_speed_grade>; ++ opp-shared; ++ ++ opp@480000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <480000000>; ++ ++ opp-microvolt-speed0 = <880000>; ++ opp-microvolt-speed1 = <820000>; ++ opp-microvolt-speed2 = <820000>; ++ }; ++ ++ opp@720000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <720000000>; ++ ++ opp-microvolt-speed0 = <880000>; ++ opp-microvolt-speed1 = <820000>; ++ opp-microvolt-speed2 = <820000>; ++ }; ++ ++ opp@816000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <816000000>; ++ ++ opp-microvolt-speed0 = <880000>; ++ opp-microvolt-speed1 = <820000>; ++ opp-microvolt-speed2 = <820000>; ++ }; ++ ++ opp@888000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <888000000>; ++ ++ opp-microvolt-speed0 = <880000>; ++ opp-microvolt-speed1 = <820000>; ++ opp-microvolt-speed2 = <820000>; ++ }; ++ ++ opp@1080000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1080000000>; ++ ++ opp-microvolt-speed0 = <940000>; ++ opp-microvolt-speed1 = <880000>; ++ opp-microvolt-speed2 = <880000>; ++ }; ++ ++ opp@1320000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1320000000>; ++ ++ opp-microvolt-speed0 = <1000000>; ++ opp-microvolt-speed1 = <940000>; ++ opp-microvolt-speed2 = <940000>; ++ }; ++ ++ opp@1488000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1488000000>; ++ ++ opp-microvolt-speed0 = <1060000>; ++ opp-microvolt-speed1 = <1000000>; ++ opp-microvolt-speed2 = <1000000>; ++ }; ++ ++ opp@1608000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1608000000>; ++ ++ opp-microvolt-speed0 = <1090000>; ++ opp-microvolt-speed1 = <1030000>; ++ opp-microvolt-speed2 = <1030000>; ++ }; ++ ++ opp@1704000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1704000000>; ++ ++ opp-microvolt-speed0 = <1120000>; ++ opp-microvolt-speed1 = <1060000>; ++ opp-microvolt-speed2 = <1060000>; ++ }; ++ ++ opp@1800000000 { ++ clock-latency-ns = <244144>; /* 8 32k periods */ ++ opp-hz = /bits/ 64 <1800000000>; ++ ++ opp-microvolt-speed0 = <1160000>; ++ opp-microvolt-speed1 = <1100000>; ++ opp-microvolt-speed2 = <1100000>; ++ }; ++ }; ++}; ++ ++&cpu0 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu1 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu2 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; ++ ++&cpu3 { ++ operating-points-v2 = <&cpu_opp_table>; ++}; +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -238,6 +238,10 @@ + ths_calibration: thermal-sensor-calibration@14 { + reg = <0x14 0x8>; + }; ++ ++ cpu_speed_grade: cpu-speed-grade@1c { ++ reg = <0x1c 0x4>; ++ }; + }; + + watchdog: watchdog@30090a0 { diff --git a/target/linux/sunxi/patches-5.4/320-v5.5-clk-sunxi-ng-h6-Use-sigma-delta-modulation-for-audio-PLL.patch b/target/linux/sunxi/patches-5.4/320-v5.5-clk-sunxi-ng-h6-Use-sigma-delta-modulation-for-audio-PLL.patch new file mode 100644 index 0000000000..1c5f89a462 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/320-v5.5-clk-sunxi-ng-h6-Use-sigma-delta-modulation-for-audio-PLL.patch @@ -0,0 +1,74 @@ +From 3ee5f8ab5e718afdde9984a089137360bdfc66eb Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 14 Sep 2019 15:51:00 +0200 +Subject: clk: sunxi-ng: h6: Use sigma-delta modulation for audio PLL + +Audio devices needs exact clock rates in order to correctly reproduce +the sound. Until now, only integer factors were used to configure H6 +audio PLL which resulted in inexact rates. Fix that by adding support +for fractional factors using sigma-delta modulation look-up table. It +contains values for two most commonly used audio base frequencies. + +Signed-off-by: Jernej Skrabec +Acked-by: Chen-Yu Tsai +Signed-off-by: Maxime Ripard +--- + drivers/clk/sunxi-ng/ccu-sun50i-h6.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c ++++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +@@ -203,12 +203,21 @@ static struct ccu_nkmp pll_hsic_clk = { + * hardcode it to match with the clock names. + */ + #define SUN50I_H6_PLL_AUDIO_REG 0x078 ++ ++static struct ccu_sdm_setting pll_audio_sdm_table[] = { ++ { .rate = 541900800, .pattern = 0xc001288d, .m = 1, .n = 22 }, ++ { .rate = 589824000, .pattern = 0xc00126e9, .m = 1, .n = 24 }, ++}; ++ + static struct ccu_nm pll_audio_base_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ ++ .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, ++ BIT(24), 0x178, BIT(31)), + .common = { ++ .features = CCU_FEATURE_SIGMA_DELTA_MOD, + .reg = 0x078, + .hw.init = CLK_HW_INIT("pll-audio-base", "osc24M", + &ccu_nm_ops, +@@ -753,12 +762,12 @@ static const struct clk_hw *clk_parent_p + }; + + /* +- * The divider of pll-audio is fixed to 8 now, as pll-audio-4x has a +- * fixed post-divider 2. ++ * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200 ++ * rates can be set exactly in conjunction with sigma-delta modulation. + */ + static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio", + clk_parent_pll_audio, +- 8, 1, CLK_SET_RATE_PARENT); ++ 24, 1, CLK_SET_RATE_PARENT); + static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", + clk_parent_pll_audio, + 4, 1, CLK_SET_RATE_PARENT); +@@ -1215,12 +1224,12 @@ static int sun50i_h6_ccu_probe(struct pl + } + + /* +- * Force the post-divider of pll-audio to 8 and the output divider +- * of it to 1, to make the clock name represents the real frequency. ++ * Force the post-divider of pll-audio to 12 and the output divider ++ * of it to 2, so 24576000 and 22579200 rates can be set exactly. + */ + val = readl(reg + SUN50I_H6_PLL_AUDIO_REG); + val &= ~(GENMASK(21, 16) | BIT(0)); +- writel(val | (7 << 16), reg + SUN50I_H6_PLL_AUDIO_REG); ++ writel(val | (11 << 16) | BIT(0), reg + SUN50I_H6_PLL_AUDIO_REG); + + /* + * First clock parent (osc32K) is unusable for CEC. But since there diff --git a/target/linux/sunxi/patches-5.4/444-0001-v5.5-arm64-dts-allwinner-h6-Add-pin-configs-for-uart1.patch b/target/linux/sunxi/patches-5.4/444-0001-v5.5-arm64-dts-allwinner-h6-Add-pin-configs-for-uart1.patch new file mode 100644 index 0000000000..135bbedf46 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/444-0001-v5.5-arm64-dts-allwinner-h6-Add-pin-configs-for-uart1.patch @@ -0,0 +1,33 @@ +From cd380e0d00b2b21506f9319a626b6205e9d64aae Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Mon, 7 Oct 2019 22:31:51 +0200 +Subject: [PATCH] arm64: dts: allwinner: h6: Add pin configs for uart1 + +Orange Pi 3 uses UART1 for bluetooth. Add pinconfigs so that we can use +them. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -341,6 +341,16 @@ + pins = "PH0", "PH1"; + function = "uart0"; + }; ++ ++ uart1_pins: uart1-pins { ++ pins = "PG6", "PG7"; ++ function = "uart1"; ++ }; ++ ++ uart1_rts_cts_pins: uart1-rts-cts-pins { ++ pins = "PG8", "PG9"; ++ function = "uart1"; ++ }; + }; + + gic: interrupt-controller@3021000 { diff --git a/target/linux/sunxi/patches-5.4/444-0002-v5.5-arm64-dts-allwinner-h6-add-USB3-device-nodes.patch b/target/linux/sunxi/patches-5.4/444-0002-v5.5-arm64-dts-allwinner-h6-add-USB3-device-nodes.patch new file mode 100644 index 0000000000..90a656b7f1 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/444-0002-v5.5-arm64-dts-allwinner-h6-add-USB3-device-nodes.patch @@ -0,0 +1,59 @@ +From 0b6f7014adc1cc12c7c3ba988594514602919eca Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Sun, 20 Oct 2019 15:42:28 +0200 +Subject: [PATCH] arm64: dts: allwinner: h6: add USB3 device nodes + +Allwinner H6 SoC features USB3 functionality, with a DWC3 controller and +a custom PHY. + +Add device tree nodes for them. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Icenowy Zheng +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 32 ++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -596,6 +596,38 @@ + status = "disabled"; + }; + ++ dwc3: dwc3@5200000 { ++ compatible = "snps,dwc3"; ++ reg = <0x05200000 0x10000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_XHCI>, ++ <&ccu CLK_BUS_XHCI>, ++ <&rtc 0>; ++ clock-names = "ref", "bus_early", "suspend"; ++ resets = <&ccu RST_BUS_XHCI>; ++ /* ++ * The datasheet of the chip doesn't declare the ++ * peripheral function, and there's no boards known ++ * to have a USB Type-B port routed to the port. ++ * In addition, no one has tested the peripheral ++ * function yet. ++ * So set the dr_mode to "host" in the DTSI file. ++ */ ++ dr_mode = "host"; ++ phys = <&usb3phy>; ++ phy-names = "usb3-phy"; ++ status = "disabled"; ++ }; ++ ++ usb3phy: phy@5210000 { ++ compatible = "allwinner,sun50i-h6-usb3-phy"; ++ reg = <0x5210000 0x10000>; ++ clocks = <&ccu CLK_USB_PHY1>; ++ resets = <&ccu RST_USB_PHY1>; ++ #phy-cells = <0>; ++ status = "disabled"; ++ }; ++ + ehci3: usb@5311000 { + compatible = "allwinner,sun50i-h6-ehci", "generic-ehci"; + reg = <0x05311000 0x100>; diff --git a/target/linux/sunxi/patches-5.4/444-0003-arm64-dts-sun50i-h6-Add-HDMI-sound-card-nodes.patch b/target/linux/sunxi/patches-5.4/444-0003-arm64-dts-sun50i-h6-Add-HDMI-sound-card-nodes.patch new file mode 100644 index 0000000000..9c62c05a68 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/444-0003-arm64-dts-sun50i-h6-Add-HDMI-sound-card-nodes.patch @@ -0,0 +1,66 @@ +From 2a63f7145be53b10c0e0c3b1be2e486a6bcadd51 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Fri, 20 Sep 2019 19:23:55 +0200 +Subject: arm64: dts: sun50i-h6: Add HDMI sound card nodes + +From Jernej / LibreELEC. + +Signed-off-by: Ondrej Jirman +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 ++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -109,6 +109,23 @@ + (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>; + }; + ++ sound_hdmi: sound { ++ compatible = "simple-audio-card"; ++ simple-audio-card,format = "i2s"; ++ simple-audio-card,name = "allwinner-hdmi"; ++ simple-audio-card,mclk-fs = <256>; ++ ++ simple-audio-card,codec { ++ sound-dai = <&hdmi>; ++ }; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&i2s1>; ++ dai-tdm-slot-num = <2>; ++ dai-tdm-slot-width = <32>; ++ }; ++ }; ++ + soc { + compatible = "simple-bus"; + #address-cells = <1>; +@@ -536,6 +553,19 @@ + status = "disabled"; + }; + ++ i2s1: i2s@5091000 { ++ #sound-dai-cells = <0>; ++ compatible = "allwinner,sun50i-h6-i2s"; ++ reg = <0x05091000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_I2S1>, <&ccu CLK_I2S1>; ++ clock-names = "apb", "mod"; ++ dmas = <&dma 4>; ++ resets = <&ccu RST_BUS_I2S1>; ++ dma-names = "tx"; ++ allwinner,playback-channels = <8>; ++ }; ++ + usb2otg: usb@5100000 { + compatible = "allwinner,sun50i-h6-musb", + "allwinner,sun8i-a33-musb"; +@@ -655,6 +685,7 @@ + }; + + hdmi: hdmi@6000000 { ++ #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-dw-hdmi"; + reg = <0x06000000 0x10000>; + reg-io-width = <1>; diff --git a/target/linux/sunxi/patches-5.4/444-0004-arm64-dts-allwinner-Add-ARM-Mali-GPU-node-for-H6.patch b/target/linux/sunxi/patches-5.4/444-0004-arm64-dts-allwinner-Add-ARM-Mali-GPU-node-for-H6.patch new file mode 100644 index 0000000000..5f0e157503 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/444-0004-arm64-dts-allwinner-Add-ARM-Mali-GPU-node-for-H6.patch @@ -0,0 +1,35 @@ +From 938519cadbdf2544c85b3a88ae73631b6b5cb7f9 Mon Sep 17 00:00:00 2001 +From: Clément Péron +Date: Tue, 21 May 2019 18:11:01 +0200 +Subject: arm64: dts: allwinner: Add ARM Mali GPU node for H6 + +Add the mali gpu node to the H6 device-tree. + +Signed-off-by: Clément Péron +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -188,6 +188,20 @@ + allwinner,sram = <&ve_sram 1>; + }; + ++ gpu: gpu@1800000 { ++ compatible = "allwinner,sun50i-h6-mali", ++ "arm,mali-t720"; ++ reg = <0x01800000 0x4000>; ++ interrupts = , ++ , ++ ; ++ interrupt-names = "job", "mmu", "gpu"; ++ clocks = <&ccu CLK_GPU>, <&ccu CLK_BUS_GPU>; ++ clock-names = "core", "bus"; ++ resets = <&ccu RST_BUS_GPU>; ++ status = "disabled"; ++ }; ++ + syscon: syscon@3000000 { + compatible = "allwinner,sun50i-h6-system-control", + "allwinner,sun50i-a64-system-control"; diff --git a/target/linux/sunxi/patches-5.4/444-0005-arm64-dts-allwinner-Add-GPU-operating-points-for-H6.patch b/target/linux/sunxi/patches-5.4/444-0005-arm64-dts-allwinner-Add-GPU-operating-points-for-H6.patch new file mode 100644 index 0000000000..24ba606fe7 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/444-0005-arm64-dts-allwinner-Add-GPU-operating-points-for-H6.patch @@ -0,0 +1,96 @@ +From f6644778f7384fa954a78f228f5bc9b31aed58ed Mon Sep 17 00:00:00 2001 +From: Tomeu Vizoso +Date: Wed, 29 May 2019 17:32:55 +0200 +Subject: arm64: dts: allwinner: Add GPU operating points for H6 + +The GPU driver needs them to change the clock frequency and regulator +voltage depending on the load. + +Signed-off-by: Tomeu Vizoso +Cc: Clément Péron +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 66 ++++++++++++++++++++++++++++ + 1 file changed, 66 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -188,6 +188,71 @@ + allwinner,sram = <&ve_sram 1>; + }; + ++ gpu_opp_table: opp-table2 { ++ compatible = "operating-points-v2"; ++ ++ opp00 { ++ opp-hz = /bits/ 64 <756000000>; ++ opp-microvolt = <1040000>; ++ }; ++ opp01 { ++ opp-hz = /bits/ 64 <624000000>; ++ opp-microvolt = <950000>; ++ }; ++ opp02 { ++ opp-hz = /bits/ 64 <576000000>; ++ opp-microvolt = <930000>; ++ }; ++ opp03 { ++ opp-hz = /bits/ 64 <540000000>; ++ opp-microvolt = <910000>; ++ }; ++ opp04 { ++ opp-hz = /bits/ 64 <504000000>; ++ opp-microvolt = <890000>; ++ }; ++ opp05 { ++ opp-hz = /bits/ 64 <456000000>; ++ opp-microvolt = <870000>; ++ }; ++ opp06 { ++ opp-hz = /bits/ 64 <432000000>; ++ opp-microvolt = <860000>; ++ }; ++ opp07 { ++ opp-hz = /bits/ 64 <420000000>; ++ opp-microvolt = <850000>; ++ }; ++ opp08 { ++ opp-hz = /bits/ 64 <408000000>; ++ opp-microvolt = <840000>; ++ }; ++ opp09 { ++ opp-hz = /bits/ 64 <384000000>; ++ opp-microvolt = <830000>; ++ }; ++ opp10 { ++ opp-hz = /bits/ 64 <360000000>; ++ opp-microvolt = <820000>; ++ }; ++ opp11 { ++ opp-hz = /bits/ 64 <336000000>; ++ opp-microvolt = <810000>; ++ }; ++ opp12 { ++ opp-hz = /bits/ 64 <312000000>; ++ opp-microvolt = <810000>; ++ }; ++ opp13 { ++ opp-hz = /bits/ 64 <264000000>; ++ opp-microvolt = <810000>; ++ }; ++ opp14 { ++ opp-hz = /bits/ 64 <216000000>; ++ opp-microvolt = <810000>; ++ }; ++ }; ++ + gpu: gpu@1800000 { + compatible = "allwinner,sun50i-h6-mali", + "arm,mali-t720"; +@@ -199,6 +264,7 @@ + clocks = <&ccu CLK_GPU>, <&ccu CLK_BUS_GPU>; + clock-names = "core", "bus"; + resets = <&ccu RST_BUS_GPU>; ++ operating-points-v2 = <&gpu_opp_table>; + status = "disabled"; + }; + diff --git a/target/linux/sunxi/patches-5.4/445-0003-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-UART1-Bluetoo.patch b/target/linux/sunxi/patches-5.4/445-0003-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-UART1-Bluetoo.patch new file mode 100644 index 0000000000..8b59299b69 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/445-0003-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-UART1-Bluetoo.patch @@ -0,0 +1,62 @@ +From 351170463471d2037aa034625d05f185e6d85f80 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Mon, 7 Oct 2019 22:31:52 +0200 +Subject: [PATCH] arm64: dts: allwinner: orange-pi-3: Enable UART1 / Bluetooth + +The board contains AP6256 WiFi/BT module that has its bluetooth part +connected to SoC's UART1 port. Enable this port, and add node for the +bluetooth device. + +Bluetooth part is named bcm4345c5. + +You'll need a BCM4345C5.hcd firmware file that can be found in the +Xulongs's repository for H6: + +https://github.com/orangepi-xunlong/OrangePiH6_external/tree/master/ap6256 + +The driver expects the firmware at the following path relative to the +firmware directory: + + brcm/BCM4345C5.hcd + +Signed-off-by: Ondrej Jirman +Signed-off-by: Maxime Ripard +--- + .../dts/allwinner/sun50i-h6-orangepi-3.dts | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -15,6 +15,7 @@ + + aliases { + serial0 = &uart0; ++ serial1 = &uart1; + }; + + chosen { +@@ -269,6 +270,24 @@ + status = "okay"; + }; + ++/* There's the BT part of the AP6256 connected to that UART */ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++ ++ bluetooth { ++ compatible = "brcm,bcm4345c5"; ++ clocks = <&rtc 1>; ++ clock-names = "lpo"; ++ device-wakeup-gpios = <&r_pio 1 2 GPIO_ACTIVE_HIGH>; /* PM2 */ ++ host-wakeup-gpios = <&r_pio 1 1 GPIO_ACTIVE_HIGH>; /* PM1 */ ++ shutdown-gpios = <&r_pio 1 4 GPIO_ACTIVE_HIGH>; /* PM4 */ ++ max-speed = <1500000>; ++ }; ++}; ++ + &usb2otg { + /* + * This board doesn't have a controllable VBUS even though it diff --git a/target/linux/sunxi/patches-5.4/445-0004-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-USB-3.0-host-.patch b/target/linux/sunxi/patches-5.4/445-0004-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-USB-3.0-host-.patch new file mode 100644 index 0000000000..4e48be7f19 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/445-0004-v5.5-arm64-dts-allwinner-orange-pi-3-Enable-USB-3.0-host-.patch @@ -0,0 +1,39 @@ +From b5d84ff8ae180e443623ede8a16852f671b0bb05 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Sun, 20 Oct 2019 15:42:29 +0200 +Subject: [PATCH] arm64: dts: allwinner: orange-pi-3: Enable USB 3.0 host + support + +Enable Allwinner's USB 3.0 phy and the host controller. Orange Pi 3 +board has GL3510 USB 3.0 4-port hub connected to the SoC's USB 3.0 +port. All four ports are exposed via USB3-A connectors. VBUS is +always on, since it's powered directly from DCIN (VCC-5V) and +not switchable. + +Signed-off-by: Ondrej Jirman +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -95,6 +95,10 @@ + status = "okay"; + }; + ++&dwc3 { ++ status = "okay"; ++}; ++ + &ehci0 { + status = "okay"; + }; +@@ -304,3 +308,7 @@ + usb3_vbus-supply = <®_vcc5v>; + status = "okay"; + }; ++ ++&usb3phy { ++ status = "okay"; ++}; diff --git a/target/linux/sunxi/patches-5.4/445-0005-v5.7-arm64-dts-allwinner-h6-orangepi-3-Add-eMMC-node.patch b/target/linux/sunxi/patches-5.4/445-0005-v5.7-arm64-dts-allwinner-h6-orangepi-3-Add-eMMC-node.patch new file mode 100644 index 0000000000..a5a73c7e9c --- /dev/null +++ b/target/linux/sunxi/patches-5.4/445-0005-v5.7-arm64-dts-allwinner-h6-orangepi-3-Add-eMMC-node.patch @@ -0,0 +1,34 @@ +From 221a690420fdad808eb0b39eebb19d4eda95568c Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Mon, 10 Feb 2020 18:40:07 +0100 +Subject: [PATCH] arm64: dts: allwinner: h6: orangepi-3: Add eMMC node + +OrangePi 3 can optionally have 8 GiB eMMC (soldered on board). Because +those pins are dedicated to eMMC exclusively, node can be added for both +variants (with and without eMMC). Kernel will then scan bus for presence +of eMMC and act accordingly. + +Signed-off-by: Jernej Skrabec +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -141,6 +141,15 @@ + }; + }; + ++&mmc2 { ++ vmmc-supply = <®_cldo1>; ++ vqmmc-supply = <®_bldo2>; ++ cap-mmc-hw-reset; ++ non-removable; ++ bus-width = <8>; ++ status = "okay"; ++}; ++ + &ohci0 { + status = "okay"; + }; diff --git a/target/linux/sunxi/patches-5.4/445-0006-v5.8-arm64-dts-allwinner-h6-Enable-CPU-opp-tables-for-Orange-P.patch b/target/linux/sunxi/patches-5.4/445-0006-v5.8-arm64-dts-allwinner-h6-Enable-CPU-opp-tables-for-Orange-P.patch new file mode 100644 index 0000000000..f061a88d85 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/445-0006-v5.8-arm64-dts-allwinner-h6-Enable-CPU-opp-tables-for-Orange-P.patch @@ -0,0 +1,52 @@ +From ebae33c3f6cee978f60ad48371258a03f9440691 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= +Date: Mon, 20 Apr 2020 15:00:18 +0200 +Subject: arm64: dts: allwinner: h6: Enable CPU opp tables for Orange Pi 3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Enable CPU opp tables for Orange Pi 3. + +This needs to change the CPU regulator max voltage to fit +the OPP table. + +Also add the ramp-delay information to avoid any out of spec +running as the regulator is slower at reaching the voltage +requested compare to the PLL reaching the frequency. + +There is no such information for AXP805 but similar PMIC (AXP813) +has a DVM (Dynamic Voltage scaling Management) ramp rate equal +to 2500uV/us. + +Signed-off-by: Clément Péron +Signed-off-by: Maxime Ripard +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -6,6 +6,7 @@ + /dts-v1/; + + #include "sun50i-h6.dtsi" ++#include "sun50i-h6-cpu-opp.dtsi" + + #include + +@@ -247,12 +248,14 @@ + regulator-always-on; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1160000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-cpu"; + }; + + reg_dcdcc: dcdcc { + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1080000>; ++ regulator-ramp-delay = <2500>; + regulator-name = "vdd-gpu"; + }; + diff --git a/target/linux/sunxi/patches-5.4/600-0001-v5.11-net-stmmac-dwmac-sun8i-Fix-probe-error-handling.patch b/target/linux/sunxi/patches-5.4/600-0001-v5.11-net-stmmac-dwmac-sun8i-Fix-probe-error-handling.patch new file mode 100644 index 0000000000..bbd02ffc80 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/600-0001-v5.11-net-stmmac-dwmac-sun8i-Fix-probe-error-handling.patch @@ -0,0 +1,87 @@ +From 7eeecc4b1f480c7ba1932cb9a7693f8c452640f2 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 3 Jan 2021 05:17:41 -0600 +Subject: net: stmmac: dwmac-sun8i: Fix probe error handling + +stmmac_pltfr_remove does three things in one function, making it +inapproprate for unwinding the steps in the probe function. Currently, +a failure before the call to stmmac_dvr_probe would leak OF node +references due to missing a call to stmmac_remove_config_dt. And an +error in stmmac_dvr_probe would cause the driver to attempt to remove a +netdevice that was never added. Fix these by reordering the init and +splitting out the error handling steps. + +Fixes: 9f93ac8d4085 ("net-next: stmmac: Add dwmac-sun8i") +Fixes: 40a1dcee2d18 ("net: ethernet: dwmac-sun8i: Use the correct function in exit path") +Signed-off-by: Samuel Holland +Reviewed-by: Chen-Yu Tsai +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 25 ++++++++++++++--------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -1127,10 +1127,6 @@ static int sun8i_dwmac_probe(struct plat + if (ret) + return ret; + +- plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); +- if (IS_ERR(plat_dat)) +- return PTR_ERR(plat_dat); +- + gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL); + if (!gmac) + return -ENOMEM; +@@ -1194,11 +1190,15 @@ static int sun8i_dwmac_probe(struct plat + ret = of_get_phy_mode(dev->of_node); + if (ret < 0) + return -EINVAL; +- plat_dat->interface = ret; ++ ++ plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); ++ if (IS_ERR(plat_dat)) ++ return PTR_ERR(plat_dat); + + /* platform data specifying hardware features and callbacks. + * hardware features were copied from Allwinner drivers. + */ ++ plat_dat->interface = ret; + plat_dat->rx_coe = STMMAC_RX_COE_TYPE2; + plat_dat->tx_coe = 1; + plat_dat->has_sun8i = true; +@@ -1211,7 +1211,7 @@ static int sun8i_dwmac_probe(struct plat + + ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); + if (ret) +- return ret; ++ goto dwmac_deconfig; + + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) +@@ -1234,7 +1234,7 @@ static int sun8i_dwmac_probe(struct plat + } else { + ret = sun8i_dwmac_reset(priv); + if (ret) +- goto dwmac_exit; ++ goto dwmac_remove; + } + + return ret; +@@ -1242,9 +1242,14 @@ dwmac_mux: + reset_control_put(gmac->rst_ephy); + clk_put(gmac->ephy_clk); + sun8i_dwmac_unset_syscon(gmac); ++dwmac_remove: ++ stmmac_dvr_remove(&pdev->dev); + dwmac_exit: +- stmmac_pltfr_remove(pdev); +-return ret; ++ sun8i_dwmac_exit(pdev, gmac); ++dwmac_deconfig: ++ stmmac_remove_config_dt(pdev, plat_dat); ++ ++ return ret; + } + + static int sun8i_dwmac_remove(struct platform_device *pdev) diff --git a/target/linux/sunxi/patches-5.4/600-0002-v5.11-net-stmmac-dwmac-sun8i-Balance-syscon-deinitialization.patch b/target/linux/sunxi/patches-5.4/600-0002-v5.11-net-stmmac-dwmac-sun8i-Balance-syscon-deinitialization.patch new file mode 100644 index 0000000000..978d1dd82c --- /dev/null +++ b/target/linux/sunxi/patches-5.4/600-0002-v5.11-net-stmmac-dwmac-sun8i-Balance-syscon-deinitialization.patch @@ -0,0 +1,205 @@ +From 9b1e39cf5dd81f33186cdb950fcf75a121f1a9a7 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Sun, 3 Jan 2021 05:17:44 -0600 +Subject: net: stmmac: dwmac-sun8i: Balance syscon (de)initialization + +Previously, sun8i_dwmac_set_syscon was called from a chain of functions +in several different files: + sun8i_dwmac_probe + stmmac_dvr_probe + stmmac_hw_init + stmmac_hwif_init + sun8i_dwmac_setup + sun8i_dwmac_set_syscon +which made the lifetime of the syscon values hard to reason about. Part +of the problem is that there is no similar platform driver callback from +stmmac_dvr_remove. As a result, the driver unset the syscon value in +sun8i_dwmac_exit, but this leaves it uninitialized after a suspend/ +resume cycle. It was also unset a second time (outside sun8i_dwmac_exit) +in the probe error path. + +Move the init to the earliest available place in sun8i_dwmac_probe +(after stmmac_probe_config_dt, which initializes plat_dat), and the +deinit to the corresponding position in the cleanup order. + +Since priv is not filled in until stmmac_dvr_probe, this requires +changing the sun8i_dwmac_set_syscon parameters to priv's two relevant +members. + +Fixes: 9f93ac8d4085 ("net-next: stmmac: Add dwmac-sun8i") +Fixes: 634db83b8265 ("net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs") +Signed-off-by: Samuel Holland +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 50 +++++++++++------------ + 1 file changed, 25 insertions(+), 25 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -882,22 +882,23 @@ static int sun8i_dwmac_register_mdio_mux + return ret; + } + +-static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv) ++static int sun8i_dwmac_set_syscon(struct device *dev, ++ struct plat_stmmacenet_data *plat) + { +- struct sunxi_priv_data *gmac = priv->plat->bsp_priv; +- struct device_node *node = priv->device->of_node; ++ struct sunxi_priv_data *gmac = plat->bsp_priv; ++ struct device_node *node = dev->of_node; + int ret; + u32 reg, val; + + ret = regmap_field_read(gmac->regmap_field, &val); + if (ret) { +- dev_err(priv->device, "Fail to read from regmap field.\n"); ++ dev_err(dev, "Fail to read from regmap field.\n"); + return ret; + } + + reg = gmac->variant->default_syscon_value; + if (reg != val) +- dev_warn(priv->device, ++ dev_warn(dev, + "Current syscon value is not the default %x (expect %x)\n", + val, reg); + +@@ -910,9 +911,9 @@ static int sun8i_dwmac_set_syscon(struct + /* Force EPHY xtal frequency to 24MHz. */ + reg |= H3_EPHY_CLK_SEL; + +- ret = of_mdio_parse_addr(priv->device, priv->plat->phy_node); ++ ret = of_mdio_parse_addr(dev, plat->phy_node); + if (ret < 0) { +- dev_err(priv->device, "Could not parse MDIO addr\n"); ++ dev_err(dev, "Could not parse MDIO addr\n"); + return ret; + } + /* of_mdio_parse_addr returns a valid (0 ~ 31) PHY +@@ -928,17 +929,17 @@ static int sun8i_dwmac_set_syscon(struct + + if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) { + if (val % 100) { +- dev_err(priv->device, "tx-delay must be a multiple of 100\n"); ++ dev_err(dev, "tx-delay must be a multiple of 100\n"); + return -EINVAL; + } + val /= 100; +- dev_dbg(priv->device, "set tx-delay to %x\n", val); ++ dev_dbg(dev, "set tx-delay to %x\n", val); + if (val <= gmac->variant->tx_delay_max) { + reg &= ~(gmac->variant->tx_delay_max << + SYSCON_ETXDC_SHIFT); + reg |= (val << SYSCON_ETXDC_SHIFT); + } else { +- dev_err(priv->device, "Invalid TX clock delay: %d\n", ++ dev_err(dev, "Invalid TX clock delay: %d\n", + val); + return -EINVAL; + } +@@ -946,17 +947,17 @@ static int sun8i_dwmac_set_syscon(struct + + if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) { + if (val % 100) { +- dev_err(priv->device, "rx-delay must be a multiple of 100\n"); ++ dev_err(dev, "rx-delay must be a multiple of 100\n"); + return -EINVAL; + } + val /= 100; +- dev_dbg(priv->device, "set rx-delay to %x\n", val); ++ dev_dbg(dev, "set rx-delay to %x\n", val); + if (val <= gmac->variant->rx_delay_max) { + reg &= ~(gmac->variant->rx_delay_max << + SYSCON_ERXDC_SHIFT); + reg |= (val << SYSCON_ERXDC_SHIFT); + } else { +- dev_err(priv->device, "Invalid RX clock delay: %d\n", ++ dev_err(dev, "Invalid RX clock delay: %d\n", + val); + return -EINVAL; + } +@@ -967,7 +968,7 @@ static int sun8i_dwmac_set_syscon(struct + if (gmac->variant->support_rmii) + reg &= ~SYSCON_RMII_EN; + +- switch (priv->plat->interface) { ++ switch (plat->interface) { + case PHY_INTERFACE_MODE_MII: + /* default */ + break; +@@ -981,8 +982,8 @@ static int sun8i_dwmac_set_syscon(struct + reg |= SYSCON_RMII_EN | SYSCON_ETCS_EXT_GMII; + break; + default: +- dev_err(priv->device, "Unsupported interface mode: %s", +- phy_modes(priv->plat->interface)); ++ dev_err(dev, "Unsupported interface mode: %s", ++ phy_modes(plat->interface)); + return -EINVAL; + } + +@@ -1007,8 +1008,6 @@ static void sun8i_dwmac_exit(struct plat + sun8i_dwmac_unpower_internal_phy(gmac); + } + +- sun8i_dwmac_unset_syscon(gmac); +- + clk_disable_unprepare(gmac->tx_clk); + + if (gmac->regulator) +@@ -1043,16 +1042,11 @@ static struct mac_device_info *sun8i_dwm + { + struct mac_device_info *mac; + struct stmmac_priv *priv = ppriv; +- int ret; + + mac = devm_kzalloc(priv->device, sizeof(*mac), GFP_KERNEL); + if (!mac) + return NULL; + +- ret = sun8i_dwmac_set_syscon(priv); +- if (ret) +- return NULL; +- + mac->pcsr = priv->ioaddr; + mac->mac = &sun8i_dwmac_ops; + mac->dma = &sun8i_dwmac_dma_ops; +@@ -1209,10 +1203,14 @@ static int sun8i_dwmac_probe(struct plat + plat_dat->tx_fifo_size = 4096; + plat_dat->rx_fifo_size = 16384; + +- ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); ++ ret = sun8i_dwmac_set_syscon(&pdev->dev, plat_dat); + if (ret) + goto dwmac_deconfig; + ++ ret = sun8i_dwmac_init(pdev, plat_dat->bsp_priv); ++ if (ret) ++ goto dwmac_syscon; ++ + ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (ret) + goto dwmac_exit; +@@ -1241,11 +1239,12 @@ static int sun8i_dwmac_probe(struct plat + dwmac_mux: + reset_control_put(gmac->rst_ephy); + clk_put(gmac->ephy_clk); +- sun8i_dwmac_unset_syscon(gmac); + dwmac_remove: + stmmac_dvr_remove(&pdev->dev); + dwmac_exit: + sun8i_dwmac_exit(pdev, gmac); ++dwmac_syscon: ++ sun8i_dwmac_unset_syscon(gmac); + dwmac_deconfig: + stmmac_remove_config_dt(pdev, plat_dat); + +@@ -1266,6 +1265,7 @@ static int sun8i_dwmac_remove(struct pla + } + + stmmac_pltfr_remove(pdev); ++ sun8i_dwmac_unset_syscon(gmac); + + return 0; + } diff --git a/target/linux/sunxi/patches-5.4/600-0003-v5.12-net-stmmac-dwmac-sun8i-Add-a-shutdown-callback.patch b/target/linux/sunxi/patches-5.4/600-0003-v5.12-net-stmmac-dwmac-sun8i-Add-a-shutdown-callback.patch new file mode 100644 index 0000000000..d9fced81a2 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/600-0003-v5.12-net-stmmac-dwmac-sun8i-Add-a-shutdown-callback.patch @@ -0,0 +1,42 @@ +From 96be41d74f2ee94203f2a61e55927b028a10fea6 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Tue, 16 Feb 2021 22:20:06 -0600 +Subject: net: stmmac: dwmac-sun8i: Add a shutdown callback + +The Ethernet MAC and PHY are usually major consumers of power on boards +which may not be able to fully power off (those with no PMIC). Powering +down the MAC and internal PHY saves power while these boards are "off". + +Reviewed-by: Chen-Yu Tsai +Signed-off-by: Samuel Holland +Signed-off-by: David S. Miller +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -1270,6 +1270,15 @@ static int sun8i_dwmac_remove(struct pla + return 0; + } + ++static void sun8i_dwmac_shutdown(struct platform_device *pdev) ++{ ++ struct net_device *ndev = platform_get_drvdata(pdev); ++ struct stmmac_priv *priv = netdev_priv(ndev); ++ struct sunxi_priv_data *gmac = priv->plat->bsp_priv; ++ ++ sun8i_dwmac_exit(pdev, gmac); ++} ++ + static const struct of_device_id sun8i_dwmac_match[] = { + { .compatible = "allwinner,sun8i-h3-emac", + .data = &emac_variant_h3 }, +@@ -1290,6 +1299,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dwmac_matc + static struct platform_driver sun8i_dwmac_driver = { + .probe = sun8i_dwmac_probe, + .remove = sun8i_dwmac_remove, ++ .shutdown = sun8i_dwmac_shutdown, + .driver = { + .name = "dwmac-sun8i", + .pm = &stmmac_pltfr_pm_ops, diff --git a/target/linux/sunxi/patches-5.4/601-0001-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regulator.patch b/target/linux/sunxi/patches-5.4/601-0001-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regulator.patch new file mode 100644 index 0000000000..9e78b4c4c8 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/601-0001-net-stmmac-sun8i-Use-devm_regulator_get-for-PHY-regulator.patch @@ -0,0 +1,69 @@ +From 3a3014ac153888453128cd4441dc99be2427454a Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Wed, 27 Mar 2019 13:21:06 +0100 +Subject: net: stmmac: sun8i: Use devm_regulator_get for PHY regulator + +Use devm_regulator_get instead of devm_regulator_get_optional and rely +on dummy supply. This avoids NULL checks before regulator_enable/disable +calls. + +This path also improves error reporting, because we now report both +use of dummy supply and error during registration with more detail, +instead of generic info level message "No regulator found" that +was reported previously on errors and lack of regulator property in DT. + +Finally, we'll be adding further optional regulators, and the overall +code will be simpler. + +Signed-off-by: Ondrej Jirman +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 23 ++++++++++------------- + 1 file changed, 10 insertions(+), 13 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -533,12 +533,10 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + +- if (gmac->regulator) { +- ret = regulator_enable(gmac->regulator); +- if (ret) { +- dev_err(&pdev->dev, "Fail to enable regulator\n"); +- return ret; +- } ++ ret = regulator_enable(gmac->regulator); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable regulator\n"); ++ return ret; + } + + ret = clk_prepare_enable(gmac->tx_clk); +@@ -1010,8 +1008,7 @@ static void sun8i_dwmac_exit(struct plat + + clk_disable_unprepare(gmac->tx_clk); + +- if (gmac->regulator) +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1138,12 +1135,12 @@ static int sun8i_dwmac_probe(struct plat + } + + /* Optional regulator for PHY */ +- gmac->regulator = devm_regulator_get_optional(dev, "phy"); ++ gmac->regulator = devm_regulator_get(dev, "phy"); + if (IS_ERR(gmac->regulator)) { +- if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- dev_info(dev, "No regulator found\n"); +- gmac->regulator = NULL; ++ ret = PTR_ERR(gmac->regulator); ++ if (ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); ++ return ret; + } + + /* The "GMAC clock control" register might be located in the diff --git a/target/linux/sunxi/patches-5.4/601-0002-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-regulat.patch b/target/linux/sunxi/patches-5.4/601-0002-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-regulat.patch new file mode 100644 index 0000000000..ab32e9e6f8 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/601-0002-net-stmmac-sun8i-Rename-PHY-regulator-variable-to-regulat.patch @@ -0,0 +1,95 @@ +From 2958cb818095ddaaf8b4c77db121638da30e09d2 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:29:29 +0200 +Subject: net: stmmac: sun8i: Rename PHY regulator variable to regulator_phy + +We'll be adding further optional regulators, and this makes it clearer +what the regulator is for. + +Signed-off-by: Ondrej Jirman +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 40 +++++++++++------------ + 1 file changed, 20 insertions(+), 20 deletions(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -57,20 +57,22 @@ struct emac_variant { + }; + + /* struct sunxi_priv_data - hold all sunxi private data +- * @tx_clk: reference to MAC TX clock +- * @ephy_clk: reference to the optional EPHY clock for the internal PHY +- * @regulator: reference to the optional regulator +- * @rst_ephy: reference to the optional EPHY reset for the internal PHY +- * @variant: reference to the current board variant +- * @regmap: regmap for using the syscon +- * @internal_phy_powered: Does the internal PHY is enabled +- * @use_internal_phy: Is the internal PHY selected for use +- * @mux_handle: Internal pointer used by mdio-mux lib ++ * @tx_clk: reference to MAC TX clock ++ * @ephy_clk: reference to the optional EPHY clock for ++ * the internal PHY ++ * @regulator_phy: reference to the optional regulator ++ * @rst_ephy: reference to the optional EPHY reset for ++ * the internal PHY ++ * @variant: reference to the current board variant ++ * @regmap: regmap for using the syscon ++ * @internal_phy_powered: Does the internal PHY is enabled ++ * @use_internal_phy: Is the internal PHY selected for use ++ * @mux_handle: Internal pointer used by mdio-mux lib + */ + struct sunxi_priv_data { + struct clk *tx_clk; + struct clk *ephy_clk; +- struct regulator *regulator; ++ struct regulator *regulator_phy; + struct reset_control *rst_ephy; + const struct emac_variant *variant; + struct regmap_field *regmap_field; +@@ -533,9 +535,9 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + +- ret = regulator_enable(gmac->regulator); ++ ret = regulator_enable(gmac->regulator_phy); + if (ret) { +- dev_err(&pdev->dev, "Fail to enable regulator\n"); ++ dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); + return ret; + } + +@@ -556,8 +558,7 @@ static int sun8i_dwmac_init(struct platf + err_disable_clk: + clk_disable_unprepare(gmac->tx_clk); + err_disable_regulator: +- if (gmac->regulator) +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator_phy); + + return ret; + } +@@ -1008,7 +1009,7 @@ static void sun8i_dwmac_exit(struct plat + + clk_disable_unprepare(gmac->tx_clk); + +- regulator_disable(gmac->regulator); ++ regulator_disable(gmac->regulator_phy); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1135,11 +1136,10 @@ static int sun8i_dwmac_probe(struct plat + } + + /* Optional regulator for PHY */ +- gmac->regulator = devm_regulator_get(dev, "phy"); +- if (IS_ERR(gmac->regulator)) { +- ret = PTR_ERR(gmac->regulator); +- if (ret != -EPROBE_DEFER) +- dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); ++ gmac->regulator_phy = devm_regulator_get(dev, "phy"); ++ if (IS_ERR(gmac->regulator_phy)) { ++ ret = PTR_ERR(gmac->regulator_phy); ++ dev_err(dev, "Failed to get PHY regulator (%d)\n", ret); + return ret; + } + diff --git a/target/linux/sunxi/patches-5.4/601-0003-net-stmmac-sun8i-Add-support-for-enabling-a-regulator-for.patch b/target/linux/sunxi/patches-5.4/601-0003-net-stmmac-sun8i-Add-support-for-enabling-a-regulator-for.patch new file mode 100644 index 0000000000..da69edcff7 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/601-0003-net-stmmac-sun8i-Add-support-for-enabling-a-regulator-for.patch @@ -0,0 +1,86 @@ +From 7cd35735f61c80cb8e2eaae493cb7a76d6c5c68b Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:31:38 +0200 +Subject: net: stmmac: sun8i: Add support for enabling a regulator for PHY I/O + pins + +Orange Pi 3 has two regulators that power the Realtek RTL8211E. According +to the phy datasheet, both regulators need to be enabled at the same time. + +Add support for the second optional regulator, "phy-io", to the glue +driver. + +Signed-off-by: Ondrej Jirman +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +@@ -61,6 +61,8 @@ struct emac_variant { + * @ephy_clk: reference to the optional EPHY clock for + * the internal PHY + * @regulator_phy: reference to the optional regulator ++ * @regulator_phy_io: reference to the optional regulator for ++ * PHY I/O pins + * @rst_ephy: reference to the optional EPHY reset for + * the internal PHY + * @variant: reference to the current board variant +@@ -73,6 +75,7 @@ struct sunxi_priv_data { + struct clk *tx_clk; + struct clk *ephy_clk; + struct regulator *regulator_phy; ++ struct regulator *regulator_phy_io; + struct reset_control *rst_ephy; + const struct emac_variant *variant; + struct regmap_field *regmap_field; +@@ -535,10 +538,16 @@ static int sun8i_dwmac_init(struct platf + struct sunxi_priv_data *gmac = priv; + int ret; + ++ ret = regulator_enable(gmac->regulator_phy_io); ++ if (ret) { ++ dev_err(&pdev->dev, "Fail to enable PHY I/O regulator\n"); ++ return ret; ++ } ++ + ret = regulator_enable(gmac->regulator_phy); + if (ret) { + dev_err(&pdev->dev, "Fail to enable PHY regulator\n"); +- return ret; ++ goto err_disable_regulator_phy_io; + } + + ret = clk_prepare_enable(gmac->tx_clk); +@@ -559,6 +568,8 @@ err_disable_clk: + clk_disable_unprepare(gmac->tx_clk); + err_disable_regulator: + regulator_disable(gmac->regulator_phy); ++err_disable_regulator_phy_io: ++ regulator_disable(gmac->regulator_phy_io); + + return ret; + } +@@ -1010,6 +1021,7 @@ static void sun8i_dwmac_exit(struct plat + clk_disable_unprepare(gmac->tx_clk); + + regulator_disable(gmac->regulator_phy); ++ regulator_disable(gmac->regulator_phy_io); + } + + static void sun8i_dwmac_set_mac_loopback(void __iomem *ioaddr, bool enable) +@@ -1143,6 +1155,14 @@ static int sun8i_dwmac_probe(struct plat + return ret; + } + ++ /* Optional regulator for PHY I/O pins */ ++ gmac->regulator_phy_io = devm_regulator_get(dev, "phy-io"); ++ if (IS_ERR(gmac->regulator_phy_io)) { ++ ret = PTR_ERR(gmac->regulator_phy_io); ++ dev_err(dev, "Failed to get PHY I/O regulator (%d)\n", ret); ++ return ret; ++ } ++ + /* The "GMAC clock control" register might be located in the + * CCU address range (on the R40), or the system control address + * range (on most other sun8i and later SoCs). diff --git a/target/linux/sunxi/patches-5.4/601-0004-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch b/target/linux/sunxi/patches-5.4/601-0004-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch new file mode 100644 index 0000000000..b6c298a4f9 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/601-0004-arm64-dts-allwinner-orange-pi-3-Enable-ethernet.patch @@ -0,0 +1,100 @@ +From e3c7934c59e412822cdf805c8107fe3a131ef498 Mon Sep 17 00:00:00 2001 +From: Ondrej Jirman +Date: Tue, 20 Aug 2019 14:54:48 +0200 +Subject: arm64: dts: allwinner: orange-pi-3: Enable ethernet + +Orange Pi 3 has two regulators that power the Realtek RTL8211E +PHY. According to the datasheet, both regulators need to be enabled +at the same time, or that "phy-io" should be enabled slightly earlier +than "phy" regulator. + +RTL8211E/RTL8211EG datasheet says: + + Note 4: 2.5V (or 1.8/1.5V) RGMII power should be risen simultaneously + or slightly earlier than 3.3V power. Rising 2.5V (or 1.8/1.5V) power + later than 3.3V power may lead to errors. + +The driver ensures the regulator enable ordering. The timing is set +in DT via startup-delay-us. + +We also need to wait at least 30ms after power-up/reset, before +accessing the PHY registers. + +All values of RX/TX delay were tested exhaustively and a middle one +of the range of working values was chosen. + +Signed-off-by: Ondrej Jirman +--- + .../boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 40 ++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -17,6 +17,7 @@ + aliases { + serial0 = &uart0; + serial1 = &uart1; ++ ethernet0 = &emac; + }; + + chosen { +@@ -59,6 +60,15 @@ + regulator-always-on; + }; + ++ reg_gmac_2v5: gmac-2v5 { ++ compatible = "regulator-fixed"; ++ regulator-name = "gmac-2v5"; ++ regulator-min-microvolt = <2500000>; ++ regulator-max-microvolt = <2500000>; ++ enable-active-high; ++ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>; /* PD6 */ ++ }; ++ + reg_vcc33_wifi: vcc33-wifi { + /* Always on 3.3V regulator for WiFi and BT */ + compatible = "regulator-fixed"; +@@ -118,6 +128,35 @@ + }; + }; + ++&emac { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rgmii_pins>; ++ phy-mode = "rgmii"; ++ phy-handle = <&ext_rgmii_phy>; ++ /* ++ * The board uses 2.5V RGMII signalling. Power sequence to enable ++ * the phy is to enable GMAC-2V5 and GMAC-3V (aldo2) power rails ++ * at the same time and to wait 100ms. The driver enables phy-io ++ * first. Delay is achieved with enable-ramp-delay on reg_aldo2. ++ */ ++ phy-supply = <®_aldo2>; ++ phy-io-supply = <®_gmac_2v5>; ++ allwinner,rx-delay-ps = <1500>; ++ allwinner,tx-delay-ps = <700>; ++ status = "okay"; ++}; ++ ++&mdio { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ ++ reset-gpios = <&pio 3 14 GPIO_ACTIVE_LOW>; /* PD14 */ ++ reset-assert-us = <15000>; ++ reset-deassert-us = <40000>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo1>; + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ +@@ -197,6 +236,7 @@ + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc33-audio-tv-ephy-mac"; ++ regulator-enable-ramp-delay = <100000>; + }; + + /* ALDO3 is shorted to CLDO1 */ diff --git a/target/linux/sunxi/patches-5.4/601-0005-arm64-dts-allwinner-h6-orangepi-3-add-status-LED-aliases.patch b/target/linux/sunxi/patches-5.4/601-0005-arm64-dts-allwinner-h6-orangepi-3-add-status-LED-aliases.patch new file mode 100644 index 0000000000..a4761e9815 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/601-0005-arm64-dts-allwinner-h6-orangepi-3-add-status-LED-aliases.patch @@ -0,0 +1,34 @@ +From 87c558ad8da5661fcad961c4f92b9dd30db50d0e Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Sat, 19 Jun 2021 12:09:34 +0800 +Subject: [PATCH] arm64: dts: allwinner: h6: orangepi-3: add status LED aliases + +Use the SYS LED on the casing for showing system status. + +Signed-off-by: Tianling Shen +--- + arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -18,6 +18,10 @@ + serial0 = &uart0; + serial1 = &uart1; + ethernet0 = &emac; ++ led-boot = &sys_led; ++ led-failsafe = &sys_led; ++ led-running = &sys_led; ++ led-upgrade = &sys_led; + }; + + chosen { +@@ -39,7 +43,7 @@ + leds { + compatible = "gpio-leds"; + +- power { ++ sys_led: power { + label = "orangepi:red:power"; + gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */ + default-state = "on"; diff --git a/target/linux/sunxi/patches-5.4/800-add-wrapped-PCIe-for-sunxi.patch b/target/linux/sunxi/patches-5.4/800-add-wrapped-PCIe-for-sunxi.patch new file mode 100644 index 0000000000..1dc4b45513 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/800-add-wrapped-PCIe-for-sunxi.patch @@ -0,0 +1,89 @@ +From 9e57b0de548676f361ff5085f3b44f48fd91784f Mon Sep 17 00:00:00 2001 +From: Icenowy Zheng +Date: Sun, 29 Mar 2020 10:56:16 +0800 +Subject: [PATCH] add wrapped PCIe for sunxi + +Signed-off-by: Icenowy Zheng +--- + arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 31 + + drivers/pci/controller/dwc/Kconfig | 8 + + drivers/pci/controller/dwc/Makefile | 1 + + .../pci/controller/dwc/pcie-sunxi.c | 589 ++++++++++++++++++ + 4 files changed, 629 insertions(+) + create mode 100644 drivers/pci/controller/dwc/pcie-sunxi.c + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +@@ -13,6 +13,8 @@ + #include + #include + ++/memreserve/ 0x40010000 0x00070000; ++ + / { + interrupt-parent = <&gic>; + #address-cells = <1>; +@@ -764,6 +766,36 @@ + status = "disabled"; + }; + ++ /* On Allwinner H6 PCIe is quirky and needs to be wrapped */ ++ pcie: pcie@5400000 { ++ #address-cells = <3>; ++ #size-cells = <2>; ++ compatible = "allwinner,sun50i-h6-pcie"; ++ reg = <0x05400000 0x4000>, ++ <0x05410000 0x10000>; ++ reg-names = "dbi", "config"; ++ device_type = "pci"; ++ bus-range = <0x00 0xff>; ++ ranges = <0x81000000 0 0 0x05e00000 0 0x00010000 /* downstream I/O */ ++ 0x82000000 0 0x05500000 0x05500000 0 0x00800000>; /* non-prefetchable memory */ ++ num-lanes = <1>; ++ max-link-speed = <2>; ++ interrupts = , ++ ; ++ interrupt-names = "msi", "linkup"; ++ clocks = <&ccu CLK_PCIE_REF_OUT>, ++ <&ccu CLK_PCIE_MAXI>, ++ <&ccu CLK_PCIE_AUX>, ++ <&ccu CLK_BUS_PCIE>; ++ clock-names = "ref", "axi", "aux", "bus"; ++ resets = <&ccu RST_PCIE_POWERUP>, <&ccu RST_BUS_PCIE>; ++ reset-names = "power", "bus"; ++ #interrupt-cells = <1>; ++ interrupt-map-mask = <0 0 0 0>; ++ interrupt-map = <0 0 0 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; ++ status = "disabled"; ++ }; ++ + hdmi: hdmi@6000000 { + #sound-dai-cells = <0>; + compatible = "allwinner,sun50i-h6-dw-hdmi"; +--- a/drivers/pci/controller/dwc/Kconfig ++++ b/drivers/pci/controller/dwc/Kconfig +@@ -236,6 +236,14 @@ config PCI_MESON + and therefore the driver re-uses the DesignWare core functions to + implement the driver. + ++config PCIE_SUNXI ++ bool "Allwinner SoCs PCIe controllers" ++ depends on PCI_MSI_IRQ_DOMAIN ++ select PCIE_DW_HOST ++ help ++ Say Y here it you want PCIe controller support on Allwinner H6, wrapped ++ to a regular PCIe controller by a hypervisor. ++ + config PCIE_TEGRA194 + tristate "NVIDIA Tegra194 (and later) PCIe controller" + depends on ARCH_TEGRA_194_SOC || COMPILE_TEST +--- a/drivers/pci/controller/dwc/Makefile ++++ b/drivers/pci/controller/dwc/Makefile +@@ -17,6 +17,7 @@ obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o + obj-$(CONFIG_PCIE_HISI_STB) += pcie-histb.o + obj-$(CONFIG_PCI_MESON) += pci-meson.o + obj-$(CONFIG_PCIE_TEGRA194) += pcie-tegra194.o ++obj-$(CONFIG_PCIE_SUNXI) += pcie-sunxi.o + obj-$(CONFIG_PCIE_UNIPHIER) += pcie-uniphier.o + + # The following drivers are for devices that use the generic ACPI diff --git a/target/linux/sunxi/patches-5.4/801-arm64-dts-allwinner-Enable-PCIe-for-Orange-Pi-3.patch b/target/linux/sunxi/patches-5.4/801-arm64-dts-allwinner-Enable-PCIe-for-Orange-Pi-3.patch new file mode 100644 index 0000000000..8236f691b4 --- /dev/null +++ b/target/linux/sunxi/patches-5.4/801-arm64-dts-allwinner-Enable-PCIe-for-Orange-Pi-3.patch @@ -0,0 +1,44 @@ +From 84110d1e78e57a09a391f24dc69ac8b1c99740e4 Mon Sep 17 00:00:00 2001 +From: Tianling Shen +Date: Fri, 11 Jun 2021 15:27:06 +0800 +Subject: [PATCH] arm64: dts: allwinner: Enable PCIe for Orange Pi 3 + +Signed-off-by: Tianling Shen +--- + .../dts/allwinner/sun50i-h6-orangepi-3.dts | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-orangepi-3.dts +@@ -55,6 +55,16 @@ + }; + }; + ++ reg_pcie_slot: pcie-slot-power { ++ compatible = "regulator-fixed"; ++ regulator-name = "pcie-slot-3v3"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ startup-delay-us = <100000>; ++ gpio = <&pio 2 15 GPIO_ACTIVE_HIGH>; ++ enable-active-high; ++ }; ++ + reg_vcc5v: vcc5v { + /* board wide 5V supply directly from the DC jack */ + compatible = "regulator-fixed"; +@@ -202,6 +212,14 @@ + status = "okay"; + }; + ++&pcie { ++ vcc-supply = <®_bldo2>; ++ vdd-supply = <®_dcdcd>; ++ slot-supply = <®_pcie_slot>; ++ perst-gpio = <&pio 6 14 GPIO_ACTIVE_LOW>; /* PG14 */ ++ status = "okay"; ++}; ++ + &pio { + vcc-pc-supply = <®_bldo2>; + vcc-pd-supply = <®_cldo1>;