diff mbox series

[v4,3/5] usb: typec: ucsi: ccg: enable runtime pm support

Message ID 20190603170545.24004-4-ajayg@nvidia.com (mailing list archive)
State Superseded
Headers show
Series usb: typec: ucsi: ccg: add runtime pm support | expand

Commit Message

Ajay Gupta June 3, 2019, 5:05 p.m. UTC
From: Ajay Gupta <ajayg@nvidia.com>

The change enables runtime pm support to UCSI CCG driver.
Added ucsi_resume() function to enable notification after
system reusme. Exported both ucsi_resume() and ucsi_send_command()
symbols in ucsi.c for modular build.

Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
---
Changes from v3->v4 : None

 drivers/usb/typec/ucsi/ucsi.c     | 10 ++++++++
 drivers/usb/typec/ucsi/ucsi.h     |  1 +
 drivers/usb/typec/ucsi/ucsi_ccg.c | 38 +++++++++++++++++++++++++++++++
 3 files changed, 49 insertions(+)

Comments

Heikki Krogerus June 7, 2019, 8:25 a.m. UTC | #1
On Mon, Jun 03, 2019 at 10:05:43AM -0700, Ajay Gupta wrote:
> From: Ajay Gupta <ajayg@nvidia.com>
> 
> The change enables runtime pm support to UCSI CCG driver.
> Added ucsi_resume() function to enable notification after
> system reusme. Exported both ucsi_resume() and ucsi_send_command()
> symbols in ucsi.c for modular build.
> 
> Signed-off-by: Ajay Gupta <ajayg@nvidia.com>

