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 | 34 | |
| 35 | 35 | #define SM501_VRAM_SIZE 0x800000 |
| 36 | 36 | |
| 37 | +#define PA_IRLMSK 0x00 | |
| 37 | 38 | #define PA_POWOFF 0x30 |
| 38 | 39 | #define PA_VERREG 0x32 |
| 39 | 40 | #define PA_OUTPORT 0x36 |
| 40 | 41 | |
| 41 | 42 | typedef struct { |
| 42 | 43 | uint16_t bcr; |
| 44 | + uint16_t irlmsk; | |
| 43 | 45 | uint16_t irlmon; |
| 44 | 46 | uint16_t cfctl; |
| 45 | 47 | uint16_t cfpow; |
| ... | ... | @@ -60,13 +62,60 @@ typedef struct { |
| 60 | 62 | uint16_t inport; |
| 61 | 63 | uint16_t outport; |
| 62 | 64 | uint16_t bverreg; |
| 65 | + | |
| 66 | +/* output pin */ | |
| 67 | + qemu_irq irl; | |
| 63 | 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 | 112 | static uint32_t r2d_fpga_read(void *opaque, target_phys_addr_t addr) |
| 66 | 113 | { |
| 67 | 114 | r2d_fpga_t *s = opaque; |
| 68 | 115 | |
| 69 | 116 | switch (addr) { |
| 117 | + case PA_IRLMSK: | |
| 118 | + return s->irlmsk; | |
| 70 | 119 | case PA_OUTPORT: |
| 71 | 120 | return s->outport; |
| 72 | 121 | case PA_POWOFF: |
| ... | ... | @@ -84,6 +133,10 @@ r2d_fpga_write(void *opaque, target_phys_addr_t addr, uint32_t value) |
| 84 | 133 | r2d_fpga_t *s = opaque; |
| 85 | 134 | |
| 86 | 135 | switch (addr) { |
| 136 | + case PA_IRLMSK: | |
| 137 | + s->irlmsk = value; | |
| 138 | + update_irl(s); | |
| 139 | + break; | |
| 87 | 140 | case PA_OUTPORT: |
| 88 | 141 | s->outport = value; |
| 89 | 142 | break; |
| ... | ... | @@ -108,18 +161,21 @@ static CPUWriteMemoryFunc *r2d_fpga_writefn[] = { |
| 108 | 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 | 166 | int iomemtype; |
| 114 | 167 | r2d_fpga_t *s; |
| 115 | 168 | |
| 116 | 169 | s = qemu_mallocz(sizeof(r2d_fpga_t)); |
| 117 | 170 | if (!s) |
| 118 | - return; | |
| 171 | + return NULL; | |
| 172 | + | |
| 173 | + s->irl = irl; | |
| 119 | 174 | |
| 120 | 175 | iomemtype = cpu_register_io_memory(0, r2d_fpga_readfn, |
| 121 | 176 | r2d_fpga_writefn, s); |
| 122 | 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 | 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 | 186 | CPUState *env; |
| 131 | 187 | struct SH7750State *s; |
| 132 | 188 | ram_addr_t sdram_addr, sm501_vga_ram_addr; |
| 189 | + qemu_irq *irq; | |
| 133 | 190 | |
| 134 | 191 | if (!cpu_model) |
| 135 | 192 | cpu_model = "SH7751R"; |
| ... | ... | @@ -144,15 +201,16 @@ static void r2d_init(ram_addr_t ram_size, int vga_ram_size, |
| 144 | 201 | sdram_addr = qemu_ram_alloc(SDRAM_SIZE); |
| 145 | 202 | cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); |
| 146 | 203 | /* Register peripherals */ |
| 147 | - r2d_fpga_init(0x04000000); | |
| 148 | 204 | s = sh7750_init(env); |
| 205 | + irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); | |
| 206 | + | |
| 149 | 207 | sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); |
| 150 | 208 | sm501_init(ds, 0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, |
| 151 | 209 | serial_hds[2]); |
| 152 | 210 | |
| 153 | 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 | 215 | /* Todo: register on board registers */ |
| 158 | 216 | { | ... | ... |