Lines Matching +full:ls1043a +full:- +full:msi

1 // SPDX-License-Identifier: GPL-2.0-only
3 * Freescale SCFG MSI(-X) support
12 #include <linux/msi.h>
61 .name = "MSI",
77 if (p && strncmp(p, "no-affinity", 11) == 0) in early_parse_ls_scfg_msi()
90 msg->address_hi = upper_32_bits(msi_data->msiir_addr); in ls_scfg_msi_compose_msg()
91 msg->address_lo = lower_32_bits(msi_data->msiir_addr); in ls_scfg_msi_compose_msg()
92 msg->data = data->hwirq; in ls_scfg_msi_compose_msg()
98 msg->data |= cpumask_first(mask); in ls_scfg_msi_compose_msg()
111 return -EINVAL; in ls_scfg_msi_set_affinity()
118 if (cpu >= msi_data->msir_num) in ls_scfg_msi_set_affinity()
119 return -EINVAL; in ls_scfg_msi_set_affinity()
121 if (msi_data->msir[cpu].gic_irq <= 0) { in ls_scfg_msi_set_affinity()
123 return -EINVAL; in ls_scfg_msi_set_affinity()
143 struct ls_scfg_msi *msi_data = domain->host_data; in ls_scfg_msi_domain_irq_alloc()
148 spin_lock(&msi_data->lock); in ls_scfg_msi_domain_irq_alloc()
149 pos = find_first_zero_bit(msi_data->used, msi_data->irqs_num); in ls_scfg_msi_domain_irq_alloc()
150 if (pos < msi_data->irqs_num) in ls_scfg_msi_domain_irq_alloc()
151 __set_bit(pos, msi_data->used); in ls_scfg_msi_domain_irq_alloc()
153 err = -ENOSPC; in ls_scfg_msi_domain_irq_alloc()
154 spin_unlock(&msi_data->lock); in ls_scfg_msi_domain_irq_alloc()
159 err = iommu_dma_prepare_msi(info->desc, msi_data->msiir_addr); in ls_scfg_msi_domain_irq_alloc()
177 pos = d->hwirq; in ls_scfg_msi_domain_irq_free()
178 if (pos < 0 || pos >= msi_data->irqs_num) { in ls_scfg_msi_domain_irq_free()
179 pr_err("failed to teardown msi. Invalid hwirq %d\n", pos); in ls_scfg_msi_domain_irq_free()
183 spin_lock(&msi_data->lock); in ls_scfg_msi_domain_irq_free()
184 __clear_bit(pos, msi_data->used); in ls_scfg_msi_domain_irq_free()
185 spin_unlock(&msi_data->lock); in ls_scfg_msi_domain_irq_free()
196 struct ls_scfg_msi *msi_data = msir->msi_data; in ls_scfg_msi_irq_handler()
202 val = ioread32be(msir->reg); in ls_scfg_msi_irq_handler()
204 pos = msir->bit_start; in ls_scfg_msi_irq_handler()
205 size = msir->bit_end + 1; in ls_scfg_msi_irq_handler()
208 hwirq = ((msir->bit_end - pos) << msi_data->cfg->ibs_shift) | in ls_scfg_msi_irq_handler()
209 msir->srs; in ls_scfg_msi_irq_handler()
210 generic_handle_domain_irq(msi_data->parent, hwirq); in ls_scfg_msi_irq_handler()
218 /* Initialize MSI domain parent */ in ls_scfg_msi_domains_init()
219 msi_data->parent = irq_domain_add_linear(NULL, in ls_scfg_msi_domains_init()
220 msi_data->irqs_num, in ls_scfg_msi_domains_init()
223 if (!msi_data->parent) { in ls_scfg_msi_domains_init()
224 dev_err(&msi_data->pdev->dev, "failed to create IRQ domain\n"); in ls_scfg_msi_domains_init()
225 return -ENOMEM; in ls_scfg_msi_domains_init()
228 msi_data->msi_domain = pci_msi_create_irq_domain( in ls_scfg_msi_domains_init()
229 of_node_to_fwnode(msi_data->pdev->dev.of_node), in ls_scfg_msi_domains_init()
231 msi_data->parent); in ls_scfg_msi_domains_init()
232 if (!msi_data->msi_domain) { in ls_scfg_msi_domains_init()
233 dev_err(&msi_data->pdev->dev, "failed to create MSI domain\n"); in ls_scfg_msi_domains_init()
234 irq_domain_remove(msi_data->parent); in ls_scfg_msi_domains_init()
235 return -ENOMEM; in ls_scfg_msi_domains_init()
246 virq = platform_get_irq(msi_data->pdev, index); in ls_scfg_msi_setup_hwirq()
248 return -ENODEV; in ls_scfg_msi_setup_hwirq()
250 msir = &msi_data->msir[index]; in ls_scfg_msi_setup_hwirq()
251 msir->index = index; in ls_scfg_msi_setup_hwirq()
252 msir->msi_data = msi_data; in ls_scfg_msi_setup_hwirq()
253 msir->gic_irq = virq; in ls_scfg_msi_setup_hwirq()
254 msir->reg = msi_data->regs + msi_data->cfg->msir_base + 4 * index; in ls_scfg_msi_setup_hwirq()
256 if (msi_data->cfg->msir_irqs == MSI_LS1043V1_1_IRQS_PER_MSIR) { in ls_scfg_msi_setup_hwirq()
257 msir->bit_start = 32 - ((msir->index + 1) * in ls_scfg_msi_setup_hwirq()
259 msir->bit_end = msir->bit_start + in ls_scfg_msi_setup_hwirq()
260 MSI_LS1043V1_1_IRQS_PER_MSIR - 1; in ls_scfg_msi_setup_hwirq()
262 msir->bit_start = 0; in ls_scfg_msi_setup_hwirq()
263 msir->bit_end = msi_data->cfg->msir_irqs - 1; in ls_scfg_msi_setup_hwirq()
266 irq_set_chained_handler_and_data(msir->gic_irq, in ls_scfg_msi_setup_hwirq()
272 irq_set_affinity(msir->gic_irq, get_cpu_mask(index)); in ls_scfg_msi_setup_hwirq()
273 msir->srs = 0; /* This value is determined by the CPU */ in ls_scfg_msi_setup_hwirq()
275 msir->srs = index; in ls_scfg_msi_setup_hwirq()
278 if (!msi_affinity_flag || msir->index == 0) { in ls_scfg_msi_setup_hwirq()
279 for (i = 0; i < msi_data->cfg->msir_irqs; i++) { in ls_scfg_msi_setup_hwirq()
280 hwirq = i << msi_data->cfg->ibs_shift | msir->index; in ls_scfg_msi_setup_hwirq()
281 bitmap_clear(msi_data->used, hwirq, 1); in ls_scfg_msi_setup_hwirq()
290 struct ls_scfg_msi *msi_data = msir->msi_data; in ls_scfg_msi_teardown_hwirq()
293 if (msir->gic_irq > 0) in ls_scfg_msi_teardown_hwirq()
294 irq_set_chained_handler_and_data(msir->gic_irq, NULL, NULL); in ls_scfg_msi_teardown_hwirq()
296 for (i = 0; i < msi_data->cfg->msir_irqs; i++) { in ls_scfg_msi_teardown_hwirq()
297 hwirq = i << msi_data->cfg->ibs_shift | msir->index; in ls_scfg_msi_teardown_hwirq()
298 bitmap_set(msi_data->used, hwirq, 1); in ls_scfg_msi_teardown_hwirq()
324 { .compatible = "fsl,1s1021a-msi", .data = &ls1021_msi_cfg},
325 { .compatible = "fsl,1s1043a-msi", .data = &ls1021_msi_cfg},
327 { .compatible = "fsl,ls1012a-msi", .data = &ls1021_msi_cfg },
328 { .compatible = "fsl,ls1021a-msi", .data = &ls1021_msi_cfg },
329 { .compatible = "fsl,ls1043a-msi", .data = &ls1021_msi_cfg },
330 { .compatible = "fsl,ls1043a-v1.1-msi", .data = &ls1043_v1_1_msi_cfg },
331 { .compatible = "fsl,ls1046a-msi", .data = &ls1046_msi_cfg },
342 msi_data = devm_kzalloc(&pdev->dev, sizeof(*msi_data), GFP_KERNEL); in ls_scfg_msi_probe()
344 return -ENOMEM; in ls_scfg_msi_probe()
346 msi_data->cfg = (struct ls_scfg_msi_cfg *)device_get_match_data(&pdev->dev); in ls_scfg_msi_probe()
347 if (!msi_data->cfg) in ls_scfg_msi_probe()
348 return -ENODEV; in ls_scfg_msi_probe()
350 msi_data->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in ls_scfg_msi_probe()
351 if (IS_ERR(msi_data->regs)) { in ls_scfg_msi_probe()
352 dev_err(&pdev->dev, "failed to initialize 'regs'\n"); in ls_scfg_msi_probe()
353 return PTR_ERR(msi_data->regs); in ls_scfg_msi_probe()
355 msi_data->msiir_addr = res->start; in ls_scfg_msi_probe()
357 msi_data->pdev = pdev; in ls_scfg_msi_probe()
358 spin_lock_init(&msi_data->lock); in ls_scfg_msi_probe()
360 msi_data->irqs_num = MSI_IRQS_PER_MSIR * in ls_scfg_msi_probe()
361 (1 << msi_data->cfg->ibs_shift); in ls_scfg_msi_probe()
362 msi_data->used = devm_bitmap_zalloc(&pdev->dev, msi_data->irqs_num, GFP_KERNEL); in ls_scfg_msi_probe()
363 if (!msi_data->used) in ls_scfg_msi_probe()
364 return -ENOMEM; in ls_scfg_msi_probe()
369 bitmap_set(msi_data->used, 0, msi_data->irqs_num); in ls_scfg_msi_probe()
371 msi_data->msir_num = of_irq_count(pdev->dev.of_node); in ls_scfg_msi_probe()
377 if (msi_data->msir_num >= cpu_num) in ls_scfg_msi_probe()
378 msi_data->msir_num = cpu_num; in ls_scfg_msi_probe()
383 msi_data->msir = devm_kcalloc(&pdev->dev, msi_data->msir_num, in ls_scfg_msi_probe()
384 sizeof(*msi_data->msir), in ls_scfg_msi_probe()
386 if (!msi_data->msir) in ls_scfg_msi_probe()
387 return -ENOMEM; in ls_scfg_msi_probe()
389 for (i = 0; i < msi_data->msir_num; i++) in ls_scfg_msi_probe()
406 for (i = 0; i < msi_data->msir_num; i++) in ls_scfg_msi_remove()
407 ls_scfg_msi_teardown_hwirq(&msi_data->msir[i]); in ls_scfg_msi_remove()
409 irq_domain_remove(msi_data->msi_domain); in ls_scfg_msi_remove()
410 irq_domain_remove(msi_data->parent); in ls_scfg_msi_remove()
417 .name = "ls-scfg-msi",
427 MODULE_DESCRIPTION("Freescale Layerscape SCFG MSI controller driver");