gic.c 14.5 KB
Newer Older
Russell King's avatar
Russell King committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 *  linux/arch/arm/common/gic.c
 *
 *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Interrupt architecture for the GIC:
 *
 * o There is one Interrupt Distributor, which receives interrupts
 *   from system devices and sends them to the Interrupt Controllers.
 *
 * o There is one CPU Interface per CPU, which sends interrupts sent
 *   by the Distributor, and interrupts generated locally, to the
17 18 19
 *   associated CPU. The base address of the CPU interface is usually
 *   aliased so that the same address points to different chips depending
 *   on the CPU it is accessed from.
Russell King's avatar
Russell King committed
20 21 22 23 24 25 26 27 28
 *
 * Note that IRQs 0-31 are special - they are local to each CPU.
 * As such, the enable set/clear, pending set/clear and active bit
 * registers are banked per-cpu for these sources.
 */
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/smp.h>
29
#include <linux/cpu_pm.h>
30
#include <linux/cpumask.h>
31
#include <linux/io.h>
Russell King's avatar
Russell King committed
32 33 34 35 36

#include <asm/irq.h>
#include <asm/mach/irq.h>
#include <asm/hardware/gic.h>

37
static DEFINE_SPINLOCK(irq_controller_lock);
Russell King's avatar
Russell King committed
38

39
/* Address of GIC 0 CPU interface */
40
void __iomem *gic_cpu_base_addr __read_mostly;
41

42 43 44 45 46
/*
 * Supported arch specific GIC irq extension.
 * Default make them NULL.
 */
struct irq_chip gic_arch_extn = {
47
	.irq_eoi	= NULL,
48 49 50 51 52 53 54
	.irq_mask	= NULL,
	.irq_unmask	= NULL,
	.irq_retrigger	= NULL,
	.irq_set_type	= NULL,
	.irq_set_wake	= NULL,
};

55 56 57 58
#ifndef MAX_GIC_NR
#define MAX_GIC_NR	1
#endif

59
static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
60

61
static inline void __iomem *gic_dist_base(struct irq_data *d)
62
{
63
	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
64 65 66
	return gic_data->dist_base;
}

67
static inline void __iomem *gic_cpu_base(struct irq_data *d)
68
{
69
	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
70 71 72
	return gic_data->cpu_base;
}

73
static inline unsigned int gic_irq(struct irq_data *d)
74
{
75 76
	struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d);
	return d->irq - gic_data->irq_offset;
77 78
}

Russell King's avatar
Russell King committed
79 80 81
/*
 * Routines to acknowledge, disable and enable interrupts
 */
82
static void gic_mask_irq(struct irq_data *d)
Russell King's avatar
Russell King committed
83
{
84
	u32 mask = 1 << (d->irq % 32);
85 86

	spin_lock(&irq_controller_lock);
87
	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
88 89
	if (gic_arch_extn.irq_mask)
		gic_arch_extn.irq_mask(d);
90
	spin_unlock(&irq_controller_lock);
Russell King's avatar
Russell King committed
91 92
}

93
static void gic_unmask_irq(struct irq_data *d)
Russell King's avatar
Russell King committed
94
{
95
	u32 mask = 1 << (d->irq % 32);
96 97

	spin_lock(&irq_controller_lock);
98 99
	if (gic_arch_extn.irq_unmask)
		gic_arch_extn.irq_unmask(d);
100
	writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
101
	spin_unlock(&irq_controller_lock);
Russell King's avatar
Russell King committed
102 103
}

104 105 106 107 108 109 110 111
static void gic_eoi_irq(struct irq_data *d)
{
	if (gic_arch_extn.irq_eoi) {
		spin_lock(&irq_controller_lock);
		gic_arch_extn.irq_eoi(d);
		spin_unlock(&irq_controller_lock);
	}

112
	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
113 114
}

115
static int gic_set_type(struct irq_data *d, unsigned int type)
116
{
117 118
	void __iomem *base = gic_dist_base(d);
	unsigned int gicirq = gic_irq(d);
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
	u32 enablemask = 1 << (gicirq % 32);
	u32 enableoff = (gicirq / 32) * 4;
	u32 confmask = 0x2 << ((gicirq % 16) * 2);
	u32 confoff = (gicirq / 16) * 4;
	bool enabled = false;
	u32 val;

	/* Interrupt configuration for SGIs can't be changed */
	if (gicirq < 16)
		return -EINVAL;

	if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
		return -EINVAL;

	spin_lock(&irq_controller_lock);

135 136 137
	if (gic_arch_extn.irq_set_type)
		gic_arch_extn.irq_set_type(d, type);

138
	val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
139 140 141 142 143 144 145 146 147
	if (type == IRQ_TYPE_LEVEL_HIGH)
		val &= ~confmask;
	else if (type == IRQ_TYPE_EDGE_RISING)
		val |= confmask;

	/*
	 * As recommended by the spec, disable the interrupt before changing
	 * the configuration
	 */
148 149
	if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
150 151 152
		enabled = true;
	}

