From c6bec81528d497e289912f4e5ae478f96b2ec9d7 Mon Sep 17 00:00:00 2001 From: Caleb James DeLisle Date: Fri, 27 Feb 2026 15:40:03 +0000 Subject: [PATCH] econet: add PCIe driver for EN751221 and enable wifi Extend the EN7528 PCIe driver to EN751221 with a specific PHY tuning ritual. Also enable wifi drivers on SmartFiber XP8421-B, TpLink Archer VR1200V v2 and Zyxel PMG5617GA. Signed-off-by: Caleb James DeLisle Link: https://github.com/openwrt/openwrt/pull/22208 Signed-off-by: Hauke Mehrtens --- target/linux/econet/dts/en751221.dtsi | 101 ++++++++++++++++++ .../dts/en751221_smartfiber_xp8421-b.dts | 25 +++++ .../dts/en751221_tplink_archer-vr1200v-v2.dts | 25 +++++ .../econet/dts/en751221_zyxel_pmg5617ga.dts | 43 ++++++++ target/linux/econet/en751221/config-6.12 | 21 +++- target/linux/econet/image/en751221.mk | 5 +- ...pcie-add-en7528-pcie-and-phy-support.patch | 90 ++++++++++++---- 7 files changed, 283 insertions(+), 27 deletions(-) diff --git a/target/linux/econet/dts/en751221.dtsi b/target/linux/econet/dts/en751221.dtsi index de1a2287cfd..7b749f88af0 100644 --- a/target/linux/econet/dts/en751221.dtsi +++ b/target/linux/econet/dts/en751221.dtsi @@ -1,6 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) #include +#include /dts-v1/; @@ -53,6 +54,18 @@ reg = <0x1fa20000 0x388>; }; + pcie_phy1: pcie-phy@1fac0000 { + compatible = "econet,en751221-pcie-phy1"; + reg = <0x1fac0000 0x1000>; + #phy-cells = <0>; + }; + + pcie_phy0: pcie-phy@1faf2000 { + compatible = "econet,en751221-pcie-phy0"; + reg = <0x1faf2000 0x1000>; + #phy-cells = <0>; + }; + intc: interrupt-controller@1fb40000 { compatible = "econet,en751221-intc"; reg = <0x1fb40000 0x100>; @@ -167,6 +180,94 @@ }; }; + pciecfg: pciecfg@1fb80000 { + compatible = "mediatek,generic-pciecfg", "syscon"; + reg = <0x1fb80000 0x1000>; + }; + + pcie0: pcie@1fb81000 { + compatible = "econet,en7528-pcie"; + device_type = "pci"; + reg = <0x1fb81000 0x1000>; + reg-names = "port0"; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <23>; + interrupt-names = "pcie_irq"; + clocks = <&scuclk EN751221_CLK_PCIE>; + clock-names = "sys_ck0"; + phys = <&pcie_phy0>; + phy-names = "pcie-phy0"; + bus-range = <0x00 0xff>; + ranges = <0x01000000 0 0x00000000 0x1f600000 0 0x00008000>, + <0x82000000 0 0x20000000 0x20000000 0 0x08000000>; + status = "disabled"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc0 0>, + <0 0 0 2 &pcie_intc0 1>, + <0 0 0 3 &pcie_intc0 2>, + <0 0 0 4 &pcie_intc0 3>; + + pcie_intc0: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + + slot0: pcie@0,0 { + reg = <0x0000 0 0 0 0>; + device_type = "pci"; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + + pcie1: pcie@1fb83000 { + compatible = "econet,en7528-pcie"; + device_type = "pci"; + reg = <0x1fb83000 0x1000>; + reg-names = "port1"; + linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; + interrupt-parent = <&intc>; + interrupts = <24>; + interrupt-names = "pcie_irq"; + clocks = <&scuclk EN751221_CLK_PCIE>; + clock-names = "sys_ck1"; + phys = <&pcie_phy1>; + phy-names = "pcie-phy1"; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0 0x00000000 0x1f608000 0 0x00008000>, + <0x82000000 0 0x28000000 0x28000000 0 0x08000000>; + status = "disabled"; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &pcie_intc1 0>, + <0 0 0 2 &pcie_intc1 1>, + <0 0 0 3 &pcie_intc1 2>, + <0 0 0 4 &pcie_intc1 3>; + + pcie_intc1: interrupt-controller { + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + + slot1: pcie@1,0 { + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + }; + usb: usb@1fb90000 { compatible = "mediatek,mt8173-xhci", "mediatek,mtk-xhci"; reg = <0x1fb90000 0x4000>, diff --git a/target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts b/target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts index 4599d340535..5f35f2189f3 100644 --- a/target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts +++ b/target/linux/econet/dts/en751221_smartfiber_xp8421-b.dts @@ -110,3 +110,28 @@ nvmem-cells = <&macaddr_bootloader_ff48 0>; nvmem-cell-names = "mac-address"; }; + +&pcie0 { + status = "okay"; +}; +&slot0 { + wifi@0,0 { + /* MT7612E */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_reserve_180040>, <&macaddr_bootloader_ff48 1>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; +&pcie1 { + status = "okay"; +}; +&slot1 { + wifi@0,0 { + /* MT7592 */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_reserve_140000>, <&macaddr_bootloader_ff48 2>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; diff --git a/target/linux/econet/dts/en751221_tplink_archer-vr1200v-v2.dts b/target/linux/econet/dts/en751221_tplink_archer-vr1200v-v2.dts index 2bc44d11cd5..6aa6aa115c1 100644 --- a/target/linux/econet/dts/en751221_tplink_archer-vr1200v-v2.dts +++ b/target/linux/econet/dts/en751221_tplink_archer-vr1200v-v2.dts @@ -102,3 +102,28 @@ nvmem-cells = <&macaddr_misc_8f100 0>; nvmem-cell-names = "mac-address"; }; + +&pcie0 { + status = "okay"; +}; +&slot0 { + wifi@0,0 { + /* MT7592 */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_misc_80000>, <&macaddr_misc_8f100 1>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; +&pcie1 { + status = "okay"; +}; +&slot1 { + wifi@0,0 { + /* MT7613BE */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_misc_a0000>, <&macaddr_misc_8f100 2>; + nvmem-cell-names = "eeprom", "mac-address"; + }; +}; diff --git a/target/linux/econet/dts/en751221_zyxel_pmg5617ga.dts b/target/linux/econet/dts/en751221_zyxel_pmg5617ga.dts index b6a95801bec..73f9af674e8 100644 --- a/target/linux/econet/dts/en751221_zyxel_pmg5617ga.dts +++ b/target/linux/econet/dts/en751221_zyxel_pmg5617ga.dts @@ -77,6 +77,49 @@ partition@7540000 { label = "reservearea"; reg = <0x007540000 0x000080000>; + nvmem-layout { + compatible = "fixed-layout"; + #address-cells = <1>; + #size-cells = <1>; + + eeprom_reserve_60000: eeprom@60000 { + /* MT7592 */ + /* This overlaps the MT7612E EEPROM, but MT7603E demands + * 1024 bytes of EEPROM even though only 512 bytes are used. + */ + reg = <0x60000 0x400>; + }; + + eeprom_reserve_60200: eeprom@60200 { + /* MT7612E */ + reg = <0x60200 0x200>; + }; + }; }; }; }; + +&pcie0 { + status = "okay"; +}; +&slot0 { + wifi@0,0 { + /* MT7592 */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_reserve_60000>; + nvmem-cell-names = "eeprom"; + }; +}; +&pcie1 { + status = "okay"; +}; +&slot1 { + wifi@0,0 { + /* MT7612E */ + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + nvmem-cells = <&eeprom_reserve_60200>; + nvmem-cell-names = "eeprom"; + }; +}; diff --git a/target/linux/econet/en751221/config-6.12 b/target/linux/econet/en751221/config-6.12 index 5357f6f9883..d68d0ca44d1 100644 --- a/target/linux/econet/en751221/config-6.12 +++ b/target/linux/econet/en751221/config-6.12 @@ -2,6 +2,7 @@ CONFIG_ARCH_32BIT_OFF_T=y CONFIG_ARCH_KEEP_MEMBLOCK=y CONFIG_ARCH_MMAP_RND_BITS_MAX=15 CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15 +CONFIG_BLK_MQ_PCI=y CONFIG_CLKSRC_MMIO=y CONFIG_CLONE_BACKWARDS=y CONFIG_COMMON_CLK=y @@ -69,7 +70,9 @@ CONFIG_GENERIC_LIB_ASHRDI3=y CONFIG_GENERIC_LIB_CMPDI2=y CONFIG_GENERIC_LIB_LSHRDI3=y CONFIG_GENERIC_LIB_UCMPDI2=y +CONFIG_GENERIC_MSI_IRQ=y CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_PHY=y CONFIG_GENERIC_SCHED_CLOCK=y CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_GENERIC_TIME_VSYSCALL=y @@ -84,6 +87,7 @@ CONFIG_HZ_PERIODIC=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 @@ -119,7 +123,6 @@ CONFIG_NET_EGRESS=y CONFIG_NET_FLOW_LIMIT=y CONFIG_NET_INGRESS=y CONFIG_NET_XGRESS=y -CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y CONFIG_NR_CPUS=2 CONFIG_NVMEM=y CONFIG_NVMEM_LAYOUTS=y @@ -135,15 +138,27 @@ 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_PCI=y +CONFIG_PCIEAER=y +CONFIG_PCIEPORTBUS=y +CONFIG_PCIE_MEDIATEK=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +CONFIG_PCI_DOMAINS_GENERIC=y +CONFIG_PCI_DRIVERS_GENERIC=y +CONFIG_PCI_MSI=y +CONFIG_PCI_MSI_ARCH_FALLBACKS=y CONFIG_PERF_USE_VMALLOC=y CONFIG_PGTABLE_LEVELS=2 -# CONFIG_PHY_EN7528_PCIE is not set +CONFIG_PHY_EN7528_PCIE=y CONFIG_PTP_1588_CLOCK_OPTIONAL=y CONFIG_QUEUED_RWLOCKS=y CONFIG_QUEUED_SPINLOCKS=y CONFIG_RANDSTRUCT_NONE=y +CONFIG_RAS=y CONFIG_RATIONAL=y +CONFIG_REGMAP=y +CONFIG_REGMAP_MMIO=y CONFIG_RESET_CONTROLLER=y CONFIG_RFS_ACCEL=y CONFIG_RPS=y diff --git a/target/linux/econet/image/en751221.mk b/target/linux/econet/image/en751221.mk index 126288bfecb..89fc0bdee2a 100644 --- a/target/linux/econet/image/en751221.mk +++ b/target/linux/econet/image/en751221.mk @@ -25,7 +25,7 @@ define Device/smartfiber_xp8421-b DEVICE_DTS := en751221_smartfiber_xp8421-b IMAGES := tclinux.trx IMAGE/tclinux.trx := append-kernel | lzma | tclinux-trx - DEVICE_PACKAGES := kmod-usb3 + DEVICE_PACKAGES := kmod-usb3 kmod-mt7603 kmod-mt76x2 endef TARGET_DEVICES += smartfiber_xp8421-b @@ -41,6 +41,7 @@ define Device/tplink_archer-vr1200v-v2 TPLINK_HWREVADD := 0x0 TPLINK_HVERSION := 3 DEVICE_DTS := en751221_tplink_archer-vr1200v-v2 + DEVICE_PACKAGES := kmod-mt7603 kmod-mt7615e kmod-mt7663-firmware-ap IMAGES := sysupgrade.bin IMAGE/sysupgrade.bin := append-kernel | lzma | pad-to 4193792 | append-rootfs | \ tplink-v2-header -R 0x400000 @@ -53,6 +54,6 @@ define Device/zyxel_pmg5617ga DEVICE_DTS := en751221_zyxel_pmg5617ga IMAGES := tclinux.trx IMAGE/tclinux.trx := append-kernel | lzma | tclinux-trx - DEVICE_PACKAGES := kmod-usb3 + DEVICE_PACKAGES := kmod-usb3 kmod-mt7603 kmod-mt76x2 endef TARGET_DEVICES += zyxel_pmg5617ga diff --git a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch b/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch index 917bd8a4808..ee8d1bdab9d 100644 --- a/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch +++ b/target/linux/econet/patches-6.12/912-pcie-add-en7528-pcie-and-phy-support.patch @@ -11,7 +11,17 @@ help --- a/arch/mips/econet/Kconfig +++ b/arch/mips/econet/Kconfig -@@ -28,9 +28,11 @@ choice +@@ -14,7 +14,9 @@ choice + select COMMON_CLK + select CPU_BIG_ENDIAN + select ECONET_EN751221_INTC ++ select HAVE_PCI + select IRQ_MIPS_CPU ++ select PCI_DRIVERS_GENERIC + select SMP + select SMP_UP + select SYS_SUPPORTS_SMP +@@ -28,9 +30,11 @@ choice bool "EN7528 family" select COMMON_CLK select CPU_LITTLE_ENDIAN @@ -205,7 +215,7 @@ broadcom/ \ --- /dev/null +++ b/drivers/phy/phy-en7528-pcie.c -@@ -0,0 +1,119 @@ +@@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2026 Ahmed Naseef @@ -220,41 +230,71 @@ +#include +#include + -+struct en7528_pcie_phy_data { ++struct en7528_pcie_phy_op { + u32 reg; + u32 mask; + u32 val; -+ u32 max_reg; +}; + +struct en7528_pcie_phy { + struct regmap *regmap; -+ const struct en7528_pcie_phy_data *data; ++ const struct en7528_pcie_phy_op *data; +}; + +/* Port 0 PHY: set LCDDS_CLK_PH_INV for PLL operation */ -+static const struct en7528_pcie_phy_data en7528_phy_port0 = { -+ .reg = 0x4a0, -+ .mask = BIT(5), -+ .val = BIT(5), -+ .max_reg = 0x4a0, ++static const struct en7528_pcie_phy_op en7528_phy_port0[] = { ++ { ++ .reg = 0x4a0, ++ .mask = BIT(5), ++ .val = BIT(5), ++ }, ++ { /* sentinel */ } +}; + +/* Port 1 PHY: Rx impedance tuning, target R -5 Ohm */ -+static const struct en7528_pcie_phy_data en7528_phy_port1 = { -+ .reg = 0xb2c, -+ .mask = GENMASK(13, 12), -+ .val = BIT(12), -+ .max_reg = 0xb2c, ++static const struct en7528_pcie_phy_op en7528_phy_port1[] = { ++ { ++ .reg = 0xb2c, ++ .mask = GENMASK(13, 12), ++ .val = BIT(12), ++ }, ++ { /* sentinel */ } ++}; ++ ++/* EN751221 Port 1 PHY */ ++static const struct en7528_pcie_phy_op en751221_phy_port1[] = { ++ /* Rx Detection Timing for 7512 E1, 16*8 clock cycles */ ++ { ++ .reg = 0xa28, ++ .mask = GENMASK(17, 9), ++ .val = 16 << 9, ++ }, ++ /* Same for different power mode */ ++ { ++ .reg = 0xa2c, ++ .mask = GENMASK(8, 0), ++ .val = 16, ++ }, ++ { /* sentinel */ } +}; + +static int en7528_pcie_phy_init(struct phy *phy) +{ + struct en7528_pcie_phy *ephy = phy_get_drvdata(phy); -+ const struct en7528_pcie_phy_data *data = ephy->data; ++ const struct en7528_pcie_phy_op *data = ephy->data; ++ int i, ret; + -+ return regmap_update_bits(ephy->regmap, data->reg, -+ data->mask, data->val); ++ for (i = 0; data[i].mask || data[i].val; i++) { ++ if (i) ++ usleep_range(1000, 2000); ++ ++ ret = regmap_update_bits(ephy->regmap, data[i].reg, ++ data[i].mask, data[i].val); ++ if (ret) ++ return ret; ++ } ++ ++ return 0; +} + +static const struct phy_ops en7528_pcie_phy_ops = { @@ -265,7 +305,7 @@ +static int en7528_pcie_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; -+ const struct en7528_pcie_phy_data *data; ++ const struct en7528_pcie_phy_op *data; + struct regmap_config regmap_config = { + .reg_bits = 32, + .val_bits = 32, @@ -275,6 +315,7 @@ + struct en7528_pcie_phy *ephy; + void __iomem *base; + struct phy *phy; ++ int i; + + data = of_device_get_match_data(dev); + if (!data) @@ -290,7 +331,10 @@ + if (IS_ERR(base)) + return PTR_ERR(base); + -+ regmap_config.max_register = data->max_reg; ++ for (i = 0; data[i].mask || data[i].val; i++) ++ if (data[i].reg > regmap_config.max_register) ++ regmap_config.max_register = data[i].reg; ++ + ephy->regmap = devm_regmap_init_mmio(dev, base, ®map_config); + if (IS_ERR(ephy->regmap)) + return PTR_ERR(ephy->regmap); @@ -307,8 +351,10 @@ +} + +static const struct of_device_id en7528_pcie_phy_ids[] = { -+ { .compatible = "econet,en7528-pcie-phy0", .data = &en7528_phy_port0 }, -+ { .compatible = "econet,en7528-pcie-phy1", .data = &en7528_phy_port1 }, ++ { .compatible = "econet,en7528-pcie-phy0", .data = en7528_phy_port0 }, ++ { .compatible = "econet,en7528-pcie-phy1", .data = en7528_phy_port1 }, ++ { .compatible = "econet,en751221-pcie-phy0", .data = en7528_phy_port0 }, ++ { .compatible = "econet,en751221-pcie-phy1", .data = en751221_phy_port1 }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, en7528_pcie_phy_ids);