48
48
#include <linux/mutex.h>
49
49
#include <linux/of.h>
50
50
#include <linux/platform_device.h>
51
+ #include <linux/pinctrl/consumer.h>
52
+ #include <linux/pm_runtime.h>
51
53
#include <linux/pm_qos.h>
52
54
#include <linux/regmap.h>
53
55
#include <linux/sizes.h>
57
59
#include <linux/spi/spi.h>
58
60
#include <linux/spi/spi-mem.h>
59
61
62
+ /* runtime pm timeout */
63
+ #define FSPI_RPM_TIMEOUT 50 /* 50ms */
64
+
60
65
/* Registers used by the driver */
61
66
#define FSPI_MCR0 0x00
62
67
#define FSPI_MCR0_AHB_TIMEOUT (x ) ((x) << 24)
@@ -394,6 +399,8 @@ struct nxp_fspi {
394
399
struct mutex lock ;
395
400
struct pm_qos_request pm_qos_req ;
396
401
int selected ;
402
+ #define FSPI_NEED_INIT (1 << 0)
403
+ int flags ;
397
404
};
398
405
399
406
static inline int needs_ip_only (struct nxp_fspi * f )
@@ -927,6 +934,13 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
927
934
928
935
mutex_lock (& f -> lock );
929
936
937
+ err = pm_runtime_get_sync (f -> dev );
938
+ if (err < 0 ) {
939
+ mutex_unlock (& f -> lock );
940
+ dev_err (f -> dev , "Failed to enable clock %d\n" , __LINE__ );
941
+ return err ;
942
+ }
943
+
930
944
/* Wait for controller being ready. */
931
945
err = fspi_readl_poll_tout (f , f -> iobase + FSPI_STS0 ,
932
946
FSPI_STS0_ARB_IDLE , 1 , POLL_TOUT , true);
@@ -955,8 +969,10 @@ static int nxp_fspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
955
969
/* Invalidate the data in the AHB buffer. */
956
970
nxp_fspi_invalid (f );
957
971
958
- mutex_unlock (& f -> lock );
972
+ pm_runtime_mark_last_busy (f -> dev );
973
+ pm_runtime_put_autosuspend (f -> dev );
959
974
975
+ mutex_unlock (& f -> lock );
960
976
return err ;
961
977
}
962
978
@@ -1216,9 +1232,14 @@ static int nxp_fspi_probe(struct platform_device *pdev)
1216
1232
if (irq < 0 )
1217
1233
return dev_err_probe (dev , irq , "Failed to get irq source" );
1218
1234
1219
- ret = nxp_fspi_clk_prep_enable (f );
1220
- if (ret )
1221
- return dev_err_probe (dev , ret , "Can't enable the clock\n" );
1235
+ pm_runtime_enable (dev );
1236
+ pm_runtime_set_autosuspend_delay (dev , FSPI_RPM_TIMEOUT );
1237
+ pm_runtime_use_autosuspend (dev );
1238
+
1239
+ /* enable clock */
1240
+ ret = pm_runtime_get_sync (f -> dev );
1241
+ if (ret < 0 )
1242
+ return dev_err_probe (dev , ret , "Failed to enable clock" );
1222
1243
1223
1244
/* Clear potential interrupts */
1224
1245
reg = fspi_readl (f , f -> iobase + FSPI_INTR );
@@ -1227,12 +1248,14 @@ static int nxp_fspi_probe(struct platform_device *pdev)
1227
1248
1228
1249
nxp_fspi_default_setup (f );
1229
1250
1251
+ ret = pm_runtime_put_sync (dev );
1252
+ if (ret < 0 )
1253
+ return dev_err_probe (dev , ret , "Failed to disable clock" );
1254
+
1230
1255
ret = devm_request_irq (dev , irq ,
1231
1256
nxp_fspi_irq_handler , 0 , pdev -> name , f );
1232
- if (ret ) {
1233
- nxp_fspi_clk_disable_unprep (f );
1257
+ if (ret )
1234
1258
return dev_err_probe (dev , ret , "Failed to request irq\n" );
1235
- }
1236
1259
1237
1260
devm_mutex_init (dev , & f -> lock );
1238
1261
@@ -1249,29 +1272,70 @@ static void nxp_fspi_remove(struct platform_device *pdev)
1249
1272
{
1250
1273
struct nxp_fspi * f = platform_get_drvdata (pdev );
1251
1274
1275
+ /* enable clock first since there is reigster access */
1276
+ pm_runtime_get_sync (f -> dev );
1277
+
1252
1278
/* disable the hardware */
1253
1279
fspi_writel (f , FSPI_MCR0_MDIS , f -> iobase + FSPI_MCR0 );
1254
1280
1281
+ pm_runtime_disable (f -> dev );
1282
+ pm_runtime_put_noidle (f -> dev );
1255
1283
nxp_fspi_clk_disable_unprep (f );
1256
1284
1257
1285
if (f -> ahb_addr )
1258
1286
iounmap (f -> ahb_addr );
1259
1287
}
1260
1288
1261
- static int nxp_fspi_suspend (struct device * dev )
1289
+ static int nxp_fspi_runtime_suspend (struct device * dev )
1262
1290
{
1291
+ struct nxp_fspi * f = dev_get_drvdata (dev );
1292
+
1293
+ nxp_fspi_clk_disable_unprep (f );
1294
+
1263
1295
return 0 ;
1264
1296
}
1265
1297
1266
- static int nxp_fspi_resume (struct device * dev )
1298
+ static int nxp_fspi_runtime_resume (struct device * dev )
1267
1299
{
1268
1300
struct nxp_fspi * f = dev_get_drvdata (dev );
1301
+ int ret ;
1269
1302
1270
- nxp_fspi_default_setup (f );
1303
+ ret = nxp_fspi_clk_prep_enable (f );
1304
+ if (ret )
1305
+ return ret ;
1271
1306
1272
- return 0 ;
1307
+ if (f -> flags & FSPI_NEED_INIT ) {
1308
+ nxp_fspi_default_setup (f );
1309
+ ret = pinctrl_pm_select_default_state (dev );
1310
+ if (ret )
1311
+ dev_err (dev , "select flexspi default pinctrl failed!\n" );
1312
+ f -> flags &= ~FSPI_NEED_INIT ;
1313
+ }
1314
+
1315
+ return ret ;
1273
1316
}
1274
1317
1318
+ static int nxp_fspi_suspend (struct device * dev )
1319
+ {
1320
+ struct nxp_fspi * f = dev_get_drvdata (dev );
1321
+ int ret ;
1322
+
1323
+ ret = pinctrl_pm_select_sleep_state (dev );
1324
+ if (ret ) {
1325
+ dev_err (dev , "select flexspi sleep pinctrl failed!\n" );
1326
+ return ret ;
1327
+ }
1328
+
1329
+ f -> flags |= FSPI_NEED_INIT ;
1330
+
1331
+ return pm_runtime_force_suspend (dev );
1332
+ }
1333
+
1334
+ static const struct dev_pm_ops nxp_fspi_pm_ops = {
1335
+ RUNTIME_PM_OPS (nxp_fspi_runtime_suspend , nxp_fspi_runtime_resume , NULL )
1336
+ SYSTEM_SLEEP_PM_OPS (nxp_fspi_suspend , pm_runtime_force_resume )
1337
+ };
1338
+
1275
1339
static const struct of_device_id nxp_fspi_dt_ids [] = {
1276
1340
{ .compatible = "nxp,lx2160a-fspi" , .data = (void * )& lx2160a_data , },
1277
1341
{ .compatible = "nxp,imx8mm-fspi" , .data = (void * )& imx8mm_data , },
@@ -1291,17 +1355,12 @@ static const struct acpi_device_id nxp_fspi_acpi_ids[] = {
1291
1355
MODULE_DEVICE_TABLE (acpi , nxp_fspi_acpi_ids );
1292
1356
#endif
1293
1357
1294
- static const struct dev_pm_ops nxp_fspi_pm_ops = {
1295
- .suspend = nxp_fspi_suspend ,
1296
- .resume = nxp_fspi_resume ,
1297
- };
1298
-
1299
1358
static struct platform_driver nxp_fspi_driver = {
1300
1359
.driver = {
1301
1360
.name = "nxp-fspi" ,
1302
1361
.of_match_table = nxp_fspi_dt_ids ,
1303
1362
.acpi_match_table = ACPI_PTR (nxp_fspi_acpi_ids ),
1304
- .pm = & nxp_fspi_pm_ops ,
1363
+ .pm = pm_ptr ( & nxp_fspi_pm_ops ) ,
1305
1364
},
1306
1365
.probe = nxp_fspi_probe ,
1307
1366
.remove = nxp_fspi_remove ,
0 commit comments