Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b56c182 authored by Wenyou Yang's avatar Wenyou Yang Committed by Alexandre Belloni
Browse files

ARM: at91: pm: Add ULP1 mode support



In the ULP1 mode, in order to achieve the lowest power consumption
with the system in retention mode and be able to resume on the wake
up events, all the clocks are shut off, inclusive the embedded 12MHz
RC oscillator, and the number of wake up sources is limited as well.
When the wake up event is asserted, the embedded 12MHz RC oscillator
restarts automatically.

The ULP1 (Ultra Low-power mode 1) is introduced by SAMA5D2.

The previous size of pm_suspend.o was 2148 bytes. With the addition of
ULP1 mode the new size of pm_suspend.o raised at 2456 bytes.

Signed-off-by: default avatarWenyou Yang <wenyou.yang@atmel.com>
Signed-off-by: default avatarLudovic Desroches <ludovic.desroches@microchip.com>
[claudiu.beznea@microchip.com: aligned with 4.18-rc1]
Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent 514e2a29
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -42,6 +42,7 @@ extern void at91_pinctrl_gpio_resume(void);
static const match_table_t pm_modes __initconst = {
static const match_table_t pm_modes __initconst = {
	{ AT91_PM_STANDBY, "standby" },
	{ AT91_PM_STANDBY, "standby" },
	{ AT91_PM_ULP0, "ulp0" },
	{ AT91_PM_ULP0, "ulp0" },
	{ AT91_PM_ULP1, "ulp1" },
	{ AT91_PM_BACKUP, "backup" },
	{ AT91_PM_BACKUP, "backup" },
	{ -1, NULL },
	{ -1, NULL },
};
};
+2 −1
Original line number Original line Diff line number Diff line
@@ -23,7 +23,8 @@


#define	AT91_PM_STANDBY		0x00
#define	AT91_PM_STANDBY		0x00
#define AT91_PM_ULP0		0x01
#define AT91_PM_ULP0		0x01
#define	AT91_PM_BACKUP		0x02
#define AT91_PM_ULP1		0x02
#define	AT91_PM_BACKUP		0x03


