AT91 SoC for 5.10
- ULP0 fast wakeup support - PM cleanups -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEycoQi/giopmpPgB12wIijOdRNOUFAl9ifcIACgkQ2wIijOdR NOWb9BAAq25Kz3s3e13oUF2txfvELbYSimWKJF2sMKojekj/RLVZKuxbc8CN0bBR QHQmHroJFdao15RR/IvyrpXmM19eaXQvj+Y0HlGAd5yeNCku2t2vRIkJ35r/PQL5 jZYyttz8ln6LyzZ4zCo7YPPISbIiT899SnO1Fghbu1h/3Wz/b9txDvAxpN1irZr2 oCjcr/Cl1E4DjOrcCEki1ey61XRbHanKYuv0MmG1AcYTCj9/7k8BNDD+UKBjtNUF qtxYCFSCzG6DU0uOA+hue5R1ObZNBQm9fESXyAieswLE/FHOwIh9m0RVqjpgMwFf 1IMZw8YVniPS1PWd0ANPKD4qzVN9GbMn3jjTVqB/K3VqSIq/dVsKA68vZCBopuQe OPPXp5iOAsF9TP17iASif+uK2EDPQABYquSVTJisYh/MZ3PtexpiQXUbm7k3M89q aR2jg4ClkrGq2TmZRysbD2Hng6pSSaiVXpq5D6mCedm9OhAXkBSS0/nqDU78uHT4 bk1rYu9vWCNFoVaz72pqt5oB6h5H4B9Uz99cS1g6C4oI0+iuWJz1ujBtIiZrGcjS QNv9z23wXJfH4WRyrxDj5qAcKxfVamnD3GWDVj35NAUTcjv2C1sdp+4gaZKEG0cB wH+1sz4ueGcx4xqb1WCYnQZI/2nFbAYtBu1v1e55TkLFFEU/xRM= =GtAw -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
8af11ee90c
@ -51,10 +51,11 @@ static struct at91_soc_pm soc_pm = {
|
||||
};
|
||||
|
||||
static const match_table_t pm_modes __initconst = {
|
||||
{ AT91_PM_STANDBY, "standby" },
|
||||
{ AT91_PM_ULP0, "ulp0" },
|
||||
{ AT91_PM_ULP1, "ulp1" },
|
||||
{ AT91_PM_BACKUP, "backup" },
|
||||
{ AT91_PM_STANDBY, "standby" },
|
||||
{ AT91_PM_ULP0, "ulp0" },
|
||||
{ AT91_PM_ULP0_FAST, "ulp0-fast" },
|
||||
{ AT91_PM_ULP1, "ulp1" },
|
||||
{ AT91_PM_BACKUP, "backup" },
|
||||
{ -1, NULL },
|
||||
};
|
||||
|
||||
@ -557,11 +558,6 @@ static void at91rm9200_idle(void)
|
||||
writel(AT91_PMC_PCK, soc_pm.data.pmc + AT91_PMC_SCDR);
|
||||
}
|
||||
|
||||
static void at91sam9x60_idle(void)
|
||||
{
|
||||
cpu_do_idle();
|
||||
}
|
||||
|
||||
static void at91sam9_idle(void)
|
||||
{
|
||||
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 = {
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static void __init at91_pm_modes_validate(const int *modes, int len)
|
||||
{
|
||||
u8 i, standby = 0, suspend = 0;
|
||||
int mode;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (standby && suspend)
|
||||
break;
|
||||
|
||||
if (modes[i] == soc_pm.data.standby_mode && !standby) {
|
||||
standby = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (modes[i] == soc_pm.data.suspend_mode && !suspend) {
|
||||
suspend = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!standby) {
|
||||
if (soc_pm.data.suspend_mode == AT91_PM_STANDBY)
|
||||
mode = AT91_PM_ULP0;
|
||||
else
|
||||
mode = AT91_PM_STANDBY;
|
||||
|
||||
pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
|
||||
pm_modes[soc_pm.data.standby_mode].pattern,
|
||||
pm_modes[mode].pattern);
|
||||
soc_pm.data.standby_mode = mode;
|
||||
}
|
||||
|
||||
if (!suspend) {
|
||||
if (soc_pm.data.standby_mode == AT91_PM_ULP0)
|
||||
mode = AT91_PM_STANDBY;
|
||||
else
|
||||
mode = AT91_PM_ULP0;
|
||||
|
||||
pr_warn("AT91: PM: %s mode not supported! Using %s.\n",
|
||||
pm_modes[soc_pm.data.suspend_mode].pattern,
|
||||
pm_modes[mode].pattern);
|
||||
soc_pm.data.suspend_mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init at91_pm_init(void (*pm_idle)(void))
|
||||
{
|
||||
struct device_node *pmc_np;
|
||||
@ -800,6 +841,7 @@ static void __init at91_pm_init(void (*pm_idle)(void))
|
||||
|
||||
pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
|
||||
soc_pm.data.pmc = of_iomap(pmc_np, 0);
|
||||
of_node_put(pmc_np);
|
||||
if (!soc_pm.data.pmc) {
|
||||
pr_err("AT91: PM not supported, PMC not found\n");
|
||||
return;
|
||||
@ -830,6 +872,14 @@ void __init at91rm9200_pm_init(void)
|
||||
if (!IS_ENABLED(CONFIG_SOC_AT91RM9200))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Force STANDBY and ULP0 mode to avoid calling
|
||||
* at91_pm_modes_validate() which may increase booting time.
|
||||
* Platform supports anyway only STANDBY and ULP0 modes.
|
||||
*/
|
||||
soc_pm.data.standby_mode = AT91_PM_STANDBY;
|
||||
soc_pm.data.suspend_mode = AT91_PM_ULP0;
|
||||
|
||||
at91_dt_ramc();
|
||||
|
||||
/*
|
||||
@ -842,12 +892,17 @@ void __init at91rm9200_pm_init(void)
|
||||
|
||||
void __init sam9x60_pm_init(void)
|
||||
{
|
||||
static const int modes[] __initconst = {
|
||||
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
|
||||
};
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SOC_SAM9X60))
|
||||
return;
|
||||
|
||||
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
|
||||
at91_pm_modes_init();
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(at91sam9x60_idle);
|
||||
at91_pm_init(NULL);
|
||||
|
||||
soc_pm.ws_ids = sam9x60_ws_ids;
|
||||
soc_pm.config_pmc_ws = at91_sam9x60_config_pmc_ws;
|
||||
@ -858,26 +913,46 @@ void __init at91sam9_pm_init(void)
|
||||
if (!IS_ENABLED(CONFIG_SOC_AT91SAM9))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Force STANDBY and ULP0 mode to avoid calling
|
||||
* at91_pm_modes_validate() which may increase booting time.
|
||||
* Platform supports anyway only STANDBY and ULP0 modes.
|
||||
*/
|
||||
soc_pm.data.standby_mode = AT91_PM_STANDBY;
|
||||
soc_pm.data.suspend_mode = AT91_PM_ULP0;
|
||||
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(at91sam9_idle);
|
||||
}
|
||||
|
||||
void __init sama5_pm_init(void)
|
||||
{
|
||||
static const int modes[] __initconst = {
|
||||
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST,
|
||||
};
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SOC_SAMA5))
|
||||
return;
|
||||
|
||||
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(NULL);
|
||||
}
|
||||
|
||||
void __init sama5d2_pm_init(void)
|
||||
{
|
||||
static const int modes[] __initconst = {
|
||||
AT91_PM_STANDBY, AT91_PM_ULP0, AT91_PM_ULP0_FAST, AT91_PM_ULP1,
|
||||
AT91_PM_BACKUP,
|
||||
};
|
||||
|
||||
if (!IS_ENABLED(CONFIG_SOC_SAMA5D2))
|
||||
return;
|
||||
|
||||
at91_pm_modes_validate(modes, ARRAY_SIZE(modes));
|
||||
at91_pm_modes_init();
|
||||
sama5_pm_init();
|
||||
at91_dt_ramc();
|
||||
at91_pm_init(NULL);
|
||||
|
||||
soc_pm.ws_ids = sama5d2_ws_ids;
|
||||
soc_pm.config_shdwc_ws = at91_sama5d2_config_shdwc_ws;
|
||||
|
@ -19,8 +19,9 @@
|
||||
|
||||
#define AT91_PM_STANDBY 0x00
|
||||
#define AT91_PM_ULP0 0x01
|
||||
#define AT91_PM_ULP1 0x02
|
||||
#define AT91_PM_BACKUP 0x03
|
||||
#define AT91_PM_ULP0_FAST 0x02
|
||||
#define AT91_PM_ULP1 0x03
|
||||
#define AT91_PM_BACKUP 0x04
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
struct at91_pm_data {
|
||||
|
@ -164,7 +164,22 @@ ENDPROC(at91_backup_mode)
|
||||
|
||||
.macro at91_pm_ulp0_mode
|
||||
ldr pmc, .pmc_base
|
||||
ldr tmp2, .pm_mode
|
||||
ldr tmp3, .mckr_offset
|
||||
|
||||
/* Check if ULP0 fast variant has been requested. */
|
||||
cmp tmp2, #AT91_PM_ULP0_FAST
|
||||
bne 0f
|
||||
|
||||
/* Set highest prescaler for power saving */
|
||||
ldr tmp1, [pmc, tmp3]
|
||||
bic tmp1, tmp1, #AT91_PMC_PRES
|
||||
orr tmp1, tmp1, #AT91_PMC_PRES_64
|
||||
str tmp1, [pmc, tmp3]
|
||||
wait_mckrdy
|
||||
b 1f
|
||||
|
||||
0:
|
||||
/* Turn off the crystal oscillator */
|
||||
ldr tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
bic tmp1, tmp1, #AT91_PMC_MOSCEN
|
||||
@ -192,7 +207,18 @@ ENDPROC(at91_backup_mode)
|
||||
/* Wait for interrupt */
|
||||
1: at91_cpu_idle
|
||||
|
||||
/* Restore RC oscillator state */
|
||||
/* Check if ULP0 fast variant has been requested. */
|
||||
cmp tmp2, #AT91_PM_ULP0_FAST
|
||||
bne 5f
|
||||
|
||||
/* Set lowest prescaler for fast resume. */
|
||||
ldr tmp1, [pmc, tmp3]
|
||||
bic tmp1, tmp1, #AT91_PMC_PRES
|
||||
str tmp1, [pmc, tmp3]
|
||||
wait_mckrdy
|
||||
b 6f
|
||||
|
||||
5: /* Restore RC oscillator state */
|
||||
ldr tmp1, .saved_osc_status
|
||||
tst tmp1, #AT91_PMC_MOSCRCS
|
||||
beq 4f
|
||||
@ -216,6 +242,7 @@ ENDPROC(at91_backup_mode)
|
||||
str tmp1, [pmc, #AT91_CKGR_MOR]
|
||||
|
||||
wait_moscrdy
|
||||
6:
|
||||
.endm
|
||||
|
||||
/**
|
||||
@ -473,23 +500,29 @@ ENDPROC(at91_backup_mode)
|
||||
ENTRY(at91_ulp_mode)
|
||||
ldr pmc, .pmc_base
|
||||
ldr tmp2, .mckr_offset
|
||||
ldr tmp3, .pm_mode
|
||||
|
||||
/* Save Master clock setting */
|
||||
ldr tmp1, [pmc, tmp2]
|
||||
str tmp1, .saved_mckr
|
||||
|
||||
/*
|
||||
* Set the Master clock source to slow clock
|
||||
* Set master clock source to:
|
||||
* - MAINCK if using ULP0 fast variant
|
||||
* - slow clock, otherwise
|
||||
*/
|
||||
bic tmp1, tmp1, #AT91_PMC_CSS
|
||||
cmp tmp3, #AT91_PM_ULP0_FAST
|
||||
bne save_mck
|
||||
orr tmp1, tmp1, #AT91_PMC_CSS_MAIN
|
||||
save_mck:
|
||||
str tmp1, [pmc, tmp2]
|
||||
|
||||
wait_mckrdy
|
||||
|
||||
at91_plla_disable
|
||||
|
||||
ldr r0, .pm_mode
|
||||
cmp r0, #AT91_PM_ULP1
|
||||
cmp tmp3, #AT91_PM_ULP1
|
||||
beq ulp1_mode
|
||||
|
||||
at91_pm_ulp0_mode
|
||||
|
Loading…
Reference in New Issue
Block a user