drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
Source file repositories/reference/linux-study-clean/drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/pci/controller/mobiveil/pcie-mobiveil-host.c- Extension
.c- Size
- 16465 bytes
- Lines
- 583
- Domain
- Representative Device Path
- Bucket
- PCIe NVMe Storage Path
- Inferred role
- Representative Device Path: implementation source
- Status
- source implementation candidate
Why This File Exists
Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Part of the selected hardware vertical slice: PCI discovery, driver binding, NVMe queues, block requests, DMA, interrupts, and completion.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Touches IRQ or DMA behavior; this matters for the representative real-device path.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/init.hlinux/interrupt.hlinux/irq.hlinux/irqchip/irq-msi-lib.hlinux/irqchip/chained_irq.hlinux/irqdomain.hlinux/kernel.hlinux/module.hlinux/msi.hlinux/of_pci.hlinux/pci.hlinux/platform_device.hlinux/slab.hpcie-mobiveil.h
Detected Declarations
function Copyrightfunction mobiveil_pcie_isrfunction for_each_set_bitfunction mobiveil_pcie_parse_dtfunction mobiveil_pcie_enable_msifunction mobiveil_host_initfunction mobiveil_mask_intx_irqfunction mobiveil_unmask_intx_irqfunction mobiveil_pcie_intx_mapfunction mobiveil_compose_msi_msgfunction mobiveil_irq_msi_domain_allocfunction mobiveil_irq_msi_domain_freefunction mobiveil_allocate_msi_domainsfunction mobiveil_pcie_init_irq_domainfunction mobiveil_pcie_integrated_interrupt_initfunction mobiveil_pcie_interrupt_initfunction mobiveil_pcie_is_bridgefunction mobiveil_pcie_host_probe
Annotated Snippet
for_each_set_bit(bit, &shifted_status, PCI_NUM_INTX) {
int ret;
ret = generic_handle_domain_irq(rp->intx_domain,
bit + 1);
if (ret)
dev_err_ratelimited(dev, "unexpected IRQ, INT%d\n",
bit);
/* clear interrupt handled */
mobiveil_csr_writel(pcie,
1 << (PAB_INTX_START + bit),
PAB_INTP_AMBA_MISC_STAT);
}
shifted_status = mobiveil_csr_readl(pcie,
PAB_INTP_AMBA_MISC_STAT);
shifted_status &= PAB_INTP_INTX_MASK;
shifted_status >>= PAB_INTX_START;
} while (shifted_status != 0);
}
/* read extra MSI status register */
msi_status = readl_relaxed(pcie->apb_csr_base + MSI_STATUS_OFFSET);
/* handle MSI interrupts */
while (msi_status & 1) {
msi_data = readl_relaxed(pcie->apb_csr_base + MSI_DATA_OFFSET);
/*
* MSI_STATUS_OFFSET register gets updated to zero
* once we pop not only the MSI data but also address
* from MSI hardware FIFO. So keeping these following
* two dummy reads.
*/
msi_addr_lo = readl_relaxed(pcie->apb_csr_base +
MSI_ADDR_L_OFFSET);
msi_addr_hi = readl_relaxed(pcie->apb_csr_base +
MSI_ADDR_H_OFFSET);
dev_dbg(dev, "MSI registers, data: %08x, addr: %08x:%08x\n",
msi_data, msi_addr_hi, msi_addr_lo);
generic_handle_domain_irq(msi->dev_domain, msi_data);
msi_status = readl_relaxed(pcie->apb_csr_base +
MSI_STATUS_OFFSET);
}
/* Clear the interrupt status */
mobiveil_csr_writel(pcie, intr_status, PAB_INTP_AMBA_MISC_STAT);
chained_irq_exit(chip, desc);
}
static int mobiveil_pcie_parse_dt(struct mobiveil_pcie *pcie)
{
struct device *dev = &pcie->pdev->dev;
struct platform_device *pdev = pcie->pdev;
struct device_node *node = dev->of_node;
struct mobiveil_root_port *rp = &pcie->rp;
struct resource *res;
/* map config resource */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"config_axi_slave");
rp->config_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
if (IS_ERR(rp->config_axi_slave_base))
return PTR_ERR(rp->config_axi_slave_base);
rp->ob_io_res = res;
/* map csr resource */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"csr_axi_slave");
pcie->csr_axi_slave_base = devm_pci_remap_cfg_resource(dev, res);
if (IS_ERR(pcie->csr_axi_slave_base))
return PTR_ERR(pcie->csr_axi_slave_base);
pcie->pcie_reg_base = res->start;
/* read the number of windows requested */
if (of_property_read_u32(node, "apio-wins", &pcie->apio_wins))
pcie->apio_wins = MAX_PIO_WINDOWS;
if (of_property_read_u32(node, "ppio-wins", &pcie->ppio_wins))
pcie->ppio_wins = MAX_PIO_WINDOWS;
return 0;
}
static void mobiveil_pcie_enable_msi(struct mobiveil_pcie *pcie)
{
phys_addr_t msg_addr = pcie->pcie_reg_base;
struct mobiveil_msi *msi = &pcie->rp.msi;
Annotation
- Immediate include surface: `linux/init.h`, `linux/interrupt.h`, `linux/irq.h`, `linux/irqchip/irq-msi-lib.h`, `linux/irqchip/chained_irq.h`, `linux/irqdomain.h`, `linux/kernel.h`, `linux/module.h`.
- Detected declarations: `function Copyright`, `function mobiveil_pcie_isr`, `function for_each_set_bit`, `function mobiveil_pcie_parse_dt`, `function mobiveil_pcie_enable_msi`, `function mobiveil_host_init`, `function mobiveil_mask_intx_irq`, `function mobiveil_unmask_intx_irq`, `function mobiveil_pcie_intx_map`, `function mobiveil_compose_msi_msg`.
- Atlas domain: Representative Device Path / PCIe NVMe Storage Path.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
- IRQ or DMA behavior appears here, which is relevant to the selected PCIe/NVMe device path.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.