Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh64-2.6
[pandora-kernel.git] / drivers / serial / cpm_uart / cpm_uart_core.c
index ced193b..a0d6136 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>
@@ -46,6 +46,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/delay.h>
+#include <asm/fs_pd.h>
 
 #if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
 #define SUPPORT_SYSRQ
@@ -81,7 +82,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
@@ -104,6 +105,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
 */
@@ -457,7 +473,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);
        }
 }
@@ -1003,12 +1023,18 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 {
        struct resource *r;
        struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
-       int idx = pdata->fs_no; /* It is UART_SMCx or UART_SCCx index */
+       int idx;        /* It is UART_SMCx or UART_SCCx index */
        struct uart_cpm_port *pinfo;
        int line;
        u32 mem, pram;
 
-       for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);
+        idx = pdata->fs_no = fs_uart_get_id(pdata);
+
+       line = cpm_uart_id2nr(idx);
+       if(line < 0) {
+               printk(KERN_ERR"%s(): port %d is not registered", __FUNCTION__, idx);
+               return -EINVAL;
+       }
 
        pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];
 
@@ -1021,11 +1047,11 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
 
        if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
                return -EINVAL;
-       mem = r->start;
+       mem = (u32)ioremap(r->start, r->end - r->start + 1);
 
        if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
                return -EINVAL;
-       pram = r->start;
+       pram = (u32)ioremap(r->start, r->end - r->start + 1);
 
        if(idx > fsid_smc2_uart) {
                pinfo->sccp = (scc_t *)mem;
@@ -1140,21 +1166,23 @@ 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 {
                pdata = pdev->dev.platform_data;
                if (pdata)
                        if (pdata->init_ioports)
-                               pdata->init_ioports();
+                               pdata->init_ioports(pdata);
 
                cpm_uart_drv_get_platform_data(pdev, 1);
        }
@@ -1164,11 +1192,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
        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
+               if ((baud = uart_baudrate()) == -1)
                        baud = 9600;
        }
 
@@ -1241,14 +1265,14 @@ 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]);
 
        if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
                return ret;
 
+       pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n", cpm_uart_id2nr(pdata->fs_no));
+
        if (pdata->init_ioports)
-                pdata->init_ioports();
+                pdata->init_ioports(pdata);
 
        ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
 
@@ -1261,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;