]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: typec: pd: Register SPR AVS caps with usb_power_delivery class
authorBadhri Jagan Sridharan <badhri@google.com>
Wed, 15 Oct 2025 04:30:14 +0000 (04:30 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Oct 2025 08:58:31 +0000 (10:58 +0200)
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>
Documentation/ABI/testing/sysfs-class-usb_power_delivery
drivers/usb/typec/pd.c

index 61d233c320ea7f6e2e81890f166c89f65e9b0e84..c754458a527e7f32aeb951a72754f63fed61265b 100644 (file)
@@ -254,3 +254,31 @@ Contact:   Heikki Krogerus <heikki.krogerus@linux.intel.com>
 Description:
                The PPS Power Limited bit indicates whether or not the source
                supply will exceed the rated output power if requested.
+
+Standard Power Range (SPR) Adjustable Voltage Supplies
+
+What:          /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply
+Date:          Oct 2025
+Contact:       Badhri Jagan Sridharan <badhri@google.com>
+Description:
+               Adjustable Voltage Supply (AVS) Augmented PDO (APDO).
+
+What:          /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/maximum_current_9V_to_15V
+Date:          Oct 2025
+Contact:       Badhri Jagan Sridharan <badhri@google.com>
+Description:
+               Maximum Current for 9V to 15V range in milliamperes.
+
+What:          /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/maximum_current_15V_to_20V
+Date:          Oct 2025
+Contact:       Badhri Jagan Sridharan <badhri@google.com>
+Description:
+               Maximum Current for greater than 15V till 20V range in
+               milliamperes.
+
+What:          /sys/class/usb_power_delivery/.../<capability>/<position>:spr_adjustable_voltage_supply/peak_current
+Date:          Oct 2025
+Contact:       Badhri Jagan Sridharan <badhri@google.com>
+Description:
+               This file shows the value of the Adjustable Voltage Supply Peak Current
+               Capability field.
index d78c04a421bc2e7a52cdfe659245887bbae870ae..67f20b5ffdf48bfd1bb4f312ee886e50a9fbaad7 100644 (file)
@@ -359,6 +359,84 @@ static const struct device_type sink_pps_type = {
        .groups = sink_pps_groups,
 };
 
+/* -------------------------------------------------------------------------- */
+/* Standard Power Range (SPR) Adjustable Voltage Supply (AVS) */
+
+static ssize_t
+spr_avs_9v_to_15v_max_current_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%umA\n",
+                         pdo_spr_avs_apdo_9v_to_15v_max_current_ma(to_pdo(dev)->pdo));
+}
+
+static ssize_t
+spr_avs_15v_to_20v_max_current_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%umA\n",
+                         pdo_spr_avs_apdo_15v_to_20v_max_current_ma(to_pdo(dev)->pdo));
+}
+
+static ssize_t
+spr_avs_src_peak_current_show(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       return sysfs_emit(buf, "%u\n",
+                         pdo_spr_avs_apdo_src_peak_current(to_pdo(dev)->pdo));
+}
+
+static struct device_attribute spr_avs_9v_to_15v_max_current_attr = {
+       .attr = {
+               .name = "maximum_current_9V_to_15V",
+               .mode = 0444,
+       },
+       .show = spr_avs_9v_to_15v_max_current_show,
+};
+
+static struct device_attribute spr_avs_15v_to_20v_max_current_attr = {
+       .attr = {
+               .name = "maximum_current_15V_to_20V",
+               .mode = 0444,
+       },
+       .show = spr_avs_15v_to_20v_max_current_show,
+};
+
+static struct device_attribute spr_avs_src_peak_current_attr = {
+       .attr = {
+               .name = "peak_current",
+               .mode = 0444,
+       },
+       .show = spr_avs_src_peak_current_show,
+};
+
+static struct attribute *source_spr_avs_attrs[] = {
+       &spr_avs_9v_to_15v_max_current_attr.attr,
+       &spr_avs_15v_to_20v_max_current_attr.attr,
+       &spr_avs_src_peak_current_attr.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(source_spr_avs);
+
+static const struct device_type source_spr_avs_type = {
+       .name = "pdo",
+       .release = pdo_release,
+       .groups = source_spr_avs_groups,
+};
+
+static struct attribute *sink_spr_avs_attrs[] = {
+       &spr_avs_9v_to_15v_max_current_attr.attr,
+       &spr_avs_15v_to_20v_max_current_attr.attr,
+       NULL
+};
+ATTRIBUTE_GROUPS(sink_spr_avs);
+
+static const struct device_type sink_spr_avs_type = {
+       .name = "pdo",
+       .release = pdo_release,
+       .groups = sink_spr_avs_groups,
+};
+
 /* -------------------------------------------------------------------------- */
 
 static const char * const supply_name[] = {
@@ -368,7 +446,8 @@ static const char * const supply_name[] = {
 };
 
 static const char * const apdo_supply_name[] = {
-       [APDO_TYPE_PPS]  = "programmable_supply",
+       [APDO_TYPE_PPS]      = "programmable_supply",
+       [APDO_TYPE_SPR_AVS]  = "spr_adjustable_voltage_supply",
 };
 
 static const struct device_type *source_type[] = {
@@ -378,7 +457,8 @@ static const struct device_type *source_type[] = {
 };
 
 static const struct device_type *source_apdo_type[] = {
-       [APDO_TYPE_PPS]  = &source_pps_type,
+       [APDO_TYPE_PPS]     = &source_pps_type,
+       [APDO_TYPE_SPR_AVS] = &source_spr_avs_type,
 };
 
 static const struct device_type *sink_type[] = {
@@ -388,7 +468,8 @@ static const struct device_type *sink_type[] = {
 };
 
 static const struct device_type *sink_apdo_type[] = {
-       [APDO_TYPE_PPS]  = &sink_pps_type,
+       [APDO_TYPE_PPS]     = &sink_pps_type,
+       [APDO_TYPE_SPR_AVS] = &sink_spr_avs_type,
 };
 
 /* REVISIT: Export when EPR_*_Capabilities need to be supported. */
@@ -407,8 +488,12 @@ static int add_pdo(struct usb_power_delivery_capabilities *cap, u32 pdo, int pos
        p->object_position = position;
 
        if (pdo_type(pdo) == PDO_TYPE_APDO) {
-               /* FIXME: Only PPS supported for now! Skipping others. */
-               if (pdo_apdo_type(pdo) > APDO_TYPE_PPS) {
+               /*
+                * FIXME: Only PPS, SPR_AVS supported for now!
+                * Skipping others.
+                */
+               if (pdo_apdo_type(pdo) != APDO_TYPE_PPS &&
+                   pdo_apdo_type(pdo) != APDO_TYPE_SPR_AVS) {
                        dev_warn(&cap->dev, "Unknown APDO type. PDO 0x%08x\n", pdo);
                        kfree(p);
                        return 0;