7986a6c908cfe0c7005d602561c4da85a084bd70
[openwrt/staging/stintel.git] /
1 From 9443d85d8f3e397b025700251516e248fc4e37c0 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 05/50] net: phy: qca808x: Add register access support routines
5 for QCA8084
6
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
10 registers.
11
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.
15
16 Change-Id: I9317307ef9bbc738a6adcbc3ea1be8e6528d711e
17 Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
18 ---
19 drivers/net/phy/qcom/qca808x.c | 88 ++++++++++++++++++++++++++++++++++
20 1 file changed, 88 insertions(+)
21
22 diff --git a/drivers/net/phy/qcom/qca808x.c b/drivers/net/phy/qcom/qca808x.c
23 index 029d5f9de6b8..8873474146e8 100644
24 --- a/drivers/net/phy/qcom/qca808x.c
25 +++ b/drivers/net/phy/qcom/qca808x.c
26 @@ -111,6 +111,22 @@
27 #define QCA8084_MMD7_IPG_OP 0x901d
28 #define QCA8084_IPG_10_TO_11_EN BIT(0)
29
30 +/* QCA8084 includes secure control module, which supports customizing the
31 + * MDIO address of PHY device and PCS device and configuring package mode
32 + * for the interface mode of PCS. The register of secure control is accessed
33 + * by MDIO bus with the special MDIO sequences, where the 32 bits register
34 + * address is split into 3 MDIO operations with 16 bits address.
35 + */
36 +#define QCA8084_HIGH_ADDR_PREFIX 0x18
37 +#define QCA8084_LOW_ADDR_PREFIX 0x10
38 +
39 +/* Bottom two bits of REG must be zero */
40 +#define QCA8084_MII_REG_MASK GENMASK(4, 0)
41 +#define QCA8084_MII_PHY_ADDR_MASK GENMASK(7, 5)
42 +#define QCA8084_MII_PAGE_MASK GENMASK(23, 8)
43 +#define QCA8084_MII_SW_ADDR_MASK GENMASK(31, 24)
44 +#define QCA8084_MII_REG_DATA_UPPER_16_BITS BIT(1)
45 +
46 MODULE_DESCRIPTION("Qualcomm Atheros QCA808X PHY driver");
47 MODULE_AUTHOR("Matus Ujhelyi, Luo Jie");
48 MODULE_LICENSE("GPL");
49 @@ -119,6 +135,78 @@ struct qca808x_priv {
50 int led_polarity_mode;
51 };
52
53 +static int __qca8084_set_page(struct mii_bus *bus, u16 sw_addr, u16 page)
54 +{
55 + return __mdiobus_write(bus, QCA8084_HIGH_ADDR_PREFIX | (sw_addr >> 5),
56 + sw_addr & 0x1f, page);
57 +}
58 +
59 +static int __qca8084_mii_read(struct mii_bus *bus, u16 addr, u16 reg, u32 *val)
60 +{
61 + int ret, data;
62 +
63 + ret = __mdiobus_read(bus, addr, reg);
64 + if (ret < 0)
65 + return ret;
66 +
67 + data = ret;
68 + ret = __mdiobus_read(bus, addr,
69 + reg | QCA8084_MII_REG_DATA_UPPER_16_BITS);
70 + if (ret < 0)
71 + return ret;
72 +
73 + *val = data | ret << 16;
74 +
75 + return 0;
76 +}
77 +
78 +static int __qca8084_mii_write(struct mii_bus *bus, u16 addr, u16 reg, u32 val)
79 +{
80 + int ret;
81 +
82 + ret = __mdiobus_write(bus, addr, reg, lower_16_bits(val));
83 + if (!ret)
84 + ret = __mdiobus_write(bus, addr,
85 + reg | QCA8084_MII_REG_DATA_UPPER_16_BITS,
86 + upper_16_bits(val));
87 +
88 + return ret;
89 +}
90 +
91 +static int qca8084_mii_modify(struct phy_device *phydev, u32 regaddr,
92 + u32 clear, u32 set)
93 +{
94 + u16 reg, addr, page, sw_addr;
95 + struct mii_bus *bus;
96 + u32 val;
97 + int ret;
98 +
99 + bus = phydev->mdio.bus;
100 + mutex_lock(&bus->mdio_lock);
101 +
102 + reg = FIELD_GET(QCA8084_MII_REG_MASK, regaddr);
103 + addr = FIELD_GET(QCA8084_MII_PHY_ADDR_MASK, regaddr);
104 + page = FIELD_GET(QCA8084_MII_PAGE_MASK, regaddr);
105 + sw_addr = FIELD_GET(QCA8084_MII_SW_ADDR_MASK, regaddr);
106 +
107 + ret = __qca8084_set_page(bus, sw_addr, page);
108 + if (ret < 0)
109 + goto qca8084_mii_modify_exit;
110 +
111 + ret = __qca8084_mii_read(bus, QCA8084_LOW_ADDR_PREFIX | addr,
112 + reg, &val);
113 + if (ret < 0)
114 + goto qca8084_mii_modify_exit;
115 +
116 + val &= ~clear;
117 + val |= set;
118 + ret = __qca8084_mii_write(bus, QCA8084_LOW_ADDR_PREFIX | addr,
119 + reg, val);
120 +qca8084_mii_modify_exit:
121 + mutex_unlock(&bus->mdio_lock);
122 + return ret;
123 +};
124 +
125 static int qca808x_phy_fast_retrain_config(struct phy_device *phydev)
126 {
127 int ret;
128 --
129 2.45.2
130