updated gen83xx BSP

updated haleakala BSP
added MPC55xx BSP
This commit is contained in:
Thomas Doerfler
2008-07-14 16:15:28 +00:00
parent 3c6fe2e7f9
commit 574fb67510
92 changed files with 12210 additions and 2515 deletions

View File

@@ -1,3 +1,29 @@
2008-07-14 Sebastian Huber <sebastian.huber@embedded-brains.de>
* configure.ac: Support for MPC55XX. Changed comment format to
Doxygen.
* mpc55xx/dspi/dspi.c, mpc55xx/edma/edma.c, mpc55xx/esci/esci.c,
mpc55xx/fec/fec.c, mpc55xx/include/dspi.h, mpc55xx/include/edma.h,
mpc55xx/include/esci.h, mpc55xx/include/irq.h,
mpc55xx/include/mpc55xx.h, mpc55xx/include/reg-defs.h,
mpc55xx/include/regs.h, mpc55xx/irq/irq.c, mpc55xx/misc/copy.S,
mpc55xx/misc/flash.S, mpc55xx/misc/fmpll.S: New BSP.
* mpc83xx/i2c/mpc83xx_i2cdrv.c,
mpc83xx/network/tsec.c, mpc83xx/spi/mpc83xx_spidrv.c,
mpc83xx/spi/mpc83xx_spidrv.h: Support for MPC8313ERDB.
* shared/include/powerpc-utility.h: Exchanged ASM and non ASM code
sections.
* rtems/powerpc/powerpc.h, shared/src/cache.c, shared/src/cache_.h:
New defines PPC_NO_CACHE_ALIGNMENT and PPC_NO_CACHE_ALIGNMENT_POWER for
CPUs with no cache. Provide default implementations for all cache
functions.
* mpc83xx/include/gtm.h, mpc83xx/gtm/gtm.c: New files.
2008-07-14 Thomas Doerfler <thomas.doerfler@embedded-brains.de>
* Makefile.am, new-exceptions/raw_exception.c,

View File

@@ -1,6 +1,15 @@
#
# $Id$
#
##
## $Id$
##
#
# @file
#
# @ingroup mpc55xx_config
#
# @brief Makefile of LibCPU for PowerPC.
#
ACLOCAL_AMFLAGS = -I ../../../aclocal
@@ -19,7 +28,7 @@ EXTRA_DIST =
noinst_PROGRAMS = new-exceptions/rtems-cpu.rel
new_exceptions_rtems_cpu_rel_SOURCES = new-exceptions/cpu.c \
new-exceptions/cpu_asm.S
new-exceptions/cpu_asm.S
new_exceptions_rtems_cpu_rel_CPPFLAGS = $(AM_CPPFLAGS)
new_exceptions_rtems_cpu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -37,7 +46,7 @@ noinst_PROGRAMS += new-exceptions/exc_bspsupport.rel
new_exceptions_exc_bspsupport_rel_SOURCES = \
new-exceptions/bspsupport/ppc_exc.S \
new-exceptions/bspsupport/ppc_exc_hdl.c \
new-exceptions/bspsupport/vectors_init.c
new-exceptions/bspsupport/vectors_init.c
new_exceptions_exc_bspsupport_rel_CPPFLAGS = $(AM_CPPFLAGS)
new_exceptions_exc_bspsupport_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
@@ -55,7 +64,7 @@ EXTRA_DIST += new-exceptions/bspsupport/README
EXTRA_DIST += new-exceptions/bspsupport/nest_irq_test.c
EXTRA_DIST += new-exceptions/bspsupport/ppc_exc_test.c
## shared/include
# shared/include
if shared
include_libcpu_HEADERS += shared/include/io.h shared/include/mmu.h shared/include/page.h \
shared/include/byteorder.h shared/include/pgtable.h
@@ -67,7 +76,7 @@ shared_cpuIdent_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_libcpu_HEADERS += shared/include/cpuIdent.h
## shared/cache
# shared/cache
noinst_PROGRAMS += shared/cache.rel
shared_cache_rel_SOURCES = shared/src/cache.c shared/src/cache_.h \
../shared/src/cache_aligned_malloc.c ../shared/src/cache_manager.c \
@@ -77,7 +86,7 @@ shared_cache_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
include_libcpu_HEADERS += ../shared/include/cache.h
## shared/stack
# shared/stack
noinst_PROGRAMS += shared/stack.rel
shared_stack_rel_SOURCES = shared/src/stack.c shared/include/spr.h shared/src/stackTrace.h
shared_stack_rel_CPPFLAGS = $(AM_CPPFLAGS)
@@ -89,13 +98,13 @@ endif
EXTRA_DIST += ppc403/README ppc403/vectors/README
if ppc403
## ppc403/clock
# ppc403/clock
noinst_PROGRAMS += ppc403/clock.rel
ppc403_clock_rel_SOURCES = ppc403/clock/clock.c
ppc403_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
ppc403_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## ppc403/console
# ppc403/console
noinst_PROGRAMS += ppc403/console.rel
if ppc405
ppc403_console_rel_SOURCES = ppc403/console/console405.c
@@ -110,13 +119,13 @@ shared_cpuIdent_rel_SOURCES = shared/include/cpuIdent.c
shared_cpuIdent_rel_CPPFLAGS = $(AM_CPPFLAGS)
shared_cpuIdent_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## ppc403/timer
# ppc403/timer
noinst_PROGRAMS += ppc403/timer.rel
ppc403_timer_rel_SOURCES = ppc403/timer/timer.c
ppc403_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
ppc403_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## ppc403/tty_drv
# ppc403/tty_drv
if ppc405
include_HEADERS += ppc403/tty_drv/tty_drv.h
@@ -145,13 +154,13 @@ include_mpc5xxdir = $(includedir)/mpc5xx
include_HEADERS = mpc5xx/include/mpc5xx.h
## mpc5xx/clock
# mpc5xx/clock
noinst_PROGRAMS += mpc5xx/clock.rel
mpc5xx_clock_rel_SOURCES = mpc5xx/clock/clock.c
mpc5xx_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc5xx_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc5xx/console-generic
# mpc5xx/console-generic
include_mpc5xx_HEADERS = mpc5xx/include/console.h
noinst_PROGRAMS += mpc5xx/console-generic.rel
@@ -159,7 +168,7 @@ mpc5xx_console_generic_rel_SOURCES = mpc5xx/console-generic/console-generic.c
mpc5xx_console_generic_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc5xx_console_generic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc5xx/exceptions
# mpc5xx/exceptions
include_libcpu_HEADERS += mpc5xx/exceptions/raw_exception.h
noinst_PROGRAMS += mpc5xx/exceptions.rel
@@ -167,7 +176,7 @@ mpc5xx_exceptions_rel_SOURCES = mpc5xx/exceptions/raw_exception.c
mpc5xx_exceptions_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc5xx_exceptions_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc5xx/irq
# mpc5xx/irq
include_libcpu_HEADERS += mpc5xx/irq/irq.h
noinst_PROGRAMS += mpc5xx/irq.rel
@@ -175,13 +184,13 @@ mpc5xx_irq_rel_SOURCES = mpc5xx/irq/irq.c mpc5xx/irq/irq_init.c mpc5xx/irq/irq_a
mpc5xx_irq_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc5xx_irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc5xx/timer
# mpc5xx/timer
noinst_PROGRAMS += mpc5xx/timer.rel
mpc5xx_timer_rel_SOURCES = mpc5xx/timer/timer.c
mpc5xx_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc5xx_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc5xx/vectors
# mpc5xx/vectors
include_libcpu_HEADERS += mpc5xx/vectors/vectors.h
noinst_PROGRAMS += mpc5xx/vectors.rel
@@ -191,7 +200,7 @@ mpc5xx_vectors_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
if mpc505
## mpc505/ictrl
# mpc505/ictrl
include_HEADERS = mpc505/ictrl/ictrl.h
noinst_PROGRAMS += mpc505/ictrl.rel
@@ -199,13 +208,13 @@ mpc505_ictrl_rel_SOURCES = mpc505/ictrl/ictrl.c
mpc505_ictrl_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc505_ictrl_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc505/timer
# mpc505/timer
noinst_PROGRAMS += mpc505/timer.rel
mpc505_timer_rel_SOURCES = mpc505/timer/timer.c
mpc505_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc505_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc505/vector
# mpc505/vector
noinst_PROGRAMS += mpc505/vectors.rel
mpc505_vectors_rel_SOURCES = mpc505/vectors/vectors.S
mpc505_vectors_rel_CPPFLAGS = $(AM_CPPFLAGS)
@@ -214,7 +223,7 @@ endif
if mpc6xx
## mpc6xx/mmu
# mpc6xx/mmu
include_libcpu_HEADERS += mpc6xx/mmu/bat.h mpc6xx/mmu/pte121.h
noinst_PROGRAMS += mpc6xx/mmu.rel
@@ -224,7 +233,7 @@ mpc6xx_mmu_rel_SOURCES = mpc6xx/mmu/bat.c mpc6xx/mmu/bat.h \
mpc6xx_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc6xx_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc6xx/clock
# mpc6xx/clock
include_libcpu_HEADERS += mpc6xx/clock/c_clock.h
noinst_PROGRAMS += mpc6xx/clock.rel
@@ -232,7 +241,7 @@ mpc6xx_clock_rel_SOURCES = mpc6xx/clock/c_clock.c mpc6xx/clock/c_clock.h
mpc6xx_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc6xx_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc6xx/timer
# mpc6xx/timer
noinst_PROGRAMS += mpc6xx/timer.rel
mpc6xx_timer_rel_SOURCES = mpc6xx/timer/timer.c
mpc6xx_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
@@ -240,7 +249,7 @@ mpc6xx_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
if e500
## mpc6xx/clock
# mpc6xx/clock
include_libcpu_HEADERS += mpc6xx/clock/c_clock.h
noinst_PROGRAMS += e500/clock.rel
@@ -248,13 +257,13 @@ e500_clock_rel_SOURCES = mpc6xx/clock/c_clock.c mpc6xx/clock/c_clock.h
e500_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
e500_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc6xx/timer
# mpc6xx/timer
noinst_PROGRAMS += e500/timer.rel
e500_timer_rel_SOURCES = mpc6xx/timer/timer.c
e500_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
e500_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## e500/mmu
# e500/mmu
include_libcpu_HEADERS += e500/mmu/e500_mmu.h
noinst_PROGRAMS += e500/mmu.rel
e500_mmu_rel_SOURCES = e500/mmu/mmu.c e500/mmu/e500_mmu.h
@@ -268,13 +277,13 @@ include_mpc8xxdir = $(includedir)/mpc8xx
include_HEADERS = mpc8xx/include/mpc8xx.h
## mpc8xx/clock
# mpc8xx/clock
noinst_PROGRAMS += mpc8xx/clock.rel
mpc8xx_clock_rel_SOURCES = mpc8xx/clock/clock.c
mpc8xx_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8xx_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8xx/console-generic
# mpc8xx/console-generic
include_mpc8xx_HEADERS = mpc8xx/include/console.h
noinst_PROGRAMS += mpc8xx/console-generic.rel
@@ -282,7 +291,7 @@ mpc8xx_console_generic_rel_SOURCES = mpc8xx/console-generic/console-generic.c
mpc8xx_console_generic_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8xx_console_generic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8xx/cpm
# mpc8xx/cpm
include_mpc8xx_HEADERS += mpc8xx/include/cpm.h
noinst_PROGRAMS += mpc8xx/cpm.rel
@@ -290,7 +299,7 @@ mpc8xx_cpm_rel_SOURCES = mpc8xx/cpm/cp.c mpc8xx/cpm/dpram.c
mpc8xx_cpm_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8xx_cpm_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8xx/mmu
# mpc8xx/mmu
include_mpc8xx_HEADERS += mpc8xx/include/mmu.h
noinst_PROGRAMS += mpc8xx/mmu.rel
@@ -298,7 +307,7 @@ mpc8xx_mmu_rel_SOURCES = mpc8xx/mmu/mmu.c
mpc8xx_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8xx_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8xx/timer
# mpc8xx/timer
noinst_PROGRAMS += mpc8xx/timer.rel
mpc8xx_timer_rel_SOURCES = mpc8xx/timer/timer.c
mpc8xx_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
@@ -311,7 +320,7 @@ include_mpc8260dir = $(includedir)/mpc8260
include_HEADERS = mpc8260/include/mpc8260.h
## mpc8260/console-generic
# mpc8260/console-generic
include_mpc8260_HEADERS = mpc8260/include/console.h
noinst_PROGRAMS += mpc8260/console-generic.rel
@@ -320,13 +329,13 @@ mpc8260_console_generic_rel_SOURCES = mpc8260/console-generic/console-generic.c
mpc8260_console_generic_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8260_console_generic_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8260/clock
# mpc8260/clock
noinst_PROGRAMS += mpc8260/clock.rel
mpc8260_clock_rel_SOURCES = mpc8260/clock/clock.c
mpc8260_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8260_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8260/cpm
# mpc8260/cpm
include_mpc8260_HEADERS += mpc8260/include/cpm.h
noinst_PROGRAMS += mpc8260/cpm.rel
@@ -335,7 +344,7 @@ mpc8260_cpm_rel_SOURCES = mpc8260/cpm/cp.c mpc8260/cpm/dpram.c mpc8260/cpm/brg.c
mpc8260_cpm_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8260_cpm_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8260/mmu
# mpc8260/mmu
include_mpc8260_HEADERS += mpc8260/include/mmu.h
noinst_PROGRAMS += mpc8260/mmu.rel
@@ -344,44 +353,121 @@ mpc8260_mmu_rel_SOURCES = mpc8260/mmu/mmu.c \
mpc8260_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8260_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc8260/timer
# mpc8260/timer
noinst_PROGRAMS += mpc8260/timer.rel
mpc8260_timer_rel_SOURCES = mpc8260/timer/timer.c
mpc8260_timer_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc8260_timer_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
##############################################################################
# START: MPC83XX #
##############################################################################
if mpc83xx
include_mpc83xxdir = $(includedir)/mpc83xx
include_mpc83xx_HEADERS = mpc83xx/include/mpc83xx.h
include_mpc83xx_HEADERS += mpc83xx/network/tsec.h
# Includes
include_bspdir = $(includedir)/bsp
## mpc83xx/network
include_bsp_HEADERS = new-exceptions/bspsupport/vectors.h \
new-exceptions/bspsupport/ppc_exc_bspsupp.h
include_mpc83xxdir = $(includedir)/mpc83xx
include_mpc83xx_HEADERS = mpc83xx/include/mpc83xx.h
# Network
include_mpc83xx_HEADERS += mpc83xx/network/tsec.h
if HAS_NETWORKING
noinst_PROGRAMS += mpc83xx/tsec.rel
mpc83xx_tsec_rel_SOURCES = mpc83xx/network/tsec.c
mpc83xx_tsec_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc83xx_tsec_rel_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
mpc83xx_tsec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
mpc83xx_tsec_rel_SOURCES = mpc83xx/network/tsec.c
mpc83xx_tsec_rel_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ -D__BSD_VISIBLE
mpc83xx_tsec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
## mpc83xx/i2c
# i2c
include_mpc83xx_HEADERS += mpc83xx/i2c/mpc83xx_i2cdrv.h
noinst_PROGRAMS += mpc83xx/i2c.rel
mpc83xx_i2c_rel_SOURCES = mpc83xx/i2c/mpc83xx_i2cdrv.c \
mpc83xx/i2c/mpc83xx_i2cdrv.h
mpc83xx_i2c_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc83xx_i2c_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
mpc83xx_i2c_rel_SOURCES = mpc83xx/i2c/mpc83xx_i2cdrv.c \
mpc83xx/i2c/mpc83xx_i2cdrv.h
mpc83xx_i2c_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
## mpc83xx/spi
# SPI
include_mpc83xx_HEADERS += mpc83xx/spi/mpc83xx_spidrv.h
noinst_PROGRAMS += mpc83xx/spi.rel
mpc83xx_spi_rel_SOURCES = mpc83xx/spi/mpc83xx_spidrv.c \
mpc83xx/spi/mpc83xx_spidrv.h
mpc83xx_spi_rel_CPPFLAGS = $(AM_CPPFLAGS)
mpc83xx_spi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
mpc83xx_spi_rel_SOURCES = mpc83xx/spi/mpc83xx_spidrv.c \
mpc83xx/spi/mpc83xx_spidrv.h
mpc83xx_spi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# GTM
include_mpc83xx_HEADERS += mpc83xx/include/gtm.h
noinst_PROGRAMS += mpc83xx/gtm.rel
mpc83xx_gtm_rel_SOURCES = mpc83xx/gtm/gtm.c \
mpc83xx/include/gtm.h
mpc83xx_gtm_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
##############################################################################
# END: MPC83XX #
##############################################################################
##############################################################################
# START: MPC55XX #
##############################################################################
if mpc55xx
# Includes
include_bspdir = $(includedir)/bsp
include_bsp_HEADERS = new-exceptions/bspsupport/vectors.h \
new-exceptions/bspsupport/ppc_exc_bspsupp.h \
mpc55xx/include/irq.h
include_mpc55xxdir = $(includedir)/mpc55xx
include_mpc55xx_HEADERS = mpc55xx/include/regs.h \
mpc55xx/include/reg-defs.h \
mpc55xx/include/dspi.h \
mpc55xx/include/edma.h \
mpc55xx/include/mpc55xx.h \
mpc55xx/include/esci.h
# IRQ
noinst_PROGRAMS += mpc55xx/irq.rel
mpc55xx_irq_rel_SOURCES = mpc55xx/irq/irq.c
mpc55xx_irq_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# FEC
noinst_PROGRAMS += mpc55xx/fec.rel
mpc55xx_fec_rel_SOURCES = mpc55xx/fec/fec.c
mpc55xx_fec_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# EMDA
noinst_PROGRAMS += mpc55xx/edma.rel
mpc55xx_edma_rel_SOURCES = mpc55xx/edma/edma.c
mpc55xx_edma_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# ESCI
noinst_PROGRAMS += mpc55xx/esci.rel
mpc55xx_esci_rel_SOURCES = mpc55xx/esci/esci.c
mpc55xx_esci_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# DSPI
noinst_PROGRAMS += mpc55xx/dspi.rel
mpc55xx_dspi_rel_SOURCES = mpc55xx/dspi/dspi.c
mpc55xx_dspi_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
# Misc
noinst_PROGRAMS += mpc55xx/misc.rel
mpc55xx_misc_rel_SOURCES = mpc55xx/misc/copy.S \
mpc55xx/misc/fmpll.S \
mpc55xx/misc/flash.S
mpc55xx_misc_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
##############################################################################
# END: MPC55XX #
##############################################################################
include $(srcdir)/preinstall.am
include $(top_srcdir)/../../../automake/local.am

