[openwrt/openwrt] siflower: new target for Siflower SF19A2890

LEDE Commits lede-commits at lists.infradead.org
Tue Sep 17 07:18:53 PDT 2024


981213 pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/4ed209326b5299584ad22b82d0f5ba0d12ceb169

commit 4ed209326b5299584ad22b82d0f5ba0d12ceb169
Author: Chuanhong Guo <gch981213 at gmail.com>
AuthorDate: Thu Aug 8 12:56:03 2024 +0800

    siflower: new target for Siflower SF19A2890
    
    Siflower SF19A2890 is an SoC with:
    Dual-core MIPS InterAptiv at 800MHz
    DDR3 controller
    One Gigabit Ethernet MAC with RGMII and IPv4 HNAT engine
    Built-in 2x2 11N + 2x2 11AC WiFi radio
    USB 2.0 OTG
    I2C/SPI/GPIO and various other peripherals
    
    This PR adds support for SF19A2890 EVB with ethernet support.
    
    EVB spec:
    Memory: DDR3 128M
    Ethernet: RTL8367RB 5-port gigabit switch
    Flash: 16M NOR
    Others: MicroUSB OTG, LED x 1, Reset button x1
    
    The built image can be flashed using u-boot recovery.
    
    This target is marked as source-only until support for a commercial
    router board comes.
    
    Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
---
 target/linux/siflower/Makefile                     |  18 +
 target/linux/siflower/dts/sf19a2890.dtsi           | 651 +++++++++++++++++++++
 target/linux/siflower/dts/sf19a2890_evb.dts        | 140 +++++
 .../arch/mips/include/asm/mach-siflower/kmalloc.h  |   9 +
 .../files-6.6/drivers/clk/siflower/Kconfig         |  27 +
 .../files-6.6/drivers/clk/siflower/Makefile        |   2 +
 .../drivers/clk/siflower/clk-sf19a2890-periph.c    | 170 ++++++
 .../files-6.6/drivers/clk/siflower/clk-sf19a2890.c | 414 +++++++++++++
 .../files-6.6/drivers/gpio/gpio-siflower.c         | 346 +++++++++++
 .../net/ethernet/stmicro/stmmac/dwmac-sf19a2890.c  | 193 ++++++
 .../files-6.6/drivers/phy/siflower/Kconfig         |   6 +
 .../files-6.6/drivers/phy/siflower/Makefile        |   2 +
 .../drivers/phy/siflower/phy-sf19a2890-usb.c       | 145 +++++
 .../files-6.6/drivers/pinctrl/pinctrl-sf19a2890.c  | 515 ++++++++++++++++
 .../drivers/reset/reset-sf19a2890-periph.c         | 131 +++++
 .../dt-bindings/clock/siflower,sf19a2890-clk.h     |  27 +
 target/linux/siflower/image/Makefile               |  28 +
 target/linux/siflower/modules.mk                   |  15 +
 ...1-mips-add-support-for-Siflower-SF19A2890.patch |  59 ++
 .../002-clk-add-drivers-for-sf19a2890.patch        |  31 +
 .../003-reset-add-support-for-sf19a2890.patch      |  38 ++
 .../004-gpio-add-support-for-siflower-socs.patch   |  37 ++
 ...pinctrl-add-driver-for-siflower-sf19a2890.patch |  39 ++
 .../006-stmmac-add-support-for-sf19a2890.patch     |  38 ++
 ...007-phy-add-support-for-SF19A2890-USB-PHY.patch |  31 +
 ...b-dwc2-add-support-for-Siflower-SF19A2890.patch |  36 ++
 ...andle-OTG-interrupt-regardless-of-GINTSTS.patch |  67 +++
 .../sf19a2890/base-files/etc/board.d/02_network    |  42 ++
 .../sf19a2890/base-files/lib/upgrade/platform.sh   |  22 +
 target/linux/siflower/sf19a2890/config-6.6         | 266 +++++++++
 target/linux/siflower/sf19a2890/target.mk          |  12 +
 31 files changed, 3557 insertions(+)

