11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify it 31da177e4SLinus Torvalds * under the terms of the GNU General Public License as published by the 41da177e4SLinus Torvalds * Free Software Foundation; either version 2 of the License, or (at your 51da177e4SLinus Torvalds * option) any later version. 627f76819SRalf Baechle * 727f76819SRalf Baechle * Copyright (c) 2004 MIPS Inc 827f76819SRalf Baechle * Author: chris@mips.com 927f76819SRalf Baechle * 1027f76819SRalf Baechle * Copyright (C) 2004, 06 Ralf Baechle <ralf@linux-mips.org> 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds #include <linux/module.h> 131da177e4SLinus Torvalds #include <linux/interrupt.h> 141da177e4SLinus Torvalds #include <linux/kernel.h> 151da177e4SLinus Torvalds #include <linux/sched.h> 161da177e4SLinus Torvalds #include <linux/kernel_stat.h> 171da177e4SLinus Torvalds #include <asm/io.h> 181da177e4SLinus Torvalds #include <asm/irq.h> 191da177e4SLinus Torvalds #include <asm/msc01_ic.h> 20411ba7fcSAtsushi Nemoto #include <asm/traps.h> 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds static unsigned long _icctrl_msc; 231da177e4SLinus Torvalds #define MSC01_IC_REG_BASE _icctrl_msc 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #define MSCIC_WRITE(reg, data) do { *(volatile u32 *)(reg) = data; } while (0) 261da177e4SLinus Torvalds #define MSCIC_READ(reg, data) do { data = *(volatile u32 *)(reg); } while (0) 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds static unsigned int irq_base; 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds /* mask off an interrupt */ 31e15883daSThomas Gleixner static inline void mask_msc_irq(struct irq_data *d) 321da177e4SLinus Torvalds { 33e15883daSThomas Gleixner unsigned int irq = d->irq; 34e15883daSThomas Gleixner 351da177e4SLinus Torvalds if (irq < (irq_base + 32)) 361da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base)); 371da177e4SLinus Torvalds else 381da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_DISH, 1<<(irq - irq_base - 32)); 391da177e4SLinus Torvalds } 401da177e4SLinus Torvalds 411da177e4SLinus Torvalds /* unmask an interrupt */ 42e15883daSThomas Gleixner static inline void unmask_msc_irq(struct irq_data *d) 431da177e4SLinus Torvalds { 44e15883daSThomas Gleixner unsigned int irq = d->irq; 45e15883daSThomas Gleixner 461da177e4SLinus Torvalds if (irq < (irq_base + 32)) 471da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base)); 481da177e4SLinus Torvalds else 491da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_ENAH, 1<<(irq - irq_base - 32)); 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds /* 531da177e4SLinus Torvalds * Masks and ACKs an IRQ 541da177e4SLinus Torvalds */ 55e15883daSThomas Gleixner static void level_mask_and_ack_msc_irq(struct irq_data *d) 561da177e4SLinus Torvalds { 57e15883daSThomas Gleixner unsigned int irq = d->irq; 58e15883daSThomas Gleixner 59e15883daSThomas Gleixner mask_msc_irq(d); 60e01402b1SRalf Baechle if (!cpu_has_veic) 611da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_EOI, 0); 6241c594abSRalf Baechle /* This actually needs to be a call into platform code */ 631146fe30SRalf Baechle smtc_im_ack_irq(irq); 641da177e4SLinus Torvalds } 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds /* 671da177e4SLinus Torvalds * Masks and ACKs an IRQ 681da177e4SLinus Torvalds */ 69e15883daSThomas Gleixner static void edge_mask_and_ack_msc_irq(struct irq_data *d) 701da177e4SLinus Torvalds { 71e15883daSThomas Gleixner unsigned int irq = d->irq; 72e15883daSThomas Gleixner 73e15883daSThomas Gleixner mask_msc_irq(d); 74e01402b1SRalf Baechle if (!cpu_has_veic) 751da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_EOI, 0); 761da177e4SLinus Torvalds else { 771da177e4SLinus Torvalds u32 r; 781da177e4SLinus Torvalds MSCIC_READ(MSC01_IC_SUP+irq*8, r); 791da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+irq*8, r | ~MSC01_IC_SUP_EDGE_BIT); 801da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+irq*8, r); 811da177e4SLinus Torvalds } 821146fe30SRalf Baechle smtc_im_ack_irq(irq); 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds /* 861da177e4SLinus Torvalds * Interrupt handler for interrupts coming from SOC-it. 871da177e4SLinus Torvalds */ 88937a8015SRalf Baechle void ll_msc_irq(void) 891da177e4SLinus Torvalds { 901da177e4SLinus Torvalds unsigned int irq; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds /* read the interrupt vector register */ 931da177e4SLinus Torvalds MSCIC_READ(MSC01_IC_VEC, irq); 941da177e4SLinus Torvalds if (irq < 64) 95937a8015SRalf Baechle do_IRQ(irq + irq_base); 961da177e4SLinus Torvalds else { 971da177e4SLinus Torvalds /* Ignore spurious interrupt */ 981da177e4SLinus Torvalds } 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds 101411ba7fcSAtsushi Nemoto static void msc_bind_eic_interrupt(int irq, int set) 1021da177e4SLinus Torvalds { 1031da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_RAMW, 1041da177e4SLinus Torvalds (irq<<MSC01_IC_RAMW_ADDR_SHF) | (set<<MSC01_IC_RAMW_DATA_SHF)); 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds 107411ba7fcSAtsushi Nemoto static struct irq_chip msc_levelirq_type = { 10870d21cdeSAtsushi Nemoto .name = "SOC-it-Level", 109e15883daSThomas Gleixner .irq_ack = level_mask_and_ack_msc_irq, 110e15883daSThomas Gleixner .irq_mask = mask_msc_irq, 111e15883daSThomas Gleixner .irq_mask_ack = level_mask_and_ack_msc_irq, 112e15883daSThomas Gleixner .irq_unmask = unmask_msc_irq, 113e15883daSThomas Gleixner .irq_eoi = unmask_msc_irq, 1141da177e4SLinus Torvalds }; 1151da177e4SLinus Torvalds 116411ba7fcSAtsushi Nemoto static struct irq_chip msc_edgeirq_type = { 11770d21cdeSAtsushi Nemoto .name = "SOC-it-Edge", 118e15883daSThomas Gleixner .irq_ack = edge_mask_and_ack_msc_irq, 119e15883daSThomas Gleixner .irq_mask = mask_msc_irq, 120e15883daSThomas Gleixner .irq_mask_ack = edge_mask_and_ack_msc_irq, 121e15883daSThomas Gleixner .irq_unmask = unmask_msc_irq, 122e15883daSThomas Gleixner .irq_eoi = unmask_msc_irq, 1231da177e4SLinus Torvalds }; 1241da177e4SLinus Torvalds 1251da177e4SLinus Torvalds 126d725cf38SChris Dearman void __init init_msc_irqs(unsigned long icubase, unsigned int irqbase, msc_irqmap_t *imp, int nirq) 1271da177e4SLinus Torvalds { 128d725cf38SChris Dearman _icctrl_msc = (unsigned long) ioremap(icubase, 0x40000); 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds /* Reset interrupt controller - initialises all registers to 0 */ 1311da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_RST, MSC01_IC_RST_RST_BIT); 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds board_bind_eic_interrupt = &msc_bind_eic_interrupt; 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds for (; nirq >= 0; nirq--, imp++) { 1361da177e4SLinus Torvalds int n = imp->im_irq; 1371da177e4SLinus Torvalds 1381da177e4SLinus Torvalds switch (imp->im_type) { 1391da177e4SLinus Torvalds case MSC01_IRQ_EDGE: 140*e4ec7989SThomas Gleixner irq_set_chip_and_handler_name(irqbase + n, 141*e4ec7989SThomas Gleixner &msc_edgeirq_type, 142*e4ec7989SThomas Gleixner handle_edge_irq, 143*e4ec7989SThomas Gleixner "edge"); 144e01402b1SRalf Baechle if (cpu_has_veic) 1451da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT); 1461da177e4SLinus Torvalds else 1471da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl); 1481da177e4SLinus Torvalds break; 1491da177e4SLinus Torvalds case MSC01_IRQ_LEVEL: 150*e4ec7989SThomas Gleixner irq_set_chip_and_handler_name(irqbase + n, 151*e4ec7989SThomas Gleixner &msc_levelirq_type, 152*e4ec7989SThomas Gleixner handle_level_irq, 153*e4ec7989SThomas Gleixner "level"); 154e01402b1SRalf Baechle if (cpu_has_veic) 1551da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+n*8, 0); 1561da177e4SLinus Torvalds else 1571da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_SUP+n*8, imp->im_lvl); 1581da177e4SLinus Torvalds } 1591da177e4SLinus Torvalds } 1601da177e4SLinus Torvalds 161d725cf38SChris Dearman irq_base = irqbase; 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds MSCIC_WRITE(MSC01_IC_GENA, MSC01_IC_GENA_GENA_BIT); /* Enable interrupt generation */ 1641da177e4SLinus Torvalds 1651da177e4SLinus Torvalds } 166