Merge "spi-geni-qcom: Support to disable runtime PM autosuspend" into msm-4.9
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
index 866d004..8b6d5a2 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
@@ -28,6 +28,7 @@
Optional properties:
- qcom,rt: Specifies if the framework worker thread for this
controller device should have "real-time" priority.
+- qcom,disable-autosuspend: Specifies to disable runtime PM auto suspend.
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 880fda4..1663d3b 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -155,6 +155,7 @@
int num_xfers;
void *ipc;
bool shared_se;
+ bool dis_autosuspend;
};
static struct spi_master *get_spi_master(struct device *dev)
@@ -747,7 +748,7 @@
static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
- int ret = 0;
+ int ret = 0, count = 0;
u32 max_speed = spi->cur_msg->spi->max_speed_hz;
struct se_geni_rsc *rsc = &mas->spi_rsc;
@@ -774,7 +775,12 @@
} else {
ret = 0;
}
-
+ if (mas->dis_autosuspend) {
+ count = atomic_read(&mas->dev->power.usage_count);
+ if (count <= 0)
+ GENI_SE_ERR(mas->ipc, false, NULL,
+ "resume usage count mismatch:%d", count);
+ }
if (unlikely(!mas->setup)) {
int proto = get_se_proto(mas->base);
unsigned int major;
@@ -863,6 +869,9 @@
mas->shared_se =
(geni_read_reg(mas->base, GENI_IF_FIFO_DISABLE_RO) &
FIFO_IF_DISABLE);
+ if (mas->dis_autosuspend)
+ GENI_SE_DBG(mas->ipc, false, mas->dev,
+ "Auto Suspend is disabled\n");
}
exit_prepare_transfer_hardware:
return ret;
@@ -871,7 +880,7 @@
static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
{
struct spi_geni_master *mas = spi_master_get_devdata(spi);
-
+ int count = 0;
if (mas->shared_se) {
struct se_geni_rsc *rsc;
int ret = 0;
@@ -884,8 +893,16 @@
"%s: Error %d pinctrl_select_state\n", __func__, ret);
}
- pm_runtime_mark_last_busy(mas->dev);
- pm_runtime_put_autosuspend(mas->dev);
+ if (mas->dis_autosuspend) {
+ pm_runtime_put_sync(mas->dev);
+ count = atomic_read(&mas->dev->power.usage_count);
+ if (count < 0)
+ GENI_SE_ERR(mas->ipc, false, NULL,
+ "suspend usage count mismatch:%d", count);
+ } else {
+ pm_runtime_mark_last_busy(mas->dev);
+ pm_runtime_put_autosuspend(mas->dev);
+ }
return 0;
}
@@ -1411,7 +1428,9 @@
rt_pri = of_property_read_bool(pdev->dev.of_node, "qcom,rt");
if (rt_pri)
spi->rt = true;
-
+ geni_mas->dis_autosuspend =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,disable-autosuspend");
geni_mas->phys_addr = res->start;
geni_mas->size = resource_size(res);
geni_mas->base = devm_ioremap(&pdev->dev, res->start,
@@ -1451,8 +1470,11 @@
init_completion(&geni_mas->tx_cb);
init_completion(&geni_mas->rx_cb);
pm_runtime_set_suspended(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTO_SUSPEND_DELAY);
- pm_runtime_use_autosuspend(&pdev->dev);
+ if (!geni_mas->dis_autosuspend) {
+ pm_runtime_set_autosuspend_delay(&pdev->dev,
+ SPI_AUTO_SUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ }
pm_runtime_enable(&pdev->dev);
ret = spi_register_master(spi);
if (ret) {