diff mbox series

[v3,13/18] usb: typec: ucsi: ccg: Move to the new API

Message ID 20191025082324.75731-14-heikki.krogerus@linux.intel.com (mailing list archive)
State Superseded
Headers show
Series usb: typec: API improvements | expand

Commit Message

Heikki Krogerus Oct. 25, 2019, 8:23 a.m. UTC
Replacing the old "cmd" and "sync" callbacks with an
implementation of struct ucsi_operations. The interrupt
handler will from now on read the CCI (Command Status and
Connector Change Indication) register, and call
ucsi_connector_change() function and/or complete pending
command completions based on it.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Ajay Gupta <ajayg@nvidia.com>
---
 drivers/usb/typec/ucsi/ucsi_ccg.c | 170 +++++++++++++++---------------
 1 file changed, 85 insertions(+), 85 deletions(-)

Comments

Guenter Roeck Nov. 2, 2019, 4:34 p.m. UTC | #1
On 10/25/19 1:23 AM, Heikki Krogerus wrote:
> Replacing the old "cmd" and "sync" callbacks with an
> implementation of struct ucsi_operations. The interrupt
> handler will from now on read the CCI (Command Status and
> Connector Change Indication) register, and call
> ucsi_connector_change() function and/or complete pending
> command completions based on it.
> 
> Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Tested-by: Ajay Gupta <ajayg@nvidia.com>
> ---
>   drivers/usb/typec/ucsi/ucsi_ccg.c | 170 +++++++++++++++---------------
>   1 file changed, 85 insertions(+), 85 deletions(-)
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index d772fce51905..43442580a13c 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -176,8 +176,8 @@ struct ccg_resp {
>   struct ucsi_ccg {
>   	struct device *dev;
>   	struct ucsi *ucsi;
> -	struct ucsi_ppm ppm;
>   	struct i2c_client *client;
> +
>   	struct ccg_dev_info info;
>   	/* version info for boot, primary and secondary */
>   	struct version_info version[FW2 + 1];
> @@ -196,6 +196,8 @@ struct ucsi_ccg {
>   	/* fw build with vendor information */
>   	u16 fw_build;
>   	struct work_struct pm_work;
> +
> +	struct completion complete;
>   };
>   
>   static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> @@ -243,7 +245,7 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
>   	return 0;
>   }
>   
> -static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
> +static int ccg_write(struct ucsi_ccg *uc, u16 rab, const u8 *data, u32 len)
>   {
>   	struct i2c_client *client = uc->client;
>   	unsigned char *buf;
> @@ -317,88 +319,89 @@ static int ucsi_ccg_init(struct ucsi_ccg *uc)
>   	return -ETIMEDOUT;
>   }
>   
> -static int ucsi_ccg_send_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
> +			 void *val, size_t val_len)
>   {
> -	u8 *ppm = (u8 *)uc->ppm.data;
> -	int status;
> -	u16 rab;
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>   
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out));
> -	status = ccg_write(uc, rab, ppm +
> -			   offsetof(struct ucsi_data, message_out),
> -			   sizeof(uc->ppm.data->message_out));
> -	if (status < 0)
> -		return status;
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl));
> -	return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl),
> -			 sizeof(uc->ppm.data->ctrl));
> +	return ccg_read(ucsi_get_drvdata(ucsi), reg, val, val_len);
>   }
>   
> -static int ucsi_ccg_recv_data(struct ucsi_ccg *uc)
> +static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
> +				const void *val, size_t val_len)
>   {
> -	u8 *ppm = (u8 *)uc->ppm.data;
> -	int status;
> -	u16 rab;
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
>   
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci));
> -	status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci),
> -			  sizeof(uc->ppm.data->cci));
> -	if (status < 0)
> -		return status;
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in));
> -	return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in),
> -			sizeof(uc->ppm.data->message_in));
> +	return ccg_write(ucsi_get_drvdata(ucsi), reg, val, val_len);
>   }
>   
> -static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc)
> +static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
> +			       const void *val, size_t val_len)
>   {
> -	int status;
> -	unsigned char data;
> +	struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
> +	int ret;
>   
> -	status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> -	if (status < 0)
> -		return status;
> +	mutex_lock(&uc->lock);
> +	pm_runtime_get_sync(uc->dev);
> +	set_bit(DEV_CMD_PENDING, &uc->flags);
>   
> -	return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
> -}
> +	ret = ucsi_ccg_async_write(ucsi, offset, val, val_len);
> +	if (ret)
> +		goto err_clear_bit;
>   
> -static int ucsi_ccg_sync(struct ucsi_ppm *ppm)
> -{
> -	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> -	int status;
> +	if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000)))
> +		ret = -ETIMEDOUT;
>   
> -	status = ucsi_ccg_recv_data(uc);
> -	if (status < 0)
> -		return status;
> +err_clear_bit:
> +	clear_bit(DEV_CMD_PENDING, &uc->flags);
> +	pm_runtime_put_sync(uc->dev);
> +	mutex_unlock(&uc->lock);
>   
> -	/* ack interrupt to allow next command to run */
> -	return ucsi_ccg_ack_interrupt(uc);
> +	return ret;
>   }
>   
> -static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
> -{
> -	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
> -
> -	ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
> -	return ucsi_ccg_send_data(uc);
> -}
> +static const struct ucsi_operations ucsi_ccg_ops = {
> +	.read = ucsi_ccg_read,
> +	.sync_write = ucsi_ccg_sync_write,
> +	.async_write = ucsi_ccg_async_write
> +};
>   
>   static irqreturn_t ccg_irq_handler(int irq, void *data)
>   {
> +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CCI);
>   	struct ucsi_ccg *uc = data;
> +	u8 intr_reg;
> +	u32 cci;
> +	int ret;
> +
> +	ret = ccg_read(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> +	if (ret)
> +		return ret;
> +
> +	ret = ccg_read(uc, reg, (void *)&cci, sizeof(cci));
> +	if (ret) {
> +		dev_err(uc->dev, "failed to read CCI\n");

ccg_read() already logs an error message.

> +		goto err_clear_irq;
> +	}
> +
> +	if (UCSI_CCI_CONNECTOR(cci))
> +		ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci));
>   
> -	ucsi_notify(uc->ucsi);
> +	if (test_bit(DEV_CMD_PENDING, &uc->flags) &&
> +	    cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
> +		complete(&uc->complete);
> +
> +err_clear_irq:
> +	ret =  ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> +	if (ret)
> +		dev_err(uc->dev, "failed to clear interrupt\n");

ccg_write() already logs an error message.

>   
>   	return IRQ_HANDLED;
>   }
>   
>   static void ccg_pm_workaround_work(struct work_struct *pm_work)
>   {
> -	struct ucsi_ccg *uc = container_of(pm_work, struct ucsi_ccg, pm_work);
> -
> -	ucsi_notify(uc->ucsi);
> +	ccg_irq_handler(0, container_of(pm_work, struct ucsi_ccg, pm_work));
>   }
>   
>   static int get_fw_info(struct ucsi_ccg *uc)
> @@ -1027,10 +1030,10 @@ static int ccg_restart(struct ucsi_ccg *uc)
>   		return status;
>   	}
>   
> -	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> -	if (IS_ERR(uc->ucsi)) {
> -		dev_err(uc->dev, "ucsi_register_ppm failed\n");
> -		return PTR_ERR(uc->ucsi);
> +	status = ucsi_register(uc->ucsi);
> +	if (status) {
> +		dev_err(uc->dev, "failed to register the interface\n");
> +		return status;
>   	}
>   
>   	return 0;
> @@ -1047,7 +1050,7 @@ static void ccg_update_firmware(struct work_struct *work)
>   		return;
>   
>   	if (flash_mode != FLASH_NOT_NEEDED) {
> -		ucsi_unregister_ppm(uc->ucsi);
> +		ucsi_unregister(uc->ucsi);
>   		free_irq(uc->irq, uc);
>   
>   		ccg_fw_update(uc, flash_mode);
> @@ -1091,21 +1094,15 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	struct device *dev = &client->dev;
>   	struct ucsi_ccg *uc;
>   	int status;
> -	u16 rab;
>   
>   	uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
>   	if (!uc)
>   		return -ENOMEM;
>   
> -	uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL);
> -	if (!uc->ppm.data)
> -		return -ENOMEM;
> -
> -	uc->ppm.cmd = ucsi_ccg_cmd;
> -	uc->ppm.sync = ucsi_ccg_sync;
>   	uc->dev = dev;
>   	uc->client = client;
>   	mutex_init(&uc->lock);
> +	init_completion(&uc->complete);
>   	INIT_WORK(&uc->work, ccg_update_firmware);
>   	INIT_WORK(&uc->pm_work, ccg_pm_workaround_work);
>   
> @@ -1133,30 +1130,25 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	if (uc->info.mode & CCG_DEVINFO_PDPORTS_MASK)
>   		uc->port_num++;
>   
> +	uc->ucsi = ucsi_create(dev, &ucsi_ccg_ops);
> +	if (IS_ERR(uc->ucsi))
> +		return PTR_ERR(uc->ucsi);
> +
> +	ucsi_set_drvdata(uc->ucsi, uc);
> +
>   	status = request_threaded_irq(client->irq, NULL, ccg_irq_handler,
>   				      IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
>   				      dev_name(dev), uc);
>   	if (status < 0) {
>   		dev_err(uc->dev, "request_threaded_irq failed - %d\n", status);
> -		return status;
> +		goto out_ucsi_destroy;
>   	}
>   
>   	uc->irq = client->irq;
>   
> -	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
> -	if (IS_ERR(uc->ucsi)) {
> -		dev_err(uc->dev, "ucsi_register_ppm failed\n");
> -		return PTR_ERR(uc->ucsi);
> -	}
> -
> -	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version));
> -	status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) +
> -			  offsetof(struct ucsi_data, version),
> -			  sizeof(uc->ppm.data->version));
> -	if (status < 0) {
> -		ucsi_unregister_ppm(uc->ucsi);
> -		return status;
> -	}
> +	status = ucsi_register(uc->ucsi);
> +	if (status)
> +		goto out_free_irq;
>   
>   	i2c_set_clientdata(client, uc);
>   
> @@ -1167,6 +1159,13 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>   	pm_runtime_idle(uc->dev);
>   
>   	return 0;
> +
> +out_free_irq:
> +	free_irq(uc->irq, uc);
> +out_ucsi_destroy:
> +	ucsi_destroy(uc->ucsi);
> +
> +	return status;
>   }
>   
>   static int ucsi_ccg_remove(struct i2c_client *client)
> @@ -1175,8 +1174,9 @@ static int ucsi_ccg_remove(struct i2c_client *client)
>   
>   	cancel_work_sync(&uc->pm_work);
>   	cancel_work_sync(&uc->work);
> -	ucsi_unregister_ppm(uc->ucsi);
>   	pm_runtime_disable(uc->dev);
> +	ucsi_unregister(uc->ucsi);
> +	ucsi_destroy(uc->ucsi);
>   	free_irq(uc->irq, uc);
>   
>   	return 0;
>
Heikki Krogerus Nov. 4, 2019, 8:45 a.m. UTC | #2
On Sat, Nov 02, 2019 at 09:34:55AM -0700, Guenter Roeck wrote:
> >   static irqreturn_t ccg_irq_handler(int irq, void *data)
> >   {
> > +	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CCI);
> >   	struct ucsi_ccg *uc = data;
> > +	u8 intr_reg;
> > +	u32 cci;
> > +	int ret;
> > +
> > +	ret = ccg_read(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> > +	if (ret)
> > +		return ret;
> > +
> > +	ret = ccg_read(uc, reg, (void *)&cci, sizeof(cci));
> > +	if (ret) {
> > +		dev_err(uc->dev, "failed to read CCI\n");
> 
> ccg_read() already logs an error message.
> 
> > +		goto err_clear_irq;
> > +	}
> > +
> > +	if (UCSI_CCI_CONNECTOR(cci))
> > +		ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci));
> > -	ucsi_notify(uc->ucsi);
> > +	if (test_bit(DEV_CMD_PENDING, &uc->flags) &&
> > +	    cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
> > +		complete(&uc->complete);
> > +
> > +err_clear_irq:
> > +	ret =  ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
> > +	if (ret)
> > +		dev_err(uc->dev, "failed to clear interrupt\n");
> 
> ccg_write() already logs an error message.

OK. I'll drop both errors.

> >   	return IRQ_HANDLED;
> >   }

