From a36d1b435808d6daef1a9641c8ab707e5feeb7c8 Mon Sep 17 00:00:00 2001 From: Jennifer Averett Date: Wed, 4 Apr 2012 12:21:15 -0500 Subject: Add MIPS/Malta BSP. --- c/src/lib/libbsp/mips/acinclude.m4 | 2 + c/src/lib/libbsp/mips/malta/ChangeLog | 23 + c/src/lib/libbsp/mips/malta/Makefile.am | 91 ++ c/src/lib/libbsp/mips/malta/STATUS | 46 + c/src/lib/libbsp/mips/malta/bsp_specs | 13 + c/src/lib/libbsp/mips/malta/configure.ac | 21 + c/src/lib/libbsp/mips/malta/console/conscfg.c | 158 +++ .../lib/libbsp/mips/malta/console/printk_support.c | 53 + c/src/lib/libbsp/mips/malta/include/bsp.h | 108 ++ c/src/lib/libbsp/mips/malta/include/irq.h | 131 +++ c/src/lib/libbsp/mips/malta/include/pci.h | 171 +++ c/src/lib/libbsp/mips/malta/irq/interruptmask.c | 36 + c/src/lib/libbsp/mips/malta/irq/maxvectors.c | 24 + c/src/lib/libbsp/mips/malta/irq/vectorisrs.c | 90 ++ c/src/lib/libbsp/mips/malta/make/custom/malta.cfg | 15 + c/src/lib/libbsp/mips/malta/pci/pci.c | 1105 ++++++++++++++++++++ c/src/lib/libbsp/mips/malta/pci/pcifinddevice.c | 279 +++++ c/src/lib/libbsp/mips/malta/pci/pcilistdevices.c | 105 ++ c/src/lib/libbsp/mips/malta/preinstall.am | 91 ++ c/src/lib/libbsp/mips/malta/start/start.S | 220 ++++ c/src/lib/libbsp/mips/malta/startup/bspreset.c | 35 + c/src/lib/libbsp/mips/malta/startup/bspstart.c | 113 ++ c/src/lib/libbsp/mips/malta/startup/inittlb.c | 26 + c/src/lib/libbsp/mips/malta/startup/linkcmds | 181 ++++ .../lib/libbsp/mips/malta/startup/simple_access.c | 133 +++ 25 files changed, 3270 insertions(+) create mode 100644 c/src/lib/libbsp/mips/malta/ChangeLog create mode 100644 c/src/lib/libbsp/mips/malta/Makefile.am create mode 100644 c/src/lib/libbsp/mips/malta/STATUS create mode 100644 c/src/lib/libbsp/mips/malta/bsp_specs create mode 100644 c/src/lib/libbsp/mips/malta/configure.ac create mode 100644 c/src/lib/libbsp/mips/malta/console/conscfg.c create mode 100644 c/src/lib/libbsp/mips/malta/console/printk_support.c create mode 100644 c/src/lib/libbsp/mips/malta/include/bsp.h create mode 100644 c/src/lib/libbsp/mips/malta/include/irq.h create mode 100644 c/src/lib/libbsp/mips/malta/include/pci.h create mode 100644 c/src/lib/libbsp/mips/malta/irq/interruptmask.c create mode 100644 c/src/lib/libbsp/mips/malta/irq/maxvectors.c create mode 100644 c/src/lib/libbsp/mips/malta/irq/vectorisrs.c create mode 100644 c/src/lib/libbsp/mips/malta/make/custom/malta.cfg create mode 100644 c/src/lib/libbsp/mips/malta/pci/pci.c create mode 100644 c/src/lib/libbsp/mips/malta/pci/pcifinddevice.c create mode 100644 c/src/lib/libbsp/mips/malta/pci/pcilistdevices.c create mode 100644 c/src/lib/libbsp/mips/malta/preinstall.am create mode 100644 c/src/lib/libbsp/mips/malta/start/start.S create mode 100644 c/src/lib/libbsp/mips/malta/startup/bspreset.c create mode 100644 c/src/lib/libbsp/mips/malta/startup/bspstart.c create mode 100644 c/src/lib/libbsp/mips/malta/startup/inittlb.c create mode 100644 c/src/lib/libbsp/mips/malta/startup/linkcmds create mode 100644 c/src/lib/libbsp/mips/malta/startup/simple_access.c diff --git a/c/src/lib/libbsp/mips/acinclude.m4 b/c/src/lib/libbsp/mips/acinclude.m4 index 47304431b4..6a7814fc76 100644 --- a/c/src/lib/libbsp/mips/acinclude.m4 +++ b/c/src/lib/libbsp/mips/acinclude.m4 @@ -10,6 +10,8 @@ AC_DEFUN([RTEMS_CHECK_BSPDIR], AC_CONFIG_SUBDIRS([hurricane]);; jmr3904 ) AC_CONFIG_SUBDIRS([jmr3904]);; + malta ) + AC_CONFIG_SUBDIRS([malta]);; rbtx4925 ) AC_CONFIG_SUBDIRS([rbtx4925]);; rbtx4938 ) diff --git a/c/src/lib/libbsp/mips/malta/ChangeLog b/c/src/lib/libbsp/mips/malta/ChangeLog new file mode 100644 index 0000000000..ec3614a52f --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/ChangeLog @@ -0,0 +1,23 @@ +2012-03-08 Jennifer Averett + + * include/bsp.h: Added define for BSP_SHARED_HANDLER_SUPPORT. + +2012-03-06 Jennifer Averett + + PR 1993/bsps + * malta/include/bsp.h: + Changed interrupt call, removed warnings and did cleanup. + +2012-02-27 Jennifer Averett + + * MIPS malta initial BSP. This version was tested using + the qemu simulator and may require modifications to work with + actual hardware. + * ChangeLog, Makefile.am, STATUS, bsp_specs, configure.ac, + console/conscfg.c, console/printk_support.c, include/bsp.h, + include/irq.h, include/pci.h, irq/interruptmask.c, + irq/maxvectors.c, irq/vectorisrs.c, make/custom/malta.cfg, + pci/pci.c, pci/pcifinddevice.c, pci/pcilistdevices.c, + preinstall.am, start/start.S, startup/bspreset.c, + startup/bspstart.c, startup/inittlb.c, startup/linkcmds, + startup/simple_access.c: New files. diff --git a/c/src/lib/libbsp/mips/malta/Makefile.am b/c/src/lib/libbsp/mips/malta/Makefile.am new file mode 100644 index 0000000000..0c5da15e71 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/Makefile.am @@ -0,0 +1,91 @@ +## +## + +ACLOCAL_AMFLAGS = -I ../../../../aclocal + +include $(top_srcdir)/../../../../automake/compile.am + +include_bspdir = $(includedir)/bsp + +dist_project_lib_DATA = bsp_specs + +include_HEADERS = include/bsp.h +include_HEADERS += ../../shared/include/tm27.h +include_bsp_HEADERS = ../shared/liblnk/regs.h +#isr +include_bsp_HEADERS += ../../shared/include/irq-generic.h +include_bsp_HEADERS += ../../shared/include/irq-info.h +include_bsp_HEADERS += include/irq.h +#pci +include_bsp_HEADERS += include/pci.h +#irq +include_bsp_HEADERS += ../shared/irq/i8259.h +nodist_include_HEADERS = include/bspopts.h +nodist_include_bsp_HEADERS = ../../shared/include/bootcard.h +DISTCLEANFILES = include/bspopts.h + +nodist_include_HEADERS += ../../shared/include/coverhd.h + +noinst_LIBRARIES = libbspstart.a +libbspstart_a_SOURCES = start/start.S ../shared/liblnk/regs.h +project_lib_DATA = start.$(OBJEXT) + +dist_project_lib_DATA += startup/linkcmds + +noinst_LIBRARIES += libbsp.a +libbsp_a_SOURCES = + +# startup +libbsp_a_SOURCES += startup/simple_access.c +libbsp_a_SOURCES += ../../shared/bspclean.c +libbsp_a_SOURCES += ../../shared/bsplibc.c +libbsp_a_SOURCES += ../../shared/bsppredriverhook.c +libbsp_a_SOURCES += ../../shared/bsppost.c +libbsp_a_SOURCES += ../../shared/bsppretaskinghook.c +libbsp_a_SOURCES += ../../shared/bspgetworkarea.c +libbsp_a_SOURCES += startup/bspstart.c +libbsp_a_SOURCES += startup/bspreset.c +libbsp_a_SOURCES += ../../shared/bootcard.c +libbsp_a_SOURCES += ../../shared/sbrk.c +libbsp_a_SOURCES += startup/inittlb.c +libbsp_a_SOURCES += ../shared/startup/idttlb.S + +# clock +libbsp_a_SOURCES += ../shared/clock/clockdrv.c +libbsp_a_SOURCES += ../shared/clock/mips_timer.S +libbsp_a_SOURCES += ../../shared/clockdrv_shell.h + +# console +libbsp_a_SOURCES += console/conscfg.c +libbsp_a_SOURCES += console/printk_support.c +libbsp_a_SOURCES += ../../shared/console.c +libbsp_a_SOURCES += ../../shared/console_select.c +libbsp_a_SOURCES += ../../shared/console_read.c +libbsp_a_SOURCES += ../../shared/console_write.c +libbsp_a_SOURCES += ../../shared/console_control.c +# timer +libbsp_a_SOURCES += ../../shared/timerstub.c + +libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/cache.rel +libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/shared/interrupts.rel + +# pci +libbsp_a_SOURCES += pci/pci.c +libbsp_a_SOURCES += pci/pcifinddevice.c +libbsp_a_SOURCES += pci/pcilistdevices.c + +#isr +libbsp_a_SOURCES += ../../shared/src/irq-generic.c +libbsp_a_SOURCES += ../../shared/src/irq-legacy.c +libbsp_a_SOURCES += ../../shared/src/irq-info.c +libbsp_a_SOURCES += ../../shared/src/irq-shell.c +libbsp_a_SOURCES += ../../shared/src/irq-server.c +libbsp_a_SOURCES += ../shared/irq/vectorexceptions.c +libbsp_a_SOURCES += ../shared/irq/irq.c +libbsp_a_SOURCES += irq/maxvectors.c +libbsp_a_SOURCES += irq/vectorisrs.c +libbsp_a_SOURCES += irq/interruptmask.c +libbsp_a_SOURCES += ../shared/irq/i8259.c + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/mips/malta/STATUS b/c/src/lib/libbsp/mips/malta/STATUS new file mode 100644 index 0000000000..494709c055 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/STATUS @@ -0,0 +1,46 @@ +# +# $Id: STATUS,v 1.3 2012/02/17 19:41:51 joel Exp $ +# + +17 Februrary 2011 + +XXX + +This is a BSP for the MIPS Malta board with a 24K CPU on it. +It has ONLY been tested on Qemu. + +Anything not mentioned has not been touched at all and will +most likely not be in the first release of the BSP. + +Working +======= ++ Board initialization and shutdown ++ tty0 working polled ++ tty1 working polled (see note in issues) ++ tty2 working polled (see notes in issues) ++ Clock Tick + + +Issues +====== ++ We have small hack to Qemu so reset will exit. This needs to be + fixed to follow the PC386 Qemu model where a command line argument + selects reset or exit on reset. + ++ tty2 is generating an interrupt which causes a TLB fault. We have + disabled the interrupt in the CPU interrupt mask for now. + ++ tty1 and tty2 are not showing any data on the screen. This is + most likely an issue with qemu since the status bit is changing + as the characters are polled out. + +TBD +=== ++ Conversion to Programmable Interrupt Controller IRQ model + using shared infrastructure ++ tty0 working interrupt driver ++ tty1 working interrupt driver ++ tty2 working interrupt driver ++ PCI Bus Support ++ AMD AM79C973 NIC ++ Consider moving mips_interrupt_mask() into BSP. diff --git a/c/src/lib/libbsp/mips/malta/bsp_specs b/c/src/lib/libbsp/mips/malta/bsp_specs new file mode 100644 index 0000000000..c3224e2f58 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/bsp_specs @@ -0,0 +1,13 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: start.o%s crti.o%s crtbegin.o%s -e _start}} + +*link: +%(old_link) %{qrtems: -dc -dp -N} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s crtn.o%s} diff --git a/c/src/lib/libbsp/mips/malta/configure.ac b/c/src/lib/libbsp/mips/malta/configure.ac new file mode 100644 index 0000000000..b6f5a18481 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/configure.ac @@ -0,0 +1,21 @@ +## Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.68]) +AC_INIT([rtems-c-src-lib-libbsp-mips-malta],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla]) +AC_CONFIG_SRCDIR([bsp_specs]) +RTEMS_TOP(../../../../../..) + +RTEMS_CANONICAL_TARGET_CPU +AM_INIT_AUTOMAKE([no-define nostdinc foreign 1.11.1]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_BSPOPTS_SET([BSP_RESET_BOARD_AT_EXIT],[*],[1]) +RTEMS_BSP_CLEANUP_OPTIONS(0, 1) + +# Explicitly list all Makefiles here +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/c/src/lib/libbsp/mips/malta/console/conscfg.c b/c/src/lib/libbsp/mips/malta/console/conscfg.c new file mode 100644 index 0000000000..47535e8f0a --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/console/conscfg.c @@ -0,0 +1,158 @@ +/** + * @file + * + * This file contains the libchip configuration information + * to instantiate the libchip driver for the serial ports. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include /* write */ + +#include +#include +#include +#include +#include + +#if 1 +#define COM_CONSOLE_FUNCTIONS &ns16550_fns_polled +#else +#define COM_CONSOLE_FUNCTIONS &ns16550_fns +#endif + +/* + * Base IO for UART + */ +#define COM1_BASE_IO 0x3F8 +#define COM2_BASE_IO 0x3E8 + +// #define CLOCK_RATE 368640 +#define CLOCK_RATE (115200 * 16) + +#define COM_IO_BASE_ADDRESS (0xa0000000UL | 0x18000000UL) + +uint8_t com_get_register(uint32_t addr, uint8_t i); +void com_set_register(uint32_t addr, uint8_t i, uint8_t val); +uint8_t tty2_get_register(uint32_t addr, uint8_t i); +void tty2_set_register(uint32_t addr, uint8_t i, uint8_t val); + + +uint8_t com_get_register(uint32_t addr, uint8_t i) +{ + uint8_t val; + volatile uint8_t *ptr; + ptr = (volatile uint8_t *) COM_IO_BASE_ADDRESS; + ptr += addr; + ptr += i; + val = *ptr; + + return val; +} + +void com_set_register(uint32_t addr, uint8_t i, uint8_t val) +{ + volatile uint8_t *ptr; + + ptr = (volatile uint8_t *) COM_IO_BASE_ADDRESS; + ptr += addr; + ptr += i; + *ptr = val; +} + +uint8_t tty2_get_register(uint32_t addr, uint8_t i) +{ + uint8_t val; + volatile uint8_t *ptr; + + ptr = (volatile uint8_t *) COM_IO_BASE_ADDRESS; + ptr += addr; + ptr += (i * 8); + val = *ptr; + + return val; +} + +void tty2_set_register(uint32_t addr, uint8_t i, uint8_t val) +{ + volatile uint8_t *ptr; + + ptr = (volatile uint8_t *) COM_IO_BASE_ADDRESS; + ptr += addr; + ptr += (i * 8); + *ptr = val; +} + +console_tbl Console_Configuration_Ports[] = { + { + "/dev/tty0", /* sDeviceName */ + SERIAL_NS16550, /* deviceType */ + COM_CONSOLE_FUNCTIONS, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) 9600, /* Baud Rate */ /* pDeviceParams */ + COM1_BASE_IO, /* ulCtrlPort1 */ + 0x00000000, /* ulCtrlPort2 */ + COM1_BASE_IO, /* ulDataPort */ + com_get_register, /* getRegister */ + com_set_register, /* setRegister */ + NULL,/* unused */ /* getData */ + NULL,/* unused */ /* setData */ + CLOCK_RATE, /* ulClock */ + MALTA_IRQ_TTY0 /* ulIntVector -- base for port */ + }, + { + "/dev/tty1", /* sDeviceName */ + SERIAL_NS16550, /* deviceType */ + COM_CONSOLE_FUNCTIONS, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) 9600, /* Baud Rate */ /* pDeviceParams */ + COM2_BASE_IO, /* ulCtrlPort1 */ + 0x00000000, /* ulCtrlPort2 */ + COM2_BASE_IO, /* ulDataPort */ + com_get_register, /* getRegister */ + com_set_register, /* setRegister */ + NULL,/* unused */ /* getData */ + NULL,/* unused */ /* setData */ + CLOCK_RATE, /* ulClock */ + MALTA_IRQ_TTY1 /* ulIntVector -- base for port */ + }, + { + "/dev/tty2", /* sDeviceName */ + SERIAL_NS16550, /* deviceType */ + COM_CONSOLE_FUNCTIONS, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) 9600, /* Baud Rate */ /* pDeviceParams */ + 0, /* IGNORED */ /* ulCtrlPort1 */ + 0, /* IGNORED */ /* ulCtrlPort2 */ + 0, /* IGNORED */ /* ulDataPort */ + tty2_get_register, /* getRegister */ + tty2_set_register, /* setRegister */ + NULL,/* unused */ /* getData */ + NULL,/* unused */ /* setData */ + CLOCK_RATE, /* ulClock */ + MALTA_CPU_INT2 /* ulIntVector -- base for port */ + }, +}; + +/* + * Define a variable that contains the number of statically configured + * console devices. + */ +unsigned long Console_Configuration_Count = \ + (sizeof(Console_Configuration_Ports)/sizeof(console_tbl)); diff --git a/c/src/lib/libbsp/mips/malta/console/printk_support.c b/c/src/lib/libbsp/mips/malta/console/printk_support.c new file mode 100644 index 0000000000..1383448c6b --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/console/printk_support.c @@ -0,0 +1,53 @@ +/** + * @file + * + * This file contains a stub for the required printk support. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include +#include + +rtems_device_minor_number BSPPrintkPort = 0; + +void BSP_com_outch(char ch); +int BSP_com_inch( void ); + +/* + * Following assume all are ns16650 + */ +void BSP_com_outch(char ch) +{ + console_tbl *cptr; + + cptr = &Console_Configuration_Ports[BSPPrintkPort]; + + return ns16550_outch_polled( cptr, ch ); +} + +int BSP_com_inch( void ) +{ + int result; + console_tbl *cptr; + + cptr = &Console_Configuration_Ports[BSPPrintkPort]; + + do { + result = ns16550_inch_polled( cptr ); + } while (result == -1); + + return result; +} + +BSP_output_char_function_type BSP_output_char = BSP_com_outch; +BSP_polling_getchar_function_type BSP_poll_char = BSP_com_inch; diff --git a/c/src/lib/libbsp/mips/malta/include/bsp.h b/c/src/lib/libbsp/mips/malta/include/bsp.h new file mode 100644 index 0000000000..b05b2c4a10 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/include/bsp.h @@ -0,0 +1,108 @@ +/** + * @file + * + * This include file contains some definitions specific to the + * MIPS Malta Board. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef _BSP_H +#define _BSP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include +#include +#include +#include + +#define BSP_FEATURE_IRQ_EXTENSION +#define BSP_SHARED_HANDLER_SUPPORT 1 + +#define REVISION_REGISTER_ADDRESS 0x1fc00010 +#define PRORV_MASK 0x0000000f /* 4 bit Product Revision */ +#define PROID_MASK 0x000000f0 /* 4 bit Product ID */ +#define CORRV_MASK 0x00000300 /* 2 bit Core Board Revision */ +#define CORID_MASK 0x0000fc00 /* 6 bit Core Board ID */ +#define FPGRV_MASK 0x00ff0000 /* 8 bit CBUS FPGA Revision */ +#define BSP_8259_BASE_ADDRESS (0x18000000UL | 0xa0000000UL) +#define BSP_PCI_BASE_ADDRESS (0x1be00000UL | 0xa0000000UL) +#define BSP_NIC_IO_BASE (0x10000000UL | 0xa0000000UL) +#define PCI0_IO_BASE (0x18000000UL | 0xa0000000UL) +#define BSP_NIC_MEM_BASE (0x00000000UL | 0xa0000000UL) + +/* functions */ +#define WRITE_PROTECTED_UINT8( _addr, _value ) \ + do { \ + volatile uint8_t *_ptr = _addr | 0x80000000; \ + *_ptr = _value; \ + } +#define WRITE_PROTECTED_UINT16( _addr, _value ) \ + do { \ + volatile uint16_t *_ptr = _addr | 0x80000000; \ + *_ptr = _value; \ + } +#define WRITE_PROTECTED_UINT32( _addr, _value ) \ + do { \ + volatile uint32_t *_ptr = _addr | 0x80000000; \ + *_ptr = _value; \ + } +#define READ_PROTECTED_UINT8( _addr, _value ) \ + do { \ + volatile uint8_t *_ptr = _addr | 0x80000000; \ + _value = *_ptr; \ + } +#define READ_PROTECTED_UINT16( _addr, _value ) \ + do { \ + volatile uint16_t *_ptr = _addr | 0x80000000; \ + _value = *_ptr; \ + } +#define READ_PROTECTED_UINT32( _addr, _value ) \ + do { \ + volatile uint32_t *_ptr = _addr | 0x80000000; \ + _value = *_ptr; \ + } + +#define READ_UINT8( _register_, _value_ ) \ + ((_value_) = *((volatile unsigned char *)(_register_))) + +#define WRITE_UINT8( _register_, _value_ ) \ + (*((volatile unsigned char *)(_register_)) = (_value_)) + +#define READ_UINT16( _register_, _value_ ) \ + ((_value_) = *((volatile unsigned short *)(_register_))) + +#define WRITE_UINT16( _register_, _value_ ) \ + (*((volatile unsigned short *)(_register_)) = (_value_)) + +void simple_out_32(uint32_t base, uint32_t addr, uint32_t val); +void simple_out_le32(uint32_t base, uint32_t addr, uint32_t val); +uint8_t simple_in_8( uint32_t base, uint32_t addr ); +void simple_out_8( uint32_t base, uint32_t addr, uint8_t val ); +int16_t simple_in_le16( uint32_t base, uint32_t addr ); +int16_t simple_in_16( uint32_t base, uint32_t addr ); +uint32_t simple_in_le32( uint32_t base, uint32_t addr ); +uint32_t simple_in_32( uint32_t base, uint32_t addr ); +void simple_out_le16( uint32_t base, uint32_t addr, uint16_t val ); +void simple_out_16( uint32_t base, uint32_t addr, uint16_t val ); + +rtems_isr_entry set_vector( + rtems_isr_entry, rtems_vector_number, int ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/src/lib/libbsp/mips/malta/include/irq.h b/c/src/lib/libbsp/mips/malta/include/irq.h new file mode 100644 index 0000000000..996d98678b --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/include/irq.h @@ -0,0 +1,131 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief Malta Interrupt Definitions + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#ifndef LIBBSP_MIPS_MALTA_IRQ_H +#define LIBBSP_MIPS_MALTA_IRQ_H + +#ifndef ASM + #include + #include + #include + #include +#endif + +/** + * @addtogroup bsp_interrupt + * + * @{ + */ + +#define BSP_INTERRUPT_VECTOR_MIN 0 + +/* + * Interrupt Vector Numbers + * + * NOTE: Numbers 0-15 directly map to levels on the IRC. + * Number 16 is "1xxxx" per p. 164 of the TX3904 manual. + */ +#define MALTA_CPU_INT_START MIPS_INTERRUPT_BASE+0 +#define MALTA_CPU_INT_SW0 MALTA_CPU_INT_START+0 +#define MALTA_CPU_INT_SW2 MALTA_CPU_INT_START+1 +#define MALTA_CPU_INT0 MALTA_CPU_INT_START+2 +#define MALTA_CPU_INT1 MALTA_CPU_INT_START+3 +#define MALTA_CPU_INT2 MALTA_CPU_INT_START+4 +#define MALTA_CPU_INT3 MALTA_CPU_INT_START+5 +#define MALTA_CPU_INT4 MALTA_CPU_INT_START+6 +#define MALTA_CPU_INT5 MALTA_CPU_INT_START+7 +#define MALTA_CPU_INT_LAST MALTA_CPU_INT5 + +#define MALTA_SB_IRQ_START MALTA_CPU_INT_LAST+1 +#define MALTA_SB_IRQ_0 MALTA_SB_IRQ_START+0 +#define MALTA_SB_IRQ_1 MALTA_SB_IRQ_START+1 +#define MALTA_SB_IRQ_2 MALTA_SB_IRQ_START+2 +#define MALTA_SB_IRQ_3 MALTA_SB_IRQ_START+3 +#define MALTA_SB_IRQ_4 MALTA_SB_IRQ_START+4 +#define MALTA_SB_IRQ_5 MALTA_SB_IRQ_START+5 +#define MALTA_SB_IRQ_6 MALTA_SB_IRQ_START+6 +#define MALTA_SB_IRQ_7 MALTA_SB_IRQ_START+7 +#define MALTA_SB_IRQ_8 MALTA_SB_IRQ_START+8 +#define MALTA_SB_IRQ_9 MALTA_SB_IRQ_START+9 +#define MALTA_SB_IRQ_10 MALTA_SB_IRQ_START+10 +#define MALTA_SB_IRQ_11 MALTA_SB_IRQ_START+11 +#define MALTA_SB_IRQ_12 MALTA_SB_IRQ_START+12 +#define MALTA_SB_IRQ_13 MALTA_SB_IRQ_START+13 +#define MALTA_SB_IRQ_14 MALTA_SB_IRQ_START+14 +#define MALTA_SB_IRQ_15 MALTA_SB_IRQ_START+15 +#define MALTA_SB_IRQ_LAST MALTA_SB_IRQ_15 + +#define MALTA_PCI_ADP_START MALTA_SB_IRQ_LAST+1 +#define MALTA_PCI_ADP20 MALTA_PCI_ADP_START+0 +#define MALTA_PCI_ADP21 MALTA_PCI_ADP_START+1 +#define MALTA_PCI_ADP22 MALTA_PCI_ADP_START+2 +#define MALTA_PCI_ADP27 MALTA_PCI_ADP_START+3 +#define MALTA_PCI_ADP28 MALTA_PCI_ADP_START+4 +#define MALTA_PCI_ADP29 MALTA_PCI_ADP_START+5 +#define MALTA_PCI_ADP30 MALTA_PCI_ADP_START+6 +#define MALTA_PCI_ADP31 MALTA_PCI_ADP_START+7 +#define MALTA_PCI_ADP_LAST MALTA_PCI_ADP31 +# + +#define BSP_INTERRUPT_VECTOR_MAX MALTA_PCI_ADP_LAST + +/* + * Redefine interrupts with more descriptive names. + * The Generic ones above match the hardware name, + * where these match the device name. + */ +#define MALTA_INT_SOUTHBRIDGE_INTR MALTA_CPU_INT0 +#define MALTA_INT_SOUTHBRIDGE_SMI MALTA_CPU_INT1 +#define MALTA_INT_TTY2 MALTA_CPU_INT2 +#define MALTA_INT_COREHI MALTA_CPU_INT3 +#define MALTA_INT_CORELO MALTA_CPU_INT4 +#define MALTA_INT_TICKER MALTA_CPU_INT5 + +#define MALTA_IRQ_TIMER_SOUTH_BRIDGE MALTA_SB_IRQ_0 +#define MALTA_IRQ_KEYBOARD_SUPERIO MALTA_SB_IRQ_1 +#define MALTA_IRQ_RESERVED1_SOUTH_BRIDGE MALTA_SB_IRQ_2 +#define MALTA_IRQ_TTY1 MALTA_SB_IRQ_3 +#define MALTA_IRQ_TTY0 MALTA_SB_IRQ_4 +#define MALTA_IRQ_NOT_USED MALTA_SB_IRQ_5 +#define MALTA_IRQ_FLOPPY_SUPERIO MALTA_SB_IRQ_6 +#define MALTA_IRQ_PARALLEL_PORT_SUPERIO MALTA_SB_IRQ_7 +#define MALTA_IRQ_REALTIME_CLOCK_SOUTH_BRIDGE MALTA_SB_IRQ_8 +#define MALTA_IRQ_I2C_SOUTH_BRIDGE MALTA_SB_IRQ_9 +/* PCI A, PCI B (including Ethernet) PCI slot 1..4, Ethernet */ +#define MALTA_IRQ_PCI_A_B MALTA_SB_IRQ_10 +/* PCI slot 1..4 (audio, USB) */ +#define MALTA_IRQ_PCI_C_D MALTA_SB_IRQ_11 +#define MALTA_IRQ_MOUSE_SUPERIO MALTA_SB_IRQ_12 +#define MALTA_IRQ_RESERVED2_SOUTH_BRIDGE MALTA_SB_IRQ_13 +#define MALTA_IRQ_PRIMARY_IDE MALTA_SB_IRQ_14 +#define MALTA_IRQ_SECONDARY_IDE MALTA_SB_IRQ_15 +#define MALTA_IRQ_SOUTH_BRIDGE MALTA_PCI_ADP20 +#define MALTA_IRQ_ETHERNET MALTA_IRQ_PCI_A_B +#define MALTA_IRQ_AUDIO MALTA_PCI_ADP22 +#define MALTA_IRQ_CORE_CARD MALTA_PCI_ADP27 +#define MALTA_IRQ_PCI_CONNECTOR_1 MALTA_PCI_ADP28 +#define MALTA_IRQ_PCI_CONNECTOR_2 MALTA_PCI_ADP29 +#define MALTA_IRQ_PCI_CONNECTOR_3 MALTA_PCI_ADP30 +#define MALTA_IRQ_PCI_CONNECTOR_4 MALTA_PCI_ADP31 + +#ifndef ASM + +#endif /* ASM */ + +/** @} */ + +#endif /* LIBBSP_MIPS_MALTA_IRQ_H */ diff --git a/c/src/lib/libbsp/mips/malta/include/pci.h b/c/src/lib/libbsp/mips/malta/include/pci.h new file mode 100644 index 0000000000..b5c0e60ae4 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/include/pci.h @@ -0,0 +1,171 @@ +/** + * @file + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* + * + * PCI defines and function prototypes + * Copyright 1994, Drew Eckhardt + * Copyright 1997, 1998 Martin Mares + * + * For more information, please consult the following manuals (look at + * http://www.pcisig.com/ for how to get them): + * + * PCI BIOS Specification + * PCI Local Bus Specification + * PCI to PCI Bridge Specification + * PCI System Design Guide + */ + +#ifndef BSP_PCI_H +#define BSP_PCI_H + +#include +#include +#include + +struct _pin_routes +{ + int pin, int_name[4]; +}; +struct _int_map +{ + int bus, slot, opts; + struct _pin_routes pin_route[5]; +}; +struct pcibridge +{ + int bus; + int slot; +}; + +/* If there's a conflict between a name in the routing table and + * what's already set on the device, reprogram the device setting + * to reflect int_name[0] for the routing table entry + */ +#define PCI_FIXUP_OPT_OVERRIDE_NAME (1<<0) + +void FixupPCI( const struct _int_map *, int (*swizzler)(int,int) ); + +/* FIXME: This probably belongs into rtems/pci.h */ +extern unsigned char pci_bus_count(); + +/* FIXME: This also is generic and could go into rtems/pci.h */ + +/* Scan pci config space and run a user callback on each + * device present; the user callback may return 0 to + * continue the scan or a value > 0 to abort the scan. + * Return values < 0 are reserved and must not be used. + * + * RETURNS: a (opaque) handle pointing to the bus/slot/fn-triple + * just after where the scan was aborted by a callback + * returning 1 (see above) or NULL if all devices were + * scanned. + * The handle may be passed to this routine to resume the + * scan continuing with the device after the one causing the + * abort. + * Pass a NULL 'handle' argument to start scanning from + * the beginning (bus/slot/fn = 0/0/0). + */ +typedef void *BSP_PciScanHandle; +typedef int (*BSP_PciScannerCb)(int bus, int slot, int fun, void *uarg); + + +BSP_PciScanHandle +BSP_pciScan(BSP_PciScanHandle handle, BSP_PciScannerCb cb, void *uarg); + +/* Dump basic config. space info to a file. The argument may + * be NULL in which case 'stdout' is used. + * NOTE: the C-library must be functional before you can use + * this routine. + */ +void BSP_pciConfigDump(FILE *fp); + +int indirect_pci_read_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t *val +); + +int indirect_pci_read_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t *val +); + +int indirect_pci_read_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t *val +); + +int indirect_pci_write_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t val +); + +int indirect_pci_write_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t val +); + +int indirect_pci_write_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t val +); + +/* Can these be moved to the rtems pci.h? */ +int FindPCIbridge( int mybus, struct pcibridge *pb ); +void pci_list_devices( void ); + +const pci_config_access_functions pci_indirect_functions; + +void pci_out_le32( uint32_t base, uint32_t addr, uint32_t val); +void pci_out_32( uint32_t base, uint32_t addr, uint32_t val); +uint8_t pci_in_8 ( uint32_t base, uint32_t addr ); +int16_t pci_in_le16 ( uint32_t base, uint32_t addr ); +uint32_t pci_in_le32 ( uint32_t base, uint32_t addr ); +int16_t pci_in_16 ( uint32_t base, uint32_t addr ); +uint32_t pci_in_32 ( uint32_t base, uint32_t addr ); +void pci_out_8 ( uint32_t base, uint32_t addr, uint8_t val ); +void pci_out_le16( uint32_t base, uint32_t addr, uint16_t val ); +void pci_out_16( uint32_t base, uint32_t addr, uint16_t val ); +void pci_out_32 ( uint32_t base, uint32_t addr, uint32_t val); + +#define out_32(_addr, _val) pci_out_32(BSP_PCI_BASE_ADDRESS, _addr, _val) +#define out_le32(_addr, _val) pci_out_le32(BSP_PCI_BASE_ADDRESS, _addr, _val) +#define out_32(_addr, _val) pci_out_32(BSP_PCI_BASE_ADDRESS, _addr, _val) +#define in_8(_addr) pci_in_8( BSP_PCI_BASE_ADDRESS, _addr ) +#define in_le16(_addr) pci_in_le16( BSP_PCI_BASE_ADDRESS, _addr ) +#define in_le32(_addr) pci_in_le32( BSP_PCI_BASE_ADDRESS, _addr ) +#define in_16(_addr) pci_in_16( BSP_PCI_BASE_ADDRESS, _addr ) +#define in_32(_addr) pci_in_32( BSP_PCI_BASE_ADDRESS, _addr ) +#define out_8(_addr,_val) pci_out_8( BSP_PCI_BASE_ADDRESS, _addr, _val ) +#define out_le16(_addr,_val) pci_out_le16( BSP_PCI_BASE_ADDRESS, _addr, _val ) +#define out_16(_addr,_val) pci_out_16( BSP_PCI_BASE_ADDRESS, _addr, _val ) + +#endif /* BSP_PCI_H */ diff --git a/c/src/lib/libbsp/mips/malta/irq/interruptmask.c b/c/src/lib/libbsp/mips/malta/irq/interruptmask.c new file mode 100644 index 0000000000..1eb667a1f6 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/irq/interruptmask.c @@ -0,0 +1,36 @@ +/** + * @file + * + * This file contains the implementation of the MIPS port + * support routine which provides the BSP specific default + * interrupt mask. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +/* + * This function returns a mask value which is used to select the bits + * in the processor status register that can be set to enable interrupts. + * The mask value should not include the 2 software interrupt enable bits. + */ + +uint32_t mips_interrupt_mask( void ) +{ + uint32_t interrupt_mask; + + /* + * This has only been tested with qemu for the mips malta and + * may not be correct for the 24k on real hardware. + */ + interrupt_mask = 0x0000ff00; + return(interrupt_mask); +} diff --git a/c/src/lib/libbsp/mips/malta/irq/maxvectors.c b/c/src/lib/libbsp/mips/malta/irq/maxvectors.c new file mode 100644 index 0000000000..77b98544f6 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/irq/maxvectors.c @@ -0,0 +1,24 @@ +/** + * @file + * + * This file contains the maximum number of vectors. This can not + * be determined without knowing the RTEMS CPU model. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* + * Reserve first 32 for exceptions. + */ + +#include + +unsigned int mips_interrupt_number_of_vectors = 13; + diff --git a/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c b/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c new file mode 100644 index 0000000000..1588eec3dc --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c @@ -0,0 +1,90 @@ +/** + * @file + * + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include + +void mips_default_isr( int vector ); +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ); + +#include /* for printk */ + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + unsigned int pending; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT; + + /* SW Bits */ + if ( pending & 0x01) { + printk("Pending IRQ Q 0x%x\n", pending ); + } + + if ( pending & 0x02) { + printk("Pending IRQ Q 0x%x\n", pending ); + } + + /* South Bridge Interrupt */ + if ( pending & 0x04) { + BSP_i8259s_int_process(); + } + + /* South Bridge SMI */ + if (pending & 0x08){ + printk( "Pending IRQ 0x%x\n", pending ); + } + + /* TTY 2 */ + if (pending & 0x10) { + printk( "Pending IRQ 0x%x\n", pending ); + } + /* Core HI */ + if (pending & 0x20) { + printk( "Pending IRQ 0x%x\n", pending ); + } + /* Core LO */ + if (pending & 0x40) { + printk( "Pending IRQ 0x%x\n", pending ); + } + + if ( pending & 0x80 ) { + bsp_interrupt_handler_dispatch( MALTA_INT_TICKER ); + } +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + + while(1); /* Lock it up */ + + rtems_fatal_error_occurred(1); +} + diff --git a/c/src/lib/libbsp/mips/malta/make/custom/malta.cfg b/c/src/lib/libbsp/mips/malta/make/custom/malta.cfg new file mode 100644 index 0000000000..f44b5e98a2 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/make/custom/malta.cfg @@ -0,0 +1,15 @@ +# +# Config file for the MIPS Malta board with 24kf CPU +# + +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU=mips +RTEMS_CPU_MODEL=mips24kf + +# This contains the compiler options necessary to select the CPU model +# and (hopefully) optimize for it. +CPU_CFLAGS = -march=24kf1_1 -Wa,-xgot -G0 + +# optimize flag: typically -O2 +CFLAGS_OPTIMIZE_V = -O0 -g diff --git a/c/src/lib/libbsp/mips/malta/pci/pci.c b/c/src/lib/libbsp/mips/malta/pci/pci.c new file mode 100644 index 0000000000..ab8949bcfe --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/pci/pci.c @@ -0,0 +1,1105 @@ +/** + * @file + * + * This file was based on the powerpc. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include + +#include +#include +#include +#include + +/* + * DEFINES + */ + +#undef SHOW_PCI_SETTING + +// #define DEBUG_PCI 1 + +/* allow for overriding these definitions */ +#ifndef PCI_CONFIG_ADDR +#define PCI_CONFIG_ADDR 0xcf8 +#endif +#ifndef PCI_CONFIG_DATA +#define PCI_CONFIG_DATA 0xcfc +#endif + +#define PCI_INVALID_VENDORDEVICEID 0xffffffff +#define PCI_MULTI_FUNCTION 0x80 + +/* define a shortcut */ +#define pci BSP_pci_configuration + +#ifndef PCI_CONFIG_ADDR_VAL +#define PCI_CONFIG_ADDR_VAL(bus, slot, funcion, offset) \ + (0x80000000|((bus)<<16)|(PCI_DEVFN((slot),(function))<<8)|(((offset)&~3))) +#endif + +#ifdef DEBUG_PCI + #define JPRINTK(fmt, ...) printk("%s: " fmt, __FUNCTION__, ##__VA_ARGS__) +#else + #define JPRINTK(fmt, ...) +#endif + +#ifndef PCI_CONFIG_WR_ADDR +#define PCI_CONFIG_WR_ADDR( addr, val ) out_le32((uint32_t)(addr), (val)) +#endif + +/* Bit encode for PCI_CONFIG_HEADER_TYPE register */ +#define PCI_CONFIG_SET_ADDR(addr, bus, slot,function,offset) \ + PCI_CONFIG_WR_ADDR( \ + (addr), \ + PCI_CONFIG_ADDR_VAL((bus), (slot), (function), (offset))\ + ) + +#define PRINT_MSG() \ + printk("pci : Device %d:0x%02x:%d routed to interrupt_line %d\n", \ + pbus, pslot, pfun, int_name ) + +/* + * STRUCTURES + */ + +/* + * PROTOTYPES + */ +void print_bars( + unsigned char slot, + unsigned char func +); +int direct_pci_read_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t *val +); +int direct_pci_read_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t *val +); +int direct_pci_read_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t *val +); +int direct_pci_write_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t val +); +int direct_pci_write_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t val +); +int direct_pci_write_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t val +); +int test_intname( + const struct _int_map *row, + int pbus, + int pslot, + int pfun, + int int_pin, + int int_name +); +void pci_memory_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +); +void pci_io_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +); +void pci_busmaster_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +); + +/* + * GLOBALS + */ +unsigned char ucMaxPCIBus; +const pci_config_access_functions pci_indirect_functions = { + indirect_pci_read_config_byte, + indirect_pci_read_config_word, + indirect_pci_read_config_dword, + indirect_pci_write_config_byte, + indirect_pci_write_config_word, + indirect_pci_write_config_dword +}; + +rtems_pci_config_t BSP_pci_configuration = { + (volatile unsigned char*)PCI_CONFIG_ADDR, + (volatile unsigned char*)PCI_CONFIG_DATA, + &pci_indirect_functions +}; + +const pci_config_access_functions pci_direct_functions = { + direct_pci_read_config_byte, + direct_pci_read_config_word, + direct_pci_read_config_dword, + direct_pci_write_config_byte, + direct_pci_write_config_word, + direct_pci_write_config_dword +}; + +/* + * PCI specific accesses. Note these are made on 32 bit + * boundries. + */ +void pci_out_32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *) (base + addr); + *ptr = val; + + JPRINTK( "%p data: 0x%x\n", ptr, val); +} + +void pci_out_le32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + uint32_t data = 0; + + ptr = (volatile uint32_t *) (base + addr); + rtems_uint32_to_little_endian( val, (uint8_t *) &data); + *ptr = data; + + JPRINTK( "%p data: 0x%x\n", ptr, data); +} + +uint8_t pci_in_8( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint8_t val; + uint32_t data; + + data = addr/4; + ptr = (volatile uint32_t *) (base + (data*4)); + data = *ptr; + + switch ( addr%4 ) { + case 0: val = (data & 0x000000ff) >> 0; break; + case 1: val = (data & 0x0000ff00) >> 8; break; + case 2: val = (data & 0x00ff0000) >> 16; break; + case 3: val = (data & 0xff000000) >> 24; break; + } + + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, data); + + return val; +} + +int16_t pci_in_le16( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint16_t val; + uint16_t rval; + uint32_t data; + + data = addr/4; + ptr = (volatile uint32_t *) (base + (data*4)); + data = *ptr; + if ( addr%4 == 0 ) + val = data & 0xffff; + else + val = (data>>16) & 0xffff; + + rval = rtems_uint16_from_little_endian( (uint8_t *) &val); + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, data); + return rval; +} + +int16_t pci_in_16( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint16_t val; + uint32_t data; + + data = addr/4; + ptr = (volatile uint32_t *) (base + (data*4)); + data = *ptr; + if ( addr%4 == 0 ) + val = data & 0xffff; + else + val = (data>>16) & 0xffff; + + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, data); + return val; +} + +uint32_t pci_in_32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, val); + return val; +} +uint32_t pci_in_le32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + uint32_t rval; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + rval = rtems_uint32_from_little_endian( (uint8_t *) &val); + + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, val); + return rval; +} + +void pci_out_8( uint32_t base, uint32_t addr, uint8_t val ) { + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *) (base + addr); + JPRINTK("Address: %p\n", ptr); + *ptr = val; + JPRINTK( "%p data: 0x%x\n", ptr, val); +} + +void pci_out_le16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint32_t *ptr; + uint32_t out_data; + uint32_t data; + + ptr = (volatile uint32_t *) (base + (addr & ~0x3)); + data = *ptr; + if ( addr%4 == 0 ) + out_data = (data & 0xffff0000) | val; + else + out_data = ((val << 16)&0xffff0000) | (data & 0xffff); + rtems_uint32_to_little_endian( out_data, (uint8_t *) &data); + *ptr = data; + + JPRINTK( "0x%x data: 0x%x\n", ptr, data); +} + +void pci_out_16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint32_t *ptr; + uint32_t out_data; + uint32_t data; + + ptr = (volatile uint32_t *) (base + (addr & ~0x3)); + data = *ptr; + if ( addr%4 == 0 ) + out_data = (data & 0xffff0000) | val; + else + out_data = ((val << 16)&0xffff0000) | (data & 0xffff); + *ptr = out_data; + + JPRINTK( "0x%x data: 0x%x\n", ptr, out_data); +} + +/* + * INDIRECT PCI CONFIGURATION ACCESSES + */ +int indirect_pci_read_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t *val +) { + + JPRINTK("==>\n"); + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + *val = in_8((uint32_t) (pci.pci_config_data + (offset&3)) ); + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +int indirect_pci_read_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t *val +) { + + JPRINTK("==>\n"); + + *val = 0xffff; + if (offset&1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + *val = in_16((uint32_t)(pci.pci_config_data + (offset&3))); + + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +int indirect_pci_read_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t *val +) { + uint32_t v; + JPRINTK("==>\n"); + + *val = 0xffffffff; + if (offset&3) + return PCIBIOS_BAD_REGISTER_NUMBER; + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + v = in_32( (uint32_t) pci.pci_config_data ); + *val = v; + if ( offset == 0x0b ) + JPRINTK( "%x:%x %x ==> 0x%08x, 0x%08x\n", bus, slot, function, v, *val ); + + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +int indirect_pci_write_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t val +) { + + JPRINTK("==>\n"); + + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + out_8( (uint32_t) (pci.pci_config_data + (offset&3)), val); + + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +int indirect_pci_write_config_word( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint16_t val +) { + + JPRINTK("==>\n"); + + if (offset&1) + return PCIBIOS_BAD_REGISTER_NUMBER; + + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + out_16((uint32_t)(pci.pci_config_data + (offset&3)), val); + + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +int indirect_pci_write_config_dword( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint32_t val +) { + + if (offset&3) + return PCIBIOS_BAD_REGISTER_NUMBER; + + JPRINTK("==>\n"); + + /* + * The Base Address Registers get accessed big endian while the + * other registers are little endian. + */ + PCI_CONFIG_SET_ADDR(pci.pci_config_addr, bus, slot, function, offset); + if ( bus == 0 && slot == 0x0b && + (offset >= PCI_BASE_ADDRESS_0 && offset <= PCI_BASE_ADDRESS_5) ) { + out_32((uint32_t)pci.pci_config_data, val); + } else { + out_le32((uint32_t)pci.pci_config_data, val); + } + + JPRINTK("\n\n"); + + return PCIBIOS_SUCCESSFUL; +} + +/* + * DIRECT CONFIGUREATION ACCESSES. + */ +int direct_pci_read_config_byte( + unsigned char bus, + unsigned char slot, + unsigned char function, + unsigned char offset, + uint8_t *val +) { + if (bus != 0 || (1<\n"); + + *val=in_8((uint32_t) (pci.pci_config_data + ((1<\n"); + + *val=in_le16((uint32_t) + (pci.pci_config_data + ((1<\n"); + + *val=in_le32((uint32_t)(pci.pci_config_data + + ((1<\n"); + + out_8((uint32_t) (pci.pci_config_data + ((1<\n"); + + out_le16((uint32_t)(pci.pci_config_data + ((1<\n"); + + out_le32((uint32_t) + (pci.pci_config_data + ((1<pin_route[j].pin > -1; j++) { + if ( row->pin_route[j].pin == int_pin ) { + _nopin = 0; + + for (k=0; k<4 && row->pin_route[j].int_name[k] > -1; k++ ) { + if ( row->pin_route[j].int_name[k] == int_name ) { + _noname=0; break; + } + } + break; + } + } + + if( _nopin ) + { + printk( + "pci : Device %d:0x%02x:%d supplied a bogus interrupt_pin %d\n", + pbus, + pslot, + pfun, + int_pin + ); + return -1; + } + else + { + if( _noname ) { + unsigned char v = row->pin_route[j].int_name[0]; + printk( + "pci : Device %d:0x%02x:%d supplied a suspicious interrupt_line %d, ", + pbus, + pslot, + pfun, + int_name + ); + if ((row->opts & PCI_FIXUP_OPT_OVERRIDE_NAME) && 255 != + (v = row->pin_route[j].int_name[0]) + ) { + printk("OVERRIDING with %d from fixup table\n", v); + pci_write_config_byte(pbus,pslot,pfun,PCI_INTERRUPT_LINE,v); + } else { + printk("using it anyway\n"); + } + } + } + return 0; +} + +int FindPCIbridge( int mybus, struct pcibridge *pb ) +{ + int pbus, pslot; + uint8_t bussec, buspri; + uint16_t devid, vendorid, dclass; + + for(pbus=0; pbus< pci_bus_count(); pbus++) { + for(pslot=0; pslot< PCI_MAX_DEVICES; pslot++) { + pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid); + if ( devid == 0xffff ) continue; + + pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &vendorid); + if ( vendorid == 0xffff ) continue; + + pci_read_config_word(pbus, pslot, 0, PCI_CLASS_DEVICE, &dclass); + + if ( dclass == PCI_CLASS_BRIDGE_PCI ) { + pci_read_config_byte(pbus, pslot, 0, PCI_PRIMARY_BUS, &buspri); + pci_read_config_byte(pbus, pslot, 0, PCI_SECONDARY_BUS, &bussec); + + #ifdef SHOW_PCI_SETTING + JPRINTK( + "pci : Found bridge at %d:0x%02x, mybus %d, pribus %d, secbus %d ", + pbus, + pslot, + mybus, + buspri, + bussec + ); + #endif + if ( bussec == mybus ) { + #ifdef SHOW_PCI_SETTING + JPRINTK("match\n"); + #endif + /* found our nearest bridge going towards the root */ + pb->bus = pbus; + pb->slot = pslot; + return 0; + } + #ifdef SHOW_PCI_SETTING + JPRINTK("no match\n"); + #endif + } + + } + } + return -1; +} + +void FixupPCI( const struct _int_map *bspmap, int (*swizzler)(int,int) ) +{ + unsigned char cvalue; + uint16_t devid; + int ismatch, i, j, pbus, pslot, pfun, int_pin, int_name, nfuns; + + /* + * If the device has a non-zero INTERRUPT_PIN, assign a bsp-specific + * INTERRUPT_NAME if one isn't already in place. Then, drivers can + * trivially use INTERRUPT_NAME to hook up with devices. + */ + + for (pbus=0; pbus< pci_bus_count(); pbus++) { + for (pslot=0; pslot< PCI_MAX_DEVICES; pslot++) { + pci_read_config_word(pbus, pslot, 0, PCI_DEVICE_ID, &devid); + if ( devid == 0xffff ) continue; + + /* got a device */ + pci_read_config_byte(pbus, pslot, 0, PCI_HEADER_TYPE, &cvalue); + nfuns = cvalue & PCI_MULTI_FUNCTION ? PCI_MAX_FUNCTIONS : 1; + for (pfun=0; pfun< nfuns; pfun++) { + + pci_read_config_word(pbus, pslot, pfun, PCI_DEVICE_ID, &devid); + if( devid == 0xffff ) continue; + + pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_PIN, &cvalue); + int_pin = cvalue; + + pci_read_config_byte( pbus, pslot, pfun, PCI_INTERRUPT_LINE, &cvalue); + int_name = cvalue; + + #ifdef SHOW_PCI_SETTING + { + unsigned short cmd,stat; + unsigned char lat, seclat, csize; + + pci_read_config_word(pbus,pslot,pfun,PCI_COMMAND, &cmd ); + pci_read_config_word(pbus,pslot,pfun,PCI_STATUS, &stat ); + pci_read_config_byte(pbus,pslot,pfun,PCI_LATENCY_TIMER, &lat ); + pci_read_config_byte(pbus,pslot,pfun,PCI_SEC_LATENCY_TIMER, &seclat); + pci_read_config_byte(pbus,pslot,pfun,PCI_CACHE_LINE_SIZE, &csize ); + + JPRINTK( + "pci : device %d:0x%02x:%d cmd %04X, stat %04X, latency %d, " + " sec_latency %d, clsize %d\n", + pbus, + pslot, + pfun, + cmd, + stat, + lat, + seclat, + csize + ); + } + #endif + + if ( int_pin > 0 ) { + ismatch = 0; + + /* + * first run thru the bspmap table and see if we have an + * explicit configuration + */ + for (i=0; bspmap[i].bus > -1; i++) { + if ( bspmap[i].bus == pbus && bspmap[i].slot == pslot ) { + ismatch = -1; + + /* we have a record in the table that gives specific + * pins and interrupts for devices in this slot + */ + if ( int_name == 255 ) { + + /* find the vector associated with whatever pin the + * device gives us + */ + for ( int_name=-1, j=0; bspmap[i].pin_route[j].pin > -1; j++ ){ + if ( bspmap[i].pin_route[j].pin == int_pin ) { + int_name = bspmap[i].pin_route[j].int_name[0]; + break; + } + } + + if ( int_name == -1 ) { + printk( + "pci : Unable to resolve device %d:0x%02x:%d w/ " + "swizzled int pin %i to an interrupt_line.\n", + pbus, + pslot, + pfun, + int_pin + ); + } else { + PRINT_MSG(); + pci_write_config_byte( + pbus, + pslot, + pfun, + PCI_INTERRUPT_LINE,(cvalue= int_name, cvalue) + ); + } + } else { + test_intname( &bspmap[i],pbus,pslot,pfun,int_pin,int_name); + } + break; + } + } + + if ( !ismatch ) { + /* + * no match, which means we're on a bus someplace. Work + * backwards from it to one of our defined busses, + * swizzling thru each bridge on the way. + */ + + /* keep pbus, pslot pointed to the device being + * configured while we track down the bridges using + * tbus,tslot. We keep searching the routing table because + * we may end up finding our bridge in it + */ + + int tbus= pbus, tslot= pslot; + for (;;) { + for (i=0; bspmap[i].bus > -1; i++) { + if ( bspmap[i].bus == tbus && + (bspmap[i].slot == tslot || bspmap[i].slot == -1)) + { + ismatch = -1; + + /* found a record for this bus, so swizzle the + * int_pin which we then use to find the + * interrupt_name. + */ + if ( int_name == 255 ) { + /* + * FIXME. I can't believe this little hack + * is right. It does not yield an error in + * convienently simple situations. + */ + if ( tbus ) int_pin = (*swizzler)(tslot,int_pin); + + /* + * int_pin points to the interrupt channel + * this card ends up delivering interrupts + * on. Find the int_name servicing it. + */ + for (int_name=-1, j=0; + bspmap[i].pin_route[j].pin > -1; + j++) + { + if ( bspmap[i].pin_route[j].pin == int_pin ) { + int_name = bspmap[i].pin_route[j].int_name[0]; + break; + } + } + + if ( int_name == -1 ) { + printk( + "pci : Unable to resolve device %d:0x%02x:%d w/ " + "swizzled int pin %i to an interrupt_line.\n", + pbus, + pslot, + pfun, + int_pin + ); + } else { + PRINT_MSG(); + pci_write_config_byte(pbus,pslot,pfun, + PCI_INTERRUPT_LINE,(cvalue=int_name, cvalue)); + } + } else { + test_intname( + &bspmap[i], + pbus, + pslot, + pfun, + int_pin, + int_name + ); + } + goto donesearch; + } + } + if ( !ismatch ) { + struct pcibridge pb; + + /* + * Haven't found our bus in the int map, so work + * upwards thru the bridges till we find it. + */ + if ( FindPCIbridge( tbus, &pb )== 0 ) { + int_pin = (*swizzler)(tslot,int_pin); + + /* our next bridge up is on pb.bus, pb.slot- now + * instead of pointing to the device we're + * trying to configure, we move from bridge to + * bridge. + */ + tbus = pb.bus; + tslot = pb.slot; + } else { + printk( + "pci : No bridge from bus %i towards root found\n", + tbus + ); + goto donesearch; + } + } + } + } + + donesearch: + if ( !ismatch && int_pin != 0 && int_name == 255 ) { + printk( + "pci : Unable to match device %d:0x%02x:%d with an int " + "routing table entry\n", + pbus, + pslot, + pfun + ); + } + } + } + } + } +} + +void print_bars( + unsigned char slot, + unsigned char func +) +{ + uint32_t addr; + + printk( "*** BARs for slot=%d func=%d\n", slot, func ); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_0, &addr); + printk("*** PCI DEVICE BAR0: 0x%x\n", addr); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_1, &addr); + printk("*** PCI DEVICE BAR1: 0x%x\n", addr); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_2, &addr); + printk("*** PCI DEVICE BAR2: 0x%x\n", addr); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_3, &addr); + printk("*** PCI DEVICE BAR3: 0x%x\n", addr); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_4, &addr); + printk("*** PCI DEVICE BAR4: 0x%x\n", addr); + pci_read_config_dword (0, slot, func, PCI_BASE_ADDRESS_5, &addr); + printk("*** PCI DEVICE BAR5: 0x%x\n", addr); +} + +void pci_memory_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +) +{ + uint16_t data; + + pci_read_config_word(0, slot, function, PCI_COMMAND, &data); + data |= PCI_COMMAND_MEMORY; + pci_write_config_word(0, slot, function, PCI_COMMAND, data ); + pci_read_config_word(0, slot, function, PCI_COMMAND, &data); +} + +void pci_io_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +) +{ + uint16_t data; + + pci_read_config_word(0, slot, function, PCI_COMMAND, &data); + data |= PCI_COMMAND_IO; + pci_write_config_word(0, slot, function, PCI_COMMAND, data ); +} + +void pci_busmaster_enable( + unsigned char bus, + unsigned char slot, + unsigned char function +) +{ + uint16_t data; + + pci_read_config_word(0, slot, function, PCI_COMMAND, &data); + data |= PCI_COMMAND_MASTER; + pci_write_config_word(0, slot, function, PCI_COMMAND, data ); +} + +/* + * This routine determines the maximum bus number in the system + */ +int pci_initialize(void) +{ + unsigned char slot, func, ucNumFuncs; + unsigned char ucHeader; + uint32_t class; + uint32_t device; + uint32_t vendor; + + /* + * Initialize GT_PCI0IOREMAP + */ + pci_out_32( BSP_PCI_BASE_ADDRESS, 0xf0, 0 ); + + /* + * According to Linux and BSD sources, this is needed to cover up a bug + * in some versions of the hardware. + */ + out_le32( PCI_CONFIG_ADDR, 0x80000020 ); + out_le32( PCI_CONFIG_DATA, 0x1be00000 ); + + /* + * Scan PCI bus 0 looking for the known Network devices and + * initializing the PCI for them. + */ + for (slot=0;slot> 16; + + /* This slot/function has a device fitted. */ + pci_read_config_dword(0, slot, func, PCI_CLASS_REVISION, &class); + class >>= 16; + + // printk( "FOUND DEVICE 0x%04x/0x%04x class 0x%x\n", + // vendor, device, class ); + if (class == PCI_CLASS_NETWORK_ETHERNET) { + JPRINTK("FOUND ETHERNET\n"); + + pci_write_config_byte( + 0, slot, func, PCI_INTERRUPT_LINE, MALTA_IRQ_ETHERNET ); + + /* + * Rewrite BAR1 for RTL8139 + */ + if ( vendor == PCI_VENDOR_ID_REALTEK && + device == PCI_DEVICE_ID_REALTEK_8139 ) { + + pci_memory_enable(0, slot, func); + pci_io_enable(0, slot, func); + pci_busmaster_enable(0, slot, func); + + // BAR0: IO at 0x0000_1001 + pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0, 0x00001001); + + // BAR1: Memory at 0x1203_1000 + pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_1, 0x12031000); + + // print_bars( slot, func ); + } else if ( vendor == PCI_VENDOR_ID_AMD && + device == PCI_DEVICE_ID_AMD_LANCE ) { + print_bars( slot, func ); + pci_memory_enable(0, slot, func); + pci_io_enable(0, slot, func); + pci_busmaster_enable(0, slot, func); + + // BAR0: IO at 0x0000_1041 + pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_0, 0x00001041); + + // BAR1: Memory at 0x1201_1020 + pci_write_config_dword(0, slot, func, PCI_BASE_ADDRESS_1, 0x12011020); + print_bars( slot, func ); + } + + } + } + } + return PCIB_ERR_SUCCESS; +} + +/* + * Return the number of PCI busses in the system + */ +unsigned char pci_bus_count(void) +{ + return (ucMaxPCIBus+1); +} diff --git a/c/src/lib/libbsp/mips/malta/pci/pcifinddevice.c b/c/src/lib/libbsp/mips/malta/pci/pcifinddevice.c new file mode 100644 index 0000000000..2ef4eaff5e --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/pci/pcifinddevice.c @@ -0,0 +1,279 @@ +/** + * @file + * + * This file was copied from the powerpc and modified slightly. + * I think this file could be made generic and put in a general pci + * area. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ +/* find a particular PCI device + * (we assume, the firmware configured the PCI bus[es] for us) + */ + +/* + * Authorship + * ---------- + * This software was created by + * Till Straumann , 2001, + * Stanford Linear Accelerator Center, Stanford University. + * + * Acknowledgement of sponsorship + * ------------------------------ + * This software was produced by + * the Stanford Linear Accelerator Center, Stanford University, + * under Contract DE-AC03-76SFO0515 with the Department of Energy. + * + * Government disclaimer of liability + * ---------------------------------- + * Neither the United States nor the United States Department of Energy, + * nor any of their employees, makes any warranty, express or implied, or + * assumes any legal liability or responsibility for the accuracy, + * completeness, or usefulness of any data, apparatus, product, or process + * disclosed, or represents that its use would not infringe privately owned + * rights. + * + * Stanford disclaimer of liability + * -------------------------------- + * Stanford University makes no representations or warranties, express or + * implied, nor assumes any liability for the use of this software. + * + * Stanford disclaimer of copyright + * -------------------------------- + * Stanford University, owner of the copyright, hereby disclaims its + * copyright and all other rights in this software. Hence, anyone may + * freely use it for any purpose without restriction. + * + * Maintenance of notices + * ---------------------- + * In the interest of clarity regarding the origin and status of this + * SLAC software, this and all the preceding Stanford University notices + * are to remain affixed to any copy or derivative of this software made + * or distributed by the recipient and are to be affixed to any copy of + * software made or distributed by the recipient that contains a copy or + * derivative of this software. + * + * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03 + */ +#define PCI_INVALID_VENDORDEVICEID 0xffffffff +#define PCI_MULTI_FUNCTION 0x80 + +#define PCI_DEBUG + +#include +#include +#include +#include + +/* Stolen from i386... */ + +/* + * Make device signature from bus number, device number and function + * number + */ +#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f)) + +/* + * Extract various parts from device signature + */ +#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff) +#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f) +#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7) + +typedef struct { + unsigned short vid,did; + int inst; +} fd_arg; + +static int find_dev_cb( + int bus, + int dev, + int fun, + void *uarg +) +{ + fd_arg *a = uarg; + unsigned short vendor; + unsigned short device; + + pci_read_config_word(bus,dev,fun,PCI_VENDOR_ID,&vendor); + pci_read_config_word(bus,dev,fun,PCI_DEVICE_ID,&device); + printk(" FOUND: Vendor 0x%x Device: 0x%x\n", vendor, device); + + if (a->vid == vendor) { + if (a->did == device && 0 == a->inst-- ) { + a->inst = PCIB_DEVSIG_MAKE( bus, dev, fun ); + return 1; + } + } + return 0; +} + +int pci_find_device( + unsigned short vendorid, + unsigned short deviceid, + int instance, + int *pbus, + int *pdev, + int *pfun +) +{ + fd_arg a; + void *h; + + a.vid = vendorid; + a.did = deviceid; + a.inst = instance; + + if ( (h = BSP_pciScan(0, find_dev_cb, (void*)&a)) ) { + *pbus = PCIB_DEVSIG_BUS( a.inst ); + *pdev = PCIB_DEVSIG_DEV( a.inst ); + *pfun = PCIB_DEVSIG_FUNC( a.inst ); + return 0; + } + + return -1; +} + +static int dump_dev_cb( + int bus, + int dev, + int fun, + void *uarg +) +{ + uint16_t vi,di; + uint16_t cd,st; + uint32_t b1,b2; + uint8_t il,ip; + FILE *f = uarg; + + pci_read_config_word (bus, dev, fun, PCI_VENDOR_ID, &vi); + pci_read_config_word (bus, dev, fun, PCI_DEVICE_ID, &di); + pci_read_config_word (bus, dev, fun, PCI_COMMAND, &cd); + pci_read_config_word (bus, dev, fun, PCI_STATUS, &st); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_0, &b1); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_1, &b2); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_LINE, &il); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_PIN, &ip); + + fprintf( + f, + "%3d:0x%02x:%d 0x%04x-0x%04x: 0x%04x 0x%04x 0x%08" PRIx32 + " 0x%08" PRIx32 " %d -> %3d (=0x%02x)\n", + bus, + dev, + fun, + vi, + di, + cd, + st, + b1, + b2, + ip, + il, + il + ); + return 0; +} + +void BSP_pciConfigDump(FILE *f) +{ + if ( !f ) + f = stdout; + fprintf( + f, + "BUS:SLOT:FUN VENDOR-DEV_ID: COMMAND STATUS BASE_ADDR0 BASE_ADDR1 " + "IRQ_PIN -> IRQ_LINE\n" + ); + BSP_pciScan(0, dump_dev_cb, f); +} + +BSP_PciScanHandle BSP_pciScan( + BSP_PciScanHandle handle, + BSP_PciScannerCb cb, + void *uarg +) { + + uint32_t d; + unsigned char bus,dev,fun,hd; + + bus = PCIB_DEVSIG_BUS( (unsigned long)handle ); + dev = PCIB_DEVSIG_DEV( (unsigned long)handle ); + fun = PCIB_DEVSIG_FUNC( (unsigned long)handle ); + + hd = fun > 0 ? PCI_MAX_FUNCTIONS : 1; + + for (; bus 0 ) { + if ( ++fun >= hd ) { + fun = 0; + if ( ++dev >= PCI_MAX_DEVICES ) { + dev = 0; + bus++; + } + } + #ifdef PCI_DEBUG + printk( + "BSP_pciScan: Going to Return: bus %d dev 0x%x fun %d\n", + bus, + dev, + fun + ); + #endif + return (void*) PCIB_DEVSIG_MAKE(bus,dev,fun); + } + } + } + } + return 0; +} diff --git a/c/src/lib/libbsp/mips/malta/pci/pcilistdevices.c b/c/src/lib/libbsp/mips/malta/pci/pcilistdevices.c new file mode 100644 index 0000000000..bc9907ed6f --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/pci/pcilistdevices.c @@ -0,0 +1,105 @@ +/** + * @file + * + * I think this file could be made generic and put in a general pci + * area. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +/* + * List all PCI Devices + */ + +#define PCI_INVALID_VENDORDEVICEID 0xffffffff +#define PCI_MULTI_FUNCTION 0x80 + +#define PCI_DEBUG + +#include +#include +#include +#include + +/* + * Make device signature from bus number, device number and function + * number + */ +#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f)) + +/* + * Extract various parts from device signature + */ +#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff) +#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f) +#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7) + +static int print_device_config( + int bus, + int dev, + int fun +) +{ + uint16_t vi,di; + uint16_t cd,st; + uint32_t b1,b2; + uint8_t il,ip; + + pci_read_config_word (bus, dev, fun, PCI_VENDOR_ID, &vi); + pci_read_config_word (bus, dev, fun, PCI_DEVICE_ID, &di); + pci_read_config_word (bus, dev, fun, PCI_COMMAND, &cd); + pci_read_config_word (bus, dev, fun, PCI_STATUS, &st); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_0, &b1); + pci_read_config_dword(bus, dev, fun, PCI_BASE_ADDRESS_1, &b2); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_LINE, &il); + pci_read_config_byte (bus, dev, fun, PCI_INTERRUPT_PIN, &ip); + + printk( + "%3d:0x%02x:%d 0x%04x-0x%04x: 0x%04x 0x%04x 0x%08" PRIx32 + " 0x%08" PRIx32 " %d -> %3d (=0x%02x)\n", + bus, dev, fun, vi, di, cd, st, b1, b2, ip, il, il); + return 0; +} + +void pci_list_devices( void ) +{ + uint32_t d; + unsigned char bus,dev,fun,hd; + + printk( + "BUS:SLOT:FUN VENDOR-DEV_ID: COMMAND STATUS BASE_ADDR0 " + "BASE_ADDR1 IRQ_PIN -> IRQ_LINE\n" + ); + for (bus=0 ; bus $(srcdir)/preinstall.am +endif + +PREINSTALL_DIRS = +DISTCLEANFILES += $(PREINSTALL_DIRS) + +all-local: $(TMPINSTALL_FILES) + +TMPINSTALL_FILES = +CLEANFILES = $(TMPINSTALL_FILES) + +all-am: $(PREINSTALL_FILES) + +PREINSTALL_FILES = +CLEANFILES += $(PREINSTALL_FILES) + +$(PROJECT_LIB)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_LIB) + @: > $(PROJECT_LIB)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_LIB)/$(dirstamp) + +$(PROJECT_INCLUDE)/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE) + @: > $(PROJECT_INCLUDE)/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp) + +$(PROJECT_INCLUDE)/bsp/$(dirstamp): + @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp + @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp) +PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp) + +$(PROJECT_LIB)/bsp_specs: bsp_specs $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/bsp_specs +PREINSTALL_FILES += $(PROJECT_LIB)/bsp_specs + +$(PROJECT_INCLUDE)/bsp.h: include/bsp.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp.h + +$(PROJECT_INCLUDE)/tm27.h: ../../shared/include/tm27.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tm27.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/tm27.h + +$(PROJECT_INCLUDE)/bsp/regs.h: ../shared/liblnk/regs.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/regs.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/regs.h + +$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h + +$(PROJECT_INCLUDE)/bsp/irq-info.h: ../../shared/include/irq-info.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-info.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-info.h + +$(PROJECT_INCLUDE)/bsp/irq.h: include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h + +$(PROJECT_INCLUDE)/bsp/pci.h: include/pci.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/pci.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/pci.h + +$(PROJECT_INCLUDE)/bsp/i8259.h: ../shared/irq/i8259.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i8259.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i8259.h + +$(PROJECT_INCLUDE)/bspopts.h: include/bspopts.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bspopts.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bspopts.h + +$(PROJECT_INCLUDE)/bsp/bootcard.h: ../../shared/include/bootcard.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bootcard.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bootcard.h + +$(PROJECT_INCLUDE)/coverhd.h: ../../shared/include/coverhd.h $(PROJECT_INCLUDE)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/coverhd.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/coverhd.h + +$(PROJECT_LIB)/start.$(OBJEXT): start.$(OBJEXT) $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/start.$(OBJEXT) +TMPINSTALL_FILES += $(PROJECT_LIB)/start.$(OBJEXT) + +$(PROJECT_LIB)/linkcmds: startup/linkcmds $(PROJECT_LIB)/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_LIB)/linkcmds +PREINSTALL_FILES += $(PROJECT_LIB)/linkcmds + diff --git a/c/src/lib/libbsp/mips/malta/start/start.S b/c/src/lib/libbsp/mips/malta/start/start.S new file mode 100644 index 0000000000..468a43b4a0 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/start/start.S @@ -0,0 +1,220 @@ +/* + * start.S -- startup file for JMR3904 BSP based upon crt0.S from + * newlib-1.8.2/libgloss/mips and adapted for RTEMS. + * + * crt0.S -- startup file for MIPS. + * + * Copyright (c) 1995, 1996, 1997 Cygnus Support + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + */ + +#include +#include + +#ifdef __mips16 +/* This file contains 32 bit assembly code. */ + .set nomips16 +#endif + +/* This is for referencing addresses that are not in the .sdata or + .sbss section under embedded-pic, or before we've set up gp. */ +#ifdef __mips_embedded_pic +# ifdef __mips64 +# define LA(t,x) la t,x-PICBASE ; daddu t,s0,t +# else +# define LA(t,x) la t,x-PICBASE ; addu t,s0,t +# endif +#else /* __mips_embedded_pic */ +# define LA(t,x) la t,x +#endif /* __mips_embedded_pic */ + + .text + .align 2 + +/* Without the following nop, GDB thinks _start is a data variable. + * This is probably a bug in GDB in handling a symbol that is at the + * start of the .text section. + */ + nop + nop + nop + nop + nop + nop + nop + nop + nop + .globl _start + .ent _start +_start: + nop + nop + nop + nop + nop + nop + nop + nop + .set noreorder + /* Get the address of start into $5 in a position independent fashion. + ** This lets us know whether we have been relocated or not. + */ + $LF1 = . + 8 + bal $LF1 + nop +_branch: +#if 0 + move $5, $31 # $5 == where are we + li $6, 0x8800000c # $6 == where we want to be +/* #la $6,_branch */ + beq $5, $6, _start_in_ram + nop + /* relocate the code from EEPROM to RAM */ + la $7, _edata +relocate: + nop + lw $8, ($5) # $8 = *EEPROM + addu $5, $5, 4 # EEPROM++ + sw $8, ($6) # *RAM = $8 + addu $6, $6, 4 # RAM++ + bne $6, $7, relocate # copied all the way to edata? + nop + la $6, _start_in_ram + jr $6 + nop + .end _start + + .globl _start_in_ram + .ent _start_in_ram +#endif +_start_in_ram: + nop +#if 0 +#ifdef __mips_embedded_pic + PICBASE = .+8 + bal PICBASE + nop + move s0,$31 +#endif +#endif + li v0, SR_CU1|SR_PE|SR_FR|SR_KX|SR_SX|SR_UX + mtc0 v0, C0_SR + mtc0 zero, C0_CAUSE + +#if 0 +/* Check for FPU presence */ +#ifndef __mips_soft_float +/* This doesn't work if there is no FPU. We get illegal instruction + exceptions. */ + li t2,0xAAAA5555 + mtc1 t2,fp0 /* write to FPR 0 */ + mtc1 zero,fp1 /* write to FPR 1 */ + mfc1 t0,fp0 + mfc1 t1,fp1 + nop + bne t0,t2,1f /* check for match */ + nop + bne t1,zero,1f /* double check */ + nop +#ifndef __mips64 /* Clear the FR bit */ + li v0, SR_CU1|SR_PE|SR_KX|SR_SX|SR_UX + mtc0 v0, C0_SR +#endif + j 2f + nop +#endif +#endif + +1: + li v0, SR_PE|SR_FR|SR_KX|SR_SX|SR_UX + mtc0 v0, C0_SR +2: +/* Fix high bits, if any, of the PC so that exception handling + doesn't get confused. */ + LA (v0, 3f) + jr v0 + nop +3: + LA (gp, _gp) # set the global data pointer +#if 0 + .end _start_in_ram +#else + .end _start +#endif + +/* + * zero out the bss section. + */ + .globl __memsize + .globl zerobss + .ent zerobss +zerobss: + LA (v0, _fbss) + LA (v1, _end) +3: + sw zero,0(v0) + bltu v0,v1,3b + addiu v0,v0,4 # executed in delay slot + + la t0, _stack_init # initialize stack so we + /* We must subtract 24 bytes for the 3 8 byte arguments to main, in + case main wants to write them back to the stack. The caller is + supposed to allocate stack space for parameters in registers in + the old MIPS ABIs. We must do this even though we aren't passing + arguments, because main might be declared to have them. + + Some ports need a larger alignment for the stack, so we subtract + 32, which satisifes the stack for the arguments and keeps the + stack pointer better aligned. */ + subu t0,t0,32 + move sp,t0 # set stack pointer + .end zerobss + + .globl exit .text + .globl init + .ent init +init: + nop + jal init_tlb /* clear the tlb */ + move a0,zero # set command line to 0 + jal boot_card # call the program start function + nop + +dead: + b dead + nop + .end init + +/* + * _sys_exit -- Exit from the application. Normally we cause a user trap + * to return to the ROM monitor for another run. NOTE: This is + * the only other routine we provide in the crt0.o object, since + * it may be tied to the "_start" routine. It also allows + * executables that contain a complete world to be linked with + * just the crt0.o object. + */ + .globl _sys_exit + .ent _sys_exit +_sys_exit: +7: +#ifdef GCRT0 + jal _mcleanup + nop +#endif + /* break instruction can cope with 0xfffff, but GAS limits the range: */ + break 1023 + nop + b 7b # but loop back just in-case + nop + .end _sys_exit + +/* EOF crt0.S */ diff --git a/c/src/lib/libbsp/mips/malta/startup/bspreset.c b/c/src/lib/libbsp/mips/malta/startup/bspreset.c new file mode 100644 index 0000000000..519dd2886a --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/startup/bspreset.c @@ -0,0 +1,35 @@ +/** + * @file + * + * This file contains the code necessary to reset the Malta board. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +void bsp_reset(void); + +void bsp_reset(void) +{ + uint32_t *reset; + + reset= (uint32_t *)0x9F000500; + /* + * Qemu understands 0x42 to reset simulated machine. + * We added code to recognize 0xFF to exit simulator. + * + * TBD: Qemu PC simulation has option to exit on reset. + * find processing of that command line option and + * use it to change behaviour of 0x42. + */ + // *reset = 0x42; + *reset = 0xFF; +} diff --git a/c/src/lib/libbsp/mips/malta/startup/bspstart.c b/c/src/lib/libbsp/mips/malta/startup/bspstart.c new file mode 100644 index 0000000000..3767e0966e --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/startup/bspstart.c @@ -0,0 +1,113 @@ +/** + * @file + * + * This file contains the bsp_start() method and support. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * STRUCTURES + */ + +/* Structure filled in by get_mem_info. Only the size field is + * actually used (to clear bss), so the others aren't even filled in. + */ +struct s_mem +{ + unsigned int size; + unsigned int icsize; + unsigned int dcsize; +}; + + +/* + * GLOBALS + */ +uint32_t bsp_clicks_per_microsecond; + + +/* + * PROTOTYPES + */ +void clear_cache( void *address, size_t n ); +void get_mem_info( struct s_mem *mem ); + +/* + * EXTERNs + */ +extern int RamSize; + +/* + * bsp_start + * + * This routine does the bulk of the system initialization. + */ +void bsp_start( void ) +{ + /* uint32_t board_ID = 0x420; */ + static int j = 1; + int pci_init_retval; + + /* + * Note: This is the value that works for qemu, and it was + * unable to be validated on the actual hardware. + */ + mips_set_sr( 0x04100000 ); + + bsp_interrupt_initialize(); + + /* + * XXX need to figure out a real value. :) + * This works for the qemu simulation, but timeing may + * be off for the actual hardware. + */ + bsp_clicks_per_microsecond = 100; + + #if 1 + while ( j != 1 ) { + int i; + printk ("."); + for (i=0; i<1000; i++); + } + #endif + + /* + * init PCI Bios interface... + */ + pci_init_retval = pci_initialize(); + if (pci_init_retval != PCIB_ERR_SUCCESS) { + printk("PCI bus: could not initialize PCI BIOS interface\n"); + } + + BSP_i8259s_init(); + +} + +/* + * Required routine by some gcc run-times. + */ +void clear_cache( void *address, size_t n ) +{ +} + +void get_mem_info( + struct s_mem *mem +) +{ + mem->size = (int) (&RamSize); /* Normally 128 or 256 MB */ +} diff --git a/c/src/lib/libbsp/mips/malta/startup/inittlb.c b/c/src/lib/libbsp/mips/malta/startup/inittlb.c new file mode 100644 index 0000000000..413783c211 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/startup/inittlb.c @@ -0,0 +1,26 @@ +/** + * @file + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +extern void resettlb( int i ); + +void init_tlb(void); + +void init_tlb(void) +{ + int i; + + for (i = 0; i < N_TLB_ENTRIES; i++ ) + resettlb(i); +} diff --git a/c/src/lib/libbsp/mips/malta/startup/linkcmds b/c/src/lib/libbsp/mips/malta/startup/linkcmds new file mode 100644 index 0000000000..e52d3b8f98 --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/startup/linkcmds @@ -0,0 +1,181 @@ +/* + * MIPS Malta Linker Script + */ + +/* + * Declare some sizes. + */ +RamBase = DEFINED(RamBase) ? RamBase : 0x80000000; +RamSize = DEFINED(RamSize) ? RamSize : 128M; +HeapSize = DEFINED(HeapSize) ? HeapSize : 0x0; +_StackSize = DEFINED(_StackSize) ? _StackSize : 0x2000; + +SECTIONS +{ + . = 0x80010000; + .text : + { + _ftext = . ; + eprol = .; + *(.text*) + *(.gnu.linkonce.t*) + *(.mips16.fn.*) + *(.mips16.call.*) + PROVIDE (__runtime_reloc_start = .); + *(.rel.sdata) + PROVIDE (__runtime_reloc_stop = .); + + /* + * Special FreeBSD sysctl sections. + */ + . = ALIGN (16); + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = ABSOLUTE(.); + *(set_domain_*); + *(set_pseudo_*); + + *(.gcc_except_table*) + *(.eh_frame_hdr) + *(.eh_frame) + } + + .init : + { + KEEP(*(.init)) + } + + .fini : + { + KEEP(*(.fini)) + } + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + + KEEP (*crtbegin.o(.ctors)) + + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + + etext = .; + _etext = .; + } + + .rdata : { + *(.rdata) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } + _fdata = ALIGN(16); + + .data : { + *(.data) + *(.data.*) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } + . = ALIGN(8); + + .jcr : { + KEEP (*(.jcr)) + } + + _gp = ALIGN(16) + 0x7440; + __global = _gp; + + .sdata : { + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s*) + } + .lit8 : { + *(.lit8) + } + .lit4 : { + *(.lit4) + } + + edata = .; + _edata = .; + _fbss = .; + + .sbss : { + *(.sbss*) + *(.scommon) + } + .bss : { + _bss_start = . ; + *(.bss*) + *(COMMON) + . = ALIGN (64); + _stack_limit = .; + . += _StackSize; + __stack = .; + _stack_init = .; + WorkAreaBase = .; + _clear_end = .; + } + . = 0x88400000; /* reserve some memory for Work Area */ + end = .; + _end = .; + + +/* Put starting stack in SRAM (8 Kb); this size is the same as the stack from + the original script (when everything was in SRAM). */ + /* __stack = 0x8000A000; */ + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to + the beginning of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } +} diff --git a/c/src/lib/libbsp/mips/malta/startup/simple_access.c b/c/src/lib/libbsp/mips/malta/startup/simple_access.c new file mode 100644 index 0000000000..abc1f8892e --- /dev/null +++ b/c/src/lib/libbsp/mips/malta/startup/simple_access.c @@ -0,0 +1,133 @@ +/** + * @file + * + * This file contains the code to do simple memory and io accesses. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include +#include + +#include +#include +#include +#include +// #define DEBUG_ACCESSES 1 + +#ifdef DEBUG_ACCESSES + #define JPRINTK(fmt, ...) printk("%s: " fmt, __FUNCTION__, ##__VA_ARGS__) +#else + #define JPRINTK(fmt, ...) +#endif + +/* + * * Simple accesses + * */ +void simple_out_32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + + ptr = (volatile uint32_t *) (base + addr); + *ptr = val; + + JPRINTK( "%p data: 0x%x\n", ptr, val); +} + +void simple_out_le32(uint32_t base, uint32_t addr, uint32_t val) +{ + volatile uint32_t *ptr; + uint32_t data = 0; + + ptr = (volatile uint32_t *) (base + addr); + rtems_uint32_to_little_endian( val, (uint8_t *) &data); + *ptr = data; + + JPRINTK( "%p data: 0x%x\n", ptr, data); +} + +uint8_t simple_in_8( uint32_t base, uint32_t addr ) { + volatile uint8_t *ptr; + uint8_t val; + + ptr = (volatile uint8_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x\n", ptr, val); + + return val; +} + +int16_t simple_in_le16( uint32_t base, uint32_t addr ) { + volatile uint16_t *ptr; + uint16_t val; + uint16_t rval; + + ptr = (volatile uint16_t *) (base + addr); + val = *ptr; + rval = rtems_uint16_from_little_endian( (uint8_t *) &val); + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, val); + return rval; +} + +int16_t simple_in_16( uint32_t base, uint32_t addr ) { + volatile uint16_t *ptr; + uint16_t val; + + ptr = (volatile uint16_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, val); + return val; +} + +uint32_t simple_in_le32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + uint32_t rval; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + rval = rtems_uint32_from_little_endian( (uint8_t *) &val); + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, rval, val); + return rval; +} + +uint32_t simple_in_32( uint32_t base, uint32_t addr ) { + volatile uint32_t *ptr; + uint32_t val; + + ptr = (volatile uint32_t *) (base + addr); + val = *ptr; + JPRINTK( "0x%x data: 0x%x raw: 0x%x\n", ptr, val, val); + return val; +} + +void simple_out_8( uint32_t base, uint32_t addr, uint8_t val ) { + volatile uint8_t *ptr; + + ptr = (volatile uint8_t *) (base | addr); + JPRINTK( "0x%x data: 0x%x\n", ptr, val); + *ptr = val; +} + +void simple_out_le16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint16_t *ptr; + uint16_t data; + ptr = (volatile uint16_t *) (base + addr); + rtems_uint16_to_little_endian( val, (uint8_t *) &data); + *ptr = data; + JPRINTK( "0x%x data: 0x%x\n", ptr, data); +} + +void simple_out_16( uint32_t base, uint32_t addr, uint16_t val ) { + volatile uint16_t *ptr; + ptr = (volatile uint16_t *) (base + addr); + *ptr = val; + JPRINTK( "0x%x data: 0x%x\n", ptr, val); +} -- cgit v1.2.3