diff options
| -rw-r--r-- | arch/m68k/include/asm/m520xsim.h | 3 | ||||
| -rw-r--r-- | arch/m68knommu/platform/coldfire/intc-simr.c | 114 |
2 files changed, 113 insertions, 4 deletions
diff --git a/arch/m68k/include/asm/m520xsim.h b/arch/m68k/include/asm/m520xsim.h index ee89801eec9d..55d5a4c5fe0b 100644 --- a/arch/m68k/include/asm/m520xsim.h +++ b/arch/m68k/include/asm/m520xsim.h | |||
| @@ -63,9 +63,12 @@ | |||
| 63 | /* | 63 | /* |
| 64 | * EPORT and GPIO registers. | 64 | * EPORT and GPIO registers. |
| 65 | */ | 65 | */ |
| 66 | #define MCFEPORT_EPPAR 0xFC088000 | ||
| 66 | #define MCFEPORT_EPDDR 0xFC088002 | 67 | #define MCFEPORT_EPDDR 0xFC088002 |
| 68 | #define MCFEPORT_EPIER 0xFC088003 | ||
| 67 | #define MCFEPORT_EPDR 0xFC088004 | 69 | #define MCFEPORT_EPDR 0xFC088004 |
| 68 | #define MCFEPORT_EPPDR 0xFC088005 | 70 | #define MCFEPORT_EPPDR 0xFC088005 |
| 71 | #define MCFEPORT_EPFR 0xFC088006 | ||
| 69 | 72 | ||
| 70 | #define MCFGPIO_PODR_BUSCTL 0xFC0A4000 | 73 | #define MCFGPIO_PODR_BUSCTL 0xFC0A4000 |
| 71 | #define MCFGPIO_PODR_BE 0xFC0A4001 | 74 | #define MCFGPIO_PODR_BE 0xFC0A4001 |
diff --git a/arch/m68knommu/platform/coldfire/intc-simr.c b/arch/m68knommu/platform/coldfire/intc-simr.c index 8876f434c125..e642b24ab729 100644 --- a/arch/m68knommu/platform/coldfire/intc-simr.c +++ b/arch/m68knommu/platform/coldfire/intc-simr.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts. | 4 | * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts. |
| 5 | * | 5 | * |
| 6 | * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com> | 6 | * (C) Copyright 2009-2011, Greg Ungerer <gerg@snapgear.com> |
| 7 | * | 7 | * |
| 8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
| 9 | * License. See the file COPYING in the main directory of this archive | 9 | * License. See the file COPYING in the main directory of this archive |
| @@ -21,6 +21,44 @@ | |||
| 21 | #include <asm/traps.h> | 21 | #include <asm/traps.h> |
| 22 | 22 | ||
| 23 | /* | 23 | /* |
| 24 | * The EDGE Port interrupts are the fixed 7 external interrupts. | ||
| 25 | * They need some special treatment, for example they need to be acked. | ||
| 26 | */ | ||
| 27 | #ifdef CONFIG_M520x | ||
| 28 | /* | ||
| 29 | * The 520x parts only support a limited range of these external | ||
| 30 | * interrupts, only 1, 4 and 7 (as interrupts 65, 66 and 67). | ||
| 31 | */ | ||
| 32 | #define EINT0 64 /* Is not actually used, but spot reserved for it */ | ||
| 33 | #define EINT1 65 /* EDGE Port interrupt 1 */ | ||
| 34 | #define EINT4 66 /* EDGE Port interrupt 4 */ | ||
| 35 | #define EINT7 67 /* EDGE Port interrupt 7 */ | ||
| 36 | |||
| 37 | static unsigned int irqebitmap[] = { 0, 1, 4, 7 }; | ||
| 38 | static unsigned int inline irq2ebit(unsigned int irq) | ||
| 39 | { | ||
| 40 | return irqebitmap[irq - EINT0]; | ||
| 41 | } | ||
| 42 | |||
| 43 | #else | ||
| 44 | |||
| 45 | /* | ||
| 46 | * Most of the ColdFire parts with the EDGE Port module just have | ||
| 47 | * a strait direct mapping of the 7 external interrupts. Although | ||
| 48 | * there is a bit reserved for 0, it is not used. | ||
| 49 | */ | ||
| 50 | #define EINT0 64 /* Is not actually used, but spot reserved for it */ | ||
| 51 | #define EINT1 65 /* EDGE Port interrupt 1 */ | ||
| 52 | #define EINT7 71 /* EDGE Port interrupt 7 */ | ||
| 53 | |||
| 54 | static unsigned int inline irq2ebit(unsigned int irq) | ||
| 55 | { | ||
| 56 | return irq - EINT0; | ||
| 57 | } | ||
| 58 | |||
| 59 | #endif | ||
| 60 | |||
| 61 | /* | ||
| 24 | * There maybe one or two interrupt control units, each has 64 | 62 | * There maybe one or two interrupt control units, each has 64 |
| 25 | * interrupts. If there is no second unit then MCFINTC1_* defines | 63 | * interrupts. If there is no second unit then MCFINTC1_* defines |
| 26 | * will be 0 (and code for them optimized away). | 64 | * will be 0 (and code for them optimized away). |
| @@ -46,21 +84,86 @@ static void intc_irq_unmask(struct irq_data *d) | |||
| 46 | __raw_writeb(irq, MCFINTC0_CIMR); | 84 | __raw_writeb(irq, MCFINTC0_CIMR); |
| 47 | } | 85 | } |
| 48 | 86 | ||
| 49 | static int intc_irq_set_type(struct irq_data *d, unsigned int type) | 87 | static void intc_irq_ack(struct irq_data *d) |
| 50 | { | 88 | { |
| 51 | unsigned int irq = d->irq - MCFINT_VECBASE; | 89 | unsigned int ebit = irq2ebit(d->irq); |
| 52 | 90 | ||
| 91 | __raw_writeb(0x1 << ebit, MCFEPORT_EPFR); | ||
| 92 | } | ||
| 93 | |||
| 94 | static unsigned int intc_irq_startup(struct irq_data *d) | ||
| 95 | { | ||
| 96 | unsigned int irq = d->irq; | ||
| 97 | |||
| 98 | if ((irq >= EINT1) && (irq <= EINT7)) { | ||
| 99 | unsigned int ebit = irq2ebit(irq); | ||
| 100 | u8 v; | ||
| 101 | |||
| 102 | /* Set EPORT line as input */ | ||
| 103 | v = __raw_readb(MCFEPORT_EPDDR); | ||
| 104 | __raw_writeb(v & ~(0x1 << ebit), MCFEPORT_EPDDR); | ||
| 105 | |||
| 106 | /* Set EPORT line as interrupt source */ | ||
| 107 | v = __raw_readb(MCFEPORT_EPIER); | ||
| 108 | __raw_writeb(v | (0x1 << ebit), MCFEPORT_EPIER); | ||
| 109 | } | ||
| 110 | |||
| 111 | irq -= MCFINT_VECBASE; | ||
| 53 | if (MCFINTC1_ICR0 && (irq > 64)) | 112 | if (MCFINTC1_ICR0 && (irq > 64)) |
| 54 | __raw_writeb(5, MCFINTC1_ICR0 + irq - 64); | 113 | __raw_writeb(5, MCFINTC1_ICR0 + irq - 64); |
| 55 | else | 114 | else |
| 56 | __raw_writeb(5, MCFINTC0_ICR0 + irq); | 115 | __raw_writeb(5, MCFINTC0_ICR0 + irq); |
| 116 | |||
| 117 | |||
| 118 | intc_irq_unmask(d); | ||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int intc_irq_set_type(struct irq_data *d, unsigned int type) | ||
| 123 | { | ||
| 124 | unsigned int ebit, irq = d->irq; | ||
| 125 | u16 pa, tb; | ||
| 126 | |||
| 127 | switch (type) { | ||
| 128 | case IRQ_TYPE_EDGE_RISING: | ||
| 129 | tb = 0x1; | ||
| 130 | break; | ||
| 131 | case IRQ_TYPE_EDGE_FALLING: | ||
| 132 | tb = 0x2; | ||
| 133 | break; | ||
| 134 | case IRQ_TYPE_EDGE_BOTH: | ||
| 135 | tb = 0x3; | ||
| 136 | break; | ||
| 137 | default: | ||
| 138 | /* Level triggered */ | ||
| 139 | tb = 0; | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (tb) | ||
| 144 | set_irq_handler(irq, handle_edge_irq); | ||
| 145 | |||
| 146 | ebit = irq2ebit(irq) * 2; | ||
| 147 | pa = __raw_readw(MCFEPORT_EPPAR); | ||
| 148 | pa = (pa & ~(0x3 << ebit)) | (tb << ebit); | ||
| 149 | __raw_writew(pa, MCFEPORT_EPPAR); | ||
| 150 | |||
| 57 | return 0; | 151 | return 0; |
| 58 | } | 152 | } |
| 59 | 153 | ||
| 60 | static struct irq_chip intc_irq_chip = { | 154 | static struct irq_chip intc_irq_chip = { |
| 61 | .name = "CF-INTC", | 155 | .name = "CF-INTC", |
| 156 | .irq_startup = intc_irq_startup, | ||
| 157 | .irq_mask = intc_irq_mask, | ||
| 158 | .irq_unmask = intc_irq_unmask, | ||
| 159 | }; | ||
| 160 | |||
| 161 | static struct irq_chip intc_irq_chip_edge_port = { | ||
| 162 | .name = "CF-INTC-EP", | ||
| 163 | .irq_startup = intc_irq_startup, | ||
| 62 | .irq_mask = intc_irq_mask, | 164 | .irq_mask = intc_irq_mask, |
| 63 | .irq_unmask = intc_irq_unmask, | 165 | .irq_unmask = intc_irq_unmask, |
| 166 | .irq_ack = intc_irq_ack, | ||
| 64 | .irq_set_type = intc_irq_set_type, | 167 | .irq_set_type = intc_irq_set_type, |
| 65 | }; | 168 | }; |
| 66 | 169 | ||
| @@ -77,7 +180,10 @@ void __init init_IRQ(void) | |||
| 77 | 180 | ||
| 78 | eirq = MCFINT_VECBASE + 64 + (MCFINTC1_ICR0 ? 64 : 0); | 181 | eirq = MCFINT_VECBASE + 64 + (MCFINTC1_ICR0 ? 64 : 0); |
| 79 | for (irq = MCFINT_VECBASE; (irq < eirq); irq++) { | 182 | for (irq = MCFINT_VECBASE; (irq < eirq); irq++) { |
| 80 | set_irq_chip(irq, &intc_irq_chip); | 183 | if ((irq >= EINT1) && (irq <= EINT7)) |
| 184 | set_irq_chip(irq, &intc_irq_chip_edge_port); | ||
| 185 | else | ||
| 186 | set_irq_chip(irq, &intc_irq_chip); | ||
| 81 | set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH); | 187 | set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH); |
| 82 | set_irq_handler(irq, handle_level_irq); | 188 | set_irq_handler(irq, handle_level_irq); |
| 83 | } | 189 | } |