thanks,
diff mbox series

Patch

diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index d772fce51905..43442580a13c 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -176,8 +176,8 @@  struct ccg_resp {
 struct ucsi_ccg {
 	struct device *dev;
 	struct ucsi *ucsi;
-	struct ucsi_ppm ppm;
 	struct i2c_client *client;
+
 	struct ccg_dev_info info;
 	/* version info for boot, primary and secondary */
 	struct version_info version[FW2 + 1];
@@ -196,6 +196,8 @@  struct ucsi_ccg {
 	/* fw build with vendor information */
 	u16 fw_build;
 	struct work_struct pm_work;
+
+	struct completion complete;
 };
 
 static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
@@ -243,7 +245,7 @@  static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
 	return 0;
 }
 
-static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
+static int ccg_write(struct ucsi_ccg *uc, u16 rab, const u8 *data, u32 len)
 {
 	struct i2c_client *client = uc->client;
 	unsigned char *buf;
@@ -317,88 +319,89 @@  static int ucsi_ccg_init(struct ucsi_ccg *uc)
 	return -ETIMEDOUT;
 }
 
-static int ucsi_ccg_send_data(struct ucsi_ccg *uc)
+static int ucsi_ccg_read(struct ucsi *ucsi, unsigned int offset,
+			 void *val, size_t val_len)
 {
-	u8 *ppm = (u8 *)uc->ppm.data;
-	int status;
-	u16 rab;
+	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
 
-	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out));
-	status = ccg_write(uc, rab, ppm +
-			   offsetof(struct ucsi_data, message_out),
-			   sizeof(uc->ppm.data->message_out));
-	if (status < 0)
-		return status;
-
-	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl));
-	return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl),
-			 sizeof(uc->ppm.data->ctrl));
+	return ccg_read(ucsi_get_drvdata(ucsi), reg, val, val_len);
 }
 
