]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/net/phy/atheros.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / net / phy / atheros.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
9082eeac
AF
2/*
3 * Atheros PHY drivers
4 *
6027384a 5 * Copyright 2011, 2013 Freescale Semiconductor, Inc.
9082eeac 6 * author Andy Fleming
fe6293a8 7 * Copyright (c) 2019 Michael Walle <michael@walle.cc>
9082eeac 8 */
d678a59d 9#include <common.h>
9082eeac 10#include <phy.h>
fe6293a8
MW
11#include <dm/device_compat.h>
12#include <linux/bitfield.h>
cd93d625 13#include <linux/bitops.h>
fe6293a8 14#include <dt-bindings/net/qca-ar803x.h>
9082eeac 15
ce412b79
M
16#define AR803x_PHY_DEBUG_ADDR_REG 0x1d
17#define AR803x_PHY_DEBUG_DATA_REG 0x1e
18
fe6293a8
MW
19/* Debug registers */
20#define AR803x_DEBUG_REG_0 0x0
21#define AR803x_RGMII_RX_CLK_DLY BIT(15)
22
ce412b79 23#define AR803x_DEBUG_REG_5 0x5
29602f9c 24#define AR803x_RGMII_TX_CLK_DLY BIT(8)
ce412b79 25
fe6293a8
MW
26#define AR803x_DEBUG_REG_1F 0x1f
27#define AR803x_PLL_ON BIT(2)
28#define AR803x_RGMII_1V8 BIT(3)
29602f9c 29
a234ae86
VO
30/* CLK_25M register is at MMD 7, address 0x8016 */
31#define AR803x_CLK_25M_SEL_REG 0x8016
fe6293a8
MW
32
33#define AR803x_CLK_25M_MASK GENMASK(4, 2)
34#define AR803x_CLK_25M_25MHZ_XTAL 0
35#define AR803x_CLK_25M_25MHZ_DSP 1
36#define AR803x_CLK_25M_50MHZ_PLL 2
37#define AR803x_CLK_25M_50MHZ_DSP 3
38#define AR803x_CLK_25M_62_5MHZ_PLL 4
39#define AR803x_CLK_25M_62_5MHZ_DSP 5
40#define AR803x_CLK_25M_125MHZ_PLL 6
41#define AR803x_CLK_25M_125MHZ_DSP 7
a234ae86
VO
42#define AR8035_CLK_25M_MASK GENMASK(4, 3)
43
fe6293a8
MW
44#define AR803x_CLK_25M_DR_MASK GENMASK(8, 7)
45#define AR803x_CLK_25M_DR_FULL 0
46#define AR803x_CLK_25M_DR_HALF 1
47#define AR803x_CLK_25M_DR_QUARTER 2
48
30e31931
MW
49#define AR8021_PHY_ID 0x004dd040
50#define AR8031_PHY_ID 0x004dd074
51#define AR8035_PHY_ID 0x004dd072
52
fe6293a8
MW
53struct ar803x_priv {
54 int flags;
55#define AR803x_FLAG_KEEP_PLL_ENABLED BIT(0) /* don't turn off internal PLL */
56#define AR803x_FLAG_RGMII_1V8 BIT(1) /* use 1.8V RGMII I/O voltage */
57 u16 clk_25m_reg;
58 u16 clk_25m_mask;
59};
60
f6ae47be 61static int ar803x_debug_reg_read(struct phy_device *phydev, u16 reg)
29602f9c 62{
f6ae47be
MW
63 int ret;
64
65 ret = phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_ADDR_REG,
66 reg);
67 if (ret < 0)
68 return ret;
69
70 return phy_read(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG);
71}
72
73static int ar803x_debug_reg_mask(struct phy_device *phydev, u16 reg,
74 u16 clear, u16 set)
75{
76 int val;
77
78 val = ar803x_debug_reg_read(phydev, reg);
79 if (val < 0)
80 return val;
81
82 val &= 0xffff;
83 val &= ~clear;
84 val |= set;
85
86 return phy_write(phydev, MDIO_DEVAD_NONE, AR803x_PHY_DEBUG_DATA_REG,
87 val);
88}
89
90static int ar803x_enable_rx_delay(struct phy_device *phydev, bool on)
91{
92 u16 clear = 0, set = 0;
29602f9c 93
29602f9c 94 if (on)
f6ae47be 95 set = AR803x_RGMII_RX_CLK_DLY;
29602f9c 96 else
f6ae47be
MW
97 clear = AR803x_RGMII_RX_CLK_DLY;
98
99 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_0, clear, set);
29602f9c
VO
100}
101
f6ae47be 102static int ar803x_enable_tx_delay(struct phy_device *phydev, bool on)
29602f9c 103{
f6ae47be 104 u16 clear = 0, set = 0;
29602f9c 105
29602f9c 106 if (on)
f6ae47be 107 set = AR803x_RGMII_TX_CLK_DLY;
29602f9c 108 else
f6ae47be
MW
109 clear = AR803x_RGMII_TX_CLK_DLY;
110
111 return ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_5, clear, set);
29602f9c 112}
ce412b79 113
9082eeac
AF
114static int ar8021_config(struct phy_device *phydev)
115{
4d4e4cf7
VO
116 phy_write(phydev, MDIO_DEVAD_NONE, MII_BMCR,
117 BMCR_ANENABLE | BMCR_ANRESTART);
118
119 ar803x_enable_tx_delay(phydev, true);
9082eeac 120
e0d80964 121 phydev->supported = phydev->drv->features;
9082eeac
AF
122 return 0;
123}
124
2b772155 125static int ar803x_delay_config(struct phy_device *phydev)
ce412b79 126{
2b772155
MW
127 int ret;
128
ce412b79 129 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID ||
29602f9c 130 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
2b772155 131 ret = ar803x_enable_tx_delay(phydev, true);
13114f38 132 else
2b772155 133 ret = ar803x_enable_tx_delay(phydev, false);
ce412b79
M
134
135 if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
29602f9c 136 phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
2b772155 137 ret = ar803x_enable_rx_delay(phydev, true);
13114f38 138 else
2b772155
MW
139 ret = ar803x_enable_rx_delay(phydev, false);
140
141 return ret;
142}
143
fe6293a8
MW
144static int ar803x_regs_config(struct phy_device *phydev)
145{
146 struct ar803x_priv *priv = phydev->priv;
147 u16 set = 0, clear = 0;
148 int val;
149 int ret;
150
151 /* no configuration available */
152 if (!priv)
153 return 0;
154
155 /*
156 * Only supported on the AR8031, AR8035 has strappings for the PLL mode
157 * as well as the RGMII voltage.
158 */
159 if (phydev->drv->uid == AR8031_PHY_ID) {
160 if (priv->flags & AR803x_FLAG_KEEP_PLL_ENABLED)
161 set |= AR803x_PLL_ON;
162 else
163 clear |= AR803x_PLL_ON;
164
165 if (priv->flags & AR803x_FLAG_RGMII_1V8)
166 set |= AR803x_RGMII_1V8;
167 else
168 clear |= AR803x_RGMII_1V8;
169
170 ret = ar803x_debug_reg_mask(phydev, AR803x_DEBUG_REG_1F, clear,
171 set);
172 if (ret < 0)
173 return ret;
174 }
175
176 /* save the write access if the mask is empty */
177 if (priv->clk_25m_mask) {
178 val = phy_read_mmd(phydev, MDIO_MMD_AN, AR803x_CLK_25M_SEL_REG);
179 if (val < 0)
180 return val;
181 val &= ~priv->clk_25m_mask;
182 val |= priv->clk_25m_reg;
183 ret = phy_write_mmd(phydev, MDIO_MMD_AN,
184 AR803x_CLK_25M_SEL_REG, val);
185 if (ret < 0)
186 return ret;
187 }
188
189 return 0;
190}
191
192static int ar803x_of_init(struct phy_device *phydev)
193{
fe6293a8
MW
194 struct ar803x_priv *priv;
195 ofnode node, vddio_reg_node;
196 u32 strength, freq, min_uV, max_uV;
197 int sel;
198
199 node = phy_get_ofnode(phydev);
200 if (!ofnode_valid(node))
5faf161d 201 return 0;
fe6293a8
MW
202
203 priv = malloc(sizeof(*priv));
204 if (!priv)
205 return -ENOMEM;
206 memset(priv, 0, sizeof(*priv));
207
208 phydev->priv = priv;
209
210 debug("%s: found PHY node: %s\n", __func__, ofnode_get_name(node));
211
212 if (ofnode_read_bool(node, "qca,keep-pll-enabled"))
213 priv->flags |= AR803x_FLAG_KEEP_PLL_ENABLED;
214
215 /*
216 * We can't use the regulator framework because the regulator is
217 * a subnode of the PHY. So just read the two properties we are
218 * interested in.
219 */
220 vddio_reg_node = ofnode_find_subnode(node, "vddio-regulator");
221 if (ofnode_valid(vddio_reg_node)) {
222 min_uV = ofnode_read_u32_default(vddio_reg_node,
223 "regulator-min-microvolt", 0);
224 max_uV = ofnode_read_u32_default(vddio_reg_node,
225 "regulator-max-microvolt", 0);
226
227 if (min_uV != max_uV) {
228 free(priv);
229 return -EINVAL;
230 }
231
232 switch (min_uV) {
233 case 1500000:
234 break;
235 case 1800000:
236 priv->flags |= AR803x_FLAG_RGMII_1V8;
237 break;
238 default:
239 free(priv);
240 return -EINVAL;
241 }
242 }
243
244 /*
245 * Get the CLK_25M frequency from the device tree. Only XTAL and PLL
246 * sources are supported right now. There is also the possibilty to use
247 * the DSP as frequency reference, this is used for synchronous
248 * ethernet.
249 */
250 if (!ofnode_read_u32(node, "qca,clk-out-frequency", &freq)) {
251 switch (freq) {
252 case 25000000:
253 sel = AR803x_CLK_25M_25MHZ_XTAL;
254 break;
255 case 50000000:
256 sel = AR803x_CLK_25M_50MHZ_PLL;
257 break;
258 case 62500000:
259 sel = AR803x_CLK_25M_62_5MHZ_PLL;
260 break;
261 case 125000000:
262 sel = AR803x_CLK_25M_125MHZ_PLL;
263 break;
264 default:
265 dev_err(phydev->dev,
266 "invalid qca,clk-out-frequency\n");
267 free(priv);
268 return -EINVAL;
269 }
270
271 priv->clk_25m_mask |= AR803x_CLK_25M_MASK;
272 priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_MASK, sel);
273 /*
274 * Fixup for the AR8035 which only has two bits. The two
275 * remaining bits map to the same frequencies.
276 */
fe6293a8 277
338d9b03
FE
278 if (phydev->drv->uid == AR8035_PHY_ID) {
279 priv->clk_25m_reg &= AR8035_CLK_25M_MASK;
280 priv->clk_25m_mask &= AR8035_CLK_25M_MASK;
fe6293a8
MW
281 }
282 }
283
284 if (phydev->drv->uid == AR8031_PHY_ID &&
285 !ofnode_read_u32(node, "qca,clk-out-strength", &strength)) {
286 switch (strength) {
287 case AR803X_STRENGTH_FULL:
288 sel = AR803x_CLK_25M_DR_FULL;
289 break;
290 case AR803X_STRENGTH_HALF:
291 sel = AR803x_CLK_25M_DR_HALF;
292 break;
293 case AR803X_STRENGTH_QUARTER:
294 sel = AR803x_CLK_25M_DR_QUARTER;
295 break;
296 default:
297 dev_err(phydev->dev,
298 "invalid qca,clk-out-strength\n");
299 free(priv);
300 return -EINVAL;
301 }
302 priv->clk_25m_mask |= AR803x_CLK_25M_DR_MASK;
303 priv->clk_25m_reg |= FIELD_PREP(AR803x_CLK_25M_DR_MASK, sel);
304 }
305
306 debug("%s: flags=%x clk_25m_reg=%04x clk_25m_mask=%04x\n", __func__,
307 priv->flags, priv->clk_25m_reg, priv->clk_25m_mask);
fe6293a8
MW
308
309 return 0;
310}
311
8737c65f 312static int ar803x_config(struct phy_device *phydev)
6027384a 313{
2b772155 314 int ret;
6027384a 315
fe6293a8
MW
316 ret = ar803x_of_init(phydev);
317 if (ret < 0)
318 return ret;
319
2b772155
MW
320 ret = ar803x_delay_config(phydev);
321 if (ret < 0)
322 return ret;
2ec4d10b 323
fe6293a8
MW
324 ret = ar803x_regs_config(phydev);
325 if (ret < 0)
326 return ret;
327
02aa4c53 328 phydev->supported = phydev->drv->features;
6027384a 329
903d384d
AW
330 genphy_config_aneg(phydev);
331 genphy_restart_aneg(phydev);
332
6027384a
XX
333 return 0;
334}
335
fba31ab9 336U_BOOT_PHY_DRIVER(AR8021) = {
9082eeac 337 .name = "AR8021",
30e31931 338 .uid = AR8021_PHY_ID,
f4d48f43 339 .mask = 0xfffffff0,
9082eeac
AF
340 .features = PHY_GBIT_FEATURES,
341 .config = ar8021_config,
342 .startup = genphy_startup,
343 .shutdown = genphy_shutdown,
344};
345
fba31ab9 346U_BOOT_PHY_DRIVER(AR8031) = {
626ee1e3 347 .name = "AR8031/AR8033",
30e31931 348 .uid = AR8031_PHY_ID,
f66e3ded 349 .mask = 0xffffffef,
433a2c53 350 .features = PHY_GBIT_FEATURES,
8737c65f 351 .config = ar803x_config,
433a2c53
HS
352 .startup = genphy_startup,
353 .shutdown = genphy_shutdown,
354};
355
fba31ab9 356U_BOOT_PHY_DRIVER(AR8035) = {
6027384a 357 .name = "AR8035",
30e31931 358 .uid = AR8035_PHY_ID,
f66e3ded 359 .mask = 0xffffffef,
6027384a 360 .features = PHY_GBIT_FEATURES,
8737c65f 361 .config = ar803x_config,
6027384a
XX
362 .startup = genphy_startup,
363 .shutdown = genphy_shutdown,
364};