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 <cjd@cjdns.fr>
Link: https://github.com/openwrt/openwrt/pull/22208
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
This commit is contained in:
Caleb James DeLisle
2026-02-27 15:40:03 +00:00
committed by Hauke Mehrtens
parent 07f140f633
commit c6bec81528
7 changed files with 283 additions and 27 deletions
+101
View File
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
#include <dt-bindings/reset/econet,en751221-scu.h>
#include <dt-bindings/clock/econet,en751221-scu.h>
/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>,
@@ -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";
};
};
@@ -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";
};
};
@@ -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";
};
};
+18 -3
View File
@@ -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
+3 -2
View File
@@ -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
@@ -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 <naseefkm@gmail.com>
@@ -220,41 +230,71 @@
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+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, &regmap_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);