drivers/serial: use nr_irqs
[safe/jmp/linux-2.6] / drivers / serial / cpm_uart / cpm_uart_core.c
index b63ff8d..e54574c 100644 (file)
  *  Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
  *              Pantelis Antoniou (panto@intracom.gr) (CPM1)
  *
- *  Copyright (C) 2004 Freescale Semiconductor, Inc.
+ *  Copyright (C) 2004, 2007 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
  *            (C) 2005-2006 MontaVista Software, Inc.
- *             Vitaly Bordug <vbordug@ru.mvista.com>
+ *             Vitaly Bordug <vbordug@ru.mvista.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
 #include <linux/bootmem.h>
 #include <linux/dma-mapping.h>
 #include <linux/fs_uart_pd.h>
+#include <linux/of_platform.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
 #include <asm/fs_pd.h>
+#include <asm/udbg.h>
 
 #if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
 
 #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 = 0;
 
 /**************************************************************/
 
@@ -73,67 +72,20 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
 
 /**************************************************************/
 
-
-/* Place-holder for board-specific stuff */
-struct platform_device* __attribute__ ((weak)) __init
-early_uart_get_pdev(int index)
-{
-       return NULL;
-}
-
-
-static void cpm_uart_count(void)
-{
-       cpm_uart_nr = 0;
-#ifdef CONFIG_SERIAL_CPM_SMC1
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
-#endif
-#ifdef CONFIG_SERIAL_CPM_SMC2
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
-#endif
-#ifdef CONFIG_SERIAL_CPM_SCC1
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
-#endif
-#ifdef CONFIG_SERIAL_CPM_SCC2
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
-#endif
-#ifdef CONFIG_SERIAL_CPM_SCC3
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
-#endif
-#ifdef CONFIG_SERIAL_CPM_SCC4
-       cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
-#endif
-}
-
-/* Get UART number by its id */
-static int cpm_uart_id2nr(int id)
-{
-       int i;
-       if (id < UART_NR) {
-               for (i=0; i<UART_NR; i++) {
-                       if (cpm_uart_port_map[i] == id)
-                               return i;
-               }
-       }
-
-       /* not found or invalid argument */
-       return -1;
-}
-
 /*
  * 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;
+       cbd_t __iomem *bdp = pinfo->tx_bd_base;
        int ret = 0;
 
        while (1) {
-               if (bdp->cbd_sc & BD_SC_READY)
+               if (in_be16(&bdp->cbd_sc) & BD_SC_READY)
                        break;
 
-               if (bdp->cbd_sc & BD_SC_WRAP) {
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) {
                        ret = TIOCSER_TEMT;
                        break;
                }
@@ -147,13 +99,41 @@ static unsigned int cpm_uart_tx_empty(struct uart_port *port)
 
 static void cpm_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-       /* Whee. Do nothing. */
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+       if (pinfo->gpios[GPIO_RTS] >= 0)
+               gpio_set_value(pinfo->gpios[GPIO_RTS], !(mctrl & TIOCM_RTS));
+
+       if (pinfo->gpios[GPIO_DTR] >= 0)
+               gpio_set_value(pinfo->gpios[GPIO_DTR], !(mctrl & TIOCM_DTR));
 }
 
 static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
 {
-       /* Whee. Do nothing. */
-       return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       unsigned int mctrl = TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
+
+       if (pinfo->gpios[GPIO_CTS] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_CTS]))
+                       mctrl &= ~TIOCM_CTS;
+       }
+
+       if (pinfo->gpios[GPIO_DSR] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_DSR]))
+                       mctrl &= ~TIOCM_DSR;
+       }
+
+       if (pinfo->gpios[GPIO_DCD] >= 0) {
+               if (gpio_get_value(pinfo->gpios[GPIO_DCD]))
+                       mctrl &= ~TIOCM_CAR;
+       }
+
+       if (pinfo->gpios[GPIO_RI] >= 0) {
+               if (!gpio_get_value(pinfo->gpios[GPIO_RI]))
+                       mctrl |= TIOCM_RNG;
+       }
+
+       return mctrl;
 }
 
 /*
@@ -162,15 +142,15 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
 static void cpm_uart_stop_tx(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;
+       smc_t __iomem *smcp = pinfo->smcp;
+       scc_t __iomem *sccp = pinfo->sccp;
 
        pr_debug("CPM uart[%d]:stop tx\n", port->line);
 
        if (IS_SMC(pinfo))
-               smcp->smc_smcm &= ~SMCM_TX;
+               clrbits8(&smcp->smc_smcm, SMCM_TX);
        else
-               sccp->scc_sccm &= ~UART_SCCM_TX;
+               clrbits16(&sccp->scc_sccm, UART_SCCM_TX);
 }
 
 /*
@@ -179,24 +159,24 @@ static void cpm_uart_stop_tx(struct uart_port *port)
 static void cpm_uart_start_tx(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;
+       smc_t __iomem *smcp = pinfo->smcp;
+       scc_t __iomem *sccp = pinfo->sccp;
 
        pr_debug("CPM uart[%d]:start tx\n", port->line);
 
        if (IS_SMC(pinfo)) {
-               if (smcp->smc_smcm & SMCM_TX)
+               if (in_8(&smcp->smc_smcm) & SMCM_TX)
                        return;
        } else {
-               if (sccp->scc_sccm & UART_SCCM_TX)
+               if (in_be16(&sccp->scc_sccm) & UART_SCCM_TX)
                        return;
        }
 
        if (cpm_uart_tx_pump(port) != 0) {
                if (IS_SMC(pinfo)) {
-                       smcp->smc_smcm |= SMCM_TX;
+                       setbits8(&smcp->smc_smcm, SMCM_TX);
                } else {
-                       sccp->scc_sccm |= UART_SCCM_TX;
+                       setbits16(&sccp->scc_sccm, UART_SCCM_TX);
                }
        }
 }
@@ -207,15 +187,15 @@ static void cpm_uart_start_tx(struct uart_port *port)
 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;
+       smc_t __iomem *smcp = pinfo->smcp;
+       scc_t __iomem *sccp = pinfo->sccp;
 
        pr_debug("CPM uart[%d]:stop rx\n", port->line);
 
        if (IS_SMC(pinfo))
-               smcp->smc_smcm &= ~SMCM_RX;
+               clrbits8(&smcp->smc_smcm, SMCM_RX);
        else
-               sccp->scc_sccm &= ~UART_SCCM_RX;
+               clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
 }
 
 /*
@@ -232,15 +212,14 @@ static void cpm_uart_enable_ms(struct uart_port *port)
 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);
+               cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
        else
-               cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
+               cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
 }
 
 /*
@@ -253,16 +232,21 @@ static void cpm_uart_int_tx(struct uart_port *port)
        cpm_uart_tx_pump(port);
 }
 
+#ifdef CONFIG_CONSOLE_POLL
+static int serial_polled;
+#endif
+
 /*
  * Receive characters
  */
 static void cpm_uart_int_rx(struct uart_port *port)
 {
        int i;
-       unsigned char ch, *cp;
-       struct tty_struct *tty = port->info->tty;
+       unsigned char ch;
+       u8 *cp;
+       struct tty_struct *tty = port->info->port.tty;
        struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-       volatile cbd_t *bdp;
+       cbd_t __iomem *bdp;
        u16 status;
        unsigned int flg;
 
@@ -273,14 +257,20 @@ static void cpm_uart_int_rx(struct uart_port *port)
         */
        bdp = pinfo->rx_cur;
        for (;;) {
+#ifdef CONFIG_CONSOLE_POLL
+               if (unlikely(serial_polled)) {
+                       serial_polled = 0;
+                       return;
+               }
+#endif
                /* get status */
-               status = bdp->cbd_sc;
+               status = in_be16(&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;
+               i = in_be16(&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
@@ -291,7 +281,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
                }
 
                /* get pointer */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+               cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
 
                /* loop through the buffer */
                while (i-- > 0) {
@@ -304,17 +294,23 @@ static void cpm_uart_int_rx(struct uart_port *port)
                                goto handle_error;
                        if (uart_handle_sysrq_char(port, ch))
                                continue;
-
+#ifdef CONFIG_CONSOLE_POLL
+                       if (unlikely(serial_polled)) {
+                               serial_polled = 0;
+                               return;
+                       }
+#endif
                      error_return:
                        tty_insert_flip_char(tty, ch, flg);
 
                }               /* 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 | BD_SC_ID);
-               bdp->cbd_sc |= BD_SC_EMPTY;
+               clrbits16(&bdp->cbd_sc, BD_SC_BR | BD_SC_FR | BD_SC_PR |
+                                       BD_SC_OV | BD_SC_ID);
+               setbits16(&bdp->cbd_sc, BD_SC_EMPTY);
 
-               if (bdp->cbd_sc & BD_SC_WRAP)
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
                        bdp = pinfo->rx_bd_base;
                else
                        bdp++;
@@ -322,7 +318,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
        } /* End for (;;) */
 
        /* Write back buffer pointer */
-       pinfo->rx_cur = (volatile cbd_t *) bdp;
+       pinfo->rx_cur = bdp;
 
        /* activate BH processing */
        tty_flip_buffer_push(tty);
@@ -374,16 +370,16 @@ static void cpm_uart_int_rx(struct uart_port *port)
 static irqreturn_t cpm_uart_int(int irq, void *data)
 {
        u8 events;
-       struct uart_port *port = (struct uart_port *)data;
+       struct uart_port *port = data;
        struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-       volatile smc_t *smcp = pinfo->smcp;
-       volatile scc_t *sccp = pinfo->sccp;
+       smc_t __iomem *smcp = pinfo->smcp;
+       scc_t __iomem *sccp = pinfo->sccp;
 
        pr_debug("CPM uart[%d]:IRQ\n", port->line);
 
        if (IS_SMC(pinfo)) {
-               events = smcp->smc_smce;
-               smcp->smc_smce = events;
+               events = in_8(&smcp->smc_smce);
+               out_8(&smcp->smc_smce, events);
                if (events & SMCM_BRKE)
                        uart_handle_break(port);
                if (events & SMCM_RX)
@@ -391,8 +387,8 @@ static irqreturn_t cpm_uart_int(int irq, void *data)
                if (events & SMCM_TX)
                        cpm_uart_int_tx(port);
        } else {
-               events = sccp->scc_scce;
-               sccp->scc_scce = events;
+               events = in_be16(&sccp->scc_scce);
+               out_be16(&sccp->scc_scce, events);
                if (events & UART_SCCM_BRKE)
                        uart_handle_break(port);
                if (events & UART_SCCM_RX)
@@ -407,7 +403,6 @@ static int cpm_uart_startup(struct uart_port *port)
 {
        int retval;
        struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
-       int line = pinfo - cpm_uart_ports;
 
        pr_debug("CPM uart[%d]:startup\n", port->line);
 
@@ -418,15 +413,15 @@ static int cpm_uart_startup(struct uart_port *port)
 
        /* Startup rx-int */
        if (IS_SMC(pinfo)) {
-               pinfo->smcp->smc_smcm |= SMCM_RX;
-               pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+               setbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
+               setbits16(&pinfo->smcp->smc_smcmr, (SMCMR_REN | SMCMR_TEN));
        } else {
-               pinfo->sccp->scc_sccm |= UART_SCCM_RX;
-               pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+               setbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
+               setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT));
        }
 
        if (!(pinfo->flags & FLAG_CONSOLE))
-               cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
+               cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
        return 0;
 }
 
@@ -442,7 +437,6 @@ inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
 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);
 
@@ -462,20 +456,23 @@ static void cpm_uart_shutdown(struct uart_port *port)
 
                /* 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);
+                       smc_t __iomem *smcp = pinfo->smcp;
+                       clrbits16(&smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
+                       clrbits8(&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);
+                       scc_t __iomem *sccp = pinfo->sccp;
+                       clrbits32(&sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+                       clrbits16(&sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
                }
 
                /* Shut them really down and reinit buffer descriptors */
-               if (IS_SMC(pinfo))
-                       cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
-               else
-                       cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+               if (IS_SMC(pinfo)) {
+                       out_be16(&pinfo->smcup->smc_brkcr, 0);
+                       cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
+               } else {
+                       out_be16(&pinfo->sccup->scc_brkcr, 0);
+                       cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
+               }
 
                cpm_uart_initbd(pinfo);
        }
@@ -490,8 +487,8 @@ static void cpm_uart_set_termios(struct uart_port *port,
        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;
+       smc_t __iomem *smcp = pinfo->smcp;
+       scc_t __iomem *sccp = pinfo->sccp;
 
        pr_debug("CPM uart[%d]:set_termios\n", port->line);
 
@@ -543,6 +540,11 @@ static void cpm_uart_set_termios(struct uart_port *port,
        }
 
        /*
+        * Update the timeout
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       /*
         * Set up parity check flag
         */
 #define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
@@ -586,16 +588,20 @@ static void cpm_uart_set_termios(struct uart_port *port,
                 * 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));
+               prev_mode = in_be16(&smcp->smc_smcmr) & (SMCMR_REN | SMCMR_TEN);
+               /* Output in *one* operation, so we don't interrupt RX/TX if they
+                * were already enabled. */
+               out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval |
+                   SMCMR_SM_UART | prev_mode);
        } else {
-               sccp->scc_psmr = (sbits << 12) | scval;
+               out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
        }
 
