Skip to content

Commit 76c35d0

Browse files
BoughChengregkh
authored andcommitted
spi: spi-nxp-fspi: enable runtime pm for fspi
[ Upstream commit 97be4b9 ] Enable the runtime PM in fspi driver. Also for system PM, On some board like i.MX8ULP-EVK board, after system suspend, IOMUX module will lost power, so all the pinctrl setting will lost when system resume back, need driver to save/restore the pinctrl setting. Signed-off-by: Han Xu <han.xu@nxp.com> Signed-off-by: Haibo Chen <haibo.chen@nxp.com> Link: https://patch.msgid.link/20250428-flexspipatch-v3-2-61d5e8f591bc@nxp.com Signed-off-by: Mark Brown <broonie@kernel.org> Stable-dep-of: 68c8c93 ("spi: nxp-fspi: Use reinit_completion() for repeated operations") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 9419838 commit 76c35d0

1 file changed

Lines changed: 76 additions & 17 deletions

File tree

drivers/spi/spi-nxp-fspi.c

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#include <linux/mutex.h>
4949
#include <linux/of.h>
5050
#include <linux/platform_device.h>
51+
#include <linux/pinctrl/consumer.h>
52+
#include <linux/pm_runtime.h>
5153
#include <linux/pm_qos.h>
5254
#include <linux/regmap.h>
5355
#include <linux/sizes.h>
@@ -57,6 +59,9 @@
5759
#include <linux/spi/spi.h>
5860
#include <linux/spi/spi-mem.h>
5961

62+
/* runtime pm timeout */
63+
#define FSPI_RPM_TIMEOUT 50 /* 50ms */
64+
6065
/* Registers used by the driver */
6166
#define FSPI_MCR0 0x00
6267
#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24)
@@ -396,6 +401,8 @@ struct nxp_fspi {
396401
struct mutex lock;
397402
struct pm_qos_request pm_qos_req;
398403
int selected;
404+
#define FSPI_NEED_INIT (1 << 0)
405+
int flags;
399406
};
400407

401408
static inline int needs_ip_only(struct nxp_fspi *f)
@@ -935,6 +942,13 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
935942

936943
mutex_lock(&f->lock);
937944

945+
err = pm_runtime_get_sync(f->dev);
946+
if (err < 0) {
947+
mutex_unlock(&f->lock);
948+
dev_err(f->dev, "Failed to enable clock %d\n", __LINE__);
949+
return err;
950+
}
951+
938952
/* Wait for controller being ready. */
939953
err = fspi_readl_poll_tout(f, f->iobase + FSPI_STS0,
940954
FSPI_STS0_ARB_IDLE, 1, POLL_TOUT, true);
@@ -963,8 +977,10 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
963977
/* Invalidate the data in the AHB buffer. */
964978
nxp_fspi_invalid(f);
965979

966-
mutex_unlock(&f->lock);
980+
pm_runtime_mark_last_busy(f->dev);
981+
pm_runtime_put_autosuspend(f->dev);
967982

983+
mutex_unlock(&f->lock);
968984
return err;
969985
}
970986

@@ -1231,9 +1247,14 @@ static int nxp_fspi_probe(struct platform_device *pdev)
12311247
if (irq < 0)
12321248
return dev_err_probe(dev, irq, "Failed to get irq source");
12331249

1234-
ret = nxp_fspi_clk_prep_enable(f);
1235-
if (ret)
1236-
return dev_err_probe(dev, ret, "Can't enable the clock\n");
1250+
pm_runtime_enable(dev);
1251+
pm_runtime_set_autosuspend_delay(dev, FSPI_RPM_TIMEOUT);
1252+
pm_runtime_use_autosuspend(dev);
1253+
1254+
/* enable clock */
1255+
ret = pm_runtime_get_sync(f->dev);
1256+
if (ret < 0)
1257+
return dev_err_probe(dev, ret, "Failed to enable clock");
12371258

12381259
/* Clear potential interrupts */
12391260
reg = fspi_readl(f, f->iobase + FSPI_INTR);
@@ -1242,12 +1263,14 @@ static int nxp_fspi_probe(struct platform_device *pdev)
12421263

12431264
nxp_fspi_default_setup(f);
12441265

1266+
ret = pm_runtime_put_sync(dev);
1267+
if (ret < 0)
1268+
return dev_err_probe(dev, ret, "Failed to disable clock");
1269+
12451270
ret = devm_request_irq(dev, irq,
12461271
nxp_fspi_irq_handler, 0, pdev->name, f);
1247-
if (ret) {
1248-
nxp_fspi_clk_disable_unprep(f);
1272+
if (ret)
12491273
return dev_err_probe(dev, ret, "Failed to request irq\n");
1250-
}
12511274

