Lines Matching +full:irqc +full:- +full:rzg2l
1 // SPDX-License-Identifier: GPL-2.0
3 * Renesas RZ/G2L IRQC Driver
7 * Author: Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
60 * struct rzg2l_irqc_reg_cache - registers cache (necessary for suspend/resume)
70 * struct rzg2l_irqc_priv - IRQ controller private data structure
85 return data->domain->host_data; in irq_data_to_priv()
90 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START; in rzg2l_irq_eoi()
95 iscr = readl_relaxed(priv->base + ISCR); in rzg2l_irq_eoi()
96 iitsr = readl_relaxed(priv->base + IITSR); in rzg2l_irq_eoi()
99 * ISCR can only be cleared if the type is falling-edge, rising-edge or in rzg2l_irq_eoi()
100 * falling/rising-edge. in rzg2l_irq_eoi()
103 writel_relaxed(iscr & ~bit, priv->base + ISCR); in rzg2l_irq_eoi()
108 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_TINT_START; in rzg2l_tint_eoi()
113 reg = readl_relaxed(priv->base + TSCR); in rzg2l_tint_eoi()
115 writel_relaxed(reg & ~bit, priv->base + TSCR); in rzg2l_tint_eoi()
123 raw_spin_lock(&priv->lock); in rzg2l_irqc_eoi()
128 raw_spin_unlock(&priv->lock); in rzg2l_irqc_eoi()
138 u32 offset = hw_irq - IRQC_TINT_START; in rzg2l_irqc_irq_disable()
143 raw_spin_lock(&priv->lock); in rzg2l_irqc_irq_disable()
144 reg = readl_relaxed(priv->base + TSSR(tssr_index)); in rzg2l_irqc_irq_disable()
146 writel_relaxed(reg, priv->base + TSSR(tssr_index)); in rzg2l_irqc_irq_disable()
147 raw_spin_unlock(&priv->lock); in rzg2l_irqc_irq_disable()
159 u32 offset = hw_irq - IRQC_TINT_START; in rzg2l_irqc_irq_enable()
164 raw_spin_lock(&priv->lock); in rzg2l_irqc_irq_enable()
165 reg = readl_relaxed(priv->base + TSSR(tssr_index)); in rzg2l_irqc_irq_enable()
167 writel_relaxed(reg, priv->base + TSSR(tssr_index)); in rzg2l_irqc_irq_enable()
168 raw_spin_unlock(&priv->lock); in rzg2l_irqc_irq_enable()
175 unsigned int hw_irq = irqd_to_hwirq(d) - IRQC_IRQ_START; in rzg2l_irq_set_type()
197 return -EINVAL; in rzg2l_irq_set_type()
200 raw_spin_lock(&priv->lock); in rzg2l_irq_set_type()
201 tmp = readl_relaxed(priv->base + IITSR); in rzg2l_irq_set_type()
204 writel_relaxed(tmp, priv->base + IITSR); in rzg2l_irq_set_type()
205 raw_spin_unlock(&priv->lock); in rzg2l_irq_set_type()
214 u32 titseln = hwirq - IRQC_TINT_START; in rzg2l_tint_set_edge()
228 return -EINVAL; in rzg2l_tint_set_edge()
233 titseln -= TITSR0_MAX_INT; in rzg2l_tint_set_edge()
237 raw_spin_lock(&priv->lock); in rzg2l_tint_set_edge()
238 reg = readl_relaxed(priv->base + TITSR(index)); in rzg2l_tint_set_edge()
241 writel_relaxed(reg, priv->base + TITSR(index)); in rzg2l_tint_set_edge()
242 raw_spin_unlock(&priv->lock); in rzg2l_tint_set_edge()
250 int ret = -EINVAL; in rzg2l_irqc_set_type()
264 struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache; in rzg2l_irqc_irq_suspend()
265 void __iomem *base = rzg2l_irqc_data->base; in rzg2l_irqc_irq_suspend()
267 cache->iitsr = readl_relaxed(base + IITSR); in rzg2l_irqc_irq_suspend()
269 cache->titsr[i] = readl_relaxed(base + TITSR(i)); in rzg2l_irqc_irq_suspend()
276 struct rzg2l_irqc_reg_cache *cache = &rzg2l_irqc_data->cache; in rzg2l_irqc_irq_resume()
277 void __iomem *base = rzg2l_irqc_data->base; in rzg2l_irqc_irq_resume()
285 writel_relaxed(cache->titsr[i], base + TITSR(i)); in rzg2l_irqc_irq_resume()
286 writel_relaxed(cache->iitsr, base + IITSR); in rzg2l_irqc_irq_resume()
295 .name = "rzg2l-irqc",
314 struct rzg2l_irqc_priv *priv = domain->host_data; in rzg2l_irqc_alloc()
325 * For TINT interrupts ie where pinctrl driver is child of irqc domain in rzg2l_irqc_alloc()
326 * the hwirq and TINT are encoded in fwspec->param[0]. in rzg2l_irqc_alloc()
327 * hwirq for TINT range from 9-40, hwirq is embedded 0-15 bits and TINT in rzg2l_irqc_alloc()
328 * from 16-31 bits. TINT from the pinctrl driver needs to be programmed in rzg2l_irqc_alloc()
329 * in IRQC registers to enable a given gpio pin as interrupt. in rzg2l_irqc_alloc()
336 return -EINVAL; in rzg2l_irqc_alloc()
339 if (hwirq > (IRQC_NUM_IRQ - 1)) in rzg2l_irqc_alloc()
340 return -EINVAL; in rzg2l_irqc_alloc()
347 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]); in rzg2l_irqc_alloc()
368 &priv->fwspec[i]); in rzg2l_irqc_parse_interrupts()
383 return -ENODEV; in rzg2l_irqc_init()
387 dev_err(&pdev->dev, "cannot find parent domain\n"); in rzg2l_irqc_init()
388 return -ENODEV; in rzg2l_irqc_init()
391 rzg2l_irqc_data = devm_kzalloc(&pdev->dev, sizeof(*rzg2l_irqc_data), GFP_KERNEL); in rzg2l_irqc_init()
393 return -ENOMEM; in rzg2l_irqc_init()
395 rzg2l_irqc_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL); in rzg2l_irqc_init()
396 if (IS_ERR(rzg2l_irqc_data->base)) in rzg2l_irqc_init()
397 return PTR_ERR(rzg2l_irqc_data->base); in rzg2l_irqc_init()
401 dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret); in rzg2l_irqc_init()
405 resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL); in rzg2l_irqc_init()
411 dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret); in rzg2l_irqc_init()
415 pm_runtime_enable(&pdev->dev); in rzg2l_irqc_init()
416 ret = pm_runtime_resume_and_get(&pdev->dev); in rzg2l_irqc_init()
418 dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret); in rzg2l_irqc_init()
422 raw_spin_lock_init(&rzg2l_irqc_data->lock); in rzg2l_irqc_init()
428 dev_err(&pdev->dev, "failed to add irq domain\n"); in rzg2l_irqc_init()
429 ret = -ENOMEM; in rzg2l_irqc_init()
438 pm_runtime_put(&pdev->dev); in rzg2l_irqc_init()
440 pm_runtime_disable(&pdev->dev); in rzg2l_irqc_init()
446 IRQCHIP_MATCH("renesas,rzg2l-irqc", rzg2l_irqc_init)
448 MODULE_AUTHOR("Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>");
449 MODULE_DESCRIPTION("Renesas RZ/G2L IRQC Driver");