153
	writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);
154 155

	if (enabled)
156
		writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);
157 158 159 160 161 162

	spin_unlock(&irq_controller_lock);

	return 0;
}

163 164 165 166 167 168 169 170
static int gic_retrigger(struct irq_data *d)
{
	if (gic_arch_extn.irq_retrigger)
		return gic_arch_extn.irq_retrigger(d);

	return -ENXIO;
}

171
#ifdef CONFIG_SMP
172 173
static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
			    bool force)
Russell King's avatar
Russell King committed
174
{
175 176
	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
	unsigned int shift = (d->irq % 4) * 8;
177
	unsigned int cpu = cpumask_any_and(mask_val, cpu_online_mask);
178
	u32 val, mask, bit;
Russell King's avatar
Russell King committed
179

180
	if (cpu >= 8 || cpu >= nr_cpu_ids)
181
		return -EINVAL;
182 183 184 185 186

	mask = 0xff << shift;
	bit = 1 << (cpu + shift);

	spin_lock(&irq_controller_lock);
187 188
	val = readl_relaxed(reg) & ~mask;
	writel_relaxed(val | bit, reg);
189
	spin_unlock(&irq_controller_lock);
190

191
	return IRQ_SET_MASK_OK;
Russell King's avatar
Russell King committed
192
}
193
#endif
Russell King's avatar
Russell King committed
194

195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
#ifdef CONFIG_PM
static int gic_set_wake(struct irq_data *d, unsigned int on)
{
	int ret = -ENXIO;

	if (gic_arch_extn.irq_set_wake)
		ret = gic_arch_extn.irq_set_wake(d, on);

	return ret;
}

#else
#define gic_set_wake	NULL
#endif

210
static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
211
{
212 213
	struct gic_chip_data *chip_data = irq_get_handler_data(irq);
	struct irq_chip *chip = irq_get_chip(irq);
214
	unsigned int cascade_irq, gic_irq;
215 216
	unsigned long status;

217
	chained_irq_enter(chip, desc);
218 219

	spin_lock(&irq_controller_lock);
220
	status = readl_relaxed(chip_data->cpu_base + GIC_CPU_INTACK);
221 222
	spin_unlock(&irq_controller_lock);

223 224
	gic_irq = (status & 0x3ff);
	if (gic_irq == 1023)
225 226
		goto out;

227 228 229 230 231
	cascade_irq = gic_irq + chip_data->irq_offset;
	if (unlikely(gic_irq < 32 || gic_irq > 1020 || cascade_irq >= NR_IRQS))
		do_bad_IRQ(cascade_irq, desc);
	else
		generic_handle_irq(cascade_irq);
232 233

 out:
234
	chained_irq_exit(chip, desc);
235 236
}

237
static struct irq_chip gic_chip = {
238 239 240
	.name			= "GIC",
	.irq_mask		= gic_mask_irq,
	.irq_unmask		= gic_unmask_irq,
241
	.irq_eoi		= gic_eoi_irq,
242
	.irq_set_type		= gic_set_type,
243
	.irq_retrigger		= gic_retrigger,
Russell King's avatar
Russell King committed
244
#ifdef CONFIG_SMP
245
	.irq_set_affinity	= gic_set_affinity,
Russell King's avatar
Russell King committed
246
#endif
247
	.irq_set_wake		= gic_set_wake,
Russell King's avatar
Russell King committed
248 249
};

250 251 252 253
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
{
	if (gic_nr >= MAX_GIC_NR)
		BUG();
254
	if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
255
		BUG();
256
	irq_set_chained_handler(irq, gic_handle_cascade_irq);
257 258
}

259
static void __init gic_dist_init(struct gic_chip_data *gic,
260
	unsigned int irq_start)
