1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * IMG PowerDown Controller (PDC) |
4 | * |
5 | * Copyright 2010-2013 Imagination Technologies Ltd. |
6 | * |
7 | * Exposes the syswake and PDC peripheral wake interrupts to the system. |
8 | * |
9 | */ |
10 | |
11 | #include <linux/bitops.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/irqdomain.h> |
14 | #include <linux/io.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/of.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/spinlock.h> |
19 | |
20 | /* PDC interrupt register numbers */ |
21 | |
22 | #define PDC_IRQ_STATUS 0x310 |
23 | #define PDC_IRQ_ENABLE 0x314 |
24 | #define PDC_IRQ_CLEAR 0x318 |
25 | #define PDC_IRQ_ROUTE 0x31c |
26 | #define PDC_SYS_WAKE_BASE 0x330 |
27 | #define PDC_SYS_WAKE_STRIDE 0x8 |
28 | #define PDC_SYS_WAKE_CONFIG_BASE 0x334 |
29 | #define PDC_SYS_WAKE_CONFIG_STRIDE 0x8 |
30 | |
31 | /* PDC interrupt register field masks */ |
32 | |
33 | #define PDC_IRQ_SYS3 0x08 |
34 | #define PDC_IRQ_SYS2 0x04 |
35 | #define PDC_IRQ_SYS1 0x02 |
36 | #define PDC_IRQ_SYS0 0x01 |
37 | #define PDC_IRQ_ROUTE_WU_EN_SYS3 0x08000000 |
38 | #define PDC_IRQ_ROUTE_WU_EN_SYS2 0x04000000 |
39 | #define PDC_IRQ_ROUTE_WU_EN_SYS1 0x02000000 |
40 | #define PDC_IRQ_ROUTE_WU_EN_SYS0 0x01000000 |
41 | #define PDC_IRQ_ROUTE_WU_EN_WD 0x00040000 |
42 | #define PDC_IRQ_ROUTE_WU_EN_IR 0x00020000 |
43 | #define PDC_IRQ_ROUTE_WU_EN_RTC 0x00010000 |
44 | #define PDC_IRQ_ROUTE_EXT_EN_SYS3 0x00000800 |
45 | #define PDC_IRQ_ROUTE_EXT_EN_SYS2 0x00000400 |
46 | #define PDC_IRQ_ROUTE_EXT_EN_SYS1 0x00000200 |
47 | #define PDC_IRQ_ROUTE_EXT_EN_SYS0 0x00000100 |
48 | #define PDC_IRQ_ROUTE_EXT_EN_WD 0x00000004 |
49 | #define PDC_IRQ_ROUTE_EXT_EN_IR 0x00000002 |
50 | #define PDC_IRQ_ROUTE_EXT_EN_RTC 0x00000001 |
51 | #define PDC_SYS_WAKE_RESET 0x00000010 |
52 | #define PDC_SYS_WAKE_INT_MODE 0x0000000e |
53 | #define PDC_SYS_WAKE_INT_MODE_SHIFT 1 |
54 | #define PDC_SYS_WAKE_PIN_VAL 0x00000001 |
55 | |
56 | /* PDC interrupt constants */ |
57 | |
58 | #define PDC_SYS_WAKE_INT_LOW 0x0 |
59 | #define PDC_SYS_WAKE_INT_HIGH 0x1 |
60 | #define PDC_SYS_WAKE_INT_DOWN 0x2 |
61 | #define PDC_SYS_WAKE_INT_UP 0x3 |
62 | #define PDC_SYS_WAKE_INT_CHANGE 0x6 |
63 | #define PDC_SYS_WAKE_INT_NONE 0x4 |
64 | |
65 | /** |
66 | * struct pdc_intc_priv - private pdc interrupt data. |
67 | * @nr_perips: Number of peripheral interrupt signals. |
68 | * @nr_syswakes: Number of syswake signals. |
69 | * @perip_irqs: List of peripheral IRQ numbers handled. |
70 | * @syswake_irq: Shared PDC syswake IRQ number. |
71 | * @domain: IRQ domain for PDC peripheral and syswake IRQs. |
72 | * @pdc_base: Base of PDC registers. |
73 | * @irq_route: Cached version of PDC_IRQ_ROUTE register. |
74 | * @lock: Lock to protect the PDC syswake registers and the cached |
75 | * values of those registers in this struct. |
76 | */ |
77 | struct pdc_intc_priv { |
78 | unsigned int nr_perips; |
79 | unsigned int nr_syswakes; |
80 | unsigned int *perip_irqs; |
81 | unsigned int syswake_irq; |
82 | struct irq_domain *domain; |
83 | void __iomem *pdc_base; |
84 | |
85 | u32 irq_route; |
86 | raw_spinlock_t lock; |
87 | }; |
88 | |
89 | static void pdc_write(struct pdc_intc_priv *priv, unsigned int reg_offs, |
90 | unsigned int data) |
91 | { |
92 | iowrite32(data, priv->pdc_base + reg_offs); |
93 | } |
94 | |
95 | static unsigned int pdc_read(struct pdc_intc_priv *priv, |
96 | unsigned int reg_offs) |
97 | { |
98 | return ioread32(priv->pdc_base + reg_offs); |
99 | } |
100 | |
101 | /* Generic IRQ callbacks */ |
102 | |
103 | #define SYS0_HWIRQ 8 |
104 | |
105 | static unsigned int hwirq_is_syswake(irq_hw_number_t hw) |
106 | { |
107 | return hw >= SYS0_HWIRQ; |
108 | } |
109 | |
110 | static unsigned int hwirq_to_syswake(irq_hw_number_t hw) |
111 | { |
112 | return hw - SYS0_HWIRQ; |
113 | } |
114 | |
115 | static irq_hw_number_t syswake_to_hwirq(unsigned int syswake) |
116 | { |
117 | return SYS0_HWIRQ + syswake; |
118 | } |
119 | |
120 | static struct pdc_intc_priv *irqd_to_priv(struct irq_data *data) |
121 | { |
122 | return (struct pdc_intc_priv *)data->domain->host_data; |
123 | } |
124 | |
125 | /* |
126 | * perip_irq_mask() and perip_irq_unmask() use IRQ_ROUTE which also contains |
127 | * wake bits, therefore we cannot use the generic irqchip mask callbacks as they |
128 | * cache the mask. |
129 | */ |
130 | |
131 | static void perip_irq_mask(struct irq_data *data) |
132 | { |
133 | struct pdc_intc_priv *priv = irqd_to_priv(data); |
134 | |
135 | raw_spin_lock(&priv->lock); |
136 | priv->irq_route &= ~data->mask; |
137 | pdc_write(priv, PDC_IRQ_ROUTE, data: priv->irq_route); |
138 | raw_spin_unlock(&priv->lock); |
139 | } |
140 | |
141 | static void perip_irq_unmask(struct irq_data *data) |
142 | { |
143 | struct pdc_intc_priv *priv = irqd_to_priv(data); |
144 | |
145 | raw_spin_lock(&priv->lock); |
146 | priv->irq_route |= data->mask; |
147 | pdc_write(priv, PDC_IRQ_ROUTE, data: priv->irq_route); |
148 | raw_spin_unlock(&priv->lock); |
149 | } |
150 | |
151 | static int syswake_irq_set_type(struct irq_data *data, unsigned int flow_type) |
152 | { |
153 | struct pdc_intc_priv *priv = irqd_to_priv(data); |
154 | unsigned int syswake = hwirq_to_syswake(hw: data->hwirq); |
155 | unsigned int irq_mode; |
156 | unsigned int soc_sys_wake_regoff, soc_sys_wake; |
157 | |
158 | /* translate to syswake IRQ mode */ |
159 | switch (flow_type) { |
160 | case IRQ_TYPE_EDGE_BOTH: |
161 | irq_mode = PDC_SYS_WAKE_INT_CHANGE; |
162 | break; |
163 | case IRQ_TYPE_EDGE_RISING: |
164 | irq_mode = PDC_SYS_WAKE_INT_UP; |
165 | break; |
166 | case IRQ_TYPE_EDGE_FALLING: |
167 | irq_mode = PDC_SYS_WAKE_INT_DOWN; |
168 | break; |
169 | case IRQ_TYPE_LEVEL_HIGH: |
170 | irq_mode = PDC_SYS_WAKE_INT_HIGH; |
171 | break; |
172 | case IRQ_TYPE_LEVEL_LOW: |
173 | irq_mode = PDC_SYS_WAKE_INT_LOW; |
174 | break; |
175 | default: |
176 | return -EINVAL; |
177 | } |
178 | |
179 | raw_spin_lock(&priv->lock); |
180 | |
181 | /* set the IRQ mode */ |
182 | soc_sys_wake_regoff = PDC_SYS_WAKE_BASE + syswake*PDC_SYS_WAKE_STRIDE; |
183 | soc_sys_wake = pdc_read(priv, reg_offs: soc_sys_wake_regoff); |
184 | soc_sys_wake &= ~PDC_SYS_WAKE_INT_MODE; |
185 | soc_sys_wake |= irq_mode << PDC_SYS_WAKE_INT_MODE_SHIFT; |
186 | pdc_write(priv, reg_offs: soc_sys_wake_regoff, data: soc_sys_wake); |
187 | |
188 | /* and update the handler */ |
189 | irq_setup_alt_chip(data, flow_type); |
190 | |
191 | raw_spin_unlock(&priv->lock); |
192 | |
193 | return 0; |
194 | } |
195 | |
196 | /* applies to both peripheral and syswake interrupts */ |
197 | static int pdc_irq_set_wake(struct irq_data *data, unsigned int on) |
198 | { |
199 | struct pdc_intc_priv *priv = irqd_to_priv(data); |
200 | irq_hw_number_t hw = data->hwirq; |
201 | unsigned int mask = (1 << 16) << hw; |
202 | unsigned int dst_irq; |
203 | |
204 | raw_spin_lock(&priv->lock); |
205 | if (on) |
206 | priv->irq_route |= mask; |
207 | else |
208 | priv->irq_route &= ~mask; |
209 | pdc_write(priv, PDC_IRQ_ROUTE, data: priv->irq_route); |
210 | raw_spin_unlock(&priv->lock); |
211 | |
212 | /* control the destination IRQ wakeup too for standby mode */ |
213 | if (hwirq_is_syswake(hw)) |
214 | dst_irq = priv->syswake_irq; |
215 | else |
216 | dst_irq = priv->perip_irqs[hw]; |
217 | irq_set_irq_wake(irq: dst_irq, on); |
218 | |
219 | return 0; |
220 | } |
221 | |
222 | static void pdc_intc_perip_isr(struct irq_desc *desc) |
223 | { |
224 | unsigned int irq = irq_desc_get_irq(desc); |
225 | struct pdc_intc_priv *priv; |
226 | unsigned int i; |
227 | |
228 | priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc); |
229 | |
230 | /* find the peripheral number */ |
231 | for (i = 0; i < priv->nr_perips; ++i) |
232 | if (irq == priv->perip_irqs[i]) |
233 | goto found; |
234 | |
235 | /* should never get here */ |
236 | return; |
237 | found: |
238 | |
239 | /* pass on the interrupt */ |
240 | generic_handle_domain_irq(priv->domain, i); |
241 | } |
242 | |
243 | static void pdc_intc_syswake_isr(struct irq_desc *desc) |
244 | { |
245 | struct pdc_intc_priv *priv; |
246 | unsigned int syswake; |
247 | unsigned int status; |
248 | |
249 | priv = (struct pdc_intc_priv *)irq_desc_get_handler_data(desc); |
250 | |
251 | status = pdc_read(priv, PDC_IRQ_STATUS) & |
252 | pdc_read(priv, PDC_IRQ_ENABLE); |
253 | status &= (1 << priv->nr_syswakes) - 1; |
254 | |
255 | for (syswake = 0; status; status >>= 1, ++syswake) { |
256 | /* Has this sys_wake triggered? */ |
257 | if (!(status & 1)) |
258 | continue; |
259 | |
260 | generic_handle_domain_irq(priv->domain, syswake_to_hwirq(syswake)); |
261 | } |
262 | } |
263 | |
264 | static void pdc_intc_setup(struct pdc_intc_priv *priv) |
265 | { |
266 | int i; |
267 | unsigned int soc_sys_wake_regoff; |
268 | unsigned int soc_sys_wake; |
269 | |
270 | /* |
271 | * Mask all syswake interrupts before routing, or we could receive an |
272 | * interrupt before we're ready to handle it. |
273 | */ |
274 | pdc_write(priv, PDC_IRQ_ENABLE, data: 0); |
275 | |
276 | /* |
277 | * Enable routing of all syswakes |
278 | * Disable all wake sources |
279 | */ |
280 | priv->irq_route = ((PDC_IRQ_ROUTE_EXT_EN_SYS0 << priv->nr_syswakes) - |
281 | PDC_IRQ_ROUTE_EXT_EN_SYS0); |
282 | pdc_write(priv, PDC_IRQ_ROUTE, data: priv->irq_route); |
283 | |
284 | /* Initialise syswake IRQ */ |
285 | for (i = 0; i < priv->nr_syswakes; ++i) { |
286 | /* set the IRQ mode to none */ |
287 | soc_sys_wake_regoff = PDC_SYS_WAKE_BASE + i*PDC_SYS_WAKE_STRIDE; |
288 | soc_sys_wake = PDC_SYS_WAKE_INT_NONE |
289 | << PDC_SYS_WAKE_INT_MODE_SHIFT; |
290 | pdc_write(priv, reg_offs: soc_sys_wake_regoff, data: soc_sys_wake); |
291 | } |
292 | } |
293 | |
294 | static int pdc_intc_probe(struct platform_device *pdev) |
295 | { |
296 | struct pdc_intc_priv *priv; |
297 | struct device_node *node = pdev->dev.of_node; |
298 | struct resource *res_regs; |
299 | struct irq_chip_generic *gc; |
300 | unsigned int i; |
301 | int irq, ret; |
302 | u32 val; |
303 | |
304 | if (!node) |
305 | return -ENOENT; |
306 | |
307 | /* Get registers */ |
308 | res_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
309 | if (res_regs == NULL) { |
310 | dev_err(&pdev->dev, "cannot find registers resource\n" ); |
311 | return -ENOENT; |
312 | } |
313 | |
314 | /* Allocate driver data */ |
315 | priv = devm_kzalloc(dev: &pdev->dev, size: sizeof(*priv), GFP_KERNEL); |
316 | if (!priv) |
317 | return -ENOMEM; |
318 | raw_spin_lock_init(&priv->lock); |
319 | platform_set_drvdata(pdev, data: priv); |
320 | |
321 | /* Ioremap the registers */ |
322 | priv->pdc_base = devm_ioremap(dev: &pdev->dev, offset: res_regs->start, |
323 | size: resource_size(res: res_regs)); |
324 | if (!priv->pdc_base) |
325 | return -EIO; |
326 | |
327 | /* Get number of peripherals */ |
328 | ret = of_property_read_u32(np: node, propname: "num-perips" , out_value: &val); |
329 | if (ret) { |
330 | dev_err(&pdev->dev, "No num-perips node property found\n" ); |
331 | return -EINVAL; |
332 | } |
333 | if (val > SYS0_HWIRQ) { |
334 | dev_err(&pdev->dev, "num-perips (%u) out of range\n" , val); |
335 | return -EINVAL; |
336 | } |
337 | priv->nr_perips = val; |
338 | |
339 | /* Get number of syswakes */ |
340 | ret = of_property_read_u32(np: node, propname: "num-syswakes" , out_value: &val); |
341 | if (ret) { |
342 | dev_err(&pdev->dev, "No num-syswakes node property found\n" ); |
343 | return -EINVAL; |
344 | } |
345 | if (val > SYS0_HWIRQ) { |
346 | dev_err(&pdev->dev, "num-syswakes (%u) out of range\n" , val); |
347 | return -EINVAL; |
348 | } |
349 | priv->nr_syswakes = val; |
350 | |
351 | /* Get peripheral IRQ numbers */ |
352 | priv->perip_irqs = devm_kcalloc(dev: &pdev->dev, n: 4, size: priv->nr_perips, |
353 | GFP_KERNEL); |
354 | if (!priv->perip_irqs) |
355 | return -ENOMEM; |
356 | for (i = 0; i < priv->nr_perips; ++i) { |
357 | irq = platform_get_irq(pdev, 1 + i); |
358 | if (irq < 0) |
359 | return irq; |
360 | priv->perip_irqs[i] = irq; |
361 | } |
362 | /* check if too many were provided */ |
363 | if (platform_get_irq(pdev, 1 + i) >= 0) { |
364 | dev_err(&pdev->dev, "surplus perip IRQs detected\n" ); |
365 | return -EINVAL; |
366 | } |
367 | |
368 | /* Get syswake IRQ number */ |
369 | irq = platform_get_irq(pdev, 0); |
370 | if (irq < 0) |
371 | return irq; |
372 | priv->syswake_irq = irq; |
373 | |
374 | /* Set up an IRQ domain */ |
375 | priv->domain = irq_domain_add_linear(of_node: node, size: 16, ops: &irq_generic_chip_ops, |
376 | host_data: priv); |
377 | if (unlikely(!priv->domain)) { |
378 | dev_err(&pdev->dev, "cannot add IRQ domain\n" ); |
379 | return -ENOMEM; |
380 | } |
381 | |
382 | /* |
383 | * Set up 2 generic irq chips with 2 chip types. |
384 | * The first one for peripheral irqs (only 1 chip type used) |
385 | * The second one for syswake irqs (edge and level chip types) |
386 | */ |
387 | ret = irq_alloc_domain_generic_chips(priv->domain, 8, 2, "pdc" , |
388 | handle_level_irq, 0, 0, |
389 | IRQ_GC_INIT_NESTED_LOCK); |
390 | if (ret) |
391 | goto err_generic; |
392 | |
393 | /* peripheral interrupt chip */ |
394 | |
395 | gc = irq_get_domain_generic_chip(priv->domain, 0); |
396 | gc->unused = ~(BIT(priv->nr_perips) - 1); |
397 | gc->reg_base = priv->pdc_base; |
398 | /* |
399 | * IRQ_ROUTE contains wake bits, so we can't use the generic versions as |
400 | * they cache the mask |
401 | */ |
402 | gc->chip_types[0].regs.mask = PDC_IRQ_ROUTE; |
403 | gc->chip_types[0].chip.irq_mask = perip_irq_mask; |
404 | gc->chip_types[0].chip.irq_unmask = perip_irq_unmask; |
405 | gc->chip_types[0].chip.irq_set_wake = pdc_irq_set_wake; |
406 | |
407 | /* syswake interrupt chip */ |
408 | |
409 | gc = irq_get_domain_generic_chip(priv->domain, 8); |
410 | gc->unused = ~(BIT(priv->nr_syswakes) - 1); |
411 | gc->reg_base = priv->pdc_base; |
412 | |
413 | /* edge interrupts */ |
414 | gc->chip_types[0].type = IRQ_TYPE_EDGE_BOTH; |
415 | gc->chip_types[0].handler = handle_edge_irq; |
416 | gc->chip_types[0].regs.ack = PDC_IRQ_CLEAR; |
417 | gc->chip_types[0].regs.mask = PDC_IRQ_ENABLE; |
418 | gc->chip_types[0].chip.irq_ack = irq_gc_ack_set_bit; |
419 | gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit; |
420 | gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit; |
421 | gc->chip_types[0].chip.irq_set_type = syswake_irq_set_type; |
422 | gc->chip_types[0].chip.irq_set_wake = pdc_irq_set_wake; |
423 | /* for standby we pass on to the shared syswake IRQ */ |
424 | gc->chip_types[0].chip.flags = IRQCHIP_MASK_ON_SUSPEND; |
425 | |
426 | /* level interrupts */ |
427 | gc->chip_types[1].type = IRQ_TYPE_LEVEL_MASK; |
428 | gc->chip_types[1].handler = handle_level_irq; |
429 | gc->chip_types[1].regs.ack = PDC_IRQ_CLEAR; |
430 | gc->chip_types[1].regs.mask = PDC_IRQ_ENABLE; |
431 | gc->chip_types[1].chip.irq_ack = irq_gc_ack_set_bit; |
432 | gc->chip_types[1].chip.irq_mask = irq_gc_mask_clr_bit; |
433 | gc->chip_types[1].chip.irq_unmask = irq_gc_mask_set_bit; |
434 | gc->chip_types[1].chip.irq_set_type = syswake_irq_set_type; |
435 | gc->chip_types[1].chip.irq_set_wake = pdc_irq_set_wake; |
436 | /* for standby we pass on to the shared syswake IRQ */ |
437 | gc->chip_types[1].chip.flags = IRQCHIP_MASK_ON_SUSPEND; |
438 | |
439 | /* Set up the hardware to enable interrupt routing */ |
440 | pdc_intc_setup(priv); |
441 | |
442 | /* Setup chained handlers for the peripheral IRQs */ |
443 | for (i = 0; i < priv->nr_perips; ++i) { |
444 | irq = priv->perip_irqs[i]; |
445 | irq_set_chained_handler_and_data(irq, pdc_intc_perip_isr, |
446 | priv); |
447 | } |
448 | |
449 | /* Setup chained handler for the syswake IRQ */ |
450 | irq_set_chained_handler_and_data(priv->syswake_irq, |
451 | pdc_intc_syswake_isr, priv); |
452 | |
453 | dev_info(&pdev->dev, |
454 | "PDC IRQ controller initialised (%u perip IRQs, %u syswake IRQs)\n" , |
455 | priv->nr_perips, |
456 | priv->nr_syswakes); |
457 | |
458 | return 0; |
459 | err_generic: |
460 | irq_domain_remove(host: priv->domain); |
461 | return ret; |
462 | } |
463 | |
464 | static int pdc_intc_remove(struct platform_device *pdev) |
465 | { |
466 | struct pdc_intc_priv *priv = platform_get_drvdata(pdev); |
467 | |
468 | irq_domain_remove(host: priv->domain); |
469 | return 0; |
470 | } |
471 | |
472 | static const struct of_device_id pdc_intc_match[] = { |
473 | { .compatible = "img,pdc-intc" }, |
474 | {} |
475 | }; |
476 | |
477 | static struct platform_driver pdc_intc_driver = { |
478 | .driver = { |
479 | .name = "pdc-intc" , |
480 | .of_match_table = pdc_intc_match, |
481 | }, |
482 | .probe = pdc_intc_probe, |
483 | .remove = pdc_intc_remove, |
484 | }; |
485 | |
486 | static int __init pdc_intc_init(void) |
487 | { |
488 | return platform_driver_register(&pdc_intc_driver); |
489 | } |
490 | core_initcall(pdc_intc_init); |
491 | |