MLK-23644: spi: spi-nxp-fspi: enable runtime pm for fspi
enable the runtime PM in fspi driver. Reading the power mode from the debug monitor, FSPI_0 was on and with the patch it is lp. Signed-off-by: Han Xu <han.xu@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
a31a61aa1d
commit
2c4cf9ce2f
|
@ -52,6 +52,11 @@
|
|||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/spi-mem.h>
|
||||
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
/* runtime pm timeout */
|
||||
#define FSPI_RPM_TIMEOUT 50 /* 50ms */
|
||||
|
||||
/*
|
||||
* The driver only uses one single LUT entry, that is updated on
|
||||
* each call of exec_op(). Index 0 is preset at boot with a basic
|
||||
|
@ -355,6 +360,8 @@ struct nxp_fspi {
|
|||
struct mutex lock;
|
||||
struct pm_qos_request pm_qos_req;
|
||||
int selected;
|
||||
#define FSPI_INITILIZED (1 << 0)
|
||||
int flags;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -833,6 +840,12 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
|
||||
mutex_lock(&f->lock);
|
||||
|
||||
err = pm_runtime_get_sync(f->dev);
|
||||
if (err < 0) {
|
||||
dev_err(f->dev, "Failed to enable clock %d\n", __LINE__);
|
||||
goto err_mutex;
|
||||
}
|
||||
|
||||
/* Wait for controller being ready. */
|
||||
err = fspi_readl_poll_tout(f, f->iobase + FSPI_STS0,
|
||||
FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true);
|
||||
|
@ -859,8 +872,13 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
|
|||
/* Invalidate the data in the AHB buffer. */
|
||||
nxp_fspi_invalid(f);
|
||||
|
||||
pm_runtime_mark_last_busy(f->dev);
|
||||
pm_runtime_put_autosuspend(f->dev);
|
||||
|
||||
mutex_unlock(&f->lock);
|
||||
|
||||
err_mutex:
|
||||
mutex_unlock(&f->lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1041,9 +1059,14 @@ static int nxp_fspi_probe(struct platform_device *pdev)
|
|||
goto err_put_ctrl;
|
||||
}
|
||||
|
||||
ret = nxp_fspi_clk_prep_enable(f);
|
||||
if (ret) {
|
||||
dev_err(dev, "can not enable the clock\n");
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_set_autosuspend_delay(dev, FSPI_RPM_TIMEOUT);
|
||||
pm_runtime_use_autosuspend(dev);
|
||||
|
||||
/* enable clock */
|
||||
ret = pm_runtime_get_sync(f->dev);
|
||||
if (ret < 0) {
|
||||
dev_err(f->dev, "Failed to enable clock %d\n", __LINE__);
|
||||
goto err_put_ctrl;
|
||||
}
|
||||
|
||||
|
@ -1073,13 +1096,19 @@ static int nxp_fspi_probe(struct platform_device *pdev)
|
|||
if (ret)
|
||||
goto err_destroy_mutex;
|
||||
|
||||
pm_runtime_mark_last_busy(f->dev);
|
||||
pm_runtime_put_autosuspend(f->dev);
|
||||
|
||||
/* indicate the controller has been initialized */
|
||||
f->flags |= FSPI_INITILIZED;
|
||||
|
||||
return 0;
|
||||
|
||||
err_destroy_mutex:
|
||||
mutex_destroy(&f->lock);
|
||||
|
||||
err_disable_clk:
|
||||
nxp_fspi_clk_disable_unprep(f);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
err_put_ctrl:
|
||||
spi_controller_put(ctlr);
|
||||
|
@ -1105,20 +1134,50 @@ static int nxp_fspi_remove(struct platform_device *pdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int nxp_fspi_suspend(struct device *dev)
|
||||
#ifdef CONFIG_PM
|
||||
static int nxp_fspi_initialized(struct nxp_fspi *f)
|
||||
{
|
||||
return 0;
|
||||
return f->flags & FSPI_INITILIZED;
|
||||
}
|
||||
|
||||
static int nxp_fspi_resume(struct device *dev)
|
||||
static int nxp_fspi_need_reinit(struct nxp_fspi *f)
|
||||
{
|
||||
/* we always use the controller in combination mode, so we check this */
|
||||
/* register bit to determine if the controller once lost power, such as */
|
||||
/* suspend/resume, and need to be re-init */
|
||||
|
||||
return !(readl(f->iobase + FSPI_MCR0) & FSPI_MCR0_OCTCOMB_EN);
|
||||
}
|
||||
|
||||
|
||||
int nxp_fspi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct nxp_fspi *f = dev_get_drvdata(dev);
|
||||
|
||||
nxp_fspi_default_setup(f);
|
||||
nxp_fspi_clk_disable_unprep(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nxp_fspi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct nxp_fspi *f = dev_get_drvdata(dev);
|
||||
|
||||
nxp_fspi_clk_prep_enable(f);
|
||||
|
||||
if (nxp_fspi_initialized(f) && nxp_fspi_need_reinit(f))
|
||||
nxp_fspi_default_setup(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops nxp_fspi_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(nxp_fspi_runtime_suspend, nxp_fspi_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
||||
};
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
static const struct of_device_id nxp_fspi_dt_ids[] = {
|
||||
{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
|
||||
{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
|
||||
|
@ -1127,11 +1186,6 @@ static const struct of_device_id nxp_fspi_dt_ids[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, nxp_fspi_dt_ids);
|
||||
|
||||
static const struct dev_pm_ops nxp_fspi_pm_ops = {
|
||||
.suspend = nxp_fspi_suspend,
|
||||
.resume = nxp_fspi_resume,
|
||||
};
|
||||
|
||||
static struct platform_driver nxp_fspi_driver = {
|
||||
.driver = {
|
||||
.name = "nxp-fspi",
|
||||
|
|
Loading…
Reference in New Issue