[PATCHv4 1/5] cpm_uart: Allocate DPRAM memory for SMC ports on CPM2-based platforms.
Laurent Pinchart
laurentp at cse-semaphore.com
Tue Apr 1 23:34:00 EST 2008
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 <laurentp at cse-semaphore.com>
---
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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: not available
URL: <http://lists.ozlabs.org/pipermail/linuxppc-dev/attachments/20080401/2324a0e5/attachment.pgp>
More information about the Linuxppc-dev
mailing list