Lines Matching +full:xgene1 +full:- +full:msi
1 // SPDX-License-Identifier: GPL-2.0+
3 * APM X-Gene MSI Driver
14 #include <linux/msi.h>
16 #include <linux/irqchip/irq-msi-lib.h>
49 * X-Gene v1 has 16 frames of MSI termination registers MSInIRx, where n is
54 * Each register supports 16 MSI vectors (0..15) to generate interrupts. A
60 * Additionally, each MSI termination frame has 1 MSIINTn register (n is
61 * 0..15) to indicate the MSI pending status caused by any of its 8
66 * There is one GIC IRQ assigned for each MSI termination frame, 16 in
92 static u32 xgene_msi_ir_read(struct xgene_msi *msi, u32 msi_grp, u32 msir_idx) in xgene_msi_ir_read() argument
94 return readl_relaxed(msi->msi_regs + MSI_IR0 + in xgene_msi_ir_read()
100 static u32 xgene_msi_int_read(struct xgene_msi *msi, u32 msi_grp) in xgene_msi_int_read() argument
102 return readl_relaxed(msi->msi_regs + MSI_INT0 + in xgene_msi_int_read()
107 * In order to allow an MSI to be moved from one CPU to another without
109 * atomically), we statically partitions the MSI frames between CPUs. Given
110 * that XGene-1 has 8 CPUs, each CPU gets two frames assigned to it
112 * We adopt the convention that when an MSI is moved, it is configured to
114 * new target CPU. This reserves a given MSI across all CPUs, and reduces
115 * the MSI capacity from 2048 to 256.
118 * - hwirq[7]::cpu[2:0] is the target frame number (n in MSInIRx)
119 * - hwirq[6:4] is the register index in any given frame (x in MSInIRx)
120 * - hwirq[3:0] is the MSI data
131 struct xgene_msi *msi = irq_data_get_irq_chip_data(data); in xgene_compose_msi_msg() local
137 msir = FIELD_GET(MSInRx_HWIRQ_MASK, data->hwirq); in xgene_compose_msi_msg()
138 frame = FIELD_PREP(BIT(3), FIELD_GET(BIT(7), data->hwirq)) | cpu; in xgene_compose_msi_msg()
140 target_addr = msi->msi_addr; in xgene_compose_msi_msg()
144 msg->address_hi = upper_32_bits(target_addr); in xgene_compose_msi_msg()
145 msg->address_lo = lower_32_bits(target_addr); in xgene_compose_msi_msg()
146 msg->data = FIELD_GET(DATA_HWIRQ_MASK, data->hwirq); in xgene_compose_msi_msg()
161 .name = "MSI",
169 struct xgene_msi *msi = domain->host_data; in xgene_irq_domain_alloc() local
172 mutex_lock(&msi->bitmap_lock); in xgene_irq_domain_alloc()
174 hwirq = find_first_zero_bit(msi->bitmap, NR_MSI_VEC); in xgene_irq_domain_alloc()
176 set_bit(hwirq, msi->bitmap); in xgene_irq_domain_alloc()
178 mutex_unlock(&msi->bitmap_lock); in xgene_irq_domain_alloc()
181 return -ENOSPC; in xgene_irq_domain_alloc()
184 &xgene_msi_bottom_irq_chip, domain->host_data, in xgene_irq_domain_alloc()
195 struct xgene_msi *msi = irq_data_get_irq_chip_data(d); in xgene_irq_domain_free() local
197 mutex_lock(&msi->bitmap_lock); in xgene_irq_domain_free()
199 clear_bit(d->hwirq, msi->bitmap); in xgene_irq_domain_free()
201 mutex_unlock(&msi->bitmap_lock); in xgene_irq_domain_free()
221 struct xgene_msi *msi) in xgene_allocate_domains() argument
227 .host_data = msi, in xgene_allocate_domains()
230 msi->inner_domain = msi_create_parent_irq_domain(&info, &xgene_msi_parent_ops); in xgene_allocate_domains()
231 return msi->inner_domain ? 0 : -ENOMEM; in xgene_allocate_domains()
236 xgene_msi_ctrl->bitmap = devm_bitmap_zalloc(dev, NR_MSI_VEC, GFP_KERNEL); in xgene_msi_init_allocator()
237 if (!xgene_msi_ctrl->bitmap) in xgene_msi_init_allocator()
238 return -ENOMEM; in xgene_msi_init_allocator()
240 mutex_init(&xgene_msi_ctrl->bitmap_lock); in xgene_msi_init_allocator()
256 msi_grp = irqp - xgene_msi->gic_irq; in xgene_msi_isr()
271 ret = generic_handle_domain_irq(xgene_msi->inner_domain, in xgene_msi_isr()
283 unsigned int irq = xgene_msi_ctrl->gic_irq[i]; in xgene_msi_remove()
289 if (xgene_msi_ctrl->inner_domain) in xgene_msi_remove()
290 irq_domain_remove(xgene_msi_ctrl->inner_domain); in xgene_msi_remove()
303 * MSInIRx registers are read-to-clear; before registering in xgene_msi_handler_setup()
313 dev_err(&pdev->dev, "Failed to clear spurious IRQ\n"); in xgene_msi_handler_setup()
321 xgene_msi->gic_irq[i] = irq; in xgene_msi_handler_setup()
324 * Statically allocate MSI GIC IRQs to each CPU core. in xgene_msi_handler_setup()
325 * With 8-core X-Gene v1, 2 MSI GIC IRQs are allocated in xgene_msi_handler_setup()
336 &xgene_msi_ctrl->gic_irq[i]); in xgene_msi_handler_setup()
343 {.compatible = "apm,xgene1-msi"},
353 xgene_msi_ctrl = devm_kzalloc(&pdev->dev, sizeof(*xgene_msi_ctrl), in xgene_msi_probe()
356 return -ENOMEM; in xgene_msi_probe()
360 xgene_msi->msi_regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res); in xgene_msi_probe()
361 if (IS_ERR(xgene_msi->msi_regs)) { in xgene_msi_probe()
362 rc = PTR_ERR(xgene_msi->msi_regs); in xgene_msi_probe()
365 xgene_msi->msi_addr = res->start; in xgene_msi_probe()
367 rc = xgene_msi_init_allocator(&pdev->dev); in xgene_msi_probe()
369 dev_err(&pdev->dev, "Error allocating MSI bitmap\n"); in xgene_msi_probe()
373 rc = xgene_allocate_domains(dev_of_node(&pdev->dev), xgene_msi); in xgene_msi_probe()
375 dev_err(&pdev->dev, "Failed to allocate MSI domain\n"); in xgene_msi_probe()
383 dev_info(&pdev->dev, "APM X-Gene PCIe MSI driver loaded\n"); in xgene_msi_probe()
393 .name = "xgene-msi",