forked from Imagelibrary/rtems
added haleakala BSP contributed by Michael Hamel
This commit is contained in:
@@ -1,3 +1,13 @@
|
||||
2008-07-14 Thomas Doerfler <thomas.doerfler@embedded-brains.de>
|
||||
|
||||
* Makefile.am, new-exceptions/raw_exception.c,
|
||||
* new-exceptions/bspsupport/irq.c, ppc403/clock/clock_4xx.c,
|
||||
* ppc403/include/ppc405ex.h, ppc403/include/ppc405gp.h,
|
||||
* ppc403/timer/timer.c, rtems/powerpc/powerpc.h,
|
||||
* shared/include/cpuIdent.c, shared/include/cpuIdent.h,
|
||||
* shared/include/powerpc-utility.h:
|
||||
Added support for PPC405EX (contributed by Michael Hamel)
|
||||
|
||||
2008-07-11 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* Makefile.am: Install powerpc-utility.h.
|
||||
@@ -15,13 +25,14 @@
|
||||
ppc_exc_vector_base for CPUs with IVPR register.
|
||||
|
||||
* new-exceptions/bspsupport/ppc_exc.S,
|
||||
new-exceptions/bspsupport/ppc_exc_asm_macros.h,
|
||||
new-exceptions/bspsupport/ppc_exc_bspsupp.h,
|
||||
new-exceptions/bspsupport/ppc_exc_hdl.c,
|
||||
new-exceptions/bspsupport/vectors.h,
|
||||
new-exceptions/bspsupport/vectors_init.c: Conistent code layout in most
|
||||
assember code sections and usage of defines for registers. Usage of
|
||||
standard header files to avoid multiple definitions.
|
||||
* new-exceptions/bspsupport/ppc_exc_asm_macros.h,
|
||||
* new-exceptions/bspsupport/ppc_exc_bspsupp.h,
|
||||
* new-exceptions/bspsupport/ppc_exc_hdl.c,
|
||||
* new-exceptions/bspsupport/vectors.h,
|
||||
* new-exceptions/bspsupport/vectors_init.c:
|
||||
Conistent code layout in most assember code sections and usage of
|
||||
defines for registers. Usage of standard header files to avoid
|
||||
multiple definitions.
|
||||
|
||||
Optimized exception code: Removed many branches and exploit branch
|
||||
prediction for asynchronous exceptions, moved common wrap code into
|
||||
|
||||
@@ -126,8 +126,19 @@ ppc403_tty_drv_rel_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
ppc403_tty_drv_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
endif
|
||||
|
||||
endif
|
||||
endif # ppc403
|
||||
|
||||
if ppc405
|
||||
|
||||
## ppc4xx/include
|
||||
include_ppc4xxdir = $(includedir)/ppc4xx
|
||||
include_ppc4xx_HEADERS = ppc403/include/ppc405gp.h \
|
||||
ppc403/include/ppc405ex.h
|
||||
|
||||
endif # ppc405
|
||||
|
||||
|
||||
## mpc5xx
|
||||
EXTRA_DIST += mpc5xx/README
|
||||
if mpc5xx
|
||||
include_mpc5xxdir = $(includedir)/mpc5xx
|
||||
@@ -341,6 +352,7 @@ mpc8260_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
endif
|
||||
|
||||
if mpc83xx
|
||||
|
||||
include_mpc83xxdir = $(includedir)/mpc83xx
|
||||
include_mpc83xx_HEADERS = mpc83xx/include/mpc83xx.h
|
||||
include_mpc83xx_HEADERS += mpc83xx/network/tsec.h
|
||||
|
||||
@@ -38,6 +38,7 @@ static rtems_irq_connect_data* rtems_hdl_tbl;
|
||||
|
||||
|
||||
SPR_RW(BOOKE_TSR)
|
||||
SPR_RW(PPC405_TSR)
|
||||
|
||||
/* legacy mode for bookE DEC exception;
|
||||
* to avoid the double layer of function calls
|
||||
@@ -52,8 +53,12 @@ int C_dispatch_dec_handler_bookE (BSP_Exception_frame *frame, unsigned int excNu
|
||||
/* clear interrupt; we must do this
|
||||
* before C_dispatch_irq_handler()
|
||||
* re-enables MSR_EE.
|
||||
* Note that PPC405 uses a different SPR# for TSR
|
||||
*/
|
||||
_write_BOOKE_TSR( BOOKE_TSR_DIS );
|
||||
if ( ppc_cpu_is_bookE()==PPC_BOOKE_405)
|
||||
_write_PPC405_TSR( BOOKE_TSR_DIS );
|
||||
else
|
||||
_write_BOOKE_TSR( BOOKE_TSR_DIS );
|
||||
return C_dispatch_irq_handler(frame, ASM_DEC_VECTOR);
|
||||
}
|
||||
|
||||
|
||||
@@ -162,7 +162,8 @@ static const cat_ini_t mpc_5xx_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
|
||||
static const cat_ini_t ppc_405_vector_categories[LAST_VALID_EXC + 1] = {
|
||||
[ ASM_EXT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC,
|
||||
[ ASM_BOOKE_DEC_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, /* PIT */
|
||||
[ ASM_BOOKE_FIT_VECTOR ] = PPC_EXC_CLASSIC | PPC_EXC_ASYNC, /* FIT */
|
||||
|
||||
[ ASM_PROT_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
[ ASM_ISI_VECTOR ] = PPC_EXC_CLASSIC,
|
||||
@@ -371,6 +372,8 @@ ppc_raw_exception_category rval = PPC_EXC_INVALID;
|
||||
rval = mpc_860_vector_categories[vector];
|
||||
break;
|
||||
case PPC_405:
|
||||
case PPC_405GP:
|
||||
case PPC_405EX:
|
||||
rval = ppc_405_vector_categories[vector];
|
||||
break;
|
||||
default:
|
||||
|
||||
251
c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c
Normal file
251
c/src/lib/libcpu/powerpc/ppc403/clock/clock_4xx.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/* clock.c
|
||||
*
|
||||
* This routine initializes the interval timer on the
|
||||
* PowerPC 405 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
|
||||
*
|
||||
* Further modifications for PPC405GP/EX by Michael Hamel
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/clockdrv.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h> /* for atexit() */
|
||||
#include <rtems/bspIo.h>
|
||||
#include <ppc405common.h>
|
||||
#include <libcpu/cpuIdent.h>
|
||||
#include <bsp/irq.h>
|
||||
|
||||
|
||||
|
||||
/* PPC405GP */
|
||||
#define CPC0_CR1 0xB2
|
||||
#define CR1_CETE 0x00800000
|
||||
|
||||
/* PPC405EX */
|
||||
#define SDR0_C405 0x180
|
||||
#define SDR_CETE 0x02000000
|
||||
|
||||
volatile uint32_t Clock_driver_ticks;
|
||||
static uint32_t pit_value, tick_time;
|
||||
|
||||
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 */
|
||||
);
|
||||
|
||||
/* Defined in bspstart.c */
|
||||
extern uint32_t bsp_clicks_per_usec;
|
||||
extern boolean bsp_timer_internal_clock;
|
||||
|
||||
/*
|
||||
* These are set by clock driver during its init
|
||||
*/
|
||||
|
||||
rtems_device_major_number rtems_clock_major = ~0;
|
||||
rtems_device_minor_number rtems_clock_minor;
|
||||
|
||||
/*
|
||||
* ISR Handler
|
||||
*/
|
||||
|
||||
void Clock_isr(void* handle)
|
||||
{
|
||||
Clock_driver_ticks++;
|
||||
rtems_clock_tick();
|
||||
}
|
||||
|
||||
int ClockIsOn(const rtems_irq_connect_data* unused)
|
||||
{
|
||||
return ((mfspr(TCR) & PIE) != 0);
|
||||
}
|
||||
|
||||
|
||||
void ClockOff(const rtems_irq_connect_data* unused)
|
||||
{
|
||||
register uint32_t r;
|
||||
|
||||
r = mfspr(TCR);
|
||||
mtspr(TCR, r & ~(PIE | ARE) );
|
||||
}
|
||||
|
||||
void ClockOn(const rtems_irq_connect_data* unused)
|
||||
{
|
||||
uint32_t iocr, r;
|
||||
ppc_cpu_id_t cpu;
|
||||
Clock_driver_ticks = 0;
|
||||
|
||||
cpu = get_ppc_cpu_type();
|
||||
if (cpu==PPC_405GP) {
|
||||
iocr = mfdcr(CPC0_CR1);
|
||||
if (bsp_timer_internal_clock) iocr &= ~CR1_CETE ;/* timer clocked from system clock */
|
||||
else iocr |= CR1_CETE; /* select external timer clock */
|
||||
mtdcr(CPC0_CR1,iocr);
|
||||
} else if (cpu==PPC_405EX) {
|
||||
mfsdr(SDR0_C405,iocr);
|
||||
if (bsp_timer_internal_clock) iocr &= ~SDR_CETE ;/* timer clocked from system clock */
|
||||
else iocr |= SDR_CETE; /* select external timer clock */
|
||||
mtsdr(SDR0_C405,iocr);
|
||||
} else {
|
||||
printk("clock.c:unrecognised CPU");
|
||||
rtems_fatal_error_occurred(1);
|
||||
}
|
||||
|
||||
pit_value = rtems_configuration_get_microseconds_per_tick() * bsp_clicks_per_usec;
|
||||
mtspr(PIT,pit_value);
|
||||
|
||||
tick_time = mfspr(TBL) + pit_value;
|
||||
r = mfspr(TCR);
|
||||
mtspr(TCR, r | PIE | ARE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Install_clock(void (*clock_isr)(void *))
|
||||
{
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
rtems_irq_connect_data clockIrqConnData;
|
||||
|
||||
Clock_driver_ticks = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
ReInstall_clock(void (*new_clock_isr)(void *))
|
||||
{
|
||||
uint32_t isrlevel = 0;
|
||||
rtems_irq_connect_data clockIrqConnData;
|
||||
|
||||
rtems_interrupt_disable(isrlevel);
|
||||
clockIrqConnData.name = BSP_PIT;
|
||||
if ( ! BSP_get_current_rtems_irq_handler(&clockIrqConnData)) {
|
||||
printk("Unable to stop system clock\n");
|
||||
rtems_fatal_error_occurred(1);
|
||||
}
|
||||
|
||||
BSP_remove_rtems_irq_handler (&clockIrqConnData);
|
||||
clockIrqConnData.on = ClockOn;
|
||||
clockIrqConnData.off = ClockOff;
|
||||
clockIrqConnData.isOn = ClockIsOn;
|
||||
clockIrqConnData.name = BSP_PIT;
|
||||
clockIrqConnData.hdl = new_clock_isr;
|
||||
if (!BSP_install_rtems_irq_handler (&clockIrqConnData)) {
|
||||
printk("Unable to connect Clock Irq handler\n");
|
||||
rtems_fatal_error_occurred(1);
|
||||
}
|
||||
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)
|
||||
{
|
||||
rtems_irq_connect_data clockIrqConnData;
|
||||
|
||||
clockIrqConnData.name = BSP_PIT;
|
||||
if (!BSP_get_current_rtems_irq_handler(&clockIrqConnData)) {
|
||||
printk("Unable to stop system clock\n");
|
||||
rtems_fatal_error_occurred(1);
|
||||
}
|
||||
BSP_remove_rtems_irq_handler (&clockIrqConnData);
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
rtems_device_driver Clock_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *pargp
|
||||
)
|
||||
{
|
||||
rtems_libio_ioctl_args_t* args = pargp;
|
||||
|
||||
if (args!=NULL) {
|
||||
/*
|
||||
* This is hokey, but until we get a defined interface
|
||||
* to do this, it will just be this simple...
|
||||
*/
|
||||
|
||||
if (args->command == rtems_build_name('I', 'S', 'R', ' '))
|
||||
Clock_isr(NULL);
|
||||
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
|
||||
ReInstall_clock(args->buffer);
|
||||
}
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
158
c/src/lib/libcpu/powerpc/ppc403/include/ppc405ex.h
Normal file
158
c/src/lib/libcpu/powerpc/ppc403/include/ppc405ex.h
Normal file
@@ -0,0 +1,158 @@
|
||||
|
||||
/*
|
||||
|
||||
Constants for manipulating system registers of PPC 405EX in C
|
||||
|
||||
Michael Hamel ADInstruments May 2008
|
||||
|
||||
*/
|
||||
|
||||
#include <libcpu/powerpc-utility.h>
|
||||
/* Indirect access to Clocking/Power-On registers */
|
||||
#define CPR0_DCR_BASE 0x0C
|
||||
#define cprcfga (CPR0_DCR_BASE+0x0)
|
||||
#define cprcfgd (CPR0_DCR_BASE+0x1)
|
||||
|
||||
#define mtcpr(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(cprcfga,reg); \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(cprcfgd,d); \
|
||||
} while (0)
|
||||
|
||||
#define mfcpr(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(cprcfga,reg); \
|
||||
d = PPC_DEVICE_CONTROL_REGISTER(cprcfgd); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Indirect access to System registers */
|
||||
#define SDR_DCR_BASE 0x0E
|
||||
#define sdrcfga (SDR_DCR_BASE+0x0)
|
||||
#define sdrcfgd (SDR_DCR_BASE+0x1)
|
||||
|
||||
#define mtsdr(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(sdrcfga,reg); \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(sdrcfgd,d); \
|
||||
} while (0)
|
||||
|
||||
#define mfsdr(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(sdrcfga,reg); \
|
||||
d = PPC_DEVICE_CONTROL_REGISTER(sdrcfgd); \
|
||||
} while (0)
|
||||
|
||||
/* Indirect access to EBC registers */
|
||||
#define EBC_DCR_BASE 0x12
|
||||
#define ebccfga (EBC_DCR_BASE+0x0)
|
||||
#define ebccfgd (EBC_DCR_BASE+0x1)
|
||||
|
||||
#define mtebc(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(ebccfga,reg); \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(ebccfgd,d); \
|
||||
} while (0)
|
||||
|
||||
#define mfebc(reg, d) \
|
||||
do { \
|
||||
PPC_SET_DEVICE_CONTROL_REGISTER(ebccfga,reg); \
|
||||
d = PPC_DEVICE_CONTROL_REGISTER(ebccfgd); \
|
||||
} while (0)
|
||||
|
||||
/* EBC DCRs */
|
||||
enum {
|
||||
/*
|
||||
EBC0_B0CR = 0,
|
||||
EBC0_B1CR = 1,
|
||||
EBC0_B2CR = 2,
|
||||
EBC0_B3CR = 3,
|
||||
EBC0_B0AP = 0x10,
|
||||
EBC0_B1AP = 0x11,
|
||||
EBC0_B2AP = 0x12,
|
||||
EBC0_B3AP = 0x13,
|
||||
EBC0_BEAR = 0x20,
|
||||
EBC0_BESR = 0x21,
|
||||
EBC0_CFG = 0x23,
|
||||
*/
|
||||
EBC0_CID = 0x24
|
||||
};
|
||||
|
||||
enum {
|
||||
SDR0_UART0 = 0x120,
|
||||
SDR0_UART1 = 0x121,
|
||||
SDR0_C405 = 0x180,
|
||||
SDR0_MALTBL = 0x280,
|
||||
SDR0_MALRBL = 0x2A0,
|
||||
SDR0_MALTBS = 0x2C0,
|
||||
SDR0_MALRBS = 0x2E0
|
||||
};
|
||||
|
||||
|
||||
/* Memory-mapped registers */
|
||||
|
||||
|
||||
/*======================= Ethernet =================== */
|
||||
|
||||
|
||||
typedef struct EthernetRegisters_EX {
|
||||
uint32_t mode0;
|
||||
uint32_t mode1;
|
||||
uint32_t xmtMode0;
|
||||
uint32_t xmtMode1;
|
||||
uint32_t rcvMode;
|
||||
uint32_t intStatus;
|
||||
uint32_t intEnable;
|
||||
uint32_t addrHi;
|
||||
uint32_t addrLo;
|
||||
uint32_t VLANTPID;
|
||||
uint32_t VLANTCI;
|
||||
uint32_t pauseTimer;
|
||||
uint32_t multicastAddr[2];
|
||||
uint32_t multicastMask[2];
|
||||
uint32_t unused[4];
|
||||
uint32_t lastSrcLo;
|
||||
uint32_t lastSrcHi;
|
||||
uint32_t IPGap;
|
||||
uint32_t STAcontrol;
|
||||
uint32_t xmtReqThreshold;
|
||||
uint32_t rcvWatermark;
|
||||
uint32_t bytesXmtd;
|
||||
uint32_t bytesRcvd;
|
||||
uint32_t unused2;
|
||||
uint32_t revID;
|
||||
uint32_t unused3[2];
|
||||
uint32_t indivHash[8];
|
||||
uint32_t groupHash[8];
|
||||
uint32_t xmtPause;
|
||||
} EthernetRegisters_EX;
|
||||
|
||||
enum {
|
||||
EMAC0Address = 0xEF600900,
|
||||
EMAC1Address = 0xEF600A00
|
||||
};
|
||||
|
||||
|
||||
typedef struct GPIORegisters {
|
||||
uint32_t OR;
|
||||
uint32_t GPIO_TCR; /* Note that TCR is defined as a DCR name */
|
||||
uint32_t OSRL;
|
||||
uint32_t OSRH;
|
||||
uint32_t TSRL;
|
||||
uint32_t TSRH;
|
||||
uint32_t ODR;
|
||||
uint32_t IR;
|
||||
uint32_t RR1;
|
||||
uint32_t RR2;
|
||||
uint32_t RR3;
|
||||
uint32_t unknown;
|
||||
uint32_t ISR1L;
|
||||
uint32_t ISR1H;
|
||||
uint32_t ISR2L;
|
||||
uint32_t ISR2H;
|
||||
uint32_t ISR3L;
|
||||
uint32_t ISR3H;
|
||||
} GPIORegisters;
|
||||
|
||||
enum { GPIOAddress = 0xEF600800 };
|
||||
|
||||
146
c/src/lib/libcpu/powerpc/ppc403/include/ppc405gp.h
Normal file
146
c/src/lib/libcpu/powerpc/ppc403/include/ppc405gp.h
Normal file
@@ -0,0 +1,146 @@
|
||||
|
||||
|
||||
/* SDRAM DCRs */
|
||||
enum {
|
||||
SDRAM0_BESR0 = 0,
|
||||
SDRAM0_BESR1 = 8,
|
||||
SDRAM0_BEAR = 0x10,
|
||||
SDRAM0_CFG = 0x20,
|
||||
SDRAM0_STATUS = 0x24,
|
||||
SDRAM0_RTR = 0x30,
|
||||
SDRAM0_PMIT = 0x34,
|
||||
SDRAM0_TR = 0x80
|
||||
};
|
||||
|
||||
|
||||
/* EBC DCRs */
|
||||
enum {
|
||||
EBC0_B0CR = 0,
|
||||
EBC0_B1CR = 1,
|
||||
EBC0_B2CR = 2,
|
||||
EBC0_B3CR = 3,
|
||||
EBC0_B4CR = 4,
|
||||
EBC0_B5CR = 5,
|
||||
EBC0_B6CR = 6,
|
||||
EBC0_B7CR = 7,
|
||||
EBC0_B0AP = 0x10,
|
||||
EBC0_B1AP = 0x11,
|
||||
EBC0_B2AP = 0x12,
|
||||
EBC0_B3AP = 0x13,
|
||||
EBC0_B4AP = 0x14,
|
||||
EBC0_B5AP = 0x15,
|
||||
EBC0_B6AP = 0x16,
|
||||
EBC0_B7AP = 0x17,
|
||||
EBC0_BEAR = 0x20,
|
||||
EBC0_BESR0 = 0x21,
|
||||
EBC0_BESR1 = 0x22,
|
||||
EBC0_CFG = 0x23
|
||||
};
|
||||
|
||||
/* Memory-mapped registers */
|
||||
|
||||
typedef struct EthernetRegisters_GP {
|
||||
uint32_t mode0;
|
||||
uint32_t mode1;
|
||||
uint32_t xmtMode0;
|
||||
uint32_t xmtMode1;
|
||||
uint32_t rcvMode;
|
||||
uint32_t intStatus;
|
||||
uint32_t intEnable;
|
||||
uint32_t addrHi;
|
||||
uint32_t addrLo;
|
||||
uint32_t VLANTPID;
|
||||
uint32_t VLANTCI;
|
||||
uint32_t pauseTimer;
|
||||
uint32_t indivHash[4];
|
||||
uint32_t groupHash[4];
|
||||
uint32_t lastSrcLo;
|
||||
uint32_t lastSrcHi;
|
||||
uint32_t IPGap;
|
||||
uint32_t STAcontrol;
|
||||
uint32_t xmtReqThreshold;
|
||||
uint32_t rcvWatermark;
|
||||
uint32_t bytesXmtd;
|
||||
uint32_t bytesRcvd;
|
||||
} EthernetRegisters_GP;
|
||||
|
||||
enum { EMACAddress = 0xEF600800 };
|
||||
|
||||
enum {
|
||||
// Mode 0 bits
|
||||
kEMACRxIdle = 0x80000000,
|
||||
kEMACTxIdle = 0x40000000,
|
||||
kEMACSoftRst = 0x20000000,
|
||||
kEMACTxEnable = 0x10000000,
|
||||
kEMACRxEnable = 0x08000000,
|
||||
|
||||
// Mode 1 bits
|
||||
kEMACFullDuplex = 0x80000000,
|
||||
kEMACIgnoreSQE = 0x01000000,
|
||||
kEMAC100MBbps = 0x00400000,
|
||||
kEMAC4KRxFIFO = 0x00300000,
|
||||
kEMAC2KTxFIFO = 0x00080000,
|
||||
kEMACTx0Multi = 0x00008000,
|
||||
kEMACTxDependent= 0x00014000,
|
||||
|
||||
// Tx mode bits
|
||||
kEMACNewPacket0 = 0x80000000,
|
||||
kEMACNewPacket1 = 0x40000000,
|
||||
|
||||
// Receive mode bits
|
||||
kEMACStripPadding = 0x80000000,
|
||||
kEMACStripFCS = 0x40000000,
|
||||
kEMACRcvRunts = 0x20000000,
|
||||
kEMACRcvFCSErrs = 0x10000000,
|
||||
kEMACRcvOversize = 0x08000000,
|
||||
kEMACPromiscRcv = 0x01000000,
|
||||
kEMACPromMultRcv = 0x00800000,
|
||||
kEMACIndivRcv = 0x00400000,
|
||||
kEMACHashRcv = 0x00200000,
|
||||
kEMACBrcastRcv = 0x00100000,
|
||||
kEMACMultcastRcv = 0x00080000,
|
||||
|
||||
// Buffer descriptor control bits
|
||||
kMALTxReady = 0x8000,
|
||||
kMALRxEmpty = 0x8000,
|
||||
kMALWrap = 0x4000,
|
||||
kMALContinuous = 0x2000,
|
||||
kMALLast = 0x1000,
|
||||
kMALRxFirst = 0x0800,
|
||||
kMALInterrupt = 0x0400,
|
||||
|
||||
// EMAC Tx descriptor bits sent
|
||||
kEMACGenFCS = 0x200,
|
||||
kEMACGenPad = 0x100,
|
||||
kEMACInsSrcAddr = 0x080,
|
||||
kEMACRepSrcAddr = 0x040,
|
||||
kEMACInsVLAN = 0x020,
|
||||
kEMACRepVLAN = 0x010,
|
||||
|
||||
// EMAC TX descriptor bits returned
|
||||
kEMACErrMask = 0x3FF,
|
||||
kEMACFCSWrong = 0x200,
|
||||
kEMACBadPrev = 0x100,
|
||||
kEMACLostCarrier = 0x080,
|
||||
kEMACDeferred = 0x040,
|
||||
kEMACCollFail = 0x020,
|
||||
kEMACLateColl = 0x010,
|
||||
kEMACMultColl = 0x008,
|
||||
kEMACOneColl = 0x004,
|
||||
kEMACUnderrun = 0x002,
|
||||
kEMACSQEFail = 0x001,
|
||||
|
||||
// EMAC Rx descriptor bits returned
|
||||
kEMACOverrun = 0x200,
|
||||
kEMACPausePkt = 0x100,
|
||||
kEMACBadPkt = 0x080,
|
||||
kEMACRuntPkt = 0x040,
|
||||
kEMACShortEvt = 0x020,
|
||||
kEMACAlignErr = 0x010,
|
||||
kEMACBadFCS = 0x008,
|
||||
kEMACPktLong = 0x004,
|
||||
kEMACPktOOR = 0x002,
|
||||
kEMACPktIRL = 0x001
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* timer.c
|
||||
*
|
||||
* This file manages the interval timer on the PowerPC 403*.
|
||||
* This file manages the interval timer on the PowerPC 405.
|
||||
* We shall use the bottom 32 bits of the timebase register,
|
||||
*
|
||||
* NOTE: It is important that the timer start/stop overhead be
|
||||
@@ -32,85 +32,47 @@
|
||||
*
|
||||
* Modifications for PPC405GP by Dennis Ehlin
|
||||
*
|
||||
* Further mods for PPC405EX/EXr by Michael Hamel
|
||||
*
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <libcpu/powerpc-utility.h>
|
||||
|
||||
static volatile uint32_t Timer_starting;
|
||||
static rtems_boolean Timer_driver_Find_average_overhead;
|
||||
extern uint32_t bsp_timer_least_valid;
|
||||
extern uint32_t bsp_timer_average_overhead;
|
||||
|
||||
/*
|
||||
* This is so small that this code will be reproduced where needed.
|
||||
*/
|
||||
static inline uint32_t get_itimer(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
#ifndef ppc405
|
||||
asm volatile ("mfspr %0, 0x3dd" : "=r" ((ret))); /* TBLO */
|
||||
#else /* ppc405 */
|
||||
/* asm volatile ("mfspr %0, 0x3dd" : "=r" ((ret))); TBLO */
|
||||
|
||||
asm volatile ("mfspr %0, 0x10c" : "=r" ((ret))); /* 405GP TBL */
|
||||
#endif /* ppc405 */
|
||||
|
||||
return ret;
|
||||
}
|
||||
static volatile uint32_t startedAt;
|
||||
static rtems_boolean subtractOverhead;
|
||||
|
||||
void Timer_initialize()
|
||||
{
|
||||
uint32_t iocr;
|
||||
|
||||
#ifndef ppc405
|
||||
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
|
||||
iocr &= ~4;
|
||||
iocr |= 4; /* Select external timer clock */
|
||||
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */
|
||||
#else /* ppc405 */
|
||||
asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */
|
||||
/* asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); IOCR */
|
||||
|
||||
/* iocr |= 0x800000; select external timer clock CETE*/
|
||||
iocr &= ~0x800000; /* timer clocked from system clock CETE*/
|
||||
|
||||
asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */
|
||||
/* asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); IOCR */
|
||||
#endif /* ppc405 */
|
||||
|
||||
Timer_starting = get_itimer();
|
||||
/* We are going to rely on clock.c to sort out where the clock comes from */
|
||||
startedAt = ppc_time_base();
|
||||
}
|
||||
|
||||
int Read_timer()
|
||||
{
|
||||
uint32_t clicks;
|
||||
uint32_t total;
|
||||
extern uint32_t bsp_timer_least_valid;
|
||||
extern uint32_t bsp_timer_average_overhead;
|
||||
uint32_t clicks, total;
|
||||
|
||||
clicks = get_itimer();
|
||||
|
||||
total = clicks - Timer_starting;
|
||||
|
||||
if ( Timer_driver_Find_average_overhead == 1 )
|
||||
return total; /* in XXX microsecond units */
|
||||
|
||||
else {
|
||||
if ( total < bsp_timer_least_valid )
|
||||
return 0; /* below timer resolution */
|
||||
return (total - bsp_timer_average_overhead);
|
||||
}
|
||||
clicks = ppc_time_base();
|
||||
total = clicks - startedAt;
|
||||
if ( ! subtractOverhead )
|
||||
return total; /* in XXX microsecond units */
|
||||
else if ( total < bsp_timer_least_valid )
|
||||
return 0; /* below timer resolution */
|
||||
else
|
||||
return (total - bsp_timer_average_overhead);
|
||||
}
|
||||
|
||||
rtems_status_code Empty_function( void )
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void Set_find_average_overhead(
|
||||
rtems_boolean find_flag
|
||||
)
|
||||
void Set_find_average_overhead( rtems_boolean find_flag)
|
||||
{
|
||||
Timer_driver_Find_average_overhead = find_flag;
|
||||
subtractOverhead = find_flag;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,10 @@ $(PROJECT_INCLUDE)/libcpu/$(dirstamp):
|
||||
@: > $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
|
||||
|
||||
$(PROJECT_INCLUDE)/libcpu/powerpc-utility.h: shared/include/powerpc-utility.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/powerpc-utility.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/powerpc-utility.h
|
||||
|
||||
if !mpc5xx
|
||||
$(PROJECT_INCLUDE)/libcpu/raw_exception.h: new-exceptions/raw_exception.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/raw_exception.h
|
||||
@@ -93,7 +97,21 @@ $(PROJECT_INCLUDE)/tty_drv.h: ppc403/tty_drv/tty_drv.h $(PROJECT_INCLUDE)/$(dirs
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tty_drv.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tty_drv.h
|
||||
endif
|
||||
endif
|
||||
endif # ppc403
|
||||
if ppc405
|
||||
$(PROJECT_INCLUDE)/ppc4xx/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/ppc4xx
|
||||
@: > $(PROJECT_INCLUDE)/ppc4xx/$(dirstamp)
|
||||
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/ppc4xx/$(dirstamp)
|
||||
|
||||
$(PROJECT_INCLUDE)/ppc4xx/ppc405gp.h: ppc403/include/ppc405gp.h $(PROJECT_INCLUDE)/ppc4xx/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ppc4xx/ppc405gp.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/ppc4xx/ppc405gp.h
|
||||
|
||||
$(PROJECT_INCLUDE)/ppc4xx/ppc405ex.h: ppc403/include/ppc405ex.h $(PROJECT_INCLUDE)/ppc4xx/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ppc4xx/ppc405ex.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/ppc4xx/ppc405ex.h
|
||||
endif # ppc405
|
||||
if mpc5xx
|
||||
$(PROJECT_INCLUDE)/mpc5xx/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/mpc5xx
|
||||
|
||||
@@ -115,6 +115,17 @@ extern "C" {
|
||||
#define PPC_HAS_EXCEPTION_PREFIX 0
|
||||
#define PPC_HAS_EVPR 1
|
||||
|
||||
#elif defined (ppc405)
|
||||
|
||||
#define PPC_CACHE_ALIGNMENT 32
|
||||
#define PPC_HAS_RI 0
|
||||
#define PPC_HAS_RFCI 1
|
||||
#define PPC_USE_MULTIPLE 1
|
||||
#define PPC_I_CACHE 16384
|
||||
#define PPC_D_CACHE 16384 /* except GP/CR */
|
||||
#define PPC_HAS_EXCEPTION_PREFIX 0
|
||||
#define PPC_HAS_EVPR 1
|
||||
|
||||
#elif defined(mpc555)
|
||||
|
||||
/* Copied from mpc505 */
|
||||
|
||||
@@ -31,6 +31,8 @@ char *get_ppc_cpu_type_name(ppc_cpu_id_t cpu)
|
||||
{
|
||||
switch (cpu) {
|
||||
case PPC_405: return "PPC405";
|
||||
case PPC_405GP: return "PPC405GP";
|
||||
case PPC_405EX: return "PPC405EX";
|
||||
case PPC_601: return "MPC601";
|
||||
case PPC_5XX: return "MPC5XX";
|
||||
case PPC_603: return "MPC603";
|
||||
@@ -69,6 +71,8 @@ ppc_cpu_id_t get_ppc_cpu_type()
|
||||
|
||||
switch (pvr) {
|
||||
case PPC_405:
|
||||
case PPC_405GP:
|
||||
case PPC_405EX:
|
||||
case PPC_601:
|
||||
case PPC_5XX:
|
||||
case PPC_603:
|
||||
@@ -128,6 +132,8 @@ ppc_cpu_id_t get_ppc_cpu_type()
|
||||
|
||||
switch ( current_ppc_cpu ) {
|
||||
case PPC_405:
|
||||
case PPC_405GP:
|
||||
case PPC_405EX:
|
||||
current_ppc_features.is_bookE = PPC_BOOKE_405;
|
||||
break;
|
||||
case PPC_8540:
|
||||
|
||||
@@ -32,6 +32,11 @@ typedef enum
|
||||
PPC_604r = 0xA,
|
||||
PPC_7400 = 0xC,
|
||||
PPC_405 = 0x2001,
|
||||
PPC_405EX = 0x1291, /* + 405EXr */
|
||||
PPC_405GP = 0x4011, /* + 405CR */
|
||||
PPC_405GPr = 0x5091,
|
||||
PPC_405EZ = 0x4151,
|
||||
PPC_405EP = 0x5121,
|
||||
PPC_7455 = 0x8001, /* Kate Feng */
|
||||
PPC_7457 = 0x8002,
|
||||
PPC_620 = 0x16,
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
* D-82178 Puchheim
|
||||
* Germany
|
||||
* rtems@embedded-brains.de
|
||||
*
|
||||
* access function for Device Control Registers inspired by "ppc405common.h"
|
||||
* from Michael Hamel ADInstruments May 2008
|
||||
*
|
||||
* 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.
|
||||
@@ -189,6 +192,7 @@ static inline void ppc_write_word( uint32_t value, volatile void *dest)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static inline void *ppc_stack_pointer()
|
||||
{
|
||||
void *sp;
|
||||
@@ -301,6 +305,8 @@ static inline void ppc_set_decrementer_register( uint32_t dec)
|
||||
PPC_Set_decrementer( dec);
|
||||
}
|
||||
|
||||
#define PPC_STRINGOF(x) #x
|
||||
|
||||
/* Do not use the following macros. Use the inline functions instead. */
|
||||
|
||||
#define PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER( spr) \
|
||||
@@ -324,6 +330,20 @@ static inline void ppc_set_decrementer_register( uint32_t dec)
|
||||
#define PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER_EXPAND( spr, val) \
|
||||
PPC_INTERNAL_MACRO_SET_SPECIAL_PURPOSE_REGISTER( spr, val)
|
||||
|
||||
/*
|
||||
* PPC4xx have Device Control Registers...
|
||||
*/
|
||||
#define PPC_DEVICE_CONTROL_REGISTER(dcr) \
|
||||
({uint32_t val;asm volatile ("mfspr %0," PPC_STRINGOF(dcr) \
|
||||
: "=r" (val)); val;})
|
||||
|
||||
#define PPC_SET_DEVICE_CONTROL_REGISTER(dcr,val) \
|
||||
do { \
|
||||
asm volatile ("mtspr " PPC_STRINGOF(dcr)",%0" \
|
||||
:: "r" (val)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
static inline uint32_t ppc_special_purpose_register_0()
|
||||
{
|
||||
PPC_INTERNAL_MACRO_RETURN_SPECIAL_PURPOSE_REGISTER_EXPAND( SPRG0);
|
||||
|
||||
Reference in New Issue
Block a user