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 <cnsztl@immortalwrt.org>
This commit is contained in:
Tianling Shen 2021-06-20 13:04:24 +08:00
parent a3bdf8b176
commit f01b7cd3cc
No known key found for this signature in database
GPG Key ID: 6850B6345C862176
37 changed files with 4294 additions and 6 deletions

View File

@ -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 <hauke@hauke-m.de>
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

View File

@ -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 <cnsztl@immortalwrt.org>
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))

View File

@ -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)

View File

@ -0,0 +1,60 @@
From 5c6e0b11d5ba2f0570a3c148977d75884bf2b889 Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 29 Mar 2020 10:55:22 +0800
Subject: [PATCH] sunxi: allow to load standalone hypervisor in FIT
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
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 <dt_name> [<dt_name> [<dt_name] ...]
[ -z "$BL31" ] && BL31="bl31.bin"
+[ -z "$HYP" ] && HYP="hyp.bin"
if [ ! -f $BL31 ]; then
echo "WARNING: BL31 file $BL31 NOT found, resulting binary is non-functional" >&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

View File

@ -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 \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,412 @@
From c81877a919d2ae214650b4f10b862dd62f0284a7 Mon Sep 17 00:00:00 2001
From: Andre Heider <a.heider@gmail.com>
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 <a.heider@gmail.com>
Acked-by: Maxime Ripard <mripard@kernel.org>
[Updated OrangePi 3 DT, rebase and config update]
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
---
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 <megous@megous.com>
+
+/dts-v1/;
+
+#include "sun50i-h6.dtsi"
+#include "sun50i-h6-cpu-opp.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ 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 = <&reg_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 = <&reg_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 = <&reg_dcdca>;
+};
+
+&de {
+ status = "okay";
+};
+
+&dwc3 {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&reg_dcdcc>;
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_cldo1>;
+ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+ bus-width = <4>;
+ status = "okay";
+};
+
+&mmc1 {
+ vmmc-supply = <&reg_vcc33_wifi>;
+ vqmmc-supply = <&reg_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 = <&reg_cldo1>;
+ vqmmc-supply = <&reg_bldo2>;
+ cap-mmc-hw-reset;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
+
+&ohci0 {
+ status = "okay";
+};
+
+&ohci3 {
+ status = "okay";
+};
+
+&pio {
+ vcc-pc-supply = <&reg_bldo2>;
+ vcc-pd-supply = <&reg_cldo1>;
+ vcc-pg-supply = <&reg_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 = <&reg_vcc5v>;
+ vinb-supply = <&reg_vcc5v>;
+ vinc-supply = <&reg_vcc5v>;
+ vind-supply = <&reg_vcc5v>;
+ vine-supply = <&reg_vcc5v>;
+ aldoin-supply = <&reg_vcc5v>;
+ bldoin-supply = <&reg_vcc5v>;
+ cldoin-supply = <&reg_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 = <&reg_vcc5v>;
+ usb3_vbus-supply = <&reg_vcc5v>;
+ status = "okay";
+};
+
+&usb3phy {
+ status = "okay";
+};
--- a/board/sunxi/MAINTAINERS
+++ b/board/sunxi/MAINTAINERS
@@ -385,6 +385,11 @@ M: Icenowy Zheng <icenowy@aosc.io>
S: Maintained
F: configs/teres_i_defconfig
+ORANGEPI 3 BOARD
+M: Andre Heider <a.heider@gmail.com>
+S: Maintained
+F: configs/orangepi_3_defconfig
+
ORANGEPI LITE2 BOARD
M: Jagan Teki <jagan@amarulasolutions.com>
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,589 @@
// SPDX-License-Identifier : GPL-2.0
/*
* PCIe RC driver for Allwinner DW PCIe controllers
*
* Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
*
* Copyright (C) 2016 Allwinner Co., Ltd.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
#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);

View File

@ -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

View File

@ -0,0 +1,69 @@
From d7cfb661b206c0f9e66c9cdb3634f416c4283449 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 <dt-bindings/reset/sun50i-h6-ccu.h>
#include <dt-bindings/reset/sun50i-h6-r-ccu.h>
#include <dt-bindings/reset/sun8i-de2.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
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 = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ 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>;
+ };
};
};

View File

@ -0,0 +1,57 @@
From 8a3a9535189d908f7e325238c9f09069d4fe9b8f Mon Sep 17 00:00:00 2001
From: Yangtao Li <tiny.windzz@gmail.com>
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 <tiny.windzz@gmail.com>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 */
};
};

View File

