Skip to content

Commit

Permalink
i2c: rcar: disable PM in multi-master mode
Browse files Browse the repository at this point in the history
In multi master mode, the IP core needs to be always active for
arbitration reasons. Get the config from DT and set up PM depending on
the config.

Acked-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
  • Loading branch information
Wolfram Sang authored and Wolfram Sang committed Jan 2, 2016
1 parent 42c0783 commit 7ee24eb
Showing 1 changed file with 14 additions and 3 deletions.
17 changes: 14 additions & 3 deletions drivers/i2c/busses/i2c-rcar.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@
#define ID_DONE (1 << 2)
#define ID_ARBLOST (1 << 3)
#define ID_NACK (1 << 4)
/* persistent flags */
#define ID_P_PM_BLOCKED (1 << 31)
#define ID_P_MASK ID_P_PM_BLOCKED

enum rcar_i2c_type {
I2C_RCAR_GEN1,
Expand Down Expand Up @@ -277,7 +280,7 @@ static void rcar_i2c_next_msg(struct rcar_i2c_priv *priv)
{
priv->msg++;
priv->msgs_left--;
priv->flags = 0;
priv->flags &= ID_P_MASK;
rcar_i2c_prepare_msg(priv);
}

Expand Down Expand Up @@ -495,7 +498,7 @@ static int rcar_i2c_master_xfer(struct i2c_adapter *adap,
/* init first message */
priv->msg = msgs;
priv->msgs_left = num;
priv->flags = ID_FIRST_MSG;
priv->flags = (priv->flags & ID_P_MASK) | ID_FIRST_MSG;
rcar_i2c_prepare_msg(priv);

time_left = wait_event_timeout(priv->wait, priv->flags & ID_DONE,
Expand Down Expand Up @@ -630,7 +633,13 @@ static int rcar_i2c_probe(struct platform_device *pdev)
goto out_pm_put;

rcar_i2c_init(priv);
pm_runtime_put(dev);

/* Don't suspend when multi-master to keep arbitration working */
if (of_property_read_bool(dev->of_node, "multi-master"))
priv->flags |= ID_P_PM_BLOCKED;
else
pm_runtime_put(dev);


irq = platform_get_irq(pdev, 0);
ret = devm_request_irq(dev, irq, rcar_i2c_irq, 0, dev_name(dev), priv);
Expand Down Expand Up @@ -664,6 +673,8 @@ static int rcar_i2c_remove(struct platform_device *pdev)
struct device *dev = &pdev->dev;

i2c_del_adapter(&priv->adap);
if (priv->flags & ID_P_PM_BLOCKED)
pm_runtime_put(dev);
pm_runtime_disable(dev);

return 0;
Expand Down

0 comments on commit 7ee24eb

Please sign in to comment.