]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/bfin/dv-bfin_sic.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / bfin / dv-bfin_sic.c
CommitLineData
ef016f83
MF
1/* Blackfin System Interrupt Controller (SIC) model.
2
8acc9f48 3 Copyright (C) 2010-2013 Free Software Foundation, Inc.
ef016f83
MF
4 Contributed by Analog Devices, Inc.
5
6 This file is part of simulators.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22
23#include "sim-main.h"
24#include "devices.h"
25#include "dv-bfin_sic.h"
26#include "dv-bfin_cec.h"
27
28struct bfin_sic
29{
30 /* We assume first element is the base. */
31 bu32 base;
32
33 /* Order after here is important -- matches hardware MMR layout. */
34 bu16 BFIN_MMR_16(swrst);
35 bu16 BFIN_MMR_16(syscr);
36 bu16 BFIN_MMR_16(rvect); /* XXX: BF59x has a 32bit AUX_REVID here. */
37 union {
38 struct {
39 bu32 imask0;
40 bu32 iar0, iar1, iar2, iar3;
41 bu32 isr0, iwr0;
42 bu32 _pad0[9];
43 bu32 imask1;
44 bu32 iar4, iar5, iar6, iar7;
45 bu32 isr1, iwr1;
46 } bf52x;
47 struct {
48 bu32 imask;
49 bu32 iar0, iar1, iar2, iar3;
50 bu32 isr, iwr;
51 } bf537;
52 struct {
53 bu32 imask0, imask1, imask2;
54 bu32 isr0, isr1, isr2;
55 bu32 iwr0, iwr1, iwr2;
56 bu32 iar0, iar1, iar2, iar3;
57 bu32 iar4, iar5, iar6, iar7;
58 bu32 iar8, iar9, iar10, iar11;
59 } bf54x;
60 struct {
61 bu32 imask0, imask1;
62 bu32 iar0, iar1, iar2, iar3;
63 bu32 iar4, iar5, iar6, iar7;
64 bu32 isr0, isr1;
65 bu32 iwr0, iwr1;
66 } bf561;
67 };
68};
69#define mmr_base() offsetof(struct bfin_sic, swrst)
70#define mmr_offset(mmr) (offsetof(struct bfin_sic, mmr) - mmr_base())
71#define mmr_idx(mmr) (mmr_offset (mmr) / 4)
72
990d19fd
MF
73static const char * const bf52x_mmr_names[] =
74{
ef016f83
MF
75 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IAR0", "SIC_IAR1",
76 "SIC_IAR2", "SIC_IAR3", "SIC_ISR0", "SIC_IWR0",
77 [mmr_idx (bf52x.imask1)] = "SIC_IMASK1", "SIC_IAR4", "SIC_IAR5",
78 "SIC_IAR6", "SIC_IAR7", "SIC_ISR1", "SIC_IWR1",
79};
990d19fd
MF
80static const char * const bf537_mmr_names[] =
81{
ef016f83
MF
82 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK", "SIC_IAR0", "SIC_IAR1",
83 "SIC_IAR2", "SIC_IAR3", "SIC_ISR", "SIC_IWR",
84};
990d19fd
MF
85static const char * const bf54x_mmr_names[] =
86{
ef016f83
MF
87 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1", "SIC_IMASK2",
88 "SIC_ISR0", "SIC_ISR1", "SIC_ISR2", "SIC_IWR0", "SIC_IWR1", "SIC_IWR2",
89 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
90 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
91 "SIC_IAR8", "SIC_IAR9", "SIC_IAR10", "SIC_IAR11",
92};
990d19fd
MF
93static const char * const bf561_mmr_names[] =
94{
ef016f83
MF
95 "SWRST", "SYSCR", "SIC_RVECT", "SIC_IMASK0", "SIC_IMASK1",
96 "SIC_IAR0", "SIC_IAR1", "SIC_IAR2", "SIC_IAR3",
97 "SIC_IAR4", "SIC_IAR5", "SIC_IAR6", "SIC_IAR7",
98 "SIC_ISR0", "SIC_ISR1", "SIC_IWR0", "SIC_IWR1",
99};
100static const char * const *mmr_names;
101#define mmr_name(off) (mmr_names[(off) / 4] ? : "<INV>")
102
103static void
104bfin_sic_forward_interrupts (struct hw *me, bu32 *isr, bu32 *imask, bu32 *iar)
105{
106 int my_port;
107 bu32 ipend;
108
109 /* Process pending and unmasked interrupts. */
110 ipend = *isr & *imask;
111
112 /* Usually none are pending unmasked, so avoid bit twiddling. */
113 if (!ipend)
114 return;
115
116 for (my_port = 0; my_port < 32; ++my_port)
117 {
118 bu32 iar_idx, iar_off, iar_val;
119 bu32 bit = (1 << my_port);
120
121 /* This bit isn't pending, so check next one. */
122 if (!(ipend & bit))
123 continue;
124
125 /* The IAR registers map the System input to the Core output.
126 Every 4 bits in the IAR are used to map to IVG{7..15}. */
127 iar_idx = my_port / 8;
128 iar_off = (my_port % 8) * 4;
129 iar_val = (iar[iar_idx] & (0xf << iar_off)) >> iar_off;
a31d4fd9 130 HW_TRACE ((me, "forwarding int %i to CEC", IVG7 + iar_val));
ef016f83
MF
131 hw_port_event (me, IVG7 + iar_val, 1);
132 }
133}
134
135static void
136bfin_sic_52x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
137{
138 bfin_sic_forward_interrupts (me, &sic->bf52x.isr0, &sic->bf52x.imask0, &sic->bf52x.iar0);
139 bfin_sic_forward_interrupts (me, &sic->bf52x.isr1, &sic->bf52x.imask1, &sic->bf52x.iar4);
140}
141
142static unsigned
143bfin_sic_52x_io_write_buffer (struct hw *me, const void *source, int space,
144 address_word addr, unsigned nr_bytes)
145{
146 struct bfin_sic *sic = hw_data (me);
147 bu32 mmr_off;
148 bu32 value;
149 bu16 *value16p;
150 bu32 *value32p;
151 void *valuep;
152
153 if (nr_bytes == 4)
154 value = dv_load_4 (source);
155 else
156 value = dv_load_2 (source);
157
158 mmr_off = addr - sic->base;
159 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
160 value16p = valuep;
161 value32p = valuep;
162
163 HW_TRACE_WRITE ();
164
165 /* XXX: Discard all SIC writes for now. */
166 switch (mmr_off)
167 {
168 case mmr_offset(swrst):
169 /* XXX: This should trigger a software reset ... */
170 break;
171 case mmr_offset(syscr):
172 /* XXX: what to do ... */
173 break;
174 case mmr_offset(bf52x.imask0):
175 case mmr_offset(bf52x.imask1):
176 bfin_sic_52x_forward_interrupts (me, sic);
177 *value32p = value;
178 break;
179 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
180 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
181 case mmr_offset(bf52x.iwr0):
182 case mmr_offset(bf52x.iwr1):
183 *value32p = value;
184 break;
185 case mmr_offset(bf52x.isr0):
186 case mmr_offset(bf52x.isr1):
187 /* ISR is read-only. */
188 break;
189 default:
190 /* XXX: Should discard other writes. */
191 ;
192 }
193
194 return nr_bytes;
195}
196
197static unsigned
198bfin_sic_52x_io_read_buffer (struct hw *me, void *dest, int space,
199 address_word addr, unsigned nr_bytes)
200{
201 struct bfin_sic *sic = hw_data (me);
202 bu32 mmr_off;
203 bu16 *value16p;
204 bu32 *value32p;
205 void *valuep;
206
207 mmr_off = addr - sic->base;
208 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
209 value16p = valuep;
210 value32p = valuep;
211
212 HW_TRACE_READ ();
213
214 switch (mmr_off)
215 {
216 case mmr_offset(swrst):
217 case mmr_offset(syscr):
218 case mmr_offset(rvect):
219 dv_store_2 (dest, *value16p);
220 break;
221 case mmr_offset(bf52x.imask0):
222 case mmr_offset(bf52x.imask1):
223 case mmr_offset(bf52x.iar0) ... mmr_offset(bf52x.iar3):
224 case mmr_offset(bf52x.iar4) ... mmr_offset(bf52x.iar7):
225 case mmr_offset(bf52x.iwr0):
226 case mmr_offset(bf52x.iwr1):
227 case mmr_offset(bf52x.isr0):
228 case mmr_offset(bf52x.isr1):
229 dv_store_4 (dest, *value32p);
230 break;
231 default:
232 if (nr_bytes == 2)
233 dv_store_2 (dest, 0);
234 else
235 dv_store_4 (dest, 0);
236 break;
237 }
238
239 return nr_bytes;
240}
241
242static void
243bfin_sic_537_forward_interrupts (struct hw *me, struct bfin_sic *sic)
244{
245 bfin_sic_forward_interrupts (me, &sic->bf537.isr, &sic->bf537.imask, &sic->bf537.iar0);
246}
247
248static unsigned
249bfin_sic_537_io_write_buffer (struct hw *me, const void *source, int space,
250 address_word addr, unsigned nr_bytes)
251{
252 struct bfin_sic *sic = hw_data (me);
253 bu32 mmr_off;
254 bu32 value;
255 bu16 *value16p;
256 bu32 *value32p;
257 void *valuep;
258
259 if (nr_bytes == 4)
260 value = dv_load_4 (source);
261 else
262 value = dv_load_2 (source);
263
264 mmr_off = addr - sic->base;
265 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
266 value16p = valuep;
267 value32p = valuep;
268
269 HW_TRACE_WRITE ();
270
271 /* XXX: Discard all SIC writes for now. */
272 switch (mmr_off)
273 {
274 case mmr_offset(swrst):
275 /* XXX: This should trigger a software reset ... */
276 break;
277 case mmr_offset(syscr):
278 /* XXX: what to do ... */
279 break;
280 case mmr_offset(bf537.imask):
281 bfin_sic_537_forward_interrupts (me, sic);
282 *value32p = value;
283 break;
284 case mmr_offset(bf537.iar0):
285 case mmr_offset(bf537.iar1):
286 case mmr_offset(bf537.iar2):
287 case mmr_offset(bf537.iar3):
288 case mmr_offset(bf537.iwr):
289 *value32p = value;
290 break;
291 case mmr_offset(bf537.isr):
292 /* ISR is read-only. */
293 break;
294 default:
295 /* XXX: Should discard other writes. */
296 ;
297 }
298
299 return nr_bytes;
300}
301
302static unsigned
303bfin_sic_537_io_read_buffer (struct hw *me, void *dest, int space,
304 address_word addr, unsigned nr_bytes)
305{
306 struct bfin_sic *sic = hw_data (me);
307 bu32 mmr_off;
308 bu16 *value16p;
309 bu32 *value32p;
310 void *valuep;
311
312 mmr_off = addr - sic->base;
313 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
314 value16p = valuep;
315 value32p = valuep;
316
317 HW_TRACE_READ ();
318
319 switch (mmr_off)
320 {
321 case mmr_offset(swrst):
322 case mmr_offset(syscr):
323 case mmr_offset(rvect):
324 dv_store_2 (dest, *value16p);
325 break;
326 case mmr_offset(bf537.imask):
327 case mmr_offset(bf537.iar0):
328 case mmr_offset(bf537.iar1):
329 case mmr_offset(bf537.iar2):
330 case mmr_offset(bf537.iar3):
331 case mmr_offset(bf537.isr):
332 case mmr_offset(bf537.iwr):
333 dv_store_4 (dest, *value32p);
334 break;
335 default:
336 if (nr_bytes == 2)
337 dv_store_2 (dest, 0);
338 else
339 dv_store_4 (dest, 0);
340 break;
341 }
342
343 return nr_bytes;
344}
345
346static void
347bfin_sic_54x_forward_interrupts (struct hw *me, struct bfin_sic *sic)
348{
349 bfin_sic_forward_interrupts (me, &sic->bf54x.isr0, &sic->bf54x.imask0, &sic->bf54x.iar0);
350 bfin_sic_forward_interrupts (me, &sic->bf54x.isr1, &sic->bf54x.imask1, &sic->bf54x.iar4);
351 bfin_sic_forward_interrupts (me, &sic->bf54x.isr2, &sic->bf54x.imask2, &sic->bf54x.iar8);
352}
353
354static unsigned
355bfin_sic_54x_io_write_buffer (struct hw *me, const void *source, int space,
356 address_word addr, unsigned nr_bytes)
357{
358 struct bfin_sic *sic = hw_data (me);
359 bu32 mmr_off;
360 bu32 value;
361 bu16 *value16p;
362 bu32 *value32p;
363 void *valuep;
364
365 if (nr_bytes == 4)
366 value = dv_load_4 (source);
367 else
368 value = dv_load_2 (source);
369
370 mmr_off = addr - sic->base;
371 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
372 value16p = valuep;
373 value32p = valuep;
374
375 HW_TRACE_WRITE ();
376
377 /* XXX: Discard all SIC writes for now. */
378 switch (mmr_off)
379 {
380 case mmr_offset(swrst):
381 /* XXX: This should trigger a software reset ... */
382 break;
383 case mmr_offset(syscr):
384 /* XXX: what to do ... */
385 break;
386 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
387 bfin_sic_54x_forward_interrupts (me, sic);
388 *value32p = value;
389 break;
390 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
391 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
392 *value32p = value;
393 break;
394 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
395 /* ISR is read-only. */
396 break;
397 default:
398 /* XXX: Should discard other writes. */
399 ;
400 }
401
402 return nr_bytes;
403}
404
405static unsigned
406bfin_sic_54x_io_read_buffer (struct hw *me, void *dest, int space,
407 address_word addr, unsigned nr_bytes)
408{
409 struct bfin_sic *sic = hw_data (me);
410 bu32 mmr_off;
411 bu16 *value16p;
412 bu32 *value32p;
413 void *valuep;
414
415 mmr_off = addr - sic->base;
416 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
417 value16p = valuep;
418 value32p = valuep;
419
420 HW_TRACE_READ ();
421
422 switch (mmr_off)
423 {
424 case mmr_offset(swrst):
425 case mmr_offset(syscr):
426 case mmr_offset(rvect):
427 dv_store_2 (dest, *value16p);
428 break;
429 case mmr_offset(bf54x.imask0) ... mmr_offset(bf54x.imask2):
430 case mmr_offset(bf54x.iar0) ... mmr_offset(bf54x.iar11):
431 case mmr_offset(bf54x.iwr0) ... mmr_offset(bf54x.iwr2):
432 case mmr_offset(bf54x.isr0) ... mmr_offset(bf54x.isr2):
433 dv_store_4 (dest, *value32p);
434 break;
435 default:
436 if (nr_bytes == 2)
437 dv_store_2 (dest, 0);
438 else
439 dv_store_4 (dest, 0);
440 break;
441 }
442
443 return nr_bytes;
444}
445
446static void
447bfin_sic_561_forward_interrupts (struct hw *me, struct bfin_sic *sic)
448{
449 bfin_sic_forward_interrupts (me, &sic->bf561.isr0, &sic->bf561.imask0, &sic->bf561.iar0);
450 bfin_sic_forward_interrupts (me, &sic->bf561.isr1, &sic->bf561.imask1, &sic->bf561.iar4);
451}
452
453static unsigned
454bfin_sic_561_io_write_buffer (struct hw *me, const void *source, int space,
455 address_word addr, unsigned nr_bytes)
456{
457 struct bfin_sic *sic = hw_data (me);
458 bu32 mmr_off;
459 bu32 value;
460 bu16 *value16p;
461 bu32 *value32p;
462 void *valuep;
463
464 if (nr_bytes == 4)
465 value = dv_load_4 (source);
466 else
467 value = dv_load_2 (source);
468
469 mmr_off = addr - sic->base;
470 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
471 value16p = valuep;
472 value32p = valuep;
473
474 HW_TRACE_WRITE ();
475
476 /* XXX: Discard all SIC writes for now. */
477 switch (mmr_off)
478 {
479 case mmr_offset(swrst):
480 /* XXX: This should trigger a software reset ... */
481 break;
482 case mmr_offset(syscr):
483 /* XXX: what to do ... */
484 break;
485 case mmr_offset(bf561.imask0):
486 case mmr_offset(bf561.imask1):
487 bfin_sic_561_forward_interrupts (me, sic);
488 *value32p = value;
489 break;
490 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
491 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
492 case mmr_offset(bf561.iwr0):
493 case mmr_offset(bf561.iwr1):
494 *value32p = value;
495 break;
496 case mmr_offset(bf561.isr0):
497 case mmr_offset(bf561.isr1):
498 /* ISR is read-only. */
499 break;
500 default:
501 /* XXX: Should discard other writes. */
502 ;
503 }
504
505 return nr_bytes;
506}
507
508static unsigned
509bfin_sic_561_io_read_buffer (struct hw *me, void *dest, int space,
510 address_word addr, unsigned nr_bytes)
511{
512 struct bfin_sic *sic = hw_data (me);
513 bu32 mmr_off;
514 bu16 *value16p;
515 bu32 *value32p;
516 void *valuep;
517
518 mmr_off = addr - sic->base;
519 valuep = (void *)((unsigned long)sic + mmr_base() + mmr_off);
520 value16p = valuep;
521 value32p = valuep;
522
523 HW_TRACE_READ ();
524
525 switch (mmr_off)
526 {
527 case mmr_offset(swrst):
528 case mmr_offset(syscr):
529 case mmr_offset(rvect):
530 dv_store_2 (dest, *value16p);
531 break;
532 case mmr_offset(bf561.imask0):
533 case mmr_offset(bf561.imask1):
534 case mmr_offset(bf561.iar0) ... mmr_offset(bf561.iar3):
535 case mmr_offset(bf561.iar4) ... mmr_offset(bf561.iar7):
536 case mmr_offset(bf561.iwr0):
537 case mmr_offset(bf561.iwr1):
538 case mmr_offset(bf561.isr0):
539 case mmr_offset(bf561.isr1):
540 dv_store_4 (dest, *value32p);
541 break;
542 default:
543 if (nr_bytes == 2)
544 dv_store_2 (dest, 0);
545 else
546 dv_store_4 (dest, 0);
547 break;
548 }
549
550 return nr_bytes;
551}
552
082e1c4a
MF
553/* Give each SIC its own base to make it easier to extract the pin at
554 runtime. The pin is used as its bit position in the SIC MMRs. */
555#define ENC(sic, pin) (((sic) << 8) + (pin))
556#define DEC_PIN(pin) ((pin) % 0x100)
557#define DEC_SIC(pin) ((pin) >> 8)
558
559/* It would be nice to declare just one set of input_ports, and then
560 have the device tree instantiate multiple SICs, but the MMR layout
561 on the BF54x/BF561 makes this pretty hard to pull off since their
562 regs are interwoven in the address space. */
563
ef016f83
MF
564#define BFIN_SIC_TO_CEC_PORTS \
565 { "ivg7", IVG7, 0, output_port, }, \
566 { "ivg8", IVG8, 0, output_port, }, \
567 { "ivg9", IVG9, 0, output_port, }, \
568 { "ivg10", IVG10, 0, output_port, }, \
569 { "ivg11", IVG11, 0, output_port, }, \
570 { "ivg12", IVG12, 0, output_port, }, \
571 { "ivg13", IVG13, 0, output_port, }, \
572 { "ivg14", IVG14, 0, output_port, }, \
573 { "ivg15", IVG15, 0, output_port, },
574
082e1c4a
MF
575#define SIC_PORTS(n) \
576 { "int0@"#n, ENC(n, 0), 0, input_port, }, \
577 { "int1@"#n, ENC(n, 1), 0, input_port, }, \
578 { "int2@"#n, ENC(n, 2), 0, input_port, }, \
579 { "int3@"#n, ENC(n, 3), 0, input_port, }, \
580 { "int4@"#n, ENC(n, 4), 0, input_port, }, \
581 { "int5@"#n, ENC(n, 5), 0, input_port, }, \
582 { "int6@"#n, ENC(n, 6), 0, input_port, }, \
583 { "int7@"#n, ENC(n, 7), 0, input_port, }, \
584 { "int8@"#n, ENC(n, 8), 0, input_port, }, \
585 { "int9@"#n, ENC(n, 9), 0, input_port, }, \
586 { "int10@"#n, ENC(n, 10), 0, input_port, }, \
587 { "int11@"#n, ENC(n, 11), 0, input_port, }, \
588 { "int12@"#n, ENC(n, 12), 0, input_port, }, \
589 { "int13@"#n, ENC(n, 13), 0, input_port, }, \
590 { "int14@"#n, ENC(n, 14), 0, input_port, }, \
591 { "int15@"#n, ENC(n, 15), 0, input_port, }, \
592 { "int16@"#n, ENC(n, 16), 0, input_port, }, \
593 { "int17@"#n, ENC(n, 17), 0, input_port, }, \
594 { "int18@"#n, ENC(n, 18), 0, input_port, }, \
595 { "int19@"#n, ENC(n, 19), 0, input_port, }, \
596 { "int20@"#n, ENC(n, 20), 0, input_port, }, \
597 { "int21@"#n, ENC(n, 21), 0, input_port, }, \
598 { "int22@"#n, ENC(n, 22), 0, input_port, }, \
599 { "int23@"#n, ENC(n, 23), 0, input_port, }, \
600 { "int24@"#n, ENC(n, 24), 0, input_port, }, \
601 { "int25@"#n, ENC(n, 25), 0, input_port, }, \
602 { "int26@"#n, ENC(n, 26), 0, input_port, }, \
603 { "int27@"#n, ENC(n, 27), 0, input_port, }, \
604 { "int28@"#n, ENC(n, 28), 0, input_port, }, \
605 { "int29@"#n, ENC(n, 29), 0, input_port, }, \
606 { "int30@"#n, ENC(n, 30), 0, input_port, }, \
607 { "int31@"#n, ENC(n, 31), 0, input_port, },
608
609static const struct hw_port_descriptor bfin_sic1_ports[] =
610{
611 BFIN_SIC_TO_CEC_PORTS
612 SIC_PORTS(0)
613 { NULL, 0, 0, 0, },
614};
e4a861d1 615
082e1c4a 616static const struct hw_port_descriptor bfin_sic2_ports[] =
990d19fd 617{
ef016f83 618 BFIN_SIC_TO_CEC_PORTS
082e1c4a
MF
619 SIC_PORTS(0)
620 SIC_PORTS(1)
ef016f83
MF
621 { NULL, 0, 0, 0, },
622};
623
082e1c4a 624static const struct hw_port_descriptor bfin_sic3_ports[] =
990d19fd 625{
ef016f83 626 BFIN_SIC_TO_CEC_PORTS
082e1c4a
MF
627 SIC_PORTS(0)
628 SIC_PORTS(1)
629 SIC_PORTS(2)
ef016f83
MF
630 { NULL, 0, 0, 0, },
631};
632
082e1c4a 633static const struct hw_port_descriptor bfin_sic_561_ports[] =
990d19fd 634{
082e1c4a
MF
635 { "sup_irq@0", 0, 0, output_port, },
636 { "sup_irq@1", 1, 0, output_port, },
ef016f83 637 BFIN_SIC_TO_CEC_PORTS
082e1c4a
MF
638 SIC_PORTS(0)
639 SIC_PORTS(1)
ef016f83
MF
640 { NULL, 0, 0, 0, },
641};
642
e10d6db3
MF
643static void
644bfin_sic_port_event (struct hw *me, bu32 *isr, bu32 bit, int level)
645{
646 if (level)
647 *isr |= bit;
648 else
649 *isr &= ~bit;
650}
651
ef016f83
MF
652static void
653bfin_sic_52x_port_event (struct hw *me, int my_port, struct hw *source,
654 int source_port, int level)
655{
656 struct bfin_sic *sic = hw_data (me);
e4a861d1 657 bu32 idx = DEC_SIC (my_port);
a31d4fd9
MF
658 bu32 pin = DEC_PIN (my_port);
659 bu32 bit = 1 << pin;
660
e10d6db3
MF
661 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
662 level, my_port, idx, pin));
ef016f83
MF
663
664 /* SIC only exists to forward interrupts from the system to the CEC. */
665 switch (idx)
666 {
e10d6db3
MF
667 case 0: bfin_sic_port_event (me, &sic->bf52x.isr0, bit, level); break;
668 case 1: bfin_sic_port_event (me, &sic->bf52x.isr1, bit, level); break;
ef016f83
MF
669 }
670
671 /* XXX: Handle SIC wakeup source ?
672 if (sic->bf52x.iwr0 & bit)
673 What to do ?;
674 if (sic->bf52x.iwr1 & bit)
675 What to do ?;
676 */
677
678 bfin_sic_52x_forward_interrupts (me, sic);
679}
680
ef016f83
MF
681static void
682bfin_sic_537_port_event (struct hw *me, int my_port, struct hw *source,
683 int source_port, int level)
684{
685 struct bfin_sic *sic = hw_data (me);
a31d4fd9
MF
686 bu32 idx = DEC_SIC (my_port);
687 bu32 pin = DEC_PIN (my_port);
688 bu32 bit = 1 << pin;
689
e10d6db3
MF
690 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
691 level, my_port, idx, pin));
ef016f83
MF
692
693 /* SIC only exists to forward interrupts from the system to the CEC. */
e10d6db3 694 bfin_sic_port_event (me, &sic->bf537.isr, bit, level);
ef016f83
MF
695
696 /* XXX: Handle SIC wakeup source ?
697 if (sic->bf537.iwr & bit)
698 What to do ?;
699 */
700
701 bfin_sic_537_forward_interrupts (me, sic);
702}
703
ef016f83
MF
704static void
705bfin_sic_54x_port_event (struct hw *me, int my_port, struct hw *source,
706 int source_port, int level)
707{
708 struct bfin_sic *sic = hw_data (me);
e4a861d1 709 bu32 idx = DEC_SIC (my_port);
a31d4fd9
MF
710 bu32 pin = DEC_PIN (my_port);
711 bu32 bit = 1 << pin;
712
e10d6db3
MF
713 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
714 level, my_port, idx, pin));
ef016f83
MF
715
716 /* SIC only exists to forward interrupts from the system to the CEC. */
717 switch (idx)
718 {
e10d6db3
MF
719 case 0: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
720 case 1: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
721 case 2: bfin_sic_port_event (me, &sic->bf54x.isr0, bit, level); break;
ef016f83
MF
722 }
723
724 /* XXX: Handle SIC wakeup source ?
725 if (sic->bf54x.iwr0 & bit)
726 What to do ?;
727 if (sic->bf54x.iwr1 & bit)
728 What to do ?;
729 if (sic->bf54x.iwr2 & bit)
730 What to do ?;
731 */
732
733 bfin_sic_54x_forward_interrupts (me, sic);
734}
735
ef016f83
MF
736static void
737bfin_sic_561_port_event (struct hw *me, int my_port, struct hw *source,
738 int source_port, int level)
739{
740 struct bfin_sic *sic = hw_data (me);
e4a861d1 741 bu32 idx = DEC_SIC (my_port);
a31d4fd9
MF
742 bu32 pin = DEC_PIN (my_port);
743 bu32 bit = 1 << pin;
744
e10d6db3
MF
745 HW_TRACE ((me, "processing level %i from port %i (SIC %u pin %u)",
746 level, my_port, idx, pin));
ef016f83
MF
747
748 /* SIC only exists to forward interrupts from the system to the CEC. */
749 switch (idx)
750 {
e10d6db3
MF
751 case 0: bfin_sic_port_event (me, &sic->bf561.isr0, bit, level); break;
752 case 1: bfin_sic_port_event (me, &sic->bf561.isr1, bit, level); break;
ef016f83
MF
753 }
754
755 /* XXX: Handle SIC wakeup source ?
756 if (sic->bf561.iwr0 & bit)
757 What to do ?;
758 if (sic->bf561.iwr1 & bit)
759 What to do ?;
760 */
761
762 bfin_sic_561_forward_interrupts (me, sic);
763}
764
ef016f83
MF
765static void
766attach_bfin_sic_regs (struct hw *me, struct bfin_sic *sic)
767{
768 address_word attach_address;
769 int attach_space;
770 unsigned attach_size;
771 reg_property_spec reg;
772
773 if (hw_find_property (me, "reg") == NULL)
774 hw_abort (me, "Missing \"reg\" property");
775
776 if (!hw_find_reg_array_property (me, "reg", 0, &reg))
777 hw_abort (me, "\"reg\" property must contain three addr/size entries");
778
779 hw_unit_address_to_attach_address (hw_parent (me),
780 &reg.address,
781 &attach_space, &attach_address, me);
782 hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
783
784 if (attach_size != BFIN_MMR_SIC_SIZE)
785 hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_SIC_SIZE);
786
787 hw_attach_address (hw_parent (me),
788 0, attach_space, attach_address, attach_size, me);
789
790 sic->base = attach_address;
791}
792
793static void
794bfin_sic_finish (struct hw *me)
795{
796 struct bfin_sic *sic;
797
798 sic = HW_ZALLOC (me, struct bfin_sic);
799
800 set_hw_data (me, sic);
801 attach_bfin_sic_regs (me, sic);
802
803 switch (hw_find_integer_property (me, "type"))
804 {
805 case 500 ... 509:
806 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
807 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
082e1c4a 808 set_hw_ports (me, bfin_sic2_ports);
ef016f83
MF
809 set_hw_port_event (me, bfin_sic_52x_port_event);
810 mmr_names = bf52x_mmr_names;
811
812 /* Initialize the SIC. */
813 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
814 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
815 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
816 sic->bf52x.iar0 = 0x00000000;
817 sic->bf52x.iar1 = 0x22111000;
818 sic->bf52x.iar2 = 0x33332222;
819 sic->bf52x.iar3 = 0x44444433;
820 sic->bf52x.iar4 = 0x55555555;
821 sic->bf52x.iar5 = 0x06666655;
822 sic->bf52x.iar6 = 0x33333003;
823 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
824 break;
825 case 510 ... 519:
826 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
827 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
082e1c4a 828 set_hw_ports (me, bfin_sic2_ports);
ef016f83
MF
829 set_hw_port_event (me, bfin_sic_52x_port_event);
830 mmr_names = bf52x_mmr_names;
831
832 /* Initialize the SIC. */
833 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
834 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
835 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
836 sic->bf52x.iar0 = 0x00000000;
837 sic->bf52x.iar1 = 0x11000000;
838 sic->bf52x.iar2 = 0x33332222;
839 sic->bf52x.iar3 = 0x44444433;
840 sic->bf52x.iar4 = 0x55555555;
841 sic->bf52x.iar5 = 0x06666655;
842 sic->bf52x.iar6 = 0x33333000;
843 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
844 break;
845 case 522 ... 527:
846 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
847 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
082e1c4a 848 set_hw_ports (me, bfin_sic2_ports);
ef016f83
MF
849 set_hw_port_event (me, bfin_sic_52x_port_event);
850 mmr_names = bf52x_mmr_names;
851
852 /* Initialize the SIC. */
853 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
854 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
855 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
856 sic->bf52x.iar0 = 0x00000000;
857 sic->bf52x.iar1 = 0x11000000;
858 sic->bf52x.iar2 = 0x33332222;
859 sic->bf52x.iar3 = 0x44444433;
860 sic->bf52x.iar4 = 0x55555555;
861 sic->bf52x.iar5 = 0x06666655;
862 sic->bf52x.iar6 = 0x33333000;
863 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
864 break;
865 case 531 ... 533:
866 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
867 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
082e1c4a 868 set_hw_ports (me, bfin_sic1_ports);
e4a861d1 869 set_hw_port_event (me, bfin_sic_537_port_event);
ef016f83
MF
870 mmr_names = bf537_mmr_names;
871
872 /* Initialize the SIC. */
873 sic->bf537.imask = 0;
874 sic->bf537.isr = 0;
875 sic->bf537.iwr = 0xFFFFFFFF;
876 sic->bf537.iar0 = 0x10000000;
877 sic->bf537.iar1 = 0x33322221;
878 sic->bf537.iar2 = 0x66655444;
879 sic->bf537.iar3 = 0; /* XXX: fix this */
880 break;
881 case 534:
882 case 536:
883 case 537:
884 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
885 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
082e1c4a 886 set_hw_ports (me, bfin_sic1_ports);
ef016f83
MF
887 set_hw_port_event (me, bfin_sic_537_port_event);
888 mmr_names = bf537_mmr_names;
889
890 /* Initialize the SIC. */
891 sic->bf537.imask = 0;
892 sic->bf537.isr = 0;
893 sic->bf537.iwr = 0xFFFFFFFF;
894 sic->bf537.iar0 = 0x22211000;
895 sic->bf537.iar1 = 0x43333332;
896 sic->bf537.iar2 = 0x55555444;
897 sic->bf537.iar3 = 0x66655555;
898 break;
899 case 538 ... 539:
900 set_hw_io_read_buffer (me, bfin_sic_52x_io_read_buffer);
901 set_hw_io_write_buffer (me, bfin_sic_52x_io_write_buffer);
082e1c4a 902 set_hw_ports (me, bfin_sic2_ports);
ef016f83
MF
903 set_hw_port_event (me, bfin_sic_52x_port_event);
904 mmr_names = bf52x_mmr_names;
905
906 /* Initialize the SIC. */
907 sic->bf52x.imask0 = sic->bf52x.imask1 = 0;
908 sic->bf52x.isr0 = sic->bf52x.isr1 = 0;
909 sic->bf52x.iwr0 = sic->bf52x.iwr1 = 0xFFFFFFFF;
910 sic->bf52x.iar0 = 0x10000000;
911 sic->bf52x.iar1 = 0x33322221;
912 sic->bf52x.iar2 = 0x66655444;
913 sic->bf52x.iar3 = 0x00000000;
914 sic->bf52x.iar4 = 0x32222220;
915 sic->bf52x.iar5 = 0x44433333;
916 sic->bf52x.iar6 = 0x00444664;
917 sic->bf52x.iar7 = 0x00000000; /* XXX: Find and fix */
918 break;
919 case 540 ... 549:
920 set_hw_io_read_buffer (me, bfin_sic_54x_io_read_buffer);
921 set_hw_io_write_buffer (me, bfin_sic_54x_io_write_buffer);
082e1c4a 922 set_hw_ports (me, bfin_sic3_ports);
ef016f83
MF
923 set_hw_port_event (me, bfin_sic_54x_port_event);
924 mmr_names = bf54x_mmr_names;
925
926 /* Initialize the SIC. */
927 sic->bf54x.imask0 = sic->bf54x.imask1 = sic->bf54x.imask2 = 0;
928 sic->bf54x.isr0 = sic->bf54x.isr1 = sic->bf54x.isr2 = 0;
8d72c970 929 sic->bf54x.iwr0 = sic->bf54x.iwr1 = sic->bf54x.iwr2 = 0xFFFFFFFF;
ef016f83
MF
930 sic->bf54x.iar0 = 0x10000000;
931 sic->bf54x.iar1 = 0x33322221;
932 sic->bf54x.iar2 = 0x66655444;
933 sic->bf54x.iar3 = 0x00000000;
934 sic->bf54x.iar4 = 0x32222220;
935 sic->bf54x.iar5 = 0x44433333;
936 sic->bf54x.iar6 = 0x00444664;
937 sic->bf54x.iar7 = 0x00000000;
938 sic->bf54x.iar8 = 0x44111111;
939 sic->bf54x.iar9 = 0x44444444;
940 sic->bf54x.iar10 = 0x44444444;
941 sic->bf54x.iar11 = 0x55444444;
942 break;
943 case 561:
944 set_hw_io_read_buffer (me, bfin_sic_561_io_read_buffer);
945 set_hw_io_write_buffer (me, bfin_sic_561_io_write_buffer);
946 set_hw_ports (me, bfin_sic_561_ports);
947 set_hw_port_event (me, bfin_sic_561_port_event);
948 mmr_names = bf561_mmr_names;
949
950 /* Initialize the SIC. */
951 sic->bf561.imask0 = sic->bf561.imask1 = 0;
952 sic->bf561.isr0 = sic->bf561.isr1 = 0;
953 sic->bf561.iwr0 = sic->bf561.iwr1 = 0xFFFFFFFF;
954 sic->bf561.iar0 = 0x00000000;
955 sic->bf561.iar1 = 0x11111000;
956 sic->bf561.iar2 = 0x21111111;
957 sic->bf561.iar3 = 0x22222222;
958 sic->bf561.iar4 = 0x33333222;
959 sic->bf561.iar5 = 0x43333333;
960 sic->bf561.iar6 = 0x21144444;
961 sic->bf561.iar7 = 0x00006552;
962 break;
963 case 590 ... 599:
964 set_hw_io_read_buffer (me, bfin_sic_537_io_read_buffer);
965 set_hw_io_write_buffer (me, bfin_sic_537_io_write_buffer);
082e1c4a 966 set_hw_ports (me, bfin_sic1_ports);
e4a861d1 967 set_hw_port_event (me, bfin_sic_537_port_event);
ef016f83
MF
968 mmr_names = bf537_mmr_names;
969
970 /* Initialize the SIC. */
971 sic->bf537.imask = 0;
972 sic->bf537.isr = 0;
973 sic->bf537.iwr = 0xFFFFFFFF;
974 sic->bf537.iar0 = 0x00000000;
975 sic->bf537.iar1 = 0x33322221;
976 sic->bf537.iar2 = 0x55444443;
977 sic->bf537.iar3 = 0x66600005;
978 break;
979 default:
980 hw_abort (me, "no support for SIC on this Blackfin model yet");
981 }
982}
983
81d126c3
MF
984const struct hw_descriptor dv_bfin_sic_descriptor[] =
985{
ef016f83
MF
986 {"bfin_sic", bfin_sic_finish,},
987 {NULL, NULL},
988};