1 From c17f19be3bec0bf5467f4e14a21573836910f671 Mon Sep 17 00:00:00 2001
2 From: Luo Jie <quic_luoj@quicinc.com>
3 Date: Wed, 29 Nov 2023 15:21:22 +0800
4 Subject: [PATCH] net: phy: qca808x: Add register access support routines for
7 QCA8084 integrates clock controller and security control modules
8 besides of the PHY and PCS. The 32bit registers in these modules
9 are accessed using special MDIO sequences to read or write these
12 The MDIO address of PHY and PCS are configured by writing to the
13 security control register. The package mode for QCA8084 is also
14 configured in a similar manner.
16 Change-Id: I9317307ef9bbc738a6adcbc3ea1be8e6528d711e
17 Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
19 drivers/net/phy/qcom/qca808x.c | 88 ++++++++++++++++++++++++++++++++++
20 1 file changed, 88 insertions(+)
22 --- a/drivers/net/phy/qcom/qca808x.c
23 +++ b/drivers/net/phy/qcom/qca808x.c
25 #define QCA8084_MMD7_IPG_OP 0x901d
26 #define QCA8084_IPG_10_TO_11_EN BIT(0)
28 +/* QCA8084 includes secure control module, which supports customizing the
29 + * MDIO address of PHY device and PCS device and configuring package mode
30 + * for the interface mode of PCS. The register of secure control is accessed
31 + * by MDIO bus with the special MDIO sequences, where the 32 bits register
32 + * address is split into 3 MDIO operations with 16 bits address.
34 +#define QCA8084_HIGH_ADDR_PREFIX 0x18
35 +#define QCA8084_LOW_ADDR_PREFIX 0x10
37 +/* Bottom two bits of REG must be zero */
38 +#define QCA8084_MII_REG_MASK GENMASK(4, 0)
39 +#define QCA8084_MII_PHY_ADDR_MASK GENMASK(7, 5)
40 +#define QCA8084_MII_PAGE_MASK GENMASK(23, 8)
41 +#define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24)
42 +#define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1)
44 MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver");
45 MODULE_AUTHOR("Matus Ujhelyi, Luo Jie");
46 MODULE_LICENSE("GPL");
47 @@ -119,6 +135,78 @@ struct qca808x_priv {
48 int led_polarity_mode;
51 +static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
53 + return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
54 + sw_addr & 0x1f, page);
57 +static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val)
61 + ret = __mdiobus_read(bus, addr, reg);
66 + ret = __mdiobus_read(bus, addr,
67 + reg | QCA8084_MII_REG_DATA_UPPER_16_BITS);
71 + *val = data | ret << 16;
76 +static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val)
80 + ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val));
82 + ret = __mdiobus_write(bus, addr,
83 + reg | QCA8084_MII_REG_DATA_UPPER_16_BITS,
84 + upper_16_bits(val));
89 +static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr,
92 + u16 reg, addr, page, sw_addr;
93 + struct mii_bus *bus;
97 + bus = phydev->mdio.bus;
98 + mutex_lock(&bus->mdio_lock);
100 + reg = FIELD_GET(QCA8084_MII_REG_MASK, regaddr);
101 + addr = FIELD_GET(QCA8084_MII_PHY_ADDR_MASK, regaddr);
102 + page = FIELD_GET(QCA8084_MII_PAGE_MASK, regaddr);
103 + sw_addr = FIELD_GET(QCA8084_MII_SW_ADDR_MASK, regaddr);
105 + ret = __qca8084_set_page(bus, sw_addr, page);
107 + goto qca8084_mii_modify_exit;
109 + ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr,
112 + goto qca8084_mii_modify_exit;
116 + ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr,
118 +qca8084_mii_modify_exit:
119 + mutex_unlock(&bus->mdio_lock);
123 static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)