Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Laurent Pinchart and committed by
Kumar Gala
d464df26 1028d4f1

+78 -10
+3
drivers/serial/cpm_uart/cpm_uart.h
··· 92 92 93 93 /* these are located in their respective files */ 94 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 98 int cpm_uart_init_portdesc(void); 96 99 int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con); 97 100 void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
+9 -10
drivers/serial/cpm_uart/cpm_uart_core.c
··· 966 966 if (!mem) 967 967 return -ENOMEM; 968 968 969 - pram = of_iomap(np, 1); 970 - if (!pram) { 971 - ret = -ENOMEM; 972 - goto out_mem; 973 - } 974 - 975 969 if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") || 976 970 of_device_is_compatible(np, "fsl,cpm2-scc-uart")) { 977 971 pinfo->sccp = mem; 978 - pinfo->sccup = pram; 972 + pinfo->sccup = pram = cpm_uart_map_pram(pinfo, np); 979 973 } else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") || 980 974 of_device_is_compatible(np, "fsl,cpm2-smc-uart")) { 981 975 pinfo->flags |= FLAG_SMC; 982 976 pinfo->smcp = mem; 983 - pinfo->smcup = pram; 977 + pinfo->smcup = pram = cpm_uart_map_pram(pinfo, np); 984 978 } else { 985 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 988 pinfo->tx_nrfifos = TX_NUM_FIFO; ··· 1006 1007 return cpm_uart_request_port(&pinfo->port); 1007 1008 1008 1009 out_pram: 1009 - iounmap(pram); 1010 + cpm_uart_unmap_pram(pinfo, pram); 1010 1011 out_mem: 1011 1012 iounmap(mem); 1012 1013 return ret;
+14
drivers/serial/cpm_uart/cpm_uart_cpm1.c
··· 45 45 #include <linux/serial_core.h> 46 46 #include <linux/kernel.h> 47 47 48 + #include <linux/of.h> 49 + 48 50 #include "cpm_uart.h" 49 51 50 52 /**************************************************************/ ··· 56 54 { 57 55 cpm_command(port->command, cmd); 58 56 } 57 + 58 + void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, 59 + struct device_node *np) 60 + { 61 + return of_iomap(np, 1); 62 + } 63 + 64 + void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) 65 + { 66 + iounmap(pram); 67 + } 68 + 59 69 #else 60 70 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) 61 71 {
+52
drivers/serial/cpm_uart/cpm_uart_cpm2.c
··· 41 41 #include <asm/io.h> 42 42 #include <asm/irq.h> 43 43 #include <asm/fs_pd.h> 44 + #ifdef CONFIG_PPC_CPM_NEW_BINDING 45 + #include <asm/prom.h> 46 + #endif 44 47 45 48 #include <linux/serial_core.h> 46 49 #include <linux/kernel.h> ··· 57 54 { 58 55 cpm_command(port->command, cmd); 59 56 } 57 + 58 + void __iomem *cpm_uart_map_pram(struct uart_cpm_port *port, 59 + struct device_node *np) 60 + { 61 + void __iomem *pram; 62 + unsigned long offset; 63 + struct resource res; 64 + unsigned long len; 65 + 66 + /* Don't remap parameter RAM if it has already been initialized 67 + * during console setup. 68 + */ 69 + if (IS_SMC(port) && port->smcup) 70 + return port->smcup; 71 + else if (!IS_SMC(port) && port->sccup) 72 + return port->sccup; 73 + 74 + if (of_address_to_resource(np, 1, &res)) 75 + return NULL; 76 + 77 + len = 1 + res.end - res.start; 78 + pram = ioremap(res.start, len); 79 + if (!pram) 80 + return NULL; 81 + 82 + if (!IS_SMC(port)) 83 + return pram; 84 + 85 + if (len != 2) { 86 + printk(KERN_WARNING "cpm_uart[%d]: device tree references " 87 + "SMC pram, using boot loader/wrapper pram mapping. " 88 + "Please fix your device tree to reference the pram " 89 + "base register instead.\n", 90 + port->port.line); 91 + return pram; 92 + } 93 + 94 + offset = cpm_dpalloc(PROFF_SMC_SIZE, 64); 95 + out_be16(pram, offset); 96 + iounmap(pram); 97 + return cpm_muram_addr(offset); 98 + } 99 + 100 + void cpm_uart_unmap_pram(struct uart_cpm_port *port, void __iomem *pram) 101 + { 102 + if (!IS_SMC(port)) 103 + iounmap(pram); 104 + } 105 + 60 106 #else 61 107 void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd) 62 108 {