immortalwrt-VIKINGYFY/target/linux/qualcommbe/patches-6.12/0310-net-phy-qca808x-Add-register-access-support-routines.patch
Alexandru Gagniuc 7656e74a95 qualcommbe: support 10g-qxgmii in QCA8084 PHY driver
The "old" QCA8084 PHY driver does not implement 10g-qxgmii support.
This is blocking several devices which use the QCA8084 form being
merged. Qualcomm has provided updated drivers for the MAC (ppe), PCS,
and PHY via github. We only need to update the PHY driver.

Update the QCA8084 PHY driver using the patches provided by Qualcomm.
Re-organize the patches so that the changes go into the existing
patches. The SERDES functionality is new, so it gets new patches. This
is sufficient to enable 10g-qxgmii on ipq95xx platforms.

Signed-off-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/20721
Signed-off-by: Robert Marko <robimarko@gmail.com>
2025-11-11 17:21:54 +01:00

126 lines
3.7 KiB
Diff

From cea8043def0c0867370c2efd5a1cd73bf4d3e5ba Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Wed, 29 Nov 2023 15:21:22 +0800
Subject: [PATCH] net: phy: qca808x: Add register access support routines for
QCA8084
QCA8084 integrates clock controller and security control modules
besides of the PHY and PCS. The 32bit registers in these modules
are accessed using special MDIO sequences to read or write these
registers.
The MDIO address of PHY and PCS are configured by writing to the
security control register. The package mode for QCA8084 is also
configured in a similar manner.
Change-Id: I9317307ef9bbc738a6adcbc3ea1be8e6528d711e
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/phy/qcom/qca808x.c | 88 ++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
--- a/drivers/net/phy/qcom/qca808x.c
+++ b/drivers/net/phy/qcom/qca808x.c
@@ -111,6 +111,22 @@
#define QCA8084_MMD7_IPG_OP 0x901d
#define QCA8084_IPG_10_TO_11_EN BIT(0)
+/* QCA8084 includes secure control module, which supports customizing the
+ * MDIO address of PHY device and PCS device and configuring package mode
+ * for the interface mode of PCS. The register of secure control is accessed
+ * by MDIO bus with the special MDIO sequences, where the 32 bits register
+ * address is split into 3 MDIO operations with 16 bits address.
+ */
+#define QCA8084_HIGH_ADDR_PREFIX 0x18
+#define QCA8084_LOW_ADDR_PREFIX 0x10
+
+/* Bottom two bits of REG must be zero */
+#define QCA8084_MII_REG_MASK GENMASK(4, 0)
+#define QCA8084_MII_PHY_ADDR_MASK GENMASK(7, 5)
+#define QCA8084_MII_PAGE_MASK GENMASK(23, 8)
+#define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24)
+#define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1)
+
MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi, Luo Jie");
MODULE_LICENSE("GPL");
@@ -119,6 +135,78 @@ struct qca808x_priv {
int led_polarity_mode;
};
+static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
+{
+ return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
+ sw_addr & 0x1f, page);
+}
+
+static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val)
+{
+ int ret, data;
+
+ ret = __mdiobus_read(bus, addr, reg);
+ if (ret < 0)
+ return ret;
+
+ data = ret;
+ ret = __mdiobus_read(bus, addr,
+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS);
+ if (ret < 0)
+ return ret;
+
+ *val = data | ret << 16;
+
+ return 0;
+}
+
+static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val)
+{
+ int ret;
+
+ ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val));
+ if (!ret)
+ ret = __mdiobus_write(bus, addr,
+ reg | QCA8084_MII_REG_DATA_UPPER_16_BITS,
+ upper_16_bits(val));
+
+ return ret;
+}
+
+static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr,
+ u32 clear, u32 set)
+{
+ u16 reg, addr, page, sw_addr;
+ struct mii_bus *bus;
+ u32 val;
+ int ret;
+
+ bus = phydev->mdio.bus;
+ mutex_lock(&bus->mdio_lock);
+
+ reg = FIELD_GET(QCA8084_MII_REG_MASK, regaddr);
+ addr = FIELD_GET(QCA8084_MII_PHY_ADDR_MASK, regaddr);
+ page = FIELD_GET(QCA8084_MII_PAGE_MASK, regaddr);
+ sw_addr = FIELD_GET(QCA8084_MII_SW_ADDR_MASK, regaddr);
+
+ ret = __qca8084_set_page(bus, sw_addr, page);
+ if (ret < 0)
+ goto qca8084_mii_modify_exit;
+
+ ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr,
+ reg, &val);
+ if (ret < 0)
+ goto qca8084_mii_modify_exit;
+
+ val &= ~clear;
+ val |= set;
+ ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr,
+ reg, val);
+qca8084_mii_modify_exit:
+ mutex_unlock(&bus->mdio_lock);
+ return ret;
+};
+
static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
{
int ret;