diff --git a/config/sources/families/sun55iw3.conf b/config/sources/families/sun55iw3.conf index a58e7a4387d3..8b879b8265dd 100644 --- a/config/sources/families/sun55iw3.conf +++ b/config/sources/families/sun55iw3.conf @@ -25,8 +25,8 @@ declare -g LINUXCONFIG="linux-sunxi64-${BRANCH}" case "${BRANCH}" in edge) - declare -g KERNEL_MAJOR_MINOR="6.16" # Major and minor versions of this kernel. - declare -g KERNELBRANCH="tag:v6.16" + declare -g KERNEL_MAJOR_MINOR="6.18" # Major and minor versions of this kernel. + declare -g KERNELBRANCH="tag:v6.18-rc4" declare -g KERNELPATCHDIR="archive/sunxi-dev-${KERNEL_MAJOR_MINOR}" ;; esac diff --git a/patch/kernel/archive/sunxi-dev-6.17/00-Add-leds-Radxa-Cubie-A5E.patch b/patch/kernel/archive/sunxi-dev-6.17/00-Add-leds-Radxa-Cubie-A5E.patch new file mode 100644 index 000000000000..71f4db1c1e27 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/00-Add-leds-Radxa-Cubie-A5E.patch @@ -0,0 +1,44 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Sat, 14 Jun 2025 19:07:52 -0400 +Subject: Add leds to Radxa Cubie A5E + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 16 ++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 0f58d92a6adc..1c56306dffa1 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -18,10 +18,26 @@ aliases { + + chosen { + stdout-path = "serial0:115200n8"; + }; + ++ leds { ++ compatible = "gpio-leds"; ++ ++ led-0 { ++ label = "radxa:green:power"; ++ gpios = <&r_pio 0 4 GPIO_ACTIVE_LOW>; /* PL4 */ ++ linux,default-trigger = "heartbeat"; ++ }; ++ ++ led-1 { ++ label = "radxa:blue:user"; ++ gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */ ++ linux,default-trigger = "default-on"; ++ }; ++ }; ++ + ext_osc32k: ext-osc32k-clk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.17/01-Add-wifi-to-Radxa-Cubie-A5E.patch b/patch/kernel/archive/sunxi-dev-6.17/01-Add-wifi-to-Radxa-Cubie-A5E.patch new file mode 100644 index 000000000000..ce6ab963e209 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/01-Add-wifi-to-Radxa-Cubie-A5E.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Fri, 4 Jul 2025 15:17:54 -0400 +Subject: Add wifi (mmc1) to Radxa Cubie A5E + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 28 ++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 1c56306dffa1..d9bbfb916090 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -11,10 +11,11 @@ / { + model = "Radxa Cubie A5E"; + compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527"; + + aliases { + ethernet0 = &gmac0; ++ ethernet2 = &sdio_wifi; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; +@@ -41,10 +42,20 @@ ext_osc32k: ext-osc32k-clk { + compatible = "fixed-clock"; + clock-frequency = <32768>; + clock-output-names = "ext_osc32k"; + }; + ++ reg_3v3_wifi: 3v3-wifi { ++ compatible = "regulator-fixed"; ++ regulator-name = "3v3-wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <®_vcc5v>; ++ gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ ++ enable-active-high; ++ }; ++ + reg_vcc5v: vcc5v { + /* board wide 5V supply from the USB-C connector */ + compatible = "regulator-fixed"; + regulator-name = "vcc-5v"; + regulator-min-microvolt = <5000000>; +@@ -94,10 +105,27 @@ &mmc0 { + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PF6 */ + bus-width = <4>; + status = "okay"; + }; + ++&mmc1_pins { ++ drive-strength = <40>; ++}; ++ ++&mmc1 { ++ bus-width = <4>; ++ vmmc-supply = <®_3v3_wifi>; ++ non-removable; ++ // todo: investigate why clock above 40MHz makes data errors ++ max-frequency = <35000000>; ++ status = "okay"; ++ ++ sdio_wifi: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ + &ohci0 { + status = "okay"; + }; + + &ohci1 { +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.17/07-arm64-dts-allwinner-a527-cubie-a5e-Add-ethernet-PHY-reset-setting.patch b/patch/kernel/archive/sunxi-dev-6.17/07-arm64-dts-allwinner-a527-cubie-a5e-Add-ethernet-PHY-reset-setting.patch new file mode 100644 index 000000000000..92aebda7466d --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/07-arm64-dts-allwinner-a527-cubie-a5e-Add-ethernet-PHY-reset-setting.patch @@ -0,0 +1,29 @@ +From: Chen-Yu Tsai + +The external Ethernet PHY has a reset pin that is connected to the SoC. +It is missing from the original submission. + +Add it to complete the description. + +Fixes: acca163f3f51 ("arm64: dts: allwinner: a527: add EMAC0 to Radxa A5E board") +Signed-off-by: Chen-Yu Tsai +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 8bc0f2c72a24..c57ecc420aed 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -70,6 +70,9 @@ &mdio0 { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; ++ reset-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; + }; + }; + +-- +2.39.5 diff --git a/patch/kernel/archive/sunxi-dev-6.17/08-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Ethernet-port.patch b/patch/kernel/archive/sunxi-dev-6.17/08-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Ethernet-port.patch new file mode 100644 index 000000000000..6f08c041cf84 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/08-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Ethernet-port.patch @@ -0,0 +1,80 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Sat, 5 Jul 2025 22:59:14 -0400 +Subject: From: Chen-Yu Tsai + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 26 +++++++++- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 76e41202ecc8..592a50436454 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -11,10 +11,11 @@ / { + model = "Radxa Cubie A5E"; + compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527"; + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + ethernet2 = &sdio_wifi; + serial0 = &uart0; + }; + + chosen { +@@ -86,7 +86,7 @@ &ehci1 { + + &gmac0 { + phy-mode = "rgmii-id"; +- phy-handle = <&ext_rgmii_phy>; ++ phy-handle = <&ext_rgmii0_phy>; + phy-supply = <®_cldo3>; + + allwinner,tx-delay-ps = <300>; +@@ -95,19 +95,40 @@ &gmac0 { + status = "okay"; + }; + ++&gmac1 { ++ phy-mode = "rgmii-id"; ++ phy-handle = <&ext_rgmii1_phy>; ++ phy-supply = <®_cldo4>; ++ ++ allwinner,tx-delay-ps = <300>; ++ allwinner,rx-delay-ps = <400>; ++ ++ status = "okay"; ++}; ++ + &gpu { + mali-supply = <®_dcdc2>; + status = "okay"; + }; + + &mdio0 { +- ext_rgmii_phy: ethernet-phy@1 { ++ ext_rgmii0_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + reset-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ + reset-assert-us = <10000>; + reset-deassert-us = <150000>; + }; ++}; ++ ++&mdio1 { ++ ext_rgmii1_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ reset-gpios = <&pio 9 16 GPIO_ACTIVE_LOW>; /* PJ16 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; + }; + + &mmc0 { +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.17/11-dt-bindings-net-sun8i-emac-Add-A523-GMAC200-compatible.patch b/patch/kernel/archive/sunxi-dev-6.17/11-dt-bindings-net-sun8i-emac-Add-A523-GMAC200-compatible.patch new file mode 100644 index 000000000000..004056112aba --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/11-dt-bindings-net-sun8i-emac-Add-A523-GMAC200-compatible.patch @@ -0,0 +1,134 @@ +From: Chen-Yu Tsai + +The Allwinner A523 SoC family has a second Ethernet controller, called +the GMAC200 in the BSP and T527 datasheet, and referred to as GMAC1 for +numbering. This controller, according to BSP sources, is fully +compatible with a slightly newer version of the Synopsys DWMAC core. +The glue layer around the controller is the same as found around older +DWMAC cores on Allwinner SoCs. The only slight difference is that since +this is the second controller on the SoC, the register for the clock +delay controls is at a different offset. Last, the integration includes +a dedicated clock gate for the memory bus and the whole thing is put in +a separately controllable power domain. + +Add a compatible string entry for it, and work in the requirements for +a second clock and a power domain. + +Signed-off-by: Chen-Yu Tsai +--- + .../net/allwinner,sun8i-a83t-emac.yaml | 68 ++++++++++++++++++- + 1 file changed, 66 insertions(+), 2 deletions(-) + +diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +index 2ac709a4c472..1058e5af92ba 100644 +--- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml ++++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +@@ -26,6 +26,9 @@ properties: + - allwinner,sun50i-h616-emac0 + - allwinner,sun55i-a523-gmac0 + - const: allwinner,sun50i-a64-emac ++ - items: ++ - const: allwinner,sun55i-a523-gmac200 ++ - const: snps,dwmac-4.20a + + reg: + maxItems: 1 +@@ -37,14 +40,19 @@ properties: + const: macirq + + clocks: +- maxItems: 1 ++ minItems: 1 ++ maxItems: 2 + + clock-names: +- const: stmmaceth ++ minItems: 1 ++ maxItems: 2 + + phy-supply: + description: PHY regulator + ++ power-domains: ++ maxItems: 1 ++ + syscon: + $ref: /schemas/types.yaml#/definitions/phandle + description: +@@ -75,6 +83,7 @@ allOf: + - allwinner,sun8i-h3-emac + - allwinner,sun8i-v3s-emac + - allwinner,sun50i-a64-emac ++ - allwinner,sun55i-a523-gmac200 + + then: + properties: +@@ -191,6 +200,31 @@ allOf: + - mdio-parent-bus + - mdio@1 + ++ - if: ++ properties: ++ compatible: ++ contains: ++ const: allwinner,sun55i-a523-gmac200 ++ then: ++ properties: ++ clocks: ++ minItems: 2 ++ clock-names: ++ items: ++ - const: stmmaceth ++ - const: mbus ++ required: ++ - power-domains ++ else: ++ properties: ++ clocks: ++ maxItems: 1 ++ clock-names: ++ items: ++ - const: stmmaceth ++ power-domains: false ++ ++ + unevaluatedProperties: false + + examples: +@@ -323,4 +357,34 @@ examples: + }; + }; + ++ - | ++ ethernet@4510000 { ++ compatible = "allwinner,sun55i-a523-gmac200", ++ "snps,dwmac-4.20a"; ++ reg = <0x04510000 0x10000>; ++ clocks = <&ccu 117>, <&ccu 79>; ++ clock-names = "stmmaceth", "mbus"; ++ resets = <&ccu 43>; ++ reset-names = "stmmaceth"; ++ interrupts = <0 47 4>; ++ interrupt-names = "macirq"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii1_pins>; ++ power-domains = <&pck600 4>; ++ syscon = <&syscon>; ++ phy-handle = <&ext_rgmii_phy_1>; ++ phy-mode = "rgmii-id"; ++ snps,fixed-burst; ++ snps,axi-config = <&gmac1_stmmac_axi_setup>; ++ ++ mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ ++ ext_rgmii_phy_1: ethernet-phy@1 { ++ reg = <1>; ++ }; ++ }; ++ }; + ... +-- +2.39.5 diff --git a/patch/kernel/archive/sunxi-dev-6.17/16-net-stmmac-Add-support-for-Allwinner-A523-GMAC200.patch b/patch/kernel/archive/sunxi-dev-6.17/16-net-stmmac-Add-support-for-Allwinner-A523-GMAC200.patch new file mode 100644 index 000000000000..bd3f569a0956 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/16-net-stmmac-Add-support-for-Allwinner-A523-GMAC200.patch @@ -0,0 +1,227 @@ +From: Chen-Yu Tsai + +The Allwinner A523 SoC family has a second Ethernet controller, called +the GMAC200 in the BSP and T527 datasheet, and referred to as GMAC1 for +numbering. This controller, according to BSP sources, is fully +compatible with a slightly newer version of the Synopsys DWMAC core. +The glue layer around the controller is the same as found around older +DWMAC cores on Allwinner SoCs. The only slight difference is that since +this is the second controller on the SoC, the register for the clock +delay controls is at a different offset. Last, the integration includes +a dedicated clock gate for the memory bus and the whole thing is put in +a separately controllable power domain. + +Add a new driver for this hardware supporting the integration layer. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/net/ethernet/stmicro/stmmac/Kconfig | 12 ++ + drivers/net/ethernet/stmicro/stmmac/Makefile | 1 + + .../ethernet/stmicro/stmmac/dwmac-sun55i.c | 161 ++++++++++++++++++ + 3 files changed, 174 insertions(+) + create mode 100644 drivers/net/ethernet/stmicro/stmmac/dwmac-sun55i.c + +diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig +index 67fa879b1e52..38ce9a0cfb5b 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig ++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig +@@ -263,6 +263,18 @@ config DWMAC_SUN8I + stmmac device driver. This driver is used for H3/A83T/A64 + EMAC ethernet controller. + ++config DWMAC_SUN55I ++ tristate "Allwinner sun55i GMAC200 support" ++ default ARCH_SUNXI ++ depends on OF && (ARCH_SUNXI || COMPILE_TEST) ++ select MDIO_BUS_MUX ++ help ++ Support for Allwinner A523/T527 GMAC200 ethernet controllers. ++ ++ This selects Allwinner SoC glue layer support for the ++ stmmac device driver. This driver is used for A523/T527 ++ GMAC200 ethernet controller. ++ + config DWMAC_THEAD + tristate "T-HEAD dwmac support" + depends on OF && (ARCH_THEAD || COMPILE_TEST) +diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile +index b591d93f8503..51e068e26ce4 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/Makefile ++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile +@@ -31,6 +31,7 @@ obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o + obj-$(CONFIG_DWMAC_STM32) += dwmac-stm32.o + obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o + obj-$(CONFIG_DWMAC_SUN8I) += dwmac-sun8i.o ++obj-$(CONFIG_DWMAC_SUN55I) += dwmac-sun55i.o + obj-$(CONFIG_DWMAC_THEAD) += dwmac-thead.o + obj-$(CONFIG_DWMAC_DWC_QOS_ETH) += dwmac-dwc-qos-eth.o + obj-$(CONFIG_DWMAC_INTEL_PLAT) += dwmac-intel-plat.o +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun55i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun55i.c +new file mode 100644 +index 000000000000..7fadb90e3098 +--- /dev/null ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun55i.c +@@ -0,0 +1,161 @@ ++// SPDX-License-Identifier: GPL-2.0-only ++/* ++ * dwmac-sun55i.c - Allwinner sun55i GMAC200 specific glue layer ++ * ++ * Copyright (C) 2025 Chen-Yu Tsai ++ * ++ * syscon parts taken from dwmac-sun8i.c, which is ++ * ++ * Copyright (C) 2017 Corentin Labbe ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "stmmac.h" ++#include "stmmac_platform.h" ++ ++#define SYSCON_REG 0x34 ++ ++/* RMII specific bits */ ++#define SYSCON_RMII_EN BIT(13) /* 1: enable RMII (overrides EPIT) */ ++/* Generic system control EMAC_CLK bits */ ++#define SYSCON_ETXDC_MASK GENMASK(12, 10) ++#define SYSCON_ERXDC_MASK GENMASK(9, 5) ++/* EMAC PHY Interface Type */ ++#define SYSCON_EPIT BIT(2) /* 1: RGMII, 0: MII */ ++#define SYSCON_ETCS_MASK GENMASK(1, 0) ++#define SYSCON_ETCS_MII 0x0 ++#define SYSCON_ETCS_EXT_GMII 0x1 ++#define SYSCON_ETCS_INT_GMII 0x2 ++ ++#define MASK_TO_VAL(mask) ((mask) >> (__builtin_ffsll(mask) - 1)) ++ ++static int sun55i_gmac200_set_syscon(struct device *dev, ++ struct plat_stmmacenet_data *plat) ++{ ++ struct device_node *node = dev->of_node; ++ struct regmap *regmap; ++ u32 val, reg = 0; ++ ++ regmap = syscon_regmap_lookup_by_phandle(node, "syscon"); ++ if (IS_ERR(regmap)) ++ return dev_err_probe(dev, PTR_ERR(regmap), "Unable to map syscon\n"); ++ ++ if (!of_property_read_u32(node, "allwinner,tx-delay-ps", &val)) { ++ if (val % 100) { ++ dev_err(dev, "tx-delay must be a multiple of 100\n"); ++ return -EINVAL; ++ } ++ val /= 100; ++ dev_dbg(dev, "set tx-delay to %x\n", val); ++ if (val > MASK_TO_VAL(SYSCON_ETXDC_MASK)) ++ return dev_err_probe(dev, -EINVAL, ++ "Invalid TX clock delay: %d\n", ++ val); ++ ++ reg |= FIELD_PREP(SYSCON_ETXDC_MASK, val); ++ } ++ ++ if (!of_property_read_u32(node, "allwinner,rx-delay-ps", &val)) { ++ if (val % 100) { ++ dev_err(dev, "rx-delay must be a multiple of 100\n"); ++ return -EINVAL; ++ } ++ val /= 100; ++ dev_dbg(dev, "set rx-delay to %x\n", val); ++ if (val > MASK_TO_VAL(SYSCON_ERXDC_MASK)) ++ return dev_err_probe(dev, -EINVAL, ++ "Invalid RX clock delay: %d\n", ++ val); ++ ++ reg |= FIELD_PREP(SYSCON_ERXDC_MASK, val); ++ } ++ ++ switch (plat->mac_interface) { ++ case PHY_INTERFACE_MODE_MII: ++ /* default */ ++ break; ++ case PHY_INTERFACE_MODE_RGMII: ++ case PHY_INTERFACE_MODE_RGMII_ID: ++ case PHY_INTERFACE_MODE_RGMII_RXID: ++ case PHY_INTERFACE_MODE_RGMII_TXID: ++ reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII; ++ break; ++ case PHY_INTERFACE_MODE_RMII: ++ reg |= SYSCON_RMII_EN; ++ break; ++ default: ++ dev_err(dev, "Unsupported interface mode: %s", ++ phy_modes(plat->mac_interface)); ++ return -EINVAL; ++ } ++ ++ regmap_write(regmap, SYSCON_REG, reg); ++ ++ return 0; ++} ++ ++static int sun55i_gmac200_probe(struct platform_device *pdev) ++{ ++ struct plat_stmmacenet_data *plat_dat; ++ struct stmmac_resources stmmac_res; ++ struct device *dev = &pdev->dev; ++ struct clk *clk; ++ int ret; ++ ++ ret = stmmac_get_platform_resources(pdev, &stmmac_res); ++ if (ret) ++ return ret; ++ ++ plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); ++ if (IS_ERR(plat_dat)) ++ return PTR_ERR(plat_dat); ++ ++ /* BSP disables it */ ++ plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE; ++ plat_dat->host_dma_width = 32; ++ ++ ret = sun55i_gmac200_set_syscon(dev, plat_dat); ++ if (ret) ++ return ret; ++ ++ clk = devm_clk_get_enabled(dev, "mbus"); ++ if (IS_ERR(clk)) ++ return dev_err_probe(dev, PTR_ERR(clk), ++ "Failed to get or enable MBUS clock\n"); ++ ++ ret = devm_regulator_get_enable_optional(dev, "phy"); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to get or enable PHY supply\n"); ++ ++ return devm_stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res); ++} ++ ++static const struct of_device_id sun55i_gmac200_match[] = { ++ { .compatible = "allwinner,sun55i-a523-gmac200" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, sun55i_gmac200_match); ++ ++static struct platform_driver sun55i_gmac200_driver = { ++ .probe = sun55i_gmac200_probe, ++ .driver = { ++ .name = "sun55i-gmac200", ++ .pm = &stmmac_pltfr_pm_ops, ++ .of_match_table = sun55i_gmac200_match, ++ }, ++}; ++module_platform_driver(sun55i_gmac200_driver); ++ ++MODULE_AUTHOR("Chen-Yu Tsai "); ++MODULE_DESCRIPTION("Allwinner sun55i GMAC200 specific glue layer"); ++MODULE_LICENSE("GPL"); +-- +2.39.5 diff --git a/patch/kernel/archive/sunxi-dev-6.17/19-regulator-axp20x-force-polyphase-setup-for-axp323.patch b/patch/kernel/archive/sunxi-dev-6.17/19-regulator-axp20x-force-polyphase-setup-for-axp323.patch new file mode 100644 index 000000000000..bfddd37e55ae --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/19-regulator-axp20x-force-polyphase-setup-for-axp323.patch @@ -0,0 +1,135 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Sun, 6 Jul 2025 00:31:46 -0400 +Subject: From: iuncuim Date: Mon, 7 Apr 2025 03:28:37 + +0300 Subject: [PATCH] regulator: axp20x: force polyphase setup for axp323 + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 3 ++ + arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts | 3 ++ + arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts | 3 ++ + arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts | 3 ++ + drivers/regulator/axp20x-regulator.c | 19 ++++++++++ + 5 files changed, 31 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index f7a6221d02c2..369bde1556ff 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -330,10 +330,13 @@ reg_dcdc1_323: dcdc1 { + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; + }; + + /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ x-powers,polyphased; ++ }; + + /* RISC-V management core supply */ + reg_dcdc3_323: dcdc3 { + regulator-always-on; + regulator-min-microvolt = <900000>; +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts +index 0d7fb419c9b4..5732088add32 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts +@@ -253,10 +253,13 @@ reg_dcdc1_323: dcdc1 { + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; + }; + + /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ x-powers,polyphased; ++ }; + + reg_dcdc3_323: dcdc3 { + regulator-always-on; + regulator-min-microvolt = <1050000>; + regulator-max-microvolt = <1050000>; +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +index 4f2366b3624a..bd1ebb15bb3e 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +@@ -283,10 +283,13 @@ reg_dcdc1_323: dcdc1 { + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; + }; + + /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ x-powers,polyphased; ++ }; + + /* Some RISC-V management core related voltage */ + reg_dcdc3_323: dcdc3 { + regulator-always-on; + regulator-min-microvolt = <900000>; +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +index d1ffc9faec80..fb7933091edf 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +@@ -321,10 +321,13 @@ reg_dcdc1_323: dcdc1 { + regulator-max-microvolt = <1150000>; + regulator-name = "vdd-cpub"; + }; + + /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ x-powers,polyphased; ++ }; + + /* Some RISC-V management core related voltage */ + reg_dcdc3_323: dcdc3 { + regulator-always-on; + regulator-min-microvolt = <900000>; +diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c +index da891415efc0..2e2d35d31ce6 100644 +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -1479,10 +1479,23 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work + } + + return regmap_update_bits(rdev->regmap, reg, mask, workmode); + } + ++static void axp20x_set_polyphased(struct axp20x_dev *axp20x, int id) ++{ ++ switch (axp20x->variant) { ++ case AXP323_ID: ++ switch (id) { ++ case AXP313A_DCDC2: ++ regmap_write(axp20x->regmap, AXP323_DCDC_MODE_CTRL2, BIT(1)); ++ } ++ break; ++ ++ default: ++ } ++} + /* + * This function checks whether a regulator is part of a poly-phase + * output setup based on the registers settings. Returns true if it is. + */ + static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) +@@ -1702,10 +1715,16 @@ static int axp20x_regulator_probe(struct platform_device *pdev) + if (axp20x_set_dcdc_workmode(rdev, i, workmode)) + dev_err(&pdev->dev, "Failed to set workmode on %s\n", + rdev->desc->name); + } + ++ /* ++ * Currently only the AXP323 needs to force dual phase setup. ++ */ ++ if (of_property_read_bool(rdev->dev.of_node,"x-powers,polyphased")) ++ axp20x_set_polyphased(axp20x, i); ++ + /* + * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later. + */ + if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) || + (regulators == axp809_regulators && i == AXP809_DCDC1) || +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.17/20-soc-sunxi-sram-add-entry-for-a523.patch b/patch/kernel/archive/sunxi-dev-6.17/20-soc-sunxi-sram-add-entry-for-a523.patch new file mode 100644 index 000000000000..f7b6409d48a9 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/20-soc-sunxi-sram-add-entry-for-a523.patch @@ -0,0 +1,42 @@ +From: Chen-Yu Tsai + +The A523 has two Ethernet controllers. So in the system controller +address space, there are two registers for Ethernet clock delays, +one for each controller. + +Add a new entry for the A523 system controller that allows access to +the second register. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/soc/sunxi/sunxi_sram.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c +index 08e264ea0697..4f8d510b7e1e 100644 +--- a/drivers/soc/sunxi/sunxi_sram.c ++++ b/drivers/soc/sunxi/sunxi_sram.c +@@ -320,6 +320,10 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { + .has_ths_offset = true, + }; + ++static const struct sunxi_sramc_variant sun55i_a523_sramc_variant = { ++ .num_emac_clocks = 2, ++}; ++ + #define SUNXI_SRAM_THS_OFFSET_REG 0x0 + #define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 + #define SUNXI_SYS_LDO_CTRL_REG 0x150 +@@ -440,6 +444,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { + .compatible = "allwinner,sun50i-h616-system-control", + .data = &sun50i_h616_sramc_variant, + }, ++ { ++ .compatible = "allwinner,sun55i-a523-system-control", ++ .data = &sun55i_a523_sramc_variant, ++ }, + { }, + }; + MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); +-- +2.39.5 diff --git a/patch/kernel/archive/sunxi-dev-6.17/21-soc-sunxi-sram-register-regmap-as-syscon.patch b/patch/kernel/archive/sunxi-dev-6.17/21-soc-sunxi-sram-register-regmap-as-syscon.patch new file mode 100644 index 000000000000..a57e8d465759 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/21-soc-sunxi-sram-register-regmap-as-syscon.patch @@ -0,0 +1,44 @@ +From: Chen-Yu Tsai + +Until now, if the system controller had a ethernet controller glue layer +control register, a limited access regmap would be registered and tied +to the system controller struct device for the ethernet driver to use. + +Signed-off-by: Chen-Yu Tsai +--- + drivers/soc/sunxi/sunxi_sram.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c +index 4f8d510b7e1e..63c23bdffa78 100644 +--- a/drivers/soc/sunxi/sunxi_sram.c ++++ b/drivers/soc/sunxi/sunxi_sram.c +@@ -12,6 +12,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -377,6 +378,7 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) + const struct sunxi_sramc_variant *variant; + struct device *dev = &pdev->dev; + struct regmap *regmap; ++ int ret; + + sram_dev = &pdev->dev; + +@@ -394,6 +396,10 @@ static int __init sunxi_sram_probe(struct platform_device *pdev) + regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); ++ ++ ret = of_syscon_register_regmap(dev->of_node, regmap); ++ if (IS_ERR(ret)) ++ return ret; + } + + of_platform_populate(dev->of_node, NULL, NULL, dev); +-- +2.39.5 diff --git a/patch/kernel/archive/sunxi-dev-6.17/23-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-controller.patch b/patch/kernel/archive/sunxi-dev-6.17/23-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-controller.patch new file mode 100644 index 000000000000..31afa7ef915e --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/23-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-controller.patch @@ -0,0 +1,90 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Sat, 2 Aug 2025 00:36:05 -0400 +Subject: Subject: From: Chen-Yu Tsai + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 55 ++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index 7fbba60ec76e..50bebaa67d32 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -180,6 +180,16 @@ rgmii0_pins: rgmii0-pins { + bias-disable; + }; + ++ rgmii1_pins: rgmii1-pins { ++ pins = "PJ0", "PJ1", "PJ2", "PJ3", "PJ4", ++ "PJ5", "PJ6", "PJ7", "PJ8", "PJ9", ++ "PJ11", "PJ12", "PJ13", "PJ14", "PJ15"; ++ allwinner,pinmux = <5>; ++ function = "gmac1"; ++ drive-strength = <40>; ++ bias-disable; ++ }; ++ + uart0_pb_pins: uart0-pb-pins { + pins = "PB9", "PB10"; + allwinner,pinmux = <2>; +@@ -593,10 +603,55 @@ mdio0: mdio { + #address-cells = <1>; + #size-cells = <0>; + }; + }; + ++ gmac1: ethernet@4510000 { ++ compatible = "allwinner,sun55i-a523-gmac200", ++ "snps,dwmac-4.20a"; ++ reg = <0x04510000 0x10000>; ++ clocks = <&ccu CLK_BUS_EMAC1>, <&ccu CLK_MBUS_EMAC1>; ++ clock-names = "stmmaceth", "mbus"; ++ resets = <&ccu RST_BUS_EMAC1>; ++ reset-names = "stmmaceth"; ++ interrupts = ; ++ interrupt-names = "macirq"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii1_pins>; ++ power-domains = <&pck600 PD_VO1>; ++ syscon = <&syscon>; ++ snps,fixed-burst; ++ snps,axi-config = <&gmac1_stmmac_axi_setup>; ++ snps,mtl-rx-config = <&gmac1_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac1_mtl_tx_setup>; ++ status = "disabled"; ++ ++ mdio1: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gmac1_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ ++ queue0 {}; ++ }; ++ ++ gmac1_stmmac_axi_setup: stmmac-axi-config { ++ snps,wr_osr_lmt = <0xf>; ++ snps,rd_osr_lmt = <0xf>; ++ snps,blen = <256 128 64 32 16 8 4>; ++ }; ++ ++ gmac1_mtl_tx_setup: tx_queues-config { ++ snps,tx-queues-to-use = <1>; ++ ++ queue0 {}; ++ }; ++ }; ++ + ppu: power-controller@7001400 { + compatible = "allwinner,sun55i-a523-ppu"; + reg = <0x07001400 0x400>; + clocks = <&r_ccu CLK_BUS_R_PPU1>; + resets = <&r_ccu RST_BUS_R_PPU1>; +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.17/24-Enable-uart1-on-Radxa-Cubie-A5E.patch b/patch/kernel/archive/sunxi-dev-6.17/24-Enable-uart1-on-Radxa-Cubie-A5E.patch new file mode 100644 index 000000000000..ef8377636072 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.17/24-Enable-uart1-on-Radxa-Cubie-A5E.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Tue, 5 Aug 2025 14:55:52 -0400 +Subject: Enable uart1 (bluetooth) on Radxa Cubie A5E + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 369bde1556ff..37585cac6648 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -14,10 +14,11 @@ / { + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + ethernet2 = &sdio_wifi; + serial0 = &uart0; ++ serial1 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +@@ -360,10 +361,18 @@ &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; + }; + ++/* Bluetooth */ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++}; ++ + &usb_otg { + /* + * The USB-C port is the primary power supply, so in this configuration + * relies on the other end of the USB cable to supply the VBUS power. + * So use this port in peripheral mode. +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.18/01-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-contro.patch b/patch/kernel/archive/sunxi-dev-6.18/01-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-contro.patch new file mode 100644 index 000000000000..b545ff682b9b --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/01-arm64-dts-allwinner-a523-Add-GMAC200-ethernet-contro.patch @@ -0,0 +1,95 @@ +From 460a71b5642a60574809032f0a21afff0f942474 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 23 Sep 2025 22:02:43 +0800 +Subject: [PATCH 1/4] arm64: dts: allwinner: a523: Add GMAC200 ethernet + controller + +The A523 SoC family has a second ethernet controller, called the +GMAC200. It is not exposed on all the SoCs in the family. + +Add a device node for it. All the hardware specific settings are from +the vendor BSP. + +Acked-by: Jernej Skrabec +Link: https://patch.msgid.link/20250923140247.2622602-4-wens@kernel.org +Signed-off-by: Chen-Yu Tsai +--- + .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 55 +++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index 7b36c47a3a13..a9e051a8bea3 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -182,6 +182,16 @@ rgmii0_pins: rgmii0-pins { + bias-disable; + }; + ++ rgmii1_pins: rgmii1-pins { ++ pins = "PJ0", "PJ1", "PJ2", "PJ3", "PJ4", ++ "PJ5", "PJ6", "PJ7", "PJ8", "PJ9", ++ "PJ11", "PJ12", "PJ13", "PJ14", "PJ15"; ++ allwinner,pinmux = <5>; ++ function = "gmac1"; ++ drive-strength = <40>; ++ bias-disable; ++ }; ++ + uart0_pb_pins: uart0-pb-pins { + pins = "PB9", "PB10"; + allwinner,pinmux = <2>; +@@ -603,6 +613,51 @@ mdio0: mdio { + }; + }; + ++ gmac1: ethernet@4510000 { ++ compatible = "allwinner,sun55i-a523-gmac200", ++ "snps,dwmac-4.20a"; ++ reg = <0x04510000 0x10000>; ++ clocks = <&ccu CLK_BUS_EMAC1>, <&ccu CLK_MBUS_EMAC1>; ++ clock-names = "stmmaceth", "mbus"; ++ resets = <&ccu RST_BUS_EMAC1>; ++ reset-names = "stmmaceth"; ++ interrupts = ; ++ interrupt-names = "macirq"; ++ pinctrl-names = "default"; ++ pinctrl-0 = <&rgmii1_pins>; ++ power-domains = <&pck600 PD_VO1>; ++ syscon = <&syscon>; ++ snps,fixed-burst; ++ snps,axi-config = <&gmac1_stmmac_axi_setup>; ++ snps,mtl-rx-config = <&gmac1_mtl_rx_setup>; ++ snps,mtl-tx-config = <&gmac1_mtl_tx_setup>; ++ status = "disabled"; ++ ++ mdio1: mdio { ++ compatible = "snps,dwmac-mdio"; ++ #address-cells = <1>; ++ #size-cells = <0>; ++ }; ++ ++ gmac1_mtl_rx_setup: rx-queues-config { ++ snps,rx-queues-to-use = <1>; ++ ++ queue0 {}; ++ }; ++ ++ gmac1_stmmac_axi_setup: stmmac-axi-config { ++ snps,wr_osr_lmt = <0xf>; ++ snps,rd_osr_lmt = <0xf>; ++ snps,blen = <256 128 64 32 16 8 4>; ++ }; ++ ++ gmac1_mtl_tx_setup: tx-queues-config { ++ snps,tx-queues-to-use = <1>; ++ ++ queue0 {}; ++ }; ++ }; ++ + ppu: power-controller@7001400 { + compatible = "allwinner,sun55i-a523-ppu"; + reg = <0x07001400 0x400>; +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/02-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Eth.patch b/patch/kernel/archive/sunxi-dev-6.18/02-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Eth.patch new file mode 100644 index 000000000000..3dd59cf4584f --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/02-arm64-dts-allwinner-a527-cubie-a5e-Enable-second-Eth.patch @@ -0,0 +1,100 @@ +From 7076938d20d22d5f75641f417f11edeee192e3cf Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 23 Sep 2025 22:02:44 +0800 +Subject: [PATCH 2/4] arm64: dts: allwinner: a527: cubie-a5e: Enable second + Ethernet port + +On the Radxa Cubie A5E board, the second Ethernet controller, aka the +GMAC200, is connected to a second external Maxio MAE0621A PHY. The PHY +uses an external 25MHz crystal, and has the SoC's PJ16 pin connected to +its reset pin. + +Enable the second Ethernet port. Also fix up the label for the existing +external PHY connected to the first Ethernet port. An enable delay for the +PHY supply regulator is added to make sure the PHY's internal regulators +are fully powered and the PHY is operational. + +Acked-by: Jernej Skrabec +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250923140247.2622602-5-wens@kernel.org +Signed-off-by: Chen-Yu Tsai +--- + .../dts/allwinner/sun55i-a527-cubie-a5e.dts | 28 +++++++++++++++++-- + 1 file changed, 26 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index f82a8d121697..bfdf1728cd14 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -14,6 +14,7 @@ / { + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + serial0 = &uart0; + }; + +@@ -75,7 +76,7 @@ &ehci1 { + + &gmac0 { + phy-mode = "rgmii-id"; +- phy-handle = <&ext_rgmii_phy>; ++ phy-handle = <&ext_rgmii0_phy>; + phy-supply = <®_cldo3>; + + allwinner,tx-delay-ps = <300>; +@@ -84,13 +85,24 @@ &gmac0 { + status = "okay"; + }; + ++&gmac1 { ++ phy-mode = "rgmii-id"; ++ phy-handle = <&ext_rgmii1_phy>; ++ phy-supply = <®_cldo4>; ++ ++ tx-internal-delay-ps = <300>; ++ rx-internal-delay-ps = <400>; ++ ++ status = "okay"; ++}; ++ + &gpu { + mali-supply = <®_dcdc2>; + status = "okay"; + }; + + &mdio0 { +- ext_rgmii_phy: ethernet-phy@1 { ++ ext_rgmii0_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + reset-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ +@@ -99,6 +111,16 @@ ext_rgmii_phy: ethernet-phy@1 { + }; + }; + ++&mdio1 { ++ ext_rgmii1_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ reset-gpios = <&pio 9 16 GPIO_ACTIVE_LOW>; /* PJ16 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo3>; + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PF6 */ +@@ -250,6 +272,8 @@ reg_cldo4: cldo4 { + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-name = "vcc-pj-phy"; ++ /* enough time for the PHY to fully power on */ ++ regulator-enable-ramp-delay = <150000>; + }; + + reg_cpusldo: cpusldo { +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/03-arm64-dts-allwinner-t527-avaota-a1-enable-second-Eth.patch b/patch/kernel/archive/sunxi-dev-6.18/03-arm64-dts-allwinner-t527-avaota-a1-enable-second-Eth.patch new file mode 100644 index 000000000000..fdeee81bcf9a --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/03-arm64-dts-allwinner-t527-avaota-a1-enable-second-Eth.patch @@ -0,0 +1,89 @@ +From 2e5d147ba90e887271297f69721d2d88122c7c4f Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 23 Sep 2025 22:02:45 +0800 +Subject: [PATCH 3/4] arm64: dts: allwinner: t527: avaota-a1: enable second + Ethernet port + +On the Avaota A1 board, the second Ethernet controller, aka the GMAC200, +is connected to a second external RTL8211F-CG PHY. The PHY uses an +external 25MHz crystal, and has the SoC's PJ16 pin connected to its +reset pin. + +Enable the second Ethernet port. Also fix up the label for the existing +external PHY connected to the first Ethernet port. + +Acked-by: Jernej Skrabec +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250923140247.2622602-6-wens@kernel.org +Signed-off-by: Chen-Yu Tsai +--- + .../dts/allwinner/sun55i-t527-avaota-a1.dts | 26 +++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +index 1b054fa8ef74..054d0357c139 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +@@ -13,6 +13,7 @@ / { + + aliases { + ethernet0 = &gmac0; ++ ethernet1 = &gmac1; + serial0 = &uart0; + }; + +@@ -73,7 +74,7 @@ &ehci1 { + + &gmac0 { + phy-mode = "rgmii-id"; +- phy-handle = <&ext_rgmii_phy>; ++ phy-handle = <&ext_rgmii0_phy>; + phy-supply = <®_dcdc4>; + + allwinner,tx-delay-ps = <100>; +@@ -82,13 +83,24 @@ &gmac0 { + status = "okay"; + }; + ++&gmac1 { ++ phy-mode = "rgmii-id"; ++ phy-handle = <&ext_rgmii1_phy>; ++ phy-supply = <®_dcdc4>; ++ ++ tx-internal-delay-ps = <100>; ++ rx-internal-delay-ps = <100>; ++ ++ status = "okay"; ++}; ++ + &gpu { + mali-supply = <®_dcdc2>; + status = "okay"; + }; + + &mdio0 { +- ext_rgmii_phy: ethernet-phy@1 { ++ ext_rgmii0_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + reset-gpios = <&pio 7 8 GPIO_ACTIVE_LOW>; /* PH8 */ +@@ -97,6 +109,16 @@ ext_rgmii_phy: ethernet-phy@1 { + }; + }; + ++&mdio1 { ++ ext_rgmii1_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ reset-gpios = <&pio 9 16 GPIO_ACTIVE_LOW>; /* PJ16 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo3>; + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PF6 */ +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/04-arm64-dts-allwinner-t527-orangepi-4a-Enable-Ethernet.patch b/patch/kernel/archive/sunxi-dev-6.18/04-arm64-dts-allwinner-t527-orangepi-4a-Enable-Ethernet.patch new file mode 100644 index 000000000000..d57b8be858e5 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/04-arm64-dts-allwinner-t527-orangepi-4a-Enable-Ethernet.patch @@ -0,0 +1,70 @@ +From a3606e8a7819534026b46e2b8c7b0e156e292f13 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Tue, 23 Sep 2025 22:02:46 +0800 +Subject: [PATCH 4/4] arm64: dts: allwinner: t527: orangepi-4a: Enable Ethernet + port + +On the Orangepi 4A board, the second Ethernet controller, aka the GMAC200, +is connected to an external Motorcomm YT8531 PHY. The PHY uses an external +25MHz crystal, has the SoC's PI15 pin connected to its reset pin, and +the PI16 pin for its interrupt pin. + +Enable it. + +Acked-by: Jernej Skrabec +Reviewed-by: Andrew Lunn +Link: https://patch.msgid.link/20250923140247.2622602-7-wens@kernel.org +Signed-off-by: Chen-Yu Tsai +--- + .../dts/allwinner/sun55i-t527-orangepi-4a.dts | 23 +++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +index 39a4e194712a..9e6b21cf293e 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +@@ -15,6 +15,7 @@ / { + compatible = "xunlong,orangepi-4a", "allwinner,sun55i-t527"; + + aliases { ++ ethernet0 = &gmac1; + serial0 = &uart0; + }; + +@@ -102,11 +103,33 @@ &ehci1 { + status = "okay"; + }; + ++&gmac1 { ++ phy-mode = "rgmii-id"; ++ phy-handle = <&ext_rgmii_phy>; ++ phy-supply = <®_cldo4>; ++ ++ tx-internal-delay-ps = <0>; ++ rx-internal-delay-ps = <300>; ++ ++ status = "okay"; ++}; ++ + &gpu { + mali-supply = <®_dcdc2>; + status = "okay"; + }; + ++&mdio1 { ++ ext_rgmii_phy: ethernet-phy@1 { ++ compatible = "ethernet-phy-ieee802.3-c22"; ++ reg = <1>; ++ interrupts-extended = <&pio 8 16 IRQ_TYPE_LEVEL_LOW>; /* PI16 */ ++ reset-gpios = <&pio 8 15 GPIO_ACTIVE_LOW>; /* PI15 */ ++ reset-assert-us = <10000>; ++ reset-deassert-us = <150000>; ++ }; ++}; ++ + &mmc0 { + vmmc-supply = <®_cldo3>; + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PF6 */ +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/05-dt-bindings-mfd-x-powers-axp152-Add-polyphased-prope.patch b/patch/kernel/archive/sunxi-dev-6.18/05-dt-bindings-mfd-x-powers-axp152-Add-polyphased-prope.patch new file mode 100644 index 000000000000..a9ee81c604ea --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/05-dt-bindings-mfd-x-powers-axp152-Add-polyphased-prope.patch @@ -0,0 +1,64 @@ +From 72286070835a37fe74b630f36a8b5c56ad26b89d Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 19 Sep 2025 01:00:17 +0100 +Subject: [PATCH 1/5] dt-bindings: mfd: x-powers,axp152: Add polyphased + property + +Some X-Powers AXP PMICs can combine some of their DC/DC buck converter +outputs in a multi-phase fashion, to achieve higher currents and +decrease the output ripple. The datasheets call this poly-phase. This is +programmable in the PMIC, although often set up as the PMIC's reset +default. + +Add the "x-powers,polyphased" property to the binding, to describe those +pairs or tuples of regulators that should work together. In the lead +regulator node, the property lists the phandles of the connected +regulators. Just an empty property means no poly-phasing. + +Signed-off-by: Andre Przywara +--- + .../devicetree/bindings/mfd/x-powers,axp152.yaml | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +index 45f015d63df1..260c4c0afc47 100644 +--- a/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml ++++ b/Documentation/devicetree/bindings/mfd/x-powers,axp152.yaml +@@ -304,6 +304,15 @@ properties: + noise. This probably makes sense for HiFi audio related + applications that aren't battery constrained. + ++ x-powers,polyphased: ++ $ref: /schemas/types.yaml#/definitions/phandle-array ++ description: ++ A list of phandles pointing to other regulators that should be ++ polyphased with this regulator. The linked regulators will be ++ synchronised with this regulator, within the PMIC, but only if ++ supported by the PMIC. An empty list means this regulator ++ should be configured in a single-phase setup. ++ + additionalProperties: false + + required: +@@ -377,6 +386,7 @@ examples: + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <1450000>; + regulator-name = "vdd-cpu"; ++ x-powers,polyphased = <®_dcdc4>; + }; + + reg_dcdc3: dcdc3 { +@@ -386,6 +396,10 @@ examples: + regulator-name = "vdd-int-dll"; + }; + ++ reg_dcdc4: dcdc4 { ++ /* dual-phased with DCDC2 */ ++ }; ++ + reg_ldo1: ldo1 { + /* LDO1 is a fixed output regulator */ + regulator-always-on; +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/06-mfd-axp20x-Refactor-axp20x_is_polyphase_slave.patch b/patch/kernel/archive/sunxi-dev-6.18/06-mfd-axp20x-Refactor-axp20x_is_polyphase_slave.patch new file mode 100644 index 000000000000..39080cc23fcb --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/06-mfd-axp20x-Refactor-axp20x_is_polyphase_slave.patch @@ -0,0 +1,148 @@ +From 0cb44fa029c3a41b769ebbd7e4044682cad9a685 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 19 Sep 2025 01:00:17 +0100 +Subject: [PATCH 2/5] mfd: axp20x: Refactor axp20x_is_polyphase_slave() + +Some X-Powers AXP PMICs allow to combine certain DC/DC rails together in +a multi-phase fashion. So far we don't actively program those +connections, but we detect the existing setup, and prevent the connected +regulators from being re-programmed or turned off. At the moment this is +done in a switch/case construct, listing the known regulator pairs for +those PMICs supported. + +To get rid of this ever growing code section, create a data structure +that describes the relationship, and have generic code that iterates +over the entries and checks for matches. + +This not only cleans that function up and makes extensions much simpler, +but also allows to reuse this information for the upcoming programming +of those poly-phase setups. + +Signed-off-by: Andre Przywara +--- + drivers/regulator/axp20x-regulator.c | 91 ++++++++++++++-------------- + 1 file changed, 45 insertions(+), 46 deletions(-) + +diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c +index da891415efc0..19c9a98d1835 100644 +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -1481,70 +1481,69 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work + return regmap_update_bits(rdev->regmap, reg, mask, workmode); + } + ++struct dualphase_regulator { ++ int axp_id; ++ int reg1, reg2; ++ unsigned int polyphase_reg; ++ unsigned int bitmask; ++} dualphase_regulators[] = { ++ { AXP323_ID, AXP313A_DCDC1, AXP313A_DCDC2, ++ AXP323_DCDC_MODE_CTRL2, BIT(1), }, ++ { AXP803_ID, AXP803_DCDC2, AXP803_DCDC3, AXP803_POLYPHASE_CTRL, ++ AXP803_DCDC23_POLYPHASE_DUAL, }, ++ { AXP803_ID, AXP803_DCDC5, AXP803_DCDC6, AXP803_POLYPHASE_CTRL, ++ AXP803_DCDC56_POLYPHASE_DUAL, }, ++ /* AXP806's DCDC-A/B/C is a tri-phase regulator */ ++ { AXP806_ID, AXP806_DCDCD, AXP806_DCDCE, AXP806_DCDC_MODE_CTRL2, ++ AXP806_DCDCDE_POLYPHASE_DUAL, }, ++ { AXP813_ID, AXP803_DCDC2, AXP803_DCDC3, AXP803_POLYPHASE_CTRL, ++ AXP803_DCDC23_POLYPHASE_DUAL, }, ++ { AXP813_ID, AXP803_DCDC5, AXP803_DCDC6, AXP803_POLYPHASE_CTRL, ++ AXP803_DCDC56_POLYPHASE_DUAL, }, ++ { AXP15060_ID, AXP15060_DCDC2, AXP15060_DCDC3, AXP15060_DCDC_MODE_CTRL1, ++ AXP15060_DCDC23_POLYPHASE_DUAL_MASK, }, ++ { AXP15060_ID, AXP15060_DCDC4, AXP15060_DCDC6, AXP15060_DCDC_MODE_CTRL1, ++ AXP15060_DCDC46_POLYPHASE_DUAL_MASK, }, ++}; ++ + /* + * This function checks whether a regulator is part of a poly-phase + * output setup based on the registers settings. Returns true if it is. + */ + static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) + { ++ struct dualphase_regulator *dpreg; + u32 reg = 0; ++ int i; + +- /* +- * Currently in our supported AXP variants, only AXP803, AXP806, +- * AXP813 and AXP15060 have polyphase regulators. +- */ +- switch (axp20x->variant) { +- case AXP803_ID: +- case AXP813_ID: +- regmap_read(axp20x->regmap, AXP803_POLYPHASE_CTRL, ®); ++ for (i = 0; i < ARRAY_SIZE(dualphase_regulators); i++) { ++ dpreg = &dualphase_regulators[i]; + +- switch (id) { +- case AXP803_DCDC3: +- return !!(reg & AXP803_DCDC23_POLYPHASE_DUAL); +- case AXP803_DCDC6: +- return !!(reg & AXP803_DCDC56_POLYPHASE_DUAL); ++ if (axp20x->variant != dpreg->axp_id) ++ continue; ++ /* Is this the second regulator from a dual-phase pair? */ ++ if (id == dpreg->reg2) { ++ regmap_read(axp20x->regmap, dpreg->polyphase_reg, ®); ++ ++ return !!(reg & dpreg->bitmask); + } +- break; ++ } + +- case AXP806_ID: ++ /* ++ * DCDC-A/B/C can be configured either as a dual-phase (A+B) or ++ * as a triple-phase regulator (A+B+C), but not in any other ++ * combination. Treat this as a special case here. ++ */ ++ if (axp20x->variant == AXP806_ID) { + regmap_read(axp20x->regmap, AXP806_DCDC_MODE_CTRL2, ®); +- +- switch (id) { +- case AXP806_DCDCB: ++ if (id == AXP806_DCDCB) + return (((reg & AXP806_DCDCABC_POLYPHASE_MASK) == + AXP806_DCDCAB_POLYPHASE_DUAL) || + ((reg & AXP806_DCDCABC_POLYPHASE_MASK) == + AXP806_DCDCABC_POLYPHASE_TRI)); +- case AXP806_DCDCC: ++ if (id == AXP806_DCDCC) + return ((reg & AXP806_DCDCABC_POLYPHASE_MASK) == + AXP806_DCDCABC_POLYPHASE_TRI); +- case AXP806_DCDCE: +- return !!(reg & AXP806_DCDCDE_POLYPHASE_DUAL); +- } +- break; +- +- case AXP15060_ID: +- regmap_read(axp20x->regmap, AXP15060_DCDC_MODE_CTRL1, ®); +- +- switch (id) { +- case AXP15060_DCDC3: +- return !!(reg & AXP15060_DCDC23_POLYPHASE_DUAL_MASK); +- case AXP15060_DCDC6: +- return !!(reg & AXP15060_DCDC46_POLYPHASE_DUAL_MASK); +- } +- break; +- +- case AXP323_ID: +- regmap_read(axp20x->regmap, AXP323_DCDC_MODE_CTRL2, ®); +- +- switch (id) { +- case AXP313A_DCDC2: +- return !!(reg & BIT(1)); +- } +- break; +- +- default: +- return false; + } + + return false; +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/07-mfd-axp20x-Allow-programming-dual-phase-regulator-pa.patch b/patch/kernel/archive/sunxi-dev-6.18/07-mfd-axp20x-Allow-programming-dual-phase-regulator-pa.patch new file mode 100644 index 000000000000..30221455c043 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/07-mfd-axp20x-Allow-programming-dual-phase-regulator-pa.patch @@ -0,0 +1,120 @@ +From d8f1a6d20eef731149c58b1847696425fdd56f83 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 19 Sep 2025 01:00:17 +0100 +Subject: [PATCH 3/5] mfd: axp20x: Allow programming dual-phase regulator pairs + +Some X-Powers AXP PMICs allow to combine certain DC/DC rails together in +a multi-phase fashion. So far we don't actively program those connections, +since the PMIC reset default for the multi-phasing setup was always +correct for the existing boards. +Now a new set of boards appeared where the reset default is not correct, +so we need to actively program the multi-phase setup. + +Use the new data structure describing the dual-phased regulators, and +the new "x-powers,polyphased" DT property to enable or disable the +dual-phase setup on the PMICs that support it. + +This works by checking how many regulators this DT property list: +- If it's none, this means any existing poly-phase setup should be broken +up. +- If the property references at least one other regulator, we can use our +dual-phase regulator table to find the register and bitmask required to +establish the dual-phase connection. + +This supports only dual-phased regulator pairs so far, but we will +somewhat paper fix this in the next patch. + +Signed-off-by: Andre Przywara +--- + drivers/regulator/axp20x-regulator.c | 68 ++++++++++++++++++++++++++++ + 1 file changed, 68 insertions(+) + +diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c +index 19c9a98d1835..e3acc4635a0e 100644 +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -1549,6 +1549,70 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) + return false; + } + ++static int axp20x_find_polyphased_reg(const struct regulator_desc *regs, ++ int nregulators, ++ const struct device_node *np, int index) ++{ ++ struct of_phandle_args args; ++ int ret, i; ++ ++ ret = of_parse_phandle_with_fixed_args(np, "x-powers,polyphased", ++ 0, index, &args); ++ if (ret) ++ return ret; ++ ++ for (i = 0; i < nregulators; i++) { ++ if (!strcmp(regs[i].name, args.np->name)) ++ return i; ++ } ++ ++ return -ENODEV; ++} ++ ++static int axp20x_parse_polyphase(struct axp20x_dev *axp20x, int primary_reg_id, ++ const struct regulator_desc *regs, ++ int nregulators, const struct device_node *np) ++{ ++ struct dualphase_regulator *dpreg; ++ int reg_id, i; ++ ++ if (!of_property_present(np, "x-powers,polyphased")) ++ return 0; ++ ++ reg_id = axp20x_find_polyphased_reg(regs, nregulators, np, 0); ++ if (reg_id < 0 && reg_id != -ENOENT) /* not just empty property */ ++ return reg_id; ++ ++ for (i = 0; i < ARRAY_SIZE(dualphase_regulators); i++) { ++ dpreg = &dualphase_regulators[i]; ++ ++ if (axp20x->variant != dpreg->axp_id) ++ continue; ++ ++ if (dpreg->reg1 != primary_reg_id && ++ dpreg->reg2 != primary_reg_id) ++ continue; ++ ++ /* Empty property means breaking any polyphase setup. */ ++ if (reg_id == -ENOENT) { ++ regmap_update_bits(axp20x->regmap, dpreg->polyphase_reg, ++ dpreg->bitmask, 0); ++ ++ return 0; ++ } ++ ++ if ((dpreg->reg1 == primary_reg_id && dpreg->reg2 == reg_id) || ++ (dpreg->reg2 == primary_reg_id && dpreg->reg1 == reg_id)) { ++ regmap_update_bits(axp20x->regmap, dpreg->polyphase_reg, ++ dpreg->bitmask, dpreg->bitmask); ++ ++ return 0; ++ } ++ } ++ ++ return 0; ++} ++ + static int axp20x_regulator_probe(struct platform_device *pdev) + { + struct regulator_dev *rdev; +@@ -1703,6 +1767,10 @@ static int axp20x_regulator_probe(struct platform_device *pdev) + rdev->desc->name); + } + ++ if (rdev->dev.of_node) ++ axp20x_parse_polyphase(axp20x, i, regulators, ++ nregulators, rdev->dev.of_node); ++ + /* + * Save AXP22X DCDC1 / DCDC5 / AXP15060 ALDO1 regulator names for later. + */ +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/08-mfd-axp20x-Support-tri-phase-setup.patch b/patch/kernel/archive/sunxi-dev-6.18/08-mfd-axp20x-Support-tri-phase-setup.patch new file mode 100644 index 000000000000..0645aadab337 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/08-mfd-axp20x-Support-tri-phase-setup.patch @@ -0,0 +1,93 @@ +From 008942ec8d1bd6615e71765d1ef2679642515fa4 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 19 Sep 2025 01:00:17 +0100 +Subject: [PATCH 4/5] mfd: axp20x: Support tri-phase setup + +Of the PMICs that support multi-phased regulators, all but one just +support a dual-phase setup, with exactly two regulators tied together. +This allows for a simple data model, since just two is somewhat of a +special case. + +However there is the AXP806, which supports a triple-phase setup, that is +also used on at least one board: the Cubieboard 4, where DCDC-A+B+C +together supply the Cortex-A15 CPU cluster. +Since this is just one case, and a fairly old one now, let's not boil +the ocean by coming up with a complex data structure that allows +describing arbitrary combinations, but instead handle this as a special +case. This is supported by the fact, that the AXP806 only supports two +specific setups: DCDC-A+B or DCDC-A+B+C, but nothing else. + +Add a function that checks for the regulators on this PMIC, and handle +the two cases, plus the one without any poly-phasing. + +Signed-off-by: Andre Przywara +--- + drivers/regulator/axp20x-regulator.c | 45 ++++++++++++++++++++++++++++ + 1 file changed, 45 insertions(+) + +diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c +index e3acc4635a0e..9dd666f228b1 100644 +--- a/drivers/regulator/axp20x-regulator.c ++++ b/drivers/regulator/axp20x-regulator.c +@@ -1569,6 +1569,39 @@ static int axp20x_find_polyphased_reg(const struct regulator_desc *regs, + return -ENODEV; + } + ++static int axp20x_handle_triphase(struct axp20x_dev *axp20x, ++ int reg1, int reg2, int reg3) ++{ ++ if (axp20x->variant == AXP806_ID && reg1 == AXP806_DCDCA) { ++ /* no other regulator listed: single phase setup */ ++ if (reg2 == -ENOENT && reg3 == -ENOENT) { ++ regmap_update_bits(axp20x->regmap, ++ AXP806_DCDC_MODE_CTRL2, ++ AXP806_DCDCABC_POLYPHASE_MASK, 0); ++ return 0; ++ } ++ /* only regulator listed is DCDC-B: dual phase setup */ ++ if (reg2 == AXP806_DCDCB && reg3 == -ENOENT) { ++ regmap_update_bits(axp20x->regmap, ++ AXP806_DCDC_MODE_CTRL2, ++ AXP806_DCDCABC_POLYPHASE_MASK, ++ AXP806_DCDCAB_POLYPHASE_DUAL); ++ return 0; ++ } ++ /* both DCDC-B+C regulators listed: tri phase setup */ ++ if ((reg2 == AXP806_DCDCB && reg3 == AXP806_DCDCC) || ++ (reg2 == AXP806_DCDCC && reg3 == AXP806_DCDCB)) { ++ regmap_update_bits(axp20x->regmap, ++ AXP806_DCDC_MODE_CTRL2, ++ AXP806_DCDCABC_POLYPHASE_MASK, ++ AXP806_DCDCABC_POLYPHASE_TRI); ++ return 0; ++ } ++ } ++ ++ return 0; ++} ++ + static int axp20x_parse_polyphase(struct axp20x_dev *axp20x, int primary_reg_id, + const struct regulator_desc *regs, + int nregulators, const struct device_node *np) +@@ -1610,6 +1643,18 @@ static int axp20x_parse_polyphase(struct axp20x_dev *axp20x, int primary_reg_id, + } + } + ++ /* Special handling for the AXP806 DCDC-A/B/C tri-phase regulator. */ ++ if (axp20x->variant == AXP806_ID && primary_reg_id == AXP806_DCDCA) { ++ int reg3_id; ++ ++ reg3_id = axp20x_find_polyphased_reg(regs, nregulators, np, 1); ++ if (reg3_id < 0 && reg3_id != -ENOENT) ++ return reg_id; ++ ++ return axp20x_handle_triphase(axp20x, primary_reg_id, ++ reg_id, reg3_id); ++ } ++ + return 0; + } + +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/09-arm64-dts-allwinner-a523-Mark-dual-phased-regulators.patch b/patch/kernel/archive/sunxi-dev-6.18/09-arm64-dts-allwinner-a523-Mark-dual-phased-regulators.patch new file mode 100644 index 000000000000..405be124562c --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/09-arm64-dts-allwinner-a523-Mark-dual-phased-regulators.patch @@ -0,0 +1,97 @@ +From 87274e8d73915412aa8b0fcefa27a1c0e982c975 Mon Sep 17 00:00:00 2001 +From: Andre Przywara +Date: Fri, 19 Sep 2025 01:00:17 +0100 +Subject: [PATCH 5/5] arm64: dts: allwinner: a523: Mark dual-phased regulators + +The X-Powers AXP323 PMIC on the boards with a SoC from the Allwinner +A523 family typically uses DCDC1 and DCDC2 in a dual-phase setup to +supply the "big" CPU cluster. For some reason this dual-phase +configuration is not the PMIC's reset default, but needs to be actively +programmed at runtime. + +Add the newly introduced x-powers,polyphased property in the board DTs, +to mark this connection and let drivers program the dual-phase setup. + +Signed-off-by: Andre Przywara +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 5 ++++- + arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts | 5 ++++- + arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts | 5 ++++- + arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts | 5 ++++- + 4 files changed, 16 insertions(+), 4 deletions(-) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index bfdf1728cd14..9e52ea338ce5 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -320,9 +320,12 @@ reg_dcdc1_323: dcdc1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; ++ x-powers,polyphased = <®_dcdc2_323>; + }; + +- /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ /* dual-phased with DCDC1 */ ++ }; + + /* RISC-V management core supply */ + reg_dcdc3_323: dcdc3 { +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts +index a96927fbdadd..9dd4178bdff1 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-h728-x96qpro+.dts +@@ -252,9 +252,12 @@ reg_dcdc1_323: dcdc1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; ++ x-powers,polyphased = <®_dcdc2_323>; + }; + +- /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ /* dual-phased with DCDC1 */ ++ }; + + reg_dcdc3_323: dcdc3 { + regulator-always-on; +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +index 054d0357c139..678736e3b717 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-avaota-a1.dts +@@ -330,9 +330,12 @@ reg_dcdc1_323: dcdc1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1160000>; + regulator-name = "vdd-cpub"; ++ x-powers,polyphased = <®_dcdc2_323>; + }; + +- /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ /* dual-phased with DCDC1 */ ++ }; + + /* Some RISC-V management core related voltage */ + reg_dcdc3_323: dcdc3 { +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +index 39a4e194712a..ef0837ffa38f 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-t527-orangepi-4a.dts +@@ -345,9 +345,12 @@ reg_dcdc1_323: dcdc1 { + regulator-min-microvolt = <900000>; + regulator-max-microvolt = <1150000>; + regulator-name = "vdd-cpub"; ++ x-powers,polyphased = <®_dcdc2_323>; + }; + +- /* DCDC2 is polyphased with DCDC1 */ ++ reg_dcdc2_323: dcdc2 { ++ /* dual-phased with DCDC1 */ ++ }; + + /* Some RISC-V management core related voltage */ + reg_dcdc3_323: dcdc3 { +-- +2.43.0 + diff --git a/patch/kernel/archive/sunxi-dev-6.18/10-Allwinner-A523-add-support-for-A523-THS0-1-controllers.patch b/patch/kernel/archive/sunxi-dev-6.18/10-Allwinner-A523-add-support-for-A523-THS0-1-controllers.patch new file mode 100644 index 000000000000..b8d032c5ebdd --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/10-Allwinner-A523-add-support-for-A523-THS0-1-controllers.patch @@ -0,0 +1,803 @@ +From 8476f1b10b6acc327455c840d3f89a56ec6dedea Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH] [PATCH v3 1/6] dt-bindings: thermal: sun8i: Add A523 THS0/1 + +Add a binding for D1/T113s thermal sensor controller. Add dt-bindings +description of the thermal sensors in the A523 processor. +The controllers require activation of the additional frequency of the +associated gpadc controller, so a new clock property has been added. + +The calibration data is split into two cells that are in different areas +of nvmem. Both controllers require access to both memory cell, so a new +property nvmem-cells has been added. To maintain backward compatibility, +the name of the old cell remains the same and the new nvmem-cell-names is +called calibration-second-part + +Signed-off-by: Mikhail Kalashnikov +--- + .../thermal/allwinner,sun8i-a83t-ths.yaml | 56 ++++++++++++++++++- + 1 file changed, 53 insertions(+), 3 deletions(-) + +diff --git a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +index 3e61689f6..b2f750ef2 100644 +--- a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml ++++ b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +@@ -24,18 +24,23 @@ properties: + - allwinner,sun50i-h5-ths + - allwinner,sun50i-h6-ths + - allwinner,sun50i-h616-ths ++ - allwinner,sun55i-a523-ths0 ++ - allwinner,sun55i-a523-ths1 + + clocks: + minItems: 1 + items: + - description: Bus Clock + - description: Module Clock ++ - description: GPADC Clock + + clock-names: + minItems: 1 ++ maxItems: 2 + items: + - const: bus + - const: mod ++ - const: gpadc + + reg: + maxItems: 1 +@@ -47,11 +52,16 @@ properties: + maxItems: 1 + + nvmem-cells: +- maxItems: 1 +- description: Calibration data for thermal sensors ++ minItems: 1 ++ items: ++ - description: Calibration data for thermal sensors ++ - description: Additional cell in case of separate calibration data + + nvmem-cell-names: +- const: calibration ++ minItems: 1 ++ items: ++ - const: calibration ++ - const: calibration-second-part + + allwinner,sram: + maxItems: 1 +@@ -107,6 +117,7 @@ allOf: + enum: + - allwinner,sun8i-h3-ths + - allwinner,sun20i-d1-ths ++ - allwinner,sun55i-a523-ths0 + + then: + properties: +@@ -132,6 +143,32 @@ allOf: + - clock-names + - resets + ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - allwinner,sun55i-a523-ths0 ++ - allwinner,sun55i-a523-ths1 ++ then: ++ properties: ++ clocks: ++ minItems: 2 ++ clock-names: ++ enum: [ bus, gpadc ] ++ nvmem-cells: ++ minItems: 2 ++ nvmem-cell-names: ++ minItems: 2 ++ else: ++ properties: ++ nvmem-cells: ++ maxItems: 1 ++ nvmem-cell-names: ++ maxItems: 1 ++ items: ++ - const: calibration ++ + required: + - compatible + - reg +@@ -176,4 +213,17 @@ examples: + #thermal-sensor-cells = <1>; + }; + ++ - | ++ thermal-sensor@2009400 { ++ compatible = "allwinner,sun55i-a523-ths1"; ++ reg = <0x02009400 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_GPADC1>; ++ clock-names = "bus", "gpadc"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration0>, <&ths_calibration1>; ++ nvmem-cell-names = "calibration", ++ "calibration-second-part"; ++ #thermal-sensor-cells = <1>; ++ }; + ... + +From 955935d64eeca888d0cde1dd3475b5b82ad37331 Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH 2/X] auto-split from bundle + +Some processors (e.g. Allwinner A523) require GPADC clocking activation for +temperature sensors to work. So let's add support for enabling it. + +Signed-off-by: Mikhail Kalashnikov +Reviewed-by: Chen-Yu Tsai +--- + drivers/thermal/sun8i_thermal.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c +index 226747906..c02c398b0 100644 +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -66,6 +66,7 @@ struct tsensor { + }; + + struct ths_thermal_chip { ++ bool has_gpadc_clk; + bool has_mod_clk; + bool has_bus_clk_reset; + bool needs_sram; +@@ -89,6 +90,7 @@ struct ths_device { + struct regmap_field *sram_regmap_field; + struct reset_control *reset; + struct clk *bus_clk; ++ struct clk *gpadc_clk; + struct clk *mod_clk; + struct tsensor sensor[MAX_SENSOR_NUM]; + }; +@@ -417,6 +419,12 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) + if (ret) + return ret; + ++ if (tmdev->chip->has_gpadc_clk) { ++ tmdev->gpadc_clk = devm_clk_get_enabled(&pdev->dev, "gpadc"); ++ if (IS_ERR(tmdev->gpadc_clk)) ++ return PTR_ERR(tmdev->gpadc_clk); ++ } ++ + if (tmdev->chip->needs_sram) { + struct regmap *regmap; + +From d047c1633c69dca78a06517d595cbbd694a621c7 Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH 3/X] auto-split from bundle + +The A523 processor has two temperature controllers, but they share a +common reset line. Make it shared with the shared variant of +devm_reset_control_get(), and also simplify the driver by switching to +devm_reset_control_get_shared_deasserted(). + +Signed-off-by: Mikhail Kalashnikov +Reviewed-by: Chen-Yu Tsai +--- + drivers/thermal/sun8i_thermal.c | 16 +--------------- + 1 file changed, 1 insertion(+), 15 deletions(-) + +diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c +index c02c398b0..aa496e1ba 100644 +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -344,11 +344,6 @@ static int sun8i_ths_calibrate(struct ths_device *tmdev) + return ret; + } + +-static void sun8i_ths_reset_control_assert(void *data) +-{ +- reset_control_assert(data); +-} +- + static struct regmap *sun8i_ths_get_sram_regmap(struct device_node *node) + { + struct platform_device *sram_pdev; +@@ -391,19 +386,10 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) + return PTR_ERR(tmdev->regmap); + + if (tmdev->chip->has_bus_clk_reset) { +- tmdev->reset = devm_reset_control_get(dev, NULL); ++ tmdev->reset = devm_reset_control_get_shared_deasserted(dev, NULL); + if (IS_ERR(tmdev->reset)) + return PTR_ERR(tmdev->reset); + +- ret = reset_control_deassert(tmdev->reset); +- if (ret) +- return ret; +- +- ret = devm_add_action_or_reset(dev, sun8i_ths_reset_control_assert, +- tmdev->reset); +- if (ret) +- return ret; +- + tmdev->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus"); + if (IS_ERR(tmdev->bus_clk)) + return PTR_ERR(tmdev->bus_clk); + +From c71a090a859ac701105f82166d6ffd03204bfcd0 Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH 4/X] auto-split from bundle + +The A523 processor has calibration data in two nvmem cell. To be able to +add support, the ability to add data from two cells into one array must be +added. + +Signed-off-by: Mikhail Kalashnikov +--- + drivers/thermal/sun8i_thermal.c | 77 ++++++++++++++++++++++----------- + 1 file changed, 52 insertions(+), 25 deletions(-) + +diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c +index aa496e1ba..d6d8e13e5 100644 +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -303,43 +303,70 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev, + + static int sun8i_ths_calibrate(struct ths_device *tmdev) + { +- struct nvmem_cell *calcell; ++ struct nvmem_cell *calcell = NULL; + struct device *dev = tmdev->dev; +- u16 *caldata; +- size_t callen; ++ struct device_node *np = dev_of_node(dev); ++ struct property *prop; ++ const char *cellname; ++ u8 *caldata = NULL; ++ size_t callen = 0; + int ret = 0; + +- calcell = nvmem_cell_get(dev, "calibration"); +- if (IS_ERR(calcell)) { +- if (PTR_ERR(calcell) == -EPROBE_DEFER) +- return -EPROBE_DEFER; +- /* +- * Even if the external calibration data stored in sid is +- * not accessible, the THS hardware can still work, although +- * the data won't be so accurate. +- * +- * The default value of calibration register is 0x800 for +- * every sensor, and the calibration value is usually 0x7xx +- * or 0x8xx, so they won't be away from the default value +- * for a lot. +- * +- * So here we do not return error if the calibration data is +- * not available, except the probe needs deferring. +- */ +- goto out; ++ of_property_for_each_string(np, "nvmem-cell-names", prop, cellname) { ++ size_t len; ++ u8 *caldatapart; ++ ++ calcell = of_nvmem_cell_get(np, cellname); ++ if (IS_ERR(calcell)) { ++ if (PTR_ERR(calcell) == -EPROBE_DEFER) ++ return -EPROBE_DEFER; ++ /* ++ * Even if the external calibration data stored in sid is ++ * not accessible, the THS hardware can still work, although ++ * the data won't be so accurate. ++ * ++ * The default value of calibration register is 0x800 for ++ * every sensor, and the calibration value is usually 0x7xx ++ * or 0x8xx, so they won't be away from the default value ++ * for a lot. ++ * ++ * So here we do not return error if the calibration data is ++ * not available, except the probe needs deferring. ++ */ ++ goto out; ++ } ++ ++ caldatapart = nvmem_cell_read(calcell, &len); ++ nvmem_cell_put(calcell); ++ calcell = NULL; ++ if (IS_ERR(caldatapart)) { ++ ret = PTR_ERR(caldatapart); ++ goto out; ++ } ++ ++ caldata = devm_krealloc(dev, caldata, callen + len, GFP_KERNEL); ++ if (!caldata) { ++ kfree(caldatapart); ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ memcpy(caldata + callen, caldatapart, len); ++ callen += len; ++ kfree(caldatapart); + } + +- caldata = nvmem_cell_read(calcell, &callen); + if (IS_ERR(caldata)) { + ret = PTR_ERR(caldata); + goto out; + } + +- tmdev->chip->calibrate(tmdev, caldata, callen); ++ tmdev->chip->calibrate(tmdev, (u16 *)caldata, callen); + +- kfree(caldata); ++ devm_kfree(dev, caldata); ++ caldata = NULL; + out: +- if (!IS_ERR(calcell)) ++ if (calcell && !IS_ERR(calcell)) + nvmem_cell_put(calcell); + return ret; + } + +From 6157843778fda7cd704d2c553e7ee9593b831fcb Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH 5/X] auto-split from bundle + +The A523 processor has two temperature controllers, THS0 and THS1. + +THS0 has only one temperature sensor, which is located in the DRAM. + +THS1 does have 3 sensors: +ths1_0 - "big" cores +ths1_1 - "little" cores +ths1_2 - gpu + +The datasheet mentions a fourth sensor in the NPU, but lacks any registers +for operation other than calibration registers. The vendor code reads the +value from ths1_2, but uses separate calibration data, so we get two +different values from real one. + +Signed-off-by: Mikhail Kalashnikov +--- + drivers/thermal/sun8i_thermal.c | 133 ++++++++++++++++++++++++++++++++ + 1 file changed, 133 insertions(+) + +diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c +index d6d8e13e5..7d35ea3c4 100644 +--- a/drivers/thermal/sun8i_thermal.c ++++ b/drivers/thermal/sun8i_thermal.c +@@ -59,6 +59,12 @@ + #define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) + #define SUN50I_H6_THS_DATA_IRQ_STS(x) BIT(x) + ++#define SUN55I_A523_DELIMITER 0x7c8 ++#define SUN55I_A523_OFFSET_ABOVE 2736 ++#define SUN55I_A523_OFFSET_BELOW 2825 ++#define SUN55I_A523_SCALE_ABOVE 74 ++#define SUN55I_A523_SCALE_BELOW 65 ++ + struct tsensor { + struct ths_device *tmdev; + struct thermal_zone_device *tzd; +@@ -116,6 +122,15 @@ static int sun50i_h5_calc_temp(struct ths_device *tmdev, + return -1590 * reg / 10 + 276000; + } + ++static int sun55i_a523_calc_temp(struct ths_device *tmdev, ++ int id, int reg) ++{ ++ if (reg >= SUN55I_A523_DELIMITER) ++ return SUN55I_A523_SCALE_ABOVE * (SUN55I_A523_OFFSET_ABOVE - reg); ++ else ++ return SUN55I_A523_SCALE_BELOW * (SUN55I_A523_OFFSET_BELOW - reg); ++} ++ + static int sun8i_ths_get_temp(struct thermal_zone_device *tz, int *temp) + { + struct tsensor *s = thermal_zone_device_priv(tz); +@@ -301,6 +316,97 @@ static int sun50i_h6_ths_calibrate(struct ths_device *tmdev, + return 0; + } + ++/* ++ * The A523 nvmem calibration values. The ths1_3 is not used as it ++ * doesn't have its own sensor and doesn't have any internal switch. ++ * Instead, the value from the ths1_2 sensor is used, which gives the ++ * illusion of an independent sensor for NPU and GPU when using ++ * different calibration values. ++ * ++ * efuse layout 0x38-0x3F (caldata[0..3]): ++ * caldata[0] caldata[1] caldata[2] caldata[3] ++ * 0 16 24 32 36 48 60 64 ++ * +---------------+---------------+---------------+---------------+ ++ * | | | temp | ths1_0 | ths1_1 | + ++ * +---------------+---------------+---------------+---------------+ ++ * ++ * efuse layout 0x44-0x4B (caldata[4..7]): ++ * caldata[4] caldata[5] caldata[6] caldata[7] ++ * 0 12 16 24 32 36 48 64 ++ * +---------------+---------------+---------------+---------------+ ++ * | ths1_2 | ths1_3 | ths0 | | + ++ * +---------------+---------------+---------------+---------------+ ++ */ ++static int sun55i_a523_ths_calibrate(struct ths_device *tmdev, ++ u16 *caldata, int callen) ++{ ++ struct device *dev = tmdev->dev; ++ int i, ft_temp; ++ ++ if (!caldata[0]) ++ return -EINVAL; ++ ++ ft_temp = (((caldata[2] << 8) | (caldata[1] >> 8)) & FT_TEMP_MASK) * 100; ++ ++ for (i = 0; i < tmdev->chip->sensor_num; i++) { ++ int sensor_reg, sensor_temp, cdata, offset; ++ /* ++ * Chips ths0 and ths1 have common parameters for value ++ * calibration. To separate them we can use the number of ++ * temperature sensors on each chip. ++ * For ths0 this value is 1. ++ */ ++ if (tmdev->chip->sensor_num == 1) { ++ sensor_reg = ((caldata[5] >> 8) | (caldata[6] << 8)) & TEMP_CALIB_MASK; ++ } else { ++ switch (i) { ++ case 0: ++ sensor_reg = (caldata[2] >> 4) & TEMP_CALIB_MASK; ++ break; ++ case 1: ++ sensor_reg = caldata[3] & TEMP_CALIB_MASK; ++ break; ++ case 2: ++ sensor_reg = caldata[4] & TEMP_CALIB_MASK; ++ break; ++ default: ++ sensor_reg = 0; ++ break; ++ } ++ } ++ ++ sensor_temp = tmdev->chip->calc_temp(tmdev, i, sensor_reg); ++ ++ /* ++ * Calibration data is CALIBRATE_DEFAULT - (calculated ++ * temperature from sensor reading at factory temperature ++ * minus actual factory temperature) * X (scale from ++ * temperature to register values) ++ */ ++ cdata = CALIBRATE_DEFAULT - ++ ((sensor_temp - ft_temp) / SUN55I_A523_SCALE_ABOVE); ++ ++ if (cdata & ~TEMP_CALIB_MASK) { ++ /* ++ * Calibration value more than 12-bit, but calibration ++ * register is 12-bit. In this case, ths hardware can ++ * still work without calibration, although the data ++ * won't be so accurate. ++ */ ++ dev_warn(dev, "sensor%d is not calibrated.\n", i); ++ continue; ++ } ++ ++ offset = (i % 2) * 16; ++ regmap_update_bits(tmdev->regmap, ++ SUN50I_H6_THS_TEMP_CALIB + (i / 2 * 4), ++ TEMP_CALIB_MASK << offset, ++ cdata << offset); ++ } ++ ++ return 0; ++} ++ + static int sun8i_ths_calibrate(struct ths_device *tmdev) + { + struct nvmem_cell *calcell = NULL; +@@ -730,6 +836,31 @@ static const struct ths_thermal_chip sun50i_h616_ths = { + .calc_temp = sun8i_ths_calc_temp, + }; + ++/* The A523 has a shared reset line for both chips */ ++static const struct ths_thermal_chip sun55i_a523_ths0 = { ++ .sensor_num = 1, ++ .has_bus_clk_reset = true, ++ .has_gpadc_clk = true, ++ .ft_deviation = 5000, ++ .temp_data_base = SUN50I_H6_THS_TEMP_DATA, ++ .calibrate = sun55i_a523_ths_calibrate, ++ .init = sun50i_h6_thermal_init, ++ .irq_ack = sun50i_h6_irq_ack, ++ .calc_temp = sun55i_a523_calc_temp, ++}; ++ ++static const struct ths_thermal_chip sun55i_a523_ths1 = { ++ .sensor_num = 3, ++ .has_bus_clk_reset = true, ++ .has_gpadc_clk = true, ++ .ft_deviation = 5000, ++ .temp_data_base = SUN50I_H6_THS_TEMP_DATA, ++ .calibrate = sun55i_a523_ths_calibrate, ++ .init = sun50i_h6_thermal_init, ++ .irq_ack = sun50i_h6_irq_ack, ++ .calc_temp = sun55i_a523_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 }, +@@ -740,6 +871,8 @@ static const struct of_device_id of_ths_match[] = { + { .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 }, ++ { .compatible = "allwinner,sun55i-a523-ths0", .data = &sun55i_a523_ths0 }, ++ { .compatible = "allwinner,sun55i-a523-ths1", .data = &sun55i_a523_ths1 }, + { /* sentinel */ }, + }; + MODULE_DEVICE_TABLE(of, of_ths_match); + +From 74804cbc70cbd2aa933b3b9144bc9ed7115a14c5 Mon Sep 17 00:00:00 2001 +From: Mikhail Kalashnikov +Date: Fri, 07 Nov 2025 12:46:30 -0000 +Subject: [PATCH 6/X] auto-split from bundle + +The A523 processor has two temperature controllers, THS0 and THS1. +THS0 has only one temperature sensor, which is located in the DRAM. + +THS1 does have 3 sensors: +ths1_0 - "big" cores +ths1_1 - "little" cores +ths1_2 - gpu + +Add the thermal sensor configuration and the thermal zones. +Trips temperature, polling-delay and sustainable-power parameters are +derived from the manufacturer's BSP. + +Signed-off-by: Mikhail Kalashnikov +--- + .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 154 ++++++++++++++++++ + 1 file changed, 154 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index 7b36c47a3..0cbe73601 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + / { + interrupt-parent = <&gic>; +@@ -26,6 +27,7 @@ cpu0: cpu@0 { + device_type = "cpu"; + reg = <0x000>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu1: cpu@100 { +@@ -33,6 +35,7 @@ cpu1: cpu@100 { + device_type = "cpu"; + reg = <0x100>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu2: cpu@200 { +@@ -40,6 +43,7 @@ cpu2: cpu@200 { + device_type = "cpu"; + reg = <0x200>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu3: cpu@300 { +@@ -47,6 +51,7 @@ cpu3: cpu@300 { + device_type = "cpu"; + reg = <0x300>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu4: cpu@400 { +@@ -54,6 +59,7 @@ cpu4: cpu@400 { + device_type = "cpu"; + reg = <0x400>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu5: cpu@500 { +@@ -61,6 +67,7 @@ cpu5: cpu@500 { + device_type = "cpu"; + reg = <0x500>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu6: cpu@600 { +@@ -68,6 +75,7 @@ cpu6: cpu@600 { + device_type = "cpu"; + reg = <0x600>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + + cpu7: cpu@700 { +@@ -75,6 +83,7 @@ cpu7: cpu@700 { + device_type = "cpu"; + reg = <0x700>; + enable-method = "psci"; ++ #cooling-cells = <2>; + }; + }; + +@@ -398,12 +407,46 @@ syscon: syscon@3000000 { + ranges; + }; + ++ ths1: thermal-sensor@2009400 { ++ compatible = "allwinner,sun55i-a523-ths1"; ++ reg = <0x02009400 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_GPADC1>; ++ clock-names = "bus", "gpadc"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration0>, <&ths_calibration1>; ++ nvmem-cell-names = "calibration", ++ "calibration-second-part"; ++ #thermal-sensor-cells = <1>; ++ }; ++ ++ ths0: thermal-sensor@200a000 { ++ compatible = "allwinner,sun55i-a523-ths0"; ++ reg = <0x0200a000 0x400>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_THS>, <&ccu CLK_GPADC0>; ++ clock-names = "bus", "gpadc"; ++ resets = <&ccu RST_BUS_THS>; ++ nvmem-cells = <&ths_calibration0>, <&ths_calibration1>; ++ nvmem-cell-names = "calibration", ++ "calibration-second-part"; ++ #thermal-sensor-cells = <0>; ++ }; ++ + sid: efuse@3006000 { + compatible = "allwinner,sun55i-a523-sid", + "allwinner,sun50i-a64-sid"; + reg = <0x03006000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; ++ ++ ths_calibration0: ths-calibration0@38 { ++ reg = <0x38 0x8>; ++ }; ++ ++ ths_calibration1: ths-calibration1@44 { ++ reg = <0x44 0x8>; ++ }; + }; + + gic: interrupt-controller@3400000 { +@@ -732,4 +775,115 @@ npu: npu@7122000 { + power-domains = <&ppu PD_NPU>; + }; + }; ++ ++ thermal-zones { ++ cpu0_thermal: cpu0-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths1 1>; ++ sustainable-power = <1200>; ++ ++ trips { ++ cpu0_threshold: cpu-trip-0 { ++ temperature = <70000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu0_target: cpu-trip-1 { ++ temperature = <90000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu0_critical: cpu-trip-2 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu0_target>; ++ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ cpu4_thermal: cpu4-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths1 0>; ++ sustainable-power = <1600>; ++ ++ trips { ++ cpu4_threshold: cpu-trip-0 { ++ temperature = <70000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu4_target: cpu-trip-1 { ++ temperature = <90000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ cpu4_critical: cpu-trip-2 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ ++ cooling-maps { ++ map0 { ++ trip = <&cpu4_target>; ++ cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>, ++ <&cpu7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; ++ }; ++ }; ++ }; ++ ++ gpu-thermal { ++ polling-delay-passive = <100>; ++ polling-delay = <1000>; ++ thermal-sensors = <&ths1 2>; ++ sustainable-power = <2400>; ++ ++ gpu-trips { ++ gpu_temp_threshold: gpu-trip-0 { ++ temperature = <60000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ gpu_temp_target: gpu-trip-1 { ++ temperature = <90000>; ++ type = "passive"; ++ hysteresis = <0>; ++ }; ++ gpu_temp_critical: gpu-trip-2 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ ++ ddr-thermal { ++ polling-delay-passive = <0>; ++ polling-delay = <0>; ++ thermal-sensors = <&ths0>; ++ ++ trips { ++ ddr_temp_critical: ddr-trip-0 { ++ temperature = <110000>; ++ type = "critical"; ++ hysteresis = <0>; ++ }; ++ }; ++ }; ++ }; + }; diff --git a/patch/kernel/archive/sunxi-dev-6.18/11-allwinner-a523-Enable-I2S-and-SPDIF-TX.patch b/patch/kernel/archive/sunxi-dev-6.18/11-allwinner-a523-Enable-I2S-and-SPDIF-TX.patch new file mode 100644 index 000000000000..6fa71295acd0 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/11-allwinner-a523-Enable-I2S-and-SPDIF-TX.patch @@ -0,0 +1,770 @@ +From 8476f1b10b6acc327455c840d3f89a56ec6dedea Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH] [PATCH v2 01/10] dt-bindings: dma: allwinner,sun50i-a64-dma: Add + +There are two DMA controllers on the A523, one in the main system area +and the other for the MCU. These are the same as the one found on the +A100. The only difference is the DMA endpoint (DRQ) layout. + +Since the number of channels and endpoints are described with additional +generic properties, just add new A523-specific compatible strings and +fallback to the A100 one. + +Acked-by: Conor Dooley +Signed-off-by: Chen-Yu Tsai +--- + .../devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml +index 0f2501f72cca..c3e14eb6cfff 100644 +--- a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml ++++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml +@@ -29,7 +29,10 @@ properties: + - const: allwinner,sun8i-r40-dma + - const: allwinner,sun50i-a64-dma + - items: +- - const: allwinner,sun50i-h616-dma ++ - enum: ++ - allwinner,sun50i-h616-dma ++ - allwinner,sun55i-a523-dma ++ - allwinner,sun55i-a523-mcu-dma + - const: allwinner,sun50i-a100-dma + + reg: + +From 955935d64eeca888d0cde1dd3475b5b82ad37331 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 2/9] auto-split from bundle + +As far as the author can tell, based on their respective manuals, +the I2S interface controllers found in the Allwinner A523 SoC is the +same as ones in the R329 SoC. + +Add a SoC-specific compatible for it, with a fallback to the R329's +compatible. + +Acked-by: Conor Dooley +Signed-off-by: Chen-Yu Tsai +--- + .../devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml +index 739114fb6549..ae86cb5f0a74 100644 +--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml ++++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml +@@ -33,7 +33,9 @@ properties: + - const: allwinner,sun50i-h6-i2s + - const: allwinner,sun50i-r329-i2s + - items: +- - const: allwinner,sun20i-d1-i2s ++ - enum: ++ - allwinner,sun20i-d1-i2s ++ - allwinner,sun55i-a523-i2s + - const: allwinner,sun50i-r329-i2s + + reg: + +From d047c1633c69dca78a06517d595cbbd694a621c7 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 3/9] auto-split from bundle + +The SPDIF hardware block in the A523 SoC has the same layout as the +H616 for the transmitter side. However unlike previous generations, +the hardware block now takes separate module clocks for the TX and RX +sides. This presumably allows the hardware to send and receive audio +streams at different sample rates. The new hardware also gained RX +insertion detection, and some extra information registers. + +Add a new compatible for it without any fallbacks. + +Acked-by: Conor Dooley +Signed-off-by: Chen-Yu Tsai +--- + .../sound/allwinner,sun4i-a10-spdif.yaml | 44 ++++++++++++++++--- + 1 file changed, 38 insertions(+), 6 deletions(-) + +diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +index aa32dc950e72..1d089ba70f45 100644 +--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml ++++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +@@ -23,6 +23,7 @@ properties: + - const: allwinner,sun8i-h3-spdif + - const: allwinner,sun50i-h6-spdif + - const: allwinner,sun50i-h616-spdif ++ - const: allwinner,sun55i-a523-spdif + - items: + - const: allwinner,sun8i-a83t-spdif + - const: allwinner,sun8i-h3-spdif +@@ -37,14 +38,12 @@ properties: + maxItems: 1 + + clocks: +- items: +- - description: Bus Clock +- - description: Module Clock ++ minItems: 2 ++ maxItems: 3 + + clock-names: +- items: +- - const: apb +- - const: spdif ++ minItems: 2 ++ maxItems: 3 + + # Even though it only applies to subschemas under the conditionals, + # not listing them here will trigger a warning because of the +@@ -65,6 +64,7 @@ allOf: + - allwinner,sun8i-h3-spdif + - allwinner,sun50i-h6-spdif + - allwinner,sun50i-h616-spdif ++ - allwinner,sun55i-a523-spdif + + then: + required: +@@ -98,6 +98,38 @@ allOf: + - const: rx + - const: tx + ++ - if: ++ properties: ++ compatible: ++ contains: ++ enum: ++ - allwinner,sun55i-a523-spdif ++ ++ then: ++ properties: ++ clocks: ++ items: ++ - description: Bus Clock ++ - description: TX Clock ++ - description: RX Clock ++ ++ clock-names: ++ items: ++ - const: apb ++ - const: tx ++ - const: rx ++ else: ++ properties: ++ clocks: ++ items: ++ - description: Bus Clock ++ - description: Module Clock ++ ++ clock-names: ++ items: ++ - const: apb ++ - const: spdif ++ + required: + - "#sound-dai-cells" + - compatible + +From c71a090a859ac701105f82166d6ffd03204bfcd0 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 4/9] auto-split from bundle + +The TX side of the SPDIF block on the A523 is almost the same the +previous generations, the only difference being that it has separate +module clock inputs for the TX and RX side. + +Since this driver currently only supports TX, add support for a +different clock name so that TX and RX clocks can be separated +if RX support is ever added. Then add support for the A523. + +Signed-off-by: Chen-Yu Tsai +Reviewed-by: Jernej Skrabec +--- +Changes since v1: +- Dropped bogus name removal +- Dropped clock rate debug message +--- + sound/soc/sunxi/sun4i-spdif.c | 26 ++++++++++++++++++++++++-- + 1 file changed, 24 insertions(+), 2 deletions(-) + +diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c +index 34e5bd94e9af..2e7ac8ab71bb 100644 +--- a/sound/soc/sunxi/sun4i-spdif.c ++++ b/sound/soc/sunxi/sun4i-spdif.c +@@ -177,6 +177,7 @@ struct sun4i_spdif_quirks { + bool has_reset; + unsigned int val_fctl_ftx; + unsigned int mclk_multiplier; ++ const char *tx_clk_name; + }; + + struct sun4i_spdif_dev { +@@ -572,6 +573,14 @@ static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { + .mclk_multiplier = 1, + }; + ++static const struct sun4i_spdif_quirks sun55i_a523_spdif_quirks = { ++ .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, ++ .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, ++ .has_reset = true, ++ .mclk_multiplier = 1, ++ .tx_clk_name = "tx", ++}; ++ + static const struct of_device_id sun4i_spdif_of_match[] = { + { + .compatible = "allwinner,sun4i-a10-spdif", +@@ -594,6 +603,15 @@ static const struct of_device_id sun4i_spdif_of_match[] = { + /* Essentially the same as the H6, but without RX */ + .data = &sun50i_h6_spdif_quirks, + }, ++ { ++ .compatible = "allwinner,sun55i-a523-spdif", ++ /* ++ * Almost the same as H6, but has split the TX and RX clocks, ++ * has a separate reset bit for the RX side, and has some ++ * expanded features for the RX side. ++ */ ++ .data = &sun55i_a523_spdif_quirks, ++ }, + { /* sentinel */ } + }; + MODULE_DEVICE_TABLE(of, sun4i_spdif_of_match); +@@ -635,6 +653,7 @@ static int sun4i_spdif_probe(struct platform_device *pdev) + const struct sun4i_spdif_quirks *quirks; + int ret; + void __iomem *base; ++ const char *tx_clk_name = "spdif"; + + dev_dbg(&pdev->dev, "Entered %s\n", __func__); + +@@ -671,9 +690,12 @@ static int sun4i_spdif_probe(struct platform_device *pdev) + return PTR_ERR(host->apb_clk); + } + +- host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); ++ if (quirks->tx_clk_name) ++ tx_clk_name = quirks->tx_clk_name; ++ host->spdif_clk = devm_clk_get(&pdev->dev, tx_clk_name); + if (IS_ERR(host->spdif_clk)) { +- dev_err(&pdev->dev, "failed to get a spdif clock.\n"); ++ dev_err(&pdev->dev, "failed to get the \"%s\" clock.\n", ++ tx_clk_name); + return PTR_ERR(host->spdif_clk); + } + + +From 6157843778fda7cd704d2c553e7ee9593b831fcb Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 5/9] auto-split from bundle + +The A523 has two DMA controllers. Add device nodes for both. Also hook +up DMA for existing devices. + +Acked-by: Jernej Skrabec +Signed-off-by: Chen-Yu Tsai +--- + .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 56 +++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index a9e051a8bea3..8edbd3873199 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -241,6 +241,8 @@ uart0: serial@2500000 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART0>; + resets = <&ccu RST_BUS_UART0>; ++ dmas = <&dma 14>, <&dma 14>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -252,6 +254,8 @@ uart1: serial@2500400 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART1>; + resets = <&ccu RST_BUS_UART1>; ++ dmas = <&dma 15>, <&dma 15>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -263,6 +267,8 @@ uart2: serial@2500800 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART2>; + resets = <&ccu RST_BUS_UART2>; ++ dmas = <&dma 16>, <&dma 16>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -274,6 +280,8 @@ uart3: serial@2500c00 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART3>; + resets = <&ccu RST_BUS_UART3>; ++ dmas = <&dma 17>, <&dma 17>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -285,6 +293,8 @@ uart4: serial@2501000 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART4>; + resets = <&ccu RST_BUS_UART4>; ++ dmas = <&dma 18>, <&dma 18>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -296,6 +306,8 @@ uart5: serial@2501400 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART5>; + resets = <&ccu RST_BUS_UART5>; ++ dmas = <&dma 19>, <&dma 19>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -307,6 +319,8 @@ uart6: serial@2501800 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART6>; + resets = <&ccu RST_BUS_UART6>; ++ dmas = <&dma 20>, <&dma 20>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -318,6 +332,8 @@ uart7: serial@2501c00 { + reg-io-width = <4>; + clocks = <&ccu CLK_BUS_UART7>; + resets = <&ccu RST_BUS_UART7>; ++ dmas = <&dma 21>, <&dma 21>; ++ dma-names = "tx", "rx"; + status = "disabled"; + }; + +@@ -329,6 +345,8 @@ i2c0: i2c@2502000 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C0>; + resets = <&ccu RST_BUS_I2C0>; ++ dmas = <&dma 43>, <&dma 43>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -342,6 +360,8 @@ i2c1: i2c@2502400 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C1>; + resets = <&ccu RST_BUS_I2C1>; ++ dmas = <&dma 44>, <&dma 44>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -355,6 +375,8 @@ i2c2: i2c@2502800 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C2>; + resets = <&ccu RST_BUS_I2C2>; ++ dmas = <&dma 45>, <&dma 45>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -368,6 +390,8 @@ i2c3: i2c@2502c00 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C3>; + resets = <&ccu RST_BUS_I2C3>; ++ dmas = <&dma 46>, <&dma 46>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -381,6 +405,8 @@ i2c4: i2c@2503000 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C4>; + resets = <&ccu RST_BUS_I2C4>; ++ dmas = <&dma 47>, <&dma 47>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -394,6 +420,8 @@ i2c5: i2c@2503400 { + interrupts = ; + clocks = <&ccu CLK_BUS_I2C5>; + resets = <&ccu RST_BUS_I2C5>; ++ dmas = <&dma 48>, <&dma 48>; ++ dma-names = "rx", "tx"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; +@@ -408,6 +436,19 @@ syscon: syscon@3000000 { + ranges; + }; + ++ dma: dma-controller@3002000 { ++ compatible = "allwinner,sun55i-a523-dma", ++ "allwinner,sun50i-a100-dma"; ++ reg = <0x03002000 0x1000>; ++ interrupts = ; ++ clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>; ++ clock-names = "bus", "mbus"; ++ dma-channels = <16>; ++ dma-requests = <54>; ++ resets = <&ccu RST_BUS_DMA>; ++ #dma-cells = <1>; ++ }; ++ + sid: efuse@3006000 { + compatible = "allwinner,sun55i-a523-sid", + "allwinner,sun50i-a64-sid"; +@@ -729,6 +770,8 @@ r_i2c0: i2c@7081400 { + reg = <0x07081400 0x400>; + interrupts = ; + clocks = <&r_ccu CLK_BUS_R_I2C0>; ++ dmas = <&dma 49>, <&dma 49>; ++ dma-names = "rx", "tx"; + resets = <&r_ccu RST_BUS_R_I2C0>; + pinctrl-names = "default"; + pinctrl-0 = <&r_i2c_pins>; +@@ -775,6 +818,19 @@ mcu_ccu: clock-controller@7102000 { + #reset-cells = <1>; + }; + ++ mcu_dma: dma-controller@7121000 { ++ compatible = "allwinner,sun55i-a523-mcu-dma", ++ "allwinner,sun50i-a100-dma"; ++ reg = <0x07121000 0x1000>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_DMA>, <&mcu_ccu CLK_MCU_MBUS_DMA>; ++ clock-names = "bus", "mbus"; ++ dma-channels = <16>; ++ dma-requests = <15>; ++ resets = <&mcu_ccu RST_BUS_MCU_DMA>; ++ #dma-cells = <1>; ++ }; ++ + npu: npu@7122000 { + compatible = "vivante,gc"; + reg = <0x07122000 0x1000>; + +From 74804cbc70cbd2aa933b3b9144bc9ed7115a14c5 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 6/9] auto-split from bundle + +The A523 has a SPDIF interface that is capable of both playback and +capture. + +Add a node for it. + +Acked-by: Jernej Skrabec +Signed-off-by: Chen-Yu Tsai +--- + arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index 8edbd3873199..33f991dbd00b 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -818,6 +818,21 @@ mcu_ccu: clock-controller@7102000 { + #reset-cells = <1>; + }; + ++ spdif: spdif@7116000 { ++ compatible = "allwinner,sun55i-a523-spdif"; ++ reg = <0x07116000 0x400>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_SPDIF>, ++ <&mcu_ccu CLK_MCU_SPDIF_TX>, ++ <&mcu_ccu CLK_MCU_SPDIF_RX>; ++ clock-names = "apb", "tx", "rx"; ++ resets = <&mcu_ccu RST_BUS_MCU_SPDIF>; ++ dmas = <&mcu_dma 2>, <&mcu_dma 2>; ++ dma-names = "rx", "tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ + mcu_dma: dma-controller@7121000 { + compatible = "allwinner,sun55i-a523-mcu-dma", + "allwinner,sun50i-a100-dma"; + +From 8492eed4f318ce6ba7493ece6ac938fd1599d596 Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 7/9] auto-split from bundle + +The A523 family of SoCs have four I2S controllers capable of both +playback and capture. The user manual also implies that I2S2 also +outputs to the eDP interface controller. + +Add device nodes for all of them. + +Acked-by: Jernej Skrabec +Signed-off-by: Chen-Yu Tsai +--- + .../arm64/boot/dts/allwinner/sun55i-a523.dtsi | 56 +++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index 33f991dbd00b..eea9ce83783c 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -818,6 +818,62 @@ mcu_ccu: clock-controller@7102000 { + #reset-cells = <1>; + }; + ++ i2s0: i2s@7112000 { ++ compatible = "allwinner,sun55i-a523-i2s", ++ "allwinner,sun50i-r329-i2s"; ++ reg = <0x07112000 0x1000>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_I2S0>, <&mcu_ccu CLK_MCU_I2S0>; ++ clock-names = "apb", "mod"; ++ resets = <&mcu_ccu RST_BUS_MCU_I2S0>; ++ dmas = <&mcu_dma 3>, <&mcu_dma 3>; ++ dma-names = "rx", "tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2s1: i2s@7113000 { ++ compatible = "allwinner,sun55i-a523-i2s", ++ "allwinner,sun50i-r329-i2s"; ++ reg = <0x07113000 0x1000>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_I2S1>, <&mcu_ccu CLK_MCU_I2S1>; ++ clock-names = "apb", "mod"; ++ resets = <&mcu_ccu RST_BUS_MCU_I2S1>; ++ dmas = <&mcu_dma 4>, <&mcu_dma 4>; ++ dma-names = "rx", "tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2s2: i2s@7114000 { ++ compatible = "allwinner,sun55i-a523-i2s", ++ "allwinner,sun50i-r329-i2s"; ++ reg = <0x07114000 0x1000>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_I2S2>, <&mcu_ccu CLK_MCU_I2S2>; ++ clock-names = "apb", "mod"; ++ resets = <&mcu_ccu RST_BUS_MCU_I2S2>; ++ dmas = <&mcu_dma 5>, <&mcu_dma 5>; ++ dma-names = "rx", "tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ ++ i2s3: i2s@7115000 { ++ compatible = "allwinner,sun55i-a523-i2s", ++ "allwinner,sun50i-r329-i2s"; ++ reg = <0x07115000 0x1000>; ++ interrupts = ; ++ clocks = <&mcu_ccu CLK_BUS_MCU_I2S3>, <&mcu_ccu CLK_MCU_I2S3>; ++ clock-names = "apb", "mod"; ++ resets = <&mcu_ccu RST_BUS_MCU_I2S3>; ++ dmas = <&mcu_dma 6>, <&mcu_dma 6>; ++ dma-names = "rx", "tx"; ++ #sound-dai-cells = <0>; ++ status = "disabled"; ++ }; ++ + spdif: spdif@7116000 { + compatible = "allwinner,sun55i-a523-spdif"; + reg = <0x07116000 0x400>; + +From 5b35f72a971ae80a9b9b3486029816299407ea4f Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 8/9] auto-split from bundle + +The Radxa Cubie A5E exposes I2S2 through the PI pin group on the 40-pin +GPIO header. + +Add a pinmux setting for it so potential users can directly reference +it. + +Acked-by: Jernej Skrabec +Signed-off-by: Chen-Yu Tsai +--- + arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index eea9ce83783c..cebd8e16e845 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -145,6 +145,14 @@ pio: pinctrl@2000000 { + interrupt-controller; + #interrupt-cells = <3>; + ++ /omit-if-no-ref/ ++ i2s2_pi_pins: i2s2-pi-pins { ++ pins = "PI2", "PI3", "PI4", "PI5"; ++ allwinner,pinmux = <5>; ++ function = "i2s2"; ++ bias-disable; ++ }; ++ + mmc0_pins: mmc0-pins { + pins = "PF0" ,"PF1", "PF2", "PF3", "PF4", "PF5"; + allwinner,pinmux = <2>; + +From 7db143937e63aec2f0026e7b586aeb1f6b871cbc Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Fri, 07 Nov 2025 12:47:21 -0000 +Subject: [PATCH v2 9/9] auto-split from bundle + +The SPDIF TX (called OWA OUT in the datasheet) is available on three +pins. Of those, the PH pin is unlikely to be used since it conflicts +with the first Ethernet controller. + +The Radxa Cubie A5E exposes SPDIF TX through the PI pin group on the +40-pin GPIO header. + +The Orange Pi 4A exposes SPDIF TX through both the PB and PI pin +groups on the 40-pin GPIO header. The PB pin alternatively would be +used for I2S0 though. + +Add pinmux settings for both options so potential users can directly +reference either one. + +Signed-off-by: Chen-Yu Tsai +Acked-by: Jernej Skrabec +--- +Changes since v1: +- New patch; missing from v1 causing dts to not compile +--- + arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +index cebd8e16e845..42dab01e3f56 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a523.dtsi +@@ -200,6 +200,20 @@ rgmii1_pins: rgmii1-pins { + bias-disable; + }; + ++ /omit-if-no-ref/ ++ spdif_out_pb_pin: spdif-pb-pin { ++ pins = "PB8"; ++ function = "spdif"; ++ allwinner,pinmux = <2>; ++ }; ++ ++ /omit-if-no-ref/ ++ spdif_out_pi_pin: spdif-pi-pin { ++ pins = "PI10"; ++ function = "spdif"; ++ allwinner,pinmux = <2>; ++ }; ++ + uart0_pb_pins: uart0-pb-pins { + pins = "PB9", "PB10"; + allwinner,pinmux = <2>; + +From 7db143937e63aec2f0026e7b586aeb1f6b871cbc Mon Sep 17 00:00:00 2001 +From: Chen-Yu Tsai +Date: Mon, 27 Oct 2025 20:56:51 +0800 +Subject: [PATCH v2 10/10] [EXAMPLE] arm64: dts: allwinner: a527-cubie-a5e: Enable I2S and SPDIF output + +This is an example change. + +The Radxa Cubie A5E exposes I2S2 and SPDIF on the 40-pin header. Enable +both. + +In this example, I2S2 is connected to adafruit speaker bonnet, which +sports a pair of MAX98357A for speaker amplication. SPDIF is connected +to a SPDIF interface card for PCs, which has both coaxial and optical +outputs. The output was connected via optical cable to a dumb SPDIF to +analog audio converter. + +Signed-off-by: Chen-Yu Tsai +--- + .../dts/allwinner/sun55i-a527-cubie-a5e.dts | 52 +++++++++++++++++++ + 1 file changed, 52 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index bfdf1728cd14..828d101d28e8 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -64,6 +64,46 @@ reg_usb_vbus: vbus { + gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */ + enable-active-high; + }; ++ ++ codec: audio-codec { ++ compatible = "maxim,max98360a"; ++ #sound-dai-cells = <0>; ++ }; ++ ++ sound-i2s { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "I2S"; ++ simple-audio-card,format = "left_j"; ++ simple-audio-card,bitclock-master = <&dailink_cpu>; ++ simple-audio-card,frame-master = <&dailink_cpu>; ++ simple-audio-card,mclk-fs = <128>; ++ ++ dailink_cpu: simple-audio-card,cpu { ++ sound-dai = <&i2s2>; ++ }; ++ ++ dailink0_master: simple-audio-card,codec { ++ sound-dai = <&codec>; ++ }; ++ }; ++ ++ sound-spdif { ++ compatible = "simple-audio-card"; ++ simple-audio-card,name = "spdif-out"; ++ ++ simple-audio-card,cpu { ++ sound-dai = <&spdif>; ++ }; ++ ++ simple-audio-card,codec { ++ sound-dai = <&spdif_out>; ++ }; ++ }; ++ ++ spdif_out: spdif-out { ++ #sound-dai-cells = <0>; ++ compatible = "linux,spdif-dit"; ++ }; + }; + + &ehci0 { +@@ -101,6 +141,12 @@ &gpu { + status = "okay"; + }; + ++&i2s2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2s2_pi_pins>; ++ status = "okay"; ++}; ++ + &mdio0 { + ext_rgmii0_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; +@@ -344,6 +390,12 @@ &r_pio { + vcc-pm-supply = <®_aldo3>; + }; + ++&spdif { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&spdif_out_pi_pin>; ++ status = "okay"; ++}; ++ + &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; diff --git a/patch/kernel/archive/sunxi-dev-6.18/20-Add-wifi-to-Radxa-Cubie-A5E.patch b/patch/kernel/archive/sunxi-dev-6.18/20-Add-wifi-to-Radxa-Cubie-A5E.patch new file mode 100644 index 000000000000..0e7dc3105ec5 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/20-Add-wifi-to-Radxa-Cubie-A5E.patch @@ -0,0 +1,78 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Fri, 4 Jul 2025 15:17:54 -0400 +Subject: Add wifi (mmc1) to Radxa Cubie A5E + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 28 ++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 1c56306dffa1..d9bbfb916090 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -12,10 +12,11 @@ / { + compatible = "radxa,cubie-a5e", "allwinner,sun55i-a527"; + + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; ++ ethernet2 = &sdio_wifi; + serial0 = &uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; +@@ -41,10 +42,20 @@ iio-hwmon { + compatible = "iio-hwmon"; + io-channels = <&axp717_adc 3>, /* vsys_v */ + <&axp717_adc 4>; /* pmic_temp */ + }; + ++ reg_3v3_wifi: 3v3-wifi { ++ compatible = "regulator-fixed"; ++ regulator-name = "3v3-wifi"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ vin-supply = <®_vcc5v>; ++ gpio = <&r_pio 0 7 GPIO_ACTIVE_HIGH>; /* PL7 */ ++ enable-active-high; ++ }; ++ + reg_vcc5v: vcc5v { + /* board wide 5V supply from the USB-C connector */ + compatible = "regulator-fixed"; + regulator-name = "vcc-5v"; + regulator-min-microvolt = <5000000>; +@@ -94,10 +105,27 @@ &mmc0 { + cd-gpios = <&pio 5 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; /* PF6 */ + bus-width = <4>; + status = "okay"; + }; + ++&mmc1_pins { ++ drive-strength = <40>; ++}; ++ ++&mmc1 { ++ bus-width = <4>; ++ vmmc-supply = <®_3v3_wifi>; ++ non-removable; ++ // todo: investigate why clock above 40MHz makes data errors ++ max-frequency = <35000000>; ++ status = "okay"; ++ ++ sdio_wifi: wifi@1 { ++ reg = <1>; ++ }; ++}; ++ + &ohci0 { + status = "okay"; + }; + + &ohci1 { +-- +Created with Armbian build tools https://github.com/armbian/build + diff --git a/patch/kernel/archive/sunxi-dev-6.18/21-Enable-uart1-on-Radxa-Cubie-A5E.patch b/patch/kernel/archive/sunxi-dev-6.18/21-Enable-uart1-on-Radxa-Cubie-A5E.patch new file mode 100644 index 000000000000..ef8377636072 --- /dev/null +++ b/patch/kernel/archive/sunxi-dev-6.18/21-Enable-uart1-on-Radxa-Cubie-A5E.patch @@ -0,0 +1,48 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Juan Sanchez +Date: Tue, 5 Aug 2025 14:55:52 -0400 +Subject: Enable uart1 (bluetooth) on Radxa Cubie A5E + +Signed-off-by: Juan Sanchez +--- + arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +index 369bde1556ff..37585cac6648 100644 +--- a/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts ++++ b/arch/arm64/boot/dts/allwinner/sun55i-a527-cubie-a5e.dts +@@ -14,10 +14,11 @@ / { + aliases { + ethernet0 = &gmac0; + ethernet1 = &gmac1; + ethernet2 = &sdio_wifi; + serial0 = &uart0; ++ serial1 = &uart1; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +@@ -360,10 +361,18 @@ &uart0 { + pinctrl-names = "default"; + pinctrl-0 = <&uart0_pb_pins>; + status = "okay"; + }; + ++/* Bluetooth */ ++&uart1 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>; ++ uart-has-rtscts; ++ status = "okay"; ++}; ++ + &usb_otg { + /* + * The USB-C port is the primary power supply, so in this configuration + * relies on the other end of the USB cable to supply the VBUS power. + * So use this port in peripheral mode. +-- +Created with Armbian build tools https://github.com/armbian/build +