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.
This commit is contained in:
Joel Sherrill
2001-11-09 00:04:57 +00:00
parent de202e7204
commit e9ae97fbc6
21 changed files with 1382 additions and 33 deletions

View File

@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n", printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc); v, i->pc);
#endif #endif
#ifdef ppc403 #if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL) if (v == PPC_IRQ_EXTERNAL)
{ {
register int r = 0; register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00; Offset = 0x00e00;
break; break;
#if defined(ppc403) #if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET /* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT: case PPC_IRQ_CRIT:

View File

@@ -474,7 +474,7 @@ typedef struct {
void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *); void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
boolean exceptions_in_RAM; /* TRUE if in RAM */ 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 */ unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock; boolean serial_external_clock;
boolean serial_xon_xoff; boolean serial_xon_xoff;
@@ -508,7 +508,7 @@ typedef struct {
#define rtems_cpu_configuration_get_exceptions_in_ram() \ #define rtems_cpu_configuration_get_exceptions_in_ram() \
(_CPU_Table.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() \ #define rtems_cpu_configuration_get_serial_per_sec() \
(_CPU_Table.serial_per_sec) (_CPU_Table.serial_per_sec)

View File

@@ -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> 2001-11-07 Joel Sherrill <joel@OARcorp.com>
* configure.ac: Delete the commented out line that said that * configure.ac: Delete the commented out line that said that

View File

@@ -34,6 +34,10 @@ endif
if ppc403 if ppc403
CPU_SUBDIR = ppc403 CPU_SUBDIR = ppc403
endif endif
if ppc405
## 403 and 405 chips use the same CPU sources...
CPU_SUBDIR = ppc403
endif
SUBDIRS = $(SHARED_LIB) $(EXCEPTION_SUBDIR) $(CPU_SUBDIR) wrapup SUBDIRS = $(SHARED_LIB) $(EXCEPTION_SUBDIR) $(CPU_SUBDIR) wrapup

View File

@@ -9,17 +9,25 @@ available from IBM and Motorola.
Since these routines can differ amongst different members Since these routines can differ amongst different members
of the PowerPC family, an entry per CPU type is provided. 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 At this time, support is included for the following PowerPC
family members: family members using the new exception processing model:
+ mpc505 + mpc505
+ mpc6xx
+ mpc750 + mpc750
+ mpc821 + mpc821
+ mpc823 (uses mpc821 directory)
+ mpc850 (uses mpc860 directory)
+ mpc860 + mpc860
+ ppc403
+ mpc8260 + 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, Note that because of similarities in various family members,
the mpc823 should be able to use the mpc821 code and the the mpc823 should be able to use the mpc821 code and the
mpc850 should be able to use the mpc850 code. mpc850 should be able to use the mpc850 code.

View File

@@ -50,6 +50,7 @@ test "$RTEMS_CPU_MODEL" = "mpc860" \
## first. ## first.
AM_CONDITIONAL(old_exception_processing, \ AM_CONDITIONAL(old_exception_processing, \
test "$RTEMS_CPU_MODEL" = "ppc403" || \ test "$RTEMS_CPU_MODEL" = "ppc403" || \
test "$RTEMS_CPU_MODEL" = "ppc405" || \
test "$RTEMS_CPU_MODEL" = "mpc505" || \ test "$RTEMS_CPU_MODEL" = "mpc505" || \
test "$RTEMS_CPU_MODEL" = "ppc603e" \ test "$RTEMS_CPU_MODEL" = "ppc603e" \
) )
@@ -64,6 +65,7 @@ AM_CONDITIONAL(mpc8xx, test "$RTEMS_CPU_MODEL" = "mpc8xx" \
|| test "$RTEMS_CPU_MODEL" = "mpc860" ) || test "$RTEMS_CPU_MODEL" = "mpc860" )
AM_CONDITIONAL(mpc8260, test "$RTEMS_CPU_MODEL" = "mpc8260") AM_CONDITIONAL(mpc8260, test "$RTEMS_CPU_MODEL" = "mpc8260")
AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403") AM_CONDITIONAL(ppc403, test "$RTEMS_CPU_MODEL" = "ppc403")
AM_CONDITIONAL(ppc405, test "$RTEMS_CPU_MODEL" = "ppc405")
# Explicitly list all Makefiles here # Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile AC_CONFIG_FILES([Makefile
@@ -82,6 +84,7 @@ mpc8xx/timer/Makefile
ppc403/Makefile ppc403/Makefile
ppc403/clock/Makefile ppc403/clock/Makefile
ppc403/console/Makefile ppc403/console/Makefile
ppc403/tty_drv/Makefile
ppc403/ictrl/Makefile ppc403/ictrl/Makefile
ppc403/timer/Makefile ppc403/timer/Makefile
ppc403/vectors/Makefile ppc403/vectors/Makefile

View File

@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n", printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc); v, i->pc);
#endif #endif
#ifdef ppc403 #if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL) if (v == PPC_IRQ_EXTERNAL)
{ {
register int r = 0; register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00; Offset = 0x00e00;
break; break;
#if defined(ppc403) #if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET /* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT: case PPC_IRQ_CRIT:

View File

@@ -366,7 +366,7 @@ static void ppc_spurious(int v, CPU_Interrupt_frame *i)
printf("Spurious interrupt on vector %d from %08.8x\n", printf("Spurious interrupt on vector %d from %08.8x\n",
v, i->pc); v, i->pc);
#endif #endif
#ifdef ppc403 #if defined(ppc403) || defined(ppc405)
if (v == PPC_IRQ_EXTERNAL) if (v == PPC_IRQ_EXTERNAL)
{ {
register int r = 0; register int r = 0;
@@ -627,7 +627,7 @@ unsigned32 ppc_exception_vector_addr(
Offset = 0x00e00; Offset = 0x00e00;
break; break;
#if defined(ppc403) #if defined(ppc403) || defined(ppc405)
/* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET /* PPC_IRQ_CRIT is the same vector as PPC_IRQ_RESET
case PPC_IRQ_CRIT: case PPC_IRQ_CRIT:

View File

@@ -474,7 +474,7 @@ typedef struct {
void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *); void (*spurious_handler)(unsigned32 vector, CPU_Interrupt_frame *);
boolean exceptions_in_RAM; /* TRUE if in RAM */ 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 */ unsigned32 serial_per_sec; /* Serial clocks per second */
boolean serial_external_clock; boolean serial_external_clock;
boolean serial_xon_xoff; boolean serial_xon_xoff;
@@ -508,7 +508,7 @@ typedef struct {
#define rtems_cpu_configuration_get_exceptions_in_ram() \ #define rtems_cpu_configuration_get_exceptions_in_ram() \
(_CPU_Table.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() \ #define rtems_cpu_configuration_get_serial_per_sec() \
(_CPU_Table.serial_per_sec) (_CPU_Table.serial_per_sec)

View File

@@ -4,7 +4,12 @@
AUTOMAKE_OPTIONS = foreign 1.4 AUTOMAKE_OPTIONS = foreign 1.4
if ppc403
SUBDIRS = console clock timer vectors ictrl 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/subdirs.am
include $(top_srcdir)/../../../../../automake/local.am include $(top_srcdir)/../../../../../automake/local.am

View File

@@ -25,7 +25,6 @@
* for these modifications: * for these modifications:
* COPYRIGHT (c) 1997 by IMD, Puchheim, Germany. * COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
* *
*
* COPYRIGHT (c) 1989-1999. * COPYRIGHT (c) 1989-1999.
* On-Line Applications Research Corporation (OAR). * On-Line Applications Research Corporation (OAR).
* *
@@ -33,6 +32,8 @@
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html. * http://www.OARcorp.com/rtems/license.html.
* *
* Modifications for PPC405GP by Dennis Ehlin
*
* $Id$ * $Id$
*/ */
@@ -59,7 +60,11 @@ static inline rtems_unsigned32 get_itimer(void)
{ {
register rtems_unsigned32 rc; register rtems_unsigned32 rc;
#ifndef ppc405 /* this is a ppc403 */
asm volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */ asm volatile ("mfspr %0, 0x3dd" : "=r" ((rc))); /* TBLO */
#else /* ppc405 */
asm volatile ("mfspr %0, 0x10c" : "=r" ((rc))); /* 405GP TBL */
#endif /* ppc405 */
return rc; return rc;
} }
@@ -71,11 +76,10 @@ static inline rtems_unsigned32 get_itimer(void)
rtems_isr rtems_isr
Clock_isr(rtems_vector_number vector) Clock_isr(rtems_vector_number vector)
{ {
rtems_unsigned32 clicks_til_next_interrupt;
if (!auto_restart) if (!auto_restart)
{ {
rtems_unsigned32 clicks_til_next_interrupt;
rtems_unsigned32 itimer_value; rtems_unsigned32 itimer_value;
/* /*
* setup for next interrupt; making sure the new value is reasonably * setup for next interrupt; making sure the new value is reasonably
* in the future.... in case we lost out on an interrupt somehow * 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) void Install_clock(rtems_isr_entry clock_isr)
{ {
rtems_isr_entry previous_isr; rtems_isr_entry previous_isr;
rtems_unsigned32 pvr, iocr; rtems_unsigned32 iocr;
register rtems_unsigned32 tcr; register rtems_unsigned32 tcr;
#ifdef ppc403
rtems_unsigned32 pvr;
#endif /* ppc403 */
Clock_driver_ticks = 0; Clock_driver_ticks = 0;
#ifndef ppc405 /* this is a ppc403 */
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */ asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
if (rtems_cpu_configuration_get_timer_internal_clock()) { if (rtems_cpu_configuration_get_timer_internal_clock()) {
iocr &= ~4; /* timer clocked from system clock */ iocr &= ~4; /* timer clocked from system clock */
} }
else { else {
iocr |= 4; /* select external timer clock */ iocr |= 4; /* select external timer clock */
} }
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */ asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */
asm volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */ asm volatile ("mfspr %0, 0x11f" : "=r" ((pvr))); /* PVR */
if (((pvr & 0xffff0000) >> 16) != 0x0020) if (((pvr & 0xffff0000) >> 16) != 0x0020)
return; /* Not a ppc403 */ return; /* Not a ppc403 */
@@ -162,10 +167,26 @@ void Install_clock(rtems_isr_entry clock_isr)
else if ((pvr & 0xff00) == 0x0100) /* 403GB */ else if ((pvr & 0xff00) == 0x0100) /* 403GB */
auto_restart = 1; 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() * pit_value = rtems_configuration_get_microseconds_per_tick() *
rtems_cpu_configuration_get_clicks_per_usec(); rtems_cpu_configuration_get_clicks_per_usec();
/* /*
* initialize the interval here * initialize the interval here
* First tick is set to right amount of time in the future * 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); rtems_interrupt_catch(clock_isr, PPC_IRQ_PIT, &previous_isr);
/*
* Set PIT value
*/
asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */ asm volatile ("mtspr 0x3db, %0" : : "r" (pit_value)); /* PIT */
asm volatile ("mfspr %0, 0x3da" : "=r" ((tcr))); /* TCR */ /*
* Set timer to autoreload, bit TCR->ARE = 1 0x0400000
tcr &= ~ 0x04400000; * Enable PIT interrupt, bit TCR->PIE = 1 0x4000000
*/
tcr |= (auto_restart ? 0x04400000 : 0x04000000);
tick_time = get_itimer() + pit_value; 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 */ asm volatile ("mtspr 0x3da, %0" : "=r" ((tcr)) : "0" ((tcr))); /* TCR */
atexit(Clock_exit); atexit(Clock_exit);
@@ -208,6 +232,9 @@ ReInstall_clock(rtems_isr_entry new_clock_isr)
/* /*
* Called via atexit() * Called via atexit()
* Remove the clock interrupt handler by setting handler to NULL * 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 void

View File

@@ -6,7 +6,12 @@ AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/console.rel PGM = $(ARCH)/console.rel
if ppc403
C_FILES = console.c C_FILES = console.c
endif
if ppc405
C_FILES = console405.c
endif
console_rel_OBJECTS = $(C_FILES:%.c=$(ARCH)/%.o) console_rel_OBJECTS = $(C_FILES:%.c=$(ARCH)/%.o)
@@ -25,6 +30,6 @@ all-local: $(ARCH) $(console_rel_OBJECTS) $(PGM)
.PRECIOUS: $(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 include $(top_srcdir)/../../../../../automake/local.am

View File

@@ -147,7 +147,7 @@ typedef volatile struct async *pasync;
static const pasync port = (pasync)0x40000000; static const pasync port = (pasync)0x40000000;
static void *spittyp; /* handle for termios */ 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 * Rx Interrupt handler

View File

@@ -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);
}

View File

@@ -18,6 +18,8 @@
* IMD makes no representations about the suitability * IMD makes no representations about the suitability
* of this software for any purpose. * of this software for any purpose.
* *
* Modifications for PPC405GP by Dennis Ehlin
*
*/ */
#include "ictrl.h" #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 * 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 RTEMS_INLINE_ROUTINE void
clr_exisr(unsigned32 mask) clr_exisr(unsigned32 mask)
{ {
@@ -78,7 +121,7 @@ set_exier(unsigned32 val)
{ {
asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/ asm volatile ("mtdcr 0x42,%0"::"r" (val));/*EXIER*/
} }
#endif /* ppc405 */
/* /*
* enable an external interrupt, make this interrupt consistent * 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 */ /* check for valid vector range */
if ((vector >= PPC_IRQ_EXT_BASE) && if ((vector >= PPC_IRQ_EXT_BASE) &&
(vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) { (vector < PPC_IRQ_EXT_BASE + PPC_IRQ_EXT_MAX)) {
/* return old handler entry */ /* return old handler entry */
*old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE]; *old_handler = ictrl_vector_table[vector - PPC_IRQ_EXT_BASE];

View File

@@ -19,6 +19,8 @@
* IMD makes no representations about the suitability * IMD makes no representations about the suitability
* of this software for any purpose. * 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 */ /* mask for external interrupt status in EXIER/EXISR register */
/* note: critical interrupt is in these registers aswell */ /* note: critical interrupt is in these registers aswell */
#ifndef ppc405
#define PPC_EXI_MASK 0x0FFFFFFF #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_SPIR (PPC_IRQ_EXT_BASE+4)
#define PPC_IRQ_EXT_SPIT (PPC_IRQ_EXT_BASE+5) #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_JTAGR (PPC_IRQ_EXT_BASE+6)
#define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7) #define PPC_IRQ_EXT_JTAGT (PPC_IRQ_EXT_BASE+7)
#define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8) #define PPC_IRQ_EXT_DMA0 (PPC_IRQ_EXT_BASE+8)

View File

@@ -30,7 +30,10 @@
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html. * http://www.OARcorp.com/rtems/license.html.
* *
* Modifications for PPC405GP by Dennis Ehlin
*
* $Id$ * $Id$
*
*/ */
#include <rtems.h> #include <rtems.h>
@@ -45,7 +48,13 @@ static inline rtems_unsigned32 get_itimer(void)
{ {
rtems_unsigned32 ret; rtems_unsigned32 ret;
#ifndef ppc405
asm volatile ("mfspr %0, 0x3dd" : "=r" ((ret))); /* TBLO */ 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; return ret;
} }
@@ -54,10 +63,21 @@ void Timer_initialize()
{ {
rtems_unsigned32 iocr; rtems_unsigned32 iocr;
#ifndef ppc405
asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */ asm volatile ("mfdcr %0, 0xa0" : "=r" (iocr)); /* IOCR */
iocr &= ~4; iocr &= ~4;
iocr |= 4; /* Select external timer clock */ iocr |= 4; /* Select external timer clock */
asm volatile ("mtdcr 0xa0, %0" : "=r" (iocr) : "0" (iocr)); /* IOCR */ 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(); Timer_starting = get_itimer();
} }

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 */