From d9a47eb66a8e628aed8e4e7b7e74485693a1e064 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Mon, 25 May 2026 14:32:02 +0530 Subject: [PATCH 1/2] ucsi wakelock Signed-off-by: Jishnu Prakash --- drivers/usb/typec/ucsi/ucsi_glink.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 12e07b9fe6228..7f379e86b6922 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,6 +15,15 @@ #include #include "ucsi.h" +/* + * Wakeup timeout covering two async hops: + * 1. pmic_glink_ucsi_notify() work runs ucsi_notify_common() + * 2. ucsi_handle_connector_change() work runs and notifies USB + * ucsi_handle_connector_change() involves GLINK round-trips with up to 5s + * timeouts, so 10s gives sufficient margin for the full chain to complete. + */ +#define UCSI_GLINK_WAKEUP_TIMEOUT_MS 200 + #define PMIC_GLINK_MAX_PORTS 3 #define UCSI_BUF_V1_SIZE (UCSI_MESSAGE_OUT + (UCSI_MESSAGE_OUT - UCSI_MESSAGE_IN)) @@ -342,6 +352,7 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) pmic_glink_ucsi_write_ack(ucsi, data, len); break; case UC_UCSI_USBC_NOTIFY_IND: + pm_wakeup_event(ucsi->dev, UCSI_GLINK_WAKEUP_TIMEOUT_MS); schedule_work(&ucsi->notify_work); break; } @@ -401,6 +412,8 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ucsi->dev = dev; dev_set_drvdata(dev, ucsi); + device_init_wakeup(dev, true); + INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify); INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register); init_completion(&ucsi->read_ack); From e392cf124d4bfe60775b0e3a54c0c20030a8dc12 Mon Sep 17 00:00:00 2001 From: Jishnu Prakash Date: Mon, 25 May 2026 14:40:08 +0530 Subject: [PATCH 2/2] sysfs control Signed-off-by: Jishnu Prakash --- drivers/usb/typec/ucsi/ucsi_glink.c | 45 ++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 7f379e86b6922..2c86ce8845294 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -89,6 +89,9 @@ struct pmic_glink_ucsi { bool pd_running; u8 read_buf[UCSI_BUF_V2_SIZE]; + + /* Wakeup timeout in ms; configurable via sysfs wakeup_timeout_ms */ + unsigned int wakeup_timeout_ms; }; static int pmic_glink_ucsi_read(struct ucsi *__ucsi, unsigned int offset, @@ -339,6 +342,41 @@ static void pmic_glink_ucsi_register(struct work_struct *work) } } +static ssize_t wakeup_timeout_ms_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pmic_glink_ucsi *ucsi = dev_get_drvdata(dev); + + return sysfs_emit(buf, "%u\n", READ_ONCE(ucsi->wakeup_timeout_ms)); +} + +static ssize_t wakeup_timeout_ms_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pmic_glink_ucsi *ucsi = dev_get_drvdata(dev); + unsigned int val; + int ret; + + ret = kstrtouint(buf, 10, &val); + if (ret) + return ret; + + WRITE_ONCE(ucsi->wakeup_timeout_ms, val); + return count; +} + +static DEVICE_ATTR_RW(wakeup_timeout_ms); + +static struct attribute *pmic_glink_ucsi_attrs[] = { + &dev_attr_wakeup_timeout_ms.attr, + NULL, +}; + +static const struct attribute_group pmic_glink_ucsi_attr_group = { + .attrs = pmic_glink_ucsi_attrs, +}; + static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) { struct pmic_glink_ucsi *ucsi = priv; @@ -352,7 +390,7 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) pmic_glink_ucsi_write_ack(ucsi, data, len); break; case UC_UCSI_USBC_NOTIFY_IND: - pm_wakeup_event(ucsi->dev, UCSI_GLINK_WAKEUP_TIMEOUT_MS); + pm_wakeup_event(ucsi->dev, READ_ONCE(ucsi->wakeup_timeout_ms)); schedule_work(&ucsi->notify_work); break; } @@ -413,6 +451,11 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, dev_set_drvdata(dev, ucsi); device_init_wakeup(dev, true); + ucsi->wakeup_timeout_ms = UCSI_GLINK_WAKEUP_TIMEOUT_MS; + + ret = devm_device_add_group(dev, &pmic_glink_ucsi_attr_group); + if (ret) + return ret; INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify); INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register);