This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: StrongARM sleep mode
- From: Andrea Acquaviva <aacquaviva at deis dot unibo dot it>
- To: Nathan J Ickes <nickes at MIT dot EDU>, "ecos-discuss at sources dot redhat dot com" <ecos-discuss at sources dot redhat dot com>
- Date: Thu, 14 Feb 2002 12:09:19 +0100
- Subject: Re: [ECOS] StrongARM sleep mode
- Organization: DEIS
- References: <200202140211.VAA19209@nerd-xing.mit.edu>
Nathan J Ickes wrote:
> I need to support sleep mode on a custom StrongARM board. Has anybody
> done this before?
>
> What I'd like is a function like
>
> void sleep(int time)
>
> that would freeze the OS, set up a RTC alarm, put the system processor
> in sleep mode, and then resurrect the OS once the processor
> returns from sleep.
>
> I notice there is code in the iPAQ vectors.s file that jumps to the
> address in the power manager scratchpad register if it detects that
> the processor is returning from sleep mode. However, I couldn't find
> any other sleep-related code in the SA11x0 tree. Did I miss something?
>
> -- Nathan
>
> --
> Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
> and search the list archive: http://sources.redhat.com/ml/ecos-discuss
I've written some code to support the sleep mode of strongarm. I modified
hal_platform_setup.h and I've partially used the linux code.
The sources are herewith attached. Some code is dedicated to my strongarm
based board, so don't take it as it is.
Andrea.
--
Ing. Andrea Acquaviva
D.E.I.S. - Universita' di Bologna
V.le Risorgimento, 2 40136 BOLOGNA (ITALY)
Tel: (+39) 051 20 93787 Fax: (+39) 051 2093786
#ifndef CYGONCE_HAL_PLATFORM_SETUP_H
#define CYGONC1_HAL_PLATFORM_SETUP_H
/*=============================================================================
//
// hal_platform_setup.h
//
// Platform specific support for HAL (assembly code)
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
// Contributors: gthomas
// Date: 2000-05-08
// Purpose: Intel SA1110/Badge4 platform specific support routines
// Description:
// Usage: #include <cyg/hal/hal_platform_setup.h>
// Only used by "vectors.S"
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
#include <pkgconf/system.h> // System-wide configuration info
#include CYGBLD_HAL_VARIANT_H // Variant (SA11x0) specific configuration
#include CYGBLD_HAL_PLATFORM_H // Platform specific configuration
#include <cyg/hal/hal_sa11x0.h> // Variant specific hardware definitions
#include <cyg/hal/hal_mmu.h> // MMU definitions
#include <cyg/hal/badge4.h> // Platform specific hardware definitions
#if defined(CYG_HAL_STARTUP_ROM)
#define PLATFORM_SETUP1 _platform_setup1
#define CYGHWR_HAL_ARM_HAS_MMU
#if (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 59000)
#define SA11X0_PLL_CLOCK 0x0
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 73700)
#define SA11X0_PLL_CLOCK 0x1
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 88500)
#define SA11X0_PLL_CLOCK 0x2
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 103200)
#define SA11X0_PLL_CLOCK 0x3
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 118000)
#define SA11X0_PLL_CLOCK 0x4
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 132700)
#define SA11X0_PLL_CLOCK 0x5
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 147500)
#define SA11X0_PLL_CLOCK 0x6
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 162200)
#define SA11X0_PLL_CLOCK 0x7
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 176900)
#define SA11X0_PLL_CLOCK 0x8
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 191700)
#define SA11X0_PLL_CLOCK 0x9
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 206400)
#define SA11X0_PLL_CLOCK 0xA
#elif (CYGHWR_HAL_ARM_SA11X0_PROCESSOR_CLOCK == 221200)
#define SA11X0_PLL_CLOCK 0xB
#else
#error Invalid processor clock speed
#endif
/* ANDREA: ADDED THE STATIC MEMORY CONFIGURATION REGISTERS */
#define MSCTL0 (SA11X0_STATIC_CONTROL_0-SA11X0_DRAM_CONFIGURATION)
#define MSCTL1 (SA11X0_STATIC_CONTROL_1-SA11X0_DRAM_CONFIGURATION)
#define MSCTL2 (SA11X0_STATIC_CONTROL_2-SA11X0_DRAM_CONFIGURATION)
#define MDREFR_VALUE ((0x1 & MDREFR_TRASR_mask) | ((0x018 & MDREFR_DRI_mask) << MDREFR_DRI)|(1<<MDREFR_K1DB2)|(1<<MDREFR_E1PIN) | (1<<MDREFR_K1RUN))
#define MDCNFG_VALUE (MDCNFG_DRAM_enable0 | MDCNFG_DRAM_enable1 | MDCNFG_DRAM_type_bank01_Synchronous | MDCNFG_DRAM_data_bus_width_bank01_32bits | MDCNFG_DRAC_12_row_address_bits_bank01 | MDCNFG_DRAM_Rotate_Every_Clock_bank01 | ((0x4 & MDCNFG_TRP0_mask)<<MDCNFG_TRP0) |((0x3 & MDCNFG_TDL0_mask)<<MDCNFG_TDL0) | ((0x3 & MDCNFG_TWR0_mask)<<MDCNFG_TWR0))
#define MDCNFG_VALUE_DIS (MDCNFG_DRAM_type_bank01_Synchronous | MDCNFG_DRAM_data_bus_width_bank01_32bits | MDCNFG_DRAC_12_row_address_bits_bank01 | MDCNFG_DRAM_Rotate_Every_Clock_bank01 | ((0x4 & MDCNFG_TRP0_mask)<<MDCNFG_TRP0) | ((0x3 & MDCNFG_TDL0_mask)<<MDCNFG_TDL0) | ((0x3 & MDCNFG_TWR0_mask)<<MDCNFG_TWR0))
#define EXP_BUS_VALUE (31 << 26) | (31 << 21) | (31 << 16) | (31 << 10) | (31 << 5) | 31
// Initialize GPIOs
#define GPIO_GRER (SA11X0_GPIO_RISING_EDGE_DETECT-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GFER (SA11X0_GPIO_FALLING_EDGE_DETECT-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GAFR (SA11X0_GPIO_ALTERNATE_FUNCTION-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GEDR (SA11X0_GPIO_EDGE_DETECT_STATUS-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GPDR (SA11X0_GPIO_PIN_DIRECTION-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GPCR (SA11X0_GPIO_PIN_OUTPUT_CLEAR-SA11X0_GPIO_PIN_LEVEL)
#define GPIO_GPSR (SA11X0_GPIO_PIN_OUTPUT_SET-SA11X0_GPIO_PIN_LEVEL)
// This macro represents the initial startup code for the platform
.macro _platform_setup1
nop
nop
nop
nop
nop
nop
nop
nop
nop
// Set up GPIO to read hardware configuration
ldr r1,=SA11X0_GPIO_PIN_DIRECTION
ldr r2,=0x0B3E9C00
str r2,[r1]
ldr r3,=SA11X0_GPIO_PIN_OUTPUT_SET
ldr r2,=0x100000 // Bits 20 and 19: enable sodimm 32MB
str r2,[r3] // Requests hardware configuration
// ldr r2,=0x0807A400 // Reconfigure 2..9 as inputs
// str r2,[r1]
ldr r3,=SA11X0_GPIO_PIN_LEVEL
mov r2,#100
10: ldr r9,[r3] // Read multiple times to settle
subs r2,r2,#1
bne 10b
// ldr r2,=0x0807A7FC // Restore proper pin configuration
// str r2,[r1]
// ldr r3,=SA11X0_GPIO_PIN_OUTPUT_SET
// ldr r2,=0x10000 // Enable high power mode
// str r2,[r3]
/* Companion chip initialization */
ldr r3,=SA11X0_GPIO_PIN_OUTPUT_CLEAR
ldr r2,=0x02000000 // Reset SA1111 low
str r2,[r3]
ldr r3,=SA11X0_TUCR
ldr r2,=0x20000400 // enable 3.6864mhz clock output
str r2,[r3]
ldr r3,=SA11X0_GPIO_ALTERNATE_FUNCTION
ldr r2,=0x08600000 // set BREQ, BGNT, CLK_1111 alternate functions
str r2,[r3]
ldr r3,=SA11X0_GPIO_PIN_OUTPUT_SET
ldr r2,=0x02000000 // set reset SA1111 high
str r2,[r3]
ldr r3,=SA1111_CNTRL_REGISTER
ldr r2,=0x00000081 // enable SA1111 PLL and enable PLL
str r2,[r3]
// I moved the following part of initialization for the companion chip in
// devs/sa1111/badge4/current/src/sa1111_badge4.c
/*
mov r2,#1000
11: ldr r9,[r3] // Read multiple times to wait
subs r2,r2,#1
bne 11b
ldr r3,=SA1111_CNTRL_REGISTER
ldr r2,=0x00000083 // enable SA1111 internal clocks
str r2,[r3]
*/
// Initialize peripheral pins:
// input: all serial receive pins
// output: all serial trasmit pins and all LCD pins
/*
ldr r0,=0x00355FFF
ldr r1,=SA11X0_PPC_PIN_DIRECTION
str r0,[r1]
mov r0,#0 // Force initial state
ldr r1,=SA11X0_PPC_PIN_STATE
str r0,[r1]
ldr r1,=SA11X0_PPC_PIN_ASSIGNMENT // Disable any reassignments
str r0,[r1]
*/
// Disable clock switching
mcr p15,0,r0,\
SA11X0_TEST_CLOCK_AND_IDLE_REGISTER,\
SA11X0_DISABLE_CLOCK_SWITCHING_RM,\
SA11X0_DISABLE_CLOCK_SWITCHING_OPCODE
// Set up processor clock
ldr r1,=SA11X0_PWR_MGR_PLL_CONFIG
ldr r2,=SA11X0_PLL_CLOCK
str r2,[r1]
// Turn clock switching back on
mcr p15,0,r0,\
SA11X0_TEST_CLOCK_AND_IDLE_REGISTER,\
SA11X0_ENABLE_CLOCK_SWITCHING_RM,\
SA11X0_ENABLE_CLOCK_SWITCHING_OPCODE
nop
nop
// Pause
ldr r1,=100000
10: sub r1,r1,#1
cmp r1,#0
bne 10b
// Initialize DRAM controller
ldr r1,=dram_table
ldr r2,=__exception_handlers
sub r1,r1,r2
ldr r2,[r1],#4 // First control register
10: ldr r3,[r1],#4
str r3,[r2]
ldr r2,[r1],#4 // Next control register
cmp r2,#0
bne 10b
// Enable UART
ldr r1,=SA1110_GPCLK_CONTROL_0
ldr r2,=SA1110_GPCLK_SUS_UART
str r2,[r1]
/* Configure Static Memory Regs */
/* 88.5 MHz --- 0x0319FF1C FLASH:4ws, SRAM:5ws read, 4ws write */
/* 103.2 MHz --- 0x0321FF1C FLASH:4ws, SRAM:5ws read, 4ws write */
/* 118.0 MHz --- 0x0421FF24 FLASH:5ws, SRAM:5/6ws read, 5ws write */
/* 132.7 MHz --- 0x0429FF24 FLASH:5ws, SRAM:6ws read, 5ws write */
/* 147.5 MHz --- 0x0531FF2C FLASH:6ws, SRAM:7ws read, 6ws write */
/* 162.2 MHz --- 0x0531FF2C FLASH:6ws, SRAM:7ws read, 6ws write */
/* 176.9 MHz --- 0x0639FF34 FLASH:7ws, SRAM:8ws read, 7ws write */
/* 191.7 MHz --- 0x0739FF3C FLASH:7/8ws, SRAM:8ws read, 7/8ws write */
/* 206.4 MHz --- 0x0741FF3C FLASH:8ws, SRAM:9ws read, 8ws write */
/* 221.2 MHz --- 0x0741FF3C FLASH:8ws, SRAM:9ws read, 8ws write */
ldr r1,=SA11X0_DRAM_CONFIGURATION
ldr r0,=0xFFF9FFFC
str r0,[r1,#MSCTL0]
ldr r1,=SA11X0_DRAM_CONFIGURATION
ldr r0,=0xFFF9FFFC
str r0,[r1,#MSCTL1]
ldr r1,=SA11X0_DRAM_CONFIGURATION
ldr r0,=0xFFF9FFF9
str r0,[r1,#MSCTL2]
// Release DRAM hold (set by RESET)
ldr r1,=SA11X0_PWR_MGR_SLEEP_STATUS
ldr r2,=SA11X0_DRAM_CONTROL_HOLD
str r2,[r1]
// Perform 8 reads from unmapped/unenabled DRAM
ldr r1,=SA11X0_RAM_BANK0_BASE
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
ldr r2,[r1]
// Enable DRAM controller
ldr r1,=SA11X0_DRAM_CONFIGURATION
ldr r2,=MDCNFG_VALUE
str r2,[r1]
b 19f
// DRAM controller initialization
dram_table:
.word SA11X0_DRAM0_CAS_0, 0xAAAAAAA7
.word SA11X0_DRAM0_CAS_1, 0xAAAAAAAA
.word SA11X0_DRAM0_CAS_2, 0xAAAAAAAA
.word SA11X0_STATIC_CONTROL_0, 0xFFF9FFFC
.word SA11X0_STATIC_CONTROL_1, 0xFFF9FFFC
.word SA11X0_EXP_BUS_CONFIGURATION, EXP_BUS_VALUE
.word SA11X0_REFRESH_CONFIGURATION, MDREFR_VALUE
.word SA11X0_DRAM2_CAS_0, 0xAAAAAAA7
.word SA11X0_DRAM2_CAS_1, 0xAAAAAAAA
.word SA11X0_DRAM2_CAS_2, 0xAAAAAAAA
.word SA11X0_STATIC_CONTROL_2, 0xFFF9FFFC
.word SA11X0_SMROM_CONFIGURATION, 0xAFCCAFCC // useless value: SMROM Not installed
.word SA11X0_DRAM_CONFIGURATION, MDCNFG_VALUE_DIS // Disabled
.word 0, 0
19:
// Release peripheral hold (set by RESET)
ldr r7,=SA11X0_PWR_MGR_SLEEP_STATUS
ldr r2,=SA11X0_PERIPHERAL_CONTROL_HOLD
str r2,[r7]
// Wakeup from deep sleep mode
ldr r6, [r7]
and r4, r6, #0x1
cmp r4, #0x1
bne 45f
mov r4, #0x1
str r4, [r7]
ldr r7, =SA11X0_PWR_MGR_SCRATCHPAD
ldr r6, [r7]
mov pc, r6
nop
45: nop
// Set up a stack [for calling C code]
ldr r1,=__startup_stack
ldr r2,=SA11X0_RAM_BANK0_BASE
orr sp,r1,r2
// Create MMU tables
bl hal_mmu_init
// Enable MMU
ldr r2,=10f
ldr r1,=MMU_Control_Init|MMU_Control_M
mcr MMU_CP,0,r1,MMU_Control,c0
mov pc,r2 /* Change address spaces */
nop
nop
nop
10:
.endm
#else // defined(CYG_HAL_STARTUP_ROM)
#define PLATFORM_SETUP1
#endif
/*---------------------------------------------------------------------------*/
/* end of hal_platform_setup.h */
#endif /* CYGONCE_HAL_PLATFORM_SETUP_H */
//==========================================================================
//
// powman.c
//
// Power manager module for SmartBadge4
//
//==========================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is 3G Lab Ltd.
// Portions created by 3G Lab are
// Copyright (C) 2000 3G Lab Ltd.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): richard.panton@3glab.com
// Contributors: richard.panton@3glab.com
// Date: 2000-09-13
// Purpose:
// Description: Touchscreen and ADC drivers for the UCB1300 device on the
// Intel Assabet SA1110 development board
//
//
//####DESCRIPTIONEND####
//
//==========================================================================
#include <cyg/kernel/kapi.h>
#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/drv_api.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_sa11x0.h>
#include <cyg/infra/cyg_type.h>
#include <cyg/io/devtab.h>
#include <stdio.h>
#include <pkgconf/powman_badge4.h>
#include <cyg/hal/badge4.h>
#include <assert.h>
static cyg_thread thread;
#define virt_to_phys(x) (x + SA11X0_RAM_BANK0_BASE)
#include "power.h"
extern void cpu_sa1100_resume(void);
extern int cpu_sa1100_do_suspend(void);
extern void cpu_sa1100_cache_clean_invalidate_all(void);
extern void cpu_sa110_data_abort(void);
extern unsigned long *sleep_param; /* virtual address */
extern unsigned long sleep_param_p; /* physical address */
static struct {
cyg_uint32 osmr0, osmr1, osmr2, osmr3, oscr;
cyg_uint32 ower, oier;
cyg_uint32 gpdr, grer, gfer, gafr;
cyg_uint32 icmr, iclr, iccr;
cyg_uint32 ppdr, ppsr, ppar, psdr;
cyg_uint32 ser1utcr0, ser1utcr1, ser1utcr2, ser1utcr3;
cyg_uint32 ser3utcr0, ser3utcr1, ser3utcr2, ser3utcr3;
cyg_uint32 rcnr;
cyg_uint32 tucr;
cyg_uint32 alternatefun;
} sys_ctx;
void
pm_do_sleep() {
unsigned int pspr = 0, program_counter = 0, link_register = 0;
// diag_printf("Entering sleep state\n");
/* set up pointer to sleep parameters */
sleep_param = malloc (SLEEP_PARAM_SIZE*sizeof(long));
sleep_param_p = sleep_param + 0xF0000000;
if (!sleep_param)
return -ENOMEM;
/*
diag_printf("sleep_param_p: 0x%x\n", sleep_param_p);
diag_printf("sleep_param: 0x%x\n", sleep_param);
*/
/* disable interrupts */
cyg_interrupt_disable();
HAL_READ_UINT32(SA11X0_RCNR, sys_ctx.rcnr);
/* save vital registers */
HAL_READ_UINT32(SA11X0_OSMR0, sys_ctx.osmr0);
HAL_READ_UINT32(SA11X0_OSMR1, sys_ctx.osmr1);
HAL_READ_UINT32(SA11X0_OSMR2, sys_ctx.osmr2);
HAL_READ_UINT32(SA11X0_OSMR3, sys_ctx.osmr3);
HAL_READ_UINT32(SA11X0_OSCR, sys_ctx.oscr);
HAL_READ_UINT32(SA11X0_OWER, sys_ctx.ower);
HAL_READ_UINT32(SA11X0_OIER, sys_ctx.oier);
HAL_READ_UINT32(SA11X0_GPIO_PIN_DIRECTION, sys_ctx.gpdr);
HAL_READ_UINT32(SA11X0_GPIO_RISING_EDGE_DETECT, sys_ctx.grer);
HAL_READ_UINT32(SA11X0_GPIO_FALLING_EDGE_DETECT, sys_ctx.gfer);
HAL_READ_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, sys_ctx.gafr);
HAL_READ_UINT32(SA11X0_ICLR, sys_ctx.iclr);
HAL_READ_UINT32(SA11X0_ICMR, sys_ctx.icmr);
HAL_READ_UINT32(SA11X0_ICCR, sys_ctx.iccr);
HAL_READ_UINT32(SA11X0_PPC_PIN_DIRECTION, sys_ctx.ppdr);
HAL_READ_UINT32(SA11X0_PPC_PIN_STATE, sys_ctx.ppsr);
HAL_READ_UINT32(SA11X0_PPC_PIN_ASSIGNMENT, sys_ctx.ppar);
HAL_READ_UINT32(SA11X0_PPC_PIN_SLEEP_MODE_DIR, sys_ctx.psdr);
HAL_READ_UINT32(SA11X0_UART1_CONTROL0, sys_ctx.ser1utcr0);
HAL_READ_UINT32(SA11X0_UART1_CONTROL1, sys_ctx.ser1utcr1);
HAL_READ_UINT32(SA11X0_UART1_CONTROL2, sys_ctx.ser1utcr2);
HAL_READ_UINT32(SA11X0_UART1_CONTROL3, sys_ctx.ser1utcr3);
HAL_READ_UINT32(SA11X0_UART3_CONTROL0, sys_ctx.ser3utcr0);
HAL_READ_UINT32(SA11X0_UART3_CONTROL1, sys_ctx.ser3utcr1);
HAL_READ_UINT32(SA11X0_UART3_CONTROL2, sys_ctx.ser3utcr2);
HAL_READ_UINT32(SA11X0_UART3_CONTROL3, sys_ctx.ser3utcr3);
#ifdef CYGPKG_SA1111_BADGE4
/* Companion chip registers */
HAL_READ_UINT32(SA11X0_TUCR, sys_ctx.tucr);
HAL_READ_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, sys_ctx.alternatefun);
#endif /* CYGPKG_SA1111_BADGE4 */
/*
HAL_WRITE_UINT32(SA11X0_RESET_STATUS, (unsigned int)(SA11X0_HARDWARE_RESET | SA11X0_SOFTWARE_RESET | SA11X0_WATCHDOG_RESET | SA11X0_SLEEP_MODE_RESET ));
*/
/* Clear reset status */
/*
HAL_WRITE_UINT32(SA11X0_PWR_MGR_CONTROL, (unsigned int)(SA11X0_STOP_OSC_DURING_SLEEP | SA11X0_FLOAT_PCMCIA_DURING_SLEEP | SA11X0_FLOAT_CHIPSEL_DURING_SLEEP));
HAL_WRITE_UINT32(SA11X0_PWR_MGR_GPIO_SLEEP_STATE, (unsigned int)(0x00000000));
*/
HAL_WRITE_UINT32(SA11X0_PWR_MGR_WAKEUP_ENABLE, (unsigned int)0x10000);
HAL_WRITE_UINT32(SA11X0_PWR_MGR_SCRATCHPAD, (unsigned int)(virt_to_phys(cpu_sa1100_resume)));
diag_printf("0x%x\n", *SA11X0_PWR_MGR_SCRATCHPAD);
cpu_sa1100_do_suspend();
HAL_WRITE_UINT32(0x08000048, (unsigned int)0x10004);
/* restore registers */
HAL_WRITE_UINT32(SA11X0_GPIO_PIN_DIRECTION, sys_ctx.gpdr);
HAL_WRITE_UINT32(SA11X0_GPIO_RISING_EDGE_DETECT, sys_ctx.grer);
HAL_WRITE_UINT32(SA11X0_GPIO_FALLING_EDGE_DETECT, sys_ctx.gfer);
HAL_WRITE_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, sys_ctx.gafr);
HAL_WRITE_UINT32(SA11X0_UART1_CONTROL0, sys_ctx.ser1utcr0);
HAL_WRITE_UINT32(SA11X0_UART1_CONTROL1, sys_ctx.ser1utcr2);
HAL_WRITE_UINT32(SA11X0_UART1_CONTROL2, sys_ctx.ser1utcr3);
HAL_WRITE_UINT32(SA11X0_UART1_CONTROL3, sys_ctx.ser3utcr0);
HAL_WRITE_UINT32(SA11X0_UART3_CONTROL0, sys_ctx.ser3utcr0);
HAL_WRITE_UINT32(SA11X0_UART3_CONTROL1, sys_ctx.ser3utcr1);
HAL_WRITE_UINT32(SA11X0_UART3_CONTROL2, sys_ctx.ser3utcr2);
HAL_WRITE_UINT32(SA11X0_UART3_CONTROL3, sys_ctx.ser3utcr3);
HAL_WRITE_UINT32(SA11X0_PPC_PIN_DIRECTION, sys_ctx.ppdr);
HAL_WRITE_UINT32(SA11X0_PPC_PIN_STATE, sys_ctx.ppsr);
HAL_WRITE_UINT32(SA11X0_PPC_PIN_ASSIGNMENT, sys_ctx.ppar);
HAL_WRITE_UINT32(SA11X0_PPC_PIN_SLEEP_MODE_DIR, sys_ctx.psdr);
HAL_WRITE_UINT32(SA11X0_OSMR0, sys_ctx.osmr0);
HAL_WRITE_UINT32(SA11X0_OSMR1, sys_ctx.osmr1);
HAL_WRITE_UINT32(SA11X0_OSMR2, sys_ctx.osmr2);
HAL_WRITE_UINT32(SA11X0_OSMR3, sys_ctx.osmr3);
HAL_WRITE_UINT32(SA11X0_OSCR, sys_ctx.oscr);
HAL_WRITE_UINT32(SA11X0_OWER, sys_ctx.ower);
HAL_WRITE_UINT32(SA11X0_OIER, sys_ctx.oier);
HAL_WRITE_UINT32(SA11X0_ICLR, sys_ctx.iclr);
HAL_WRITE_UINT32(SA11X0_ICMR, sys_ctx.icmr);
HAL_WRITE_UINT32(SA11X0_ICCR, sys_ctx.iccr);
#ifdef CYGPKG_SA1111_BADGE4
/* Companion chip registers */
HAL_WRITE_UINT32(SA11X0_TUCR, sys_ctx.tucr);
HAL_WRITE_UINT32(SA11X0_GPIO_ALTERNATE_FUNCTION, sys_ctx.alternatefun);
#endif /* CYGPKG_SA1111_BADGE4 */
cyg_interrupt_enable();
diag_printf("Exiting sleep state\n");
#include "power.h"
#include <cyg/hal/hal_sa11x0.h>
/*
* cpu_sa1100_do_suspend()
*
* Causes sa11x0 to enter sleep state
*
*/
.text
.global sleep_param
.global sleep_param_p
sleep_param: .word 0 @ virtual address of parameter array
sleep_param_p: .word 0 @ physical address of parameter array
ENTRY(cpu_sa1100_do_suspend)
@ save registers on stack
stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, lr}
@ load virtual address for sleep_param array
ldr r0, sleep_param
@ save cpsr
mrs r1, cpsr
str r1, [r0, #(SLEEP_PARAM_CPSR*4)]
@ save register for all modes
@ we are currently in SVC mode
str r13, [r0, #(SLEEP_PARAM_SVC_R13*4)]
str r14, [r0, #(SLEEP_PARAM_SVC_R14*4)]
mrs r1, spsr
str r1, [r0, #(SLEEP_PARAM_SVC_SPSR*4)]
@ usr mode
mrs r3, cpsr @ save for later
bic r1, r3, #0x1F
orr r1, r1, #0xDF
msr cpsr, r1
str r13, [r0, #(SLEEP_PARAM_USER_R13*4)]
str r14, [r0, #(SLEEP_PARAM_USER_R14*4)]
@ abort mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD7
msr cpsr, r1
str r13, [r0, #(SLEEP_PARAM_ABORT_R13*4)]
str r14, [r0, #(SLEEP_PARAM_ABORT_R14*4)]
mrs r1, spsr
str r1, [r0, #(SLEEP_PARAM_ABORT_SPSR*4)]
@ undef mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xDB
msr cpsr, r1
str r13, [r0, #(SLEEP_PARAM_UNDEF_R13*4)]
str r14, [r0, #(SLEEP_PARAM_UNDEF_R14*4)]
mrs r1, spsr
str r1, [r0, #(SLEEP_PARAM_UNDEF_SPSR*4)]
@ irq mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD2
msr cpsr, r1
str r13, [r0, #(SLEEP_PARAM_IRQ_R13*4)]
str r14, [r0, #(SLEEP_PARAM_IRQ_R14*4)]
mrs r1, spsr
str r1, [r0, #(SLEEP_PARAM_IRQ_SPSR*4)]
@ fiq mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD1
msr cpsr, r1
str r8, [r0, #(SLEEP_PARAM_FIQ_R8*4)]
str r9, [r0, #(SLEEP_PARAM_FIQ_R9*4)]
str r10, [r0, #(SLEEP_PARAM_FIQ_R10*4)]
str r11, [r0, #(SLEEP_PARAM_FIQ_R11*4)]
str r12, [r0, #(SLEEP_PARAM_FIQ_R12*4)]
str r13, [r0, #(SLEEP_PARAM_FIQ_R13*4)]
str r14, [r0, #(SLEEP_PARAM_IRQ_R14*4)]
mrs r1, spsr
str r1, [r0, #(SLEEP_PARAM_IRQ_SPSR*4)]
@ go back to svc mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD3
msr cpsr, r1
@ save coprocessor registers
mrc p15, 0, r1, c1, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R1*4)]
mrc p15, 0, r1, c2, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R2*4)]
mrc p15, 0, r1, c3, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R3*4)]
mrc p15, 0, r1, c5, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R5*4)]
mrc p15, 0, r1, c6, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R6*4)]
mrc p15, 0, r1, c13, c0, 0
str r1, [r0, #(SLEEP_PARAM_CP15_R13*4)]
@ clean data cache and invalidate WB
bl cpu_sa1100_cache_clean_invalidate_all
@ disable clock switching
mcr p15, 0, r1, c15, c2, 2
@ save address of sleep_param in r4
mov r0, r4
@ Step 6 set force sleep bit in PMCR
ldr r12, =SA11X0_PWR_MGR_CONTROL
mov r13, #0x1
str r13, [r12]
20:
b 20b @ loop waiting for sleep
/*
@ Adjust memory timing before lowering CPU clock
@ Clock speed ajdustment without changing memory timing makes
@ CPU hang in some cases
ldr r0, =MDREFR
ldr r1, [r0]
orr r1, r1, #MDREFR_K1DB2
str r1, [r0]
@ delay 90us and set CPU PLL to lowest speed
@ fixes resume problem on high speed SA1110
mov r0, #90
bl SYMBOL_NAME(udelay)
ldr r0, =PPCR
mov r1, #0
str r1, [r0]
mov r0, #90
bl SYMBOL_NAME(udelay)
*/
/* setup up register contents for jump to page containing SA1110 SDRAM controller bug fix suspend code
*
* r0 points to MSC0 register
* r1 points to MSC1 register
* r2 points to MSC2 register
* r3 is MSC0 value
* r4 is MSC1 value
* r5 is MSC2 value
* r6 points to MDREFR register
* r7 is first MDREFR value
* r8 is second MDREFR value
* r9 is pointer to MDCNFG register
* r10 is MDCNFG value
* r11 is third MDREFR value
* r12 is pointer to PMCR register
* r13 is PMCR value (1)
*
*/
/*
ldr r0, =MSC0
ldr r1, =MSC1
ldr r2, =MSC2
ldr r3, [r0]
bic r3, r3, #FMsk(MSC_RT)
bic r3, r3, #FMsk(MSC_RT)<<16
ldr r4, [r1]
bic r4, r4, #FMsk(MSC_RT)
bic r4, r4, #FMsk(MSC_RT)<<16
ldr r5, [r2]
bic r5, r5, #FMsk(MSC_RT)
bic r5, r5, #FMsk(MSC_RT)<<16
ldr r6, =MDREFR
ldr r7, [r6]
bic r7, r7, #0x0000FF00
bic r7, r7, #0x000000F0
orr r8, r7, #MDREFR_SLFRSH
ldr r9, =MDCNFG
ldr r10, [r9]
bic r10, r10, #(MDCNFG_DE0+MDCNFG_DE1)
bic r10, r10, #(MDCNFG_DE2+MDCNFG_DE3)
bic r11, r8, #MDREFR_SLFRSH
bic r11, r11, #MDREFR_E1PIN
ldr r12, =PMCR
mov r13, #PMCR_SF
b sa1110_sdram_controller_fix
.align 5
sa1110_sdram_controller_fix:
@ Step 1 clear RT field of all MSCx registers
str r3, [r0]
str r4, [r1]
str r5, [r2]
@ Step 2 clear DRI field in MDREFR
str r7, [r6]
@ Step 3 set SLFRSH bit in MDREFR
str r8, [r6]
@ Step 4 clear DE bis in MDCNFG
str r10, [r9]
@ Step 5 clear DRAM refresh control register
str r11, [r6]
@ Wow, now the hardware suspend request pins can be used, that makes them functional for
@ about 7 ns out of the entire time that the CPU is running!
@ Step 6 set force sleep bit in PMCR
str r13, [r12]
20:
b 20b @ loop waiting for sleep
*/
/*
* cpu_sa1100_resume()
*
* entry point from bootloader into kernel during resume
*
*/
.align 5
ENTRY(cpu_sa1100_resume)
ldr r7, =0x08000024
ldr r8, =0x4
str r8, [r7]
@ load physical address of sleep_param into r0
adr r0, sleep_param_p
ldr r0, [r0]
@ restore cp15_r3, domain id
ldr r1, [r0, #(SLEEP_PARAM_CP15_R3*4)]
mcr p15, 0, r1, c3, c0 ,0
@ restore cp15_r2, translation table base address
ldr r1, [r0, #(SLEEP_PARAM_CP15_R2*4)]
mcr p15, 0, r1, c2, c0 ,0
mov r1, #0
mcr p15, 0, r1, c8, c7, 0 @ flush I+D TLBs
mcr p15, 0, r1, c7, c7, 0 @ flush I&D cache
@ get saved cp15 r1 (control register)
ldr r1, [r0, #(SLEEP_PARAM_CP15_R1*4)]
@ get address to jump to after turning on MMU
ldr r2, =resume_after_mmu
cmp r2, #0
b resume_turn_on_mmu
.align 5
resume_turn_on_mmu:
@ turn on mmu
mcr p15, 0, r1, c1, c0 ,0
@ jump to resume_after_mmu
mov pc, r2
nop
nop
.align 5
resume_after_mmu:
@ load virtual address for sleep_param array
ldr r0, sleep_param
ldr r1, [r0, #(SLEEP_PARAM_CP15_R13*4)]
mcr p15, 0, r1, c13, c0, 0
@ Restore the rest of the CPU state
@ svc
ldr r13, [r0, #(SLEEP_PARAM_SVC_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_SVC_R14*4)]
ldr r1, [r0, #(SLEEP_PARAM_SVC_SPSR*4)]
msr spsr, r1
ldr r7, =0x08000034
ldr r8, =0x4
str r8, [r7]
@ usr
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xDF
msr cpsr, r1
ldr r13, [r0, #(SLEEP_PARAM_USER_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_USER_R14*4)]
@ abort
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD7
msr cpsr, r1
ldr r13, [r0, #(SLEEP_PARAM_ABORT_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_ABORT_R14*4)]
ldr r1, [r0, #(SLEEP_PARAM_ABORT_SPSR*4)]
msr spsr, r1
@ undef
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xDB
msr cpsr, r1
ldr r13, [r0, #(SLEEP_PARAM_UNDEF_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_UNDEF_R14*4)]
ldr r1, [r0, #(SLEEP_PARAM_UNDEF_SPSR*4)]
msr spsr, r0
@ irq
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD2
msr cpsr, r1
ldr r13, [r0, #(SLEEP_PARAM_IRQ_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_IRQ_R14*4)]
ldr r1, [r0, #(SLEEP_PARAM_IRQ_SPSR*4)]
msr spsr, r1
@ fiq
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD1
msr cpsr, r1
ldr r8, [r0, #(SLEEP_PARAM_FIQ_R8*4)]
ldr r9, [r0, #(SLEEP_PARAM_FIQ_R9*4)]
ldr r10, [r0, #(SLEEP_PARAM_FIQ_R10*4)]
ldr r11, [r0, #(SLEEP_PARAM_FIQ_R11*4)]
ldr r12, [r0, #(SLEEP_PARAM_FIQ_R12*4)]
ldr r13, [r0, #(SLEEP_PARAM_FIQ_R13*4)]
ldr r14, [r0, #(SLEEP_PARAM_FIQ_R14*4)]
ldr r1, [r0, #(SLEEP_PARAM_FIQ_SPSR*4)]
msr spsr, r1
ldr r7, =0x08000008
ldr r8, =0x4
str r8, [r7]
@ switch to svc mode
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0xD3
msr cpsr, r1
ldr r7, =0x0800000c
ldr r8, =0x4
str r8, [r7]
@ Restore rest of Coprocessor state
ldr r1, [r0, #(SLEEP_PARAM_CP15_R5*4)]
mcr p15, 0, r1, c5, c0 ,0
ldr r1, [r0, #(SLEEP_PARAM_CP15_R6*4)]
mcr p15, 0, r1, c6, c0 ,0
ldr r7, =0x08000014
ldr r8, =0x4
str r8, [r7]
@ restore cpsr
ldr r1, [r0, #(SLEEP_PARAM_CPSR*4)]
msr cpsr, r1
ldr r7, =0x08000064
ldr r8, =0x4
str r8, [r7]
ldr r7, =0x08000068
mov r8, lr
str r8, [r7]
@ return to caller
ldmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12}
mov pc, lr
// ldr pc, =0x20dc0
/*
* suspend defines
*
*/
#define SLEEP_PARAM_USER_R0 0
#define SLEEP_PARAM_USER_R1 1
#define SLEEP_PARAM_USER_R2 2
#define SLEEP_PARAM_USER_R3 3
#define SLEEP_PARAM_USER_R4 4
#define SLEEP_PARAM_USER_R5 5
#define SLEEP_PARAM_USER_R6 6
#define SLEEP_PARAM_USER_R7 7
#define SLEEP_PARAM_USER_R8 8
#define SLEEP_PARAM_USER_R9 9
#define SLEEP_PARAM_USER_R10 10
#define SLEEP_PARAM_USER_R11 11
#define SLEEP_PARAM_USER_R12 12
#define SLEEP_PARAM_USER_R13 13
#define SLEEP_PARAM_USER_R14 14
#define SLEEP_PARAM_PC 15
#define SLEEP_PARAM_SVC_R13 16
#define SLEEP_PARAM_SVC_R14 17
#define SLEEP_PARAM_ABORT_R13 18
#define SLEEP_PARAM_ABORT_R14 19
#define SLEEP_PARAM_UNDEF_R13 20
#define SLEEP_PARAM_UNDEF_R14 21
#define SLEEP_PARAM_IRQ_R13 22
#define SLEEP_PARAM_IRQ_R14 23
#define SLEEP_PARAM_FIQ_R8 24
#define SLEEP_PARAM_FIQ_R9 25
#define SLEEP_PARAM_FIQ_R10 26
#define SLEEP_PARAM_FIQ_R11 27
#define SLEEP_PARAM_FIQ_R12 28
#define SLEEP_PARAM_FIQ_R13 29
#define SLEEP_PARAM_FIQ_R14 30
#define SLEEP_PARAM_CPSR 31
#define SLEEP_PARAM_SVC_SPSR 32
#define SLEEP_PARAM_ABORT_SPSR 33
#define SLEEP_PARAM_UNDEF_SPSR 34
#define SLEEP_PARAM_IRQ_SPSR 35
#define SLEEP_PARAM_FIQ_SPSR 36
#define SLEEP_PARAM_CP15_R1 37
#define SLEEP_PARAM_CP15_R2 38
#define SLEEP_PARAM_CP15_R3 39
#define SLEEP_PARAM_CP15_R5 40
#define SLEEP_PARAM_CP15_R6 41
#define SLEEP_PARAM_CP15_R13 42
#define SLEEP_PARAM_SIZE (SLEEP_PARAM_CP15_R13 + 1)
#define __ALIGN .align 0
#define __ALIGN_STR ".align 0"
#define ALIGN __ALIGN
#define ALIGN_STR __ALIGN_STR
#define SYMBOL_NAME(X) X
#define SYMBOL_NAME_LABEL(X) X/**/:
#define ENTRY(name) \
.globl SYMBOL_NAME(name); \
ALIGN; \
SYMBOL_NAME_LABEL(name)
#define MODE_MASK 0x03
#define F_BIT (1 << 26)
#define I_BIT (1 << 27)
/* Flushing areas */
#define FLUSH_BASE 0xe0000000 /* SA1100 zero bank */
/* Resource list defines */
#define TOT_RESOURCES 2
#define TOT_APPLICATIONS 2
#define AVAIL_FREQ 11
--
Before posting, please read the FAQ: http://sources.redhat.com/fom/ecos
and search the list archive: http://sources.redhat.com/ml/ecos-discuss