View File

@@ -1,6 +1,15 @@
## Process this file with autoconf to produce a configure script.
##
## $Id$
# Process this file with autoconf to produce a configure script.
#
# $Id$
##
#
# @file
#
# @ingroup mpc55xx_config
#
# @brief Configure script of LibCPU for PowerPC.
#
AC_PREREQ(2.60)
AC_INIT([rtems-c-src-lib-libcpu-powerpc],[_RTEMS_VERSION],[http://www.rtems.org/bugzilla])
@@ -27,6 +36,7 @@ AM_CONDITIONAL(shared, \
|| test "$RTEMS_CPU_MODEL" = "mpc7455" \
|| test "$RTEMS_CPU_MODEL" = "mpc7457" \
|| test "$RTEMS_CPU_MODEL" = "mpc555" \
|| test "$RTEMS_CPU_MODEL" = "mpc55xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc5xx" \
|| test "$RTEMS_CPU_MODEL" = "ppc603e" \
|| test "$RTEMS_CPU_MODEL" = "ppc403" \
@@ -42,8 +52,9 @@ AM_CONDITIONAL(shared, \
|| test "$RTEMS_CPU_MODEL" = "mpc83xx" \
|| test "$RTEMS_CPU_MODEL" = "e500")
## test on CPU type
# test on CPU type
AM_CONDITIONAL(mpc505, test "$RTEMS_CPU_MODEL" = "mpc505")
AM_CONDITIONAL(mpc55xx, test "$RTEMS_CPU_MODEL" = "mpc55xx")
AM_CONDITIONAL(mpc5xx, test "$RTEMS_CPU_MODEL" = "mpc5xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc555" )
AM_CONDITIONAL(mpc6xx, test "$RTEMS_CPU_MODEL" = "mpc6xx" \

View File

@@ -0,0 +1,746 @@
/**
* @file
*
* @ingroup mpc55xx_dspi
*
* @brief Source file for the LibI2C bus driver for the Deserial Serial Peripheral Interface (DSPI).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <mpc55xx/regs.h>
#include <mpc55xx/dspi.h>
#include <mpc55xx/edma.h>
#include <mpc55xx/mpc55xx.h>
#include <libcpu/powerpc-utility.h>
#define RTEMS_STATUS_CHECKS_USE_PRINTK
#include <rtems/status-checks.h>
#define MPC55XX_DSPI_FIFO_SIZE 4
#define MPC55XX_DSPI_CTAR_NUMBER 8
#define MPC55XX_DSPI_CTAR_DEFAULT 0
#define MPC55XX_DSPI_EDMA_MAGIC_SIZE 128
#define MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE 63
typedef struct {
uint32_t scaler : 26;
uint32_t pbr : 2;
uint32_t br : 4;
} mpc55xx_dspi_baudrate_scaler_entry;
static const mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_baudrate_scaler_table [MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE] = {
{ 4, 0, 0 },
{ 6, 1, 0 },
{ 8, 0, 1 },
{ 10, 2, 0 },
{ 12, 1, 1 },
{ 14, 3, 0 },
{ 16, 0, 3 },
{ 18, 1, 2 },
{ 20, 2, 1 },
{ 24, 1, 3 },
{ 28, 3, 1 },
{ 30, 2, 2 },
{ 32, 0, 4 },
{ 40, 2, 3 },
{ 42, 3, 2 },
{ 48, 1, 4 },
{ 56, 3, 3 },
{ 64, 0, 5 },
{ 80, 2, 4 },
{ 96, 1, 5 },
{ 112, 3, 4 },
{ 128, 0, 6 },
{ 160, 2, 5 },
{ 192, 1, 6 },
{ 224, 3, 5 },
{ 256, 0, 7 },
{ 320, 2, 6 },
{ 384, 1, 7 },
{ 448, 3, 6 },
{ 512, 0, 8 },
{ 640, 2, 7 },
{ 768, 1, 8 },
{ 896, 3, 7 },
{ 1024, 0, 9 },
{ 1280, 2, 8 },
{ 1536, 1, 9 },
{ 1792, 3, 8 },
{ 2048, 0, 10 },
{ 2560, 2, 9 },
{ 3072, 1, 10 },
{ 3584, 3, 9 },
{ 4096, 0, 11 },
{ 5120, 2, 10 },
{ 6144, 1, 11 },
{ 7168, 3, 10 },
{ 8192, 0, 12 },
{ 10240, 2, 11 },
{ 12288, 1, 12 },
{ 14336, 3, 11 },
{ 16384, 0, 13 },
{ 20480, 2, 12 },
{ 24576, 1, 13 },
{ 28672, 3, 12 },
{ 32768, 0, 14 },
{ 40960, 2, 13 },
{ 49152, 1, 14 },
{ 57344, 3, 13 },
{ 65536, 0, 15 },
{ 81920, 2, 14 },
{ 98304, 1, 15 },
{ 114688, 3, 14 },
{ 163840, 2, 15 },
{ 229376, 3, 15 },
};
static mpc55xx_dspi_baudrate_scaler_entry mpc55xx_dspi_search_baudrate_scaler( uint32_t scaler, int min, int mid, int max)
{
if (scaler <= mpc55xx_dspi_baudrate_scaler_table [mid].scaler) {
max = mid;
} else {
min = mid;
}
mid = (min + max) / 2;
if (mid == min) {
return mpc55xx_dspi_baudrate_scaler_table [max];
} else {
return mpc55xx_dspi_search_baudrate_scaler( scaler, min, mid, max);
}
}
static uint32_t mpc55xx_dspi_push_data [8 * MPC55XX_DSPI_NUMBER] __attribute__ ((aligned (32)));
static inline void mpc55xx_dspi_store_push_data( mpc55xx_dspi_bus_entry *e)
{
mpc55xx_dspi_push_data [e->table_index * 8] = e->push_data.R;
rtems_cache_flush_multiple_data_lines( &mpc55xx_dspi_push_data [e->table_index * 8], 4);
}
static inline uint32_t mpc55xx_dspi_push_data_address( mpc55xx_dspi_bus_entry *e)
{
return (uint32_t) &mpc55xx_dspi_push_data [e->table_index * 8];
}
static inline uint32_t mpc55xx_dspi_nirvana_address( mpc55xx_dspi_bus_entry *e)
{
return (uint32_t) &mpc55xx_dspi_push_data [e->table_index * 8 + 1];
}
static rtems_status_code mpc55xx_dspi_init( rtems_libi2c_bus_t *bus)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
union DSPI_MCR_tag mcr = MPC55XX_ZERO_FLAGS;
union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
union DSPI_RSER_tag rser = MPC55XX_ZERO_FLAGS;
struct tcd_t tcd_push = MPC55XX_EDMA_TCD_DEFAULT;
int i = 0;
/* eDMA receive */
sc = rtems_semaphore_create (
rtems_build_name ( 'S', 'P', 'I', 'R'),
0,
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
RTEMS_NO_PRIORITY,
&e->edma_channel_receive_update
);
CHECK_SC( sc, "Create receive update semaphore");
sc = mpc55xx_edma_obtain_channel( e->edma_channel_receive, &e->edma_channel_receive_error, e->edma_channel_receive_update);
CHECK_SC( sc, "Obtain receive eDMA channel");
/* eDMA transmit */
sc = rtems_semaphore_create (
rtems_build_name ( 'S', 'P', 'I', 'T'),
0,
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
RTEMS_NO_PRIORITY,
&e->edma_channel_transmit_update
);
CHECK_SC( sc, "Create transmit update semaphore");
sc = mpc55xx_edma_obtain_channel( e->edma_channel_transmit, &e->edma_channel_transmit_error, e->edma_channel_transmit_update);
CHECK_SC( sc, "Obtain transmit eDMA channel");
sc = mpc55xx_edma_obtain_channel( e->edma_channel_push, NULL, RTEMS_ID_NONE);
CHECK_SC( sc, "Obtain push eDMA channel");
tcd_push.SADDR = mpc55xx_dspi_push_data_address( e);
tcd_push.SSIZE = 2;
tcd_push.SOFF = 0;
tcd_push.DADDR = (uint32_t) &e->regs->PUSHR.R;
tcd_push.DSIZE = 2;
tcd_push.DOFF = 0;
tcd_push.NBYTES = 4;
tcd_push.CITER = 1;
tcd_push.BITER = 1;
EDMA.TCD [e->edma_channel_push] = tcd_push;
/* Module Control Register */
mcr.B.MSTR = e->master ? 1 : 0;
mcr.B.CONT_SCKE = 0;
mcr.B.DCONF = 0;
mcr.B.FRZ = 0;
mcr.B.MTFE = 0;
mcr.B.PCSSE = 0;
mcr.B.ROOE = 0;
mcr.B.PCSIS0 = 1;
mcr.B.PCSIS1 = 1;
mcr.B.PCSIS2 = 1;
mcr.B.PCSIS3 = 1;
mcr.B.PCSIS5 = 1;
mcr.B.MDIS = 0;
mcr.B.DIS_TXF = 0;
mcr.B.DIS_RXF = 0;
mcr.B.CLR_TXF = 0;
mcr.B.CLR_RXF = 0;
mcr.B.SMPL_PT = 0;
mcr.B.HALT = 0;
e->regs->MCR.R = mcr.R;
/* Clock and Transfer Attributes Register */
ctar.B.DBR = 0;
ctar.B.FMSZ = 0x7;
ctar.B.CPOL = 0;
ctar.B.CPHA = 0;
ctar.B.LSBFE = 0;
ctar.B.PCSSCK = 0;
ctar.B.PASC = 0;
ctar.B.PDT = 0;
ctar.B.PBR = 0;
ctar.B.CSSCK = 0;
ctar.B.ASC = 0;
ctar.B.DT = 0;
ctar.B.BR = 0;
for (i = 0; i < MPC55XX_DSPI_CTAR_NUMBER; ++i) {
e->regs->CTAR [i].R = ctar.R;
}
/* DMA/Interrupt Request Select and Enable Register */
rser.B.TFFFRE = 1;
rser.B.TFFFDIRS = 1;
rser.B.RFDFRE = 1;
rser.B.RFDFDIRS = 1;
e->regs->RSER.R = rser.R;
return RTEMS_SUCCESSFUL;
}
static rtems_status_code mpc55xx_dspi_send_start( rtems_libi2c_bus_t *bus)
{
mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
/* Reset chip selects */
e->push_data.B.PCS0 = 0;
e->push_data.B.PCS1 = 0;
e->push_data.B.PCS2 = 0;
e->push_data.B.PCS3 = 0;
e->push_data.B.PCS4 = 0;
e->push_data.B.PCS5 = 0;
mpc55xx_dspi_store_push_data( e);
return RTEMS_SUCCESSFUL;
}
static rtems_status_code mpc55xx_dspi_send_stop( rtems_libi2c_bus_t *bus)
{
return RTEMS_SUCCESSFUL;
}
static rtems_status_code mpc55xx_dspi_send_addr( rtems_libi2c_bus_t *bus, uint32_t addr, int rw)
{
mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
union DSPI_SR_tag sr = MPC55XX_ZERO_FLAGS;
/* Flush transmit and receive FIFO */
e->regs->MCR.B.CLR_TXF = 1;
e->regs->MCR.B.CLR_RXF = 1;
/* Clear status flags */
sr.B.EOQF = 1;
sr.B.TFFF = 1;
sr.B.RFDF = 1;
e->regs->SR.R = sr.R;
/* Frame command */
e->push_data.R = 0;
e->push_data.B.CONT = 0;
e->push_data.B.CTAS = MPC55XX_DSPI_CTAR_DEFAULT;
e->push_data.B.EOQ = 0;
e->push_data.B.CTCNT = 0;
switch (addr) {
case 0:
e->push_data.B.PCS0 = 1;
break;
case 1:
e->push_data.B.PCS1 = 1;
break;
case 2:
e->push_data.B.PCS2 = 1;
break;
case 3:
e->push_data.B.PCS3 = 1;
break;
case 4:
e->push_data.B.PCS4 = 1;
break;
case 5:
e->push_data.B.PCS5 = 1;
break;
default:
return -RTEMS_INVALID_ADDRESS;
}
mpc55xx_dspi_store_push_data( e);
return RTEMS_SUCCESSFUL;
}
static int mpc55xx_dspi_set_transfer_mode( rtems_libi2c_bus_t *bus, const rtems_libi2c_tfr_mode_t *mode)
{
mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
union DSPI_CTAR_tag ctar = MPC55XX_ZERO_FLAGS;
// FIXME, TODO
extern uint32_t bsp_clock_speed;
uint32_t scaler = bsp_clock_speed / mode->baudrate;
mpc55xx_dspi_baudrate_scaler_entry bse = mpc55xx_dspi_search_baudrate_scaler( scaler, 0, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE / 2, MPC55XX_DSPI_BAUDRATE_SCALER_TABLE_SIZE);
if (mode->bits_per_char != 8) {
return -RTEMS_INVALID_NUMBER;
}
e->idle_char = mode->idle_char;
ctar.R = e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R;
ctar.B.PBR = bse.pbr;
ctar.B.BR = bse.br;
// ctar.B.PCSSCK = bse.pbr;
// ctar.B.CSSCK = bse.br;
// ctar.B.PASC = bse.pbr;
// ctar.B.ASC = bse.br;
ctar.B.PCSSCK = 0;
ctar.B.CSSCK = 0;
ctar.B.PASC = 0;
ctar.B.ASC = 0;
ctar.B.LSBFE = mode->lsb_first ? 1 : 0;
ctar.B.CPOL = mode->clock_inv ? 1 : 0;
ctar.B.CPHA = mode->clock_phs ? 1 : 0;
e->regs->CTAR [MPC55XX_DSPI_CTAR_DEFAULT].R = ctar.R;
return 0;
}
/**
* @brief Writes @a n characters from @a out to bus @a bus and synchronously stores the received data in @a in.
*
* eDMA channel usage for transmission:
* @dot
* digraph push {
* push [label="Push Register"];
* push_data [label="Push Data"];
* idle_push_data [label="Idle Push Data"];
* out [shape=box,label="Output Buffer"];
* edge [color=red,fontcolor=red];
* push -> idle_push_data [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_transmit"];
* push -> out [label="Transmit Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_transmit"];
* out -> push_data [label="Channel Link",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_push"];
* edge [color=blue,fontcolor=blue];
* out -> push_data [label="Data"];
* push_data -> push [label="Data"];
* idle_push_data -> push [label="Data"];
* }
* @enddot
*
* eDMA channel usage for receiving:
* @dot
* digraph pop {
* pop [label="Pop Register"];
* nirvana [label="Nirvana"];
* in [shape=box,label="Input Buffer"];
* edge [color=red,fontcolor=red];
* pop -> nirvana [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_receive"];
* pop -> in [label="Receive Request",URL="\ref mpc55xx_dspi_bus_entry::edma_channel_receive"];
* edge [color=blue,fontcolor=blue];
* pop -> nirvana [label="Data"];
* pop -> in [label="Data"];
* }
* @enddot
*/
static int mpc55xx_dspi_read_write( rtems_libi2c_bus_t *bus, unsigned char *in, const unsigned char *out, int n)
{
mpc55xx_dspi_bus_entry *e = (mpc55xx_dspi_bus_entry *) bus;
/* Non cache aligned characters */
int n_nc = n;
/* Cache aligned characters */
int n_c = 0;
/* Register addresses */
volatile void *push = &e->regs->PUSHR.R;
volatile void *pop = &e->regs->POPR.R;
volatile union DSPI_SR_tag *status = &e->regs->SR;
/* Push and pop data */
union DSPI_PUSHR_tag push_data = e->push_data;
union DSPI_POPR_tag pop_data;
/* Status register */
union DSPI_SR_tag sr;
/* Read and write indices */
int r = 0;
int w = 0;
if (n == 0) {
return 0;
} else if (in == NULL && out == NULL) {
return -RTEMS_INVALID_ADDRESS;
}
if (n > MPC55XX_DSPI_EDMA_MAGIC_SIZE) {
n_nc = mpc55xx_non_cache_aligned_size( in);
n_c = mpc55xx_cache_aligned_size( in, n);
if (n_c > EDMA_TCD_BITER_LINKED_SIZE) {
SYSLOG_WARNING( "Buffer size out of range, cannot use eDMA\n");
n_nc = n;
n_c = 0;
} else if (n_nc + n_c != n) {
SYSLOG_WARNING( "Input buffer not proper cache aligned, cannot use eDMA\n");
n_nc = n;
n_c = 0;
}
}
#ifdef DEBUG
if (e->regs->SR.B.TXCTR != e->regs->SR.B.RXCTR) {
SYSLOG_WARNING( "FIFO counter not equal\n");
}
#endif /* DEBUG */
/* Direct IO */
if (out == NULL) {
push_data.B.TXDATA = e->idle_char;
while (r < n_nc || w < n_nc) {
/* Wait for available FIFO */
do {
sr.R = status->R;
} while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
/* Write */
if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
++w;
ppc_write_word( push_data.R, push);
}
/* Read */
if (r < n_nc && sr.B.RXCTR != 0) {
pop_data.R = ppc_read_word( pop);
in [r] = pop_data.B.RXDATA;
// printk( "[%03u]: 0x%02x -> 0x%02x\n", r, out [r], in [r]);
++r;
}
}
} else if (in == NULL) {
while (r < n_nc || w < n_nc) {
/* Wait for available FIFO */
do {
sr.R = status->R;
} while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
/* Write */
if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
push_data.B.TXDATA = out [w];
++w;
ppc_write_word( push_data.R, push);
}
/* Read */
if (r < n_nc && sr.B.RXCTR != 0) {
pop_data.R = ppc_read_word( pop);
// printk( "[%03u]: 0x%02x -> 0x%02x\n", r, out [r], in [r]);
++r;
}
}
} else {
while (r < n_nc || w < n_nc) {
/* Wait for available FIFO */
do {
sr.R = status->R;
} while (sr.B.TXCTR == MPC55XX_DSPI_FIFO_SIZE && sr.B.RXCTR == 0);
/* Write */
if (w < n_nc && (w - r) < MPC55XX_DSPI_FIFO_SIZE && sr.B.TXCTR != MPC55XX_DSPI_FIFO_SIZE) {
push_data.B.TXDATA = out [w];
++w;
ppc_write_word( push_data.R, push);
}
/* Read */
if (r < n_nc && sr.B.RXCTR != 0) {
pop_data.R = ppc_read_word( pop);
in [r] = pop_data.B.RXDATA;
// printk( "[%03u]: 0x%02x -> 0x%02x\n", r, out [r], in [r]);
++r;
}
}
}
/* eDMA transfers */
if (n_c > 0) {
rtems_status_code sc = RTEMS_SUCCESSFUL;
unsigned char *in_c = in + n_nc;
const unsigned char *out_c = out + n_nc;
struct tcd_t tcd_transmit = MPC55XX_EDMA_TCD_DEFAULT;
struct tcd_t tcd_receive = MPC55XX_EDMA_TCD_DEFAULT;
/* Cache operations */
rtems_cache_flush_multiple_data_lines( out_c, n_c);
rtems_cache_invalidate_multiple_data_lines( in_c, n_c);
/* Set transmit TCD */
if (out == NULL) {
e->push_data.B.TXDATA = e->idle_char;
mpc55xx_dspi_store_push_data( e);
tcd_transmit.SADDR = mpc55xx_dspi_push_data_address( e);
tcd_transmit.SSIZE = 2;
tcd_transmit.SOFF = 0;
tcd_transmit.DADDR = (uint32_t) push;
tcd_transmit.DSIZE = 2;
tcd_transmit.DOFF = 0;
tcd_transmit.NBYTES = 4;
tcd_transmit.CITER = n_c;
tcd_transmit.BITER = n_c;
} else {
EDMA.CDSBR.R = e->edma_channel_transmit;
tcd_transmit.SADDR = (uint32_t) out_c;
tcd_transmit.SSIZE = 0;
tcd_transmit.SOFF = 1;
tcd_transmit.DADDR = mpc55xx_dspi_push_data_address( e) + 3;
tcd_transmit.DSIZE = 0;
tcd_transmit.DOFF = 0;
tcd_transmit.NBYTES = 1;
tcd_transmit.CITERE_LINK = 1;
tcd_transmit.BITERE_LINK = 1;
tcd_transmit.MAJORLINKCH = e->edma_channel_push;
tcd_transmit.CITER = EDMA_TCD_LINK_AND_BITER( e->edma_channel_push, n_c);
tcd_transmit.BITER = EDMA_TCD_LINK_AND_BITER( e->edma_channel_push, n_c);
tcd_transmit.MAJORE_LINK = 1;
}
tcd_transmit.D_REQ = 1;
tcd_transmit.INT_MAJ = 1;
EDMA.TCD [e->edma_channel_transmit] = tcd_transmit;
/* Set receive TCD */
if (in == NULL) {
tcd_receive.DOFF = 0;
tcd_receive.DADDR = mpc55xx_dspi_nirvana_address( e);
} else {
tcd_receive.DOFF = 1;
tcd_receive.DADDR = (uint32_t) in_c;
}
tcd_receive.SADDR = (uint32_t) pop + 3;
tcd_receive.SSIZE = 0;
tcd_receive.SOFF = 0;
tcd_receive.DSIZE = 0;
tcd_receive.NBYTES = 1;
tcd_receive.D_REQ = 1;
tcd_receive.INT_MAJ = 1;
tcd_receive.CITER = n_c;
tcd_receive.BITER = n_c;
EDMA.TCD [e->edma_channel_receive] = tcd_receive;
/* Clear request flags */
sr.R = 0;
sr.B.TFFF = 1;
sr.B.RFDF = 1;
status->R = sr.R;
/* Enable hardware requests */
sc = mpc55xx_edma_enable_hardware_requests( e->edma_channel_receive, true);
CHECK_SCRV( sc, "Enable receive hardware requests");
sc = mpc55xx_edma_enable_hardware_requests( e->edma_channel_transmit, true);
CHECK_SCRV( sc, "Enable transmit hardware requests");
/* Wait for transmit update */
sc = rtems_semaphore_obtain( e->edma_channel_transmit_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
CHECK_SCRV( sc, "Transmit update");
if (e->edma_channel_transmit_error != 0) {
SYSLOG_ERROR( "Transmit error status: 0x%08x\n", e->edma_channel_transmit_error);
e->edma_channel_transmit_error = 0;
return -RTEMS_IO_ERROR;
}
/* Wait for receive update */
sc = rtems_semaphore_obtain( e->edma_channel_receive_update, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
CHECK_SCRV( sc, "Receive update");
if (e->edma_channel_receive_error != 0) {
SYSLOG_ERROR( "Receive error status: 0x%08x\n", e->edma_channel_receive_error);
e->edma_channel_receive_error = 0;
return -RTEMS_IO_ERROR;
}
}
return n;
}
/**
* @brief Reads @a n characters from bus @a bus and stores it in @a in.
*
* Writes idle characters to receive data.
*
* @see mpc55xx_dspi_read_write().
*/
static int mpc55xx_dspi_read( rtems_libi2c_bus_t *bus, unsigned char *in, int n)
{
return mpc55xx_dspi_read_write( bus, in, NULL, n);
}
/**
* @brief Writes @a n characters from @a out to bus @a bus.
*
* Discards the synchronously received data.
*
* @see mpc55xx_dspi_read_write().
*/
static int mpc55xx_dspi_write( rtems_libi2c_bus_t *bus, unsigned char *out, int n)
{
return mpc55xx_dspi_read_write( bus, NULL, out, n);
}
static int mpc55xx_dspi_ioctl( rtems_libi2c_bus_t *bus, int cmd, void *arg)
{
int rv = -1;
switch (cmd) {
case RTEMS_LIBI2C_IOCTL_SET_TFRMODE:
rv = mpc55xx_dspi_set_transfer_mode( bus, (const rtems_libi2c_tfr_mode_t *) arg);
break;
case RTEMS_LIBI2C_IOCTL_READ_WRITE:
rv = mpc55xx_dspi_read_write(
bus,
((rtems_libi2c_read_write_t *) arg)->rd_buf,
((rtems_libi2c_read_write_t *) arg)->wr_buf,
((rtems_libi2c_read_write_t *) arg)->byte_cnt
);
break;
default:
rv = -RTEMS_NOT_DEFINED;
break;
}
return rv;
}
static const rtems_libi2c_bus_ops_t mpc55xx_dspi_ops = {
.init = mpc55xx_dspi_init,
.send_start = mpc55xx_dspi_send_start,
.send_stop = mpc55xx_dspi_send_stop,
.send_addr = mpc55xx_dspi_send_addr,
.read_bytes = mpc55xx_dspi_read,
.write_bytes = mpc55xx_dspi_write,
.ioctl = mpc55xx_dspi_ioctl
};
mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [MPC55XX_DSPI_NUMBER] = { {
/* DSPI A */
.bus = {
.ops = &mpc55xx_dspi_ops,
.size = sizeof( mpc55xx_dspi_bus_entry)
},
.table_index = 0,
.bus_number = 0,
.regs = &DSPI_A,
.master = 1,
.push_data = MPC55XX_ZERO_FLAGS,
.edma_channel_transmit = 32,
.edma_channel_push = 43,
.edma_channel_receive = 33,
.edma_channel_transmit_update = 0,
.edma_channel_receive_update = 0,
.edma_channel_transmit_error = 0,
.edma_channel_receive_error = 0,
.idle_char = 0xffffffff,
}, {
/* DSPI B */
.bus = {
.ops = &mpc55xx_dspi_ops,
.size = sizeof( mpc55xx_dspi_bus_entry)
},
.table_index = 1,
.bus_number = 0,
.regs = &DSPI_B,
.master = 1,
.push_data = MPC55XX_ZERO_FLAGS,
.edma_channel_transmit = 12,
.edma_channel_push = 10,
.edma_channel_receive = 13,
.edma_channel_transmit_update = 0,
.edma_channel_receive_update = 0,
.edma_channel_transmit_error = 0,
.edma_channel_receive_error = 0,
.idle_char = 0xffffffff,
}, {
/* DSPI C */
.bus = {
.ops = &mpc55xx_dspi_ops,
.size = sizeof( mpc55xx_dspi_bus_entry)
},
.table_index = 2,
.bus_number = 0,
.regs = &DSPI_C,
.master = 1,
.push_data = MPC55XX_ZERO_FLAGS,
.edma_channel_transmit = 14,
.edma_channel_push = 11,
.edma_channel_receive = 15,
.edma_channel_transmit_update = 0,
.edma_channel_receive_update = 0,
.edma_channel_transmit_error = 0,
.edma_channel_receive_error = 0,
.idle_char = 0xffffffff,
}, {
/* DSPI D */
.bus = {
.ops = &mpc55xx_dspi_ops,
.size = sizeof( mpc55xx_dspi_bus_entry)
},
.table_index = 3,
.bus_number = 0,
.regs = &DSPI_D,
.master = 1,
.push_data = MPC55XX_ZERO_FLAGS,
.edma_channel_transmit = 16,
.edma_channel_push = 18,
.edma_channel_receive = 17,
.edma_channel_transmit_update = 0,
.edma_channel_receive_update = 0,
.edma_channel_transmit_error = 0,
.edma_channel_receive_error = 0,
.idle_char = 0xffffffff,
},
};

View File

@@ -0,0 +1,279 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Enhanced Direct Memory Access (eDMA).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <mpc55xx/regs.h>
#include <mpc55xx/edma.h>
#include <mpc55xx/mpc55xx.h>
#include <bsp/irq.h>
#include <string.h>
#define RTEMS_STATUS_CHECKS_USE_PRINTK
#include <rtems/status-checks.h>
#define MPC55XX_EDMA_CHANNEL_NUMBER 64
#define MPC55XX_EDMA_INVALID_CHANNEL -1
#define MPC55XX_EDMA_IS_CHANNEL_INVALID( i) ((i) < 0 || (i) >= MPC55XX_EDMA_CHANNEL_NUMBER)
#define MPC55XX_EDMA_IRQ_PRIORITY MPC55XX_INTC_MIN_PRIORITY
typedef struct {
uint8_t channel;
rtems_id transfer_update;
uint32_t *error_status;
} mpc55xx_edma_channel_entry;
static mpc55xx_edma_channel_entry mpc55xx_edma_channel_table [MPC55XX_EDMA_CHANNEL_NUMBER];
static uint32_t mpc55xx_edma_channel_occupation_low = 0;
static uint32_t mpc55xx_edma_channel_occupation_high = 0;
static rtems_id mpc55xx_edma_channel_occupation_mutex = RTEMS_ID_NONE;
static uint8_t mpc55xx_edma_irq_error_low_channel = 0;
static uint8_t mpc55xx_edma_irq_error_high_channel = 32;
static void mpc55xx_edma_irq_handler( rtems_vector_number vector, void *data)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
mpc55xx_edma_channel_entry *e = (mpc55xx_edma_channel_entry *) data;
#ifdef DEBUG
uint32_t citer = EDMA.TCD [e->channel].CITERE_LINK ? EDMA.TCD [e->channel].CITER & EDMA_TCD_BITER_LINKED_MASK : EDMA.TCD [e->channel].CITER;
DEBUG_PRINT( "Channel %i (CITER = %i)\n", e->channel, citer);
#endif /* DEBUG */
EDMA.CIRQR.R = e->channel;
sc = rtems_semaphore_release( e->transfer_update);
SYSLOG_WARNING_SC( sc, "Transfer update semaphore release");
}
static void mpc55xx_edma_irq_update_error_table( uint8_t *link_table, uint8_t *error_table, uint8_t channel)
{
int i = 0;
error_table [channel] = 1;
for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
if (channel == link_table [i] && error_table [i] == 0) {
mpc55xx_edma_irq_update_error_table( link_table, error_table, i);
}
}
}
static void mpc55xx_edma_irq_error_handler( rtems_vector_number vector, void *data)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
uint8_t channel_start = *((uint8_t *) data);
uint8_t channel_end = channel_start + 32;
uint8_t i = 0;
uint32_t mask = 0x1;
uint32_t error_register = 0;
uint8_t channel_link_table [MPC55XX_EDMA_CHANNEL_NUMBER];
uint8_t channel_error_table [MPC55XX_EDMA_CHANNEL_NUMBER];
/* Error register */
if (channel_start < 32) {
error_register = EDMA.ERL.R;
} else if (channel_start < 64) {
error_register = EDMA.ERH.R;
}
DEBUG_PRINT( "Error register %s: 0x%08x\n", channel_start < 32 ? "low" : "high", error_register);
/* Fill channel link table */
for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
if (EDMA.TCD [i].BITERE_LINK && EDMA.TCD [i].CITER != EDMA.TCD [i].BITER) {
channel_link_table [i] = EDMA_TCD_BITER_LINK( i);
} else if (EDMA.TCD [i].MAJORE_LINK && EDMA.TCD [i].CITER == EDMA.TCD [i].BITER) {
channel_link_table [i] = EDMA.TCD [i].MAJORLINKCH;
} else {
channel_link_table [i] = MPC55XX_EDMA_INVALID_CHANNEL;
}
channel_error_table [i] = 0;
}
/* Search for channels with errors */
for (i = channel_start; i < channel_end; ++i) {
if ((error_register & mask) != 0) {
mpc55xx_edma_irq_update_error_table( channel_link_table, channel_error_table, i);
}
mask <<= 1;
}
/* Process the channels related to errors */
error_register = EDMA.ESR.R;
for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
if (channel_error_table [i]) {
mpc55xx_edma_channel_entry *e = &mpc55xx_edma_channel_table [i];
if (e->error_status != NULL) {
*e->error_status = error_register;
}
sc = mpc55xx_edma_enable_hardware_requests( i, false);
SYSLOG_ERROR_SC( sc, "Disable hardware requests, channel = %i", i);
sc = rtems_semaphore_release( e->transfer_update);
SYSLOG_WARNING_SC( sc, "Transfer update semaphore release, channel = %i", i);
}
}
/* Clear the error interrupt requests */
for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
if (channel_error_table [i]) {
EDMA.CER.R = i;
}
}
}
rtems_status_code mpc55xx_edma_enable_hardware_requests( int channel, bool enable)
{
if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
return RTEMS_INVALID_NUMBER;
}
if (enable) {
EDMA.SERQR.R = channel;
} else {
EDMA.CERQR.R = channel;
}
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc55xx_edma_enable_error_interrupts( int channel, bool enable)
{
if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
return RTEMS_INVALID_NUMBER;
}
if (enable) {
EDMA.SEEIR.R = channel;
} else {
EDMA.CEEIR.R = channel;
}
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc55xx_edma_init()
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
int i = 0;
/* Channel occupation mutex */
sc = rtems_semaphore_create (
rtems_build_name ( 'D', 'M', 'A', 'O'),
1,
RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
RTEMS_NO_PRIORITY,
&mpc55xx_edma_channel_occupation_mutex
);
CHECK_SC( sc, "Create channel occupation mutex");
/* Arbitration mode: round robin */
EDMA.CR.B.ERCA = 1;
EDMA.CR.B.ERGA = 1;
/* Clear TCDs */
memset( &EDMA.TCD [0], 0, sizeof( EDMA.TCD));
/* Channel table */
for (i = 0; i < MPC55XX_EDMA_CHANNEL_NUMBER; ++i) {
mpc55xx_edma_channel_table [i].channel = i;
mpc55xx_edma_channel_table [i].transfer_update = RTEMS_ID_NONE;
mpc55xx_edma_channel_table [i].error_status = NULL;
}
/* Error interrupt handler */
sc = mpc55xx_interrupt_handler_install(
MPC55XX_IRQ_EDMA_ERROR_LOW,
MPC55XX_EDMA_IRQ_PRIORITY,
"eDMA Error (Low)",
RTEMS_INTERRUPT_UNIQUE,
mpc55xx_edma_irq_error_handler,
&mpc55xx_edma_irq_error_low_channel
);
CHECK_SC( sc, "Install low error interrupt handler");
sc = mpc55xx_interrupt_handler_install(
MPC55XX_IRQ_EDMA_ERROR_HIGH,
MPC55XX_EDMA_IRQ_PRIORITY,
"eDMA Error (High)",
RTEMS_INTERRUPT_UNIQUE,
mpc55xx_edma_irq_error_handler,
&mpc55xx_edma_irq_error_high_channel
);
CHECK_SC( sc, "Install high error interrupt handler");
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc55xx_edma_obtain_channel( int channel, uint32_t *error_status, rtems_id transfer_update)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
int channel_occupied = 1;
if (MPC55XX_EDMA_IS_CHANNEL_INVALID( channel)) {
return RTEMS_INVALID_NUMBER;
}
/* Check occupation */
sc = rtems_semaphore_obtain( mpc55xx_edma_channel_occupation_mutex, RTEMS_WAIT, 0);
CHECK_SC( sc, "Obtain channel occupation mutex");
if (channel < 32) {
channel_occupied = mpc55xx_edma_channel_occupation_low & (0x1 << channel);
if (!channel_occupied) {
mpc55xx_edma_channel_occupation_low |= 0x1 << channel;
}
} else if (channel < 64) {
channel_occupied = mpc55xx_edma_channel_occupation_high & (0x1 << (channel - 32));
if (!channel_occupied) {
mpc55xx_edma_channel_occupation_high |= 0x1 << (channel - 32);
}
}
if (channel_occupied) {
sc = rtems_semaphore_release( mpc55xx_edma_channel_occupation_mutex);
SYSLOG_WARNING_SC( sc, "Release occupation mutex");
return RTEMS_RESOURCE_IN_USE;
} else {
sc = rtems_semaphore_release( mpc55xx_edma_channel_occupation_mutex);
CHECK_SC( sc, "Release channel occupation mutex");
}
/* Channel data */
mpc55xx_edma_channel_table [channel].transfer_update = transfer_update;
mpc55xx_edma_channel_table [channel].error_status = error_status;
/* Interrupt handler */
sc = mpc55xx_interrupt_handler_install(
MPC55XX_IRQ_EDMA_GET_REQUEST( channel),
MPC55XX_EDMA_IRQ_PRIORITY,
"eDMA Channel",
RTEMS_INTERRUPT_SHARED,
mpc55xx_edma_irq_handler,
&mpc55xx_edma_channel_table [channel]
);
CHECK_SC( sc, "Install channel interrupt handler");
/* Enable error interrupts */
sc = mpc55xx_edma_enable_error_interrupts( channel, true);
CHECK_SC( sc, "Enable error interrupts");
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc55xx_edma_release_channel( int channel)
{
// TODO
return RTEMS_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,659 @@
/**
* @file
*
* @ingroup mpc55xx_esci
*
* @brief Source file for the Enhanced Serial Communication Interface (eSCI).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
/* Include order is important */
#include <mpc55xx/regs.h>
#include <mpc55xx/esci.h>
#include <bsp/irq.h>
#include <unistd.h>
#include <termios.h>
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/console.h>
#include <rtems/bspIo.h>
#define RTEMS_STATUS_CHECKS_USE_PRINTK
#include <rtems/status-checks.h>
/* Evil define conflicts */
#define TERMIOS_CR1 CR1
#undef CR1
#define TERMIOS_CR2 CR2
#undef CR2
#define MPC55XX_ESCI_IRQ_PRIORITY MPC55XX_INTC_MIN_PRIORITY
#define MPC55XX_ESCI_IS_MINOR_INVALD(minor) ((minor) < 0 || (minor) >= MPC55XX_ESCI_NUMBER)
#define MPC55XX_ESCI_USE_INTERRUPTS(e) (!(e)->console && (e)->use_interrupts)
/**
* @brief eSCI driver table.
*/
mpc55xx_esci_driver_entry mpc55xx_esci_driver_table [MPC55XX_ESCI_NUMBER] = { {
.regs = &ESCI_A,
.device_name = "/dev/tty1",
.use_termios = 1,
.use_interrupts = 0,
.console = 1,
.tty = NULL,
.irq_number = 146
}, {
.regs = &ESCI_B,
.device_name = "/dev/tty2",
.use_termios = 1,
.use_interrupts = 0,
.console = 0,
.tty = NULL,
.irq_number = 149
}
};
/**
* @brief Default termios configuration.
*/
static const struct termios mpc55xx_esci_termios_default = {
0,
0,
CS8 | CREAD | CLOCAL | B115200,
0,
0,
{ 0 }
};
/**
* @name Low-Level
* @{
*/
/**
* @brief Reads one character from the receive register.
*
* @note Waits for the receive data register full flag.
*/
static inline uint8_t mpc55xx_esci_read_char( mpc55xx_esci_driver_entry *e)
{
volatile union ESCI_SR_tag *status = &e->regs->SR;
volatile union ESCI_DR_tag *data = &e->regs->DR;
union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
while (status->B.RDRF == 0) {
/* Wait */
}
/* Clear flag */
sr.B.RDRF = 1;
status->R = sr.R;
/* Read */
return data->B.D;
}
/**
* @brief Writes the character @a c to the transmit register.
*
* @note Waits for the transmit data register empty flag.
*/
static inline void mpc55xx_esci_write_char( mpc55xx_esci_driver_entry *e, uint8_t c)
{
volatile union ESCI_SR_tag *status = &e->regs->SR;
volatile union ESCI_DR_tag *data = &e->regs->DR;
union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
while (status->B.TDRE == 0) {
/* Wait */
}
/* Clear flag */
sr.B.TDRE = 1;
status->R = sr.R;
/* Write */
data->B.D = c;
}
/** @} */
/**
* @name Termios Support
* @{
*/
/**
* @brief Opens port @a minor.
*
* @return Status code.
*/
static int mpc55xx_esci_termios_first_open( int major, int minor, void *arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
union ESCI_CR1_tag cr1 = MPC55XX_ZERO_FLAGS;
struct rtems_termios_tty *tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
/* Connect TTY */
e->tty = tty;
/* Enable interrupts */
if (MPC55XX_ESCI_USE_INTERRUPTS( e)) {
cr1.R = e->regs->CR1.R;
cr1.B.RIE = 1;
cr1.B.TIE = 1;
e->regs->CR1.R = cr1.R;
}
return RTEMS_SUCCESSFUL;
}
/**
* @brief Closes port @a minor.
*
* @return Status code.
*/
static int mpc55xx_esci_termios_last_close( int major, int minor, void* arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
union ESCI_CR1_tag cr1 = MPC55XX_ZERO_FLAGS;
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
/* Disable interrupts */
cr1.R = e->regs->CR1.R;
cr1.B.RIE = 0;
cr1.B.TIE = 0;
e->regs->CR1.R = cr1.R;
/* Disconnect TTY */
e->tty = NULL;
return RTEMS_SUCCESSFUL;
}
/**
* @brief Reads one character from port @a minor.
*
* @return Returns the character or -1 on error.
*/
static int mpc55xx_esci_termios_poll_read( int minor)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return -1;
}
return (int) mpc55xx_esci_read_char( e);
}
/**
* @brief Writes @a n characters from @a out to port @a minor.
*
* @return Returns 0 on success or -1 otherwise.
*/
static int mpc55xx_esci_termios_poll_write( int minor, const char *out, int n)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
int i = 0;
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return -1;
}
/* Write */
for (i = 0; i < n; ++i) {
mpc55xx_esci_write_char( e, out [i]);
if (out [i] == '\n') {
mpc55xx_esci_write_char( e, '\r');
}
}
return 0;
}
/**
* @brief Writes one character from @a out to port @a minor.
*
* @return Returns always 0.
*
* @note The buffer @a out has to provide at least one character.
* This function assumes that the transmit data register is empty.
*/
static int mpc55xx_esci_termios_write( int minor, const char *out, int n)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Write */
e->regs->DR.B.D = out [0];
return 0;
}
/**
* @brief Sets attributes of port @a minor according to termios attributes @a t.
*
* @return Status code.
*/
static int mpc55xx_esci_termios_set_attributes( int minor, const struct termios *t)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
volatile struct ESCI_tag *regs = e->regs;
union ESCI_CR1_tag cr1 = MPC55XX_ZERO_FLAGS;
union ESCI_CR2_tag cr2 = MPC55XX_ZERO_FLAGS;
unsigned br = 0;
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
/* Enable module */
cr2.B.MDIS = 0;
/* Interrupts */
if (MPC55XX_ESCI_USE_INTERRUPTS( e) && e->tty != NULL) {
cr1.B.RIE = 1;
cr1.B.TIE = 1;
} else {
cr1.B.RIE = 0;
cr1.B.TIE = 0;
}
cr1.B.TCIE = 0;
cr1.B.ILIE = 0;
cr2.B.IEBERR = 0;
cr2.B.ORIE = 0;
cr2.B.NFIE = 0;
cr2.B.FEIE = 0;
cr2.B.PFIE = 0;
/* Disable receiver wake-up standby */
cr1.B.RWU = 0;
/* Disable DMA channels */
cr2.B.RXDMA = 0;
cr2.B.TXDMA = 0;
/* Idle line type */
cr1.B.ILT = 0;
/* Disable loops */
cr1.B.LOOPS = 0;
/* Enable or disable receiver */
cr1.B.RE = (t->c_cflag & CREAD) ? 1 : 0;
/* Enable transmitter */
cr1.B.TE = 1;
/* Baud rate */
switch (t->c_cflag & CBAUD) {
case B50: br = 50; break;
case B75: br = 75; break;
case B110: br = 110; break;
case B134: br = 134; break;
case B150: br = 150; break;
case B200: br = 200; break;
case B300: br = 300; break;
case B600: br = 600; break;
case B1200: br = 1200; break;
case B1800: br = 1800; break;
case B2400: br = 2400; break;
case B4800: br = 4800; break;
case B9600: br = 9600; break;
case B19200: br = 19200; break;
case B38400: br = 38400; break;
case B57600: br = 57600; break;
case B115200: br = 115200; break;
case B230400: br = 230400; break;
case B460800: br = 460800; break;
default: br = 0; break;
}
if (br > 0) {
// FIXME, TODO
extern uint32_t bsp_clock_speed;
br = bsp_clock_speed / (16 * br);
br = (br > 8191) ? 8191 : br;
} else {
br = 0;
}
cr1.B.SBR = br;
/* Number of data bits */
if ((t->c_cflag & CSIZE) != CS8) {
return RTEMS_IO_ERROR;
}
cr1.B.M = 0;
/* Parity */
cr1.B.PE = (t->c_cflag & PARENB) ? 1 : 0;
cr1.B.PT = (t->c_cflag & PARODD) ? 1 : 0;
/* Stop bits */
if ( t->c_cflag & CSTOPB ) {
/* Two stop bits */
return RTEMS_IO_ERROR;
}
/* Set control registers */
regs->CR1.R = cr1.R;
regs->CR2.R = cr2.R;
/* Disable LIN */
regs->LCR.R = 0;
return RTEMS_SUCCESSFUL;
}
/**
* @brief Interrupt handler.
*/
static void mpc55xx_esci_termios_interrupt_handler( rtems_vector_number vector, void *arg)
{
mpc55xx_esci_driver_entry *e = (mpc55xx_esci_driver_entry *) arg;
volatile union ESCI_SR_tag *status = &e->regs->SR;
volatile union ESCI_DR_tag *data = &e->regs->DR;
union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
union ESCI_SR_tag active = MPC55XX_ZERO_FLAGS;
/* Status */
sr.R = status->R;
/* Receive data register full? */
if (sr.B.RDRF != 0) {
active.B.RDRF = 1;
}
/* Transmit data register empty? */
if (sr.B.TDRE != 0) {
active.B.TDRE = 1;
}
/* Clear flags */
status->R = active.R;
/* Enqueue */
if (active.B.RDRF != 0) {
char c = data->B.D;
rtems_termios_enqueue_raw_characters( e->tty, &c, 1);
}
/* Dequeue */
if (active.B.TDRE != 0) {
rtems_termios_dequeue_characters( e->tty, 1);
}
}
/** @} */
/**
* @brief Termios callbacks with interrupt support.
*/
static const rtems_termios_callbacks mpc55xx_esci_termios_callbacks = {
.firstOpen = mpc55xx_esci_termios_first_open,
.lastClose = mpc55xx_esci_termios_last_close,
.pollRead = NULL,
.write = mpc55xx_esci_termios_write,
.setAttributes = mpc55xx_esci_termios_set_attributes,
.stopRemoteTx = NULL,
.startRemoteTx = NULL,
.outputUsesInterrupts = TERMIOS_IRQ_DRIVEN
};
/**
* @brief Termios callbacks with polling functions (no interrupts).
*/
static const rtems_termios_callbacks mpc55xx_esci_termios_callbacks_polled = {
.firstOpen = mpc55xx_esci_termios_first_open,
.lastClose = mpc55xx_esci_termios_last_close,
.pollRead = mpc55xx_esci_termios_poll_read,
.write = mpc55xx_esci_termios_poll_write,
.setAttributes = mpc55xx_esci_termios_set_attributes,
.stopRemoteTx = NULL,
.startRemoteTx = NULL,
.outputUsesInterrupts = TERMIOS_POLLED
};
/**
* @name Console Driver
* @{
*/
rtems_device_driver console_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
int console_done = 0;
int termios_do_init = 1;
int i = 0;
mpc55xx_esci_driver_entry *e = NULL;
for (i = 0; i < MPC55XX_ESCI_NUMBER; ++i) {
e = &mpc55xx_esci_driver_table [i];
sc = rtems_io_register_name ( e->device_name, major, i);
CHECK_SC( sc, "Register IO device");
if (e->console) {
if (console_done) {
SYSLOG_WARNING( "Multiple console ports defined\n");
} else {
console_done = 1;
if (e->use_interrupts) {
SYSLOG_WARNING( "Cannot use interrupts for console port\n");
}
sc = rtems_io_register_name( CONSOLE_DEVICE_NAME, major, i);
CHECK_SC( sc, "Register IO device");
}
}
if (e->use_termios && termios_do_init) {
if (termios_do_init) {
termios_do_init = 0;
rtems_termios_initialize();
}
if (MPC55XX_ESCI_USE_INTERRUPTS( e)) {
sc = mpc55xx_interrupt_handler_install(
e->irq_number,
MPC55XX_ESCI_IRQ_PRIORITY,
"eSCI",
RTEMS_INTERRUPT_UNIQUE,
mpc55xx_esci_termios_interrupt_handler,
e
);
CHECK_SC( sc, "Install IRQ handler");
}
}
mpc55xx_esci_termios_set_attributes( minor, &mpc55xx_esci_termios_default);
}
return RTEMS_SUCCESSFUL;
}
rtems_device_driver console_open( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
int rv = 0;
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
if (e->use_termios) {
if (MPC55XX_ESCI_USE_INTERRUPTS( e)) {
sc = rtems_termios_open( major, minor, arg, &mpc55xx_esci_termios_callbacks);
} else {
sc = rtems_termios_open( major, minor, arg, &mpc55xx_esci_termios_callbacks_polled);
}
if (sc != RTEMS_SUCCESSFUL) {
return sc;
}
rv = rtems_termios_set_initial_baud( e->tty, 115200);
if (rv < 0) {
return RTEMS_IO_ERROR;
}
}
return RTEMS_SUCCESSFUL;
}
rtems_device_driver console_close( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
if (e->use_termios) {
return rtems_termios_close( arg);
}
return RTEMS_SUCCESSFUL;
}
rtems_device_driver console_read( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
if (e->use_termios) {
return rtems_termios_read( arg);
} else {
rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
uint32_t i = 0;
while (i < rw->count) {
rw->buffer [i] = mpc55xx_esci_read_char( e);
++i;
}
rw->bytes_moved = i;
}
return RTEMS_SUCCESSFUL;
}
rtems_device_driver console_write( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
if (e->use_termios) {
return rtems_termios_write( arg);
} else {
rtems_libio_rw_args_t *rw = (rtems_libio_rw_args_t *) arg;
uint32_t i = 0;
while (i < rw->count) {
mpc55xx_esci_write_char( e, rw->buffer [i]);
if (rw->buffer [i] == '\n') {
mpc55xx_esci_write_char( e, '\r');
}
++i;
}
rw->bytes_moved = i;
}
return RTEMS_SUCCESSFUL;
}
rtems_device_driver console_control( rtems_device_major_number major, rtems_device_minor_number minor, void *arg)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [minor];
/* Check minor number */
if (MPC55XX_ESCI_IS_MINOR_INVALD( minor)) {
return RTEMS_INVALID_NUMBER;
}
if (e->use_termios) {
return rtems_termios_ioctl( arg);
}
return RTEMS_NOT_DEFINED;
}
/** @} */
/**
* @brief Port number for the BSP character output function.
*
* The correct value will be set by mpc55xx_esci_output_char_init().
*/
static unsigned mpc55xx_esci_output_char_minor = 0;
/**
* @name BSP Character Output
* @{
*/
static void mpc55xx_esci_output_char( char c)
{
mpc55xx_esci_driver_entry *e = &mpc55xx_esci_driver_table [mpc55xx_esci_output_char_minor];
mpc55xx_esci_write_char( e, c);
if (c == '\n') {
mpc55xx_esci_write_char( e, '\r');
}
}
static void mpc55xx_esci_output_char_nop( char c)
{
/* Do nothing */
}
static void mpc55xx_esci_output_char_init( char c)
{
int console_found = 0;
unsigned i = 0;
for (i = 0; i < MPC55XX_ESCI_NUMBER; ++i) {
if (mpc55xx_esci_driver_table [i].console) {
console_found = 1;
mpc55xx_esci_output_char_minor = i;
break;
}
}
if (console_found) {
BSP_output_char = mpc55xx_esci_output_char;
mpc55xx_esci_termios_set_attributes( mpc55xx_esci_output_char_minor, &mpc55xx_esci_termios_default);
mpc55xx_esci_output_char( c);
} else {
BSP_output_char = mpc55xx_esci_output_char_nop;
}
}
/** @} */
BSP_output_char_function_type BSP_output_char = mpc55xx_esci_output_char_init;