Russell King's avatar
Russell King committed
261
{
262
	unsigned int gic_irqs, irq_limit, i;
263
	void __iomem *base = gic->dist_base;
Russell King's avatar
Russell King committed
264 265 266 267 268
	u32 cpumask = 1 << smp_processor_id();

	cpumask |= cpumask << 8;
	cpumask |= cpumask << 16;

269
	writel_relaxed(0, base + GIC_DIST_CTRL);
Russell King's avatar
Russell King committed
270 271 272 273 274

	/*
	 * Find out how many interrupts are supported.
	 * The GIC only supports up to 1020 interrupt sources.
	 */
275
	gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
276 277 278
	gic_irqs = (gic_irqs + 1) * 32;
	if (gic_irqs > 1020)
		gic_irqs = 1020;
Russell King's avatar
Russell King committed
279

280 281
	gic->gic_irqs = gic_irqs;

Russell King's avatar
Russell King committed
282 283 284
	/*
	 * Set all global interrupts to be level triggered, active low.
	 */
285
	for (i = 32; i < gic_irqs; i += 16)
286
		writel_relaxed(0, base + GIC_DIST_CONFIG + i * 4 / 16);
Russell King's avatar
Russell King committed
287 288 289 290

	/*
	 * Set all global interrupts to this CPU only.
	 */
291
	for (i = 32; i < gic_irqs; i += 4)
292
		writel_relaxed(cpumask, base + GIC_DIST_TARGET + i * 4 / 4);
Russell King's avatar
Russell King committed
293 294

	/*
295
	 * Set priority on all global interrupts.
Russell King's avatar
Russell King committed
296
	 */
297
	for (i = 32; i < gic_irqs; i += 4)
298
		writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);
Russell King's avatar
Russell King committed
299 300

	/*
301 302
	 * Disable all interrupts.  Leave the PPI and SGIs alone
	 * as these enables are banked registers.
Russell King's avatar
Russell King committed
303
	 */
304
	for (i = 32; i < gic_irqs; i += 32)
305
		writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32);
Russell King's avatar
Russell King committed
306

307 308 309
	/*
	 * Limit number of interrupts registered to the platform maximum
	 */
310
	irq_limit = gic->irq_offset + gic_irqs;
311 312 313
	if (WARN_ON(irq_limit > NR_IRQS))
		irq_limit = NR_IRQS;

Russell King's avatar
Russell King committed
314 315 316
	/*
	 * Setup the Linux IRQ subsystem.
	 */
317
	for (i = irq_start; i < irq_limit; i++) {
318
		irq_set_chip_and_handler(i, &gic_chip, handle_fasteoi_irq);
319
		irq_set_chip_data(i, gic);
Russell King's avatar
Russell King committed
320 321 322
		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
	}

323
	writel_relaxed(1, base + GIC_DIST_CTRL);
Russell King's avatar
Russell King committed
324 325
}

326
static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
Russell King's avatar
Russell King committed
327
{
328 329
	void __iomem *dist_base = gic->dist_base;
	void __iomem *base = gic->cpu_base;
330 331 332 333 334 335
	int i;

	/*
	 * Deal with the banked PPI and SGI interrupts - disable all
	 * PPI interrupts, ensure all SGI interrupts are enabled.
	 */
336 337
	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
338 339 340 341 342

	/*
	 * Set priority on PPI and SGI interrupts
	 */
	for (i = 0; i < 32; i += 4)
343
		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);
344

345 346
	writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
	writel_relaxed(1, base + GIC_CPU_CTRL);
Russell King's avatar
Russell King committed
347 348
}

349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
#ifdef CONFIG_CPU_PM
/*
 * Saves the GIC distributor registers during suspend or idle.  Must be called
 * with interrupts disabled but before powering down the GIC.  After calling
 * this function, no interrupts will be delivered by the GIC, and another
 * platform-specific wakeup source must be enabled.
 */
static void gic_dist_save(unsigned int gic_nr)
{
	unsigned int gic_irqs;
	void __iomem *dist_base;
	int i;

	if (gic_nr >= MAX_GIC_NR)
		BUG();

	gic_irqs = gic_data[gic_nr].gic_irqs;
	dist_base = gic_data[gic_nr].dist_base;

	if (!dist_base)
		return;

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
		gic_data[gic_nr].saved_spi_conf[i] =
			readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
		gic_data[gic_nr].saved_spi_target[i] =
			readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
		gic_data[gic_nr].saved_spi_enable[i] =
			readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
}

/*
 * Restores the GIC distributor registers during resume or when coming out of
 * idle.  Must be called before enabling interrupts.  If a level interrupt
 * that occured while the GIC was suspended is still present, it will be
 * handled normally, but any edge interrupts that occured will not be seen by
 * the GIC and need to be handled by the platform-specific wakeup source.
 */
static void gic_dist_restore(unsigned int gic_nr)
{
	unsigned int gic_irqs;
	unsigned int i;
	void __iomem *dist_base;

	if (gic_nr >= MAX_GIC_NR)
		BUG();

	gic_irqs = gic_data[gic_nr].gic_irqs;
	dist_base = gic_data[gic_nr].dist_base;

	if (!dist_base)
		return;

	writel_relaxed(0, dist_base + GIC_DIST_CTRL);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 16); i++)
		writel_relaxed(gic_data[gic_nr].saved_spi_conf[i],
			dist_base + GIC_DIST_CONFIG + i * 4);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
		writel_relaxed(0xa0a0a0a0,
			dist_base + GIC_DIST_PRI + i * 4);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 4); i++)
		writel_relaxed(gic_data[gic_nr].saved_spi_target[i],
			dist_base + GIC_DIST_TARGET + i * 4);

	for (i = 0; i < DIV_ROUND_UP(gic_irqs, 32); i++)
		writel_relaxed(gic_data[gic_nr].saved_spi_enable[i],
			dist_base + GIC_DIST_ENABLE_SET + i * 4);

	writel_relaxed(1, dist_base + GIC_DIST_CTRL);
}

