This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: StrongARM sleep mode


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]