-       cpm_set_brg(pinfo->brg - 1, baud);
+       if (pinfo->clk)
+               clk_set_rate(pinfo->clk, baud);
+       else
+               cpm_set_brg(pinfo->brg - 1, baud);
        spin_unlock_irqrestore(&port->lock, flags);
-
 }
 
 static const char *cpm_uart_type(struct uart_port *port)
@@ -617,7 +623,7 @@ static int cpm_uart_verify_port(struct uart_port *port,
 
        if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
                ret = -EINVAL;
-       if (ser->irq < 0 || ser->irq >= NR_IRQS)
+       if (ser->irq < 0 || ser->irq >= nr_irqs)
                ret = -EINVAL;
        if (ser->baud_base < 9600)
                ret = -EINVAL;
@@ -629,8 +635,8 @@ static int cpm_uart_verify_port(struct uart_port *port,
  */
 static int cpm_uart_tx_pump(struct uart_port *port)
 {
-       volatile cbd_t *bdp;
-       unsigned char *p;
+       cbd_t __iomem *bdp;
+       u8 *p;
        int count;
        struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
        struct circ_buf *xmit = &port->info->xmit;
@@ -640,13 +646,14 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                /* Pick next descriptor and fill from buffer */
                bdp = pinfo->tx_cur;
 
-               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+               p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
 
                *p++ = port->x_char;
-               bdp->cbd_datlen = 1;
-               bdp->cbd_sc |= BD_SC_READY;
+
+               out_be16(&bdp->cbd_datlen, 1);
+               setbits16(&bdp->cbd_sc, BD_SC_READY);
                /* Get next BD. */
-               if (bdp->cbd_sc & BD_SC_WRAP)
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
                        bdp = pinfo->tx_bd_base;
                else
                        bdp++;
@@ -665,9 +672,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
        /* Pick next descriptor and fill from buffer */
        bdp = pinfo->tx_cur;
 
-       while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
+       while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
+              xmit->tail != xmit->head) {
                count = 0;
-               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+               p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
                while (count < pinfo->tx_fifosize) {
                        *p++ = xmit->buf[xmit->tail];
                        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -676,11 +684,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
                        if (xmit->head == xmit->tail)
                                break;
                }
-               bdp->cbd_datlen = count;
-               bdp->cbd_sc |= BD_SC_READY;
-               __asm__("eieio");
+               out_be16(&bdp->cbd_datlen, count);
+               setbits16(&bdp->cbd_sc, BD_SC_READY);
                /* Get next BD. */
-               if (bdp->cbd_sc & BD_SC_WRAP)
+               if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
                        bdp = pinfo->tx_bd_base;
                else
                        bdp++;
@@ -705,7 +712,7 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
 {
        int i;
        u8 *mem_addr;
-       volatile cbd_t *bdp;
+       cbd_t __iomem *bdp;
 
        pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
 
@@ -716,13 +723,13 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        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 = cpu2cpm_addr(mem_addr, pinfo);
-               bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
+               out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+               out_be16(&bdp->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
                mem_addr += pinfo->rx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
-       bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
+       out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+       out_be16(&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
@@ -731,20 +738,19 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
        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 = cpu2cpm_addr(mem_addr, pinfo);
-               bdp->cbd_sc = BD_SC_INTRPT;
+               out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+               out_be16(&bdp->cbd_sc, BD_SC_INTRPT);
                mem_addr += pinfo->tx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
-       bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
+       out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
+       out_be16(&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;
+       scc_t __iomem *scp;
+       scc_uart_t __iomem *sup;
 
        pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
 
@@ -752,8 +758,10 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
        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;
+       out_be16(&pinfo->sccup->scc_genscc.scc_rbase,
+                (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
+       out_be16(&pinfo->sccup->scc_genscc.scc_tbase,
+                (u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
 
        /* Set up the uart parameters in the
         * parameter ram.
@@ -761,51 +769,50 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
 
        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;
+       out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
+       out_be16(&sup->scc_maxidl, pinfo->rx_fifosize);
+       out_be16(&sup->scc_brkcr, 1);
+       out_be16(&sup->scc_parec, 0);
+       out_be16(&sup->scc_frmec, 0);
+       out_be16(&sup->scc_nosec, 0);
+       out_be16(&sup->scc_brkec, 0);
+       out_be16(&sup->scc_uaddr1, 0);
+       out_be16(&sup->scc_uaddr2, 0);
+       out_be16(&sup->scc_toseq, 0);
+       out_be16(&sup->scc_char1, 0x8000);
+       out_be16(&sup->scc_char2, 0x8000);
+       out_be16(&sup->scc_char3, 0x8000);
+       out_be16(&sup->scc_char4, 0x8000);
+       out_be16(&sup->scc_char5, 0x8000);
+       out_be16(&sup->scc_char6, 0x8000);
+       out_be16(&sup->scc_char7, 0x8000);
+       out_be16(&sup->scc_char8, 0x8000);
+       out_be16(&sup->scc_rccm, 0xc0ff);
 
        /* Send the CPM an initialize command.
         */
-       cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+       cpm_line_cr_cmd(pinfo, 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);
+       out_be32(&scp->scc_gsmrh, 0);
+       out_be32(&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;
+       out_be16(&scp->scc_sccm, 0);
+       out_be16(&scp->scc_scce, 0xffff);
+       out_be16(&scp->scc_dsr, 0x7e7e);
+       out_be16(&scp->scc_psmr, 0x3000);
 
-       scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
+       setbits32(&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;
+       smc_t __iomem *sp;
+       smc_uart_t __iomem *up;
 
        pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
 
@@ -813,19 +820,21 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
        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;
+       out_be16(&pinfo->smcup->smc_rbase,
+                (u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
+       out_be16(&pinfo->smcup->smc_tbase,
+                (u8 __iomem *)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;
+       out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
+       out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
+       out_be32(&up->smc_rstate, 0);
+       out_be32(&up->smc_tstate, 0);
+       out_be16(&up->smc_brkcr, 1);              /* number of break chars */
+       out_be16(&up->smc_brkec, 0);
 #endif
 
        /* Set up the uart parameters in the
@@ -834,24 +843,24 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
        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_brklen = 0;
-       up->smc_brkec = 0;
-       up->smc_brkcr = 1;
+       out_be16(&up->smc_mrblr, pinfo->rx_fifosize);
+       out_be16(&up->smc_maxidl, pinfo->rx_fifosize);
+       out_be16(&up->smc_brklen, 0);
+       out_be16(&up->smc_brkec, 0);
+       out_be16(&up->smc_brkcr, 1);
 
-       cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
+       cpm_line_cr_cmd(pinfo, 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;
+       out_be16(&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;
+       out_8(&sp->smc_smcm, 0);
+       out_8(&sp->smc_smce, 0xff);
 
-       sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
+       setbits16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
 }
 
 /*
@@ -869,11 +878,11 @@ static int cpm_uart_request_port(struct uart_port *port)
                return 0;
 
        if (IS_SMC(pinfo)) {
-               pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-               pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+               clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
+               clrbits16(&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);
+               clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+               clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
        }
 
        ret = cpm_uart_allocbuf(pinfo, 0);
@@ -910,6 +919,80 @@ static void cpm_uart_config_port(struct uart_port *port, int flags)
                cpm_uart_request_port(port);
        }
 }
+
+#ifdef CONFIG_CONSOLE_POLL
+/* Serial polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+#define GDB_BUF_SIZE   512     /* power of 2, please */
+
+static char poll_buf[GDB_BUF_SIZE];
+static char *pollp;
+static int poll_chars;
+
+static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
+{
+       u_char          c, *cp;
+       volatile cbd_t  *bdp;
+       int             i;
+
+       /* Get the address of the host memory buffer.
+        */
+       bdp = pinfo->rx_cur;
+       while (bdp->cbd_sc & BD_SC_EMPTY)
+               ;
+
+       /* If the buffer address is in the CPM DPRAM, don't
+        * convert it.
+        */
+       cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
+
+       if (obuf) {
+               i = c = bdp->cbd_datlen;
+               while (i-- > 0)
+                       *obuf++ = *cp++;
+       } else
+               c = *cp;
+       bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
+       bdp->cbd_sc |= BD_SC_EMPTY;
+
+       if (bdp->cbd_sc & BD_SC_WRAP)
+               bdp = pinfo->rx_bd_base;
+       else
+               bdp++;
+       pinfo->rx_cur = (cbd_t *)bdp;
+
+       return (int)c;
+}
+
+static int cpm_get_poll_char(struct uart_port *port)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+
+       if (!serial_polled) {
+               serial_polled = 1;
+               poll_chars = 0;
+       }
+       if (poll_chars <= 0) {
+               poll_chars = poll_wait_key(poll_buf, pinfo);
+               pollp = poll_buf;
+       }
+       poll_chars--;
+       return *pollp++;
+}
+
+static void cpm_put_poll_char(struct uart_port *port,
+                        unsigned char c)
+{
+       struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
+       static char ch[2];
+
+       ch[0] = (char)c;
+       cpm_uart_early_write(pinfo->port.line, ch, 1);
+}
+#endif /* CONFIG_CONSOLE_POLL */
+
 static struct uart_ops cpm_uart_pops = {
        .tx_empty       = cpm_uart_tx_empty,
        .set_mctrl      = cpm_uart_set_mctrl,
@@ -927,150 +1010,99 @@ static struct uart_ops cpm_uart_pops = {
        .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         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SMC1].port.lock),
-               },
-               .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         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SMC2].port.lock),
-               },
-               .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,
+#ifdef CONFIG_CONSOLE_POLL
+       .poll_get_char = cpm_get_poll_char,
+       .poll_put_char = cpm_put_poll_char,
 #endif
-       },
-       [UART_SCC1] = {
-               .port = {
-                       .irq            = SCC1_IRQ,
-                       .ops            = &cpm_uart_pops,
-                       .iotype         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC1].port.lock),
-               },
-               .tx_nrfifos = TX_NUM_FIFO,
-               .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO,
-               .rx_fifosize = RX_BUF_SIZE,
-               .set_lineif = scc1_lineif,
-               .wait_closing = SCC_WAIT_CLOSING,
-       },
-       [UART_SCC2] = {
-               .port = {
-                       .irq            = SCC2_IRQ,
-                       .ops            = &cpm_uart_pops,
-                       .iotype         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC2].port.lock),
-               },
-               .tx_nrfifos = TX_NUM_FIFO,
-               .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO,
-               .rx_fifosize = RX_BUF_SIZE,
-               .set_lineif = scc2_lineif,
-               .wait_closing = SCC_WAIT_CLOSING,
-       },
-       [UART_SCC3] = {
-               .port = {
-                       .irq            = SCC3_IRQ,
-                       .ops            = &cpm_uart_pops,
-                       .iotype         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC3].port.lock),
-               },
-               .tx_nrfifos = TX_NUM_FIFO,
-               .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO,
-               .rx_fifosize = RX_BUF_SIZE,
-               .set_lineif = scc3_lineif,
-               .wait_closing = SCC_WAIT_CLOSING,
-       },
-       [UART_SCC4] = {
-               .port = {
-                       .irq            = SCC4_IRQ,
-                       .ops            = &cpm_uart_pops,
-                       .iotype         = UPIO_MEM,
-                       .lock           = __SPIN_LOCK_UNLOCKED(cpm_uart_ports[UART_SCC4].port.lock),
-               },
-               .tx_nrfifos = TX_NUM_FIFO,
-               .tx_fifosize = TX_BUF_SIZE,
-               .rx_nrfifos = RX_NUM_FIFO,
-               .rx_fifosize = RX_BUF_SIZE,
-               .set_lineif = scc4_lineif,
-               .wait_closing = SCC_WAIT_CLOSING,
-       },
 };
 
-int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
+struct uart_cpm_port cpm_uart_ports[UART_NR];
+
+static int cpm_uart_init_port(struct device_node *np,
+                              struct uart_cpm_port *pinfo)
 {
-       struct resource *r;
-       struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
-       int idx;        /* It is UART_SMCx or UART_SCCx index */
-       struct uart_cpm_port *pinfo;
-       int line;
-       u32 mem, pram;
+       const u32 *data;
+       void __iomem *mem, *pram;
+       int len;
+       int ret;
+       int i;
 
-        idx = pdata->fs_no = fs_uart_get_id(pdata);
+       data = of_get_property(np, "clock", NULL);
+       if (data) {
+               struct clk *clk = clk_get(NULL, (const char*)data);
+               if (!IS_ERR(clk))
+                       pinfo->clk = clk;
+       }
+       if (!pinfo->clk) {
+               data = of_get_property(np, "fsl,cpm-brg", &len);
+               if (!data || len != 4) {
+                       printk(KERN_ERR "CPM UART %s has no/invalid "
+                                       "fsl,cpm-brg property.\n", np->name);
+                       return -EINVAL;
+               }
+               pinfo->brg = *data;
+       }
 
-       line = cpm_uart_id2nr(idx);
-       if(line < 0) {
-               printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+       data = of_get_property(np, "fsl,cpm-command", &len);
+       if (!data || len != 4) {
+               printk(KERN_ERR "CPM UART %s has no/invalid "
+                               "fsl,cpm-command property.\n", np->name);
                return -EINVAL;
        }
-
-       pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
-
-       pinfo->brg = pdata->brg;
-
-       if (!is_con) {
-               pinfo->port.line = line;
-               pinfo->port.flags = UPF_BOOT_AUTOCONF;
+       pinfo->command = *data;
+
+       mem = of_iomap(np, 0);
+       if (!mem)
+               return -ENOMEM;
+
+       if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
+           of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
+               pinfo->sccp = mem;
+               pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np);
+       } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
+                  of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
+               pinfo->flags |= FLAG_SMC;
+               pinfo->smcp = mem;
+               pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
+       } else {
+               ret = -ENODEV;
+               goto out_mem;
        }
 
-       if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
-               return -EINVAL;
-       mem = (u32)ioremap(r->start, r->end - r->start + 1);
+       if (!pram) {
+               ret = -ENOMEM;
+               goto out_mem;
+       }
 
-       if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
-               return -EINVAL;
-       pram = (u32)ioremap(r->start, r->end - r->start + 1);
+       pinfo->tx_nrfifos = TX_NUM_FIFO;
+       pinfo->tx_fifosize = TX_BUF_SIZE;
+       pinfo->rx_nrfifos = RX_NUM_FIFO;
+       pinfo->rx_fifosize = RX_BUF_SIZE;
 
-       if(idx > fsid_smc2_uart) {
-               pinfo->sccp = (scc_t *)mem;
-               pinfo->sccup = (scc_uart_t *)pram;
-       } else {
-               pinfo->smcp = (smc_t *)mem;
-               pinfo->smcup = (smc_uart_t *)pram;
+       pinfo->port.uartclk = ppc_proc_freq;
+       pinfo->port.mapbase = (unsigned long)mem;
+       pinfo->port.type = PORT_CPM;
+       pinfo->port.ops = &cpm_uart_pops,
+       pinfo->port.iotype = UPIO_MEM;
+       pinfo->port.fifosize = pinfo->tx_nrfifos * pinfo->tx_fifosize;
+       spin_lock_init(&pinfo->port.lock);
+
+       pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
+       if (pinfo->port.irq == NO_IRQ) {
+               ret = -EINVAL;
+               goto out_pram;
        }
-       pinfo->tx_nrfifos = pdata->tx_num_fifo;
-       pinfo->tx_fifosize = pdata->tx_buf_size;
 
-       pinfo->rx_nrfifos = pdata->rx_num_fifo;
-       pinfo->rx_fifosize = pdata->rx_buf_size;
+       for (i = 0; i < NUM_GPIOS; i++)
+               pinfo->gpios[i] = of_get_gpio(np, i);
 
-       pinfo->port.uartclk = pdata->uart_clk;
-       pinfo->port.mapbase = (unsigned long)mem;
-       pinfo->port.irq = platform_get_irq(pdev, 0);
+       return cpm_uart_request_port(&pinfo->port);
 
-       return 0;
+out_pram:
+       cpm_uart_unmap_pram(pinfo, pram);
+out_mem:
+       iounmap(mem);
+       return ret;
 }
 
 #ifdef CONFIG_SERIAL_CPM_CONSOLE
@@ -1083,11 +1115,18 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 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]];
+       struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
        unsigned int i;
-       volatile cbd_t *bdp, *bdbase;
-       volatile unsigned char *cp;
+       cbd_t __iomem *bdp, *bdbase;
+       unsigned char *cp;
+       unsigned long flags;
+       int nolock = oops_in_progress;
+
+       if (unlikely(nolock)) {
+               local_irq_save(flags);
+       } else {
+               spin_lock_irqsave(&pinfo->port.lock, flags);
+       }
 
        /* Get the address of the host memory buffer.
         */
@@ -1105,37 +1144,36 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                 * 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)
+               while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
                        ;
 
                /* Send the character out.
                 * If the buffer address is in the CPM DPRAM, don't
                 * convert it.
                 */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
