PageRenderTime 36ms CodeModel.GetById 13ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 1ms

/arch/ppc/platforms/adir_pic.c

https://bitbucket.org/evzijst/gittest
C | 130 lines | 83 code | 25 blank | 22 comment | 9 complexity | e9a2ef31c6bc894920447bf26ebebeac MD5 | raw file
  1/*
  2 * arch/ppc/platforms/adir_pic.c
  3 *
  4 * Interrupt controller support for SBS Adirondack
  5 *
  6 * By Michael Sokolov <msokolov@ivan.Harhan.ORG>
  7 * based on the K2 and SCM versions by Matt Porter <mporter@mvista.com>
  8 */
  9
 10#include <linux/stddef.h>
 11#include <linux/init.h>
 12#include <linux/sched.h>
 13#include <linux/pci.h>
 14#include <linux/interrupt.h>
 15
 16#include <asm/io.h>
 17#include <asm/i8259.h>
 18#include "adir.h"
 19
 20static void adir_onboard_pic_enable(unsigned int irq);
 21static void adir_onboard_pic_disable(unsigned int irq);
 22
 23__init static void
 24adir_onboard_pic_init(void)
 25{
 26	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
 27
 28	/* Disable all Adirondack onboard interrupts */
 29	out_be16(maskreg, 0xFFFF);
 30}
 31
 32static int
 33adir_onboard_pic_get_irq(void)
 34{
 35	volatile u_short *statreg = (volatile u_short *) ADIR_PROCA_INT_STAT;
 36	int irq;
 37	u_short int_status, int_test;
 38
 39	int_status = in_be16(statreg);
 40	for (irq = 0, int_test = 1; irq < 16; irq++, int_test <<= 1) {
 41		if (int_status & int_test)
 42			break;
 43	}
 44
 45	if (irq == 16)
 46		return -1;
 47
 48	return (irq+16);
 49}
 50
 51static void
 52adir_onboard_pic_enable(unsigned int irq)
 53{
 54	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
 55
 56	/* Change irq to Adirondack onboard native value */
 57	irq -= 16;
 58
 59	/* Enable requested irq number */
 60	out_be16(maskreg, in_be16(maskreg) & ~(1 << irq));
 61}
 62
 63static void
 64adir_onboard_pic_disable(unsigned int irq)
 65{
 66	volatile u_short *maskreg = (volatile u_short *) ADIR_PROCA_INT_MASK;
 67
 68	/* Change irq to Adirondack onboard native value */
 69	irq -= 16;
 70
 71	/* Disable requested irq number */
 72	out_be16(maskreg, in_be16(maskreg) | (1 << irq));
 73}
 74
 75static struct hw_interrupt_type adir_onboard_pic = {
 76	" ADIR PIC ",
 77	NULL,
 78	NULL,
 79	adir_onboard_pic_enable,		/* unmask */
 80	adir_onboard_pic_disable,		/* mask */
 81	adir_onboard_pic_disable,		/* mask and ack */
 82	NULL,
 83	NULL
 84};
 85
 86static struct irqaction noop_action = {
 87	.handler	= no_action,
 88	.flags          = SA_INTERRUPT,
 89	.mask           = CPU_MASK_NONE,
 90	.name           = "82c59 primary cascade",
 91};
 92
 93/*
 94 * Linux interrupt values are assigned as follows:
 95 *
 96 * 	0-15		VT82C686 8259 interrupts
 97 * 	16-31		Adirondack CPLD interrupts
 98 */
 99__init void
100adir_init_IRQ(void)
101{
102	int	i;
103
104	/* Initialize the cascaded 8259's on the VT82C686 */
105	for (i=0; i<16; i++)
106		irq_desc[i].handler = &i8259_pic;
107	i8259_init(NULL);
108
109	/* Initialize Adirondack CPLD PIC and enable 8259 interrupt cascade */
110	for (i=16; i<32; i++)
111		irq_desc[i].handler = &adir_onboard_pic;
112	adir_onboard_pic_init();
113
114	/* Enable 8259 interrupt cascade */
115	setup_irq(ADIR_IRQ_VT82C686_INTR, &noop_action);
116}
117
118int
119adir_get_irq(struct pt_regs *regs)
120{
121	int	irq;
122
123	if ((irq = adir_onboard_pic_get_irq()) < 0)
124		return irq;
125
126	if (irq == ADIR_IRQ_VT82C686_INTR)
127		irq = i8259_irq(regs);
128
129	return irq;
130}