diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-qcom-geni.c')
-rw-r--r-- | drivers/i2c/busses/i2c-qcom-geni.c | 36 |
1 files changed, 31 insertions, 5 deletions
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index c7f6c6b00d1b..3050db563ab3 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -116,6 +116,7 @@ struct geni_i2c_dev { struct msm_gpi_dma_async_tx_cb_param tx_cb; struct msm_gpi_dma_async_tx_cb_param rx_cb; enum i2c_se_mode se_mode; + bool autosuspend_disable; }; struct geni_i2c_err_log { @@ -600,6 +601,7 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, { struct geni_i2c_dev *gi2c = i2c_get_adapdata(adap); int i, ret = 0, timeout = 0; + int ref = 0; gi2c->err = 0; gi2c->cur = &msgs[0]; @@ -613,6 +615,12 @@ static int geni_i2c_xfer(struct i2c_adapter *adap, pm_runtime_set_suspended(gi2c->dev); return ret; } + ref = atomic_read(&gi2c->dev->power.usage_count); + if (ref <= 0) { + GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, + "resume usage count mismatch:%d\n", ref); + } + if (gi2c->se_mode == GSI_ONLY) { ret = geni_i2c_gsi_xfer(adap, msgs, num); goto geni_i2c_txn_ret; @@ -716,8 +724,17 @@ geni_i2c_txn_ret: if (ret == 0) ret = num; - pm_runtime_mark_last_busy(gi2c->dev); - pm_runtime_put_autosuspend(gi2c->dev); + if (gi2c->autosuspend_disable) { + pm_runtime_put_sync(gi2c->dev); + ref = atomic_read(&gi2c->dev->power.usage_count); + if (ref < 0) + GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, + "suspend usage count mismatch:%d\n", ref); + } else { + pm_runtime_mark_last_busy(gi2c->dev); + pm_runtime_put_autosuspend(gi2c->dev); + } + gi2c->cur = NULL; gi2c->err = 0; dev_dbg(gi2c->dev, "i2c txn ret:%d\n", ret); @@ -830,6 +847,9 @@ static int geni_i2c_probe(struct platform_device *pdev) gi2c->i2c_rsc.clk_freq_out = KHz(400); } + gi2c->autosuspend_disable = of_property_read_bool(pdev->dev.of_node, + "qcom,disable-autosuspend"); + gi2c->irq = platform_get_irq(pdev, 0); if (gi2c->irq < 0) { dev_err(gi2c->dev, "IRQ error for i2c-geni\n"); @@ -861,8 +881,11 @@ static int geni_i2c_probe(struct platform_device *pdev) strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name)); pm_runtime_set_suspended(gi2c->dev); - pm_runtime_set_autosuspend_delay(gi2c->dev, I2C_AUTO_SUSPEND_DELAY); - pm_runtime_use_autosuspend(gi2c->dev); + if (!gi2c->autosuspend_disable) { + pm_runtime_set_autosuspend_delay(gi2c->dev, + I2C_AUTO_SUSPEND_DELAY); + pm_runtime_use_autosuspend(gi2c->dev); + } pm_runtime_enable(gi2c->dev); i2c_add_adapter(&gi2c->adap); @@ -950,6 +973,9 @@ static int geni_i2c_runtime_resume(struct device *dev) "i2c fifo/se-dma mode. fifo depth:%d\n", gi2c_tx_depth); } + if (gi2c->autosuspend_disable) + GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, + "i2c in autosuspend disable mode\n"); } if (gi2c->se_mode == FIFO_SE_DMA) enable_irq(gi2c->irq); |