File Index
Files and directories
Sign in
FILE

irq-stm32-exti.c

File preview with syntax highlighting.

linux-6.19.14/drivers/irqchip/irq-stm32-exti.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) Maxime Coquelin 2015
  4 * Copyright (C) STMicroelectronics 2017-2024
  5 * Author:  Maxime Coquelin <mcoquelin.stm32@gmail.com>
  6 */
  7
  8#include <linux/bitops.h>
  9#include <linux/interrupt.h>
 10#include <linux/io.h>
 11#include <linux/irq.h>
 12#include <linux/irqchip.h>
 13#include <linux/irqchip/chained_irq.h>
 14#include <linux/irqdomain.h>
 15#include <linux/of_address.h>
 16#include <linux/of_irq.h>
 17
 18#define IRQS_PER_BANK			32
 19
 20struct stm32_exti_bank {
 21	u32 imr_ofst;
 22	u32 emr_ofst;
 23	u32 rtsr_ofst;
 24	u32 ftsr_ofst;
 25	u32 swier_ofst;
 26	u32 rpr_ofst;
 27};
 28
 29struct stm32_exti_drv_data {
 30	const struct stm32_exti_bank **exti_banks;
 31	const u8 *desc_irqs;
 32	u32 bank_nr;
 33};
 34
 35struct stm32_exti_chip_data {
 36	struct stm32_exti_host_data *host_data;
 37	const struct stm32_exti_bank *reg_bank;
 38	u32 wake_active;
 39	u32 mask_cache;
 40	u32 rtsr_cache;
 41	u32 ftsr_cache;
 42	u32 event_reserved;
 43};
 44
 45struct stm32_exti_host_data {
 46	void __iomem *base;
 47	struct device *dev;
 48	struct stm32_exti_chip_data *chips_data;
 49	const struct stm32_exti_drv_data *drv_data;
 50};
 51
 52static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
 53	.imr_ofst	= 0x00,
 54	.emr_ofst	= 0x04,
 55	.rtsr_ofst	= 0x08,
 56	.ftsr_ofst	= 0x0C,
 57	.swier_ofst	= 0x10,
 58	.rpr_ofst	= 0x14,
 59};
 60
 61static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
 62	&stm32f4xx_exti_b1,
 63};
 64
 65static const struct stm32_exti_drv_data stm32f4xx_drv_data = {
 66	.exti_banks = stm32f4xx_exti_banks,
 67	.bank_nr = ARRAY_SIZE(stm32f4xx_exti_banks),
 68};
 69
 70static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
 71	.imr_ofst	= 0x80,
 72	.emr_ofst	= 0x84,
 73	.rtsr_ofst	= 0x00,
 74	.ftsr_ofst	= 0x04,
 75	.swier_ofst	= 0x08,
 76	.rpr_ofst	= 0x88,
 77};
 78
 79static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
 80	.imr_ofst	= 0x90,
 81	.emr_ofst	= 0x94,
 82	.rtsr_ofst	= 0x20,
 83	.ftsr_ofst	= 0x24,
 84	.swier_ofst	= 0x28,
 85	.rpr_ofst	= 0x98,
 86};
 87
 88static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
 89	.imr_ofst	= 0xA0,
 90	.emr_ofst	= 0xA4,
 91	.rtsr_ofst	= 0x40,
 92	.ftsr_ofst	= 0x44,
 93	.swier_ofst	= 0x48,
 94	.rpr_ofst	= 0xA8,
 95};
 96
 97static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
 98	&stm32h7xx_exti_b1,
 99	&stm32h7xx_exti_b2,
