• 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 #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 
55 struct eic {
56 	void __iomem *regs;
57 	struct irq_chip *chip;
58 	unsigned int first_irq;
59 };
60 
61 static struct eic *nmi_eic;
62 static bool nmi_enabled;
63 
eic_ack_irq(struct irq_data * d)64 static 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 
eic_mask_irq(struct irq_data * d)70 static 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 
eic_mask_ack_irq(struct irq_data * d)76 static 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 
eic_unmask_irq(struct irq_data * d)83 static 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 
eic_set_irq_type(struct irq_data * d,unsigned int flow_type)89 static 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 
138 static 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 
demux_eic_irq(unsigned int irq,struct irq_desc * desc)147 static 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 
nmi_enable(void)164 int 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 
nmi_disable(void)174 void nmi_disable(void)
175 {
176 	if (nmi_eic)
177 		eic_writel(nmi_eic, NMIC, 0);
178 
179 	nmi_enabled = false;
180 }
181 
eic_probe(struct platform_device * pdev)182 static 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 
256 err_ioremap:
257 	kfree(eic);
258 err_kzalloc:
259 	return ret;
260 }
261 
262 static struct platform_driver eic_driver = {
263 	.driver = {
264 		.name = "at32_eic",
265 	},
266 };
267 
eic_init(void)268 static int __init eic_init(void)
269 {
270 	return platform_driver_probe(&eic_driver, eic_probe);
271 }
272 arch_initcall(eic_init);
273