Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/drivers/serial/cpm_uart/Makefile b/drivers/serial/cpm_uart/Makefile
new file mode 100644
index 0000000..e072724
--- /dev/null
+++ b/drivers/serial/cpm_uart/Makefile
@@ -0,0 +1,11 @@
+#
+# Makefile for the Motorola 8xx FEC ethernet controller
+#
+
+obj-$(CONFIG_SERIAL_CPM) += cpm_uart.o
+
+# Select the correct platform objects.
+cpm_uart-objs-$(CONFIG_CPM2)	+= cpm_uart_cpm2.o
+cpm_uart-objs-$(CONFIG_8xx)	+= cpm_uart_cpm1.o
+
+cpm_uart-objs	:= cpm_uart_core.o $(cpm_uart-objs-y)
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h
new file mode 100644
index 0000000..5f6187b
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -0,0 +1,89 @@
+/*
+ *  linux/drivers/serial/cpm_uart.h
+ *
+ *  Driver for CPM (SCC/SMC) serial ports
+ *
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *
+ */
+#ifndef CPM_UART_H
+#define CPM_UART_H
+
+#include <linux/config.h>
+
+#if defined(CONFIG_CPM2)
+#include "cpm_uart_cpm2.h"
+#elif defined(CONFIG_8xx)
+#include "cpm_uart_cpm1.h"
+#endif
+
+#define SERIAL_CPM_MAJOR	204
+#define SERIAL_CPM_MINOR	46
+
+#define IS_SMC(pinfo) 		(pinfo->flags & FLAG_SMC)
+#define IS_DISCARDING(pinfo)	(pinfo->flags & FLAG_DISCARDING)
+#define FLAG_DISCARDING	0x00000004	/* when set, don't discard */
+#define FLAG_SMC	0x00000002
+#define FLAG_CONSOLE	0x00000001
+
+#define UART_SMC1	0
+#define UART_SMC2	1
+#define UART_SCC1	2
+#define UART_SCC2	3
+#define UART_SCC3	4
+#define UART_SCC4	5
+
+#define UART_NR	6
+
+#define RX_NUM_FIFO	4
+#define RX_BUF_SIZE	32
+#define TX_NUM_FIFO	4
+#define TX_BUF_SIZE	32
+
+struct uart_cpm_port {
+	struct uart_port	port;
+	u16			rx_nrfifos;	
+	u16			rx_fifosize;
+	u16			tx_nrfifos;	
+	u16			tx_fifosize;
+	smc_t			*smcp;	
+	smc_uart_t		*smcup;
+	scc_t			*sccp;
+	scc_uart_t		*sccup;
+	volatile cbd_t		*rx_bd_base;
+	volatile cbd_t		*rx_cur;
+	volatile cbd_t		*tx_bd_base;
+	volatile cbd_t		*tx_cur;
+	unsigned char		*tx_buf;
+	unsigned char		*rx_buf;
+	u32			flags;
+	void			(*set_lineif)(struct uart_cpm_port *);
+	u8			brg;
+	uint			 dp_addr;
+	void			*mem_addr;
+	dma_addr_t		 dma_addr;
+	/* helpers */
+	int			 baud;
+	int			 bits;
+	/* Keep track of 'odd' SMC2 wirings */
+	int			is_portb;
+};
+
+extern int cpm_uart_port_map[UART_NR];
+extern int cpm_uart_nr;
+extern struct uart_cpm_port cpm_uart_ports[UART_NR];
+
+/* these are located in their respective files */
+void cpm_line_cr_cmd(int line, int cmd);
+int cpm_uart_init_portdesc(void);
+int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
+void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
+
+void smc1_lineif(struct uart_cpm_port *pinfo);
+void smc2_lineif(struct uart_cpm_port *pinfo);
+void scc1_lineif(struct uart_cpm_port *pinfo);
+void scc2_lineif(struct uart_cpm_port *pinfo);
+void scc3_lineif(struct uart_cpm_port *pinfo);
+void scc4_lineif(struct uart_cpm_port *pinfo);
+
+#endif /* CPM_UART_H */
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
new file mode 100644
index 0000000..29db677
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -0,0 +1,1177 @@
+/*
+ *  linux/drivers/serial/cpm_uart.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; core driver
+ *
+ *  Based on arch/ppc/cpm2_io/uart.c by Dan Malek
+ *  Based on ppc8xx.c by Thomas Gleixner
+ *  Based on drivers/serial/amba.c by Russell King
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+
+#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/***********************************************************************/
+
+/* Track which ports are configured as uarts */
+int cpm_uart_port_map[UART_NR];
+/* How many ports did we config as uarts */
+int cpm_uart_nr;
+
+/**************************************************************/
+
+static int  cpm_uart_tx_pump(struct uart_port *port);
+static void cpm_uart_init_smc(struct uart_cpm_port *pinfo);
+static void cpm_uart_init_scc(struct uart_cpm_port *pinfo);
+static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
+
+/**************************************************************/
+
+/*
+ * Check, if transmit buffers are processed		
+*/
+static unsigned int cpm_uart_tx_empty(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile cbd_t *bdp = pinfo->tx_bd_base;
+	int ret = 0;
+
+	while (1) {
+		if (bdp->cbd_sc & BD_SC_READY)
+			break;
+
+		if (bdp->cbd_sc & BD_SC_WRAP) {
+			ret = TIOCSER_TEMT;
+			break;
+		}
+		bdp++;
+	}
+
+	pr_debug("CPM uart[%d]:tx_empty: %d\n", port->line, ret);
+
+	return ret;
+}
+
+static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	/* Whee. Do nothing. */
+}
+
+static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
+{
+	/* Whee. Do nothing. */
+	return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/*
+ * Stop transmitter
+ */
+static void cpm_uart_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile smc_t *smcp = pinfo->smcp;
+	volatile scc_t *sccp = pinfo->sccp;
+
+	pr_debug("CPM uart[%d]:stop tx\n", port->line);
+
+	if (IS_SMC(pinfo))
+		smcp->smc_smcm &= ~SMCM_TX;
+	else
+		sccp->scc_sccm &= ~UART_SCCM_TX;
+}
+
+/*
+ * Start transmitter
+ */
+static void cpm_uart_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile smc_t *smcp = pinfo->smcp;
+	volatile scc_t *sccp = pinfo->sccp;
+
+	pr_debug("CPM uart[%d]:start tx\n", port->line);
+
+	if (IS_SMC(pinfo)) {
+		if (smcp->smc_smcm & SMCM_TX)
+			return;
+	} else {
+		if (sccp->scc_sccm & UART_SCCM_TX)
+			return;
+	}
+
+	if (cpm_uart_tx_pump(port) != 0) {
+		if (IS_SMC(pinfo))
+			smcp->smc_smcm |= SMCM_TX;
+		else
+			sccp->scc_sccm |= UART_SCCM_TX;
+	}
+}
+
+/*
+ * Stop receiver 
+ */
+static void cpm_uart_stop_rx(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile smc_t *smcp = pinfo->smcp;
+	volatile scc_t *sccp = pinfo->sccp;
+
+	pr_debug("CPM uart[%d]:stop rx\n", port->line);
+
+	if (IS_SMC(pinfo))
+		smcp->smc_smcm &= ~SMCM_RX;
+	else
+		sccp->scc_sccm &= ~UART_SCCM_RX;
+}
+
+/*
+ * Enable Modem status interrupts
+ */
+static void cpm_uart_enable_ms(struct uart_port *port)
+{
+	pr_debug("CPM uart[%d]:enable ms\n", port->line);
+}
+
+/*
+ * Generate a break. 
+ */
+static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	int line = pinfo - cpm_uart_ports;
+
+	pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
+		break_state);
+
+	if (break_state)
+		cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+	else
+		cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
+}
+
+/*
+ * Transmit characters, refill buffer descriptor, if possible
+ */
+static void cpm_uart_int_tx(struct uart_port *port, struct pt_regs *regs)
+{
+	pr_debug("CPM uart[%d]:TX INT\n", port->line);
+
+	cpm_uart_tx_pump(port);
+}
+
+/*
+ * Receive characters
+ */
+static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
+{
+	int i;
+	unsigned char ch, *cp;
+	struct tty_struct *tty = port->info->tty;
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile cbd_t *bdp;
+	u16 status;
+	unsigned int flg;
+
+	pr_debug("CPM uart[%d]:RX INT\n", port->line);
+
+	/* Just loop through the closed BDs and copy the characters into
+	 * the buffer.
+	 */
+	bdp = pinfo->rx_cur;
+	for (;;) {
+		/* get status */
+		status = bdp->cbd_sc;
+		/* If this one is empty, return happy */
+		if (status & BD_SC_EMPTY)
+			break;
+
+		/* get number of characters, and check spce in flip-buffer */
+		i = bdp->cbd_datlen;
+
+		/* If we have not enough room in tty flip buffer, then we try 
+		 * later, which will be the next rx-interrupt or a timeout
+		 */
+		if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
+			tty->flip.work.func((void *)tty);
+			if ((tty->flip.count + i) >= TTY_FLIPBUF_SIZE) {
+				printk(KERN_WARNING "TTY_DONT_FLIP set\n");
+				return;
+			}
+		}
+
+		/* get pointer */
+		cp = (unsigned char *)bus_to_virt(bdp->cbd_bufaddr);
+
+		/* loop through the buffer */
+		while (i-- > 0) {
+			ch = *cp++;
+			port->icount.rx++;
+			flg = TTY_NORMAL;
+
+			if (status &
+			    (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
+				goto handle_error;
+			if (uart_handle_sysrq_char(port, ch, regs))
+				continue;
+
+		      error_return:
+			*tty->flip.char_buf_ptr++ = ch;
+			*tty->flip.flag_buf_ptr++ = flg;
+			tty->flip.count++;
+
+		}		/* End while (i--) */
+
+		/* This BD is ready to be used again. Clear status. get next */
+		bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV);
+		bdp->cbd_sc |= BD_SC_EMPTY;
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = pinfo->rx_bd_base;
+		else
+			bdp++;
+	} /* End for (;;) */
+
+	/* Write back buffer pointer */
+	pinfo->rx_cur = (volatile cbd_t *) bdp;
+
+	/* activate BH processing */
+	tty_flip_buffer_push(tty);
+
+	return;
+
+	/* Error processing */
+
+      handle_error:
+	/* Statistics */
+	if (status & BD_SC_BR)
+		port->icount.brk++;
+	if (status & BD_SC_PR)
+		port->icount.parity++;
+	if (status & BD_SC_FR)
+		port->icount.frame++;
+	if (status & BD_SC_OV)
+		port->icount.overrun++;
+
+	/* Mask out ignored conditions */
+	status &= port->read_status_mask;
+
+	/* Handle the remaining ones */
+	if (status & BD_SC_BR)
+		flg = TTY_BREAK;
+	else if (status & BD_SC_PR)
+		flg = TTY_PARITY;
+	else if (status & BD_SC_FR)
+		flg = TTY_FRAME;
+
+	/* overrun does not affect the current character ! */
+	if (status & BD_SC_OV) {
+		ch = 0;
+		flg = TTY_OVERRUN;
+		/* We skip this buffer */
+		/* CHECK: Is really nothing senseful there */
+		/* ASSUMPTION: it contains nothing valid */
+		i = 0;
+	}
+#ifdef SUPPORT_SYSRQ
+	port->sysrq = 0;
+#endif
+	goto error_return;
+}
+
+/*
+ * Asynchron mode interrupt handler
+ */
+static irqreturn_t cpm_uart_int(int irq, void *data, struct pt_regs *regs)
+{
+	u8 events;
+	struct uart_port *port = (struct uart_port *)data;
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile smc_t *smcp = pinfo->smcp;
+	volatile scc_t *sccp = pinfo->sccp;
+
+	pr_debug("CPM uart[%d]:IRQ\n", port->line);
+
+	if (IS_SMC(pinfo)) {
+		events = smcp->smc_smce;
+		if (events & SMCM_BRKE)
+			uart_handle_break(port);
+		if (events & SMCM_RX)
+			cpm_uart_int_rx(port, regs);
+		if (events & SMCM_TX)
+			cpm_uart_int_tx(port, regs);
+		smcp->smc_smce = events;
+	} else {
+		events = sccp->scc_scce;
+		if (events & UART_SCCM_BRKE)
+			uart_handle_break(port);
+		if (events & UART_SCCM_RX)
+			cpm_uart_int_rx(port, regs);
+		if (events & UART_SCCM_TX)
+			cpm_uart_int_tx(port, regs);
+		sccp->scc_scce = events;
+	}
+	return (events) ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int cpm_uart_startup(struct uart_port *port)
+{
+	int retval;
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+	pr_debug("CPM uart[%d]:startup\n", port->line);
+
+	/* Install interrupt handler. */
+	retval = request_irq(port->irq, cpm_uart_int, 0, "cpm_uart", port);
+	if (retval)
+		return retval;
+
+	/* Startup rx-int */
+	if (IS_SMC(pinfo)) {
+		pinfo->smcp->smc_smcm |= SMCM_RX;
+		pinfo->smcp->smc_smcmr |= SMCMR_REN;
+	} else {
+		pinfo->sccp->scc_sccm |= UART_SCCM_RX;
+	}
+
+	return 0;
+}
+
+/*
+ * Shutdown the uart
+ */
+static void cpm_uart_shutdown(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	int line = pinfo - cpm_uart_ports;
+
+	pr_debug("CPM uart[%d]:shutdown\n", port->line);
+
+	/* free interrupt handler */
+	free_irq(port->irq, port);
+
+	/* If the port is not the console, disable Rx and Tx. */
+	if (!(pinfo->flags & FLAG_CONSOLE)) {
+		/* Stop uarts */
+		if (IS_SMC(pinfo)) {
+			volatile smc_t *smcp = pinfo->smcp;
+			smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+			smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+		} else {
+			volatile scc_t *sccp = pinfo->sccp;
+			sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+			sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+		}
+
+		/* Shut them really down and reinit buffer descriptors */
+		cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+		cpm_uart_initbd(pinfo);
+	}
+}
+
+static void cpm_uart_set_termios(struct uart_port *port,
+				 struct termios *termios, struct termios *old)
+{
+	int baud;
+	unsigned long flags;
+	u16 cval, scval, prev_mode;
+	int bits, sbits;
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	volatile smc_t *smcp = pinfo->smcp;
+	volatile scc_t *sccp = pinfo->sccp;
+
+	pr_debug("CPM uart[%d]:set_termios\n", port->line);
+
+	baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+
+	/* Character length programmed into the mode register is the
+	 * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+	 * 1 or 2 stop bits, minus 1.
+	 * The value 'bits' counts this for us.
+	 */
+	cval = 0;
+	scval = 0;
+
+	/* byte size */
+	switch (termios->c_cflag & CSIZE) {
+	case CS5:
+		bits = 5;
+		break;
+	case CS6:
+		bits = 6;
+		break;
+	case CS7:
+		bits = 7;
+		break;
+	case CS8:
+		bits = 8;
+		break;
+		/* Never happens, but GCC is too dumb to figure it out */
+	default:
+		bits = 8;
+		break;
+	}
+	sbits = bits - 5;
+
+	if (termios->c_cflag & CSTOPB) {
+		cval |= SMCMR_SL;	/* Two stops */
+		scval |= SCU_PSMR_SL;
+		bits++;
+	}
+
+	if (termios->c_cflag & PARENB) {
+		cval |= SMCMR_PEN;
+		scval |= SCU_PSMR_PEN;
+		bits++;
+		if (!(termios->c_cflag & PARODD)) {
+			cval |= SMCMR_PM_EVEN;
+			scval |= (SCU_PSMR_REVP | SCU_PSMR_TEVP);
+		}
+	}
+
+	/*
+	 * Set up parity check flag
+	 */
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+	port->read_status_mask = (BD_SC_EMPTY | BD_SC_OV);
+	if (termios->c_iflag & INPCK)
+		port->read_status_mask |= BD_SC_FR | BD_SC_PR;
+	if ((termios->c_iflag & BRKINT) || (termios->c_iflag & PARMRK))
+		port->read_status_mask |= BD_SC_BR;
+
+	/*
+	 * Characters to ignore
+	 */
+	port->ignore_status_mask = 0;
+	if (termios->c_iflag & IGNPAR)
+		port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+	if (termios->c_iflag & IGNBRK) {
+		port->ignore_status_mask |= BD_SC_BR;
+		/*
+		 * If we're ignore parity and break indicators, ignore
+		 * overruns too.  (For real raw support).
+		 */
+		if (termios->c_iflag & IGNPAR)
+			port->ignore_status_mask |= BD_SC_OV;
+	}
+	/*
+	 * !!! ignore all characters if CREAD is not set
+	 */
+	if ((termios->c_cflag & CREAD) == 0)
+		port->read_status_mask &= ~BD_SC_EMPTY;
+	
+	spin_lock_irqsave(&port->lock, flags);
+
+	/* Start bit has not been added (so don't, because we would just
+	 * subtract it later), and we need to add one for the number of
+	 * stops bits (there is always at least one).
+	 */
+	bits++;
+	if (IS_SMC(pinfo)) {
+		/* Set the mode register.  We want to keep a copy of the
+		 * enables, because we want to put them back if they were
+		 * present.
+		 */
+		prev_mode = smcp->smc_smcmr;
+		smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
+		smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
+	} else {
+		sccp->scc_psmr = (sbits << 12) | scval;
+	}
+
+	cpm_set_brg(pinfo->brg - 1, baud);
+	spin_unlock_irqrestore(&port->lock, flags);
+
+}
+
+static const char *cpm_uart_type(struct uart_port *port)
+{
+	pr_debug("CPM uart[%d]:uart_type\n", port->line);
+
+	return port->type == PORT_CPM ? "CPM UART" : NULL;
+}
+
+/*
+ * verify the new serial_struct (for TIOCSSERIAL).
+ */
+static int cpm_uart_verify_port(struct uart_port *port,
+				struct serial_struct *ser)
+{
+	int ret = 0;
+
+	pr_debug("CPM uart[%d]:verify_port\n", port->line);
+
+	if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
+		ret = -EINVAL;
+	if (ser->irq < 0 || ser->irq >= NR_IRQS)
+		ret = -EINVAL;
+	if (ser->baud_base < 9600)
+		ret = -EINVAL;
+	return ret;
+}
+
+/*
+ * Transmit characters, refill buffer descriptor, if possible
+ */
+static int cpm_uart_tx_pump(struct uart_port *port)
+{
+	volatile cbd_t *bdp;
+	unsigned char *p;
+	int count;
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	struct circ_buf *xmit = &port->info->xmit;
+
+	/* Handle xon/xoff */
+	if (port->x_char) {
+		/* Pick next descriptor and fill from buffer */
+		bdp = pinfo->tx_cur;
+
+		p = bus_to_virt(bdp->cbd_bufaddr);
+		*p++ = xmit->buf[xmit->tail];
+		bdp->cbd_datlen = 1;
+		bdp->cbd_sc |= BD_SC_READY;
+		/* Get next BD. */
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = pinfo->tx_bd_base;
+		else
+			bdp++;
+		pinfo->tx_cur = bdp;
+
+		port->icount.tx++;
+		port->x_char = 0;
+		return 1;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		cpm_uart_stop_tx(port, 0);
+		return 0;
+	}
+
+	/* Pick next descriptor and fill from buffer */
+	bdp = pinfo->tx_cur;
+
+	while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
+		count = 0;
+		p = bus_to_virt(bdp->cbd_bufaddr);
+		while (count < pinfo->tx_fifosize) {
+			*p++ = xmit->buf[xmit->tail];
+			xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+			port->icount.tx++;
+			count++;
+			if (xmit->head == xmit->tail)
+				break;
+		}
+		bdp->cbd_datlen = count;
+		bdp->cbd_sc |= BD_SC_READY;
+		/* Get next BD. */
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = pinfo->tx_bd_base;
+		else
+			bdp++;
+	}
+	pinfo->tx_cur = bdp;
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit)) {
+		cpm_uart_stop_tx(port, 0);
+		return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * init buffer descriptors
+ */
+static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
+{
+	int i;
+	u8 *mem_addr;
+	volatile cbd_t *bdp;
+
+	pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
+
+	/* Set the physical address of the host memory
+	 * buffers in the buffer descriptors, and the
+	 * virtual address for us to work with.
+	 */
+	mem_addr = pinfo->mem_addr;
+	bdp = pinfo->rx_cur = pinfo->rx_bd_base;
+	for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
+		bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+		bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+		mem_addr += pinfo->rx_fifosize;
+	}
+	
+	bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+	bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+
+	/* Set the physical address of the host memory
+	 * buffers in the buffer descriptors, and the
+	 * virtual address for us to work with.
+	 */
+	mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
+	bdp = pinfo->tx_cur = pinfo->tx_bd_base;
+	for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
+		bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+		bdp->cbd_sc = BD_SC_INTRPT;
+		mem_addr += pinfo->tx_fifosize;
+	}
+	
+	bdp->cbd_bufaddr = virt_to_bus(mem_addr);
+	bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
+}
+
+static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
+{
+	int line = pinfo - cpm_uart_ports;
+	volatile scc_t *scp;
+	volatile scc_uart_t *sup;
+
+	pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
+
+	scp = pinfo->sccp;
+	sup = pinfo->sccup;
+
+	/* Store address */
+	pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
+	pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
+
+	/* Set up the uart parameters in the
+	 * parameter ram.
+	 */
+
+	cpm_set_scc_fcr(sup);
+
+	sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
+	sup->scc_maxidl = pinfo->rx_fifosize;
+	sup->scc_brkcr = 1;
+	sup->scc_parec = 0;
+	sup->scc_frmec = 0;
+	sup->scc_nosec = 0;
+	sup->scc_brkec = 0;
+	sup->scc_uaddr1 = 0;
+	sup->scc_uaddr2 = 0;
+	sup->scc_toseq = 0;
+	sup->scc_char1 = 0x8000;
+	sup->scc_char2 = 0x8000;
+	sup->scc_char3 = 0x8000;
+	sup->scc_char4 = 0x8000;
+	sup->scc_char5 = 0x8000;
+	sup->scc_char6 = 0x8000;
+	sup->scc_char7 = 0x8000;
+	sup->scc_char8 = 0x8000;
+	sup->scc_rccm = 0xc0ff;
+
+	/* Send the CPM an initialize command.
+	 */
+	cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	scp->scc_gsmrh = 0;
+	scp->scc_gsmrl =
+	    (SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
+
+	/* Enable rx interrupts  and clear all pending events.  */
+	scp->scc_sccm = 0;
+	scp->scc_scce = 0xffff;
+	scp->scc_dsr = 0x7e7e;
+	scp->scc_psmr = 0x3000;
+
+	scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+}
+
+static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
+{
+	int line = pinfo - cpm_uart_ports;
+	volatile smc_t *sp;
+	volatile smc_uart_t *up;
+
+	pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
+
+	sp = pinfo->smcp;
+	up = pinfo->smcup;
+
+	/* Store address */
+	pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;
+	pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;
+
+/*
+ *  In case SMC1 is being relocated...
+ */
+#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
+	up->smc_rbptr = pinfo->smcup->smc_rbase;
+	up->smc_tbptr = pinfo->smcup->smc_tbase;
+	up->smc_rstate = 0;
+	up->smc_tstate = 0;
+	up->smc_brkcr = 1;              /* number of break chars */
+	up->smc_brkec = 0;
+#endif
+
+	/* Set up the uart parameters in the
+	 * parameter ram.
+	 */
+	cpm_set_smc_fcr(up);
+
+	/* Using idle charater time requires some additional tuning.  */
+	up->smc_mrblr = pinfo->rx_fifosize;
+	up->smc_maxidl = pinfo->rx_fifosize;
+	up->smc_brkcr = 1;
+
+	cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+
+	/* Set UART mode, 8 bit, no parity, one stop.
+	 * Enable receive and transmit.
+	 */
+	sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
+
+	/* Enable only rx interrupts clear all pending events. */
+	sp->smc_smcm = 0;
+	sp->smc_smce = 0xff;
+
+	sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+}
+
+/*
+ * Initialize port. This is called from early_console stuff
+ * so we have to be careful here !
+ */
+static int cpm_uart_request_port(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+	int ret;
+
+	pr_debug("CPM uart[%d]:request port\n", port->line);
+
+	if (pinfo->flags & FLAG_CONSOLE)
+		return 0;
+
+	/*
+	 * Setup any port IO, connect any baud rate generators,
+	 * etc.  This is expected to be handled by board
+	 * dependant code 
+	 */
+	if (pinfo->set_lineif)
+		pinfo->set_lineif(pinfo);
+
+	if (IS_SMC(pinfo)) {
+		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	} else {
+		pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+		pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	}
+
+	ret = cpm_uart_allocbuf(pinfo, 0);
+
+	if (ret)
+		return ret;
+
+	cpm_uart_initbd(pinfo);
+
+	return 0;
+}
+
+static void cpm_uart_release_port(struct uart_port *port)
+{
+	struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+	if (!(pinfo->flags & FLAG_CONSOLE))
+		cpm_uart_freebuf(pinfo);
+}
+
+/*
+ * Configure/autoconfigure the port.
+ */
+static void cpm_uart_config_port(struct uart_port *port, int flags)
+{
+	pr_debug("CPM uart[%d]:config_port\n", port->line);
+
+	if (flags & UART_CONFIG_TYPE) {
+		port->type = PORT_CPM;
+		cpm_uart_request_port(port);
+	}
+}
+static struct uart_ops cpm_uart_pops = {
+	.tx_empty	= cpm_uart_tx_empty,
+	.set_mctrl	= cpm_uart_set_mctrl,
+	.get_mctrl	= cpm_uart_get_mctrl,
+	.stop_tx	= cpm_uart_stop_tx,
+	.start_tx	= cpm_uart_start_tx,
+	.stop_rx	= cpm_uart_stop_rx,
+	.enable_ms	= cpm_uart_enable_ms,
+	.break_ctl	= cpm_uart_break_ctl,
+	.startup	= cpm_uart_startup,
+	.shutdown	= cpm_uart_shutdown,
+	.set_termios	= cpm_uart_set_termios,
+	.type		= cpm_uart_type,
+	.release_port	= cpm_uart_release_port,
+	.request_port	= cpm_uart_request_port,
+	.config_port	= cpm_uart_config_port,
+	.verify_port	= cpm_uart_verify_port,
+};
+
+struct uart_cpm_port cpm_uart_ports[UART_NR] = {
+	[UART_SMC1] = {
+		.port = {
+			.irq		= SMC1_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.flags = FLAG_SMC,
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = smc1_lineif,
+	},
+	[UART_SMC2] = {
+		.port = {
+			.irq		= SMC2_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.flags = FLAG_SMC,
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = smc2_lineif,
+#ifdef CONFIG_SERIAL_CPM_ALT_SMC2
+		.is_portb = 1,
+#endif
+	},
+	[UART_SCC1] = {
+		.port = {
+			.irq		= SCC1_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = scc1_lineif,
+	},
+	[UART_SCC2] = {
+		.port = {
+			.irq		= SCC2_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = scc2_lineif,
+	},
+	[UART_SCC3] = {
+		.port = {
+			.irq		= SCC3_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = scc3_lineif,
+	},
+	[UART_SCC4] = {
+		.port = {
+			.irq		= SCC4_IRQ,
+			.ops		= &cpm_uart_pops,
+			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
+		},
+		.tx_nrfifos = TX_NUM_FIFO,
+		.tx_fifosize = TX_BUF_SIZE,
+		.rx_nrfifos = RX_NUM_FIFO, 
+		.rx_fifosize = RX_BUF_SIZE,
+		.set_lineif = scc4_lineif,
+	},
+};
+
+#ifdef CONFIG_SERIAL_CPM_CONSOLE
+/*
+ *	Print a string to the serial port trying not to disturb
+ *	any possible real use of the port...
+ *
+ *	Note that this is called with interrupts already disabled
+ */
+static void cpm_uart_console_write(struct console *co, const char *s,
+				   u_int count)
+{
+	struct uart_cpm_port *pinfo =
+	    &cpm_uart_ports[cpm_uart_port_map[co->index]];
+	unsigned int i;
+	volatile cbd_t *bdp, *bdbase;
+	volatile unsigned char *cp;
+
+	/* Get the address of the host memory buffer.
+	 */
+	bdp = pinfo->tx_cur;
+	bdbase = pinfo->tx_bd_base;
+
+	/*
+	 * Now, do each character.  This is not as bad as it looks
+	 * since this is a holding FIFO and not a transmitting FIFO.
+	 * We could add the complexity of filling the entire transmit
+	 * buffer, but we would just wait longer between accesses......
+	 */
+	for (i = 0; i < count; i++, s++) {
+		/* Wait for transmitter fifo to empty.
+		 * Ready indicates output is ready, and xmt is doing
+		 * that, not that it is ready for us to send.
+		 */
+		while ((bdp->cbd_sc & BD_SC_READY) != 0)
+			;
+
+		/* Send the character out.
+		 * If the buffer address is in the CPM DPRAM, don't
+		 * convert it.
+		 */
+		if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
+			cp = (unsigned char *) (bdp->cbd_bufaddr);
+		else
+			cp = bus_to_virt(bdp->cbd_bufaddr);
+		
+		*cp = *s;
+
+		bdp->cbd_datlen = 1;
+		bdp->cbd_sc |= BD_SC_READY;
+
+		if (bdp->cbd_sc & BD_SC_WRAP)
+			bdp = bdbase;
+		else
+			bdp++;
+
+		/* if a LF, also do CR... */
+		if (*s == 10) {
+			while ((bdp->cbd_sc & BD_SC_READY) != 0)
+				;
+
+			if ((uint) (bdp->cbd_bufaddr) > (uint) CPM_ADDR)
+				cp = (unsigned char *) (bdp->cbd_bufaddr);
+			else
+				cp = bus_to_virt(bdp->cbd_bufaddr);
+
+			*cp = 13;
+			bdp->cbd_datlen = 1;
+			bdp->cbd_sc |= BD_SC_READY;
+
+			if (bdp->cbd_sc & BD_SC_WRAP)
+				bdp = bdbase;
+			else
+				bdp++;
+		}
+	}
+
+	/*
+	 * Finally, Wait for transmitter & holding register to empty
+	 *  and restore the IER
+	 */
+	while ((bdp->cbd_sc & BD_SC_READY) != 0)
+		;
+
+	pinfo->tx_cur = (volatile cbd_t *) bdp;
+}
+
+/*
+ * Setup console. Be careful is called early !
+ */
+static int __init cpm_uart_console_setup(struct console *co, char *options)
+{
+	struct uart_port *port;
+	struct uart_cpm_port *pinfo;
+	int baud = 38400;
+	int bits = 8;
+	int parity = 'n';
+	int flow = 'n';
+	int ret;
+
+	port =
+	    (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
+	pinfo = (struct uart_cpm_port *)port;
+	
+	pinfo->flags |= FLAG_CONSOLE;
+
+	if (options) {
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+	} else {
+		bd_t *bd = (bd_t *) __res;
+
+		if (bd->bi_baudrate)
+			baud = bd->bi_baudrate;
+		else
+			baud = 9600;
+	}
+
+	/*
+	 * Setup any port IO, connect any baud rate generators,
+	 * etc.  This is expected to be handled by board
+	 * dependant code 
+	 */
+	if (pinfo->set_lineif)
+		pinfo->set_lineif(pinfo);
+
+	if (IS_SMC(pinfo)) {
+		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
+		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	} else {
+		pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
+		pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	}
+
+	ret = cpm_uart_allocbuf(pinfo, 1);
+
+	if (ret)
+		return ret;
+
+	cpm_uart_initbd(pinfo);
+
+	if (IS_SMC(pinfo))
+		cpm_uart_init_smc(pinfo);
+	else
+		cpm_uart_init_scc(pinfo);
+
+	uart_set_options(port, co, baud, parity, bits, flow);
+
+	return 0;
+}
+
+extern struct uart_driver cpm_reg;
+static struct console cpm_scc_uart_console = {
+	.name		"ttyCPM",
+	.write		cpm_uart_console_write,
+	.device		uart_console_device,
+	.setup		cpm_uart_console_setup,
+	.flags		CON_PRINTBUFFER,
+	.index		-1,
+	.data		= &cpm_reg,
+};
+
+int __init cpm_uart_console_init(void)
+{
+	int ret = cpm_uart_init_portdesc();
+
+	if (!ret)
+		register_console(&cpm_scc_uart_console);
+	return ret;
+}
+
+console_initcall(cpm_uart_console_init);
+
+#define CPM_UART_CONSOLE	&cpm_scc_uart_console
+#else
+#define CPM_UART_CONSOLE	NULL
+#endif
+
+static struct uart_driver cpm_reg = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "ttyCPM",
+	.dev_name	= "ttyCPM",
+	.major		= SERIAL_CPM_MAJOR,
+	.minor		= SERIAL_CPM_MINOR,
+	.cons		= CPM_UART_CONSOLE,
+};
+
+static int __init cpm_uart_init(void)
+{
+	int ret, i;
+
+	printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");
+
+#ifndef CONFIG_SERIAL_CPM_CONSOLE
+	ret = cpm_uart_init_portdesc();
+	if (ret)
+		return ret;
+#endif
+
+	cpm_reg.nr = cpm_uart_nr;
+	ret = uart_register_driver(&cpm_reg);
+
+	if (ret)
+		return ret;
+
+	for (i = 0; i < cpm_uart_nr; i++) {
+		int con = cpm_uart_port_map[i];
+		cpm_uart_ports[con].port.line = i;
+		cpm_uart_ports[con].port.flags = UPF_BOOT_AUTOCONF;
+		uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+	}
+
+	return ret;
+}
+
+static void __exit cpm_uart_exit(void)
+{
+	int i;
+
+	for (i = 0; i < cpm_uart_nr; i++) {
+		int con = cpm_uart_port_map[i];
+		uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
+	}
+
+	uart_unregister_driver(&cpm_reg);
+}
+
+module_init(cpm_uart_init);
+module_exit(cpm_uart_exit);
+
+MODULE_AUTHOR("Kumar Gala/Antoniou Pantelis");
+MODULE_DESCRIPTION("CPM SCC/SMC port driver $Revision: 0.01 $");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV(SERIAL_CPM_MAJOR, SERIAL_CPM_MINOR);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
new file mode 100644
index 0000000..de26cf7
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -0,0 +1,290 @@
+/*
+ *  linux/drivers/serial/cpm_uart.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; CPM1 definitions
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/**************************************************************/
+
+void cpm_line_cr_cmd(int line, int cmd)
+{
+	ushort val;
+	volatile cpm8xx_t *cp = cpmp;
+
+	switch (line) {
+	case UART_SMC1:
+		val = mk_cr_cmd(CPM_CR_CH_SMC1, cmd) | CPM_CR_FLG;
+		break;
+	case UART_SMC2:
+		val = mk_cr_cmd(CPM_CR_CH_SMC2, cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC1:
+		val = mk_cr_cmd(CPM_CR_CH_SCC1, cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC2:
+		val = mk_cr_cmd(CPM_CR_CH_SCC2, cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC3:
+		val = mk_cr_cmd(CPM_CR_CH_SCC3, cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC4:
+		val = mk_cr_cmd(CPM_CR_CH_SCC4, cmd) | CPM_CR_FLG;
+		break;
+	default:
+		return;
+
+	}
+	cp->cp_cpcr = val;
+	while (cp->cp_cpcr & CPM_CR_FLG) ;
+}
+
+void smc1_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile cpm8xx_t *cp = cpmp;
+	unsigned int iobits = 0x000000c0;
+
+	if (!pinfo->is_portb) {
+		cp->cp_pbpar |= iobits;
+		cp->cp_pbdir &= ~iobits;
+		cp->cp_pbodr &= ~iobits;
+	} else {
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
+		((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
+	}
+
+	pinfo->brg = 1;
+}
+
+void smc2_lineif(struct uart_cpm_port *pinfo)
+{
+	/* XXX SMC2: insert port configuration here */
+	pinfo->brg = 2;
+}
+
+void scc1_lineif(struct uart_cpm_port *pinfo)
+{
+	/* XXX SCC1: insert port configuration here */
+	pinfo->brg = 1;
+}
+
+void scc2_lineif(struct uart_cpm_port *pinfo)
+{
+	/* XXX SCC2: insert port configuration here */
+	pinfo->brg = 2;
+}
+
+void scc3_lineif(struct uart_cpm_port *pinfo)
+{
+	/* XXX SCC3: insert port configuration here */
+	pinfo->brg = 3;
+}
+
+void scc4_lineif(struct uart_cpm_port *pinfo)
+{
+	/* XXX SCC4: insert port configuration here */
+	pinfo->brg = 4;
+}
+
+/*
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * receive buffer descriptors from dual port ram, and a character
+ * buffer area from host mem. If we are allocating for the console we need
+ * to do it from bootmem
+ */
+int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
+{
+	int dpmemsz, memsz;
+	u8 *dp_mem;
+	uint dp_offset;
+	u8 *mem_addr;
+	dma_addr_t dma_addr = 0;
+
+	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
+
+	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
+	dp_offset = cpm_dpalloc(dpmemsz, 8);
+	if (IS_DPERR(dp_offset)) {
+		printk(KERN_ERR
+		       "cpm_uart_cpm1.c: could not allocate buffer descriptors\n");
+		return -ENOMEM;
+	}
+	dp_mem = cpm_dpram_addr(dp_offset);
+
+	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
+	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
+	if (is_con) {
+		mem_addr = (u8 *) m8xx_cpm_hostalloc(memsz);
+		dma_addr = 0;
+	} else
+		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+					      GFP_KERNEL);
+
+	if (mem_addr == NULL) {
+		cpm_dpfree(dp_offset);
+		printk(KERN_ERR
+		       "cpm_uart_cpm1.c: could not allocate coherent memory\n");
+		return -ENOMEM;
+	}
+
+	pinfo->dp_addr = dp_offset;
+	pinfo->mem_addr = mem_addr;
+	pinfo->dma_addr = dma_addr;
+
+	pinfo->rx_buf = mem_addr;
+	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
+						       * pinfo->rx_fifosize);
+
+	pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
+
+	return 0;
+}
+
+void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
+{
+	dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+					       pinfo->rx_fifosize) +
+			  L1_CACHE_ALIGN(pinfo->tx_nrfifos *
+					 pinfo->tx_fifosize), pinfo->mem_addr,
+			  pinfo->dma_addr);
+
+	cpm_dpfree(pinfo->dp_addr);
+}
+
+/* Setup any dynamic params in the uart desc */
+int cpm_uart_init_portdesc(void)
+{
+	pr_debug("CPM uart[-]:init portdesc\n");
+
+	cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+	cpm_uart_ports[UART_SMC1].smcp = &cpmp->cp_smc[0];
+/*
+ *  Is SMC1 being relocated?
+ */
+# ifdef CONFIG_I2C_SPI_SMC1_UCODE_PATCH
+	cpm_uart_ports[UART_SMC1].smcup =
+	    (smc_uart_t *) & cpmp->cp_dparam[0x3C0];
+# else
+	cpm_uart_ports[UART_SMC1].smcup =
+	    (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC1];
+# endif
+	cpm_uart_ports[UART_SMC1].port.mapbase =
+	    (unsigned long)&cpmp->cp_smc[0];
+	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+	cpm_uart_ports[UART_SMC2].smcp = &cpmp->cp_smc[1];
+	cpm_uart_ports[UART_SMC2].smcup =
+	    (smc_uart_t *) & cpmp->cp_dparam[PROFF_SMC2];
+	cpm_uart_ports[UART_SMC2].port.mapbase =
+	    (unsigned long)&cpmp->cp_smc[1];
+	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+	cpm_uart_ports[UART_SCC1].sccp = &cpmp->cp_scc[0];
+	cpm_uart_ports[UART_SCC1].sccup =
+	    (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC1];
+	cpm_uart_ports[UART_SCC1].port.mapbase =
+	    (unsigned long)&cpmp->cp_scc[0];
+	cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+	cpm_uart_ports[UART_SCC2].sccp = &cpmp->cp_scc[1];
+	cpm_uart_ports[UART_SCC2].sccup =
+	    (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC2];
+	cpm_uart_ports[UART_SCC2].port.mapbase =
+	    (unsigned long)&cpmp->cp_scc[1];
+	cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+	cpm_uart_ports[UART_SCC3].sccp = &cpmp->cp_scc[2];
+	cpm_uart_ports[UART_SCC3].sccup =
+	    (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC3];
+	cpm_uart_ports[UART_SCC3].port.mapbase =
+	    (unsigned long)&cpmp->cp_scc[2];
+	cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+	cpm_uart_ports[UART_SCC4].sccp = &cpmp->cp_scc[3];
+	cpm_uart_ports[UART_SCC4].sccup =
+	    (scc_uart_t *) & cpmp->cp_dparam[PROFF_SCC4];
+	cpm_uart_ports[UART_SCC4].port.mapbase =
+	    (unsigned long)&cpmp->cp_scc[3];
+	cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
+	return 0;
+}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.h b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
new file mode 100644
index 0000000..5d867ab
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.h
@@ -0,0 +1,45 @@
+/*
+ * linux/drivers/serial/cpm_uart_cpm1.h
+ *
+ * Driver for CPM (SCC/SMC) serial ports
+ * 
+ * definitions for cpm1
+ *
+ */
+
+#ifndef CPM_UART_CPM1_H
+#define CPM_UART_CPM1_H
+
+#include <asm/commproc.h>
+
+/* defines for IRQs */
+#define SMC1_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SMC1)
+#define SMC2_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SMC2)
+#define SCC1_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SCC1)
+#define SCC2_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SCC2)
+#define SCC3_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SCC3)
+#define SCC4_IRQ	(CPM_IRQ_OFFSET + CPMVEC_SCC4)
+
+/* the CPM address */
+#define CPM_ADDR	IMAP_ADDR
+
+static inline void cpm_set_brg(int brg, int baud)
+{
+	cpm_setbrg(brg, baud);
+}
+
+static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+{
+	sup->scc_genscc.scc_rfcr = SMC_EB;
+	sup->scc_genscc.scc_tfcr = SMC_EB;
+}
+
+static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+{
+	up->smc_rfcr = SMC_EB;
+	up->smc_tfcr = SMC_EB;
+}
+
+#define DPRAM_BASE	((unsigned char *)&cpmp->cp_dpmem[0])
+
+#endif
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
new file mode 100644
index 0000000..b422c3a
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -0,0 +1,328 @@
+/*
+ *  linux/drivers/serial/cpm_uart_cpm2.c
+ *
+ *  Driver for CPM (SCC/SMC) serial ports; CPM2 definitions
+ *
+ *  Maintainer: Kumar Gala (kumar.gala@freescale.com) (CPM2)
+ *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
+ * 
+ *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *            (C) 2004 Intracom, S.A.
+ *
+ * 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/serial.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/bootmem.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <linux/serial_core.h>
+#include <linux/kernel.h>
+
+#include "cpm_uart.h"
+
+/**************************************************************/
+
+void cpm_line_cr_cmd(int line, int cmd)
+{
+	volatile cpm_cpm2_t *cp = cpmp;
+	ulong val;
+
+	switch (line) {
+	case UART_SMC1:
+		val = mk_cr_cmd(CPM_CR_SMC1_PAGE, CPM_CR_SMC1_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	case UART_SMC2:
+		val = mk_cr_cmd(CPM_CR_SMC2_PAGE, CPM_CR_SMC2_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC1:
+		val = mk_cr_cmd(CPM_CR_SCC1_PAGE, CPM_CR_SCC1_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC2:
+		val = mk_cr_cmd(CPM_CR_SCC2_PAGE, CPM_CR_SCC2_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC3:
+		val = mk_cr_cmd(CPM_CR_SCC3_PAGE, CPM_CR_SCC3_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	case UART_SCC4:
+		val = mk_cr_cmd(CPM_CR_SCC4_PAGE, CPM_CR_SCC4_SBLOCK, 0,
+				cmd) | CPM_CR_FLG;
+		break;
+	default:
+		return;
+
+	}
+	cp->cp_cpcr = val;
+	while (cp->cp_cpcr & CPM_CR_FLG) ;
+}
+
+void smc1_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+	/* SMC1 is only on port D */
+	io->iop_ppard |= 0x00c00000;
+	io->iop_pdird |= 0x00400000;
+	io->iop_pdird &= ~0x00800000;
+	io->iop_psord &= ~0x00c00000;
+
+	/* Wire BRG1 to SMC1 */
+	cpm2_immr->im_cpmux.cmx_smr &= 0x0f;
+	pinfo->brg = 1;
+}
+
+void smc2_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+	/* SMC2 is only on port A */
+	io->iop_ppara |= 0x00c00000;
+	io->iop_pdira |= 0x00400000;
+	io->iop_pdira &= ~0x00800000;
+	io->iop_psora &= ~0x00c00000;
+
+	/* Wire BRG2 to SMC2 */
+	cpm2_immr->im_cpmux.cmx_smr &= 0xf0;
+	pinfo->brg = 2;
+}
+
+void scc1_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+	/* Use Port D for SCC1 instead of other functions.  */
+	io->iop_ppard |= 0x00000003;
+	io->iop_psord &= ~0x00000001;	/* Rx */
+	io->iop_psord |= 0x00000002;	/* Tx */
+	io->iop_pdird &= ~0x00000001;	/* Rx */
+	io->iop_pdird |= 0x00000002;	/* Tx */
+
+	/* Wire BRG1 to SCC1 */
+	cpm2_immr->im_cpmux.cmx_scr &= 0x00ffffff;
+	cpm2_immr->im_cpmux.cmx_scr |= 0x00000000;
+	pinfo->brg = 1;
+}
+
+void scc2_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+	cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
+	cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;
+	pinfo->brg = 2;
+}
+
+void scc3_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+	io->iop_pparb |= 0x008b0000;
+	io->iop_pdirb |= 0x00880000;
+	io->iop_psorb |= 0x00880000;
+	io->iop_pdirb &= ~0x00030000;
+	io->iop_psorb &= ~0x00030000;
+	cpm2_immr->im_cpmux.cmx_scr &= 0xffff00ff;
+	cpm2_immr->im_cpmux.cmx_scr |= 0x00001200;
+	pinfo->brg = 3;
+}
+
+void scc4_lineif(struct uart_cpm_port *pinfo)
+{
+	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
+
+	io->iop_ppard |= 0x00000600;
+	io->iop_psord &= ~0x00000600;	/* Tx/Rx */
+	io->iop_pdird &= ~0x00000200;	/* Rx */
+	io->iop_pdird |= 0x00000400;	/* Tx */
+
+	cpm2_immr->im_cpmux.cmx_scr &= 0xffffff00;
+	cpm2_immr->im_cpmux.cmx_scr |= 0x0000001b;
+	pinfo->brg = 4;
+}
+
+/*
+ * Allocate DP-Ram and memory buffers. We need to allocate a transmit and 
+ * receive buffer descriptors from dual port ram, and a character
+ * buffer area from host mem. If we are allocating for the console we need
+ * to do it from bootmem
+ */
+int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
+{
+	int dpmemsz, memsz;
+	u8 *dp_mem;
+	uint dp_offset;
+	u8 *mem_addr;
+	dma_addr_t dma_addr = 0;
+
+	pr_debug("CPM uart[%d]:allocbuf\n", pinfo->port.line);
+
+	dpmemsz = sizeof(cbd_t) * (pinfo->rx_nrfifos + pinfo->tx_nrfifos);
+	dp_offset = cpm_dpalloc(dpmemsz, 8);
+	if (IS_DPERR(dp_offset)) {
+		printk(KERN_ERR
+		       "cpm_uart_cpm.c: could not allocate buffer descriptors\n");
+		return -ENOMEM;
+	}
+
+	dp_mem = cpm_dpram_addr(dp_offset);
+
+	memsz = L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize) +
+	    L1_CACHE_ALIGN(pinfo->tx_nrfifos * pinfo->tx_fifosize);
+	if (is_con)
+		mem_addr = alloc_bootmem(memsz);
+	else
+		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+					      GFP_KERNEL);
+
+	if (mem_addr == NULL) {
+		cpm_dpfree(dp_offset);
+		printk(KERN_ERR
+		       "cpm_uart_cpm.c: could not allocate coherent memory\n");
+		return -ENOMEM;
+	}
+
+	pinfo->dp_addr = dp_offset;
+	pinfo->mem_addr = mem_addr;
+	pinfo->dma_addr = dma_addr;
+
+	pinfo->rx_buf = mem_addr;
+	pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
+						       * pinfo->rx_fifosize);
+
+	pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
+	pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
+
+	return 0;
+}
+
+void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
+{
+	dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+					       pinfo->rx_fifosize) +
+			  L1_CACHE_ALIGN(pinfo->tx_nrfifos *
+					 pinfo->tx_fifosize), pinfo->mem_addr,
+			  pinfo->dma_addr);
+
+	cpm_dpfree(pinfo->dp_addr);
+}
+
+/* Setup any dynamic params in the uart desc */
+int cpm_uart_init_portdesc(void)
+{
+	pr_debug("CPM uart[-]:init portdesc\n");
+
+	cpm_uart_nr = 0;
+#ifdef CONFIG_SERIAL_CPM_SMC1
+	cpm_uart_ports[UART_SMC1].smcp = (smc_t *) & cpm2_immr->im_smc[0];
+	cpm_uart_ports[UART_SMC1].smcup =
+	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC1];
+	cpm_uart_ports[UART_SMC1].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_smc[0];
+	cpm_uart_ports[UART_SMC1].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+	cpm_uart_ports[UART_SMC1].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	cpm_uart_ports[UART_SMC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SMC2
+	cpm_uart_ports[UART_SMC2].smcp = (smc_t *) & cpm2_immr->im_smc[1];
+	cpm_uart_ports[UART_SMC2].smcup =
+	    (smc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SMC2];
+	cpm_uart_ports[UART_SMC2].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_smc[1];
+	cpm_uart_ports[UART_SMC2].smcp->smc_smcm |= (SMCM_RX | SMCM_TX);
+	cpm_uart_ports[UART_SMC2].smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+	cpm_uart_ports[UART_SMC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC1
+	cpm_uart_ports[UART_SCC1].sccp = (scc_t *) & cpm2_immr->im_scc[0];
+	cpm_uart_ports[UART_SCC1].sccup =
+	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC1];
+	cpm_uart_ports[UART_SCC1].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_scc[0];
+	cpm_uart_ports[UART_SCC1].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC1].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC1].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC2
+	cpm_uart_ports[UART_SCC2].sccp = (scc_t *) & cpm2_immr->im_scc[1];
+	cpm_uart_ports[UART_SCC2].sccup =
+	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC2];
+	cpm_uart_ports[UART_SCC2].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_scc[1];
+	cpm_uart_ports[UART_SCC2].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC2].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC2].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC3
+	cpm_uart_ports[UART_SCC3].sccp = (scc_t *) & cpm2_immr->im_scc[2];
+	cpm_uart_ports[UART_SCC3].sccup =
+	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC3];
+	cpm_uart_ports[UART_SCC3].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_scc[2];
+	cpm_uart_ports[UART_SCC3].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC3].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC3].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
+#endif
+
+#ifdef CONFIG_SERIAL_CPM_SCC4
+	cpm_uart_ports[UART_SCC4].sccp = (scc_t *) & cpm2_immr->im_scc[3];
+	cpm_uart_ports[UART_SCC4].sccup =
+	    (scc_uart_t *) & cpm2_immr->im_dprambase[PROFF_SCC4];
+	cpm_uart_ports[UART_SCC4].port.mapbase =
+	    (unsigned long)&cpm2_immr->im_scc[3];
+	cpm_uart_ports[UART_SCC4].sccp->scc_sccm &=
+	    ~(UART_SCCM_TX | UART_SCCM_RX);
+	cpm_uart_ports[UART_SCC4].sccp->scc_gsmrl &=
+	    ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+	cpm_uart_ports[UART_SCC4].port.uartclk = (((bd_t *) __res)->bi_intfreq);
+	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
+#endif
+
+	return 0;
+}
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.h b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
new file mode 100644
index 0000000..4793fec
--- /dev/null
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.h
@@ -0,0 +1,45 @@
+/*
+ * linux/drivers/serial/cpm_uart_cpm2.h
+ *
+ * Driver for CPM (SCC/SMC) serial ports
+ * 
+ * definitions for cpm2
+ *
+ */
+
+#ifndef CPM_UART_CPM2_H
+#define CPM_UART_CPM2_H
+
+#include <asm/cpm2.h>
+
+/* defines for IRQs */
+#define SMC1_IRQ	SIU_INT_SMC1
+#define SMC2_IRQ	SIU_INT_SMC2
+#define SCC1_IRQ	SIU_INT_SCC1
+#define SCC2_IRQ	SIU_INT_SCC2
+#define SCC3_IRQ	SIU_INT_SCC3
+#define SCC4_IRQ	SIU_INT_SCC4
+
+/* the CPM address */
+#define CPM_ADDR	CPM_MAP_ADDR
+
+static inline void cpm_set_brg(int brg, int baud)
+{
+	cpm_setbrg(brg, baud);
+}
+
+static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
+{
+	sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+}
+
+static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
+{
+	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
+}
+
+#define DPRAM_BASE	((unsigned char *)&cpm2_immr->im_dprambase[0])
+
+#endif