irq-mips-gic.c 12.5 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
 * Copyright (C) 2008 Ralf Baechle (ralf@linux-mips.org)
 * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved.
 */
9 10
#include <linux/bitmap.h>
#include <linux/init.h>
11
#include <linux/smp.h>
12
#include <linux/irq.h>
13
#include <linux/clocksource.h>
14 15 16

#include <asm/io.h>
#include <asm/gic.h>
S
Steven J. Hill 已提交
17 18
#include <asm/setup.h>
#include <asm/traps.h>
19 20 21
#include <linux/hardirq.h>
#include <asm-generic/bitops/find.h>

22
unsigned int gic_frequency;
23
unsigned int gic_present;
24 25 26
unsigned long _gic_base;
unsigned int gic_irq_base;
unsigned int gic_irq_flags[GIC_NUM_INTRS];
27

S
Steven J. Hill 已提交
28 29 30
/* The index into this array is the vector # of the interrupt. */
struct gic_shared_intr_map gic_shared_intr_map[GIC_NUM_INTRS];

31 32 33 34 35 36 37 38 39 40 41 42
struct gic_pcpu_mask {
	DECLARE_BITMAP(pcpu_mask, GIC_NUM_INTRS);
};

struct gic_pending_regs {
	DECLARE_BITMAP(pending, GIC_NUM_INTRS);
};

struct gic_intrmask_regs {
	DECLARE_BITMAP(intrmask, GIC_NUM_INTRS);
};

43
static struct gic_pcpu_mask pcpu_masks[NR_CPUS];
44 45
static struct gic_pending_regs pending_regs[NR_CPUS];
static struct gic_intrmask_regs intrmask_regs[NR_CPUS];
46
static DEFINE_SPINLOCK(gic_lock);
47
static struct irq_domain *gic_irq_domain;
48

49
#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
50 51 52 53 54 55 56 57 58 59 60 61
cycle_t gic_read_count(void)
{
	unsigned int hi, hi2, lo;

	do {
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo);
		GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2);
	} while (hi2 != hi);

	return (((cycle_t) hi) << 32) + lo;
}
62 63 64 65 66 67 68 69 70

void gic_write_compare(cycle_t cnt)
{
	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI),
				(int)(cnt >> 32));
	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO),
				(int)(cnt & 0xffffffff));
}

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
void gic_write_cpu_compare(cycle_t cnt, int cpu)
{
	unsigned long flags;

	local_irq_save(flags);

	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), cpu);
	GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_HI),
				(int)(cnt >> 32));
	GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_COMPARE_LO),
				(int)(cnt & 0xffffffff));

	local_irq_restore(flags);
}

86 87 88 89 90 91 92 93 94
cycle_t gic_read_compare(void)
{
	unsigned int hi, lo;

	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_HI), hi);
	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_COMPARE_LO), lo);

	return (((cycle_t) hi) << 32) + lo;
}
95 96
#endif

S
Steven J. Hill 已提交
97 98 99 100 101 102
unsigned int gic_get_timer_pending(void)
{
	unsigned int vpe_pending;

	GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), 0);
	GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_PEND), vpe_pending);
R
Ralf Baechle 已提交
103
	return vpe_pending & GIC_VPE_PEND_TIMER_MSK;
S
Steven J. Hill 已提交
104 105 106 107 108 109 110 111 112 113 114
}

void gic_bind_eic_interrupt(int irq, int set)
{
	/* Convert irq vector # to hw int # */
	irq -= GIC_PIN_TO_VEC_OFFSET;

	/* Set irq to use shadow set */
	GICWRITE(GIC_REG_ADDR(VPE_LOCAL, GIC_VPE_EIC_SS(irq)), set);
}

115 116 117 118 119
void gic_send_ipi(unsigned int intr)
{
	GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), 0x80000000 | intr);
}

S
Steven J. Hill 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
static void gic_eic_irq_dispatch(void)
{
	unsigned int cause = read_c0_cause();
	int irq;

	irq = (cause & ST0_IM) >> STATUSB_IP2;
	if (irq == 0)
		irq = -1;

	if (irq >= 0)
		do_IRQ(gic_irq_base + irq);
	else
		spurious_interrupt();
}

135
static void __init vpe_local_setup(unsigned int numvpes)
136
{
S
Steven J. Hill 已提交
137 138
	unsigned long timer_intr = GIC_INT_TMR;
	unsigned long perf_intr = GIC_INT_PERFCTR;
139
	unsigned int vpe_ctl;
140
	int i;
141

S
Steven J. Hill 已提交
142 143 144 145 146 147 148 149 150 151 152 153 154
	if (cpu_has_veic) {
		/*
		 * GIC timer interrupt -> CPU HW Int X (vector X+2) ->
		 * map to pin X+2-1 (since GIC adds 1)
		 */
		timer_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
		/*
		 * GIC perfcnt interrupt -> CPU HW Int X (vector X+2) ->
		 * map to pin X+2-1 (since GIC adds 1)
		 */
		perf_intr += (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);
	}

155 156 157 158 159 160 161 162 163 164 165
	/*
	 * Setup the default performance counter timer interrupts
	 * for all VPEs
	 */
	for (i = 0; i < numvpes; i++) {
		GICWRITE(GIC_REG(VPE_LOCAL, GIC_VPE_OTHER_ADDR), i);

		/* Are Interrupts locally routable? */
		GICREAD(GIC_REG(VPE_OTHER, GIC_VPE_CTL), vpe_ctl);
		if (vpe_ctl & GIC_VPE_CTL_TIMER_RTBL_MSK)
			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_TIMER_MAP),
S
Steven J. Hill 已提交
166 167 168 169 170 171
				 GIC_MAP_TO_PIN_MSK | timer_intr);
		if (cpu_has_veic) {
			set_vi_handler(timer_intr + GIC_PIN_TO_VEC_OFFSET,
				gic_eic_irq_dispatch);
			gic_shared_intr_map[timer_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_TIMER_MSK;
		}
172 173 174

		if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
S
Steven J. Hill 已提交
175 176 177 178 179
				 GIC_MAP_TO_PIN_MSK | perf_intr);
		if (cpu_has_veic) {
			set_vi_handler(perf_intr + GIC_PIN_TO_VEC_OFFSET, gic_eic_irq_dispatch);
			gic_shared_intr_map[perf_intr + GIC_PIN_TO_VEC_OFFSET].local_intr_mask |= GIC_VPE_RMASK_PERFCNT_MSK;
		}
180 181 182
	}
}

183 184 185 186 187 188 189 190 191 192 193
unsigned int gic_compare_int(void)
{
	unsigned int pending;

	GICREAD(GIC_REG(VPE_LOCAL, GIC_VPE_PEND), pending);
	if (pending & GIC_VPE_PEND_CMP_MSK)
		return 1;
	else
		return 0;
}

194
void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
{
	unsigned int i;
	unsigned long *pending, *intrmask, *pcpu_mask;
	unsigned long *pending_abs, *intrmask_abs;

	/* Get per-cpu bitmaps */
	pending = pending_regs[smp_processor_id()].pending;
	intrmask = intrmask_regs[smp_processor_id()].intrmask;
	pcpu_mask = pcpu_masks[smp_processor_id()].pcpu_mask;

	pending_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
							 GIC_SH_PEND_31_0_OFS);
	intrmask_abs = (unsigned long *) GIC_REG_ABS_ADDR(SHARED,
							  GIC_SH_MASK_31_0_OFS);

	for (i = 0; i < BITS_TO_LONGS(GIC_NUM_INTRS); i++) {
		GICREAD(*pending_abs, pending[i]);
		GICREAD(*intrmask_abs, intrmask[i]);
		pending_abs++;
		intrmask_abs++;
	}

	bitmap_and(pending, pending, intrmask, GIC_NUM_INTRS);
	bitmap_and(pending, pending, pcpu_mask, GIC_NUM_INTRS);
219 220 221 222 223 224 225 226 227
	bitmap_and(dst, src, pending, GIC_NUM_INTRS);
}

unsigned int gic_get_int(void)
{
	DECLARE_BITMAP(interrupts, GIC_NUM_INTRS);

	bitmap_fill(interrupts, GIC_NUM_INTRS);
	gic_get_int_mask(interrupts, interrupts);
228

229
	return find_first_bit(interrupts, GIC_NUM_INTRS);
230 231
}

232
static void gic_mask_irq(struct irq_data *d)
233
{
234
	GIC_CLR_INTR_MASK(d->hwirq);
235 236
}

237
static void gic_unmask_irq(struct irq_data *d)
238
{
239
	GIC_SET_INTR_MASK(d->hwirq);
240 241
}

242 243
static void gic_ack_irq(struct irq_data *d)
{
244 245
	unsigned int irq = d->hwirq;

246
	/* Clear edge detector */
247 248
	if (gic_irq_flags[irq] & GIC_TRIG_EDGE)
		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
249 250
}