-static int ucsi_ccg_recv_data(struct ucsi_ccg *uc)
+static int ucsi_ccg_async_write(struct ucsi *ucsi, unsigned int offset,
+				const void *val, size_t val_len)
 {
-	u8 *ppm = (u8 *)uc->ppm.data;
-	int status;
-	u16 rab;
+	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(offset);
 
-	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci));
-	status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci),
-			  sizeof(uc->ppm.data->cci));
-	if (status < 0)
-		return status;
-
-	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in));
-	return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in),
-			sizeof(uc->ppm.data->message_in));
+	return ccg_write(ucsi_get_drvdata(ucsi), reg, val, val_len);
 }
 
-static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc)
+static int ucsi_ccg_sync_write(struct ucsi *ucsi, unsigned int offset,
+			       const void *val, size_t val_len)
 {
-	int status;
-	unsigned char data;
+	struct ucsi_ccg *uc = ucsi_get_drvdata(ucsi);
+	int ret;
 
-	status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
-	if (status < 0)
-		return status;
+	mutex_lock(&uc->lock);
+	pm_runtime_get_sync(uc->dev);
+	set_bit(DEV_CMD_PENDING, &uc->flags);
 
-	return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data));
-}
+	ret = ucsi_ccg_async_write(ucsi, offset, val, val_len);
+	if (ret)
+		goto err_clear_bit;
 
