/*
    cpu.h, Copyright (c) by Silvio Dragone & David Reist,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public Licence.
 
    A full copy of the GNU GPL is provided in the file COPYING found in the 
    development root of Topsy.
*/
/*
	
	File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Topsy/sa1100/cpu.h,v $
 	Author(s):             Silvio Dragone, David Reist
 	Affiliation:           ETH Zuerich, TIK
 	Version:               $Revision: 2922 $
 	Creation Date:         
 	Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $      by: $Author: baderma $
 
*/


/* available memory */
#define SRAM_AVAIL                              (2*1024*1024)               /*   2MB */
#define DRAM_AVAIL                              (32*1024*1024)              /*  32MB */
#define FLASH_AVAIL                             (2*1024*1024)               /*   2MB */
#define PHYSRAM                                 (SRAM_AVAIL + SRAM_AVAIL)   /*  34MB */

/* memory layout of the 4GB virtual address space */

/* physical memory layout */

/* SA1100 core memory bases */
#define DRAM_BASE                               0xC0000000       /* Physical DRAM (SDRAM)                           */
#define ATU_BASE                                0xB0000000       /* AMBA Translation Unit                           */
#define SA_CORE_SYSTEM_BASE                     0x90000000       /* SA1100 Core System Registers                    */
#define PCI_CONF_BASE                           0x42000000       /* Local PCI Configuration Space and PCI Unit CSRs */
#define PCI_BASE                                0x40000000       /* PCI Unit                                        */
#define SLOW_PORT_BASE                          0x38400000       /* Slow Port                                       */
#define SRAM_BASE                               0x10000000       /* Physical SRAM                                   */
#define UENGBASE															  0xB0000000       /* uEng xfer & csr & fbi */
#define SCRATCH_BASE														0xB0044000			 /* Scratch DRAM */
#define FLASH_BASE                              0x00000000       /* Flash Memory, DO NOT WRITE TO!!!                */

/* SA1100 additional memory bases*/
#define ZEROS_BASE                              0xE0000000       /* 128MB region returning 0 when read, user/kernel space */
#define ROM_BASE                                FLASH_BASE       /* boot ROM, DO NOT WRITE TO!!!                          */

/* Bootstack */
#define BOOTSTACK                               0xC0100000  /* let's brake things */
#define STEALALLOC                              0xC1000000	/* XXX */

/* virtual memory layout */

/* DRAM */
#define	K0SEG_BASE				(DRAM_BASE + 1*1024*1024)   /* mapped to DRAM_BASE + 1MB            */
#define	K0SEG_SIZE				(1*1024*1024)               /* 1MB    kernel cached                 */
#define	K1SEG_BASE				(DRAM_BASE + 2*1024*1024)   /* mapped to DRAM_BASE + 2MB            */
#define	K1SEG_SIZE				(1*1024*1024)               /* 1MB    kernel uncached               */
#define	K2SEG_BASE				(DRAM_BASE + 3*1024*1024)   /* mapped to DRAM_BASE + 3MB            */
#define	K2SEG_SIZE				(1*1024*1024)               /* 1MB    kernel mapped, cached         */
#define	KUSEG_BASE				(DRAM_BASE + 4*1024*1024)   /* mapped to DRAM_BASE + 4MB            */
#define	KUSEG_SIZE				(1*1024*1024)               /* 1MB    kernel/user mapped, cacheable */
#define NASEG_BASE                              (DRAM_BASE + 5*1024*1024)   /* mapped to DRAM_BASE + 5MB            */
#define	NASEG_SIZE				(1*1024*1024)


/* SRAM (physical addresses!!!) */
#define	EXCSEG_PHYS_BASE			BOOTSTACK             /* located at begin of avail SRAM */
#define	EXCSEG_BASE				0x00000000                /* indirectly mapped to 0x0       */
#define	EXCSEG_SIZE				4096
#define EXCEPTIONSTACKTOP (EXCSEG_BASE + EXCSEG_SIZE - 4)
#define EXCEPTIONSTACKSIZE 768
#define EXCSTACK_SVC			(EXCEPTIONSTACKTOP - 0*EXCEPTIONSTACKSIZE)
#define EXCSTACK_ABT			(EXCEPTIONSTACKTOP - 1*EXCEPTIONSTACKSIZE)
#define EXCSTACK_UND			(EXCEPTIONSTACKTOP - 2*EXCEPTIONSTACKSIZE)
#define EXCSTACK_IRQ			(EXCEPTIONSTACKTOP - 3*EXCEPTIONSTACKSIZE)
#define EXCSTACK_FIQ			(EXCEPTIONSTACKTOP - 4*EXCEPTIONSTACKSIZE)



