@@ -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;
@@ -4,6 +4,7 @@
#define __DRIVER_USB_TYPEC_UCSI_H
#include <linux/bitops.h>
+#include <linux/completion.h>
#include <linux/device.h>
#include <linux/power_supply.h>
#include <linux/types.h>
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);