aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/extint.c
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2006-09-26 02:32:13 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:48:54 -0400
commit5f97f7f9400de47ae837170bb274e90ad3934386 (patch)
tree514451e6dc6b46253293a00035d375e77b1c65ed /arch/avr32/mach-at32ap/extint.c
parent53e62d3aaa60590d4a69b4e07c29f448b5151047 (diff)
[PATCH] avr32 architecture
This adds support for the Atmel AVR32 architecture as well as the AT32AP7000 CPU and the AT32STK1000 development board. AVR32 is a new high-performance 32-bit RISC microprocessor core, designed for cost-sensitive embedded applications, with particular emphasis on low power consumption and high code density. The AVR32 architecture is not binary compatible with earlier 8-bit AVR architectures. The AVR32 architecture, including the instruction set, is described by the AVR32 Architecture Manual, available from http://www.atmel.com/dyn/resources/prod_documents/doc32000.pdf The Atmel AT32AP7000 is the first CPU implementing the AVR32 architecture. It features a 7-stage pipeline, 16KB instruction and data caches and a full Memory Management Unit. It also comes with a large set of integrated peripherals, many of which are shared with the AT91 ARM-based controllers from Atmel. Full data sheet is available from http://www.atmel.com/dyn/resources/prod_documents/doc32003.pdf while the CPU core implementation including caches and MMU is documented by the AVR32 AP Technical Reference, available from http://www.atmel.com/dyn/resources/prod_documents/doc32001.pdf Information about the AT32STK1000 development board can be found at http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3918 including a BSP CD image with an earlier version of this patch, development tools (binaries and source/patches) and a root filesystem image suitable for booting from SD card. Alternatively, there's a preliminary "getting started" guide available at http://avr32linux.org/twiki/bin/view/Main/GettingStarted which provides links to the sources and patches you will need in order to set up a cross-compiling environment for avr32-linux. This patch, as well as the other patches included with the BSP and the toolchain patches, is actively supported by Atmel Corporation. [dmccr@us.ibm.com: Fix more pxx_page macro locations] [bunk@stusta.de: fix `make defconfig'] Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Dave McCracken <dmccr@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/avr32/mach-at32ap/extint.c')
-rw-r--r--arch/avr32/mach-at32ap/extint.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c
new file mode 100644
index 000000000000..7da9c5f7a0eb
--- /dev/null
+++ b/arch/avr32/mach-at32ap/extint.c
@@ -0,0 +1,171 @@
1/*
2 * External interrupt handling for AT32AP CPUs
3 *
4 * Copyright (C) 2006 Atmel Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/errno.h>
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/irq.h>
15#include <linux/platform_device.h>
16#include <linux/random.h>
17
18#include <asm/io.h>
19
20#include <asm/arch/sm.h>
21
22#include "sm.h"
23
24static void eim_ack_irq(unsigned int irq)
25{
26 struct at32_sm *sm = get_irq_chip_data(irq);
27 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
28}
29
30static void eim_mask_irq(unsigned int irq)
31{
32 struct at32_sm *sm = get_irq_chip_data(irq);
33 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
34}
35
36static void eim_mask_ack_irq(unsigned int irq)
37{
38 struct at32_sm *sm = get_irq_chip_data(irq);
39 sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq));
40 sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq));
41}
42
43static void eim_unmask_irq(unsigned int irq)
44{
45 struct at32_sm *sm = get_irq_chip_data(irq);
46 sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq));
47}
48
49static int eim_set_irq_type(unsigned int irq, unsigned int flow_type)
50{
51 struct at32_sm *sm = get_irq_chip_data(irq);
52 unsigned int i = irq - sm->eim_first_irq;
53 u32 mode, edge, level;
54 unsigned long flags;
55 int ret = 0;
56
57 flow_type &= IRQ_TYPE_SENSE_MASK;
58
59 spin_lock_irqsave(&sm->lock, flags);
60
61 mode = sm_readl(sm, EIM_MODE);
62 edge = sm_readl(sm, EIM_EDGE);
63 level = sm_readl(sm, EIM_LEVEL);
64
65 switch (flow_type) {
66 case IRQ_TYPE_LEVEL_LOW:
67 mode |= 1 << i;
68 level &= ~(1 << i);
69 break;
70 case IRQ_TYPE_LEVEL_HIGH:
71 mode |= 1 << i;
72 level |= 1 << i;
73 break;
74 case IRQ_TYPE_EDGE_RISING:
75 mode &= ~(1 << i);
76 edge |= 1 << i;
77 break;
78 case IRQ_TYPE_EDGE_FALLING:
79 mode &= ~(1 << i);
80 edge &= ~(1 << i);
81 break;
82 default:
83 ret = -EINVAL;
84 break;
85 }
86
87 sm_writel(sm, EIM_MODE, mode);
88 sm_writel(sm, EIM_EDGE, edge);
89 sm_writel(sm, EIM_LEVEL, level);
90
91 spin_unlock_irqrestore(&sm->lock, flags);
92
93 return ret;
94}
95
96struct irq_chip eim_chip = {
97 .name = "eim",
98 .ack = eim_ack_irq,
99 .mask = eim_mask_irq,
100 .mask_ack = eim_mask_ack_irq,
101 .unmask = eim_unmask_irq,
102 .set_type = eim_set_irq_type,
103};
104
105static void demux_eim_irq(unsigned int irq, struct irq_desc *desc,
106 struct pt_regs *regs)
107{
108 struct at32_sm *sm = desc->handler_data;
109 struct irq_desc *ext_desc;
110 unsigned long status, pending;
111 unsigned int i, ext_irq;
112
113 spin_lock(&sm->lock);
114
115 status = sm_readl(sm, EIM_ISR);
116 pending = status & sm_readl(sm, EIM_IMR);
117
118 while (pending) {
119 i = fls(pending) - 1;
120 pending &= ~(1 << i);
121
122 ext_irq = i + sm->eim_first_irq;
123 ext_desc = irq_desc + ext_irq;
124 ext_desc->handle_irq(ext_irq, ext_desc, regs);
125 }
126
127 spin_unlock(&sm->lock);
128}
129
130static int __init eim_init(void)
131{
132 struct at32_sm *sm = &system_manager;
133 unsigned int i;
134 unsigned int nr_irqs;
135 unsigned int int_irq;
136 u32 pattern;
137
138 /*
139 * The EIM is really the same module as SM, so register
140 * mapping, etc. has been taken care of already.
141 */
142
143 /*
144 * Find out how many interrupt lines that are actually
145 * implemented in hardware.
146 */
147 sm_writel(sm, EIM_IDR, ~0UL);
148 sm_writel(sm, EIM_MODE, ~0UL);
149 pattern = sm_readl(sm, EIM_MODE);
150 nr_irqs = fls(pattern);
151
152 sm->eim_chip = &eim_chip;
153
154 for (i = 0; i < nr_irqs; i++) {
155 set_irq_chip(sm->eim_first_irq + i, &eim_chip);
156 set_irq_chip_data(sm->eim_first_irq + i, sm);
157 }
158
159 int_irq = platform_get_irq_byname(sm->pdev, "eim");
160
161 set_irq_chained_handler(int_irq, demux_eim_irq);
162 set_irq_data(int_irq, sm);
163
164 printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n",
165 sm->regs, int_irq);
166 printk("EIM: Handling %u external IRQs, starting with IRQ %u\n",
167 nr_irqs, sm->eim_first_irq);
168
169 return 0;
170}
171arch_initcall(eim_init);