This patch allocates parameter RAM for SMC serial ports without relying on
previous initialisation by a boot loader or a wrapper layer.

SMC parameter RAM on CPM2-based platforms can be allocated anywhere in the
general-purpose areas of the dual-port RAM. The current code relies on the
boot loader to allocate a section of general-purpose CPM RAM and gets the
section address from the device tree.

This patch modifies the device tree address usage to reference the SMC
parameter RAM base pointer instead of a pre-allocated RAM section and
allocates memory from the CPM dual-port RAM when initialising the SMC port.
CPM1-based platforms are not affected.

Signed-off-by: Laurent Pinchart <[EMAIL PROTECTED]>
---
 drivers/serial/cpm_uart/cpm_uart.h      |    3 ++
 drivers/serial/cpm_uart/cpm_uart_core.c |   19 +++++------
 drivers/serial/cpm_uart/cpm_uart_cpm1.c |   12 +++++++
 drivers/serial/cpm_uart/cpm_uart_cpm2.c |   52 +++++++++++++++++++++++++++++++
 4 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/drivers/serial/cpm_uart/cpm_uart.h 
b/drivers/serial/cpm_uart/cpm_uart.h
index 80a7d60..5334653 100644
--- a/drivers/serial/cpm_uart/cpm_uart.h
+++ b/drivers/serial/cpm_uart/cpm_uart.h
@@ -93,6 +93,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
 
 /* these are located in their respective files */
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
+void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
+                               struct device_node *np);
+void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram);
 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);
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c 
b/drivers/serial/cpm_uart/cpm_uart_core.c
index 1ea123c..3a44a3f 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -997,24 +997,23 @@ static int cpm_uart_init_port(struct device_node *np,
        if (!mem)
                return -ENOMEM;
 
-       pram = of_iomap(np, 1);
-       if (!pram) {
-               ret = -ENOMEM;
-               goto out_mem;
-       }
-
        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;
+               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;
+               pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
        } else {
                ret = -ENODEV;
-               goto out_pram;
+               goto out_mem;
+       }
+
+       if (!pram) {
+               ret = -ENOMEM;
+               goto out_mem;
        }
 
        pinfo->tx_nrfifos = TX_NUM_FIFO;
@@ -1038,7 +1037,7 @@ static int cpm_uart_init_port(struct device_node *np,
        return cpm_uart_request_port(&pinfo->port);
 
 out_pram:
-       iounmap(pram);
+       cpm_uart_unmap_pram(pinfo, pram);
 out_mem:
        iounmap(mem);
        return ret;
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c 
b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 6ea0366..e692593 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -54,6 +54,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
        cpm_command(port->command, cmd);
 }
+
+void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
+                               struct device_node *np)
+{
+       return of_iomap(np, 1);
+}
+
+void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
+{
+       iounmap(pram);
+}
+
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c 
b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index 6291094..a4cfb0b 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -41,6 +41,9 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/fs_pd.h>
+#ifdef CONFIG_PPC_CPM_NEW_BINDING
+#include <asm/prom.h>
+#endif
 
 #include <linux/serial_core.h>
 #include <linux/kernel.h>
@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
        cpm_command(port->command, cmd);
 }
+
+void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port,
+                               struct device_node *np)
+{
+       void __iomem *pram;
+       unsigned long offset;
+       struct resource res;
+       unsigned long len;
+
+       /* Don't remap parameter RAM if it has already been initialized
+        * during console setup.
+        */
+       if (IS_SMC(port) && port->smcup)
+               return port->smcup;
+       else if (!IS_SMC(port) && port->sccup)
+               return port->sccup;
+
+       if (of_address_to_resource(np, 1, &res))
+               return NULL;
+
+       len = 1 + res.end - res.start;
+       pram = ioremap(res.start, len);
+       if (!pram)
+               return NULL;
+
+       if (!IS_SMC(port))
+               return pram;
+
+       if (len != 2) {
+               printk(KERN_WARNING "cpm_uart[%d]: device tree references "
+                       "SMC pram, using boot loader/wrapper pram mapping. "
+                       "Please fix your device tree to reference the pram "
+                       "base register instead.\n",
+                       port->port.line);
+               return pram;
+       }
+
+       offset = cpm_dpalloc(PROFF_SMC_SIZE, 64);
+       out_be16(pram, offset);
+       iounmap(pram);
+       return cpm_muram_addr(offset);
+}
+
+void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram)
+{
+       if (!IS_SMC(port))
+               iounmap(pram);
+}
+
 #else
 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
 {
-- 
1.5.0


-- 
Laurent Pinchart
CSE Semaphore Belgium

Chaussée de Bruxelles, 732A
B-1410 Waterloo
Belgium

T +32 (2) 387 42 59
F +32 (2) 387 42 75

Attachment: pgp4sjnu31XsH.pgp
Description: PGP signature

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to