2 * $Id: setup.c,v 1.5 2004/03/16 00:07:50 lethal Exp $
3 * Copyright (C) 2000 YAEGASHI Takeshi
4 * Hitachi HD64461 companion chip support
7 #include <linux/config.h>
8 #include <linux/sched.h>
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/param.h>
12 #include <linux/interrupt.h>
13 #include <linux/init.h>
14 #include <linux/irq.h>
19 #include <asm/hd64461/hd64461.h>
21 static void disable_hd64461_irq(unsigned int irq
)
25 unsigned short mask
= 1 << (irq
- HD64461_IRQBASE
);
27 local_irq_save(flags
);
28 nimr
= inw(HD64461_NIMR
);
30 outw(nimr
, HD64461_NIMR
);
31 local_irq_restore(flags
);
34 static void enable_hd64461_irq(unsigned int irq
)
38 unsigned short mask
= 1 << (irq
- HD64461_IRQBASE
);
40 local_irq_save(flags
);
41 nimr
= inw(HD64461_NIMR
);
43 outw(nimr
, HD64461_NIMR
);
44 local_irq_restore(flags
);
47 static void mask_and_ack_hd64461(unsigned int irq
)
49 disable_hd64461_irq(irq
);
50 #ifdef CONFIG_HD64461_ENABLER
51 if (irq
== HD64461_IRQBASE
+ 13)
52 outb(0x00, HD64461_PCC1CSCR
);
56 static void end_hd64461_irq(unsigned int irq
)
58 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
)))
59 enable_hd64461_irq(irq
);
62 static unsigned int startup_hd64461_irq(unsigned int irq
)
64 enable_hd64461_irq(irq
);
68 static void shutdown_hd64461_irq(unsigned int irq
)
70 disable_hd64461_irq(irq
);
73 static struct hw_interrupt_type hd64461_irq_type
= {
74 .typename
= "HD64461-IRQ",
75 .startup
= startup_hd64461_irq
,
76 .shutdown
= shutdown_hd64461_irq
,
77 .enable
= enable_hd64461_irq
,
78 .disable
= disable_hd64461_irq
,
79 .ack
= mask_and_ack_hd64461
,
80 .end
= end_hd64461_irq
,
83 static irqreturn_t
hd64461_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
86 "HD64461: spurious interrupt, nirr: 0x%x nimr: 0x%x\n",
87 inw(HD64461_NIRR
), inw(HD64461_NIMR
));
93 int (*func
) (int, void *);
95 } hd64461_demux
[HD64461_IRQ_NUM
];
97 void hd64461_register_irq_demux(int irq
,
98 int (*demux
) (int irq
, void *dev
), void *dev
)
100 hd64461_demux
[irq
- HD64461_IRQBASE
].func
= demux
;
101 hd64461_demux
[irq
- HD64461_IRQBASE
].dev
= dev
;
104 EXPORT_SYMBOL(hd64461_register_irq_demux
);
106 void hd64461_unregister_irq_demux(int irq
)
108 hd64461_demux
[irq
- HD64461_IRQBASE
].func
= 0;
111 EXPORT_SYMBOL(hd64461_unregister_irq_demux
);
113 int hd64461_irq_demux(int irq
)
115 if (irq
== CONFIG_HD64461_IRQ
) {
117 unsigned short nirr
= inw(HD64461_NIRR
);
118 unsigned short nimr
= inw(HD64461_NIMR
);
122 for (bit
= 1, i
= 0; i
< 16; bit
<<= 1, i
++)
126 irq
= CONFIG_HD64461_IRQ
;
128 irq
= HD64461_IRQBASE
+ i
;
129 if (hd64461_demux
[i
].func
!= 0) {
130 irq
= hd64461_demux
[i
].func(irq
, hd64461_demux
[i
].dev
);
134 return __irq_demux(irq
);
137 static struct irqaction irq0
= { hd64461_interrupt
, SA_INTERRUPT
, CPU_MASK_NONE
, "HD64461", NULL
, NULL
};
139 int __init
setup_hd64461(void)
147 "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
148 CONFIG_HD64461_IOBASE
, CONFIG_HD64461_IRQ
, HD64461_IRQBASE
,
149 HD64461_IRQBASE
+ 15);
151 #if defined(CONFIG_CPU_SUBTYPE_SH7709) /* Should be at processor specific part.. */
152 outw(0x2240, INTC_ICR1
);
154 outw(0xffff, HD64461_NIMR
);
156 for (i
= HD64461_IRQBASE
; i
< HD64461_IRQBASE
+ 16; i
++) {
157 irq_desc
[i
].handler
= &hd64461_irq_type
;
160 setup_irq(CONFIG_HD64461_IRQ
, &irq0
);
162 #ifdef CONFIG_HD64461_ENABLER
163 printk(KERN_INFO
"HD64461: enabling PCMCIA devices\n");
164 outb(0x4c, HD64461_PCC1CSCIER
);
165 outb(0x00, HD64461_PCC1CSCR
);
171 module_init(setup_hd64461
);