@@ -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);
}
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@linaro.org> --- drivers/usb/typec/ucsi/ucsi_glink.c | 90 +++++++++++++++++++++++++++++-------- 1 file changed, 71 insertions(+), 19 deletions(-)