sun4d_irq.c revision 6baa9b20a68a88c2fd751cbe8d7652009379351b
188278ca27a43ae503572b52ea2c171fbf45db5a2Adrian Bunk/*
2e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * SS1000/SC2000 interrupt handling.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Heavily based on arch/sparc/kernel/irq.c.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel_stat.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h>
10e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/timer.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/traps.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/sbi.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cacheflush.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881265fd93bc40c7c43fd36796571786ae3df00e0Sam Ravnborg#include "kernel.h"
1932231a66b4e1b649c346dc76b7d191f7e64a663aAl Viro#include "irq.h"
2032231a66b4e1b649c346dc76b7d191f7e64a663aAl Viro
21e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg/* Sun4d interrupts fall roughly into two categories.  SBUS and
22e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * cpu local.  CPU local interrupts cover the timer interrupts
23e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * and whatnot, and we encode those as normal PILs between
24e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * 0 and 15.
256baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * SBUS interrupts are encodes as a combination of board, level and slot.
26e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg */
27e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstruct sun4d_handler_data {
296baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int cpuid;    /* target cpu */
306baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int real_irq; /* interrupt level */
316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg};
326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic unsigned int sun4d_encode_irq(int board, int lvl, int slot)
356baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg{
366baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	return (board + 1) << 5 | (lvl << 2) | slot;
376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg}
386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
39f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstruct sun4d_timer_regs {
40f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	u32	l10_timer_limit;
41f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	u32	l10_cur_countx;
42f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	u32	l10_limit_noclear;
43f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	u32	ctrl;
44f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	u32	l10_cur_count;
45f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller};
46f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
47f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic struct sun4d_timer_regs __iomem *sun4d_timers;
48f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
496baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#define SUN4D_TIMER_IRQ        10
50db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg
51db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg/* Specify which cpu handle interrupts from which board.
52db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg * Index is board - value is cpu.
53db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg */
54db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborgstatic unsigned char board_to_cpu[32];
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pil_to_sbus[] = {
57e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
58e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
59e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	1,
60e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	2,
61e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
62e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	3,
63e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
64e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	4,
65e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
66e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	5,
67e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
68e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	6,
69e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
70e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	7,
71e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
72e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	0,
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
75f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller/* Exported for sun4d_smp.c */
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDEFINE_SPINLOCK(sun4d_imsk_lock);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
786baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg/* SBUS interrupts are encoded integers including the board number
796baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * (plus one), the SBUS level, and the SBUS slot number.  Sun4D
806baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * IRQ dispatch is done by:
816baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *
826baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 1) Reading the BW local interrupt table in order to get the bus
836baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *    interrupt mask.
846baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *
856baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *    This table is indexed by SBUS interrupt level which can be
866baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *    derived from the PIL we got interrupted on.
876baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *
886baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 2) For each bus showing interrupt pending from #1, read the
896baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *    SBI interrupt state register.  This will indicate which slots
906baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *    have interrupts pending for that SBUS interrupt level.
916baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg *
926baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 3) Call the genreric IRQ support.
936baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg */
946baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_sbus_handler_irq(int sbusl)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
966baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int bus_mask;
976baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int sbino, slot;
986baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int sbil;
996baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1006baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff;
1016baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	bw_clear_intr_mask(sbusl, bus_mask);
1026baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1036baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	sbil = (sbusl << 2);
1046baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	/* Loop for each pending SBI */
1056baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	for (sbino = 0; bus_mask; sbino++) {
1066baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		unsigned int idx, mask;
1076baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1086baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		bus_mask >>= 1;
1096baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		if (!(bus_mask & 1))
1106baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			continue;
1116baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		/* XXX This seems to ACK the irq twice.  acquire_sbi()
1126baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		 * XXX uses swap, therefore this writes 0xf << sbil,
1136baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		 * XXX then later release_sbi() will write the individual
1146baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		 * XXX bits which were set again.
1156baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		 */
1166baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		mask = acquire_sbi(SBI2DEVID(sbino), 0xf << sbil);
1176baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		mask &= (0xf << sbil);
1186baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1196baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		/* Loop for each pending SBI slot */
1206baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		idx = 0;
1216baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		slot = (1 << sbil);
1226baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		while (mask != 0) {
1236baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			unsigned int pil;
1246baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			struct irq_bucket *p;
1256baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1266baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			idx++;
1276baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			slot <<= 1;
1286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			if (!(mask & slot))
1296baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg				continue;
1306baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			mask &= ~slot;
1326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			pil = sun4d_encode_irq(sbino, sbil, idx);
1336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			p = irq_map[pil];
1356baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			while (p) {
1366baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg				struct irq_bucket *next;
1376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg				next = p->next;
1396baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg				generic_handle_irq(p->irq);
1406baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg				p = next;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
1426baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			release_sbi(SBI2DEVID(sbino), slot);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
147e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborgvoid sun4d_handler_irq(int pil, struct pt_regs *regs)
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1490d84438d98777b0f9425d39121c42f47a06878caAl Viro	struct pt_regs *old_regs;
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* SBUS IRQ level (1 - 7) */
151d4d1ec48c4b1568338931bf8e7833543b78ec9d5Sam Ravnborg	int sbusl = pil_to_sbus[pil];
152e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* FIXME: Is this necessary?? */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cc_get_ipen();
155e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
156d4d1ec48c4b1568338931bf8e7833543b78ec9d5Sam Ravnborg	cc_set_iclr(1 << pil);
157e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
1580d84438d98777b0f9425d39121c42f47a06878caAl Viro	old_regs = set_irq_regs(regs);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irq_enter();
1606baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	if (sbusl == 0) {
1616baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		/* cpu interrupt */
1626baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		struct irq_bucket *p;
1636baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1646baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		p = irq_map[pil];
1656baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		while (p) {
1666baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			struct irq_bucket *next;
1676baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1686baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			next = p->next;
1696baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			generic_handle_irq(p->irq);
1706baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg			p = next;
1716baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		}
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1736baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		/* SBUS interrupt */
1746baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		sun4d_sbus_handler_irq(sbusl);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	irq_exit();
1770d84438d98777b0f9425d39121c42f47a06878caAl Viro	set_irq_regs(old_regs);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1806baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
1816baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_mask_irq(struct irq_data *data)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1836baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	struct sun4d_handler_data *handler_data = data->handler_data;
1846baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int real_irq;
1856baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP
1866baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	int cpuid = handler_data->cpuid;
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
1886baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif
1896baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	real_irq = handler_data->real_irq;
1906baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP
1916baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	spin_lock_irqsave(&sun4d_imsk_lock, flags);
1926baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq));
1936baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
1946baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#else
1956baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	cc_set_imsk(cc_get_imsk() | (1 << real_irq));
1966baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1996baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_unmask_irq(struct irq_data *data)
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2016baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	struct sun4d_handler_data *handler_data = data->handler_data;
2026baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int real_irq;
2036baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP
2046baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	int cpuid = handler_data->cpuid;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
2066baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif
2076baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	real_irq = handler_data->real_irq;
208e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
2096baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&sun4d_imsk_lock, flags);
2116baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | ~(1 << real_irq));
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&sun4d_imsk_lock, flags);
2136baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#else
2146baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	cc_set_imsk(cc_get_imsk() | ~(1 << real_irq));
2156baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2186baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic unsigned int sun4d_startup_irq(struct irq_data *data)
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2206baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq_link(data->irq);
2216baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	sun4d_unmask_irq(data);
2226baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	return 0;
2236baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg}
224f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller
2256baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_shutdown_irq(struct irq_data *data)
2266baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg{
2276baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	sun4d_mask_irq(data);
2286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq_unlink(data->irq);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstruct irq_chip sun4d_irq = {
2326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	.name		= "sun4d",
2336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	.irq_startup	= sun4d_startup_irq,
2346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	.irq_shutdown	= sun4d_shutdown_irq,
2356baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	.irq_unmask	= sun4d_unmask_irq,
2366baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	.irq_mask	= sun4d_mask_irq,
2376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg};
2386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_set_cpu_int(int cpu, int level)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sun4d_send_ipi(cpu, level);
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_clear_ipi(int cpu, int level)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_set_udt(int cpu)
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Setup IRQ distribution scheme. */
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_distribute_irqs(void)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25671d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller	struct device_node *dp;
25771d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int cpuid = cpu_logical_map(1);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cpuid == -1)
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cpuid = cpu_logical_map(0);
26271d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller	for_each_node_by_name(dp, "sbi") {
26371d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		int devid = of_getintprop_default(dp, "device-id", 0);
26471d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		int board = of_getintprop_default(dp, "board#", 0);
265db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg		board_to_cpu[board] = cpuid;
26671d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		set_sbi_tid(devid, cpuid << 3);
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
268e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg	printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
271e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_clear_clock_irq(void)
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
274f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	sbus_readl(&sun4d_timers->l10_timer_limit);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_load_profile_irq(int cpu, unsigned int limit)
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bw_set_prof_limit(cpu, limit);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
282f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_load_profile_irqs(void)
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
284f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	int cpu = 0, mid;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
286f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	while (!cpu_find_by_instance(cpu, NULL, &mid)) {
287f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		sun4d_load_profile_irq(mid >> 3, 0);
288f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		cpu++;
289f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	}
290f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller}
291f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
2921d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborgunsigned int sun4d_build_device_irq(struct platform_device *op,
2931d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg                                    unsigned int real_irq)
2941d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg{
2951d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	struct device_node *dp = op->dev.of_node;
2961d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	struct device_node *io_unit, *sbi = dp->parent;
2971d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	const struct linux_prom_registers *regs;
2986baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	struct sun4d_handler_data *handler_data;
2996baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int pil;
3006baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int irq;
3011d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	int board, slot;
3021d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	int sbusl;
3031d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3046baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq = 0;
3051d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	while (sbi) {
3061d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		if (!strcmp(sbi->name, "sbi"))
3071d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg			break;
3081d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3091d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		sbi = sbi->parent;
3101d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	}
3111d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	if (!sbi)
3121d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		goto err_out;
3131d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3141d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	regs = of_get_property(dp, "reg", NULL);
3151d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	if (!regs)
3161d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		goto err_out;
3171d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3181d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	slot = regs->which_io;
3191d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3201d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	/*
3211d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	 *  If SBI's parent is not io-unit or the io-unit lacks
3221d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	 * a "board#" property, something is very wrong.
3231d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	 */
3241d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
3251d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		printk("%s: Error, parent is not io-unit.\n", sbi->full_name);
3261d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		goto err_out;
3271d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	}
3281d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	io_unit = sbi->parent;
3291d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	board = of_getintprop_default(io_unit, "board#", -1);
3301d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	if (board == -1) {
3311d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		printk("%s: Error, lacks board# property.\n", io_unit->full_name);
3321d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg		goto err_out;
3331d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	}
3341d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3351d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	sbusl = pil_to_sbus[real_irq];
3361d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	if (sbusl)
3376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		pil = sun4d_encode_irq(board, sbusl, slot);
3386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	else
3396baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		pil = real_irq;
3406baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
3416baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq = irq_alloc(real_irq, pil);
3426baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	if (irq == 0)
3436baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		goto err_out;
3446baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
3456baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	handler_data = irq_get_handler_data(irq);
3466baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	if (unlikely(handler_data))
3476baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		goto err_out;
3486baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg
3496baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
3506baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	if (unlikely(!handler_data)) {
3516baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
3526baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg		prom_halt();
3536baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	}
3546baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	handler_data->cpuid    = board_to_cpu[board];
3556baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	handler_data->real_irq = real_irq;
3566baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq_set_chip_and_handler_name(irq, &sun4d_irq,
3576baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	                              handle_level_irq, "level");
3586baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq_set_handler_data(irq, handler_data);
3591d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
3601d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborgerr_out:
3611d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	return real_irq;
3621d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg}
3631d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg
364f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_fixup_trap_table(void)
365f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller{
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
367f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	unsigned long flags;
368f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
369f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
370f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	/* Adjust so that we jump directly to smp4d_ticker */
371f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	lvl14_save[2] += smp4d_ticker - real_irq_entry;
372f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
373f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	/* For SMP we use the level 14 ticker, however the bootup code
374f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 * has copied the firmware's level 14 vector into the boot cpu's
375f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 * trap table, we must fix this now or we get squashed.
376f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 */
377f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	local_irq_save(flags);
378f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
379f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	trap_table->inst_one = lvl14_save[0];
380f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	trap_table->inst_two = lvl14_save[1];
381f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	trap_table->inst_three = lvl14_save[2];
382f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	trap_table->inst_four = lvl14_save[3];
383f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	local_flush_cache_all();
384f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	local_irq_restore(flags);
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
386f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller}
387f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
388f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_init_timers(irq_handler_t counter_fn)
389f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller{
390f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	struct device_node *dp;
391f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	struct resource res;
3926baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	unsigned int irq;
393f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	const u32 *reg;
394f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	int err;
395f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
396f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	dp = of_find_node_by_name(NULL, "cpu-unit");
397f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	if (!dp) {
398f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_printf("sun4d_init_timers: Unable to find cpu-unit\n");
399f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_halt();
400f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	}
401f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
402f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	/* Which cpu-unit we use is arbitrary, we can view the bootbus timer
403f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 * registers via any cpu's mapping.  The first 'reg' property is the
404f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 * bootbus.
405f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	 */
406f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	reg = of_get_property(dp, "reg", NULL);
407c2e27c359ab76fecbbd292dbfc0bcfa8399afdd9Nicolas Palix	of_node_put(dp);
408f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	if (!reg) {
409f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_printf("sun4d_init_timers: No reg property\n");
410f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_halt();
411f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	}
412f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
413f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	res.start = reg[1];
414f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	res.end = reg[2] - 1;
415f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	res.flags = reg[0] & 0xff;
416f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT,
417f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller				  sizeof(struct sun4d_timer_regs), "user timer");
418f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	if (!sun4d_timers) {
419f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_printf("sun4d_init_timers: Can't map timer regs\n");
420f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller		prom_halt();
421f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	}
422f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller
423f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	master_l10_counter = &sun4d_timers->l10_cur_count;
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4276baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ);
4286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
429f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	if (err) {
430e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg		prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
431e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg		             err);
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		prom_halt();
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
434f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	sun4d_load_profile_irqs();
435f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller	sun4d_fixup_trap_table();
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_init_sbi_irq(void)
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
44071d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller	struct device_node *dp;
441f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller	int target_cpu = 0;
442f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller
443f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller#ifdef CONFIG_SMP
444f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller	target_cpu = boot_cpu_id;
445f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller#endif
44671d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller	for_each_node_by_name(dp, "sbi") {
44771d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		int devid = of_getintprop_default(dp, "device-id", 0);
44871d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		int board = of_getintprop_default(dp, "board#", 0);
44971d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		unsigned int mask;
45071d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller
451f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller		set_sbi_tid(devid, target_cpu << 3);
452db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg		board_to_cpu[board] = target_cpu;
453f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Get rid of pending irqs from PROM */
45571d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller		mask = acquire_sbi(devid, 0xffffffff);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (mask) {
457e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg			printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
458e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg			       mask, board);
45971d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller			release_sbi(devid, mask);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_init_IRQ(void)
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_disable();
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
470bbdc2661eabddd442240533a66b2290f77d89cccSam Ravnborg
4716baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg	sparc_irq_config.init_timers      = sun4d_init_timers;
4721d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg	sparc_irq_config.build_device_irq = sun4d_build_device_irq;
473bbdc2661eabddd442240533a66b2290f77d89cccSam Ravnborg
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP);
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Cannot enable interrupts until OBP ticker is disabled. */
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
481