summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-11-09 00:04:57 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-11-09 00:04:57 +0000
commite9ae97fbc6221ffb11b1ce14f6fc320dc602b686 (patch)
treed3143d5a2ee19ac375731e462a59cca3339182fc
parentde202e7204715267e2439f0e87c4b83c143ecddf (diff)
downloadrtems-e9ae97fbc6221ffb11b1ce14f6fc320dc602b686.tar.bz2
2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@ecs.ericsson.se>
This modification is part of the submitted modifications necessary to support the IBM PPC405 family. This submission was reviewed by Thomas Doerfler <Thomas.Doerfler@imd-systems.de> who ensured it did not negatively impact the ppc403 BSPs. The submission and tracking process was captured as PR50. * ppc403/console/console405.c ppc403/tty_drv/.cvsignore, ppc403/tty_drv/Makefile.am, ppc403/tty_drv/tty_drv.c, ppc403/tty_drv/tty_drv.h: New files. * Makefile.am, README, configure.ac, old_exception_processing/cpu.c, old_exception_processing/cpu.h, ppc403/Makefile.am, ppc403/clock/clock.c, ppc403/console/Makefile.am, ppc403/console/console.c, ppc403/ictrl/ictrl.c, ppc403/ictrl/ictrl.h, ppc403/timer/timer.c: Modified.
-rw-r--r--c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.c4
-rw-r--r--c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.h4
-rw-r--r--c/src/lib/libcpu/powerpc/ChangeLog16
-rw-r--r--c/src/lib/libcpu/powerpc/Makefile.am4
-rw-r--r--c/src/lib/libcpu/powerpc/README16
-rw-r--r--c/src/lib/libcpu/powerpc/configure.ac3
-rw-r--r--c/src/lib/libcpu/powerpc/old-exceptions/cpu.c4
-rw-r--r--c/src/lib/libcpu/powerpc/old_exception_processing/cpu.c4
-rw-r--r--c/src/lib/libcpu/powerpc/old_exception_processing/cpu.h4
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/Makefile.am5
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/clock/clock.c57
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/Makefile.am7
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/console.c2
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/console/console405.c554
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c46
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h11
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/timer/timer.c20
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/tty_drv/.cvsignore2
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/tty_drv/Makefile.am32
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.c557
-rw-r--r--c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.h63
21 files changed, 1382 insertions, 33 deletions
diff --git a/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.c b/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.c
index 5771b5f7cd..1d6845cb69 100644
--- a/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.c
+++ b/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.c
@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc);
#endif
-#ifdef ppc403
+#if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL)
{
register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00;
break;
-#if defined(ppc403)
+#if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT:
diff --git a/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.h b/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.h
index 803377b99f..935f4ca0d3 100644
--- a/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.h
+++ b/c/src/lib/libbsp/powerpc/support/old_exception_processing/cpu.h
@@ -474,7 +474,7 @@ typedef struct {
void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
boolean exceptions_in_RAM; /* TRUE if in RAM */
-#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock;
boolean serial_xon_xoff;
@@ -508,7 +508,7 @@ typedef struct {
#define rtems_cpu_configuration_get_exceptions_in_ram() \
(_CPU_Table.exceptions_in_RAM)
-#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
#define rtems_cpu_configuration_get_serial_per_sec() \
(_CPU_Table.serial_per_sec)
diff --git a/c/src/lib/libcpu/powerpc/ChangeLog b/c/src/lib/libcpu/powerpc/ChangeLog
index 2c71a462c1..822d7fef3b 100644
--- a/c/src/lib/libcpu/powerpc/ChangeLog
+++ b/c/src/lib/libcpu/powerpc/ChangeLog
@@ -1,3 +1,19 @@
+2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@ecs.ericsson.se>
+
+ This modification is part of the submitted modifications necessary to
+ support the IBM PPC405 family. This submission was reviewed by
+ Thomas Doerfler <Thomas.Doerfler@imd-systems.de> who ensured it did
+ not negatively impact the ppc403 BSPs. The submission and tracking
+ process was captured as PR50.
+ * ppc403/console/console405.c ppc403/tty_drv/.cvsignore,
+ ppc403/tty_drv/Makefile.am, ppc403/tty_drv/tty_drv.c,
+ ppc403/tty_drv/tty_drv.h: New files.
+ * Makefile.am, README, configure.ac, old_exception_processing/cpu.c,
+ old_exception_processing/cpu.h, ppc403/Makefile.am,
+ ppc403/clock/clock.c, ppc403/console/Makefile.am,
+ ppc403/console/console.c, ppc403/ictrl/ictrl.c, ppc403/ictrl/ictrl.h,
+ ppc403/timer/timer.c: Modified.
+
2001-11-07 Joel Sherrill <joel@OARcorp.com>
* configure.ac: Delete the commented out line that said that
diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am
index 0f12c3ba67..02dac61d17 100644
--- a/c/src/lib/libcpu/powerpc/Makefile.am
+++ b/c/src/lib/libcpu/powerpc/Makefile.am
@@ -34,6 +34,10 @@ endif
if ppc403
CPU_SUBDIR = ppc403
endif
+if ppc405
+## 403 and 405 chips use the same CPU sources...
+CPU_SUBDIR = ppc403
+endif
SUBDIRS = $(SHARED_LIB) $(EXCEPTION_SUBDIR) $(CPU_SUBDIR) wrapup
diff --git a/c/src/lib/libcpu/powerpc/README b/c/src/lib/libcpu/powerpc/README
index bd1d41e66a..c17cfecee0 100644
--- a/c/src/lib/libcpu/powerpc/README
+++ b/c/src/lib/libcpu/powerpc/README
@@ -9,17 +9,25 @@ available from IBM and Motorola.
Since these routines can differ amongst different members
of the PowerPC family, an entry per CPU type is provided.
-Initially, (4/December/1995), only the PPC403 was supported.
At this time, support is included for the following PowerPC
-family members:
+family members using the new exception processing model:
+ mpc505
+ + mpc6xx
+ mpc750
- + mpc821
+ + mpc821
+ + mpc823 (uses mpc821 directory)
+ + mpc850 (uses mpc860 directory)
+ mpc860
- + ppc403
+ mpc8260
+The following PowerPC family members are supported but
+still use the old exception processing model:
+
+ + ppc403
+ + ppc405 (uses ppc403 directory)
+ + ppc6xx (no libcpu support)
+
Note that because of similarities in various family members,
the mpc823 should be able to use the mpc821 code and the
mpc850 should be able to use the mpc850 code.
diff --git a/c/src/lib/libcpu/powerpc/configure.ac b/c/src/lib/libcpu/powerpc/configure.ac
index 06a38d4bae..8a91c2c611 100644
--- a/c/src/lib/libcpu/powerpc/configure.ac
+++ b/c/src/lib/libcpu/powerpc/configure.ac
@@ -50,6 +50,7 @@ test "$RTEMS_CPU_MODEL" = "mpc860" \
## first.
AM_CONDITIONAL(old_exception_processing, \
test "$RTEMS_CPU_MODEL" = "ppc403" || \
+test "$RTEMS_CPU_MODEL" = "ppc405" || \
test "$RTEMS_CPU_MODEL" = "mpc505" || \
test "$RTEMS_CPU_MODEL" = "ppc603e" \
)
@@ -64,6 +65,7 @@ AM_CONDITIONAL(mpc8xx, test "$RTEMS_CPU_MODEL" = "mpc8xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc860" )
AM_CONDITIONAL(mpc8260, test "$RTEMS_CPU_MODEL" = "mpc8260")
AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403")
+AM_CONDITIONAL(ppc405, test "$RTEMS_CPU_MODEL" = "ppc405")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
@@ -82,6 +84,7 @@ mpc8xx/timer/Makefile
ppc403/Makefile
ppc403/clock/Makefile
ppc403/console/Makefile
+ppc403/tty_drv/Makefile
ppc403/ictrl/Makefile
ppc403/timer/Makefile
ppc403/vectors/Makefile
diff --git a/c/src/lib/libcpu/powerpc/old-exceptions/cpu.c b/c/src/lib/libcpu/powerpc/old-exceptions/cpu.c
index 5771b5f7cd..1d6845cb69 100644
--- a/c/src/lib/libcpu/powerpc/old-exceptions/cpu.c
+++ b/c/src/lib/libcpu/powerpc/old-exceptions/cpu.c
@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc);
#endif
-#ifdef ppc403
+#if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL)
{
register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00;
break;
-#if defined(ppc403)
+#if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT:
diff --git a/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.c b/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.c
index 5771b5f7cd..1d6845cb69 100644
--- a/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.c
+++ b/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.c
@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc);
#endif
-#ifdef ppc403
+#if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL)
{
register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00;
break;
-#if defined(ppc403)
+#if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT:
diff --git a/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.h b/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.h
index 803377b99f..935f4ca0d3 100644
--- a/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.h
+++ b/c/src/lib/libcpu/powerpc/old_exception_processing/cpu.h
@@ -474,7 +474,7 @@ typedef struct {
void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
boolean exceptions_in_RAM; /* TRUE if in RAM */
-#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock;
boolean serial_xon_xoff;
@@ -508,7 +508,7 @@ typedef struct {
#define rtems_cpu_configuration_get_exceptions_in_ram() \
(_CPU_Table.exceptions_in_RAM)
-#if (defined(ppc403) || defined(mpc860) || defined(mpc821))
+#if (defined(ppc403) || defined(ppc405) || defined(mpc860) || defined(mpc821))
#define rtems_cpu_configuration_get_serial_per_sec() \
(_CPU_Table.serial_per_sec)
diff --git a/c/src/lib/libcpu/powerpc/ppc403/Makefile.am b/c/src/lib/libcpu/powerpc/ppc403/Makefile.am
index bd55ab2ed0..4354510022 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/Makefile.am
+++ b/c/src/lib/libcpu/powerpc/ppc403/Makefile.am
@@ -4,7 +4,12 @@
AUTOMAKE_OPTIONS = foreign 1.4
+if ppc403
SUBDIRS = console clock timer vectors ictrl
+endif
+if ppc405
+SUBDIRS = console tty_drv clock timer vectors ictrl
+endif
include $(top_srcdir)/../../../../../automake/subdirs.am
include $(top_srcdir)/../../../../../automake/local.am
diff --git a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
index d7e9514b5f..5ba10ace42 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/clock/clock.c
@@ -25,7 +25,6 @@
* for these modifications:
* COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
*
- *
* COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR).
*
@@ -33,6 +32,8 @@
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
* $Id$
*/
@@ -59,7 +60,11 @@ static inline rtems_unsigned32 get_itimer(void)
{
register rtems_unsigned32 rc;
+#ifndef ppc405 /* this is a ppc403 */
asm volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */
+#else /* ppc405 */
+ asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */
+#endif /* ppc405 */
return rc;
}
@@ -71,11 +76,10 @@ static inline rtems_unsigned32 get_itimer(void)
rtems_isr
Clock_isr(rtems_vector_number vector)
{
+ rtems_unsigned32 clicks_til_next_interrupt;
if (!auto_restart)
{
- rtems_unsigned32 clicks_til_next_interrupt;
rtems_unsigned32 itimer_value;
-
/*
* setup for next interrupt; making sure the new value is reasonably
* in the future.... in case we lost out on an interrupt somehow
@@ -131,24 +135,25 @@ Clock_isr(rtems_vector_number vector)
void Install_clock(rtems_isr_entry clock_isr)
{
rtems_isr_entry previous_isr;
- rtems_unsigned32 pvr, iocr;
+ rtems_unsigned32 iocr;
register rtems_unsigned32 tcr;
+#ifdef ppc403
+ rtems_unsigned32 pvr;
+#endif /* ppc403 */
Clock_driver_ticks = 0;
+#ifndef ppc405 /* this is a ppc403 */
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
-
if (rtems_cpu_configuration_get_timer_internal_clock()) {
iocr &= ~4; /* timer clocked from system clock */
}
else {
iocr |= 4; /* select external timer clock */
}
-
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */
asm volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */
-
if (((pvr & 0xffff0000) >> 16) != 0x0020)
return; /* Not a ppc403 */
@@ -162,10 +167,26 @@ void Install_clock(rtems_isr_entry clock_isr)
else if ((pvr & 0xff00) == 0x0100) /* 403GB */
auto_restart = 1;
+#else /* ppc405 */
+ asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */
+ if (rtems_cpu_configuration_get_timer_internal_clock()) {
+ iocr &=~0x800000 ;/* timer clocked from system clock CETE*/
+ }
+ else {
+ iocr |= 0x800000; /* select external timer clock CETE*/
+ }
+ asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */
+
+ /*
+ * Enable auto restart
+ */
+
+ auto_restart=1;
+
+#endif /* ppc405 */
pit_value = rtems_configuration_get_microseconds_per_tick() *
rtems_cpu_configuration_get_clicks_per_usec();
-
/*
* initialize the interval here
* First tick is set to right amount of time in the future
@@ -176,16 +197,19 @@ void Install_clock(rtems_isr_entry clock_isr)
rtems_interrupt_catch(clock_isr, PPC_IRQ_PIT, &previous_isr);
+ /*
+ * Set PIT value
+ */
+
asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */
- asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */
-
- tcr &= ~ 0x04400000;
-
- tcr |= (auto_restart ? 0x04400000 : 0x04000000);
-
+ /*
+ * Set timer to autoreload, bit TCR->ARE = 1 0x0400000
+ * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000
+ */
tick_time = get_itimer() + pit_value;
-
+ asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */
+ tcr = (tcr & ~0x04400000) | (auto_restart ? 0x04400000 : 0x04000000);
asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
atexit(Clock_exit);
@@ -208,6 +232,9 @@ ReInstall_clock(rtems_isr_entry new_clock_isr)
/*
* Called via atexit()
* Remove the clock interrupt handler by setting handler to NULL
+ *
+ * This will not work on the 405GP because
+ * when bit's are set in TCR they can only be unset by a reset
*/
void
diff --git a/c/src/lib/libcpu/powerpc/ppc403/console/Makefile.am b/c/src/lib/libcpu/powerpc/ppc403/console/Makefile.am
index 923bbe4886..bda2b1c06f 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/console/Makefile.am
+++ b/c/src/lib/libcpu/powerpc/ppc403/console/Makefile.am
@@ -6,7 +6,12 @@ AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/console.rel
+if ppc403
C_FILES = console.c
+endif
+if ppc405
+C_FILES = console405.c
+endif
console_rel_OBJECTS = $(C_FILES:%.c=$(ARCH)/%.o)
@@ -25,6 +30,6 @@ all-local: $(ARCH) $(console_rel_OBJECTS) $(PGM)
.PRECIOUS: $(PGM)
-EXTRA_DIST = console.c console.c.polled
+EXTRA_DIST = console.c console.c.polled console405.c
include $(top_srcdir)/../../../../../automake/local.am
diff --git a/c/src/lib/libcpu/powerpc/ppc403/console/console.c b/c/src/lib/libcpu/powerpc/ppc403/console/console.c
index 9313a9bc90..c92ea2129d 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/console/console.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/console/console.c
@@ -147,7 +147,7 @@ typedef volatile struct async *pasync;
static const pasync port = (pasync)0x40000000;
static void *spittyp; /* handle for termios */
-int ppc403_spi_interrupt = 1; /* do not use interrupts... */
+int ppc403_spi_interrupt = 1; /* use interrupts... */
/*
* Rx Interrupt handler
diff --git a/c/src/lib/libcpu/powerpc/ppc403/console/console405.c b/c/src/lib/libcpu/powerpc/ppc403/console/console405.c
new file mode 100644
index 0000000000..3be6423fa3
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/console/console405.c
@@ -0,0 +1,554 @@
+/*
+ * This file contains the PowerPC 405GP console IO package.
+ *
+ * Author: Thomas Doerfler <td@imd.m.isar.de>
+ * IMD Ingenieurbuero fuer Microcomputertechnik
+ *
+ * COPYRIGHT (c) 1998 by IMD
+ *
+ * Changes from IMD are covered by the original distributions terms.
+ * changes include interrupt support and termios support
+ * for backward compatibility, the original polled driver has been
+ * renamed to console.c.polled
+ *
+ * This file has been initially created (polled version) by
+ *
+ * Author: Andrew Bray <andy@i-cubed.co.uk>
+ *
+ * COPYRIGHT (c) 1995 by i-cubed ltd.
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies, and that the name of i-cubed limited not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * i-cubed limited makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Modifications for spooling (interrupt driven) console driver
+ * by Thomas Doerfler <td@imd.m.isar.de>
+ * for these modifications:
+ * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
+ *
+ *
+ * To anyone who acknowledges that this file is provided "AS IS"
+ * without any express or implied warranty:
+ * permission to use, copy, modify, and distribute this file
+ * for any purpose is hereby granted without fee, provided that
+ * the above copyright notice and this notice appears in all
+ * copies. IMD makes no representations about the suitability
+ * of this software for any purpose.
+ *
+ * Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
+ *
+ * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
+ * On-Line Applications Research Corporation (OAR).
+ * All rights assigned to U.S. Government, 1994.
+ *
+ * This material may be reproduced by or for the U.S. Government pursuant
+ * to the copyright license under the clause at DFARS 252.227-7013. This
+ * notice must appear in all copies of this file and its derivatives.
+ *
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
+ * console405.c,v 1.4 1995/12/05 19:23:02 joel Exp
+ */
+
+#define NO_BSP_INIT
+
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "../ictrl/ictrl.h"
+#include <stdlib.h> /* for atexit() */
+
+
+
+struct async {
+/*---------------------------------------------------------------------------+
+| Data Register.
++---------------------------------------------------------------------------*/
+ unsigned char RBR; /* 0x00 */
+ #define THR RBR
+/*---------------------------------------------------------------------------+
+| Interrupt registers
++---------------------------------------------------------------------------*/
+ unsigned char IER; /* 0x01 */
+ #define IER_RCV 0x01
+ #define IER_XMT 0x02
+ #define IER_LS 0x04
+ #define IER_MS 0x08
+
+ unsigned char ISR; /* 0x02 */
+ #define ISR_MS 0x00
+ #define ISR_nIP 0x01
+ #define ISR_Tx 0x02
+ #define ISR_Rx 0x04
+ #define ISR_LS 0x06
+ #define ISR_RxTO 0x0C
+ #define ISR_64BFIFO 0x20
+ #define ISR_FIFOworks 0x40
+ #define ISR_FIFOen 0x80
+
+/*---------------------------------------------------------------------------+
+| FIFO Control registers
++---------------------------------------------------------------------------*/
+ #define FCR ISR
+ #define FCR_FE 0x01 /* FIFO enable */
+ #define FCR_CRF 0x02 /* Clear receive FIFO */
+ #define FCR_CTF 0x04 /* Clear transmit FIFO */
+ #define FCR_DMA 0x08 /* DMA mode select */
+ #define FCR_F64 0x20 /* Enable 64 byte fifo (16750+) */
+ #define FCR_RT14 0xC0 /* Set Rx trigger at 14 */
+ #define FCR_RT8 0x80 /* Set Rx trigger at 8 */
+ #define FCR_RT4 0x40 /* Set Rx trigger at 4 */
+ #define FCR_RT1 0x00 /* Set Rx trigger at 1 */
+
+/*---------------------------------------------------------------------------+
+| Baud rate divisor registers
++---------------------------------------------------------------------------*/
+ #define DLL RBR
+ #define DLM IER
+
+/*---------------------------------------------------------------------------+
+| Alternate function registers
++---------------------------------------------------------------------------*/
+ #define AFR ISR
+
+/*---------------------------------------------------------------------------+
+| Line control Register.
++---------------------------------------------------------------------------*/
+ unsigned char LCR; /* 0x03 */
+ #define LCR_WL5 0x00 /* Word length 5 */
+ #define LCR_WL6 0x01 /* Word length 6 */
+ #define LCR_WL7 0x02 /* Word length 7 */
+ #define LCR_WL8 0x03 /* Word length 8 */
+
+ #define LCR_SB1 0x00 /* 1 stop bits */
+ #define LCR_SB1_5 0x04 /* 1.5 stop bits , only valid with 5 bit words*/
+ #define LCR_SB1_5 0x04 /* 2 stop bits */
+
+ #define LCR_PN 0x00 /* Parity NONE */
+ #define LCR_PE 0x0C /* Parity EVEN */
+ #define LCR_PO 0x08 /* Parity ODD */
+ #define LCR_PM 0x28 /* Forced "mark" parity */
+ #define LCR_PS 0x38 /* Forced "space" parity */
+
+ #define LCR_DL 0x80 /* Enable baudrate latch */
+
+/*---------------------------------------------------------------------------+
+| Modem control Register.
++---------------------------------------------------------------------------*/
+ unsigned char MCR; /* 0x04 */
+ #define MCR_DTR 0x01
+ #define MCR_RTS 0x02
+ #define MCR_INT 0x08 /* Enable interrupts */
+ #define MCR_LOOP 0x10 /* Loopback mode */
+
+/*---------------------------------------------------------------------------+
+| Line status Register.
++---------------------------------------------------------------------------*/
+ unsigned char LSR; /* 0x05 */
+ #define LSR_RSR 0x01
+ #define LSR_OE 0x02
+ #define LSR_PE 0x04
+ #define LSR_FE 0x08
+ #define LSR_BI 0x10
+ #define LSR_THE 0x20
+ #define LSR_TEMT 0x40
+ #define LSR_FIE 0x80
+
+/*---------------------------------------------------------------------------+
+| Modem status Register.
++---------------------------------------------------------------------------*/
+ unsigned char MSR; /* 0x06 */
+ #define MSR_DCTS 0x01
+ #define MSR_DDSR 0x02
+ #define MSR_TERI 0x04
+ #define MSR_DDCD 0x08
+ #define MSR_CTS 0x10
+ #define MSR_DSR 0x20
+ #define MSR_RI 0x40
+ #define MSR_CD 0x80
+
+/*---------------------------------------------------------------------------+
+| Scratch pad Register.
++---------------------------------------------------------------------------*/
+ unsigned char SCR; /* 0x07 */
+};
+
+
+#define USE_UART 0 /* 0=UART0 1=UART1 */
+#define UART_INTERNAL_CLOCK_DIVISOR 16
+
+typedef volatile struct async *pasync;
+static const pasync port = (pasync)(0xEF600300 + (USE_UART*0x100)); /* 0xEF600300 - port A, 0xEF600400 - port B */
+
+static void *spittyp; /* handle for termios */
+int ppc403_spi_interrupt = 0; /* do not use interrupts... */
+
+
+int round(double x)
+{
+ return (int)((int)((x-(int)x)*1000)>500 ? x+1 : x);
+}
+
+void
+spiBaudSet(unsigned32 baudrate)
+{
+ unsigned32 tmp;
+
+ tmp = round( (double)rtems_cpu_configuration_get_serial_per_sec() / (baudrate * 16) );
+
+ port->LCR = port->LCR | LCR_DL;
+
+ port->DLL = tmp & 0xff;
+ port->DLM = tmp >> 8;
+
+ port->LCR = port->LCR & ~LCR_DL;
+}
+/*
+ * Hardware-dependent portion of tcsetattr().
+ */
+static int
+spiSetAttributes (int minor, const struct termios *t)
+{
+ int baud;
+
+ /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
+ /* FIXME: check and IMPLEMENT XON/XOFF */
+ switch (t->c_cflag & CBAUD) {
+ default: baud = -1; break;
+ case B50: baud = 50; break;
+ case B75: baud = 75; break;
+ case B110: baud = 110; break;
+ case B134: baud = 134; break;
+ case B150: baud = 150; break;
+ case B200: baud = 200; break;
+ case B300: baud = 300; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ case B9600: baud = 9600; break;
+ case B19200: baud = 19200; break;
+ case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ }
+ if (baud > 0) {
+ spiBaudSet(baud);
+ }
+ return 0;
+}
+
+static int
+spiPollRead (int minor)
+{
+
+ /* Wait for character */
+ while ((port->LSR & LSR_RSR)==0);;
+
+ return port->RBR;
+}
+
+
+static int
+spiPollWrite(int minor,const char *buf,int len)
+{
+
+ while (len-- > 0) {
+ while (!(port->LSR & LSR_THE));;
+ port->THR = *buf++;
+ }
+ return 0;
+}
+
+/*
+ * enable/disable RTS line to start/stop remote transmitter
+ */
+static int
+spiStartRemoteTx (int minor)
+{
+/* Not implemented !
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+ port->SPCTL |= CRRts; activate RTS
+ rtems_interrupt_enable (level);
+*/
+ return 0;
+}
+
+static int
+spiStopRemoteTx (int minor)
+{
+/* Not implemented !
+ rtems_interrupt_level level;
+
+ rtems_interrupt_disable (level);
+ port->SPCTL &= ~CRRts; deactivate RTS
+ rtems_interrupt_enable (level);
+*/
+ return 0;
+}
+
+static int InterruptWrite (int minor, const char *buf, int len)
+{
+ port->IER |= IER_XMT; /* always enable tx interrupt */
+ port->THR = *buf; /* write char to send */
+ return 0;
+}
+
+static rtems_isr serial_ISR(rtems_vector_number v)
+{
+ unsigned char _isr;
+ char ch;
+ int res;
+
+ _isr=port->ISR & 0x0E;
+
+ if ((_isr == ISR_Rx) || (_isr==ISR_RxTO)) {
+ ch = port->RBR;
+ rtems_termios_enqueue_raw_characters (spittyp,&ch,1);
+ }
+
+ if (_isr == ISR_Tx) {
+ res = rtems_termios_dequeue_characters (spittyp,1);
+ if (res==0) {
+ port->IER &= ~IER_XMT;
+ }
+
+ }
+}
+
+
+/*
+ *
+ * deinit SPI
+ *
+ */
+void
+spiDeInit(void)
+{
+ /*
+ * disable interrupts for serial port
+ * set it to state to work with polling boot monitor, if any...
+ */
+
+
+ /* set up baud rate to original state */
+ spiBaudSet(rtems_cpu_configuration_get_serial_rate());
+
+ port->IER = 0;
+
+}
+
+/*
+ *
+ * init SPI
+ *
+ */
+rtems_status_code
+spiInitialize(void)
+{
+ register unsigned tmp;
+ rtems_isr_entry previous_isr; /* this is a dummy */
+ unsigned char _ier;
+
+ /*
+ * Initialise the serial port
+ */
+
+ /*
+ * Select clock source and set uart internal clock divisor
+ */
+
+ asm volatile ("mfdcr %0, 0x0b1" : "=r" (tmp)); /* CPC_CR0 0x0b1 */
+
+ /* UART0 bit 24 0x80, UART1 bit 25 0x40 */
+ tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? (USE_UART ? 0x40 : 0x80) : 0);
+
+ tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? 0: ((UART_INTERNAL_CLOCK_DIVISOR -1) << 1));
+
+ asm volatile ("mtdcr 0x0b1, %0" : "=r" (tmp) : "0" (tmp)); /* CPC_CR0 0x0b1*/
+
+ /* Disable port interrupts while changing hardware */
+ _ier = port->IER;
+ port->IER = 0;
+
+ /* set up port control: 8 bit,1 stop,no parity */
+ port->LCR = LCR_WL8 | LCR_SB1 | LCR_PN;
+
+ /* set up baud rate */
+ spiBaudSet(rtems_cpu_configuration_get_serial_rate());
+
+ if (ppc403_spi_interrupt) {
+
+ /* add rx/tx isr to vector table */
+ if (USE_UART==0)
+ ictrl_set_vector(serial_ISR,PPC_IRQ_EXT_UART0,&previous_isr);
+ else
+ ictrl_set_vector(serial_ISR,PPC_IRQ_EXT_UART1,&previous_isr);
+
+ /* Enable and clear FIFO */
+ port->FCR = FCR_FE | FCR_CRF | FCR_CTF | FCR_RT8;
+
+ /* Enable recive interrupts, don't enable TxInt yet */
+ port->IER=IER_RCV;
+ }
+ else {
+ port->IER=_ier;
+ }
+
+ atexit(spiDeInit);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ */
+
+/* console_initialize
+ *
+ * This routine initializes the console IO driver.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
+
+ /*
+ * Do device-specific initialization
+ */
+ spiInitialize ();
+
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name ("/dev/console", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_status_code sc;
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ InterruptWrite, /* write */
+ spiSetAttributes, /* setAttributes */
+ spiStopRemoteTx, /* stopRemoteTx */
+ spiStartRemoteTx, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ spiPollRead, /* pollRead */
+ spiPollWrite, /* write */
+ spiSetAttributes, /* setAttributes */
+ spiStopRemoteTx, /* stopRemoteTx */
+ spiStartRemoteTx, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+ if (ppc403_spi_interrupt) {
+ rtems_libio_open_close_args_t *args = arg;
+ sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
+ spittyp = args->iop->data1;
+ }
+ else {
+ sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
+ }
+ return sc;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close (arg);
+}
+
+/*
+ * read bytes from the serial port. We only have stdin.
+ */
+
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read (arg);
+}
+
+/*
+ * write bytes to the serial port. Stdout and stderr are the same.
+ */
+
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write (arg);
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
+
diff --git a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c
index 6ba3947bc8..eb8bcb7bd8 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.c
@@ -18,6 +18,8 @@
* IMD makes no representations about the suitability
* of this software for any purpose.
*
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
*/
#include "ictrl.h"
@@ -41,6 +43,47 @@ rtems_isr_entry ictrl_vector_table[PPC_IRQ_EXT_MAX];
/*
* clear bits in EXISR that have a bit set in mask
*/
+#if defined(ppc405)
+RTEMS_INLINE_ROUTINE void
+clr_exisr(unsigned32 mask)
+{
+ asm volatile ("mtdcr 0xC0,%0"::"r" (mask));/*EXISR*/
+}
+
+/*
+ * get value of EXISR
+ */
+RTEMS_INLINE_ROUTINE unsigned32
+get_exisr(void)
+{
+ unsigned32 val;
+
+ asm volatile ("mfdcr %0,0xC0":"=r" (val));/*EXISR*/
+ return val;
+}
+
+/*
+ * get value of EXIER
+ */
+RTEMS_INLINE_ROUTINE unsigned32
+get_exier(void)
+{
+ unsigned32 val;
+ asm volatile ("mfdcr %0,0xC2":"=r" (val));/*EXIER*/
+ return val;
+}
+
+/*
+ * set value of EXIER
+ */
+RTEMS_INLINE_ROUTINE void
+set_exier(unsigned32 val)
+{
+ asm volatile ("mtdcr 0xC2,%0"::"r" (val));/*EXIER*/
+}
+
+#else /* not ppc405 */
+
RTEMS_INLINE_ROUTINE void
clr_exisr(unsigned32 mask)
{
@@ -78,7 +121,7 @@ set_exier(unsigned32 val)
{
asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
}
-
+#endif /* ppc405 */
/*
* enable an external interrupt, make this interrupt consistent
*/
@@ -191,7 +234,6 @@ ictrl_set_vector(rtems_isr_entry new_handler,
/* check for valid vector range */
if ((vector >= PPC_IRQ_EXT_BASE) &&
(vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
-
/* return old handler entry */
*old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];
diff --git a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h
index 5891d8aa2e..6c6f77f0e5 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h
+++ b/c/src/lib/libcpu/powerpc/ppc403/ictrl/ictrl.h
@@ -19,6 +19,8 @@
* IMD makes no representations about the suitability
* of this software for any purpose.
*
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
*/
@@ -40,10 +42,19 @@ extern "C" {
/* mask for external interrupt status in EXIER/EXISR register */
/* note: critical interrupt is in these registers aswell */
+#ifndef ppc405
#define PPC_EXI_MASK 0x0FFFFFFF
+#else /* ppc405 */
+#define PPC_EXI_MASK 0xFFFFFFFF
+#endif /* ppc405 */
+#ifndef ppc405
#define PPC_IRQ_EXT_SPIR (PPC_IRQ_EXT_BASE+4)
#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5)
+#else /* ppc405 */
+#define PPC_IRQ_EXT_UART0 (PPC_IRQ_EXT_BASE+0)
+#define PPC_IRQ_EXT_UART1 (PPC_IRQ_EXT_BASE+1)
+#endif /* ppc405 */
#define PPC_IRQ_EXT_JTAGR (PPC_IRQ_EXT_BASE+6)
#define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7)
#define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8)
diff --git a/c/src/lib/libcpu/powerpc/ppc403/timer/timer.c b/c/src/lib/libcpu/powerpc/ppc403/timer/timer.c
index 93a188da60..a29851e349 100644
--- a/c/src/lib/libcpu/powerpc/ppc403/timer/timer.c
+++ b/c/src/lib/libcpu/powerpc/ppc403/timer/timer.c
@@ -30,7 +30,10 @@
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
+ * Modifications for PPC405GP by Dennis Ehlin
+ *
* $Id$
+ *
*/
#include <rtems.h>
@@ -45,7 +48,13 @@ static inline rtems_unsigned32 get_itimer(void)
{
rtems_unsigned32 ret;
+#ifndef ppc405
asm volatile ("mfspr %0, 0x3dd" : "=r" ((ret))); /* TBLO */
+#else /* ppc405 */
+/* asm volatile ("mfspr %0, 0x3dd" : "=r" ((ret))); TBLO */
+
+ asm volatile ("mfspr %0, 0x10c" : "=r" ((ret))); /* 405GP TBL */
+#endif /* ppc405 */
return ret;
}
@@ -54,10 +63,21 @@ void Timer_initialize()
{
rtems_unsigned32 iocr;
+#ifndef ppc405
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
iocr &= ~4;
iocr |= 4; /* Select external timer clock */
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */
+#else /* ppc405 */
+ asm volatile ("mfdcr %0, 0x0b2" : "=r" (iocr)); /*405GP CPC0_CR1 */
+/* asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); IOCR */
+
+ /* iocr |= 0x800000; select external timer clock CETE*/
+ iocr &= ~0x800000; /* timer clocked from system clock CETE*/
+
+ asm volatile ("mtdcr 0x0b2, %0" : "=r" (iocr) : "0" (iocr)); /* 405GP CPC0_CR1 */
+/* asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); IOCR */
+#endif /* ppc405 */
Timer_starting = get_itimer();
}
diff --git a/c/src/lib/libcpu/powerpc/ppc403/tty_drv/.cvsignore b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/.cvsignore
new file mode 100644
index 0000000000..282522db03
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+Makefile.in
diff --git a/c/src/lib/libcpu/powerpc/ppc403/tty_drv/Makefile.am b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/Makefile.am
new file mode 100644
index 0000000000..f445fec6d8
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/Makefile.am
@@ -0,0 +1,32 @@
+##
+## $Id$
+##
+
+AUTOMAKE_OPTIONS = foreign 1.4
+
+PGM = $(ARCH)/tty_drv.rel
+
+include_HEADERS = tty_drv.h
+
+C_FILES = tty_drv.c
+
+tty_drv_rel_OBJECTS = $(C_FILES:%.c=$(ARCH)/%.o)
+
+include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
+include $(top_srcdir)/../../../../../automake/compile.am
+include $(top_srcdir)/../../../../../automake/lib.am
+
+#
+# (OPTIONAL) Add local stuff here using +=
+#
+
+$(PGM): $(tty_drv_rel_OBJECTS)
+ $(make-rel)
+
+all-local: $(ARCH) $(tty_drv_rel_OBJECTS) $(PGM)
+
+.PRECIOUS: $(PGM)
+
+EXTRA_DIST = tty_drv.c tty_drv.h
+
+include $(top_srcdir)/../../../../../automake/local.am
diff --git a/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.c b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.c
new file mode 100644
index 0000000000..56ff791f41
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.c
@@ -0,0 +1,557 @@
+/*
+ * This file contains the PowerPC 405GP tty driver.
+ *
+ * Derived from /c/src/lib/libbsp/i386/shared/comm/tty_drv.c
+ *
+ * Modifications to PPC405GP by Dennis Ehlin
+ *
+ */
+
+#define NO_BSP_INIT
+
+#include <stdio.h>
+#include <rtems/termiostypes.h>
+#include <termios.h>
+#include <assert.h>
+#include <rtems.h>
+#include <rtems/libio.h>
+#include "../ictrl/ictrl.h"
+#include <stdlib.h> /* for atexit() */
+
+
+struct ttyasync {
+/*---------------------------------------------------------------------------+
+| Data Register.
++---------------------------------------------------------------------------*/
+ unsigned char RBR; /* 0x00 */
+ #define THR RBR
+/*---------------------------------------------------------------------------+
+| Interrupt registers
++---------------------------------------------------------------------------*/
+ unsigned char IER; /* Interrupt Enable Register 0x01 */
+ #define IER_RCV 0x01
+ #define IER_XMT 0x02
+ #define IER_LS 0x04
+ #define IER_MS 0x08
+
+ unsigned char ISR; /* Interrupt Status Register 0x02 */
+ #define ISR_MS 0x00
+ #define ISR_nIP 0x01
+ #define ISR_Tx 0x02
+ #define ISR_Rx 0x04
+ #define ISR_LS 0x06
+ #define ISR_RxTO 0x0C
+ #define ISR_64BFIFO 0x20
+ #define ISR_FIFOworks 0x40
+ #define ISR_FIFOen 0x80
+
+/*---------------------------------------------------------------------------+
+| FIFO Control registers
++---------------------------------------------------------------------------*/
+ #define FCR ISR
+ #define FCR_FE 0x01 /* FIFO enable */
+ #define FCR_CRF 0x02 /* Clear receive FIFO */
+ #define FCR_CTF 0x04 /* Clear transmit FIFO */
+ #define FCR_DMA 0x08 /* DMA mode select */
+ #define FCR_F64 0x20 /* Enable 64 byte fifo (16750+) */
+ #define FCR_RT14 0xC0 /* Set Rx trigger at 14 */
+ #define FCR_RT8 0x80 /* Set Rx trigger at 8 */
+ #define FCR_RT4 0x40 /* Set Rx trigger at 4 */
+ #define FCR_RT1 0x00 /* Set Rx trigger at 1 */
+
+/*---------------------------------------------------------------------------+
+| Baud rate divisor registers
++---------------------------------------------------------------------------*/
+ #define DLL RBR
+ #define DLM IER
+
+/*---------------------------------------------------------------------------+
+| Alternate function registers
++---------------------------------------------------------------------------*/
+ #define AFR ISR
+
+/*---------------------------------------------------------------------------+
+| Line control Register.
++---------------------------------------------------------------------------*/
+ unsigned char LCR; /* 0x03 */
+ #define LCR_WL5 0x00 /* Word length 5 */
+ #define LCR_WL6 0x01 /* Word length 6 */
+ #define LCR_WL7 0x02 /* Word length 7 */
+ #define LCR_WL8 0x03 /* Word length 8 */
+
+ #define LCR_SB1 0x00 /* 1 stop bits */
+ #define LCR_SB1_5 0x04 /* 1.5 stop bits , only valid with 5 bit words*/
+ #define LCR_SB1_5 0x04 /* 2 stop bits */
+
+ #define LCR_PN 0x00 /* Parity NONE */
+ #define LCR_PE 0x0C /* Parity EVEN */
+ #define LCR_PO 0x08 /* Parity ODD */
+ #define LCR_PM 0x28 /* Forced "mark" parity */
+ #define LCR_PS 0x38 /* Forced "space" parity */
+
+ #define LCR_DL 0x80 /* Enable baudrate latch */
+
+/*---------------------------------------------------------------------------+
+| Modem control Register.
++---------------------------------------------------------------------------*/
+ unsigned char MCR; /* 0x04 */
+ #define MCR_DTR 0x01
+ #define MCR_RTS 0x02
+ #define MCR_INT 0x08 /* Enable interrupts */
+ #define MCR_LOOP 0x10 /* Loopback mode */
+
+/*---------------------------------------------------------------------------+
+| Line status Register.
++---------------------------------------------------------------------------*/
+ unsigned char LSR; /* 0x05 */
+ #define LSR_RSR 0x01
+ #define LSR_OE 0x02
+ #define LSR_PE 0x04
+ #define LSR_FE 0x08
+ #define LSR_BI 0x10
+ #define LSR_THE 0x20
+ #define LSR_TEMT 0x40
+ #define LSR_FIE 0x80
+
+/*---------------------------------------------------------------------------+
+| Modem status Register.
++---------------------------------------------------------------------------*/
+ unsigned char MSR; /* 0x06 */
+ #define MSR_DCTS 0x01
+ #define MSR_DDSR 0x02
+ #define MSR_TERI 0x04
+ #define MSR_DDCD 0x08
+ #define MSR_CTS 0x10
+ #define MSR_DSR 0x20
+ #define MSR_RI 0x40
+ #define MSR_CD 0x80
+
+/*---------------------------------------------------------------------------+
+| Scratch pad Register.
++---------------------------------------------------------------------------*/
+ unsigned char SCR; /* 0x07 */
+};
+
+
+#define TTY0_USE_UART 1 /* 0=UART0 1=UART1 */
+#define TTY0_UART_INTERNAL_CLOCK_DIVISOR 16
+#define TTY0_USE_INTERRUPT
+
+
+typedef volatile struct ttyasync *tty0pasync;
+static const tty0pasync tty0port = (tty0pasync)(0xEF600300 + (TTY0_USE_UART*0x100)); /* 0xEF600300 - port A, 0xEF600400 - port B */
+
+static void *tty0ttyp; /* handle for termios */
+
+
+int tty0_round(double x)
+{
+ return (int)((int)((x-(int)x)*1000)>500 ? x+1 : x);
+}
+
+void
+tty0BaudSet(unsigned32 baudrate)
+{
+ unsigned32 tmp;
+
+ tmp = tty0_round( (double)rtems_cpu_configuration_get_serial_per_sec() / (baudrate * 16) );
+
+ tty0port->LCR = tty0port->LCR | LCR_DL;
+
+ tty0port->DLL = tmp & 0xff;
+ tty0port->DLM = tmp >> 8;
+
+ tty0port->LCR = tty0port->LCR & ~LCR_DL;
+}
+/*
+ * Hardware-dependent portion of tcsetattr().
+ */
+static int
+tty0SetAttributes (int minor, const struct termios *t)
+{
+ int baud;
+
+ /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
+ /* FIXME: check and IMPLEMENT XON/XOFF */
+ switch (t->c_cflag & CBAUD) {
+ default: baud = -1; break;
+ case B50: baud = 50; break;
+ case B75: baud = 75; break;
+ case B110: baud = 110; break;
+ case B134: baud = 134; break;
+ case B150: baud = 150; break;
+ case B200: baud = 200; break;
+ case B300: baud = 300; break;
+ case B600: baud = 600; break;
+ case B1200: baud = 1200; break;
+ case B1800: baud = 1800; break;
+ case B2400: baud = 2400; break;
+ case B4800: baud = 4800; break;
+ case B9600: baud = 9600; break;
+ case B19200: baud = 19200; break;
+ case B38400: baud = 38400; break;
+ case B57600: baud = 57600; break;
+ case B115200: baud = 115200; break;
+ case B230400: baud = 230400; break;
+ case B460800: baud = 460800; break;
+ }
+ if (baud > 0) {
+ tty0BaudSet(baud);
+ }
+ return 0;
+}
+
+static int
+tty0PollRead (int minor)
+{
+
+ /* Wait for character */
+ while ((tty0port->LSR & LSR_RSR)==0);;
+
+ return tty0port->RBR;
+}
+
+
+static int
+tty0PollWrite(int minor,const char *buf,int len)
+{
+
+ while (len-- > 0) {
+ while (!(tty0port->LSR & LSR_THE));;
+ tty0port->THR = *buf++;
+ }
+ return 0;
+}
+
+/* ================ Termios support =================*/
+
+static int tty0InterruptWrite (int minor, const char *buf, int len)
+{
+
+ if(len <= 0)
+ {
+ return 0;
+ }
+
+ /* Write character */
+
+ tty0port->THR = (*buf &0xff);
+ tty0port->IER |= IER_XMT; /* always enable tx interrupt */
+
+ return 0;
+
+}
+
+static rtems_isr tty0serial_ISR(rtems_vector_number v)
+{
+ char buf[128];
+ int off, ret, vect;
+
+ off = 0;
+
+ for(;;)
+ {
+ vect = tty0port->ISR & 0x0f;
+ if(vect & 1)
+ {
+ /* no more interrupts */
+ if(off > 0) {
+ /* Update rx buffer */
+ rtems_termios_enqueue_raw_characters(tty0ttyp, buf, off );
+
+ tty0port->IER |= IER_RCV; /* always enable rx interrupt */
+ /*rtems_termios_rxirq_occured(tty0ttyp);*/
+ }
+ return;
+ }
+
+ vect = vect & 0xe; /*mask out all except interrupt pending*/
+
+ switch(vect)
+ {
+
+ case ISR_Tx :
+ /*
+ * TX holding empty: we have to disable these interrupts
+ * if there is nothing more to send.
+ */
+
+ /* If nothing else to send disable interrupts */
+ ret = rtems_termios_dequeue_characters(tty0ttyp, 1);
+
+ if ( ret == 0 ) {
+ tty0port->IER &= ~IER_XMT;
+ }
+
+ break;
+ case ISR_RxTO:
+ case ISR_Rx :
+
+ /* disable interrupts and notify termios */
+ tty0port->IER &= ~IER_RCV;
+
+ /* read all bytes in fifo*/
+ while (( off < sizeof(buf) ) && ( tty0port->LSR & LSR_RSR ))
+ {
+ buf[off++] = tty0port->RBR;
+ }
+
+ break;
+ case ISR_LS:
+ /* RX error: eat character */
+ /* printk("********* Error **********\n"); */
+ break;
+ default:
+ /* Should not happen */
+ /* printk("error vect=%x",vect); */
+ return;
+ }
+ }
+
+}
+
+
+/*
+ *
+ * deinit TTY0
+ *
+ */
+void
+tty0DeInit(void)
+{
+ /*
+ * disable interrupts for serial tty0port
+ * set it to state to work with polling boot monitor, if any...
+ */
+
+ /* set up baud rate to original state */
+ tty0BaudSet(rtems_cpu_configuration_get_serial_rate());
+
+ tty0port->IER = 0;
+
+}
+
+/*
+ *
+ * init SPI
+ *
+ */
+rtems_status_code
+tty0Initialize(void)
+{
+ register unsigned tmp;
+ rtems_isr_entry previous_isr; /* this is a dummy */
+ unsigned char _ier;
+ unsigned char _tmp;
+
+ /*
+ * Initialise the serial tty0port
+ */
+
+ /*
+ * Select clock source and set uart internal clock divisor
+ */
+
+ asm volatile ("mfdcr %0, 0x0b1" : "=r" (tmp)); /* CPC_CR0 0x0b1 */
+
+ /* UART0 bit 24 0x80, UART1 bit 25 0x40 */
+ tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? (TTY0_USE_UART ? 0x40 : 0x80) : 0);
+
+ tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? 0: ((TTY0_UART_INTERNAL_CLOCK_DIVISOR -1) << 1));
+
+ asm volatile ("mtdcr 0x0b1, %0" : "=r" (tmp) : "0" (tmp)); /* CPC_CR0 0x0b1*/
+
+ /* Disable tty0port interrupts while changing hardware */
+ _ier = tty0port->IER;
+ tty0port->IER = 0;
+
+ /* set up tty0port control: 8 bit,1 stop,no parity */
+ tty0port->LCR = LCR_WL8 | LCR_SB1 | LCR_PN;
+
+ /* set up baud rate */
+ tty0BaudSet(rtems_cpu_configuration_get_serial_rate());
+
+
+#ifdef TTY0_USE_INTERRUPT
+
+ /* add rx/tx isr to vector table */
+
+ if (TTY0_USE_UART==0)
+ ictrl_set_vector(tty0serial_ISR,PPC_IRQ_EXT_UART0,&previous_isr);
+ else
+ ictrl_set_vector(tty0serial_ISR,PPC_IRQ_EXT_UART1,&previous_isr);
+
+ /* Enable and clear FIFO */
+ tty0port->FCR = FCR_FE | FCR_CRF | FCR_CTF | FCR_RT14;
+
+ /* Read status to clear them */
+ _tmp = tty0port->LSR;
+ _tmp = tty0port->RBR;
+ _tmp = tty0port->MSR;
+
+ /* Enable recive interrupts, don't enable TxInt yet */
+ tty0port->IER=IER_RCV;
+
+#else
+
+ tty0port->IER=_ier;
+
+#endif
+
+ atexit(tty0DeInit);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ */
+
+/* console_initialize
+ *
+ * This routine initializes the console IO driver.
+ *
+ * Input parameters: NONE
+ *
+ * Output parameters: NONE
+ *
+ * Return values:
+ */
+
+rtems_device_driver tty0_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+
+ /*
+ * Set up TERMIOS
+ */
+ rtems_termios_initialize ();
+
+ /*
+ * Do device-specific initialization
+ */
+
+ /*tty0Initialize (); Moved this to open instead */
+
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name ("/dev/ttyS0", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver tty0_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_status_code sc;
+
+#ifdef TTY0_USE_INTERRUPT
+
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ tty0InterruptWrite, /* write */
+ tty0SetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ TERMIOS_TASK_DRIVEN /* outputUsesInterrupts */
+ };
+ rtems_libio_open_close_args_t *args = arg;
+
+ tty0Initialize (); /* Initalize hardware */
+
+ sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
+ tty0ttyp = args->iop->data1;
+
+#else
+
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ tty0PollRead, /* pollRead */
+ tty0PollWrite, /* write */
+ tty0SetAttributes, /* setAttributes */
+ NULL, /* stopRemoteTx */
+ NULL, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+ tty0Initialize (); /* Initalize hardware */
+
+ sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
+
+#endif
+
+ return sc;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver tty0_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_close (arg);
+}
+
+/*
+ * read bytes from the serial port. We only have stdin.
+ */
+
+rtems_device_driver tty0_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_read (arg);
+}
+
+/*
+ * write bytes to the serial port. Stdout and stderr are the same.
+ */
+
+rtems_device_driver tty0_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_write (arg);
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver tty0_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ return rtems_termios_ioctl (arg);
+}
+
diff --git a/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.h b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.h
new file mode 100644
index 0000000000..d2024c89d7
--- /dev/null
+++ b/c/src/lib/libcpu/powerpc/ppc403/tty_drv/tty_drv.h
@@ -0,0 +1,63 @@
+#ifdef ppc405
+#ifndef __tty_drv__
+#define __tty_drv__
+
+/* functions */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* ttyS1 entry points */
+rtems_device_driver tty0_initialize(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver tty0_open(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver tty0_control(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+
+/* tty1 & tty2 shared entry points */
+rtems_device_driver tty0_close(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+
+rtems_device_driver tty0_read(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+rtems_device_driver tty0_write(
+ rtems_device_major_number,
+ rtems_device_minor_number,
+ void *
+);
+
+
+#define TTY0_DRIVER_TABLE_ENTRY \
+ { tty0_initialize, tty0_open, tty0_close, \
+ tty0_read, tty0_write, tty0_control }
+
+
+#ifdef __cplusplus
+}
+#endif
+/* end of include file */
+
+#endif /* __tty_drv__ */
+#endif /* ppc405 */