1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * USB Power Delivery sysfs entries
4 *
5 * Copyright (C) 2022, Intel Corporation
6 * Author: Heikki Krogerus <heikki.krogerus@linux.intel.com>
7 */
8
9 #include <linux/slab.h>
10 #include <linux/usb/pd.h>
11
12 #include "pd.h"
13
14 static DEFINE_IDA(pd_ida);
15
16 static struct class pd_class = {
17 .name = "usb_power_delivery",
18 };
19
20 #define to_pdo(o) container_of(o, struct pdo, dev)
21
22 struct pdo {
23 struct device dev;
24 int object_position;
25 u32 pdo;
26 };
27
pdo_release(struct device * dev)28 static void pdo_release(struct device *dev)
29 {
30 kfree(to_pdo(dev));
31 }
32
33 /* -------------------------------------------------------------------------- */
34 /* Fixed Supply */
35
36 static ssize_t
dual_role_power_show(struct device * dev,struct device_attribute * attr,char * buf)37 dual_role_power_show(struct device *dev, struct device_attribute *attr, char *buf)
38 {
39 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_DUAL_ROLE));
40 }
41 static DEVICE_ATTR_RO(dual_role_power);
42
43 static ssize_t
usb_suspend_supported_show(struct device * dev,struct device_attribute * attr,char * buf)44 usb_suspend_supported_show(struct device *dev, struct device_attribute *attr, char *buf)
45 {
46 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_SUSPEND));
47 }
48 static DEVICE_ATTR_RO(usb_suspend_supported);
49
50 static ssize_t
higher_capability_show(struct device * dev,struct device_attribute * attr,char * buf)51 higher_capability_show(struct device *dev, struct device_attribute *attr, char *buf)
52 {
53 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_HIGHER_CAP));
54 }
55 static DEVICE_ATTR_RO(higher_capability);
56
57 static ssize_t
unconstrained_power_show(struct device * dev,struct device_attribute * attr,char * buf)58 unconstrained_power_show(struct device *dev, struct device_attribute *attr, char *buf)
59 {
60 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_EXTPOWER));
61 }
62 static DEVICE_ATTR_RO(unconstrained_power);
63
64 static ssize_t
usb_communication_capable_show(struct device * dev,struct device_attribute * attr,char * buf)65 usb_communication_capable_show(struct device *dev, struct device_attribute *attr, char *buf)
66 {
67 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_USB_COMM));
68 }
69 static DEVICE_ATTR_RO(usb_communication_capable);
70
71 static ssize_t
dual_role_data_show(struct device * dev,struct device_attribute * attr,char * buf)72 dual_role_data_show(struct device *dev, struct device_attribute *attr, char *buf)
73 {
74 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_DATA_SWAP));
75 }
76 static DEVICE_ATTR_RO(dual_role_data);
77
78 static ssize_t
unchunked_extended_messages_supported_show(struct device * dev,struct device_attribute * attr,char * buf)79 unchunked_extended_messages_supported_show(struct device *dev,
80 struct device_attribute *attr, char *buf)
81 {
82 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & PDO_FIXED_UNCHUNK_EXT));
83 }
84 static DEVICE_ATTR_RO(unchunked_extended_messages_supported);
85
86 /*
87 * REVISIT: Peak Current requires access also to the RDO.
88 static ssize_t
89 peak_current_show(struct device *dev, struct device_attribute *attr, char *buf)
90 {
91 ...
92 }
93 */
94
95 static ssize_t
fast_role_swap_current_show(struct device * dev,struct device_attribute * attr,char * buf)96 fast_role_swap_current_show(struct device *dev, struct device_attribute *attr, char *buf)
97 {
98 return sysfs_emit(buf, "%u\n", (to_pdo(dev)->pdo >> PDO_FIXED_FRS_CURR_SHIFT) & 3);
99 }
100 static DEVICE_ATTR_RO(fast_role_swap_current);
101
voltage_show(struct device * dev,struct device_attribute * attr,char * buf)102 static ssize_t voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
103 {
104 return sysfs_emit(buf, "%umV\n", pdo_fixed_voltage(to_pdo(dev)->pdo));
105 }
106 static DEVICE_ATTR_RO(voltage);
107
108 /* Shared with Variable supplies, both source and sink */
current_show(struct device * dev,struct device_attribute * attr,char * buf)109 static ssize_t current_show(struct device *dev, struct device_attribute *attr, char *buf)
110 {
111 return sysfs_emit(buf, "%umA\n", pdo_max_current(to_pdo(dev)->pdo));
112 }
113
114 /* Shared with Variable type supplies */
115 static struct device_attribute maximum_current_attr = {
116 .attr = {
117 .name = "maximum_current",
118 .mode = 0444,
119 },
120 .show = current_show,
121 };
122
123 static struct device_attribute operational_current_attr = {
124 .attr = {
125 .name = "operational_current",
126 .mode = 0444,
127 },
128 .show = current_show,
129 };
130
131 static struct attribute *source_fixed_supply_attrs[] = {
132 &dev_attr_dual_role_power.attr,
133 &dev_attr_usb_suspend_supported.attr,
134 &dev_attr_unconstrained_power.attr,
135 &dev_attr_usb_communication_capable.attr,
136 &dev_attr_dual_role_data.attr,
137 &dev_attr_unchunked_extended_messages_supported.attr,
138 /*&dev_attr_peak_current.attr,*/
139 &dev_attr_voltage.attr,
140 &maximum_current_attr.attr,
141 NULL
142 };
143
fixed_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)144 static umode_t fixed_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
145 {
146 if (to_pdo(kobj_to_dev(kobj))->object_position &&
147 /*attr != &dev_attr_peak_current.attr &&*/
148 attr != &dev_attr_voltage.attr &&
149 attr != &maximum_current_attr.attr &&
150 attr != &operational_current_attr.attr)
151 return 0;
152
153 return attr->mode;
154 }
155
156 static const struct attribute_group source_fixed_supply_group = {
157 .is_visible = fixed_attr_is_visible,
158 .attrs = source_fixed_supply_attrs,
159 };
160 __ATTRIBUTE_GROUPS(source_fixed_supply);
161
162 static struct device_type source_fixed_supply_type = {
163 .name = "pdo",
164 .release = pdo_release,
165 .groups = source_fixed_supply_groups,
166 };
167
168 static struct attribute *sink_fixed_supply_attrs[] = {
169 &dev_attr_dual_role_power.attr,
170 &dev_attr_higher_capability.attr,
171 &dev_attr_unconstrained_power.attr,
172 &dev_attr_usb_communication_capable.attr,
173 &dev_attr_dual_role_data.attr,
174 &dev_attr_unchunked_extended_messages_supported.attr,
175 &dev_attr_fast_role_swap_current.attr,
176 &dev_attr_voltage.attr,
177 &operational_current_attr.attr,
178 NULL
179 };
180
181 static const struct attribute_group sink_fixed_supply_group = {
182 .is_visible = fixed_attr_is_visible,
183 .attrs = sink_fixed_supply_attrs,
184 };
185 __ATTRIBUTE_GROUPS(sink_fixed_supply);
186
187 static struct device_type sink_fixed_supply_type = {
188 .name = "pdo",
189 .release = pdo_release,
190 .groups = sink_fixed_supply_groups,
191 };
192
193 /* -------------------------------------------------------------------------- */
194 /* Variable Supply */
195
196 static ssize_t
maximum_voltage_show(struct device * dev,struct device_attribute * attr,char * buf)197 maximum_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
198 {
199 return sysfs_emit(buf, "%umV\n", pdo_max_voltage(to_pdo(dev)->pdo));
200 }
201 static DEVICE_ATTR_RO(maximum_voltage);
202
203 static ssize_t
minimum_voltage_show(struct device * dev,struct device_attribute * attr,char * buf)204 minimum_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
205 {
206 return sysfs_emit(buf, "%umV\n", pdo_min_voltage(to_pdo(dev)->pdo));
207 }
208 static DEVICE_ATTR_RO(minimum_voltage);
209
210 static struct attribute *source_variable_supply_attrs[] = {
211 &dev_attr_maximum_voltage.attr,
212 &dev_attr_minimum_voltage.attr,
213 &maximum_current_attr.attr,
214 NULL
215 };
216 ATTRIBUTE_GROUPS(source_variable_supply);
217
218 static struct device_type source_variable_supply_type = {
219 .name = "pdo",
220 .release = pdo_release,
221 .groups = source_variable_supply_groups,
222 };
223
224 static struct attribute *sink_variable_supply_attrs[] = {
225 &dev_attr_maximum_voltage.attr,
226 &dev_attr_minimum_voltage.attr,
227 &operational_current_attr.attr,
228 NULL
229 };
230 ATTRIBUTE_GROUPS(sink_variable_supply);
231
232 static struct device_type sink_variable_supply_type = {
233 .name = "pdo",
234 .release = pdo_release,
235 .groups = sink_variable_supply_groups,
236 };
237
238 /* -------------------------------------------------------------------------- */
239 /* Battery */
240
241 static ssize_t
maximum_power_show(struct device * dev,struct device_attribute * attr,char * buf)242 maximum_power_show(struct device *dev, struct device_attribute *attr, char *buf)
243 {
244 return sysfs_emit(buf, "%umW\n", pdo_max_power(to_pdo(dev)->pdo));
245 }
246 static DEVICE_ATTR_RO(maximum_power);
247
248 static ssize_t
operational_power_show(struct device * dev,struct device_attribute * attr,char * buf)249 operational_power_show(struct device *dev, struct device_attribute *attr, char *buf)
250 {
251 return sysfs_emit(buf, "%umW\n", pdo_max_power(to_pdo(dev)->pdo));
252 }
253 static DEVICE_ATTR_RO(operational_power);
254
255 static struct attribute *source_battery_attrs[] = {
256 &dev_attr_maximum_voltage.attr,
257 &dev_attr_minimum_voltage.attr,
258 &dev_attr_maximum_power.attr,
259 NULL
260 };
261 ATTRIBUTE_GROUPS(source_battery);
262
263 static struct device_type source_battery_type = {
264 .name = "pdo",
265 .release = pdo_release,
266 .groups = source_battery_groups,
267 };
268
269 static struct attribute *sink_battery_attrs[] = {
270 &dev_attr_maximum_voltage.attr,
271 &dev_attr_minimum_voltage.attr,
272 &dev_attr_operational_power.attr,
273 NULL
274 };
275 ATTRIBUTE_GROUPS(sink_battery);
276
277 static struct device_type sink_battery_type = {
278 .name = "pdo",
279 .release = pdo_release,
280 .groups = sink_battery_groups,
281 };
282
283 /* -------------------------------------------------------------------------- */
284 /* Standard Power Range (SPR) Programmable Power Supply (PPS) */
285
286 static ssize_t
pps_power_limited_show(struct device * dev,struct device_attribute * attr,char * buf)287 pps_power_limited_show(struct device *dev, struct device_attribute *attr, char *buf)
288 {
289 return sysfs_emit(buf, "%u\n", !!(to_pdo(dev)->pdo & BIT(27)));
290 }
291 static DEVICE_ATTR_RO(pps_power_limited);
292
293 static ssize_t
pps_max_voltage_show(struct device * dev,struct device_attribute * attr,char * buf)294 pps_max_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
295 {
296 return sysfs_emit(buf, "%umV\n", pdo_pps_apdo_max_voltage(to_pdo(dev)->pdo));
297 }
298
299 static ssize_t
pps_min_voltage_show(struct device * dev,struct device_attribute * attr,char * buf)300 pps_min_voltage_show(struct device *dev, struct device_attribute *attr, char *buf)
301 {
302 return sysfs_emit(buf, "%umV\n", pdo_pps_apdo_min_voltage(to_pdo(dev)->pdo));
303 }
304
305 static ssize_t
pps_max_current_show(struct device * dev,struct device_attribute * attr,char * buf)306 pps_max_current_show(struct device *dev, struct device_attribute *attr, char *buf)
307 {
308 return sysfs_emit(buf, "%umA\n", pdo_pps_apdo_max_current(to_pdo(dev)->pdo));
309 }
310
311 static struct device_attribute pps_max_voltage_attr = {
312 .attr = {
313 .name = "maximum_voltage",
314 .mode = 0444,
315 },
316 .show = pps_max_voltage_show,
317 };
318
319 static struct device_attribute pps_min_voltage_attr = {
320 .attr = {
321 .name = "minimum_voltage",
322 .mode = 0444,
323 },
324 .show = pps_min_voltage_show,
325 };
326
327 static struct device_attribute pps_max_current_attr = {
328 .attr = {
329 .name = "maximum_current",
330 .mode = 0444,
331 },
332 .show = pps_max_current_show,
333 };
334
335 static struct attribute *source_pps_attrs[] = {
336 &dev_attr_pps_power_limited.attr,
337 &pps_max_voltage_attr.attr,
338 &pps_min_voltage_attr.attr,
339 &pps_max_current_attr.attr,
340 NULL
341 };
342 ATTRIBUTE_GROUPS(source_pps);
343
344 static struct device_type source_pps_type = {
345 .name = "pdo",
346 .release = pdo_release,
347 .groups = source_pps_groups,
348 };
349
350 static struct attribute *sink_pps_attrs[] = {
351 &pps_max_voltage_attr.attr,
352 &pps_min_voltage_attr.attr,
353 &pps_max_current_attr.attr,
354 NULL
355 };
356 ATTRIBUTE_GROUPS(sink_pps);
357
358 static struct device_type sink_pps_type = {
359 .name = "pdo",
360 .release = pdo_release,
361 .groups = sink_pps_groups,
362 };
363
364 /* -------------------------------------------------------------------------- */
365
366 static const char * const supply_name[] = {
367 [PDO_TYPE_FIXED] = "fixed_supply",
368 [PDO_TYPE_BATT] = "battery",
369 [PDO_TYPE_VAR] = "variable_supply",
370 };
371
372 static const char * const apdo_supply_name[] = {
373 [APDO_TYPE_PPS] = "programmable_supply",
374 };
375
376 static struct device_type *source_type[] = {
377 [PDO_TYPE_FIXED] = &source_fixed_supply_type,
378 [PDO_TYPE_BATT] = &source_battery_type,
379 [PDO_TYPE_VAR] = &source_variable_supply_type,
380 };
381
382 static struct device_type *source_apdo_type[] = {
383 [APDO_TYPE_PPS] = &source_pps_type,
384 };
385
386 static struct device_type *sink_type[] = {
387 [PDO_TYPE_FIXED] = &sink_fixed_supply_type,
388 [PDO_TYPE_BATT] = &sink_battery_type,
389 [PDO_TYPE_VAR] = &sink_variable_supply_type,
390 };
391
392 static struct device_type *sink_apdo_type[] = {
393 [APDO_TYPE_PPS] = &sink_pps_type,
394 };
395
396 /* REVISIT: Export when EPR_*_Capabilities need to be supported. */
add_pdo(struct usb_power_delivery_capabilities * cap,u32 pdo,int position)397 static int add_pdo(struct usb_power_delivery_capabilities *cap, u32 pdo, int position)
398 {
399 struct device_type *type;
400 const char *name;
401 struct pdo *p;
402 int ret;
403
404 p = kzalloc(sizeof(*p), GFP_KERNEL);
405 if (!p)
406 return -ENOMEM;
407
408 p->pdo = pdo;
409 p->object_position = position;
410
411 if (pdo_type(pdo) == PDO_TYPE_APDO) {
412 /* FIXME: Only PPS supported for now! Skipping others. */
413 if (pdo_apdo_type(pdo) > APDO_TYPE_PPS) {
414 dev_warn(&cap->dev, "Unknown APDO type. PDO 0x%08x\n", pdo);
415 kfree(p);
416 return 0;
417 }
418
419 if (is_source(cap->role))
420 type = source_apdo_type[pdo_apdo_type(pdo)];
421 else
422 type = sink_apdo_type[pdo_apdo_type(pdo)];
423
424 name = apdo_supply_name[pdo_apdo_type(pdo)];
425 } else {
426 if (is_source(cap->role))
427 type = source_type[pdo_type(pdo)];
428 else
429 type = sink_type[pdo_type(pdo)];
430
431 name = supply_name[pdo_type(pdo)];
432 }
433
434 p->dev.parent = &cap->dev;
435 p->dev.type = type;
436 dev_set_name(&p->dev, "%u:%s", position + 1, name);
437
438 ret = device_register(&p->dev);
439 if (ret) {
440 put_device(&p->dev);
441 return ret;
442 }
443
444 return 0;
445 }
446
remove_pdo(struct device * dev,void * data)447 static int remove_pdo(struct device *dev, void *data)
448 {
449 device_unregister(dev);
450 return 0;
451 }
452
453 /* -------------------------------------------------------------------------- */
454
455 static const char * const cap_name[] = {
456 [TYPEC_SINK] = "sink-capabilities",
457 [TYPEC_SOURCE] = "source-capabilities",
458 };
459
pd_capabilities_release(struct device * dev)460 static void pd_capabilities_release(struct device *dev)
461 {
462 kfree(to_usb_power_delivery_capabilities(dev));
463 }
464
465 static struct device_type pd_capabilities_type = {
466 .name = "capabilities",
467 .release = pd_capabilities_release,
468 };
469
470 /**
471 * usb_power_delivery_register_capabilities - Register a set of capabilities.
472 * @pd: The USB PD instance that the capabilities belong to.
473 * @desc: Description of the Capablities Message.
474 *
475 * This function registers a Capabilities Message described in @desc. The
476 * capabilities will have their own sub-directory under @pd in sysfs.
477 *
478 * The function returns pointer to struct usb_power_delivery_capabilities, or
479 * ERR_PRT(errno).
480 */
481 struct usb_power_delivery_capabilities *
usb_power_delivery_register_capabilities(struct usb_power_delivery * pd,struct usb_power_delivery_capabilities_desc * desc)482 usb_power_delivery_register_capabilities(struct usb_power_delivery *pd,
483 struct usb_power_delivery_capabilities_desc *desc)
484 {
485 struct usb_power_delivery_capabilities *cap;
486 int ret;
487 int i;
488
489 cap = kzalloc(sizeof(*cap), GFP_KERNEL);
490 if (!cap)
491 return ERR_PTR(-ENOMEM);
492
493 cap->pd = pd;
494 cap->role = desc->role;
495
496 cap->dev.parent = &pd->dev;
497 cap->dev.type = &pd_capabilities_type;
498 dev_set_name(&cap->dev, "%s", cap_name[cap->role]);
499
500 ret = device_register(&cap->dev);
501 if (ret) {
502 put_device(&cap->dev);
503 return ERR_PTR(ret);
504 }
505
506 for (i = 0; i < PDO_MAX_OBJECTS && desc->pdo[i]; i++) {
507 ret = add_pdo(cap, desc->pdo[i], i);
508 if (ret) {
509 usb_power_delivery_unregister_capabilities(cap);
510 return ERR_PTR(ret);
511 }
512 }
513
514 return cap;
515 }
516 EXPORT_SYMBOL_GPL(usb_power_delivery_register_capabilities);
517
518 /**
519 * usb_power_delivery_unregister_capabilities - Unregister a set of capabilities
520 * @cap: The capabilities
521 */
usb_power_delivery_unregister_capabilities(struct usb_power_delivery_capabilities * cap)522 void usb_power_delivery_unregister_capabilities(struct usb_power_delivery_capabilities *cap)
523 {
524 if (!cap)
525 return;
526
527 device_for_each_child(&cap->dev, NULL, remove_pdo);
528 device_unregister(&cap->dev);
529 }
530 EXPORT_SYMBOL_GPL(usb_power_delivery_unregister_capabilities);
531
532 /* -------------------------------------------------------------------------- */
533
revision_show(struct device * dev,struct device_attribute * attr,char * buf)534 static ssize_t revision_show(struct device *dev, struct device_attribute *attr, char *buf)
535 {
536 struct usb_power_delivery *pd = to_usb_power_delivery(dev);
537
538 return sysfs_emit(buf, "%u.%u\n", (pd->revision >> 8) & 0xff, (pd->revision >> 4) & 0xf);
539 }
540 static DEVICE_ATTR_RO(revision);
541
version_show(struct device * dev,struct device_attribute * attr,char * buf)542 static ssize_t version_show(struct device *dev, struct device_attribute *attr, char *buf)
543 {
544 struct usb_power_delivery *pd = to_usb_power_delivery(dev);
545
546 return sysfs_emit(buf, "%u.%u\n", (pd->version >> 8) & 0xff, (pd->version >> 4) & 0xf);
547 }
548 static DEVICE_ATTR_RO(version);
549
550 static struct attribute *pd_attrs[] = {
551 &dev_attr_revision.attr,
552 &dev_attr_version.attr,
553 NULL
554 };
555
pd_attr_is_visible(struct kobject * kobj,struct attribute * attr,int n)556 static umode_t pd_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
557 {
558 struct usb_power_delivery *pd = to_usb_power_delivery(kobj_to_dev(kobj));
559
560 if (attr == &dev_attr_version.attr && !pd->version)
561 return 0;
562
563 return attr->mode;
564 }
565
566 static const struct attribute_group pd_group = {
567 .is_visible = pd_attr_is_visible,
568 .attrs = pd_attrs,
569 };
570 __ATTRIBUTE_GROUPS(pd);
571
pd_release(struct device * dev)572 static void pd_release(struct device *dev)
573 {
574 struct usb_power_delivery *pd = to_usb_power_delivery(dev);
575
576 ida_simple_remove(&pd_ida, pd->id);
577 kfree(pd);
578 }
579
580 static struct device_type pd_type = {
581 .name = "usb_power_delivery",
582 .release = pd_release,
583 .groups = pd_groups,
584 };
585
usb_power_delivery_find(const char * name)586 struct usb_power_delivery *usb_power_delivery_find(const char *name)
587 {
588 struct device *dev;
589
590 dev = class_find_device_by_name(&pd_class, name);
591
592 return dev ? to_usb_power_delivery(dev) : NULL;
593 }
594
595 /**
596 * usb_power_delivery_register - Register USB Power Delivery Support.
597 * @parent: Parent device.
598 * @desc: Description of the USB PD contract.
599 *
600 * This routine can be used to register USB Power Delivery capabilities that a
601 * device or devices can support. These capabilities represent all the
602 * capabilities that can be negotiated with a partner, so not only the Power
603 * Capabilities that are negotiated using the USB PD Capabilities Message.
604 *
605 * The USB Power Delivery Support object that this routine generates can be used
606 * as the parent object for all the actual USB Power Delivery Messages and
607 * objects that can be negotiated with the partner.
608 *
609 * Returns handle to struct usb_power_delivery or ERR_PTR.
610 */
611 struct usb_power_delivery *
usb_power_delivery_register(struct device * parent,struct usb_power_delivery_desc * desc)612 usb_power_delivery_register(struct device *parent, struct usb_power_delivery_desc *desc)
613 {
614 struct usb_power_delivery *pd;
615 int ret;
616
617 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
618 if (!pd)
619 return ERR_PTR(-ENOMEM);
620
621 ret = ida_simple_get(&pd_ida, 0, 0, GFP_KERNEL);
622 if (ret < 0) {
623 kfree(pd);
624 return ERR_PTR(ret);
625 }
626
627 pd->id = ret;
628 pd->revision = desc->revision;
629 pd->version = desc->version;
630
631 pd->dev.parent = parent;
632 pd->dev.type = &pd_type;
633 pd->dev.class = &pd_class;
634 dev_set_name(&pd->dev, "pd%d", pd->id);
635
636 ret = device_register(&pd->dev);
637 if (ret) {
638 put_device(&pd->dev);
639 return ERR_PTR(ret);
640 }
641
642 return pd;
643 }
644 EXPORT_SYMBOL_GPL(usb_power_delivery_register);
645
646 /**
647 * usb_power_delivery_unregister - Unregister USB Power Delivery Support.
648 * @pd: The USB PD contract.
649 */
usb_power_delivery_unregister(struct usb_power_delivery * pd)650 void usb_power_delivery_unregister(struct usb_power_delivery *pd)
651 {
652 if (IS_ERR_OR_NULL(pd))
653 return;
654
655 device_unregister(&pd->dev);
656 }
657 EXPORT_SYMBOL_GPL(usb_power_delivery_unregister);
658
659 /**
660 * usb_power_delivery_link_device - Link device to its USB PD object.
661 * @pd: The USB PD instance.
662 * @dev: The device.
663 *
664 * This function can be used to create a symlink named "usb_power_delivery" for
665 * @dev that points to @pd.
666 */
usb_power_delivery_link_device(struct usb_power_delivery * pd,struct device * dev)667 int usb_power_delivery_link_device(struct usb_power_delivery *pd, struct device *dev)
668 {
669 int ret;
670
671 if (IS_ERR_OR_NULL(pd) || !dev)
672 return 0;
673
674 ret = sysfs_create_link(&dev->kobj, &pd->dev.kobj, "usb_power_delivery");
675 if (ret)
676 return ret;
677
678 get_device(&pd->dev);
679 get_device(dev);
680
681 return 0;
682 }
683 EXPORT_SYMBOL_GPL(usb_power_delivery_link_device);
684
685 /**
686 * usb_power_delivery_unlink_device - Unlink device from its USB PD object.
687 * @pd: The USB PD instance.
688 * @dev: The device.
689 *
690 * Remove the symlink that was previously created with pd_link_device().
691 */
usb_power_delivery_unlink_device(struct usb_power_delivery * pd,struct device * dev)692 void usb_power_delivery_unlink_device(struct usb_power_delivery *pd, struct device *dev)
693 {
694 if (IS_ERR_OR_NULL(pd) || !dev)
695 return;
696
697 sysfs_remove_link(&dev->kobj, "usb_power_delivery");
698 put_device(&pd->dev);
699 put_device(dev);
700 }
701 EXPORT_SYMBOL_GPL(usb_power_delivery_unlink_device);
702
703 /* -------------------------------------------------------------------------- */
704
usb_power_delivery_init(void)705 int __init usb_power_delivery_init(void)
706 {
707 return class_register(&pd_class);
708 }
709
usb_power_delivery_exit(void)710 void __exit usb_power_delivery_exit(void)
711 {
712 ida_destroy(&pd_ida);
713 class_unregister(&pd_class);
714 }
715