diff options
42 files changed, 4534 insertions, 191 deletions
diff --git a/c/src/lib/libbsp/powerpc/acinclude.m4 b/c/src/lib/libbsp/powerpc/acinclude.m4 index 32a28301c7..6ea1d33687 100644 --- a/c/src/lib/libbsp/powerpc/acinclude.m4 +++ b/c/src/lib/libbsp/powerpc/acinclude.m4 @@ -36,6 +36,10 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR], AC_CONFIG_SUBDIRS([ss555]);; tqm8xx ) AC_CONFIG_SUBDIRS([tqm8xx]);; + virtex4 ) + AC_CONFIG_SUBDIRS([virtex4]);; + virtex5 ) + AC_CONFIG_SUBDIRS([virtex5]);; virtex ) AC_CONFIG_SUBDIRS([virtex]);; *) diff --git a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am new file mode 100644 index 0000000000..d6ae5d3350 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am @@ -0,0 +1,72 @@ + +## +## $Id: $ +## + +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am + +include_bspdir = $(includedir)/bsp + +dist_project_lib_DATA = bsp_specs + +# include +include_HEADERS = include/bsp.h +include_HEADERS += ../../shared/include/tm27.h + +include_bsp_HEADERS = + +nodist_include_HEADERS = include/bspopts.h +nodist_include_HEADERS += include/coverhd.h +nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h +DISTCLEANFILES = include/bspopts.h + +# start +noinst_LIBRARIES = libbspstart.a +libbspstart_a_SOURCES = ../../powerpc/shared/start/rtems_crti.S +project_lib_DATA = rtems_crti.$(OBJEXT) + +dist_project_lib_DATA += startup/linkcmds + +noinst_LIBRARIES += libbsp.a + +# startup +libbsp_a_SOURCES = startup/bspclean.c \ + ../shared/startup/zerobss.c \ + ../../shared/bsplibc.c \ + ../../shared/bspgetworkarea.c \ + ../../shared/bsppost.c \ + startup/bspstart.c \ + ../../shared/bootcard.c \ + ../../shared/sbrk.c \ + ../../shared/gnatinstallhandler.c + +# start +libbsp_a_SOURCES += startup/start.S + +# clock & timer +libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/clock/clock.c +libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/timer/timer.c + +# console +libbsp_a_SOURCES += startup/dummy_console.c \ + ../../shared/dummy_printk_support.c + +# irq +include_bsp_HEADERS += include/irq.h +libbsp_a_SOURCES += irq/irq_init.c + +#vectors +include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h +include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h + +libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \ + ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel + +EXTRA_DIST = times + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/virtex4/bsp_specs b/c/src/lib/libbsp/powerpc/virtex4/bsp_specs new file mode 100644 index 0000000000..98864c9398 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/bsp_specs @@ -0,0 +1,16 @@ +%rename startfile old_startfile +%rename link old_link +%rename endfile old_endfile + + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s }} + +*link: +%{!qrtems: %(old_link)} \ +%{qrtems: -dc -dp -Bstatic -u __vectors -u download_entry -N } + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c b/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c new file mode 100644 index 0000000000..050824ad1a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/clock/clock.c @@ -0,0 +1,273 @@ +/* clock.c + * + * This routine initializes the interval timer on the + * PowerPC 403 CPU. The tick frequency is specified by the 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. + * + * Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c: + * + * Modifications for deriving timer clock from cpu system clock by + * Thomas Doerfler <td@imd.m.isar.de> + * for these modifications: + * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. + * + * 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.com/license/LICENSE. + * + * Modifications for PPC405GP by Dennis Ehlin + * + * $Id: clock.c 63 2011-04-26 00:23:51Z claus $ + */ + +#include <rtems.h> +#include <rtems/clockdrv.h> +#include <rtems/libio.h> +#include <stdlib.h> /* for atexit() */ +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> + +/* + * check, which exception handling code is present + */ + +#include <bsp.h> + +#include <bsp/vectors.h> +#include <bsp/irq_supp.h> + +volatile uint32_t Clock_driver_ticks; +static uint32_t pit_value, tick_time; +static bool auto_restart; + +void Clock_exit( void ); + +rtems_isr_entry set_vector( /* returns old vector */ + rtems_isr_entry handler, /* isr routine */ + rtems_vector_number vector, /* vector number */ + int type /* RTEMS or RAW intr */ +); + +/* + * These are set by clock driver during its init + */ + +rtems_device_major_number rtems_clock_major = ~0; +rtems_device_minor_number rtems_clock_minor; + +static inline uint32_t get_itimer(void) +{ + register uint32_t rc; + + asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */ + + return rc; +} + +/* + * ISR Handler + */ + +int Clock_isr(BSP_Exception_frame *f, unsigned int vector) +{ + uint32_t clicks_til_next_interrupt; +#if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) + uint32_t l_orig = _ISR_Get_level(); +#endif + if (!auto_restart) + { + uint32_t itimer_value; + /* + * setup for next interrupt; making sure the new value is reasonably + * in the future.... in case we lost out on an interrupt somehow + */ + + itimer_value = get_itimer(); + tick_time += pit_value; + + /* + * how far away is next interrupt *really* + * It may be a long time; this subtraction works even if + * Clock_clicks_interrupt < Clock_clicks_low_order via + * the miracle of unsigned math. + */ + clicks_til_next_interrupt = tick_time - itimer_value; + + /* + * If it is too soon then bump it up. + * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small. + * But setting it low is useful for debug, so... + */ + + if (clicks_til_next_interrupt < 400) + { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should be rare */ + } + + /* + * If it is too late, that means we missed the interrupt somehow. + * Rather than wait 35-50s for a wrap, we just fudge it here. + */ + + if (clicks_til_next_interrupt > pit_value) + { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should never happen :-) */ + } + + asm volatile ("mtspr 0x3db, %0" :: "r" + (clicks_til_next_interrupt)); /* PIT */ + } + + /* Clear the Programmable Interrupt Status */ + asm volatile ( "mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */ + + Clock_driver_ticks++; + + rtems_clock_tick(); + + return 0; +} + +void ClockOff(void) +{ + register uint32_t tcr; + + asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + + tcr &= ~ 0x04400000; + + asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +} + +void ClockOn(void) +{ + uint32_t iocr; + register uint32_t tcr; + + Clock_driver_ticks = 0; + + asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */ + if (bsp_timer_internal_clock) { + iocr &=~0x800000; /* timer clocked from system clock CETE*/ + } + else { + iocr |= 0x800000; /* select external timer clock CETE*/ + } + asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */ + + /* + * Enable auto restart + */ + + auto_restart = true; + + pit_value = rtems_configuration_get_microseconds_per_tick() * + bsp_clicks_per_usec; + + /* + * Set PIT value + */ + + asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ + + /* + * Set timer to autoreload, bit TCR->ARE = 1 0x0400000 + * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000 + */ + tick_time = get_itimer() + pit_value; + + asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); + asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +} + + + +void Install_clock(ppc_exc_handler_t clock_isr) +{ +#ifdef ppc403 + uint32_t pvr; +#endif /* ppc403 */ + + Clock_driver_ticks = 0; + + /* + * initialize the interval here + * First tick is set to right amount of time in the future + * Future ticks will be incremented over last value set + * in order to provide consistent clicks in the face of + * interrupt overhead + */ + + ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr ); + ClockOn(); + + atexit(Clock_exit); +} + +void +ReInstall_clock(ppc_exc_handler_t clock_isr) +{ + uint32_t isrlevel = 0; + + rtems_interrupt_disable(isrlevel); + + ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, clock_isr ); + ClockOn(); + + rtems_interrupt_enable(isrlevel); +} + + +/* + * Called via atexit() + * Remove the clock interrupt handler by setting handler to NULL + * + * This will not work on the 405GP because + * when bit's are set in TCR they can only be unset by a reset + */ + +void Clock_exit(void) +{ + ClockOff(); + ppc_exc_set_handler( BSP_PPC403_CLOCK_HOOK_EXCEPTION, 0 ); +} + +rtems_device_driver Clock_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *pargp +) +{ + Install_clock( Clock_isr ); + + /* + * make major/minor avail to others such as shared memory driver + */ + + rtems_clock_major = major; + rtems_clock_minor = minor; + + return RTEMS_SUCCESSFUL; +} diff --git a/c/src/lib/libbsp/powerpc/virtex4/configure.ac b/c/src/lib/libbsp/powerpc/virtex4/configure.ac new file mode 100644 index 0000000000..8f865816d0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/configure.ac @@ -0,0 +1,48 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +dnl $Id: $ + +AC_PREREQ(2.68) +AC_INIT([rtems-c-src-lib-libbsp-powerpc-virtex4],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([bsp_specs]) +RTEMS_TOP(../../../../../..) + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.11.1]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_CHECK_NETWORKING +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + +RTEMS_BSPOPTS_SET([PPC_USE_DATA_CACHE],[*],[1]) +RTEMS_BSPOPTS_HELP([PPC_USE_DATA_CACHE], +[If defined, then the PowerPC specific code in RTEMS will use + data cache instructions to optimize the context switch code. + This code can conflict with debuggers or emulators. It is known + to break the Corelis PowerPC emulator with at least some combinations + of PowerPC 603e revisions and emulator versions. + The BSP actually contains the call that enables this.]) + +RTEMS_BSPOPTS_SET([PPC_USE_SPRG],[*],[1]) +RTEMS_BSPOPTS_HELP([PPC_USE_SPRG], +[If defined, then the PowerPC specific code in RTEMS will use some + of the special purpose registers to slightly optimize interrupt + response time. The use of these registers can conflict with + other tools like debuggers.]) + +RTEMS_BSPOPTS_SET([PPC_VECTOR_FILE_BASE],[*],[0x0100]) +RTEMS_BSPOPTS_HELP([PPC_VECTOR_FILE_BASE], +[This defines the base address of the exception table.]) + +RTEMS_BSP_CLEANUP_OPTIONS(0, 1) + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) + +RTEMS_PPC_EXCEPTIONS + +AC_OUTPUT diff --git a/c/src/lib/libbsp/powerpc/virtex4/include/bsp.h b/c/src/lib/libbsp/powerpc/virtex4/include/bsp.h new file mode 100644 index 0000000000..1ae242abec --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/include/bsp.h @@ -0,0 +1,82 @@ +/* bsp.h + * + * This include file contains all GEN405 board IO definitions. + * + * derived from helas403/include/bsp.h: + * Id: bsp.h,v 1.4 2001/06/18 17:01:48 joel Exp + * 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. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/include/bsp.h + * + * 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.com/license/LICENSE. + * + * $Id: bsp.h 63 2011-04-26 00:23:51Z claus $ + * + */ + +#ifndef _BSP_H +#define _BSP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <bspopts.h> + +/* + * confdefs.h overrides for this BSP: + * - Interrupt stack space is not minimum if defined. + */ +#define CONFIGURE_INTERRUPT_STACK_MEMORY (16 * 1024) + +#ifdef ASM +/* Definition of where to store registers in alignment handler */ +#define ALIGN_REGS 0x0140 + +#else +#include <rtems.h> +#include <rtems/console.h> +#include <rtems/clockdrv.h> +#include <rtems/iosupp.h> + +/* miscellaneous stuff assumed to exist */ +extern bool bsp_timer_internal_clock; /* TRUE, when timer runs with CPU clk */ + +extern rtems_configuration_table BSP_Configuration; /* owned by BSP */ +#endif /* ASM */ + +void BSP_ask_for_reset(void); +void BSP_panic(char *s); +void _BSP_Fatal_error(unsigned int v); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/virtex4/include/coverhd.h b/c/src/lib/libbsp/powerpc/virtex4/include/coverhd.h new file mode 100644 index 0000000000..50d9606cef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/include/coverhd.h @@ -0,0 +1,133 @@ +/* coverhd.h + * + * This include file has defines to represent the overhead associated + * with calling a particular directive from C. These are used in the + * Timing Test Suite to ignore the overhead required to pass arguments + * to directives. On some CPUs and/or target boards, this overhead + * is significant and makes it difficult to distinguish internal + * RTEMS execution time from that used to call the directive. + * This file should be updated after running the C overhead timing + * test. Once this update has been performed, the RTEMS Time Test + * Suite should be rebuilt to account for these overhead times in the + * timing results. + * + * NOTE: If these are all zero, then the times reported include + * all calling overhead including passing of arguments. + * + * 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.com/license/LICENSE. + * + * $Id: coverhd.h 63 2011-04-26 00:23:51Z claus $ + */ + +/* + * Updated for a 25MHz Papyrus by Andrew Bray <andy@i-cubed.co.uk> + * + * Units are 100ns. + * + * These numbers are of questionable use, as they are developed by calling + * the routine many times, thus getting its entry veneer into the (small) + * cache on the 403GA. This in general is not true of the RTEMS timing + * tests, which usually call a routine only once, thus having no cache loaded + * advantage. + * + * Whether the directive times are useful after deducting the function call + * overhead is also questionable. The user is more interested generally + * in the total cost of a directive, not the cost if the procedure call + * is inlined! (In general this is not true). + * + * Andrew Bray 18/08/1995 + * + */ + +#ifndef __COVERHD_h +#define __COVERHD_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 1 +#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 1 +#define CALLING_OVERHEAD_TASK_CREATE 3 +#define CALLING_OVERHEAD_TASK_IDENT 1 +#define CALLING_OVERHEAD_TASK_START 1 +#define CALLING_OVERHEAD_TASK_RESTART 1 +#define CALLING_OVERHEAD_TASK_DELETE 1 +#define CALLING_OVERHEAD_TASK_SUSPEND 1 +#define CALLING_OVERHEAD_TASK_RESUME 1 +#define CALLING_OVERHEAD_TASK_SET_PRIORITY 1 +#define CALLING_OVERHEAD_TASK_MODE 1 +#define CALLING_OVERHEAD_TASK_GET_NOTE 1 +#define CALLING_OVERHEAD_TASK_SET_NOTE 1 +#define CALLING_OVERHEAD_TASK_WAKE_WHEN 4 +#define CALLING_OVERHEAD_TASK_WAKE_AFTER 1 +#define CALLING_OVERHEAD_INTERRUPT_CATCH 1 +#define CALLING_OVERHEAD_CLOCK_GET 4 +#define CALLING_OVERHEAD_CLOCK_SET 3 +#define CALLING_OVERHEAD_CLOCK_TICK 1 + +#define CALLING_OVERHEAD_TIMER_CREATE 1 +#define CALLING_OVERHEAD_TIMER_IDENT 1 +#define CALLING_OVERHEAD_TIMER_DELETE 1 +#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 2 +#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 5 +#define CALLING_OVERHEAD_TIMER_RESET 1 +#define CALLING_OVERHEAD_TIMER_CANCEL 1 +#define CALLING_OVERHEAD_SEMAPHORE_CREATE 2 +#define CALLING_OVERHEAD_SEMAPHORE_IDENT 1 +#define CALLING_OVERHEAD_SEMAPHORE_DELETE 1 +#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 1 +#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 2 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 2 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 1 + +#define CALLING_OVERHEAD_EVENT_SEND 1 +#define CALLING_OVERHEAD_EVENT_RECEIVE 2 +#define CALLING_OVERHEAD_SIGNAL_CATCH 1 +#define CALLING_OVERHEAD_SIGNAL_SEND 1 +#define CALLING_OVERHEAD_PARTITION_CREATE 3 +#define CALLING_OVERHEAD_PARTITION_IDENT 1 +#define CALLING_OVERHEAD_PARTITION_DELETE 1 +#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 1 +#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 1 +#define CALLING_OVERHEAD_REGION_CREATE 3 +#define CALLING_OVERHEAD_REGION_IDENT 1 +#define CALLING_OVERHEAD_REGION_DELETE 1 +#define CALLING_OVERHEAD_REGION_GET_SEGMENT 2 +#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 1 +#define CALLING_OVERHEAD_PORT_CREATE 2 +#define CALLING_OVERHEAD_PORT_IDENT 1 +#define CALLING_OVERHEAD_PORT_DELETE 1 +#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 1 +#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 2 + +#define CALLING_OVERHEAD_IO_INITIALIZE 2 +#define CALLING_OVERHEAD_IO_OPEN 2 +#define CALLING_OVERHEAD_IO_CLOSE 2 +#define CALLING_OVERHEAD_IO_READ 2 +#define CALLING_OVERHEAD_IO_WRITE 2 +#define CALLING_OVERHEAD_IO_CONTROL 2 +#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 1 +#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/virtex4/include/irq.h b/c/src/lib/libbsp/powerpc/virtex4/include/irq.h new file mode 100644 index 0000000000..50d3b4c880 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/include/irq.h @@ -0,0 +1,77 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file declares constants of the interrupt controller | +\*===============================================================*/ +#ifndef VIRTEX4_IRQ_IRQ_H +#define VIRTEX4_IRQ_IRQ_H + +#include <rtems/irq.h> + +/* + * the following definitions specify the indices used + * to interface the interrupt handler API + */ + +/* + * Peripheral IRQ handlers related definitions + */ + /* Not supported at this level */ + +/* + * Processor IRQ handlers related definitions + */ +#define BSP_PROCESSOR_IRQ_NUMBER 3 +#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET 0 +#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET\ + +BSP_PROCESSOR_IRQ_NUMBER-1) + +#define BSP_IS_PROCESSOR_IRQ(irqnum) \ + (((irqnum) >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) && \ + ((irqnum) <= BSP_PROCESSOR_IRQ_MAX_OFFSET)) + +/* + * Summary + */ +#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET+1) +#define BSP_LOWEST_OFFSET BSP_PROCESSOR_IRQ_LOWEST_OFFSET +#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET + +#define BSP_IS_VALID_IRQ(irqnum) (BSP_IS_PROCESSOR_IRQ(irqnum)) + +#ifndef ASM +#ifdef __cplusplus +extern "C" { +#endif + +/* + * index table for the module specific handlers, a few entries are only placeholders + */ + typedef enum { + BSP_EXT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 0, + BSP_PIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 1, + BSP_CRIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 2 + } rtems_irq_symbolic_name; + + extern rtems_irq_connect_data *BSP_rtems_irq_tbl; + void BSP_rtems_irq_mngt_init(unsigned cpuId); + +#ifdef __cplusplus +} +#endif +#endif /* ASM */ + +#endif /* VIRTEX4_IRQ_IRQ_H */ diff --git a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c new file mode 100644 index 0000000000..74aaebb275 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c @@ -0,0 +1,328 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2007 | +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +#include <libcpu/spr.h> +#include <bsp/irq.h> +#include <bsp.h> +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> +#include <bsp/vectors.h> + +uint32_t* IRQ_Counter = (uint32_t*)0x1500; + +static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; +rtems_irq_connect_data *BSP_rtems_irq_tbl; +rtems_irq_global_settings* BSP_rtems_irq_config; + +/*********************************************************** + * dummy functions for on/off/isOn calls + * these functions just do nothing fulfill the semantic + * requirements to enable/disable a certain interrupt or exception + */ +void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +void BSP_irq_nop_hdl(void *hdl) +{ + /* + * nothing to do + */ +} + +int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ + return 0; +} + +/*********************************************************** + * interrupt handler and its enable/disable functions + ***********************************************************/ + +/*********************************************************** + * functions to enable/disable/query external/critical interrupts + */ +void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value &= ~PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +/*********************************************************** + * High level IRQ handler called from shared_raw_irq_code_entry + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + /* + * Handle interrupt + */ + switch(excNum) { + case ASM_EXT_VECTOR: + BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); + break; + case ASM_BOOKE_DEC_VECTOR: + BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle); + break; +#if 0 /* Critical interrupts not yet supported */ + case ASM_BOOKE_CRIT_VECTOR: + BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); + break; +#endif + } + + return 0; +} + +/*********************************************************** + * functions to set/get/remove interrupt handlers + ***********************************************************/ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid irq name + * if invalid, print error and return 0 + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + printk("Invalid interrupt vector %d\n",irq->name); + return 0; + } + + /* + * disable interrupts + */ + rtems_interrupt_disable(level); + + /* + * check, that default handler is installed now + */ + if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { + rtems_interrupt_enable(level); + printk("IRQ vector %d already connected\n",irq->name); + return 0; + } + + /* + * store new handler data + */ + rtemsIrqTbl[irq->name] = *irq; + + /* + * call "on" function to enable interrupt at device + */ + irq->on(irq); + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * return current IRQ entry + */ + *irq = rtemsIrqTbl[irq->name]; + rtems_interrupt_enable(level); + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * check, that specified handler is really connected now + */ + if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { + rtems_interrupt_enable(level); + return 0; + } + + /* + * disable interrupt at source + */ + irq->off(irq); + + /* + * restore default interrupt handler + */ + rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +/*********************************************************** + * functions to set/get the basic interrupt management setup + ***********************************************************/ +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) +{ + *ret_ptr = BSP_rtems_irq_config; + return 0; +} + + +/* + * set management stuff + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + /* + * store given configuration + */ + BSP_rtems_irq_config = config; + BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; + + /* + * store any irq-like processor exceptions + */ + for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; + i < BSP_PROCESSOR_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + if (BSP_rtems_irq_tbl[i].on != NULL) { + BSP_rtems_irq_tbl[i].on + (&(BSP_rtems_irq_tbl[i])); + } + } + else { + if (BSP_rtems_irq_tbl[i].off != NULL) { + BSP_rtems_irq_tbl[i].off + (&(BSP_rtems_irq_tbl[i])); + } + } + } + rtems_interrupt_enable(level); + return 1; +} + +/* + * dummy for an empty IRQ handler entry + */ +static rtems_irq_connect_data emptyIrq = { + 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ +}; + +static rtems_irq_global_settings initialConfig = { + BSP_IRQ_NUMBER, /* irqNb */ + { 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ + }, /* emptyIrq */ + rtemsIrqTbl, /* irqHdlTbl */ + 0, /* irqBase */ + NULL /* irqPrioTbl */ +}; + +void BSP_rtems_irq_mngt_init(unsigned cpuId) +{ + int i; + + /* + * connect all exception vectors needed + */ + ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); + ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler); + + /* + * setup interrupt handlers table + */ + for (i = 0; + i < BSP_IRQ_NUMBER; + i++) { + rtemsIrqTbl[i] = emptyIrq; + rtemsIrqTbl[i].name = i; + } + + /* + * initialize interrupt management + */ + if (!BSP_rtems_irq_mngt_set(&initialConfig)) { + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +} diff --git a/c/src/lib/libbsp/powerpc/virtex4/make/custom/virtex4.cfg b/c/src/lib/libbsp/powerpc/virtex4/make/custom/virtex4.cfg new file mode 100644 index 0000000000..333b144b43 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/make/custom/virtex4.cfg @@ -0,0 +1,19 @@ +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU=powerpc +RTEMS_CPU_MODEL=ppc405 + +# This contains the compiler options necessary to select the CPU model +# and (hopefully) optimize for it. +# +CPU_CFLAGS = -mcpu=405 -Dppc405 + +# optimize flag: typically -O2 +CFLAGS_OPTIMIZE_V = -O2 -g -fno-keep-inline-functions + +# Miscellaneous additions go here +define bsp-post-link + $(default-bsp-post-link) + $(OBJCOPY) -O srec $(basename $@).exe $(basename $@)$(DOWNEXT) +endef + diff --git a/c/src/lib/libbsp/powerpc/virtex4/preinstall.am b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am new file mode 100644 index 0000000000..34b03f177c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/preinstall.am @@ -0,0 +1,79 @@ +## Automatically generated by ampolish3 - Do not edit + +if AMPOLISH3 +$(srcdir)/preinstall.am: Makefile.am + $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am +endif + +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + +all-local: $(TMPINSTALL_FILES) + +TMPINSTALL_FILES = +CLEANFILES = $(TMPINSTALL_FILES) + +all-am: $(PREINSTALL_FILES) + +PREINSTALL_FILES = +CLEANFILES += $(PREINSTALL_FILES) + +$(PROJECT_LIB)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_LIB) + @: > $(PROJECT_LIB)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) + +$(PROJECT_INCLUDE)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE) + @: > $(PROJECT_INCLUDE)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) + +$(PROJECT_INCLUDE)/bsp/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp + @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp) + +$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs +PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs + +$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h + +$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h + +$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h + +$(PROJECT_INCLUDE)/coverhd.h: include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h + +$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h + +$(PROJECT_LIB)/rtems_crti.$(OBJEXT): rtems_crti.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/rtems_crti.$(OBJEXT) +TMPINSTALL_FILES += $(PROJECT_LIB)/rtems_crti.$(OBJEXT) + +$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds +PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds + +$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h + +$(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h + +$(PROJECT_INCLUDE)/bsp/irq_supp.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq_supp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq_supp.h + diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/bspclean.c b/c/src/lib/libbsp/powerpc/virtex4/startup/bspclean.c new file mode 100644 index 0000000000..df2d7af477 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/bspclean.c @@ -0,0 +1,49 @@ +/* bsp_cleanup() + * + * 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.com/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp.h> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_cleanup( void ) +{ + app_bsp_cleanup(); + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c new file mode 100644 index 0000000000..f99526403c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/bspstart.c @@ -0,0 +1,255 @@ +/* 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 + * Modifications for Virtex4 by Richard Claus <claus@slac.stanford.edu> + */ + +#include <string.h> +#include <fcntl.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/vectors.h> +#include <rtems/bspIo.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sptables.h> /* for RTEMS_VERSION */ +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.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) + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; +bool bsp_timer_internal_clock; /* true, when timer runs with CPU clk */ +uint32_t bsp_timer_least_valid; +uint32_t bsp_timer_average_overhead; + + +/* 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); + + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} +static void _bsp_start(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uintptr_t intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + uintptr_t intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + * + * This BSP does not assume anything about firmware possibly loaded in the + * FPGA, so the external interrupt should not be enabled in order to avoid + * spurious interrupts. + */ + sc = ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT & ~MSR_EE, + intrStackStart, + intrStackSize); + if (sc != RTEMS_SUCCESSFUL) BSP_panic("Cannot initialize exceptions"); + + /* Install our own set of exception vectors */ + BSP_rtems_irq_mngt_init(0); +} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_bsp_start") )); + +void app_bsp_pretasking_hook(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(;;); +} + + +void BSP_panic(char *s) +{ + printk("\n%s PANIC %s\n", _RTEMS_version, s); + BSP_ask_for_reset(); +} + + +void _BSP_Fatal_error(unsigned int v) +{ + printk("\n%s FATAL ERROR %x\n", _RTEMS_version, v); + BSP_ask_for_reset(); +} + + +/*===================================================================*/ + +/* + * 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("\nWelcome to RTEMS %s\n", _RTEMS_version ); + + /* + * 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; + bsp_timer_internal_clock = true; + bsp_timer_average_overhead = 2; + bsp_timer_least_valid = 3; + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + printk(" Base/Start End Size\n" + "RAM: 0x%08x 0x%x\n" + "RTEMS: 0x%08x\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: 0x%08x 0x%08x 0x%x\n" + "Workspace: 0x%08x 0x%08x\n" + "MsgArea: 0x%08x 0x%x\n" + "Physical RAM 0x%08x\n", + (uint32_t)RamBase, (uint32_t)RamSize, + (uint32_t)__rtems_end, + intrStackStart, intrStackSize, + (uint32_t)__stack_base, (uint32_t)_stack, (uint32_t)StackSize, + (uint32_t)WorkAreaBase, (uint32_t)__bsp_ram_end, + (uint32_t)MsgAreaBase, (uint32_t)MsgAreaSize, + (uint32_t)__phy_ram_end); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP pretasking hook. Called just before drivers are initialized. + * Used to setup libc and install any BSP extensions. + * + * Must not use libc (to do io) from here, since drivers are not yet + * initialized. + */ + +void bsp_pretasking_hook(void) +{ + app_bsp_pretasking_hook(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +void bsp_predriver_hook(void) +{ + app_bsp_predriver_hook(); +} diff --git a/c/src/lib/libbsp/powerpc/virtex4/startup/dummy_console.c b/c/src/lib/libbsp/powerpc/virtex4/startup/dummy_console.c new file mode 100644 index 0000000000..048133d1c2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/dummy_console.c @@ -0,0 +1,102 @@ +#include <rtems.h> +#include <rtems/libio.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); +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_control(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) + { + BSP_output_char(*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/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds new file mode 100644 index 0000000000..cff5767aef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/linkcmds @@ -0,0 +1,267 @@ +/* + * 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) + +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 = 8K + RAM : ORIGIN = 0x00002000, LENGTH = 128M - 8K +} + + +SECTIONS +{ + __exeentry = download_entry; + __exestart = 0x100; + .vectors __exestart : { *(.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*) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + /* Initialised small data addressed as offsets from r2 */ +_SDA2_BASE_ = __SDATA2_START__ + 0x8000; + .sdata2 : { *(.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.*) + *(.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 */ +_SDA_BASE_ = __SDATA_START__ + 0x8000; + .sdata : { *(.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 = __bsp_ram_end; + . += 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/c/src/lib/libbsp/powerpc/virtex4/startup/start.S b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S new file mode 100644 index 0000000000..c3053fb0b5 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex4/startup/start.S @@ -0,0 +1,324 @@ +/*!@file start.S +* +* @brief Initialization code to set up the CPU and call boot_card() +* +* This "BSP" targets the Xilinx Virtex XC4VFX60 and related parts. This +* BSP makes no assumptions on what firmware is loaded into the FPGA. +* +* Provides the .entry section code. This is the first code to run in +* the PPC after download to RAM. Excecution in this case starts at +* 'download_entry'. +* +* The entrypoint 'start' is provided for the case where a bootloader has +* initialized the CPU, and all that remains to do is to set up a C +* environment and call boot_card. +* +* Derived from virtex dlentry and others. +* +* IBM refers to the version of the processor as PPC405F5. +* The processor version register returns 0x20011470. +* References: +* PowerPC Processor Reference Guide UG011 (v1.3) +* http://www.xilinx.com/support/documentation/user_guides/ug011.pdf +* +* PowerPC Block Reference Guide +* http://www.xilinx.com/support/documentation/user_guides/ug018.pdf +* +* PowerPC errata +* ftp://ftp.xilinx.com/pub/documentation/misc/ppc405f6v5_2_0.pdf +* +* PowerPC 405-S Embedded Processor Core User's Manual (Version 1.2) +* https://www-01.ibm.com/chips/techlib/techlib.nsf/products/PowerPC_405_Embedded_Cores +* +* @author Richard Claus <claus@SLAC.Stanford.edu> +* +* @date March 4, 2011 -- Created +* +* $Revision: 674 $ +* +* @verbatim Copyright 2011 +* by +* The Board of Trustees of the +* Leland Stanford Junior University. +* All rights reserved. +* +* Work supported by the U.S. Department of Energy under contract +* DE-AC03-76SF00515. +* +* Disclaimer Notice +* +* The items furnished herewith were developed under the sponsorship +* of the U.S. Government. Neither the U.S., nor the U.S. D.O.E., nor the +* Leland Stanford Junior University, nor their employees, makes any war- +* ranty, express or implied, or assumes any liability or responsibility +* for accuracy, completeness or usefulness of any information, apparatus, +* product or process disclosed, or represents that its use will not in- +* fringe privately-owned rights. Mention of any product, its manufactur- +* er, or suppliers shall not, nor is it intended to, imply approval, dis- +* approval, or fitness for any particular use. The U.S. and the Univer- +* sity at all times retain the right to use and disseminate the furnished +* items for any purpose whatsoever. Notice 91 02 01 +* +* @endverbatim +*/ + +#include <rtems/asm.h> +#include <rtems/powerpc/powerpc.h> + +/* + * The virtex ELF link scripts support some special sections: + * .entry The actual entry point + * .vectors The section containing the interrupt entry veneers. + */ + +/* + * Downloaded code loads the vectors separately to 0x00000100, + * so .entry can be over 256 bytes. + * + * The other sections are linked in the following order: + * .entry + * .text + * .data + * .bss + * see linker command file for section placement + * + * The initial stack is set to __stack_base. + * + */ + + .section .entry + + PUBLIC_VAR (download_entry) + PUBLIC_VAR (__rtems_entry_point) +SYM(download_entry): +SYM(__rtems_entry_point): + b startupDow /* Entry point used by xmd dow command */ + + PUBLIC_VAR (start) +SYM(start): + b startupBL /* Entry point used by bootLoader */ + +base_addr: + /*------------------------------------------------------------------- + * Parameters from linker + *-----------------------------------------------------------------*/ +toc_pointer: + .long __got_start +bss_length: + .long __bss_size +bss_addr: + .long __bss_start +stack_top: + .long __stack_base +dccr_contents: + .long __dccr +iccr_contents: + .long __iccr +sgr_contents: + .long __sgr + + /*------------------------------------------------------------------- + * Setup iccr, sgr, msr, cccr0, dcwr, dccr and clear bss + *-----------------------------------------------------------------*/ + +startupDow: + /*------------------------------------------------------------------- + * Load the parameter table base address + *------------------------------------------------------------------*/ + lis r1, base_addr@h + ori r1,r1,base_addr@l + + /* ------------------------------------------------------------------- + * Clear the Machine State Register's Critical and External + * interrupt enables. + *------------------------------------------------------------------*/ + mfmsr r3 + lis r0, 0x00028000@h + ori r0,r0,0x00028000@l + andc r3,r3,r0 + mtmsr r3 + sync + + /* ------------------------------------------------------------------- + * Initialize the memory system. + *------------------------------------------------------------------*/ + li r0,0 + + /* Set the Storage Guarded Register. */ + lwz r2,sgr_contents-base_addr(r1) + mtsgr r2 + + /* Configure endianness, compression */ + lis r0,0x00000000@h // Endianess value + mtsler r0 + lis r0,0x00000000@h // Compression value + mtsu0r r0 + + /* Invalidate the entire instruction cache. */ + iccci r0,r0 + + /* Set the Instruction Cache Cacheability Register. */ + lwz r2,iccr_contents-base_addr(r1) + mticcr r2 + isync + + /*------------------------------------------------------------------- + * Tell the processor where the exception vector table will be. + *------------------------------------------------------------------*/ + .extern SYM(__vectors) + lis r0, __vectors@h /* set EVPR exc. vector prefix */ + mtspr evpr,r0 + + /*------------------------------------------------------------------- + * Set up the debug register to freeze timers on debug events. + *------------------------------------------------------------------*/ + mfdbcr0 r0 + ori r0,r0,0x0001 + mtdbcr0 r0 + isync + + /* Select whether APU, Wait Enable, interrupts/exceptions and address + translation should be enabled when application starts */ + lis r0,0x00000000@h /* SRR1 value */ + mtsrr1 r0 /* Potentially: 0x80000000 >> 6 is APU */ + + /* Clear out stale values in certain registers to avoid confusion */ + mtxer r0 /* Fixed-point exception register */ + mtesr r0 /* Exception syndrome register */ + mtdear r0 /* Data exception address register */ + mtmcsr r0 /* Machine check syndrome register */ + mtpit r0 /* Programmable interval timer */ + li r0,-1 /* -1 to clear TSR */ + mttsr r0 /* Timer status register */ + + /* Invalidate the data cache */ + li r2,0 /* Start address */ + li r3,0x100 /* Number of cache lines */ + mtctr r3 /* Transfer data cache congruence class count to CTR */ +1: dccci 0,r2 /* Invalidate this congruence class */ + addi r2,r2,0x20 /* Point to next congruence class */ + bdnz 1b /* Decrement counter and loop whilst not zero */ + + /* ------------------------------------------------------------------- + * Set Core Configuration Register 0 as follows: + * sum: 0x02700E00 + * bit 1 off: as told by ppc405 errata to avoid CPU_213 ppc bug + * bit 3 off: as told by ppc405 errata to avoid CPU_213 ppc bug + (Note added later: PPC405F6 is not subject to CPU_213.) + * bit 1 on: Xilinx: CR 203746 Patch for PPC405 errata (RiC 12/8/11) + * bit 2 on: Xilinx: CR 203746 Patch for PPC405 errata (RiC 12/8/11) + * bit 6 on: load word as line + * bit 7 off: load misses allocate cache line + * bit 8 off: store misses allocate cache line + * bit 9-11 on: default settings to do with plb priority + * bit 20 on: prefetching for cacheable regions + * bit 21 on: prefetching for non-cacheable regions + * bit 22 on: request size of non-cacheable inst fetches is 8 words + * bit 23 off: fetch misses allocate cache line + *------------------------------------------------------------------*/ + lis r5, 0x52700E00@h + ori r5,r5,0x52700E00@l + + /* ------------------------------------------------------------------- + * To change CCR0 we make sure the code writing to it is + * running from the I-cache. This is needed because changing some + * CCR0 fields will cause a hang if the processor is trying to + * access memory at the same time. + *------------------------------------------------------------------*/ + lis r4, 2f@h + ori r4,r4,2f@l + icbt r0,r4 + b 2f + + .align 5 /* New cache line (32 bytes each) */ +2: + icbt r0,r4 /* Put this line into the I-cache. */ + isync + mtccr0 r5 + isync + b 3f + + .align 5 +3: + /* Set the Data Cache Write-Through Register for no write-through, i.e., for write-back. */ + li r0,0 + mtdcwr r0 + + /* Set the Data Cache Cacheablility Register. */ + lwz r0,dccr_contents-base_addr(r1) + mtdccr r0 + isync + + /* Fall through */ + + + /* ------------------------------------------------------------------- + * If a bootloader has run that has already performed some + * initialization, which among other things has loaded + * this code into memory and jumped to start above, the initialization + * above does not need to be done. Execution thus resumes here. + *------------------------------------------------------------------*/ + +startupBL: + /* ------------------------------------------------------------------- + * Note that some initialization has already been performed by the + * bootloader code in Block RAM, which among other things has loaded + * this code into memory and jumped to start above. + *------------------------------------------------------------------*/ + + /*------------------------------------------------------------------- + * Load the parameter table base address + *------------------------------------------------------------------*/ + lis r1, base_addr@h + ori r1,r1,base_addr@l + + /*------------------------------------------------------------------- + * Setup stack for RTEMS and call boot_card(). From this + * point forward registers will be used in accordance with the + * PowerPC EABI. + * + * boot_card() supervises the initialization of RTEMS and the C + * library. It calls bsp_start(), bsp_pretasking_hook(), etc. + *------------------------------------------------------------------*/ + lwz r2,toc_pointer-base_addr(r1) /* set r2 to toc */ + lwz r1,stack_top-base_addr(r1) /* set r1 to stack_top */ + + /* Align as required by ABI */ + li r3,PPC_STACK_ALIGNMENT-1 + andc r1,r1,r3 + + /*------------------------------------------------------------------- + * Set up r2 and r13. Upon entry r1 must have a nonzero value + * as it will be stored in an "init done" flag. Stupid but true. + * r1 must also be set up as a stack pointer as __eabi() jumps + * to __init() which has a standard function prolog. + *------------------------------------------------------------------*/ + bl __eabi + + /*------------------------------------------------------------------- + * Zero the .bss, .sbss and .sbss2 sections. + * Must have r2 and r13 properly set. + *------------------------------------------------------------------*/ + bl zero_bss + + /*------------------------------------------------------------------- + * Create a minimal stack frame for this code, the caller of boot_card(). + *------------------------------------------------------------------*/ + addi r1,r1, -PPC_MINIMUM_STACK_FRAME_SIZE + + xor r3,r3,r3 + stw r3,0(r1) /* Terminate the chain of stack frames. */ + stw r3,4(r1) + stw r3,8(r1) + stw r3,12(r1) + lis r5,environ@ha + la r5,environ@l(r5) /* environp */ + + /*------------------------------------------------------------------- + * Call boot_card() with its arguments, the command-line pointer and + * the argument count, set to NULL. + *------------------------------------------------------------------*/ + li r4,0 /* argv */ + li r3,0 /* argc */ + .extern SYM (boot_card) + b SYM (boot_card) diff --git a/c/src/lib/libbsp/powerpc/virtex5/Makefile.am b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am new file mode 100644 index 0000000000..5952497008 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am @@ -0,0 +1,71 @@ +## +## $Id: $ +## + +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am + +include_bspdir = $(includedir)/bsp + +dist_project_lib_DATA = bsp_specs + +# include +include_HEADERS = include/bsp.h +include_HEADERS += ../../shared/include/tm27.h + +include_bsp_HEADERS = + +nodist_include_HEADERS = include/bspopts.h +nodist_include_HEADERS += include/coverhd.h +nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h +DISTCLEANFILES = include/bspopts.h + +# start +noinst_LIBRARIES = libbspstart.a +libbspstart_a_SOURCES = ../../powerpc/shared/start/rtems_crti.S +project_lib_DATA = rtems_crti.$(OBJEXT) + +dist_project_lib_DATA += startup/linkcmds + +noinst_LIBRARIES += libbsp.a + +# startup +libbsp_a_SOURCES = startup/bspclean.c \ + ../shared/startup/zerobss.c \ + ../../shared/bsplibc.c \ + ../../shared/bspgetworkarea.c \ + ../../shared/bsppost.c \ + startup/bspstart.c \ + ../../shared/bootcard.c \ + ../../shared/sbrk.c \ + ../../shared/gnatinstallhandler.c + +# start +libbsp_a_SOURCES += startup/start.S + +# clock & timer +libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/clock/clock.c +libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/timer/timer.c + +# console +libbsp_a_SOURCES += startup/dummy_console.c \ + ../../shared/dummy_printk_support.c + +# irq +include_bsp_HEADERS += include/irq.h +libbsp_a_SOURCES += irq/irq_init.c + +#vectors +include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h +include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h + +libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \ + ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel + +EXTRA_DIST = times + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/virtex5/bsp_specs b/c/src/lib/libbsp/powerpc/virtex5/bsp_specs new file mode 100644 index 0000000000..98864c9398 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/bsp_specs @@ -0,0 +1,16 @@ +%rename startfile old_startfile +%rename link old_link +%rename endfile old_endfile + + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s }} + +*link: +%{!qrtems: %(old_link)} \ +%{qrtems: -dc -dp -Bstatic -u __vectors -u download_entry -N } + +*endfile: +%{!qrtems: %(old_endfile)} \ +%{qrtems: crtend.o%s ecrtn.o%s} diff --git a/c/src/lib/libbsp/powerpc/virtex5/configure.ac b/c/src/lib/libbsp/powerpc/virtex5/configure.ac new file mode 100644 index 0000000000..7abff1b817 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/configure.ac @@ -0,0 +1,48 @@ +dnl Process this file with autoconf to produce a configure script. +dnl +dnl $Id: $ + +AC_PREREQ(2.68) +AC_INIT([rtems-c-src-lib-libbsp-powerpc-virtex5],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([bsp_specs]) +RTEMS_TOP(../../../../../..) + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.11.1]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_CHECK_NETWORKING +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + +RTEMS_BSPOPTS_SET([PPC_USE_DATA_CACHE],[*],[1]) +RTEMS_BSPOPTS_HELP([PPC_USE_DATA_CACHE], +[If defined, then the PowerPC specific code in RTEMS will use + data cache instructions to optimize the context switch code. + This code can conflict with debuggers or emulators. It is known + to break the Corelis PowerPC emulator with at least some combinations + of PowerPC 603e revisions and emulator versions. + The BSP actually contains the call that enables this.]) + +RTEMS_BSPOPTS_SET([PPC_USE_SPRG],[*],[1]) +RTEMS_BSPOPTS_HELP([PPC_USE_SPRG], +[If defined, then the PowerPC specific code in RTEMS will use some + of the special purpose registers to slightly optimize interrupt + response time. The use of these registers can conflict with + other tools like debuggers.]) + +RTEMS_BSPOPTS_SET([PPC_VECTOR_FILE_BASE],[*],[0x0100]) +RTEMS_BSPOPTS_HELP([PPC_VECTOR_FILE_BASE], +[This defines the base address of the exception table.]) + +RTEMS_BSP_CLEANUP_OPTIONS(0, 1) + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) + +RTEMS_PPC_EXCEPTIONS + +AC_OUTPUT diff --git a/c/src/lib/libbsp/powerpc/virtex5/console/dummy_console.c b/c/src/lib/libbsp/powerpc/virtex5/console/dummy_console.c new file mode 100644 index 0000000000..048133d1c2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/console/dummy_console.c @@ -0,0 +1,102 @@ +#include <rtems.h> +#include <rtems/libio.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); +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_control(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) + { + BSP_output_char(*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/c/src/lib/libbsp/powerpc/virtex5/include/bsp.h b/c/src/lib/libbsp/powerpc/virtex5/include/bsp.h new file mode 100644 index 0000000000..1ae242abec --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/include/bsp.h @@ -0,0 +1,82 @@ +/* bsp.h + * + * This include file contains all GEN405 board IO definitions. + * + * derived from helas403/include/bsp.h: + * Id: bsp.h,v 1.4 2001/06/18 17:01:48 joel Exp + * 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. + * + * Derived from c/src/lib/libbsp/no_cpu/no_bsp/include/bsp.h + * + * 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.com/license/LICENSE. + * + * $Id: bsp.h 63 2011-04-26 00:23:51Z claus $ + * + */ + +#ifndef _BSP_H +#define _BSP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <bspopts.h> + +/* + * confdefs.h overrides for this BSP: + * - Interrupt stack space is not minimum if defined. + */ +#define CONFIGURE_INTERRUPT_STACK_MEMORY (16 * 1024) + +#ifdef ASM +/* Definition of where to store registers in alignment handler */ +#define ALIGN_REGS 0x0140 + +#else +#include <rtems.h> +#include <rtems/console.h> +#include <rtems/clockdrv.h> +#include <rtems/iosupp.h> + +/* miscellaneous stuff assumed to exist */ +extern bool bsp_timer_internal_clock; /* TRUE, when timer runs with CPU clk */ + +extern rtems_configuration_table BSP_Configuration; /* owned by BSP */ +#endif /* ASM */ + +void BSP_ask_for_reset(void); +void BSP_panic(char *s); +void _BSP_Fatal_error(unsigned int v); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/virtex5/include/coverhd.h b/c/src/lib/libbsp/powerpc/virtex5/include/coverhd.h new file mode 100644 index 0000000000..50d9606cef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/include/coverhd.h @@ -0,0 +1,133 @@ +/* coverhd.h + * + * This include file has defines to represent the overhead associated + * with calling a particular directive from C. These are used in the + * Timing Test Suite to ignore the overhead required to pass arguments + * to directives. On some CPUs and/or target boards, this overhead + * is significant and makes it difficult to distinguish internal + * RTEMS execution time from that used to call the directive. + * This file should be updated after running the C overhead timing + * test. Once this update has been performed, the RTEMS Time Test + * Suite should be rebuilt to account for these overhead times in the + * timing results. + * + * NOTE: If these are all zero, then the times reported include + * all calling overhead including passing of arguments. + * + * 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.com/license/LICENSE. + * + * $Id: coverhd.h 63 2011-04-26 00:23:51Z claus $ + */ + +/* + * Updated for a 25MHz Papyrus by Andrew Bray <andy@i-cubed.co.uk> + * + * Units are 100ns. + * + * These numbers are of questionable use, as they are developed by calling + * the routine many times, thus getting its entry veneer into the (small) + * cache on the 403GA. This in general is not true of the RTEMS timing + * tests, which usually call a routine only once, thus having no cache loaded + * advantage. + * + * Whether the directive times are useful after deducting the function call + * overhead is also questionable. The user is more interested generally + * in the total cost of a directive, not the cost if the procedure call + * is inlined! (In general this is not true). + * + * Andrew Bray 18/08/1995 + * + */ + +#ifndef __COVERHD_h +#define __COVERHD_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define CALLING_OVERHEAD_INITIALIZE_EXECUTIVE 1 +#define CALLING_OVERHEAD_SHUTDOWN_EXECUTIVE 1 +#define CALLING_OVERHEAD_TASK_CREATE 3 +#define CALLING_OVERHEAD_TASK_IDENT 1 +#define CALLING_OVERHEAD_TASK_START 1 +#define CALLING_OVERHEAD_TASK_RESTART 1 +#define CALLING_OVERHEAD_TASK_DELETE 1 +#define CALLING_OVERHEAD_TASK_SUSPEND 1 +#define CALLING_OVERHEAD_TASK_RESUME 1 +#define CALLING_OVERHEAD_TASK_SET_PRIORITY 1 +#define CALLING_OVERHEAD_TASK_MODE 1 +#define CALLING_OVERHEAD_TASK_GET_NOTE 1 +#define CALLING_OVERHEAD_TASK_SET_NOTE 1 +#define CALLING_OVERHEAD_TASK_WAKE_WHEN 4 +#define CALLING_OVERHEAD_TASK_WAKE_AFTER 1 +#define CALLING_OVERHEAD_INTERRUPT_CATCH 1 +#define CALLING_OVERHEAD_CLOCK_GET 4 +#define CALLING_OVERHEAD_CLOCK_SET 3 +#define CALLING_OVERHEAD_CLOCK_TICK 1 + +#define CALLING_OVERHEAD_TIMER_CREATE 1 +#define CALLING_OVERHEAD_TIMER_IDENT 1 +#define CALLING_OVERHEAD_TIMER_DELETE 1 +#define CALLING_OVERHEAD_TIMER_FIRE_AFTER 2 +#define CALLING_OVERHEAD_TIMER_FIRE_WHEN 5 +#define CALLING_OVERHEAD_TIMER_RESET 1 +#define CALLING_OVERHEAD_TIMER_CANCEL 1 +#define CALLING_OVERHEAD_SEMAPHORE_CREATE 2 +#define CALLING_OVERHEAD_SEMAPHORE_IDENT 1 +#define CALLING_OVERHEAD_SEMAPHORE_DELETE 1 +#define CALLING_OVERHEAD_SEMAPHORE_OBTAIN 1 +#define CALLING_OVERHEAD_SEMAPHORE_RELEASE 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_CREATE 2 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_IDENT 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_DELETE 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_SEND 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_URGENT 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_BROADCAST 1 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_RECEIVE 2 +#define CALLING_OVERHEAD_MESSAGE_QUEUE_FLUSH 1 + +#define CALLING_OVERHEAD_EVENT_SEND 1 +#define CALLING_OVERHEAD_EVENT_RECEIVE 2 +#define CALLING_OVERHEAD_SIGNAL_CATCH 1 +#define CALLING_OVERHEAD_SIGNAL_SEND 1 +#define CALLING_OVERHEAD_PARTITION_CREATE 3 +#define CALLING_OVERHEAD_PARTITION_IDENT 1 +#define CALLING_OVERHEAD_PARTITION_DELETE 1 +#define CALLING_OVERHEAD_PARTITION_GET_BUFFER 1 +#define CALLING_OVERHEAD_PARTITION_RETURN_BUFFER 1 +#define CALLING_OVERHEAD_REGION_CREATE 3 +#define CALLING_OVERHEAD_REGION_IDENT 1 +#define CALLING_OVERHEAD_REGION_DELETE 1 +#define CALLING_OVERHEAD_REGION_GET_SEGMENT 2 +#define CALLING_OVERHEAD_REGION_RETURN_SEGMENT 1 +#define CALLING_OVERHEAD_PORT_CREATE 2 +#define CALLING_OVERHEAD_PORT_IDENT 1 +#define CALLING_OVERHEAD_PORT_DELETE 1 +#define CALLING_OVERHEAD_PORT_EXTERNAL_TO_INTERNAL 1 +#define CALLING_OVERHEAD_PORT_INTERNAL_TO_EXTERNAL 2 + +#define CALLING_OVERHEAD_IO_INITIALIZE 2 +#define CALLING_OVERHEAD_IO_OPEN 2 +#define CALLING_OVERHEAD_IO_CLOSE 2 +#define CALLING_OVERHEAD_IO_READ 2 +#define CALLING_OVERHEAD_IO_WRITE 2 +#define CALLING_OVERHEAD_IO_CONTROL 2 +#define CALLING_OVERHEAD_FATAL_ERROR_OCCURRED 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CREATE 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_IDENT 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_DELETE 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_CANCEL 1 +#define CALLING_OVERHEAD_RATE_MONOTONIC_PERIOD 1 +#define CALLING_OVERHEAD_MULTIPROCESSING_ANNOUNCE 1 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/virtex5/include/irq.h b/c/src/lib/libbsp/powerpc/virtex5/include/irq.h new file mode 100644 index 0000000000..2edf6aa917 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/include/irq.h @@ -0,0 +1,77 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file declares constants of the interrupt controller | +\*===============================================================*/ +#ifndef VIRTEX5_IRQ_IRQ_H +#define VIRTEX5_IRQ_IRQ_H + +#include <rtems/irq.h> + +/* + * the following definitions specify the indices used + * to interface the interrupt handler API + */ + +/* + * Peripheral IRQ handlers related definitions + */ + /* Not supported at this level */ + +/* + * Processor IRQ handlers related definitions + */ +#define BSP_PROCESSOR_IRQ_NUMBER 3 +#define BSP_PROCESSOR_IRQ_LOWEST_OFFSET 0 +#define BSP_PROCESSOR_IRQ_MAX_OFFSET (BSP_PROCESSOR_IRQ_LOWEST_OFFSET\ + +BSP_PROCESSOR_IRQ_NUMBER-1) + +#define BSP_IS_PROCESSOR_IRQ(irqnum) \ + (((irqnum) >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) && \ + ((irqnum) <= BSP_PROCESSOR_IRQ_MAX_OFFSET)) + +/* + * Summary + */ +#define BSP_IRQ_NUMBER (BSP_PROCESSOR_IRQ_MAX_OFFSET+1) +#define BSP_LOWEST_OFFSET BSP_PROCESSOR_IRQ_LOWEST_OFFSET +#define BSP_MAX_OFFSET BSP_PROCESSOR_IRQ_MAX_OFFSET + +#define BSP_IS_VALID_IRQ(irqnum) (BSP_IS_PROCESSOR_IRQ(irqnum)) + +#ifndef ASM +#ifdef __cplusplus +extern "C" { +#endif + +/* + * index table for the module specific handlers, a few entries are only placeholders + */ + typedef enum { + BSP_EXT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 0, + BSP_PIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 1, + BSP_CRIT = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + 2 + } rtems_irq_symbolic_name; + + extern rtems_irq_connect_data *BSP_rtems_irq_tbl; + void BSP_rtems_irq_mngt_init(unsigned cpuId); + +#ifdef __cplusplus +} +#endif +#endif /* ASM */ + +#endif /* VIRTEX5_IRQ_IRQ_H */ diff --git a/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c new file mode 100644 index 0000000000..ffcfe4ca11 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c @@ -0,0 +1,326 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2007 | +| 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.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +#include <libcpu/spr.h> +#include <bsp/irq.h> +#include <bsp.h> +#include <rtems/bspIo.h> +#include <rtems/powerpc/powerpc.h> +#include <bsp/vectors.h> + +static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; +rtems_irq_connect_data *BSP_rtems_irq_tbl; +rtems_irq_global_settings* BSP_rtems_irq_config; + +/*********************************************************** + * dummy functions for on/off/isOn calls + * these functions just do nothing fulfill the semantic + * requirements to enable/disable a certain interrupt or exception + */ +void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +void BSP_irq_nop_hdl(void *hdl) +{ + /* + * nothing to do + */ +} + +int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ + return 0; +} + +/*********************************************************** + * interrupt handler and its enable/disable functions + ***********************************************************/ + +/*********************************************************** + * functions to enable/disable/query external/critical interrupts + */ +void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value &= ~PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +/*********************************************************** + * High level IRQ handler called from shared_raw_irq_code_entry + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + /* + * Handle interrupt + */ + switch(excNum) { + case ASM_EXT_VECTOR: + BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); + break; + case ASM_BOOKE_DEC_VECTOR: + BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle); + break; +#if 0 /* Critical interrupts not yet supported */ + case ASM_BOOKE_CRIT_VECTOR: + BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); + break; +#endif + } + + return 0; +} + +/*********************************************************** + * functions to set/get/remove interrupt handlers + ***********************************************************/ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid irq name + * if invalid, print error and return 0 + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + printk("Invalid interrupt vector %d\n",irq->name); + return 0; + } + + /* + * disable interrupts + */ + rtems_interrupt_disable(level); + + /* + * check, that default handler is installed now + */ + if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { + rtems_interrupt_enable(level); + printk("IRQ vector %d already connected\n",irq->name); + return 0; + } + + /* + * store new handler data + */ + rtemsIrqTbl[irq->name] = *irq; + + /* + * call "on" function to enable interrupt at device + */ + irq->on(irq); + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * return current IRQ entry + */ + *irq = rtemsIrqTbl[irq->name]; + rtems_interrupt_enable(level); + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * check, that specified handler is really connected now + */ + if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { + rtems_interrupt_enable(level); + return 0; + } + + /* + * disable interrupt at source + */ + irq->off(irq); + + /* + * restore default interrupt handler + */ + rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +/*********************************************************** + * functions to set/get the basic interrupt management setup + ***********************************************************/ +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) +{ + *ret_ptr = BSP_rtems_irq_config; + return 0; +} + + +/* + * set management stuff + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + /* + * store given configuration + */ + BSP_rtems_irq_config = config; + BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; + + /* + * store any irq-like processor exceptions + */ + for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; + i < BSP_PROCESSOR_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + if (BSP_rtems_irq_tbl[i].on != NULL) { + BSP_rtems_irq_tbl[i].on + (&(BSP_rtems_irq_tbl[i])); + } + } + else { + if (BSP_rtems_irq_tbl[i].off != NULL) { + BSP_rtems_irq_tbl[i].off + (&(BSP_rtems_irq_tbl[i])); + } + } + } + rtems_interrupt_enable(level); + return 1; +} + +/* + * dummy for an empty IRQ handler entry + */ +static rtems_irq_connect_data emptyIrq = { + 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ +}; + +static rtems_irq_global_settings initialConfig = { + BSP_IRQ_NUMBER, /* irqNb */ + { 0, /* Irq Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ + }, /* emptyIrq */ + rtemsIrqTbl, /* irqHdlTbl */ + 0, /* irqBase */ + NULL /* irqPrioTbl */ +}; + +void BSP_rtems_irq_mngt_init(unsigned cpuId) +{ + int i; + + /* + * connect all exception vectors needed + */ + ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); + ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler); + + /* + * setup interrupt handlers table + */ + for (i = 0; + i < BSP_IRQ_NUMBER; + i++) { + rtemsIrqTbl[i] = emptyIrq; + rtemsIrqTbl[i].name = i; + } + + /* + * initialize interrupt management + */ + if (!BSP_rtems_irq_mngt_set(&initialConfig)) { + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +} diff --git a/c/src/lib/libbsp/powerpc/virtex5/make/custom/virtex5.cfg b/c/src/lib/libbsp/powerpc/virtex5/make/custom/virtex5.cfg new file mode 100644 index 0000000000..b4a7bd3836 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/make/custom/virtex5.cfg @@ -0,0 +1,19 @@ +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU=powerpc +RTEMS_CPU_MODEL=ppc440 + +# This contains the compiler options necessary to select the CPU model +# and (hopefully) optimize for it. +# +CPU_CFLAGS = -mcpu=440 -Dppc440 -msoft-float + +# optimize flag: typically -O2 +CFLAGS_OPTIMIZE_V = -O2 -g -fno-keep-inline-functions + +# Miscellaneous additions go here +define bsp-post-link + $(default-bsp-post-link) + $(OBJCOPY) -O srec $(basename $@).exe $(basename $@)$(DOWNEXT) +endef + diff --git a/c/src/lib/libbsp/powerpc/virtex5/preinstall.am b/c/src/lib/libbsp/powerpc/virtex5/preinstall.am new file mode 100644 index 0000000000..7f0e69881e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/preinstall.am @@ -0,0 +1,75 @@ +## Automatically generated by ampolish3 - Do not edit + +if AMPOLISH3 +$(srcdir)/preinstall.am: Makefile.am + $(AMPOLISH3) $(srcdir)/Makefile.am > $(srcdir)/preinstall.am +endif + +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + +all-local: $(TMPINSTALL_FILES) + +TMPINSTALL_FILES = +CLEANFILES = $(TMPINSTALL_FILES) + +all-am: $(PREINSTALL_FILES) + +PREINSTALL_FILES = +CLEANFILES += $(PREINSTALL_FILES) + +$(PROJECT_LIB)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_LIB) + @: > $(PROJECT_LIB)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) + +$(PROJECT_INCLUDE)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE) + @: > $(PROJECT_INCLUDE)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) + +$(PROJECT_INCLUDE)/bsp/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp + @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp) + +$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs +PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs + +$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h + +$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h + +$(PROJECT_INCLUDE)/coverhd.h: include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h + +$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h + +$(PROJECT_LIB)/rtems_crti.$(OBJEXT): rtems_crti.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/rtems_crti.$(OBJEXT) +TMPINSTALL_FILES += $(PROJECT_LIB)/rtems_crti.$(OBJEXT) + +$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds +PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds + +$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h + +$(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h + +$(PROJECT_INCLUDE)/bsp/irq_supp.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq_supp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq_supp.h + diff --git a/c/src/lib/libbsp/powerpc/virtex5/startup/bspclean.c b/c/src/lib/libbsp/powerpc/virtex5/startup/bspclean.c new file mode 100644 index 0000000000..df2d7af477 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/startup/bspclean.c @@ -0,0 +1,49 @@ +/* bsp_cleanup() + * + * 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.com/license/LICENSE. + */ + +#include <rtems.h> +#include <bsp.h> + +static void _noopfun(void) {} + +void app_bsp_cleanup(void) +__attribute__(( weak, alias("_noopfun") )); + +void bsp_cleanup( void ) +{ + app_bsp_cleanup(); + + /* All done. Hang out. */ + BSP_ask_for_reset(); +} diff --git a/c/src/lib/libbsp/powerpc/virtex5/startup/bspstart.c b/c/src/lib/libbsp/powerpc/virtex5/startup/bspstart.c new file mode 100644 index 0000000000..31872d4a1a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/startup/bspstart.c @@ -0,0 +1,255 @@ +/* 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 + * Modifications for Virtex5 by Richard Claus <claus@slac.stanford.edu> + */ + +#include <string.h> +#include <fcntl.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/vectors.h> +#include <rtems/bspIo.h> +#include <rtems/libio.h> +#include <rtems/libcsupport.h> +#include <rtems/sptables.h> /* for RTEMS_VERSION */ +#include <libcpu/cpuIdent.h> +#include <libcpu/spr.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) + + +/* Expected by clock.c */ +uint32_t bsp_clicks_per_usec; +bool bsp_timer_internal_clock; /* true, when timer runs with CPU clk */ +uint32_t bsp_timer_least_valid; +uint32_t bsp_timer_average_overhead; + + +/* 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); + + +/* + * Provide weak aliases so that RTEMS distribution builds + */ +static void _noopfun(void) {} +static void _bsp_start(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uintptr_t intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + uintptr_t intrStackSize = rtems_configuration_get_interrupt_stack_size(); + + /* + * Initialize default raw exception handlers. + * + * This BSP does not assume anything about firmware possibly loaded in the + * FPGA, so the external interrupt should not be enabled in order to avoid + * spurious interrupts. + */ + sc = ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT & ~MSR_EE, + intrStackStart, + intrStackSize); + if (sc != RTEMS_SUCCESSFUL) BSP_panic("Cannot initialize exceptions"); + + /* Install our own set of exception vectors */ + BSP_rtems_irq_mngt_init(0); +} + + +void app_bsp_start(void) +__attribute__(( weak, alias("_bsp_start") )); + +void app_bsp_pretasking_hook(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(;;); +} + + +void BSP_panic(char *s) +{ + printk("\n%s PANIC %s\n", _RTEMS_version, s); + BSP_ask_for_reset(); +} + + +void _BSP_Fatal_error(unsigned int v) +{ + printk("\n%s FATAL ERROR %x\n", _RTEMS_version, v); + BSP_ask_for_reset(); +} + + +/*===================================================================*/ + +/* + * 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("\nWelcome to RTEMS %s\n", _RTEMS_version ); + + /* + * 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 = 450; + bsp_timer_internal_clock = true; + bsp_timer_average_overhead = 2; + bsp_timer_least_valid = 3; + + /* + * Initialize the interrupt related settings. + */ + intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start); + intrStackSize = rtems_configuration_get_interrupt_stack_size(); + printk(" Base/Start End Size\n" + "RAM: 0x%08x 0x%x\n" + "RTEMS: 0x%08x\n" + "Interrupt Stack: 0x%08x 0x%x\n" + "Stack: 0x%08x 0x%08x 0x%x\n" + "Workspace: 0x%08x 0x%08x\n" + "MsgArea: 0x%08x 0x%x\n" + "Physical RAM 0x%08x\n", + (uint32_t)RamBase, (uint32_t)RamSize, + (uint32_t)__rtems_end, + intrStackStart, intrStackSize, + (uint32_t)__stack_base, (uint32_t)_stack, (uint32_t)StackSize, + (uint32_t)WorkAreaBase, (uint32_t)__bsp_ram_end, + (uint32_t)MsgAreaBase, (uint32_t)MsgAreaSize, + (uint32_t)__phy_ram_end); + + /* Continue with application-specific initialization */ + app_bsp_start(); +} + + +/* + * BSP pretasking hook. Called just before drivers are initialized. + * Used to setup libc and install any BSP extensions. + * + * Must not use libc (to do io) from here, since drivers are not yet + * initialized. + */ + +void bsp_pretasking_hook(void) +{ + app_bsp_pretasking_hook(); +} + + +/* + * BSP predriver hook. Called by boot_card() just before drivers are + * initialized. Clear out any stale interrupts here. + */ +void bsp_predriver_hook(void) +{ + app_bsp_predriver_hook(); +} diff --git a/c/src/lib/libbsp/powerpc/virtex5/startup/dummy_console.c b/c/src/lib/libbsp/powerpc/virtex5/startup/dummy_console.c new file mode 100644 index 0000000000..048133d1c2 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/startup/dummy_console.c @@ -0,0 +1,102 @@ +#include <rtems.h> +#include <rtems/libio.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); +rtems_device_driver console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void* arg); +rtems_device_driver console_control(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) + { + BSP_output_char(*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/c/src/lib/libbsp/powerpc/virtex5/startup/linkcmds b/c/src/lib/libbsp/powerpc/virtex5/startup/linkcmds new file mode 100644 index 0000000000..20d4095d41 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/startup/linkcmds @@ -0,0 +1,264 @@ +/* + * 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) + +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 = 8K + RAM : ORIGIN = 0x00002000, LENGTH = 2048M - 8K +} + + +SECTIONS +{ + __exeentry = download_entry; + __exestart = 0x100; + .vectors __exestart : { *(.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*) } > RAM + .rodata1 : { *(.rodata1) } > RAM + + /* Initialised small data addressed as offsets from r2 */ +_SDA2_BASE_ = __SDATA2_START__ + 0x8000; + .sdata2 : { *(.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.*) + *(.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 */ +_SDA_BASE_ = __SDATA_START__ + 0x8000; + .sdata : { *(.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; +} diff --git a/c/src/lib/libbsp/powerpc/virtex5/startup/start.S b/c/src/lib/libbsp/powerpc/virtex5/startup/start.S new file mode 100644 index 0000000000..1afa587ab3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/virtex5/startup/start.S @@ -0,0 +1,454 @@ +/*!@file start.S +* +* @brief Initialization code to set up the CPU and call boot_card() +* +* This "BSP" targets the Xilinx Virtex XC5VFX70T and related parts. This +* BSP makes no assumptions on what firmware is loaded into the FPGA. +* +* Provides the .entry section code. This is the first code to run in +* the PPC after download to RAM. Excecution in this case starts at +* 'download_entry'. +* +* The entrypoint 'start' is provided for the case where a bootloader has +* initialized the CPU, and all that remains to do is to set up a C +* environment and call boot_card. +* +* Derived from virtex dlentry and others. +* +* Some portions of this code follow section 3.4 of the PPC440x5 CPU Core User's +* Manual v7.1 from IBM. Other parts were derived from examples provided +* by Xilinx in their ML510 Reference Designs, e.g., ml510_bsb1_design_ppc440. +* See boot.S in standalone/, for example. +* +* References: +* Embedded Processor Block in Virtex-5 FPGAs Reference Guide UG200 (v1.8) +* http://www.xilinx.com/support/documentation/user_guides/ug200.pdf +* +* PowerPC 440x5 Embedded Processor Core User's Manual (Version 7.1) +* https://www-01.ibm.com/chips/techlib/techlib.nsf/products/PowerPC_440_Embedded_Core +* +* @author Richard Claus <claus@SLAC.Stanford.edu> +* +* @date March 4, 2011 -- Created +* +* $Revision: 675 $ +* +* @verbatim Copyright 2011 +* by +* The Board of Trustees of the +* Leland Stanford Junior University. +* All rights reserved. +* +* Work supported by the U.S. Department of Energy under contract +* DE-AC03-76SF00515. +* +* Disclaimer Notice +* +* The items furnished herewith were developed under the sponsorship +* of the U.S. Government. Neither the U.S., nor the U.S. D.O.E., nor the +* Leland Stanford Junior University, nor their employees, makes any war- +* ranty, express or implied, or assumes any liability or responsibility +* for accuracy, completeness or usefulness of any information, apparatus, +* product or process disclosed, or represents that its use will not in- +* fringe privately-owned rights. Mention of any product, its manufactur- +* er, or suppliers shall not, nor is it intended to, imply approval, dis- +* approval, or fitness for any particular use. The U.S. and the Univer- +* sity at all times retain the right to use and disseminate the furnished +* items for any purpose whatsoever. Notice 91 02 01 +* +* @endverbatim +*/ + +#include <rtems/asm.h> +#include <rtems/powerpc/powerpc.h> + +#define V_TS_SZ_I 0x0290 // V,TS=0(Inst),SIZE=9,TID=0 +#define V_TS_SZ_D 0x0390 // V,TS=1(Data),SIZE=9,TID=0 +#define WIMG_U_S_0 0x043F // !(U0-3),!W, I,!M,!G,!E,UX,UW,UR,SX,SW,SR +#define WIMG_U_S_1 0x003F // !(U0-3),!W,!I,!M,!G,!E,UX,UW,UR,SX,SW,SR +#define PAGE_SZ 0x10000000 // 256 MB + +/* + * The virtex ELF link scripts support some special sections: + * .entry The actual entry point + * .vectors The section containing the interrupt entry veneers. + */ + +/* + * Downloaded code loads the vectors separately to 0x00000100, + * so .entry can be over 256 bytes. + * + * The other sections are linked in the following order: + * .entry + * .text + * .data + * .bss + * see linker command file for section placement + * + * The initial stack is set to __stack_base + * + * All the entry veneer has to do is to clear the BSS. + */ + + .section .entry + + PUBLIC_VAR(download_entry) + PUBLIC_VAR(__rtems_entry_point) +SYM(download_entry): +SYM(__rtems_entry_point): + b startupDL /* Entry point used by xmd dow command */ + + PUBLIC_VAR (start) +SYM(start): + b startupBL /* Entry point used by bootLoader */ + +base_addr: + /*------------------------------------------------------------------- + * Parameters from linker + *-----------------------------------------------------------------*/ +toc_pointer: + .long __got_start +bss_length: + .long __bss_size +bss_addr: + .long __bss_start +stack_top: + .long __stack_base + + + .eject + + /*------------------------------------------------------------------ + * This code follows section 3.4 of the PPC440x5 CPU Core User's + * Manual. The numbers in the comments refer to the step numbers + * therein. Some of the implementation comes from examples provided + * by Xilinx in their ML510 Reference Designs, e.g., + * ml510_bsb1_design_ppc440. See boot.S in standalone/. + *------------------------------------------------------------------*/ + /*------------------------------------------------------------------ + * This code is designed to accomodate warm restarts, in which the + * application software triggers the restart of the system by branching + * to the following code (either boot or boot1) without causing + * one of the hardware resets: core, chip, system or JTAG (section + * 3.2,3 in the Power PC 440-S Embedded Processor Core User's Manual). + *-----------------------------------------------------------------*/ + + /* ----------------------------------------------------------------- + * Setup CPU + *-----------------------------------------------------------------*/ +first: li r0,0 // Clear r0 + + /* ----------------------------------------------------------------- + * Initialize the memory system. + *------------------------------------------------------------------*/ + iccci r0,r0 // 2. Invalidate instruction cache + dccci r0,r0 // 3. Invalidate data cache + msync // 4. Force in-progress data PLB ops to complete + + mfdbcr0 r2 // 5. Disable all debug events + lis r3,0x8100 + and r2,r2,r3 // Ignore EDM,TRAP to allow XMD use + mtdbcr0 r2 + li r2,-1 + mtdbsr r2 // 6. Initialize all debug event status + + /*------------------------------------------------------------------ + * Set Core Configuration Register 0 as follows: + * sum: 0x00200000 + * bit 1 off Parity Recovery Enable + * bit 4 off Cache Read Parity Enable + * bit 10 on Disable Store Gathering + * bit 11 off Disable APU Instruction Broadcast + * bit 16 off Disable Trace Broadcast + * bit 17:18 off Specifies behaviour of icbt,dcbt/dcbtst insts + * bit 23 off Force Load/Store Alignment + * bit 28:29 off Instruction Cache Speculative Line Count + * bit 30:31 off Instruction Cache Speculative Line Threshold + * NB: UG200/pg 21: Spec. prefetching must be disabled + *------------------------------------------------------------------*/ + + lis r2,0x0020 // 7. Set CCR0: DSTG + mtccr0 r2 // Configure CCR0 + + mtspr ccr1,r0 // 8. Clear CCR1 + + /*------------------------------------------------------------------ + * 9. Configure cache regions + *------------------------------------------------------------------*/ + mtspr inv0,r0 + mtspr inv1,r0 + mtspr inv2,r0 + mtspr inv3,r0 + mtspr dnv0,r0 + mtspr dnv1,r0 + mtspr dnv2,r0 + mtspr dnv3,r0 + mtspr itv0,r0 + mtspr itv1,r0 + mtspr itv2,r0 + mtspr itv3,r0 + mtspr dtv0,r0 + mtspr dtv1,r0 + mtspr dtv2,r0 + mtspr dtv3,r0 + + /*------------------------------------------------------------------ + * Cache victim limits + * floors 0, ceiling max to use the entire cache -- nothing locked + *------------------------------------------------------------------*/ + lis r2, 0x0001f800@h + ori r2,r2,0x0001f800@l + mtspr ivlim,r2 + mtspr dvlim,r2 + + /*------------------------------------------------------------------ + * Configure instruction and data cache regions: + * Set up register constants (r6,r7), page index (r5), address + * variable (r4), EPN_V_TS bits (r3) + * + * Word 0 bits: 0xX0000290, 0xX0000390 + * Bits Field Inst Data Description + * 0:21 EPN 0-15 0-15 Effective Page Number + * 22 V 1 1 Valid + * 23 TS 0 1 Translation Address Space + * 24:27 SIZE 9 9 Page Size (9 = 256 MB) + * 38:31 TPAR 0 0 Tag Parity + * 32:39 TID 0 0 Translation ID (in the MMUCR) + * + * Word 1 bits: 0x00000000, 0x00000000 + * Bits Field Inst Data Description + * 0:21 RPN 0 0 Real Page Number + * 22:23 PAR1 0 0 Parity for TLB word 1 + * 28:31 ERPN 0 0 Extended Real Page Number + * + * Word 2 bits: 0x0000043f, 0x00000c3f + * Bits Field Inst Data Description + * 0: 1 PAR2 0 0 Parity for TLB word 2 + * 16 U0 0 0 User-Defineable Storage Attribute 0 + * 17 U1 0 0 User-Defineable Storage Attribute 1 + * 18 U2 0 0 User-Defineable Storage Attribute 2 + * 19 U3 0 0 User-Defineable Storage Attribute 3 + * 20 W 0 0 Write-Through + * 21 I 1 1 Caching Inhibited + * 22 M 0 0 Memory Coherence Required + * 23 G 0 0 Guarded + * 24 E 0 0 Endian + * 26 UX 1 1 User State Execute Enable + * 27 UW 1 1 User State Write Enable + * 28 UR 1 1 User State Read Enable + * 29 SX 1 1 Supervisor State Execute Enable + * 30 SW 1 1 Supervisor State Write Enable + * 31 SR 1 1 Supervisor State Read Enable + *------------------------------------------------------------------*/ + + mtspr mmucr,r0 // 10a. Clear MMUCR + li r7,WIMG_U_S_1 // Word 2: Pages are NOT cache inhibited + lis r6, PAGE_SZ@h // Page size constant + ori r6,r6,PAGE_SZ@l + mr r5,r0 // TLB entry index + mr r4,r0 // Initialize RPN to zero + mflr r28 // Save return address + bl tlbSetup // 10b. Set up the TLBs + mtlr r28 // Restore return address + + /*------------------------------------------------------------------ + * Select whether Wait Enable, interrupts/exceptions and which address + * spaces should be enabled when application starts + *------------------------------------------------------------------*/ + lis r0, 0x00000000@h // 10d. MSR[IS]=0 MSR[DS]=0 + ori r0,r0,0x00000000@l + mtsrr1 r0 + mtsrr0 r28 // Return address + rfi // Context synchronize to invalidate shadow TLB contents + + + /*------------------------------------------------------------------- + * Entry point used when downloaded, e.g. through XMD + *------------------------------------------------------------------*/ +startupDL: + /*------------------------------------------------------------------- + * Do initialization up to the point where a context sync is required + *------------------------------------------------------------------*/ + bl first // Do first things first + + /*------------------------------------------------------------------- + * 11. Tell the processor where the exception vector table will be + *------------------------------------------------------------------*/ + .extern SYM(__vectors) + lis r2, __vectors@h /* set EVPR exc. vector prefix */ + mtspr ivpr,r2 + + /*------------------------------------------------------------------ + * Set up default exception and interrupt vectors + *------------------------------------------------------------------*/ + li r1,0x100 + mtivor0 r1 + addi r1,r1,0x100 + mtivor1 r1 + addi r1,r1,0x100 + mtivor2 r1 + addi r1,r1,0x100 + mtivor3 r1 + addi r1,r1,0x100 + mtivor4 r1 + addi r1,r1,0x100 + mtivor5 r1 + addi r1,r1,0x100 + mtivor6 r1 + addi r1,r1,0x100 + mtivor7 r1 + addi r1,r1,0x100 + mtivor8 r1 + addi r1,r1,0x100 + mtivor9 r1 + addi r1,r1,0x100 + mtivor10 r1 + addi r1,r1,0x100 + mtivor11 r1 + addi r1,r1,0x100 + mtivor12 r1 + addi r1,r1,0x100 + mtivor13 r1 + addi r1,r1,0x100 + mtivor14 r1 + addi r1,r1,0x100 + mtivor15 r1 + + /*------------------------------------------------------------------ + * 12. Configure debug facilities + *------------------------------------------------------------------*/ + mtdbcr1 r0 + mtdbcr2 r0 + mtiac1 r0 + mtiac2 r0 + mtiac3 r0 + mtiac4 r0 + mtdac1 r0 + mtdac2 r0 + mtdvc1 r0 + mtdvc2 r0 + mfdbcr0 r2 // Freeze timers on debug events + ori r2,r2,0x0001 + mtdbcr0 r2 + isync + + /*------------------------------------------------------------------- + * 13. Configure timer facilities + *------------------------------------------------------------------*/ + mtdec r0 // Clear Decrementer to prevent exception + mttbu r0 // Clear Timebase to prevent Fixed Interval.. + mttbl r0 // ..timer and Watchdog Timer exceptions + mtpit r0 // Programmable interval timer + li r1,-1 // -1 to clear TSR + mttsr r1 // Timer status register + + /*------------------------------------------------------------------- + * Clear out stale values in certain registers to avoid confusion + *------------------------------------------------------------------*/ + li r0,0 + mtcrf 0xff,r0 // Need for simulation + mtctr r0 // Counter register + mtxer r0 // Fixed-point exception register + mtesr r0 // Exception syndrome register + mtdear r0 // Data exception address register + mtmcsr r0 // Machine check syndrome register + + /* Fall through */ + + /* ------------------------------------------------------------------- + * If a bootloader has run that has already initialized the CPU, + * which among other things has loaded this code into memory and + * jumped to start above, the initialization above does not need + * to be redone. Execution thus resumes here. + *------------------------------------------------------------------*/ + +startupBL: + /*------------------------------------------------------------------- + * Load the parameter table base address + *------------------------------------------------------------------*/ + lis r1, base_addr@h + ori r1,r1,base_addr@l + + /*------------------------------------------------------------------- + * Setup stack for RTEMS and call boot_card(). From this + * point forward registers will be used in accordance with the + * PowerPC EABI. + * + * boot_card() supervises the initialization of RTEMS and the C + * library. It calls bsp_start(), bsp_pretasking_hook(), etc. + *------------------------------------------------------------------*/ + lwz r2,toc_pointer-base_addr(r1) /* set r2 to toc */ + lwz r1,stack_top-base_addr(r1) /* set r1 to stack_top */ + + /* Align as required by ABI */ + li r3,PPC_STACK_ALIGNMENT-1 + andc r1,r1,r3 + + /*------------------------------------------------------------------- + * Set up r2 and r13. Upon entry r1 must have a nonzero value + * as it will be stored in an "init done" flag. Stupid but true. + * r1 must also be set up as a stack pointer as __eabi() jumps + * to __init() which has a standard function prolog. + *------------------------------------------------------------------*/ + bl __eabi /* setup EABI and SYSV environment */ + + /*------------------------------------------------------------------- + * Zero the .bss, .sbss and .sbss2 sections. + * Must have r2 and r13 properly set. + *------------------------------------------------------------------*/ + bl zero_bss /* Assume Bank regs set up..., cache etc. */ + + /*------------------------------------------------------------------- + * Create a minimal stack frame for this code, the caller of boot_card(). + *------------------------------------------------------------------*/ + addi r1,r1,-PPC_MINIMUM_STACK_FRAME_SIZE + + xor r3,r3,r3 /* Clear r3 */ + stw r3,0(r1) /* Clear stack chain */ + stw r3,4(r1) + stw r3,8(r1) + stw r3,12(r1) + lis r5,environ@ha + la r5,environ@l(r5) /* environp */ + + /*------------------------------------------------------------------- + * Call boot_card() with its arguments, the command-line pointer and + * the argument count, set to NULL. + *------------------------------------------------------------------*/ + li r4,0 /* argv */ + li r3,0 /* argc */ + .extern SYM (boot_card) + b SYM (boot_card) /* call the first C routine */ + + + .eject + + /*------------------------------------------------------------------ + * Set up TLB entries: 2 entries are needed for the same 256MB page + * one for instruction memory and the other for data memory. + * (TS bit=0 for instructions) + *------------------------------------------------------------------*/ +tlbSetup: +1: ori r3,r4,V_TS_SZ_I // Fold V_TS_SZ in with EPN=RPN + tlbwe r3,r5,0 // Word 0: EPN_V_TS_SZ (Instructions) + tlbwe r4,r5,1 // Word 1: RPN_ERPN + tlbwe r7,r5,2 // Word 2: WIMG_U_S + ori r3,r4,V_TS_SZ_D // Fold V_TS_SZ in with EPN=RPN + addi r5,r5,1 // Next TLB entry + tlbwe r3,r5,0 // Word 0: EPN_V_TS_SZ (Data) + tlbwe r4,r5,1 // Word 1: RPN_ERPN + tlbwe r7,r5,2 // Word 2: WIMG_U_S + add r4,r4,r6 // Increment RPN to next 256MB block + addi r5,r5,1 // Next TLB entry + cmpwi r5,32 // Done yet? + bne 1b + li r0,0 +2: // Zero out index 32-63 TLB entries + tlbwe r0,r5,0 + tlbwe r0,r5,1 + tlbwe r0,r5,2 + addi r5,r5,1 + cmpwi r5,64 + bne 2b + + blr diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am index 67eb8790d2..d01b91776f 100644 --- a/c/src/lib/libcpu/powerpc/Makefile.am +++ b/c/src/lib/libcpu/powerpc/Makefile.am @@ -94,7 +94,7 @@ include_libcpu_HEADERS += shared/src/stackTrace.h endif EXTRA_DIST += ppc403/README ppc403/vectors/README -if ppc403 +if ppc4xx # ppc403/clock noinst_PROGRAMS += ppc403/clock.rel ppc403_clock_rel_SOURCES = ppc403/clock/clock.c @@ -132,7 +132,7 @@ ppc403_tty_drv_rel_CPPFLAGS = $(AM_CPPFLAGS) ppc403_tty_drv_rel_LDFLAGS = $(RTEMS_RELLDFLAGS) endif -endif # ppc403 +endif # ppc4xx if ppc405 diff --git a/c/src/lib/libcpu/powerpc/README b/c/src/lib/libcpu/powerpc/README index 57ac52a9fa..820deb1b2f 100644 --- a/c/src/lib/libcpu/powerpc/README +++ b/c/src/lib/libcpu/powerpc/README @@ -22,6 +22,7 @@ family members using the new exception processing model: + mpc860 + mpc8260 + ppc405 + + ppc440 Note that because of similarities in various family members, the mpc823 should be able to use the mpc821 code and the diff --git a/c/src/lib/libcpu/powerpc/configure.ac b/c/src/lib/libcpu/powerpc/configure.ac index a77b907206..4fe697645d 100644 --- a/c/src/lib/libcpu/powerpc/configure.ac +++ b/c/src/lib/libcpu/powerpc/configure.ac @@ -41,6 +41,7 @@ AM_CONDITIONAL(shared, \ || test "$RTEMS_CPU_MODEL" = "ppc603e" \ || test "$RTEMS_CPU_MODEL" = "ppc403" \ || test "$RTEMS_CPU_MODEL" = "ppc405" \ +|| test "$RTEMS_CPU_MODEL" = "ppc440" \ || test "$RTEMS_CPU_MODEL" = "mpc604" \ || test "$RTEMS_CPU_MODEL" = "mpc6xx" \ || test "$RTEMS_CPU_MODEL" = "mpc8xx" \ @@ -74,10 +75,13 @@ AM_CONDITIONAL(mpc8260, test "$RTEMS_CPU_MODEL" = "mpc8260") AM_CONDITIONAL(mpc83xx, test "$RTEMS_CPU_MODEL" = "mpc83xx") AM_CONDITIONAL(qoriq, test "$RTEMS_CPU_MODEL" = "qoriq") -# the ppc405 shares files with the ppc403 -AM_CONDITIONAL(ppc403,[test "$RTEMS_CPU_MODEL" = "ppc403" \ -|| test "$RTEMS_CPU_MODEL" = "ppc405"]) +# the ppc405 and ppc440 share files with the ppc403 +AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403") AM_CONDITIONAL(ppc405, test "$RTEMS_CPU_MODEL" = "ppc405") +AM_CONDITIONAL(ppc440, test "$RTEMS_CPU_MODEL" = "ppc440") +AM_CONDITIONAL(ppc4xx, test "$RTEMS_CPU_MODEL" = "ppc403" \ +|| test "$RTEMS_CPU_MODEL" = "ppc405" \ +|| test "$RTEMS_CPU_MODEL" = "ppc440") AM_CONDITIONAL(e500, test "$RTEMS_CPU_MODEL" = "e500" \ || test "$RTEMS_CPU_MODEL" = "qoriq" ) diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c index f13d720dce..260270dfba 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_categories.c @@ -56,10 +56,10 @@ static const ppc_exc_categories ppc_405_category_table = { [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC, [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC, - [ASM_PPC405_APU_UNAVAIL_VECTOR] = PPC_EXC_CLASSIC, - [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC, + [ASM_PPC405_APU_UNAVAIL_VECTOR] = PPC_EXC_CLASSIC, + [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_405_CRITICAL | PPC_EXC_ASYNC, @@ -68,6 +68,25 @@ static const ppc_exc_categories ppc_405_category_table = { [ASM_TRACE_VECTOR] = PPC_EXC_405_CRITICAL, }; +static const ppc_exc_categories ppc_booke_category_table = { + [ASM_BOOKE_CRIT_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC, + [ASM_MACH_VECTOR] = PPC_EXC_E500_MACHCHK, + [ASM_PROT_VECTOR] = PPC_EXC_CLASSIC, + [ASM_ISI_VECTOR] = PPC_EXC_CLASSIC, + [ASM_EXT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, + [ASM_ALIGN_VECTOR] = PPC_EXC_CLASSIC, + [ASM_PROG_VECTOR] = PPC_EXC_CLASSIC, + [ASM_FLOAT_VECTOR] = PPC_EXC_CLASSIC, + [ASM_SYS_VECTOR] = PPC_EXC_CLASSIC, + [ASM_BOOKE_APU_VECTOR] = PPC_EXC_CLASSIC, + [ASM_BOOKE_DEC_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, + [ASM_BOOKE_FIT_VECTOR] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, + [ASM_BOOKE_WDOG_VECTOR] = PPC_EXC_BOOKE_CRITICAL | PPC_EXC_ASYNC, + [ASM_BOOKE_DTLBMISS_VECTOR] = PPC_EXC_CLASSIC, + [ASM_BOOKE_ITLBMISS_VECTOR] = PPC_EXC_CLASSIC, + [ASM_BOOKE_DEBUG_VECTOR] = PPC_EXC_BOOKE_CRITICAL, +}; + static const ppc_exc_categories mpc_5xx_category_table = { [ASM_RESET_VECTOR] = PPC_EXC_CLASSIC, [ASM_MACH_VECTOR] = PPC_EXC_CLASSIC, @@ -286,6 +305,8 @@ const ppc_exc_categories *ppc_exc_categories_for_cpu(ppc_cpu_id_t cpu) case PPC_405GP: case PPC_405EX: return &ppc_405_category_table; + case PPC_440: + return &ppc_booke_category_table; default: break; } diff --git a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c index 5d40090fc5..c807bbadcd 100644 --- a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c +++ b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c @@ -1,12 +1,17 @@ -/* clock.c +/** + * @file * * This routine initializes the interval timer on the - * PowerPC 403 CPU. The tick frequency is specified by the bsp. - * + * PowerPC 403 CPU. The tick frequency is specified by the BSP. + */ + +/* + * Original PPC403 Code from: * Author: Andrew Bray <andy@i-cubed.co.uk> - * * COPYRIGHT (c) 1995 by i-cubed ltd. * + * Modifications for PPC405GP by Dennis Ehlin + * * 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 @@ -18,22 +23,18 @@ * i-cubed limited makes no representations about the suitability * of this software for any purpose. * - * Derived from c/src/lib/libcpu/hppa1.1/clock/clock.c: - * * Modifications for deriving timer clock from cpu system clock by * Thomas Doerfler <td@imd.m.isar.de> * for these modifications: * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. * - * COPYRIGHT (c) 1989-2007. + * COPYRIGHT (c) 1989-2012. * 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.com/license/LICENSE. * - * Modifications for PPC405GP by Dennis Ehlin - * * $Id$ */ @@ -62,231 +63,244 @@ static bool auto_restart; void Clock_exit( void ); -rtems_isr_entry set_vector( /* returns old vector */ - rtems_isr_entry handler, /* isr routine */ - rtems_vector_number vector, /* vector number */ - int type /* RTEMS or RAW intr */ -); - static inline uint32_t get_itimer(void) { - register uint32_t rc; + register uint32_t rc; #ifndef ppc405 /* this is a ppc403 */ - __asm__ volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */ + __asm__ volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */ #else /* ppc405 */ - __asm__ volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */ + __asm__ volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */ #endif /* ppc405 */ - return rc; + return rc; } /* * ISR Handler */ - void Clock_isr(void* handle) { - uint32_t clicks_til_next_interrupt; + uint32_t clicks_til_next_interrupt; #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) - uint32_t l_orig = _ISR_Get_level(); + uint32_t l_orig = _ISR_Get_level(); +#endif + + if (!auto_restart) { + uint32_t itimer_value; + /* + * setup for next interrupt; making sure the new value is reasonably + * in the future.... in case we lost out on an interrupt somehow + */ + itimer_value = get_itimer(); + tick_time += pit_value; + + /* + * how far away is next interrupt *really* + * It may be a long time; this subtraction works even if + * Clock_clicks_interrupt < Clock_clicks_low_order via + * the miracle of unsigned math. + */ + clicks_til_next_interrupt = tick_time - itimer_value; + + /* + * If it is too soon then bump it up. + * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small. + * But setting it low is useful for debug, so... + */ + + if (clicks_til_next_interrupt < 400) { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should be rare */ + } + + /* + * If it is too late, that means we missed the interrupt somehow. + * Rather than wait 35-50s for a wrap, we just fudge it here. + */ + + if (clicks_til_next_interrupt > pit_value) { + tick_time = itimer_value + 1000; + clicks_til_next_interrupt = 1000; + /* XXX: count these! this should never happen :-) */ + } + +#ifndef ppc440 + __asm__ volatile ("mtspr 0x3db, %0" :: "r" + (clicks_til_next_interrupt)); /* PIT */ +#else + __asm__ volatile ("mtspr 0x016, %0" :: "r" + (clicks_til_next_interrupt)); /* Decrementer */ #endif - if (!auto_restart) - { - uint32_t itimer_value; - /* - * setup for next interrupt; making sure the new value is reasonably - * in the future.... in case we lost out on an interrupt somehow - */ - - itimer_value = get_itimer(); - tick_time += pit_value; - - /* - * how far away is next interrupt *really* - * It may be a long time; this subtraction works even if - * Clock_clicks_interrupt < Clock_clicks_low_order via - * the miracle of unsigned math. - */ - clicks_til_next_interrupt = tick_time - itimer_value; - - /* - * If it is too soon then bump it up. - * This should only happen if CPU_HPPA_CLICKS_PER_TICK is too small. - * But setting it low is useful for debug, so... - */ - - if (clicks_til_next_interrupt < 400) - { - tick_time = itimer_value + 1000; - clicks_til_next_interrupt = 1000; - /* XXX: count these! this should be rare */ - } - - /* - * If it is too late, that means we missed the interrupt somehow. - * Rather than wait 35-50s for a wrap, we just fudge it here. - */ - - if (clicks_til_next_interrupt > pit_value) - { - tick_time = itimer_value + 1000; - clicks_til_next_interrupt = 1000; - /* XXX: count these! this should never happen :-) */ - } - - __asm__ volatile ("mtspr 0x3db, %0" :: "r" - (clicks_til_next_interrupt)); /* PIT */ } +#ifndef ppc440 __asm__ volatile ( "mtspr 0x3d8, %0" :: "r" (0x08000000)); /* TSR */ +#else /* Book E */ + __asm__ volatile ( "mtspr 0x150, %0" :: "r" (0x08000000)); /* TSR */ +#endif - Clock_driver_ticks++; - - /* Give BSP a chance to say if they want to re-enable interrupts */ + Clock_driver_ticks++; + /* Give BSP a chance to say if they want to re-enable interrupts */ #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) - _ISR_Set_level(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL); + _ISR_Set_level(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL); #endif - - rtems_clock_tick(); + rtems_clock_tick(); #if defined(BSP_PPC403_CLOCK_ISR_IRQ_LEVEL) - _ISR_Set_level(l_orig) + _ISR_Set_level(l_orig) #endif } int ClockIsOn(const rtems_irq_connect_data* unused) { - register uint32_t tcr; + register uint32_t tcr; - __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ +#ifndef ppc440 + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ +#else /* Book E */ + __asm__ volatile ("mfspr %0, 0x154" : "=r" ((tcr))); /* TCR */ +#endif - return (tcr & 0x04000000) != 0; + return (tcr & 0x04000000) != 0; } -void ClockOff( - const rtems_irq_connect_data* unused -) +void ClockOff(const rtems_irq_connect_data* unused) { - register uint32_t tcr; - - __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ - - tcr &= ~ 0x04400000; - - __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ + register uint32_t tcr; + +#ifndef ppc440 + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + tcr &= ~ 0x04400000; + __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +#else /* Book E */ + __asm__ volatile ("mfspr %0, 0x154" : "=r" ((tcr))); /* TCR */ + tcr &= ~ 0x04400000; + __asm__ volatile ("mtspr 0x154, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +#endif } -void ClockOn( - const rtems_irq_connect_data* unused -) +void ClockOn(const rtems_irq_connect_data* unused) { - uint32_t iocr; - register uint32_t tcr; -#ifndef ppc405 - uint32_t pvr; + uint32_t iocr; + register uint32_t tcr; +#ifdef ppc403 + uint32_t pvr; #endif /* ppc403 */ - Clock_driver_ticks = 0; + Clock_driver_ticks = 0; -#ifndef ppc405 /* this is a ppc403 */ - __asm__ volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */ - if (bsp_timer_internal_clock) { - iocr &= ~4; /* timer clocked from system clock */ - } - else { - iocr |= 4; /* select external timer clock */ - } - __asm__ volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */ +#ifdef ppc403 /* this is a ppc403 */ + __asm__ volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */ + if (bsp_timer_internal_clock) { + iocr &= ~4; /* timer clocked from system clock */ + } else { + iocr |= 4; /* select external timer clock */ + } + __asm__ volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */ - __asm__ volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */ - if (((pvr & 0xffff0000) >> 16) != 0x0020) - return; /* Not a ppc403 */ + __asm__ volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */ + if (((pvr & 0xffff0000) >> 16) != 0x0020) + return; /* Not a ppc403 */ - if ((pvr & 0xff00) == 0x0000) /* 403GA */ + if ((pvr & 0xff00) == 0x0000) /* 403GA */ #if 0 /* FIXME: in which processor versions will "autoload" work properly? */ - auto_restart = (pvr & 0x00f0) > 0x0000 ? true : false; + auto_restart = (pvr & 0x00f0) > 0x0000 ? true : false; #else - /* no known chip version supports auto restart of timer... */ - auto_restart = false; + /* no known chip version supports auto restart of timer... */ + auto_restart = false; #endif - else if ((pvr & 0xff00) == 0x0100) /* 403GB */ - auto_restart = true; - -#else /* ppc405 */ - __asm__ volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */ - if (bsp_timer_internal_clock) { - iocr &=~0x800000 ;/* timer clocked from system clock CETE*/ - } - else { - iocr |= 0x800000; /* select external timer clock CETE*/ - } - __asm__ volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */ - - /* - * Enable auto restart - */ - - auto_restart=true; - -#endif /* ppc405 */ - pit_value = rtems_configuration_get_microseconds_per_tick() * - bsp_clicks_per_usec; - - /* - * Set PIT value - */ - - __asm__ volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ - - /* - * Set timer to autoreload, bit TCR->ARE = 1 0x0400000 - * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000 - */ - tick_time = get_itimer() + pit_value; + else if ((pvr & 0xff00) == 0x0100) /* 403GB */ + auto_restart = true; + +#elif defined(ppc405) /* ppc405 */ + __asm__ volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */ + if (bsp_timer_internal_clock) { + iocr &=~0x800000; /* timer clocked from system clock CETE */ + } else { + iocr |= 0x800000; /* select external timer clock CETE */ + } + /* 405GP CPC0_CR1 */ + __asm__ volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); - __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ - tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); -#if 1 - __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ + /* + * Enable auto restart + */ + auto_restart = true; +#else + /* PPC440 */ + __asm__ volatile ("mfspr %0, 0x378" : "=r" (iocr)); /* 440 CCR1 */ + if (bsp_timer_internal_clock) { + iocr &= ~0x00000100; /* timer clocked from system clock CETE */ + } else { + iocr |= 0x00000100; /* select external timer clock CETE */ + } + __asm__ volatile ("mtspr 0x378, %0" : "=r" (iocr) : "0" (iocr)); /*440 CCR1*/ +#endif + pit_value = rtems_configuration_get_microseconds_per_tick() * + bsp_clicks_per_usec; + + /* + * Set PIT value + */ +#ifndef ppc440 + __asm__ volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ +#else /* Book E */ + __asm__ volatile ("mtspr 0x016, %0" : : "r" (pit_value)); /* Decrementer */ #endif + /* + * Set timer to autoreload, bit TCR->ARE = 1 0x0400000 + * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000 + */ + tick_time = get_itimer() + pit_value; + +#ifndef ppc440 + __asm__ volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ + tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); + __asm__ volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +#else /* Book E */ + __asm__ volatile ("mfspr %0, 0x154" : "=r" ((tcr))); /* TCR */ + tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000); + __asm__ volatile ("mtspr 0x154, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */ +#endif } - - void Install_clock( void (*clock_isr)(void *) ) { - rtems_irq_connect_data clockIrqConnData; + rtems_irq_connect_data clockIrqConnData; - Clock_driver_ticks = 0; + Clock_driver_ticks = 0; - /* - * initialize the interval here - * First tick is set to right amount of time in the future - * Future ticks will be incremented over last value set - * in order to provide consistent clicks in the face of - * interrupt overhead - */ + /* + * initialize the interval here + * First tick is set to right amount of time in the future + * Future ticks will be incremented over last value set + * in order to provide consistent clicks in the face of + * interrupt overhead + */ + clockIrqConnData.on = ClockOn; + clockIrqConnData.off = ClockOff; + clockIrqConnData.isOn = ClockIsOn; +#if defined(ppc440) || defined(ppc405) + clockIrqConnData.name = BSP_PIT; +#else + clockIrqConnData.name = BSP_DECREMENTER; +#endif + clockIrqConnData.hdl = clock_isr; + if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) { + printk("Unable to connect Clock Irq handler\n"); + rtems_fatal_error_occurred(1); + } - clockIrqConnData.on = ClockOn; - clockIrqConnData.off = ClockOff; - clockIrqConnData.isOn = ClockIsOn; - clockIrqConnData.name = BSP_PIT; - clockIrqConnData.hdl = clock_isr; - if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) { - printk("Unable to connect Clock Irq handler\n"); - rtems_fatal_error_occurred(1); - } - - atexit(Clock_exit); + atexit(Clock_exit); } -void -ReInstall_clock( +void ReInstall_clock( void (*new_clock_isr)(void *) ) { @@ -295,8 +309,11 @@ ReInstall_clock( rtems_interrupt_disable(isrlevel); - +#if defined(ppc440) || defined(ppc405) clockIrqConnData.name = BSP_PIT; +#else + clockIrqConnData.name = BSP_DECREMENTER; +#endif if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) { printk("Unable to stop system clock\n"); rtems_fatal_error_occurred(1); @@ -307,7 +324,11 @@ ReInstall_clock( clockIrqConnData.on = ClockOn; clockIrqConnData.off = ClockOff; clockIrqConnData.isOn = ClockIsOn; +#if defined(ppc440) || defined(ppc405) clockIrqConnData.name = BSP_PIT; +#else + clockIrqConnData.name = BSP_DECREMENTER; +#endif clockIrqConnData.hdl = new_clock_isr; if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) { @@ -318,7 +339,6 @@ ReInstall_clock( rtems_interrupt_enable(isrlevel); } - /* * Called via atexit() * Remove the clock interrupt handler by setting handler to NULL @@ -326,12 +346,15 @@ ReInstall_clock( * This will not work on the 405GP because * when bit's are set in TCR they can only be unset by a reset */ - void Clock_exit(void) { rtems_irq_connect_data clockIrqConnData; +#if defined(ppc440) || defined(ppc405) clockIrqConnData.name = BSP_PIT; +#else + clockIrqConnData.name = BSP_DECREMENTER; +#endif if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) { printk("Unable to stop system clock\n"); rtems_fatal_error_occurred(1); diff --git a/c/src/lib/libcpu/powerpc/preinstall.am b/c/src/lib/libcpu/powerpc/preinstall.am index c6fbf8e2e0..79b7d88878 100644 --- a/c/src/lib/libcpu/powerpc/preinstall.am +++ b/c/src/lib/libcpu/powerpc/preinstall.am @@ -96,13 +96,13 @@ $(PROJECT_INCLUDE)/libcpu/stackTrace.h: shared/src/stackTrace.h $(PROJECT_INCLUD $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/stackTrace.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/stackTrace.h endif -if ppc403 +if ppc4xx if ppc405 $(PROJECT_INCLUDE)/tty_drv.h: ppc403/tty_drv/tty_drv.h $(PROJECT_INCLUDE)/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tty_drv.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/tty_drv.h endif -endif # ppc403 +endif # ppc4xx if ppc405 $(PROJECT_INCLUDE)/ppc4xx/$(dirstamp): @$(MKDIR_P) $(PROJECT_INCLUDE)/ppc4xx diff --git a/c/src/lib/libcpu/powerpc/rtems/powerpc/debugmod.h b/c/src/lib/libcpu/powerpc/rtems/powerpc/debugmod.h index 692a5643cc..565534fcd8 100644 --- a/c/src/lib/libcpu/powerpc/rtems/powerpc/debugmod.h +++ b/c/src/lib/libcpu/powerpc/rtems/powerpc/debugmod.h @@ -78,7 +78,7 @@ extern "C" { #define PPC_DEBUG_MODEL_SINGLE_STEP_ONLY 2 #define PPC_DEBUG_MODEL_IBM4xx 3 -#elif defined(ppc403) || defined(ppc405) +#elif defined(ppc403) || defined(ppc405) || defined(ppc440) #define PPC_DEBUG_MODEL PPC_DEBUG_MODEL_IBM4xx diff --git a/c/src/lib/libcpu/powerpc/rtems/powerpc/powerpc.h b/c/src/lib/libcpu/powerpc/rtems/powerpc/powerpc.h index 9609fd10d2..092fbf93ec 100644 --- a/c/src/lib/libcpu/powerpc/rtems/powerpc/powerpc.h +++ b/c/src/lib/libcpu/powerpc/rtems/powerpc/powerpc.h @@ -137,6 +137,17 @@ extern "C" { #define PPC_HAS_EXCEPTION_PREFIX 0 #define PPC_HAS_EVPR 1 +#elif defined (ppc440) + +#define PPC_CACHE_ALIGNMENT 32 +#define PPC_HAS_RI 0 +#define PPC_HAS_RFCI 1 +#define PPC_USE_MULTIPLE 1 +#define PPC_I_CACHE 32768 +#define PPC_D_CACHE 32768 +#define PPC_HAS_EXCEPTION_PREFIX 0 +#define PPC_HAS_EVPR 1 + #elif defined(mpc555) /* Copied from mpc505 */ @@ -380,7 +391,7 @@ extern "C" { #define PPC_IRQ_FIRST PPC_IRQ_SYSTEM_RESET -#if defined(ppc403) || defined(ppc405) +#if defined(ppc403) || defined(ppc405) || defined(ppc440) #define PPC_IRQ_CRIT PPC_IRQ_SYSTEM_RESET /*0x00100- Critical int. pin */ #define PPC_IRQ_PIT (PPC_STD_IRQ_LAST+1) /*0x01000- Pgm interval timer*/ diff --git a/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.c b/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.c index 9acdafb696..2c671c6c74 100644 --- a/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.c +++ b/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.c @@ -33,6 +33,7 @@ const char *get_ppc_cpu_type_name(ppc_cpu_id_t cpu) case PPC_405: return "PPC405"; case PPC_405GP: return "PPC405GP"; case PPC_405EX: return "PPC405EX"; + case PPC_440: return "PPC440"; case PPC_601: return "MPC601"; case PPC_5XX: return "MPC5XX"; case PPC_603: return "MPC603"; @@ -104,6 +105,7 @@ ppc_cpu_id_t get_ppc_cpu_type(void) case PPC_405: case PPC_405GP: case PPC_405EX: + case PPC_440: case PPC_601: case PPC_5XX: case PPC_603: @@ -150,7 +152,7 @@ ppc_cpu_id_t get_ppc_cpu_type(void) case PPC_7400: /* NOTE: PSIM PVR doesn't tell us anything (its * contents are not set based on what model - * the uses chooses but has to be programmed via + * the user chooses but has to be programmed via * the device file with the special value 0xfffe * telling us that we have a 'psim cpu'). * @@ -182,6 +184,8 @@ ppc_cpu_id_t get_ppc_cpu_type(void) case PPC_405EX: current_ppc_features.is_bookE = PPC_BOOKE_405; break; + case PPC_440: + current_ppc_features.is_bookE = PPC_BOOKE_STD; case PPC_8540: case PPC_e200z0: case PPC_e200z1: diff --git a/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.h b/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.h index cae5d84ead..d37a6ee50d 100644 --- a/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.h +++ b/c/src/lib/libcpu/powerpc/shared/include/cpuIdent.h @@ -35,12 +35,13 @@ typedef enum PPC_604e = 0x9, PPC_604r = 0xA, PPC_7400 = 0xC, - PPC_405 = 0x2001, + PPC_405 = 0x2001, /* Xilinx Virtex-II Pro or -4 */ PPC_405EX = 0x1291, /* + 405EXr */ PPC_405GP = 0x4011, /* + 405CR */ PPC_405GPr = 0x5091, PPC_405EZ = 0x4151, PPC_405EP = 0x5121, + PPC_440 = 0x7ff2, /* Xilinx Virtex-5*/ PPC_7455 = 0x8001, /* Kate Feng */ PPC_7457 = 0x8002, PPC_620 = 0x16, diff --git a/cpukit/score/cpu/powerpc/rtems/asm.h b/cpukit/score/cpu/powerpc/rtems/asm.h index d54c0607e2..e6b90ece72 100644 --- a/cpukit/score/cpu/powerpc/rtems/asm.h +++ b/cpukit/score/cpu/powerpc/rtems/asm.h @@ -25,7 +25,7 @@ * COPYRIGHT (c) 1994. * On-Line Applications Research Corporation (OAR). * - * $Id$ + * $Id:$ */ #ifndef _RTEMS_ASM_H @@ -204,6 +204,83 @@ #define br5 0x085 /* DCR: memory bank register 5 */ #define br6 0x086 /* DCR: memory bank register 6 */ #define br7 0x087 /* DCR: memory bank register 7 */ + +#elif defined(ppc440) +#define xer 0x001 /* SPR: Integer Exception Register */ +#define lr 0x008 /* SPR: Link Register */ +#define ctr 0x009 /* SPR: Count Register */ +#define pid 0x030 /* SPR: Process ID */ +#define decar 0x036 /* SPR: Decrementer Auto-Reload */ +#define dear 0x03d /* SPR: Data Exception Address Register */ +#define esr 0x03e /* SPR: Exception Syndrome Register */ +#define ivpr 0x03f /* SPR: Interrupt Vector Prefix Register */ +#define sprg4_w 0x104 /* SPR: Special Purpose Register General 4 (WO) */ +#define sprg5_w 0x105 /* SPR: Special Purpose Register General 5 (WO) */ +#define sprg6_w 0x107 /* SPR: Special Purpose Register General 6 (WO) */ +#define sprg7_w 0x108 /* SPR: Special Purpose Register General 7 (WO) */ +#define tbl 0x10c /* SPR: Time Base Lower */ +#define tbu 0x10d /* SPR: Time Base Upper */ +#define pir 0x11e /* SPR: Processor ID Register */ +#define pvr 0x11f /* SPR: Processor Version Register */ +#define dbsr 0x130 /* SPR: Debug Status Register */ +#define dbcr0 0x134 /* SPR: Debug Control Register 0 */ +#define dbcr1 0x135 /* SPR: Debug Control Register 1 */ +#define dbcr2 0x136 /* SPR: Debug Control Register 2 */ +#define iac1 0x138 /* SPR: Instruction Address Compare 1 */ +#define iac2 0x139 /* SPR: Instruction Address Compare 2 */ +#define iac3 0x13a /* SPR: Instruction Address Compare 3 */ +#define iac4 0x13b /* SPR: Instruction Address Compare 4 */ +#define dac1 0x13c /* SPR: Data Address Compare 1 */ +#define dac2 0x13d /* SPR: Data Address Compare 2 */ +#define dvc1 0x13e /* SPR: Data Value Compare 1 */ +#define dvc2 0x13f /* SPR: Data Value Compare 2 */ +#define tsr 0x150 /* SPR: Timer Status Register */ +#define tcr 0x154 /* SPR: Timer Control Register */ +#define ivor0 0x190 /* SPR: Interrupt Vector Offset Register 0 */ +#define ivor1 0x191 /* SPR: Interrupt Vector Offset Register 1 */ +#define ivor2 0x192 /* SPR: Interrupt Vector Offset Register 2 */ +#define ivor3 0x193 /* SPR: Interrupt Vector Offset Register 3 */ +#define ivor4 0x194 /* SPR: Interrupt Vector Offset Register 4 */ +#define ivor5 0x195 /* SPR: Interrupt Vector Offset Register 5 */ +#define ivor6 0x196 /* SPR: Interrupt Vector Offset Register 6 */ +#define ivor7 0x197 /* SPR: Interrupt Vector Offset Register 7 */ +#define ivor8 0x198 /* SPR: Interrupt Vector Offset Register 8 */ +#define ivor9 0x199 /* SPR: Interrupt Vector Offset Register 9 */ +#define ivor10 0x19a /* SPR: Interrupt Vector Offset Register 10 */ +#define ivor11 0x19b /* SPR: Interrupt Vector Offset Register 11 */ +#define ivor12 0x19c /* SPR: Interrupt Vector Offset Register 12 */ +#define ivor13 0x19d /* SPR: Interrupt Vector Offset Register 13 */ +#define ivor14 0x19e /* SPR: Interrupt Vector Offset Register 14 */ +#define ivor15 0x19f /* SPR: Interrupt Vector Offset Register 15 */ +#define mcsr 0x23c /* SPR: Machine Check Status Register */ +#define inv0 0x370 /* SPR: Instruction Cache Normal Victim 0 */ +#define inv1 0x371 /* SPR: Instruction Cache Normal Victim 1 */ +#define inv2 0x372 /* SPR: Instruction Cache Normal Victim 2 */ +#define inv3 0x373 /* SPR: Instruction Cache Normal Victim 3 */ +#define itv0 0x374 /* SPR: Instruction Cache Transient Victim 0 */ +#define itv1 0x375 /* SPR: Instruction Cache Transient Victim 1 */ +#define itv2 0x376 /* SPR: Instruction Cache Transient Victim 2 */ +#define itv3 0x377 /* SPR: Instruction Cache Transient Victim 3 */ +#define ccr1 0x378 /* SPR: Core Configuration Register 1 */ +#define dnv0 0x390 /* SPR: Data Cache Normal Victim 0 */ +#define dnv1 0x391 /* SPR: Data Cache Normal Victim 1 */ +#define dnv2 0x392 /* SPR: Data Cache Normal Victim 2 */ +#define dnv3 0x393 /* SPR: Data Cache Normal Victim 3 */ +#define dtv0 0x394 /* SPR: Data Cache Transient Victim 0 */ +#define dtv1 0x395 /* SPR: Data Cache Transient Victim 1 */ +#define dtv2 0x396 /* SPR: Data Cache Transient Victim 2 */ +#define dtv3 0x397 /* SPR: Data Cache Transient Victim 3 */ +#define dvlim 0x398 /* SPR: Data Cache Victim Limit */ +#define ivlim 0x399 /* SPR: Instruction Cache Victim Limit */ +#define rstcfg 0x39b /* SPR: Reset Configuration */ +#define dcdbtrl 0x39c /* SPR: Data Cache Debug Tag Register Low */ +#define dcdbtrh 0x39d /* SPR: Data Cache Debug Tag Register High */ +#define icdbtrl 0x39e /* SPR: Instruction Cache Debug Tag Register Low */ +#define icdbtrh 0x39f /* SPR: Instruction Cache Debug Tag Register High */ +#define mmucr 0x3b2 /* SPR: Memory Management Unit Control Register */ +#define ccr0 0x3b3 /* SPR: Core Configuration Register 0 */ +#define icdbdr 0x3d3 /* SPR: Instruction Cache Debug Data Register */ +#define dbdr 0x3f3 /* SPR: Debug Data Register */ /* end of IBM400 series register definitions */ #elif defined(mpc555) |