1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/arch/sh/boards/se/7206/irq.c 4 * 5 * Copyright (C) 2005,2006 Yoshinori Sato 6 * 7 * Hitachi SolutionEngine Support. 8 * 9 */ 10 #include <linux/init.h> 11 #include <linux/irq.h> 12 #include <linux/io.h> 13 #include <linux/interrupt.h> 14 #include <mach-se/mach/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 29 static void disable_se7206_irq(struct irq_data *data) 30 { 31 unsigned int irq = data->irq; 32 unsigned short val; 33 unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); 34 unsigned short msk0,msk1; 35 36 /* Set the priority in IPR to 0 */ 37 val = __raw_readw(INTC_IPR01); 38 val &= mask; 39 __raw_writew(val, INTC_IPR01); 40 /* FPGA mask set */ 41 msk0 = __raw_readw(INTMSK0); 42 msk1 = __raw_readw(INTMSK1); 43 44 switch (irq) { 45 case IRQ0_IRQ: 46 msk0 |= 0x0010; 47 break; 48 case IRQ1_IRQ: 49 msk0 |= 0x000f; 50 break; 51 case IRQ3_IRQ: 52 msk0 |= 0x0f00; 53 msk1 |= 0x00ff; 54 break; 55 } 56 __raw_writew(msk0, INTMSK0); 57 __raw_writew(msk1, INTMSK1); 58 } 59 60 static void enable_se7206_irq(struct irq_data *data) 61 { 62 unsigned int irq = data->irq; 63 unsigned short val; 64 unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); 65 unsigned short msk0,msk1; 66 67 /* Set priority in IPR back to original value */ 68 val = __raw_readw(INTC_IPR01); 69 val |= value; 70 __raw_writew(val, INTC_IPR01); 71 72 /* FPGA mask reset */ 73 msk0 = __raw_readw(INTMSK0); 74 msk1 = __raw_readw(INTMSK1); 75 76 switch (irq) { 77 case IRQ0_IRQ: 78 msk0 &= ~0x0010; 79 break; 80 case IRQ1_IRQ: 81 msk0 &= ~0x000f; 82 break; 83 case IRQ3_IRQ: 84 msk0 &= ~0x0f00; 85 msk1 &= ~0x00ff; 86 break; 87 } 88 __raw_writew(msk0, INTMSK0); 89 __raw_writew(msk1, INTMSK1); 90 } 91 92 static void eoi_se7206_irq(struct irq_data *data) 93 { 94 unsigned short sts0,sts1; 95 unsigned int irq = data->irq; 96 97 if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data)) 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 irq_set_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