linux-i2c.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] i2c: i801: Add runtime PM support
@ 2016-03-10 12:12 Jarkko Nikula
  2016-03-10 12:12 ` [PATCH 1/2] i2c: i801: Convert to struct dev_pm_ops for suspend/resume Jarkko Nikula
  2016-03-10 12:12 ` [PATCH 2/2] i2c: i801: Add runtime PM support with autosuspend Jarkko Nikula
  0 siblings, 2 replies; 3+ messages in thread
From: Jarkko Nikula @ 2016-03-10 12:12 UTC (permalink / raw)
  To: linux-i2c; +Cc: Jean Delvare, Wolfram Sang, Reinette Chatre, Jarkko Nikula

Motivation here is to help newer SoCs to reach deeper runtime sleep
states by suspending the SMBUS device with 1 second autosuspend delay
when it is idle.

This is ought to work on both cases where SMBUS PCI device does and
doesn't have PM capabilities. PCI core won't power down the device at
runtime if it doesn't have PM capabilities. We have tested these both
cases, although platforms were quite recent ones.

Jarkko Nikula (2):
  i2c: i801: Convert to struct dev_pm_ops for suspend/resume
  i2c: i801: Add runtime PM support with autosuspend

 drivers/i2c/busses/i2c-i801.c | 52 +++++++++++++++++++++++++++----------------
 1 file changed, 33 insertions(+), 19 deletions(-)

-- 
2.7.0

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] i2c: i801: Convert to struct dev_pm_ops for suspend/resume
  2016-03-10 12:12 [PATCH 0/2] i2c: i801: Add runtime PM support Jarkko Nikula
@ 2016-03-10 12:12 ` Jarkko Nikula
  2016-03-10 12:12 ` [PATCH 2/2] i2c: i801: Add runtime PM support with autosuspend Jarkko Nikula
  1 sibling, 0 replies; 3+ messages in thread
From: Jarkko Nikula @ 2016-03-10 12:12 UTC (permalink / raw)
  To: linux-i2c; +Cc: Jean Delvare, Wolfram Sang, Reinette Chatre, Jarkko Nikula

Stop using legacy PCI PM support and convert to standard dev_pm_ops.
This provides more straightforward path to add runtime PM.

While at it remove explicit PCI power state control and configuration space
save/restore as the PCI core does it.

Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/i2c/busses/i2c-i801.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index f62d69799a9c..091debf7c9de 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -1431,34 +1431,32 @@ static void i801_remove(struct pci_dev *dev)
 }
 
 #ifdef CONFIG_PM
-static int i801_suspend(struct pci_dev *dev, pm_message_t mesg)
+static int i801_suspend(struct device *dev)
 {
-	struct i801_priv *priv = pci_get_drvdata(dev);
+	struct pci_dev *pci_dev = to_pci_dev(dev);
+	struct i801_priv *priv = pci_get_drvdata(pci_dev);
 
-	pci_save_state(dev);
-	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
-	pci_set_power_state(dev, pci_choose_state(dev, mesg));
+	pci_write_config_byte(pci_dev, SMBHSTCFG, priv->original_hstcfg);
 	return 0;
 }
 
-static int i801_resume(struct pci_dev *dev)
+static int i801_resume(struct device *dev)
 {
-	pci_set_power_state(dev, PCI_D0);
-	pci_restore_state(dev);
 	return 0;
 }
-#else
-#define i801_suspend NULL
-#define i801_resume NULL
 #endif
 
