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