Commit d464df26 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Kumar Gala

[POWERPC] cpm_uart: Allocate DPRAM memory for SMC ports on CPM2-based platforms.

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: default avatarLaurent Pinchart <laurentp@cse-semaphore.com>
Acked-by: default avatarScott Wood <scottwood@freescale.com>
Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
parent 1028d4f1
...@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; ...@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR];
/* these are located in their respective files */ /* these are located in their respective files */
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); 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_init_portdesc(void);
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
void cpm_uart_freebuf(struct uart_cpm_port *pinfo); void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
......
...@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np, ...@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np,
if (!mem) if (!mem)
return -ENOMEM; return -ENOMEM;
pram = of_iomap(np, 1);
if (!pram) {
ret = -ENOMEM;
goto out_mem;
}
if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
pinfo->sccp = mem; 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") || } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
pinfo->flags |= FLAG_SMC; pinfo->flags |= FLAG_SMC;
pinfo->smcp = mem; pinfo->smcp = mem;
pinfo->smcup = pram; pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np);
} else { } else {
ret = -ENODEV; ret = -ENODEV;
goto out_pram; goto out_mem;
}
if (!pram) {
ret = -ENOMEM;
goto out_mem;
} }
pinfo->tx_nrfifos = TX_NUM_FIFO; pinfo->tx_nrfifos = TX_NUM_FIFO;
...@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np, ...@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np,
return cpm_uart_request_port(&pinfo->port); return cpm_uart_request_port(&pinfo->port);
out_pram: out_pram:
iounmap(pram); cpm_uart_unmap_pram(pinfo, pram);
out_mem: out_mem:
iounmap(mem); iounmap(mem);
return ret; return ret;
......
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h>
#include "cpm_uart.h" #include "cpm_uart.h"
/**************************************************************/ /**************************************************************/
...@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) ...@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{ {
cpm_command(port->command, 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 #else
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{ {
......
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/fs_pd.h> #include <asm/fs_pd.h>
#ifdef CONFIG_PPC_CPM_NEW_BINDING
#include <asm/prom.h>
#endif
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) ...@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{ {
cpm_command(port->command, 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 #else
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment