[Patch V7] i2c: imx: add runtime pm support to improve the performance

2015-08-31 Thread Gao Pan
In our former i2c driver, i2c clk is enabled and disabled in
xfer function, which contributes to power saving. However,
the clk enable process brings a busy wait delay until the core
is stable. As a result, the performance is sacrificed.

To weigh the power consumption and i2c bus performance, runtime
pm is the good solution for it. The clk is enabled when a i2c
transfer starts, and disabled after a specifically defined delay.

Without the patch the test case (many eeprom reads) executes with approx:
real 1m7.735s
user 0m0.488s
sys 0m20.040s

With the patch the same test case (many eeprom reads) executes with approx:
real 0m54.241s
user 0m0.440s
sys 0m5.920s

Signed-off-by: Fugang Duan 
Signed-off-by: Gao Pan 
[wsa: fixed some indentation]
Signed-off-by: Wolfram Sang 
---
V2:
As Uwe Kleine-König's suggestion, the version do below changes:
 -call clk_prepare_enable in probe to avoid never enabling clock
  if CONFIG_PM is disabled
 -enable clock before request IRQ in probe
 -remove the pm staff in i2c_imx_isr

V3:
 -pm_runtime_get_sync returns < 0 as error

V4:
 -add pm_runtime_set_active before pm_runtime_enable
 -replace pm_runtime_put_autosuspend with pm_runtime_autosuspend
  in probe
 -add error disposal when i2c_add_numbered_adapter fails

V5:
 -clean up and disable runtime PM when i2c_add_numbered_adapter fails
 -use pm_runtime_get and pm_runtime_put_autosuspend in probe

V6:
 -disable the clock manually and set the state to suspended explicitly with
  pm_runtime_set_suspended

V7:
 -manually disabling the clock and use pm_runtime_put_noidle in the remove 
callback

 drivers/i2c/busses/i2c-imx.c | 90 ++--
 1 file changed, 78 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 785aa67..d7c823b 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -53,6 +53,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /** Defines 

 
***/
@@ -118,6 +119,8 @@
 #define I2CR_IEN_OPCODE_0  0x0
 #define I2CR_IEN_OPCODE_1  I2CR_IEN
 
+#define I2C_PM_TIMEOUT 10 /* ms */
+
 /** Variables 
**
 
***/
 
@@ -520,9 +523,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
 
i2c_imx_set_clk(i2c_imx);
 
-   result = clk_prepare_enable(i2c_imx->clk);
-   if (result)
-   return result;
imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
/* Enable I2C controller */
imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, 
IMX_I2C_I2SR);
@@ -575,7 +575,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
/* Disable I2C controller */
temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
-   clk_disable_unprepare(i2c_imx->clk);
 }
 
 static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
@@ -894,6 +893,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
 
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
 
+   result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
+   if (result < 0)
+   goto out;
+
/* Start I2C transfer */
result = i2c_imx_start(i2c_imx);
if (result)
@@ -950,6 +953,10 @@ fail0:
/* Stop I2C transfer */
i2c_imx_stop(i2c_imx);
 
+out:
+   pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
+   pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
+
dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
(result < 0) ? "error" : "success msg",
(result < 0) ? result : num);
@@ -1020,9 +1027,10 @@ static int i2c_imx_probe(struct platform_device *pdev)
 
ret = clk_prepare_enable(i2c_imx->clk);
if (ret) {
-   dev_err(&pdev->dev, "can't enable I2C clock\n");
+   dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
return ret;
}
+
/* Request IRQ */
ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
pdev->name, i2c_imx);
@@ -1037,6 +1045,18 @@ static int i2c_imx_probe(struct platform_device *pdev)
/* Set up adapter data */
i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
 
