Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17 127 lines 3.4 kB view raw
1#include <linux/config.h> 2#include <linux/module.h> 3#include <linux/stddef.h> 4#include <linux/init.h> 5#include <linux/sched.h> 6#include <linux/signal.h> 7#include <linux/interrupt.h> 8#include <asm/irq.h> 9#include <asm/io.h> 10#include <asm/8xx_immap.h> 11#include <asm/mpc8xx.h> 12#include "ppc8xx_pic.h" 13 14extern int cpm_get_irq(struct pt_regs *regs); 15 16/* The 8xx internal interrupt controller. It is usually 17 * the only interrupt controller. Some boards, like the MBX and 18 * Sandpoint have the 8259 as a secondary controller. Depending 19 * upon the processor type, the internal controller can have as 20 * few as 16 interrups or as many as 64. We could use the 21 * "clear_bit()" and "set_bit()" functions like other platforms, 22 * but they are overkill for us. 23 */ 24 25static void m8xx_mask_irq(unsigned int irq_nr) 26{ 27 int bit, word; 28 29 bit = irq_nr & 0x1f; 30 word = irq_nr >> 5; 31 32 ppc_cached_irq_mask[word] &= ~(1 << (31-bit)); 33 out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]); 34} 35 36static void m8xx_unmask_irq(unsigned int irq_nr) 37{ 38 int bit, word; 39 40 bit = irq_nr & 0x1f; 41 word = irq_nr >> 5; 42 43 ppc_cached_irq_mask[word] |= (1 << (31-bit)); 44 out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]); 45} 46 47static void m8xx_end_irq(unsigned int irq_nr) 48{ 49 if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) 50 && irq_desc[irq_nr].action) { 51 int bit, word; 52 53 bit = irq_nr & 0x1f; 54 word = irq_nr >> 5; 55 56 ppc_cached_irq_mask[word] |= (1 << (31-bit)); 57 out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]); 58 } 59} 60 61 62static void m8xx_mask_and_ack(unsigned int irq_nr) 63{ 64 int bit, word; 65 66 bit = irq_nr & 0x1f; 67 word = irq_nr >> 5; 68 69 ppc_cached_irq_mask[word] &= ~(1 << (31-bit)); 70 out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask, ppc_cached_irq_mask[word]); 71 out_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend, 1 << (31-bit)); 72} 73 74struct hw_interrupt_type ppc8xx_pic = { 75 .typename = " 8xx SIU ", 76 .enable = m8xx_unmask_irq, 77 .disable = m8xx_mask_irq, 78 .ack = m8xx_mask_and_ack, 79 .end = m8xx_end_irq, 80}; 81 82/* 83 * We either return a valid interrupt or -1 if there is nothing pending 84 */ 85int 86m8xx_get_irq(struct pt_regs *regs) 87{ 88 int irq; 89 90 /* For MPC8xx, read the SIVEC register and shift the bits down 91 * to get the irq number. 92 */ 93 irq = in_be32(&((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec) >> 26; 94 95 /* 96 * When we read the sivec without an interrupt to process, we will 97 * get back SIU_LEVEL7. In this case, return -1 98 */ 99 if (irq == CPM_INTERRUPT) 100 irq = CPM_IRQ_OFFSET + cpm_get_irq(regs); 101#if defined(CONFIG_PCI) 102 else if (irq == ISA_BRIDGE_INT) { 103 int isa_irq; 104 105 if ((isa_irq = i8259_poll(regs)) >= 0) 106 irq = I8259_IRQ_OFFSET + isa_irq; 107 } 108#endif /* CONFIG_PCI */ 109 else if (irq == SIU_LEVEL7) 110 irq = -1; 111 112 return irq; 113} 114 115#if defined(CONFIG_MBX) && defined(CONFIG_PCI) 116/* Only the MBX uses the external 8259. This allows us to catch standard 117 * drivers that may mess up the internal interrupt controllers, and also 118 * allow them to run without modification on the MBX. 119 */ 120void mbx_i8259_action(int irq, void *dev_id, struct pt_regs *regs) 121{ 122 /* This interrupt handler never actually gets called. It is 123 * installed only to unmask the 8259 cascade interrupt in the SIU 124 * and to make the 8259 cascade interrupt visible in /proc/interrupts. 125 */ 126} 127#endif /* CONFIG_PCI */