View File

@@ -0,0 +1,19 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Device driver for the Fast Ethernet Controller
*
* @par Copyright
* Copyright (c) 2008<br>
* Embedded Brains GmbH<br>
* Obere Lagerstr. 30<br>
* D-82178 Puchheim<br>
* Germany<br>
* rtems@embedded-brains.de<br>
*
* @par License
* 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.
*/

View File

@@ -0,0 +1,135 @@
/**
* @file
*
* @ingroup mpc55xx_dspi
*
* @brief Header file for the LibI2C bus driver for the Deserial Serial Peripheral Interface (DSPI).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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.
*/
/**
* @defgroup mpc55xx_dspi Deserial Serial Peripheral Interface (DSPI)
*
* @ingroup mpc55xx
*/
#ifndef LIBCPU_POWERPC_MPC55XX_DSPI_H
#define LIBCPU_POWERPC_MPC55XX_DSPI_H
#include <rtems/libi2c.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
struct DSPI_tag;
/**
* @brief LibI2C bus driver entry.
*/
typedef struct {
/**
* @brief Standard bus driver fields.
*/
rtems_libi2c_bus_t bus;
/**
* @brief Index in the bus table: @ref mpc55xx_dspi_bus_table.
*/
unsigned table_index;
/**
* @brief Bus number (available after rtems_libi2c_register_bus()).
*
* @note You must set it in the initialization code after the bus registration.
*/
unsigned bus_number;
/**
* @brief Hardware registers.
*/
volatile struct DSPI_tag *regs;
/**
* @brief Selects SPI master or slave mode.
*/
int master;
/**
* @brief Data for the Push Register.
*/
union DSPI_PUSHR_tag push_data;
/**
* @brief eDMA channel for transmission.
*
* The channel is fixed to particular DSPI.
*/
int edma_channel_transmit;
/**
* @brief eDMA channel to generate the push data.
*
* You can choose any available channel.
*/
int edma_channel_push;
/**
* @brief eDMA channel for receiving.
*
* The channel is fixed to particular DSPI.
*/
int edma_channel_receive;
/**
* @brief Semaphore ID for a transmit update.
*/
rtems_id edma_channel_transmit_update;
/**
* @brief Semaphore ID for a receive update.
*/
rtems_id edma_channel_receive_update;
/**
* @brief Transmit error status.
*/
uint32_t edma_channel_transmit_error;
/**
* @brief Receive error status.
*/
uint32_t edma_channel_receive_error;
/**
* @brief Idle character transmitted in read only mode.
*/
uint32_t idle_char;
} mpc55xx_dspi_bus_entry;
/**
* @brief Number of DSPIs.
*/
#define MPC55XX_DSPI_NUMBER 4
/**
* @brief Table with bus driver entries.
*/
extern mpc55xx_dspi_bus_entry mpc55xx_dspi_bus_table [ /* MPC55XX_DSPI_NUMBER */ ];
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LIBCPU_POWERPC_MPC55XX_DSPI_H */

