• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /* EIC register offsets */
21 #define EIC_IER					0x0000
22 #define EIC_IDR					0x0004
23 #define EIC_IMR					0x0008
24 #define EIC_ISR					0x000c
25 #define EIC_ICR					0x0010
26 #define EIC_MODE				0x0014
27 #define EIC_EDGE				0x0018
28 #define EIC_LEVEL				0x001c
29 #define EIC_NMIC				0x0024
30 
31 /* Bitfields in NMIC */
32 #define EIC_NMIC_ENABLE				(1 << 0)
33 
34 /* Bit manipulation macros */
35 #define EIC_BIT(name)					\
36 	(1 << EIC_##name##_OFFSET)
37 #define EIC_BF(name,value)				\
38 	(((value) & ((1 << EIC_##name##_SIZE) - 1))	\
39 	 << EIC_##name##_OFFSET)
40 #define EIC_BFEXT(name,value)				\
41 	(((value) >> EIC_##name##_OFFSET)		\
42 	 & ((1 << EIC_##name##_SIZE) - 1))
43 #define EIC_BFINS(name,value,old)			\
44 	(((old) & ~(((1 << EIC_##name##_SIZE) - 1)	\
45 		    << EIC_##name##_OFFSET))		\
46 	 | EIC_BF(name,value))
47 
48 /* Register access macros */
49 #define eic_readl(port,reg)				\
50 	__raw_readl((port)->regs + EIC_##reg)
51 #define eic_writel(port,reg,value)			\
52 	__raw_writel((value), (port)->regs + EIC_##reg)
53 
54 struct eic {
55 	void __iomem *regs;
56 	struct irq_chip *chip;
57 	unsigned int first_irq;
58 };
59 
60 static struct eic *nmi_eic;
61 static bool nmi_enabled;
62 
eic_ack_irq(unsigned int irq)63 static void eic_ack_irq(unsigned int irq)
64 {
65 	struct eic *eic = get_irq_chip_data(irq);
66 	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
67 }
68 
eic_mask_irq(unsigned int irq)69 static void eic_mask_irq(unsigned int irq)
70 {
71 	struct eic *eic = get_irq_chip_data(irq);
72 	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
73 }
74 
eic_mask_ack_irq(unsigned int irq)75 static void eic_mask_ack_irq(unsigned int irq)
76 {
77 	struct eic *eic = get_irq_chip_data(irq);
78 	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
79 	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
80 }
81 
eic_unmask_irq(unsigned int irq)82 static void eic_unmask_irq(unsigned int irq)
83 {
84 	struct eic *eic = get_irq_chip_data(irq);
85 	eic_writel(eic, IER, 1 << (irq - eic->first_irq));
86 }
87 
eic_set_irq_type(unsigned int irq,unsigned int flow_type)88 static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
89 {
90 	struct eic *eic = get_irq_chip_data(irq);
91 	struct irq_desc *desc;
92 	unsigned int i = irq - eic->first_irq;
93 	u32 mode, edge, level;
94 	int ret = 0;
95 
96 	flow_type &= IRQ_TYPE_SENSE_MASK;
97 	if (flow_type == IRQ_TYPE_NONE)
98 		flow_type = IRQ_TYPE_LEVEL_LOW;
99 
100 	desc = &irq_desc[irq];
101 
102 	mode = eic_readl(eic, MODE);
103 	edge = eic_readl(eic, EDGE);
104 	level = eic_readl(eic, LEVEL);
105 
106 	switch (flow_type) {
107 	case IRQ_TYPE_LEVEL_LOW:
108 		mode |= 1 << i;
109 		level &= ~(1 << i);
110 		break;
111 	case IRQ_TYPE_LEVEL_HIGH:
112 		mode |= 1 << i;
113 		level |= 1 << i;
114 		break;
115 	case IRQ_TYPE_EDGE_RISING:
116 		mode &= ~(1 << i);
117 		edge |= 1 << i;
118 		break;
119 	case IRQ_TYPE_EDGE_FALLING:
120 		mode &= ~(1 << i);
121 		edge &= ~(1 << i);
122 		break;
123 	default:
124 		ret = -EINVAL;
125 		break;
126 	}
127 
128 	if (ret == 0) {
129 		eic_writel(eic, MODE, mode);
130 		eic_writel(eic, EDGE, edge);
131 		eic_writel(eic, LEVEL, level);
132 
133 		if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
134 			flow_type |= IRQ_LEVEL;
135 			__set_irq_handler_unlocked(irq, handle_level_irq);
136 		} else
137 			__set_irq_handler_unlocked(irq, handle_edge_irq);
138 		desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
139 		desc->status |= flow_type;
140 	}
141 
142 	return ret;
143 }
144 
145 static struct irq_chip eic_chip = {
146 	.name		= "eic",
147 	.ack		= eic_ack_irq,
148 	.mask		= eic_mask_irq,
149 	.mask_ack	= eic_mask_ack_irq,
150 	.unmask		= eic_unmask_irq,
151 	.set_type	= eic_set_irq_type,
152 };
153 
demux_eic_irq(unsigned int irq,struct irq_desc * desc)154 static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
155 {
156 	struct eic *eic = desc->handler_data;
157 	unsigned long status, pending;
158 	unsigned int i;
159 
160 	status = eic_readl(eic, ISR);
161 	pending = status & eic_readl(eic, IMR);
162 
163 	while (pending) {
164 		i = fls(pending) - 1;
165 		pending &= ~(1 << i);
166 
167 		generic_handle_irq(i + eic->first_irq);
168 	}
169 }
170 
nmi_enable(void)171 int nmi_enable(void)
172 {
173 	nmi_enabled = true;
174 
175 	if (nmi_eic)
176 		eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE);
177 
178 	return 0;
179 }
180 
nmi_disable(void)181 void nmi_disable(void)
182 {
183 	if (nmi_eic)
184 		eic_writel(nmi_eic, NMIC, 0);
185 
186 	nmi_enabled = false;
187 }
188 
eic_probe(struct platform_device * pdev)189 static int __init eic_probe(struct platform_device *pdev)
190 {
191 	struct eic *eic;
192 	struct resource *regs;
193 	unsigned int i;
194 	unsigned int nr_of_irqs;
195 	unsigned int int_irq;
196 	int ret;
197 	u32 pattern;
198 
199 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
200 	int_irq = platform_get_irq(pdev, 0);
201 	if (!regs || !int_irq) {
202 		dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
203 		return -ENXIO;
204 	}
205 
206 	ret = -ENOMEM;
207 	eic = kzalloc(sizeof(struct eic), GFP_KERNEL);
208 	if (!eic) {
209 		dev_dbg(&pdev->dev, "no memory for eic structure\n");
210 		goto err_kzalloc;
211 	}
212 
213 	eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id;
214 	eic->regs = ioremap(regs->start, regs->end - regs->start + 1);
215 	if (!eic->regs) {
216 		dev_dbg(&pdev->dev, "failed to map regs\n");
217 		goto err_ioremap;
218 	}
219 
220 	/*
221 	 * Find out how many interrupt lines that are actually
222 	 * implemented in hardware.
223 	 */
224 	eic_writel(eic, IDR, ~0UL);
225 	eic_writel(eic, MODE, ~0UL);
226 	pattern = eic_readl(eic, MODE);
227 	nr_of_irqs = fls(pattern);
228 
229 	/* Trigger on low level unless overridden by driver */
230 	eic_writel(eic, EDGE, 0UL);
231 	eic_writel(eic, LEVEL, 0UL);
232 
233 	eic->chip = &eic_chip;
234 
235 	for (i = 0; i < nr_of_irqs; i++) {
236 		set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
237 					 handle_level_irq);
238 		set_irq_chip_data(eic->first_irq + i, eic);
239 	}
240 
241 	set_irq_chained_handler(int_irq, demux_eic_irq);
242 	set_irq_data(int_irq, eic);
243 
244 	if (pdev->id == 0) {
245 		nmi_eic = eic;
246 		if (nmi_enabled)
247 			/*
248 			 * Someone tried to enable NMI before we were
249 			 * ready. Do it now.
250 			 */
251 			nmi_enable();
252 	}
253 
254 	dev_info(&pdev->dev,
255 		 "External Interrupt Controller at 0x%p, IRQ %u\n",
256 		 eic->regs, int_irq);
257 	dev_info(&pdev->dev,
258 		 "Handling %u external IRQs, starting with IRQ %u\n",
259 		 nr_of_irqs, eic->first_irq);
260 
261 	return 0;
262 
263 err_ioremap:
264 	kfree(eic);
265 err_kzalloc:
266 	return ret;
267 }
268 
269 static struct platform_driver eic_driver = {
270 	.driver = {
271 		.name = "at32_eic",
272 	},
273 };
274 
eic_init(void)275 static int __init eic_init(void)
276 {
277 	return platform_driver_probe(&eic_driver, eic_probe);
278 }
279 arch_initcall(eic_init);
280