Lines Matching +full:msi +full:- +full:base +full:- +full:spi

4  * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
14 #include <linux/msi.h>
20 #include <linux/irqchip/irq-msi-lib.h>
22 #include <dt-bindings/interrupt-controller/arm-gic.h>
46 for (i = 0; i < gicp->spi_ranges_cnt; i++) { in gicp_idx_to_spi()
47 struct mvebu_gicp_spi_range *r = &gicp->spi_ranges[i]; in gicp_idx_to_spi()
49 if (idx < r->count) in gicp_idx_to_spi()
50 return r->start + idx; in gicp_idx_to_spi()
52 idx -= r->count; in gicp_idx_to_spi()
55 return -EINVAL; in gicp_idx_to_spi()
60 struct mvebu_gicp *gicp = data->chip_data; in gicp_compose_msi_msg()
61 phys_addr_t setspi = gicp->res->start + GICP_SETSPI_NSR_OFFSET; in gicp_compose_msi_msg()
62 phys_addr_t clrspi = gicp->res->start + GICP_CLRSPI_NSR_OFFSET; in gicp_compose_msi_msg()
64 msg[0].data = data->hwirq; in gicp_compose_msi_msg()
67 msg[1].data = data->hwirq; in gicp_compose_msi_msg()
85 struct mvebu_gicp *gicp = domain->host_data; in gicp_irq_domain_alloc()
90 spin_lock(&gicp->spi_lock); in gicp_irq_domain_alloc()
91 hwirq = find_first_zero_bit(gicp->spi_bitmap, gicp->spi_cnt); in gicp_irq_domain_alloc()
92 if (hwirq == gicp->spi_cnt) { in gicp_irq_domain_alloc()
93 spin_unlock(&gicp->spi_lock); in gicp_irq_domain_alloc()
94 return -ENOSPC; in gicp_irq_domain_alloc()
96 __set_bit(hwirq, gicp->spi_bitmap); in gicp_irq_domain_alloc()
97 spin_unlock(&gicp->spi_lock); in gicp_irq_domain_alloc()
99 fwspec.fwnode = domain->parent->fwnode; in gicp_irq_domain_alloc()
102 fwspec.param[1] = gicp_idx_to_spi(gicp, hwirq) - 32; in gicp_irq_domain_alloc()
105 * ->set_type() is called in gicp_irq_domain_alloc()
111 dev_err(gicp->dev, "Cannot allocate parent IRQ\n"); in gicp_irq_domain_alloc()
125 spin_lock(&gicp->spi_lock); in gicp_irq_domain_alloc()
126 __clear_bit(hwirq, gicp->spi_bitmap); in gicp_irq_domain_alloc()
127 spin_unlock(&gicp->spi_lock); in gicp_irq_domain_alloc()
134 struct mvebu_gicp *gicp = domain->host_data; in gicp_irq_domain_free()
137 if (d->hwirq >= gicp->spi_cnt) { in gicp_irq_domain_free()
138 dev_err(gicp->dev, "Invalid hwirq %lu\n", d->hwirq); in gicp_irq_domain_free()
144 spin_lock(&gicp->spi_lock); in gicp_irq_domain_free()
145 __clear_bit(d->hwirq, gicp->spi_bitmap); in gicp_irq_domain_free()
146 spin_unlock(&gicp->spi_lock); in gicp_irq_domain_free()
167 .prefix = "GICP-",
173 struct device_node *node = pdev->dev.of_node; in mvebu_gicp_probe()
180 void __iomem *base; in mvebu_gicp_probe() local
183 gicp = devm_kzalloc(&pdev->dev, sizeof(*gicp), GFP_KERNEL); in mvebu_gicp_probe()
185 return -ENOMEM; in mvebu_gicp_probe()
187 gicp->dev = &pdev->dev; in mvebu_gicp_probe()
188 spin_lock_init(&gicp->spi_lock); in mvebu_gicp_probe()
190 gicp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); in mvebu_gicp_probe()
191 if (!gicp->res) in mvebu_gicp_probe()
192 return -ENODEV; in mvebu_gicp_probe()
194 ret = of_property_count_u32_elems(node, "marvell,spi-ranges"); in mvebu_gicp_probe()
198 gicp->spi_ranges_cnt = ret / 2; in mvebu_gicp_probe()
200 gicp->spi_ranges = in mvebu_gicp_probe()
201 devm_kcalloc(&pdev->dev, in mvebu_gicp_probe()
202 gicp->spi_ranges_cnt, in mvebu_gicp_probe()
205 if (!gicp->spi_ranges) in mvebu_gicp_probe()
206 return -ENOMEM; in mvebu_gicp_probe()
208 for (i = 0; i < gicp->spi_ranges_cnt; i++) { in mvebu_gicp_probe()
209 of_property_read_u32_index(node, "marvell,spi-ranges", in mvebu_gicp_probe()
211 &gicp->spi_ranges[i].start); in mvebu_gicp_probe()
213 of_property_read_u32_index(node, "marvell,spi-ranges", in mvebu_gicp_probe()
215 &gicp->spi_ranges[i].count); in mvebu_gicp_probe()
217 gicp->spi_cnt += gicp->spi_ranges[i].count; in mvebu_gicp_probe()
220 gicp->spi_bitmap = devm_bitmap_zalloc(&pdev->dev, gicp->spi_cnt, GFP_KERNEL); in mvebu_gicp_probe()
221 if (!gicp->spi_bitmap) in mvebu_gicp_probe()
222 return -ENOMEM; in mvebu_gicp_probe()
224 info.size = gicp->spi_cnt; in mvebu_gicp_probe()
229 dev_err(&pdev->dev, "failed to find parent IRQ node\n"); in mvebu_gicp_probe()
230 return -ENODEV; in mvebu_gicp_probe()
236 dev_err(&pdev->dev, "failed to find parent IRQ domain\n"); in mvebu_gicp_probe()
237 return -ENODEV; in mvebu_gicp_probe()
240 base = ioremap(gicp->res->start, resource_size(gicp->res)); in mvebu_gicp_probe()
241 if (!base) { in mvebu_gicp_probe()
242 dev_err(&pdev->dev, "ioremap() failed. Unable to clear pending interrupts.\n"); in mvebu_gicp_probe()
245 writel(i, base + GICP_CLRSPI_NSR_OFFSET); in mvebu_gicp_probe()
246 iounmap(base); in mvebu_gicp_probe()
249 return msi_create_parent_irq_domain(&info, &gicp_msi_parent_ops) ? 0 : -ENOMEM; in mvebu_gicp_probe()
253 { .compatible = "marvell,ap806-gicp", },
260 .name = "mvebu-gicp",