251 252
static int gic_set_type(struct irq_data *d, unsigned int type)
{
253
	unsigned int irq = d->hwirq;
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
	unsigned long flags;
	bool is_edge;

	spin_lock_irqsave(&gic_lock, flags);
	switch (type & IRQ_TYPE_SENSE_MASK) {
	case IRQ_TYPE_EDGE_FALLING:
		GIC_SET_POLARITY(irq, GIC_POL_NEG);
		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
		is_edge = true;
		break;
	case IRQ_TYPE_EDGE_RISING:
		GIC_SET_POLARITY(irq, GIC_POL_POS);
		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
		is_edge = true;
		break;
	case IRQ_TYPE_EDGE_BOTH:
		/* polarity is irrelevant in this case */
		GIC_SET_TRIGGER(irq, GIC_TRIG_EDGE);
		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_ENABLE);
		is_edge = true;
		break;
	case IRQ_TYPE_LEVEL_LOW:
		GIC_SET_POLARITY(irq, GIC_POL_NEG);
		GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
		is_edge = false;
		break;
	case IRQ_TYPE_LEVEL_HIGH:
	default:
		GIC_SET_POLARITY(irq, GIC_POL_POS);
		GIC_SET_TRIGGER(irq, GIC_TRIG_LEVEL);
		GIC_SET_DUAL(irq, GIC_TRIG_DUAL_DISABLE);
		is_edge = false;
		break;
	}

	if (is_edge) {
		gic_irq_flags[irq] |= GIC_TRIG_EDGE;
		__irq_set_handler_locked(d->irq, handle_edge_irq);
	} else {
		gic_irq_flags[irq] &= ~GIC_TRIG_EDGE;
		__irq_set_handler_locked(d->irq, handle_level_irq);
	}
	spin_unlock_irqrestore(&gic_lock, flags);
300

301 302 303 304
	return 0;
}

#ifdef CONFIG_SMP
305 306
static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
			    bool force)
307
{
308
	unsigned int irq = d->hwirq;
309 310 311 312
	cpumask_t	tmp = CPU_MASK_NONE;
	unsigned long	flags;
	int		i;

313
	cpumask_and(&tmp, cpumask, cpu_online_mask);
314
	if (cpus_empty(tmp))
315
		return -EINVAL;
316 317 318 319

	/* Assumption : cpumask refers to a single CPU */
	spin_lock_irqsave(&gic_lock, flags);

320 321 322 323 324 325 326
	/* Re-route this IRQ */
	GIC_SH_MAP_TO_VPE_SMASK(irq, first_cpu(tmp));

	/* Update the pcpu_masks */
	for (i = 0; i < NR_CPUS; i++)
		clear_bit(irq, pcpu_masks[i].pcpu_mask);
	set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
327

328
	cpumask_copy(d->affinity, cpumask);
329 330
	spin_unlock_irqrestore(&gic_lock, flags);

331
	return IRQ_SET_MASK_OK_NOCOPY;
332 333 334 335
}
#endif

static struct irq_chip gic_irq_controller = {
336
	.name			=	"MIPS GIC",
337
	.irq_ack		=	gic_ack_irq,
338 339
	.irq_mask		=	gic_mask_irq,
	.irq_unmask		=	gic_unmask_irq,
340
	.irq_set_type		=	gic_set_type,
341
#ifdef CONFIG_SMP
342
	.irq_set_affinity	=	gic_set_affinity,
343 344 345
#endif
};

346 347 348
static void __init gic_setup_intr(unsigned int intr, unsigned int cpu,
	unsigned int pin, unsigned int polarity, unsigned int trigtype,
	unsigned int flags)
349
{
S
Steven J. Hill 已提交
350
	struct gic_shared_intr_map *map_ptr;
351
	int i;
S
Steven J. Hill 已提交
352

353 354
	/* Setup Intr to Pin mapping */
	if (pin & GIC_MAP_TO_NMI_MSK) {
J
Jeffrey Deans 已提交
355 356
		int i;

357 358
		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
		/* FIXME: hack to route NMI to all cpu's */
J
Jeffrey Deans 已提交
359
		for (i = 0; i < NR_CPUS; i += 32) {
360
			GICWRITE(GIC_REG_ADDR(SHARED,
J
Jeffrey Deans 已提交
361
					  GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
362 363 364 365 366 367 368
				 0xffffffff);
		}
	} else {
		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)),
			 GIC_MAP_TO_PIN_MSK | pin);
		/* Setup Intr to CPU mapping */
		GIC_SH_MAP_TO_VPE_SMASK(intr, cpu);
S
Steven J. Hill 已提交
369 370 371 372 373 374 375 376
		if (cpu_has_veic) {
			set_vi_handler(pin + GIC_PIN_TO_VEC_OFFSET,
				gic_eic_irq_dispatch);
			map_ptr = &gic_shared_intr_map[pin + GIC_PIN_TO_VEC_OFFSET];
			if (map_ptr->num_shared_intr >= GIC_MAX_SHARED_INTR)
				BUG();
			map_ptr->intr_list[map_ptr->num_shared_intr++] = intr;
		}
