diff mbox series

[RFC,3/6] usb: typec: ucsi: Make Version a parameter to ucsi_register

Message ID 20240218222039.822040-4-lk@c--e.de
State New
Headers show
Series UCSI backend API refactoring | expand

Commit Message

Christian A. Ehrhardt Feb. 18, 2024, 10:20 p.m. UTC
Reading UCSI_VERSION is a special case as there is no
notification that syncs the data into host memory.

Read UCSI_VERSION only once during initialization and provide
it as a parameter to ucsi_register().

Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
---
 drivers/usb/typec/ucsi/ucsi.c         | 13 ++++---------
 drivers/usb/typec/ucsi/ucsi.h         |  2 +-
 drivers/usb/typec/ucsi/ucsi_acpi.c    |  8 +++++++-
 drivers/usb/typec/ucsi/ucsi_ccg.c     | 12 ++++++++++--
 drivers/usb/typec/ucsi/ucsi_glink.c   | 11 ++++++++++-
 drivers/usb/typec/ucsi/ucsi_stm32g0.c | 26 ++++++++++++++++++++++----
 6 files changed, 54 insertions(+), 18 deletions(-)
diff mbox series

Patch

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index ae105383e69e..eb630447ba80 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1581,18 +1581,13 @@  EXPORT_SYMBOL_GPL(ucsi_destroy);
 /**
  * ucsi_register - Register UCSI interface
  * @ucsi: UCSI instance
+ * @version: The revision of the UCSI spec
  */
