diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c index 2d87fe277c627..25d2ee5ee8bb0 100644 --- a/drivers/usb/typec/ucsi/ucsi.c +++ b/drivers/usb/typec/ucsi/ucsi.c @@ -36,6 +36,48 @@ */ #define UCSI_SWAP_TIMEOUT_MS 5000 +void ucsi_notify_common(struct ucsi *ucsi, u32 cci) +{ + if (UCSI_CCI_CONNECTOR(cci)) + ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci)); + + if (cci & UCSI_CCI_ACK_COMPLETE && + test_bit(ACK_PENDING, &ucsi->flags)) + complete(&ucsi->complete); + + if (cci & UCSI_CCI_COMMAND_COMPLETE && + test_bit(COMMAND_PENDING, &ucsi->flags)) + complete(&ucsi->complete); +} +EXPORT_SYMBOL_GPL(ucsi_notify_common); + +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command) +{ + bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; + int ret; + + if (ack) + set_bit(ACK_PENDING, &ucsi->flags); + else + set_bit(COMMAND_PENDING, &ucsi->flags); + + ret = ucsi->ops->async_control(ucsi, command); + if (ret) + goto out_clear_bit; + + if (!wait_for_completion_timeout(&ucsi->complete, 5 * HZ)) + ret = -ETIMEDOUT; + +out_clear_bit: + if (ack) + clear_bit(ACK_PENDING, &ucsi->flags); + else + clear_bit(COMMAND_PENDING, &ucsi->flags); + + return ret; +} +EXPORT_SYMBOL_GPL(ucsi_sync_control_common); + static int ucsi_acknowledge(struct ucsi *ucsi, bool conn_ack) { u64 ctrl; @@ -1919,6 +1961,7 @@ struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops) INIT_WORK(&ucsi->resume_work, ucsi_resume_work); INIT_DELAYED_WORK(&ucsi->work, ucsi_init_work); mutex_init(&ucsi->ppm_lock); + init_completion(&ucsi->complete); ucsi->dev = dev; ucsi->ops = ops; diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h index 2560e144e158a..57129f3c08142 100644 --- a/drivers/usb/typec/ucsi/ucsi.h +++ b/drivers/usb/typec/ucsi/ucsi.h @@ -4,6 +4,7 @@ #define __DRIVER_USB_TYPEC_UCSI_H #include +#include #include #include #include @@ -425,6 +426,9 @@ struct ucsi { /* PPM communication flags */ unsigned long flags; #define EVENT_PENDING 0 +#define COMMAND_PENDING 1 +#define ACK_PENDING 2 + struct completion complete; unsigned long quirks; #define UCSI_NO_PARTNER_PDOS BIT(0) /* Don't read partner's PDOs */ @@ -489,6 +493,9 @@ int ucsi_send_command(struct ucsi *ucsi, u64 command, void ucsi_altmode_update_active(struct ucsi_connector *con); int ucsi_resume(struct ucsi *ucsi); +void ucsi_notify_common(struct ucsi *ucsi, u32 cci); +int ucsi_sync_control_common(struct ucsi *ucsi, u64 command); + #if IS_ENABLED(CONFIG_POWER_SUPPLY) int ucsi_register_port_psy(struct ucsi_connector *con); void ucsi_unregister_port_psy(struct ucsi_connector *con); diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c index 3660dc3e6d32b..7a5dff8d9cc6c 100644 --- a/drivers/usb/typec/ucsi/ucsi_acpi.c +++ b/drivers/usb/typec/ucsi/ucsi_acpi.c @@ -21,11 +21,7 @@ struct ucsi_acpi { struct device *dev; struct ucsi *ucsi; void *base; - struct completion complete; - unsigned long flags; -#define UCSI_ACPI_COMMAND_PENDING 1 -#define UCSI_ACPI_ACK_PENDING 2 -#define UCSI_ACPI_CHECK_BOGUS_EVENT 3 + bool check_bogus_event; guid_t guid; u64 cmd; }; @@ -98,38 +94,11 @@ static int ucsi_acpi_async_control(struct ucsi *ucsi, u64 command) return ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_WRITE); } -static int ucsi_acpi_sync_control(struct ucsi *ucsi, u64 command) -{ - struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); - bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; - int ret; - - if (ack) - set_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); - else - set_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); - - ret = ucsi_acpi_async_control(ucsi, command); - if (ret) - goto out_clear_bit; - - if (!wait_for_completion_timeout(&ua->complete, 5 * HZ)) - ret = -ETIMEDOUT; - -out_clear_bit: - if (ack) - clear_bit(UCSI_ACPI_ACK_PENDING, &ua->flags); - else - clear_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags); - - return ret; -} - static const struct ucsi_operations ucsi_acpi_ops = { .read_version = ucsi_acpi_read_version, .read_cci = ucsi_acpi_read_cci, .read_message_in = ucsi_acpi_read_message_in, - .sync_control = ucsi_acpi_sync_control, + .sync_control = ucsi_sync_control_common, .async_control = ucsi_acpi_async_control }; @@ -165,7 +134,7 @@ static const struct ucsi_operations ucsi_zenbook_ops = { .read_version = ucsi_acpi_read_version, .read_cci = ucsi_zenbook_read_cci, .read_message_in = ucsi_zenbook_read_message_in, - .sync_control = ucsi_acpi_sync_control, + .sync_control = ucsi_sync_control_common, .async_control = ucsi_acpi_async_control }; @@ -182,14 +151,14 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le return ret; if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS && - test_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags)) { + ua->check_bogus_event) { status = (struct ucsi_connector_status *)val; /* Clear the bogus change */ if (status->change == bogus_change) status->change = 0; - clear_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags); + ua->check_bogus_event = false; } return ret; @@ -200,14 +169,14 @@ static int ucsi_gram_sync_control(struct ucsi *ucsi, u64 command) struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); int ret; - ret = ucsi_acpi_sync_control(ucsi, command); + ret = ucsi_sync_control_common(ucsi, command); if (ret < 0) return ret; if (UCSI_COMMAND(ua->cmd) == UCSI_GET_PDOS && ua->cmd & UCSI_GET_PDOS_PARTNER_PDO(1) && ua->cmd & UCSI_GET_PDOS_SRC_PDOS) - set_bit(UCSI_ACPI_CHECK_BOGUS_EVENT, &ua->flags); + ua->check_bogus_event = true; return ret; } @@ -249,15 +218,7 @@ static void ucsi_acpi_notify(acpi_handle handle, u32 event, void *data) if (ret) return; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); - - if (cci & UCSI_CCI_ACK_COMPLETE && - test_bit(UCSI_ACPI_ACK_PENDING, &ua->flags)) - complete(&ua->complete); - if (cci & UCSI_CCI_COMMAND_COMPLETE && - test_bit(UCSI_ACPI_COMMAND_PENDING, &ua->flags)) - complete(&ua->complete); + ucsi_notify_common(ua->ucsi, cci); } static int ucsi_acpi_probe(struct platform_device *pdev) @@ -291,7 +252,6 @@ static int ucsi_acpi_probe(struct platform_device *pdev) if (ret) return ret; - init_completion(&ua->complete); ua->dev = &pdev->dev; id = dmi_first_match(ucsi_acpi_quirks); diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c index 6ccc394f268ed..ba4db2310a050 100644 --- a/drivers/usb/typec/ucsi/ucsi_ccg.c +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -222,8 +222,6 @@ struct ucsi_ccg { u16 fw_build; struct work_struct pm_work; - struct completion complete; - u64 last_cmd_sent; bool has_multiple_dp; struct ucsi_ccg_altmode orig[UCSI_MAX_ALTMODES]; @@ -637,7 +635,6 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) mutex_lock(&uc->lock); pm_runtime_get_sync(uc->dev); - set_bit(DEV_CMD_PENDING, &uc->flags); uc->last_cmd_sent = command; @@ -649,15 +646,8 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command) ucsi_ccg_update_set_new_cam_cmd(uc, con, &command); } - ret = ucsi_ccg_async_control(ucsi, command); - if (ret) - goto err_clear_bit; - - if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000))) - ret = -ETIMEDOUT; + ret = ucsi_sync_control_common(ucsi, command); -err_clear_bit: - clear_bit(DEV_CMD_PENDING, &uc->flags); pm_runtime_put_sync(uc->dev); mutex_unlock(&uc->lock); @@ -694,9 +684,6 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) if (ret) goto err_clear_irq; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci)); - /* * As per CCGx UCSI interface guide, copy CCI and MESSAGE_IN * to the OpRegion before clear the UCSI interrupt @@ -708,9 +695,8 @@ static irqreturn_t ccg_irq_handler(int irq, void *data) err_clear_irq: ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg)); - if (!ret && test_bit(DEV_CMD_PENDING, &uc->flags) && - cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) - complete(&uc->complete); + if (!ret) + ucsi_notify_common(uc->ucsi, cci); return IRQ_HANDLED; } @@ -1429,7 +1415,6 @@ static int ucsi_ccg_probe(struct i2c_client *client) uc->client = client; uc->irq = client->irq; mutex_init(&uc->lock); - init_completion(&uc->complete); INIT_WORK(&uc->work, ccg_update_firmware); INIT_WORK(&uc->pm_work, ccg_pm_workaround_work); diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index 56bad054e78fc..16c328497e0b8 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -64,12 +64,8 @@ struct pmic_glink_ucsi { struct ucsi *ucsi; struct completion read_ack; struct completion write_ack; - struct completion sync_ack; - bool sync_pending; struct mutex lock; /* protects concurrent access to PMIC Glink interface */ - int sync_val; - struct work_struct notify_work; struct work_struct register_work; @@ -170,35 +166,6 @@ static int pmic_glink_ucsi_async_control(struct ucsi *__ucsi, u64 command) return ret; } -static int pmic_glink_ucsi_sync_control(struct ucsi *__ucsi, u64 command) -{ - struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(__ucsi); - unsigned long left; - int ret; - - /* TOFIX: Downstream forces recipient to CON when UCSI_GET_ALTERNATE_MODES command */ - - mutex_lock(&ucsi->lock); - ucsi->sync_val = 0; - reinit_completion(&ucsi->sync_ack); - ucsi->sync_pending = true; - ret = pmic_glink_ucsi_locked_write(ucsi, UCSI_CONTROL, &command, sizeof(command)); - mutex_unlock(&ucsi->lock); - - left = wait_for_completion_timeout(&ucsi->sync_ack, 5 * HZ); - if (!left) { - dev_err(ucsi->dev, "timeout waiting for UCSI sync write response\n"); - /* return 0 here and let core UCSI code handle the CCI_BUSY */ - ret = 0; - } else if (ucsi->sync_val) { - dev_err(ucsi->dev, "sync write returned: %d\n", ucsi->sync_val); - } - - ucsi->sync_pending = false; - - return ret; -} - static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con) { struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi); @@ -232,7 +199,7 @@ static const struct ucsi_operations pmic_glink_ucsi_ops = { .read_version = pmic_glink_ucsi_read_version, .read_cci = pmic_glink_ucsi_read_cci, .read_message_in = pmic_glink_ucsi_read_message_in, - .sync_control = pmic_glink_ucsi_sync_control, + .sync_control = ucsi_sync_control_common, .async_control = pmic_glink_ucsi_async_control, .update_connector = pmic_glink_ucsi_update_connector, .connector_status = pmic_glink_ucsi_connector_status, @@ -256,14 +223,12 @@ static void pmic_glink_ucsi_write_ack(struct pmic_glink_ucsi *ucsi, const void * if (resp->ret_code) return; - ucsi->sync_val = resp->ret_code; complete(&ucsi->write_ack); } static void pmic_glink_ucsi_notify(struct work_struct *work) { struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work); - unsigned int con_num; u32 cci; int ret; @@ -273,14 +238,7 @@ static void pmic_glink_ucsi_notify(struct work_struct *work) return; } - con_num = UCSI_CCI_CONNECTOR(cci); - if (con_num) - ucsi_connector_change(ucsi->ucsi, con_num); - - if (ucsi->sync_pending && - (cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))) { - complete(&ucsi->sync_ack); - } + ucsi_notify_common(ucsi->ucsi, cci); } static void pmic_glink_ucsi_register(struct work_struct *work) @@ -362,7 +320,6 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register); init_completion(&ucsi->read_ack); init_completion(&ucsi->write_ack); - init_completion(&ucsi->sync_ack); mutex_init(&ucsi->lock); ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops); diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c index 14737ca3724c4..d948c3f579e18 100644 --- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c +++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c @@ -61,11 +61,7 @@ struct ucsi_stm32g0 { struct i2c_client *i2c_bl; bool in_bootloader; u8 bl_version; - struct completion complete; struct device *dev; - unsigned long flags; -#define COMMAND_PENDING 1 -#define ACK_PENDING 2 const char *fw_name; struct ucsi *ucsi; bool suspended; @@ -407,35 +403,6 @@ static int ucsi_stm32g0_async_control(struct ucsi *ucsi, u64 command) return 0; } -static int ucsi_stm32g0_sync_control(struct ucsi *ucsi, u64 command) -{ - struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi); - bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; - int ret; - - if (ack) - set_bit(ACK_PENDING, &g0->flags); - else - set_bit(COMMAND_PENDING, &g0->flags); - - ret = ucsi_stm32g0_async_control(ucsi, command); - if (ret) - goto out_clear_bit; - - if (!wait_for_completion_timeout(&g0->complete, msecs_to_jiffies(5000))) - ret = -ETIMEDOUT; - else - return 0; - -out_clear_bit: - if (ack) - clear_bit(ACK_PENDING, &g0->flags); - else - clear_bit(COMMAND_PENDING, &g0->flags); - - return ret; -} - static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) { struct ucsi_stm32g0 *g0 = data; @@ -449,13 +416,7 @@ static irqreturn_t ucsi_stm32g0_irq_handler(int irq, void *data) if (ret) return IRQ_NONE; - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(g0->ucsi, UCSI_CCI_CONNECTOR(cci)); - - if (cci & UCSI_CCI_ACK_COMPLETE && test_and_clear_bit(ACK_PENDING, &g0->flags)) - complete(&g0->complete); - if (cci & UCSI_CCI_COMMAND_COMPLETE && test_and_clear_bit(COMMAND_PENDING, &g0->flags)) - complete(&g0->complete); + ucsi_notify_common(g0->ucsi, cci); return IRQ_HANDLED; } @@ -464,7 +425,7 @@ static const struct ucsi_operations ucsi_stm32g0_ops = { .read_version = ucsi_stm32g0_read_version, .read_cci = ucsi_stm32g0_read_cci, .read_message_in = ucsi_stm32g0_read_message_in, - .sync_control = ucsi_stm32g0_sync_control, + .sync_control = ucsi_sync_control_common, .async_control = ucsi_stm32g0_async_control, }; @@ -665,7 +626,6 @@ static int ucsi_stm32g0_probe(struct i2c_client *client) g0->dev = dev; g0->client = client; - init_completion(&g0->complete); i2c_set_clientdata(client, g0); g0->ucsi = ucsi_create(dev, &ucsi_stm32g0_ops); diff --git a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c index 95a333ad54966..f3a5e24ea84d5 100644 --- a/drivers/usb/typec/ucsi/ucsi_yoga_c630.c +++ b/drivers/usb/typec/ucsi/ucsi_yoga_c630.c @@ -20,10 +20,6 @@ struct yoga_c630_ucsi { struct yoga_c630_ec *ec; struct ucsi *ucsi; struct notifier_block nb; - struct completion complete; - unsigned long flags; -#define UCSI_C630_COMMAND_PENDING 0 -#define UCSI_C630_ACK_PENDING 1 u16 version; }; @@ -75,57 +71,14 @@ static int yoga_c630_ucsi_async_control(struct ucsi *ucsi, u64 command) return yoga_c630_ec_ucsi_write(uec->ec, (u8*)&command); } -static int yoga_c630_ucsi_sync_control(struct ucsi *ucsi, u64 command) -{ - struct yoga_c630_ucsi *uec = ucsi_get_drvdata(ucsi); - bool ack = UCSI_COMMAND(command) == UCSI_ACK_CC_CI; - int ret; - - if (ack) - set_bit(UCSI_C630_ACK_PENDING, &uec->flags); - else - set_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); - - reinit_completion(&uec->complete); - - ret = yoga_c630_ucsi_async_control(ucsi, command); - if (ret) - goto out_clear_bit; - - if (!wait_for_completion_timeout(&uec->complete, 5 * HZ)) - ret = -ETIMEDOUT; - -out_clear_bit: - if (ack) - clear_bit(UCSI_C630_ACK_PENDING, &uec->flags); - else - clear_bit(UCSI_C630_COMMAND_PENDING, &uec->flags); - - return ret; -} - const struct ucsi_operations yoga_c630_ucsi_ops = { .read_version = yoga_c630_ucsi_read_version, .read_cci = yoga_c630_ucsi_read_cci, .read_message_in = yoga_c630_ucsi_read_message_in, - .sync_control = yoga_c630_ucsi_sync_control, + .sync_control = ucsi_sync_control_common, .async_control = yoga_c630_ucsi_async_control, }; -static void yoga_c630_ucsi_notify_ucsi(struct yoga_c630_ucsi *uec, u32 cci) -{ - if (UCSI_CCI_CONNECTOR(cci)) - ucsi_connector_change(uec->ucsi, UCSI_CCI_CONNECTOR(cci)); - - if (cci & UCSI_CCI_ACK_COMPLETE && - test_bit(UCSI_C630_ACK_PENDING, &uec->flags)) - complete(&uec->complete); - - if (cci & UCSI_CCI_COMMAND_COMPLETE && - test_bit(UCSI_C630_COMMAND_PENDING, &uec->flags)) - complete(&uec->complete); -} - static int yoga_c630_ucsi_notify(struct notifier_block *nb, unsigned long action, void *data) { @@ -144,7 +97,7 @@ static int yoga_c630_ucsi_notify(struct notifier_block *nb, if (ret) return NOTIFY_DONE; - yoga_c630_ucsi_notify_ucsi(uec, cci); + ucsi_notify_common(uec->ucsi, cci); return NOTIFY_OK; @@ -165,7 +118,6 @@ static int yoga_c630_ucsi_probe(struct auxiliary_device *adev, return -ENOMEM; uec->ec = ec; - init_completion(&uec->complete); uec->nb.notifier_call = yoga_c630_ucsi_notify; uec->ucsi = ucsi_create(&adev->dev, &yoga_c630_ucsi_ops);