1/* 2 * linux/arch/arm/common/vic.c 3 * 4 * Copyright (C) 1999 - 2003 ARM Limited 5 * Copyright (C) 2000 Deep Blue Solutions Ltd 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#include <linux/init.h> 22#include <linux/list.h> 23 24#include <asm/io.h> 25#include <asm/mach/irq.h> 26#include <asm/hardware/vic.h> 27 28static void vic_mask_irq(unsigned int irq) 29{ 30 void __iomem *base = get_irq_chip_data(irq); 31 irq &= 31; 32 writel(1 << irq, base + VIC_INT_ENABLE_CLEAR); 33} 34 35static void vic_unmask_irq(unsigned int irq) 36{ 37 void __iomem *base = get_irq_chip_data(irq); 38 irq &= 31; 39 writel(1 << irq, base + VIC_INT_ENABLE); 40} 41 42static struct irq_chip vic_chip = { 43 .name = "VIC", 44 .ack = vic_mask_irq, 45 .mask = vic_mask_irq, 46 .unmask = vic_unmask_irq, 47}; 48 49/** 50 * vic_init - initialise a vectored interrupt controller 51 * @base: iomem base address 52 * @irq_start: starting interrupt number, must be muliple of 32 53 * @vic_sources: bitmask of interrupt sources to allow 54 */ 55void __init vic_init(void __iomem *base, unsigned int irq_start, 56 u32 vic_sources) 57{ 58 unsigned int i; 59 60 /* Disable all interrupts initially. */ 61 62 writel(0, base + VIC_INT_SELECT); 63 writel(0, base + VIC_INT_ENABLE); 64 writel(~0, base + VIC_INT_ENABLE_CLEAR); 65 writel(0, base + VIC_IRQ_STATUS); 66 writel(0, base + VIC_ITCR); 67 writel(~0, base + VIC_INT_SOFT_CLEAR); 68 69 /* 70 * Make sure we clear all existing interrupts 71 */ 72 writel(0, base + VIC_VECT_ADDR); 73 for (i = 0; i < 19; i++) { 74 unsigned int value; 75 76 value = readl(base + VIC_VECT_ADDR); 77 writel(value, base + VIC_VECT_ADDR); 78 } 79 80 for (i = 0; i < 16; i++) { 81 void __iomem *reg = base + VIC_VECT_CNTL0 + (i * 4); 82 writel(VIC_VECT_CNTL_ENABLE | i, reg); 83 } 84 85 writel(32, base + VIC_DEF_VECT_ADDR); 86 87 for (i = 0; i < 32; i++) { 88 unsigned int irq = irq_start + i; 89 90 set_irq_chip(irq, &vic_chip); 91 set_irq_chip_data(irq, base); 92 93 if (vic_sources & (1 << i)) { 94 set_irq_handler(irq, handle_level_irq); 95 set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); 96 } 97 } 98} 99