+   /* Set up platform driver data */
+   platform_set_drvdata(pdev, i2c_imx);
+
+   pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT);
+   pm_runtime_use_autosuspend(&pdev->dev);
+   pm_runtime_set_active(&pdev->dev);
+   pm_runtime_enable(&pdev->dev);
+
+   ret = pm_runtime_get_sync(&pdev->dev);
+   if (ret < 0)
+   goto rpm_disable;
+
/* 

RE: [Patch V6] i2c: imx: add runtime pm support to improve the performance

2015-08-31 Thread Gao Pandy


> -Original Message-
> From: Heiner Kallweit [mailto:hkallwe...@gmail.com]
> Sent: Monday, August 31, 2015 2:14 PM
> To: Gao Pan-B54642; w...@the-dreams.de
> Cc: linux-i2c@vger.kernel.org; Li Frank-B20596; Duan Fugang-B38611;
> u.kleine-koe...@pengutronix.de; ker...@pengutronix.de
> Subject: Re: [Patch V6] i2c: imx: add runtime pm support to improve the
> performance
> 
> Am 28.08.2015 um 08:30 schrieb Gao Pan:
> > In our former i2c driver, i2c clk is enabled and disabled in xfer
> > function, which contributes to power saving. However, the clk enable
> > process brings a busy wait delay until the core is stable. As a
> > result, the performance is sacrificed.
> >
> > To weigh the power consumption and i2c bus performance, runtime pm is
> > the good solution for it. The clk is enabled when a i2c transfer
> > starts, and disabled after a specifically defined delay.
> >
> > Without the patch the test case (many eeprom reads) executes with
> approx:
> > real 1m7.735s
> > user 0m0.488s
> > sys 0m20.040s
> >
> > With the patch the same test case (many eeprom reads) executes with
> approx:
> > real 0m54.241s
> > user 0m0.440s
> > sys 0m5.920s
> >
> > Signed-off-by: Fugang Duan 
> > Signed-off-by: Gao Pan 
> > [wsa: fixed some indentation]
> > Signed-off-by: Wolfram Sang 
> > ---
> > V2:
> > As Uwe Kleine-König's suggestion, the version do below changes:
> >  -call clk_prepare_enable in probe to avoid never enabling clock
> >   if CONFIG_PM is disabled
> >  -enable clock before request IRQ in probe  -remove the pm staff in
> > i2c_imx_isr
> >
> > V3:
> >  -pm_runtime_get_sync returns < 0 as error
> >
> > V4:
> >  -add pm_runtime_set_active before pm_runtime_enable  -replace
> > pm_runtime_put_autosuspend with pm_runtime_autosuspend
> >   in probe
> >  -add error disposal when i2c_add_numbered_adapter fails
> >
> > V5:
> >  -clean up and disable runtime PM when i2c_add_numbered_adapter fails
> > -use pm_runtime_get and pm_runtime_put_autosuspend in probe
> >
> > V6:
> >  -disable the clock manually and set the state to suspended explicitly
> with
> >   pm_runtime_set_suspended
> >
> > drivers/i2c/busses/i2c-imx.c | 88
> > ++--
> >  1 file changed, 76 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/i2c/busses/i2c-imx.c
> > b/drivers/i2c/busses/i2c-imx.c index 785aa67..ac85e5c 100644
> > --- a/drivers/i2c/busses/i2c-imx.c
> > +++ b/drivers/i2c/busses/i2c-imx.c
> > @@ -53,6 +53,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  /** Defines
> > 
> >
> > **
> > */
> > @@ -118,6 +119,8 @@
> >  #define I2CR_IEN_OPCODE_0  0x0
> >  #define I2CR_IEN_OPCODE_1  I2CR_IEN
> >
> > +#define I2C_PM_TIMEOUT 10 /* ms */
> > +
> >  /** Variables
> > **
> >
> > **
> > */
> >
> > @@ -520,9 +523,6 @@ static int i2c_imx_start(struct imx_i2c_struct
> > *i2c_imx)
> >
> > i2c_imx_set_clk(i2c_imx);
> >
> > -   result = clk_prepare_enable(i2c_imx->clk);
> > -   if (result)
> > -   return result;
> > imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
> > /* Enable I2C controller */
> > imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx,
> > IMX_I2C_I2SR); @@ -575,7 +575,6 @@ static void i2c_imx_stop(struct
> imx_i2c_struct *i2c_imx)
> > /* Disable I2C controller */
> > temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
> > imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
> > -   clk_disable_unprepare(i2c_imx->clk);
> >  }
> >
> >  static irqreturn_t i2c_imx_isr(int irq, void *dev_id) @@ -894,6
> > +893,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
> >
> > dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
> >
> > +   result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
> > +   if (result < 0)
> > +   goto out;
> > +
> > /* Start I2C transfer */
> > result = i2c_imx_start(i2c_imx);
> > if (result)
> > @@ -950,6 +953,10 @@ fail0:
> > /* Stop I2C transfer */
> > i2c_imx_stop(i2c_imx);
> >
> > +out:
> > +   pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
> > +   pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
> > +
> > dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
> > (result < 0) ? "error" : "success msg",
> > (result < 0) ? result : num);
> > @@ -1020,9 +1027,10 @@ static int i2c_imx_probe(struct platform_device
> > *pdev)
> >
> > ret = clk_prepare_enable(i2c_imx->clk);
> > if (ret) {
> > -   dev_err(&pdev->dev, "can't enable I2C clock\n");
> > +   dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
> > return ret;
> > }
> > +
> > /* Request I

[PATCH 2/6] i2c: designware: Disable interrupts before requesting PCI device interrupt

2015-08-31 Thread Jarkko Nikula
Device must not generate interrupts before registering the interrupt
handler so move i2c_dw_disable_int() before requesting it.

There are no known issues with this. The code has been here since commit
fe20ff5c7e9c ("i2c-designware: Add support for Designware core behind PCI
devices.").

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-pcidrv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
index e477dddcdae5..d9e8937f062f 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -260,6 +260,7 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
 
snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci");
 
+   i2c_dw_disable_int(dev);
r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr,
IRQF_SHARED | IRQF_COND_SUSPEND, adap->name, dev);
if (r) {
@@ -267,7 +268,6 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
return r;
}
 
-   i2c_dw_disable_int(dev);
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/6] i2c: designware: Make dw_readl() and dw_writel() static

2015-08-31 Thread Jarkko Nikula
dw_readl() and dw_writel() are not used outside of i2c-designware-core and
they are not exported so make them static and remove their forward
declaration.

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-core.c | 4 ++--
 drivers/i2c/busses/i2c-designware-core.h | 2 --
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index c9e93a76a455..52272a01c679 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -165,7 +165,7 @@ static char *abort_sources[] = {
"lost arbitration",
 };
 
-u32 dw_readl(struct dw_i2c_dev *dev, int offset)
+static u32 dw_readl(struct dw_i2c_dev *dev, int offset)
 {
u32 value;
 
@@ -181,7 +181,7 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
return value;
 }
 
-void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
+static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
 {
if (dev->accessor_flags & ACCESS_SWAP)
b = swab32(b);
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index 10c79038834d..0e73b8672402 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -112,8 +112,6 @@ struct dw_i2c_dev {
 #define ACCESS_SWAP0x0001
 #define ACCESS_16BIT   0x0002
 
-extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
-extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
 extern int i2c_dw_init(struct dw_i2c_dev *dev);
 extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
int num);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/6] i2c: designware: Move common probe code into i2c_dw_probe()

2015-08-31 Thread Jarkko Nikula
There is some code duplication in i2c-designware-platdrv and
i2c-designware-pcidrv probe functions. What is even worse that duplication
requires i2c_dw_xfer(), i2c_dw_func() and i2c_dw_isr() i2c-designware-core
functions to be exported.

Therefore move common code into new i2c_dw_probe() and make functions above
local to i2c-designware-core.

While merging the code patch does following functional changes:

- I2C Adapter name will be "i2c-designware". Previously adapter name was
  "Synopsys DesignWare I2C adapter" for platform and ACPI devices and
  "i2c-designware-pci" for PCI devices.
- Interrupt name too will be "i2c-designware". Previous it was platform
  device name, ACPI device name or "i2c-designware-pci".
- Error code from devm_request_irq() and i2c_add_numbered_adapter() will be
  printed in case of error.

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-core.c| 48 +
 drivers/i2c/busses/i2c-designware-core.h|  5 +--
 drivers/i2c/busses/i2c-designware-pcidrv.c  | 30 ++
 drivers/i2c/busses/i2c-designware-platdrv.c | 28 ++---
 4 files changed, 48 insertions(+), 63 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 52272a01c679..501c8ac0cf14 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -618,7 +618,7 @@ static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev)
 /*
  * Prepare controller for a transaction and call i2c_dw_xfer_msg
  */
