Skip to content

Commit 5cb44d9

Browse files
committed
Merge branch 'at91-4.14-trunk/ulp' into linux-4.14-at91
2 parents bcd443f + cba0d57 commit 5cb44d9

5 files changed

Lines changed: 269 additions & 31 deletions

File tree

Documentation/devicetree/bindings/arm/atmel-pmc.txt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,55 @@ Examples:
1212
compatible = "atmel,at91rm9200-pmc";
1313
reg = <0xfffffc00 0x100>;
1414
};
15+
16+
PMC Fast Startup Signals
17+
18+
The PMC Fast Start Signals are used as the wake up source to trigger the PMC
19+
to wake up the system from the ULP1 mode.
20+
21+
required properties:
22+
- compatible: should be "atmel,sama5d2-pmc-fast-startup".
23+
24+
optional properties:
25+
- atmel,wakeup-rtc-timer: boolean to enable RTC alarm wake-up.
26+
- atmel,wakeup-usb-resume: boolean to enable USB resume wake-up.
27+
- atmel,wakeup-sdmmc-cd: boolean to enable SDMMC card detect wake-up.
28+
- atmel,wakeup-rxlp-match: boolean to enable RXLP matching condition wake-up.
29+
- atmel,wakeup-acc-comparison: boolean to enable ACC comparison wake-up.
30+
31+
The node contains child nodes for each wake-up input pin that the platform uses.
32+
33+
Input nodes
34+
35+
Required properties:
36+
- reg: should contain the wake-up input index [0 - 10], to enable
37+
the corresponding wake-up input.
38+
39+
Optional properties:
40+
- atmel,wakeup-active-high: boolean to declare the corresponding wake-up
41+
input described by the child be active high.
42+
The default is to be active low.
43+
44+
Example:
45+
46+
pmc: pmc@f0014000 {
47+
compatible = "atmel,sama5d2-pmc";
48+
reg = <0xf0014000 0x160>;
49+
50+
pmc_fast_restart {
51+
compatible = "atmel,sama5d2-pmc-fast-startup";
52+
#address-cells = <1>;
53+
#size-cells = <0>;
54+
55+
atmel,wakeup-rtc-timer;
56+
57+
wkpin: input@0 {
58+
reg = <0>;
59+
};
60+
61+
gmac_wol: input@10 {
62+
reg = <10>;
63+
atmel,wakeup-active-high;
64+
};
65+
};
66+
};

arch/arm/mach-at91/pm.c

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
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

4244
static 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

4952
static 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
*/
146149
int 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
}
150153
EXPORT_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

554557
struct 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+
609674
void __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

651717
static int __init at91_pm_modes_select(char *str)

arch/arm/mach-at91/pm.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@
2121
#define AT91_MEMCTRL_SDRAMC 1
2222
#define AT91_MEMCTRL_DDRSDR 2
2323

24-
#define AT91_PM_SLOW_CLOCK 0x01
25-
#define AT91_PM_BACKUP 0x02
24+
#define AT91_PM_STANDBY 0x00
25+
#define AT91_PM_ULP0 0x01
26+
#define AT91_PM_ULP1 0x02
27+
#define AT91_PM_BACKUP 0x03
2628

2729
#ifndef __ASSEMBLY__
2830
struct at91_pm_data {

0 commit comments

Comments
 (0)