#ifndef __ASSEMBLY__
#ifndef __ASSEMBLY__
struct at91_pm_data {
struct at91_pm_data {
+122 −20
Original line number Original line Diff line number Diff line
@@ -41,6 +41,15 @@ tmp2 .req r5
	beq	1b
	beq	1b
	.endm
	.endm


/*
 * Wait for main oscillator selection is done
 */
	.macro wait_moscsels
1:	ldr	tmp1, [pmc, #AT91_PMC_SR]
	tst	tmp1, #AT91_PMC_MOSCSELS
	beq	1b
	.endm

/*
/*
 * Wait until PLLA has locked.
 * Wait until PLLA has locked.
 */
 */
@@ -112,19 +121,20 @@ ENTRY(at91_pm_suspend_in_sram)
	bl	at91_sramc_self_refresh
	bl	at91_sramc_self_refresh


	ldr	r0, .pm_mode
	ldr	r0, .pm_mode
	cmp	r0, #AT91_PM_ULP0
	cmp	r0, #AT91_PM_STANDBY
	beq	ulp0_mode
	beq	standby
	cmp	r0, #AT91_PM_BACKUP
	cmp	r0, #AT91_PM_BACKUP
	beq	backup_mode
	beq	backup_mode


	bl	at91_ulp_mode
	b	exit_suspend

standby:
	/* Wait for interrupt */
	/* Wait for interrupt */
	ldr	pmc, .pmc_base
	ldr	pmc, .pmc_base
	at91_cpu_idle
	at91_cpu_idle
	b	exit_suspend
	b	exit_suspend


ulp0_mode:
	bl	at91_ulp0_mode
	b	exit_suspend
backup_mode:
backup_mode:
	bl	at91_backup_mode
	bl	at91_backup_mode
	b	exit_suspend
	b	exit_suspend
@@ -151,7 +161,102 @@ ENTRY(at91_backup_mode)
	str	tmp1, [r0, #0]
	str	tmp1, [r0, #0]
ENDPROC(at91_backup_mode)
ENDPROC(at91_backup_mode)


ENTRY(at91_ulp0_mode)
.macro at91_pm_ulp0_mode
	ldr	pmc, .pmc_base

	/* Turn off the crystal oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	/* Wait for interrupt */
	at91_cpu_idle

	/* Turn on the crystal oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	wait_moscrdy
.endm

/**
 * Note: This procedure only applies on the platform which uses
 * the external crystal oscillator as a main clock source.
 */
.macro at91_pm_ulp1_mode
	ldr	pmc, .pmc_base

	/* Switch the main clock source to 12-MHz RC oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	bic	tmp1, tmp1, #AT91_PMC_MOSCSEL
	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	wait_moscsels

	/* Disable the crystal oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	/* Switch the master clock source to main clock */
	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
	bic	tmp1, tmp1, #AT91_PMC_CSS
	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
	str	tmp1, [pmc, #AT91_PMC_MCKR]

	wait_mckrdy

	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	orr	tmp1, tmp1, #AT91_PMC_WAITMODE
	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	wait_mckrdy

	/* Enable the crystal oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	wait_moscrdy

	/* Switch the master clock source to slow clock */
	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
	bic	tmp1, tmp1, #AT91_PMC_CSS
	str	tmp1, [pmc, #AT91_PMC_MCKR]

	wait_mckrdy

	/* Switch main clock source to crystal oscillator */
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	orr	tmp1, tmp1, #AT91_PMC_MOSCSEL
	bic	tmp1, tmp1, #AT91_PMC_KEY_MASK
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]

	wait_moscsels

	/* Switch the master clock source to main clock */
	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
	bic	tmp1, tmp1, #AT91_PMC_CSS
	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
	str	tmp1, [pmc, #AT91_PMC_MCKR]

	wait_mckrdy
.endm

ENTRY(at91_ulp_mode)
	ldr	pmc, .pmc_base
	ldr	pmc, .pmc_base


	/* Save Master clock setting */
	/* Save Master clock setting */
@@ -174,22 +279,19 @@ ENTRY(at91_ulp0_mode)
	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
	str	tmp1, [pmc, #AT91_CKGR_PLLAR]


	/* Turn off the main oscillator */
	ldr	r0, .pm_mode
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	cmp	r0, #AT91_PM_ULP1
	bic	tmp1, tmp1, #AT91_PMC_MOSCEN
	beq	ulp1_mode
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]


	/* Wait for interrupt */
	at91_pm_ulp0_mode
	at91_cpu_idle
	b	ulp_exit


	/* Turn on the main oscillator */
ulp1_mode:
	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
	at91_pm_ulp1_mode
	orr	tmp1, tmp1, #AT91_PMC_MOSCEN
	b	ulp_exit
	orr	tmp1, tmp1, #AT91_PMC_KEY
	str	tmp1, [pmc, #AT91_CKGR_MOR]


	wait_moscrdy
ulp_exit:
	ldr	pmc, .pmc_base


	/* Restore PLLA setting */
	/* Restore PLLA setting */
	ldr	tmp1, .saved_pllar
	ldr	tmp1, .saved_pllar
@@ -212,7 +314,7 @@ ENTRY(at91_ulp0_mode)
	wait_mckrdy
	wait_mckrdy


	mov	pc, lr
	mov	pc, lr
ENDPROC(at91_ulp0_mode)
ENDPROC(at91_ulp_mode)


/*
/*
 * void at91_sramc_self_refresh(unsigned int is_active)
 * void at91_sramc_self_refresh(unsigned int is_active)
+2 −0
Original line number Original line Diff line number Diff line
@@ -47,8 +47,10 @@
#define	AT91_CKGR_MOR		0x20			/* Main Oscillator Register [not on SAM9RL] */
#define	AT91_CKGR_MOR		0x20			/* Main Oscillator Register [not on SAM9RL] */
#define		AT91_PMC_MOSCEN		(1    <<  0)		/* Main Oscillator Enable */
#define		AT91_PMC_MOSCEN		(1    <<  0)		/* Main Oscillator Enable */
#define		AT91_PMC_OSCBYPASS	(1    <<  1)		/* Oscillator Bypass */
#define		AT91_PMC_OSCBYPASS	(1    <<  1)		/* Oscillator Bypass */
#define		AT91_PMC_WAITMODE	(1    <<  2)		/* Wait Mode Command */
#define		AT91_PMC_MOSCRCEN	(1    <<  3)		/* Main On-Chip RC Oscillator Enable [some SAM9] */
#define		AT91_PMC_MOSCRCEN	(1    <<  3)		/* Main On-Chip RC Oscillator Enable [some SAM9] */
#define		AT91_PMC_OSCOUNT	(0xff <<  8)		/* Main Oscillator Start-up Time */
#define		AT91_PMC_OSCOUNT	(0xff <<  8)		/* Main Oscillator Start-up Time */
#define		AT91_PMC_KEY_MASK	(0xff << 16)
#define		AT91_PMC_KEY		(0x37 << 16)		/* MOR Writing Key */
#define		AT91_PMC_KEY		(0x37 << 16)		/* MOR Writing Key */
#define		AT91_PMC_MOSCSEL	(1    << 24)		/* Main Oscillator Selection [some SAM9] */
#define		AT91_PMC_MOSCSEL	(1    << 24)		/* Main Oscillator Selection [some SAM9] */
#define		AT91_PMC_CFDEN		(1    << 25)		/* Clock Failure Detector Enable [some SAM9] */
#define		AT91_PMC_CFDEN		(1    << 25)		/* Clock Failure Detector Enable [some SAM9] */