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/device.h> 27#include <linux/io.h> 28 29#include <mach/hardware.h> 30#include <asm/irq.h> 31 32#include <asm/mach/irq.h> 33 34#include <mach/regs-irq.h> 35#include <mach/regs-gpio.h> 36 37static void ks8695_irq_mask(struct irq_data *d) 38{ 39 unsigned long inten; 40 41 inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); 42 inten &= ~(1 << d->irq); 43 44 __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); 45} 46 47static void ks8695_irq_unmask(struct irq_data *d) 48{ 49 unsigned long inten; 50 51 inten = __raw_readl(KS8695_IRQ_VA + KS8695_INTEN); 52 inten |= (1 << d->irq); 53 54 __raw_writel(inten, KS8695_IRQ_VA + KS8695_INTEN); 55} 56 57static void ks8695_irq_ack(struct irq_data *d) 58{ 59 __raw_writel((1 << d->irq), KS8695_IRQ_VA + KS8695_INTST); 60} 61 62 63static struct irq_chip ks8695_irq_level_chip; 64static struct irq_chip ks8695_irq_edge_chip; 65 66 67static int ks8695_irq_set_type(struct irq_data *d, unsigned int type) 68{ 69 unsigned long ctrl, mode; 70 unsigned short level_triggered = 0; 71 72 ctrl = __raw_readl(KS8695_GPIO_VA + KS8695_IOPC); 73 74 switch (type) { 75 case IRQ_TYPE_LEVEL_HIGH: 76 mode = IOPC_TM_HIGH; 77 level_triggered = 1; 78 break; 79 case IRQ_TYPE_LEVEL_LOW: 80 mode = IOPC_TM_LOW; 81 level_triggered = 1; 82 break; 83 case IRQ_TYPE_EDGE_RISING: 84 mode = IOPC_TM_RISING; 85 break; 86 case IRQ_TYPE_EDGE_FALLING: 87 mode = IOPC_TM_FALLING; 88 break; 89 case IRQ_TYPE_EDGE_BOTH: 90 mode = IOPC_TM_EDGE; 91 break; 92 default: 93 return -EINVAL; 94 } 95 96 switch (d->irq) { 97 case KS8695_IRQ_EXTERN0: 98 ctrl &= ~IOPC_IOEINT0TM; 99 ctrl |= IOPC_IOEINT0_MODE(mode); 100 break; 101 case KS8695_IRQ_EXTERN1: 102 ctrl &= ~IOPC_IOEINT1TM; 103 ctrl |= IOPC_IOEINT1_MODE(mode); 104 break; 105 case KS8695_IRQ_EXTERN2: 106 ctrl &= ~IOPC_IOEINT2TM; 107 ctrl |= IOPC_IOEINT2_MODE(mode); 108 break; 109 case KS8695_IRQ_EXTERN3: 110 ctrl &= ~IOPC_IOEINT3TM; 111 ctrl |= IOPC_IOEINT3_MODE(mode); 112 break; 113 default: 114 return -EINVAL; 115 } 116 117 if (level_triggered) { 118 irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip, 119 handle_level_irq); 120 } 121 else { 122 irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip, 123 handle_edge_irq); 124 } 125 126 __raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC); 127 return 0; 128} 129 130static struct irq_chip ks8695_irq_level_chip = { 131 .irq_ack = ks8695_irq_mask, 132 .irq_mask = ks8695_irq_mask, 133 .irq_unmask = ks8695_irq_unmask, 134 .irq_set_type = ks8695_irq_set_type, 135}; 136 137static struct irq_chip ks8695_irq_edge_chip = { 138 .irq_ack = ks8695_irq_ack, 139 .irq_mask = ks8695_irq_mask, 140 .irq_unmask = ks8695_irq_unmask, 141 .irq_set_type = ks8695_irq_set_type, 142}; 143 144void __init ks8695_init_irq(void) 145{ 146 unsigned int irq; 147 148 /* Disable all interrupts initially */ 149 __raw_writel(0, KS8695_IRQ_VA + KS8695_INTMC); 150 __raw_writel(0, KS8695_IRQ_VA + KS8695_INTEN); 151 152 for (irq = 0; irq < NR_IRQS; irq++) { 153 switch (irq) { 154 /* Level-triggered interrupts */ 155 case KS8695_IRQ_BUS_ERROR: 156 case KS8695_IRQ_UART_MODEM_STATUS: 157 case KS8695_IRQ_UART_LINE_STATUS: 158 case KS8695_IRQ_UART_RX: 159 case KS8695_IRQ_COMM_TX: 160 case KS8695_IRQ_COMM_RX: 161 irq_set_chip_and_handler(irq, 162 &ks8695_irq_level_chip, 163 handle_level_irq); 164 break; 165 166 /* Edge-triggered interrupts */ 167 default: 168 /* clear pending bit */ 169 ks8695_irq_ack(irq_get_irq_data(irq)); 170 irq_set_chip_and_handler(irq, 171 &ks8695_irq_edge_chip, 172 handle_edge_irq); 173 } 174 175 set_irq_flags(irq, IRQF_VALID); 176 } 177} 178