1515#include <linux/module.h>
1616#include <linux/mtd/mtd.h>
1717#include <linux/mtd/partitions.h>
18+ #include <linux/pm_runtime.h>
1819#include <linux/string.h>
1920#include <linux/slab.h>
2021#include <linux/sizes.h>
2122#include <linux/types.h>
2223
24+ #define INTEL_DG_NVM_RPM_TIMEOUT_MS 500
25+
2326struct intel_dg_nvm {
2427 struct kref refcnt ;
2528 struct mtd_info mtd ;
29+ struct device * dev ;
2630 struct mutex lock ; /* region access lock */
2731 void __iomem * base ;
2832 void __iomem * base2 ;
@@ -421,6 +425,8 @@ static int intel_dg_nvm_init(struct intel_dg_nvm *nvm, struct device *device,
421425 unsigned int i , n ;
422426 int ret ;
423427
428+ nvm -> dev = device ;
429+
424430 /* clean error register, previous errors are ignored */
425431 idg_nvm_error (nvm );
426432
@@ -498,6 +504,7 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
498504 size_t len ;
499505 u8 region ;
500506 u64 addr ;
507+ int ret ;
501508
502509 if (WARN_ON (!nvm ))
503510 return - EINVAL ;
@@ -512,20 +519,29 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
512519 total_len = info -> len ;
513520 addr = info -> addr ;
514521
522+ ret = pm_runtime_resume_and_get (nvm -> dev );
523+ if (ret < 0 ) {
524+ dev_err (& mtd -> dev , "rpm: get failed %d\n" , ret );
525+ return ret ;
526+ }
527+
528+ ret = 0 ;
515529 guard (mutex )(& nvm -> lock );
516530
517531 while (total_len > 0 ) {
518532 if (!IS_ALIGNED (addr , SZ_4K ) || !IS_ALIGNED (total_len , SZ_4K )) {
519533 dev_err (& mtd -> dev , "unaligned erase %llx %zx\n" , addr , total_len );
520534 info -> fail_addr = addr ;
521- return - ERANGE ;
535+ ret = - ERANGE ;
536+ break ;
522537 }
523538
524539 idx = idg_nvm_get_region (nvm , addr );
525540 if (idx >= nvm -> nregions ) {
526541 dev_err (& mtd -> dev , "out of range" );
527542 info -> fail_addr = MTD_FAIL_ADDR_UNKNOWN ;
528- return - ERANGE ;
543+ ret = - ERANGE ;
544+ break ;
529545 }
530546
531547 from = addr - nvm -> regions [idx ].offset ;
@@ -541,14 +557,16 @@ static int intel_dg_mtd_erase(struct mtd_info *mtd, struct erase_info *info)
541557 if (bytes < 0 ) {
542558 dev_dbg (& mtd -> dev , "erase failed with %zd\n" , bytes );
543559 info -> fail_addr += nvm -> regions [idx ].offset ;
544- return bytes ;
560+ ret = bytes ;
561+ break ;
545562 }
546563
547564 addr += len ;
548565 total_len -= len ;
549566 }
550567
551- return 0 ;
568+ pm_runtime_put_autosuspend (nvm -> dev );
569+ return ret ;
552570}
553571
554572static int intel_dg_mtd_read (struct mtd_info * mtd , loff_t from , size_t len ,
@@ -577,17 +595,24 @@ static int intel_dg_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
577595 if (len > nvm -> regions [idx ].size - from )
578596 len = nvm -> regions [idx ].size - from ;
579597
598+ ret = pm_runtime_resume_and_get (nvm -> dev );
599+ if (ret < 0 ) {
600+ dev_err (& mtd -> dev , "rpm: get failed %zd\n" , ret );
601+ return ret ;
602+ }
603+
580604 guard (mutex )(& nvm -> lock );
581605
582606 ret = idg_read (nvm , region , from , len , buf );
583607 if (ret < 0 ) {
584608 dev_dbg (& mtd -> dev , "read failed with %zd\n" , ret );
585- return ret ;
609+ } else {
610+ * retlen = ret ;
611+ ret = 0 ;
586612 }
587613
588- * retlen = ret ;
589-
590- return 0 ;
614+ pm_runtime_put_autosuspend (nvm -> dev );
615+ return ret ;
591616}
592617
593618static int intel_dg_mtd_write (struct mtd_info * mtd , loff_t to , size_t len ,
@@ -616,17 +641,24 @@ static int intel_dg_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
616641 if (len > nvm -> regions [idx ].size - to )
617642 len = nvm -> regions [idx ].size - to ;
618643
644+ ret = pm_runtime_resume_and_get (nvm -> dev );
645+ if (ret < 0 ) {
646+ dev_err (& mtd -> dev , "rpm: get failed %zd\n" , ret );
647+ return ret ;
648+ }
649+
619650 guard (mutex )(& nvm -> lock );
620651
621652 ret = idg_write (nvm , region , to , len , buf );
622653 if (ret < 0 ) {
623654 dev_dbg (& mtd -> dev , "write failed with %zd\n" , ret );
624- return ret ;
655+ } else {
656+ * retlen = ret ;
657+ ret = 0 ;
625658 }
626659
627- * retlen = ret ;
628-
629- return 0 ;
660+ pm_runtime_put_autosuspend (nvm -> dev );
661+ return ret ;
630662}
631663
632664static void intel_dg_nvm_release (struct kref * kref )
@@ -753,6 +785,21 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
753785 }
754786 nvm -> nregions = n ; /* in case where kasprintf fail */
755787
788+ ret = devm_pm_runtime_enable (device );
789+ if (ret < 0 ) {
790+ dev_err (device , "rpm: enable failed %d\n" , ret );
791+ goto err_norpm ;
792+ }
793+
794+ pm_runtime_set_autosuspend_delay (device , INTEL_DG_NVM_RPM_TIMEOUT_MS );
795+ pm_runtime_use_autosuspend (device );
796+
797+ ret = pm_runtime_resume_and_get (device );
798+ if (ret < 0 ) {
799+ dev_err (device , "rpm: get failed %d\n" , ret );
800+ goto err_norpm ;
801+ }
802+
756803 nvm -> base = devm_ioremap_resource (device , & invm -> bar );
757804 if (IS_ERR (nvm -> base )) {
758805 ret = PTR_ERR (nvm -> base );
@@ -781,9 +828,12 @@ static int intel_dg_mtd_probe(struct auxiliary_device *aux_dev,
781828
782829 dev_set_drvdata (& aux_dev -> dev , nvm );
783830
831+ pm_runtime_put (device );
784832 return 0 ;
785833
786834err :
835+ pm_runtime_put (device );
836+ err_norpm :
787837 kref_put (& nvm -> refcnt , intel_dg_nvm_release );
788838 return ret ;
789839}
0 commit comments