99#include <linux/irqreturn.h>
1010#include <linux/pci.h>
1111#include <linux/sizes.h>
12+ #include <linux/pm_runtime.h>
1213
1314#include "intel-thc-dev.h"
1415#include "intel-thc-hw.h"
@@ -289,10 +290,15 @@ static irqreturn_t quicki2c_irq_thread_handler(int irq, void *dev_id)
289290 struct quicki2c_device * qcdev = dev_id ;
290291 int err_recover = 0 ;
291292 int int_mask ;
293+ int ret ;
292294
293295 if (qcdev -> state == QUICKI2C_DISABLED )
294296 return IRQ_HANDLED ;
295297
298+ ret = pm_runtime_resume_and_get (qcdev -> dev );
299+ if (ret )
300+ return IRQ_HANDLED ;
301+
296302 int_mask = thc_interrupt_handler (qcdev -> thc_hw );
297303
298304 if (int_mask & BIT (THC_FATAL_ERR_INT ) || int_mask & BIT (THC_TXN_ERR_INT ) ||
@@ -314,6 +320,9 @@ static irqreturn_t quicki2c_irq_thread_handler(int irq, void *dev_id)
314320 if (try_recover (qcdev ))
315321 qcdev -> state = QUICKI2C_DISABLED ;
316322
323+ pm_runtime_mark_last_busy (qcdev -> dev );
324+ pm_runtime_put_autosuspend (qcdev -> dev );
325+
317326 return IRQ_HANDLED ;
318327}
319328
@@ -639,6 +648,13 @@ static int quicki2c_probe(struct pci_dev *pdev,
639648
640649 qcdev -> state = QUICKI2C_ENABLED ;
641650
651+ /* Enable runtime power management */
652+ pm_runtime_use_autosuspend (qcdev -> dev );
653+ pm_runtime_set_autosuspend_delay (qcdev -> dev , DEFAULT_AUTO_SUSPEND_DELAY_MS );
654+ pm_runtime_mark_last_busy (qcdev -> dev );
655+ pm_runtime_put_noidle (qcdev -> dev );
656+ pm_runtime_put_autosuspend (qcdev -> dev );
657+
642658 dev_dbg (& pdev -> dev , "QuickI2C probe success\n" );
643659
644660 return 0 ;
@@ -674,6 +690,8 @@ static void quicki2c_remove(struct pci_dev *pdev)
674690 quicki2c_hid_remove (qcdev );
675691 quicki2c_dma_deinit (qcdev );
676692
693+ pm_runtime_get_noresume (qcdev -> dev );
694+
677695 quicki2c_dev_deinit (qcdev );
678696
679697 pcim_iounmap_regions (pdev , BIT (0 ));
@@ -703,6 +721,220 @@ static void quicki2c_shutdown(struct pci_dev *pdev)
703721 quicki2c_dev_deinit (qcdev );
704722}
705723
724+ static int quicki2c_suspend (struct device * device )
725+ {
726+ struct pci_dev * pdev = to_pci_dev (device );
727+ struct quicki2c_device * qcdev ;
728+ int ret ;
729+
730+ qcdev = pci_get_drvdata (pdev );
731+ if (!qcdev )
732+ return - ENODEV ;
733+
734+ /*
735+ * As I2C is THC subsystem, no register auto save/restore support,
736+ * need driver to do that explicitly for every D3 case.
737+ */
738+ ret = thc_i2c_subip_regs_save (qcdev -> thc_hw );
739+ if (ret )
740+ return ret ;
741+
742+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , true);
743+ if (ret )
744+ return ret ;
745+
746+ thc_interrupt_enable (qcdev -> thc_hw , false);
747+
748+ thc_dma_unconfigure (qcdev -> thc_hw );
749+
750+ return 0 ;
751+ }
752+
753+ static int quicki2c_resume (struct device * device )
754+ {
755+ struct pci_dev * pdev = to_pci_dev (device );
756+ struct quicki2c_device * qcdev ;
757+ int ret ;
758+
759+ qcdev = pci_get_drvdata (pdev );
760+ if (!qcdev )
761+ return - ENODEV ;
762+
763+ ret = thc_port_select (qcdev -> thc_hw , THC_PORT_TYPE_I2C );
764+ if (ret )
765+ return ret ;
766+
767+ ret = thc_i2c_subip_regs_restore (qcdev -> thc_hw );
768+ if (ret )
769+ return ret ;
770+
771+ thc_interrupt_config (qcdev -> thc_hw );
772+
773+ thc_interrupt_enable (qcdev -> thc_hw , true);
774+
775+ ret = thc_dma_configure (qcdev -> thc_hw );
776+ if (ret )
777+ return ret ;
778+
779+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , false);
780+ if (ret )
781+ return ret ;
782+
783+ return 0 ;
784+ }
785+
786+ static int quicki2c_freeze (struct device * device )
787+ {
788+ struct pci_dev * pdev = to_pci_dev (device );
789+ struct quicki2c_device * qcdev ;
790+ int ret ;
791+
792+ qcdev = pci_get_drvdata (pdev );
793+ if (!qcdev )
794+ return - ENODEV ;
795+
796+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , true);
797+ if (ret )
798+ return ret ;
799+
800+ thc_interrupt_enable (qcdev -> thc_hw , false);
801+
802+ thc_dma_unconfigure (qcdev -> thc_hw );
803+
804+ return 0 ;
805+ }
806+
807+ static int quicki2c_thaw (struct device * device )
808+ {
809+ struct pci_dev * pdev = to_pci_dev (device );
810+ struct quicki2c_device * qcdev ;
811+ int ret ;
812+
813+ qcdev = pci_get_drvdata (pdev );
814+ if (!qcdev )
815+ return - ENODEV ;
816+
817+ ret = thc_dma_configure (qcdev -> thc_hw );
818+ if (ret )
819+ return ret ;
820+
821+ thc_interrupt_enable (qcdev -> thc_hw , true);
822+
823+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , false);
824+ if (ret )
825+ return ret ;
826+
827+ return 0 ;
828+ }
829+
830+ static int quicki2c_poweroff (struct device * device )
831+ {
832+ struct pci_dev * pdev = to_pci_dev (device );
833+ struct quicki2c_device * qcdev ;
834+ int ret ;
835+
836+ qcdev = pci_get_drvdata (pdev );
837+ if (!qcdev )
838+ return - ENODEV ;
839+
840+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , true);
841+ if (ret )
842+ return ret ;
843+
844+ thc_interrupt_enable (qcdev -> thc_hw , false);
845+
846+ thc_ltr_unconfig (qcdev -> thc_hw );
847+
848+ quicki2c_dma_deinit (qcdev );
849+
850+ return 0 ;
851+ }
852+
853+ static int quicki2c_restore (struct device * device )
854+ {
855+ struct pci_dev * pdev = to_pci_dev (device );
856+ struct quicki2c_device * qcdev ;
857+ int ret ;
858+
859+ qcdev = pci_get_drvdata (pdev );
860+ if (!qcdev )
861+ return - ENODEV ;
862+
863+ /* Reconfig THC HW when back from hibernate */
864+ ret = thc_port_select (qcdev -> thc_hw , THC_PORT_TYPE_I2C );
865+ if (ret )
866+ return ret ;
867+
868+ ret = thc_i2c_subip_init (qcdev -> thc_hw , qcdev -> i2c_slave_addr ,
869+ qcdev -> i2c_speed_mode ,
870+ qcdev -> i2c_clock_hcnt ,
871+ qcdev -> i2c_clock_lcnt );
872+ if (ret )
873+ return ret ;
874+
875+ thc_interrupt_config (qcdev -> thc_hw );
876+
877+ thc_interrupt_enable (qcdev -> thc_hw , true);
878+
879+ ret = thc_interrupt_quiesce (qcdev -> thc_hw , false);
880+ if (ret )
881+ return ret ;
882+
883+ ret = thc_dma_configure (qcdev -> thc_hw );
884+ if (ret )
885+ return ret ;
886+
887+ thc_ltr_config (qcdev -> thc_hw ,
888+ qcdev -> active_ltr_val ,
889+ qcdev -> low_power_ltr_val );
890+
891+ thc_change_ltr_mode (qcdev -> thc_hw , THC_LTR_MODE_ACTIVE );
892+
893+ return 0 ;
894+ }
895+
896+ static int quicki2c_runtime_suspend (struct device * device )
897+ {
898+ struct pci_dev * pdev = to_pci_dev (device );
899+ struct quicki2c_device * qcdev ;
900+
901+ qcdev = pci_get_drvdata (pdev );
902+ if (!qcdev )
903+ return - ENODEV ;
904+
905+ thc_change_ltr_mode (qcdev -> thc_hw , THC_LTR_MODE_LP );
906+
907+ pci_save_state (pdev );
908+
909+ return 0 ;
910+ }
911+
912+ static int quicki2c_runtime_resume (struct device * device )
913+ {
914+ struct pci_dev * pdev = to_pci_dev (device );
915+ struct quicki2c_device * qcdev ;
916+
917+ qcdev = pci_get_drvdata (pdev );
918+ if (!qcdev )
919+ return - ENODEV ;
920+
921+ thc_change_ltr_mode (qcdev -> thc_hw , THC_LTR_MODE_ACTIVE );
922+
923+ return 0 ;
924+ }
925+
926+ static const struct dev_pm_ops quicki2c_pm_ops = {
927+ .suspend = quicki2c_suspend ,
928+ .resume = quicki2c_resume ,
929+ .freeze = quicki2c_freeze ,
930+ .thaw = quicki2c_thaw ,
931+ .poweroff = quicki2c_poweroff ,
932+ .restore = quicki2c_restore ,
933+ .runtime_suspend = quicki2c_runtime_suspend ,
934+ .runtime_resume = quicki2c_runtime_resume ,
935+ .runtime_idle = NULL ,
936+ };
937+
706938static const struct pci_device_id quicki2c_pci_tbl [] = {
707939 {PCI_VDEVICE (INTEL , THC_LNL_DEVICE_ID_I2C_PORT1 ), },
708940 {PCI_VDEVICE (INTEL , THC_LNL_DEVICE_ID_I2C_PORT2 ), },
@@ -720,6 +952,7 @@ static struct pci_driver quicki2c_driver = {
720952 .probe = quicki2c_probe ,
721953 .remove = quicki2c_remove ,
722954 .shutdown = quicki2c_shutdown ,
955+ .driver .pm = & quicki2c_pm_ops ,
723956 .driver .probe_type = PROBE_PREFER_ASYNCHRONOUS ,
724957};
725958
0 commit comments