/* flashentry.s * * This file contains the entry code for RTEMS programs starting * directly from Flash. * * Author: Thomas Doerfler * IMD Ingenieurbuero fuer Microcomputertechnik * * COPYRIGHT (c) 1998 by IMD * * Changes from IMD are covered by the original distributions terms. * This file has been derived from the papyrus BSP: * * This file contains the entry veneer for RTEMS programs * stored in Papyrus' flash ROM. * * Author: Andrew Bray * * COPYRIGHT (c) 1995 by i-cubed ltd. * * To anyone who acknowledges that this file is provided "AS IS" * without any express or implied warranty: * permission to use, copy, modify, and distribute this file * for any purpose is hereby granted without fee, provided that * the above copyright notice and this notice appears in all * copies, and that the name of i-cubed limited not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * i-cubed limited makes no representations about the suitability * of this software for any purpose. * * $Id$ */ #include "asm.h" #include /*---------------------------------------------------------------------------- * Reset_entry. *---------------------------------------------------------------------------*/ #if PPC_ASM == PPC_ASM_ELF .section .reset,"ax",@progbits /* this section MUST be located at absolute address 0xFFFFFFFC or last word of EPROM */ #else .csect .text[PR] #endif ba flash_entry /* this is the first instruction after reset */ .previous /*---------------------------------------------------------------------------- * ROM Vector area. *---------------------------------------------------------------------------*/ #if PPC_ASM == PPC_ASM_ELF .section .entry,"ax",@progbits #else .csect .text[PR] #endif PUBLIC_VAR (flash_entry) SYM (flash_entry): bl .startup /* call startup, link reg points to base_addr */ base_addr: /*---------------------------------------------------------------------------- * Parameters from linker *---------------------------------------------------------------------------*/ toc_pointer: #if PPC_ASM == PPC_ASM_ELF .long s.got #else .long TOC[tc0] #endif text_length: .long text.size text_addr: .long text.start copy_src: .long copy.src copy_length: .long copy.size copy_dest: .long copy.dest bss_length: .long bss.size bss_addr: .long bss.start stack_top: .long stack.end /*---------------------------------------------------------------------------- * from Reset_entry. *---------------------------------------------------------------------------*/ .startup: /* Get start address, r1 points to label base_addr */ mflr r1 /* Set up Bank regs, cache etc. */ /* set up bank register BR0 for Flash-EPROM: * NOTE: bank size should stay 1MByte, this is standard size * after RESET * base addr = Fffxxxxx -> 0b11111111........................ * bank size = 1 MByte -> 0b........000..................... (std) * bank use = readonly -> 0b...........01................... * seq. fill = targ frst-> 0b.............0.................. * burst mode= enable -> 0b..............1................. * bus width = 8 bit -> 0b...............00............... * ready pin = disable -> 0b.................0.............. * first wait= 2 clocks -> 0b..................0010.......... * burst wait= 2 clocks -> 0b......................10........ * CSon time = 0 clocks -> 0b........................0....... * OEon time = 0 clocks -> 0b.........................0...... * WBon time = 1 clocks -> 0b..........................1..... * WBoff time= 0 clocks -> 0b...........................0.... * Hold time = 1 clocks -> 0b............................001. * ram type = SRAM(ign)-> 0b...............................1 * value 0b11111111000010100000101000100011 * 0x F F 0 A 0 A 2 3 */ lis r2,0xFF0A ori r2,r2,0x0A23 mtdcr br0,r2 /* write to DCR BR0 */ /*-------------------------------------------------------------------- * test various RAM configurations (from big to small per bank) *------------------------------------------------------------------*/ /*-------------------------------------------------------------------- * test RAM config 16 MByte (1x4Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 for DRAM: * base addr = 000xxxxx -> 0b00000000........................ * bank size = 16MByte -> 0b........100..................... * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00000000100110010010101010110000 * 0x 0 0 9 9 2 A B 0 */ lis r2,0x0099 ori r2,r2,0x2AB0 mtdcr br7,r2 /* write to DCR BR7*/ lis r2,0x0000 /* start address = 0x00000000 */ lis r3,0x0100 /* size 16 MB = 0x01000000 */ bl ramacc /* test memory accessibility */ cmpi 0,0,r4,0 /* memory ok? else test smaller size */ bne ramcfgt18 /*-------------------------------------------------------------------- * test RAM config 32 MByte (2x4Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 like above * set up bank register BR6 for DRAM: * base addr = 010xxxxx -> 0b00010000........................ * bank size = 16MByte -> 0b........100..................... (for now) * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00010000100110010010101010110000 * 0x 1 0 9 9 2 A B 0 */ lis r2,0x1099 ori r2,r2,0x2AB0 mtdcr br6,r2 /* write to DCR BR6*/ lis r2,0x0100 /* start address = 0x01000000 */ lis r3,0x0100 /* size 16 MB = 0x01000000 */ bl ramacc /* test memory accessibility */ cmpi 0,0,r4,0 /* memory ok? else test smaller size */ beq ramcfgok /* ok, we found configuration... +/ lis r2,0x0000 /* disable BR6, config not ok */ mtdcr br6,r2 /* write to DCR BR6*/ b ramcfgok /* and finish configuration */ ramcfgt18: /*-------------------------------------------------------------------- * test RAM config 8 MByte (1x2Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 for DRAM: * base addr = 000xxxxx -> 0b00000000........................ * bank size = 8MByte -> 0b........011..................... * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00000000011110010010101010110000 * 0x 0 0 7 9 2 A B 0 */ lis r2,0x0079 ori r2,r2,0x2AB0 mtdcr br7,r2 /* write to DCR BR7 */ lis r2,0x0000 /* start address = 0x00000000 */ lis r3,0x0080 /* size 8 MB = 0x00800000 */ bl ramacc /* test memory accessibility */ cmpi 0,0,r4,0 /* memory ok? else test smaller size */ bne ramcfgt14 /*-------------------------------------------------------------------- * test RAM config 16 MByte (2x2Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 like above * set up bank register BR6 for DRAM: * base addr = 008xxxxx -> 0b00001000........................ * bank size = 08MByte -> 0b........011..................... (for now) * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00001000011110010010101010110000 * 0x 0 8 7 9 2 A B 0 */ lis r2,0x0879 ori r2,r2,0x2AB0 mtdcr br6,r2 /* write to DCR BR6*/ lis r2,0x0080 /* start address = 0x00800000 */ lis r3,0x0080 /* size 8 MB = 0x00800000 */ bl ramacc /* test memory accessibility */ cmpi 0,0,r4,0 /* memory ok? else test smaller size */ beq ramcfgok /* ok, we found configuration... +/ lis r2,0x0000 /* disable BR6, config not ok */ mtdcr br6,r2 /* write to DCR BR6*/ b ramcfgok /* and finish configuration */ ramcfgt14: /*-------------------------------------------------------------------- * test RAM config 4 MByte (1x1Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 for DRAM: * base addr = 000xxxxx -> 0b00000000........................ * bank size = 4MByte -> 0b........010..................... * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00000000010110010010101010110000 * 0x 0 0 5 9 2 A B 0 */ /* * FIXME: this is the minimum size supported, should test and * report error, when failed */ lis r2,0x0059 ori r2,r2,0x2AB0 mtdcr br7,r2 /* write to DCR BR7*/ /*-------------------------------------------------------------------- * test RAM config 8 MByte (2x1Mx32Bit) *------------------------------------------------------------------*/ /* set up bank register BR7 like above * set up bank register BR6 for DRAM: * base addr = 004xxxxx -> 0b00000100........................ * bank size = 4MByte -> 0b........010..................... (for now) * bank use = readwrite-> 0b...........11................... * seq. fill = targ.frst-> 0b.............0.................. * early RAS = disabled -> 0b..............0................. * bus width = 32bit -> 0b...............10............... * adr mux = internal -> 0b.................0.............. * RAS to CAS= 2 clocks -> 0b..................1............. * Alt. Rfrsh= normal -> 0b...................0............ * page mode = enabled -> 0b....................1........... * first wait= 1 clocks -> 0b.....................01......... * burst wait= 1 clocks -> 0b.......................01....... * precharge = 1 clocks -> 0b.........................0...... * RAS Rfrsh = 2 clocks -> 0b..........................1..... * Rfrsh Itvl= 512 clks -> 0b...........................1000. * ram type = DRAM -> 0b...............................0 * value 0b00000100010110010010101010110000 * 0x 0 4 5 9 2 A B 0 */ lis r2,0x0459 ori r2,r2,0x2AB0 mtdcr br6,r2 /* write to DCR BR6*/ lis r2,0x0040 /* start address = 0x00400000 */ lis r3,0x0040 /* size 4 MB = 0x00400000 */ bl ramacc /* test memory accessibility */ cmpi 0,0,r4,0 /* memory ok? else test smaller size */ beq ramcfgok /* ok, we found configuration... +/ lis r2,0x0000 /* disable BR6, config not ok */ mtdcr br6,r2 /* write to DCR BR6*/ b ramcfgok /* and finish configuration */ ramcfgok: /*-------------------------------------------------------------------- * init the DRAM where STACK+ DATA+ BBS will be placed. If this is OK * we will return here. *-------------------------------------------------------------------*/ bl rom2ram /* clear caches */ addi r2,0,PPC_I_CACHE/PPC_CACHE_ALIGNMENT mtctr r2 /* count the loops needed... */ xor r2,r2,r2 /* start at adr zero */ icinvlp: iccci 0,r2 addi r2,r2,PPC_CACHE_ALIGNMENT bdnz icinvlp addi r2,r0,PPC_D_CACHE/PPC_CACHE_ALIGNMENT mtctr r2 /* count the loops needed... */ xor r2,r2,r2 /* start at adr 0 */ dcinvlp: dccci 0,r2 addi r2,r2,PPC_CACHE_ALIGNMENT bdnz dcinvlp /*-------------------------------------------------------------------- * Enable two 128MB cachable regions. * FEPROM is cachable at 0xFFF00000..0xFFFFFFFF * DRAM is cachable at 0x00000000..0x00FFFFFF * FEPROM is noncachable at 0x7FF00000..0x7FFFFFFF * DRAM is noncachable at 0x80000000..0x80FFFFFF *-------------------------------------------------------------------*/ addis r2,r0,0x8000 addi r2,r2,0x0001 mtspr iccr, r2 /* ICCR */ mtspr dccr, r2 /* DCCR */ .extern SYM(__vectors) lis r2,__vectors@h /* set EVPR exc. vector prefix */ mtspr evpr,r2 lis r2,0x0000 ori r2,r2,0x0000 mtmsr r2 /* set default msr */ lis r2,0x0000 /* do not allow critical IRQ */ ori r2,r2,0x0000 mtdcr exier, r2 /* disable all external IRQs */ addi r2,r0,-1 /* r2 = 0xffffffff */ mtdcr exisr, r2 /* clear all pendingdisable IRQs */ /*-------------------------------------------------------------------- * C_setup. *-------------------------------------------------------------------*/ lwz r2,toc_pointer-base_addr(r1) /* set r2 to toc */ lwz r1,stack_top-base_addr(r1) /* set r1 to stack_top */ addi r1,r1,-56 /* start stack at data_addr - 56 */ addi r3,r0,0x0 /* clear r3 */ stw r3, 0(r1) /* Clear stack chain */ stw r3, 4(r1) stw r3, 8(r1) stw r3, 12(r1) .extern SYM (boot_card) b SYM (boot_card) /* call the first C routine */ /*---------------------------------------------------------------------------- * Rom2ram. *---------------------------------------------------------------------------*/ rom2ram: lwz r2,copy_dest-base_addr(r1) /* start of data set by loader */ lwz r3,copy_length-base_addr(r1) /* data length */ rlwinm r3,r3,30,0x3FFFFFFF /* form length/4 */ mtctr r3 /* set ctr reg */ /*-------------------------------------------------------------------- * Calculate offset of data in image. *-------------------------------------------------------------------*/ lwz r4,copy_src-base_addr(r1) /* get start of copy area */ move_data: lswi r6,r4,0x4 /* load r6 */ stswi r6,r2,0x4 /* store r6 */ addi r4,r4,0x4 /* update r4 */ addi r2,r2,0x4 /* update r2 */ bdnz move_data /* decrement counter and loop */ /*-------------------------------------------------------------------- * Data move finished, zero out bss. *-------------------------------------------------------------------*/ lwz r2,bss_addr-base_addr(r1) /* start of bss set by loader */ lwz r3,bss_length-base_addr(r1) /* bss length */ rlwinm. r3,r3,30,0x3FFFFFFF /* form length/4 */ beqlr /* no bss */ mtctr r3 /* set ctr reg */ xor r6,r6,r6 /* r6 = 0 */ clear_bss: stswi r6,r2,0x4 /* store r6 */ addi r2,r2,0x4 /* update r2 */ bdnz clear_bss /* decrement counter and loop */ blr /* return */ /*---------------------------------------------------------------------------- * ramacc test accessibility of RAM * input: r2 = start address, r3 = length (in byte) * output: r4 = 0 -> ok, !=0 -> fail *---------------------------------------------------------------------------*/ ramacc: xor r4,r4,r4 /* r4 = 0 */ stw r4,0(r2) /* init ram at start address */ addi r4,r0,0x04 /* set start shift */ ramaccf1: cmp 0,0,r4,r3 /* compare with length */ bge ramaccfx /* r4 >= r3? then finished */ add r5,r4,r2 /* get next address to fill */ stw r4,0(r5) /* store new pattern */ add r4,r4,r4 /* r4 = r4*2 */ b ramaccf1 /* and then next loop */ ramaccfx: lwz r4,0(r2) /* get memory at start adr */ blr #if PPC_ABI == PPC_ABI_POWEROPEN DESCRIPTOR (startup) #endif