Skip to content

Commit

Permalink
i2c: i801: Add runtime PM support with autosuspend
Browse files Browse the repository at this point in the history
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>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Jarkko Nikula authored and Wolfram Sang committed Apr 12, 2016
1 parent 2ee73c4 commit a7401ca
Showing 1 changed file with 22 additions and 6 deletions.
28 changes: 22 additions & 6 deletions drivers/i2c/busses/i2c-i801.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand All @@ -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 */
Expand All @@ -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;
}


Expand Down Expand Up @@ -1413,13 +1421,21 @@ 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;
}

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);
Expand Down

0 comments on commit a7401ca

Please sign in to comment.