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 |