Skip to content

Commit 8af11ee

Browse files
committed
Merge tag 'at91-soc-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux into arm/soc
AT91 SoC for 5.10 - ULP0 fast wakeup support - PM cleanups * tag 'at91-soc-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux: ARM: at91: pm: remove unnecessary at91sam9x60_idle ARM: at91: pm: of_node_put() after its usage ARM: at91: pm: add per soc validation of pm modes ARM: at91: pm: add support for ULP0 fast wakeup Link: https://lore.kernel.org/r/20200916211119.GA275438@piout.net Signed-off-by: Olof Johansson <olof@lixom.net>
2 parents 632db90 + faf6dc6 commit 8af11ee

3 files changed

Lines changed: 126 additions & 17 deletions

File tree

arch/arm/mach-at91/pm.c

Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ static struct at91_soc_pm soc_pm = {
5151
};
5252

5353
static const match_table_t pm_modes __initconst = {
54-
{ AT91_PM_STANDBY, "standby" },
55-
{ AT91_PM_ULP0, "ulp0" },
56-
{ AT91_PM_ULP1, "ulp1" },
57-
{ AT91_PM_BACKUP, "backup" },
54+
{ AT91_PM_STANDBY, "standby" },
55+
{ AT91_PM_ULP0, "ulp0" },
56+
{ AT91_PM_ULP0_FAST, "ulp0-fast" },
57+
{ AT91_PM_ULP1, "ulp1" },
58+
{ AT91_PM_BACKUP, "backup" },
5859
{ -1, NULL },
5960
};
6061

@@ -557,11 +558,6 @@ static void at91rm9200_idle(void)
557558
writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
558559
}
559560

