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> 175fcafb7a23e35b2f1a5243f4dd536240f52c8cebDaniel Hellstrom#include <asm/setup.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981265fd93bc40c7c43fd36796571786ae3df00e0Sam Ravnborg#include "kernel.h" 2032231a66b4e1b649c346dc76b7d191f7e64a663aAl Viro#include "irq.h" 2132231a66b4e1b649c346dc76b7d191f7e64a663aAl Viro 22e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg/* Sun4d interrupts fall roughly into two categories. SBUS and 23e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * cpu local. CPU local interrupts cover the timer interrupts 24e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * and whatnot, and we encode those as normal PILs between 25e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg * 0 and 15. 266baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * SBUS interrupts are encodes as a combination of board, level and slot. 27e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg */ 28e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 296baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstruct sun4d_handler_data { 306baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int cpuid; /* target cpu */ 316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int real_irq; /* interrupt level */ 326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg}; 336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 356baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic unsigned int sun4d_encode_irq(int board, int lvl, int slot) 366baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg{ 376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg return (board + 1) << 5 | (lvl << 2) | slot; 386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg} 396baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 40f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstruct sun4d_timer_regs { 41f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller u32 l10_timer_limit; 42f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller u32 l10_cur_countx; 43f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller u32 l10_limit_noclear; 44f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller u32 ctrl; 45f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller u32 l10_cur_count; 46f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller}; 47f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 48f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic struct sun4d_timer_regs __iomem *sun4d_timers; 49f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 506baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#define SUN4D_TIMER_IRQ 10 51db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg 52db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg/* Specify which cpu handle interrupts from which board. 53db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg * Index is board - value is cpu. 54db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg */ 55db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborgstatic unsigned char board_to_cpu[32]; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int pil_to_sbus[] = { 58e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 59e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 60e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 1, 61e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 2, 62e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 63e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 3, 64e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 65e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 4, 66e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 67e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 5, 68e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 69e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 6, 70e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 71e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 7, 72e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 73e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 0, 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 76f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller/* Exported for sun4d_smp.c */ 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsDEFINE_SPINLOCK(sun4d_imsk_lock); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 796baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg/* SBUS interrupts are encoded integers including the board number 806baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * (plus one), the SBUS level, and the SBUS slot number. Sun4D 816baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * IRQ dispatch is done by: 826baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 836baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 1) Reading the BW local interrupt table in order to get the bus 846baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * interrupt mask. 856baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 866baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * This table is indexed by SBUS interrupt level which can be 876baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * derived from the PIL we got interrupted on. 886baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 896baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 2) For each bus showing interrupt pending from #1, read the 906baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * SBI interrupt state register. This will indicate which slots 916baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * have interrupts pending for that SBUS interrupt level. 926baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 936baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg * 3) Call the genreric IRQ support. 946baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg */ 956baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_sbus_handler_irq(int sbusl) 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 976baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int bus_mask; 986baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int sbino, slot; 996baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int sbil; 1006baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1016baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg bus_mask = bw_get_intr_mask(sbusl) & 0x3ffff; 1026baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg bw_clear_intr_mask(sbusl, bus_mask); 1036baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1046baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg sbil = (sbusl << 2); 1056baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg /* Loop for each pending SBI */ 106ea160584574e345495e75ee4a7d3a7dbcad9e16coftedal for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1) { 1076baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int idx, mask; 1086baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 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 slot = (1 << sbil); 121ea160584574e345495e75ee4a7d3a7dbcad9e16coftedal for (idx = 0; mask != 0; idx++, slot <<= 1) { 1226baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int pil; 1236baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct irq_bucket *p; 1246baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1256baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg if (!(mask & slot)) 1266baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg continue; 1276baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg mask &= ~slot; 129ea160584574e345495e75ee4a7d3a7dbcad9e16coftedal pil = sun4d_encode_irq(sbino, sbusl, idx); 1306baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg p = irq_map[pil]; 1326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg while (p) { 1336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct irq_bucket *next; 1346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1356baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg next = p->next; 1366baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg generic_handle_irq(p->irq); 1376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg p = next; 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1396baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg release_sbi(SBI2DEVID(sbino), slot); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 144e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborgvoid sun4d_handler_irq(int pil, struct pt_regs *regs) 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1460d84438d98777b0f9425d39121c42f47a06878caAl Viro struct pt_regs *old_regs; 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* SBUS IRQ level (1 - 7) */ 148d4d1ec48c4b1568338931bf8e7833543b78ec9d5Sam Ravnborg int sbusl = pil_to_sbus[pil]; 149e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* FIXME: Is this necessary?? */ 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc_get_ipen(); 152e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 153d4d1ec48c4b1568338931bf8e7833543b78ec9d5Sam Ravnborg cc_set_iclr(1 << pil); 154e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 15555dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom#ifdef CONFIG_SMP 15655dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom /* 15755dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom * Check IPI data structures after IRQ has been cleared. Hard and Soft 15855dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom * IRQ can happen at the same time, so both cases are always handled. 15955dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom */ 16055dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom if (pil == SUN4D_IPI_IRQ) 16155dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom sun4d_ipi_interrupt(); 16255dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom#endif 16355dd23eca666876e6028aa35d5e391cfced54871Daniel Hellstrom 1640d84438d98777b0f9425d39121c42f47a06878caAl Viro old_regs = set_irq_regs(regs); 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_enter(); 1666baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg if (sbusl == 0) { 1676baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg /* cpu interrupt */ 1686baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct irq_bucket *p; 1696baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1706baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg p = irq_map[pil]; 1716baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg while (p) { 1726baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct irq_bucket *next; 1736baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1746baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg next = p->next; 1756baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg generic_handle_irq(p->irq); 1766baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg p = next; 1776baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg } 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1796baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg /* SBUS interrupt */ 1806baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg sun4d_sbus_handler_irq(sbusl); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq_exit(); 1830d84438d98777b0f9425d39121c42f47a06878caAl Viro set_irq_regs(old_regs); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1866baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 1876baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_mask_irq(struct irq_data *data) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1896baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct sun4d_handler_data *handler_data = data->handler_data; 1906baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int real_irq; 1916baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP 1926baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg int cpuid = handler_data->cpuid; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 1946baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif 1956baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg real_irq = handler_data->real_irq; 1966baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP 1976baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg spin_lock_irqsave(&sun4d_imsk_lock, flags); 1986baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) | (1 << real_irq)); 1996baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg spin_unlock_irqrestore(&sun4d_imsk_lock, flags); 2006baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#else 2016baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg cc_set_imsk(cc_get_imsk() | (1 << real_irq)); 2026baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2056baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_unmask_irq(struct irq_data *data) 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2076baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg struct sun4d_handler_data *handler_data = data->handler_data; 2086baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int real_irq; 2096baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP 2106baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg int cpuid = handler_data->cpuid; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long flags; 2126baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif 2136baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg real_irq = handler_data->real_irq; 214e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 2156baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#ifdef CONFIG_SMP 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irqsave(&sun4d_imsk_lock, flags); 217ea160584574e345495e75ee4a7d3a7dbcad9e16coftedal cc_set_imsk_other(cpuid, cc_get_imsk_other(cpuid) & ~(1 << real_irq)); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irqrestore(&sun4d_imsk_lock, flags); 2196baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#else 220ea160584574e345495e75ee4a7d3a7dbcad9e16coftedal cc_set_imsk(cc_get_imsk() & ~(1 << real_irq)); 2216baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg#endif 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2246baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic unsigned int sun4d_startup_irq(struct irq_data *data) 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2266baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg irq_link(data->irq); 2276baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg sun4d_unmask_irq(data); 2286baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg return 0; 2296baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg} 230f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller 2316baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstatic void sun4d_shutdown_irq(struct irq_data *data) 2326baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg{ 2336baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg sun4d_mask_irq(data); 2346baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg irq_unlink(data->irq); 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2376baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborgstruct irq_chip sun4d_irq = { 2386baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg .name = "sun4d", 2396baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg .irq_startup = sun4d_startup_irq, 2406baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg .irq_shutdown = sun4d_shutdown_irq, 2416baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg .irq_unmask = sun4d_unmask_irq, 2426baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg .irq_mask = sun4d_mask_irq, 2436baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg}; 2446baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_set_cpu_int(int cpu, int level) 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sun4d_send_ipi(cpu, level); 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_clear_ipi(int cpu, int level) 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_set_udt(int cpu) 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Setup IRQ distribution scheme. */ 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_distribute_irqs(void) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 26271d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller struct device_node *dp; 26371d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int cpuid = cpu_logical_map(1); 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cpuid == -1) 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cpuid = cpu_logical_map(0); 26871d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller for_each_node_by_name(dp, "sbi") { 26971d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller int devid = of_getintprop_default(dp, "device-id", 0); 27071d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller int board = of_getintprop_default(dp, "board#", 0); 271db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg board_to_cpu[board] = cpuid; 27271d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller set_sbi_tid(devid, cpuid << 3); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 274e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid); 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 277e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_clear_clock_irq(void) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 280f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sbus_readl(&sun4d_timers->l10_timer_limit); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sun4d_load_profile_irq(int cpu, unsigned int limit) 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bw_set_prof_limit(cpu, limit); 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 288f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_load_profile_irqs(void) 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 290f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller int cpu = 0, mid; 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 292f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller while (!cpu_find_by_instance(cpu, NULL, &mid)) { 293f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sun4d_load_profile_irq(mid >> 3, 0); 294f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller cpu++; 295f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller } 296f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller} 297f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 2985fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedalunsigned int _sun4d_build_device_irq(unsigned int real_irq, 2995fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal unsigned int pil, 3005fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal unsigned int board) 3015fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal{ 3025fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal struct sun4d_handler_data *handler_data; 3035fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal unsigned int irq; 3045fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3055fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq = irq_alloc(real_irq, pil); 3065fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal if (irq == 0) { 3075fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal prom_printf("IRQ: allocate for %d %d %d failed\n", 3085fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal real_irq, pil, board); 3095fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal goto err_out; 3105fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal } 3115fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3125fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal handler_data = irq_get_handler_data(irq); 3135fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal if (unlikely(handler_data)) 3145fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal goto err_out; 3155fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3165fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC); 3175fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal if (unlikely(!handler_data)) { 3185fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n"); 3195fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal prom_halt(); 3205fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal } 3215fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal handler_data->cpuid = board_to_cpu[board]; 3225fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal handler_data->real_irq = real_irq; 3235fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq_set_chip_and_handler_name(irq, &sun4d_irq, 3245fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal handle_level_irq, "level"); 3255fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq_set_handler_data(irq, handler_data); 3265fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3275fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedalerr_out: 3285fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal return irq; 3295fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal} 3305fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3315fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3325fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 3331d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborgunsigned int sun4d_build_device_irq(struct platform_device *op, 3341d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg unsigned int real_irq) 3351d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg{ 3361d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg struct device_node *dp = op->dev.of_node; 3379eeb08986f41c0740306f6f56cf04e619e2fe525oftedal struct device_node *board_parent, *bus = dp->parent; 3389eeb08986f41c0740306f6f56cf04e619e2fe525oftedal char *bus_connection; 3391d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg const struct linux_prom_registers *regs; 3406baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int pil; 3416baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int irq; 3421d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg int board, slot; 3431d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg int sbusl; 3441d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3455fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq = real_irq; 3469eeb08986f41c0740306f6f56cf04e619e2fe525oftedal while (bus) { 3479eeb08986f41c0740306f6f56cf04e619e2fe525oftedal if (!strcmp(bus->name, "sbi")) { 3489eeb08986f41c0740306f6f56cf04e619e2fe525oftedal bus_connection = "io-unit"; 3491d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg break; 3509eeb08986f41c0740306f6f56cf04e619e2fe525oftedal } 3519eeb08986f41c0740306f6f56cf04e619e2fe525oftedal 3529eeb08986f41c0740306f6f56cf04e619e2fe525oftedal if (!strcmp(bus->name, "bootbus")) { 3539eeb08986f41c0740306f6f56cf04e619e2fe525oftedal bus_connection = "cpu-unit"; 3549eeb08986f41c0740306f6f56cf04e619e2fe525oftedal break; 3559eeb08986f41c0740306f6f56cf04e619e2fe525oftedal } 3561d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3579eeb08986f41c0740306f6f56cf04e619e2fe525oftedal bus = bus->parent; 3581d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg } 3599eeb08986f41c0740306f6f56cf04e619e2fe525oftedal if (!bus) 3601d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg goto err_out; 3611d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3621d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg regs = of_get_property(dp, "reg", NULL); 3631d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg if (!regs) 3641d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg goto err_out; 3651d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3661d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg slot = regs->which_io; 3671d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3681d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg /* 3699eeb08986f41c0740306f6f56cf04e619e2fe525oftedal * If Bus nodes parent is not io-unit/cpu-unit or the io-unit/cpu-unit 3709eeb08986f41c0740306f6f56cf04e619e2fe525oftedal * lacks a "board#" property, something is very wrong. 3711d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg */ 3729eeb08986f41c0740306f6f56cf04e619e2fe525oftedal if (!bus->parent || strcmp(bus->parent->name, bus_connection)) { 3739eeb08986f41c0740306f6f56cf04e619e2fe525oftedal printk(KERN_ERR "%s: Error, parent is not %s.\n", 3749eeb08986f41c0740306f6f56cf04e619e2fe525oftedal bus->full_name, bus_connection); 3751d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg goto err_out; 3761d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg } 3779eeb08986f41c0740306f6f56cf04e619e2fe525oftedal board_parent = bus->parent; 3789eeb08986f41c0740306f6f56cf04e619e2fe525oftedal board = of_getintprop_default(board_parent, "board#", -1); 3791d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg if (board == -1) { 3809eeb08986f41c0740306f6f56cf04e619e2fe525oftedal printk(KERN_ERR "%s: Error, lacks board# property.\n", 3819eeb08986f41c0740306f6f56cf04e619e2fe525oftedal board_parent->full_name); 3821d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg goto err_out; 3831d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg } 3841d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3851d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg sbusl = pil_to_sbus[real_irq]; 3861d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg if (sbusl) 3876baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg pil = sun4d_encode_irq(board, sbusl, slot); 3886baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg else 3896baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg pil = real_irq; 3906baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg 3915fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq = _sun4d_build_device_irq(real_irq, pil, board); 3921d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborgerr_out: 3935fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal return irq; 3941d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg} 3951d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg 3965fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedalunsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq) 3975fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal{ 3985fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal return _sun4d_build_device_irq(real_irq, real_irq, board); 3995fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal} 4005fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 4015fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 402f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_fixup_trap_table(void) 403f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller{ 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 405f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller unsigned long flags; 406f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; 407f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 408f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller /* Adjust so that we jump directly to smp4d_ticker */ 409f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller lvl14_save[2] += smp4d_ticker - real_irq_entry; 410f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 411f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller /* For SMP we use the level 14 ticker, however the bootup code 412f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller * has copied the firmware's level 14 vector into the boot cpu's 413f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller * trap table, we must fix this now or we get squashed. 414f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller */ 415f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller local_irq_save(flags); 416f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ 417f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller trap_table->inst_one = lvl14_save[0]; 418f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller trap_table->inst_two = lvl14_save[1]; 419f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller trap_table->inst_three = lvl14_save[2]; 420f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller trap_table->inst_four = lvl14_save[3]; 421f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller local_flush_cache_all(); 422f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller local_irq_restore(flags); 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 424f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller} 425f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 426f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Millerstatic void __init sun4d_init_timers(irq_handler_t counter_fn) 427f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller{ 428f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller struct device_node *dp; 429f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller struct resource res; 4306baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg unsigned int irq; 431f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller const u32 *reg; 432f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller int err; 4335fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal int board; 434f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 435f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller dp = of_find_node_by_name(NULL, "cpu-unit"); 436f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller if (!dp) { 437f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_printf("sun4d_init_timers: Unable to find cpu-unit\n"); 438f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_halt(); 439f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller } 440f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 441f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller /* Which cpu-unit we use is arbitrary, we can view the bootbus timer 442f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller * registers via any cpu's mapping. The first 'reg' property is the 443f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller * bootbus. 444f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller */ 445f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller reg = of_get_property(dp, "reg", NULL); 446f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller if (!reg) { 447f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_printf("sun4d_init_timers: No reg property\n"); 448f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_halt(); 449f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller } 450f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 4515fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal board = of_getintprop_default(dp, "board#", -1); 4525fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal if (board == -1) { 4535fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal prom_printf("sun4d_init_timers: No board# property on cpu-unit\n"); 4545fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal prom_halt(); 4555fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal } 4565fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 4575fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal of_node_put(dp); 4585fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal 459f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller res.start = reg[1]; 460f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller res.end = reg[2] - 1; 461f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller res.flags = reg[0] & 0xff; 462f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT, 463f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sizeof(struct sun4d_timer_regs), "user timer"); 464f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller if (!sun4d_timers) { 465f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_printf("sun4d_init_timers: Can't map timer regs\n"); 466f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller prom_halt(); 467f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller } 468f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller 469f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds master_l10_counter = &sun4d_timers->l10_cur_count; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4735fba17084e5d1b00bf24e17b2b580cfa7705e7beoftedal irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); 4746baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 475f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller if (err) { 476e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg prom_printf("sun4d_init_timers: request_irq() failed with %d\n", 477e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg err); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds prom_halt(); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 480f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sun4d_load_profile_irqs(); 481f5f1085720c4799dd1437f78e28e40c8dd557bbaDavid S. Miller sun4d_fixup_trap_table(); 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_init_sbi_irq(void) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 48671d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller struct device_node *dp; 4875fcafb7a23e35b2f1a5243f4dd536240f52c8cebDaniel Hellstrom int target_cpu; 488f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller 489f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller target_cpu = boot_cpu_id; 49071d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller for_each_node_by_name(dp, "sbi") { 49171d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller int devid = of_getintprop_default(dp, "device-id", 0); 49271d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller int board = of_getintprop_default(dp, "board#", 0); 49371d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller unsigned int mask; 49471d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller 495f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller set_sbi_tid(devid, target_cpu << 3); 496db1cdd146a0814b6f312fe1a7fa1ab87ac177b2aSam Ravnborg board_to_cpu[board] = target_cpu; 497f8376e933c4e80663f6f66a5b5dd90390a0feba2David S. Miller 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Get rid of pending irqs from PROM */ 49971d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller mask = acquire_sbi(devid, 0xffffffff); 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mask) { 501e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n", 502e54f8548ff5285f57125c08d8092eec38dd05e0dSam Ravnborg mask, board); 50371d3721189c0f4fad105a81e052bddfb826b693bDavid S. Miller release_sbi(devid, mask); 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid __init sun4d_init_IRQ(void) 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds local_irq_disable(); 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); 514bbdc2661eabddd442240533a66b2290f77d89cccSam Ravnborg 5156baa9b20a68a88c2fd751cbe8d7652009379351bSam Ravnborg sparc_irq_config.init_timers = sun4d_init_timers; 5161d05995b0880b23353741d5b2b826f7c2fd6a296Sam Ravnborg sparc_irq_config.build_device_irq = sun4d_build_device_irq; 517bbdc2661eabddd442240533a66b2290f77d89cccSam Ravnborg 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_SMP 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM); 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds BTFIXUPSET_CALL(set_irq_udt, sun4d_set_udt, BTFIXUPCALL_NOP); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Cannot enable interrupts until OBP ticker is disabled. */ 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 525