forked from Imagelibrary/rtems
Virtex5 BSP: Various updates and improvements.
This BSP now uses the MPC6xx clock driver instead of a modified PPC403 clock driver. Support for the MMU has been added, but is not enabled by default.
This commit is contained in:
committed by
Sebastian Huber
parent
5b822ab26a
commit
655bd39676
@@ -35,14 +35,14 @@ libbsp_a_SOURCES = startup/bspclean.c \
|
|||||||
startup/bspstart.c \
|
startup/bspstart.c \
|
||||||
../../shared/bootcard.c \
|
../../shared/bootcard.c \
|
||||||
../../shared/sbrk.c \
|
../../shared/sbrk.c \
|
||||||
../../shared/gnatinstallhandler.c
|
../../shared/gnatinstallhandler.c \
|
||||||
|
../shared/src/memcpy.c
|
||||||
|
|
||||||
# start
|
# start
|
||||||
libbsp_a_SOURCES += startup/start.S
|
libbsp_a_SOURCES += startup/start.S
|
||||||
|
|
||||||
# clock & timer
|
# clock & timer
|
||||||
libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/clock/clock.c
|
libbsp_a_SOURCES += ../../powerpc/shared/clock/p_clock.c
|
||||||
libbsp_a_SOURCES += ../../../libcpu/@RTEMS_CPU@/ppc403/timer/timer.c
|
|
||||||
|
|
||||||
# console
|
# console
|
||||||
libbsp_a_SOURCES += startup/dummy_console.c \
|
libbsp_a_SOURCES += startup/dummy_console.c \
|
||||||
@@ -52,6 +52,10 @@ libbsp_a_SOURCES += startup/dummy_console.c \
|
|||||||
include_bsp_HEADERS += include/irq.h
|
include_bsp_HEADERS += include/irq.h
|
||||||
libbsp_a_SOURCES += irq/irq_init.c
|
libbsp_a_SOURCES += irq/irq_init.c
|
||||||
|
|
||||||
|
# mmu
|
||||||
|
include_bsp_HEADERS += include/mmu.h
|
||||||
|
libbsp_a_SOURCES += mmu/mmu.c
|
||||||
|
|
||||||
#vectors
|
#vectors
|
||||||
include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h
|
include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h
|
||||||
include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h
|
include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_supp.h
|
||||||
@@ -59,7 +63,9 @@ include_bsp_HEADERS += ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/irq_s
|
|||||||
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
|
libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
|
../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/shared/cache.rel \
|
../../../libcpu/@RTEMS_CPU@/shared/cache.rel \
|
||||||
../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel
|
../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \
|
||||||
|
../../../libcpu/@RTEMS_CPU@/e500/clock.rel \
|
||||||
|
../../../libcpu/@RTEMS_CPU@/e500/timer.rel
|
||||||
|
|
||||||
EXTRA_DIST = times
|
EXTRA_DIST = times
|
||||||
|
|
||||||
|
|||||||
86
c/src/lib/libbsp/powerpc/virtex5/README
Normal file
86
c/src/lib/libbsp/powerpc/virtex5/README
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# Adapted from virtex BSP
|
||||||
|
|
||||||
|
BSP NAME: virtex5
|
||||||
|
BOARD: N/A
|
||||||
|
BUS: N/A
|
||||||
|
CPU FAMILY: ppc
|
||||||
|
CPU: PowerPC 440x5
|
||||||
|
COPROCESSORS: N/A
|
||||||
|
MODE: 32 bit mode
|
||||||
|
|
||||||
|
DEBUG MONITOR:
|
||||||
|
|
||||||
|
PERIPHERALS
|
||||||
|
===========
|
||||||
|
TIMERS: 440 internal
|
||||||
|
SERIAL PORTS: none
|
||||||
|
REAL-TIME CLOCK: none
|
||||||
|
DMA: Xilinx virtex internal
|
||||||
|
VIDEO: none
|
||||||
|
SCSI: none
|
||||||
|
NETWORKING: none
|
||||||
|
|
||||||
|
DRIVER INFORMATION
|
||||||
|
==================
|
||||||
|
CLOCK DRIVER: PPC Decrementer
|
||||||
|
IOSUPP DRIVER: N/A
|
||||||
|
SHMSUPP: N/A
|
||||||
|
TIMER DRIVER: N/A
|
||||||
|
TTY DRIVER: N/A
|
||||||
|
|
||||||
|
STDIO
|
||||||
|
=====
|
||||||
|
PORT: N/A
|
||||||
|
ELECTRICAL: N/A
|
||||||
|
BAUD: N/A
|
||||||
|
BITS PER CHARACTER: N/A
|
||||||
|
PARITY: N/A
|
||||||
|
STOP BITS: N/A
|
||||||
|
|
||||||
|
Notes
|
||||||
|
=====
|
||||||
|
|
||||||
|
Board description
|
||||||
|
-----------------
|
||||||
|
clock rate: 465 MHz
|
||||||
|
ROM: N/A
|
||||||
|
RAM: 4GByte DRAM
|
||||||
|
|
||||||
|
Virtex only supports single processor operations.
|
||||||
|
|
||||||
|
Porting
|
||||||
|
-------
|
||||||
|
This board support package is written for a naked Virtex 5/PPC FPGA
|
||||||
|
system. The rough features of such a board are described above.
|
||||||
|
The BSP itself makes no assumptions on what is loaded in the FPGA,
|
||||||
|
other than that the CPU has access to some memory, either on-board
|
||||||
|
or external, from which code can be run.
|
||||||
|
|
||||||
|
This BSP has been constructed so that an application of both firmware
|
||||||
|
and software can be layered on top of it by supplying implementations
|
||||||
|
for the various 'weak' symbols. These symbols are prefaced with the
|
||||||
|
term 'app_'. Applications can thus be built outside of the RTEMS
|
||||||
|
directory tree by linking with the appropriate libraries.
|
||||||
|
|
||||||
|
The linkcmds file describes the memory layout. Included in this
|
||||||
|
definition is a section of memory named MsgArea. Output sent to
|
||||||
|
stdout is recorded in this area and can be dumped using the JTAG
|
||||||
|
interface, for example.
|
||||||
|
|
||||||
|
For adapting this BSP to other boards, the following files should be
|
||||||
|
modified:
|
||||||
|
|
||||||
|
- c/src/lib/libbsp/powerpc/virtex5/startup/linkcmds
|
||||||
|
for the memory layout required
|
||||||
|
|
||||||
|
- c/src/lib/libbsp/powerpc/virtex5/startup/bspstart.c
|
||||||
|
Here you can select the clock source for the timers and the
|
||||||
|
serial interface (system clock or external clock pin), the
|
||||||
|
clock rates, etc.
|
||||||
|
|
||||||
|
- c/src/lib/libbsp/powerpc/virtex5/include/bsp.h
|
||||||
|
some BSP-related constants
|
||||||
|
|
||||||
|
- c/src/lib/libbsp/powerpc/virtex5/*
|
||||||
|
well, they should be generic, so there _should_ be no reason
|
||||||
|
to mess around there (but who knows...)
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
#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);
|
|
||||||
}
|
|
||||||
@@ -71,6 +71,10 @@ extern "C" {
|
|||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BSP_DEC BSP_PIT
|
||||||
|
#define BSP_DECREMENTER BSP_PIT
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif /* ASM */
|
#endif /* ASM */
|
||||||
|
|
||||||
|
|||||||
287
c/src/lib/libbsp/powerpc/virtex5/include/mmu.h
Normal file
287
c/src/lib/libbsp/powerpc/virtex5/include/mmu.h
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
#ifndef RTEMS_VIRTEX5_MMU_H
|
||||||
|
#define RTEMS_VIRTEX5_MMU_H
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup Virtex5MMU
|
||||||
|
*
|
||||||
|
* @brief Routines to manipulate the PPC 440 MMU.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Authorship
|
||||||
|
* ----------
|
||||||
|
* This software was created by
|
||||||
|
* Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
|
||||||
|
* Stanford Linear Accelerator Center, Stanford University.
|
||||||
|
* and was transcribed for the PPC 440 by
|
||||||
|
* R. Claus <claus@slac.stanford.edu>, 2012,
|
||||||
|
* Stanford Linear Accelerator Center, Stanford University,
|
||||||
|
*
|
||||||
|
* Acknowledgement of sponsorship
|
||||||
|
* ------------------------------
|
||||||
|
* This software was produced by
|
||||||
|
* the Stanford Linear Accelerator Center, Stanford University,
|
||||||
|
* under Contract DE-AC03-76SFO0515 with the Department of Energy.
|
||||||
|
*
|
||||||
|
* Government disclaimer of liability
|
||||||
|
* ----------------------------------
|
||||||
|
* Neither the United States nor the United States Department of Energy,
|
||||||
|
* nor any of their employees, makes any warranty, express or implied, or
|
||||||
|
* assumes any legal liability or responsibility for the accuracy,
|
||||||
|
* completeness, or usefulness of any data, apparatus, product, or process
|
||||||
|
* disclosed, or represents that its use would not infringe privately owned
|
||||||
|
* rights.
|
||||||
|
*
|
||||||
|
* Stanford disclaimer of liability
|
||||||
|
* --------------------------------
|
||||||
|
* Stanford University makes no representations or warranties, express or
|
||||||
|
* implied, nor assumes any liability for the use of this software.
|
||||||
|
*
|
||||||
|
* Stanford disclaimer of copyright
|
||||||
|
* --------------------------------
|
||||||
|
* Stanford University, owner of the copyright, hereby disclaims its
|
||||||
|
* copyright and all other rights in this software. Hence, anyone may
|
||||||
|
* freely use it for any purpose without restriction.
|
||||||
|
*
|
||||||
|
* Maintenance of notices
|
||||||
|
* ----------------------
|
||||||
|
* In the interest of clarity regarding the origin and status of this
|
||||||
|
* SLAC software, this and all the preceding Stanford University notices
|
||||||
|
* are to remain affixed to any copy or derivative of this software made
|
||||||
|
* or distributed by the recipient and are to be affixed to any copy of
|
||||||
|
* software made or distributed by the recipient that contains a copy or
|
||||||
|
* derivative of this software.
|
||||||
|
*
|
||||||
|
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup Virtex5MMU Virtex 5 - MMU Support
|
||||||
|
*
|
||||||
|
* @ingroup Virtex5
|
||||||
|
*
|
||||||
|
* @brief MMU support.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Some routines require or return an index 'key'.
|
||||||
|
*/
|
||||||
|
typedef int bsp_tlb_idx_t;
|
||||||
|
|
||||||
|
/* Cache the relevant TLB entries so that we can make sure the user cannot
|
||||||
|
* create conflicting (overlapping) entries. Keep them public for informational
|
||||||
|
* purposes.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
struct {
|
||||||
|
uint32_t pad:24;
|
||||||
|
uint32_t tid:8; /** Translation ID */
|
||||||
|
} id;
|
||||||
|
struct {
|
||||||
|
uint32_t epn:22; /** Effective page number */
|
||||||
|
uint32_t v:1; /** Valid */
|
||||||
|
uint32_t ts:1; /** Translation Address Space */
|
||||||
|
uint32_t size:4; /** Page size */
|
||||||
|
uint32_t tpar:4; /** Tag parity */
|
||||||
|
} w0;
|
||||||
|
struct {
|
||||||
|
uint32_t rpn:22; /** The real (translated) page number. */
|
||||||
|
uint32_t par1:2; /** For matching the TLB array parity */
|
||||||
|
uint32_t pad:4;
|
||||||
|
uint32_t erpn:4; /** Extended Real Page Number */
|
||||||
|
} w1;
|
||||||
|
struct {
|
||||||
|
uint32_t par2:2; /** Parity for TLB word 2 */
|
||||||
|
uint32_t pad1:14;
|
||||||
|
uint32_t att:4; /** User-defined attributes */
|
||||||
|
uint32_t wimge:5; /** Write-Through/Caching Inhibited/Memory Coherent/Guarded/Endian */
|
||||||
|
uint32_t pad2:1;
|
||||||
|
uint32_t perm:6; /** User-State Executable/Writeable/Readable Supervisor-State Executable/Writeable/Readable */
|
||||||
|
} w2;
|
||||||
|
} bsp_tlb_entry_t;
|
||||||
|
|
||||||
|
#define NTLBS 64
|
||||||
|
|
||||||
|
extern bsp_tlb_entry_t* bsp_mmu_cache;
|
||||||
|
|
||||||
|
// These constants will have to be shifted right by 20 bits before
|
||||||
|
// being inserted the high word of the TLB.
|
||||||
|
|
||||||
|
#define MMU_M_SIZE_1K (0x00000000U)
|
||||||
|
#define MMU_M_SIZE_4K (0x08000000U)
|
||||||
|
#define MMU_M_SIZE_16K (0x10000000U)
|
||||||
|
#define MMU_M_SIZE_64K (0x18000000U)
|
||||||
|
#define MMU_M_SIZE_256K (0x20000000U)
|
||||||
|
#define MMU_M_SIZE_1M (0x28000000U)
|
||||||
|
#define MMU_M_SIZE_16M (0x38000000U)
|
||||||
|
#define MMU_M_SIZE_256M (0x48000000U)
|
||||||
|
#define MMU_M_SIZE_MIN (MMU_M_SIZE_1K)
|
||||||
|
#define MMU_M_SIZE_MAX (MMU_M_SIZE_256M)
|
||||||
|
#define MMU_M_SIZE (0x78000000U)
|
||||||
|
#define MMU_V_SIZE (27)
|
||||||
|
|
||||||
|
// These constants have the same bit positions they'll occupy
|
||||||
|
// in low word of the TLB.
|
||||||
|
|
||||||
|
#define MMU_M_ATTR_USER0 (0x00010000U)
|
||||||
|
#define MMU_M_ATTR_USER1 (0x00008000U)
|
||||||
|
#define MMU_M_ATTR_USER2 (0x00004000U)
|
||||||
|
#define MMU_M_ATTR_USER3 (0x00002000U)
|
||||||
|
#define MMU_M_ATTR (0x0001e000U)
|
||||||
|
#define MMU_V_ATTR (13)
|
||||||
|
|
||||||
|
#define MMU_M_PROP_WRITE_THROUGH (0x00001000U)
|
||||||
|
#define MMU_M_PROP_UNCACHED (0x00000800U)
|
||||||
|
#define MMU_M_PROP_MEM_COHERENT (0x00000400U)
|
||||||
|
#define MMU_M_PROP_GUARDED (0x00000200U)
|
||||||
|
#define MMU_M_PROP_LITTLE_ENDIAN (0x00000100U)
|
||||||
|
#define MMU_M_PROP (0x00000f00U)
|
||||||
|
#define MMU_V_PROP (8)
|
||||||
|
|
||||||
|
#define MMU_M_PERM_USER_EXEC (0x00000020U)
|
||||||
|
#define MMU_M_PERM_USER_WRITE (0x00000010U)
|
||||||
|
#define MMU_M_PERM_USER_READ (0x00000008U)
|
||||||
|
#define MMU_M_PERM_SUPER_EXEC (0x00000004U)
|
||||||
|
#define MMU_M_PERM_SUPER_WRITE (0x00000002U)
|
||||||
|
#define MMU_M_PERM_SUPER_READ (0x00000001U)
|
||||||
|
#define MMU_M_PERM (0x0000003fU)
|
||||||
|
#define MMU_V_PERM (0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dump (cleartext) content info from cached TLB entries
|
||||||
|
* to a file (stdout if f==NULL).
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bsp_mmu_dump_cache(FILE *f);
|
||||||
|
|
||||||
|
/* Read a TLB entry from the hardware and store the settings in the
|
||||||
|
* bsp_mmu_cache[] structure.
|
||||||
|
*
|
||||||
|
* The routine can perform this operation quietly or
|
||||||
|
* print information to a file.
|
||||||
|
*
|
||||||
|
* 'key': TLB entry index.
|
||||||
|
* 'quiet': perform operation silently (no info printed) if nonzero.
|
||||||
|
* 'f': open FILE where to print information. May be NULL, in
|
||||||
|
* which case 'stdout' is used.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0: success; TLB entry is VALID
|
||||||
|
* +1: success but TLB entry is INVALID
|
||||||
|
* < 0: error (-1: invalid argument)
|
||||||
|
* (-2: driver not initialized)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f);
|
||||||
|
|
||||||
|
/* Initialize cache. Should be done only once although this is not enforced.
|
||||||
|
*
|
||||||
|
* RETURNS: zero on success, nonzero on error; in this case the driver will
|
||||||
|
* refuse to change TLB entries (other than disabling them).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_initialize(void);
|
||||||
|
|
||||||
|
/* Find first free TLB entry by examining all entries' valid bit. The first
|
||||||
|
* entry without the valid bit set is returned.
|
||||||
|
*
|
||||||
|
* RETURNS: A free TLB entry number. -1 if no entry can be found.
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_find_first_free(void);
|
||||||
|
|
||||||
|
/* Write a TLB entry (can also be used to disable an entry).
|
||||||
|
*
|
||||||
|
* The routine checks against the cached data in bsp_mmu_cache[]
|
||||||
|
* to prevent the user from generating overlapping entries.
|
||||||
|
*
|
||||||
|
* 'idx': TLB entry # to manipulate
|
||||||
|
* 'ea': Effective address (must be page aligned)
|
||||||
|
* 'pa': Physical address (must be page aligned)
|
||||||
|
* 'sz': Page size selector; page size is 1024 * 2^(2*sz) bytes.
|
||||||
|
* 'sz' may also be one of the following:
|
||||||
|
* - page size in bytes ( >= 1024 ); the selector
|
||||||
|
* value is then computed by this routine.
|
||||||
|
* However, 'sz' must be a valid page size
|
||||||
|
* or -1 will be returned.
|
||||||
|
* - a value < 0 to invalidate/disable the
|
||||||
|
* TLB entry.
|
||||||
|
* 'flgs': Page's User-defined flags, permissions and WIMGE page attributes
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
* 'erpn': Extended Real Page Number
|
||||||
|
*
|
||||||
|
* RETURNS: 0 on success, nonzero on error:
|
||||||
|
*
|
||||||
|
* >0: requested mapping would overlap with
|
||||||
|
* existing mapping in another entry. Return
|
||||||
|
* value gives conflicting entry + 1; i.e.,
|
||||||
|
* if a value of 4 is returned then the request
|
||||||
|
* conflicts with existing mapping in entry 3.
|
||||||
|
* -1: invalid argument
|
||||||
|
* -3: driver not initialized (or initialization failed).
|
||||||
|
* <0: other error
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, int sz,
|
||||||
|
uint32_t flgs, uint32_t tid, uint32_t ts, uint32_t erpn);
|
||||||
|
|
||||||
|
/* Check if a ea/tid/ts/sz mapping overlaps with an existing entry.
|
||||||
|
*
|
||||||
|
* 'ea': The Effective Address to match against
|
||||||
|
* 'sz': The 'logarithmic' size selector; the page size
|
||||||
|
* is 1024*2^(2*sz).
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* >= 0: index of TLB entry that already provides a mapping
|
||||||
|
* which overlaps within the ea range.
|
||||||
|
* -1: SUCCESS (no conflicting entry found)
|
||||||
|
* <=-2: ERROR (invalid input)
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_match(uint32_t ea, int sz, uint32_t tid, uint32_t ts);
|
||||||
|
|
||||||
|
/* Find TLB index that maps 'ea/tid/ts' combination
|
||||||
|
*
|
||||||
|
* 'ea': Effective address to match against
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
*
|
||||||
|
* RETURNS: index 'key'; i.e., the index number.
|
||||||
|
*
|
||||||
|
* On error (no mapping) -1 is returned.
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_find(uint32_t ea, uint32_t tid, uint32_t ts);
|
||||||
|
|
||||||
|
/* Mark TLB entry as invalid ('disabled').
|
||||||
|
*
|
||||||
|
* 'key': TLB entry index.
|
||||||
|
*
|
||||||
|
* RETURNS: zero on success, nonzero on error (TLB unchanged).
|
||||||
|
*
|
||||||
|
* NOTE: If a TLB entry is disabled the associated
|
||||||
|
* entry in bsp_tlb_cache[] is also marked as disabled.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_invalidate(bsp_tlb_idx_t key);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -35,21 +35,21 @@ rtems_irq_global_settings* BSP_rtems_irq_config;
|
|||||||
* these functions just do nothing fulfill the semantic
|
* these functions just do nothing fulfill the semantic
|
||||||
* requirements to enable/disable a certain interrupt or exception
|
* requirements to enable/disable a certain interrupt or exception
|
||||||
*/
|
*/
|
||||||
void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
|
static void BSP_irq_nop_func(const rtems_irq_connect_data *unused)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* nothing to do
|
* nothing to do
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSP_irq_nop_hdl(void *hdl)
|
static void BSP_irq_nop_hdl(void *hdl)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* nothing to do
|
* nothing to do
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
|
static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* nothing to do
|
* nothing to do
|
||||||
@@ -64,7 +64,7 @@ int BSP_irq_isOn_func(const rtems_irq_connect_data *unused)
|
|||||||
/***********************************************************
|
/***********************************************************
|
||||||
* functions to enable/disable/query external/critical interrupts
|
* functions to enable/disable/query external/critical interrupts
|
||||||
*/
|
*/
|
||||||
void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data)
|
void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data)
|
||||||
{
|
{
|
||||||
uint32_t msr_value;
|
uint32_t msr_value;
|
||||||
/*
|
/*
|
||||||
@@ -76,7 +76,7 @@ void BSP_irqexc_on_fnc(rtems_irq_connect_data *conn_data)
|
|||||||
_CPU_MSR_SET(msr_value);
|
_CPU_MSR_SET(msr_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused)
|
void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused)
|
||||||
{
|
{
|
||||||
uint32_t msr_value;
|
uint32_t msr_value;
|
||||||
/*
|
/*
|
||||||
@@ -88,6 +88,20 @@ void BSP_irqexc_off_fnc(rtems_irq_connect_data *unused)
|
|||||||
_CPU_MSR_SET(msr_value);
|
_CPU_MSR_SET(msr_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPR_RW(BOOKE_TSR)
|
||||||
|
|
||||||
|
int C_dispatch_dec_handler (BSP_Exception_frame *frame, unsigned int excNum)
|
||||||
|
{
|
||||||
|
/* Acknowledge the interrupt */
|
||||||
|
_write_BOOKE_TSR( BOOKE_TSR_DIS );
|
||||||
|
|
||||||
|
/* Handle the interrupt */
|
||||||
|
BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************
|
/***********************************************************
|
||||||
* High level IRQ handler called from shared_raw_irq_code_entry
|
* High level IRQ handler called from shared_raw_irq_code_entry
|
||||||
*/
|
*/
|
||||||
@@ -100,9 +114,12 @@ int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
|
|||||||
case ASM_EXT_VECTOR:
|
case ASM_EXT_VECTOR:
|
||||||
BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
|
BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle);
|
||||||
break;
|
break;
|
||||||
|
#if 0 /* Dealt with by C_dispatch_dec_handler(), above */
|
||||||
case ASM_BOOKE_DEC_VECTOR:
|
case ASM_BOOKE_DEC_VECTOR:
|
||||||
BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle);
|
_write_BOOKE_TSR( BOOKE_TSR_DIS );
|
||||||
|
BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
#if 0 /* Critical interrupts not yet supported */
|
#if 0 /* Critical interrupts not yet supported */
|
||||||
case ASM_BOOKE_CRIT_VECTOR:
|
case ASM_BOOKE_CRIT_VECTOR:
|
||||||
BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
|
BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle);
|
||||||
@@ -275,7 +292,7 @@ int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
|
|||||||
* dummy for an empty IRQ handler entry
|
* dummy for an empty IRQ handler entry
|
||||||
*/
|
*/
|
||||||
static rtems_irq_connect_data emptyIrq = {
|
static rtems_irq_connect_data emptyIrq = {
|
||||||
0, /* Irq Name */
|
0, /* IRQ Name */
|
||||||
BSP_irq_nop_hdl, /* handler function */
|
BSP_irq_nop_hdl, /* handler function */
|
||||||
NULL, /* handle passed to handler */
|
NULL, /* handle passed to handler */
|
||||||
BSP_irq_nop_func, /* on function */
|
BSP_irq_nop_func, /* on function */
|
||||||
@@ -284,8 +301,8 @@ static rtems_irq_connect_data emptyIrq = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static rtems_irq_global_settings initialConfig = {
|
static rtems_irq_global_settings initialConfig = {
|
||||||
BSP_IRQ_NUMBER, /* irqNb */
|
BSP_IRQ_NUMBER, /* IRQ number */
|
||||||
{ 0, /* Irq Name */
|
{ 0, /* IRQ Name */
|
||||||
BSP_irq_nop_hdl, /* handler function */
|
BSP_irq_nop_hdl, /* handler function */
|
||||||
NULL, /* handle passed to handler */
|
NULL, /* handle passed to handler */
|
||||||
BSP_irq_nop_func, /* on function */
|
BSP_irq_nop_func, /* on function */
|
||||||
@@ -305,7 +322,7 @@ void BSP_rtems_irq_mngt_init(unsigned cpuId)
|
|||||||
* connect all exception vectors needed
|
* connect all exception vectors needed
|
||||||
*/
|
*/
|
||||||
ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
|
ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler);
|
||||||
ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler);
|
ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* setup interrupt handlers table
|
* setup interrupt handlers table
|
||||||
|
|||||||
581
c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c
Normal file
581
c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c
Normal file
@@ -0,0 +1,581 @@
|
|||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup Virtex5MMU
|
||||||
|
*
|
||||||
|
* @brief Implementation of routines to manipulate the PPC 440 MMU.
|
||||||
|
*
|
||||||
|
* Since this is a real-time OS we want to stay away from
|
||||||
|
* software TLB replacement.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Authorship
|
||||||
|
* ----------
|
||||||
|
* This software was created by
|
||||||
|
* Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
|
||||||
|
* Stanford Linear Accelerator Center, Stanford University.
|
||||||
|
* and was transcribed for the PPC 440 by
|
||||||
|
* R. Claus <claus@slac.stanford.edu>, 2012,
|
||||||
|
* Stanford Linear Accelerator Center, Stanford University,
|
||||||
|
*
|
||||||
|
* Acknowledgement of sponsorship
|
||||||
|
* ------------------------------
|
||||||
|
* This software was produced by
|
||||||
|
* the Stanford Linear Accelerator Center, Stanford University,
|
||||||
|
* under Contract DE-AC03-76SFO0515 with the Department of Energy.
|
||||||
|
*
|
||||||
|
* Government disclaimer of liability
|
||||||
|
* ----------------------------------
|
||||||
|
* Neither the United States nor the United States Department of Energy,
|
||||||
|
* nor any of their employees, makes any warranty, express or implied, or
|
||||||
|
* assumes any legal liability or responsibility for the accuracy,
|
||||||
|
* completeness, or usefulness of any data, apparatus, product, or process
|
||||||
|
* disclosed, or represents that its use would not infringe privately owned
|
||||||
|
* rights.
|
||||||
|
*
|
||||||
|
* Stanford disclaimer of liability
|
||||||
|
* --------------------------------
|
||||||
|
* Stanford University makes no representations or warranties, express or
|
||||||
|
* implied, nor assumes any liability for the use of this software.
|
||||||
|
*
|
||||||
|
* Stanford disclaimer of copyright
|
||||||
|
* --------------------------------
|
||||||
|
* Stanford University, owner of the copyright, hereby disclaims its
|
||||||
|
* copyright and all other rights in this software. Hence, anyone may
|
||||||
|
* freely use it for any purpose without restriction.
|
||||||
|
*
|
||||||
|
* Maintenance of notices
|
||||||
|
* ----------------------
|
||||||
|
* In the interest of clarity regarding the origin and status of this
|
||||||
|
* SLAC software, this and all the preceding Stanford University notices
|
||||||
|
* are to remain affixed to any copy or derivative of this software made
|
||||||
|
* or distributed by the recipient and are to be affixed to any copy of
|
||||||
|
* software made or distributed by the recipient that contains a copy or
|
||||||
|
* derivative of this software.
|
||||||
|
*
|
||||||
|
* ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* 440 MSR definitions; note that there are *substantial* differences
|
||||||
|
* compared to classic powerpc; in particular, IS/DS are *different*
|
||||||
|
* from IR/DR; the ppc440 MMU cannot be switched off!
|
||||||
|
*
|
||||||
|
* Also: To disable/enable all external interrupts, CE and EE must both be
|
||||||
|
* controlled.
|
||||||
|
*/
|
||||||
|
#include <rtems.h>
|
||||||
|
#include <rtems/bspIo.h>
|
||||||
|
#include <rtems/powerpc/powerpc.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <bsp/mmu.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define STATIC
|
||||||
|
#else
|
||||||
|
#define STATIC static
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
bsp_tlb_entry_t* bsp_mmu_cache = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/* Since it is likely that these routines are used during
|
||||||
|
* early initialization when stdio is not available yet
|
||||||
|
* we provide a helper that resorts to 'printk()'
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
myprintf(FILE *f, char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
|
||||||
|
if (!f || !_impure_ptr->__sdidinit) {
|
||||||
|
/* Might be called at an early stage when stdio is not yet initialized. */
|
||||||
|
vprintk(fmt,ap);
|
||||||
|
} else {
|
||||||
|
vfprintf(f,fmt,ap);
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
bsp_mmu_dump_cache(FILE *f)
|
||||||
|
{
|
||||||
|
bsp_tlb_idx_t idx;
|
||||||
|
if ( !bsp_mmu_cache ) {
|
||||||
|
myprintf(stderr,"MMU TLB cache not initialized\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for ( idx=0; idx<NTLBS; idx++ ) {
|
||||||
|
bsp_tlb_entry_t *tlb = bsp_mmu_cache + idx;
|
||||||
|
if ( !tlb->w0.v )
|
||||||
|
continue;
|
||||||
|
myprintf(f, "#%2i: EA 0x%08x .. 0x%08x, TID 0x%03x, TS %i\n",
|
||||||
|
idx,
|
||||||
|
tlb->w0.epn<<10,
|
||||||
|
(tlb->w0.epn<<10) + (1024<<(2*tlb->w0.size))-1,
|
||||||
|
tlb->id.tid,
|
||||||
|
tlb->w0.ts);
|
||||||
|
myprintf(f, " PA 0x%08"PRIx32", U0-3 0x%01x, WIMGE 0x%02x, PERM 0x%03x\n",
|
||||||
|
tlb->w1.rpn<<10,
|
||||||
|
tlb->w2.att,
|
||||||
|
tlb->w2.wimge,
|
||||||
|
tlb->w2.perm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fetch(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb)
|
||||||
|
{
|
||||||
|
register uint32_t tmp;
|
||||||
|
__asm__ volatile ("mfpid %[tmp] \n\t"
|
||||||
|
"stw %[tmp],0(%[tlb]) \n\t"
|
||||||
|
"tlbre %[tmp],%[key],0 \n\t"
|
||||||
|
"stw %[tmp],4(%[tlb]) \n\t"
|
||||||
|
"tlbre %[tmp],%[key],1 \n\t"
|
||||||
|
"stw %[tmp],8(%[tlb]) \n\t"
|
||||||
|
"tlbre %[tmp],%[key],2 \n\t"
|
||||||
|
"stw %[tmp],12(%[tlb]) \n\t"
|
||||||
|
"sync \n\t"
|
||||||
|
: [tmp]"=&r"(tmp)
|
||||||
|
: [key]"r"(key),
|
||||||
|
[tlb]"b"(tlb)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
store(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb)
|
||||||
|
{
|
||||||
|
register uint32_t tmp;
|
||||||
|
__asm__ volatile ("lwz %[tmp],0(%[tlb]) \n\t"
|
||||||
|
"mtpid %[tmp] \n\t"
|
||||||
|
"lwz %[tmp],4(%[tlb]) \n\t"
|
||||||
|
"tlbwe %[tmp],%[idx],0 \n\t"
|
||||||
|
"lwz %[tmp],8(%[tlb]) \n\t"
|
||||||
|
"tlbwe %[tmp],%[idx],1 \n\t"
|
||||||
|
"lwz %[tmp],12(%[tlb]) \n\t"
|
||||||
|
"tlbwe %[tmp],%[idx],2 \n\t"
|
||||||
|
: [tmp]"=&r"(tmp)
|
||||||
|
: [tlb]"b"(tlb),
|
||||||
|
[idx]"r"(key)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
commit(void)
|
||||||
|
{
|
||||||
|
__asm__ volatile("isync \n\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read a TLB entry from the hardware store the current settings in the
|
||||||
|
* bsp_mmu_cache[] structure.
|
||||||
|
*
|
||||||
|
* The routine can perform this operation quietly or
|
||||||
|
* print information to a file.
|
||||||
|
*
|
||||||
|
* 'idx': which TLB entry to access.
|
||||||
|
* 'quiet': perform operation silently (no info printed)
|
||||||
|
* if nonzero.
|
||||||
|
* 'f': open FILE where to print information. May be
|
||||||
|
* NULL in which case 'stdout' is used.
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* 0: success; TLB entry is VALID
|
||||||
|
* +1: success but TLB entry is INVALID
|
||||||
|
* < 0: error (-1: invalid argument)
|
||||||
|
* (-2: driver not initialized)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f)
|
||||||
|
{
|
||||||
|
rtems_interrupt_level lvl;
|
||||||
|
bsp_tlb_entry_t* tlb;
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
idx = key;
|
||||||
|
|
||||||
|
if ( idx < 0 || idx > NTLBS-1 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (!bsp_mmu_cache)
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
tlb = bsp_mmu_cache + idx;
|
||||||
|
|
||||||
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
|
fetch(idx, tlb);
|
||||||
|
|
||||||
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
|
if ( tlb->w0.v ) {
|
||||||
|
if ( !quiet ) {
|
||||||
|
/*
|
||||||
|
"TLB Entry # 0 spans EA range 0x00000000 - 0x00000000
|
||||||
|
"Mapping: VA [TS 0 / TID 0x00 / EPN 0x00000] -> RPN 0x00000"
|
||||||
|
"Size: TSIZE 0x0 (4^sz KB = 000000 KB = 0x00000000 B)
|
||||||
|
"Attributes: PERM 0x000 (ux/uw/ur/sx/sw/sr) WIMGE 0x00 U0-3 0x0"
|
||||||
|
*/
|
||||||
|
myprintf(f,
|
||||||
|
"TLB Entry # %2d spans EA range 0x%08x - 0x%08x\n",
|
||||||
|
idx,
|
||||||
|
(tlb->w0.epn << 10),
|
||||||
|
(tlb->w0.epn << 10) + (1024<<(2*tlb->w0.size)) - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
myprintf(f,
|
||||||
|
"Mapping: VA [TS %d / TID 0x%02x / EPN 0x%05x] -> RPN 0x%05"PRIx32"\n",
|
||||||
|
tlb->w0.ts, tlb->id.tid, tlb->w0.epn, tlb->w1.rpn
|
||||||
|
);
|
||||||
|
myprintf(f,
|
||||||
|
"Size: TSIZE 0x%x (4^sz KB = %6d KB = 0x%08x B)\n",
|
||||||
|
tlb->w0.size, (1<<(2*tlb->w0.size)), (1024<<(2*tlb->w0.size))
|
||||||
|
);
|
||||||
|
myprintf(f,
|
||||||
|
"Properties: PERM 0x%03x (ux/uw/ur/sx/sw/sr) WIMGE 0x%02x U0-3 0x%01x\n",
|
||||||
|
tlb->w2.perm, tlb->w2.wimge, tlb->w2.att
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ( !quiet ) {
|
||||||
|
myprintf(f, "TLB Entry # %2d <OFF> (size 0x%x = 0x%xb)\n",
|
||||||
|
idx, tlb->w0.size, (1024<<(2*tlb->w0.size)));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize cache. Should be done only once although this is not enforced.
|
||||||
|
*
|
||||||
|
* RETURNS: zero on success, nonzero on error; in this case the driver will
|
||||||
|
* refuse to change TLB entries (other than disabling them).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_initialize()
|
||||||
|
{
|
||||||
|
static bsp_tlb_entry_t mmu_cache[NTLBS];
|
||||||
|
bsp_tlb_entry_t* tlb = mmu_cache; /* Should malloc if it's not too early */
|
||||||
|
rtems_interrupt_level lvl;
|
||||||
|
|
||||||
|
bsp_tlb_idx_t idx;
|
||||||
|
rtems_interrupt_disable(lvl);
|
||||||
|
for (idx=0; idx<NTLBS; tlb++, idx++)
|
||||||
|
{
|
||||||
|
fetch(idx, tlb);
|
||||||
|
}
|
||||||
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
|
bsp_mmu_cache = mmu_cache;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find first free TLB entry by examining all entries' valid bit. The first
|
||||||
|
* entry without the valid bit set is returned.
|
||||||
|
*
|
||||||
|
* RETURNS: A free TLB entry number. -1 if no entry can be found.
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_find_first_free()
|
||||||
|
{
|
||||||
|
bsp_tlb_idx_t idx;
|
||||||
|
bsp_tlb_entry_t entry;
|
||||||
|
|
||||||
|
for (idx=0; idx<NTLBS; idx++) {
|
||||||
|
register uint32_t tmp;
|
||||||
|
__asm__ volatile ("tlbre %[tmp],%[idx],0 \n\t"
|
||||||
|
"stw %[tmp],4(%[tlb]) \n\t" /* entry.w0 */
|
||||||
|
"sync \n\t"
|
||||||
|
: [tmp]"=&r"(tmp)
|
||||||
|
: [idx]"r"(idx),
|
||||||
|
[tlb]"b"(&entry)
|
||||||
|
: "memory"
|
||||||
|
);
|
||||||
|
if (!(entry.w0.v))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return (idx < NTLBS) ? idx : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write TLB entry (can also be used to disable an entry).
|
||||||
|
*
|
||||||
|
* The routine checks against the cached data in
|
||||||
|
* bsp_mmu_cache[] to prevent the user from generating
|
||||||
|
* overlapping entries.
|
||||||
|
*
|
||||||
|
* 'idx': TLB entry # to manipulate
|
||||||
|
* 'ea': Effective address (must be page aligned)
|
||||||
|
* 'pa': Physical address (must be page aligned)
|
||||||
|
* 'sz': Page size selector; page size is
|
||||||
|
* 1024 * 2^(2*sz) bytes.
|
||||||
|
* 'sz' may also be one of the following:
|
||||||
|
* - page size in bytes ( >= 1024 ); the selector
|
||||||
|
* value is then computed by this routine.
|
||||||
|
* However, 'sz' must be a valid page size
|
||||||
|
* or -1 will be returned.
|
||||||
|
* - a value < 0 to invalidate/disable the
|
||||||
|
* TLB entry.
|
||||||
|
* 'flgs': Page's User-defined flags, permissions and WIMGE page attributes
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
* 'erpn': Extended Real Page Number
|
||||||
|
*
|
||||||
|
* RETURNS: 0 on success, nonzero on error:
|
||||||
|
*
|
||||||
|
* >0: requested mapping would overlap with
|
||||||
|
* existing mapping in other entry. Return
|
||||||
|
* value gives conflicting entry + 1; i.e.,
|
||||||
|
* if a value of 4 is returned then the request
|
||||||
|
* conflicts with existing mapping in entry 3.
|
||||||
|
* -1: invalid argument
|
||||||
|
* -3: driver not initialized (or initialization failed).
|
||||||
|
* <0: other error
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, int sz,
|
||||||
|
uint32_t flgs, uint32_t tid, uint32_t ts, uint32_t erpn)
|
||||||
|
{
|
||||||
|
bsp_tlb_entry_t tlb;
|
||||||
|
uint32_t msk;
|
||||||
|
bsp_tlb_idx_t lkup;
|
||||||
|
rtems_interrupt_level lvl;
|
||||||
|
|
||||||
|
if ( sz >= 1024 ) {
|
||||||
|
/* Assume they literally specify a size */
|
||||||
|
msk = sz;
|
||||||
|
sz = 0;
|
||||||
|
while ( msk != (1024<<(sz+sz)) ) {
|
||||||
|
if ( ++sz > 15 ) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* OK, acceptable */
|
||||||
|
}
|
||||||
|
|
||||||
|
msk = sz > 0 ? (1024<<(sz+sz)) - 1 : 0;
|
||||||
|
|
||||||
|
if ( !bsp_mmu_cache && sz > 0 ) {
|
||||||
|
myprintf(stderr,"MMU driver not initialized; refusing to enable any entry\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( (ea & msk) || (pa & msk) ) {
|
||||||
|
myprintf(stderr,"Misaligned EA (%08x) or PA (%08x) (mask is %08x)\n", ea, pa, msk);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( idx < 0 || idx > NTLBS-1 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Not all 16 possible sizes are supported */
|
||||||
|
if ( sz == 6 || sz == 8 || sz > 9 ) {
|
||||||
|
myprintf(stderr,"Invalid size %u = %08x = %u KB\n", sz, 1024<<(sz+sz), (1024<<(sz+sz))/1024);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( sz >=0 ) {
|
||||||
|
lkup = bsp_mmu_match(ea, sz, tid, ts);
|
||||||
|
|
||||||
|
if ( lkup < -1 ) {
|
||||||
|
/* some error */
|
||||||
|
return lkup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( lkup >= 0 && lkup != idx && (bsp_mmu_cache[lkup].w0.v != 0) ) {
|
||||||
|
myprintf(stderr,"TLB #%i overlaps with requested mapping\n", lkup);
|
||||||
|
bsp_mmu_update( lkup, false, stderr);
|
||||||
|
return lkup+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OK to proceed */
|
||||||
|
tlb.id.tid = tid;
|
||||||
|
tlb.w0.v = sz >= 0;
|
||||||
|
tlb.w0.ts = ts;
|
||||||
|
tlb.w0.size = sz;
|
||||||
|
tlb.w0.epn = (ea & (0xfffffc00 << (sz+sz))) >> 10;
|
||||||
|
if (sz < 11) {
|
||||||
|
tlb.w1.rpn = (pa & (0xfffffc00 << (sz+sz))) >> 10;
|
||||||
|
tlb.w1.erpn = erpn;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sz -= 11;
|
||||||
|
tlb.w1.rpn = 0;
|
||||||
|
tlb.w1.erpn = (erpn & (0xf << (sz+sz))) & 0xf;
|
||||||
|
}
|
||||||
|
tlb.w2.att = (flgs & MMU_M_ATTR) >> MMU_V_ATTR;
|
||||||
|
tlb.w2.wimge = (flgs & MMU_M_PROP) >> MMU_V_PROP;
|
||||||
|
tlb.w2.perm = (flgs & MMU_M_PERM) >> MMU_V_PERM;
|
||||||
|
|
||||||
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
|
store(idx, &tlb);
|
||||||
|
|
||||||
|
commit();
|
||||||
|
|
||||||
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
|
/* update cache */
|
||||||
|
bsp_mmu_update(idx, true, 0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if a ea/tid/ts/sz mapping overlaps with an existing entry.
|
||||||
|
*
|
||||||
|
* 'ea': The Effective Address to match against
|
||||||
|
* 'sz': The 'logarithmic' size selector; the page size
|
||||||
|
* is 1024*2^(2*sz).
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
*
|
||||||
|
* RETURNS:
|
||||||
|
* >= 0: index of the TLB entry that already provides a mapping
|
||||||
|
* which overlaps within the ea range.
|
||||||
|
* -1: SUCCESS (no conflicting entry found)
|
||||||
|
* <=-2: ERROR (invalid input)
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_match(uint32_t ea, int sz, uint32_t tid, uint32_t ts)
|
||||||
|
{
|
||||||
|
bsp_tlb_idx_t idx;
|
||||||
|
uint32_t m,a;
|
||||||
|
bsp_tlb_entry_t* tlb;
|
||||||
|
|
||||||
|
if ( sz < 0 || sz == 6 || sz == 8 || sz > 9 )
|
||||||
|
return -4;
|
||||||
|
|
||||||
|
sz = (1024<<(2*sz));
|
||||||
|
|
||||||
|
if ( !bsp_mmu_cache ) {
|
||||||
|
/* cache not initialized */
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ea & (sz-1) ) {
|
||||||
|
/* misaligned ea */
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( idx=0, tlb=bsp_mmu_cache; idx<NTLBS; idx++, tlb++ ) {
|
||||||
|
if ( ! tlb->w0.v )
|
||||||
|
continue;
|
||||||
|
if ( tlb->id.tid && tlb->id.tid != tid )
|
||||||
|
continue;
|
||||||
|
if ( tlb->w0.ts != ts )
|
||||||
|
continue;
|
||||||
|
/* TID and TS match a valid entry */
|
||||||
|
m = (1024<<(2*tlb->w0.size)) - 1;
|
||||||
|
/* calculate starting address of this entry */
|
||||||
|
a = tlb->w0.epn<<10;
|
||||||
|
if ( ea <= a + m && ea + sz -1 >= a ) {
|
||||||
|
/* overlap */
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find TLB index that maps 'ea/tid/ts' combination
|
||||||
|
*
|
||||||
|
* 'ea': Effective address to match against
|
||||||
|
* 'tid': Translation ID
|
||||||
|
* 'ts': Translation Space
|
||||||
|
*
|
||||||
|
* RETURNS: index 'key' which indicates whether
|
||||||
|
* the mapping was found.
|
||||||
|
*
|
||||||
|
* On error (no mapping) -1 is returned.
|
||||||
|
*/
|
||||||
|
bsp_tlb_idx_t
|
||||||
|
bsp_mmu_find(uint32_t ea, uint32_t tid, uint32_t ts)
|
||||||
|
{
|
||||||
|
rtems_interrupt_level lvl;
|
||||||
|
register uint32_t mmucr;
|
||||||
|
register bsp_tlb_idx_t idx;
|
||||||
|
register int failure;
|
||||||
|
|
||||||
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
|
__asm__ volatile ("mfspr %[mmucr],0x3b2 \n\t" /* Save MMUCR */
|
||||||
|
: [mmucr]"=r"(mmucr)
|
||||||
|
);
|
||||||
|
__asm__ volatile ("mtspr 0x3b2,%[tid] \n\t"
|
||||||
|
"tlbsx. %[idx],0,%[ea] \n\t" /* Failure changes the index reg randomly. */
|
||||||
|
"mfcr %[failure] \n\t"
|
||||||
|
"mtspr 0x3b2,%[mmucr] \n\t" /* Restore MMUCR */
|
||||||
|
: [idx]"=&r"(idx),
|
||||||
|
[failure]"=&r"(failure)
|
||||||
|
: [tid]"r"((mmucr & 0xfffeff00) | (ts << 16) | tid),
|
||||||
|
[ea]"r"(ea),
|
||||||
|
[mmucr]"r"(mmucr)
|
||||||
|
: "cc"
|
||||||
|
);
|
||||||
|
|
||||||
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
|
return (failure & 0x20000000) ? idx : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark TLB entry as invalid ('disabled').
|
||||||
|
*
|
||||||
|
* 'key': TLB entry (index).
|
||||||
|
*
|
||||||
|
* RETURNS: zero on success, nonzero on error (TLB unchanged).
|
||||||
|
*
|
||||||
|
* NOTE: If a TLB entry is disabled the associated
|
||||||
|
* entry in bsp_mmu_cache[] is also
|
||||||
|
* marked as disabled.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
bsp_mmu_invalidate(bsp_tlb_idx_t key)
|
||||||
|
{
|
||||||
|
bsp_tlb_idx_t k0;
|
||||||
|
rtems_interrupt_level lvl;
|
||||||
|
bsp_tlb_entry_t tlb;
|
||||||
|
|
||||||
|
/* minimal guard against bad key */
|
||||||
|
if ( key < 0 || key > NTLBS-1 )
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Must not invalidate page 0 which holds vectors, text etc... */
|
||||||
|
k0 = bsp_mmu_find(0, 0, 0);
|
||||||
|
if ( -1 == k0 ) {
|
||||||
|
myprintf(stderr,"No mapping for address 0 found\n");
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOTE: we assume PID is ignored */
|
||||||
|
if ( k0 == key ) {
|
||||||
|
myprintf(stderr,"Cannot invalidate page holding address 0 (always needed)\n");
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
|
fetch(key, &tlb);
|
||||||
|
|
||||||
|
/* Invalidate old entries */
|
||||||
|
tlb.w0.v = 0;
|
||||||
|
|
||||||
|
store(key, &tlb);
|
||||||
|
|
||||||
|
commit();
|
||||||
|
|
||||||
|
/* Update cache */
|
||||||
|
bsp_mmu_cache[ key ].w0.v = tlb.w0.v;
|
||||||
|
|
||||||
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -69,6 +69,10 @@ $(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
|||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
|
||||||
|
|
||||||
|
$(PROJECT_INCLUDE)/bsp/mmu.h: include/mmu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
||||||
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/mmu.h
|
||||||
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/mmu.h
|
||||||
|
|
||||||
$(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
$(PROJECT_INCLUDE)/bsp/vectors.h: ../../../libcpu/@RTEMS_CPU@/@exceptions@/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
||||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
|
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
|
||||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
|
||||||
|
|||||||
@@ -54,20 +54,23 @@
|
|||||||
* Modifications for PPC405GP by Dennis Ehlin
|
* Modifications for PPC405GP by Dennis Ehlin
|
||||||
* Modifications for Virtex5 by Richard Claus <claus@slac.stanford.edu>
|
* Modifications for Virtex5 by Richard Claus <claus@slac.stanford.edu>
|
||||||
*/
|
*/
|
||||||
|
#include <rtems.h>
|
||||||
#include <string.h>
|
#include <rtems/config.h>
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include <bsp.h>
|
|
||||||
#include <bsp/irq.h>
|
|
||||||
#include <bsp/vectors.h>
|
|
||||||
#include <rtems/bspIo.h>
|
#include <rtems/bspIo.h>
|
||||||
#include <rtems/libio.h>
|
#include <rtems/libio.h>
|
||||||
#include <rtems/libcsupport.h>
|
#include <rtems/libcsupport.h>
|
||||||
#include <rtems/sptables.h> /* for RTEMS_VERSION */
|
|
||||||
#include <libcpu/cpuIdent.h>
|
#include <libcpu/cpuIdent.h>
|
||||||
#include <libcpu/spr.h>
|
#include <libcpu/spr.h>
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <bsp/vectors.h>
|
||||||
|
#include <bsp/bootcard.h>
|
||||||
|
#include <bsp/irq.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1))
|
#define DO_DOWN_ALIGN(x,a) ((x) & ~((a)-1))
|
||||||
|
|
||||||
#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a)
|
#define DO_UP_ALIGN(x,a) DO_DOWN_ALIGN(((x) + (a) - 1 ),a)
|
||||||
@@ -76,13 +79,6 @@
|
|||||||
#define CPU_UP_ALIGN(x) DO_UP_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 */
|
/* Defined in linkcmds linker script */
|
||||||
LINKER_SYMBOL(RamBase);
|
LINKER_SYMBOL(RamBase);
|
||||||
LINKER_SYMBOL(RamSize);
|
LINKER_SYMBOL(RamSize);
|
||||||
@@ -96,35 +92,37 @@ LINKER_SYMBOL(WorkAreaBase);
|
|||||||
LINKER_SYMBOL(MsgAreaBase);
|
LINKER_SYMBOL(MsgAreaBase);
|
||||||
LINKER_SYMBOL(MsgAreaSize);
|
LINKER_SYMBOL(MsgAreaSize);
|
||||||
LINKER_SYMBOL(__phy_ram_end);
|
LINKER_SYMBOL(__phy_ram_end);
|
||||||
|
LINKER_SYMBOL(bsp_exc_vector_base);
|
||||||
|
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bus Frequency
|
||||||
|
*/
|
||||||
|
unsigned int BSP_bus_frequency;
|
||||||
|
/*
|
||||||
|
* processor clock frequency
|
||||||
|
*/
|
||||||
|
unsigned int BSP_processor_frequency;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Time base divisior (bus freq / TB clock)
|
||||||
|
*/
|
||||||
|
unsigned int BSP_time_base_divisor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Provide weak aliases so that RTEMS distribution builds
|
* Provide weak aliases so that RTEMS distribution builds
|
||||||
*/
|
*/
|
||||||
static void _noopfun(void) {}
|
static void _noopfun(void) {}
|
||||||
static void _bsp_start(void)
|
|
||||||
{
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT & ~MSR_EE,
|
|
||||||
intrStackStart,
|
|
||||||
intrStackSize);
|
|
||||||
|
|
||||||
/* Install our own set of exception vectors */
|
|
||||||
BSP_rtems_irq_mngt_init(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void app_bsp_start(void)
|
void app_bsp_start(void)
|
||||||
__attribute__(( weak, alias("_bsp_start") ));
|
__attribute__(( weak, alias("_noopfun") ));
|
||||||
|
|
||||||
void app_bsp_pretasking_hook(void)
|
void app_bsp_pretasking_hook(void)
|
||||||
__attribute__(( weak, alias("_noopfun") ));
|
__attribute__(( weak, alias("_noopfun") ));
|
||||||
@@ -147,20 +145,31 @@ static void __bsp_outchar_to_memory(char c)
|
|||||||
void BSP_ask_for_reset(void)
|
void BSP_ask_for_reset(void)
|
||||||
{
|
{
|
||||||
printk("\nSystem stopped, issue RESET");
|
printk("\nSystem stopped, issue RESET");
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BSP_panic(char *s)
|
void BSP_panic(char *s)
|
||||||
{
|
{
|
||||||
printk("\n%s PANIC %s\n", _RTEMS_version, s);
|
rtems_interrupt_level level;
|
||||||
|
|
||||||
|
rtems_interrupt_disable(level);
|
||||||
|
|
||||||
|
printk("\n%s PANIC %s\n", rtems_get_version_string(), s);
|
||||||
|
|
||||||
BSP_ask_for_reset();
|
BSP_ask_for_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _BSP_Fatal_error(unsigned int v)
|
void _BSP_Fatal_error(unsigned int v)
|
||||||
{
|
{
|
||||||
printk("\n%s FATAL ERROR %x\n", _RTEMS_version, v);
|
rtems_interrupt_level level;
|
||||||
|
|
||||||
|
rtems_interrupt_disable(level);
|
||||||
|
|
||||||
|
printk("\n%s FATAL ERROR %x\n", rtems_get_version_string(), v);
|
||||||
|
|
||||||
BSP_ask_for_reset();
|
BSP_ask_for_reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,13 +185,14 @@ void bsp_start(void)
|
|||||||
{
|
{
|
||||||
uintptr_t intrStackStart;
|
uintptr_t intrStackStart;
|
||||||
uintptr_t intrStackSize;
|
uintptr_t intrStackSize;
|
||||||
|
|
||||||
ppc_cpu_id_t myCpu;
|
ppc_cpu_id_t myCpu;
|
||||||
ppc_cpu_revision_t myCpuRevision;
|
ppc_cpu_revision_t myCpuRevision;
|
||||||
|
|
||||||
/* Set the character output function; The application may override this */
|
/* Set the character output function; The application may override this */
|
||||||
BSP_output_char = __bsp_outchar_to_memory;
|
BSP_output_char = __bsp_outchar_to_memory;
|
||||||
|
|
||||||
printk("\nWelcome to RTEMS %s\n", _RTEMS_version );
|
printk("RTEMS %s\n", rtems_get_version_string());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get CPU identification dynamically. Note that the get_ppc_cpu_type()
|
* Get CPU identification dynamically. Note that the get_ppc_cpu_type()
|
||||||
@@ -197,8 +207,13 @@ void bsp_start(void)
|
|||||||
* Initialize the device driver parameters
|
* Initialize the device driver parameters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* For mpc6xx clock driver: */
|
||||||
|
BSP_bus_frequency = 465000000;
|
||||||
|
BSP_processor_frequency = 465000000; /* Measured with a DPM 440 2012/8/13 */
|
||||||
|
BSP_time_base_divisor = 1000;
|
||||||
|
|
||||||
/* Timebase register ticks/microsecond; The application may override these */
|
/* Timebase register ticks/microsecond; The application may override these */
|
||||||
bsp_clicks_per_usec = 450;
|
bsp_clicks_per_usec = BSP_bus_frequency/(BSP_time_base_divisor * 1000);
|
||||||
bsp_timer_internal_clock = true;
|
bsp_timer_internal_clock = true;
|
||||||
bsp_timer_average_overhead = 2;
|
bsp_timer_average_overhead = 2;
|
||||||
bsp_timer_least_valid = 3;
|
bsp_timer_least_valid = 3;
|
||||||
@@ -208,6 +223,12 @@ void bsp_start(void)
|
|||||||
*/
|
*/
|
||||||
intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start);
|
intrStackStart = CPU_UP_ALIGN((uint32_t)__bsp_ram_start);
|
||||||
intrStackSize = rtems_configuration_get_interrupt_stack_size();
|
intrStackSize = rtems_configuration_get_interrupt_stack_size();
|
||||||
|
|
||||||
|
ppc_exc_initialize(PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
|
||||||
|
intrStackStart,
|
||||||
|
intrStackSize);
|
||||||
|
|
||||||
|
/* Let the user know what parameters we were compiled with */
|
||||||
printk(" Base/Start End Size\n"
|
printk(" Base/Start End Size\n"
|
||||||
"RAM: 0x%08x 0x%x\n"
|
"RAM: 0x%08x 0x%x\n"
|
||||||
"RTEMS: 0x%08x\n"
|
"RTEMS: 0x%08x\n"
|
||||||
@@ -224,6 +245,11 @@ void bsp_start(void)
|
|||||||
(uint32_t)MsgAreaBase, (uint32_t)MsgAreaSize,
|
(uint32_t)MsgAreaBase, (uint32_t)MsgAreaSize,
|
||||||
(uint32_t)__phy_ram_end);
|
(uint32_t)__phy_ram_end);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize RTEMS IRQ system
|
||||||
|
*/
|
||||||
|
BSP_rtems_irq_mngt_init(0);
|
||||||
|
|
||||||
/* Continue with application-specific initialization */
|
/* Continue with application-specific initialization */
|
||||||
app_bsp_start();
|
app_bsp_start();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,16 +20,17 @@ HeapSize = DEFINED(HeapSize) ? HeapSize : 0; /* 0=Use def */
|
|||||||
|
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
VECTORS : ORIGIN = 0x00000000, LENGTH = 8K
|
VECTORS : ORIGIN = 0x00000000, LENGTH = 512
|
||||||
RAM : ORIGIN = 0x00002000, LENGTH = 2048M - 8K
|
RAM : ORIGIN = 0x00000200, LENGTH = 2048M - 512
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
|
bsp_exc_vector_base = 0;
|
||||||
__exeentry = download_entry;
|
__exeentry = download_entry;
|
||||||
__exestart = 0x100;
|
__exestart = bsp_exc_vector_base;
|
||||||
.vectors __exestart : { *(.vectors) } > VECTORS
|
.vectors bsp_exc_vector_base : { *(.vectors) } > VECTORS
|
||||||
|
|
||||||
/* Read-only sections, merged into text segment: */
|
/* Read-only sections, merged into text segment: */
|
||||||
.interp : { *(.interp) } > RAM
|
.interp : { *(.interp) } > RAM
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
|
|
||||||
#include <rtems/asm.h>
|
#include <rtems/asm.h>
|
||||||
#include <rtems/powerpc/powerpc.h>
|
#include <rtems/powerpc/powerpc.h>
|
||||||
|
#include <rtems/powerpc/registers.h>
|
||||||
|
|
||||||
#define V_TS_SZ_I 0x0290 // V,TS=0(Inst),SIZE=9,TID=0
|
#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 V_TS_SZ_D 0x0390 // V,TS=1(Data),SIZE=9,TID=0
|
||||||
@@ -154,43 +155,44 @@ first: li r0,0 // Clear r0
|
|||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
* Set Core Configuration Register 0 as follows:
|
* Set Core Configuration Register 0 as follows:
|
||||||
* sum: 0x00200000
|
* sum: 0x00206000
|
||||||
* bit 1 off Parity Recovery Enable
|
* bit 1 off Parity Recovery Enable
|
||||||
* bit 4 off Cache Read Parity Enable
|
* bit 4 off Cache Read Parity Enable
|
||||||
* bit 10 on Disable Store Gathering
|
* bit 10 on Disable Store Gathering
|
||||||
* bit 11 off Disable APU Instruction Broadcast
|
* bit 11 off Disable APU Instruction Broadcast
|
||||||
* bit 16 off Disable Trace Broadcast
|
* bit 16 off Disable Trace Broadcast
|
||||||
* bit 17:18 off Specifies behaviour of icbt,dcbt/dcbtst insts
|
* bit 17:18 on Specifies behaviour of icbt,dcbt/dcbtst insts
|
||||||
* bit 23 off Force Load/Store Alignment
|
* bit 23 off Force Load/Store Alignment
|
||||||
* bit 28:29 off Instruction Cache Speculative Line Count
|
* bit 28:29 off Instruction Cache Speculative Line Count
|
||||||
* bit 30:31 off Instruction Cache Speculative Line Threshold
|
* bit 30:31 off Instruction Cache Speculative Line Threshold
|
||||||
* NB: UG200/pg 21: Spec. prefetching must be disabled
|
* NB: UG200/pg 21: Spec. prefetching must be disabled
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
lis r2,0x0020 // 7. Set CCR0: DSTG
|
lis r2, 0x00206000@h // 7. Set CCR0: DSTG
|
||||||
|
ori r2,r2,0x00206000@l // Set CCR0: GDCBT, GICBT
|
||||||
mtccr0 r2 // Configure CCR0
|
mtccr0 r2 // Configure CCR0
|
||||||
|
|
||||||
mtspr ccr1,r0 // 8. Clear CCR1
|
mtspr PPC440_CCR1,r0 // 8. Clear CCR1
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
* 9. Configure cache regions
|
* 9. Configure cache regions
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
mtspr inv0,r0
|
mtspr PPC440_INV0,r0
|
||||||
mtspr inv1,r0
|
mtspr PPC440_INV1,r0
|
||||||
mtspr inv2,r0
|
mtspr PPC440_INV2,r0
|
||||||
mtspr inv3,r0
|
mtspr PPC440_INV3,r0
|
||||||
mtspr dnv0,r0
|
mtspr PPC440_DNV0,r0
|
||||||
mtspr dnv1,r0
|
mtspr PPC440_DNV1,r0
|
||||||
mtspr dnv2,r0
|
mtspr PPC440_DNV2,r0
|
||||||
mtspr dnv3,r0
|
mtspr PPC440_DNV3,r0
|
||||||
mtspr itv0,r0
|
mtspr PPC440_ITV0,r0
|
||||||
mtspr itv1,r0
|
mtspr PPC440_ITV1,r0
|
||||||
mtspr itv2,r0
|
mtspr PPC440_ITV2,r0
|
||||||
mtspr itv3,r0
|
mtspr PPC440_ITV3,r0
|
||||||
mtspr dtv0,r0
|
mtspr PPC440_DTV0,r0
|
||||||
mtspr dtv1,r0
|
mtspr PPC440_DTV1,r0
|
||||||
mtspr dtv2,r0
|
mtspr PPC440_DTV2,r0
|
||||||
mtspr dtv3,r0
|
mtspr PPC440_DTV3,r0
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
* Cache victim limits
|
* Cache victim limits
|
||||||
@@ -198,8 +200,8 @@ first: li r0,0 // Clear r0
|
|||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
lis r2, 0x0001f800@h
|
lis r2, 0x0001f800@h
|
||||||
ori r2,r2,0x0001f800@l
|
ori r2,r2,0x0001f800@l
|
||||||
mtspr ivlim,r2
|
mtspr PPC440_IVLIM,r2
|
||||||
mtspr dvlim,r2
|
mtspr PPC440_DVLIM,r2
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
* Configure instruction and data cache regions:
|
* Configure instruction and data cache regions:
|
||||||
@@ -241,7 +243,7 @@ first: li r0,0 // Clear r0
|
|||||||
* 31 SR 1 1 Supervisor State Read Enable
|
* 31 SR 1 1 Supervisor State Read Enable
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
|
|
||||||
mtspr mmucr,r0 // 10a. Clear MMUCR
|
mtspr PPC440_MMUCR,r0 // 10a. Clear MMUCR
|
||||||
li r7,WIMG_U_S_1 // Word 2: Pages are NOT cache inhibited
|
li r7,WIMG_U_S_1 // Word 2: Pages are NOT cache inhibited
|
||||||
lis r6, PAGE_SZ@h // Page size constant
|
lis r6, PAGE_SZ@h // Page size constant
|
||||||
ori r6,r6,PAGE_SZ@l
|
ori r6,r6,PAGE_SZ@l
|
||||||
@@ -255,9 +257,9 @@ first: li r0,0 // Clear r0
|
|||||||
* Select whether Wait Enable, interrupts/exceptions and which address
|
* Select whether Wait Enable, interrupts/exceptions and which address
|
||||||
* spaces should be enabled when application starts
|
* spaces should be enabled when application starts
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
lis r0, 0x00000000@h // 10d. MSR[IS]=0 MSR[DS]=0
|
lis r3, 0x00000000@h // 10d. MSR[IS]=0 MSR[DS]=0
|
||||||
ori r0,r0,0x00000000@l
|
ori r3,r3,0x00000000@l
|
||||||
mtsrr1 r0
|
mtsrr1 r3
|
||||||
mtsrr0 r28 // Return address
|
mtsrr0 r28 // Return address
|
||||||
rfi // Context synchronize to invalidate shadow TLB contents
|
rfi // Context synchronize to invalidate shadow TLB contents
|
||||||
|
|
||||||
@@ -275,43 +277,43 @@ startupDL:
|
|||||||
* 11. Tell the processor where the exception vector table will be
|
* 11. Tell the processor where the exception vector table will be
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
.extern SYM(__vectors)
|
.extern SYM(__vectors)
|
||||||
lis r2, __vectors@h /* set EVPR exc. vector prefix */
|
lis r1, __vectors@h /* set EVPR exc. vector prefix */
|
||||||
mtspr ivpr,r2
|
mtspr BOOKE_IVPR,r1
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
* Set up default exception and interrupt vectors
|
* Set up default exception and interrupt vectors
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
li r1,0x100
|
li r1,0
|
||||||
mtivor0 r1
|
mtivor0 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor1 r1
|
mtivor1 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor2 r1
|
mtivor2 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor3 r1
|
mtivor3 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor4 r1
|
mtivor4 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor5 r1
|
mtivor5 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor6 r1
|
mtivor6 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor7 r1
|
mtivor7 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor8 r1
|
mtivor8 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor9 r1
|
mtivor9 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor10 r1
|
mtivor10 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor11 r1
|
mtivor11 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor12 r1
|
mtivor12 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor13 r1
|
mtivor13 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor14 r1
|
mtivor14 r1
|
||||||
addi r1,r1,0x100
|
addi r1,r1,0x10
|
||||||
mtivor15 r1
|
mtivor15 r1
|
||||||
|
|
||||||
/*------------------------------------------------------------------
|
/*------------------------------------------------------------------
|
||||||
@@ -336,16 +338,15 @@ startupDL:
|
|||||||
* 13. Configure timer facilities
|
* 13. Configure timer facilities
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
mtdec r0 // Clear Decrementer to prevent exception
|
mtdec r0 // Clear Decrementer to prevent exception
|
||||||
mttbu r0 // Clear Timebase to prevent Fixed Interval..
|
mttbl r0 // Clear Timebase to prevent Fixed Interval..
|
||||||
mttbl r0 // ..timer and Watchdog Timer exceptions
|
mttbu r0 // ..timer and Watchdog Timer exceptions
|
||||||
mtpit r0 // Programmable interval timer
|
mtpit r0 // Programmable interval timer
|
||||||
li r1,-1 // -1 to clear TSR
|
li r2,-1 // -1 to clear TSR
|
||||||
mttsr r1 // Timer status register
|
mttsr r2 // Timer status register
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
* Clear out stale values in certain registers to avoid confusion
|
* Clear out stale values in certain registers to avoid confusion
|
||||||
*------------------------------------------------------------------*/
|
*------------------------------------------------------------------*/
|
||||||
li r0,0
|
|
||||||
mtcrf 0xff,r0 // Need for simulation
|
mtcrf 0xff,r0 // Need for simulation
|
||||||
mtctr r0 // Counter register
|
mtctr r0 // Counter register
|
||||||
mtxer r0 // Fixed-point exception register
|
mtxer r0 // Fixed-point exception register
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ AM_CONDITIONAL(mpc6xx, test "$RTEMS_CPU_MODEL" = "mpc6xx" \
|
|||||||
|| test "$RTEMS_CPU_MODEL" = "mpc750" \
|
|| test "$RTEMS_CPU_MODEL" = "mpc750" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "mpc8240" \
|
|| test "$RTEMS_CPU_MODEL" = "mpc8240" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "mpc8245" \
|
|| test "$RTEMS_CPU_MODEL" = "mpc8245" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "mpc83xx" )
|
|| test "$RTEMS_CPU_MODEL" = "mpc83xx")
|
||||||
AM_CONDITIONAL(mpc8xx, test "$RTEMS_CPU_MODEL" = "mpc8xx" \
|
AM_CONDITIONAL(mpc8xx, test "$RTEMS_CPU_MODEL" = "mpc8xx" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "mpc821" \
|
|| test "$RTEMS_CPU_MODEL" = "mpc821" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "mpc860" )
|
|| test "$RTEMS_CPU_MODEL" = "mpc860" )
|
||||||
@@ -65,15 +65,15 @@ AM_CONDITIONAL(mpc8260, test "$RTEMS_CPU_MODEL" = "mpc8260")
|
|||||||
AM_CONDITIONAL(mpc83xx, test "$RTEMS_CPU_MODEL" = "mpc83xx")
|
AM_CONDITIONAL(mpc83xx, test "$RTEMS_CPU_MODEL" = "mpc83xx")
|
||||||
AM_CONDITIONAL(qoriq, test "$RTEMS_CPU_MODEL" = "qoriq")
|
AM_CONDITIONAL(qoriq, test "$RTEMS_CPU_MODEL" = "qoriq")
|
||||||
|
|
||||||
# the ppc405 and ppc440 share files with the ppc403
|
# the ppc405 share files with the ppc403
|
||||||
AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403")
|
AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403")
|
||||||
AM_CONDITIONAL(ppc405, test "$RTEMS_CPU_MODEL" = "ppc405")
|
AM_CONDITIONAL(ppc405, test "$RTEMS_CPU_MODEL" = "ppc405")
|
||||||
AM_CONDITIONAL(ppc440, test "$RTEMS_CPU_MODEL" = "ppc440")
|
AM_CONDITIONAL(ppc440, test "$RTEMS_CPU_MODEL" = "ppc440")
|
||||||
AM_CONDITIONAL(ppc4xx, test "$RTEMS_CPU_MODEL" = "ppc403" \
|
AM_CONDITIONAL(ppc4xx, test "$RTEMS_CPU_MODEL" = "ppc403" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "ppc405" \
|
|| test "$RTEMS_CPU_MODEL" = "ppc405")
|
||||||
|| test "$RTEMS_CPU_MODEL" = "ppc440")
|
|
||||||
|
|
||||||
AM_CONDITIONAL(e500, test "$RTEMS_CPU_MODEL" = "e500" \
|
AM_CONDITIONAL(e500, test "$RTEMS_CPU_MODEL" = "e500" \
|
||||||
|
|| test "$RTEMS_CPU_MODEL" = "ppc440" \
|
||||||
|| test "$RTEMS_CPU_MODEL" = "qoriq" )
|
|| test "$RTEMS_CPU_MODEL" = "qoriq" )
|
||||||
|
|
||||||
RTEMS_CHECK_NETWORKING
|
RTEMS_CHECK_NETWORKING
|
||||||
|
|||||||
Reference in New Issue
Block a user