100	&stm32h7xx_exti_b3,
101};
102
103static const struct stm32_exti_drv_data stm32h7xx_drv_data = {
104	.exti_banks = stm32h7xx_exti_banks,
105	.bank_nr = ARRAY_SIZE(stm32h7xx_exti_banks),
106};
107
108static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
109{
110	struct stm32_exti_chip_data *chip_data = gc->private;
111	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
112
113	return irq_reg_readl(gc, stm32_bank->rpr_ofst);
114}
115
116static void stm32_irq_handler(struct irq_desc *desc)
117{
118	struct irq_domain *domain = irq_desc_get_handler_data(desc);
119	struct irq_chip *chip = irq_desc_get_chip(desc);
120	unsigned int nbanks = domain->gc->num_chips;
121	struct irq_chip_generic *gc;
122	unsigned long pending;
123	int n, i, irq_base = 0;
124
125	chained_irq_enter(chip, desc);
126
127	for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
128		gc = irq_get_domain_generic_chip(domain, irq_base);
129
130		while ((pending = stm32_exti_pending(gc))) {
131			for_each_set_bit(n, &pending, IRQS_PER_BANK)
132				generic_handle_domain_irq(domain, irq_base + n);
133		}
134	}
135
136	chained_irq_exit(chip, desc);
137}
138
139static int stm32_exti_set_type(struct irq_data *d,
140			       unsigned int type, u32 *rtsr, u32 *ftsr)
141{
142	u32 mask = BIT(d->hwirq % IRQS_PER_BANK);
143
144	switch (type) {
145	case IRQ_TYPE_EDGE_RISING:
146		*rtsr |= mask;
147		*ftsr &= ~mask;
148		break;
149	case IRQ_TYPE_EDGE_FALLING:
150		*rtsr &= ~mask;
151		*ftsr |= mask;
152		break;
153	case IRQ_TYPE_EDGE_BOTH:
154		*rtsr |= mask;
155		*ftsr |= mask;
156		break;
157	default:
158		return -EINVAL;
159	}
160
161	return 0;
162}
163
164static int stm32_irq_set_type(struct irq_data *d, unsigned int type)
165{
166	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
167	struct stm32_exti_chip_data *chip_data = gc->private;
168	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
169	u32 rtsr, ftsr;
170	int err;
171
172	guard(raw_spinlock)(&gc->lock);
173
174	rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
175	ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
176
177	err = stm32_exti_set_type(d, type, &rtsr, &ftsr);
178	if (err)
179		return err;
180
181	irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
182	irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
183	return 0;
184}
185
186static void stm32_chip_suspend(struct stm32_exti_chip_data *chip_data,
187			       u32 wake_active)
188{
189	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
190	void __iomem *base = chip_data->host_data->base;
191
192	/* save rtsr, ftsr registers */
193	chip_data->rtsr_cache = readl_relaxed(base + stm32_bank->rtsr_ofst);
194	chip_data->ftsr_cache = readl_relaxed(base + stm32_bank->ftsr_ofst);
195
196	writel_relaxed(wake_active, base + stm32_bank->imr_ofst);
197}
198
199static void stm32_chip_resume(struct stm32_exti_chip_data *chip_data,
200			      u32 mask_cache)
201{
202	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
203	void __iomem *base = chip_data->host_data->base;
204
205	/* restore rtsr, ftsr, registers */
206	writel_relaxed(chip_data->rtsr_cache, base + stm32_bank->rtsr_ofst);
207	writel_relaxed(chip_data->ftsr_cache, base + stm32_bank->ftsr_ofst);
208
209	writel_relaxed(mask_cache, base + stm32_bank->imr_ofst);
210}
211
212static void stm32_irq_suspend(struct irq_chip_generic *gc)
213{
214	struct stm32_exti_chip_data *chip_data = gc->private;
215
216	guard(raw_spinlock)(&gc->lock);
217	stm32_chip_suspend(chip_data, gc->wake_active);
218}
219
220static void stm32_irq_resume(struct irq_chip_generic *gc)
221{
222	struct stm32_exti_chip_data *chip_data = gc->private;
223
224	guard(raw_spinlock)(&gc->lock);
225	stm32_chip_resume(chip_data, gc->mask_cache);
226}
227
228static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
229			    unsigned int nr_irqs, void *data)
230{
231	struct irq_fwspec *fwspec = data;
232	irq_hw_number_t hwirq;
233
234	hwirq = fwspec->param[0];
235
236	irq_map_generic_chip(d, virq, hwirq);
237
238	return 0;
239}
240
241static void stm32_exti_free(struct irq_domain *d, unsigned int virq,
242			    unsigned int nr_irqs)
243{
244	struct irq_data *data = irq_domain_get_irq_data(d, virq);
245
246	irq_domain_reset_irq_data(data);
247}
248
249static const struct irq_domain_ops irq_exti_domain_ops = {
250	.map	= irq_map_generic_chip,
251	.alloc  = stm32_exti_alloc,
252	.free	= stm32_exti_free,
253	.xlate	= irq_domain_xlate_twocell,
254};
255
256static void stm32_irq_ack(struct irq_data *d)
257{
258	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
259	struct stm32_exti_chip_data *chip_data = gc->private;
260	const struct stm32_exti_bank *stm32_bank = chip_data->reg_bank;
261
262	guard(raw_spinlock)(&gc->lock);
263	irq_reg_writel(gc, d->mask, stm32_bank->rpr_ofst);
264}
265
266static struct
267stm32_exti_host_data *stm32_exti_host_init(const struct stm32_exti_drv_data *dd,
268					   struct device_node *node)
269{
270	struct stm32_exti_host_data *host_data;
271
272	host_data = kzalloc(sizeof(*host_data), GFP_KERNEL);
273	if (!host_data)
274		return NULL;
275
276	host_data->drv_data = dd;
277	host_data->chips_data = kcalloc(dd->bank_nr,
278					sizeof(struct stm32_exti_chip_data),
279					GFP_KERNEL);
280	if (!host_data->chips_data)
281		goto free_host_data;
282
283	host_data->base = of_iomap(node, 0);
284	if (!host_data->base) {
285		pr_err("%pOF: Unable to map registers\n", node);
286		goto free_chips_data;
287	}
288
289	return host_data;
290
291free_chips_data:
292	kfree(host_data->chips_data);
293free_host_data:
294	kfree(host_data);
295
296	return NULL;
297}
298
299static struct
300stm32_exti_chip_data *stm32_exti_chip_init(struct stm32_exti_host_data *h_data,
301					   u32 bank_idx,
302					   struct device_node *node)
303{
304	const struct stm32_exti_bank *stm32_bank;
305	struct stm32_exti_chip_data *chip_data;
306	void __iomem *base = h_data->base;
307
308	stm32_bank = h_data->drv_data->exti_banks[bank_idx];
309	chip_data = &h_data->chips_data[bank_idx];
310	chip_data->host_data = h_data;
311	chip_data->reg_bank = stm32_bank;
312
313	/*
314	 * This IP has no reset, so after hot reboot we should
315	 * clear registers to avoid residue
316	 */
317	writel_relaxed(0, base + stm32_bank->imr_ofst);
318	writel_relaxed(0, base + stm32_bank->emr_ofst);
319
320	pr_info("%pOF: bank%d\n", node, bank_idx);
321
322	return chip_data;
323}
324
325static int __init stm32_exti_init(const struct stm32_exti_drv_data *drv_data,
326				  struct device_node *node)
327{
328	struct stm32_exti_host_data *host_data;
329	unsigned int clr = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
330	int nr_irqs, ret, i;
331	struct irq_chip_generic *gc;
332	struct irq_domain *domain;
333
334	host_data = stm32_exti_host_init(drv_data, node);
335	if (!host_data)
336		return -ENOMEM;
337
338	domain = irq_domain_create_linear(of_fwnode_handle(node), drv_data->bank_nr * IRQS_PER_BANK,
339					  &irq_exti_domain_ops, NULL);
340	if (!domain) {
341		pr_err("%pOFn: Could not register interrupt domain.\n",
342		       node);
343		ret = -ENOMEM;
344		goto out_unmap;
345	}
346
347	ret = irq_alloc_domain_generic_chips(domain, IRQS_PER_BANK, 1, "exti",
348					     handle_edge_irq, clr, 0, 0);
349	if (ret) {
350		pr_err("%pOF: Could not allocate generic interrupt chip.\n",
351		       node);
352		goto out_free_domain;
353	}
354
355	for (i = 0; i < drv_data->bank_nr; i++) {
356		const struct stm32_exti_bank *stm32_bank;
357		struct stm32_exti_chip_data *chip_data;
358
359		stm32_bank = drv_data->exti_banks[i];
360		chip_data = stm32_exti_chip_init(host_data, i, node);
361
362		gc = irq_get_domain_generic_chip(domain, i * IRQS_PER_BANK);
363
364		gc->reg_base = host_data->base;
365		gc->chip_types->type = IRQ_TYPE_EDGE_BOTH;
366		gc->chip_types->chip.irq_ack = stm32_irq_ack;
367		gc->chip_types->chip.irq_mask = irq_gc_mask_clr_bit;
368		gc->chip_types->chip.irq_unmask = irq_gc_mask_set_bit;
369		gc->chip_types->chip.irq_set_type = stm32_irq_set_type;
370		gc->chip_types->chip.irq_set_wake = irq_gc_set_wake;
371		gc->suspend = stm32_irq_suspend;
372		gc->resume = stm32_irq_resume;
373		gc->wake_enabled = IRQ_MSK(IRQS_PER_BANK);
374
375		gc->chip_types->regs.mask = stm32_bank->imr_ofst;
376		gc->private = (void *)chip_data;
377	}
378
379	nr_irqs = of_irq_count(node);
380	for (i = 0; i < nr_irqs; i++) {
381		unsigned int irq = irq_of_parse_and_map(node, i);
382
383		irq_set_handler_data(irq, domain);
384		irq_set_chained_handler(irq, stm32_irq_handler);
385	}
386
387	return 0;
388
389out_free_domain:
390	irq_domain_remove(domain);
391out_unmap:
392	iounmap(host_data->base);
393	kfree(host_data->chips_data);
394	kfree(host_data);
395	return ret;
396}
397
398static int __init stm32f4_exti_of_init(struct device_node *np,
399				       struct device_node *parent)
400{
401	return stm32_exti_init(&stm32f4xx_drv_data, np);
402}
403
404IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
405
406static int __init stm32h7_exti_of_init(struct device_node *np,
407				       struct device_node *parent)
408{
409	return stm32_exti_init(&stm32h7xx_drv_data, np);
410}
411
412IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
~/ Read-only file preview.