2020#include <linux/of_irq.h>
2121#include <linux/of_address.h>
2222#include <linux/platform_device.h>
23+ #include <linux/pm_runtime.h>
2324#include <linux/spi/spi.h>
2425#include <linux/spinlock.h>
2526#include <linux/workqueue.h>
135136#define GQSPI_DMA_UNALIGN 0x3
136137#define GQSPI_DEFAULT_NUM_CS 1 /* Default number of chip selects */
137138
139+ #define SPI_AUTOSUSPEND_TIMEOUT 3000
138140enum mode_type {GQSPI_MODE_IO , GQSPI_MODE_DMA };
139141
140142/**
@@ -356,21 +358,9 @@ static void zynqmp_qspi_copy_read_data(struct zynqmp_qspi *xqspi,
356358static int zynqmp_prepare_transfer_hardware (struct spi_master * master )
357359{
358360 struct zynqmp_qspi * xqspi = spi_master_get_devdata (master );
359- int ret ;
360-
361- ret = clk_enable (xqspi -> refclk );
362- if (ret )
363- return ret ;
364-
365- ret = clk_enable (xqspi -> pclk );
366- if (ret )
367- goto clk_err ;
368361
369362 zynqmp_gqspi_write (xqspi , GQSPI_EN_OFST , GQSPI_EN_MASK );
370363 return 0 ;
371- clk_err :
372- clk_disable (xqspi -> refclk );
373- return ret ;
374364}
375365
376366/**
@@ -387,8 +377,6 @@ static int zynqmp_unprepare_transfer_hardware(struct spi_master *master)
387377 struct zynqmp_qspi * xqspi = spi_master_get_devdata (master );
388378
389379 zynqmp_gqspi_write (xqspi , GQSPI_EN_OFST , 0x0 );
390- clk_disable (xqspi -> refclk );
391- clk_disable (xqspi -> pclk );
392380 return 0 ;
393381}
394382
@@ -959,11 +947,67 @@ static int __maybe_unused zynqmp_qspi_resume(struct device *dev)
959947
960948 spi_master_resume (master );
961949
950+ clk_disable (xqspi -> refclk );
951+ clk_disable (xqspi -> pclk );
962952 return 0 ;
963953}
964954
965- static SIMPLE_DEV_PM_OPS (zynqmp_qspi_dev_pm_ops , zynqmp_qspi_suspend ,
966- zynqmp_qspi_resume ) ;
955+ /**
956+ * zynqmp_runtime_suspend - Runtime suspend method for the SPI driver
957+ * @dev: Address of the platform_device structure
958+ *
959+ * This function disables the clocks
960+ *
961+ * Return: Always 0
962+ */
963+ static int __maybe_unused zynqmp_runtime_suspend (struct device * dev )
964+ {
965+ struct platform_device * pdev = to_platform_device (dev );
966+ struct spi_master * master = platform_get_drvdata (pdev );
967+ struct zynqmp_qspi * xqspi = spi_master_get_devdata (master );
968+
969+ clk_disable (xqspi -> refclk );
970+ clk_disable (xqspi -> pclk );
971+
972+ return 0 ;
973+ }
974+
975+ /**
976+ * zynqmp_runtime_resume - Runtime resume method for the SPI driver
977+ * @dev: Address of the platform_device structure
978+ *
979+ * This function enables the clocks
980+ *
981+ * Return: 0 on success and error value on error
982+ */
983+ static int __maybe_unused zynqmp_runtime_resume (struct device * dev )
984+ {
985+ struct platform_device * pdev = to_platform_device (dev );
986+ struct spi_master * master = platform_get_drvdata (pdev );
987+ struct zynqmp_qspi * xqspi = spi_master_get_devdata (master );
988+ int ret ;
989+
990+ ret = clk_enable (xqspi -> pclk );
991+ if (ret ) {
992+ dev_err (dev , "Cannot enable APB clock.\n" );
993+ return ret ;
994+ }
995+
996+ ret = clk_enable (xqspi -> refclk );
997+ if (ret ) {
998+ dev_err (dev , "Cannot enable device clock.\n" );
999+ clk_disable (xqspi -> pclk );
1000+ return ret ;
1001+ }
1002+
1003+ return 0 ;
1004+ }
1005+
1006+ static const struct dev_pm_ops zynqmp_qspi_dev_pm_ops = {
1007+ SET_RUNTIME_PM_OPS (zynqmp_runtime_suspend ,
1008+ zynqmp_runtime_resume , NULL )
1009+ SET_SYSTEM_SLEEP_PM_OPS (zynqmp_qspi_suspend , zynqmp_qspi_resume )
1010+ };
9671011
9681012/**
9691013 * zynqmp_qspi_probe: Probe method for the QSPI driver
@@ -1023,9 +1067,15 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
10231067 goto clk_dis_pclk ;
10241068 }
10251069
1070+ pm_runtime_use_autosuspend (& pdev -> dev );
1071+ pm_runtime_set_autosuspend_delay (& pdev -> dev , SPI_AUTOSUSPEND_TIMEOUT );
1072+ pm_runtime_set_active (& pdev -> dev );
1073+ pm_runtime_enable (& pdev -> dev );
10261074 /* QSPI controller initializations */
10271075 zynqmp_qspi_init_hw (xqspi );
10281076
1077+ pm_runtime_mark_last_busy (& pdev -> dev );
1078+ pm_runtime_put_autosuspend (& pdev -> dev );
10291079 xqspi -> irq = platform_get_irq (pdev , 0 );
10301080 if (xqspi -> irq <= 0 ) {
10311081 ret = - ENXIO ;
@@ -1063,6 +1113,8 @@ static int zynqmp_qspi_probe(struct platform_device *pdev)
10631113 return 0 ;
10641114
10651115clk_dis_all :
1116+ pm_runtime_set_suspended (& pdev -> dev );
1117+ pm_runtime_disable (& pdev -> dev );
10661118 clk_disable_unprepare (xqspi -> refclk );
10671119clk_dis_pclk :
10681120 clk_disable_unprepare (xqspi -> pclk );
@@ -1090,6 +1142,8 @@ static int zynqmp_qspi_remove(struct platform_device *pdev)
10901142 zynqmp_gqspi_write (xqspi , GQSPI_EN_OFST , 0x0 );
10911143 clk_disable_unprepare (xqspi -> refclk );
10921144 clk_disable_unprepare (xqspi -> pclk );
1145+ pm_runtime_set_suspended (& pdev -> dev );
1146+ pm_runtime_disable (& pdev -> dev );
10931147
10941148 spi_unregister_master (master );
10951149
0 commit comments