[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:
committed by
Kumar Gala
parent
1028d4f162
commit
d464df2667
@@ -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,
|
|||||||
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,
|
|||||||
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 @@
|
|||||||
#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)
|
|||||||
{
|
{
|
||||||
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 @@
|
|||||||
#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)
|
|||||||
{
|
{
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user