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_eoi()
53 val = readl_relaxed(data->base + EIMASK) | BIT(d->hwirq); in exiu_irq_mask()
54 writel_relaxed(val, data->base + EIMASK); in exiu_irq_mask()
63 val = readl_relaxed(data->base + EIMASK) & ~BIT(d->hwirq); in exiu_irq_unmask()
64 writel_relaxed(val, data->base + EIMASK); in exiu_irq_unmask()
74 writel_relaxed(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_enable()
76 val = readl_relaxed(data->base + EIMASK) & ~BIT(d->hwirq); in exiu_irq_enable()
77 writel_relaxed(val, data->base + EIMASK); in exiu_irq_enable()
86 val = readl_relaxed(data->base + EILVL); in exiu_irq_set_type()
88 val |= BIT(d->hwirq); in exiu_irq_set_type()
90 val &= ~BIT(d->hwirq); in exiu_irq_set_type()
91 writel_relaxed(val, data->base + EILVL); in exiu_irq_set_type()
93 val = readl_relaxed(data->base + EIEDG); in exiu_irq_set_type()
95 val &= ~BIT(d->hwirq); in exiu_irq_set_type()
97 val |= BIT(d->hwirq); in exiu_irq_set_type()
98 writel_relaxed(val, data->base + EIEDG); in exiu_irq_set_type()
100 writel_relaxed(BIT(d->hwirq), data->base + EIREQCLR); in exiu_irq_set_type()
124 struct exiu_irq_data *info = domain->host_data; in exiu_domain_translate()
126 if (is_of_node(fwspec->fwnode)) { in exiu_domain_translate()
127 if (fwspec->param_count != 3) in exiu_domain_translate()
128 return -EINVAL; in exiu_domain_translate()
130 if (fwspec->param[0] != GIC_SPI) in exiu_domain_translate()
131 return -EINVAL; /* No PPI should point to this domain */ in exiu_domain_translate()
133 *hwirq = fwspec->param[1] - info->spi_base; in exiu_domain_translate()
134 *type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK; in exiu_domain_translate()
136 if (fwspec->param_count != 2) in exiu_domain_translate()
137 return -EINVAL; in exiu_domain_translate()
138 *hwirq = fwspec->param[0]; in exiu_domain_translate()
139 *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; in exiu_domain_translate()
149 struct exiu_irq_data *info = dom->host_data; in exiu_domain_alloc()
153 if (is_of_node(dom->parent->fwnode)) { in exiu_domain_alloc()
154 if (fwspec->param_count != 3) in exiu_domain_alloc()
155 return -EINVAL; /* Not GIC compliant */ in exiu_domain_alloc()
156 if (fwspec->param[0] != GIC_SPI) in exiu_domain_alloc()
157 return -EINVAL; /* No PPI should point to this domain */ in exiu_domain_alloc()
159 hwirq = fwspec->param[1] - info->spi_base; in exiu_domain_alloc()
161 hwirq = fwspec->param[0]; in exiu_domain_alloc()
162 parent_fwspec.param[0] = hwirq + info->spi_base + 32; in exiu_domain_alloc()
167 parent_fwspec.fwnode = dom->parent->fwnode; in exiu_domain_alloc()
185 return ERR_PTR(-ENOMEM); in exiu_init()
187 if (fwnode_property_read_u32_array(fwnode, "socionext,spi-base", in exiu_init()
188 &data->spi_base, 1)) { in exiu_init()
189 err = -ENODEV; in exiu_init()
193 data->base = ioremap(res->start, resource_size(res)); in exiu_init()
194 if (!data->base) { in exiu_init()
195 err = -ENODEV; in exiu_init()
200 writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR); in exiu_init()
201 writel_relaxed(0xFFFFFFFF, data->base + EIMASK); in exiu_init()
211 struct device_node *parent) in exiu_dt_init() argument
217 if (!parent) { in exiu_dt_init()
218 pr_err("%pOF: no parent, giving up\n", node); in exiu_dt_init()
219 return -ENODEV; in exiu_dt_init()
222 parent_domain = irq_find_host(parent); in exiu_dt_init()
224 pr_err("%pOF: unable to obtain parent domain\n", node); in exiu_dt_init()
225 return -ENXIO; in exiu_dt_init()
230 return -ENXIO; in exiu_dt_init()
245 parent); in exiu_dt_init()
250 iounmap(data->base); in exiu_dt_init()
252 return -ENOMEM; in exiu_dt_init()
254 IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init);
265 dev_err(&pdev->dev, "failed to parse memory resource\n"); in exiu_acpi_probe()
266 return -ENXIO; in exiu_acpi_probe()
269 data = exiu_init(dev_fwnode(&pdev->dev), res); in exiu_acpi_probe()
273 domain = acpi_irq_create_hierarchy(0, NUM_IRQS, dev_fwnode(&pdev->dev), in exiu_acpi_probe()
276 dev_err(&pdev->dev, "failed to create IRQ domain\n"); in exiu_acpi_probe()
280 dev_info(&pdev->dev, "%d interrupts forwarded\n", NUM_IRQS); in exiu_acpi_probe()
285 iounmap(data->base); in exiu_acpi_probe()
287 return -ENOMEM; in exiu_acpi_probe()