diff options
author | Laurent Pinchart <laurentp@cse-semaphore.com> | 2008-04-10 11:01:27 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2008-04-17 02:01:36 -0400 |
commit | d464df2667cf181419604e656773f80996cf0470 (patch) | |
tree | fedca2185763550331f0a73450c1d82f0c146ad6 /drivers/serial | |
parent | 1028d4f162796a99b87565b6b40b5fec79c242d0 (diff) |
[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>
Diffstat (limited to 'drivers/serial')
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart.h | 3 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_core.c | 19 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_cpm1.c | 14 | ||||
-rw-r--r-- | drivers/serial/cpm_uart/cpm_uart_cpm2.c | 52 |
4 files changed, 78 insertions, 10 deletions
diff --git a/drivers/serial/cpm_uart/cpm_uart.h b/drivers/serial/cpm_uart/cpm_uart.h index 32b9737759c4..0cc39f82d7c5 100644 --- a/drivers/serial/cpm_uart/cpm_uart.h +++ b/drivers/serial/cpm_uart/cpm_uart.h | |||
@@ -92,6 +92,9 @@ extern struct uart_cpm_port cpm_uart_ports[UART_NR]; | |||
92 | 92 | ||
93 | /* these are located in their respective files */ | 93 | /* these are located in their respective files */ |
94 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); | 94 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd); |
95 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
96 | struct device_node *np); | ||
97 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram); | ||
95 | int cpm_uart_init_portdesc(void); | 98 | int cpm_uart_init_portdesc(void); |
96 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); | 99 | int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); |
97 | void cpm_uart_freebuf(struct uart_cpm_port *pinfo); | 100 | 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 236af9d33851..a638ba0679ac 100644 --- a/drivers/serial/cpm_uart/cpm_uart_core.c +++ b/drivers/serial/cpm_uart/cpm_uart_core.c | |||
@@ -966,24 +966,23 @@ static int cpm_uart_init_port(struct device_node *np, | |||
966 | if (!mem) | 966 | if (!mem) |
967 | return -ENOMEM; | 967 | return -ENOMEM; |
968 | 968 | ||
969 | pram = of_iomap(np, 1); | ||
970 | if (!pram) { | ||
971 | ret = -ENOMEM; | ||
972 | goto out_mem; | ||
973 | } | ||
974 | |||
975 | if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || | 969 | if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || |
976 | of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { | 970 | of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { |
977 | pinfo->sccp = mem; | 971 | pinfo->sccp = mem; |
978 | pinfo->sccup = pram; | 972 | pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np); |
979 | } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || | 973 | } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || |
980 | of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { | 974 | of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { |
981 | pinfo->flags |= FLAG_SMC; | 975 | pinfo->flags |= FLAG_SMC; |
982 | pinfo->smcp = mem; | 976 | pinfo->smcp = mem; |
983 | pinfo->smcup = pram; | 977 | pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np); |
984 | } else { | 978 | } else { |
985 | ret = -ENODEV; | 979 | ret = -ENODEV; |
986 | goto out_pram; | 980 | goto out_mem; |
981 | } | ||
982 | |||
983 | if (!pram) { | ||
984 | ret = -ENOMEM; | ||
985 | goto out_mem; | ||
987 | } | 986 | } |
988 | 987 | ||
989 | pinfo->tx_nrfifos = TX_NUM_FIFO; | 988 | pinfo->tx_nrfifos = TX_NUM_FIFO; |
@@ -1007,7 +1006,7 @@ static int cpm_uart_init_port(struct device_node *np, | |||
1007 | return cpm_uart_request_port(&pinfo->port); | 1006 | return cpm_uart_request_port(&pinfo->port); |
1008 | 1007 | ||
1009 | out_pram: | 1008 | out_pram: |
1010 | iounmap(pram); | 1009 | cpm_uart_unmap_pram(pinfo, pram); |
1011 | out_mem: | 1010 | out_mem: |
1012 | iounmap(mem); | 1011 | iounmap(mem); |
1013 | return ret; | 1012 | return ret; |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c index 6ea0366e26ae..74f1432bb248 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c | |||
@@ -45,6 +45,8 @@ | |||
45 | #include <linux/serial_core.h> | 45 | #include <linux/serial_core.h> |
46 | #include <linux/kernel.h> | 46 | #include <linux/kernel.h> |
47 | 47 | ||
48 | #include <linux/of.h> | ||
49 | |||
48 | #include "cpm_uart.h" | 50 | #include "cpm_uart.h" |
49 | 51 | ||
50 | /**************************************************************/ | 52 | /**************************************************************/ |
@@ -54,6 +56,18 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | |||
54 | { | 56 | { |
55 | cpm_command(port->command, cmd); | 57 | cpm_command(port->command, cmd); |
56 | } | 58 | } |
59 | |||
60 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
61 | struct device_node *np) | ||
62 | { | ||
63 | return of_iomap(np, 1); | ||
64 | } | ||
65 | |||
66 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) | ||
67 | { | ||
68 | iounmap(pram); | ||
69 | } | ||
70 | |||
57 | #else | 71 | #else |
58 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | 72 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) |
59 | { | 73 | { |
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c index d9af06a791ba..bb862e2f54cf 100644 --- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c +++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c | |||
@@ -41,6 +41,9 @@ | |||
41 | #include <asm/io.h> | 41 | #include <asm/io.h> |
42 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
43 | #include <asm/fs_pd.h> | 43 | #include <asm/fs_pd.h> |
44 | #ifdef CONFIG_PPC_CPM_NEW_BINDING | ||
45 | #include <asm/prom.h> | ||
46 | #endif | ||
44 | 47 | ||
45 | #include <linux/serial_core.h> | 48 | #include <linux/serial_core.h> |
46 | #include <linux/kernel.h> | 49 | #include <linux/kernel.h> |
@@ -54,6 +57,55 @@ void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | |||
54 | { | 57 | { |
55 | cpm_command(port->command, cmd); | 58 | cpm_command(port->command, cmd); |
56 | } | 59 | } |
60 | |||
61 | void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, | ||
62 | struct device_node *np) | ||
63 | { | ||
64 | void __iomem *pram; | ||
65 | unsigned long offset; | ||
66 | struct resource res; | ||
67 | unsigned long len; | ||
68 | |||
69 | /* Don't remap parameter RAM if it has already been initialized | ||
70 | * during console setup. | ||
71 | */ | ||
72 | if (IS_SMC(port) && port->smcup) | ||
73 | return port->smcup; | ||
74 | else if (!IS_SMC(port) && port->sccup) | ||
75 | return port->sccup; | ||
76 | |||
77 | if (of_address_to_resource(np, 1, &res)) | ||
78 | return NULL; | ||
79 | |||
80 | len = 1 + res.end - res.start; | ||
81 | pram = ioremap(res.start, len); | ||
82 | if (!pram) | ||
83 | return NULL; | ||
84 | |||
85 | if (!IS_SMC(port)) | ||
86 | return pram; | ||
87 | |||
88 | if (len != 2) { | ||
89 | printk(KERN_WARNING "cpm_uart[%d]: device tree references " | ||
90 | "SMC pram, using boot loader/wrapper pram mapping. " | ||
91 | "Please fix your device tree to reference the pram " | ||
92 | "base register instead.\n", | ||
93 | port->port.line); | ||
94 | return pram; | ||
95 | } | ||
96 | |||
97 | offset = cpm_dpalloc(PROFF_SMC_SIZE, 64); | ||
98 | out_be16(pram, offset); | ||
99 | iounmap(pram); | ||
100 | return cpm_muram_addr(offset); | ||
101 | } | ||
102 | |||
103 | void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) | ||
104 | { | ||
105 | if (!IS_SMC(port)) | ||
106 | iounmap(pram); | ||
107 | } | ||
108 | |||
57 | #else | 109 | #else |
58 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) | 110 | void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) |
59 | { | 111 | { |