1717#include <linux/list.h>
1818#include <linux/module.h>
1919#include <linux/of.h>
20+ #include <linux/pinctrl/consumer.h>
2021#include <linux/platform_device.h>
22+ #include <linux/pm_runtime.h>
2123
2224/* Master Mode Registers */
2325#define SVC_I3C_MCONFIG 0x000
119121#define SVC_MDYNADDR_ADDR (x ) FIELD_PREP(GENMASK(7, 1), (x))
120122
121123#define SVC_I3C_MAX_DEVS 32
124+ #define SVC_I3C_PM_TIMEOUT_MS 1000
122125
123126/* This parameter depends on the implementation and may be tuned */
124127#define SVC_I3C_FIFO_SIZE 16
@@ -480,10 +483,20 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
480483 u32 ppbaud , pplow , odhpp , odbaud , odstop , i2cbaud , reg ;
481484 int ret ;
482485
486+ ret = pm_runtime_resume_and_get (master -> dev );
487+ if (ret < 0 ) {
488+ dev_err (master -> dev ,
489+ "<%s> cannot resume i3c bus master, err: %d\n" ,
490+ __func__ , ret );
491+ return ret ;
492+ }
493+
483494 /* Timings derivation */
484495 fclk_rate = clk_get_rate (master -> fclk );
485- if (!fclk_rate )
486- return - EINVAL ;
496+ if (!fclk_rate ) {
497+ ret = - EINVAL ;
498+ goto rpm_out ;
499+ }
487500
488501 fclk_period_ns = DIV_ROUND_UP (1000000000 , fclk_rate );
489502
@@ -527,7 +540,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
527540 odstop = 1 ;
528541 break ;
529542 default :
530- return - EINVAL ;
543+ goto rpm_out ;
531544 }
532545
533546 reg = SVC_I3C_MCONFIG_MASTER_EN |
@@ -545,7 +558,7 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
545558 /* Master core's registration */
546559 ret = i3c_master_get_free_addr (m , 0 );
547560 if (ret < 0 )
548- return ret ;
561+ goto rpm_out ;
549562
550563 info .dyn_addr = ret ;
551564
@@ -554,21 +567,35 @@ static int svc_i3c_master_bus_init(struct i3c_master_controller *m)
554567
555568 ret = i3c_master_set_info (& master -> base , & info );
556569 if (ret )
557- return ret ;
570+ goto rpm_out ;
558571
559572 svc_i3c_master_enable_interrupts (master , SVC_I3C_MINT_SLVSTART );
560573
561- return 0 ;
574+ rpm_out :
575+ pm_runtime_mark_last_busy (master -> dev );
576+ pm_runtime_put_autosuspend (master -> dev );
577+
578+ return ret ;
562579}
563580
564581static void svc_i3c_master_bus_cleanup (struct i3c_master_controller * m )
565582{
566583 struct svc_i3c_master * master = to_svc_i3c_master (m );
584+ int ret ;
585+
586+ ret = pm_runtime_resume_and_get (master -> dev );
587+ if (ret < 0 ) {
588+ dev_err (master -> dev , "<%s> Cannot get runtime PM.\n" , __func__ );
589+ return ;
590+ }
567591
568592 svc_i3c_master_disable_interrupts (master );
569593
570594 /* Disable master */
571595 writel (0 , master -> regs + SVC_I3C_MCONFIG );
596+
597+ pm_runtime_mark_last_busy (master -> dev );
598+ pm_runtime_put_autosuspend (master -> dev );
572599}
573600
574601static int svc_i3c_master_reserve_slot (struct svc_i3c_master * master )
@@ -867,31 +894,36 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
867894 unsigned int dev_nb ;
868895 int ret , i ;
869896
897+ ret = pm_runtime_resume_and_get (master -> dev );
898+ if (ret < 0 ) {
899+ dev_err (master -> dev , "<%s> Cannot get runtime PM.\n" , __func__ );
900+ return ret ;
901+ }
902+
870903 spin_lock_irqsave (& master -> xferqueue .lock , flags );
871904 ret = svc_i3c_master_do_daa_locked (master , addrs , & dev_nb );
872905 spin_unlock_irqrestore (& master -> xferqueue .lock , flags );
873- if (ret )
874- goto emit_stop ;
906+ if (ret ) {
907+ svc_i3c_master_emit_stop (master );
908+ svc_i3c_master_clear_merrwarn (master );
909+ goto rpm_out ;
910+ }
875911
876912 /* Register all devices who participated to the core */
877913 for (i = 0 ; i < dev_nb ; i ++ ) {
878914 ret = i3c_master_add_i3c_dev_locked (m , addrs [i ]);
879915 if (ret )
880- return ret ;
916+ goto rpm_out ;
881917 }
882918
883919 /* Configure IBI auto-rules */
884920 ret = svc_i3c_update_ibirules (master );
885- if (ret ) {
921+ if (ret )
886922 dev_err (master -> dev , "Cannot handle such a list of devices" );
887- return ret ;
888- }
889-
890- return 0 ;
891923
892- emit_stop :
893- svc_i3c_master_emit_stop (master );
894- svc_i3c_master_clear_merrwarn (master );
924+ rpm_out :
925+ pm_runtime_mark_last_busy (master -> dev );
926+ pm_runtime_put_autosuspend (master -> dev );
895927
896928 return ret ;
897929}
@@ -1060,6 +1092,12 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
10601092 if (!xfer )
10611093 return ;
10621094
1095+ ret = pm_runtime_resume_and_get (master -> dev );
1096+ if (ret < 0 ) {
1097+ dev_err (master -> dev , "<%s> Cannot get runtime PM.\n" , __func__ );
1098+ return ;
1099+ }
1100+
10631101 svc_i3c_master_clear_merrwarn (master );
10641102 svc_i3c_master_flush_fifo (master );
10651103
@@ -1074,6 +1112,9 @@ static void svc_i3c_master_start_xfer_locked(struct svc_i3c_master *master)
10741112 break ;
10751113 }
10761114
1115+ pm_runtime_mark_last_busy (master -> dev );
1116+ pm_runtime_put_autosuspend (master -> dev );
1117+
10771118 xfer -> ret = ret ;
10781119 complete (& xfer -> comp );
10791120
@@ -1350,15 +1391,30 @@ static void svc_i3c_master_free_ibi(struct i3c_dev_desc *dev)
13501391static int svc_i3c_master_enable_ibi (struct i3c_dev_desc * dev )
13511392{
13521393 struct i3c_master_controller * m = i3c_dev_get_master (dev );
1394+ struct svc_i3c_master * master = to_svc_i3c_master (m );
1395+ int ret ;
1396+
1397+ ret = pm_runtime_resume_and_get (master -> dev );
1398+ if (ret < 0 ) {
1399+ dev_err (master -> dev , "<%s> Cannot get runtime PM.\n" , __func__ );
1400+ return ret ;
1401+ }
13531402
13541403 return i3c_master_enec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
13551404}
13561405
13571406static int svc_i3c_master_disable_ibi (struct i3c_dev_desc * dev )
13581407{
13591408 struct i3c_master_controller * m = i3c_dev_get_master (dev );
1409+ struct svc_i3c_master * master = to_svc_i3c_master (m );
1410+ int ret ;
1411+
1412+ ret = i3c_master_disec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
13601413
1361- return i3c_master_disec_locked (m , dev -> info .dyn_addr , I3C_CCC_EVENT_SIR );
1414+ pm_runtime_mark_last_busy (master -> dev );
1415+ pm_runtime_put_autosuspend (master -> dev );
1416+
1417+ return ret ;
13621418}
13631419
13641420static void svc_i3c_master_recycle_ibi_slot (struct i3c_dev_desc * dev ,
@@ -1389,6 +1445,37 @@ static const struct i3c_master_controller_ops svc_i3c_master_ops = {
13891445 .disable_ibi = svc_i3c_master_disable_ibi ,
13901446};
13911447
1448+ static int svc_i3c_master_prepare_clks (struct svc_i3c_master * master )
1449+ {
1450+ int ret = 0 ;
1451+
1452+ ret = clk_prepare_enable (master -> pclk );
1453+ if (ret )
1454+ return ret ;
1455+
1456+ ret = clk_prepare_enable (master -> fclk );
1457+ if (ret ) {
1458+ clk_disable_unprepare (master -> pclk );
1459+ return ret ;
1460+ }
1461+
1462+ ret = clk_prepare_enable (master -> sclk );
1463+ if (ret ) {
1464+ clk_disable_unprepare (master -> pclk );
1465+ clk_disable_unprepare (master -> fclk );
1466+ return ret ;
1467+ }
1468+
1469+ return 0 ;
1470+ }
1471+
1472+ static void svc_i3c_master_unprepare_clks (struct svc_i3c_master * master )
1473+ {
1474+ clk_disable_unprepare (master -> pclk );
1475+ clk_disable_unprepare (master -> fclk );
1476+ clk_disable_unprepare (master -> sclk );
1477+ }
1478+
13921479static int svc_i3c_master_probe (struct platform_device * pdev )
13931480{
13941481 struct device * dev = & pdev -> dev ;
@@ -1421,24 +1508,16 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
14211508
14221509 master -> dev = dev ;
14231510
1424- ret = clk_prepare_enable (master -> pclk );
1511+ ret = svc_i3c_master_prepare_clks (master );
14251512 if (ret )
14261513 return ret ;
14271514
1428- ret = clk_prepare_enable (master -> fclk );
1429- if (ret )
1430- goto err_disable_pclk ;
1431-
1432- ret = clk_prepare_enable (master -> sclk );
1433- if (ret )
1434- goto err_disable_fclk ;
1435-
14361515 INIT_WORK (& master -> hj_work , svc_i3c_master_hj_work );
14371516 INIT_WORK (& master -> ibi_work , svc_i3c_master_ibi_work );
14381517 ret = devm_request_irq (dev , master -> irq , svc_i3c_master_irq_handler ,
14391518 IRQF_NO_SUSPEND , "svc-i3c-irq" , master );
14401519 if (ret )
1441- goto err_disable_sclk ;
1520+ goto err_disable_clks ;
14421521
14431522 master -> free_slots = GENMASK (SVC_I3C_MAX_DEVS - 1 , 0 );
14441523
@@ -1452,29 +1531,38 @@ static int svc_i3c_master_probe(struct platform_device *pdev)
14521531 GFP_KERNEL );
14531532 if (!master -> ibi .slots ) {
14541533 ret = - ENOMEM ;
1455- goto err_disable_sclk ;
1534+ goto err_disable_clks ;
14561535 }
14571536
14581537 platform_set_drvdata (pdev , master );
14591538
1539+ pm_runtime_set_autosuspend_delay (& pdev -> dev , SVC_I3C_PM_TIMEOUT_MS );
1540+ pm_runtime_use_autosuspend (& pdev -> dev );
1541+ pm_runtime_get_noresume (& pdev -> dev );
1542+ pm_runtime_set_active (& pdev -> dev );
1543+ pm_runtime_enable (& pdev -> dev );
1544+
14601545 svc_i3c_master_reset (master );
14611546
14621547 /* Register the master */
14631548 ret = i3c_master_register (& master -> base , & pdev -> dev ,
14641549 & svc_i3c_master_ops , false);
14651550 if (ret )
1466- goto err_disable_sclk ;
1551+ goto rpm_disable ;
1552+
1553+ pm_runtime_mark_last_busy (& pdev -> dev );
1554+ pm_runtime_put_autosuspend (& pdev -> dev );
14671555
14681556 return 0 ;
14691557
1470- err_disable_sclk :
1471- clk_disable_unprepare (master -> sclk );
1558+ rpm_disable :
1559+ pm_runtime_dont_use_autosuspend (& pdev -> dev );
1560+ pm_runtime_put_noidle (& pdev -> dev );
1561+ pm_runtime_set_suspended (& pdev -> dev );
1562+ pm_runtime_disable (& pdev -> dev );
14721563
1473- err_disable_fclk :
1474- clk_disable_unprepare (master -> fclk );
1475-
1476- err_disable_pclk :
1477- clk_disable_unprepare (master -> pclk );
1564+ err_disable_clks :
1565+ svc_i3c_master_unprepare_clks (master );
14781566
14791567 return ret ;
14801568}
@@ -1488,13 +1576,40 @@ static int svc_i3c_master_remove(struct platform_device *pdev)
14881576 if (ret )
14891577 return ret ;
14901578
1491- clk_disable_unprepare (master -> pclk );
1492- clk_disable_unprepare (master -> fclk );
1493- clk_disable_unprepare (master -> sclk );
1579+ pm_runtime_dont_use_autosuspend (& pdev -> dev );
1580+ pm_runtime_disable (& pdev -> dev );
14941581
14951582 return 0 ;
14961583}
14971584
1585+ static int __maybe_unused svc_i3c_runtime_suspend (struct device * dev )
1586+ {
1587+ struct svc_i3c_master * master = dev_get_drvdata (dev );
1588+
1589+ svc_i3c_master_unprepare_clks (master );
1590+ pinctrl_pm_select_sleep_state (dev );
1591+
1592+ return 0 ;
1593+ }
1594+
1595+ static int __maybe_unused svc_i3c_runtime_resume (struct device * dev )
1596+ {
1597+ struct svc_i3c_master * master = dev_get_drvdata (dev );
1598+ int ret = 0 ;
1599+
1600+ pinctrl_pm_select_default_state (dev );
1601+ svc_i3c_master_prepare_clks (master );
1602+
1603+ return ret ;
1604+ }
1605+
1606+ static const struct dev_pm_ops svc_i3c_pm_ops = {
1607+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS (pm_runtime_force_suspend ,
1608+ pm_runtime_force_resume )
1609+ SET_RUNTIME_PM_OPS (svc_i3c_runtime_suspend ,
1610+ svc_i3c_runtime_resume , NULL )
1611+ };
1612+
14981613static const struct of_device_id svc_i3c_master_of_match_tbl [] = {
14991614 { .compatible = "silvaco,i3c-master" },
15001615 { /* sentinel */ },
@@ -1506,6 +1621,7 @@ static struct platform_driver svc_i3c_master = {
15061621 .driver = {
15071622 .name = "silvaco-i3c-master" ,
15081623 .of_match_table = svc_i3c_master_of_match_tbl ,
1624+ .pm = & svc_i3c_pm_ops ,
15091625 },
15101626};
15111627module_platform_driver (svc_i3c_master );
0 commit comments