@ -0,0 +1,83 @@
From 9f8a93b742e99dd93ca888161909e7245f1c7269 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 {

View File

@ -0,0 +1,153 @@
From 905434e0b544ee220bcce6da16a6857c0274b8ba Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Clément Péron <peron.clem@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
.../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 <megous@megous.com>
+// Copyright (C) 2020 Clément Péron <peron.clem@gmail.com>
+
+/ {
+ 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 {

View File

@ -0,0 +1,74 @@
From 3ee5f8ab5e718afdde9984a089137360bdfc66eb Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
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 <jernej.skrabec@siol.net>
Acked-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
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

View File

@ -0,0 +1,33 @@
From cd380e0d00b2b21506f9319a626b6205e9d64aae Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
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 {

View File

@ -0,0 +1,59 @@
From 0b6f7014adc1cc12c7c3ba988594514602919eca Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
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 <megous@megous.com>
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ 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>;

View File

@ -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 <megous@megous.com>
---
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 = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ 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>;

View File

@ -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 <peron.clem@gmail.com>
---
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 = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ 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";

View File

@ -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 <tomeu.vizoso@collabora.com>
Cc: Clément Péron <peron.clem@gmail.com>
---
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";
};

View File

@ -0,0 +1,62 @@
From 351170463471d2037aa034625d05f185e6d85f80 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Maxime Ripard <mripard@kernel.org>
---
.../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

View File

@ -0,0 +1,39 @@
From b5d84ff8ae180e443623ede8a16852f671b0bb05 Mon Sep 17 00:00:00 2001
From: Ondrej Jirman <megous@megous.com>
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 <megous@megous.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 = <&reg_vcc5v>;
status = "okay";
};
+
+&usb3phy {
+ status = "okay";
+};

View File

@ -0,0 +1,34 @@
From 221a690420fdad808eb0b39eebb19d4eda95568c Mon Sep 17 00:00:00 2001
From: Jernej Skrabec <jernej.skrabec@siol.net>
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 <jernej.skrabec@siol.net>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 = <&reg_cldo1>;
+ vqmmc-supply = <&reg_bldo2>;
+ cap-mmc-hw-reset;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
+};
+
&ohci0 {
status = "okay";
};

View File

@ -0,0 +1,52 @@
From ebae33c3f6cee978f60ad48371258a03f9440691 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9ron?= <peron.clem@gmail.com>
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 <peron.clem@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
---
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 <dt-bindings/gpio/gpio.h>
@@ -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";
};

View File

@ -0,0 +1,87 @@
From 7eeecc4b1f480c7ba1932cb9a7693f8c452640f2 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
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 <samuel@sholland.org>
Reviewed-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
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)

View File

@ -0,0 +1,205 @@
From 9b1e39cf5dd81f33186cdb950fcf75a121f1a9a7 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
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 <samuel@sholland.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
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;
}

View File

@ -0,0 +1,42 @@
From 96be41d74f2ee94203f2a61e55927b028a10fea6 Mon Sep 17 00:00:00 2001
From: Samuel Holland <samuel@sholland.org>
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 <wens@csie.org>
Signed-off-by: Samuel Holland <samuel@sholland.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
---
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,

View File

@ -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 <megous@megous.com>
---
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

View File

@ -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 <megous@megous.com>
---
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;
}

View File

@ -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 <megous@megous.com>
---
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).

View File

@ -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 <megous@megous.com>
---
.../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 = <&reg_aldo2>;
+ phy-io-supply = <&reg_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 = <&reg_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 */

View File

@ -0,0 +1,34 @@
From 87c558ad8da5661fcad961c4f92b9dd30db50d0e Mon Sep 17 00:00:00 2001
From: Tianling Shen <cnsztl@immortalwrt.org>
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 <cnsztl@immortalwrt.org>
---
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";

View File

@ -0,0 +1,89 @@
From 9e57b0de548676f361ff5085f3b44f48fd91784f Mon Sep 17 00:00:00 2001
From: Icenowy Zheng <icenowy@aosc.io>
Date: Sun, 29 Mar 2020 10:56:16 +0800
Subject: [PATCH] add wrapped PCIe for sunxi
Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
---
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 <dt-bindings/reset/sun8i-de2.h>
#include <dt-bindings/thermal/thermal.h>
+/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 = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ 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

View File

@ -0,0 +1,44 @@
From 84110d1e78e57a09a391f24dc69ac8b1c99740e4 Mon Sep 17 00:00:00 2001
From: Tianling Shen <cnsztl@immortalwrt.org>
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 <cnsztl@immortalwrt.org>
---
.../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 = <&reg_bldo2>;
+ vdd-supply = <&reg_dcdcd>;
+ slot-supply = <&reg_pcie_slot>;
+ perst-gpio = <&pio 6 14 GPIO_ACTIVE_LOW>; /* PG14 */
+ status = "okay";
+};
+
&pio {
vcc-pc-supply = <&reg_bldo2>;
vcc-pd-supply = <&reg_cldo1>;