-int
+static int
 i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 {
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
@@ -702,14 +702,17 @@ done_nolock:
 
return ret;
 }
-EXPORT_SYMBOL_GPL(i2c_dw_xfer);
 
-u32 i2c_dw_func(struct i2c_adapter *adap)
+static u32 i2c_dw_func(struct i2c_adapter *adap)
 {
struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
return dev->functionality;
 }
-EXPORT_SYMBOL_GPL(i2c_dw_func);
+
+static struct i2c_algorithm i2c_dw_algo = {
+   .master_xfer= i2c_dw_xfer,
+   .functionality  = i2c_dw_func,
+};
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
@@ -770,7 +773,7 @@ static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev 
*dev)
  * Interrupt service routine. This gets called whenever an I2C interrupt
  * occurs.
  */
-irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
+static irqreturn_t i2c_dw_isr(int this_irq, void *dev_id)
 {
struct dw_i2c_dev *dev = dev_id;
u32 stat, enabled;
@@ -813,7 +816,6 @@ tx_aborted:
 
return IRQ_HANDLED;
 }
-EXPORT_SYMBOL_GPL(i2c_dw_isr);
 
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
@@ -838,5 +840,39 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
 }
 EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
 
+int i2c_dw_probe(struct dw_i2c_dev *dev)
+{
+   struct i2c_adapter *adap = &dev->adapter;
+   int r;
+
+   init_completion(&dev->cmd_complete);
+   mutex_init(&dev->lock);
+
+   r = i2c_dw_init(dev);
+   if (r)
+   return r;
+
+   snprintf(adap->name, sizeof(adap->name), "i2c-designware");
+   adap->algo = &i2c_dw_algo;
+   adap->dev.parent = dev->dev;
+   i2c_set_adapdata(adap, dev);
+
+   i2c_dw_disable_int(dev);
+   r = devm_request_irq(dev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
+adap->name, dev);
+   if (r) {
+   dev_err(dev->dev, "failure requesting irq %i: %d\n",
+   dev->irq, r);
+   return r;
+   }
+
+   r = i2c_add_numbered_adapter(adap);
+   if (r)
+   dev_err(dev->dev, "failure adding adapter: %d\n", r);
+
+   return r;
+}
+EXPORT_SYMBOL_GPL(i2c_dw_probe);
+
 MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index 0e73b8672402..1d50898e7b24 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -113,13 +113,10 @@ struct dw_i2c_dev {
 #define ACCESS_16BIT   0x0002
 
 extern int i2c_dw_init(struct dw_i2c_dev *dev);
-extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
-   int num);
-extern u32 i2c_dw_func(struct i2c_adapter *adap);
-extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
 extern void i2c_dw_disable(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
 extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
+extern int i2c_dw_probe(struct dw_i2c_dev *dev);
 
 #if IS_ENABLED(CONFIG_I2C_DESIGNWARE_BAYTRAIL)
 extern int i2c_dw_eval_lock_support(struct dw_i2c_dev *dev);
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
index d9e8937f062f..169be1e26241 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ 

[PATCH 5/6] i2c: designware: Rename platform driver probe and PM functions

2015-08-31 Thread Jarkko Nikula
Make it easier to distinguish between i2c-designware-platdrv and
i2c-designware-core functions and to be consistent with
i2c-designware-pcidrv.

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-platdrv.c | 24 
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c 
b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3dd2de31a2f8..17167cd4812d 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -133,7 +133,7 @@ static inline int dw_i2c_acpi_configure(struct 
platform_device *pdev)
 static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
 #endif
 
-static int dw_i2c_probe(struct platform_device *pdev)
+static int dw_i2c_plat_probe(struct platform_device *pdev)
 {
struct dw_i2c_dev *dev;
struct i2c_adapter *adap;
@@ -271,7 +271,7 @@ static int dw_i2c_probe(struct platform_device *pdev)
return 0;
 }
 
-static int dw_i2c_remove(struct platform_device *pdev)
+static int dw_i2c_plat_remove(struct platform_device *pdev)
 {
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
 
@@ -300,12 +300,12 @@ MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
 #endif
 
 #ifdef CONFIG_PM_SLEEP
-static int dw_i2c_prepare(struct device *dev)
+static int dw_i2c_plat_prepare(struct device *dev)
 {
return pm_runtime_suspended(dev);
 }
 
-static void dw_i2c_complete(struct device *dev)
+static void dw_i2c_plat_complete(struct device *dev)
 {
if (dev->power.direct_complete)
pm_request_resume(dev);
@@ -316,7 +316,7 @@ static void dw_i2c_complete(struct device *dev)
 #endif
 
 #ifdef CONFIG_PM
-static int dw_i2c_suspend(struct device *dev)
+static int dw_i2c_plat_suspend(struct device *dev)
 {
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
@@ -327,7 +327,7 @@ static int dw_i2c_suspend(struct device *dev)
return 0;
 }
 
-static int dw_i2c_resume(struct device *dev)
+static int dw_i2c_plat_resume(struct device *dev)
 {
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
@@ -341,10 +341,10 @@ static int dw_i2c_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
-   .prepare = dw_i2c_prepare,
-   .complete = dw_i2c_complete,
-   SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_suspend, dw_i2c_resume)
-   SET_RUNTIME_PM_OPS(dw_i2c_suspend, dw_i2c_resume, NULL)
+   .prepare = dw_i2c_plat_prepare,
+   .complete = dw_i2c_plat_complete,
+   SET_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
+   SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
 };
 
 #define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
@@ -356,8 +356,8 @@ static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
 MODULE_ALIAS("platform:i2c_designware");
 
 static struct platform_driver dw_i2c_driver = {
-   .probe = dw_i2c_probe,
-   .remove = dw_i2c_remove,
+   .probe = dw_i2c_plat_probe,
+   .remove = dw_i2c_plat_remove,
.driver = {
.name   = "i2c_designware",
.of_match_table = of_match_ptr(dw_i2c_of_match),
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/6] i2c: designware: Remove unused functions

2015-08-31 Thread Jarkko Nikula
i2c_dw_is_enabled() became unused by the commit be58eda775c8
("i2c: designware-pci: Cleanup driver power management") and
i2c_dw_enable() by the commit 3a48d1c08fe0 ("i2c: prevent spurious
interrupt on Designware controllers").

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-core.c | 13 -
 drivers/i2c/busses/i2c-designware-core.h |  2 --
 2 files changed, 15 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index dec0af7d0471..c9e93a76a455 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -815,19 +815,6 @@ tx_aborted:
 }
 EXPORT_SYMBOL_GPL(i2c_dw_isr);
 
-void i2c_dw_enable(struct dw_i2c_dev *dev)
-{
-   /* Enable the adapter */
-   __i2c_dw_enable(dev, true);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_enable);
-
-u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
-{
-   return dw_readl(dev, DW_IC_ENABLE);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
-
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
/* Disable controller */
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index f44aeeeb91c6..10c79038834d 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -119,8 +119,6 @@ extern int i2c_dw_xfer(struct i2c_adapter *adap, struct 
i2c_msg msgs[],
int num);
 extern u32 i2c_dw_func(struct i2c_adapter *adap);
 extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
-extern void i2c_dw_enable(struct dw_i2c_dev *dev);
-extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
 extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/6] i2c: designware: Code duplication removal and cleanups

2015-08-31 Thread Jarkko Nikula
It bothered to me to see "static struct i2c_algorithm i2c_dw_algo {}"
defined twice both in i2c-designware-pcidrv.c and
i2c-designware-platdrv.c and so many exported i2c-designware-core
functions.

It turned out some of them became unused or are local and there were
also duplicated probe code that I moved to new common i2c_dw_probe().

Object sizes below before and after this set from CONFIG_X86_64=y build.

   textdata bss dec hex filename
   64391096   075351d6f 
drivers/i2c/busses/i2c-designware-core.ko
   51231588  1667271a47 drivers/i2c/busses/i2c-designware-pci.ko
   52741096  16638618f2 
drivers/i2c/busses/i2c-designware-platform.ko
  168363780  32   2064850a8 (TOTALS)

   textdata bss dec hex filename
   72251120  16836120a9 
drivers/i2c/busses/i2c-designware-core.ko
   42811524   0580516ad drivers/i2c/busses/i2c-designware-pci.ko
   43371072   054091521 
drivers/i2c/busses/i2c-designware-platform.ko
  158433716  16   195754c77 (TOTALS)

Jarkko Nikula (6):
  i2c: designware: Remove interrupt clearing from i2c_dw_pci_probe()
  i2c: designware: Disable interrupts before requesting PCI device
interrupt
  i2c: designware: Remove unused functions
  i2c: designware: Make dw_readl() and dw_writel() static
  i2c: designware: Rename platform driver probe and PM functions
  i2c: designware: Move common probe code into i2c_dw_probe()

 drivers/i2c/busses/i2c-designware-core.c| 73 ++---
 drivers/i2c/busses/i2c-designware-core.h| 10 +---
 drivers/i2c/busses/i2c-designware-pcidrv.c  | 31 ++--
 drivers/i2c/busses/i2c-designware-platdrv.c | 52 ++--
 4 files changed, 63 insertions(+), 103 deletions(-)

-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/6] i2c: designware: Remove interrupt clearing from i2c_dw_pci_probe()

2015-08-31 Thread Jarkko Nikula
There is no need to clear interrupts in i2c_dw_pci_probe() since only place
where interrupts are unmasked is i2c_dw_xfer_init() and there interrupts
are always cleared after commit 2a2d95e9d6d2 ("i2c: designware: always
clear interrupts before enabling them").

This allows to cleanup the code and replace i2c_dw_clear_int() in
i2c_dw_xfer_init() by direct register read as there are no other callers.

Signed-off-by: Jarkko Nikula 
---
 drivers/i2c/busses/i2c-designware-core.c   | 8 +---
 drivers/i2c/busses/i2c-designware-core.h   | 1 -
 drivers/i2c/busses/i2c-designware-pcidrv.c | 1 -
 3 files changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/i2c/busses/i2c-designware-core.c 
b/drivers/i2c/busses/i2c-designware-core.c
index 7441cdc1b34a..dec0af7d0471 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -438,7 +438,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
__i2c_dw_enable(dev, true);
 
/* Clear and enable interrupts */
-   i2c_dw_clear_int(dev);
+   dw_readl(dev, DW_IC_CLR_INTR);
dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK);
 }
 
@@ -839,12 +839,6 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
 }
 EXPORT_SYMBOL_GPL(i2c_dw_disable);
 
