aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v32/mach-a3
diff options
context:
space:
mode:
authorJesper Nilsson <jespern@stork.se.axis.com>2007-11-29 11:11:23 -0500
committerJesper Nilsson <jesper.nilsson@axis.com>2008-02-08 05:06:23 -0500
commit035e111f9a9b29843bc899f03d56f19d94bebb53 (patch)
treecb46b3c0eb6d9f2cc915522153454d3acaa7fcda /arch/cris/arch-v32/mach-a3
parent6107c61fd3e6b47106b078db1726ad814564efef (diff)
CRIS v32: Add new machine dependent files for Etrax-FS and Artpec-3.
The two chips are somewhat different, and needs different handling. Adds handing of the dma, dram initialization, hardware settings, io, memory arbiter and pinmux Also moves the dma, dram initialization and io from CRIS v32 common files.
Diffstat (limited to 'arch/cris/arch-v32/mach-a3')
-rw-r--r--arch/cris/arch-v32/mach-a3/Kconfig110
-rw-r--r--arch/cris/arch-v32/mach-a3/Makefile11
-rw-r--r--arch/cris/arch-v32/mach-a3/arbiter.c634
-rw-r--r--arch/cris/arch-v32/mach-a3/cpufreq.c153
-rw-r--r--arch/cris/arch-v32/mach-a3/dma.c185
-rw-r--r--arch/cris/arch-v32/mach-a3/dram_init.S104
-rw-r--r--arch/cris/arch-v32/mach-a3/hw_settings.S51
-rw-r--r--arch/cris/arch-v32/mach-a3/io.c150
-rw-r--r--arch/cris/arch-v32/mach-a3/pinmux.c386
-rw-r--r--arch/cris/arch-v32/mach-a3/vcs_hook.c103
-rw-r--r--arch/cris/arch-v32/mach-a3/vcs_hook.h58
11 files changed, 1945 insertions, 0 deletions
diff --git a/arch/cris/arch-v32/mach-a3/Kconfig b/arch/cris/arch-v32/mach-a3/Kconfig
new file mode 100644
index 000000000000..a4df06d5997a
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/Kconfig
@@ -0,0 +1,110 @@
1if CRIS_MACH_ARTPEC3
2
3menu "Artpec-3 options"
4 depends on CRIS_MACH_ARTPEC3
5
6config ETRAX_DRAM_VIRTUAL_BASE
7 hex
8 default "c0000000"
9
10config ETRAX_L2CACHE
11 bool
12 default y
13
14config ETRAX_SERIAL_PORTS
15 int
16 default 5
17
18config ETRAX_DDR
19 bool
20 default y
21
22config ETRAX_DDR2_MRS
23 hex "DDR2 MRS"
24 default "0"
25
26config ETRAX_DDR2_TIMING
27 hex "DDR2 SDRAM timing"
28 default "0"
29 help
30 SDRAM timing parameters.
31
32config ETRAX_DDR2_CONFIG
33 hex "DDR2 config"
34 default "0"
35
36config ETRAX_PIO_CE0_CFG
37 hex "PIO CE0 configuration"
38 default "0"
39
40config ETRAX_PIO_CE1_CFG
41 hex "PIO CE1 configuration"
42 default "0"
43
44config ETRAX_PIO_CE2_CFG
45 hex "PIO CE2 configuration"
46 default "0"
47
48config ETRAX_DEF_GIO_PA_OE
49 hex "GIO_PA_OE"
50 default "00000000"
51 help
52 Configures the direction of general port A bits. 1 is out, 0 is in.
53 This is often totally different depending on the product used.
54 There are some guidelines though - if you know that only LED's are
55 connected to port PA, then they are usually connected to bits 2-4
56 and you can therefore use 1c. On other boards which don't have the
57 LED's at the general ports, these bits are used for all kinds of
58 stuff. If you don't know what to use, it is always safe to put all
59 as inputs, although floating inputs isn't good.
60
61config ETRAX_DEF_GIO_PA_OUT
62 hex "GIO_PA_OUT"
63 default "00000000"
64 help
65 Configures the initial data for the general port A bits. Most
66 products should use 00 here.
67
68config ETRAX_DEF_GIO_PB_OE
69 hex "GIO_PB_OE"
70 default "000000000"
71 help
72 Configures the direction of general port B bits. 1 is out, 0 is in.
73 This is often totally different depending on the product used.
74 There are some guidelines though - if you know that only LED's are
75 connected to port PA, then they are usually connected to bits 2-4
76 and you can therefore use 1c. On other boards which don't have the
77 LED's at the general ports, these bits are used for all kinds of
78 stuff. If you don't know what to use, it is always safe to put all
79 as inputs, although floating inputs isn't good.
80
81config ETRAX_DEF_GIO_PB_OUT
82 hex "GIO_PB_OUT"
83 default "000000000"
84 help
85 Configures the initial data for the general port B bits. Most
86 products should use 00000 here.
87
88config ETRAX_DEF_GIO_PC_OE
89 hex "GIO_PC_OE"
90 default "00000"
91 help
92 Configures the direction of general port C bits. 1 is out, 0 is in.
93 This is often totally different depending on the product used.
94 There are some guidelines though - if you know that only LED's are
95 connected to port PA, then they are usually connected to bits 2-4
96 and you can therefore use 1c. On other boards which don't have the
97 LED's at the general ports, these bits are used for all kinds of
98 stuff. If you don't know what to use, it is always safe to put all
99 as inputs, although floating inputs isn't good.
100
101config ETRAX_DEF_GIO_PC_OUT
102 hex "GIO_PC_OUT"
103 default "00000"
104 help
105 Configures the initial data for the general port C bits. Most
106 products should use 00000 here.
107
108endmenu
109
110endif
diff --git a/arch/cris/arch-v32/mach-a3/Makefile b/arch/cris/arch-v32/mach-a3/Makefile
new file mode 100644
index 000000000000..41fa6a6893a9
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/Makefile
@@ -0,0 +1,11 @@
1# $Id: Makefile,v 1.3 2007/03/13 11:57:46 starvik Exp $
2#
3# Makefile for the linux kernel.
4#
5
6obj-y := dma.o pinmux.o io.o arbiter.o
7obj-$(CONFIG_ETRAX_VCS_SIM) += vcs_hook.o
8obj-$(CONFIG_CPU_FREQ) += cpufreq.o
9
10clean:
11
diff --git a/arch/cris/arch-v32/mach-a3/arbiter.c b/arch/cris/arch-v32/mach-a3/arbiter.c
new file mode 100644
index 000000000000..b92fd7eed3c4
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/arbiter.c
@@ -0,0 +1,634 @@
1/*
2 * Memory arbiter functions. Allocates bandwidth through the
3 * arbiter and sets up arbiter breakpoints.
4 *
5 * The algorithm first assigns slots to the clients that has specified
6 * bandwith (e.g. ethernet) and then the remaining slots are divided
7 * on all the active clients.
8 *
9 * Copyright (c) 2004-2007 Axis Communications AB.
10 *
11 * The artpec-3 has two arbiters. The memory hierarchy looks like this:
12 *
13 *
14 * CPU DMAs
15 * | |
16 * | |
17 * -------------- ------------------
18 * | foo arbiter|----| Internal memory|
19 * -------------- ------------------
20 * |
21 * --------------
22 * | L2 cache |
23 * --------------
24 * |
25 * h264 etc |
26 * | |
27 * | |
28 * --------------
29 * | bar arbiter|
30 * --------------
31 * |
32 * ---------
33 * | SDRAM |
34 * ---------
35 *
36 */
37
38#include <hwregs/reg_map.h>
39#include <hwregs/reg_rdwr.h>
40#include <hwregs/marb_foo_defs.h>
41#include <hwregs/marb_bar_defs.h>
42#include <arbiter.h>
43#include <hwregs/intr_vect.h>
44#include <linux/interrupt.h>
45#include <linux/irq.h>
46#include <linux/signal.h>
47#include <linux/errno.h>
48#include <linux/spinlock.h>
49#include <asm/io.h>
50#include <asm/irq_regs.h>
51
52#define D(x)
53
54struct crisv32_watch_entry {
55 unsigned long instance;
56 watch_callback *cb;
57 unsigned long start;
58 unsigned long end;
59 int used;
60};
61
62#define NUMBER_OF_BP 4
63#define SDRAM_BANDWIDTH 400000000
64#define INTMEM_BANDWIDTH 400000000
65#define NBR_OF_SLOTS 64
66#define NBR_OF_REGIONS 2
67#define NBR_OF_CLIENTS 15
68#define ARBITERS 2
69#define UNASSIGNED 100
70
71struct arbiter {
72 unsigned long instance;
73 int nbr_regions;
74 int nbr_clients;
75 int requested_slots[NBR_OF_REGIONS][NBR_OF_CLIENTS];
76 int active_clients[NBR_OF_REGIONS][NBR_OF_CLIENTS];
77};
78
79static struct crisv32_watch_entry watches[ARBITERS][NUMBER_OF_BP] =
80{
81 {
82 {regi_marb_foo_bp0},
83 {regi_marb_foo_bp1},
84 {regi_marb_foo_bp2},
85 {regi_marb_foo_bp3}
86 },
87 {
88 {regi_marb_bar_bp0},
89 {regi_marb_bar_bp1},
90 {regi_marb_bar_bp2},
91 {regi_marb_bar_bp3}
92 }
93};
94
95struct arbiter arbiters[ARBITERS] =
96{
97 { /* L2 cache arbiter */
98 .instance = regi_marb_foo,
99 .nbr_regions = 2,
100 .nbr_clients = 15
101 },
102 { /* DDR2 arbiter */
103 .instance = regi_marb_bar,
104 .nbr_regions = 1,
105 .nbr_clients = 9
106 }
107};
108
109static int max_bandwidth[NBR_OF_REGIONS] = {SDRAM_BANDWIDTH, INTMEM_BANDWIDTH};
110
111DEFINE_SPINLOCK(arbiter_lock);
112
113static irqreturn_t
114crisv32_foo_arbiter_irq(int irq, void *dev_id);
115static irqreturn_t
116crisv32_bar_arbiter_irq(int irq, void *dev_id);
117
118/*
119 * "I'm the arbiter, I know the score.
120 * From square one I'll be watching all 64."
121 * (memory arbiter slots, that is)
122 *
123 * Or in other words:
124 * Program the memory arbiter slots for "region" according to what's
125 * in requested_slots[] and active_clients[], while minimizing
126 * latency. A caller may pass a non-zero positive amount for
127 * "unused_slots", which must then be the unallocated, remaining
128 * number of slots, free to hand out to any client.
129 */
130
131static void crisv32_arbiter_config(int arbiter, int region, int unused_slots)
132{
133 int slot;
134 int client;
135 int interval = 0;
136
137 /*
138 * This vector corresponds to the hardware arbiter slots (see
139 * the hardware documentation for semantics). We initialize
140 * each slot with a suitable sentinel value outside the valid
141 * range {0 .. NBR_OF_CLIENTS - 1} and replace them with
142 * client indexes. Then it's fed to the hardware.
143 */
144 s8 val[NBR_OF_SLOTS];
145
146 for (slot = 0; slot < NBR_OF_SLOTS; slot++)
147 val[slot] = -1;
148
149 for (client = 0; client < arbiters[arbiter].nbr_clients; client++) {
150 int pos;
151 /* Allocate the requested non-zero number of slots, but
152 * also give clients with zero-requests one slot each
153 * while stocks last. We do the latter here, in client
154 * order. This makes sure zero-request clients are the
155 * first to get to any spare slots, else those slots
156 * could, when bandwidth is allocated close to the limit,
157 * all be allocated to low-index non-zero-request clients
158 * in the default-fill loop below. Another positive but
159 * secondary effect is a somewhat better spread of the
160 * zero-bandwidth clients in the vector, avoiding some of
161 * the latency that could otherwise be caused by the
162 * partitioning of non-zero-bandwidth clients at low
163 * indexes and zero-bandwidth clients at high
164 * indexes. (Note that this spreading can only affect the
165 * unallocated bandwidth.) All the above only matters for
166 * memory-intensive situations, of course.
167 */
168 if (!arbiters[arbiter].requested_slots[region][client]) {
169 /*
170 * Skip inactive clients. Also skip zero-slot
171 * allocations in this pass when there are no known
172 * free slots.
173 */
174 if (!arbiters[arbiter].active_clients[region][client] ||
175 unused_slots <= 0)
176 continue;
177
178 unused_slots--;
179
180 /* Only allocate one slot for this client. */
181 interval = NBR_OF_SLOTS;
182 } else
183 interval = NBR_OF_SLOTS /
184 arbiters[arbiter].requested_slots[region][client];
185
186 pos = 0;
187 while (pos < NBR_OF_SLOTS) {
188 if (val[pos] >= 0)
189 pos++;
190 else {
191 val[pos] = client;
192 pos += interval;
193 }
194 }
195 }
196
197 client = 0;
198 for (slot = 0; slot < NBR_OF_SLOTS; slot++) {
199 /*
200 * Allocate remaining slots in round-robin
201 * client-number order for active clients. For this
202 * pass, we ignore requested bandwidth and previous
203 * allocations.
204 */
205 if (val[slot] < 0) {
206 int first = client;
207 while (!arbiters[arbiter].active_clients[region][client]) {
208 client = (client + 1) %
209 arbiters[arbiter].nbr_clients;
210 if (client == first)
211 break;
212 }
213 val[slot] = client;
214 client = (client + 1) % arbiters[arbiter].nbr_clients;
215 }
216 if (arbiter == 0) {
217 if (region == EXT_REGION)
218 REG_WR_INT_VECT(marb_foo, regi_marb_foo,
219 rw_l2_slots, slot, val[slot]);
220 else if (region == INT_REGION)
221 REG_WR_INT_VECT(marb_foo, regi_marb_foo,
222 rw_intm_slots, slot, val[slot]);
223 } else {
224 REG_WR_INT_VECT(marb_bar, regi_marb_bar,
225 rw_ddr2_slots, slot, val[slot]);
226 }
227 }
228}
229
230extern char _stext, _etext;
231
232static void crisv32_arbiter_init(void)
233{
234 static int initialized;
235
236 if (initialized)
237 return;
238
239 initialized = 1;
240
241 /*
242 * CPU caches are always set to active, but with zero
243 * bandwidth allocated. It should be ok to allocate zero
244 * bandwidth for the caches, because DMA for other channels
245 * will supposedly finish, once their programmed amount is
246 * done, and then the caches will get access according to the
247 * "fixed scheme" for unclaimed slots. Though, if for some
248 * use-case somewhere, there's a maximum CPU latency for
249 * e.g. some interrupt, we have to start allocating specific
250 * bandwidth for the CPU caches too.
251 */
252 arbiters[0].active_clients[EXT_REGION][11] = 1;
253 arbiters[0].active_clients[EXT_REGION][12] = 1;
254 crisv32_arbiter_config(0, EXT_REGION, 0);
255 crisv32_arbiter_config(0, INT_REGION, 0);
256 crisv32_arbiter_config(1, EXT_REGION, 0);
257
258 if (request_irq(MEMARB_FOO_INTR_VECT, crisv32_foo_arbiter_irq,
259 IRQF_DISABLED, "arbiter", NULL))
260 printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
261
262 if (request_irq(MEMARB_BAR_INTR_VECT, crisv32_bar_arbiter_irq,
263 IRQF_DISABLED, "arbiter", NULL))
264 printk(KERN_ERR "Couldn't allocate arbiter IRQ\n");
265
266#ifndef CONFIG_ETRAX_KGDB
267 /* Global watch for writes to kernel text segment. */
268 crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
269 MARB_CLIENTS(arbiter_all_clients, arbiter_bar_all_clients),
270 arbiter_all_write, NULL);
271#endif
272
273 /* Set up max burst sizes by default */
274 REG_WR_INT(marb_bar, regi_marb_bar, rw_h264_rd_burst, 3);
275 REG_WR_INT(marb_bar, regi_marb_bar, rw_h264_wr_burst, 3);
276 REG_WR_INT(marb_bar, regi_marb_bar, rw_ccd_burst, 3);
277 REG_WR_INT(marb_bar, regi_marb_bar, rw_vin_wr_burst, 3);
278 REG_WR_INT(marb_bar, regi_marb_bar, rw_vin_rd_burst, 3);
279 REG_WR_INT(marb_bar, regi_marb_bar, rw_sclr_rd_burst, 3);
280 REG_WR_INT(marb_bar, regi_marb_bar, rw_vout_burst, 3);
281 REG_WR_INT(marb_bar, regi_marb_bar, rw_sclr_fifo_burst, 3);
282 REG_WR_INT(marb_bar, regi_marb_bar, rw_l2cache_burst, 3);
283}
284
285int crisv32_arbiter_allocate_bandwith(int client, int region,
286 unsigned long bandwidth)
287{
288 int i;
289 int total_assigned = 0;
290 int total_clients = 0;
291 int req;
292 int arbiter = 0;
293
294 crisv32_arbiter_init();
295
296 if (client & 0xffff0000) {
297 arbiter = 1;
298 client >>= 16;
299 }
300
301 for (i = 0; i < arbiters[arbiter].nbr_clients; i++) {
302 total_assigned += arbiters[arbiter].requested_slots[region][i];
303 total_clients += arbiters[arbiter].active_clients[region][i];
304 }
305
306 /* Avoid division by 0 for 0-bandwidth requests. */
307 req = bandwidth == 0
308 ? 0 : NBR_OF_SLOTS / (max_bandwidth[region] / bandwidth);
309
310 /*
311 * We make sure that there are enough slots only for non-zero
312 * requests. Requesting 0 bandwidth *may* allocate slots,
313 * though if all bandwidth is allocated, such a client won't
314 * get any and will have to rely on getting memory access
315 * according to the fixed scheme that's the default when one
316 * of the slot-allocated clients doesn't claim their slot.
317 */
318 if (total_assigned + req > NBR_OF_SLOTS)
319 return -ENOMEM;
320
321 arbiters[arbiter].active_clients[region][client] = 1;
322 arbiters[arbiter].requested_slots[region][client] = req;
323 crisv32_arbiter_config(arbiter, region, NBR_OF_SLOTS - total_assigned);
324
325 /* Propagate allocation from foo to bar */
326 if (arbiter == 0)
327 crisv32_arbiter_allocate_bandwith(8 << 16,
328 EXT_REGION, bandwidth);
329 return 0;
330}
331
332/*
333 * Main entry for bandwidth deallocation.
334 *
335 * Strictly speaking, for a somewhat constant set of clients where
336 * each client gets a constant bandwidth and is just enabled or
337 * disabled (somewhat dynamically), no action is necessary here to
338 * avoid starvation for non-zero-allocation clients, as the allocated
339 * slots will just be unused. However, handing out those unused slots
340 * to active clients avoids needless latency if the "fixed scheme"
341 * would give unclaimed slots to an eager low-index client.
342 */
343
344void crisv32_arbiter_deallocate_bandwidth(int client, int region)
345{
346 int i;
347 int total_assigned = 0;
348 int arbiter = 0;
349
350 if (client & 0xffff0000)
351 arbiter = 1;
352
353 arbiters[arbiter].requested_slots[region][client] = 0;
354 arbiters[arbiter].active_clients[region][client] = 0;
355
356 for (i = 0; i < arbiters[arbiter].nbr_clients; i++)
357 total_assigned += arbiters[arbiter].requested_slots[region][i];
358
359 crisv32_arbiter_config(arbiter, region, NBR_OF_SLOTS - total_assigned);
360}
361
362int crisv32_arbiter_watch(unsigned long start, unsigned long size,
363 unsigned long clients, unsigned long accesses,
364 watch_callback *cb)
365{
366 int i;
367 int arbiter;
368 int used[2];
369 int ret = 0;
370
371 crisv32_arbiter_init();
372
373 if (start > 0x80000000) {
374 printk(KERN_ERR "Arbiter: %lX doesn't look like a "
375 "physical address", start);
376 return -EFAULT;
377 }
378
379 spin_lock(&arbiter_lock);
380
381 if (clients & 0xffff)
382 used[0] = 1;
383 if (clients & 0xffff0000)
384 used[1] = 1;
385
386 for (arbiter = 0; arbiter < ARBITERS; arbiter++) {
387 if (!used[arbiter])
388 continue;
389
390 for (i = 0; i < NUMBER_OF_BP; i++) {
391 if (!watches[arbiter][i].used) {
392 unsigned intr_mask;
393 if (arbiter)
394 intr_mask = REG_RD_INT(marb_bar,
395 regi_marb_bar, rw_intr_mask);
396 else
397 intr_mask = REG_RD_INT(marb_foo,
398 regi_marb_foo, rw_intr_mask);
399
400 watches[arbiter][i].used = 1;
401 watches[arbiter][i].start = start;
402 watches[arbiter][i].end = start + size;
403 watches[arbiter][i].cb = cb;
404
405 ret |= (i + 1) << (arbiter + 8);
406 if (arbiter) {
407 REG_WR_INT(marb_bar_bp,
408 watches[arbiter][i].instance,
409 rw_first_addr,
410 watches[arbiter][i].start);
411 REG_WR_INT(marb_bar_bp,
412 watches[arbiter][i].instance,
413 rw_last_addr,
414 watches[arbiter][i].end);
415 REG_WR_INT(marb_bar_bp,
416 watches[arbiter][i].instance,
417 rw_op, accesses);
418 REG_WR_INT(marb_bar_bp,
419 watches[arbiter][i].instance,
420 rw_clients,
421 clients & 0xffff);
422 } else {
423 REG_WR_INT(marb_foo_bp,
424 watches[arbiter][i].instance,
425 rw_first_addr,
426 watches[arbiter][i].start);
427 REG_WR_INT(marb_foo_bp,
428 watches[arbiter][i].instance,
429 rw_last_addr,
430 watches[arbiter][i].end);
431 REG_WR_INT(marb_foo_bp,
432 watches[arbiter][i].instance,
433 rw_op, accesses);
434 REG_WR_INT(marb_foo_bp,
435 watches[arbiter][i].instance,
436 rw_clients, clients >> 16);
437 }
438
439 if (i == 0)
440 intr_mask |= 1;
441 else if (i == 1)
442 intr_mask |= 2;
443 else if (i == 2)
444 intr_mask |= 4;
445 else if (i == 3)
446 intr_mask |= 8;
447
448 if (arbiter)
449 REG_WR_INT(marb_bar, regi_marb_bar,
450 rw_intr_mask, intr_mask);
451 else
452 REG_WR_INT(marb_foo, regi_marb_foo,
453 rw_intr_mask, intr_mask);
454
455 spin_unlock(&arbiter_lock);
456
457 break;
458 }
459 }
460 }
461 spin_unlock(&arbiter_lock);
462 if (ret)
463 return ret;
464 else
465 return -ENOMEM;
466}
467
468int crisv32_arbiter_unwatch(int id)
469{
470 int arbiter;
471 int intr_mask;
472
473 crisv32_arbiter_init();
474
475 spin_lock(&arbiter_lock);
476
477 for (arbiter = 0; arbiter < ARBITERS; arbiter++) {
478 int id2;
479
480 if (arbiter)
481 intr_mask = REG_RD_INT(marb_bar, regi_marb_bar,
482 rw_intr_mask);
483 else
484 intr_mask = REG_RD_INT(marb_foo, regi_marb_foo,
485 rw_intr_mask);
486
487 id2 = (id & (0xff << (arbiter + 8))) >> (arbiter + 8);
488 if (id2 == 0)
489 continue;
490 id2--;
491 if ((id2 >= NUMBER_OF_BP) || (!watches[arbiter][id2].used)) {
492 spin_unlock(&arbiter_lock);
493 return -EINVAL;
494 }
495
496 memset(&watches[arbiter][id2], 0,
497 sizeof(struct crisv32_watch_entry));
498
499 if (id2 == 0)
500 intr_mask &= ~1;
501 else if (id2 == 1)
502 intr_mask &= ~2;
503 else if (id2 == 2)
504 intr_mask &= ~4;
505 else if (id2 == 3)
506 intr_mask &= ~8;
507
508 if (arbiter)
509 REG_WR_INT(marb_bar, regi_marb_bar, rw_intr_mask,
510 intr_mask);
511 else
512 REG_WR_INT(marb_foo, regi_marb_foo, rw_intr_mask,
513 intr_mask);
514 }
515
516 spin_unlock(&arbiter_lock);
517 return 0;
518}
519
520extern void show_registers(struct pt_regs *regs);
521
522
523static irqreturn_t
524crisv32_foo_arbiter_irq(int irq, void *dev_id)
525{
526 reg_marb_foo_r_masked_intr masked_intr =
527 REG_RD(marb_foo, regi_marb_foo, r_masked_intr);
528 reg_marb_foo_bp_r_brk_clients r_clients;
529 reg_marb_foo_bp_r_brk_addr r_addr;
530 reg_marb_foo_bp_r_brk_op r_op;
531 reg_marb_foo_bp_r_brk_first_client r_first;
532 reg_marb_foo_bp_r_brk_size r_size;
533 reg_marb_foo_bp_rw_ack ack = {0};
534 reg_marb_foo_rw_ack_intr ack_intr = {
535 .bp0 = 1, .bp1 = 1, .bp2 = 1, .bp3 = 1
536 };
537 struct crisv32_watch_entry *watch;
538 unsigned arbiter = (unsigned)dev_id;
539
540 masked_intr = REG_RD(marb_foo, regi_marb_foo, r_masked_intr);
541
542 if (masked_intr.bp0)
543 watch = &watches[arbiter][0];
544 else if (masked_intr.bp1)
545 watch = &watches[arbiter][1];
546 else if (masked_intr.bp2)
547 watch = &watches[arbiter][2];
548 else if (masked_intr.bp3)
549 watch = &watches[arbiter][3];
550 else
551 return IRQ_NONE;
552
553 /* Retrieve all useful information and print it. */
554 r_clients = REG_RD(marb_foo_bp, watch->instance, r_brk_clients);
555 r_addr = REG_RD(marb_foo_bp, watch->instance, r_brk_addr);
556 r_op = REG_RD(marb_foo_bp, watch->instance, r_brk_op);
557 r_first = REG_RD(marb_foo_bp, watch->instance, r_brk_first_client);
558 r_size = REG_RD(marb_foo_bp, watch->instance, r_brk_size);
559
560 printk(KERN_DEBUG "Arbiter IRQ\n");
561 printk(KERN_DEBUG "Clients %X addr %X op %X first %X size %X\n",
562 REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_clients, r_clients),
563 REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_addr, r_addr),
564 REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_op, r_op),
565 REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_first_client, r_first),
566 REG_TYPE_CONV(int, reg_marb_foo_bp_r_brk_size, r_size));
567
568 REG_WR(marb_foo_bp, watch->instance, rw_ack, ack);
569 REG_WR(marb_foo, regi_marb_foo, rw_ack_intr, ack_intr);
570
571 printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs());
572
573 if (watch->cb)
574 watch->cb();
575
576 return IRQ_HANDLED;
577}
578
579static irqreturn_t
580crisv32_bar_arbiter_irq(int irq, void *dev_id)
581{
582 reg_marb_bar_r_masked_intr masked_intr =
583 REG_RD(marb_bar, regi_marb_bar, r_masked_intr);
584 reg_marb_bar_bp_r_brk_clients r_clients;
585 reg_marb_bar_bp_r_brk_addr r_addr;
586 reg_marb_bar_bp_r_brk_op r_op;
587 reg_marb_bar_bp_r_brk_first_client r_first;
588 reg_marb_bar_bp_r_brk_size r_size;
589 reg_marb_bar_bp_rw_ack ack = {0};
590 reg_marb_bar_rw_ack_intr ack_intr = {
591 .bp0 = 1, .bp1 = 1, .bp2 = 1, .bp3 = 1
592 };
593 struct crisv32_watch_entry *watch;
594 unsigned arbiter = (unsigned)dev_id;
595
596 masked_intr = REG_RD(marb_bar, regi_marb_bar, r_masked_intr);
597
598 if (masked_intr.bp0)
599 watch = &watches[arbiter][0];
600 else if (masked_intr.bp1)
601 watch = &watches[arbiter][1];
602 else if (masked_intr.bp2)
603 watch = &watches[arbiter][2];
604 else if (masked_intr.bp3)
605 watch = &watches[arbiter][3];
606 else
607 return IRQ_NONE;
608
609 /* Retrieve all useful information and print it. */
610 r_clients = REG_RD(marb_bar_bp, watch->instance, r_brk_clients);
611 r_addr = REG_RD(marb_bar_bp, watch->instance, r_brk_addr);
612 r_op = REG_RD(marb_bar_bp, watch->instance, r_brk_op);
613 r_first = REG_RD(marb_bar_bp, watch->instance, r_brk_first_client);
614 r_size = REG_RD(marb_bar_bp, watch->instance, r_brk_size);
615
616 printk(KERN_DEBUG "Arbiter IRQ\n");
617 printk(KERN_DEBUG "Clients %X addr %X op %X first %X size %X\n",
618 REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_clients, r_clients),
619 REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_addr, r_addr),
620 REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_op, r_op),
621 REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_first_client, r_first),
622 REG_TYPE_CONV(int, reg_marb_bar_bp_r_brk_size, r_size));
623
624 REG_WR(marb_bar_bp, watch->instance, rw_ack, ack);
625 REG_WR(marb_bar, regi_marb_bar, rw_ack_intr, ack_intr);
626
627 printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs()->erp);
628
629 if (watch->cb)
630 watch->cb();
631
632 return IRQ_HANDLED;
633}
634
diff --git a/arch/cris/arch-v32/mach-a3/cpufreq.c b/arch/cris/arch-v32/mach-a3/cpufreq.c
new file mode 100644
index 000000000000..8e5a3cab8ad7
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/cpufreq.c
@@ -0,0 +1,153 @@
1#include <linux/init.h>
2#include <linux/module.h>
3#include <linux/cpufreq.h>
4#include <hwregs/reg_map.h>
5#include <hwregs/reg_rdwr.h>
6#include <hwregs/clkgen_defs.h>
7#include <hwregs/ddr2_defs.h>
8
9static int
10cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
11 void *data);
12
13static struct notifier_block cris_sdram_freq_notifier_block = {
14 .notifier_call = cris_sdram_freq_notifier
15};
16
17static struct cpufreq_frequency_table cris_freq_table[] = {
18 {0x01, 6000},
19 {0x02, 200000},
20 {0, CPUFREQ_TABLE_END},
21};
22
23static unsigned int cris_freq_get_cpu_frequency(unsigned int cpu)
24{
25 reg_clkgen_rw_clk_ctrl clk_ctrl;
26 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
27 return clk_ctrl.pll ? 200000 : 6000;
28}
29
30static void cris_freq_set_cpu_state(unsigned int state)
31{
32 int i = 0;
33 struct cpufreq_freqs freqs;
34 reg_clkgen_rw_clk_ctrl clk_ctrl;
35 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
36
37#ifdef CONFIG_SMP
38 for_each_present_cpu(i)
39#endif
40 {
41 freqs.old = cris_freq_get_cpu_frequency(i);
42 freqs.new = cris_freq_table[state].frequency;
43 freqs.cpu = i;
44 }
45
46 cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
47
48 local_irq_disable();
49
50 /* Even though we may be SMP they will share the same clock
51 * so all settings are made on CPU0. */
52 if (cris_freq_table[state].frequency == 200000)
53 clk_ctrl.pll = 1;
54 else
55 clk_ctrl.pll = 0;
56 REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
57
58 local_irq_enable();
59
60 cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
61};
62
63static int cris_freq_verify(struct cpufreq_policy *policy)
64{
65 return cpufreq_frequency_table_verify(policy, &cris_freq_table[0]);
66}
67
68static int cris_freq_target(struct cpufreq_policy *policy,
69 unsigned int target_freq,
70 unsigned int relation)
71{
72 unsigned int newstate = 0;
73
74 if (cpufreq_frequency_table_target(policy, cris_freq_table,
75 target_freq, relation, &newstate))
76 return -EINVAL;
77
78 cris_freq_set_cpu_state(newstate);
79
80 return 0;
81}
82
83static int cris_freq_cpu_init(struct cpufreq_policy *policy)
84{
85 int result;
86
87 /* cpuinfo and default policy values */
88 policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
89 policy->cpuinfo.transition_latency = 1000000; /* 1ms */
90 policy->cur = cris_freq_get_cpu_frequency(0);
91
92 result = cpufreq_frequency_table_cpuinfo(policy, cris_freq_table);
93 if (result)
94 return (result);
95
96 cpufreq_frequency_table_get_attr(cris_freq_table, policy->cpu);
97
98 return 0;
99}
100
101
102static int cris_freq_cpu_exit(struct cpufreq_policy *policy)
103{
104 cpufreq_frequency_table_put_attr(policy->cpu);
105 return 0;
106}
107
108
109static struct freq_attr *cris_freq_attr[] = {
110 &cpufreq_freq_attr_scaling_available_freqs,
111 NULL,
112};
113
114static struct cpufreq_driver cris_freq_driver = {
115 .get = cris_freq_get_cpu_frequency,
116 .verify = cris_freq_verify,
117 .target = cris_freq_target,
118 .init = cris_freq_cpu_init,
119 .exit = cris_freq_cpu_exit,
120 .name = "cris_freq",
121 .owner = THIS_MODULE,
122 .attr = cris_freq_attr,
123};
124
125static int __init cris_freq_init(void)
126{
127 int ret;
128 ret = cpufreq_register_driver(&cris_freq_driver);
129 cpufreq_register_notifier(&cris_sdram_freq_notifier_block,
130 CPUFREQ_TRANSITION_NOTIFIER);
131 return ret;
132}
133
134static int
135cris_sdram_freq_notifier(struct notifier_block *nb, unsigned long val,
136 void *data)
137{
138 int i;
139 struct cpufreq_freqs *freqs = data;
140 if (val == CPUFREQ_PRECHANGE) {
141 reg_ddr2_rw_cfg cfg =
142 REG_RD(ddr2, regi_ddr2_ctrl, rw_cfg);
143 cfg.ref_interval = (freqs->new == 200000 ? 1560 : 46);
144
145 if (freqs->new == 200000)
146 for (i = 0; i < 50000; i++);
147 REG_WR(bif_core, regi_bif_core, rw_sdram_timing, timing);
148 }
149 return 0;
150}
151
152
153module_init(cris_freq_init);
diff --git a/arch/cris/arch-v32/mach-a3/dma.c b/arch/cris/arch-v32/mach-a3/dma.c
new file mode 100644
index 000000000000..0c19fede0e65
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/dma.c
@@ -0,0 +1,185 @@
1/* Wrapper for DMA channel allocator that starts clocks etc */
2
3#include <linux/kernel.h>
4#include <linux/spinlock.h>
5#include <asm/arch/mach/dma.h>
6#include <hwregs/reg_map.h>
7#include <hwregs/reg_rdwr.h>
8#include <hwregs/marb_defs.h>
9#include <hwregs/clkgen_defs.h>
10#include <hwregs/strmux_defs.h>
11#include <linux/errno.h>
12#include <asm/system.h>
13#include <arbiter.h>
14
15static char used_dma_channels[MAX_DMA_CHANNELS];
16static const char *used_dma_channels_users[MAX_DMA_CHANNELS];
17
18static DEFINE_SPINLOCK(dma_lock);
19
20int crisv32_request_dma(unsigned int dmanr, const char *device_id,
21 unsigned options, unsigned int bandwidth, enum dma_owner owner)
22{
23 unsigned long flags;
24 reg_clkgen_rw_clk_ctrl clk_ctrl;
25 reg_strmux_rw_cfg strmux_cfg;
26
27 if (crisv32_arbiter_allocate_bandwith(dmanr,
28 options & DMA_INT_MEM ? INT_REGION : EXT_REGION,
29 bandwidth))
30 return -ENOMEM;
31
32 spin_lock_irqsave(&dma_lock, flags);
33
34 if (used_dma_channels[dmanr]) {
35 spin_unlock_irqrestore(&dma_lock, flags);
36 if (options & DMA_VERBOSE_ON_ERROR)
37 printk(KERN_ERR "Failed to request DMA %i for %s, "
38 "already allocated by %s\n",
39 dmanr,
40 device_id,
41 used_dma_channels_users[dmanr]);
42
43 if (options & DMA_PANIC_ON_ERROR)
44 panic("request_dma error!");
45 spin_unlock_irqrestore(&dma_lock, flags);
46 return -EBUSY;
47 }
48 clk_ctrl = REG_RD(clkgen, regi_clkgen, rw_clk_ctrl);
49 strmux_cfg = REG_RD(strmux, regi_strmux, rw_cfg);
50
51 switch (dmanr) {
52 case 0:
53 case 1:
54 clk_ctrl.dma0_1_eth = 1;
55 break;
56 case 2:
57 case 3:
58 clk_ctrl.dma2_3_strcop = 1;
59 break;
60 case 4:
61 case 5:
62 clk_ctrl.dma4_5_iop = 1;
63 break;
64 case 6:
65 case 7:
66 clk_ctrl.sser_ser_dma6_7 = 1;
67 break;
68 case 9:
69 case 11:
70 clk_ctrl.dma9_11 = 1;
71 break;
72#if MAX_DMA_CHANNELS-1 != 11
73#error Check dma.c
74#endif
75 default:
76 spin_unlock_irqrestore(&dma_lock, flags);
77 if (options & DMA_VERBOSE_ON_ERROR)
78 printk(KERN_ERR "Failed to request DMA %i for %s, "
79 "only 0-%i valid)\n",
80 dmanr, device_id, MAX_DMA_CHANNELS-1);
81
82 if (options & DMA_PANIC_ON_ERROR)
83 panic("request_dma error!");
84 return -EINVAL;
85 }
86
87 switch (owner) {
88 case dma_eth:
89 if (dmanr == 0)
90 strmux_cfg.dma0 = regk_strmux_eth;
91 else if (dmanr == 1)
92 strmux_cfg.dma1 = regk_strmux_eth;
93 else
94 panic("Invalid DMA channel for eth\n");
95 break;
96 case dma_ser0:
97 if (dmanr == 0)
98 strmux_cfg.dma0 = regk_strmux_ser0;
99 else if (dmanr == 1)
100 strmux_cfg.dma1 = regk_strmux_ser0;
101 else
102 panic("Invalid DMA channel for ser0\n");
103 break;
104 case dma_ser3:
105 if (dmanr == 2)
106 strmux_cfg.dma2 = regk_strmux_ser3;
107 else if (dmanr == 3)
108 strmux_cfg.dma3 = regk_strmux_ser3;
109 else
110 panic("Invalid DMA channel for ser3\n");
111 break;
112 case dma_strp:
113 if (dmanr == 2)
114 strmux_cfg.dma2 = regk_strmux_strcop;
115 else if (dmanr == 3)
116 strmux_cfg.dma3 = regk_strmux_strcop;
117 else
118 panic("Invalid DMA channel for strp\n");
119 break;
120 case dma_ser1:
121 if (dmanr == 4)
122 strmux_cfg.dma4 = regk_strmux_ser1;
123 else if (dmanr == 5)
124 strmux_cfg.dma5 = regk_strmux_ser1;
125 else
126 panic("Invalid DMA channel for ser1\n");
127 break;
128 case dma_iop:
129 if (dmanr == 4)
130 strmux_cfg.dma4 = regk_strmux_iop;
131 else if (dmanr == 5)
132 strmux_cfg.dma5 = regk_strmux_iop;
133 else
134 panic("Invalid DMA channel for iop\n");
135 break;
136 case dma_ser2:
137 if (dmanr == 6)
138 strmux_cfg.dma6 = regk_strmux_ser2;
139 else if (dmanr == 7)
140 strmux_cfg.dma7 = regk_strmux_ser2;
141 else
142 panic("Invalid DMA channel for ser2\n");
143 break;
144 case dma_sser:
145 if (dmanr == 6)
146 strmux_cfg.dma6 = regk_strmux_sser;
147 else if (dmanr == 7)
148 strmux_cfg.dma7 = regk_strmux_sser;
149 else
150 panic("Invalid DMA channel for sser\n");
151 break;
152 case dma_ser4:
153 if (dmanr == 9)
154 strmux_cfg.dma9 = regk_strmux_ser4;
155 else
156 panic("Invalid DMA channel for ser4\n");
157 break;
158 case dma_jpeg:
159 if (dmanr == 9)
160 strmux_cfg.dma9 = regk_strmux_jpeg;
161 else
162 panic("Invalid DMA channel for JPEG\n");
163 break;
164 case dma_h264:
165 if (dmanr == 11)
166 strmux_cfg.dma11 = regk_strmux_h264;
167 else
168 panic("Invalid DMA channel for H264\n");
169 break;
170 }
171
172 used_dma_channels[dmanr] = 1;
173 used_dma_channels_users[dmanr] = device_id;
174 REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
175 REG_WR(strmux, regi_strmux, rw_cfg, strmux_cfg);
176 spin_unlock_irqrestore(&dma_lock, flags);
177 return 0;
178}
179
180void crisv32_free_dma(unsigned int dmanr)
181{
182 spin_lock(&dma_lock);
183 used_dma_channels[dmanr] = 0;
184 spin_unlock(&dma_lock);
185}
diff --git a/arch/cris/arch-v32/mach-a3/dram_init.S b/arch/cris/arch-v32/mach-a3/dram_init.S
new file mode 100644
index 000000000000..94d6b41cb299
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/dram_init.S
@@ -0,0 +1,104 @@
1/*
2 * DDR SDRAM initialization - alter with care
3 * This file is intended to be included from other assembler files
4 *
5 * Note: This file may not modify r8 or r9 because they are used to
6 * carry information from the decompresser to the kernel
7 *
8 * Copyright (C) 2005-2007 Axis Communications AB
9 *
10 * Authors: Mikael Starvik <starvik@axis.com>
11 */
12
13/* Just to be certain the config file is included, we include it here
14 * explicitely instead of depending on it being included in the file that
15 * uses this code.
16 */
17
18#include <hwregs/asm/reg_map_asm.h>
19#include <hwregs/asm/ddr2_defs_asm.h>
20
21 ;; WARNING! The registers r8 and r9 are used as parameters carrying
22 ;; information from the decompressor (if the kernel was compressed).
23 ;; They should not be used in the code below.
24
25 ;; Refer to ddr2 MDS for initialization sequence
26
27 ; Start clock
28 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_cfg), $r0
29 move.d REG_STATE(ddr2, rw_phy_cfg, en, yes), $r1
30 move.d $r1, [$r0]
31
32 ; Reset phy and start calibration
33 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_phy_ctrl), $r0
34 move.d REG_STATE(ddr2, rw_phy_ctrl, rst, yes) | \
35 REG_STATE(ddr2, rw_phy_ctrl, cal_rst, yes), $r1
36 move.d $r1, [$r0]
37 move.d REG_STATE(ddr2, rw_phy_ctrl, cal_start, yes), $r1
38 move.d $r1, [$r0]
39
40 ; 2. Wait 200us
41 move.d 10000, $r2
421: bne 1b
43 subq 1, $r2
44
45 ; Issue commands
46 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_ctrl), $r0
47 move.d sdram_commands_start, $r2
48command_loop:
49 movu.b [$r2+], $r1
50 movu.w [$r2+], $r3
51do_cmd:
52 lslq 16, $r1
53 or.d $r3, $r1
54 move.d $r1, [$r0]
55 cmp.d sdram_commands_end, $r2
56 blo command_loop
57 nop
58
59 ; Set timing
60 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_timing), $r0
61 move.d CONFIG_ETRAX_DDR2_TIMING, $r1
62 move.d $r1, [$r0]
63
64 ; Set latency
65 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_latency), $r0
66 move.d 0x13, $r1
67 move.d $r1, [$r0]
68
69 ; Set configuration
70 move.d REG_ADDR(ddr2, regi_ddr2_ctrl, rw_cfg), $r0
71 move.d CONFIG_ETRAX_DDR2_CONFIG, $r1
72 move.d $r1, [$r0]
73
74 ba after_sdram_commands
75 nop
76
77sdram_commands_start:
78 .byte regk_ddr2_deselect
79 .word 0
80 .byte regk_ddr2_pre
81 .word regk_ddr2_pre_all
82 .byte regk_ddr2_emrs2
83 .word 0
84 .byte regk_ddr2_emrs3
85 .word 0
86 .byte regk_ddr2_emrs
87 .word regk_ddr2_dll_en
88 .byte regk_ddr2_mrs
89 .word regk_ddr2_dll_rst
90 .byte regk_ddr2_pre
91 .word regk_ddr2_pre_all
92 .byte regk_ddr2_ref
93 .word 0
94 .byte regk_ddr2_ref
95 .word 0
96 .byte regk_ddr2_mrs
97 .word CONFIG_ETRAX_DDR2_MRS & 0xffff
98 .byte regk_ddr2_emrs
99 .word regk_ddr2_ocd_default | regk_ddr2_dll_en
100 .byte regk_ddr2_emrs
101 .word regk_ddr2_ocd_exit | regk_ddr2_dll_en | (CONFIG_ETRAX_DDR2_MRS >> 16)
102sdram_commands_end:
103 .align 1
104after_sdram_commands:
diff --git a/arch/cris/arch-v32/mach-a3/hw_settings.S b/arch/cris/arch-v32/mach-a3/hw_settings.S
new file mode 100644
index 000000000000..258a6329cd4a
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/hw_settings.S
@@ -0,0 +1,51 @@
1/*
2 * This table is used by some tools to extract hardware parameters.
3 * The table should be included in the kernel and the decompressor.
4 * Don't forget to update the tools if you change this table.
5 *
6 * Copyright (C) 2001-2007 Axis Communications AB
7 *
8 * Authors: Mikael Starvik <starvik@axis.com>
9 */
10
11#include <hwregs/asm/reg_map_asm.h>
12#include <hwregs/asm/ddr2_defs_asm.h>
13#include <hwregs/asm/gio_defs_asm.h>
14
15 .ascii "HW_PARAM_MAGIC" ; Magic number
16 .dword 0xc0004000 ; Kernel start address
17
18 ; Debug port
19#ifdef CONFIG_ETRAX_DEBUG_PORT0
20 .dword 0
21#elif defined(CONFIG_ETRAX_DEBUG_PORT1)
22 .dword 1
23#elif defined(CONFIG_ETRAX_DEBUG_PORT2)
24 .dword 2
25#elif defined(CONFIG_ETRAX_DEBUG_PORT3)
26 .dword 3
27#else
28 .dword 4 ; No debug
29#endif
30
31 ; Register values
32 .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_cfg)
33 .dword CONFIG_ETRAX_DDR2_CONFIG
34 .dword REG_ADDR(ddr2, regi_ddr2_ctrl, rw_timing)
35 .dword CONFIG_ETRAX_DDR2_TIMING
36 .dword CONFIG_ETRAX_DDR2_MRS
37
38 .dword REG_ADDR(gio, regi_gio, rw_pa_dout)
39 .dword CONFIG_ETRAX_DEF_GIO_PA_OUT
40 .dword REG_ADDR(gio, regi_gio, rw_pa_oe)
41 .dword CONFIG_ETRAX_DEF_GIO_PA_OE
42 .dword REG_ADDR(gio, regi_gio, rw_pb_dout)
43 .dword CONFIG_ETRAX_DEF_GIO_PB_OUT
44 .dword REG_ADDR(gio, regi_gio, rw_pb_oe)
45 .dword CONFIG_ETRAX_DEF_GIO_PB_OE
46 .dword REG_ADDR(gio, regi_gio, rw_pc_dout)
47 .dword CONFIG_ETRAX_DEF_GIO_PC_OUT
48 .dword REG_ADDR(gio, regi_gio, rw_pc_oe)
49 .dword CONFIG_ETRAX_DEF_GIO_PC_OE
50
51 .dword 0 ; No more register values
diff --git a/arch/cris/arch-v32/mach-a3/io.c b/arch/cris/arch-v32/mach-a3/io.c
new file mode 100644
index 000000000000..5e6c1aad8b4f
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/io.c
@@ -0,0 +1,150 @@
1/*
2 * Helper functions for I/O pins.
3 *
4 * Copyright (c) 2005-2007 Axis Communications AB.
5 */
6
7#include <linux/types.h>
8#include <linux/errno.h>
9#include <linux/init.h>
10#include <linux/string.h>
11#include <linux/ctype.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <asm/io.h>
15#include <asm/arch/mach/pinmux.h>
16#include <hwregs/gio_defs.h>
17
18struct crisv32_ioport crisv32_ioports[] = {
19 {
20 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_oe),
21 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pa_dout),
22 (unsigned long *)REG_ADDR(gio, regi_gio, r_pa_din),
23 32
24 },
25 {
26 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_oe),
27 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pb_dout),
28 (unsigned long *)REG_ADDR(gio, regi_gio, r_pb_din),
29 32
30 },
31 {
32 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_oe),
33 (unsigned long *)REG_ADDR(gio, regi_gio, rw_pc_dout),
34 (unsigned long *)REG_ADDR(gio, regi_gio, r_pc_din),
35 16
36 },
37};
38
39#define NBR_OF_PORTS sizeof(crisv32_ioports)/sizeof(struct crisv32_ioport)
40
41struct crisv32_iopin crisv32_led_net0_green;
42struct crisv32_iopin crisv32_led_net0_red;
43struct crisv32_iopin crisv32_led2_green;
44struct crisv32_iopin crisv32_led2_red;
45struct crisv32_iopin crisv32_led3_green;
46struct crisv32_iopin crisv32_led3_red;
47
48/* Dummy port used when green LED and red LED is on the same bit */
49static unsigned long io_dummy;
50static struct crisv32_ioport dummy_port = {
51 &io_dummy,
52 &io_dummy,
53 &io_dummy,
54 32
55};
56static struct crisv32_iopin dummy_led = {
57 &dummy_port,
58 0
59};
60
61static int __init crisv32_io_init(void)
62{
63 int ret = 0;
64
65 u32 i;
66
67 /* Locks *should* be dynamically initialized. */
68 for (i = 0; i < ARRAY_SIZE(crisv32_ioports); i++)
69 spin_lock_init(&crisv32_ioports[i].lock);
70 spin_lock_init(&dummy_port.lock);
71
72 /* Initialize LEDs */
73#if (defined(CONFIG_ETRAX_NBR_LED_GRP_ONE) || defined(CONFIG_ETRAX_NBR_LED_GRP_TWO))
74 ret += crisv32_io_get_name(&crisv32_led_net0_green,
75 CONFIG_ETRAX_LED_G_NET0);
76 crisv32_io_set_dir(&crisv32_led_net0_green, crisv32_io_dir_out);
77 if (strcmp(CONFIG_ETRAX_LED_G_NET0, CONFIG_ETRAX_LED_R_NET0)) {
78 ret += crisv32_io_get_name(&crisv32_led_net0_red,
79 CONFIG_ETRAX_LED_R_NET0);
80 crisv32_io_set_dir(&crisv32_led_net0_red, crisv32_io_dir_out);
81 } else
82 crisv32_led_net0_red = dummy_led;
83#endif
84
85 ret += crisv32_io_get_name(&crisv32_led2_green, CONFIG_ETRAX_V32_LED2G);
86 ret += crisv32_io_get_name(&crisv32_led2_red, CONFIG_ETRAX_V32_LED2R);
87 ret += crisv32_io_get_name(&crisv32_led3_green, CONFIG_ETRAX_V32_LED3G);
88 ret += crisv32_io_get_name(&crisv32_led3_red, CONFIG_ETRAX_V32_LED3R);
89
90 crisv32_io_set_dir(&crisv32_led2_green, crisv32_io_dir_out);
91 crisv32_io_set_dir(&crisv32_led2_red, crisv32_io_dir_out);
92 crisv32_io_set_dir(&crisv32_led3_green, crisv32_io_dir_out);
93 crisv32_io_set_dir(&crisv32_led3_red, crisv32_io_dir_out);
94
95 return ret;
96}
97
98__initcall(crisv32_io_init);
99
100int crisv32_io_get(struct crisv32_iopin *iopin,
101 unsigned int port, unsigned int pin)
102{
103 if (port > NBR_OF_PORTS)
104 return -EINVAL;
105 if (port > crisv32_ioports[port].pin_count)
106 return -EINVAL;
107
108 iopin->bit = 1 << pin;
109 iopin->port = &crisv32_ioports[port];
110
111 if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
112 return -EIO;
113
114 return 0;
115}
116
117int crisv32_io_get_name(struct crisv32_iopin *iopin,
118 const char *name)
119{
120 int port;
121 int pin;
122
123 if (toupper(*name) == 'P')
124 name++;
125
126 if (toupper(*name) < 'A' || toupper(*name) > 'E')
127 return -EINVAL;
128
129 port = toupper(*name) - 'A';
130 name++;
131 pin = simple_strtoul(name, NULL, 10);
132
133 if (pin < 0 || pin > crisv32_ioports[port].pin_count)
134 return -EINVAL;
135
136 iopin->bit = 1 << pin;
137 iopin->port = &crisv32_ioports[port];
138
139 if (crisv32_pinmux_alloc(port, pin, pin, pinmux_gpio))
140 return -EIO;
141
142 return 0;
143}
144
145#ifdef CONFIG_PCI
146/* PCI I/O access stuff */
147struct cris_io_operations *cris_iops = NULL;
148EXPORT_SYMBOL(cris_iops);
149#endif
150
diff --git a/arch/cris/arch-v32/mach-a3/pinmux.c b/arch/cris/arch-v32/mach-a3/pinmux.c
new file mode 100644
index 000000000000..0a28c9bedfb7
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/pinmux.c
@@ -0,0 +1,386 @@
1/*
2 * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
3 * Unassigned pins and GPIO pins can be allocated to a fixed interface
4 * or the I/O processor instead.
5 *
6 * Copyright (c) 2005-2007 Axis Communications AB.
7 */
8
9#include <linux/init.h>
10#include <linux/errno.h>
11#include <linux/kernel.h>
12#include <linux/string.h>
13#include <linux/spinlock.h>
14#include <hwregs/reg_map.h>
15#include <hwregs/reg_rdwr.h>
16#include <pinmux.h>
17#include <hwregs/pinmux_defs.h>
18#include <hwregs/clkgen_defs.h>
19
20#undef DEBUG
21
22#define PINS 80
23#define PORT_PINS 32
24#define PORTS 3
25
26static char pins[PINS];
27static DEFINE_SPINLOCK(pinmux_lock);
28
29static void crisv32_pinmux_set(int port);
30
31int
32crisv32_pinmux_init(void)
33{
34 static int initialized;
35
36 if (!initialized) {
37 initialized = 1;
38 REG_WR_INT(pinmux, regi_pinmux, rw_hwprot, 0);
39 crisv32_pinmux_alloc(PORT_A, 0, 31, pinmux_gpio);
40 crisv32_pinmux_alloc(PORT_B, 0, 31, pinmux_gpio);
41 crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_gpio);
42 }
43
44 return 0;
45}
46
47int
48crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
49{
50 int i;
51 unsigned long flags;
52
53 crisv32_pinmux_init();
54
55 if (port >= PORTS)
56 return -EINVAL;
57
58 spin_lock_irqsave(&pinmux_lock, flags);
59
60 for (i = first_pin; i <= last_pin; i++) {
61 if ((pins[port * PORT_PINS + i] != pinmux_none) &&
62 (pins[port * PORT_PINS + i] != pinmux_gpio) &&
63 (pins[port * PORT_PINS + i] != mode)) {
64 spin_unlock_irqrestore(&pinmux_lock, flags);
65#ifdef DEBUG
66 panic("Pinmux alloc failed!\n");
67#endif
68 return -EPERM;
69 }
70 }
71
72 for (i = first_pin; i <= last_pin; i++)
73 pins[port * PORT_PINS + i] = mode;
74
75 crisv32_pinmux_set(port);
76
77 spin_unlock_irqrestore(&pinmux_lock, flags);
78
79 return 0;
80}
81
82int
83crisv32_pinmux_alloc_fixed(enum fixed_function function)
84{
85 int ret = -EINVAL;
86 char saved[sizeof pins];
87 unsigned long flags;
88
89 spin_lock_irqsave(&pinmux_lock, flags);
90
91 /* Save internal data for recovery */
92 memcpy(saved, pins, sizeof pins);
93
94 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
95
96 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
97 reg_clkgen_rw_clk_ctrl clk_ctrl = REG_RD(clkgen, regi_clkgen,
98 rw_clk_ctrl);
99
100 switch (function) {
101 case pinmux_eth:
102 clk_ctrl.eth = regk_clkgen_yes;
103 clk_ctrl.dma0_1_eth = regk_clkgen_yes;
104 ret = crisv32_pinmux_alloc(PORT_B, 8, 23, pinmux_fixed);
105 ret |= crisv32_pinmux_alloc(PORT_B, 24, 25, pinmux_fixed);
106 hwprot.eth = hwprot.eth_mdio = regk_pinmux_yes;
107 break;
108 case pinmux_geth:
109 ret = crisv32_pinmux_alloc(PORT_B, 0, 7, pinmux_fixed);
110 hwprot.geth = regk_pinmux_yes;
111 break;
112 case pinmux_tg_cmos:
113 clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
114 ret = crisv32_pinmux_alloc(PORT_B, 27, 29, pinmux_fixed);
115 hwprot.tg_clk = regk_pinmux_yes;
116 break;
117 case pinmux_tg_ccd:
118 clk_ctrl.ccd_tg_100 = clk_ctrl.ccd_tg_200 = regk_clkgen_yes;
119 ret = crisv32_pinmux_alloc(PORT_B, 27, 31, pinmux_fixed);
120 ret |= crisv32_pinmux_alloc(PORT_C, 0, 15, pinmux_fixed);
121 hwprot.tg = hwprot.tg_clk = regk_pinmux_yes;
122 break;
123 case pinmux_vout:
124 clk_ctrl.strdma0_2_video = regk_clkgen_yes;
125 ret = crisv32_pinmux_alloc(PORT_A, 8, 18, pinmux_fixed);
126 hwprot.vout = hwprot.vout_sync = regk_pinmux_yes;
127 break;
128 case pinmux_ser1:
129 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
130 ret = crisv32_pinmux_alloc(PORT_A, 24, 25, pinmux_fixed);
131 hwprot.ser1 = regk_pinmux_yes;
132 break;
133 case pinmux_ser2:
134 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
135 ret = crisv32_pinmux_alloc(PORT_A, 26, 27, pinmux_fixed);
136 hwprot.ser2 = regk_pinmux_yes;
137 break;
138 case pinmux_ser3:
139 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
140 ret = crisv32_pinmux_alloc(PORT_A, 28, 29, pinmux_fixed);
141 hwprot.ser3 = regk_pinmux_yes;
142 break;
143 case pinmux_ser4:
144 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
145 ret = crisv32_pinmux_alloc(PORT_A, 30, 31, pinmux_fixed);
146 hwprot.ser4 = regk_pinmux_yes;
147 break;
148 case pinmux_sser:
149 clk_ctrl.sser_ser_dma6_7 = regk_clkgen_yes;
150 ret = crisv32_pinmux_alloc(PORT_A, 19, 23, pinmux_fixed);
151 hwprot.sser = regk_pinmux_yes;
152 break;
153 case pinmux_pio:
154 hwprot.pio = regk_pinmux_yes;
155 ret = 0;
156 break;
157 case pinmux_pwm0:
158 ret = crisv32_pinmux_alloc(PORT_A, 30, 30, pinmux_fixed);
159 hwprot.pwm0 = regk_pinmux_yes;
160 break;
161 case pinmux_pwm1:
162 ret = crisv32_pinmux_alloc(PORT_A, 31, 31, pinmux_fixed);
163 hwprot.pwm1 = regk_pinmux_yes;
164 break;
165 case pinmux_pwm2:
166 ret = crisv32_pinmux_alloc(PORT_B, 26, 26, pinmux_fixed);
167 hwprot.pwm2 = regk_pinmux_yes;
168 break;
169 case pinmux_i2c0:
170 ret = crisv32_pinmux_alloc(PORT_A, 0, 1, pinmux_fixed);
171 hwprot.i2c0 = regk_pinmux_yes;
172 break;
173 case pinmux_i2c1:
174 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
175 hwprot.i2c1 = regk_pinmux_yes;
176 break;
177 case pinmux_i2c1_3wire:
178 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
179 ret |= crisv32_pinmux_alloc(PORT_A, 7, 7, pinmux_fixed);
180 hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_yes;
181 break;
182 case pinmux_i2c1_sda1:
183 ret = crisv32_pinmux_alloc(PORT_A, 2, 4, pinmux_fixed);
184 hwprot.i2c1 = hwprot.i2c1_sda1 = regk_pinmux_yes;
185 break;
186 case pinmux_i2c1_sda2:
187 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
188 ret |= crisv32_pinmux_alloc(PORT_A, 5, 5, pinmux_fixed);
189 hwprot.i2c1 = hwprot.i2c1_sda2 = regk_pinmux_yes;
190 break;
191 case pinmux_i2c1_sda3:
192 ret = crisv32_pinmux_alloc(PORT_A, 2, 3, pinmux_fixed);
193 ret |= crisv32_pinmux_alloc(PORT_A, 6, 6, pinmux_fixed);
194 hwprot.i2c1 = hwprot.i2c1_sda3 = regk_pinmux_yes;
195 break;
196 default:
197 ret = -EINVAL;
198 break;
199 }
200
201 if (!ret) {
202 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
203 REG_WR(clkgen, regi_clkgen, rw_clk_ctrl, clk_ctrl);
204 } else
205 memcpy(pins, saved, sizeof pins);
206
207 spin_unlock_irqrestore(&pinmux_lock, flags);
208
209 return ret;
210}
211
212void
213crisv32_pinmux_set(int port)
214{
215 int i;
216 int gpio_val = 0;
217 int iop_val = 0;
218 int pin = port * PORT_PINS;
219
220 for (i = 0; (i < PORT_PINS) && (pin < PINS); i++, pin++) {
221 if (pins[pin] == pinmux_gpio)
222 gpio_val |= (1 << i);
223 else if (pins[pin] == pinmux_iop)
224 iop_val |= (1 << i);
225 }
226
227 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_gio_pa + 4 * port,
228 gpio_val);
229 REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_iop_pa + 4 * port,
230 iop_val);
231
232#ifdef DEBUG
233 crisv32_pinmux_dump();
234#endif
235}
236
237int
238crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
239{
240 int i;
241 unsigned long flags;
242
243 crisv32_pinmux_init();
244
245 if (port > PORTS)
246 return -EINVAL;
247
248 spin_lock_irqsave(&pinmux_lock, flags);
249
250 for (i = first_pin; i <= last_pin; i++)
251 pins[port * PORT_PINS + i] = pinmux_none;
252
253 crisv32_pinmux_set(port);
254 spin_unlock_irqrestore(&pinmux_lock, flags);
255
256 return 0;
257}
258
259int
260crisv32_pinmux_dealloc_fixed(enum fixed_function function)
261{
262 int ret = -EINVAL;
263 char saved[sizeof pins];
264 unsigned long flags;
265
266 spin_lock_irqsave(&pinmux_lock, flags);
267
268 /* Save internal data for recovery */
269 memcpy(saved, pins, sizeof pins);
270
271 crisv32_pinmux_init(); /* must be done before we read rw_hwprot */
272
273 reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);
274
275 switch (function) {
276 case pinmux_eth:
277 ret = crisv32_pinmux_dealloc(PORT_B, 8, 23);
278 ret |= crisv32_pinmux_dealloc(PORT_B, 24, 25);
279 ret |= crisv32_pinmux_dealloc(PORT_B, 0, 7);
280 hwprot.eth = hwprot.eth_mdio = hwprot.geth = regk_pinmux_no;
281 break;
282 case pinmux_tg_cmos:
283 ret = crisv32_pinmux_dealloc(PORT_B, 27, 29);
284 hwprot.tg_clk = regk_pinmux_no;
285 break;
286 case pinmux_tg_ccd:
287 ret = crisv32_pinmux_dealloc(PORT_B, 27, 31);
288 ret |= crisv32_pinmux_dealloc(PORT_C, 0, 15);
289 hwprot.tg = hwprot.tg_clk = regk_pinmux_no;
290 break;
291 case pinmux_vout:
292 ret = crisv32_pinmux_dealloc(PORT_A, 8, 18);
293 hwprot.vout = hwprot.vout_sync = regk_pinmux_no;
294 break;
295 case pinmux_ser1:
296 ret = crisv32_pinmux_dealloc(PORT_A, 24, 25);
297 hwprot.ser1 = regk_pinmux_no;
298 break;
299 case pinmux_ser2:
300 ret = crisv32_pinmux_dealloc(PORT_A, 26, 27);
301 hwprot.ser2 = regk_pinmux_no;
302 break;
303 case pinmux_ser3:
304 ret = crisv32_pinmux_dealloc(PORT_A, 28, 29);
305 hwprot.ser3 = regk_pinmux_no;
306 break;
307 case pinmux_ser4:
308 ret = crisv32_pinmux_dealloc(PORT_A, 30, 31);
309 hwprot.ser4 = regk_pinmux_no;
310 break;
311 case pinmux_sser:
312 ret = crisv32_pinmux_dealloc(PORT_A, 19, 23);
313 hwprot.sser = regk_pinmux_no;
314 break;
315 case pinmux_pwm0:
316 ret = crisv32_pinmux_dealloc(PORT_A, 30, 30);
317 hwprot.pwm0 = regk_pinmux_no;
318 break;
319 case pinmux_pwm1:
320 ret = crisv32_pinmux_dealloc(PORT_A, 31, 31);
321 hwprot.pwm1 = regk_pinmux_no;
322 break;
323 case pinmux_pwm2:
324 ret = crisv32_pinmux_dealloc(PORT_B, 26, 26);
325 hwprot.pwm2 = regk_pinmux_no;
326 break;
327 case pinmux_i2c0:
328 ret = crisv32_pinmux_dealloc(PORT_A, 0, 1);
329 hwprot.i2c0 = regk_pinmux_no;
330 break;
331 case pinmux_i2c1:
332 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
333 hwprot.i2c1 = regk_pinmux_no;
334 break;
335 case pinmux_i2c1_3wire:
336 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
337 ret |= crisv32_pinmux_dealloc(PORT_A, 7, 7);
338 hwprot.i2c1 = hwprot.i2c1_sen = regk_pinmux_no;
339 break;
340 case pinmux_i2c1_sda1:
341 ret = crisv32_pinmux_dealloc(PORT_A, 2, 4);
342 hwprot.i2c1_sda1 = regk_pinmux_no;
343 break;
344 case pinmux_i2c1_sda2:
345 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
346 ret |= crisv32_pinmux_dealloc(PORT_A, 5, 5);
347 hwprot.i2c1_sda2 = regk_pinmux_no;
348 break;
349 case pinmux_i2c1_sda3:
350 ret = crisv32_pinmux_dealloc(PORT_A, 2, 3);
351 ret |= crisv32_pinmux_dealloc(PORT_A, 6, 6);
352 hwprot.i2c1_sda3 = regk_pinmux_no;
353 break;
354 default:
355 ret = -EINVAL;
356 break;
357 }
358
359 if (!ret)
360 REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
361 else
362 memcpy(pins, saved, sizeof pins);
363
364 spin_unlock_irqrestore(&pinmux_lock, flags);
365
366 return ret;
367}
368
369void
370crisv32_pinmux_dump(void)
371{
372 int i, j;
373 int pin = 0;
374
375 crisv32_pinmux_init();
376
377 for (i = 0; i < PORTS; i++) {
378 pin++;
379 printk(KERN_DEBUG "Port %c\n", 'A'+i);
380 for (j = 0; (j < PORT_PINS) && (pin < PINS); j++, pin++)
381 printk(KERN_DEBUG
382 " Pin %d = %d\n", j, pins[i * PORT_PINS + j]);
383 }
384}
385
386__initcall(crisv32_pinmux_init);
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.c b/arch/cris/arch-v32/mach-a3/vcs_hook.c
new file mode 100644
index 000000000000..58b1a5469fd7
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/vcs_hook.c
@@ -0,0 +1,103 @@
1/*
2 * Simulator hook mechanism
3 */
4
5#include "vcs_hook.h"
6#include <asm/io.h>
7#include <stdarg.h>
8
9#define HOOK_TRIG_ADDR 0xb7000000
10#define HOOK_MEM_BASE_ADDR 0xce000000
11
12static volatile unsigned *hook_base;
13
14#define HOOK_DATA(offset) hook_base[offset]
15#define VHOOK_DATA(offset) hook_base[offset]
16#define HOOK_TRIG(funcid) \
17 do { \
18 *((unsigned *) HOOK_TRIG_ADDR) = funcid; \
19 } while (0)
20#define HOOK_DATA_BYTE(offset) ((unsigned char *)hook_base)[offset]
21
22static void hook_init(void)
23{
24 static int first = 1;
25 if (first) {
26 first = 0;
27 hook_base = ioremap(HOOK_MEM_BASE_ADDR, 8192);
28 }
29}
30
31static unsigned hook_trig(unsigned id)
32{
33 unsigned ret;
34
35 /* preempt_disable(); */
36
37 /* Dummy read from mem to make sure data has propagated to memory
38 * before trigging */
39 ret = *hook_base;
40
41 /* trigger hook */
42 HOOK_TRIG(id);
43
44 /* wait for call to finish */
45 while (VHOOK_DATA(0) > 0) ;
46
47 /* extract return value */
48
49 ret = VHOOK_DATA(1);
50
51 return ret;
52}
53
54int hook_call(unsigned id, unsigned pcnt, ...)
55{
56 va_list ap;
57 int i;
58 unsigned ret;
59
60 hook_init();
61
62 HOOK_DATA(0) = id;
63
64 va_start(ap, pcnt);
65 for (i = 1; i <= pcnt; i++)
66 HOOK_DATA(i) = va_arg(ap, unsigned);
67 va_end(ap);
68
69 ret = hook_trig(id);
70
71 return ret;
72}
73
74int hook_call_str(unsigned id, unsigned size, const char *str)
75{
76 int i;
77 unsigned ret;
78
79 hook_init();
80
81 HOOK_DATA(0) = id;
82 HOOK_DATA(1) = size;
83
84 for (i = 0; i < size; i++)
85 HOOK_DATA_BYTE(8 + i) = str[i];
86 HOOK_DATA_BYTE(8 + i) = 0;
87
88 ret = hook_trig(id);
89
90 return ret;
91}
92
93void print_str(const char *str)
94{
95 int i;
96 /* find null at end of string */
97 for (i = 1; str[i]; i++) ;
98 hook_call(hook_print_str, i, str);
99}
100
101void CPU_WATCHDOG_TIMEOUT(unsigned t)
102{
103}
diff --git a/arch/cris/arch-v32/mach-a3/vcs_hook.h b/arch/cris/arch-v32/mach-a3/vcs_hook.h
new file mode 100644
index 000000000000..8b73d0e8392d
--- /dev/null
+++ b/arch/cris/arch-v32/mach-a3/vcs_hook.h
@@ -0,0 +1,58 @@
1/*
2 * Simulator hook call mechanism
3 */
4
5#ifndef __hook_h__
6#define __hook_h__
7
8int hook_call(unsigned id, unsigned pcnt, ...);
9int hook_call_str(unsigned id, unsigned size, const char *str);
10
11enum hook_ids {
12 hook_debug_on = 1,
13 hook_debug_off,
14 hook_stop_sim_ok,
15 hook_stop_sim_fail,
16 hook_alloc_shared,
17 hook_ptr_shared,
18 hook_free_shared,
19 hook_file2shared,
20 hook_cmp_shared,
21 hook_print_params,
22 hook_sim_time,
23 hook_stop_sim,
24 hook_kick_dog,
25 hook_dog_timeout,
26 hook_rand,
27 hook_srand,
28 hook_rand_range,
29 hook_print_str,
30 hook_print_hex,
31 hook_cmp_offset_shared,
32 hook_fill_random_shared,
33 hook_alloc_random_data,
34 hook_calloc_random_data,
35 hook_print_int,
36 hook_print_uint,
37 hook_fputc,
38 hook_init_fd,
39 hook_sbrk,
40 hook_print_context_descr,
41 hook_print_data_descr,
42 hook_print_group_descr,
43 hook_fill_shared,
44 hook_sl_srand,
45 hook_sl_rand_irange,
46 hook_sl_rand_urange,
47 hook_sl_sh_malloc_aligned,
48 hook_sl_sh_calloc_aligned,
49 hook_sl_sh_alloc_random_data,
50 hook_sl_sh_file2mem,
51 hook_sl_vera_mbox_handle,
52 hook_sl_vera_mbox_put,
53 hook_sl_vera_mbox_get,
54 hook_sl_system,
55 hook_sl_sh_hexdump
56};
57
58#endif