]> err.no Git - linux-2.6/blob - arch/arm/common/uengine.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
[linux-2.6] / arch / arm / common / uengine.c
1 /*
2  * Generic library functions for the microengines found on the Intel
3  * IXP2000 series of network processors.
4  *
5  * Copyright (C) 2004, 2005 Lennert Buytenhek <buytenh@wantstofly.org>
6  * Dedicated to Marija Kulikova.
7  *
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.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
18 #include <linux/string.h>
19 #include <mach/hardware.h>
20 #include <asm/hardware/uengine.h>
21 #include <asm/io.h>
22
23 #if defined(CONFIG_ARCH_IXP2000)
24 #define IXP_UENGINE_CSR_VIRT_BASE       IXP2000_UENGINE_CSR_VIRT_BASE
25 #define IXP_PRODUCT_ID                  IXP2000_PRODUCT_ID
26 #define IXP_MISC_CONTROL                IXP2000_MISC_CONTROL
27 #define IXP_RESET1                      IXP2000_RESET1
28 #else
29 #if defined(CONFIG_ARCH_IXP23XX)
30 #define IXP_UENGINE_CSR_VIRT_BASE       IXP23XX_UENGINE_CSR_VIRT_BASE
31 #define IXP_PRODUCT_ID                  IXP23XX_PRODUCT_ID
32 #define IXP_MISC_CONTROL                IXP23XX_MISC_CONTROL
33 #define IXP_RESET1                      IXP23XX_RESET1
34 #else
35 #error unknown platform
36 #endif
37 #endif
38
39 #define USTORE_ADDRESS                  0x000
40 #define USTORE_DATA_LOWER               0x004
41 #define USTORE_DATA_UPPER               0x008
42 #define CTX_ENABLES                     0x018
43 #define CC_ENABLE                       0x01c
44 #define CSR_CTX_POINTER                 0x020
45 #define INDIRECT_CTX_STS                0x040
46 #define ACTIVE_CTX_STS                  0x044
47 #define INDIRECT_CTX_SIG_EVENTS         0x048
48 #define INDIRECT_CTX_WAKEUP_EVENTS      0x050
49 #define NN_PUT                          0x080
50 #define NN_GET                          0x084
51 #define TIMESTAMP_LOW                   0x0c0
52 #define TIMESTAMP_HIGH                  0x0c4
53 #define T_INDEX_BYTE_INDEX              0x0f4
54 #define LOCAL_CSR_STATUS                0x180
55
56 u32 ixp2000_uengine_mask;
57
58 static void *ixp2000_uengine_csr_area(int uengine)
59 {
60         return ((void *)IXP_UENGINE_CSR_VIRT_BASE) + (uengine << 10);
61 }
62
63 /*
64  * LOCAL_CSR_STATUS=1 after a read or write to a microengine's CSR
65  * space means that the microengine we tried to access was also trying
66  * to access its own CSR space on the same clock cycle as we did.  When
67  * this happens, we lose the arbitration process by default, and the
68  * read or write we tried to do was not actually performed, so we try
69  * again until it succeeds.
70  */
71 u32 ixp2000_uengine_csr_read(int uengine, int offset)
72 {
73         void *uebase;
74         u32 *local_csr_status;
75         u32 *reg;
76         u32 value;
77
78         uebase = ixp2000_uengine_csr_area(uengine);
79
80         local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
81         reg = (u32 *)(uebase + offset);
82         do {
83                 value = ixp2000_reg_read(reg);
84         } while (ixp2000_reg_read(local_csr_status) & 1);
85
86         return value;
87 }
88 EXPORT_SYMBOL(ixp2000_uengine_csr_read);
89
90 void ixp2000_uengine_csr_write(int uengine, int offset, u32 value)
91 {
92         void *uebase;
93         u32 *local_csr_status;
94         u32 *reg;
95
96         uebase = ixp2000_uengine_csr_area(uengine);
97
98         local_csr_status = (u32 *)(uebase + LOCAL_CSR_STATUS);
99         reg = (u32 *)(uebase + offset);
100         do {
101                 ixp2000_reg_write(reg, value);
102         } while (ixp2000_reg_read(local_csr_status) & 1);
103 }
104 EXPORT_SYMBOL(ixp2000_uengine_csr_write);
105
106 void ixp2000_uengine_reset(u32 uengine_mask)
107 {
108         u32 value;
109
110         value = ixp2000_reg_read(IXP_RESET1) & ~ixp2000_uengine_mask;
111
112         uengine_mask &= ixp2000_uengine_mask;
113         ixp2000_reg_wrb(IXP_RESET1, value | uengine_mask);
114         ixp2000_reg_wrb(IXP_RESET1, value);
115 }
116 EXPORT_SYMBOL(ixp2000_uengine_reset);
117
118 void ixp2000_uengine_set_mode(int uengine, u32 mode)
119 {
120         /*
121          * CTL_STR_PAR_EN: unconditionally enable parity checking on
122          * control store.
123          */
124         mode |= 0x10000000;
125         ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mode);
126
127         /*
128          * Enable updating of condition codes.
129          */
130         ixp2000_uengine_csr_write(uengine, CC_ENABLE, 0x00002000);
131
132         /*
133          * Initialise other per-microengine registers.
134          */
135         ixp2000_uengine_csr_write(uengine, NN_PUT, 0x00);
136         ixp2000_uengine_csr_write(uengine, NN_GET, 0x00);
137         ixp2000_uengine_csr_write(uengine, T_INDEX_BYTE_INDEX, 0);
138 }
139 EXPORT_SYMBOL(ixp2000_uengine_set_mode);
140
141 static int make_even_parity(u32 x)
142 {
143         return hweight32(x) & 1;
144 }
145
146 static void ustore_write(int uengine, u64 insn)
147 {
148         /*
149          * Generate even parity for top and bottom 20 bits.
150          */
151         insn |= (u64)make_even_parity((insn >> 20) & 0x000fffff) << 41;
152         insn |= (u64)make_even_parity(insn & 0x000fffff) << 40;
153
154         /*
155          * Write to microstore.  The second write auto-increments
156          * the USTORE_ADDRESS index register.
157          */
158         ixp2000_uengine_csr_write(uengine, USTORE_DATA_LOWER, (u32)insn);
159         ixp2000_uengine_csr_write(uengine, USTORE_DATA_UPPER, (u32)(insn >> 32));
160 }
161
162 void ixp2000_uengine_load_microcode(int uengine, u8 *ucode, int insns)
163 {
164         int i;
165
166         /*
167          * Start writing to microstore at address 0.
168          */
169         ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x80000000);
170         for (i = 0; i < insns; i++) {
171                 u64 insn;
172
173                 insn = (((u64)ucode[0]) << 32) |
174                         (((u64)ucode[1]) << 24) |
175                         (((u64)ucode[2]) << 16) |
176                         (((u64)ucode[3]) << 8) |
177                         ((u64)ucode[4]);
178                 ucode += 5;
179
180                 ustore_write(uengine, insn);
181         }
182
183         /*
184          * Pad with a few NOPs at the end (to avoid the microengine
185          * aborting as it prefetches beyond the last instruction), unless
186          * we run off the end of the instruction store first, at which
187          * point the address register will wrap back to zero.
188          */
189         for (i = 0; i < 4; i++) {
190                 u32 addr;
191
192                 addr = ixp2000_uengine_csr_read(uengine, USTORE_ADDRESS);
193                 if (addr == 0x80000000)
194                         break;
195                 ustore_write(uengine, 0xf0000c0300ULL);
196         }
197
198         /*
199          * End programming.
200          */
201         ixp2000_uengine_csr_write(uengine, USTORE_ADDRESS, 0x00000000);
202 }
203 EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
204
205 void ixp2000_uengine_init_context(int uengine, int context, int pc)
206 {
207         /*
208          * Select the right context for indirect access.
209          */
210         ixp2000_uengine_csr_write(uengine, CSR_CTX_POINTER, context);
211
212         /*
213          * Initialise signal masks to immediately go to Ready state.
214          */
215         ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_SIG_EVENTS, 1);
216         ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_WAKEUP_EVENTS, 1);
217
218         /*
219          * Set program counter.
220          */
221         ixp2000_uengine_csr_write(uengine, INDIRECT_CTX_STS, pc);
222 }
223 EXPORT_SYMBOL(ixp2000_uengine_init_context);
224
225 void ixp2000_uengine_start_contexts(int uengine, u8 ctx_mask)
226 {
227         u32 mask;
228
229         /*
230          * Enable the specified context to go to Executing state.
231          */
232         mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
233         mask |= ctx_mask << 8;
234         ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
235 }
236 EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
237
238 void ixp2000_uengine_stop_contexts(int uengine, u8 ctx_mask)
239 {
240         u32 mask;
241
242         /*
243          * Disable the Ready->Executing transition.  Note that this
244          * does not stop the context until it voluntarily yields.
245          */
246         mask = ixp2000_uengine_csr_read(uengine, CTX_ENABLES);
247         mask &= ~(ctx_mask << 8);
248         ixp2000_uengine_csr_write(uengine, CTX_ENABLES, mask);
249 }
250 EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
251
252 static int check_ixp_type(struct ixp2000_uengine_code *c)
253 {
254         u32 product_id;
255         u32 rev;
256
257         product_id = ixp2000_reg_read(IXP_PRODUCT_ID);
258         if (((product_id >> 16) & 0x1f) != 0)
259                 return 0;
260
261         switch ((product_id >> 8) & 0xff) {
262 #ifdef CONFIG_ARCH_IXP2000
263         case 0:         /* IXP2800 */
264                 if (!(c->cpu_model_bitmask & 4))
265                         return 0;
266                 break;
267
268         case 1:         /* IXP2850 */
269                 if (!(c->cpu_model_bitmask & 8))
270                         return 0;
271                 break;
272
273         case 2:         /* IXP2400 */
274                 if (!(c->cpu_model_bitmask & 2))
275                         return 0;
276                 break;
277 #endif
278
279 #ifdef CONFIG_ARCH_IXP23XX
280         case 4:         /* IXP23xx */
281                 if (!(c->cpu_model_bitmask & 0x3f0))
282                         return 0;
283                 break;
284 #endif
285
286         default:
287                 return 0;
288         }
289
290         rev = product_id & 0xff;
291         if (rev < c->cpu_min_revision || rev > c->cpu_max_revision)
292                 return 0;
293
294         return 1;
295 }
296
297 static void generate_ucode(u8 *ucode, u32 *gpr_a, u32 *gpr_b)
298 {
299         int offset;
300         int i;
301
302         offset = 0;
303
304         for (i = 0; i < 128; i++) {
305                 u8 b3;
306                 u8 b2;
307                 u8 b1;
308                 u8 b0;
309
310                 b3 = (gpr_a[i] >> 24) & 0xff;
311                 b2 = (gpr_a[i] >> 16) & 0xff;
312                 b1 = (gpr_a[i] >> 8) & 0xff;
313                 b0 = gpr_a[i] & 0xff;
314
315                 // immed[@ai, (b1 << 8) | b0]
316                 // 11110000 0000VVVV VVVV11VV VVVVVV00 1IIIIIII
317                 ucode[offset++] = 0xf0;
318                 ucode[offset++] = (b1 >> 4);
319                 ucode[offset++] = (b1 << 4) | 0x0c | (b0 >> 6);
320                 ucode[offset++] = (b0 << 2);
321                 ucode[offset++] = 0x80 | i;
322
323                 // immed_w1[@ai, (b3 << 8) | b2]
324                 // 11110100 0100VVVV VVVV11VV VVVVVV00 1IIIIIII
325                 ucode[offset++] = 0xf4;
326                 ucode[offset++] = 0x40 | (b3 >> 4);
327                 ucode[offset++] = (b3 << 4) | 0x0c | (b2 >> 6);
328                 ucode[offset++] = (b2 << 2);
329                 ucode[offset++] = 0x80 | i;
330         }
331
332         for (i = 0; i < 128; i++) {
333                 u8 b3;
334                 u8 b2;
335                 u8 b1;
336                 u8 b0;
337
338                 b3 = (gpr_b[i] >> 24) & 0xff;
339                 b2 = (gpr_b[i] >> 16) & 0xff;
340                 b1 = (gpr_b[i] >> 8) & 0xff;
341                 b0 = gpr_b[i] & 0xff;
342
343                 // immed[@bi, (b1 << 8) | b0]
344                 // 11110000 0000VVVV VVVV001I IIIIII11 VVVVVVVV
345                 ucode[offset++] = 0xf0;
346                 ucode[offset++] = (b1 >> 4);
347                 ucode[offset++] = (b1 << 4) | 0x02 | (i >> 6);
348                 ucode[offset++] = (i << 2) | 0x03;
349                 ucode[offset++] = b0;
350
351                 // immed_w1[@bi, (b3 << 8) | b2]
352                 // 11110100 0100VVVV VVVV001I IIIIII11 VVVVVVVV
353                 ucode[offset++] = 0xf4;
354                 ucode[offset++] = 0x40 | (b3 >> 4);
355                 ucode[offset++] = (b3 << 4) | 0x02 | (i >> 6);
356                 ucode[offset++] = (i << 2) | 0x03;
357                 ucode[offset++] = b2;
358         }
359
360         // ctx_arb[kill]
361         ucode[offset++] = 0xe0;
362         ucode[offset++] = 0x00;
363         ucode[offset++] = 0x01;
364         ucode[offset++] = 0x00;
365         ucode[offset++] = 0x00;
366 }
367
368 static int set_initial_registers(int uengine, struct ixp2000_uengine_code *c)
369 {
370         int per_ctx_regs;
371         u32 *gpr_a;
372         u32 *gpr_b;
373         u8 *ucode;
374         int i;
375
376         gpr_a = kzalloc(128 * sizeof(u32), GFP_KERNEL);
377         gpr_b = kzalloc(128 * sizeof(u32), GFP_KERNEL);
378         ucode = kmalloc(513 * 5, GFP_KERNEL);
379         if (gpr_a == NULL || gpr_b == NULL || ucode == NULL) {
380                 kfree(ucode);
381                 kfree(gpr_b);
382                 kfree(gpr_a);
383                 return 1;
384         }
385
386         per_ctx_regs = 16;
387         if (c->uengine_parameters & IXP2000_UENGINE_4_CONTEXTS)
388                 per_ctx_regs = 32;
389
390         for (i = 0; i < 256; i++) {
391                 struct ixp2000_reg_value *r = c->initial_reg_values + i;
392                 u32 *bank;
393                 int inc;
394                 int j;
395
396                 if (r->reg == -1)
397                         break;
398
399                 bank = (r->reg & 0x400) ? gpr_b : gpr_a;
400                 inc = (r->reg & 0x80) ? 128 : per_ctx_regs;
401
402                 j = r->reg & 0x7f;
403                 while (j < 128) {
404                         bank[j] = r->value;
405                         j += inc;
406                 }
407         }
408
409         generate_ucode(ucode, gpr_a, gpr_b);
410         ixp2000_uengine_load_microcode(uengine, ucode, 513);
411         ixp2000_uengine_init_context(uengine, 0, 0);
412         ixp2000_uengine_start_contexts(uengine, 0x01);
413         for (i = 0; i < 100; i++) {
414                 u32 status;
415
416                 status = ixp2000_uengine_csr_read(uengine, ACTIVE_CTX_STS);
417                 if (!(status & 0x80000000))
418                         break;
419         }
420         ixp2000_uengine_stop_contexts(uengine, 0x01);
421
422         kfree(ucode);
423         kfree(gpr_b);
424         kfree(gpr_a);
425
426         return !!(i == 100);
427 }
428
429 int ixp2000_uengine_load(int uengine, struct ixp2000_uengine_code *c)
430 {
431         int ctx;
432
433         if (!check_ixp_type(c))
434                 return 1;
435
436         if (!(ixp2000_uengine_mask & (1 << uengine)))
437                 return 1;
438
439         ixp2000_uengine_reset(1 << uengine);
440         ixp2000_uengine_set_mode(uengine, c->uengine_parameters);
441         if (set_initial_registers(uengine, c))
442                 return 1;
443         ixp2000_uengine_load_microcode(uengine, c->insns, c->num_insns);
444
445         for (ctx = 0; ctx < 8; ctx++)
446                 ixp2000_uengine_init_context(uengine, ctx, 0);
447
448         return 0;
449 }
450 EXPORT_SYMBOL(ixp2000_uengine_load);
451
452
453 static int __init ixp2000_uengine_init(void)
454 {
455         int uengine;
456         u32 value;
457
458         /*
459          * Determine number of microengines present.
460          */
461         switch ((ixp2000_reg_read(IXP_PRODUCT_ID) >> 8) & 0x1fff) {
462 #ifdef CONFIG_ARCH_IXP2000
463         case 0:         /* IXP2800 */
464         case 1:         /* IXP2850 */
465                 ixp2000_uengine_mask = 0x00ff00ff;
466                 break;
467
468         case 2:         /* IXP2400 */
469                 ixp2000_uengine_mask = 0x000f000f;
470                 break;
471 #endif
472
473 #ifdef CONFIG_ARCH_IXP23XX
474         case 4:         /* IXP23xx */
475                 ixp2000_uengine_mask = (*IXP23XX_EXP_CFG_FUSE >> 8) & 0xf;
476                 break;
477 #endif
478
479         default:
480                 printk(KERN_INFO "Detected unknown IXP2000 model (%.8x)\n",
481                         (unsigned int)ixp2000_reg_read(IXP_PRODUCT_ID));
482                 ixp2000_uengine_mask = 0x00000000;
483                 break;
484         }
485
486         /*
487          * Reset microengines.
488          */
489         ixp2000_uengine_reset(ixp2000_uengine_mask);
490
491         /*
492          * Synchronise timestamp counters across all microengines.
493          */
494         value = ixp2000_reg_read(IXP_MISC_CONTROL);
495         ixp2000_reg_wrb(IXP_MISC_CONTROL, value & ~0x80);
496         for (uengine = 0; uengine < 32; uengine++) {
497                 if (ixp2000_uengine_mask & (1 << uengine)) {
498                         ixp2000_uengine_csr_write(uengine, TIMESTAMP_LOW, 0);
499                         ixp2000_uengine_csr_write(uengine, TIMESTAMP_HIGH, 0);
500                 }
501         }
502         ixp2000_reg_wrb(IXP_MISC_CONTROL, value | 0x80);
503
504         return 0;
505 }
506
507 subsys_initcall(ixp2000_uengine_init);