-void i2c_dw_clear_int(struct dw_i2c_dev *dev)
-{
-   dw_readl(dev, DW_IC_CLR_INTR);
-}
-EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
-
 void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 {
dw_writel(dev, 0, DW_IC_INTR_MASK);
diff --git a/drivers/i2c/busses/i2c-designware-core.h 
b/drivers/i2c/busses/i2c-designware-core.h
index 9630222abf32..f44aeeeb91c6 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -122,7 +122,6 @@ extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id);
 extern void i2c_dw_enable(struct dw_i2c_dev *dev);
 extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable(struct dw_i2c_dev *dev);
-extern void i2c_dw_clear_int(struct dw_i2c_dev *dev);
 extern void i2c_dw_disable_int(struct dw_i2c_dev *dev);
 extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
 
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c 
b/drivers/i2c/busses/i2c-designware-pcidrv.c
index df23e8c30e6f..e477dddcdae5 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -268,7 +268,6 @@ static int i2c_dw_pci_probe(struct pci_dev *pdev,
}
 
i2c_dw_disable_int(dev);
-   i2c_dw_clear_int(dev);
r = i2c_add_numbered_adapter(adap);
if (r) {
dev_err(&pdev->dev, "failure adding adapter\n");
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Do you need a loan?

2015-08-31 Thread
We offer private, commercial and personal loans with very low annualinterest 
rates as low as 2% in one year to 50 years repayment period anywhere in the 
world. We offer loans ranging from $5000 to $100 million. Our loans are well 
insured for maximum security is our priority. Are you losing sleep at night 
worrying how to get a legitimate loan lender? You bite your nails that fast? 
Instead of beating you, contact JM Financial Services Ltd now, specialists who 
help stop loans bad credit history to find a solution that victory is our 
mission. Applicants must fill out a loan application form below:

FORM credit application

loan applications
Your full name *
Your e-mail *
Your phone *
Your address *
Your city *
State / Province *
Country *
Fax*
Date of birth *
Do you have an account? *
Have you applied before? *
The loan amount is needed *
The Loan Duration*
The life expectancy *
The purpose of the loan *
Send me a scanned copy of your passport: *

Creditor: Mr. Prakash Lass Dickson.
Company: JM Financial Services Ltd.
Copyright JM Financial Ltd. All rights reserved.
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] i2c: mux: reg: simplify register size checking

