diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 10:35:35 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 13:52:14 +0200 |
commit | 99648958668d3a33ee57974479b36201fe303f34 (patch) | |
tree | 6f27ea790e2823c6156e71219a4f54680263fac6 /bsps/powerpc | |
parent | bsps: Move start files to bsps (diff) | |
download | rtems-99648958668d3a33ee57974479b36201fe303f34.tar.bz2 |
bsps: Move startup files to bsps
Adjust build support files to new directory layout.
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/powerpc')
155 files changed, 13691 insertions, 0 deletions
diff --git a/bsps/powerpc/beatnik/start/bsp_specs b/bsps/powerpc/beatnik/start/bsp_specs new file mode 100644 index 0000000000..99ca0adb61 --- /dev/null +++ b/bsps/powerpc/beatnik/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/beatnik/start/bspclean.c b/bsps/powerpc/beatnik/start/bspclean.c new file mode 100644 index 0000000000..251d47a46d --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspclean.c @@ -0,0 +1,25 @@ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + printk("fatal source: %s\n", rtems_fatal_source_text(source)); + + if (source == RTEMS_FATAL_SOURCE_EXCEPTION) { + rtems_exception_frame_print((const rtems_exception_frame *) error); + } + + /* We can't go back to MotLoad since we blew it's memory area + * and vectors. Just pull the reset line... + */ + printk( + "bsp_fatal_extension(): RTEMS terminated -- no way back to MotLoad " + "so I reset the card\n" + ); + bsp_reset(); +} diff --git a/bsps/powerpc/beatnik/start/bspreset.c b/bsps/powerpc/beatnik/start/bspreset.c new file mode 100644 index 0000000000..68540847ee --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspreset.c @@ -0,0 +1,18 @@ +#include <rtems.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/io.h> +#include <libcpu/stackTrace.h> +#include <stdint.h> + +void bsp_reset() +{ + + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + + printk("RTEMS terminated; Rebooting ...\n"); + /* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */ + out_8((volatile uint8_t*) (BSP_MV64x60_DEV1_BASE +2), 0x80); +} diff --git a/bsps/powerpc/beatnik/start/bspstart.c b/bsps/powerpc/beatnik/start/bspstart.c new file mode 100644 index 0000000000..c3f2c0ceda --- /dev/null +++ b/bsps/powerpc/beatnik/start/bspstart.c @@ -0,0 +1,387 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified to support the Synergy VGM & Motorola PowerPC boards. + * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005 + * + * Modified to support the mvme5500 BSP + * (C) by Kate Feng <feng1@bnl.gov>, 2003, 2004 + * under the contract DE-AC02-98CH10886 with the Deaprtment of Energy + * + * T. Straumann: 2005-2007; stolen again for 'beatnik'... + */ +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include <rtems/system.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/powerpc/powerpc.h> +#include <rtems/sysinit.h> +/*#include <bsp/consoleIo.h>*/ +#include <libcpu/spr.h> /* registers.h is included here */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/pci.h> +#include <bsp/gtreg.h> +#include <bsp/gt_timer.h> +#include <libcpu/bat.h> +#include <libcpu/pte121.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <bsp/vpd.h> + +#define SHOW_MORE_INIT_SETTINGS + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *); +extern void BSP_pgtbl_activate(Triv121PgTbl); +extern void BSP_motload_pci_fixup(void); + +extern unsigned long __rtems_end[]; + +/* We really shouldn't use these since MMUoff also sets IP; + * nevertheless, during early init I don't care for now + */ +extern void MMUoff(void); +extern void MMUon(void); + +extern uint32_t probeMemoryEnd(void); + +SPR_RW(SPRG0) +SPR_RW(SPRG1) +SPR_RO(HID1) + +/* Table of PLL multipliers for 7455/7457: +01000 2 00010 7.5 00000 11.5 00001 17 +10000 3 11000 8 10111 12 00101 18 +10100 4 01100 8.5 11111 12.5 00111 20 +10110 5 01111 9 01011 13 01001 21 +10010 5.5 01110 9.5 11100 13.5 01101 24 +11010 6 10101 10 11001 14 11101 28 +01010 6.5 10001 10.5 00011 15 00110 bypass +00100 7 10011 11 11011 16 11110 off +*/ + +/* Sorted according to CFG bits and multiplied by 2 it looks + * like this (note that this is in sequential order, not + * tabulated as above) + */ +signed char mpc7450PllMultByTwo[32] = { +23, 34, 15, 30, +14, 36, 2/*bypass*/, 40, +4, 42, 13, 26, +17, 48, 19, 18, +6, 21, 11, 22, +8, 20, 10, 24, +16, 28, 12, 32, +27, 56, 0/*off*/, 25, +}; + +uint32_t bsp_clicks_per_usec = 0; + +/* + * Total memory using probing. + */ +unsigned int BSP_mem_size; + +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency = 0xdeadbeef; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency = 0xdeadbeef; + +/* + * Time base divisior (bus freq / TB clock) + */ +unsigned int BSP_time_base_divisor = 4000; /* most 604+ CPUs seem to use this */ + +/* Board identification string */ +char BSP_productIdent[20] = {0}; +char BSP_serialNumber[20] = {0}; + +/* VPD appends an extra char -- what for ? */ +char BSP_enetAddr0[7] = {0}; +char BSP_enetAddr1[7] = {0}; + +char *rtems_progname; + +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE]; +char *BSP_commandline_string = cmdline_buf; + +/* this routine is called early and must be safe with a not properly + * aligned stack + */ +char *save_boot_params( + void *r3, + void *r4, + void *r5, + char *cmdline_start, + char *cmdline_end +) +{ +int i=cmdline_end-cmdline_start; + if ( i >= CMDLINE_BUF_SIZE ) + i = CMDLINE_BUF_SIZE-1; + else if ( i < 0 ) + i = 0; + memmove(cmdline_buf, cmdline_start, i); + cmdline_buf[i]=0; + return cmdline_buf; +} + +static BSP_BoardType board_type = Unknown; + +BSP_BoardType +BSP_getBoardType( void ) +{ + return board_type; +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start( void ) +{ + unsigned char *stack; + char *chpt; + uint32_t intrStackStart; + uint32_t intrStackSize; + + Triv121PgTbl pt=0; + + VpdBufRec vpdData [] = { + { key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 }, + { key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 }, + { key: CpuClockHz, instance: 0, buf: &BSP_processor_frequency, buflen: sizeof(BSP_processor_frequency) }, + { key: BusClockHz, instance: 0, buf: &BSP_bus_frequency, buflen: sizeof(BSP_bus_frequency) }, + { key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) }, + { key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) }, + VPD_END + }; + + /* T. Straumann: 4/2005 + * + * Need to map the system registers early, so we can printk... + * (otherwise we silently die) + */ + /* map the PCI 0, 1 Domain I/O space, GT64260B registers + * and the reserved area so that the size is the power of 2. + */ + setdbat(7, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_BASE, BSP_DEV_AND_PCI_IO_SIZE, IO_PAGE); + + /* Intersperse messages with actions to help locate problems */ + printk("-----------------------------------------\n"); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() & friends functions + * store the result in global variables so that it can be used latter... + * This also verifies that we run on a known CPU. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Make sure we detect a known host bridge */ + BSP_getDiscoveryVersion(/* assert detection */ 1); + + printk("Welcome to RTEMS %s\n", _RTEMS_version ); + + /* Leave all caches as MotLoad left them. Seems to be fine */ + + /* + * the initial stack has aready been set to this value in start.S + * so there is no need to set it in r1 again... It is just for info + * so that it can be printed without accessing R1. + */ + __asm__ volatile("mr %0, 1":"=r"(stack)); + + /* tag the bottom (T. Straumann 6/36/2001 <strauman@slac.stanford.edu>) */ + + *((uint32_t *)stack) = 0; + + /* + * Initialize the interrupt related settings + * SPRG0 = interrupt nesting level count + * SPRG1 = software managed IRQ stack + * + * This could be done latter (e.g in IRQ_INIT) but it helps to understand + * some settings below... + */ + intrStackStart = (uint32_t)__rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. See vectors/vectors_init.c + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + printk("CPU: %s\n", get_ppc_cpu_type_name(current_ppc_cpu)); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + BSP_vpdRetrieveFields(vpdData); + + if ( !strncmp(BSP_productIdent,"MVME5500",8) ) + board_type = MVME5500; + else if ( !strncmp(BSP_productIdent,"MVME6100",8) ) + board_type = MVME6100; + + printk("Board Type: %s (S/N %s)\n", + BSP_productIdent[0] ? BSP_productIdent : "n/a", + BSP_serialNumber[0] ? BSP_serialNumber : "n/a"); + + if ( 0xdeadbeef == BSP_bus_frequency ) { + BSP_bus_frequency = 133333333; + printk("Bus Clock Freq NOT FOUND in VPD; using %10u Hz\n", + BSP_bus_frequency); + } else { + printk("Bus Clock Freq: %10u Hz\n", + BSP_bus_frequency); + } + + if ( 0xdeadbeef == BSP_processor_frequency ) { + BSP_processor_frequency = BSP_bus_frequency/2; + BSP_processor_frequency *= mpc7450PllMultByTwo[ (_read_HID1() >> (31-19)) & 31 ]; + } + printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency); + + /* probe real memory size; if it's more than 256M we can't currently access it + * since at this point only BAT-0 maps 0..256M + */ + BSP_mem_size = probeMemoryEnd(); + + if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) { + char *endp; + uint32_t sz; + chpt+=6 /* strlen("MEMSZ=") */; + sz = strtoul(chpt, &endp, 0); + if ( endp != chpt ) + BSP_mem_size = sz; + } + + printk("Memory: %10u bytes\n", BSP_mem_size); + + if ( BSP_mem_size > 0x10000000 ) { + uint32_t s; + if ( BSP_mem_size > 0x80000000 ) { + BSP_mem_size = 0x80000000; + printk("Memory clipped to 0x%08x for now, sorry\n", BSP_mem_size); + } + for ( s = 0x20000000; s < BSP_mem_size ; s<<=1) + ; + MMUoff(); + /* since it's currently in use we must first surrender it */ + setdbat(0, 0, 0, 0, 0); + setdbat(0, 0, 0, s, _PAGE_RW); + MMUon(); + } + + printk("-----------------------------------------\n"); + + /* Maybe not setup yet because of the warning message */ + + /* Allocate and set up the page table mappings + * This is only available on >604 CPUs. + * + * NOTE: This setup routine may modify the available memory + * size. It is essential to call it before + * calculating the workspace etc. + */ + pt = BSP_pgtbl_setup(&BSP_mem_size); + if (!pt) + printk("WARNING: unable to setup page tables.\n"); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size); +#endif + + /* + * Set up our hooks + */ + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk( + "Configuration.work_space_size = %x\n", + rtems_configuration_get_work_space_size() + ); +#endif + + /* Activate the page table mappings only after + * initializing interrupts because the irq_mng_init() + * routine needs to modify the text + */ + if ( pt ) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Page table setup finished; will activate it NOW...\n"); +#endif + BSP_pgtbl_activate(pt); + } + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + BSP_pci_initialize(); + + /* need to tweak the motload setup */ + BSP_motload_pci_fixup(); + + /* map 512M, 256 for PCI 256 for VME */ + setdbat(5,BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_BASE, BSP_PCI_HOSE0_MEM_SIZE, IO_PAGE); + setdbat(6,BSP_PCI_HOSE1_MEM_BASE, BSP_PCI_HOSE1_MEM_BASE, 0x10000000, IO_PAGE); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); +#endif + + /* + * Initialize hardware timer facility (not used by BSP itself) + * Needs PCI to identify discovery version... + */ + BSP_timers_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("MSR 0x%lx \n", _read_MSR()); + printk("Exit from bspstart\n"); +#endif +} + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/beatnik/start/i2c_init.c b/bsps/powerpc/beatnik/start/i2c_init.c new file mode 100644 index 0000000000..bc5c5ead02 --- /dev/null +++ b/bsps/powerpc/beatnik/start/i2c_init.c @@ -0,0 +1,131 @@ +#include <rtems.h> +#include <bsp.h> +#include <rtems/libi2c.h> +#include <libchip/i2c-2b-eeprom.h> +#include <libchip/i2c-ds1621.h> +#include <bsp/gti2c_busdrv.h> +#include <rtems/libio.h> + +#include <stdio.h> +#include <sys/stat.h> + +/* Register i2c bus driver & devices */ + +/* + * Authorship + * ---------- + * This software ('beatnik' RTEMS BSP for MVME6100 and MVME5500) was + * created by Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * The 'beatnik' BSP was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +int +BSP_i2c_initialize( void ) +{ +int busno; + /* Initialize the library */ + if ( rtems_libi2c_initialize() ) { + fprintf(stderr,"Initializing I2C library failed\n"); + return -1; + } + + /* Register our bus driver */ + if ( (busno=rtems_libi2c_register_bus( + BSP_I2C_BUS0_NAME, + BSP_I2C_BUS_DESCRIPTOR) ) < 0 ) { + perror("Registering gt64260 i2c bus driver"); + return -1; + } + + /* Now register higher level drivers; note that + * the i2c address in the manual is actually left-shifted + * by one bit, i.e., as it would go on the bus. + */ + + /* Use read-only driver for VPD */ + if ( rtems_libi2c_register_drv( + BSP_I2C_VPD_EEPROM_NAME, + i2c_2b_eeprom_ro_driver_descriptor, + busno, + BSP_VPD_I2C_ADDR) < 0 ) { + perror("Registering i2c VPD eeprom driver failed"); + return -1; + } + + /* Use read-write driver for user eeprom -- you still might + * have to disable HW write-protection on your board. + */ + if ( rtems_libi2c_register_drv( + BSP_I2C_USR_EEPROM_NAME, + i2c_2b_eeprom_driver_descriptor, + busno, + BSP_USR_I2C_ADDR) < 0 ) { + perror("Registering i2c USR eeprom driver failed"); + return -1; + } + + /* The thermostat */ + if ( rtems_libi2c_register_drv( + BSP_I2C_DS1621_NAME, + i2c_ds1621_driver_descriptor, + busno, + BSP_THM_I2C_ADDR) < 0 ) { + perror("Registering i2c ds1621 temp sensor. driver failed"); + return -1; + } + + /* Finally, as an example, register raw access to the + * ds1621. The driver above just reads the 8 msb of the + * temperature but doesn't support anything else. Using + * the raw device node you can write/read individual + * control bytes yourself and e.g., program the thermostat... + */ + + if ( mknod( + BSP_I2C_DS1621_RAW_DEV_NAME, + 0666 | S_IFCHR, + rtems_filesystem_make_dev_t(rtems_libi2c_major, + RTEMS_LIBI2C_MAKE_MINOR(busno,BSP_THM_I2C_ADDR))) ) { + perror("Creating device node for raw ds1621 access failed"); + return -1; + } + printf("I2C devices registered\n"); + return 0; +} diff --git a/bsps/powerpc/beatnik/start/linkcmds b/bsps/powerpc/beatnik/start/linkcmds new file mode 100644 index 0000000000..b30fb91277 --- /dev/null +++ b/bsps/powerpc/beatnik/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(motld_start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/gen5200/start/bestcomm.c b/bsps/powerpc/gen5200/start/bestcomm.c new file mode 100644 index 0000000000..ef59adcfd8 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bestcomm.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#define NDEBUG + +#include <bsp/bestcomm.h> + +#include <string.h> + +#include <bsp/mpc5200.h> + +static void bestcomm_irq_handler(void *arg) +{ + bestcomm_irq *self = arg; + + bestcomm_irq_clear(self); + bestcomm_irq_wakeup_event_task(self); +} + +void bestcomm_irq_create(bestcomm_irq *self, int task_index) +{ + assert(task_index >= 0 && task_index <= 15); + + self->task_index = task_index; + self->event_task_id = rtems_task_self(); + bestcomm_glue_irq_install(task_index, bestcomm_irq_handler, self); +} + +void bestcomm_irq_destroy(const bestcomm_irq *self) +{ + bestcomm_glue_irq_install(self->task_index, NULL, NULL); +} + +void bestcomm_task_create(bestcomm_task *self, TaskId task_index) +{ + self->task_control_register = &mpc5200.sdma.tcr[task_index]; + self->variable_table = BESTCOMM_TASK_ENTRY_TABLE[task_index].var_table; + self->task_index = task_index; + self->tdt_begin = NULL; + self->tdt_opcode_count = 0; + bestcomm_task_stop(self); + bestcomm_irq_create(&self->irq, task_index); +} + +void bestcomm_task_create_and_load( + bestcomm_task *self, + TaskId task_index, + const uint32_t *tdt_source_begin, + size_t tdt_size +) +{ + bestcomm_task_create(self, task_index); + bestcomm_task_load(self, tdt_source_begin, tdt_size); +} + +void bestcomm_task_destroy(bestcomm_task *self) +{ + bestcomm_task_stop(self); + bestcomm_task_free_tdt(self); +} + +void bestcomm_task_load(bestcomm_task *self, const uint32_t *tdt_source_begin, size_t tdt_size) +{ + assert(tdt_size % 4 == 0); + + bestcomm_task_irq_disable(self); + bestcomm_task_stop(self); + bestcomm_task_irq_clear(self); + bestcomm_task_irq_enable(self); + bestcomm_task_free_tdt(self); + bestcomm_task_clear_variables(self); + + self->tdt_opcode_count = tdt_size / 4; + + self->tdt_begin = bestcomm_malloc(tdt_size); + assert(self->tdt_begin != NULL); + uint32_t *tdt_last = self->tdt_begin + self->tdt_opcode_count - 1; + + memcpy(self->tdt_begin, tdt_source_begin, tdt_size); + + volatile bestcomm_task_entry *entry = bestcomm_task_get_task_entry(self); + entry->tdt_begin = self->tdt_begin; + entry->tdt_last = tdt_last; + + bestcomm_task_clear_pragmas(self); + bestcomm_task_set_priority(self, 0); +} + +void bestcomm_task_clear_variables(const bestcomm_task *self) +{ + int i; + + for (i = 0; i < 32; ++i) { + (*self->variable_table)[i] = 0; + } +} diff --git a/bsps/powerpc/gen5200/start/bsp_specs b/bsps/powerpc/gen5200/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/gen5200/start/bspreset.c b/bsps/powerpc/gen5200/start/bspreset.c new file mode 100644 index 0000000000..232ebfeac0 --- /dev/null +++ b/bsps/powerpc/gen5200/start/bspreset.c @@ -0,0 +1,30 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp.h> +#include <bsp/mpc5200.h> +#include <bsp/bootcard.h> + +void bsp_reset( void ) +{ + #if (BENCHMARK_IRQ_PROCESSING == 1) + { + BSP_IRQ_Benchmarking_Report(); + } + #endif + + /* + * Now reset the CPU + */ + mpc5200.gpt[0].count_in = 0xf; + mpc5200.gpt[0].emsel = 0x9004; + + while(1) ; +} diff --git a/bsps/powerpc/gen5200/start/bspstart.c b/bsps/powerpc/gen5200/start/bspstart.c new file mode 100644 index 0000000000..209cc7738e --- /dev/null +++ b/bsps/powerpc/gen5200/start/bspstart.c @@ -0,0 +1,172 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the BSP initialization code | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: bspstart.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This routine starts the application. It includes */ +/* application, board, and monitor specific */ +/* initialization and configuration. The generic CPU */ +/* dependent initialization has been performed before */ +/* this routine is invoked. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads C level startup code */ +/* Module: bspstart.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.2 */ +/* Date: 04/17/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* The MPC860 specific stuff was written by Jay Monkman */ +/* (jmonkman@frasca.com) */ +/* */ +/* Modified for the MPC8260ADS board by Andy Dachs */ +/* <a.dachs@sstl.co.uk> */ +/* Surrey Satellite Technology Limited, 2001 */ +/* A 40MHz system clock is assumed. */ +/* The PON. RST.CONF. Dip switches (DS1) are */ +/* 1 - Off */ +/* 2 - On */ +/* 3 - Off */ +/* 4 - On */ +/* 5 - Off */ +/* 6 - Off */ +/* 7 - Off */ +/* 8 - Off */ +/* Dip switches on DS2 and DS3 are all set to ON */ +/* The LEDs on the board are used to signal panic and fatal_error */ +/* conditions. */ +/* The mmu is unused at this time. */ +/* */ +/* COPYRIGHT (c) 1989-2007. */ +/* On-Line Applications Research Corporation (OAR). */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in the file LICENSE in this distribution or at */ +/* http://www.rtems.org/license/LICENSE. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <rtems.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/mpc5200.h> + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +void bsp_start(void) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + #if defined(HAS_UBOOT) && defined(SHOW_MORE_INIT_SETTINGS) + { + void dumpUBootBDInfo( bd_t * ); + dumpUBootBDInfo( &bsp_uboot_board_info ); + } + #endif + + cpu_init(); + + if(get_ppc_cpu_revision() >= 0x2014) { + /* Special settings for MPC5200B (B variant) */ + uint32_t xlb_cfg = mpc5200.config; + + /* XXX: The Freescale documentation for BSDIS seems to be wrong */ + xlb_cfg |= XLB_CFG_BSDIS; + + xlb_cfg &= ~XLB_CFG_PLDIS; + + mpc5200.config = xlb_cfg; + } + + bsp_time_base_frequency = XLB_CLOCK / 4; + bsp_clicks_per_usec = (XLB_CLOCK/4000000); + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize exception handler */ + ppc_exc_cache_wb_check = 0; + ppc_exc_initialize( + (uintptr_t) bsp_interrupt_stack_start, + (uintptr_t) bsp_interrupt_stack_size + ); + ppc_exc_set_handler(ASM_ALIGN_VECTOR, ppc_exc_alignment_handler); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + + /* + * If the BSP was built with IRQ benchmarking enabled, + * then intialize it. + */ + #if (BENCHMARK_IRQ_PROCESSING == 1) + BSP_IRQ_Benchmarking_Reset(); + #endif + + #ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); + #endif +} diff --git a/bsps/powerpc/gen5200/start/cpuinit.c b/bsps/powerpc/gen5200/start/cpuinit.c new file mode 100644 index 0000000000..77787c4956 --- /dev/null +++ b/bsps/powerpc/gen5200/start/cpuinit.c @@ -0,0 +1,348 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the code to initialize the cpu | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: cpuinit.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains additional functions for */ +/* initializing the MPC5x00 CPU */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads additional CPU initialization */ +/* Module: cpuinit.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.1 */ +/* Date: 10/22/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Written by Jay Monkman (jmonkman@frasca.com) */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <stdbool.h> +#include <string.h> + +#include <libcpu/powerpc-utility.h> +#include <libcpu/mmu.h> + +#include <bsp.h> +#include <bsp/mpc5200.h> + +#define SET_DBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##U, uv); \ + } while (0) + +static void calc_dbat_regvals( + BAT *bat_ptr, + uint32_t base_addr, + uint32_t size, + bool flg_w, + bool flg_i, + bool flg_m, + bool flg_g, + uint32_t flg_bpp +) +{ + uint32_t block_mask = 0xffffffff; + uint32_t end_addr = base_addr + size - 1; + + /* Determine block mask, that overlaps the whole block */ + while ((end_addr & block_mask) != (base_addr & block_mask)) { + block_mask <<= 1; + } + + bat_ptr->batu.bepi = base_addr >> (32 - 15); + bat_ptr->batu.bl = ~(block_mask >> (28 - 11)); + bat_ptr->batu.vs = 1; + bat_ptr->batu.vp = 1; + + bat_ptr->batl.brpn = base_addr >> (32 - 15); + bat_ptr->batl.w = flg_w; + bat_ptr->batl.i = flg_i; + bat_ptr->batl.m = flg_m; + bat_ptr->batl.g = flg_g; + bat_ptr->batl.pp = flg_bpp; +} + +static inline void enable_bat_4_to_7(void) +{ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(HID2, BSP_BBIT32(13)); +} + +static void cpu_init_bsp(void) +{ + BAT dbat; + +#if defined(MPC5200_BOARD_BRS5L) || defined(MPC5200_BOARD_BRS6L) + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT(0,dbat.batu,dbat.batl); + + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + false, + false, + false, + false, + BPP_RX + ); + SET_DBAT(1,dbat.batu,dbat.batl); + + calc_dbat_regvals( + &dbat, + (uint32_t) MBAR, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(2,dbat.batu,dbat.batl); +#elif defined (HAS_UBOOT) + uint32_t start = 0; + + /* + * Accesses (also speculative accesses) outside of the RAM area are a + * disaster especially in combination with the BestComm. For safety reasons + * we make the available RAM a little bit smaller to have an unused area at + * the end. + */ + bsp_uboot_board_info.bi_memsize -= 4 * 1024; + + /* + * Program BAT0 for RAM + */ + calc_dbat_regvals( + &dbat, + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT(0,dbat.batu,dbat.batl); + + /* + * Program BAT1 for Flash + * + * WARNING!! Some Freescale LITE5200B boards ship with a version of + * U-Boot that lies about the starting address of Flash. This check + * corrects that. + */ + if ((bsp_uboot_board_info.bi_flashstart + bsp_uboot_board_info.bi_flashsize) + < bsp_uboot_board_info.bi_flashstart) { + start = 0 - bsp_uboot_board_info.bi_flashsize; + } else { + start = bsp_uboot_board_info.bi_flashstart; + } + calc_dbat_regvals( + &dbat, + start, + bsp_uboot_board_info.bi_flashsize, + false, + false, + false, + false, + BPP_RX + ); + SET_DBAT(1,dbat.batu,dbat.batl); + + /* + * Program BAT2 for the MBAR + */ + calc_dbat_regvals( + &dbat, + (uint32_t) MBAR, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(2,dbat.batu,dbat.batl); + + /* + * If there is SRAM, program BAT3 for that memory + */ + if (bsp_uboot_board_info.bi_sramsize != 0) { + calc_dbat_regvals( + &dbat, + bsp_uboot_board_info.bi_sramstart, + bsp_uboot_board_info.bi_sramsize, + false, + true, + true, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); + } +#else +#warning "Using BAT register values set by environment" +#endif + +#if defined(MPC5200_BOARD_DP2) + enable_bat_4_to_7(); + + /* FPGA */ + calc_dbat_regvals( + &dbat, + 0xf0020000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(4, dbat.batu, dbat.batl); +#elif defined(MPC5200_BOARD_PM520_ZE30) + enable_bat_4_to_7(); + + /* External CC770 CAN controller available in version 2 */ + calc_dbat_regvals( + &dbat, + 0xf2000000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(4, dbat.batu, dbat.batl); +#elif defined(MPC5200_BOARD_BRS5L) + calc_dbat_regvals( + &dbat, + (uint32_t) bsp_dpram_start, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); +#elif defined(MPC5200_BOARD_BRS6L) + enable_bat_4_to_7(); + + /* FPGA */ + calc_dbat_regvals( + &dbat, + MPC5200_BRS6L_FPGA_BEGIN, + MPC5200_BRS6L_FPGA_SIZE, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); + + /* MRAM */ + calc_dbat_regvals( + &dbat, + MPC5200_BRS6L_MRAM_BEGIN, + MPC5200_BRS6L_MRAM_SIZE, + true, + false, + false, + false, + BPP_RW + ); + SET_DBAT(4,dbat.batu,dbat.batl); +#endif +} + +void cpu_init(void) +{ + uint32_t msr; + + #if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); + #endif + + /* Set up DBAT registers in MMU */ + cpu_init_bsp(); + + #if defined(SHOW_MORE_INIT_SETTINGS) + { extern void ShowBATS(void); + ShowBATS(); + } + #endif + + /* Read MSR */ + msr = ppc_machine_state_register(); + + /* Enable data MMU in MSR */ + msr |= MSR_DR; + + /* Update MSR */ + ppc_set_machine_state_register( msr); + + #if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); + #endif +} diff --git a/bsps/powerpc/gen5200/start/linkcmds.brs5l b/bsps/powerpc/gen5200/start/linkcmds.brs5l new file mode 100644 index 0000000000..58407e5f56 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.brs5l @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the BRS5L board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k + REGS : ORIGIN = 0xf0000000, LENGTH = 64k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.brs6l b/bsps/powerpc/gen5200/start/linkcmds.brs6l new file mode 100644 index 0000000000..ae80a72ad5 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.brs6l @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the BRS6L board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xff800000, LENGTH = 8M + DPRAM : ORIGIN = 0xff000000, LENGTH = 0 + REGS : ORIGIN = 0xf0000000, LENGTH = 64k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.dp2 b/bsps/powerpc/gen5200/start/linkcmds.dp2 new file mode 100644 index 0000000000..4ad76d6fce --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.dp2 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the Direct Prototyping Data Processing board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0x0, LENGTH = 0 +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.gen5200_base b/bsps/powerpc/gen5200/start/linkcmds.gen5200_base new file mode 100644 index 0000000000..1a92c7c9dd --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.gen5200_base @@ -0,0 +1,357 @@ +/** + * @file + * + * Derived from internal linker script of GNU ld (GNU Binutils) 2.18 for elf32ppc emulation. + */ + +OUTPUT_FORMAT ("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH (powerpc) +ENTRY (start) +STARTUP (start.o) + +bsp_ram_start = ORIGIN (RAM); +bsp_ram_end = ORIGIN (RAM) + LENGTH (RAM); +bsp_ram_size = LENGTH (RAM); + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_end = ORIGIN (ROM) + LENGTH (ROM); +bsp_rom_size = LENGTH (ROM); + +bsp_dpram_start = ORIGIN (DPRAM); +bsp_dpram_end = ORIGIN (DPRAM) + LENGTH (DPRAM); +bsp_dpram_size = LENGTH (DPRAM); + +bsp_section_align = 32; + +RamBase = bsp_ram_start; +RamSize = bsp_ram_size; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + /* + * BSP: MPC5200 registers + */ + .regs (NOLOAD) : { + MBAR = .; + mpc5200 = .; + } > REGS + + /* + * BSP: Exception vectors + */ + .vectors 0x100 : { + *(.vectors) + } > RAM + + /* + * BSP: The initial stack will live in this area - between the vectors + * and the text section. + */ + + .text 0x10000 : { + /* + * BSP: Start of text section + */ + bsp_section_text_start = .; + + /* + * BSP: System startup entry + */ + KEEP (*(.entry)) + + /* + * BSP: Moved into .text from .init + */ + KEEP (*(.init)) + + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.glink) + + /* + * BSP: Special FreeBSD sysctl sections + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* + * BSP: Moved into .text from .* + */ + *(.rodata .rodata.* .gnu.linkonce.r.*) + KEEP (*(SORT(.rtemsroset.*))) + *(.rodata1) + *(.interp) + *(.note.gnu.build-id) + *(.hash) + *(.gnu.hash) + *(.dynsym) + *(.dynstr) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) + *(.eh_frame_hdr) + + /* + * BSP: Magic PPC stuff + */ + *(.PPC.*) + + /* + * BSP: Required by cpukit/score/src/threadhandler.c + */ + PROVIDE (_fini = .); + + /* + * BSP: Moved into .text from .fini + */ + KEEP (*(.fini)) + + . = ALIGN (bsp_section_align); + + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > RAM + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > RAM + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + .sdata2 : { + PROVIDE (_SDA2_BASE_ = 32768); + + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + + . = ALIGN (bsp_section_align); + } > RAM + + .sbss2 : { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + . = ALIGN (bsp_section_align); + + /* + * BSP: End of text section + */ + bsp_section_text_end = .; + } > RAM + + .data : { + /* + * BSP: Start of data section + */ + bsp_section_data_start = .; + + /* + * BSP: Moved into .data from .ctors + */ + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + + /* + * BSP: Moved into .data from .dtors + */ + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + /* + * BSP: Moved into .data from .* + */ + *(.tdata .tdata.* .gnu.linkonce.td.*) + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + *(.data1) + KEEP (*(.eh_frame)) + *(.gcc_except_table .gcc_except_table.*) + KEEP (*(.jcr)) + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) + *(.fixup) + *(.got1) + *(.got2) + *(.dynamic) + *(.got) + *(.plt) + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE_HIDDEN (__fini_array_end = .); + + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + + . = ALIGN (bsp_section_align); + } > RAM + + .sdata : { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + + . = ALIGN (bsp_section_align); + + _edata = .; + PROVIDE (edata = .); + + /* + * BSP: End of data section + */ + bsp_section_data_end = .; + } > RAM + + .sbss : { + /* + * BSP: Start of bss section + */ + bsp_section_bss_start = .; + + __bss_start = .; + + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.scommon) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + + . = ALIGN (bsp_section_align); + } > RAM + + .bss : { + *(COMMON) + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + + . = ALIGN (bsp_section_align); + + __end = .; + _end = .; + PROVIDE (end = .); + + /* + * BSP: End of bss section + */ + bsp_section_bss_end = .; + } > RAM + + /* + * BSP: Section sizes + */ + bsp_section_text_size = bsp_section_text_end - bsp_section_text_start; + bsp_section_data_size = bsp_section_data_end - bsp_section_data_start; + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_start; + + /* + * BSP: Interrupt stack + */ + bsp_interrupt_stack_start = bsp_section_bss_end; + bsp_interrupt_stack_end = bsp_interrupt_stack_start + 32k; + bsp_interrupt_stack_size = bsp_interrupt_stack_end - bsp_interrupt_stack_start; + + /* + * BSP: Work area start + */ + bsp_work_area_start = bsp_interrupt_stack_end; + WorkAreaBase = bsp_work_area_start; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF extension */ + .debug_macro 0 : { *(.debug_macro) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + + /DISCARD/ : { + *(.note.GNU-stack) *(.gnu_debuglink) + } + + /* + * This is a RTEMS specific section to catch all unexpected input + * sections. In case you get an error like + * "section `.unexpected_sections' will not fit in region + * `UNEXPECTED_SECTIONS'" + * you have to figure out the offending input section and add it to the + * appropriate output section definition above. + */ + .unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS +} diff --git a/bsps/powerpc/gen5200/start/linkcmds.icecube b/bsps/powerpc/gen5200/start/linkcmds.icecube new file mode 100644 index 0000000000..c05d45a852 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.icecube @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the IceCube board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 128M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0x0, LENGTH = 0 +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 b/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 new file mode 100644 index 0000000000..49d596b577 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.pm520_cr825 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the MicroSys PM520 board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 b/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 new file mode 100644 index 0000000000..49d596b577 --- /dev/null +++ b/bsps/powerpc/gen5200/start/linkcmds.pm520_ze30 @@ -0,0 +1,15 @@ +/** + * @file + * + * Linker command file for the MicroSys PM520 board. + */ + +MEMORY { + /* For the 4k adjustment see cpuinit.c */ + RAM : ORIGIN = 0x0, LENGTH = 64M - 4k + ROM : ORIGIN = 0xffe00000, LENGTH = 2M + REGS : ORIGIN = 0xf0000000, LENGTH = 64k + DPRAM : ORIGIN = 0xff000000, LENGTH = 1k +} + +INCLUDE linkcmds.gen5200_base diff --git a/bsps/powerpc/gen5200/start/uboot_support.c b/bsps/powerpc/gen5200/start/uboot_support.c new file mode 100644 index 0000000000..f373f558e7 --- /dev/null +++ b/bsps/powerpc/gen5200/start/uboot_support.c @@ -0,0 +1,23 @@ +/* + * This file contains variables which assist the shared + * U-Boot code. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdint.h> + +#include <bsp.h> + +#if defined(HAS_UBOOT) +/* Base address of U-Boot environment variables */ +const uint8_t *uboot_environment = (const uint8_t *)0xfff40000; + +/* Length of area reserved for U-Boot environment variables */ +const size_t uboot_environment_size = 0x10000; +#endif diff --git a/bsps/powerpc/gen83xx/start/bsp_specs b/bsps/powerpc/gen83xx/start/bsp_specs new file mode 100644 index 0000000000..a37ec281c8 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s -u __vectors}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/gen83xx/start/bspreset.c b/bsps/powerpc/gen83xx/start/bspreset.c new file mode 100644 index 0000000000..ebaf9f129f --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bspreset.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2008 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +#include <mpc83xx/mpc83xx.h> + +void bsp_reset(void) +{ + mpc83xx_reset(); +} diff --git a/bsps/powerpc/gen83xx/start/bsprestart.c b/bsps/powerpc/gen83xx/start/bsprestart.c new file mode 100644 index 0000000000..4a2d298de0 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bsprestart.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/u-boot.h> + +#include <libcpu/powerpc-utility.h> + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + void (*start)(void) = addr; + #ifdef HAS_UBOOT + const void *mem_begin = (const void *) bsp_uboot_board_info.bi_memstart; + size_t mem_size = bsp_uboot_board_info.bi_memsize; + #else /* HAS_UBOOT */ + const void *mem_begin = bsp_ram_start; + size_t mem_size = (size_t) bsp_ram_size; + #endif /* HAS_UBOOT */ + uint32_t hid0; + + rtems_interrupt_disable(level); + (void) level; /* avoid set but not used warning */ + + hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0); + + if ((hid0 & HID0_DCE) != 0) { + rtems_cache_flush_multiple_data_lines(mem_begin, mem_size); + } + + hid0 &= ~(HID0_DCE | HID0_ICE); + + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + + (*start)(); +} diff --git a/bsps/powerpc/gen83xx/start/bspstart.c b/bsps/powerpc/gen83xx/start/bspstart.c new file mode 100644 index 0000000000..cd729a8e17 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/bspstart.c @@ -0,0 +1,129 @@ +/** + * @file + * + * @ingroup mpc83xx + * + * @brief Source for BSP startup code. + */ + +/* + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/counter.h> + +#include <libchip/ns16550.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/u-boot.h> +#include <bsp/console-termios.h> + +/* Configuration parameters for console driver, ... */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +/* Default decrementer exception handler */ +static int mpc83xx_decrementer_exception_handler( BSP_Exception_frame *frame, unsigned number) +{ + ppc_set_decrementer_register(UINT32_MAX); + + return 0; +} + +void bsp_start( void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + unsigned long i = 0; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Basic CPU initialization */ + cpu_init(); + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ + +#ifdef BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif + +#ifdef BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * This is evaluated during runtime, so it should be ok to set it + * before we initialize the drivers. + */ + + /* Initialize some device driver parameters */ + +#ifdef HAS_UBOOT + BSP_bus_frequency = bsp_uboot_board_info.bi_busfreq; +#else /* HAS_UBOOT */ + BSP_bus_frequency = BSP_CLKIN_FRQ * BSP_SYSPLL_MF / BSP_SYSPLL_CKID; +#endif /* HAS_UBOOT */ + bsp_time_base_frequency = BSP_bus_frequency / 4; + bsp_clicks_per_usec = bsp_time_base_frequency / 1000000; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize some console parameters */ + for (i = 0; i < console_device_count; ++i) { + ns16550_context *ctx = (ns16550_context *) console_device_table[i].context; + + ctx->clock = BSP_bus_frequency; + + #ifdef HAS_UBOOT + ctx->initial_baud = bsp_uboot_board_info.bi_baudrate; + #endif + } + + /* Initialize exception handler */ +#ifndef BSP_DATA_CACHE_ENABLED + ppc_exc_cache_wb_check = 0; +#endif + ppc_exc_initialize( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + /* Install default handler for the decrementer exception */ + sc = ppc_exc_set_handler( ASM_DEC_VECTOR, mpc83xx_decrementer_exception_handler); + if (sc != RTEMS_SUCCESSFUL) { + rtems_panic("cannot install decrementer exception handler"); + } + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} diff --git a/bsps/powerpc/gen83xx/start/cpuinit.c b/bsps/powerpc/gen83xx/start/cpuinit.c new file mode 100644 index 0000000000..1b0fd1efef --- /dev/null +++ b/bsps/powerpc/gen83xx/start/cpuinit.c @@ -0,0 +1,329 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the code to initialize the cpu | +\*===============================================================*/ + + +/***********************************************************************/ +/* */ +/* Module: cpuinit.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 C level startup code */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains additional functions for */ +/* initializing the MPC5x00 CPU */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads additional CPU initialization */ +/* Module: cpuinit.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.1 */ +/* Date: 10/22/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Written by Jay Monkman (jmonkman@frasca.com) */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include <stdbool.h> +#include <string.h> + +#include <libcpu/powerpc-utility.h> +#include <libcpu/mmu.h> + +#include <mpc83xx/mpc83xx.h> + +#include <bsp.h> +#include <bsp/u-boot.h> + +#define SET_DBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( DBAT##n##U, uv); \ + } while (0) + +#define SET_IBAT( n, uv, lv) \ + do { \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##L, lv); \ + PPC_SET_SPECIAL_PURPOSE_REGISTER( IBAT##n##U, uv); \ + } while (0) + +static void calc_dbat_regvals( + BAT *bat_ptr, + uint32_t base_addr, + uint32_t size, + bool flg_w, + bool flg_i, + bool flg_m, + bool flg_g, + uint32_t flg_bpp +) +{ + uint32_t block_mask = 0xffffffff; + uint32_t end_addr = base_addr + size - 1; + + /* Determine block mask, that overlaps the whole block */ + while ((end_addr & block_mask) != (base_addr & block_mask)) { + block_mask <<= 1; + } + + bat_ptr->batu.bepi = base_addr >> (32 - 15); + bat_ptr->batu.bl = ~(block_mask >> (28 - 11)); + bat_ptr->batu.vs = 1; + bat_ptr->batu.vp = 1; + + bat_ptr->batl.brpn = base_addr >> (32 - 15); + bat_ptr->batl.w = flg_w; + bat_ptr->batl.i = flg_i; + bat_ptr->batl.m = flg_m; + bat_ptr->batl.g = flg_g; + bat_ptr->batl.pp = flg_bpp; +} + +static void clear_mmu_regs( void) +{ + uint32_t i; + + /* Clear segment registers */ + for (i = 0;i < 16;i++) { + __asm__ volatile( "mtsrin %0, %1\n" : : "r" (i * 0x1000), "r" (i << (31 - 3))); + } + + /* Clear TLBs */ + for (i = 0;i < 32;i++) { + __asm__ volatile( "tlbie %0\n" : : "r" (i << (31 - 19))); + } +} + +void cpu_init( void) +{ + BAT dbat, ibat; + uint32_t msr; + uint32_t hid0; + + /* Clear MMU and segment registers */ + clear_mmu_regs(); + + /* Clear caches */ + hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0); + if ((hid0 & (HID0_ICE | HID0_DCE)) == 0) { + hid0 &= ~(HID0_ILOCK | HID0_DLOCK | HID0_ICE | HID0_DCE); + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + hid0 |= HID0_ICFI | HID0_DCI; + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + hid0 &= ~(HID0_ICFI | HID0_DCI); + PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); + } + + /* + * Set up IBAT registers in MMU + */ + + memset(&ibat, 0, sizeof( ibat)); + SET_IBAT( 2, ibat.batu, ibat.batl); + SET_IBAT( 3, ibat.batu, ibat.batl); + SET_IBAT( 4, ibat.batu, ibat.batl); + SET_IBAT( 5, ibat.batu, ibat.batl); + SET_IBAT( 6, ibat.batu, ibat.batl); + SET_IBAT( 7, ibat.batu, ibat.batl); + + calc_dbat_regvals( + &ibat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RX + ); + SET_IBAT( 0, ibat.batu, ibat.batl); + + calc_dbat_regvals( + &ibat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_flashstart, + bsp_uboot_board_info.bi_flashsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RX + ); + SET_IBAT( 1, ibat.batu, ibat.batl); + + /* + * Set up DBAT registers in MMU + */ + + memset(&dbat, 0, sizeof( dbat)); + SET_DBAT( 3, dbat.batu, dbat.batl); + SET_DBAT( 4, dbat.batu, dbat.batl); + SET_DBAT( 5, dbat.batu, dbat.batl); + SET_DBAT( 6, dbat.batu, dbat.batl); + SET_DBAT( 7, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_memstart, + bsp_uboot_board_info.bi_memsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_ram_start, + (uint32_t) bsp_ram_size, + #endif /* HAS_UBOOT */ + false, + false, + false, + false, + BPP_RW + ); + SET_DBAT( 0, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_flashstart, + bsp_uboot_board_info.bi_flashsize, + #else /* HAS_UBOOT */ + (uint32_t) bsp_rom_start, + (uint32_t) bsp_rom_size, + #endif /* HAS_UBOOT */ + #ifdef MPC83XX_HAS_NAND_LP_FLASH_ON_CS0 + false, + true, + false, + true, + BPP_RW + #else + true, + false, + false, + false, + BPP_RX + #endif + ); + SET_DBAT( 1, dbat.batu, dbat.batl); + + calc_dbat_regvals( + &dbat, + #ifdef HAS_UBOOT + bsp_uboot_board_info.bi_immrbar, + #else /* HAS_UBOOT */ + (uint32_t) IMMRBAR, + #endif /* HAS_UBOOT */ + #if MPC83XX_CHIP_TYPE / 10 == 830 + 2 * 1024 * 1024, + #else + 1024 * 1024, + #endif + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT( 2, dbat.batu, dbat.batl); + +#if defined(MPC83XX_BOARD_HSC_CM01) + calc_dbat_regvals( + &dbat, + FPGA_START, + FPGA_SIZE, + true, + true, + true, + false, + BPP_RW + ); + SET_DBAT(3,dbat.batu,dbat.batl); +#endif + +#ifdef MPC83XX_BOARD_MPC8313ERDB + /* Enhanced Local Bus Controller (eLBC) */ + calc_dbat_regvals( + &dbat, + 0xfa000000, + 128 * 1024, + false, + true, + false, + true, + BPP_RW + ); + SET_DBAT( 3, dbat.batu, dbat.batl); +#endif /* MPC83XX_BOARD_MPC8313ERDB */ + + /* Read MSR */ + msr = ppc_machine_state_register(); + + /* Enable data and instruction MMU in MSR */ + msr |= MSR_DR | MSR_IR; + + /* Enable FPU in MSR */ + msr |= MSR_FP; + + /* Update MSR */ + ppc_set_machine_state_register( msr); + + /* + * In HID0: + * - Enable dynamic power management + * - Enable machine check interrupts + */ + PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, HID0_EMCP | HID0_DPM); + + /* Enable timebase clock */ + mpc83xx.syscon.spcr |= M83xx_SYSCON_SPCR_TBEN; +} diff --git a/bsps/powerpc/gen83xx/start/linkcmds b/bsps/powerpc/gen83xx/start/linkcmds new file mode 100644 index 0000000000..094fdf51af --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds @@ -0,0 +1,19 @@ +/** + * @file + * + * Default linker script -- copy of linkcmds.mpc8313erdb + * for MPC8313E Reference Design Board. + * + * This exists simply for consistency so autoconf tests will + * be able to compile against this BSP. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x0, LENGTH = 128M + ROM : ORIGIN = 0xfe000000, LENGTH = 8M + MPC83XX_REGS : ORIGIN = 0xe0000000, LENGTH = 256k +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/gen83xx/start/linkcmds.br_uid b/bsps/powerpc/gen83xx/start/linkcmds.br_uid new file mode 100644 index 0000000000..3d8c3a154a --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.br_uid @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 2M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 b/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.hsc_cm01 @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som b/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8309som @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb b/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb new file mode 100644 index 0000000000..717b3b4866 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8313erdb @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 128M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds b/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds new file mode 100644 index 0000000000..d5b4b1e145 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc8349eamds @@ -0,0 +1,10 @@ +MEMORY { + RESCONF : ORIGIN = 0x0, LENGTH = 0x100 + VECTORS : ORIGIN = 0x100, LENGTH = 0x10000 - 0x100 + WORK : ORIGIN = 0x10000, LENGTH = 256M - 0x10000 + ROM : ORIGIN = 0xfe000000, LENGTH = 8M +} + +REGION_ALIAS ("START", WORK); + +INCLUDE linkcmds.mpc83xx diff --git a/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx b/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx new file mode 100644 index 0000000000..4ddbcd6f76 --- /dev/null +++ b/bsps/powerpc/gen83xx/start/linkcmds.mpc83xx @@ -0,0 +1,47 @@ +bsp_ram_start = ORIGIN (RESCONF); +bsp_ram_end = ORIGIN (WORK) + LENGTH (WORK); +bsp_ram_size = bsp_ram_end - bsp_ram_start; + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_size = LENGTH (ROM); +bsp_rom_end = bsp_rom_start + bsp_rom_size; + +IMMRBAR = 0xe0000000; +mpc83xx = IMMRBAR; + +EXTERN (__vectors) + +MEMORY { + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +SECTIONS { + .resconf : { + *(.resconf) + } > RESCONF AT > RESCONF + + .vectors : { + *(.vectors) + } > VECTORS AT > VECTORS +} + +REGION_ALIAS ("REGION_START", START); +REGION_ALIAS ("REGION_FAST_TEXT", WORK); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", WORK); +REGION_ALIAS ("REGION_TEXT", WORK); +REGION_ALIAS ("REGION_TEXT_LOAD", WORK); +REGION_ALIAS ("REGION_RODATA", WORK); +REGION_ALIAS ("REGION_RODATA_LOAD", WORK); +REGION_ALIAS ("REGION_FAST_DATA", WORK); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", WORK); +REGION_ALIAS ("REGION_DATA", WORK); +REGION_ALIAS ("REGION_DATA_LOAD", WORK); +REGION_ALIAS ("REGION_BSS", WORK); +REGION_ALIAS ("REGION_RWEXTRA", WORK); +REGION_ALIAS ("REGION_WORK", WORK); +REGION_ALIAS ("REGION_STACK", WORK); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/gen83xx/start/uboot_support.c b/bsps/powerpc/gen83xx/start/uboot_support.c new file mode 100644 index 0000000000..295059889d --- /dev/null +++ b/bsps/powerpc/gen83xx/start/uboot_support.c @@ -0,0 +1,24 @@ +/* + * This file contains variables which assist the shared + * U-Boot code. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdint.h> + +#include <bsp.h> + +#if defined(HAS_UBOOT) +/* XXX TODO fill in with real information */ +/* Base address of U-Boot environment variables */ +const uint8_t *uboot_environment = (const uint8_t *) 0x00000000; + +/* Length of area reserved for U-Boot environment variables */ +const size_t *uboot_environment_size = (const size_t *) 0x00010000; +#endif diff --git a/bsps/powerpc/haleakala/start/bsp_specs b/bsps/powerpc/haleakala/start/bsp_specs new file mode 100644 index 0000000000..5752caaca0 --- /dev/null +++ b/bsps/powerpc/haleakala/start/bsp_specs @@ -0,0 +1,10 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} + diff --git a/bsps/powerpc/haleakala/start/bspstart.c b/bsps/powerpc/haleakala/start/bspstart.c new file mode 100644 index 0000000000..18b45f33df --- /dev/null +++ b/bsps/powerpc/haleakala/start/bspstart.c @@ -0,0 +1,195 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * 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: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * 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. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * + * Further modified for the PPC405EX Haleakala board by + * Michael Hamel ADInstruments Ltd May 2008 + */ +#include <string.h> +#include <fcntl.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/irq.h> +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> +#include <ppc4xx/ppc405gp.h> +#include <ppc4xx/ppc405ex.h> + +#include <stdio.h> + +LINKER_SYMBOL(intrStack_start); +LINKER_SYMBOL(intrStack_size); +/* + * Driver configuration parameters + */ + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + +/*-------------------- Haleakala-specific UART setup -------------------------*/ + +static void +EarlyUARTInit(int baudRate) +{ + volatile uint8_t* up = (uint8_t*)(BSP_UART_IOBASE_COM1); + int divider = BSP_UART_BAUD_BASE / baudRate; + up[LCR] = DLAB; /* Access DLM/DLL */ + up[DLL] = divider & 0x0FF; + up[DLM] = divider >> 8; + up[LCR] = CHR_8_BITS; + up[MCR] = DTR | RTS; + up[FCR] = FIFO_EN | XMIT_RESET | RCV_RESET; + up[THR] = '+'; +} + + +static void +InitUARTClock(void) +{ + uint32_t reg; + mfsdr(SDR0_UART0,reg); + reg &= ~0x008000FF; + reg |= 0x00800001; /* Ext clock, div 1 */ + mtsdr(SDR0_UART0,reg); +} + +static void GPIO_AlternateSelect(int bitnum, int source) +/* PPC405EX: select a GPIO function for the specified pin */ +{ + int shift; + unsigned long value, mask; + GPIORegisters* gpioPtr = (GPIORegisters*)(GPIOAddress); + + shift = (31 - bitnum) & 0xF; + value = (source & 3) << (shift*2); + mask = 3 << (shift*2); + if (bitnum <= 15) { + gpioPtr->OSRL = (gpioPtr->OSRL & ~mask) | value; + gpioPtr->TSRL = (gpioPtr->TSRL & ~mask) | value; + } else { + gpioPtr->OSRH = (gpioPtr->OSRH & ~mask) | value; + gpioPtr->TSRH = (gpioPtr->TSRH & ~mask) | value; + } +} + +static void Init_FPGA(void) +{ + /* Have to write to the FPGA to enable the UART drivers */ + /* Have to enable CS2 as an output in GPIO to get the FPGA working */ + mtebc(EBC0_B2CR,0xF0018000); /* Set up CS2 at 0xF0000000 */ + mtebc(EBC0_B2AP,0x9400C800); + GPIO_AlternateSelect(9,1); /* GPIO9 = PerCS2 */ + { + unsigned long *fpgaPtr = (unsigned long*)(0xF0000000); + unsigned long n; + n = *(fpgaPtr); + n &= ~0x00100; /* User LEDs on */ + n |= 0x30000; /* UART 0 and 1 transcievers on! */ + *fpgaPtr = n; + } +} + +/*===================================================================*/ + +static void +DirectUARTWrite(const char c) +{ + volatile uint8_t* up = (uint8_t*)(BSP_UART_IOBASE_COM1); + while ((up[LSR] & THRE) == 0) { ; } + up[THR] = c; +} + +/* We will provide our own printk output function as it may get used early */ +BSP_output_char_function_type BSP_output_char = DirectUARTWrite; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +/*===================================================================*/ + +void bsp_start( void ) +{ + /* Get the UART clock initialized first in case we call printk */ + + InitUARTClock(); + Init_FPGA(); + EarlyUARTInit(115200); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables + * so that it can be used later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * initialize the device driver parameters + */ + + /* Set globals visible to clock.c */ + /* timebase register ticks/microsecond = CPU Clk in MHz */ + bsp_clicks_per_usec = 400; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize( + (uintptr_t) intrStack_start, + (uintptr_t) intrStack_size + ); + + /* + * Install our own set of exception vectors + */ + BSP_rtems_irq_mng_init(0); +} diff --git a/bsps/powerpc/haleakala/start/linkcmds b/bsps/powerpc/haleakala/start/linkcmds new file mode 100644 index 0000000000..8c06a5103b --- /dev/null +++ b/bsps/powerpc/haleakala/start/linkcmds @@ -0,0 +1,277 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the 405GP/EX + * This file is intended to be used together with dlentry.s + * it will generate downloadable code + * + * Modifications for gen405 by Dennis Ehlin + * Modifications for virtex by Keith, Greg, and Bob + * Modifications for 405GP/EX by Michael Hamel + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(download_entry) +EXTERN(__vectors) + +kIntrStackSize = 16K; +kMainStackSize = 64K; + +RamBase = DEFINED(RamBase) ? RamBase : 0; +RamSize = DEFINED(RamSize) ? RamSize : 256M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; + +MEMORY { + RAM : ORIGIN = 0, LENGTH = 256M + /*FLASH : ORIGIN = 0xFFE00000, LENGTH = 16M*/ +} + + +SECTIONS +{ + /* First 16K is occupied by exception vectors and anything else we want to put there */ + .text 0x4000: + { + text.start = . ; + *(.entry) + *(.entry2) + *(.text*) + *(.rodata*) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + + PROVIDE (__CTOR_LIST__ = .); + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* Exception frame info */ + *(.eh_frame) + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata) + *(.rodata1) + *(.descriptors) + *(rom_ver) + _erodata = .; + + PROVIDE (__EXCEPT_START__ = .); + *(.gcc_except_table*) + PROVIDE (__EXCEPT_END__ = .); + __GOT_START__ = .; + s.got = .; + *(.got.plt) + *(.got) + *(.got1) + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + *(.got2) + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + *(.fixup) + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + + *(.lit) + *(.shdata) + _endtext = ALIGN(0x10); + text.end = .; + text.size = text.end - text.start; + } >RAM + + text.size = text.end - text.start; + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + .jcr : { KEEP (*(.jcr)) } >RAM + + .rel.dyn : { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } >RAM + .rela.dyn : { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >RAM + + + /* Initialised large data */ + .data ( . ) : + { + . = ALIGN (4); + data.start = .; + *(.data) + *(.data1) + KEEP (*(SORT(.rtemsrwset.*))) + *(.data.* .gnu.linkonce.d.*) + data.end = .; + } > RAM + + /* Initialised small data addressed as offsets from r13 */ + .sdata : { + . = ALIGN (4); + PROVIDE (__SDATA_START__ = .); + sdata.start = .; + *(.sdata*) + *(.gnu.linkonce.s.*) + sdata.end = .; + } > RAM + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { + . = ALIGN (4); + PROVIDE(__SBSS_START__ = .); + sbss.start = .; + *(.sbss .sbss.* *.gnu.linkonce.sb.*); + sbss.end = .; + } > RAM + PROVIDE(__SBSS_END__ = .); + + /* Zeroed large data */ + .bss : { + . = ALIGN (4); + bss.start = .; + *(.bss .bss* .gnu.linkonce.b*) + . = ALIGN(4); + bss.end = .; + } > RAM + + bss.size = bss.end - bss.start; + sbss.size = sbss.end - sbss.start; + + /* Interrupt stack: align to a cache-line boundary */ + IntrStack_start = ALIGN(0x20); + . += kIntrStackSize; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + PROVIDE(intrStack_start = IntrStack_start); + PROVIDE(intrStack_size = kIntrStackSize); + + /* Main stack: align to a cache-line boundary */ + stack.start = ALIGN(0x20); + . += kMainStackSize; + stack.end = .; + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x20); + + /* Debugging information */ + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_aregion 0 : { *(.debug_aregion) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } +} diff --git a/bsps/powerpc/motorola_powerpc/start/bsp_specs b/bsps/powerpc/motorola_powerpc/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/motorola_powerpc/start/bspreset.c b/bsps/powerpc/motorola_powerpc/start/bspreset.c new file mode 100644 index 0000000000..0931badae4 --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/bspreset.c @@ -0,0 +1,28 @@ +#include <bsp.h> +#include <rtems/bspIo.h> +#include <libcpu/stackTrace.h> +#include <bsp/bootcard.h> + +/*-------------------------------------------------------------------------+ +| Function: bsp_reset +| Description: Reboot the PC. +| Global Variables: None. +| Arguments: None. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +void bsp_reset(void) +{ + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + /* shutdown and reboot */ + +#if defined(mvme2100) + *(unsigned char*)0xffe00000 |= 0x80; +#else + /* Memory-mapped Port 92 PIB device access + *(unsigned char*)0x80000092 |= 0x01; + */ + outb(1, 0x92); + +#endif +} /* bsp_reset */ diff --git a/bsps/powerpc/motorola_powerpc/start/linkcmds b/bsps/powerpc/motorola_powerpc/start/linkcmds new file mode 100644 index 0000000000..ae44032d4f --- /dev/null +++ b/bsps/powerpc/motorola_powerpc/start/linkcmds @@ -0,0 +1,6 @@ +INPUT(vectors_entry.o) +STARTUP(start.o) +ENTRY(__rtems_entry_point) +EXTERN(_vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mpc55xxevb/start/bsp_specs b/bsps/powerpc/mpc55xxevb/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c b/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c new file mode 100644 index 0000000000..e7d988cf87 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspgetworkarea.c @@ -0,0 +1,53 @@ +/** + * @file + * + * @ingroup mpc55xx + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_section_work_bonus_begin); +LINKER_SYMBOL(bsp_section_work_bonus_size); + +void bsp_work_area_initialize(void) +{ + Heap_Area areas [] = { + { + bsp_section_work_begin, + (uintptr_t) bsp_section_work_size + }, { + bsp_section_work_bonus_begin, + (uintptr_t) bsp_section_work_bonus_size + } + }; + + #ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + { + uint32_t stack_size = rtems_configuration_get_interrupt_stack_size(); + + areas [0].begin = (char *) areas [0].begin + stack_size; + areas [0].size -= stack_size; + } + #endif + + bsp_work_area_initialize_with_table( + areas, + sizeof(areas) / sizeof(areas [0]) + ); +} diff --git a/bsps/powerpc/mpc55xxevb/start/bspreset.c b/bsps/powerpc/mpc55xxevb/start/bspreset.c new file mode 100644 index 0000000000..a99b3856d3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspreset.c @@ -0,0 +1,38 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief BSP reset. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdbool.h> + +#include <bsp/bootcard.h> + +#include <mpc55xx/regs.h> + +void bsp_reset(void) +{ + while (true) { + #if MPC55XX_CHIP_FAMILY == 564 + /* TODO */ + #else + SIU.SRCR.R = 1U << (31 - 0); + #endif + } +} diff --git a/bsps/powerpc/mpc55xxevb/start/bspstart.c b/bsps/powerpc/mpc55xxevb/start/bspstart.c new file mode 100644 index 0000000000..9042fc3864 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/bspstart.c @@ -0,0 +1,104 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief BSP startup code. + */ + +/* + * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <mpc55xx/mpc55xx.h> +#include <mpc55xx/regs.h> +#include <mpc55xx/edma.h> +#include <mpc55xx/emios.h> + +#include <string.h> + +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> +#include <bsp/vectors.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +/* Symbols defined in linker command file */ +LINKER_SYMBOL(mpc55xx_exc_vector_base); + +unsigned int bsp_clock_speed = 0; + +uint32_t bsp_clicks_per_usec = 0; + +static void null_pointer_protection(void) +{ +#ifdef MPC55XX_NULL_POINTER_PROTECTION + struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } }; + + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R); + __asm__ volatile ("tlbre"); + mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); + mmu.MAS1.B.VALID = 0; + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R); + __asm__ volatile ("tlbwe"); +#endif +} + +void bsp_start(void) +{ + null_pointer_protection(); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * determine clock speed + */ + bsp_clock_speed = mpc55xx_get_system_clock() / MPC55XX_SYSTEM_CLOCK_DIVIDER; + + /* Time reference value */ + bsp_clicks_per_usec = bsp_clock_speed / 1000000; + rtems_counter_initialize_converter(bsp_clock_speed); + + /* Initialize exceptions */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + mpc55xx_exc_vector_base + ); + + /* Initialize interrupts */ + bsp_interrupt_initialize(); + + #if MPC55XX_CHIP_FAMILY != 566 + mpc55xx_edma_init(); + #endif + + #ifdef MPC55XX_EMIOS_PRESCALER + mpc55xx_emios_initialize(MPC55XX_EMIOS_PRESCALER); + #endif +} diff --git a/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S b/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S new file mode 100644 index 0000000000..9d9e79f351 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/exc-vector-base.S @@ -0,0 +1,124 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Exception minimum prologues. + */ + +/* + * Copyright (c) 2011-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +/** + * @defgroup mpc55xx_asm Assembler files + * + * @ingroup mpc55xx + */ + +#include <bspopts.h> + +#include <bsp/vectors.h> + + .globl mpc55xx_exc_vector_base + + .section ".bsp_text", "ax" + +#if 5510 <= MPC55XX_CHIP_TYPE && MPC55XX_CHIP_TYPE <= 5517 + .align 12 +#else + .align 16 +#endif + +mpc55xx_exc_vector_base: + + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32767 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 2 + b ppc_exc_wrap_nopush_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 3 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 4 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32763 + b ppc_exc_interrupt + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 6 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 7 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 8 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 12 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 24 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32752 + b ppc_exc_interrupt + stwu r1, -PPC_EXC_INTERRUPT_FRAME_SIZE(r1) + stw r3, GPR3_OFFSET(r1) + li r3, -32749 + b ppc_exc_interrupt + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32748 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 18 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 17 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 13 + b ppc_exc_wrap_nopush_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 10 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 25 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 26 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 15 + b ppc_exc_wrap_nopush_std diff --git a/bsps/powerpc/mpc55xxevb/start/get-system-clock.c b/bsps/powerpc/mpc55xxevb/start/get-system-clock.c new file mode 100644 index 0000000000..42e2b38327 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/get-system-clock.c @@ -0,0 +1,85 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief System clock calculation. + */ + +/* + * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +uint32_t mpc55xx_get_system_clock(void) +{ + uint32_t system_clock = 0; + + #ifdef MPC55XX_HAS_FMPLL + volatile struct FMPLL_tag *fmpll = &FMPLL; + union FMPLL_SYNSR_tag synsr = { .R = fmpll->SYNSR.R }; + uint32_t reference_clock = MPC55XX_REFERENCE_CLOCK; + bool pll_clock_mode = synsr.B.MODE != 0; + bool crystal_or_external_reference_mode = synsr.B.PLLSEL != 0; + + if (pll_clock_mode) { + if (crystal_or_external_reference_mode) { + union FMPLL_SYNCR_tag syncr = { .R = fmpll->SYNCR.R }; + uint32_t prediv = syncr.B.PREDIV; + uint32_t mfd = syncr.B.MFD; + uint32_t rfd = syncr.B.RFD; + + system_clock = ((reference_clock * (mfd + 4)) >> rfd) / (prediv + 1); + } else { + system_clock = 2 * reference_clock; + } + } else { + system_clock = reference_clock; + } + #endif + + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + volatile struct FMPLL_tag *fmpll = &FMPLL; + union FMPLL_ESYNCR1_tag esyncr1 = { .R = fmpll->ESYNCR1.R }; + uint32_t reference_clock = MPC55XX_REFERENCE_CLOCK; + bool normal_mode = (esyncr1.B.CLKCFG & 0x4U) != 0; + + if (normal_mode) { + union FMPLL_ESYNCR2_tag esyncr2 = { .R = fmpll->ESYNCR2.R }; + uint32_t eprediv = esyncr1.B.EPREDIV; + uint32_t emfd = esyncr1.B.EMFD; + uint32_t erfd = esyncr2.B.ERFD; + + system_clock = ((reference_clock / (eprediv + 1)) * (emfd + 16)) + / (erfd + 1); + } else { + system_clock = reference_clock; + } + #endif + + #ifdef MPC55XX_HAS_MODE_CONTROL + /* FIXME: Assumes normal mode and external oscillator */ + PLLD_CR_32B_tag cr = { . R = CGM.FMPLL [0].CR.R }; + uint32_t xosc = MPC55XX_REFERENCE_CLOCK; + uint32_t ldf = cr.B.NDIV; + uint32_t idf = cr.B.IDF + 1; + uint32_t odf = 2U << cr.B.ODF; + + system_clock = (xosc * ldf) / (idf * odf); + #endif + + return system_clock; +} diff --git a/bsps/powerpc/mpc55xxevb/start/idle-thread.c b/bsps/powerpc/mpc55xxevb/start/idle-thread.c new file mode 100644 index 0000000000..45bea8e418 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/idle-thread.c @@ -0,0 +1,34 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief bsp_idle_thread() implementation. + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> + +#include <mpc55xx/mpc55xx.h> + +void *bsp_idle_thread(uintptr_t arg) +{ + while (true) { + mpc55xx_wait_for_interrupt(); + } + + return NULL; +} diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds b/bsps/powerpc/mpc55xxevb/start/linkcmds new file mode 100644 index 0000000000..5c2161deba --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds @@ -0,0 +1 @@ +include linkcmds.mpc55xxevb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm b/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm new file mode 100644 index 0000000000..cabaac2201 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.gwlcfm @@ -0,0 +1,27 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 1536K + RAM : ORIGIN = 0x40000000, LENGTH = 80K + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb new file mode 100644 index 0000000000..4f63fb0e0a --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb @@ -0,0 +1,27 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 3M + RAM : ORIGIN = 0x40000000, LENGTH = 128K + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe new file mode 100644 index 0000000000..9255b15076 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5566evb_spe @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5566evb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx new file mode 100644 index 0000000000..2c4e1e3f7b --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc55xx @@ -0,0 +1,22 @@ +bsp_ram_start = ORIGIN (RAM); +bsp_ram_size = LENGTH (RAM) + LENGTH (NOCACHE); +bsp_ram_end = bsp_ram_start + bsp_ram_size; + +bsp_rom_start = ORIGIN (ROM); +bsp_rom_size = LENGTH (ROM); +bsp_rom_end = bsp_rom_start + bsp_rom_size; + +INCLUDE linkcmds.base + +SECTIONS { + .work_bonus : { + /* + * This section will occupy the remaining RAM_EXT region and may + * contain parts of the RTEMS work space and heap. + */ + bsp_section_work_bonus_begin = .; + . += ORIGIN (RAM_EXT) + LENGTH (RAM_EXT) - ABSOLUTE (.); + bsp_section_work_bonus_end = .; + } > RAM_EXT AT > RAM_EXT + bsp_section_work_bonus_size = bsp_section_work_bonus_end - bsp_section_work_bonus_begin; +} diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu new file mode 100644 index 0000000000..2f7d80716d --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_dpu @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5643l_evb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb new file mode 100644 index 0000000000..1977c92d59 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5643l_evb @@ -0,0 +1,33 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 1M + RAM : ORIGIN = 0x40000000, LENGTH = 64K + RAM_1 : ORIGIN = 0x50000000, LENGTH = 64K + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("RAM_EXT", RAM); + +bsp_ram_1_start = ORIGIN (RAM_1); +bsp_ram_1_size = LENGTH (RAM_1); +bsp_ram_1_end = bsp_ram_1_start + bsp_ram_1_size; + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM_1); +REGION_ALIAS ("REGION_STACK", RAM_1); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g new file mode 100644 index 0000000000..6c8e5a64f1 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5668g @@ -0,0 +1,29 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 2M + RAM : ORIGIN = 0x40000000, LENGTH = 256K - 16k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("RAM_EXT", RAM); + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 new file mode 100644 index 0000000000..1e52a3c6c3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508 @@ -0,0 +1,51 @@ +MEMORY { + DSROM : ORIGIN = 0x00020000, LENGTH = 64k + SYSROM : ORIGIN = 0x00100000, LENGTH = 4k + RAM : ORIGIN = 0x40000000, LENGTH = 240k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + DSRAM : ORIGIN = 0x20000000, LENGTH = 64k + RAM_EXT : ORIGIN = 0x20010000, LENGTH = 444k + SYSRAM : ORIGIN = 0x2007f000, LENGTH = 4k + NVRAM : ORIGIN = 0x3ffa0000, LENGTH = 128k +} + +REGION_ALIAS ("REGION_START", STARTROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", NVRAM); + +SECTIONS { + .dsram (NOLOAD) : { + bsp_section_dsram_begin = .; + *(SORT(.bsp_dsram*)) + bsp_section_dsram_end = .; + } > DSRAM AT > DSROM + bsp_section_dsram_size = bsp_section_dsram_end - bsp_section_dsram_begin; + bsp_section_dsram_load_begin = LOADADDR (.dsram); + bsp_section_dsram_load_end = bsp_section_dsram_load_begin + bsp_section_dsram_size; + + .sysram : { + bsp_section_sysram_begin = .; + *(SORT(.bsp_sysram*)) + bsp_section_sysram_end = .; + } > SYSRAM AT > SYSROM + bsp_section_sysram_size = bsp_section_sysram_end - bsp_section_sysram_begin; + bsp_section_sysram_load_begin = LOADADDR (.sysram); + bsp_section_sysram_load_end = bsp_section_sysram_load_begin + bsp_section_sysram_size; +} + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app new file mode 100644 index 0000000000..4b94ac50c4 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_app @@ -0,0 +1,8 @@ +MEMORY { + /* Let space for the binary image library header */ + ROM : ORIGIN = 0x00101000, LENGTH = 3064k +} + +REGION_ALIAS ("STARTROM", ROM); + +INCLUDE linkcmds.mpc5674f_ecu508 diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot new file mode 100644 index 0000000000..6dc5a7fcb0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_ecu508_boot @@ -0,0 +1,6 @@ +MEMORY { + STARTROM : ORIGIN = 0x0, LENGTH = 32k + ROM : ORIGIN = 0x40000, LENGTH = 768k +} + +INCLUDE linkcmds.mpc5674f_ecu508 diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 new file mode 100644 index 0000000000..c96f8b9078 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6 @@ -0,0 +1,6 @@ +MEMORY { + STARTROM : ORIGIN = 0x0, LENGTH = 32k + ROM : ORIGIN = 0x40000, LENGTH = 768k +} + +INCLUDE linkcmds.mpc5674f_rsm6_base diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base new file mode 100644 index 0000000000..8f6a403ca8 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674f_rsm6_base @@ -0,0 +1,28 @@ +MEMORY { + RAM : ORIGIN = 0x40000000, LENGTH = 240k + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + MRAM : ORIGIN = 0x20000000, LENGTH = 4M +} + +REGION_ALIAS ("RAM_EXT", RAM); + +REGION_ALIAS ("REGION_START", STARTROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", MRAM); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb new file mode 100644 index 0000000000..3113fb20b7 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb @@ -0,0 +1,28 @@ +MEMORY { + ROM : ORIGIN = 0x0, LENGTH = 4M + RAM : ORIGIN = 0x40000000, LENGTH = 256K - 16k + RAM_EXT : ORIGIN = 0x20000000, LENGTH = 512K + NOCACHE : ORIGIN = 0x4003c000, LENGTH = 16k + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", ROM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe new file mode 100644 index 0000000000..eab0907009 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.mpc5674fevb_spe @@ -0,0 +1 @@ +INCLUDE linkcmds.mpc5674fevb diff --git a/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 b/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 new file mode 100644 index 0000000000..77b8abc5e0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/linkcmds.phycore_mpc5554 @@ -0,0 +1,36 @@ +/* + * Debug RAM is the top 4MB of external RAM and is swapped with the + * FLASH for development. + */ +MEMORY { + ROM : ORIGIN = 0x00000000, LENGTH = 2M + RAM : ORIGIN = 0x40000000, LENGTH = 64K + RAM_EXT : ORIGIN = 0x21000000, LENGTH = 4M + DEBUG_RAM : ORIGIN = 0x21400000, LENGTH = 4M + NOCACHE : ORIGIN = 0x0, LENGTH = 0 +} + +bsp_debug_ram_start = ORIGIN (DEBUG_RAM); +bsp_debug_ram_end = ORIGIN (DEBUG_RAM) + LENGTH (DEBUG_RAM); +bsp_debug_ram_size = LENGTH (DEBUG_RAM); + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM_EXT); +REGION_ALIAS ("REGION_RWEXTRA", RAM_EXT); +REGION_ALIAS ("REGION_WORK", RAM_EXT); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", NOCACHE); +REGION_ALIAS ("REGION_NVRAM", NOCACHE); + +INCLUDE linkcmds.mpc55xx diff --git a/bsps/powerpc/mpc55xxevb/start/restart.c b/bsps/powerpc/mpc55xxevb/start/restart.c new file mode 100644 index 0000000000..495aa39a95 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/restart.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + void (*start)(void) = addr; + + (void) level; + rtems_interrupt_disable(level); + (*start)(); +} diff --git a/bsps/powerpc/mpc55xxevb/start/sd-card-init.c b/bsps/powerpc/mpc55xxevb/start/sd-card-init.c new file mode 100644 index 0000000000..f6e0484122 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/sd-card-init.c @@ -0,0 +1,163 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief SD Card initialization code. + */ + +/* + * Copyright (c) 2008 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdio.h> + +#include <mpc55xx/mpc55xx.h> +#include <mpc55xx/regs.h> +#include <mpc55xx/dspi.h> + +#include <bsp.h> + +#include <rtems/status-checks.h> + +#ifdef MPC55XX_BOARD_MPC5566EVB + +static rtems_status_code mpc55xx_dspi_init(void) +{ + int rv = 0; + int i = 0; + char device_name [] = "/dev/spi0"; + union SIU_PCR_tag pcr = MPC55XX_ZERO_FLAGS; + + rv = rtems_libi2c_initialize(); + RTEMS_CHECK_RV_SC( rv, "rtems_libi2c_initialize"); + + /* DSPI D inputs are taken from DSPI C */ + SIU.DISR.R = 0x000000FC; + + /* DSPI A signals */ + pcr.B.PA = 1; + pcr.B.ODE = 0; + pcr.B.HYS = 0; + pcr.B.SRC = 3; + pcr.B.WPE = 1; + pcr.B.WPS = 1; + + /* SCK */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [93].R = pcr.R; + + /* SIN */ + pcr.B.OBE = 0; + pcr.B.IBE = 1; + SIU.PCR [94].R = pcr.R; + + /* SOUT */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [95].R = pcr.R; + + /* PCSx */ + pcr.B.OBE = 1; + pcr.B.IBE = 0; + SIU.PCR [96].R = pcr.R; + SIU.PCR [97].R = pcr.R; + SIU.PCR [98].R = pcr.R; + SIU.PCR [99].R = pcr.R; + SIU.PCR [100].R = pcr.R; + SIU.PCR [101].R = pcr.R; + + mpc55xx_dspi_bus_table [3].master = 0; + for (i = 0; i < MPC55XX_DSPI_NUMBER; ++i) { + device_name [8] = (char) ('0' + i); + rv = rtems_libi2c_register_bus( device_name, (rtems_libi2c_bus_t *) &mpc55xx_dspi_bus_table [i]); + RTEMS_CHECK_RV_SC( rv, device_name); + } + + return RTEMS_SUCCESSFUL; +} + +#include <stdio.h> +#include <rtems/fsmount.h> +#include <rtems/dosfs.h> +#include <rtems/bdpart.h> +#include <rtems/console.h> + +#include <libchip/spi-sd-card.h> + +#define MPC55XX_DEVICE "sd-card-a" +#define MPC55XX_DEVICE_FILE "/dev/" MPC55XX_DEVICE +#define MPC55XX_PARTITION "/dev/sd-card-a1" +#define MPC55XX_MOUNT_POINT "/mnt" + +static fstab_t mpc55xx_fs_table [] = { { + MPC55XX_PARTITION, MPC55XX_MOUNT_POINT, + "dosfs", RTEMS_FILESYSTEM_READ_WRITE, + FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, + FSMOUNT_MNT_OK + }, { + MPC55XX_DEVICE_FILE, MPC55XX_MOUNT_POINT, + "dosfs", RTEMS_FILESYSTEM_READ_WRITE, + FSMOUNT_MNT_OK | FSMOUNT_MNTPNT_CRTERR | FSMOUNT_MNT_FAILED, + 0 + } +}; + +sd_card_driver_entry sd_card_driver_table [] = { + { + .device_name = "/dev/sd-card-a", + .bus = 0, + .transfer_mode = SD_CARD_TRANSFER_MODE_DEFAULT, + .command = SD_CARD_COMMAND_DEFAULT, + /* response : whatever, */ + .response_index = SD_CARD_COMMAND_SIZE, + .n_ac_max = SD_CARD_N_AC_MAX_DEFAULT, + .block_number = 0, + .block_size = 0, + .block_size_shift = 0, + .busy = true, + .verbose = true, + .schedule_if_busy = false + } +}; + +size_t sd_card_driver_table_size = sizeof( sd_card_driver_table) / sizeof( sd_card_driver_table [0]); + +rtems_status_code mpc55xx_sd_card_init( bool mount) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + int rv = 0; + sd_card_driver_entry *e = &sd_card_driver_table [0]; + + RTEMS_DEBUG_PRINT( "Task started\n"); + + sc = mpc55xx_dspi_init(); + RTEMS_CHECK_SC( rv, "Intitalize DSPI bus"); + + e->bus = mpc55xx_dspi_bus_table [0].bus_number; + + sc = sd_card_register(); + RTEMS_CHECK_SC( sc, "Register SD Card"); + + if (mount) { + sc = rtems_bdpart_register_from_disk( MPC55XX_DEVICE_FILE); + RTEMS_CHECK_SC( sc, "Initialize IDE partition table"); + + rv = rtems_fsmount( mpc55xx_fs_table, sizeof( mpc55xx_fs_table) / sizeof( mpc55xx_fs_table [0]), NULL); + RTEMS_CHECK_RV_SC( rv, "Mount file systems"); + } + + return RTEMS_SUCCESSFUL; +} + +#endif /* MPC55XX_BOARD_MPC5566EVB */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-cache.S b/bsps/powerpc/mpc55xxevb/start/start-cache.S new file mode 100644 index 0000000000..c30de57fc6 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-cache.S @@ -0,0 +1,114 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Cache initialization. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> + +#include <mpc55xx/regs.h> + + .globl mpc55xx_start_cache + + .section ".bsp_start_text", "ax" + +mpc55xx_start_cache: + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + + /* Load zero, CINV, and CABT) */ + li r0, 0 + li r3, 0x2 + li r4, 0x4 + +#if defined(BSP_INSTRUCTION_CACHE_ENABLED) \ + && defined(MPC55XX_HAS_INSTRUCTION_CACHE) + +start_instruction_cache_invalidation: + + /* Clear instruction cache invalidation abort */ + mtspr FSL_EIS_L1CSR1, r0 + + /* Start instruction cache invalidation */ + mtspr FSL_EIS_L1CSR1, r3 + +get_instruction_cache_invalidation_status: + + /* Get instruction cache invalidation status */ + mfspr r5, FSL_EIS_L1CSR1 + + /* Check CABT */ + and. r6, r5, r4 + bne start_instruction_cache_invalidation + + /* Check CINV */ + and. r6, r5, r3 + bne get_instruction_cache_invalidation_status + + /* Save instruction cache settings */ + LWI r6, 0x00010001 + isync + msync + mtspr FSL_EIS_L1CSR1, r6 + +#endif + +#if (defined(BSP_DATA_CACHE_ENABLED) && defined(MPC55XX_HAS_DATA_CACHE)) \ + || ((defined(BSP_DATA_CACHE_ENABLED) \ + || defined(BSP_INSTRUCTION_CACHE_ENABLED)) \ + && defined(MPC55XX_HAS_UNIFIED_CACHE)) + +start_data_cache_invalidation: + + /* Clear data cache invalidation abort */ + mtspr FSL_EIS_L1CSR0, r0 + + /* Start data cache invalidation */ + mtspr FSL_EIS_L1CSR0, r3 + +get_data_cache_invalidation_status: + + /* Get data cache invalidation status */ + mfspr r5, FSL_EIS_L1CSR0 + + /* Check CABT */ + and. r6, r5, r4 + bne start_data_cache_invalidation + + /* Check CINV */ + and. r6, r5, r3 + bne get_data_cache_invalidation_status + + /* Save data cache settings */ +#if MPC55XX_CHIP_FAMILY != 567 + /* FIXME: CORG??? 0x00180011 */ + LWI r6, 0x00100001 +#else + LWI r6, 0x00190001 +#endif + isync + msync + mtspr FSL_EIS_L1CSR0, r6 + +#endif + +#endif /* MPC55XX_NEEDS_LOW_LEVEL_INIT */ + + /* Return */ + blr diff --git a/bsps/powerpc/mpc55xxevb/start/start-clock.c b/bsps/powerpc/mpc55xxevb/start/start-clock.c new file mode 100644 index 0000000000..85468d5cb0 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-clock.c @@ -0,0 +1,104 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Clock and FMPLL initialization code. + */ + +/* + * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/fatal.h> +#include <bsp/start.h> +#include <bsp/bootcard.h> +#include <bsp/mpc55xx-config.h> + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #if defined(MPC55XX_HAS_FMPLL) || defined(MPC55XX_HAS_FMPLL_ENHANCED) + static BSP_START_TEXT_SECTION void fmpll_wait_for_lock(void) + { + int i = 0; + bool lock = false; + + while (!lock && i < 6000) { + lock = FMPLL.SYNSR.B.LOCK != 0; + ++i; + } + + if (!lock) { + bsp_fatal(MPC55XX_FATAL_FMPLL_LOCK); + } + } + #endif +#endif + +BSP_START_TEXT_SECTION void mpc55xx_start_clock(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + const mpc55xx_clock_config *cfg = mpc55xx_start_config_clock; + + #ifdef MPC55XX_HAS_FMPLL + volatile struct FMPLL_tag *fmpll = &FMPLL; + + fmpll->SYNCR.R = cfg->syncr_tmp.R; + fmpll->SYNCR.R; + fmpll_wait_for_lock(); + + fmpll->SYNCR.R = cfg->syncr_final.R; + fmpll->SYNCR.R; + fmpll_wait_for_lock(); + #endif + + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + volatile struct FMPLL_tag *fmpll = &FMPLL; + + fmpll->ESYNCR2.R = cfg->esyncr2_tmp.R; + fmpll->ESYNCR2.R; + fmpll->ESYNCR1.R = cfg->esyncr1_final.R; + fmpll->ESYNCR1.R; + fmpll_wait_for_lock(); + + fmpll->ESYNCR2.R = cfg->esyncr2_final.R; + fmpll->ESYNCR2.R; + fmpll_wait_for_lock(); + + #if MPC55XX_CHIP_FAMILY == 551 || MPC55XX_CHIP_FAMILY == 566 + /* System clock supplied by PLL */ + SIU.SYSCLK.B.SYSCLKSEL = 2; + #endif + #endif + + #ifdef MPC55XX_HAS_MODE_CONTROL + volatile CGM_tag *cgm = &CGM; + size_t fmpll_count = sizeof(cfg->fmpll) / sizeof(cfg->fmpll [0]); + size_t auxclk_count = sizeof(cfg->auxclk) / sizeof(cfg->auxclk [0]); + size_t i = 0; + + for (i = 0; i < auxclk_count; ++i) { + cgm->AUXCLK [i].AC_SC.R = cfg->auxclk [i].AC_SC.R; + cgm->AUXCLK [i].AC_DC0_3.R = cfg->auxclk [i].AC_DC0_3.R; + } + + for (i = 0; i < fmpll_count; ++i) { + cgm->FMPLL [i].CR.R = cfg->fmpll [i].cr.R; + cgm->FMPLL [i].MR.R = cfg->fmpll [i].mr.R; + } + + cgm->OC_EN.R = cfg->oc_en.R; + cgm->OCDS_SC.R = cfg->ocds_sc.R; + #endif + #endif +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-clock.c b/bsps/powerpc/mpc55xxevb/start/start-config-clock.c new file mode 100644 index 0000000000..d820af3755 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-clock.c @@ -0,0 +1,132 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Clock and FMPLL configuration. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +const mpc55xx_clock_config mpc55xx_start_config_clock [1] = { { + #ifdef MPC55XX_HAS_FMPLL + .syncr_tmp = { + .B = { + .PREDIV = MPC55XX_FMPLL_PREDIV - 1, + .MFD = MPC55XX_FMPLL_MFD, + .RFD = 2, + .LOCEN = 1 + } + }, + .syncr_final = { + .B = { + .PREDIV = MPC55XX_FMPLL_PREDIV - 1, + .MFD = MPC55XX_FMPLL_MFD, + .RFD = 0, + .LOCEN = 1, + .LOLIRQ = 1, + .LOCIRQ = 1 + } + } + #endif + #ifdef MPC55XX_HAS_FMPLL_ENHANCED + #define EPREDIV_VAL (MPC55XX_FMPLL_PREDIV-1) + #define EMFD_VAL (MPC55XX_FMPLL_MFD-16) + #define VCO_CLK_REF (MPC55XX_REFERENCE_CLOCK/(EPREDIV_VAL+1)) + #define VCO_CLK_OUT (VCO_CLK_REF*(EMFD_VAL+16)) + #define ERFD_VAL \ + (((VCO_CLK_OUT + MPC55XX_SYSTEM_CLOCK - 1) / MPC55XX_SYSTEM_CLOCK)-1) + + .esyncr2_tmp = { + .B = { + .LOCEN = 0, + .LOLRE = 0, + .LOCRE = 0, + .LOLIRQ = 0, + .LOCIRQ = 0, + .ERATE = 0, + .EDEPTH = 0, + .ERFD = ERFD_VAL + 2 /* reduce output clock during init */ + } + }, + .esyncr2_final = { + .B = { + .LOCEN = 0, + .LOLRE = 0, + .LOCRE = 0, + .LOLIRQ = 0, + .LOCIRQ = 0, + .ERATE = 0, + #if MPC55XX_CHIP_FAMILY == 567 + .CLKCFG_DIS = 1, + #endif + .EDEPTH = 0, + .ERFD = ERFD_VAL /* nominal output clock after init */ + } + }, + .esyncr1_final = { + .B = { + .CLKCFG = MPC55XX_FMPLL_ESYNCR1_CLKCFG, + .EPREDIV = EPREDIV_VAL, + .EMFD = EMFD_VAL + } + } + #endif + #ifdef MPC55XX_HAS_MODE_CONTROL + .fmpll = { + { + .cr = { + #if MPC55XX_REFERENCE_CLOCK == 8000000 + .B = { .IDF = 0, .ODF = 1, .NDIV = 60, .I_LOCK = 1, .PLL_ON = 1 } + #elif MPC55XX_REFERENCE_CLOCK == 40000000 + .B = { .IDF = 3, .ODF = 1, .NDIV = 48, .I_LOCK = 1, .PLL_ON = 1 } + #else + #error "unexpected reference clock" + #endif + } + }, + { + .cr = { + .B = { .IDF = 3, .ODF = 2, .NDIV = 32, .I_LOCK = 1, .PLL_ON = 1 } + } + } + }, + .ocds_sc = { + .B = { .SELDIV = 2, .SELCTL = 2 } + }, + .auxclk = { + [0] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 0 } } + }, + [1] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 11 } } + }, + [2] = { + .AC_SC = { .B = { .SELCTL = 4 } }, + .AC_DC0_3 = { .B = { .DE0 = 1, .DIV0 = 11 } } + }, + [3] = { + .AC_SC = { .B = { .SELCTL = 1 } } + }, + [4] = { + .AC_SC = { .B = { .SELCTL = 1 } } + } + } + #endif +} }; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c new file mode 100644 index 0000000000..69f9b61a7d --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs-cal.c @@ -0,0 +1,257 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI calibration chip-select configuration. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const struct EBI_CAL_CS_tag mpc55xx_start_config_ebi_cal_cs [] = { +#if defined(MPC55XX_BOARD_MPC5674FEVB) + /* External SRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 1, + .WEBS = 0, + .TBDIP = 1, + .SETA = 0, + .BI = 0, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + /* External Ethernet controller */ + { + .BR = { + .B = { + .BA = 0x3fff8000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + } +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* D_CS0 for external SRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 1, + .WEBS = 0, + .TBDIP = 1, + .SETA = 0, + .BI = 0, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffe00000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS1 for Ethernet Controller */ + { + .BR = { + .B = { + .BA = 0x3fff8000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffff8000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + }, + + /* D_CS2 unused */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 0 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS3 for MRAM, ARCNET */ + { + .BR = { + .B = { + .BA = 0x3ff80000 >> 15, + .PS = 1, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 1, + .BSCY = 0 + } + } + } +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + /* D_CS0 for MRAM */ + { + .BR = { + .B = { + .BA = 0x20000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xffc00000 >> 15, + .SCY = 4, + .BSCY = 0 + } + } + }, + + /* D_CS1 for FPGA */ + { + .BR = { + .B = { + .BA = 0x21000000 >> 15, + .PS = 0, + .AD_MUX = 1, + .BL = 0, + .WEBS = 0, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xff800000 >> 15, + .SCY = 0, + .BSCY = 0 + } + } + }, + + /* D_CS2 unused */ + { + .BR = { .R = 0x20000002 }, + .OR = { .R = 0xe0000000 } + }, + + /* D_CS3 for Ethernet Controller */ + { + .BR = { + .B = { + .BA = 0x23000000 >> 15, + .PS = 1, + .AD_MUX = 1, + .BL = 0, + .WEBS = 1, + .TBDIP = 0, + .SETA = 0, + .BI = 1, + .V = 1 + } + }, + .OR = { + .B = { + .AM = 0xfff80000 >> 15, + .SCY = 8, + .BSCY = 0 + } + } + } +#endif +}; + +const size_t mpc55xx_start_config_ebi_cal_cs_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi_cal_cs) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c new file mode 100644 index 0000000000..d12d0fa059 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi-cs.c @@ -0,0 +1,164 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI chip-select configuration. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const struct EBI_CS_tag mpc55xx_start_config_ebi_cs [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + /* CS0: External SRAM (16 bit, 1 wait states, 512kB, no burst) */ + { + { + .B.BA = 0x20000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 1, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1fff0, + .B.SCY = 1, + .B.BSCY = 0 + } + }, + /* CS1: External USB controller (16 bit, 3 wait states, 32kB, no burst) */ + { + { + .B.BA = 0x22000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1ffff, + .B.SCY = 3, + .B.BSCY = 0 + } + }, + /* CS2: Ethernet (16 bit, 2 wait states, 32kB, no burst) */ + { + { + .B.BA = 0x22800000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 1, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + { + .B.AM = 0x1ffff, + .B.SCY = 1, + .B.BSCY = 0 + } + }, + { /* CS3: MOST Companion. */ + { + .B.BA = 0x23000000>>15, + .B.PS = 1, + .B.AD_MUX = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + + { + .B.AM = 0x1fff0, + .B.SCY = 1, + .B.BSCY = 0 + } + } +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + /* CS0: External flash. */ + { + { .R = 0x20000003 }, /* Base 0x2000000, Burst Inhibit, Valid */ + { .R = 0xff000050 } + }, + /* CS1: External synchronous burst mode SRAM. */ + { + { .R = 0x21000051 }, /* Base 0x2100000, 4-word Burst Enabled, Valid */ + { .R = 0xff000000 } /* No wait states. */ + }, + /* CS2: External LAN91C111 */ + { + { .R = 0x22000003 }, /* Base 0x22000000, Burst inhibit, valid */ + { .R = 0xff000010 } + }, + + /* CS3: External FPGA */ + { + { .R = 0x23000003 }, /* Base 0x23000000, Burst inhibit, valid. */ + { .R = 0xff000020 } + } +#elif defined(MPC55XX_BOARD_MPC5566EVB) + /* CS0: External SRAM (2 wait states, 512kB, 4 word burst) */ + { + { + .B.BA = 0, + .B.PS = 1, + .B.BL = 1, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, /* TODO: Enable burst */ + .B.V = 1 + }, + + { + .B.AM = 0x1fff0, + .B.SCY = 0, + .B.BSCY = 0 + } + }, + { { .R = 0 }, { .R = 0 } }, /* CS1: Unused. */ + { { .R = 0 }, { .R = 0 } }, /* CS2: Unused. */ + { /* CS3: ethernet? */ + { + .B.BA = 0x7fff, + .B.PS = 1, + .B.BL = 0, + .B.WEBS = 0, + .B.TBDIP = 0, + .B.BI = 1, + .B.V = 1 + }, + + { + .B.AM = 0x1ffff, + .B.SCY = 1, + .B.BSCY = 0 + } + } +#endif +}; + +const size_t mpc55xx_start_config_ebi_cs_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi_cs) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c b/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c new file mode 100644 index 0000000000..1ce2b297d8 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-ebi.c @@ -0,0 +1,62 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief EBI configuration. + */ + +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +#ifdef MPC55XX_HAS_EBI + +const mpc55xx_ebi_config mpc55xx_start_config_ebi [] = { + #if defined(MPC55XX_BOARD_GWLCFM) + { + .ebi_mcr = { + .B = { + .DBM = 1, + .AD_MUX = 1, /* use multiplexed bus */ + .D16_31 = 1 /* use lower AD bus */ + } + }, + .siu_eccr_ebdf = 4 - 1 /* use CLK/4 as bus clock */ + } + #elif (defined(MPC55XX_BOARD_MPC5674FEVB) \ + || defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + || defined(MPC55XX_BOARD_MPC5674F_RSM6)) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + { + .ebi_mcr = { + .B = { + .ACGE = 0, + .MDIS = 0, + .D16_31 = 1, + .AD_MUX = 0, + .DBM = 0 + } + }, + .siu_eccr_ebdf = 2 - 1 + } + #endif +}; + +const size_t mpc55xx_start_config_ebi_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_ebi) +}; + +#endif /* MPC55XX_HAS_EBI */ diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c b/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c new file mode 100644 index 0000000000..84e638d55c --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-mmu-early.c @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief MMU early configuration. + */ + +/* + * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +const struct MMU_tag mpc55xx_start_config_mmu_early [] = { +#if (defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + || defined(MPC55XX_BOARD_MPC5674F_RSM6)) \ + && !defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* Used as cache-inhibited area later (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 555 + /* Internal SRAM 96k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0), +#elif MPC55XX_CHIP_FAMILY == 556 + /* Internal SRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40010000, MPC55XX_MMU_64K, 0, 1, 1, 0), +#elif MPC55XX_CHIP_FAMILY == 564 + /* Internal flash 1M */ + MPC55XX_MMU_TAG_INITIALIZER(0, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 1), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0xffe00000, MPC55XX_MMU_2M, 0, 1, 1, 1), + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 64k + 64k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x50000000, MPC55XX_MMU_64K, 0, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 566 + /* Internal flash 2M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40040000, MPC55XX_MMU_256K, 1, 1, 1, 0) +#elif MPC55XX_CHIP_FAMILY == 567 + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 1, 1, 1, 0) +#endif +}; + +const size_t mpc55xx_start_config_mmu_early_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_mmu_early) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c b/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c new file mode 100644 index 0000000000..7cf319edd3 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-mmu.c @@ -0,0 +1,151 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief MMU configuration. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +const struct MMU_tag mpc55xx_start_config_mmu [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + /* External Ethernet Controller 64k */ + MPC55XX_MMU_TAG_INITIALIZER(5, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + /* Arguments macro: idx, addr, size, x, w, r, io */ + MPC55XX_MMU_TAG_INITIALIZER(8, 0x20000000, MPC55XX_MMU_8M, 1, 0, 1, 0), /* External FLASH 8M */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x21000000, MPC55XX_MMU_4M, 0, 1, 1, 0), /* Lower half SRAM */ + MPC55XX_MMU_TAG_INITIALIZER(5, 0x21400000, MPC55XX_MMU_4M, 1, 1, 1, 0), /* Upper half SRAM ("debug") */ + MPC55XX_MMU_TAG_INITIALIZER(6, 0x22000000, MPC55XX_MMU_16M, 0, 1, 1, 1), /* LAN91C111 */ + MPC55XX_MMU_TAG_INITIALIZER(7, 0x23000000, MPC55XX_MMU_16M, 0, 1, 1, 1), /* FPGA */ +#elif defined(MPC55XX_BOARD_MPC5566EVB) + /* Internal flash 3M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00020000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00030000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00080000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x000c0000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x00200000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* External SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(14, 0x20040000, MPC55XX_MMU_256K, 0, 1, 1, 0), + /* Internal SRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x40010000, MPC55XX_MMU_64K, 0, 1, 1, 0), + /* External Ethernet Controller 64k */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_MPC5674FEVB) + /* Internal flash 4M */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External SRAM 512k */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_512K, 0, 1, 1, 0), + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_128K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_64K, 0, 1, 1, 1) +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) + #if defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + /* Arguments macro: idx, addr, size, x, w, r, io */ + + /* Internal flash 4M */ + /* First 64k unused, to detect NULL pointer access */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External SRAM 2M */ + #ifndef BSP_DATA_CACHE_USE_WRITE_THROUGH + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_2M, 0, 1, 1, 0), + #else + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_2M, 0, 1, 1, 2), + #endif + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x3fff8000, MPC55XX_MMU_1K, 0, 1, 1, 1), + /* External MRAM 128k */ + MPC55XX_MMU_TAG_INITIALIZER(16, 0x3ffa0000, MPC55XX_MMU_128K, 0, 1, 1, 0), + /* External ARCNET controller */ + MPC55XX_MMU_TAG_INITIALIZER(17, 0x3ffc0000, MPC55XX_MMU_1K, 0, 1, 1, 1) + /* Peripheral Bridge A-Registers on MMU-table pos 4 */ + /* Peripheral Bridge B-Registers on MMU-table pos 0 */ + #else + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1) + #endif +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + /* Arguments macro: idx, addr, size, x, w, r, io */ + + /* Internal flash 4M */ + /* First 64k unused, to detect NULL pointer access */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0x00000000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(5, 0x00010000, MPC55XX_MMU_64K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(6, 0x00020000, MPC55XX_MMU_128K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(7, 0x00040000, MPC55XX_MMU_256K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(8, 0x00080000, MPC55XX_MMU_512K, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(9, 0x00100000, MPC55XX_MMU_1M, 1, 0, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(10, 0x00200000, MPC55XX_MMU_2M, 1, 0, 1, 0), + /* External MRAM 4M */ + MPC55XX_MMU_TAG_INITIALIZER(2, 0x20000000, MPC55XX_MMU_4M, 0, 1, 1, 0), + /* Internal SRAM 256k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_256K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(11, 0x40020000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(12, 0x40030000, MPC55XX_MMU_32K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(13, 0x40038000, MPC55XX_MMU_16K, 0, 1, 1, 0), + /* Used as cache-inhibited area (ADC, DSPI queues) */ + MPC55XX_MMU_TAG_INITIALIZER(14, 0x4003c000, MPC55XX_MMU_16K, 0, 1, 1, 1), + /* External FPGA */ + MPC55XX_MMU_TAG_INITIALIZER(15, 0x21000000, MPC55XX_MMU_8M, 0, 1, 1, 1), + /* External Ethernet controller */ + MPC55XX_MMU_TAG_INITIALIZER(16, 0x23000000, MPC55XX_MMU_1K, 0, 1, 1, 1) +#elif MPC55XX_CHIP_FAMILY == 564 + /* Internal flash 1M */ + MPC55XX_MMU_TAG_INITIALIZER(0, 0x00000000, MPC55XX_MMU_1M, 1, 0, 1, 0), + /* IO */ + MPC55XX_MMU_TAG_INITIALIZER(1, 0xffe00000, MPC55XX_MMU_2M, 0, 1, 1, 1), + MPC55XX_MMU_TAG_INITIALIZER(2, 0xc3f00000, MPC55XX_MMU_1M, 0, 1, 1, 1), + /* Internal SRAM 64k + 64k */ + MPC55XX_MMU_TAG_INITIALIZER(3, 0x40000000, MPC55XX_MMU_64K, 0, 1, 1, 0), + MPC55XX_MMU_TAG_INITIALIZER(4, 0x50000000, MPC55XX_MMU_64K, 0, 1, 1, 0) +#endif +}; + +const size_t mpc55xx_start_config_mmu_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_mmu) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c b/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c new file mode 100644 index 0000000000..8355e647ca --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-config-siu-pcr.c @@ -0,0 +1,148 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief SIU PCR configuration. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +const mpc55xx_siu_pcr_config mpc55xx_start_config_siu_pcr [] = { +#if defined(MPC55XX_BOARD_GWLCFM) + { 0,16, 0, {.B.PA = 1, .B.WPE = 0}}, /* PA[ 0..15] analog input */ + { 16, 4, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[ 0.. 4] LED/CAN_STBN out */ + { 20, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PB[ 5.. 6] CAN_ERR/USBFLGC in*/ + { 22, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[ 7 ] FR_A_EN out */ + { 23, 4, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PB[ 8..10] IRQ/FR_A_ERR/USB_RDYin */ + { 27, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PB[11..11] FR_STBN out */ + + { 32, 2, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 0.. 1] FR_A_TX/TXEN out */ + { 34, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 2.. 2] FR_A_RX in */ + { 35, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 3.. 4] INIT_ERR/ISB_IRQ in */ + { 37, 2, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 5.. 6] PWRO1/2_ON out */ + { 39, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PC[ 7.. 7] FR_B_RX in */ + { 40, 2, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PC[ 8.. 9] FR_B_TX/TXEN out */ + { 42, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[10 ] FR_B_EN out */ + { 43, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[11 ] FOR_STATUS in */ + { 44, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[12 ] FR_B_ERRN in */ + { 45, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[13 ] HS_CAN_STBN out */ + { 46, 1, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PC[14 ] HS_CAN_ERR in */ + { 47, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PC[15 ] HS_CAN_EN out */ + + { 48, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 0 ] HS_CAN_TX out */ + { 49, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 1 ] HS_CAN_RX in */ + { 50, 2, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 2.. 3] PWRO1/2_OC in */ + { 52, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 4 ] LS_CAN_TX out */ + { 53, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 5 ] LS_CAN_RX in */ + { 54, 1, 0, {.B.PA = 1,.B.OBE = 1,.B.WPE = 0}}, /* PD[ 6 ] HS_CAN_TX out */ + { 55, 1, 0, {.B.PA = 1,.B.IBE = 1,.B.WPE = 0}}, /* PD[ 7 ] HS_CAN_RX in */ + { 56, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.OBE = 1,.B.WPE = 0}}, + /* PD[ 8 ] I2C_SCL in/out */ + { 57, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.OBE = 1,.B.WPE = 0}}, + /* PD[ 9 ] I2C_SDA in/out */ + + { 58, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PD[10] LS_CAN_EN out*/ + { 59, 3, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, + /* PD[11..13] PWO1_OC, MOCO_INT in */ + + { 62, 4, 0, {.B.PA = 0,.B.IBE = 1,.B.WPE = 0}}, /* PD[14..15] USB_FLGA/B in */ + + { 64, 5, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PE[ 0.. 4] LED_EXT1-5. out*/ + { 70, 1, 0, {.B.PA = 1,.B.SRC = 3,.B.WPE = 0}}, /* PE[ 6.. 6] CLKOUT out*/ + + { 80, 1, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 0.. 0] RD_WR out*/ + { 81, 1, 0, {.B.PA = 0,.B.SRC = 0,.B.WPE = 0}}, /* PF[ 1.. 1] (nc) in */ + { 82, 8, 0, {.B.PA = 2,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 2..11] ADDR[8..15] out*/ + { 90, 2, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[ 2..11] CS[0..1] out*/ + { 92, 1, 0, {.B.PA = 3,.B.SRC = 3,.B.WPE = 0}}, /* PF[ 12] ALE out*/ + { 93, 3, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PF[13..15] OE/WE out*/ + + { 96,16, 0, {.B.PA = 1,.B.SRC = 1,.B.WPE = 0}}, /* PG[ 0..15] AD16..31 in/out*/ + + {113, 1, 1, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 1.. 1] RES_MOSTComp out*/ + {114, 1, 0, {.B.PA = 3,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 2.. 2] CS3_MOSTComp out*/ + {115, 1, 0, {.B.PA = 3,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 3.. 3] CS2_ETH out*/ + {116, 2, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 4.. 5] FR/HC_TERM out*/ + {118, 1, 0, {.B.PA = 2,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 6.. 6] LIN_Tx out*/ + {119, 1, 0, {.B.PA = 2,.B.IBE = 1,.B.WPE = 0}}, /* PH[ 7.. 7] LIN_Rx in */ + {120, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 8..11] LIN_SLP,RST out*/ + {121, 2, 1, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}}, /* PH[ 8..11] LIN_SLP,RST out*/ + {120, 1, 0, {.B.PA = 0,.B.OBE = 1,.B.WPE = 0}} /* PH[ 8..11] LIN_SLP,RST out*/ +#elif defined(MPC55XX_BOARD_PHYCORE_MPC5554) + { 0, 4, 0, {.B.PA = 1, .B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [0:3] */ + { 4,24, 0, {.B.PA = 1, .B.DSC = 1 }}, /* ADDR [8 : 31] */ + { 28,32, 0, {.B.PA = 1, .B.DSC = 1 }}, /* DATA [0 : 31] */ + { 60, 4, 0, {.B.PA = 1, .B.DSC = 1, }}, /* TSIZ[0:1], RD_!WR, BDIP */ + { 64, 6, 0, {.B.PA = 1, .B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* RD_!WR, BDIP, !WE, !OE, !TS */ + { 89, 4, 0, {.B.PA = 1 }}, /* ESCI_A and ESCI_B */ + {229, 4, 0, { .B.OBE= 1,.B.DSC = 1 }} /* CLKOUT */ +#elif defined(MPC55XX_BOARD_MPC5566EVB) + { 0, 1, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [0] */ + { 3, 1, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* !CS [3] */ + { 4,24, 0, {.B.PA = 1,.B.DSC = 1 }}, /* ADDR [8 : 31] */ + { 28,16, 0, {.B.PA = 1,.B.DSC = 1 }}, /* DATA [0 : 15] */ + { 62, 8, 0, {.B.PA = 1,.B.DSC = 1,.B.WPE=1,.B.WPS=1}}, /* RD_!WR, BDIP, + !WE, !OE, !TS */ + { 89, 2, 0, {.B.PA = 1 }} /* ESCI_B */ +#elif defined(MPC55XX_BOARD_MPC5674FEVB) + { 89, 2, 0, { .B = { .PA = 1 } } }, /* ESCI_A */ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT31 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 1 } } }, /* D_CS1 */ + { 302, 6, 0, { .B = { .PA = 1, .DSC = 1 } } } /* D_BDIP, D_WE2, D_WE3, D_ADD9 .. D_ADD11 */ +#elif defined(MPC55XX_BOARD_MPC5674F_ECU508) \ + && defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) + { 196, 2, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS17 .. EMIOS18 (5VS_EN, 80V_EN) */ + { 200, 4, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS21 .. EMIOS24 (\KS_RST, \LS_RST, \IGNINJ_RST, \INJDI_RST) */ + { 204, 1, 1, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS25 (HBR12_RST) */ + { 244, 2, 0, { .B = { .PA = 1 } } }, /* ESCI_C */ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT31 */ + { 258, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS3 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_CS1 */ + { 302, 3, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_BDIP, D_WE2, D_WE3 */ + { 305, 3, 0, { .B = { .PA = 1, .DSC = 0 } } }, /* D_ADD9 .. D_ADD11 */ + { 432, 1, 1, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } }, /* EMIOS26 (HBR34_RST) */ + { 433, 1, 0, { .B = { .PA = 0, .OBE = 1, .WPE = 0 } } } /* EMIOS27 (\ETH_RST) */ +#elif defined(MPC55XX_BOARD_MPC5674F_RSM6) + { 89, 1, 0, { .B = { .PA = 1, .OBE = 1, .IBE = 1, .WPE = 1, .WPS = 1 } } }, /* TXD_A (ESCI_A)*/ + { 90, 1, 0, { .B = { .PA = 1, .OBE = 0, .IBE = 1, .WPE = 1, .WPS = 1 } } }, /* RXD_A (ESCI_A)*/ + { 256, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS0 */ + { 257, 1, 0, { .B = { .PA = 2, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT31 */ + { 258, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS3 */ + { 259, 4, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD12 .. D_ADD15 */ + { 263, 15, 0, { .B = { .PA = 2, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT16 .. D_ADD_DAT30 */ + { 278, 16, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_ADD_DAT0 .. D_ADD_DAT15 */ + { 294, 6, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_RD_WR, D_WE0, D_WE1, D_OE, D_TS, D_ALE */ + { 301, 1, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_CS1 */ + { 302, 3, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } }, /* D_BDIP, D_WE2, D_WE3 */ + { 305, 3, 0, { .B = { .PA = 1, .DSC = 3, .WPE = 1, .WPS = 1 } } } /* D_ADD9 .. D_ADD11 */ +#endif +}; + +const size_t mpc55xx_start_config_siu_pcr_count [] = { + RTEMS_ARRAY_SIZE(mpc55xx_start_config_siu_pcr) +}; diff --git a/bsps/powerpc/mpc55xxevb/start/start-early.c b/bsps/powerpc/mpc55xxevb/start/start-early.c new file mode 100644 index 0000000000..e1a0b3da09 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-early.c @@ -0,0 +1,216 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Early initialization code. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> +#include <bsp/linker-symbols.h> + +/* This function is defined in start.S */ +BSP_START_TEXT_SECTION void mpc55xx_start_load_section( + void *dst, + const void *src, + size_t n +); + +static BSP_START_TEXT_SECTION void mpc55xx_start_mmu(void) +{ + #ifdef MPC55XX_BOOTFLAGS + /* If the low bit of bootflag 0 is clear don't change the MMU. */ + bool do_mmu_config = (mpc55xx_bootflag_0 [0] & 1) != 0; + #else + bool do_mmu_config = true; + #endif + + if (do_mmu_config) { + mpc55xx_start_mmu_apply_config( + &mpc55xx_start_config_mmu [0], + mpc55xx_start_config_mmu_count [0] + ); + } +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_internal_ram(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + /* Initialize internal SRAM to zero (ECC) */ + bsp_start_zero( + (char *) bsp_ram_start + MPC55XX_EARLY_STACK_SIZE, + (size_t) bsp_ram_size - MPC55XX_EARLY_STACK_SIZE + ); + #ifdef MPC55XX_HAS_SECOND_INTERNAL_RAM_AREA + bsp_start_zero(&bsp_ram_1_start [0], (size_t) bsp_ram_1_size); + #endif + #else + bsp_start_zero( + bsp_section_sbss_begin, + (size_t) bsp_section_sbss_size + ); + bsp_start_zero( + bsp_section_bss_begin, + (size_t) bsp_section_bss_size + ); + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_load_nocache_section(void) +{ + mpc55xx_start_load_section( + bsp_section_nocache_begin, + bsp_section_nocache_load_begin, + (size_t) bsp_section_nocache_size + ); + rtems_cache_flush_multiple_data_lines( + bsp_section_nocache_begin, + (size_t) bsp_section_nocache_size + ); +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_mode_change(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #ifdef MPC55XX_HAS_MODE_CONTROL + uint32_t mctl_key1 = 0x5af0; + uint32_t mctl_key2 = 0xa50f; + int i = 0; + + /* Clear any pending RGM status */ + RGM.FES.R = 0xffff; + RGM.DES.R = 0xffff; + + /* Make sure XOSC and PLLs are on in RUN0 state */ + ME.DRUN_MC.R = 0x001f0074; + ME.RUN_MC [0].R = 0x001f0074; + + /* + * Make sure all peripherals are active in DRUN and RUN0 state. + * + * FIXME: This might be optimized to reduce power consumtion. + */ + for (i = 0; i < 8; ++i) { + ME_RUN_PC_32B_tag run_pc = { .R = ME.RUN_PC [i].R }; + + run_pc.B.DRUN = 1; + run_pc.B.RUN0 = 1; + + ME.RUN_PC [i].R = run_pc.R; + } + + /* Switch to RUN0 state */ + ME.MCTL.R = 0x40000000 | mctl_key1; + ME.MCTL.R = 0x40000000 | mctl_key2; + + while (ME.GS.B.S_MTRANS) { + /* Wait for mode switch to be completed */ + } + #endif + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_siu(void) +{ + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_siu_pcr_count [0]; ++i) { + const mpc55xx_siu_pcr_config *e = &mpc55xx_start_config_siu_pcr [i]; + int j = e->index; + int n = j + e->count; + uint8_t gpdo = e->output; + uint16_t pcr = e->pcr.R; + + while (j < n) { + SIU.GPDO [j].R = gpdo; + SIU.PCR [j].R = pcr; + ++j; + } + } +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_ebi_chip_select(void) +{ + #ifdef MPC55XX_HAS_EBI + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_ebi_cs_count [0]; ++i) { + EBI.CS [i] = mpc55xx_start_config_ebi_cs [i]; + } + + for (i = 0; i < mpc55xx_start_config_ebi_cal_cs_count [0]; ++i) { + EBI.CAL_CS [i] = mpc55xx_start_config_ebi_cal_cs [i]; + } + #endif +} + +static BSP_START_TEXT_SECTION void mpc55xx_start_ebi(void) +{ + #ifdef MPC55XX_HAS_EBI + size_t i = 0; + + for (i = 0; i < mpc55xx_start_config_ebi_count [0]; ++i) { + SIU.ECCR.B.EBDF = mpc55xx_start_config_ebi [i].siu_eccr_ebdf; + EBI.MCR.R = mpc55xx_start_config_ebi [i].ebi_mcr.R; + } + #endif +} + +#ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT +static BSP_START_TEXT_SECTION bool +mpc55xx_start_is_in_internal_ram(const void *addr) +{ + return (size_t) addr - (size_t) bsp_ram_start < (size_t) bsp_ram_size; +} +#endif + +static BSP_START_TEXT_SECTION void mpc55xx_start_clear_bss(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + if (!mpc55xx_start_is_in_internal_ram(bsp_section_sbss_begin)) { + bsp_start_zero( + bsp_section_sbss_begin, + (size_t) bsp_section_sbss_size + ); + } + + if (!mpc55xx_start_is_in_internal_ram(bsp_section_bss_begin)) { + bsp_start_zero( + bsp_section_bss_begin, + (size_t) bsp_section_bss_size + ); + } + #endif +} + +BSP_START_TEXT_SECTION void mpc55xx_start_early(void) +{ + mpc55xx_start_watchdog(); + mpc55xx_start_clock(); + mpc55xx_start_flash(); + #if defined(BSP_DATA_CACHE_ENABLED) || defined(BSP_INSTRUCTION_CACHE_ENABLED) + mpc55xx_start_cache(); + #endif + mpc55xx_start_internal_ram(); + mpc55xx_start_load_nocache_section(); + mpc55xx_start_mmu(); + mpc55xx_start_mode_change(); + mpc55xx_start_siu(); + mpc55xx_start_ebi_chip_select(); + mpc55xx_start_ebi(); + mpc55xx_start_clear_bss(); +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-flash.S b/bsps/powerpc/mpc55xxevb/start/start-flash.S new file mode 100644 index 0000000000..9c87d38a83 --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-flash.S @@ -0,0 +1,139 @@ +/** + * @file + * + * @ingroup mpc55xx_asm + * + * @brief Flash configuration. + */ + +/* + * Copyright (c) 2008-2015 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> +#include <mpc55xx/reg-defs.h> + + .section ".bsp_start_text", "ax" + +#if MPC55XX_CHIP_FAMILY == 551 + +/* MPC5510 Microcontroller Family Data Sheet, Rev. 3, Table 16, Num 7 */ +.equ FLASH_CLOCK_0, 25000000 +.equ FLASH_CLOCK_1, 50000000 +.equ FLASH_CLOCK_2, 80000000 +.equ FLASH_CLOCK_3, FLASH_CLOCK_2 +.equ FLASH_SETTINGS_0, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_0 | FLASH_BUICR_RWSC_0 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_1, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_1 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_2, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_2 | FLASH_BUICR_RWSC_2 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_1 | FLASH_BUICR_IPFEN_1 | FLASH_BUICR_PFLIM_2 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_3, FLASH_SETTINGS_2 + +#else + +/* Optimized flash configurations (Table 13-15 [MPC5567 Microcontroller Reference Manual]) */ +.equ FLASH_CLOCK_0, 82000000 +.equ FLASH_CLOCK_1, 102000000 +.equ FLASH_CLOCK_2, 132000000 +.equ FLASH_CLOCK_3, 264000000 +.equ FLASH_SETTINGS_0, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_1 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_1, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_2 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_2, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_2 | FLASH_BUICR_RWSC_3 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN +.equ FLASH_SETTINGS_3, 0x01716B15 + +#endif + +/** + * @fn void mpc55xx_start_flash() + * @brief Optimized flash configuration. + * @warning Code will be copied and executed on the stack. + */ +GLOBAL_FUNCTION mpc55xx_start_flash +#if !defined(MPC55XX_NEEDS_LOW_LEVEL_INIT) \ + || MPC55XX_CHIP_FAMILY == 564 \ + || MPC55XX_CHIP_FAMILY == 566 + blr +#else + .equ stack_size, 20 + .equ lr_offset, 28 + + /* Reserve stack frame */ + stwu r1, -stack_size(r1) + mflr r0 + stw r0, lr_offset(r1) + + /* Flash settings dependent on system clock */ + bl mpc55xx_get_system_clock + LWI r4, FLASH_CLOCK_0 + cmpw r3, r4 + ble clock_0 + LWI r4, FLASH_CLOCK_1 + cmpw r3, r4 + ble clock_1 + LWI r4, FLASH_CLOCK_2 + cmpw r3, r4 + ble clock_2 + LWI r4, FLASH_CLOCK_3 + cmpw r3, r4 + ble clock_3 + + /* + * In case we don't have the right flash settings for the system clock + * value, then rely on the BAM settings. + */ + blr + +clock_0: + LWI r3, FLASH_SETTINGS_0 + b settings_done +clock_1: + LWI r3, FLASH_SETTINGS_1 + b settings_done +clock_2: + LWI r3, FLASH_SETTINGS_2 + b settings_done +clock_3: + LWI r3, FLASH_SETTINGS_3 + b settings_done +settings_done: + + /* Copy store code on the stack */ + LA r4, store_start + lwz r6, 0(r4) + lwz r7, 4(r4) + lwz r8, 8(r4) + stw r6, 8(r1) + stw r7, 12(r1) + stw r8, 16(r1) + + /* Execute store code */ + LA r4, FLASH_BIUCR + addi r5, r1, 8 + mtctr r5 + bctrl + + /* Return */ + lwz r0, lr_offset(r1) + addi r1, r1, stack_size + mtlr r0 + blr + +/* + * Store flash settings + */ + +store_start: + + stw r3, 0(r4) + isync + blr + +#endif diff --git a/bsps/powerpc/mpc55xxevb/start/start-prologue.c b/bsps/powerpc/mpc55xxevb/start/start-prologue.c new file mode 100644 index 0000000000..872a96edfd --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-prologue.c @@ -0,0 +1,28 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Start prologue. + */ + +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mpc55xx-config.h> + +BSP_START_TEXT_SECTION void mpc55xx_start_prologue(void) +{ + /* Do nothing */ +} diff --git a/bsps/powerpc/mpc55xxevb/start/start-watchdog.c b/bsps/powerpc/mpc55xxevb/start/start-watchdog.c new file mode 100644 index 0000000000..7cf36ef02f --- /dev/null +++ b/bsps/powerpc/mpc55xxevb/start/start-watchdog.c @@ -0,0 +1,39 @@ +/** + * @file + * + * @ingroup mpc55xx + * + * @brief Watchdog initialization code. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/start.h> +#include <bsp/mpc55xx-config.h> + +BSP_START_TEXT_SECTION void mpc55xx_start_watchdog(void) +{ + #ifdef MPC55XX_NEEDS_LOW_LEVEL_INIT + #ifdef MPC55XX_HAS_SWT + /* Write keys to clear soft lock bit */ + SWT.SR.R = 0x0000c520; + SWT.SR.R = 0x0000d928; + + /* Clear watchdog enable (WEN) */ + SWT.CR.R = 0x8000010A; + #endif + #endif +} diff --git a/bsps/powerpc/mpc8260ads/start/bsp_specs b/bsps/powerpc/mpc8260ads/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mpc8260ads/start/bspstart.c b/bsps/powerpc/mpc8260ads/start/bspstart.c new file mode 100644 index 0000000000..44ec072775 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/bspstart.c @@ -0,0 +1,191 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * The MPC860 specific stuff was written by Jay Monkman (jmonkman@frasca.com) + * + * Modified for the MPC8260ADS board by Andy Dachs <a.dachs@sstl.co.uk> + * Surrey Satellite Technology Limited, 2001 + * A 40MHz system clock is assumed. + * The PON. RST.CONF. Dip switches (DS1) are + * 1 - Off + * 2 - On + * 3 - Off + * 4 - On + * 5 - Off + * 6 - Off + * 7 - Off + * 8 - Off + * Dip switches on DS2 and DS3 are all set to ON + * The LEDs on the board are used to signal panic and fatal_error + * conditions. + * The mmu is unused at this time. + * + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +/* +#include <mmu.h> +*/ + +#include <mpc8260.h> +#include <rtems/score/thread.h> +#include <rtems/powerpc/powerpc.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <bsp/irq.h> +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <string.h> + +#define UART1_E 0x02000002 /* bit 6 of BCSR1 */ +#define UART2_E 0x01000001 /* bit 7 of BCSR1 */ + +#define GP0_LED 0x02000002 /* bit 6 of BCSR0 */ +#define GP1_LED 0x01000001 /* bit 7 of BCSR0 */ + +SPR_RW(SPRG1) + +/* + * Driver configuration parameters + */ +uint32_t bsp_clock_speed; +uint32_t bsp_time_base_frequency; +uint32_t bsp_clicks_per_usec; +uint32_t bsp_serial_per_sec; /* Serial clocks per second */ +bool bsp_serial_external_clock; +bool bsp_serial_xon_xoff; +bool bsp_serial_cts_rts; +uint32_t bsp_serial_rate; + +extern char IntrStack_start []; +extern char intrStack []; + +static void _BSP_GPLED0_on(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP0_LED; /* Turn on GP0 LED */ +} + +static void _BSP_GPLED0_off(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP0_LED; /* Turn off GP0 LED */ +} + +static void _BSP_GPLED1_on(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 &= ~GP1_LED; /* Turn on GP1 LED */ +} + +static void _BSP_GPLED1_off(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr0 |= GP1_LED; /* Turn off GP1 LED */ +} + +static void _BSP_Uart1_enable(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART1_E; /* Enable Uart1 */ +} + +static void _BSP_Uart2_enable(void) +{ + BCSR *csr; + csr = (BCSR *)(m8260.memc[1].br & 0xFFFF8000); + csr->bcsr1 &= ~UART2_E; /* Enable Uart2 */ +} + +void bsp_start(void) +{ + /* Set MPC8260ADS board LEDS and Uart enable lines */ + _BSP_GPLED0_off(); + _BSP_GPLED1_off(); + _BSP_Uart1_enable(); + _BSP_Uart2_enable(); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + cpu_init(); + +/* + mmu_init(); +*/ + + /* Initialize exception handler */ + /* FIXME: Interrupt stack begin and size */ + ppc_exc_initialize( + (uintptr_t) IntrStack_start, + (uintptr_t) intrStack - (uintptr_t) IntrStack_start + ); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +/* + mmu_init(); +*/ + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ +#if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif +#if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * initialize the device driver parameters + */ + bsp_time_base_frequency = 10000000; + bsp_clicks_per_usec = 10; /* for 40MHz extclk */ + bsp_serial_per_sec = 40000000; + bsp_serial_external_clock = 0; + bsp_serial_xon_xoff = 0; + bsp_serial_cts_rts = 0; + bsp_serial_rate = 9600; + bsp_clock_speed = 40000000; + rtems_counter_initialize_converter(bsp_clock_speed); + +#ifdef REV_0_2 + /* set up some board specific registers */ + m8260.siumcr &= 0xF3FFFFFF; /* set TBEN ** BUG FIX ** */ + m8260.siumcr |= 0x08000000; +#endif + + /* use BRG1 to generate 32kHz timebase */ +/* + m8260.brgc1 = M8260_BRG_EN + (uint32_t)(((uint16_t)((40016384)/(32768)) - 1) << 1) + 0; +*/ + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif + +} diff --git a/bsps/powerpc/mpc8260ads/start/cpuinit.c b/bsps/powerpc/mpc8260ads/start/cpuinit.c new file mode 100644 index 0000000000..c56ec69362 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/cpuinit.c @@ -0,0 +1,49 @@ +/* + * cpuinit.c - this file contains functions for initializing the CPU + * + * Written by Jay Monkman (jmonkman@frasca.com) + */ + +#include <bsp.h> + +/* Macros for handling all the MMU SPRs */ +#define PUT_IC_CST(r) __asm__ volatile ("mtspr 0x230,%0\n" ::"r"(r)) +#define GET_IC_CST(r) __asm__ volatile ("mfspr %0,0x230\n" :"=r"(r)) +#define PUT_DC_CST(r) __asm__ volatile ("mtspr 0x238,%0\n" ::"r"(r)) +#define GET_DC_CST(r) __asm__ volatile ("mfspr %0,0x238\n" :"=r"(r)) + +void cpu_init(void) +{ + /* BRGCLK is VCO_OUT/4 */ +/* + m8260.sccr = 0; +*/ + +#if 0 + register unsigned long t1, t2; + + /* Let's clear MSR[IR] and MSR[DR] */ + t2 = PPC_MSR_IR | PPC_MSR_DR; + __asm__ volatile ( + "mfmsr %0\n" + "andc %0, %0, %1\n" + "mtmsr %0\n" :"=r"(t1), "=r"(t2): + "1"(t2)); + + t1 = M8xx_CACHE_CMD_UNLOCK; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_INVALIDATE; + /* PUT_DC_CST(t1); */ + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_ENABLE; + PUT_IC_CST(t1); + + t1 = M8xx_CACHE_CMD_SFWT; + /* PUT_DC_CST(t1); */ + t1 = M8xx_CACHE_CMD_ENABLE; + /* PUT_DC_CST(t1);*/ +#endif +} diff --git a/bsps/powerpc/mpc8260ads/start/linkcmds b/bsps/powerpc/mpc8260ads/start/linkcmds new file mode 100644 index 0000000000..f3092b862d --- /dev/null +++ b/bsps/powerpc/mpc8260ads/start/linkcmds @@ -0,0 +1,352 @@ +/* + * This file contains directives for the GNU linker which are specific + * to the MPC8260ADS Board + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(start) +STARTUP(start.o) +EXTERN(__vectors) + +/* + * Declare some sizes. + * XXX: The assignment of ". += XyzSize;" fails in older gld's if the + * number used there is not constant. If this happens to you, edit + * the lines marked XXX below to use a constant value. + */ +StackSize = DEFINED(StackSize) ? StackSize : 0x8000; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamDiskSize : 0x0800000; /* 8M program ram */ +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +RamDiskBase = DEFINED(RamDiskBase) ? RamDiskBase : 0x0800000; +RamDiskSize = DEFINED(RamDiskSize) ? RamDiskSize : 0x0800000; /* 8M ram disk */ + +MEMORY +{ + ram : org = 0x0, l = 8M + ramdisk : org = 0x0800000, l = 8M + dpram : org = 0x04700000, l = 128K + flash : org = 0xff800000, l = 8M +} + + +SECTIONS +{ + /* + * The stack will live in this area - between the vectors and + * the text section. + */ + + .text 0x10000: + { + _textbase = .; + + + text.start = .; + + /* Entry point is the .entry section */ + *(.entry) + *(.entry2) + + /* Actual Code */ + *(.text*) + + + *(.rodata*) + *(.rodata1) + + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + + PROVIDE (__CTOR_LIST__ = .); + /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* Exception frame info */ + *(.eh_frame) + + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + *(.descriptors) + *(rom_ver) + _erodata = .; + + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + _endtext = .; + text.end = .; + PROVIDE (etext = .); + PROVIDE (__etext = .); + + } > ram + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >ram + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >ram + + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + + .rel.dyn : + { + *(.rel.init) + *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) + *(.rel.fini) + *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) + *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) + *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) + *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) + *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) + *(.rel.ctors) + *(.rel.dtors) + *(.rel.got) + *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) + *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) + *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) + *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) + *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) + } >ram + .rela.dyn : + { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + } >ram + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table*) } >ram + PROVIDE (__EXCEPT_END__ = .); + __GOT_START__ = .; + .got : + { + s.got = .; + *(.got.plt) *(.got) + } > ram + __GOT_END__ = .; + + .got1 : { *(.got1) } >ram + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } >ram + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } >ram + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + .sdata : { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + } > ram + + .sbss : { + __bss_start = .; + + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.scommon) + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } > ram + + .sdata2 : { + PROVIDE (_SDA2_BASE_ = 32768); + + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > ram =0 + + .sbss2 : { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > ram =0 + + .bss : + { + bss.start = .; + *(.bss .bss* .gnu.linkonce.b*) + . = ALIGN(4); + bss.end = .; + } > ram + + /* R/W Data */ + .data ( . ) : + { + . = ALIGN (4); + + data.start = .; + + *(.data) + *(.data1) + *(.data.* .gnu.linkonce.d.*) + KEEP (*(SORT(.rtemsrwset.*))) + PROVIDE (__SDATA_START__ = .); + *(.sdata .sdata.* .gnu.linkonce.s.*) + data.end = .; + } > ram + + data.size = data.end - data.start; + bss.size = bss.end - bss.start; + text.size = text.end - text.start; + + PROVIDE(_end = data.end); + + .gzipmalloc : { + . = ALIGN (16); + _startmalloc = .; + } >ram + + + /* + * Interrupt stack setup + */ + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + + + clear_end = .; + + WorkAreaBase = .; + + /* Sections for compressed .text and .data */ + /* after the .datarom section is an int specifying */ + /* the length of the following compressed image */ + /* Executes once then could get overwritten */ + .textrom 0x100000 : + { + *(.textrom) + _endloader = .; + } > ram + + .datarom : + { + _dr_start = .; + *(.datarom) + _dr_end = .; + } > ram + dr_len = _dr_end - _dr_start; + + .dpram : + { + m8260 = .; + _m8260 = .; + . += (128 * 1024); + } > dpram + + + /* the reset vector is at 0xfff00000 which is */ + /* located at offset 0x400000 from the base */ + /* of flash */ + .bootrom 0xFFF00000 : + { + *(.bootrom) + _endboot = .; + } > flash + + + .line 0 : { *(.line) } + .debug 0 : { *(.debug) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_aregion 0 : { *(.debug_aregion) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } +} diff --git a/bsps/powerpc/mvme3100/start/bsp_specs b/bsps/powerpc/mvme3100/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mvme3100/start/bspstart.c b/bsps/powerpc/mvme3100/start/bspstart.c new file mode 100644 index 0000000000..27b483332c --- /dev/null +++ b/bsps/powerpc/mvme3100/start/bspstart.c @@ -0,0 +1,440 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified for mvme3100 by T. Straumann + */ + +#include <string.h> +#include <stdlib.h> +#include <inttypes.h> + +#include <rtems.h> +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/sysinit.h> +#include <libcpu/spr.h> +#include <libcpu/io.h> +#include <libcpu/e500_mmu.h> +#include <bsp/uart.h> +#include <bsp/irq.h> +#include <bsp/pci.h> +#include <bsp/vpd.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <rtems/powerpc/powerpc.h> + +#define SHOW_MORE_INIT_SETTINGS +#undef DEBUG + +#define NumberOf(arr) (sizeof(arr)/sizeof(arr[0])) + +#ifdef DEBUG +#define STATIC +#else +#define STATIC static +#endif + +extern unsigned long __rtems_end[]; +extern unsigned ppc_exc_lock_std, ppc_exc_gpr3_std; + +/* + * Copy Additional boot param passed by boot loader + */ +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE] = {0}; +char *BSP_commandline_string = cmdline_buf; + +/* + * Vital Board data Start using DATA RESIDUAL + */ +uint32_t bsp_clicks_per_usec = 0; +/* + * Total memory using RESIDUAL DATA + */ +unsigned int BSP_mem_size = 0; +/* + * PCI Bus Frequency + */ +unsigned int BSP_pci_bus_frequency = 0xdeadbeef; +/* + * PPC Bus Frequency + */ +unsigned int BSP_bus_frequency = 0; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency = 0; +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor = 8000; /* if external RTC clock unused (HID0) */ + +/* Board identification string */ +char BSP_productIdent[20] = {0}; +char BSP_serialNumber[20] = {0}; + +/* VPD appends an extra char -- what for ? */ +char BSP_enetAddr0[7] = {0}; +char BSP_enetAddr1[7] = {0}; +char BSP_enetAddr2[7] = {0}; + +static void +prether(char *b, int idx) +{ +int i; + printk("Ethernet %i %02X", idx, *b++); + for ( i=0; i<5; i++ ) + printk(":%02X",*b++); + printk("\n"); +} + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +char *rtems_progname; + +/* + * Use the shared implementations of the following routines + */ +char *save_boot_params( + void *r3, + void *r4, + void *r5, + char *cmdline_start, + char *cmdline_end +) +{ + + strncpy(cmdline_buf, cmdline_start, CMDLINE_BUF_SIZE); + cmdline_buf[CMDLINE_BUF_SIZE - 1] ='\0'; + return cmdline_buf; +} + +#define CS_CONFIG_CS_EN (1<<31) +#define CS_BNDS_SA(x) ((((uint32_t)(x))>>(31-15)) & 0xff) +#define CS_BNDS_EA(x) ((((uint32_t)(x))>>(31-31)) & 0xff) + +static inline uint32_t +_ccsr_rd32(uint32_t off) +{ + return in_be32( (volatile uint32_t *)(BSP_8540_CCSR_BASE + off) ); +} + +static inline void +_ccsr_wr32(uint32_t off, uint32_t val) +{ + out_be32( (volatile uint32_t *)(BSP_8540_CCSR_BASE + off), val ); +} + + +STATIC uint32_t +BSP_get_mem_size( void ) +{ + int i; + uint32_t cs_bnds, cs_config; + uint32_t memsz=0; + uint32_t v; + + for ( cs_bnds = 0x2000, cs_config=0x2080, i=0; i<4; i++, cs_bnds+=8, cs_config+=4 ) { + if ( CS_CONFIG_CS_EN & _ccsr_rd32( cs_config ) ) { + v = _ccsr_rd32( cs_bnds ); + + memsz += CS_BNDS_EA(v) - CS_BNDS_SA(v) + 1; + } + } + return memsz << 24; +} + +STATIC void +BSP_calc_freqs( void ) +{ + uint32_t porpllsr = _ccsr_rd32( 0xe0000 ); + unsigned plat_ratio = (porpllsr >> (31-30)) & 0x1f; + unsigned e500_ratio = (porpllsr >> (31-15)) & 0x3f; + + switch ( plat_ratio ) { + case 2: case 3: case 4: case 5: case 6: + case 8: case 9: case 10: case 12: case 16: + /* supported ratios */ + BSP_bus_frequency = BSP_pci_bus_frequency * plat_ratio; + break; + + default: + rtems_panic("Unknown PLL sys-clock ratio; something's wrong here"); + } + + switch ( e500_ratio ) { + case 4: case 5: case 6: case 7: + BSP_processor_frequency = (BSP_pci_bus_frequency * e500_ratio) >> 1; + break; + + default: + rtems_panic("Unknown PLL e500-clock ratio; something's wrong here"); + } + + printk("Core Complex Bus (CCB) Clock Freq: %10u Hz\n", BSP_bus_frequency); + printk("CPU Clock Freq: %10u Hz\n", BSP_processor_frequency); +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +#include <libcpu/spr.h> + +SPR_RW(HID1) + +void bsp_start( void ) +{ + unsigned char *stack; + uintptr_t intrStackStart; + uintptr_t intrStackSize; + char *chpt; + int i; + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + E500_tlb_va_cache_t *tlb; + +VpdBufRec vpdData [] = { + { key: ProductIdent, instance: 0, buf: BSP_productIdent, buflen: sizeof(BSP_productIdent) - 1 }, + { key: SerialNumber, instance: 0, buf: BSP_serialNumber, buflen: sizeof(BSP_serialNumber) - 1 }, + { key: BusClockHz, instance: 0, buf: &BSP_pci_bus_frequency, buflen: sizeof(BSP_pci_bus_frequency) }, + { key: EthernetAddr, instance: 0, buf: BSP_enetAddr0, buflen: sizeof(BSP_enetAddr0) }, + { key: EthernetAddr, instance: 1, buf: BSP_enetAddr1, buflen: sizeof(BSP_enetAddr1) }, + { key: EthernetAddr, instance: 2, buf: BSP_enetAddr2, buflen: sizeof(BSP_enetAddr2) }, + VPD_END +}; + + /* Intersperse messages with actions to help locate problems */ + printk("-----------------------------------------\n"); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used + * later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + + printk("Welcome to %s\n", _RTEMS_version); + printk("BSP: %s, CVS Release ($Name$)\n", "mvme3100"); + + /* + * the initial stack has aready been set to this value in start.S + * so there is no need to set it in r1 again... It is just for info + * so that It can be printed without accessing R1. + */ + asm volatile("mr %0, 1":"=r"(stack)); + + /* tag the bottom */ + *((uint32_t*)stack) = 0; + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) __rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + printk("CPU 0x%x - rev 0x%x\n", myCpu, myCpuRevision); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Additionnal boot options are %s\n", BSP_commandline_string); + printk("Initial system stack at %" PRIxPTR "\n", (uintptr_t) stack); + printk("Software IRQ stack starts at %x with size %u\n", intrStackStart, intrStackSize); +#endif + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + + BSP_mem_size = BSP_get_mem_size(); + + { + /* memory-select errors were disabled in 'start.S'; + * motload has all TLBs mapping a possible larger area as + * memory (not-guarded, caching-enabled) than actual physical + * memory is available. + * In case of speculative loads this may cause 'memory-select' errors + * which seem to raise 'core_fault_in' (found no description in + * the manual but I experienced this problem). + * Such errors (if HID1[RFXE] is clear) may *stall* execution + * leading to mysterious 'hangs'. + * + * Here we remove all mappings, re-enable memory-select + * errors and make sure we enable HID1[RFXE] to avoid + * stalls (since we don't implement handling individual + * error-handling interrupts). + */ + + /* enable machine check for bad bus errors */ + _write_HID1( _read_HID1() | 0x20000 ); + + rtems_e500_initlb(); + + for ( i=0, tlb=rtems_e500_tlb_va_cache; i<NumberOf(rtems_e500_tlb_va_cache); i++, tlb++ ) { + /* disable TLBs for caching-enabled, non-guarded areas + * beyond physical memory + */ + if ( tlb->att.v + && 0xa != (tlb->att.wimge & 0xa) + && (tlb->va.va_epn<<12) >= BSP_mem_size ) { + rtems_e500_clrtlb( E500_SELTLB_1 | i ); + } + } + + /* clear all pending memory errors */ + _ccsr_wr32(0x2e40, 0xffffffff); + /* enable checking for memory-select errors */ + _ccsr_wr32(0x2e44, _ccsr_rd32(0x2e44) & ~1 ); + } + + BSP_vpdRetrieveFields( vpdData ); + + printk("Board Type: %s (S/N %s)\n", + BSP_productIdent[0] ? BSP_productIdent : "n/a", + BSP_serialNumber[0] ? BSP_serialNumber : "n/a"); + + printk("External (=PCI Bus) Clock Freq "); + if ( 0xdeadbeef == BSP_pci_bus_frequency ) { + BSP_pci_bus_frequency = 66666666; + printk(" NOT FOUND in VPD; using %10u Hz\n", + BSP_pci_bus_frequency); + } else { + printk(": %10u Hz\n", + BSP_pci_bus_frequency); + } + + /* Calculate CPU and CCB bus freqs */ + BSP_calc_freqs(); + + pci_initialize(); + + prether(BSP_enetAddr0, 0); + prether(BSP_enetAddr1, 1); + prether(BSP_enetAddr2, 2); + + /* need to tweak the motload setup */ + BSP_motload_pci_fixup(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); + { + BSP_pciConfigDump_early(); + } +#endif + + if ( (chpt = strstr(BSP_commandline_string,"MEMSZ=")) ) { + char *endp; + uint32_t sz; + chpt+=6 /* strlen("MEMSZ=") */; + sz = strtoul(chpt, &endp, 0); + if ( endp != chpt ) + BSP_mem_size = sz; + } + + printk("Memory: %10u bytes\n", BSP_mem_size); + + BSP_bus_frequency = 333333333; + BSP_processor_frequency = 833333333; + BSP_time_base_divisor = 8000; /* if external RTC clock unused (HID0) */ + + /* clear hostbridge errors but leave MCP disabled - + * PCI config space scanning code will trip otherwise :-( + */ + _BSP_clear_hostbridge_errors(0 /* enableMCP */, 0/*quiet*/); + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + if (1) { + int i; + unsigned msr,tcr; + asm volatile("mfmsr %0":"=r"(msr)); + asm volatile("mftcr %0":"=r"(tcr)); + printk("MSR is 0x%08x, TCR 0x%08x\n",msr,tcr); + asm volatile("mttcr %0"::"r"(0)); + if (0) { + asm volatile("mtmsr %0"::"r"(msr|0x8000)); + for (i=0; i<12; i++) + BSP_enable_irq_at_pic(i); + printk("IRQS enabled\n"); + } + } + + if (0) { + unsigned x; + asm volatile("mfivpr %0":"=r"(x)); + printk("IVPR: 0x%08x\n",x); + asm volatile("mfivor8 %0":"=r"(x)); + printk("IVOR8: 0x%08x\n",x); + printk("0x%08x\n",*(unsigned *)0xc00); + printk("0x%08x\n",*(unsigned *)0xc04); + printk("0x%08x\n",*(unsigned *)0xc08); + printk("0x%08x\n\n\n",*(unsigned *)0xc0c); + if (0) { + *(unsigned *)0xc08 = 0x4c000064; + asm volatile("dcbf 0, %0; icbi 0, %0; sync; isync"::"r"(0xc00)); + } + + printk("0x%08x\n", ppc_exc_lock_std); + printk("0x%08x\n", ppc_exc_gpr3_std); + + asm volatile("sc"); + + printk("0x%08x\n", ppc_exc_lock_std); + printk("0x%08x\n", ppc_exc_gpr3_std); + } + + printk("-----------------------------------------\n"); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} + +static void mvme3100_i2c_initialize(void) +{ + BSP_i2c_initialize(); +} + +RTEMS_SYSINIT_ITEM( + mvme3100_i2c_initialize, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/mvme3100/start/linkcmds b/bsps/powerpc/mvme3100/start/linkcmds new file mode 100644 index 0000000000..b30fb91277 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(motld_start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mvme3100/start/misc.c b/bsps/powerpc/mvme3100/start/misc.c new file mode 100644 index 0000000000..3a15397480 --- /dev/null +++ b/bsps/powerpc/mvme3100/start/misc.c @@ -0,0 +1,131 @@ +/* Miscellaneous small BSP routines; reboot, board CSR, ... */ + +/* + * Authorship + * ---------- + * This software ('mvme3100' RTEMS BSP) was created by + * + * Till Straumann <strauman@slac.stanford.edu>, 2005-2007, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * The 'mvme3100' BSP was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +void +bsp_reset(void) +{ +uint8_t v; + /* + * AFAIK, the hardest reset available; cleared + * some errors a VME-bus reset wouldn't (hung + * i2c bus)... + */ + v = in_8( BSP_MVME3100_SYS_CR ); + v &= ~BSP_MVME3100_SYS_CR_RESET_MSK; + v |= BSP_MVME3100_SYS_CR_RESET; + out_8( BSP_MVME3100_SYS_CR, v ); +} + +uint8_t +BSP_setSysReg(volatile uint8_t *r, uint8_t mask) +{ +uint8_t v; +rtems_interrupt_level l; + + if ( !mask ) + return in_8( r ); + + rtems_interrupt_disable(l); + v = in_8( r ); + if ( mask ) { + out_8( r, v | mask ); + } + rtems_interrupt_enable(l); + return v; +} + +uint8_t +BSP_clrSysReg(volatile uint8_t *r, uint8_t mask) +{ +uint8_t v; +rtems_interrupt_level l; + + if ( !mask ) + return in_8( r ); + + rtems_interrupt_disable(l); + v = in_8( r ); + if ( mask ) { + out_8( r, v & ~mask ); + } + rtems_interrupt_enable(l); + return v; +} + +uint8_t +BSP_setLEDs(uint8_t mask) +{ + return BSP_setSysReg( BSP_MVME3100_SYS_IND_REG, mask ); +} + +uint8_t +BSP_clrLEDs(uint8_t mask) +{ + return BSP_clrSysReg( BSP_MVME3100_SYS_IND_REG, mask ); +} + +uint8_t +BSP_eeprom_write_protect(void) +{ +uint8_t m = BSP_MVME3100_SYS_CR_EEPROM_WP; +volatile uint8_t *r = BSP_MVME3100_SYS_CR; + + return m & BSP_setSysReg( r, m ); +} + +uint8_t +BSP_eeprom_write_enable(void) +{ +uint8_t m = BSP_MVME3100_SYS_CR_EEPROM_WP; +volatile uint8_t *r = BSP_MVME3100_SYS_CR; + + return m & BSP_clrSysReg( r, m ); +} diff --git a/bsps/powerpc/mvme5500/start/bootpstuff.c b/bsps/powerpc/mvme5500/start/bootpstuff.c new file mode 100644 index 0000000000..518a43cdc8 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bootpstuff.c @@ -0,0 +1,70 @@ +#define FLAG_MAND 1 +#define FLAG_NOUSE 2 /* dont put into the commandline at all */ +#define FLAG_CLRBP 4 /* field needs to be cleared for bootp */ + +typedef struct ParmRec_ { + char *name; + char **pval; + int flags; +} ParmRec, *Parm; + + +static char *boot_filename=0; +static char *boot_srvname=0; +static char *boot_use_bootp=0; +static char *boot_my_ip=0; +static char *boot_my_netmask=0; + +#define boot_cmdline BSP_commandline_string + +static ParmRec parmList[]={ + { "BP_FILE=", &boot_filename, + FLAG_MAND, + }, + { "BP_PARM=", &boot_cmdline, + 0, + }, + { "BP_SRVR=", &boot_srvname, + FLAG_MAND, + }, + { "BP_GTWY=", &net_config.gateway, + FLAG_CLRBP, + }, + { "BP_MYIP=", &boot_my_ip, + FLAG_MAND | FLAG_CLRBP, + }, + { "BP_MYMK=", &boot_my_netmask, + FLAG_MAND | FLAG_CLRBP, + }, + { "BP_MYNM=", &net_config.hostname, + FLAG_CLRBP, + }, + { "BP_MYDN=", &net_config.domainname, + FLAG_CLRBP, + }, + { "BP_LOGH=", &net_config.log_host, + FLAG_CLRBP, + }, + { "BP_DNS1=", &net_config.name_server[0], + FLAG_CLRBP, + }, + { "BP_DNS2=", &net_config.name_server[1], + FLAG_CLRBP, + }, + { "BP_DNS3=", &net_config.name_server[2], + FLAG_CLRBP, + }, + { "BP_NTP1=", &net_config.ntp_server[0], + FLAG_CLRBP, + }, + { "BP_NTP2=", &net_config.ntp_server[1], + FLAG_CLRBP, + }, + { "BP_NTP3=", &net_config.ntp_server[2], + FLAG_CLRBP, + }, + { "BP_ENBL=", &boot_use_bootp, + 0, + }, + { 0, } +}; diff --git a/bsps/powerpc/mvme5500/start/bsp_specs b/bsps/powerpc/mvme5500/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/mvme5500/start/bspclean.c b/bsps/powerpc/mvme5500/start/bspclean.c new file mode 100644 index 0000000000..bd332cc89c --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspclean.c @@ -0,0 +1,26 @@ +/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>, + * NSLS,Brookhaven National Laboratory + */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/stackTrace.h> + +#define AUTO_BOOT 0 + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ +#if AUTO_BOOT + /* Till Straumann <strauman@slac.stanford.edu> for SVGM */ + bsp_reset(); +#else + /* Kate Feng <feng1@bnl.gov> for the MVME5500 */ + printk("\nPrinting a stack trace for your convenience :-)\n"); + CPU_print_stack(); + printk("RTEMS terminated; Boot manually or turn on AUTO_BOOT.\n"); +#endif +} diff --git a/bsps/powerpc/mvme5500/start/bspreset.c b/bsps/powerpc/mvme5500/start/bspreset.c new file mode 100644 index 0000000000..de15bc4972 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspreset.c @@ -0,0 +1,22 @@ +/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>, + * NSLS,Brookhaven National Laboratory + * + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <rtems/bspIo.h> +#include <libcpu/io.h> +#include <libcpu/stackTrace.h> +#include <stdint.h> + +void bsp_reset() +{ + + printk("Printing a stack trace for your convenience :-)\n"); + CPU_print_stack(); + + printk("RTEMS terminated; Rebooting ...\n"); + /* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */ + out_8((volatile uint8_t*) (GT64x60_DEV1_BASE +2), 0x80); +} diff --git a/bsps/powerpc/mvme5500/start/bspstart.c b/bsps/powerpc/mvme5500/start/bspstart.c new file mode 100644 index 0000000000..279524eb8f --- /dev/null +++ b/bsps/powerpc/mvme5500/start/bspstart.c @@ -0,0 +1,351 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * Modified to support the Synergy VGM & Motorola PowerPC boards + * (C) by Till Straumann, <strauman@slac.stanford.edu>, 2002, 2004, 2005 + * + * Modified to support the MVME5500 board. + * Also, the settings of L1, L2, and L3 caches is not necessary here. + * (C) by Brookhaven National Lab., S. Kate Feng <feng1@bnl.gov>, 2003-2009 + */ + +#include <string.h> +#include <stdlib.h> +#include <ctype.h> + +#include <rtems/sysinit.h> +#include <rtems/system.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/spr.h> /* registers.h is included here */ +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/uart.h> +#include <bsp/pci.h> +#include <libcpu/bat.h> +#include <libcpu/pte121.h> +#include <libcpu/cpuIdent.h> +#include <bsp/vectors.h> +#include <bsp/VME.h> +#include <bsp/bspException.h> + +#include <rtems/bspIo.h> +#include <rtems/counter.h> + +/* +#define SHOW_MORE_INIT_SETTINGS +#define SHOW_LCR1_REGISTER +#define SHOW_LCR2_REGISTER +#define SHOW_LCR3_REGISTER +#define CONF_VPD +*/ + +extern uint32_t probeMemoryEnd(void); /* from shared/startup/probeMemoryEnd.c */ + +BSP_output_char_function_type BSP_output_char = BSP_output_char_via_serial; +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +extern void _return_to_ppcbug(void); +extern unsigned long __rtems_end[]; +extern unsigned get_L1CR(void), get_L2CR(void), get_L3CR(void); +extern Triv121PgTbl BSP_pgtbl_setup(unsigned int *); +extern void BSP_pgtbl_activate(Triv121PgTbl); +extern int I2Cread_eeprom(unsigned char I2cBusAddr, uint32_t devA2A1A0, uint32_t AddrBytes, unsigned char *pBuff, uint32_t numBytes); +extern void BSP_vme_config(void); + +extern unsigned char ReadConfVPD_buff(int offset); + +uint32_t bsp_clicks_per_usec; + +typedef struct CmdLineRec_ { + unsigned long size; + char buf[0]; +} CmdLineRec, *CmdLine; + + +#define mtspr(reg, val) \ + __asm __volatile("mtspr %0,%1" : : "K"(reg), "r"(val)) + + +#define mfspr(reg) \ + ( { unsigned val; \ + __asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \ + val; } ) + +/* + * Copy Additional boot param passed by boot loader + */ +#define MAX_LOADER_ADD_PARM 80 +char loaderParam[MAX_LOADER_ADD_PARM]; + +/* + * Total memory using RESIDUAL DATA + */ +unsigned int BSP_mem_size; +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency; +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor; +static unsigned char ConfVPD_buff[200]; + +#define CMDLINE_BUF_SIZE 2048 + +static char cmdline_buf[CMDLINE_BUF_SIZE]; +char *BSP_commandline_string = cmdline_buf; + +/* NOTE: we cannot simply malloc the commandline string; + * save_boot_params() is called during a very early stage when + * libc/malloc etc. are not yet initialized! + * + * Here's what we do: + * + * initial layout setup by the loader (preload.S): + * + * 0..RTEMS...__rtems_end | cmdline ....... TOP + * + * After the save_boot_params() routine returns, the stack area will be + * set up (start.S): + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ..... TOP + * + * initialize_executive_early() [called from boot_card()] + * will initialize the workspace: + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | ...... | workspace | TOP + * + * and later calls our bsp_predriver_hook() which ends up initializing + * libc which in turn initializes the heap + * + * 0..RTEMS..__rtems_end | INIT_STACK | IRQ_STACK | heap | workspace | TOP + * + * The idea here is to first move the commandline to the future 'heap' area + * from where it will be picked up by our bsp_predriver_hook(). + * bsp_predriver_hook() then moves it either to INIT_STACK or the workspace + * area using proper allocation, initializes libc and finally moves + * the data to the environment / malloced areas... + */ + +/* this routine is called early at shared/start/start.S + * and must be safe with a not properly aligned stack + */ +char * +save_boot_params( + void *r3, + void *r4, + void* r5, + char *cmdline_start, + char *cmdline_end +) +{ + int i=cmdline_end-cmdline_start; + + if ( i >= CMDLINE_BUF_SIZE ) + i = CMDLINE_BUF_SIZE-1; + else if ( i < 0 ) + i = 0; + + memmove(cmdline_buf, cmdline_start, i); + cmdline_buf[i]=0; + return cmdline_buf; +} + +void bsp_start( void ) +{ +#ifdef CONF_VPD + int i; +#endif +#ifdef SHOW_LCR1_REGISTER + unsigned l1cr; +#endif +#ifdef SHOW_LCR2_REGISTER + unsigned l2cr; +#endif +#ifdef SHOW_LCR3_REGISTER + unsigned l3cr; +#endif + uintptr_t intrStackStart; + uintptr_t intrStackSize; + Triv121PgTbl pt=0; + + /* Till Straumann: 4/2005 + * Need to map the system registers early, so we can printk... + * (otherwise we silently die) + */ + /* + * Kate Feng : PCI 0 domain memory space, want to leave room for the VME window + */ + setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE); + + /* Till Straumann: 2004 + * map the PCI 0, 1 Domain I/O space, GT64260B registers + * and the reserved area so that the size is the power of 2. + * 2009 : map the entire 256 M space + * + */ + setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE); + + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables so that it can be used later. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + +#ifdef SHOW_LCR1_REGISTER + l1cr = get_L1CR(); + printk("Initial L1CR value = %x\n", l1cr); +#endif + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) __rtems_end; + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* + * Init MMU block address translation to enable hardware + * access + * More PCI1 memory mapping to be done after BSP_pgtbl_activate. + */ + printk("-----------------------------------------\n"); + printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version ); + printk("-----------------------------------------\n"); + + BSP_mem_size = probeMemoryEnd(); + + /* TODO: calculate the BSP_bus_frequency using the REF_CLK bit + * of System Status register + */ + /* rtems_bsp_delay_in_bus_cycles are defined in registers.h */ + BSP_bus_frequency = 133333333; + BSP_processor_frequency = 1000000000; + /* P94 : 7455 clocks the TB/DECR at 1/4 of the system bus clock frequency */ + BSP_time_base_divisor = 4000; + + /* Maybe not setup yet becuase of the warning message */ + /* Allocate and set up the page table mappings + * This is only available on >604 CPUs. + * + * NOTE: This setup routine may modify the available memory + * size. It is essential to call it before + * calculating the workspace etc. + */ + pt = BSP_pgtbl_setup(&BSP_mem_size); + if (!pt) + printk("WARNING: unable to setup page tables.\n"); + + printk("Now BSP_mem_size = 0x%x\n",BSP_mem_size); + + /* P94 : 7455 TB/DECR is clocked by the system bus clock frequency */ + + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + +#ifdef SHOW_LCR2_REGISTER + l2cr = get_L2CR(); + printk("Initial L2CR value = %x\n", l2cr); +#endif + +#ifdef SHOW_LCR3_REGISTER + /* L3CR needs DEC int. handler installed for bsp_delay()*/ + l3cr = get_L3CR(); + printk("Initial L3CR value = %x\n", l3cr); +#endif + + + /* Activate the page table mappings only after + * initializing interrupts because the irq_mng_init() + * routine needs to modify the text + */ + if (pt) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Page table setup finished; will activate it NOW...\n"); +#endif + BSP_pgtbl_activate(pt); + } + /* Read Configuration Vital Product Data (VPD) */ + if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150)) + printk("I2Cread_eeprom() error \n"); + else { +#ifdef CONF_VPD + printk("\n"); + for (i=0; i<150; i++) { + printk("%2x ", ConfVPD_buff[i]); + if ((i % 20)==0 ) printk("\n"); + } + printk("\n"); +#endif + } + + /* + * PCI 1 domain memory space + */ + setdbat(1, PCI1_MEM_BASE, PCI1_MEM_BASE, 0x10000000, IO_PAGE); + + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Going to start PCI buses scanning and initialization\n"); +#endif + pci_initialize(); +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Number of PCI buses found is : %d\n", pci_bus_count()); +#endif + + /* Install our own exception handler (needs PCI) */ + globalExceptHdl = BSP_exceptionHandler; + + /* clear hostbridge errors. MCP signal is not used on the MVME5500 + * PCI config space scanning code will trip otherwise :-( + */ + _BSP_clear_hostbridge_errors(0, 1 /*quiet*/); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("MSR %x \n", _read_MSR()); + printk("Exit from bspstart\n"); +#endif + +} + +unsigned char ReadConfVPD_buff(int offset) +{ + return(ConfVPD_buff[offset]); +} + +RTEMS_SYSINIT_ITEM( + BSP_vme_config, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/mvme5500/start/linkcmds b/bsps/powerpc/mvme5500/start/linkcmds new file mode 100644 index 0000000000..384b623474 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/linkcmds @@ -0,0 +1,5 @@ +STARTUP(mvme5500start.o) +ENTRY(__rtems_entry_point) +EXTERN(__vectors) + +INCLUDE linkcmds.share diff --git a/bsps/powerpc/mvme5500/start/pgtbl_activate.c b/bsps/powerpc/mvme5500/start/pgtbl_activate.c new file mode 100644 index 0000000000..79725c6a06 --- /dev/null +++ b/bsps/powerpc/mvme5500/start/pgtbl_activate.c @@ -0,0 +1,37 @@ +/* + * Default activation of the page tables. This is a weak + * alias, so applications may easily override this + * default activation procedure. + */ + +/* Author: Till Straumann, <strauman@slac.stanford.edu>, 4/2002 + * Kate Feng <feng1@bnl.gov> ported it to MVME5500, 4/2004 + */ + +#include <rtems.h> +#include <libcpu/pte121.h> +#include <libcpu/bat.h> + +static void +__BSP_default_pgtbl_activate(Triv121PgTbl pt) +{ + if (!pt) + return; + + /* switch the text/ro sements to RO only after + * initializing the interrupts because the irq_mng + * installs some code... + * + * activate the page table; it is still masked by the + * DBAT0, however + */ + triv121PgTblActivate(pt); + + /* finally, switch off DBAT0 & DBAT1 */ + setdbat(0,0,0,0,0); + setdbat(1,0,0,0,0); /* <skf> */ + /* At this point, DBAT0 is available for other use... */ +} + +void BSP_pgtbl_activate(Triv121PgTbl) + __attribute__ (( weak, alias("__BSP_default_pgtbl_activate") )); diff --git a/bsps/powerpc/psim/start/bsp_specs b/bsps/powerpc/psim/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/psim/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/psim/start/bspstart.c b/bsps/powerpc/psim/start/bspstart.c new file mode 100644 index 0000000000..3a9809c022 --- /dev/null +++ b/bsps/powerpc/psim/start/bspstart.c @@ -0,0 +1,113 @@ +/* + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <string.h> +#include <fcntl.h> +#include <bsp.h> +#include <bsp/irq.h> +#include <psim.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/bat.h> +#include <libcpu/spr.h> + +SPR_RW(SPRG1) + +/* On psim, each click of the decrementer register corresponds + * to 1 instruction. By setting this to 100, we are indicating + * that we are assuming it can execute 100 instructions per + * microsecond. This corresponds to sustaining 1 instruction + * per cycle at 100 Mhz. Whether this is a good guess or not + * is anyone's guess. + */ +extern int PSIM_INSTRUCTIONS_PER_MICROSECOND[]; + +/* + * PCI Bus Frequency + */ +unsigned int BSP_bus_frequency; + +/* + * Driver configuration parameters + */ +uint32_t bsp_clicks_per_usec; + +/* + * Memory on this board. + */ +uint32_t BSP_mem_size = (uint32_t)RamSize; + +/* + * Time base divisior (how many tick for 1 second). + */ +unsigned int BSP_time_base_divisor; + +extern unsigned long __rtems_end[]; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* + * Note we can not get CPU identification dynamically. + * PVR has to be set to PPC_PSIM (0xfffe) from the device + * file. + */ + + get_ppc_cpu_type(); + + /* + * initialize the device driver parameters + */ + BSP_bus_frequency = (unsigned int)PSIM_INSTRUCTIONS_PER_MICROSECOND; + bsp_clicks_per_usec = BSP_bus_frequency; + BSP_time_base_divisor = 1; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + (void *) 0xfff00000 + ); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); + + /* + * Setup BATs and enable MMU + */ + /* Memory */ + setdbat(0, 0x0<<24, 0x0<<24, 2<<24, _PAGE_RW); + setibat(0, 0x0<<24, 0x0<<24, 2<<24, 0); + /* PCI */ + setdbat(1, 0x8<<24, 0x8<<24, 1<<24, IO_PAGE); + setdbat(2, 0xc<<24, 0xc<<24, 1<<24, IO_PAGE); + + _write_MSR(_read_MSR() | MSR_DR | MSR_IR); + __asm__ volatile("sync; isync"); + +} diff --git a/bsps/powerpc/psim/start/device-tree b/bsps/powerpc/psim/start/device-tree new file mode 100644 index 0000000000..bd2a2a56ef --- /dev/null +++ b/bsps/powerpc/psim/start/device-tree @@ -0,0 +1,4 @@ +#/openprom/init/register/pc 0 +#/openprom/options/smp 2 +#/openprom/options/oea-memory-size 4194304 +/openprom/options/oea-memory-size 8388608 diff --git a/bsps/powerpc/psim/start/linkcmds b/bsps/powerpc/psim/start/linkcmds new file mode 100644 index 0000000000..ba9319c91d --- /dev/null +++ b/bsps/powerpc/psim/start/linkcmds @@ -0,0 +1,40 @@ +/* + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0, LENGTH = 16M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +PROVIDE (PSIM_INSTRUCTIONS_PER_MICROSECOND = 10000); + +PSIM = 0x0c000000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qemuppc/start/bsp_specs b/bsps/powerpc/qemuppc/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/qemuppc/start/bspstart.c b/bsps/powerpc/qemuppc/start/bspstart.c new file mode 100644 index 0000000000..94d7f4b84d --- /dev/null +++ b/bsps/powerpc/qemuppc/start/bspstart.c @@ -0,0 +1,121 @@ +/* + * This set of routines starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before any of these are invoked. + * + * COPYRIGHT (c) 1989-2008. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <string.h> +#include <fcntl.h> + +#include <rtems/counter.h> + +#include <libcpu/bat.h> +#include <libcpu/spr.h> +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> + +/* + * CPU Bus Frequency + */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; + +/* + * Memory on this board. + */ +extern char RamSize[]; +extern char bsp_interrupt_stack_start[]; +extern char bsp_interrupt_stack_end[]; +uint32_t BSP_mem_size = (uint32_t)RamSize; + +/* Default decrementer exception handler */ +static int default_decrementer_exception_handler( BSP_Exception_frame *frame, unsigned number) +{ + ppc_set_decrementer_register(UINT32_MAX); + + return 0; +} + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ + +void bsp_start( void ) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + /* + * Note we can not get CPU identification dynamically, so + * force current_ppc_cpu. + */ + current_ppc_cpu = PPC_PSIM; + + /* + * initialize the device driver parameters + * assume we are running with 20MHz bus + * this should speed up some tests :-) + */ + BSP_bus_frequency = 20; + bsp_time_base_frequency = 20000000; + bsp_clicks_per_usec = BSP_bus_frequency; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = (uintptr_t) bsp_interrupt_stack_start; + intrStackSize = (uintptr_t) bsp_interrupt_stack_end - intrStackStart; + + BSP_mem_size = (uint32_t )RamSize; + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Install default handler for the decrementer exception */ + sc = ppc_exc_set_handler( ASM_DEC_VECTOR, default_decrementer_exception_handler); + if (sc != RTEMS_SUCCESSFUL) { + rtems_panic("cannot install decrementer exception handler"); + } + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#if 0 + /* + * Setup BATs and enable MMU + */ + /* Memory */ + setdbat(0, 0x0<<24, 0x0<<24, 2<<24, _PAGE_RW); + setibat(0, 0x0<<24, 0x0<<24, 2<<24, 0); + /* PCI */ + setdbat(1, 0x8<<24, 0x8<<24, 1<<24, IO_PAGE); + setdbat(2, 0xc<<24, 0xc<<24, 1<<24, IO_PAGE); + + _write_MSR(_read_MSR() | MSR_DR | MSR_IR); + __asm__ volatile("sync; isync"); +#endif +} diff --git a/bsps/powerpc/qemuppc/start/cmain.c b/bsps/powerpc/qemuppc/start/cmain.c new file mode 100644 index 0000000000..bf46d03177 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/cmain.c @@ -0,0 +1,55 @@ +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +static void +__outb(int port, unsigned char v) +{ + *((volatile unsigned char *)(0x80000000 + port)) = v; +} + +#if 0 +/* currently unused but keep just in case */ + +static unsigned char +__inb(int port) +{ + return *((volatile unsigned char *)(0x80000000 + port)); +} +#endif + +static void +__memcpy (unsigned char *d, unsigned char *s, int len) +{ + while (len--) + *d++ = *s++; +} + +static void +__bzero (unsigned char *d, int len) +{ + while (len--) + *d++ = 0; +} + + +/* + * Prototype this here because it is just the entry symbol and + * not referenced from any compileable code. + */ +void cmain (void); + +void cmain (void) +{ + /* + * init variable sections + */ + __memcpy (bsp_section_data_begin, bsp_section_data_load_begin, (int)bsp_section_data_size); + __bzero (bsp_section_bss_begin, (int)bsp_section_bss_size); + __bzero (bsp_section_sbss_begin, (int)bsp_section_sbss_size); + /* printk( "start of BSP\n"); */ + boot_card(0); + /* printk( "end of BSP\n"); */ + __outb (0x92, 0x01); + while (1) + ; +} diff --git a/bsps/powerpc/qemuppc/start/linkcmds b/bsps/powerpc/qemuppc/start/linkcmds new file mode 100644 index 0000000000..3169ad2741 --- /dev/null +++ b/bsps/powerpc/qemuppc/start/linkcmds @@ -0,0 +1,38 @@ +EXTERN(__vectors) + +MEMORY + { + EMPTY : ORIGIN = 0, LENGTH = 0 + RAM : ORIGIN = 0x2000, LENGTH = 4M - 0x2000 + ROM : ORIGIN = 0xFFC00000, LENGTH = 4M + VECTORS : ORIGIN = 0xFFF00000, LENGTH = 0x20000 + RESET : ORIGIN = 0xFFFFFFFC, LENGTH = 0x4 + } + +REGION_ALIAS ("REGION_START", ROM); +REGION_ALIAS ("REGION_FAST_TEXT", ROM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_TEXT", ROM); +REGION_ALIAS ("REGION_TEXT_LOAD", ROM); +REGION_ALIAS ("REGION_RODATA", ROM); +REGION_ALIAS ("REGION_RODATA_LOAD", ROM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", ROM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + .reset : + { + KEEP(*(.reset)) + } >RESET +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/bsp_specs b/bsps/powerpc/qoriq/start/bsp_specs new file mode 100644 index 0000000000..001c45b3c4 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s rtems_crtn.o%s ecrtn.o%s} diff --git a/bsps/powerpc/qoriq/start/bspreset.c b/bsps/powerpc/qoriq/start/bspreset.c new file mode 100644 index 0000000000..545aa28ee3 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspreset.c @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP reset. + */ + +/* + * Copyright (c) 2010, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/bootcard.h> +#include <bsp/fdt.h> +#include <bsp/qoriq.h> + +#include <libfdt.h> + +static int find_rstcr_node(const void *fdt, int node) +{ + return fdt_node_offset_by_prop_value(fdt, node, "fsl,has-rstcr", NULL, 0); +} + +void bsp_reset(void) +{ + rtems_interrupt_level level; + const char *fdt; + + rtems_interrupt_local_disable(level); + (void) level; + + fdt = bsp_fdt_get(); + + /* If we do not find a RSTCR, then loop forever */ + while (true) { + int node; + + node = -1; + + while ((node = find_rstcr_node(fdt, node)) >= 0) { + const uint32_t *reg; + int len; + + reg = fdt_getprop(fdt, node, "reg", &len); + if (reg != NULL && len >= 4) { + volatile uint32_t *rstcr; + + rstcr = (volatile uint32_t *) + ((uintptr_t) &qoriq + fdt32_to_cpu(reg[0]) + 0xb0); + *rstcr = 0x2; + } + } + } +} diff --git a/bsps/powerpc/qoriq/start/bsprestart.c b/bsps/powerpc/qoriq/start/bsprestart.c new file mode 100644 index 0000000000..36e751e50d --- /dev/null +++ b/bsps/powerpc/qoriq/start/bsprestart.c @@ -0,0 +1,146 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP restart. + */ + +/* + * Copyright (c) 2016, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/fatal.h> +#include <bsp/fdt.h> +#include <bsp/linker-symbols.h> +#include <bsp/qoriq.h> + +#include <libcpu/powerpc-utility.h> + +#include <string.h> + +static char fdt_copy[BSP_FDT_BLOB_SIZE_MAX]; + +static RTEMS_NO_RETURN void do_restart(void *addr) +{ + void (*restart)(uintptr_t); + + qoriq_reset_qman_and_bman(); + + memcpy(fdt_copy, bsp_fdt_get(), sizeof(fdt_copy)); + rtems_cache_flush_multiple_data_lines(fdt_copy, sizeof(fdt_copy)); + + restart = addr; + (*restart)((uintptr_t) fdt_copy); + bsp_fatal(QORIQ_FATAL_RESTART_FAILED); +} + +#if defined(RTEMS_SMP) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + +#include <rtems/score/smpimpl.h> +#include <rtems/score/smpbarrier.h> + +#define RESTART_IPI_INDEX 1 + +static SMP_barrier_Control restart_barrier = SMP_BARRIER_CONTROL_INITIALIZER; + +static void restart_interrupt(void *arg) +{ + uint32_t cpu_self_index; + uint32_t thread_index; + rtems_interrupt_level level; + SMP_barrier_State bs; + + rtems_interrupt_local_disable(level); + (void) level; + + _SMP_barrier_State_initialize(&bs); + _SMP_barrier_Wait(&restart_barrier, &bs, _SMP_Processor_count); + + cpu_self_index = rtems_get_current_processor(); + thread_index = cpu_self_index % QORIQ_THREAD_COUNT; + + if (cpu_self_index == 0) { + do_restart(arg); + } else if (thread_index == 0) { + uint32_t real_processor_index; + const qoriq_start_spin_table *spin_table; + + real_processor_index = cpu_self_index / QORIQ_THREAD_COUNT; + spin_table = qoriq_start_spin_table_addr[real_processor_index]; + + qoriq_restart_secondary_processor(spin_table); + } else { + uint32_t pir_reset_value; + + /* Restore reset PIR value */ + pir_reset_value = (cpu_self_index & ~0x1U) << 2; + PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, pir_reset_value); + + /* Thread Enable Clear (TENC) */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENC, 1U << thread_index); + + RTEMS_UNREACHABLE(); + } +} + +static void raise_restart_interrupt(void) +{ + qoriq.pic.ipidr[RESTART_IPI_INDEX].reg = + _Processor_mask_To_uint32_t(_SMP_Get_online_processors(), 0); + ppc_synchronize_data(); + ppc_synchronize_instructions(); +} + +void bsp_restart(void *addr) +{ + rtems_status_code sc; + size_t i; + + for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr); ++i) { + qoriq_start_spin_table *spin_table; + + spin_table = qoriq_start_spin_table_addr[i]; + memset(spin_table, 0, sizeof(*spin_table)); + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + } + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0 + RESTART_IPI_INDEX, + "Restart", + RTEMS_INTERRUPT_UNIQUE, + restart_interrupt, + addr + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(QORIQ_FATAL_RESTART_INSTALL_INTERRUPT); + } + + raise_restart_interrupt(); + bsp_fatal(QORIQ_FATAL_RESTART_INTERRUPT_FAILED); +} + +#else /* !RTEMS_SMP || QORIQ_IS_HYPERVISOR_GUEST */ + +void bsp_restart(void *addr) +{ + rtems_interrupt_level level; + + rtems_interrupt_local_disable(level); + (void) level; + do_restart(addr); +} + +#endif /* RTEMS_SMP && !QORIQ_IS_HYPERVISOR_GUEST */ diff --git a/bsps/powerpc/qoriq/start/bspsmp.c b/bsps/powerpc/qoriq/start/bspsmp.c new file mode 100644 index 0000000000..a2d9fbede5 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspsmp.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/score/smpimpl.h> + +#include <libfdt.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/fdt.h> +#include <bsp/mmu.h> +#include <bsp/fatal.h> +#include <bsp/qoriq.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +#if QORIQ_THREAD_COUNT > 1 +void _start_thread(void); +#endif + +void _start_secondary_processor(void); + +#define IPI_INDEX 0 + +#if QORIQ_THREAD_COUNT > 1 +static bool is_started_by_u_boot(uint32_t cpu_index) +{ + return cpu_index % QORIQ_THREAD_COUNT == 0; +} + +void qoriq_start_thread(void) +{ + const Per_CPU_Control *cpu_self = _Per_CPU_Get(); + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) cpu_self->interrupt_stack_low, + rtems_configuration_get_interrupt_stack_size() + ); + + bsp_interrupt_facility_initialize(); + + _SMP_Start_multitasking_on_secondary_processor(); +} +#endif + +static void start_thread_if_necessary(uint32_t cpu_index_self) +{ +#if QORIQ_THREAD_COUNT > 1 + uint32_t i; + + for (i = 1; i < QORIQ_THREAD_COUNT; ++i) { + uint32_t cpu_index_next = cpu_index_self + i; + + if ( + is_started_by_u_boot(cpu_index_self) + && cpu_index_next < rtems_configuration_get_maximum_processors() + && _SMP_Should_start_processor(cpu_index_next) + ) { + /* Thread Initial Next Instruction Address (INIA) */ + PPC_SET_THREAD_MGMT_REGISTER(321, (uintptr_t) _start_thread); + + /* Thread Initial Machine State (IMSR) */ + PPC_SET_THREAD_MGMT_REGISTER(289, QORIQ_INITIAL_MSR); + + /* Thread Enable Set (TENS) */ + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENS, 1U << i); + } + } +#endif +} + +void bsp_start_on_secondary_processor(void) +{ + uint32_t cpu_index_self = _SMP_Get_current_processor(); + const Per_CPU_Control *cpu_self = _Per_CPU_Get_by_index(cpu_index_self); + + qoriq_initialize_exceptions(cpu_self->interrupt_stack_low); + bsp_interrupt_facility_initialize(); + + start_thread_if_necessary(cpu_index_self); + + _SMP_Start_multitasking_on_secondary_processor(); +} + +#ifndef QORIQ_IS_HYPERVISOR_GUEST +static void bsp_inter_processor_interrupt(void *arg) +{ + _SMP_Inter_processor_interrupt_handler(); +} +#endif + +static void setup_boot_page(void) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + qoriq_mmu_context mmu_context; + + qoriq_mmu_context_init(&mmu_context); + qoriq_mmu_add( + &mmu_context, + 0xfffff000, + 0xffffffff, + 0, + 0, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + 0 + ); + qoriq_mmu_partition(&mmu_context, 1); + qoriq_mmu_write_to_tlb1(&mmu_context, QORIQ_TLB1_ENTRY_COUNT - 1); +#endif +} + +static uint32_t discover_processors(void) +{ + const void *fdt = bsp_fdt_get(); + int cpus = fdt_path_offset(fdt, "/cpus"); + int node = fdt_first_subnode(fdt, cpus); + uint32_t cpu = 0; + + while (node >= 0 && cpu < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr)) { + int len; + fdt64_t *addr_fdt = (fdt64_t *) + fdt_getprop(fdt, node, "cpu-release-addr", &len); + + if (addr_fdt != NULL) { + uintptr_t addr = (uintptr_t) fdt64_to_cpu(*addr_fdt); + + qoriq_start_spin_table_addr[cpu] = (qoriq_start_spin_table *) addr; + } + + ++cpu; + node = fdt_next_subnode(fdt, node); + } + + return cpu * QORIQ_THREAD_COUNT; +} + +uint32_t _CPU_SMP_Initialize(void) +{ + uint32_t cpu_count = 1; + + if (rtems_configuration_get_maximum_processors() > 0) { + setup_boot_page(); + cpu_count = discover_processors(); + } + + start_thread_if_necessary(0); + + return cpu_count; +} + +static bool release_processor( + qoriq_start_spin_table *spin_table, + uint32_t cpu_index +) +{ + bool spin_table_present = (spin_table != NULL); + + if (spin_table_present) { + const Per_CPU_Control *cpu = _Per_CPU_Get_by_index(cpu_index); + + spin_table->pir = cpu_index; + spin_table->r3 = (uintptr_t) cpu->interrupt_stack_high; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + ppc_synchronize_data(); + spin_table->addr = (uintptr_t) _start_secondary_processor; + rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table)); + } + + return spin_table_present; +} + +static qoriq_start_spin_table *get_spin_table(uint32_t cpu_index) +{ + qoriq_start_spin_table *spin_table; + + spin_table = qoriq_start_spin_table_addr[cpu_index / QORIQ_THREAD_COUNT]; + + return spin_table; +} + +bool _CPU_SMP_Start_processor(uint32_t cpu_index) +{ +#if QORIQ_THREAD_COUNT > 1 + if (is_started_by_u_boot(cpu_index)) { + qoriq_start_spin_table *spin_table = get_spin_table(cpu_index); + + return release_processor(spin_table, cpu_index); + } else { + return _SMP_Should_start_processor(cpu_index - 1); + } +#else + qoriq_start_spin_table *spin_table = get_spin_table(cpu_index); + + return release_processor(spin_table, cpu_index); +#endif +} + +void _CPU_SMP_Finalize_initialization(uint32_t cpu_count) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + (void) cpu_count; +#else + if (cpu_count > 1) { + rtems_status_code sc; + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0 + IPI_INDEX, + "IPI", + RTEMS_INTERRUPT_UNIQUE, + bsp_inter_processor_interrupt, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + bsp_fatal(QORIQ_FATAL_SMP_IPI_HANDLER_INSTALL); + } + } +#endif +} + +void _CPU_SMP_Prepare_start_multitasking(void) +{ + /* Do nothing */ +} + +void _CPU_SMP_Send_interrupt(uint32_t target_processor_index) +{ +#ifdef QORIQ_IS_HYPERVISOR_GUEST + uint32_t msg; + + /* DBELL message type */ + msg = (0U << (63 - 36)) | target_processor_index; + __asm__ volatile ("msgsnd %0" : : "r" (msg)); +#else + qoriq.pic.ipidr [IPI_INDEX].reg = 1U << target_processor_index; +#endif +} diff --git a/bsps/powerpc/qoriq/start/bspstart.c b/bsps/powerpc/qoriq/start/bspstart.c new file mode 100644 index 0000000000..7d9fa0d3c7 --- /dev/null +++ b/bsps/powerpc/qoriq/start/bspstart.c @@ -0,0 +1,197 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP startup. + */ + +/* + * Copyright (c) 2010, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libfdt.h> + +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/counter.h> +#include <rtems/sysinit.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/console-termios.h> +#include <bsp/fatal.h> +#include <bsp/fdt.h> +#include <bsp/intercom.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> +#include <bsp/qoriq.h> +#include <bsp/vectors.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +qoriq_start_spin_table * +qoriq_start_spin_table_addr[QORIQ_CPU_COUNT / QORIQ_THREAD_COUNT]; + +/* Configuration parameters for console driver, ... */ +unsigned int BSP_bus_frequency; + +/* Configuration parameter for clock driver, ... */ +uint32_t bsp_time_base_frequency; + +uint32_t qoriq_clock_frequency; + +static void initialize_frequency_parameters(void) +{ + const void *fdt = bsp_fdt_get(); + int node; + int len; + fdt32_t *val_fdt; + + node = fdt_node_offset_by_prop_value(fdt, -1, "device_type", "cpu", 4); + + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "bus-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_BUS_FREQUENCY); + } + BSP_bus_frequency = fdt32_to_cpu(*val_fdt) / QORIQ_BUS_CLOCK_DIVIDER; + + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "timebase-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_BUS_FREQUENCY); + } + bsp_time_base_frequency = fdt32_to_cpu(*val_fdt); + + #ifdef __PPC_CPU_E6500__ + val_fdt = (fdt32_t *) fdt_getprop(fdt, node, "clock-frequency", &len); + if (val_fdt == NULL || len != 4) { + bsp_fatal(QORIQ_FATAL_FDT_NO_CLOCK_FREQUENCY); + } + qoriq_clock_frequency = fdt32_to_cpu(*val_fdt); + #endif + rtems_counter_initialize_converter(fdt32_to_cpu(*val_fdt)); +} + +#define MTIVPR(base) \ + __asm__ volatile ("mtivpr %0" : : "r" (base)) + +#ifdef __powerpc64__ +#define VECTOR_TABLE_ENTRY_SIZE 32 +#else +#define VECTOR_TABLE_ENTRY_SIZE 16 +#endif + +#define MTIVOR(vec, offset) \ + do { \ + __asm__ volatile ("mtspr " RTEMS_XSTRING(vec) ", %0" : : "r" (offset)); \ + offset += VECTOR_TABLE_ENTRY_SIZE; \ + } while (0) + +void qoriq_initialize_exceptions(void *interrupt_stack_begin) +{ + uintptr_t addr; + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) interrupt_stack_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + addr = (uintptr_t) bsp_exc_vector_base; + MTIVPR(addr); + MTIVOR(BOOKE_IVOR0, addr); + MTIVOR(BOOKE_IVOR1, addr); + MTIVOR(BOOKE_IVOR2, addr); + MTIVOR(BOOKE_IVOR3, addr); + MTIVOR(BOOKE_IVOR4, addr); + MTIVOR(BOOKE_IVOR5, addr); + MTIVOR(BOOKE_IVOR6, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR7, addr); +#endif + MTIVOR(BOOKE_IVOR8, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR9, addr); +#endif + MTIVOR(BOOKE_IVOR10, addr); + MTIVOR(BOOKE_IVOR11, addr); + MTIVOR(BOOKE_IVOR12, addr); + MTIVOR(BOOKE_IVOR13, addr); + MTIVOR(BOOKE_IVOR14, addr); + MTIVOR(BOOKE_IVOR15, addr); + MTIVOR(BOOKE_IVOR32, addr); + MTIVOR(BOOKE_IVOR33, addr); +#ifndef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR34, addr); +#endif + MTIVOR(BOOKE_IVOR35, addr); +#ifdef __PPC_CPU_E6500__ + MTIVOR(BOOKE_IVOR36, addr); + MTIVOR(BOOKE_IVOR37, addr); +#ifndef QORIQ_IS_HYPERVISOR_GUEST + MTIVOR(BOOKE_IVOR38, addr); + MTIVOR(BOOKE_IVOR39, addr); + MTIVOR(BOOKE_IVOR40, addr); + MTIVOR(BOOKE_IVOR41, addr); + MTIVOR(BOOKE_IVOR42, addr); +#endif +#endif +} + +void bsp_start(void) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + initialize_frequency_parameters(); + + qoriq_initialize_exceptions(bsp_section_work_begin); + bsp_interrupt_initialize(); + + rtems_cache_coherent_add_area( + bsp_section_nocacheheap_begin, + (uintptr_t) bsp_section_nocacheheap_size + ); + +#ifndef QORIQ_IS_HYPERVISOR_GUEST + /* Disable boot page translation */ +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + qoriq.lcc.bstar &= ~LCC_BSTAR_EN; +#else + qoriq.lcc.bptr &= ~BPTR_EN; +#endif +#endif +} + +uint32_t bsp_fdt_map_intr(const uint32_t *intr, size_t icells) +{ +#ifndef QORIQ_IS_HYPERVISOR_GUEST + return intr[0] - 16; +#else + return intr[0]; +#endif +} + +#ifdef RTEMS_MULTIPROCESSING +RTEMS_SYSINIT_ITEM( + qoriq_intercom_init, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); +#endif diff --git a/bsps/powerpc/qoriq/start/epapr_hcalls.S b/bsps/powerpc/qoriq/start/epapr_hcalls.S new file mode 100644 index 0000000000..b019e5d710 --- /dev/null +++ b/bsps/powerpc/qoriq/start/epapr_hcalls.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> + + .text + + .global epapr_hypercall_start +epapr_hypercall_start: + + sc 1 + nop + nop + nop + blr diff --git a/bsps/powerpc/qoriq/start/l1cache.S b/bsps/powerpc/qoriq/start/l1cache.S new file mode 100644 index 0000000000..bee3d28123 --- /dev/null +++ b/bsps/powerpc/qoriq/start/l1cache.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> + + .global qoriq_l1cache_invalidate + + .section ".bsp_start_text", "ax" + +qoriq_l1cache_invalidate: + + /* Invalidate L1 data cache */ + mfspr r3, FSL_EIS_L1CSR0 + ori r3, r3, FSL_EIS_L1CSR0_CFI + mtspr FSL_EIS_L1CSR0, r3 +1: + mfspr r3, FSL_EIS_L1CSR0 + andi. r3, r3, FSL_EIS_L1CSR0_CFI + bne 1b + isync + + /* Invalidate L1 instruction cache */ + mfspr r3, FSL_EIS_L1CSR1 + ori r3, r3, FSL_EIS_L1CSR1_ICFI + mtspr FSL_EIS_L1CSR1, r3 +1: + mfspr r3, FSL_EIS_L1CSR1 + andi. r3, r3, FSL_EIS_L1CSR1_ICFI + bne 1b + isync + + blr diff --git a/bsps/powerpc/qoriq/start/l2cache.S b/bsps/powerpc/qoriq/start/l2cache.S new file mode 100644 index 0000000000..1c57659aa1 --- /dev/null +++ b/bsps/powerpc/qoriq/start/l2cache.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> + + .global qoriq_l2cache_flush_invalidate + + .section ".bsp_start_text", "ax" + +qoriq_l2cache_flush_invalidate: + + /* Flush L2 cache */ + lwz r4, 0(r3) + oris r4, r4, FSL_EIS_L2CSR0_L2FL >> 16 + stw r4, 0(r3) +1: + lwz r4, 0(r3) + andis. r4, r4, FSL_EIS_L2CSR0_L2FL >> 16 + bne 1b + isync + + /* Invalidate L2 cache */ + lwz r4, 0(r3) + oris r4, r4, FSL_EIS_L2CSR0_L2FI >> 16 + stw r4, 0(r3) +1: + lwz r4, 0(r3) + andis. r4, r4, FSL_EIS_L2CSR0_L2FI >> 16 + bne 1b + isync + + blr diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 new file mode 100644 index 0000000000..80ae3937bf --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_0 @@ -0,0 +1,38 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 0. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 32M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 new file mode 100644 index 0000000000..ecb601b9ef --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_core_1 @@ -0,0 +1,37 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 1. + */ + +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x4000000, LENGTH = 64M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 new file mode 100644 index 0000000000..b727aefaa8 --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e500 @@ -0,0 +1,38 @@ +/** + * @file + * + * Memory map for P1020RDB. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 512M - 16M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 new file mode 100644 index 0000000000..900147c163 --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_32 @@ -0,0 +1,41 @@ +/** + * @file + * + * Memory map for e6500 core based QorIQ chips, e.g. T2080, T4240. + */ + +EXTERN (__vectors) + +MEMORY { + LOW : ORIGIN = 0x00004000, LENGTH = 16M - 16k + NOCACHE : ORIGIN = 0x01000000, LENGTH = 48M + HIGH : ORIGIN = 0x04000000, LENGTH = 512M - 64M + EMPTY : ORIGIN = 0x00000000, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); +REGION_ALIAS ("REGION_NOCACHE", NOCACHE); +REGION_ALIAS ("REGION_NOCACHE_LOAD", LOW); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe000000; +qoriq_bman_portal = 0xff4000000; +qoriq_qman_portal = 0xff6000000; + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 new file mode 100644 index 0000000000..a4969756ec --- /dev/null +++ b/bsps/powerpc/qoriq/start/linkcmds.qoriq_e6500_64 @@ -0,0 +1 @@ +INCLUDE linkcmds.qoriq_e6500_32 diff --git a/bsps/powerpc/qoriq/start/mmu-config.c b/bsps/powerpc/qoriq/start/mmu-config.c new file mode 100644 index 0000000000..b59d9c7114 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu-config.c @@ -0,0 +1,352 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/fdt.h> +#include <bsp/linker-symbols.h> +#include <bsp/mmu.h> +#include <bsp/qoriq.h> + +#include <sys/param.h> + +#include <libfdt.h> + +#include <rtems/config.h> + +#define TEXT __attribute__((section(".bsp_start_text"))) +#define DATA __attribute__((section(".bsp_start_data"))) + +typedef struct { + uintptr_t begin; + uintptr_t size; + uint32_t mas2; + uint32_t mas3; + uint32_t mas7; +} entry; + +#define ENTRY_X(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SX \ +} + +#define ENTRY_R(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SR \ +} + +#ifdef RTEMS_SMP + #define ENTRY_RW_MAS2 FSL_EIS_MAS2_M +#else + #define ENTRY_RW_MAS2 0 +#endif + +#define ENTRY_RW(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = ENTRY_RW_MAS2, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +#define ENTRY_IO(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +#define ENTRY_DEV(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ + .mas7 = QORIQ_MMU_DEVICE_MAS7 \ +} + +/* + * MMU entry for BMan and QMan software portals. + * + * The M bit must be set if stashing is used, see 3.3.8.6 DQRR Entry Stashing + * and 3.3.8 Software Portals in T4240DPAARM. + * + * The G bit must be set, otherwise ECC errors in the QMan software portals + * will occur. No documentation reference for this is available. + */ +#define ENTRY_DEV_CACHED(b, s) { \ + .begin = (uintptr_t) b, \ + .size = (uintptr_t) s, \ + .mas2 = FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, \ + .mas7 = QORIQ_MMU_DEVICE_MAS7 \ +} + +#define WORKSPACE_ENTRY_INDEX 0 + +static entry DATA config[] = { + /* Must be first entry, see WORKSPACE_ENTRY_INDEX */ + ENTRY_RW(bsp_section_work_begin, bsp_section_work_size), + + #if defined(RTEMS_MULTIPROCESSING) && \ + defined(QORIQ_INTERCOM_AREA_BEGIN) && \ + defined(QORIQ_INTERCOM_AREA_SIZE) + { + .begin = QORIQ_INTERCOM_AREA_BEGIN, + .size = QORIQ_INTERCOM_AREA_SIZE, + .mas2 = FSL_EIS_MAS2_M, + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW + }, + #endif + ENTRY_X(bsp_section_start_begin, bsp_section_start_size), + ENTRY_R(bsp_section_fast_text_load_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_fast_text_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_text_begin, bsp_section_text_size), + ENTRY_R(bsp_section_rodata_load_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_rodata_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_fast_data_load_begin, bsp_section_fast_data_size), + ENTRY_RW(bsp_section_fast_data_begin, bsp_section_fast_data_size), + ENTRY_R(bsp_section_data_load_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_data_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_sbss_begin, bsp_section_sbss_size), + ENTRY_RW(bsp_section_bss_begin, bsp_section_bss_size), + ENTRY_RW(bsp_section_rwextra_begin, bsp_section_rwextra_size), + ENTRY_RW(bsp_section_stack_begin, bsp_section_stack_size), + ENTRY_IO(bsp_section_nocache_begin, bsp_section_nocache_size), + ENTRY_IO(bsp_section_nocachenoload_begin, bsp_section_nocachenoload_size), +#ifndef QORIQ_IS_HYPERVISOR_GUEST +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + /* BMan Portals */ + ENTRY_DEV_CACHED(&qoriq_bman_portal[0][0], sizeof(qoriq_bman_portal[0])), + ENTRY_DEV(&qoriq_bman_portal[1][0], sizeof(qoriq_bman_portal[1])), + /* QMan Portals */ + ENTRY_DEV_CACHED(&qoriq_qman_portal[0][0], sizeof(qoriq_qman_portal[0])), + ENTRY_DEV(&qoriq_qman_portal[1][0], sizeof(qoriq_qman_portal[1])), +#endif + ENTRY_DEV(&qoriq, sizeof(qoriq)) +#endif +}; + +static DATA char memory_path[] = "/memory"; + +#ifdef QORIQ_IS_HYPERVISOR_GUEST +static void TEXT add_dpaa_bqman_portals( + qoriq_mmu_context *context, + const void *fdt, + const char *compatible +) +{ + int node; + + node = -1; + + while (true) { + const void *val; + int len; + uintptr_t paddr; + uintptr_t size; + + node = fdt_node_offset_by_compatible(fdt, node, compatible); + if (node < 0) { + break; + } + + val = fdt_getprop(fdt, node, "reg", &len); + if (len != 32) { + continue; + } + + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); + + qoriq_mmu_add( + context, + paddr, + paddr + size - 1, + 0, + FSL_EIS_MAS2_M | FSL_EIS_MAS2_G, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + QORIQ_MMU_DEVICE_MAS7 + ); + + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[3]); + + qoriq_mmu_add( + context, + paddr, + paddr + size - 1, + 0, + FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + QORIQ_MMU_DEVICE_MAS7 + ); + } +} + +static void TEXT add_dpaa_bpool(qoriq_mmu_context *context, const void *fdt) +{ + int node; + + node = -1; + + while (true) { + const void *val; + int len; + uintptr_t config_count; + uintptr_t size; + uintptr_t paddr; + + node = fdt_node_offset_by_compatible(fdt, node, "fsl,bpool"); + if (node < 0) { + break; + } + + val = fdt_getprop(fdt, node, "fsl,bpool-ethernet-cfg", &len); + if (len != 24) { + continue; + } + + config_count = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[0]); + size = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[1]); + paddr = (uintptr_t) fdt64_to_cpu(((fdt64_t *) val)[2]); + + qoriq_mmu_add( + context, + paddr, + paddr + config_count * size - 1, + 0, + FSL_EIS_MAS2_M, + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW, + 0 + ); + } +} +#endif + +static void TEXT config_fdt_adjust(const void *fdt) +{ + int node; + + node = fdt_path_offset_namelen( + fdt, + memory_path, + (int) sizeof(memory_path) - 1 + ); + + if (node >= 0) { + int len; + const void *val; + uint64_t mem_begin; + uint64_t mem_size; + + val = fdt_getprop(fdt, node, "reg", &len); + if (len == 8) { + mem_begin = fdt32_to_cpu(((fdt32_t *) val)[0]); + mem_size = fdt32_to_cpu(((fdt32_t *) val)[1]); + } else if (len == 16) { + mem_begin = fdt64_to_cpu(((fdt64_t *) val)[0]); + mem_size = fdt64_to_cpu(((fdt64_t *) val)[1]); + } else { + mem_begin = 0; + mem_size = 0; + } + +#ifndef __powerpc64__ + mem_size = MIN(mem_size, 0x80000000U); +#endif + + if ( + mem_begin == 0 + && mem_size > (uintptr_t) bsp_section_work_end + && (uintptr_t) bsp_section_nocache_end + < (uintptr_t) bsp_section_work_end + ) { + /* Assign new value to allow a bsp_restart() */ + config[WORKSPACE_ENTRY_INDEX].size = (uintptr_t) mem_size + - (uintptr_t) bsp_section_work_begin; + } + } +} + +void TEXT qoriq_mmu_config(bool boot_processor, int first_tlb, int scratch_tlb) +{ + qoriq_mmu_context context; + const void *fdt; + int max_count; + int i; + + for (i = 0; i < QORIQ_TLB1_ENTRY_COUNT; ++i) { + if (i != scratch_tlb) { + qoriq_tlb1_invalidate(i); + } + } + + fdt = bsp_fdt_get(); + qoriq_mmu_context_init(&context); + +#ifdef QORIQ_IS_HYPERVISOR_GUEST + add_dpaa_bqman_portals(&context, fdt, "fsl,bman-portal"); + add_dpaa_bqman_portals(&context, fdt, "fsl,qman-portal"); + add_dpaa_bpool(&context, fdt); + max_count = QORIQ_TLB1_ENTRY_COUNT - 1; +#else + max_count = (3 * QORIQ_TLB1_ENTRY_COUNT) / 4; +#endif + + if (boot_processor) { + config_fdt_adjust(fdt); + } + + for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) { + const entry *cur = &config [i]; + if (cur->size > 0) { + qoriq_mmu_add( + &context, + cur->begin, + cur->begin + cur->size - 1, + 0, + cur->mas2, + cur->mas3, + cur->mas7 + ); + } + } + + qoriq_mmu_partition(&context, max_count); + qoriq_mmu_write_to_tlb1(&context, first_tlb); +} + +void TEXT bsp_work_area_initialize(void) +{ + const entry *we = &config[WORKSPACE_ENTRY_INDEX]; + uintptr_t begin = we->begin; + uintptr_t end = begin + we->size; + +#ifdef BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN + begin += rtems_configuration_get_interrupt_stack_size(); +#endif + + bsp_work_area_initialize_default((void *) begin, end - begin); +} diff --git a/bsps/powerpc/qoriq/start/mmu-tlb1.S b/bsps/powerpc/qoriq/start/mmu-tlb1.S new file mode 100644 index 0000000000..2dd06e2ed8 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu-tlb1.S @@ -0,0 +1,107 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief qoriq_tlb1_write() and qoriq_tlb1_invalidate() implementation. + */ + +/* + * Copyright (c) 2011, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bspopts.h> + +#include <libcpu/powerpc-utility.h> + + .global qoriq_tlb1_write + .global qoriq_tlb1_invalidate + .global qoriq_tlb1_invalidate_all_by_ts + + .section ".bsp_start_text", "ax" + +qoriq_tlb1_write: + rlwinm r3, r3, 16, 10, 15 +#ifdef __powerpc64__ + rldicr r8, r8, 0, 51 +#else + rlwinm r8, r8, 0, 0, 19 +#endif + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + oris r4, r4, 0xc000 + rlwinm r9, r9, 8, 20, 23 + or r9, r4, r9 + mtspr FSL_EIS_MAS1, r9 + or r5, r8, r5 + mtspr FSL_EIS_MAS2, r5 + or r6, r8, r6 + mtspr FSL_EIS_MAS3, r6 +#ifdef __powerpc64__ + srdi r8, r8, 32 + or r7, r7, r8 + mtspr FSL_EIS_MAS7, r7 +#endif + mtspr FSL_EIS_MAS7, r7 +#if defined(QORIQ_HAS_HYPERVISOR_MODE) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + li r0, 0 + mtspr FSL_EIS_MAS8, r0 +#endif + isync + msync + tlbwe + isync + blr + +qoriq_tlb1_invalidate: + rlwinm r3, r3, 16, 10, 15 + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + li r0, 0 + mtspr FSL_EIS_MAS1, r0 + mtspr FSL_EIS_MAS2, r0 + mtspr FSL_EIS_MAS3, r0 + mtspr FSL_EIS_MAS7, r0 +#if defined(QORIQ_HAS_HYPERVISOR_MODE) && !defined(QORIQ_IS_HYPERVISOR_GUEST) + mtspr FSL_EIS_MAS8, r0 +#endif + isync + msync + tlbwe + isync + blr + +/* r3 = 0 for TS0, 1 for TS1 */ +qoriq_tlb1_invalidate_all_by_ts: + mflr r12 + li r11, QORIQ_TLB1_ENTRY_COUNT + mtctr r11 + li r11, 0 + mr r10, r3 + +2: + rlwinm r0, r11, 16, 10, 15 + oris r0, r0, (FSL_EIS_MAS0_TLBSEL >> 16) + mtspr FSL_EIS_MAS0, r0 + tlbre + mfspr r0, FSL_EIS_MAS1 + rlwinm r0, r0, 20, 31, 31 + cmpw r0, r10 + bne 1f + mr r3, r11 + bl qoriq_tlb1_invalidate +1: + addi r11, r11, 1 + bdnz 2b + mtlr r12 + blr diff --git a/bsps/powerpc/qoriq/start/mmu.c b/bsps/powerpc/qoriq/start/mmu.c new file mode 100644 index 0000000000..2629c9f999 --- /dev/null +++ b/bsps/powerpc/qoriq/start/mmu.c @@ -0,0 +1,368 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/mmu.h> +#include <libcpu/powerpc-utility.h> + +#define TEXT __attribute__((section(".bsp_start_text"))) + +static uintptr_t TEXT power_of_two(uintptr_t val) +{ + uintptr_t test_power = QORIQ_MMU_MIN_POWER; + uintptr_t power = test_power; + uintptr_t alignment = 1U << test_power; + + while (test_power <= QORIQ_MMU_MAX_POWER && (val & (alignment - 1)) == 0) { + power = test_power; + alignment <<= QORIQ_MMU_POWER_STEP; + test_power += QORIQ_MMU_POWER_STEP; + } + + return power; +} + +static uintptr_t TEXT max_power_of_two(uintptr_t val) +{ + uintptr_t test_power = QORIQ_MMU_MIN_POWER; + uintptr_t power = test_power; + uintptr_t max = 1U << test_power; + + do { + power = test_power; + max <<= QORIQ_MMU_POWER_STEP; + test_power += QORIQ_MMU_POWER_STEP; + } while (test_power <= QORIQ_MMU_MAX_POWER && max <= val); + + return power; +} + +void TEXT qoriq_mmu_context_init(qoriq_mmu_context *self) +{ + int *cur = (int *) self; + const int *end = cur + sizeof(*self) / sizeof(*cur); + + while (cur != end) { + *cur = 0; + ++cur; + } +} + +static void TEXT sort(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry key = entries [i]; + int j = 0; + + for (j = i - 1; j >= 0 && entries [j].begin > key.begin; --j) { + entries [j + 1] = entries [j]; + } + + entries [j + 1] = key; + } +} + +static bool TEXT mas_compatible(const qoriq_mmu_entry *a, const qoriq_mmu_entry *b) +{ + uint32_t m = FSL_EIS_MAS2_M; + + return (a->mas2 & ~m) == (b->mas2 & ~m); +} + +static bool TEXT can_merge(const qoriq_mmu_entry *prev, const qoriq_mmu_entry *cur) +{ + return mas_compatible(prev, cur) + && (prev->begin == cur->begin || prev->last >= cur->begin - 1); +} + +static void TEXT merge(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry *prev = &entries [i - 1]; + qoriq_mmu_entry *cur = &entries [i]; + + if (can_merge(prev, cur)) { + int j = 0; + + prev->mas1 |= cur->mas1; + prev->mas2 |= cur->mas2; + prev->mas3 |= cur->mas3; + + if (cur->last > prev->last) { + prev->last = cur->last; + } + + for (j = i + 1; j < n; ++j) { + entries [j - 1] = entries [j]; + } + + --i; + --n; + } + } + + self->count = n; +} + +static void TEXT compact(qoriq_mmu_context *self) +{ + sort(self); + merge(self); +} + +static bool TEXT can_expand_down( + const qoriq_mmu_context *self, + const qoriq_mmu_entry *cur, + int i, + uintptr_t new_begin +) +{ + int j; + + for (j = 0; j < i; ++j) { + const qoriq_mmu_entry *before = &self->entries[j]; + + if ( + before->begin <= new_begin + && new_begin <= before->last + && !mas_compatible(before, cur) + ) { + return false; + } + } + + return true; +} + +static bool TEXT can_expand_up( + const qoriq_mmu_context *self, + const qoriq_mmu_entry *cur, + int i, + int n, + uintptr_t new_last +) +{ + int j; + + for (j = i + 1; j < n; ++j) { + const qoriq_mmu_entry *after = &self->entries[j]; + + if ( + after->begin <= new_last + && new_last <= after->last + && !mas_compatible(after, cur) + ) { + return false; + } + } + + return true; +} + +static void TEXT align(qoriq_mmu_context *self, uintptr_t alignment) +{ + int n = self->count; + int i; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &self->entries[i]; + uintptr_t new_begin = cur->begin & ~(alignment - 1); + uintptr_t new_last = alignment + (cur->last & ~(alignment - 1)) - 1; + + if ( + can_expand_down(self, cur, i, new_begin) + && can_expand_up(self, cur, i, n, new_last) + ) { + cur->begin = new_begin; + cur->last = new_last; + } + } +} + +static bool TEXT is_full(qoriq_mmu_context *self) +{ + return self->count >= QORIQ_TLB1_ENTRY_COUNT; +} + +static void TEXT append(qoriq_mmu_context *self, const qoriq_mmu_entry *new_entry) +{ + self->entries [self->count] = *new_entry; + ++self->count; +} + +bool TEXT qoriq_mmu_add( + qoriq_mmu_context *self, + uintptr_t begin, + uintptr_t last, + uint32_t mas1, + uint32_t mas2, + uint32_t mas3, + uint32_t mas7 +) +{ + bool ok = true; + + if (is_full(self)) { + compact(self); + } + + if (!is_full(self)) { + if (begin < last) { + qoriq_mmu_entry new_entry = { + .begin = begin, + .last = last, + .mas1 = mas1, + .mas2 = mas2, + .mas3 = mas3, + .mas7 = mas7 + }; + append(self, &new_entry); + } else { + ok = false; + } + } else { + ok = false; + } + + return ok; +} + +static uintptr_t TEXT min(uintptr_t a, uintptr_t b) +{ + return a < b ? a : b; +} + +static bool TEXT split(qoriq_mmu_context *self, qoriq_mmu_entry *cur) +{ + bool again = false; + uintptr_t begin = cur->begin; + uintptr_t end = cur->last + 1; + uintptr_t size = end - begin; + uintptr_t begin_power = power_of_two(begin); + uintptr_t size_power = max_power_of_two(size); + uintptr_t power = min(begin_power, size_power); + uintptr_t split_size = power < 32 ? (1U << power) : 0; + uintptr_t split_pos = begin + split_size; + + if (split_pos != end && !is_full(self)) { + qoriq_mmu_entry new_entry = *cur; + cur->begin = split_pos; + new_entry.last = split_pos - 1; + append(self, &new_entry); + again = true; + } + + return again; +} + +static void TEXT split_all(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + + while (split(self, cur)) { + /* Repeat */ + } + } +} + +static TEXT void partition(qoriq_mmu_context *self) +{ + compact(self); + split_all(self); + sort(self); +} + +void TEXT qoriq_mmu_partition(qoriq_mmu_context *self, int max_count) +{ + uintptr_t alignment = 4096; + + sort(self); + + do { + align(self, alignment); + partition(self); + alignment *= 4; + } while (self->count > max_count); +} + +void TEXT qoriq_mmu_write_to_tlb1(qoriq_mmu_context *self, int first_tlb) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + uintptr_t ea = cur->begin; + uintptr_t size = cur->last - ea + 1; + uintptr_t tsize = (power_of_two(size) - 10) / 2; + int tlb = first_tlb + i; + + qoriq_tlb1_write( + tlb, + cur->mas1, + cur->mas2, + cur->mas3, + cur->mas7, + ea, + (int) tsize + ); + } +} + +void qoriq_mmu_change_perm(uint32_t test, uint32_t set, uint32_t clear) +{ + int i = 0; + + for (i = 0; i < 16; ++i) { + uint32_t mas0 = FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(i); + uint32_t mas1 = 0; + + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mas0); + asm volatile ("tlbre"); + + mas1 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); + if ((mas1 & FSL_EIS_MAS1_V) != 0) { + uint32_t mask = 0x3ff; + uint32_t mas3 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3); + + if ((mas3 & mask) == test) { + mas3 &= ~(clear & mask); + mas3 |= set & mask; + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3, mas3); + asm volatile ("isync; msync; tlbwe; isync" : : : "memory"); + } + } + } +} diff --git a/bsps/powerpc/qoriq/start/portal.c b/bsps/powerpc/qoriq/start/portal.c new file mode 100644 index 0000000000..f20eaf4d28 --- /dev/null +++ b/bsps/powerpc/qoriq/start/portal.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/qoriq.h> + +#if QORIQ_CHIP_IS_T_VARIANT(QORIQ_CHIP_VARIANT) + +#include <libcpu/powerpc-utility.h> + +void qoriq_clear_ce_portal(void *base, size_t size) +{ + size_t offset; + + for (offset = 0; offset < size; offset += 64) { + ppc_data_cache_block_clear_to_zero_2(base, offset); + ppc_data_cache_block_flush_2(base, offset); + } +} + +void qoriq_clear_ci_portal(void *base, size_t size) +{ + uint32_t zero; + size_t offset; + + zero = 0; + + for (offset = 0; offset < size; offset += 4) { + ppc_write_word(zero, (char *) base + offset); + } +} + +#endif diff --git a/bsps/powerpc/qoriq/start/restart.S b/bsps/powerpc/qoriq/start/restart.S new file mode 100644 index 0000000000..7dd9eb198d --- /dev/null +++ b/bsps/powerpc/qoriq/start/restart.S @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libcpu/powerpc-utility.h> + +#define FIRST_TLB 0 + +#define SCRATCH_TLB QORIQ_TLB1_ENTRY_COUNT - 1 + + .global qoriq_restart_secondary_processor + + .section ".bsp_start_text", "ax" + +qoriq_restart_secondary_processor: + + mr r14, r3 + + /* Invalidate all TS1 MMU entries */ + li r3, 1 + bl qoriq_tlb1_invalidate_all_by_ts + + /* Add TS1 entry for the first 4GiB of RAM */ + li r3, SCRATCH_TLB + li r4, FSL_EIS_MAS1_TS + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 0 + li r9, 11 + bl qoriq_tlb1_write + + bl qoriq_l1cache_invalidate + + /* Set MSR and use TS1 for address translation */ + LWI r0, QORIQ_INITIAL_MSR | MSR_IS | MSR_DS + mtmsr r0 + isync + + /* Invalidate all TS0 MMU entries */ + li r3, 0 + bl qoriq_tlb1_invalidate_all_by_ts + + /* Add TS0 entry for the first 4GiB of RAM */ + li r3, FIRST_TLB + li r4, 0 + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 0 + li r9, 11 + bl qoriq_tlb1_write + + /* Use TS0 for address translation */ + LWI r0, QORIQ_INITIAL_MSR + mtmsr r0 + isync + + bl qoriq_l1cache_invalidate + + /* Wait for restart request */ + li r0, 0 +.Lrestartagain: + lwz r4, 4(r14) + cmpw r0, r4 + beq .Lrestartagain + isync + mtctr r4 + lwz r3, 12(r14) + bctr diff --git a/bsps/powerpc/shared/start/bspgetworkarea.c b/bsps/powerpc/shared/start/bspgetworkarea.c new file mode 100644 index 0000000000..3c86905020 --- /dev/null +++ b/bsps/powerpc/shared/start/bspgetworkarea.c @@ -0,0 +1,40 @@ +/* + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +#include <libcpu/powerpc-utility.h> + +#include <rtems/sysinit.h> + +LINKER_SYMBOL(__rtems_end) + +void bsp_work_area_initialize(void) +{ + /* + * Cannot do work area initialization before bsp_start(), since BSP_mem_size + * and MMU is not set up. + */ +} + +static void bsp_work_area_initialize_later(void) +{ + uintptr_t work_size; + uintptr_t work_area; + + work_area = (uintptr_t)__rtems_end + + rtems_configuration_get_interrupt_stack_size(); + work_size = (uintptr_t)BSP_mem_size - work_area; + + bsp_work_area_initialize_default((void *) work_area, work_size); +} + +RTEMS_SYSINIT_ITEM( + bsp_work_area_initialize_later, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/powerpc/shared/start/bspidle.c b/bsps/powerpc/shared/start/bspidle.c new file mode 100644 index 0000000000..de37fa1ced --- /dev/null +++ b/bsps/powerpc/shared/start/bspidle.c @@ -0,0 +1,36 @@ +/* + * Moved to libbsp/powerpc/shared by Joel Sherrill (9 Sept 09). + */ + +/* + * The MPC860 specific stuff was written by Jay Monkman (jmonkman@frasca.com) + * + * Modified for the MPC8260ADS board by Andy Dachs <a.dachs@sstl.co.uk> + * Surrey Satellite Technology Limited, 2001 + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> + +/** + * @brief BSP Idle thread body. + * + * The MSR[POW] bit is set to put the CPU into the low power mode + * defined in HID0. HID0 is set during starup in start.S. + */ +void *bsp_idle_thread( uintptr_t ignored ) +{ + for( ; ; ) { + __asm__ volatile( + "mfmsr 3; oris 3,3,4; sync; mtmsr 3; isync; ori 3,3,0; ori 3,3,0" + ); + } + + return 0; /* to remove warning */ +} diff --git a/bsps/powerpc/shared/start/linkcmds.base b/bsps/powerpc/shared/start/linkcmds.base new file mode 100644 index 0000000000..e0dfdcc914 --- /dev/null +++ b/bsps/powerpc/shared/start/linkcmds.base @@ -0,0 +1,436 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command base file. + */ + +/* + * Copyright (c) 2011, 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +ENTRY (_start) +STARTUP (start.o) + +/* + * Global symbols that may be defined externally + */ + +bsp_section_xbarrier_align = DEFINED (bsp_section_xbarrier_align) ? bsp_section_xbarrier_align : 1; +bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1; +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1; + +MEMORY { + UNEXPECTED_SECTIONS : ORIGIN = 0xffffffff, LENGTH = 0 +} + +SECTIONS { + .start : ALIGN_WITH_INPUT { + bsp_section_start_begin = .; + KEEP (*(.bsp_start_text)) + KEEP (*(.bsp_start_data)) + bsp_section_start_end = .; + } > REGION_START AT > REGION_START + bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin; + + .xbarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_xbarrier_align); + } > REGION_TEXT AT > REGION_TEXT + + .text : ALIGN_WITH_INPUT { + bsp_section_text_begin = .; + *(SORT(.bsp_text*)) + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + *(.sfpr .glink) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : ALIGN_WITH_INPUT { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : ALIGN_WITH_INPUT { + PROVIDE (_fini = .); + KEEP (*(.fini)) + bsp_section_text_end = .; + } > REGION_TEXT AT > REGION_TEXT_LOAD + bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin; + bsp_section_text_load_begin = LOADADDR (.text); + bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size; + + .fast_text : ALIGN_WITH_INPUT { + bsp_section_fast_text_begin = .; + *(.bsp_fast_text) + bsp_section_fast_text_end = .; + } > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD + bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin; + bsp_section_fast_text_load_begin = LOADADDR (.fast_text); + bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size; + + .robarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_robarrier_align); + } > REGION_RODATA AT > REGION_RODATA + + .rodata : ALIGN_WITH_INPUT { + bsp_section_rodata_begin = .; + *(SORT(.bsp_rodata*)) + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rodata1 : ALIGN_WITH_INPUT { + *(.rodata1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sdata2 : ALIGN_WITH_INPUT { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sbss2 : ALIGN_WITH_INPUT { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame_hdr : ALIGN_WITH_INPUT { + *(.eh_frame_hdr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame : ALIGN_WITH_INPUT { + KEEP (*(*.eh_frame)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : ALIGN_WITH_INPUT { + *(.gcc_except_table *.gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : ALIGN_WITH_INPUT { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : ALIGN_WITH_INPUT { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + .preinit_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fini_array : ALIGN_WITH_INPUT { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : ALIGN_WITH_INPUT { + KEEP (*ecrti.o(.ctors)) + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *ecrtn.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dtors : ALIGN_WITH_INPUT { + KEEP (*ecrti.o(.dtors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o *ecrtn.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .jcr : ALIGN_WITH_INPUT { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .data.rel.ro : ALIGN_WITH_INPUT { + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fixup : ALIGN_WITH_INPUT { + *(.fixup) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : ALIGN_WITH_INPUT { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .opd : ALIGN_WITH_INPUT { + KEEP (*(.opd)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tm_clone_table : ALIGN_WITH_INPUT { + *(.tm_clone_table) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .toc1 : ALIGN_WITH_INPUT { + *(.toc1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .branch_lt : ALIGN_WITH_INPUT { + *(.branch_lt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got1 : ALIGN_WITH_INPUT { + *(.got1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got2 : ALIGN_WITH_INPUT { + *(.got2) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : ALIGN_WITH_INPUT { + *(.got) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .toc : ALIGN_WITH_INPUT { + *(.toc) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : ALIGN_WITH_INPUT { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : ALIGN_WITH_INPUT { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : ALIGN_WITH_INPUT { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : ALIGN_WITH_INPUT { + *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : ALIGN_WITH_INPUT { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : ALIGN_WITH_INPUT { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : ALIGN_WITH_INPUT { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : ALIGN_WITH_INPUT { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : ALIGN_WITH_INPUT { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : ALIGN_WITH_INPUT { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : ALIGN_WITH_INPUT { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.dyn : ALIGN_WITH_INPUT { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + *(.rela.rtemsroset*) + *(.rela.rtemsrwset*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : ALIGN_WITH_INPUT { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rtemsroset : ALIGN_WITH_INPUT { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + + KEEP (*(SORT(*.rtemsroset.*))) + bsp_section_rodata_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin; + bsp_section_rodata_load_begin = LOADADDR (.rodata); + bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size; + + .rwbarrier : ALIGN_WITH_INPUT { + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA AT > REGION_DATA + + .fast_data : ALIGN_WITH_INPUT { + bsp_section_fast_data_begin = .; + *(SORT(.bsp_fast_data*)) + bsp_section_fast_data_end = .; + } > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD + bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin; + bsp_section_fast_data_load_begin = LOADADDR (.fast_data); + bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size; + + .data : ALIGN_WITH_INPUT { + bsp_section_data_begin = .; + *(SORT(.bsp_data*)) + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : ALIGN_WITH_INPUT { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rtemsrwset : ALIGN_WITH_INPUT { + KEEP (*(SORT(.rtemsrwset.*))) + } > REGION_DATA AT > REGION_DATA_LOAD + .sdata : ALIGN_WITH_INPUT { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + bsp_section_data_end = .; + } > REGION_DATA AT > REGION_DATA_LOAD + bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin; + bsp_section_data_load_begin = LOADADDR (.data); + bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size; + + .sbss : ALIGN_WITH_INPUT { + bsp_section_sbss_begin = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + bsp_section_sbss_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_section_sbss_size = bsp_section_sbss_end - bsp_section_sbss_begin; + + .bss : ALIGN_WITH_INPUT { + bsp_section_bss_begin = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + bsp_section_bss_end = .; + } > REGION_BSS AT > REGION_BSS + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + + .rwextra : ALIGN_WITH_INPUT { + bsp_section_rwextra_begin = .; + *(.bsp_rwextra) + bsp_section_rwextra_end = .; + } > REGION_RWEXTRA AT > REGION_RWEXTRA + bsp_section_rwextra_size = bsp_section_rwextra_end - bsp_section_rwextra_begin; + + .work : ALIGN_WITH_INPUT { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + .stack : ALIGN_WITH_INPUT { + /* + * The stack section will occupy the remaining REGION_STACK region and may + * contain the task stacks. Depending on the region distribution this + * section may be of zero size. + */ + bsp_section_stack_begin = .; + . += ORIGIN (REGION_STACK) + LENGTH (REGION_STACK) - ABSOLUTE (.); + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_end - bsp_section_stack_begin; + + .nocache : ALIGN_WITH_INPUT { + bsp_section_nocache_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_nocache*))) + bsp_section_nocache_end = .; + } > REGION_NOCACHE AT > REGION_NOCACHE_LOAD + bsp_section_nocache_size = bsp_section_nocache_end - bsp_section_nocache_begin; + bsp_section_nocache_load_begin = LOADADDR (.nocache); + bsp_section_nocache_load_end = bsp_section_nocache_load_begin + bsp_section_nocache_size; + + .nocachenoload (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_nocachenoload_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_noload_nocache*))) + bsp_section_nocacheheap_begin = .; + . += ORIGIN (REGION_NOCACHE) + LENGTH (REGION_NOCACHE) - ABSOLUTE (.); + bsp_section_nocacheheap_end = .; + bsp_section_nocachenoload_end = .; + } > REGION_NOCACHE AT > REGION_NOCACHE + bsp_section_nocacheheap_size = bsp_section_nocacheheap_end - bsp_section_nocacheheap_begin; + bsp_section_nocachenoload_size = bsp_section_nocachenoload_end - bsp_section_nocachenoload_begin; + + .nvram (NOLOAD) : ALIGN_WITH_INPUT { + bsp_section_nvram_begin = .; + *(SORT_BY_ALIGNMENT (SORT_BY_NAME (.bsp_nvram*))) + bsp_section_nvram_end = .; + } > REGION_NVRAM AT > REGION_NVRAM + bsp_section_nvram_size = bsp_section_nvram_end - bsp_section_nvram_begin; + + /* FIXME */ + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges) } + /* DWARF Extension. */ + .debug_macro 0 : { *(.debug_macro) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + .PPC.EMB.apuinfo 0 : { *(.PPC.EMB.apuinfo) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + + /* + * This is a RTEMS specific section to catch all unexpected input + * sections. In case you get an error like + * "section `.unexpected_sections' will not fit in region + * `UNEXPECTED_SECTIONS'" + * you have to figure out the offending input section and add it to the + * appropriate output section definition above. + */ + .unexpected_sections : { *(*) } > UNEXPECTED_SECTIONS +} diff --git a/bsps/powerpc/shared/start/linkcmds.share b/bsps/powerpc/shared/start/linkcmds.share new file mode 100644 index 0000000000..59f538e3a2 --- /dev/null +++ b/bsps/powerpc/shared/start/linkcmds.share @@ -0,0 +1,296 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc) +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +PROVIDE (__stack = 0); +MEMORY { + VECTORS : ORIGIN = 0x0 , LENGTH = 0x3000 + CODE : ORIGIN = 0x3000 , LENGTH = 32M - 0x3000 +} +SECTIONS +{ + .entry_point_section : + { + KEEP(*(.entry_point_section)) + } > VECTORS + + /* + * This section is used only if NO_DYNAMIC_EXCEPTION_VECTOR_INSTALL + * is defined in vectors/vectors.S + */ + .vectors : + { + *(.vectors) + } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > CODE + .hash : { *(.hash) } > CODE + .dynsym : { *(.dynsym) } > CODE + .dynstr : { *(.dynstr) } > CODE + .gnu.version : { *(.gnu.version) } > CODE + .gnu.version_d : { *(.gnu.version_d) } > CODE + .gnu.version_r : { *(.gnu.version_r) } > CODE + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } > CODE + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } > CODE + .rela.rodata : + { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > CODE + .rela.got : { *(.rela.got) } > CODE + .rela.got1 : { *(.rela.got1) } > CODE + .rela.got2 : { *(.rela.got2) } > CODE + .rela.ctors : { *(.rela.ctors) } > CODE + .rela.dtors : { *(.rela.dtors) } > CODE + .rela.init : { *(.rela.init) } > CODE + .rela.fini : { *(.rela.fini) } > CODE + .rela.bss : { *(.rela.bss) } > CODE + .rela.plt : { *(.rela.plt) } > CODE + .rela.sdata : { *(.rela.sdata) } > CODE + .rela.sbss : { *(.rela.sbss) } > CODE + .rela.sdata2 : { *(.rela.sdata2) } > CODE + .rela.sbss2 : { *(.rela.sbss2) } > CODE + .rela.dyn : { *(.rela.dyn) } > CODE + + .init : { KEEP(*(.init)) } > CODE + + .text : + { + *(.text*) + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > CODE + + .fini : { _fini = .; KEEP(*(.fini)) } > CODE + + .rodata : { *(.rodata*) KEEP (*(SORT(.rtemsroset.*))) *(.gnu.linkonce.r*) } > CODE + .rodata1 : { *(.rodata1) } > CODE + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >CODE + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >CODE + + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x10000) + (. & (0x10000 - 1)); + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } >CODE + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } >CODE + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } >CODE + PROVIDE (__fini_array_end = .); + + .sdata2 : {PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } >CODE + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + /* avoid empty sdata2/sbss2 area -- __eabi would not set up r2 + * which may be important if run-time loading is used + */ + . += 1; + PROVIDE (__SBSS2_END__ = .); + } >CODE + .eh_frame : { *(.eh_frame) } >CODE + + /* NOTE: if the BSP uses page tables, the correctness of + * '_etext' (and __DATA_START__) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + _etext = .; + PROVIDE (etext = .); + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = ALIGN(0x40000) + (ALIGN(8) & (0x40000 - 1)); + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = ALIGN(0x1000); + .data ALIGN(0x1000) : + { + /* NOTE: if the BSP uses page tables, the correctness of + * '__DATA_START__' (and _etext) is CRUCIAL - otherwise, + * an invalid mapping may result!!! + */ + PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data .data.* .gnu.linkonce.d*) + KEEP (*(SORT(.rtemsrwset.*))) + SORT(CONSTRUCTORS) + } > CODE + .data1 : { *(.data1) } > CODE + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table*) } > CODE + PROVIDE (__EXCEPT_END__ = .); + .got1 : { *(.got1) } > CODE + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + get relocated with -mrelocatable. Also put in the .fixup pointers. + The current compiler no longer needs this, but keep it around for 2.7.2 */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > CODE + .dynamic : { *(.dynamic) } > CODE + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > CODE + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > CODE + + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > CODE + PROVIDE (_FIXUP_END_ = .); + PROVIDE (_GOT2_END_ = .); + PROVIDE (_GOT_START_ = .); + + .got : { *(.got) } > CODE + .got.plt : { *(.got.plt) } > CODE + + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > CODE + + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata*) *(.gnu.linkonce.s.*) } >CODE + _edata = .; + PROVIDE (edata = .); + .sbss : + { + PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss* .gnu.linkonce.sb.*) + *(.scommon) + /* avoid empty sdata/sbss area -- __eabi would not set up r13 + * which may be important if run-time loading is used + */ + . += 1; + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > CODE + .plt : { *(.plt) } > CODE + .bss : + { + PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(16); + PROVIDE (__bss_end = .); + } > CODE + . = ALIGN(16); + . += 0x1000; + __stack = .; + _end = . ; + __rtems_end = . ; + PROVIDE (end = .); + /DISCARD/ : + { + *(.comment) + } + + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/bsps/powerpc/shared/start/pgtbl_activate.c b/bsps/powerpc/shared/start/pgtbl_activate.c new file mode 100644 index 0000000000..2455f1e06d --- /dev/null +++ b/bsps/powerpc/shared/start/pgtbl_activate.c @@ -0,0 +1,77 @@ +#include <rtems.h> +#include <libcpu/pte121.h> +#include <libcpu/bat.h> + +/* Default activation of the page tables. This is a weak + * alias, so applications may easily override this + * default activation procedure. + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 4/2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +void __BSP_default_pgtbl_activate(Triv121PgTbl pt); +void +BSP_pgtbl_activate(Triv121PgTbl) + __attribute__ (( weak, alias("__BSP_default_pgtbl_activate") )); + +void +__BSP_default_pgtbl_activate(Triv121PgTbl pt) +{ + if (!pt) return; + + /* switch the text/ro sements to RO only after + * initializing the interrupts because the irq_mng + * installs some code... + * + * activate the page table; it is still masked by the + * DBAT0, however + */ + triv121PgTblActivate(pt); + + /* finally, switch off DBAT0 */ + setdbat(0,0,0,0,0); + /* At this point, DBAT0 is available for other use... */ +} diff --git a/bsps/powerpc/shared/start/pgtbl_setup.c b/bsps/powerpc/shared/start/pgtbl_setup.c new file mode 100644 index 0000000000..8a8407bd49 --- /dev/null +++ b/bsps/powerpc/shared/start/pgtbl_setup.c @@ -0,0 +1,135 @@ +#include <rtems.h> +#include <libcpu/mmu.h> +#include <rtems/bspIo.h> +#include <libcpu/pte121.h> + +/* Default setup of the page tables. This is a weak + * alias, so applications may easily override this + * default setup. + * + * NOTE: while it is possible to change the individual + * mappings, the page table itself MUST be + * allocated at the top of the physical memory! + * bspstart.c RELIES on this. + * Also, the 'setup' routine must reduce + * *pmemsize by the size of the page table. + */ +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 4/2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +Triv121PgTbl __BSP_default_pgtbl_setup(unsigned int *pmemsize); +Triv121PgTbl BSP_pgtbl_setup(unsigned int *) + __attribute__ (( weak, alias("__BSP_default_pgtbl_setup") )); + +/* get those from the linker script. + * NOTE THAT THE CORRECTNESS OF THE LINKER SCRIPT IS CRUCIAL + */ +extern unsigned long __DATA_START__[], _etext[]; + +Triv121PgTbl +__BSP_default_pgtbl_setup(unsigned int *pmemsize) +{ +Triv121PgTbl pt; +unsigned ldPtSize,tmp; + + /* Allocate a page table large enough to map + * the entire physical memory. We put the page + * table at the top of the physical memory. + */ + + /* get minimal size (log base 2) of PT for + * this board's memory + */ + ldPtSize = triv121PgTblLdMinSize(*pmemsize); + ldPtSize++; /* double this amount -- then why? */ + + /* allocate the page table at the top of the physical + * memory - THIS IS NOT AN OPTION - bspstart.c RELIES + * ON THIS LAYOUT! (the size, however may be changed) + */ + if ( (pt = triv121PgTblInit(*pmemsize - (1<<ldPtSize), ldPtSize)) ) { + /* map text and RO data read-only */ + tmp = triv121PgTblMap( + pt, + TRIV121_121_VSID, + 0, + (PAGE_ALIGN((unsigned long)_etext) - 0) >> PG_SHIFT, + 0, /* WIMG */ + TRIV121_PP_RO_PAGE); + if (TRIV121_MAP_SUCCESS != tmp) { + printk("Unable to map page index %i; reverting to BAT0\n", + tmp); + pt = 0; + } else { + /* map the rest (without the page table itself) RW */ + tmp = triv121PgTblMap( + pt, + TRIV121_121_VSID, + (unsigned long)__DATA_START__, + (*pmemsize - (1<<ldPtSize) - (unsigned long)__DATA_START__ )>> PG_SHIFT, + 0, /* WIMG */ + TRIV121_PP_RW_PAGE); + if (TRIV121_MAP_SUCCESS != tmp) { + printk("Unable to map page index %i; reverting to BAT0\n", + tmp); + pt = 0; + } + } + } else { + printk("WARNING: unable to allocate page table, keeping DBAT0\n"); + } + if (pt) { +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Setting up page table mappings; protecting text/read-only data from write access\n"); +#endif + /* SUCCESS; reduce available memory by size of the page table */ + *pmemsize -= (1<<ldPtSize); + } + return pt; +} diff --git a/bsps/powerpc/shared/start/ppc_idle.c b/bsps/powerpc/shared/start/ppc_idle.c new file mode 100644 index 0000000000..44ae87311c --- /dev/null +++ b/bsps/powerpc/shared/start/ppc_idle.c @@ -0,0 +1,106 @@ +/* + * ppc_idle.c + * + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2010, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ +#include <bsp.h> +#include <stdint.h> + +#ifdef BSP_IDLE_TASK_BODY + +/* Provide an idle-task body which switches the + * CPU into power-save mode when idle. Any exception + * (including an interrupt/external-exception) + * wakes it up. + * + * IIRC - this cannot be used on real hardware due + * to errata on many chips which is a real + * pity. However, when used under qemu it + * saves host-CPU cycles. + * While qemu-0.12.4 needed to be patched + * (would otherwise hang because an exception + * didn't clear MSR_POW) qemu-0.14.1 seems + * to work fine. + */ + +#include <rtems/powerpc/registers.h> +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +SPR_RW(HID0) + +void * +bsp_ppc_idle_task_body(uintptr_t ignored) +{ +uint32_t msr; + + switch ( current_ppc_cpu ) { + + case PPC_7400: + case PPC_7455: + case PPC_7457: + /* Must enable NAP mode in HID0 for MSR_POW to work */ + _write_HID0( _read_HID0() | HID0_NAP ); + break; + + default: + break; + } + + for ( ;; ) { + _CPU_MSR_GET(msr); + msr |= MSR_POW; + asm volatile( + "1: sync \n" + " mtmsr %0 \n" + " isync \n" + " b 1b \n" + ::"r"(msr) + ); + } + + return 0; +} + +#endif diff --git a/bsps/powerpc/shared/start/probeMemEnd.c b/bsps/powerpc/shared/start/probeMemEnd.c new file mode 100644 index 0000000000..73b85d4709 --- /dev/null +++ b/bsps/powerpc/shared/start/probeMemEnd.c @@ -0,0 +1,219 @@ +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2005, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +#include <bsp.h> +#include <libcpu/spr.h> +#include <libcpu/cpuIdent.h> +#include <rtems/bspIo.h> +#include <inttypes.h> + +/* Simple memory probing routine + * + * - call from MMU-disabled section to avoid having to + * set up mappings. + * NOTE: this implies WIMG = 0011 + * - call AFTER image is at its destination and PRIOR + * to setting up the heap or using any memory beyond + * __rtems_end, i.e., the probing algorithm may safely + * tamper with memory > __rtems_end. + * - MUST lock caches since we're gonna hit space with + * no memory attached. + * + * ASSUMPTIONS: + * o image occupies addresses between 0..__rtems_end + * o memory size is a multiple of 1<<LD_MEM_PROBE_STEP + * + * CAVEATS: + * o all caches must be disabled or locked (some + * boards really don't like it if you try to + * cache physical addresses with nothing attached) + * and this is highly CPU dependent :-(... + * + * - RETURNS size of memory detected in bytes or 0 on + * error. + */ + +/* declare as an array so the compiler doesn't generate + * a reloc to .sdata & friends + */ +extern uint32_t __rtems_end[]; + +#ifndef LD_MEM_PROBE_STEP +#define LD_MEM_PROBE_STEP (24) /* 16MB */ +#endif + +#define TAG 0xfeedcafe + +#define __DO_ALIGN(a, s) (((uint32_t)(a) + (s)-1) & ~((s)-1)) +#define __ALIGN(a) __DO_ALIGN(a, (1<<LD_MEM_PROBE_STEP)) + +#define SWITCH_MSR(msr) \ + do { \ + register uint32_t __rr; \ + asm volatile( \ + " mtsrr1 %0 \n" \ + " bl 1f \n" \ + "1: mflr %0 \n" \ + " addi %0, %0, 1f-1b \n"\ + " mtsrr0 %0 \n" \ + " sync \n" \ + " rfi \n" \ + "1: \n" \ + :"=b&"(__rr) \ + :"0"(msr) \ + :"lr","memory" \ + ); \ + } while (0) + +SPR_RW(L2CR) +SPR_RW(L3CR) +SPR_RO(PPC_PVR) +SPR_RW(HID0) + + +/* Shouldn't matter if the caches are enabled or not... */ + +/* FIXME: This should go into libcpu, really... */ +static int +CPU_lockUnlockCaches(register int doLock) +{ +register uint32_t v, x; + if ( _read_MSR() & MSR_VE ) { +#define DSSALL 0x7e00066c /* dssall opcode */ + __asm__ volatile(" .long %0"::"i"(DSSALL)); +#undef DSSALL + } + asm volatile("sync"); + switch ( _read_PPC_PVR()>>16 ) { + default: printk(__FILE__" CPU_lockUnlockCaches(): unknown CPU (PVR = 0x%08" PRIx32 ")\n",_read_PPC_PVR()); + return -1; + case PPC_750: printk("CPU_lockUnlockCaches(): Can't lock L2 on a mpc750, sorry :-(\n"); + return -2; /* cannot lock L2 :-( */ + case PPC_7455: + case PPC_7457: + v = _read_L3CR(); + x = 1<<(31-9); + v = doLock ? v | x : v & ~x; + _write_L3CR(v); + + v = _read_L2CR(); + x = 1<<(31-11); + v = doLock ? v | x : v & ~x; + _write_L2CR(v); + break; + + case PPC_7400: + v = _read_L2CR(); + x = 1<<(31-21); + v = doLock ? v | x : v & ~x; + _write_L2CR(v); + break; + case PPC_603: + case PPC_604: + case PPC_604e: + break; + } + + v = _read_HID0(); + x = 1<<(31-19); + v = doLock ? v | x : v & ~x; + _write_HID0(v); + asm volatile("sync":::"memory"); + return 0; +} + +uint32_t +probeMemoryEnd(void) +{ +register volatile uint32_t *probe; +register uint32_t scratch; +register uint32_t tag = TAG; +register uint32_t flags; + + probe = (volatile uint32_t *)__ALIGN(__rtems_end); + + /* Start with some checks. We avoid using any services + * such as 'printk' so we can run at a very early stage. + * Also, we *try* to avoid to really rely on the memory + * being unused by restoring the probed locations and + * keeping everything in registers. Hence we could + * even probe our own stack :-) + */ + + if ( CPU_lockUnlockCaches(1) ) + return 0; + + _CPU_MSR_GET(flags); + + SWITCH_MSR( flags & ~(MSR_EE|MSR_DR|MSR_IR) ); + + for ( ; (uint32_t)probe ; probe += (1<<LD_MEM_PROBE_STEP)/sizeof(*probe) ) { + + /* see if by chance our tag is already there */ + if ( tag == (scratch = *probe) ) { + /* try another tag */ + tag = ~tag; + } + *probe = tag; + + /* make sure it's written out */ + asm volatile ("sync":::"memory"); + + /* try to read back */ + if ( tag != *probe ) { + break; + } + /* restore */ + *probe = scratch; + /* make sure the icache is not contaminated */ + asm volatile ("sync; icbi 0, %0"::"r"(probe):"memory"); + } + + SWITCH_MSR(flags); + + CPU_lockUnlockCaches(0); + + return (uint32_t) probe; +} diff --git a/bsps/powerpc/shared/start/sbrk.c b/bsps/powerpc/shared/start/sbrk.c new file mode 100644 index 0000000000..f17a1511e4 --- /dev/null +++ b/bsps/powerpc/shared/start/sbrk.c @@ -0,0 +1,147 @@ +/* + * sbrk.c + * + * Authorship + * ---------- + * This software was created by + * Till Straumann <strauman@slac.stanford.edu>, 2002, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ + +/* + * Hack around the 32bit powerpc 32M problem: + * + * GCC by default uses relative branches which can not jump + * farther than 32M. Hence all program text is confined to + * a single 32M segment. + * This hack gives the RTEMS malloc region all memory below + * 32M at startup. Only when this region is exhausted will sbrk + * add more memory. Loading modules may fail at that point, hence + * the user is expected to load all modules at startup _prior_ + * to malloc()ing lots of memory... + * + * NOTE: it would probably be better to have a separate region + * for module code. + */ + +#include <errno.h> +#include <unistd.h> + +#include <bsp/bootcard.h> + +#define INVALID_REMAINING_START ((uintptr_t) -1) + +static uintptr_t remaining_start = INVALID_REMAINING_START; +static uintptr_t remaining_size = 0; + +/* App. may provide a value by defining the BSP_sbrk_policy + * variable. + * + * (-1) -> give all memory to the heap at initialization time + * > 0 -> value used as sbrk amount; initially give 32M + * 0 -> limit memory effectively to 32M. + * + */ +extern uintptr_t BSP_sbrk_policy[] __attribute__((weak)); + +#define LIMIT_32M 0x02000000 + +ptrdiff_t bsp_sbrk_init(Heap_Area *area, uintptr_t min_size) +{ + uintptr_t rval = 0; + uintptr_t policy; + uintptr_t remaining_end; + + remaining_start = (uintptr_t) area->begin; + remaining_size = area->size; + remaining_end = remaining_start + remaining_size; + + if (remaining_start < LIMIT_32M && + remaining_end > LIMIT_32M && + min_size <= LIMIT_32M - remaining_start) { + /* clip at LIMIT_32M */ + rval = remaining_end - LIMIT_32M; + area->size = LIMIT_32M - remaining_start; + remaining_start = LIMIT_32M; + remaining_size = rval; + } + + policy = (0 == BSP_sbrk_policy[0] ? (uintptr_t)(-1) : BSP_sbrk_policy[0]); + switch ( policy ) { + case (uintptr_t)(-1): + area->size += rval; + remaining_start = (uintptr_t) area->begin + area->size; + remaining_size = 0; + break; + + case 0: + remaining_size = 0; + break; + + default: + if ( rval > policy ) + rval = policy; + break; + } + + return (ptrdiff_t) (rval <= PTRDIFF_MAX ? rval : rval / 2); +} + +/* + * This is just so the sbrk test can force its magic. All normal applications + * should just use the default implementation in this file. + */ +void *sbrk(ptrdiff_t incr) __attribute__ (( weak, alias("bsp_sbrk") )); +static void *bsp_sbrk(ptrdiff_t incr) +{ + void *rval=(void*)-1; + + if ( remaining_start != INVALID_REMAINING_START && incr <= remaining_size) { + remaining_size-=incr; + rval = (void *) remaining_start; + remaining_start += incr; + } else { + errno = ENOMEM; + } + #ifdef DEBUG + printk("************* SBRK 0x%08x (ret 0x%08x) **********\n", incr, rval); + #endif + return rval; +} diff --git a/bsps/powerpc/shared/start/zerobss.c b/bsps/powerpc/shared/start/zerobss.c new file mode 100644 index 0000000000..b3ab1ad9d9 --- /dev/null +++ b/bsps/powerpc/shared/start/zerobss.c @@ -0,0 +1,42 @@ +/* + * zero the various bss areas. + */ + +/* + * COPYRIGHT (c) 1989-2014. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + */ + +#include <string.h> +#include <bsp.h> + +/* prevent these from being accessed in the short data areas */ +extern unsigned long __bss_start[], __SBSS_START__[], __SBSS_END__[]; +extern unsigned long __SBSS2_START__[], __SBSS2_END__[]; +extern unsigned long __bss_end[]; + +void zero_bss(void) +{ + memset( + __SBSS_START__, + 0, + ((unsigned) __SBSS_END__) - ((unsigned)__SBSS_START__) + ); + memset( + __SBSS2_START__, + 0, + ((unsigned) __SBSS2_END__) - ((unsigned)__SBSS2_START__) + ); + memset( + __bss_start, + 0, + ((unsigned) __bss_end) - ((unsigned)__bss_start) + ); +} diff --git a/bsps/powerpc/ss555/start/bsp_specs b/bsps/powerpc/ss555/start/bsp_specs new file mode 100644 index 0000000000..2625609327 --- /dev/null +++ b/bsps/powerpc/ss555/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/ss555/start/bspstart.c b/bsps/powerpc/ss555/start/bspstart.c new file mode 100644 index 0000000000..f47ca7d5be --- /dev/null +++ b/bsps/powerpc/ss555/start/bspstart.c @@ -0,0 +1,97 @@ +/* + * This routine does the bulk of the system initialization. + */ + +/* + * COPYRIGHT (c) 1989-2007. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * SS555 port sponsored by Defence Research and Development Canada - Suffield + * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca) + * + * Derived from c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c: + * + * Modifications for MBX860: + * Copyright (c) 1999, National Research Council of Canada + */ + +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <bsp/bootcard.h> +#include <rtems/powerpc/powerpc.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp/irq.h> +#include <bsp.h> + +SPR_RW(SPRG1) + +extern unsigned long intrStackPtr; + +/* + * Driver configuration parameters + */ +uint32_t bsp_clicks_per_usec; +uint32_t bsp_clock_speed; /* Serial clocks per second */ + +/* + * bsp_start() + * + * Board-specific initialization code. Called from the generic boot_card() + * function defined in rtems/c/src/lib/libbsp/shared/main.c. That function + * does some of the board independent initialization. It is called from the + * SS555 entry point _start() defined in + * rtems/c/src/lib/libbsp/powerpc/ss555/start/start.S + * + * _start() has set up a stack, has zeroed the .bss section, has set up the + * .data section from contents stored in ROM, has turned off interrupts, + * and placed the processor in the supervisor mode. boot_card() has left + * the processor in that state when bsp_start() was called. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: NONE + */ +void bsp_start(void) +{ + register unsigned char* intrStack; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later. + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* + * Initialize some SPRG registers related to irq handling + */ + intrStack = (((unsigned char*)&intrStackPtr) - PPC_MINIMUM_STACK_FRAME_SIZE); + _write_SPRG1((unsigned int)intrStack); + + /* + * Install our own set of exception vectors + */ + initialize_exceptions(); + + /* + * initialize the device driver parameters + */ + bsp_clicks_per_usec = BSP_CRYSTAL_HZ / 4 / 1000000; + bsp_clock_speed = BSP_CLOCK_HZ; /* for SCI baud rate generator */ + rtems_counter_initialize_converter(BSP_CRYSTAL_HZ / 4); + + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); +} diff --git a/bsps/powerpc/ss555/start/iss555.c b/bsps/powerpc/ss555/start/iss555.c new file mode 100644 index 0000000000..034ae74b1d --- /dev/null +++ b/bsps/powerpc/ss555/start/iss555.c @@ -0,0 +1,148 @@ +/* + * Intec SS555 initialization routines. + */ + +/* + * SS555 port sponsored by Defence Research and Development Canada - Suffield + * Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca) + * + * Derived from c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c: + * + * Copyright (c) 1999, National Research Council of Canada + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> + +SPR_RW(ICTRL); +SPR_RW(PPC_DEC); +SPR_RW(TBWU); +SPR_RW(TBWL); +SPR_RO(IMMR); +SPR_RW(MI_GRA); +SPR_RW(L2U_GRA); +SPR_RW(BBCMCR); + +extern char int_ram_top[]; /* top of internal ram */ + +/* + * Initialize SS555 + */ +void _InitSS555 (void) +{ + register uint32_t plprcr, msr; + + /* + * Initialize the System Protection Control Register (SYPCR). + * The SYPCR can only be written once after Reset. + */ + usiu.sypcr = + USIU_SYPCR_SWTC(WATCHDOG_TIMEOUT) /* set watchdog timeout */ + | USIU_SYPCR_BMT(0xFF) /* set bus monitor timeout */ + | USIU_SYPCR_BME /* enable bus monitor */ + | USIU_SYPCR_SWF /* watchdog halted in freeze */ +#if WATCHDOG_TIMEOUT != 0xFFFF + | USIU_SYPCR_SWE /* enable watchdog */ +#endif + | USIU_SYPCR_SWRI /* watchdog forces reset */ + | USIU_SYPCR_SWP; /* prescale watchdog by 2048 */ + + TICKLE_WATCHDOG(); /* restart watchdog timer */ + + /* + * Re-tune the PLL to the desired system clock frequency. + */ + usiu.plprck = USIU_UNLOCK_KEY; /* unlock PLPRCR */ + usiu.plprcr = + USIU_PLPRCR_TEXPS /* assert TEXP always */ + | USIU_PLPRCR_MF(BSP_CLOCK_HZ / BSP_CRYSTAL_HZ); + /* PLL multiplication factor */ + usiu.plprck = 0; /* lock PLPRCR */ + + while (((plprcr = usiu.plprcr) & USIU_PLPRCR_SPLS) == 0) + ; /* wait for PLL to re-lock */ + + /* + * Enable the timebase and decrementer, then initialize decrementer + * register to a large value to guarantee that a decrementer interrupt + * will not be generated before the kernel is fully initialized. + * Initialize the timebase register to zero. + */ + usiu.tbscrk = USIU_UNLOCK_KEY; + usiu.tbscr |= USIU_TBSCR_TBE; /* enable time base and decrementer */ + usiu.tbscrk = 0; + + usiu.tbk = USIU_UNLOCK_KEY; + _write_PPC_DEC(0x7FFFFFFF); + _write_TBWU(0x00000000 ); + _write_TBWL(0x00000000 ); + usiu.tbk = 0; + + /* + * Run the Inter-Module Bus at full speed. + */ + imb.uimb.umcr &= ~UIMB_UMCR_HSPEED; + + /* + * Initialize Memory Controller for External RAM + * + * Initialize the Base and Option Registers (BR0-BR7 and OR0-OR7). Note + * that for all chip selects, ORx should be programmed before BRx. + * + * If booting from internal flash ROM, configure the external RAM to + * extend the internal RAM. If booting from external RAM, leave it at + * zero but set it up appropriately. + */ + usiu.memc[0]._or = + USIU_MEMC_OR_512K /* bank size */ + | USIU_MEMC_OR_SCY(0) /* wait states in first beat of burst */ + | USIU_MEMC_OR_BSCY(0); /* wait states in subsequent beats */ + + usiu.memc[0]._br = + USIU_MEMC_BR_BA(_read_IMMR() & IMMR_FLEN + ? (uint32_t)int_ram_top : 0) /* base address */ + | USIU_MEMC_BR_PS32 /* 32-bit data bus */ + | USIU_MEMC_BR_TBDIP /* toggle bdip */ + | USIU_MEMC_BR_V; /* base register valid */ + + /* + * Initialize Memory Controller for External CPLD + * + * The SS555 board includes a CPLD to control on-board features and + * off-board devices. (Configuration taken from Intec's hwhook.c) + */ + usiu.memc[3]._or = + USIU_MEMC_OR_16M /* bank size */ + | USIU_MEMC_OR_CSNT /* negate CS/WE early */ + | USIU_MEMC_OR_ACS_HALF /* assert CS half cycle after address */ + | USIU_MEMC_OR_SCY(15) /* wait states in first beat of burst */ + | USIU_MEMC_OR_TRLX; /* relaxed timing */ + + usiu.memc[3]._br = + USIU_MEMC_BR_BA(&cpld) /* base address */ + | USIU_MEMC_BR_PS16 /* 16-bit data bus */ + | USIU_MEMC_BR_BI /* inhibit bursting */ + | USIU_MEMC_BR_V; /* base register valid */ + + /* + * Disable show cycles and serialization so that burst accesses will work + * properly. A different value, such as 0x0, may be more appropriate for + * debugging, but can be set with the debugger, if needed. + */ + _write_ICTRL(0x00000007); + + /* + * Set up Burst Buffer Controller (BBC) + */ + _write_BBCMCR( + BBCMCR_ETRE /* enable exception relocation */ + | BBCMCR_BE); /* enable burst accesses */ + _isync; + + _CPU_MSR_GET(msr); + msr |= MSR_IP; /* set prefix for exception relocation */ + _CPU_MSR_SET(msr); +} diff --git a/bsps/powerpc/ss555/start/linkcmds b/bsps/powerpc/ss555/start/linkcmds new file mode 100644 index 0000000000..8282d6c605 --- /dev/null +++ b/bsps/powerpc/ss555/start/linkcmds @@ -0,0 +1,328 @@ +/* + * Linker command file for Intec SS555 board + * + * When debugging, we assume that the internal flash ROM will be replaced by + * the external RAM on the SS555 board. All sections are stacked starting + * at address zero. Nothing is placed in the internal RAM, since it's not + * contiguous with the external SRAM when the external RAM is placed at + * zero. + * + * For final production, we assume that the .text section will be burned + * into flash ROM starting at address zero. The .data, .bss, heap, and + * workspace will reside in RAM, starting at the beginning of the internal + * RAM. The system startup code will configure the external RAM to begin + * where the internal RAM ends, so as to make one large RAM block. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) +ENTRY(start) +EXTERN(_vectors) + +int_ram_org = 0x003F9800; /* base of internal RAM */ +int_ram_top = 0x00400000; /* top of internal RAM */ +ext_ram_size = 0x00080000; /* size of external RAM */ + +RamBase = DEFINED(_RamBase) ? RamBase : 0x003F9800; +RamSize = DEFINED(_RamSize) ? RamSize : 0x00486800; +HeapSize = DEFINED(_HeapSize) ? HeapSize : 0x0; + +SECTIONS +{ + .vectors 0x0: + { + /* + * For the MPC555, we use the compressed vector table format which puts + * all of the exception vectors before 0x100. + */ + *(.vectors) + } + + .text 0x100: + { + /* Read-only sections, merged into text segment: */ + + text.start = .; + + /* Entry point is the .entry section */ + *(.entry) + *(.entry2) + + /* Actual code */ + *(.text*) + + /* C++ constructors/destructors */ + *(.gnu.linkonce.t*) + + /* Initialization and finalization code. + * + * Various files can provide initialization and finalization functions. + * The bodies of these functions are in .init and .fini sections. We + * accumulate the bodies here, and prepend function prologues from + * ecrti.o and function epilogues from ecrtn.o. ecrti.o must be linked + * first; ecrtn.o must be linked last. Because these are wildcards, it + * doesn't matter if the user does not actually link against ecrti.o and + * ecrtn.o; the linker won't look for a file to match a wildcard. The + * wildcard also means that it doesn't matter which directory ecrti.o + * and ecrtn.o are in. + */ + PROVIDE (_init = .); + *ecrti.o(.init) + *(.init) + *ecrtn.o(.init) + + PROVIDE (_fini = .); + *ecrti.o(.fini) + *(.fini) + *ecrtn.o(.init) + + /* + * C++ constructors and destructors for static objects. + * PowerPC EABI does not use crtstuff yet, so we build "old-style" + * constructor and destructor lists that begin with the list length + * end terminate with a NULL entry. + */ + PROVIDE (__CTOR_LIST__ = .); + /* LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.ctors) + *(.ctors) + *crtend.o(.ctors) + LONG(0) + PROVIDE (__CTOR_END__ = .); + + PROVIDE (__DTOR_LIST__ = .); + /* LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2) */ + *crtbegin.o(.dtors) + *(.dtors) + *crtend.o(.dtors) + LONG(0) + PROVIDE (__DTOR_END__ = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* Exception frame info */ + *(.eh_frame) + + /* Miscellaneous read-only data */ + _rodata_start = . ; + *(.gnu.linkonce.r*) + *(.lit) + *(.shdata) + *(.rodata*) + *(.rodata1) + KEEP (*(SORT(.rtemsroset.*))) + *(.descriptors) + *(rom_ver) + _erodata = .; + + /* Various possible names for the end of the .text section */ + etext = ALIGN(0x10); + _etext = .; + _endtext = .; + text.end = .; + PROVIDE (etext = .); + PROVIDE (__etext = .); + } + text.size = text.end - text.start; + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + + /* + * .data section contents, copied to RAM at system startup. + */ + . = ALIGN(0x20); + data.contents.start = .; + } + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + /* + * If debugging, stack the read/write sections directly after the text + * section. Otherwise, stack the read/write sections starting at base of + * internal RAM. + */ + . = DEFINED(RTEMS_DEBUG) ? . : int_ram_org; + + .data : AT (data.contents.start) + { + data.start = .; + + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.data1) + + PROVIDE (__SDATA_START__ = .); + *(.sdata .sdata.* .gnu.linkonce.s.*) + PROVIDE (__SDATA_END__ = .); + + PROVIDE (__EXCEPT_START__ = .); + *(.gcc_except_table*) + PROVIDE (__EXCEPT_END__ = .); + + PROVIDE(__GOT_START__ = .); + *(.got.plt) + *(.got) + PROVIDE(__GOT_END__ = .); + + *(.got1) + + PROVIDE (__GOT2_START__ = .); + PROVIDE (_GOT2_START_ = .); + *(.got2) + PROVIDE (__GOT2_END__ = .); + PROVIDE (_GOT2_END_ = .); + + PROVIDE (__FIXUP_START__ = .); + PROVIDE (_FIXUP_START_ = .); + *(.fixup) + PROVIDE (_FIXUP_END_ = .); + PROVIDE (__FIXUP_END__ = .); + + /* We want the small data sections together, so single-instruction + * offsets can access them all. + */ + PROVIDE (__SDATA2_START__ = .); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + PROVIDE (__SDATA2_END__ = .); + + data.end = .; + } + data.size = data.end - data.start; + + bss.start = .; + .sbss : + { + PROVIDE (__sbss_start = .); PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss* .gnu.linkonce.b*) + *(COMMON) + . = ALIGN(4); + } + bss.end = .; + bss.size = bss.end - bss.start; + + PROVIDE(_end = bss.end); + + /* + * Initialization stack + */ + InitStack_start = ALIGN(0x10); + . += 0x1000; + initStack = .; + PROVIDE(initStackPtr = initStack); + + /* + * Interrupt stack + */ + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + + /* + * Work Area + * + * The Work Area is configured at run-time to use all available memory. It + * begins just after the end of the Workspace and continues to the end of + * the external RAM. + */ + . = DEFINED(RTEMS_DEBUG) ? 0 + ext_ram_size : int_ram_top + ext_ram_size; + WorkAreaBase = .; + + + /* + * Internal I/O devices + */ + .usiu 0x002FC000: /* unified system interface unit */ + { + usiu = .; + } + + .imb 0x00300000: /* inter-module bus and devices */ + { + imb = .; + } + + .sram 0x00380000: /* internal SRAM control registers */ + { + sram = .; + } + + /* + * SS555 external devices managed by on-board CPLD + */ + .cpld 0xFF000000: /* SS555 external CPLD devices */ + { + cpld = .; + } + + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/bsps/powerpc/ss555/start/tm27supp.c b/bsps/powerpc/ss555/start/tm27supp.c new file mode 100644 index 0000000000..4c1660ff70 --- /dev/null +++ b/bsps/powerpc/ss555/start/tm27supp.c @@ -0,0 +1,14 @@ +/* + * Support routines for TM27 + */ + +#include <bsp.h> + +rtems_irq_connect_data tm27IrqData = { + CPU_USIU_EXT_IRQ_7, + (rtems_irq_hdl)0, + NULL, + NULL, + NULL +}; + diff --git a/bsps/powerpc/t32mppc/start/bsp_specs b/bsps/powerpc/t32mppc/start/bsp_specs new file mode 100644 index 0000000000..f8bbffbdf6 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bsp_specs @@ -0,0 +1,11 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} + diff --git a/bsps/powerpc/t32mppc/start/bspreset.c b/bsps/powerpc/t32mppc/start/bspreset.c new file mode 100644 index 0000000000..9472192fab --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bspreset.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdbool.h> + +#include <bsp/bootcard.h> + +void bsp_reset(void) +{ + while (true) { + /* Do nothing */ + } +} diff --git a/bsps/powerpc/t32mppc/start/bspstart.c b/bsps/powerpc/t32mppc/start/bspstart.c new file mode 100644 index 0000000000..5fc36b4019 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/bspstart.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2012, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/config.h> +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> +#include <bsp/linker-symbols.h> + +LINKER_SYMBOL(bsp_exc_vector_base); + +/* + * Configuration parameter for clock driver. The Trace32 PowerPC simulator has + * an odd decrementer frequency. The time base frequency is one tick per + * instruction. The decrementer frequency is one tick per ten instructions. + * The clock driver assumes that the time base and decrementer frequencies are + * equal. For now we simulate processor that issues 10000000 instructions per + * second. + */ +uint32_t bsp_time_base_frequency = 10000000; + +#define MTIVPR(base) \ + __asm__ volatile ("mtivpr %0" : : "r" (base)) + +#define VECTOR_TABLE_ENTRY_SIZE 16 + +#define MTIVOR(vec, offset) \ + do { \ + __asm__ volatile ("mtspr " RTEMS_XSTRING(vec) ", %0" : : "r" (offset)); \ + offset += VECTOR_TABLE_ENTRY_SIZE; \ + } while (0) + +static void t32mppc_initialize_exceptions(void *interrupt_stack_begin) +{ + uintptr_t addr; + + ppc_exc_initialize_interrupt_stack( + (uintptr_t) interrupt_stack_begin, + rtems_configuration_get_interrupt_stack_size() + ); + + addr = (uintptr_t) bsp_exc_vector_base; + MTIVPR(addr); + MTIVOR(BOOKE_IVOR0, addr); + MTIVOR(BOOKE_IVOR1, addr); + MTIVOR(BOOKE_IVOR2, addr); + MTIVOR(BOOKE_IVOR3, addr); + MTIVOR(BOOKE_IVOR4, addr); + MTIVOR(BOOKE_IVOR5, addr); + MTIVOR(BOOKE_IVOR6, addr); + MTIVOR(BOOKE_IVOR7, addr); + MTIVOR(BOOKE_IVOR8, addr); + MTIVOR(BOOKE_IVOR9, addr); + MTIVOR(BOOKE_IVOR10, addr); + MTIVOR(BOOKE_IVOR11, addr); + MTIVOR(BOOKE_IVOR12, addr); + MTIVOR(BOOKE_IVOR13, addr); + MTIVOR(BOOKE_IVOR14, addr); + MTIVOR(BOOKE_IVOR15, addr); + MTIVOR(BOOKE_IVOR32, addr); + MTIVOR(BOOKE_IVOR33, addr); + MTIVOR(BOOKE_IVOR34, addr); + MTIVOR(BOOKE_IVOR35, addr); +} + +void bsp_start(void) +{ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + rtems_counter_initialize_converter(bsp_time_base_frequency); + + t32mppc_initialize_exceptions(bsp_section_work_begin); + bsp_interrupt_initialize(); +} diff --git a/bsps/powerpc/t32mppc/start/linkcmds.t32mppc b/bsps/powerpc/t32mppc/start/linkcmds.t32mppc new file mode 100644 index 0000000000..02367f57d0 --- /dev/null +++ b/bsps/powerpc/t32mppc/start/linkcmds.t32mppc @@ -0,0 +1,27 @@ +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = 0x0, LENGTH = 128M + EMPTY : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", RAM); +REGION_ALIAS ("REGION_NOCACHE_LOAD", RAM); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/tqm8xx/start/bsp_specs b/bsps/powerpc/tqm8xx/start/bsp_specs new file mode 100644 index 0000000000..b5cd6764ce --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn%O%s} diff --git a/bsps/powerpc/tqm8xx/start/bspgetworkarea.c b/bsps/powerpc/tqm8xx/start/bspgetworkarea.c new file mode 100644 index 0000000000..4a0a4db534 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bspgetworkarea.c @@ -0,0 +1,34 @@ +/** + * @file + * + * @ingroup tqm8xx + * + * @brief Source for BSP Get Work Area Memory + */ + +/* + * Copyright (c) 2008, 2018 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +void bsp_work_area_initialize(void) +{ + char *ram_end = (char *) (TQM_BD_INFO.sdram_size - (uint32_t)TopRamReserved); + void *area_start = bsp_section_work_begin; + uintptr_t area_size = (uintptr_t) ram_end - (uintptr_t) area_start; + + bsp_work_area_initialize_default( area_start, area_size ); +} diff --git a/bsps/powerpc/tqm8xx/start/bspstart.c b/bsps/powerpc/tqm8xx/start/bspstart.c new file mode 100644 index 0000000000..df0581ce77 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/bspstart.c @@ -0,0 +1,156 @@ +/** + * @file + * + * @ingroup tqm8xx + * + * @brief Source for BSP startup code. + */ + +/* + * Copyright (c) 2008 + * Embedded Brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * rtems@embedded-brains.de + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <stdlib.h> + +#include <rtems.h> +#include <rtems/counter.h> + +#include <libcpu/powerpc-utility.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq-generic.h> + +#ifdef BSP_HAS_TQMMON +/* + * FIXME: TQ Monitor structure + */ +#endif /* BSP_HAS_TQMMON */ + +/* Configuration parameters for console driver, ... */ +uint32_t BSP_bus_frequency; + +/* Configuration parameter for clock driver */ +uint32_t bsp_time_base_frequency; + +/* Legacy */ +uint32_t bsp_clicks_per_usec; /* for PIT driver: OSCCLK */ + +static const char *bsp_tqm_get_cib_string( const char *cib_id) +{ + char srch_pattern[10] = ""; + char *fnd_str; + /* + * create search pattern + */ + strcat(srch_pattern,"-"); + strncat(srch_pattern, + cib_id, + sizeof(srch_pattern)-1-strlen(srch_pattern)); + strncat(srch_pattern, + " ", + sizeof(srch_pattern)-1-strlen(srch_pattern)); + /* + * search for pattern in info block (CIB) + */ + fnd_str = strstr((const char *)TQM_CONF_INFO_BLOCK_ADDR,srch_pattern); + + if (fnd_str == NULL) { + return NULL; + } + else { + /* + * found? then advance behind search pattern + */ + return fnd_str + strlen(srch_pattern); + } +} + +static rtems_status_code bsp_tqm_get_cib_uint32( const char *cib_id, + uint32_t *result) +{ + const char *item_ptr; + char *end_ptr; + item_ptr = bsp_tqm_get_cib_string(cib_id); + if (item_ptr == NULL) { + return RTEMS_INVALID_ID; + } + /* + * convert string to uint32 + */ + *result = strtoul(item_ptr,&end_ptr,10); + return RTEMS_SUCCESSFUL; +} + +void bsp_start( void) +{ + + uintptr_t interrupt_stack_start = (uintptr_t) bsp_interrupt_stack_start; + uintptr_t interrupt_stack_size = (uintptr_t) bsp_interrupt_stack_end + - interrupt_stack_start; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used + * later... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + /* Basic CPU initialization */ + cpu_init(); + + /* + * Enable instruction and data caches. Do not force writethrough mode. + */ + +#if BSP_INSTRUCTION_CACHE_ENABLED + rtems_cache_enable_instruction(); +#endif + +#if BSP_DATA_CACHE_ENABLED + rtems_cache_enable_data(); +#endif + + /* + * This is evaluated during runtime, so it should be ok to set it + * before we initialize the drivers. + */ + + /* Initialize some device driver parameters */ + /* + * get the (internal) bus frequency + * NOTE: the external bus may be clocked at a lower speed + * but this does not concern the internal units like PIT, + * DEC, baudrate generator etc) + */ + if (RTEMS_SUCCESSFUL != + bsp_tqm_get_cib_uint32("cu", + &BSP_bus_frequency)) { + rtems_panic("Cannot determine BUS frequency\n"); + } + + bsp_time_base_frequency = BSP_bus_frequency / 16; + bsp_clicks_per_usec = bsp_time_base_frequency / 1000000; + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* Initialize exception handler */ + ppc_exc_initialize(interrupt_stack_start, interrupt_stack_size); + + /* Initalize interrupt support */ + bsp_interrupt_initialize(); + +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif +} diff --git a/bsps/powerpc/tqm8xx/start/cpuinit.c b/bsps/powerpc/tqm8xx/start/cpuinit.c new file mode 100644 index 0000000000..5d34e07cfb --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/cpuinit.c @@ -0,0 +1,133 @@ +/* + * cpuinit.c + * + * TQM8xx initialization routines. + * derived from MBX8xx BSP + * adapted to TQM8xx by Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> + * + * Copyright (c) 1999, National Research Council of Canada + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/tqm.h> + + +/* + * Initialize TQM8xx + */ +void _InitTQM8xx (void) +{ + register uint32_t r1; + + /* + * Initialize the Instruction Support Control Register (ICTRL) to a + * an appropriate value for normal operation. A different value, + * such as 0x0, may be more appropriate for debugging. + */ + r1 = 0x00000007; + _mtspr( M8xx_ICTRL, r1 ); + + /* + * Disable and invalidate the instruction and data caches. + */ + r1 = M8xx_CACHE_CMD_DISABLE; + _mtspr( M8xx_IC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_UNLOCKALL; + _mtspr( M8xx_IC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */ + _mtspr( M8xx_IC_CST, r1 ); + _isync; + + r1 = M8xx_CACHE_CMD_DISABLE; + _mtspr( M8xx_DC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_UNLOCKALL; + _mtspr( M8xx_DC_CST, r1 ); + _isync; + r1 = M8xx_CACHE_CMD_INVALIDATE; /* invalidate all */ + _mtspr( M8xx_DC_CST, r1 ); + _isync; + + /* + * Initialize the SIU Module Configuration Register (SIUMCR) + * m8xx.siumcr = 0x00602900, the default value. + */ + m8xx.siumcr = M8xx_SIUMCR_EARP0 | M8xx_SIUMCR_DBGC3 | M8xx_SIUMCR_DBPC0 | + M8xx_SIUMCR_DPC | M8xx_SIUMCR_MLRC2 | M8xx_SIUMCR_SEME; + + /* + * Initialize the System Protection Control Register (SYPCR). + * The SYPCR can only be written once after Reset. + * - Enable bus monitor + * - Disable software watchdog timer + * m8xx.sypcr = 0xFFFFFF88, the default MBX and firmware value. + */ + m8xx.sypcr = M8xx_SYPCR_SWTC(0xFFFF) | M8xx_SYPCR_BMT(0xFF) | + M8xx_SYPCR_BME | M8xx_SYPCR_SWF; + + /* Initialize the SIU Interrupt Edge Level Mask Register (SIEL) */ + m8xx.siel = 0xAAAA0000; /* Default MBX and firmware value. */ + + /* Initialize the Transfer Error Status Register (TESR) */ + m8xx.tesr = 0xFFFFFFFF; /* Default firmware value. */ + + /* Initialize the SDMA Configuration Register (SDCR) */ + m8xx.sdcr = 0x00000001; /* Default firmware value. */ + + /* + * Initialize the Timebase Status and Control Register (TBSCR) + * m8xx.tbscr = 0x00C3, default MBX and firmware value. + */ + m8xx.tbscrk = M8xx_UNLOCK_KEY; /* unlock TBSCR */ + m8xx.tbscr = M8xx_TBSCR_REFA | M8xx_TBSCR_REFB | + M8xx_TBSCR_TBF | M8xx_TBSCR_TBE; + + /* Initialize the Real-Time Clock Status and Control Register (RTCSC) */ + m8xx.rtcsk = M8xx_UNLOCK_KEY; /* unlock RTCSC */ + m8xx.rtcsc = 0x00C3; /* Default MBX and firmware value. */ + + /* Unlock other Real-Time Clock registers */ + m8xx.rtck = M8xx_UNLOCK_KEY; /* unlock RTC */ + m8xx.rtseck = M8xx_UNLOCK_KEY; /* unlock RTSEC */ + m8xx.rtcalk = M8xx_UNLOCK_KEY; /* unlock RTCAL */ + + /* Initialize the Periodic Interrupt Status and Control Register (PISCR) */ + m8xx.piscrk = M8xx_UNLOCK_KEY; /* unlock PISCR */ + m8xx.piscr = 0x0083; /* Default MBX and firmware value. */ + + /* Initialize the System Clock and Reset Control Register (SCCR) + * Set the clock sources and division factors: + * Timebase Source is GCLK2 / 16 + */ + m8xx.sccrk = M8xx_UNLOCK_KEY; /* unlock SCCR */ + m8xx.sccr |= 0x02000000; + + /* Unlock the timebase and decrementer registers. */ + m8xx.tbk = M8xx_UNLOCK_KEY; + /* + * Initialize decrementer register to a large value to + * guarantee that a decrementer interrupt will not be + * generated before the kernel is fully initialized. + */ + r1 = 0x7FFFFFFF; + _mtspr( M8xx_DEC, r1 ); + + /* Initialize the timebase register (TB is 64 bits) */ + r1 = 0x00000000; + _mtspr( M8xx_TBU_WR, r1 ); + _mtspr( M8xx_TBL_WR, r1 ); +} +/* + * further initialization (called from bsp_start) + */ +void cpu_init(void) +{ + /* mmu initialization */ + mmu_init(); +} diff --git a/bsps/powerpc/tqm8xx/start/linkcmds b/bsps/powerpc/tqm8xx/start/linkcmds new file mode 100644 index 0000000000..7171d0230a --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/linkcmds @@ -0,0 +1,43 @@ +/** + * @file + * + * TQM8xx + */ + +TopRamReserved = DEFINED(TopRamReserved) ? TopRamReserved : 0; + +MEMORY { + EMPTY : ORIGIN = 0, LENGTH = 0 + RAM : ORIGIN = 0x10000, LENGTH = 128M - 64k + immr : org = 0xfa200000, l = 16K + ROM : ORIGIN = 0x40000000, LENGTH = 8M +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + dpram : { + m8xx = .; + _m8xx = .; + /* . += (16 * 1024); this makes the mbx loader crash */ + } >immr +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/tqm8xx/start/mmutlbtab.c b/bsps/powerpc/tqm8xx/start/mmutlbtab.c new file mode 100644 index 0000000000..8b1ad90036 --- /dev/null +++ b/bsps/powerpc/tqm8xx/start/mmutlbtab.c @@ -0,0 +1,103 @@ +/*===============================================================*\ +| Project: RTEMS TQM8xx BSP | ++-----------------------------------------------------------------+ +| This file has been adapted to MPC8xx by | +| Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | +| | +| See the other copyright notice below for the original parts. | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the console driver | +\*===============================================================*/ +/* derived from: */ +/* + * mmutlbtab.c + * + * Copyright (c) 1999, National Research Council of Canada + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <mpc8xx/mmu.h> +/* + * This MMU_TLB_table is used to statically initialize the Table Lookaside + * Buffers in the MMU of the TQM8xx board. + * + * We initialize the entries in both the instruction and data TLBs + * with the same values - a few bits relevant to the data TLB are unused + * in the instruction TLB. + * + * An Effective Page Number (EPN), Tablewalk Control Register (TWC) and + * Real Page Number (RPN) value are supplied in the table for each TLB entry. + * + * The instruction and data TLBs each can hold 32 entries, so _TLB_Table must + * not have more than 32 lines in it! + * + * We set up the virtual memory map so that virtual address of a + * location is equal to its real address. + */ +MMU_TLB_table_t MMU_TLB_table[] = { + /* + * DRAM: Start address 0x00000000, 128M, + * ASID=0x0, APG=0x0, not guarded memory, copyback data cache policy, + * R/W,X for all, no ASID comparison, not cache-inhibited. + * EPN TWC RPN + */ + { 0x00000200, 0x0D, 0x000009FD }, /* DRAM - PS=8M */ + { 0x00800200, 0x0D, 0x008009FD }, /* DRAM - PS=8M */ + { 0x01000200, 0x0D, 0x010009FD }, /* DRAM - PS=8M */ + { 0x01800200, 0x0D, 0x018009FD }, /* DRAM - PS=8M */ + { 0x02000200, 0x0D, 0x020009FD }, /* DRAM - PS=8M */ + { 0x02800200, 0x0D, 0x028009FD }, /* DRAM - PS=8M */ + { 0x03000200, 0x0D, 0x030009FD }, /* DRAM - PS=8M */ + { 0x03800200, 0x0D, 0x038009FD }, /* DRAM - PS=8M */ + { 0x04000200, 0x0D, 0x040009FD }, /* DRAM - PS=8M */ + { 0x04800200, 0x0D, 0x048009FD }, /* DRAM - PS=8M */ + { 0x05000200, 0x0D, 0x050009FD }, /* DRAM - PS=8M */ + { 0x05800200, 0x0D, 0x058009FD }, /* DRAM - PS=8M */ + { 0x06000200, 0x0D, 0x060009FD }, /* DRAM - PS=8M */ + { 0x06800200, 0x0D, 0x068009FD }, /* DRAM - PS=8M */ + { 0x07000200, 0x0D, 0x070009FD }, /* DRAM - PS=8M */ + { 0x07800200, 0x0D, 0x078009FD }, /* DRAM - PS=8M */ + /* + * + * (IMMR-SPRs) Dual Port RAM: Start address 0xFA200000, 16K, + * ASID=0x0, APG=0x0, guarded memory, write-through data cache policy, + * R/W,X for all, no ASID comparison, cache-inhibited. + * + * Note: We use the value in MBXA/PG2, which is also the value that + * EPPC-Bug programmed into our boards. The alternative is the value + * in MBXA/PG1: 0xFFA00000. This value might well depend on the revision + * of the firmware. + * EPN TWC RPN + */ + { 0xFA200200, 0x13, 0xFA2009FF }, /* IMMR - PS=16K */ + /* + * + * Flash: Start address 0x40000000, 8M, + * ASID=0x0, APG=0x0, not guarded memory, + * R/O,X for all, no ASID comparison, not cache-inhibited. + * EPN TWC RPN + */ + { 0x40000200, 0x0D, 0x40000CFD } /* Flash - PS=8M */ +}; + +/* + * MMU_N_TLB_Table_Entries is defined here because the size of the + * MMU_TLB_table is only known in this file. + */ +int MMU_N_TLB_Table_Entries = ( sizeof(MMU_TLB_table) / sizeof(MMU_TLB_table[0]) ); diff --git a/bsps/powerpc/virtex/start/bsp_specs b/bsps/powerpc/virtex/start/bsp_specs new file mode 100644 index 0000000000..6cb546f392 --- /dev/null +++ b/bsps/powerpc/virtex/start/bsp_specs @@ -0,0 +1,9 @@ +%rename endfile old_endfile +%rename startfile old_startfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex/start/bspstart.c b/bsps/powerpc/virtex/start/bspstart.c new file mode 100644 index 0000000000..5b4a4a135f --- /dev/null +++ b/bsps/powerpc/virtex/start/bspstart.c @@ -0,0 +1,105 @@ +/* bsp_start() + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Thomas Doerfler <td@imd.m.isar.de> + * 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: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * 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. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + */ + +#include <rtems/counter.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/irq-generic.h> +#include <bsp/bootcard.h> +#include <bsp/linker-symbols.h> + +#include <libcpu/powerpc-utility.h> + +#include RTEMS_XPARAMETERS_H + +/* Symbols defined in linker command file */ +LINKER_SYMBOL(virtex_exc_vector_base); + +/* + * Driver configuration parameters + */ +uint32_t bsp_time_base_frequency = XPAR_CPU_PPC405_CORE_CLOCK_FREQ_HZ; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function store the result in global variables + * so that it can be used latter... + */ + get_ppc_cpu_type(); + get_ppc_cpu_revision(); + + rtems_counter_initialize_converter(bsp_time_base_frequency); + + /* + * Initialize default raw exception handlers. + */ + ppc_exc_initialize_with_vector_base( + (uintptr_t) bsp_section_work_begin, + rtems_configuration_get_interrupt_stack_size(), + virtex_exc_vector_base + ); + __asm__ volatile ("mtevpr %0" : : "r" (virtex_exc_vector_base)); + + bsp_interrupt_initialize(); +} diff --git a/bsps/powerpc/virtex/start/linkcmds.in b/bsps/powerpc/virtex/start/linkcmds.in new file mode 100644 index 0000000000..13f9217e9d --- /dev/null +++ b/bsps/powerpc/virtex/start/linkcmds.in @@ -0,0 +1,35 @@ +EXTERN (__vectors) + +MEMORY { + RAM : ORIGIN = @VIRTEX_RAM_ORIGIN@, LENGTH = @VIRTEX_RAM_LENGTH@ + FAST_RAM : ORIGIN = @VIRTEX_FAST_RAM_ORIGIN@, LENGTH = @VIRTEX_FAST_RAM_LENGTH@ + RESET : ORIGIN = @VIRTEX_RESET_ORIGIN@, LENGTH = @VIRTEX_RESET_LENGTH@ + EMPTY : ORIGIN = 0x0, LENGTH = 0x0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", FAST_RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", FAST_RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); +REGION_ALIAS ("REGION_NOCACHE", EMPTY); +REGION_ALIAS ("REGION_NOCACHE_LOAD", EMPTY); +REGION_ALIAS ("REGION_NVRAM", EMPTY); + +SECTIONS { + .virtex_reset : { + KEEP (*(.virtex_reset)) + } > RESET AT > RESET +} + +INCLUDE linkcmds.base diff --git a/bsps/powerpc/virtex4/start/bsp_specs b/bsps/powerpc/virtex4/start/bsp_specs new file mode 100644 index 0000000000..ccbea2690c --- /dev/null +++ b/bsps/powerpc/virtex4/start/bsp_specs @@ -0,0 +1,10 @@ +%rename startfile old_startfile +%rename endfile old_endfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex4/start/bspclean.c b/bsps/powerpc/virtex4/start/bspclean.c new file mode 100644 index 0000000000..bd5829e0b2 --- /dev/null +++ b/bsps/powerpc/virtex4/start/bspclean.c @@ -0,0 +1,54 @@ +/* + * This routine normally is part of start.s and usually returns + * control to a monitor. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspclean.c: + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + if ( source == RTEMS_FATAL_SOURCE_EXIT ) { + app_bsp_cleanup(); + } + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/bsps/powerpc/virtex4/start/bspstart.c b/bsps/powerpc/virtex4/start/bspstart.c new file mode 100644 index 0000000000..d5c255be6d --- /dev/null +++ b/bsps/powerpc/virtex4/start/bspstart.c @@ -0,0 +1,219 @@ +/* + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * 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: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * 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. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * Modifications for Virtex4 by Richard Claus <claus@slac.stanford.edu> + */ +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sysinit.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> + +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> + +#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1)) + +#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a) + +#define CPU_DOWN_ALIGN(x) DO_DOWN_ALIGN(x, CPU_ALIGNMENT) +#define CPU_UP_ALIGN(x) DO_UP_ALIGN(x, CPU_ALIGNMENT) + + +/* Defined in linkcmds linker script */ +LINKER_SYMBOL(RamBase); +LINKER_SYMBOL(RamSize); +LINKER_SYMBOL(__bsp_ram_start); +LINKER_SYMBOL(__bsp_ram_end); +LINKER_SYMBOL(__rtems_end); +LINKER_SYMBOL(_stack); +LINKER_SYMBOL(StackSize); +LINKER_SYMBOL(__stack_base); +LINKER_SYMBOL(WorkAreaBase); +LINKER_SYMBOL(MsgAreaBase); +LINKER_SYMBOL(MsgAreaSize); +LINKER_SYMBOL(__phy_ram_end); +LINKER_SYMBOL(bsp_exc_vector_base); + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_noopfun") )); + +void app_bsp_predriver_hook(void) +__attribute__(( weak, alias("_noopfun") )); + + +static char* bspMsgBuffer = (char*)MsgAreaBase; + +static void __bsp_outchar_to_memory(char c) +{ + static char* msgBuffer = (char*)MsgAreaBase; + *msgBuffer++ = c; + if (msgBuffer >= &bspMsgBuffer[(int)MsgAreaSize]) msgBuffer = bspMsgBuffer; + *msgBuffer = 0x00; /* Overwrite next location to show EOM */ +} + + +void BSP_ask_for_reset(void) +{ + printk("\nSystem stopped, issue RESET"); + + for(;;); +} + + +/*===================================================================*/ + +/* + * BSP start routine. Called by boot_card(). + * + * This routine does the bulk of the system initialization. + */ +void bsp_start(void) +{ + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + + /* Set the character output function; The application may override this */ + BSP_output_char = __bsp_outchar_to_memory; + + printk("RTEMS %s\n", rtems_get_version_string()); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + printk("CPU: 0x%04x, Revision: 0x%04x = %d, Name: %s\n", + myCpu, myCpuRevision, myCpuRevision, get_ppc_cpu_type_name(myCpu)); + + /* + * Initialize the device driver parameters + */ + + /* Timebase register ticks/microsecond; The application may override these */ + bsp_clicks_per_usec = 350; + rtems_counter_initialize_converter(bsp_clicks_per_usec * 1000000); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Let the user know what parameters we were compiled with */ + printk(" Base/Start End Size\n" + "RAM: %p %p\n" + "RTEMS: %p\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: %p %p %p\n" + "Workspace: %p %p\n" + "MsgArea: %p %p\n" + "Physical RAM %p\n", + RamBase, RamSize, + __rtems_end, + intrStackStart, intrStackSize, + __stack_base, _stack, StackSize, + WorkAreaBase, __bsp_ram_end, + MsgAreaBase, MsgAreaSize, + __phy_ram_end); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mngt_init(0); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +static void virtex4_pre_driver_hook(void) +{ + app_bsp_predriver_hook(); +} + +RTEMS_SYSINIT_ITEM( + virtex4_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/virtex4/start/dummy_console.c b/bsps/powerpc/virtex4/start/dummy_console.c new file mode 100644 index 0000000000..642fe45618 --- /dev/null +++ b/bsps/powerpc/virtex4/start/dummy_console.c @@ -0,0 +1,88 @@ +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/bspIo.h> +#include <rtems/console.h> + +#include <string.h> + +ssize_t app_memory_write(int minor, const char* buf, size_t len) +__attribute__(( weak, alias("__bsp_memory_write") )); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len); +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len) +{ + const char* const last = buf+len; + while (buf < last) + { + rtems_putc(*buf++); + } + return len; +} + +static rtems_termios_callbacks gMemCallbacks = { + 0, /* firstOpen */ + 0, /* lastClose */ + 0, /* PollRead */ + app_memory_write, /* write */ + 0, /* SetAttr */ + 0, /* stopRemoteTx */ + 0, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ +}; + +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code status; + + rtems_termios_initialize(); + + status = rtems_io_register_name("/dev/console", major, 0); + + if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code sc; + + sc = rtems_termios_open (major, minor, arg, &gMemCallbacks); + + return sc; +} + +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_close(arg); +} + +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_read(arg); +} + +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_write(arg); +} + +rtems_device_driver console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_ioctl(arg); +} diff --git a/bsps/powerpc/virtex4/start/linkcmds b/bsps/powerpc/virtex4/start/linkcmds new file mode 100644 index 0000000000..50d3a3f13c --- /dev/null +++ b/bsps/powerpc/virtex4/start/linkcmds @@ -0,0 +1,288 @@ +/* + * This file contains directives for the GNU linker which are specific to the + * Virtex 4 PPC 405. No assumptions are made on the firmware in the FPGA. + * This file is intended to be used together with start.S to generate + * downloadable code. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(download_entry) +EXTERN(download_entry) +EXTERN(__vectors) + +MsgAreaSize = DEFINED(MsgAreaSize) ? MsgAreaSize : 1M; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 128M - MsgAreaSize; +IntrStackSize = DEFINED(IntrStackSize) ? IntrStackSize : 16K; +StackSize = DEFINED(StackSize) ? StackSize : 64K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */ + + +MEMORY +{ + VECTORS : ORIGIN = 0x00000000, LENGTH = 12K + RAM : ORIGIN = 0x00003000, LENGTH = 128M - 12K +} + + +SECTIONS +{ + bsp_exc_vector_base = 0x100; + __exeentry = download_entry; + __exestart = bsp_exc_vector_base; + .vectors bsp_exc_vector_base : { *(.vectors) } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > RAM + .hash : { *(.hash) } > RAM + .dynsym : { *(.dynsym) } > RAM + .dynstr : { *(.dynstr) } > RAM + .gnu.version : { *(.gnu.version) } > RAM + .gnu.version_d : { *(.gnu.version_d) } > RAM + .gnu.version_r : { *(.gnu.version_r) } > RAM + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } > RAM + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } > RAM + .rela.rodata : { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > RAM + .rela.got : { *(.rela.got) } > RAM + .rela.got1 : { *(.rela.got1) } > RAM + .rela.got2 : { *(.rela.got2) } > RAM + .rela.ctors : { *(.rela.ctors) } > RAM + .rela.dtors : { *(.rela.dtors) } > RAM + .rela.init : { *(.rela.init) } > RAM + .rela.fini : { *(.rela.fini) } > RAM + .rela.bss : { *(.rela.bss) } > RAM + .rela.plt : { *(.rela.plt) } > RAM + .rela.sdata : { *(.rela.sdata) } > RAM + .rela.sbss : { *(.rela.sbss) } > RAM + .rela.sdata2 : { *(.rela.sdata2) } > RAM + .rela.sbss2 : { *(.rela.sbss2) } > RAM + .rela.dyn : { *(.rela.dyn) } > RAM + + /* Initialization code */ + .init : { PROVIDE (_init = .); + *ecrti.o(.init) + KEEP(*(.init)) + *ecrtn.o(.init) + } > RAM + + .text : { *(.entry) + *(.text) + *(.text.*) + + /* Special FreeBSD sysctl sections */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em + */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > RAM + + /* Finalization code */ + .fini : { PROVIDE (_fini = .); + *ecrti.o(.fini) + KEEP(*(.fini)) + *ecrtn.o(.fini) + } > RAM + + /* Miscellaneous read-only data */ + .rodata : { *(.rodata.* .gnu.linkonce.r*) KEEP (*(SORT(.rtemsroset.*))) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + /* Initialised small data addressed as offsets from r2 */ + .sdata2 : { PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } > RAM + + /* Zeroed small data addressed as offsets from r2 */ + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + /* Avoid empty sdata2/sbss2 area: __eabi would not set up + * r2 which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS2_END__ = .); + } > RAM + + /* Exception frame info */ + .eh_frame : { *(.eh_frame .eh_frame.*) } > RAM + .eh_frame_hdr : { *(.eh_frame_hdr) } > RAM + + /* Declares where the .text section ends */ + _etext = .; + PROVIDE (etext = .); + + /* Initialized R/W Data section goes in RAM */ + .data : { PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + } > RAM + + .data1 : { *(.data1) } > RAM + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } > RAM + PROVIDE (__EXCEPT_END__ = .); + + .got1 : { *(.got1) } > RAM + + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + * get relocated with -mrelocatable. Also put in the .fixup pointers. + * The current compiler no longer needs this, but keep it around for 2.7.2. + */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > RAM + + .dynamic : { *(.dynamic) } > RAM + + .ctors : { /* gcc uses crtbegin.o to find the start of + * the constructors, so we make sure it is + * first. Because this is a wildcard, it + * doesn't matter if the user does not + * actually link against crtbegin.o; the + * linker won't look for a file to match a + * wildcard. The wildcard also means that it + * doesn't matter which directory crtbegin.o + * is in. + */ + KEEP (*crtbegin.o(.ctors)) + /* We don't want to include the .ctor section from + * the crtend.o file until after the sorted ctors. + * The .ctor section from the crtend file contains the + * end of ctors marker and it must be last. + */ + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > RAM + + .dtors : { KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > RAM + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > RAM + PROVIDE (_FIXUP_END_ = .); + + PROVIDE (_GOT2_END_ = .); + + PROVIDE (_GOT_START_ = .); + .got : { __got_start = .; + *(.got) + } > RAM + + .got.plt : { *(.got.plt) } > RAM + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > RAM + + /* We want the small data sections together, so single-instruction offsets + * can access them all, and initialized data all before uninitialized, so + * we can shorten the on-disk segment size. + */ + /* Initialised small data addressed as offsets from r13 */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata* .gnu.linkonce.s.*) } > RAM + + _edata = .; + PROVIDE (edata = .); + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.scommon) + + /* Avoid empty sdata/sbss area: __eabi would not set up + * r13, which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > RAM + + .plt : { *(.plt) } > RAM + .iplt : { *(.iplt) } > RAM + + /* Zeroed large data */ + .bss : { PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + + PROVIDE (__bss_end = ALIGN(4)); + __bss_size = __bss_end - __bss_start; + } > RAM + + __exeend = ALIGN(4); + __rtems_end = .; + . = ALIGN(0x10); /* Align to a cache-line boundary */ + PROVIDE(__bsp_ram_start = .); + + /* Interrupt stack: aligned on a cache-line boundary */ + . += IntrStackSize; + __intrStack = .; + + /* Main stack lives here */ + _stack = ALIGN(0x10); /* Align to a cache-line boundary */ + . += StackSize; + __stack_base = .; /* Initial stack builds downwards */ + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x10); /* Align to a cache-line boundary */ + + /* The heap comes after the work space */ + + . = RamBase + RamSize; + PROVIDE(__bsp_ram_end = .); + + /* Message area for capturing early printk output */ + /* Placed here to be easily findable with a debugger */ + MsgAreaBase = .; + . += MsgAreaSize; + + __phy_ram_end = .; /* True end of physical memory */ + + /DISCARD/ : + { + *(.comment) + } + + /* Some configuration constants: Not clear why they're placed here */ + __dccr = 0x80000000; + __iccr = 0x80000000; + __sgr = 0x7fffffff; + __vectors = 0; +} diff --git a/bsps/powerpc/virtex5/start/bsp_specs b/bsps/powerpc/virtex5/start/bsp_specs new file mode 100644 index 0000000000..ccbea2690c --- /dev/null +++ b/bsps/powerpc/virtex5/start/bsp_specs @@ -0,0 +1,10 @@ +%rename startfile old_startfile +%rename endfile old_endfile + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/bsps/powerpc/virtex5/start/bspclean.c b/bsps/powerpc/virtex5/start/bspclean.c new file mode 100644 index 0000000000..bd5829e0b2 --- /dev/null +++ b/bsps/powerpc/virtex5/start/bspclean.c @@ -0,0 +1,54 @@ +/* + * This routine normally is part of start.s and usually returns + * control to a monitor. + * + * INPUT: NONE + * + * OUTPUT: NONE + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspclean.c: + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/bootcard.h> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_fatal_extension( + rtems_fatal_source source, + bool always_set_to_false, + rtems_fatal_code error +) +{ + if ( source == RTEMS_FATAL_SOURCE_EXIT ) { + app_bsp_cleanup(); + } + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/bsps/powerpc/virtex5/start/bspstart.c b/bsps/powerpc/virtex5/start/bspstart.c new file mode 100644 index 0000000000..ff821574a9 --- /dev/null +++ b/bsps/powerpc/virtex5/start/bspstart.c @@ -0,0 +1,240 @@ +/* + * + * This routine starts the application. It includes application, + * board, and monitor specific initialization and configuration. + * The generic CPU dependent initialization has been performed + * before this routine is invoked. + */ + +/* + * Author: Thomas Doerfler <td@imd.m.isar.de> + * 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: + * + * Author: Andrew Bray <andy@i-cubed.co.uk> + * + * 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. + * + * Modifications for spooling console driver and control of memory layout + * with linker command file by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * 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. IMD makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/startup/bspstart.c: + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * + * Modifications for PPC405GP by Dennis Ehlin + * Modifications for Virtex5 by Richard Claus <claus@slac.stanford.edu> + */ +#include <rtems.h> +#include <rtems/config.h> +#include <rtems/bspIo.h> +#include <rtems/counter.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sysinit.h> + +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.h> + +#include <bsp.h> +#include <bsp/vectors.h> +#include <bsp/bootcard.h> +#include <bsp/irq.h> + +#include <string.h> +#include <fcntl.h> +#include <inttypes.h> + +#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1)) + +#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a) + +#define CPU_DOWN_ALIGN(x) DO_DOWN_ALIGN(x, CPU_ALIGNMENT) +#define CPU_UP_ALIGN(x) DO_UP_ALIGN(x, CPU_ALIGNMENT) + + +/* Defined in linkcmds linker script */ +LINKER_SYMBOL(RamBase); +LINKER_SYMBOL(RamSize); +LINKER_SYMBOL(__bsp_ram_start); +LINKER_SYMBOL(__bsp_ram_end); +LINKER_SYMBOL(__rtems_end); +LINKER_SYMBOL(_stack); +LINKER_SYMBOL(StackSize); +LINKER_SYMBOL(__stack_base); +LINKER_SYMBOL(WorkAreaBase); +LINKER_SYMBOL(MsgAreaBase); +LINKER_SYMBOL(MsgAreaSize); +LINKER_SYMBOL(__phy_ram_end); +LINKER_SYMBOL(bsp_exc_vector_base); + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; + +/* + * Bus Frequency + */ +unsigned int BSP_bus_frequency; +/* + * processor clock frequency + */ +unsigned int BSP_processor_frequency; + +/* + * Time base divisior (bus freq / TB clock) + */ +unsigned int BSP_time_base_divisor; + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_noopfun") )); + +void app_bsp_predriver_hook(void) +__attribute__(( weak, alias("_noopfun") )); + + +static char* bspMsgBuffer = (char*)MsgAreaBase; + +static void __bsp_outchar_to_memory(char c) +{ + static char* msgBuffer = (char*)MsgAreaBase; + *msgBuffer++ = c; + if (msgBuffer >= &bspMsgBuffer[(int)MsgAreaSize]) msgBuffer = bspMsgBuffer; + *msgBuffer = 0x00; /* Overwrite next location to show EOM */ +} + + +void BSP_ask_for_reset(void) +{ + printk("\nSystem stopped, issue RESET"); + + for(;;); +} + + +/*===================================================================*/ + +/* + * BSP start routine. Called by boot_card(). + * + * This routine does the bulk of the system initialization. + */ +void bsp_start(void) +{ + uintptr_t intrStackStart; + uintptr_t intrStackSize; + + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + + /* Set the character output function; The application may override this */ + BSP_output_char = __bsp_outchar_to_memory; + + printk("RTEMS %s\n", rtems_get_version_string()); + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() + * function stores the result in global variables so that it can be used later... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + printk("CPU: 0x%04x, Revision: 0x%04x = %d, Name: %s\n", + myCpu, myCpuRevision, myCpuRevision, get_ppc_cpu_type_name(myCpu)); + + /* + * Initialize the device driver parameters + */ + + /* For mpc6xx clock driver: */ + BSP_bus_frequency = 465000000; + BSP_processor_frequency = 465000000; /* Measured with a DPM 440 2012/8/13 */ + BSP_time_base_divisor = 1000; + + /* Timebase register ticks/microsecond; The application may override these */ + bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000); + rtems_counter_initialize_converter( + BSP_bus_frequency / (BSP_time_base_divisor / 1000) + ); + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + ppc_exc_initialize(intrStackStart, intrStackSize); + + /* Let the user know what parameters we were compiled with */ + printk(" Base/Start End Size\n" + "RAM: %p %p\n" + "RTEMS: %p\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: %p %p %p\n" + "Workspace: %p %p\n" + "MsgArea: %p %p\n" + "Physical RAM %p\n", + RamBase, RamSize, + __rtems_end, + intrStackStart, intrStackSize, + __stack_base, _stack, StackSize, + WorkAreaBase, __bsp_ram_end, + MsgAreaBase, MsgAreaSize, + __phy_ram_end); + + /* + * Initialize RTEMS IRQ system + */ + BSP_rtems_irq_mngt_init(0); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +static void virtex5_pre_driver_hook(void) +{ + app_bsp_predriver_hook(); +} + +RTEMS_SYSINIT_ITEM( + virtex5_pre_driver_hook, + RTEMS_SYSINIT_BSP_PRE_DRIVERS, + RTEMS_SYSINIT_ORDER_MIDDLE +); diff --git a/bsps/powerpc/virtex5/start/dummy_console.c b/bsps/powerpc/virtex5/start/dummy_console.c new file mode 100644 index 0000000000..2cdab33c8c --- /dev/null +++ b/bsps/powerpc/virtex5/start/dummy_console.c @@ -0,0 +1,85 @@ +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/bspIo.h> +#include <rtems/console.h> + +#include <string.h> + +ssize_t app_memory_write(int minor, const char* buf, size_t len) +__attribute__(( weak, alias("__bsp_memory_write") )); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len); + +ssize_t __bsp_memory_write(int minor, const char* buf, size_t len) +{ + const char* const last = buf+len; + while (buf < last) + { + rtems_putc(*buf++); + } + return len; +} + +static rtems_termios_callbacks gMemCallbacks = { + 0, /* firstOpen */ + 0, /* lastClose */ + 0, /* PollRead */ + app_memory_write, /* write */ + 0, /* SetAttr */ + 0, /* stopRemoteTx */ + 0, /* startRemoteTx */ + 0 /* outputUsesInterrupts */ +}; + +rtems_device_driver console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code status; + + rtems_termios_initialize(); + + status = rtems_io_register_name("/dev/console", major, 0); + + if (status != RTEMS_SUCCESSFUL) rtems_fatal_error_occurred (status); + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + rtems_status_code sc; + + sc = rtems_termios_open (major, minor, arg, &gMemCallbacks); + + return sc; +} + +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_close(arg); +} + +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_read(arg); +} + +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_write(arg); +} + +rtems_device_driver console_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg) +{ + return rtems_termios_ioctl(arg); +} diff --git a/bsps/powerpc/virtex5/start/linkcmds b/bsps/powerpc/virtex5/start/linkcmds new file mode 100644 index 0000000000..9bd7c2e67f --- /dev/null +++ b/bsps/powerpc/virtex5/start/linkcmds @@ -0,0 +1,285 @@ +/* + * This file contains directives for the GNU linker which are specific to the + * Virtex 5 PPC 440. No assumptions are made on the firmware in the FPGA. + * This file is intended to be used together with start.S to generate + * downloadable code. + */ + +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") +OUTPUT_ARCH(powerpc) + +ENTRY(download_entry) +EXTERN(download_entry) +EXTERN(__vectors) + +MsgAreaSize = DEFINED(MsgAreaSize) ? MsgAreaSize : 1M; +RamBase = DEFINED(RamBase) ? RamBase : 0x0; +RamSize = DEFINED(RamSize) ? RamSize : 2048M - MsgAreaSize; +IntrStackSize = DEFINED(IntrStackSize) ? IntrStackSize : 16K; +StackSize = DEFINED(StackSize) ? StackSize : 64K; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */ + + +MEMORY +{ + VECTORS : ORIGIN = 0x00000000, LENGTH = 512 + RAM : ORIGIN = 0x00000200, LENGTH = 2048M - 512 +} + + +SECTIONS +{ + bsp_exc_vector_base = 0; + __exeentry = download_entry; + __exestart = bsp_exc_vector_base; + .vectors bsp_exc_vector_base : { *(.vectors) } > VECTORS + + /* Read-only sections, merged into text segment: */ + .interp : { *(.interp) } > RAM + .hash : { *(.hash) } > RAM + .dynsym : { *(.dynsym) } > RAM + .dynstr : { *(.dynstr) } > RAM + .gnu.version : { *(.gnu.version) } > RAM + .gnu.version_d : { *(.gnu.version_d) } > RAM + .gnu.version_r : { *(.gnu.version_r) } > RAM + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } > RAM + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } > RAM + .rela.rodata : { *(.rela.rodata*) *(.rela.gnu.linkonce.r*) } > RAM + .rela.got : { *(.rela.got) } > RAM + .rela.got1 : { *(.rela.got1) } > RAM + .rela.got2 : { *(.rela.got2) } > RAM + .rela.ctors : { *(.rela.ctors) } > RAM + .rela.dtors : { *(.rela.dtors) } > RAM + .rela.init : { *(.rela.init) } > RAM + .rela.fini : { *(.rela.fini) } > RAM + .rela.bss : { *(.rela.bss) } > RAM + .rela.plt : { *(.rela.plt) } > RAM + .rela.sdata : { *(.rela.sdata) } > RAM + .rela.sbss : { *(.rela.sbss) } > RAM + .rela.sdata2 : { *(.rela.sdata2) } > RAM + .rela.sbss2 : { *(.rela.sbss2) } > RAM + .rela.dyn : { *(.rela.dyn) } > RAM + + /* Initialization code */ + .init : { PROVIDE (_init = .); + *ecrti.o(.init) + KEEP(*(.init)) + *ecrtn.o(.init) + } > RAM + + .text : { *(.entry) + *(.text) + *(.text.*) + + /* Special FreeBSD sysctl sections */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + /* .gnu.warning sections are handled specially by elf32.em + */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } > RAM + + /* Finalization code */ + .fini : { PROVIDE (_fini = .); + *ecrti.o(.fini) + KEEP(*(.fini)) + *ecrtn.o(.fini) + } > RAM + + /* Miscellaneous read-only data */ + .rodata : { *(.rodata.* .gnu.linkonce.r*) KEEP (*(SORT(.rtemsroset.*))) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + .tdata : { + _TLS_Data_begin = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + _TLS_Data_end = .; + } >RAM + + .tbss : { + _TLS_BSS_begin = .; + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + _TLS_BSS_end = .; + } >RAM + + _TLS_Data_size = _TLS_Data_end - _TLS_Data_begin; + _TLS_Data_begin = _TLS_Data_size != 0 ? _TLS_Data_begin : _TLS_BSS_begin; + _TLS_Data_end = _TLS_Data_size != 0 ? _TLS_Data_end : _TLS_BSS_begin; + _TLS_BSS_size = _TLS_BSS_end - _TLS_BSS_begin; + _TLS_Size = _TLS_BSS_end - _TLS_Data_begin; + _TLS_Alignment = MAX (ALIGNOF (.tdata), ALIGNOF (.tbss)); + + /* Initialised small data addressed as offsets from r2 */ + .sdata2 : { PROVIDE (_SDA2_BASE_ = 32768); *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } > RAM + + /* Zeroed small data addressed as offsets from r2 */ + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + + /* Avoid empty sdata2/sbss2 area: __eabi would not set up + * r2 which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS2_END__ = .); + } > RAM + + /* Exception frame info */ + .eh_frame : { *(.eh_frame .eh_frame.*) } > RAM + .eh_frame_hdr : { *(.eh_frame_hdr) } > RAM + + /* Declares where the .text section ends */ + _etext = .; + PROVIDE (etext = .); + + /* Initialized R/W Data section goes in RAM */ + .data : { PROVIDE(__DATA_START__ = ABSOLUTE(.) ); + *(.data) + *(.data.*) + KEEP (*(SORT(.rtemsrwset.*))) + *(.gnu.linkonce.d*) + } > RAM + + .data1 : { *(.data1) } > RAM + + PROVIDE (__EXCEPT_START__ = .); + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } > RAM + PROVIDE (__EXCEPT_END__ = .); + + .got1 : { *(.got1) } > RAM + + /* Put .ctors and .dtors next to the .got2 section, so that the pointers + * get relocated with -mrelocatable. Also put in the .fixup pointers. + * The current compiler no longer needs this, but keep it around for 2.7.2. + */ + PROVIDE (_GOT2_START_ = .); + .got2 : { *(.got2) } > RAM + + .dynamic : { *(.dynamic) } > RAM + + .ctors : { /* gcc uses crtbegin.o to find the start of + * the constructors, so we make sure it is + * first. Because this is a wildcard, it + * doesn't matter if the user does not + * actually link against crtbegin.o; the + * linker won't look for a file to match a + * wildcard. The wildcard also means that it + * doesn't matter which directory crtbegin.o + * is in. + */ + KEEP (*crtbegin.o(.ctors)) + /* We don't want to include the .ctor section from + * the crtend.o file until after the sorted ctors. + * The .ctor section from the crtend file contains the + * end of ctors marker and it must be last. + */ + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > RAM + + .dtors : { KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > RAM + + PROVIDE (_FIXUP_START_ = .); + .fixup : { *(.fixup) } > RAM + PROVIDE (_FIXUP_END_ = .); + + PROVIDE (_GOT2_END_ = .); + + PROVIDE (_GOT_START_ = .); + .got : { __got_start = .; + *(.got) + } > RAM + + .got.plt : { *(.got.plt) } > RAM + PROVIDE (_GOT_END_ = .); + + .jcr : { KEEP (*(.jcr)) } > RAM + + /* We want the small data sections together, so single-instruction offsets + * can access them all, and initialized data all before uninitialized, so + * we can shorten the on-disk segment size. + */ + /* Initialised small data addressed as offsets from r13 */ + .sdata : { PROVIDE (_SDA_BASE_ = 32768); *(.sdata* .gnu.linkonce.s.*) } > RAM + + _edata = .; + PROVIDE (edata = .); + + /* Zeroed small data addressed as offsets from r13 */ + .sbss : { PROVIDE (__sbss_start = .); + *(.dynsbss) + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.scommon) + + /* Avoid empty sdata/sbss area: __eabi would not set up + * r13, which may be important if run-time loading is used + */ + . += 1; + + PROVIDE (__SBSS_END__ = .); + PROVIDE (__sbss_end = .); + } > RAM + + .plt : { *(.plt) } > RAM + .iplt : { *(.iplt) } > RAM + + /* Zeroed large data */ + .bss : { PROVIDE (__bss_start = .); + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b*) + *(COMMON) + + PROVIDE (__bss_end = ALIGN(4)); + __bss_size = __bss_end - __bss_start; + } > RAM + + __exeend = ALIGN(4); + __rtems_end = .; + . = ALIGN(0x20); /* Align to a cache-line boundary */ + PROVIDE(__bsp_ram_start = .); + + /* Interrupt stack: aligned on a cache-line boundary */ + . += IntrStackSize; + __intrStack = .; + + /* Main stack lives here */ + _stack = ALIGN(0x20); /* Align to a cache-line boundary */ + . += StackSize; + __stack_base = .; /* Initial stack builds downwards */ + + /* RTEMS workspace: size specified by application */ + WorkAreaBase = ALIGN(0x20); /* Align to a cache-line boundary */ + + /* The heap comes after the work space */ + + . = RamBase + RamSize; + PROVIDE(__bsp_ram_end = .); + + /* Message area for capturing early printk output */ + /* Placed here to be easily findable with a debugger */ + MsgAreaBase = __bsp_ram_end; + . += MsgAreaSize; + + __phy_ram_end = .; /* True end of physical memory */ + + /DISCARD/ : + { + *(.comment) + } + + /* Some configuration constants */ + __vectors = 0; +} |