[PATCH] x86_64: x86_64-enable-large-bzImage.patch
[usb.git] / arch / arm / common / uengine.c
blobdfca596a9a276b90a76b6e02a6528c80fd8acdb5
1 /*
2 * Generic library functions for the microengines found on the Intel
3 * IXP2000 series of network processors.
5 * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
6 * Dedicated to Marija Kulikova.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 2.1 of the
11 * License, or (at your option) any later version.
14 #include <linux/config.h>
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/slab.h>
18 #include <linux/module.h>
19 #include <linux/string.h>
20 #include <asm/hardware.h>
21 #include <asm/arch/hardware.h>
22 #include <asm/hardware/uengine.h>
23 #include <asm/io.h>
25 #if defined(CONFIG_ARCH_IXP2000)
26 #define IXP_UENGINE_CSR_VIRT_BASE IXP2000_UENGINE_CSR_VIRT_BASE
27 #define IXP_PRODUCT_ID IXP2000_PRODUCT_ID
28 #define IXP_MISC_CONTROL IXP2000_MISC_CONTROL
29 #define IXP_RESET1 IXP2000_RESET1
30 #else
31 #if defined(CONFIG_ARCH_IXP23XX)
32 #define IXP_UENGINE_CSR_VIRT_BASE IXP23XX_UENGINE_CSR_VIRT_BASE
33 #define IXP_PRODUCT_ID IXP23XX_PRODUCT_ID
34 #define IXP_MISC_CONTROL IXP23XX_MISC_CONTROL
35 #define IXP_RESET1 IXP23XX_RESET1
36 #else
37 #error unknown platform
38 #endif
39 #endif
41 #define USTORE_ADDRESS 0x000
42 #define USTORE_DATA_LOWER 0x004
43 #define USTORE_DATA_UPPER 0x008
44 #define CTX_ENABLES 0x018
45 #define CC_ENABLE 0x01c
46 #define CSR_CTX_POINTER 0x020
47 #define INDIRECT_CTX_STS 0x040
48 #define ACTIVE_CTX_STS 0x044
49 #define INDIRECT_CTX_SIG_EVENTS 0x048
50 #define INDIRECT_CTX_WAKEUP_EVENTS 0x050
51 #define NN_PUT 0x080
52 #define NN_GET 0x084
53 #define TIMESTAMP_LOW 0x0c0
54 #define TIMESTAMP_HIGH 0x0c4
55 #define T_INDEX_BYTE_INDEX 0x0f4
56 #define LOCAL_CSR_STATUS 0x180
58 u32 ixp2000_uengine_mask;
60 static void *ixp2000_uengine_csr_area(int uengine)
62 return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
66 * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR
67 * space means that the microengine we tried to access was also trying
68 * to access its own CSR space on the same clock cycle as we did. When
69 * this happens, we lose the arbitration process by default, and the
70 * read or write we tried to do was not actually performed, so we try
71 * again until it succeeds.
73 u32 ixp2000_uengine_csr_read(int uengine, int offset)
75 void *uebase;
76 u32 *local_csr_status;
77 u32 *reg;
78 u32 value;
80 uebase = ixp2000_uengine_csr_area(uengine);
82 local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
83 reg = (u32 *)(uebase + offset);
84 do {
85 value = ixp2000_reg_read(reg);
86 } while (ixp2000_reg_read(local_csr_status) & 1);
88 return value;
90 EXPORT_SYMBOL(ixp2000_uengine_csr_read);
92 void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
94 void *uebase;
95 u32 *local_csr_status;
96 u32 *reg;
98 uebase = ixp2000_uengine_csr_area(uengine);
100 local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
101 reg = (u32 *)(uebase + offset);
102 do {
103 ixp2000_reg_write(reg, value);
104 } while (ixp2000_reg_read(local_csr_status) & 1);
106 EXPORT_SYMBOL(ixp2000_uengine_csr_write);
108 void ixp2000_uengine_reset(u32 uengine_mask)
110 u32 value;
112 value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
114 uengine_mask &= ixp2000_uengine_mask;
115 ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
116 ixp2000_reg_wrb(IXP_RESET1, value);
118 EXPORT_SYMBOL(ixp2000_uengine_reset);
120 void ixp2000_uengine_set_mode(int uengine, u32 mode)
123 * CTL_STR_PAR_EN: unconditionally enable parity checking on
124 * control store.
126 mode |= 0x10000000;
127 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode);
130 * Enable updating of condition codes.
132 ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000);
135 * Initialise other per-microengine registers.
137 ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00);
138 ixp2000_uengine_csr_write(uengine, NN_GET, 0x00);
139 ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0);
141 EXPORT_SYMBOL(ixp2000_uengine_set_mode);
143 static int make_even_parity(u32 x)
145 return hweight32(x) & 1;
148 static void ustore_write(int uengine, u64 insn)
151 * Generate even parity for top and bottom 20 bits.
153 insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41;
154 insn |= (u64)make_even_parity(insn & 0x000fffff) << 40;
157 * Write to microstore. The second write auto-increments
158 * the USTORE_ADDRESS index register.
160 ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn);
161 ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32));
164 void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns)
166 int i;
169 * Start writing to microstore at address 0.
171 ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000);
172 for (i = 0; i < insns; i++) {
173 u64 insn;
175 insn = (((u64)ucode[0]) << 32) |
176 (((u64)ucode[1]) << 24) |
177 (((u64)ucode[2]) << 16) |
178 (((u64)ucode[3]) << 8) |
179 ((u64)ucode[4]);
180 ucode += 5;
182 ustore_write(uengine, insn);
186 * Pad with a few NOPs at the end (to avoid the microengine
187 * aborting as it prefetches beyond the last instruction), unless
188 * we run off the end of the instruction store first, at which
189 * point the address register will wrap back to zero.
191 for (i = 0; i < 4; i++) {
192 u32 addr;
194 addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS);
195 if (addr == 0x80000000)
196 break;
197 ustore_write(uengine, 0xf0000c0300ULL);
201 * End programming.
203 ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000);
205 EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
207 void ixp2000_uengine_init_context(int uengine, int context, int pc)
210 * Select the right context for indirect access.
212 ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context);
215 * Initialise signal masks to immediately go to Ready state.
217 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1);
218 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1);
221 * Set program counter.
223 ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc);
225 EXPORT_SYMBOL(ixp2000_uengine_init_context);
227 void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask)
229 u32 mask;
232 * Enable the specified context to go to Executing state.
234 mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
235 mask |= ctx_mask << 8;
236 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
238 EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
240 void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask)
242 u32 mask;
245 * Disable the Ready->Executing transition. Note that this
246 * does not stop the context until it voluntarily yields.
248 mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
249 mask &= ~(ctx_mask << 8);
250 ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
252 EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
254 static int check_ixp_type(struct ixp2000_uengine_code *c)
256 u32 product_id;
257 u32 rev;
259 product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
260 if (((product_id >> 16) & 0x1f) != 0)
261 return 0;
263 switch ((product_id >> 8) & 0xff) {
264 #ifdef CONFIG_ARCH_IXP2000
265 case 0: /* IXP2800 */
266 if (!(c->cpu_model_bitmask & 4))
267 return 0;
268 break;
270 case 1: /* IXP2850 */
271 if (!(c->cpu_model_bitmask & 8))
272 return 0;
273 break;
275 case 2: /* IXP2400 */
276 if (!(c->cpu_model_bitmask & 2))
277 return 0;
278 break;
279 #endif
281 #ifdef CONFIG_ARCH_IXP23XX
282 case 4: /* IXP23xx */
283 if (!(c->cpu_model_bitmask & 0x3f0))
284 return 0;
285 break;
286 #endif
288 default:
289 return 0;
292 rev = product_id & 0xff;
293 if (rev < c->cpu_min_revision || rev > c->cpu_max_revision)
294 return 0;
296 return 1;
299 static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b)
301 int offset;
302 int i;
304 offset = 0;
306 for (i = 0; i < 128; i++) {
307 u8 b3;
308 u8 b2;
309 u8 b1;
310 u8 b0;
312 b3 = (gpr_a[i] >> 24) & 0xff;
313 b2 = (gpr_a[i] >> 16) & 0xff;
314 b1 = (gpr_a[i] >> 8) & 0xff;
315 b0 = gpr_a[i] & 0xff;
317 // immed[@ai, (b1 << 8) | b0]
318 // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII
319 ucode[offset++] = 0xf0;
320 ucode[offset++] = (b1 >> 4);
321 ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6);
322 ucode[offset++] = (b0 << 2);
323 ucode[offset++] = 0x80 | i;
325 // immed_w1[@ai, (b3 << 8) | b2]
326 // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII
327 ucode[offset++] = 0xf4;
328 ucode[offset++] = 0x40 | (b3 >> 4);
329 ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6);
330 ucode[offset++] = (b2 << 2);
331 ucode[offset++] = 0x80 | i;
334 for (i = 0; i < 128; i++) {
335 u8 b3;
336 u8 b2;
337 u8 b1;
338 u8 b0;
340 b3 = (gpr_b[i] >> 24) & 0xff;
341 b2 = (gpr_b[i] >> 16) & 0xff;
342 b1 = (gpr_b[i] >> 8) & 0xff;
343 b0 = gpr_b[i] & 0xff;
345 // immed[@bi, (b1 << 8) | b0]
346 // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV
347 ucode[offset++] = 0xf0;
348 ucode[offset++] = (b1 >> 4);
349 ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6);
350 ucode[offset++] = (i << 2) | 0x03;
351 ucode[offset++] = b0;
353 // immed_w1[@bi, (b3 << 8) | b2]
354 // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV
355 ucode[offset++] = 0xf4;
356 ucode[offset++] = 0x40 | (b3 >> 4);
357 ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6);
358 ucode[offset++] = (i << 2) | 0x03;
359 ucode[offset++] = b2;
362 // ctx_arb[kill]
363 ucode[offset++] = 0xe0;
364 ucode[offset++] = 0x00;
365 ucode[offset++] = 0x01;
366 ucode[offset++] = 0x00;
367 ucode[offset++] = 0x00;
370 static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c)
372 int per_ctx_regs;
373 u32 *gpr_a;
374 u32 *gpr_b;
375 u8 *ucode;
376 int i;
378 gpr_a = kmalloc(128 * sizeof(u32), GFP_KERNEL);
379 gpr_b = kmalloc(128 * sizeof(u32), GFP_KERNEL);
380 ucode = kmalloc(513 * 5, GFP_KERNEL);
381 if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) {
382 kfree(ucode);
383 kfree(gpr_b);
384 kfree(gpr_a);
385 return 1;
388 per_ctx_regs = 16;
389 if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS)
390 per_ctx_regs = 32;
392 memset(gpr_a, 0, sizeof(gpr_a));
393 memset(gpr_b, 0, sizeof(gpr_b));
394 for (i = 0; i < 256; i++) {
395 struct ixp2000_reg_value *r = c->initial_reg_values + i;
396 u32 *bank;
397 int inc;
398 int j;
400 if (r->reg == -1)
401 break;
403 bank = (r->reg & 0x400) ? gpr_b : gpr_a;
404 inc = (r->reg & 0x80) ? 128 : per_ctx_regs;
406 j = r->reg & 0x7f;
407 while (j < 128) {
408 bank[j] = r->value;
409 j += inc;
413 generate_ucode(ucode, gpr_a, gpr_b);
414 ixp2000_uengine_load_microcode(uengine, ucode, 513);
415 ixp2000_uengine_init_context(uengine, 0, 0);
416 ixp2000_uengine_start_contexts(uengine, 0x01);
417 for (i = 0; i < 100; i++) {
418 u32 status;
420 status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS);
421 if (!(status & 0x80000000))
422 break;
424 ixp2000_uengine_stop_contexts(uengine, 0x01);
426 kfree(ucode);
427 kfree(gpr_b);
428 kfree(gpr_a);
430 return !!(i == 100);
433 int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c)
435 int ctx;
437 if (!check_ixp_type(c))
438 return 1;
440 if (!(ixp2000_uengine_mask & (1 << uengine)))
441 return 1;
443 ixp2000_uengine_reset(1 << uengine);
444 ixp2000_uengine_set_mode(uengine, c->uengine_parameters);
445 if (set_initial_registers(uengine, c))
446 return 1;
447 ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns);
449 for (ctx = 0; ctx < 8; ctx++)
450 ixp2000_uengine_init_context(uengine, ctx, 0);
452 return 0;
454 EXPORT_SYMBOL(ixp2000_uengine_load);
457 static int __init ixp2000_uengine_init(void)
459 int uengine;
460 u32 value;
463 * Determine number of microengines present.
465 switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
466 #ifdef CONFIG_ARCH_IXP2000
467 case 0: /* IXP2800 */
468 case 1: /* IXP2850 */
469 ixp2000_uengine_mask = 0x00ff00ff;
470 break;
472 case 2: /* IXP2400 */
473 ixp2000_uengine_mask = 0x000f000f;
474 break;
475 #endif
477 #ifdef CONFIG_ARCH_IXP23XX
478 case 4: /* IXP23xx */
479 ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
480 break;
481 #endif
483 default:
484 printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
485 (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
486 ixp2000_uengine_mask = 0x00000000;
487 break;
491 * Reset microengines.
493 ixp2000_uengine_reset(ixp2000_uengine_mask);
496 * Synchronise timestamp counters across all microengines.
498 value = ixp2000_reg_read(IXP_MISC_CONTROL);
499 ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
500 for (uengine = 0; uengine < 32; uengine++) {
501 if (ixp2000_uengine_mask & (1 << uengine)) {
502 ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
503 ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
506 ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
508 return 0;
511 subsys_initcall(ixp2000_uengine_init);