2015-08-31 Thread Wolfram Sang
On Fri, Aug 21, 2015 at 03:26:23AM +, York Sun wrote:
> Sorry for top posting, I am out and replying using web access.
> 
> This patch looks OK. I cannot test it until earliest next Friday.

Did you have the chance to test it?

Thanks,

   Wolfram



signature.asc
Description: Digital signature


Re: [RESEND PATCH 1/7] i2c: core: Export I2C module alias information in dummy driver

2015-08-31 Thread Wolfram Sang

> > The dummy driver is always loaded when the i2c core inits.
> > 
> 
> Ok, I wondered if that was the case but I
> was not sure so I posted it just in case.

Check the source code, this part is pretty obvious...



signature.asc
Description: Digital signature


Re: [PATCH] i2c: muxes: fix leaked i2c adapter device node references

2015-08-31 Thread Wolfram Sang
On Wed, Aug 26, 2015 at 11:59:33PM +0300, Vladimir Zapolskiy wrote:
> Every call of of_parse_phandle() increments user count of found device
> node, if OF_DYNAMIC is enabled.
> 
> The change fixes all similar addressed cases in drivers/i2c.
> 
> Signed-off-by: Vladimir Zapolskiy 

Applied to for-next, thanks!



signature.asc
Description: Digital signature


Re: [PATCH] i2c: mux: reg: simplify register size checking

2015-08-31 Thread York Sun


On 08/31/2015 03:24 PM, Wolfram Sang wrote:
> On Fri, Aug 21, 2015 at 03:26:23AM +, York Sun wrote:
>> Sorry for top posting, I am out and replying using web access.
>>
>> This patch looks OK. I cannot test it until earliest next Friday.
> 
> Did you have the chance to test it?
> 

I am working on it. My hardware was replaced with a new version. I am running my
driver now. Will try your patch and confirm.

York

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] drivers: i2c: exynos5: irq spinlock rt-safe

2015-08-31 Thread Anders Roxell
On 2015-08-25 23:51, Thomas Gleixner wrote:
> On Tue, 25 Aug 2015, Anders Roxell wrote:
> 
> > The exynos5_i2c_message_start enables interrupts while holding the i2c
> > lock which is sought by the irq handler. If an IRQ is received before
> > this lock is released then a deadlock occurs.
> 
> That's crap. The interrupt handler runs in an irq thread as RT forces
> all normal interrupts to that.

You are right, I will send a v2 with a better changelog.

Cheers,
Anders
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] i2c: mux: reg: simplify register size checking

2015-08-31 Thread York Sun


On 08/20/2015 04:40 PM, Wolfram Sang wrote:
> Checking was done at three different locations, just do it once and
> properly at probing time.
> 
> Signed-off-by: Wolfram Sang 
> Cc: York Sun 
> ---
> 
> York Sun: Can you test this patch? I can only build test.

