All platforms except Qualcomm SC8180X pass CCI in the notification message. Use it instead of going back and forth over RPMSG interface to read CCI. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@xxxxxxxxxx> --- drivers/usb/typec/ucsi/ucsi_glink.c | 90 +++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 19 deletions(-) diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c index d029cc9d82e3..40fcda055b05 100644 --- a/drivers/usb/typec/ucsi/ucsi_glink.c +++ b/drivers/usb/typec/ucsi/ucsi_glink.c @@ -6,6 +6,7 @@ #include <linux/auxiliary_bus.h> #include <linux/module.h> #include <linux/mutex.h> +#include <linux/of.h> #include <linux/of_device.h> #include <linux/property.h> #include <linux/soc/qcom/pdr.h> @@ -70,7 +71,7 @@ struct pmic_glink_ucsi { int sync_val; - struct work_struct notify_work; + struct work_struct notify_work_sc8180x; struct work_struct register_work; u8 read_buf[UCSI_BUF_SIZE]; @@ -223,6 +224,20 @@ static const struct ucsi_operations pmic_glink_ucsi_ops = { .connector_status = pmic_glink_ucsi_connector_status, }; +static void pmic_glink_ucsi_notify_handle(struct pmic_glink_ucsi *ucsi, u32 cci) +{ + unsigned int con_num; + + 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); + } +} + static void pmic_glink_ucsi_read_ack(struct pmic_glink_ucsi *ucsi, const void *data, size_t len) { const struct ucsi_read_buf_resp_msg *resp; @@ -259,10 +274,24 @@ static void pmic_glink_ucsi_write_ack(struct pmic_glink_ucsi *ucsi, const void * complete(&ucsi->write_ack); } -static void pmic_glink_ucsi_notify(struct work_struct *work) +/* used everywhere except sc8180x */ +static void pmic_glink_ucsi_notify_ind(struct pmic_glink_ucsi *ucsi, const void *data, size_t len) { - struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work); - unsigned int con_num; + const struct ucsi_notify_ind_msg *msg; + + if (len != sizeof (*msg)) { + dev_err_ratelimited(ucsi->dev, "Unexpected notification struct size %zd\n", len); + return; + } + + msg = data; + + pmic_glink_ucsi_notify_handle(ucsi, le32_to_cpu(msg->notification)); +} + +static void pmic_glink_ucsi_notify_work_sc8180x(struct work_struct *work) +{ + struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, notify_work_sc8180x); u32 cci; int ret; @@ -272,14 +301,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); - } + pmic_glink_ucsi_notify_handle(ucsi, cci); } static void pmic_glink_ucsi_register(struct work_struct *work) @@ -289,6 +311,24 @@ static void pmic_glink_ucsi_register(struct work_struct *work) ucsi_register(ucsi->ucsi); } +static void pmic_glink_ucsi_callback_sc8180x(const void *data, size_t len, void *priv) +{ + struct pmic_glink_ucsi *ucsi = priv; + const struct pmic_glink_hdr *hdr = data; + + switch (le32_to_cpu(hdr->opcode)) { + case UC_UCSI_READ_BUF_REQ: + pmic_glink_ucsi_read_ack(ucsi, data, len); + break; + case UC_UCSI_WRITE_BUF_REQ: + pmic_glink_ucsi_write_ack(ucsi, data, len); + break; + case UC_UCSI_USBC_NOTIFY_IND: + schedule_work(&ucsi->notify_work_sc8180x); + break; + }; +} + static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv) { struct pmic_glink_ucsi *ucsi = priv; @@ -302,7 +342,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: - schedule_work(&ucsi->notify_work); + pmic_glink_ucsi_notify_ind(ucsi, data, len); break; }; } @@ -348,6 +388,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, struct device *dev = &adev->dev; const struct of_device_id *match; struct fwnode_handle *fwnode; + bool sc8180x_glink; int ret; ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL); @@ -357,7 +398,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ucsi->dev = dev; dev_set_drvdata(dev, ucsi); - INIT_WORK(&ucsi->notify_work, pmic_glink_ucsi_notify); + INIT_WORK(&ucsi->notify_work_sc8180x, pmic_glink_ucsi_notify_work_sc8180x); INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register); init_completion(&ucsi->read_ack); init_completion(&ucsi->write_ack); @@ -406,11 +447,22 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev, ucsi->port_orientation[port] = desc; } - ucsi->client = devm_pmic_glink_register_client(dev, - PMIC_GLINK_OWNER_USBC, - pmic_glink_ucsi_callback, - pmic_glink_ucsi_pdr_notify, - ucsi); + sc8180x_glink = of_device_is_compatible(dev->parent->of_node, + "qcom,sc8180x-pmic-glink"); + + if (sc8180x_glink) { + ucsi->client = devm_pmic_glink_register_client(dev, + PMIC_GLINK_OWNER_USBC, + pmic_glink_ucsi_callback_sc8180x, + pmic_glink_ucsi_pdr_notify, + ucsi); + } else { + ucsi->client = devm_pmic_glink_register_client(dev, + PMIC_GLINK_OWNER_USBC, + pmic_glink_ucsi_callback, + pmic_glink_ucsi_pdr_notify, + ucsi); + } return PTR_ERR_OR_ZERO(ucsi->client); } -- 2.39.2