/* Registers */
#define	REGSEG_BASE				SA_CORE_SYSTEM_BASE       /* directly mapped to SA_CORE_SYSTEM_BASE */
#define	REGSEG_SIZE				1*1024*1024               /* 1MB                                    */
#define	PCIREGSEG_BASE				PCI_CONF_BASE             /* directly mapped to SA_CORE_SYSTEM_BASE */
#define	PCIREGSEG_SIZE				1*1024*1024               /* 1MB                                    */


/* KUSEG layout */
#define KU_USER_SIZE                            (64*4*1024)                    /* 256KB                    */
#define KU_KERNEL_SIZE                          (KUSEG_SIZE - KU_USER_SIZE)    /* remaining space in KUSEG */
#define KU_USER_BASE                            (KUSEG_BASE + KU_KERNEL_SIZE)
#define KU_KERNEL_BASE                          KUSEG_BASE


/* Page Translation Tables (TT)
 * L1: first level TT (1MB regions), 12 bit 1st level table address
 *     (4K entries, 16KB space needed for all 1st level entries in TT_L1)
 *     TT_L1 needs to be filled completely or address translation points to undefined physical address!
 *     we let point the unused virtual address regions to K0SEG, but KUSEG would be better (user cannot change kernel code then)
 *
 * L2: second level TT (4KB pages), 8 bit 2nd level table address
 *     (256 entries per 1st level entry, 1KB max. space needed for all 2nd level entries per 1st level entry,
 *      8*256*4B = 8KB space needed for all 2nd level entries in TT_L2)
 */
#define	TT_L1_BASE      		        DRAM_BASE       /* TT L1 base address (in Bytes), must be a 16KB boundry
* directly mapped to DRAM_BASE */
#define TT_L1_SIZE                              4*1024          /* number of L1 page entries (since 4K*1MB=4GB) */
#define	TT_L2_BASE      		        (TT_L1_BASE + 4*TT_L1_SIZE)
/* first possible free address after L1 TT, must be a 1KB boundry)
* TT L2 base address (in Bytes), just following the L1 TT
* directly mapped after TT_L1 */
#define TT_L2_SIZE                              256             /* number of L2 page entries per L1 entry (since 256*4KB=1MB) */

#define TT_DOMAIN_NOACCESS                      (0x0 << 5)      /* we use domain 0 as 'no access domain' */
#define TT_DOMAIN_RESTRICTED                    (0x2 << 5)      /* we use domain 2 as 'restricted domain' (client, access rights are checked) */
#define TT_DOMAIN_FULLACCESS                    (0x1 << 5)      /* we use domain 1 as 'full access domain' (master, no access rights checked) */

#define TT_IMP_IMPDEF                           (0x0 << 2)      /* !!! IMPLEMENTATION DEFINED, refer to Intel IXP1200 manual and don't find it there...
* needs to be changed possibly! */
#define TT_L1_DESCRIPTOR_COARSE                 0x1             /* L1 TT is coarse type */

#define TT_AP3_PERM_URW                         (0x3 << 10)     /* access permission for subpage 3, full access for user */
#define TT_AP2_PERM_URW                         (0x3 << 8)      /* access permission for subpage 2, full access for user */
#define TT_AP1_PERM_URW                         (0x3 << 6)      /* access permission for subpage 1, full access for user */
#define TT_AP0_PERM_URW                         (0x3 << 4)      /* access permission for subpage 0, full access for user */

#define TT_AP3_PERM_URO                         (0x2 << 10)     /* access permission for subpage 3, read only access for user */
#define TT_AP2_PERM_URO                         (0x2 << 8)      /* access permission for subpage 2, read only access for user */
#define TT_AP1_PERM_URO                         (0x2 << 6)      /* access permission for subpage 1, read only access for user */
#define TT_AP0_PERM_URO                         (0x2 << 4)      /* access permission for subpage 0, read only access for user */

#define TT_AP3_PERM_UNO                         (0x1 << 10)     /* access permission for subpage 3, no access for user */
#define TT_AP2_PERM_UNO                         (0x1 << 8)      /* access permission for subpage 2, no access for user */
#define TT_AP1_PERM_UNO                         (0x1 << 6)      /* access permission for subpage 1, no access for user */
#define TT_AP0_PERM_UNO                         (0x1 << 4)      /* access permission for subpage 0, no access for user */

