drivers/pci/controller/dwc/pcie-amd-mdb.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pcie-amd-mdb.c
Extension
.c
Size
13774 bytes
Lines
527
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 amd_mdb_pcie {
	struct dw_pcie			pci;
	void __iomem			*slcr;
	struct irq_domain		*intx_domain;
	struct irq_domain		*mdb_domain;
	struct gpio_desc		*perst_gpio;
	int				intx_irq;
};

static const struct dw_pcie_host_ops amd_mdb_pcie_host_ops = {
};

static void amd_mdb_intx_irq_mask(struct irq_data *data)
{
	struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data);
	struct dw_pcie *pci = &pcie->pci;
	struct dw_pcie_rp *port = &pci->pp;
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&port->lock, flags);
	val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));

	/*
	 * Writing '1' to a bit in AMD_MDB_TLP_IR_DISABLE_MISC disables that
	 * interrupt, writing '0' has no effect.
	 */
	writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_DISABLE_MISC);
	raw_spin_unlock_irqrestore(&port->lock, flags);
}

static void amd_mdb_intx_irq_unmask(struct irq_data *data)
{
	struct amd_mdb_pcie *pcie = irq_data_get_irq_chip_data(data);
	struct dw_pcie *pci = &pcie->pci;
	struct dw_pcie_rp *port = &pci->pp;
	unsigned long flags;
	u32 val;

	raw_spin_lock_irqsave(&port->lock, flags);
	val = FIELD_PREP(AMD_MDB_TLP_PCIE_INTX_MASK,
			 AMD_MDB_PCIE_INTR_INTX_ASSERT(data->hwirq));

	/*
	 * Writing '1' to a bit in AMD_MDB_TLP_IR_ENABLE_MISC enables that
	 * interrupt, writing '0' has no effect.
	 */
	writel_relaxed(val, pcie->slcr + AMD_MDB_TLP_IR_ENABLE_MISC);
	raw_spin_unlock_irqrestore(&port->lock, flags);
}

static struct irq_chip amd_mdb_intx_irq_chip = {
	.name		= "AMD MDB INTx",
	.irq_mask	= amd_mdb_intx_irq_mask,
	.irq_unmask	= amd_mdb_intx_irq_unmask,
};

/**
 * amd_mdb_pcie_intx_map - Set the handler for the INTx and mark IRQ as valid
 * @domain: IRQ domain
 * @irq: Virtual IRQ number
 * @hwirq: Hardware interrupt number
 *
 * Return: Always returns '0'.
 */
static int amd_mdb_pcie_intx_map(struct irq_domain *domain,
				 unsigned int irq, irq_hw_number_t hwirq)
{
	irq_set_chip_and_handler(irq, &amd_mdb_intx_irq_chip,
				 handle_level_irq);
	irq_set_chip_data(irq, domain->host_data);
	irq_set_status_flags(irq, IRQ_LEVEL);

	return 0;
}

/* INTx IRQ domain operations. */
static const struct irq_domain_ops amd_intx_domain_ops = {
	.map = amd_mdb_pcie_intx_map,
};

static irqreturn_t dw_pcie_rp_intx(int irq, void *args)
{
	struct amd_mdb_pcie *pcie = args;
	unsigned long val;
	int i, int_status;

	val = readl_relaxed(pcie->slcr + AMD_MDB_TLP_IR_STATUS_MISC);
	int_status = FIELD_GET(AMD_MDB_TLP_PCIE_INTX_MASK, val);

Annotation

Implementation Notes