diff --git a/target/linux/siflower/Makefile b/target/linux/siflower/Makefile
new file mode 100644
index 0000000000..d6cded021a
--- /dev/null
+++ b/target/linux/siflower/Makefile
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-only
+include $(TOPDIR)/rules.mk
+
+ARCH:=mipsel
+BOARD:=siflower
+BOARDNAME:=Siflower SoCs
+FEATURES:=squashfs usb usbgadget source-only
+SUBTARGETS:=sf19a2890
+
+KERNEL_PATCHVER:=6.6
+
+include $(INCLUDE_DIR)/target.mk
+
+DEFAULT_PACKAGES += \
+	kmod-gpio-button-hotplug \
+	uboot-envtools
+
+$(eval $(call BuildTarget))
diff --git a/target/linux/siflower/dts/sf19a2890.dtsi b/target/linux/siflower/dts/sf19a2890.dtsi
new file mode 100644
index 0000000000..b8f1cec83e
--- /dev/null
+++ b/target/linux/siflower/dts/sf19a2890.dtsi
@@ -0,0 +1,651 @@
+#include <dt-bindings/clock/siflower,sf19a2890-clk.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/mips-gic.h>
+
+/ {
+	compatible = "siflower,sf19a2890";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+	};
+
+	chosen {
+		bootargs = "earlycon";
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		wlan24_dsp: wlandsp at 1f00000 {
+			reg = <0x01f00000 0x200000>;
+		};
+
+		wlan5_dsp: wlandsp at 2100000 {
+			reg = <0x02100000 0x200000>;
+		};
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu at 0 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			reg = <0>;
+			clocks = <&clk CLK_MUXDIV_CPU>;
+			clock-names = "cpu";
+			clock-latency = <0>;
+		};
+
+		cpu at 1 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			reg = <1>;
+			clocks = <&clk CLK_MUXDIV_CPU>;
+			clock-names = "cpu";
+			clock-latency = <0>;
+		};
+		cpu at 2 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			reg = <2>;
+			clocks = <&clk CLK_MUXDIV_CPU>;
+			clock-names = "cpu";
+			clock-latency = <0>;
+		};
+		cpu at 3 {
+			device_type = "cpu";
+			compatible = "mti,interaptiv";
+			reg = <3>;
+			clocks = <&clk CLK_MUXDIV_CPU>;
+			clock-names = "cpu";
+			clock-latency = <0>;
+		};
+	};
+
+	osc32k: oscillator-32k {
+		compatible = "fixed-clock";
+		clock-frequency = <32768>;
+		#clock-cells = <0>;
+		clock-output-names = "osc32k";
+	};
+
+	osc12m: oscillator-12m {
+		compatible = "fixed-clock";
+		clock-frequency = <12000000>;
+		#clock-cells = <0>;
+		clock-output-names = "osc12m";
+	};
+
+	osc40m: oscillator-40m {
+		compatible = "fixed-clock";
+		clock-frequency = <40000000>;
+		#clock-cells = <0>;
+		clock-output-names = "osc40m";
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&gic>;
+
+		gmac: ethernet at 10800000 {
+			compatible = "siflower,sf19a2890-gmac", "snps,dwmac";
+			reg = <0x10800000 0x200000>,
+				<0x19e04440 0x10>;
+			interrupts = <GIC_SHARED 32 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SHARED 34 IRQ_TYPE_LEVEL_HIGH>,
+					<GIC_SHARED 33 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
+			clocks = <&gmacclk 0>, <&gmacclk 1>, <&gmacclk 3>, <&gmacclk 2>;
+			clock-names = "stmmaceth", "pclk", "ptp_ref", "gmac_byp_ref";
+			resets = <&gmacrst 0>;
+			reset-names = "stmmaceth";
+			pinctrl-names = "default";
+			pinctrl-0 = <&rgmii_pins>, <&mdio_pins>;
+			status = "disabled";
+
+			mdio: mdio {
+				compatible = "snps,dwmac-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
+		};
+
+		wlan_rf: phy at 11c00000{
+			compatible = "siflower,sf19a2890-rf";
+			reg = <0x11c00000 0x600000>;
+			interrupts = <GIC_SHARED 187 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rfclk 1>, <&rfclk 2>, <&rfclk 3>;
+			clock-names = "axi", "boot", "lp";
+			resets = <&rfrst 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&wlan_pins>;
+			status = "disabled";
+		};
+
+		usb: usb at 17000000 {
+			compatible = "siflower,sf19a2890-usb";
+			reg = <0x17000000 0x40000>;
+			interrupts = <GIC_SHARED 128 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&usbclk 0>;
+			clock-names = "otg";
+			resets = <&usbrst 0>;
+			reset-names = "dwc2";
+			dr_mode = "otg";
+			phys = <&usb_phy>;
+			phy-names = "usb2-phy";
+			g-np-tx-fifo-size = <768>;
+			status = "disabled";
+		};
+
+		i2c: i2c at 18100000 {
+			compatible = "snps,designware-i2c";
+			reg = <0x18100000 0x1000>;
+			interrupts = <GIC_SHARED 217 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&i2cclk 0>;
+			clock-names = "ref";
+			resets = <&i2crst 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&i2c0_pins>;
+		};
+
+		spi: spi at 18202000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x18202000 0x1000>;
+			cs-gpios = <&gpio 8 GPIO_ACTIVE_LOW>;
+			clocks = <&spiclk 1>, <&spiclk 0>;
+			clock-names = "sspclk", "apb_pclk";
+			interrupts = <GIC_SHARED 225 IRQ_TYPE_LEVEL_HIGH>;
+			resets = <&spirst 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&spi_pins>;
+			status = "disabled";
+		};
+
+		uart0: serial at 18300000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x18300000 0x1000>;
+			interrupts = <GIC_SHARED 226 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk 3>, <&uartclk 0>;
+			clock-names = "uartclk", "apb_pclk";
+			resets = <&uartrst 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart0_pins>;
+			status = "disabled";
+		};
+
+		uart1: serial at 18301000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x18301000 0x1000>;
+			interrupts = <GIC_SHARED 227 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk 4>, <&uartclk 1>;
+			clock-names = "uartclk", "apb_pclk";
+			resets = <&uartrst 1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart1_pins>;
+			status = "disabled";
+		};
+
+		uart2: serial at 18302000 {
+			compatible = "arm,pl011", "arm,primecell";
+			reg = <0x18302000 0x1000>;
+			interrupts = <GIC_SHARED 228 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&uartclk 5>, <&uartclk 2>;
+			clock-names = "uartclk", "apb_pclk";
+			resets = <&uartrst 2>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&uart2_pins>;
+			status = "disabled";
+		};
+
+		watchdog: watchdog at 18700000 {
+			compatible = "snps,dw-wdt";
+			reg = <0x18700000 0x1000>;
+			interrupts = <GIC_SHARED 238 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&wdtclk 0>;
+			resets = <&wdtrst 0>;
+		};
+
+		gpio: gpio at 19d00000 {
+			compatible = "siflower,sf19a2890-gpio";
+			reg=<0x19d00000 0x100000>;
+			interrupts = <GIC_SHARED 246 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SHARED 247 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SHARED 248 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SHARED 249 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&gpioclk 0>;
+			resets = <&gpiorst 0>;
+
+			gpio-controller;
+			#gpio-cells = <2>;
+			gpio-ranges = <&pinctrl 0 0 49>;
+
+			interrupt-controller;
+			#interrupt-cells = <2>;
+		};
+
+		clk: clock-controller at 19e01000 {
+			compatible = "siflower,sf19a2890-clk";
+			reg = <0x19e01000 0x800>;
+			clocks = <&osc12m>, <&osc40m>;
+			clock-names = "osc12m", "osc40m";
+			#clock-cells = <1>;
+		};
+
+		brom_sysm: syscon at 19e02000 {
+			compatible = "syscon", "simple-mfd";
+			reg = <0x19e02000 0x100>;
+
+			reboot {
+				compatible = "syscon-reboot";
+				offset = <0x30>;
+				value = <0x1>;
+			};
+		};
+
+		gmacrst: reset-controller at 19e04400 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e04400 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x3>;
+		};
+
+		gmacclk: clock-controller at 19e04404 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e04404 0xc>;
+			clocks = <&clk CLK_MUXDIV_BUS1>, <&clk CLK_MUXDIV_CPU>, <&clk CLK_MUXDIV_GMAC_BYP_REF>, <&clk CLK_MUXDIV_ETH_TSU>;
+			clock-output-names = "gmac", "gmac_pclk", "gmac_byp_ref", "ethtsu";
+			#clock-cells = <1>;
+		};
+
+		wlan24rst: reset-controller at 19e08000 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e08000 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x7>;
+		};
+
+		wlan24clk: clock-controller at 19e08004 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e08004 0xc>;
+			clocks = <&clk CLK_MUXDIV_CPU>, <&clk CLK_MUXDIV_BUS2>, <&clk CLK_MUXDIV_WLAN24_PLF>;
+			clock-output-names = "wlan24_axis", "wlan24_axim", "wlan24_plf";
+			#clock-cells = <1>;
+		};
+
+		rfrst: reset-controller at 19e08800 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e08800 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x7>;
+		};
+
+		rfclk: clock-controller at 19e08804 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e08804 0xc>;
+			clocks = <&clk CLK_MUXDIV_BUS2>, <&clk CLK_MUXDIV_CPU>, <&osc12m>, <&osc32k>;
+			clock-output-names = "rf_dft", "rf_axis", "rf_boot", "rf_lp";
+			#clock-cells = <1>;
+		};
+
+		usbrst: reset-controller at 19e0c000 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e0c000 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x7 0x8 0x10>;
+		};
+
+		usbclk: clock-controller at 19e0c004 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e0c004 0xc>;
+			clocks = <&clk CLK_MUXDIV_BUS3>, <&clk CLK_MUXDIV_CPU>, <&clk CLK_MUXDIV_USBPHY_REF>;
+			clock-output-names = "usb", "usb_axim", "usbphy_ref";
+			siflower,valid-gates = <0xd>;
+			siflower,critical-gates = <0x4>;
+			#clock-cells = <1>;
+		};
+
+		usb_phy: usb-phy at 19e0c040 {
+			compatible = "siflower,sf19a2890-usb-phy";
+			reg = <0x19e0C040 0x60>;
+			clocks = <&usbclk 2>;
+			resets = <&usbrst 1>, <&usbrst 2>;
+			reset-names = "power_on_rst", "usb_phy_rst";
+			#phy-cells = <0>;
+			status = "disabled";
+		};
+
+		wlan5rst: reset-controller at 19e0c400 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e0c400 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x7>;
+		};
+
+		wlan5clk: clock-controller at 19e0c404 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e0c404 0xc>;
+			clocks = <&clk CLK_MUXDIV_CPU>, <&clk CLK_MUXDIV_BUS2>, <&clk CLK_MUXDIV_WLAN5_PLF>;
+			clock-output-names = "wlan5_axis", "wlan5_axim", "wlan5_plf";
+			#clock-cells = <1>;
+		};
+
+		i2crst: reset-controller at 19e24400 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e24400 0x4>;
+			#reset-cells = <1>;
+			siflower,num-resets = <1>;
+		};
+
+		i2cclk: clock-controller at 19e24404 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e24404 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "i2c0";
+			#clock-cells = <1>;
+		};
+
+		spirst: reset-controller at 19e24800 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e24800 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x30>;
+		};
+
+		spiclk: clock-controller at 19e24804 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e24804 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>, <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "spi_apb", "spi_ssp";
+			siflower,valid-gates = <0x30>;
+			#clock-cells = <1>;
+		};
+
+		uartrst: reset-controller at 19e24c00 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e24c00 0x4>;
+			#reset-cells = <1>;
+			siflower,reset-masks = <0x11 0x22 0x44>;
+		};
+
+		uartclk: clock-controller at 19e24c04 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e24c04 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>, <&clk CLK_MUXDIV_PBUS>, <&clk CLK_MUXDIV_PBUS>,
+				 <&clk CLK_MUXDIV_UART>, <&clk CLK_MUXDIV_UART>, <&clk CLK_MUXDIV_UART>;
+			clock-output-names = "uart0_apb", "uart1_apb", "uart2_apb",
+					     "uart0", "uart1","uart2";
+			siflower,valid-gates = <0x77>;
+			siflower,critical-gates = <0x11>;
+			#clock-cells = <1>;
+		};
+
+		pwmrst: reset-controller at 19e25400 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e25400 0x4>;
+			#reset-cells = <1>;
+			siflower,num-resets = <1>;
+		};
+
+		pwmclk: clock-controller at 19e25404 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e25404 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "pwm";
+			#clock-cells = <1>;
+		};
+
+		timerrst: reset-controller at 19e25800 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e25800 0x4>;
+			#reset-cells = <1>;
+			siflower,num-resets = <1>;
+		};
+
+		timerclk: clock-controller at 19e25804 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e25804 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "timer";
+			#clock-cells = <1>;
+		};
+
+		wdtrst: reset-controller at 19e25c00 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e25c00 0x4>;
+			#reset-cells = <1>;
+			siflower,num-resets = <1>;
+		};
+
+		wdtclk: clock-controller at 19e25c04 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e25c04 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "wdt";
+			#clock-cells = <1>;
+		};
+
+		gpiorst: reset-controller at 19e2b400 {
+			compatible = "siflower,sf19a2890-periph-reset";
+			reg = <0x19e2b400 0x4>;
+			#reset-cells = <1>;
+			siflower,num-resets = <1>;
+		};
+
+		gpioclk: clock-controller at 19e2b404 {
+			compatible = "siflower,sf19a2890-periph-clk";
+			reg = <0x19e2b404 0xc>;
+			clocks = <&clk CLK_MUXDIV_PBUS>;
+			clock-output-names = "gpio";
+			#clock-cells = <1>;
+		};
+
+		pinctrl: pinctrl at 19e3fc00 {
+			compatible = "siflower,sf19a2890-pinctrl";
+			reg = <0x19e3fc00 0x400>;
+
+			jtag_pins: jtag-pins {
+				tdo {
+					pins = "JTAG_TDO";
+					function = "func0";
+					bias-disable;
+				};
+
+				input-pins {
+					pins = "JTAG_TDI", "JTAG_TMS", "JTAG_TCK";
+					function = "func0";
+					input-enable;
+					bias-disable;
+				};
+
+				trst {
+					pins = "JTAG_RST";
+					function = "func0";
+					input-enable;
+					bias-pull-down;
+				};
+			};
+
+			spi_pins: spi-pins {
+				sck {
+					pins = "SPI_CLK";
+					function = "func0";
+					bias-disable;
+				};
+
+				mosi {
+					pins = "SPI_TXD";
+					function = "func0";
+					bias-pull-down;
+				};
+
+				miso {
+					pins = "SPI_RXD";
+					function = "func0";
+					input-enable;
+					bias-pull-down;
+				};
+
+				cs {
+					pins = "SPI_CSN";
+					bias-pull-up;
+				};
+			};
+
+			uart0_pins: uart0-pins {
+				tx {
+					pins = "UART_TX";
+					function = "func0";
+					bias-pull-up;
+				};
+
+				rx {
+					pins = "UART_RX";
+					function = "func0";
+					input-enable;
+					bias-pull-up;
+				};
+			};
+
+			uart0_rtscts: uart0-rtscts-pins {
+				cts {
+					pins = "I2C_DAT";
+					function = "func0";
+					input-enable;
+					bias-pull-up;
+				};
+
+				rts {
+					pins = "I2C_CLK";
+					function = "func0";
+					bias-pull-up;
+				};
+			};
+
+			uart1_pins: uart1-pins {
+				tx {
+					pins = "JATG_TDO";
+					function = "func1";
+					bias-pull-up;
+				};
+
+				rx {
+					pins = "JATG_TDI";
+					function = "func1";
+					input-enable;
+					bias-pull-up;
+				};
+			};
+
+			uart1_rtscts: uart1-rtscts-pins {
+				cts {
+					pins = "JTAG_TMS";
+					function = "func1";
+					input-enable;
+					bias-pull-up;
+				};
+
+				rts {
+					pins = "JTAG_TCK";
+					function = "func1";
+					bias-pull-up;
+				};
+			};
+
+			uart2_pins: uart2-pins {
+				tx {
+					pins = "I2C_DAT";
+					function = "func1";
+					bias-pull-up;
+				};
+
+				rx {
+					pins = "I2C_CLK";
+					function = "func1";
+					input-enable;
+					bias-pull-up;
+				};
+			};
+
+			rgmii_pins: rgmii-pins {
+				tx-pins {
+					pins =  "RGMII_TXCLK", "RGMII_TXD0",
+						"RGMII_TXD1", "RGMII_TXD2",
+						"RGMII_TXD3", "RGMII_TXCTL";
+					function = "func0";
+					bias-disable;
+				};
+
+				rx-pins {
+					pins = "RGMII_RXCLK", "RGMII_RXD0",
+						"RGMII_RXD1", "RGMII_RXD2",
+						"RGMII_RXD3", "RGMII_RXCTL";
+					function = "func0";
+					input-enable;
+					bias-disable;
+				};
+			};
+
+			mdio_pins: mdio-pins {
+				pins {
+					pins = "RGMII_MDC", "RGMII_MDIO";
+					function = "func0";
+					input-enable;
+					bias-pull-up;
+				};
+			};
+
+			wlan_pins: wlan-pins {
+				pins {
+					pins = "HB0_PA_EN", "HB0_LNA_EN",
+						"HB0_SW_CTRL0", "HB0_SW_CTRL1",
+						"HB1_PA_EN", "HB1_LNA_EN",
+						"HB1_SW_CTRL0", "HB1_SW_CTRL1",
+						"LB0_PA_EN", "LB0_LNA_EN",
+						"LB0_SW_CTRL0", "LB0_SW_CTRL1",
+						"LB1_PA_EN", "LB1_LNA_EN",
+						"LB1_SW_CTRL0", "LB1_SW_CTRL1";
+					function = "func0";
+				};
+			};
+
+
+			i2c0_pins: i2c0-pins {
+				pins {
+					pins = "I2C_CLK", "I2C_DAT";
+					function = "func2";
+					input-enable;
+					bias-pull-up;
+				};
+			};
+		};
+
+		gic: interrupt-controller at 1bdc0000 {
+			compatible = "mti,gic";
+			reg = <0x1bdc0000 0x20000>;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			mti,reserved-ipi-vectors = <0 8>;
+
+			timer {
+				compatible = "mti,gic-timer";
+				interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
+				clocks = <&clk CLK_MUXDIV_CPU>;
+			};
+		};
+	};
+};
diff --git a/target/linux/siflower/dts/sf19a2890_evb.dts b/target/linux/siflower/dts/sf19a2890_evb.dts
new file mode 100644
index 0000000000..669a28b596
--- /dev/null
+++ b/target/linux/siflower/dts/sf19a2890_evb.dts
@@ -0,0 +1,140 @@
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include "sf19a2890.dtsi"
+
+/ {
+	model = "Siflower SF19A2890 Evaluation Board";
+	compatible = "siflower,sf19a2890-evb", "siflower,sf19a2890";
+
+	aliases {
+		led-boot = &led_wlan;
+		led-failsafe = &led_wlan;
+		led-running = &led_wlan;
+		led-upgrade = &led_wlan;
+	};
+
+	chosen {
+		stdout-path = "serial0:115200n8";
+	};
+
+	memory at 0 {
+		device_type = "memory";
+		reg = <0x0 0x8000000>;
+	};
+
+	leds {
+		compatible = "gpio-leds";
+
+		led_wlan: wlan {
+			function = LED_FUNCTION_WLAN;
+			color = <LED_COLOR_ID_RED>;
+			gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
+		};
+	};
+
+	keys {
+		compatible = "gpio-keys";
+
+		reset {
+			label = "reset";
+			gpios = <&gpio 27 GPIO_ACTIVE_LOW>;
+			linux,code = <KEY_RESTART>;
+		};
+	};
+
+	rtl8367rb {
+		compatible = "realtek,rtl8367b";
+		realtek,extif = <6 0 0 1 1 1 1 1 1 2>;
+		mii-bus = <&mdio>;
+		phy-id = <0>;
+	};
+};
+
+&gmac {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	snps,ps-speed = <1000>;
+	nvmem-cells = <&macaddr_factory_0>, <&rgmii_delay_factory_b2>;
+	nvmem-cell-names = "mac-address", "rgmii-delay";
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+		pause;
+	};
+};
+
+&wlan_rf {
+	status = "okay";
+};
+
+&uart0 {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+};
+
+&usb_phy {
+	status = "okay";
+};
+
+&spi {
+	status = "okay";
+	flash at 0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <30000000>;
+
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition at 0 {
+				label = "spl-loader";
+				reg = <0x0 0x20000>; /* 128k */
+				read-only;
+			};
+
+			partition at 20000 {
+				label = "u-boot";
+				reg = <0x20000 0x60000>; /* 384k */
+			};
+
+			partition at 80000 {
+				label = "u-boot-env";
+				reg = <0x80000 0x10000>; /* 64k */
+			};
+
+			factory:partition at 90000 {
+				label = "factory";
+				reg = <0x90000 0x10000>; /* 64k */
+
+				nvmem-layout {
+					compatible = "fixed-layout";
+					#address-cells = <1>;
+					#size-cells = <1>;
+
+					macaddr_factory_0: macaddr at 0 {
+						reg = <0x0 0x6>;
+					};
+
+					rgmii_delay_factory_b2: rgmii-delay at b2 {
+						reg = <0xb2 0x4>;
+					};
+				};
+			};
+
+			partition at a0000 {
+				compatible = "denx,uimage";
+				label = "firmware";
+				reg = <0xa0000 0x0>; /* 640k- */
+			};
+		};
+	};
+};
diff --git a/target/linux/siflower/files-6.6/arch/mips/include/asm/mach-siflower/kmalloc.h b/target/linux/siflower/files-6.6/arch/mips/include/asm/mach-siflower/kmalloc.h
new file mode 100644
index 0000000000..d0b270e2ec
--- /dev/null
+++ b/target/linux/siflower/files-6.6/arch/mips/include/asm/mach-siflower/kmalloc.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_MACH_SIFLOWER_KMALLOC_H
+#define __ASM_MACH_SIFLOWER_KMALLOC_H
+
+#ifdef CONFIG_DMA_NONCOHERENT
+#define ARCH_DMA_MINALIGN	32
+#endif
+
+#endif /* __ASM_MACH_SIFLOWER_KMALLOC_H */
diff --git a/target/linux/siflower/files-6.6/drivers/clk/siflower/Kconfig b/target/linux/siflower/files-6.6/drivers/clk/siflower/Kconfig
new file mode 100644
index 0000000000..8e1c5a8f26
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/clk/siflower/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0
+
+menuconfig CLK_SIFLOWER
+	bool "Siflower SoC driver support"
+	depends on MIPS || COMPILE_TEST
+	help
+	  SoC drivers for Siflower Linux-capable SoCs.
+
+if CLK_SIFLOWER
+
+config CLK_SF19A2890
+	bool "Clock driver for Siflower CLK_SF19A2890"
+	depends on MIPS || COMPILE_TEST
+	help
+	  Supports the Top Clock Module found in SF19A2890. If this
+	  kernel is meant to run on a Siflower SF19A2890 SoC,
+	  enable this driver.
+
+config CLK_SF19A2890_PERIPH
+	bool "Clock driver for Siflower SF19A2890 peripheral clock gates"
+	depends on MIPS || COMPILE_TEST
+	help
+	  Supports the clock gates for various peripherals in SF19A2890.
+	  If this kernel is meant to run on a Siflower SF19A2890 SoC,
+	  enable this driver.
+
+endif
diff --git a/target/linux/siflower/files-6.6/drivers/clk/siflower/Makefile b/target/linux/siflower/files-6.6/drivers/clk/siflower/Makefile
new file mode 100644
index 0000000000..d03a72ee25
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/clk/siflower/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_CLK_SF19A2890) += clk-sf19a2890.o
+obj-$(CONFIG_CLK_SF19A2890_PERIPH) += clk-sf19a2890-periph.o
diff --git a/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890-periph.c b/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890-periph.c
new file mode 100644
index 0000000000..4679c714bd
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890-periph.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/of_clk.h>
+#include <linux/of.h>
+#include <linux/spinlock.h>
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+#define REG_GATE 0x0
+/*
+ * A shared 'Bus Output Enable' signal for all APB peripherals. The peripheral
+ * only responds to bus requests if its dedicated clock is enabled and this
+ * shared BOE is set.
+ */
+#define REG_BOE 0x8
+#define BOE_EN GENMASK(1, 0)
+
+struct sf19a2890_periphclk {
+	void __iomem *base;
+	struct clk_hw hw;
+	u32 idx;
+};
+
+struct sf19a2890_periphclk_priv {
+	struct sf19a2890_periphclk *gates;
+	struct clk_hw_onecell_data clk_data;
+};
+
+static inline struct sf19a2890_periphclk *hw_to_periphclk(struct clk_hw *hw)
+{
+	return container_of(hw, struct sf19a2890_periphclk, hw);
+}
+
+static int sf19a2890_periphclk_enable(struct clk_hw *hw)
+{
+	struct sf19a2890_periphclk *priv = hw_to_periphclk(hw);
+	u32 reg = readl(priv->base + REG_GATE);
+
+	writel(reg | BIT(priv->idx), priv->base + REG_GATE);
+	writel(BOE_EN, priv->base + REG_BOE);
+	return 0;
+}
+
+static void sf19a2890_periphclk_disable(struct clk_hw *hw)
+{
+	struct sf19a2890_periphclk *priv = hw_to_periphclk(hw);
+	u32 reg = readl(priv->base + REG_GATE);
+
+	reg &= ~BIT(priv->idx);
+	writel(reg, priv->base + REG_GATE);
+	if (reg == 0)
+		writel(0, priv->base + REG_BOE);
+}
+
+static int sf19a2890_periphclk_is_enabled(struct clk_hw *hw)
+{
+	struct sf19a2890_periphclk *priv = hw_to_periphclk(hw);
+
+	return !!(readl(priv->base + REG_GATE) & BIT(priv->idx));
+}
+
+static const struct clk_ops sf19a28_periphclk_ops = {
+	.enable = sf19a2890_periphclk_enable,
+	.disable = sf19a2890_periphclk_disable,
+	.is_enabled = sf19a2890_periphclk_is_enabled,
+};
+
+static void __init sf19a2890_periphclk_init(struct device_node *node)
+{
+	struct clk_init_data init = {};
+	struct sf19a2890_periphclk_priv *priv;
+	u32 reg, valid_gates, critical_gates;
+	int num_clks, i, ret, idx;
+	const char *name, *parent;
+	void __iomem *base;
+
+	num_clks = of_count_phandle_with_args(node, "clocks", "#clock-cells");
+	if (num_clks < 1 || num_clks > 32)
+		return;
+
+	ret = of_property_read_u32(node, "siflower,valid-gates", &valid_gates);
+	if (ret < 0)
+		valid_gates = BIT(num_clks) - 1;
+
+	ret = of_property_read_u32(node, "siflower,critical-gates", &critical_gates);
+	if (ret < 0)
+		critical_gates = 0;
+
+	priv = kzalloc(struct_size(priv, clk_data.hws, num_clks), GFP_KERNEL);
+	if (!priv)
+		return;
+
+	priv->clk_data.num = num_clks;
+
+	priv->gates = kcalloc(num_clks, sizeof(struct sf19a2890_periphclk),
+			      GFP_KERNEL);
+	if (!priv->gates)
+		goto err1;
+
+	base = of_iomap(node, 0);
+	if (!base) {
+		pr_err("failed to map resources.\n");
+		goto err2;
+	}
+
+	/* clear unused higher bits for BOE check in disable call. */
+	reg = readl(base + REG_GATE);
+	reg &= valid_gates;
+	writel(reg, base + REG_GATE);
+
+	for (i = 0, idx = 0; i < num_clks && idx < 32; i++, idx++) {
+		ret = of_property_read_string_index(node, "clock-output-names",
+						    i, &name);
+		if (ret != 0) {
+			pr_err("failed to read output name for the %dth gate.\n",
+			       i);
+			goto err3;
+		}
+		parent = of_clk_get_parent_name(node, i);
+		if (!parent) {
+			pr_err("failed to get parent clock for the %dth gate.\n",
+			       i);
+			goto err3;
+		}
+
+		while (!(valid_gates & BIT(idx))) {
+			idx++;
+			if (idx >= 32) {
+				pr_err("too few valid gates.");
+				goto err3;
+			}
+		}
+
+		priv->gates[i].base = base;
+		priv->gates[i].idx = idx;
+		init.name = name;
+		init.ops = &sf19a28_periphclk_ops;
+		init.parent_names = &parent;
+		init.num_parents = 1;
+		init.flags = (critical_gates & BIT(idx)) ? CLK_IS_CRITICAL : 0;
+		priv->gates[i].hw.init = &init;
+
+		ret = clk_hw_register(NULL, &priv->gates[i].hw);
+		if (ret) {
+			pr_err("failed to register the %dth gate: %d.\n", i,
+			       ret);
+			goto err3;
+		}
+		priv->clk_data.hws[i] = &priv->gates[i].hw;
+	}
+
+	ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get,
+				     &priv->clk_data);
+	if (ret) {
+		pr_err("failed to add hw provider.\n");
+		goto err3;
+	}
+	return;
+err3:
+	for (i--; i >= 0; i--)
+		clk_hw_unregister_gate(priv->clk_data.hws[i]);
+err2:
+	kfree(priv->gates);
+err1:
+	kfree(priv);
+}
+
+CLK_OF_DECLARE(sf19a2890_periphclk, "siflower,sf19a2890-periph-clk",
+	       sf19a2890_periphclk_init);
diff --git a/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890.c b/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890.c
new file mode 100644
index 0000000000..626fbe7b8e
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/clk/siflower/clk-sf19a2890.c
@@ -0,0 +1,414 @@
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/compiler.h>
+#include <linux/clk-provider.h>
+#include <linux/bitfield.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/bug.h>
+#include <dt-bindings/clock/siflower,sf19a2890-clk.h>
+
+#define REG_PLL_BASE		0x0
+#define REG_PLL_PD		0x0
+#define  PLL_PD			BIT(0)
+#define  PLL_PD_VCO		BIT(1)
+#define  PLL_PD_POSTDIV		BIT(2)
+#define  PLL_PD_4PHASE		BIT(3)
+#define  PLL_PD_DAC		BIT(4)
+#define  PLL_PD_DSM		BIT(5)
+
+/*
+ * PLL_PARAM is a 48-bit value put into 6 registers, 8-bit per register:
+ * REFDIV = PLL_PARAM[47:42]
+ * POSTDIV2 = PLL_PARAM[41:39]
+ * POSTDIV1 = PLL_PARAM[38:36]
+ * FRAC = PLL_PARAM[35:12]
+ * FBDIV = PLL_PARAM[11:0]
+ */
+
+#define REG_PLL_PARAM(_x)	(0x4 + (_x) * 4)
+#define  PLL_REFDIV_HI		47
+#define  PLL_REFDIV_LO		42
+#define  PLL_POSTDIV2_HI	41
+#define  PLL_POSTDIV2_LO	39
+#define  PLL_POSTDIV1_HI	38
+#define  PLL_POSTDIV1_LO	36
+#define  PLL_FRAC_HI		35
+#define  PLL_FRAC_LO		12
+#define  PLL_FRAC_BITS		(PLL_FRAC_HI - PLL_FRAC_LO + 1)
+#define  PLL_FBDIV_HI		11
+#define  PLL_FBDIV_LO		0
+
+#define REG_PLL_CFG 0x1c
+#define  PLL_CFG_BYPASS		BIT(0)
+#define  PLL_CFG_SRC		GENMASK(2, 1)
+#define  PLL_CFG_OCLK_SEL	BIT(3)
+#define  PLL_CFG_OCLK_GATE	BIT(4)
+#define  PLL_CFG_LOAD_DIVS	BIT(5)
+
+#define REG_PLL_LOCK 0x20
+
+/*
+ * Read-only register indicating the value of the hardware clock source
+ * override pin. When the first bit of this register is set, PLL clock
+ * source is forced to the 40M oscillator regardless of PLL_CFG_SRC
+ * value.
+ */
+#define REG_PLL_SRC_OVERRIDE 0x24
+
+struct sf_clk_common {
+	void __iomem *base;
+	spinlock_t *lock;
+	struct clk_hw hw;
+};
+
+struct sf19a2890_clk {
+	struct sf_clk_common common;
+	ulong offset;
+};
+
+#define SF_CLK_COMMON(_name, _parents, _op, _flags)                           \
+	{                                                                     \
+		.hw.init = CLK_HW_INIT_PARENTS(_name, _parents, _op, _flags), \
+	}
+
+static inline struct sf_clk_common *hw_to_sf_clk_common(struct clk_hw *hw)
+{
+	return container_of(hw, struct sf_clk_common, hw);
+}
+
+static inline struct sf19a2890_clk *cmn_to_clk(struct sf_clk_common *cmn_priv)
+{
+	return container_of(cmn_priv, struct sf19a2890_clk, common);
+}
+
+static inline u32 sf_readl(struct sf_clk_common *priv, u32 reg)
+{
+	return readl(priv->base + reg);
+}
+
+static inline void sf_writel(struct sf_clk_common *priv, u32 reg, u32 val)
+{
+	return writel(val, priv->base + reg);
+}
+
+static inline void sf_rmw(struct sf_clk_common *priv, u32 reg, u32 clr, u32 set)
+{
+	u32 val = sf_readl(priv, reg);
+
+	val &= ~clr;
+	val |= set;
+	sf_writel(priv, reg, val);
+}
+
+static u32 sf_pll_param_get(struct sf19a2890_clk *priv, u32 hi, u32 lo)
+{
+	struct sf_clk_common *cmn = &priv->common;
+	u32 ret = 0;
+	int reg_hi = hi / 8;
+	int reg_lo = lo / 8;
+	u32 reg_hi_pos = hi % 8;
+	u32 reg_lo_pos = lo % 8;
+	int i;
+
+	if (reg_hi == reg_lo) {
+		u32 mask = (BIT(reg_hi_pos - reg_lo_pos + 1)) - 1;
+		u32 reg_val =
+			sf_readl(cmn, priv->offset + REG_PLL_PARAM(reg_hi));
+		return (reg_val >> reg_lo_pos) & mask;
+	}
+
+	ret = sf_readl(cmn, priv->offset + REG_PLL_PARAM(reg_hi)) &
+	      (BIT(reg_hi_pos + 1) - 1);
+	for (i = reg_hi - 1; i > reg_lo; i--)
+		ret = (ret << 8) |
+		      sf_readl(cmn, priv->offset + REG_PLL_PARAM(i));
+	ret = (ret << (8 - reg_lo_pos)) |
+	      (sf_readl(cmn, priv->offset + REG_PLL_PARAM(reg_lo)) >>
+	       reg_lo_pos);
+
+	return ret;
+}
+
+static unsigned long sf19a28_pll_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	u32 refdiv = sf_pll_param_get(priv, PLL_REFDIV_HI, PLL_REFDIV_LO);
+	u32 fbdiv = sf_pll_param_get(priv, PLL_FBDIV_HI, PLL_FBDIV_LO);
+	u32 postdiv1 = sf_pll_param_get(priv, PLL_POSTDIV1_HI, PLL_POSTDIV1_LO);
+	u32 postdiv2 = sf_pll_param_get(priv, PLL_POSTDIV2_HI, PLL_POSTDIV2_LO);
+	u32 pll_pd = sf_readl(cmn_priv, PLL_PD);
+	u32 ref = parent_rate / refdiv;
+	u32 rate = ref * fbdiv;
+	u32 frac;
+	u64 frac_rate;
+
+	if (!(pll_pd & PLL_PD_DSM)) {
+		frac = sf_pll_param_get(priv, PLL_FRAC_HI, PLL_FRAC_LO);
+		frac_rate = ((u64)rate * frac) >> PLL_FRAC_BITS;
+		rate += frac_rate;
+	}
+	rate = rate / postdiv1 / postdiv2;
+	return rate;
+}
+
+static u8 sf19a28_pll_get_parent(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	u32 cfg;
+
+	if (sf_readl(cmn_priv, priv->offset + REG_PLL_SRC_OVERRIDE))
+		return 1;
+	cfg = sf_readl(cmn_priv, priv->offset + REG_PLL_CFG);
+	return (FIELD_GET(PLL_CFG_SRC, cfg) == 1);
+}
+
+static const struct clk_ops sf19a28_pll_ops = {
+	.recalc_rate = sf19a28_pll_recalc_rate,
+	.get_parent = sf19a28_pll_get_parent,
+};
+
+static const char * const clk_pll_parents[] = { "osc12m", "osc40m" };
+
+#define SF19A28_PLL(_name, _offset, _flags)				\
+	struct sf19a2890_clk _name = {					\
+		.common = SF_CLK_COMMON(#_name, clk_pll_parents,	\
+					&sf19a28_pll_ops, _flags),	\
+		.offset = REG_PLL_BASE + _offset,			\
+	}
+
+static SF19A28_PLL(pll_cpu, 0x0, 0);
+static SF19A28_PLL(pll_ddr, 0x40, 0);
+static SF19A28_PLL(pll_cmn, 0x80, 0);
+
+#define REG_MUXDIV_BASE		0x400
+#define REG_MUXDIV_CFG		0x0
+#define  MUXDIV_USE_NCO		BIT(3)
+#define  MUXDIV_SRC_SEL		GENMASK(2, 0)
+#define REG_MUXDIV_RATIO	0x4
+#define  MUXDIV_RATIO_MAX	0xff
+#define REG_MUXDIV_NCO_V	0x8
+#define REG_MUXDIV_EN		0xc
+#define REG_MUXDIV_XN_DIV_RATIO	0x10
+#define  MUXDIV_XN_DIV_MAX	3
+
+static unsigned long sf19a28_muxdiv_recalc_rate(struct clk_hw *hw,
+						unsigned long parent_rate)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	u32 div;
+
+	div = sf_readl(cmn_priv, priv->offset + REG_MUXDIV_RATIO) + 1;
+	return parent_rate / div;
+}
+
+int sf19a28_muxdiv_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
+{
+	unsigned int div;
+
+	div = DIV_ROUND_CLOSEST(req->best_parent_rate, req->rate);
+	if (!div)
+		div = 1;
+	else if (div > MUXDIV_RATIO_MAX + 1)
+		div = MUXDIV_RATIO_MAX + 1;
+
+	req->rate = req->best_parent_rate / div;
+	return 0;
+}
+
+static int sf19a28_muxdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long parent_rate)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	unsigned int div;
+
+	div = DIV_ROUND_CLOSEST(parent_rate, rate);
+	if (div < 1)
+		div = 1;
+	else if (div > MUXDIV_RATIO_MAX + 1)
+		div = MUXDIV_RATIO_MAX + 1;
+	div -= 1;
+
+	sf_writel(cmn_priv, priv->offset + REG_MUXDIV_RATIO, div);
+
+	return 0;
+}
+
+static int sf19a28_muxdiv_enable(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+
+	sf_writel(cmn_priv, priv->offset + REG_MUXDIV_EN, 1);
+	return 0;
+}
+
+static void sf19a28_muxdiv_disable(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+
+	sf_writel(cmn_priv, priv->offset + REG_MUXDIV_EN, 0);
+}
+
+static int sf19a28_muxdiv_is_enabled(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+
+	return !!sf_readl(cmn_priv, priv->offset + REG_MUXDIV_EN);
+}
+
+static u8 sf19a28_muxdiv_get_parent(struct clk_hw *hw)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	u32 cfg = sf_readl(cmn_priv, priv->offset + REG_MUXDIV_CFG);
+	u32 src = FIELD_GET(MUXDIV_SRC_SEL, cfg);
+
+	if (src <= 2)
+		return src;
+	if (src == 4)
+		return 3;
+	return 4;
+}
+
+static int sf19a28_muxdiv_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sf_clk_common *cmn_priv = hw_to_sf_clk_common(hw);
+	struct sf19a2890_clk *priv = cmn_to_clk(cmn_priv);
+	u32 src;
+
+	if (index <= 2)
+		src = index;
+	else if (index == 3)
+		src = 4;
+	else
+		src = 6;
+	sf_writel(cmn_priv, priv->offset + REG_MUXDIV_CFG, src);
+	return 0;
+}
+
+static const char * const clk_muxdiv_parents[] = { "pll_cpu", "pll_ddr", "pll_cmn",
+					    "osc12m", "osc40m" };
+
+static const struct clk_ops sf19a28_muxdiv_ops = {
+	.recalc_rate = sf19a28_muxdiv_recalc_rate,
+	.determine_rate = sf19a28_muxdiv_determine_rate,
+	.set_rate = sf19a28_muxdiv_set_rate,
+	.enable = sf19a28_muxdiv_enable,
+	.disable = sf19a28_muxdiv_disable,
+	.is_enabled = sf19a28_muxdiv_is_enabled,
+	.get_parent = sf19a28_muxdiv_get_parent,
+	.set_parent = sf19a28_muxdiv_set_parent,
+};
+
+#define SF19A28_MUXDIV(_name, _offset, _flags)				\
+	struct sf19a2890_clk _name = {					\
+		.common = SF_CLK_COMMON(#_name, clk_muxdiv_parents,	\
+					&sf19a28_muxdiv_ops, _flags),	\
+		.offset = REG_MUXDIV_BASE + _offset,			\
+	}
+
+static SF19A28_MUXDIV(muxdiv_bus1, 0x0, CLK_IS_CRITICAL);
+static SF19A28_MUXDIV(muxdiv_bus2, 0x20, CLK_IS_CRITICAL);
+static SF19A28_MUXDIV(muxdiv_bus3, 0x40, CLK_IS_CRITICAL);
+static SF19A28_MUXDIV(muxdiv_cpu, 0x100, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT);
+static SF19A28_MUXDIV(muxdiv_pbus, 0x120, CLK_IS_CRITICAL);
+static SF19A28_MUXDIV(muxdiv_mem_phy, 0x140, CLK_IS_CRITICAL);
+static SF19A28_MUXDIV(muxdiv_uart, 0x180, 0);
+static SF19A28_MUXDIV(muxdiv_eth_ref, 0x200, 0);
+static SF19A28_MUXDIV(muxdiv_eth_byp_ref, 0x220, 0);
+static SF19A28_MUXDIV(muxdiv_eth_tsu, 0x240, 0);
+static SF19A28_MUXDIV(muxdiv_gmac_byp_ref, 0x260, 0);
+static SF19A28_MUXDIV(muxdiv_m6250_0, 0x280, 0);
+static SF19A28_MUXDIV(muxdiv_m6250_1, 0x2a0, 0);
+static SF19A28_MUXDIV(muxdiv_wlan24_plf, 0x2c0, 0);
+static SF19A28_MUXDIV(muxdiv_wlan5_plf, 0x2e0, 0);
+static SF19A28_MUXDIV(muxdiv_usbphy_ref, 0x300, 0);
+static SF19A28_MUXDIV(muxdiv_tclk, 0x320, 0);
+static SF19A28_MUXDIV(muxdiv_npu_pe, 0x340, 0);
+
+static struct clk_hw_onecell_data sf19a2890_hw_clks = {
+	.num = CLK_SF19A2890_MAX,
+	.hws = {
+		[CLK_PLL_CPU] = &pll_cpu.common.hw,
+		[CLK_PLL_DDR] = &pll_ddr.common.hw,
+		[CLK_PLL_CMN] = &pll_cmn.common.hw,
+		[CLK_MUXDIV_BUS1] = &muxdiv_bus1.common.hw,
+		[CLK_MUXDIV_BUS2] = &muxdiv_bus2.common.hw,
+		[CLK_MUXDIV_BUS3] = &muxdiv_bus3.common.hw,
+		[CLK_MUXDIV_CPU] = &muxdiv_cpu.common.hw,
+		[CLK_MUXDIV_PBUS] = &muxdiv_pbus.common.hw,
+		[CLK_MUXDIV_MEM_PHY] = &muxdiv_mem_phy.common.hw,
+		[CLK_MUXDIV_UART] = &muxdiv_uart.common.hw,
+		[CLK_MUXDIV_ETH_REF] = &muxdiv_eth_ref.common.hw,
+		[CLK_MUXDIV_ETH_BYP_REF] = &muxdiv_eth_byp_ref.common.hw,
+		[CLK_MUXDIV_ETH_TSU] = &muxdiv_eth_tsu.common.hw,
+		[CLK_MUXDIV_GMAC_BYP_REF] = &muxdiv_gmac_byp_ref.common.hw,
+		[CLK_MUXDIV_M6250_0] = &muxdiv_m6250_0.common.hw,
+		[CLK_MUXDIV_M6250_1] = &muxdiv_m6250_1.common.hw,
+		[CLK_MUXDIV_WLAN24_PLF] = &muxdiv_wlan24_plf.common.hw,
+		[CLK_MUXDIV_WLAN5_PLF] = &muxdiv_wlan5_plf.common.hw,
+		[CLK_MUXDIV_USBPHY_REF] = &muxdiv_usbphy_ref.common.hw,
+		[CLK_MUXDIV_TCLK] = &muxdiv_tclk.common.hw,
+		[CLK_MUXDIV_NPU_PE_CLK] = &muxdiv_npu_pe.common.hw,
+	},
+};
+
+
+struct sf19a2890_clk_ctrl {
+	void __iomem *base;
+	spinlock_t lock;
+};
+
+static void __init sf19a2890_clk_init(struct device_node *node)
+{
+	struct sf19a2890_clk_ctrl *ctrl;
+	int i, ret;
+
+	ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return;
+
+	ctrl->base = of_iomap(node, 0);
+	if (!ctrl->base) {
+		pr_err("failed to map resources.\n");
+		return;
+	}
+
+	spin_lock_init(&ctrl->lock);
+
+	for (i = 0; i < sf19a2890_hw_clks.num; i++) {
+		struct clk_hw *hw = sf19a2890_hw_clks.hws[i];
+		struct sf_clk_common *common;
+
+		if (!hw)
+			continue;
+		common = hw_to_sf_clk_common(hw);
+		common->base = ctrl->base;
+		common->lock = &ctrl->lock;
+		ret = clk_hw_register(NULL, hw);
+		if (ret) {
+			pr_err("Couldn't register clock %d: %d\n", i, ret);
+			goto err;
+		}
+	}
+
+	ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, &sf19a2890_hw_clks);
+	if (ret) {
+		pr_err("failed to add hw provider.\n");
+		goto err;
+	}
+	return;
+err:
+	iounmap(ctrl->base);
+}
+
+CLK_OF_DECLARE(sf19a2890_clk, "siflower,sf19a2890-clk", sf19a2890_clk_init);
diff --git a/target/linux/siflower/files-6.6/drivers/gpio/gpio-siflower.c b/target/linux/siflower/files-6.6/drivers/gpio/gpio-siflower.c
new file mode 100644
index 0000000000..b28ecafec8
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/gpio/gpio-siflower.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/pinctrl/consumer.h>
+#include <linux/clk.h>
+#include <linux/gpio/driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <asm/div64.h>
+
+#define GPIO_IR(n)	(0x40 * (n) + 0x00)
+#define GPIO_OR(n)	(0x40 * (n) + 0x04)
+#define GPIO_OEN(n)	(0x40 * (n) + 0x08)
+#define GPIO_IMR(n)	(0x40 * (n) + 0x0c)
+#define GPIO_GPIMR(n)	(0x40 * (n) + 0x10)
+#define GPIO_PIR(n)	(0x40 * (n) + 0x14)
+#define GPIO_ITR(n)	(0x40 * (n) + 0x18)
+#define GPIO_IFR(n)	(0x40 * (n) + 0x1c)
+#define GPIO_ICR(n)	(0x40 * (n) + 0x20)
+#define GPIO_GPxIR(n)	(0x4 * (n) + 0x4000)
+
+#define GPIOS_PER_GROUP	16
+
+struct sf_gpio_priv {
+	struct gpio_chip gc;
+	void __iomem *base;
+	struct clk *clk;
+	struct reset_control *rstc;
+	unsigned int irq[];
+};
+
+#define to_sf_gpio(x)	container_of(x, struct sf_gpio_priv, gc)
+
+static u32 sf_gpio_rd(struct sf_gpio_priv *priv, unsigned long reg)
+{
+	return readl_relaxed(priv->base + reg);
+}
+
+static void sf_gpio_wr(struct sf_gpio_priv *priv, unsigned long reg,
+		       u32 val)
+{
+	writel_relaxed(val, priv->base + reg);
+}
+
+static int sf_gpio_get_value(struct gpio_chip *gc, unsigned int offset)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+	return sf_gpio_rd(priv, GPIO_IR(offset));
+}
+
+static void sf_gpio_set_value(struct gpio_chip *gc, unsigned int offset,
+			      int value)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+	sf_gpio_wr(priv, GPIO_OR(offset), value);
+}
+
+static int sf_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+	if (sf_gpio_rd(priv, GPIO_OEN(offset)))
+		return GPIO_LINE_DIRECTION_IN;
+	else
+		return GPIO_LINE_DIRECTION_OUT;
+}
+
+static int sf_gpio_direction_input(struct gpio_chip *gc, unsigned int offset)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+	sf_gpio_wr(priv, GPIO_OEN(offset), 1);
+	return 0;
+}
+
+static int sf_gpio_direction_output(struct gpio_chip *gc, unsigned int offset,
+				    int value)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+
+	sf_gpio_wr(priv, GPIO_OR(offset), value);
+	sf_gpio_wr(priv, GPIO_OEN(offset), 0);
+	return 0;
+}
+
+static int sf_gpio_set_debounce(struct gpio_chip *gc, unsigned int offset,
+				u32 debounce)
+{
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned long freq = clk_get_rate(priv->clk);
+	u64 mul;
+
+	/* (ICR + 1) * IFR = debounce_us * clkfreq_mhz / 4 */
+	mul = (u64)debounce * freq;
+	do_div(mul, 1000000 * 4);
+	if (mul > 0xff00)
+		return -EINVAL;
+
+	sf_gpio_wr(priv, GPIO_ICR(offset), 0xff);
+	sf_gpio_wr(priv, GPIO_IFR(offset), DIV_ROUND_UP(mul, 0x100));
+
+	return 0;
+}
+
+static int sf_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
+			      unsigned long config)
+{
+	switch (pinconf_to_config_param(config)) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		return sf_gpio_set_debounce(gc, offset,
+			pinconf_to_config_argument(config));
+	default:
+		return gpiochip_generic_config(gc, offset, config);
+	}
+}
+
+static void sf_gpio_irq_ack(struct irq_data *data)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned long offset = irqd_to_hwirq(data);
+
+	sf_gpio_wr(priv, GPIO_PIR(offset), 0);
+}
+
+static void sf_gpio_irq_mask(struct irq_data *data)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned long offset = irqd_to_hwirq(data);
+
+	sf_gpio_wr(priv, GPIO_IMR(offset), 1);
+	sf_gpio_wr(priv, GPIO_GPIMR(offset), 1);
+}
+
+static void sf_gpio_irq_unmask(struct irq_data *data)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned long offset = irqd_to_hwirq(data);
+
+	sf_gpio_wr(priv, GPIO_IMR(offset), 0);
+	sf_gpio_wr(priv, GPIO_GPIMR(offset), 0);
+}
+
+/* We are actually setting the parents' affinity. */
+static int sf_gpio_irq_set_affinity(struct irq_data *data,
+				    const struct cpumask *dest, bool force)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	unsigned long offset = irqd_to_hwirq(data);
+	const struct cpumask *pdest;
+	struct irq_desc *pdesc;
+	struct irq_data *pdata;
+	unsigned int group;
+	int ret;
+
+	/* Find the parent IRQ and call its irq_set_affinity */
+	group = offset / GPIOS_PER_GROUP;
+	if (group >= gc->irq.num_parents)
+		return -EINVAL;
+
+	pdesc = irq_to_desc(gc->irq.parents[group]);
+	if (!pdesc)
+		return -EINVAL;
+
+	pdata = irq_desc_get_irq_data(pdesc);
+	if (!pdata->chip->irq_set_affinity)
+		return -EINVAL;
+
+	ret = pdata->chip->irq_set_affinity(pdata, dest, force);
+	if (ret < 0)
+		return ret;
+
+	/* Copy its effective_affinity back */
+	pdest = irq_data_get_effective_affinity_mask(pdata);
+	irq_data_update_effective_affinity(data, pdest);
+	return ret;
+}
+
+static int sf_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
+{
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned long offset = irqd_to_hwirq(data);
+	u32 val;
+
+	switch (flow_type) {
+	case IRQ_TYPE_EDGE_RISING:
+		val = 4;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		val = 2;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		val = 6;
+		break;
+	case IRQ_TYPE_LEVEL_HIGH:
+		val = 1;
+		break;
+	case IRQ_TYPE_LEVEL_LOW:
+		val = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	sf_gpio_wr(priv, GPIO_ITR(offset), val);
+
+	if (flow_type & IRQ_TYPE_LEVEL_MASK)
+		irq_set_handler_locked(data, handle_level_irq);
+	else
+		irq_set_handler_locked(data, handle_edge_irq);
+
+	return 0;
+}
+
+static const struct irq_chip sf_gpio_irqchip = {
+	.name			= KBUILD_MODNAME,
+	.irq_ack		= sf_gpio_irq_ack,
+	.irq_mask		= sf_gpio_irq_mask,
+	.irq_unmask		= sf_gpio_irq_unmask,
+	.irq_set_affinity	= sf_gpio_irq_set_affinity,
+	.irq_set_type		= sf_gpio_irq_set_type,
+	.flags			= IRQCHIP_IMMUTABLE,
+	GPIOCHIP_IRQ_RESOURCE_HELPERS,
+};
+
+static void sf_gpio_irq_handler(struct irq_desc *desc)
+{
+	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
+	struct irq_chip *ic = irq_desc_get_chip(desc);
+	struct sf_gpio_priv *priv = to_sf_gpio(gc);
+	unsigned int irq = irq_desc_get_irq(desc);
+	unsigned int group = irq - priv->irq[0];
+	unsigned long pending;
+	unsigned int n;
+
+	chained_irq_enter(ic, desc);
+
+	pending = sf_gpio_rd(priv, GPIO_GPxIR(group));
+	for_each_set_bit(n, &pending, GPIOS_PER_GROUP) {
+		generic_handle_domain_irq(gc->irq.domain,
+					  n + group * GPIOS_PER_GROUP);
+	}
+
+	chained_irq_exit(ic, desc);
+}
+
+static int sf_gpio_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sf_gpio_priv *priv;
+	struct gpio_irq_chip *girq;
+	struct gpio_chip *gc;
+	u32 ngpios, ngroups;
+	int ret, i;
+
+	ngpios = (unsigned int) device_get_match_data(dev);
+	ngroups = DIV_ROUND_UP(ngpios, GPIOS_PER_GROUP);
+	priv = devm_kzalloc(dev, struct_size(priv, irq, ngroups), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	priv->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->clk = devm_clk_get_enabled(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	priv->rstc = devm_reset_control_get_optional(&pdev->dev, NULL);
+	if (IS_ERR(priv->rstc))
+		return PTR_ERR(priv->rstc);
+
+	ret = reset_control_deassert(priv->rstc);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < ngroups; i++) {
+		ret = platform_get_irq(pdev, i);
+		if (ret < 0)
+			return ret;
+
+		priv->irq[i] = ret;
+	}
+
+	gc = &priv->gc;
+	gc->label = KBUILD_MODNAME;
+	gc->parent = dev;
+	gc->owner = THIS_MODULE;
+	gc->request = gpiochip_generic_request;
+	gc->free = gpiochip_generic_free;
+	gc->get_direction = sf_gpio_get_direction;
+	gc->direction_input = sf_gpio_direction_input;
+	gc->direction_output = sf_gpio_direction_output;
+	gc->get = sf_gpio_get_value;
+	gc->set = sf_gpio_set_value;
+	gc->set_config = sf_gpio_set_config;
+	gc->base = -1;
+	gc->ngpio = ngpios;
+
+	girq = &gc->irq;
+	gpio_irq_chip_set_chip(girq, &sf_gpio_irqchip);
+	girq->num_parents = ngroups;
+	girq->parents = priv->irq;
+	girq->parent_handler = sf_gpio_irq_handler;
+	girq->default_type = IRQ_TYPE_NONE;
+	girq->handler = handle_bad_irq;
+
+	platform_set_drvdata(pdev, priv);
+	return devm_gpiochip_add_data(dev, gc, priv);
+}
+
+static int sf_gpio_remove(struct platform_device *pdev)
+{
+	struct sf_gpio_priv *priv = platform_get_drvdata(pdev);
+
+	reset_control_assert(priv->rstc);
+	return 0;
+}
+
+static const struct of_device_id sf_gpio_ids[] = {
+	{ .compatible = "siflower,sf19a2890-gpio", .data = (void *)49 },
+	{},
+};
+MODULE_DEVICE_TABLE(of, sf_gpio_ids);
+
+static struct platform_driver sf_gpio_driver = {
+	.probe		= sf_gpio_probe,
+	.remove		= sf_gpio_remove,
+	.driver = {
+		.name		= "siflower_gpio",
+		.owner		= THIS_MODULE,
+		.of_match_table	= sf_gpio_ids,
+	},
+};
+module_platform_driver(sf_gpio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Qingfang Deng <qingfang.deng at siflower.com.cn>");
+MODULE_DESCRIPTION("GPIO driver for SiFlower SoCs");
diff --git a/target/linux/siflower/files-6.6/drivers/net/ethernet/stmicro/stmmac/dwmac-sf19a2890.c b/target/linux/siflower/files-6.6/drivers/net/ethernet/stmicro/stmmac/dwmac-sf19a2890.c
new file mode 100644
index 0000000000..05067e9a43
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/net/ethernet/stmicro/stmmac/dwmac-sf19a2890.c
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Siflower SF19A2890 GMAC glue layer
+ * SF19A2890 GMAC is a DWMAC 3.73a with a custom HNAT engine
+ * between its MAC and DMA engine.
+ *
+ * Copyright (C) 2024 Chuanhong Guo <gch981213 at gmail.com>
+ */
+
+#include <linux/of_net.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/nvmem-consumer.h>
+
+#include "stmmac.h"
+#include "stmmac_platform.h"
+
+struct sf19a2890_gmac_priv {
+	struct device *dev;
+	void __iomem *gmac_cfg;
+	struct clk *gmac_byp_ref_clk;
+};
+
+#define REG_MISC		0x0
+#define  MISC_PHY_INTF_SEL	GENMASK(2, 0)
+#define   PHY_IF_GMII_MII	0
+#define   PHY_IF_RGMII		1
+#define   PHY_IF_RMII		4
+#define  MISC_PTP_AUX_TS_TRIG	BIT(3)
+#define  MISC_SBD_FLOWCTRL	BIT(4)
+#define  CLK_RMII_OEN		BIT(5)
+
+#define REG_CLK_TX_DELAY	0x4
+#define REG_CLK_RX_PHY_DELAY	0x8
+#define REG_CLK_RX_PHY_DELAY_EN	0xc
+
+/* Siflower stores RGMII delay as a 4-byte hex string in MTD. */
+#define SFGMAC_DELAY_STR_LEN	4
+static int sfgmac_set_delay_from_nvmem(struct sf19a2890_gmac_priv *priv)
+{
+	struct device_node *np = priv->dev->of_node;
+	int ret = 0;
+	struct nvmem_cell *cell;
+	const void *data;
+	size_t retlen;
+	u16 gmac_delay;
+	u8 delay_tx, delay_rx;
+
+	cell = of_nvmem_cell_get(np, "rgmii-delay");
+	if (IS_ERR(cell))
+		return PTR_ERR(cell);
+
+	data = nvmem_cell_read(cell, &retlen);
+	nvmem_cell_put(cell);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	if (retlen < SFGMAC_DELAY_STR_LEN) {
+		ret = -EINVAL;
+		goto exit;
+	}
+
+	ret = kstrtou16(data, 16, &gmac_delay);
+	if (ret == 0) {
+		delay_tx = (gmac_delay >> 8) & 0xff;
+		delay_rx = gmac_delay & 0xff;
+		writel(delay_tx, priv->gmac_cfg + REG_CLK_TX_DELAY);
+		writel(delay_rx, priv->gmac_cfg + REG_CLK_RX_PHY_DELAY);
+		if (delay_rx)
+			writel(1, priv->gmac_cfg + REG_CLK_RX_PHY_DELAY_EN);
+	}
+
+exit:
+	kfree(data);
+
+	return ret;
+}
+
+static int sfgmac_setup_phy_interface(struct sf19a2890_gmac_priv *priv)
+{
+	phy_interface_t phy_iface;
+	int mode;
+	u32 reg;
+
+	of_get_phy_mode(priv->dev->of_node, &phy_iface);
+	switch (phy_iface) {
+	case PHY_INTERFACE_MODE_MII:
+	case PHY_INTERFACE_MODE_GMII:
+		mode = PHY_IF_GMII_MII;
+		break;
+	case PHY_INTERFACE_MODE_RMII:
+		mode = PHY_IF_RMII;
+		break;
+	case PHY_INTERFACE_MODE_RGMII:
+	case PHY_INTERFACE_MODE_RGMII_ID:
+	case PHY_INTERFACE_MODE_RGMII_RXID:
+	case PHY_INTERFACE_MODE_RGMII_TXID:
+		mode = PHY_IF_RGMII;
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+	reg = readl(priv->gmac_cfg + REG_MISC);
+	reg &= ~MISC_PHY_INTF_SEL;
+	reg |= FIELD_PREP(MISC_PHY_INTF_SEL, mode);
+	writel(reg, priv->gmac_cfg + REG_MISC);
+	return 0;
+}
+
+static int sf19a2890_gmac_probe(struct platform_device *pdev)
+{
+	struct plat_stmmacenet_data *plat_dat;
+	struct sf19a2890_gmac_priv *priv;
+	struct stmmac_resources stmmac_res;
+	int ret;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	priv->dev = &pdev->dev;
+
+	priv->gmac_byp_ref_clk = devm_clk_get_enabled(&pdev->dev, "gmac_byp_ref");
+	if (IS_ERR(priv->gmac_byp_ref_clk))
+		return PTR_ERR(priv->gmac_byp_ref_clk);
+
+	priv->gmac_cfg = devm_platform_ioremap_resource(pdev, 1);
+	if (IS_ERR(priv->gmac_cfg)) {
+		dev_err(&pdev->dev, "failed to map regs for gmac config.\n");
+		return PTR_ERR(priv->gmac_cfg);
+	}
+
+	ret = sfgmac_set_delay_from_nvmem(priv);
+	if (ret == -EPROBE_DEFER)
+		return -EPROBE_DEFER;
+
+	ret = sfgmac_setup_phy_interface(priv);
+	if (ret)
+		return ret;
+
+	ret = stmmac_get_platform_resources(pdev, &stmmac_res);
+	if (ret)
+		return ret;
+
+	plat_dat = stmmac_probe_config_dt(pdev, stmmac_res.mac);
+	if (IS_ERR(plat_dat)) {
+		dev_err(&pdev->dev, "dt configuration failed\n");
+		return PTR_ERR(plat_dat);
+	}
+
+	plat_dat->bsp_priv = priv;
+	/* This DWMAC has PCSSEL set, but it's not SGMII capable, and doesn't
+	 * return anything in PCS registers under RGMII mode.
+	 * Set this flag to bypass reading pcs regs stmmac_ethtool_get_link_ksettings.
+	 * No idea if it's correct or not.
+	 */
+	plat_dat->flags |= STMMAC_FLAG_HAS_INTEGRATED_PCS;
+
+	ret = stmmac_pltfr_probe(pdev, plat_dat, &stmmac_res);
+	if (ret)
+		goto err_remove_config_dt;
+
+	return 0;
+
+err_remove_config_dt:
+	if (pdev->dev.of_node)
+		stmmac_remove_config_dt(pdev, plat_dat);
+
+	return ret;
+}
+
+static const struct of_device_id dwmac_sf19a2890_match[] = {
+	{ .compatible = "siflower,sf19a2890-gmac"},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, dwmac_sf19a2890_match);
+
+static struct platform_driver sf19a2890_gmac_driver = {
+	.probe  = sf19a2890_gmac_probe,
+	.remove_new = stmmac_pltfr_remove,
+	.driver = {
+		.name           = "sf19a2890-gmac",
+		.pm		= &stmmac_pltfr_pm_ops,
+		.of_match_table = dwmac_sf19a2890_match,
+	},
+};
+module_platform_driver(sf19a2890_gmac_driver);
+
+MODULE_DESCRIPTION("SF19A2890 GMAC driver");
+MODULE_LICENSE("GPL");
diff --git a/target/linux/siflower/files-6.6/drivers/phy/siflower/Kconfig b/target/linux/siflower/files-6.6/drivers/phy/siflower/Kconfig
new file mode 100644
index 0000000000..000d1864e9
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/phy/siflower/Kconfig
@@ -0,0 +1,6 @@
+config PHY_SF19A2890_USB
+	tristate "SIFLOWER sf19a2890 USB2.0 PHY driver"
+	default n
+	select GENERIC_PHY
+	help
+	  Enable this to support the USB2.0 PHY on the SIFLOWER SF19A2890.
diff --git a/target/linux/siflower/files-6.6/drivers/phy/siflower/Makefile b/target/linux/siflower/files-6.6/drivers/phy/siflower/Makefile
new file mode 100644
index 0000000000..0c65e8c866
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/phy/siflower/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_PHY_SF19A2890_USB) += phy-sf19a2890-usb.o
+
diff --git a/target/linux/siflower/files-6.6/drivers/phy/siflower/phy-sf19a2890-usb.c b/target/linux/siflower/files-6.6/drivers/phy/siflower/phy-sf19a2890-usb.c
new file mode 100644
index 0000000000..21f65957be
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/phy/siflower/phy-sf19a2890-usb.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define USB_SLEEPM 0x4
+
+struct sf19a2890_usb_phy {
+	struct device *dev;
+	struct clk *phy_clk;
+	struct reset_control *usb_phy_rst;
+	struct reset_control *power_on_rst;
+	void __iomem *base;
+};
+
+static int sf19a2890_usb_phy_power_on(struct phy *phy)
+{
+	struct sf19a2890_usb_phy *p_phy = phy_get_drvdata(phy);
+	int ret;
+
+	ret = clk_prepare_enable(p_phy->phy_clk);
+	if (ret < 0) {
+		dev_err(p_phy->dev, "Failed to enable PHY clock: %d\n", ret);
+		return ret;
+	}
+
+	ret = reset_control_deassert(p_phy->usb_phy_rst);
+	if (ret)
+		goto err1;
+
+	ret = reset_control_deassert(p_phy->power_on_rst);
+	if (ret)
+		goto err2;
+
+	writel(1, p_phy->base + USB_SLEEPM);
+	return 0;
+err2:
+	reset_control_assert(p_phy->usb_phy_rst);
+err1:
+	clk_disable_unprepare(p_phy->phy_clk);
+	return ret;
+}
+
+static int sf19a2890_usb_phy_power_off(struct phy *phy)
+{
+	struct sf19a2890_usb_phy *p_phy = phy_get_drvdata(phy);
+
+	writel(0, p_phy->base + USB_SLEEPM);
+	reset_control_assert(p_phy->power_on_rst);
+	reset_control_assert(p_phy->usb_phy_rst);
+	clk_disable_unprepare(p_phy->phy_clk);
+	return 0;
+}
+
+static const struct phy_ops sf19a2890_usb_phy_ops = {
+	.power_on = sf19a2890_usb_phy_power_on,
+	.power_off = sf19a2890_usb_phy_power_off,
+	.owner = THIS_MODULE,
+};
+
+static int sf19a2890_usb_phy_probe(struct platform_device *pdev)
+{
+	struct sf19a2890_usb_phy *p_phy;
+	struct phy_provider *provider;
+	struct phy *phy;
+	int ret;
+
+	p_phy = devm_kzalloc(&pdev->dev, sizeof(*p_phy), GFP_KERNEL);
+	if (!p_phy)
+		return -ENOMEM;
+
+	p_phy->dev = &pdev->dev;
+
+	p_phy->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(p_phy->base))
+		return PTR_ERR(p_phy->base);
+
+	p_phy->phy_clk = devm_clk_get(p_phy->dev, NULL);
+	if (IS_ERR(p_phy->phy_clk))
+		return dev_err_probe(p_phy->dev, PTR_ERR(p_phy->phy_clk),
+				     "failed to get usb phy clock\n");
+
+	p_phy->power_on_rst =
+		devm_reset_control_get_exclusive(&pdev->dev, "power_on_rst");
+	if (IS_ERR(p_phy->power_on_rst))
+		return PTR_ERR(p_phy->power_on_rst);
+
+	ret = reset_control_assert(p_phy->power_on_rst);
+	if (ret)
+		return ret;
+
+	p_phy->usb_phy_rst =
+		devm_reset_control_get_exclusive(&pdev->dev, "usb_phy_rst");
+	if (IS_ERR(p_phy->usb_phy_rst))
+		return PTR_ERR(p_phy->usb_phy_rst);
+
+	ret = reset_control_assert(p_phy->usb_phy_rst);
+	if (ret)
+		return ret;
+
+	phy = devm_phy_create(p_phy->dev, NULL, &sf19a2890_usb_phy_ops);
+	if (IS_ERR(phy))
+		return dev_err_probe(p_phy->dev, PTR_ERR(phy),
+				     "Failed to create PHY\n");
+
+	phy_set_drvdata(phy, p_phy);
+
+	provider =
+		devm_of_phy_provider_register(p_phy->dev, of_phy_simple_xlate);
+	if (IS_ERR(provider))
+		return dev_err_probe(p_phy->dev, PTR_ERR(provider),
+				     "Failed to register PHY provider\n");
+
+	platform_set_drvdata(pdev, p_phy);
+	return 0;
+}
+
+static const struct of_device_id sf19a2890_usb_phy_of_match[] = {
+	{
+		.compatible = "siflower,sf19a2890-usb-phy",
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, sf19a2890_usb_phy_of_match);
+
+static struct platform_driver sf19a2890_usb_phy_driver = {
+	.probe		= sf19a2890_usb_phy_probe,
+	.driver		= {
+		.name	= "sf19a2890-usb-phy",
+		.of_match_table = sf19a2890_usb_phy_of_match,
+	},
+};
+module_platform_driver(sf19a2890_usb_phy_driver);
+
+MODULE_AUTHOR("Ziying Wu <ziying.wu at siflower.com.cn>");
+MODULE_DESCRIPTION("Siflower SF19A2890 USB2.0 PHY driver");
+MODULE_LICENSE("GPL");
diff --git a/target/linux/siflower/files-6.6/drivers/pinctrl/pinctrl-sf19a2890.c b/target/linux/siflower/files-6.6/drivers/pinctrl/pinctrl-sf19a2890.c
new file mode 100644
index 0000000000..42f8cb9668
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/pinctrl/pinctrl-sf19a2890.c
@@ -0,0 +1,515 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Driver for Siflower SF19A2890 pinctrl.
+ *
+ * Based on:
+ * Driver for Broadcom BCM2835 GPIO unit (pinctrl + GPIO)
+ *
+ * Copyright (C) 2012 Chris Boot, Simon Arlott, Stephen Warren
+ */
+
+#include <linux/bitmap.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define MODULE_NAME "sf19a2890-pinctrl"
+
+struct sf_pinctrl {
+	struct device *dev;
+	void __iomem *base;
+
+	struct pinctrl_dev *pctl_dev;
+	struct pinctrl_desc pctl_desc;
+	struct pinctrl_gpio_range gpio_range;
+};
+
+#define SF19A28_NUM_GPIOS	49
+
+#define SF19A28_REG_PC(pin)	((pin) * 0x8)
+#define  PC_OEN			BIT(7)
+#define  PC_ST			BIT(6)
+#define  PC_IE			BIT(5)
+#define  PC_PD			BIT(4)
+#define  PC_PU			BIT(3)
+#define  PC_DS			GENMASK(2, 0)
+
+#define DRIVE_MIN		6
+#define DRIVE_STEP		3
+#define DRIVE_MAX		(7 * DRIVE_STEP)
+
+#define SF19A28_REG_PMX(pin)	((pin) * 0x8 + 0x4)
+/*
+ * FUNC_SW:
+ *  0: Override pad output enable with PC_OEN
+ *  1: take OEN from GPIO or alternative function
+ * FMUX_SEL:
+ *  0: Alternative function mode
+ *  1: GPIO mode
+ */
+#define  PMX_FUNC_SW		BIT(3)
+#define  PMX_FMUX_SEL		BIT(2)
+#define  PMX_MODE		GENMASK(1, 0)
+
+static struct pinctrl_pin_desc sf19a2890_gpio_pins[] = {
+	PINCTRL_PIN(0, "JTAG_TDO"),
+	PINCTRL_PIN(1, "JTAG_TDI"),
+	PINCTRL_PIN(2, "JTAG_TMS"),
+	PINCTRL_PIN(3, "JTAG_TCK"),
+	PINCTRL_PIN(4, "JTAG_RST"),
+	PINCTRL_PIN(5, "SPI_TXD"),
+	PINCTRL_PIN(6, "SPI_RXD"),
+	PINCTRL_PIN(7, "SPI_CLK"),
+	PINCTRL_PIN(8, "SPI_CSN"),
+	PINCTRL_PIN(9, "UART_TX"),
+	PINCTRL_PIN(10, "UART_RX"),
+	PINCTRL_PIN(11, "I2C_DAT"),
+	PINCTRL_PIN(12, "I2C_CLK"),
+	PINCTRL_PIN(13, "RGMII_GTX_CLK"),
+	PINCTRL_PIN(14, "RGMII_TXCLK"),
+	PINCTRL_PIN(15, "RGMII_TXD0"),
+	PINCTRL_PIN(16, "RGMII_TXD1"),
+	PINCTRL_PIN(17, "RGMII_TXD2"),
+	PINCTRL_PIN(18, "RGMII_TXD3"),
+	PINCTRL_PIN(19, "RGMII_TXCTL"),
+	PINCTRL_PIN(20, "RGMII_RXCLK"),
+	PINCTRL_PIN(21, "RGMII_RXD0"),
+	PINCTRL_PIN(22, "RGMII_RXD1"),
+	PINCTRL_PIN(23, "RGMII_RXD2"),
+	PINCTRL_PIN(24, "RGMII_RXD3"),
+	PINCTRL_PIN(25, "RGMII_RXCTL"),
+	PINCTRL_PIN(26, "RGMII_COL"),
+	PINCTRL_PIN(27, "RGMII_CRS"),
+	PINCTRL_PIN(28, "RGMII_MDC"),
+	PINCTRL_PIN(29, "RGMII_MDIO"),
+	PINCTRL_PIN(30, "HB0_PA_EN"),
+	PINCTRL_PIN(31, "HB0_LNA_EN"),
+	PINCTRL_PIN(32, "HB0_SW_CTRL0"),
+	PINCTRL_PIN(33, "HB0_SW_CTRL1"),
+	PINCTRL_PIN(34, "HB1_PA_EN"),
+	PINCTRL_PIN(35, "HB1_LNA_EN"),
+	PINCTRL_PIN(36, "HB1_SW_CTRL0"),
+	PINCTRL_PIN(37, "HB1_SW_CTRL1"),
+	PINCTRL_PIN(38, "LB0_PA_EN"),
+	PINCTRL_PIN(39, "LB0_LNA_EN"),
+	PINCTRL_PIN(40, "LB0_SW_CTRL0"),
+	PINCTRL_PIN(41, "LB0_SW_CTRL1"),
+	PINCTRL_PIN(42, "LB1_PA_EN"),
+	PINCTRL_PIN(43, "LB1_LNA_EN"),
+	PINCTRL_PIN(44, "LB1_SW_CTRL0"),
+	PINCTRL_PIN(45, "LB1_SW_CTRL1"),
+	PINCTRL_PIN(46, "CLK_OUT"),
+	PINCTRL_PIN(47, "EXT_CLK_IN"),
+	PINCTRL_PIN(48, "DRVVBUS0"),
+};
+
+static const char * const sf19a2890_gpio_groups[] = {
+	"JTAG_TDO",
+	"JTAG_TDI",
+	"JTAG_TMS",
+	"JTAG_TCK",
+	"JTAG_RST",
+	"SPI_TXD",
+	"SPI_RXD",
+	"SPI_CLK",
+	"SPI_CSN",
+	"UART_TX",
+	"UART_RX",
+	"I2C_DAT",
+	"I2C_CLK",
+	"RGMII_GTX_CLK",
+	"RGMII_TXCLK",
+	"RGMII_TXD0",
+	"RGMII_TXD1",
+	"RGMII_TXD2",
+	"RGMII_TXD3",
+	"RGMII_TXCTL",
+	"RGMII_RXCLK",
+	"RGMII_RXD0",
+	"RGMII_RXD1",
+	"RGMII_RXD2",
+	"RGMII_RXD3",
+	"RGMII_RXCTL",
+	"RGMII_COL",
+	"RGMII_CRS",
+	"RGMII_MDC",
+	"RGMII_MDIO",
+	"HB0_PA_EN",
+	"HB0_LNA_EN",
+	"HB0_SW_CTRL0",
+	"HB0_SW_CTRL1",
+	"HB1_PA_EN",
+	"HB1_LNA_EN",
+	"HB1_SW_CTRL0",
+	"HB1_SW_CTRL1",
+	"LB0_PA_EN",
+	"LB0_LNA_EN",
+	"LB0_SW_CTRL0",
+	"LB0_SW_CTRL1",
+	"LB1_PA_EN",
+	"LB1_LNA_EN",
+	"LB1_SW_CTRL0",
+	"LB1_SW_CTRL1",
+	"CLK_OUT",
+	"EXT_CLK_IN",
+	"DRVVBUS0",
+};
+
+#define SF19A28_FUNC0		0
+#define SF19A28_FUNC1		1
+#define SF19A28_FUNC2		2
+#define SF19A28_FUNC3		3
+#define SF19A28_NUM_FUNCS	4
+
+static const char * const sf19a2890_functions[] = {
+	"func0", "func1", "func2", "func3"
+};
+
+static inline u32 sf_pinctrl_rd(struct sf_pinctrl *pc, ulong reg)
+{
+	return readl(pc->base + reg);
+}
+
+static inline void sf_pinctrl_wr(struct sf_pinctrl *pc, ulong reg, u32 val)
+{
+	writel(val, pc->base + reg);
+}
+
+static inline void sf_pinctrl_rmw(struct sf_pinctrl *pc, ulong reg, u32 clr,
+				  u32 set)
+{
+	u32 val;
+
+	val = sf_pinctrl_rd(pc, reg);
+	val &= ~clr;
+	val |= set;
+	sf_pinctrl_wr(pc, reg, val);
+}
+
+static int sf19a2890_pctl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return SF19A28_NUM_GPIOS;
+}
+
+static const char *sf19a2890_pctl_get_group_name(struct pinctrl_dev *pctldev,
+						 unsigned selector)
+{
+	return sf19a2890_gpio_groups[selector];
+}
+
+static int sf19a2890_pctl_get_group_pins(struct pinctrl_dev *pctldev,
+					 unsigned selector,
+					 const unsigned **pins,
+					 unsigned *num_pins)
+{
+	*pins = &sf19a2890_gpio_pins[selector].number;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static void sf19a2890_pctl_pin_dbg_show(struct pinctrl_dev *pctldev,
+					struct seq_file *s, unsigned offset)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	u32 conf = sf_pinctrl_rd(pc, SF19A28_REG_PC(offset));
+	u32 mux = sf_pinctrl_rd(pc, SF19A28_REG_PMX(offset));
+
+	if (!(mux & PMX_FUNC_SW))
+		seq_puts(s, "Forced OE");
+	else if (mux & PMX_FMUX_SEL)
+		seq_puts(s, "GPIO");
+	else
+		seq_printf(s, "Func%lu", mux & PMX_MODE);
+	seq_puts(s, " |");
+
+	if (!(conf & PC_OEN) && !(mux & PMX_FUNC_SW))
+		seq_puts(s, " Output");
+	if ((conf & PC_ST))
+		seq_puts(s, " Schmitt_Trigger");
+	if ((conf & PC_IE))
+		seq_puts(s, " Input");
+	if ((conf & PC_PD))
+		seq_puts(s, " Pull_Down");
+	if ((conf & PC_PU))
+		seq_puts(s, " Pull_Up");
+
+	seq_printf(s, " Drive: %lu mA",
+		   DRIVE_MIN + (conf & PC_DS) * DRIVE_STEP);
+}
+
+static const struct pinctrl_ops sf19a2890_pctl_ops = {
+	.get_groups_count = sf19a2890_pctl_get_groups_count,
+	.get_group_name = sf19a2890_pctl_get_group_name,
+	.get_group_pins = sf19a2890_pctl_get_group_pins,
+	.pin_dbg_show = sf19a2890_pctl_pin_dbg_show,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int sf19a2890_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	sf_pinctrl_rmw(pc, SF19A28_REG_PC(offset), PC_IE, PC_OEN);
+	sf_pinctrl_rmw(pc, SF19A28_REG_PMX(offset), PMX_FUNC_SW, 0);
+	return 0;
+}
+
+static int sf19a2890_pmx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+	return SF19A28_NUM_FUNCS;
+}
+
+static const char *sf19a2890_pmx_get_function_name(struct pinctrl_dev *pctldev,
+						   unsigned selector)
+{
+	return sf19a2890_functions[selector];
+}
+
+static int sf19a2890_pmx_get_function_groups(struct pinctrl_dev *pctldev,
+					     unsigned selector,
+					     const char *const **groups,
+					     unsigned *const num_groups)
+{
+	/* every pin can do every function */
+	*groups = sf19a2890_gpio_groups;
+	*num_groups = SF19A28_NUM_GPIOS;
+
+	return 0;
+}
+
+static int sf19a2890_pmx_set(struct pinctrl_dev *pctldev,
+			     unsigned func_selector, unsigned group_selector)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	unsigned pin = group_selector;
+
+	sf_pinctrl_wr(pc, SF19A28_REG_PMX(pin),
+		      PMX_FUNC_SW | FIELD_PREP(PMX_MODE, func_selector));
+	return 0;
+}
+
+static int sf19a2890_pmx_gpio_request_enable(struct pinctrl_dev *pctldev,
+					     struct pinctrl_gpio_range *range,
+					     unsigned offset)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	/* Set to GPIO mode & Let peripheral control OEN */
+	sf_pinctrl_wr(pc, SF19A28_REG_PMX(offset), PMX_FUNC_SW | PMX_FMUX_SEL);
+	/*
+	 * Set PC_IE regardless of whether GPIO is in input mode.
+	 * Otherwise GPIO driver can't read back its status in output mode.
+	 */
+	sf_pinctrl_rmw(pc, SF19A28_REG_PC(offset), 0, PC_IE);
+	return 0;
+}
+
+static void sf19a2890_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
+					    struct pinctrl_gpio_range *range,
+					    unsigned offset)
+{
+	sf19a2890_pmx_free(pctldev, offset);
+}
+
+static const struct pinmux_ops sf19a2890_pmx_ops = {
+	.free = sf19a2890_pmx_free,
+	.get_functions_count = sf19a2890_pmx_get_functions_count,
+	.get_function_name = sf19a2890_pmx_get_function_name,
+	.get_function_groups = sf19a2890_pmx_get_function_groups,
+	.set_mux = sf19a2890_pmx_set,
+	.gpio_request_enable = sf19a2890_pmx_gpio_request_enable,
+	.gpio_disable_free = sf19a2890_pmx_gpio_disable_free,
+};
+
+static int sf19a2890_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+				 unsigned long *config)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param = pinconf_to_config_param(*config);
+	u32 arg = 0;
+	u32 val = 0;
+
+	if (pin >= SF19A28_NUM_GPIOS)
+		return -EINVAL;
+
+	val = sf_pinctrl_rd(pc, SF19A28_REG_PC(pin));
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_SCHMITT:
+		val &= PC_ST;
+		if (val)
+			arg = 1;
+		break;
+
+	case PIN_CONFIG_INPUT_ENABLE:
+		val &= PC_IE;
+		if (val)
+			arg = 1;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		val &= PC_PD;
+		if (val)
+			arg = 1;
+		break;
+
+	case PIN_CONFIG_BIAS_PULL_UP:
+		val &= PC_PU;
+		if (val)
+			arg = 1;
+		break;
+
+	case PIN_CONFIG_DRIVE_STRENGTH:
+		arg = DRIVE_MIN + (val & PC_DS) * DRIVE_STEP;
+		break;
+
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+	return 0;
+}
+
+static int sf19a2890_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+				 unsigned long *configs, unsigned num_configs)
+{
+	struct sf_pinctrl *pc = pinctrl_dev_get_drvdata(pctldev);
+	enum pin_config_param param;
+	u32 arg, val;
+	int i;
+
+	val = sf_pinctrl_rd(pc, SF19A28_REG_PC(pin));
+
+	if (pin >= SF19A28_NUM_GPIOS)
+		return -EINVAL;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+		switch (param) {
+		case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
+			if (arg)
+				val |= PC_ST;
+			else
+				val &= ~PC_ST;
+			break;
+
+		case PIN_CONFIG_INPUT_ENABLE:
+			if (arg)
+				val |= PC_IE;
+			else
+				val &= ~PC_IE;
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_DOWN:
+			if (arg) {
+				val |= PC_PD;
+				val &= ~PC_PU;
+			} else {
+				val &= ~PC_PD;
+			}
+			break;
+
+		case PIN_CONFIG_BIAS_PULL_UP:
+			if (arg) {
+				val |= PC_PU;
+				val &= ~PC_PD;
+			} else {
+				val &= ~PC_PU;
+			}
+			break;
+
+		case PIN_CONFIG_DRIVE_STRENGTH:
+			val &= ~PC_DS;
+			if (arg > DRIVE_MAX)
+				val |= PC_DS;
+			else if (arg > DRIVE_MIN)
+				val |= FIELD_PREP(PC_DS, (arg - DRIVE_MIN) /
+								 DRIVE_STEP);
+			break;
+		default:
+			break;
+		}
+		sf_pinctrl_wr(pc, SF19A28_REG_PC(pin), val);
+	}
+	return 0;
+}
+
+static const struct pinconf_ops sf19a2890_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = sf19a2890_pinconf_get,
+	.pin_config_set = sf19a2890_pinconf_set,
+};
+
+static const struct pinctrl_desc sf19a2890_pinctrl_desc = {
+	.name = MODULE_NAME,
+	.pins = sf19a2890_gpio_pins,
+	.npins = SF19A28_NUM_GPIOS,
+	.pctlops = &sf19a2890_pctl_ops,
+	.pmxops = &sf19a2890_pmx_ops,
+	.confops = &sf19a2890_pinconf_ops,
+	.owner = THIS_MODULE,
+};
+
+static const struct pinctrl_gpio_range sf_pinctrl_gpio_range = {
+	.name = MODULE_NAME,
+	.npins = SF19A28_NUM_GPIOS,
+};
+
+static const struct of_device_id sf_pinctrl_match[] = {
+	{ .compatible = "siflower,sf19a2890-pinctrl" },
+	{}
+};
+
+static int sf_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct sf_pinctrl *pc;
+
+	pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, pc);
+	pc->dev = dev;
+
+	pc->base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(pc->base))
+		return PTR_ERR(pc->base);
+
+	pc->pctl_desc = sf19a2890_pinctrl_desc;
+	pc->pctl_dev = devm_pinctrl_register(dev, &pc->pctl_desc, pc);
+	if (IS_ERR(pc->pctl_dev))
+		return PTR_ERR(pc->pctl_dev);
+
+	return 0;
+}
+
+static struct platform_driver sf_pinctrl_driver = {
+	.probe = sf_pinctrl_probe,
+	.driver = {
+		.name = MODULE_NAME,
+		.of_match_table = sf_pinctrl_match,
+		.suppress_bind_attrs = true,
+	},
+};
+module_platform_driver(sf_pinctrl_driver);
+
+MODULE_AUTHOR("Chuanhong Guo <gch981213 at gmail.com>");
+MODULE_DESCRIPTION("Siflower SF19A2890 pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/target/linux/siflower/files-6.6/drivers/reset/reset-sf19a2890-periph.c b/target/linux/siflower/files-6.6/drivers/reset/reset-sf19a2890-periph.c
new file mode 100644
index 0000000000..21874da517
--- /dev/null
+++ b/target/linux/siflower/files-6.6/drivers/reset/reset-sf19a2890-periph.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/spinlock.h>
+
+struct reset_sf19a28_periph_data {
+	struct reset_controller_dev rcdev;
+	void __iomem *base;
+	spinlock_t lock;
+	u32 reset_masks[];
+};
+
+static inline struct reset_sf19a28_periph_data *
+to_reset_sf19a28_periph_data(struct reset_controller_dev *rcdev)
+{
+	return container_of(rcdev, struct reset_sf19a28_periph_data, rcdev);
+}
+
+static int reset_sf19a28_periph_update(struct reset_controller_dev *rcdev,
+			       unsigned long id, bool assert)
+{
+	struct reset_sf19a28_periph_data *data = to_reset_sf19a28_periph_data(rcdev);
+	unsigned long flags;
+	u32 reg;
+
+	spin_lock_irqsave(&data->lock, flags);
+	reg = readl(data->base);
+	if (assert)
+		reg |= data->reset_masks[id];
+	else
+		reg &= ~data->reset_masks[id];
+	writel(reg, data->base);
+	spin_unlock_irqrestore(&data->lock, flags);
+	return 0;
+}
+
+static int reset_sf19a28_periph_assert(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	return reset_sf19a28_periph_update(rcdev, id, true);
+}
+
+static int reset_sf19a28_periph_deassert(struct reset_controller_dev *rcdev,
+				 unsigned long id)
+{
+	return reset_sf19a28_periph_update(rcdev, id, false);
+}
+
+static int reset_sf19a28_periph_status(struct reset_controller_dev *rcdev,
+			       unsigned long id)
+{
+	struct reset_sf19a28_periph_data *data = to_reset_sf19a28_periph_data(rcdev);
+	u32 reg;
+
+	reg = readl(data->base);
+	return !!(reg & data->reset_masks[id]);
+}
+
+const struct reset_control_ops reset_sf19a28_periph_ops = {
+	.assert		= reset_sf19a28_periph_assert,
+	.deassert	= reset_sf19a28_periph_deassert,
+	.status		= reset_sf19a28_periph_status,
+};
+
+static const struct of_device_id reset_sf19a28_periph_dt_ids[] = {
+	{ .compatible = "siflower,sf19a2890-periph-reset", },
+	{ /* sentinel */ },
+};
+
+static int reset_sf19a28_periph_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *node = dev->of_node;
+	struct reset_sf19a28_periph_data *data;
+	void __iomem *base;
+	int nr_resets;
+	int ret, i;
+	u32 tmp;
+
+	nr_resets = of_property_count_u32_elems(node, "siflower,reset-masks");
+
+	if (nr_resets < 1) {
+		ret = of_property_read_u32(node, "siflower,num-resets", &tmp);
+		if (ret < 0 || tmp < 1)
+			return -EINVAL;
+		nr_resets = tmp;
+	}
+
+	if (nr_resets >= 32) {
+		dev_err(dev, "too many resets.");
+		return -EINVAL;
+	}
+
+	data = devm_kzalloc(dev, struct_size(data, reset_masks, nr_resets), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(node, "siflower,reset-masks",
+					 data->reset_masks, nr_resets);
+	if (ret)
+		for (i = 0; i < nr_resets; i++)
+			data->reset_masks[i] = BIT(i);
+
+	base = devm_platform_ioremap_resource(pdev, 0);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	spin_lock_init(&data->lock);
+	data->base = base;
+	data->rcdev.owner = THIS_MODULE;
+	data->rcdev.nr_resets = nr_resets;
+	data->rcdev.ops = &reset_sf19a28_periph_ops;
+	data->rcdev.of_node = dev->of_node;
+
+	return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static struct platform_driver reset_sf19a28_periph_driver = {
+	.probe	= reset_sf19a28_periph_probe,
+	.driver = {
+		.name		= "reset-sf19a2890-periph",
+		.of_match_table	= reset_sf19a28_periph_dt_ids,
+	},
+};
+builtin_platform_driver(reset_sf19a28_periph_driver);
diff --git a/target/linux/siflower/files-6.6/include/dt-bindings/clock/siflower,sf19a2890-clk.h b/target/linux/siflower/files-6.6/include/dt-bindings/clock/siflower,sf19a2890-clk.h
new file mode 100644
index 0000000000..06bf0b007e
--- /dev/null
+++ b/target/linux/siflower/files-6.6/include/dt-bindings/clock/siflower,sf19a2890-clk.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
+#ifndef __DT_BINDINGS_CLOCK_SIFLOWER_SF19A2890_CLK_H
+#define __DT_BINDINGS_CLOCK_SIFLOWER_SF19A2890_CLK_H
+#define CLK_PLL_CPU		0
+#define CLK_PLL_DDR		1
+#define CLK_PLL_CMN		2
+#define CLK_MUXDIV_BUS1		3
+#define CLK_MUXDIV_BUS2		4
+#define CLK_MUXDIV_BUS3		5
+#define CLK_MUXDIV_CPU		6
+#define CLK_MUXDIV_PBUS		7
+#define CLK_MUXDIV_MEM_PHY	8
+#define CLK_MUXDIV_UART		9
+#define CLK_MUXDIV_ETH_REF	10
+#define CLK_MUXDIV_ETH_BYP_REF	11
+#define CLK_MUXDIV_ETH_TSU	12
+#define CLK_MUXDIV_GMAC_BYP_REF	13
+#define CLK_MUXDIV_M6250_0	14
+#define CLK_MUXDIV_M6250_1	15
+#define CLK_MUXDIV_WLAN24_PLF	16
+#define CLK_MUXDIV_WLAN5_PLF	17
+#define CLK_MUXDIV_USBPHY_REF	18
+#define CLK_MUXDIV_TCLK		19
+#define CLK_MUXDIV_NPU_PE_CLK	20
+
+#define CLK_SF19A2890_MAX	21
+#endif /* __DT_BINDINGS_CLOCK_SIFLOWER_SF19A2890_CLK_H */
diff --git a/target/linux/siflower/image/Makefile b/target/linux/siflower/image/Makefile
new file mode 100644
index 0000000000..e86927dd78
--- /dev/null
+++ b/target/linux/siflower/image/Makefile
@@ -0,0 +1,28 @@
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/image.mk
+
+KERNEL_LOADADDR := 0x80100000
+
+define Device/Default
+  PROFILES := Default
+  BLOCKSIZE := 64k
+  FILESYSTEMS := squashfs
+  DEVICE_DTS_DIR := ../dts
+  KERNEL := kernel-bin | append-dtb | lzma | uImage lzma
+  KERNEL_INITRAMFS := kernel-bin | append-dtb | lzma | uImage lzma
+  IMAGES := sysupgrade.bin
+  IMAGE/sysupgrade.bin = append-kernel | pad-to $$$$(BLOCKSIZE) | \
+	append-rootfs | pad-rootfs | append-metadata
+endef
+
+define Device/siflower_sf19a2890-evb
+  DEVICE_VENDOR := Siflower
+  DEVICE_MODEL := SF19A2890 EVB
+  BOARD_NAME := siflower,sf19a2890-evb
+  DEVICE_DTS := sf19a2890_evb
+  DEVICE_PACKAGES := kmod-switch-rtl8367b swconfig
+endef
+TARGET_DEVICES += siflower_sf19a2890-evb
+
+$(eval $(call BuildImage))
diff --git a/target/linux/siflower/modules.mk b/target/linux/siflower/modules.mk
new file mode 100644
index 0000000000..e8aaf768e4
--- /dev/null
+++ b/target/linux/siflower/modules.mk
@@ -0,0 +1,15 @@
+define KernelPackage/phy-sf19a2890-usb
+  TITLE:=Siflower SF19A2890 USB 2.0 PHY Driver
+  KCONFIG:=CONFIG_PHY_SF19A2890_USB
+  DEPENDS:=@TARGET_siflower_sf19a2890
+  SUBMENU:=$(USB_MENU)
+  FILES:=$(LINUX_DIR)/drivers/phy/siflower/phy-sf19a2890-usb.ko
+  AUTOLOAD:=$(call AutoLoad,45,phy-sf19a2890-usb,1)
+endef
+
+define KernelPackage/phy-sf19a2890-usb/description
+  Support for Siflower SF19A2890 USB 2.0 PHY connected to the USB
+  controller.
+endef
+
+$(eval $(call KernelPackage,phy-sf19a2890-usb))
diff --git a/target/linux/siflower/patches-6.6/001-mips-add-support-for-Siflower-SF19A2890.patch b/target/linux/siflower/patches-6.6/001-mips-add-support-for-Siflower-SF19A2890.patch
new file mode 100644
index 0000000000..69bd0b83d7
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/001-mips-add-support-for-Siflower-SF19A2890.patch
@@ -0,0 +1,59 @@
+From c2ec4604afb39904c01dfe38ca8289c446b898bb Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:32:17 +0800
+Subject: [PATCH 1/9] mips: add support for Siflower SF19A2890
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ arch/mips/Kconfig          | 29 +++++++++++++++++++++++++++++
+ arch/mips/generic/Platform |  1 +
+ 2 files changed, 30 insertions(+)
+
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -861,6 +861,35 @@ config SIBYTE_BIGSUR
+ 	select ZONE_DMA32 if 64BIT
+ 	select SWIOTLB if ARCH_DMA_ADDR_T_64BIT && PCI
+ 
++config MACH_SIFLOWER_MIPS
++	bool "Siflower MIPS SoCs"
++	select MIPS_GENERIC
++	select ARM_AMBA
++	select BOOT_RAW
++	select CEVT_R4K
++	select CLKSRC_MIPS_GIC
++	select COMMON_CLK
++	select CPU_MIPSR2_IRQ_EI
++	select CPU_MIPSR2_IRQ_VI
++	select CSRC_R4K
++	select DMA_NONCOHERENT
++	select IRQ_MIPS_CPU
++	select MIPS_CPU_SCACHE
++	select MIPS_GIC
++	select MIPS_L1_CACHE_SHIFT_5
++	select NO_EXCEPT_FILL
++	select SMP_UP if SMP
++	select SYS_HAS_CPU_MIPS32_R2
++	select SYS_SUPPORTS_32BIT_KERNEL
++	select SYS_SUPPORTS_LITTLE_ENDIAN
++	select SYS_SUPPORTS_MIPS16
++	select SYS_SUPPORTS_MIPS_CPS
++	select SYS_SUPPORTS_MULTITHREADING
++	select USE_OF
++	help
++	  Select this to build a kernel which supports SoCs from Siflower
++	  with MIPS InterAptiv cores, like Siflower SF19A2890.
++
+ config SNI_RM
+ 	bool "SNI RM200/300/400"
+ 	select ARC_MEMORY
+--- a/arch/mips/generic/Platform
++++ b/arch/mips/generic/Platform
+@@ -10,6 +10,7 @@
+ 
+ # Note: order matters, keep the asm/mach-generic include last.
+ cflags-$(CONFIG_MACH_INGENIC_SOC)	+= -I$(srctree)/arch/mips/include/asm/mach-ingenic
++cflags-$(CONFIG_MACH_SIFLOWER_MIPS)	+= -I$(srctree)/arch/mips/include/asm/mach-siflower
+ cflags-$(CONFIG_MIPS_GENERIC)	+= -I$(srctree)/arch/mips/include/asm/mach-generic
+ 
+ load-$(CONFIG_MIPS_GENERIC)	+= 0xffffffff80100000
diff --git a/target/linux/siflower/patches-6.6/002-clk-add-drivers-for-sf19a2890.patch b/target/linux/siflower/patches-6.6/002-clk-add-drivers-for-sf19a2890.patch
new file mode 100644
index 0000000000..620e432a49
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/002-clk-add-drivers-for-sf19a2890.patch
@@ -0,0 +1,31 @@
+From fcb96cb774abf14375326c41cedd237d6c8f6e94 Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:33:01 +0800
+Subject: [PATCH 2/9] clk: add drivers for sf19a2890
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ drivers/clk/Kconfig  | 1 +
+ drivers/clk/Makefile | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/clk/Kconfig
++++ b/drivers/clk/Kconfig
+@@ -489,6 +489,7 @@ source "drivers/clk/renesas/Kconfig"
+ source "drivers/clk/rockchip/Kconfig"
+ source "drivers/clk/samsung/Kconfig"
+ source "drivers/clk/sifive/Kconfig"
++source "drivers/clk/siflower/Kconfig"
+ source "drivers/clk/socfpga/Kconfig"
+ source "drivers/clk/sprd/Kconfig"
+ source "drivers/clk/starfive/Kconfig"
+--- a/drivers/clk/Makefile
++++ b/drivers/clk/Makefile
+@@ -116,6 +116,7 @@ obj-y					+= renesas/
+ obj-$(CONFIG_ARCH_ROCKCHIP)		+= rockchip/
+ obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
+ obj-$(CONFIG_CLK_SIFIVE)		+= sifive/
++obj-$(CONFIG_CLK_SIFLOWER)		+= siflower/
+ obj-y					+= socfpga/
+ obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+ obj-y					+= sprd/
diff --git a/target/linux/siflower/patches-6.6/003-reset-add-support-for-sf19a2890.patch b/target/linux/siflower/patches-6.6/003-reset-add-support-for-sf19a2890.patch
new file mode 100644
index 0000000000..52992ac5dd
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/003-reset-add-support-for-sf19a2890.patch
@@ -0,0 +1,38 @@
+From 819d2a48d45f3734c876186e651917bae69be9ba Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:33:43 +0800
+Subject: [PATCH 3/9] reset: add support for sf19a2890
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ drivers/reset/Kconfig  | 8 ++++++++
+ drivers/reset/Makefile | 1 +
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/reset/Kconfig
++++ b/drivers/reset/Kconfig
+@@ -211,6 +211,14 @@ config RESET_SCMI
+ 	  This driver uses SCMI Message Protocol to interact with the
+ 	  firmware controlling all the reset signals.
+ 
++config RESET_SF19A2890_PERIPH
++	bool "Siflower SF19A2890 Peripheral Reset Controller Driver"
++	default MACH_SIFLOWER_MIPS
++	depends on HAS_IOMEM
++	help
++	  This enables reset controller driver for peripheral reset blocks
++	  found on Siflower SF19A2890 SoC.
++
+ config RESET_SIMPLE
+ 	bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
+ 	default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
+--- a/drivers/reset/Makefile
++++ b/drivers/reset/Makefile
+@@ -29,6 +29,7 @@ obj-$(CONFIG_RESET_QCOM_PDC) += reset-qc
+ obj-$(CONFIG_RESET_RASPBERRYPI) += reset-raspberrypi.o
+ obj-$(CONFIG_RESET_RZG2L_USBPHY_CTRL) += reset-rzg2l-usbphy-ctrl.o
+ obj-$(CONFIG_RESET_SCMI) += reset-scmi.o
++obj-$(CONFIG_RESET_SF19A2890_PERIPH) += reset-sf19a2890-periph.o
+ obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
+ obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
+ obj-$(CONFIG_RESET_SUNPLUS) += reset-sunplus.o
diff --git a/target/linux/siflower/patches-6.6/004-gpio-add-support-for-siflower-socs.patch b/target/linux/siflower/patches-6.6/004-gpio-add-support-for-siflower-socs.patch
new file mode 100644
index 0000000000..c381b86e14
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/004-gpio-add-support-for-siflower-socs.patch
@@ -0,0 +1,37 @@
+From 1d37455eacb1d0c262ae6aaecadf27964cbf97d8 Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:33:57 +0800
+Subject: [PATCH 4/9] gpio: add support for siflower socs
+
+---
+ drivers/gpio/Kconfig  | 8 ++++++++
+ drivers/gpio/Makefile | 1 +
+ 2 files changed, 9 insertions(+)
+
+--- a/drivers/gpio/Kconfig
++++ b/drivers/gpio/Kconfig
+@@ -576,6 +576,14 @@ config GPIO_SIFIVE
+ 	help
+ 	  Say yes here to support the GPIO device on SiFive SoCs.
+ 
++config GPIO_SIFLOWER
++	tristate "SiFlower GPIO support"
++	depends on OF_GPIO
++	depends on MACH_SIFLOWER_MIPS || COMPILE_TEST
++	select GPIOLIB_IRQCHIP
++	help
++	  GPIO controller driver for SiFlower SoCs.
++
+ config GPIO_SIOX
+ 	tristate "SIOX GPIO support"
+ 	depends on SIOX
+--- a/drivers/gpio/Makefile
++++ b/drivers/gpio/Makefile
+@@ -143,6 +143,7 @@ obj-$(CONFIG_GPIO_SAMA5D2_PIOBU)	+= gpio
+ obj-$(CONFIG_GPIO_SCH311X)		+= gpio-sch311x.o
+ obj-$(CONFIG_GPIO_SCH)			+= gpio-sch.o
+ obj-$(CONFIG_GPIO_SIFIVE)		+= gpio-sifive.o
++obj-$(CONFIG_GPIO_SIFLOWER)		+= gpio-siflower.o
+ obj-$(CONFIG_GPIO_SIM)			+= gpio-sim.o
+ obj-$(CONFIG_GPIO_SIOX)			+= gpio-siox.o
+ obj-$(CONFIG_GPIO_SL28CPLD)		+= gpio-sl28cpld.o
diff --git a/target/linux/siflower/patches-6.6/005-pinctrl-add-driver-for-siflower-sf19a2890.patch b/target/linux/siflower/patches-6.6/005-pinctrl-add-driver-for-siflower-sf19a2890.patch
new file mode 100644
index 0000000000..e9026476d3
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/005-pinctrl-add-driver-for-siflower-sf19a2890.patch
@@ -0,0 +1,39 @@
+From 59c6a4972b584d986f72fe8d7c55930fdf799bc8 Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:34:20 +0800
+Subject: [PATCH 5/9] pinctrl: add driver for siflower sf19a2890
+
+---
+ drivers/pinctrl/Kconfig  | 10 ++++++++++
+ drivers/pinctrl/Makefile |  1 +
+ 2 files changed, 11 insertions(+)
+
+--- a/drivers/pinctrl/Kconfig
++++ b/drivers/pinctrl/Kconfig
+@@ -417,6 +417,16 @@ config PINCTRL_ROCKCHIP
+ 	help
+           This support pinctrl and GPIO driver for Rockchip SoCs.
+ 
++config PINCTRL_SF19A2890
++	tristate "Siflower SF19A2890 pinctrl driver"
++	depends on OF && (MACH_SIFLOWER_MIPS || COMPILE_TEST)
++	select PINMUX
++	select PINCONF
++	select GENERIC_PINCONF
++	default MACH_SIFLOWER_MIPS
++	help
++	   Say Y here to enable the Siflower SF19A2890 pinctrl driver.
++
+ config PINCTRL_SINGLE
+ 	tristate "One-register-per-pin type device tree based pinctrl driver"
+ 	depends on OF
+--- a/drivers/pinctrl/Makefile
++++ b/drivers/pinctrl/Makefile
+@@ -43,6 +43,7 @@ obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl-p
+ obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
+ obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
+ obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
++obj-$(CONFIG_PINCTRL_SF19A2890)	+= pinctrl-sf19a2890.o
+ obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
+ obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
+ obj-$(CONFIG_PINCTRL_STMFX) 	+= pinctrl-stmfx.o
diff --git a/target/linux/siflower/patches-6.6/006-stmmac-add-support-for-sf19a2890.patch b/target/linux/siflower/patches-6.6/006-stmmac-add-support-for-sf19a2890.patch
new file mode 100644
index 0000000000..b65cd3ed04
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/006-stmmac-add-support-for-sf19a2890.patch
@@ -0,0 +1,38 @@
+From baa6c00f7a88b28f6838a9743f66c9f7f4716e25 Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 20 Aug 2024 08:34:42 +0800
+Subject: [PATCH 6/9] stmmac: add support for sf19a2890
+
+---
+ drivers/net/ethernet/stmicro/stmmac/Kconfig  | 9 +++++++++
+ drivers/net/ethernet/stmicro/stmmac/Makefile | 1 +
+ 2 files changed, 10 insertions(+)
+
+--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
++++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
+@@ -142,6 +142,15 @@ config DWMAC_ROCKCHIP
+ 	  This selects the Rockchip RK3288 SoC glue layer support for
+ 	  the stmmac device driver.
+ 
++config DWMAC_SF19A2890
++	tristate "Siflower SF19A2890 GMAC support"
++	default MACH_SIFLOWER_MIPS
++	help
++	  Support for GMAC on Siflower SF19A2890 SoC.
++
++	  This selects the Siflower SF19A2890 SoC glue layer support for
++	  the stmmac device driver.
++
+ config DWMAC_SOCFPGA
+ 	tristate "SOCFPGA dwmac support"
+ 	default ARCH_INTEL_SOCFPGA
+--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
++++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
+@@ -21,6 +21,7 @@ obj-$(CONFIG_DWMAC_MEDIATEK)	+= dwmac-me
+ obj-$(CONFIG_DWMAC_MESON)	+= dwmac-meson.o dwmac-meson8b.o
+ obj-$(CONFIG_DWMAC_QCOM_ETHQOS)	+= dwmac-qcom-ethqos.o
+ obj-$(CONFIG_DWMAC_ROCKCHIP)	+= dwmac-rk.o
++obj-$(CONFIG_DWMAC_SF19A2890)	+= dwmac-sf19a2890.o
+ obj-$(CONFIG_DWMAC_SOCFPGA)	+= dwmac-altr-socfpga.o
+ obj-$(CONFIG_DWMAC_STARFIVE)	+= dwmac-starfive.o
+ obj-$(CONFIG_DWMAC_STI)		+= dwmac-sti.o
diff --git a/target/linux/siflower/patches-6.6/007-phy-add-support-for-SF19A2890-USB-PHY.patch b/target/linux/siflower/patches-6.6/007-phy-add-support-for-SF19A2890-USB-PHY.patch
new file mode 100644
index 0000000000..97b7126e02
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/007-phy-add-support-for-SF19A2890-USB-PHY.patch
@@ -0,0 +1,31 @@
+From 68817a14ae9dff587cee8515e68c67cba89b39ab Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Mon, 9 Sep 2024 10:18:33 +0800
+Subject: [PATCH 7/9] phy: add support for SF19A2890 USB PHY
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ drivers/phy/Kconfig  | 1 +
+ drivers/phy/Makefile | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/phy/Kconfig
++++ b/drivers/phy/Kconfig
+@@ -90,6 +90,7 @@ source "drivers/phy/ralink/Kconfig"
+ source "drivers/phy/renesas/Kconfig"
+ source "drivers/phy/rockchip/Kconfig"
+ source "drivers/phy/samsung/Kconfig"
++source "drivers/phy/siflower/Kconfig"
+ source "drivers/phy/socionext/Kconfig"
+ source "drivers/phy/st/Kconfig"
+ source "drivers/phy/starfive/Kconfig"
+--- a/drivers/phy/Makefile
++++ b/drivers/phy/Makefile
+@@ -29,6 +29,7 @@ obj-y					+= allwinner/	\
+ 					   renesas/	\
+ 					   rockchip/	\
+ 					   samsung/	\
++					   siflower/	\
+ 					   socionext/	\
+ 					   st/		\
+ 					   starfive/	\
diff --git a/target/linux/siflower/patches-6.6/008-usb-dwc2-add-support-for-Siflower-SF19A2890.patch b/target/linux/siflower/patches-6.6/008-usb-dwc2-add-support-for-Siflower-SF19A2890.patch
new file mode 100644
index 0000000000..b551e4f2ca
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/008-usb-dwc2-add-support-for-Siflower-SF19A2890.patch
@@ -0,0 +1,36 @@
+From 29282086f215ae723e6d2c139d23094e699ba5bb Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Mon, 9 Sep 2024 16:46:53 +0800
+Subject: [PATCH 8/9] usb: dwc2: add support for Siflower SF19A2890
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ drivers/usb/dwc2/params.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/usb/dwc2/params.c
++++ b/drivers/usb/dwc2/params.c
+@@ -200,6 +200,14 @@ static void dwc2_set_amcc_params(struct
+ 	p->ahbcfg = GAHBCFG_HBSTLEN_INCR16 << GAHBCFG_HBSTLEN_SHIFT;
+ }
+ 
++static void dwc2_set_sf19a2890_params(struct dwc2_hsotg *hsotg)
++{
++	struct dwc2_core_params *p = &hsotg->params;
++
++	p->max_transfer_size = 65535;
++	p->ahbcfg = GAHBCFG_HBSTLEN_INCR4 << GAHBCFG_HBSTLEN_SHIFT;
++}
++
+ static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg)
+ {
+ 	struct dwc2_core_params *p = &hsotg->params;
+@@ -294,6 +302,8 @@ const struct of_device_id dwc2_of_match_
+ 	  .data = dwc2_set_amlogic_a1_params },
+ 	{ .compatible = "amcc,dwc-otg", .data = dwc2_set_amcc_params },
+ 	{ .compatible = "apm,apm82181-dwc-otg", .data = dwc2_set_amcc_params },
++	{ .compatible = "siflower,sf19a2890-usb",
++	  .data = dwc2_set_sf19a2890_params },
+ 	{ .compatible = "st,stm32f4x9-fsotg",
+ 	  .data = dwc2_set_stm32f4x9_fsotg_params },
+ 	{ .compatible = "st,stm32f4x9-hsotg" },
diff --git a/target/linux/siflower/patches-6.6/009-usb-dwc2-handle-OTG-interrupt-regardless-of-GINTSTS.patch b/target/linux/siflower/patches-6.6/009-usb-dwc2-handle-OTG-interrupt-regardless-of-GINTSTS.patch
new file mode 100644
index 0000000000..03fb16879c
--- /dev/null
+++ b/target/linux/siflower/patches-6.6/009-usb-dwc2-handle-OTG-interrupt-regardless-of-GINTSTS.patch
@@ -0,0 +1,67 @@
+From 0b04c37a1aae523025195c29a6477cf26234d26c Mon Sep 17 00:00:00 2001
+From: Chuanhong Guo <gch981213 at gmail.com>
+Date: Tue, 10 Sep 2024 09:10:27 +0800
+Subject: [PATCH 9/9] usb: dwc2: handle OTG interrupt regardless of GINTSTS
+
+The DWC OTG 3.30a found on Siflower SF19A2890 has battery charger
+support enabled. It triggers MultVallpChng interrupt (bit 20 of
+GOTGINT) but doesn't set OTGInt in GINTSTS. As a result, this
+interrupt is never handled, and linux disables USB interrupt
+because "nobody cares".
+
+Handle OTG interrupt in IRQ handler regardless of whether the
+OTGInt bit in GINTSTS is set or not.
+
+Signed-off-by: Chuanhong Guo <gch981213 at gmail.com>
+---
+ drivers/usb/dwc2/core_intr.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/dwc2/core_intr.c
++++ b/drivers/usb/dwc2/core_intr.c
+@@ -79,7 +79,7 @@ static void dwc2_handle_mode_mismatch_in
+  *
+  * @hsotg: Programming view of DWC_otg controller
+  */
+-static void dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
++static irqreturn_t dwc2_handle_otg_intr(struct dwc2_hsotg *hsotg)
+ {
+ 	u32 gotgint;
+ 	u32 gotgctl;
+@@ -87,6 +87,10 @@ static void dwc2_handle_otg_intr(struct
+ 
+ 	gotgint = dwc2_readl(hsotg, GOTGINT);
+ 	gotgctl = dwc2_readl(hsotg, GOTGCTL);
++
++	if (!gotgint)
++		return IRQ_NONE;
++
+ 	dev_dbg(hsotg->dev, "++OTG Interrupt gotgint=%0x [%s]\n", gotgint,
+ 		dwc2_op_state_str(hsotg));
+ 
+@@ -229,6 +233,7 @@ static void dwc2_handle_otg_intr(struct
+ 
+ 	/* Clear GOTGINT */
+ 	dwc2_writel(hsotg, gotgint, GOTGINT);
++	return IRQ_HANDLED;
+ }
+ 
+ /**
+@@ -842,6 +847,8 @@ irqreturn_t dwc2_handle_common_intr(int
+ 		hsotg->frame_number = (dwc2_readl(hsotg, HFNUM)
+ 				       & HFNUM_FRNUM_MASK) >> HFNUM_FRNUM_SHIFT;
+ 
++	retval = dwc2_handle_otg_intr(hsotg);
++
+ 	gintsts = dwc2_read_common_intr(hsotg);
+ 	if (gintsts & ~GINTSTS_PRTINT)
+ 		retval = IRQ_HANDLED;
+@@ -855,8 +862,6 @@ irqreturn_t dwc2_handle_common_intr(int
+ 
+ 	if (gintsts & GINTSTS_MODEMIS)
+ 		dwc2_handle_mode_mismatch_intr(hsotg);
+-	if (gintsts & GINTSTS_OTGINT)
+-		dwc2_handle_otg_intr(hsotg);
+ 	if (gintsts & GINTSTS_CONIDSTSCHNG)
+ 		dwc2_handle_conn_id_status_change_intr(hsotg);
+ 	if (gintsts & GINTSTS_DISCONNINT)
diff --git a/target/linux/siflower/sf19a2890/base-files/etc/board.d/02_network b/target/linux/siflower/sf19a2890/base-files/etc/board.d/02_network
new file mode 100644
index 0000000000..f3da21444b
--- /dev/null
+++ b/target/linux/siflower/sf19a2890/base-files/etc/board.d/02_network
@@ -0,0 +1,42 @@
+
+. /lib/functions.sh
+. /lib/functions/uci-defaults.sh
+. /lib/functions/system.sh
+
+siflower_setup_interfaces()
+{
+	local board="$1"
+
+	case $board in
+	siflower,sf19a2890-evb)
+		ucidef_add_switch "switch0" \
+			"0:wan" "1:lan" "2:lan" "3:lan" "4:lan" "6 at eth0"
+		;;
+	esac
+}
+
+siflower_setup_macs()
+{
+	local board="$1"
+	local lan_mac=""
+	local wan_mac=""
+	local label_mac=""
+
+	case $board in
+	siflower,sf19a2890-evb)
+		wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory 0x0)" 1)
+		;;
+	esac
+
+	[ -n "$lan_mac" ] && ucidef_set_interface_macaddr "lan" $lan_mac
+	[ -n "$wan_mac" ] && ucidef_set_interface_macaddr "wan" $wan_mac
+	[ -n "$label_mac" ] && ucidef_set_label_macaddr $label_mac
+}
+
+board_config_update
+board=$(board_name)
+siflower_setup_interfaces $board
+siflower_setup_macs $board
+board_config_flush
+
+exit 0
diff --git a/target/linux/siflower/sf19a2890/base-files/lib/upgrade/platform.sh b/target/linux/siflower/sf19a2890/base-files/lib/upgrade/platform.sh
new file mode 100644
index 0000000000..80cf1cdcf0
--- /dev/null
+++ b/target/linux/siflower/sf19a2890/base-files/lib/upgrade/platform.sh
@@ -0,0 +1,22 @@
+PART_NAME=firmware
+REQUIRE_IMAGE_METADATA=1
+
+platform_check_image() {
+	local board=$(board_name)
+
+	case "$board" in
+	*)
+		return 0
+		;;
+	esac
+}
+
+platform_do_upgrade() {
+	local board=$(board_name)
+
+	case "$board" in
+	*)
+		default_do_upgrade "$1"
+		;;
+	esac
+}
diff --git a/target/linux/siflower/sf19a2890/config-6.6 b/target/linux/siflower/sf19a2890/config-6.6
new file mode 100644
index 0000000000..bec75436e0
--- /dev/null
+++ b/target/linux/siflower/sf19a2890/config-6.6
@@ -0,0 +1,266 @@
+CONFIG_ARCH_32BIT_OFF_T=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_KEEP_MEMBLOCK=y
+CONFIG_ARCH_MMAP_RND_BITS_MAX=15
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARM_AMBA=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BOARD_SCACHE=y
+CONFIG_CC_IMPLICIT_FALLTHROUGH="-Wimplicit-fallthrough=5"
+CONFIG_CC_NO_ARRAY_BOUNDS=y
+CONFIG_CEVT_R4K=y
+CONFIG_CLKSRC_MIPS_GIC=y
+CONFIG_CLK_SF19A2890=y
+CONFIG_CLK_SF19A2890_PERIPH=y
+CONFIG_CLK_SIFLOWER=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_CLOCKSOURCE_WATCHDOG_MAX_SKEW_US=100
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_CONNECTOR=y
+CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+CONFIG_COREDUMP=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_HAS_DIEI=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_RIXI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS32=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MITIGATIONS=y
+CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+CONFIG_CPU_R4K_FPU=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_MSA=y
+CONFIG_CRC16=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_LIB_GF128MUL=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
+CONFIG_CRYPTO_LIB_SHA1=y
+CONFIG_CRYPTO_LIB_UTILS=y
+CONFIG_CSRC_R4K=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DTC=y
+# CONFIG_DWMAC_GENERIC is not set
+CONFIG_DWMAC_SF19A2890=y
+CONFIG_DW_WATCHDOG=y
+CONFIG_ELF_CORE=y
+CONFIG_EXCLUSIVE_SYSTEM_RAM=y
+CONFIG_FANOTIFY=y
+CONFIG_FHANDLE=y
+CONFIG_FIXED_PHY=y
+CONFIG_FS_IOMAP=y
+CONFIG_FUNCTION_ALIGNMENT=0
+CONFIG_FWNODE_MDIO=y
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_FW_LOADER_SYSFS=y
+CONFIG_GCC10_NO_ARRAY_BOUNDS=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_MIGRATION=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_LIB_ASHLDI3=y
+CONFIG_GENERIC_LIB_ASHRDI3=y
+CONFIG_GENERIC_LIB_CMPDI2=y
+CONFIG_GENERIC_LIB_LSHRDI3=y
+CONFIG_GENERIC_LIB_UCMPDI2=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_SIFLOWER=y
+CONFIG_GRO_CELLS=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HOTPLUG_CORE_SYNC=y
+CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_MIPS_CPU=y
+CONFIG_IRQ_WORK=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_MACH_SIFLOWER_MIPS=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_DEVRES=y
+CONFIG_MFD_SYSCON=y
+CONFIG_MICREL_PHY=y
+CONFIG_MIGRATION=y
+CONFIG_MIPS=y
+CONFIG_MIPS_ASID_BITS=8
+CONFIG_MIPS_ASID_SHIFT=0
+CONFIG_MIPS_CLOCK_VSYSCALL=y
+CONFIG_MIPS_CM=y
+CONFIG_MIPS_CMDLINE_DTB_EXTEND=y
+# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_MIPS_CPC=y
+CONFIG_MIPS_CPS=y
+# CONFIG_MIPS_CPS_NS16550_BOOL is not set
+CONFIG_MIPS_CPS_PM=y
+CONFIG_MIPS_CPU_SCACHE=y
+CONFIG_MIPS_FP_SUPPORT=y
+CONFIG_MIPS_GENERIC=y
+CONFIG_MIPS_GIC=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_MIPS_L1_CACHE_SHIFT_5=y
+CONFIG_MIPS_MT=y
+CONFIG_MIPS_MT_FPAFF=y
+CONFIG_MIPS_MT_SMP=y
+# CONFIG_MIPS_NO_APPENDED_DTB is not set
+CONFIG_MIPS_NR_CPU_NR_MAP=4
+CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
+CONFIG_MIPS_RAW_APPENDED_DTB=y
+CONFIG_MIPS_SPRAM=y
+CONFIG_MMU_LAZY_TLB_REFCOUNT=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y
+CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_MTD_SPLIT_UIMAGE_FW=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SRCU_NMI_SAFE=y
+CONFIG_NET_DEVLINK=y
+CONFIG_NET_DSA=y
+CONFIG_NET_DSA_TAG_NONE=y
+CONFIG_NET_EGRESS=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_INGRESS=y
+CONFIG_NET_PTP_CLASSIFY=y
+CONFIG_NET_SELFTESTS=y
+CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_XGRESS=y
+CONFIG_NLS=y
+CONFIG_NO_EXCEPT_FILL=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=4
+CONFIG_NVMEM=y
+CONFIG_NVMEM_LAYOUTS=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_OF_MDIO=y
+CONFIG_PADATA=y
+CONFIG_PAGE_POOL=y
+CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
+CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PCI_DRIVERS_LEGACY=y
+CONFIG_PCS_XPCS=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PHYLIB=y
+CONFIG_PHYLIB_LEDS=y
+CONFIG_PHYLINK=y
+# CONFIG_PHY_SF19A2890_USB is not set
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_SF19A2890=y
+# CONFIG_PINCTRL_SINGLE is not set
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PPS=y
+CONFIG_PREEMPT_NONE_BUILD=y
+CONFIG_PRINTK_TIME=y
+CONFIG_PROC_EVENTS=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_RANDSTRUCT_NONE=y
+CONFIG_RATIONAL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RESET_SF19A2890_PERIPH=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_INFO=y
+# CONFIG_SERIAL_8250 is not set
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SMP=y
+CONFIG_SMP_UP=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPI_PL022=y
+CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SRAM=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_STMMAC_ETH=y
+CONFIG_STMMAC_PLATFORM=y
+CONFIG_SWPHY=y
+CONFIG_SYNC_R4K=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_MIPS16=y
+CONFIG_SYS_SUPPORTS_MIPS_CPS=y
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+CONFIG_SYS_SUPPORTS_SCHED_SMT=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_TARGET_ISA_REV=2
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USE_OF=y
+CONFIG_WATCHDOG_CORE=y
+CONFIG_WEAK_ORDERING=y
+CONFIG_WERROR=y
+CONFIG_XPS=y
diff --git a/target/linux/siflower/sf19a2890/target.mk b/target/linux/siflower/sf19a2890/target.mk
new file mode 100644
index 0000000000..6c47709895
--- /dev/null
+++ b/target/linux/siflower/sf19a2890/target.mk
@@ -0,0 +1,12 @@
+ARCH:=mipsel
+SUBTARGET:=sf19a2890
+BOARDNAME:=Siflower SF19A2890 based boards
+FEATURES+=fpu
+CPU_TYPE:=24kc
+CPU_SUBTYPE:=24kf
+
+KERNELNAME:=vmlinux
+
+define Target/Description
+	Build firmware images for Siflower SF19A2890 based boards.
+endef




More information about the lede-commits mailing list