drivers/pci/controller/dwc/pcie-sophgo.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/dwc/pcie-sophgo.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pcie-sophgo.c
Extension
.c
Size
6692 bytes
Lines
276
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct sophgo_pcie {
	struct dw_pcie		pci;
	void __iomem		*app_base;
	struct clk_bulk_data	*clks;
	unsigned int		clk_cnt;
	struct irq_domain	*irq_domain;
};

static int sophgo_pcie_readl_app(struct sophgo_pcie *sophgo, u32 reg)
{
	return readl_relaxed(sophgo->app_base + reg);
}

static void sophgo_pcie_writel_app(struct sophgo_pcie *sophgo, u32 val, u32 reg)
{
	writel_relaxed(val, sophgo->app_base + reg);
}

static void sophgo_pcie_intx_handler(struct irq_desc *desc)
{
	struct dw_pcie_rp *pp = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
	unsigned long hwirq, reg;

	chained_irq_enter(chip, desc);

	reg = sophgo_pcie_readl_app(sophgo, PCIE_INT_SIGNAL);
	reg = FIELD_GET(PCIE_INT_SIGNAL_INTX, reg);

	for_each_set_bit(hwirq, &reg, PCI_NUM_INTX)
		generic_handle_domain_irq(sophgo->irq_domain, hwirq);

	chained_irq_exit(chip, desc);
}

static void sophgo_intx_irq_mask(struct irq_data *d)
{
	struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&pp->lock, flags);

	val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
	val &= ~FIELD_PREP(PCIE_INT_EN_INTX, BIT(d->hwirq));
	sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);

	raw_spin_unlock_irqrestore(&pp->lock, flags);
};

static void sophgo_intx_irq_unmask(struct irq_data *d)
{
	struct dw_pcie_rp *pp = irq_data_get_irq_chip_data(d);
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct sophgo_pcie *sophgo = to_sophgo_pcie(pci);
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&pp->lock, flags);

	val = sophgo_pcie_readl_app(sophgo, PCIE_INT_EN);
	val |= FIELD_PREP(PCIE_INT_EN_INTX, BIT(d->hwirq));
	sophgo_pcie_writel_app(sophgo, val, PCIE_INT_EN);

	raw_spin_unlock_irqrestore(&pp->lock, flags);
};

static struct irq_chip sophgo_intx_irq_chip = {
	.name			= "INTx",
	.irq_mask		= sophgo_intx_irq_mask,
	.irq_unmask		= sophgo_intx_irq_unmask,
};

static int sophgo_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
				irq_hw_number_t hwirq)
{
	irq_set_chip_and_handler(irq, &sophgo_intx_irq_chip, handle_level_irq);
	irq_set_chip_data(irq, domain->host_data);

	return 0;
}

static const struct irq_domain_ops intx_domain_ops = {
	.map = sophgo_pcie_intx_map,
};

Annotation

Implementation Notes