Revision 80f515e6 hw/sh7750.c
b/hw/sh7750.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* SH7750 device |
3 | 3 |
* |
4 |
* Copyright (c) 2007 Magnus Damm |
|
4 | 5 |
* Copyright (c) 2005 Samuel Tardieu |
5 | 6 |
* |
6 | 7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
... | ... | |
26 | 27 |
#include "vl.h" |
27 | 28 |
#include "sh7750_regs.h" |
28 | 29 |
#include "sh7750_regnames.h" |
30 |
#include "sh_intc.h" |
|
29 | 31 |
|
30 | 32 |
#define NB_DEVICES 4 |
31 | 33 |
|
... | ... | |
53 | 55 |
sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */ |
54 | 56 |
|
55 | 57 |
uint16_t icr; |
56 |
uint16_t ipra; |
|
57 |
uint16_t iprb; |
|
58 |
uint16_t iprc; |
|
59 |
uint16_t iprd; |
|
60 |
uint32_t intpri00; |
|
61 |
uint32_t intmsk00; |
|
62 | 58 |
/* Cache */ |
63 | 59 |
uint32_t ccr; |
64 | 60 |
|
61 |
struct intc_desc intc; |
|
65 | 62 |
} SH7750State; |
66 | 63 |
|
67 | 64 |
|
... | ... | |
219 | 216 |
return portb_lines(s); |
220 | 217 |
case 0x1fd00000: |
221 | 218 |
return s->icr; |
222 |
case 0x1fd00004: |
|
223 |
return s->ipra; |
|
224 |
case 0x1fd00008: |
|
225 |
return s->iprb; |
|
226 |
case 0x1fd0000c: |
|
227 |
return s->iprc; |
|
228 |
case 0x1fd00010: |
|
229 |
return s->iprd; |
|
230 | 219 |
default: |
231 | 220 |
error_access("word read", addr); |
232 | 221 |
assert(0); |
... | ... | |
262 | 251 |
return 0x00110000; /* Minimum caches */ |
263 | 252 |
case 0x1f000044: /* Processor version PRR */ |
264 | 253 |
return 0x00000100; /* SH7750R */ |
265 |
case 0x1e080000: |
|
266 |
return s->intpri00; |
|
267 |
case 0x1e080020: |
|
268 |
return 0; |
|
269 |
case 0x1e080040: |
|
270 |
return s->intmsk00; |
|
271 |
case 0x1e080060: |
|
272 |
return 0; |
|
273 | 254 |
default: |
274 | 255 |
error_access("long read", addr); |
275 | 256 |
assert(0); |
... | ... | |
331 | 312 |
case 0x1fd00000: |
332 | 313 |
s->icr = mem_value; |
333 | 314 |
return; |
334 |
case 0x1fd00004: |
|
335 |
s->ipra = mem_value; |
|
336 |
return; |
|
337 |
case 0x1fd00008: |
|
338 |
s->iprb = mem_value; |
|
339 |
return; |
|
340 |
case 0x1fd0000c: |
|
341 |
s->iprc = mem_value; |
|
342 |
return; |
|
343 |
case 0x1fd00010: |
|
344 |
s->iprd = mem_value; |
|
345 |
return; |
|
346 | 315 |
default: |
347 | 316 |
error_access("word write", addr); |
348 | 317 |
assert(0); |
... | ... | |
407 | 376 |
case SH7750_CCR_A7: |
408 | 377 |
s->ccr = mem_value; |
409 | 378 |
return; |
410 |
case 0x1e080000: |
|
411 |
s->intpri00 = mem_value; |
|
412 |
return; |
|
413 |
case 0x1e080020: |
|
414 |
return; |
|
415 |
case 0x1e080040: |
|
416 |
s->intmsk00 = mem_value; |
|
417 |
return; |
|
418 |
case 0x1e080060: |
|
419 |
return; |
|
420 | 379 |
default: |
421 | 380 |
error_access("long write", addr); |
422 | 381 |
assert(0); |
... | ... | |
435 | 394 |
sh7750_mem_writel |
436 | 395 |
}; |
437 | 396 |
|
397 |
/* sh775x interrupt controller tables for sh_intc.c |
|
398 |
* stolen from linux/arch/sh/kernel/cpu/sh4/setup-sh7750.c |
|
399 |
*/ |
|
400 |
|
|
401 |
enum { |
|
402 |
UNUSED = 0, |
|
403 |
|
|
404 |
/* interrupt sources */ |
|
405 |
IRL0, IRL1, IRL2, IRL3, /* only IRLM mode supported */ |
|
406 |
HUDI, GPIOI, |
|
407 |
DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, DMAC_DMTE3, |
|
408 |
DMAC_DMTE4, DMAC_DMTE5, DMAC_DMTE6, DMAC_DMTE7, |
|
409 |
DMAC_DMAE, |
|
410 |
PCIC0_PCISERR, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON, |
|
411 |
PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3, |
|
412 |
TMU3, TMU4, TMU0, TMU1, TMU2_TUNI, TMU2_TICPI, |
|
413 |
RTC_ATI, RTC_PRI, RTC_CUI, |
|
414 |
SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI, |
|
415 |
SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI, |
|
416 |
WDT, |
|
417 |
REF_RCMI, REF_ROVI, |
|
418 |
|
|
419 |
/* interrupt groups */ |
|
420 |
DMAC, PCIC1, TMU2, RTC, SCI1, SCIF, REF, |
|
421 |
|
|
422 |
NR_SOURCES, |
|
423 |
}; |
|
424 |
|
|
425 |
static struct intc_vect vectors[] = { |
|
426 |
INTC_VECT(HUDI, 0x600), INTC_VECT(GPIOI, 0x620), |
|
427 |
INTC_VECT(TMU0, 0x400), INTC_VECT(TMU1, 0x420), |
|
428 |
INTC_VECT(TMU2_TUNI, 0x440), INTC_VECT(TMU2_TICPI, 0x460), |
|
429 |
INTC_VECT(RTC_ATI, 0x480), INTC_VECT(RTC_PRI, 0x4a0), |
|
430 |
INTC_VECT(RTC_CUI, 0x4c0), |
|
431 |
INTC_VECT(SCI1_ERI, 0x4e0), INTC_VECT(SCI1_RXI, 0x500), |
|
432 |
INTC_VECT(SCI1_TXI, 0x520), INTC_VECT(SCI1_TEI, 0x540), |
|
433 |
INTC_VECT(SCIF_ERI, 0x700), INTC_VECT(SCIF_RXI, 0x720), |
|
434 |
INTC_VECT(SCIF_BRI, 0x740), INTC_VECT(SCIF_TXI, 0x760), |
|
435 |
INTC_VECT(WDT, 0x560), |
|
436 |
INTC_VECT(REF_RCMI, 0x580), INTC_VECT(REF_ROVI, 0x5a0), |
|
437 |
}; |
|
438 |
|
|
439 |
static struct intc_group groups[] = { |
|
440 |
INTC_GROUP(TMU2, TMU2_TUNI, TMU2_TICPI), |
|
441 |
INTC_GROUP(RTC, RTC_ATI, RTC_PRI, RTC_CUI), |
|
442 |
INTC_GROUP(SCI1, SCI1_ERI, SCI1_RXI, SCI1_TXI, SCI1_TEI), |
|
443 |
INTC_GROUP(SCIF, SCIF_ERI, SCIF_RXI, SCIF_BRI, SCIF_TXI), |
|
444 |
INTC_GROUP(REF, REF_RCMI, REF_ROVI), |
|
445 |
}; |
|
446 |
|
|
447 |
static struct intc_prio_reg prio_registers[] = { |
|
448 |
{ 0xffd00004, 0, 16, 4, /* IPRA */ { TMU0, TMU1, TMU2, RTC } }, |
|
449 |
{ 0xffd00008, 0, 16, 4, /* IPRB */ { WDT, REF, SCI1, 0 } }, |
|
450 |
{ 0xffd0000c, 0, 16, 4, /* IPRC */ { GPIOI, DMAC, SCIF, HUDI } }, |
|
451 |
{ 0xffd00010, 0, 16, 4, /* IPRD */ { IRL0, IRL1, IRL2, IRL3 } }, |
|
452 |
{ 0xfe080000, 0, 32, 4, /* INTPRI00 */ { 0, 0, 0, 0, |
|
453 |
TMU4, TMU3, |
|
454 |
PCIC1, PCIC0_PCISERR } }, |
|
455 |
}; |
|
456 |
|
|
457 |
/* SH7750, SH7750S, SH7751 and SH7091 all have 4-channel DMA controllers */ |
|
458 |
|
|
459 |
static struct intc_vect vectors_dma4[] = { |
|
460 |
INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660), |
|
461 |
INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0), |
|
462 |
INTC_VECT(DMAC_DMAE, 0x6c0), |
|
463 |
}; |
|
464 |
|
|
465 |
static struct intc_group groups_dma4[] = { |
|
466 |
INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, |
|
467 |
DMAC_DMTE3, DMAC_DMAE), |
|
468 |
}; |
|
469 |
|
|
470 |
/* SH7750R and SH7751R both have 8-channel DMA controllers */ |
|
471 |
|
|
472 |
static struct intc_vect vectors_dma8[] = { |
|
473 |
INTC_VECT(DMAC_DMTE0, 0x640), INTC_VECT(DMAC_DMTE1, 0x660), |
|
474 |
INTC_VECT(DMAC_DMTE2, 0x680), INTC_VECT(DMAC_DMTE3, 0x6a0), |
|
475 |
INTC_VECT(DMAC_DMTE4, 0x780), INTC_VECT(DMAC_DMTE5, 0x7a0), |
|
476 |
INTC_VECT(DMAC_DMTE6, 0x7c0), INTC_VECT(DMAC_DMTE7, 0x7e0), |
|
477 |
INTC_VECT(DMAC_DMAE, 0x6c0), |
|
478 |
}; |
|
479 |
|
|
480 |
static struct intc_group groups_dma8[] = { |
|
481 |
INTC_GROUP(DMAC, DMAC_DMTE0, DMAC_DMTE1, DMAC_DMTE2, |
|
482 |
DMAC_DMTE3, DMAC_DMTE4, DMAC_DMTE5, |
|
483 |
DMAC_DMTE6, DMAC_DMTE7, DMAC_DMAE), |
|
484 |
}; |
|
485 |
|
|
486 |
/* SH7750R, SH7751 and SH7751R all have two extra timer channels */ |
|
487 |
|
|
488 |
static struct intc_vect vectors_tmu34[] = { |
|
489 |
INTC_VECT(TMU3, 0xb00), INTC_VECT(TMU4, 0xb80), |
|
490 |
}; |
|
491 |
|
|
492 |
static struct intc_mask_reg mask_registers[] = { |
|
493 |
{ 0xfe080040, 0xfe080060, 32, /* INTMSK00 / INTMSKCLR00 */ |
|
494 |
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
|
495 |
0, 0, 0, 0, 0, 0, TMU4, TMU3, |
|
496 |
PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON, |
|
497 |
PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, |
|
498 |
PCIC1_PCIDMA3, PCIC0_PCISERR } }, |
|
499 |
}; |
|
500 |
|
|
501 |
/* SH7750S, SH7750R, SH7751 and SH7751R all have IRLM priority registers */ |
|
502 |
|
|
503 |
static struct intc_vect vectors_irlm[] = { |
|
504 |
INTC_VECT(IRL0, 0x240), INTC_VECT(IRL1, 0x2a0), |
|
505 |
INTC_VECT(IRL2, 0x300), INTC_VECT(IRL3, 0x360), |
|
506 |
}; |
|
507 |
|
|
508 |
/* SH7751 and SH7751R both have PCI */ |
|
509 |
|
|
510 |
static struct intc_vect vectors_pci[] = { |
|
511 |
INTC_VECT(PCIC0_PCISERR, 0xa00), INTC_VECT(PCIC1_PCIERR, 0xae0), |
|
512 |
INTC_VECT(PCIC1_PCIPWDWN, 0xac0), INTC_VECT(PCIC1_PCIPWON, 0xaa0), |
|
513 |
INTC_VECT(PCIC1_PCIDMA0, 0xa80), INTC_VECT(PCIC1_PCIDMA1, 0xa60), |
|
514 |
INTC_VECT(PCIC1_PCIDMA2, 0xa40), INTC_VECT(PCIC1_PCIDMA3, 0xa20), |
|
515 |
}; |
|
516 |
|
|
517 |
static struct intc_group groups_pci[] = { |
|
518 |
INTC_GROUP(PCIC1, PCIC1_PCIERR, PCIC1_PCIPWDWN, PCIC1_PCIPWON, |
|
519 |
PCIC1_PCIDMA0, PCIC1_PCIDMA1, PCIC1_PCIDMA2, PCIC1_PCIDMA3), |
|
520 |
}; |
|
521 |
|
|
522 |
#define SH_CPU_SH7750 (1 << 0) |
|
523 |
#define SH_CPU_SH7750S (1 << 1) |
|
524 |
#define SH_CPU_SH7750R (1 << 2) |
|
525 |
#define SH_CPU_SH7751 (1 << 3) |
|
526 |
#define SH_CPU_SH7751R (1 << 4) |
|
527 |
#define SH_CPU_SH7750_ALL (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7750R) |
|
528 |
#define SH_CPU_SH7751_ALL (SH_CPU_SH7751 | SH_CPU_SH7751R) |
|
529 |
|
|
438 | 530 |
SH7750State *sh7750_init(CPUSH4State * cpu) |
439 | 531 |
{ |
440 | 532 |
SH7750State *s; |
441 | 533 |
int sh7750_io_memory; |
534 |
int cpu_model = SH_CPU_SH7751R; /* for now */ |
|
442 | 535 |
|
443 | 536 |
s = qemu_mallocz(sizeof(SH7750State)); |
444 | 537 |
s->cpu = cpu; |
... | ... | |
448 | 541 |
sh7750_mem_write, s); |
449 | 542 |
cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory); |
450 | 543 |
|
544 |
sh_intc_init(&s->intc, NR_SOURCES, |
|
545 |
_INTC_ARRAY(mask_registers), |
|
546 |
_INTC_ARRAY(prio_registers)); |
|
547 |
|
|
548 |
sh_intc_register_sources(&s->intc, |
|
549 |
_INTC_ARRAY(vectors), |
|
550 |
_INTC_ARRAY(groups)); |
|
551 |
|
|
451 | 552 |
sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]); |
452 | 553 |
sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF, |
453 | 554 |
s->periph_freq, serial_hds[1]); |
... | ... | |
455 | 556 |
tmu012_init(0x1fd80000, |
456 | 557 |
TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, |
457 | 558 |
s->periph_freq); |
458 |
tmu012_init(0x1e100000, 0, s->periph_freq); |
|
559 |
|
|
560 |
|
|
561 |
if (cpu_model & (SH_CPU_SH7750 | SH_CPU_SH7750S | SH_CPU_SH7751)) { |
|
562 |
sh_intc_register_sources(&s->intc, |
|
563 |
_INTC_ARRAY(vectors_dma4), |
|
564 |
_INTC_ARRAY(groups_dma4)); |
|
565 |
} |
|
566 |
|
|
567 |
if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751R)) { |
|
568 |
sh_intc_register_sources(&s->intc, |
|
569 |
_INTC_ARRAY(vectors_dma8), |
|
570 |
_INTC_ARRAY(groups_dma8)); |
|
571 |
} |
|
572 |
|
|
573 |
if (cpu_model & (SH_CPU_SH7750R | SH_CPU_SH7751 | SH_CPU_SH7751R)) { |
|
574 |
sh_intc_register_sources(&s->intc, |
|
575 |
_INTC_ARRAY(vectors_tmu34), |
|
576 |
_INTC_ARRAY(NULL)); |
|
577 |
tmu012_init(0x1e100000, 0, s->periph_freq); |
|
578 |
} |
|
579 |
|
|
580 |
if (cpu_model & (SH_CPU_SH7751_ALL)) { |
|
581 |
sh_intc_register_sources(&s->intc, |
|
582 |
_INTC_ARRAY(vectors_pci), |
|
583 |
_INTC_ARRAY(groups_pci)); |
|
584 |
} |
|
585 |
|
|
586 |
if (cpu_model & (SH_CPU_SH7750S | SH_CPU_SH7750R | SH_CPU_SH7751_ALL)) { |
|
587 |
sh_intc_register_sources(&s->intc, |
|
588 |
_INTC_ARRAY(vectors_irlm), |
|
589 |
_INTC_ARRAY(NULL)); |
|
590 |
} |
|
591 |
|
|
459 | 592 |
return s; |
460 | 593 |
} |
Also available in: Unified diff