-
+               cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
                *cp = *s;
 
-               bdp->cbd_datlen = 1;
-               bdp->cbd_sc |= BD_SC_READY;
+               out_be16(&bdp->cbd_datlen, 1);
+               setbits16(&bdp->cbd_sc, BD_SC_READY);
 
-               if (bdp->cbd_sc & BD_SC_WRAP)
+               if (in_be16(&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)
+                       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
                                ;
 
-                       cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
-
+                       cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
                        *cp = 13;
-                       bdp->cbd_datlen = 1;
-                       bdp->cbd_sc |= BD_SC_READY;
 
-                       if (bdp->cbd_sc & BD_SC_WRAP)
+                       out_be16(&bdp->cbd_datlen, 1);
+                       setbits16(&bdp->cbd_sc, BD_SC_READY);
+
+                       if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
                                bdp = bdbase;
                        else
                                bdp++;
@@ -1146,48 +1184,59 @@ static void cpm_uart_console_write(struct console *co, const char *s,
         * Finally, Wait for transmitter & holding register to empty
         *  and restore the IER
         */
-       while ((bdp->cbd_sc & BD_SC_READY) != 0)
+       while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
                ;
 
-       pinfo->tx_cur = (volatile cbd_t *) bdp;
+       pinfo->tx_cur = bdp;
+
+       if (unlikely(nolock)) {
+               local_irq_restore(flags);
+       } else {
+               spin_unlock_irqrestore(&pinfo->port.lock, flags);
+       }
 }
 
 
 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;
+       struct uart_cpm_port *pinfo;
+       struct uart_port *port;
 
-       struct fs_uart_platform_info *pdata;
-       struct platform_device* pdev = early_uart_get_pdev(co->index);
+       struct device_node *np = NULL;
+       int i = 0;
 
-       if (!pdev) {
-               pr_info("cpm_uart: console: compat mode\n");
-               /* compatibility - will be cleaned up */
-               cpm_uart_init_portdesc();
+       if (co->index >= UART_NR) {
+               printk(KERN_ERR "cpm_uart: console index %d too high\n",
+                      co->index);
+               return -ENODEV;
        }
 
-       port =
-           (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
-       pinfo = (struct uart_cpm_port *)port;
-       if (!pdev) {
-               if (pinfo->set_lineif)
-                       pinfo->set_lineif(pinfo);
-       } else {
-               pdata = pdev->dev.platform_data;
-               if (pdata)
-                       if (pdata->init_ioports)
-                               pdata->init_ioports(pdata);
+       do {
+               np = of_find_node_by_type(np, "serial");
+               if (!np)
+                       return -ENODEV;
 
-               cpm_uart_drv_get_platform_data(pdev, 1);
-       }
+               if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
+                   !of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
+                   !of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
+                   !of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
+                       i--;
+       } while (i++ != co->index);
+
+       pinfo = &cpm_uart_ports[co->index];
 
        pinfo->flags |= FLAG_CONSOLE;
+       port = &pinfo->port;
+
+       ret = cpm_uart_init_port(np, pinfo);
+       of_node_put(np);
+       if (ret)
+               return ret;
 
        if (options) {
                uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -1196,12 +1245,20 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
                        baud = 9600;
        }
 
+#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
+       udbg_putc = NULL;
+#endif
+
        if (IS_SMC(pinfo)) {
-               pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
-               pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
+               out_be16(&pinfo->smcup->smc_brkcr, 0);
+               cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
+               clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
+               clrbits16(&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);
+               out_be16(&pinfo->sccup->scc_brkcr, 0);
+               cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
+               clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
+               clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
        }
 
        ret = cpm_uart_allocbuf(pinfo, 1);
@@ -1217,6 +1274,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
                cpm_uart_init_scc(pinfo);
 
        uart_set_options(port, co, baud, parity, bits, flow);
+       cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
 
        return 0;
 }
@@ -1232,7 +1290,7 @@ static struct console cpm_scc_uart_console = {
        .data           = &cpm_reg,
 };
 
-int __init cpm_uart_console_init(void)
+static int __init cpm_uart_console_init(void)
 {
        register_console(&cpm_scc_uart_console);
        return 0;
@@ -1252,132 +1310,77 @@ static struct uart_driver cpm_reg = {
        .major          = SERIAL_CPM_MAJOR,
        .minor          = SERIAL_CPM_MINOR,
        .cons           = CPM_UART_CONSOLE,
+       .nr             = UART_NR,
 };
-static int cpm_uart_drv_probe(struct device *dev)
-{
-       struct platform_device  *pdev = to_platform_device(dev);
-       struct fs_uart_platform_info *pdata;
-       int ret = -ENODEV;
 
-       if(!pdev) {
-               printk(KERN_ERR"CPM UART: platform data missing!\n");
-               return ret;
-       }
+static int probe_index;
 
-       pdata = pdev->dev.platform_data;
+static int __devinit cpm_uart_probe(struct of_device *ofdev,
+                                    const struct of_device_id *match)
+{
+       int index = probe_index++;
+       struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
+       int ret;
 
-       if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
-               return ret;
+       pinfo->port.line = index;
 
-       pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
+       if (index >= UART_NR)
+               return -ENODEV;
 
-       if (pdata->init_ioports)
-                pdata->init_ioports(pdata);
+       dev_set_drvdata(&ofdev->dev, pinfo);
 
-       ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
+       ret = cpm_uart_init_port(ofdev->node, pinfo);
+       if (ret)
+               return ret;
 
-        return ret;
+       return uart_add_one_port(&cpm_reg, &pinfo->port);
 }
 
-static int cpm_uart_drv_remove(struct device *dev)
+static int __devexit cpm_uart_remove(struct of_device *ofdev)
 {
-       struct platform_device  *pdev = to_platform_device(dev);
-       struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
-
-       pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
-                       cpm_uart_id2nr(pdata->fs_no));
-
-        uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
-        return 0;
+       struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
+       return uart_remove_one_port(&cpm_reg, &pinfo->port);
 }
 
-static struct device_driver cpm_smc_uart_driver = {
-        .name   = "fsl-cpm-smc:uart",
-        .bus    = &platform_bus_type,
-        .probe  = cpm_uart_drv_probe,
-        .remove = cpm_uart_drv_remove,
+static struct of_device_id cpm_uart_match[] = {
+       {
+               .compatible = "fsl,cpm1-smc-uart",
+       },
+       {
+               .compatible = "fsl,cpm1-scc-uart",
+       },
+       {
+               .compatible = "fsl,cpm2-smc-uart",
+       },
+       {
+               .compatible = "fsl,cpm2-scc-uart",
+       },
+       {}
 };
 
-static struct device_driver cpm_scc_uart_driver = {
-        .name   = "fsl-cpm-scc:uart",
-        .bus    = &platform_bus_type,
-        .probe  = cpm_uart_drv_probe,
-        .remove = cpm_uart_drv_remove,
-};
+static struct of_platform_driver cpm_uart_driver = {
+       .name = "cpm_uart",
+       .match_table = cpm_uart_match,
+       .probe = cpm_uart_probe,
+       .remove = cpm_uart_remove,
+ };
 
-/*
-   This is supposed to match uart devices on platform bus,
-   */
-static int match_is_uart (struct device* dev, void* data)
+static int __init cpm_uart_init(void)
 {
-       struct platform_device* pdev = container_of(dev, struct platform_device, dev);
-       int ret = 0;
-       /* this was setfunc as uart */
-       if(strstr(pdev->name,":uart")) {
-               ret = 1;
-       }
-       return ret;
-}
-
-
-static int cpm_uart_init(void) {
-
-       int ret;
-       int i;
-       struct device *dev;
-       printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");
-
-       /* lookup the bus for uart devices */
-       dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);
-
-       /* There are devices on the bus - all should be OK  */
-       if (dev) {
-               cpm_uart_count();
-               cpm_reg.nr = cpm_uart_nr;
+       int ret = uart_register_driver(&cpm_reg);
+       if (ret)
+               return ret;
 
-               if (!(ret = uart_register_driver(&cpm_reg))) {
-                       if ((ret = driver_register(&cpm_smc_uart_driver))) {
-                               uart_unregister_driver(&cpm_reg);
-                               return ret;
-                       }
-                       if ((ret = driver_register(&cpm_scc_uart_driver))) {
-                               driver_unregister(&cpm_scc_uart_driver);
-                               uart_unregister_driver(&cpm_reg);
-                       }
-               }
-       } else {
-       /* No capable platform devices found - falling back to legacy mode */
-               pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");
-               pr_info(
-               "cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n");
-
-               /* Don't run this again, if the console driver did it already */
-               if (cpm_uart_nr == 0)
-                       cpm_uart_init_portdesc();
-
-               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;
-                       if (cpm_uart_ports[con].set_lineif)
-                               cpm_uart_ports[con].set_lineif(&cpm_uart_ports[con]);
-                       uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
-               }
+       ret = of_register_platform_driver(&cpm_uart_driver);
+       if (ret)
+               uart_unregister_driver(&cpm_reg);
 
-       }
        return ret;
 }
 
 static void __exit cpm_uart_exit(void)
 {
-       driver_unregister(&cpm_scc_uart_driver);
-       driver_unregister(&cpm_smc_uart_driver);
+       of_unregister_platform_driver(&cpm_uart_driver);
        uart_unregister_driver(&cpm_reg);
 }