summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/ppc403
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libcpu/powerpc/ppc403')
-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
12 files changed, 1337 insertions, 19 deletions
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 */