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