leon_kernel.c 12.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * Copyright (C) 2009 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
 * Copyright (C) 2009 Konrad Eisele (konrad@gaisler.com) Aeroflex Gaisler AB
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
K
Konrad Eisele 已提交
14

15 16 17 18 19
#include <asm/oplib.h>
#include <asm/timer.h>
#include <asm/prom.h>
#include <asm/leon.h>
#include <asm/leon_amba.h>
K
Konrad Eisele 已提交
20 21
#include <asm/traps.h>
#include <asm/cacheflush.h>
22
#include <asm/smp.h>
23
#include <asm/setup.h>
24 25 26 27

#include "prom.h"
#include "irq.h"

28 29
struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
30 31 32 33

int leondebug_irq_disable;
int leon_debug_irqout;
static int dummy_master_l10_counter;
34
unsigned long amba_system_id;
35
static DEFINE_SPINLOCK(leon_irq_lock);
36

37
unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
38
unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
39
int leon3_ticker_irq; /* Timer ticker IRQ */
40
unsigned int sparc_leon_eirq;
41
#define LEON_IMASK(cpu) (&leon3_irqctrl_regs->mask[cpu])
42 43
#define LEON_IACK (&leon3_irqctrl_regs->iclear)
#define LEON_DO_ACK_HW 1
44

45 46 47 48
/* Return the last ACKed IRQ by the Extended IRQ controller. It has already
 * been (automatically) ACKed when the CPU takes the trap.
 */
static inline unsigned int leon_eirq_get(int cpu)
49 50 51 52
{
	return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f;
}

53 54
/* Handle one or multiple IRQs from the extended interrupt controller */
static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
55
{
56
	unsigned int eirq;
57
	int cpu = sparc_leon3_cpuid();
58 59 60 61

	eirq = leon_eirq_get(cpu);
	if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
		generic_handle_irq(irq_map[eirq]->irq);
62 63 64
}

/* The extended IRQ controller has been found, this function registers it */
65
void leon_eirq_setup(unsigned int eirq)
66
{
67 68
	unsigned long mask, oldmask;
	unsigned int veirq;
69

70 71 72
	if (eirq < 1 || eirq > 0xf) {
		printk(KERN_ERR "LEON EXT IRQ NUMBER BAD: %d\n", eirq);
		return;
73 74
	}

75 76 77 78 79 80 81 82
	veirq = leon_build_device_irq(eirq, leon_handle_ext_irq, "extirq", 0);

	/*
	 * Unmask the Extended IRQ, the IRQs routed through the Ext-IRQ
	 * controller have a mask-bit of their own, so this is safe.
	 */
	irq_link(veirq);
	mask = 1 << eirq;
83 84
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(boot_cpu_id));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(boot_cpu_id), (oldmask | mask));
85
	sparc_leon_eirq = eirq;
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
}

static inline unsigned long get_irqmask(unsigned int irq)
{
	unsigned long mask;

	if (!irq || ((irq > 0xf) && !sparc_leon_eirq)
	    || ((irq > 0x1f) && sparc_leon_eirq)) {
		printk(KERN_ERR
		       "leon_get_irqmask: false irq number: %d\n", irq);
		mask = 0;
	} else {
		mask = LEON_HARD_INT(irq);
	}
	return mask;
}

103 104 105 106 107 108 109
#ifdef CONFIG_SMP
static int irq_choose_cpu(const struct cpumask *affinity)
{
	cpumask_t mask;

	cpus_and(mask, cpu_online_map, *affinity);
	if (cpus_equal(mask, cpu_online_map) || cpus_empty(mask))
110
		return boot_cpu_id;
111 112 113 114
	else
		return first_cpu(mask);
}
#else
115
#define irq_choose_cpu(affinity) boot_cpu_id
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
#endif

static int leon_set_affinity(struct irq_data *data, const struct cpumask *dest,
			     bool force)
{
	unsigned long mask, oldmask, flags;
	int oldcpu, newcpu;

	mask = (unsigned long)data->chip_data;
	oldcpu = irq_choose_cpu(data->affinity);
	newcpu = irq_choose_cpu(dest);

	if (oldcpu == newcpu)
		goto out;

	/* unmask on old CPU first before enabling on the selected CPU */
	spin_lock_irqsave(&leon_irq_lock, flags);
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask));
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask));
	spin_unlock_irqrestore(&leon_irq_lock, flags);
out:
	return IRQ_SET_MASK_OK;
}

S
Sam Ravnborg 已提交
142
static void leon_unmask_irq(struct irq_data *data)
143
{
144
	unsigned long mask, oldmask, flags;
145
	int cpu;
S
Sam Ravnborg 已提交
146 147

	mask = (unsigned long)data->chip_data;
148
	cpu = irq_choose_cpu(data->affinity);
149
	spin_lock_irqsave(&leon_irq_lock, flags);
150 151
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask | mask));
152
	spin_unlock_irqrestore(&leon_irq_lock, flags);
153 154
}

S
Sam Ravnborg 已提交
155
static void leon_mask_irq(struct irq_data *data)
156
{
157
	unsigned long mask, oldmask, flags;
158
	int cpu;
S
Sam Ravnborg 已提交
159 160

	mask = (unsigned long)data->chip_data;
161
	cpu = irq_choose_cpu(data->affinity);
162
	spin_lock_irqsave(&leon_irq_lock, flags);
163 164
	oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(cpu));
	LEON3_BYPASS_STORE_PA(LEON_IMASK(cpu), (oldmask & ~mask));
165
	spin_unlock_irqrestore(&leon_irq_lock, flags);
166 167
}

S
Sam Ravnborg 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180
static unsigned int leon_startup_irq(struct irq_data *data)
{
	irq_link(data->irq);
	leon_unmask_irq(data);
	return 0;
}

static void leon_shutdown_irq(struct irq_data *data)
{
	leon_mask_irq(data);
	irq_unlink(data->irq);
}

181 182 183 184 185 186 187 188 189
/* Used by external level sensitive IRQ handlers on the LEON: ACK IRQ ctrl */
static void leon_eoi_irq(struct irq_data *data)
{
	unsigned long mask = (unsigned long)data->chip_data;

	if (mask & LEON_DO_ACK_HW)
		LEON3_BYPASS_STORE_PA(LEON_IACK, mask & ~LEON_DO_ACK_HW);
}

S
Sam Ravnborg 已提交
190
static struct irq_chip leon_irq = {
191 192 193 194 195 196 197
	.name			= "leon",
	.irq_startup		= leon_startup_irq,
	.irq_shutdown		= leon_shutdown_irq,
	.irq_mask		= leon_mask_irq,
	.irq_unmask		= leon_unmask_irq,
	.irq_eoi		= leon_eoi_irq,
	.irq_set_affinity	= leon_set_affinity,
S
Sam Ravnborg 已提交
198 199
};

200 201 202 203 204 205 206 207 208
/*
 * Build a LEON IRQ for the edge triggered LEON IRQ controller:
 *  Edge (normal) IRQ           - handle_simple_irq, ack=DONT-CARE, never ack
 *  Level IRQ (PCI|Level-GPIO)  - handle_fasteoi_irq, ack=1, ack after ISR
 *  Per-CPU Edge                - handle_percpu_irq, ack=0
 */
unsigned int leon_build_device_irq(unsigned int real_irq,
				    irq_flow_handler_t flow_handler,
				    const char *name, int do_ack)
S
Sam Ravnborg 已提交
209 210 211 212 213 214 215 216 217 218 219 220 221
{
	unsigned int irq;
	unsigned long mask;

	irq = 0;
	mask = get_irqmask(real_irq);
	if (mask == 0)
		goto out;

	irq = irq_alloc(real_irq, real_irq);
	if (irq == 0)
		goto out;

222 223 224
	if (do_ack)
		mask |= LEON_DO_ACK_HW;

S
Sam Ravnborg 已提交
225
	irq_set_chip_and_handler_name(irq, &leon_irq,
226
				      flow_handler, name);
S
Sam Ravnborg 已提交
227 228 229 230 231 232
	irq_set_chip_data(irq, (void *)mask);

out:
	return irq;
}

233 234 235 236 237 238
static unsigned int _leon_build_device_irq(struct platform_device *op,
					   unsigned int real_irq)
{
	return leon_build_device_irq(real_irq, handle_simple_irq, "edge", 0);
}

239 240
void __init leon_init_timers(irq_handler_t counter_fn)
{
241
	int irq, eirq;
242
	struct device_node *rootnp, *np, *nnp;
243 244
	struct property *pp;
	int len;
245
	int icsel;
246
	int ampopts;
S
Sam Ravnborg 已提交
247
	int err;
248 249 250 251 252 253

	leondebug_irq_disable = 0;
	leon_debug_irqout = 0;
	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
	dummy_master_l10_counter = 0;

254 255 256
	rootnp = of_find_node_by_path("/ambapp0");
	if (!rootnp)
		goto bad;
257 258 259 260 261 262 263

	/* Find System ID: GRLIB build ID and optional CHIP ID */
	pp = of_find_property(rootnp, "systemid", &len);
	if (pp)
		amba_system_id = *(unsigned long *)pp->value;

	/* Find IRQMP IRQ Controller Registers base adr otherwise bail out */
264
	np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
265 266 267 268 269
	if (!np) {
		np = of_find_node_by_name(rootnp, "01_00d");
		if (!np)
			goto bad;
	}
270 271 272 273 274 275
	pp = of_find_property(np, "reg", &len);
	if (!pp)
		goto bad;
	leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;

	/* Find GPTIMER Timer Registers base address otherwise bail out. */
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
	nnp = rootnp;
	do {
		np = of_find_node_by_name(nnp, "GAISLER_GPTIMER");
		if (!np) {
			np = of_find_node_by_name(nnp, "01_011");
			if (!np)
				goto bad;
		}

		ampopts = 0;
		pp = of_find_property(np, "ampopts", &len);
		if (pp) {
			ampopts = *(int *)pp->value;
			if (ampopts == 0) {
				/* Skip this instance, resource already
				 * allocated by other OS */
				nnp = np;
				continue;
			}
		}

		/* Select Timer-Instance on Timer Core. Default is zero */
		leon3_gptimer_idx = ampopts & 0x7;

		pp = of_find_property(np, "reg", &len);
		if (pp)
			leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)
						pp->value;
		pp = of_find_property(np, "interrupts", &len);
		if (pp)
			leon3_gptimer_irq = *(unsigned int *)pp->value;
	} while (0);
308

309 310 311 312 313 314 315
	if (!(leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq))
		goto bad;

	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0);
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld,
				(((1000000 / HZ) - 1)));
	LEON3_BYPASS_STORE_PA(
316
			&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
317

K
Konrad Eisele 已提交
318
#ifdef CONFIG_SMP
319
	leon3_ticker_irq = leon3_gptimer_irq + 1 + leon3_gptimer_idx;
K
Konrad Eisele 已提交
320

321 322 323 324
	if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
	      (1<<LEON3_GPTIMER_SEPIRQ))) {
		printk(KERN_ERR "timer not configured with separate irqs\n");
		BUG();
325 326
	}

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val,
				0);
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld,
				(((1000000/HZ) - 1)));
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
				0);
#endif

	/*
	 * The IRQ controller may (if implemented) consist of multiple
	 * IRQ controllers, each mapped on a 4Kb boundary.
	 * Each CPU may be routed to different IRQCTRLs, however
	 * we assume that all CPUs (in SMP system) is routed to the
	 * same IRQ Controller, and for non-SMP only one IRQCTRL is
	 * accessed anyway.
	 * In AMP systems, Linux must run on CPU0 for the time being.
	 */
344 345
	icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[boot_cpu_id/8]);
	icsel = (icsel >> ((7 - (boot_cpu_id&0x7)) * 4)) & 0xf;
346 347
	leon3_irqctrl_regs += icsel;

348 349 350
	/* Mask all IRQs on boot-cpu IRQ controller */
	LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[boot_cpu_id], 0);

351 352 353 354 355 356
	/* Probe extended IRQ controller */
	eirq = (LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->mpstatus)
		>> 16) & 0xf;
	if (eirq != 0)
		leon_eirq_setup(eirq);

357
	irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
S
Sam Ravnborg 已提交
358 359
	err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
	if (err) {
360
		printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
361 362 363
		prom_halt();
	}

