Commit 106627d0a036f9ebe523c648686b087eb8888355
1 parent
577390ff
Rework OMAP1 interrupt handling to allow multiple interrupt banks, by Lauro Ramos Venancio.
Add irq pulse shortcut, by Lauro Ramos Venancio. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3774 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
167 additions
and
134 deletions
hw/irq.h
@@ -19,6 +19,12 @@ static inline void qemu_irq_lower(qemu_irq irq) | @@ -19,6 +19,12 @@ static inline void qemu_irq_lower(qemu_irq irq) | ||
19 | qemu_set_irq(irq, 0); | 19 | qemu_set_irq(irq, 0); |
20 | } | 20 | } |
21 | 21 | ||
22 | +static inline void qemu_irq_pulse(qemu_irq irq) | ||
23 | +{ | ||
24 | + qemu_set_irq(irq, 1); | ||
25 | + qemu_set_irq(irq, 0); | ||
26 | +} | ||
27 | + | ||
22 | /* Returns an array of N IRQs. */ | 28 | /* Returns an array of N IRQs. */ |
23 | qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); | 29 | qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n); |
24 | 30 |
hw/omap.c
@@ -80,71 +80,68 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, | @@ -80,71 +80,68 @@ void omap_badwidth_write32(void *opaque, target_phys_addr_t addr, | ||
80 | } | 80 | } |
81 | 81 | ||
82 | /* Interrupt Handlers */ | 82 | /* Interrupt Handlers */ |
83 | -struct omap_intr_handler_s { | ||
84 | - qemu_irq *pins; | ||
85 | - qemu_irq *parent_pic; | ||
86 | - target_phys_addr_t base; | ||
87 | - | ||
88 | - /* state */ | 83 | +struct omap_intr_handler_bank_s { |
89 | uint32_t irqs; | 84 | uint32_t irqs; |
85 | + uint32_t inputs; | ||
90 | uint32_t mask; | 86 | uint32_t mask; |
91 | - uint32_t sens_edge; | ||
92 | uint32_t fiq; | 87 | uint32_t fiq; |
93 | - int priority[32]; | ||
94 | - uint32_t new_irq_agr; | ||
95 | - uint32_t new_fiq_agr; | ||
96 | - int sir_irq; | ||
97 | - int sir_fiq; | ||
98 | - int stats[32]; | 88 | + uint32_t sens_edge; |
89 | + unsigned char priority[32]; | ||
99 | }; | 90 | }; |
100 | 91 | ||
101 | -static void omap_inth_update(struct omap_intr_handler_s *s) | ||
102 | -{ | ||
103 | - uint32_t irq = s->irqs & ~s->mask & ~s->fiq; | ||
104 | - uint32_t fiq = s->irqs & ~s->mask & s->fiq; | 92 | +struct omap_intr_handler_s { |
93 | + qemu_irq *pins; | ||
94 | + qemu_irq parent_intr[2]; | ||
95 | + target_phys_addr_t base; | ||
96 | + unsigned char nbanks; | ||
105 | 97 | ||
106 | - if (s->new_irq_agr || !irq) { | ||
107 | - qemu_set_irq(s->parent_pic[ARM_PIC_CPU_IRQ], irq); | ||
108 | - if (irq) | ||
109 | - s->new_irq_agr = 0; | ||
110 | - } | 98 | + /* state */ |
99 | + uint32_t new_agr[2]; | ||
100 | + int sir_intr[2]; | ||
101 | + struct omap_intr_handler_bank_s banks[]; | ||
102 | +}; | ||
111 | 103 | ||
112 | - if (s->new_fiq_agr || !irq) { | ||
113 | - qemu_set_irq(s->parent_pic[ARM_PIC_CPU_FIQ], fiq); | ||
114 | - if (fiq) | ||
115 | - s->new_fiq_agr = 0; | 104 | +static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq) |
105 | +{ | ||
106 | + int i, j, sir_intr, p_intr, p, f; | ||
107 | + uint32_t level; | ||
108 | + sir_intr = 0; | ||
109 | + p_intr = 255; | ||
110 | + | ||
111 | + /* Find the interrupt line with the highest dynamic priority. | ||
112 | + * Note: 0 denotes the hightest priority. | ||
113 | + * If all interrupts have the same priority, the default order is IRQ_N, | ||
114 | + * IRQ_N-1,...,IRQ_0. */ | ||
115 | + for (j = 0; j < s->nbanks; ++j) { | ||
116 | + level = s->banks[j].irqs & ~s->banks[j].mask & | ||
117 | + (is_fiq ? s->banks[j].fiq : ~s->banks[j].fiq); | ||
118 | + for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f, | ||
119 | + level >>= f) { | ||
120 | + p = s->banks[j].priority[i]; | ||
121 | + if (p <= p_intr) { | ||
122 | + p_intr = p; | ||
123 | + sir_intr = 32 * j + i; | ||
124 | + } | ||
125 | + f = ffs(level >> 1); | ||
126 | + } | ||
116 | } | 127 | } |
128 | + s->sir_intr[is_fiq] = sir_intr; | ||
117 | } | 129 | } |
118 | 130 | ||
119 | -static void omap_inth_sir_update(struct omap_intr_handler_s *s) | 131 | +static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq) |
120 | { | 132 | { |
121 | - int i, intr_irq, intr_fiq, p_irq, p_fiq, p, f; | ||
122 | - uint32_t level = s->irqs & ~s->mask; | 133 | + int i; |
134 | + uint32_t has_intr = 0; | ||
123 | 135 | ||
124 | - intr_irq = 0; | ||
125 | - intr_fiq = 0; | ||
126 | - p_irq = -1; | ||
127 | - p_fiq = -1; | ||
128 | - /* Find the interrupt line with the highest dynamic priority */ | ||
129 | - for (f = ffs(level), i = f - 1, level >>= f - 1; f; i += f, level >>= f) { | ||
130 | - p = s->priority[i]; | ||
131 | - if (s->fiq & (1 << i)) { | ||
132 | - if (p > p_fiq) { | ||
133 | - p_fiq = p; | ||
134 | - intr_fiq = i; | ||
135 | - } | ||
136 | - } else { | ||
137 | - if (p > p_irq) { | ||
138 | - p_irq = p; | ||
139 | - intr_irq = i; | ||
140 | - } | ||
141 | - } | 136 | + for (i = 0; i < s->nbanks; ++i) |
137 | + has_intr |= s->banks[i].irqs & ~s->banks[i].mask & | ||
138 | + (is_fiq ? s->banks[i].fiq : ~s->banks[i].fiq); | ||
142 | 139 | ||
143 | - f = ffs(level >> 1); | 140 | + if (s->new_agr[is_fiq] && has_intr) { |
141 | + s->new_agr[is_fiq] = 0; | ||
142 | + omap_inth_sir_update(s, is_fiq); | ||
143 | + qemu_set_irq(s->parent_intr[is_fiq], 1); | ||
144 | } | 144 | } |
145 | - | ||
146 | - s->sir_irq = intr_irq; | ||
147 | - s->sir_fiq = intr_fiq; | ||
148 | } | 145 | } |
149 | 146 | ||
150 | #define INT_FALLING_EDGE 0 | 147 | #define INT_FALLING_EDGE 0 |
@@ -155,19 +152,24 @@ static void omap_set_intr(void *opaque, int irq, int req) | @@ -155,19 +152,24 @@ static void omap_set_intr(void *opaque, int irq, int req) | ||
155 | struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; | 152 | struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque; |
156 | uint32_t rise; | 153 | uint32_t rise; |
157 | 154 | ||
155 | + struct omap_intr_handler_bank_s *bank = &ih->banks[irq >> 5]; | ||
156 | + int n = irq & 31; | ||
157 | + | ||
158 | if (req) { | 158 | if (req) { |
159 | - rise = ~ih->irqs & (1 << irq); | ||
160 | - ih->irqs |= rise; | ||
161 | - ih->stats[irq] += !!rise; | 159 | + rise = ~bank->irqs & (1 << n); |
160 | + if (~bank->sens_edge & (1 << n)) | ||
161 | + rise &= ~bank->inputs & (1 << n); | ||
162 | + | ||
163 | + bank->inputs |= (1 << n); | ||
164 | + if (rise) { | ||
165 | + bank->irqs |= rise; | ||
166 | + omap_inth_update(ih, 0); | ||
167 | + omap_inth_update(ih, 1); | ||
168 | + } | ||
162 | } else { | 169 | } else { |
163 | - rise = ih->sens_edge & ih->irqs & (1 << irq); | ||
164 | - ih->irqs &= ~rise; | ||
165 | - } | ||
166 | - | ||
167 | - if (rise & ~ih->mask) { | ||
168 | - omap_inth_sir_update(ih); | ||
169 | - | ||
170 | - omap_inth_update(ih); | 170 | + rise = bank->sens_edge & bank->irqs & (1 << n); |
171 | + bank->irqs &= ~rise; | ||
172 | + bank->inputs &= ~(1 << n); | ||
171 | } | 173 | } |
172 | } | 174 | } |
173 | 175 | ||
@@ -175,33 +177,32 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) | @@ -175,33 +177,32 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) | ||
175 | { | 177 | { |
176 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; | 178 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; |
177 | int i, offset = addr - s->base; | 179 | int i, offset = addr - s->base; |
180 | + int bank_no = offset >> 8; | ||
181 | + int line_no; | ||
182 | + struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; | ||
183 | + offset &= 0xff; | ||
178 | 184 | ||
179 | switch (offset) { | 185 | switch (offset) { |
180 | case 0x00: /* ITR */ | 186 | case 0x00: /* ITR */ |
181 | - return s->irqs; | 187 | + return bank->irqs; |
182 | 188 | ||
183 | case 0x04: /* MIR */ | 189 | case 0x04: /* MIR */ |
184 | - return s->mask; | 190 | + return bank->mask; |
185 | 191 | ||
186 | case 0x10: /* SIR_IRQ_CODE */ | 192 | case 0x10: /* SIR_IRQ_CODE */ |
187 | - i = s->sir_irq; | ||
188 | - if (((s->sens_edge >> i) & 1) == INT_FALLING_EDGE && i) { | ||
189 | - s->irqs &= ~(1 << i); | ||
190 | - omap_inth_sir_update(s); | ||
191 | - omap_inth_update(s); | ||
192 | - } | ||
193 | - return i; | ||
194 | - | ||
195 | - case 0x14: /* SIR_FIQ_CODE */ | ||
196 | - i = s->sir_fiq; | ||
197 | - if (((s->sens_edge >> i) & 1) == INT_FALLING_EDGE && i) { | ||
198 | - s->irqs &= ~(1 << i); | ||
199 | - omap_inth_sir_update(s); | ||
200 | - omap_inth_update(s); | ||
201 | - } | 193 | + case 0x14: /* SIR_FIQ_CODE */ |
194 | + if (bank_no != 0) | ||
195 | + break; | ||
196 | + line_no = s->sir_intr[(offset - 0x10) >> 2]; | ||
197 | + bank = &s->banks[line_no >> 5]; | ||
198 | + i = line_no & 31; | ||
199 | + if (((bank->sens_edge >> i) & 1) == INT_FALLING_EDGE) | ||
200 | + bank->irqs &= ~(1 << i); | ||
202 | return i; | 201 | return i; |
203 | 202 | ||
204 | case 0x18: /* CONTROL_REG */ | 203 | case 0x18: /* CONTROL_REG */ |
204 | + if (bank_no != 0) | ||
205 | + break; | ||
205 | return 0; | 206 | return 0; |
206 | 207 | ||
207 | case 0x1c: /* ILR0 */ | 208 | case 0x1c: /* ILR0 */ |
@@ -237,17 +238,15 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) | @@ -237,17 +238,15 @@ static uint32_t omap_inth_read(void *opaque, target_phys_addr_t addr) | ||
237 | case 0x94: /* ILR30 */ | 238 | case 0x94: /* ILR30 */ |
238 | case 0x98: /* ILR31 */ | 239 | case 0x98: /* ILR31 */ |
239 | i = (offset - 0x1c) >> 2; | 240 | i = (offset - 0x1c) >> 2; |
240 | - return (s->priority[i] << 2) | | ||
241 | - (((s->sens_edge >> i) & 1) << 1) | | ||
242 | - ((s->fiq >> i) & 1); | 241 | + return (bank->priority[i] << 2) | |
242 | + (((bank->sens_edge >> i) & 1) << 1) | | ||
243 | + ((bank->fiq >> i) & 1); | ||
243 | 244 | ||
244 | case 0x9c: /* ISR */ | 245 | case 0x9c: /* ISR */ |
245 | return 0x00000000; | 246 | return 0x00000000; |
246 | 247 | ||
247 | - default: | ||
248 | - OMAP_BAD_REG(addr); | ||
249 | - break; | ||
250 | } | 248 | } |
249 | + OMAP_BAD_REG(addr); | ||
251 | return 0; | 250 | return 0; |
252 | } | 251 | } |
253 | 252 | ||
@@ -256,18 +255,21 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | @@ -256,18 +255,21 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | ||
256 | { | 255 | { |
257 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; | 256 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque; |
258 | int i, offset = addr - s->base; | 257 | int i, offset = addr - s->base; |
258 | + int bank_no = offset >> 8; | ||
259 | + struct omap_intr_handler_bank_s *bank = &s->banks[bank_no]; | ||
260 | + offset &= 0xff; | ||
259 | 261 | ||
260 | switch (offset) { | 262 | switch (offset) { |
261 | case 0x00: /* ITR */ | 263 | case 0x00: /* ITR */ |
262 | - s->irqs &= value | 1; | ||
263 | - omap_inth_sir_update(s); | ||
264 | - omap_inth_update(s); | 264 | + /* Important: ignore the clearing if the IRQ is level-triggered and |
265 | + the input bit is 1 */ | ||
266 | + bank->irqs &= value | (bank->inputs & bank->sens_edge); | ||
265 | return; | 267 | return; |
266 | 268 | ||
267 | case 0x04: /* MIR */ | 269 | case 0x04: /* MIR */ |
268 | - s->mask = value; | ||
269 | - omap_inth_sir_update(s); | ||
270 | - omap_inth_update(s); | 270 | + bank->mask = value; |
271 | + omap_inth_update(s, 0); | ||
272 | + omap_inth_update(s, 1); | ||
271 | return; | 273 | return; |
272 | 274 | ||
273 | case 0x10: /* SIR_IRQ_CODE */ | 275 | case 0x10: /* SIR_IRQ_CODE */ |
@@ -276,11 +278,18 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | @@ -276,11 +278,18 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | ||
276 | break; | 278 | break; |
277 | 279 | ||
278 | case 0x18: /* CONTROL_REG */ | 280 | case 0x18: /* CONTROL_REG */ |
279 | - if (value & 2) | ||
280 | - s->new_fiq_agr = ~0; | ||
281 | - if (value & 1) | ||
282 | - s->new_irq_agr = ~0; | ||
283 | - omap_inth_update(s); | 281 | + if (bank_no != 0) |
282 | + break; | ||
283 | + if (value & 2) { | ||
284 | + qemu_set_irq(s->parent_intr[1], 0); | ||
285 | + s->new_agr[1] = ~0; | ||
286 | + omap_inth_update(s, 1); | ||
287 | + } | ||
288 | + if (value & 1) { | ||
289 | + qemu_set_irq(s->parent_intr[0], 0); | ||
290 | + s->new_agr[0] = ~0; | ||
291 | + omap_inth_update(s, 0); | ||
292 | + } | ||
284 | return; | 293 | return; |
285 | 294 | ||
286 | case 0x1c: /* ILR0 */ | 295 | case 0x1c: /* ILR0 */ |
@@ -316,24 +325,22 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | @@ -316,24 +325,22 @@ static void omap_inth_write(void *opaque, target_phys_addr_t addr, | ||
316 | case 0x94: /* ILR30 */ | 325 | case 0x94: /* ILR30 */ |
317 | case 0x98: /* ILR31 */ | 326 | case 0x98: /* ILR31 */ |
318 | i = (offset - 0x1c) >> 2; | 327 | i = (offset - 0x1c) >> 2; |
319 | - s->priority[i] = (value >> 2) & 0x1f; | ||
320 | - s->sens_edge &= ~(1 << i); | ||
321 | - s->sens_edge |= ((value >> 1) & 1) << i; | ||
322 | - s->fiq &= ~(1 << i); | ||
323 | - s->fiq |= (value & 1) << i; | 328 | + bank->priority[i] = (value >> 2) & 0x1f; |
329 | + bank->sens_edge &= ~(1 << i); | ||
330 | + bank->sens_edge |= ((value >> 1) & 1) << i; | ||
331 | + bank->fiq &= ~(1 << i); | ||
332 | + bank->fiq |= (value & 1) << i; | ||
324 | return; | 333 | return; |
325 | 334 | ||
326 | case 0x9c: /* ISR */ | 335 | case 0x9c: /* ISR */ |
327 | for (i = 0; i < 32; i ++) | 336 | for (i = 0; i < 32; i ++) |
328 | if (value & (1 << i)) { | 337 | if (value & (1 << i)) { |
329 | - omap_set_intr(s, i, 1); | 338 | + omap_set_intr(s, 32 * bank_no + i, 1); |
330 | return; | 339 | return; |
331 | } | 340 | } |
332 | return; | 341 | return; |
333 | - | ||
334 | - default: | ||
335 | - OMAP_BAD_REG(addr); | ||
336 | } | 342 | } |
343 | + OMAP_BAD_REG(addr); | ||
337 | } | 344 | } |
338 | 345 | ||
339 | static CPUReadMemoryFunc *omap_inth_readfn[] = { | 346 | static CPUReadMemoryFunc *omap_inth_readfn[] = { |
@@ -348,31 +355,43 @@ static CPUWriteMemoryFunc *omap_inth_writefn[] = { | @@ -348,31 +355,43 @@ static CPUWriteMemoryFunc *omap_inth_writefn[] = { | ||
348 | omap_inth_write, | 355 | omap_inth_write, |
349 | }; | 356 | }; |
350 | 357 | ||
351 | -static void omap_inth_reset(struct omap_intr_handler_s *s) | 358 | +void omap_inth_reset(struct omap_intr_handler_s *s) |
352 | { | 359 | { |
353 | - s->irqs = 0x00000000; | ||
354 | - s->mask = 0xffffffff; | ||
355 | - s->sens_edge = 0x00000000; | ||
356 | - s->fiq = 0x00000000; | ||
357 | - memset(s->priority, 0, sizeof(s->priority)); | ||
358 | - s->new_irq_agr = ~0; | ||
359 | - s->new_fiq_agr = ~0; | ||
360 | - s->sir_irq = 0; | ||
361 | - s->sir_fiq = 0; | 360 | + int i; |
361 | + | ||
362 | + for (i = 0; i < s->nbanks; ++i){ | ||
363 | + s->banks[i].irqs = 0x00000000; | ||
364 | + s->banks[i].mask = 0xffffffff; | ||
365 | + s->banks[i].sens_edge = 0x00000000; | ||
366 | + s->banks[i].fiq = 0x00000000; | ||
367 | + s->banks[i].inputs = 0x00000000; | ||
368 | + memset(s->banks[i].priority, 0, sizeof(s->banks[i].priority)); | ||
369 | + } | ||
362 | 370 | ||
363 | - omap_inth_update(s); | 371 | + s->new_agr[0] = ~0; |
372 | + s->new_agr[1] = ~0; | ||
373 | + s->sir_intr[0] = 0; | ||
374 | + s->sir_intr[1] = 0; | ||
375 | + | ||
376 | + qemu_set_irq(s->parent_intr[0], 0); | ||
377 | + qemu_set_irq(s->parent_intr[1], 0); | ||
364 | } | 378 | } |
365 | 379 | ||
366 | struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, | 380 | struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, |
367 | - unsigned long size, qemu_irq parent[2], omap_clk clk) | 381 | + unsigned long size, unsigned char nbanks, |
382 | + qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk) | ||
368 | { | 383 | { |
369 | int iomemtype; | 384 | int iomemtype; |
370 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) | 385 | struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) |
371 | - qemu_mallocz(sizeof(struct omap_intr_handler_s)); | 386 | + qemu_mallocz(sizeof(struct omap_intr_handler_s) + |
387 | + sizeof(struct omap_intr_handler_bank_s) * nbanks); | ||
372 | 388 | ||
373 | - s->parent_pic = parent; | 389 | + s->parent_intr[0] = parent_irq; |
390 | + s->parent_intr[1] = parent_fiq; | ||
374 | s->base = base; | 391 | s->base = base; |
375 | - s->pins = qemu_allocate_irqs(omap_set_intr, s, 32); | 392 | + s->nbanks = nbanks; |
393 | + s->pins = qemu_allocate_irqs(omap_set_intr, s, nbanks * 32); | ||
394 | + | ||
376 | omap_inth_reset(s); | 395 | omap_inth_reset(s); |
377 | 396 | ||
378 | iomemtype = cpu_register_io_memory(0, omap_inth_readfn, | 397 | iomemtype = cpu_register_io_memory(0, omap_inth_readfn, |
@@ -1144,7 +1163,8 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer) | @@ -1144,7 +1163,8 @@ static inline void omap_timer_update(struct omap_mpu_timer_s *timer) | ||
1144 | timer->val = 0; | 1163 | timer->val = 0; |
1145 | timer->st = 0; | 1164 | timer->st = 0; |
1146 | if (timer->it_ena) | 1165 | if (timer->it_ena) |
1147 | - qemu_irq_raise(timer->irq); | 1166 | + /* Edge-triggered irq */ |
1167 | + qemu_irq_pulse(timer->irq); | ||
1148 | } | 1168 | } |
1149 | } else | 1169 | } else |
1150 | qemu_del_timer(timer->timer); | 1170 | qemu_del_timer(timer->timer); |
@@ -1161,7 +1181,8 @@ static void omap_timer_tick(void *opaque) | @@ -1161,7 +1181,8 @@ static void omap_timer_tick(void *opaque) | ||
1161 | } | 1181 | } |
1162 | 1182 | ||
1163 | if (timer->it_ena) | 1183 | if (timer->it_ena) |
1164 | - qemu_irq_raise(timer->irq); | 1184 | + /* Edge-triggered irq */ |
1185 | + qemu_irq_pulse(timer->irq); | ||
1165 | omap_timer_update(timer); | 1186 | omap_timer_update(timer); |
1166 | } | 1187 | } |
1167 | 1188 | ||
@@ -3678,6 +3699,7 @@ struct omap_rtc_s { | @@ -3678,6 +3699,7 @@ struct omap_rtc_s { | ||
3678 | 3699 | ||
3679 | static void omap_rtc_interrupts_update(struct omap_rtc_s *s) | 3700 | static void omap_rtc_interrupts_update(struct omap_rtc_s *s) |
3680 | { | 3701 | { |
3702 | + /* s->alarm is level-triggered */ | ||
3681 | qemu_set_irq(s->alarm, (s->status >> 6) & 1); | 3703 | qemu_set_irq(s->alarm, (s->status >> 6) & 1); |
3682 | } | 3704 | } |
3683 | 3705 | ||
@@ -4000,26 +4022,26 @@ static void omap_rtc_tick(void *opaque) | @@ -4000,26 +4022,26 @@ static void omap_rtc_tick(void *opaque) | ||
4000 | switch (s->interrupts & 3) { | 4022 | switch (s->interrupts & 3) { |
4001 | case 0: | 4023 | case 0: |
4002 | s->status |= 0x04; | 4024 | s->status |= 0x04; |
4003 | - qemu_irq_raise(s->irq); | 4025 | + qemu_irq_pulse(s->irq); |
4004 | break; | 4026 | break; |
4005 | case 1: | 4027 | case 1: |
4006 | if (s->current_tm.tm_sec) | 4028 | if (s->current_tm.tm_sec) |
4007 | break; | 4029 | break; |
4008 | s->status |= 0x08; | 4030 | s->status |= 0x08; |
4009 | - qemu_irq_raise(s->irq); | 4031 | + qemu_irq_pulse(s->irq); |
4010 | break; | 4032 | break; |
4011 | case 2: | 4033 | case 2: |
4012 | if (s->current_tm.tm_sec || s->current_tm.tm_min) | 4034 | if (s->current_tm.tm_sec || s->current_tm.tm_min) |
4013 | break; | 4035 | break; |
4014 | s->status |= 0x10; | 4036 | s->status |= 0x10; |
4015 | - qemu_irq_raise(s->irq); | 4037 | + qemu_irq_pulse(s->irq); |
4016 | break; | 4038 | break; |
4017 | case 3: | 4039 | case 3: |
4018 | if (s->current_tm.tm_sec || | 4040 | if (s->current_tm.tm_sec || |
4019 | s->current_tm.tm_min || s->current_tm.tm_hour) | 4041 | s->current_tm.tm_min || s->current_tm.tm_hour) |
4020 | break; | 4042 | break; |
4021 | s->status |= 0x20; | 4043 | s->status |= 0x20; |
4022 | - qemu_irq_raise(s->irq); | 4044 | + qemu_irq_pulse(s->irq); |
4023 | break; | 4045 | break; |
4024 | } | 4046 | } |
4025 | 4047 | ||
@@ -4121,7 +4143,8 @@ static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | @@ -4121,7 +4143,8 @@ static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | ||
4121 | break; | 4143 | break; |
4122 | } | 4144 | } |
4123 | 4145 | ||
4124 | - qemu_set_irq(s->rxirq, irq); | 4146 | + if (irq) |
4147 | + qemu_irq_pulse(s->rxirq); | ||
4125 | 4148 | ||
4126 | switch ((s->spcr[1] >> 4) & 3) { /* XINTM */ | 4149 | switch ((s->spcr[1] >> 4) & 3) { /* XINTM */ |
4127 | case 0: | 4150 | case 0: |
@@ -4135,7 +4158,8 @@ static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | @@ -4135,7 +4158,8 @@ static void omap_mcbsp_intr_update(struct omap_mcbsp_s *s) | ||
4135 | break; | 4158 | break; |
4136 | } | 4159 | } |
4137 | 4160 | ||
4138 | - qemu_set_irq(s->txirq, irq); | 4161 | + if (irq) |
4162 | + qemu_irq_pulse(s->txirq); | ||
4139 | } | 4163 | } |
4140 | 4164 | ||
4141 | static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s) | 4165 | static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s) |
@@ -4901,8 +4925,9 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -4901,8 +4925,9 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4901 | struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) | 4925 | struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) |
4902 | qemu_mallocz(sizeof(struct omap_mpu_state_s)); | 4926 | qemu_mallocz(sizeof(struct omap_mpu_state_s)); |
4903 | ram_addr_t imif_base, emiff_base; | 4927 | ram_addr_t imif_base, emiff_base; |
4928 | + qemu_irq *cpu_irq; | ||
4904 | int sdindex; | 4929 | int sdindex; |
4905 | - | 4930 | + |
4906 | if (!core) | 4931 | if (!core) |
4907 | core = "ti925t"; | 4932 | core = "ti925t"; |
4908 | 4933 | ||
@@ -4929,11 +4954,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | @@ -4929,11 +4954,12 @@ struct omap_mpu_state_s *omap310_mpu_init(unsigned long sdram_size, | ||
4929 | 4954 | ||
4930 | omap_clkm_init(0xfffece00, 0xe1008000, s); | 4955 | omap_clkm_init(0xfffece00, 0xe1008000, s); |
4931 | 4956 | ||
4932 | - s->ih[0] = omap_inth_init(0xfffecb00, 0x100, | ||
4933 | - arm_pic_init_cpu(s->env), | 4957 | + cpu_irq = arm_pic_init_cpu(s->env); |
4958 | + s->ih[0] = omap_inth_init(0xfffecb00, 0x100, 1, | ||
4959 | + cpu_irq[ARM_PIC_CPU_IRQ], cpu_irq[ARM_PIC_CPU_FIQ], | ||
4934 | omap_findclk(s, "arminth_ck")); | 4960 | omap_findclk(s, "arminth_ck")); |
4935 | - s->ih[1] = omap_inth_init(0xfffe0000, 0x800, | ||
4936 | - &s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], | 4961 | + s->ih[1] = omap_inth_init(0xfffe0000, 0x800, 1, |
4962 | + s->ih[0]->pins[OMAP_INT_15XX_IH2_IRQ], NULL, | ||
4937 | omap_findclk(s, "arminth_ck")); | 4963 | omap_findclk(s, "arminth_ck")); |
4938 | s->irq[0] = s->ih[0]->pins; | 4964 | s->irq[0] = s->ih[0]->pins; |
4939 | s->irq[1] = s->ih[1]->pins; | 4965 | s->irq[1] = s->ih[1]->pins; |
hw/omap.h
@@ -57,7 +57,8 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent); | @@ -57,7 +57,8 @@ void omap_clk_reparent(omap_clk clk, omap_clk parent); | ||
57 | /* omap.c */ | 57 | /* omap.c */ |
58 | struct omap_intr_handler_s; | 58 | struct omap_intr_handler_s; |
59 | struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, | 59 | struct omap_intr_handler_s *omap_inth_init(target_phys_addr_t base, |
60 | - unsigned long size, qemu_irq parent[2], omap_clk clk); | 60 | + unsigned long size, unsigned char nbanks, |
61 | + qemu_irq parent_irq, qemu_irq parent_fiq, omap_clk clk); | ||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * Common IRQ numbers for level 1 interrupt handler | 64 | * Common IRQ numbers for level 1 interrupt handler |