PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/ppc/syslib/ppc8xx_pic.c

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