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

power: supply: Add 'usb_type' property and supporting code

This commit adds the 'usb_type' property to represent USB supplies
which can report a number of different types based on a connection
event.

Examples of this already exist in drivers whereby the existing 'type'
property is updated, based on an event, to represent what was
connected (e.g. USB, USB_DCP, USB_ACA, ...). Current implementations
however don't show all supported connectable types, so this knowledge
has to be exlicitly known for each driver that supports this.

The 'usb_type' property is intended to fill this void and show users
all possible USB types supported by a driver. The property, when read,
shows all available types for the driver, and the one currently chosen
is highlighted/bracketed. It is expected that the 'type' property
would then just show the top-level type 'USB', and this would be
static.

Currently the 'usb_type' enum contains all of the USB variant types
that exist for the 'type' enum at this time, and in addition has
SDP and PPS types. The mirroring is intentional so as to not impact
existing usage of the 'type' property.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Adam Thomson and committed by
Greg Kroah-Hartman
cf450041 1ac3eef7

+80 -1
+12
Documentation/ABI/testing/sysfs-class-power
··· 409 409 Access: Read 410 410 Valid values: Represented in 1/10 Degrees Celsius 411 411 412 + What: /sys/class/power_supply/<supply_name>/usb_type 413 + Date: March 2018 414 + Contact: linux-pm@vger.kernel.org 415 + Description: 416 + Reports what type of USB connection is currently active for 417 + the supply, for example it can show if USB-PD capable source 418 + is attached. 419 + 420 + Access: Read-Only 421 + Valid values: "Unknown", "SDP", "DCP", "CDP", "ACA", "C", "PD", 422 + "PD_DRP", "PD_PPS", "BrickID" 423 + 412 424 What: /sys/class/power_supply/<supply_name>/voltage_max 413 425 Date: January 2008 414 426 Contact: linux-pm@vger.kernel.org
+7 -1
drivers/power/supply/power_supply_core.c
··· 843 843 { 844 844 struct device *dev; 845 845 struct power_supply *psy; 846 - int rc; 846 + int i, rc; 847 847 848 848 if (!parent) 849 849 pr_warn("%s: Expected proper parent device for '%s'\n", ··· 851 851 852 852 if (!desc || !desc->name || !desc->properties || !desc->num_properties) 853 853 return ERR_PTR(-EINVAL); 854 + 855 + for (i = 0; i < desc->num_properties; ++i) { 856 + if ((desc->properties[i] == POWER_SUPPLY_PROP_USB_TYPE) && 857 + (!desc->usb_types || !desc->num_usb_types)) 858 + return ERR_PTR(-EINVAL); 859 + } 854 860 855 861 psy = kzalloc(sizeof(*psy), GFP_KERNEL); 856 862 if (!psy)
+45
drivers/power/supply/power_supply_sysfs.c
··· 46 46 "USB_PD", "USB_PD_DRP", "BrickID" 47 47 }; 48 48 49 + static const char * const power_supply_usb_type_text[] = { 50 + "Unknown", "SDP", "DCP", "CDP", "ACA", "C", 51 + "PD", "PD_DRP", "PD_PPS", "BrickID" 52 + }; 53 + 49 54 static const char * const power_supply_status_text[] = { 50 55 "Unknown", "Charging", "Discharging", "Not charging", "Full" 51 56 }; ··· 77 72 static const char * const power_supply_scope_text[] = { 78 73 "Unknown", "System", "Device" 79 74 }; 75 + 76 + static ssize_t power_supply_show_usb_type(struct device *dev, 77 + enum power_supply_usb_type *usb_types, 78 + ssize_t num_usb_types, 79 + union power_supply_propval *value, 80 + char *buf) 81 + { 82 + enum power_supply_usb_type usb_type; 83 + ssize_t count = 0; 84 + bool match = false; 85 + int i; 86 + 87 + for (i = 0; i < num_usb_types; ++i) { 88 + usb_type = usb_types[i]; 89 + 90 + if (value->intval == usb_type) { 91 + count += sprintf(buf + count, "[%s] ", 92 + power_supply_usb_type_text[usb_type]); 93 + match = true; 94 + } else { 95 + count += sprintf(buf + count, "%s ", 96 + power_supply_usb_type_text[usb_type]); 97 + } 98 + } 99 + 100 + if (!match) { 101 + dev_warn(dev, "driver reporting unsupported connected type\n"); 102 + return -EINVAL; 103 + } 104 + 105 + if (count) 106 + buf[count - 1] = '\n'; 107 + 108 + return count; 109 + } 80 110 81 111 static ssize_t power_supply_show_property(struct device *dev, 82 112 struct device_attribute *attr, ··· 155 115 else if (off == POWER_SUPPLY_PROP_TYPE) 156 116 return sprintf(buf, "%s\n", 157 117 power_supply_type_text[value.intval]); 118 + else if (off == POWER_SUPPLY_PROP_USB_TYPE) 119 + return power_supply_show_usb_type(dev, psy->desc->usb_types, 120 + psy->desc->num_usb_types, 121 + &value, buf); 158 122 else if (off == POWER_SUPPLY_PROP_SCOPE) 159 123 return sprintf(buf, "%s\n", 160 124 power_supply_scope_text[value.intval]); ··· 285 241 POWER_SUPPLY_ATTR(time_to_full_now), 286 242 POWER_SUPPLY_ATTR(time_to_full_avg), 287 243 POWER_SUPPLY_ATTR(type), 244 + POWER_SUPPLY_ATTR(usb_type), 288 245 POWER_SUPPLY_ATTR(scope), 289 246 POWER_SUPPLY_ATTR(precharge_current), 290 247 POWER_SUPPLY_ATTR(charge_term_current),
+16
include/linux/power_supply.h
··· 145 145 POWER_SUPPLY_PROP_TIME_TO_FULL_NOW, 146 146 POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 147 147 POWER_SUPPLY_PROP_TYPE, /* use power_supply.type instead */ 148 + POWER_SUPPLY_PROP_USB_TYPE, 148 149 POWER_SUPPLY_PROP_SCOPE, 149 150 POWER_SUPPLY_PROP_PRECHARGE_CURRENT, 150 151 POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT, ··· 169 168 POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery Port */ 170 169 POWER_SUPPLY_TYPE_USB_PD_DRP, /* PD Dual Role Port */ 171 170 POWER_SUPPLY_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ 171 + }; 172 + 173 + enum power_supply_usb_type { 174 + POWER_SUPPLY_USB_TYPE_UNKNOWN = 0, 175 + POWER_SUPPLY_USB_TYPE_SDP, /* Standard Downstream Port */ 176 + POWER_SUPPLY_USB_TYPE_DCP, /* Dedicated Charging Port */ 177 + POWER_SUPPLY_USB_TYPE_CDP, /* Charging Downstream Port */ 178 + POWER_SUPPLY_USB_TYPE_ACA, /* Accessory Charger Adapters */ 179 + POWER_SUPPLY_USB_TYPE_C, /* Type C Port */ 180 + POWER_SUPPLY_USB_TYPE_PD, /* Power Delivery Port */ 181 + POWER_SUPPLY_USB_TYPE_PD_DRP, /* PD Dual Role Port */ 182 + POWER_SUPPLY_USB_TYPE_PD_PPS, /* PD Programmable Power Supply */ 183 + POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID, /* Apple Charging Method */ 172 184 }; 173 185 174 186 enum power_supply_notifier_events { ··· 210 196 struct power_supply_desc { 211 197 const char *name; 212 198 enum power_supply_type type; 199 + enum power_supply_usb_type *usb_types; 200 + size_t num_usb_types; 213 201 enum power_supply_property *properties; 214 202 size_t num_properties; 215 203