1/* 2 * Copyright 2001 MontaVista Software Inc. 3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 4 * 5 * arch/mips/ddb5xxx/ddb5477/irq_5477.c 6 * This file defines the irq handler for Vrc5477. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15/* 16 * Vrc5477 defines 32 IRQs. 17 * 18 * This file exports one function: 19 * vrc5477_irq_init(u32 irq_base); 20 */ 21 22#include <linux/interrupt.h> 23#include <linux/types.h> 24#include <linux/ptrace.h> 25 26#include <asm/debug.h> 27 28#include <asm/ddb5xxx/ddb5xxx.h> 29 30/* number of total irqs supported by Vrc5477 */ 31#define NUM_5477_IRQ 32 32 33static int vrc5477_irq_base = -1; 34 35 36static void 37vrc5477_irq_enable(unsigned int irq) 38{ 39 db_assert(vrc5477_irq_base != -1); 40 db_assert(irq >= vrc5477_irq_base); 41 db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ); 42 43 ll_vrc5477_irq_enable(irq - vrc5477_irq_base); 44} 45 46static void 47vrc5477_irq_disable(unsigned int irq) 48{ 49 db_assert(vrc5477_irq_base != -1); 50 db_assert(irq >= vrc5477_irq_base); 51 db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); 52 53 ll_vrc5477_irq_disable(irq - vrc5477_irq_base); 54} 55 56static void 57vrc5477_irq_ack(unsigned int irq) 58{ 59 db_assert(vrc5477_irq_base != -1); 60 db_assert(irq >= vrc5477_irq_base); 61 db_assert(irq < vrc5477_irq_base+ NUM_5477_IRQ); 62 63 /* clear the interrupt bit */ 64 /* some irqs require the driver to clear the sources */ 65 ddb_out32(DDB_INTCLR32, 1 << (irq - vrc5477_irq_base)); 66 67 /* disable interrupt - some handler will re-enable the irq 68 * and if the interrupt is leveled, we will have infinite loop 69 */ 70 ll_vrc5477_irq_disable(irq - vrc5477_irq_base); 71} 72 73static void 74vrc5477_irq_end(unsigned int irq) 75{ 76 db_assert(vrc5477_irq_base != -1); 77 db_assert(irq >= vrc5477_irq_base); 78 db_assert(irq < vrc5477_irq_base + NUM_5477_IRQ); 79 80 if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 81 ll_vrc5477_irq_enable( irq - vrc5477_irq_base); 82} 83 84struct irq_chip vrc5477_irq_controller = { 85 .name = "vrc5477_irq", 86 .ack = vrc5477_irq_ack, 87 .mask = vrc5477_irq_disable, 88 .mask_ack = vrc5477_irq_ack, 89 .unmask = vrc5477_irq_enable, 90 .end = vrc5477_irq_end 91}; 92 93void __init vrc5477_irq_init(u32 irq_base) 94{ 95 u32 i; 96 97 for (i= irq_base; i< irq_base+ NUM_5477_IRQ; i++) 98 set_irq_chip(i, &vrc5477_irq_controller); 99 100 vrc5477_irq_base = irq_base; 101} 102 103void ll_vrc5477_irq_route(int vrc5477_irq, int ip) 104{ 105 u32 reg_value; 106 u32 reg_bitmask; 107 u32 reg_index; 108 109 db_assert(vrc5477_irq >= 0); 110 db_assert(vrc5477_irq < NUM_5477_IRQ); 111 db_assert(ip >= 0); 112 db_assert((ip < 5) || (ip == 6)); 113 114 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; 115 reg_value = ddb_in32(reg_index); 116 reg_bitmask = 7 << (vrc5477_irq % 8 * 4); 117 reg_value &= ~reg_bitmask; 118 reg_value |= ip << (vrc5477_irq % 8 * 4); 119 ddb_out32(reg_index, reg_value); 120} 121 122void ll_vrc5477_irq_enable(int vrc5477_irq) 123{ 124 u32 reg_value; 125 u32 reg_bitmask; 126 u32 reg_index; 127 128 db_assert(vrc5477_irq >= 0); 129 db_assert(vrc5477_irq < NUM_5477_IRQ); 130 131 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; 132 reg_value = ddb_in32(reg_index); 133 reg_bitmask = 8 << (vrc5477_irq % 8 * 4); 134 db_assert((reg_value & reg_bitmask) == 0); 135 ddb_out32(reg_index, reg_value | reg_bitmask); 136} 137 138void ll_vrc5477_irq_disable(int vrc5477_irq) 139{ 140 u32 reg_value; 141 u32 reg_bitmask; 142 u32 reg_index; 143 144 db_assert(vrc5477_irq >= 0); 145 db_assert(vrc5477_irq < NUM_5477_IRQ); 146 147 reg_index = DDB_INTCTRL0 + vrc5477_irq/8*4; 148 reg_value = ddb_in32(reg_index); 149 reg_bitmask = 8 << (vrc5477_irq % 8 * 4); 150 151 /* we assert that the interrupt is enabled (perhaps over-zealous) */ 152 db_assert( (reg_value & reg_bitmask) != 0); 153 ddb_out32(reg_index, reg_value & ~reg_bitmask); 154} 155