blob: 3cd301c50edf0adb81b67805999248b91905c6e0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Andy Fleming60ca78b2011-04-07 21:56:05 -05002/*
3 * Atheros PHY drivers
4 *
Xie Xiaobodcc307e2013-04-10 16:23:39 +08005 * Copyright 2011, 2013 Freescale Semiconductor, Inc.
Andy Fleming60ca78b2011-04-07 21:56:05 -05006 * author Andy Fleming
Michael Walle5d0ea112020-05-07 00:11:57 +02007 * Copyright (c) 2019 Michael Walle <michael@walle.cc>
Andy Fleming60ca78b2011-04-07 21:56:05 -05008 */
Joe Hershberger14b48122018-07-25 12:59:22 -05009#include <common.h>
Andy Fleming60ca78b2011-04-07 21:56:05 -050010#include <phy.h>
Michael Walle5d0ea112020-05-07 00:11:57 +020011#include <dm/device_compat.h>
12#include <linux/bitfield.h>
13#include <dt-bindings/net/qca-ar803x.h>
Andy Fleming60ca78b2011-04-07 21:56:05 -050014
Mugunthan V N3e4537d2016-10-13 19:33:36 +053015#define AR803x_PHY_DEBUG_ADDR_REG 0x1d
16#define AR803x_PHY_DEBUG_DATA_REG 0x1e
17
Michael Walle5d0ea112020-05-07 00:11:57 +020018/* Debug registers */
19#define AR803x_DEBUG_REG_0 0x0
20#define AR803x_RGMII_RX_CLK_DLY BIT(15)
21
Mugunthan V N3e4537d2016-10-13 19:33:36 +053022#define AR803x_DEBUG_REG_5 0x5
Vladimir Oltean23d8b892020-05-07 00:11:49 +020023#define AR803x_RGMII_TX_CLK_DLY BIT(8)
Mugunthan V N3e4537d2016-10-13 19:33:36 +053024
Michael Walle5d0ea112020-05-07 00:11:57 +020025#define AR803x_DEBUG_REG_1F 0x1f
26#define AR803x_PLL_ON BIT(2)
27#define AR803x_RGMII_1V8 BIT(3)
Vladimir Oltean23d8b892020-05-07 00:11:49 +020028
Vladimir Oltean3e7330e2020-05-07 00:11:50 +020029/* CLK_25M register is at MMD 7, address 0x8016 */
30#define AR803x_CLK_25M_SEL_REG 0x8016
Michael Walle5d0ea112020-05-07 00:11:57 +020031
32#define AR803x_CLK_25M_MASK GENMASK(4, 2)
33#define AR803x_CLK_25M_25MHZ_XTAL 0
34#define AR803x_CLK_25M_25MHZ_DSP 1
35#define AR803x_CLK_25M_50MHZ_PLL 2
36#define AR803x_CLK_25M_50MHZ_DSP 3
37#define AR803x_CLK_25M_62_5MHZ_PLL 4
38#define AR803x_CLK_25M_62_5MHZ_DSP 5
39#define AR803x_CLK_25M_125MHZ_PLL 6
40#define AR803x_CLK_25M_125MHZ_DSP 7
41
Vladimir Oltean3e7330e2020-05-07 00:11:50 +020042/* AR8035: Select frequency on CLK_25M pin through bits 4:3 */
43#define AR8035_CLK_25M_FREQ_25M (0 | 0)
44#define AR8035_CLK_25M_FREQ_50M (0 | BIT(3))
45#define AR8035_CLK_25M_FREQ_62M (BIT(4) | 0)
46#define AR8035_CLK_25M_FREQ_125M (BIT(4) | BIT(3))
47#define AR8035_CLK_25M_MASK GENMASK(4, 3)
48
Michael Walle5d0ea112020-05-07 00:11:57 +020049#define AR803x_CLK_25M_DR_MASK GENMASK(8, 7)
50#define AR803x_CLK_25M_DR_FULL 0
51#define AR803x_CLK_25M_DR_HALF 1
52#define AR803x_CLK_25M_DR_QUARTER 2
53
Michael Walle69a107e2020-05-07 00:11:54 +020054#define AR8021_PHY_ID 0x004dd040
55#define AR8031_PHY_ID 0x004dd074
56#define AR8035_PHY_ID 0x004dd072
57
Michael Walle5d0ea112020-05-07 00:11:57 +020058struct ar803x_priv {
59 int flags;
60#define AR803x_FLAG_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
61#define AR803x_FLAG_RGMII_1V8 BIT(1) /* use 1.8V RGMII I/O voltage */
62 u16 clk_25m_reg;
63 u16 clk_25m_mask;
64};
65
Michael Wallefb4a4652020-05-07 00:11:55 +020066static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg)
Vladimir Oltean23d8b892020-05-07 00:11:49 +020067{
Michael Wallefb4a4652020-05-07 00:11:55 +020068 int ret;
Vladimir Oltean23d8b892020-05-07 00:11:49 +020069
Michael Wallefb4a4652020-05-07 00:11:55 +020070 ret = phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
71 reg);
72 if (ret < 0)
73 return ret;
74
75 return phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG);
76}
77
78static int ar803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
79 u16 clear, u16 set)
80{
81 int val;
82
83 val = ar803x_debug_reg_read(phydev, reg);
84 if (val < 0)
85 return val;
86
87 val &= 0xffff;
88 val &= ~clear;
89 val |= set;
90
91 return phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG,
92 val);
93}
94
95static int ar803x_enable_rx_delay(struct phy_device *phydev, bool on)
96{
97 u16 clear = 0, set = 0;
98
Vladimir Oltean23d8b892020-05-07 00:11:49 +020099 if (on)
Michael Wallefb4a4652020-05-07 00:11:55 +0200100 set = AR803x_RGMII_RX_CLK_DLY;
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200101 else
Michael Wallefb4a4652020-05-07 00:11:55 +0200102 clear = AR803x_RGMII_RX_CLK_DLY;
103
104 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_0, clear, set);
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200105}
106
Michael Wallefb4a4652020-05-07 00:11:55 +0200107static int ar803x_enable_tx_delay(struct phy_device *phydev, bool on)
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200108{
Michael Wallefb4a4652020-05-07 00:11:55 +0200109 u16 clear = 0, set = 0;
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200110
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200111 if (on)
Michael Wallefb4a4652020-05-07 00:11:55 +0200112 set = AR803x_RGMII_TX_CLK_DLY;
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200113 else
Michael Wallefb4a4652020-05-07 00:11:55 +0200114 clear = AR803x_RGMII_TX_CLK_DLY;
115
116 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_5, clear, set);
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200117}
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530118
Andy Fleming60ca78b2011-04-07 21:56:05 -0500119static int ar8021_config(struct phy_device *phydev)
120{
Vladimir Oltean1e37f752020-05-07 00:11:52 +0200121 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
122 BMCR_ANENABLE | BMCR_ANRESTART);
123
124 ar803x_enable_tx_delay(phydev, true);
Andy Fleming60ca78b2011-04-07 21:56:05 -0500125
Zhao Qiang04f2ba42013-12-23 15:51:33 +0800126 phydev->supported = phydev->drv->features;
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530127 return 0;
128}
129
Michael Walle376019a2020-05-07 00:11:56 +0200130static int ar803x_delay_config(struct phy_device *phydev)
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530131{
Michael Walle376019a2020-05-07 00:11:56 +0200132 int ret;
133
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530134 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200135 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
Michael Walle376019a2020-05-07 00:11:56 +0200136 ret = ar803x_enable_tx_delay(phydev, true);
Vladimir Oltean3ccbb4b2020-05-07 00:11:51 +0200137 else
Michael Walle376019a2020-05-07 00:11:56 +0200138 ret = ar803x_enable_tx_delay(phydev, false);
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530139
140 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
Vladimir Oltean23d8b892020-05-07 00:11:49 +0200141 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
Michael Walle376019a2020-05-07 00:11:56 +0200142 ret = ar803x_enable_rx_delay(phydev, true);
Vladimir Oltean3ccbb4b2020-05-07 00:11:51 +0200143 else
Michael Walle376019a2020-05-07 00:11:56 +0200144 ret = ar803x_enable_rx_delay(phydev, false);
145
146 return ret;
147}
148
Michael Walle5d0ea112020-05-07 00:11:57 +0200149static int ar803x_regs_config(struct phy_device *phydev)
150{
151 struct ar803x_priv *priv = phydev->priv;
152 u16 set = 0, clear = 0;
153 int val;
154 int ret;
155
156 /* no configuration available */
157 if (!priv)
158 return 0;
159
160 /*
161 * Only supported on the AR8031, AR8035 has strappings for the PLL mode
162 * as well as the RGMII voltage.
163 */
164 if (phydev->drv->uid == AR8031_PHY_ID) {
165 if (priv->flags & AR803x_FLAG_KEEP_PLL_ENABLED)
166 set |= AR803x_PLL_ON;
167 else
168 clear |= AR803x_PLL_ON;
169
170 if (priv->flags & AR803x_FLAG_RGMII_1V8)
171 set |= AR803x_RGMII_1V8;
172 else
173 clear |= AR803x_RGMII_1V8;
174
175 ret = ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_1F, clear,
176 set);
177 if (ret < 0)
178 return ret;
179 }
180
181 /* save the write access if the mask is empty */
182 if (priv->clk_25m_mask) {
183 val = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG);
184 if (val < 0)
185 return val;
186 val &= ~priv->clk_25m_mask;
187 val |= priv->clk_25m_reg;
188 ret = phy_write_mmd(phydev, MDIO_MMD_AN,
189 AR803x_CLK_25M_SEL_REG, val);
190 if (ret < 0)
191 return ret;
192 }
193
194 return 0;
195}
196
197static int ar803x_of_init(struct phy_device *phydev)
198{
199#if defined(CONFIG_DM_ETH)
200 struct ar803x_priv *priv;
201 ofnode node, vddio_reg_node;
202 u32 strength, freq, min_uV, max_uV;
203 int sel;
204
205 node = phy_get_ofnode(phydev);
206 if (!ofnode_valid(node))
207 return -EINVAL;
208
209 priv = malloc(sizeof(*priv));
210 if (!priv)
211 return -ENOMEM;
212 memset(priv, 0, sizeof(*priv));
213
214 phydev->priv = priv;
215
216 debug("%s: found PHY node: %s\n", __func__, ofnode_get_name(node));
217
218 if (ofnode_read_bool(node, "qca,keep-pll-enabled"))
219 priv->flags |= AR803x_FLAG_KEEP_PLL_ENABLED;
220
221 /*
222 * We can't use the regulator framework because the regulator is
223 * a subnode of the PHY. So just read the two properties we are
224 * interested in.
225 */
226 vddio_reg_node = ofnode_find_subnode(node, "vddio-regulator");
227 if (ofnode_valid(vddio_reg_node)) {
228 min_uV = ofnode_read_u32_default(vddio_reg_node,
229 "regulator-min-microvolt", 0);
230 max_uV = ofnode_read_u32_default(vddio_reg_node,
231 "regulator-max-microvolt", 0);
232
233 if (min_uV != max_uV) {
234 free(priv);
235 return -EINVAL;
236 }
237
238 switch (min_uV) {
239 case 1500000:
240 break;
241 case 1800000:
242 priv->flags |= AR803x_FLAG_RGMII_1V8;
243 break;
244 default:
245 free(priv);
246 return -EINVAL;
247 }
248 }
249
250 /*
251 * Get the CLK_25M frequency from the device tree. Only XTAL and PLL
252 * sources are supported right now. There is also the possibilty to use
253 * the DSP as frequency reference, this is used for synchronous
254 * ethernet.
255 */
256 if (!ofnode_read_u32(node, "qca,clk-out-frequency", &freq)) {
257 switch (freq) {
258 case 25000000:
259 sel = AR803x_CLK_25M_25MHZ_XTAL;
260 break;
261 case 50000000:
262 sel = AR803x_CLK_25M_50MHZ_PLL;
263 break;
264 case 62500000:
265 sel = AR803x_CLK_25M_62_5MHZ_PLL;
266 break;
267 case 125000000:
268 sel = AR803x_CLK_25M_125MHZ_PLL;
269 break;
270 default:
271 dev_err(phydev->dev,
272 "invalid qca,clk-out-frequency\n");
273 free(priv);
274 return -EINVAL;
275 }
276
277 priv->clk_25m_mask |= AR803x_CLK_25M_MASK;
278 priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_MASK, sel);
279 /*
280 * Fixup for the AR8035 which only has two bits. The two
281 * remaining bits map to the same frequencies.
282 */
283 if (phydev->drv->uid == AR8035_PHY_ID) {
284 u16 clear = AR803x_CLK_25M_MASK & AR8035_CLK_25M_MASK;
285
286 priv->clk_25m_mask &= ~clear;
287 priv->clk_25m_reg &= ~clear;
288 }
289 }
290
291 if (phydev->drv->uid == AR8031_PHY_ID &&
292 !ofnode_read_u32(node, "qca,clk-out-strength", &strength)) {
293 switch (strength) {
294 case AR803X_STRENGTH_FULL:
295 sel = AR803x_CLK_25M_DR_FULL;
296 break;
297 case AR803X_STRENGTH_HALF:
298 sel = AR803x_CLK_25M_DR_HALF;
299 break;
300 case AR803X_STRENGTH_QUARTER:
301 sel = AR803x_CLK_25M_DR_QUARTER;
302 break;
303 default:
304 dev_err(phydev->dev,
305 "invalid qca,clk-out-strength\n");
306 free(priv);
307 return -EINVAL;
308 }
309 priv->clk_25m_mask |= AR803x_CLK_25M_DR_MASK;
310 priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_DR_MASK, sel);
311 }
312
313 debug("%s: flags=%x clk_25m_reg=%04x clk_25m_mask=%04x\n", __func__,
314 priv->flags, priv->clk_25m_reg, priv->clk_25m_mask);
315#endif
316
317 return 0;
318}
319
Michael Walle376019a2020-05-07 00:11:56 +0200320static int ar8031_config(struct phy_device *phydev)
321{
322 int ret;
323
Michael Walle5d0ea112020-05-07 00:11:57 +0200324 ret = ar803x_of_init(phydev);
325 if (ret < 0)
326 return ret;
327
Michael Walle376019a2020-05-07 00:11:56 +0200328 ret = ar803x_delay_config(phydev);
329 if (ret < 0)
330 return ret;
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530331
Michael Walle5d0ea112020-05-07 00:11:57 +0200332 ret = ar803x_regs_config(phydev);
333 if (ret < 0)
334 return ret;
335
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530336 phydev->supported = phydev->drv->features;
337
338 genphy_config_aneg(phydev);
339 genphy_restart_aneg(phydev);
340
Andy Fleming60ca78b2011-04-07 21:56:05 -0500341 return 0;
342}
343
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800344static int ar8035_config(struct phy_device *phydev)
345{
Michael Walle376019a2020-05-07 00:11:56 +0200346 int ret;
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800347 int regval;
348
Michael Walle5d0ea112020-05-07 00:11:57 +0200349 ret = ar803x_of_init(phydev);
350 if (ret < 0)
351 return ret;
352
Vladimir Oltean3e7330e2020-05-07 00:11:50 +0200353 /* Configure CLK_25M output clock at 125 MHz */
354 regval = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG);
355 regval &= ~AR8035_CLK_25M_MASK; /* No surprises */
356 regval |= AR8035_CLK_25M_FREQ_125M;
357 phy_write_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG, regval);
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800358
Michael Walle376019a2020-05-07 00:11:56 +0200359 ret = ar803x_delay_config(phydev);
360 if (ret < 0)
361 return ret;
Andrea Merello1e3e19f2016-05-26 18:24:28 +0200362
Michael Walle5d0ea112020-05-07 00:11:57 +0200363 ret = ar803x_regs_config(phydev);
364 if (ret < 0)
365 return ret;
366
Xiaobo Xieaa09e682014-04-11 16:03:11 +0800367 phydev->supported = phydev->drv->features;
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800368
Alison Wang5dc3af82016-02-19 15:52:28 +0800369 genphy_config_aneg(phydev);
370 genphy_restart_aneg(phydev);
371
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800372 return 0;
373}
374
Kim Phillips40c2c032012-10-29 13:34:33 +0000375static struct phy_driver AR8021_driver = {
Andy Fleming60ca78b2011-04-07 21:56:05 -0500376 .name = "AR8021",
Michael Walle69a107e2020-05-07 00:11:54 +0200377 .uid = AR8021_PHY_ID,
Michael Wallea5eb6592020-05-07 00:11:53 +0200378 .mask = 0xfffffff0,
Andy Fleming60ca78b2011-04-07 21:56:05 -0500379 .features = PHY_GBIT_FEATURES,
380 .config = ar8021_config,
381 .startup = genphy_startup,
382 .shutdown = genphy_shutdown,
383};
384
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200385static struct phy_driver AR8031_driver = {
Shengzhou Liu76f57c32013-08-08 16:33:35 +0800386 .name = "AR8031/AR8033",
Michael Walle69a107e2020-05-07 00:11:54 +0200387 .uid = AR8031_PHY_ID,
Fabio Estevam2edb6062014-01-03 15:55:59 -0200388 .mask = 0xffffffef,
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200389 .features = PHY_GBIT_FEATURES,
Mugunthan V N3e4537d2016-10-13 19:33:36 +0530390 .config = ar8031_config,
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200391 .startup = genphy_startup,
392 .shutdown = genphy_shutdown,
393};
394
395static struct phy_driver AR8035_driver = {
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800396 .name = "AR8035",
Michael Walle69a107e2020-05-07 00:11:54 +0200397 .uid = AR8035_PHY_ID,
Fabio Estevam2edb6062014-01-03 15:55:59 -0200398 .mask = 0xffffffef,
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800399 .features = PHY_GBIT_FEATURES,
400 .config = ar8035_config,
401 .startup = genphy_startup,
402 .shutdown = genphy_shutdown,
403};
404
Andy Fleming60ca78b2011-04-07 21:56:05 -0500405int phy_atheros_init(void)
406{
407 phy_register(&AR8021_driver);
Heiko Schocher93ac9b82013-06-04 10:58:00 +0200408 phy_register(&AR8031_driver);
Xie Xiaobodcc307e2013-04-10 16:23:39 +0800409 phy_register(&AR8035_driver);
Andy Fleming60ca78b2011-04-07 21:56:05 -0500410
411 return 0;
412}