Commit 80f515e63688f43b7800027c233ec7139cf3375b
1 parent
30d6eaca
sh775x interrupt controller by Magnus Damm.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3327 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
631 additions
and
91 deletions
Makefile.target
| @@ -484,7 +484,7 @@ CPPFLAGS += -DHAS_AUDIO | @@ -484,7 +484,7 @@ CPPFLAGS += -DHAS_AUDIO | ||
| 484 | endif | 484 | endif |
| 485 | ifeq ($(TARGET_BASE_ARCH), sh4) | 485 | ifeq ($(TARGET_BASE_ARCH), sh4) |
| 486 | VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o | 486 | VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o |
| 487 | -VL_OBJS+= sh_timer.o ptimer.o sh_serial.o | 487 | +VL_OBJS+= sh_timer.o ptimer.o sh_serial.o sh_intc.o |
| 488 | endif | 488 | endif |
| 489 | ifeq ($(TARGET_BASE_ARCH), m68k) | 489 | ifeq ($(TARGET_BASE_ARCH), m68k) |
| 490 | VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o | 490 | VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o |
hw/sh7750.c
| 1 | /* | 1 | /* |
| 2 | * SH7750 device | 2 | * SH7750 device |
| 3 | * | 3 | * |
| 4 | + * Copyright (c) 2007 Magnus Damm | ||
| 4 | * Copyright (c) 2005 Samuel Tardieu | 5 | * Copyright (c) 2005 Samuel Tardieu |
| 5 | * | 6 | * |
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy |
| @@ -26,6 +27,7 @@ | @@ -26,6 +27,7 @@ | ||
| 26 | #include "vl.h" | 27 | #include "vl.h" |
| 27 | #include "sh7750_regs.h" | 28 | #include "sh7750_regs.h" |
| 28 | #include "sh7750_regnames.h" | 29 | #include "sh7750_regnames.h" |
| 30 | +#include "sh_intc.h" | ||
| 29 | 31 | ||
| 30 | #define NB_DEVICES 4 | 32 | #define NB_DEVICES 4 |
| 31 | 33 | ||
| @@ -53,15 +55,10 @@ typedef struct SH7750State { | @@ -53,15 +55,10 @@ typedef struct SH7750State { | ||
| 53 | sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */ | 55 | sh7750_io_device *devices[NB_DEVICES]; /* External peripherals */ |
| 54 | 56 | ||
| 55 | uint16_t icr; | 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 | /* Cache */ | 58 | /* Cache */ |
| 63 | uint32_t ccr; | 59 | uint32_t ccr; |
| 64 | 60 | ||
| 61 | + struct intc_desc intc; | ||
| 65 | } SH7750State; | 62 | } SH7750State; |
| 66 | 63 | ||
| 67 | 64 | ||
| @@ -219,14 +216,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) | @@ -219,14 +216,6 @@ static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) | ||
| 219 | return portb_lines(s); | 216 | return portb_lines(s); |
| 220 | case 0x1fd00000: | 217 | case 0x1fd00000: |
| 221 | return s->icr; | 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 | default: | 219 | default: |
| 231 | error_access("word read", addr); | 220 | error_access("word read", addr); |
| 232 | assert(0); | 221 | assert(0); |
| @@ -262,14 +251,6 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) | @@ -262,14 +251,6 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) | ||
| 262 | return 0x00110000; /* Minimum caches */ | 251 | return 0x00110000; /* Minimum caches */ |
| 263 | case 0x1f000044: /* Processor version PRR */ | 252 | case 0x1f000044: /* Processor version PRR */ |
| 264 | return 0x00000100; /* SH7750R */ | 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 | default: | 254 | default: |
| 274 | error_access("long read", addr); | 255 | error_access("long read", addr); |
| 275 | assert(0); | 256 | assert(0); |
| @@ -331,18 +312,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, | @@ -331,18 +312,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, | ||
| 331 | case 0x1fd00000: | 312 | case 0x1fd00000: |
| 332 | s->icr = mem_value; | 313 | s->icr = mem_value; |
| 333 | return; | 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 | default: | 315 | default: |
| 347 | error_access("word write", addr); | 316 | error_access("word write", addr); |
| 348 | assert(0); | 317 | assert(0); |
| @@ -407,16 +376,6 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, | @@ -407,16 +376,6 @@ static void sh7750_mem_writel(void *opaque, target_phys_addr_t addr, | ||
| 407 | case SH7750_CCR_A7: | 376 | case SH7750_CCR_A7: |
| 408 | s->ccr = mem_value; | 377 | s->ccr = mem_value; |
| 409 | return; | 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 | default: | 379 | default: |
| 421 | error_access("long write", addr); | 380 | error_access("long write", addr); |
| 422 | assert(0); | 381 | assert(0); |
| @@ -435,10 +394,144 @@ static CPUWriteMemoryFunc *sh7750_mem_write[] = { | @@ -435,10 +394,144 @@ static CPUWriteMemoryFunc *sh7750_mem_write[] = { | ||
| 435 | sh7750_mem_writel | 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 | SH7750State *sh7750_init(CPUSH4State * cpu) | 530 | SH7750State *sh7750_init(CPUSH4State * cpu) |
| 439 | { | 531 | { |
| 440 | SH7750State *s; | 532 | SH7750State *s; |
| 441 | int sh7750_io_memory; | 533 | int sh7750_io_memory; |
| 534 | + int cpu_model = SH_CPU_SH7751R; /* for now */ | ||
| 442 | 535 | ||
| 443 | s = qemu_mallocz(sizeof(SH7750State)); | 536 | s = qemu_mallocz(sizeof(SH7750State)); |
| 444 | s->cpu = cpu; | 537 | s->cpu = cpu; |
| @@ -448,6 +541,14 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | @@ -448,6 +541,14 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | ||
| 448 | sh7750_mem_write, s); | 541 | sh7750_mem_write, s); |
| 449 | cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory); | 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 | sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]); | 552 | sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]); |
| 452 | sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF, | 553 | sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF, |
| 453 | s->periph_freq, serial_hds[1]); | 554 | s->periph_freq, serial_hds[1]); |
| @@ -455,6 +556,38 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | @@ -455,6 +556,38 @@ SH7750State *sh7750_init(CPUSH4State * cpu) | ||
| 455 | tmu012_init(0x1fd80000, | 556 | tmu012_init(0x1fd80000, |
| 456 | TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, | 557 | TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, |
| 457 | s->periph_freq); | 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 | return s; | 592 | return s; |
| 460 | } | 593 | } |
hw/sh7750_regnames.c
| @@ -76,9 +76,6 @@ static regname_t regnames[] = { | @@ -76,9 +76,6 @@ static regname_t regnames[] = { | ||
| 76 | REGNAME(SH7750_PDTRB_A7) | 76 | REGNAME(SH7750_PDTRB_A7) |
| 77 | REGNAME(SH7750_GPIOIC_A7) | 77 | REGNAME(SH7750_GPIOIC_A7) |
| 78 | REGNAME(SH7750_ICR_A7) | 78 | REGNAME(SH7750_ICR_A7) |
| 79 | - REGNAME(SH7750_IPRA_A7) | ||
| 80 | - REGNAME(SH7750_IPRB_A7) | ||
| 81 | - REGNAME(SH7750_IPRC_A7) | ||
| 82 | REGNAME(SH7750_BCR3_A7) | 79 | REGNAME(SH7750_BCR3_A7) |
| 83 | REGNAME(SH7750_BCR4_A7) | 80 | REGNAME(SH7750_BCR4_A7) |
| 84 | REGNAME(SH7750_PRECHARGE0_A7) | 81 | REGNAME(SH7750_PRECHARGE0_A7) |
hw/sh7750_regs.h
| @@ -1241,48 +1241,6 @@ | @@ -1241,48 +1241,6 @@ | ||
| 1241 | #define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four independent | 1241 | #define SH7750_ICR_IRLM_RAW 0x0080 /* IRL\ pins used as a four independent |
| 1242 | interrupt requests */ | 1242 | interrupt requests */ |
| 1243 | 1243 | ||
| 1244 | -/* Interrupt Priority Register A - IPRA (half) */ | ||
| 1245 | -#define SH7750_IPRA_REGOFS 0xD00004 /* offset */ | ||
| 1246 | -#define SH7750_IPRA SH7750_P4_REG32(SH7750_IPRA_REGOFS) | ||
| 1247 | -#define SH7750_IPRA_A7 SH7750_A7_REG32(SH7750_IPRA_REGOFS) | ||
| 1248 | - | ||
| 1249 | -#define SH7750_IPRA_TMU0 0xF000 /* TMU0 interrupt priority */ | ||
| 1250 | -#define SH7750_IPRA_TMU0_S 12 | ||
| 1251 | -#define SH7750_IPRA_TMU1 0x0F00 /* TMU1 interrupt priority */ | ||
| 1252 | -#define SH7750_IPRA_TMU1_S 8 | ||
| 1253 | -#define SH7750_IPRA_TMU2 0x00F0 /* TMU2 interrupt priority */ | ||
| 1254 | -#define SH7750_IPRA_TMU2_S 4 | ||
| 1255 | -#define SH7750_IPRA_RTC 0x000F /* RTC interrupt priority */ | ||
| 1256 | -#define SH7750_IPRA_RTC_S 0 | ||
| 1257 | - | ||
| 1258 | -/* Interrupt Priority Register B - IPRB (half) */ | ||
| 1259 | -#define SH7750_IPRB_REGOFS 0xD00008 /* offset */ | ||
| 1260 | -#define SH7750_IPRB SH7750_P4_REG32(SH7750_IPRB_REGOFS) | ||
| 1261 | -#define SH7750_IPRB_A7 SH7750_A7_REG32(SH7750_IPRB_REGOFS) | ||
| 1262 | - | ||
| 1263 | -#define SH7750_IPRB_WDT 0xF000 /* WDT interrupt priority */ | ||
| 1264 | -#define SH7750_IPRB_WDT_S 12 | ||
| 1265 | -#define SH7750_IPRB_REF 0x0F00 /* Memory Refresh unit interrupt | ||
| 1266 | - priority */ | ||
| 1267 | -#define SH7750_IPRB_REF_S 8 | ||
| 1268 | -#define SH7750_IPRB_SCI1 0x00F0 /* SCI1 interrupt priority */ | ||
| 1269 | -#define SH7750_IPRB_SCI1_S 4 | ||
| 1270 | - | ||
| 1271 | -/* Interrupt Priority Register ó - IPRó (half) */ | ||
| 1272 | -#define SH7750_IPRC_REGOFS 0xD00004 /* offset */ | ||
| 1273 | -#define SH7750_IPRC SH7750_P4_REG32(SH7750_IPRC_REGOFS) | ||
| 1274 | -#define SH7750_IPRC_A7 SH7750_A7_REG32(SH7750_IPRC_REGOFS) | ||
| 1275 | - | ||
| 1276 | -#define SH7750_IPRC_GPIO 0xF000 /* GPIO interrupt priority */ | ||
| 1277 | -#define SH7750_IPRC_GPIO_S 12 | ||
| 1278 | -#define SH7750_IPRC_DMAC 0x0F00 /* DMAC interrupt priority */ | ||
| 1279 | -#define SH7750_IPRC_DMAC_S 8 | ||
| 1280 | -#define SH7750_IPRC_SCIF 0x00F0 /* SCIF interrupt priority */ | ||
| 1281 | -#define SH7750_IPRC_SCIF_S 4 | ||
| 1282 | -#define SH7750_IPRC_HUDI 0x000F /* H-UDI interrupt priority */ | ||
| 1283 | -#define SH7750_IPRC_HUDI_S 0 | ||
| 1284 | - | ||
| 1285 | - | ||
| 1286 | /* | 1244 | /* |
| 1287 | * User Break Controller registers | 1245 | * User Break Controller registers |
| 1288 | */ | 1246 | */ |
hw/sh_intc.c
0 → 100644
| 1 | +/* | ||
| 2 | + * SuperH interrupt controller module | ||
| 3 | + * | ||
| 4 | + * Copyright (c) 2007 Magnus Damm | ||
| 5 | + * Based on sh_timer.c and arm_timer.c by Paul Brook | ||
| 6 | + * Copyright (c) 2005-2006 CodeSourcery. | ||
| 7 | + * | ||
| 8 | + * This code is licenced under the GPL. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +#include <assert.h> | ||
| 12 | +#include "sh_intc.h" | ||
| 13 | +#include "vl.h" | ||
| 14 | + | ||
| 15 | +//#define DEBUG_INTC | ||
| 16 | + | ||
| 17 | +#define INTC_A7(x) ((x) & 0x1fffffff) | ||
| 18 | +#define INTC_ARRAY(x) (sizeof(x) / sizeof(x[0])) | ||
| 19 | + | ||
| 20 | +#define INTC_MODE_NONE 0 | ||
| 21 | +#define INTC_MODE_DUAL_SET 1 | ||
| 22 | +#define INTC_MODE_DUAL_CLR 2 | ||
| 23 | +#define INTC_MODE_ENABLE_REG 3 | ||
| 24 | +#define INTC_MODE_MASK_REG 4 | ||
| 25 | +#define INTC_MODE_IS_PRIO 8 | ||
| 26 | + | ||
| 27 | +static unsigned int sh_intc_mode(unsigned long address, | ||
| 28 | + unsigned long set_reg, unsigned long clr_reg) | ||
| 29 | +{ | ||
| 30 | + if ((address != INTC_A7(set_reg)) && | ||
| 31 | + (address != INTC_A7(clr_reg))) | ||
| 32 | + return INTC_MODE_NONE; | ||
| 33 | + | ||
| 34 | + if (set_reg && clr_reg) { | ||
| 35 | + if (address == INTC_A7(set_reg)) | ||
| 36 | + return INTC_MODE_DUAL_SET; | ||
| 37 | + else | ||
| 38 | + return INTC_MODE_DUAL_CLR; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + if (set_reg) | ||
| 42 | + return INTC_MODE_ENABLE_REG; | ||
| 43 | + else | ||
| 44 | + return INTC_MODE_MASK_REG; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +static void sh_intc_locate(struct intc_desc *desc, | ||
| 48 | + unsigned long address, | ||
| 49 | + unsigned long **datap, | ||
| 50 | + intc_enum **enums, | ||
| 51 | + unsigned int *first, | ||
| 52 | + unsigned int *width, | ||
| 53 | + unsigned int *modep) | ||
| 54 | +{ | ||
| 55 | + unsigned int i, mode; | ||
| 56 | + | ||
| 57 | + /* this is slow but works for now */ | ||
| 58 | + | ||
| 59 | + if (desc->mask_regs) { | ||
| 60 | + for (i = 0; i < desc->nr_mask_regs; i++) { | ||
| 61 | + struct intc_mask_reg *mr = desc->mask_regs + i; | ||
| 62 | + | ||
| 63 | + mode = sh_intc_mode(address, mr->set_reg, mr->clr_reg); | ||
| 64 | + if (mode == INTC_MODE_NONE) | ||
| 65 | + continue; | ||
| 66 | + | ||
| 67 | + *modep = mode; | ||
| 68 | + *datap = &mr->value; | ||
| 69 | + *enums = mr->enum_ids; | ||
| 70 | + *first = mr->reg_width - 1; | ||
| 71 | + *width = 1; | ||
| 72 | + return; | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + | ||
| 76 | + if (desc->prio_regs) { | ||
| 77 | + for (i = 0; i < desc->nr_prio_regs; i++) { | ||
| 78 | + struct intc_prio_reg *pr = desc->prio_regs + i; | ||
| 79 | + | ||
| 80 | + mode = sh_intc_mode(address, pr->set_reg, pr->clr_reg); | ||
| 81 | + if (mode == INTC_MODE_NONE) | ||
| 82 | + continue; | ||
| 83 | + | ||
| 84 | + *modep = mode | INTC_MODE_IS_PRIO; | ||
| 85 | + *datap = &pr->value; | ||
| 86 | + *enums = pr->enum_ids; | ||
| 87 | + *first = (pr->reg_width / pr->field_width) - 1; | ||
| 88 | + *width = pr->field_width; | ||
| 89 | + return; | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | + | ||
| 93 | + assert(0); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +static void sh_intc_toggle(struct intc_desc *desc, intc_enum id, | ||
| 97 | + int enable, int is_group) | ||
| 98 | +{ | ||
| 99 | + struct intc_source *source = desc->sources + id; | ||
| 100 | + int old = source->enable_count; | ||
| 101 | + | ||
| 102 | + if (!id) | ||
| 103 | + return; | ||
| 104 | + | ||
| 105 | + if (!source->next_enum_id && (!source->enable_max || !source->vect)) { | ||
| 106 | +#ifdef DEBUG_INTC | ||
| 107 | + printf("sh_intc: reserved interrupt source %d modified\n", id); | ||
| 108 | +#endif | ||
| 109 | + return; | ||
| 110 | + } | ||
| 111 | + | ||
| 112 | + if (source->vect) { | ||
| 113 | + if (enable) | ||
| 114 | + source->enable_count++; | ||
| 115 | + else | ||
| 116 | + source->enable_count--; | ||
| 117 | + | ||
| 118 | + if (source->enable_count == source->enable_max) { | ||
| 119 | +#ifdef DEBUG_INTC | ||
| 120 | + printf("sh_intc: enabling interrupt source %d -> 0x%04x\n", | ||
| 121 | + id, source->vect); | ||
| 122 | +#endif | ||
| 123 | + } | ||
| 124 | + | ||
| 125 | + if (old == source->enable_max) { | ||
| 126 | +#ifdef DEBUG_INTC | ||
| 127 | + printf("sh_intc: disabling interrupt source %d -> 0x%04x\n", | ||
| 128 | + id, source->vect); | ||
| 129 | +#endif | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | +#ifdef DEBUG_INTC | ||
| 133 | + else { | ||
| 134 | + printf("setting interrupt group %d to %d\n", id, !!enable); | ||
| 135 | + } | ||
| 136 | +#endif | ||
| 137 | + | ||
| 138 | + if ((is_group || !source->vect) && source->next_enum_id) { | ||
| 139 | + sh_intc_toggle(desc, source->next_enum_id, enable, 1); | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | +#ifdef DEBUG_INTC | ||
| 143 | + if (!source->vect) { | ||
| 144 | + printf("setting interrupt group %d to %d - done\n", id, !!enable); | ||
| 145 | + } | ||
| 146 | +#endif | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +static uint32_t sh_intc_read(void *opaque, target_phys_addr_t offset) | ||
| 150 | +{ | ||
| 151 | + struct intc_desc *desc = opaque; | ||
| 152 | + intc_enum *enum_ids = NULL; | ||
| 153 | + unsigned int first = 0; | ||
| 154 | + unsigned int width = 0; | ||
| 155 | + unsigned int mode = 0; | ||
| 156 | + unsigned long *valuep; | ||
| 157 | + | ||
| 158 | +#ifdef DEBUG_INTC | ||
| 159 | + printf("sh_intc_read 0x%lx\n", (unsigned long) offset); | ||
| 160 | +#endif | ||
| 161 | + | ||
| 162 | + sh_intc_locate(desc, (unsigned long)offset, &valuep, | ||
| 163 | + &enum_ids, &first, &width, &mode); | ||
| 164 | + return *valuep; | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +static void sh_intc_write(void *opaque, target_phys_addr_t offset, | ||
| 168 | + uint32_t value) | ||
| 169 | +{ | ||
| 170 | + struct intc_desc *desc = opaque; | ||
| 171 | + intc_enum *enum_ids = NULL; | ||
| 172 | + unsigned int first = 0; | ||
| 173 | + unsigned int width = 0; | ||
| 174 | + unsigned int mode = 0; | ||
| 175 | + unsigned int k; | ||
| 176 | + unsigned long *valuep; | ||
| 177 | + unsigned long mask; | ||
| 178 | + | ||
| 179 | +#ifdef DEBUG_INTC | ||
| 180 | + printf("sh_intc_write 0x%lx 0x%08x\n", (unsigned long) offset, value); | ||
| 181 | +#endif | ||
| 182 | + | ||
| 183 | + sh_intc_locate(desc, (unsigned long)offset, &valuep, | ||
| 184 | + &enum_ids, &first, &width, &mode); | ||
| 185 | + | ||
| 186 | + switch (mode) { | ||
| 187 | + case INTC_MODE_ENABLE_REG | INTC_MODE_IS_PRIO: break; | ||
| 188 | + case INTC_MODE_DUAL_SET: value |= *valuep; break; | ||
| 189 | + case INTC_MODE_DUAL_CLR: value = *valuep & ~value; break; | ||
| 190 | + default: assert(0); | ||
| 191 | + } | ||
| 192 | + | ||
| 193 | + for (k = 0; k <= first; k++) { | ||
| 194 | + mask = ((1 << width) - 1) << ((first - k) * width); | ||
| 195 | + | ||
| 196 | + if ((*valuep & mask) == (value & mask)) | ||
| 197 | + continue; | ||
| 198 | +#if 0 | ||
| 199 | + printf("k = %d, first = %d, enum = %d, mask = 0x%08x\n", | ||
| 200 | + k, first, enum_ids[k], (unsigned int)mask); | ||
| 201 | +#endif | ||
| 202 | + sh_intc_toggle(desc, enum_ids[k], value & mask, 0); | ||
| 203 | + } | ||
| 204 | + | ||
| 205 | + *valuep = value; | ||
| 206 | + | ||
| 207 | +#ifdef DEBUG_INTC | ||
| 208 | + printf("sh_intc_write 0x%lx -> 0x%08x\n", (unsigned long) offset, value); | ||
| 209 | +#endif | ||
| 210 | +} | ||
| 211 | + | ||
| 212 | +static CPUReadMemoryFunc *sh_intc_readfn[] = { | ||
| 213 | + sh_intc_read, | ||
| 214 | + sh_intc_read, | ||
| 215 | + sh_intc_read | ||
| 216 | +}; | ||
| 217 | + | ||
| 218 | +static CPUWriteMemoryFunc *sh_intc_writefn[] = { | ||
| 219 | + sh_intc_write, | ||
| 220 | + sh_intc_write, | ||
| 221 | + sh_intc_write | ||
| 222 | +}; | ||
| 223 | + | ||
| 224 | +struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id) | ||
| 225 | +{ | ||
| 226 | + if (id) | ||
| 227 | + return desc->sources + id; | ||
| 228 | + | ||
| 229 | + return NULL; | ||
| 230 | +} | ||
| 231 | + | ||
| 232 | +static void sh_intc_register(struct intc_desc *desc, | ||
| 233 | + unsigned long address) | ||
| 234 | +{ | ||
| 235 | + if (address) | ||
| 236 | + cpu_register_physical_memory(INTC_A7(address), 4, desc->iomemtype); | ||
| 237 | +} | ||
| 238 | + | ||
| 239 | +static void sh_intc_register_source(struct intc_desc *desc, | ||
| 240 | + intc_enum source, | ||
| 241 | + struct intc_group *groups, | ||
| 242 | + int nr_groups) | ||
| 243 | +{ | ||
| 244 | + unsigned int i, k; | ||
| 245 | + struct intc_source *s; | ||
| 246 | + | ||
| 247 | + if (desc->mask_regs) { | ||
| 248 | + for (i = 0; i < desc->nr_mask_regs; i++) { | ||
| 249 | + struct intc_mask_reg *mr = desc->mask_regs + i; | ||
| 250 | + | ||
| 251 | + for (k = 0; k < INTC_ARRAY(mr->enum_ids); k++) { | ||
| 252 | + if (mr->enum_ids[k] != source) | ||
| 253 | + continue; | ||
| 254 | + | ||
| 255 | + s = sh_intc_source(desc, mr->enum_ids[k]); | ||
| 256 | + if (s) | ||
| 257 | + s->enable_max++; | ||
| 258 | + } | ||
| 259 | + } | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + if (desc->prio_regs) { | ||
| 263 | + for (i = 0; i < desc->nr_prio_regs; i++) { | ||
| 264 | + struct intc_prio_reg *pr = desc->prio_regs + i; | ||
| 265 | + | ||
| 266 | + for (k = 0; k < INTC_ARRAY(pr->enum_ids); k++) { | ||
| 267 | + if (pr->enum_ids[k] != source) | ||
| 268 | + continue; | ||
| 269 | + | ||
| 270 | + s = sh_intc_source(desc, pr->enum_ids[k]); | ||
| 271 | + if (s) | ||
| 272 | + s->enable_max++; | ||
| 273 | + } | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + | ||
| 277 | + if (groups) { | ||
| 278 | + for (i = 0; i < nr_groups; i++) { | ||
| 279 | + struct intc_group *gr = groups + i; | ||
| 280 | + | ||
| 281 | + for (k = 0; k < INTC_ARRAY(gr->enum_ids); k++) { | ||
| 282 | + if (gr->enum_ids[k] != source) | ||
| 283 | + continue; | ||
| 284 | + | ||
| 285 | + s = sh_intc_source(desc, gr->enum_ids[k]); | ||
| 286 | + if (s) | ||
| 287 | + s->enable_max++; | ||
| 288 | + } | ||
| 289 | + } | ||
| 290 | + } | ||
| 291 | + | ||
| 292 | +} | ||
| 293 | + | ||
| 294 | +void sh_intc_register_sources(struct intc_desc *desc, | ||
| 295 | + struct intc_vect *vectors, | ||
| 296 | + int nr_vectors, | ||
| 297 | + struct intc_group *groups, | ||
| 298 | + int nr_groups) | ||
| 299 | +{ | ||
| 300 | + unsigned int i, k; | ||
| 301 | + struct intc_source *s; | ||
| 302 | + | ||
| 303 | + for (i = 0; i < nr_vectors; i++) { | ||
| 304 | + struct intc_vect *vect = vectors + i; | ||
| 305 | + | ||
| 306 | + sh_intc_register_source(desc, vect->enum_id, groups, nr_groups); | ||
| 307 | + s = sh_intc_source(desc, vect->enum_id); | ||
| 308 | + if (s) | ||
| 309 | + s->vect = vect->vect; | ||
| 310 | + | ||
| 311 | +#ifdef DEBUG_INTC | ||
| 312 | + printf("sh_intc: registered source %d -> 0x%04x (%d/%d)\n", | ||
| 313 | + vect->enum_id, s->vect, s->enable_count, s->enable_max); | ||
| 314 | +#endif | ||
| 315 | + } | ||
| 316 | + | ||
| 317 | + if (groups) { | ||
| 318 | + for (i = 0; i < nr_groups; i++) { | ||
| 319 | + struct intc_group *gr = groups + i; | ||
| 320 | + | ||
| 321 | + s = sh_intc_source(desc, gr->enum_id); | ||
| 322 | + s->next_enum_id = gr->enum_ids[0]; | ||
| 323 | + | ||
| 324 | + for (k = 1; k < INTC_ARRAY(gr->enum_ids); k++) { | ||
| 325 | + if (!gr->enum_ids[k]) | ||
| 326 | + continue; | ||
| 327 | + | ||
| 328 | + s = sh_intc_source(desc, gr->enum_ids[k - 1]); | ||
| 329 | + s->next_enum_id = gr->enum_ids[k]; | ||
| 330 | + } | ||
| 331 | + | ||
| 332 | +#ifdef DEBUG_INTC | ||
| 333 | + printf("sh_intc: registered group %d (%d/%d)\n", | ||
| 334 | + gr->enum_id, s->enable_count, s->enable_max); | ||
| 335 | +#endif | ||
| 336 | + } | ||
| 337 | + } | ||
| 338 | +} | ||
| 339 | + | ||
| 340 | +int sh_intc_init(struct intc_desc *desc, | ||
| 341 | + int nr_sources, | ||
| 342 | + struct intc_mask_reg *mask_regs, | ||
| 343 | + int nr_mask_regs, | ||
| 344 | + struct intc_prio_reg *prio_regs, | ||
| 345 | + int nr_prio_regs) | ||
| 346 | +{ | ||
| 347 | + unsigned int i; | ||
| 348 | + | ||
| 349 | + desc->nr_sources = nr_sources; | ||
| 350 | + desc->mask_regs = mask_regs; | ||
| 351 | + desc->nr_mask_regs = nr_mask_regs; | ||
| 352 | + desc->prio_regs = prio_regs; | ||
| 353 | + desc->nr_prio_regs = nr_prio_regs; | ||
| 354 | + | ||
| 355 | + i = sizeof(struct intc_source) * nr_sources; | ||
| 356 | + desc->sources = malloc(i); | ||
| 357 | + if (!desc->sources) | ||
| 358 | + return -1; | ||
| 359 | + | ||
| 360 | + memset(desc->sources, 0, i); | ||
| 361 | + | ||
| 362 | + desc->iomemtype = cpu_register_io_memory(0, sh_intc_readfn, | ||
| 363 | + sh_intc_writefn, desc); | ||
| 364 | + if (desc->mask_regs) { | ||
| 365 | + for (i = 0; i < desc->nr_mask_regs; i++) { | ||
| 366 | + struct intc_mask_reg *mr = desc->mask_regs + i; | ||
| 367 | + | ||
| 368 | + sh_intc_register(desc, mr->set_reg); | ||
| 369 | + sh_intc_register(desc, mr->clr_reg); | ||
| 370 | + } | ||
| 371 | + } | ||
| 372 | + | ||
| 373 | + if (desc->prio_regs) { | ||
| 374 | + for (i = 0; i < desc->nr_prio_regs; i++) { | ||
| 375 | + struct intc_prio_reg *pr = desc->prio_regs + i; | ||
| 376 | + | ||
| 377 | + sh_intc_register(desc, pr->set_reg); | ||
| 378 | + sh_intc_register(desc, pr->clr_reg); | ||
| 379 | + } | ||
| 380 | + } | ||
| 381 | + | ||
| 382 | + return 0; | ||
| 383 | +} |
hw/sh_intc.h
0 → 100644
| 1 | +#ifndef __SH_INTC_H__ | ||
| 2 | +#define __SH_INTC_H__ | ||
| 3 | + | ||
| 4 | +typedef unsigned char intc_enum; | ||
| 5 | + | ||
| 6 | +struct intc_vect { | ||
| 7 | + intc_enum enum_id; | ||
| 8 | + unsigned short vect; | ||
| 9 | +}; | ||
| 10 | + | ||
| 11 | +#define INTC_VECT(enum_id, vect) { enum_id, vect } | ||
| 12 | + | ||
| 13 | +struct intc_group { | ||
| 14 | + intc_enum enum_id; | ||
| 15 | + intc_enum enum_ids[32]; | ||
| 16 | +}; | ||
| 17 | + | ||
| 18 | +#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } } | ||
| 19 | + | ||
| 20 | +struct intc_mask_reg { | ||
| 21 | + unsigned long set_reg, clr_reg, reg_width; | ||
| 22 | + intc_enum enum_ids[32]; | ||
| 23 | + unsigned long value; | ||
| 24 | +}; | ||
| 25 | + | ||
| 26 | +struct intc_prio_reg { | ||
| 27 | + unsigned long set_reg, clr_reg, reg_width, field_width; | ||
| 28 | + intc_enum enum_ids[16]; | ||
| 29 | + unsigned long value; | ||
| 30 | +}; | ||
| 31 | + | ||
| 32 | +#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a) | ||
| 33 | + | ||
| 34 | +struct intc_source { | ||
| 35 | + unsigned short vect; | ||
| 36 | + intc_enum next_enum_id; | ||
| 37 | + | ||
| 38 | + int asserted; | ||
| 39 | + int enable_count; | ||
| 40 | + int enable_max; | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +struct intc_desc { | ||
| 44 | + struct intc_source *sources; | ||
| 45 | + int nr_sources; | ||
| 46 | + struct intc_mask_reg *mask_regs; | ||
| 47 | + int nr_mask_regs; | ||
| 48 | + struct intc_prio_reg *prio_regs; | ||
| 49 | + int nr_prio_regs; | ||
| 50 | + | ||
| 51 | + int iomemtype; | ||
| 52 | +}; | ||
| 53 | + | ||
| 54 | +struct intc_source *sh_intc_source(struct intc_desc *desc, intc_enum id); | ||
| 55 | + | ||
| 56 | +void sh_intc_register_sources(struct intc_desc *desc, | ||
| 57 | + struct intc_vect *vectors, | ||
| 58 | + int nr_vectors, | ||
| 59 | + struct intc_group *groups, | ||
| 60 | + int nr_groups); | ||
| 61 | + | ||
| 62 | +int sh_intc_init(struct intc_desc *desc, | ||
| 63 | + int nr_sources, | ||
| 64 | + struct intc_mask_reg *mask_regs, | ||
| 65 | + int nr_mask_regs, | ||
| 66 | + struct intc_prio_reg *prio_regs, | ||
| 67 | + int nr_prio_regs); | ||
| 68 | + | ||
| 69 | +#endif /* __SH_INTC_H__ */ |