-static int ucsi_ccg_sync(struct ucsi_ppm *ppm)
-{
-	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
-	int status;
+	if (!wait_for_completion_timeout(&uc->complete, msecs_to_jiffies(5000)))
+		ret = -ETIMEDOUT;
 
-	status = ucsi_ccg_recv_data(uc);
-	if (status < 0)
-		return status;
+err_clear_bit:
+	clear_bit(DEV_CMD_PENDING, &uc->flags);
+	pm_runtime_put_sync(uc->dev);
+	mutex_unlock(&uc->lock);
 
-	/* ack interrupt to allow next command to run */
-	return ucsi_ccg_ack_interrupt(uc);
+	return ret;
 }
 
-static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl)
-{
-	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm);
-
-	ppm->data->ctrl.raw_cmd = ctrl->raw_cmd;
-	return ucsi_ccg_send_data(uc);
-}
+static const struct ucsi_operations ucsi_ccg_ops = {
+	.read = ucsi_ccg_read,
+	.sync_write = ucsi_ccg_sync_write,
+	.async_write = ucsi_ccg_async_write
+};
 
 static irqreturn_t ccg_irq_handler(int irq, void *data)
 {
+	u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_CCI);
 	struct ucsi_ccg *uc = data;
+	u8 intr_reg;
+	u32 cci;
+	int ret;
+
+	ret = ccg_read(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
+	if (ret)
+		return ret;
+
+	ret = ccg_read(uc, reg, (void *)&cci, sizeof(cci));
+	if (ret) {
+		dev_err(uc->dev, "failed to read CCI\n");
+		goto err_clear_irq;
+	}
+
+	if (UCSI_CCI_CONNECTOR(cci))
+		ucsi_connector_change(uc->ucsi, UCSI_CCI_CONNECTOR(cci));
 
-	ucsi_notify(uc->ucsi);
+	if (test_bit(DEV_CMD_PENDING, &uc->flags) &&
+	    cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE))
+		complete(&uc->complete);
+
+err_clear_irq:
+	ret =  ccg_write(uc, CCGX_RAB_INTR_REG, &intr_reg, sizeof(intr_reg));
+	if (ret)
+		dev_err(uc->dev, "failed to clear interrupt\n");
 
 	return IRQ_HANDLED;
 }
 
 static void ccg_pm_workaround_work(struct work_struct *pm_work)
 {
-	struct ucsi_ccg *uc = container_of(pm_work, struct ucsi_ccg, pm_work);
-
-	ucsi_notify(uc->ucsi);
+	ccg_irq_handler(0, container_of(pm_work, struct ucsi_ccg, pm_work));
 }
 
 static int get_fw_info(struct ucsi_ccg *uc)