Was the idea that Wolfram picks these? In that case:

Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
> Changes from v3->v4 : None
> 
>  drivers/usb/typec/ucsi/ucsi.c     | 10 ++++++++
>  drivers/usb/typec/ucsi/ucsi.h     |  1 +
>  drivers/usb/typec/ucsi/ucsi_ccg.c | 38 +++++++++++++++++++++++++++++++
>  3 files changed, 49 insertions(+)
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index 7850b851cecd..ba288b964dc8 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -206,7 +206,17 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
>  
>  	return ret;
>  }
> +EXPORT_SYMBOL_GPL(ucsi_send_command);
>  
> +int ucsi_resume(struct ucsi *ucsi)
> +{
> +	struct ucsi_control ctrl;
> +
> +	/* Restore UCSI notification enable mask after system resume */
> +	UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_ALL);
> +	return ucsi_send_command(ucsi, &ctrl, NULL, 0);
> +}
> +EXPORT_SYMBOL_GPL(ucsi_resume);
>  /* -------------------------------------------------------------------------- */
>  
>  void ucsi_altmode_update_active(struct ucsi_connector *con)
> diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
> index 1e2981aef629..de87d0b8319d 100644
> --- a/drivers/usb/typec/ucsi/ucsi.h
> +++ b/drivers/usb/typec/ucsi/ucsi.h
> @@ -430,6 +430,7 @@ int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
>  		      void *retval, size_t size);
>  
>  void ucsi_altmode_update_active(struct ucsi_connector *con);
> +int ucsi_resume(struct ucsi *ucsi);
>  
>  #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
>  struct typec_altmode *
> diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
> index 9d46aa9e4e35..b15bc6c29c46 100644
> --- a/drivers/usb/typec/ucsi/ucsi_ccg.c
> +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
> @@ -14,6 +14,8 @@
>  #include <linux/module.h>
>  #include <linux/pci.h>
>  #include <linux/platform_device.h>
> +#include <linux/pm.h>
> +#include <linux/pm_runtime.h>
>  
>  #include <asm/unaligned.h>
>  #include "ucsi.h"
> @@ -210,6 +212,7 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
>  	if (quirks && quirks->max_read_len)
>  		max_read_len = quirks->max_read_len;
>  
> +	pm_runtime_get_sync(uc->dev);
>  	while (rem_len > 0) {
>  		msgs[1].buf = &data[len - rem_len];
>  		rlen = min_t(u16, rem_len, max_read_len);
> @@ -218,12 +221,14 @@ static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
>  		status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
>  		if (status < 0) {
>  			dev_err(uc->dev, "i2c_transfer failed %d\n", status);
> +			pm_runtime_put_sync(uc->dev);
>  			return status;
>  		}
>  		rab += rlen;
>  		rem_len -= rlen;
>  	}
>  
> +	pm_runtime_put_sync(uc->dev);
>  	return 0;
>  }
>  
> @@ -249,13 +254,16 @@ static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
>  	msgs[0].len = len + sizeof(rab);
>  	msgs[0].buf = buf;
>  
> +	pm_runtime_get_sync(uc->dev);
>  	status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
>  	if (status < 0) {
>  		dev_err(uc->dev, "i2c_transfer failed %d\n", status);
> +		pm_runtime_put_sync(uc->dev);
>  		kfree(buf);
>  		return status;
>  	}
>  
> +	pm_runtime_put_sync(uc->dev);
>  	kfree(buf);
>  	return 0;
>  }
> @@ -1134,6 +1142,10 @@ static int ucsi_ccg_probe(struct i2c_client *client,
>  	if (status)
>  		dev_err(uc->dev, "cannot create sysfs group: %d\n", status);
>  
> +	pm_runtime_set_active(uc->dev);
> +	pm_runtime_enable(uc->dev);
> +	pm_runtime_idle(uc->dev);
> +
>  	return 0;
>  }
>  
> @@ -1143,6 +1155,7 @@ static int ucsi_ccg_remove(struct i2c_client *client)
>  
>  	cancel_work_sync(&uc->work);
>  	ucsi_unregister_ppm(uc->ucsi);
> +	pm_runtime_disable(uc->dev);
>  	free_irq(uc->irq, uc);
>  	sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group);
>  
> @@ -1155,9 +1168,34 @@ static const struct i2c_device_id ucsi_ccg_device_id[] = {
>  };
>  MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id);
>  
> +static int ucsi_ccg_resume(struct device *dev)
> +{
> +	struct i2c_client *client = to_i2c_client(dev);
> +	struct ucsi_ccg *uc = i2c_get_clientdata(client);
> +
> +	return ucsi_resume(uc->ucsi);
> +}
> +
> +static int ucsi_ccg_runtime_suspend(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static int ucsi_ccg_runtime_resume(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops ucsi_ccg_pm = {
> +	.resume = ucsi_ccg_resume,
> +	.runtime_suspend = ucsi_ccg_runtime_suspend,
> +	.runtime_resume = ucsi_ccg_runtime_resume,
> +};
> +
>  static struct i2c_driver ucsi_ccg_driver = {
>  	.driver = {
>  		.name = "ucsi_ccg",
> +		.pm = &ucsi_ccg_pm,
>  	},
>  	.probe = ucsi_ccg_probe,
>  	.remove = ucsi_ccg_remove,
> -- 
> 2.17.1

thanks,
Wolfram Sang June 7, 2019, 8:27 a.m. UTC | #2
On Fri, Jun 07, 2019 at 11:25:10AM +0300, Heikki Krogerus wrote:
> On Mon, Jun 03, 2019 at 10:05:43AM -0700, Ajay Gupta wrote:
> > From: Ajay Gupta <ajayg@nvidia.com>
> > 
> > The change enables runtime pm support to UCSI CCG driver.
> > Added ucsi_resume() function to enable notification after
> > system reusme. Exported both ucsi_resume() and ucsi_send_command()
> > symbols in ucsi.c for modular build.
> > 
> > Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
> 
> Was the idea that Wolfram picks these? In that case:

Cover letter says your tree, will check the i2c patches now.
Ajay Gupta June 7, 2019, 3:46 p.m. UTC | #3
Hi Heikki and Wolfram,

> -----Original Message-----
> From: linux-i2c-owner@vger.kernel.org <linux-i2c-owner@vger.kernel.org>
> On Behalf Of Wolfram Sang
> Sent: Friday, June 7, 2019 1:27 AM
> To: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Ajay Gupta <ajaykuee@gmail.com>; linux-usb@vger.kernel.org; linux-
> i2c@vger.kernel.org; Ajay Gupta <ajayg@nvidia.com>
> Subject: Re: [PATCH v4 3/5] usb: typec: ucsi: ccg: enable runtime pm support
> 
> On Fri, Jun 07, 2019 at 11:25:10AM +0300, Heikki Krogerus wrote:
> > On Mon, Jun 03, 2019 at 10:05:43AM -0700, Ajay Gupta wrote:
> > > From: Ajay Gupta <ajayg@nvidia.com>
> > >
> > > The change enables runtime pm support to UCSI CCG driver.
> > > Added ucsi_resume() function to enable notification after system
> > > reusme. Exported both ucsi_resume() and ucsi_send_command()
> symbols
> > > in ucsi.c for modular build.
> > >
> > > Signed-off-by: Ajay Gupta <ajayg@nvidia.com>
> >
> > Was the idea that Wolfram picks these? In that case:
> 
> Cover letter says your tree, will check the i2c patches now.
Either tree is fine with me. There are 3 (out of 5)  I2C related patches in the set so better
they go through I2C tree.

Thanks
Ajay
> nvpublic
diff mbox series

Patch

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 7850b851cecd..ba288b964dc8 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -206,7 +206,17 @@  int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
 
 	return ret;
 }
+EXPORT_SYMBOL_GPL(ucsi_send_command);
 
+int ucsi_resume(struct ucsi *ucsi)
+{
+	struct ucsi_control ctrl;
+
+	/* Restore UCSI notification enable mask after system resume */
+	UCSI_CMD_SET_NTFY_ENABLE(ctrl, UCSI_ENABLE_NTFY_ALL);
+	return ucsi_send_command(ucsi, &ctrl, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(ucsi_resume);
 /* -------------------------------------------------------------------------- */
 
 void ucsi_altmode_update_active(struct ucsi_connector *con)
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 1e2981aef629..de87d0b8319d 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -430,6 +430,7 @@  int ucsi_send_command(struct ucsi *ucsi, struct ucsi_control *ctrl,
 		      void *retval, size_t size);
 
 void ucsi_altmode_update_active(struct ucsi_connector *con);
+int ucsi_resume(struct ucsi *ucsi);
 
 #if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
 struct typec_altmode *
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index 9d46aa9e4e35..b15bc6c29c46 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -14,6 +14,8 @@ 
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/unaligned.h>
 #include "ucsi.h"
@@ -210,6 +212,7 @@  static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
 	if (quirks && quirks->max_read_len)
 		max_read_len = quirks->max_read_len;
 
+	pm_runtime_get_sync(uc->dev);
 	while (rem_len > 0) {
 		msgs[1].buf = &data[len - rem_len];
 		rlen = min_t(u16, rem_len, max_read_len);
@@ -218,12 +221,14 @@  static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
 		status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 		if (status < 0) {
 			dev_err(uc->dev, "i2c_transfer failed %d\n", status);
+			pm_runtime_put_sync(uc->dev);
 			return status;
 		}
 		rab += rlen;
 		rem_len -= rlen;
 	}
 
+	pm_runtime_put_sync(uc->dev);
 	return 0;
 }
 
@@ -249,13 +254,16 @@  static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len)
 	msgs[0].len = len + sizeof(rab);
 	msgs[0].buf = buf;
 
+	pm_runtime_get_sync(uc->dev);
 	status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
 	if (status < 0) {
 		dev_err(uc->dev, "i2c_transfer failed %d\n", status);
+		pm_runtime_put_sync(uc->dev);
 		kfree(buf);
 		return status;
 	}
 
+	pm_runtime_put_sync(uc->dev);
 	kfree(buf);
 	return 0;
 }
@@ -1134,6 +1142,10 @@  static int ucsi_ccg_probe(struct i2c_client *client,
 	if (status)
 		dev_err(uc->dev, "cannot create sysfs group: %d\n", status);
 
+	pm_runtime_set_active(uc->dev);
+	pm_runtime_enable(uc->dev);
+	pm_runtime_idle(uc->dev);
+
 	return 0;
 }
 
@@ -1143,6 +1155,7 @@  static int ucsi_ccg_remove(struct i2c_client *client)
 
 	cancel_work_sync(&uc->work);
 	ucsi_unregister_ppm(uc->ucsi);
+	pm_runtime_disable(uc->dev);
 	free_irq(uc->irq, uc);
 	sysfs_remove_group(&uc->dev->kobj, &ucsi_ccg_attr_group);
 
@@ -1155,9 +1168,34 @@  static const struct i2c_device_id ucsi_ccg_device_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id);
 
+static int ucsi_ccg_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ucsi_ccg *uc = i2c_get_clientdata(client);
+
+	return ucsi_resume(uc->ucsi);
+}
+
+static int ucsi_ccg_runtime_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int ucsi_ccg_runtime_resume(struct device *dev)
+{
+	return 0;
+}
+
+static const struct dev_pm_ops ucsi_ccg_pm = {
+	.resume = ucsi_ccg_resume,
+	.runtime_suspend = ucsi_ccg_runtime_suspend,
+	.runtime_resume = ucsi_ccg_runtime_resume,
+};
+
 static struct i2c_driver ucsi_ccg_driver = {
 	.driver = {
 		.name = "ucsi_ccg",
+		.pm = &ucsi_ccg_pm,
 	},
 	.probe = ucsi_ccg_probe,
 	.remove = ucsi_ccg_remove,