static void gic_cpu_save(unsigned int gic_nr)
{
	int i;
	u32 *ptr;
	void __iomem *dist_base;
	void __iomem *cpu_base;

	if (gic_nr >= MAX_GIC_NR)
		BUG();

	dist_base = gic_data[gic_nr].dist_base;
	cpu_base = gic_data[gic_nr].cpu_base;

	if (!dist_base || !cpu_base)
		return;

	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);

	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
		ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);

}

static void gic_cpu_restore(unsigned int gic_nr)
{
	int i;
	u32 *ptr;
	void __iomem *dist_base;
	void __iomem *cpu_base;

	if (gic_nr >= MAX_GIC_NR)
		BUG();

	dist_base = gic_data[gic_nr].dist_base;
	cpu_base = gic_data[gic_nr].cpu_base;

	if (!dist_base || !cpu_base)
		return;

	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_enable);
	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
		writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);

	ptr = __this_cpu_ptr(gic_data[gic_nr].saved_ppi_conf);
	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);

	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
		writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);

	writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
	writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
}

static int gic_notifier(struct notifier_block *self, unsigned long cmd,	void *v)
{
	int i;

	for (i = 0; i < MAX_GIC_NR; i++) {
		switch (cmd) {
		case CPU_PM_ENTER:
			gic_cpu_save(i);
			break;
		case CPU_PM_ENTER_FAILED:
		case CPU_PM_EXIT:
			gic_cpu_restore(i);
			break;
		case CPU_CLUSTER_PM_ENTER:
			gic_dist_save(i);
			break;
		case CPU_CLUSTER_PM_ENTER_FAILED:
		case CPU_CLUSTER_PM_EXIT:
			gic_dist_restore(i);
			break;
		}
	}

	return NOTIFY_OK;
}

static struct notifier_block gic_notifier_block = {
	.notifier_call = gic_notifier,
};

static void __init gic_pm_init(struct gic_chip_data *gic)
{
	gic->saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
		sizeof(u32));
	BUG_ON(!gic->saved_ppi_enable);

	gic->saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
		sizeof(u32));
	BUG_ON(!gic->saved_ppi_conf);

	cpu_pm_register_notifier(&gic_notifier_block);
}
#else
static void __init gic_pm_init(struct gic_chip_data *gic)
{
}
#endif

532 533 534
void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
	void __iomem *dist_base, void __iomem *cpu_base)
{
535 536 537 538 539 540 541 542 543
	struct gic_chip_data *gic;

	BUG_ON(gic_nr >= MAX_GIC_NR);

	gic = &gic_data[gic_nr];
	gic->dist_base = dist_base;
	gic->cpu_base = cpu_base;
	gic->irq_offset = (irq_start - 1) & ~31;

544 545
	if (gic_nr == 0)
		gic_cpu_base_addr = cpu_base;
546 547 548

	gic_dist_init(gic, irq_start);
	gic_cpu_init(gic);
549
	gic_pm_init(gic);
550 551
}

552 553
void __cpuinit gic_secondary_init(unsigned int gic_nr)
{
554 555 556
	BUG_ON(gic_nr >= MAX_GIC_NR);

	gic_cpu_init(&gic_data[gic_nr]);
557 558
}

559 560 561 562 563
void __cpuinit gic_enable_ppi(unsigned int irq)
{
	unsigned long flags;

	local_irq_save(flags);
564
	irq_set_status_flags(irq, IRQ_NOPROBE);
565
	gic_unmask_irq(irq_get_irq_data(irq));
566 567 568
	local_irq_restore(flags);
}

Russell King's avatar
Russell King committed
569
#ifdef CONFIG_SMP
570
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
Russell King's avatar
Russell King committed
571
{
572
	unsigned long map = *cpus_addr(*mask);
Russell King's avatar
Russell King committed
573

574 575 576 577 578 579
	/*
	 * Ensure that stores to Normal memory are visible to the
	 * other CPUs before issuing the IPI.
	 */
	dsb();

580
	/* this always happens on GIC0 */
581
	writel_relaxed(map << 16 | irq, gic_data[0].dist_base + GIC_DIST_SOFTINT);
Russell King's avatar
Russell King committed
582 583
}
#endif