From: Andrei Kuchynski Date: Mon, 3 Feb 2025 12:59:46 +0000 (+0000) Subject: platform/chrome: cros_ec_sysfs: Expose PD mux status X-Git-Tag: v6.15-rc1~176^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e6a3215f78716d25ad60b002fd0585c04ffd5d01;p=thirdparty%2Flinux.git platform/chrome: cros_ec_sysfs: Expose PD mux status This adds sysfs attribute /sys/class/chromeos/cros_ec/usbpdmuxinfo to expose the PD mux status for each Type-C port. This allows user-space applications to easily determine the current mux state without using ioctls. Signed-off-by: Andrei Kuchynski Link: https://lore.kernel.org/r/20250203125947.2701106-2-akuchynski@chromium.org Signed-off-by: Tzung-Bi Shih --- diff --git a/Documentation/ABI/testing/sysfs-class-chromeos b/Documentation/ABI/testing/sysfs-class-chromeos index 74ece942722e7..e067dbdab170a 100644 --- a/Documentation/ABI/testing/sysfs-class-chromeos +++ b/Documentation/ABI/testing/sysfs-class-chromeos @@ -31,3 +31,16 @@ Date: August 2015 KernelVersion: 4.2 Description: Show the information about the EC software and hardware. + +What: /sys/class/chromeos/cros_ec/usbpdmuxinfo +Date: February 2025 +Description: + Show PD mux status for each typec port with following flags: + - "USB": USB connected + - "DP": DP connected + - "POLARITY": CC line Polarity inverted + - "HPD_IRQ": Hot Plug Detect interrupt is asserted + - "HPD_LVL": Hot Plug Detect level is asserted + - "SAFE": DP is in safe mode + - "TBT": TBT enabled + - "USB4": USB4 enabled diff --git a/drivers/platform/chrome/cros_ec_sysfs.c b/drivers/platform/chrome/cros_ec_sysfs.c index bc1a5ba095281..93e9ed87249cf 100644 --- a/drivers/platform/chrome/cros_ec_sysfs.c +++ b/drivers/platform/chrome/cros_ec_sysfs.c @@ -296,18 +296,69 @@ static ssize_t kb_wake_angle_store(struct device *dev, return count; } +static ssize_t usbpdmuxinfo_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct cros_ec_dev *ec = to_cros_ec_dev(dev); + ssize_t count = 0; + struct ec_response_usb_pd_ports resp_pd_ports; + int ret; + int i; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_PORTS, NULL, 0, + &resp_pd_ports, sizeof(resp_pd_ports)); + if (ret < 0) + return -EIO; + + for (i = 0; i < resp_pd_ports.num_ports; i++) { + struct ec_response_usb_pd_mux_info resp_mux; + struct ec_params_usb_pd_mux_info req = { + .port = i, + }; + + ret = cros_ec_cmd(ec->ec_dev, 0, EC_CMD_USB_PD_MUX_INFO, + &req, sizeof(req), &resp_mux, sizeof(resp_mux)); + + if (ret >= 0) { + count += sysfs_emit_at(buf, count, "Port %d:", i); + count += sysfs_emit_at(buf, count, " USB=%d", + !!(resp_mux.flags & USB_PD_MUX_USB_ENABLED)); + count += sysfs_emit_at(buf, count, " DP=%d", + !!(resp_mux.flags & USB_PD_MUX_DP_ENABLED)); + count += sysfs_emit_at(buf, count, " POLARITY=%s", + (resp_mux.flags & USB_PD_MUX_POLARITY_INVERTED) ? + "INVERTED" : "NORMAL"); + count += sysfs_emit_at(buf, count, " HPD_IRQ=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_IRQ)); + count += sysfs_emit_at(buf, count, " HPD_LVL=%d", + !!(resp_mux.flags & USB_PD_MUX_HPD_LVL)); + count += sysfs_emit_at(buf, count, " SAFE=%d", + !!(resp_mux.flags & USB_PD_MUX_SAFE_MODE)); + count += sysfs_emit_at(buf, count, " TBT=%d", + !!(resp_mux.flags & USB_PD_MUX_TBT_COMPAT_ENABLED)); + count += sysfs_emit_at(buf, count, " USB4=%d\n", + !!(resp_mux.flags & USB_PD_MUX_USB4_ENABLED)); + } + } + + return count ? : -EIO; +} + /* Module initialization */ static DEVICE_ATTR_RW(reboot); static DEVICE_ATTR_RO(version); static DEVICE_ATTR_RO(flashinfo); static DEVICE_ATTR_RW(kb_wake_angle); +static DEVICE_ATTR_RO(usbpdmuxinfo); static struct attribute *__ec_attrs[] = { &dev_attr_kb_wake_angle.attr, &dev_attr_reboot.attr, &dev_attr_version.attr, &dev_attr_flashinfo.attr, + &dev_attr_usbpdmuxinfo.attr, NULL, }; @@ -320,6 +371,13 @@ static umode_t cros_ec_ctrl_visible(struct kobject *kobj, if (a == &dev_attr_kb_wake_angle.attr && !ec->has_kb_wake_angle) return 0; + if (a == &dev_attr_usbpdmuxinfo.attr) { + struct cros_ec_platform *ec_platform = dev_get_platdata(ec->dev); + + if (strcmp(ec_platform->ec_name, CROS_EC_DEV_NAME)) + return 0; + } + return a->mode; }