560-
static void at91sam9x60_idle(void)
561-
{
562-
cpu_do_idle();
563-
}
564-
565561
static void at91sam9_idle(void)
566562
{
567563
writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
@@ -789,6 +785,51 @@ static const struct of_device_id atmel_pmc_ids[] __initconst = {
789785
{ /* sentinel */ },
790786
};
791787

788+
static void __init at91_pm_modes_validate(const int *modes, int len)
789+
{
790+
u8 i, standby = 0, suspend = 0;
791+
int mode;
792+
793+
for (i = 0; i < len; i++) {
794+
if (standby && suspend)
795+
break;
796+
797+
if (modes[i] == soc_pm.data.standby_mode && !standby) {
798+
standby = 1;
799+
continue;
800+
}
801+
802+
if (modes[i] == soc_pm.data.suspend_mode && !suspend) {
803+
suspend = 1;
804+
continue;
805+
}
806+
}
807+
808+
if (!standby) {
809+
if (soc_pm.data.suspend_mode == AT91_PM_STANDBY)
810+
mode = AT91_PM_ULP0;
811+
else
812+
mode = AT91_PM_STANDBY;
813+
814+
pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
815+
pm_modes[soc_pm.data.standby_mode].pattern,
816+
pm_modes[mode].pattern);
817+
soc_pm.data.standby_mode = mode;
818+
}
819+
820+
if (!suspend) {
821+
if (soc_pm.data.standby_mode == AT91_PM_ULP0)
822+
mode = AT91_PM_STANDBY;
823+
else
824+
mode = AT91_PM_ULP0;
825+
826+
pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
827+
pm_modes[soc_pm.data.suspend_mode].pattern,
828+
pm_modes[mode].pattern);
829+
soc_pm.data.suspend_mode = mode;
830+
}
831+
}
832+
792833
static void __init at91_pm_init(void (*pm_idle)(void))
793834
{
794835
struct device_node *pmc_np;
@@ -800,6 +841,7 @@ static void __init at91_pm_init(void (*pm_idle)(void))
800841

801842
pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
802843
soc_pm.data.pmc = of_iomap(pmc_np, 0);
844+
of_node_put(pmc_np);
803845
if (!soc_pm.data.pmc) {
804846
pr_err("AT91: PM not supported, PMC not found\n");
805847
return;
@@ -830,6 +872,14 @@ void __init at91rm9200_pm_init(void)
830872
if (!IS_ENABLED(CONFIG_SOC_AT91RM9200))
831873
return;
832874

875+
/*
876+
* Force STANDBY and ULP0 mode to avoid calling
877+
* at91_pm_modes_validate() which may increase booting time.
878+
* Platform supports anyway only STANDBY and ULP0 modes.
879+
*/
880+
soc_pm.data.standby_mode = AT91_PM_STANDBY;
881+
soc_pm.data.suspend_mode = AT91_PM_ULP0;
882+
833883
at91_dt_ramc();
834884

835885
/*
@@ -842,12 +892,17 @@ void __init at91rm9200_pm_init(void)
842892

843893
void __init sam9x60_pm_init(void)
844894
{
895+
static const int modes[] __initconst = {
896+
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
897+
};
898+
845899
if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
846900
return;
847901

902+
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
848903
at91_pm_modes_init();
849904
at91_dt_ramc();
850-
at91_pm_init(at91sam9x60_idle);
905+
at91_pm_init(NULL);
851906

852907
soc_pm.ws_ids = sam9x60_ws_ids;
853908
soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
@@ -858,26 +913,46 @@ void __init at91sam9_pm_init(void)
858913
if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
859914
return;
860915

916+
/*
917+
* Force STANDBY and ULP0 mode to avoid calling
918+
* at91_pm_modes_validate() which may increase booting time.
919+
* Platform supports anyway only STANDBY and ULP0 modes.
920+
*/
921+
soc_pm.data.standby_mode = AT91_PM_STANDBY;
922+
soc_pm.data.suspend_mode = AT91_PM_ULP0;
923+
861924
at91_dt_ramc();
862925
at91_pm_init(at91sam9_idle);
863926
}
864927

865928
void __init sama5_pm_init(void)
866929
{
930+
static const int modes[] __initconst = {
931+
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST,
932+
};
933+
867934
if (!IS_ENABLED(CONFIG_SOC_SAMA5))
868935
return;
869936

937+
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
870938
at91_dt_ramc();
871939
at91_pm_init(NULL);
872940
}
873941

874942
void __init sama5d2_pm_init(void)
875943
{
944+
static const int modes[] __initconst = {
945+
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
946+
AT91_PM_BACKUP,
947+
};
948+
876949
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
877950
return;
878951

952+
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
879953
at91_pm_modes_init();
880-
sama5_pm_init();
954+
at91_dt_ramc();
955+
at91_pm_init(NULL);
881956

882957
soc_pm.ws_ids = sama5d2_ws_ids;
883958
soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;

arch/arm/mach-at91/pm.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919

2020
#define AT91_PM_STANDBY 0x00
2121
#define AT91_PM_ULP0 0x01
22-
#define AT91_PM_ULP1 0x02
23-
#define AT91_PM_BACKUP 0x03
22+
#define AT91_PM_ULP0_FAST 0x02
23+
#define AT91_PM_ULP1 0x03
24+
#define AT91_PM_BACKUP 0x04
2425

2526
#ifndef __ASSEMBLY__
2627
struct at91_pm_data {

arch/arm/mach-at91/pm_suspend.S

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,22 @@ ENDPROC(at91_backup_mode)
164164

165165
.macro at91_pm_ulp0_mode
166166
ldr pmc, .pmc_base
167+
ldr tmp2, .pm_mode
168+
ldr tmp3, .mckr_offset
169+
170+
/* Check if ULP0 fast variant has been requested. */
171+
cmp tmp2, #AT91_PM_ULP0_FAST
172+
bne 0f
173+
174+
/* Set highest prescaler for power saving */
175+
ldr tmp1, [pmc, tmp3]
176+
bic tmp1, tmp1, #AT91_PMC_PRES
177+
orr tmp1, tmp1, #AT91_PMC_PRES_64
178+
str tmp1, [pmc, tmp3]
179+
wait_mckrdy
180+
b 1f
167181

182+
0:
168183
/* Turn off the crystal oscillator */
169184
ldr tmp1, [pmc, #AT91_CKGR_MOR]
170185
bic tmp1, tmp1, #AT91_PMC_MOSCEN
@@ -192,7 +207,18 @@ ENDPROC(at91_backup_mode)
192207
/* Wait for interrupt */
193208
1: at91_cpu_idle
194209

195-
/* Restore RC oscillator state */
210+
/* Check if ULP0 fast variant has been requested. */
211+
cmp tmp2, #AT91_PM_ULP0_FAST
212+
bne 5f
213+
214+
/* Set lowest prescaler for fast resume. */
215+
ldr tmp1, [pmc, tmp3]
216+
bic tmp1, tmp1, #AT91_PMC_PRES
217+
str tmp1, [pmc, tmp3]
218+
wait_mckrdy
219+
b 6f
220+
221+
5: /* Restore RC oscillator state */
196222
ldr tmp1, .saved_osc_status
197223
tst tmp1, #AT91_PMC_MOSCRCS
198224
beq 4f
@@ -216,6 +242,7 @@ ENDPROC(at91_backup_mode)
216242
str tmp1, [pmc, #AT91_CKGR_MOR]
217243

218244
wait_moscrdy
245+
6:
219246
.endm
220247

221248
/**
@@ -473,23 +500,29 @@ ENDPROC(at91_backup_mode)
473500
ENTRY(at91_ulp_mode)
474501
ldr pmc, .pmc_base
475502
ldr tmp2, .mckr_offset
503+
ldr tmp3, .pm_mode
476504

477505
/* Save Master clock setting */
478506
ldr tmp1, [pmc, tmp2]
479507
str tmp1, .saved_mckr
480508

481509
/*
482-
* Set the Master clock source to slow clock
510+
* Set master clock source to:
511+
* - MAINCK if using ULP0 fast variant
512+
* - slow clock, otherwise
483513
*/
484514
bic tmp1, tmp1, #AT91_PMC_CSS
515+
cmp tmp3, #AT91_PM_ULP0_FAST
516+
bne save_mck
517+
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
518+
save_mck:
485519
str tmp1, [pmc, tmp2]
486520

487521
wait_mckrdy
488522

489523
at91_plla_disable
490524

491-
ldr r0, .pm_mode
492-
cmp r0, #AT91_PM_ULP1
525+
cmp tmp3, #AT91_PM_ULP1
493526
beq ulp1_mode
494527

495528
at91_pm_ulp0_mode

0 commit comments

Comments
 (0)