Skip to content

Commit

Permalink
[ARM] 3430/1: ARM: OMAP: 5/8 Update PM
Browse files Browse the repository at this point in the history
Patch from Tony Lindgren

Update OMAP PM code from linux-omap tree:

- Move PM code from plat-omap to mach-omap1 and mach-omap2
  by Tony Lindgren
- Add minimal PM support for omap24xx by Tony Lindgren and
  Richard Woodruff
- Misc updates to omap1 PM code by Tuukka Tikkanen et al
- Updates to the SRAM code needed for PM and FB by Imre Deak

Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Tony Lindgren authored and Russell King committed Apr 2, 2006
1 parent 6e60e79 commit 670c104
Show file tree
Hide file tree
Showing 9 changed files with 1,354 additions and 51 deletions.
770 changes: 770 additions & 0 deletions arch/arm/mach-omap1/pm.c

Large diffs are not rendered by default.

111 changes: 92 additions & 19 deletions arch/arm/plat-omap/sleep.S → arch/arm/mach-omap1/sleep.S
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* linux/arch/arm/plat-omap/sleep.S
* linux/arch/arm/mach-omap1/sleep.S
*
* Low-level OMAP730/1510/1610 sleep/wakeUp support
*
Expand Down Expand Up @@ -383,68 +383,141 @@ ENTRY(omap1610_cpu_suspend)
mcr p15, 0, r0, c7, c10, 4
nop

@ load base address of Traffic Controller
@ Load base address of Traffic Controller
mov r6, #TCMIF_ASM_BASE & 0xff000000
orr r6, r6, #TCMIF_ASM_BASE & 0x00ff0000
orr r6, r6, #TCMIF_ASM_BASE & 0x0000ff00

@ prepare to put SDRAM into self-refresh manually
@ Prepare to put SDRAM into self-refresh manually
ldr r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
orr r9, r7, #SELF_REFRESH_MODE & 0xff000000
orr r9, r9, #SELF_REFRESH_MODE & 0x000000ff
str r9, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]

@ prepare to put EMIFS to Sleep
@ Prepare to put EMIFS to Sleep
ldr r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]
orr r9, r8, #IDLE_EMIFS_REQUEST & 0xff
str r9, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]

@ load base address of ARM_IDLECT1 and ARM_IDLECT2
@ Load base address of ARM_IDLECT1 and ARM_IDLECT2
mov r4, #CLKGEN_REG_ASM_BASE & 0xff000000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x00ff0000
orr r4, r4, #CLKGEN_REG_ASM_BASE & 0x0000ff00

@ turn off clock domains
@ do not disable PERCK (0x04)
@ Turn off clock domains
@ Do not disable PERCK (0x04)
mov r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff
orr r5, r5, #OMAP1610_IDLECT2_SLEEP_VAL & 0xff00
strh r5, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]

@ request ARM idle
@ Request ARM idle
mov r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff
orr r3, r3, #OMAP1610_IDLECT1_SLEEP_VAL & 0xff00
strh r3, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]

@ disable instruction cache
mrc p15, 0, r9, c1, c0, 0
bic r2, r9, #0x1000
mcr p15, 0, r2, c1, c0, 0
nop

/*
* Let's wait for the next wake up event to wake us up. r0 can't be
* used here because r0 holds ARM_IDLECT1
*/
mov r2, #0
mcr p15, 0, r2, c7, c0, 4 @ wait for interrupt

@ Errata (HEL3SU467, section 1.4.4) specifies nop-instructions
@ according to this formula:
@ 2 + (4*DPLL_MULT)/DPLL_DIV/ARMDIV
@ Max DPLL_MULT = 18
@ DPLL_DIV = 1
@ ARMDIV = 1
@ => 74 nop-instructions
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @10
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @20
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @30
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @40
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @50
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @60
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop @70
nop
nop
nop
nop @74
/*
* omap1610_cpu_suspend()'s resume point.
*
* It will just start executing here, so we'll restore stuff from the
* stack.
*/
@ re-enable Icache
mcr p15, 0, r9, c1, c0, 0

