summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/spi/spi-fsl-espi.c
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/spi/spi-fsl-espi.c
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/spi/spi-fsl-espi.c')
-rw-r--r--kernel/drivers/spi/spi-fsl-espi.c95
1 files changed, 60 insertions, 35 deletions
diff --git a/kernel/drivers/spi/spi-fsl-espi.c b/kernel/drivers/spi/spi-fsl-espi.c
index 80d245ac8..c27124a5e 100644
--- a/kernel/drivers/spi/spi-fsl-espi.c
+++ b/kernel/drivers/spi/spi-fsl-espi.c
@@ -21,6 +21,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
+#include <linux/pm_runtime.h>
#include <sysdev/fsl_soc.h>
#include "spi-fsl-lib.h"
@@ -85,6 +86,8 @@ struct fsl_espi_transfer {
#define SPCOM_TRANLEN(x) ((x) << 0)
#define SPCOM_TRANLEN_MAX 0xFFFF /* Max transaction length */
+#define AUTOSUSPEND_TIMEOUT 2000
+
static void fsl_espi_change_mode(struct spi_device *spi)
{
struct mpc8xxx_spi *mspi = spi_master_get_devdata(spi->master);
@@ -485,6 +488,8 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi = spi_master_get_devdata(spi->master);
reg_base = mpc8xxx_spi->reg_base;
+ pm_runtime_get_sync(mpc8xxx_spi->dev);
+
hw_mode = cs->hw_mode; /* Save original settings */
cs->hw_mode = mpc8xxx_spi_read_reg(
&reg_base->csmode[spi->chip_select]);
@@ -507,6 +512,10 @@ static int fsl_espi_setup(struct spi_device *spi)
mpc8xxx_spi_write_reg(&reg_base->mode, loop_mode);
retval = fsl_espi_setup_transfer(spi, NULL);
+
+ pm_runtime_mark_last_busy(mpc8xxx_spi->dev);
+ pm_runtime_put_autosuspend(mpc8xxx_spi->dev);
+
if (retval < 0) {
cs->hw_mode = hw_mode; /* Restore settings */
return retval;
@@ -561,9 +570,13 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
/* spin until TX is done */
ret = spin_event_timeout(((events = mpc8xxx_spi_read_reg(
- &reg_base->event)) & SPIE_NF) == 0, 1000, 0);
+ &reg_base->event)) & SPIE_NF), 1000, 0);
if (!ret) {
dev_err(mspi->dev, "tired waiting for SPIE_NF\n");
+
+ /* Clear the SPIE bits */
+ mpc8xxx_spi_write_reg(&reg_base->event, events);
+ complete(&mspi->done);
return;
}
}
@@ -600,20 +613,14 @@ static irqreturn_t fsl_espi_irq(s32 irq, void *context_data)
return ret;
}
-static void fsl_espi_remove(struct mpc8xxx_spi *mspi)
+#ifdef CONFIG_PM
+static int fsl_espi_runtime_suspend(struct device *dev)
{
- iounmap(mspi->reg_base);
-}
-
-static int fsl_espi_suspend(struct spi_master *master)
-{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+ struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;
- mpc8xxx_spi = spi_master_get_devdata(master);
- reg_base = mpc8xxx_spi->reg_base;
-
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval &= ~SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
@@ -621,21 +628,20 @@ static int fsl_espi_suspend(struct spi_master *master)
return 0;
}
-static int fsl_espi_resume(struct spi_master *master)
+static int fsl_espi_runtime_resume(struct device *dev)
{
- struct mpc8xxx_spi *mpc8xxx_spi;
- struct fsl_espi_reg *reg_base;
+ struct spi_master *master = dev_get_drvdata(dev);
+ struct mpc8xxx_spi *mpc8xxx_spi = spi_master_get_devdata(master);
+ struct fsl_espi_reg *reg_base = mpc8xxx_spi->reg_base;
u32 regval;
- mpc8xxx_spi = spi_master_get_devdata(master);
- reg_base = mpc8xxx_spi->reg_base;
-
regval = mpc8xxx_spi_read_reg(&reg_base->mode);
regval |= SPMODE_ENABLE;
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
return 0;
}
+#endif
static struct spi_master * fsl_espi_probe(struct device *dev,
struct resource *mem, unsigned int irq)
@@ -663,25 +669,23 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
master->setup = fsl_espi_setup;
master->cleanup = fsl_espi_cleanup;
master->transfer_one_message = fsl_espi_do_one_msg;
- master->prepare_transfer_hardware = fsl_espi_resume;
- master->unprepare_transfer_hardware = fsl_espi_suspend;
+ master->auto_runtime_pm = true;
mpc8xxx_spi = spi_master_get_devdata(master);
- mpc8xxx_spi->spi_remove = fsl_espi_remove;
- mpc8xxx_spi->reg_base = ioremap(mem->start, resource_size(mem));
- if (!mpc8xxx_spi->reg_base) {
- ret = -ENOMEM;
+ mpc8xxx_spi->reg_base = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(mpc8xxx_spi->reg_base)) {
+ ret = PTR_ERR(mpc8xxx_spi->reg_base);
goto err_probe;
}
reg_base = mpc8xxx_spi->reg_base;
/* Register for SPI Interrupt */
- ret = request_irq(mpc8xxx_spi->irq, fsl_espi_irq,
+ ret = devm_request_irq(dev, mpc8xxx_spi->irq, fsl_espi_irq,
0, "fsl_espi", mpc8xxx_spi);
if (ret)
- goto free_irq;
+ goto err_probe;
if (mpc8xxx_spi->flags & SPI_QE_CPU_MODE) {
mpc8xxx_spi->rx_shift = 16;
@@ -727,18 +731,27 @@ static struct spi_master * fsl_espi_probe(struct device *dev,
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
- ret = spi_register_master(master);
+ pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_TIMEOUT);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);
+ pm_runtime_get_sync(dev);
+
+ ret = devm_spi_register_master(dev, master);
if (ret < 0)
- goto unreg_master;
+ goto err_pm;
dev_info(dev, "at 0x%p (irq = %d)\n", reg_base, mpc8xxx_spi->irq);
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
return master;
-unreg_master:
- free_irq(mpc8xxx_spi->irq, mpc8xxx_spi);
-free_irq:
- iounmap(mpc8xxx_spi->reg_base);
+err_pm:
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
err_probe:
spi_master_put(master);
err:
@@ -805,7 +818,9 @@ err:
static int of_fsl_espi_remove(struct platform_device *dev)
{
- return mpc8xxx_spi_remove(&dev->dev);
+ pm_runtime_disable(&dev->dev);
+
+ return 0;
}
#ifdef CONFIG_PM_SLEEP
@@ -820,7 +835,11 @@ static int of_fsl_espi_suspend(struct device *dev)
return ret;
}
- return fsl_espi_suspend(master);
+ ret = pm_runtime_force_suspend(dev);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int of_fsl_espi_resume(struct device *dev)
@@ -830,7 +849,7 @@ static int of_fsl_espi_resume(struct device *dev)
struct mpc8xxx_spi *mpc8xxx_spi;
struct fsl_espi_reg *reg_base;
u32 regval;
- int i;
+ int i, ret;
mpc8xxx_spi = spi_master_get_devdata(master);
reg_base = mpc8xxx_spi->reg_base;
@@ -850,11 +869,17 @@ static int of_fsl_espi_resume(struct device *dev)
mpc8xxx_spi_write_reg(&reg_base->mode, regval);
+ ret = pm_runtime_force_resume(dev);
+ if (ret < 0)
+ return ret;
+
return spi_master_resume(master);
}
#endif /* CONFIG_PM_SLEEP */
static const struct dev_pm_ops espi_pm = {
+ SET_RUNTIME_PM_OPS(fsl_espi_runtime_suspend,
+ fsl_espi_runtime_resume, NULL)
SET_SYSTEM_SLEEP_PM_OPS(of_fsl_espi_suspend, of_fsl_espi_resume)
};