View File

@@ -0,0 +1,102 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Enhanced Direct Memory Access (eDMA).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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 LIBCPU_POWERPC_MPC55XX_EDMA_H
#define LIBCPU_POWERPC_MPC55XX_EDMA_H
#include <stdbool.h>
#include <rtems.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define MPC55XX_EDMA_TCD_DEFAULT { \
.SADDR = 0, \
.SMOD = 0, \
.SSIZE = 0x2, \
.SOFF = 4, \
.DADDR = 0, \
.DMOD = 0, \
.DSIZE = 0x2, \
.DOFF = 4, \
.NBYTES = 0, \
.SLAST = 0, \
.CITER = 1, \
.BITER = 1, \
.MAJORLINKCH = 0, \
.CITERE_LINK = 0, \
.BITERE_LINK = 0, \
.MAJORE_LINK = 0, \
.E_SG = 0, \
.DLAST_SGA = 0, \
.D_REQ = 0, \
.BWC = 0, \
.INT_HALF = 0, \
.INT_MAJ = 0, \
.DONE = 0, \
.ACTIVE = 0, \
.START = 0, \
}
#define MPC55XX_EDMA_TCD_ALT_DEFAULT { \
.SADDR = 0, \
.SMOD = 0, \
.SSIZE = 2, \
.DMOD = 0, \
.DSIZE = 2, \
.SOFF = 4, \
.NBYTES = 0, \
.SLAST = 0, \
.DADDR = 0, \
.CITERE_LINK = 0, \
.CITERLINKCH = 0, \
.CITER = 0, \
.DOFF = 4, \
.DLAST_SGA = 0, \
.BITERE_LINK = 0, \
.BITERLINKCH = 0, \
.BITER = 0, \
.BWC = 0, \
.MAJORLINKCH = 0, \
.DONE = 0, \
.ACTIVE = 0, \
.MAJORE_LINK = 0, \
.E_SG = 0, \
.D_REQ = 0, \
.INT_HALF = 0, \
.INT_MAJ = 0, \
.START = 0, \
}
rtems_status_code mpc55xx_edma_init();
rtems_status_code mpc55xx_edma_obtain_channel( int channel, uint32_t *error_status, rtems_id transfer_update);
rtems_status_code mpc55xx_edma_enable_hardware_requests( int channel, bool enable);
rtems_status_code mpc55xx_edma_enable_error_interrupts( int channel, bool enable);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* LIBCPU_POWERPC_MPC55XX_EDMA_H */

