summaryrefslogtreecommitdiffstats
path: root/drivers/serial
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-05 18:02:15 +0200
committerSascha Hauer <sha@octopus.labnet.pengutronix.de>2007-07-05 18:02:15 +0200
commitf59546b79bcad4d65b84208817ab740214e78340 (patch)
tree142f4c2e3749509cd9be24da63b210fb553d2b47 /drivers/serial
parent4f69d7aa1a4ff6f871ff0f95b76c1b6b4d03d87c (diff)
downloadbarebox-f59546b79bcad4d65b84208817ab740214e78340.tar.gz
barebox-f59546b79bcad4d65b84208817ab740214e78340.tar.xz
svn_rev_675
move serial and network drivers from cpu/ to drivers/
Diffstat (limited to 'drivers/serial')
-rw-r--r--drivers/serial/asc_serial.c371
-rw-r--r--drivers/serial/asc_serial.h177
-rw-r--r--drivers/serial/serial_at91rm9200.c110
-rw-r--r--drivers/serial/serial_au1x00.c135
-rw-r--r--drivers/serial/serial_bf533.c195
-rw-r--r--drivers/serial/serial_bf533.h78
-rw-r--r--drivers/serial/serial_clps7111.c126
-rw-r--r--drivers/serial/serial_ixp.c125
-rw-r--r--drivers/serial/serial_ks8695.c117
-rw-r--r--drivers/serial/serial_lh7a40x.c166
-rw-r--r--drivers/serial/serial_mcf52x2.c215
-rw-r--r--drivers/serial/serial_mpc5xx.c170
-rw-r--r--drivers/serial/serial_mpc8260_scc.c498
-rw-r--r--drivers/serial/serial_mpc8260_smc.c462
-rw-r--r--drivers/serial/serial_mpc85xx_scc.c274
-rw-r--r--drivers/serial/serial_mpc8xx.c704
-rw-r--r--drivers/serial/serial_netarm.c200
-rw-r--r--drivers/serial/serial_nios.c135
-rw-r--r--drivers/serial/serial_nios2.c143
-rw-r--r--drivers/serial/serial_ppc4xx.c984
-rw-r--r--drivers/serial/serial_pxa.c198
-rw-r--r--drivers/serial/serial_s3c24x0.c166
-rw-r--r--drivers/serial/serial_s3c44b0.c218
-rw-r--r--drivers/serial/serial_sa1100.c160
24 files changed, 6127 insertions, 0 deletions
diff --git a/drivers/serial/asc_serial.c b/drivers/serial/asc_serial.c
new file mode 100644
index 0000000000..d95ec3fd2f
--- /dev/null
+++ b/drivers/serial/asc_serial.c
@@ -0,0 +1,371 @@
+/*
+ * (INCA) ASC UART support
+ */
+
+#include <config.h>
+
+#if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP)
+
+#ifdef CONFIG_PURPLE
+#define serial_init asc_serial_init
+#define serial_putc asc_serial_putc
+#define serial_puts asc_serial_puts
+#define serial_getc asc_serial_getc
+#define serial_tstc asc_serial_tstc
+#define serial_setbrg asc_serial_setbrg
+#endif
+
+#include <common.h>
+#include <asm/inca-ip.h>
+#include "asc_serial.h"
+
+#ifdef CONFIG_PURPLE
+
+#undef ASC_FIFO_PRESENT
+#define TOUT_LOOP 100000
+
+/* Set base address for second FPI interrupt control register bank */
+#define SFPI_INTCON_BASEADDR 0xBF0F0000
+
+/* Register offset from base address */
+#define FBS_ISR 0x00000000 /* Interrupt status register */
+#define FBS_IMR 0x00000008 /* Interrupt mask register */
+#define FBS_IDIS 0x00000010 /* Interrupt disable register */
+
+/* Interrupt status register bits */
+#define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */
+#define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */
+#define FBS_ISR_AE 0x00000010 /* ASC error interrupt */
+#define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */
+#define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */
+#define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */
+
+#else
+
+#define ASC_FIFO_PRESENT
+
+#endif
+
+
+#define SET_BIT(reg, mask) reg |= (mask)
+#define CLEAR_BIT(reg, mask) reg &= (~mask)
+#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask)
+#define SET_BITS(reg, mask) SET_BIT(reg, mask)
+#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);}
+
+extern uint incaip_get_fpiclk(void);
+
+static int serial_setopt (void);
+
+/* pointer to ASC register base address */
+static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC;
+
+/******************************************************************************
+*
+* serial_init - initialize a INCAASC channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+#ifdef CONFIG_INCA_IP
+ /* we have to set PMU.EN13 bit to enable an ASC device*/
+ INCAASC_PMU_ENABLE(13);
+#endif
+
+ /* and we have to set CLC register*/
+ CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS);
+ SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001);
+
+ /* initialy we are in async mode */
+ pAsc->asc_con = ASCCON_M_8ASYNC;
+
+ /* select input port */
+ pAsc->asc_pisel = (CONSOLE_TTY & 0x1);
+
+#ifdef ASC_FIFO_PRESENT
+ /* TXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK,
+ ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL);
+ /* enable TXFIFO */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN);
+
+ /* RXFIFO's filling level */
+ SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK,
+ ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL);
+ /* enable RXFIFO */
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN);
+#endif
+
+ /* enable error signals */
+ SET_BIT(pAsc->asc_con, ASCCON_FEN);
+ SET_BIT(pAsc->asc_con, ASCCON_OEN);
+
+#ifdef CONFIG_INCA_IP
+ /* acknowledge ASC interrupts */
+ ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL);
+
+ /* disable ASC interrupts */
+ ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL);
+#endif
+
+#ifdef ASC_FIFO_PRESENT
+ /* set FIFOs into the transparent mode */
+ SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN);
+ SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN);
+#endif
+
+ /* set baud rate */
+ serial_setbrg();
+
+ /* set the options */
+ serial_setopt();
+
+ return 0;
+}
+
+void serial_setbrg (void)
+{
+ ulong uiReloadValue, fdv;
+ ulong f_ASC;
+
+#ifdef CONFIG_INCA_IP
+ f_ASC = incaip_get_fpiclk();
+#else
+ f_ASC = ASC_CLOCK_RATE;
+#endif
+
+#ifndef INCAASC_USE_FDV
+ fdv = 2;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_HIGH_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+#ifndef INCAASC_USE_FDV
+ fdv = 3;
+ uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1;
+#else
+ fdv = INCAASC_FDV_LOW_BAUDRATE;
+ uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1;
+#endif /* INCAASC_USE_FDV */
+
+ if ( (uiReloadValue < 0) || (uiReloadValue > 8191) )
+ {
+ return; /* can't impossibly generate that baud rate */
+ }
+ }
+
+ /* Disable Baud Rate Generator; BG should only be written when R=0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_R);
+
+#ifndef INCAASC_USE_FDV
+ /*
+ * Disable Fractional Divider (FDE)
+ * Divide clock by reload-value + constant (BRS)
+ */
+ /* FDE = 0 */
+ CLEAR_BIT(pAsc->asc_con, ASCCON_FDE);
+
+ if ( fdv == 2 )
+ CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */
+ else
+ SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */
+
+#else /* INCAASC_USE_FDV */
+
+ /* Enable Fractional Divider */
+ SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */
+
+ /* Set fractional divider value */
+ pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK;
+
+#endif /* INCAASC_USE_FDV */
+
+ /* Set reload value in BG */
+ pAsc->asc_bg = uiReloadValue;
+
+ /* Enable Baud Rate Generator */
+ SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */
+}
+
+/*******************************************************************************
+*
+* serial_setopt - set the serial options
+*
+* Set the channel operating mode to that specified. Following options
+* are supported: CREAD, CSIZE, PARENB, and PARODD.
+*
+* Note, this routine disables the transmitter. The calling routine
+* may have to re-enable it.
+*
+* RETURNS:
+* Returns 0 to indicate success, otherwise -1 is returned
+*/
+
+static int serial_setopt (void)
+{
+ ulong con;
+
+ switch ( ASC_OPTIONS & ASCOPT_CSIZE )
+ {
+ /* 7-bit-data */
+ case ASCOPT_CS7:
+ con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */
+ break;
+
+ /* 8-bit-data */
+ case ASCOPT_CS8:
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */
+ else
+ con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */
+ break;
+
+ /*
+ * only 7 and 8-bit frames are supported
+ * if we don't use IOCTL extensions
+ */
+ default:
+ return -1;
+ }
+
+ if ( ASC_OPTIONS & ASCOPT_STOPB )
+ SET_BIT(con, ASCCON_STP); /* 2 stop bits */
+ else
+ CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */
+
+ if ( ASC_OPTIONS & ASCOPT_PARENB )
+ SET_BIT(con, ASCCON_PEN); /* enable parity checking */
+ else
+ CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */
+
+ if ( ASC_OPTIONS & ASCOPT_PARODD )
+ SET_BIT(con, ASCCON_ODD); /* odd parity */
+ else
+ CLEAR_BIT(con, ASCCON_ODD); /* even parity */
+
+ if ( ASC_OPTIONS & ASCOPT_CREAD )
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */
+
+ pAsc->asc_con |= con;
+
+ return 0;
+}
+
+void serial_putc (const char c)
+{
+#ifdef ASC_FIFO_PRESENT
+ uint txFl = 0;
+#else
+ uint timeout = 0;
+#endif
+
+ if (c == '\n') serial_putc ('\r');
+
+#ifdef ASC_FIFO_PRESENT
+ /* check do we have a free space in the TX FIFO */
+ /* get current filling level */
+ do
+ {
+ txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF;
+ }
+ while ( txFl == INCAASC_TXFIFO_FULL );
+#else
+
+ while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
+ FBS_ISR_AB))
+ {
+ if (timeout++ > TOUT_LOOP)
+ {
+ break;
+ }
+ }
+#endif
+
+ pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */
+
+#ifndef ASC_FIFO_PRESENT
+ *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB |
+ FBS_ISR_AT;
+#endif
+
+ /* check for errors */
+ if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ return;
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ ulong symbol_mask;
+ char c;
+
+ while (!serial_tstc());
+
+ symbol_mask =
+ ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff);
+
+ c = (char)(pAsc->asc_rbuf & symbol_mask);
+
+#ifndef ASC_FIFO_PRESENT
+ *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR;
+#endif
+
+ return c;
+}
+
+int serial_tstc (void)
+{
+ int res = 1;
+
+#ifdef ASC_FIFO_PRESENT
+ if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 )
+ {
+ res = 0;
+ }
+#else
+ if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) &
+ FBS_ISR_AR))
+
+ {
+ res = 0;
+ }
+#endif
+ else if ( pAsc->asc_con & ASCCON_FE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_PE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE);
+ res = 0;
+ }
+ else if ( pAsc->asc_con & ASCCON_OE )
+ {
+ SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE);
+ res = 0;
+ }
+
+ return res;
+}
+#endif /* CONFIG_PURPLE || CONFIG_INCA_IP */
diff --git a/drivers/serial/asc_serial.h b/drivers/serial/asc_serial.h
new file mode 100644
index 0000000000..7ffdcfaf8b
--- /dev/null
+++ b/drivers/serial/asc_serial.h
@@ -0,0 +1,177 @@
+/* incaAscSio.h - (INCA) ASC UART tty driver header */
+
+#ifndef __INCincaAscSioh
+#define __INCincaAscSioh
+
+#include <asm/inca-ip.h>
+
+/* channel operating modes */
+#define ASCOPT_CSIZE 0x00000003
+#define ASCOPT_CS7 0x00000001
+#define ASCOPT_CS8 0x00000002
+#define ASCOPT_PARENB 0x00000004
+#define ASCOPT_STOPB 0x00000008
+#define ASCOPT_PARODD 0x00000010
+#define ASCOPT_CREAD 0x00000020
+
+#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8)
+
+/* ASC input select (0 or 1) */
+#define CONSOLE_TTY 0
+
+/* use fractional divider for baudrate settings */
+#define INCAASC_USE_FDV
+
+#ifdef INCAASC_USE_FDV
+ #define INCAASC_FDV_LOW_BAUDRATE 71
+ #define INCAASC_FDV_HIGH_BAUDRATE 453
+#endif /*INCAASC_USE_FDV*/
+
+
+#define INCAASC_TXFIFO_FL 1
+#define INCAASC_RXFIFO_FL 1
+#define INCAASC_TXFIFO_FULL 16
+
+/* interrupt lines masks for the ASC device interrupts*/
+/* change these macroses if it's necessary */
+#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */
+
+#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */
+#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */
+#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */
+#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/
+
+/* interrupt controller access macros */
+#define ASC_INTERRUPTS_ENABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X;
+#define ASC_INTERRUPTS_DISABLE(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X;
+#define ASC_INTERRUPTS_CLEAR(X) \
+ *((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X;
+
+/* CLC register's bits and bitfields */
+#define ASCCLC_DISR 0x00000001
+#define ASCCLC_DISS 0x00000002
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+
+/* CON register's bits and bitfields */
+#define ASCCON_MODEMASK 0x0007
+ #define ASCCON_M_8SYNC 0x0
+ #define ASCCON_M_8ASYNC 0x1
+ #define ASCCON_M_8IRDAASYNC 0x2
+ #define ASCCON_M_7ASYNCPAR 0x3
+ #define ASCCON_M_9ASYNC 0x4
+ #define ASCCON_M_8WAKEUPASYNC 0x5
+ #define ASCCON_M_8ASYNCPAR 0x7
+#define ASCCON_STP 0x0008
+#define ASCCON_REN 0x0010
+#define ASCCON_PEN 0x0020
+#define ASCCON_FEN 0x0040
+#define ASCCON_OEN 0x0080
+#define ASCCON_PE 0x0100
+#define ASCCON_FE 0x0200
+#define ASCCON_OE 0x0400
+#define ASCCON_FDE 0x0800
+#define ASCCON_ODD 0x1000
+#define ASCCON_BRS 0x2000
+#define ASCCON_LB 0x4000
+#define ASCCON_R 0x8000
+
+/* WHBCON register's bits and bitfields */
+#define ASCWHBCON_CLRREN 0x0010
+#define ASCWHBCON_SETREN 0x0020
+#define ASCWHBCON_CLRPE 0x0100
+#define ASCWHBCON_CLRFE 0x0200
+#define ASCWHBCON_CLROE 0x0400
+#define ASCWHBCON_SETPE 0x0800
+#define ASCWHBCON_SETFE 0x1000
+#define ASCWHBCON_SETOE 0x2000
+
+/* ABCON register's bits and bitfields */
+#define ASCABCON_ABEN 0x0001
+#define ASCABCON_AUREN 0x0002
+#define ASCABCON_ABSTEN 0x0004
+#define ASCABCON_ABDETEN 0x0008
+#define ASCABCON_FCDETEN 0x0010
+#define ASCABCON_EMMASK 0x0300
+ #define ASCABCON_EMOFF 8
+ #define ASCABCON_EM_DISAB 0x0
+ #define ASCABCON_EM_DURAB 0x1
+ #define ASCABCON_EM_ALWAYS 0x2
+#define ASCABCON_TXINV 0x0400
+#define ASCABCON_RXINV 0x0800
+
+/* FDV register mask, offset and bitfields*/
+#define ASCFDV_VALUE_MASK 0x000001FF
+
+/* WHBABCON register's bits and bitfields */
+#define ASCWHBABCON_SETABEN 0x0001
+#define ASCWHBABCON_CLRABEN 0x0002
+
+/* ABSTAT register's bits and bitfields */
+#define ASCABSTAT_FCSDET 0x0001
+#define ASCABSTAT_FCCDET 0x0002
+#define ASCABSTAT_SCSDET 0x0004
+#define ASCABSTAT_SCCDET 0x0008
+#define ASCABSTAT_DETWAIT 0x0010
+
+/* WHBABSTAT register's bits and bitfields */
+#define ASCWHBABSTAT_CLRFCSDET 0x0001
+#define ASCWHBABSTAT_SETFCSDET 0x0002
+#define ASCWHBABSTAT_CLRFCCDET 0x0004
+#define ASCWHBABSTAT_SETFCCDET 0x0008
+#define ASCWHBABSTAT_CLRSCSDET 0x0010
+#define ASCWHBABSTAT_SETSCSDET 0x0020
+#define ASCWHBABSTAT_SETSCCDET 0x0040
+#define ASCWHBABSTAT_CLRSCCDET 0x0080
+#define ASCWHBABSTAT_CLRDETWAIT 0x0100
+#define ASCWHBABSTAT_SETDETWAIT 0x0200
+
+/* TXFCON register's bits and bitfields */
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXTMEN 0x0004
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+
+/* RXFCON register's bits and bitfields */
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXTMEN 0x0004
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+
+/* FSTAT register's bits and bitfields */
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFFLOFF 8
+
+#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT);
+
+typedef struct /* incaAsc_t */
+{
+ volatile unsigned long asc_clc; /*0x0000*/
+ volatile unsigned long asc_pisel; /*0x0004*/
+ volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/
+ volatile unsigned long asc_con; /*0x0010*/
+ volatile unsigned long asc_bg; /*0x0014*/
+ volatile unsigned long asc_fdv; /*0x0018*/
+ volatile unsigned long asc_pmw; /* not used */ /*0x001C*/
+ volatile unsigned long asc_tbuf; /*0x0020*/
+ volatile unsigned long asc_rbuf; /*0x0024*/
+ volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/
+ volatile unsigned long asc_abcon; /*0x0030*/
+ volatile unsigned long asc_abstat; /* not used */ /*0x0034*/
+ volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/
+ volatile unsigned long asc_rxfcon; /*0x0040*/
+ volatile unsigned long asc_txfcon; /*0x0044*/
+ volatile unsigned long asc_fstat; /*0x0048*/
+ volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/
+ volatile unsigned long asc_whbcon; /*0x0050*/
+ volatile unsigned long asc_whbabcon; /*0x0054*/
+ volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/
+
+} incaAsc_t;
+
+#endif /* __INCincaAscSioh */
diff --git a/drivers/serial/serial_at91rm9200.c b/drivers/serial/serial_at91rm9200.c
new file mode 100644
index 0000000000..7f00b30ad6
--- /dev/null
+++ b/drivers/serial/serial_at91rm9200.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2002
+ * Lineo, Inc <www.lineo.com>
+ * Bernhard Kuhn <bkuhn@lineo.com>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+#if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1)
+#error must define one of CONFIG_DBGU or CONFIG_USART0 or CONFIG_USART1
+#endif
+
+/* ggi thunder */
+#ifdef CONFIG_DBGU
+AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU;
+#endif
+#ifdef CONFIG_USART0
+AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US0;
+#endif
+#ifdef CONFIG_USART1
+AT91PS_USART us = (AT91PS_USART) AT91C_BASE_US1;
+#endif
+
+void serial_setbrg (void)
+{
+ int baudrate;
+
+ baudrate = CONFIG_BAUDRATE;
+ /* MASTER_CLOCK/(16 * baudrate) */
+ us->US_BRGR = (AT91C_MASTER_CLOCK >> 4) / (unsigned)baudrate;
+}
+
+int serial_init (void)
+{
+ /* make any port initializations specific to this port */
+#ifdef CONFIG_DBGU
+ *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; /* PA 31 & 30 */
+ *AT91C_PMC_PCER = 1 << AT91C_ID_SYS; /* enable clock */
+#endif
+#ifdef CONFIG_USART0
+ *AT91C_PIOA_PDR = AT91C_PA17_TXD0 | AT91C_PA18_RXD0;
+ *AT91C_PMC_PCER |= 1 << AT91C_ID_USART0; /* enable clock */
+#endif
+#ifdef CONFIG_USART1
+ *AT91C_PIOB_PDR = AT91C_PB21_TXD1 | AT91C_PB20_RXD1;
+ *AT91C_PMC_PCER |= 1 << AT91C_ID_USART1; /* enable clock */
+#endif
+ serial_setbrg ();
+
+ us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX;
+ us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
+ us->US_MR =
+ (AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS |
+ AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT);
+ us->US_IMR = ~0ul;
+ return (0);
+}
+
+void serial_putc (const char c)
+{
+ if (c == '\n')
+ serial_putc ('\r');
+ while ((us->US_CSR & AT91C_US_TXRDY) == 0);
+ us->US_THR = c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ while ((us->US_CSR & AT91C_US_RXRDY) == 0);
+ return us->US_RHR;
+}
+
+int serial_tstc (void)
+{
+ return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY);
+}
diff --git a/drivers/serial/serial_au1x00.c b/drivers/serial/serial_au1x00.c
new file mode 100644
index 0000000000..42c668ee3d
--- /dev/null
+++ b/drivers/serial/serial_au1x00.c
@@ -0,0 +1,135 @@
+/*
+ * AU1X00 UART support
+ *
+ * Hardcoded to UART 0 for now
+ * Speed and options also hardcoded to 115200 8N1
+ *
+ * Copyright (c) 2003 Thomas.Lange@corelatus.se
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <config.h>
+
+#ifdef CONFIG_AU1X00
+
+#include <common.h>
+#include <asm/au1x00.h>
+
+/******************************************************************************
+*
+* serial_init - initialize a channel
+*
+* This routine initializes the number of data bits, parity
+* and set the selected baud rate. Interrupts are disabled.
+* Set the modem control signals if the option is selected.
+*
+* RETURNS: N/A
+*/
+
+int serial_init (void)
+{
+ volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR);
+ volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE);
+
+ /* Enable clocks first */
+ *uart_enable = UART_EN_CE;
+
+ /* Then release reset */
+ /* Must release reset before setting other regs */
+ *uart_enable = UART_EN_CE|UART_EN_E;
+
+ /* Activate fifos, reset tx and rx */
+ /* Set tx trigger level to 12 */
+ *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR|
+ UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12;
+
+ serial_setbrg();
+
+ return 0;
+}
+
+
+void serial_setbrg (void)
+{
+ volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK);
+ volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR);
+ volatile u32 *sys_powerctrl = (u32 *)SYS_POWERCTRL;
+ int sd;
+ int divisorx2;
+
+ /* sd is system clock divisor */
+ /* see section 10.4.5 in au1550 datasheet */
+ sd = (*sys_powerctrl & 0x03) + 2;
+
+ /* calulate 2x baudrate and round */
+ divisorx2 = ((CFG_HZ/(sd * 16 * CONFIG_BAUDRATE)));
+
+ if (divisorx2 & 0x01)
+ divisorx2 = divisorx2 + 1;
+
+ *uart_clk = divisorx2 / 2;
+
+ /* Set parity, stop bits and word length to 8N1 */
+ *uart_lcr = UART_LCR_WLEN8;
+}
+
+void serial_putc (const char c)
+{
+ volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
+ volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX);
+
+ if (c == '\n') serial_putc ('\r');
+
+ /* Wait for fifo to shift out some bytes */
+ while((*uart_lsr&UART_LSR_THRE)==0);
+
+ *uart_tx = (u32)c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s)
+ {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc (void)
+{
+ volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX);
+ char c;
+
+ while (!serial_tstc());
+
+ c = (*uart_rx&0xFF);
+ return c;
+}
+
+int serial_tstc (void)
+{
+ volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR);
+
+ if(*uart_lsr&UART_LSR_DR){
+ /* Data in rfifo */
+ return(1);
+ }
+ return 0;
+}
+#endif /* CONFIG_SERIAL_AU1X00 */
diff --git a/drivers/serial/serial_bf533.c b/drivers/serial/serial_bf533.c
new file mode 100644
index 0000000000..7b43ffd188
--- /dev/null
+++ b/drivers/serial/serial_bf533.c
@@ -0,0 +1,195 @@
+/*
+ * U-boot - serial.c Serial driver for BF533
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ *
+ * This file is based on
+ * bf533_serial.c: Serial driver for BlackFin BF533 DSP internal UART.
+ * Copyright (c) 2003 Bas Vermeulen <bas@buyways.nl>,
+ * BuyWays B.V. (www.buyways.nl)
+ *
+ * Based heavily on blkfinserial.c
+ * blkfinserial.c: Serial driver for BlackFin DSP internal USRTs.
+ * Copyright(c) 2003 Metrowerks <mwaddel@metrowerks.com>
+ * Copyright(c) 2001 Tony Z. Kou <tonyko@arcturusnetworks.com>
+ * Copyright(c) 2001-2002 Arcturus Networks Inc. <www.arcturusnetworks.com>
+ *
+ * Based on code from 68328 version serial driver imlpementation which was:
+ * Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
+ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
+ * Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
+ * Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+#include <asm/uaccess.h>
+#include "bf533_serial.h"
+
+DECLARE_GLOBAL_DATA_PTR;
+
+unsigned long pll_div_fact;
+
+void calc_baud(void)
+{
+ unsigned char i;
+ int temp;
+
+ for(i = 0; i < sizeof(baud_table)/sizeof(int); i++) {
+ temp = CONFIG_SCLK_HZ/(baud_table[i]*8);
+ if ( temp && 0x1 == 1 ) {
+ temp++;
+ }
+ temp = temp/2;
+ hw_baud_table[i].dl_high = (temp >> 8)& 0xFF;
+ hw_baud_table[i].dl_low = (temp) & 0xFF;
+ }
+}
+
+void serial_setbrg(void)
+{
+ int i;
+
+ calc_baud();
+
+ for (i = 0; i < sizeof(baud_table) / sizeof(int); i++) {
+ if (gd->baudrate == baud_table[i])
+ break;
+ }
+
+ /* Enable UART */
+ *pUART_GCTL |= UART_GCTL_UCEN;
+ asm("ssync;");
+
+ /* Set DLAB in LCR to Access DLL and DLH */
+ ACCESS_LATCH;
+ asm("ssync;");
+
+ *pUART_DLL = hw_baud_table[i].dl_low;
+ asm("ssync;");
+ *pUART_DLH = hw_baud_table[i].dl_high;
+ asm("ssync;");
+
+ /* Clear DLAB in LCR to Access THR RBR IER */
+ ACCESS_PORT_IER;
+ asm("ssync;");
+
+ /* Enable ERBFI and ELSI interrupts
+ * to poll SIC_ISR register*/
+ *pUART_IER = UART_IER_ELSI | UART_IER_ERBFI | UART_IER_ETBEI;
+ asm("ssync;");
+
+ /* Set LCR to Word Lengh 8-bit word select */
+ *pUART_LCR = UART_LCR_WLS8;
+ asm("ssync;");
+
+ return;
+}
+
+int serial_init(void)
+{
+ serial_setbrg();
+ return (0);
+}
+
+void serial_putc(const char c)
+{
+ if ((*pUART_LSR) & UART_LSR_TEMT)
+ {
+ if (c == '\n')
+ serial_putc('\r');
+
+ local_put_char(c);
+ }
+
+ while (!((*pUART_LSR) & UART_LSR_TEMT))
+ SYNC_ALL;
+
+ return;
+}
+
+int serial_tstc(void)
+{
+ if (*pUART_LSR & UART_LSR_DR)
+ return 1;
+ else
+ return 0;
+}
+
+int serial_getc(void)
+{
+ unsigned short uart_lsr_val, uart_rbr_val;
+ unsigned long isr_val;
+ int ret;
+
+ /* Poll for RX Interrupt */
+ while (!((isr_val = *(volatile unsigned long *)SIC_ISR) & IRQ_UART_RX_BIT));
+ asm("csync;");
+
+ uart_lsr_val = *pUART_LSR; /* Clear status bit */
+ uart_rbr_val = *pUART_RBR; /* getc() */
+
+ if (isr_val & IRQ_UART_ERROR_BIT) {
+ ret = -1;
+ }
+ else
+ {
+ ret = uart_rbr_val & 0xff;
+ }
+
+ return ret;
+}
+
+void serial_puts(const char *s)
+{
+ while (*s) {
+ serial_putc(*s++);
+ }
+}
+
+static void local_put_char(char ch)
+{
+ int flags = 0;
+ unsigned long isr_val;
+
+ save_and_cli(flags);
+
+ /* Poll for TX Interruput */
+ while (!((isr_val = *pSIC_ISR) & IRQ_UART_TX_BIT));
+ asm("csync;");
+
+ *pUART_THR = ch; /* putc() */
+
+ if (isr_val & IRQ_UART_ERROR_BIT) {
+ printf("?");
+ }
+
+ restore_flags(flags);
+
+ return ;
+}
diff --git a/drivers/serial/serial_bf533.h b/drivers/serial/serial_bf533.h
new file mode 100644
index 0000000000..d430e6cabd
--- /dev/null
+++ b/drivers/serial/serial_bf533.h
@@ -0,0 +1,78 @@
+/*
+ * U-boot - bf533_serial.h Serial Driver defines
+ *
+ * Copyright (c) 2005 blackfin.uclinux.org
+ *
+ * This file is based on
+ * bf533_serial.h: Definitions for the BlackFin BF533 DSP serial driver.
+ * Copyright (C) 2003 Bas Vermeulen <bas@buyways.nl>
+ * BuyWays B.V. (www.buyways.nl)
+ *
+ * Based heavily on:
+ * blkfinserial.h: Definitions for the BlackFin DSP serial driver.
+ *
+ * Copyright (C) 2001 Tony Z. Kou tonyko@arcturusnetworks.com
+ * Copyright (C) 2001 Arcturus Networks Inc. <www.arcturusnetworks.com>
+ *
+ * Based on code from 68328serial.c which was:
+ * Copyright (C) 1995 David S. Miller <davem@caip.rutgers.edu>
+ * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
+ * Copyright (C) 1998, 1999 D. Jeff Dionne <jeff@uclinux.org>
+ * Copyright (C) 1999 Vladimir Gurevich <vgurevic@cisco.com>
+ *
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _Bf533_SERIAL_H
+#define _Bf533_SERIAL_H
+
+#include <linux/config.h>
+#include <asm/blackfin.h>
+
+#define SYNC_ALL __asm__ __volatile__ ("ssync;\n")
+#define ACCESS_LATCH *pUART_LCR |= UART_LCR_DLAB;
+#define ACCESS_PORT_IER *pUART_LCR &= (~UART_LCR_DLAB);
+
+void serial_setbrg(void);
+static void local_put_char(char ch);
+void calc_baud(void);
+void serial_setbrg(void);
+int serial_init(void);
+void serial_putc(const char c);
+int serial_tstc(void);
+int serial_getc(void);
+void serial_puts(const char *s);
+static void local_put_char(char ch);
+
+extern int get_clock(void);
+int baud_table[5] = {9600, 19200, 38400, 57600, 115200};
+
+struct {
+ unsigned char dl_high;
+ unsigned char dl_low;
+} hw_baud_table[5];
+
+#ifdef CONFIG_STAMP
+extern unsigned long pll_div_fact;
+#endif
+
+#endif
diff --git a/drivers/serial/serial_clps7111.c b/drivers/serial/serial_clps7111.c
new file mode 100644
index 0000000000..054bab9811
--- /dev/null
+++ b/drivers/serial/serial_clps7111.c
@@ -0,0 +1,126 @@
+/*
+ * (C) Copyright 2002-2004
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+
+#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_ARMADILLO)
+
+#include <clps7111.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void serial_setbrg (void)
+{
+ unsigned int reg = 0;
+
+ switch (gd->baudrate) {
+ case 1200: reg = 191; break;
+ case 9600: reg = 23; break;
+ case 19200: reg = 11; break;
+ case 38400: reg = 5; break;
+ case 57600: reg = 3; break;
+ case 115200: reg = 1; break;
+ default: hang (); break;
+ }
+
+ /* init serial serial 1,2 */
+ IO_SYSCON1 = SYSCON1_UART1EN;
+ IO_SYSCON2 = SYSCON2_UART2EN;
+
+ reg |= UBRLCR_WRDLEN8;
+
+ IO_UBRLCR1 = reg;
+ IO_UBRLCR2 = reg;
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ int tmo;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+
+ tmo = get_timer (0) + 1 * CFG_HZ;
+ while (IO_SYSFLG1 & SYSFLG1_UTXFF)
+ if (get_timer (0) > tmo)
+ break;
+
+ IO_UARTDR1 = c;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+ return !(IO_SYSFLG1 & SYSFLG1_URXFE);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+ while (IO_SYSFLG1 & SYSFLG1_URXFE);
+
+ return IO_UARTDR1 & 0xff;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+#endif /* defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) */
diff --git a/drivers/serial/serial_ixp.c b/drivers/serial/serial_ixp.c
new file mode 100644
index 0000000000..2015958571
--- /dev/null
+++ b/drivers/serial/serial_ixp.c
@@ -0,0 +1,125 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/arch/ixp425.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void serial_setbrg (void)
+{
+ unsigned int quot = 0;
+ int uart = CFG_IXP425_CONSOLE;
+
+ if (gd->baudrate == 1200)
+ quot = 192;
+ else if (gd->baudrate == 9600)
+ quot = 96;
+ else if (gd->baudrate == 19200)
+ quot = 48;
+ else if (gd->baudrate == 38400)
+ quot = 24;
+ else if (gd->baudrate == 57600)
+ quot = 16;
+ else if (gd->baudrate == 115200)
+ quot = 8;
+ else
+ hang ();
+
+ IER(uart) = 0; /* Disable for now */
+ FCR(uart) = 0; /* No fifos enabled */
+
+ /* set baud rate */
+ LCR(uart) = LCR_WLS0 | LCR_WLS1 | LCR_DLAB;
+ DLL(uart) = quot & 0xff;
+ DLH(uart) = quot >> 8;
+ LCR(uart) = LCR_WLS0 | LCR_WLS1;
+
+ IER(uart) = IER_UUE;
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ /* wait for room in the tx FIFO on UART */
+ while ((LSR(CFG_IXP425_CONSOLE) & LSR_TEMT) == 0);
+
+ THR(CFG_IXP425_CONSOLE) = c;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+ return LSR(CFG_IXP425_CONSOLE) & LSR_DR;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+ while (!(LSR(CFG_IXP425_CONSOLE) & LSR_DR));
+
+ return (char) RBR(CFG_IXP425_CONSOLE) & 0xff;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
diff --git a/drivers/serial/serial_ks8695.c b/drivers/serial/serial_ks8695.c
new file mode 100644
index 0000000000..aacd1be630
--- /dev/null
+++ b/drivers/serial/serial_ks8695.c
@@ -0,0 +1,117 @@
+/*
+ * serial.c -- KS8695 serial driver
+ *
+ * (C) Copyright 2004, Greg Ungerer <greg.ungerer@opengear.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <asm/arch/platform.h>
+
+#ifndef CONFIG_SERIAL1
+#error "Bad: you didn't configure serial ..."
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Define the UART hardware register access structure.
+ */
+struct ks8695uart {
+ unsigned int RX; /* 0x00 - Receive data (r) */
+ unsigned int TX; /* 0x04 - Transmit data (w) */
+ unsigned int FCR; /* 0x08 - Fifo Control (r/w) */
+ unsigned int LCR; /* 0x0c - Line Control (r/w) */
+ unsigned int MCR; /* 0x10 - Modem Control (r/w) */
+ unsigned int LSR; /* 0x14 - Line Status (r/w) */
+ unsigned int MSR; /* 0x18 - Modem Status (r/w) */
+ unsigned int BD; /* 0x1c - Baud Rate (r/w) */
+ unsigned int SR; /* 0x20 - Status (r/w) */
+};
+
+#define KS8695_UART_ADDR ((void *) (KS8695_IO_BASE + KS8695_UART_RX_BUFFER))
+#define KS8695_UART_CLK 25000000
+
+
+/*
+ * Under some circumstances we want to be "quiet" and not issue any
+ * serial output - though we want u-boot to otherwise work and behave
+ * the same. By default be noisy.
+ */
+int serial_console = 1;
+
+
+void serial_setbrg(void)
+{
+ volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
+
+ /* Set to global baud rate and 8 data bits, no parity, 1 stop bit*/
+ uartp->BD = KS8695_UART_CLK / gd->baudrate;
+ uartp->LCR = KS8695_UART_LINEC_WLEN8;
+}
+
+int serial_init(void)
+{
+ serial_console = 1;
+ serial_setbrg();
+ return 0;
+}
+
+void serial_raw_putc(const char c)
+{
+ volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
+ int i;
+
+ for (i = 0; (i < 0x100000); i++) {
+ if (uartp->LSR & KS8695_UART_LINES_TXFE)
+ break;
+ }
+
+ uartp->TX = c;
+}
+
+void serial_putc(const char c)
+{
+ if (serial_console) {
+ serial_raw_putc(c);
+ if (c == '\n')
+ serial_raw_putc('\r');
+ }
+}
+
+int serial_tstc(void)
+{
+ volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
+ if (serial_console)
+ return ((uartp->LSR & KS8695_UART_LINES_RXFE) ? 1 : 0);
+ return 0;
+}
+
+void serial_puts(const char *s)
+{
+ char c;
+ while ((c = *s++) != 0)
+ serial_putc(c);
+}
+
+int serial_getc(void)
+{
+ volatile struct ks8695uart *uartp = KS8695_UART_ADDR;
+
+ while ((uartp->LSR & KS8695_UART_LINES_RXFE) == 0)
+ ;
+ return (uartp->RX);
+}
diff --git a/drivers/serial/serial_lh7a40x.c b/drivers/serial/serial_lh7a40x.c
new file mode 100644
index 0000000000..d727ccaa4f
--- /dev/null
+++ b/drivers/serial/serial_lh7a40x.c
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <lh7a40x.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONSOLE_UART1)
+# define UART_CONSOLE 1
+#elif defined(CONFIG_CONSOLE_UART2)
+# define UART_CONSOLE 2
+#elif defined(CONFIG_CONSOLE_UART3)
+# define UART_CONSOLE 3
+#else
+# error "No console configured ... "
+#endif
+
+void serial_setbrg (void)
+{
+ lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
+ int i;
+ unsigned int reg = 0;
+
+ /*
+ * userguide 15.1.2.4
+ *
+ * BAUDDIV is (UART_REF_FREQ/(16 X BAUD))-1
+ *
+ * UART_REF_FREQ = external system clock input / 2 (Hz)
+ * BAUD is desired baudrate (bits/s)
+ *
+ * NOTE: we add (divisor/2) to numerator to round for
+ * more precision
+ */
+ reg = (((get_PLLCLK()/2) + ((16*gd->baudrate)/2)) / (16 * gd->baudrate)) - 1;
+ uart->brcon = reg;
+
+ for (i = 0; i < 100; i++);
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
+
+ /* UART must be enabled before writing to any config registers */
+ uart->con |= (UART_EN);
+
+#ifdef CONFIG_CONSOLE_UART1
+ /* infrared disabled */
+ uart->con |= UART_SIRD;
+#endif
+ /* loopback disabled */
+ uart->con &= ~(UART_LBE);
+
+ /* modem lines and tx/rx polarities */
+ uart->con &= ~(UART_MXP | UART_TXP | UART_RXP);
+
+ /* FIFO enable, N81 */
+ uart->fcon = (UART_WLEN_8 | UART_FEN | UART_STP2_1);
+
+ /* set baudrate */
+ serial_setbrg ();
+
+ /* enable rx interrupt */
+ uart->inten |= UART_RI;
+
+ return (0);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+ lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
+
+ /* wait for character to arrive */
+ while (uart->status & UART_RXFE);
+
+ return(uart->data & 0xff);
+}
+
+#ifdef CONFIG_HWFLOW
+static int hwflow = 0; /* turned off by default */
+int hwflow_onoff(int on)
+{
+ switch(on) {
+ case 0:
+ default:
+ break; /* return current */
+ case 1:
+ hwflow = 1; /* turn on */
+ break;
+ case -1:
+ hwflow = 0; /* turn off */
+ break;
+ }
+ return hwflow;
+}
+#endif
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
+
+ /* wait for room in the tx FIFO */
+ while (!(uart->status & UART_TXFE));
+
+#ifdef CONFIG_HWFLOW
+ /* Wait for CTS up */
+ while(hwflow && !(uart->status & UART_CTS));
+#endif
+
+ uart->data = c;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int serial_tstc (void)
+{
+ lh7a40x_uart_t* uart = LH7A40X_UART_PTR(UART_CONSOLE);
+
+ return(!(uart->status & UART_RXFE));
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
diff --git a/drivers/serial/serial_mcf52x2.c b/drivers/serial/serial_mcf52x2.c
new file mode 100644
index 0000000000..8be09e34fe
--- /dev/null
+++ b/drivers/serial/serial_mcf52x2.c
@@ -0,0 +1,215 @@
+/*
+ * (C) Copyright 2000-2004
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <watchdog.h>
+
+#include <asm/mcfuart.h>
+
+#ifdef CONFIG_M5271
+#include <asm/m5271.h>
+#endif
+
+#ifdef CONFIG_M5272
+#include <asm/m5272.h>
+#endif
+
+#ifdef CONFIG_M5282
+#include <asm/m5282.h>
+#endif
+
+#ifdef CONFIG_M5249
+#include <asm/m5249.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_M5249) || defined(CONFIG_M5271)
+#define DoubleClock(a) ((double)(CFG_CLK/2) / 32.0 / (double)(a))
+#else
+#define DoubleClock(a) ((double)(CFG_CLK) / 32.0 / (double)(a))
+#endif
+
+void rs_serial_setbaudrate(int port,int baudrate)
+{
+#if defined(CONFIG_M5272) || defined(CONFIG_M5249) || defined(CONFIG_M5271)
+ volatile unsigned char *uartp;
+# ifndef CONFIG_M5271
+ double fraction;
+# endif
+ double clock;
+
+ if (port == 0)
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+ else
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
+
+ clock = DoubleClock(baudrate); /* Set baud above */
+
+ uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */
+ uartp[MCFUART_UBG2] = ((int)clock & 0xff); /* set lsb baud */
+
+# ifndef CONFIG_M5271
+ fraction = ((clock - (int)clock) * 16.0) + 0.5;
+ uartp[MCFUART_UFPD] = ((int)fraction & 0xf); /* set baud fraction adjust */
+# endif
+#endif
+
+#if defined(CONFIG_M5282)
+ volatile unsigned char *uartp;
+ long clock;
+
+ switch (port) {
+ case 1:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
+ break;
+ case 2:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE3);
+ break;
+ default:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+ }
+
+ clock = (long) CFG_CLK / ((long) 32 * baudrate); /* Set baud above */
+
+ uartp[MCFUART_UBG1] = (((int)clock >> 8) & 0xff); /* set msb baud */
+ uartp[MCFUART_UBG2] = ((int) clock & 0xff); /* set lsb baud */
+
+#endif
+};
+
+void rs_serial_init (int port, int baudrate)
+{
+ volatile unsigned char *uartp;
+
+ /*
+ * Reset UART, get it into known state...
+ */
+ switch (port) {
+ case 1:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE2);
+ break;
+#if defined(CONFIG_M5282)
+ case 2:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE3);
+ break;
+#endif
+ default:
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+ }
+
+ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETTX; /* reset TX */
+ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETRX; /* reset RX */
+
+ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETMRPTR; /* reset MR pointer */
+ uartp[MCFUART_UCR] = MCFUART_UCR_CMDRESETERR; /* reset Error pointer */
+
+ /*
+ * Set port for CONSOLE_BAUD_RATE, 8 data bits, 1 stop bit, no parity.
+ */
+ uartp[MCFUART_UMR] = MCFUART_MR1_PARITYNONE | MCFUART_MR1_CS8;
+ uartp[MCFUART_UMR] = MCFUART_MR2_STOP1;
+
+ /* Mask UART interrupts */
+ uartp[MCFUART_UIMR] = 0;
+
+ /* Set clock Select Register: Tx/Rx clock is timer */
+ uartp[MCFUART_UCSR] = MCFUART_UCSR_RXCLKTIMER | MCFUART_UCSR_TXCLKTIMER;
+
+ rs_serial_setbaudrate (port, baudrate);
+
+ /* Enable Tx/Rx */
+ uartp[MCFUART_UCR] = MCFUART_UCR_RXENABLE | MCFUART_UCR_TXENABLE;
+
+ return;
+}
+
+/****************************************************************************/
+/*
+ * Output a single character, using UART polled mode.
+ * This is used for console output.
+ */
+
+void rs_put_char(char ch)
+{
+ volatile unsigned char *uartp;
+ int i;
+
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+
+ for (i = 0; (i < 0x10000); i++) {
+ if (uartp[MCFUART_USR] & MCFUART_USR_TXREADY)
+ break;
+ }
+ uartp[MCFUART_UTB] = ch;
+ return;
+}
+
+int rs_is_char(void)
+{
+ volatile unsigned char *uartp;
+
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+ return((uartp[MCFUART_USR] & MCFUART_USR_RXREADY) ? 1 : 0);
+}
+
+int rs_get_char(void)
+{
+ volatile unsigned char *uartp;
+
+ uartp = (volatile unsigned char *) (CFG_MBAR + MCFUART_BASE1);
+ return(uartp[MCFUART_URB]);
+}
+
+void serial_setbrg(void) {
+ rs_serial_setbaudrate(0,gd->bd->bi_baudrate);
+}
+
+int serial_init(void) {
+ rs_serial_init(0,gd->baudrate);
+ return 0;
+}
+
+
+void serial_putc(const char c) {
+ if (c == '\n')
+ serial_putc ('\r');
+ rs_put_char(c);
+}
+
+void serial_puts (const char *s) {
+ while (*s)
+ serial_putc(*s++);
+}
+
+int serial_getc(void) {
+ while(!rs_is_char())
+ WATCHDOG_RESET();
+
+ return rs_get_char();
+}
+
+int serial_tstc() {
+ return rs_is_char();
+}
diff --git a/drivers/serial/serial_mpc5xx.c b/drivers/serial/serial_mpc5xx.c
new file mode 100644
index 0000000000..ac5556f05c
--- /dev/null
+++ b/drivers/serial/serial_mpc5xx.c
@@ -0,0 +1,170 @@
+/*
+ * (C) Copyright 2003
+ * Martin Winistoerfer, martinwinistoerfer@gmx.ch.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation,
+ */
+
+/*
+ * File: serial.c
+ *
+ * Discription: Serial interface driver for SCI1 and SCI2.
+ * Since this code will be called from ROM use
+ * only non-static local variables.
+ *
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <mpc5xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*
+ * Local function prototypes
+ */
+
+static int ready_to_send(void);
+
+/*
+ * Minimal global serial functions needed to use one of the SCI modules.
+ */
+
+int serial_init (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ serial_setbrg();
+
+#if defined(CONFIG_5xx_CONS_SCI1)
+ /* 10-Bit, 1 start bit, 8 data bit, no parity, 1 stop bit */
+ immr->im_qsmcm.qsmcm_scc1r1 = SCI_M_10;
+ immr->im_qsmcm.qsmcm_scc1r1 = SCI_TE | SCI_RE;
+#else
+ immr->im_qsmcm.qsmcm_scc2r1 = SCI_M_10;
+ immr->im_qsmcm.qsmcm_scc2r1 = SCI_TE | SCI_RE;
+#endif
+ return 0;
+}
+
+void serial_putc(const char c)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ /* Test for completition */
+ if(ready_to_send()) {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_sc1dr = (short)c;
+#else
+ immr->im_qsmcm.qsmcm_sc2dr = (short)c;
+#endif
+ if(c == '\n') {
+ if(ready_to_send());
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_sc1dr = (short)'\r';
+#else
+ immr->im_qsmcm.qsmcm_sc2dr = (short)'\r';
+#endif
+ }
+ }
+}
+
+int serial_getc(void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile short status;
+ unsigned char tmp;
+
+ /* New data ? */
+ do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ reset_5xx_watchdog (immr);
+#endif
+ } while ((status & SCI_RDRF) == 0);
+
+ /* Read data */
+#if defined(CONFIG_5xx_CONS_SCI1)
+ tmp = (unsigned char)(immr->im_qsmcm.qsmcm_sc1dr & SCI_SCXDR_MK);
+#else
+ tmp = (unsigned char)( immr->im_qsmcm.qsmcm_sc2dr & SCI_SCXDR_MK);
+#endif
+ return tmp;
+}
+
+int serial_tstc()
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ short status;
+
+ /* New data character ? */
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+ return (status & SCI_RDRF);
+}
+
+void serial_setbrg (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ short scxbr;
+
+ /* Set baudrate */
+ scxbr = (gd->cpu_clk / (32 * gd->baudrate));
+#if defined(CONFIG_5xx_CONS_SCI1)
+ immr->im_qsmcm.qsmcm_scc1r0 = (scxbr & SCI_SCXBR_MK);
+#else
+ immr->im_qsmcm.qsmcm_scc2r0 = (scxbr & SCI_SCXBR_MK);
+#endif
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc(*s);
+ ++s;
+ }
+}
+
+int ready_to_send(void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile short status;
+
+ do {
+#if defined(CONFIG_5xx_CONS_SCI1)
+ status = immr->im_qsmcm.qsmcm_sc1sr;
+#else
+ status = immr->im_qsmcm.qsmcm_sc2sr;
+#endif
+
+#if defined(CONFIG_WATCHDOG)
+ reset_5xx_watchdog (immr);
+#endif
+ } while ((status & SCI_TDRE) == 0);
+ return 1;
+
+}
diff --git a/drivers/serial/serial_mpc8260_scc.c b/drivers/serial/serial_mpc8260_scc.c
new file mode 100644
index 0000000000..3a6eaf0a67
--- /dev/null
+++ b/drivers/serial/serial_mpc8260_scc.c
@@ -0,0 +1,498 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
+
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
+
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
+
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
+
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+int serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(im->im_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpmux.cmx_scr = (im->im_cpmux.cmx_scr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->scc_gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8260_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int
+serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif /* CONFIG_CONS_ON_SCC */
+
+#if defined(CONFIG_KGDB_ON_SCC)
+
+#if defined(CONFIG_CONS_ON_SCC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same scc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SCC1 */
+
+#define KGDB_SCC_INDEX 0
+#define KGDB_PROFF_SCC PROFF_SCC1
+#define KGDB_CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SCC2 */
+
+#define KGDB_SCC_INDEX 1
+#define KGDB_PROFF_SCC PROFF_SCC2
+#define KGDB_CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 3 /* KGDB Port on SCC3 */
+
+#define KGDB_SCC_INDEX 2
+#define KGDB_PROFF_SCC PROFF_SCC3
+#define KGDB_CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_KGDB_INDEX == 4 /* KGDB Port on SCC4 */
+
+#define KGDB_SCC_INDEX 3
+#define KGDB_PROFF_SCC PROFF_SCC4
+#define KGDB_CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define KGDB_CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define KGDB_CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define KGDB_CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "kgdb serial port not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+ char *s, *e;
+
+ if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+ ulong rate = simple_strtoul(s, &e, 10);
+ if (e > s && *e == '\0')
+ speed = rate;
+ }
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(im->im_scc[KGDB_SCC_INDEX]);
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpmux.cmx_scr = \
+ (im->im_cpmux.cmx_scr & ~KGDB_CMXSCR_MASK) | KGDB_CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+#if defined(CONFIG_KGDB_USE_EXTC)
+ m8260_cpm_extcbrg(KGDB_SCC_INDEX, speed,
+ CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(KGDB_SCC_INDEX, speed);
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->scc_gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->scc_gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->scc_psmr = SCU_PSMR_FLC | SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SCC_PAGE, KGDB_CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->scc_gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ printf("SCC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ putDebugChar ('\r');
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+ tbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+ while (*s) {
+ putDebugChar (*s++);
+ }
+}
+
+int
+getDebugChar(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&im->im_dprambase[KGDB_PROFF_SCC];
+ rbdf = (cbd_t *)&im->im_dprambase[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+ return;
+}
+
+#endif /* CONFIG_KGDB_ON_SCC */
diff --git a/drivers/serial/serial_mpc8260_smc.c b/drivers/serial/serial_mpc8260_smc.c
new file mode 100644
index 0000000000..f3dffeb119
--- /dev/null
+++ b/drivers/serial/serial_mpc8260_smc.c
@@ -0,0 +1,462 @@
+/*
+ * (C) Copyright 2000, 2001, 2002
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
+ * changes based on the file arch/ppc/mbxboot/m8260_tty.c from the
+ * Linux/PPC sources (m8260_tty.c had no copyright info in it).
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <mpc8260.h>
+#include <asm/cpm_8260.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CONS_ON_SMC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SMC1 */
+
+#define SMC_INDEX 0
+#define PROFF_SMC_BASE PROFF_SMC1_BASE
+#define PROFF_SMC PROFF_SMC1
+#define CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
+#define CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
+#define CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SMC2 */
+
+#define SMC_INDEX 1
+#define PROFF_SMC_BASE PROFF_SMC2_BASE
+#define PROFF_SMC PROFF_SMC2
+#define CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
+#define CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
+#define CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+/* map rs_table index to baud rate generator index */
+static unsigned char brg_map[] = {
+ 6, /* BRG7 for SMC1 */
+ 7, /* BRG8 for SMC2 */
+ 0, /* BRG1 for SCC1 */
+ 1, /* BRG1 for SCC2 */
+ 2, /* BRG1 for SCC3 */
+ 3, /* BRG1 for SCC4 */
+};
+
+int serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr;
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(im->im_smc[SMC_INDEX]);
+ *(ushort *)(&im->im_dprambase[PROFF_SMC_BASE]) = PROFF_SMC;
+ up = (smc_uart_t *)&im->im_dprambase[PROFF_SMC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* put the SMC channel into NMSI (non multiplexd serial interface)
+ * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+ */
+ im->im_cpmux.cmx_smr = (im->im_cpmux.cmx_smr&~CMXSMR_MASK)|CMXSMR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_SMC_PAGE, CPM_CR_SMC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8260_cpm_extcbrg(brg_map[SMC_INDEX], gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(brg_map[SMC_INDEX], gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+ tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int
+serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ unsigned char c;
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+ rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+ up = (smc_uart_t *)&(im->im_dprambase[PROFF_SMC]);
+
+ rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
+#endif /* CONFIG_CONS_ON_SMC */
+
+#if defined(CONFIG_KGDB_ON_SMC)
+
+#if defined(CONFIG_CONS_ON_SMC) && CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX
+#error Whoops! serial console and kgdb are on the same smc serial port
+#endif
+
+#if CONFIG_KGDB_INDEX == 1 /* KGDB Port on SMC1 */
+
+#define KGDB_SMC_INDEX 0
+#define KGDB_PROFF_SMC_BASE PROFF_SMC1_BASE
+#define KGDB_PROFF_SMC PROFF_SMC1
+#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC1_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC1_SBLOCK
+#define KGDB_CMXSMR_MASK (CMXSMR_SMC1|CMXSMR_SMC1CS_MSK)
+#define KGDB_CMXSMR_VALUE CMXSMR_SMC1CS_BRG7
+
+#elif CONFIG_KGDB_INDEX == 2 /* KGDB Port on SMC2 */
+
+#define KGDB_SMC_INDEX 1
+#define KGDB_PROFF_SMC_BASE PROFF_SMC2_BASE
+#define KGDB_PROFF_SMC PROFF_SMC2
+#define KGDB_CPM_CR_SMC_PAGE CPM_CR_SMC2_PAGE
+#define KGDB_CPM_CR_SMC_SBLOCK CPM_CR_SMC2_SBLOCK
+#define KGDB_CMXSMR_MASK (CMXSMR_SMC2|CMXSMR_SMC2CS_MSK)
+#define KGDB_CMXSMR_VALUE CMXSMR_SMC2CS_BRG8
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+void
+kgdb_serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8260_t *cp = &(im->im_cpm);
+ uint dpaddr, speed = CONFIG_KGDB_BAUDRATE;
+ char *s, *e;
+
+ if ((s = getenv("kgdbrate")) != NULL && *s != '\0') {
+ ulong rate = simple_strtoul(s, &e, 10);
+ if (e > s && *e == '\0')
+ speed = rate;
+ }
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(im->im_smc[KGDB_SMC_INDEX]);
+ *(ushort *)(&im->im_dprambase[KGDB_PROFF_SMC_BASE]) = KGDB_PROFF_SMC;
+ up = (smc_uart_t *)&im->im_dprambase[KGDB_PROFF_SMC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* NOTE: I/O port pins are set up via the iop_conf_tab[] table */
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8260_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&im->im_dprambase[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = CPMFCR_EB;
+ up->smc_tfcr = CPMFCR_EB;
+ up->smc_brklen = 0;
+ up->smc_brkec = 0;
+ up->smc_brkcr = 0;
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+ /* put the SMC channel into NMSI (non multiplexd serial interface)
+ * mode and wire either BRG7 to SMC1 or BRG8 to SMC2 (15-17).
+ */
+ im->im_cpmux.cmx_smr =
+ (im->im_cpmux.cmx_smr & ~KGDB_CMXSMR_MASK) | KGDB_CMXSMR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+#if defined(CONFIG_KGDB_USE_EXTC)
+ m8260_cpm_extcbrg(brg_map[KGDB_SMC_INDEX], speed,
+ CONFIG_KGDB_EXTC_RATE, CONFIG_KGDB_EXTC_PINSEL);
+#else
+ m8260_cpm_setbrg(brg_map[KGDB_SMC_INDEX], speed);
+#endif
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(KGDB_CPM_CR_SMC_PAGE, KGDB_CPM_CR_SMC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ printf("SMC%d at %dbps ", CONFIG_KGDB_INDEX, speed);
+}
+
+void
+putDebugChar(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+
+ if (c == '\n')
+ putDebugChar ('\r');
+
+ up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+ tbdf = (cbd_t *)&im->im_dprambase[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+ buf = (char *)tbdf->cbd_bufaddr;
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+putDebugStr (const char *s)
+{
+ while (*s) {
+ putDebugChar (*s++);
+ }
+}
+
+int
+getDebugChar(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ unsigned char c;
+
+ up = (smc_uart_t *)&(im->im_dprambase[KGDB_PROFF_SMC]);
+
+ rbdf = (cbd_t *)&im->im_dprambase[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+void
+kgdb_interruptible(int yes)
+{
+ return;
+}
+
+#endif /* CONFIG_KGDB_ON_SMC */
diff --git a/drivers/serial/serial_mpc85xx_scc.c b/drivers/serial/serial_mpc85xx_scc.c
new file mode 100644
index 0000000000..4e925f8bea
--- /dev/null
+++ b/drivers/serial/serial_mpc85xx_scc.c
@@ -0,0 +1,274 @@
+/*
+ * (C) Copyright 2003 Motorola Inc.
+ * Xianghua Xiao (X.Xiao@motorola.com)
+ * Modified based on 8260 for 8560.
+ *
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00.
+ */
+
+/*
+ * Minimal serial functions needed to use one of the SCC ports
+ * as serial console interface.
+ */
+
+#include <common.h>
+#include <asm/cpm_85xx.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if defined(CONFIG_CPM2)
+#if defined(CONFIG_CONS_ON_SCC)
+
+#if CONFIG_CONS_INDEX == 1 /* Console on SCC1 */
+
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CMXSCR_MASK (CMXSCR_GR1|CMXSCR_SC1|\
+ CMXSCR_RS1CS_MSK|CMXSCR_TS1CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS1CS_BRG1|CMXSCR_TS1CS_BRG1)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC1_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC1_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 2 /* Console on SCC2 */
+
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CMXSCR_MASK (CMXSCR_GR2|CMXSCR_SC2|\
+ CMXSCR_RS2CS_MSK|CMXSCR_TS2CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS2CS_BRG2|CMXSCR_TS2CS_BRG2)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC2_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC2_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 3 /* Console on SCC3 */
+
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CMXSCR_MASK (CMXSCR_GR3|CMXSCR_SC3|\
+ CMXSCR_RS3CS_MSK|CMXSCR_TS3CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS3CS_BRG3|CMXSCR_TS3CS_BRG3)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC3_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC3_SBLOCK
+
+#elif CONFIG_CONS_INDEX == 4 /* Console on SCC4 */
+
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CMXSCR_MASK (CMXSCR_GR4|CMXSCR_SC4|\
+ CMXSCR_RS4CS_MSK|CMXSCR_TS4CS_MSK)
+#define CMXSCR_VALUE (CMXSCR_RS4CS_BRG4|CMXSCR_TS4CS_BRG4)
+#define CPM_CR_SCC_PAGE CPM_CR_SCC4_PAGE
+#define CPM_CR_SCC_SBLOCK CPM_CR_SCC4_SBLOCK
+
+#else
+
+#error "console not correctly defined"
+
+#endif
+
+int serial_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile ccsr_cpm_scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile ccsr_cpm_cp_t *cp = &(im->im_cpm.im_cpm_cp);
+ uint dpaddr;
+
+ /* initialize pointers to SCC */
+
+ sp = (ccsr_cpm_scc_t *) &(im->im_cpm.im_cpm_scc[SCC_INDEX]);
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+
+ /* Disable transmitter/receiver.
+ */
+ sp->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ /* put the SCC channel into NMSI (non multiplexd serial interface)
+ * mode and wire the selected SCC Tx and Rx clocks to BRGx (15-15).
+ */
+ im->im_cpm.im_cpm_mux.cmxscr = \
+ (im->im_cpm.im_cpm_mux.cmxscr&~CMXSCR_MASK)|CMXSCR_VALUE;
+
+ /* Set up the baud rate generator.
+ */
+ serial_setbrg ();
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ dpaddr = m8560_cpm_dpalloc((2 * sizeof (cbd_t)) + 2, 16);
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[dpaddr]);
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = BD_SC_WRAP;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+ up->scc_genscc.scc_rfcr = CPMFCR_EB;
+ up->scc_genscc.scc_tfcr = CPMFCR_EB;
+ up->scc_genscc.scc_mrblr = 1;
+ up->scc_maxidl = 0;
+ up->scc_brkcr = 1;
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = up->scc_char2 = up->scc_char3 = up->scc_char4 = 0x8000;
+ up->scc_char5 = up->scc_char6 = up->scc_char7 = up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->sccm = 0;
+ sp->scce = 0xffff;
+
+ /* Set 8 bit FIFO, 16 bit oversampling and UART mode.
+ */
+ sp->gsmrh = SCC_GSMRH_RFW; /* 8 bit FIFO */
+ sp->gsmrl = \
+ SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16 | SCC_GSMRL_MODE_UART;
+
+ /* Set CTS no flow control, 1 stop bit, 8 bit character length,
+ * normal async UART mode, no parity
+ */
+ sp->psmr = SCU_PSMR_CL;
+
+ /* execute the "Init Rx and Tx params" CP command.
+ */
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cpcr = mk_cr_cmd(CPM_CR_SCC_PAGE, CPM_CR_SCC_SBLOCK,
+ 0, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->gsmrl |= SCC_GSMRL_ENR | SCC_GSMRL_ENT;
+
+ return (0);
+}
+
+void
+serial_setbrg (void)
+{
+#if defined(CONFIG_CONS_USE_EXTC)
+ m8560_cpm_extcbrg(SCC_INDEX, gd->baudrate,
+ CONFIG_CONS_EXTC_RATE, CONFIG_CONS_EXTC_PINSEL);
+#else
+ m8560_cpm_setbrg(SCC_INDEX, gd->baudrate);
+#endif
+}
+
+void
+serial_putc(const char c)
+{
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf;
+ volatile immap_t *im;
+
+ if (c == '\n')
+ serial_putc ('\r');
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ tbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_tbase]);
+
+ /* Wait for last character to go.
+ */
+ while (tbdf->cbd_sc & BD_SC_READY)
+ ;
+
+ /* Load the character into the transmit buffer.
+ */
+ *(volatile char *)tbdf->cbd_bufaddr = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int
+serial_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+ unsigned char c;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
+
+ /* Wait for character to show up.
+ */
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ ;
+
+ /* Grab the char and clear the buffer again.
+ */
+ c = *(volatile unsigned char *)rbdf->cbd_bufaddr;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return (c);
+}
+
+int
+serial_tstc()
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im;
+
+ im = (immap_t *)CFG_IMMR;
+ up = (scc_uart_t *)&(im->im_cpm.im_dprambase[PROFF_SCC]);
+ rbdf = (cbd_t *)&(im->im_cpm.im_dprambase[up->scc_genscc.scc_rbase]);
+
+ return ((rbdf->cbd_sc & BD_SC_EMPTY) == 0);
+}
+
+#endif /* CONFIG_CONS_ON_SCC */
+
+#endif /* CONFIG_CPM2 */
diff --git a/drivers/serial/serial_mpc8xx.c b/drivers/serial/serial_mpc8xx.c
new file mode 100644
index 0000000000..af5f4cf201
--- /dev/null
+++ b/drivers/serial/serial_mpc8xx.c
@@ -0,0 +1,704 @@
+/*
+ * (C) Copyright 2000
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <commproc.h>
+#include <command.h>
+#include <serial.h>
+#include <watchdog.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_8xx_CONS_NONE) /* No Console at all */
+
+#if defined(CONFIG_8xx_CONS_SMC1) /* Console on SMC1 */
+#define SMC_INDEX 0
+#define PROFF_SMC PROFF_SMC1
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC1
+
+#elif defined(CONFIG_8xx_CONS_SMC2) /* Console on SMC2 */
+#define SMC_INDEX 1
+#define PROFF_SMC PROFF_SMC2
+#define CPM_CR_CH_SMC CPM_CR_CH_SMC2
+
+#endif /* CONFIG_8xx_CONS_SMCx */
+
+#if defined(CONFIG_8xx_CONS_SCC1) /* Console on SCC1 */
+#define SCC_INDEX 0
+#define PROFF_SCC PROFF_SCC1
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC1
+
+#elif defined(CONFIG_8xx_CONS_SCC2) /* Console on SCC2 */
+#define SCC_INDEX 1
+#define PROFF_SCC PROFF_SCC2
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC2
+
+#elif defined(CONFIG_8xx_CONS_SCC3) /* Console on SCC3 */
+#define SCC_INDEX 2
+#define PROFF_SCC PROFF_SCC3
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC3
+
+#elif defined(CONFIG_8xx_CONS_SCC4) /* Console on SCC4 */
+#define SCC_INDEX 3
+#define PROFF_SCC PROFF_SCC4
+#define CPM_CR_CH_SCC CPM_CR_CH_SCC4
+
+#endif /* CONFIG_8xx_CONS_SCCx */
+
+static void serial_setdivisor(volatile cpm8xx_t *cp)
+{
+ int divisor=(gd->cpu_clk + 8*gd->baudrate)/16/gd->baudrate;
+
+ if(divisor/16>0x1000) {
+ /* bad divisor, assume 50Mhz clock and 9600 baud */
+ divisor=(50*1000*1000 + 8*9600)/16/9600;
+ }
+
+#ifdef CFG_BRGCLK_PRESCALE
+ divisor /= CFG_BRGCLK_PRESCALE;
+#endif
+
+ if(divisor<=0x1000) {
+ cp->cp_brgc1=((divisor-1)<<1) | CPM_BRG_EN;
+ } else {
+ cp->cp_brgc1=((divisor/16-1)<<1) | CPM_BRG_EN | CPM_BRG_DIV16;
+ }
+}
+
+#if (defined (CONFIG_8xx_CONS_SMC1) || defined (CONFIG_8xx_CONS_SMC2))
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+static void smc_setbrg (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SMCx
+ */
+
+ cp->cp_simode = 0x00000000;
+
+ serial_setdivisor(cp);
+}
+
+static int smc_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile smc_t *sp;
+ volatile smc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+#if (!defined(CONFIG_8xx_CONS_SMC1)) && (defined(CONFIG_MPC823) || defined(CONFIG_MPC850))
+ volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+ uint dpaddr;
+
+ /* initialize pointers to SMC */
+
+ sp = (smc_t *) &(cp->cp_smc[SMC_INDEX]);
+ up = (smc_uart_t *) &cp->cp_dparam[PROFF_SMC];
+
+ /* Disable transmitter/receiver.
+ */
+ sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+
+ /* Enable SDMA.
+ */
+ im->im_siu_conf.sc_sdcr = 1;
+
+ /* clear error conditions */
+#ifdef CFG_SDSR
+ im->im_sdma.sdma_sdsr = CFG_SDSR;
+#else
+ im->im_sdma.sdma_sdsr = 0x83;
+#endif
+
+ /* clear SDMA interrupt mask */
+#ifdef CFG_SDMR
+ im->im_sdma.sdma_sdmr = CFG_SDMR;
+#else
+ im->im_sdma.sdma_sdmr = 0x00;
+#endif
+
+#if defined(CONFIG_8xx_CONS_SMC1)
+ /* Use Port B for SMC1 instead of other functions.
+ */
+ cp->cp_pbpar |= 0x000000c0;
+ cp->cp_pbdir &= ~0x000000c0;
+ cp->cp_pbodr &= ~0x000000c0;
+#else /* CONFIG_8xx_CONS_SMC2 */
+# if defined(CONFIG_MPC823) || defined(CONFIG_MPC850)
+ /* Use Port A for SMC2 instead of other functions.
+ */
+ ip->iop_papar |= 0x00c0;
+ ip->iop_padir &= ~0x00c0;
+ ip->iop_paodr &= ~0x00c0;
+# else /* must be a 860 then */
+ /* Use Port B for SMC2 instead of other functions.
+ */
+ cp->cp_pbpar |= 0x00000c00;
+ cp->cp_pbdir &= ~0x00000c00;
+ cp->cp_pbodr &= ~0x00000c00;
+# endif
+#endif
+
+#if defined(CONFIG_FADS) || defined(CONFIG_ADS)
+ /* Enable RS232 */
+#if defined(CONFIG_8xx_CONS_SMC1)
+ *((uint *) BCSR1) &= ~BCSR1_RS232EN_1;
+#else
+ *((uint *) BCSR1) &= ~BCSR1_RS232EN_2;
+#endif
+#endif /* CONFIG_FADS */
+
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+ /* Enable Monitor Port Transceiver */
+ *((uchar *) BCSR0) |= BCSR0_ENMONXCVR ;
+#endif /* CONFIG_RPXLITE */
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+
+#ifdef CFG_ALLOC_DPRAM
+ dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
+#else
+ dpaddr = CPM_SERIAL_BASE ;
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ * For now, this address seems OK, but it may have to
+ * change with newer versions of the firmware.
+ * damm: allocating space after the two buffers for rx/tx data
+ */
+
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->smc_rbase = dpaddr;
+ up->smc_tbase = dpaddr+sizeof(cbd_t);
+ up->smc_rfcr = SMC_EB;
+ up->smc_tfcr = SMC_EB;
+
+#if defined(CONFIG_MBX)
+ board_serial_init();
+#endif /* CONFIG_MBX */
+
+ /* Set UART mode, 8 bit, no parity, one stop.
+ * Enable receive and transmit.
+ */
+ sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->smc_smcm = 0;
+ sp->smc_smce = 0xff;
+
+#ifdef CFG_SPC1920_SMC1_CLK4 /* clock source is PLD */
+ *((volatile uchar *) CFG_SPC1920_PLD_BASE+6) = 0xff;
+#else
+ /* Set up the baud rate generator */
+ smc_setbrg ();
+#endif
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Single character receive.
+ */
+ up->smc_mrblr = 1;
+ up->smc_maxidl = 0;
+
+ /* Initialize Tx/Rx parameters.
+ */
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SMC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
+
+ return (0);
+}
+
+static void
+smc_putc(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+ if (c == '\n')
+ smc_putc ('\r');
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
+
+ /* Wait for last character to go.
+ */
+
+ buf = (char *)tbdf->cbd_bufaddr;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
+
+ while (tbdf->cbd_sc & BD_SC_READY) {
+ WATCHDOG_RESET ();
+ __asm__("eieio");
+ }
+}
+
+static void
+smc_puts (const char *s)
+{
+ while (*s) {
+ smc_putc (*s++);
+ }
+}
+
+static int
+smc_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ unsigned char c;
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ WATCHDOG_RESET ();
+
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+static int
+smc_tstc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile smc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+ up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_SMC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
+struct serial_device serial_smc_device =
+{
+ "serial_smc",
+ "SMC",
+ smc_init,
+ smc_setbrg,
+ smc_getc,
+ smc_tstc,
+ smc_putc,
+ smc_puts,
+};
+
+#endif /* CONFIG_8xx_CONS_SMC1 || CONFIG_8xx_CONS_SMC2 */
+
+#if defined(CONFIG_8xx_CONS_SCC1) || defined(CONFIG_8xx_CONS_SCC2) || \
+ defined(CONFIG_8xx_CONS_SCC3) || defined(CONFIG_8xx_CONS_SCC4)
+
+static void
+scc_setbrg (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+
+ /* Set up the baud rate generator.
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SCCx
+ */
+
+ cp->cp_sicr &= ~(0x000000FF << (8 * SCC_INDEX));
+
+ serial_setdivisor(cp);
+}
+
+static int scc_init (void)
+{
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile scc_t *sp;
+ volatile scc_uart_t *up;
+ volatile cbd_t *tbdf, *rbdf;
+ volatile cpm8xx_t *cp = &(im->im_cpm);
+ uint dpaddr;
+#if (SCC_INDEX != 2) || !defined(CONFIG_MPC850)
+ volatile iop8xx_t *ip = (iop8xx_t *)&(im->im_ioport);
+#endif
+
+ /* initialize pointers to SCC */
+
+ sp = (scc_t *) &(cp->cp_scc[SCC_INDEX]);
+ up = (scc_uart_t *) &cp->cp_dparam[PROFF_SCC];
+
+#if defined(CONFIG_LWMON) && defined(CONFIG_8xx_CONS_SCC2)
+ { /* Disable Ethernet, enable Serial */
+ uchar c;
+
+ c = pic_read (0x61);
+ c &= ~0x40; /* enable COM3 */
+ c |= 0x80; /* disable Ethernet */
+ pic_write (0x61, c);
+
+ /* enable RTS2 */
+ cp->cp_pbpar |= 0x2000;
+ cp->cp_pbdat |= 0x2000;
+ cp->cp_pbdir |= 0x2000;
+ }
+#endif /* CONFIG_LWMON */
+
+ /* Disable transmitter/receiver.
+ */
+ sp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+#if (SCC_INDEX == 2) && defined(CONFIG_MPC850)
+ /*
+ * The MPC850 has SCC3 on Port B
+ */
+ cp->cp_pbpar |= 0x06;
+ cp->cp_pbdir &= ~0x06;
+ cp->cp_pbodr &= ~0x06;
+
+#elif (SCC_INDEX < 2) || !defined(CONFIG_IP860)
+ /*
+ * Standard configuration for SCC's is on Part A
+ */
+ ip->iop_papar |= ((3 << (2 * SCC_INDEX)));
+ ip->iop_padir &= ~((3 << (2 * SCC_INDEX)));
+ ip->iop_paodr &= ~((3 << (2 * SCC_INDEX)));
+#else
+ /*
+ * The IP860 has SCC3 and SCC4 on Port D
+ */
+ ip->iop_pdpar |= ((3 << (2 * SCC_INDEX)));
+#endif
+
+ /* Allocate space for two buffer descriptors in the DP ram.
+ */
+
+#ifdef CFG_ALLOC_DPRAM
+ dpaddr = dpram_alloc_align (sizeof(cbd_t)*2 + 2, 8) ;
+#else
+ dpaddr = CPM_SERIAL2_BASE ;
+#endif
+
+ /* Enable SDMA.
+ */
+ im->im_siu_conf.sc_sdcr = 0x0001;
+
+ /* Set the physical address of the host memory buffers in
+ * the buffer descriptors.
+ */
+
+ rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
+ rbdf->cbd_bufaddr = (uint) (rbdf+2);
+ rbdf->cbd_sc = 0;
+ tbdf = rbdf + 1;
+ tbdf->cbd_bufaddr = ((uint) (rbdf+2)) + 1;
+ tbdf->cbd_sc = 0;
+
+ /* Set up the baud rate generator.
+ */
+ scc_setbrg ();
+
+ /* Set up the uart parameters in the parameter ram.
+ */
+ up->scc_genscc.scc_rbase = dpaddr;
+ up->scc_genscc.scc_tbase = dpaddr+sizeof(cbd_t);
+
+ /* Initialize Tx/Rx parameters.
+ */
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SCC, CPM_CR_INIT_TRX) | CPM_CR_FLG;
+
+ while (cp->cp_cpcr & CPM_CR_FLG) /* wait if cp is busy */
+ ;
+
+ up->scc_genscc.scc_rfcr = SCC_EB | 0x05;
+ up->scc_genscc.scc_tfcr = SCC_EB | 0x05;
+
+ up->scc_genscc.scc_mrblr = 1; /* Single character receive */
+ up->scc_maxidl = 0; /* disable max idle */
+ up->scc_brkcr = 1; /* send one break character on stop TX */
+ up->scc_parec = 0;
+ up->scc_frmec = 0;
+ up->scc_nosec = 0;
+ up->scc_brkec = 0;
+ up->scc_uaddr1 = 0;
+ up->scc_uaddr2 = 0;
+ up->scc_toseq = 0;
+ up->scc_char1 = 0x8000;
+ up->scc_char2 = 0x8000;
+ up->scc_char3 = 0x8000;
+ up->scc_char4 = 0x8000;
+ up->scc_char5 = 0x8000;
+ up->scc_char6 = 0x8000;
+ up->scc_char7 = 0x8000;
+ up->scc_char8 = 0x8000;
+ up->scc_rccm = 0xc0ff;
+
+ /* Set low latency / small fifo.
+ */
+ sp->scc_gsmrh = SCC_GSMRH_RFW;
+
+ /* Set SCC(x) clock mode to 16x
+ * See 8xx_io/commproc.c for details.
+ *
+ * Wire BRG1 to SCCn
+ */
+
+ /* Set UART mode, clock divider 16 on Tx and Rx
+ */
+ sp->scc_gsmrl &= ~0xF;
+ sp->scc_gsmrl |=
+ (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+ sp->scc_psmr = 0;
+ sp->scc_psmr |= SCU_PSMR_CL;
+
+ /* Mask all interrupts and remove anything pending.
+ */
+ sp->scc_sccm = 0;
+ sp->scc_scce = 0xffff;
+ sp->scc_dsr = 0x7e7e;
+ sp->scc_psmr = 0x3000;
+
+ /* Make the first buffer the only buffer.
+ */
+ tbdf->cbd_sc |= BD_SC_WRAP;
+ rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
+
+ /* Enable transmitter/receiver.
+ */
+ sp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+
+ return (0);
+}
+
+static void
+scc_putc(const char c)
+{
+ volatile cbd_t *tbdf;
+ volatile char *buf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+ if (c == '\n')
+ scc_putc ('\r');
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ tbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_tbase];
+
+ /* Wait for last character to go.
+ */
+
+ buf = (char *)tbdf->cbd_bufaddr;
+
+ *buf = c;
+ tbdf->cbd_datlen = 1;
+ tbdf->cbd_sc |= BD_SC_READY;
+ __asm__("eieio");
+
+ while (tbdf->cbd_sc & BD_SC_READY) {
+ __asm__("eieio");
+ WATCHDOG_RESET ();
+ }
+}
+
+static void
+scc_puts (const char *s)
+{
+ while (*s) {
+ scc_putc (*s++);
+ }
+}
+
+static int
+scc_getc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile unsigned char *buf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+ unsigned char c;
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+ /* Wait for character to show up.
+ */
+ buf = (unsigned char *)rbdf->cbd_bufaddr;
+
+ while (rbdf->cbd_sc & BD_SC_EMPTY)
+ WATCHDOG_RESET ();
+
+ c = *buf;
+ rbdf->cbd_sc |= BD_SC_EMPTY;
+
+ return(c);
+}
+
+static int
+scc_tstc(void)
+{
+ volatile cbd_t *rbdf;
+ volatile scc_uart_t *up;
+ volatile immap_t *im = (immap_t *)CFG_IMMR;
+ volatile cpm8xx_t *cpmp = &(im->im_cpm);
+
+ up = (scc_uart_t *)&cpmp->cp_dparam[PROFF_SCC];
+
+ rbdf = (cbd_t *)&cpmp->cp_dpmem[up->scc_genscc.scc_rbase];
+
+ return(!(rbdf->cbd_sc & BD_SC_EMPTY));
+}
+
+struct serial_device serial_scc_device =
+{
+ "serial_scc",
+ "SCC",
+ scc_init,
+ scc_setbrg,
+ scc_getc,
+ scc_tstc,
+ scc_putc,
+ scc_puts,
+};
+
+#endif /* CONFIG_8xx_CONS_SCCx */
+
+void enable_putc(void)
+{
+ gd->be_quiet = 0;
+}
+#endif
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+
+void
+kgdb_serial_init(void)
+{
+ int i = -1;
+
+ if (strcmp(default_serial_console()->ctlr, "SMC") == 0)
+ {
+#if defined(CONFIG_8xx_CONS_SMC1)
+ i = 1;
+#elif defined(CONFIG_8xx_CONS_SMC2)
+ i = 2;
+#endif
+ }
+ else if (strcmp(default_serial_console()->ctlr, "SMC") == 0)
+ {
+#if defined(CONFIG_8xx_CONS_SCC1)
+ i = 1;
+#elif defined(CONFIG_8xx_CONS_SCC2)
+ i = 2;
+#elif defined(CONFIG_8xx_CONS_SCC3)
+ i = 3;
+#elif defined(CONFIG_8xx_CONS_SCC4)
+ i = 4;
+#endif
+ }
+
+ if (i >= 0)
+ {
+ serial_printf("[on %s%d] ", default_serial_console()->ctlr, i);
+ }
+}
+
+void
+putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void
+putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int
+getDebugChar (void)
+{
+ return serial_getc();
+}
+
+void
+kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif /* CFG_CMD_KGDB */
+
+#endif /* CONFIG_8xx_CONS_NONE */
diff --git a/drivers/serial/serial_netarm.c b/drivers/serial/serial_netarm.c
new file mode 100644
index 0000000000..bc6bf30b69
--- /dev/null
+++ b/drivers/serial/serial_netarm.c
@@ -0,0 +1,200 @@
+/*
+ * Serial Port stuff - taken from Linux
+ *
+ * (C) Copyright 2002
+ * MAZeT GmbH <www.mazet.de>
+ * Stephan Linz <linz@mazet.de>, <linz@li-pro.net>
+ *
+ * (c) 2004
+ * IMMS gGmbH <www.imms.de>
+ * Thomas Elste <info@elste.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+
+#ifdef CONFIG_NETARM
+
+#include <asm/hardware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define PORTA (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTA))
+#if !defined(CONFIG_NETARM_NS7520)
+#define PORTB (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTB))
+#else
+#define PORTC (*(volatile unsigned int *)(NETARM_GEN_MODULE_BASE + NETARM_GEN_PORTC))
+#endif
+
+/* wait until transmitter is ready for another character */
+#define TXWAITRDY(registers) \
+{ \
+ ulong tmo = get_timer(0) + 1 * CFG_HZ; \
+ while (((registers)->status_a & NETARM_SER_STATA_TX_RDY) == 0 ) { \
+ if (get_timer(0) > tmo) \
+ break; \
+ } \
+}
+
+
+#ifndef CONFIG_UART1_CONSOLE
+volatile netarm_serial_channel_t *serial_reg_ch1 = get_serial_channel(0);
+volatile netarm_serial_channel_t *serial_reg_ch2 = get_serial_channel(1);
+#else
+volatile netarm_serial_channel_t *serial_reg_ch1 = get_serial_channel(1);
+volatile netarm_serial_channel_t *serial_reg_ch2 = get_serial_channel(0);
+#endif
+
+extern void _netarm_led_FAIL1(void);
+
+/*
+ * Setup both serial i/f with given baudrate
+ */
+void serial_setbrg (void)
+{
+ /* set 0 ... make sure pins are configured for serial */
+#if !defined(CONFIG_NETARM_NS7520)
+ PORTA = PORTB =
+ NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0);
+#else
+ PORTA = NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0);
+ PORTC = NETARM_GEN_PORT_CSF (0xef) | NETARM_GEN_PORT_MODE (0xef) | NETARM_GEN_PORT_DIR (0xe0);
+#endif
+
+ /* first turn em off */
+ serial_reg_ch1->ctrl_a = serial_reg_ch2->ctrl_a = 0;
+
+ /* clear match register, we don't need it */
+ serial_reg_ch1->rx_match = serial_reg_ch2->rx_match = 0;
+
+ /* setup bit rate generator and rx buffer gap timer (1 byte only) */
+ if ((gd->baudrate >= MIN_BAUD_RATE)
+ && (gd->baudrate <= MAX_BAUD_RATE)) {
+ serial_reg_ch1->bitrate = serial_reg_ch2->bitrate =
+ NETARM_SER_BR_X16 (gd->baudrate);
+ serial_reg_ch1->rx_buf_timer = serial_reg_ch2->rx_buf_timer =
+ 0;
+ serial_reg_ch1->rx_char_timer = serial_reg_ch2->rx_char_timer =
+ NETARM_SER_RXGAP (gd->baudrate);
+ } else {
+ hang ();
+ }
+
+ /* setup port mode */
+ serial_reg_ch1->ctrl_b = serial_reg_ch2->ctrl_b =
+ ( NETARM_SER_CTLB_RCGT_EN |
+ NETARM_SER_CTLB_UART_MODE);
+ serial_reg_ch1->ctrl_a = serial_reg_ch2->ctrl_a =
+ ( NETARM_SER_CTLA_ENABLE |
+ NETARM_SER_CTLA_P_NONE |
+ /* see errata */
+ NETARM_SER_CTLA_2STOP |
+ NETARM_SER_CTLA_8BITS |
+ NETARM_SER_CTLA_DTR_EN |
+ NETARM_SER_CTLA_RTS_EN);
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+ return 0;
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ volatile unsigned char *fifo;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+
+ fifo = (volatile unsigned char *) &(serial_reg_ch1->fifo);
+ TXWAITRDY (serial_reg_ch1);
+ *fifo = c;
+}
+
+/*
+ * Test of a single byte from the serial port. Returns 1 on success, 0
+ * otherwise.
+ */
+int serial_tstc(void)
+{
+ return serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY;
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise.
+ */
+int serial_getc (void)
+{
+ unsigned int ch_uint;
+ volatile unsigned int *fifo;
+ volatile unsigned char *fifo_char = NULL;
+ int buf_count = 0;
+
+ while (!(serial_reg_ch1->status_a & NETARM_SER_STATA_RX_RDY))
+ /* NOP */ ;
+
+ fifo = (volatile unsigned int *) &(serial_reg_ch1->fifo);
+ fifo_char = (unsigned char *) &ch_uint;
+ ch_uint = *fifo;
+
+ buf_count = NETARM_SER_STATA_RXFDB (serial_reg_ch1->status_a);
+ switch (buf_count) {
+ case NETARM_SER_STATA_RXFDB_4BYTES:
+ buf_count = 4;
+ break;
+ case NETARM_SER_STATA_RXFDB_3BYTES:
+ buf_count = 3;
+ break;
+ case NETARM_SER_STATA_RXFDB_2BYTES:
+ buf_count = 2;
+ break;
+ case NETARM_SER_STATA_RXFDB_1BYTES:
+ buf_count = 1;
+ break;
+ default:
+ /* panic, be never here */
+ break;
+ }
+
+ serial_reg_ch1->status_a |= NETARM_SER_STATA_RX_CLOSED;
+
+ return ch_uint & 0xff;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+#endif /* CONFIG_NETARM */
diff --git a/drivers/serial/serial_nios.c b/drivers/serial/serial_nios.c
new file mode 100644
index 0000000000..5ecdc6d7ea
--- /dev/null
+++ b/drivers/serial/serial_nios.c
@@ -0,0 +1,135 @@
+/*
+ * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <nios-io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*------------------------------------------------------------------
+ * JTAG acts as the serial port
+ *-----------------------------------------------------------------*/
+#if defined(CONFIG_CONSOLE_JTAG)
+
+static nios_jtag_t *jtag = (nios_jtag_t *)CFG_NIOS_CONSOLE;
+
+void serial_setbrg( void ){ return; }
+int serial_init( void ) { return(0);}
+
+void serial_putc (char c)
+{
+ while ((jtag->txcntl & NIOS_JTAG_TRDY) != 0)
+ WATCHDOG_RESET ();
+ jtag->txcntl = NIOS_JTAG_TRDY | (unsigned char)c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s != 0)
+ serial_putc (*s++);
+}
+
+int serial_tstc (void)
+{
+ return (jtag->rxcntl & NIOS_JTAG_RRDY);
+}
+
+int serial_getc (void)
+{
+ int c;
+ while (serial_tstc() == 0)
+ WATCHDOG_RESET ();
+ c = jtag->rxcntl & 0x0ff;
+ jtag->rxcntl = 0;
+ return (c);
+}
+
+/*------------------------------------------------------------------
+ * UART the serial port
+ *-----------------------------------------------------------------*/
+#else
+
+static nios_uart_t *uart = (nios_uart_t *)CFG_NIOS_CONSOLE;
+
+#if defined(CFG_NIOS_FIXEDBAUD)
+
+/* Everything's already setup for fixed-baud PTF
+ * assignment
+ */
+void serial_setbrg (void){ return; }
+int serial_init (void) { return (0);}
+
+#else
+
+void serial_setbrg (void)
+{
+ unsigned div;
+
+ div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1;
+ uart->divisor = div;
+ return;
+}
+
+int serial_init (void)
+{
+ serial_setbrg ();
+ return (0);
+}
+
+#endif /* CFG_NIOS_FIXEDBAUD */
+
+
+/*-----------------------------------------------------------------------
+ * UART CONSOLE
+ *---------------------------------------------------------------------*/
+void serial_putc (char c)
+{
+ if (c == '\n')
+ serial_putc ('\r');
+ while ((uart->status & NIOS_UART_TRDY) == 0)
+ WATCHDOG_RESET ();
+ uart->txdata = (unsigned char)c;
+}
+
+void serial_puts (const char *s)
+{
+ while (*s != 0) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_tstc (void)
+{
+ return (uart->status & NIOS_UART_RRDY);
+}
+
+int serial_getc (void)
+{
+ while (serial_tstc () == 0)
+ WATCHDOG_RESET ();
+ return( uart->rxdata & 0x00ff );
+}
+
+#endif /* CONFIG_JTAG_CONSOLE */
diff --git a/drivers/serial/serial_nios2.c b/drivers/serial/serial_nios2.c
new file mode 100644
index 0000000000..0bd3821e39
--- /dev/null
+++ b/drivers/serial/serial_nios2.c
@@ -0,0 +1,143 @@
+/*
+ * (C) Copyright 2004, Psyent Corporation <www.psyent.com>
+ * Scott McNutt <smcnutt@psyent.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/io.h>
+#include <nios2-io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*------------------------------------------------------------------
+ * JTAG acts as the serial port
+ *-----------------------------------------------------------------*/
+#if defined(CONFIG_CONSOLE_JTAG)
+
+static nios_jtag_t *jtag = (nios_jtag_t *)CFG_NIOS_CONSOLE;
+
+void serial_setbrg( void ){ return; }
+int serial_init( void ) { return(0);}
+
+void serial_putc (char c)
+{
+ unsigned val;
+
+ while (NIOS_JTAG_WSPACE ( readl (&jtag->control)) == 0)
+ WATCHDOG_RESET ();
+ writel (&jtag->data, (unsigned char)c);
+}
+
+void serial_puts (const char *s)
+{
+ while (*s != 0)
+ serial_putc (*s++);
+}
+
+int serial_tstc (void)
+{
+ return ( readl (&jtag->control) & NIOS_JTAG_RRDY);
+}
+
+int serial_getc (void)
+{
+ int c;
+ unsigned val;
+
+ while (1) {
+ WATCHDOG_RESET ();
+ val = readl (&jtag->data);
+ if (val & NIOS_JTAG_RVALID)
+ break;
+ }
+ c = val & 0x0ff;
+ return (c);
+}
+
+/*------------------------------------------------------------------
+ * UART the serial port
+ *-----------------------------------------------------------------*/
+#else
+
+static nios_uart_t *uart = (nios_uart_t *) CFG_NIOS_CONSOLE;
+
+#if defined(CFG_NIOS_FIXEDBAUD)
+
+/* Everything's already setup for fixed-baud PTF
+ * assignment
+ */
+void serial_setbrg (void){ return; }
+int serial_init (void) { return (0);}
+
+#else
+
+void serial_setbrg (void)
+{
+ unsigned div;
+
+ div = (CONFIG_SYS_CLK_FREQ/gd->baudrate)-1;
+ writel (&uart->divisor,div);
+ return;
+}
+
+int serial_init (void)
+{
+ serial_setbrg ();
+ return (0);
+}
+
+#endif /* CFG_NIOS_FIXEDBAUD */
+
+
+/*-----------------------------------------------------------------------
+ * UART CONSOLE
+ *---------------------------------------------------------------------*/
+void serial_putc (char c)
+{
+ if (c == '\n')
+ serial_putc ('\r');
+ while ((readl (&uart->status) & NIOS_UART_TRDY) == 0)
+ WATCHDOG_RESET ();
+ writel (&uart->txdata,(unsigned char)c);
+}
+
+void serial_puts (const char *s)
+{
+ while (*s != 0) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_tstc (void)
+{
+ return (readl (&uart->status) & NIOS_UART_RRDY);
+}
+
+int serial_getc (void)
+{
+ while (serial_tstc () == 0)
+ WATCHDOG_RESET ();
+ return (readl (&uart->rxdata) & 0x00ff );
+}
+
+#endif /* CONFIG_JTAG_CONSOLE */
diff --git a/drivers/serial/serial_ppc4xx.c b/drivers/serial/serial_ppc4xx.c
new file mode 100644
index 0000000000..fab0d95006
--- /dev/null
+++ b/drivers/serial/serial_ppc4xx.c
@@ -0,0 +1,984 @@
+/*
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+/*------------------------------------------------------------------------------+ */
+/*
+ * This source code has been made available to you by IBM on an AS-IS
+ * basis. Anyone receiving this source is licensed under IBM
+ * copyrights to use it in any way he or she deems fit, including
+ * copying it, modifying it, compiling it, and redistributing it either
+ * with or without modifications. No license under IBM patents or
+ * patent applications is to be implied by the copyright license.
+ *
+ * Any user of this software should understand that IBM cannot provide
+ * technical support for this software and will not be responsible for
+ * any consequences resulting from the use of this software.
+ *
+ * Any person who transfers this source code or any derivative work
+ * must include the IBM copyright notice, this paragraph, and the
+ * preceding two paragraphs in the transferred software.
+ *
+ * COPYRIGHT I B M CORPORATION 1995
+ * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ */
+/*------------------------------------------------------------------------------- */
+/*
+ * Travis Sawyer 15 September 2004
+ * Added CONFIG_SERIAL_MULTI support
+ */
+#include <common.h>
+#include <commproc.h>
+#include <asm/processor.h>
+#include <watchdog.h>
+#include "vecnum.h"
+
+#ifdef CONFIG_SERIAL_MULTI
+#include <serial.h>
+#endif
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+#include <malloc.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/*****************************************************************************/
+#ifdef CONFIG_IOP480
+
+#define SPU_BASE 0x40000000
+
+#define spu_LineStat_rc 0x00 /* Line Status Register (Read/Clear) */
+#define spu_LineStat_w 0x04 /* Line Status Register (Set) */
+#define spu_Handshk_rc 0x08 /* Handshake Status Register (Read/Clear) */
+#define spu_Handshk_w 0x0c /* Handshake Status Register (Set) */
+#define spu_BRateDivh 0x10 /* Baud rate divisor high */
+#define spu_BRateDivl 0x14 /* Baud rate divisor low */
+#define spu_CtlReg 0x18 /* Control Register */
+#define spu_RxCmd 0x1c /* Rx Command Register */
+#define spu_TxCmd 0x20 /* Tx Command Register */
+#define spu_RxBuff 0x24 /* Rx data buffer */
+#define spu_TxBuff 0x24 /* Tx data buffer */
+
+/*-----------------------------------------------------------------------------+
+ | Line Status Register.
+ +-----------------------------------------------------------------------------*/
+#define asyncLSRport1 0x40000000
+#define asyncLSRport1set 0x40000004
+#define asyncLSRDataReady 0x80
+#define asyncLSRFramingError 0x40
+#define asyncLSROverrunError 0x20
+#define asyncLSRParityError 0x10
+#define asyncLSRBreakInterrupt 0x08
+#define asyncLSRTxHoldEmpty 0x04
+#define asyncLSRTxShiftEmpty 0x02
+
+/*-----------------------------------------------------------------------------+
+ | Handshake Status Register.
+ +-----------------------------------------------------------------------------*/
+#define asyncHSRport1 0x40000008
+#define asyncHSRport1set 0x4000000c
+#define asyncHSRDsr 0x80
+#define asyncLSRCts 0x40
+
+/*-----------------------------------------------------------------------------+
+ | Control Register.
+ +-----------------------------------------------------------------------------*/
+#define asyncCRport1 0x40000018
+#define asyncCRNormal 0x00
+#define asyncCRLoopback 0x40
+#define asyncCRAutoEcho 0x80
+#define asyncCRDtr 0x20
+#define asyncCRRts 0x10
+#define asyncCRWordLength7 0x00
+#define asyncCRWordLength8 0x08
+#define asyncCRParityDisable 0x00
+#define asyncCRParityEnable 0x04
+#define asyncCREvenParity 0x00
+#define asyncCROddParity 0x02
+#define asyncCRStopBitsOne 0x00
+#define asyncCRStopBitsTwo 0x01
+#define asyncCRDisableDtrRts 0x00
+
+/*-----------------------------------------------------------------------------+
+ | Receiver Command Register.
+ +-----------------------------------------------------------------------------*/
+#define asyncRCRport1 0x4000001c
+#define asyncRCRDisable 0x00
+#define asyncRCREnable 0x80
+#define asyncRCRIntDisable 0x00
+#define asyncRCRIntEnabled 0x20
+#define asyncRCRDMACh2 0x40
+#define asyncRCRDMACh3 0x60
+#define asyncRCRErrorInt 0x10
+#define asyncRCRPauseEnable 0x08
+
+/*-----------------------------------------------------------------------------+
+ | Transmitter Command Register.
+ +-----------------------------------------------------------------------------*/
+#define asyncTCRport1 0x40000020
+#define asyncTCRDisable 0x00
+#define asyncTCREnable 0x80
+#define asyncTCRIntDisable 0x00
+#define asyncTCRIntEnabled 0x20
+#define asyncTCRDMACh2 0x40
+#define asyncTCRDMACh3 0x60
+#define asyncTCRTxEmpty 0x10
+#define asyncTCRErrorInt 0x08
+#define asyncTCRStopPause 0x04
+#define asyncTCRBreakGen 0x02
+
+/*-----------------------------------------------------------------------------+
+ | Miscellanies defines.
+ +-----------------------------------------------------------------------------*/
+#define asyncTxBufferport1 0x40000024
+#define asyncRxBufferport1 0x40000024
+#define asyncDLABLsbport1 0x40000014
+#define asyncDLABMsbport1 0x40000010
+#define asyncXOFFchar 0x13
+#define asyncXONchar 0x11
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+int serial_init (void)
+{
+ volatile char val;
+ unsigned short br_reg;
+
+ br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
+
+ /*
+ * Init onboard UART
+ */
+ out8 (SPU_BASE + spu_LineStat_rc, 0x78); /* Clear all bits in Line Status Reg */
+ out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */
+ out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */
+ out8 (SPU_BASE + spu_CtlReg, 0x08); /* Set 8 bits, no parity and 1 stop bit */
+ out8 (SPU_BASE + spu_RxCmd, 0xb0); /* Enable Rx */
+ out8 (SPU_BASE + spu_TxCmd, 0x9c); /* Enable Tx */
+ out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
+ val = in8 (SPU_BASE + spu_RxBuff); /* Dummy read, to clear receiver */
+
+ return (0);
+}
+
+void serial_setbrg (void)
+{
+ unsigned short br_reg;
+
+ br_reg = ((((CONFIG_CPUCLOCK * 1000000) / 16) / gd->baudrate) - 1);
+
+ out8 (SPU_BASE + spu_BRateDivl, (br_reg & 0x00ff)); /* Set baud rate divisor... */
+ out8 (SPU_BASE + spu_BRateDivh, ((br_reg & 0xff00) >> 8)); /* ... */
+}
+
+void serial_putc (const char c)
+{
+ if (c == '\n')
+ serial_putc ('\r');
+
+ /* load status from handshake register */
+ if (in8 (SPU_BASE + spu_Handshk_rc) != 00)
+ out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
+
+ out8 (SPU_BASE + spu_TxBuff, c); /* Put char */
+
+ while ((in8 (SPU_BASE + spu_LineStat_rc) & 04) != 04) {
+ if (in8 (SPU_BASE + spu_Handshk_rc) != 00)
+ out8 (SPU_BASE + spu_Handshk_rc, 0xff); /* Clear Handshake */
+ }
+}
+
+void serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int serial_getc ()
+{
+ unsigned char status = 0;
+
+ while (1) {
+ status = in8 (asyncLSRport1);
+ if ((status & asyncLSRDataReady) != 0x0) {
+ break;
+ }
+ if ((status & ( asyncLSRFramingError |
+ asyncLSROverrunError |
+ asyncLSRParityError |
+ asyncLSRBreakInterrupt )) != 0) {
+ (void) out8 (asyncLSRport1,
+ asyncLSRFramingError |
+ asyncLSROverrunError |
+ asyncLSRParityError |
+ asyncLSRBreakInterrupt );
+ }
+ }
+ return (0x000000ff & (int) in8 (asyncRxBufferport1));
+}
+
+int serial_tstc ()
+{
+ unsigned char status;
+
+ status = in8 (asyncLSRport1);
+ if ((status & asyncLSRDataReady) != 0x0) {
+ return (1);
+ }
+ if ((status & ( asyncLSRFramingError |
+ asyncLSROverrunError |
+ asyncLSRParityError |
+ asyncLSRBreakInterrupt )) != 0) {
+ (void) out8 (asyncLSRport1,
+ asyncLSRFramingError |
+ asyncLSROverrunError |
+ asyncLSRParityError |
+ asyncLSRBreakInterrupt);
+ }
+ return 0;
+}
+
+#endif /* CONFIG_IOP480 */
+
+/*****************************************************************************/
+#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405EP) || \
+ defined(CONFIG_440)
+
+#if defined(CONFIG_440)
+#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \
+ defined(CONFIG_440EPX) || defined(CONFIG_440GRX)
+#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000300
+#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000400
+#else
+#define UART0_BASE CFG_PERIPHERAL_BASE + 0x00000200
+#define UART1_BASE CFG_PERIPHERAL_BASE + 0x00000300
+#endif
+
+#if defined(CONFIG_440SP) || defined(CONFIG_440SPE)
+#define UART2_BASE CFG_PERIPHERAL_BASE + 0x00000600
+#endif
+
+#if defined(CONFIG_440GP)
+#define CR0_MASK 0x3fff0000
+#define CR0_EXTCLK_ENA 0x00600000
+#define CR0_UDIV_POS 16
+#define UDIV_SUBTRACT 1
+#define UART0_SDR cntrl0
+#define MFREG(a, d) d = mfdcr(a)
+#define MTREG(a, d) mtdcr(a, d)
+#else /* #if defined(CONFIG_440GP) */
+/* all other 440 PPC's access clock divider via sdr register */
+#define CR0_MASK 0xdfffffff
+#define CR0_EXTCLK_ENA 0x00800000
+#define CR0_UDIV_POS 0
+#define UDIV_SUBTRACT 0
+#define UART0_SDR sdr_uart0
+#define UART1_SDR sdr_uart1
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRx) || \
+ defined(CONFIG_440SP) || defined(CONFIG_440SPe)
+#define UART2_SDR sdr_uart2
+#endif
+#if defined(CONFIG_440EP) || defined(CONFIG_440EPx) || \
+ defined(CONFIG_440GR) || defined(CONFIG_440GRx)
+#define UART3_SDR sdr_uart3
+#endif
+#define MFREG(a, d) mfsdr(a, d)
+#define MTREG(a, d) mtsdr(a, d)
+#endif /* #if defined(CONFIG_440GP) */
+#elif defined(CONFIG_405EP)
+#define UART0_BASE 0xef600300
+#define UART1_BASE 0xef600400
+#define UCR0_MASK 0x0000007f
+#define UCR1_MASK 0x00007f00
+#define UCR0_UDIV_POS 0
+#define UCR1_UDIV_POS 8
+#define UDIV_MAX 127
+#else /* CONFIG_405GP || CONFIG_405CR */
+#define UART0_BASE 0xef600300
+#define UART1_BASE 0xef600400
+#define CR0_MASK 0x00001fff
+#define CR0_EXTCLK_ENA 0x000000c0
+#define CR0_UDIV_POS 1
+#define UDIV_MAX 32
+#endif
+
+/* using serial port 0 or 1 as U-Boot console ? */
+#if defined(CONFIG_UART1_CONSOLE)
+#define ACTING_UART0_BASE UART1_BASE
+#define ACTING_UART1_BASE UART0_BASE
+#else
+#define ACTING_UART0_BASE UART0_BASE
+#define ACTING_UART1_BASE UART1_BASE
+#endif
+
+#if defined(CONFIG_SERIAL_MULTI)
+#define UART_BASE dev_base
+#else
+#define UART_BASE ACTING_UART0_BASE
+#endif
+
+#if defined(CONFIG_405EP) && defined(CFG_EXT_SERIAL_CLOCK)
+#error "External serial clock not supported on AMCC PPC405EP!"
+#endif
+
+#define UART_RBR 0x00
+#define UART_THR 0x00
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/*-----------------------------------------------------------------------------+
+ | Line Status Register.
+ +-----------------------------------------------------------------------------*/
+/*#define asyncLSRport1 ACTING_UART0_BASE+0x05 */
+#define asyncLSRDataReady1 0x01
+#define asyncLSROverrunError1 0x02
+#define asyncLSRParityError1 0x04
+#define asyncLSRFramingError1 0x08
+#define asyncLSRBreakInterrupt1 0x10
+#define asyncLSRTxHoldEmpty1 0x20
+#define asyncLSRTxShiftEmpty1 0x40
+#define asyncLSRRxFifoError1 0x80
+
+/*-----------------------------------------------------------------------------+
+ | Miscellanies defines.
+ +-----------------------------------------------------------------------------*/
+/*#define asyncTxBufferport1 ACTING_UART0_BASE+0x00 */
+/*#define asyncRxBufferport1 ACTING_UART0_BASE+0x00 */
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+/*-----------------------------------------------------------------------------+
+ | Fifo
+ +-----------------------------------------------------------------------------*/
+typedef struct {
+ char *rx_buffer;
+ ulong rx_put;
+ ulong rx_get;
+} serial_buffer_t;
+
+volatile static serial_buffer_t buf_info;
+#endif
+
+#if defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLOCK)
+static void serial_divs (int baudrate, unsigned long *pudiv,
+ unsigned short *pbdiv )
+{
+ sys_info_t sysinfo;
+ unsigned long div; /* total divisor udiv * bdiv */
+ unsigned long umin; /* minimum udiv */
+ unsigned short diff; /* smallest diff */
+ unsigned long udiv; /* best udiv */
+
+ unsigned short idiff; /* current diff */
+ unsigned short ibdiv; /* current bdiv */
+ unsigned long i;
+ unsigned long est; /* current estimate */
+
+ get_sys_info( &sysinfo );
+
+ udiv = 32; /* Assume lowest possible serial clk */
+ div = sysinfo.freqPLB/(16*baudrate); /* total divisor */
+ umin = sysinfo.pllOpbDiv<<1; /* 2 x OPB divisor */
+ diff = 32; /* highest possible */
+
+ /* i is the test udiv value -- start with the largest
+ * possible (32) to minimize serial clock and constrain
+ * search to umin.
+ */
+ for( i = 32; i > umin; i-- ){
+ ibdiv = div/i;
+ est = i * ibdiv;
+ idiff = (est > div) ? (est-div) : (div-est);
+ if( idiff == 0 ){
+ udiv = i;
+ break; /* can't do better */
+ }
+ else if( idiff < diff ){
+ udiv = i; /* best so far */
+ diff = idiff; /* update lowest diff*/
+ }
+ }
+
+ *pudiv = udiv;
+ *pbdiv = div/udiv;
+
+}
+#endif /* defined(CONFIG_440) && !defined(CFG_EXT_SERIAL_CLK) */
+
+/*
+ * Minimal serial functions needed to use one of the SMC ports
+ * as serial console interface.
+ */
+
+#if defined(CONFIG_440)
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_init_dev (unsigned long dev_base)
+#else
+int serial_init(void)
+#endif
+{
+ unsigned long reg;
+ unsigned long udiv;
+ unsigned short bdiv;
+ volatile char val;
+#ifdef CFG_EXT_SERIAL_CLOCK
+ unsigned long tmp;
+#endif
+
+ MFREG(UART0_SDR, reg);
+ reg &= ~CR0_MASK;
+
+#ifdef CFG_EXT_SERIAL_CLOCK
+ reg |= CR0_EXTCLK_ENA;
+ udiv = 1;
+ tmp = gd->baudrate * 16;
+ bdiv = (CFG_EXT_SERIAL_CLOCK + tmp / 2) / tmp;
+#else
+ /* For 440, the cpu clock is on divider chain A, UART on divider
+ * chain B ... so cpu clock is irrelevant. Get the "optimized"
+ * values that are subject to the 1/2 opb clock constraint
+ */
+ serial_divs (gd->baudrate, &udiv, &bdiv);
+#endif
+
+ reg |= (udiv - UDIV_SUBTRACT) << CR0_UDIV_POS; /* set the UART divisor */
+
+ /*
+ * Configure input clock to baudrate generator for all
+ * available serial ports here
+ */
+ MTREG(UART0_SDR, reg);
+#if defined(UART1_SDR)
+ MTREG(UART1_SDR, reg);
+#endif
+#if defined(UART2_SDR)
+ MTREG(UART2_SDR, reg);
+#endif
+#if defined(UART3_SDR)
+ MTREG(UART3_SDR, reg);
+#endif
+
+ out8(UART_BASE + UART_LCR, 0x80); /* set DLAB bit */
+ out8(UART_BASE + UART_DLL, bdiv); /* set baudrate divisor */
+ out8(UART_BASE + UART_DLM, bdiv >> 8); /* set baudrate divisor */
+ out8(UART_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */
+ out8(UART_BASE + UART_FCR, 0x00); /* disable FIFO */
+ out8(UART_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */
+ val = in8(UART_BASE + UART_LSR); /* clear line status */
+ val = in8(UART_BASE + UART_RBR); /* read receive buffer */
+ out8(UART_BASE + UART_SCR, 0x00); /* set scratchpad */
+ out8(UART_BASE + UART_IER, 0x00); /* set interrupt enable reg */
+
+ return (0);
+}
+
+#else /* !defined(CONFIG_440) */
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_init_dev (unsigned long dev_base)
+#else
+int serial_init (void)
+#endif
+{
+ unsigned long reg;
+ unsigned long tmp;
+ unsigned long clk;
+ unsigned long udiv;
+ unsigned short bdiv;
+ volatile char val;
+
+#ifdef CONFIG_405EP
+ reg = mfdcr(cpc0_ucr) & ~(UCR0_MASK | UCR1_MASK);
+ clk = gd->cpu_clk;
+ tmp = CFG_BASE_BAUD * 16;
+ udiv = (clk + tmp / 2) / tmp;
+ if (udiv > UDIV_MAX) /* max. n bits for udiv */
+ udiv = UDIV_MAX;
+ reg |= (udiv) << UCR0_UDIV_POS; /* set the UART divisor */
+ reg |= (udiv) << UCR1_UDIV_POS; /* set the UART divisor */
+ mtdcr (cpc0_ucr, reg);
+#else /* CONFIG_405EP */
+ reg = mfdcr(cntrl0) & ~CR0_MASK;
+#ifdef CFG_EXT_SERIAL_CLOCK
+ clk = CFG_EXT_SERIAL_CLOCK;
+ udiv = 1;
+ reg |= CR0_EXTCLK_ENA;
+#else
+ clk = gd->cpu_clk;
+#ifdef CFG_405_UART_ERRATA_59
+ udiv = 31; /* Errata 59: stuck at 31 */
+#else
+ tmp = CFG_BASE_BAUD * 16;
+ udiv = (clk + tmp / 2) / tmp;
+ if (udiv > UDIV_MAX) /* max. n bits for udiv */
+ udiv = UDIV_MAX;
+#endif
+#endif
+ reg |= (udiv - 1) << CR0_UDIV_POS; /* set the UART divisor */
+ mtdcr (cntrl0, reg);
+#endif /* CONFIG_405EP */
+
+ tmp = gd->baudrate * udiv * 16;
+ bdiv = (clk + tmp / 2) / tmp;
+
+ out8(UART_BASE + UART_LCR, 0x80); /* set DLAB bit */
+ out8(UART_BASE + UART_DLL, bdiv); /* set baudrate divisor */
+ out8(UART_BASE + UART_DLM, bdiv >> 8); /* set baudrate divisor */
+ out8(UART_BASE + UART_LCR, 0x03); /* clear DLAB; set 8 bits, no parity */
+ out8(UART_BASE + UART_FCR, 0x00); /* disable FIFO */
+ out8(UART_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */
+ val = in8(UART_BASE + UART_LSR); /* clear line status */
+ val = in8(UART_BASE + UART_RBR); /* read receive buffer */
+ out8(UART_BASE + UART_SCR, 0x00); /* set scratchpad */
+ out8(UART_BASE + UART_IER, 0x00); /* set interrupt enable reg */
+
+ return (0);
+}
+
+#endif /* if defined(CONFIG_440) */
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_setbrg_dev (unsigned long dev_base)
+#else
+void serial_setbrg (void)
+#endif
+{
+#if defined(CONFIG_SERIAL_MULTI)
+ serial_init_dev(dev_base);
+#else
+ serial_init();
+#endif
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_putc_dev (unsigned long dev_base, const char c)
+#else
+void serial_putc (const char c)
+#endif
+{
+ int i;
+
+ if (c == '\n')
+#if defined(CONFIG_SERIAL_MULTI)
+ serial_putc_dev (dev_base, '\r');
+#else
+ serial_putc ('\r');
+#endif
+
+ /* check THRE bit, wait for transmiter available */
+ for (i = 1; i < 3500; i++) {
+ if ((in8 (UART_BASE + UART_LSR) & 0x20) == 0x20)
+ break;
+ udelay (100);
+ }
+ out8 (UART_BASE + UART_THR, c); /* put character out */
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+void serial_puts_dev (unsigned long dev_base, const char *s)
+#else
+void serial_puts (const char *s)
+#endif
+{
+ while (*s) {
+#if defined(CONFIG_SERIAL_MULTI)
+ serial_putc_dev (dev_base, *s++);
+#else
+ serial_putc (*s++);
+#endif
+ }
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_getc_dev (unsigned long dev_base)
+#else
+int serial_getc (void)
+#endif
+{
+ unsigned char status = 0;
+
+ while (1) {
+#if defined(CONFIG_HW_WATCHDOG)
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+#endif /* CONFIG_HW_WATCHDOG */
+ status = in8 (UART_BASE + UART_LSR);
+ if ((status & asyncLSRDataReady1) != 0x0) {
+ break;
+ }
+ if ((status & ( asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1 )) != 0) {
+ out8 (UART_BASE + UART_LSR,
+ asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1);
+ }
+ }
+ return (0x000000ff & (int) in8 (UART_BASE));
+}
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial_tstc_dev (unsigned long dev_base)
+#else
+int serial_tstc (void)
+#endif
+{
+ unsigned char status;
+
+ status = in8 (UART_BASE + UART_LSR);
+ if ((status & asyncLSRDataReady1) != 0x0) {
+ return (1);
+ }
+ if ((status & ( asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1 )) != 0) {
+ out8 (UART_BASE + UART_LSR,
+ asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1);
+ }
+ return 0;
+}
+
+#ifdef CONFIG_SERIAL_SOFTWARE_FIFO
+
+void serial_isr (void *arg)
+{
+ int space;
+ int c;
+ const int rx_get = buf_info.rx_get;
+ int rx_put = buf_info.rx_put;
+
+ if (rx_get <= rx_put) {
+ space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+ } else {
+ space = rx_get - rx_put;
+ }
+ while (serial_tstc_dev (ACTING_UART0_BASE)) {
+ c = serial_getc_dev (ACTING_UART0_BASE);
+ if (space) {
+ buf_info.rx_buffer[rx_put++] = c;
+ space--;
+ }
+ if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO)
+ rx_put = 0;
+ if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) {
+ /* Stop flow by setting RTS inactive */
+ out8 (ACTING_UART0_BASE + UART_MCR,
+ in8 (ACTING_UART0_BASE + UART_MCR) & (0xFF ^ 0x02));
+ }
+ }
+ buf_info.rx_put = rx_put;
+}
+
+void serial_buffered_init (void)
+{
+ serial_puts ("Switching to interrupt driven serial input mode.\n");
+ buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO);
+ buf_info.rx_put = 0;
+ buf_info.rx_get = 0;
+
+ if (in8 (ACTING_UART0_BASE + UART_MSR) & 0x10) {
+ serial_puts ("Check CTS signal present on serial port: OK.\n");
+ } else {
+ serial_puts ("WARNING: CTS signal not present on serial port.\n");
+ }
+
+ irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ ,
+ serial_isr /*interrupt_handler_t *handler */ ,
+ (void *) &buf_info /*void *arg */ );
+
+ /* Enable "RX Data Available" Interrupt on UART */
+ /* out8(ACTING_UART0_BASE + UART_IER, in8(ACTING_UART0_BASE + UART_IER) |0x01); */
+ out8 (ACTING_UART0_BASE + UART_IER, 0x01);
+ /* Set DTR active */
+ out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x01);
+ /* Start flow by setting RTS active */
+ out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02);
+ /* Setup UART FIFO: RX trigger level: 4 byte, Enable FIFO */
+ out8 (ACTING_UART0_BASE + UART_FCR, (1 << 6) | 1);
+}
+
+void serial_buffered_putc (const char c)
+{
+ /* Wait for CTS */
+#if defined(CONFIG_HW_WATCHDOG)
+ while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10))
+ WATCHDOG_RESET ();
+#else
+ while (!(in8 (ACTING_UART0_BASE + UART_MSR) & 0x10));
+#endif
+ serial_putc (c);
+}
+
+void serial_buffered_puts (const char *s)
+{
+ serial_puts (s);
+}
+
+int serial_buffered_getc (void)
+{
+ int space;
+ int c;
+ int rx_get = buf_info.rx_get;
+ int rx_put;
+
+#if defined(CONFIG_HW_WATCHDOG)
+ while (rx_get == buf_info.rx_put)
+ WATCHDOG_RESET ();
+#else
+ while (rx_get == buf_info.rx_put);
+#endif
+ c = buf_info.rx_buffer[rx_get++];
+ if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO)
+ rx_get = 0;
+ buf_info.rx_get = rx_get;
+
+ rx_put = buf_info.rx_put;
+ if (rx_get <= rx_put) {
+ space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get);
+ } else {
+ space = rx_get - rx_put;
+ }
+ if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) {
+ /* Start flow by setting RTS active */
+ out8 (ACTING_UART0_BASE + UART_MCR, in8 (ACTING_UART0_BASE + UART_MCR) | 0x02);
+ }
+
+ return c;
+}
+
+int serial_buffered_tstc (void)
+{
+ return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0;
+}
+
+#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+/*
+ AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port
+ number 0 or number 1
+ - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 :
+ configuration has been already done
+ - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 :
+ configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE
+*/
+#if (CONFIG_KGDB_SER_INDEX & 2)
+void kgdb_serial_init (void)
+{
+ volatile char val;
+ unsigned short br_reg;
+
+ get_clocks ();
+ br_reg = (((((gd->cpu_clk / 16) / 18) * 10) / CONFIG_KGDB_BAUDRATE) +
+ 5) / 10;
+ /*
+ * Init onboard 16550 UART
+ */
+ out8 (ACTING_UART1_BASE + UART_LCR, 0x80); /* set DLAB bit */
+ out8 (ACTING_UART1_BASE + UART_DLL, (br_reg & 0x00ff)); /* set divisor for 9600 baud */
+ out8 (ACTING_UART1_BASE + UART_DLM, ((br_reg & 0xff00) >> 8)); /* set divisor for 9600 baud */
+ out8 (ACTING_UART1_BASE + UART_LCR, 0x03); /* line control 8 bits no parity */
+ out8 (ACTING_UART1_BASE + UART_FCR, 0x00); /* disable FIFO */
+ out8 (ACTING_UART1_BASE + UART_MCR, 0x00); /* no modem control DTR RTS */
+ val = in8 (ACTING_UART1_BASE + UART_LSR); /* clear line status */
+ val = in8 (ACTING_UART1_BASE + UART_RBR); /* read receive buffer */
+ out8 (ACTING_UART1_BASE + UART_SCR, 0x00); /* set scratchpad */
+ out8 (ACTING_UART1_BASE + UART_IER, 0x00); /* set interrupt enable reg */
+}
+
+void putDebugChar (const char c)
+{
+ if (c == '\n')
+ serial_putc ('\r');
+
+ out8 (ACTING_UART1_BASE + UART_THR, c); /* put character out */
+
+ /* check THRE bit, wait for transfer done */
+ while ((in8 (ACTING_UART1_BASE + UART_LSR) & 0x20) != 0x20);
+}
+
+void putDebugStr (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+int getDebugChar (void)
+{
+ unsigned char status = 0;
+
+ while (1) {
+ status = in8 (ACTING_UART1_BASE + UART_LSR);
+ if ((status & asyncLSRDataReady1) != 0x0) {
+ break;
+ }
+ if ((status & ( asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1 )) != 0) {
+ out8 (ACTING_UART1_BASE + UART_LSR,
+ asyncLSRFramingError1 |
+ asyncLSROverrunError1 |
+ asyncLSRParityError1 |
+ asyncLSRBreakInterrupt1);
+ }
+ }
+ return (0x000000ff & (int) in8 (ACTING_UART1_BASE));
+}
+
+void kgdb_interruptible (int yes)
+{
+ return;
+}
+
+#else /* ! (CONFIG_KGDB_SER_INDEX & 2) */
+
+void kgdb_serial_init (void)
+{
+ serial_printf ("[on serial] ");
+}
+
+void putDebugChar (int c)
+{
+ serial_putc (c);
+}
+
+void putDebugStr (const char *str)
+{
+ serial_puts (str);
+}
+
+int getDebugChar (void)
+{
+ return serial_getc ();
+}
+
+void kgdb_interruptible (int yes)
+{
+ return;
+}
+#endif /* (CONFIG_KGDB_SER_INDEX & 2) */
+#endif /* CFG_CMD_KGDB */
+
+
+#if defined(CONFIG_SERIAL_MULTI)
+int serial0_init(void)
+{
+ return (serial_init_dev(UART0_BASE));
+}
+
+int serial1_init(void)
+{
+ return (serial_init_dev(UART1_BASE));
+}
+void serial0_setbrg (void)
+{
+ serial_setbrg_dev(UART0_BASE);
+}
+void serial1_setbrg (void)
+{
+ serial_setbrg_dev(UART1_BASE);
+}
+
+void serial0_putc(const char c)
+{
+ serial_putc_dev(UART0_BASE,c);
+}
+
+void serial1_putc(const char c)
+{
+ serial_putc_dev(UART1_BASE, c);
+}
+void serial0_puts(const char *s)
+{
+ serial_puts_dev(UART0_BASE, s);
+}
+
+void serial1_puts(const char *s)
+{
+ serial_puts_dev(UART1_BASE, s);
+}
+
+int serial0_getc(void)
+{
+ return(serial_getc_dev(UART0_BASE));
+}
+
+int serial1_getc(void)
+{
+ return(serial_getc_dev(UART1_BASE));
+}
+int serial0_tstc(void)
+{
+ return (serial_tstc_dev(UART0_BASE));
+}
+
+int serial1_tstc(void)
+{
+ return (serial_tstc_dev(UART1_BASE));
+}
+
+struct serial_device serial0_device =
+{
+ "serial0",
+ "UART0",
+ serial0_init,
+ serial0_setbrg,
+ serial0_getc,
+ serial0_tstc,
+ serial0_putc,
+ serial0_puts,
+};
+
+struct serial_device serial1_device =
+{
+ "serial1",
+ "UART1",
+ serial1_init,
+ serial1_setbrg,
+ serial1_getc,
+ serial1_tstc,
+ serial1_putc,
+ serial1_puts,
+};
+#endif /* CONFIG_SERIAL_MULTI */
+
+#endif /* CONFIG_405GP || CONFIG_405CR */
diff --git a/drivers/serial/serial_pxa.c b/drivers/serial/serial_pxa.c
new file mode 100644
index 0000000000..09e036db40
--- /dev/null
+++ b/drivers/serial/serial_pxa.c
@@ -0,0 +1,198 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <asm/arch/pxa-regs.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void serial_setbrg (void)
+{
+ unsigned int quot = 0;
+
+ if (gd->baudrate == 1200)
+ quot = 768;
+ else if (gd->baudrate == 9600)
+ quot = 96;
+ else if (gd->baudrate == 19200)
+ quot = 48;
+ else if (gd->baudrate == 38400)
+ quot = 24;
+ else if (gd->baudrate == 57600)
+ quot = 16;
+ else if (gd->baudrate == 115200)
+ quot = 8;
+ else
+ hang ();
+
+#ifdef CONFIG_FFUART
+#ifdef CONFIG_CPU_MONAHANS
+ CKENA |= CKENA_22_FFUART;
+#else
+ CKEN |= CKEN6_FFUART;
+#endif /* CONFIG_CPU_MONAHANS */
+
+ FFIER = 0; /* Disable for now */
+ FFFCR = FCR_TRFIFOE; /* Fifos enabled */
+
+ /* set baud rate */
+ FFLCR = LCR_WLS0 | LCR_WLS1 | LCR_DLAB;
+ FFDLL = quot & 0xff;
+ FFDLH = quot >> 8;
+ FFLCR = LCR_WLS0 | LCR_WLS1;
+
+ FFIER = IER_UUE; /* Enable FFUART */
+
+#elif defined(CONFIG_BTUART)
+#ifdef CONFIG_CPU_MONAHANS
+ CKENA |= CKENA_21_BTUART;
+#else
+ CKEN |= CKEN7_BTUART;
+#endif /* CONFIG_CPU_MONAHANS */
+
+ BTIER = 0;
+ BTFCR = FCR_TRFIFOE; /* Fifos enabled */
+
+ /* set baud rate */
+ BTLCR = LCR_DLAB;
+ BTDLL = quot & 0xff;
+ BTDLH = quot >> 8;
+ BTLCR = LCR_WLS0 | LCR_WLS1;
+
+ BTIER = IER_UUE; /* Enable BFUART */
+
+#elif defined(CONFIG_STUART)
+#ifdef CONFIG_CPU_MONAHANS
+ CKENA |= CKENA_23_STUART;
+#else
+ CKEN |= CKEN5_STUART;
+#endif /* CONFIG_CPU_MONAHANS */
+
+ STIER = 0;
+ STFCR = 0;
+
+ /* set baud rate */
+ STLCR = LCR_DLAB;
+ STDLL = quot & 0xff;
+ STDLH = quot >> 8;
+ STLCR = LCR_WLS0 | LCR_WLS1;
+
+ STIER = IER_UUE; /* Enable STUART */
+
+#else
+#error "Bad: you didn't configure serial ..."
+#endif
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+#ifdef CONFIG_FFUART
+ /* wait for room in the tx FIFO on FFUART */
+ while ((FFLSR & LSR_TEMT) == 0)
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ FFTHR = c;
+#elif defined(CONFIG_BTUART)
+ while ((BTLSR & LSR_TEMT ) == 0 )
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ BTTHR = c;
+#elif defined(CONFIG_STUART)
+ while ((STLSR & LSR_TEMT ) == 0 )
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ STTHR = c;
+#endif
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+#ifdef CONFIG_FFUART
+ return FFLSR & LSR_DR;
+#elif defined(CONFIG_BTUART)
+ return BTLSR & LSR_DR;
+#elif defined(CONFIG_STUART)
+ return STLSR & LSR_DR;
+#endif
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+#ifdef CONFIG_FFUART
+ while (!(FFLSR & LSR_DR))
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ return (char) FFRBR & 0xff;
+#elif defined(CONFIG_BTUART)
+ while (!(BTLSR & LSR_DR))
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ return (char) BTRBR & 0xff;
+#elif defined(CONFIG_STUART)
+ while (!(STLSR & LSR_DR))
+ WATCHDOG_RESET (); /* Reset HW Watchdog, if needed */
+ return (char) STRBR & 0xff;
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c
new file mode 100644
index 0000000000..52b07ad286
--- /dev/null
+++ b/drivers/serial/serial_s3c24x0.c
@@ -0,0 +1,166 @@
+/*
+ * (C) Copyright 2002
+ * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#if defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB)
+
+#if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB)
+#include <s3c2400.h>
+#elif defined(CONFIG_S3C2410)
+#include <s3c2410.h>
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifdef CONFIG_SERIAL1
+#define UART_NR S3C24X0_UART0
+
+#elif defined(CONFIG_SERIAL2)
+# if defined(CONFIG_TRAB)
+# error "TRAB supports only CONFIG_SERIAL1"
+# endif
+#define UART_NR S3C24X0_UART1
+
+#elif defined(CONFIG_SERIAL3)
+# if defined(CONFIG_TRAB)
+# #error "TRAB supports only CONFIG_SERIAL1"
+# endif
+#define UART_NR S3C24X0_UART2
+
+#else
+#error "Bad: you didn't configure serial ..."
+#endif
+
+void serial_setbrg (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+ int i;
+ unsigned int reg = 0;
+
+ /* value is calculated so : (int)(PCLK/16./baudrate) -1 */
+ reg = get_PCLK() / (16 * gd->baudrate) - 1;
+
+ /* FIFO enable, Tx/Rx FIFO clear */
+ uart->UFCON = 0x07;
+ uart->UMCON = 0x0;
+ /* Normal,No parity,1 stop,8 bit */
+ uart->ULCON = 0x3;
+ /*
+ * tx=level,rx=edge,disable timeout int.,enable rx error int.,
+ * normal,interrupt or polling
+ */
+ uart->UCON = 0x245;
+ uart->UBRDIV = reg;
+
+#ifdef CONFIG_HWFLOW
+ uart->UMCON = 0x1; /* RTS up */
+#endif
+ for (i = 0; i < 100; i++);
+}
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ /* wait for character to arrive */
+ while (!(uart->UTRSTAT & 0x1));
+
+ return uart->URXH & 0xff;
+}
+
+#ifdef CONFIG_HWFLOW
+static int hwflow = 0; /* turned off by default */
+int hwflow_onoff(int on)
+{
+ switch(on) {
+ case 0:
+ default:
+ break; /* return current */
+ case 1:
+ hwflow = 1; /* turn on */
+ break;
+ case -1:
+ hwflow = 0; /* turn off */
+ break;
+ }
+ return hwflow;
+}
+#endif
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ /* wait for room in the tx FIFO */
+ while (!(uart->UTRSTAT & 0x2));
+
+#ifdef CONFIG_HWFLOW
+ /* Wait for CTS up */
+ while(hwflow && !(uart->UMSTAT & 0x1))
+ ;
+#endif
+
+ uart->UTXH = c;
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+}
+
+/*
+ * Test whether a character is in the RX buffer
+ */
+int serial_tstc (void)
+{
+ S3C24X0_UART * const uart = S3C24X0_GetBase_UART(UART_NR);
+
+ return uart->UTRSTAT & 0x1;
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
+
+#endif /* defined(CONFIG_S3C2400) || defined (CONFIG_S3C2410) || defined (CONFIG_TRAB) */
diff --git a/drivers/serial/serial_s3c44b0.c b/drivers/serial/serial_s3c44b0.c
new file mode 100644
index 0000000000..95d0266c6c
--- /dev/null
+++ b/drivers/serial/serial_s3c44b0.c
@@ -0,0 +1,218 @@
+/*
+ * (C) Copyright 2004
+ * DAVE Srl
+ * http://www.dave-tech.it
+ * http://www.wawnet.biz
+ * mailto:info@wawnet.biz
+ *
+ * (C) Copyright 2002-2004
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <asm/hardware.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* flush serial input queue. returns 0 on success or negative error
+ * number otherwise
+ */
+static int serial_flush_input(void)
+{
+ volatile u32 tmp;
+
+ /* keep on reading as long as the receiver is not empty */
+ while(UTRSTAT0&0x01) {
+ tmp = REGB(URXH0);
+ }
+
+ return 0;
+}
+
+
+/* flush output queue. returns 0 on success or negative error number
+ * otherwise
+ */
+static int serial_flush_output(void)
+{
+ /* wait until the transmitter is no longer busy */
+ while(!(UTRSTAT0 & 0x02)) {
+ }
+
+ return 0;
+}
+
+
+void serial_setbrg (void)
+{
+ u32 divisor = 0;
+
+ /* get correct divisor */
+ switch(gd->baudrate) {
+
+ case 1200:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 3124;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 3905;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif
+ break;
+
+ case 9600:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 390;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 487;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif
+ break;
+
+ case 19200:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 194;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 243;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif
+ break;
+
+ case 38400:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 97;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 121;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif /* break; */
+
+ case 57600:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 64;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 80;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif /* break; */
+
+ case 115200:
+#if CONFIG_S3C44B0_CLOCK_SPEED==66
+ divisor = 32;
+#elif CONFIG_S3C44B0_CLOCK_SPEED==75
+ divisor = 40;
+#else
+# error CONFIG_S3C44B0_CLOCK_SPEED undefined
+#endif /* break; */
+ }
+
+ serial_flush_output();
+ serial_flush_input();
+ UFCON0 = 0x0;
+ ULCON0 = 0x03;
+ UCON0 = 0x05;
+ UBRDIV0 = divisor;
+
+ UFCON1 = 0x0;
+ ULCON1 = 0x03;
+ UCON1 = 0x05;
+ UBRDIV1 = divisor;
+
+ for(divisor=0; divisor<100; divisor++) {
+ /* NOP */
+ }
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+ /* wait for room in the transmit FIFO */
+ while(!(UTRSTAT0 & 0x02));
+
+ UTXH0 = (unsigned char)c;
+
+ /*
+ to be polite with serial console add a line feed
+ to the carriage return character
+ */
+ if (c=='\n')
+ serial_putc('\r');
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+ return (UTRSTAT0 & 0x01);
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+ int rv;
+
+ for(;;) {
+ rv = serial_tstc();
+
+ if(rv > 0)
+ return URXH0;
+ }
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}
diff --git a/drivers/serial/serial_sa1100.c b/drivers/serial/serial_sa1100.c
new file mode 100644
index 0000000000..5d1887580d
--- /dev/null
+++ b/drivers/serial/serial_sa1100.c
@@ -0,0 +1,160 @@
+/*
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.de>
+ *
+ * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <common.h>
+#include <SA-1100.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void serial_setbrg (void)
+{
+ unsigned int reg = 0;
+
+ if (gd->baudrate == 1200)
+ reg = 191;
+ else if (gd->baudrate == 9600)
+ reg = 23;
+ else if (gd->baudrate == 19200)
+ reg = 11;
+ else if (gd->baudrate == 38400)
+ reg = 5;
+ else if (gd->baudrate == 57600)
+ reg = 3;
+ else if (gd->baudrate == 115200)
+ reg = 1;
+ else
+ hang ();
+
+#ifdef CONFIG_SERIAL1
+ /* SA1110 uart function */
+ Ser1SDCR0 |= SDCR0_SUS;
+
+ /* Wait until port is ready ... */
+ while(Ser1UTSR1 & UTSR1_TBY) {}
+
+ /* init serial serial 1 */
+ Ser1UTCR3 = 0x00;
+ Ser1UTSR0 = 0xff;
+ Ser1UTCR0 = ( UTCR0_1StpBit | UTCR0_8BitData );
+ Ser1UTCR1 = 0;
+ Ser1UTCR2 = (u32)reg;
+ Ser1UTCR3 = ( UTCR3_RXE | UTCR3_TXE );
+#elif defined(CONFIG_SERIAL3)
+ /* Wait until port is ready ... */
+ while (Ser3UTSR1 & UTSR1_TBY) {
+ }
+
+ /* init serial serial 3 */
+ Ser3UTCR3 = 0x00;
+ Ser3UTSR0 = 0xff;
+ Ser3UTCR0 = (UTCR0_1StpBit | UTCR0_8BitData);
+ Ser3UTCR1 = 0;
+ Ser3UTCR2 = (u32) reg;
+ Ser3UTCR3 = (UTCR3_RXE | UTCR3_TXE);
+#else
+#error "Bad: you didn't configured serial ..."
+#endif
+}
+
+
+/*
+ * Initialise the serial port with the given baudrate. The settings
+ * are always 8 data bits, no parity, 1 stop bit, no start bits.
+ *
+ */
+int serial_init (void)
+{
+ serial_setbrg ();
+
+ return (0);
+}
+
+
+/*
+ * Output a single byte to the serial port.
+ */
+void serial_putc (const char c)
+{
+#ifdef CONFIG_SERIAL1
+ /* wait for room in the tx FIFO on SERIAL1 */
+ while ((Ser1UTSR0 & UTSR0_TFS) == 0);
+
+ Ser1UTDR = c;
+#elif defined(CONFIG_SERIAL3)
+ /* wait for room in the tx FIFO on SERIAL3 */
+ while ((Ser3UTSR0 & UTSR0_TFS) == 0);
+
+ Ser3UTDR = c;
+#endif
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ serial_putc ('\r');
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_tstc (void)
+{
+#ifdef CONFIG_SERIAL1
+ return Ser1UTSR1 & UTSR1_RNE;
+#elif defined(CONFIG_SERIAL3)
+ return Ser3UTSR1 & UTSR1_RNE;
+#endif
+}
+
+/*
+ * Read a single byte from the serial port. Returns 1 on success, 0
+ * otherwise. When the function is succesfull, the character read is
+ * written into its argument c.
+ */
+int serial_getc (void)
+{
+#ifdef CONFIG_SERIAL1
+ while (!(Ser1UTSR1 & UTSR1_RNE));
+
+ return (char) Ser1UTDR & 0xff;
+#elif defined(CONFIG_SERIAL3)
+ while (!(Ser3UTSR1 & UTSR1_RNE));
+
+ return (char) Ser3UTDR & 0xff;
+#endif
+}
+
+void
+serial_puts (const char *s)
+{
+ while (*s) {
+ serial_putc (*s++);
+ }
+}