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