[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: Laurent Pinchart <laurentp@cse-semaphore.com> Acked-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
This commit is contained in:
parent
1028d4f162
commit
d464df2667
4 changed files with 78 additions and 10 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
@ -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;
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include <linux/serial_core.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "cpm_uart.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue