irq-mips-gic.c 11.7 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

48
#if defined(CONFIG_CSRC_GIC) || defined(CONFIG_CEVT_GIC)
49 50 51 52 53 54 55 56 57 58 59 60
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;
}
61 62 63 64 65 66 67 68 69

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));
}

70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
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);
}

85 86 87 88 89 90 91 92 93
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;
}
94 95
#endif

S
Steven J. Hill 已提交
96 97 98 99 100 101
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 已提交
102
	return vpe_pending & GIC_VPE_PEND_TIMER_MSK;
S
Steven J. Hill 已提交
103 104 105 106 107 108 109 110 111 112 113
}

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);
}

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

S
Steven J. Hill 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
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();
}

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

S
Steven J. Hill 已提交
141 142 143 144 145 146 147 148 149 150 151 152 153
	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);
	}

154 155 156 157 158 159 160 161 162 163 164
	/*
	 * 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 已提交
165 166 167 168 169 170
				 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;
		}
171 172 173

		if (vpe_ctl & GIC_VPE_CTL_PERFCNT_RTBL_MSK)
			GICWRITE(GIC_REG(VPE_OTHER, GIC_VPE_PERFCTR_MAP),
S
Steven J. Hill 已提交
174 175 176 177 178
				 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;
		}
179 180 181
	}
}

182 183 184 185 186 187 188 189 190 191 192
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;
}

193
void gic_get_int_mask(unsigned long *dst, const unsigned long *src)
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
{
	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);
218 219 220 221 222 223 224 225 226
	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);
227

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

231
static void gic_mask_irq(struct irq_data *d)
232
{
233
	GIC_CLR_INTR_MASK(d->irq - gic_irq_base);
234 235
}

236
static void gic_unmask_irq(struct irq_data *d)
237
{
238
	GIC_SET_INTR_MASK(d->irq - gic_irq_base);
239 240
}

241 242 243 244 245 246 247
static void gic_ack_irq(struct irq_data *d)
{
	/* Clear edge detector */
	if (gic_irq_flags[d->irq - gic_irq_base] & GIC_TRIG_EDGE)
		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), d->irq - gic_irq_base);
}

248 249 250 251 252 253 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
static int gic_set_type(struct irq_data *d, unsigned int type)
{
	unsigned int irq = d->irq - gic_irq_base;
	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);
297

298 299 300 301
	return 0;
}

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

310
	cpumask_and(&tmp, cpumask, cpu_online_mask);
311
	if (cpus_empty(tmp))
312
		return -1;
313 314 315 316

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

317 318 319 320 321 322 323
	/* 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);
324

325
	cpumask_copy(d->affinity, cpumask);
326 327
	spin_unlock_irqrestore(&gic_lock, flags);

328
	return IRQ_SET_MASK_OK_NOCOPY;
329 330 331 332
}
#endif

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

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

349 350
	/* Setup Intr to Pin mapping */
	if (pin & GIC_MAP_TO_NMI_MSK) {
J
Jeffrey Deans 已提交
351 352
		int i;

353 354
		GICWRITE(GIC_REG_ADDR(SHARED, GIC_SH_MAP_TO_PIN(intr)), pin);
		/* FIXME: hack to route NMI to all cpu's */
J
Jeffrey Deans 已提交
355
		for (i = 0; i < NR_CPUS; i += 32) {
356
			GICWRITE(GIC_REG_ADDR(SHARED,
J
Jeffrey Deans 已提交
357
					  GIC_SH_MAP_TO_VPE_REG_OFF(intr, i)),
358 359 360 361 362 363 364
				 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 已提交
365 366 367 368 369 370 371 372
		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;
		}
373 374 375 376 377 378 379 380 381
	}

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

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

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

384
	/* Initialise per-cpu Interrupt software masks */
J
Jeffrey Deans 已提交
385 386
	set_bit(intr, pcpu_masks[cpu].pcpu_mask);

S
Steven J. Hill 已提交
387
	if ((flags & GIC_FLAG_TRANSPARENT) && (cpu_has_veic == 0))
388 389
		GIC_SET_INTR_MASK(intr);
	if (trigtype == GIC_TRIG_EDGE)
390
		gic_irq_flags[intr] |= GIC_TRIG_EDGE;
391 392
}

393 394
static void __init gic_basic_init(int numintrs, int numvpes,
			struct gic_intr_map *intrmap, int mapsize)
395 396
{
	unsigned int i, cpu;
S
Steven J. Hill 已提交
397 398 399
	unsigned int pin_offset = 0;

	board_bind_eic_interrupt = &gic_bind_eic_interrupt;
400 401

	/* Setup defaults */
402
	for (i = 0; i < numintrs; i++) {
403 404
		GIC_SET_POLARITY(i, GIC_POL_POS);
		GIC_SET_TRIGGER(i, GIC_TRIG_LEVEL);
405
		GIC_CLR_INTR_MASK(i);
S
Steven J. Hill 已提交
406
		if (i < GIC_NUM_INTRS) {
407
			gic_irq_flags[i] = 0;
S
Steven J. Hill 已提交
408 409 410
			gic_shared_intr_map[i].num_shared_intr = 0;
			gic_shared_intr_map[i].local_intr_mask = 0;
		}
411 412
	}

S
Steven J. Hill 已提交
413 414 415 416 417 418 419
	/*
	 * 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);

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

	vpe_local_setup(numvpes);
}

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;
442
	int numvpes, numintrs;
443 444 445

	_gic_base = (unsigned long) ioremap_nocache(gic_base_addr,
						    gic_addrspace_size);
446
	gic_irq_base = irqbase;
447 448 449 450 451 452 453 454

	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;
455
	numvpes = numvpes + 1;
456

457
	gic_basic_init(numintrs, numvpes, intr_map, intr_map_size);
458 459

	gic_platform_init(numintrs, &gic_irq_controller);
460
}