View File

@@ -0,0 +1,48 @@
/**
* @file
*
* @ingroup mpc55xx_esci
*
* @brief Header file for the Enhanced Serial Communication Interface (eSCI).
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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.
*/
/**
* @defgroup mpc55xx_esci Enhanced Serial Communication Interface (eSCI).
*
* @ingroup mpc55xx
*/
#ifndef LIBCPU_POWERPC_MPC55XX_ESCI_H
#define LIBCPU_POWERPC_MPC55XX_ESCI_H
#include <rtems/termiostypes.h>
#define MPC55XX_ESCI_NUMBER 2
struct ESCI_tag;
typedef struct {
volatile struct ESCI_tag *regs;
const char *device_name;
int use_termios;
int use_interrupts;
int console;
struct rtems_termios_tty *tty;
unsigned irq_number;
} mpc55xx_esci_driver_entry;
extern mpc55xx_esci_driver_entry mpc55xx_esci_driver_table [ /* MPC55XX_ESCI_NUMBER */ ];
#endif /* LIBCPU_POWERPC_MPC55XX_ESCI_H */

View File

@@ -0,0 +1,92 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief IRQ
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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_IRQ_H
#define LIBBSP_POWERPC_IRQ_H
#include <rtems/irq-extension.h>
#include <rtems/irq.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Interrupt numbers
*/
/* Basics */
#define MPC55XX_IRQ_MIN 0
#define MPC55XX_IRQ_MAX 328
#define MPC55XX_IRQ_BASE MPC55XX_IRQ_MIN
#define MPC55XX_IRQ_NUMBER (MPC55XX_IRQ_MAX + 1)
/* Software interrupts */
#define MPC55XX_IRQ_SOFTWARE_MIN 0
#define MPC55XX_IRQ_SOFTWARE_MAX 7
#define MPC55XX_IRQ_SOFTWARE_NUMBER (MPC55XX_IRQ_SOFTWARE_MAX + 1)
/* eDMA interrupts */
#define MPC55XX_IRQ_EDMA_ERROR_LOW 10
#define MPC55XX_IRQ_EDMA_ERROR_HIGH 210
#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN 11
#define MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX 42
#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN 211
#define MPC55XX_IRQ_EDMA_REQUEST_HIGH_MAX 242
#define MPC55XX_IRQ_EDMA_GET_CHANNEL( i) (((i) > MPC55XX_IRQ_EDMA_REQUEST_LOW_MAX) ? ((i) - MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN + 32) : ((i) - MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
#define MPC55XX_IRQ_EDMA_GET_REQUEST( c) (((c) > 31) ? ((c) + MPC55XX_IRQ_EDMA_REQUEST_HIGH_MIN - 32) : ((c) + MPC55XX_IRQ_EDMA_REQUEST_LOW_MIN))
/* Checks */
#define MPC55XX_IRQ_IS_VALID(i) ((i) >= MPC55XX_IRQ_MIN && (i) <= MPC55XX_IRQ_MAX)
#define MPC55XX_IRQ_IS_SOFTWARE(i) ((i) >= MPC55XX_IRQ_SOFTWARE_MIN && (i) <= MPC55XX_IRQ_SOFTWARE_MAX)
/*
* Interrupt controller
*/
#define MPC55XX_INTC_INVALID_PRIORITY -1
#define MPC55XX_INTC_DISABLED_PRIORITY 0
#define MPC55XX_INTC_MIN_PRIORITY 1
#define MPC55XX_INTC_MAX_PRIORITY 15
#define MPC55XX_INTC_DEFAULT_PRIORITY MPC55XX_INTC_MIN_PRIORITY
#define MPC55XX_INTC_IS_VALID_PRIORITY(p) ((p) >= MPC55XX_INTC_DISABLED_PRIORITY && (p) <= MPC55XX_INTC_MAX_PRIORITY)
rtems_status_code mpc55xx_interrupt_handler_install(
rtems_vector_number vector,
int priority,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
);
rtems_status_code mpc55xx_intc_get_priority( int i, int *p);
rtems_status_code mpc55xx_intc_set_priority( int i, int p);
rtems_status_code mpc55xx_intc_raise_software_irq( int i);
rtems_status_code mpc55xx_intc_clear_software_irq( int i);
#ifdef __cplusplus
};
#endif /* __cplusplus */
#endif /* LIBBSP_POWERPC_IRQ_H */

View File

@@ -0,0 +1,111 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Documentation for this file
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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.
*/
/**
* @defgroup mpc55xx BSP for MPC55xx boards
*/
/**
* @defgroup mpc55xx_config Configuration files
*
* @ingroup mpc55xx
*
* Makefiles, configure scripts etc.
*/
/**
* @page mpc55xx_ext_doc External Documentation
*
* @section mpc55xx_ext_doc_mpc5567rm_1 MPC5567 Microcontroller Reference Manual (Rev. 1, January 2007, Volume 1 of 2)
* @section mpc55xx_ext_doc_mpc5567rm_2 MPC5567 Microcontroller Reference Manual (Rev. 1, January 2007, Volume 2 of 2)
*/
#ifndef LIBCPU_POWERPC_MPC55XX_H
#define LIBCPU_POWERPC_MPC55XX_H
#include <stddef.h>
#include <stdint.h>
/* Defined in copy.S */
int mpc55xx_copy_8( const void *src, void *dest, size_t n);
/* Defined in copy.S */
int mpc55xx_zero_8( void *dest, size_t n);
/* Defined in copy.S */
int mpc55xx_zero_32( void *dest, size_t n);
/* Defined in fmpll.S */
void mpc55xx_fmpll_reset_config();
/* Defined in fmpll.S */
void mpc55xx_fmpll_wait_for_lock();
/* Defined in fmpll.S */
int mpc55xx_get_system_clock();
/* Defined in fmpll.S */
void mpc55xx_system_reset();
/* Defined in flash.S */
void mpc55xx_flash_config();
#define MPC55XX_CACHE_ALIGNED_MASK ((uintptr_t) 0x1f)
#define MPC55XX_CACHE_LINE_SIZE 32
/**
* @brief Returns true if the buffer starting at @a s of size @a n is cache aligned.
*/
static inline int mpc55xx_is_cache_aligned( const void *s, size_t n)
{
return !(((uintptr_t) s & MPC55XX_CACHE_ALIGNED_MASK) || (n & MPC55XX_CACHE_ALIGNED_MASK));
}
static inline void* mpc55xx_cache_aligned_start( const void *s)
{
return ((uintptr_t) s & MPC55XX_CACHE_ALIGNED_MASK) ? (((uintptr_t) s & ~MPC55XX_CACHE_ALIGNED_MASK) + MPC55XX_CACHE_LINE_SIZE) : s;
}
static inline size_t mpc55xx_non_cache_aligned_size( const void *s)
{
return (uintptr_t) mpc55xx_cache_aligned_start( s) - (uintptr_t) s;
}
static inline size_t mpc55xx_cache_aligned_size( const void *s, size_t n)
{
return (n - mpc55xx_non_cache_aligned_size( s)) & ~MPC55XX_CACHE_ALIGNED_MASK;
}
/**
* @brief Returns the number of leading zeros.
*/
static inline uint32_t mpc55xx_count_leading_zeros( uint32_t value)
{
uint32_t count;
asm (
"cntlzw %0, %1;"
: "=r" (count)
: "r" (value)
);
return count;
}
#endif /* LIBCPU_POWERPC_MPC55XX_H */