Patch is OK. Verified on hardware with good and intentional bad values.

Acked-by: York Sun 

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH 1/7] i2c: core: Export I2C module alias information in dummy driver

2015-08-31 Thread Javier Martinez Canillas
Hello Wolfram,

On 08/31/2015 10:31 PM, Wolfram Sang wrote:
> 
>>> The dummy driver is always loaded when the i2c core inits.
>>>
>>
>> Ok, I wondered if that was the case but I
>> was not sure so I posted it just in case.
> 
> Check the source code, this part is pretty obvious...
>

Yes, sorry for missing that obvious detail...

Best regards,
-- 
Javier Martinez Canillas
Open Source Group
Samsung Research America
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RESEND PATCH 1/7] i2c: core: Export I2C module alias information in dummy driver

2015-08-31 Thread Wolfram Sang
On Tue, Sep 01, 2015 at 12:30:22AM +0200, Javier Martinez Canillas wrote:
> Hello Wolfram,
> 
> On 08/31/2015 10:31 PM, Wolfram Sang wrote:
> > 
> >>> The dummy driver is always loaded when the i2c core inits.
> >>>
> >>
> >> Ok, I wondered if that was the case but I
> >> was not sure so I posted it just in case.
> > 
> > Check the source code, this part is pretty obvious...
> >
> 
> Yes, sorry for missing that obvious detail...

No problem, now you know :)



signature.asc
Description: Digital signature


Re: [Patch V7] i2c: imx: add runtime pm support to improve the performance

