diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/i2c/busses/i2c-bcm-iproc.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/i2c/busses/i2c-bcm-iproc.c')
-rw-r--r-- | kernel/drivers/i2c/busses/i2c-bcm-iproc.c | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/kernel/drivers/i2c/busses/i2c-bcm-iproc.c b/kernel/drivers/i2c/busses/i2c-bcm-iproc.c index f9f2c2082..0419f5284 100644 --- a/kernel/drivers/i2c/busses/i2c-bcm-iproc.c +++ b/kernel/drivers/i2c/busses/i2c-bcm-iproc.c @@ -91,6 +91,7 @@ struct bcm_iproc_i2c_dev { void __iomem *base; struct i2c_adapter adapter; + unsigned int bus_speed; struct completion done; int xfer_is_done; @@ -309,6 +310,7 @@ static int bcm_iproc_i2c_cfg_speed(struct bcm_iproc_i2c_dev *iproc_i2c) bus_speed = 400000; } + iproc_i2c->bus_speed = bus_speed; val = readl(iproc_i2c->base + TIM_CFG_OFFSET); val &= ~(1 << TIM_CFG_MODE_400_SHIFT); val |= (bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; @@ -439,6 +441,60 @@ static int bcm_iproc_i2c_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM_SLEEP + +static int bcm_iproc_i2c_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); + + /* make sure there's no pending interrupt when we go into suspend */ + writel(0, iproc_i2c->base + IE_OFFSET); + readl(iproc_i2c->base + IE_OFFSET); + synchronize_irq(iproc_i2c->irq); + + /* now disable the controller */ + bcm_iproc_i2c_enable_disable(iproc_i2c, false); + + return 0; +} + +static int bcm_iproc_i2c_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct bcm_iproc_i2c_dev *iproc_i2c = platform_get_drvdata(pdev); + int ret; + u32 val; + + /* + * Power domain could have been shut off completely in system deep + * sleep, so re-initialize the block here + */ + ret = bcm_iproc_i2c_init(iproc_i2c); + if (ret) + return ret; + + /* configure to the desired bus speed */ + val = readl(iproc_i2c->base + TIM_CFG_OFFSET); + val &= ~(1 << TIM_CFG_MODE_400_SHIFT); + val |= (iproc_i2c->bus_speed == 400000) << TIM_CFG_MODE_400_SHIFT; + writel(val, iproc_i2c->base + TIM_CFG_OFFSET); + + bcm_iproc_i2c_enable_disable(iproc_i2c, true); + + return 0; +} + +static const struct dev_pm_ops bcm_iproc_i2c_pm_ops = { + .suspend_late = &bcm_iproc_i2c_suspend, + .resume_early = &bcm_iproc_i2c_resume +}; + +#define BCM_IPROC_I2C_PM_OPS (&bcm_iproc_i2c_pm_ops) +#else +#define BCM_IPROC_I2C_PM_OPS NULL +#endif /* CONFIG_PM_SLEEP */ + static const struct of_device_id bcm_iproc_i2c_of_match[] = { { .compatible = "brcm,iproc-i2c" }, { /* sentinel */ } @@ -449,6 +505,7 @@ static struct platform_driver bcm_iproc_i2c_driver = { .driver = { .name = "bcm-iproc-i2c", .of_match_table = bcm_iproc_i2c_of_match, + .pm = BCM_IPROC_I2C_PM_OPS, }, .probe = bcm_iproc_i2c_probe, .remove = bcm_iproc_i2c_remove, |