Lines Matching +full:parent +full:- +full:interrupt +full:- +full:base
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Driver for Socionext External Interrupt Unit (EXIU)
5 * Copyright (c) 2017-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org>
7 * Based on irq-tegra.c:
12 #include <linux/interrupt.h>
22 #include <dt-bindings/interrupt-controller/arm-gic.h>
36 void __iomem *base; member
44 writel(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_ack()
53 * EOI or the interrupt will be jammed on. Of course if a level in exiu_irq_eoi()
54 * triggered interrupt is still asserted then the write will not clear in exiu_irq_eoi()
55 * the interrupt. in exiu_irq_eoi()
58 writel(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_eoi()
68 val = readl_relaxed(data->base + EIMASK) | BIT(d->hwirq); in exiu_irq_mask()
69 writel_relaxed(val, data->base + EIMASK); in exiu_irq_mask()
78 val = readl_relaxed(data->base + EIMASK) & ~BIT(d->hwirq); in exiu_irq_unmask()
79 writel_relaxed(val, data->base + EIMASK); in exiu_irq_unmask()
89 writel_relaxed(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_enable()
91 val = readl_relaxed(data->base + EIMASK) & ~BIT(d->hwirq); in exiu_irq_enable()
92 writel_relaxed(val, data->base + EIMASK); in exiu_irq_enable()
101 val = readl_relaxed(data->base + EILVL); in exiu_irq_set_type()
103 val |= BIT(d->hwirq); in exiu_irq_set_type()
105 val &= ~BIT(d->hwirq); in exiu_irq_set_type()
106 writel_relaxed(val, data->base + EILVL); in exiu_irq_set_type()
108 val = readl_relaxed(data->base + EIEDG); in exiu_irq_set_type()
110 val &= ~BIT(d->hwirq); in exiu_irq_set_type()
113 val |= BIT(d->hwirq); in exiu_irq_set_type()
116 writel_relaxed(val, data->base + EIEDG); in exiu_irq_set_type()
118 writel_relaxed(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_set_type()
143 struct exiu_irq_data *info = domain->host_data; in exiu_domain_translate()
145 if (is_of_node(fwspec->fwnode)) { in exiu_domain_translate()
146 if (fwspec->param_count != 3) in exiu_domain_translate()
147 return -EINVAL; in exiu_domain_translate()
149 if (fwspec->param[0] != GIC_SPI) in exiu_domain_translate()
150 return -EINVAL; /* No PPI should point to this domain */ in exiu_domain_translate()
152 *hwirq = fwspec->param[1] - info->spi_base; in exiu_domain_translate()
153 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in exiu_domain_translate()
155 if (fwspec->param_count != 2) in exiu_domain_translate()
156 return -EINVAL; in exiu_domain_translate()
157 *hwirq = fwspec->param[0]; in exiu_domain_translate()
158 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; in exiu_domain_translate()
168 struct exiu_irq_data *info = dom->host_data; in exiu_domain_alloc()
172 if (is_of_node(dom->parent->fwnode)) { in exiu_domain_alloc()
173 if (fwspec->param_count != 3) in exiu_domain_alloc()
174 return -EINVAL; /* Not GIC compliant */ in exiu_domain_alloc()
175 if (fwspec->param[0] != GIC_SPI) in exiu_domain_alloc()
176 return -EINVAL; /* No PPI should point to this domain */ in exiu_domain_alloc()
178 hwirq = fwspec->param[1] - info->spi_base; in exiu_domain_alloc()
180 hwirq = fwspec->param[0]; in exiu_domain_alloc()
181 parent_fwspec.param[0] = hwirq + info->spi_base + 32; in exiu_domain_alloc()
186 parent_fwspec.fwnode = dom->parent->fwnode; in exiu_domain_alloc()
204 return ERR_PTR(-ENOMEM); in exiu_init()
206 if (fwnode_property_read_u32_array(fwnode, "socionext,spi-base", in exiu_init()
207 &data->spi_base, 1)) { in exiu_init()
208 err = -ENODEV; in exiu_init()
212 data->base = ioremap(res->start, resource_size(res)); in exiu_init()
213 if (!data->base) { in exiu_init()
214 err = -ENODEV; in exiu_init()
219 writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR); in exiu_init()
220 writel_relaxed(0xFFFFFFFF, data->base + EIMASK); in exiu_init()
230 struct device_node *parent) in exiu_dt_init() argument
236 if (!parent) { in exiu_dt_init()
237 pr_err("%pOF: no parent, giving up\n", node); in exiu_dt_init()
238 return -ENODEV; in exiu_dt_init()
241 parent_domain = irq_find_host(parent); in exiu_dt_init()
243 pr_err("%pOF: unable to obtain parent domain\n", node); in exiu_dt_init()
244 return -ENXIO; in exiu_dt_init()
249 return -ENXIO; in exiu_dt_init()
264 parent); in exiu_dt_init()
269 iounmap(data->base); in exiu_dt_init()
271 return -ENOMEM; in exiu_dt_init()
273 IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
284 dev_err(&pdev->dev, "failed to parse memory resource\n"); in exiu_acpi_probe()
285 return -ENXIO; in exiu_acpi_probe()
288 data = exiu_init(dev_fwnode(&pdev->dev), res); in exiu_acpi_probe()
292 domain = acpi_irq_create_hierarchy(0, NUM_IRQS, dev_fwnode(&pdev->dev), in exiu_acpi_probe()
295 dev_err(&pdev->dev, "failed to create IRQ domain\n"); in exiu_acpi_probe()
299 dev_info(&pdev->dev, "%d interrupts forwarded\n", NUM_IRQS); in exiu_acpi_probe()
304 iounmap(data->base); in exiu_acpi_probe()
306 return -ENOMEM; in exiu_acpi_probe()