blob: 9e0083ca7896e800eb91ba53f9853a6671817b29 [file] [log] [blame]
Grygorii Strashkocf56fb72018-10-31 16:21:43 -05001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * CPSW MDIO generic driver for TI AMxx/K2x/EMAC devices.
4 *
Nishanth Menoneaa39c62023-11-01 15:56:03 -05005 * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
Grygorii Strashkocf56fb72018-10-31 16:21:43 -05006 */
7
Roger Quadrosfced6b62024-02-28 12:35:27 +02008#include <clk.h>
Roger Quadrosfced6b62024-02-28 12:35:27 +02009#include <dm/device_compat.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070011#include <malloc.h>
Roger Quadrosfced6b62024-02-28 12:35:27 +020012#include <phy.h>
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050013#include <asm/io.h>
14#include <miiphy.h>
Roger Quadrosfced6b62024-02-28 12:35:27 +020015#include <soc.h>
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050016#include <wait_bit.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060017#include <linux/bitops.h>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050019
20struct cpsw_mdio_regs {
21 u32 version;
22 u32 control;
23#define CONTROL_IDLE BIT(31)
24#define CONTROL_ENABLE BIT(30)
25#define CONTROL_FAULT BIT(19)
26#define CONTROL_FAULT_ENABLE BIT(18)
27#define CONTROL_DIV_MASK GENMASK(15, 0)
Roger Quadrosfced6b62024-02-28 12:35:27 +020028#define CONTROL_MAX_DIV CONTROL_DIV_MASK
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050029
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053030#define MDIO_MAN_MDCLK_O BIT(2)
31#define MDIO_MAN_OE BIT(1)
32#define MDIO_MAN_PIN BIT(0)
33#define MDIO_MANUALMODE BIT(31)
34
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050035 u32 alive;
36 u32 link;
37 u32 linkintraw;
38 u32 linkintmasked;
39 u32 __reserved_0[2];
40 u32 userintraw;
41 u32 userintmasked;
42 u32 userintmaskset;
43 u32 userintmaskclr;
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053044 u32 manualif;
45 u32 poll;
46 u32 __reserved_1[18];
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050047
48 struct {
49 u32 access;
50 u32 physel;
51#define USERACCESS_GO BIT(31)
52#define USERACCESS_WRITE BIT(30)
53#define USERACCESS_ACK BIT(29)
54#define USERACCESS_READ (0)
55#define USERACCESS_PHY_REG_SHIFT (21)
56#define USERACCESS_PHY_ADDR_SHIFT (16)
57#define USERACCESS_DATA GENMASK(15, 0)
Ulf Samuelssonfaa537a2023-02-07 09:25:27 +010058 } user[2];
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050059};
60
61#define CPSW_MDIO_DIV_DEF 0xff
62#define PHY_REG_MASK 0x1f
63#define PHY_ID_MASK 0x1f
64
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053065#define MDIO_BITRANGE 0x8000
66#define C22_READ_PATTERN 0x6
67#define C22_WRITE_PATTERN 0x5
68#define C22_BITRANGE 0x8
69#define PHY_BITRANGE 0x10
70#define PHY_DATA_BITRANGE 0x8000
71
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050072/*
73 * This timeout definition is a worst-case ultra defensive measure against
74 * unexpected controller lock ups. Ideally, we should never ever hit this
75 * scenario in practice.
76 */
77#define CPSW_MDIO_TIMEOUT 100 /* msecs */
78
Roger Quadrosfced6b62024-02-28 12:35:27 +020079#define CPSW_MDIO_DEF_BUS_FREQ 2200000 /* 2.2 MHz */
80
Ravi Gunasekaran40cea492022-09-22 15:21:23 +053081enum cpsw_mdio_manual {
82 MDIO_PIN = 0,
83 MDIO_OE,
84 MDIO_MDCLK,
85};
86
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050087struct cpsw_mdio {
88 struct cpsw_mdio_regs *regs;
89 struct mii_dev *bus;
90 int div;
Roger Quadrosfced6b62024-02-28 12:35:27 +020091 bool manual_mode;
92 struct clk clk;
93 unsigned long bus_freq;
Grygorii Strashkocf56fb72018-10-31 16:21:43 -050094};
95
Roger Quadrosfced6b62024-02-28 12:35:27 +020096static int cpsw_mdio_enable(struct cpsw_mdio *data)
97{
98 int ret;
99
100 /* set enable and clock divider */
101 writel(data->div | CONTROL_ENABLE, &data->regs->control);
102 ret = wait_for_bit_le32(&data->regs->control,
103 CONTROL_IDLE, false, CPSW_MDIO_TIMEOUT, true);
104 if (ret)
105 return ret;
106
107 /*
108 * wait for scan logic to settle:
109 * the scan time consists of (a) a large fixed component, and (b) a
110 * small component that varies with the mii bus frequency. These
111 * were estimated using measurements at 1.1 and 2.2 MHz on tnetv107x
112 * silicon. Since the effect of (b) was found to be largely
113 * negligible, we keep things simple here.
114 */
115 mdelay(1);
116
117 return 0;
118}
119
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530120static void cpsw_mdio_disable(struct cpsw_mdio *mdio)
121{
122 u32 reg;
123 /* Disable MDIO state machine */
124 reg = readl(&mdio->regs->control);
125 reg &= ~CONTROL_ENABLE;
126
127 writel(reg, &mdio->regs->control);
128}
129
130static void cpsw_mdio_enable_manual_mode(struct cpsw_mdio *mdio)
131{
132 u32 reg;
133
134 /* set manual mode */
135 reg = readl(&mdio->regs->poll);
136 reg |= MDIO_MANUALMODE;
137
138 writel(reg, &mdio->regs->poll);
139}
140
141static void cpsw_mdio_sw_set_bit(struct cpsw_mdio *mdio,
142 enum cpsw_mdio_manual bit)
143{
144 u32 reg;
145
146 reg = readl(&mdio->regs->manualif);
147
148 switch (bit) {
149 case MDIO_OE:
150 reg |= MDIO_MAN_OE;
151 writel(reg, &mdio->regs->manualif);
152 break;
153 case MDIO_PIN:
154 reg |= MDIO_MAN_PIN;
155 writel(reg, &mdio->regs->manualif);
156 break;
157 case MDIO_MDCLK:
158 reg |= MDIO_MAN_MDCLK_O;
159 writel(reg, &mdio->regs->manualif);
160 break;
161 default:
162 break;
163 };
164}
165
166static void cpsw_mdio_sw_clr_bit(struct cpsw_mdio *mdio,
167 enum cpsw_mdio_manual bit)
168{
169 u32 reg;
170
171 reg = readl(&mdio->regs->manualif);
172
173 switch (bit) {
174 case MDIO_OE:
175 reg &= ~MDIO_MAN_OE;
176 writel(reg, &mdio->regs->manualif);
177 break;
178 case MDIO_PIN:
179 reg &= ~MDIO_MAN_PIN;
180 writel(reg, &mdio->regs->manualif);
181 break;
182 case MDIO_MDCLK:
183 reg = readl(&mdio->regs->manualif);
184 reg &= ~MDIO_MAN_MDCLK_O;
185 writel(reg, &mdio->regs->manualif);
186 break;
187 default:
188 break;
189 };
190}
191
192static int cpsw_mdio_test_man_bit(struct cpsw_mdio *mdio,
193 enum cpsw_mdio_manual bit)
194{
195 u32 reg;
196
197 reg = readl(&mdio->regs->manualif);
198 return test_bit(bit, &reg);
199}
200
201static void cpsw_mdio_toggle_man_bit(struct cpsw_mdio *mdio,
202 enum cpsw_mdio_manual bit)
203{
204 cpsw_mdio_sw_clr_bit(mdio, bit);
205 cpsw_mdio_sw_set_bit(mdio, bit);
206}
207
208static void cpsw_mdio_man_send_pattern(struct cpsw_mdio *mdio,
209 u32 bitrange, u32 val)
210{
211 u32 i;
212
213 for (i = bitrange; i; i = i >> 1) {
214 if (i & val)
215 cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
216 else
217 cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
218
219 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
220 }
221}
222
223static void cpsw_mdio_sw_preamble(struct cpsw_mdio *mdio)
224{
225 u32 i;
226
227 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
228
229 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
230 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
231 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
232 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
233
234 for (i = 0; i < 32; i++) {
235 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
236 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
237 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
238 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
239 }
240}
241
Roger Quadrosfced6b62024-02-28 12:35:27 +0200242#if defined(CONFIG_DM_MDIO)
243#define MII_TO_CPSW_MDIO(bus) (dev_get_priv((struct udevice *)(bus)->priv))
244#else
245#define MII_TO_CPSW_MDIO(bus) ((bus)->priv)
246#endif
247
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530248static int cpsw_mdio_sw_read(struct mii_dev *bus, int phy_id,
249 int dev_addr, int phy_reg)
250{
Roger Quadrosfced6b62024-02-28 12:35:27 +0200251 struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530252 u32 reg, i;
253 u8 ack;
254
255 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
256 return -EINVAL;
257
258 cpsw_mdio_disable(mdio);
259 cpsw_mdio_enable_manual_mode(mdio);
260 cpsw_mdio_sw_preamble(mdio);
261
262 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
263 cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
264
265 /* Issue clause 22 MII read function {0,1,1,0} */
266 cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_READ_PATTERN);
267
268 /* Send the device number MSB first */
269 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
270
271 /* Send the register number MSB first */
272 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
273
274 /* Send turn around cycles */
275 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
276
277 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
278
279 ack = cpsw_mdio_test_man_bit(mdio, MDIO_PIN);
280 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
281
282 reg = 0;
283 if (ack == 0) {
284 for (i = MDIO_BITRANGE; i; i = i >> 1) {
285 if (cpsw_mdio_test_man_bit(mdio, MDIO_PIN))
286 reg |= i;
287
288 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
289 }
290 } else {
291 for (i = MDIO_BITRANGE; i; i = i >> 1)
292 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
293
294 reg = 0xFFFF;
295 }
296
297 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
298 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
299 cpsw_mdio_sw_set_bit(mdio, MDIO_MDCLK);
300 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
301
302 return reg;
303}
304
305static int cpsw_mdio_sw_write(struct mii_dev *bus, int phy_id,
306 int dev_addr, int phy_reg, u16 phy_data)
307{
Roger Quadrosfced6b62024-02-28 12:35:27 +0200308 struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530309
310 if ((phy_reg & ~PHY_REG_MASK) || (phy_id & ~PHY_ID_MASK))
311 return -EINVAL;
312
313 cpsw_mdio_disable(mdio);
314 cpsw_mdio_enable_manual_mode(mdio);
315 cpsw_mdio_sw_preamble(mdio);
316
317 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
318 cpsw_mdio_sw_set_bit(mdio, MDIO_OE);
319
320 /* Issue clause 22 MII write function {0,1,0,1} */
321 cpsw_mdio_man_send_pattern(mdio, C22_BITRANGE, C22_WRITE_PATTERN);
322
323 /* Send the device number MSB first */
324 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_id);
325
326 /* Send the register number MSB first */
327 cpsw_mdio_man_send_pattern(mdio, PHY_BITRANGE, phy_reg);
328
329 /* set turn-around cycles */
330 cpsw_mdio_sw_set_bit(mdio, MDIO_PIN);
331 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
332 cpsw_mdio_sw_clr_bit(mdio, MDIO_PIN);
333 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
334
335 /* Send Register data MSB first */
336 cpsw_mdio_man_send_pattern(mdio, PHY_DATA_BITRANGE, phy_data);
337 cpsw_mdio_sw_clr_bit(mdio, MDIO_OE);
338
339 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
340 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
341 cpsw_mdio_sw_clr_bit(mdio, MDIO_MDCLK);
342 cpsw_mdio_toggle_man_bit(mdio, MDIO_MDCLK);
343
344 return 0;
345}
346
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500347/* wait until hardware is ready for another user access */
348static int cpsw_mdio_wait_for_user_access(struct cpsw_mdio *mdio)
349{
350 return wait_for_bit_le32(&mdio->regs->user[0].access,
351 USERACCESS_GO, false,
352 CPSW_MDIO_TIMEOUT, false);
353}
354
355static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
356 int dev_addr, int phy_reg)
357{
Roger Quadrosfced6b62024-02-28 12:35:27 +0200358 struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500359 int data, ret;
360 u32 reg;
361
362 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
363 return -EINVAL;
364
365 ret = cpsw_mdio_wait_for_user_access(mdio);
366 if (ret)
367 return ret;
368 reg = (USERACCESS_GO | USERACCESS_READ |
369 (phy_reg << USERACCESS_PHY_REG_SHIFT) |
370 (phy_id << USERACCESS_PHY_ADDR_SHIFT));
371 writel(reg, &mdio->regs->user[0].access);
372 ret = cpsw_mdio_wait_for_user_access(mdio);
373 if (ret)
374 return ret;
375
376 reg = readl(&mdio->regs->user[0].access);
377 data = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -1;
378 return data;
379}
380
381static int cpsw_mdio_write(struct mii_dev *bus, int phy_id, int dev_addr,
382 int phy_reg, u16 data)
383{
Roger Quadrosfced6b62024-02-28 12:35:27 +0200384 struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500385 u32 reg;
386 int ret;
387
388 if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
389 return -EINVAL;
390
391 ret = cpsw_mdio_wait_for_user_access(mdio);
392 if (ret)
393 return ret;
394 reg = (USERACCESS_GO | USERACCESS_WRITE |
395 (phy_reg << USERACCESS_PHY_REG_SHIFT) |
396 (phy_id << USERACCESS_PHY_ADDR_SHIFT) |
397 (data & USERACCESS_DATA));
398 writel(reg, &mdio->regs->user[0].access);
399
400 return cpsw_mdio_wait_for_user_access(mdio);
401}
402
Roger Quadrosfced6b62024-02-28 12:35:27 +0200403#if !defined(CONFIG_MDIO_TI_CPSW)
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500404u32 cpsw_mdio_get_alive(struct mii_dev *bus)
405{
Roger Quadrosfced6b62024-02-28 12:35:27 +0200406 struct cpsw_mdio *mdio = MII_TO_CPSW_MDIO(bus);
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500407 u32 val;
408
Ulf Samuelssonfaa537a2023-02-07 09:25:27 +0100409 val = readl(&mdio->regs->alive);
410 return val & GENMASK(7, 0);
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500411}
412
Keerthy21deb9b2019-07-09 10:30:33 +0530413struct mii_dev *cpsw_mdio_init(const char *name, phys_addr_t mdio_base,
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530414 u32 bus_freq, int fck_freq, bool manual_mode)
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500415{
416 struct cpsw_mdio *cpsw_mdio;
417 int ret;
418
419 cpsw_mdio = calloc(1, sizeof(*cpsw_mdio));
420 if (!cpsw_mdio) {
421 debug("failed to alloc cpsw_mdio\n");
422 return NULL;
423 }
424
425 cpsw_mdio->bus = mdio_alloc();
426 if (!cpsw_mdio->bus) {
427 debug("failed to alloc mii bus\n");
428 free(cpsw_mdio);
429 return NULL;
430 }
431
Keerthy21deb9b2019-07-09 10:30:33 +0530432 cpsw_mdio->regs = (struct cpsw_mdio_regs *)(uintptr_t)mdio_base;
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500433
434 if (!bus_freq || !fck_freq)
435 cpsw_mdio->div = CPSW_MDIO_DIV_DEF;
436 else
437 cpsw_mdio->div = (fck_freq / bus_freq) - 1;
438 cpsw_mdio->div &= CONTROL_DIV_MASK;
Roger Quadrosfced6b62024-02-28 12:35:27 +0200439 ret = cpsw_mdio_enable(cpsw_mdio);
440 if (ret) {
441 debug("mdio_enable failed: %d\n", ret);
442 goto free_bus;
443 }
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500444
Ravi Gunasekaran40cea492022-09-22 15:21:23 +0530445 if (manual_mode) {
446 cpsw_mdio->bus->read = cpsw_mdio_sw_read;
447 cpsw_mdio->bus->write = cpsw_mdio_sw_write;
448 } else {
449 cpsw_mdio->bus->read = cpsw_mdio_read;
450 cpsw_mdio->bus->write = cpsw_mdio_write;
451 }
452
Grygorii Strashkocf56fb72018-10-31 16:21:43 -0500453 cpsw_mdio->bus->priv = cpsw_mdio;
454 snprintf(cpsw_mdio->bus->name, sizeof(cpsw_mdio->bus->name), name);
455
456 ret = mdio_register(cpsw_mdio->bus);
457 if (ret < 0) {
458 debug("failed to register mii bus\n");
459 goto free_bus;
460 }
461
462 return cpsw_mdio->bus;
463
464free_bus:
465 mdio_free(cpsw_mdio->bus);
466 free(cpsw_mdio);
467 return NULL;
468}
469
470void cpsw_mdio_free(struct mii_dev *bus)
471{
472 struct cpsw_mdio *mdio = bus->priv;
473 u32 reg;
474
475 /* disable mdio */
476 reg = readl(&mdio->regs->control);
477 reg &= ~CONTROL_ENABLE;
478 writel(reg, &mdio->regs->control);
479
480 mdio_unregister(bus);
481 mdio_free(bus);
482 free(mdio);
483}
Roger Quadrosfced6b62024-02-28 12:35:27 +0200484
485#else
486
487static int cpsw_mdio_init_clk(struct cpsw_mdio *data)
488{
489 u32 mdio_in, div;
490
491 mdio_in = clk_get_rate(&data->clk);
492 div = (mdio_in / data->bus_freq) - 1;
493 if (div > CONTROL_MAX_DIV)
494 div = CONTROL_MAX_DIV;
495
496 data->div = div;
497 return cpsw_mdio_enable(data);
498}
499
500static int cpsw_mdio_bus_read(struct udevice *dev, int addr,
501 int devad, int reg)
502{
503 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
504 NULL;
505 struct cpsw_mdio *priv = dev_get_priv(dev);
506
507 if (pdata && pdata->mii_bus) {
508 if (priv->manual_mode)
509 return cpsw_mdio_sw_read(pdata->mii_bus, addr, devad, reg);
510 else
511 return cpsw_mdio_read(pdata->mii_bus, addr, devad, reg);
512 }
513
514 return -1;
515}
516
517static int cpsw_mdio_bus_write(struct udevice *dev, int addr,
518 int devad, int reg, u16 val)
519{
520 struct mdio_perdev_priv *pdata = (dev) ? dev_get_uclass_priv(dev) :
521 NULL;
522 struct cpsw_mdio *priv = dev_get_priv(dev);
523
524 if (pdata && pdata->mii_bus) {
525 if (priv->manual_mode)
526 return cpsw_mdio_sw_write(pdata->mii_bus, addr, devad, reg, val);
527 else
528 return cpsw_mdio_write(pdata->mii_bus, addr, devad, reg, val);
529 }
530
531 return -1;
532}
533
534static const struct mdio_ops cpsw_mdio_ops = {
535 .read = cpsw_mdio_bus_read,
536 .write = cpsw_mdio_bus_write,
537};
538
539static const struct soc_attr k3_mdio_soc_data[] = {
540 { .family = "AM62X", .revision = "SR1.0" },
541 { .family = "AM64X", .revision = "SR1.0" },
542 { .family = "AM64X", .revision = "SR2.0" },
543 { .family = "AM65X", .revision = "SR1.0" },
544 { .family = "AM65X", .revision = "SR2.0" },
545 { .family = "J7200", .revision = "SR1.0" },
546 { .family = "J7200", .revision = "SR2.0" },
547 { .family = "J721E", .revision = "SR1.0" },
548 { .family = "J721E", .revision = "SR1.1" },
549 { .family = "J721S2", .revision = "SR1.0" },
550 { /* sentinel */ },
551};
552
553static const struct udevice_id cpsw_mdio_ids[] = {
554 { .compatible = "ti,davinci_mdio", },
555 { .compatible = "ti,cpsw-mdio", },
556 { /* sentinel */ },
557};
558
559static int cpsw_mdio_probe(struct udevice *dev)
560{
561 struct cpsw_mdio *priv = dev_get_priv(dev);
562 int ret;
563
564 if (!priv) {
565 dev_err(dev, "dev_get_priv(dev %p) = NULL\n", dev);
566 return -ENOMEM;
567 }
568
569 priv->regs = dev_remap_addr(dev);
570
571 if (soc_device_match(k3_mdio_soc_data))
572 priv->manual_mode = true;
573
574 ret = clk_get_by_name(dev, "fck", &priv->clk);
575 if (ret) {
576 dev_err(dev, "failed to get clock %d\n", ret);
577 return ret;
578 }
579
580 priv->bus_freq = dev_read_u32_default(dev, "bus_freq",
581 CPSW_MDIO_DEF_BUS_FREQ);
582 ret = cpsw_mdio_init_clk(priv);
583 if (ret) {
584 dev_err(dev, "init clock failed: %d\n", ret);
585 return ret;
586 }
587
588 return 0;
589}
590
591static int cpsw_mdio_remove(struct udevice *dev)
592{
593 struct cpsw_mdio *priv = dev_get_priv(dev);
594
595 cpsw_mdio_disable(priv);
596
597 return 0;
598}
599
600U_BOOT_DRIVER(cpsw_mdio) = {
601 .name = "cpsw_mdio",
602 .id = UCLASS_MDIO,
603 .of_match = cpsw_mdio_ids,
604 .probe = cpsw_mdio_probe,
605 .remove = cpsw_mdio_remove,
606 .ops = &cpsw_mdio_ops,
607 .priv_auto = sizeof(struct cpsw_mdio),
608};
609#endif /* CONFIG_MDIO_TI_CPSW */