1/* 2 * Copyright (C) NEC Electronics Corporation 2004-2006 3 * 4 * This file is based on the arch/mips/ddb5xxx/ddb5477/irq.c 5 * 6 * Copyright 2001 MontaVista Software Inc. 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22#include <linux/init.h> 23#include <linux/interrupt.h> 24#include <linux/irq.h> 25#include <linux/types.h> 26#include <linux/ptrace.h> 27#include <linux/delay.h> 28 29#include <asm/irq_cpu.h> 30#include <asm/system.h> 31#include <asm/mipsregs.h> 32#include <asm/addrspace.h> 33#include <asm/bootinfo.h> 34 35#include <asm/emma/emma2rh.h> 36 37static void emma2rh_irq_enable(unsigned int irq) 38{ 39 u32 reg_value; 40 u32 reg_bitmask; 41 u32 reg_index; 42 43 irq -= EMMA2RH_IRQ_BASE; 44 45 reg_index = EMMA2RH_BHIF_INT_EN_0 + 46 (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32); 47 reg_value = emma2rh_in32(reg_index); 48 reg_bitmask = 0x1 << (irq % 32); 49 emma2rh_out32(reg_index, reg_value | reg_bitmask); 50} 51 52static void emma2rh_irq_disable(unsigned int irq) 53{ 54 u32 reg_value; 55 u32 reg_bitmask; 56 u32 reg_index; 57 58 irq -= EMMA2RH_IRQ_BASE; 59 60 reg_index = EMMA2RH_BHIF_INT_EN_0 + 61 (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32); 62 reg_value = emma2rh_in32(reg_index); 63 reg_bitmask = 0x1 << (irq % 32); 64 emma2rh_out32(reg_index, reg_value & ~reg_bitmask); 65} 66 67struct irq_chip emma2rh_irq_controller = { 68 .name = "emma2rh_irq", 69 .ack = emma2rh_irq_disable, 70 .mask = emma2rh_irq_disable, 71 .mask_ack = emma2rh_irq_disable, 72 .unmask = emma2rh_irq_enable, 73}; 74 75void emma2rh_irq_init(void) 76{ 77 u32 i; 78 79 for (i = 0; i < NUM_EMMA2RH_IRQ; i++) 80 set_irq_chip_and_handler_name(EMMA2RH_IRQ_BASE + i, 81 &emma2rh_irq_controller, 82 handle_level_irq, "level"); 83} 84 85static void emma2rh_sw_irq_enable(unsigned int irq) 86{ 87 u32 reg; 88 89 irq -= EMMA2RH_SW_IRQ_BASE; 90 91 reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); 92 reg |= 1 << irq; 93 emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); 94} 95 96static void emma2rh_sw_irq_disable(unsigned int irq) 97{ 98 u32 reg; 99 100 irq -= EMMA2RH_SW_IRQ_BASE; 101 102 reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); 103 reg &= ~(1 << irq); 104 emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg); 105} 106 107struct irq_chip emma2rh_sw_irq_controller = { 108 .name = "emma2rh_sw_irq", 109 .ack = emma2rh_sw_irq_disable, 110 .mask = emma2rh_sw_irq_disable, 111 .mask_ack = emma2rh_sw_irq_disable, 112 .unmask = emma2rh_sw_irq_enable, 113}; 114 115void emma2rh_sw_irq_init(void) 116{ 117 u32 i; 118 119 for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++) 120 set_irq_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i, 121 &emma2rh_sw_irq_controller, 122 handle_level_irq, "level"); 123} 124 125static void emma2rh_gpio_irq_enable(unsigned int irq) 126{ 127 u32 reg; 128 129 irq -= EMMA2RH_GPIO_IRQ_BASE; 130 131 reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); 132 reg |= 1 << irq; 133 emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); 134} 135 136static void emma2rh_gpio_irq_disable(unsigned int irq) 137{ 138 u32 reg; 139 140 irq -= EMMA2RH_GPIO_IRQ_BASE; 141 142 reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); 143 reg &= ~(1 << irq); 144 emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); 145} 146 147static void emma2rh_gpio_irq_ack(unsigned int irq) 148{ 149 irq -= EMMA2RH_GPIO_IRQ_BASE; 150 emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); 151} 152 153static void emma2rh_gpio_irq_mask_ack(unsigned int irq) 154{ 155 u32 reg; 156 157 irq -= EMMA2RH_GPIO_IRQ_BASE; 158 emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq)); 159 160 reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); 161 reg &= ~(1 << irq); 162 emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg); 163} 164 165struct irq_chip emma2rh_gpio_irq_controller = { 166 .name = "emma2rh_gpio_irq", 167 .ack = emma2rh_gpio_irq_ack, 168 .mask = emma2rh_gpio_irq_disable, 169 .mask_ack = emma2rh_gpio_irq_mask_ack, 170 .unmask = emma2rh_gpio_irq_enable, 171}; 172 173void emma2rh_gpio_irq_init(void) 174{ 175 u32 i; 176 177 for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++) 178 set_irq_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i, 179 &emma2rh_gpio_irq_controller, 180 handle_edge_irq, "edge"); 181} 182 183static struct irqaction irq_cascade = { 184 .handler = no_action, 185 .flags = 0, 186 .name = "cascade", 187 .dev_id = NULL, 188 .next = NULL, 189}; 190 191/* 192 * the first level int-handler will jump here if it is a emma2rh irq 193 */ 194void emma2rh_irq_dispatch(void) 195{ 196 u32 intStatus; 197 u32 bitmask; 198 u32 i; 199 200 intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_0) & 201 emma2rh_in32(EMMA2RH_BHIF_INT_EN_0); 202 203#ifdef EMMA2RH_SW_CASCADE 204 if (intStatus & (1UL << EMMA2RH_SW_CASCADE)) { 205 u32 swIntStatus; 206 swIntStatus = emma2rh_in32(EMMA2RH_BHIF_SW_INT) 207 & emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN); 208 for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { 209 if (swIntStatus & bitmask) { 210 do_IRQ(EMMA2RH_SW_IRQ_BASE + i); 211 return; 212 } 213 } 214 } 215 /* Skip S/W interrupt */ 216 intStatus &= ~(1UL << EMMA2RH_SW_CASCADE); 217#endif 218 219 for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { 220 if (intStatus & bitmask) { 221 do_IRQ(EMMA2RH_IRQ_BASE + i); 222 return; 223 } 224 } 225 226 intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_1) & 227 emma2rh_in32(EMMA2RH_BHIF_INT_EN_1); 228 229#ifdef EMMA2RH_GPIO_CASCADE 230 if (intStatus & (1UL << (EMMA2RH_GPIO_CASCADE % 32))) { 231 u32 gpioIntStatus; 232 gpioIntStatus = emma2rh_in32(EMMA2RH_GPIO_INT_ST) 233 & emma2rh_in32(EMMA2RH_GPIO_INT_MASK); 234 for (i = 0, bitmask = 1; i < 32; i++, bitmask <<= 1) { 235 if (gpioIntStatus & bitmask) { 236 do_IRQ(EMMA2RH_GPIO_IRQ_BASE + i); 237 return; 238 } 239 } 240 } 241 /* Skip GPIO interrupt */ 242 intStatus &= ~(1UL << (EMMA2RH_GPIO_CASCADE % 32)); 243#endif 244 245 for (i = 32, bitmask = 1; i < 64; i++, bitmask <<= 1) { 246 if (intStatus & bitmask) { 247 do_IRQ(EMMA2RH_IRQ_BASE + i); 248 return; 249 } 250 } 251 252 intStatus = emma2rh_in32(EMMA2RH_BHIF_INT_ST_2) & 253 emma2rh_in32(EMMA2RH_BHIF_INT_EN_2); 254 255 for (i = 64, bitmask = 1; i < 96; i++, bitmask <<= 1) { 256 if (intStatus & bitmask) { 257 do_IRQ(EMMA2RH_IRQ_BASE + i); 258 return; 259 } 260 } 261} 262 263void __init arch_init_irq(void) 264{ 265 u32 reg; 266 267 /* by default, interrupts are disabled. */ 268 emma2rh_out32(EMMA2RH_BHIF_INT_EN_0, 0); 269 emma2rh_out32(EMMA2RH_BHIF_INT_EN_1, 0); 270 emma2rh_out32(EMMA2RH_BHIF_INT_EN_2, 0); 271 emma2rh_out32(EMMA2RH_BHIF_INT1_EN_0, 0); 272 emma2rh_out32(EMMA2RH_BHIF_INT1_EN_1, 0); 273 emma2rh_out32(EMMA2RH_BHIF_INT1_EN_2, 0); 274 emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, 0); 275 276 clear_c0_status(0xff00); 277 set_c0_status(0x0400); 278 279#define GPIO_PCI (0xf<<15) 280 /* setup GPIO interrupt for PCI interface */ 281 /* direction input */ 282 reg = emma2rh_in32(EMMA2RH_GPIO_DIR); 283 emma2rh_out32(EMMA2RH_GPIO_DIR, reg & ~GPIO_PCI); 284 /* disable interrupt */ 285 reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK); 286 emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg & ~GPIO_PCI); 287 /* level triggerd */ 288 reg = emma2rh_in32(EMMA2RH_GPIO_INT_MODE); 289 emma2rh_out32(EMMA2RH_GPIO_INT_MODE, reg | GPIO_PCI); 290 reg = emma2rh_in32(EMMA2RH_GPIO_INT_CND_A); 291 emma2rh_out32(EMMA2RH_GPIO_INT_CND_A, reg & (~GPIO_PCI)); 292 /* interrupt clear */ 293 emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~GPIO_PCI); 294 295 /* init all controllers */ 296 emma2rh_irq_init(); 297 emma2rh_sw_irq_init(); 298 emma2rh_gpio_irq_init(); 299 mips_cpu_irq_init(); 300 301 /* setup cascade interrupts */ 302 setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_SW_CASCADE, &irq_cascade); 303 setup_irq(EMMA2RH_IRQ_BASE + EMMA2RH_GPIO_CASCADE, &irq_cascade); 304 setup_irq(MIPS_CPU_IRQ_BASE + 2, &irq_cascade); 305} 306 307asmlinkage void plat_irq_dispatch(void) 308{ 309 unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; 310 311 if (pending & STATUSF_IP7) 312 do_IRQ(MIPS_CPU_IRQ_BASE + 7); 313 else if (pending & STATUSF_IP2) 314 emma2rh_irq_dispatch(); 315 else if (pending & STATUSF_IP1) 316 do_IRQ(MIPS_CPU_IRQ_BASE + 1); 317 else if (pending & STATUSF_IP0) 318 do_IRQ(MIPS_CPU_IRQ_BASE + 0); 319 else 320 spurious_interrupt(); 321} 322