lede/target/linux/qualcommbe/patches-6.6/103-05-net-phy-qca808x-Add-register-access-support-routines.patch
John Audia d989a3256a qualcommb/ipq95xx: refresh patches ahead of 6.6.75
Refreshed patches for qualcommb/ipq95xx by running
make target/linux/refresh after creating a .config containing:
CONFIG_TARGET_qualcommbe=y
CONFIG_TARGET_qualcommbe_ipq95xx=y
CONFIG_TARGET_qualcommbe_ipq95xx_DEVICE_qcom_rdp433=y

Signed-off-by: John Audia <therealgraysky@proton.me>
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
2025-02-18 11:00:26 +08:00

126 lines
3.7 KiB
Diff

From 9443d85d8f3e397b025700251516e248fc4e37c0 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 05/50] 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;