Commit d47ede60933f265e558723096e67734db165bdae
1 parent
c6d86a33
sh4: Add r2d onboard FPGA IRQ controller (Takashi YOSHII).
This adds IRQ controller in FPGA on r2d, and use it for CF. Signed-off-by: Takashi YOSHII <takasi-y@ops.dti.ne.jp> Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5926 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
63 additions
and
5 deletions
hw/r2d.c
| @@ -34,12 +34,14 @@ | @@ -34,12 +34,14 @@ | ||
| 34 | 34 | ||
| 35 | #define SM501_VRAM_SIZE 0x800000 | 35 | #define SM501_VRAM_SIZE 0x800000 |
| 36 | 36 | ||
| 37 | +#define PA_IRLMSK 0x00 | ||
| 37 | #define PA_POWOFF 0x30 | 38 | #define PA_POWOFF 0x30 |
| 38 | #define PA_VERREG 0x32 | 39 | #define PA_VERREG 0x32 |
| 39 | #define PA_OUTPORT 0x36 | 40 | #define PA_OUTPORT 0x36 |
| 40 | 41 | ||
| 41 | typedef struct { | 42 | typedef struct { |
| 42 | uint16_t bcr; | 43 | uint16_t bcr; |
| 44 | + uint16_t irlmsk; | ||
| 43 | uint16_t irlmon; | 45 | uint16_t irlmon; |
| 44 | uint16_t cfctl; | 46 | uint16_t cfctl; |
| 45 | uint16_t cfpow; | 47 | uint16_t cfpow; |
| @@ -60,13 +62,60 @@ typedef struct { | @@ -60,13 +62,60 @@ typedef struct { | ||
| 60 | uint16_t inport; | 62 | uint16_t inport; |
| 61 | uint16_t outport; | 63 | uint16_t outport; |
| 62 | uint16_t bverreg; | 64 | uint16_t bverreg; |
| 65 | + | ||
| 66 | +/* output pin */ | ||
| 67 | + qemu_irq irl; | ||
| 63 | } r2d_fpga_t; | 68 | } r2d_fpga_t; |
| 64 | 69 | ||
| 70 | +enum r2d_fpga_irq { | ||
| 71 | + PCI_INTD, CF_IDE, CF_CD, PCI_INTC, SM501, KEY, RTC_A, RTC_T, | ||
| 72 | + SDCARD, PCI_INTA, PCI_INTB, EXT, TP, | ||
| 73 | + NR_IRQS | ||
| 74 | +}; | ||
| 75 | + | ||
| 76 | +static const struct { short irl; uint16_t msk; } irqtab[NR_IRQS] = { | ||
| 77 | + [CF_IDE] = { 1, 1<<9 }, | ||
| 78 | + [CF_CD] = { 2, 1<<8 }, | ||
| 79 | + [PCI_INTA] = { 9, 1<<14 }, | ||
| 80 | + [PCI_INTB] = { 10, 1<<13 }, | ||
| 81 | + [PCI_INTC] = { 3, 1<<12 }, | ||
| 82 | + [PCI_INTD] = { 0, 1<<11 }, | ||
| 83 | + [SM501] = { 4, 1<<10 }, | ||
| 84 | + [KEY] = { 5, 1<<6 }, | ||
| 85 | + [RTC_A] = { 6, 1<<5 }, | ||
| 86 | + [RTC_T] = { 7, 1<<4 }, | ||
| 87 | + [SDCARD] = { 8, 1<<7 }, | ||
| 88 | + [EXT] = { 11, 1<<0 }, | ||
| 89 | + [TP] = { 12, 1<<15 }, | ||
| 90 | +}; | ||
| 91 | + | ||
| 92 | +static void update_irl(r2d_fpga_t *fpga) | ||
| 93 | +{ | ||
| 94 | + int i, irl = 15; | ||
| 95 | + for (i = 0; i < NR_IRQS; i++) | ||
| 96 | + if (fpga->irlmon & fpga->irlmsk & irqtab[i].msk) | ||
| 97 | + if (irqtab[i].irl < irl) | ||
| 98 | + irl = irqtab[i].irl; | ||
| 99 | + qemu_set_irq(fpga->irl, irl ^ 15); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +static void r2d_fpga_irq_set(void *opaque, int n, int level) | ||
| 103 | +{ | ||
| 104 | + r2d_fpga_t *fpga = opaque; | ||
| 105 | + if (level) | ||
| 106 | + fpga->irlmon |= irqtab[n].msk; | ||
| 107 | + else | ||
| 108 | + fpga->irlmon &= ~irqtab[n].msk; | ||
| 109 | + update_irl(fpga); | ||
| 110 | +} | ||
| 111 | + | ||
| 65 | static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) | 112 | static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) |
| 66 | { | 113 | { |
| 67 | r2d_fpga_t *s = opaque; | 114 | r2d_fpga_t *s = opaque; |
| 68 | 115 | ||
| 69 | switch (addr) { | 116 | switch (addr) { |
| 117 | + case PA_IRLMSK: | ||
| 118 | + return s->irlmsk; | ||
| 70 | case PA_OUTPORT: | 119 | case PA_OUTPORT: |
| 71 | return s->outport; | 120 | return s->outport; |
| 72 | case PA_POWOFF: | 121 | case PA_POWOFF: |
| @@ -84,6 +133,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) | @@ -84,6 +133,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) | ||
| 84 | r2d_fpga_t *s = opaque; | 133 | r2d_fpga_t *s = opaque; |
| 85 | 134 | ||
| 86 | switch (addr) { | 135 | switch (addr) { |
| 136 | + case PA_IRLMSK: | ||
| 137 | + s->irlmsk = value; | ||
| 138 | + update_irl(s); | ||
| 139 | + break; | ||
| 87 | case PA_OUTPORT: | 140 | case PA_OUTPORT: |
| 88 | s->outport = value; | 141 | s->outport = value; |
| 89 | break; | 142 | break; |
| @@ -108,18 +161,21 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { | @@ -108,18 +161,21 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { | ||
| 108 | NULL, | 161 | NULL, |
| 109 | }; | 162 | }; |
| 110 | 163 | ||
| 111 | -static void r2d_fpga_init(target_phys_addr_t base) | 164 | +static qemu_irq *r2d_fpga_init(target_phys_addr_t base, qemu_irq irl) |
| 112 | { | 165 | { |
| 113 | int iomemtype; | 166 | int iomemtype; |
| 114 | r2d_fpga_t *s; | 167 | r2d_fpga_t *s; |
| 115 | 168 | ||
| 116 | s = qemu_mallocz(sizeof(r2d_fpga_t)); | 169 | s = qemu_mallocz(sizeof(r2d_fpga_t)); |
| 117 | if (!s) | 170 | if (!s) |
| 118 | - return; | 171 | + return NULL; |
| 172 | + | ||
| 173 | + s->irl = irl; | ||
| 119 | 174 | ||
| 120 | iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, | 175 | iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, |
| 121 | r2d_fpga_writefn, s); | 176 | r2d_fpga_writefn, s); |
| 122 | cpu_register_physical_memory(base, 0x40, iomemtype); | 177 | cpu_register_physical_memory(base, 0x40, iomemtype); |
| 178 | + return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS); | ||
| 123 | } | 179 | } |
| 124 | 180 | ||
| 125 | static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | 181 | static void r2d_init(ram_addr_t ram_size, int vga_ram_size, |
| @@ -130,6 +186,7 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | @@ -130,6 +186,7 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | ||
| 130 | CPUState *env; | 186 | CPUState *env; |
| 131 | struct SH7750State *s; | 187 | struct SH7750State *s; |
| 132 | ram_addr_t sdram_addr, sm501_vga_ram_addr; | 188 | ram_addr_t sdram_addr, sm501_vga_ram_addr; |
| 189 | + qemu_irq *irq; | ||
| 133 | 190 | ||
| 134 | if (!cpu_model) | 191 | if (!cpu_model) |
| 135 | cpu_model = "SH7751R"; | 192 | cpu_model = "SH7751R"; |
| @@ -144,15 +201,16 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | @@ -144,15 +201,16 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, | ||
| 144 | sdram_addr = qemu_ram_alloc(SDRAM_SIZE); | 201 | sdram_addr = qemu_ram_alloc(SDRAM_SIZE); |
| 145 | cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); | 202 | cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); |
| 146 | /* Register peripherals */ | 203 | /* Register peripherals */ |
| 147 | - r2d_fpga_init(0x04000000); | ||
| 148 | s = sh7750_init(env); | 204 | s = sh7750_init(env); |
| 205 | + irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); | ||
| 206 | + | ||
| 149 | sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); | 207 | sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); |
| 150 | sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, | 208 | sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, |
| 151 | serial_hds[2]); | 209 | serial_hds[2]); |
| 152 | 210 | ||
| 153 | /* onboard CF (True IDE mode, Master only). */ | 211 | /* onboard CF (True IDE mode, Master only). */ |
| 154 | - mmio_ide_init(0x14001000, 0x1400080c, NULL, 1, | ||
| 155 | - drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); | 212 | + mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, |
| 213 | + drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); | ||
| 156 | 214 | ||
| 157 | /* Todo: register on board registers */ | 215 | /* Todo: register on board registers */ |
| 158 | { | 216 | { |