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(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 59static 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 91static void eoi_se7206_irq(struct irq_data *data) 92{ 93 unsigned short sts0,sts1; 94 unsigned int irq = data->irq; 95 96 if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data)) 97 enable_se7206_irq(data); 98 /* FPGA isr clear */ 99 sts0 = __raw_readw(INTSTS0); 100 sts1 = __raw_readw(INTSTS1); 101 102 switch (irq) { 103 case IRQ0_IRQ: 104 sts0 &= ~0x0010; 105 break; 106 case IRQ1_IRQ: 107 sts0 &= ~0x000f; 108 break; 109 case IRQ3_IRQ: 110 sts0 &= ~0x0f00; 111 sts1 &= ~0x00ff; 112 break; 113 } 114 __raw_writew(sts0, INTSTS0); 115 __raw_writew(sts1, INTSTS1); 116} 117 118static struct irq_chip se7206_irq_chip __read_mostly = { 119 .name = "SE7206-FPGA", 120 .irq_mask = disable_se7206_irq, 121 .irq_unmask = enable_se7206_irq, 122 .irq_eoi = eoi_se7206_irq, 123}; 124 125static void make_se7206_irq(unsigned int irq) 126{ 127 disable_irq_nosync(irq); 128 irq_set_chip_and_handler_name(irq, &se7206_irq_chip, 129 handle_level_irq, "level"); 130 disable_se7206_irq(irq_get_irq_data(irq)); 131} 132 133/* 134 * Initialize IRQ setting 135 */ 136void __init init_se7206_IRQ(void) 137{ 138 make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ 139 make_se7206_irq(IRQ1_IRQ); /* ATA */ 140 make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ 141 142 __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */ 143 144 /* FPGA System register setup*/ 145 __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ 146 __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ 147 148 /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 149 __raw_writew(0x0001,INTSEL); 150} 151