aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/boot/cpm-serial.c
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2007-09-28 15:06:16 -0400
committerKumar Gala <galak@kernel.crashing.org>2007-10-04 16:47:05 -0400
commit15f8c604a79c4840ed76eecf3af5d88b7c1dee9e (patch)
treed86815bc2daf835fee081ee7dac92cef8784f6a3 /arch/powerpc/boot/cpm-serial.c
parent3c5df5c26ed17828760945d59653a2e22e3fb63f (diff)
[POWERPC] cpm: Describe multi-user ram in its own device node.
The way the current CPM binding describes available multi-user (a.k.a. dual-ported) RAM doesn't work well when there are multiple free regions, and it doesn't work at all if the region doesn't begin at the start of the muram area (as the hardware needs to be programmed with offsets into this area). The latter situation can happen with SMC UARTs on CPM2, as its parameter RAM is relocatable, u-boot puts it at zero, and the kernel doesn't support moving it. It is now described with a muram node, similar to QE. The current CPM binding is sufficiently recent (i.e. never appeared in an official release) that compatibility with existing device trees is not an issue. The code supporting the new binding is shared between cpm1 and cpm2, rather than remain separated. QE should be able to use this code as well, once minor fixes are made to its device trees. Signed-off-by: Scott Wood <scottwood@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/boot/cpm-serial.c')
-rw-r--r--arch/powerpc/boot/cpm-serial.c44
1 files changed, 32 insertions, 12 deletions
diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
index fcb8b5e956bd..28296facb2ae 100644
--- a/arch/powerpc/boot/cpm-serial.c
+++ b/arch/powerpc/boot/cpm-serial.c
@@ -56,7 +56,8 @@ static struct cpm_smc *smc;
56static struct cpm_scc *scc; 56static struct cpm_scc *scc;
57struct cpm_bd *tbdf, *rbdf; 57struct cpm_bd *tbdf, *rbdf;
58static u32 cpm_cmd; 58static u32 cpm_cmd;
59static u8 *dpram_start; 59static u8 *muram_start;
60static u32 muram_offset;
60 61
61static void (*do_cmd)(int op); 62static void (*do_cmd)(int op);
62static void (*enable_port)(void); 63static void (*enable_port)(void);
@@ -114,13 +115,12 @@ static void scc_enable_port(void)
114 115
115static int cpm_serial_open(void) 116static int cpm_serial_open(void)
116{ 117{
117 int dpaddr = 0x800;
118 disable_port(); 118 disable_port();
119 119
120 out_8(&param->rfcr, 0x10); 120 out_8(&param->rfcr, 0x10);
121 out_8(&param->tfcr, 0x10); 121 out_8(&param->tfcr, 0x10);
122 122
123 rbdf = (struct cpm_bd *)(dpram_start + dpaddr); 123 rbdf = (struct cpm_bd *)muram_start;
124 rbdf->addr = (u8 *)(rbdf + 2); 124 rbdf->addr = (u8 *)(rbdf + 2);
125 rbdf->sc = 0xa000; 125 rbdf->sc = 0xa000;
126 rbdf->len = 1; 126 rbdf->len = 1;
@@ -131,8 +131,8 @@ static int cpm_serial_open(void)
131 tbdf->len = 1; 131 tbdf->len = 1;
132 132
133 sync(); 133 sync();
134 out_be16(&param->rbase, dpaddr); 134 out_be16(&param->rbase, muram_offset);
135 out_be16(&param->tbase, dpaddr + sizeof(struct cpm_bd)); 135 out_be16(&param->tbase, muram_offset + sizeof(struct cpm_bd));
136 136
137 do_cmd(CPM_CMD_INIT_RX_TX); 137 do_cmd(CPM_CMD_INIT_RX_TX);
138 138
@@ -178,7 +178,7 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
178 void *reg_virt[2]; 178 void *reg_virt[2];
179 int is_smc = 0, is_cpm2 = 0, n; 179 int is_smc = 0, is_cpm2 = 0, n;
180 unsigned long reg_phys; 180 unsigned long reg_phys;
181 void *parent; 181 void *parent, *muram;
182 182
183 if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) { 183 if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
184 is_smc = 1; 184 is_smc = 1;
@@ -229,16 +229,36 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
229 229
230 n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt)); 230 n = getprop(parent, "virtual-reg", reg_virt, sizeof(reg_virt));
231 if (n < (int)sizeof(reg_virt)) { 231 if (n < (int)sizeof(reg_virt)) {
232 for (n = 0; n < 2; n++) { 232 if (!dt_xlate_reg(parent, 0, &reg_phys, NULL))
233 if (!dt_xlate_reg(parent, n, &reg_phys, NULL)) 233 return -1;
234 return -1;
235 234
236 reg_virt[n] = (void *)reg_phys; 235 reg_virt[0] = (void *)reg_phys;
237 }
238 } 236 }
239 237
240 cpcr = reg_virt[0]; 238 cpcr = reg_virt[0];
241 dpram_start = reg_virt[1]; 239
240 muram = finddevice("/soc/cpm/muram/data");
241 if (!muram)
242 return -1;
243
244 /* For bootwrapper-compatible device trees, we assume that the first
245 * entry has at least 18 bytes, and that #address-cells/#data-cells
246 * is one for both parent and child.
247 */
248
249 n = getprop(muram, "virtual-reg", reg_virt, sizeof(reg_virt));
250 if (n < (int)sizeof(reg_virt)) {
251 if (!dt_xlate_reg(muram, 0, &reg_phys, NULL))
252 return -1;
253
254 reg_virt[0] = (void *)reg_phys;
255 }
256
257 muram_start = reg_virt[0];
258
259 n = getprop(muram, "reg", &muram_offset, 4);
260 if (n < 4)
261 return -1;
242 262
243 scdp->open = cpm_serial_open; 263 scdp->open = cpm_serial_open;
244 scdp->putc = cpm_serial_putc; 264 scdp->putc = cpm_serial_putc;