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