diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 12:23:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-22 12:23:24 -0400 |
commit | 9bc747bea5fad819e0c0ad96e6a67ea0640dfe2b (patch) | |
tree | d500225e7a1c90a6bd17d3e63e2f6e781810db2b /arch/arm/common | |
parent | 32b908eea9e5ecd1049008e134eadbfcd0da5e38 (diff) | |
parent | 0e896b1ddc1905df904df98c204bacf028219729 (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/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/common/uengine.c | 507 |
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 | |||
11 | obj-$(CONFIG_SHARP_LOCOMO) += locomo.o | 11 | obj-$(CONFIG_SHARP_LOCOMO) += locomo.o |
12 | obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o | 12 | obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o |
13 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o | 13 | obj-$(CONFIG_SHARP_SCOOP) += scoop.o |
14 | obj-$(CONFIG_ARCH_IXP2000) += uengine.o | ||
15 | obj-$(CONFIG_ARCH_IXP23XX) += uengine.o | ||
16 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o | 14 | obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o |
17 | obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o | 15 | obj-$(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 | |||
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); | ||