From 35bb69b1cd7d5a54f5727195cc7b5f06a7cb2344 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 6 Apr 2001 15:52:03 +0000 Subject: 2001-03-30 Eric Valette * clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, include/8xx_immap.h, include/commproc.h, include/mbx.h, irq/.cvsignore, irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S, irq/irq_init.c, vectors/.cvsignore, vectors/Makefile.am, vectors/vectors.S, vectors/vectors.h, vectors/vectors_init.c: New files. * Makefile.am, configure.in, console/console.c, include/Makefile.am, network/network.c, startup/Makefile.am, startup/bspstart.c, startup/imbx8xx.c, startup/linkcmds, startup/mmutlbtab.c, startup/start.S, wrapup/Makefile.am: The modifications to this BSP reflect the conversion of the mpc8xx CPU to the "new exception processing model." --- c/src/lib/libbsp/powerpc/mbx8xx/ChangeLog | 15 + c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/mbx8xx/clock/.cvsignore | 2 + c/src/lib/libbsp/powerpc/mbx8xx/clock/Makefile.am | 26 + c/src/lib/libbsp/powerpc/mbx8xx/clock/p_clock.c | 70 +++ c/src/lib/libbsp/powerpc/mbx8xx/configure.in | 3 + c/src/lib/libbsp/powerpc/mbx8xx/console/console.c | 27 +- .../lib/libbsp/powerpc/mbx8xx/include/8xx_immap.h | 455 ++++++++++++++++++ .../lib/libbsp/powerpc/mbx8xx/include/Makefile.am | 20 +- c/src/lib/libbsp/powerpc/mbx8xx/include/commproc.h | 529 +++++++++++++++++++++ c/src/lib/libbsp/powerpc/mbx8xx/include/mbx.h | 62 +++ c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore | 2 + c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am | 46 ++ c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c | 506 ++++++++++++++++++++ c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h | 331 +++++++++++++ c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S | 329 +++++++++++++ c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c | 162 +++++++ c/src/lib/libbsp/powerpc/mbx8xx/network/network.c | 88 ++-- .../lib/libbsp/powerpc/mbx8xx/startup/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c | 48 +- c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c | 2 +- c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds | 10 +- .../lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c | 8 +- c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S | 16 +- c/src/lib/libbsp/powerpc/mbx8xx/vectors/.cvsignore | 2 + .../lib/libbsp/powerpc/mbx8xx/vectors/Makefile.am | 40 ++ c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.S | 143 ++++++ c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.h | 144 ++++++ .../libbsp/powerpc/mbx8xx/vectors/vectors_init.c | 134 ++++++ c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am | 4 +- 30 files changed, 3165 insertions(+), 63 deletions(-) create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/clock/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/clock/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/clock/p_clock.c create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/include/8xx_immap.h create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/include/commproc.h create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/include/mbx.h create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/vectors/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/vectors/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.S create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.h create mode 100644 c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors_init.c (limited to 'c') diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/ChangeLog b/c/src/lib/libbsp/powerpc/mbx8xx/ChangeLog index abc5f4b5ec..90970de721 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/ChangeLog +++ b/c/src/lib/libbsp/powerpc/mbx8xx/ChangeLog @@ -1,3 +1,18 @@ +2001-03-30 Eric Valette + + * clock/.cvsignore, clock/Makefile.am, clock/p_clock.c, + include/8xx_immap.h, include/commproc.h, include/mbx.h, + irq/.cvsignore, irq/Makefile.am, irq/irq.c, irq/irq.h, + irq/irq_asm.S, irq/irq_init.c, vectors/.cvsignore, + vectors/Makefile.am, vectors/vectors.S, vectors/vectors.h, + vectors/vectors_init.c: New files. + * Makefile.am, configure.in, console/console.c, + include/Makefile.am, network/network.c, startup/Makefile.am, + startup/bspstart.c, startup/imbx8xx.c, startup/linkcmds, + startup/mmutlbtab.c, startup/start.S, wrapup/Makefile.am: + The modifications to this BSP reflect the conversion of the + mpc8xx CPU to the "new exception processing model." + 2000-11-09 Ralf Corsepius * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am index 6e3e8af82d..c9765b8063 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mbx8xx/Makefile.am @@ -7,7 +7,7 @@ ACLOCAL_AMFLAGS = -I ../../../../../../aclocal # wrapup is the one that actually builds and installs the library # from the individual .rel files built in other directories -SUBDIRS = console include network startup wrapup +SUBDIRS = clock console include irq network startup vectors wrapup include $(top_srcdir)/../../bsp.am diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/clock/.cvsignore b/c/src/lib/libbsp/powerpc/mbx8xx/clock/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/clock/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/clock/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/clock/Makefile.am new file mode 100644 index 0000000000..c41be0decc --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/clock/Makefile.am @@ -0,0 +1,26 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +VPATH = @srcdir@:@srcdir@/../../shared/clock + +C_FILES = p_clock.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: $(ARCH) $(OBJS) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/clock/p_clock.c b/c/src/lib/libbsp/powerpc/mbx8xx/clock/p_clock.c new file mode 100644 index 0000000000..327919f7f9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/clock/p_clock.c @@ -0,0 +1,70 @@ +/* + * Clock Tick interrupt conexion code. + * + * COPYRIGHT (c) 1989-1997. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * The license and distribution terms for this file may in + * the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Modified to support the MPC750. + * Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr + * + * $Id$ + */ + +#include +#include + +extern void clockOn(void*); +extern void clockOff (void*); +extern int clockIsOn(void*); +extern void Clock_isr(); + +static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER, + (rtems_irq_hdl)Clock_isr, + (rtems_irq_enable)clockOn, + (rtems_irq_disable)clockOff, + (rtems_irq_is_enabled)clockIsOn}; + +int BSP_get_clock_irq_level() +{ + /* + * Caution : if you change this, you must change the + * definition of BSP_PERIODIC_TIMER accordingly + */ + return 6; +} + +int BSP_disconnect_clock_handler (void) +{ + if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) { + printk("Unable to stop system clock\n"); + rtems_fatal_error_occurred(1); + } + return BSP_remove_rtems_irq_handler (&clockIrqData); +} + +int BSP_connect_clock_handler (rtems_irq_hdl hdl) +{ + if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) { + printk("Unable to get system clock handler\n"); + rtems_fatal_error_occurred(1); + } + if (!BSP_remove_rtems_irq_handler (&clockIrqData)) { + printk("Unable to remove current system clock handler\n"); + rtems_fatal_error_occurred(1); + } + /* + * Reinit structure + */ + clockIrqData.name = BSP_PERIODIC_TIMER; + clockIrqData.hdl = (rtems_irq_hdl) hdl; + clockIrqData.on = (rtems_irq_enable)clockOn; + clockIrqData.off = (rtems_irq_enable)clockOff; + clockIrqData.isOn = (rtems_irq_is_enabled)clockIsOn; + + return BSP_install_rtems_irq_handler (&clockIrqData); +} diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/configure.in b/c/src/lib/libbsp/powerpc/mbx8xx/configure.in index 6e04fb895f..3081f5e6c6 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/configure.in +++ b/c/src/lib/libbsp/powerpc/mbx8xx/configure.in @@ -28,8 +28,11 @@ AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") # Explicitly list a Makefile here AC_OUTPUT( Makefile +clock/Makefile console/Makefile include/Makefile +irq/Makefile network/Makefile startup/Makefile +vectors/Makefile wrapup/Makefile) diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c b/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c index a601572703..2a10d3c652 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c +++ b/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c @@ -80,6 +80,7 @@ #include #include #include +#include static int _EPPCBug_pollRead( int minor ); static int _EPPCBug_pollWrite( int minor, const char *buf, int len ); @@ -87,8 +88,9 @@ static void _BSP_output_char( char c ); static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg); +static void _BSP_null_char( char c ) {return;} -BSP_output_char_function_type BSP_output_char = _BSP_output_char; +BSP_output_char_function_type BSP_output_char = _BSP_null_char; /* @@ -502,6 +504,20 @@ static void _BSP_output_char( char c ) #endif } +bd_t *eppcbugInfo= (bd_t *)0xdeadbeef; +bd_t fakeEppcBugInfo = { + 0x42444944, /* Should be 0x42444944 "BDID" */ + sizeof(bd_t), /* Size of this structure */ + 0, /* revision of this structure */ + 0, /* EPPCbug date, i.e. 0x11061997 */ + 0, /* Memory start address */ + 0x1000000, /* Memory (end) size in bytes */ + 0x28, /* Internal Freq, in Hz */ + 0, /* Bus Freq, in Hz */ + 0, /* Boot device controller */ + 0 /* Boot device logical dev */ +}; + /* *************** @@ -566,7 +582,7 @@ rtems_device_driver console_initialize( m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4 */ #endif /* mpc860 */ - + BSP_output_char = _BSP_output_char; #else /* NVRAM_CONFIGURE != 1 */ console_minor = CONSOLE_MINOR; @@ -609,13 +625,10 @@ rtems_device_driver console_initialize( #endif /* mpc860 */ -#endif /* NVRAM_CONFIGURE != 1 */ + BSP_output_char = _BSP_output_char; +#endif /* NVRAM_CONFIGURE != 1 */ - /* - * Set up interrupts - */ - m8xx_uart_interrupts_initialize(); status = rtems_io_register_name ("/dev/tty0", major, SMC1_MINOR); if (status != RTEMS_SUCCESSFUL) diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/8xx_immap.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/8xx_immap.h new file mode 100644 index 0000000000..3e9f981b31 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/8xx_immap.h @@ -0,0 +1,455 @@ + +/* + * MPC8xx Internal Memory Map + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * The I/O on the MPC860 is comprised of blocks of special registers + * and the dual port ram for the Communication Processor Module. + * Within this space are functional units such as the SIU, memory + * controller, system timers, and other control functions. It is + * a combination that I found difficult to separate into logical + * functional files.....but anyone else is welcome to try. -- Dan + */ +#ifndef __IMMAP_8XX__ +#define __IMMAP_8XX__ + +/* System configuration registers. +*/ +typedef struct sys_conf { + unsigned int sc_siumcr; + unsigned int sc_sypcr; + unsigned int sc_swt; + char res1[2]; + unsigned short sc_swsr; + unsigned int sc_sipend; + unsigned int sc_simask; + unsigned int sc_siel; + unsigned int sc_sivec; + unsigned int sc_tesr; + char res2[0xc]; + unsigned int sc_sdcr; + char res3[0x4c]; +} sysconf8xx_t; + +/* PCMCIA configuration registers. +*/ +typedef struct pcmcia_conf { + unsigned int pcmc_pbr0; + unsigned int pcmc_por0; + unsigned int pcmc_pbr1; + unsigned int pcmc_por1; + unsigned int pcmc_pbr2; + unsigned int pcmc_por2; + unsigned int pcmc_pbr3; + unsigned int pcmc_por3; + unsigned int pcmc_pbr4; + unsigned int pcmc_por4; + unsigned int pcmc_pbr5; + unsigned int pcmc_por5; + unsigned int pcmc_pbr6; + unsigned int pcmc_por6; + unsigned int pcmc_pbr7; + unsigned int pcmc_por7; + char res1[0x20]; + unsigned int pcmc_pgcra; + unsigned int pcmc_pgcrb; + unsigned int pcmc_pscr; + char res2[4]; + unsigned int pcmc_pipr; + char res3[4]; + unsigned int pcmc_per; + char res4[4]; +} pcmconf8xx_t; + +/* Memory controller registers. +*/ +typedef struct mem_ctlr { + unsigned int memc_br0; + unsigned int memc_or0; + unsigned int memc_br1; + unsigned int memc_or1; + unsigned int memc_br2; + unsigned int memc_or2; + unsigned int memc_br3; + unsigned int memc_or3; + unsigned int memc_br4; + unsigned int memc_or4; + unsigned int memc_br5; + unsigned int memc_or5; + unsigned int memc_br6; + unsigned int memc_or6; + unsigned int memc_br7; + unsigned int memc_or7; + char res1[0x24]; + unsigned int memc_mar; + unsigned int memc_mcr; + char res2[4]; + unsigned int memc_mamr; + unsigned int memc_mbmr; + unsigned short memc_mstat; + unsigned short memc_mptpr; + unsigned int memc_mdr; + char res3[0x80]; +} memctl8xx_t; + +/* System Integration Timers. +*/ +typedef struct sys_int_timers { + unsigned short sit_tbscr; + unsigned int sit_tbreff0; + unsigned int sit_tbreff1; + char res1[0x14]; + unsigned short sit_rtcsc; + unsigned int sit_rtc; + unsigned int sit_rtsec; + unsigned int sit_rtcal; + char res2[0x10]; + unsigned short sit_piscr; + char res3[2]; + unsigned int sit_pitc; + unsigned int sit_pitr; + char res4[0x34]; +} sit8xx_t; + +#define TBSCR_TBIRQ_MASK ((unsigned short)0xff00) +#define TBSCR_REFA ((unsigned short)0x0080) +#define TBSCR_REFB ((unsigned short)0x0040) +#define TBSCR_REFAE ((unsigned short)0x0008) +#define TBSCR_REFBE ((unsigned short)0x0004) +#define TBSCR_TBF ((unsigned short)0x0002) +#define TBSCR_TBE ((unsigned short)0x0001) + +#define RTCSC_RTCIRQ_MASK ((unsigned short)0xff00) +#define RTCSC_SEC ((unsigned short)0x0080) +#define RTCSC_ALR ((unsigned short)0x0040) +#define RTCSC_38K ((unsigned short)0x0010) +#define RTCSC_SIE ((unsigned short)0x0008) +#define RTCSC_ALE ((unsigned short)0x0004) +#define RTCSC_RTF ((unsigned short)0x0002) +#define RTCSC_RTE ((unsigned short)0x0001) + +#define PISCR_PIRQ_MASK ((unsigned short)0xff00) +#define PISCR_PS ((unsigned short)0x0080) +#define PISCR_PIE ((unsigned short)0x0004) +#define PISCR_PTF ((unsigned short)0x0002) +#define PISCR_PTE ((unsigned short)0x0001) + +/* Clocks and Reset. +*/ +typedef struct clk_and_reset { + unsigned int car_sccr; + unsigned int car_plprcr; + unsigned int car_rsr; + char res[0x74]; /* Reserved area */ +} car8xx_t; + +/* System Integration Timers keys. +*/ +typedef struct sitk { + unsigned int sitk_tbscrk; + unsigned int sitk_tbreff0k; + unsigned int sitk_tbreff1k; + unsigned int sitk_tbk; + char res1[0x10]; + unsigned int sitk_rtcsck; + unsigned int sitk_rtck; + unsigned int sitk_rtseck; + unsigned int sitk_rtcalk; + char res2[0x10]; + unsigned int sitk_piscrk; + unsigned int sitk_pitck; + char res3[0x38]; +} sitk8xx_t; + +/* Clocks and reset keys. +*/ +typedef struct cark { + unsigned int cark_sccrk; + unsigned int cark_plprcrk; + unsigned int cark_rsrk; + char res[0x474]; +} cark8xx_t; + +/* The key to unlock registers maintained by keep-alive power. +*/ +#define KAPWR_KEY ((unsigned int)0x55ccaa33) + +/* LCD interface. MPC821 Only. +*/ +typedef struct lcd { + unsigned short lcd_lcolr[16]; + char res[0x20]; + unsigned int lcd_lccr; + unsigned int lcd_lchcr; + unsigned int lcd_lcvcr; + char res2[4]; + unsigned int lcd_lcfaa; + unsigned int lcd_lcfba; + char lcd_lcsr; + char res3[0x7]; +} lcd8xx_t; + +/* I2C +*/ +typedef struct i2c { + unsigned char i2c_i2mod; + char res1[3]; + unsigned char i2c_i2add; + char res2[3]; + unsigned char i2c_i2brg; + char res3[3]; + unsigned char i2c_i2com; + char res4[3]; + unsigned char i2c_i2cer; + char res5[3]; + unsigned char i2c_i2cmr; + char res6[0x8b]; +} i2c8xx_t; + +/* DMA control/status registers. +*/ +typedef struct sdma_csr { + char res1[4]; + unsigned int sdma_sdar; + unsigned char sdma_sdsr; + char res3[3]; + unsigned char sdma_sdmr; + char res4[3]; + unsigned char sdma_idsr1; + char res5[3]; + unsigned char sdma_idmr1; + char res6[3]; + unsigned char sdma_idsr2; + char res7[3]; + unsigned char sdma_idmr2; + char res8[0x13]; +} sdma8xx_t; + +/* Communication Processor Module Interrupt Controller. +*/ +typedef struct cpm_ic { + unsigned short cpic_civr; + char res[0xe]; + unsigned int cpic_cicr; + unsigned int cpic_cipr; + unsigned int cpic_cimr; + unsigned int cpic_cisr; +} cpic8xx_t; + +/* Input/Output Port control/status registers. +*/ +typedef struct io_port { + unsigned short iop_padir; + unsigned short iop_papar; + unsigned short iop_paodr; + unsigned short iop_padat; + char res1[8]; + unsigned short iop_pcdir; + unsigned short iop_pcpar; + unsigned short iop_pcso; + unsigned short iop_pcdat; + unsigned short iop_pcint; + char res2[6]; + unsigned short iop_pddir; + unsigned short iop_pdpar; + char res3[2]; + unsigned short iop_pddat; + char res4[8]; +} iop8xx_t; + +/* Communication Processor Module Timers +*/ +typedef struct cpm_timers { + unsigned short cpmt_tgcr; + char res1[0xe]; + unsigned short cpmt_tmr1; + unsigned short cpmt_tmr2; + unsigned short cpmt_trr1; + unsigned short cpmt_trr2; + unsigned short cpmt_tcr1; + unsigned short cpmt_tcr2; + unsigned short cpmt_tcn1; + unsigned short cpmt_tcn2; + unsigned short cpmt_tmr3; + unsigned short cpmt_tmr4; + unsigned short cpmt_trr3; + unsigned short cpmt_trr4; + unsigned short cpmt_tcr3; + unsigned short cpmt_tcr4; + unsigned short cpmt_tcn3; + unsigned short cpmt_tcn4; + unsigned short cpmt_ter1; + unsigned short cpmt_ter2; + unsigned short cpmt_ter3; + unsigned short cpmt_ter4; + char res2[8]; +} cpmtimer8xx_t; + +/* Finally, the Communication Processor stuff..... +*/ +typedef struct scc { /* Serial communication channels */ + unsigned int scc_gsmrl; + unsigned int scc_gsmrh; + unsigned short scc_pmsr; + char res1[2]; + unsigned short scc_todr; + unsigned short scc_dsr; + unsigned short scc_scce; + char res2[2]; + unsigned short scc_sccm; + char res3; + unsigned char scc_sccs; + char res4[8]; +} scc_t; + +typedef struct smc { /* Serial management channels */ + char res1[2]; + unsigned short smc_smcmr; + char res2[2]; + unsigned char smc_smce; + char res3[3]; + unsigned char smc_smcm; + char res4[5]; +} smc_t; + +/* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but + * it fits within the address space. + */ +typedef struct fec { + unsigned int fec_addr_low; /* LS 32 bits of station address */ + unsigned short fec_addr_high; /* MS 16 bits of address */ + unsigned short res1; + unsigned int fec_hash_table_high; + unsigned int fec_hash_table_low; + unsigned int fec_r_des_start; + unsigned int fec_x_des_start; + unsigned int fec_r_buff_size; + unsigned int res2[9]; + unsigned int fec_ecntrl; + unsigned int fec_ievent; + unsigned int fec_imask; + unsigned int fec_ivec; + unsigned int fec_r_des_active; + unsigned int fec_x_des_active; + unsigned int res3[10]; + unsigned int fec_mii_data; + unsigned int fec_mii_speed; + unsigned int res4[17]; + unsigned int fec_r_bound; + unsigned int fec_r_fstart; + unsigned int res5[6]; + unsigned int fec_x_fstart; + unsigned int res6[17]; + unsigned int fec_fun_code; + unsigned int res7[3]; + unsigned int fec_r_cntrl; + unsigned int fec_r_hash; + unsigned int res8[14]; + unsigned int fec_x_cntrl; + unsigned int res9[0x1e]; +} fec_t; + +typedef struct comm_proc { + /* General control and status registers. + */ + unsigned short cp_cpcr; + char res1[2]; + unsigned short cp_rccr; + char res2[6]; + unsigned short cp_cpmcr1; + unsigned short cp_cpmcr2; + unsigned short cp_cpmcr3; + unsigned short cp_cpmcr4; + char res3[2]; + unsigned short cp_rter; + char res4[2]; + unsigned short cp_rtmr; + char res5[0x14]; + + /* Baud rate generators. + */ + unsigned int cp_brgc1; + unsigned int cp_brgc2; + unsigned int cp_brgc3; + unsigned int cp_brgc4; + + /* Serial Communication Channels. + */ + scc_t cp_scc[4]; + + /* Serial Management Channels. + */ + smc_t cp_smc[2]; + + /* Serial Peripheral Interface. + */ + unsigned short cp_spmode; + char res6[4]; + unsigned char cp_spie; + char res7[3]; + unsigned char cp_spim; + char res8[2]; + unsigned char cp_spcom; + char res9[2]; + + /* Parallel Interface Port. + */ + char res10[2]; + unsigned short cp_pipc; + char res11[2]; + unsigned short cp_ptpr; + unsigned int cp_pbdir; + unsigned int cp_pbpar; + char res12[2]; + unsigned short cp_pbodr; + unsigned int cp_pbdat; + char res13[0x18]; + + /* Serial Interface and Time Slot Assignment. + */ + unsigned int cp_simode; + unsigned char cp_sigmr; + char res14; + unsigned char cp_sistr; + unsigned char cp_sicmr; + char res15[4]; + unsigned int cp_sicr; + unsigned int cp_sirp; + char res16[0x10c]; + unsigned char cp_siram[0x200]; + + /* The fast ethernet controller is not really part of the CPM, + * but it resides in the address space. + */ + fec_t cp_fec; + char res18[0x1000]; + + /* Dual Ported RAM follows. + * There are many different formats for this memory area + * depending upon the devices used and options chosen. + */ + unsigned char cp_dpmem[0x1000]; /* BD / Data / ucode */ + unsigned char res19[0xc00]; + unsigned char cp_dparam[0x400]; /* Parameter RAM */ +} cpm8xx_t; + +/* Internal memory map. +*/ +typedef struct immap { + sysconf8xx_t im_siu_conf; /* SIU Configuration */ + pcmconf8xx_t im_pcmcia; /* PCMCIA Configuration */ + memctl8xx_t im_memctl; /* Memory Controller */ + sit8xx_t im_sit; /* System integration timers */ + car8xx_t im_clkrst; /* Clocks and reset */ + sitk8xx_t im_sitk; /* Sys int timer keys */ + cark8xx_t im_clkrstk; /* Clocks and reset keys */ + lcd8xx_t im_lcd; /* LCD (821 only) */ + i2c8xx_t im_i2c; /* I2C control/status */ + sdma8xx_t im_sdma; /* SDMA control/status */ + cpic8xx_t im_cpic; /* CPM Interrupt Controller */ + iop8xx_t im_ioport; /* IO Port control/status */ + cpmtimer8xx_t im_cpmtimer; /* CPM timers */ + cpm8xx_t im_cpm; /* Communication processor */ +} immap_t; + +#endif /* __IMMAP_8XX__ */ diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am index 6c4e41dd5d..6728c6032c 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/Makefile.am @@ -6,17 +6,33 @@ AUTOMAKE_OPTIONS = foreign 1.4 H_FILES = bsp.h coverhd.h +BSP_H_FILES = mbx.h commproc.h 8xx_immap.h + $(PROJECT_INCLUDE): $(mkinstalldirs) $@ +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + $(PROJECT_INCLUDE)/bsp.h: bsp.h $(INSTALL_DATA) $< $@ $(PROJECT_INCLUDE)/coverhd.h: coverhd.h $(INSTALL_DATA) $< $@ -PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/bsp.h \ - $(PROJECT_INCLUDE)/coverhd.h +$(PROJECT_INCLUDE)/bsp/mbx.h : mbx.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/bsp/commproc.h : commproc.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/bsp/8xx_immap.h : 8xx_immap.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/bsp \ + $(PROJECT_INCLUDE)/bsp.h \ + $(PROJECT_INCLUDE)/coverhd.h $(PROJECT_INCLUDE)/bsp/mbx.h \ + $(PROJECT_INCLUDE)/bsp/commproc.h $(PROJECT_INCLUDE)/bsp/8xx_immap.h all-local: $(PREINSTALL_FILES) diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/commproc.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/commproc.h new file mode 100644 index 0000000000..e157203467 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/commproc.h @@ -0,0 +1,529 @@ + +/* + * MPC8xx Communication Processor Module. + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + * + * This file contains structures and information for the communication + * processor channels. Some CPM control and status is available + * throught the MPC8xx internal memory map. See immap.h for details. + * This file only contains what I need for the moment, not the total + * CPM capabilities. I (or someone else) will add definitions as they + * are needed. -- Dan + * + * On the MBX board, EPPC-Bug loads CPM microcode into the first 512 + * bytes of the DP RAM and relocates the I2C parameter area to the + * IDMA1 space. The remaining DP RAM is available for buffer descriptors + * or other use. + */ +#ifndef __CPM_8XX__ +#define __CPM_8XX__ + +#include + +/* CPM Command register. +*/ +#define CPM_CR_RST ((ushort)0x8000) +#define CPM_CR_OPCODE ((ushort)0x0f00) +#define CPM_CR_CHAN ((ushort)0x00f0) +#define CPM_CR_FLG ((ushort)0x0001) + +/* Some commands (there are more...later) +*/ +#define CPM_CR_INIT_TRX ((ushort)0x0000) +#define CPM_CR_INIT_RX ((ushort)0x0001) +#define CPM_CR_INIT_TX ((ushort)0x0002) +#define CPM_CR_STOP_TX ((ushort)0x0004) +#define CPM_CR_RESTART_TX ((ushort)0x0006) +#define CPM_CR_SET_GADDR ((ushort)0x0008) + +/* Channel numbers. +*/ +#define CPM_CR_CH_SCC1 ((ushort)0x0000) +#define CPM_CR_CH_I2C ((ushort)0x0001) /* I2C and IDMA1 */ +#define CPM_CR_CH_SCC2 ((ushort)0x0004) +#define CPM_CR_CH_SPI ((ushort)0x0005) /* SPI / IDMA2 / Timers */ +#define CPM_CR_CH_SCC3 ((ushort)0x0008) +#define CPM_CR_CH_SMC1 ((ushort)0x0009) /* SMC1 / DSP1 */ +#define CPM_CR_CH_SCC4 ((ushort)0x000c) +#define CPM_CR_CH_SMC2 ((ushort)0x000d) /* SMC2 / DSP2 */ + +#define mk_cr_cmd(CH, CMD) ((CMD << 8) | (CH << 4)) + +/* The dual ported RAM is multi-functional. Some areas can be (and are + * being) used for microcode. There is an area that can only be used + * as data ram for buffer descriptors, which is all we use right now. + * Currently the first 512 and last 256 bytes are used for microcode. + */ +#define CPM_DATAONLY_BASE ((uint)0x0800) +#define CPM_DATAONLY_SIZE ((uint)0x0700) +#define CPM_DP_NOSPACE ((uint)0x7fffffff) + +/* Export the base address of the communication processor registers + * and dual port ram. + */ +extern cpm8xx_t *cpmp; /* Pointer to comm processor */ +uint m8xx_cpm_dpalloc(uint size); +uint m8xx_cpm_hostalloc(uint size); +void m8xx_cpm_setbrg(uint brg, uint rate); + +/* Buffer descriptors used by many of the CPM protocols. +*/ +typedef struct cpm_buf_desc { + ushort cbd_sc; /* Status and Control */ + ushort cbd_datlen; /* Data length in buffer */ + uint cbd_bufaddr; /* Buffer address in host memory */ +} cbd_t; + +#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */ +#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */ +#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */ +#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */ +#define BD_SC_CM ((ushort)0x0200) /* Continous mode */ +#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */ +#define BD_SC_P ((ushort)0x0100) /* xmt preamble */ +#define BD_SC_BR ((ushort)0x0020) /* Break received */ +#define BD_SC_FR ((ushort)0x0010) /* Framing error */ +#define BD_SC_PR ((ushort)0x0008) /* Parity error */ +#define BD_SC_OV ((ushort)0x0002) /* Overrun */ +#define BD_SC_CD ((ushort)0x0001) /* ?? */ + +/* Parameter RAM offsets. +*/ +#define PROFF_SCC1 ((uint)0x0000) +#define PROFF_SCC2 ((uint)0x0100) +#define PROFF_SCC3 ((uint)0x0200) +#define PROFF_SMC1 ((uint)0x0280) +#define PROFF_SCC4 ((uint)0x0300) +#define PROFF_SMC2 ((uint)0x0380) + +/* Define enough so I can at least use the serial port as a UART. + */ +typedef struct smc_uart { + ushort smc_rbase; /* Rx Buffer descriptor base address */ + ushort smc_tbase; /* Tx Buffer descriptor base address */ + u_char smc_rfcr; /* Rx function code */ + u_char smc_tfcr; /* Tx function code */ + ushort smc_mrblr; /* Max receive buffer length */ + uint smc_rstate; /* Internal */ + uint smc_idp; /* Internal */ + ushort smc_rbptr; /* Internal */ + ushort smc_ibc; /* Internal */ + uint smc_rxtmp; /* Internal */ + uint smc_tstate; /* Internal */ + uint smc_tdp; /* Internal */ + ushort smc_tbptr; /* Internal */ + ushort smc_tbc; /* Internal */ + uint smc_txtmp; /* Internal */ + ushort smc_maxidl; /* Maximum idle characters */ + ushort smc_tmpidl; /* Temporary idle counter */ + ushort smc_brklen; /* Last received break length */ + ushort smc_brkec; /* rcv'd break condition counter */ + ushort smc_brkcr; /* xmt break count register */ + ushort smc_rmask; /* Temporary bit mask */ +} smc_uart_t; + +/* Function code bits. +*/ +#define SMC_EB ((u_char)0x10) /* Set big endian byte order */ + +/* SMC uart mode register. +*/ +#define SMCMR_REN ((ushort)0x0001) +#define SMCMR_TEN ((ushort)0x0002) +#define SMCMR_DM ((ushort)0x000c) +#define SMCMR_SM_GCI ((ushort)0x0000) +#define SMCMR_SM_UART ((ushort)0x0020) +#define SMCMR_SM_TRANS ((ushort)0x0030) +#define SMCMR_SM_MASK ((ushort)0x0030) +#define SMCMR_PM_EVEN ((ushort)0x0100) /* Even parity, else odd */ +#define SMCMR_PEN ((ushort)0x0200) /* Parity enable */ +#define SMCMR_SL ((ushort)0x0400) /* Two stops, else one */ +#define SMCR_CLEN_MASK ((ushort)0x7800) /* Character length */ +#define smcr_mk_clen(C) (((C) << 11) & SMCR_CLEN_MASK) + +/* SMC Event and Mask register. +*/ +#define SMCM_TXE ((unsigned char)0x10) +#define SMCM_BSY ((unsigned char)0x04) +#define SMCM_TX ((unsigned char)0x02) +#define SMCM_RX ((unsigned char)0x01) + +/* Baud rate generators. +*/ +#define CPM_BRG_RST ((uint)0x00020000) +#define CPM_BRG_EN ((uint)0x00010000) +#define CPM_BRG_EXTC_INT ((uint)0x00000000) +#define CPM_BRG_EXTC_CLK2 ((uint)0x00004000) +#define CPM_BRG_EXTC_CLK6 ((uint)0x00008000) +#define CPM_BRG_ATB ((uint)0x00002000) +#define CPM_BRG_CD_MASK ((uint)0x00001ffe) +#define CPM_BRG_DIV16 ((uint)0x00000001) + +/* SCCs. +*/ +#define SCC_GSMRH_IRP ((uint)0x00040000) +#define SCC_GSMRH_GDE ((uint)0x00010000) +#define SCC_GSMRH_TCRC_CCITT ((uint)0x00008000) +#define SCC_GSMRH_TCRC_BISYNC ((uint)0x00004000) +#define SCC_GSMRH_TCRC_HDLC ((uint)0x00000000) +#define SCC_GSMRH_REVD ((uint)0x00002000) +#define SCC_GSMRH_TRX ((uint)0x00001000) +#define SCC_GSMRH_TTX ((uint)0x00000800) +#define SCC_GSMRH_CDP ((uint)0x00000400) +#define SCC_GSMRH_CTSP ((uint)0x00000200) +#define SCC_GSMRH_CDS ((uint)0x00000100) +#define SCC_GSMRH_CTSS ((uint)0x00000080) +#define SCC_GSMRH_TFL ((uint)0x00000040) +#define SCC_GSMRH_RFW ((uint)0x00000020) +#define SCC_GSMRH_TXSY ((uint)0x00000010) +#define SCC_GSMRH_SYNL16 ((uint)0x0000000c) +#define SCC_GSMRH_SYNL8 ((uint)0x00000008) +#define SCC_GSMRH_SYNL4 ((uint)0x00000004) +#define SCC_GSMRH_RTSM ((uint)0x00000002) +#define SCC_GSMRH_RSYN ((uint)0x00000001) + +#define SCC_GSMRL_SIR ((uint)0x80000000) /* SCC2 only */ +#define SCC_GSMRL_EDGE_NONE ((uint)0x60000000) +#define SCC_GSMRL_EDGE_NEG ((uint)0x40000000) +#define SCC_GSMRL_EDGE_POS ((uint)0x20000000) +#define SCC_GSMRL_EDGE_BOTH ((uint)0x00000000) +#define SCC_GSMRL_TCI ((uint)0x10000000) +#define SCC_GSMRL_TSNC_3 ((uint)0x0c000000) +#define SCC_GSMRL_TSNC_4 ((uint)0x08000000) +#define SCC_GSMRL_TSNC_14 ((uint)0x04000000) +#define SCC_GSMRL_TSNC_INF ((uint)0x00000000) +#define SCC_GSMRL_RINV ((uint)0x02000000) +#define SCC_GSMRL_TINV ((uint)0x01000000) +#define SCC_GSMRL_TPL_128 ((uint)0x00c00000) +#define SCC_GSMRL_TPL_64 ((uint)0x00a00000) +#define SCC_GSMRL_TPL_48 ((uint)0x00800000) +#define SCC_GSMRL_TPL_32 ((uint)0x00600000) +#define SCC_GSMRL_TPL_16 ((uint)0x00400000) +#define SCC_GSMRL_TPL_8 ((uint)0x00200000) +#define SCC_GSMRL_TPL_NONE ((uint)0x00000000) +#define SCC_GSMRL_TPP_ALL1 ((uint)0x00180000) +#define SCC_GSMRL_TPP_01 ((uint)0x00100000) +#define SCC_GSMRL_TPP_10 ((uint)0x00080000) +#define SCC_GSMRL_TPP_ZEROS ((uint)0x00000000) +#define SCC_GSMRL_TEND ((uint)0x00040000) +#define SCC_GSMRL_TDCR_32 ((uint)0x00030000) +#define SCC_GSMRL_TDCR_16 ((uint)0x00020000) +#define SCC_GSMRL_TDCR_8 ((uint)0x00010000) +#define SCC_GSMRL_TDCR_1 ((uint)0x00000000) +#define SCC_GSMRL_RDCR_32 ((uint)0x0000c000) +#define SCC_GSMRL_RDCR_16 ((uint)0x00008000) +#define SCC_GSMRL_RDCR_8 ((uint)0x00004000) +#define SCC_GSMRL_RDCR_1 ((uint)0x00000000) +#define SCC_GSMRL_RENC_DFMAN ((uint)0x00003000) +#define SCC_GSMRL_RENC_MANCH ((uint)0x00002000) +#define SCC_GSMRL_RENC_FM0 ((uint)0x00001000) +#define SCC_GSMRL_RENC_NRZI ((uint)0x00000800) +#define SCC_GSMRL_RENC_NRZ ((uint)0x00000000) +#define SCC_GSMRL_TENC_DFMAN ((uint)0x00000600) +#define SCC_GSMRL_TENC_MANCH ((uint)0x00000400) +#define SCC_GSMRL_TENC_FM0 ((uint)0x00000200) +#define SCC_GSMRL_TENC_NRZI ((uint)0x00000100) +#define SCC_GSMRL_TENC_NRZ ((uint)0x00000000) +#define SCC_GSMRL_DIAG_LE ((uint)0x000000c0) /* Loop and echo */ +#define SCC_GSMRL_DIAG_ECHO ((uint)0x00000080) +#define SCC_GSMRL_DIAG_LOOP ((uint)0x00000040) +#define SCC_GSMRL_DIAG_NORM ((uint)0x00000000) +#define SCC_GSMRL_ENR ((uint)0x00000020) +#define SCC_GSMRL_ENT ((uint)0x00000010) +#define SCC_GSMRL_MODE_ENET ((uint)0x0000000c) +#define SCC_GSMRL_MODE_DDCMP ((uint)0x00000009) +#define SCC_GSMRL_MODE_BISYNC ((uint)0x00000008) +#define SCC_GSMRL_MODE_V14 ((uint)0x00000007) +#define SCC_GSMRL_MODE_AHDLC ((uint)0x00000006) +#define SCC_GSMRL_MODE_PROFIBUS ((uint)0x00000005) +#define SCC_GSMRL_MODE_UART ((uint)0x00000004) +#define SCC_GSMRL_MODE_SS7 ((uint)0x00000003) +#define SCC_GSMRL_MODE_ATALK ((uint)0x00000002) +#define SCC_GSMRL_MODE_HDLC ((uint)0x00000000) + +#define SCC_TODR_TOD ((ushort)0x8000) + +/* SCC Event and Mask register. +*/ +#define SCCM_TXE ((unsigned char)0x10) +#define SCCM_BSY ((unsigned char)0x04) +#define SCCM_TX ((unsigned char)0x02) +#define SCCM_RX ((unsigned char)0x01) + +typedef struct scc_param { + ushort scc_rbase; /* Rx Buffer descriptor base address */ + ushort scc_tbase; /* Tx Buffer descriptor base address */ + u_char scc_rfcr; /* Rx function code */ + u_char scc_tfcr; /* Tx function code */ + ushort scc_mrblr; /* Max receive buffer length */ + uint scc_rstate; /* Internal */ + uint scc_idp; /* Internal */ + ushort scc_rbptr; /* Internal */ + ushort scc_ibc; /* Internal */ + uint scc_rxtmp; /* Internal */ + uint scc_tstate; /* Internal */ + uint scc_tdp; /* Internal */ + ushort scc_tbptr; /* Internal */ + ushort scc_tbc; /* Internal */ + uint scc_txtmp; /* Internal */ + uint scc_rcrc; /* Internal */ + uint scc_tcrc; /* Internal */ +} sccp_t; + +/* Function code bits. +*/ +#define SCC_EB ((u_char)0x10) /* Set big endian byte order */ + +/* CPM Ethernet through SCC1. + */ +typedef struct scc_enet { + sccp_t sen_genscc; + uint sen_cpres; /* Preset CRC */ + uint sen_cmask; /* Constant mask for CRC */ + uint sen_crcec; /* CRC Error counter */ + uint sen_alec; /* alignment error counter */ + uint sen_disfc; /* discard frame counter */ + ushort sen_pads; /* Tx short frame pad character */ + ushort sen_retlim; /* Retry limit threshold */ + ushort sen_retcnt; /* Retry limit counter */ + ushort sen_maxflr; /* maximum frame length register */ + ushort sen_minflr; /* minimum frame length register */ + ushort sen_maxd1; /* maximum DMA1 length */ + ushort sen_maxd2; /* maximum DMA2 length */ + ushort sen_maxd; /* Rx max DMA */ + ushort sen_dmacnt; /* Rx DMA counter */ + ushort sen_maxb; /* Max BD byte count */ + ushort sen_gaddr1; /* Group address filter */ + ushort sen_gaddr2; + ushort sen_gaddr3; + ushort sen_gaddr4; + uint sen_tbuf0data0; /* Save area 0 - current frame */ + uint sen_tbuf0data1; /* Save area 1 - current frame */ + uint sen_tbuf0rba; /* Internal */ + uint sen_tbuf0crc; /* Internal */ + ushort sen_tbuf0bcnt; /* Internal */ + ushort sen_paddrh; /* physical address (MSB) */ + ushort sen_paddrm; + ushort sen_paddrl; /* physical address (LSB) */ + ushort sen_pper; /* persistence */ + ushort sen_rfbdptr; /* Rx first BD pointer */ + ushort sen_tfbdptr; /* Tx first BD pointer */ + ushort sen_tlbdptr; /* Tx last BD pointer */ + uint sen_tbuf1data0; /* Save area 0 - current frame */ + uint sen_tbuf1data1; /* Save area 1 - current frame */ + uint sen_tbuf1rba; /* Internal */ + uint sen_tbuf1crc; /* Internal */ + ushort sen_tbuf1bcnt; /* Internal */ + ushort sen_txlen; /* Tx Frame length counter */ + ushort sen_iaddr1; /* Individual address filter */ + ushort sen_iaddr2; + ushort sen_iaddr3; + ushort sen_iaddr4; + ushort sen_boffcnt; /* Backoff counter */ + + /* NOTE: Some versions of the manual have the following items + * incorrectly documented. Below is the proper order. + */ + ushort sen_taddrh; /* temp address (MSB) */ + ushort sen_taddrm; + ushort sen_taddrl; /* temp address (LSB) */ +} scc_enet_t; + +/* Bits in parallel I/O port registers that have to be set/cleared + * to configure the pins for SCC1 use. The TCLK and RCLK seem unique + * to the MBX860 board. Any two of the four available clocks could be + * used, and the MPC860 cookbook manual has an example using different + * clock pins. + */ +#define PA_ENET_RXD ((ushort)0x0001) +#define PA_ENET_TXD ((ushort)0x0002) +#define PA_ENET_TCLK ((ushort)0x0200) +#define PA_ENET_RCLK ((ushort)0x0800) +#define PC_ENET_TENA ((ushort)0x0001) +#define PC_ENET_CLSN ((ushort)0x0010) +#define PC_ENET_RENA ((ushort)0x0020) + +/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to + * SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero. + */ +#define SICR_ENET_MASK ((uint)0x000000ff) +#define SICR_ENET_CLKRT ((uint)0x0000003d) + +/* SCC Event register as used by Ethernet. +*/ +#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */ +#define SCCE_ENET_TXE ((ushort)0x0010) /* Transmit Error */ +#define SCCE_ENET_RXF ((ushort)0x0008) /* Full frame received */ +#define SCCE_ENET_BSY ((ushort)0x0004) /* All incoming buffers full */ +#define SCCE_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */ +#define SCCE_ENET_RXB ((ushort)0x0001) /* A buffer was received */ + +/* SCC Mode Register (PMSR) as used by Ethernet. +*/ +#define SCC_PMSR_HBC ((ushort)0x8000) /* Enable heartbeat */ +#define SCC_PMSR_FC ((ushort)0x4000) /* Force collision */ +#define SCC_PMSR_RSH ((ushort)0x2000) /* Receive short frames */ +#define SCC_PMSR_IAM ((ushort)0x1000) /* Check individual hash */ +#define SCC_PMSR_ENCRC ((ushort)0x0800) /* Ethernet CRC mode */ +#define SCC_PMSR_PRO ((ushort)0x0200) /* Promiscuous mode */ +#define SCC_PMSR_BRO ((ushort)0x0100) /* Catch broadcast pkts */ +#define SCC_PMSR_SBT ((ushort)0x0080) /* Special backoff timer */ +#define SCC_PMSR_LPB ((ushort)0x0040) /* Set Loopback mode */ +#define SCC_PMSR_SIP ((ushort)0x0020) /* Sample Input Pins */ +#define SCC_PMSR_LCW ((ushort)0x0010) /* Late collision window */ +#define SCC_PMSR_NIB22 ((ushort)0x000a) /* Start frame search */ +#define SCC_PMSR_FDE ((ushort)0x0001) /* Full duplex enable */ + +/* Buffer descriptor control/status used by Ethernet receive. +*/ +#define BD_ENET_RX_EMPTY ((ushort)0x8000) +#define BD_ENET_RX_WRAP ((ushort)0x2000) +#define BD_ENET_RX_INTR ((ushort)0x1000) +#define BD_ENET_RX_LAST ((ushort)0x0800) +#define BD_ENET_RX_FIRST ((ushort)0x0400) +#define BD_ENET_RX_MISS ((ushort)0x0100) +#define BD_ENET_RX_LG ((ushort)0x0020) +#define BD_ENET_RX_NO ((ushort)0x0010) +#define BD_ENET_RX_SH ((ushort)0x0008) +#define BD_ENET_RX_CR ((ushort)0x0004) +#define BD_ENET_RX_OV ((ushort)0x0002) +#define BD_ENET_RX_CL ((ushort)0x0001) +#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */ + +/* Buffer descriptor control/status used by Ethernet transmit. +*/ +#define BD_ENET_TX_READY ((ushort)0x8000) +#define BD_ENET_TX_PAD ((ushort)0x4000) +#define BD_ENET_TX_WRAP ((ushort)0x2000) +#define BD_ENET_TX_INTR ((ushort)0x1000) +#define BD_ENET_TX_LAST ((ushort)0x0800) +#define BD_ENET_TX_TC ((ushort)0x0400) +#define BD_ENET_TX_DEF ((ushort)0x0200) +#define BD_ENET_TX_HB ((ushort)0x0100) +#define BD_ENET_TX_LC ((ushort)0x0080) +#define BD_ENET_TX_RL ((ushort)0x0040) +#define BD_ENET_TX_RCMASK ((ushort)0x003c) +#define BD_ENET_TX_UN ((ushort)0x0002) +#define BD_ENET_TX_CSL ((ushort)0x0001) +#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */ + +/* SCC as UART +*/ +typedef struct scc_uart { + sccp_t scc_genscc; + uint scc_res1; /* Reserved */ + uint scc_res2; /* Reserved */ + ushort scc_maxidl; /* Maximum idle chars */ + ushort scc_idlc; /* temp idle counter */ + ushort scc_brkcr; /* Break count register */ + ushort scc_parec; /* receive parity error counter */ + ushort scc_frmec; /* receive framing error counter */ + ushort scc_nosec; /* receive noise counter */ + ushort scc_brkec; /* receive break condition counter */ + ushort scc_brkln; /* last received break length */ + ushort scc_uaddr1; /* UART address character 1 */ + ushort scc_uaddr2; /* UART address character 2 */ + ushort scc_rtemp; /* Temp storage */ + ushort scc_toseq; /* Transmit out of sequence char */ + ushort scc_char1; /* control character 1 */ + ushort scc_char2; /* control character 2 */ + ushort scc_char3; /* control character 3 */ + ushort scc_char4; /* control character 4 */ + ushort scc_char5; /* control character 5 */ + ushort scc_char6; /* control character 6 */ + ushort scc_char7; /* control character 7 */ + ushort scc_char8; /* control character 8 */ + ushort scc_rccm; /* receive control character mask */ + ushort scc_rccr; /* receive control character register */ + ushort scc_rlbc; /* receive last break character */ +} scc_uart_t; + +/* SCC Event and Mask registers when it is used as a UART. +*/ +#define UART_SCCM_GLR ((ushort)0x1000) +#define UART_SCCM_GLT ((ushort)0x0800) +#define UART_SCCM_AB ((ushort)0x0200) +#define UART_SCCM_IDL ((ushort)0x0100) +#define UART_SCCM_GRA ((ushort)0x0080) +#define UART_SCCM_BRKE ((ushort)0x0040) +#define UART_SCCM_BRKS ((ushort)0x0020) +#define UART_SCCM_CCR ((ushort)0x0008) +#define UART_SCCM_BSY ((ushort)0x0004) +#define UART_SCCM_TX ((ushort)0x0002) +#define UART_SCCM_RX ((ushort)0x0001) + +/* The SCC PMSR when used as a UART. +*/ +#define SCU_PMSR_FLC ((ushort)0x8000) +#define SCU_PMSR_SL ((ushort)0x4000) +#define SCU_PMSR_CL ((ushort)0x3000) +#define SCU_PMSR_UM ((ushort)0x0c00) +#define SCU_PMSR_FRZ ((ushort)0x0200) +#define SCU_PMSR_RZS ((ushort)0x0100) +#define SCU_PMSR_SYN ((ushort)0x0080) +#define SCU_PMSR_DRT ((ushort)0x0040) +#define SCU_PMSR_PEN ((ushort)0x0010) +#define SCU_PMSR_RPM ((ushort)0x000c) +#define SCU_PMSR_REVP ((ushort)0x0008) +#define SCU_PMSR_TPM ((ushort)0x0003) +#define SCU_PMSR_TEVP ((ushort)0x0003) + +/* CPM Transparent mode SCC. + */ +typedef struct scc_trans { + sccp_t st_genscc; + uint st_cpres; /* Preset CRC */ + uint st_cmask; /* Constant mask for CRC */ +} scc_trans_t; + +/* CPM interrupts. There are nearly 32 interrupts generated by CPM + * channels or devices. All of these are presented to the PPC core + * as a single interrupt. The CPM interrupt handler dispatches its + * own handlers, in a similar fashion to the PPC core handler. We + * use the table as defined in the manuals (i.e. no special high + * priority and SCC1 == SCCa, etc...). + */ +#define CPMVEC_NR 32 +#define CPMVEC_PIO_PC15 ((ushort)0x1f) +#define CPMVEC_SCC1 ((ushort)0x1e) +#define CPMVEC_SCC2 ((ushort)0x1d) +#define CPMVEC_SCC3 ((ushort)0x1c) +#define CPMVEC_SCC4 ((ushort)0x1b) +#define CPMVEC_PIO_PC14 ((ushort)0x1a) +#define CPMVEC_TIMER1 ((ushort)0x19) +#define CPMVEC_PIO_PC13 ((ushort)0x18) +#define CPMVEC_PIO_PC12 ((ushort)0x17) +#define CPMVEC_SDMA_CB_ERR ((ushort)0x16) +#define CPMVEC_IDMA1 ((ushort)0x15) +#define CPMVEC_IDMA2 ((ushort)0x14) +#define CPMVEC_TIMER2 ((ushort)0x12) +#define CPMVEC_RISCTIMER ((ushort)0x11) +#define CPMVEC_I2C ((ushort)0x10) +#define CPMVEC_PIO_PC11 ((ushort)0x0f) +#define CPMVEC_PIO_PC10 ((ushort)0x0e) +#define CPMVEC_TIMER3 ((ushort)0x0c) +#define CPMVEC_PIO_PC9 ((ushort)0x0b) +#define CPMVEC_PIO_PC8 ((ushort)0x0a) +#define CPMVEC_PIO_PC7 ((ushort)0x09) +#define CPMVEC_TIMER4 ((ushort)0x07) +#define CPMVEC_PIO_PC6 ((ushort)0x06) +#define CPMVEC_SPI ((ushort)0x05) +#define CPMVEC_SMC1 ((ushort)0x04) +#define CPMVEC_SMC2 ((ushort)0x03) +#define CPMVEC_PIO_PC5 ((ushort)0x02) +#define CPMVEC_PIO_PC4 ((ushort)0x01) +#define CPMVEC_ERROR ((ushort)0x00) + +extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id); + +/* CPM interrupt configuration vector. +*/ +#define CICR_SCD_SCC4 ((uint)0x00c00000) /* SCC4 @ SCCd */ +#define CICR_SCC_SCC3 ((uint)0x00200000) /* SCC3 @ SCCc */ +#define CICR_SCB_SCC2 ((uint)0x00040000) /* SCC2 @ SCCb */ +#define CICR_SCA_SCC1 ((uint)0x00000000) /* SCC1 @ SCCa */ +#define CICR_IRL_MASK ((uint)0x0000e000) /* Core interrrupt */ +#define CICR_HP_MASK ((uint)0x00001f00) /* Hi-pri int. */ +#define CICR_IEN ((uint)0x00000080) /* Int. enable */ +#define CICR_SPS ((uint)0x00000001) /* SCC Spread */ +#endif /* __CPM_8XX__ */ diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/include/mbx.h b/c/src/lib/libbsp/powerpc/mbx8xx/include/mbx.h new file mode 100644 index 0000000000..0c72b4a9a9 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/include/mbx.h @@ -0,0 +1,62 @@ + +/* + * A collection of structures, addresses, and values associated with + * the Motorola MBX boards. This was originally created for the + * MBX860, and probably needs revisions for other boards (like the 821). + * When this file gets out of control, we can split it up into more + * meaningful pieces. + * + * Copyright (c) 1997 Dan Malek (dmalek@jlc.net) + */ +#ifndef __MACH_MBX_DEFS +#define __MACH_MBX_DEFS + +/* A Board Information structure that is given to a program when + * EPPC-Bug starts it up. + */ +typedef struct bd_info { + unsigned int bi_tag; /* Should be 0x42444944 "BDID" */ + unsigned int bi_size; /* Size of this structure */ + unsigned int bi_revision; /* revision of this structure */ + unsigned int bi_bdate; /* EPPCbug date, i.e. 0x11061997 */ + unsigned int bi_memstart; /* Memory start address */ + unsigned int bi_memsize; /* Memory (end) size in bytes */ + unsigned int bi_intfreq; /* Internal Freq, in Hz */ + unsigned int bi_busfreq; /* Bus Freq, in Hz */ + unsigned int bi_clun; /* Boot device controller */ + unsigned int bi_dlun; /* Boot device logical dev */ +} bd_t; + +/* Memory map for the MBX as configured by EPPC-Bug. We could reprogram + * The SIU and PCI bridge, and try to use larger MMU pages, but the + * performance gain is not measureable and it certainly complicates the + * generic MMU model. + * + * In a effort to minimize memory usage for embedded applications, any + * PCI driver or ISA driver must request or map the region required by + * the device. For convenience (and since we can map up to 4 Mbytes with + * a single page table page), the MMU initialization will map the + * NVRAM, Status/Control registers, CPM Dual Port RAM, and the PCI + * Bridge CSRs 1:1 into the kernel address space. + */ +#define PCI_ISA_IO_ADDR ((unsigned int)0x80000000) +#define PCI_ISA_IO_SIZE ((unsigned int)(512 * 1024 * 1024)) +#define PCI_ISA_MEM_ADDR ((unsigned int)0xc0000000) +#define PCI_ISA_MEM_SIZE ((unsigned int)(512 * 1024 * 1024)) +#define PCMCIA_MEM_ADDR ((unsigned int)0xe0000000) +#define PCMCIA_MEM_SIZE ((unsigned int)(64 * 1024 * 1024)) +#define PCMCIA_DMA_ADDR ((unsigned int)0xe4000000) +#define PCMCIA_DMA_SIZE ((unsigned int)(64 * 1024 * 1024)) +#define PCMCIA_ATTRB_ADDR ((unsigned int)0xe8000000) +#define PCMCIA_ATTRB_SIZE ((unsigned int)(64 * 1024 * 1024)) +#define PCMCIA_IO_ADDR ((unsigned int)0xec000000) +#define PCMCIA_IO_SIZE ((unsigned int)(64 * 1024 * 1024)) +#define NVRAM_ADDR ((unsigned int)0xfa000000) +#define NVRAM_SIZE ((unsigned int)(1 * 1024 * 1024)) +#define MBX_CSR_ADDR ((unsigned int)0xfa100000) +#define MBX_CSR_SIZE ((unsigned int)(1 * 1024 * 1024)) +#define IMAP_ADDR ((unsigned int)0xfa200000) +#define IMAP_SIZE ((unsigned int)(64 * 1024)) +#define PCI_CSR_ADDR ((unsigned int)0xfa210000) +#define PCI_CSR_SIZE ((unsigned int)(64 * 1024)) +#endif diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore b/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am new file mode 100644 index 0000000000..4b5bc87fe4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/Makefile.am @@ -0,0 +1,46 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +C_FILES = irq.c irq_init.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +H_FILES = irq.h + +S_FILES = irq_asm.S +S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) $(S_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +SORDID_HACK: + rm -f $(PROJECT_INCLUDE)/bsp/irq.h + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp/%.h: %.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp \ + $(H_FILES:%.h=$(PROJECT_INCLUDE)/bsp/%.h) + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +all-local: SORDID_HACK $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(PGM) + +EXTRA_DIST = irq.c irq.h irq_asm.S irq_init.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c new file mode 100644 index 0000000000..7e9e003c12 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.c @@ -0,0 +1,506 @@ +/* + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * default handler connected on each irq after bsp initialization + */ +static rtems_irq_connect_data default_rtems_entry; + +/* + * location used to store initial tables used for interrupt + * management. + */ +static rtems_irq_global_settings* internal_config; +static rtems_irq_connect_data* rtems_hdl_tbl; + +/* + * Check if symbolic IRQ name is an SIU IRQ + */ +static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine) +{ + return (((int) irqLine <= BSP_SIU_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET) + ); +} + +/* + * Check if symbolic IRQ name is an CPM IRQ + */ +static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine) +{ + return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET) + ); +} + +/* + * Check if symbolic IRQ name is a Processor IRQ + */ +static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine) +{ + return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) + ); +} + + +/* + * masks used to mask off the interrupts. For exmaple, for ILVL2, the + * mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7 + * and ILVL7. + * + */ +const static unsigned int SIU_IvectMask[BSP_SIU_IRQ_NUMBER] = +{ + /* IRQ0 ILVL0 IRQ1 ILVL1 */ + 0x00000000, 0x80000000, 0xC0000000, 0xE0000000, + + /* IRQ2 ILVL2 IRQ3 ILVL3 */ + 0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000, + + /* IRQ4 ILVL4 IRQ5 ILVL5 */ + 0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000, + + /* IRQ6 ILVL6 IRQ7 ILVL7 */ + 0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000 +}; + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +/* + * Caution : this function assumes the variable "internal_config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_SIU_IvectMask_from_prio () +{ + /* + * In theory this is feasible. No time to code it yet. See i386/shared/irq.c + * for an example based on 8259 controller mask. The actual masks defined + * correspond to the priorities defined for the SIU in irq_init.c. + */ +} + +/* + * This function check that the value given for the irq line + * is valid. + */ + +static int isValidInterrupt(int irq) +{ + if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) || (irq == BSP_CPM_INTERRUPT) ) + return 0; + return 1; +} + +int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 1; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_irq_index); + + return 0; +} + +int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 1; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_irq_index); + + return 0; +} + +int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine) +{ + int cpm_irq_index; + + if (!is_cpm_irq(irqLine)) + return 0; + + cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET); + return (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr & (1 << cpm_irq_index)); +} + +int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine) +{ + int siu_irq_index; + + if (!is_siu_irq(irqLine)) + return 1; + + siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET); + ppc_cached_irq_mask |= (1 << (31-siu_irq_index)); + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; + + return 0; +} + +int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine) +{ + int siu_irq_index; + + if (!is_siu_irq(irqLine)) + return 1; + + siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET); + ppc_cached_irq_mask &= ~(1 << (31-siu_irq_index)); + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; + + return 0; +} + +int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine) +{ + int siu_irq_index; + + if (!is_siu_irq(irqLine)) + return 0; + + siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET); + return ppc_cached_irq_mask & (1 << (31-siu_irq_index)); +} + +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ + +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + + if (!isValidInterrupt(irq->name)) { + return 0; + } + /* + * Check if default handler is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) { + return 0; + } + + _CPU_ISR_Disable(level); + + /* + * store the data provided by user + */ + rtems_hdl_tbl[irq->name] = *irq; + + if (is_cpm_irq(irq->name)) { + /* + * Enable interrupt at PIC level + */ + BSP_irq_enable_at_cpm (irq->name); + } + + if (is_siu_irq(irq->name)) { + /* + * Enable interrupt at SIU level + */ + BSP_irq_enable_at_siu (irq->name); + } + + if (is_processor_irq(irq->name)) { + /* + * Should Enable exception at processor level but not needed. Will restore + * EE flags at the end of the routine anyway. + */ + } + /* + * Enable interrupt on device + */ + irq->on(irq); + + _CPU_ISR_Enable(level); + + return 1; +} + + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + if (!isValidInterrupt(irq->name)) { + return 0; + } + *irq = rtems_hdl_tbl[irq->name]; + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + unsigned int level; + + if (!isValidInterrupt(irq->name)) { + return 0; + } + /* + * Check if default handler is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) { + return 0; + } + _CPU_ISR_Disable(level); + + if (is_cpm_irq(irq->name)) { + /* + * disable interrupt at PIC level + */ + BSP_irq_disable_at_cpm (irq->name); + } + if (is_siu_irq(irq->name)) { + /* + * disable interrupt at OPENPIC level + */ + BSP_irq_disable_at_siu (irq->name); + } + if (is_processor_irq(irq->name)) { + /* + * disable exception at processor level + */ + } + + /* + * Disable interrupt on device + */ + irq->off(irq); + + /* + * restore the default irq value + */ + rtems_hdl_tbl[irq->name] = default_rtems_entry; + + _CPU_ISR_Enable(level); + + return 1; +} + +/* + * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- + */ + +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + unsigned int level; + /* + * Store various code accelerators + */ + internal_config = config; + default_rtems_entry = config->defaultEntry; + rtems_hdl_tbl = config->irqHdlTbl; + + _CPU_ISR_Disable(level); + /* + * start with CPM IRQ + */ + for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + BSP_irq_enable_at_cpm (i); + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + } + else { + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + BSP_irq_disable_at_cpm (i); + } + } + + /* + * continue with PCI IRQ + */ + /* + * set up internal tables used by rtems interrupt prologue + */ + compute_SIU_IvectMask_from_prio (); + + for (i=BSP_SIU_IRQ_LOWEST_OFFSET; i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + BSP_irq_enable_at_siu (i); + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + } + else { + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + BSP_irq_disable_at_siu (i); + } + } + /* + * Must enable CPM interrupt on SIU. CPM on SIU Interrupt level has already been + * set up in BSP_CPM_irq_init. + */ + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; + BSP_irq_enable_at_siu (BSP_CPM_INTERRUPT); + /* + * finish with Processor exceptions handled like IRQ + */ + for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); + } + else { + rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); + } + } + _CPU_ISR_Enable(level); + return 1; +} + +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config) +{ + *config = internal_config; + return 0; +} + +#ifdef DISPATCH_HANDLER_STAT +volatile unsigned int maxLoop = 0; +#endif + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum) +{ + register unsigned int irq; + register unsigned cpmIntr; /* boolean */ + register unsigned oldMask; /* old siu pic masks */ + register unsigned msr; + register unsigned new_msr; + unsigned loopCounter; + + /* + * Handle decrementer interrupt + */ + if (excNum == ASM_DEC_VECTOR) { + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + rtems_hdl_tbl[BSP_DECREMENTER].hdl(); + + _CPU_MSR_SET(msr); + return; + } + /* + * Handle external interrupt generated by SIU on PPC core + */ +#ifdef DISPATCH_HANDLER_STAT + loopCounter = 0; +#endif + while (1) { + if ((ppc_cached_irq_mask & ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend) == 0) { +#ifdef DISPATCH_HANDLER_STAT + if (loopCounter > maxLoop) maxLoop = loopCounter; +#endif + break; + } + irq = (((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26); + cpmIntr = (irq == BSP_CPM_INTERRUPT); + /* + * Disable the interrupt of the same and lower priority. + */ + oldMask = ppc_cached_irq_mask; + ppc_cached_irq_mask = oldMask & SIU_IvectMask[irq]; + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; + /* + * Acknowledge current interrupt. This has no effect on internal level interrupt. + */ + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = (1 << (31 - irq)); + + if (cpmIntr) { + /* + * We will reenable the SIU CPM interrupt to allow nesting of CPM interrupt. + * We must before acknowledege the current irq at CPM level to avoid trigerring + * the interrupt again. + */ + /* + * Acknowledge and get the vector. + */ + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1; + irq = (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr >> 11); + /* + * transform IRQ to normalized irq table index. + */ + irq += BSP_CPM_IRQ_LOWEST_OFFSET; + /* + * Unmask CPM interrupt at SIU level + */ + ppc_cached_irq_mask |= (1 << (31 - BSP_CPM_INTERRUPT)); + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; + } + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + rtems_hdl_tbl[irq].hdl(); + + _CPU_MSR_SET(msr); + + if (cpmIntr) { + irq -= BSP_CPM_IRQ_LOWEST_OFFSET; + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << irq); + } + ppc_cached_irq_mask |= (oldMask & ~(SIU_IvectMask[irq])); + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask; +#ifdef DISPATCH_HANDLER_STAT + ++ loopCounter; +#endif + } +} + + + +void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx) +{ + /* + * Process pending signals that have not already been + * processed by _Thread_Displatch. This happens quite + * unfrequently : the ISR must have posted an action + * to the current running thread. + */ + if ( _Thread_Do_post_task_switch_extension || + _Thread_Executing->do_post_task_switch_extension ) { + _Thread_Executing->do_post_task_switch_extension = FALSE; + _API_extensions_Run_postswitch(); + } + /* + * I plan to process other thread related events here. + * This will include DEBUG session requested from keyboard... + */ +} diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h new file mode 100644 index 0000000000..2f0b46179f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq.h @@ -0,0 +1,331 @@ +/* irq.h + * + * This include file describe the data structure and the functions implemented + * by rtems to write interrupt handlers. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * This code is heavilly inspired by the public specification of STREAM V2 + * that can be found at : + * + * by following + * the STREAM API Specification Document link. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H +#define LIBBSP_POWERPC_MBX8XX_IRQ_IRQ_H + + +#define BSP_ASM_IRQ_VECTOR_BASE 0x0 + +#ifndef ASM + +extern volatile unsigned int ppc_cached_irq_mask; + +/* + * Symblolic IRQ names and related definitions. + */ + +typedef enum { + /* Base vector for our SIU IRQ handlers. */ + BSP_SIU_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE, + /* + * SIU IRQ handler related definitions + */ + BSP_SIU_IRQ_NUMBER = 16, /* 16 reserved but in the future... */ + BSP_SIU_IRQ_LOWEST_OFFSET = 0, + BSP_SIU_IRQ_MAX_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER - 1, + /* + * CPM IRQ handlers related definitions + * CAUTION : BSP_CPM_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE + */ + BSP_CPM_IRQ_NUMBER = 32, + BSP_CPM_IRQ_LOWEST_OFFSET = BSP_SIU_IRQ_NUMBER + BSP_SIU_VECTOR_BASE, + BSP_CPM_IRQ_MAX_OFFSET = BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER - 1, + /* + * PowerPc exceptions handled as interrupt where a rtems managed interrupt + * handler might be connected + */ + BSP_PROCESSOR_IRQ_NUMBER = 1, + BSP_PROCESSOR_IRQ_LOWEST_OFFSET = BSP_CPM_IRQ_MAX_OFFSET + 1, + BSP_PROCESSOR_IRQ_MAX_OFFSET = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1, + /* + * Summary + */ + BSP_IRQ_NUMBER = BSP_PROCESSOR_IRQ_MAX_OFFSET + 1, + BSP_LOWEST_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET, + BSP_MAX_OFFSET = BSP_PROCESSOR_IRQ_MAX_OFFSET, + /* + * Some SIU IRQ symbolic name definition. Please note that + * INT IRQ are defined but a single one will be used to + * redirect all CPM interrupt. + */ + BSP_SIU_EXT_IRQ_0 = 0, + BSP_SIU_INT_IRQ_0 = 1, + + BSP_SIU_EXT_IRQ_1 = 2, + BSP_SIU_INT_IRQ_1 = 3, + + BSP_SIU_EXT_IRQ_2 = 4, + BSP_SIU_INT_IRQ_2 = 5, + + BSP_SIU_EXT_IRQ_3 = 6, + BSP_SIU_INT_IRQ_3 = 7, + + BSP_SIU_EXT_IRQ_4 = 8, + BSP_SIU_INT_IRQ_4 = 9, + + BSP_SIU_EXT_IRQ_5 = 10, + BSP_SIU_INT_IRQ_5 = 11, + + BSP_SIU_EXT_IRQ_6 = 12, + BSP_SIU_INT_IRQ_6 = 13, + + BSP_SIU_EXT_IRQ_7 = 14, + BSP_SIU_INT_IRQ_7 = 15, + /* + * Symbolic name for CPM interrupt on SIU Internal level 2 + */ + BSP_CPM_INTERRUPT = BSP_SIU_INT_IRQ_2, + BSP_PERIODIC_TIMER = BSP_SIU_INT_IRQ_6, + BSP_FAST_ETHERNET_CTRL = BSP_SIU_INT_IRQ_3, + /* + * Some CPM IRQ symbolic name definition + */ + BSP_CPM_IRQ_ERROR = BSP_CPM_IRQ_LOWEST_OFFSET, + BSP_CPM_IRQ_PARALLEL_IO_PC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 1, + BSP_CPM_IRQ_PARALLEL_IO_PC5 = BSP_CPM_IRQ_LOWEST_OFFSET + 2, + BSP_CPM_IRQ_SMC2_OR_PIP = BSP_CPM_IRQ_LOWEST_OFFSET + 3, + BSP_CPM_IRQ_SMC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 4, + BSP_CPM_IRQ_SPI = BSP_CPM_IRQ_LOWEST_OFFSET + 5, + BSP_CPM_IRQ_PARALLEL_IO_PC6 = BSP_CPM_IRQ_LOWEST_OFFSET + 6, + BSP_CPM_IRQ_TIMER_4 = BSP_CPM_IRQ_LOWEST_OFFSET + 7, + + BSP_CPM_IRQ_PARALLEL_IO_PC7 = BSP_CPM_IRQ_LOWEST_OFFSET + 9, + BSP_CPM_IRQ_PARALLEL_IO_PC8 = BSP_CPM_IRQ_LOWEST_OFFSET + 10, + BSP_CPM_IRQ_PARALLEL_IO_PC9 = BSP_CPM_IRQ_LOWEST_OFFSET + 11, + BSP_CPM_IRQ_TIMER_3 = BSP_CPM_IRQ_LOWEST_OFFSET + 12, + + BSP_CPM_IRQ_PARALLEL_IO_PC10 = BSP_CPM_IRQ_LOWEST_OFFSET + 14, + BSP_CPM_IRQ_PARALLEL_IO_PC11 = BSP_CPM_IRQ_LOWEST_OFFSET + 15, + BSP_CPM_I2C = BSP_CPM_IRQ_LOWEST_OFFSET + 16, + BSP_CPM_RISC_TIMER_TABLE = BSP_CPM_IRQ_LOWEST_OFFSET + 17, + BSP_CPM_IRQ_TIMER_2 = BSP_CPM_IRQ_LOWEST_OFFSET + 18, + + BSP_CPM_IDMA2 = BSP_CPM_IRQ_LOWEST_OFFSET + 20, + BSP_CPM_IDMA1 = BSP_CPM_IRQ_LOWEST_OFFSET + 21, + BSP_CPM_SDMA_CHANNEL_BUS_ERR = BSP_CPM_IRQ_LOWEST_OFFSET + 22, + BSP_CPM_IRQ_PARALLEL_IO_PC12 = BSP_CPM_IRQ_LOWEST_OFFSET + 23, + BSP_CPM_IRQ_PARALLEL_IO_PC13 = BSP_CPM_IRQ_LOWEST_OFFSET + 24, + BSP_CPM_IRQ_TIMER_1 = BSP_CPM_IRQ_LOWEST_OFFSET + 25, + BSP_CPM_IRQ_PARALLEL_IO_PC14 = BSP_CPM_IRQ_LOWEST_OFFSET + 26, + BSP_CPM_IRQ_SCC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 27, + BSP_CPM_IRQ_SCC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 28, + BSP_CPM_IRQ_SCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 29, + BSP_CPM_IRQ_SCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 30, + BSP_CPM_IRQ_PARALLEL_IO_PC15 = BSP_CPM_IRQ_LOWEST_OFFSET + 31, + /* + * Some Processor exception handled as rtems IRQ symbolic name definition + */ + BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + +}rtems_irq_symbolic_name; + +#define CPM_INTERRUPT + + +/* + * Type definition for RTEMS managed interrupts + */ +typedef unsigned char rtems_irq_prio; +struct __rtems_irq_connect_data__; /* forward declaratiuon */ + +typedef void (*rtems_irq_hdl) (void); +typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*); +typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*); +typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*); + +typedef struct __rtems_irq_connect_data__ { + /* + * IRQ line + */ + rtems_irq_symbolic_name name; + /* + * handler. See comment on handler properties below in function prototype. + */ + rtems_irq_hdl hdl; + /* + * function for enabling interrupts at device level (ONLY!). + * The BSP code will automatically enable it at SIU level and CPM level. + * RATIONALE : anyway such code has to exist in current driver code. + * It is usually called immediately AFTER connecting the interrupt handler. + * RTEMS may well need such a function when restoring normal interrupt + * processing after a debug session. + * + */ + rtems_irq_enable on; + /* + * function for disabling interrupts at device level (ONLY!). + * The code will disable it at SIU and CPM level. RATIONALE : anyway + * such code has to exist for clean shutdown. It is usually called + * BEFORE disconnecting the interrupt. RTEMS may well need such + * a function when disabling normal interrupt processing for + * a debug session. May well be a NOP function. + */ + rtems_irq_disable off; + /* + * function enabling to know what interrupt may currently occur + * if someone manipulates the i8259s interrupt mask without care... + */ + rtems_irq_is_enabled isOn; +}rtems_irq_connect_data; + +typedef struct { + /* + * size of all the table fields (*Tbl) described below. + */ + unsigned int irqNb; + /* + * Default handler used when disconnecting interrupts. + */ + rtems_irq_connect_data defaultEntry; + /* + * Table containing initials/current value. + */ + rtems_irq_connect_data* irqHdlTbl; + /* + * actual value of BSP_SIU_IRQ_VECTOR_BASE... + */ + rtems_irq_symbolic_name irqBase; + /* + * software priorities associated with interrupts. + * if irqPrio [i] > intrPrio [j] it means that + * interrupt handler hdl connected for interrupt name i + * will not be interrupted by the handler connected for interrupt j + * The interrupt source will be physically masked at i8259 level. + */ + rtems_irq_prio* irqPrioTbl; +}rtems_irq_global_settings; + + + + +/*-------------------------------------------------------------------------+ +| Function Prototypes. ++--------------------------------------------------------------------------*/ +/* + * ------------------------ PPC SIU Mngt Routines ------- + */ + +/* + * function to disable a particular irq at 8259 level. After calling + * this function, even if the device asserts the interrupt line it will + * not be propagated further to the processor + */ +int BSP_irq_disable_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to enable a particular irq at 8259 level. After calling + * this function, if the device asserts the interrupt line it will + * be propagated further to the processor + */ +int BSP_irq_enable_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to acknoledge a particular irq at 8259 level. After calling + * this function, if a device asserts an enabled interrupt line it will + * be propagated further to the processor. Mainly usefull for people + * writting raw handlers as this is automagically done for rtems managed + * handlers. + */ +int BSP_irq_ack_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * function to check if a particular irq is enabled at 8259 level. After calling + */ +int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine); +/* + * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- + */ +/* + * function to connect a particular irq handler. This hanlder will NOT be called + * directly as the result of the corresponding interrupt. Instead, a RTEMS + * irq prologue will be called that will : + * + * 1) save the C scratch registers, + * 2) switch to a interrupt stack if the interrupt is not nested, + * 4) modify them to disable the current interrupt at SIU level (and may + * be others depending on software priorities) + * 5) aknowledge the SIU', + * 6) demask the processor, + * 7) call the application handler + * + * As a result the hdl function provided + * + * a) can perfectly be written is C, + * b) may also well directly call the part of the RTEMS API that can be used + * from interrupt level, + * c) It only responsible for handling the jobs that need to be done at + * the device level including (aknowledging/re-enabling the interrupt at device, + * level, getting the data,...) + * + * When returning from the function, the following will be performed by + * the RTEMS irq epilogue : + * + * 1) masks the interrupts again, + * 2) restore the original SIU interrupt masks + * 3) switch back on the orinal stack if needed, + * 4) perform rescheduling when necessary, + * 5) restore the C scratch registers... + * 6) restore initial execution flow + * + */ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); +/* + * function to get the current RTEMS irq handler for ptr->name. It enables to + * define hanlder chain... + */ +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); +/* + * function to get disconnect the RTEMS irq handler for ptr->name. + * This function checks that the value given is the current one for safety reason. + * The user can use the previous function to get it. + */ +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); + +/* + * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- + */ +/* + * (Re) Initialize the RTEMS interrupt management. + * + * The result of calling this function will be the same as if each individual + * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl" + * has been individualy connected via + * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i]) + * And each handler currently equal to config->defaultEntry.hdl + * has been previously disconnected via + * BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i]) + * + * This is to say that all information given will be used and not just + * only the space. + * + * CAUTION : the various table address contained in config will be used + * directly by the interrupt mangement code in order to save + * data size so they must stay valid after the call => they should + * not be modified or declared on a stack. + */ + +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config); +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**); + +extern void BSP_rtems_irq_mng_init(unsigned cpuId); +#endif + +#endif diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S new file mode 100644 index 0000000000..914ab67a4d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_asm.S @@ -0,0 +1,329 @@ +/* + * This file contains the assembly code for the PowerPC + * IRQ veneers for RTEMS. + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Modified to support the MCP750. + * Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * + * $Id$ + */ + +#include +#include +#include +#include /* for PPC_HAS_FPU */ +#include "asm.h" + + +#define SYNC \ + sync; \ + isync + + .text + .p2align 5 + + PUBLIC_VAR(decrementer_exception_vector_prolog_code) + +SYM (decrementer_exception_vector_prolog_code): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_DEC_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (decrementer_exception_vector_prolog_code_size) + + decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code + + PUBLIC_VAR(external_exception_vector_prolog_code) + +SYM (external_exception_vector_prolog_code): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r4, GPR4_OFFSET(r1) + li r4, ASM_EXT_VECTOR + ba shared_raw_irq_code_entry + + PUBLIC_VAR (external_exception_vector_prolog_code_size) + + external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code + + PUBLIC_VAR(shared_raw_irq_code_entry) + PUBLIC_VAR(C_dispatch_irq_handler) + + .p2align 5 +SYM (shared_raw_irq_code_entry): + /* + * Entry conditions : + * Registers already saved : R1, R4 + * R1 : points to a location with enough room for the + * interrupt frame + * R4 : vector number + */ + /* + * Save SRR0/SRR1 As soon As possible as it is the minimal needed + * to reenable exception processing + */ + stw r0, GPR0_OFFSET(r1) + stw r2, GPR2_OFFSET(r1) + stw r3, GPR3_OFFSET(r1) + + mfsrr0 r0 + mfsrr1 r2 + mfmsr r3 + + stw r0, SRR0_FRAME_OFFSET(r1) + stw r2, SRR1_FRAME_OFFSET(r1) + /* + * Enable data and instruction address translation, exception recovery + * + * also, on CPUs with FP, enable FP so that FP context can be + * saved and restored (using FP instructions) + */ +#if (PPC_HAS_FPU == 0) + ori r3, r3, MSR_RI | MSR_IR | MSR_DR +#else + ori r3, r3, MSR_RI | MSR_IR | MSR_DR | MSR_FP +#endif + mtmsr r3 + SYNC + /* + * Push C scratch registers on the current stack. It may + * actually be the thread stack or the interrupt stack. + * Anyway we have to make it in order to be able to call C/C++ + * functions. Depending on the nesting interrupt level, we will + * switch to the right stack later. + */ + stw r5, GPR5_OFFSET(r1) + stw r6, GPR6_OFFSET(r1) + stw r7, GPR7_OFFSET(r1) + stw r8, GPR8_OFFSET(r1) + stw r9, GPR9_OFFSET(r1) + stw r10, GPR10_OFFSET(r1) + stw r11, GPR11_OFFSET(r1) + stw r12, GPR12_OFFSET(r1) + stw r13, GPR13_OFFSET(r1) + + mfcr r5 + mfctr r6 + mfxer r7 + mflr r8 + + stw r5, EXC_CR_OFFSET(r1) + stw r6, EXC_CTR_OFFSET(r1) + stw r7, EXC_XER_OFFSET(r1) + stw r8, EXC_LR_OFFSET(r1) + + /* + * Add some non volatile registers to store information + * that will be used when returning from C handler + */ + stw r14, GPR14_OFFSET(r1) + stw r15, GPR15_OFFSET(r1) + /* + * save current stack pointer location in R14 + */ + addi r14, r1, 0 + /* + * store part of _Thread_Dispatch_disable_level address in R15 + */ + addis r15,0, _Thread_Dispatch_disable_level@ha + /* + * Get current nesting level in R2 + */ + mfspr r2, SPRG0 + /* + * Check if stack switch is necessary + */ + cmpwi r2,0 + bne nested + mfspr r1, SPRG1 + +nested: + /* + * Start Incrementing nesting level in R2 + */ + addi r2,r2,1 + /* + * Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level + */ + lwz r6,_Thread_Dispatch_disable_level@l(r15) + /* + * store new nesting level in SPRG0 + */ + mtspr SPRG0, r2 + + addi r6, r6, 1 + mfmsr r5 + /* + * store new _Thread_Dispatch_disable_level value + */ + stw r6, _Thread_Dispatch_disable_level@l(r15) + /* + * We are now running on the interrupt stack. External and decrementer + * exceptions are still disabled. I see no purpose trying to optimize + * further assembler code. + */ + /* + * Call C exception handler for decrementer Interrupt frame is passed just + * in case... + */ + addi r3, r14, 0x8 + bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */ + /* + * start decrementing nesting level. Note : do not test result against 0 + * value as an easy exit condition because if interrupt nesting level > 1 + * then _Thread_Dispatch_disable_level > 1 + */ + mfspr r2, SPRG0 + /* + * start decrementing _Thread_Dispatch_disable_level + */ + lwz r3,_Thread_Dispatch_disable_level@l(r15) + addi r2, r2, -1 /* Continue decrementing nesting level */ + addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */ + mtspr SPRG0, r2 /* End decrementing nesting level */ + stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */ + cmpwi r3, 0 + /* + * switch back to original stack (done here just optimize registers + * contention. Could have been done before...) + */ + addi r1, r14, 0 + bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */ + /* + * Here we are running again on the thread system stack. + * We have interrupt nesting level = _Thread_Dispatch_disable_level = 0. + * Interrupt are still disabled. Time to check if scheduler request to + * do something with the current thread... + */ + addis r4, 0, _Context_Switch_necessary@ha + lwz r5, _Context_Switch_necessary@l(r4) + cmpwi r5, 0 + bne switch + + addis r6, 0, _ISR_Signals_to_thread_executing@ha + lwz r7, _ISR_Signals_to_thread_executing@l(r6) + cmpwi r7, 0 + li r8, 0 + beq easy_exit + stw r8, _ISR_Signals_to_thread_executing@l(r6) + /* + * going to call _ThreadProcessSignalsFromIrq + * Push a complete exception like frame... + */ + stmw r16, GPR16_OFFSET(r1) + addi r3, r1, 0x8 + /* + * compute SP at exception entry + */ + addi r2, r1, EXCEPTION_FRAME_END + /* + * store it at the right place + */ + stw r2, GPR1_OFFSET(r1) + /* + * Call High Level signal handling code + */ + bl _ThreadProcessSignalsFromIrq + /* + * start restoring exception like frame + */ + lwz r31, EXC_CTR_OFFSET(r1) + lwz r30, EXC_XER_OFFSET(r1) + lwz r29, EXC_CR_OFFSET(r1) + lwz r28, EXC_LR_OFFSET(r1) + + mtctr r31 + mtxer r30 + mtcr r29 + mtlr r28 + + lmw r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + /* + * Disable data and instruction translation. Make path non recoverable... + */ + mfmsr r3 + xori r3, r3, MSR_RI | MSR_IR | MSR_DR + mtmsr r3 + SYNC + /* + * Restore rfi related settings + */ + + lwz r3, SRR1_FRAME_OFFSET(r1) + mtsrr1 r3 + lwz r3, SRR0_FRAME_OFFSET(r1) + mtsrr0 r3 + + lwz r3, GPR3_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + +switch: + bl SYM (_Thread_Dispatch) + +easy_exit: + /* + * start restoring interrupt frame + */ + lwz r3, EXC_CTR_OFFSET(r1) + lwz r4, EXC_XER_OFFSET(r1) + lwz r5, EXC_CR_OFFSET(r1) + lwz r6, EXC_LR_OFFSET(r1) + + mtctr r3 + mtxer r4 + mtcr r5 + mtlr r6 + + lwz r15, GPR15_OFFSET(r1) + lwz r14, GPR14_OFFSET(r1) + lwz r13, GPR13_OFFSET(r1) + lwz r12, GPR12_OFFSET(r1) + lwz r11, GPR11_OFFSET(r1) + lwz r10, GPR10_OFFSET(r1) + lwz r9, GPR9_OFFSET(r1) + lwz r8, GPR8_OFFSET(r1) + lwz r7, GPR7_OFFSET(r1) + lwz r6, GPR6_OFFSET(r1) + lwz r5, GPR5_OFFSET(r1) + + /* + * Disable nested exception processing, data and instruction + * translation. + */ + mfmsr r3 + xori r3, r3, MSR_RI | MSR_IR | MSR_DR + mtmsr r3 + SYNC + /* + * Restore rfi related settings + */ + + lwz r4, SRR1_FRAME_OFFSET(r1) + lwz r2, SRR0_FRAME_OFFSET(r1) + lwz r3, GPR3_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + mtsrr1 r4 + mtsrr0 r2 + lwz r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi + diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c new file mode 100644 index 0000000000..9834c40145 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/irq/irq_init.c @@ -0,0 +1,162 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * CopyRight (C) 2001 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#include +#include +#include +#include +#include +#include + +extern unsigned int external_exception_vector_prolog_code_size; +extern void external_exception_vector_prolog_code(); +extern unsigned int decrementer_exception_vector_prolog_code_size; +extern void decrementer_exception_vector_prolog_code(); + +volatile unsigned int ppc_cached_irq_mask; + +/* + * default on/off function + */ +static void nop_func(){} +/* + * default isOn function + */ +static int not_connected() {return 0;} +/* + * default possible isOn function + */ +static int connected() {return 1;} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + /* vectorIdex, hdl , on , off , isOn */ + 0, nop_func , nop_func , nop_func , not_connected +}; +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * actual rpiorities for interrupt : + * 0 means that only current interrupt is masked + * 255 means all other interrupts are masked + */ + /* + * SIU interrupts. + */ + 7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0, + /* + * CPM Interrupts + */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + +void BSP_SIU_irq_init() +{ + /* + * In theory we should initialize two registers at least : + * SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But + * we should take care that a monitor may have restoreed to another value. + * If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT + * please feel free to add it here. + */ + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0; + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000; + ppc_cached_irq_mask = 0; + ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel; +} + +/* + * Initialize CPM interrupt management + */ +void +BSP_CPM_irq_init(void) +{ + /* + * Initialize the CPM interrupt controller. + */ + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr = +#ifdef mpc860 + (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) | +#else + (CICR_SCB_SCC2 | CICR_SCA_SCC1) | +#endif + ((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK; + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0; + + ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN; +} + +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + rtems_raw_except_connect_data vectorDesc; + int i; + + BSP_SIU_irq_init(); + BSP_CPM_irq_init(); + /* + * Initialize Rtems management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE; + initial_config.irqPrioTbl = irqPrioTable; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } + + /* + * We must connect the raw irq handler for the two + * expected interrupt sources : decrementer and external interrupts. + */ + vectorDesc.exceptIndex = ASM_DEC_VECTOR; + vectorDesc.hdl.vector = ASM_DEC_VECTOR; + vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size; + vectorDesc.on = nop_func; + vectorDesc.off = nop_func; + vectorDesc.isOn = connected; + if (!mpc8xx_set_exception (&vectorDesc)) { + BSP_panic("Unable to initialize RTEMS decrementer raw exception\n"); + } + vectorDesc.exceptIndex = ASM_EXT_VECTOR; + vectorDesc.hdl.vector = ASM_EXT_VECTOR; + vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code; + vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size; + if (!mpc8xx_set_exception (&vectorDesc)) { + BSP_panic("Unable to initialize RTEMS external raw exception\n"); + } +#ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operationnal\n"); +#endif +} + diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c b/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c index a491af5670..2f28be8907 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c +++ b/c/src/lib/libbsp/powerpc/mbx8xx/network/network.c @@ -37,6 +37,7 @@ #include #include +#include /* * Number of interfaces supported by this driver @@ -79,8 +80,6 @@ # error "Driver must have MCLBYTES > RBUF_SIZE" #endif -extern unsigned32 simask_copy; - /* * Per-device data */ @@ -124,11 +123,26 @@ struct m8xx_enet_struct { static struct m8xx_enet_struct enet_driver[NIFACES]; +static void m8xx_scc1_ethernet_on(const rtems_irq_connect_data* ptr) +{ +} + +static void m8xx_scc1_ethernet_off(const rtems_irq_connect_data* ptr) +{ + /* + * Please put relevant code there + */ +} + +static void m8xx_scc1_ethernet_isOn(const rtems_irq_connect_data* ptr) +{ + return BSP_irq_enabled_at_cpm (ptr->name); +} + /* * SCC1 interrupt handler */ -static rtems_isr -m8xx_scc1_interrupt_handler (rtems_vector_number v) +static void m8xx_scc1_interrupt_handler () { /* Frame received? */ if ((m8xx.scc1.sccm & 0x8) && (m8xx.scc1.scce & 0x8)) { @@ -145,15 +159,13 @@ m8xx_scc1_interrupt_handler (rtems_vector_number v) enet_driver[0].txInterrupts++; /* Tx int has occurred */ rtems_event_send (enet_driver[0].txDaemonTid, INTERRUPT_EVENT); } - m8xx.cisr = 1UL << 30; /* Clear SCC1 interrupt-in-service bit */ } #ifdef MPC860T /* * FEC interrupt handler */ -static rtems_isr -m860_fec_interrupt_handler (rtems_vector_number v) +static void m860_fec_interrupt_handler () { /* * Frame received? @@ -175,6 +187,13 @@ m860_fec_interrupt_handler (rtems_vector_number v) } #endif +static rtems_irq_connect_data ethernetSCC1IrqData = { + BSP_CPM_IRQ_SCC1, + (rtems_irq_hdl) m8xx_scc1_interrupt_handler, + (rtems_irq_enable) m8xx_scc1_ethernet_on, + (rtems_irq_disable) m8xx_scc1_ethernet_off, + (rtems_irq_is_enabled)m8xx_scc1_ethernet_isOn +}; /* * Initialize the ethernet hardware @@ -348,15 +367,12 @@ m8xx_enet_initialize (struct m8xx_enet_struct *sc) /* * Set up interrupts */ - status = rtems_interrupt_catch (m8xx_scc1_interrupt_handler, - PPC_IRQ_CPM_SCC1, - &old_handler); + status = BSP_install_rtems_irq_handler (ðernetSCC1IrqData); if (status != RTEMS_SUCCESSFUL) { rtems_panic ("Can't attach M8xx SCC1 interrupt handler: %s\n", rtems_status_text (status)); } m8xx.scc1.sccm = 0; /* No interrupts unmasked till necessary */ - m8xx.cimr |= (1UL << 30); /* Enable SCC1 interrupt */ /* * Set up General SCC Mode Register @@ -395,27 +411,6 @@ m8xx_enet_initialize (struct m8xx_enet_struct *sc) m8xx.pcpar |= 0x1; m8xx.pcdir &= ~0x1; - - /* - * Set up interrupts - * FIXME: DANGER: WARNING: - * CICR and SIMASK must be set in any module that uses - * the CPM. Currently those are console-generic.c and - * network.c. If the registers are not set the same - * in both places, strange things may happen. - * If they are only set in one place, then an application - * that uses only the other module won't work correctly. - * Put this comment in each module that sets these 2 registers - */ -#ifdef mpc860 - m8xx.cicr = 0x00e43f80; /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3, - SCdP=SCC4, IRL=1, HP=PC15, IEN=1 */ -#else - m8xx.cicr = 0x00043F80; /* SCaP=SCC1, SCbP=SCC2, IRL=1, HP=PC15, IEN=1 */ -#endif - simask_copy = m8xx.simask | M8xx_SIMASK_LVM1; /* Enable level interrupts */ - m8xx.simask |= M8xx_SIMASK_LVM1; /* Enable level interrupts */ - /* * Enable receiver and transmitter */ @@ -424,6 +419,25 @@ m8xx_enet_initialize (struct m8xx_enet_struct *sc) #ifdef MPC860T +/* + * Please organize FEC controller code better by moving code from + * m860_fec_initialize_hardware to m8xx_fec_ethernet_on + */ +static void m8xx_fec_ethernet_on(){}; +static void m8xx_fec_ethernet_off(){}; +static int m8xx_fec_ethernet_isOn (const rtems_irq_connect_data* ptr) +{ + return BSP_irq_enabled_at_siu (ptr->name); +} + +static rtems_irq_connect_data ethernetFECIrqData = { + BSP_FAST_ETHERNET_CTRL, + (rtems_irq_hdl) m8xx_fec_interrupt_handler, + (rtems_irq_enable) m8xx_fec_ethernet_on, + (rtems_irq_disable) m8xx_fec_ethernet_off, + (rtems_irq_is_enabled)m8xx_fec_ethernet_isOn +}; + static void m860_fec_initialize_hardware (struct m860_enet_struct *sc) { @@ -458,7 +472,7 @@ m860_fec_initialize_hardware (struct m860_enet_struct *sc) * Set SIU interrupt level to LVL2 * */ - m8xx.fec.ivec = 0x02 << 29; + m8xx.fec.ivec = ((((unsigned) BSP_FAST_ETHERNET_CTRL)/2) << 29); /* * Set the TX and RX fifo sizes. For now, we'll split it evenly @@ -572,9 +586,7 @@ m860_fec_initialize_hardware (struct m860_enet_struct *sc) /* * Set up interrupts */ - status = rtems_interrupt_catch (m860_fec_interrupt_handler, - PPC_IRQ_LVL2, - &old_handler); + status = status = BSP_install_rtems_irq_handler (ðernetFECIrqData); if (status != RTEMS_SUCCESSFUL) rtems_panic ("Can't attach M860 FEC interrupt handler: %s\n", rtems_status_text (status)); @@ -1566,7 +1578,7 @@ rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config) /* * Process options */ - #if NVRAM_CONFIGURE == 1 +#if NVRAM_CONFIGURE == 1 /* Configure from NVRAM */ if ( (addr = nvram->ipaddr) ) { @@ -1607,7 +1619,7 @@ rtems_scc1_driver_attach (struct rtems_bsdnet_ifconfig *config) rtems_panic("No Ethernet address specified!\n"); } - #else /* NVRAM_CONFIGURE != 1 */ +#else /* NVRAM_CONFIGURE != 1 */ if (config->hardware_address) { memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am index 1047f49ab7..f112f6297a 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/Makefile.am @@ -9,7 +9,7 @@ VPATH = @srcdir@:@srcdir@/../../../shared PGM = $(ARCH)/startup.rel C_FILES = bspclean.c bsplibc.c bsppost.c bspstart.c bootcard.c imbx8xx.c \ - main.c mmutlbtab.c sbrk.c setvec.c gnatinstallhandler.c + main.c mmutlbtab.c sbrk.c gnatinstallhandler.c C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) S_FILES = start.s diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c index 7e6a7ae9cf..bf874f70b6 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/bspstart.c @@ -32,6 +32,7 @@ * the .bss section (RAM). */ extern rtems_configuration_table Configuration; +extern unsigned long intrStackPtr; rtems_configuration_table BSP_Configuration; rtems_cpu_table Cpu_table; @@ -46,6 +47,18 @@ char *rtems_progname; void bsp_postdriver_hook(void); void bsp_libc_init( void *, unsigned32, int ); +void BSP_panic(char *s) +{ + printk("%s PANIC %s\n",_RTEMS_version, s); + __asm__ __volatile ("sc"); +} + +void _BSP_Fatal_error(unsigned int v) +{ + printk("%s PANIC ERROR %x\n",_RTEMS_version, v); + __asm__ __volatile ("sc"); +} + /* * bsp_pretasking_hook * @@ -116,6 +129,18 @@ void bsp_start(void) { extern void *_WorkspaceBase; + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + register unsigned char* intrStack; + register unsigned int intrNestingLevel = 0; + + /* + * Get CPU identification dynamically. Note that the get_ppc_cpu_type() function + * store the result in global variables so that it can be used latter... + */ + myCpu = get_ppc_cpu_type(); + myCpuRevision = get_ppc_cpu_revision(); + mmu_init(); /* @@ -134,7 +159,20 @@ void bsp_start(void) rtems_cache_enable_data(); #endif #endif - + /* + * Initialize some SPRG registers related to irq handling + */ + + intrStack = (((unsigned char*)&intrStackPtr) - CPU_MINIMUM_STACK_FRAME_SIZE); + asm volatile ("mtspr 273, %0" : "=r" (intrStack) : "0" (intrStack)); + asm volatile ("mtspr 272, %0" : "=r" (intrNestingLevel) : "0" (intrNestingLevel)); + + /* + * Install our own set of exception vectors + */ + initialize_exceptions(); + + /* * Allocate the memory for the RTEMS Work Space. This can come from * a variety of places: hard coded address, malloc'ed from outside @@ -181,5 +219,13 @@ void bsp_start(void) m8xx.scc2p.rbase=0; m8xx.scc2p.tbase=0; m8xx_cp_execute_cmd( M8xx_CR_OP_STOP_TX | M8xx_CR_CHAN_SCC2 ); + /* + * Initalize RTEMS IRQ system + */ + BSP_rtems_irq_mng_init(0); +#ifdef SHOW_MORE_INIT_SETTINGS + printk("Exit from bspstart\n"); +#endif + } diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c index eca58e56f5..716e86ab61 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/imbx8xx.c @@ -258,7 +258,7 @@ void _InitMBX8xx (void) /* Initialize the Periodic Interrupt Status and Control Register (PISCR) */ m8xx.piscrk = M8xx_UNLOCK_KEY; /* unlock PISCR */ - m8xx.piscr = 0x0083; /* Default MBX and firmware value. */ + m8xx.piscr = 0x0083; /* Default MBX and firmware value. */ /* Initialize the System Clock and Reset Control Register (SCCR) * Set the clock sources and division factors: diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds b/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds index 565e7f175b..5afa4b1d51 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/linkcmds @@ -198,7 +198,15 @@ SECTIONS bss.size = bss.end - bss.start; text.size = text.end - text.start; PROVIDE(_end = bss.end); - + /* + * Interrupt stack setup + */ + + IntrStack_start = ALIGN(0x10); + . += 0x4000; + intrStack = .; + PROVIDE(intrStackPtr = intrStack); + _HeapStart = .; __HeapStart = .; . += HeapSize; /* XXX -- Old gld can't handle this */ diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c b/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c index 50e1a57abd..6330bc1741 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/mmutlbtab.c @@ -103,15 +103,15 @@ MMU_TLB_table_t MMU_TLB_table[] = { /* * * Board Control/Status Register #1/#2: CS4, Start address 0xFA100000, (4 x 8 bits?) - * ASID=0x0, APG=0x0, guarded memory, copyback data cache policy, + * ASID=0x0, APG=0x0, guarded memory, write-through data cache policy, * R/W,X for all, no ASID comparison, cache-inhibited. * EPN TWC RPN */ - { 0xFA100200, 0x11, 0xFA1009F7 }, /* BCSR - PS=4K */ + { 0xFA100200, 0x13, 0xFA1009F7 }, /* BCSR - PS=4K */ /* * * (IMMR-SPRs) Dual Port RAM: Start address 0xFA200000, 16K, - * ASID=0x0, APG=0x0, guarded memory, copyback data cache policy, + * ASID=0x0, APG=0x0, guarded memory, write-through data cache policy, * R/W,X for all, no ASID comparison, cache-inhibited. * * Note: We use the value in MBXA/PG2, which is also the value that @@ -120,7 +120,7 @@ MMU_TLB_table_t MMU_TLB_table[] = { * of the firmware. * EPN TWC RPN */ - { 0xFA200200, 0x11, 0xFA2009FF }, /* IMMR - PS=16K */ + { 0xFA200200, 0x13, 0xFA2009FF }, /* IMMR - PS=16K */ /* * * Flash: CS0, Start address 0xFE000000, 4M, (BootROM-EPPCBug) diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S b/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S index ecd2971559..7b8dfde7f9 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S +++ b/c/src/lib/libbsp/powerpc/mbx8xx/startup/start.S @@ -239,14 +239,20 @@ spin: lwz r3, spin@l(r3) cmpwi r3, 0x1 beq .spin - +/* + * #define LOADED_BY_EPPCBUG + */ /* * Initialization code */ .startup: /* Get the start address. */ mflr r1 - +#ifdef LOADED_BY_EPPCBUG + /* Save pointer to residual/board data */ + lis r9,eppcbugInfo@ha + stw r3,eppcbugInfo@l(r9) +#endif /* Initialize essential registers. */ bl initregs nop @@ -270,8 +276,8 @@ spin: bl bssclr nop - lis 5,environ@ha - la 5,environ@l(5) /* environp */ + lis r5,environ@ha + la r5,environ@l(r5) /* environp */ /* clear argc and argv */ xor r3, r3, r3 xor r4, r4, r4 @@ -358,7 +364,7 @@ initregs: mr r8, r0 mr r9, r0 mr r10, r0 - mr r11, r0 + mr r11, r0 mr r12, r0 mr r13, r0 mr r14, r0 diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/vectors/.cvsignore b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/vectors/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/Makefile.am new file mode 100644 index 0000000000..d3a237fee4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/Makefile.am @@ -0,0 +1,40 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +VPATH = @srcdir@: + +C_FILES = vectors_init.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +H_FILES = vectors.h + +S_FILES = vectors.S +S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o) + +OBJS = $(S_O_FILES) $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PGM): $(OBJS) + $(make-rel) + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $@ + +$(PROJECT_INCLUDE)/bsp/vectors.h: vectors.h + $(INSTALL_DATA) $< $@ + +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/vectors.h + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.S b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.S new file mode 100644 index 0000000000..a056fab3ce --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.S @@ -0,0 +1,143 @@ +/* + * (c) 1999, Eric Valette valette@crf.canon.fr + * + * + * This file contains the assembly code for the PowerPC + * exception veneers for RTEMS. + * + * $Id$ + */ + + + +#include +#include +#include +#include "asm.h" + + +#define SYNC \ + sync; \ + isync + + .text + .p2align 5 + +PUBLIC_VAR(default_exception_vector_code_prolog) +SYM (default_exception_vector_code_prolog): + /* + * let room for exception frame + */ + stwu r1, - (EXCEPTION_FRAME_END)(r1) + stw r3, GPR3_OFFSET(r1) + stw r2, GPR2_OFFSET(r1) + mflr r2 + stw r2, EXC_LR_OFFSET(r1) + bl 0f +0: /* + * r3 = exception vector entry point + * (256 * vector number) + few instructions + */ + mflr r3 + /* + * r3 = r3 >> 8 = vector + */ + srwi r3,r3,8 + ba push_normalized_frame + + PUBLIC_VAR (default_exception_vector_code_prolog_size) + + default_exception_vector_code_prolog_size= . - default_exception_vector_code_prolog + + .p2align 5 +PUBLIC_VAR (push_normalized_frame) +SYM (push_normalized_frame): + stw r3, EXCEPTION_NUMBER_OFFSET(r1) + stw r0, GPR0_OFFSET(r1) + mfsrr0 r2 + stw r2, SRR0_FRAME_OFFSET(r1) + mfsrr1 r3 + stw r3, SRR1_FRAME_OFFSET(r1) + /* + * Save general purpose registers + * Already saved in prolog : R1, R2, R3, LR. + * Saved a few line above : R0 + * + * Manual says that "stmw" instruction may be slower than + * series of individual "stw" but who cares about performance + * for the DEFAULT exception handler? + */ + stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */ + + mfcr r31 + stw r31, EXC_CR_OFFSET(r1) + mfctr r30 + stw r30, EXC_CTR_OFFSET(r1) + mfxer r28 + stw r28, EXC_XER_OFFSET(r1) + /* + * compute SP at exception entry + */ + addi r2, r1, EXCEPTION_FRAME_END + /* + * store it at the right place + */ + stw r2, GPR1_OFFSET(r1) + /* + * Enable data and instruction address translation, exception nesting + */ + mfmsr r3 + ori r3,r3, MSR_RI | MSR_IR | MSR_DR + mtmsr r3 + SYNC + + /* + * Call C exception handler + */ + /* + * store the execption frame address in r3 (first param) + */ + addi r3, r1, 0x8 + /* + * globalExceptHdl(r3) + */ + addis r4, 0, globalExceptHdl@ha + lwz r5, globalExceptHdl@l(r4) + mtlr r5 + blrl + /* + * Restore registers status + */ + lwz r31, EXC_CR_OFFSET(r1) + mtcr r31 + lwz r30, EXC_CTR_OFFSET(r1) + mtctr r30 + lwz r29, EXC_LR_OFFSET(r1) + mtlr r29 + lwz r28, EXC_XER_OFFSET(r1) + mtxer r28 + + lmw r4, GPR4_OFFSET(r1) + lwz r2, GPR2_OFFSET(r1) + lwz r0, GPR0_OFFSET(r1) + + /* + * Disable data and instruction translation. Make path non recoverable... + */ + mfmsr r3 + xori r3, r3, MSR_RI | MSR_IR | MSR_DR + mtmsr r3 + SYNC + /* + * Restore rfi related settings + */ + + lwz r3, SRR1_FRAME_OFFSET(r1) + mtsrr1 r3 + lwz r3, SRR0_FRAME_OFFSET(r1) + mtsrr0 r3 + + lwz r3, GPR3_OFFSET(r1) + addi r1,r1, EXCEPTION_FRAME_END + SYNC + rfi diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.h b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.h new file mode 100644 index 0000000000..22b9b27f3a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors.h @@ -0,0 +1,144 @@ +/* + * vectors.h Exception frame related contant and API. + * + * This include file describe the data structure and the functions implemented + * by rtems to handle exceptions. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#ifndef LIBBSP_POWERPC_MBX8XX_VECTORS_H +#define LIBBSP_POWERPC_MBX8xx_VECTORS_H + +/* + * The callee (high level exception code written in C) + * will store the Link Registers (return address) at entry r1 + 4 !!!. + * So let room for it!!!. + */ +#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4 +#define SRR0_FRAME_OFFSET 8 +#define SRR1_FRAME_OFFSET 12 +#define EXCEPTION_NUMBER_OFFSET 16 +#define GPR0_OFFSET 20 +#define GPR1_OFFSET 24 +#define GPR2_OFFSET 28 +#define GPR3_OFFSET 32 +#define GPR4_OFFSET 36 +#define GPR5_OFFSET 40 +#define GPR6_OFFSET 44 +#define GPR7_OFFSET 48 +#define GPR8_OFFSET 52 +#define GPR9_OFFSET 56 +#define GPR10_OFFSET 60 +#define GPR11_OFFSET 64 +#define GPR12_OFFSET 68 +#define GPR13_OFFSET 72 +#define GPR14_OFFSET 76 +#define GPR15_OFFSET 80 +#define GPR16_OFFSET 84 +#define GPR17_OFFSET 88 +#define GPR18_OFFSET 92 +#define GPR19_OFFSET 96 +#define GPR20_OFFSET 100 +#define GPR21_OFFSET 104 +#define GPR22_OFFSET 108 +#define GPR23_OFFSET 112 +#define GPR24_OFFSET 116 +#define GPR25_OFFSET 120 +#define GPR26_OFFSET 124 +#define GPR27_OFFSET 128 +#define GPR28_OFFSET 132 +#define GPR29_OFFSET 136 +#define GPR30_OFFSET 140 +#define GPR31_OFFSET 144 +#define EXC_CR_OFFSET 148 +#define EXC_CTR_OFFSET 152 +#define EXC_XER_OFFSET 156 +#define EXC_LR_OFFSET 160 +#define EXC_DAR_OFFSET 164 +/* + * maintain the EABI requested 8 bytes aligment + * As SVR4 ABI requires 16, make it 16 (as some + * exception may need more registers to be processed...) + */ +#define EXCEPTION_FRAME_END 176 + +#ifndef ASM +/* + * default raw exception handlers + */ + +extern void default_exception_vector_code_prolog(); +extern int default_exception_vector_code_prolog_size; + +/* codemove is like memmove, but it also gets the cache line size + * as 4th parameter to synchronize them. If this last parameter is + * zero, it performs more or less like memmove. No copy is performed if + * source and destination addresses are equal. However the caches + * are synchronized. Note that the size is always rounded up to the + * next mutiple of 4. + */ +extern void * codemove(void *, const void *, unsigned int, unsigned long); +extern void initialize_exceptions(); + +typedef struct { + unsigned EXC_SRR0; + unsigned EXC_SRR1; + unsigned _EXC_number; + unsigned GPR0; + unsigned GPR1; + unsigned GPR2; + unsigned GPR3; + unsigned GPR4; + unsigned GPR5; + unsigned GPR6; + unsigned GPR7; + unsigned GPR8; + unsigned GPR9; + unsigned GPR10; + unsigned GPR11; + unsigned GPR12; + unsigned GPR13; + unsigned GPR14; + unsigned GPR15; + unsigned GPR16; + unsigned GPR17; + unsigned GPR18; + unsigned GPR19; + unsigned GPR20; + unsigned GPR21; + unsigned GPR22; + unsigned GPR23; + unsigned GPR24; + unsigned GPR25; + unsigned GPR26; + unsigned GPR27; + unsigned GPR28; + unsigned GPR29; + unsigned GPR30; + unsigned GPR31; + unsigned EXC_CR; + unsigned EXC_CTR; + unsigned EXC_XER; + unsigned EXC_LR; + unsigned EXC_MSR; + unsigned EXC_DAR; +}BSP_Exception_frame; + + +typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr); +extern exception_handler_t globalExceptHdl; +/* + * Compatibility with pc386 + */ +typedef BSP_Exception_frame CPU_Exception_frame; +typedef exception_handler_t cpuExcHandlerType; + +#endif /* ASM */ + +#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */ diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors_init.c b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors_init.c new file mode 100644 index 0000000000..864aac71a4 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mbx8xx/vectors/vectors_init.c @@ -0,0 +1,134 @@ +/* + * vectors_init.c Exception hanlding initialisation (and generic handler). + * + * This include file describe the data structure and the functions implemented + * by rtems to handle exceptions. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * $Id$ + */ +#include +#include +#include + +static rtems_raw_except_global_settings exception_config; +static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1]; + +exception_handler_t globalExceptHdl; + +void C_exception_handler(BSP_Exception_frame* excPtr) +{ + int recoverable = 0; + + printk("exception handler called for exception %d\n", excPtr->_EXC_number); + printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0); + printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1); + printk("\t R0 = %x\n", excPtr->GPR0); + printk("\t R1 = %x\n", excPtr->GPR1); + printk("\t R2 = %x\n", excPtr->GPR2); + printk("\t R3 = %x\n", excPtr->GPR3); + printk("\t R4 = %x\n", excPtr->GPR4); + printk("\t R5 = %x\n", excPtr->GPR5); + printk("\t R6 = %x\n", excPtr->GPR6); + printk("\t R7 = %x\n", excPtr->GPR7); + printk("\t R8 = %x\n", excPtr->GPR8); + printk("\t R9 = %x\n", excPtr->GPR9); + printk("\t R10 = %x\n", excPtr->GPR10); + printk("\t R11 = %x\n", excPtr->GPR11); + printk("\t R12 = %x\n", excPtr->GPR12); + printk("\t R13 = %x\n", excPtr->GPR13); + printk("\t R14 = %x\n", excPtr->GPR14); + printk("\t R15 = %x\n", excPtr->GPR15); + printk("\t R16 = %x\n", excPtr->GPR16); + printk("\t R17 = %x\n", excPtr->GPR17); + printk("\t R18 = %x\n", excPtr->GPR18); + printk("\t R19 = %x\n", excPtr->GPR19); + printk("\t R20 = %x\n", excPtr->GPR20); + printk("\t R21 = %x\n", excPtr->GPR21); + printk("\t R22 = %x\n", excPtr->GPR22); + printk("\t R23 = %x\n", excPtr->GPR23); + printk("\t R24 = %x\n", excPtr->GPR24); + printk("\t R25 = %x\n", excPtr->GPR25); + printk("\t R26 = %x\n", excPtr->GPR26); + printk("\t R27 = %x\n", excPtr->GPR27); + printk("\t R28 = %x\n", excPtr->GPR28); + printk("\t R29 = %x\n", excPtr->GPR29); + printk("\t R30 = %x\n", excPtr->GPR30); + printk("\t R31 = %x\n", excPtr->GPR31); + printk("\t CR = %x\n", excPtr->EXC_CR); + printk("\t CTR = %x\n", excPtr->EXC_CTR); + printk("\t XER = %x\n", excPtr->EXC_XER); + printk("\t LR = %x\n", excPtr->EXC_LR); + printk("\t MSR = %x\n", excPtr->EXC_MSR); + if (excPtr->_EXC_number == ASM_DEC_VECTOR) + recoverable = 1; + if (excPtr->_EXC_number == ASM_SYS_VECTOR) +#ifdef TEST_RAW_EXCEPTION_CODE + recoverable = 1; +#else + recoverable = 0; +#endif + if (!recoverable) { + printk("unrecoverable exception!!! Push reset button\n"); + while(1); + } +} + +void nop_except_enable(const rtems_raw_except_connect_data* ptr) +{ +} +int except_always_enabled(const rtems_raw_except_connect_data* ptr) +{ + return 1; +} + +void initialize_exceptions() +{ + int i; + + /* + * Initialize pointer used by low level execption handling + */ + globalExceptHdl = C_exception_handler; + /* + * Put default_exception_vector_code_prolog at relevant exception + * code entry addresses + */ + exception_config.exceptSize = LAST_VALID_EXC + 1; + exception_config.rawExceptHdlTbl = &exception_table[0]; + exception_config.defaultRawEntry.exceptIndex = 0; + exception_config.defaultRawEntry.hdl.vector = 0; + exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog; + /* + * Note that next line the '&' before default_exception_vector_code_prolog_size + * is not a bug as it is defined a .set directly in asm... + */ + exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) &default_exception_vector_code_prolog_size; + for (i=0; i <= exception_config.exceptSize; i++) { + printk("installing exception number %d\n", i); + if (!mpc8xx_vector_is_valid (i)) { + continue; + } + exception_table[i].exceptIndex = i; + exception_table[i].hdl = exception_config.defaultRawEntry.hdl; + exception_table[i].hdl.vector = i; + exception_table[i].on = nop_except_enable; + exception_table[i].off = nop_except_enable; + exception_table[i].isOn = except_always_enabled; + } + if (!mpc8xx_init_exceptions(&exception_config)) { + /* + * At this stage we may not call BSP_Panic because it uses exceptions!!! + */ + printk("Exception handling initialization failed\n"); + printk("System locked\n"); while(1); + } + else { + printk("Exception handling initialization done\n"); + } +} diff --git a/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am b/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am index f8dc756f75..a79f007f62 100644 --- a/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mbx8xx/wrapup/Makefile.am @@ -9,7 +9,7 @@ if HAS_NETWORKING NETWORKING = network endif -BSP_PIECES = startup console $(NETWORKING) +BSP_PIECES = clock irq startup console vectors $(NETWORKING) # pieces to pick up out of libcpu/ppc # CPU_PIECES = mpc8xx/clock mpc8xx/console-generic mpc8xx/cpm \ # mpc8xx/mmu mpc8xx/timer mpc8xx/vectors @@ -17,7 +17,7 @@ BSP_PIECES = startup console $(NETWORKING) # bummer; have to use $foreach since % pattern subst rules only replace 1x OBJS = $(foreach piece, $(BSP_PIECES), $(wildcard ../$(piece)/$(ARCH)/*.o)) \ $(wildcard ../../../../libcpu/$(RTEMS_CPU)/shared/*/$(ARCH)/*.o) \ - $(wildcard ../../../../libcpu/powerpc/old_exception_processing/$(ARCH)/*.rel) \ + $(wildcard ../../../../libcpu/powerpc/new_exception_processing/$(ARCH)/*.rel) \ $(wildcard ../../../../libcpu/$(RTEMS_CPU)/mpc8xx/*/$(ARCH)/*.o) LIB = $(ARCH)/libbsp.a -- cgit v1.2.3