mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-22 17:33:01 +00:00
23be4be5a6
To simply the PM code, the suspend to standby mode uses same sram function as the suspend to memory mode, running in the internal SRAM, instead of the respective code for each mode. For the suspend to standby mode, the master clock doesn't switch to the slow clock, and PLLA and the main oscillator doesn't turn off as well. Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com> Tested-by: Sylvain Rochet <sylvain.rochet@finsecur.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
119 lines
3.2 KiB
C
119 lines
3.2 KiB
C
/*
|
|
* AT91 Power Management
|
|
*
|
|
* Copyright (C) 2005 David Brownell
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*/
|
|
#ifndef __ARCH_ARM_MACH_AT91_PM
|
|
#define __ARCH_ARM_MACH_AT91_PM
|
|
|
|
#include <asm/proc-fns.h>
|
|
|
|
#include <mach/at91_ramc.h>
|
|
|
|
#define AT91_PM_MEMTYPE_MASK 0x0f
|
|
|
|
#define AT91_PM_MODE_OFFSET 4
|
|
#define AT91_PM_MODE_MASK 0x01
|
|
#define AT91_PM_MODE(x) (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET)
|
|
|
|
#define AT91_PM_SLOW_CLOCK 0x01
|
|
|
|
/*
|
|
* The AT91RM9200 goes into self-refresh mode with this command, and will
|
|
* terminate self-refresh automatically on the next SDRAM access.
|
|
*
|
|
* Self-refresh mode is exited as soon as a memory access is made, but we don't
|
|
* know for sure when that happens. However, we need to restore the low-power
|
|
* mode if it was enabled before going idle. Restoring low-power mode while
|
|
* still in self-refresh is "not recommended", but seems to work.
|
|
*/
|
|
|
|
#ifndef __ASSEMBLY__
|
|
static inline void at91rm9200_standby(void)
|
|
{
|
|
u32 lpr = at91_ramc_read(0, AT91RM9200_SDRAMC_LPR);
|
|
|
|
asm volatile(
|
|
"b 1f\n\t"
|
|
".align 5\n\t"
|
|
"1: mcr p15, 0, %0, c7, c10, 4\n\t"
|
|
" str %0, [%1, %2]\n\t"
|
|
" str %3, [%1, %4]\n\t"
|
|
" mcr p15, 0, %0, c7, c0, 4\n\t"
|
|
" str %5, [%1, %2]"
|
|
:
|
|
: "r" (0), "r" (at91_ramc_base[0]), "r" (AT91RM9200_SDRAMC_LPR),
|
|
"r" (1), "r" (AT91RM9200_SDRAMC_SRR),
|
|
"r" (lpr));
|
|
}
|
|
|
|
/* We manage both DDRAM/SDRAM controllers, we need more than one value to
|
|
* remember.
|
|
*/
|
|
static inline void at91_ddr_standby(void)
|
|
{
|
|
/* Those two values allow us to delay self-refresh activation
|
|
* to the maximum. */
|
|
u32 lpr0, lpr1 = 0;
|
|
u32 saved_lpr0, saved_lpr1 = 0;
|
|
|
|
if (at91_ramc_base[1]) {
|
|
saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
|
|
lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
|
|
lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
|
|
}
|
|
|
|
saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
|
|
lpr0 = saved_lpr0 & ~AT91_DDRSDRC_LPCB;
|
|
lpr0 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
|
|
|
|
/* self-refresh mode now */
|
|
at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
|
|
if (at91_ramc_base[1])
|
|
at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
|
|
|
|
cpu_do_idle();
|
|
|
|
at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
|
|
if (at91_ramc_base[1])
|
|
at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
|
|
}
|
|
|
|
/* We manage both DDRAM/SDRAM controllers, we need more than one value to
|
|
* remember.
|
|
*/
|
|
static inline void at91sam9_sdram_standby(void)
|
|
{
|
|
u32 lpr0, lpr1 = 0;
|
|
u32 saved_lpr0, saved_lpr1 = 0;
|
|
|
|
if (at91_ramc_base[1]) {
|
|
saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
|
|
lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
|
|
lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
|
|
}
|
|
|
|
saved_lpr0 = at91_ramc_read(0, AT91_SDRAMC_LPR);
|
|
lpr0 = saved_lpr0 & ~AT91_SDRAMC_LPCB;
|
|
lpr0 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
|
|
|
|
/* self-refresh mode now */
|
|
at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
|
|
if (at91_ramc_base[1])
|
|
at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
|
|
|
|
cpu_do_idle();
|
|
|
|
at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
|
|
if (at91_ramc_base[1])
|
|
at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
|
|
}
|
|
|
|
#endif
|
|
#endif
|