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.

usb: typec: pd: Register SPR AVS caps with usb_power_delivery class

usb_power_delivery class will now display AVS cap as
`spr_adjustable_voltage_supply`. `maximum_current_9V_to_15V` and
`maximum_current_15V_to_20V` shows the corresponding current limits
in mA. `peak_current` follows the same convention as fixed_supply
where the value reported in the capabilities message is displayed
as is.

Sample output with an SPR AVS capable PD charger:
$cat /sys/class/usb_power_delivery/pd1/source-capabilities/5:spr_adjustable_voltage_supply/maximum_current_9V_to_15V
4000mA

$cat /sys/class/usb_power_delivery/pd1/source-capabilities/5:spr_adjustable_voltage_supply/maximum_current_15V_to_20V
3350mA

$cat /sys/class/usb_power_delivery/pd1/source-capabilities/5:spr_adjustable_voltage_supply/peak_current
0

Signed-off-by: Badhri Jagan Sridharan <badhri@google.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://patch.msgid.link/20251015043017.3382908-2-badhri@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Badhri Jagan Sridharan and committed by
Greg Kroah-Hartman
b4528e1d f82890c9

+118 -5
+28
Documentation/ABI/testing/sysfs-class-usb_power_delivery
··· 254 254 Description: 255 255 The PPS Power Limited bit indicates whether or not the source 256 256 supply will exceed the rated output power if requested. 257 + 258 + Standard Power Range (SPR) Adjustable Voltage Supplies 259 + 260 + What: /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply 261 + Date: Oct 2025 262 + Contact: Badhri Jagan Sridharan <badhri@google.com> 263 + Description: 264 + Adjustable Voltage Supply (AVS) Augmented PDO (APDO). 265 + 266 + What: /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/maximum_current_9V_to_15V 267 + Date: Oct 2025 268 + Contact: Badhri Jagan Sridharan <badhri@google.com> 269 + Description: 270 + Maximum Current for 9V to 15V range in milliamperes. 271 + 272 + What: /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/maximum_current_15V_to_20V 273 + Date: Oct 2025 274 + Contact: Badhri Jagan Sridharan <badhri@google.com> 275 + Description: 276 + Maximum Current for greater than 15V till 20V range in 277 + milliamperes. 278 + 279 + What: /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/peak_current 280 + Date: Oct 2025 281 + Contact: Badhri Jagan Sridharan <badhri@google.com> 282 + Description: 283 + This file shows the value of the Adjustable Voltage Supply Peak Current 284 + Capability field.
+90 -5
drivers/usb/typec/pd.c
··· 360 360 }; 361 361 362 362 /* -------------------------------------------------------------------------- */ 363 + /* Standard Power Range (SPR) Adjustable Voltage Supply (AVS) */ 364 + 365 + static ssize_t 366 + spr_avs_9v_to_15v_max_current_show(struct device *dev, 367 + struct device_attribute *attr, char *buf) 368 + { 369 + return sysfs_emit(buf, "%umA\n", 370 + pdo_spr_avs_apdo_9v_to_15v_max_current_ma(to_pdo(dev)->pdo)); 371 + } 372 + 373 + static ssize_t 374 + spr_avs_15v_to_20v_max_current_show(struct device *dev, 375 + struct device_attribute *attr, char *buf) 376 + { 377 + return sysfs_emit(buf, "%umA\n", 378 + pdo_spr_avs_apdo_15v_to_20v_max_current_ma(to_pdo(dev)->pdo)); 379 + } 380 + 381 + static ssize_t 382 + spr_avs_src_peak_current_show(struct device *dev, 383 + struct device_attribute *attr, char *buf) 384 + { 385 + return sysfs_emit(buf, "%u\n", 386 + pdo_spr_avs_apdo_src_peak_current(to_pdo(dev)->pdo)); 387 + } 388 + 389 + static struct device_attribute spr_avs_9v_to_15v_max_current_attr = { 390 + .attr = { 391 + .name = "maximum_current_9V_to_15V", 392 + .mode = 0444, 393 + }, 394 + .show = spr_avs_9v_to_15v_max_current_show, 395 + }; 396 + 397 + static struct device_attribute spr_avs_15v_to_20v_max_current_attr = { 398 + .attr = { 399 + .name = "maximum_current_15V_to_20V", 400 + .mode = 0444, 401 + }, 402 + .show = spr_avs_15v_to_20v_max_current_show, 403 + }; 404 + 405 + static struct device_attribute spr_avs_src_peak_current_attr = { 406 + .attr = { 407 + .name = "peak_current", 408 + .mode = 0444, 409 + }, 410 + .show = spr_avs_src_peak_current_show, 411 + }; 412 + 413 + static struct attribute *source_spr_avs_attrs[] = { 414 + &spr_avs_9v_to_15v_max_current_attr.attr, 415 + &spr_avs_15v_to_20v_max_current_attr.attr, 416 + &spr_avs_src_peak_current_attr.attr, 417 + NULL 418 + }; 419 + ATTRIBUTE_GROUPS(source_spr_avs); 420 + 421 + static const struct device_type source_spr_avs_type = { 422 + .name = "pdo", 423 + .release = pdo_release, 424 + .groups = source_spr_avs_groups, 425 + }; 426 + 427 + static struct attribute *sink_spr_avs_attrs[] = { 428 + &spr_avs_9v_to_15v_max_current_attr.attr, 429 + &spr_avs_15v_to_20v_max_current_attr.attr, 430 + NULL 431 + }; 432 + ATTRIBUTE_GROUPS(sink_spr_avs); 433 + 434 + static const struct device_type sink_spr_avs_type = { 435 + .name = "pdo", 436 + .release = pdo_release, 437 + .groups = sink_spr_avs_groups, 438 + }; 439 + 440 + /* -------------------------------------------------------------------------- */ 363 441 364 442 static const char * const supply_name[] = { 365 443 [PDO_TYPE_FIXED] = "fixed_supply", ··· 446 368 }; 447 369 448 370 static const char * const apdo_supply_name[] = { 449 - [APDO_TYPE_PPS] = "programmable_supply", 371 + [APDO_TYPE_PPS] = "programmable_supply", 372 + [APDO_TYPE_SPR_AVS] = "spr_adjustable_voltage_supply", 450 373 }; 451 374 452 375 static const struct device_type *source_type[] = { ··· 457 378 }; 458 379 459 380 static const struct device_type *source_apdo_type[] = { 460 - [APDO_TYPE_PPS] = &source_pps_type, 381 + [APDO_TYPE_PPS] = &source_pps_type, 382 + [APDO_TYPE_SPR_AVS] = &source_spr_avs_type, 461 383 }; 462 384 463 385 static const struct device_type *sink_type[] = { ··· 468 388 }; 469 389 470 390 static const struct device_type *sink_apdo_type[] = { 471 - [APDO_TYPE_PPS] = &sink_pps_type, 391 + [APDO_TYPE_PPS] = &sink_pps_type, 392 + [APDO_TYPE_SPR_AVS] = &sink_spr_avs_type, 472 393 }; 473 394 474 395 /* REVISIT: Export when EPR_*_Capabilities need to be supported. */ ··· 488 407 p->object_position = position; 489 408 490 409 if (pdo_type(pdo) == PDO_TYPE_APDO) { 491 - /* FIXME: Only PPS supported for now! Skipping others. */ 492 - if (pdo_apdo_type(pdo) > APDO_TYPE_PPS) { 410 + /* 411 + * FIXME: Only PPS, SPR_AVS supported for now! 412 + * Skipping others. 413 + */ 414 + if (pdo_apdo_type(pdo) != APDO_TYPE_PPS && 415 + pdo_apdo_type(pdo) != APDO_TYPE_SPR_AVS) { 493 416 dev_warn(&cap->dev, "Unknown APDO type. PDO 0x%08x\n", pdo); 494 417 kfree(p); 495 418 return 0;