@ reset the ARM_IDLECT1 and ARM_IDLECT2.
@ Restore the ARM_IDLECT1 and ARM_IDLECT2.
strh r1, [r4, #ARM_IDLECT2_ASM_OFFSET & 0xff]
strh r0, [r4, #ARM_IDLECT1_ASM_OFFSET & 0xff]

@ Restore EMIFF controls
str r7, [r6, #EMIFF_SDRAM_CONFIG_ASM_OFFSET & 0xff]
str r8, [r6, #EMIFS_CONFIG_ASM_OFFSET & 0xff]

@ restore regs and return
@ Restore regs and return
ldmfd sp!, {r0 - r12, pc}

ENTRY(omap1610_cpu_suspend_sz)
Expand Down
149 changes: 149 additions & 0 deletions arch/arm/mach-omap2/pm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* linux/arch/arm/mach-omap2/pm.c
*
* OMAP2 Power Management Routines
*
* Copyright (C) 2006 Nokia Corporation
* Tony Lindgren <tony@atomide.com>
*
* Copyright (C) 2005 Texas Instruments, Inc.
* Richard Woodruff <r-woodruff2@ti.com>
*
* Based on pm.c for omap1
*
* 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/pm.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/pm.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/module.h>

#include <asm/io.h>
#include <asm/irq.h>
#include <asm/atomic.h>
#include <asm/mach/time.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h>

#include <asm/arch/irqs.h>
#include <asm/arch/clock.h>
#include <asm/arch/sram.h>
#include <asm/arch/pm.h>

static struct clk *vclk;
static void (*omap2_sram_idle)(void);
static void (*omap2_sram_suspend)(int dllctrl, int cpu_rev);
static void (*saved_idle)(void);

void omap2_pm_idle(void)
{
local_irq_disable();
local_fiq_disable();
if (need_resched()) {
local_fiq_enable();
local_irq_enable();
return;
}

/*
* Since an interrupt may set up a timer, we don't want to
* reprogram the hardware timer with interrupts enabled.
* Re-enable interrupts only after returning from idle.
*/
timer_dyn_reprogram();

omap2_sram_idle();
local_fiq_enable();
local_irq_enable();
}

static int omap2_pm_prepare(suspend_state_t state)
{
int error = 0;

/* We cannot sleep in idle until we have resumed */
saved_idle = pm_idle;
pm_idle = NULL;

switch (state)
{
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
break;

case PM_SUSPEND_DISK:
return -ENOTSUPP;

default:
return -EINVAL;
}

return error;
}

static int omap2_pm_enter(suspend_state_t state)
{
switch (state)
{
case PM_SUSPEND_STANDBY:
case PM_SUSPEND_MEM:
/* FIXME: Add suspend */
break;

case PM_SUSPEND_DISK:
return -ENOTSUPP;

default:
return -EINVAL;
}

return 0;
}

static int omap2_pm_finish(suspend_state_t state)
{
pm_idle = saved_idle;
return 0;
}

static struct pm_ops omap_pm_ops = {
.pm_disk_mode = 0,
.prepare = omap2_pm_prepare,
.enter = omap2_pm_enter,
.finish = omap2_pm_finish,
};

int __init omap2_pm_init(void)
{
printk("Power Management for TI OMAP.\n");

vclk = clk_get(NULL, "virt_prcm_set");
if (IS_ERR(vclk)) {
printk(KERN_ERR "Could not get PM vclk\n");
return -ENODEV;
}

/*
* We copy the assembler sleep/wakeup routines to SRAM.
* These routines need to be in SRAM as that's the only
* memory the MPU can see when it wakes up.
*/
omap2_sram_idle = omap_sram_push(omap24xx_idle_loop_suspend,
omap24xx_idle_loop_suspend_sz);

omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
omap24xx_cpu_suspend_sz);

pm_set_ops(&omap_pm_ops);
pm_idle = omap2_pm_idle;

return 0;
}

__initcall(omap2_pm_init);
Loading

0 comments on commit 670c104

Please sign in to comment.