avr32: Power Management support ("standby" and "mem" modes)
Implement Standby support. In this mode, we'll suspend all drivers, put the SDRAM in self-refresh mode and switch off the HSB bus ("frozen" mode.) Implement Suspend-to-mem support. In this mode, we suspend all drivers, put the SDRAM into self-refresh mode and switch off all internal clocks except the 32 kHz oscillator ("stop" mode.) The lowest-level suspend code runs from a small portion of SRAM allocated at startup time. This gets rid of a small potential race with the SDRAM where we might try to enter self-refresh mode in the middle of an icache burst. We also relocate all interrupt and exception handlers to SRAM during the small window when we enter and exit the low-power modes. We don't need to do any special tricks to start and stop the PLL. The main clock is automatically gated by hardware until the PLL is stable. Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
This commit is contained in:
parent
aa8e87ca61
commit
02a00cf672
8 changed files with 496 additions and 1 deletions
|
@ -205,6 +205,11 @@ endmenu
|
||||||
|
|
||||||
menu "Power management options"
|
menu "Power management options"
|
||||||
|
|
||||||
|
source "kernel/power/Kconfig"
|
||||||
|
|
||||||
|
config ARCH_SUSPEND_POSSIBLE
|
||||||
|
def_bool y
|
||||||
|
|
||||||
menu "CPU Frequency scaling"
|
menu "CPU Frequency scaling"
|
||||||
|
|
||||||
source "drivers/cpufreq/Kconfig"
|
source "drivers/cpufreq/Kconfig"
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o
|
obj-y += pdc.o clock.o intc.o extint.o pio.o hsmc.o
|
||||||
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
|
obj-$(CONFIG_CPU_AT32AP700X) += at32ap700x.o pm-at32ap700x.o
|
||||||
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
|
obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o
|
||||||
|
obj-$(CONFIG_PM) += pm.o
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_PM_DEBUG),y)
|
||||||
|
CFLAGS_pm.o += -DDEBUG
|
||||||
|
endif
|
||||||
|
|
|
@ -22,6 +22,10 @@ struct intc {
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
struct irq_chip chip;
|
struct irq_chip chip;
|
||||||
struct sys_device sysdev;
|
struct sys_device sysdev;
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
unsigned long suspend_ipr;
|
||||||
|
unsigned long saved_ipr[64];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct platform_device at32_intc0_device;
|
extern struct platform_device at32_intc0_device;
|
||||||
|
@ -138,8 +142,56 @@ void __init init_IRQ(void)
|
||||||
panic("Interrupt controller initialization failed!\n");
|
panic("Interrupt controller initialization failed!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
void intc_set_suspend_handler(unsigned long offset)
|
||||||
|
{
|
||||||
|
intc0.suspend_ipr = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intc_suspend(struct sys_device *sdev, pm_message_t state)
|
||||||
|
{
|
||||||
|
struct intc *intc = container_of(sdev, struct intc, sysdev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (unlikely(!irqs_disabled())) {
|
||||||
|
pr_err("intc_suspend: called with interrupts enabled\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlikely(!intc->suspend_ipr)) {
|
||||||
|
pr_err("intc_suspend: suspend_ipr not initialized\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++) {
|
||||||
|
intc->saved_ipr[i] = intc_readl(intc, INTPR0 + 4 * i);
|
||||||
|
intc_writel(intc, INTPR0 + 4 * i, intc->suspend_ipr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intc_resume(struct sys_device *sdev)
|
||||||
|
{
|
||||||
|
struct intc *intc = container_of(sdev, struct intc, sysdev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
WARN_ON(!irqs_disabled());
|
||||||
|
|
||||||
|
for (i = 0; i < 64; i++)
|
||||||
|
intc_writel(intc, INTPR0 + 4 * i, intc->saved_ipr[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define intc_suspend NULL
|
||||||
|
#define intc_resume NULL
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct sysdev_class intc_class = {
|
static struct sysdev_class intc_class = {
|
||||||
.name = "intc",
|
.name = "intc",
|
||||||
|
.suspend = intc_suspend,
|
||||||
|
.resume = intc_resume,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init intc_init_sysdev(void)
|
static int __init intc_init_sysdev(void)
|
||||||
|
|
|
@ -12,6 +12,12 @@
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
#include <asm/arch/pm.h>
|
#include <asm/arch/pm.h>
|
||||||
|
|
||||||
|
#include "pm.h"
|
||||||
|
#include "sdramc.h"
|
||||||
|
|
||||||
|
/* Same as 0xfff00000 but fits in a 21 bit signed immediate */
|
||||||
|
#define PM_BASE -0x100000
|
||||||
|
|
||||||
.section .bss, "wa", @nobits
|
.section .bss, "wa", @nobits
|
||||||
.global disable_idle_sleep
|
.global disable_idle_sleep
|
||||||
.type disable_idle_sleep, @object
|
.type disable_idle_sleep, @object
|
||||||
|
@ -64,3 +70,105 @@ cpu_idle_skip_sleep:
|
||||||
unmask_interrupts
|
unmask_interrupts
|
||||||
retal r12
|
retal r12
|
||||||
.size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
|
.size cpu_idle_skip_sleep, . - cpu_idle_skip_sleep
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
.section .init.text, "ax", @progbits
|
||||||
|
|
||||||
|
.global pm_exception
|
||||||
|
.type pm_exception, @function
|
||||||
|
pm_exception:
|
||||||
|
/*
|
||||||
|
* Exceptions are masked when we switch to this handler, so
|
||||||
|
* we'll only get "unrecoverable" exceptions (offset 0.)
|
||||||
|
*/
|
||||||
|
sub r12, pc, . - .Lpanic_msg
|
||||||
|
lddpc pc, .Lpanic_addr
|
||||||
|
|
||||||
|
.align 2
|
||||||
|
.Lpanic_addr:
|
||||||
|
.long panic
|
||||||
|
.Lpanic_msg:
|
||||||
|
.asciz "Unrecoverable exception during suspend\n"
|
||||||
|
.size pm_exception, . - pm_exception
|
||||||
|
|
||||||
|
.global pm_irq0
|
||||||
|
.type pm_irq0, @function
|
||||||
|
pm_irq0:
|
||||||
|
/* Disable interrupts and return after the sleep instruction */
|
||||||
|
mfsr r9, SYSREG_RSR_INT0
|
||||||
|
mtsr SYSREG_RAR_INT0, r8
|
||||||
|
sbr r9, SYSREG_GM_OFFSET
|
||||||
|
mtsr SYSREG_RSR_INT0, r9
|
||||||
|
rete
|
||||||
|
|
||||||
|
/*
|
||||||
|
* void cpu_enter_standby(unsigned long sdramc_base)
|
||||||
|
*
|
||||||
|
* Enter PM_SUSPEND_STANDBY mode. At this point, all drivers
|
||||||
|
* are suspended and interrupts are disabled. Interrupts
|
||||||
|
* marked as 'wakeup' event sources may still come along and
|
||||||
|
* get us out of here.
|
||||||
|
*
|
||||||
|
* The SDRAM will be put into self-refresh mode (which does
|
||||||
|
* not require a clock from the CPU), and the CPU will be put
|
||||||
|
* into "frozen" mode (HSB bus stopped). The SDRAM controller
|
||||||
|
* will automatically bring the SDRAM into normal mode on the
|
||||||
|
* first access, and the power manager will automatically
|
||||||
|
* start the HSB and CPU clocks upon a wakeup event.
|
||||||
|
*
|
||||||
|
* This code uses the same "skip sleep" technique as above.
|
||||||
|
* It is very important that we jump directly to
|
||||||
|
* cpu_after_sleep after the sleep instruction since that's
|
||||||
|
* where we'll end up if the interrupt handler decides that we
|
||||||
|
* need to skip the sleep instruction.
|
||||||
|
*/
|
||||||
|
.global pm_standby
|
||||||
|
.type pm_standby, @function
|
||||||
|
pm_standby:
|
||||||
|
/*
|
||||||
|
* interrupts are already masked at this point, and EVBA
|
||||||
|
* points to pm_exception above.
|
||||||
|
*/
|
||||||
|
ld.w r10, r12[SDRAMC_LPR]
|
||||||
|
sub r8, pc, . - 1f /* return address for irq handler */
|
||||||
|
mov r11, SDRAMC_LPR_LPCB_SELF_RFR
|
||||||
|
bfins r10, r11, 0, 2 /* LPCB <- self Refresh */
|
||||||
|
sync 0 /* flush write buffer */
|
||||||
|
st.w r12[SDRAMC_LPR], r11 /* put SDRAM in self-refresh mode */
|
||||||
|
ld.w r11, r12[SDRAMC_LPR]
|
||||||
|
unmask_interrupts
|
||||||
|
sleep CPU_SLEEP_FROZEN
|
||||||
|
1: mask_interrupts
|
||||||
|
retal r12
|
||||||
|
.size pm_standby, . - pm_standby
|
||||||
|
|
||||||
|
.global pm_suspend_to_ram
|
||||||
|
.type pm_suspend_to_ram, @function
|
||||||
|
pm_suspend_to_ram:
|
||||||
|
/*
|
||||||
|
* interrupts are already masked at this point, and EVBA
|
||||||
|
* points to pm_exception above.
|
||||||
|
*/
|
||||||
|
mov r11, 0
|
||||||
|
cache r11[2], 8 /* clean all dcache lines */
|
||||||
|
sync 0 /* flush write buffer */
|
||||||
|
ld.w r10, r12[SDRAMC_LPR]
|
||||||
|
sub r8, pc, . - 1f /* return address for irq handler */
|
||||||
|
mov r11, SDRAMC_LPR_LPCB_SELF_RFR
|
||||||
|
bfins r10, r11, 0, 2 /* LPCB <- self refresh */
|
||||||
|
st.w r12[SDRAMC_LPR], r10 /* put SDRAM in self-refresh mode */
|
||||||
|
ld.w r11, r12[SDRAMC_LPR]
|
||||||
|
|
||||||
|
unmask_interrupts
|
||||||
|
sleep CPU_SLEEP_STOP
|
||||||
|
1: mask_interrupts
|
||||||
|
|
||||||
|
retal r12
|
||||||
|
.size pm_suspend_to_ram, . - pm_suspend_to_ram
|
||||||
|
|
||||||
|
.global pm_sram_end
|
||||||
|
.type pm_sram_end, @function
|
||||||
|
pm_sram_end:
|
||||||
|
.size pm_sram_end, 0
|
||||||
|
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
|
|
245
arch/avr32/mach-at32ap/pm.c
Normal file
245
arch/avr32/mach-at32ap/pm.c
Normal file
|
@ -0,0 +1,245 @@
|
||||||
|
/*
|
||||||
|
* AVR32 AP Power Management
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Atmel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/suspend.h>
|
||||||
|
#include <linux/vmalloc.h>
|
||||||
|
|
||||||
|
#include <asm/cacheflush.h>
|
||||||
|
#include <asm/sysreg.h>
|
||||||
|
|
||||||
|
#include <asm/arch/pm.h>
|
||||||
|
#include <asm/arch/sram.h>
|
||||||
|
|
||||||
|
/* FIXME: This is only valid for AP7000 */
|
||||||
|
#define SDRAMC_BASE 0xfff03800
|
||||||
|
|
||||||
|
#include "sdramc.h"
|
||||||
|
|
||||||
|
#define SRAM_PAGE_FLAGS (SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1) \
|
||||||
|
| SYSREG_BF(AP, 3) | SYSREG_BIT(G))
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned long pm_sram_start;
|
||||||
|
static size_t pm_sram_size;
|
||||||
|
static struct vm_struct *pm_sram_area;
|
||||||
|
|
||||||
|
static void (*avr32_pm_enter_standby)(unsigned long sdramc_base);
|
||||||
|
static void (*avr32_pm_enter_str)(unsigned long sdramc_base);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called with interrupts disabled. Exceptions will be masked
|
||||||
|
* on return (i.e. all exceptions will be "unrecoverable".)
|
||||||
|
*/
|
||||||
|
static void *avr32_pm_map_sram(void)
|
||||||
|
{
|
||||||
|
unsigned long vaddr;
|
||||||
|
unsigned long page_addr;
|
||||||
|
u32 tlbehi;
|
||||||
|
u32 mmucr;
|
||||||
|
|
||||||
|
vaddr = (unsigned long)pm_sram_area->addr;
|
||||||
|
page_addr = pm_sram_start & PAGE_MASK;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mask exceptions and grab the first TLB entry. We won't be
|
||||||
|
* needing it while sleeping.
|
||||||
|
*/
|
||||||
|
asm volatile("ssrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
|
||||||
|
|
||||||
|
mmucr = sysreg_read(MMUCR);
|
||||||
|
tlbehi = sysreg_read(TLBEHI);
|
||||||
|
sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
|
||||||
|
|
||||||
|
tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
|
||||||
|
tlbehi |= vaddr & PAGE_MASK;
|
||||||
|
tlbehi |= SYSREG_BIT(TLBEHI_V);
|
||||||
|
|
||||||
|
sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS);
|
||||||
|
sysreg_write(TLBEHI, tlbehi);
|
||||||
|
__builtin_tlbw();
|
||||||
|
|
||||||
|
return (void *)(vaddr + pm_sram_start - page_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Must be called with interrupts disabled. Exceptions will be
|
||||||
|
* unmasked on return.
|
||||||
|
*/
|
||||||
|
static void avr32_pm_unmap_sram(void)
|
||||||
|
{
|
||||||
|
u32 mmucr;
|
||||||
|
u32 tlbehi;
|
||||||
|
u32 tlbarlo;
|
||||||
|
|
||||||
|
/* Going to update TLB entry at index 0 */
|
||||||
|
mmucr = sysreg_read(MMUCR);
|
||||||
|
tlbehi = sysreg_read(TLBEHI);
|
||||||
|
sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr));
|
||||||
|
|
||||||
|
/* Clear the "valid" bit */
|
||||||
|
tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi));
|
||||||
|
sysreg_write(TLBEHI, tlbehi);
|
||||||
|
|
||||||
|
/* Mark it as "not accessed" */
|
||||||
|
tlbarlo = sysreg_read(TLBARLO);
|
||||||
|
sysreg_write(TLBARLO, tlbarlo | 0x80000000U);
|
||||||
|
|
||||||
|
/* Update the TLB */
|
||||||
|
__builtin_tlbw();
|
||||||
|
|
||||||
|
/* Unmask exceptions */
|
||||||
|
asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int avr32_pm_valid_state(suspend_state_t state)
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case PM_SUSPEND_ON:
|
||||||
|
case PM_SUSPEND_STANDBY:
|
||||||
|
case PM_SUSPEND_MEM:
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int avr32_pm_enter(suspend_state_t state)
|
||||||
|
{
|
||||||
|
u32 lpr_saved;
|
||||||
|
u32 evba_saved;
|
||||||
|
void *sram;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case PM_SUSPEND_STANDBY:
|
||||||
|
sram = avr32_pm_map_sram();
|
||||||
|
|
||||||
|
/* Switch to in-sram exception handlers */
|
||||||
|
evba_saved = sysreg_read(EVBA);
|
||||||
|
sysreg_write(EVBA, (unsigned long)sram);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the LPR register so that we can re-enable
|
||||||
|
* SDRAM Low Power mode on resume.
|
||||||
|
*/
|
||||||
|
lpr_saved = sdramc_readl(LPR);
|
||||||
|
pr_debug("%s: Entering standby...\n", __func__);
|
||||||
|
avr32_pm_enter_standby(SDRAMC_BASE);
|
||||||
|
sdramc_writel(LPR, lpr_saved);
|
||||||
|
|
||||||
|
/* Switch back to regular exception handlers */
|
||||||
|
sysreg_write(EVBA, evba_saved);
|
||||||
|
|
||||||
|
avr32_pm_unmap_sram();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_SUSPEND_MEM:
|
||||||
|
sram = avr32_pm_map_sram();
|
||||||
|
|
||||||
|
/* Switch to in-sram exception handlers */
|
||||||
|
evba_saved = sysreg_read(EVBA);
|
||||||
|
sysreg_write(EVBA, (unsigned long)sram);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save the LPR register so that we can re-enable
|
||||||
|
* SDRAM Low Power mode on resume.
|
||||||
|
*/
|
||||||
|
lpr_saved = sdramc_readl(LPR);
|
||||||
|
pr_debug("%s: Entering suspend-to-ram...\n", __func__);
|
||||||
|
avr32_pm_enter_str(SDRAMC_BASE);
|
||||||
|
sdramc_writel(LPR, lpr_saved);
|
||||||
|
|
||||||
|
/* Switch back to regular exception handlers */
|
||||||
|
sysreg_write(EVBA, evba_saved);
|
||||||
|
|
||||||
|
avr32_pm_unmap_sram();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PM_SUSPEND_ON:
|
||||||
|
pr_debug("%s: Entering idle...\n", __func__);
|
||||||
|
cpu_enter_idle();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pr_debug("%s: Invalid suspend state %d\n", __func__, state);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("%s: wakeup\n", __func__);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_suspend_ops avr32_pm_ops = {
|
||||||
|
.valid = avr32_pm_valid_state,
|
||||||
|
.enter = avr32_pm_enter,
|
||||||
|
};
|
||||||
|
|
||||||
|
static unsigned long avr32_pm_offset(void *symbol)
|
||||||
|
{
|
||||||
|
extern u8 pm_exception[];
|
||||||
|
|
||||||
|
return (unsigned long)symbol - (unsigned long)pm_exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init avr32_pm_init(void)
|
||||||
|
{
|
||||||
|
extern u8 pm_exception[];
|
||||||
|
extern u8 pm_irq0[];
|
||||||
|
extern u8 pm_standby[];
|
||||||
|
extern u8 pm_suspend_to_ram[];
|
||||||
|
extern u8 pm_sram_end[];
|
||||||
|
void *dst;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* To keep things simple, we depend on not needing more than a
|
||||||
|
* single page.
|
||||||
|
*/
|
||||||
|
pm_sram_size = avr32_pm_offset(pm_sram_end);
|
||||||
|
if (pm_sram_size > PAGE_SIZE)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pm_sram_start = sram_alloc(pm_sram_size);
|
||||||
|
if (!pm_sram_start)
|
||||||
|
goto err_alloc_sram;
|
||||||
|
|
||||||
|
/* Grab a virtual area we can use later on. */
|
||||||
|
pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP);
|
||||||
|
if (!pm_sram_area)
|
||||||
|
goto err_vm_area;
|
||||||
|
pm_sram_area->phys_addr = pm_sram_start;
|
||||||
|
|
||||||
|
local_irq_disable();
|
||||||
|
dst = avr32_pm_map_sram();
|
||||||
|
memcpy(dst, pm_exception, pm_sram_size);
|
||||||
|
flush_dcache_region(dst, pm_sram_size);
|
||||||
|
invalidate_icache_region(dst, pm_sram_size);
|
||||||
|
avr32_pm_unmap_sram();
|
||||||
|
local_irq_enable();
|
||||||
|
|
||||||
|
avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby);
|
||||||
|
avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram);
|
||||||
|
intc_set_suspend_handler(avr32_pm_offset(pm_irq0));
|
||||||
|
|
||||||
|
suspend_set_ops(&avr32_pm_ops);
|
||||||
|
|
||||||
|
printk("AVR32 AP Power Management enabled\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_vm_area:
|
||||||
|
sram_free(pm_sram_start, pm_sram_size);
|
||||||
|
err_alloc_sram:
|
||||||
|
err:
|
||||||
|
pr_err("AVR32 Power Management initialization failed\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
arch_initcall(avr32_pm_init);
|
76
arch/avr32/mach-at32ap/sdramc.h
Normal file
76
arch/avr32/mach-at32ap/sdramc.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Register definitions for the AT32AP SDRAM Controller
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 Atmel Corporation
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* version 2 as published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Register offsets */
|
||||||
|
#define SDRAMC_MR 0x0000
|
||||||
|
#define SDRAMC_TR 0x0004
|
||||||
|
#define SDRAMC_CR 0x0008
|
||||||
|
#define SDRAMC_HSR 0x000c
|
||||||
|
#define SDRAMC_LPR 0x0010
|
||||||
|
#define SDRAMC_IER 0x0014
|
||||||
|
#define SDRAMC_IDR 0x0018
|
||||||
|
#define SDRAMC_IMR 0x001c
|
||||||
|
#define SDRAMC_ISR 0x0020
|
||||||
|
#define SDRAMC_MDR 0x0024
|
||||||
|
|
||||||
|
/* MR - Mode Register */
|
||||||
|
#define SDRAMC_MR_MODE_NORMAL ( 0 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_NOP ( 1 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_BANKS_PRECHARGE ( 2 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_LOAD_MODE ( 3 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_AUTO_REFRESH ( 4 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_EXT_LOAD_MODE ( 5 << 0)
|
||||||
|
#define SDRAMC_MR_MODE_POWER_DOWN ( 6 << 0)
|
||||||
|
|
||||||
|
/* CR - Configuration Register */
|
||||||
|
#define SDRAMC_CR_NC_8_BITS ( 0 << 0)
|
||||||
|
#define SDRAMC_CR_NC_9_BITS ( 1 << 0)
|
||||||
|
#define SDRAMC_CR_NC_10_BITS ( 2 << 0)
|
||||||
|
#define SDRAMC_CR_NC_11_BITS ( 3 << 0)
|
||||||
|
#define SDRAMC_CR_NR_11_BITS ( 0 << 2)
|
||||||
|
#define SDRAMC_CR_NR_12_BITS ( 1 << 2)
|
||||||
|
#define SDRAMC_CR_NR_13_BITS ( 2 << 2)
|
||||||
|
#define SDRAMC_CR_NB_2_BANKS ( 0 << 4)
|
||||||
|
#define SDRAMC_CR_NB_4_BANKS ( 1 << 4)
|
||||||
|
#define SDRAMC_CR_CAS(x) ((x) << 5)
|
||||||
|
#define SDRAMC_CR_DBW_32_BITS ( 0 << 7)
|
||||||
|
#define SDRAMC_CR_DBW_16_BITS ( 1 << 7)
|
||||||
|
#define SDRAMC_CR_TWR(x) ((x) << 8)
|
||||||
|
#define SDRAMC_CR_TRC(x) ((x) << 12)
|
||||||
|
#define SDRAMC_CR_TRP(x) ((x) << 16)
|
||||||
|
#define SDRAMC_CR_TRCD(x) ((x) << 20)
|
||||||
|
#define SDRAMC_CR_TRAS(x) ((x) << 24)
|
||||||
|
#define SDRAMC_CR_TXSR(x) ((x) << 28)
|
||||||
|
|
||||||
|
/* HSR - High Speed Register */
|
||||||
|
#define SDRAMC_HSR_DA ( 1 << 0)
|
||||||
|
|
||||||
|
/* LPR - Low Power Register */
|
||||||
|
#define SDRAMC_LPR_LPCB_INHIBIT ( 0 << 0)
|
||||||
|
#define SDRAMC_LPR_LPCB_SELF_RFR ( 1 << 0)
|
||||||
|
#define SDRAMC_LPR_LPCB_PDOWN ( 2 << 0)
|
||||||
|
#define SDRAMC_LPR_LPCB_DEEP_PDOWN ( 3 << 0)
|
||||||
|
#define SDRAMC_LPR_PASR(x) ((x) << 4)
|
||||||
|
#define SDRAMC_LPR_TCSR(x) ((x) << 8)
|
||||||
|
#define SDRAMC_LPR_DS(x) ((x) << 10)
|
||||||
|
#define SDRAMC_LPR_TIMEOUT(x) ((x) << 12)
|
||||||
|
|
||||||
|
/* IER/IDR/IMR/ISR - Interrupt Enable/Disable/Mask/Status Register */
|
||||||
|
#define SDRAMC_ISR_RES ( 1 << 0)
|
||||||
|
|
||||||
|
/* MDR - Memory Device Register */
|
||||||
|
#define SDRAMC_MDR_MD_SDRAM ( 0 << 0)
|
||||||
|
#define SDRAMC_MDR_MD_LOW_PWR_SDRAM ( 1 << 0)
|
||||||
|
|
||||||
|
/* Register access macros */
|
||||||
|
#define sdramc_readl(reg) \
|
||||||
|
__raw_readl((void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
|
||||||
|
#define sdramc_writel(reg, value) \
|
||||||
|
__raw_writel(value, (void __iomem __force *)SDRAMC_BASE + SDRAMC_##reg)
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
extern void cpu_enter_idle(void);
|
extern void cpu_enter_idle(void);
|
||||||
|
extern void cpu_enter_standby(unsigned long sdramc_base);
|
||||||
|
|
||||||
extern bool disable_idle_sleep;
|
extern bool disable_idle_sleep;
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ static inline void cpu_idle_sleep(void)
|
||||||
else
|
else
|
||||||
cpu_enter_idle();
|
cpu_enter_idle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void intc_set_suspend_handler(unsigned long offset);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* __ASM_AVR32_ARCH_PM_H */
|
#endif /* __ASM_AVR32_ARCH_PM_H */
|
||||||
|
|
|
@ -88,6 +88,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||||
#define TIF_MEMDIE 6
|
#define TIF_MEMDIE 6
|
||||||
#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal */
|
#define TIF_RESTORE_SIGMASK 7 /* restore signal mask in do_signal */
|
||||||
#define TIF_CPU_GOING_TO_SLEEP 8 /* CPU is entering sleep 0 mode */
|
#define TIF_CPU_GOING_TO_SLEEP 8 /* CPU is entering sleep 0 mode */
|
||||||
|
#define TIF_FREEZE 29
|
||||||
#define TIF_DEBUG 30 /* debugging enabled */
|
#define TIF_DEBUG 30 /* debugging enabled */
|
||||||
#define TIF_USERSPACE 31 /* true if FS sets userspace */
|
#define TIF_USERSPACE 31 /* true if FS sets userspace */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue