summaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-bcm-iproc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 18:42:39 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-25 18:42:39 -0700
commit24867481b8c0a3bc3ab53b634e3cc03680ac3ac6 (patch)
tree87a0f018c5e0fb61275b5a48977108ad1a33aa8b /drivers/i2c/busses/i2c-bcm-iproc.c
parent9390bd0d14b4585f7ac2df15ff5f52af182251e1 (diff)
parenta294aba164389a3d2c40dfcf5f3989a3bbfe38a2 (diff)
downloadblackbird-op-linux-24867481b8c0a3bc3ab53b634e3cc03680ac3ac6.tar.gz
blackbird-op-linux-24867481b8c0a3bc3ab53b634e3cc03680ac3ac6.zip
Merge branch 'i2c/for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang: "Highlights: - new drivers for Mediatek I2C, APM X-Gene, Broadcom Settop - major updates to at91, davinci - bugfixes to the mux infrastructure when dealing with the new quirk mechanism - more users for the bus recovery feature - further improvements to the slave framework Plus the usual bunch of smaller driver and core improvements and fixes. There is one patch removing old code from an ARM platform. This has been acked by the sh_mobile maintainer Simon Horman" * 'i2c/for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (48 commits) i2c: busses: i2c-bcm2835: limits cdiv to allowed values i2c: sh_mobile: use proper type for timeout i2c: sh_mobile: use adapter default for timeout i2c: rcar: use proper type for timeout i2c: rcar: use adapter default for timeout i2c: designware: Make sure the device is suspended before disabling runtime PM i2c: tegra: apply size limit quirk i2c: tegra: don't advertise SMBUS_QUICK i2c: octeon: remove unused signal handling i2c: davinci: Optimize SCL generation i2c: mux: pca954x: Use __i2c_transfer because of quirks i2c: mux: Use __i2c_transfer() instead of calling parent's master_xfer() i2c: use parent adapter quirks in mux i2c: bcm2835: clear reserved bits in S-Register ARM: shmobile: r8a7740: remove I2C errata handling i2c: sh_mobile: add errata workaround i2c: at91: fix code checker warnings i2c: busses: xgene-slimpro: fix incorrect __init declation for probe i2c: davinci: Avoid sending to own address i2c: davinci: Refactor i2c_davinci_wait_bus_not_busy() ...
Diffstat (limited to 'drivers/i2c/busses/i2c-bcm-iproc.c')
-rw-r--r--drivers/i2c/busses/i2c-bcm-iproc.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-bcm-iproc.c b/drivers/i2c/busses/i2c-bcm-iproc.c
index f9f2c2082151..0419f5284609 100644
--- a/drivers/i2c/busses/i2c-bcm-iproc.c
+++ b/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,
OpenPOWER on IntegriCloud