2015-08-31 Thread Heiner Kallweit
Am 31.08.2015 um 09:32 schrieb Gao Pan:
> In our former i2c driver, i2c clk is enabled and disabled in
> xfer function, which contributes to power saving. However,
> the clk enable process brings a busy wait delay until the core
> is stable. As a result, the performance is sacrificed.
> 
> To weigh the power consumption and i2c bus performance, runtime
> pm is the good solution for it. The clk is enabled when a i2c
> transfer starts, and disabled after a specifically defined delay.
> 
> Without the patch the test case (many eeprom reads) executes with approx:
> real 1m7.735s
> user 0m0.488s
> sys 0m20.040s
> 
> With the patch the same test case (many eeprom reads) executes with approx:
> real 0m54.241s
> user 0m0.440s
> sys 0m5.920s
> 
> Signed-off-by: Fugang Duan 
> Signed-off-by: Gao Pan 
> [wsa: fixed some indentation]
> Signed-off-by: Wolfram Sang 
> ---
> V2:
> As Uwe Kleine-König's suggestion, the version do below changes:
>  -call clk_prepare_enable in probe to avoid never enabling clock
>   if CONFIG_PM is disabled
>  -enable clock before request IRQ in probe
>  -remove the pm staff in i2c_imx_isr
> 
> V3:
>  -pm_runtime_get_sync returns < 0 as error
> 
> V4:
>  -add pm_runtime_set_active before pm_runtime_enable
>  -replace pm_runtime_put_autosuspend with pm_runtime_autosuspend
>   in probe
>  -add error disposal when i2c_add_numbered_adapter fails
> 
> V5:
>  -clean up and disable runtime PM when i2c_add_numbered_adapter fails
>  -use pm_runtime_get and pm_runtime_put_autosuspend in probe
> 
> V6:
>  -disable the clock manually and set the state to suspended explicitly with
>   pm_runtime_set_suspended
> 
> V7:
>  -manually disabling the clock and use pm_runtime_put_noidle in the remove 
> callback
> 
>  drivers/i2c/busses/i2c-imx.c | 90 
> ++--
>  1 file changed, 78 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
> index 785aa67..d7c823b 100644
> --- a/drivers/i2c/busses/i2c-imx.c
> +++ b/drivers/i2c/busses/i2c-imx.c
> @@ -53,6 +53,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  /** Defines 
> 
>  
> ***/
> @@ -118,6 +119,8 @@
>  #define I2CR_IEN_OPCODE_00x0
>  #define I2CR_IEN_OPCODE_1I2CR_IEN
>  
> +#define I2C_PM_TIMEOUT   10 /* ms */
> +
>  /** Variables 
> **
>  
> ***/
>  
> @@ -520,9 +523,6 @@ static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
>  
>   i2c_imx_set_clk(i2c_imx);
>  
> - result = clk_prepare_enable(i2c_imx->clk);
> - if (result)
> - return result;
>   imx_i2c_write_reg(i2c_imx->ifdr, i2c_imx, IMX_I2C_IFDR);
>   /* Enable I2C controller */
>   imx_i2c_write_reg(i2c_imx->hwdata->i2sr_clr_opcode, i2c_imx, 
> IMX_I2C_I2SR);
> @@ -575,7 +575,6 @@ static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
>   /* Disable I2C controller */
>   temp = i2c_imx->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
>   imx_i2c_write_reg(temp, i2c_imx, IMX_I2C_I2CR);
> - clk_disable_unprepare(i2c_imx->clk);
>  }
>  
>  static irqreturn_t i2c_imx_isr(int irq, void *dev_id)
> @@ -894,6 +893,10 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
>  
>   dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
>  
> + result = pm_runtime_get_sync(i2c_imx->adapter.dev.parent);
> + if (result < 0)
> + goto out;
> +
>   /* Start I2C transfer */
>   result = i2c_imx_start(i2c_imx);
>   if (result)
> @@ -950,6 +953,10 @@ fail0:
>   /* Stop I2C transfer */
>   i2c_imx_stop(i2c_imx);
>  
> +out:
> + pm_runtime_mark_last_busy(i2c_imx->adapter.dev.parent);
> + pm_runtime_put_autosuspend(i2c_imx->adapter.dev.parent);
> +
>   dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__,
>   (result < 0) ? "error" : "success msg",
>   (result < 0) ? result : num);
> @@ -1020,9 +1027,10 @@ static int i2c_imx_probe(struct platform_device *pdev)
>  
>   ret = clk_prepare_enable(i2c_imx->clk);
>   if (ret) {
> - dev_err(&pdev->dev, "can't enable I2C clock\n");
> + dev_err(&pdev->dev, "can't enable I2C clock, ret=%d\n", ret);
>   return ret;
>   }
> +
>   /* Request IRQ */
>   ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0,
>   pdev->name, i2c_imx);
> @@ -1037,6 +1045,18 @@ static int i2c_imx_probe(struct platform_device *pdev)
>   /* Set up adapter data */
>   i2c_set_adapdata(&i2c_imx->adapter, i2c_imx);
>  
> + /* Set up platform driver data */
> + platform_set_drvdata(pdev, i2c_imx);
> +
> + pm_runtime_set_autosuspend_delay(&pdev->dev, I2C_PM_TIMEOUT)