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 28static 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 = __raw_readw(INTC_IPR01); 36 val &= mask; 37 __raw_writew(val, INTC_IPR01); 38 /* FPGA mask set */ 39 msk0 = __raw_readw(INTMSK0); 40 msk1 = __raw_readw(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 __raw_writew(msk0, INTMSK0); 55 __raw_writew(msk1, INTMSK1); 56} 57 58static 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 = __raw_readw(INTC_IPR01); 66 val |= value; 67 __raw_writew(val, INTC_IPR01); 68 69 /* FPGA mask reset */ 70 msk0 = __raw_readw(INTMSK0); 71 msk1 = __raw_readw(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 __raw_writew(msk0, INTMSK0); 86 __raw_writew(msk1, INTMSK1); 87} 88 89static void eoi_se7206_irq(unsigned int irq) 90{ 91 unsigned short sts0,sts1; 92 struct irq_desc *desc = irq_to_desc(irq); 93 94 if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) 95 enable_se7206_irq(irq); 96 /* FPGA isr clear */ 97 sts0 = __raw_readw(INTSTS0); 98 sts1 = __raw_readw(INTSTS1); 99 100 switch (irq) { 101 case IRQ0_IRQ: 102 sts0 &= ~0x0010; 103 break; 104 case IRQ1_IRQ: 105 sts0 &= ~0x000f; 106 break; 107 case IRQ3_IRQ: 108 sts0 &= ~0x0f00; 109 sts1 &= ~0x00ff; 110 break; 111 } 112 __raw_writew(sts0, INTSTS0); 113 __raw_writew(sts1, INTSTS1); 114} 115 116static struct irq_chip se7206_irq_chip __read_mostly = { 117 .name = "SE7206-FPGA", 118 .mask = disable_se7206_irq, 119 .unmask = enable_se7206_irq, 120 .mask_ack = disable_se7206_irq, 121 .eoi = eoi_se7206_irq, 122}; 123 124static void make_se7206_irq(unsigned int irq) 125{ 126 disable_irq_nosync(irq); 127 set_irq_chip_and_handler_name(irq, &se7206_irq_chip, 128 handle_level_irq, "level"); 129 disable_se7206_irq(irq); 130} 131 132/* 133 * Initialize IRQ setting 134 */ 135void __init init_se7206_IRQ(void) 136{ 137 make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ 138 make_se7206_irq(IRQ1_IRQ); /* ATA */ 139 make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ 140 __raw_writew(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ 141 142 /* FPGA System register setup*/ 143 __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ 144 __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ 145 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 146 __raw_writew(0x0001,INTSEL); 147} 148