#define TT_AP3_PERM_NO                          (0x0 << 10)     /* access permission for subpage 3, no access for all */
#define TT_AP2_PERM_NO                          (0x0 << 8)      /* access permission for subpage 2, no access for all */
#define TT_AP1_PERM_NO                          (0x0 << 6)      /* access permission for subpage 1, no access for all */
#define TT_AP0_PERM_NO                          (0x0 << 4)      /* access permission for subpage 0, no access for all */

#define TT_CACHABLE                             (0x1 << 3)      /* set page to cachable */
#define TT_BUFFERABLE                           (0x1 << 2)      /* set page to bufferable */
#define TT_L2_DESCRIPTOR_SMALL                  0x2             /* L2 TT is small type */


/* PRID Register and status bits */
#define PRID_REV_MASK			        0x0000000F 	/* Revision */
#define PRID_PART_MASK                          0x0000FFF0      /* Primary part number */
#define PRID_ARCH_MASK                          0x000F0000      /* Architecture */
#define PRID_VAR_MASK                           0x00F00000      /* Variant */
#define PRID_IMP_MASK			        0xFF000000	/* Implementor */
#define PRID_ARCH_4                             0x1             /* Architecture: 4 */
#define PRID_IMP_INTEL                          0x69            /* Implementor: Intel */
#define PRID_IMP_DEC                            0x44            /* Implementor: DEC */
#define PRID_SA1100_B				0x4401A111      /* SA1100 ID, B stepping */
#define PRID_SA1100_C                           0x4401A112      /* SA1100 ID, C stepping */
#define PRID_SA1100_D                           0x4401A118      /* SA1100 ID, D stepping */
#define PRID_SA1100_E                           0x4401A119      /* SA1100 ID, E stepping */
#define PRID_SA1100_G                           0x4401A11B      /* SA1100 ID, G stepping */
#define PRID_IXP1200                            0x6901C120      /* IXP1200 ID */
#define PRID_IXP1200_MASK                       0xFFFFFFF0      /* no stepping check */

/* PLL_CFG Register */
#define SA_PLL_CFG                              0x90000C00      /* PLL_CFG Register */

/* Clock Frequency 3.6864 MHz */
/* Max. specified core frequency is 200 MHz, DO NOT EXCEED THIS!!!
 * Should be slowest after reset */

/* 00000 29.491 MHz
 * 00001 36.865 
 * 00010 44.237 
 * 00011 51.61 
 * 00100 58.982 
 * 00101 66.355 
 * 00110 73.728 
 * 00111 81.101 
 * 01000 88.474 
 * 01001 95.846 
 * 01010 103.219 
 * 01011 110.592 
 * 01100 132.71 
 * 01101 147.456 
 * 01110 154.829 
 * 01111 162.202 
 * 10000 165.89 
 * 10001 176.947 
 * 10010 191.693 
 * 10011 199.066
 */

#define SA_PLL_FREQ                             0b10011         /* Core Frequency, bit [4:0] in PLL_CFG *
* We use fastest _________8-) */

/* StrongARM system registers */
#define SA_TIMER_BASE              0x42000000      /* base address used for mapping */
#define SA_TIMER_1_LOAD            0x42000300      /* Holds initial value for system timer N */
#define SA_TIMER_2_LOAD            0x42000320
#define SA_TIMER_3_LOAD            0x42000340
#define SA_TIMER_4_LOAD            0x42000360
#define SA_TIMER_1_VALUE           0x42000304      /* Holds current value of system timer N */
#define SA_TIMER_2_VALUE           0x42000324
#define SA_TIMER_3_VALUE           0x42000344
#define SA_TIMER_4_VALUE           0x42000364
#define SA_TIMER_1_CONTROL         0x42000308      /* Control register for system timer N */
#define SA_TIMER_2_CONTROL         0x42000328
#define SA_TIMER_3_CONTROL         0x42000348
#define SA_TIMER_4_CONTROL         0x42000368
#define SA_TIMER_1_CLEAR           0x4200030C      /* Clears associated interrupt of system timer N */
#define SA_TIMER_2_CLEAR           0x4200032C
#define SA_TIMER_3_CLEAR           0x4200034C
#define SA_TIMER_4_CLEAR           0x4200036C
#define SA_TIMER_ENABLE            0x000000C0      /* enable; Mode: periodic; Timer-Scaler: Core Clock */