+static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
+			    i801_resume, NULL);
+
 static struct pci_driver i801_driver = {
 	.name		= "i801_smbus",
 	.id_table	= i801_ids,
 	.probe		= i801_probe,
 	.remove		= i801_remove,
-	.suspend	= i801_suspend,
-	.resume		= i801_resume,
+	.driver		= {
+		.pm	= &i801_pm_ops,
+	},
 };
 
 static int __init i2c_i801_init(void)
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] i2c: i801: Add runtime PM support with autosuspend
  2016-03-10 12:12 [PATCH 0/2] i2c: i801: Add runtime PM support Jarkko Nikula
  2016-03-10 12:12 ` [PATCH 1/2] i2c: i801: Convert to struct dev_pm_ops for suspend/resume Jarkko Nikula
@ 2016-03-10 12:12 ` Jarkko Nikula
  1 sibling, 0 replies; 3+ messages in thread
From: Jarkko Nikula @ 2016-03-10 12:12 UTC (permalink / raw)
  To: linux-i2c; +Cc: Jean Delvare, Wolfram Sang, Reinette Chatre, Jarkko Nikula

Allow runtime PM so that PM and PCI core can put the device into low-power
state when idle and resume it back when needed in those platforms that
support PM for i801 device.

Enable also autosuspend with 1 second delay in order to not needlessly
toggle power state on and off if there are multiple transactions during
short time.

Device is resumed at the beginning of bus access and marked idle ready
for autosuspend at the end of it.

Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com>
Tested-by: Reinette Chatre <reinette.chatre@intel.com>
---
 drivers/i2c/busses/i2c-i801.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 091debf7c9de..184dfcd547cd 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -94,6 +94,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/itco_wdt.h>
+#include <linux/pm_runtime.h>
 
 #if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
 		defined CONFIG_DMI
@@ -714,9 +715,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 {
 	int hwpec;
 	int block = 0;
-	int ret, xact = 0;
+	int ret = 0, xact = 0;
 	struct i801_priv *priv = i2c_get_adapdata(adap);
 
+	pm_runtime_get_sync(&priv->pci_dev->dev);
+
 	hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC)
 		&& size != I2C_SMBUS_QUICK
 		&& size != I2C_SMBUS_I2C_BLOCK_DATA;
@@ -773,7 +776,8 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 	default:
 		dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n",
 			size);
-		return -EOPNOTSUPP;
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
 
 	if (hwpec)	/* enable/disable hardware PEC */
@@ -796,11 +800,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 		       ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv));
 
 	if (block)
-		return ret;
+		goto out;
 	if (ret)
-		return ret;
+		goto out;
 	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
-		return 0;
+		goto out;
 
 	switch (xact & 0x7f) {
 	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
@@ -812,7 +816,11 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr,
 			     (inb_p(SMBHSTDAT1(priv)) << 8);
 		break;
 	}
-	return 0;
+
+out:
+	pm_runtime_mark_last_busy(&priv->pci_dev->dev);
+	pm_runtime_put_autosuspend(&priv->pci_dev->dev);
+	return ret;
 }
 
 
@@ -1411,6 +1419,11 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	pci_set_drvdata(dev, priv);
 
+	pm_runtime_set_autosuspend_delay(&dev->dev, 1000);
+	pm_runtime_use_autosuspend(&dev->dev);
+	pm_runtime_put_autosuspend(&dev->dev);
+	pm_runtime_allow(&dev->dev);
+
 	return 0;
 }
 
@@ -1418,6 +1431,9 @@ static void i801_remove(struct pci_dev *dev)
 {
 	struct i801_priv *priv = pci_get_drvdata(dev);
 
+	pm_runtime_forbid(&dev->dev);
+	pm_runtime_get_noresume(&dev->dev);
+
 	i801_del_mux(priv);
 	i2c_del_adapter(&priv->adapter);
 	pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
-- 
2.7.0

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-03-10 12:12 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-03-10 12:12 [PATCH 0/2] i2c: i801: Add runtime PM support Jarkko Nikula
2016-03-10 12:12 ` [PATCH 1/2] i2c: i801: Convert to struct dev_pm_ops for suspend/resume Jarkko Nikula
2016-03-10 12:12 ` [PATCH 2/2] i2c: i801: Add runtime PM support with autosuspend Jarkko Nikula

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).