| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* arch/arm/mach-lh7a40x/irq-lpd7a40x.c | 
|  | 2 | * | 
|  | 3 | *  Copyright (C) 2004 Coastal Environmental Systems | 
|  | 4 | *  Copyright (C) 2004 Logic Product Development | 
|  | 5 | * | 
|  | 6 | *  This program is free software; you can redistribute it and/or | 
|  | 7 | *  modify it under the terms of the GNU General Public License | 
|  | 8 | *  version 2 as published by the Free Software Foundation. | 
|  | 9 | * | 
|  | 10 | */ | 
|  | 11 |  | 
|  | 12 | #include <linux/init.h> | 
|  | 13 | #include <linux/module.h> | 
|  | 14 | #include <linux/interrupt.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 15 |  | 
|  | 16 | #include <asm/hardware.h> | 
|  | 17 | #include <asm/irq.h> | 
|  | 18 | #include <asm/mach/irq.h> | 
|  | 19 | #include <asm/arch/irqs.h> | 
|  | 20 |  | 
| Russell King | 411ef7f | 2006-03-04 10:37:07 +0000 | [diff] [blame] | 21 | #include "common.h" | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 22 |  | 
|  | 23 | static void lh7a40x_ack_cpld_irq (u32 irq) | 
|  | 24 | { | 
|  | 25 | /* CPLD doesn't have ack capability */ | 
|  | 26 | } | 
|  | 27 |  | 
|  | 28 | static void lh7a40x_mask_cpld_irq (u32 irq) | 
|  | 29 | { | 
|  | 30 | switch (irq) { | 
|  | 31 | case IRQ_LPD7A40X_ETH_INT: | 
|  | 32 | CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4; | 
|  | 33 | break; | 
|  | 34 | case IRQ_LPD7A400_TS: | 
|  | 35 | CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8; | 
|  | 36 | break; | 
|  | 37 | } | 
|  | 38 | } | 
|  | 39 |  | 
|  | 40 | static void lh7a40x_unmask_cpld_irq (u32 irq) | 
|  | 41 | { | 
|  | 42 | switch (irq) { | 
|  | 43 | case IRQ_LPD7A40X_ETH_INT: | 
|  | 44 | CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4; | 
|  | 45 | break; | 
|  | 46 | case IRQ_LPD7A400_TS: | 
|  | 47 | CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8; | 
|  | 48 | break; | 
|  | 49 | } | 
|  | 50 | } | 
|  | 51 |  | 
| David Brownell | 38c677c | 2006-08-01 22:26:25 +0100 | [diff] [blame] | 52 | static struct irq_chip lh7a40x_cpld_chip = { | 
|  | 53 | .name	= "CPLD", | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 54 | .ack	= lh7a40x_ack_cpld_irq, | 
|  | 55 | .mask	= lh7a40x_mask_cpld_irq, | 
|  | 56 | .unmask	= lh7a40x_unmask_cpld_irq, | 
|  | 57 | }; | 
|  | 58 |  | 
| Russell King | 10dd5ce | 2006-11-23 11:41:32 +0000 | [diff] [blame] | 59 | static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 60 | { | 
|  | 61 | unsigned int mask = CPLD_INTERRUPTS; | 
|  | 62 |  | 
|  | 63 | desc->chip->ack (irq); | 
|  | 64 |  | 
|  | 65 | if ((mask & 0x1) == 0)	/* WLAN */ | 
|  | 66 | IRQ_DISPATCH (IRQ_LPD7A40X_ETH_INT); | 
|  | 67 |  | 
|  | 68 | if ((mask & 0x2) == 0)	/* Touch */ | 
|  | 69 | IRQ_DISPATCH (IRQ_LPD7A400_TS); | 
|  | 70 |  | 
|  | 71 | desc->chip->unmask (irq); /* Level-triggered need this */ | 
|  | 72 | } | 
|  | 73 |  | 
|  | 74 |  | 
|  | 75 | /* IRQ initialization */ | 
|  | 76 |  | 
|  | 77 | void __init lh7a40x_init_board_irq (void) | 
|  | 78 | { | 
|  | 79 | int irq; | 
|  | 80 |  | 
|  | 81 | /* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs. | 
|  | 82 | PF7 supports the CPLD. | 
|  | 83 | Rev B (v3.4): PF0, PF1, and PF2 are available IRQs. | 
|  | 84 | PF3 supports the CPLD. | 
|  | 85 | (Some) LPD7A404 prerelease boards report a version | 
|  | 86 | number of 0x16, but we force an override since the | 
|  | 87 | hardware is of the newer variety. | 
|  | 88 | */ | 
|  | 89 |  | 
|  | 90 | unsigned char cpld_version = CPLD_REVISION; | 
|  | 91 | int pinCPLD; | 
|  | 92 |  | 
|  | 93 | #if defined CONFIG_MACH_LPD7A404 | 
|  | 94 | cpld_version = 0x34;	/* Override, for now */ | 
|  | 95 | #endif | 
|  | 96 | pinCPLD = (cpld_version == 0x28) ? 7 : 3; | 
|  | 97 |  | 
|  | 98 | /* First, configure user controlled GPIOF interrupts  */ | 
|  | 99 |  | 
|  | 100 | GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */ | 
|  | 101 | GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */ | 
|  | 102 | GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */ | 
|  | 103 | barrier (); | 
|  | 104 | GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */ | 
|  | 105 |  | 
|  | 106 | /* Then, configure CPLD interrupt */ | 
|  | 107 |  | 
|  | 108 | CPLD_INTERRUPTS	=   0x0c; /* Disable all CPLD interrupts */ | 
|  | 109 | GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */ | 
|  | 110 | GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */ | 
|  | 111 | GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */ | 
|  | 112 | barrier (); | 
|  | 113 | GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */ | 
|  | 114 |  | 
|  | 115 | /* Cascade CPLD interrupts */ | 
|  | 116 |  | 
|  | 117 | for (irq = IRQ_BOARD_START; | 
|  | 118 | irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) { | 
|  | 119 | set_irq_chip (irq, &lh7a40x_cpld_chip); | 
| Russell King | 10dd5ce | 2006-11-23 11:41:32 +0000 | [diff] [blame] | 120 | set_irq_handler (irq, handle_edge_irq); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 121 | set_irq_flags (irq, IRQF_VALID); | 
|  | 122 | } | 
|  | 123 |  | 
|  | 124 | set_irq_chained_handler ((cpld_version == 0x28) | 
|  | 125 | ? IRQ_CPLD_V28 | 
|  | 126 | : IRQ_CPLD_V34, | 
|  | 127 | lh7a40x_cpld_handler); | 
|  | 128 | } |