1919#include <linux/suspend.h>
2020
2121#include <linux/clk/at91_pmc.h>
22+ #include <linux/mfd/syscon.h>
23+ #include <linux/regmap.h>
2224
2325#include <asm/cacheflush.h>
2426#include <asm/fncpy.h>
@@ -40,15 +42,16 @@ extern void at91_pinctrl_gpio_resume(void);
4042#endif
4143
4244static const match_table_t pm_modes __initconst = {
43- { 0 , "standby" },
44- { AT91_PM_SLOW_CLOCK , "ulp0" },
45+ { AT91_PM_STANDBY , "standby" },
46+ { AT91_PM_ULP0 , "ulp0" },
47+ { AT91_PM_ULP1 , "ulp1" },
4548 { AT91_PM_BACKUP , "backup" },
4649 { -1 , NULL },
4750};
4851
4952static struct at91_pm_data pm_data = {
50- .standby_mode = 0 ,
51- .suspend_mode = AT91_PM_SLOW_CLOCK ,
53+ .standby_mode = AT91_PM_STANDBY ,
54+ .suspend_mode = AT91_PM_ULP0 ,
5255};
5356
5457#define at91_ramc_read (id , field ) \
@@ -145,7 +148,7 @@ static int at91_pm_verify_clocks(void)
145148 */
146149int at91_suspend_entering_slow_clock (void )
147150{
148- return (pm_data .mode >= AT91_PM_SLOW_CLOCK );
151+ return (pm_data .mode >= AT91_PM_ULP0 );
149152}
150153EXPORT_SYMBOL (at91_suspend_entering_slow_clock );
151154
@@ -186,7 +189,7 @@ static void at91_pm_suspend(suspend_state_t state)
186189 * event sources; and reduces DRAM power. But otherwise it's identical to
187190 * PM_SUSPEND_ON: cpu idle, and nothing fancy done with main or cpu clocks.
188191 *
189- * AT91_PM_SLOW_CLOCK is like STANDBY plus slow clock mode, so drivers must
192+ * AT91_PM_ULP0 is like STANDBY plus slow clock mode, so drivers must
190193 * suspend more deeply, the master clock switches to the clk32k and turns off
191194 * the main oscillator
192195 *
@@ -204,7 +207,7 @@ static int at91_pm_enter(suspend_state_t state)
204207 /*
205208 * Ensure that clocks are in a valid state.
206209 */
207- if (( pm_data .mode >= AT91_PM_SLOW_CLOCK ) &&
210+ if (pm_data .mode >= AT91_PM_ULP0 &&
208211 !at91_pm_verify_clocks ())
209212 goto error ;
210213
@@ -546,9 +549,9 @@ static void __init at91_pm_backup_init(void)
546549 pm_data .sfrbu = NULL ;
547550
548551 if (pm_data .standby_mode == AT91_PM_BACKUP )
549- pm_data .standby_mode = AT91_PM_SLOW_CLOCK ;
552+ pm_data .standby_mode = AT91_PM_ULP0 ;
550553 if (pm_data .suspend_mode == AT91_PM_BACKUP )
551- pm_data .suspend_mode = AT91_PM_SLOW_CLOCK ;
554+ pm_data .suspend_mode = AT91_PM_ULP0 ;
552555}
553556
554557struct pmc_info {
@@ -606,6 +609,68 @@ static void __init at91_pm_init(void (*pm_idle)(void))
606609 }
607610}
608611
612+ static int __init at91_pmc_fast_startup_init (void )
613+ {
614+ struct device_node * np , * cnp ;
615+ struct regmap * regmap ;
616+ u32 input , input_mask ;
617+ u32 mode = 0 , polarity = 0 ;
618+
619+ np = of_find_compatible_node (NULL , NULL ,
620+ "atmel,sama5d2-pmc-fast-startup" );
621+ if (!np )
622+ return - ENODEV ;
623+
624+ regmap = syscon_node_to_regmap (of_get_parent (np ));
625+ if (IS_ERR (regmap )) {
626+ pr_info ("AT91: failed to find PMC fast startup node\n" );
627+ return PTR_ERR (regmap );
628+ }
629+
630+ for_each_child_of_node (np , cnp ) {
631+ if (of_property_read_u32 (cnp , "reg" , & input )) {
632+ pr_warn ("AT91: reg property is missing for %s\n" ,
633+ cnp -> full_name );
634+ continue ;
635+ }
636+
637+ input_mask = 1 << input ;
638+ if (!(input_mask & AT91_PMC_FS_INPUT_MASK )) {
639+ pr_warn ("AT91: wake-up input %d out of range\n" , input );
640+ continue ;
641+ }
642+ mode |= input_mask ;
643+
644+ if (of_property_read_bool (cnp , "atmel,wakeup-active-high" ))
645+ polarity |= input_mask ;
646+ }
647+
648+ if (of_property_read_bool (np , "atmel,wakeup-rtc-timer" ))
649+ mode |= AT91_PMC_RTCAL ;
650+
651+ if (of_property_read_bool (np , "atmel,wakeup-usb-resume" ))
652+ mode |= AT91_PMC_USBAL ;
653+
654+ if (of_property_read_bool (np , "atmel,wakeup-sdmmc-cd" ))
655+ mode |= AT91_PMC_SDMMC_CD ;
656+
657+ if (of_property_read_bool (np , "atmel,wakeup-rxlp-match" ))
658+ mode |= AT91_PMC_RXLP_MCE ;
659+
660+ if (of_property_read_bool (np , "atmel,wakeup-acc-comparison" ))
661+ mode |= AT91_PMC_ACC_CE ;
662+
663+ pr_debug ("AT91: mode = 0x%x, ploarity = 0%x\n" , mode , polarity );
664+
665+ regmap_write (regmap , AT91_PMC_FSMR , mode );
666+
667+ regmap_write (regmap , AT91_PMC_FSPR , polarity );
668+
669+ of_node_put (np );
670+
671+ return 0 ;
672+ }
673+
609674void __init at91rm9200_pm_init (void )
610675{
611676 if (!IS_ENABLED (CONFIG_SOC_AT91RM9200 ))
@@ -646,6 +711,7 @@ void __init sama5d2_pm_init(void)
646711
647712 at91_pm_backup_init ();
648713 sama5_pm_init ();
714+ at91_pmc_fast_startup_init ();
649715}
650716
651717static int __init at91_pm_modes_select (char * str )
0 commit comments