1313#include <linux/completion.h>
1414#include <linux/dma-mapping.h>
1515#include <linux/iopoll.h>
16+ #include <linux/interrupt.h>
1617#include <linux/mm.h>
1718#include <linux/module.h>
1819#include <linux/of.h>
20+ #include <linux/pinctrl/consumer.h>
1921#include <linux/platform_device.h>
22+ #include <linux/pm_runtime.h>
2023#include <linux/slab.h>
21- #include <linux/interrupt.h>
2224#include <linux/spi/spi-mem.h>
2325
2426/* System control */
150152/* Data */
151153#define SFC_DATA 0x108
152154
153- /* The controller and documentation reports that it supports up to 4 CS
154- * devices (0-3), however I have only been able to test a single CS (CS 0)
155- * due to the configuration of my device.
156- */
157- #define SFC_MAX_CHIPSELECT_NUM 4
155+ #define SFC_CS1_REG_OFFSET 0x200
156+
157+ #define SFC_MAX_CHIPSELECT_NUM 2
158158
159159/* The SFC can transfer max 16KB - 1 at one time
160160 * we set it to 15.5KB here for alignment.
169169 */
170170#define SFC_MAX_SPEED (150 * 1000 * 1000)
171171
172+ #define ROCKCHIP_AUTOSUSPEND_DELAY 2000
173+
172174struct rockchip_sfc {
173175 struct device * dev ;
174176 void __iomem * regbase ;
175177 struct clk * hclk ;
176178 struct clk * clk ;
177- u32 frequency ;
179+ u32 speed [ SFC_MAX_CHIPSELECT_NUM ] ;
178180 /* virtual mapped addr for dma_buffer */
179181 void * buffer ;
180182 dma_addr_t dma_buffer ;
@@ -301,6 +303,7 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
301303 u32 len )
302304{
303305 u32 ctrl = 0 , cmd = 0 ;
306+ u8 cs = spi_get_chipselect (mem -> spi , 0 );
304307
305308 /* set CMD */
306309 cmd = op -> cmd .opcode ;
@@ -314,7 +317,8 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
314317 cmd |= SFC_CMD_ADDR_24BITS << SFC_CMD_ADDR_SHIFT ;
315318 } else {
316319 cmd |= SFC_CMD_ADDR_XBITS << SFC_CMD_ADDR_SHIFT ;
317- writel (op -> addr .nbytes * 8 - 1 , sfc -> regbase + SFC_ABIT );
320+ writel (op -> addr .nbytes * 8 - 1 ,
321+ sfc -> regbase + cs * SFC_CS1_REG_OFFSET + SFC_ABIT );
318322 }
319323
320324 ctrl |= ((op -> addr .buswidth >> 1 ) << SFC_CTRL_ADDR_BITS_SHIFT );
@@ -346,15 +350,15 @@ static int rockchip_sfc_xfer_setup(struct rockchip_sfc *sfc,
346350
347351 /* set the Controller */
348352 ctrl |= SFC_CTRL_PHASE_SEL_NEGETIVE ;
349- cmd |= spi_get_chipselect ( mem -> spi , 0 ) << SFC_CMD_CS_SHIFT ;
353+ cmd |= cs << SFC_CMD_CS_SHIFT ;
350354
351355 dev_dbg (sfc -> dev , "sfc addr.nbytes=%x(x%d) dummy.nbytes=%x(x%d)\n" ,
352356 op -> addr .nbytes , op -> addr .buswidth ,
353357 op -> dummy .nbytes , op -> dummy .buswidth );
354358 dev_dbg (sfc -> dev , "sfc ctrl=%x cmd=%x addr=%llx len=%x\n" ,
355359 ctrl , cmd , op -> addr .val , len );
356360
357- writel (ctrl , sfc -> regbase + SFC_CTRL );
361+ writel (ctrl , sfc -> regbase + cs * SFC_CS1_REG_OFFSET + SFC_CTRL );
358362 writel (cmd , sfc -> regbase + SFC_CMD );
359363 if (op -> addr .nbytes )
360364 writel (op -> addr .val , sfc -> regbase + SFC_ADDR );
@@ -500,14 +504,22 @@ static int rockchip_sfc_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op
500504 struct rockchip_sfc * sfc = spi_controller_get_devdata (mem -> spi -> controller );
501505 u32 len = op -> data .nbytes ;
502506 int ret ;
507+ u8 cs = spi_get_chipselect (mem -> spi , 0 );
508+
509+ ret = pm_runtime_get_sync (sfc -> dev );
510+ if (ret < 0 ) {
511+ pm_runtime_put_noidle (sfc -> dev );
512+ return ret ;
513+ }
503514
504- if (unlikely (mem -> spi -> max_speed_hz != sfc -> frequency ) && !has_acpi_companion (sfc -> dev )) {
515+ if (unlikely (mem -> spi -> max_speed_hz != sfc -> speed [cs ]) &&
516+ !has_acpi_companion (sfc -> dev )) {
505517 ret = clk_set_rate (sfc -> clk , mem -> spi -> max_speed_hz );
506518 if (ret )
507- return ret ;
508- sfc -> frequency = mem -> spi -> max_speed_hz ;
519+ goto out ;
520+ sfc -> speed [ cs ] = mem -> spi -> max_speed_hz ;
509521 dev_dbg (sfc -> dev , "set_freq=%dHz real_freq=%ldHz\n" ,
510- sfc -> frequency , clk_get_rate (sfc -> clk ));
522+ sfc -> speed [ cs ] , clk_get_rate (sfc -> clk ));
511523 }
512524
513525 rockchip_sfc_adjust_op_work ((struct spi_mem_op * )op );
@@ -524,11 +536,17 @@ static int rockchip_sfc_exec_mem_op(struct spi_mem *mem, const struct spi_mem_op
524536 if (ret != len ) {
525537 dev_err (sfc -> dev , "xfer data failed ret %d dir %d\n" , ret , op -> data .dir );
526538
527- return - EIO ;
539+ ret = - EIO ;
540+ goto out ;
528541 }
529542 }
530543
531- return rockchip_sfc_xfer_done (sfc , 100000 );
544+ ret = rockchip_sfc_xfer_done (sfc , 100000 );
545+ out :
546+ pm_runtime_mark_last_busy (sfc -> dev );
547+ pm_runtime_put_autosuspend (sfc -> dev );
548+
549+ return ret ;
532550}
533551
534552static int rockchip_sfc_adjust_op_size (struct spi_mem * mem , struct spi_mem_op * op )
@@ -570,6 +588,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
570588 struct spi_controller * host ;
571589 struct rockchip_sfc * sfc ;
572590 int ret ;
591+ u32 i , val ;
573592
574593 host = devm_spi_alloc_host (& pdev -> dev , sizeof (* sfc ));
575594 if (!host )
@@ -602,9 +621,12 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
602621 "Failed to get sfc ahb clk\n" );
603622
604623 if (has_acpi_companion (& pdev -> dev )) {
605- ret = device_property_read_u32 (& pdev -> dev , "clock-frequency" , & sfc -> frequency );
624+ ret = device_property_read_u32 (& pdev -> dev , "clock-frequency" , & val );
606625 if (ret )
607- return dev_err_probe (& pdev -> dev , ret , "Failed to find clock-frequency\n" );
626+ return dev_err_probe (& pdev -> dev , ret ,
627+ "Failed to find clock-frequency in ACPI\n" );
628+ for (i = 0 ; i < SFC_MAX_CHIPSELECT_NUM ; i ++ )
629+ sfc -> speed [i ] = val ;
608630 }
609631
610632 sfc -> use_dma = !of_property_read_bool (sfc -> dev -> of_node , "rockchip,sfc-no-dma" );
@@ -646,19 +668,36 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
646668 goto err_irq ;
647669 }
648670
671+ platform_set_drvdata (pdev , sfc );
672+
649673 ret = rockchip_sfc_init (sfc );
650674 if (ret )
651675 goto err_irq ;
652676
653677 sfc -> max_iosize = rockchip_sfc_get_max_iosize (sfc );
654678 sfc -> version = rockchip_sfc_get_version (sfc );
655679
656- ret = spi_register_controller (host );
680+ pm_runtime_set_autosuspend_delay (dev , ROCKCHIP_AUTOSUSPEND_DELAY );
681+ pm_runtime_use_autosuspend (dev );
682+ pm_runtime_set_active (dev );
683+ pm_runtime_enable (dev );
684+ pm_runtime_get_noresume (dev );
685+
686+ ret = devm_spi_register_controller (dev , host );
657687 if (ret )
658- goto err_irq ;
688+ goto err_pm_runtime_free ;
689+
690+ pm_runtime_mark_last_busy (dev );
691+ pm_runtime_put_autosuspend (dev );
659692
660693 return 0 ;
661694
695+ err_pm_runtime_free :
696+ pm_runtime_get_sync (dev );
697+ pm_runtime_put_noidle (dev );
698+ pm_runtime_disable (dev );
699+ pm_runtime_set_suspended (dev );
700+ pm_runtime_dont_use_autosuspend (dev );
662701err_irq :
663702 clk_disable_unprepare (sfc -> clk );
664703err_clk :
@@ -678,6 +717,74 @@ static void rockchip_sfc_remove(struct platform_device *pdev)
678717 clk_disable_unprepare (sfc -> hclk );
679718}
680719
720+ #ifdef CONFIG_PM
721+ static int rockchip_sfc_runtime_suspend (struct device * dev )
722+ {
723+ struct rockchip_sfc * sfc = dev_get_drvdata (dev );
724+
725+ clk_disable_unprepare (sfc -> clk );
726+ clk_disable_unprepare (sfc -> hclk );
727+
728+ return 0 ;
729+ }
730+
731+ static int rockchip_sfc_runtime_resume (struct device * dev )
732+ {
733+ struct rockchip_sfc * sfc = dev_get_drvdata (dev );
734+ int ret ;
735+
736+ ret = clk_prepare_enable (sfc -> hclk );
737+ if (ret < 0 )
738+ return ret ;
739+
740+ ret = clk_prepare_enable (sfc -> clk );
741+ if (ret < 0 )
742+ clk_disable_unprepare (sfc -> hclk );
743+
744+ return ret ;
745+ }
746+ #endif /* CONFIG_PM */
747+
748+ #ifdef CONFIG_PM_SLEEP
749+ static int rockchip_sfc_suspend (struct device * dev )
750+ {
751+ pinctrl_pm_select_sleep_state (dev );
752+
753+ return pm_runtime_force_suspend (dev );
754+ }
755+
756+ static int rockchip_sfc_resume (struct device * dev )
757+ {
758+ struct rockchip_sfc * sfc = dev_get_drvdata (dev );
759+ int ret ;
760+
761+ ret = pm_runtime_force_resume (dev );
762+ if (ret < 0 )
763+ return ret ;
764+
765+ pinctrl_pm_select_default_state (dev );
766+
767+ ret = pm_runtime_get_sync (dev );
768+ if (ret < 0 ) {
769+ pm_runtime_put_noidle (dev );
770+ return ret ;
771+ }
772+
773+ rockchip_sfc_init (sfc );
774+
775+ pm_runtime_mark_last_busy (dev );
776+ pm_runtime_put_autosuspend (dev );
777+
778+ return 0 ;
779+ }
780+ #endif /* CONFIG_PM_SLEEP */
781+
782+ static const struct dev_pm_ops rockchip_sfc_pm_ops = {
783+ SET_RUNTIME_PM_OPS (rockchip_sfc_runtime_suspend ,
784+ rockchip_sfc_runtime_resume , NULL )
785+ SET_SYSTEM_SLEEP_PM_OPS (rockchip_sfc_suspend , rockchip_sfc_resume )
786+ };
787+
681788static const struct of_device_id rockchip_sfc_dt_ids [] = {
682789 { .compatible = "rockchip,sfc" },
683790 { /* sentinel */ }
@@ -688,6 +795,7 @@ static struct platform_driver rockchip_sfc_driver = {
688795 .driver = {
689796 .name = "rockchip-sfc" ,
690797 .of_match_table = rockchip_sfc_dt_ids ,
798+ .pm = & rockchip_sfc_pm_ops ,
691799 },
692800 .probe = rockchip_sfc_probe ,
693801 .remove = rockchip_sfc_remove ,
0 commit comments