1/* 2 * arch/arm/mach-ks8695/irq.c 3 * 4 * Copyright (C) 2006 Ben Dooks <ben@simtec.co.uk> 5 * Copyright (C) 2006 Simtec Electronics 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 22#include <linux/init.h> 23#include <linux/module.h> 24#include <linux/interrupt.h> 25#include <linux/ioport.h> 26#include <linux/ptrace.h> 27#include <linux/sysdev.h> 28 29#include <asm/hardware.h> 30#include <asm/irq.h> 31#include <asm/io.h> 32 33#include <asm/mach/irq.h> 34 35#include <asm/arch/regs-irq.h> 36#include <asm/arch/regs-gpio.h> 37 38static void ks8695_irq_mask(unsigned int irqno) 39{ 40 unsigned long inten; 41 42 inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); 43 inten &= ~(1 << irqno); 44 45 __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); 46} 47 48static void ks8695_irq_unmask(unsigned int irqno) 49{ 50 unsigned long inten; 51 52 inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); 53 inten |= (1 << irqno); 54 55 __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); 56} 57 58static void ks8695_irq_ack(unsigned int irqno) 59{ 60 __raw_writel((1 << irqno), KS8695_IRQ_VA + KS8695_INTST); 61} 62 63 64static struct irq_chip ks8695_irq_level_chip; 65static struct irq_chip ks8695_irq_edge_chip; 66 67 68static int ks8695_irq_set_type(unsigned int irqno, unsigned int type) 69{ 70 unsigned long ctrl, mode; 71 unsigned short level_triggered = 0; 72 73 ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); 74 75 switch (type) { 76 case IRQT_HIGH: 77 mode = IOPC_TM_HIGH; 78 level_triggered = 1; 79 break; 80 case IRQT_LOW: 81 mode = IOPC_TM_LOW; 82 level_triggered = 1; 83 break; 84 case IRQT_RISING: 85 mode = IOPC_TM_RISING; 86 break; 87 case IRQT_FALLING: 88 mode = IOPC_TM_FALLING; 89 break; 90 case IRQT_BOTHEDGE: 91 mode = IOPC_TM_EDGE; 92 break; 93 default: 94 return -EINVAL; 95 } 96 97 switch (irqno) { 98 case KS8695_IRQ_EXTERN0: 99 ctrl &= ~IOPC_IOEINT0TM; 100 ctrl |= IOPC_IOEINT0_MODE(mode); 101 break; 102 case KS8695_IRQ_EXTERN1: 103 ctrl &= ~IOPC_IOEINT1TM; 104 ctrl |= IOPC_IOEINT1_MODE(mode); 105 break; 106 case KS8695_IRQ_EXTERN2: 107 ctrl &= ~IOPC_IOEINT2TM; 108 ctrl |= IOPC_IOEINT2_MODE(mode); 109 break; 110 case KS8695_IRQ_EXTERN3: 111 ctrl &= ~IOPC_IOEINT3TM; 112 ctrl |= IOPC_IOEINT3_MODE(mode); 113 break; 114 default: 115 return -EINVAL; 116 } 117 118 if (level_triggered) { 119 set_irq_chip(irqno, &ks8695_irq_level_chip); 120 set_irq_handler(irqno, handle_level_irq); 121 } 122 else { 123 set_irq_chip(irqno, &ks8695_irq_edge_chip); 124 set_irq_handler(irqno, handle_edge_irq); 125 } 126 127 __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC); 128 return 0; 129} 130 131static struct irq_chip ks8695_irq_level_chip = { 132 .ack = ks8695_irq_mask, 133 .mask = ks8695_irq_mask, 134 .unmask = ks8695_irq_unmask, 135 .set_type = ks8695_irq_set_type, 136}; 137 138static struct irq_chip ks8695_irq_edge_chip = { 139 .ack = ks8695_irq_ack, 140 .mask = ks8695_irq_mask, 141 .unmask = ks8695_irq_unmask, 142 .set_type = ks8695_irq_set_type, 143}; 144 145void __init ks8695_init_irq(void) 146{ 147 unsigned int irq; 148 149 /* Disable all interrupts initially */ 150 __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC); 151 __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN); 152 153 for (irq = 0; irq < NR_IRQS; irq++) { 154 switch (irq) { 155 /* Level-triggered interrupts */ 156 case KS8695_IRQ_BUS_ERROR: 157 case KS8695_IRQ_UART_MODEM_STATUS: 158 case KS8695_IRQ_UART_LINE_STATUS: 159 case KS8695_IRQ_UART_RX: 160 case KS8695_IRQ_COMM_TX: 161 case KS8695_IRQ_COMM_RX: 162 set_irq_chip(irq, &ks8695_irq_level_chip); 163 set_irq_handler(irq, handle_level_irq); 164 break; 165 166 /* Edge-triggered interrupts */ 167 default: 168 ks8695_irq_ack(irq); /* clear pending bit */ 169 set_irq_chip(irq, &ks8695_irq_edge_chip); 170 set_irq_handler(irq, handle_edge_irq); 171 } 172 173 set_irq_flags(irq, IRQF_VALID); 174 } 175} 176