1 /* 2 * linux/arch/sh/boards/se/7206/irq.c 3 * 4 * Copyright (C) 2005,2006 Yoshinori Sato 5 * 6 * Hitachi SolutionEngine Support. 7 * 8 */ 9 #include <linux/init.h> 10 #include <linux/irq.h> 11 #include <linux/io.h> 12 #include <linux/interrupt.h> 13 #include <mach-se/mach/se7206.h> 14 15 #define INTSTS0 0x31800000 16 #define INTSTS1 0x31800002 17 #define INTMSK0 0x31800004 18 #define INTMSK1 0x31800006 19 #define INTSEL 0x31800008 20 21 #define IRQ0_IRQ 64 22 #define IRQ1_IRQ 65 23 #define IRQ3_IRQ 67 24 25 #define INTC_IPR01 0xfffe0818 26 #define INTC_ICR1 0xfffe0802 27 28 static void disable_se7206_irq(unsigned int irq) 29 { 30 unsigned short val; 31 unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); 32 unsigned short msk0,msk1; 33 34 /* Set the priority in IPR to 0 */ 35 val = ctrl_inw(INTC_IPR01); 36 val &= mask; 37 ctrl_outw(val, INTC_IPR01); 38 /* FPGA mask set */ 39 msk0 = ctrl_inw(INTMSK0); 40 msk1 = ctrl_inw(INTMSK1); 41 42 switch (irq) { 43 case IRQ0_IRQ: 44 msk0 |= 0x0010; 45 break; 46 case IRQ1_IRQ: 47 msk0 |= 0x000f; 48 break; 49 case IRQ3_IRQ: 50 msk0 |= 0x0f00; 51 msk1 |= 0x00ff; 52 break; 53 } 54 ctrl_outw(msk0, INTMSK0); 55 ctrl_outw(msk1, INTMSK1); 56 } 57 58 static void enable_se7206_irq(unsigned int irq) 59 { 60 unsigned short val; 61 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); 62 unsigned short msk0,msk1; 63 64 /* Set priority in IPR back to original value */ 65 val = ctrl_inw(INTC_IPR01); 66 val |= value; 67 ctrl_outw(val, INTC_IPR01); 68 69 /* FPGA mask reset */ 70 msk0 = ctrl_inw(INTMSK0); 71 msk1 = ctrl_inw(INTMSK1); 72 73 switch (irq) { 74 case IRQ0_IRQ: 75 msk0 &= ~0x0010; 76 break; 77 case IRQ1_IRQ: 78 msk0 &= ~0x000f; 79 break; 80 case IRQ3_IRQ: 81 msk0 &= ~0x0f00; 82 msk1 &= ~0x00ff; 83 break; 84 } 85 ctrl_outw(msk0, INTMSK0); 86 ctrl_outw(msk1, INTMSK1); 87 } 88 89 static void eoi_se7206_irq(unsigned int irq) 90 { 91 unsigned short sts0,sts1; 92 93 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 94 enable_se7206_irq(irq); 95 /* FPGA isr clear */ 96 sts0 = ctrl_inw(INTSTS0); 97 sts1 = ctrl_inw(INTSTS1); 98 99 switch (irq) { 100 case IRQ0_IRQ: 101 sts0 &= ~0x0010; 102 break; 103 case IRQ1_IRQ: 104 sts0 &= ~0x000f; 105 break; 106 case IRQ3_IRQ: 107 sts0 &= ~0x0f00; 108 sts1 &= ~0x00ff; 109 break; 110 } 111 ctrl_outw(sts0, INTSTS0); 112 ctrl_outw(sts1, INTSTS1); 113 } 114 115 static struct irq_chip se7206_irq_chip __read_mostly = { 116 .name = "SE7206-FPGA", 117 .mask = disable_se7206_irq, 118 .unmask = enable_se7206_irq, 119 .mask_ack = disable_se7206_irq, 120 .eoi = eoi_se7206_irq, 121 }; 122 123 static void make_se7206_irq(unsigned int irq) 124 { 125 disable_irq_nosync(irq); 126 set_irq_chip_and_handler_name(irq, &se7206_irq_chip, 127 handle_level_irq, "level"); 128 disable_se7206_irq(irq); 129 } 130 131 /* 132 * Initialize IRQ setting 133 */ 134 void __init init_se7206_IRQ(void) 135 { 136 make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ 137 make_se7206_irq(IRQ1_IRQ); /* ATA */ 138 make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ 139 ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ 140 141 /* FPGA System register setup*/ 142 ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ 143 ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ 144 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 145 ctrl_outw(0x0001,INTSEL); 146 } 147