From 640b0b79ff05c42991e99a49ed81efb3fac25045 Mon Sep 17 00:00:00 2001 From: Allen Zhao Date: Sat, 9 Mar 2024 10:44:58 +0800 Subject: [PATCH 1/9] mediatek: filogic: add Unielec U7981-01 support Hardware specification: SoC: MediaTek MT7981B 2x A53 Flash: 8GB eMMC or 128 MB SPI-NAND RAM: 256MB Ethernet: 5x 10/100/1000 Mbps Switch: MediaTek MT7531AE WiFi: MediaTek MT7976C Button: Reset USB: M.2(B-key) for 4G/5G Module Power: DC 12V 1A UART: 3.3v, 115200n8 -------------------------- | Layout | | ----------------- | | 4 | VCC RX TX GND | <= | | ----------------- | -------------------------- The U-boot menu will automatically appear at startup, and then select the required options through UP/DOWN Key. NAND Flash and eMMC Flash instructions: 1. Set your computers IP adress to 192.168.1.2. 2. Run a TFTP server providing the sysupgrade.bin image. 3. Power on the router, into the U-Boot menu. 4. Select "2. Upgrade firmware" 5. Update sysupgrade.bin file name, input server IP and input device IP (if they deviate from the defaults) 6. Wait for automatic startup after burning Signed-off-by: Allen Zhao --- .../dts/mt7981b-unielec-u7981-01-emmc.dts | 99 ++++++++++++++ .../dts/mt7981b-unielec-u7981-01-nand.dts | 116 ++++++++++++++++ .../dts/mt7981b-unielec-u7981-01.dtsi | 124 ++++++++++++++++++ .../filogic/base-files/etc/board.d/02_network | 1 + .../base-files/lib/upgrade/platform.sh | 17 +++ target/linux/mediatek/image/filogic.mk | 22 ++++ 6 files changed, 379 insertions(+) create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts create mode 100644 target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts new file mode 100644 index 0000000000..abd4d4e59d --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-emmc.dts @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981b-unielec-u7981-01.dtsi" +/ { + model = "Unielec U7981-01 (EMMC)"; + compatible = "unielec,u7981-01-emmc", "mediatek,mt7981"; +}; + +&mmc0 { + pinctrl-names = "default", "state_uhs"; + pinctrl-0 = <&mmc0_pins_default>; + pinctrl-1 = <&mmc0_pins_uhs>; + bus-width = <8>; + max-frequency = <52000000>; + cap-mmc-highspeed; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; + + card@0 { + compatible = "mmc-card"; + reg = <0>; + + block { + compatible = "block-device"; + partitions { + block-partition-env { + partname = "u-boot-env"; + + nvmem-layout { + compatible = "u-boot,env-layout"; + }; + }; + + block-partition-factory { + partname = "factory"; + + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_4: macaddr@4 { + compatible = "mac-base"; + reg = <0x4 0x6>; + #nvmem-cell-cells = <1>; + }; + + macaddr_factory_1000: macaddr@1000 { + compatible = "mac-base"; + reg = <0x1000 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + }; + }; + }; +}; + +&pio { + mmc0_pins_default: mmc0-pins-default { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; + + mmc0_pins_uhs: mmc0-pins-uhs { + mux { + function = "flash"; + groups = "emmc_45"; + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_1000 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_1000 1>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts new file mode 100644 index 0000000000..230a612a34 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01-nand.dts @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981b-unielec-u7981-01.dtsi" +/ { + model = "Unielec U7981-01 (NAND)"; + compatible = "unielec,u7981-01-nand", "mediatek,mt7981"; +}; + +&spi0 { + pinctrl-names = "default"; + pinctrl-0 = <&spi0_flash_pins>; + status = "okay"; + spi_nand: spi_nand@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "spi-nand"; + reg = <0>; + spi-max-frequency = <52000000>; + spi-tx-buswidth = <4>; + spi-rx-buswidth = <4>; + + mediatek,nmbm; + mediatek,bmt-max-ratio = <1>; + mediatek,bmt-max-reserved-blocks = <64>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "bl2"; + reg = <0x00000 0x0100000>; + read-only; + }; + + partition@100000 { + label = "u-boot-env"; + reg = <0x0100000 0x0080000>; + }; + + factory: partition@180000 { + label = "factory"; + reg = <0x180000 0x200000>; + read-only; + + compatible = "nvmem-cells"; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_factory_0: eeprom@0 { + reg = <0x0 0x1000>; + }; + + macaddr_factory_1000: macaddr@1000 { + compatible = "mac-base"; + reg = <0x1000 0x6>; + #nvmem-cell-cells = <1>; + }; + }; + }; + + partition@380000 { + label = "fip"; + reg = <0x380000 0x0200000>; + }; + + partition@580000 { + label = "ubi"; + reg = <0x580000 0x4000000>; + }; + }; + }; +}; + +&pio { + spi0_flash_pins: spi0-pins { + mux { + function = "spi"; + groups = "spi0", "spi0_wp_hold"; + }; + + conf-pu { + pins = "SPI0_CS", "SPI0_HOLD", "SPI0_WP"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + + conf-pd { + pins = "SPI0_CLK", "SPI0_MOSI", "SPI0_MISO"; + drive-strength = <8>; + mediatek,pull-up-adv = <0>; /* bias-disable */ + }; + }; +}; + +&gmac0 { + nvmem-cells = <&macaddr_factory_1000 0>; + nvmem-cell-names = "mac-address"; +}; + +&gmac1 { + nvmem-cells = <&macaddr_factory_1000 1>; + nvmem-cell-names = "mac-address"; +}; + +&wifi { + nvmem-cells = <&eeprom_factory_0>; + nvmem-cell-names = "eeprom"; + status = "okay"; +}; diff --git a/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi new file mode 100644 index 0000000000..6e6150ba21 --- /dev/null +++ b/target/linux/mediatek/dts/mt7981b-unielec-u7981-01.dtsi @@ -0,0 +1,124 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (C) 2023 Allen Zhao + */ + +/dts-v1/; +#include "mt7981.dtsi" +/ { + model = "Unielec U7981-01 (EMMC)"; + compatible = "unielec,u7981-01-emmc", "mediatek,mt7981"; + + chosen { + bootargs = "console=ttyS0,115200n1 loglevel=8 \ + earlycon=uart8250,mmio32,0x11002000 \ + "; + }; + + gpio-keys { + compatible = "gpio-keys"; + reset { + label = "reset"; + linux,code = ; + gpios = <&pio 1 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&uart0 { + status = "okay"; +}; + +&watchdog { + status = "okay"; +}; + +ð { + pinctrl-names = "default"; + pinctrl-0 = <&mdio_pins &gbe_led0_pins &gbe_led1_pins>; + status = "okay"; + + gmac0: mac@0 { + /* LAN */ + compatible = "mediatek,eth-mac"; + reg = <0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + + gmac1: mac@1 { + /* WAN */ + compatible = "mediatek,eth-mac"; + reg = <1>; + phy-mode = "gmii"; + phy-handle = <&int_gbe_phy>; + }; +}; + +&mdio_bus { + switch: switch@1f { + compatible = "mediatek,mt7531"; + reg = <31>; + reset-gpios = <&pio 39 GPIO_ACTIVE_HIGH>; + interrupt-controller; + #interrupt-cells = <1>; + interrupt-parent = <&pio>; + interrupts = <38 IRQ_TYPE_LEVEL_HIGH>; + }; +}; + +&switch { + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + label = "lan1"; + }; + + port@1 { + reg = <1>; + label = "lan2"; + }; + + port@2 { + reg = <2>; + label = "lan3"; + }; + + port@3 { + reg = <3>; + label = "lan4"; + }; + + port@6 { + reg = <6>; + label = "cpu"; + ethernet = <&gmac0>; + phy-mode = "2500base-x"; + + fixed-link { + speed = <2500>; + full-duplex; + pause; + }; + }; + }; +}; + +&usb_phy { + status = "okay"; +}; + +&xhci { + mediatek,u3p-dis-msk = <0x0>; + phys = <&u2port0 PHY_TYPE_USB2>, + <&u3port0 PHY_TYPE_USB3>; + status = "okay"; +}; diff --git a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network index 8e4fd8003c..5b8b910f62 100644 --- a/target/linux/mediatek/filogic/base-files/etc/board.d/02_network +++ b/target/linux/mediatek/filogic/base-files/etc/board.d/02_network @@ -26,6 +26,7 @@ mediatek_setup_interfaces() asus,tuf-ax4200|\ jdcloud,re-cp-03|\ mediatek,mt7981-rfb|\ + unielec,u7981-01*|\ zbtlink,zbt-z8102ax) ucidef_set_interfaces_lan_wan "lan1 lan2 lan3 lan4" eth1 ;; diff --git a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh index 4df4370f0f..389c177fb9 100755 --- a/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh +++ b/target/linux/mediatek/filogic/base-files/lib/upgrade/platform.sh @@ -164,6 +164,23 @@ platform_do_upgrade() { CI_ROOTPART="ubi_rootfs" nand_do_upgrade "$1" ;; + unielec,u7981-01*) + local rootdev="$(cmdline_get_var root)" + rootdev="${rootdev##*/}" + rootdev="${rootdev%p[0-9]*}" + case "$rootdev" in + mmc*) + CI_ROOTDEV="$rootdev" + CI_KERNPART="kernel" + CI_ROOTPART="rootfs" + emmc_do_upgrade "$1" + ;; + *) + CI_KERNPART="fit" + nand_do_upgrade "$1" + ;; + esac + ;; *) nand_do_upgrade "$1" ;; diff --git a/target/linux/mediatek/image/filogic.mk b/target/linux/mediatek/image/filogic.mk index 7d2fac56b6..e3b588c861 100644 --- a/target/linux/mediatek/image/filogic.mk +++ b/target/linux/mediatek/image/filogic.mk @@ -913,6 +913,28 @@ define Device/ubnt_unifi-6-plus endef TARGET_DEVICES += ubnt_unifi-6-plus +define Device/unielec_u7981-01 + DEVICE_VENDOR := Unielec + DEVICE_MODEL := U7981-01 + DEVICE_DTS_DIR := ../dts + DEVICE_PACKAGES := kmod-mt7981-firmware mt7981-wo-firmware kmod-usb3 e2fsprogs f2fsck mkf2fs fdisk partx-utils + IMAGE/sysupgrade.bin := sysupgrade-tar | append-metadata +endef + +define Device/unielec_u7981-01-emmc + DEVICE_DTS := mt7981b-unielec-u7981-01-emmc + DEVICE_VARIANT := (EMMC) + $(call Device/unielec_u7981-01) +endef +TARGET_DEVICES += unielec_u7981-01-emmc + +define Device/unielec_u7981-01-nand + DEVICE_DTS := mt7981b-unielec-u7981-01-nand + DEVICE_VARIANT := (NAND) + $(call Device/unielec_u7981-01) +endef +TARGET_DEVICES += unielec_u7981-01-nand + define Device/xiaomi_mi-router-ax3000t DEVICE_VENDOR := Xiaomi DEVICE_MODEL := Mi Router AX3000T From 71ccb35017ada8211c62b1d02819ad9a7a0fa14a Mon Sep 17 00:00:00 2001 From: Goetz Goerisch Date: Sun, 24 Mar 2024 18:31:06 +0100 Subject: [PATCH 2/9] realtek: add Zyxel GS1900-8 v2 The Zyxel GS1900-8 v2 or Rev.B1 is a newer variant of the GS1900-8, but otherwise similar to the other GS1900 switches. Differences ------------ * Front Button labeled RESTORE * NO Power Switch on rear * Serial Header next to the barrel power connector * Part Number ends 0102F Signed-off-by: Goetz Goerisch --- target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts | 2 +- target/linux/realtek/image/rtl838x.mk | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts b/target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts index e9c5efe603..7aa1cc274c 100644 --- a/target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts +++ b/target/linux/realtek/dts-5.15/rtl8380_zyxel_gs1900-8.dts @@ -4,7 +4,7 @@ / { compatible = "zyxel,gs1900-8", "realtek,rtl838x-soc"; - model = "ZyXEL GS1900-8 Switch"; + model = "ZyXEL GS1900-8v1/v2 Switch"; }; &gpio1 { diff --git a/target/linux/realtek/image/rtl838x.mk b/target/linux/realtek/image/rtl838x.mk index 19a40f1f61..dc4ddc6d1d 100644 --- a/target/linux/realtek/image/rtl838x.mk +++ b/target/linux/realtek/image/rtl838x.mk @@ -313,6 +313,10 @@ define Device/zyxel_gs1900-8 $(Device/zyxel_gs1900) SOC := rtl8380 DEVICE_MODEL := GS1900-8 + DEVICE_VARIANT := v1 + DEVICE_ALT0_VENDOR := ZyXEL + DEVICE_ALT0_MODEL := GS1900-8 + DEVICE_ALT0_VARIANT := v2 ZYXEL_VERS := AAHH endef TARGET_DEVICES += zyxel_gs1900-8 From 79e9ce354efc03859fea288d4131b8fa0cca1b3a Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Mon, 25 Mar 2024 21:58:49 +0000 Subject: [PATCH 3/9] generic: phy-mediatek-xfi-tphy: fix SGMII issue Fix issue of transmitting abnormal data which leads to link problems in 1G and 2.5G SerDes modes (SGMII, 1000Base-X, 2500Base-X) on the MediaTek MT7988 SoC. Link: https://git01.mediatek.com/plugins/gitiles/openwrt/feeds/mtk-openwrt-feeds/+/b72d6cba92bf9e29fb035c03052fa1e86664a25b Signed-off-by: Daniel Golle --- .../739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch | 3 ++- .../739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch b/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch index d7424020a7..1aa36fcd3d 100644 --- a/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch +++ b/target/linux/generic/pending-6.1/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch @@ -102,7 +102,7 @@ Signed-off-by: Daniel Golle phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c -@@ -0,0 +1,392 @@ +@@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* MediaTek 10GE SerDes PHY driver + * @@ -272,6 +272,7 @@ Signed-off-by: Daniel Golle + XTP_PCS_PWD_ASYNC(2)); + + usleep_range(1, 5); ++ writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40); + + /* Setup TX DA default value */ + mtk_xfi_tphy_rmw(xfi_tphy, 0x30b0, 0x30, 0x20); diff --git a/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch b/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch index d7424020a7..1aa36fcd3d 100644 --- a/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch +++ b/target/linux/generic/pending-6.6/739-02-phy-add-driver-for-MediaTek-XFI-T-PHY.patch @@ -102,7 +102,7 @@ Signed-off-by: Daniel Golle phy-mtk-hdmi-drv-y += phy-mtk-hdmi-mt2701.o --- /dev/null +++ b/drivers/phy/mediatek/phy-mtk-xfi-tphy.c -@@ -0,0 +1,392 @@ +@@ -0,0 +1,393 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* MediaTek 10GE SerDes PHY driver + * @@ -272,6 +272,7 @@ Signed-off-by: Daniel Golle + XTP_PCS_PWD_ASYNC(2)); + + usleep_range(1, 5); ++ writel(XTP_LN_FRC_TX_DATA_EN, xfi_tphy->base + REG_DIG_LN_TRX_40); + + /* Setup TX DA default value */ + mtk_xfi_tphy_rmw(xfi_tphy, 0x30b0, 0x30, 0x20); From 80b2288ea3234958e78761cc4720c03d4072d830 Mon Sep 17 00:00:00 2001 From: Josef Schlehofer Date: Tue, 26 Mar 2024 10:37:37 +0100 Subject: [PATCH 4/9] tools/expat: update to version 2.6.2 Release notes: https://github.com/libexpat/libexpat/blob/R_2_6_2/expat/Changes Fixes: CVE-2024-28757 Signed-off-by: Josef Schlehofer --- tools/expat/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/expat/Makefile b/tools/expat/Makefile index 1df6f8ec96..95e631716c 100644 --- a/tools/expat/Makefile +++ b/tools/expat/Makefile @@ -9,10 +9,10 @@ include $(TOPDIR)/rules.mk PKG_NAME:=expat PKG_CPE_ID:=cpe:/a:libexpat:expat -PKG_VERSION:=2.6.0 +PKG_VERSION:=2.6.2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz -PKG_HASH:=cb5f5a8ea211e1cabd59be0a933a52e3c02cc326e86a4d387d8d218e7ee47a3e +PKG_HASH:=ee14b4c5d8908b1bec37ad937607eab183d4d9806a08adee472c3c3121d27364 PKG_SOURCE_URL:=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$(PKG_VERSION)) HOST_BUILD_PARALLEL:=1 From 1d33ee019f62021dfd4911ce8b5a7537a545ede8 Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Tue, 26 Mar 2024 12:36:27 +0100 Subject: [PATCH 5/9] kernel: qca-ssdk: fix C45 MDIO support on kernel 6.6 Kernel 6.3 has introduced separate C45 read/write operations, and thus split them out of the C22 operations completely so the old way of marking C45 reads and writes via the register value does not work anymore. This is causing SSDK to fail and find C45 only PHY-s such as Aquantia ones: [ 22.187877] ssdk_phy_driver_init[371]:INFO:dev_id = 0, phy_adress = 8, phy_id = 0x0 phytype doesn't match [ 22.209924] ssdk_phy_driver_init[371]:INFO:dev_id = 0, phy_adress = 0, phy_id = 0x0 phytype doesn't match This in turn causes USXGMII MAC autoneg bit to not get set and then UNIPHY autoneg will time out, causing the 10G ports not to work: [ 37.292784] uniphy autoneg time out! So, lets detect C45 reads and writes by the magic BIT(30) in the register argument and if so call separate C45 mdiobus read/write functions. Signed-off-by: Robert Marko --- package/kernel/qca-ssdk/Makefile | 2 +- ...dapt-to-C22-and-C45-read-write-split.patch | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 package/kernel/qca-ssdk/patches/103-mdio-adapt-to-C22-and-C45-read-write-split.patch diff --git a/package/kernel/qca-ssdk/Makefile b/package/kernel/qca-ssdk/Makefile index 6a7bab7a9a..cd81aeb61c 100644 --- a/package/kernel/qca-ssdk/Makefile +++ b/package/kernel/qca-ssdk/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=qca-ssdk -PKG_RELEASE:=5 +PKG_RELEASE:=6 PKG_SOURCE_URL:=https://git.codelinaro.org/clo/qsdk/oss/lklm/qca-ssdk.git PKG_SOURCE_PROTO:=git diff --git a/package/kernel/qca-ssdk/patches/103-mdio-adapt-to-C22-and-C45-read-write-split.patch b/package/kernel/qca-ssdk/patches/103-mdio-adapt-to-C22-and-C45-read-write-split.patch new file mode 100644 index 0000000000..7ddca554ec --- /dev/null +++ b/package/kernel/qca-ssdk/patches/103-mdio-adapt-to-C22-and-C45-read-write-split.patch @@ -0,0 +1,98 @@ +From bdae481e89cbe551068a99028bb57119b59f5ff4 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 26 Mar 2024 12:19:49 +0100 +Subject: [PATCH] mdio: adapt to C22 and C45 read/write split + +Kernel 6.3 has introduced separate C45 read/write operations, and thus +split them out of the C22 operations completely so the old way of marking +C45 reads and writes via the register value does not work anymore. + +This is causing SSDK to fail and find C45 only PHY-s such as Aquantia ones: +[ 22.187877] ssdk_phy_driver_init[371]:INFO:dev_id = 0, phy_adress = 8, phy_id = 0x0 phytype doesn't match +[ 22.209924] ssdk_phy_driver_init[371]:INFO:dev_id = 0, phy_adress = 0, phy_id = 0x0 phytype doesn't match + +This in turn causes USXGMII MAC autoneg bit to not get set and then UNIPHY +autoneg will time out, causing the 10G ports not to work: +[ 37.292784] uniphy autoneg time out! + +So, lets detect C45 reads and writes by the magic BIT(30) in the register +argument and if so call separate C45 mdiobus read/write functions. + +Signed-off-by: Robert Marko +--- + include/init/ssdk_plat.h | 7 +++++++ + src/init/ssdk_plat.c | 30 ++++++++++++++++++++++++++++++ + 2 files changed, 37 insertions(+) + +--- a/include/init/ssdk_plat.h ++++ b/include/init/ssdk_plat.h +@@ -505,3 +505,10 @@ void ssdk_plat_exit(a_uint32_t dev_id); + + #endif + /*qca808x_end*/ ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)) ++#define MII_ADDR_C45 (1<<30) ++#define MII_DEVADDR_C45_SHIFT 16 ++#define MII_DEVADDR_C45_MASK GENMASK(20, 16) ++#define MII_REGADDR_C45_MASK GENMASK(15, 0) ++#endif +--- a/src/init/ssdk_plat.c ++++ b/src/init/ssdk_plat.c +@@ -356,6 +356,18 @@ phy_addr_validation_check(a_uint32_t phy + return A_TRUE; + } + ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)) ++static inline u16 mdiobus_c45_regad(u32 regnum) ++{ ++ return FIELD_GET(MII_REGADDR_C45_MASK, regnum); ++} ++ ++static inline u16 mdiobus_c45_devad(u32 regnum) ++{ ++ return FIELD_GET(MII_DEVADDR_C45_MASK, regnum); ++} ++#endif ++ + sw_error_t + qca_ar8327_phy_read(a_uint32_t dev_id, a_uint32_t phy_addr, + a_uint32_t reg, a_uint16_t* data) +@@ -371,9 +383,18 @@ qca_ar8327_phy_read(a_uint32_t dev_id, a + if (!bus) + return SW_NOT_SUPPORTED; + phy_addr = TO_PHY_ADDR(phy_addr); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)) ++ mutex_lock(&bus->mdio_lock); ++ if (reg & MII_ADDR_C45) ++ *data = __mdiobus_c45_read(bus, phy_addr, mdiobus_c45_devad(reg), mdiobus_c45_regad(reg)); ++ else ++ *data = __mdiobus_read(bus, phy_addr, reg); ++ mutex_unlock(&bus->mdio_lock); ++#else + mutex_lock(&bus->mdio_lock); + *data = __mdiobus_read(bus, phy_addr, reg); + mutex_unlock(&bus->mdio_lock); ++#endif + + return 0; + } +@@ -393,9 +414,18 @@ qca_ar8327_phy_write(a_uint32_t dev_id, + if (!bus) + return SW_NOT_SUPPORTED; + phy_addr = TO_PHY_ADDR(phy_addr); ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6,3,0)) ++ mutex_lock(&bus->mdio_lock); ++ if (reg & MII_ADDR_C45) ++ __mdiobus_c45_write(bus, phy_addr, mdiobus_c45_devad(reg), mdiobus_c45_regad(reg), data); ++ else ++ __mdiobus_write(bus, phy_addr, reg, data); ++ mutex_unlock(&bus->mdio_lock); ++#else + mutex_lock(&bus->mdio_lock); + __mdiobus_write(bus, phy_addr, reg, data); + mutex_unlock(&bus->mdio_lock); ++#endif + + return 0; + } From 9a19ec79f9483cc26b91a59291bd8548bed58c67 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Fri, 5 Jan 2024 23:16:16 +0800 Subject: [PATCH 6/9] uboot-sunxi: bump to 2024.01 This version supports LPDDR4 DRAM of H618 SoC. Runtime-tested: Olimex Olinuxino Micro (A20) Orange Pi Zero 3 (H618) Pine64 SoPine (A64) Tested-by: Zoltan HERPAI Signed-off-by: Chukun Pan --- package/boot/uboot-sunxi/Makefile | 4 ++-- .../uboot-sunxi/patches/062-A20-improve-gmac-upload.patch | 2 +- ...00-mkimage-check-environment-for-dtc-binary-location.patch | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package/boot/uboot-sunxi/Makefile b/package/boot/uboot-sunxi/Makefile index 7f50992e69..de07dbdec2 100644 --- a/package/boot/uboot-sunxi/Makefile +++ b/package/boot/uboot-sunxi/Makefile @@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/kernel.mk -PKG_VERSION:=2023.04 +PKG_VERSION:=2024.01 -PKG_HASH:=e31cac91545ff41b71cec5d8c22afd695645cd6e2a442ccdacacd60534069341 +PKG_HASH:=b99611f1ed237bf3541bdc8434b68c96a6e05967061f992443cb30aabebef5b3 PKG_MAINTAINER:=Zoltan HERPAI diff --git a/package/boot/uboot-sunxi/patches/062-A20-improve-gmac-upload.patch b/package/boot/uboot-sunxi/patches/062-A20-improve-gmac-upload.patch index 13a703f307..a1caf18a18 100644 --- a/package/boot/uboot-sunxi/patches/062-A20-improve-gmac-upload.patch +++ b/package/boot/uboot-sunxi/patches/062-A20-improve-gmac-upload.patch @@ -2,7 +2,7 @@ --- a/configs/A20-OLinuXino-Lime2_defconfig +++ b/configs/A20-OLinuXino-Lime2_defconfig -@@ -26,6 +26,7 @@ CONFIG_ETH_DESIGNWARE=y +@@ -25,6 +25,7 @@ CONFIG_ETH_DESIGNWARE=y CONFIG_RGMII=y CONFIG_MII=y CONFIG_SUN7I_GMAC=y diff --git a/package/boot/uboot-sunxi/patches/200-mkimage-check-environment-for-dtc-binary-location.patch b/package/boot/uboot-sunxi/patches/200-mkimage-check-environment-for-dtc-binary-location.patch index fcc30ce35c..0307d6b99b 100644 --- a/package/boot/uboot-sunxi/patches/200-mkimage-check-environment-for-dtc-binary-location.patch +++ b/package/boot/uboot-sunxi/patches/200-mkimage-check-environment-for-dtc-binary-location.patch @@ -17,7 +17,7 @@ Cc: Simon Glass --- a/tools/fit_image.c +++ b/tools/fit_image.c -@@ -754,9 +754,14 @@ static int fit_handle_file(struct image_ +@@ -774,9 +774,14 @@ static int fit_handle_file(struct image_ } *cmd = '\0'; } else if (params->datafile) { From 85b156c11318005fe56dcfbc47adf86a947be497 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Fri, 8 Dec 2023 23:10:21 +0800 Subject: [PATCH 7/9] generic: 6.1: backport AXP PMIC support Backport AXP15060, AXP313a and AXP192 support. The AXP15060 PMIC is used for starfive boards, and the AXP313a PMIC is used for sunxi boards. Remove conflicting patches from starfive target. Signed-off-by: Chukun Pan --- ...ix-order-of-pek-rise-and-fall-events.patch | 80 ++ ...0x-Switch-to-the-sys-off-handler-API.patch | 82 ++ ...fd-axp20x-Fix-axp288-writable-ranges.patch | 28 + ...axp20x-Add-support-for-AXP15060-PMIC.patch | 343 ++++++ ...-axp20x-Add-support-for-AXP313a-PMIC.patch | 256 +++++ ...p20x-Add-support-for-AXP313a-variant.patch | 129 +++ ...gulator-axp20x-Add-AXP15060-support.patch} | 159 +-- ....5-mfd-axp20x-Add-support-for-AXP192.patch | 383 +++++++ ...-mfd-axp20x-Add-support-for-AXP15060.patch | 1014 ----------------- 9 files changed, 1347 insertions(+), 1127 deletions(-) create mode 100644 target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch create mode 100644 target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch create mode 100644 target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch create mode 100644 target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch create mode 100644 target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch create mode 100644 target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch rename target/linux/{starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch => generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch} (74%) create mode 100644 target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch delete mode 100644 target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch diff --git a/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch b/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch new file mode 100644 index 0000000000..23681ba937 --- /dev/null +++ b/target/linux/generic/backport-6.1/880-v6.3-mfd-axp20x-Fix-order-of-pek-rise-and-fall-events.patch @@ -0,0 +1,80 @@ +From 8781ba7f45695af3ab8e8d1b55a31f527c9201a3 Mon Sep 17 00:00:00 2001 +From: Aren Moynihan +Date: Thu, 8 Dec 2022 17:02:26 -0500 +Subject: [PATCH] mfd: axp20x: Fix order of pek rise and fall events + +The power button can get "stuck" if the rising edge and falling edge irq +are read in the same pass. This can often be triggered when resuming +from suspend if the power button is released before the kernel handles +the interrupt. + +Swapping the order of the rise and fall events makes sure that the press +event is handled first, which prevents this situation. + +Signed-off-by: Aren Moynihan +Reviewed-by: Samuel Holland +Tested-by: Samuel Holland +Acked-by: Chen-Yu Tsai +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20221208220225.635414-1-aren@peacevolution.org +--- + include/linux/mfd/axp20x.h | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -432,8 +432,9 @@ enum { + AXP152_IRQ_PEK_SHORT, + AXP152_IRQ_PEK_LONG, + AXP152_IRQ_TIMER, +- AXP152_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP152_IRQ_PEK_FAL_EDGE, ++ AXP152_IRQ_PEK_RIS_EDGE, + AXP152_IRQ_GPIO3_INPUT, + AXP152_IRQ_GPIO2_INPUT, + AXP152_IRQ_GPIO1_INPUT, +@@ -472,8 +473,9 @@ enum { + AXP20X_IRQ_LOW_PWR_LVL1, + AXP20X_IRQ_LOW_PWR_LVL2, + AXP20X_IRQ_TIMER, +- AXP20X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP20X_IRQ_PEK_FAL_EDGE, ++ AXP20X_IRQ_PEK_RIS_EDGE, + AXP20X_IRQ_GPIO3_INPUT, + AXP20X_IRQ_GPIO2_INPUT, + AXP20X_IRQ_GPIO1_INPUT, +@@ -502,8 +504,9 @@ enum axp22x_irqs { + AXP22X_IRQ_LOW_PWR_LVL1, + AXP22X_IRQ_LOW_PWR_LVL2, + AXP22X_IRQ_TIMER, +- AXP22X_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP22X_IRQ_PEK_FAL_EDGE, ++ AXP22X_IRQ_PEK_RIS_EDGE, + AXP22X_IRQ_GPIO1_INPUT, + AXP22X_IRQ_GPIO0_INPUT, + }; +@@ -571,8 +574,9 @@ enum axp803_irqs { + AXP803_IRQ_LOW_PWR_LVL1, + AXP803_IRQ_LOW_PWR_LVL2, + AXP803_IRQ_TIMER, +- AXP803_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP803_IRQ_PEK_FAL_EDGE, ++ AXP803_IRQ_PEK_RIS_EDGE, + AXP803_IRQ_PEK_SHORT, + AXP803_IRQ_PEK_LONG, + AXP803_IRQ_PEK_OVER_OFF, +@@ -623,8 +627,9 @@ enum axp809_irqs { + AXP809_IRQ_LOW_PWR_LVL1, + AXP809_IRQ_LOW_PWR_LVL2, + AXP809_IRQ_TIMER, +- AXP809_IRQ_PEK_RIS_EDGE, ++ /* out of bit order to make sure the press event is handled first */ + AXP809_IRQ_PEK_FAL_EDGE, ++ AXP809_IRQ_PEK_RIS_EDGE, + AXP809_IRQ_PEK_SHORT, + AXP809_IRQ_PEK_LONG, + AXP809_IRQ_PEK_OVER_OFF, diff --git a/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch b/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch new file mode 100644 index 0000000000..b742276c8a --- /dev/null +++ b/target/linux/generic/backport-6.1/881-v6.3-mfd-axp20x-Switch-to-the-sys-off-handler-API.patch @@ -0,0 +1,82 @@ +From 1b1305e95e85624f538ec56db9acf88e2d3d7397 Mon Sep 17 00:00:00 2001 +From: Samuel Holland +Date: Wed, 28 Dec 2022 10:27:52 -0600 +Subject: [PATCH] mfd: axp20x: Switch to the sys-off handler API + +This removes a layer of indirection through pm_power_off() and allows +the PMIC handler to be used as a fallback when firmware power off fails. +This happens on boards like the Clockwork DevTerm R-01 where OpenSBI +does not know how to use the PMIC to power off the board. + +Move the check for AXP288 to avoid registering a dummy handler. + +Signed-off-by: Samuel Holland +[Lee: Removed superfluous new line] +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20221228162752.14204-1-samuel@sholland.org +--- + drivers/mfd/axp20x.c | 27 +++++++++++---------------- + 1 file changed, 11 insertions(+), 16 deletions(-) + +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -23,7 +23,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +@@ -832,17 +832,16 @@ static const struct mfd_cell axp813_cell + }, + }; + +-static struct axp20x_dev *axp20x_pm_power_off; +-static void axp20x_power_off(void) ++static int axp20x_power_off(struct sys_off_data *data) + { +- if (axp20x_pm_power_off->variant == AXP288_ID) +- return; ++ struct axp20x_dev *axp20x = data->cb_data; + +- regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, +- AXP20X_OFF); ++ regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ + mdelay(500); ++ ++ return NOTIFY_DONE; + } + + int axp20x_match_device(struct axp20x_dev *axp20x) +@@ -1009,10 +1008,11 @@ int axp20x_device_probe(struct axp20x_de + return ret; + } + +- if (!pm_power_off) { +- axp20x_pm_power_off = axp20x; +- pm_power_off = axp20x_power_off; +- } ++ if (axp20x->variant != AXP288_ID) ++ devm_register_sys_off_handler(axp20x->dev, ++ SYS_OFF_MODE_POWER_OFF, ++ SYS_OFF_PRIO_DEFAULT, ++ axp20x_power_off, axp20x); + + dev_info(axp20x->dev, "AXP20X driver loaded\n"); + +@@ -1022,11 +1022,6 @@ EXPORT_SYMBOL(axp20x_device_probe); + + void axp20x_device_remove(struct axp20x_dev *axp20x) + { +- if (axp20x == axp20x_pm_power_off) { +- axp20x_pm_power_off = NULL; +- pm_power_off = NULL; +- } +- + mfd_remove_devices(axp20x->dev); + regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); + } diff --git a/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch b/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch new file mode 100644 index 0000000000..b84815e1a8 --- /dev/null +++ b/target/linux/generic/backport-6.1/882-v6.3-mfd-axp20x-Fix-axp288-writable-ranges.patch @@ -0,0 +1,28 @@ +From 2405fbfb384ef39e9560d76d3f6e4c90519f90aa Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Wed, 29 Mar 2023 22:55:44 +0200 +Subject: [PATCH] mfd: axp20x: Fix axp288 writable-ranges + +Register AXP288_POWER_REASON is writable and needs to be written +to reset the reset- / power-on-reason bits. + +Add it to the axp288 writable-ranges so that the extcon-axp288 +driver can properly clear the reset- / power-on-reason bits. + +Signed-off-by: Hans de Goede +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/20230329205544.1051393-1-hdegoede@redhat.com +--- + drivers/mfd/axp20x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -119,6 +119,7 @@ static const struct regmap_access_table + + /* AXP288 ranges are shared with the AXP803, as they cover the same range */ + static const struct regmap_range axp288_writeable_ranges[] = { ++ regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), + regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), + }; diff --git a/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch b/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch new file mode 100644 index 0000000000..83ef60aecd --- /dev/null +++ b/target/linux/generic/backport-6.1/883-v6.4-mfd-axp20x-Add-support-for-AXP15060-PMIC.patch @@ -0,0 +1,343 @@ +From e0f8ad2a705367518b5c56bf9d6da89681467c02 Mon Sep 17 00:00:00 2001 +From: Shengyu Qu +Date: Fri, 21 Apr 2023 23:08:15 +0800 +Subject: [PATCH] mfd: axp20x: Add support for AXP15060 PMIC + +The AXP15060 is a PMIC chip produced by X-Powers, and could be connected +via an I2C bus. + +Describe the regmap and the MFD bits, along with the registers exposed +via I2C. Eventually advertise the device using a new compatible string +and add support for power off the system. + +The driver would disable PEK function if IRQ is not configured in device +tree, since some boards (For example, Starfive Visionfive 2) didn't +connect IRQ line of PMIC to SOC. + +GPIO function isn't enabled in this commit, since its configuration +operation is different from any existing AXP PMICs and needs +logic modification on existing driver. GPIO support might come in later +patches. + +Signed-off-by: Shengyu Qu +Reviewed-by: Krzysztof Kozlowski +Signed-off-by: Lee Jones +Link: https://lore.kernel.org/r/TY3P286MB261162D57695AC8164ED50E298609@TY3P286MB2611.JPNP286.PROD.OUTLOOK.COM +--- + drivers/mfd/axp20x-i2c.c | 2 + + drivers/mfd/axp20x.c | 107 +++++++++++++++++++++++++++++++++++++ + include/linux/mfd/axp20x.h | 85 +++++++++++++++++++++++++++++ + 3 files changed, 194 insertions(+) + +--- a/drivers/mfd/axp20x-i2c.c ++++ b/drivers/mfd/axp20x-i2c.c +@@ -66,6 +66,7 @@ static const struct of_device_id axp20x_ + { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, + { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, + { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, ++ { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, + { }, + }; + MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); +@@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x + { "axp223", 0 }, + { "axp803", 0 }, + { "axp806", 0 }, ++ { "axp15060", 0 }, + { }, + }; + MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -43,6 +43,7 @@ static const char * const axp20x_model_n + "AXP806", + "AXP809", + "AXP813", ++ "AXP15060", + }; + + static const struct regmap_range axp152_writeable_ranges[] = { +@@ -169,6 +170,31 @@ static const struct regmap_access_table + .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), + }; + ++static const struct regmap_range axp15060_writeable_ranges[] = { ++ regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), ++ regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), ++ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), ++ regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), ++ regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), ++ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), ++}; ++ ++static const struct regmap_range axp15060_volatile_ranges[] = { ++ regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), ++ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), ++ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), ++}; ++ ++static const struct regmap_access_table axp15060_writeable_table = { ++ .yes_ranges = axp15060_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp15060_volatile_table = { ++ .yes_ranges = axp15060_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges), ++}; ++ + static const struct resource axp152_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +@@ -237,6 +263,11 @@ static const struct resource axp809_pek_ + DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), + }; + ++static const struct resource axp15060_pek_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"), ++ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"), ++}; ++ + static const struct regmap_config axp152_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -282,6 +313,15 @@ static const struct regmap_config axp806 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp15060_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp15060_writeable_table, ++ .volatile_table = &axp15060_volatile_table, ++ .max_register = AXP15060_IRQ2_STATE, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ + [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } + +@@ -503,6 +543,23 @@ static const struct regmap_irq axp809_re + INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), + }; + ++static const struct regmap_irq axp15060_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0), ++ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1), ++ INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2), ++ INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3), ++ INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4), ++ INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5), ++ INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6), ++ INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7), ++ INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0), ++ INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1), ++ INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2), ++ INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3), ++ INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4), ++ INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5), ++}; ++ + static const struct regmap_irq_chip axp152_regmap_irq_chip = { + .name = "axp152_irq_chip", + .status_base = AXP152_IRQ1_STATE, +@@ -589,6 +646,17 @@ static const struct regmap_irq_chip axp8 + .num_regs = 5, + }; + ++static const struct regmap_irq_chip axp15060_regmap_irq_chip = { ++ .name = "axp15060", ++ .status_base = AXP15060_IRQ1_STATE, ++ .ack_base = AXP15060_IRQ1_STATE, ++ .unmask_base = AXP15060_IRQ1_EN, ++ .init_ack_masked = true, ++ .irqs = axp15060_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs), ++ .num_regs = 2, ++}; ++ + static const struct mfd_cell axp20x_cells[] = { + { + .name = "axp20x-gpio", +@@ -833,6 +901,23 @@ static const struct mfd_cell axp813_cell + }, + }; + ++static const struct mfd_cell axp15060_cells[] = { ++ { ++ .name = "axp221-pek", ++ .num_resources = ARRAY_SIZE(axp15060_pek_resources), ++ .resources = axp15060_pek_resources, ++ }, { ++ .name = "axp20x-regulator", ++ }, ++}; ++ ++/* For boards that don't have IRQ line connected to SOC. */ ++static const struct mfd_cell axp_regulator_only_cells[] = { ++ { ++ .name = "axp20x-regulator", ++ }, ++}; ++ + static int axp20x_power_off(struct sys_off_data *data) + { + struct axp20x_dev *axp20x = data->cb_data; +@@ -942,6 +1027,28 @@ int axp20x_match_device(struct axp20x_de + */ + axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; + break; ++ case AXP15060_ID: ++ /* ++ * Don't register the power key part if there is no interrupt ++ * line. ++ * ++ * Since most use cases of AXP PMICs are Allwinner SOCs, board ++ * designers follow Allwinner's reference design and connects ++ * IRQ line to SOC, there's no need for those variants to deal ++ * with cases that IRQ isn't connected. However, AXP15660 is ++ * used by some other vendors' SOCs that didn't connect IRQ ++ * line, we need to deal with this case. ++ */ ++ if (axp20x->irq > 0) { ++ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); ++ axp20x->cells = axp15060_cells; ++ } else { ++ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); ++ axp20x->cells = axp_regulator_only_cells; ++ } ++ axp20x->regmap_cfg = &axp15060_regmap_config; ++ axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; ++ break; + default: + dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); + return -EINVAL; +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -21,6 +21,7 @@ enum axp20x_variants { + AXP806_ID, + AXP809_ID, + AXP813_ID, ++ AXP15060_ID, + NR_AXP20X_VARIANTS, + }; + +@@ -131,6 +132,39 @@ enum axp20x_variants { + /* Other DCDC regulator control registers are the same as AXP803 */ + #define AXP813_DCDC7_V_OUT 0x26 + ++#define AXP15060_STARTUP_SRC 0x00 ++#define AXP15060_PWR_OUT_CTRL1 0x10 ++#define AXP15060_PWR_OUT_CTRL2 0x11 ++#define AXP15060_PWR_OUT_CTRL3 0x12 ++#define AXP15060_DCDC1_V_CTRL 0x13 ++#define AXP15060_DCDC2_V_CTRL 0x14 ++#define AXP15060_DCDC3_V_CTRL 0x15 ++#define AXP15060_DCDC4_V_CTRL 0x16 ++#define AXP15060_DCDC5_V_CTRL 0x17 ++#define AXP15060_DCDC6_V_CTRL 0x18 ++#define AXP15060_ALDO1_V_CTRL 0x19 ++#define AXP15060_DCDC_MODE_CTRL1 0x1a ++#define AXP15060_DCDC_MODE_CTRL2 0x1b ++#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e ++#define AXP15060_IRQ_PWROK_VOFF 0x1f ++#define AXP15060_ALDO2_V_CTRL 0x20 ++#define AXP15060_ALDO3_V_CTRL 0x21 ++#define AXP15060_ALDO4_V_CTRL 0x22 ++#define AXP15060_ALDO5_V_CTRL 0x23 ++#define AXP15060_BLDO1_V_CTRL 0x24 ++#define AXP15060_BLDO2_V_CTRL 0x25 ++#define AXP15060_BLDO3_V_CTRL 0x26 ++#define AXP15060_BLDO4_V_CTRL 0x27 ++#define AXP15060_BLDO5_V_CTRL 0x28 ++#define AXP15060_CLDO1_V_CTRL 0x29 ++#define AXP15060_CLDO2_V_CTRL 0x2a ++#define AXP15060_CLDO3_V_CTRL 0x2b ++#define AXP15060_CLDO4_V_CTRL 0x2d ++#define AXP15060_CPUSLDO_V_CTRL 0x2e ++#define AXP15060_PWR_WAKEUP_CTRL 0x31 ++#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32 ++#define AXP15060_PEK_KEY 0x36 ++ + /* Interrupt */ + #define AXP152_IRQ1_EN 0x40 + #define AXP152_IRQ2_EN 0x41 +@@ -152,6 +186,11 @@ enum axp20x_variants { + #define AXP20X_IRQ5_STATE 0x4c + #define AXP20X_IRQ6_STATE 0x4d + ++#define AXP15060_IRQ1_EN 0x40 ++#define AXP15060_IRQ2_EN 0x41 ++#define AXP15060_IRQ1_STATE 0x48 ++#define AXP15060_IRQ2_STATE 0x49 ++ + /* ADC */ + #define AXP20X_ACIN_V_ADC_H 0x56 + #define AXP20X_ACIN_V_ADC_L 0x57 +@@ -222,6 +261,8 @@ enum axp20x_variants { + #define AXP22X_GPIO_STATE 0x94 + #define AXP22X_GPIO_PULL_DOWN 0x95 + ++#define AXP15060_CLDO4_GPIO2_MODESET 0x2c ++ + /* Battery */ + #define AXP20X_CHRG_CC_31_24 0xb0 + #define AXP20X_CHRG_CC_23_16 0xb1 +@@ -419,6 +460,33 @@ enum { + AXP813_REG_ID_MAX, + }; + ++enum { ++ AXP15060_DCDC1 = 0, ++ AXP15060_DCDC2, ++ AXP15060_DCDC3, ++ AXP15060_DCDC4, ++ AXP15060_DCDC5, ++ AXP15060_DCDC6, ++ AXP15060_ALDO1, ++ AXP15060_ALDO2, ++ AXP15060_ALDO3, ++ AXP15060_ALDO4, ++ AXP15060_ALDO5, ++ AXP15060_BLDO1, ++ AXP15060_BLDO2, ++ AXP15060_BLDO3, ++ AXP15060_BLDO4, ++ AXP15060_BLDO5, ++ AXP15060_CLDO1, ++ AXP15060_CLDO2, ++ AXP15060_CLDO3, ++ AXP15060_CLDO4, ++ AXP15060_CPUSLDO, ++ AXP15060_SW, ++ AXP15060_RTC_LDO, ++ AXP15060_REG_ID_MAX, ++}; ++ + /* IRQs */ + enum { + AXP152_IRQ_LDO0IN_CONNECT = 1, +@@ -637,6 +705,23 @@ enum axp809_irqs { + AXP809_IRQ_GPIO0_INPUT, + }; + ++enum axp15060_irqs { ++ AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1, ++ AXP15060_IRQ_DIE_TEMP_HIGH_LV2, ++ AXP15060_IRQ_DCDC1_V_LOW, ++ AXP15060_IRQ_DCDC2_V_LOW, ++ AXP15060_IRQ_DCDC3_V_LOW, ++ AXP15060_IRQ_DCDC4_V_LOW, ++ AXP15060_IRQ_DCDC5_V_LOW, ++ AXP15060_IRQ_DCDC6_V_LOW, ++ AXP15060_IRQ_PEK_LONG, ++ AXP15060_IRQ_PEK_SHORT, ++ AXP15060_IRQ_GPIO1_INPUT, ++ AXP15060_IRQ_PEK_FAL_EDGE, ++ AXP15060_IRQ_PEK_RIS_EDGE, ++ AXP15060_IRQ_GPIO2_INPUT, ++}; ++ + struct axp20x_dev { + struct device *dev; + int irq; diff --git a/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch b/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch new file mode 100644 index 0000000000..c9470eacec --- /dev/null +++ b/target/linux/generic/backport-6.1/884-v6.5-mfd-axp20x-Add-support-for-AXP313a-PMIC.patch @@ -0,0 +1,256 @@ +From 75c8cb2f4cb218aaf4ea68cab08d6dbc96eeae15 Mon Sep 17 00:00:00 2001 +From: Martin Botka +Date: Wed, 24 May 2023 01:00:10 +0100 +Subject: [PATCH] mfd: axp20x: Add support for AXP313a PMIC + +The AXP313a is a PMIC chip produced by X-Powers, it can be connected via +an I2C bus. +The name AXP1530 seems to appear as well, and this is what is used in +the BSP driver. From all we know it's the same chip, just a different +name. However we have only seen AXP313a chips in the wild, so go with +this name. + +Compared to the other AXP PMICs it's a rather simple affair: just three +DCDC converters, three LDOs, and no battery charging support. + +Describe the regmap and the MFD bits, along with the registers exposed +via I2C. Aside from the various regulators, also describe the power key +interrupts, and adjust the shutdown handler routine to use a different +register than the other PMICs. +Eventually advertise the device using the new compatible string. + +Signed-off-by: Martin Botka +Signed-off-by: Andre Przywara +Reviewed-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20230524000012.15028-2-andre.przywara@arm.com +Signed-off-by: Lee Jones +--- + drivers/mfd/axp20x-i2c.c | 2 + + drivers/mfd/axp20x.c | 78 +++++++++++++++++++++++++++++++++++++- + include/linux/mfd/axp20x.h | 32 ++++++++++++++++ + 3 files changed, 111 insertions(+), 1 deletion(-) + +--- a/drivers/mfd/axp20x-i2c.c ++++ b/drivers/mfd/axp20x-i2c.c +@@ -64,6 +64,7 @@ static const struct of_device_id axp20x_ + { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, + { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, + { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, ++ { .compatible = "x-powers,axp313a", .data = (void *)AXP313A_ID }, + { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, + { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, + { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, +@@ -78,6 +79,7 @@ static const struct i2c_device_id axp20x + { "axp209", 0 }, + { "axp221", 0 }, + { "axp223", 0 }, ++ { "axp313a", 0 }, + { "axp803", 0 }, + { "axp806", 0 }, + { "axp15060", 0 }, +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -39,6 +39,7 @@ static const char * const axp20x_model_n + "AXP221", + "AXP223", + "AXP288", ++ "AXP313a", + "AXP803", + "AXP806", + "AXP809", +@@ -156,6 +157,25 @@ static const struct regmap_range axp806_ + regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), + }; + ++static const struct regmap_range axp313a_writeable_ranges[] = { ++ regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE), ++}; ++ ++static const struct regmap_range axp313a_volatile_ranges[] = { ++ regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL), ++ regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE), ++}; ++ ++static const struct regmap_access_table axp313a_writeable_table = { ++ .yes_ranges = axp313a_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp313a_volatile_table = { ++ .yes_ranges = axp313a_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), ++}; ++ + static const struct regmap_range axp806_volatile_ranges[] = { + regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), + }; +@@ -248,6 +268,11 @@ static const struct resource axp288_fuel + DEFINE_RES_IRQ(AXP288_IRQ_WL1), + }; + ++static const struct resource axp313a_pek_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"), ++ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), ++}; ++ + static const struct resource axp803_pek_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), + DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), +@@ -304,6 +329,15 @@ static const struct regmap_config axp288 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp313a_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp313a_writeable_table, ++ .volatile_table = &axp313a_volatile_table, ++ .max_register = AXP313A_IRQ_STATE, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static const struct regmap_config axp806_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -456,6 +490,16 @@ static const struct regmap_irq axp288_re + INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), + }; + ++static const struct regmap_irq axp313a_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7), ++ INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6), ++ INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5), ++ INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4), ++ INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3), ++ INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2), ++ INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), ++}; ++ + static const struct regmap_irq axp803_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), +@@ -610,6 +654,17 @@ static const struct regmap_irq_chip axp2 + + }; + ++static const struct regmap_irq_chip axp313a_regmap_irq_chip = { ++ .name = "axp313a_irq_chip", ++ .status_base = AXP313A_IRQ_STATE, ++ .ack_base = AXP313A_IRQ_STATE, ++ .unmask_base = AXP313A_IRQ_EN, ++ .init_ack_masked = true, ++ .irqs = axp313a_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs), ++ .num_regs = 1, ++}; ++ + static const struct regmap_irq_chip axp803_regmap_irq_chip = { + .name = "axp803", + .status_base = AXP20X_IRQ1_STATE, +@@ -752,6 +807,11 @@ static const struct mfd_cell axp152_cell + }, + }; + ++static struct mfd_cell axp313a_cells[] = { ++ MFD_CELL_NAME("axp20x-regulator"), ++ MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), ++}; ++ + static const struct resource axp288_adc_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), + }; +@@ -921,8 +981,18 @@ static const struct mfd_cell axp_regulat + static int axp20x_power_off(struct sys_off_data *data) + { + struct axp20x_dev *axp20x = data->cb_data; ++ unsigned int shutdown_reg; + +- regmap_write(axp20x->regmap, AXP20X_OFF_CTRL, AXP20X_OFF); ++ switch (axp20x->variant) { ++ case AXP313A_ID: ++ shutdown_reg = AXP313A_SHUTDOWN_CTRL; ++ break; ++ default: ++ shutdown_reg = AXP20X_OFF_CTRL; ++ break; ++ } ++ ++ regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF); + + /* Give capacitors etc. time to drain to avoid kernel panic msg. */ + mdelay(500); +@@ -985,6 +1055,12 @@ int axp20x_match_device(struct axp20x_de + axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; + axp20x->irq_flags = IRQF_TRIGGER_LOW; + break; ++ case AXP313A_ID: ++ axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); ++ axp20x->cells = axp313a_cells; ++ axp20x->regmap_cfg = &axp313a_regmap_config; ++ axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; ++ break; + case AXP803_ID: + axp20x->nr_cells = ARRAY_SIZE(axp803_cells); + axp20x->cells = axp803_cells; +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -17,6 +17,7 @@ enum axp20x_variants { + AXP221_ID, + AXP223_ID, + AXP288_ID, ++ AXP313A_ID, + AXP803_ID, + AXP806_ID, + AXP809_ID, +@@ -92,6 +93,17 @@ enum axp20x_variants { + #define AXP22X_ALDO3_V_OUT 0x2a + #define AXP22X_CHRG_CTRL3 0x35 + ++#define AXP313A_ON_INDICATE 0x00 ++#define AXP313A_OUTPUT_CONTROL 0x10 ++#define AXP313A_DCDC1_CONRTOL 0x13 ++#define AXP313A_DCDC2_CONRTOL 0x14 ++#define AXP313A_DCDC3_CONRTOL 0x15 ++#define AXP313A_ALDO1_CONRTOL 0x16 ++#define AXP313A_DLDO1_CONRTOL 0x17 ++#define AXP313A_SHUTDOWN_CTRL 0x1a ++#define AXP313A_IRQ_EN 0x20 ++#define AXP313A_IRQ_STATE 0x21 ++ + #define AXP806_STARTUP_SRC 0x00 + #define AXP806_CHIP_ID 0x03 + #define AXP806_PWR_OUT_CTRL1 0x10 +@@ -364,6 +376,16 @@ enum { + }; + + enum { ++ AXP313A_DCDC1 = 0, ++ AXP313A_DCDC2, ++ AXP313A_DCDC3, ++ AXP313A_ALDO1, ++ AXP313A_DLDO1, ++ AXP313A_RTC_LDO, ++ AXP313A_REG_ID_MAX, ++}; ++ ++enum { + AXP806_DCDCA = 0, + AXP806_DCDCB, + AXP806_DCDCC, +@@ -616,6 +638,16 @@ enum axp288_irqs { + AXP288_IRQ_BC_USB_CHNG, + }; + ++enum axp313a_irqs { ++ AXP313A_IRQ_DIE_TEMP_HIGH, ++ AXP313A_IRQ_DCDC2_V_LOW = 2, ++ AXP313A_IRQ_DCDC3_V_LOW, ++ AXP313A_IRQ_PEK_LONG, ++ AXP313A_IRQ_PEK_SHORT, ++ AXP313A_IRQ_PEK_FAL_EDGE, ++ AXP313A_IRQ_PEK_RIS_EDGE, ++}; ++ + enum axp803_irqs { + AXP803_IRQ_ACIN_OVER_V = 1, + AXP803_IRQ_ACIN_PLUGIN, diff --git a/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch b/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch new file mode 100644 index 0000000000..91f1b39824 --- /dev/null +++ b/target/linux/generic/backport-6.1/885-v6.5-regulator-axp20x-Add-support-for-AXP313a-variant.patch @@ -0,0 +1,129 @@ +From 60fd7eb89670d2636ac3156881acbd103c6eba6a Mon Sep 17 00:00:00 2001 +From: Martin Botka +Date: Wed, 24 May 2023 01:00:11 +0100 +Subject: [PATCH] regulator: axp20x: Add support for AXP313a variant + +The AXP313a is your typical I2C controlled PMIC, although in a lighter +fashion compared to the other X-Powers PMICs: it has only three DCDC +rails, three LDOs, and no battery charging support. + +The AXP313a datasheet does not describe a register to change the DCDC +switching frequency, and talks of it being fixed at 3 MHz. Check that +the property allowing to change that frequency is absent from the DT, +and bail out otherwise. + +The third LDO, RTCLDO, is fixed, and cannot even be turned on or off, +programmatically. On top of that, its voltage is customisable (either +1.8V or 3.3V), which we cannot describe easily using the existing +regulator wrapper functions. This should be fixed properly, using +regulator-{min,max}-microvolt in the DT, but this requires more changes +to the code. As some other PMICs (AXP2xx, AXP803) seem to paper over the +same problem as well, we follow suit here and pretend it's a fixed 1.8V +regulator. A proper fix can follow later. The BSP code seems to ignore +this regulator altogether. + +Describe the AXP313A's voltage settings and switch registers, how the +voltages are encoded, and connect this to the MFD device via its +regulator ID. + +Signed-off-by: Martin Botka +Signed-off-by: Andre Przywara +Reviewed-by: Chen-Yu Tsai +Reviewed-by: Mark Brown +Tested-by: Shengyu Qu +Link: https://lore.kernel.org/r/20230524000012.15028-3-andre.przywara@arm.com +Signed-off-by: Mark Brown +--- + drivers/regulator/axp20x-regulator.c | 60 ++++++++++++++++++++++++++++ + 1 file changed, 60 insertions(+) + +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -134,6 +134,11 @@ + #define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6) + #define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7) + ++#define AXP313A_DCDC1_NUM_VOLTAGES 107 ++#define AXP313A_DCDC23_NUM_VOLTAGES 88 ++#define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) ++#define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) ++ + #define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0) + #define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1) + #define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2) +@@ -638,6 +643,48 @@ static const struct regulator_desc axp22 + .ops = &axp20x_ops_sw, + }; + ++static const struct linear_range axp313a_dcdc1_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), ++ REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000), ++}; ++ ++static const struct linear_range axp313a_dcdc2_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), ++}; ++ ++/* ++ * This is deviating from the datasheet. The values here are taken from the ++ * BSP driver and have been confirmed by measurements. ++ */ ++static const struct linear_range axp313a_dcdc3_ranges[] = { ++ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), ++ REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), ++}; ++ ++static const struct regulator_desc axp313a_regulators[] = { ++ AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1", ++ axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES, ++ AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(0)), ++ AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2", ++ axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES, ++ AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(1)), ++ AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3", ++ axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES, ++ AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(2)), ++ AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100, ++ AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(3)), ++ AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100, ++ AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, ++ AXP313A_OUTPUT_CONTROL, BIT(4)), ++ AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), ++}; ++ + /* DCDC ranges shared with AXP813 */ + static const struct linear_range axp803_dcdc234_ranges[] = { + REGULATOR_LINEAR_RANGE(500000, +@@ -1040,6 +1087,15 @@ static int axp20x_set_dcdc_freq(struct p + def = 3000; + step = 150; + break; ++ case AXP313A_ID: ++ /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ ++ if (dcdcfreq != 0) { ++ dev_err(&pdev->dev, ++ "DCDC frequency on AXP313a is fixed to 3 MHz.\n"); ++ return -EINVAL; ++ } ++ ++ return 0; + default: + dev_err(&pdev->dev, + "Setting DCDC frequency for unsupported AXP variant\n"); +@@ -1232,6 +1288,10 @@ static int axp20x_regulator_probe(struct + drivevbus = of_property_read_bool(pdev->dev.parent->of_node, + "x-powers,drive-vbus-en"); + break; ++ case AXP313A_ID: ++ regulators = axp313a_regulators; ++ nregulators = AXP313A_REG_ID_MAX; ++ break; + case AXP803_ID: + regulators = axp803_regulators; + nregulators = AXP803_REG_ID_MAX; diff --git a/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch b/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch similarity index 74% rename from target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch rename to target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch index ccb277b3a0..6af09204af 100644 --- a/target/linux/starfive/patches-6.1/0118-driver-regulator-axp20x-Support-AXP15060-variant.patch +++ b/target/linux/generic/backport-6.1/886-v6.5-regulator-axp20x-Add-AXP15060-support.patch @@ -1,30 +1,35 @@ -From 1b017f3376a5df4a2cd5a120c16723e777fc9a36 Mon Sep 17 00:00:00 2001 -From: "ziv.xu" -Date: Fri, 4 Aug 2023 13:55:23 +0800 -Subject: [PATCH 118/122] driver: regulator: axp20x: Support AXP15060 variant. +From 9e72869d0fe12aba8cd489e485d93912b3f5c248 Mon Sep 17 00:00:00 2001 +From: Shengyu Qu +Date: Wed, 24 May 2023 01:00:12 +0100 +Subject: [PATCH] regulator: axp20x: Add AXP15060 support -Add axp15060 variant support to axp20x +The AXP15060 is a typical I2C-controlled PMIC, seen on multiple boards +with different default register value. Current driver is tested on +Starfive Visionfive 2. -Signed-off-by: ziv.xu +The RTCLDO is fixed, and cannot even be turned on or off. On top of +that, its voltage is customisable (either 1.8V or 3.3V). We pretend it's +a fixed 1.8V regulator since other AXP driver also do like this. Also, +BSP code ignores this regulator and it's not used according to VF2 +schematic. + +Describe the AXP15060's voltage settings and switch registers, how the +voltages are encoded, and connect this to the MFD device via its +regulator ID. + +Signed-off-by: Shengyu Qu +Signed-off-by: Andre Przywara +Reviewed-by: Mark Brown +Tested-by: Shengyu Qu +Link: https://lore.kernel.org/r/20230524000012.15028-4-andre.przywara@arm.com +Signed-off-by: Mark Brown --- - drivers/regulator/axp20x-regulator.c | 291 ++++++++++++++++++++++++++- - 1 file changed, 283 insertions(+), 8 deletions(-) + drivers/regulator/axp20x-regulator.c | 232 +++++++++++++++++++++++++-- + 1 file changed, 223 insertions(+), 9 deletions(-) --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c -@@ -134,6 +134,11 @@ - #define AXP22X_PWR_OUT_DLDO4_MASK BIT_MASK(6) - #define AXP22X_PWR_OUT_ALDO3_MASK BIT_MASK(7) - -+#define AXP313A_DCDC1_NUM_VOLTAGES 107 -+#define AXP313A_DCDC23_NUM_VOLTAGES 88 -+#define AXP313A_DCDC_V_OUT_MASK GENMASK(6, 0) -+#define AXP313A_LDO_V_OUT_MASK GENMASK(4, 0) -+ - #define AXP803_PWR_OUT_DCDC1_MASK BIT_MASK(0) - #define AXP803_PWR_OUT_DCDC2_MASK BIT_MASK(1) - #define AXP803_PWR_OUT_DCDC3_MASK BIT_MASK(2) -@@ -270,6 +275,74 @@ +@@ -275,6 +275,74 @@ #define AXP813_PWR_OUT_DCDC7_MASK BIT_MASK(6) @@ -99,56 +104,7 @@ Signed-off-by: ziv.xu #define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ _vmask, _ereg, _emask, _enable_val, _disable_val) \ [_family##_##_id] = { \ -@@ -638,6 +711,48 @@ static const struct regulator_desc axp22 - .ops = &axp20x_ops_sw, - }; - -+static const struct linear_range axp313a_dcdc1_ranges[] = { -+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), -+ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), -+ REGULATOR_LINEAR_RANGE(1600000, 88, 106, 100000), -+}; -+ -+static const struct linear_range axp313a_dcdc2_ranges[] = { -+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), -+ REGULATOR_LINEAR_RANGE(1220000, 71, 87, 20000), -+}; -+ -+/* -+ * This is deviating from the datasheet. The values here are taken from the -+ * BSP driver and have been confirmed by measurements. -+ */ -+static const struct linear_range axp313a_dcdc3_ranges[] = { -+ REGULATOR_LINEAR_RANGE(500000, 0, 70, 10000), -+ REGULATOR_LINEAR_RANGE(1220000, 71, 102, 20000), -+}; -+ -+static const struct regulator_desc axp313a_regulators[] = { -+ AXP_DESC_RANGES(AXP313A, DCDC1, "dcdc1", "vin1", -+ axp313a_dcdc1_ranges, AXP313A_DCDC1_NUM_VOLTAGES, -+ AXP313A_DCDC1_CONRTOL, AXP313A_DCDC_V_OUT_MASK, -+ AXP313A_OUTPUT_CONTROL, BIT(0)), -+ AXP_DESC_RANGES(AXP313A, DCDC2, "dcdc2", "vin2", -+ axp313a_dcdc2_ranges, AXP313A_DCDC23_NUM_VOLTAGES, -+ AXP313A_DCDC2_CONRTOL, AXP313A_DCDC_V_OUT_MASK, -+ AXP313A_OUTPUT_CONTROL, BIT(1)), -+ AXP_DESC_RANGES(AXP313A, DCDC3, "dcdc3", "vin3", -+ axp313a_dcdc3_ranges, AXP313A_DCDC23_NUM_VOLTAGES, -+ AXP313A_DCDC3_CONRTOL, AXP313A_DCDC_V_OUT_MASK, -+ AXP313A_OUTPUT_CONTROL, BIT(2)), -+ AXP_DESC(AXP313A, ALDO1, "aldo1", "vin1", 500, 3500, 100, -+ AXP313A_ALDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, -+ AXP313A_OUTPUT_CONTROL, BIT(3)), -+ AXP_DESC(AXP313A, DLDO1, "dldo1", "vin1", 500, 3500, 100, -+ AXP313A_DLDO1_CONRTOL, AXP313A_LDO_V_OUT_MASK, -+ AXP313A_OUTPUT_CONTROL, BIT(4)), -+ AXP_DESC_FIXED(AXP313A, RTC_LDO, "rtc-ldo", "vin1", 1800), -+}; -+ - /* DCDC ranges shared with AXP813 */ - static const struct linear_range axp803_dcdc234_ranges[] = { - REGULATOR_LINEAR_RANGE(500000, -@@ -1001,6 +1116,104 @@ static const struct regulator_desc axp81 +@@ -1048,6 +1116,104 @@ static const struct regulator_desc axp81 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_DC1SW_MASK), }; @@ -253,24 +209,20 @@ Signed-off-by: ziv.xu static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) { struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); -@@ -1040,6 +1253,16 @@ static int axp20x_set_dcdc_freq(struct p - def = 3000; +@@ -1088,10 +1254,11 @@ static int axp20x_set_dcdc_freq(struct p step = 150; break; -+ case AXP313A_ID: + case AXP313A_ID: + case AXP15060_ID: -+ /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ -+ if (dcdcfreq != 0) { -+ dev_err(&pdev->dev, + /* The DCDC PWM frequency seems to be fixed to 3 MHz. */ + if (dcdcfreq != 0) { + dev_err(&pdev->dev, +- "DCDC frequency on AXP313a is fixed to 3 MHz.\n"); + "DCDC frequency on this PMIC is fixed to 3 MHz.\n"); -+ return -EINVAL; -+ } -+ -+ return 0; - default: - dev_err(&pdev->dev, - "Setting DCDC frequency for unsupported AXP variant\n"); -@@ -1145,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(stru + return -EINVAL; + } + +@@ -1201,6 +1368,15 @@ static int axp20x_set_dcdc_workmode(stru workmode <<= id - AXP813_DCDC1; break; @@ -286,7 +238,7 @@ Signed-off-by: ziv.xu default: /* should not happen */ WARN_ON(1); -@@ -1164,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(st +@@ -1220,7 +1396,7 @@ static bool axp20x_is_polyphase_slave(st /* * Currently in our supported AXP variants, only AXP803, AXP806, @@ -295,7 +247,7 @@ Signed-off-by: ziv.xu */ switch (axp20x->variant) { case AXP803_ID: -@@ -1196,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(st +@@ -1252,6 +1428,17 @@ static bool axp20x_is_polyphase_slave(st } break; @@ -313,7 +265,7 @@ Signed-off-by: ziv.xu default: return false; } -@@ -1217,6 +1460,7 @@ static int axp20x_regulator_probe(struct +@@ -1273,6 +1460,7 @@ static int axp20x_regulator_probe(struct u32 workmode; const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name; const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name; @@ -321,18 +273,7 @@ Signed-off-by: ziv.xu bool drivevbus = false; switch (axp20x->variant) { -@@ -1232,6 +1476,10 @@ static int axp20x_regulator_probe(struct - drivevbus = of_property_read_bool(pdev->dev.parent->of_node, - "x-powers,drive-vbus-en"); - break; -+ case AXP313A_ID: -+ regulators = axp313a_regulators; -+ nregulators = AXP313A_REG_ID_MAX; -+ break; - case AXP803_ID: - regulators = axp803_regulators; - nregulators = AXP803_REG_ID_MAX; -@@ -1252,6 +1500,10 @@ static int axp20x_regulator_probe(struct +@@ -1312,6 +1500,10 @@ static int axp20x_regulator_probe(struct drivevbus = of_property_read_bool(pdev->dev.parent->of_node, "x-powers,drive-vbus-en"); break; @@ -343,7 +284,7 @@ Signed-off-by: ziv.xu default: dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", axp20x->variant); -@@ -1278,8 +1530,9 @@ static int axp20x_regulator_probe(struct +@@ -1338,8 +1530,9 @@ static int axp20x_regulator_probe(struct continue; /* @@ -355,7 +296,7 @@ Signed-off-by: ziv.xu * * We always register the regulators in proper sequence, * so the supply names are correctly read. See the last -@@ -1288,7 +1541,8 @@ static int axp20x_regulator_probe(struct +@@ -1348,7 +1541,8 @@ static int axp20x_regulator_probe(struct */ if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) || (regulators == axp803_regulators && i == AXP803_DC1SW) || @@ -365,7 +306,7 @@ Signed-off-by: ziv.xu new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) -@@ -1300,7 +1554,8 @@ static int axp20x_regulator_probe(struct +@@ -1360,7 +1554,8 @@ static int axp20x_regulator_probe(struct } if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) || @@ -375,7 +316,7 @@ Signed-off-by: ziv.xu new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL); if (!new_desc) -@@ -1311,6 +1566,18 @@ static int axp20x_regulator_probe(struct +@@ -1371,6 +1566,18 @@ static int axp20x_regulator_probe(struct desc = new_desc; } @@ -394,7 +335,7 @@ Signed-off-by: ziv.xu rdev = devm_regulator_register(&pdev->dev, desc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "Failed to register %s\n", -@@ -1329,19 +1596,26 @@ static int axp20x_regulator_probe(struct +@@ -1389,19 +1596,26 @@ static int axp20x_regulator_probe(struct } /* @@ -424,11 +365,3 @@ Signed-off-by: ziv.xu } if (drivevbus) { -@@ -1364,6 +1638,7 @@ static struct platform_driver axp20x_reg - .probe = axp20x_regulator_probe, - .driver = { - .name = "axp20x-regulator", -+ .probe_type = PROBE_PREFER_ASYNCHRONOUS, - }, - }; - diff --git a/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch b/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch new file mode 100644 index 0000000000..d75b4e7453 --- /dev/null +++ b/target/linux/generic/backport-6.1/887-v6.5-mfd-axp20x-Add-support-for-AXP192.patch @@ -0,0 +1,383 @@ +From 63eeabbc9dbddd7381409feccd9082e5ffabfe59 Mon Sep 17 00:00:00 2001 +From: Aidan MacDonald +Date: Thu, 11 May 2023 10:26:08 +0100 +Subject: [PATCH] mfd: axp20x: Add support for AXP192 + +The AXP192 PMIC is similar to the AXP202/AXP209, but with different +regulators, additional GPIOs, and a different IRQ register layout. + +Signed-off-by: Aidan MacDonald +Link: https://lore.kernel.org/r/20230511092609.76183-1-aidanmacdonald.0x0@gmail.com +Signed-off-by: Lee Jones +--- + drivers/mfd/axp20x-i2c.c | 2 + + drivers/mfd/axp20x.c | 141 +++++++++++++++++++++++++++++++++++++ + include/linux/mfd/axp20x.h | 84 ++++++++++++++++++++++ + 3 files changed, 227 insertions(+) + +--- a/drivers/mfd/axp20x-i2c.c ++++ b/drivers/mfd/axp20x-i2c.c +@@ -60,6 +60,7 @@ static void axp20x_i2c_remove(struct i2c + #ifdef CONFIG_OF + static const struct of_device_id axp20x_i2c_of_match[] = { + { .compatible = "x-powers,axp152", .data = (void *)AXP152_ID }, ++ { .compatible = "x-powers,axp192", .data = (void *)AXP192_ID }, + { .compatible = "x-powers,axp202", .data = (void *)AXP202_ID }, + { .compatible = "x-powers,axp209", .data = (void *)AXP209_ID }, + { .compatible = "x-powers,axp221", .data = (void *)AXP221_ID }, +@@ -75,6 +76,7 @@ MODULE_DEVICE_TABLE(of, axp20x_i2c_of_ma + + static const struct i2c_device_id axp20x_i2c_id[] = { + { "axp152", 0 }, ++ { "axp192", 0 }, + { "axp202", 0 }, + { "axp209", 0 }, + { "axp221", 0 }, +--- a/drivers/mfd/axp20x.c ++++ b/drivers/mfd/axp20x.c +@@ -34,6 +34,7 @@ + + static const char * const axp20x_model_names[] = { + "AXP152", ++ "AXP192", + "AXP202", + "AXP209", + "AXP221", +@@ -94,6 +95,35 @@ static const struct regmap_access_table + .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), + }; + ++static const struct regmap_range axp192_writeable_ranges[] = { ++ regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)), ++ regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE), ++ regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL), ++ regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL), ++}; ++ ++static const struct regmap_range axp192_volatile_ranges[] = { ++ regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS), ++ regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE), ++ regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE), ++ regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), ++ regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), ++ regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE), ++ regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE), ++ regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL), ++ regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL), ++}; ++ ++static const struct regmap_access_table axp192_writeable_table = { ++ .yes_ranges = axp192_writeable_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges), ++}; ++ ++static const struct regmap_access_table axp192_volatile_table = { ++ .yes_ranges = axp192_volatile_ranges, ++ .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges), ++}; ++ + /* AXP22x ranges are shared with the AXP809, as they cover the same range */ + static const struct regmap_range axp22x_writeable_ranges[] = { + regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), +@@ -220,6 +250,19 @@ static const struct resource axp152_pek_ + DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), + }; + ++static const struct resource axp192_ac_power_supply_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), ++}; ++ ++static const struct resource axp192_usb_power_supply_resources[] = { ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"), ++ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), ++}; ++ + static const struct resource axp20x_ac_power_supply_resources[] = { + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), + DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), +@@ -302,6 +345,15 @@ static const struct regmap_config axp152 + .cache_type = REGCACHE_RBTREE, + }; + ++static const struct regmap_config axp192_regmap_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .wr_table = &axp192_writeable_table, ++ .volatile_table = &axp192_volatile_table, ++ .max_register = AXP20X_CC_CTRL, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ + static const struct regmap_config axp20x_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +@@ -379,6 +431,42 @@ static const struct regmap_irq axp152_re + INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), + }; + ++static const struct regmap_irq axp192_regmap_irqs[] = { ++ INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7), ++ INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6), ++ INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5), ++ INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4), ++ INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3), ++ INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2), ++ INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1), ++ INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7), ++ INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6), ++ INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5), ++ INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4), ++ INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3), ++ INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2), ++ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1), ++ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0), ++ INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7), ++ INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6), ++ INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5), ++ INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4), ++ INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3), ++ INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1), ++ INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0), ++ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7), ++ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6), ++ INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5), ++ INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4), ++ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3), ++ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2), ++ INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0), ++ INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7), ++ INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2), ++ INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1), ++ INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0), ++}; ++ + static const struct regmap_irq axp20x_regmap_irqs[] = { + INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), + INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), +@@ -616,6 +704,32 @@ static const struct regmap_irq_chip axp1 + .num_regs = 3, + }; + ++static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data, ++ unsigned int base, int index) ++{ ++ /* linear mapping for IRQ1 to IRQ4 */ ++ if (index < 4) ++ return base + index; ++ ++ /* handle IRQ5 separately */ ++ if (base == AXP192_IRQ1_EN) ++ return AXP192_IRQ5_EN; ++ ++ return AXP192_IRQ5_STATE; ++} ++ ++static const struct regmap_irq_chip axp192_regmap_irq_chip = { ++ .name = "axp192_irq_chip", ++ .status_base = AXP192_IRQ1_STATE, ++ .ack_base = AXP192_IRQ1_STATE, ++ .unmask_base = AXP192_IRQ1_EN, ++ .init_ack_masked = true, ++ .irqs = axp192_regmap_irqs, ++ .num_irqs = ARRAY_SIZE(axp192_regmap_irqs), ++ .num_regs = 5, ++ .get_irq_reg = axp192_get_irq_reg, ++}; ++ + static const struct regmap_irq_chip axp20x_regmap_irq_chip = { + .name = "axp20x_irq_chip", + .status_base = AXP20X_IRQ1_STATE, +@@ -712,6 +826,27 @@ static const struct regmap_irq_chip axp1 + .num_regs = 2, + }; + ++static const struct mfd_cell axp192_cells[] = { ++ { ++ .name = "axp192-adc", ++ .of_compatible = "x-powers,axp192-adc", ++ }, { ++ .name = "axp20x-battery-power-supply", ++ .of_compatible = "x-powers,axp192-battery-power-supply", ++ }, { ++ .name = "axp20x-ac-power-supply", ++ .of_compatible = "x-powers,axp202-ac-power-supply", ++ .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources), ++ .resources = axp192_ac_power_supply_resources, ++ }, { ++ .name = "axp20x-usb-power-supply", ++ .of_compatible = "x-powers,axp192-usb-power-supply", ++ .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources), ++ .resources = axp192_usb_power_supply_resources, ++ }, ++ { .name = "axp20x-regulator" }, ++}; ++ + static const struct mfd_cell axp20x_cells[] = { + { + .name = "axp20x-gpio", +@@ -1029,6 +1164,12 @@ int axp20x_match_device(struct axp20x_de + axp20x->regmap_cfg = &axp152_regmap_config; + axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; + break; ++ case AXP192_ID: ++ axp20x->nr_cells = ARRAY_SIZE(axp192_cells); ++ axp20x->cells = axp192_cells; ++ axp20x->regmap_cfg = &axp192_regmap_config; ++ axp20x->regmap_irq_chip = &axp192_regmap_irq_chip; ++ break; + case AXP202_ID: + case AXP209_ID: + axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); +--- a/include/linux/mfd/axp20x.h ++++ b/include/linux/mfd/axp20x.h +@@ -12,6 +12,7 @@ + + enum axp20x_variants { + AXP152_ID = 0, ++ AXP192_ID, + AXP202_ID, + AXP209_ID, + AXP221_ID, +@@ -26,6 +27,7 @@ enum axp20x_variants { + NR_AXP20X_VARIANTS, + }; + ++#define AXP192_DATACACHE(m) (0x06 + (m)) + #define AXP20X_DATACACHE(m) (0x04 + (m)) + + /* Power supply */ +@@ -47,6 +49,13 @@ enum axp20x_variants { + #define AXP152_DCDC_FREQ 0x37 + #define AXP152_DCDC_MODE 0x80 + ++#define AXP192_USB_OTG_STATUS 0x04 ++#define AXP192_PWR_OUT_CTRL 0x12 ++#define AXP192_DCDC2_V_OUT 0x23 ++#define AXP192_DCDC1_V_OUT 0x26 ++#define AXP192_DCDC3_V_OUT 0x27 ++#define AXP192_LDO2_3_V_OUT 0x28 ++ + #define AXP20X_PWR_INPUT_STATUS 0x00 + #define AXP20X_PWR_OP_MODE 0x01 + #define AXP20X_USB_OTG_STATUS 0x02 +@@ -185,6 +194,17 @@ enum axp20x_variants { + #define AXP152_IRQ2_STATE 0x49 + #define AXP152_IRQ3_STATE 0x4a + ++#define AXP192_IRQ1_EN 0x40 ++#define AXP192_IRQ2_EN 0x41 ++#define AXP192_IRQ3_EN 0x42 ++#define AXP192_IRQ4_EN 0x43 ++#define AXP192_IRQ1_STATE 0x44 ++#define AXP192_IRQ2_STATE 0x45 ++#define AXP192_IRQ3_STATE 0x46 ++#define AXP192_IRQ4_STATE 0x47 ++#define AXP192_IRQ5_EN 0x4a ++#define AXP192_IRQ5_STATE 0x4d ++ + #define AXP20X_IRQ1_EN 0x40 + #define AXP20X_IRQ2_EN 0x41 + #define AXP20X_IRQ3_EN 0x42 +@@ -204,6 +224,11 @@ enum axp20x_variants { + #define AXP15060_IRQ2_STATE 0x49 + + /* ADC */ ++#define AXP192_GPIO2_V_ADC_H 0x68 ++#define AXP192_GPIO2_V_ADC_L 0x69 ++#define AXP192_GPIO3_V_ADC_H 0x6a ++#define AXP192_GPIO3_V_ADC_L 0x6b ++ + #define AXP20X_ACIN_V_ADC_H 0x56 + #define AXP20X_ACIN_V_ADC_L 0x57 + #define AXP20X_ACIN_I_ADC_H 0x58 +@@ -233,6 +258,8 @@ enum axp20x_variants { + #define AXP20X_IPSOUT_V_HIGH_L 0x7f + + /* Power supply */ ++#define AXP192_GPIO30_IN_RANGE 0x85 ++ + #define AXP20X_DCDC_MODE 0x80 + #define AXP20X_ADC_EN1 0x82 + #define AXP20X_ADC_EN2 0x83 +@@ -261,6 +288,16 @@ enum axp20x_variants { + #define AXP152_PWM1_FREQ_Y 0x9c + #define AXP152_PWM1_DUTY_CYCLE 0x9d + ++#define AXP192_GPIO0_CTRL 0x90 ++#define AXP192_LDO_IO0_V_OUT 0x91 ++#define AXP192_GPIO1_CTRL 0x92 ++#define AXP192_GPIO2_CTRL 0x93 ++#define AXP192_GPIO2_0_STATE 0x94 ++#define AXP192_GPIO4_3_CTRL 0x95 ++#define AXP192_GPIO4_3_STATE 0x96 ++#define AXP192_GPIO2_0_PULL 0x97 ++#define AXP192_N_RSTO_CTRL 0x9e ++ + #define AXP20X_GPIO0_CTRL 0x90 + #define AXP20X_LDO5_V_OUT 0x91 + #define AXP20X_GPIO1_CTRL 0x92 +@@ -341,6 +378,17 @@ enum axp20x_variants { + + /* Regulators IDs */ + enum { ++ AXP192_DCDC1 = 0, ++ AXP192_DCDC2, ++ AXP192_DCDC3, ++ AXP192_LDO1, ++ AXP192_LDO2, ++ AXP192_LDO3, ++ AXP192_LDO_IO0, ++ AXP192_REG_ID_MAX ++}; ++ ++enum { + AXP20X_LDO1 = 0, + AXP20X_LDO2, + AXP20X_LDO3, +@@ -531,6 +579,42 @@ enum { + AXP152_IRQ_GPIO0_INPUT, + }; + ++enum axp192_irqs { ++ AXP192_IRQ_ACIN_OVER_V = 1, ++ AXP192_IRQ_ACIN_PLUGIN, ++ AXP192_IRQ_ACIN_REMOVAL, ++ AXP192_IRQ_VBUS_OVER_V, ++ AXP192_IRQ_VBUS_PLUGIN, ++ AXP192_IRQ_VBUS_REMOVAL, ++ AXP192_IRQ_VBUS_V_LOW, ++ AXP192_IRQ_BATT_PLUGIN, ++ AXP192_IRQ_BATT_REMOVAL, ++ AXP192_IRQ_BATT_ENT_ACT_MODE, ++ AXP192_IRQ_BATT_EXIT_ACT_MODE, ++ AXP192_IRQ_CHARG, ++ AXP192_IRQ_CHARG_DONE, ++ AXP192_IRQ_BATT_TEMP_HIGH, ++ AXP192_IRQ_BATT_TEMP_LOW, ++ AXP192_IRQ_DIE_TEMP_HIGH, ++ AXP192_IRQ_CHARG_I_LOW, ++ AXP192_IRQ_DCDC1_V_LONG, ++ AXP192_IRQ_DCDC2_V_LONG, ++ AXP192_IRQ_DCDC3_V_LONG, ++ AXP192_IRQ_PEK_SHORT = 22, ++ AXP192_IRQ_PEK_LONG, ++ AXP192_IRQ_N_OE_PWR_ON, ++ AXP192_IRQ_N_OE_PWR_OFF, ++ AXP192_IRQ_VBUS_VALID, ++ AXP192_IRQ_VBUS_NOT_VALID, ++ AXP192_IRQ_VBUS_SESS_VALID, ++ AXP192_IRQ_VBUS_SESS_END, ++ AXP192_IRQ_LOW_PWR_LVL = 31, ++ AXP192_IRQ_TIMER, ++ AXP192_IRQ_GPIO2_INPUT = 37, ++ AXP192_IRQ_GPIO1_INPUT, ++ AXP192_IRQ_GPIO0_INPUT, ++}; ++ + enum { + AXP20X_IRQ_ACIN_OVER_V = 1, + AXP20X_IRQ_ACIN_PLUGIN, diff --git a/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch b/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch deleted file mode 100644 index 18ad298065..0000000000 --- a/target/linux/starfive/patches-6.1/0117-driver-mfd-axp20x-Add-support-for-AXP15060.patch +++ /dev/null @@ -1,1014 +0,0 @@ -From e62161318f2fe3e396fc31c50d210e99bec83021 Mon Sep 17 00:00:00 2001 -From: "ziv.xu" -Date: Fri, 4 Aug 2023 13:53:10 +0800 -Subject: [PATCH 117/122] driver: mfd: axp20x: Add support for AXP15060 - -axp20x add support for AXP15060 - -Signed-off-by: ziv.xu ---- - drivers/mfd/axp20x-i2c.c | 2 + - drivers/mfd/axp20x.c | 373 ++++++++++++++++++++++++++++++++++--- - include/linux/mfd/axp20x.h | 218 +++++++++++++++++++++- - 3 files changed, 557 insertions(+), 36 deletions(-) - ---- a/drivers/mfd/axp20x-i2c.c -+++ b/drivers/mfd/axp20x-i2c.c -@@ -66,6 +66,7 @@ static const struct of_device_id axp20x_ - { .compatible = "x-powers,axp223", .data = (void *)AXP223_ID }, - { .compatible = "x-powers,axp803", .data = (void *)AXP803_ID }, - { .compatible = "x-powers,axp806", .data = (void *)AXP806_ID }, -+ { .compatible = "x-powers,axp15060", .data = (void *)AXP15060_ID }, - { }, - }; - MODULE_DEVICE_TABLE(of, axp20x_i2c_of_match); -@@ -79,6 +80,7 @@ static const struct i2c_device_id axp20x - { "axp223", 0 }, - { "axp803", 0 }, - { "axp806", 0 }, -+ { "axp15060", 0 }, - { }, - }; - MODULE_DEVICE_TABLE(i2c, axp20x_i2c_id); ---- a/drivers/mfd/axp20x.c -+++ b/drivers/mfd/axp20x.c -@@ -23,7 +23,7 @@ - #include - #include - #include --#include -+#include - #include - #include - -@@ -34,15 +34,18 @@ - - static const char * const axp20x_model_names[] = { - "AXP152", -+ "AXP192", - "AXP202", - "AXP209", - "AXP221", - "AXP223", - "AXP288", -+ "AXP313a", - "AXP803", - "AXP806", - "AXP809", - "AXP813", -+ "AXP15060", - }; - - static const struct regmap_range axp152_writeable_ranges[] = { -@@ -92,6 +95,35 @@ static const struct regmap_access_table - .n_yes_ranges = ARRAY_SIZE(axp20x_volatile_ranges), - }; - -+static const struct regmap_range axp192_writeable_ranges[] = { -+ regmap_reg_range(AXP192_DATACACHE(0), AXP192_DATACACHE(5)), -+ regmap_reg_range(AXP192_PWR_OUT_CTRL, AXP192_IRQ5_STATE), -+ regmap_reg_range(AXP20X_DCDC_MODE, AXP192_N_RSTO_CTRL), -+ regmap_reg_range(AXP20X_CC_CTRL, AXP20X_CC_CTRL), -+}; -+ -+static const struct regmap_range axp192_volatile_ranges[] = { -+ regmap_reg_range(AXP20X_PWR_INPUT_STATUS, AXP192_USB_OTG_STATUS), -+ regmap_reg_range(AXP192_IRQ1_STATE, AXP192_IRQ4_STATE), -+ regmap_reg_range(AXP192_IRQ5_STATE, AXP192_IRQ5_STATE), -+ regmap_reg_range(AXP20X_ACIN_V_ADC_H, AXP20X_IPSOUT_V_HIGH_L), -+ regmap_reg_range(AXP20X_TIMER_CTRL, AXP20X_TIMER_CTRL), -+ regmap_reg_range(AXP192_GPIO2_0_STATE, AXP192_GPIO2_0_STATE), -+ regmap_reg_range(AXP192_GPIO4_3_STATE, AXP192_GPIO4_3_STATE), -+ regmap_reg_range(AXP192_N_RSTO_CTRL, AXP192_N_RSTO_CTRL), -+ regmap_reg_range(AXP20X_CHRG_CC_31_24, AXP20X_CC_CTRL), -+}; -+ -+static const struct regmap_access_table axp192_writeable_table = { -+ .yes_ranges = axp192_writeable_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp192_writeable_ranges), -+}; -+ -+static const struct regmap_access_table axp192_volatile_table = { -+ .yes_ranges = axp192_volatile_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp192_volatile_ranges), -+}; -+ - /* AXP22x ranges are shared with the AXP809, as they cover the same range */ - static const struct regmap_range axp22x_writeable_ranges[] = { - regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ5_STATE), -@@ -119,6 +151,7 @@ static const struct regmap_access_table - - /* AXP288 ranges are shared with the AXP803, as they cover the same range */ - static const struct regmap_range axp288_writeable_ranges[] = { -+ regmap_reg_range(AXP288_POWER_REASON, AXP288_POWER_REASON), - regmap_reg_range(AXP20X_DATACACHE(0), AXP20X_IRQ6_STATE), - regmap_reg_range(AXP20X_DCDC_MODE, AXP288_FG_TUNE5), - }; -@@ -154,6 +187,25 @@ static const struct regmap_range axp806_ - regmap_reg_range(AXP806_REG_ADDR_EXT, AXP806_REG_ADDR_EXT), - }; - -+static const struct regmap_range axp313a_writeable_ranges[] = { -+ regmap_reg_range(AXP313A_ON_INDICATE, AXP313A_IRQ_STATE), -+}; -+ -+static const struct regmap_range axp313a_volatile_ranges[] = { -+ regmap_reg_range(AXP313A_SHUTDOWN_CTRL, AXP313A_SHUTDOWN_CTRL), -+ regmap_reg_range(AXP313A_IRQ_STATE, AXP313A_IRQ_STATE), -+}; -+ -+static const struct regmap_access_table axp313a_writeable_table = { -+ .yes_ranges = axp313a_writeable_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp313a_writeable_ranges), -+}; -+ -+static const struct regmap_access_table axp313a_volatile_table = { -+ .yes_ranges = axp313a_volatile_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp313a_volatile_ranges), -+}; -+ - static const struct regmap_range axp806_volatile_ranges[] = { - regmap_reg_range(AXP20X_IRQ1_STATE, AXP20X_IRQ2_STATE), - }; -@@ -168,11 +220,49 @@ static const struct regmap_access_table - .n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges), - }; - -+static const struct regmap_range axp15060_writeable_ranges[] = { -+ regmap_reg_range(AXP15060_PWR_OUT_CTRL1, AXP15060_DCDC_MODE_CTRL2), -+ regmap_reg_range(AXP15060_OUTPUT_MONITOR_DISCHARGE, AXP15060_CPUSLDO_V_CTRL), -+ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), -+ regmap_reg_range(AXP15060_PEK_KEY, AXP15060_PEK_KEY), -+ regmap_reg_range(AXP15060_IRQ1_EN, AXP15060_IRQ2_EN), -+ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), -+}; -+ -+static const struct regmap_range axp15060_volatile_ranges[] = { -+ regmap_reg_range(AXP15060_STARTUP_SRC, AXP15060_STARTUP_SRC), -+ regmap_reg_range(AXP15060_PWR_WAKEUP_CTRL, AXP15060_PWR_DISABLE_DOWN_SEQ), -+ regmap_reg_range(AXP15060_IRQ1_STATE, AXP15060_IRQ2_STATE), -+}; -+ -+static const struct regmap_access_table axp15060_writeable_table = { -+ .yes_ranges = axp15060_writeable_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp15060_writeable_ranges), -+}; -+ -+static const struct regmap_access_table axp15060_volatile_table = { -+ .yes_ranges = axp15060_volatile_ranges, -+ .n_yes_ranges = ARRAY_SIZE(axp15060_volatile_ranges), -+}; -+ - static const struct resource axp152_pek_resources[] = { - DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"), - DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"), - }; - -+static const struct resource axp192_ac_power_supply_resources[] = { -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_ACIN_OVER_V, "ACIN_OVER_V"), -+}; -+ -+static const struct resource axp192_usb_power_supply_resources[] = { -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"), -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"), -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_VALID, "VBUS_VALID"), -+ DEFINE_RES_IRQ_NAMED(AXP192_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"), -+}; -+ - static const struct resource axp20x_ac_power_supply_resources[] = { - DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"), - DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"), -@@ -221,6 +311,11 @@ static const struct resource axp288_fuel - DEFINE_RES_IRQ(AXP288_IRQ_WL1), - }; - -+static const struct resource axp313a_pek_resources[] = { -+ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_RIS_EDGE, "PEK_DBR"), -+ DEFINE_RES_IRQ_NAMED(AXP313A_IRQ_PEK_FAL_EDGE, "PEK_DBF"), -+}; -+ - static const struct resource axp803_pek_resources[] = { - DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"), - DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"), -@@ -236,6 +331,11 @@ static const struct resource axp809_pek_ - DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"), - }; - -+static const struct resource axp15060_pek_resources[] = { -+ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_RIS_EDGE, "PEK_DBR"), -+ DEFINE_RES_IRQ_NAMED(AXP15060_IRQ_PEK_FAL_EDGE, "PEK_DBF"), -+}; -+ - static const struct regmap_config axp152_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -@@ -245,6 +345,15 @@ static const struct regmap_config axp152 - .cache_type = REGCACHE_RBTREE, - }; - -+static const struct regmap_config axp192_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .wr_table = &axp192_writeable_table, -+ .volatile_table = &axp192_volatile_table, -+ .max_register = AXP20X_CC_CTRL, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ - static const struct regmap_config axp20x_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -@@ -272,6 +381,15 @@ static const struct regmap_config axp288 - .cache_type = REGCACHE_RBTREE, - }; - -+static const struct regmap_config axp313a_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .wr_table = &axp313a_writeable_table, -+ .volatile_table = &axp313a_volatile_table, -+ .max_register = AXP313A_IRQ_STATE, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ - static const struct regmap_config axp806_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -@@ -281,6 +399,15 @@ static const struct regmap_config axp806 - .cache_type = REGCACHE_RBTREE, - }; - -+static const struct regmap_config axp15060_regmap_config = { -+ .reg_bits = 8, -+ .val_bits = 8, -+ .wr_table = &axp15060_writeable_table, -+ .volatile_table = &axp15060_volatile_table, -+ .max_register = AXP15060_IRQ2_STATE, -+ .cache_type = REGCACHE_RBTREE, -+}; -+ - #define INIT_REGMAP_IRQ(_variant, _irq, _off, _mask) \ - [_variant##_IRQ_##_irq] = { .reg_offset = (_off), .mask = BIT(_mask) } - -@@ -304,6 +431,42 @@ static const struct regmap_irq axp152_re - INIT_REGMAP_IRQ(AXP152, GPIO0_INPUT, 2, 0), - }; - -+static const struct regmap_irq axp192_regmap_irqs[] = { -+ INIT_REGMAP_IRQ(AXP192, ACIN_OVER_V, 0, 7), -+ INIT_REGMAP_IRQ(AXP192, ACIN_PLUGIN, 0, 6), -+ INIT_REGMAP_IRQ(AXP192, ACIN_REMOVAL, 0, 5), -+ INIT_REGMAP_IRQ(AXP192, VBUS_OVER_V, 0, 4), -+ INIT_REGMAP_IRQ(AXP192, VBUS_PLUGIN, 0, 3), -+ INIT_REGMAP_IRQ(AXP192, VBUS_REMOVAL, 0, 2), -+ INIT_REGMAP_IRQ(AXP192, VBUS_V_LOW, 0, 1), -+ INIT_REGMAP_IRQ(AXP192, BATT_PLUGIN, 1, 7), -+ INIT_REGMAP_IRQ(AXP192, BATT_REMOVAL, 1, 6), -+ INIT_REGMAP_IRQ(AXP192, BATT_ENT_ACT_MODE, 1, 5), -+ INIT_REGMAP_IRQ(AXP192, BATT_EXIT_ACT_MODE, 1, 4), -+ INIT_REGMAP_IRQ(AXP192, CHARG, 1, 3), -+ INIT_REGMAP_IRQ(AXP192, CHARG_DONE, 1, 2), -+ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_HIGH, 1, 1), -+ INIT_REGMAP_IRQ(AXP192, BATT_TEMP_LOW, 1, 0), -+ INIT_REGMAP_IRQ(AXP192, DIE_TEMP_HIGH, 2, 7), -+ INIT_REGMAP_IRQ(AXP192, CHARG_I_LOW, 2, 6), -+ INIT_REGMAP_IRQ(AXP192, DCDC1_V_LONG, 2, 5), -+ INIT_REGMAP_IRQ(AXP192, DCDC2_V_LONG, 2, 4), -+ INIT_REGMAP_IRQ(AXP192, DCDC3_V_LONG, 2, 3), -+ INIT_REGMAP_IRQ(AXP192, PEK_SHORT, 2, 1), -+ INIT_REGMAP_IRQ(AXP192, PEK_LONG, 2, 0), -+ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_ON, 3, 7), -+ INIT_REGMAP_IRQ(AXP192, N_OE_PWR_OFF, 3, 6), -+ INIT_REGMAP_IRQ(AXP192, VBUS_VALID, 3, 5), -+ INIT_REGMAP_IRQ(AXP192, VBUS_NOT_VALID, 3, 4), -+ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_VALID, 3, 3), -+ INIT_REGMAP_IRQ(AXP192, VBUS_SESS_END, 3, 2), -+ INIT_REGMAP_IRQ(AXP192, LOW_PWR_LVL, 3, 0), -+ INIT_REGMAP_IRQ(AXP192, TIMER, 4, 7), -+ INIT_REGMAP_IRQ(AXP192, GPIO2_INPUT, 4, 2), -+ INIT_REGMAP_IRQ(AXP192, GPIO1_INPUT, 4, 1), -+ INIT_REGMAP_IRQ(AXP192, GPIO0_INPUT, 4, 0), -+}; -+ - static const struct regmap_irq axp20x_regmap_irqs[] = { - INIT_REGMAP_IRQ(AXP20X, ACIN_OVER_V, 0, 7), - INIT_REGMAP_IRQ(AXP20X, ACIN_PLUGIN, 0, 6), -@@ -415,6 +578,16 @@ static const struct regmap_irq axp288_re - INIT_REGMAP_IRQ(AXP288, BC_USB_CHNG, 5, 1), - }; - -+static const struct regmap_irq axp313a_regmap_irqs[] = { -+ INIT_REGMAP_IRQ(AXP313A, PEK_RIS_EDGE, 0, 7), -+ INIT_REGMAP_IRQ(AXP313A, PEK_FAL_EDGE, 0, 6), -+ INIT_REGMAP_IRQ(AXP313A, PEK_SHORT, 0, 5), -+ INIT_REGMAP_IRQ(AXP313A, PEK_LONG, 0, 4), -+ INIT_REGMAP_IRQ(AXP313A, DCDC3_V_LOW, 0, 3), -+ INIT_REGMAP_IRQ(AXP313A, DCDC2_V_LOW, 0, 2), -+ INIT_REGMAP_IRQ(AXP313A, DIE_TEMP_HIGH, 0, 0), -+}; -+ - static const struct regmap_irq axp803_regmap_irqs[] = { - INIT_REGMAP_IRQ(AXP803, ACIN_OVER_V, 0, 7), - INIT_REGMAP_IRQ(AXP803, ACIN_PLUGIN, 0, 6), -@@ -502,24 +675,65 @@ static const struct regmap_irq axp809_re - INIT_REGMAP_IRQ(AXP809, GPIO0_INPUT, 4, 0), - }; - -+static const struct regmap_irq axp15060_regmap_irqs[] = { -+ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV1, 0, 0), -+ INIT_REGMAP_IRQ(AXP15060, DIE_TEMP_HIGH_LV2, 0, 1), -+ INIT_REGMAP_IRQ(AXP15060, DCDC1_V_LOW, 0, 2), -+ INIT_REGMAP_IRQ(AXP15060, DCDC2_V_LOW, 0, 3), -+ INIT_REGMAP_IRQ(AXP15060, DCDC3_V_LOW, 0, 4), -+ INIT_REGMAP_IRQ(AXP15060, DCDC4_V_LOW, 0, 5), -+ INIT_REGMAP_IRQ(AXP15060, DCDC5_V_LOW, 0, 6), -+ INIT_REGMAP_IRQ(AXP15060, DCDC6_V_LOW, 0, 7), -+ INIT_REGMAP_IRQ(AXP15060, PEK_LONG, 1, 0), -+ INIT_REGMAP_IRQ(AXP15060, PEK_SHORT, 1, 1), -+ INIT_REGMAP_IRQ(AXP15060, GPIO1_INPUT, 1, 2), -+ INIT_REGMAP_IRQ(AXP15060, PEK_FAL_EDGE, 1, 3), -+ INIT_REGMAP_IRQ(AXP15060, PEK_RIS_EDGE, 1, 4), -+ INIT_REGMAP_IRQ(AXP15060, GPIO2_INPUT, 1, 5), -+}; -+ - static const struct regmap_irq_chip axp152_regmap_irq_chip = { - .name = "axp152_irq_chip", - .status_base = AXP152_IRQ1_STATE, - .ack_base = AXP152_IRQ1_STATE, -- .mask_base = AXP152_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP152_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp152_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp152_regmap_irqs), - .num_regs = 3, - }; - -+static unsigned int axp192_get_irq_reg(struct regmap_irq_chip_data *data, -+ unsigned int base, int index) -+{ -+ /* linear mapping for IRQ1 to IRQ4 */ -+ if (index < 4) -+ return base + index; -+ -+ /* handle IRQ5 separately */ -+ if (base == AXP192_IRQ1_EN) -+ return AXP192_IRQ5_EN; -+ -+ return AXP192_IRQ5_STATE; -+} -+ -+static const struct regmap_irq_chip axp192_regmap_irq_chip = { -+ .name = "axp192_irq_chip", -+ .status_base = AXP192_IRQ1_STATE, -+ .ack_base = AXP192_IRQ1_STATE, -+ .unmask_base = AXP192_IRQ1_EN, -+ .init_ack_masked = true, -+ .irqs = axp192_regmap_irqs, -+ .num_irqs = ARRAY_SIZE(axp192_regmap_irqs), -+ .num_regs = 5, -+ .get_irq_reg = axp192_get_irq_reg, -+}; -+ - static const struct regmap_irq_chip axp20x_regmap_irq_chip = { - .name = "axp20x_irq_chip", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp20x_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp20x_regmap_irqs), -@@ -531,8 +745,7 @@ static const struct regmap_irq_chip axp2 - .name = "axp22x_irq_chip", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp22x_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp22x_regmap_irqs), -@@ -543,8 +756,7 @@ static const struct regmap_irq_chip axp2 - .name = "axp288_irq_chip", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp288_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp288_regmap_irqs), -@@ -552,12 +764,22 @@ static const struct regmap_irq_chip axp2 - - }; - -+static const struct regmap_irq_chip axp313a_regmap_irq_chip = { -+ .name = "axp313a_irq_chip", -+ .status_base = AXP313A_IRQ_STATE, -+ .ack_base = AXP313A_IRQ_STATE, -+ .unmask_base = AXP313A_IRQ_EN, -+ .init_ack_masked = true, -+ .irqs = axp313a_regmap_irqs, -+ .num_irqs = ARRAY_SIZE(axp313a_regmap_irqs), -+ .num_regs = 1, -+}; -+ - static const struct regmap_irq_chip axp803_regmap_irq_chip = { - .name = "axp803", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp803_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp803_regmap_irqs), -@@ -568,8 +790,7 @@ static const struct regmap_irq_chip axp8 - .name = "axp806", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp806_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp806_regmap_irqs), -@@ -580,14 +801,45 @@ static const struct regmap_irq_chip axp8 - .name = "axp809", - .status_base = AXP20X_IRQ1_STATE, - .ack_base = AXP20X_IRQ1_STATE, -- .mask_base = AXP20X_IRQ1_EN, -- .mask_invert = true, -+ .unmask_base = AXP20X_IRQ1_EN, - .init_ack_masked = true, - .irqs = axp809_regmap_irqs, - .num_irqs = ARRAY_SIZE(axp809_regmap_irqs), - .num_regs = 5, - }; - -+static const struct regmap_irq_chip axp15060_regmap_irq_chip = { -+ .name = "axp15060", -+ .status_base = AXP15060_IRQ1_STATE, -+ .ack_base = AXP15060_IRQ1_STATE, -+ .unmask_base = AXP15060_IRQ1_EN, -+ .init_ack_masked = true, -+ .irqs = axp15060_regmap_irqs, -+ .num_irqs = ARRAY_SIZE(axp15060_regmap_irqs), -+ .num_regs = 2, -+}; -+ -+static const struct mfd_cell axp192_cells[] = { -+ { -+ .name = "axp192-adc", -+ .of_compatible = "x-powers,axp192-adc", -+ }, { -+ .name = "axp20x-battery-power-supply", -+ .of_compatible = "x-powers,axp192-battery-power-supply", -+ }, { -+ .name = "axp20x-ac-power-supply", -+ .of_compatible = "x-powers,axp202-ac-power-supply", -+ .num_resources = ARRAY_SIZE(axp192_ac_power_supply_resources), -+ .resources = axp192_ac_power_supply_resources, -+ }, { -+ .name = "axp20x-usb-power-supply", -+ .of_compatible = "x-powers,axp192-usb-power-supply", -+ .num_resources = ARRAY_SIZE(axp192_usb_power_supply_resources), -+ .resources = axp192_usb_power_supply_resources, -+ }, -+ { .name = "axp20x-regulator" }, -+}; -+ - static const struct mfd_cell axp20x_cells[] = { - { - .name = "axp20x-gpio", -@@ -683,6 +935,11 @@ static const struct mfd_cell axp152_cell - }, - }; - -+static struct mfd_cell axp313a_cells[] = { -+ MFD_CELL_NAME("axp20x-regulator"), -+ MFD_CELL_RES("axp313a-pek", axp313a_pek_resources), -+}; -+ - static const struct resource axp288_adc_resources[] = { - DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"), - }; -@@ -832,17 +1089,43 @@ static const struct mfd_cell axp813_cell - }, - }; - --static struct axp20x_dev *axp20x_pm_power_off; --static void axp20x_power_off(void) -+static const struct mfd_cell axp15060_cells[] = { -+ { -+ .name = "axp221-pek", -+ .num_resources = ARRAY_SIZE(axp15060_pek_resources), -+ .resources = axp15060_pek_resources, -+ }, { -+ .name = "axp20x-regulator", -+ }, -+}; -+ -+/* For boards that don't have IRQ line connected to SOC. */ -+static const struct mfd_cell axp_regulator_only_cells[] = { -+ { -+ .name = "axp20x-regulator", -+ }, -+}; -+ -+static int axp20x_power_off(struct sys_off_data *data) - { -- if (axp20x_pm_power_off->variant == AXP288_ID) -- return; -+ struct axp20x_dev *axp20x = data->cb_data; -+ unsigned int shutdown_reg; - -- regmap_write(axp20x_pm_power_off->regmap, AXP20X_OFF_CTRL, -- AXP20X_OFF); -+ switch (axp20x->variant) { -+ case AXP313A_ID: -+ shutdown_reg = AXP313A_SHUTDOWN_CTRL; -+ break; -+ default: -+ shutdown_reg = AXP20X_OFF_CTRL; -+ break; -+ } -+ -+ regmap_write(axp20x->regmap, shutdown_reg, AXP20X_OFF); - - /* Give capacitors etc. time to drain to avoid kernel panic msg. */ - mdelay(500); -+ -+ return NOTIFY_DONE; - } - - int axp20x_match_device(struct axp20x_dev *axp20x) -@@ -874,6 +1157,12 @@ int axp20x_match_device(struct axp20x_de - axp20x->regmap_cfg = &axp152_regmap_config; - axp20x->regmap_irq_chip = &axp152_regmap_irq_chip; - break; -+ case AXP192_ID: -+ axp20x->nr_cells = ARRAY_SIZE(axp192_cells); -+ axp20x->cells = axp192_cells; -+ axp20x->regmap_cfg = &axp192_regmap_config; -+ axp20x->regmap_irq_chip = &axp192_regmap_irq_chip; -+ break; - case AXP202_ID: - case AXP209_ID: - axp20x->nr_cells = ARRAY_SIZE(axp20x_cells); -@@ -900,6 +1189,12 @@ int axp20x_match_device(struct axp20x_de - axp20x->regmap_irq_chip = &axp288_regmap_irq_chip; - axp20x->irq_flags = IRQF_TRIGGER_LOW; - break; -+ case AXP313A_ID: -+ axp20x->nr_cells = ARRAY_SIZE(axp313a_cells); -+ axp20x->cells = axp313a_cells; -+ axp20x->regmap_cfg = &axp313a_regmap_config; -+ axp20x->regmap_irq_chip = &axp313a_regmap_irq_chip; -+ break; - case AXP803_ID: - axp20x->nr_cells = ARRAY_SIZE(axp803_cells); - axp20x->cells = axp803_cells; -@@ -942,6 +1237,28 @@ int axp20x_match_device(struct axp20x_de - */ - axp20x->regmap_irq_chip = &axp803_regmap_irq_chip; - break; -+ case AXP15060_ID: -+ /* -+ * Don't register the power key part if there is no interrupt -+ * line. -+ * -+ * Since most use cases of AXP PMICs are Allwinner SOCs, board -+ * designers follow Allwinner's reference design and connects -+ * IRQ line to SOC, there's no need for those variants to deal -+ * with cases that IRQ isn't connected. However, AXP15660 is -+ * used by some other vendors' SOCs that didn't connect IRQ -+ * line, we need to deal with this case. -+ */ -+ if (axp20x->irq > 0) { -+ axp20x->nr_cells = ARRAY_SIZE(axp15060_cells); -+ axp20x->cells = axp15060_cells; -+ } else { -+ axp20x->nr_cells = ARRAY_SIZE(axp_regulator_only_cells); -+ axp20x->cells = axp_regulator_only_cells; -+ } -+ axp20x->regmap_cfg = &axp15060_regmap_config; -+ axp20x->regmap_irq_chip = &axp15060_regmap_irq_chip; -+ break; - default: - dev_err(dev, "unsupported AXP20X ID %lu\n", axp20x->variant); - return -EINVAL; -@@ -1009,10 +1326,11 @@ int axp20x_device_probe(struct axp20x_de - return ret; - } - -- if (!pm_power_off) { -- axp20x_pm_power_off = axp20x; -- pm_power_off = axp20x_power_off; -- } -+ if (axp20x->variant != AXP288_ID) -+ devm_register_sys_off_handler(axp20x->dev, -+ SYS_OFF_MODE_POWER_OFF, -+ SYS_OFF_PRIO_DEFAULT, -+ axp20x_power_off, axp20x); - - dev_info(axp20x->dev, "AXP20X driver loaded\n"); - -@@ -1022,11 +1340,6 @@ EXPORT_SYMBOL(axp20x_device_probe); - - void axp20x_device_remove(struct axp20x_dev *axp20x) - { -- if (axp20x == axp20x_pm_power_off) { -- axp20x_pm_power_off = NULL; -- pm_power_off = NULL; -- } -- - mfd_remove_devices(axp20x->dev); - regmap_del_irq_chip(axp20x->irq, axp20x->regmap_irqc); - } ---- a/include/linux/mfd/axp20x.h -+++ b/include/linux/mfd/axp20x.h -@@ -12,18 +12,22 @@ - - enum axp20x_variants { - AXP152_ID = 0, -+ AXP192_ID, - AXP202_ID, - AXP209_ID, - AXP221_ID, - AXP223_ID, - AXP288_ID, -+ AXP313A_ID, - AXP803_ID, - AXP806_ID, - AXP809_ID, - AXP813_ID, -+ AXP15060_ID, - NR_AXP20X_VARIANTS, - }; - -+#define AXP192_DATACACHE(m) (0x06 + (m)) - #define AXP20X_DATACACHE(m) (0x04 + (m)) - - /* Power supply */ -@@ -45,6 +49,13 @@ enum axp20x_variants { - #define AXP152_DCDC_FREQ 0x37 - #define AXP152_DCDC_MODE 0x80 - -+#define AXP192_USB_OTG_STATUS 0x04 -+#define AXP192_PWR_OUT_CTRL 0x12 -+#define AXP192_DCDC2_V_OUT 0x23 -+#define AXP192_DCDC1_V_OUT 0x26 -+#define AXP192_DCDC3_V_OUT 0x27 -+#define AXP192_LDO2_3_V_OUT 0x28 -+ - #define AXP20X_PWR_INPUT_STATUS 0x00 - #define AXP20X_PWR_OP_MODE 0x01 - #define AXP20X_USB_OTG_STATUS 0x02 -@@ -91,6 +102,17 @@ enum axp20x_variants { - #define AXP22X_ALDO3_V_OUT 0x2a - #define AXP22X_CHRG_CTRL3 0x35 - -+#define AXP313A_ON_INDICATE 0x00 -+#define AXP313A_OUTPUT_CONTROL 0x10 -+#define AXP313A_DCDC1_CONRTOL 0x13 -+#define AXP313A_DCDC2_CONRTOL 0x14 -+#define AXP313A_DCDC3_CONRTOL 0x15 -+#define AXP313A_ALDO1_CONRTOL 0x16 -+#define AXP313A_DLDO1_CONRTOL 0x17 -+#define AXP313A_SHUTDOWN_CTRL 0x1a -+#define AXP313A_IRQ_EN 0x20 -+#define AXP313A_IRQ_STATE 0x21 -+ - #define AXP806_STARTUP_SRC 0x00 - #define AXP806_CHIP_ID 0x03 - #define AXP806_PWR_OUT_CTRL1 0x10 -@@ -131,6 +153,39 @@ enum axp20x_variants { - /* Other DCDC regulator control registers are the same as AXP803 */ - #define AXP813_DCDC7_V_OUT 0x26 - -+#define AXP15060_STARTUP_SRC 0x00 -+#define AXP15060_PWR_OUT_CTRL1 0x10 -+#define AXP15060_PWR_OUT_CTRL2 0x11 -+#define AXP15060_PWR_OUT_CTRL3 0x12 -+#define AXP15060_DCDC1_V_CTRL 0x13 -+#define AXP15060_DCDC2_V_CTRL 0x14 -+#define AXP15060_DCDC3_V_CTRL 0x15 -+#define AXP15060_DCDC4_V_CTRL 0x16 -+#define AXP15060_DCDC5_V_CTRL 0x17 -+#define AXP15060_DCDC6_V_CTRL 0x18 -+#define AXP15060_ALDO1_V_CTRL 0x19 -+#define AXP15060_DCDC_MODE_CTRL1 0x1a -+#define AXP15060_DCDC_MODE_CTRL2 0x1b -+#define AXP15060_OUTPUT_MONITOR_DISCHARGE 0x1e -+#define AXP15060_IRQ_PWROK_VOFF 0x1f -+#define AXP15060_ALDO2_V_CTRL 0x20 -+#define AXP15060_ALDO3_V_CTRL 0x21 -+#define AXP15060_ALDO4_V_CTRL 0x22 -+#define AXP15060_ALDO5_V_CTRL 0x23 -+#define AXP15060_BLDO1_V_CTRL 0x24 -+#define AXP15060_BLDO2_V_CTRL 0x25 -+#define AXP15060_BLDO3_V_CTRL 0x26 -+#define AXP15060_BLDO4_V_CTRL 0x27 -+#define AXP15060_BLDO5_V_CTRL 0x28 -+#define AXP15060_CLDO1_V_CTRL 0x29 -+#define AXP15060_CLDO2_V_CTRL 0x2a -+#define AXP15060_CLDO3_V_CTRL 0x2b -+#define AXP15060_CLDO4_V_CTRL 0x2d -+#define AXP15060_CPUSLDO_V_CTRL 0x2e -+#define AXP15060_PWR_WAKEUP_CTRL 0x31 -+#define AXP15060_PWR_DISABLE_DOWN_SEQ 0x32 -+#define AXP15060_PEK_KEY 0x36 -+ - /* Interrupt */ - #define AXP152_IRQ1_EN 0x40 - #define AXP152_IRQ2_EN 0x41 -@@ -139,6 +194,17 @@ enum axp20x_variants { - #define AXP152_IRQ2_STATE 0x49 - #define AXP152_IRQ3_STATE 0x4a - -+#define AXP192_IRQ1_EN 0x40 -+#define AXP192_IRQ2_EN 0x41 -+#define AXP192_IRQ3_EN 0x42 -+#define AXP192_IRQ4_EN 0x43 -+#define AXP192_IRQ1_STATE 0x44 -+#define AXP192_IRQ2_STATE 0x45 -+#define AXP192_IRQ3_STATE 0x46 -+#define AXP192_IRQ4_STATE 0x47 -+#define AXP192_IRQ5_EN 0x4a -+#define AXP192_IRQ5_STATE 0x4d -+ - #define AXP20X_IRQ1_EN 0x40 - #define AXP20X_IRQ2_EN 0x41 - #define AXP20X_IRQ3_EN 0x42 -@@ -152,7 +218,17 @@ enum axp20x_variants { - #define AXP20X_IRQ5_STATE 0x4c - #define AXP20X_IRQ6_STATE 0x4d - -+#define AXP15060_IRQ1_EN 0x40 -+#define AXP15060_IRQ2_EN 0x41 -+#define AXP15060_IRQ1_STATE 0x48 -+#define AXP15060_IRQ2_STATE 0x49 -+ - /* ADC */ -+#define AXP192_GPIO2_V_ADC_H 0x68 -+#define AXP192_GPIO2_V_ADC_L 0x69 -+#define AXP192_GPIO3_V_ADC_H 0x6a -+#define AXP192_GPIO3_V_ADC_L 0x6b -+ - #define AXP20X_ACIN_V_ADC_H 0x56 - #define AXP20X_ACIN_V_ADC_L 0x57 - #define AXP20X_ACIN_I_ADC_H 0x58 -@@ -182,6 +258,8 @@ enum axp20x_variants { - #define AXP20X_IPSOUT_V_HIGH_L 0x7f - - /* Power supply */ -+#define AXP192_GPIO30_IN_RANGE 0x85 -+ - #define AXP20X_DCDC_MODE 0x80 - #define AXP20X_ADC_EN1 0x82 - #define AXP20X_ADC_EN2 0x83 -@@ -210,6 +288,16 @@ enum axp20x_variants { - #define AXP152_PWM1_FREQ_Y 0x9c - #define AXP152_PWM1_DUTY_CYCLE 0x9d - -+#define AXP192_GPIO0_CTRL 0x90 -+#define AXP192_LDO_IO0_V_OUT 0x91 -+#define AXP192_GPIO1_CTRL 0x92 -+#define AXP192_GPIO2_CTRL 0x93 -+#define AXP192_GPIO2_0_STATE 0x94 -+#define AXP192_GPIO4_3_CTRL 0x95 -+#define AXP192_GPIO4_3_STATE 0x96 -+#define AXP192_GPIO2_0_PULL 0x97 -+#define AXP192_N_RSTO_CTRL 0x9e -+ - #define AXP20X_GPIO0_CTRL 0x90 - #define AXP20X_LDO5_V_OUT 0x91 - #define AXP20X_GPIO1_CTRL 0x92 -@@ -222,6 +310,8 @@ enum axp20x_variants { - #define AXP22X_GPIO_STATE 0x94 - #define AXP22X_GPIO_PULL_DOWN 0x95 - -+#define AXP15060_CLDO4_GPIO2_MODESET 0x2c -+ - /* Battery */ - #define AXP20X_CHRG_CC_31_24 0xb0 - #define AXP20X_CHRG_CC_23_16 0xb1 -@@ -288,6 +378,17 @@ enum axp20x_variants { - - /* Regulators IDs */ - enum { -+ AXP192_DCDC1 = 0, -+ AXP192_DCDC2, -+ AXP192_DCDC3, -+ AXP192_LDO1, -+ AXP192_LDO2, -+ AXP192_LDO3, -+ AXP192_LDO_IO0, -+ AXP192_REG_ID_MAX -+}; -+ -+enum { - AXP20X_LDO1 = 0, - AXP20X_LDO2, - AXP20X_LDO3, -@@ -323,6 +424,16 @@ enum { - }; - - enum { -+ AXP313A_DCDC1 = 0, -+ AXP313A_DCDC2, -+ AXP313A_DCDC3, -+ AXP313A_ALDO1, -+ AXP313A_DLDO1, -+ AXP313A_RTC_LDO, -+ AXP313A_REG_ID_MAX, -+}; -+ -+enum { - AXP806_DCDCA = 0, - AXP806_DCDCB, - AXP806_DCDCC, -@@ -419,6 +530,33 @@ enum { - AXP813_REG_ID_MAX, - }; - -+enum { -+ AXP15060_DCDC1 = 0, -+ AXP15060_DCDC2, -+ AXP15060_DCDC3, -+ AXP15060_DCDC4, -+ AXP15060_DCDC5, -+ AXP15060_DCDC6, -+ AXP15060_ALDO1, -+ AXP15060_ALDO2, -+ AXP15060_ALDO3, -+ AXP15060_ALDO4, -+ AXP15060_ALDO5, -+ AXP15060_BLDO1, -+ AXP15060_BLDO2, -+ AXP15060_BLDO3, -+ AXP15060_BLDO4, -+ AXP15060_BLDO5, -+ AXP15060_CLDO1, -+ AXP15060_CLDO2, -+ AXP15060_CLDO3, -+ AXP15060_CLDO4, -+ AXP15060_CPUSLDO, -+ AXP15060_SW, -+ AXP15060_RTC_LDO, -+ AXP15060_REG_ID_MAX, -+}; -+ - /* IRQs */ - enum { - AXP152_IRQ_LDO0IN_CONNECT = 1, -@@ -432,14 +570,51 @@ enum { - AXP152_IRQ_PEK_SHORT, - AXP152_IRQ_PEK_LONG, - AXP152_IRQ_TIMER, -- AXP152_IRQ_PEK_RIS_EDGE, -+ /* out of bit order to make sure the press event is handled first */ - AXP152_IRQ_PEK_FAL_EDGE, -+ AXP152_IRQ_PEK_RIS_EDGE, - AXP152_IRQ_GPIO3_INPUT, - AXP152_IRQ_GPIO2_INPUT, - AXP152_IRQ_GPIO1_INPUT, - AXP152_IRQ_GPIO0_INPUT, - }; - -+enum axp192_irqs { -+ AXP192_IRQ_ACIN_OVER_V = 1, -+ AXP192_IRQ_ACIN_PLUGIN, -+ AXP192_IRQ_ACIN_REMOVAL, -+ AXP192_IRQ_VBUS_OVER_V, -+ AXP192_IRQ_VBUS_PLUGIN, -+ AXP192_IRQ_VBUS_REMOVAL, -+ AXP192_IRQ_VBUS_V_LOW, -+ AXP192_IRQ_BATT_PLUGIN, -+ AXP192_IRQ_BATT_REMOVAL, -+ AXP192_IRQ_BATT_ENT_ACT_MODE, -+ AXP192_IRQ_BATT_EXIT_ACT_MODE, -+ AXP192_IRQ_CHARG, -+ AXP192_IRQ_CHARG_DONE, -+ AXP192_IRQ_BATT_TEMP_HIGH, -+ AXP192_IRQ_BATT_TEMP_LOW, -+ AXP192_IRQ_DIE_TEMP_HIGH, -+ AXP192_IRQ_CHARG_I_LOW, -+ AXP192_IRQ_DCDC1_V_LONG, -+ AXP192_IRQ_DCDC2_V_LONG, -+ AXP192_IRQ_DCDC3_V_LONG, -+ AXP192_IRQ_PEK_SHORT = 22, -+ AXP192_IRQ_PEK_LONG, -+ AXP192_IRQ_N_OE_PWR_ON, -+ AXP192_IRQ_N_OE_PWR_OFF, -+ AXP192_IRQ_VBUS_VALID, -+ AXP192_IRQ_VBUS_NOT_VALID, -+ AXP192_IRQ_VBUS_SESS_VALID, -+ AXP192_IRQ_VBUS_SESS_END, -+ AXP192_IRQ_LOW_PWR_LVL = 31, -+ AXP192_IRQ_TIMER, -+ AXP192_IRQ_GPIO2_INPUT = 37, -+ AXP192_IRQ_GPIO1_INPUT, -+ AXP192_IRQ_GPIO0_INPUT, -+}; -+ - enum { - AXP20X_IRQ_ACIN_OVER_V = 1, - AXP20X_IRQ_ACIN_PLUGIN, -@@ -472,8 +647,9 @@ enum { - AXP20X_IRQ_LOW_PWR_LVL1, - AXP20X_IRQ_LOW_PWR_LVL2, - AXP20X_IRQ_TIMER, -- AXP20X_IRQ_PEK_RIS_EDGE, -+ /* out of bit order to make sure the press event is handled first */ - AXP20X_IRQ_PEK_FAL_EDGE, -+ AXP20X_IRQ_PEK_RIS_EDGE, - AXP20X_IRQ_GPIO3_INPUT, - AXP20X_IRQ_GPIO2_INPUT, - AXP20X_IRQ_GPIO1_INPUT, -@@ -502,8 +678,9 @@ enum axp22x_irqs { - AXP22X_IRQ_LOW_PWR_LVL1, - AXP22X_IRQ_LOW_PWR_LVL2, - AXP22X_IRQ_TIMER, -- AXP22X_IRQ_PEK_RIS_EDGE, -+ /* out of bit order to make sure the press event is handled first */ - AXP22X_IRQ_PEK_FAL_EDGE, -+ AXP22X_IRQ_PEK_RIS_EDGE, - AXP22X_IRQ_GPIO1_INPUT, - AXP22X_IRQ_GPIO0_INPUT, - }; -@@ -545,6 +722,16 @@ enum axp288_irqs { - AXP288_IRQ_BC_USB_CHNG, - }; - -+enum axp313a_irqs { -+ AXP313A_IRQ_DIE_TEMP_HIGH, -+ AXP313A_IRQ_DCDC2_V_LOW = 2, -+ AXP313A_IRQ_DCDC3_V_LOW, -+ AXP313A_IRQ_PEK_LONG, -+ AXP313A_IRQ_PEK_SHORT, -+ AXP313A_IRQ_PEK_FAL_EDGE, -+ AXP313A_IRQ_PEK_RIS_EDGE, -+}; -+ - enum axp803_irqs { - AXP803_IRQ_ACIN_OVER_V = 1, - AXP803_IRQ_ACIN_PLUGIN, -@@ -571,8 +758,9 @@ enum axp803_irqs { - AXP803_IRQ_LOW_PWR_LVL1, - AXP803_IRQ_LOW_PWR_LVL2, - AXP803_IRQ_TIMER, -- AXP803_IRQ_PEK_RIS_EDGE, -+ /* out of bit order to make sure the press event is handled first */ - AXP803_IRQ_PEK_FAL_EDGE, -+ AXP803_IRQ_PEK_RIS_EDGE, - AXP803_IRQ_PEK_SHORT, - AXP803_IRQ_PEK_LONG, - AXP803_IRQ_PEK_OVER_OFF, -@@ -623,8 +811,9 @@ enum axp809_irqs { - AXP809_IRQ_LOW_PWR_LVL1, - AXP809_IRQ_LOW_PWR_LVL2, - AXP809_IRQ_TIMER, -- AXP809_IRQ_PEK_RIS_EDGE, -+ /* out of bit order to make sure the press event is handled first */ - AXP809_IRQ_PEK_FAL_EDGE, -+ AXP809_IRQ_PEK_RIS_EDGE, - AXP809_IRQ_PEK_SHORT, - AXP809_IRQ_PEK_LONG, - AXP809_IRQ_PEK_OVER_OFF, -@@ -632,6 +821,23 @@ enum axp809_irqs { - AXP809_IRQ_GPIO0_INPUT, - }; - -+enum axp15060_irqs { -+ AXP15060_IRQ_DIE_TEMP_HIGH_LV1 = 1, -+ AXP15060_IRQ_DIE_TEMP_HIGH_LV2, -+ AXP15060_IRQ_DCDC1_V_LOW, -+ AXP15060_IRQ_DCDC2_V_LOW, -+ AXP15060_IRQ_DCDC3_V_LOW, -+ AXP15060_IRQ_DCDC4_V_LOW, -+ AXP15060_IRQ_DCDC5_V_LOW, -+ AXP15060_IRQ_DCDC6_V_LOW, -+ AXP15060_IRQ_PEK_LONG, -+ AXP15060_IRQ_PEK_SHORT, -+ AXP15060_IRQ_GPIO1_INPUT, -+ AXP15060_IRQ_PEK_FAL_EDGE, -+ AXP15060_IRQ_PEK_RIS_EDGE, -+ AXP15060_IRQ_GPIO2_INPUT, -+}; -+ - struct axp20x_dev { - struct device *dev; - int irq; -@@ -698,4 +904,4 @@ int axp20x_device_probe(struct axp20x_de - */ - void axp20x_device_remove(struct axp20x_dev *axp20x); - --#endif /* __LINUX_MFD_AXP20X_H */ -+#endif /* __LINUX_MFD_AXP20X_H */ -\ No newline at end of file From 29b8ba75fa52d2a9db98521644dfcc61fcd6b6a1 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sat, 18 Nov 2023 23:10:25 +0800 Subject: [PATCH 8/9] sunxi: add support for Orange Pi Zero 3 Key features: Allwinner H618 SoC (Quad core Cortex-A53) 1/1.5/2/4 GiB LPDDR4 DRAM 1 USB 2.0 type C port (Power + OTG) 1 USB 2.0 host port 1Gbps Ethernet port Micro-HDMI port MicroSD slot Installation: Write the image to SD Card with dd. Signed-off-by: Chukun Pan --- package/boot/uboot-sunxi/Makefile | 10 + target/linux/sunxi/cortexa53/config-6.1 | 1 + target/linux/sunxi/image/cortexa53.mk | 12 + ...inner-h616-Split-Orange-Pi-Zero-2-DT.patch | 305 ++++++++++++++++++ ...inner-h616-Add-OrangePi-Zero-3-board.patch | 140 ++++++++ ...inner-h616-update-emac-for-Orange-Pi.patch | 57 ++++ 6 files changed, 525 insertions(+) create mode 100644 target/linux/sunxi/patches-6.1/005-v6.6-arm64-dts-allwinner-h616-Split-Orange-Pi-Zero-2-DT.patch create mode 100644 target/linux/sunxi/patches-6.1/006-v6.6-arm64-dts-allwinner-h616-Add-OrangePi-Zero-3-board.patch create mode 100644 target/linux/sunxi/patches-6.1/007-v6.7-arm64-dts-allwinner-h616-update-emac-for-Orange-Pi.patch diff --git a/package/boot/uboot-sunxi/Makefile b/package/boot/uboot-sunxi/Makefile index de07dbdec2..112ea47d21 100644 --- a/package/boot/uboot-sunxi/Makefile +++ b/package/boot/uboot-sunxi/Makefile @@ -339,6 +339,15 @@ define U-Boot/orangepi_zero2 ATF:=h616 endef +define U-Boot/orangepi_zero3 + BUILD_SUBTARGET:=cortexa53 + NAME:=Xunlong Orange Pi Zero3 + BUILD_DEVICES:=xunlong_orangepi-zero3 + DEPENDS:=+PACKAGE_u-boot-orangepi_zero3:trusted-firmware-a-sunxi-h616 + UENV:=h616 + ATF:=h616 +endef + define U-Boot/Bananapi_M2_Ultra BUILD_SUBTARGET:=cortexa7 NAME:=Bananapi M2 Ultra @@ -402,6 +411,7 @@ UBOOT_TARGETS := \ orangepi_2 \ orangepi_pc2 \ orangepi_zero2 \ + orangepi_zero3 \ pangolin \ pine64_plus \ Sinovoip_BPI_M3 \ diff --git a/target/linux/sunxi/cortexa53/config-6.1 b/target/linux/sunxi/cortexa53/config-6.1 index 5331352386..55bcd4e8e5 100644 --- a/target/linux/sunxi/cortexa53/config-6.1 +++ b/target/linux/sunxi/cortexa53/config-6.1 @@ -54,6 +54,7 @@ CONFIG_MDIO_BUS_MUX=y CONFIG_MICREL_PHY=y # CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_MOTORCOMM_PHY=y CONFIG_MUSB_PIO_ONLY=y CONFIG_NEED_SG_DMA_LENGTH=y CONFIG_NOP_USB_XCEIV=y diff --git a/target/linux/sunxi/image/cortexa53.mk b/target/linux/sunxi/image/cortexa53.mk index 80718b34bf..63ada59f85 100644 --- a/target/linux/sunxi/image/cortexa53.mk +++ b/target/linux/sunxi/image/cortexa53.mk @@ -29,6 +29,11 @@ define Device/sun50i-h616 $(Device/sun50i) endef +define Device/sun50i-h618 + SOC := sun50i-h618 + $(Device/sun50i) +endef + define Device/friendlyarm_nanopi-neo-plus2 DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi NEO Plus2 @@ -120,6 +125,13 @@ define Device/xunlong_orangepi-zero2 endef TARGET_DEVICES += xunlong_orangepi-zero2 +define Device/xunlong_orangepi-zero3 + DEVICE_VENDOR := Xunlong + DEVICE_MODEL := Orange Pi Zero 3 + $(Device/sun50i-h618) +endef +TARGET_DEVICES += xunlong_orangepi-zero3 + define Device/xunlong_orangepi-zero-plus DEVICE_VENDOR := Xunlong DEVICE_MODEL := Orange Pi Zero Plus diff --git a/target/linux/sunxi/patches-6.1/005-v6.6-arm64-dts-allwinner-h616-Split-Orange-Pi-Zero-2-DT.patch b/target/linux/sunxi/patches-6.1/005-v6.6-arm64-dts-allwinner-h616-Split-Orange-Pi-Zero-2-DT.patch new file mode 100644 index 0000000000..0747e6a8e0 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/005-v6.6-arm64-dts-allwinner-h616-Split-Orange-Pi-Zero-2-DT.patch @@ -0,0 +1,305 @@ +From 322bf103204b8f786547acbeed85569254e7088f Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 4 Aug 2023 18:08:54 +0100 +Subject: [PATCH] arm64: dts: allwinner: h616: Split Orange Pi Zero 2 DT + +The Orange Pi Zero 2 got a successor (Zero 3), which shares quite some +DT nodes with the Zero 2, but comes with a different PMIC. + +Move the common parts (except the PMIC) into a new shared file, and +include that from the existing board .dts file. + +No functional change, the generated DTB is the same, except for some +phandle numbering differences. + +Signed-off-by: Andre Przywara +Acked-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20230804170856.1237202-2-andre.przywara@arm.com +Signed-off-by: Jernej Skrabec +--- + .../allwinner/sun50i-h616-orangepi-zero.dtsi | 134 ++++++++++++++++++ + .../allwinner/sun50i-h616-orangepi-zero2.dts | 119 +--------------- + 2 files changed, 135 insertions(+), 118 deletions(-) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi + +--- /dev/null ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi +@@ -0,0 +1,134 @@ ++// SPDX-License-Identifier: (GPL-2.0+ or MIT) ++/* ++ * Copyright (C) 2020 Arm Ltd. ++ * ++ * DT nodes common between Orange Pi Zero 2 and Orange Pi Zero 3. ++ * Excludes PMIC nodes and properties, since they are different between the two. ++ */ ++ ++#include "sun50i-h616.dtsi" ++ ++#include ++#include ++#include ++ ++/ { ++ aliases { ++ ethernet0 = &emac0; ++ serial0 = &uart0; ++ }; ++ ++ chosen { ++ stdout-path = "serial0:115200n8"; ++ }; ++ ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ function = LED_FUNCTION_POWER; ++ color = ; ++ gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */ ++ default-state = "on"; ++ }; ++ ++ led-1 { ++ function = LED_FUNCTION_STATUS; ++ color = ; ++ gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */ ++ }; ++ }; ++ ++ reg_vcc5v: vcc5v { ++ /* board wide 5V supply directly from the USB-C socket */ ++ compatible = "regulator-fixed"; ++ regulator-name = "vcc-5v"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ regulator-always-on; ++ }; ++ ++ reg_usb1_vbus: regulator-usb1-vbus { ++ compatible = "regulator-fixed"; ++ regulator-name = "usb1-vbus"; ++ regulator-min-microvolt = <5000000>; ++ regulator-max-microvolt = <5000000>; ++ vin-supply = <®_vcc5v>; ++ enable-active-high; ++ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ ++ }; ++}; ++ ++&ehci1 { ++ status = "okay"; ++}; ++ ++/* USB 2 & 3 are on headers only. */ ++ ++&emac0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&ext_rgmii_pins>; ++ phy-mode = "rgmii"; ++ phy-handle = <&ext_rgmii_phy>; ++ allwinner,rx-delay-ps = <3100>; ++ allwinner,tx-delay-ps = <700>; ++ status = "okay"; ++}; ++ ++&mdio0 { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ }; ++}; ++ ++&mmc0 { ++ cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ ++ bus-width = <4>; ++ status = "okay"; ++}; ++ ++&ohci1 { ++ status = "okay"; ++}; ++ ++&spi0 { ++ status = "okay"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>; ++ ++ flash@0 { ++ #address-cells = <1>; ++ #size-cells = <1>; ++ compatible = "jedec,spi-nor"; ++ reg = <0>; ++ spi-max-frequency = <40000000>; ++ }; ++}; ++ ++&uart0 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_ph_pins>; ++ status = "okay"; ++}; ++ ++&usbotg { ++ /* ++ * PHY0 pins are connected to a USB-C socket, but a role switch ++ * is not implemented: both CC pins are pulled to GND. ++ * The VBUS pins power the device, so a fixed peripheral mode ++ * is the best choice. ++ * The board can be powered via GPIOs, in this case port0 *can* ++ * act as a host (with a cable/adapter ignoring CC), as VBUS is ++ * then provided by the GPIOs. Any user of this setup would ++ * need to adjust the DT accordingly: dr_mode set to "host", ++ * enabling OHCI0 and EHCI0. ++ */ ++ dr_mode = "peripheral"; ++ status = "okay"; ++}; ++ ++&usbphy { ++ usb1_vbus-supply = <®_usb1_vbus>; ++ status = "okay"; ++}; +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +@@ -5,95 +5,19 @@ + + /dts-v1/; + +-#include "sun50i-h616.dtsi" +- +-#include +-#include +-#include ++#include "sun50i-h616-orangepi-zero.dtsi" + + / { + model = "OrangePi Zero2"; + compatible = "xunlong,orangepi-zero2", "allwinner,sun50i-h616"; +- +- aliases { +- ethernet0 = &emac0; +- serial0 = &uart0; +- }; +- +- chosen { +- stdout-path = "serial0:115200n8"; +- }; +- +- leds { +- compatible = "gpio-leds"; +- +- led-0 { +- function = LED_FUNCTION_POWER; +- color = ; +- gpios = <&pio 2 12 GPIO_ACTIVE_HIGH>; /* PC12 */ +- default-state = "on"; +- }; +- +- led-1 { +- function = LED_FUNCTION_STATUS; +- color = ; +- gpios = <&pio 2 13 GPIO_ACTIVE_HIGH>; /* PC13 */ +- }; +- }; +- +- reg_vcc5v: vcc5v { +- /* board wide 5V supply directly from the USB-C socket */ +- compatible = "regulator-fixed"; +- regulator-name = "vcc-5v"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- regulator-always-on; +- }; +- +- reg_usb1_vbus: regulator-usb1-vbus { +- compatible = "regulator-fixed"; +- regulator-name = "usb1-vbus"; +- regulator-min-microvolt = <5000000>; +- regulator-max-microvolt = <5000000>; +- vin-supply = <®_vcc5v>; +- enable-active-high; +- gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */ +- }; +-}; +- +-&ehci1 { +- status = "okay"; + }; + +-/* USB 2 & 3 are on headers only. */ +- + &emac0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&ext_rgmii_pins>; +- phy-mode = "rgmii"; +- phy-handle = <&ext_rgmii_phy>; + phy-supply = <®_dcdce>; +- allwinner,rx-delay-ps = <3100>; +- allwinner,tx-delay-ps = <700>; +- status = "okay"; +-}; +- +-&mdio0 { +- ext_rgmii_phy: ethernet-phy@1 { +- compatible = "ethernet-phy-ieee802.3-c22"; +- reg = <1>; +- }; + }; + + &mmc0 { + vmmc-supply = <®_dcdce>; +- cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ +- bus-width = <4>; +- status = "okay"; +-}; +- +-&ohci1 { +- status = "okay"; + }; + + &r_rsb { +@@ -211,44 +135,3 @@ + vcc-ph-supply = <®_aldo1>; + vcc-pi-supply = <®_aldo1>; + }; +- +-&spi0 { +- status = "okay"; +- pinctrl-names = "default"; +- pinctrl-0 = <&spi0_pins>, <&spi0_cs0_pin>; +- +- flash@0 { +- #address-cells = <1>; +- #size-cells = <1>; +- compatible = "jedec,spi-nor"; +- reg = <0>; +- spi-max-frequency = <40000000>; +- }; +-}; +- +-&uart0 { +- pinctrl-names = "default"; +- pinctrl-0 = <&uart0_ph_pins>; +- status = "okay"; +-}; +- +-&usbotg { +- /* +- * PHY0 pins are connected to a USB-C socket, but a role switch +- * is not implemented: both CC pins are pulled to GND. +- * The VBUS pins power the device, so a fixed peripheral mode +- * is the best choice. +- * The board can be powered via GPIOs, in this case port0 *can* +- * act as a host (with a cable/adapter ignoring CC), as VBUS is +- * then provided by the GPIOs. Any user of this setup would +- * need to adjust the DT accordingly: dr_mode set to "host", +- * enabling OHCI0 and EHCI0. +- */ +- dr_mode = "peripheral"; +- status = "okay"; +-}; +- +-&usbphy { +- usb1_vbus-supply = <®_usb1_vbus>; +- status = "okay"; +-}; diff --git a/target/linux/sunxi/patches-6.1/006-v6.6-arm64-dts-allwinner-h616-Add-OrangePi-Zero-3-board.patch b/target/linux/sunxi/patches-6.1/006-v6.6-arm64-dts-allwinner-h616-Add-OrangePi-Zero-3-board.patch new file mode 100644 index 0000000000..4081a82d52 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/006-v6.6-arm64-dts-allwinner-h616-Add-OrangePi-Zero-3-board.patch @@ -0,0 +1,140 @@ +From f1b3ddb3ecc2eec1f912383e01156c226daacfab Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 4 Aug 2023 18:08:56 +0100 +Subject: [PATCH] arm64: dts: allwinner: h616: Add OrangePi Zero 3 board + support + +The OrangePi Zero 3 is a development board based on the Allwinner H618 SoC, +which seems to be just an H616 with more L2 cache. The board itself is a +slightly updated version of the Orange Pi Zero 2. It features: +- Four ARM Cortex-A53 cores, Mali-G31 MP2 GPU +- 1/1.5/2/4 GiB LPDDR4 DRAM SKUs (only up to 1GB on the Zero2) +- AXP313a PMIC (more capable AXP305 on the Zero2) +- Raspberry-Pi-1 compatible GPIO header +- extra 13 pin expansion header, exposing pins for 2x USB 2.0 ports +- 1 USB 2.0 host port +- 1 USB 2.0 type C port (power supply + OTG) +- MicroSD slot +- on-board 16MiB bootable SPI NOR flash (only 2MB on the Zero2) +- 1Gbps Ethernet port (via Motorcomm YT8531 PHY) (RTL8211 on the Zero2) +- micro-HDMI port +- (yet) unsupported Allwinner WiFi/BT chip + +Add the devicetree file describing the currently supported features, +namely LEDs, SD card, PMIC, SPI flash, USB. Ethernet seems unstable at +the moment, though the basic functionality works. + +Signed-off-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20230804170856.1237202-4-andre.przywara@arm.com +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/Makefile | 1 + + .../allwinner/sun50i-h618-orangepi-zero3.dts | 94 +++++++++++++++++++ + 2 files changed, 95 insertions(+) + create mode 100644 arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts + +--- a/arch/arm64/boot/dts/allwinner/Makefile ++++ b/arch/arm64/boot/dts/allwinner/Makefile +@@ -40,3 +40,4 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-ta + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-tanix-tx6-mini.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-orangepi-zero2.dtb + dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h616-x96-mate.dtb ++dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h618-orangepi-zero3.dtb +--- /dev/null ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts +@@ -0,0 +1,94 @@ ++// SPDX-License-Identifier: (GPL-2.0+ or MIT) ++/* ++ * Copyright (C) 2023 Arm Ltd. ++ */ ++ ++/dts-v1/; ++ ++#include "sun50i-h616-orangepi-zero.dtsi" ++ ++/ { ++ model = "OrangePi Zero3"; ++ compatible = "xunlong,orangepi-zero3", "allwinner,sun50i-h618"; ++}; ++ ++&emac0 { ++ phy-supply = <®_dldo1>; ++}; ++ ++&ext_rgmii_phy { ++ motorcomm,clk-out-frequency-hz = <125000000>; ++}; ++ ++&mmc0 { ++ /* ++ * The schematic shows the card detect pin wired up to PF6, via an ++ * inverter, but it just doesn't work. ++ */ ++ broken-cd; ++ vmmc-supply = <®_dldo1>; ++}; ++ ++&r_i2c { ++ status = "okay"; ++ ++ axp313: pmic@36 { ++ compatible = "x-powers,axp313a"; ++ reg = <0x36>; ++ #interrupt-cells = <1>; ++ interrupt-controller; ++ interrupt-parent = <&pio>; ++ interrupts = <2 9 IRQ_TYPE_LEVEL_LOW>; /* PC9 */ ++ ++ vin1-supply = <®_vcc5v>; ++ vin2-supply = <®_vcc5v>; ++ vin3-supply = <®_vcc5v>; ++ ++ regulators { ++ /* Supplies VCC-PLL, so needs to be always on. */ ++ reg_aldo1: aldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; ++ regulator-name = "vcc1v8"; ++ }; ++ ++ /* Supplies VCC-IO, so needs to be always on. */ ++ reg_dldo1: dldo1 { ++ regulator-always-on; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ regulator-name = "vcc3v3"; ++ }; ++ ++ reg_dcdc1: dcdc1 { ++ regulator-always-on; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <990000>; ++ regulator-name = "vdd-gpu-sys"; ++ }; ++ ++ reg_dcdc2: dcdc2 { ++ regulator-always-on; ++ regulator-min-microvolt = <810000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-name = "vdd-cpu"; ++ }; ++ ++ reg_dcdc3: dcdc3 { ++ regulator-always-on; ++ regulator-min-microvolt = <1100000>; ++ regulator-max-microvolt = <1100000>; ++ regulator-name = "vdd-dram"; ++ }; ++ }; ++ }; ++}; ++ ++&pio { ++ vcc-pc-supply = <®_dldo1>; ++ vcc-pf-supply = <®_dldo1>; ++ vcc-pg-supply = <®_aldo1>; ++ vcc-ph-supply = <®_dldo1>; ++ vcc-pi-supply = <®_dldo1>; ++}; diff --git a/target/linux/sunxi/patches-6.1/007-v6.7-arm64-dts-allwinner-h616-update-emac-for-Orange-Pi.patch b/target/linux/sunxi/patches-6.1/007-v6.7-arm64-dts-allwinner-h616-update-emac-for-Orange-Pi.patch new file mode 100644 index 0000000000..a492eed551 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/007-v6.7-arm64-dts-allwinner-h616-update-emac-for-Orange-Pi.patch @@ -0,0 +1,57 @@ +From b9622937d95809ef89904583191571a9fa326402 Mon Sep 17 00:00:00 2001 +From: Chukun Pan +Date: Sun, 29 Oct 2023 15:40:09 +0800 +Subject: [PATCH] arm64: dts: allwinner: h616: update emac for Orange Pi Zero 3 + +The current emac setting is not suitable for Orange Pi Zero 3, +move it back to Orange Pi Zero 2 DT. Also update phy mode and +delay values for emac on Orange Pi Zero 3. +With these changes, Ethernet now looks stable. + +Fixes: 322bf103204b ("arm64: dts: allwinner: h616: Split Orange Pi Zero 2 DT") +Signed-off-by: Chukun Pan +Reviewed-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20231029074009.7820-2-amadeus@jmu.edu.cn +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi | 3 --- + arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts | 3 +++ + arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts | 2 ++ + 3 files changed, 5 insertions(+), 3 deletions(-) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero.dtsi +@@ -68,10 +68,7 @@ + &emac0 { + pinctrl-names = "default"; + pinctrl-0 = <&ext_rgmii_pins>; +- phy-mode = "rgmii"; + phy-handle = <&ext_rgmii_phy>; +- allwinner,rx-delay-ps = <3100>; +- allwinner,tx-delay-ps = <700>; + status = "okay"; + }; + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts +@@ -13,6 +13,9 @@ + }; + + &emac0 { ++ allwinner,rx-delay-ps = <3100>; ++ allwinner,tx-delay-ps = <700>; ++ phy-mode = "rgmii"; + phy-supply = <®_dcdce>; + }; + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h618-orangepi-zero3.dts +@@ -13,6 +13,8 @@ + }; + + &emac0 { ++ allwinner,tx-delay-ps = <700>; ++ phy-mode = "rgmii-rxid"; + phy-supply = <®_dldo1>; + }; + From 29515862ac704506e1c7d567703a9d6247c69715 Mon Sep 17 00:00:00 2001 From: Chukun Pan Date: Sat, 9 Mar 2024 23:16:25 +0800 Subject: [PATCH 9/9] sunxi: backport h616 thermal sensor support Backport H616 thermal sensor support from linux-next. Tested on the Orange Pi Zero 3 (H618 SoC). Signed-off-by: Chukun Pan --- ...lwinner-h616-Add-SID-controller-node.patch | 31 ++++ ...am-export-register-0-for-THS-on-H616.patch | 98 +++++++++++++ ...-Add-D1-T113s-THS-controller-support.patch | 47 ++++++ ...8i-Explain-unknown-H6-register-value.patch | 79 ++++++++++ ...i-Extend-H6-calibration-to-support-4.patch | 74 ++++++++++ ...-sun8i-Add-SRAM-register-access-code.patch | 126 ++++++++++++++++ ...-Add-support-for-H616-THS-controller.patch | 50 +++++++ ...Dont-fail-probe-due-to-zone-registra.patch | 68 +++++++++ ...er-h616-Add-thermal-sensor-and-zones.patch | 138 ++++++++++++++++++ 9 files changed, 711 insertions(+) create mode 100644 target/linux/sunxi/patches-6.1/008-v6.7-arm64-dts-allwinner-h616-Add-SID-controller-node.patch create mode 100644 target/linux/sunxi/patches-6.1/009-v6.9-soc-sunxi-sram-export-register-0-for-THS-on-H616.patch create mode 100644 target/linux/sunxi/patches-6.1/010-v6.8-thermal-drivers-sun8i-Add-D1-T113s-THS-controller-support.patch create mode 100644 target/linux/sunxi/patches-6.1/011-v6.9-thermal-drivers-sun8i-Explain-unknown-H6-register-value.patch create mode 100644 target/linux/sunxi/patches-6.1/012-v6.9-thermal-drivers-sun8i-Extend-H6-calibration-to-support-4.patch create mode 100644 target/linux/sunxi/patches-6.1/013-v6.9-thermal-drivers-sun8i-Add-SRAM-register-access-code.patch create mode 100644 target/linux/sunxi/patches-6.1/014-v6.9-thermal-drivers-sun8i-Add-support-for-H616-THS-controller.patch create mode 100644 target/linux/sunxi/patches-6.1/015-v6.9-thermal-drivers-sun8i-Dont-fail-probe-due-to-zone-registra.patch create mode 100644 target/linux/sunxi/patches-6.1/016-v6.9-arm64-dts-allwinner-h616-Add-thermal-sensor-and-zones.patch diff --git a/target/linux/sunxi/patches-6.1/008-v6.7-arm64-dts-allwinner-h616-Add-SID-controller-node.patch b/target/linux/sunxi/patches-6.1/008-v6.7-arm64-dts-allwinner-h616-Add-SID-controller-node.patch new file mode 100644 index 0000000000..ce8add18ab --- /dev/null +++ b/target/linux/sunxi/patches-6.1/008-v6.7-arm64-dts-allwinner-h616-Add-SID-controller-node.patch @@ -0,0 +1,31 @@ +From 951992797378a2177946400438f4d23c9fceae5b Mon Sep 17 00:00:00 2001 +From: Martin Botka +Date: Tue, 12 Sep 2023 14:25:13 +0200 +Subject: [PATCH] arm64: dts: allwinner: h616: Add SID controller node + +Add node for the H616 SID controller + +Signed-off-by: Martin Botka +Acked-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20230912-sid-h616-v3-2-ee18e1c5bbb5@somainline.org +Signed-off-by: Jernej Skrabec +--- + arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +@@ -133,6 +133,13 @@ + #reset-cells = <1>; + }; + ++ sid: efuse@3006000 { ++ compatible = "allwinner,sun50i-h616-sid", "allwinner,sun50i-a64-sid"; ++ reg = <0x03006000 0x1000>; ++ #address-cells = <1>; ++ #size-cells = <1>; ++ }; ++ + watchdog: watchdog@30090a0 { + compatible = "allwinner,sun50i-h616-wdt", + "allwinner,sun6i-a31-wdt"; diff --git a/target/linux/sunxi/patches-6.1/009-v6.9-soc-sunxi-sram-export-register-0-for-THS-on-H616.patch b/target/linux/sunxi/patches-6.1/009-v6.9-soc-sunxi-sram-export-register-0-for-THS-on-H616.patch new file mode 100644 index 0000000000..3453e2aa53 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/009-v6.9-soc-sunxi-sram-export-register-0-for-THS-on-H616.patch @@ -0,0 +1,98 @@ +From 898d96c5464b69af44f6407c5de81ebc349d574b Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 19 Feb 2024 15:36:33 +0000 +Subject: [PATCH] soc: sunxi: sram: export register 0 for THS on H616 + +The Allwinner H616 SoC contains a mysterious bit at register offset 0x0 +in the SRAM control block. If bit 16 is set (the reset value), the +temperature readings of the THS are way off, leading to reports about +200C, at normal ambient temperatures. Clearing this bits brings the +reported values down to the expected values. +The BSP code clears this bit in firmware (U-Boot), and has an explicit +comment about this, but offers no real explanation. + +Experiments in U-Boot show that register 0x0 has no effect on the SRAM C +visibility: all tested bit settings still allow full read and write +access by the CPU to the whole of SRAM C. Only bit 24 of the register at +offset 0x4 makes all of SRAM C inaccessible by the CPU. So modelling +the THS switch functionality as an SRAM region would not reflect reality. + +Since we should not rely on firmware settings, allow other code (the THS +driver) to access this register, by exporting it through the already +existing regmap. This mimics what we already do for the LDO control and +the EMAC register. + +To avoid concurrent accesses to the same register at the same time, by +the SRAM switch code and the regmap code, use the same lock to protect +the access. The regmap subsystem allows to use an existing lock, so we +just need to hook in there. + +Signed-off-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240219153639.179814-2-andre.przywara@arm.com +--- + drivers/soc/sunxi/sunxi_sram.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +--- a/drivers/soc/sunxi/sunxi_sram.c ++++ b/drivers/soc/sunxi/sunxi_sram.c +@@ -284,6 +284,7 @@ EXPORT_SYMBOL(sunxi_sram_release); + struct sunxi_sramc_variant { + int num_emac_clocks; + bool has_ldo_ctrl; ++ bool has_ths_offset; + }; + + static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = { +@@ -305,8 +306,10 @@ static const struct sunxi_sramc_variant + + static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { + .num_emac_clocks = 2, ++ .has_ths_offset = true, + }; + ++#define SUNXI_SRAM_THS_OFFSET_REG 0x0 + #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 + #define SUNXI_SYS_LDO_CTRL_REG 0x150 + +@@ -315,6 +318,8 @@ static bool sunxi_sram_regmap_accessible + { + const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev); + ++ if (reg == SUNXI_SRAM_THS_OFFSET_REG && variant->has_ths_offset) ++ return true; + if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG && + reg < SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) + return true; +@@ -324,6 +329,20 @@ static bool sunxi_sram_regmap_accessible + return false; + } + ++static void sunxi_sram_lock(void *_lock) ++{ ++ spinlock_t *lock = _lock; ++ ++ spin_lock(lock); ++} ++ ++static void sunxi_sram_unlock(void *_lock) ++{ ++ spinlock_t *lock = _lock; ++ ++ spin_unlock(lock); ++} ++ + static struct regmap_config sunxi_sram_regmap_config = { + .reg_bits = 32, + .val_bits = 32, +@@ -333,6 +352,9 @@ static struct regmap_config sunxi_sram_r + /* other devices have no business accessing other registers */ + .readable_reg = sunxi_sram_regmap_accessible_reg, + .writeable_reg = sunxi_sram_regmap_accessible_reg, ++ .lock = sunxi_sram_lock, ++ .unlock = sunxi_sram_unlock, ++ .lock_arg = &sram_lock, + }; + + static int __init sunxi_sram_probe(struct platform_device *pdev) diff --git a/target/linux/sunxi/patches-6.1/010-v6.8-thermal-drivers-sun8i-Add-D1-T113s-THS-controller-support.patch b/target/linux/sunxi/patches-6.1/010-v6.8-thermal-drivers-sun8i-Add-D1-T113s-THS-controller-support.patch new file mode 100644 index 0000000000..8b19989118 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/010-v6.8-thermal-drivers-sun8i-Add-D1-T113s-THS-controller-support.patch @@ -0,0 +1,47 @@ +From ebbf19e36d021f253425344b4d4b987f3b7d9be5 Mon Sep 17 00:00:00 2001 +From: Maxim Kiselev +Date: Mon, 18 Dec 2023 00:06:23 +0300 +Subject: [PATCH] thermal/drivers/sun8i: Add D1/T113s THS controller support + +This patch adds a thermal sensor controller support for the D1/T113s, +which is similar to the one on H6, but with only one sensor and +different scale and offset values. + +Signed-off-by: Maxim Kiselev +Acked-by: Jernej Skrabec +Reviewed-by: Andre Przywara +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20231217210629.131486-3-bigunclemax@gmail.com +--- + drivers/thermal/sun8i_thermal.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -610,6 +610,18 @@ static const struct ths_thermal_chip sun + .calc_temp = sun8i_ths_calc_temp, + }; + ++static const struct ths_thermal_chip sun20i_d1_ths = { ++ .sensor_num = 1, ++ .has_bus_clk_reset = true, ++ .offset = 188552, ++ .scale = 673, ++ .temp_data_base = SUN50I_H6_THS_TEMP_DATA, ++ .calibrate = sun50i_h6_ths_calibrate, ++ .init = sun50i_h6_thermal_init, ++ .irq_ack = sun50i_h6_irq_ack, ++ .calc_temp = sun8i_ths_calc_temp, ++}; ++ + static const struct of_device_id of_ths_match[] = { + { .compatible = "allwinner,sun8i-a83t-ths", .data = &sun8i_a83t_ths }, + { .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths }, +@@ -618,6 +630,7 @@ static const struct of_device_id of_ths_ + { .compatible = "allwinner,sun50i-a100-ths", .data = &sun50i_a100_ths }, + { .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths }, + { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths }, ++ { .compatible = "allwinner,sun20i-d1-ths", .data = &sun20i_d1_ths }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, of_ths_match); diff --git a/target/linux/sunxi/patches-6.1/011-v6.9-thermal-drivers-sun8i-Explain-unknown-H6-register-value.patch b/target/linux/sunxi/patches-6.1/011-v6.9-thermal-drivers-sun8i-Explain-unknown-H6-register-value.patch new file mode 100644 index 0000000000..b8138a3870 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/011-v6.9-thermal-drivers-sun8i-Explain-unknown-H6-register-value.patch @@ -0,0 +1,79 @@ +From 14f118aa50fe7c7c7330f56d007ecacca487cea8 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 19 Feb 2024 15:36:35 +0000 +Subject: [PATCH] thermal/drivers/sun8i: Explain unknown H6 register value + +So far we were ORing in some "unknown" value into the THS control +register on the Allwinner H6. This part of the register is not explained +in the H6 manual, but the H616 manual details those bits, and on closer +inspection the THS IP blocks in both SoCs seem very close: +- The BSP code for both SoCs writes the same values into THS_CTRL. +- The reset values of at least the first three registers are the same. + +Replace the "unknown" value with its proper meaning: "acquire time", +most probably the sample part of the sample & hold circuit of the ADC, +according to its explanation in the H616 manual. + +No functional change, just a macro rename and adjustment. + +Signed-off-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Acked-by: Vasily Khoruzhick +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240219153639.179814-4-andre.przywara@arm.com +--- + drivers/thermal/sun8i_thermal.c | 29 ++++++++++++++++------------- + 1 file changed, 16 insertions(+), 13 deletions(-) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -50,7 +50,8 @@ + #define SUN8I_THS_CTRL2_T_ACQ1(x) ((GENMASK(15, 0) & (x)) << 16) + #define SUN8I_THS_DATA_IRQ_STS(x) BIT(x + 8) + +-#define SUN50I_THS_CTRL0_T_ACQ(x) ((GENMASK(15, 0) & (x)) << 16) ++#define SUN50I_THS_CTRL0_T_ACQ(x) (GENMASK(15, 0) & ((x) - 1)) ++#define SUN50I_THS_CTRL0_T_SAMPLE_PER(x) ((GENMASK(15, 0) & ((x) - 1)) << 16) + #define SUN50I_THS_FILTER_EN BIT(2) + #define SUN50I_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) + #define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) +@@ -410,25 +411,27 @@ static int sun8i_h3_thermal_init(struct + return 0; + } + +-/* +- * Without this undocumented value, the returned temperatures would +- * be higher than real ones by about 20C. +- */ +-#define SUN50I_H6_CTRL0_UNK 0x0000002f +- + static int sun50i_h6_thermal_init(struct ths_device *tmdev) + { + int val; + + /* +- * T_acq = 20us +- * clkin = 24MHz +- * +- * x = T_acq * clkin - 1 +- * = 479 ++ * The manual recommends an overall sample frequency of 50 KHz (20us, ++ * 480 cycles at 24 MHz), which provides plenty of time for both the ++ * acquisition time (>24 cycles) and the actual conversion time ++ * (>14 cycles). ++ * The lower half of the CTRL register holds the "acquire time", in ++ * clock cycles, which the manual recommends to be 2us: ++ * 24MHz * 2us = 48 cycles. ++ * The high half of THS_CTRL encodes the sample frequency, in clock ++ * cycles: 24MHz * 20us = 480 cycles. ++ * This is explained in the H616 manual, but apparently wrongly ++ * described in the H6 manual, although the BSP code does the same ++ * for both SoCs. + */ + regmap_write(tmdev->regmap, SUN50I_THS_CTRL0, +- SUN50I_H6_CTRL0_UNK | SUN50I_THS_CTRL0_T_ACQ(479)); ++ SUN50I_THS_CTRL0_T_ACQ(48) | ++ SUN50I_THS_CTRL0_T_SAMPLE_PER(480)); + /* average over 4 samples */ + regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC, + SUN50I_THS_FILTER_EN | diff --git a/target/linux/sunxi/patches-6.1/012-v6.9-thermal-drivers-sun8i-Extend-H6-calibration-to-support-4.patch b/target/linux/sunxi/patches-6.1/012-v6.9-thermal-drivers-sun8i-Extend-H6-calibration-to-support-4.patch new file mode 100644 index 0000000000..3d01a507fa --- /dev/null +++ b/target/linux/sunxi/patches-6.1/012-v6.9-thermal-drivers-sun8i-Extend-H6-calibration-to-support-4.patch @@ -0,0 +1,74 @@ +From 6c04a419a4c5fb18edefc44dd676fb95c7f6c55d Mon Sep 17 00:00:00 2001 +From: Maksim Kiselev +Date: Mon, 19 Feb 2024 15:36:36 +0000 +Subject: [PATCH] thermal/drivers/sun8i: Extend H6 calibration to support 4 + sensors + +The H616 SoC resembles the H6 thermal sensor controller, with a few +changes like four sensors. + +Extend sun50i_h6_ths_calibrate() function to support calibration of +these sensors. + +Co-developed-by: Martin Botka +Signed-off-by: Martin Botka +Signed-off-by: Maksim Kiselev +Reviewed-by: Andre Przywara +Signed-off-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Acked-by: Vasily Khoruzhick +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240219153639.179814-5-andre.przywara@arm.com +--- + drivers/thermal/sun8i_thermal.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -224,16 +224,21 @@ static int sun50i_h6_ths_calibrate(struc + struct device *dev = tmdev->dev; + int i, ft_temp; + +- if (!caldata[0] || callen < 2 + 2 * tmdev->chip->sensor_num) ++ if (!caldata[0]) + return -EINVAL; + + /* + * efuse layout: + * +- * 0 11 16 32 +- * +-------+-------+-------+ +- * |temp| |sensor0|sensor1| +- * +-------+-------+-------+ ++ * 0 11 16 27 32 43 48 57 ++ * +----------+-----------+-----------+-----------+ ++ * | temp | |sensor0| |sensor1| |sensor2| | ++ * +----------+-----------+-----------+-----------+ ++ * ^ ^ ^ ++ * | | | ++ * | | sensor3[11:8] ++ * | sensor3[7:4] ++ * sensor3[3:0] + * + * The calibration data on the H6 is the ambient temperature and + * sensor values that are filled during the factory test stage. +@@ -246,9 +251,16 @@ static int sun50i_h6_ths_calibrate(struc + ft_temp = (caldata[0] & FT_TEMP_MASK) * 100; + + for (i = 0; i < tmdev->chip->sensor_num; i++) { +- int sensor_reg = caldata[i + 1] & TEMP_CALIB_MASK; +- int cdata, offset; +- int sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg); ++ int sensor_reg, sensor_temp, cdata, offset; ++ ++ if (i == 3) ++ sensor_reg = (caldata[1] >> 12) ++ | ((caldata[2] >> 12) << 4) ++ | ((caldata[3] >> 12) << 8); ++ else ++ sensor_reg = caldata[i + 1] & TEMP_CALIB_MASK; ++ ++ sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg); + + /* + * Calibration data is CALIBRATE_DEFAULT - (calculated diff --git a/target/linux/sunxi/patches-6.1/013-v6.9-thermal-drivers-sun8i-Add-SRAM-register-access-code.patch b/target/linux/sunxi/patches-6.1/013-v6.9-thermal-drivers-sun8i-Add-SRAM-register-access-code.patch new file mode 100644 index 0000000000..6db1e32cfb --- /dev/null +++ b/target/linux/sunxi/patches-6.1/013-v6.9-thermal-drivers-sun8i-Add-SRAM-register-access-code.patch @@ -0,0 +1,126 @@ +From f8b54d1120b81ed57bed96cc8e814ba08886d1e5 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Mon, 19 Feb 2024 15:36:37 +0000 +Subject: [PATCH] thermal/drivers/sun8i: Add SRAM register access code + +The Allwinner H616 SoC needs to clear a bit in one register in the SRAM +controller, to report reasonable temperature values. On reset, bit 16 in +register 0x3000000 is set, which leads to the driver reporting +temperatures around 200C. Clearing this bit brings the values down to the +expected range. The BSP code does a one-time write in U-Boot, with a +comment just mentioning the effect on the THS, but offering no further +explanation. + +To not rely on firmware to set things up for us, add code that queries +the SRAM controller device via a DT phandle link, then clear just this +single bit. + +Signed-off-by: Andre Przywara +Acked-by: Vasily Khoruzhick +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240219153639.179814-6-andre.przywara@arm.com +--- + drivers/thermal/sun8i_thermal.c | 51 +++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -68,6 +69,7 @@ struct tsensor { + struct ths_thermal_chip { + bool has_mod_clk; + bool has_bus_clk_reset; ++ bool needs_sram; + int sensor_num; + int offset; + int scale; +@@ -85,12 +87,16 @@ struct ths_device { + const struct ths_thermal_chip *chip; + struct device *dev; + struct regmap *regmap; ++ struct regmap_field *sram_regmap_field; + struct reset_control *reset; + struct clk *bus_clk; + struct clk *mod_clk; + struct tsensor sensor[MAX_SENSOR_NUM]; + }; + ++/* The H616 needs to have a bit 16 in the SRAM control register cleared. */ ++static const struct reg_field sun8i_ths_sram_reg_field = REG_FIELD(0x0, 16, 16); ++ + /* Temp Unit: millidegree Celsius */ + static int sun8i_ths_calc_temp(struct ths_device *tmdev, + int id, int reg) +@@ -337,6 +343,34 @@ static void sun8i_ths_reset_control_asse + reset_control_assert(data); + } + ++static struct regmap *sun8i_ths_get_sram_regmap(struct device_node *node) ++{ ++ struct device_node *sram_node; ++ struct platform_device *sram_pdev; ++ struct regmap *regmap = NULL; ++ ++ sram_node = of_parse_phandle(node, "allwinner,sram", 0); ++ if (!sram_node) ++ return ERR_PTR(-ENODEV); ++ ++ sram_pdev = of_find_device_by_node(sram_node); ++ if (!sram_pdev) { ++ /* platform device might not be probed yet */ ++ regmap = ERR_PTR(-EPROBE_DEFER); ++ goto out_put_node; ++ } ++ ++ /* If no regmap is found then the other device driver is at fault */ ++ regmap = dev_get_regmap(&sram_pdev->dev, NULL); ++ if (!regmap) ++ regmap = ERR_PTR(-EINVAL); ++ ++ platform_device_put(sram_pdev); ++out_put_node: ++ of_node_put(sram_node); ++ return regmap; ++} ++ + static int sun8i_ths_resource_init(struct ths_device *tmdev) + { + struct device *dev = tmdev->dev; +@@ -381,6 +415,19 @@ static int sun8i_ths_resource_init(struc + if (ret) + return ret; + ++ if (tmdev->chip->needs_sram) { ++ struct regmap *regmap; ++ ++ regmap = sun8i_ths_get_sram_regmap(dev->of_node); ++ if (IS_ERR(regmap)) ++ return PTR_ERR(regmap); ++ tmdev->sram_regmap_field = devm_regmap_field_alloc(dev, ++ regmap, ++ sun8i_ths_sram_reg_field); ++ if (IS_ERR(tmdev->sram_regmap_field)) ++ return PTR_ERR(tmdev->sram_regmap_field); ++ } ++ + ret = sun8i_ths_calibrate(tmdev); + if (ret) + return ret; +@@ -427,6 +474,10 @@ static int sun50i_h6_thermal_init(struct + { + int val; + ++ /* The H616 needs to have a bit in the SRAM control register cleared. */ ++ if (tmdev->sram_regmap_field) ++ regmap_field_write(tmdev->sram_regmap_field, 0); ++ + /* + * The manual recommends an overall sample frequency of 50 KHz (20us, + * 480 cycles at 24 MHz), which provides plenty of time for both the diff --git a/target/linux/sunxi/patches-6.1/014-v6.9-thermal-drivers-sun8i-Add-support-for-H616-THS-controller.patch b/target/linux/sunxi/patches-6.1/014-v6.9-thermal-drivers-sun8i-Add-support-for-H616-THS-controller.patch new file mode 100644 index 0000000000..e743d344c6 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/014-v6.9-thermal-drivers-sun8i-Add-support-for-H616-THS-controller.patch @@ -0,0 +1,50 @@ +From e7dbfa19572a1440a2e67ef70f94ff204849a0a8 Mon Sep 17 00:00:00 2001 +From: Martin Botka +Date: Mon, 19 Feb 2024 15:36:38 +0000 +Subject: [PATCH] thermal/drivers/sun8i: Add support for H616 THS controller + +Add support for the thermal sensor found in H616 SoCs, is the same as +the H6 thermal sensor controller, but with four sensors. +Also the registers readings are wrong, unless a bit in the first SYS_CFG +register cleared, so set exercise the SRAM regmap to take care of that. + +Signed-off-by: Martin Botka +Signed-off-by: Andre Przywara +Acked-by: Vasily Khoruzhick +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240219153639.179814-7-andre.przywara@arm.com +--- + drivers/thermal/sun8i_thermal.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -688,6 +688,20 @@ static const struct ths_thermal_chip sun + .calc_temp = sun8i_ths_calc_temp, + }; + ++static const struct ths_thermal_chip sun50i_h616_ths = { ++ .sensor_num = 4, ++ .has_bus_clk_reset = true, ++ .needs_sram = true, ++ .ft_deviation = 8000, ++ .offset = 263655, ++ .scale = 810, ++ .temp_data_base = SUN50I_H6_THS_TEMP_DATA, ++ .calibrate = sun50i_h6_ths_calibrate, ++ .init = sun50i_h6_thermal_init, ++ .irq_ack = sun50i_h6_irq_ack, ++ .calc_temp = sun8i_ths_calc_temp, ++}; ++ + static const struct of_device_id of_ths_match[] = { + { .compatible = "allwinner,sun8i-a83t-ths", .data = &sun8i_a83t_ths }, + { .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths }, +@@ -697,6 +711,7 @@ static const struct of_device_id of_ths_ + { .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths }, + { .compatible = "allwinner,sun50i-h6-ths", .data = &sun50i_h6_ths }, + { .compatible = "allwinner,sun20i-d1-ths", .data = &sun20i_d1_ths }, ++ { .compatible = "allwinner,sun50i-h616-ths", .data = &sun50i_h616_ths }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, of_ths_match); diff --git a/target/linux/sunxi/patches-6.1/015-v6.9-thermal-drivers-sun8i-Dont-fail-probe-due-to-zone-registra.patch b/target/linux/sunxi/patches-6.1/015-v6.9-thermal-drivers-sun8i-Dont-fail-probe-due-to-zone-registra.patch new file mode 100644 index 0000000000..384bf55084 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/015-v6.9-thermal-drivers-sun8i-Dont-fail-probe-due-to-zone-registra.patch @@ -0,0 +1,68 @@ +From 9ac53d5532cc4bb595bbee86ccba2172ccc336c3 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Tue, 23 Jan 2024 23:33:07 +0000 +Subject: [PATCH] thermal/drivers/sun8i: Don't fail probe due to zone + registration failure + +Currently the sun8i thermal driver will fail to probe if any of the +thermal zones it is registering fails to register with the thermal core. +Since we currently do not define any trip points for the GPU thermal +zones on at least A64 or H5 this means that we have no thermal support +on these platforms: + +[ 1.698703] thermal_sys: Failed to find 'trips' node +[ 1.698707] thermal_sys: Failed to find trip points for thermal-sensor id=1 + +even though the main CPU thermal zone on both SoCs is fully configured. +This does not seem ideal, while we may not be able to use all the zones +it seems better to have those zones which are usable be operational. +Instead just carry on registering zones if we get any non-deferral +error, allowing use of those zones which are usable. + +This means that we also need to update the interrupt handler to not +attempt to notify the core for events on zones which we have not +registered, I didn't see an ability to mask individual interrupts and +I would expect that interrupts would still be indicated in the ISR even +if they were masked. + +Reviewed-by: Vasily Khoruzhick +Acked-by: Jernej Skrabec +Signed-off-by: Mark Brown +Signed-off-by: Daniel Lezcano +Link: https://lore.kernel.org/r/20240123-thermal-sun8i-registration-v3-1-3e5771b1bbdd@kernel.org +--- + drivers/thermal/sun8i_thermal.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -197,6 +197,9 @@ static irqreturn_t sun8i_irq_thread(int + int i; + + for_each_set_bit(i, &irq_bitmap, tmdev->chip->sensor_num) { ++ /* We allow some zones to not register. */ ++ if (IS_ERR(tmdev->sensor[i].tzd)) ++ continue; + thermal_zone_device_update(tmdev->sensor[i].tzd, + THERMAL_EVENT_UNSPECIFIED); + } +@@ -531,8 +534,17 @@ static int sun8i_ths_register(struct ths + i, + &tmdev->sensor[i], + &ths_ops); +- if (IS_ERR(tmdev->sensor[i].tzd)) +- return PTR_ERR(tmdev->sensor[i].tzd); ++ ++ /* ++ * If an individual zone fails to register for reasons ++ * other than probe deferral (eg, a bad DT) then carry ++ * on, other zones might register successfully. ++ */ ++ if (IS_ERR(tmdev->sensor[i].tzd)) { ++ if (PTR_ERR(tmdev->sensor[i].tzd) == -EPROBE_DEFER) ++ return PTR_ERR(tmdev->sensor[i].tzd); ++ continue; ++ } + + if (devm_thermal_add_hwmon_sysfs(tmdev->sensor[i].tzd)) + dev_warn(tmdev->dev, diff --git a/target/linux/sunxi/patches-6.1/016-v6.9-arm64-dts-allwinner-h616-Add-thermal-sensor-and-zones.patch b/target/linux/sunxi/patches-6.1/016-v6.9-arm64-dts-allwinner-h616-Add-thermal-sensor-and-zones.patch new file mode 100644 index 0000000000..cd6542bf14 --- /dev/null +++ b/target/linux/sunxi/patches-6.1/016-v6.9-arm64-dts-allwinner-h616-Add-thermal-sensor-and-zones.patch @@ -0,0 +1,138 @@ +From f4318af40544b8e7ff5a6b667ede60e6cf808262 Mon Sep 17 00:00:00 2001 +From: Martin Botka +Date: Mon, 19 Feb 2024 15:36:39 +0000 +Subject: [PATCH] arm64: dts: allwinner: h616: Add thermal sensor and zones + +There are four thermal sensors: +- CPU +- GPU +- VE +- DRAM + +Add the thermal sensor configuration and the thermal zones. + +Signed-off-by: Martin Botka +Signed-off-by: Andre Przywara +Reviewed-by: Jernej Skrabec +Link: https://lore.kernel.org/r/20240219153639.179814-8-andre.przywara@arm.com +Signed-off-by: Jernej Skrabec +--- + .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 88 +++++++++++++++++++ + 1 file changed, 88 insertions(+) + +--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -138,6 +139,10 @@ + reg = <0x03006000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ ths_calibration: thermal-sensor-calibration@14 { ++ reg = <0x14 0x8>; ++ }; + }; + + watchdog: watchdog@30090a0 { +@@ -511,6 +516,19 @@ + }; + }; + ++ ths: thermal-sensor@5070400 { ++ compatible = "allwinner,sun50i-h616-ths"; ++ reg = <0x05070400 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>; ++ clock-names = "bus"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration>; ++ nvmem-cell-names = "calibration"; ++ allwinner,sram = <&syscon>; ++ #thermal-sensor-cells = <1>; ++ }; ++ + usbotg: usb@5100000 { + compatible = "allwinner,sun50i-h616-musb", + "allwinner,sun8i-h3-musb"; +@@ -755,4 +773,74 @@ + #size-cells = <0>; + }; + }; ++ ++ thermal-zones { ++ cpu-thermal { ++ polling-delay-passive = <500>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 2>; ++ sustainable-power = <1000>; ++ ++ trips { ++ cpu_threshold: cpu-trip-0 { ++ temperature = <60000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu_target: cpu-trip-1 { ++ temperature = <70000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu_critical: cpu-trip-2 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ ++ gpu-thermal { ++ polling-delay-passive = <500>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths 0>; ++ sustainable-power = <1100>; ++ ++ trips { ++ gpu_temp_critical: gpu-trip-0 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ ++ ve-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 1>; ++ ++ trips { ++ ve_temp_critical: ve-trip-0 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ ++ ddr-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths 3>; ++ ++ trips { ++ ddr_temp_critical: ddr-trip-0 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ }; + };