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