364 365 366 367 368
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
			      LEON3_GPTIMER_EN |
			      LEON3_GPTIMER_RL |
			      LEON3_GPTIMER_LD |
			      LEON3_GPTIMER_IRQEN);
K
Konrad Eisele 已提交
369 370

#ifdef CONFIG_SMP
371 372 373 374 375 376 377 378 379 380
	/* Install per-cpu IRQ handler for broadcasted ticker */
	irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
				    "per-cpu", 0);
	err = request_irq(irq, leon_percpu_timer_interrupt,
			  IRQF_PERCPU | IRQF_TIMER, "ticker",
			  NULL);
	if (err) {
		printk(KERN_ERR "unable to attach ticker IRQ%d\n", irq);
		prom_halt();
	}
381

382 383 384 385 386
	LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
			      LEON3_GPTIMER_EN |
			      LEON3_GPTIMER_RL |
			      LEON3_GPTIMER_LD |
			      LEON3_GPTIMER_IRQEN);
K
Konrad Eisele 已提交
387
#endif
388 389 390 391 392
	return;
bad:
	printk(KERN_ERR "No Timer/irqctrl found\n");
	BUG();
	return;
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
}

void leon_clear_clock_irq(void)
{
}

void leon_load_profile_irq(int cpu, unsigned int limit)
{
	BUG();
}

void __init leon_trans_init(struct device_node *dp)
{
	if (strcmp(dp->type, "cpu") == 0 && strcmp(dp->name, "<NULL>") == 0) {
		struct property *p;
		p = of_find_property(dp, "mid", (void *)0);
		if (p) {
			int mid;
			dp->name = prom_early_alloc(5 + 1);
			memcpy(&mid, p->value, p->length);
			sprintf((char *)dp->name, "cpu%.2d", mid);
		}
	}
}

void __initdata (*prom_amba_init)(struct device_node *dp, struct device_node ***nextp) = 0;

void __init leon_node_init(struct device_node *dp, struct device_node ***nextp)
{
	if (prom_amba_init &&
	    strcmp(dp->type, "ambapp") == 0 &&
	    strcmp(dp->name, "ambapp0") == 0) {
		prom_amba_init(dp, nextp);
	}
}

K
Konrad Eisele 已提交
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
#ifdef CONFIG_SMP

void leon_set_cpu_int(int cpu, int level)
{
	unsigned long mask;
	mask = get_irqmask(level);
	LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask);
}

static void leon_clear_ipi(int cpu, int level)
{
	unsigned long mask;
	mask = get_irqmask(level);
	LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->force[cpu], mask<<16);
}

static void leon_set_udt(int cpu)
{
}

void leon_clear_profile_irq(int cpu)
{
}

void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu)
{
	unsigned long mask, flags, *addr;
	mask = get_irqmask(irq_nr);
457
	spin_lock_irqsave(&leon_irq_lock, flags);
458 459
	addr = (unsigned long *)LEON_IMASK(cpu);
	LEON3_BYPASS_STORE_PA(addr, (LEON3_BYPASS_LOAD_PA(addr) | mask));
460
	spin_unlock_irqrestore(&leon_irq_lock, flags);
K
Konrad Eisele 已提交
461 462 463 464
}

#endif

465 466
void __init leon_init_IRQ(void)
{
S
Sam Ravnborg 已提交
467
	sparc_irq_config.init_timers      = leon_init_timers;
468
	sparc_irq_config.build_device_irq = _leon_build_device_irq;
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484

	BTFIXUPSET_CALL(clear_clock_irq, leon_clear_clock_irq,
			BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(load_profile_irq, leon_load_profile_irq,
			BTFIXUPCALL_NOP);

#ifdef CONFIG_SMP
	BTFIXUPSET_CALL(set_cpu_int, leon_set_cpu_int, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(clear_cpu_int, leon_clear_ipi, BTFIXUPCALL_NORM);
	BTFIXUPSET_CALL(set_irq_udt, leon_set_udt, BTFIXUPCALL_NORM);
#endif

}

void __init leon_init(void)
{
485
	of_pdt_build_more = &leon_node_init;
486
}