Revision 106627d0 hw/omap.c

b/hw/omap.c
80 80
}
81 81

  
82 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 84
    uint32_t irqs;
85
    uint32_t inputs;
90 86
    uint32_t mask;
91
    uint32_t sens_edge;
92 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 147
#define INT_FALLING_EDGE	0
......
155 152
    struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
156 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 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 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 177
{
176 178
    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
177 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 185
    switch (offset) {
180 186
    case 0x00:	/* ITR */
181
        return s->irqs;
187
        return bank->irqs;
182 188

  
183 189
    case 0x04:	/* MIR */
184
        return s->mask;
190
        return bank->mask;
185 191

  
186 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 201
        return i;
203 202

  
204 203
    case 0x18:	/* CONTROL_REG */
204
        if (bank_no != 0)
205
            break;
205 206
        return 0;
206 207

  
207 208
    case 0x1c:	/* ILR0 */
......
237 238
    case 0x94:	/* ILR30 */
238 239
    case 0x98:	/* ILR31 */
239 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 245
    case 0x9c:	/* ISR */
245 246
        return 0x00000000;
246 247

  
247
    default:
248
        OMAP_BAD_REG(addr);
249
        break;
250 248
    }
249
    OMAP_BAD_REG(addr);
251 250
    return 0;
252 251
}
253 252

  
......
256 255
{
257 256
    struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
258 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 262
    switch (offset) {
261 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 267
        return;
266 268

  
267 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 273
        return;
272 274

  
273 275
    case 0x10:	/* SIR_IRQ_CODE */
......
276 278
        break;
277 279

  
278 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 293
        return;
285 294

  
286 295
    case 0x1c:	/* ILR0 */
......
316 325
    case 0x94:	/* ILR30 */
317 326
    case 0x98:	/* ILR31 */
318 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 333
        return;
325 334

  
326 335
    case 0x9c:	/* ISR */
327 336
        for (i = 0; i < 32; i ++)
328 337
            if (value & (1 << i)) {
329
                omap_set_intr(s, i, 1);
338
                omap_set_intr(s, 32 * bank_no + i, 1);
330 339
                return;
331 340
            }
332 341
        return;
333

  
334
    default:
335
        OMAP_BAD_REG(addr);
336 342
    }
343
    OMAP_BAD_REG(addr);
337 344
}
338 345

  
339 346
static CPUReadMemoryFunc *omap_inth_readfn[] = {
......
348 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 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 384
    int iomemtype;
370 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 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 395
    omap_inth_reset(s);
377 396

  
378 397
    iomemtype = cpu_register_io_memory(0, omap_inth_readfn,
......
1144 1163
            timer->val = 0;
1145 1164
            timer->st = 0;
1146 1165
            if (timer->it_ena)
1147
                qemu_irq_raise(timer->irq);
1166
                /* Edge-triggered irq */
1167
                qemu_irq_pulse(timer->irq);
1148 1168
        }
1149 1169
    } else
1150 1170
        qemu_del_timer(timer->timer);
......
1161 1181
    }
1162 1182

  
1163 1183
    if (timer->it_ena)
1164
        qemu_irq_raise(timer->irq);
1184
        /* Edge-triggered irq */
1185
        qemu_irq_pulse(timer->irq);
1165 1186
    omap_timer_update(timer);
1166 1187
}
1167 1188

  
......
3678 3699

  
3679 3700
static void omap_rtc_interrupts_update(struct omap_rtc_s *s)
3680 3701
{
3702
    /* s->alarm is level-triggered */
3681 3703
    qemu_set_irq(s->alarm, (s->status >> 6) & 1);
3682 3704
}
3683 3705

  
......
4000 4022
        switch (s->interrupts & 3) {
4001 4023
        case 0:
4002 4024
            s->status |= 0x04;
4003
            qemu_irq_raise(s->irq);
4025
            qemu_irq_pulse(s->irq);
4004 4026
            break;
4005 4027
        case 1:
4006 4028
            if (s->current_tm.tm_sec)
4007 4029
                break;
4008 4030
            s->status |= 0x08;
4009
            qemu_irq_raise(s->irq);
4031
            qemu_irq_pulse(s->irq);
4010 4032
            break;
4011 4033
        case 2:
4012 4034
            if (s->current_tm.tm_sec || s->current_tm.tm_min)
4013 4035
                break;
4014 4036
            s->status |= 0x10;
4015
            qemu_irq_raise(s->irq);
4037
            qemu_irq_pulse(s->irq);
4016 4038
            break;
4017 4039
        case 3:
4018 4040
            if (s->current_tm.tm_sec ||
4019 4041
                            s->current_tm.tm_min || s->current_tm.tm_hour)
4020 4042
                break;
4021 4043
            s->status |= 0x20;
4022
            qemu_irq_raise(s->irq);
4044
            qemu_irq_pulse(s->irq);
4023 4045
            break;
4024 4046
        }
4025 4047

  
......
4121 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 4149
    switch ((s->spcr[1] >> 4) & 3) {			/* XINTM */
4127 4150
    case 0:
......
4135 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 4165
static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
......
4901 4925
    struct omap_mpu_state_s *s = (struct omap_mpu_state_s *)
4902 4926
            qemu_mallocz(sizeof(struct omap_mpu_state_s));
4903 4927
    ram_addr_t imif_base, emiff_base;
4928
    qemu_irq *cpu_irq;
4904 4929
    int sdindex;
4905
    
4930

  
4906 4931
    if (!core)
4907 4932
        core = "ti925t";
4908 4933

  
......
4929 4954

  
4930 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 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 4963
                    omap_findclk(s, "arminth_ck"));
4938 4964
    s->irq[0] = s->ih[0]->pins;
4939 4965
    s->irq[1] = s->ih[1]->pins;

Also available in: Unified diff