Skip to content

Commit

Permalink
[POWERPC] cpm_uart: Allocate DPRAM memory for SMC ports on CPM2-based…
Browse files Browse the repository at this point in the history
… 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: Laurent Pinchart <laurentp@cse-semaphore.com>
Acked-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
  • Loading branch information
Laurent Pinchart authored and Kumar Gala committed Apr 17, 2008
1 parent 1028d4f commit d464df2
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 10 deletions.
3 changes: 3 additions & 0 deletions drivers/serial/cpm_uart/cpm_uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,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);
Expand Down
19 changes: 9 additions & 10 deletions drivers/serial/cpm_uart/cpm_uart_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,24 +966,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;
Expand All @@ -1007,7 +1006,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;
Expand Down
14 changes: 14 additions & 0 deletions drivers/serial/cpm_uart/cpm_uart_cpm1.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <linux/serial_core.h>
#include <linux/kernel.h>

#include <linux/of.h>

#include "cpm_uart.h"

/**************************************************************/
Expand All @@ -54,6 +56,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)
{
Expand Down
52 changes: 52 additions & 0 deletions drivers/serial/cpm_uart/cpm_uart_cpm2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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)
{
Expand Down

0 comments on commit d464df2

Please sign in to comment.