From dc0a7df67469f1170cfb95114c03f5980710c1be Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 21 Jul 2011 15:18:02 +0000 Subject: 2011-07-21 Sebastian Huber PR 1799/bsps * .cvsignore, ChangeLog, Makefile.am, README, bsp_specs, configure.ac, clock/clock-config.c, console/console-config.c, console/uart-bridge-master.c, console/uart-bridge-slave.c, include/.cvsignore, include/bsp.h, include/hwreg_vals.h, include/intercom.h, include/irq.h, include/mmu.h, include/qoriq.h, include/tm27.h, include/tsec-config.h, include/u-boot-config.h, include/uart-bridge.h, irq/irq.c, make/custom/qoriq.inc, make/custom/qoriq_core_0.cfg, make/custom/qoriq_core_1.cfg, make/custom/qoriq_p1020rdb.cfg, network/if_intercom.c, network/network.c, rtc/rtc-config.c, shmsupp/intercom-mpci.c, shmsupp/intercom.c, shmsupp/lock.S, start/start.S, startup/bsppredriverhook.c, startup/bspreset.c, startup/bspstart.c, startup/linkcmds.base, startup/linkcmds.qoriq_core_0, startup/linkcmds.qoriq_core_1, startup/linkcmds.qoriq_p1020rdb, startup/mmu-config.c, startup/mmu-tlb1.S, startup/mmu.c: New files. --- c/src/lib/libbsp/powerpc/qoriq/.cvsignore | 8 + c/src/lib/libbsp/powerpc/qoriq/ChangeLog | 18 + c/src/lib/libbsp/powerpc/qoriq/Makefile.am | 123 +++++ c/src/lib/libbsp/powerpc/qoriq/README | 5 + c/src/lib/libbsp/powerpc/qoriq/bsp_specs | 14 + .../lib/libbsp/powerpc/qoriq/clock/clock-config.c | 128 ++++++ c/src/lib/libbsp/powerpc/qoriq/configure.ac | 98 ++++ .../libbsp/powerpc/qoriq/console/console-config.c | 206 +++++++++ .../powerpc/qoriq/console/uart-bridge-master.c | 197 ++++++++ .../powerpc/qoriq/console/uart-bridge-slave.c | 213 +++++++++ c/src/lib/libbsp/powerpc/qoriq/include/.cvsignore | 2 + c/src/lib/libbsp/powerpc/qoriq/include/bsp.h | 68 +++ .../lib/libbsp/powerpc/qoriq/include/hwreg_vals.h | 0 c/src/lib/libbsp/powerpc/qoriq/include/intercom.h | 127 ++++++ c/src/lib/libbsp/powerpc/qoriq/include/irq.h | 279 ++++++++++++ c/src/lib/libbsp/powerpc/qoriq/include/mmu.h | 100 +++++ c/src/lib/libbsp/powerpc/qoriq/include/qoriq.h | 452 +++++++++++++++++++ c/src/lib/libbsp/powerpc/qoriq/include/tm27.h | 67 +++ .../lib/libbsp/powerpc/qoriq/include/tsec-config.h | 36 ++ .../libbsp/powerpc/qoriq/include/u-boot-config.h | 24 + .../lib/libbsp/powerpc/qoriq/include/uart-bridge.h | 70 +++ c/src/lib/libbsp/powerpc/qoriq/irq/irq.c | 341 ++++++++++++++ .../lib/libbsp/powerpc/qoriq/make/custom/qoriq.inc | 17 + .../powerpc/qoriq/make/custom/qoriq_core_0.cfg | 3 + .../powerpc/qoriq/make/custom/qoriq_core_1.cfg | 3 + .../powerpc/qoriq/make/custom/qoriq_p1020rdb.cfg | 3 + .../lib/libbsp/powerpc/qoriq/network/if_intercom.c | 297 ++++++++++++ c/src/lib/libbsp/powerpc/qoriq/network/network.c | 135 ++++++ c/src/lib/libbsp/powerpc/qoriq/rtc/rtc-config.c | 71 +++ .../libbsp/powerpc/qoriq/shmsupp/intercom-mpci.c | 126 ++++++ c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom.c | 496 +++++++++++++++++++++ c/src/lib/libbsp/powerpc/qoriq/shmsupp/lock.S | 54 +++ c/src/lib/libbsp/powerpc/qoriq/start/start.S | 252 +++++++++++ .../powerpc/qoriq/startup/bsppredriverhook.c | 33 ++ c/src/lib/libbsp/powerpc/qoriq/startup/bspreset.c | 34 ++ c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c | 138 ++++++ .../lib/libbsp/powerpc/qoriq/startup/linkcmds.base | 375 ++++++++++++++++ .../powerpc/qoriq/startup/linkcmds.qoriq_core_0 | 33 ++ .../powerpc/qoriq/startup/linkcmds.qoriq_core_1 | 32 ++ .../powerpc/qoriq/startup/linkcmds.qoriq_p1020rdb | 33 ++ .../lib/libbsp/powerpc/qoriq/startup/mmu-config.c | 124 ++++++ c/src/lib/libbsp/powerpc/qoriq/startup/mmu-tlb1.S | 86 ++++ c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c | 302 +++++++++++++ 43 files changed, 5223 insertions(+) create mode 100644 c/src/lib/libbsp/powerpc/qoriq/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/qoriq/ChangeLog create mode 100644 c/src/lib/libbsp/powerpc/qoriq/Makefile.am create mode 100644 c/src/lib/libbsp/powerpc/qoriq/README create mode 100644 c/src/lib/libbsp/powerpc/qoriq/bsp_specs create mode 100644 c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/configure.ac create mode 100644 c/src/lib/libbsp/powerpc/qoriq/console/console-config.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/.cvsignore create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/bsp.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/hwreg_vals.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/intercom.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/irq.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/mmu.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/qoriq.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/tm27.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/tsec-config.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/u-boot-config.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h create mode 100644 c/src/lib/libbsp/powerpc/qoriq/irq/irq.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq.inc create mode 100644 c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_0.cfg create mode 100644 c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_1.cfg create mode 100644 c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_p1020rdb.cfg create mode 100644 c/src/lib/libbsp/powerpc/qoriq/network/if_intercom.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/network/network.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/rtc/rtc-config.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom-mpci.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/shmsupp/lock.S create mode 100644 c/src/lib/libbsp/powerpc/qoriq/start/start.S create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/bsppredriverhook.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/bspreset.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.base create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_0 create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_1 create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_p1020rdb create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/mmu-tlb1.S create mode 100644 c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c diff --git a/c/src/lib/libbsp/powerpc/qoriq/.cvsignore b/c/src/lib/libbsp/powerpc/qoriq/.cvsignore new file mode 100644 index 0000000000..849c802af6 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/.cvsignore @@ -0,0 +1,8 @@ +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +config.cache +config.log +config.status +configure diff --git a/c/src/lib/libbsp/powerpc/qoriq/ChangeLog b/c/src/lib/libbsp/powerpc/qoriq/ChangeLog new file mode 100644 index 0000000000..733aeb528e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/ChangeLog @@ -0,0 +1,18 @@ +2011-07-21 Sebastian Huber + + PR 1799/bsps + * .cvsignore, ChangeLog, Makefile.am, README, bsp_specs, configure.ac, + clock/clock-config.c, console/console-config.c, + console/uart-bridge-master.c, console/uart-bridge-slave.c, + include/.cvsignore, include/bsp.h, include/hwreg_vals.h, + include/intercom.h, include/irq.h, include/mmu.h, include/qoriq.h, + include/tm27.h, include/tsec-config.h, include/u-boot-config.h, + include/uart-bridge.h, irq/irq.c, make/custom/qoriq.inc, + make/custom/qoriq_core_0.cfg, make/custom/qoriq_core_1.cfg, + make/custom/qoriq_p1020rdb.cfg, network/if_intercom.c, + network/network.c, rtc/rtc-config.c, shmsupp/intercom-mpci.c, + shmsupp/intercom.c, shmsupp/lock.S, start/start.S, + startup/bsppredriverhook.c, startup/bspreset.c, startup/bspstart.c, + startup/linkcmds.base, startup/linkcmds.qoriq_core_0, + startup/linkcmds.qoriq_core_1, startup/linkcmds.qoriq_p1020rdb, + startup/mmu-config.c, startup/mmu-tlb1.S, startup/mmu.c: New files. diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am new file mode 100644 index 0000000000..a8e650d830 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am @@ -0,0 +1,123 @@ +## +## $Id$ +## + +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 += include/tm27.h + +nodist_include_HEADERS = include/bspopts.h +DISTCLEANFILES = include/bspopts.h + +EXTRA_DIST = README + +noinst_PROGRAMS = + +include_HEADERS += ../../shared/include/coverhd.h + +nodist_include_HEADERS += ../../shared/tod.h + +include_bsp_HEADERS = include/irq.h \ + ../../shared/include/irq-generic.h \ + ../../shared/include/irq-info.h \ + ../../shared/include/bootcard.h \ + ../../shared/include/u-boot.h \ + ../../shared/include/utility.h \ + ../shared/include/u-boot-board-info.h \ + ../shared/include/start.h \ + ../shared/include/tictac.h \ + ../shared/include/linker-symbols.h \ + include/hwreg_vals.h \ + include/tsec-config.h \ + include/u-boot-config.h \ + include/mmu.h \ + include/intercom.h \ + include/uart-bridge.h \ + include/qoriq.h + +noinst_LIBRARIES = libbspstart.a +libbspstart_a_SOURCES = start/start.S +project_lib_DATA = start.$(OBJEXT) + +libbspstart_a_SOURCES += ../../powerpc/shared/start/rtems_crti.S +project_lib_DATA += rtems_crti.$(OBJEXT) + +dist_project_lib_DATA += startup/linkcmds \ + startup/linkcmds.base \ + startup/linkcmds.qoriq_core_0 \ + startup/linkcmds.qoriq_core_1 \ + startup/linkcmds.qoriq_p1020rdb + +noinst_LIBRARIES += libbsp.a +libbsp_a_SOURCES = + +# Startup +libbsp_a_SOURCES += ../../shared/bsplibc.c \ + ../../shared/bsppost.c \ + ../../shared/bootcard.c \ + ../../shared/bsppretaskinghook.c \ + ../../shared/sbrk.c \ + ../../shared/gnatinstallhandler.c \ + ../../shared/bspclean.c \ + ../../shared/bspgetworkarea.c \ + ../../shared/src/bsp-uboot-board-info.c \ + ../shared/src/tictac.c \ + ../shared/src/bsp-start-zero.S \ + ../shared/startup/bspidle.c \ + ../shared/uboot_getenv.c \ + ../shared/uboot_dump_bdinfo.c \ + startup/mmu.c \ + startup/mmu-tlb1.S \ + startup/mmu-config.c \ + startup/bsppredriverhook.c \ + startup/bspstart.c \ + startup/bspreset.c + +# Clock +libbsp_a_SOURCES += clock/clock-config.c \ + ../../shared/clockdrv_shell.h + +# IRQ +libbsp_a_SOURCES += irq/irq.c \ + ../../shared/src/irq-generic.c \ + ../../shared/src/irq-legacy.c \ + ../../shared/src/irq-info.c \ + ../../shared/src/irq-shell.c \ + ../../shared/src/irq-server.c + +# Console +libbsp_a_SOURCES += ../../shared/console.c \ + console/uart-bridge-master.c \ + console/uart-bridge-slave.c \ + console/console-config.c + +# RTC +libbsp_a_SOURCES += ../../shared/tod.c \ + rtc/rtc-config.c + +# MPCI +libbsp_a_SOURCES += shmsupp/lock.S \ + shmsupp/intercom.c \ + shmsupp/intercom-mpci.c + +libbsp_a_LIBADD = ../../../libcpu/@RTEMS_CPU@/shared/cpuIdent.rel \ + ../../../libcpu/@RTEMS_CPU@/shared/cache.rel \ + ../../../libcpu/@RTEMS_CPU@/@exceptions@/rtems-cpu.rel \ + ../../../libcpu/@RTEMS_CPU@/@exceptions@/exc_bspsupport.rel \ + ../../../libcpu/@RTEMS_CPU@/e500/mmu.rel + +if HAS_NETWORKING +libbsp_a_SOURCES += network/network.c \ + network/if_intercom.c +libbsp_a_LIBADD += ../../../libcpu/@RTEMS_CPU@/tsec.rel +endif + +include $(srcdir)/preinstall.am +include $(top_srcdir)/../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/qoriq/README b/c/src/lib/libbsp/powerpc/qoriq/README new file mode 100644 index 0000000000..bf8335469d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/README @@ -0,0 +1,5 @@ +Board support package for the Freescale QorIQ platform: + + http://en.wikipedia.org/wiki/QorIQ + +Development board P1020RDB. diff --git a/c/src/lib/libbsp/powerpc/qoriq/bsp_specs b/c/src/lib/libbsp/powerpc/qoriq/bsp_specs new file mode 100644 index 0000000000..92f6c582e8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/bsp_specs @@ -0,0 +1,14 @@ +%rename endfile old_endfile +%rename startfile old_startfile +%rename link old_link + +*startfile: +%{!qrtems: %(old_startfile)} \ +%{!nostdlib: %{qrtems: ecrti%O%s rtems_crti%O%s crtbegin.o%s start.o%s}} + +*endfile: +%{!qrtems: %(old_endfile)} %{qrtems: crtend.o%s ecrtn.o%s} + +*link: +%{!qrtems: %(old_link)} %{qrtems: -dc -dp -u __vectors -N} + diff --git a/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c new file mode 100644 index 0000000000..249d604f74 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/clock/clock-config.c @@ -0,0 +1,128 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief QorIQ clock configuration. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include +#include +#include + +/* This is defined in ../../../shared/clockdrv_shell.h */ +rtems_isr Clock_isr(rtems_vector_number vector); + +static uint32_t qoriq_clock_nanoseconds_per_timer_tick; + +static volatile qoriq_pic_global_timer *const qoriq_clock = + #if QORIQ_CLOCK_TIMER < 4 + &qoriq.pic.gta [QORIQ_CLOCK_TIMER]; + #else + &qoriq.pic.gtb [QORIQ_CLOCK_TIMER - 4]; + #endif + +#define CLOCK_INTERRUPT (QORIQ_IRQ_GT_BASE + QORIQ_CLOCK_TIMER) + +static void qoriq_clock_handler_install(rtems_isr_entry *old_isr) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + *old_isr = NULL; + + sc = qoriq_pic_set_affinity( + CLOCK_INTERRUPT, + ppc_processor_id() + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } + + sc = qoriq_pic_set_priority( + CLOCK_INTERRUPT, + QORIQ_PIC_PRIORITY_LOWEST, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } + + sc = rtems_interrupt_handler_install( + CLOCK_INTERRUPT, + "Clock", + RTEMS_INTERRUPT_UNIQUE, + (rtems_interrupt_handler) Clock_isr, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +static void qoriq_clock_initialize(void) +{ + uint32_t timer_frequency = BSP_bus_frequency / 8; + uint32_t nanoseconds_per_second = 1000000000; + uint32_t interval = (uint32_t) (((uint64_t) timer_frequency + * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000); + + qoriq_clock_nanoseconds_per_timer_tick = + nanoseconds_per_second / timer_frequency; + + qoriq_clock->bcr = GTBCR_COUNT(interval); +} + +static void qoriq_clock_cleanup(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + qoriq_clock->bcr = GTBCR_CI; + + sc = rtems_interrupt_handler_remove( + CLOCK_INTERRUPT, + (rtems_interrupt_handler) Clock_isr, + NULL + ); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred(0xdeadbeef); + } +} + +static uint32_t qoriq_clock_nanoseconds_since_last_tick(void) +{ + uint32_t current = GTCCR_COUNT_GET(qoriq_clock->ccr); + uint32_t base = qoriq_clock->bcr; + + return (base - current) * qoriq_clock_nanoseconds_per_timer_tick; +} + +#define Clock_driver_support_at_tick() +#define Clock_driver_support_initialize_hardware() \ + qoriq_clock_initialize() +#define Clock_driver_support_install_isr(clock_isr, old_isr) \ + qoriq_clock_handler_install(&old_isr) +#define Clock_driver_support_shutdown_hardware() \ + qoriq_clock_cleanup() +#define Clock_driver_nanoseconds_since_last_tick \ + qoriq_clock_nanoseconds_since_last_tick + +/* Include shared source clock driver code */ +#include "../../../shared/clockdrv_shell.h" diff --git a/c/src/lib/libbsp/powerpc/qoriq/configure.ac b/c/src/lib/libbsp/powerpc/qoriq/configure.ac new file mode 100644 index 0000000000..8bd7523c6f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/configure.ac @@ -0,0 +1,98 @@ +## +## $Id$ +## + +AC_PREREQ(2.60) +AC_INIT([rtems-c-src-lib-libbsp-powerpc-qoriq],[_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.10]) +RTEMS_BSP_CONFIGURE + +RTEMS_PROG_CC_FOR_TARGET +RTEMS_CANONICALIZE_TOOLS +RTEMS_PROG_CCAS + +RTEMS_BSPOPTS_SET_DATA_CACHE_ENABLED([*],[1]) +RTEMS_BSPOPTS_HELP_DATA_CACHE_ENABLED + +RTEMS_BSPOPTS_SET_INSTRUCTION_CACHE_ENABLED([*],[1]) +RTEMS_BSPOPTS_HELP_INSTRUCTION_CACHE_ENABLED + +RTEMS_BSPOPTS_SET([BSP_CONSOLE_BAUD],[*],[115200]) +RTEMS_BSPOPTS_HELP([BSP_CONSOLE_BAUD],[default baud for console and other serial devices]) + +RTEMS_BSPOPTS_SET([BSP_USE_UART_INTERRUPTS],[*],[1]) +RTEMS_BSPOPTS_HELP([BSP_USE_UART_INTERRUPTS],[enable usage of interrupts for the UART modules]) + +RTEMS_BSPOPTS_SET([HAS_UBOOT],[*],[1]) +RTEMS_BSPOPTS_HELP([HAS_UBOOT],[enables U-Boot support]) + +RTEMS_BSPOPTS_SET([QORIQ_ETSEC_1_PHY_ADDR],[*],[-1]) +RTEMS_BSPOPTS_HELP([QORIQ_ETSEC_1_PHY_ADDR],[PHY address for eTSEC interface 1]) + +RTEMS_BSPOPTS_SET([QORIQ_ETSEC_2_PHY_ADDR],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_ETSEC_2_PHY_ADDR],[PHY address for eTSEC interface 2]) + +RTEMS_BSPOPTS_SET([QORIQ_ETSEC_3_PHY_ADDR],[*],[1]) +RTEMS_BSPOPTS_HELP([QORIQ_ETSEC_3_PHY_ADDR],[PHY address for eTSEC interface 3]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_0_ENABLE],[qoriq_core_0],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_0_ENABLE],[qoriq_p1020rdb],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_0_ENABLE],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_0_ENABLE],[use 1 to enable UART 0, otherwise use 0]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_1_ENABLE],[qoriq_core_0],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_1_ENABLE],[qoriq_p1020rdb],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_1_ENABLE],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_1_ENABLE],[use 1 to enable UART 1, otherwise use 0]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_MASTER_CORE],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_BRIDGE_MASTER_CORE],[UART to Intercom bridge master core index]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_SLAVE_CORE],[*],[1]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_BRIDGE_SLAVE_CORE],[UART to Intercom bridge slave core index]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_TASK_PRIORITY],[*],[250]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_BRIDGE_TASK_PRIORITY],[UART to Intercom bridge task priority]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_0_ENABLE],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_BRIDGE_0_ENABLE],[use 1 to enable UART 0 to Intercom bridge, otherwise use 0]) + +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_1_ENABLE],[qoriq_core_0],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_1_ENABLE],[qoriq_core_1],[1]) +RTEMS_BSPOPTS_SET([QORIQ_UART_BRIDGE_1_ENABLE],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_UART_BRIDGE_1_ENABLE],[use 1 to enable UART 1 to Intercom bridge, otherwise use 0]) + +RTEMS_BSPOPTS_SET([BSP_DISABLE_UBOOT_WORK_AREA_CONFIG],[*],[1]) +RTEMS_BSPOPTS_HELP([BSP_DISABLE_UBOOT_WORK_AREA_CONFIG],[disable U-Boot work area configuration]) + +RTEMS_BSPOPTS_SET([BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN],[*],[1]) +RTEMS_BSPOPTS_HELP([BSP_INTERRUPT_STACK_AT_WORK_AREA_BEGIN],[indicate that the interrupt stack is at the work area begin]) + +RTEMS_BSPOPTS_SET([QORIQ_INTERCOM_AREA_BEGIN],[*],[0x3000000]) +RTEMS_BSPOPTS_HELP([QORIQ_INTERCOM_AREA_BEGIN],[inter-processor communication area begin]) +RTEMS_BSPOPTS_SET([QORIQ_INTERCOM_AREA_SIZE],[*],[0x1000000]) +RTEMS_BSPOPTS_HELP([QORIQ_INTERCOM_AREA_SIZE],[inter-processor communication area size]) + +RTEMS_BSPOPTS_SET([QORIQ_INITIAL_MSR],[*],[0x02000200]) +RTEMS_BSPOPTS_HELP([QORIQ_INITIAL_MSR],[initial MSR value]) + +RTEMS_BSPOPTS_SET([QORIQ_INITIAL_SPEFSCR],[*],[0x00000000]) +RTEMS_BSPOPTS_HELP([QORIQ_INITIAL_SPEFSCR],[initial SPEFSCR value]) + +RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[qoriq_core_1],[4]) +RTEMS_BSPOPTS_SET([QORIQ_CLOCK_TIMER],[*],[0]) +RTEMS_BSPOPTS_HELP([QORIQ_CLOCK_TIMER],[global timer used for system clock, 0..3 maps to A0..A3, and 4..7 maps to B0..B3]) + +RTEMS_CHECK_NETWORKING +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + +RTEMS_BSP_CLEANUP_OPTIONS(0, 0) +RTEMS_PPC_EXCEPTIONS +RTEMS_BSP_LINKCMDS + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c new file mode 100644 index 0000000000..d8545d42bb --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c @@ -0,0 +1,206 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief Console configuration. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#define CONSOLE_COUNT \ + (QORIQ_UART_0_ENABLE \ + + QORIQ_UART_1_ENABLE \ + + QORIQ_UART_BRIDGE_0_ENABLE \ + + QORIQ_UART_BRIDGE_1_ENABLE) + +#if (QORIQ_UART_0_ENABLE + QORIQ_UART_BRIDGE_0_ENABLE == 2) \ + || (QORIQ_UART_1_ENABLE + QORIQ_UART_BRIDGE_1_ENABLE == 2) + #define BRIDGE_MASTER +#elif QORIQ_UART_BRIDGE_0_ENABLE || QORIQ_UART_BRIDGE_1_ENABLE + #define BRIDGE_SLAVE +#endif + +#ifdef BRIDGE_MASTER + #define BRIDGE_FNS &qoriq_uart_bridge_master + #if QORIQ_UART_BRIDGE_0_ENABLE + static uart_bridge_master_control bridge_0_control = { + .device_path = "/dev/ttyS0", + .type = INTERCOM_TYPE_UART_0, + .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( + bridge_0_control.transmit_fifo + ) + }; + #define BRIDGE_0_CONTROL &bridge_0_control + #endif + #if QORIQ_UART_BRIDGE_1_ENABLE + static uart_bridge_master_control bridge_1_control = { + .device_path = "/dev/ttyS1", + .type = INTERCOM_TYPE_UART_1, + .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( + bridge_1_control.transmit_fifo + ) + }; + #define BRIDGE_1_CONTROL &bridge_1_control + #endif +#endif + +#ifdef BRIDGE_SLAVE + #define BRIDGE_FNS &qoriq_uart_bridge_slave + #if QORIQ_UART_BRIDGE_0_ENABLE + static uart_bridge_slave_control bridge_0_control = { + .type = INTERCOM_TYPE_UART_0, + .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( + bridge_0_control.transmit_fifo + ) + }; + #define BRIDGE_0_CONTROL &bridge_0_control + #endif + #if QORIQ_UART_BRIDGE_1_ENABLE + static uart_bridge_slave_control bridge_1_control = { + .type = INTERCOM_TYPE_UART_1, + .transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY( + bridge_1_control.transmit_fifo + ) + }; + #define BRIDGE_1_CONTROL &bridge_1_control + #endif +#endif + +#ifdef BSP_USE_UART_INTERRUPTS + #define DEVICE_FNS &ns16550_fns +#else + #define DEVICE_FNS &ns16550_fns_polled +#endif + +#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE + static uint8_t get_register(uintptr_t addr, uint8_t i) + { + volatile uint8_t *reg = (uint8_t *) addr; + + return reg [i]; + } + + static void set_register(uintptr_t addr, uint8_t i, uint8_t val) + { + volatile uint8_t *reg = (uint8_t *) addr; + + reg [i] = val; + } +#endif + +unsigned long Console_Port_Count = CONSOLE_COUNT; + +rtems_device_minor_number Console_Port_Minor; + +console_data Console_Port_Data [CONSOLE_COUNT]; + +console_tbl Console_Port_Tbl [CONSOLE_COUNT] = { + #if QORIQ_UART_0_ENABLE + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_NS16550, + .pDeviceFns = DEVICE_FNS, + .deviceProbe = NULL, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *) BSP_CONSOLE_BAUD, + .ulCtrlPort1 = (uintptr_t) &qoriq.uart_0, + .ulCtrlPort2 = 0, + .ulDataPort = (uintptr_t) &qoriq.uart_0, + .getRegister = get_register, + .setRegister = set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 0, + .ulIntVector = QORIQ_IRQ_DUART + }, + #endif + #if QORIQ_UART_1_ENABLE + { + .sDeviceName = "/dev/ttyS1", + .deviceType = SERIAL_NS16550, + .pDeviceFns = DEVICE_FNS, + .deviceProbe = NULL, + .pDeviceFlow = NULL, + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *) BSP_CONSOLE_BAUD, + .ulCtrlPort1 = (uintptr_t) &qoriq.uart_1, + .ulCtrlPort2 = 0, + .ulDataPort = (uintptr_t) &qoriq.uart_1, + .getRegister = get_register, + .setRegister = set_register, + .getData = NULL, + .setData = NULL, + .ulClock = 0, + .ulIntVector = QORIQ_IRQ_DUART + }, + #endif + #if QORIQ_UART_BRIDGE_0_ENABLE + { + #if QORIQ_UART_1_ENABLE + .sDeviceName = "/dev/ttyB0", + #else + .sDeviceName = "/dev/ttyS0", + #endif + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = BRIDGE_FNS, + .pDeviceParams = BRIDGE_0_CONTROL + }, + #endif + #if QORIQ_UART_BRIDGE_1_ENABLE + { + #if QORIQ_UART_1_ENABLE + .sDeviceName = "/dev/ttyB1", + #else + .sDeviceName = "/dev/ttyS1", + #endif + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = BRIDGE_FNS, + .pDeviceParams = BRIDGE_1_CONTROL + } + #endif +}; + +static void output_char(char c) +{ + const console_fns *con = Console_Port_Tbl [Console_Port_Minor].pDeviceFns; + + if (c == '\n') { + con->deviceWritePolled((int) Console_Port_Minor, '\r'); + } + con->deviceWritePolled((int) Console_Port_Minor, c); +} + +BSP_output_char_function_type BSP_output_char = output_char; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c new file mode 100644 index 0000000000..881b617280 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c @@ -0,0 +1,197 @@ +/** + * @file + * + * @ingroup QorIQUartBridge + * + * @brief UART bridge master implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define TRANSMIT_EVENT RTEMS_EVENT_13 + +static void serial_settings(int fd) +{ + struct termios term; + int rv = tcgetattr(fd, &term); + assert(rv == 0); + + term.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); + term.c_oflag &= ~OPOST; + term.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + term.c_cflag &= ~(CSIZE | PARENB); + term.c_cflag |= CS8; + + term.c_cc [VMIN] = 1; + term.c_cc [VTIME] = 1; + + rv = tcsetattr(fd, TCSANOW, &term); + assert(rv == 0); +} + +static void uart_bridge_master_service(intercom_packet *packet, void *arg) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uart_bridge_master_control *control = arg; + + sc = rtems_chain_append_with_notification( + &control->transmit_fifo, + &packet->glue.node, + control->transmit_task, + TRANSMIT_EVENT + ); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void receive_task(rtems_task_argument arg) +{ + uart_bridge_master_control *control = (uart_bridge_master_control *) arg; + intercom_type type = control->type; + + int fd = open(control->device_path, O_RDONLY); + assert(fd >= 0); + + serial_settings(fd); + + while (true) { + intercom_packet *packet = qoriq_intercom_allocate_packet( + type, + INTERCOM_SIZE_64 + ); + ssize_t in = read(fd, packet->data, packet->size - 1); + if (in > 0) { + packet->size = (size_t) in; + qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_SLAVE_CORE, packet); + } else { + qoriq_intercom_free_packet(packet); + } + } +} + +static void transmit_task(rtems_task_argument arg) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uart_bridge_master_control *control = (uart_bridge_master_control *) arg; + rtems_chain_control *fifo = &control->transmit_fifo; + + int fd = open(control->device_path, O_WRONLY); + assert(fd >= 0); + + serial_settings(fd); + + while (true) { + intercom_packet *packet = NULL; + sc = rtems_chain_get_with_wait( + fifo, + TRANSMIT_EVENT, + RTEMS_NO_TIMEOUT, + (rtems_chain_node **) &packet + ); + assert(sc == RTEMS_SUCCESSFUL); + write(fd, packet->data, packet->size); + qoriq_intercom_free_packet(packet); + } +} + +static rtems_id create_task( + char name, + rtems_task_entry entry, + uart_bridge_master_control *control +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_id task = RTEMS_ID_NONE; + char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0); + + sc = rtems_task_create( + rtems_build_name('U', 'B', name, index), + QORIQ_UART_BRIDGE_TASK_PRIORITY, + 0, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start( + task, + entry, + (rtems_task_argument) control + ); + assert(sc == RTEMS_SUCCESSFUL); + + return task; +} + +static void initialize(int minor) +{ + console_tbl *ct = &Console_Port_Tbl [minor]; + uart_bridge_master_control *control = ct->pDeviceParams; + intercom_type type = control->type; + + qoriq_intercom_service_install(type, uart_bridge_master_service, control); + create_task('R', receive_task, control); + control->transmit_task = create_task('T', transmit_task, control); +} + +static int first_open(int major, int minor, void *arg) +{ + return -1; +} + +static int last_close(int major, int minor, void *arg) +{ + return -1; +} + +static int read_polled(int minor) +{ + return -1; +} + +static void write_polled(int minor, char c) +{ + /* Do nothing */ +} + +static int set_attributes(int minor, const struct termios *term) +{ + return -1; +} + +console_fns qoriq_uart_bridge_master = { + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = first_open, + .deviceLastClose = last_close, + .deviceRead = read_polled, + .deviceWrite = NULL, + .deviceInitialize = initialize, + .deviceWritePolled = write_polled, + .deviceSetAttributes = set_attributes, + .deviceOutputUsesInterrupts = false +}; diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c new file mode 100644 index 0000000000..5a3ce39366 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c @@ -0,0 +1,213 @@ +/** + * @file + * + * @ingroup QorIQUartBridge + * + * @brief UART bridge slave implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +#include +#include + +#define TRANSMIT_EVENT RTEMS_EVENT_13 + +static rtems_mode disable_preemption(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_mode prev_mode = 0; + + sc = rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &prev_mode); + assert(sc == RTEMS_SUCCESSFUL); + + return prev_mode; +} + +static void restore_preemption(rtems_mode prev_mode) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_task_mode (prev_mode, RTEMS_PREEMPT_MASK, &prev_mode); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void uart_bridge_slave_service(intercom_packet *packet, void *arg) +{ + uart_bridge_slave_control *control = arg; + struct rtems_termios_tty *tty = control->tty; + + /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */ + rtems_mode prev_mode = disable_preemption(); + + rtems_termios_enqueue_raw_characters(tty, packet->data, (int) packet->size); + qoriq_intercom_free_packet(packet); + + restore_preemption(prev_mode); +} + +static void transmit_task(rtems_task_argument arg) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uart_bridge_slave_control *control = (uart_bridge_slave_control *) arg; + rtems_chain_control *fifo = &control->transmit_fifo; + struct rtems_termios_tty *tty = control->tty; + + while (true) { + intercom_packet *packet = NULL; + sc = rtems_chain_get_with_wait( + fifo, + TRANSMIT_EVENT, + RTEMS_NO_TIMEOUT, + (rtems_chain_node **) &packet + ); + assert(sc == RTEMS_SUCCESSFUL); + + /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */ + rtems_mode prev_mode = disable_preemption(); + + size_t size = packet->size; + qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet); + rtems_termios_dequeue_characters(tty, (int) size); + + restore_preemption(prev_mode); + } +} + +static void create_transmit_task( + uart_bridge_slave_control *control +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_id task = RTEMS_ID_NONE; + char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0); + + sc = rtems_task_create( + rtems_build_name('U', 'B', 'T', index), + QORIQ_UART_BRIDGE_TASK_PRIORITY, + 0, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_task_start( + task, + transmit_task, + (rtems_task_argument) control + ); + assert(sc == RTEMS_SUCCESSFUL); + + control->transmit_task = task; +} + +static void initialize(int minor) +{ + /* Do nothing */ +} + +static int first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; + struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; + console_tbl *ct = &Console_Port_Tbl [minor]; + console_data *cd = &Console_Port_Data [minor]; + uart_bridge_slave_control *control = ct->pDeviceParams; + intercom_type type = control->type; + + control->tty = tty; + cd->termios_data = tty; + rtems_termios_set_initial_baud(tty, 115200); + create_transmit_task(control); + qoriq_intercom_service_install(type, uart_bridge_slave_service, control); + + return 0; +} + +static int last_close(int major, int minor, void *arg) +{ + console_tbl *ct = &Console_Port_Tbl [minor]; + uart_bridge_slave_control *control = ct->pDeviceParams; + + qoriq_intercom_service_remove(control->type); + + return 0; +} + +static ssize_t write_with_interrupts(int minor, const char *buf, size_t len) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + console_tbl *ct = &Console_Port_Tbl [minor]; + uart_bridge_slave_control *control = ct->pDeviceParams; + intercom_packet *packet = qoriq_intercom_allocate_packet( + control->type, + INTERCOM_SIZE_64 + ); + + packet->size = len; + memcpy(packet->data, buf, len); + + /* + * Due to the lovely Termios implementation we have to hand this over to + * another context. + */ + sc = rtems_chain_append_with_notification( + &control->transmit_fifo, + &packet->glue.node, + control->transmit_task, + TRANSMIT_EVENT + ); + assert(sc == RTEMS_SUCCESSFUL); + + return 0; +} + +static void write_polled(int minor, char c) +{ + console_tbl *ct = &Console_Port_Tbl [minor]; + uart_bridge_slave_control *control = ct->pDeviceParams; + intercom_packet *packet = qoriq_intercom_allocate_packet( + control->type, + INTERCOM_SIZE_64 + ); + char *data = packet->data; + data [0] = c; + packet->size = 1; + qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet); +} + +static int set_attribues(int minor, const struct termios *term) +{ + return -1; +} + +console_fns qoriq_uart_bridge_slave = { + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = first_open, + .deviceLastClose = last_close, + .deviceRead = NULL, + .deviceWrite = write_with_interrupts, + .deviceInitialize = initialize, + .deviceWritePolled = write_polled, + .deviceSetAttributes = set_attribues, + .deviceOutputUsesInterrupts = true +}; diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/.cvsignore b/c/src/lib/libbsp/powerpc/qoriq/include/.cvsignore new file mode 100644 index 0000000000..67a49af49a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/.cvsignore @@ -0,0 +1,2 @@ +bspopts.h +bspopts.h.in diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h b/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h new file mode 100644 index 0000000000..fd4853dfef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/bsp.h @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP API. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_BSP_H +#define LIBBSP_POWERPC_QORIQ_BSP_H + +#include + +#ifndef ASM + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define BSP_FEATURE_IRQ_EXTENSION + +extern unsigned BSP_bus_frequency; + +struct rtems_bsdnet_ifconfig; + +int BSP_tsec_attach( + struct rtems_bsdnet_ifconfig *config, + int attaching +); + +int qoriq_if_intercom_attach_detach( + struct rtems_bsdnet_ifconfig *config, + int attaching +); + +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH BSP_tsec_attach +#define RTEMS_BSP_NETWORK_DRIVER_ATTACH4 qoriq_if_intercom_attach_detach + +#define RTEMS_BSP_NETWORK_DRIVER_NAME "tsec1" +#define RTEMS_BSP_NETWORK_DRIVER_NAME2 "tsec2" +#define RTEMS_BSP_NETWORK_DRIVER_NAME3 "tsec3" +#define RTEMS_BSP_NETWORK_DRIVER_NAME4 "intercom1" + +#endif /* ASM */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_BSP_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/hwreg_vals.h b/c/src/lib/libbsp/powerpc/qoriq/include/hwreg_vals.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/intercom.h b/c/src/lib/libbsp/powerpc/qoriq/include/intercom.h new file mode 100644 index 0000000000..15964169f8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/intercom.h @@ -0,0 +1,127 @@ +/** + * @file + * + * @ingroup QorIQInterCom + * + * @brief Inter-Processor Communication API. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_INTERCOM_H +#define LIBBSP_POWERPC_QORIQ_INTERCOM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup QorIQInterCom QorIQ - Inter-Processor Communication Support + * + * @ingroup QorIQ + * + * @brief Inter-processor communication support. + * + * @{ + */ + +uint32_t qoriq_spin_lock(uint32_t *lock); + +void qoriq_spin_unlock(uint32_t *lock, uint32_t msr); + +#define INTERCOM_CORE_COUNT 2 + +#define INTERCOM_SERVICE_COUNT 8 + +typedef enum { + INTERCOM_TYPE_MPCI, + INTERCOM_TYPE_UART_0, + INTERCOM_TYPE_UART_1, + INTERCOM_TYPE_NETWORK, + INTERCOM_TYPE_CUSTOM_0, + INTERCOM_TYPE_CUSTOM_1, + INTERCOM_TYPE_CUSTOM_2, + INTERCOM_TYPE_CUSTOM_3, + INTERCOM_TYPE_CUSTOM_4 +} intercom_type; + +typedef enum { + INTERCOM_SIZE_64 = 0, + INTERCOM_SIZE_512, + INTERCOM_SIZE_2K, + INTERCOM_SIZE_4K +} intercom_size; + +typedef struct intercom_packet { + union { + struct intercom_packet *next; + rtems_chain_node node; + } glue; + intercom_type type_index; + intercom_size size_index; + uint32_t flags; + size_t size; + uint32_t cache_line_alignment [2]; + char data []; +} intercom_packet; + +typedef void (*intercom_service)(intercom_packet *packet, void *arg); + +void qoriq_intercom_init(void); + +void qoriq_intercom_start(void); + +void qoriq_intercom_service_install(intercom_type type, intercom_service service, void *arg); + +void qoriq_intercom_service_remove(intercom_type type); + +intercom_packet *qoriq_intercom_allocate_packet(intercom_type type, intercom_size size); + +void qoriq_intercom_send_packets(int destination_core, intercom_packet *first, intercom_packet *last); + +static inline void qoriq_intercom_send_packet(int destination_core, intercom_packet *packet) +{ + qoriq_intercom_send_packets(destination_core, packet, packet); +} + +void qoriq_intercom_broadcast_packets(intercom_packet *first, intercom_packet *last); + +static inline void qoriq_intercom_broadcast_packet(intercom_packet *packet) +{ + qoriq_intercom_broadcast_packets(packet, packet); +} + +void qoriq_intercom_send(int destination_core, intercom_type type, intercom_size size, const void *buf, size_t n); + +void qoriq_intercom_free_packet(intercom_packet *packet); + +intercom_packet *qoriq_intercom_clone_packet(const intercom_packet *packet); + +#ifdef RTEMS_MULTIPROCESSING + extern rtems_mpci_table qoriq_intercom_mpci; +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_INTERCOM_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/irq.h b/c/src/lib/libbsp/powerpc/qoriq/include/irq.h new file mode 100644 index 0000000000..248bc2b8fb --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/irq.h @@ -0,0 +1,279 @@ +/** + * @file + * + * @ingroup QorIQInterrupt + * + * @brief Interrupt API. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_IRQ_H +#define LIBBSP_POWERPC_QORIQ_IRQ_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup QoriqInterruptP1020 QorIQ - P1020 Internal Interrupt Sources + * + * @ingroup QorIQInterrupt + * + * @brief P1020 internal interrupt sources. + * + * @{ + */ + +#define QORIQ_IRQ_ERROR 0 +#define QORIQ_IRQ_ETSEC_TX_1_GROUP_1 1 +#define QORIQ_IRQ_ETSEC_RX_1_GROUP_1 2 +#define QORIQ_IRQ_ETSEC_ER_1_GROUP_1 8 +#define QORIQ_IRQ_ETSEC_TX_3_GROUP_1 9 +#define QORIQ_IRQ_ETSEC_RX_3_GROUP_1 10 +#define QORIQ_IRQ_ETSEC_ER_3_GROUP_1 11 +#define QORIQ_IRQ_ETSEC_TX_2_GROUP_1 35 +#define QORIQ_IRQ_ETSEC_RX_2_GROUP_1 36 +#define QORIQ_IRQ_TDM 46 +#define QORIQ_IRQ_TDM_ERROR 47 +#define QORIQ_IRQ_ETSEC_ER_2_GROUP_1 51 + +/** @} */ + +/** + * @defgroup QoriqInterruptP2020 QorIQ - P2020 Internal Interrupt Sources + * + * @ingroup QorIQInterrupt + * + * @brief P2020 internal interrupt sources. + * + * @{ + */ + +#define QORIQ_IRQ_L2_CACHE 0 +#define QORIQ_IRQ_ECM 1 +#define QORIQ_IRQ_DDR_CONTROLLER 2 +#define QORIQ_IRQ_PCI_EXPRESS_3 8 +#define QORIQ_IRQ_PCI_EXPRESS_2 9 +#define QORIQ_IRQ_PCI_EXPRESS_1 10 +#define QORIQ_IRQ_SRIO_ERR_WRT_1_2 32 +#define QORIQ_IRQ_SRIO_OUT_DOORBELL_1 33 +#define QORIQ_IRQ_SRIO_IN_DOORBELL_1 34 +#define QORIQ_IRQ_SRIO_OUT_MSG_1 37 +#define QORIQ_IRQ_SRIO_IN_MSG_1 38 +#define QORIQ_IRQ_SRIO_OUT_MSG_2 39 +#define QORIQ_IRQ_SRIO_IN_MSG_2 40 + +/** @} */ + +/** + * @defgroup QoriqInterruptAll QorIQ - Internal Interrupt Sources + * + * @ingroup QorIQInterrupt + * + * @brief Internal interrupt sources. + * + * @{ + */ + +#define QORIQ_IRQ_ELBC 3 +#define QORIQ_IRQ_DMA_CHANNEL_1_1 4 +#define QORIQ_IRQ_DMA_CHANNEL_2_1 5 +#define QORIQ_IRQ_DMA_CHANNEL_3_1 6 +#define QORIQ_IRQ_DMA_CHANNEL_4_1 7 +#define QORIQ_IRQ_USB_1 12 +#define QORIQ_IRQ_ETSEC_TX_1 13 +#define QORIQ_IRQ_ETSEC_RX_1 14 +#define QORIQ_IRQ_ETSEC_TX_3 15 +#define QORIQ_IRQ_ETSEC_RX_3 16 +#define QORIQ_IRQ_ETSEC_ER_3 17 +#define QORIQ_IRQ_ETSEC_ER_1 18 +#define QORIQ_IRQ_ETSEC_TX_2 19 +#define QORIQ_IRQ_ETSEC_RX_2 20 +#define QORIQ_IRQ_ETSEC_ER_2 24 +#define QORIQ_IRQ_DUART 26 +#define QORIQ_IRQ_I2C 27 +#define QORIQ_IRQ_PERFORMANCE_MONITOR 28 +#define QORIQ_IRQ_SECURITY_1 29 +#define QORIQ_IRQ_USB_2 30 +#define QORIQ_IRQ_GPIO 31 +#define QORIQ_IRQ_SECURITY_2 42 +#define QORIQ_IRQ_ESPI 43 +#define QORIQ_IRQ_ETSEC_IEEE_1588_1 52 +#define QORIQ_IRQ_ETSEC_IEEE_1588_2 53 +#define QORIQ_IRQ_ETSEC_IEEE_1588_3 54 +#define QORIQ_IRQ_ESDHC 56 +#define QORIQ_IRQ_DMA_CHANNEL_1_2 60 +#define QORIQ_IRQ_DMA_CHANNEL_2_2 61 +#define QORIQ_IRQ_DMA_CHANNEL_3_2 62 +#define QORIQ_IRQ_DMA_CHANNEL_4_2 63 + +/** @} */ + +/** + * @defgroup QoriqInterruptExternal QorIQ - External Interrupt Sources + * + * @ingroup QorIQInterrupt + * + * @brief External interrupt sources. + * + * @{ + */ + +#define QORIQ_IRQ_EXT_BASE 64 +#define QORIQ_IRQ_EXT_0 (QORIQ_IRQ_EXT_BASE + 0) +#define QORIQ_IRQ_EXT_1 (QORIQ_IRQ_EXT_BASE + 1) +#define QORIQ_IRQ_EXT_2 (QORIQ_IRQ_EXT_BASE + 2) +#define QORIQ_IRQ_EXT_3 (QORIQ_IRQ_EXT_BASE + 3) +#define QORIQ_IRQ_EXT_4 (QORIQ_IRQ_EXT_BASE + 4) +#define QORIQ_IRQ_EXT_5 (QORIQ_IRQ_EXT_BASE + 5) +#define QORIQ_IRQ_EXT_6 (QORIQ_IRQ_EXT_BASE + 6) +#define QORIQ_IRQ_EXT_7 (QORIQ_IRQ_EXT_BASE + 7) +#define QORIQ_IRQ_EXT_8 (QORIQ_IRQ_EXT_BASE + 8) +#define QORIQ_IRQ_EXT_9 (QORIQ_IRQ_EXT_BASE + 9) +#define QORIQ_IRQ_EXT_10 (QORIQ_IRQ_EXT_BASE + 10) +#define QORIQ_IRQ_EXT_11 (QORIQ_IRQ_EXT_BASE + 11) + +/** @} */ + +/** + * @defgroup QoriqInterruptIPI QorIQ - Interprocessor Interrupts + * + * @ingroup QorIQInterrupt + * + * @brief Interprocessor interrupts. + * + * @{ + */ + +#define QORIQ_IRQ_IPI_BASE (QORIQ_IRQ_EXT_11 + 1) +#define QORIQ_IRQ_IPI_0 (QORIQ_IRQ_IPI_BASE + 0) +#define QORIQ_IRQ_IPI_1 (QORIQ_IRQ_IPI_BASE + 1) +#define QORIQ_IRQ_IPI_2 (QORIQ_IRQ_IPI_BASE + 2) +#define QORIQ_IRQ_IPI_3 (QORIQ_IRQ_IPI_BASE + 3) + +/** @} */ + +/** + * @defgroup QoriqInterruptIPI QorIQ - Message Interrupts + * + * @ingroup QorIQInterrupt + * + * @brief Message interrupts. + * + * @{ + */ + +#define QORIQ_IRQ_MI_BASE (QORIQ_IRQ_IPI_3 + 1) +#define QORIQ_IRQ_MI_0 (QORIQ_IRQ_MI_BASE + 0) +#define QORIQ_IRQ_MI_1 (QORIQ_IRQ_MI_BASE + 1) +#define QORIQ_IRQ_MI_2 (QORIQ_IRQ_MI_BASE + 2) +#define QORIQ_IRQ_MI_3 (QORIQ_IRQ_MI_BASE + 3) +#define QORIQ_IRQ_MI_4 (QORIQ_IRQ_MI_BASE + 4) +#define QORIQ_IRQ_MI_5 (QORIQ_IRQ_MI_BASE + 5) +#define QORIQ_IRQ_MI_6 (QORIQ_IRQ_MI_BASE + 6) +#define QORIQ_IRQ_MI_7 (QORIQ_IRQ_MI_BASE + 7) + +/** @} */ + +/** + * @defgroup QoriqInterruptIPI QorIQ - Shared Message Signaled Interrupts + * + * @ingroup QorIQInterrupt + * + * @brief Shared message signaled interrupts. + * + * @{ + */ + +#define QORIQ_IRQ_MSI_BASE (QORIQ_IRQ_MI_7 + 1) +#define QORIQ_IRQ_MSI_0 (QORIQ_IRQ_MSI_BASE + 0) +#define QORIQ_IRQ_MSI_1 (QORIQ_IRQ_MSI_BASE + 1) +#define QORIQ_IRQ_MSI_2 (QORIQ_IRQ_MSI_BASE + 2) +#define QORIQ_IRQ_MSI_3 (QORIQ_IRQ_MSI_BASE + 3) +#define QORIQ_IRQ_MSI_4 (QORIQ_IRQ_MSI_BASE + 4) +#define QORIQ_IRQ_MSI_5 (QORIQ_IRQ_MSI_BASE + 5) +#define QORIQ_IRQ_MSI_6 (QORIQ_IRQ_MSI_BASE + 6) +#define QORIQ_IRQ_MSI_7 (QORIQ_IRQ_MSI_BASE + 7) + +/** @} */ + +/** + * @defgroup QoriqInterruptIPI QorIQ - Global Timer Interrupts + * + * @ingroup QorIQInterrupt + * + * @brief Global Timer interrupts. + * + * @{ + */ + +#define QORIQ_IRQ_GT_BASE (QORIQ_IRQ_MSI_7 + 1) +#define QORIQ_IRQ_GT_A_0 (QORIQ_IRQ_GT_BASE + 0) +#define QORIQ_IRQ_GT_A_1 (QORIQ_IRQ_GT_BASE + 1) +#define QORIQ_IRQ_GT_A_2 (QORIQ_IRQ_GT_BASE + 2) +#define QORIQ_IRQ_GT_A_3 (QORIQ_IRQ_GT_BASE + 3) +#define QORIQ_IRQ_GT_B_0 (QORIQ_IRQ_GT_BASE + 4) +#define QORIQ_IRQ_GT_B_1 (QORIQ_IRQ_GT_BASE + 5) +#define QORIQ_IRQ_GT_B_2 (QORIQ_IRQ_GT_BASE + 6) +#define QORIQ_IRQ_GT_B_3 (QORIQ_IRQ_GT_BASE + 7) + +/** @} */ + +/** + * @defgroup QorIQInterrupt QorIQ - Interrupt Support + * + * @ingroup QorIQ + * + * @brief Interrupt support. + * + * @{ + */ + +#define BSP_INTERRUPT_VECTOR_MIN 0 +#define BSP_INTERRUPT_VECTOR_MAX QORIQ_IRQ_GT_B_3 + +#define QORIQ_PIC_PRIORITY_LOWEST 1 +#define QORIQ_PIC_PRIORITY_HIGHEST 15 +#define QORIQ_PIC_PRIORITY_DISABLED 0 +#define QORIQ_PIC_PRIORITY_INVALID (QORIQ_PIC_PRIORITY_HIGHEST + 1) +#define QORIQ_PIC_PRIORITY_DEFAULT (QORIQ_PIC_PRIORITY_LOWEST + 1) +#define QORIQ_PIC_PRIORITY_IS_VALID(p) \ + ((p) >= QORIQ_PIC_PRIORITY_DISABLED && (p) <= QORIQ_PIC_PRIORITY_HIGHEST) + +rtems_status_code qoriq_pic_set_priority( + rtems_vector_number vector, + int new_priority, + int *old_priority +); + +rtems_status_code qoriq_pic_set_affinity( + rtems_vector_number vector, + uint32_t processor_index +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_IRQ_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/mmu.h b/c/src/lib/libbsp/powerpc/qoriq/include/mmu.h new file mode 100644 index 0000000000..92a241d87d --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/mmu.h @@ -0,0 +1,100 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU API. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_MMU_H +#define LIBBSP_POWERPC_QORIQ_MMU_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup QorIQMMU QorIQ - MMU Support + * + * @ingroup QorIQ + * + * @brief MMU support. + * + * @{ + */ + +#define QORIQ_MMU_ENTRY_COUNT 32 + +#define QORIQ_MMU_MIN_POWER 12 +#define QORIQ_MMU_MAX_POWER 32 +#define QORIQ_MMU_POWER_STEP 2 + +typedef struct { + uint32_t begin; + uint32_t last; + uint32_t mas1; + uint32_t mas2; + uint32_t mas3; +} qoriq_mmu_entry; + +typedef struct { + int count; + qoriq_mmu_entry entries [QORIQ_MMU_ENTRY_COUNT]; +} qoriq_mmu_context; + +void qoriq_mmu_context_init(qoriq_mmu_context *self); + +bool qoriq_mmu_add( + qoriq_mmu_context *self, + uint32_t begin, + uint32_t last, + uint32_t mas1, + uint32_t mas2, + uint32_t mas3 +); + +void qoriq_mmu_partition(qoriq_mmu_context *self, int max_count); + +void qoriq_mmu_write_to_tlb1(qoriq_mmu_context *self, int first_tlb); + +void qoriq_mmu_change_perm(uint32_t test, uint32_t set, uint32_t clear); + +void qoriq_mmu_config(int first_tlb, int scratch_tlb); + +void qoriq_tlb1_write( + int esel, + uint32_t mas1, + uint32_t mas2, + uint32_t mas3, + uint32_t ea, + uint32_t tsize +); + +void qoriq_tlb1_invalidate(int esel); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_MMU_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/qoriq.h b/c/src/lib/libbsp/powerpc/qoriq/include/qoriq.h new file mode 100644 index 0000000000..36c5c20362 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/qoriq.h @@ -0,0 +1,452 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief QorIQ Configuration, Control and Status Registers. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_QORIQ_H +#define LIBBSP_POWERPC_QORIQ_QORIQ_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define QORIQ_FILL(a, b, s) uint8_t reserved_ ## b [b - a - sizeof(s)] +#define QORIQ_RESERVE(a, b) uint8_t reserved_ ## b [b - a] + +typedef struct { + uint32_t ccsrbar; + uint32_t reserved_0; + uint32_t altcbar; + uint32_t reserved_1; + uint32_t altcar; + uint32_t reserved_2 [3]; + uint32_t bptr; +} qoriq_lcc; + +#define CCSRBAR_BASE_ADDR(val) BSP_BFLD32(val, 8, 23) +#define CCSRBAR_BASE_ADDR_GET(reg) BSP_BFLD32GET(reg, 8, 23) +#define CCSRBAR_BASE_ADDR_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 23) + +#define ALTCBAR_BASE_ADDR(val) BSP_BFLD32(val, 8, 23) +#define ALTCBAR_BASE_ADDR_GET(reg) BSP_BFLD32GET(reg, 8, 23) +#define ALTCBAR_BASE_ADDR_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 23) + +#define ALTCAR_EN BSP_BBIT32(0) +#define ALTCAR_TRGT_ID(val) BSP_BFLD32(val, 8, 11) +#define ALTCAR_TRGT_ID_GET(reg) BSP_BFLD32GET(reg, 8, 11) +#define ALTCAR_TRGT_ID_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 11) + +#define BPTR_EN BSP_BBIT32(0) +#define BPTR_BOOT_PAGE(val) BSP_BFLD32(val, 8, 31) +#define BPTR_BOOT_PAGE_GET(reg) BSP_BFLD32GET(reg, 8, 31) +#define BPTR_BOOT_PAGE_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 31) + +typedef struct { + uint32_t bar; + uint32_t reserved_0; + uint32_t ar; + uint32_t reserved_1 [5]; +} qoriq_law; + +#define LAWBAR_BASE_ADDR(val) BSP_BFLD32(val, 8, 31) +#define LAWBAR_BASE_ADDR_GET(reg) BSP_BFLD32GET(reg, 8, 31) +#define LAWBAR_BASE_ADDR_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 31) + +#define LAWAR_EN BSP_BBIT32(0) +#define LAWAR_TRGT(val) BSP_BFLD32(val, 8, 11) +#define LAWAR_TRGT_GET(reg) BSP_BFLD32GET(reg, 8, 11) +#define LAWAR_TRGT_SET(reg, val) BSP_BFLD32SET(reg, val, 8, 11) +#define LAWAR_SIZE(val) BSP_BFLD32(val, 26, 31) +#define LAWAR_SIZE_GET(reg) BSP_BFLD32GET(reg, 26, 31) +#define LAWAR_SIZE_SET(reg, val) BSP_BFLD32SET(reg, val, 26, 31) + +typedef struct { +} qoriq_ecm; + +typedef struct { +} qoriq_ddr_controller; + +typedef struct { +} qoriq_i2c; + +typedef struct { +} qoriq_uart; + +typedef struct { +} qoriq_local_bus; + +typedef struct { +} qoriq_spi; + +typedef struct { +} qoriq_pci_express; + +typedef struct { +} qoriq_gpio; + +typedef struct { +} qoriq_tdm; + +typedef struct { +} qoriq_l2_cache; + +typedef struct { +} qoriq_dma; + +typedef struct { + QORIQ_RESERVE(0x000, 0x100); + uint16_t caplength; + uint16_t hciversion; + uint32_t hcsparams; + uint32_t hccparams; + QORIQ_RESERVE(0x10c, 0x120); + uint32_t dciversion; + uint32_t dccparams; + QORIQ_RESERVE(0x128, 0x140); + uint32_t usbcmd; + uint32_t usbsts; + uint32_t usbintr; + uint32_t frindex; + QORIQ_RESERVE(0x150, 0x154); + union { + uint32_t periodiclistbase; + uint32_t deviceaddr; + } perbase_devaddr; + union { + uint32_t asynclistaddr; + uint32_t addr; + } async_addr; + QORIQ_RESERVE(0x15c, 0x160); + uint32_t burstsize; + uint32_t txfilltuning; + QORIQ_RESERVE(0x168, 0x170); + uint32_t viewport; + QORIQ_RESERVE(0x174, 0x180); + uint32_t configflag; + uint32_t portsc1; + QORIQ_RESERVE(0x188, 0x1a8); + uint32_t usbmode; + uint32_t endptsetupstat; + uint32_t endpointprime; + uint32_t endptflush; + uint32_t endptstatus; + uint32_t endptcomplete; + uint32_t endptctrl[6]; + QORIQ_RESERVE(0x1d8, 0x400); + uint32_t snoop1; + uint32_t snoop2; + uint32_t age_cnt_thresh; + uint32_t pri_ctrl; + uint32_t si_ctrl; + QORIQ_RESERVE(0x414, 0x500); + uint32_t control; +} qoriq_usb; + +typedef struct { +} qoriq_tdm_dma; + +typedef struct { + uint32_t dsaddr; + uint32_t blkattr; + uint32_t cmdarg; + uint32_t xfertyp; + uint32_t cmdrsp0; + uint32_t cmdrsp1; + uint32_t cmdrsp2; + uint32_t cmdrsp3; + uint32_t datport; + uint32_t prsstat; + uint32_t proctl; + uint32_t sysctl; + uint32_t irqstat; + uint32_t irqstaten; + uint32_t irqsigen; + uint32_t autoc12err; + uint32_t hostcapblt; + uint32_t wml; + QORIQ_FILL(0x00044, 0x00050, uint32_t); + uint32_t fevt; + QORIQ_FILL(0x00050, 0x000fc, uint32_t); + uint32_t hostver; + QORIQ_FILL(0x000fc, 0x0040c, uint32_t); + uint32_t dcr; +} qoriq_esdhc; + +typedef struct { +} qoriq_sec; + +typedef struct { + uint32_t reg; + QORIQ_FILL(0x00000, 0x00010, uint32_t); +} qoriq_pic_reg; + +typedef struct { + uint32_t ccr; + QORIQ_FILL(0x00000, 0x00010, uint32_t); + uint32_t bcr; + QORIQ_FILL(0x00010, 0x00020, uint32_t); + uint32_t vpr; + QORIQ_FILL(0x00020, 0x00030, uint32_t); + uint32_t dr; + QORIQ_FILL(0x00030, 0x00040, uint32_t); +} qoriq_pic_global_timer; + +#define GTCCR_TOG BSP_BBIT32(0) +#define GTCCR_COUNT_GET(reg) BSP_BFLD32GET(reg, 1, 31) + +#define GTBCR_CI BSP_BBIT32(0) +#define GTBCR_COUNT(val) BSP_BFLD32(val, 1, 31) +#define GTBCR_COUNT_GET(reg) BSP_BFLD32GET(reg, 1, 31) +#define GTBCR_COUNT_SET(reg, val) BSP_BFLD32SET(reg, val, 1, 31) + +typedef struct { + uint32_t misc; + QORIQ_FILL(0x00000, 0x00010, uint32_t); + uint32_t internal [2]; + QORIQ_FILL(0x00010, 0x00020, uint32_t [2]); +} qoriq_pic_bit_field; + +typedef struct { + uint32_t vpr; + QORIQ_FILL(0x00000, 0x00010, uint32_t); + uint32_t dr; + QORIQ_FILL(0x00010, 0x00020, uint32_t); +} qoriq_pic_src_cfg; + +typedef struct { + QORIQ_RESERVE(0x00000, 0x00040); + qoriq_pic_reg ipidr [4]; + uint32_t ctpr; + QORIQ_FILL(0x00080, 0x00090, uint32_t); + uint32_t whoami; + QORIQ_FILL(0x00090, 0x000a0, uint32_t); + uint32_t iack; + QORIQ_FILL(0x000a0, 0x000b0, uint32_t); + uint32_t eoi; + QORIQ_FILL(0x000b0, 0x01000, uint32_t); +} qoriq_pic_per_cpu; + +typedef struct { + uint32_t brr1; + QORIQ_FILL(0x00000, 0x00010, uint32_t); + uint32_t brr2; + QORIQ_FILL(0x00010, 0x00040, uint32_t); + qoriq_pic_reg ipidr [4]; + uint32_t ctpr; + QORIQ_FILL(0x00080, 0x00090, uint32_t); + uint32_t whoami; + QORIQ_FILL(0x00090, 0x000a0, uint32_t); + uint32_t iack; + QORIQ_FILL(0x000a0, 0x000b0, uint32_t); + uint32_t eoi; + QORIQ_FILL(0x000b0, 0x01000, uint32_t); + uint32_t frr; + QORIQ_FILL(0x01000, 0x01020, uint32_t); + uint32_t gcr; + QORIQ_FILL(0x01020, 0x01080, uint32_t); + uint32_t vir; + QORIQ_FILL(0x01080, 0x01090, uint32_t); + uint32_t pir; + QORIQ_FILL(0x01090, 0x010a0, uint32_t); + qoriq_pic_reg ipivpr [4]; + uint32_t svr; + QORIQ_FILL(0x010e0, 0x010f0, uint32_t); + uint32_t tfrra; + QORIQ_FILL(0x010f0, 0x01100, uint32_t); + qoriq_pic_global_timer gta [4]; + QORIQ_RESERVE(0x01200, 0x01300); + uint32_t tcra; + QORIQ_FILL(0x01300, 0x01308, uint32_t); + uint32_t erqsr; + QORIQ_FILL(0x01308, 0x01310, uint32_t); + qoriq_pic_bit_field irqsr; + qoriq_pic_bit_field cisr; + qoriq_pic_bit_field pm [4]; + QORIQ_RESERVE(0x013d0, 0x01400); + qoriq_pic_reg msgr03 [4]; + QORIQ_RESERVE(0x01440, 0x01500); + uint32_t mer03; + QORIQ_FILL(0x01500, 0x01510, uint32_t); + uint32_t msr03; + QORIQ_FILL(0x01510, 0x01600, uint32_t); + qoriq_pic_reg msir [8]; + QORIQ_RESERVE(0x01680, 0x01720); + uint32_t msisr; + QORIQ_FILL(0x01720, 0x01740, uint32_t); + uint32_t msiir; + QORIQ_FILL(0x01740, 0x020f0, uint32_t); + uint32_t tfrrb; + QORIQ_FILL(0x020f0, 0x02100, uint32_t); + qoriq_pic_global_timer gtb [4]; + QORIQ_RESERVE(0x02200, 0x02300); + uint32_t tcrb; + QORIQ_FILL(0x02300, 0x02400, uint32_t); + qoriq_pic_reg msgr47 [4]; + QORIQ_RESERVE(0x02440, 0x02500); + uint32_t mer47; + QORIQ_FILL(0x02500, 0x02510, uint32_t); + uint32_t msr47; + QORIQ_FILL(0x02510, 0x10000, uint32_t); + qoriq_pic_src_cfg ei [12]; + QORIQ_RESERVE(0x10180, 0x10200); + qoriq_pic_src_cfg ii [64]; + QORIQ_RESERVE(0x10a00, 0x11600); + qoriq_pic_src_cfg mi [8]; + QORIQ_RESERVE(0x11700, 0x11c00); + qoriq_pic_src_cfg msi [8]; + QORIQ_RESERVE(0x11d00, 0x20000); + qoriq_pic_per_cpu per_cpu [2]; +} qoriq_pic; + +#define GTTCR_ROVR(val) BSP_BFLD32(val, 5, 7) +#define GTTCR_ROVR_GET(reg) BSP_BFLD32GET(reg, 5, 7) +#define GTTCR_ROVR_SET(reg, val) BSP_BFLD32SET(reg, val, 5, 7) +#define GTTCR_RTM BSP_BBIT32(15) +#define GTTCR_CLKR(val) BSP_BFLD32(val, 22, 23) +#define GTTCR_CLKR_GET(reg) BSP_BFLD32GET(reg, 22, 23) +#define GTTCR_CLKR_SET(reg, val) BSP_BFLD32SET(reg, val, 22, 23) +#define GTTCR_CASC(val) BSP_BFLD32(val, 29, 31) +#define GTTCR_CASC_GET(reg) BSP_BFLD32GET(reg, 29, 31) +#define GTTCR_CASC_SET(reg, val) BSP_BFLD32SET(reg, val, 29, 31) + +typedef struct { +} qoriq_serial_rapid_io; + +typedef struct { +} qoriq_global_utilities; + +typedef struct { +} qoriq_performance_monitor; + +typedef struct { +} qoriq_debug_watchpoint; + +typedef struct { +} qoriq_serdes; + +typedef struct { +} qoriq_boot_rom; + +typedef struct { + qoriq_lcc lcc; + QORIQ_FILL(0x00000, 0x00c08, qoriq_lcc); + qoriq_law law [12]; + QORIQ_FILL(0x00c08, 0x01000, qoriq_law [12]); + qoriq_ecm ecm; + QORIQ_FILL(0x01000, 0x02000, qoriq_ecm); + qoriq_ddr_controller ddr_controller; + QORIQ_FILL(0x02000, 0x03000, qoriq_ddr_controller); + qoriq_i2c i2c; + QORIQ_FILL(0x03000, 0x04000, qoriq_i2c); + QORIQ_RESERVE(0x04000, 0x04500); + qoriq_uart uart_0; + QORIQ_FILL(0x04500, 0x04600, qoriq_uart); + qoriq_uart uart_1; + QORIQ_FILL(0x04600, 0x04700, qoriq_uart); + QORIQ_RESERVE(0x04700, 0x05000); + qoriq_local_bus local_bus; + QORIQ_FILL(0x05000, 0x06000, qoriq_local_bus); + qoriq_spi spi; + QORIQ_FILL(0x06000, 0x07000, qoriq_spi); + QORIQ_RESERVE(0x07000, 0x08000); + qoriq_pci_express pci_express_3; + QORIQ_FILL(0x08000, 0x09000, qoriq_pci_express); + qoriq_pci_express pci_express_2; + QORIQ_FILL(0x09000, 0x0a000, qoriq_pci_express); + qoriq_pci_express pci_express_1; + QORIQ_FILL(0x0a000, 0x0b000, qoriq_pci_express); + QORIQ_RESERVE(0x0b000, 0x0c000); + qoriq_dma dma_2; + QORIQ_FILL(0x0c000, 0x0d000, qoriq_dma); + QORIQ_RESERVE(0x0d000, 0x0f000); + qoriq_gpio gpio; + QORIQ_FILL(0x0f000, 0x10000, qoriq_gpio); + QORIQ_RESERVE(0x10000, 0x16000); + qoriq_tdm tdm; + QORIQ_FILL(0x16000, 0x17000, qoriq_tdm); + QORIQ_RESERVE(0x17000, 0x20000); + qoriq_l2_cache l2_cache; + QORIQ_FILL(0x20000, 0x21000, qoriq_l2_cache); + qoriq_dma dma_1; + QORIQ_FILL(0x21000, 0x22000, qoriq_dma); + qoriq_usb usb_1; + QORIQ_FILL(0x22000, 0x23000, qoriq_usb); + qoriq_usb usb_2; + QORIQ_FILL(0x23000, 0x24000, qoriq_usb); + tsec_registers tsec_1; + QORIQ_FILL(0x24000, 0x25000, tsec_registers); + tsec_registers tsec_2; + QORIQ_FILL(0x25000, 0x26000, tsec_registers); + tsec_registers tsec_3; + QORIQ_FILL(0x26000, 0x27000, tsec_registers); + QORIQ_RESERVE(0x27000, 0x2c000); + qoriq_tdm_dma tdm_dma; + QORIQ_FILL(0x2c000, 0x2d000, qoriq_tdm_dma); + QORIQ_RESERVE(0x2d000, 0x2e000); + qoriq_esdhc esdhc; + QORIQ_FILL(0x2e000, 0x2f000, qoriq_esdhc); + QORIQ_RESERVE(0x2f000, 0x30000); + qoriq_sec sec; + QORIQ_FILL(0x30000, 0x31000, qoriq_sec); + QORIQ_RESERVE(0x31000, 0x40000); + qoriq_pic pic; + QORIQ_FILL(0x40000, 0x80000, qoriq_pic); + QORIQ_RESERVE(0x80000, 0xb0000); + tsec_registers tsec_1_group_0; + QORIQ_FILL(0xb0000, 0xb1000, tsec_registers); + tsec_registers tsec_2_group_0; + QORIQ_FILL(0xb1000, 0xb2000, tsec_registers); + tsec_registers tsec_3_group_0; + QORIQ_FILL(0xb2000, 0xb3000, tsec_registers); + QORIQ_RESERVE(0xb3000, 0xb4000); + tsec_registers tsec_1_group_1; + QORIQ_FILL(0xb4000, 0xb5000, tsec_registers); + tsec_registers tsec_2_group_1; + QORIQ_FILL(0xb5000, 0xb6000, tsec_registers); + tsec_registers tsec_3_group_1; + QORIQ_FILL(0xb6000, 0xb7000, tsec_registers); + QORIQ_RESERVE(0xb7000, 0xc0000); + qoriq_serial_rapid_io serial_rapid_io; + QORIQ_FILL(0xc0000, 0xe0000, qoriq_serial_rapid_io); + qoriq_global_utilities global_utilities; + QORIQ_FILL(0xe0000, 0xe1000, qoriq_global_utilities); + qoriq_performance_monitor performance_monitor; + QORIQ_FILL(0xe1000, 0xe2000, qoriq_performance_monitor); + qoriq_debug_watchpoint debug_watchpoint; + QORIQ_FILL(0xe2000, 0xe3000, qoriq_debug_watchpoint); + qoriq_serdes serdes; + QORIQ_FILL(0xe3000, 0xe4000, qoriq_serdes); + QORIQ_RESERVE(0xe4000, 0xf0000); + qoriq_boot_rom boot_rom; + QORIQ_FILL(0xf0000, 0x100000, qoriq_boot_rom); +} qoriq_ccsr; + +extern volatile qoriq_ccsr qoriq; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_QORIQ_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/tm27.h b/c/src/lib/libbsp/powerpc/qoriq/include/tm27.h new file mode 100644 index 0000000000..bc38d5f559 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/tm27.h @@ -0,0 +1,67 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief Support file for Timer Test 27. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef _RTEMS_TMTEST27 + #error "This is an RTEMS internal file you must not include directly." +#endif /* _RTEMS_TMTEST27 */ + +#ifndef TMTESTS_TM27_H +#define TMTESTS_TM27_H + +#include +#include + +#define MUST_WAIT_FOR_INTERRUPT 1 + +static rtems_isr_entry tm27_interrupt_handler = NULL; + +static int tm27_exception_handler( BSP_Exception_frame *frame, unsigned number) +{ + tm27_interrupt_handler( 0); + + return 0; +} + +void Install_tm27_vector( rtems_isr_entry handler) +{ + int rv = 0; + + tm27_interrupt_handler = handler; + + rv = ppc_exc_set_handler( ASM_DEC_VECTOR, tm27_exception_handler); + if (rv < 0) { + printk( "Error installing clock interrupt handler!\n"); + } +} + +#define Cause_tm27_intr() \ + ppc_set_decrementer_register( 8) + +#define Clear_tm27_intr() \ + ppc_set_decrementer_register( UINT32_MAX) + +#define Lower_tm27_intr() \ + (void) ppc_external_exceptions_enable() + +#endif /* TMTESTS_TM27_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/tsec-config.h b/c/src/lib/libbsp/powerpc/qoriq/include/tsec-config.h new file mode 100644 index 0000000000..a72b32954f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/tsec-config.h @@ -0,0 +1,36 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief TSEC configuration. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * 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_POWERPC_QORIQ_TSEC_CONFIG_H +#define LIBBSP_POWERPC_QORIQ_TSEC_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define TSEC_COUNT 3 + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_TSEC_CONFIG_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/u-boot-config.h b/c/src/lib/libbsp/powerpc/qoriq/include/u-boot-config.h new file mode 100644 index 0000000000..f2c1d6a6ec --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/u-boot-config.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_U_BOOT_CONFIG_H +#define LIBBSP_POWERPC_QORIQ_U_BOOT_CONFIG_H + +#define CONFIG_E500 +#define CONFIG_HAS_ETH1 +#define CONFIG_HAS_ETH2 + +#endif /* LIBBSP_POWERPC_QORIQ_U_BOOT_CONFIG_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h new file mode 100644 index 0000000000..af59fc9a7a --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h @@ -0,0 +1,70 @@ +/** + * @file + * + * @ingroup QorIQUartBridge + * + * @brief UART to Intercom bridge API. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H +#define LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup QorIQUartBridge QorIQ - UART to Intercom Bridge Support + * + * @ingroup QorIQ + * + * @brief UART to Intercom bridge support. + * + * @{ + */ + +typedef struct { + const char *device_path; + intercom_type type; + rtems_id transmit_task; + rtems_chain_control transmit_fifo; +} uart_bridge_master_control; + +typedef struct { + struct rtems_termios_tty *tty; + intercom_type type; + rtems_id transmit_task; + rtems_chain_control transmit_fifo; +} uart_bridge_slave_control; + +extern console_fns qoriq_uart_bridge_master; + +extern console_fns qoriq_uart_bridge_slave; + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c b/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c new file mode 100644 index 0000000000..fb1d52b040 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c @@ -0,0 +1,341 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief Interrupt implementation. + */ + +/* + * Copyright (c) 2010, 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define VPR_MSK BSP_BBIT32(0) +#define VPR_A BSP_BBIT32(1) +#define VPR_P BSP_BBIT32(8) +#define VPR_S BSP_BBIT32(9) +#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15) +#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15) +#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15) +#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31) +#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31) +#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31) + +#define GCR_RST BSP_BBIT32(0) +#define GCR_M BSP_BBIT32(2) + +#define SPURIOUS 0xffff + +static const uint16_t vpr_and_dr_offsets [] = { + [0] = 0x10200 >> 4, + [1] = 0x10220 >> 4, + [2] = 0x10240 >> 4, + [3] = 0x10260 >> 4, + [4] = 0x10280 >> 4, + [5] = 0x102a0 >> 4, + [6] = 0x102c0 >> 4, + [7] = 0x102e0 >> 4, + [8] = 0x10300 >> 4, + [9] = 0x10320 >> 4, + [10] = 0x10340 >> 4, + [11] = 0x10360 >> 4, + [12] = 0x10380 >> 4, + [13] = 0x103a0 >> 4, + [14] = 0x103c0 >> 4, + [15] = 0x103e0 >> 4, + [16] = 0x10400 >> 4, + [17] = 0x10420 >> 4, + [18] = 0x10440 >> 4, + [19] = 0x10460 >> 4, + [20] = 0x10480 >> 4, + [21] = 0x104a0 >> 4, + [22] = 0x104c0 >> 4, + [23] = 0x104e0 >> 4, + [24] = 0x10500 >> 4, + [25] = 0x10520 >> 4, + [26] = 0x10540 >> 4, + [27] = 0x10560 >> 4, + [28] = 0x10580 >> 4, + [29] = 0x105a0 >> 4, + [30] = 0x105c0 >> 4, + [31] = 0x105e0 >> 4, + [32] = 0x10600 >> 4, + [33] = 0x10620 >> 4, + [34] = 0x10640 >> 4, + [35] = 0x10660 >> 4, + [36] = 0x10680 >> 4, + [37] = 0x106a0 >> 4, + [38] = 0x106c0 >> 4, + [39] = 0x106e0 >> 4, + [40] = 0x10700 >> 4, + [41] = 0x10720 >> 4, + [42] = 0x10740 >> 4, + [43] = 0x10760 >> 4, + [44] = 0x10780 >> 4, + [45] = 0x107a0 >> 4, + [46] = 0x107c0 >> 4, + [47] = 0x107e0 >> 4, + [48] = 0x10800 >> 4, + [49] = 0x10820 >> 4, + [50] = 0x10840 >> 4, + [51] = 0x10860 >> 4, + [52] = 0x10880 >> 4, + [53] = 0x108a0 >> 4, + [54] = 0x108c0 >> 4, + [55] = 0x108e0 >> 4, + [56] = 0x10900 >> 4, + [57] = 0x10920 >> 4, + [58] = 0x10940 >> 4, + [59] = 0x10960 >> 4, + [60] = 0x10980 >> 4, + [61] = 0x109a0 >> 4, + [62] = 0x109c0 >> 4, + [63] = 0x109e0 >> 4, + [QORIQ_IRQ_EXT_0] = 0x10000 >> 4, + [QORIQ_IRQ_EXT_1] = 0x10020 >> 4, + [QORIQ_IRQ_EXT_2] = 0x10040 >> 4, + [QORIQ_IRQ_EXT_3] = 0x10060 >> 4, + [QORIQ_IRQ_EXT_4] = 0x10080 >> 4, + [QORIQ_IRQ_EXT_5] = 0x100a0 >> 4, + [QORIQ_IRQ_EXT_6] = 0x100c0 >> 4, + [QORIQ_IRQ_EXT_7] = 0x100e0 >> 4, + [QORIQ_IRQ_EXT_8] = 0x10100 >> 4, + [QORIQ_IRQ_EXT_9] = 0x10120 >> 4, + [QORIQ_IRQ_EXT_10] = 0x10140 >> 4, + [QORIQ_IRQ_EXT_11] = 0x10160 >> 4, + [QORIQ_IRQ_IPI_0] = 0x010a0 >> 4, + [QORIQ_IRQ_IPI_1] = 0x010b0 >> 4, + [QORIQ_IRQ_IPI_2] = 0x010c0 >> 4, + [QORIQ_IRQ_IPI_3] = 0x010d0 >> 4, + [QORIQ_IRQ_MI_0] = 0x11600 >> 4, + [QORIQ_IRQ_MI_1] = 0x11620 >> 4, + [QORIQ_IRQ_MI_2] = 0x11640 >> 4, + [QORIQ_IRQ_MI_3] = 0x11660 >> 4, + [QORIQ_IRQ_MI_4] = 0x11680 >> 4, + [QORIQ_IRQ_MI_5] = 0x116a0 >> 4, + [QORIQ_IRQ_MI_6] = 0x116c0 >> 4, + [QORIQ_IRQ_MI_7] = 0x116e0 >> 4, + [QORIQ_IRQ_MSI_0] = 0x11c00 >> 4, + [QORIQ_IRQ_MSI_1] = 0x11c20 >> 4, + [QORIQ_IRQ_MSI_2] = 0x11c40 >> 4, + [QORIQ_IRQ_MSI_3] = 0x11c60 >> 4, + [QORIQ_IRQ_MSI_4] = 0x11c80 >> 4, + [QORIQ_IRQ_MSI_5] = 0x11ca0 >> 4, + [QORIQ_IRQ_MSI_6] = 0x11cc0 >> 4, + [QORIQ_IRQ_MSI_7] = 0x11ce0 >> 4, + [QORIQ_IRQ_GT_A_0] = 0x01120 >> 4, + [QORIQ_IRQ_GT_A_1] = 0x01160 >> 4, + [QORIQ_IRQ_GT_A_2] = 0x011a0 >> 4, + [QORIQ_IRQ_GT_A_3] = 0x011e0 >> 4, + [QORIQ_IRQ_GT_B_0] = 0x02120 >> 4, + [QORIQ_IRQ_GT_B_1] = 0x02160 >> 4, + [QORIQ_IRQ_GT_B_2] = 0x021a0 >> 4, + [QORIQ_IRQ_GT_B_3] = 0x021e0 >> 4 +}; + +rtems_status_code qoriq_pic_set_priority( + rtems_vector_number vector, + int new_priority, + int *old_priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t old_vpr = 0; + + if (bsp_interrupt_is_valid_vector(vector)) { + int offs = vpr_and_dr_offsets [vector] << 2; + volatile uint32_t *vpr = (volatile uint32_t *) &qoriq.pic + offs; + + if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + old_vpr = *vpr; + *vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority); + rtems_interrupt_enable(level); + } else if (new_priority < 0) { + old_vpr = *vpr; + } else { + sc = RTEMS_INVALID_PRIORITY; + } + } else { + sc = RTEMS_INVALID_ID; + } + + if (old_priority != NULL) { + *old_priority = (int) VPR_PRIORITY_GET(old_vpr); + } + + return sc; +} + +rtems_status_code qoriq_pic_set_affinity( + rtems_vector_number vector, + uint32_t processor_index +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + if (processor_index <= 1) { + int offs = (vpr_and_dr_offsets [vector] << 2) + 4; + volatile uint32_t *dr = (volatile uint32_t *) &qoriq.pic + offs; + + *dr = BSP_BIT32(processor_index); + } else { + sc = RTEMS_INVALID_NUMBER; + } + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +static rtems_status_code pic_vector_enable(rtems_vector_number vector, uint32_t msk) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + int offs = vpr_and_dr_offsets [vector] << 2; + volatile uint32_t *vpr = (volatile uint32_t *) &qoriq.pic + offs; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + *vpr = (*vpr & ~VPR_MSK) | msk; + rtems_interrupt_enable(level); + } + + return sc; +} + +rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + return pic_vector_enable(vector, 0); +} + +rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + return pic_vector_enable(vector, VPR_MSK); +} + +static int qoriq_external_exception_handler(BSP_Exception_frame *frame, unsigned exception_number) +{ + rtems_vector_number vector = qoriq.pic.iack; + + if (vector != SPURIOUS) { + uint32_t msr = ppc_external_exceptions_enable(); + + bsp_interrupt_handler_dispatch(vector); + + ppc_external_exceptions_disable(msr); + + qoriq.pic.eoi = 0; + qoriq.pic.whoami; + } else { + bsp_interrupt_handler_default(vector); + } + + return 0; +} + +static bool pic_is_ipi(rtems_vector_number vector) +{ + return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3; +} + +static void pic_reset(void) +{ + qoriq.pic.gcr = GCR_RST; + while ((qoriq.pic.gcr & GCR_RST) != 0) { + /* Wait */ + } +} + +static void pic_global_timer_init(void) +{ + int i = 0; + + qoriq.pic.tcra = 0; + qoriq.pic.tcrb = 0; + + for (i = 0; i < 4; ++i) { + qoriq.pic.gta [0].bcr = GTBCR_CI; + qoriq.pic.gtb [0].bcr = GTBCR_CI; + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + rtems_vector_number i = 0; + uint32_t processor_id = ppc_processor_id(); + + if (ppc_exc_set_handler(ASM_EXT_VECTOR, qoriq_external_exception_handler)) { + return RTEMS_IO_ERROR; + } + + if (processor_id == 0) { + /* Core 0 must do the basic initialization */ + + pic_reset(); + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + volatile uint32_t *base = (volatile uint32_t *) &qoriq.pic; + int offs = vpr_and_dr_offsets [i] << 2; + volatile uint32_t *vpr = base + offs; + + *vpr = VPR_MSK | VPR_P | VPR_PRIORITY(1) | VPR_VECTOR(i); + + if (!pic_is_ipi(i)) { + volatile uint32_t *dr = base + offs + 4; + + *dr = 0x1; + } + } + + qoriq.pic.mer03 = 0xf; + qoriq.pic.mer47 = 0xf; + qoriq.pic.svr = SPURIOUS; + qoriq.pic.gcr = GCR_M; + + pic_global_timer_init(); + } + + qoriq.pic.ctpr = 0; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + qoriq.pic.iack; + qoriq.pic.eoi = 0; + qoriq.pic.whoami; + } + + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("Spurious interrupt: 0x%08x\n", vector); +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq.inc b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq.inc new file mode 100644 index 0000000000..dd266f6291 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq.inc @@ -0,0 +1,17 @@ +# +# Shared base config file for QorIQ BSPs +# +# $Id$ +# + +include $(RTEMS_ROOT)/make/custom/default.cfg + +RTEMS_CPU = powerpc + +RTEMS_CPU_MODEL = qoriq + +CPU_CFLAGS = -mcpu=8540 -meabi -msdata -fno-common -mfloat-gprs=double -mstrict-align \ + -D__ppc_generic \ + -Wextra -Wno-unused -Wpointer-arith -Wcast-qual -Wconversion -Wmissing-prototypes + +CFLAGS_OPTIMIZE_V = -Os -g diff --git a/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_0.cfg b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_0.cfg new file mode 100644 index 0000000000..8ce12d84a3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_0.cfg @@ -0,0 +1,3 @@ +# Config file for QorIQ Core 0 + +include $(RTEMS_ROOT)/make/custom/qoriq.inc diff --git a/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_1.cfg b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_1.cfg new file mode 100644 index 0000000000..ee7eadd947 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_core_1.cfg @@ -0,0 +1,3 @@ +# Config file for QorIQ Core 1 + +include $(RTEMS_ROOT)/make/custom/qoriq.inc diff --git a/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_p1020rdb.cfg b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_p1020rdb.cfg new file mode 100644 index 0000000000..66199d5a00 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/make/custom/qoriq_p1020rdb.cfg @@ -0,0 +1,3 @@ +# Config file for P1020RDB + +include $(RTEMS_ROOT)/make/custom/qoriq.inc diff --git a/c/src/lib/libbsp/powerpc/qoriq/network/if_intercom.c b/c/src/lib/libbsp/powerpc/qoriq/network/if_intercom.c new file mode 100644 index 0000000000..da9414f1b3 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/network/if_intercom.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1 +#define __BSD_VISIBLE 1 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +typedef struct { + struct arpcom arpcom; + int destination_core; + intercom_packet *packet; + unsigned transmitted_frames; + unsigned received_frames; +} if_intercom_control; + +static if_intercom_control if_intercom; + +static struct mbuf *new_mbuf(struct ifnet *ifp, bool wait) +{ + struct mbuf *m = NULL; + int mw = wait ? M_WAIT : M_DONTWAIT; + + MGETHDR(m, mw, MT_DATA); + if (m != NULL) { + MCLGET(m, mw); + if ((m->m_flags & M_EXT) != 0) { + m->m_pkthdr.rcvif = ifp; + + return m; + } else { + m_free(m); + } + } + + return NULL; +} + +static void if_intercom_service(intercom_packet *packet, void *arg) +{ + rtems_bsdnet_semaphore_obtain(); + + if_intercom_control *self = arg; + struct ifnet *ifp = &self->arpcom.ac_if; + struct mbuf *m = new_mbuf(ifp, true); + + memcpy(mtod(m, void *), packet->data, packet->size); + + /* Ethernet header */ + struct ether_header *eh = mtod(m, struct ether_header *); + + /* Discard Ethernet header and CRC */ + int sz = (int) packet->size - ETHER_HDR_LEN; + + /* Update mbuf */ + m->m_len = sz; + m->m_pkthdr.len = sz; + m->m_data = mtod(m, char *) + ETHER_HDR_LEN; + + /* Hand over */ + ether_input(ifp, eh, m); + + ++self->received_frames; + qoriq_intercom_free_packet(packet); + + rtems_bsdnet_semaphore_release(); +} + +static intercom_packet *allocate_packet(void) +{ + intercom_packet *packet = qoriq_intercom_allocate_packet( + INTERCOM_TYPE_NETWORK, + INTERCOM_SIZE_2K + ); + + packet->size = 0; + + return packet; +} + +static struct mbuf *get_next_fragment(struct ifnet *ifp, struct mbuf *m) +{ + struct mbuf *n = NULL; + int size = 0; + + while (true) { + if (m == NULL) { + /* Dequeue first fragment of the next frame */ + IF_DEQUEUE(&ifp->if_snd, m); + + /* Empty queue? */ + if (m == NULL) { + return m; + } + } + + /* Get fragment size */ + size = m->m_len; + + if (size > 0) { + /* Now we have a not empty fragment */ + break; + } else { + /* Discard empty fragments */ + m = m_free(m); + } + } + + /* Discard empty successive fragments */ + n = m->m_next; + while (n != NULL && n->m_len <= 0) { + n = m_free(n); + } + m->m_next = n; + + return m; +} + +static void if_intercom_start(struct ifnet *ifp) +{ + if_intercom_control *self = ifp->if_softc; + int destination_core = self->destination_core; + intercom_packet *packet = self->packet; + size_t size = packet->size; + char *data = packet->data + size; + struct mbuf *m = NULL; + + while ((m = get_next_fragment(ifp, m)) != NULL) { + size_t fragment_size = (size_t) m->m_len; + size_t new_size = size + fragment_size; + + assert(new_size <= 2048); + + memcpy(data, mtod(m, void *), fragment_size); + data += fragment_size; + size = new_size; + + m = m_free(m); + + /* Last fragment of frame ? */ + if (m == NULL) { + packet->size = size; + qoriq_intercom_send_packet(destination_core, packet); + ++self->transmitted_frames; + packet = allocate_packet(); + data = packet->data; + size = 0; + } + } + + packet->size = size; + self->packet = packet; + ifp->if_flags &= ~IFF_OACTIVE; +} + +static void if_intercom_init(void *arg) +{ + if_intercom_control *self = arg; + uint32_t self_core = ppc_processor_id(); + + self->destination_core = self_core == 0 ? 1 : 0; + self->packet = allocate_packet(); + + qoriq_intercom_service_install( + INTERCOM_TYPE_NETWORK, + if_intercom_service, + self + ); +} + +static void show_stats(if_intercom_control *self) +{ + printf("transmitted frames: %u\n", self->transmitted_frames); + printf("received frames: %u\n", self->received_frames); +} + +static int if_intercom_ioctl( + struct ifnet *ifp, + ioctl_command_t command, + caddr_t data +) +{ + if_intercom_control *self = ifp->if_softc; + int rv = 0; + + switch (command) { + case SIOCGIFADDR: + case SIOCSIFADDR: + ether_ioctl(ifp, command, data); + break; + case SIOCSIFFLAGS: + if (ifp->if_flags & IFF_RUNNING) { + /* TODO: off */ + } + if (ifp->if_flags & IFF_UP) { + ifp->if_flags |= IFF_RUNNING; + /* TODO: init */ + } + break; + case SIO_RTEMS_SHOW_STATS: + show_stats(self); + break; + default: + rv = EINVAL; + break; + } + + return rv; +} + +static void if_intercom_watchdog(struct ifnet *ifp) +{ + ifp->if_timer = 0; +} + +static int if_intercom_attach(struct rtems_bsdnet_ifconfig *config) +{ + if_intercom_control *self = &if_intercom; + struct ifnet *ifp = &self->arpcom.ac_if; + char *unit_name = NULL; + int unit_index = rtems_bsdnet_parse_driver_name(config, &unit_name); + + assert(unit_index == 1); + assert(strcmp(unit_name, "intercom") == 0); + assert(config->hardware_address != NULL); + + memcpy(self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); + + /* Set interface data */ + ifp->if_softc = self; + ifp->if_unit = (short) unit_index; + ifp->if_name = unit_name; + ifp->if_mtu = (config->mtu > 0) ? (u_long) config->mtu : ETHERMTU; + ifp->if_init = if_intercom_init; + ifp->if_ioctl = if_intercom_ioctl; + ifp->if_start = if_intercom_start; + ifp->if_output = ether_output; + ifp->if_watchdog = if_intercom_watchdog; + ifp->if_flags = config->ignore_broadcast ? 0 : IFF_BROADCAST; + ifp->if_snd.ifq_maxlen = ifqmaxlen; + ifp->if_timer = 0; + + /* Attach the interface */ + if_attach(ifp); + ether_ifattach(ifp); + + return 1; +} + +int qoriq_if_intercom_attach_detach( + struct rtems_bsdnet_ifconfig *config, + int attaching +) +{ + if (attaching) { + return if_intercom_attach(config); + } else { + assert(0); + } +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/network/network.c b/c/src/lib/libbsp/powerpc/qoriq/network/network.c new file mode 100644 index 0000000000..db04809429 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/network/network.c @@ -0,0 +1,135 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief Network configuration. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1 +#define __BSD_VISIBLE 1 + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +int BSP_tsec_attach( + struct rtems_bsdnet_ifconfig *config, + int attaching +) +{ + char *unit_name = NULL; + int unit_number = rtems_bsdnet_parse_driver_name(config, &unit_name); + tsec_config tsec_cfg; + bool has_groups = false; + + memset(&tsec_cfg, 0, sizeof(tsec_cfg)); + config->drv_ctrl = &tsec_cfg; + + if (unit_number <= 0 || unit_number > TSEC_COUNT) { + return 0; + } + + switch (ppc_fsl_system_version_sid(ppc_fsl_system_version())) { + /* P1010 and P1020 */ + case 0x0ec: + case 0x0e4: + case 0x0ed: + case 0x0e5: + has_groups = true; + break; + } + + if (config->hardware_address == NULL) { + #ifdef HAS_UBOOT + switch (unit_number) { + case 1: + config->hardware_address = bsp_uboot_board_info.bi_enetaddr; + break; + case 2: + config->hardware_address = bsp_uboot_board_info.bi_enet1addr; + break; + case 3: + config->hardware_address = bsp_uboot_board_info.bi_enet2addr; + break; + default: + assert(0); + break; + } + #else + assert(0); + #endif + } + + switch (unit_number) { + case 1: + if (has_groups) { + tsec_cfg.reg_ptr = &qoriq.tsec_1_group_0; + } else { + tsec_cfg.reg_ptr = &qoriq.tsec_1; + } + tsec_cfg.mdio_ptr = &qoriq.tsec_1; + tsec_cfg.irq_num_tx = QORIQ_IRQ_ETSEC_TX_1; + tsec_cfg.irq_num_rx = QORIQ_IRQ_ETSEC_RX_1; + tsec_cfg.irq_num_err = QORIQ_IRQ_ETSEC_ER_1; + tsec_cfg.phy_default = QORIQ_ETSEC_1_PHY_ADDR; + break; + case 2: + if (has_groups) { + tsec_cfg.reg_ptr = &qoriq.tsec_2_group_0; + } else { + tsec_cfg.reg_ptr = &qoriq.tsec_2; + } + tsec_cfg.mdio_ptr = &qoriq.tsec_1; + tsec_cfg.irq_num_tx = QORIQ_IRQ_ETSEC_TX_2; + tsec_cfg.irq_num_rx = QORIQ_IRQ_ETSEC_RX_2; + tsec_cfg.irq_num_err = QORIQ_IRQ_ETSEC_ER_2; + tsec_cfg.phy_default = QORIQ_ETSEC_2_PHY_ADDR; + break; + case 3: + if (has_groups) { + tsec_cfg.reg_ptr = &qoriq.tsec_3_group_0; + } else { + tsec_cfg.reg_ptr = &qoriq.tsec_3; + } + tsec_cfg.mdio_ptr = &qoriq.tsec_1; + tsec_cfg.irq_num_tx = QORIQ_IRQ_ETSEC_TX_3; + tsec_cfg.irq_num_rx = QORIQ_IRQ_ETSEC_RX_3; + tsec_cfg.irq_num_err = QORIQ_IRQ_ETSEC_ER_3; + tsec_cfg.phy_default = QORIQ_ETSEC_3_PHY_ADDR; + break; + default: + assert(0); + break; + } + + tsec_cfg.unit_number = unit_number; + tsec_cfg.unit_name = unit_name; + + return tsec_driver_attach_detach(config, attaching); +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/rtc/rtc-config.c b/c/src/lib/libbsp/powerpc/qoriq/rtc/rtc-config.c new file mode 100644 index 0000000000..4e9cac1ea5 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/rtc/rtc-config.c @@ -0,0 +1,71 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief RTC configuration. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#define RTC_COUNT 1 + +static void qoriq_rtc_initialize(int minor) +{ + /* FIXME */ +} + +static int qoriq_rtc_get_time(int minor, rtems_time_of_day *tod) +{ + return -1; +} + +static int qoriq_rtc_set_time(int minor, const rtems_time_of_day *tod) +{ + return -1; +} + +static bool qoriq_rtc_probe(int minor) +{ + return false; +} + +const rtc_fns qoriq_rtc_ops = { + .deviceInitialize = qoriq_rtc_initialize, + .deviceGetTime = qoriq_rtc_get_time, + .deviceSetTime = qoriq_rtc_set_time +}; + +size_t RTC_Count = RTC_COUNT; + +rtems_device_minor_number RTC_Minor = 0; + +rtc_tbl RTC_Table [RTC_COUNT] = { + { + .sDeviceName = "/dev/rtc", + .deviceType = RTC_CUSTOM, + .pDeviceFns = &qoriq_rtc_ops, + .deviceProbe = qoriq_rtc_probe, + .pDeviceParams = NULL, + .ulCtrlPort1 = 0, + .ulDataPort = 0, + .getRegister = NULL, + .setRegister = NULL + } +}; diff --git a/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom-mpci.c b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom-mpci.c new file mode 100644 index 0000000000..8dfb81d427 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom-mpci.c @@ -0,0 +1,126 @@ +/** + * @file + * + * @ingroup QorIQInterCom + * + * @brief Inter-Processor Communication implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +#include + +#ifdef RTEMS_MULTIPROCESSING + +typedef struct { + intercom_packet *head; + intercom_packet *tail; +} mpic_fifo; + +static mpic_fifo fifo; + +static void mpci_service(intercom_packet *packet, void *arg) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + packet->glue.next = NULL; + if (fifo.head != NULL) { + fifo.tail->glue.next = packet; + } else { + fifo.head = packet; + } + fifo.tail = packet; + rtems_interrupt_enable(level); + + rtems_multiprocessing_announce(); +} + +static void mpci_init(void) +{ + qoriq_intercom_service_install(INTERCOM_TYPE_MPCI, mpci_service, NULL); +} + +static intercom_packet *packet_of_prefix(rtems_packet_prefix *prefix) +{ + return (intercom_packet *) ((char *) prefix - sizeof(intercom_packet)); +} + +static rtems_packet_prefix *prefix_of_packet(intercom_packet *packet) +{ + return (rtems_packet_prefix *) packet->data; +} + +static void mpci_get_packet(rtems_packet_prefix **prefix_ptr) +{ + intercom_packet *packet = qoriq_intercom_allocate_packet( + INTERCOM_TYPE_MPCI, + INTERCOM_SIZE_512 + ); + *prefix_ptr = prefix_of_packet(packet); +} + +static void mpci_return_packet(rtems_packet_prefix *prefix) +{ + intercom_packet *packet = packet_of_prefix(prefix); + + qoriq_intercom_free_packet(packet); +} + +static void mpci_send_packet(uint32_t destination_node, rtems_packet_prefix *prefix) +{ + intercom_packet *packet = packet_of_prefix(prefix); + if (destination_node != MPCI_ALL_NODES) { + qoriq_intercom_send_packet((int) destination_node - 1, packet); + } else { + uint32_t self = ppc_processor_id(); + int other = self == 0 ? 1 : 0; + + qoriq_intercom_send_packet(other, packet); + } +} + +static void mpci_receive_packet(rtems_packet_prefix **prefix_ptr) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + intercom_packet *packet = fifo.head; + if (packet != NULL) { + fifo.head = packet->glue.next; + *prefix_ptr = prefix_of_packet(packet); + } else { + *prefix_ptr = NULL; + } + rtems_interrupt_enable(level); +} + +rtems_mpci_table qoriq_intercom_mpci = { + .default_timeout = UINT32_MAX, + .maximum_packet_size = 512 - sizeof(rtems_packet_prefix), + .initialization = mpci_init, + .get_packet = mpci_get_packet, + .return_packet = mpci_return_packet, + .send_packet = mpci_send_packet, + .receive_packet = mpci_receive_packet +}; + +#endif /* RTEMS_MULTIPROCESSING */ diff --git a/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom.c b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom.c new file mode 100644 index 0000000000..e1420997ba --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/intercom.c @@ -0,0 +1,496 @@ +/** + * @file + * + * @ingroup QorIQInterCom + * + * @brief Inter-Processor Communication implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#define INTERCOM_EVENT_IPI RTEMS_EVENT_13 +#define INTERCOM_EVENT_WAKE_UP RTEMS_EVENT_14 + +#define PACKET_SIZE_COUNT 4 + +#define ONE_CORE(core) (1U << (core)) +#define ALL_CORES ((1U << INTERCOM_CORE_COUNT) - 1U) +#define OTHER_CORES(core) (ALL_CORES & ~ONE_CORE(core)) + +#define IPI_INDEX 0 + +typedef struct consumer { + struct consumer *next; + rtems_id task; +} consumer; + +typedef struct { + consumer *head; + uint32_t cache_line_alignment [7]; +} consumer_list; + +typedef struct { + uint32_t lock; + intercom_packet *head; + size_t size; + uint32_t cores_to_notify; + uint32_t cache_line_alignment [4]; + consumer_list waiting_consumers [INTERCOM_CORE_COUNT]; +} free_list; + +typedef struct { + uint32_t lock; + intercom_packet *head; + intercom_packet *tail; + uint32_t cache_line_alignment [5]; +} core_fifo; + +typedef struct { + free_list free_lists [PACKET_SIZE_COUNT]; + core_fifo core_fifos [INTERCOM_CORE_COUNT]; + intercom_service services [INTERCOM_CORE_COUNT][INTERCOM_SERVICE_COUNT]; + void *service_args [INTERCOM_CORE_COUNT][INTERCOM_SERVICE_COUNT]; + uint32_t ready_lock; + uint32_t ready; + uint32_t cache_line_alignment [6]; +} control; + +static control *const intercom = (control *) QORIQ_INTERCOM_AREA_BEGIN; + +static const size_t packet_sizes [PACKET_SIZE_COUNT] = { + 64, + 512, + 2048, + 4096 +}; + +static void send_event(rtems_id task, rtems_event_set event) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + sc = rtems_event_send(task, event); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void wait_for_event(rtems_event_set in) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_event_set out; + + sc = rtems_event_receive( + in, + RTEMS_EVENT_ALL | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &out + ); + assert(sc == RTEMS_SUCCESSFUL); +} + +static void intercom_handler(void *arg) +{ + rtems_id task = (rtems_id) arg; + send_event(task, INTERCOM_EVENT_IPI); +} + +static void notify_core_by_index(int core) +{ + uint32_t self = ppc_processor_id(); + qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg = ONE_CORE(core); +} + +static void notify_cores(uint32_t cores) +{ + uint32_t self = ppc_processor_id(); + qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg = cores; +} + +void qoriq_intercom_free_packet(intercom_packet *packet) +{ + free_list *list = &intercom->free_lists [packet->size_index]; + + uint32_t msr = qoriq_spin_lock(&list->lock); + intercom_packet *first = list->head; + list->head = packet; + packet->glue.next = first; + uint32_t cores = list->cores_to_notify; + if (cores != 0) { + list->cores_to_notify = 0; + notify_cores(cores); + } + qoriq_spin_unlock(&list->lock, msr); +} + +static void default_service(intercom_packet *packet, void *arg) +{ + qoriq_intercom_free_packet(packet); +} + +static void process_free_lists(free_list *free_lists, uint32_t self) +{ + int i = 0; + + for (i = 0; i < PACKET_SIZE_COUNT; ++i) { + free_list *list = &free_lists [i]; + + uint32_t msr = qoriq_spin_lock(&list->lock); + consumer *waiting_consumer = list->waiting_consumers [self].head; + list->waiting_consumers [self].head = NULL; + qoriq_spin_unlock(&list->lock, msr); + + while (waiting_consumer != NULL) { + send_event(waiting_consumer->task, INTERCOM_EVENT_WAKE_UP); + waiting_consumer = waiting_consumer->next; + } + } +} + +static void process_core_fifo(core_fifo *fifo, intercom_service *services, void **service_args) +{ + uint32_t msr = qoriq_spin_lock(&fifo->lock); + intercom_packet *packet = fifo->head; + fifo->head = NULL; + qoriq_spin_unlock(&fifo->lock, msr); + + while (packet != NULL) { + intercom_packet *current = packet; + intercom_type type_index = current->type_index; + packet = current->glue.next; + (*services [type_index])(current, service_args [type_index]); + } +} + +static void intercom_task(rtems_task_argument arg) +{ + uint32_t self = ppc_processor_id(); + free_list *free_lists = &intercom->free_lists [0]; + intercom_service *services = &intercom->services [self][0]; + void **service_args = &intercom->service_args [self][0]; + core_fifo *fifo = &intercom->core_fifos [self]; + + while (true) { + process_free_lists(free_lists, self); + process_core_fifo(fifo, services, service_args); + wait_for_event(INTERCOM_EVENT_IPI); + } +} + +static intercom_packet *free_list_and_packet_init( + free_list *list, + size_t count, + intercom_packet *current, + intercom_size size_index, + size_t size +) +{ + intercom_packet *last = current; + size_t inc = 1 + size / sizeof(*current); + size_t i = 0; + + assert(count > 0); + assert(size % sizeof(*current) == 0); + + list->size = size; + list->head = current; + for (i = 0; i < count; ++i) { + intercom_packet *next = current + inc; + current->glue.next = next; + current->size_index = size_index; + last = current; + current = next; + } + last->glue.next = NULL; + + return current; +} + +static void basic_init(void) +{ + char *begin = (char *) QORIQ_INTERCOM_AREA_BEGIN; + size_t size = QORIQ_INTERCOM_AREA_SIZE; + int i = 0; + + memset(begin, 0, size); + + assert(size % packet_sizes [PACKET_SIZE_COUNT - 1] == 0); + + /* Calculate data area sizes */ + size_t data_sizes [PACKET_SIZE_COUNT]; + data_sizes [PACKET_SIZE_COUNT - 1] = size / 2; + for (i = PACKET_SIZE_COUNT - 2; i > 0; --i) { + data_sizes [i] = data_sizes [i + 1] / 2; + } + data_sizes [i] = data_sizes [i + 1]; + + /* Calculate packet counts */ + size_t packet_counts [PACKET_SIZE_COUNT]; + size_t count = 0; + for (i = 1; i < PACKET_SIZE_COUNT; ++i) { + packet_counts [i] = data_sizes [i] / packet_sizes [i]; + count += packet_counts [i]; + } + packet_counts [0] = (data_sizes [0] - sizeof(control) - count * sizeof(intercom_packet)) + / (sizeof(intercom_packet) + packet_sizes [0]); + + /* Initialize free lists and packets */ + intercom_packet *packet = (intercom_packet *) (begin + sizeof(control)); + for (i = 0; i < PACKET_SIZE_COUNT; ++i) { + packet = free_list_and_packet_init( + &intercom->free_lists [i], + packet_counts [i], + packet, + i, + packet_sizes [i] + ); + } + + rtems_cache_flush_multiple_data_lines(begin, size); + ppc_synchronize_data(); +} + +static void services_init(uint32_t self) +{ + int i = 0; + + for (i = 0; i < INTERCOM_SERVICE_COUNT; ++i) { + if (intercom->services [self][i] == NULL) { + intercom->services [self][i] = default_service; + } + } +} + +void qoriq_intercom_init(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_id task = RTEMS_ID_NONE; + uint32_t self = ppc_processor_id(); + + sc = rtems_task_create( + rtems_build_name('I', 'C', 'O', 'M'), + 10, + 0, + RTEMS_DEFAULT_MODES, + RTEMS_DEFAULT_ATTRIBUTES, + &task + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = qoriq_pic_set_priority( + QORIQ_IRQ_IPI_0, + QORIQ_PIC_PRIORITY_LOWEST, + NULL + ); + assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_interrupt_handler_install( + QORIQ_IRQ_IPI_0, + "INTERCOM", + RTEMS_INTERRUPT_UNIQUE, + intercom_handler, + (void *) task + ); + assert(sc == RTEMS_SUCCESSFUL); + + if (self == 0) { + basic_init(); + } + + services_init(self); + + sc = rtems_task_start(task, intercom_task, 0); + assert(sc == RTEMS_SUCCESSFUL); +} + +void qoriq_intercom_start(void) +{ + uint32_t self = ppc_processor_id(); + uint32_t ready = 0; + + while (ready != ALL_CORES) { + uint32_t msr = qoriq_spin_lock(&intercom->ready_lock); + ready = intercom->ready; + intercom->ready = ready | ONE_CORE(self); + qoriq_spin_unlock(&intercom->ready_lock, msr); + } +} + +static intercom_packet *allocate(intercom_type type, free_list *list) +{ + uint32_t self = ppc_processor_id(); + intercom_packet *packet = NULL; + consumer poor = { + .task = rtems_task_self() + }; + + while (packet == NULL) { + uint32_t msr = qoriq_spin_lock(&list->lock); + packet = list->head; + if (packet != NULL) { + list->head = packet->glue.next; + } else { + consumer *first = list->waiting_consumers [self].head; + list->waiting_consumers [self].head = &poor; + poor.next = first; + if (first == NULL) { + list->cores_to_notify |= ONE_CORE(self); + } + } + qoriq_spin_unlock(&list->lock, msr); + + if (packet == NULL) { + wait_for_event(INTERCOM_EVENT_WAKE_UP); + } + } + + packet->glue.next = NULL; + packet->type_index = type; + packet->flags = 0; + packet->size = list->size; + + return packet; +} + +intercom_packet *qoriq_intercom_allocate_packet(intercom_type type, intercom_size size) +{ + assert((unsigned) type < INTERCOM_SERVICE_COUNT); + assert((unsigned) size < PACKET_SIZE_COUNT); + + return allocate(type, &intercom->free_lists [size]); +} + +void qoriq_intercom_send_packets(int destination_core, intercom_packet *first, intercom_packet *last) +{ + assert(destination_core >= 0); + assert(destination_core < INTERCOM_CORE_COUNT); + + core_fifo *fifo = &intercom->core_fifos [destination_core]; + + uint32_t msr = qoriq_spin_lock(&fifo->lock); + last->glue.next = NULL; + if (fifo->head != NULL) { + fifo->tail->glue.next = first; + } else { + fifo->head = first; + notify_core_by_index(destination_core); + } + fifo->tail = last; + qoriq_spin_unlock(&fifo->lock, msr); +} + +void qoriq_intercom_broadcast_packets(intercom_packet *first, intercom_packet *last) +{ + int i = 0; + + for (i = 1; i < INTERCOM_CORE_COUNT; ++i) { + intercom_packet *clone_first = NULL; + intercom_packet *clone_last = NULL; + + intercom_packet *current = first; + while (current != NULL) { + intercom_packet *clone = qoriq_intercom_clone_packet(current); + if (clone_first == NULL) { + clone_first = clone; + } + if (clone_last != NULL) { + clone_last->glue.next = clone; + } + clone_last = clone; + current = current->glue.next; + } + + qoriq_intercom_send_packets(i, clone_first, clone_last); + } + + qoriq_intercom_send_packets(0, first, last); +} + +void qoriq_intercom_send(int destination_core, intercom_type type, intercom_size size, const void *buf, size_t n) +{ + assert((unsigned) size < PACKET_SIZE_COUNT); + + size_t remaining = n; + size_t packet_size = packet_sizes [size]; + const char *src = buf; + intercom_packet *first = NULL; + intercom_packet *last = NULL; + + do { + intercom_packet *packet = qoriq_intercom_allocate_packet( + type, + size + ); + if (first == NULL) { + first = packet; + } + if (last != NULL) { + last->glue.next = packet; + } + last = packet; + size_t current_size = remaining < packet_size ? remaining : packet_size; + remaining -= current_size; + packet->size = current_size; + const char *current = src; + src += current_size; + memcpy(packet->data, current, current_size); + } while (remaining > 0); + + qoriq_intercom_send_packets(destination_core, first, last); +} + +void qoriq_intercom_service_install(intercom_type type, intercom_service service, void *arg) +{ + assert((unsigned) type < INTERCOM_SERVICE_COUNT); + + uint32_t self = ppc_processor_id(); + intercom->service_args [self][type] = arg; + ppc_enforce_in_order_execution_of_io(); + intercom->services [self][type] = service; +} + +void qoriq_intercom_service_remove(intercom_type type) +{ + assert((unsigned) type < INTERCOM_SERVICE_COUNT); + + uint32_t self = ppc_processor_id(); + intercom->services [self][type] = default_service; + ppc_enforce_in_order_execution_of_io(); + intercom->service_args [self][type] = NULL; +} + +intercom_packet *qoriq_intercom_clone_packet(const intercom_packet *packet) +{ + intercom_packet *clone = qoriq_intercom_allocate_packet( + packet->type_index, + packet->size_index + ); + + clone->size = packet->size; + memcpy(clone->data, packet->data, clone->size); + + return clone; +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/shmsupp/lock.S b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/lock.S new file mode 100644 index 0000000000..d41a59fdd0 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/shmsupp/lock.S @@ -0,0 +1,54 @@ +/** + * @file + * + * @ingroup QorIQInterCom + * + * @brief qoriq_spin_lock() and qoriq_spin_unlock() implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + + .global qoriq_spin_lock + .global qoriq_spin_unlock + +qoriq_spin_lock: + li r0, 1 + mfmsr r4 + GET_INTERRUPT_MASK r5 + andc r5, r4, r5 + b 2f +1: + mtmsr r4 +2: + lwarx r6, r0, r3 + cmpwi r6, 0 + bne 2b + mtmsr r5 + stwcx. r0, r0, r3 + bne 1b + isync + mr r3, r4 + blr + +qoriq_spin_unlock: + msync + li r0, 0 + stw r0, 0(r3) + mtmsr r4 + blr diff --git a/c/src/lib/libbsp/powerpc/qoriq/start/start.S b/c/src/lib/libbsp/powerpc/qoriq/start/start.S new file mode 100644 index 0000000000..59be1c23f8 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/start/start.S @@ -0,0 +1,252 @@ +/** + * @file + * + * @ingroup qoriq + * + * @brief BSP start. + */ + +/* + * Copyright (c) 2010-2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +#include + +#define FIRST_TLB 0 +#define SCRATCH_TLB 15 +#define INITIAL_MSR r14 +#define UBOOT_BOARD_INFO r15 + + .globl _start + .globl bsp_exc_vector_base + + .section ".bsp_start_text", "ax" + +_start: + /* Reset time base */ + li r0, 0 + mtspr TBWU, r0 + mtspr TBWL, r0 + +#ifdef HAS_UBOOT + mr UBOOT_BOARD_INFO, r3 +#endif /* HAS_UBOOT */ + + /* Initial MMU setup */ + bl qoriq_tlb1_ts_0_only + li r3, SCRATCH_TLB + li r4, FSL_EIS_MAS1_TS + li r5, FSL_EIS_MAS2_I + li r6, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW | FSL_EIS_MAS3_SX + li r7, 0 + li r8, 11 + bl qoriq_tlb1_write + + /* MSR initialization */ + LWI INITIAL_MSR, QORIQ_INITIAL_MSR + ori r0, INITIAL_MSR, MSR_IS | MSR_DS + mtmsr r0 + + /* SPEFSCR initialization */ + LWI r0, QORIQ_INITIAL_SPEFSCR + mtspr FSL_EIS_SPEFSCR, r0 + + /* Initialize start stack */ + LWI r1, start_stack_end + subi r1, r1, 16 + li r0, 0 + stw r0, 0(r1) + + /* Copy fast text */ + LWI r3, bsp_section_fast_text_begin + LWI r4, bsp_section_fast_text_load_begin + LWI r5, bsp_section_fast_text_size + bl copy + + /* Copy read-only data */ + LWI r3, bsp_section_rodata_begin + LWI r4, bsp_section_rodata_load_begin + LWI r5, bsp_section_rodata_size + bl copy + + /* Copy fast data */ + LWI r3, bsp_section_fast_data_begin + LWI r4, bsp_section_fast_data_load_begin + LWI r5, bsp_section_fast_data_size + bl copy + + /* Copy data */ + LWI r3, bsp_section_data_begin + LWI r4, bsp_section_data_load_begin + LWI r5, bsp_section_data_size + bl copy + + /* NULL pointer access protection (only core 0 has to do this) */ + mfspr r3, BOOKE_PIR + cmpwi r3, 0 + bne null_area_setup_done + LWI r3, bsp_section_start_begin + srawi r3, r3, 2 + mtctr r3 + li r3, -4 + LWI r4, 0x44000002 +null_area_setup_loop: + stwu r4, 4(r3) + bdnz null_area_setup_loop +null_area_setup_done: + + /* Configure MMU */ + li r3, FIRST_TLB + li r4, SCRATCH_TLB + bl qoriq_mmu_config + mtmsr INITIAL_MSR + li r3, SCRATCH_TLB + bl qoriq_tlb1_invalidate + + /* Clear SBSS */ + LWI r3, bsp_section_sbss_begin + LWI r4, bsp_section_sbss_size + bl bsp_start_zero + + /* Clear BSS */ + LWI r3, bsp_section_bss_begin + LWI r4, bsp_section_bss_size + bl bsp_start_zero + +#ifdef HAS_UBOOT + li r3, SCRATCH_TLB + li r4, 0 + li r5, 0 + li r6, FSL_EIS_MAS3_SR + mr r7, UBOOT_BOARD_INFO + li r8, 1 + bl qoriq_tlb1_write + mr r3, UBOOT_BOARD_INFO + bl bsp_uboot_copy_board_info + li r3, SCRATCH_TLB + bl qoriq_tlb1_invalidate +#endif /* HAS_UBOOT */ + + /* Set up EABI and SYSV environment */ + bl __eabi + + /* Clear command line */ + li r3, 0 + + bl boot_card + +twiddle: + b twiddle + +copy: + cmpw r3, r4 + beqlr + b memcpy + + /* Exception vector prologues area */ + .section ".bsp_start_text", "ax" + .align 4 +bsp_exc_vector_base: + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32767 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 2 + b ppc_exc_wrap_nopush_e500_mchk + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 3 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 4 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1) + stw r4, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1) + li r4, -32763 + b ppc_exc_wrap_async_normal + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 6 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 7 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 8 + b ppc_exc_wrap_nopush_std +system_call: + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 12 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 24 + b ppc_exc_wrap_nopush_std + stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1) + stw r4, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1) + li r4, -32752 + b ppc_exc_wrap_async_normal + stwu r1, -PPC_EXC_MINIMAL_FRAME_SIZE(r1) + stw r4, PPC_EXC_VECTOR_PROLOGUE_OFFSET(r1) + li r4, -32749 + b ppc_exc_wrap_async_normal + stw r1, ppc_exc_lock_crit@sdarel(r13) + stw r4, ppc_exc_vector_register_crit@sdarel(r13) + li r4, -32748 + b ppc_exc_wrap_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 18 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 17 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 13 + b ppc_exc_wrap_nopush_bookE_crit + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 10 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 25 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 26 + b ppc_exc_wrap_nopush_std + stwu r1, -EXC_GENERIC_SIZE(r1) + stw r4, GPR4_OFFSET(r1) + li r4, 15 + b ppc_exc_wrap_nopush_std + + /* Start stack area */ + .section ".bsp_rwextra", "aw", @nobits + .align 4 + .space 4096 +start_stack_end: diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bsppredriverhook.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bsppredriverhook.c new file mode 100644 index 0000000000..80084b78bf --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bsppredriverhook.c @@ -0,0 +1,33 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief bsp_predriver_hook() implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include + +void bsp_predriver_hook(void) +{ + #ifdef RTEMS_MULTIPROCESSING + qoriq_intercom_init(); + #endif +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspreset.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspreset.c new file mode 100644 index 0000000000..24c2c5291f --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspreset.c @@ -0,0 +1,34 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP reset. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + +#include + +void bsp_reset(void) +{ + while (true) { + /* Do nothing */ + } +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c new file mode 100644 index 0000000000..9333ff791e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c @@ -0,0 +1,138 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief BSP startup. + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +LINKER_SYMBOL(bsp_exc_vector_base); + +/* Configuration parameters for console driver, ... */ +unsigned int BSP_bus_frequency; + +/* Configuration parameters for clock driver, ... */ +uint32_t bsp_clicks_per_usec; + +void BSP_panic(char *s) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + printk("%s PANIC %s\n", rtems_get_version_string(), s); + + while (1) { + /* Do nothing */ + } +} + +void _BSP_Fatal_error(unsigned n) +{ + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + printk("%s PANIC ERROR %u\n", rtems_get_version_string(), n); + + while (1) { + /* Do nothing */ + } +} + +void bsp_start(void) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + unsigned long i = 0; + + ppc_cpu_id_t myCpu; + ppc_cpu_revision_t myCpuRevision; + + /* + * 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(); + + /* Initialize some device driver parameters */ + #ifdef HAS_UBOOT + BSP_bus_frequency = bsp_uboot_board_info.bi_busfreq; + bsp_clicks_per_usec = bsp_uboot_board_info.bi_busfreq / 8000000; + #endif /* HAS_UBOOT */ + + /* Initialize some console parameters */ + for (i = 0; i < Console_Port_Count; ++i) { + console_tbl *ct = &Console_Port_Tbl [i]; + + ct->ulClock = BSP_bus_frequency; + + #ifdef HAS_UBOOT + if (ct->deviceType == SERIAL_NS16550) { + ct->pDeviceParams = (void *) bsp_uboot_board_info.bi_baudrate; + } + #endif + } + + /* Disable decrementer */ + PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE); + + /* Initialize exception handler */ + ppc_exc_vector_base = (uint32_t) bsp_exc_vector_base; + sc = ppc_exc_initialize( + PPC_INTERRUPT_DISABLE_MASK_DEFAULT, + (uintptr_t) bsp_section_work_begin, + Configuration.interrupt_stack_size + ); + if (sc != RTEMS_SUCCESSFUL) { + BSP_panic("cannot initialize exceptions"); + } + + /* Now it is possible to make the code execute only */ + qoriq_mmu_change_perm( + FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SX, + FSL_EIS_MAS3_SX, + FSL_EIS_MAS3_SR + ); + + /* Initalize interrupt support */ + sc = bsp_interrupt_initialize(); + if (sc != RTEMS_SUCCESSFUL) { + BSP_panic("cannot intitialize interrupts\n"); + } + + /* Disable boot page translation */ + qoriq.lcc.bptr &= ~BPTR_EN; +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.base b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.base new file mode 100644 index 0000000000..25fc1dcd39 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.base @@ -0,0 +1,375 @@ +/** + * @file + * + * @ingroup bsp_linker + * + * @brief Linker command base file. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * 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. + */ + +OUTPUT_FORMAT ("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") + +OUTPUT_ARCH (powerpc:common) + +ENTRY (_start) + +/* + * Global symbols that may be defined externally + */ + +bsp_section_xbarrier_align = DEFINED (bsp_section_xbarrier_align) ? bsp_section_xbarrier_align : 1; +bsp_section_robarrier_align = DEFINED (bsp_section_robarrier_align) ? bsp_section_robarrier_align : 1; +bsp_section_rwbarrier_align = DEFINED (bsp_section_rwbarrier_align) ? bsp_section_rwbarrier_align : 1; + +SECTIONS { + .start : { + bsp_section_start_begin = .; + KEEP (*(.bsp_start_text)) + KEEP (*(.bsp_start_data)) + bsp_section_start_end = .; + } > REGION_START AT > REGION_START + bsp_section_start_size = bsp_section_start_end - bsp_section_start_begin; + + .xbarrier : { + . = ALIGN (bsp_section_xbarrier_align); + } > REGION_TEXT + + .fast_text : { + bsp_section_fast_text_begin = .; + *(.bsp_fast_text) + bsp_section_fast_text_end = .; + } > REGION_FAST_TEXT AT > REGION_FAST_TEXT_LOAD + bsp_section_fast_text_size = bsp_section_fast_text_end - bsp_section_fast_text_begin; + bsp_section_fast_text_load_begin = LOADADDR (.fast_text); + bsp_section_fast_text_load_end = bsp_section_fast_text_load_begin + bsp_section_fast_text_size; + + .text : { + bsp_section_text_begin = .; + *(.text.unlikely .text.*_unlikely) + *(.text .stub .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + *(.glink) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .init : { + KEEP (*(.init)) + } > REGION_TEXT AT > REGION_TEXT_LOAD + .fini : { + PROVIDE (_fini = .); + KEEP (*(.fini)) + bsp_section_text_end = .; + } > REGION_TEXT AT > REGION_TEXT_LOAD + bsp_section_text_size = bsp_section_text_end - bsp_section_text_begin; + bsp_section_text_load_begin = LOADADDR (.text); + bsp_section_text_load_end = bsp_section_text_load_begin + bsp_section_text_size; + + .robarrier : { + . = ALIGN (bsp_section_robarrier_align); + } > REGION_RODATA + + .rodata : { + bsp_section_rodata_begin = .; + *(.rodata .rodata.* .gnu.linkonce.r.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rodata1 : { + *(.rodata1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sdata2 : { + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .sbss2 : { + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame_hdr : { + *(.eh_frame_hdr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .eh_frame : { + KEEP (*(.eh_frame)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gcc_except_table : { + *(.gcc_except_table .gcc_except_table.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tdata : { + *(.tdata .tdata.* .gnu.linkonce.td.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .tbss : { + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .preinit_array : { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .init_array : { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fini_array : { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT(.fini_array.*))) + KEEP (*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .ctors : { + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dtors : { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .jcr : { + KEEP (*(.jcr)) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .data.rel.ro : { + *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .fixup : { + *(.fixup) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynamic : { + *(.dynamic) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got1 : { + *(.got1) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got2 : { + *(.got2) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .got : { + *(.got) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .plt : { + *(.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .iplt : { + *(.iplt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .interp : { + *(.interp) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .note.gnu.build-id : { + *(.note.gnu.build-id) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .hash : { + *(.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.hash : { + *(.gnu.hash) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynsym : { + *(.dynsym) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .dynstr : { + *(.dynstr) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version : { + *(.gnu.version) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_d : { + *(.gnu.version_d) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .gnu.version_r : { + *(.gnu.version_r) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.dyn : { + *(.rela.init) + *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) + *(.rela.fini) + *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) + *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) + *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) + *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) + *(.rela.ctors) + *(.rela.dtors) + *(.rela.got) + *(.rela.got1) + *(.rela.got2) + *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) + *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) + *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) + *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) + *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) + PROVIDE_HIDDEN (__rel_iplt_start = .); + PROVIDE_HIDDEN (__rel_iplt_end = .); + PROVIDE_HIDDEN (__rela_iplt_start = .); + *(.rela.iplt) + PROVIDE_HIDDEN (__rela_iplt_end = .); + } > REGION_RODATA AT > REGION_RODATA_LOAD + .rela.plt : { + *(.rela.plt) + } > REGION_RODATA AT > REGION_RODATA_LOAD + .robsdsets : { + /* Special FreeBSD linker set sections */ + __start_set_sysctl_set = .; + *(set_sysctl_*); + __stop_set_sysctl_set = .; + *(set_domain_*); + *(set_pseudo_*); + _bsd__start_set_modmetadata_set = .; + *(_bsd_set_modmetadata_set); + _bsd__stop_set_modmetadata_set = .; + _bsd__start_set_sysctl_set = .; + *(_bsd_set_sysctl_set); + _bsd__stop_set_sysctl_set = .; + + bsp_section_rodata_end = .; + } > REGION_RODATA AT > REGION_RODATA_LOAD + bsp_section_rodata_size = bsp_section_rodata_end - bsp_section_rodata_begin; + bsp_section_rodata_load_begin = LOADADDR (.rodata); + bsp_section_rodata_load_end = bsp_section_rodata_load_begin + bsp_section_rodata_size; + + .rwbarrier : { + . = ALIGN (bsp_section_rwbarrier_align); + } > REGION_DATA + + .fast_data : { + bsp_section_fast_data_begin = .; + *(.bsp_fast_data) + bsp_section_fast_data_end = .; + } > REGION_FAST_DATA AT > REGION_FAST_DATA_LOAD + bsp_section_fast_data_size = bsp_section_fast_data_end - bsp_section_fast_data_begin; + bsp_section_fast_data_load_begin = LOADADDR (.fast_data); + bsp_section_fast_data_load_end = bsp_section_fast_data_load_begin + bsp_section_fast_data_size; + + .data : { + bsp_section_data_begin = .; + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } > REGION_DATA AT > REGION_DATA_LOAD + .data1 : { + *(.data1) + } > REGION_DATA AT > REGION_DATA_LOAD + .rwbsdsets : { + /* Special FreeBSD linker set sections */ + _bsd__start_set_sysinit_set = .; + *(_bsd_set_sysinit_set); + _bsd__stop_set_sysinit_set = .; + } > REGION_DATA AT > REGION_DATA_LOAD + .sdata : { + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + bsp_section_data_end = .; + } > REGION_DATA AT > REGION_DATA_LOAD + bsp_section_data_size = bsp_section_data_end - bsp_section_data_begin; + bsp_section_data_load_begin = LOADADDR (.data); + bsp_section_data_load_end = bsp_section_data_load_begin + bsp_section_data_size; + + .sbss : { + bsp_section_sbss_begin = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + bsp_section_sbss_end = .; + } > REGION_DATA AT > REGION_DATA + bsp_section_sbss_size = bsp_section_sbss_end - bsp_section_sbss_begin; + + .bss : { + bsp_section_bss_begin = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + bsp_section_bss_end = .; + } > REGION_BSS AT > REGION_BSS + bsp_section_bss_size = bsp_section_bss_end - bsp_section_bss_begin; + + .rwextra : { + bsp_section_rwextra_begin = .; + *(.bsp_rwextra) + bsp_section_rwextra_end = .; + } > REGION_RWEXTRA AT > REGION_RWEXTRA + bsp_section_rwextra_size = bsp_section_rwextra_end - bsp_section_rwextra_begin; + + .work : { + /* + * The work section will occupy the remaining REGION_WORK region and + * contains the RTEMS work space and heap. + */ + bsp_section_work_begin = .; + . += ORIGIN (REGION_WORK) + LENGTH (REGION_WORK) - ABSOLUTE (.); + bsp_section_work_end = .; + } > REGION_WORK AT > REGION_WORK + bsp_section_work_size = bsp_section_work_end - bsp_section_work_begin; + + .stack : { + /* + * The stack section will occupy the remaining REGION_STACK region and may + * contain the task stacks. Depending on the region distribution this + * section may be of zero size. + */ + bsp_section_stack_begin = .; + . += ORIGIN (REGION_STACK) + LENGTH (REGION_STACK) - ABSOLUTE (.); + bsp_section_stack_end = .; + } > REGION_STACK AT > REGION_STACK + bsp_section_stack_size = bsp_section_stack_end - bsp_section_stack_begin; + + /* FIXME */ + RamBase = ORIGIN (REGION_WORK); + RamSize = LENGTH (REGION_WORK); + WorkAreaBase = bsp_section_work_begin; + HeapSize = 0; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* 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 .zdebug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames .zdebug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges .zdebug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames .zdebug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.* .zdebug_info) } + .debug_abbrev 0 : { *(.debug_abbrev .zdebug_abbrev) } + .debug_line 0 : { *(.debug_line .zdebug_line) } + .debug_frame 0 : { *(.debug_frame .zdebug_frame) } + .debug_str 0 : { *(.debug_str .zdebug_str) } + .debug_loc 0 : { *(.debug_loc .zdebug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo .zdebug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames .zdebug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames .zdebug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames .zdebug_typenames) } + .debug_varnames 0 : { *(.debug_varnames .zdebug_varnames) } + /* DWARF 3 */ + .debug_pubtypes 0 : { *(.debug_pubtypes .zdebug_pubtypes) } + .debug_ranges 0 : { *(.debug_ranges .zdebug_ranges) } + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } + .PPC.EMB.apuinfo 0 : { *(.PPC.EMB.apuinfo) } + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } + + /* Catch all unknown sections */ + .nirvana : { *(*) } > NIRVANA +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_0 b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_0 new file mode 100644 index 0000000000..4d2c130860 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_0 @@ -0,0 +1,33 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 0. + */ + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 32M + NIRVANA : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_1 b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_1 new file mode 100644 index 0000000000..4d38dc6e8c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_core_1 @@ -0,0 +1,32 @@ +/** + * @file + * + * @brief Memory map for QorIQ Core 1. + */ + +MEMORY { + RAM : ORIGIN = 0x4000000, LENGTH = 64M + NIRVANA : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", RAM); +REGION_ALIAS ("REGION_TEXT", RAM); +REGION_ALIAS ("REGION_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_RODATA", RAM); +REGION_ALIAS ("REGION_RODATA_LOAD", RAM); +REGION_ALIAS ("REGION_DATA", RAM); +REGION_ALIAS ("REGION_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_TEXT", RAM); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", RAM); +REGION_ALIAS ("REGION_FAST_DATA", RAM); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", RAM); +REGION_ALIAS ("REGION_BSS", RAM); +REGION_ALIAS ("REGION_RWEXTRA", RAM); +REGION_ALIAS ("REGION_WORK", RAM); +REGION_ALIAS ("REGION_STACK", RAM); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_p1020rdb b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_p1020rdb new file mode 100644 index 0000000000..2ee00584cf --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/linkcmds.qoriq_p1020rdb @@ -0,0 +1,33 @@ +/** + * @file + * + * Memory map for P1020RDB. + */ + +MEMORY { + LOW : ORIGIN = 0x4000, LENGTH = 16M - 16k + HIGH : ORIGIN = 0x1000000, LENGTH = 32M + NIRVANA : ORIGIN = 0x0, LENGTH = 0 +} + +REGION_ALIAS ("REGION_START", LOW); +REGION_ALIAS ("REGION_FAST_TEXT", LOW); +REGION_ALIAS ("REGION_FAST_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_TEXT", LOW); +REGION_ALIAS ("REGION_TEXT_LOAD", LOW); +REGION_ALIAS ("REGION_RODATA", HIGH); +REGION_ALIAS ("REGION_RODATA_LOAD", LOW); +REGION_ALIAS ("REGION_FAST_DATA", HIGH); +REGION_ALIAS ("REGION_FAST_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_DATA", HIGH); +REGION_ALIAS ("REGION_DATA_LOAD", LOW); +REGION_ALIAS ("REGION_BSS", HIGH); +REGION_ALIAS ("REGION_RWEXTRA", HIGH); +REGION_ALIAS ("REGION_WORK", HIGH); +REGION_ALIAS ("REGION_STACK", HIGH); + +bsp_section_robarrier_align = 0x1000000; +bsp_section_rwbarrier_align = 0x1000000; +qoriq = 0xffe00000; + +INCLUDE linkcmds.base diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c new file mode 100644 index 0000000000..6f3ab103ef --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-config.c @@ -0,0 +1,124 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include +#include +#include + +#define TEXT __attribute__((section(".bsp_start_text"))) +#define DATA __attribute__((section(".bsp_start_data"))) + +typedef struct { + uint32_t begin; + uint32_t size; + uint32_t mas2; + uint32_t mas3; +} entry; + +#define ENTRY_X(b, s) { \ + .begin = (uint32_t) b, \ + .size = (uint32_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SX \ +} + +#define ENTRY_R(b, s) { \ + .begin = (uint32_t) b, \ + .size = (uint32_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SR \ +} + +#define ENTRY_RW(b, s) { \ + .begin = (uint32_t) b, \ + .size = (uint32_t) s, \ + .mas2 = 0, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +#define ENTRY_DEV(b, s) { \ + .begin = (uint32_t) b, \ + .size = (uint32_t) s, \ + .mas2 = FSL_EIS_MAS2_I | FSL_EIS_MAS2_G, \ + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW \ +} + +static const entry DATA config [] = { + #if defined(QORIQ_INTERCOM_AREA_BEGIN) && defined(QORIQ_INTERCOM_AREA_SIZE) + { + .begin = QORIQ_INTERCOM_AREA_BEGIN, + .size = QORIQ_INTERCOM_AREA_SIZE, + .mas2 = FSL_EIS_MAS2_M, + .mas3 = FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW + }, + #endif + ENTRY_X(bsp_section_start_begin, bsp_section_start_size), + ENTRY_R(bsp_section_fast_text_load_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_fast_text_begin, bsp_section_fast_text_size), + ENTRY_X(bsp_section_text_begin, bsp_section_text_size), + ENTRY_R(bsp_section_rodata_load_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_rodata_begin, bsp_section_rodata_size), + ENTRY_R(bsp_section_fast_data_load_begin, bsp_section_fast_data_size), + ENTRY_RW(bsp_section_fast_data_begin, bsp_section_fast_data_size), + ENTRY_R(bsp_section_data_load_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_data_begin, bsp_section_data_size), + ENTRY_RW(bsp_section_sbss_begin, bsp_section_sbss_size), + ENTRY_RW(bsp_section_bss_begin, bsp_section_bss_size), + ENTRY_RW(bsp_section_rwextra_begin, bsp_section_rwextra_size), + ENTRY_RW(bsp_section_work_begin, bsp_section_work_size), + ENTRY_RW(bsp_section_stack_begin, bsp_section_stack_size), + ENTRY_DEV(&qoriq, sizeof(qoriq)) +}; + +void TEXT qoriq_mmu_config(int first_tlb, int scratch_tlb) +{ + qoriq_mmu_context context; + int i = 0; + + qoriq_mmu_context_init(&context); + + for (i = 0; i < 16; ++i) { + if (i != scratch_tlb) { + qoriq_tlb1_invalidate(i); + } + } + + for (i = 0; i < (int) (sizeof(config) / sizeof(config [0])); ++i) { + const entry *cur = &config [i]; + if (cur->size > 0) { + qoriq_mmu_add( + &context, + cur->begin, + cur->begin + cur->size - 1, + 0, + cur->mas2, + cur->mas3 + ); + } + } + + qoriq_mmu_partition(&context, 8); + qoriq_mmu_write_to_tlb1(&context, first_tlb); +} diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-tlb1.S b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-tlb1.S new file mode 100644 index 0000000000..390b5474b6 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu-tlb1.S @@ -0,0 +1,86 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief qoriq_tlb1_write() and qoriq_tlb1_invalidate() implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include + + .global qoriq_tlb1_write + .global qoriq_tlb1_invalidate + .global qoriq_tlb1_ts_0_only + + .section ".bsp_start_text", "ax" + +qoriq_tlb1_write: + rlwinm r3, r3, 16, 12, 15 + rlwinm r7, r7, 0, 0, 19 + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + oris r4, r4, 0xc000 + rlwinm r8, r8, 8, 20, 23 + or r8, r4, r8 + mtspr FSL_EIS_MAS1, r8 + or r5, r7, r5 + mtspr FSL_EIS_MAS2, r5 + or r6, r7, r6 + mtspr FSL_EIS_MAS3, r6 + li r0, 0 + mtspr FSL_EIS_MAS7, r0 + tlbwe + sync + isync + blr + +qoriq_tlb1_invalidate: + rlwinm r3, r3, 16, 12, 15 + oris r3, r3, 0x1000 + mtspr FSL_EIS_MAS0, r3 + li r0, 0 + mtspr FSL_EIS_MAS1, r0 + mtspr FSL_EIS_MAS2, r0 + mtspr FSL_EIS_MAS3, r0 + mtspr FSL_EIS_MAS7, r0 + tlbwe + sync + isync + blr + +qoriq_tlb1_ts_0_only: + mflr r12 + li r11, 16 + mtctr r11 + li r11, 0 +2: + rlwinm r0, r11, 16, 12, 15 + oris r0, r0, (FSL_EIS_MAS0_TLBSEL >> 16) + mtspr FSL_EIS_MAS0, r0 + tlbre + mfspr r0, FSL_EIS_MAS1 + andi. r0, r0, FSL_EIS_MAS1_TS + beq 1f + mr r3, r11 + bl qoriq_tlb1_invalidate +1: + addi r11, r11, 1 + bdnz 2b + mtlr r12 + blr diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c new file mode 100644 index 0000000000..485ef5b243 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/qoriq/startup/mmu.c @@ -0,0 +1,302 @@ +/** + * @file + * + * @ingroup QorIQMMU + * + * @brief MMU implementation. + */ + +/* + * Copyright (c) 2011 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include +#include + +#define TEXT __attribute__((section(".bsp_start_text"))) + +static uint32_t TEXT power_of_two(uint32_t val) +{ + uint32_t test_power = QORIQ_MMU_MIN_POWER; + uint32_t power = test_power; + uint32_t alignment = 1U << test_power; + + while (test_power <= QORIQ_MMU_MAX_POWER && (val & (alignment - 1)) == 0) { + power = test_power; + alignment <<= QORIQ_MMU_POWER_STEP; + test_power += QORIQ_MMU_POWER_STEP; + } + + return power; +} + +void TEXT qoriq_mmu_context_init(qoriq_mmu_context *self) +{ + int *cur = (int *) self; + const int *end = cur + sizeof(*self) / sizeof(*cur); + + while (cur != end) { + *cur = 0; + ++cur; + } +} + +static void TEXT sort(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry key = entries [i]; + int j = 0; + + for (j = i - 1; j >= 0 && entries [j].begin > key.begin; --j) { + entries [j + 1] = entries [j]; + } + + entries [j + 1] = key; + } +} + +static bool TEXT mas_equal(const qoriq_mmu_entry *a, const qoriq_mmu_entry *b) +{ + return a->mas1 == b->mas1 && a->mas2 == b->mas2 && a->mas3 == b->mas3; +} + +static bool TEXT can_merge(const qoriq_mmu_entry *prev, const qoriq_mmu_entry *cur) +{ + bool can = false; + + if (prev->begin == cur->begin || prev->last >= cur->begin - 1) { + /* + * Here we can technically merge. We need a heuristic to + * prevent merges in case the MAS values differ and the boarder + * is reasonably well aligned. + */ + if ( + mas_equal(prev, cur) + || prev->last != cur->begin - 1 + || power_of_two(cur->begin) < 24 + ) { + can = true; + } + } + + return can; +} + +static void TEXT merge(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 1; i < n; ++i) { + qoriq_mmu_entry *prev = &entries [i - 1]; + qoriq_mmu_entry *cur = &entries [i]; + + if (can_merge(prev, cur)) { + int j = 0; + + prev->mas1 |= cur->mas1; + prev->mas2 |= cur->mas2; + prev->mas3 |= cur->mas3; + + if (cur->last > prev->last) { + prev->last = cur->last; + } + + for (j = i + 1; j < n; ++j) { + entries [j - 1] = entries [j]; + } + + --i; + --n; + } + } + + self->count = n; +} + +static void TEXT compact(qoriq_mmu_context *self) +{ + sort(self); + merge(self); +} + +static void TEXT align(qoriq_mmu_context *self, uint32_t alignment) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + cur->begin &= ~(alignment - 1); + cur->last = alignment + (cur->last & ~(alignment - 1)) - 1; + } +} + +static bool TEXT is_full(qoriq_mmu_context *self) +{ + return self->count >= QORIQ_MMU_ENTRY_COUNT; +} + +static void TEXT append(qoriq_mmu_context *self, const qoriq_mmu_entry *new_entry) +{ + self->entries [self->count] = *new_entry; + ++self->count; +} + +bool TEXT qoriq_mmu_add( + qoriq_mmu_context *self, + uint32_t begin, + uint32_t last, + uint32_t mas1, + uint32_t mas2, + uint32_t mas3 +) +{ + bool ok = true; + + if (is_full(self)) { + compact(self); + } + + if (!is_full(self)) { + if (begin < last) { + qoriq_mmu_entry new_entry = { + .begin = begin, + .last = last, + .mas1 = mas1, + .mas2 = mas2, + .mas3 = mas3 + }; + append(self, &new_entry); + } else { + ok = false; + } + } else { + ok = false; + } + + return ok; +} + +static uint32_t TEXT min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} + +static bool TEXT split(qoriq_mmu_context *self, qoriq_mmu_entry *cur) +{ + bool again = false; + uint32_t begin = cur->begin; + uint32_t end = cur->last + 1; + uint32_t size = end - begin; + uint32_t begin_power = power_of_two(begin); + uint32_t end_power = power_of_two(end); + uint32_t size_power = power_of_two(size); + uint32_t power = min(begin_power, min(end_power, size_power)); + uint32_t split_size = power < 32 ? (1U << power) : 0; + uint32_t split_pos = begin + split_size; + + if (split_pos != end && !is_full(self)) { + qoriq_mmu_entry new_entry = *cur; + cur->begin = split_pos; + new_entry.last = split_pos - 1; + append(self, &new_entry); + again = true; + } + + return again; +} + +static void TEXT split_all(qoriq_mmu_context *self) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + + while (split(self, cur)) { + /* Repeat */ + } + } +} + +static TEXT void partition(qoriq_mmu_context *self) +{ + compact(self); + split_all(self); + sort(self); +} + +void TEXT qoriq_mmu_partition(qoriq_mmu_context *self, int max_count) +{ + uint32_t alignment = 4096; + + do { + align(self, alignment); + partition(self); + alignment *= 4; + } while (self->count > max_count); +} + +void TEXT qoriq_mmu_write_to_tlb1(qoriq_mmu_context *self, int first_tlb) +{ + qoriq_mmu_entry *entries = self->entries; + int n = self->count; + int i = 0; + + for (i = 0; i < n; ++i) { + qoriq_mmu_entry *cur = &entries [i]; + uint32_t ea = cur->begin; + uint32_t size = cur->last - ea + 1; + uint32_t tsize = (power_of_two(size) - 10) / 2; + int tlb = first_tlb + i; + + qoriq_tlb1_write(tlb, cur->mas1, cur->mas2, cur->mas3, ea, tsize); + } +} + +void qoriq_mmu_change_perm(uint32_t test, uint32_t set, uint32_t clear) +{ + int i = 0; + + for (i = 0; i < 16; ++i) { + int mas0 = FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(i); + int mas1 = 0; + + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mas0); + asm volatile ("tlbre"); + + mas1 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); + if ((mas1 & FSL_EIS_MAS1_V) != 0) { + uint32_t mask = 0x3ff; + uint32_t mas3 = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3); + + if ((mas3 & mask) == test) { + mas3 &= ~(clear & mask); + mas3 |= set & mask; + PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS3, mas3); + asm volatile ("tlbwe; msync; isync" : : : "memory"); + } + } + } +} -- cgit v1.2.3