1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-10-24     GuEe-GUI     first version
9  */
10 
11 #define DBG_TAG "rtdm.phye"
12 #define DBG_LVL DBG_INFO
13 #include <rtdbg.h>
14 
15 #include <rtdevice.h>
16 #include <rtthread.h>
17 
rt_phye_register(struct rt_phye * phye)18 rt_err_t rt_phye_register(struct rt_phye *phye)
19 {
20     rt_err_t err;
21 
22     if (phye && phye->dev && phye->ops)
23     {
24         err = RT_EOK;
25 
26         rt_spin_lock_init(&phye->lock);
27         rt_dm_dev_bind_fwdata(phye->dev, RT_NULL, phye);
28     }
29     else
30     {
31         err = -RT_EINVAL;
32     }
33 
34     return err;
35 }
36 
rt_phye_unregister(struct rt_phye * phye)37 rt_err_t rt_phye_unregister(struct rt_phye *phye)
38 {
39     rt_err_t err;
40 
41     if (phye)
42     {
43         err = RT_EOK;
44 
45         rt_spin_lock(&phye->lock);
46 
47         if (phye->dev->ref_count)
48         {
49             err = -RT_EBUSY;
50             LOG_E("%s is busy in unregister", rt_dm_dev_get_name(phye->dev));
51         }
52 
53         rt_dm_dev_unbind_fwdata(phye->dev, RT_NULL);
54 
55         rt_spin_unlock(&phye->lock);
56     }
57     else
58     {
59         err = -RT_EINVAL;
60     }
61 
62     return err;
63 }
64 
rt_phye_init(struct rt_phye * phye)65 rt_err_t rt_phye_init(struct rt_phye *phye)
66 {
67     rt_err_t err;
68 
69     if (!phye)
70     {
71         return RT_EOK;
72     }
73 
74     err = RT_EOK;
75 
76     rt_spin_lock(&phye->lock);
77 
78     if (phye->init_count == 0 && phye->ops->init)
79     {
80         if ((err = phye->ops->init(phye)))
81         {
82             goto _out_lock;
83         }
84     }
85     ++phye->init_count;
86 
87 _out_lock:
88     rt_spin_unlock(&phye->lock);
89 
90     return err;
91 }
92 
rt_phye_exit(struct rt_phye * phye)93 rt_err_t rt_phye_exit(struct rt_phye *phye)
94 {
95     rt_err_t err;
96 
97     if (!phye)
98     {
99         return RT_EOK;
100     }
101 
102     err = RT_EOK;
103 
104     rt_spin_lock(&phye->lock);
105 
106     if (phye->init_count == 1 && phye->ops->exit)
107     {
108         if ((err = phye->ops->exit(phye)))
109         {
110             goto _out_lock;
111         }
112     }
113     if (phye->init_count)
114     {
115         --phye->init_count;
116     }
117 
118 _out_lock:
119     rt_spin_unlock(&phye->lock);
120 
121     return err;
122 }
123 
rt_phye_reset(struct rt_phye * phye)124 rt_err_t rt_phye_reset(struct rt_phye *phye)
125 {
126     rt_err_t err;
127 
128     if (!phye)
129     {
130         return RT_EOK;
131     }
132 
133     err = RT_EOK;
134 
135     rt_spin_lock(&phye->lock);
136 
137     if (phye->ops->reset)
138     {
139         err = phye->ops->reset(phye);
140     }
141 
142     rt_spin_unlock(&phye->lock);
143 
144     return err;
145 }
146 
rt_phye_power_on(struct rt_phye * phye)147 rt_err_t rt_phye_power_on(struct rt_phye *phye)
148 {
149     rt_err_t err;
150 
151     if (!phye)
152     {
153         return RT_EOK;
154     }
155 
156     err = RT_EOK;
157 
158     rt_spin_lock(&phye->lock);
159 
160     if (phye->power_count == 0 && phye->ops->power_on)
161     {
162         if ((err = phye->ops->power_on(phye)))
163         {
164             goto _out_lock;
165         }
166     }
167     ++phye->power_count;
168 
169 _out_lock:
170     rt_spin_unlock(&phye->lock);
171 
172     return err;
173 }
174 
rt_phye_power_off(struct rt_phye * phye)175 rt_err_t rt_phye_power_off(struct rt_phye *phye)
176 {
177     rt_err_t err;
178 
179     if (!phye)
180     {
181         return RT_EOK;
182     }
183 
184     err = RT_EOK;
185 
186     rt_spin_lock(&phye->lock);
187 
188     if (phye->power_count == 1 && phye->ops->power_off)
189     {
190         if ((err = phye->ops->power_off(phye)))
191         {
192             goto _out_lock;
193         }
194     }
195     if (phye->power_count)
196     {
197         --phye->power_count;
198     }
199 
200 _out_lock:
201     rt_spin_unlock(&phye->lock);
202 
203     return err;
204 }
205 
rt_phye_set_mode(struct rt_phye * phye,enum rt_phye_mode mode,int submode)206 rt_err_t rt_phye_set_mode(struct rt_phye *phye, enum rt_phye_mode mode, int submode)
207 {
208     rt_err_t err;
209 
210     if (!phye)
211     {
212         return RT_EOK;
213     }
214 
215     if (mode < RT_PHYE_MODE_MAX &&
216         (submode == RT_PHYE_MODE_INVALID || submode >= RT_PHYE_MODE_MAX))
217     {
218         err = RT_EOK;
219 
220         rt_spin_lock(&phye->lock);
221 
222         if (phye->ops->set_mode)
223         {
224             err = phye->ops->set_mode(phye, mode, submode);
225         }
226 
227         rt_spin_unlock(&phye->lock);
228     }
229     else
230     {
231         err = -RT_EINVAL;
232     }
233 
234     return err;
235 }
236 
ofw_phye_get_by_index(struct rt_ofw_node * np,int index)237 static struct rt_phye *ofw_phye_get_by_index(struct rt_ofw_node *np, int index)
238 {
239     struct rt_phye *phye = RT_NULL;
240 #ifdef RT_USING_OFW
241     rt_err_t err;
242     struct rt_ofw_node *phye_np;
243     struct rt_ofw_cell_args phye_args;
244 
245     if (!rt_ofw_parse_phandle_cells(np, "phys", "#phy-cells", index, &phye_args))
246     {
247         phye_np = phye_args.data;
248 
249         if (!rt_ofw_data(phye_np))
250         {
251             rt_platform_ofw_request(phye_np);
252         }
253 
254         phye = rt_ofw_data(phye_np);
255         rt_ofw_node_put(phye_np);
256 
257         if (phye && phye->ops->ofw_parse)
258         {
259             if ((err = phye->ops->ofw_parse(phye, &phye_args)))
260             {
261                 phye = rt_err_ptr(err);
262             }
263         }
264     }
265 #endif /* RT_USING_OFW */
266     return phye;
267 }
268 
rt_phye_get_by_index(struct rt_device * dev,int index)269 struct rt_phye *rt_phye_get_by_index(struct rt_device *dev, int index)
270 {
271     struct rt_phye *phye = RT_NULL;
272 
273     if (!dev || index < 0)
274     {
275         return rt_err_ptr(-RT_EINVAL);
276     }
277 
278     if (dev->ofw_node)
279     {
280         phye = ofw_phye_get_by_index(dev->ofw_node, index);
281     }
282 
283     if (!rt_is_err_or_null(phye))
284     {
285         rt_spin_lock(&phye->lock);
286         ++phye->dev->ref_count;
287         rt_spin_unlock(&phye->lock);
288     }
289 
290     return phye;
291 }
292 
rt_phye_get_by_name(struct rt_device * dev,const char * id)293 struct rt_phye *rt_phye_get_by_name(struct rt_device *dev, const char *id)
294 {
295     int index;
296 
297     if (!dev || !id)
298     {
299         return rt_err_ptr(-RT_EINVAL);
300     }
301 
302     index = rt_dm_dev_prop_index_of_string(dev, "phy-names", id);
303 
304     if (index >= 0)
305     {
306         return rt_phye_get_by_index(dev, index);
307     }
308 
309     return RT_NULL;
310 }
311 
rt_phye_put(struct rt_phye * phye)312 void rt_phye_put(struct rt_phye *phye)
313 {
314     if (phye)
315     {
316         rt_spin_lock(&phye->lock);
317         --phye->dev->ref_count;
318         rt_spin_unlock(&phye->lock);
319     }
320 }
321