aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/common
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 12:23:24 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 12:23:24 -0400
commit9bc747bea5fad819e0c0ad96e6a67ea0640dfe2b (patch)
treed500225e7a1c90a6bd17d3e63e2f6e781810db2b /arch/arm/common
parent32b908eea9e5ecd1049008e134eadbfcd0da5e38 (diff)
parent0e896b1ddc1905df904df98c204bacf028219729 (diff)
Merge tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull first batch of arm-soc cleanups from Olof Johansson: "These cleanups are basically all over the place. The idea is to collect changes with minimal impact but large number of changes so we can avoid them from distracting in the diffstat in the other series. A significant number of lines get removed here, in particular because the ixp2000 and ixp23xx platforms get removed. These have never been extremely popular and have fallen into disuse over time with no active maintainer taking care of them. The u5500 soc never made it into a product, so we are removing it from the ux500 platform. Many good cleanups also went into the at91 and omap platforms, as has been the case for a number of releases." Trivial modify-delete conflicts in arch/arm/mach-{ixp2000,ixp23xx} * tag 'cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (152 commits) ARM: clps711x: Cleanup IRQ handling ARM clps711x: Removed unused header mach/time.h ARM: clps711x: Added note about support EP731x CPU to Kconfig ARM: clps711x: Added missing register definitions ARM: clps711x: Used own subarch directory for store header file Dove: Fix Section mismatch warnings ARM: orion5x: ts78xx debugging changes ARM: orion5x: remove PM dependency from ts78xx ARM: orion5x: ts78xx fix NAND resource off by one ARM: orion5x: ts78xx whitespace cleanups Orion5x: Fix Section mismatch warnings Orion5x: Fix warning: struct pci_dev declared inside paramter list ARM: clps711x: Combine header files into one for clps711x-targets ARM: S3C24XX: Use common macro to define resources on mach-qt2410.c ARM: S3C24XX: Use common macro to define resources on mach-osiris.c ARM: EXYNOS: Adapt to cpuidle core time keeping and irq enable ARM: S5PV210: Use common macro to define resources on mach-smdkv210.c ARM: S5PV210: Use common macro to define resources on dev-audio.c ARM: S5PC100: Use common macro to define resources on dev-audio.c ARM: S5P64X0: Use common macro to define resources on dev-audio.c ...
Diffstat (limited to 'arch/arm/common')
-rw-r--r--arch/arm/common/Makefile2
-rw-r--r--arch/arm/common/uengine.c507
2 files changed, 0 insertions, 509 deletions
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 215816f1775f..e8a4e58f1b82 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -11,7 +11,5 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o
11obj-$(CONFIG_SHARP_LOCOMO) += locomo.o 11obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
12obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o 12obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
13obj-$(CONFIG_SHARP_SCOOP) += scoop.o 13obj-$(CONFIG_SHARP_SCOOP) += scoop.o
14obj-$(CONFIG_ARCH_IXP2000) += uengine.o
15obj-$(CONFIG_ARCH_IXP23XX) += uengine.o
16obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o 14obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
17obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o 15obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
diff --git a/arch/arm/common/uengine.c b/arch/arm/common/uengine.c
deleted file mode 100644
index bef408f3d76c..000000000000
--- a/arch/arm/common/uengine.c
+++ /dev/null
@@ -1,507 +0,0 @@
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 <linux/io.h>
20#include <mach/hardware.h>
21#include <asm/hardware/uengine.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
56u32 ixp2000_uengine_mask;
57
58static 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 */
71u32 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}
88EXPORT_SYMBOL(ixp2000_uengine_csr_read);
89
90void 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}
104EXPORT_SYMBOL(ixp2000_uengine_csr_write);
105
106void 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}
116EXPORT_SYMBOL(ixp2000_uengine_reset);
117
118void 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}
139EXPORT_SYMBOL(ixp2000_uengine_set_mode);
140
141static int make_even_parity(u32 x)
142{
143 return hweight32(x) & 1;
144}
145
146static 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
162void 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}
203EXPORT_SYMBOL(ixp2000_uengine_load_microcode);
204
205void 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}
223EXPORT_SYMBOL(ixp2000_uengine_init_context);
224
225void 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}
236EXPORT_SYMBOL(ixp2000_uengine_start_contexts);
237
238void 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}
250EXPORT_SYMBOL(ixp2000_uengine_stop_contexts);
251
252static 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
297static 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
368static 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
429int 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}
450EXPORT_SYMBOL(ixp2000_uengine_load);
451
452
453static 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
507subsys_initcall(ixp2000_uengine_init);