#define SA_FIQ_SOURCE              0x90001000      /* Register to determine the source of a FIQ interrupt */
#define SA_IRQ_SOURCE              0x90001400      /* Register to determine the source of an IRQ interrupt */
#define SA_MBZ_INT                 0x8             /* Mask for "Must be zero" - bit */
#define SA_MBZ_I                   0x1C
#define SA_UART_INT                0x100           /* Mask for "UART-interrupt" - bit */
#define SA_UART_I                  0x18
#define SA_SDRAM_INT               0x080           /* Mask for "SDRAM-interrupt" - bit */
#define SA_SDRAM_I                 0x14
#define SA_RTC_INT                 0x040           /* Mask for "RTC-interrupt" - bit */
#define SA_RTC_I                   0x10
#define SA_SRAM_INT                0x020           /* Mask for "SRAM-interrupt" - bit */
#define SA_SRAM_I                  0xC
#define SA_UENG_INT                0x010           /* Mask for "MicroThread-interrupt" - bit */
#define SA_UENG_I                  0x8
#define SA_CINT_INT                0x008           /* Mask for "CInt" - bit */
#define SA_CINT_I                  0x4
#define SA_PCI_INT                 0x004           /* Mask for "PCI-interrupt" - bit */
#define SA_PCI_I                   0x0

/* PCI Control register (Timer interrupts) */
#define PCI_IRQ_STATUS             0x00000180      /* Bitwise AND of PCI_IRQ_RAW and PCI_IRQ_ENABLE */
#define PCI_FIQ_STATUS             0x00000280      /* Bitwise AND of PCI_FIQ_RAW and PCI_FIQ_ENABLE */
#define PCI_IRQ_RAW                0x00000184      /* Indicates associated interrupt source is active */
#define PCI_FIQ_RAW                0x00000284      /* Contains indentical data as PCI_IRQ_RAW */
#define PCI_IRQ_ENABLE             0x00000188      /* Masks interrupt input source for PCI_IRQ */
#define PCI_FIQ_ENABLE             0x00000288      /* Masks interrupt input source for PCI_FIQ */
#define PCI_IRQ_ENABLE_SET         0x00000188      /* Sets bits in the PCI_IRQ_ENABLE */
#define PCI_FIQ_ENABLE_SET         0x00000288      /* Sets bits in the PCI_FIQ_ENABLE */
#define PCI_IRQ_ENABLE_CLEAR       0x0000018C      /* Clears bits in the PCI_IRQ_ENABLE */
#define PCI_FIQ_ENABLE_CLEAR       0x0000028C      /* Clears bits in the PCI_FIQ_ENABLE */
#define PCI_TIMER4_MASK            0x00000080      /* Mask for Timer 4 */
#define PCI_TIMER3_MASK            0x00000040      /* Mask for Timer 3 */
#define PCI_TIMER2_MASK            0x00000020      /* Mask for Timer 2 */
#define PCI_TIMER1_MASK            0x00000010      /* Mask for Timer 1 */

/* SA1100 modes */
#define USER_MODE                  0x00000010
#define FIQ_MODE                   0x00000011
#define IRQ_MODE                   0x00000012
#define SVC_MODE                   0x00000013      /* Supervisor */
#define ABT_MODE                   0x00000017      /* Abort */
#define UND_MODE                   0x0000001B      /* Undefined */
#define SYSTEM_MODE                0x0000001F

/* exception causes */
#define EXC_RESET                  0x0
#define EXC_UNDEF_INSTR            0x1
#define EXC_SOFT_INTR              0x2
#define EXC_ABORT_PREFETCH         0x3
#define EXC_ABORT_DATA             0x4
#define EXC_IRQ_INTR               0x5
#define EXC_FIQ_INTR               0x6

/* Program status register masks */
#define CPSR_N                     0x80000000      /* result is negativ */
#define CPSR_Z                     0x40000000      /* result is zero */
#define CPSR_C                     0x20000000      /* carry flag */
#define CPSR_V                     0x10000000      /* overflow flag */
#define CPSR_I                     0x00000080      /* IRQ disable */
#define CPSR_F                     0x00000040      /* FIQ disable */

/* UART addresses */
#define UART_CR                    0x90003800
#define UART_DR                    0x90003C00
#define UART_SR                    0x90003400
#define UART_TX_READY              0x00000004
#define UART_INIT                  0x001700F0      /* UART enable, RX-IRQ enable, 9600, 8N1 */

/* LED address */
#define LED_ADDR                   0x38508000

/* read & write from bytes to words */
#define READB(addr)    (*(volatile uint8  *)(addr))
#define READN(addr)    (*(volatile uint16 *)(addr))
#define READW(addr)    (*(volatile uint32 *)(addr))

#define WRITEB(v,addr) (*(volatile uint8  *)(addr) = (v))
#define WRITEN(v,addr) (*(volatile uint16 *)(addr) = (v))
#define WRITEW(v,addr) (*(volatile uint32 *)(addr) = (v))
