1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * phy.c -- USB phy handling |
4 | * |
5 | * Copyright (C) 2004-2013 Texas Instruments |
6 | */ |
7 | #include <linux/kernel.h> |
8 | #include <linux/export.h> |
9 | #include <linux/err.h> |
10 | #include <linux/device.h> |
11 | #include <linux/module.h> |
12 | #include <linux/slab.h> |
13 | #include <linux/of.h> |
14 | |
15 | #include <linux/usb/phy.h> |
16 | |
17 | /* Default current range by charger type. */ |
18 | #define DEFAULT_SDP_CUR_MIN 2 |
19 | #define DEFAULT_SDP_CUR_MAX 500 |
20 | #define DEFAULT_SDP_CUR_MIN_SS 150 |
21 | #define DEFAULT_SDP_CUR_MAX_SS 900 |
22 | #define DEFAULT_DCP_CUR_MIN 500 |
23 | #define DEFAULT_DCP_CUR_MAX 5000 |
24 | #define DEFAULT_CDP_CUR_MIN 1500 |
25 | #define DEFAULT_CDP_CUR_MAX 5000 |
26 | #define DEFAULT_ACA_CUR_MIN 1500 |
27 | #define DEFAULT_ACA_CUR_MAX 5000 |
28 | |
29 | static LIST_HEAD(phy_list); |
30 | static DEFINE_SPINLOCK(phy_lock); |
31 | |
32 | struct phy_devm { |
33 | struct usb_phy *phy; |
34 | struct notifier_block *nb; |
35 | }; |
36 | |
37 | static const char *const usb_chger_type[] = { |
38 | [UNKNOWN_TYPE] = "USB_CHARGER_UNKNOWN_TYPE" , |
39 | [SDP_TYPE] = "USB_CHARGER_SDP_TYPE" , |
40 | [CDP_TYPE] = "USB_CHARGER_CDP_TYPE" , |
41 | [DCP_TYPE] = "USB_CHARGER_DCP_TYPE" , |
42 | [ACA_TYPE] = "USB_CHARGER_ACA_TYPE" , |
43 | }; |
44 | |
45 | static const char *const usb_chger_state[] = { |
46 | [USB_CHARGER_DEFAULT] = "USB_CHARGER_DEFAULT" , |
47 | [USB_CHARGER_PRESENT] = "USB_CHARGER_PRESENT" , |
48 | [USB_CHARGER_ABSENT] = "USB_CHARGER_ABSENT" , |
49 | }; |
50 | |
51 | static struct usb_phy *__usb_find_phy(struct list_head *list, |
52 | enum usb_phy_type type) |
53 | { |
54 | struct usb_phy *phy = NULL; |
55 | |
56 | list_for_each_entry(phy, list, head) { |
57 | if (phy->type != type) |
58 | continue; |
59 | |
60 | return phy; |
61 | } |
62 | |
63 | return ERR_PTR(error: -ENODEV); |
64 | } |
65 | |
66 | static struct usb_phy *__of_usb_find_phy(struct device_node *node) |
67 | { |
68 | struct usb_phy *phy; |
69 | |
70 | if (!of_device_is_available(device: node)) |
71 | return ERR_PTR(error: -ENODEV); |
72 | |
73 | list_for_each_entry(phy, &phy_list, head) { |
74 | if (node != phy->dev->of_node) |
75 | continue; |
76 | |
77 | return phy; |
78 | } |
79 | |
80 | return ERR_PTR(error: -EPROBE_DEFER); |
81 | } |
82 | |
83 | static struct usb_phy *__device_to_usb_phy(const struct device *dev) |
84 | { |
85 | struct usb_phy *usb_phy; |
86 | |
87 | list_for_each_entry(usb_phy, &phy_list, head) { |
88 | if (usb_phy->dev == dev) |
89 | return usb_phy; |
90 | } |
91 | |
92 | return NULL; |
93 | } |
94 | |
95 | static void usb_phy_set_default_current(struct usb_phy *usb_phy) |
96 | { |
97 | usb_phy->chg_cur.sdp_min = DEFAULT_SDP_CUR_MIN; |
98 | usb_phy->chg_cur.sdp_max = DEFAULT_SDP_CUR_MAX; |
99 | usb_phy->chg_cur.dcp_min = DEFAULT_DCP_CUR_MIN; |
100 | usb_phy->chg_cur.dcp_max = DEFAULT_DCP_CUR_MAX; |
101 | usb_phy->chg_cur.cdp_min = DEFAULT_CDP_CUR_MIN; |
102 | usb_phy->chg_cur.cdp_max = DEFAULT_CDP_CUR_MAX; |
103 | usb_phy->chg_cur.aca_min = DEFAULT_ACA_CUR_MIN; |
104 | usb_phy->chg_cur.aca_max = DEFAULT_ACA_CUR_MAX; |
105 | } |
106 | |
107 | /** |
108 | * usb_phy_notify_charger_work - notify the USB charger state |
109 | * @work: the charger work to notify the USB charger state |
110 | * |
111 | * This work can be issued when USB charger state has been changed or |
112 | * USB charger current has been changed, then we can notify the current |
113 | * what can be drawn to power user and the charger state to userspace. |
114 | * |
115 | * If we get the charger type from extcon subsystem, we can notify the |
116 | * charger state to power user automatically by usb_phy_get_charger_type() |
117 | * issuing from extcon subsystem. |
118 | * |
119 | * If we get the charger type from ->charger_detect() instead of extcon |
120 | * subsystem, the usb phy driver should issue usb_phy_set_charger_state() |
121 | * to set charger state when the charger state has been changed. |
122 | */ |
123 | static void usb_phy_notify_charger_work(struct work_struct *work) |
124 | { |
125 | struct usb_phy *usb_phy = container_of(work, struct usb_phy, chg_work); |
126 | unsigned int min, max; |
127 | |
128 | switch (usb_phy->chg_state) { |
129 | case USB_CHARGER_PRESENT: |
130 | usb_phy_get_charger_current(usb_phy, min: &min, max: &max); |
131 | |
132 | atomic_notifier_call_chain(nh: &usb_phy->notifier, val: max, v: usb_phy); |
133 | break; |
134 | case USB_CHARGER_ABSENT: |
135 | usb_phy_set_default_current(usb_phy); |
136 | |
137 | atomic_notifier_call_chain(nh: &usb_phy->notifier, val: 0, v: usb_phy); |
138 | break; |
139 | default: |
140 | dev_warn(usb_phy->dev, "Unknown USB charger state: %d\n" , |
141 | usb_phy->chg_state); |
142 | return; |
143 | } |
144 | |
145 | kobject_uevent(kobj: &usb_phy->dev->kobj, action: KOBJ_CHANGE); |
146 | } |
147 | |
148 | static int usb_phy_uevent(const struct device *dev, struct kobj_uevent_env *env) |
149 | { |
150 | const struct usb_phy *usb_phy; |
151 | char uchger_state[50] = { 0 }; |
152 | char uchger_type[50] = { 0 }; |
153 | unsigned long flags; |
154 | |
155 | spin_lock_irqsave(&phy_lock, flags); |
156 | usb_phy = __device_to_usb_phy(dev); |
157 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
158 | |
159 | if (!usb_phy) |
160 | return -ENODEV; |
161 | |
162 | snprintf(buf: uchger_state, ARRAY_SIZE(uchger_state), |
163 | fmt: "USB_CHARGER_STATE=%s" , usb_chger_state[usb_phy->chg_state]); |
164 | |
165 | snprintf(buf: uchger_type, ARRAY_SIZE(uchger_type), |
166 | fmt: "USB_CHARGER_TYPE=%s" , usb_chger_type[usb_phy->chg_type]); |
167 | |
168 | if (add_uevent_var(env, format: uchger_state)) |
169 | return -ENOMEM; |
170 | |
171 | if (add_uevent_var(env, format: uchger_type)) |
172 | return -ENOMEM; |
173 | |
174 | return 0; |
175 | } |
176 | |
177 | static void __usb_phy_get_charger_type(struct usb_phy *usb_phy) |
178 | { |
179 | if (extcon_get_state(edev: usb_phy->edev, EXTCON_CHG_USB_SDP) > 0) { |
180 | usb_phy->chg_type = SDP_TYPE; |
181 | usb_phy->chg_state = USB_CHARGER_PRESENT; |
182 | } else if (extcon_get_state(edev: usb_phy->edev, EXTCON_CHG_USB_CDP) > 0) { |
183 | usb_phy->chg_type = CDP_TYPE; |
184 | usb_phy->chg_state = USB_CHARGER_PRESENT; |
185 | } else if (extcon_get_state(edev: usb_phy->edev, EXTCON_CHG_USB_DCP) > 0) { |
186 | usb_phy->chg_type = DCP_TYPE; |
187 | usb_phy->chg_state = USB_CHARGER_PRESENT; |
188 | } else if (extcon_get_state(edev: usb_phy->edev, EXTCON_CHG_USB_ACA) > 0) { |
189 | usb_phy->chg_type = ACA_TYPE; |
190 | usb_phy->chg_state = USB_CHARGER_PRESENT; |
191 | } else { |
192 | usb_phy->chg_type = UNKNOWN_TYPE; |
193 | usb_phy->chg_state = USB_CHARGER_ABSENT; |
194 | } |
195 | |
196 | schedule_work(work: &usb_phy->chg_work); |
197 | } |
198 | |
199 | /** |
200 | * usb_phy_get_charger_type - get charger type from extcon subsystem |
201 | * @nb: the notifier block to determine charger type |
202 | * @state: the cable state |
203 | * @data: private data |
204 | * |
205 | * Determin the charger type from extcon subsystem which also means the |
206 | * charger state has been chaned, then we should notify this event. |
207 | */ |
208 | static int usb_phy_get_charger_type(struct notifier_block *nb, |
209 | unsigned long state, void *data) |
210 | { |
211 | struct usb_phy *usb_phy = container_of(nb, struct usb_phy, type_nb); |
212 | |
213 | __usb_phy_get_charger_type(usb_phy); |
214 | return NOTIFY_OK; |
215 | } |
216 | |
217 | /** |
218 | * usb_phy_set_charger_current - set the USB charger current |
219 | * @usb_phy: the USB phy to be used |
220 | * @mA: the current need to be set |
221 | * |
222 | * Usually we only change the charger default current when USB finished the |
223 | * enumeration as one SDP charger. As one SDP charger, usb_phy_set_power() |
224 | * will issue this function to change charger current when after setting USB |
225 | * configuration, or suspend/resume USB. For other type charger, we should |
226 | * use the default charger current and we do not suggest to issue this function |
227 | * to change the charger current. |
228 | * |
229 | * When USB charger current has been changed, we need to notify the power users. |
230 | */ |
231 | void usb_phy_set_charger_current(struct usb_phy *usb_phy, unsigned int mA) |
232 | { |
233 | switch (usb_phy->chg_type) { |
234 | case SDP_TYPE: |
235 | if (usb_phy->chg_cur.sdp_max == mA) |
236 | return; |
237 | |
238 | usb_phy->chg_cur.sdp_max = (mA > DEFAULT_SDP_CUR_MAX_SS) ? |
239 | DEFAULT_SDP_CUR_MAX_SS : mA; |
240 | break; |
241 | case DCP_TYPE: |
242 | if (usb_phy->chg_cur.dcp_max == mA) |
243 | return; |
244 | |
245 | usb_phy->chg_cur.dcp_max = (mA > DEFAULT_DCP_CUR_MAX) ? |
246 | DEFAULT_DCP_CUR_MAX : mA; |
247 | break; |
248 | case CDP_TYPE: |
249 | if (usb_phy->chg_cur.cdp_max == mA) |
250 | return; |
251 | |
252 | usb_phy->chg_cur.cdp_max = (mA > DEFAULT_CDP_CUR_MAX) ? |
253 | DEFAULT_CDP_CUR_MAX : mA; |
254 | break; |
255 | case ACA_TYPE: |
256 | if (usb_phy->chg_cur.aca_max == mA) |
257 | return; |
258 | |
259 | usb_phy->chg_cur.aca_max = (mA > DEFAULT_ACA_CUR_MAX) ? |
260 | DEFAULT_ACA_CUR_MAX : mA; |
261 | break; |
262 | default: |
263 | return; |
264 | } |
265 | |
266 | schedule_work(work: &usb_phy->chg_work); |
267 | } |
268 | EXPORT_SYMBOL_GPL(usb_phy_set_charger_current); |
269 | |
270 | /** |
271 | * usb_phy_get_charger_current - get the USB charger current |
272 | * @usb_phy: the USB phy to be used |
273 | * @min: the minimum current |
274 | * @max: the maximum current |
275 | * |
276 | * Usually we will notify the maximum current to power user, but for some |
277 | * special case, power user also need the minimum current value. Then the |
278 | * power user can issue this function to get the suitable current. |
279 | */ |
280 | void usb_phy_get_charger_current(struct usb_phy *usb_phy, |
281 | unsigned int *min, unsigned int *max) |
282 | { |
283 | switch (usb_phy->chg_type) { |
284 | case SDP_TYPE: |
285 | *min = usb_phy->chg_cur.sdp_min; |
286 | *max = usb_phy->chg_cur.sdp_max; |
287 | break; |
288 | case DCP_TYPE: |
289 | *min = usb_phy->chg_cur.dcp_min; |
290 | *max = usb_phy->chg_cur.dcp_max; |
291 | break; |
292 | case CDP_TYPE: |
293 | *min = usb_phy->chg_cur.cdp_min; |
294 | *max = usb_phy->chg_cur.cdp_max; |
295 | break; |
296 | case ACA_TYPE: |
297 | *min = usb_phy->chg_cur.aca_min; |
298 | *max = usb_phy->chg_cur.aca_max; |
299 | break; |
300 | default: |
301 | *min = 0; |
302 | *max = 0; |
303 | break; |
304 | } |
305 | } |
306 | EXPORT_SYMBOL_GPL(usb_phy_get_charger_current); |
307 | |
308 | /** |
309 | * usb_phy_set_charger_state - set the USB charger state |
310 | * @usb_phy: the USB phy to be used |
311 | * @state: the new state need to be set for charger |
312 | * |
313 | * The usb phy driver can issue this function when the usb phy driver |
314 | * detected the charger state has been changed, in this case the charger |
315 | * type should be get from ->charger_detect(). |
316 | */ |
317 | void usb_phy_set_charger_state(struct usb_phy *usb_phy, |
318 | enum usb_charger_state state) |
319 | { |
320 | if (usb_phy->chg_state == state || !usb_phy->charger_detect) |
321 | return; |
322 | |
323 | usb_phy->chg_state = state; |
324 | if (usb_phy->chg_state == USB_CHARGER_PRESENT) |
325 | usb_phy->chg_type = usb_phy->charger_detect(usb_phy); |
326 | else |
327 | usb_phy->chg_type = UNKNOWN_TYPE; |
328 | |
329 | schedule_work(work: &usb_phy->chg_work); |
330 | } |
331 | EXPORT_SYMBOL_GPL(usb_phy_set_charger_state); |
332 | |
333 | static void devm_usb_phy_release(struct device *dev, void *res) |
334 | { |
335 | struct usb_phy *phy = *(struct usb_phy **)res; |
336 | |
337 | usb_put_phy(phy); |
338 | } |
339 | |
340 | static void devm_usb_phy_release2(struct device *dev, void *_res) |
341 | { |
342 | struct phy_devm *res = _res; |
343 | |
344 | if (res->nb) |
345 | usb_unregister_notifier(x: res->phy, nb: res->nb); |
346 | usb_put_phy(res->phy); |
347 | } |
348 | |
349 | static int devm_usb_phy_match(struct device *dev, void *res, void *match_data) |
350 | { |
351 | struct usb_phy **phy = res; |
352 | |
353 | return *phy == match_data; |
354 | } |
355 | |
356 | static void usb_charger_init(struct usb_phy *usb_phy) |
357 | { |
358 | usb_phy->chg_type = UNKNOWN_TYPE; |
359 | usb_phy->chg_state = USB_CHARGER_DEFAULT; |
360 | usb_phy_set_default_current(usb_phy); |
361 | INIT_WORK(&usb_phy->chg_work, usb_phy_notify_charger_work); |
362 | } |
363 | |
364 | static int usb_add_extcon(struct usb_phy *x) |
365 | { |
366 | int ret; |
367 | |
368 | if (of_property_read_bool(np: x->dev->of_node, propname: "extcon" )) { |
369 | x->edev = extcon_get_edev_by_phandle(dev: x->dev, index: 0); |
370 | if (IS_ERR(ptr: x->edev)) |
371 | return PTR_ERR(ptr: x->edev); |
372 | |
373 | x->id_edev = extcon_get_edev_by_phandle(dev: x->dev, index: 1); |
374 | if (IS_ERR(ptr: x->id_edev)) { |
375 | x->id_edev = NULL; |
376 | dev_info(x->dev, "No separate ID extcon device\n" ); |
377 | } |
378 | |
379 | if (x->vbus_nb.notifier_call) { |
380 | ret = devm_extcon_register_notifier(dev: x->dev, edev: x->edev, |
381 | EXTCON_USB, |
382 | nb: &x->vbus_nb); |
383 | if (ret < 0) { |
384 | dev_err(x->dev, |
385 | "register VBUS notifier failed\n" ); |
386 | return ret; |
387 | } |
388 | } else { |
389 | x->type_nb.notifier_call = usb_phy_get_charger_type; |
390 | |
391 | ret = devm_extcon_register_notifier(dev: x->dev, edev: x->edev, |
392 | EXTCON_CHG_USB_SDP, |
393 | nb: &x->type_nb); |
394 | if (ret) { |
395 | dev_err(x->dev, |
396 | "register extcon USB SDP failed.\n" ); |
397 | return ret; |
398 | } |
399 | |
400 | ret = devm_extcon_register_notifier(dev: x->dev, edev: x->edev, |
401 | EXTCON_CHG_USB_CDP, |
402 | nb: &x->type_nb); |
403 | if (ret) { |
404 | dev_err(x->dev, |
405 | "register extcon USB CDP failed.\n" ); |
406 | return ret; |
407 | } |
408 | |
409 | ret = devm_extcon_register_notifier(dev: x->dev, edev: x->edev, |
410 | EXTCON_CHG_USB_DCP, |
411 | nb: &x->type_nb); |
412 | if (ret) { |
413 | dev_err(x->dev, |
414 | "register extcon USB DCP failed.\n" ); |
415 | return ret; |
416 | } |
417 | |
418 | ret = devm_extcon_register_notifier(dev: x->dev, edev: x->edev, |
419 | EXTCON_CHG_USB_ACA, |
420 | nb: &x->type_nb); |
421 | if (ret) { |
422 | dev_err(x->dev, |
423 | "register extcon USB ACA failed.\n" ); |
424 | return ret; |
425 | } |
426 | } |
427 | |
428 | if (x->id_nb.notifier_call) { |
429 | struct extcon_dev *id_ext; |
430 | |
431 | if (x->id_edev) |
432 | id_ext = x->id_edev; |
433 | else |
434 | id_ext = x->edev; |
435 | |
436 | ret = devm_extcon_register_notifier(dev: x->dev, edev: id_ext, |
437 | EXTCON_USB_HOST, |
438 | nb: &x->id_nb); |
439 | if (ret < 0) { |
440 | dev_err(x->dev, |
441 | "register ID notifier failed\n" ); |
442 | return ret; |
443 | } |
444 | } |
445 | } |
446 | |
447 | if (x->type_nb.notifier_call) |
448 | __usb_phy_get_charger_type(usb_phy: x); |
449 | |
450 | return 0; |
451 | } |
452 | |
453 | /** |
454 | * devm_usb_get_phy - find the USB PHY |
455 | * @dev: device that requests this phy |
456 | * @type: the type of the phy the controller requires |
457 | * |
458 | * Gets the phy using usb_get_phy(), and associates a device with it using |
459 | * devres. On driver detach, release function is invoked on the devres data, |
460 | * then, devres data is freed. |
461 | * |
462 | * For use by USB host and peripheral drivers. |
463 | */ |
464 | struct usb_phy *devm_usb_get_phy(struct device *dev, enum usb_phy_type type) |
465 | { |
466 | struct usb_phy **ptr, *phy; |
467 | |
468 | ptr = devres_alloc(devm_usb_phy_release, sizeof(*ptr), GFP_KERNEL); |
469 | if (!ptr) |
470 | return ERR_PTR(error: -ENOMEM); |
471 | |
472 | phy = usb_get_phy(type); |
473 | if (!IS_ERR(ptr: phy)) { |
474 | *ptr = phy; |
475 | devres_add(dev, res: ptr); |
476 | } else |
477 | devres_free(res: ptr); |
478 | |
479 | return phy; |
480 | } |
481 | EXPORT_SYMBOL_GPL(devm_usb_get_phy); |
482 | |
483 | /** |
484 | * usb_get_phy - find the USB PHY |
485 | * @type: the type of the phy the controller requires |
486 | * |
487 | * Returns the phy driver, after getting a refcount to it; or |
488 | * -ENODEV if there is no such phy. The caller is responsible for |
489 | * calling usb_put_phy() to release that count. |
490 | * |
491 | * For use by USB host and peripheral drivers. |
492 | */ |
493 | struct usb_phy *usb_get_phy(enum usb_phy_type type) |
494 | { |
495 | struct usb_phy *phy = NULL; |
496 | unsigned long flags; |
497 | |
498 | spin_lock_irqsave(&phy_lock, flags); |
499 | |
500 | phy = __usb_find_phy(list: &phy_list, type); |
501 | if (IS_ERR(ptr: phy) || !try_module_get(module: phy->dev->driver->owner)) { |
502 | pr_debug("PHY: unable to find transceiver of type %s\n" , |
503 | usb_phy_type_string(type)); |
504 | if (!IS_ERR(ptr: phy)) |
505 | phy = ERR_PTR(error: -ENODEV); |
506 | |
507 | goto err0; |
508 | } |
509 | |
510 | get_device(dev: phy->dev); |
511 | |
512 | err0: |
513 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
514 | |
515 | return phy; |
516 | } |
517 | EXPORT_SYMBOL_GPL(usb_get_phy); |
518 | |
519 | /** |
520 | * devm_usb_get_phy_by_node - find the USB PHY by device_node |
521 | * @dev: device that requests this phy |
522 | * @node: the device_node for the phy device. |
523 | * @nb: a notifier_block to register with the phy. |
524 | * |
525 | * Returns the phy driver associated with the given device_node, |
526 | * after getting a refcount to it, -ENODEV if there is no such phy or |
527 | * -EPROBE_DEFER if the device is not yet loaded. While at that, it |
528 | * also associates the device with |
529 | * the phy using devres. On driver detach, release function is invoked |
530 | * on the devres data, then, devres data is freed. |
531 | * |
532 | * For use by peripheral drivers for devices related to a phy, |
533 | * such as a charger. |
534 | */ |
535 | struct usb_phy *devm_usb_get_phy_by_node(struct device *dev, |
536 | struct device_node *node, |
537 | struct notifier_block *nb) |
538 | { |
539 | struct usb_phy *phy = ERR_PTR(error: -ENOMEM); |
540 | struct phy_devm *ptr; |
541 | unsigned long flags; |
542 | |
543 | ptr = devres_alloc(devm_usb_phy_release2, sizeof(*ptr), GFP_KERNEL); |
544 | if (!ptr) { |
545 | dev_dbg(dev, "failed to allocate memory for devres\n" ); |
546 | goto err0; |
547 | } |
548 | |
549 | spin_lock_irqsave(&phy_lock, flags); |
550 | |
551 | phy = __of_usb_find_phy(node); |
552 | if (IS_ERR(ptr: phy)) { |
553 | devres_free(res: ptr); |
554 | goto err1; |
555 | } |
556 | |
557 | if (!try_module_get(module: phy->dev->driver->owner)) { |
558 | phy = ERR_PTR(error: -ENODEV); |
559 | devres_free(res: ptr); |
560 | goto err1; |
561 | } |
562 | if (nb) |
563 | usb_register_notifier(x: phy, nb); |
564 | ptr->phy = phy; |
565 | ptr->nb = nb; |
566 | devres_add(dev, res: ptr); |
567 | |
568 | get_device(dev: phy->dev); |
569 | |
570 | err1: |
571 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
572 | |
573 | err0: |
574 | |
575 | return phy; |
576 | } |
577 | EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_node); |
578 | |
579 | /** |
580 | * devm_usb_get_phy_by_phandle - find the USB PHY by phandle |
581 | * @dev: device that requests this phy |
582 | * @phandle: name of the property holding the phy phandle value |
583 | * @index: the index of the phy |
584 | * |
585 | * Returns the phy driver associated with the given phandle value, |
586 | * after getting a refcount to it, -ENODEV if there is no such phy or |
587 | * -EPROBE_DEFER if there is a phandle to the phy, but the device is |
588 | * not yet loaded. While at that, it also associates the device with |
589 | * the phy using devres. On driver detach, release function is invoked |
590 | * on the devres data, then, devres data is freed. |
591 | * |
592 | * For use by USB host and peripheral drivers. |
593 | */ |
594 | struct usb_phy *devm_usb_get_phy_by_phandle(struct device *dev, |
595 | const char *phandle, u8 index) |
596 | { |
597 | struct device_node *node; |
598 | struct usb_phy *phy; |
599 | |
600 | if (!dev->of_node) { |
601 | dev_dbg(dev, "device does not have a device node entry\n" ); |
602 | return ERR_PTR(error: -EINVAL); |
603 | } |
604 | |
605 | node = of_parse_phandle(np: dev->of_node, phandle_name: phandle, index); |
606 | if (!node) { |
607 | dev_dbg(dev, "failed to get %s phandle in %pOF node\n" , phandle, |
608 | dev->of_node); |
609 | return ERR_PTR(error: -ENODEV); |
610 | } |
611 | phy = devm_usb_get_phy_by_node(dev, node, NULL); |
612 | of_node_put(node); |
613 | return phy; |
614 | } |
615 | EXPORT_SYMBOL_GPL(devm_usb_get_phy_by_phandle); |
616 | |
617 | /** |
618 | * devm_usb_put_phy - release the USB PHY |
619 | * @dev: device that wants to release this phy |
620 | * @phy: the phy returned by devm_usb_get_phy() |
621 | * |
622 | * destroys the devres associated with this phy and invokes usb_put_phy |
623 | * to release the phy. |
624 | * |
625 | * For use by USB host and peripheral drivers. |
626 | */ |
627 | void devm_usb_put_phy(struct device *dev, struct usb_phy *phy) |
628 | { |
629 | int r; |
630 | |
631 | r = devres_destroy(dev, release: devm_usb_phy_release, match: devm_usb_phy_match, match_data: phy); |
632 | dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n" ); |
633 | } |
634 | EXPORT_SYMBOL_GPL(devm_usb_put_phy); |
635 | |
636 | /** |
637 | * usb_put_phy - release the USB PHY |
638 | * @x: the phy returned by usb_get_phy() |
639 | * |
640 | * Releases a refcount the caller received from usb_get_phy(). |
641 | * |
642 | * For use by USB host and peripheral drivers. |
643 | */ |
644 | void usb_put_phy(struct usb_phy *x) |
645 | { |
646 | if (x) { |
647 | struct module *owner = x->dev->driver->owner; |
648 | |
649 | put_device(dev: x->dev); |
650 | module_put(module: owner); |
651 | } |
652 | } |
653 | EXPORT_SYMBOL_GPL(usb_put_phy); |
654 | |
655 | /** |
656 | * usb_add_phy: declare the USB PHY |
657 | * @x: the USB phy to be used; or NULL |
658 | * @type: the type of this PHY |
659 | * |
660 | * This call is exclusively for use by phy drivers, which |
661 | * coordinate the activities of drivers for host and peripheral |
662 | * controllers, and in some cases for VBUS current regulation. |
663 | */ |
664 | int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) |
665 | { |
666 | int ret = 0; |
667 | unsigned long flags; |
668 | struct usb_phy *phy; |
669 | |
670 | if (x->type != USB_PHY_TYPE_UNDEFINED) { |
671 | dev_err(x->dev, "not accepting initialized PHY %s\n" , x->label); |
672 | return -EINVAL; |
673 | } |
674 | |
675 | usb_charger_init(usb_phy: x); |
676 | ret = usb_add_extcon(x); |
677 | if (ret) |
678 | return ret; |
679 | |
680 | ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); |
681 | |
682 | spin_lock_irqsave(&phy_lock, flags); |
683 | |
684 | list_for_each_entry(phy, &phy_list, head) { |
685 | if (phy->type == type) { |
686 | ret = -EBUSY; |
687 | dev_err(x->dev, "transceiver type %s already exists\n" , |
688 | usb_phy_type_string(type)); |
689 | goto out; |
690 | } |
691 | } |
692 | |
693 | x->type = type; |
694 | list_add_tail(new: &x->head, head: &phy_list); |
695 | |
696 | out: |
697 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
698 | return ret; |
699 | } |
700 | EXPORT_SYMBOL_GPL(usb_add_phy); |
701 | |
702 | static const struct device_type usb_phy_dev_type = { |
703 | .name = "usb_phy" , |
704 | .uevent = usb_phy_uevent, |
705 | }; |
706 | |
707 | /** |
708 | * usb_add_phy_dev - declare the USB PHY |
709 | * @x: the USB phy to be used; or NULL |
710 | * |
711 | * This call is exclusively for use by phy drivers, which |
712 | * coordinate the activities of drivers for host and peripheral |
713 | * controllers, and in some cases for VBUS current regulation. |
714 | */ |
715 | int usb_add_phy_dev(struct usb_phy *x) |
716 | { |
717 | unsigned long flags; |
718 | int ret; |
719 | |
720 | if (!x->dev) { |
721 | dev_err(x->dev, "no device provided for PHY\n" ); |
722 | return -EINVAL; |
723 | } |
724 | |
725 | usb_charger_init(usb_phy: x); |
726 | ret = usb_add_extcon(x); |
727 | if (ret) |
728 | return ret; |
729 | |
730 | x->dev->type = &usb_phy_dev_type; |
731 | |
732 | ATOMIC_INIT_NOTIFIER_HEAD(&x->notifier); |
733 | |
734 | spin_lock_irqsave(&phy_lock, flags); |
735 | list_add_tail(new: &x->head, head: &phy_list); |
736 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
737 | |
738 | return 0; |
739 | } |
740 | EXPORT_SYMBOL_GPL(usb_add_phy_dev); |
741 | |
742 | /** |
743 | * usb_remove_phy - remove the OTG PHY |
744 | * @x: the USB OTG PHY to be removed; |
745 | * |
746 | * This reverts the effects of usb_add_phy |
747 | */ |
748 | void usb_remove_phy(struct usb_phy *x) |
749 | { |
750 | unsigned long flags; |
751 | |
752 | spin_lock_irqsave(&phy_lock, flags); |
753 | if (x) |
754 | list_del(entry: &x->head); |
755 | spin_unlock_irqrestore(lock: &phy_lock, flags); |
756 | } |
757 | EXPORT_SYMBOL_GPL(usb_remove_phy); |
758 | |
759 | /** |
760 | * usb_phy_set_event - set event to phy event |
761 | * @x: the phy returned by usb_get_phy(); |
762 | * @event: event to set |
763 | * |
764 | * This sets event to phy event |
765 | */ |
766 | void usb_phy_set_event(struct usb_phy *x, unsigned long event) |
767 | { |
768 | x->last_event = event; |
769 | } |
770 | EXPORT_SYMBOL_GPL(usb_phy_set_event); |
771 | |