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/irq.h> 13#include <linux/interrupt.h> 14#include <asm/se7206.h> 15 16#define INTSTS0 0x31800000 17#define INTSTS1 0x31800002 18#define INTMSK0 0x31800004 19#define INTMSK1 0x31800006 20#define INTSEL 0x31800008 21 22#define IRQ0_IRQ 64 23#define IRQ1_IRQ 65 24#define IRQ3_IRQ 67 25 26#define INTC_IPR01 0xfffe0818 27#define INTC_ICR1 0xfffe0802 28 29static void disable_se7206_irq(unsigned int irq) 30{ 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 = ctrl_inw(INTC_IPR01); 37 val &= mask; 38 ctrl_outw(val, INTC_IPR01); 39 /* FPGA mask set */ 40 msk0 = ctrl_inw(INTMSK0); 41 msk1 = ctrl_inw(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 ctrl_outw(msk0, INTMSK0); 56 ctrl_outw(msk1, INTMSK1); 57} 58 59static void enable_se7206_irq(unsigned int irq) 60{ 61 unsigned short val; 62 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); 63 unsigned short msk0,msk1; 64 65 /* Set priority in IPR back to original value */ 66 val = ctrl_inw(INTC_IPR01); 67 val |= value; 68 ctrl_outw(val, INTC_IPR01); 69 70 /* FPGA mask reset */ 71 msk0 = ctrl_inw(INTMSK0); 72 msk1 = ctrl_inw(INTMSK1); 73 74 switch (irq) { 75 case IRQ0_IRQ: 76 msk0 &= ~0x0010; 77 break; 78 case IRQ1_IRQ: 79 msk0 &= ~0x000f; 80 break; 81 case IRQ3_IRQ: 82 msk0 &= ~0x0f00; 83 msk1 &= ~0x00ff; 84 break; 85 } 86 ctrl_outw(msk0, INTMSK0); 87 ctrl_outw(msk1, INTMSK1); 88} 89 90static void eoi_se7206_irq(unsigned int irq) 91{ 92 unsigned short sts0,sts1; 93 94 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 95 enable_se7206_irq(irq); 96 /* FPGA isr clear */ 97 sts0 = ctrl_inw(INTSTS0); 98 sts1 = ctrl_inw(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 ctrl_outw(sts0, INTSTS0); 113 ctrl_outw(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 ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ 141 142 /* FPGA System register setup*/ 143 ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ 144 ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ 145 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 146 ctrl_outw(0x0001,INTSEL); 147} 148