drivers/pci/controller/pcie-xilinx-cpm.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/pcie-xilinx-cpm.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/pcie-xilinx-cpm.c
Extension
.c
Size
18122 bytes
Lines
687
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 xilinx_cpm_variant {
	enum xilinx_cpm_version version;
	u32 ir_status;
	u32 ir_enable;
	u32 ir_misc_value;
};

/**
 * struct xilinx_cpm_pcie - PCIe port information
 * @dev: Device pointer
 * @reg_base: Bridge Register Base
 * @cpm_base: CPM System Level Control and Status Register(SLCR) Base
 * @intx_domain: Legacy IRQ domain pointer
 * @cpm_domain: CPM IRQ domain pointer
 * @cfg: Holds mappings of config space window
 * @intx_irq: legacy interrupt number
 * @irq: Error interrupt number
 * @lock: lock protecting shared register access
 * @variant: CPM version check pointer
 */
struct xilinx_cpm_pcie {
	struct device			*dev;
	void __iomem			*reg_base;
	void __iomem			*cpm_base;
	struct irq_domain		*intx_domain;
	struct irq_domain		*cpm_domain;
	struct pci_config_window	*cfg;
	int				intx_irq;
	int				irq;
	raw_spinlock_t			lock;
	const struct xilinx_cpm_variant   *variant;
};

static u32 pcie_read(struct xilinx_cpm_pcie *port, u32 reg)
{
	return readl_relaxed(port->reg_base + reg);
}

static void pcie_write(struct xilinx_cpm_pcie *port,
		       u32 val, u32 reg)
{
	writel_relaxed(val, port->reg_base + reg);
}

static bool cpm_pcie_link_up(struct xilinx_cpm_pcie *port)
{
	return (pcie_read(port, XILINX_CPM_PCIE_REG_PSCR) &
		XILINX_CPM_PCIE_REG_PSCR_LNKUP);
}

static void cpm_pcie_clear_err_interrupts(struct xilinx_cpm_pcie *port)
{
	unsigned long val = pcie_read(port, XILINX_CPM_PCIE_REG_RPEFR);

	if (val & XILINX_CPM_PCIE_RPEFR_ERR_VALID) {
		dev_dbg(port->dev, "Requester ID %lu\n",
			val & XILINX_CPM_PCIE_RPEFR_REQ_ID);
		pcie_write(port, XILINX_CPM_PCIE_RPEFR_ALL_MASK,
			   XILINX_CPM_PCIE_REG_RPEFR);
	}
}

static void xilinx_cpm_mask_leg_irq(struct irq_data *data)
{
	struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
	unsigned long flags;
	u32 mask;
	u32 val;

	mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
	raw_spin_lock_irqsave(&port->lock, flags);
	val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
	pcie_write(port, (val & (~mask)), XILINX_CPM_PCIE_REG_IDRN_MASK);
	raw_spin_unlock_irqrestore(&port->lock, flags);
}

static void xilinx_cpm_unmask_leg_irq(struct irq_data *data)
{
	struct xilinx_cpm_pcie *port = irq_data_get_irq_chip_data(data);
	unsigned long flags;
	u32 mask;
	u32 val;

	mask = BIT(data->hwirq + XILINX_CPM_PCIE_IDRN_SHIFT);
	raw_spin_lock_irqsave(&port->lock, flags);
	val = pcie_read(port, XILINX_CPM_PCIE_REG_IDRN_MASK);
	pcie_write(port, (val | mask), XILINX_CPM_PCIE_REG_IDRN_MASK);
	raw_spin_unlock_irqrestore(&port->lock, flags);
}

Annotation

Implementation Notes