| /* |
| * Copyright (C) Telechips, Inc. |
| * Copyright (C) 2009-2010 Hans J. Koch <hjk@linutronix.de> |
| * |
| * Licensed under the terms of the GNU GPL version 2. |
| */ |
| |
| #include <linux/init.h> |
| #include <linux/interrupt.h> |
| #include <linux/io.h> |
| |
| #include <asm/irq.h> |
| #include <asm/mach/irq.h> |
| |
| #include <mach/tcc8k-regs.h> |
| #include <mach/irqs.h> |
| |
| #include "common.h" |
| |
| /* Disable IRQ */ |
| static void tcc8000_mask_ack_irq0(struct irq_data *d) |
| { |
| PIC0_IEN &= ~(1 << d->irq); |
| PIC0_CREQ |= (1 << d->irq); |
| } |
| |
| static void tcc8000_mask_ack_irq1(struct irq_data *d) |
| { |
| PIC1_IEN &= ~(1 << (d->irq - 32)); |
| PIC1_CREQ |= (1 << (d->irq - 32)); |
| } |
| |
| static void tcc8000_mask_irq0(struct irq_data *d) |
| { |
| PIC0_IEN &= ~(1 << d->irq); |
| } |
| |
| static void tcc8000_mask_irq1(struct irq_data *d) |
| { |
| PIC1_IEN &= ~(1 << (d->irq - 32)); |
| } |
| |
| static void tcc8000_ack_irq0(struct irq_data *d) |
| { |
| PIC0_CREQ |= (1 << d->irq); |
| } |
| |
| static void tcc8000_ack_irq1(struct irq_data *d) |
| { |
| PIC1_CREQ |= (1 << (d->irq - 32)); |
| } |
| |
| /* Enable IRQ */ |
| static void tcc8000_unmask_irq0(struct irq_data *d) |
| { |
| PIC0_IEN |= (1 << d->irq); |
| PIC0_INTOEN |= (1 << d->irq); |
| } |
| |
| static void tcc8000_unmask_irq1(struct irq_data *d) |
| { |
| PIC1_IEN |= (1 << (d->irq - 32)); |
| PIC1_INTOEN |= (1 << (d->irq - 32)); |
| } |
| |
| static struct irq_chip tcc8000_irq_chip0 = { |
| .name = "tcc_irq0", |
| .irq_mask = tcc8000_mask_irq0, |
| .irq_ack = tcc8000_ack_irq0, |
| .irq_mask_ack = tcc8000_mask_ack_irq0, |
| .irq_unmask = tcc8000_unmask_irq0, |
| }; |
| |
| static struct irq_chip tcc8000_irq_chip1 = { |
| .name = "tcc_irq1", |
| .irq_mask = tcc8000_mask_irq1, |
| .irq_ack = tcc8000_ack_irq1, |
| .irq_mask_ack = tcc8000_mask_ack_irq1, |
| .irq_unmask = tcc8000_unmask_irq1, |
| }; |
| |
| void __init tcc8k_init_irq(void) |
| { |
| int irqno; |
| |
| /* Mask and clear all interrupts */ |
| PIC0_IEN = 0x00000000; |
| PIC0_CREQ = 0xffffffff; |
| PIC1_IEN = 0x00000000; |
| PIC1_CREQ = 0xffffffff; |
| |
| PIC0_MEN0 = 0x00000003; |
| PIC1_MEN1 = 0x00000003; |
| PIC1_MEN = 0x00000003; |
| |
| /* let all IRQs be level triggered */ |
| PIC0_TMODE = 0xffffffff; |
| PIC1_TMODE = 0xffffffff; |
| /* all IRQs are IRQs (not FIQs) */ |
| PIC0_IRQSEL = 0xffffffff; |
| PIC1_IRQSEL = 0xffffffff; |
| |
| for (irqno = 0; irqno < NR_IRQS; irqno++) { |
| if (irqno < 32) |
| irq_set_chip(irqno, &tcc8000_irq_chip0); |
| else |
| irq_set_chip(irqno, &tcc8000_irq_chip1); |
| irq_set_handler(irqno, handle_level_irq); |
| set_irq_flags(irqno, IRQF_VALID); |
| } |
| } |