377 378 379 380 381 382 383 384 385
	}

	/* Setup Intr Polarity */
	GIC_SET_POLARITY(intr, polarity);

	/* Setup Intr Trigger Type */
	GIC_SET_TRIGGER(intr, trigtype);

	/* Init Intr Masks */
386
	GIC_CLR_INTR_MASK(intr);
J
Jeffrey Deans 已提交
387

388
	/* Initialise per-cpu Interrupt software masks */
389 390
	for (i = 0; i < NR_CPUS; i++)
		clear_bit(intr, pcpu_masks[i].pcpu_mask);
J
Jeffrey Deans 已提交
391 392
	set_bit(intr, pcpu_masks[cpu].pcpu_mask);

S
Steven J. Hill 已提交
393
	if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
394 395
		GIC_SET_INTR_MASK(intr);
	if (trigtype == GIC_TRIG_EDGE)
396
		gic_irq_flags[intr] |= GIC_TRIG_EDGE;
397 398
}

399 400
static void __init gic_basic_init(int numintrs, int numvpes,
			struct gic_intr_map *intrmap, int mapsize)
401 402
{
	unsigned int i, cpu;
S
Steven J. Hill 已提交
403 404 405
	unsigned int pin_offset = 0;

	board_bind_eic_interrupt = &gic_bind_eic_interrupt;
406 407

	/* Setup defaults */
408
	for (i = 0; i < numintrs; i++) {
409 410
		GIC_SET_POLARITY(i, GIC_POL_POS);
		GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
411
		GIC_CLR_INTR_MASK(i);
S
Steven J. Hill 已提交
412
		if (i < GIC_NUM_INTRS) {
413
			gic_irq_flags[i] = 0;
S
Steven J. Hill 已提交
414 415 416
			gic_shared_intr_map[i].num_shared_intr = 0;
			gic_shared_intr_map[i].local_intr_mask = 0;
		}
417 418
	}

S
Steven J. Hill 已提交
419 420 421 422 423 424 425
	/*
	 * In EIC mode, the HW_INT# is offset by (2-1). Need to subtract
	 * one because the GIC will add one (since 0=no intr).
	 */
	if (cpu_has_veic)
		pin_offset = (GIC_CPU_TO_VEC_OFFSET - GIC_PIN_TO_VEC_OFFSET);

426
	/* Setup specifics */
427 428
	for (i = 0; i < mapsize; i++) {
		cpu = intrmap[i].cpunum;
429
		if (cpu == GIC_UNUSED)
430
			continue;
431 432
		gic_setup_intr(i,
			intrmap[i].cpunum,
S
Steven J. Hill 已提交
433
			intrmap[i].pin + pin_offset,
434 435 436
			intrmap[i].polarity,
			intrmap[i].trigtype,
			intrmap[i].flags);
437 438 439 440 441
	}

	vpe_local_setup(numvpes);
}

442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq,
			      irq_hw_number_t hw)
{
	unsigned long flags;

	irq_set_chip_and_handler(virq, &gic_irq_controller, handle_level_irq);

	spin_lock_irqsave(&gic_lock, flags);
	GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(hw)),
		 GIC_MAP_TO_PIN_MSK | 0);
	/* Map to VPE 0 by default */
	GIC_SH_MAP_TO_VPE_SMASK(hw, 0);
	set_bit(hw, pcpu_masks[0].pcpu_mask);
	spin_unlock_irqrestore(&gic_lock, flags);

	return 0;
}

static struct irq_domain_ops gic_irq_domain_ops = {
	.map = gic_irq_domain_map,
	.xlate = irq_domain_xlate_twocell,
};

465 466 467 468 469 470
void __init gic_init(unsigned long gic_base_addr,
		     unsigned long gic_addrspace_size,
		     struct gic_intr_map *intr_map, unsigned int intr_map_size,
		     unsigned int irqbase)
{
	unsigned int gicconfig;
471
	int numvpes, numintrs;
472 473 474

	_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
						    gic_addrspace_size);
475
	gic_irq_base = irqbase;
476 477 478 479 480 481 482 483

	GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), gicconfig);
	numintrs = (gicconfig & GIC_SH_CONFIG_NUMINTRS_MSK) >>
		   GIC_SH_CONFIG_NUMINTRS_SHF;
	numintrs = ((numintrs + 1) * 8);

	numvpes = (gicconfig & GIC_SH_CONFIG_NUMVPES_MSK) >>
		  GIC_SH_CONFIG_NUMVPES_SHF;
484
	numvpes = numvpes + 1;
485

486 487 488 489
	gic_irq_domain = irq_domain_add_simple(NULL, GIC_NUM_INTRS, irqbase,
					       &gic_irq_domain_ops, NULL);
	if (!gic_irq_domain)
		panic("Failed to add GIC IRQ domain");
490

491
	gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
492
}