Lines Matching +full:msi +full:- +full:parent

1 // SPDX-License-Identifier: GPL-2.0
4 * Loongson PCH MSI support
7 #define pr_fmt(fmt) "pch-msi: " fmt
10 #include <linux/msi.h>
18 #include "irq-msi-lib.h"
19 #include "irq-loongson.h"
37 mutex_lock(&priv->msi_map_lock); in pch_msi_allocate_hwirq()
39 first = bitmap_find_free_region(priv->msi_map, priv->num_irqs, in pch_msi_allocate_hwirq()
42 mutex_unlock(&priv->msi_map_lock); in pch_msi_allocate_hwirq()
43 return -ENOSPC; in pch_msi_allocate_hwirq()
46 mutex_unlock(&priv->msi_map_lock); in pch_msi_allocate_hwirq()
48 return priv->irq_first + first; in pch_msi_allocate_hwirq()
54 int first = hwirq - priv->irq_first; in pch_msi_free_hwirq()
56 mutex_lock(&priv->msi_map_lock); in pch_msi_free_hwirq()
57 bitmap_release_region(priv->msi_map, first, get_count_order(num_req)); in pch_msi_free_hwirq()
58 mutex_unlock(&priv->msi_map_lock); in pch_msi_free_hwirq()
66 msg->address_hi = upper_32_bits(priv->doorbell); in pch_msi_compose_msi_msg()
67 msg->address_lo = lower_32_bits(priv->doorbell); in pch_msi_compose_msi_msg()
68 msg->data = data->hwirq; in pch_msi_compose_msi_msg()
72 .name = "PCH MSI",
85 fwspec.fwnode = domain->parent->fwnode; in pch_msi_parent_domain_alloc()
96 struct pch_msi_data *priv = domain->host_data; in pch_msi_middle_domain_alloc()
129 pch_msi_free_hwirq(priv, d->hwirq, nr_irqs); in pch_msi_middle_domain_free()
151 .prefix = "PCH-",
156 struct irq_domain *parent, in pch_msi_init_domains() argument
161 middle_domain = irq_domain_create_hierarchy(parent, 0, priv->num_irqs, in pch_msi_init_domains()
166 pr_err("Failed to create the MSI middle domain\n"); in pch_msi_init_domains()
167 return -ENOMEM; in pch_msi_init_domains()
172 middle_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; in pch_msi_init_domains()
173 middle_domain->msi_parent_ops = &pch_msi_parent_ops; in pch_msi_init_domains()
186 return -ENOMEM; in pch_msi_init()
188 mutex_init(&priv->msi_map_lock); in pch_msi_init()
190 priv->doorbell = msg_address; in pch_msi_init()
191 priv->irq_first = irq_base; in pch_msi_init()
192 priv->num_irqs = irq_count; in pch_msi_init()
194 priv->msi_map = bitmap_zalloc(priv->num_irqs, GFP_KERNEL); in pch_msi_init()
195 if (!priv->msi_map) in pch_msi_init()
199 priv->num_irqs, priv->irq_first); in pch_msi_init()
209 bitmap_free(priv->msi_map); in pch_msi_init()
213 return -EINVAL; in pch_msi_init()
217 static int pch_msi_of_init(struct device_node *node, struct device_node *parent) in pch_msi_of_init() argument
224 parent_domain = irq_find_host(parent); in pch_msi_of_init()
226 pr_err("Failed to find the parent domain\n"); in pch_msi_of_init()
227 return -ENXIO; in pch_msi_of_init()
232 return -EINVAL; in pch_msi_of_init()
235 if (of_property_read_u32(node, "loongson,msi-base-vec", &irq_base)) { in pch_msi_of_init()
236 pr_err("Unable to parse MSI vec base\n"); in pch_msi_of_init()
237 return -EINVAL; in pch_msi_of_init()
240 if (of_property_read_u32(node, "loongson,msi-num-vecs", &irq_count)) { in pch_msi_of_init()
241 pr_err("Unable to parse MSI vec number\n"); in pch_msi_of_init()
242 return -EINVAL; in pch_msi_of_init()
252 IRQCHIP_DECLARE(pch_msi, "loongson,pch-msi-1.0", pch_msi_of_init);
268 int __init pch_msi_acpi_init(struct irq_domain *parent, struct acpi_madt_msi_pic *acpi_pchmsi) in pch_msi_acpi_init() argument
273 domain_handle = irq_domain_alloc_fwnode(&acpi_pchmsi->msg_address); in pch_msi_acpi_init()
274 ret = pch_msi_init(acpi_pchmsi->msg_address, acpi_pchmsi->start, in pch_msi_acpi_init()
275 acpi_pchmsi->count, parent, domain_handle); in pch_msi_acpi_init()
282 int __init pch_msi_acpi_init_avec(struct irq_domain *parent) in pch_msi_acpi_init_avec() argument
287 pch_msi_handle[0] = parent->fwnode; in pch_msi_acpi_init_avec()
288 irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); in pch_msi_acpi_init_avec()
290 parent->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT; in pch_msi_acpi_init_avec()
291 parent->msi_parent_ops = &pch_msi_parent_ops; in pch_msi_acpi_init_avec()