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