/* **************************************************************************** * PUBLIC INTERFACE * * $Workfile: cpu.h $ * $Author: save $ * * Copyright (C) 2002 by OSE Systems. All rights reserved. * **************************************************************************** */ /* **************************************************************************** CONTENTS -------- 1 Description 2 History of development 3 Include files 4 Manifest constants 5 Macros 6 Types 7 Global Functions 8 Process prototypes 9 Global variables **************************************************************************** */ #ifndef _CPU_H #define _CPU_H #ifdef __cplusplus extern "C" { #endif /* **************************************************************************** * 1 DESCRIPTION. **************************************************************************** * CPU specific definitions for the ARM family. * * Contains facilities to manipulate the interrupt mask. These facilities * are available for supervisor processes compiled to 32 bit ARM code, not * for THUMB mode. * * Also contains an architecture dependent structure to report the processor * state at unexpected exceptions. */ /* **************************************************************************** * 2 HISTORY OF DEVELOPMENT. * * 2002.07.17 guek * - Optimize LOCK functions for use in supervisor mode only. * Calls from user mode are ignored, calls from exception * handling modes is a user error. * 2002.03.04 guek * - Hide obsolete LOCK_PUSH, LOCK_POP macros unless * USE_OBSOLETE_LOCK_PUSH defined by caller. * 2001.10.10 kjsv * - Changed macro name, FLUSH_CACHE -> INVALIDATE_CACHE * 2001.09.27 johk * - Added the FLUSH_CACHE macro * * Moved PVCS Rev 1.4 to ClearCase. * */ /* **************************************************************************** * 3 INCLUDE FILES. **************************************************************************** */ #include "osetypes.h" /* **************************************************************************** * 4 MANIFEST CONSTANTS. **************************************************************************** */ /* **************************************************************************** * 5 MACROS. **************************************************************************** */ #define SUPERV_MODE 0x13 /* Supervisor mode bits */ #define IRQ_DISABLE 0x80 /* IRQ interrupt mask */ #define FIQ_DISABLE 0x40 /* FIQ interrupt mask */ /* It may be needed to mask FIQ interrupts when manipulating some obscure * interrupt controllers. In that case, board.c in the BSP must define * BSP_MASK_FIQ. Usually that is not needed as FIQ and IRQ have separate * register sets. */ #ifdef BSP_MASK_FIQ #define ZZLOCKED ((SUPERV_MODE) | (IRQ_DISABLE) | (FIQ_DISABLE)) #else #define ZZLOCKED ((SUPERV_MODE) | (IRQ_DISABLE)) #endif #define ZZUNLOCKED (SUPERV_MODE) /* **************************************************************************** * 6 TYPES. **************************************************************************** */ /* Type that can hold a Machine Status Register. */ typedef U32 Msr; /* Register Dump Struct, used to report Unexpected Exceptions. * The address of the struct ose_regdump is passed in the 'extra' parameter * to the Kernel Error Handler. * * ARM Note: * Note that the ARM architecture contains instructions that can modify * several registers. Some of these registers may be updated before the * exception is taken. See the relevant ARM Processor Core datasheet, * keyword Data Abort Model. */ #define CPU_REGDUMP_MAGIC (0x0001DAEA) /* Current magic number */ typedef struct cpu_mode_reg_bank /* Mode specific core register bank */ { U32 sp; U32 lr; U32 psr; /* current cpsr for user mode, * mode specific spsr for other modes. */ } CPU_REG_BANK; struct cpu_core /* Complete set of core registers */ { U32 r[13]; /* Shared r0-r12 for all modes but FIQ, * FIQ has own set for r8-r12 */ CPU_REG_BANK user; CPU_REG_BANK supervisor; CPU_REG_BANK abort; CPU_REG_BANK undefined; CPU_REG_BANK irq; U32 fiq_r8; U32 fiq_r9; U32 fiq_r10; U32 fiq_r11; U32 fiq_r12; CPU_REG_BANK fiq; }; struct cpu_dumpsection /* Dump section */ { U32 identity; /* Identifies contents of this dump part. * Zero for a set of basic processor core * registers, saved in form of a struct * cpu_core. * Other identities may be allocated to * provide more detailed or processors * specific information in the future. */ U32 size; /* Size of dump part, in bytes */ U32 address; /* Address of dump part (word aligned) */ }; struct cpu_regdump /* Register Dump */ { U32 pc; /* Program counter at exception */ U32 sp; /* Stack pointer at exception */ U32 sr; /* Status register before exception */ U32 vector; /* Exception Vector address offset counted * from the Reset vector */ U32 fault_data_set; /* Nonzero if fault_data_addr is set up */ U32 fault_data_addr; /* Faulting address of data exceptions */ U32 magic; /* Magic number, to handle compatibility */ U32 no_sects; /* Number of parts (Currently one) */ struct cpu_dumpsection sect[1];/* Basic register dump information * (and in the future, more detailed or * processor dependent information) */ }; /* **************************************************************************** * 7 GLOBAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * LOCK_PUSH() Disable IRQ, save old IRQ mask. (OBSOLETE - use LOCK_SAVE) * LOCK_POP() Restore saved IRQ mask. (OBSOLETE - use LOCK_RESTORE) * LOCK() Disable IRQ * UNLOCK() Enable IRQ * LOCK_SAVE(mask) Disable IRQ and save previous IRQ mask in argument * LOCK_RESTORE(mask) Restore IRQ mask from argument * * Note! LOCK_SAVE and LOCK_RESTORE are macros, do not use & operator on * the argument. Use a variable of type 'Msr' for portability. * LOCK_SAVE + LOCK_RESTORE is faster than LOCK_PUSH + LOCK_POP as a * register variable may be used. * * Note! LOCK_PUSH and LOCK_POP are obsolete, and WILL BE REMOVED in the next * release. *=========================================================================== */ #ifdef USE_OBSOLETE_LOCK_PUSH static Msr zzbsp_pushed_lock; /* Saved mask for lock_pop */ #else #define LOCK_PUSH() Define_USE_OBSOLETE_LOCK_PUSH_to_enable_LOCK_PUSH_or_use_LOCK_SAVE() #define LOCK_POP() Define_USE_OBSOLETE_LOCK_PUSH_to_enable_LOCK_POP_or_use_LOCK_RESTORE() #endif /* ARM zzlock_save returns unsigned char for backward compatibility */ unsigned char zzlock_save(Msr new_mask); void zzlock_set(Msr new_mask); #ifndef __lint /* NOT lint */ #ifdef __ARMCC_VERSION /* ARM Ltd toolkits, SDT and ADS */ #ifdef __thumb /* 16 bit THUMB code */ #ifdef USE_OBSOLETE_LOCK_PUSH #define LOCK_PUSH() \ zzbsp_pushed_lock = zzlock_save(ZZLOCKED) #define LOCK_POP() \ zzlock_set(zzbsp_pushed_lock) #endif #define LOCK() \ zzlock_set(ZZLOCKED) #define UNLOCK() \ zzlock_set(ZZUNLOCKED) #define LOCK_SAVE(mask) \ (mask) = zzlock_save(ZZLOCKED) #define LOCK_RESTORE(mask) \ zzlock_set(mask) #else /* 32 bit ARM code - inline */ #ifdef USE_OBSOLETE_LOCK_PUSH #define LOCK_PUSH() \ do \ { \ register Msr sr; \ __asm { MRS sr, CPSR ; \ MSR CPSR_c, ZZLOCKED } \ zzbsp_pushed_lock = sr; \ } while (0) #define LOCK_POP() \ __asm { MSR CPSR_c, zzbsp_pushed_lock } #endif #define LOCK() \ __asm { MSR CPSR_c, ZZLOCKED } #define UNLOCK() \ __asm { MSR CPSR_c, ZZUNLOCKED } /* ARM LOCK_SAVE returns unsigned char for backward compatibility */ #define LOCK_SAVE(mask) \ do \ { \ register unsigned char zzmacro_local_sr; \ __asm { MRS zzmacro_local_sr, CPSR ; \ MSR CPSR_c, ZZLOCKED } \ (mask) = zzmacro_local_sr; \ } while (0) #define LOCK_RESTORE(mask) \ __asm { MSR CPSR_c, (mask) } #endif /* 32 bit ARM code - inline */ #endif /* ARM Ltd, SDT and ADS */ #else /* __lint */ #ifdef USE_OBSOLETE_LOCK_PUSH #define LOCK_PUSH() \ zzbsp_pushed_lock = zzlock_save(ZZLOCKED) #define LOCK_POP() \ zzlock_set(zzbsp_pushed_lock) #endif #define LOCK() \ zzlock_set(ZZLOCKED) #define UNLOCK() \ zzlock_set(ZZUNLOCKED) #define LOCK_SAVE(mask) \ (mask) = zzlock_save(ZZLOCKED) #define LOCK_RESTORE(mask) \ zzlock_set(mask) #endif /* __lint */ /* *=========================================================================== * MEMBAR *=========================================================================== * Description: Issue a memory barrier, force previously issued memory * operations to complete before continuing. * * Parameters: None * * Returns: None * */ #define MEMBAR() /* *=========================================================================== * INVALIDATE_CACHE *=========================================================================== * Description: Automatically identifies the target CPU and depending on * the CPU found applies the following methods of invalidating * the cache/s: * * 720 - (Unified cache) The entire cache is invalidated * 920, 922 - (Harvard cache) D-cache entrys with base addresses * ranging from address to address+length are * invalidated. * 940 - (Harvard cache) The entire D-cache is invalidated * * Parameters: address: Base address to start invalidating cache * length: Number of bytes to invalidate. * * Returns: Nothing. */ #define INVALIDATE_CACHE(address, length) \ do \ { \ register unsigned long zzlocal_idcode; \ register unsigned long zzlocal_tmp = 0; \ __asm { MRC p15, 0, zzlocal_idcode, c0, c0, 0 } \ zzlocal_idcode = ((zzlocal_idcode >> 4) & 0xFFF); \ switch(zzlocal_idcode) \ { \ case 0x720: \ __asm { MCR p15, 0, zzlocal_tmp, c7, c7, 0 } \ break; \ case 0x920: \ case 0x922: \ { \ register unsigned long base = (U32) address; \ register unsigned long limit = (U32) address+length; \ for(; base