View File

@@ -0,0 +1,193 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Register definitions.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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 LIBCPU_POWERPC_MPC55XX_REG_DEFS_H
#define LIBCPU_POWERPC_MPC55XX_REG_DEFS_H
/*
* Register addresses
*/
#define FMPLL_SYNCR 0xC3F80000
#define FMPLL_SYNSR 0xC3F80004
#define FLASH_BIUCR 0xC3F8801C
#define SIU_ECCR 0xC3F90984
#define SIU_SRCR 0xC3F90010
/*
* Special purpose registers
*/
#define BUCSR 1013
/*
* Branch Unit Control and Status Register (BUCSR)
*/
#define BUCSR_BBFI 0x00000200
#define BUCSR_BPEN 0x00000001
/*
* Definitions for FMPLL_SYNCR (FMPLL Synthesizer Control Register)
*/
/* Fields used for PREDIV (Pre-Divider bits [1:3]) */
#define FMPLL_SYNCR_PREDIV_0 0x00000000
/* Fields used for MFD (Muliplication Factor Divider bits [4:8]) */
#define FMPLL_SYNCR_MFD_0 0x00000000
#define FMPLL_SYNCR_MFD_2 0x01000000
#define FMPLL_SYNCR_MFD_4 0x02000000
#define FMPLL_SYNCR_MFD_6 0x03000000
#define FMPLL_SYNCR_MFD_8 0x04000000
#define FMPLL_SYNCR_MFD_10 0x05000000
#define FMPLL_SYNCR_MFD_12 0x06000000
/* Fields used for RFD (Reduced Frequency Divider bits [10:12]) */
#define FMPLL_SYNCR_RFD_0 0x00000000
#define FMPLL_SYNCR_RFD_1 0x00080000
#define FMPLL_SYNCR_RFD_2 0x00100000
#define FMPLL_SYNCR_RFD_3 0x00180000
#define FMPLL_SYNCR_RFD_4 0x00200000
#define FMPLL_SYNCR_RFD_5 0x00280000
#define FMPLL_SYNCR_RFD_6 0x00300000
#define FMPLL_SYNCR_RFD_7 0x00380000
/* Fields for LOCEN (Loss-of-clock enable bit [13]) */
#define FMPLL_SYNCR_LOCEN 0x00040000
/* Fields for LOLRE (Loss-of-lock reset enable bit [14]) */
#define FMPLL_SYNCR_LOLRE 0x00020000
/* Fields for LOCRE (Loss-of-clock reset enable bit [15]) */
#define FMPLL_SYNCR_LOCRE 0x00010000
/* Fields for DISCLK (Disable CLKOUT bit [16]) */
#define FMPLL_SYNCR_DISCLK 0x00008000
/* Fields for LOLIRQ (Loss-of-lock interrupt request bit [17]) */
#define FMPLL_SYNCR_LOLIRQ 0x00004000
/* Fields for LOCIRQ (Loss-of-clock interrupt request bit [18]) */
#define FMPLL_SYNCR_LOCIRQ 0x00002000
/* Fields for RATE (Modulation rate bit [19]) */
#define FMPLL_SYNCR_RATE_FREF 0x00001000
/* Fields for DEPTH (Modulation depth percentage bits [20:21]) */
#define FMPLL_SYNCR_DEPTH_0 0x00000000
#define FMPLL_SYNCR_DEPTH_1 0x00000400
#define FMPLL_SYNCR_DEPTH_2 0x00000800
/* Fields for EXP (Expected difference bits [22:31]) */
#define FMPLL_SYNCR_EXP_0 0x00000000
/*
* Definitions for the FMPLL_SYNSR (Synthesizer Status Register)
*/
/* Fields for LOLF (Loss-of-lock flag bit [22]) */
#define FMPLL_SYNSR_LOLF 0x00000200
/* Fields for LOCK (Lock status bit [28]) */
#define FMPLL_SYNSR_LOCK 0x00000008
/* Fields for LOCF (Loss-of-clock flag bit [29]) */
#define FMPLL_SYNSR_LOCF 0x00000004
/*
* Definitions for the SIU_SRCR (System Reset Control Register)
*/
/* Fields for SSR (software system reset bit [0]) */
#define SIU_SRCR_SSR 0x80000000
/* Fields for SER (external system reset bit [1]) */
#define SIU_SRCR_SER 0x40000000
/* Fields for CRE (checkstop reset enable bit [16]) */
#define SIU_SRCR_CRE 0x00008000
/*
* Definitions for FLASH_BIUCR (Flash BIU Control Register)
*/
/* Fields for Flash Bus Interface Control */
/* Fields for Prefetch Control (MnPFE Master n Prefetch Enable) */
/* Fields for M3PFE (Master 3 (EBI) prefetch enable bit [12]) */
#define FLASH_BUICR_EBI_PREFTCH 0x00080000
/* Fields for M2PFE (Master 2 (eDMA) prefetch enable bit [13]) */
#define FLASH_BUICR_EDMA_PREFTCH 0x00040000
/* Fields for M1PFE (Master 1 (Nexus) prefetch enable bit [14]) */
#define FLASH_BUICR_NEX_PREFTCH 0x00020000
/* Fields for M0PFE (Master 0 (e200z core) prefetch enable bit [15]) */
#define FLASH_BUICR_CPU_PREFTCH 0x00010000
/* Fields for APC (access pipelining control bits [16:18]) */
#define FLASH_BUICR_APC_1 0x00002000
#define FLASH_BUICR_APC_2 0x00004000
#define FLASH_BUICR_APC_3 0x00006000
#define FLASH_BUICR_APC_4 0x00008000
#define FLASH_BUICR_APC_5 0x0000A000
#define FLASH_BUICR_APC_6 0x0000C000
#define FLASH_BUICR_APC_NO 0x0000E000
/* Fields for WWSC (write wait state control bits [19:20]) */
#define FLASH_BUICR_WWSC_1 0x00000800
#define FLASH_BUICR_WWSC_2 0x00001000
#define FLASH_BUICR_WWSC_3 0x00001800
/* Fields for RWSC (read wait state control bits [21:23]) */
#define FLASH_BUICR_RWSC_0 0x00000000
#define FLASH_BUICR_RWSC_1 0x00000100
#define FLASH_BUICR_RWSC_2 0x00000200
#define FLASH_BUICR_RWSC_3 0x00000300
#define FLASH_BUICR_RWSC_4 0x00000400
#define FLASH_BUICR_RWSC_5 0x00000500
#define FLASH_BUICR_RWSC_6 0x00000600
#define FLASH_BUICR_RWSC_7 0x00000700
/* Fields for DPFEN (data prefetch enable bits [24:25]) */
#define FLASH_BUICR_DPFEN_0 0x00000000
#define FLASH_BUICR_DPFEN_1 0x00000040
#define FLASH_BUICR_DPFEN_3 0x000000C0
/* Fields for IPFEN (instruction prefetch enable bits [26:27]) */
#define FLASH_BUICR_IPFEN_0 0x00000000
#define FLASH_BUICR_IPFEN_1 0x00000010
#define FLASH_BUICR_IPFEN_3 0x00000030
/* Fields for PFLIM (additional line prefetch (limit) bits [28:30]) */
#define FLASH_BUICR_PFLIM_0 0x00000000
#define FLASH_BUICR_PFLIM_1 0x00000002
#define FLASH_BUICR_PFLIM_2 0x00000004
#define FLASH_BUICR_PFLIM_3 0x00000006
#define FLASH_BUICR_PFLIM_4 0x00000008
#define FLASH_BUICR_PFLIM_5 0x0000000A
#define FLASH_BUICR_PFLIM_6 0x0000000C
/* Fields for BFEN (enable line read buffer hits bit [31]) */
#define FLASH_BUICR_BFEN 0x00000001
#endif /* LIBCPU_POWERPC_MPC55XX_REG_DEFS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,179 @@
/**
* @file
*
* @ingroup mpc55xx
*
* @brief Source file for MPC55XX interrupt support.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <mpc55xx/regs.h>
#include <libcpu/raw_exception.h>
#include <bsp/irq.h>
#include <bsp/irq-generic.h>
#include <bsp/ppc_exc_bspsupp.h>
#define RTEMS_STATUS_CHECKS_USE_PRINTK
#include <rtems/status-checks.h>
/**
* @brief Returns the priority @a p of IRQ @a i from the INTC.
*/
rtems_status_code mpc55xx_intc_get_priority( int i, int *p)
{
if (MPC55XX_IRQ_IS_VALID( i)) {
*p = INTC.PSR [i].B.PRI;
return RTEMS_SUCCESSFUL;
} else {
*p = MPC55XX_INTC_INVALID_PRIORITY;
return RTEMS_INVALID_NUMBER;
}
}
/**
* @brief Sets the priority of IRQ @a i to @a p at the INTC.
*/
rtems_status_code mpc55xx_intc_set_priority( int i, int p)
{
if (MPC55XX_IRQ_IS_VALID( i) && MPC55XX_INTC_IS_VALID_PRIORITY( p)) {
INTC.PSR [i].B.PRI = p;
if (INTC.PSR [i].B.PRI == p) {
return RTEMS_SUCCESSFUL;
} else {
return RTEMS_IO_ERROR;
}
} else {
return RTEMS_INVALID_NUMBER;
}
}
/**
* @brief Raises the software IRQ with number @a i.
*/
rtems_status_code mpc55xx_intc_raise_software_irq( int i)
{
if (MPC55XX_IRQ_IS_SOFTWARE( i)) {
INTC.SSCIR [i].B.SET = 1;
return RTEMS_SUCCESSFUL;
} else {
return RTEMS_INVALID_NUMBER;
}
}
/**
* @brief Clears the software IRQ with number @a i.
*/
rtems_status_code mpc55xx_intc_clear_software_irq( int i)
{
if (MPC55XX_IRQ_IS_SOFTWARE( i)) {
INTC.SSCIR [i].B.CLR = 1;
return RTEMS_SUCCESSFUL;
} else {
return RTEMS_INVALID_NUMBER;
}
}
/**
* @brief Installs interrupt handler and sets priority.
*/
rtems_status_code mpc55xx_interrupt_handler_install(
rtems_vector_number vector,
int priority,
const char *info,
rtems_option options,
rtems_interrupt_handler handler,
void *arg
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
if (MPC55XX_IRQ_IS_VALID( vector) && MPC55XX_INTC_IS_VALID_PRIORITY( priority)) {
sc = rtems_interrupt_handler_install( vector, info, options, handler, arg);
CHECK_SC( sc, "Install interrupt handler");
return mpc55xx_intc_set_priority( vector, priority);
} else {
return RTEMS_INVALID_NUMBER;
}
}
/**
* @brief External exception handler.
*/
static int mpc55xx_external_exception_handler( BSP_Exception_frame *frame, unsigned exception_number)
{
/* Acknowlege interrupt request */
rtems_vector_number vector_number = INTC.IACKR.B.INTVEC;
/* Save current interrupt level */
uint32_t level = _ISR_Get_level();
/* Enable all interrupts */
_ISR_Set_level( 0);
/* Dispatch interrupt handlers */
bsp_interrupt_handler_dispatch( vector_number);
/* Restore interrupt level */
_ISR_Set_level( level);
/* End of interrupt */
INTC.EOIR.R = 1;
return 0;
}
rtems_status_code bsp_interrupt_facility_initialize()
{
/* Install exception handler */
if (ppc_exc_set_handler( ASM_EXT_VECTOR, mpc55xx_external_exception_handler)) {
return RTEMS_IO_ERROR;
}
/* Initialize interrupt controller */
/* Software vector mode */
INTC.MCR.B.VTES = 0;
INTC.MCR.B.HVEN = 0;
/* Set current priority to 0 */
INTC.CPR.B.PRI = 0;
return RTEMS_SUCCESSFUL;
}
rtems_status_code bsp_interrupt_vector_enable( rtems_vector_number vector)
{
if (MPC55XX_IRQ_IS_VALID( vector)) {
return mpc55xx_intc_set_priority( vector, MPC55XX_INTC_DEFAULT_PRIORITY);
} else {
return RTEMS_SUCCESSFUL;
}
}
rtems_status_code bsp_interrupt_vector_disable( rtems_vector_number vector)
{
if (MPC55XX_IRQ_IS_VALID( vector)) {
return mpc55xx_intc_set_priority( vector, MPC55XX_INTC_DISABLED_PRIORITY);
} else {
return RTEMS_SUCCESSFUL;
}
}
void bsp_interrupt_handler_default( rtems_vector_number vector)
{
/* Do nothing */
}

View File

@@ -0,0 +1,150 @@
/**
* @file
*
* @ingroup mpc55xx_asm
*
* @brief Memory copy and zero functions.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <libcpu/powerpc-utility.h>
.section ".text"
/**
* @fn int mpc55xx_copy_8( const void *src, void *dest, size_t n)
*
* @brief Copy @a n bytes from @a src to @a dest with 8 byte reads and writes.
*
* The memory areas should not overlap. The addresses @a src and @a dest have
* to be aligned on 8 byte boundaries. The size @a n must be evenly divisible by 8.
* The SPE operations @b evxor, @b evlddx and @b evstddx will be used.
*/
GLOBAL_FUNCTION mpc55xx_copy_8
/* Loop counter = data size / 8 */
srwi. r5, r5, 3
beqlr
mtctr r5
/* Set offset */
evxor r5, r5, r5
copy_data:
evlddx r6, r3, r5
evstddx r6, r4, r5
addi r5, r5, 8
bdnz copy_data
/* Return */
blr
/**
* @fn int mpc55xx_zero_8( void *dest, size_t n)
*
* @brief Zero all @a n bytes starting at @a dest with 8 byte writes.
*
* The address @a dest has to be aligned on 8 byte boundaries. The size @a n
* must be evenly divisible by 8. The SPE operations @b evxor and @b evstddx will be used.
*/
GLOBAL_FUNCTION mpc55xx_zero_8
/* Create zero */
evxor r0, r0, r0
/* Set offset */
evxor r5, r5, r5
/* Loop counter for the first bytes up to 32 bytes */
rlwinm. r9, r4, 29, 30, 31
beq zero_more
mtctr r9
zero_data:
evstddx r0, r3, r5
addi r5, r5, 8
bdnz zero_data
zero_more:
/* More than 32 bytes? */
srwi. r9, r4, 5
beqlr
mtctr r9
/* Set offsets */
addi r6, r5, 8
addi r7, r5, 16
addi r8, r5, 24
zero_big_data:
evstddx r0, r3, r5
addi r5, r5, 32
evstddx r0, r3, r6
addi r6, r6, 32
evstddx r0, r3, r7
addi r7, r7, 32
evstddx r0, r3, r8
addi r8, r8, 32
bdnz zero_big_data
/* Return */
blr
/**
* @fn int mpc55xx_zero_32( void *dest, size_t n)
*
* @brief Zero all @a n bytes starting at @a dest with 32 byte writes.
*
* The address @a dest has to be aligned on 32 byte boundaries. The size @a n
* must be evenly divisible by 32. The function operates with the cache block zero
* operation @b dcbz.
*
* @note The cache has to be enabled for the desired memory area.
*/
GLOBAL_FUNCTION mpc55xx_zero_32
/* Set offset */
xor r5, r5, r5
/* Loop counter for the first bytes up to 128 bytes */
rlwinm. r9, r4, 27, 28, 31
beq zero_more_lines
mtctr r9
zero_line:
dcbz r3, r5
addi r5, r5, 32
bdnz zero_line
zero_more_lines:
/* More than 128 bytes? */
srwi. r9, r4, 7
beqlr
mtctr r9
/* Set offsets */
addi r6, r5, 32
addi r7, r5, 64
addi r8, r5, 96
zero_big_line:
dcbz r3, r5
addi r5, r5, 128
dcbz r3, r6
addi r6, r6, 128
dcbz r3, r7
addi r7, r7, 128
dcbz r3, r8
addi r8, r8, 128
bdnz zero_big_line
/* Return */
blr

