Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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