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(struct irq_data *data) 29 { 30 unsigned int irq = data->irq; 31 unsigned short val; 32 unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); 33 unsigned short msk0,msk1; 34 35 /* Set the priority in IPR to 0 */ 36 val = __raw_readw(INTC_IPR01); 37 val &= mask; 38 __raw_writew(val, INTC_IPR01); 39 /* FPGA mask set */ 40 msk0 = __raw_readw(INTMSK0); 41 msk1 = __raw_readw(INTMSK1); 42 43 switch (irq) { 44 case IRQ0_IRQ: 45 msk0 |= 0x0010; 46 break; 47 case IRQ1_IRQ: 48 msk0 |= 0x000f; 49 break; 50 case IRQ3_IRQ: 51 msk0 |= 0x0f00; 52 msk1 |= 0x00ff; 53 break; 54 } 55 __raw_writew(msk0, INTMSK0); 56 __raw_writew(msk1, INTMSK1); 57 } 58 59 static void enable_se7206_irq(struct irq_data *data) 60 { 61 unsigned int irq = data->irq; 62 unsigned short val; 63 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); 64 unsigned short msk0,msk1; 65 66 /* Set priority in IPR back to original value */ 67 val = __raw_readw(INTC_IPR01); 68 val |= value; 69 __raw_writew(val, INTC_IPR01); 70 71 /* FPGA mask reset */ 72 msk0 = __raw_readw(INTMSK0); 73 msk1 = __raw_readw(INTMSK1); 74 75 switch (irq) { 76 case IRQ0_IRQ: 77 msk0 &= ~0x0010; 78 break; 79 case IRQ1_IRQ: 80 msk0 &= ~0x000f; 81 break; 82 case IRQ3_IRQ: 83 msk0 &= ~0x0f00; 84 msk1 &= ~0x00ff; 85 break; 86 } 87 __raw_writew(msk0, INTMSK0); 88 __raw_writew(msk1, INTMSK1); 89 } 90 91 static void eoi_se7206_irq(struct irq_data *data) 92 { 93 unsigned short sts0,sts1; 94 unsigned int irq = data->irq; 95 struct irq_desc *desc = irq_to_desc(irq); 96 97 if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) 98 enable_se7206_irq(data); 99 /* FPGA isr clear */ 100 sts0 = __raw_readw(INTSTS0); 101 sts1 = __raw_readw(INTSTS1); 102 103 switch (irq) { 104 case IRQ0_IRQ: 105 sts0 &= ~0x0010; 106 break; 107 case IRQ1_IRQ: 108 sts0 &= ~0x000f; 109 break; 110 case IRQ3_IRQ: 111 sts0 &= ~0x0f00; 112 sts1 &= ~0x00ff; 113 break; 114 } 115 __raw_writew(sts0, INTSTS0); 116 __raw_writew(sts1, INTSTS1); 117 } 118 119 static struct irq_chip se7206_irq_chip __read_mostly = { 120 .name = "SE7206-FPGA", 121 .irq_mask = disable_se7206_irq, 122 .irq_unmask = enable_se7206_irq, 123 .irq_eoi = eoi_se7206_irq, 124 }; 125 126 static void make_se7206_irq(unsigned int irq) 127 { 128 disable_irq_nosync(irq); 129 set_irq_chip_and_handler_name(irq, &se7206_irq_chip, 130 handle_level_irq, "level"); 131 disable_se7206_irq(irq_get_irq_data(irq)); 132 } 133 134 /* 135 * Initialize IRQ setting 136 */ 137 void __init init_se7206_IRQ(void) 138 { 139 make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ 140 make_se7206_irq(IRQ1_IRQ); /* ATA */ 141 make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ 142 143 __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */ 144 145 /* FPGA System register setup*/ 146 __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ 147 __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ 148 149 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 150 __raw_writew(0x0001,INTSEL); 151 } 152