diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2019-05-28 09:36:45 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2019-05-28 09:55:02 -0400 |
commit | 0444638c0f0641c5239197f0c00a4293949d071e (patch) | |
tree | cbb88e43c713b2ab235c7d6d2ec81a303a7f7d88 /drivers/irqchip | |
parent | 621dc2fdcea1496ddd472c297d42e8d6642b05bc (diff) |
irqchip/exiu: Preparatory refactor for ACPI support
In preparation of adding support for EXIU controller devices described
via ACPI, split the DT init function in a DT specific and a generic part,
where the latter will be reused for ACPI support later.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'drivers/irqchip')
-rw-r--r-- | drivers/irqchip/irq-sni-exiu.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/drivers/irqchip/irq-sni-exiu.c b/drivers/irqchip/irq-sni-exiu.c index 1927b2f36ff6..fef7c2437dfb 100644 --- a/drivers/irqchip/irq-sni-exiu.c +++ b/drivers/irqchip/irq-sni-exiu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for Socionext External Interrupt Unit (EXIU) | 2 | * Driver for Socionext External Interrupt Unit (EXIU) |
3 | * | 3 | * |
4 | * Copyright (c) 2017 Linaro, Ltd. <ard.biesheuvel@linaro.org> | 4 | * Copyright (c) 2017-2019 Linaro, Ltd. <ard.biesheuvel@linaro.org> |
5 | * | 5 | * |
6 | * Based on irq-tegra.c: | 6 | * Based on irq-tegra.c: |
7 | * Copyright (C) 2011 Google, Inc. | 7 | * Copyright (C) 2011 Google, Inc. |
@@ -167,35 +167,23 @@ static const struct irq_domain_ops exiu_domain_ops = { | |||
167 | .free = irq_domain_free_irqs_common, | 167 | .free = irq_domain_free_irqs_common, |
168 | }; | 168 | }; |
169 | 169 | ||
170 | static int __init exiu_init(struct device_node *node, | 170 | static struct exiu_irq_data *exiu_init(const struct fwnode_handle *fwnode, |
171 | struct device_node *parent) | 171 | struct resource *res) |
172 | { | 172 | { |
173 | struct irq_domain *parent_domain, *domain; | ||
174 | struct exiu_irq_data *data; | 173 | struct exiu_irq_data *data; |
175 | int err; | 174 | int err; |
176 | 175 | ||
177 | if (!parent) { | ||
178 | pr_err("%pOF: no parent, giving up\n", node); | ||
179 | return -ENODEV; | ||
180 | } | ||
181 | |||
182 | parent_domain = irq_find_host(parent); | ||
183 | if (!parent_domain) { | ||
184 | pr_err("%pOF: unable to obtain parent domain\n", node); | ||
185 | return -ENXIO; | ||
186 | } | ||
187 | |||
188 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 176 | data = kzalloc(sizeof(*data), GFP_KERNEL); |
189 | if (!data) | 177 | if (!data) |
190 | return -ENOMEM; | 178 | return ERR_PTR(-ENOMEM); |
191 | 179 | ||
192 | if (of_property_read_u32(node, "socionext,spi-base", &data->spi_base)) { | 180 | if (fwnode_property_read_u32_array(fwnode, "socionext,spi-base", |
193 | pr_err("%pOF: failed to parse 'spi-base' property\n", node); | 181 | &data->spi_base, 1)) { |
194 | err = -ENODEV; | 182 | err = -ENODEV; |
195 | goto out_free; | 183 | goto out_free; |
196 | } | 184 | } |
197 | 185 | ||
198 | data->base = of_iomap(node, 0); | 186 | data->base = ioremap(res->start, resource_size(res)); |
199 | if (!data->base) { | 187 | if (!data->base) { |
200 | err = -ENODEV; | 188 | err = -ENODEV; |
201 | goto out_free; | 189 | goto out_free; |
@@ -205,11 +193,44 @@ static int __init exiu_init(struct device_node *node, | |||
205 | writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR); | 193 | writel_relaxed(0xFFFFFFFF, data->base + EIREQCLR); |
206 | writel_relaxed(0xFFFFFFFF, data->base + EIMASK); | 194 | writel_relaxed(0xFFFFFFFF, data->base + EIMASK); |
207 | 195 | ||
196 | return data; | ||
197 | |||
198 | out_free: | ||
199 | kfree(data); | ||
200 | return ERR_PTR(err); | ||
201 | } | ||
202 | |||
203 | static int __init exiu_dt_init(struct device_node *node, | ||
204 | struct device_node *parent) | ||
205 | { | ||
206 | struct irq_domain *parent_domain, *domain; | ||
207 | struct exiu_irq_data *data; | ||
208 | struct resource res; | ||
209 | |||
210 | if (!parent) { | ||
211 | pr_err("%pOF: no parent, giving up\n", node); | ||
212 | return -ENODEV; | ||
213 | } | ||
214 | |||
215 | parent_domain = irq_find_host(parent); | ||
216 | if (!parent_domain) { | ||
217 | pr_err("%pOF: unable to obtain parent domain\n", node); | ||
218 | return -ENXIO; | ||
219 | } | ||
220 | |||
221 | if (of_address_to_resource(node, 0, &res)) { | ||
222 | pr_err("%pOF: failed to parse memory resource\n", node); | ||
223 | return -ENXIO; | ||
224 | } | ||
225 | |||
226 | data = exiu_init(of_node_to_fwnode(node), &res); | ||
227 | if (IS_ERR(data)) | ||
228 | return PTR_ERR(data); | ||
229 | |||
208 | domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_IRQS, node, | 230 | domain = irq_domain_add_hierarchy(parent_domain, 0, NUM_IRQS, node, |
209 | &exiu_domain_ops, data); | 231 | &exiu_domain_ops, data); |
210 | if (!domain) { | 232 | if (!domain) { |
211 | pr_err("%pOF: failed to allocate domain\n", node); | 233 | pr_err("%pOF: failed to allocate domain\n", node); |
212 | err = -ENOMEM; | ||
213 | goto out_unmap; | 234 | goto out_unmap; |
214 | } | 235 | } |
215 | 236 | ||
@@ -220,8 +241,7 @@ static int __init exiu_init(struct device_node *node, | |||
220 | 241 | ||
221 | out_unmap: | 242 | out_unmap: |
222 | iounmap(data->base); | 243 | iounmap(data->base); |
223 | out_free: | ||
224 | kfree(data); | 244 | kfree(data); |
225 | return err; | 245 | return -ENOMEM; |
226 | } | 246 | } |
227 | IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_init); | 247 | IRQCHIP_DECLARE(exiu, "socionext,synquacer-exiu", exiu_dt_init); |