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  * 2024-09-25     zhujiale    the first version
9  */
10 #include <rtthread.h>
11 #include <rtdevice.h>
12 #include <stdio.h>
13 #define DBG_TAG "rtdm.phy"
14 #define DBG_LVL DBG_INFO
15 #include <rtdbg.h>
16 #include "ofw.h"
17 
18 static const char* const rt_phy_modes[] =
19 {
20     [RT_PHY_INTERFACE_MODE_NA]         = "",
21     [RT_PHY_INTERFACE_MODE_INTERNAL]   = "internal",
22     [RT_PHY_INTERFACE_MODE_MII]        = "mii",
23     [RT_PHY_INTERFACE_MODE_GMII]       = "gmii",
24     [RT_PHY_INTERFACE_MODE_SGMII]      = "sgmii",
25     [RT_PHY_INTERFACE_MODE_TBI]        = "tbi",
26     [RT_PHY_INTERFACE_MODE_REVMII]     = "rev-mii",
27     [RT_PHY_INTERFACE_MODE_RMII]       = "rmii",
28     [RT_PHY_INTERFACE_MODE_REVRMII]    = "rev-rmii",
29     [RT_PHY_INTERFACE_MODE_RGMII]      = "rgmii",
30     [RT_PHY_INTERFACE_MODE_RGMII_ID]   = "rgmii-id",
31     [RT_PHY_INTERFACE_MODE_RGMII_RXID] = "rgmii-rxid",
32     [RT_PHY_INTERFACE_MODE_RGMII_TXID] = "rgmii-txid",
33     [RT_PHY_INTERFACE_MODE_RTBI]       = "rtbi",
34     [RT_PHY_INTERFACE_MODE_SMII]       = "smii",
35     [RT_PHY_INTERFACE_MODE_XGMII]      = "xgmii",
36     [RT_PHY_INTERFACE_MODE_XLGMII]     = "xlgmii",
37     [RT_PHY_INTERFACE_MODE_MOCA]       = "moca",
38     [RT_PHY_INTERFACE_MODE_PSGMII]     = "psgmii",
39     [RT_PHY_INTERFACE_MODE_QSGMII]     = "qsgmii",
40     [RT_PHY_INTERFACE_MODE_TRGMII]     = "trgmii",
41     [RT_PHY_INTERFACE_MODE_1000BASEX]  = "1000base-x",
42     [RT_PHY_INTERFACE_MODE_1000BASEKX] = "1000base-kx",
43     [RT_PHY_INTERFACE_MODE_2500BASEX]  = "2500base-x",
44     [RT_PHY_INTERFACE_MODE_5GBASER]    = "5gbase-r",
45     [RT_PHY_INTERFACE_MODE_RXAUI]      = "rxaui",
46     [RT_PHY_INTERFACE_MODE_XAUI]       = "xaui",
47     [RT_PHY_INTERFACE_MODE_10GBASER]   = "10gbase-r",
48     [RT_PHY_INTERFACE_MODE_25GBASER]   = "25gbase-r",
49     [RT_PHY_INTERFACE_MODE_USXGMII]    = "usxgmii",
50     [RT_PHY_INTERFACE_MODE_10GKR]      = "10gbase-kr",
51     [RT_PHY_INTERFACE_MODE_100BASEX]   = "100base-x",
52     [RT_PHY_INTERFACE_MODE_QUSGMII]    = "qusgmii",
53     [RT_PHY_INTERFACE_MODE_MAX]        = "",
54 };
55 
_get_interface_by_name(const char * name,rt_phy_interface * interface)56 static rt_err_t _get_interface_by_name(const char *name, rt_phy_interface *interface)
57 {
58     for (int i = 0; i < RT_PHY_INTERFACE_MODE_MAX; i++)
59     {
60         if (!strcmp(name, rt_phy_modes[i]))
61         {
62             *interface = i;
63             return RT_EOK;
64         }
65     }
66     return -RT_ERROR;
67 }
68 
rt_ofw_get_interface(struct rt_ofw_node * np,rt_phy_interface * interface)69 rt_err_t rt_ofw_get_interface(struct rt_ofw_node *np, rt_phy_interface *interface)
70 {
71     const char *phy_mode = RT_NULL;
72 
73     if (rt_ofw_prop_read_string(np, "phy-mode", &phy_mode))
74         rt_ofw_prop_read_string(np, "phy-connection-type", &phy_mode);
75     if (!phy_mode)
76         return -RT_ERROR;
77 
78     return _get_interface_by_name(phy_mode, interface);
79 }
80 
rt_ofw_get_mac_addr_by_name(struct rt_ofw_node * np,const char * name,rt_uint8_t * addr)81 rt_err_t rt_ofw_get_mac_addr_by_name(struct rt_ofw_node *np, const char *name, rt_uint8_t *addr)
82 {
83     rt_ssize_t  len;
84     const void *p;
85     p = rt_ofw_prop_read_raw(np, name, &len);
86     if (p)
87     {
88         rt_memcpy(addr, p, len);
89         return RT_EOK;
90     }
91 
92     return -RT_ERROR;
93 }
94 
rt_ofw_get_mac_addr(struct rt_ofw_node * np,rt_uint8_t * addr)95 rt_err_t rt_ofw_get_mac_addr(struct rt_ofw_node *np, rt_uint8_t *addr)
96 {
97     if (!rt_ofw_get_mac_addr_by_name(np, "mac-address", addr))
98         return RT_EOK;
99 
100     if (!rt_ofw_get_mac_addr_by_name(np, "local-mac-address", addr))
101         return RT_EOK;
102 
103     if (!rt_ofw_get_mac_addr_by_name(np, "address", addr))
104         return RT_EOK;
105 
106     return -RT_ERROR;
107 }
108 
rt_ofw_get_phyid(struct rt_ofw_node * np,rt_uint32_t * id)109 rt_err_t rt_ofw_get_phyid(struct rt_ofw_node *np,rt_uint32_t *id)
110 {
111     const char *phy_id;
112     unsigned int upper, lower;
113     int ret;
114 
115     ret = rt_ofw_prop_read_string(np,"compatible",&phy_id);
116     if (ret)
117         return ret;
118 
119     ret = rt_sscanf(phy_id,"ethernet-phy-id%4x.%4x",&upper, &lower);
120     if(ret != 2)
121         return -RT_ERROR;
122 
123     *id = ((upper & 0xffff) << 16) | (lower & 0xffff);
124     return RT_EOK;
125 
126 }
rt_ofw_create_phy(struct mii_bus * bus,struct rt_ofw_node * np,int phyaddr)127 struct rt_phy_device *rt_ofw_create_phy(struct mii_bus *bus,struct rt_ofw_node *np,int phyaddr)
128 {
129     struct rt_phy_device *dev = RT_NULL;
130     struct rt_ofw_node *phy_node;
131     int ret;
132     rt_uint32_t id = 0xffff;
133 
134     phy_node = rt_ofw_parse_phandle(np, "phy-handle", 0);
135     if (!phy_node)
136     {
137         LOG_D("Failed to find phy-handle");
138         return RT_NULL;
139     }
140 
141     ret = rt_ofw_get_phyid(np, &id);
142     if (ret)
143     {
144         LOG_D("Failed to read eth PHY id, err: %d\n", ret);
145         return RT_NULL;
146     }
147 
148     LOG_D("Found a PHY id: 0x%x\n", id);
149 
150     dev = rt_phy_device_create(bus, phyaddr, id, RT_FALSE);
151 
152     if(dev)
153         dev->node = phy_node;
154 
155     return dev;
156 }
157