1 // SPDX-License-Identifier: GPL-2.0+
4 #include <linux/module.h>
8 #define AT803X_DEBUG_REG_3C 0x3C
10 #define AT803X_DEBUG_REG_GREEN 0x3D
11 #define AT803X_DEBUG_GATE_CLK_IN1000 BIT(6)
13 #define MDIO_AZ_DEBUG 0x800D
15 #define QCA8327_A_PHY_ID 0x004dd033
16 #define QCA8327_B_PHY_ID 0x004dd034
17 #define QCA8337_PHY_ID 0x004dd036
19 #define QCA8K_DEVFLAGS_REVISION_MASK GENMASK(2, 0)
21 static struct at803x_hw_stat qca83xx_hw_stats[] = {
22 { "phy_idle_errors", 0xa, GENMASK(7, 0), PHY},
23 { "phy_receive_errors", 0x15, GENMASK(15, 0), PHY},
24 { "eee_wake_errors", 0x16, GENMASK(15, 0), MMD},
28 u64 stats[ARRAY_SIZE(qca83xx_hw_stats)];
31 MODULE_DESCRIPTION("Qualcomm Atheros QCA83XX PHY driver");
32 MODULE_AUTHOR("Matus Ujhelyi");
34 MODULE_LICENSE("GPL");
36 static int qca83xx_get_sset_count(struct phy_device *phydev)
38 return ARRAY_SIZE(qca83xx_hw_stats);
41 static void qca83xx_get_strings(struct phy_device *phydev, u8 *data)
45 for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
46 ethtool_puts(&data, qca83xx_hw_stats[i].string);
49 static u64 qca83xx_get_stat(struct phy_device *phydev, int i)
51 struct at803x_hw_stat stat = qca83xx_hw_stats[i];
52 struct qca83xx_priv *priv = phydev->priv;
56 if (stat.access_type == MMD)
57 val = phy_read_mmd(phydev, MDIO_MMD_PCS, stat.reg);
59 val = phy_read(phydev, stat.reg);
64 val = val & stat.mask;
65 priv->stats[i] += val;
72 static void qca83xx_get_stats(struct phy_device *phydev,
73 struct ethtool_stats *stats, u64 *data)
77 for (i = 0; i < ARRAY_SIZE(qca83xx_hw_stats); i++)
78 data[i] = qca83xx_get_stat(phydev, i);
81 static int qca83xx_probe(struct phy_device *phydev)
83 struct device *dev = &phydev->mdio.dev;
84 struct qca83xx_priv *priv;
86 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
95 static int qca83xx_config_init(struct phy_device *phydev)
99 switch_revision = phydev->dev_flags & QCA8K_DEVFLAGS_REVISION_MASK;
101 switch (switch_revision) {
103 /* For 100M waveform */
104 at803x_debug_reg_write(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL, 0x02ea);
105 /* Turn on Gigabit clock */
106 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x68a0);
110 phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0x0);
113 phy_write_mmd(phydev, MDIO_MMD_PCS, MDIO_AZ_DEBUG, 0x803f);
114 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_GREEN, 0x6860);
115 at803x_debug_reg_write(phydev, AT803X_DEBUG_SYSTEM_CTRL_MODE, 0x2c46);
116 at803x_debug_reg_write(phydev, AT803X_DEBUG_REG_3C, 0x6000);
120 /* Following original QCA sourcecode set port to prefer master */
121 phy_set_bits(phydev, MII_CTRL1000, CTL1000_PREFER_MASTER);
126 static int qca8327_config_init(struct phy_device *phydev)
128 /* QCA8327 require DAC amplitude adjustment for 100m set to +6%.
129 * Disable on init and enable only with 100m speed following
130 * qca original source code.
132 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
133 QCA8327_DEBUG_MANU_CTRL_EN, 0);
135 return qca83xx_config_init(phydev);
138 static void qca83xx_link_change_notify(struct phy_device *phydev)
140 /* Set DAC Amplitude adjustment to +6% for 100m on link running */
141 if (phydev->state == PHY_RUNNING) {
142 if (phydev->speed == SPEED_100)
143 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
144 QCA8327_DEBUG_MANU_CTRL_EN,
145 QCA8327_DEBUG_MANU_CTRL_EN);
147 /* Reset DAC Amplitude adjustment */
148 at803x_debug_reg_mask(phydev, AT803X_DEBUG_ANALOG_TEST_CTRL,
149 QCA8327_DEBUG_MANU_CTRL_EN, 0);
153 static int qca83xx_resume(struct phy_device *phydev)
157 /* Skip reset if not suspended */
158 if (!phydev->suspended)
161 /* Reinit the port, reset values set by suspend */
162 qca83xx_config_init(phydev);
164 /* Reset the port on port resume */
165 phy_set_bits(phydev, MII_BMCR, BMCR_RESET | BMCR_ANENABLE);
167 /* On resume from suspend the switch execute a reset and
168 * restart auto-negotiation. Wait for reset to complete.
170 ret = phy_read_poll_timeout(phydev, MII_BMCR, val, !(val & BMCR_RESET),
171 50000, 600000, true);
175 usleep_range(1000, 2000);
180 static int qca83xx_suspend(struct phy_device *phydev)
182 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_GREEN,
183 AT803X_DEBUG_GATE_CLK_IN1000, 0);
185 at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL,
186 AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE |
187 AT803X_DEBUG_HIB_CTRL_SEL_RST_80U, 0);
192 static int qca8337_suspend(struct phy_device *phydev)
194 /* Only QCA8337 support actual suspend. */
195 genphy_suspend(phydev);
197 return qca83xx_suspend(phydev);
200 static int qca8327_suspend(struct phy_device *phydev)
204 /* QCA8327 cause port unreliability when phy suspend
207 mask |= ~(BMCR_SPEED1000 | BMCR_FULLDPLX);
208 phy_modify(phydev, MII_BMCR, mask, 0);
210 return qca83xx_suspend(phydev);
213 static struct phy_driver qca83xx_driver[] = {
216 PHY_ID_MATCH_EXACT(QCA8337_PHY_ID),
217 .name = "Qualcomm Atheros 8337 internal PHY",
218 /* PHY_GBIT_FEATURES */
219 .probe = qca83xx_probe,
220 .flags = PHY_IS_INTERNAL,
221 .config_init = qca83xx_config_init,
222 .soft_reset = genphy_soft_reset,
223 .get_sset_count = qca83xx_get_sset_count,
224 .get_strings = qca83xx_get_strings,
225 .get_stats = qca83xx_get_stats,
226 .suspend = qca8337_suspend,
227 .resume = qca83xx_resume,
229 /* QCA8327-A from switch QCA8327-AL1A */
230 PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID),
231 .name = "Qualcomm Atheros 8327-A internal PHY",
232 /* PHY_GBIT_FEATURES */
233 .link_change_notify = qca83xx_link_change_notify,
234 .probe = qca83xx_probe,
235 .flags = PHY_IS_INTERNAL,
236 .config_init = qca8327_config_init,
237 .soft_reset = genphy_soft_reset,
238 .get_sset_count = qca83xx_get_sset_count,
239 .get_strings = qca83xx_get_strings,
240 .get_stats = qca83xx_get_stats,
241 .suspend = qca8327_suspend,
242 .resume = qca83xx_resume,
244 /* QCA8327-B from switch QCA8327-BL1A */
245 PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID),
246 .name = "Qualcomm Atheros 8327-B internal PHY",
247 /* PHY_GBIT_FEATURES */
248 .link_change_notify = qca83xx_link_change_notify,
249 .probe = qca83xx_probe,
250 .flags = PHY_IS_INTERNAL,
251 .config_init = qca8327_config_init,
252 .soft_reset = genphy_soft_reset,
253 .get_sset_count = qca83xx_get_sset_count,
254 .get_strings = qca83xx_get_strings,
255 .get_stats = qca83xx_get_stats,
256 .suspend = qca8327_suspend,
257 .resume = qca83xx_resume,
260 module_phy_driver(qca83xx_driver);
262 static const struct mdio_device_id __maybe_unused qca83xx_tbl[] = {
263 { PHY_ID_MATCH_EXACT(QCA8337_PHY_ID) },
264 { PHY_ID_MATCH_EXACT(QCA8327_A_PHY_ID) },
265 { PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
269 MODULE_DEVICE_TABLE(mdio, qca83xx_tbl);