sh: rework ipr code
[linux-2.6.git] / arch / sh / boards / se / 7722 / irq.c
1 /*
2  * linux/arch/sh/boards/se/7722/irq.c
3  *
4  * Copyright (C) 2007  Nobuhiro Iwamatsu
5  *
6  * Hitachi UL SolutionEngine 7722 Support.
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 #include <linux/init.h>
13 #include <linux/irq.h>
14 #include <linux/interrupt.h>
15 #include <asm/irq.h>
16 #include <asm/io.h>
17 #include <asm/se7722.h>
18
19 #define INTC_INTMSK0             0xFFD00044
20 #define INTC_INTMSKCLR0          0xFFD00064
21
22 struct se7722_data {
23         unsigned char irq;
24         unsigned char ipr_idx;
25         unsigned char shift;
26         unsigned short priority;
27         unsigned long addr;
28 };
29
30
31 static void disable_se7722_irq(unsigned int irq)
32 {
33         struct se7722_data *p = get_irq_chip_data(irq);
34         ctrl_outw( ctrl_inw( p->addr ) | p->priority , p->addr );
35 }
36
37 static void enable_se7722_irq(unsigned int irq)
38 {
39         struct se7722_data *p = get_irq_chip_data(irq);
40         ctrl_outw( ctrl_inw( p->addr ) & ~p->priority , p->addr );
41 }
42
43 static struct irq_chip se7722_irq_chip __read_mostly = {
44         .name           = "SE7722",
45         .mask           = disable_se7722_irq,
46         .unmask         = enable_se7722_irq,
47         .mask_ack       = disable_se7722_irq,
48 };
49
50 static struct se7722_data ipr_irq_table[] = {
51         /* irq        ,idx,sft, priority     , addr   */
52         { MRSHPC_IRQ0 , 0 , 0 , MRSHPC_BIT0 , IRQ01_MASK } ,
53         { MRSHPC_IRQ1 , 0 , 0 , MRSHPC_BIT1 , IRQ01_MASK } ,
54         { MRSHPC_IRQ2 , 0 , 0 , MRSHPC_BIT2 , IRQ01_MASK } ,
55         { MRSHPC_IRQ3 , 0 , 0 , MRSHPC_BIT3 , IRQ01_MASK } ,
56         { SMC_IRQ     , 0 , 0 , SMC_BIT     , IRQ01_MASK } ,
57         { EXT_IRQ     , 0 , 0 , EXT_BIT     , IRQ01_MASK } ,
58 };
59
60 int se7722_irq_demux(int irq)
61 {
62
63         if ((irq == IRQ0_IRQ)||(irq == IRQ1_IRQ)) {
64                 volatile unsigned short intv =
65                         *(volatile unsigned short *)IRQ01_STS;
66                 if (irq == IRQ0_IRQ){
67                         if(intv & SMC_BIT ) {
68                                 return SMC_IRQ;
69                         } else if(intv & USB_BIT) {
70                                 return USB_IRQ;
71                         } else {
72                                 printk("intv =%04x\n", intv);
73                                 return SMC_IRQ;
74                         }
75                 } else if(irq == IRQ1_IRQ){
76                         if(intv & MRSHPC_BIT0) {
77                                 return MRSHPC_IRQ0;
78                         } else if(intv & MRSHPC_BIT1) {
79                                 return MRSHPC_IRQ1;
80                         } else if(intv & MRSHPC_BIT2) {
81                                 return MRSHPC_IRQ2;
82                         } else if(intv & MRSHPC_BIT3) {
83                                 return MRSHPC_IRQ3;
84                         } else {
85                                 printk("BIT_EXTENTION =%04x\n", intv);
86                                 return EXT_IRQ;
87                         }
88                 }
89         }
90         return irq;
91
92 }
93 /*
94  * Initialize IRQ setting
95  */
96 void __init init_se7722_IRQ(void)
97 {
98         int i = 0;
99         ctrl_outw(0x2000, 0xb03fffec);  /* mrshpc irq enable */
100         ctrl_outl((3 << ((7 - 0) * 4))|(3 << ((7 - 1) * 4)), INTC_INTPRI0);     /* irq0 pri=3,irq1,pri=3 */
101         ctrl_outw((2 << ((7 - 0) * 2))|(2 << ((7 - 1) * 2)), INTC_ICR1);        /* irq0,1 low-level irq */
102
103         for (i = 0; i < ARRAY_SIZE(ipr_irq_table); i++) {
104                 disable_irq_nosync(ipr_irq_table[i].irq);
105                 set_irq_chip_and_handler_name( ipr_irq_table[i].irq, &se7722_irq_chip,
106                         handle_level_irq, "level");
107                 set_irq_chip_data( ipr_irq_table[i].irq, &ipr_irq_table[i] );
108                 disable_se7722_irq(ipr_irq_table[i].irq);
109         }
110 }