~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/arm/common/gic.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
 * Default make them NULL.
50
50
 */
51
51
struct irq_chip gic_arch_extn = {
52
 
        .irq_ack        = NULL,
 
52
        .irq_eoi        = NULL,
53
53
        .irq_mask       = NULL,
54
54
        .irq_unmask     = NULL,
55
55
        .irq_retrigger  = NULL,
84
84
/*
85
85
 * Routines to acknowledge, disable and enable interrupts
86
86
 */
87
 
static void gic_ack_irq(struct irq_data *d)
88
 
{
89
 
        spin_lock(&irq_controller_lock);
90
 
        if (gic_arch_extn.irq_ack)
91
 
                gic_arch_extn.irq_ack(d);
92
 
        writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
93
 
        spin_unlock(&irq_controller_lock);
94
 
}
95
 
 
96
87
static void gic_mask_irq(struct irq_data *d)
97
88
{
98
89
        u32 mask = 1 << (d->irq % 32);
99
90
 
100
91
        spin_lock(&irq_controller_lock);
101
 
        writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
 
92
        writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
102
93
        if (gic_arch_extn.irq_mask)
103
94
                gic_arch_extn.irq_mask(d);
104
95
        spin_unlock(&irq_controller_lock);
111
102
        spin_lock(&irq_controller_lock);
112
103
        if (gic_arch_extn.irq_unmask)
113
104
                gic_arch_extn.irq_unmask(d);
114
 
        writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
 
105
        writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
115
106
        spin_unlock(&irq_controller_lock);
116
107
}
117
108
 
 
109
static void gic_eoi_irq(struct irq_data *d)
 
110
{
 
111
        if (gic_arch_extn.irq_eoi) {
 
112
                spin_lock(&irq_controller_lock);
 
113
                gic_arch_extn.irq_eoi(d);
 
114
                spin_unlock(&irq_controller_lock);
 
115
        }
 
116
 
 
117
        writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 
118
}
 
119
 
118
120
static int gic_set_type(struct irq_data *d, unsigned int type)
119
121
{
120
122
        void __iomem *base = gic_dist_base(d);
138
140
        if (gic_arch_extn.irq_set_type)
139
141
                gic_arch_extn.irq_set_type(d, type);
140
142
 
141
 
        val = readl(base + GIC_DIST_CONFIG + confoff);
 
143
        val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
142
144
        if (type == IRQ_TYPE_LEVEL_HIGH)
143
145
                val &= ~confmask;
144
146
        else if (type == IRQ_TYPE_EDGE_RISING)
148
150
         * As recommended by the spec, disable the interrupt before changing
149
151
         * the configuration
150
152
         */
151
 
        if (readl(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
152
 
                writel(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
 
153
        if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
 
154
                writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
153
155
                enabled = true;
154
156
        }
155
157
 
156
 
        writel(val, base + GIC_DIST_CONFIG + confoff);
 
158
        writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
157
159
 
158
160
        if (enabled)
159
 
                writel(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
 
161
                writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
160
162
 
161
163
        spin_unlock(&irq_controller_lock);
162
164
 
188
190
 
189
191
        spin_lock(&irq_controller_lock);
190
192
        d->node = cpu;
191
 
        val = readl(reg) & ~mask;
192
 
        writel(val | bit, reg);
 
193
        val = readl_relaxed(reg) & ~mask;
 
194
        writel_relaxed(val | bit, reg);
193
195
        spin_unlock(&irq_controller_lock);
194
196
 
195
197
        return 0;
213
215
 
214
216
static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
215
217
{
216
 
        struct gic_chip_data *chip_data = get_irq_data(irq);
217
 
        struct irq_chip *chip = get_irq_chip(irq);
 
218
        struct gic_chip_data *chip_data = irq_get_handler_data(irq);
 
219
        struct irq_chip *chip = irq_get_chip(irq);
218
220
        unsigned int cascade_irq, gic_irq;
219
221
        unsigned long status;
220
222
 
221
 
        /* primary controller ack'ing */
222
 
        chip->irq_ack(&desc->irq_data);
 
223
        chained_irq_enter(chip, desc);
223
224
 
224
225
        spin_lock(&irq_controller_lock);
225
 
        status = readl(chip_data->cpu_base + GIC_CPU_INTACK);
 
226
        status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
226
227
        spin_unlock(&irq_controller_lock);
227
228
 
228
229
        gic_irq = (status & 0x3ff);
236
237
                generic_handle_irq(cascade_irq);
237
238
 
238
239
 out:
239
 
        /* primary controller unmasking */
240
 
        chip->irq_unmask(&desc->irq_data);
 
240
        chained_irq_exit(chip, desc);
241
241
}
242
242
 
243
243
static struct irq_chip gic_chip = {
244
244
        .name                   = "GIC",
245
 
        .irq_ack                = gic_ack_irq,
246
245
        .irq_mask               = gic_mask_irq,
247
246
        .irq_unmask             = gic_unmask_irq,
 
247
        .irq_eoi                = gic_eoi_irq,
248
248
        .irq_set_type           = gic_set_type,
249
249
        .irq_retrigger          = gic_retrigger,
250
250
#ifdef CONFIG_SMP
257
257
{
258
258
        if (gic_nr >= MAX_GIC_NR)
259
259
                BUG();
260
 
        if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
 
260
        if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
261
261
                BUG();
262
 
        set_irq_chained_handler(irq, gic_handle_cascade_irq);
 
262
        irq_set_chained_handler(irq, gic_handle_cascade_irq);
263
263
}
264
264
 
265
265
static void __init gic_dist_init(struct gic_chip_data *gic,
269
269
        void __iomem *base = gic->dist_base;
270
270
        u32 cpumask = 1 << smp_processor_id();
271
271
 
272
 
        /*
273
 
         * HACK: Panda sound does not work with gic_set_type
274
 
         * enabled.  Kill it on Omap44xx until a proper fix is
275
 
         * available
276
 
         */
277
 
 
278
 
        if (cpu_is_omap44xx())
279
 
                gic_chip.irq_set_type = NULL;
280
 
 
281
272
        cpumask |= cpumask << 8;
282
273
        cpumask |= cpumask << 16;
283
274
 
284
 
        writel(0, base + GIC_DIST_CTRL);
 
275
        writel_relaxed(0, base + GIC_DIST_CTRL);
285
276
 
286
277
        /*
287
278
         * Find out how many interrupts are supported.
288
279
         * The GIC only supports up to 1020 interrupt sources.
289
280
         */
290
 
        gic_irqs = readl(base + GIC_DIST_CTR) & 0x1f;
 
281
        gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
291
282
        gic_irqs = (gic_irqs + 1) * 32;
292
283
        if (gic_irqs > 1020)
293
284
                gic_irqs = 1020;
296
287
         * Set all global interrupts to be level triggered, active low.
297
288
         */
298
289
        for (i = 32; i < gic_irqs; i += 16)
299
 
                writel(0, base + GIC_DIST_CONFIG + i * 4 / 16);
 
290
                writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
300
291
 
301
292
        /*
302
293
         * Set all global interrupts to this CPU only.
303
294
         */
304
295
        for (i = 32; i < gic_irqs; i += 4)
305
 
                writel(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
 
296
                writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
306
297
 
307
298
        /*
308
299
         * Set priority on all global interrupts.
309
300
         */
310
301
        for (i = 32; i < gic_irqs; i += 4)
311
 
                writel(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
 
302
                writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
312
303
 
313
304
        /*
314
305
         * Disable all interrupts.  Leave the PPI and SGIs alone
315
306
         * as these enables are banked registers.
316
307
         */
317
308
        for (i = 32; i < gic_irqs; i += 32)
318
 
                writel(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
 
309
                writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
319
310
 
320
311
        /*
321
312
         * Limit number of interrupts registered to the platform maximum
328
319
         * Setup the Linux IRQ subsystem.
329
320
         */
330
321
        for (i = irq_start; i < irq_limit; i++) {
331
 
                set_irq_chip(i, &gic_chip);
332
 
                set_irq_chip_data(i, gic);
333
 
                set_irq_handler(i, handle_level_irq);
 
322
                irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
 
323
                irq_set_chip_data(i, gic);
334
324
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
335
325
        }
336
326
 
337
 
        writel(1, base + GIC_DIST_CTRL);
 
327
        writel_relaxed(1, base + GIC_DIST_CTRL);
338
328
}
339
329
 
340
330
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
347
337
         * Deal with the banked PPI and SGI interrupts - disable all
348
338
         * PPI interrupts, ensure all SGI interrupts are enabled.
349
339
         */
350
 
        writel(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
351
 
        writel(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
 
340
        writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
 
341
        writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
352
342
 
353
343
        /*
354
344
         * Set priority on PPI and SGI interrupts
355
345
         */
356
346
        for (i = 0; i < 32; i += 4)
357
 
                writel(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
 
347
                writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
358
348
 
359
 
        writel(0xf0, base + GIC_CPU_PRIMASK);
360
 
        writel(1, base + GIC_CPU_CTRL);
 
349
        writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
 
350
        writel_relaxed(1, base + GIC_CPU_CTRL);
361
351
}
362
352
 
363
353
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
391
381
        unsigned long flags;
392
382
 
393
383
        local_irq_save(flags);
394
 
        irq_to_desc(irq)->status |= IRQ_NOPROBE;
 
384
        irq_set_status_flags(irq, IRQ_NOPROBE);
395
385
        gic_unmask_irq(irq_get_irq_data(irq));
396
386
        local_irq_restore(flags);
397
387
}
401
391
{
402
392
        unsigned long map = *cpus_addr(*mask);
403
393
 
 
394
        /*
 
395
         * Ensure that stores to Normal memory are visible to the
 
396
         * other CPUs before issuing the IPI.
 
397
         */
 
398
        dsb();
 
399
 
404
400
        /* this always happens on GIC0 */
405
 
        writel(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
 
401
        writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
406
402
}
407
403
#endif