12521275
ret = devm_mutex_init(dev, &f->lock);
12531276
if (ret)
@@ -1271,29 +1294,70 @@ static void nxp_fspi_remove(struct platform_device *pdev)
12711294
{
12721295
struct nxp_fspi *f = platform_get_drvdata(pdev);
12731296

1297+
/* enable clock first since there is reigster access */
1298+
pm_runtime_get_sync(f->dev);
1299+
12741300
/* disable the hardware */
12751301
fspi_writel(f, FSPI_MCR0_MDIS, f->iobase + FSPI_MCR0);
12761302

1303+
pm_runtime_disable(f->dev);
1304+
pm_runtime_put_noidle(f->dev);
12771305
nxp_fspi_clk_disable_unprep(f);
12781306

12791307
if (f->ahb_addr)
12801308
iounmap(f->ahb_addr);
12811309
}
12821310

1283-
static int nxp_fspi_suspend(struct device *dev)
1311+
static int nxp_fspi_runtime_suspend(struct device *dev)
12841312
{
1313+
struct nxp_fspi *f = dev_get_drvdata(dev);
1314+
1315+
nxp_fspi_clk_disable_unprep(f);
1316+
12851317
return 0;
12861318
}
12871319

1288-
static int nxp_fspi_resume(struct device *dev)
1320+
static int nxp_fspi_runtime_resume(struct device *dev)
12891321
{
12901322
struct nxp_fspi *f = dev_get_drvdata(dev);
1323+
int ret;
12911324

1292-
nxp_fspi_default_setup(f);
1325+
ret = nxp_fspi_clk_prep_enable(f);
1326+
if (ret)
1327+
return ret;
12931328

1294-
return 0;
1329+
if (f->flags & FSPI_NEED_INIT) {
1330+
nxp_fspi_default_setup(f);
1331+
ret = pinctrl_pm_select_default_state(dev);
1332+
if (ret)
1333+
dev_err(dev, "select flexspi default pinctrl failed!\n");
1334+
f->flags &= ~FSPI_NEED_INIT;
1335+
}
1336+
1337+
return ret;
12951338
}
12961339

1340+
static int nxp_fspi_suspend(struct device *dev)
1341+
{
1342+
struct nxp_fspi *f = dev_get_drvdata(dev);
1343+
int ret;
1344+
1345+
ret = pinctrl_pm_select_sleep_state(dev);
1346+
if (ret) {
1347+
dev_err(dev, "select flexspi sleep pinctrl failed!\n");
1348+
return ret;
1349+
}
1350+
1351+
f->flags |= FSPI_NEED_INIT;
1352+
1353+
return pm_runtime_force_suspend(dev);
1354+
}
1355+
1356+
static const struct dev_pm_ops nxp_fspi_pm_ops = {
1357+
RUNTIME_PM_OPS(nxp_fspi_runtime_suspend, nxp_fspi_runtime_resume, NULL)
1358+
SYSTEM_SLEEP_PM_OPS(nxp_fspi_suspend, pm_runtime_force_resume)
1359+
};
1360+
12971361
static const struct of_device_id nxp_fspi_dt_ids[] = {
12981362
{ .compatible = "nxp,lx2160a-fspi", .data = (void *)&lx2160a_data, },
12991363
{ .compatible = "nxp,imx8mm-fspi", .data = (void *)&imx8mm_data, },
@@ -1313,17 +1377,12 @@ static const struct acpi_device_id nxp_fspi_acpi_ids[] = {
13131377
MODULE_DEVICE_TABLE(acpi, nxp_fspi_acpi_ids);
13141378
#endif
13151379

1316-
static const struct dev_pm_ops nxp_fspi_pm_ops = {
1317-
.suspend = nxp_fspi_suspend,
1318-
.resume = nxp_fspi_resume,
1319-
};
1320-
13211380
static struct platform_driver nxp_fspi_driver = {
13221381
.driver = {
13231382
.name = "nxp-fspi",
13241383
.of_match_table = nxp_fspi_dt_ids,
13251384
.acpi_match_table = ACPI_PTR(nxp_fspi_acpi_ids),
1326-
.pm = &nxp_fspi_pm_ops,
1385+
.pm = pm_ptr(&nxp_fspi_pm_ops),
13271386
},
13281387
.probe = nxp_fspi_probe,
13291388
.remove_new = nxp_fspi_remove,

0 commit comments

Comments
 (0)