Pull acpi_device_handle_cleanup into release branch
[pandora-kernel.git] / drivers / serial / cpm_uart / cpm_uart_core.c
index 9a5b044..90ff96e 100644 (file)
@@ -12,7 +12,8 @@
  *
  *  Copyright (C) 2004 Freescale Semiconductor, Inc.
  *            (C) 2004 Intracom, S.A.
- *            (C) 2005 MontaVista Software, Inc. by Vitaly Bordug <vbordug@ru.mvista.com>
+ *            (C) 2005-2006 MontaVista Software, Inc.
+ *             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
@@ -30,7 +31,6 @@
  *
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/ioport.h>
@@ -72,19 +72,6 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
 
 /**************************************************************/
 
-static inline unsigned long cpu2cpm_addr(void *addr)
-{
-       if ((unsigned long)addr >= CPM_ADDR)
-               return (unsigned long)addr;
-       return virt_to_bus(addr);
-}
-
-static inline void *cpm2cpu_addr(unsigned long addr)
-{
-       if (addr >= CPM_ADDR)
-               return (void *)addr;
-       return bus_to_virt(addr);
-}
 
 /* Place-holder for board-specific stuff */
 struct platform_device* __attribute__ ((weak)) __init
@@ -94,7 +81,7 @@ early_uart_get_pdev(int index)
 }
 
 
-void cpm_uart_count(void)
+static void cpm_uart_count(void)
 {
        cpm_uart_nr = 0;
 #ifdef CONFIG_SERIAL_CPM_SMC1
@@ -117,6 +104,21 @@ void cpm_uart_count(void)
 #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
 */
@@ -290,7 +292,7 @@ static void cpm_uart_int_rx(struct uart_port *port, struct pt_regs *regs)
                }
 
                /* get pointer */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                /* loop through the buffer */
                while (i-- > 0) {
@@ -470,7 +472,11 @@ static void cpm_uart_shutdown(struct uart_port *port)
                }
 
                /* Shut them really down and reinit buffer descriptors */
-               cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+               if (IS_SMC(pinfo))
+                       cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
+               else
+                       cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
+
                cpm_uart_initbd(pinfo);
        }
 }
@@ -633,7 +639,7 @@ 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);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                *p++ = port->x_char;
                bdp->cbd_datlen = 1;
@@ -660,7 +666,7 @@ static int cpm_uart_tx_pump(struct uart_port *port)
 
        while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
                count = 0;
-               p = cpm2cpu_addr(bdp->cbd_bufaddr);
+               p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
                while (count < pinfo->tx_fifosize) {
                        *p++ = xmit->buf[xmit->tail];
                        xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -709,12 +715,12 @@ 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);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
                bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
                mem_addr += pinfo->rx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
 
        /* Set the physical address of the host memory
@@ -724,12 +730,12 @@ 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);
+               bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
                bdp->cbd_sc = BD_SC_INTRPT;
                mem_addr += pinfo->tx_fifosize;
        }
 
-       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr);
+       bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
        bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
 }
 
@@ -1021,7 +1027,11 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
        int line;
        u32 mem, pram;
 
-       for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);
+       line = cpm_uart_id2nr(idx);
+       if(line < 0) {
+               printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+               return -1;
+       }
 
        pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
 
@@ -1099,7 +1109,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                 * If the buffer address is in the CPM DPRAM, don't
                 * convert it.
                 */
-               cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+               cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                *cp = *s;
 
@@ -1116,7 +1126,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
                        while ((bdp->cbd_sc & BD_SC_READY) != 0)
                                ;
 
-                       cp = cpm2cpu_addr(bdp->cbd_bufaddr);
+                       cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
 
                        *cp = 13;
                        bdp->cbd_datlen = 1;
@@ -1153,14 +1163,16 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        struct fs_uart_platform_info *pdata;
        struct platform_device* pdev = early_uart_get_pdev(co->index);
 
-       port =
-           (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
-       pinfo = (struct uart_cpm_port *)port;
        if (!pdev) {
                pr_info("cpm_uart: console: compat mode\n");
                /* compatibility - will be cleaned up */
                cpm_uart_init_portdesc();
+       }
 
+       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 {
@@ -1254,8 +1266,7 @@ static int cpm_uart_drv_probe(struct device *dev)
        }
 
        pdata = pdev->dev.platform_data;
-       pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n",
-                       cpm_uart_port_map[pdata->fs_no]);
+       pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
 
        if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
                return ret;
@@ -1274,7 +1285,7 @@ static int cpm_uart_drv_remove(struct 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_port_map[pdata->fs_no]);
+                       cpm_uart_id2nr(pdata->fs_no));
 
         uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
         return 0;