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 | { | ... | ... |