View File

@@ -0,0 +1,101 @@
/**
* @file
*
* @ingroup mpc55xx_asm
*
* @brief Flash configuration.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <libcpu/powerpc-utility.h>
#include <mpc55xx/reg-defs.h>
.section ".text"
/* Optimized flash configurations (Table 13-15 [MPC5567 Microcontroller Reference Manual]) */
.equ FLASH_SETTINGS_RESET, 0xff00
.equ FLASH_SETTINGS_82, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_1 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN
.equ FLASH_SETTINGS_102, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_1 | FLASH_BUICR_RWSC_2 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN
.equ FLASH_SETTINGS_132, FLASH_BUICR_CPU_PREFTCH | FLASH_BUICR_APC_2 | FLASH_BUICR_RWSC_3 | FLASH_BUICR_WWSC_1 | FLASH_BUICR_DPFEN_3 | FLASH_BUICR_IPFEN_3 | FLASH_BUICR_PFLIM_6 | FLASH_BUICR_BFEN
/**
* @fn void mpc55xx_flash_config()
* @brief Optimized flash configuration.
* @warning Code will be copied and executed on the stack. The stack pointer
* will not be updated, since this function has to work before memory
* initialization.
*/
GLOBAL_FUNCTION mpc55xx_flash_config
mflr r31
/* Flash settings dependent on system clock */
bl mpc55xx_get_system_clock
LWI r4, 82000000
cmpw r3, r4
ble clock_82
LWI r4, 102000000
cmpw r3, r4
ble clock_102
LWI r4, 132000000
cmpw r3, r4
ble clock_132
LWI r30, FLASH_SETTINGS_RESET
b settings_done
clock_82:
LWI r30, FLASH_SETTINGS_82
b settings_done
clock_102:
LWI r30, FLASH_SETTINGS_102
b settings_done
clock_132:
LWI r30, FLASH_SETTINGS_132
b settings_done
settings_done:
/* Copy store code on the stack */
LA r3, store_start
LA r5, store_end
subf r5, r3, r5
subf r4, r5, r1
/* Assert: Proper alignment of destination start */
andi. r6, r4, 0x7
bne twiddle
/* Copy */
bl mpc55xx_copy_8
LA r6, FLASH_BIUCR
/* Execute store code */
mtctr r4
bctrl
mtlr r31
blr
/*
* Store flash settings
*/
.align 3
.set store_start, .
stw r30, 0(r6)
isync
blr
.align 3
.set store_end, .
twiddle:
b twiddle

View File

@@ -0,0 +1,133 @@
/**
* @file
*
* @ingroup mpc55xx_asm
*
* @brief FMPLL setup.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <libcpu/powerpc-utility.h>
#include <mpc55xx/reg-defs.h>
.section ".text"
/* Timeout for delay in clocks */
.equ FMPLL_TIMEOUT, 6000
/* Reference clock */
.equ FMPLL_REF_CLOCK, 8000000
/* Settings for FMPLL from 12 MHz up to 128 MHz with 8 MHz reference frequency */
.equ FMPLL_128_8_SYNCR_SETTING_0, (FMPLL_SYNCR_PREDIV_0 | FMPLL_SYNCR_MFD_12 | FMPLL_SYNCR_RFD_2 | FMPLL_SYNCR_LOCEN)
.equ FMPLL_128_8_SYNCR_SETTING_1, (FMPLL_SYNCR_PREDIV_0 | FMPLL_SYNCR_MFD_12 | FMPLL_SYNCR_RFD_0 | FMPLL_SYNCR_LOCEN)
.macro DO_SETTING setting
LWI r5, FMPLL_128_8_SYNCR_SETTING_\setting
stw r5, 0(r4)
msync
bl mpc55xx_fmpll_wait_for_lock
.endm
/**
* @fn void mpc55xx_fmpll_reset_config()
* @brief Configure FMPLL after reset.
*
* Sets the system clock from 12 MHz in two steps up to 128 MHz.
*/
GLOBAL_FUNCTION mpc55xx_fmpll_reset_config
/* Save link register */
mflr r3
LA r4, FMPLL_SYNCR
DO_SETTING 0
DO_SETTING 1
/* Enable loss-of-clock and loss-of-lock IRQs */
lwz r5, 0(r4)
LWI r6, FMPLL_SYNCR_LOCIRQ | FMPLL_SYNCR_LOLIRQ
or r5, r5, r6
/* Disable loss-of-clock and loss-of-lock resets */
LWI r6, ~FMPLL_SYNCR_LOCRE & ~FMPLL_SYNCR_LOLRE
and r5, r5, r6
stw r5, 0(r4)
/* Restore link register and return */
mtlr r3
blr
/**
* @fn void mpc55xx_fmpll_wait_for_lock()
* @brief Wait for FMPLL lock.
* @warning If the lock cannot be obtained within some clock cycles a software
* system reset will be initiated.
*/
GLOBAL_FUNCTION mpc55xx_fmpll_wait_for_lock
LWI r6, FMPLL_TIMEOUT
mtctr r6
LWI r7, FMPLL_SYNSR_LOCK
LA r6, FMPLL_SYNSR
fmpll_not_locked:
bdnz fmpll_continue
b mpc55xx_system_reset
fmpll_continue:
lwz r8, 0(r6)
and. r8, r8, r7
beq fmpll_not_locked
blr
/**
* @fn int mpc55xx_get_system_clock()
* @brief Returns the system clock.
*/
GLOBAL_FUNCTION mpc55xx_get_system_clock
LA r4, FMPLL_SYNCR
lwz r3, 0(r4)
/* PREDIV */
rlwinm r5, r3, 4, 29, 31
/* MFD */
rlwinm r6, r3, 9, 27, 31
/* RFD */
rlwinm r7, r3, 13, 29, 31
/* Calculate system clock (Table 11-10 [MPC5567 Microcontroller Reference Manual]) */
LWI r8, FMPLL_REF_CLOCK
addi r5, r5, 1
addi r6, r6, 4
mullw r6, r6, r8
sraw r6, r6, r7
divw r3, r6, r5
blr
/**
* @fn void mpc55xx_system_reset()
* @brief Software system reset.
*/
GLOBAL_FUNCTION mpc55xx_system_reset
LA r8, SIU_SRCR
LWI r9, SIU_SRCR_SSR
stw r9, 0(r8)
twiddle:
b twiddle

View File

@@ -0,0 +1,274 @@
/**
* @file
*
* @brief Source file for timer functions.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* The license and distribution terms for this file may be found in the file
* LICENSE in this distribution or at http://www.rtems.com/license/LICENSE.
*/
#include <rtems/bspIo.h>
#include <mpc83xx/mpc83xx.h>
#include <mpc83xx/gtm.h>
#define RTEMS_STATUS_CHECKS_USE_PRINTK
#include <rtems/status-checks.h>
#define MPC83XX_GTM_CHECK_INDEX( timer) \
if (( timer) < 0 || ( timer) >= MPC83XX_GTM_NUMBER) { \
return RTEMS_INVALID_NUMBER; \
}
#define MPC83XX_GTM_VARIABLES( timer) \
int module = (timer) / 4; \
int module_timer = (timer) % 4; \
int high = module_timer / 2; \
int low = module_timer % 2; \
rtems_interrupt_level level;
#define MPC83XX_GTM_CLOCK_MASK MPC83XX_GTM_CLOCK_EXTERN
static const uint8_t mpc83xx_gmt_interrupt_vector_table [MPC83XX_GTM_NUMBER] = { 90, 78, 84, 72, 91, 79, 85, 73 };
static const uint8_t mpc83xx_gmt_interrupt_priority_table [MPC83XX_GTM_NUMBER] = { 113, 77, 95, 59, 116, 80, 98, 62 };
rtems_status_code mpc83xx_gtm_initialize( int timer, int clock)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
MPC83XX_GTM_VARIABLES( timer);
uint8_t mask = 0xf << (low * 4);
uint8_t flags = 0x3 << (low * 4);
uint16_t reg = 0;
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
reg = mpc83xx.gtm [module].gtcfr [high].reg;
mpc83xx.gtm [module].gtcfr [high].reg = (reg & ~mask) | flags;
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = 0;
rtems_interrupt_enable( level);
sc = mpc83xx_gtm_set_clock( timer, clock);
CHECK_SC( sc, "Set clock");
sc = mpc83xx_gtm_set_value( timer, 0);
CHECK_SC( sc, "Set value");
sc = mpc83xx_gtm_set_reference( timer, 0);
CHECK_SC( sc, "Set reference");
sc = mpc83xx_gtm_set_prescale( timer, 0);
CHECK_SC( sc, "Set prescale");
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
if (enable) {
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0008;
} else {
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0008;
}
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock)
{
MPC83XX_GTM_VARIABLES( timer);
uint16_t reg = 0;
MPC83XX_GTM_CHECK_INDEX( timer);
if (clock & ~MPC83XX_GTM_CLOCK_MASK) {
return RTEMS_INVALID_CLOCK;
}
rtems_interrupt_disable( level);
reg = mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low];
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] = (reg & ~MPC83XX_GTM_CLOCK_MASK) | clock;
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_get_clock( int timer, int *clock)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
*clock = mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] & MPC83XX_GTM_CLOCK_MASK;
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_start( int timer)
{
MPC83XX_GTM_VARIABLES( timer);
uint8_t flags = 0x2 << (low * 4);
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
mpc83xx.gtm [module].gtcfr [high].reg &= ~flags;
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_stop( int timer)
{
MPC83XX_GTM_VARIABLES( timer);
uint8_t flags = 0x2 << (low * 4);
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
mpc83xx.gtm [module].gtcfr [high].reg |= flags;
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low] = value;
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
*value = mpc83xx.gtm [module].gt_tim_regs [high].gtcnr [low];
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low] = reference;
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
reference = mpc83xx.gtm [module].gt_tim_regs [high].gtrfr [low];
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
mpc83xx.gtm [module].gtpsr [module_timer] = prescale;
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
prescale = mpc83xx.gtm [module].gtpsr [module_timer];
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_interrupt_get_vector( int timer, rtems_vector_number *vector)
{
MPC83XX_GTM_CHECK_INDEX( timer);
*vector = mpc83xx_gmt_interrupt_vector_table [timer];
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_interrupt_enable( int timer)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] |= 0x0010;
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_interrupt_disable( int timer)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
rtems_interrupt_disable( level);
mpc83xx.gtm [module].gt_tim_regs [high].gtmdr [low] &= ~0x0010;
rtems_interrupt_enable( level);
return RTEMS_SUCCESSFUL;
}
rtems_status_code mpc83xx_gtm_interrupt_clear( int timer)
{
MPC83XX_GTM_VARIABLES( timer);
MPC83XX_GTM_CHECK_INDEX( timer);
mpc83xx.gtm [module].gtevr [module_timer] = 0x0002;
return RTEMS_SUCCESSFUL;
}

View File

@@ -619,11 +619,11 @@ static int mpc83xx_i2c_write_bytes
}
rtems_libi2c_bus_ops_t mpc83xx_i2c_ops = {
init: mpc83xx_i2c_init,
send_start: mpc83xx_i2c_send_start,
send_stop: mpc83xx_i2c_send_stop,
send_addr: mpc83xx_i2c_send_addr,
read_bytes: mpc83xx_i2c_read_bytes,
write_bytes: mpc83xx_i2c_write_bytes,
.init = mpc83xx_i2c_init,
.send_start = mpc83xx_i2c_send_start,
.send_stop = mpc83xx_i2c_send_stop,
.send_addr = mpc83xx_i2c_send_addr,
.read_bytes = mpc83xx_i2c_read_bytes,
.write_bytes = mpc83xx_i2c_write_bytes,
};

View File

@@ -0,0 +1,66 @@
/**
* @file
*
* @brief Header file for timer functions.
*/
/*
* Copyright (c) 2008
* Embedded Brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* rtems@embedded-brains.de
*
* 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_MPC83XX_TIMER_H
#define LIBBSP_POWERPC_MPC83XX_TIMER_H
#include <stdint.h>
#include <stdbool.h>
#include <rtems.h>
#define MPC83XX_GTM_NUMBER 8
#define MPC83XX_GTM_CLOCK_CASCADED 0x0000
#define MPC83XX_GTM_CLOCK_SYSTEM 0x0002
#define MPC83XX_GTM_CLOCK_SYSTEM_SLOW 0x0004
#define MPC83XX_GTM_CLOCK_EXTERN 0x0006
rtems_status_code mpc83xx_gtm_initialize( int timer, int clock);
rtems_status_code mpc83xx_gtm_enable_restart( int timer, bool enable);
rtems_status_code mpc83xx_gtm_set_clock( int timer, int clock);
rtems_status_code mpc83xx_gtm_get_clock( int timer, int *clock);
rtems_status_code mpc83xx_gtm_start( int timer);
rtems_status_code mpc83xx_gtm_stop( int timer);
rtems_status_code mpc83xx_gtm_set_value( int timer, uint16_t value);
rtems_status_code mpc83xx_gtm_get_value( int timer, uint16_t *value);
rtems_status_code mpc83xx_gtm_set_reference( int timer, uint16_t reference);
rtems_status_code mpc83xx_gtm_get_reference( int timer, uint16_t *reference);
rtems_status_code mpc83xx_gtm_set_prescale( int timer, uint8_t prescale);
rtems_status_code mpc83xx_gtm_get_prescale( int timer, uint8_t *prescale);
rtems_status_code mpc83xx_gtm_interrupt_get_vector( int timer, rtems_vector_number *vector);
rtems_status_code mpc83xx_gtm_interrupt_enable( int timer);
rtems_status_code mpc83xx_gtm_interrupt_disable( int timer);
rtems_status_code mpc83xx_gtm_interrupt_clear( int timer);
#endif /* LIBBSP_POWERPC_MPC83XX_TIMER_H */

View File

