aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurentp@cse-semaphore.com>2008-04-10 11:01:59 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-04-17 02:01:37 -0400
commitc2dd3529f35de9e2f51eba9bbf9969f5dc8382d4 (patch)
tree51af219a028b66325a4a70331297e2ecc81a0d33
parentda0a5f0c65913e4ec0a70a5019ce0a7bcaab21c9 (diff)
[POWERPC] cpm-serial: Relocate CPM buffer descriptors and SMC parameter ram.
This patch relocates the buffer descriptors and the SMC parameter RAM at the end of the first CPM muram chunk, as described in the device tree. This allows device trees to stop excluding SMC parameter ram allocated by the boot loader from the CPM muram node. 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>
-rw-r--r--arch/powerpc/Kconfig.debug2
-rw-r--r--arch/powerpc/boot/cpm-serial.c89
2 files changed, 69 insertions, 22 deletions
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index db7cc34c24d4..a86d8d853214 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -269,7 +269,7 @@ config PPC_EARLY_DEBUG_CPM_ADDR
269 hex "CPM UART early debug transmit descriptor address" 269 hex "CPM UART early debug transmit descriptor address"
270 depends on PPC_EARLY_DEBUG_CPM 270 depends on PPC_EARLY_DEBUG_CPM
271 default "0xfa202008" if PPC_EP88XC 271 default "0xfa202008" if PPC_EP88XC
272 default "0xf0000008" if CPM2 272 default "0xf0001ff8" if CPM2
273 default "0xff002008" if CPM1 273 default "0xff002008" if CPM1
274 help 274 help
275 This specifies the address of the transmit descriptor 275 This specifies the address of the transmit descriptor
diff --git a/arch/powerpc/boot/cpm-serial.c b/arch/powerpc/boot/cpm-serial.c
index 1f6225aad298..19dc15abe43d 100644
--- a/arch/powerpc/boot/cpm-serial.c
+++ b/arch/powerpc/boot/cpm-serial.c
@@ -11,6 +11,7 @@
11#include "types.h" 11#include "types.h"
12#include "io.h" 12#include "io.h"
13#include "ops.h" 13#include "ops.h"
14#include "page.h"
14 15
15struct cpm_scc { 16struct cpm_scc {
16 u32 gsmrl; 17 u32 gsmrl;
@@ -42,6 +43,22 @@ struct cpm_param {
42 u16 tbase; 43 u16 tbase;
43 u8 rfcr; 44 u8 rfcr;
44 u8 tfcr; 45 u8 tfcr;
46 u16 mrblr;
47 u32 rstate;
48 u8 res1[4];
49 u16 rbptr;
50 u8 res2[6];
51 u32 tstate;
52 u8 res3[4];
53 u16 tbptr;
54 u8 res4[6];
55 u16 maxidl;
56 u16 idlc;
57 u16 brkln;
58 u16 brkec;
59 u16 brkcr;
60 u16 rmask;
61 u8 res5[4];
45}; 62};
46 63
47struct cpm_bd { 64struct cpm_bd {
@@ -54,10 +71,10 @@ static void *cpcr;
54static struct cpm_param *param; 71static struct cpm_param *param;
55static struct cpm_smc *smc; 72static struct cpm_smc *smc;
56static struct cpm_scc *scc; 73static struct cpm_scc *scc;
57struct cpm_bd *tbdf, *rbdf; 74static struct cpm_bd *tbdf, *rbdf;
58static u32 cpm_cmd; 75static u32 cpm_cmd;
59static u8 *muram_start; 76static void *cbd_addr;
60static u32 muram_offset; 77static u32 cbd_offset;
61 78
62static void (*do_cmd)(int op); 79static void (*do_cmd)(int op);
63static void (*enable_port)(void); 80static void (*enable_port)(void);
@@ -119,20 +136,25 @@ static int cpm_serial_open(void)
119 136
120 out_8(&param->rfcr, 0x10); 137 out_8(&param->rfcr, 0x10);
121 out_8(&param->tfcr, 0x10); 138 out_8(&param->tfcr, 0x10);
122 139 out_be16(&param->mrblr, 1);
123 rbdf = (struct cpm_bd *)muram_start; 140 out_be16(&param->maxidl, 0);
124 rbdf->addr = (u8 *)(rbdf + 2); 141 out_be16(&param->brkec, 0);
142 out_be16(&param->brkln, 0);
143 out_be16(&param->brkcr, 0);
144
145 rbdf = cbd_addr;
146 rbdf->addr = (u8 *)rbdf - 1;
125 rbdf->sc = 0xa000; 147 rbdf->sc = 0xa000;
126 rbdf->len = 1; 148 rbdf->len = 1;
127 149
128 tbdf = rbdf + 1; 150 tbdf = rbdf + 1;
129 tbdf->addr = (u8 *)(rbdf + 2) + 1; 151 tbdf->addr = (u8 *)rbdf - 2;
130 tbdf->sc = 0x2000; 152 tbdf->sc = 0x2000;
131 tbdf->len = 1; 153 tbdf->len = 1;
132 154
133 sync(); 155 sync();
134 out_be16(&param->rbase, muram_offset); 156 out_be16(&param->rbase, cbd_offset);
135 out_be16(&param->tbase, muram_offset + sizeof(struct cpm_bd)); 157 out_be16(&param->tbase, cbd_offset + sizeof(struct cpm_bd));
136 158
137 do_cmd(CPM_CMD_INIT_RX_TX); 159 do_cmd(CPM_CMD_INIT_RX_TX);
138 160
@@ -175,9 +197,12 @@ static unsigned char cpm_serial_getc(void)
175 197
176int cpm_console_init(void *devp, struct serial_console_data *scdp) 198int cpm_console_init(void *devp, struct serial_console_data *scdp)
177{ 199{
178 void *reg_virt[2]; 200 void *vreg[2];
179 int is_smc = 0, is_cpm2 = 0, n; 201 u32 reg[2];
202 int is_smc = 0, is_cpm2 = 0;
180 void *parent, *muram; 203 void *parent, *muram;
204 void *muram_addr;
205 unsigned long muram_offset, muram_size;
181 206
182 if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) { 207 if (dt_is_compatible(devp, "fsl,cpm1-smc-uart")) {
183 is_smc = 1; 208 is_smc = 1;
@@ -201,19 +226,18 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
201 else 226 else
202 do_cmd = cpm1_cmd; 227 do_cmd = cpm1_cmd;
203 228
204 n = getprop(devp, "fsl,cpm-command", &cpm_cmd, 4); 229 if (getprop(devp, "fsl,cpm-command", &cpm_cmd, 4) < 4)
205 if (n < 4)
206 return -1; 230 return -1;
207 231
208 if (dt_get_virtual_reg(devp, reg_virt, 2) < 2) 232 if (dt_get_virtual_reg(devp, vreg, 2) < 2)
209 return -1; 233 return -1;
210 234
211 if (is_smc) 235 if (is_smc)
212 smc = reg_virt[0]; 236 smc = vreg[0];
213 else 237 else
214 scc = reg_virt[0]; 238 scc = vreg[0];
215 239
216 param = reg_virt[1]; 240 param = vreg[1];
217 241
218 parent = get_parent(devp); 242 parent = get_parent(devp);
219 if (!parent) 243 if (!parent)
@@ -227,17 +251,40 @@ int cpm_console_init(void *devp, struct serial_console_data *scdp)
227 return -1; 251 return -1;
228 252
229 /* For bootwrapper-compatible device trees, we assume that the first 253 /* For bootwrapper-compatible device trees, we assume that the first
230 * entry has at least 18 bytes, and that #address-cells/#data-cells 254 * entry has at least 128 bytes, and that #address-cells/#data-cells
231 * is one for both parent and child. 255 * is one for both parent and child.
232 */ 256 */
233 257
234 if (dt_get_virtual_reg(muram, (void **)&muram_start, 1) < 1) 258 if (dt_get_virtual_reg(muram, &muram_addr, 1) < 1)
235 return -1; 259 return -1;
236 260
237 n = getprop(muram, "reg", &muram_offset, 4); 261 if (getprop(muram, "reg", reg, 8) < 8)
238 if (n < 4)
239 return -1; 262 return -1;
240 263
264 muram_offset = reg[0];
265 muram_size = reg[1];
266
267 /* Store the buffer descriptors at the end of the first muram chunk.
268 * For SMC ports on CPM2-based platforms, relocate the parameter RAM
269 * just before the buffer descriptors.
270 */
271
272 cbd_offset = muram_offset + muram_size - 2 * sizeof(struct cpm_bd);
273
274 if (is_cpm2 && is_smc) {
275 u16 *smc_base = (u16 *)param;
276 u16 pram_offset;
277
278 pram_offset = cbd_offset - 64;
279 pram_offset = _ALIGN_DOWN(pram_offset, 64);
280
281 disable_port();
282 out_be16(smc_base, pram_offset);
283 param = muram_addr - muram_offset + pram_offset;
284 }
285
286 cbd_addr = muram_addr - muram_offset + cbd_offset;
287
241 scdp->open = cpm_serial_open; 288 scdp->open = cpm_serial_open;
242 scdp->putc = cpm_serial_putc; 289 scdp->putc = cpm_serial_putc;
243 scdp->getc = cpm_serial_getc; 290 scdp->getc = cpm_serial_getc;