@@ -1027,10 +1030,10 @@  static int ccg_restart(struct ucsi_ccg *uc)
 		return status;
 	}
 
-	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
-	if (IS_ERR(uc->ucsi)) {
-		dev_err(uc->dev, "ucsi_register_ppm failed\n");
-		return PTR_ERR(uc->ucsi);
+	status = ucsi_register(uc->ucsi);
+	if (status) {
+		dev_err(uc->dev, "failed to register the interface\n");
+		return status;
 	}
 
 	return 0;
@@ -1047,7 +1050,7 @@  static void ccg_update_firmware(struct work_struct *work)
 		return;
 
 	if (flash_mode != FLASH_NOT_NEEDED) {
-		ucsi_unregister_ppm(uc->ucsi);
+		ucsi_unregister(uc->ucsi);
 		free_irq(uc->irq, uc);
 
 		ccg_fw_update(uc, flash_mode);
@@ -1091,21 +1094,15 @@  static int ucsi_ccg_probe(struct i2c_client *client,
 	struct device *dev = &client->dev;
 	struct ucsi_ccg *uc;
 	int status;
-	u16 rab;
 
 	uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL);
 	if (!uc)
 		return -ENOMEM;
 
-	uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL);
-	if (!uc->ppm.data)
-		return -ENOMEM;
-
-	uc->ppm.cmd = ucsi_ccg_cmd;
-	uc->ppm.sync = ucsi_ccg_sync;
 	uc->dev = dev;
 	uc->client = client;
 	mutex_init(&uc->lock);
+	init_completion(&uc->complete);
 	INIT_WORK(&uc->work, ccg_update_firmware);
 	INIT_WORK(&uc->pm_work, ccg_pm_workaround_work);
 
@@ -1133,30 +1130,25 @@  static int ucsi_ccg_probe(struct i2c_client *client,
 	if (uc->info.mode & CCG_DEVINFO_PDPORTS_MASK)
 		uc->port_num++;
 
+	uc->ucsi = ucsi_create(dev, &ucsi_ccg_ops);
+	if (IS_ERR(uc->ucsi))
+		return PTR_ERR(uc->ucsi);
+
+	ucsi_set_drvdata(uc->ucsi, uc);
+
 	status = request_threaded_irq(client->irq, NULL, ccg_irq_handler,
 				      IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
 				      dev_name(dev), uc);
 	if (status < 0) {
 		dev_err(uc->dev, "request_threaded_irq failed - %d\n", status);
-		return status;
+		goto out_ucsi_destroy;
 	}
 
 	uc->irq = client->irq;
 
-	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm);
-	if (IS_ERR(uc->ucsi)) {
-		dev_err(uc->dev, "ucsi_register_ppm failed\n");
-		return PTR_ERR(uc->ucsi);
-	}
-
-	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version));
-	status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) +
-			  offsetof(struct ucsi_data, version),
-			  sizeof(uc->ppm.data->version));
-	if (status < 0) {
-		ucsi_unregister_ppm(uc->ucsi);
-		return status;
-	}
+	status = ucsi_register(uc->ucsi);
+	if (status)
+		goto out_free_irq;
 
 	i2c_set_clientdata(client, uc);
 
@@ -1167,6 +1159,13 @@  static int ucsi_ccg_probe(struct i2c_client *client,
 	pm_runtime_idle(uc->dev);
 
 	return 0;
+
+out_free_irq:
+	free_irq(uc->irq, uc);
+out_ucsi_destroy:
+	ucsi_destroy(uc->ucsi);
+
+	return status;
 }
 
 static int ucsi_ccg_remove(struct i2c_client *client)
@@ -1175,8 +1174,9 @@  static int ucsi_ccg_remove(struct i2c_client *client)
 
 	cancel_work_sync(&uc->pm_work);
 	cancel_work_sync(&uc->work);
-	ucsi_unregister_ppm(uc->ucsi);
 	pm_runtime_disable(uc->dev);
+	ucsi_unregister(uc->ucsi);
+	ucsi_destroy(uc->ucsi);
 	free_irq(uc->irq, uc);
 
 	return 0;