@@ -27,6 +27,7 @@
#include <bsp/irq.h>
#include <mpc83xx/mpc83xx.h>
#include <mpc83xx/tsec.h>
#include <libcpu/spr.h>
#include <rtems/error.h>
#include <rtems/bspIo.h>
#include <rtems/rtems_bsdnet.h>
@@ -43,6 +44,13 @@
#include <netinet/if_ether.h>
#include <stdio.h>
/* System Version Register */
#define SVR 286
SPR_RO( SVR)
/* Processor Version Register */
SPR_RO( PVR)
#define CLREVENT_IN_IRQ
#define TSEC_WATCHDOG_TIMEOUT 5 /* check media every 5 seconds */
@@ -57,7 +65,8 @@ struct mpc83xx_tsec_struct {
/*
* HW links: (filled from rtems_bsdnet_ifconfig
*/
m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC register block */
m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC register block */
m83xxTSEC_Registers_t *mdio_ptr; /* pointer to TSEC register block which is responsible for MDIO communication */
int irq_num_tx; /* tx irq number */
int irq_num_rx; /* rx irq number */
int irq_num_err; /* error irq number */
@@ -192,7 +201,7 @@ static void mpc83xx_tsec_hwinit
{
m83xxTSEC_Registers_t *reg_ptr = sc->reg_ptr; /* pointer to TSEC registers*/
uint8_t *mac_addr;
int i;
size_t i;
/*
* init ECNTL register
@@ -272,9 +281,9 @@ static void mpc83xx_tsec_hwinit
/*
* init MACCFG2 register
*/
reg_ptr->maccfg2 = ((reg_ptr->maccfg2 & M83xx_TSEC_MACCFG2_IFMODE_MSK)
| M83xx_TSEC_MACCFG2_PRELEN(7)
| M83xx_TSEC_MACCFG2_FULLDUPLEX);
reg_ptr->maccfg2 = (reg_ptr->maccfg2 & M83xx_TSEC_MACCFG2_IFMODE_MSK)
| M83xx_TSEC_MACCFG2_PRELEN( 7)
| M83xx_TSEC_MACCFG2_FULLDUPLEX;
/*
* init station address register
@@ -324,10 +333,19 @@ static void mpc83xx_tsec_mdio_init
| <none> |
\*=========================================================================*/
{
/* Set TSEC registers for MDIO communication */
/*
* FIXME: Not clear if this works for all boards.
* Tested only on MPC8313ERDB.
*/
sc->mdio_ptr = &mpc83xx.tsec [0];
/*
* set clock divider
*/
sc->reg_ptr->miimcfg = 3;
sc->mdio_ptr->miimcfg = 3;
}
/*=========================================================================*\
@@ -351,10 +369,10 @@ int mpc83xx_tsec_mdio_read
| 0, if ok, else error |
\*=========================================================================*/
{
struct mpc83xx_tsec_struct *sc = uarg;/* control structure */
m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC registers */
struct mpc83xx_tsec_struct *sc = uarg;/* control structure */
reg_ptr = sc->reg_ptr;
/* pointer to TSEC registers */
m83xxTSEC_Registers_t *reg_ptr = sc->mdio_ptr;
/*
* make sure we work with a valid phy
@@ -419,10 +437,10 @@ int mpc83xx_tsec_mdio_write
| 0, if ok, else error |
\*=========================================================================*/
{
struct mpc83xx_tsec_struct *sc = uarg;/* control structure */
m83xxTSEC_Registers_t *reg_ptr; /* pointer to TSEC registers */
struct mpc83xx_tsec_struct *sc = uarg;/* control structure */
reg_ptr = sc->reg_ptr;
/* pointer to TSEC registers */
m83xxTSEC_Registers_t *reg_ptr = sc->mdio_ptr;
/*
* make sure we work with a valid phy
@@ -1685,9 +1703,9 @@ int rtems_mpc83xx_tsec_mode_adapt
| 0, if success |
\*=========================================================================*/
{
int result;
int media;
int result = 0;
struct mpc83xx_tsec_struct *sc = ifp->if_softc;
int media = IFM_MAKEWORD( 0, 0, 0, sc->phy_default);
#ifdef DEBUG
printf("c");
@@ -1819,6 +1837,8 @@ static int mpc83xx_tsec_driver_attach
struct ifnet *ifp;
int unitNumber;
char *unitName;
uint32_t svr = _read_SVR();
uint32_t pvr = _read_PVR();
/*
* Parse driver name
@@ -1865,10 +1885,30 @@ static int mpc83xx_tsec_driver_attach
/* get pointer to TSEC register block */
sc->reg_ptr = &mpc83xx.tsec[unitNumber-1];
/* get base interrupt number (for Tx irq, Rx=base+1,Err=base+2) */
sc->irq_num_tx = config->irno + 0; /* tx irq number from BSP */
sc->irq_num_rx = config->irno + 1; /* rx irq number from BSP */
sc->irq_num_err = config->irno + 2; /* err irq number from BSP */
if (svr == 0x80b00010 && pvr == 0x80850010) {
/*
* This is a special case for MPC8313ERDB with silicon revision 1. Look in
* "MPC8313ECE Rev. 3, 3/2008" errata for "IPIC 1".
*/
if (unitNumber == 1) {
sc->irq_num_tx = 37;
sc->irq_num_rx = 36;
sc->irq_num_err = 35;
} else if (unitNumber == 2) {
sc->irq_num_tx = 34;
sc->irq_num_rx = 33;
sc->irq_num_err = 32;
} else {
return 0;
}
} else {
/* get base interrupt number (for Tx irq, Rx=base+1,Err=base+2) */
sc->irq_num_tx = config->irno + 0; /* tx irq number from BSP */
sc->irq_num_rx = config->irno + 1; /* rx irq number from BSP */
sc->irq_num_err = config->irno + 2; /* err irq number from BSP */
}
if (config->irno == 0) {
rtems_panic("TSEC: interupt base number irno not defined");
}
@@ -1878,11 +1918,22 @@ static int mpc83xx_tsec_driver_attach
sc->mdio_info.mdio_r = mpc83xx_tsec_mdio_read;
sc->mdio_info.mdio_w = mpc83xx_tsec_mdio_write;
sc->mdio_info.has_gmii = 1; /* we support gigabit IF */
/*
* XXX: Although most hardware builders will assign the PHY addresses
* like this, this should be more configurable
*/
#ifdef MPC8313ERDB
if (unitNumber == 2) {
sc->phy_default = 4;
} else {
/* TODO */
return 0;
}
#else /* MPC8313ERDB */
sc->phy_default = unitNumber-1;
#endif /* MPC8313ERDB */
/*
* Set up network interface values
*/

View File

@@ -434,9 +434,9 @@ int mpc83xx_spi_read_write_bytes
#endif
if (tbuf == NULL) {
/*
* perform dummy write to read byte
* perform idle char write to read byte
*/
softc_ptr->reg_ptr->spitd = 0;
softc_ptr->reg_ptr->spitd = softc_ptr->idle_char << bit_shift;
}
else {
switch(bytes_per_char) {
@@ -583,6 +583,10 @@ rtems_status_code mpc83xx_spi_set_tfr_mode
mpc83xx_spi_softc_t *softc_ptr = &(((mpc83xx_spi_desc_t *)(bh))->softc);
uint32_t spimode_baud,spimode;
rtems_status_code rc = RTEMS_SUCCESSFUL;
/* Set idle character */
softc_ptr->idle_char = tfr_mode->idle_char;
/*
* FIXME: set proper mode
*/

View File

@@ -35,6 +35,7 @@ typedef struct mpc83xx_spi_softc {
uint32_t base_frq; /* input frq for baud rate divider */
rtems_id irq_sema_id;
uint32_t curr_addr; /* current spi address */
uint32_t idle_char;
uint8_t bytes_per_char;
uint8_t bit_shift;
} mpc83xx_spi_softc_t ;

View File

@@ -210,6 +210,19 @@ $(PROJECT_INCLUDE)/mpc8260/mmu.h: mpc8260/include/mmu.h $(PROJECT_INCLUDE)/mpc82
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc8260/mmu.h
endif
if mpc83xx
$(PROJECT_INCLUDE)/bsp/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(PROJECT_INCLUDE)/bsp/vectors.h: new-exceptions/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
$(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h: new-exceptions/bspsupport/ppc_exc_bspsupp.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
$(PROJECT_INCLUDE)/mpc83xx/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/mpc83xx
@: > $(PROJECT_INCLUDE)/mpc83xx/$(dirstamp)
@@ -230,4 +243,55 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_i2cdrv.h
$(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h: mpc83xx/spi/mpc83xx_spidrv.h $(PROJECT_INCLUDE)/mpc83xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/mpc83xx_spidrv.h
$(PROJECT_INCLUDE)/mpc83xx/gtm.h: mpc83xx/include/gtm.h $(PROJECT_INCLUDE)/mpc83xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc83xx/gtm.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc83xx/gtm.h
endif
if mpc55xx
$(PROJECT_INCLUDE)/bsp/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
@: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(PROJECT_INCLUDE)/bsp/vectors.h: new-exceptions/bspsupport/vectors.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vectors.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/vectors.h
$(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h: new-exceptions/bspsupport/ppc_exc_bspsupp.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/ppc_exc_bspsupp.h
$(PROJECT_INCLUDE)/bsp/irq.h: mpc55xx/include/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
$(PROJECT_INCLUDE)/mpc55xx/$(dirstamp):
@$(MKDIR_P) $(PROJECT_INCLUDE)/mpc55xx
@: > $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
PREINSTALL_DIRS += $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(PROJECT_INCLUDE)/mpc55xx/regs.h: mpc55xx/include/regs.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/regs.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/regs.h
$(PROJECT_INCLUDE)/mpc55xx/reg-defs.h: mpc55xx/include/reg-defs.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/reg-defs.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/reg-defs.h
$(PROJECT_INCLUDE)/mpc55xx/dspi.h: mpc55xx/include/dspi.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/dspi.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/dspi.h
$(PROJECT_INCLUDE)/mpc55xx/edma.h: mpc55xx/include/edma.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/edma.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/edma.h
$(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h: mpc55xx/include/mpc55xx.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/mpc55xx.h
$(PROJECT_INCLUDE)/mpc55xx/esci.h: mpc55xx/include/esci.h $(PROJECT_INCLUDE)/mpc55xx/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/mpc55xx/esci.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/mpc55xx/esci.h
endif

View File

@@ -91,6 +91,17 @@ extern "C" {
#define PPC_LOW_POWER_MODE_NONE 0
#define PPC_LOW_POWER_MODE_STANDARD 1
/**
* @brief For boards with no cache set PPC_CACHE_ALIGNMENT to this value.
*/
#define PPC_NO_CACHE_ALIGNMENT 4
/**
* @brief Used to define PPC_CACHE_ALIGN_POWER for boards with no cache (and
* PPC_NO_CACHE_ALIGNMENT defined).
*/
#define PPC_NO_CACHE_ALIGNMENT_POWER 2
/*
* Figure out all CPU Model Feature Flags based upon compiler
* predefines.
@@ -129,7 +140,7 @@ extern "C" {
#elif defined(mpc555)
/* Copied from mpc505 */
#define PPC_CACHE_ALIGNMENT 16
#define PPC_CACHE_ALIGNMENT PPC_NO_CACHE_ALIGNMENT
/* Added by querbach@realtime.bc.ca */
#define PPC_LOW_POWER_MODE PPC_LOW_POWER_MODE_STANDARD
@@ -145,7 +156,9 @@ extern "C" {
* to get the setting correct.
*/
#define PPC_CACHE_ALIGNMENT 16
#define CPU_MODEL_NAME "PowerPC 505/509"
#define PPC_CACHE_ALIGNMENT PPC_NO_CACHE_ALIGNMENT
#define PPC_I_CACHE 4096
#define PPC_D_CACHE 0
@@ -280,6 +293,8 @@ extern "C" {
#define PPC_CACHE_ALIGN_POWER 4
#elif (PPC_CACHE_ALIGNMENT == 32)
#define PPC_CACHE_ALIGN_POWER 5
#elif (PPC_CACHE_ALIGNMENT == PPC_NO_CACHE_ALIGNMENT)
#define PPC_CACHE_ALIGN_POWER PPC_NO_CACHE_ALIGNMENT_POWER
#else
#error "Undefined power of 2 for PPC_CACHE_ALIGNMENT"
#endif

View File

@@ -31,73 +31,7 @@
#include <rtems/powerpc/registers.h>
#ifdef ASM
#include <rtems/asm.h>
.macro LA reg, addr
lis \reg, (\addr)@h
ori \reg, \reg, (\addr)@l
.endm
.macro LWI reg, value
lis \reg, (\value)@h
ori \reg, \reg, (\value)@l
.endm
.macro LW reg, addr
lis \reg, \addr@ha
lwz \reg, \addr@l(\reg)
.endm
/*
* Tests the bits in reg1 against the bits set in mask. A match is indicated
* by EQ = 0 in CR0. A mismatch is indicated by EQ = 1 in CR0. The register
* reg2 is used to load the mask.
*/
.macro TSTBITS reg1, reg2, mask
LWI \reg2, \mask
and \reg1, \reg1, \reg2
cmplw \reg1, \reg2
.endm
.macro SETBITS reg1, reg2, mask
LWI \reg2, \mask
or \reg1, \reg1, \reg2
.endm
.macro CLRBITS reg1, reg2, mask
LWI \reg2, \mask
andc \reg1, \reg1, \reg2
.endm
.macro GLOBAL_FUNCTION name
.global \name
.type \name, @function
\name:
.endm
/*
* Disables all asynchronous exeptions (interrupts) which may cause a context
* switch.
*/
.macro INTERRUPT_DISABLE level, mask
mfmsr \level
mfspr \mask, sprg0
andc \mask, \level, \mask
mtmsr \mask
.endm
/*
* Restore previous machine state.
*/
.macro INTERRUPT_ENABLE level
mtmsr \level
.endm
#define LINKER_SYMBOL( sym) .extern sym
#else /* ASM */
#ifndef ASM
#include <stdint.h>
@@ -518,6 +452,72 @@ static inline void ppc_set_time_base_64( uint64_t val)
PPC_Set_timebase_register( val);
}
#else /* ASM */
#include <rtems/asm.h>
.macro LA reg, addr
lis \reg, (\addr)@h
ori \reg, \reg, (\addr)@l
.endm
.macro LWI reg, value
lis \reg, (\value)@h
ori \reg, \reg, (\value)@l
.endm
.macro LW reg, addr
lis \reg, \addr@ha
lwz \reg, \addr@l(\reg)
.endm
/*
* Tests the bits in reg1 against the bits set in mask. A match is indicated
* by EQ = 0 in CR0. A mismatch is indicated by EQ = 1 in CR0. The register
* reg2 is used to load the mask.
*/
.macro TSTBITS reg1, reg2, mask
LWI \reg2, \mask
and \reg1, \reg1, \reg2
cmplw \reg1, \reg2
.endm
.macro SETBITS reg1, reg2, mask
LWI \reg2, \mask
or \reg1, \reg1, \reg2
.endm
.macro CLRBITS reg1, reg2, mask
LWI \reg2, \mask
andc \reg1, \reg1, \reg2
.endm
.macro GLOBAL_FUNCTION name
.global \name
.type \name, @function
\name:
.endm
/*
* Disables all asynchronous exeptions (interrupts) which may cause a context
* switch.
*/
.macro INTERRUPT_DISABLE level, mask
mfmsr \level
mfspr \mask, sprg0
andc \mask, \level, \mask
mtmsr \mask
.endm
/*
* Restore previous machine state.
*/
.macro INTERRUPT_ENABLE level
mtmsr \level
.endm
#define LINKER_SYMBOL( sym) .extern sym
#endif /* ASM */
#endif /* LIBCPU_POWERPC_UTILITY_H */

View File

@@ -1,3 +1,11 @@
/**
* @file
*
* #ingroup powerpc_shared
*
* @brief Source file for the Cache Manager PowerPC support.
*/
/*
* Cache Management Support Routines for the MC68040
* Modified for MPC8260 Andy Dachs <a.dachs@sstl.co.uk>
@@ -194,6 +202,67 @@ void _CPU_cache_disable_instruction ( void )
mtspr( 560, r1 );
isync;
}
#else
#warning Most cache functions are not implemented
void _CPU_cache_flush_entire_data()
{
/* Void */
}
void _CPU_cache_invalidate_entire_data()
{
/* Void */
}
void _CPU_cache_freeze_data()
{
/* Void */
}
void _CPU_cache_unfreeze_data()
{
/* Void */
}
void _CPU_cache_enable_data()
{
/* Void */
}
void _CPU_cache_disable_data()
{
/* Void */
}
void _CPU_cache_invalidate_entire_instruction()
{
/* Void */
}
void _CPU_cache_freeze_instruction()
{
/* Void */
}
void _CPU_cache_unfreeze_instruction()
{
/* Void */
}
void _CPU_cache_enable_instruction()
{
/* Void */
}
void _CPU_cache_disable_instruction()
{
/* Void */
}
#endif
void _CPU_cache_invalidate_1_data_line(

View File

@@ -1,38 +1,25 @@
/*
* PowerPC Cache Manager Support
/**
* @file
*
* #ingroup powerpc_shared
*
* @brief Header file for the Cache Manager PowerPC support.
*/
#ifndef __POWERPC_CACHE_h
#define __POWERPC_CACHE_h
/*
* get definitions from the score/powerpc header
* about individual cache alignments
*/
#ifndef LIBCPU_POWERPC_CACHE_H
#define LIBCPU_POWERPC_CACHE_H
#include <rtems/score/powerpc.h>
/*
* CACHE MANAGER: The following functions are CPU-specific.
* They provide the basic implementation for the rtems_* cache
* management routines. If a given function has no meaning for the CPU,
* it does nothing by default.
*
* FIXME: Some functions simply have not been implemented.
*/
#if defined(ppc603) || defined(ppc603e) || defined(mpc8260)
/* And possibly others */
#if defined(PPC_CACHE_ALIGNMENT)
#define CPU_DATA_CACHE_ALIGNMENT PPC_CACHE_ALIGNMENT
#define CPU_INSTRUCTION_CACHE_ALIGNMENT PPC_CACHE_ALIGNMENT
#endif
/* Provide the CPU defines only if we have a cache */
#if PPC_CACHE_ALIGNMENT != PPC_NO_CACHE_ALIGNMENT
#define CPU_DATA_CACHE_ALIGNMENT PPC_CACHE_ALIGNMENT
#define CPU_INSTRUCTION_CACHE_ALIGNMENT PPC_CACHE_ALIGNMENT
#endif
#ifdef _OLD_EXCEPTIONS
#include <libcpu/cache.h>
# warning OLD EXCEPTIONS
# include <libcpu/cache.h>
#endif
#endif
/* end of include file */
#endif /* LIBCPU_POWERPC_CACHE_H */