1 /*
2 * Copyright (c) 2006-2024 RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-09-27 wangqiang first version
9 * 2024-10-08 zhujiale add phy v2.0
10 */
11 #include <stddef.h>
12 #include <rthw.h>
13 #include <rtdevice.h>
14 #define DBG_TAG "rtdm.phy"
15 #define DBG_LVL DBG_INFO
16 #include <rtdbg.h>
17
18 #ifdef RT_USING_PHY
19
phy_device_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t count)20 static rt_ssize_t phy_device_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t count)
21 {
22 struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data;
23 struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer;
24 return phy->bus->ops->read(phy->bus, phy->addr, msg->reg, &(msg->value), 4);
25 }
phy_device_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t count)26 static rt_ssize_t phy_device_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t count)
27 {
28 struct rt_phy_device *phy = (struct rt_phy_device *)dev->user_data;
29 struct rt_phy_msg *msg = (struct rt_phy_msg *)buffer;
30 return phy->bus->ops->write(phy->bus, phy->addr, msg->reg, &(msg->value), 4);
31 }
32
33 #ifdef RT_USING_DEVICE_OPS
34 const static struct rt_device_ops phy_ops =
35 {
36 RT_NULL,
37 RT_NULL,
38 RT_NULL,
39 phy_device_read,
40 phy_device_write,
41 RT_NULL,
42 };
43 #endif
44
45 /*
46 * phy device register
47 */
rt_hw_phy_register(struct rt_phy_device * phy,const char * name)48 rt_err_t rt_hw_phy_register(struct rt_phy_device *phy, const char *name)
49 {
50 rt_err_t ret;
51 struct rt_device *device;
52
53 device = &(phy->parent);
54
55 device->type = RT_Device_Class_PHY;
56 device->rx_indicate = RT_NULL;
57 device->tx_complete = RT_NULL;
58
59 #ifdef RT_USING_DEVICE_OPS
60 device->ops = &phy_ops;
61 #else
62 device->init = NULL;
63 device->open = NULL;
64 device->close = NULL;
65 device->read = phy_device_read;
66 device->write = phy_device_write;
67 device->control = NULL;
68 #endif
69 device->user_data = phy;
70
71 /* register a character device */
72 ret = rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
73
74 return ret;
75 }
76 #endif
77
78 #ifdef RT_USING_PHY_V2
rt_phy_set_supported(struct rt_phy_device * phydev,rt_uint32_t max_speed)79 int rt_phy_set_supported(struct rt_phy_device *phydev, rt_uint32_t max_speed)
80 {
81 phydev->supported &= RT_PHY_DEFAULT_FEATURES;
82
83 switch (max_speed)
84 {
85 default:
86 return -ENOTSUP;
87 case SPEED_1000:
88 phydev->supported |= RT_PHY_1000BT_FEATURES;
89 case SPEED_100:
90 phydev->supported |= RT_PHY_100BT_FEATURES;
91 case SPEED_10:
92 phydev->supported |= RT_PHY_10BT_FEATURES;
93 }
94
95 return 0;
96 }
97
rt_phy_read(struct rt_phy_device * phydev,int devad,int regnum)98 int rt_phy_read(struct rt_phy_device *phydev, int devad, int regnum)
99 {
100 struct mii_bus *bus = phydev->bus;
101 if(phydev->is_c45)
102 {
103 if(bus->read_c45)
104 return bus->read_c45(bus, phydev->addr, devad, regnum);
105 }
106
107 if( bus && bus->read )
108 return bus->read(bus, phydev->addr, devad, regnum);
109
110 LOG_D("no read function\n");
111 return -1;
112 }
113
rt_phy_write(struct rt_phy_device * phydev,int devad,int regnum,rt_uint16_t val)114 int rt_phy_write(struct rt_phy_device *phydev, int devad, int regnum, rt_uint16_t val)
115 {
116 struct mii_bus *bus = phydev->bus;
117 if(phydev->is_c45)
118 {
119 if(bus->write_c45)
120 return bus->write_c45(bus, phydev->addr, devad, regnum, val);
121 }
122 if( bus && bus->write )
123 return bus->write(bus, phydev->addr, devad, regnum, val);
124
125 LOG_D("no write function\n");
126 return -1;
127 }
128
rt_phy_startup(struct rt_phy_device * phydev)129 int rt_phy_startup(struct rt_phy_device *phydev)
130 {
131 if(!phydev->drv)
132 {
133 LOG_D("PHY device hace no driver\n");
134 return -1;
135 }
136
137 if (phydev->drv->startup)
138 return phydev->drv->startup(phydev);
139
140 LOG_D("phy startup err\n");
141 return -1;
142 }
143
rt_phy_config(struct rt_phy_device * phydev)144 int rt_phy_config(struct rt_phy_device *phydev)
145 {
146 if(!phydev->drv)
147 {
148 LOG_D("PHY device hace no driver\n");
149 return -1;
150 }
151
152 if (phydev->drv->config)
153 return phydev->drv->config(phydev);
154
155 LOG_D("no config function\n");
156 return -1;
157 }
158
rt_phy_shutdown(struct rt_phy_device * phydev)159 int rt_phy_shutdown(struct rt_phy_device *phydev)
160 {
161 if(!phydev->drv)
162 {
163 LOG_D("PHY device hace no driver\n");
164 return -1;
165 }
166
167 if (phydev->drv->shutdown)
168 phydev->drv->shutdown(phydev);
169
170 LOG_D("no shutdown function\n");
171 return -1;
172 }
173
rt_phy_mmd_start_indirect(struct rt_phy_device * phydev,int devad,int regnum)174 void rt_phy_mmd_start_indirect(struct rt_phy_device *phydev, int devad, int regnum)
175 {
176 /* Write the desired MMD Devad */
177 rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, RT_MII_MMD_CTRL, devad);
178
179 /* Write the desired MMD register address */
180 rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, RT_MII_MMD_DATA, regnum);
181
182 /* Select the Function : DATA with no post increment */
183 rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, RT_MII_MMD_CTRL,
184 (devad | RT_MII_MMD_CTRL_NOINCR));
185 }
186
rt_phy_read_mmd(struct rt_phy_device * phydev,int devad,int regnum)187 int rt_phy_read_mmd(struct rt_phy_device *phydev, int devad, int regnum)
188 {
189 struct rt_phy_driver *drv = phydev->drv;
190
191 if (regnum > (rt_uint16_t)~0 || devad > 32 || !drv)
192 return -EINVAL;
193
194 if (drv->read_mmd)
195 return drv->read_mmd(phydev, devad, regnum);
196
197 if ((drv->features & RT_PHY_10G_FEATURES) == RT_PHY_10G_FEATURES ||
198 devad == RT_MDIO_DEVAD_NONE || !devad)
199 return rt_phy_read(phydev, devad, regnum);
200
201 rt_phy_mmd_start_indirect(phydev, devad, regnum);
202
203 return rt_phy_read(phydev, RT_MDIO_DEVAD_NONE, RT_MII_MMD_DATA);
204 }
205
rt_phy_write_mmd(struct rt_phy_device * phydev,int devad,int regnum,rt_uint16_t val)206 int rt_phy_write_mmd(struct rt_phy_device *phydev, int devad, int regnum, rt_uint16_t val)
207 {
208 struct rt_phy_driver *drv = phydev->drv;
209
210 if (regnum > (rt_uint16_t)~0 || devad > 32 || !drv)
211 return -EINVAL;
212
213 if (drv->write_mmd)
214 return drv->write_mmd(phydev, devad, regnum, val);
215
216 if ((drv->features & RT_PHY_10G_FEATURES) == RT_PHY_10G_FEATURES ||
217 devad == RT_MDIO_DEVAD_NONE || !devad)
218 return rt_phy_write(phydev, devad, regnum, val);
219
220 rt_phy_mmd_start_indirect(phydev, devad, regnum);
221
222 return rt_phy_write(phydev, RT_MDIO_DEVAD_NONE, RT_MII_MMD_DATA, val);
223 }
224
rt_phy_reset(struct rt_phy_device * phydev)225 int rt_phy_reset(struct rt_phy_device *phydev)
226 {
227 int reg;
228 int timeout = 500;
229 int devad = RT_MDIO_DEVAD_NONE;
230
231 if (phydev->flags & RT_PHY_FLAG_BROKEN_RESET)
232 return 0;
233
234 if (rt_phy_write(phydev, devad, RT_MII_BMCR, RT_BMCR_RESET) < 0)
235 {
236 LOG_D("PHY reset failed\n");
237 return -1;
238 }
239
240 reg = rt_phy_read(phydev, devad, RT_MII_BMCR);
241 while ((reg & RT_BMCR_RESET) && timeout--)
242 {
243 reg = rt_phy_read(phydev, devad, RT_MII_BMCR);
244
245 if (reg < 0)
246 {
247 LOG_D("PHY status read failed\n");
248 return -1;
249 }
250 rt_thread_mdelay(1);
251 }
252
253 if (reg & RT_BMCR_RESET)
254 {
255 LOG_D("PHY reset timed out\n");
256 return -1;
257 }
258
259 return 0;
260 }
261
262 static struct rt_bus rt_phy_bus;
263
264 /**
265 * @brief create a phy device
266 *
267 * Creates a new PHY device based on the given bus, address, PHY ID, and whether Clause 45 is supported.
268 *
269 * @param bus the pointer to the bus
270 * @param addr PHY device address
271 * @param phy_id PHY device id
272 * @param is_c45 if suport Clause 45
273 *
274 * @return if create success return the phy device pointer,else return RT_NULL
275 */
rt_phy_device_create(struct mii_bus * bus,int addr,rt_uint32_t phy_id,rt_bool_t is_c45)276 struct rt_phy_device *rt_phy_device_create(struct mii_bus *bus, int addr,
277 rt_uint32_t phy_id, rt_bool_t is_c45)
278 {
279 struct rt_phy_device *dev = rt_malloc(sizeof(struct rt_phy_device));
280
281 if (!dev)
282 {
283 LOG_E("Failed to allocate PHY device for %s:%d\n",
284 bus ? bus->name : "(null bus)", addr);
285 return RT_NULL;
286 }
287
288 memset(dev, 0, sizeof(*dev));
289
290 dev->duplex = -1;
291 dev->link = 0;
292 dev->interface = RT_PHY_INTERFACE_MODE_NA;
293 #ifdef RT_USING_OFW
294 dev->node = RT_NULL;
295 #endif
296 dev->autoneg = RT_TRUE;
297
298 dev->addr = addr;
299 dev->phy_id = phy_id;
300 dev->is_c45 = is_c45;
301 dev->bus = bus;
302
303 if(rt_phy_device_register(dev))
304 {
305 LOG_D("register phy device filed")
306 }
307
308 if (addr >= 0 && addr < RT_PHY_MAX && phy_id != RT_PHY_FIXED_ID &&
309 phy_id != RT_PHY_NCSI_ID)
310 bus->phymap[addr] = dev;
311
312 return dev;
313 }
314
315 /**
316 * @brief get phy id
317 *
318 * get phy id by read the register 2 and 3 of PHY device,
319 * Register of the MII management interface stipulates that
320 * register 2 contains thehigh 16 bits of the PHY’s identifier
321 * the register 3 contains the low 16 bits of the PHY’s identifier
322 *
323 * @param bus MII bus pointer
324 * @param addr PHY device address
325 * @param devad dev addr if be set to zero it means c22 mode,else it means c45 mode
326 * @param phy_id the phy id which will be read
327 *
328 * @return if read success return 0,else return -RT_EIO
329 */
get_phy_id(struct mii_bus * bus,int addr,int devad,rt_uint32_t * phy_id)330 static int get_phy_id(struct mii_bus *bus, int addr, int devad, rt_uint32_t *phy_id)
331 {
332 int phy_reg;
333
334 phy_reg = bus->read(bus, addr, devad, RT_MII_PHYSID1);
335
336 if (phy_reg < 0)
337 return -RT_EIO;
338
339 *phy_id = (phy_reg & 0xffff) << 16;
340
341 phy_reg = bus->read(bus, addr, devad, RT_MII_PHYSID2);
342
343 if (phy_reg < 0)
344 return -RT_EIO;
345
346 *phy_id |= (phy_reg & 0xffff);
347
348 return 0;
349 }
350
351 /**
352 * @brief create phy device by mask
353 *
354 * @param bus MII bus pointer
355 * @param phy_mask the mask which phy addr corresponding will be set 1
356 * @param devad dev addr if be set to zero it means c22 mode,else it means c45 mode
357 *
358 * @return if create success return the phy device pointer,if create fail return NULL
359 */
create_phy_by_mask(struct mii_bus * bus,unsigned int phy_mask,int devad)360 static struct rt_phy_device *create_phy_by_mask(struct mii_bus *bus, unsigned int phy_mask,int devad)
361 {
362 rt_uint32_t id = 0xffffffff;
363 rt_bool_t is_c45;
364
365 while (phy_mask)
366 {
367 int addr = __rt_ffs(phy_mask) - 1;
368 int r = get_phy_id(bus, addr, devad, &id);
369
370 if (r == 0 && id == 0)
371 {
372 phy_mask &= ~(1 << addr);
373 continue;
374 }
375
376 if (r == 0 && (id & 0x1fffffff) != 0x1fffffff)
377 {
378 is_c45 = (devad == RT_MDIO_DEVAD_NONE) ? RT_FALSE : RT_TRUE;
379 return rt_phy_device_create(bus, addr, id, is_c45);
380 }
381
382 }
383 return RT_NULL;
384 }
385
386 /**
387 * @brief create phy device by mask
388 *
389 * it will create phy device by c22 mode or c45 mode
390 *
391 * @param bus mii bus pointer
392 * @param phy_mask PHY mask it depend on the phy addr, the phy addr corresponding will be set 1
393 *
394 * @return if create success return the phy device pointer,if create fail return NULL
395 */
rt_phydev_create_by_mask(struct mii_bus * bus,unsigned int phy_mask)396 static struct rt_phy_device *rt_phydev_create_by_mask(struct mii_bus *bus, unsigned int phy_mask)
397 {
398 struct rt_phy_device *phy;
399 /*
400 *The bit of devad is dev addr which is the new features in c45
401 *so if devad equal to zero it means it is c22 mode ,and if not
402 *equal to zero it means it is c45 mode,which include PMD/PMA ,
403 *WIS ,PCS,PHY XS,PHY XS ....
404 */
405 int devad[] = {
406 /* Clause-22 */
407 RT_MDIO_DEVAD_NONE,
408 /* Clause-45 */
409 RT_MDIO_MMD_PMAPMD,
410 RT_MDIO_MMD_WIS,
411 RT_MDIO_MMD_PCS,
412 RT_MDIO_MMD_PHYXS,
413 RT_MDIO_MMD_VEND1,
414 };
415
416 for (int i = 0; i < sizeof(devad)/sizeof(devad[0]); i++)
417 {
418 phy = create_phy_by_mask(bus, phy_mask, devad[i]);
419 if(phy)
420 return phy;
421 }
422
423 return RT_NULL;
424 }
425
rt_phy_find_by_mask(struct mii_bus * bus,unsigned int phy_mask)426 struct rt_phy_device *rt_phy_find_by_mask(struct mii_bus *bus, unsigned int phy_mask)
427 {
428 struct rt_phy_device *phy;
429 unsigned int mask = phy_mask;
430 unsigned int addr;
431 if (bus->reset)
432 {
433 bus->reset(bus);
434
435 rt_thread_mdelay(15);
436 }
437
438 while (mask)
439 {
440 /*
441 *Whichever bit of the mask is the 1,
442 *which bit is the addr as the array subscript to search
443 *such as mask = 1110 ,this loop will search for subscript
444 *1,2,3,if the array subscript is not null then return it,
445 *if the array subscript is null then continue to search
446 */
447 addr = __rt_ffs(mask) - 1;
448
449 if (bus->phymap[addr])
450 return bus->phymap[addr];
451
452 mask &= ~(1U << addr);
453 }
454 /*ifcan't find phy device, create a new phy device*/
455 phy = rt_phydev_create_by_mask(bus, phy_mask);
456
457 return phy;
458
459 }
460
461 /**
462 * @brief get phy device by given mii bus, node and address
463 * @param bus MII bus pointer
464 * @param np the dtb node of device which need to get phy device
465 * @param addr address of phy device
466 * @param interface interface of phy device
467 *
468 * @return phy device pointer or NULL if not found
469 */
rt_phy_get_device(struct mii_bus * bus,struct rt_ofw_node * np,int addr,rt_phy_interface interface)470 struct rt_phy_device *rt_phy_get_device(struct mii_bus *bus,struct rt_ofw_node *np, int addr,rt_phy_interface interface)
471 {
472 struct rt_phy_device *phy = RT_NULL;
473 unsigned int phy_mask = addr? 1 << addr:0xffffffff;
474
475 #ifdef RT_USING_OFW
476 if(np)
477 phy = rt_ofw_create_phy(bus,np,addr);
478 #endif
479 if(!phy)
480 phy = rt_phy_find_by_mask(bus,phy_mask);
481
482 if(phy)
483 {
484 rt_phy_reset(phy);
485 phy->interface = interface;
486 return phy;
487 }
488
489 LOG_D("PHY device get failed");
490 return RT_NULL;
491 }
492
493 static struct rt_phy_driver genphy = {
494 .uid = 0xffffffff,
495 .mask = 0xffffffff,
496 .name = "Generic PHY",
497 .features = RT_PHY_GBIT_FEATURES | RT_SUPPORTED_MII |
498 RT_SUPPORTED_AUI | RT_SUPPORTED_FIBRE |
499 RT_SUPPORTED_BNC,
500 .config = rt_genphy_config,
501 .startup = rt_genphy_startup,
502 };
503 RT_PHY_DRIVER_REGISTER(genphy);
504
rt_phy_device_register(struct rt_phy_device * pdev)505 rt_err_t rt_phy_device_register(struct rt_phy_device *pdev)
506 {
507 rt_err_t err;
508 RT_ASSERT(pdev != RT_NULL);
509 err = rt_bus_add_device(&rt_phy_bus, &pdev->parent);
510 if (err)
511 {
512 return err;
513 }
514 if(!pdev->drv)
515 pdev->drv = &genphy;
516
517 return RT_EOK;
518 }
519
rt_phy_driver_register(struct rt_phy_driver * pdrv)520 rt_err_t rt_phy_driver_register(struct rt_phy_driver *pdrv)
521 {
522 RT_ASSERT(pdrv != RT_NULL);
523
524 pdrv->parent.bus = &rt_phy_bus;
525 #if RT_NAME_MAX > 0
526 rt_strcpy(pdrv->parent.parent.name, pdrv->name);
527 #else
528 pdrv->parent.parent.name = pdrv->name;
529 #endif
530
531 return rt_driver_register(&pdrv->parent);
532 }
533
phy_match(rt_driver_t drv,rt_device_t dev)534 static rt_bool_t phy_match(rt_driver_t drv, rt_device_t dev)
535 {
536 struct rt_phy_device *pdev = rt_container_of(dev, struct rt_phy_device, parent);
537 struct rt_phy_driver *pdrv = rt_container_of(drv, struct rt_phy_driver, parent);
538 if ((pdrv->uid & pdrv->mask) == (pdev->phy_id & pdrv->mask))
539 return RT_TRUE;
540
541 return RT_FALSE;
542
543 }
544
phy_probe(rt_device_t dev)545 static rt_err_t phy_probe(rt_device_t dev)
546 {
547 rt_err_t err = RT_EOK;
548 struct rt_phy_driver *pdrv = rt_container_of(dev->drv, struct rt_phy_driver, parent);
549 struct rt_phy_device *pdev = rt_container_of(dev, struct rt_phy_device, parent);
550 pdev->drv = pdrv;
551 pdev->advertising = pdev->drv->features;
552 pdev->supported = pdev->drv->features;
553
554 pdev->mmds = pdev->drv->mmds;
555 if(pdrv->probe)
556 err = pdrv->probe(pdev);
557
558 return err;
559 }
560
561 static struct rt_bus rt_phy_bus =
562 {
563 .name = "phy",
564 .match = phy_match,
565 .probe = phy_probe,
566 };
567
rt_phy_bus_init(void)568 static int rt_phy_bus_init(void)
569 {
570 rt_bus_register(&rt_phy_bus);
571
572 return 0;
573 }
574 INIT_CORE_EXPORT(rt_phy_bus_init);
575 #endif
576