-int ucsi_register(struct ucsi *ucsi)
+int ucsi_register(struct ucsi *ucsi, u16 version)
 {
-	int ret;
-
-	ret = ucsi->ops->read(ucsi, UCSI_VERSION, &ucsi->version,
-			      sizeof(ucsi->version));
-	if (ret)
-		return ret;
-
-	if (!ucsi->version)
+	if (!version)
 		return -ENODEV;
+	ucsi->version = version;
 
 	/*
 	 * Version format is JJ.M.N (JJ = Major version, M = Minor version,
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 7e35ffbe0a6f..100e16b49814 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -77,7 +77,7 @@  struct ucsi_operations {
 
 struct ucsi *ucsi_create(struct device *dev, const struct ucsi_operations *ops);
 void ucsi_destroy(struct ucsi *ucsi);
-int ucsi_register(struct ucsi *ucsi);
+int ucsi_register(struct ucsi *ucsi, u16 version);
 void ucsi_unregister(struct ucsi *ucsi);
 void *ucsi_get_drvdata(struct ucsi *ucsi);
 void ucsi_set_drvdata(struct ucsi *ucsi, void *data);
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 928eacbeb21a..710ddfc03ed0 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -226,6 +226,7 @@  static int ucsi_acpi_probe(struct platform_device *pdev)
 	const struct dmi_system_id *id;
 	struct ucsi_acpi *ua;
 	struct resource *res;
+	u16 version;
 	acpi_status status;
 	int ret;
 
@@ -272,7 +273,12 @@  static int ucsi_acpi_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	ret = ucsi_register(ua->ucsi);
+	ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
+	if (ret)
+		return ret;
+	version = le16_to_cpu(*(__le16 *)(ua->base + UCSI_VERSION));
+
+	ret = ucsi_register(ua->ucsi, version);
 	if (ret) {
 		acpi_remove_notify_handler(ACPI_HANDLE(&pdev->dev),
 					   ACPI_DEVICE_NOTIFY,
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index 709295948c65..d47f5e31c98a 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -1356,7 +1356,7 @@  static int ccg_restart(struct ucsi_ccg *uc)
 		return status;
 	}
 
-	status = ucsi_register(uc->ucsi);
+	status = ucsi_register(uc->ucsi, uc->ucsi->version);
 	if (status) {
 		dev_err(uc->dev, "failed to register the interface\n");
 		return status;
@@ -1422,6 +1422,7 @@  static int ucsi_ccg_probe(struct i2c_client *client)
 	struct ucsi_ccg *uc;
 	const char *fw_name;
 	int status;
+	__le16 version;
 
 	uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
 	if (!uc)
@@ -1477,7 +1478,14 @@  static int ucsi_ccg_probe(struct i2c_client *client)
 		goto out_ucsi_destroy;
 	}
 
-	status = ucsi_register(uc->ucsi);
+	status = ccg_read(uc, CCGX_RAB_UCSI_DATA_BLOCK(UCSI_VERSION),
+			  (u8 *)&version, sizeof(version));
+	if (status < 0) {
+		dev_err(uc->dev, "cannot read UCSI version - %d\n", status);
+		return status;
+	}
+
+	status = ucsi_register(uc->ucsi, le16_to_cpu(version));
 	if (status)
 		goto out_free_irq;
 
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index 0a0d08467c56..7a0b28536abd 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -255,8 +255,17 @@  static void pmic_glink_ucsi_notify(struct work_struct *work)
 static void pmic_glink_ucsi_register(struct work_struct *work)
 {
 	struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
+	__le16 version;
+	int ret;
+
+	ret = pmic_glink_ucsi_read(ucsi->ucsi, UCSI_VERSION, &version,
+				   sizeof(version));
+	if (ret < 0) {
+		dev_err(ucsi->dev, "cannot read version: %d\n", ret);
+		return;
+	}
 
-	ucsi_register(ucsi->ucsi);
+	ucsi_register(ucsi->ucsi, le16_to_cpu(version));
 }
 
 static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
diff --git a/drivers/usb/typec/ucsi/ucsi_stm32g0.c b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
index 93d7806681cf..112692c7a158 100644
--- a/drivers/usb/typec/ucsi/ucsi_stm32g0.c
+++ b/drivers/usb/typec/ucsi/ucsi_stm32g0.c
@@ -325,10 +325,10 @@  static int ucsi_stm32g0_fw_rcv(struct ucsi *ucsi, void *data, size_t len)
 	return ucsi_stm32g0_bl_rcv_woack(ucsi, data, len);
 }
 
-/* UCSI ops */
-static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val, size_t len)
+static int ucsi_stm32g0_read_from_hw(struct ucsi_stm32g0 *g0,
+				     unsigned int offset,
+				     void *val, size_t len)
 {
-	struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi);
 	struct i2c_client *client = g0->client;
 	u8 reg = offset;
 	struct i2c_msg msg[] = {
@@ -357,6 +357,15 @@  static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset, void *val,
 	return 0;
 }
 
+/* UCSI ops */
+static int ucsi_stm32g0_read(struct ucsi *ucsi, unsigned int offset,
+			     void *val, size_t len)
+{
+	struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi);
+
+	return ucsi_stm32g0_read_from_hw(g0, offset, val, len);
+}
+
 static int ucsi_stm32g0_async_write(struct ucsi *ucsi, unsigned int offset, const void *val,
 				    size_t len)
 {
@@ -445,6 +454,7 @@  static int ucsi_stm32g0_register(struct ucsi *ucsi)
 {
 	struct ucsi_stm32g0 *g0 = ucsi_get_drvdata(ucsi);
 	struct i2c_client *client = g0->client;
+	__le16 version;
 	int ret;
 
 	/* Request alert interrupt */
@@ -455,7 +465,15 @@  static int ucsi_stm32g0_register(struct ucsi *ucsi)
 		return ret;
 	}
 
-	ret = ucsi_register(ucsi);
+	ret = ucsi_stm32g0_read_from_hw(g0, UCSI_VERSION, &version,
+					sizeof(version));
+	if (ret) {
+		dev_err(g0->dev, "failed to read version number: %d\n", ret);
+		free_irq(client->irq, g0);
+		return ret;
+	}
+
+	ret = ucsi_register(ucsi, le16_to_cpu(version));
 	if (ret) {
 		dev_err_probe(g0->dev, ret, "ucsi_register failed\n");
 		free_irq(client->irq, g0);