drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/mobiveil/pcie-layerscape-gen4.c
Extension
.c
Size
6185 bytes
Lines
250
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 ls_g4_pcie {
	struct mobiveil_pcie pci;
	struct delayed_work dwork;
	int irq;
};

static inline u32 ls_g4_pcie_pf_readl(struct ls_g4_pcie *pcie, u32 off)
{
	return ioread32(pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
}

static inline void ls_g4_pcie_pf_writel(struct ls_g4_pcie *pcie,
					u32 off, u32 val)
{
	iowrite32(val, pcie->pci.csr_axi_slave_base + PCIE_PF_OFF + off);
}

static bool ls_g4_pcie_link_up(struct mobiveil_pcie *pci)
{
	struct ls_g4_pcie *pcie = to_ls_g4_pcie(pci);
	u32 state;

	state = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG);
	return (state & PF_DBG_LTSSM_MASK) == PF_DBG_LTSSM_L0;
}

static void ls_g4_pcie_disable_interrupt(struct ls_g4_pcie *pcie)
{
	struct mobiveil_pcie *mv_pci = &pcie->pci;

	mobiveil_csr_writel(mv_pci, 0, PAB_INTP_AMBA_MISC_ENB);
}

static void ls_g4_pcie_enable_interrupt(struct ls_g4_pcie *pcie)
{
	struct mobiveil_pcie *mv_pci = &pcie->pci;
	u32 val;

	/* Clear the interrupt status */
	mobiveil_csr_writel(mv_pci, 0xffffffff, PAB_INTP_AMBA_MISC_STAT);

	val = PAB_INTP_INTX_MASK | PAB_INTP_MSI | PAB_INTP_RESET |
	      PAB_INTP_PCIE_UE | PAB_INTP_IE_PMREDI | PAB_INTP_IE_EC;
	mobiveil_csr_writel(mv_pci, val, PAB_INTP_AMBA_MISC_ENB);
}

static int ls_g4_pcie_reinit_hw(struct ls_g4_pcie *pcie)
{
	struct mobiveil_pcie *mv_pci = &pcie->pci;
	struct device *dev = &mv_pci->pdev->dev;
	u32 val, act_stat;
	int to = 100;

	/* Poll for pab_csb_reset to set and PAB activity to clear */
	do {
		usleep_range(10, 15);
		val = ls_g4_pcie_pf_readl(pcie, PCIE_PF_INT_STAT);
		act_stat = mobiveil_csr_readl(mv_pci, PAB_ACTIVITY_STAT);
	} while (((val & PF_INT_STAT_PABRST) == 0 || act_stat) && to--);
	if (to < 0) {
		dev_err(dev, "Poll PABRST&PABACT timeout\n");
		return -EIO;
	}

	/* clear PEX_RESET bit in PEX_PF0_DBG register */
	val = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG);
	val |= PF_DBG_WE;
	ls_g4_pcie_pf_writel(pcie, PCIE_PF_DBG, val);

	val = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG);
	val |= PF_DBG_PABR;
	ls_g4_pcie_pf_writel(pcie, PCIE_PF_DBG, val);

	val = ls_g4_pcie_pf_readl(pcie, PCIE_PF_DBG);
	val &= ~PF_DBG_WE;
	ls_g4_pcie_pf_writel(pcie, PCIE_PF_DBG, val);

	mobiveil_host_init(mv_pci, true);

	to = 100;
	while (!ls_g4_pcie_link_up(mv_pci) && to--)
		usleep_range(200, 250);
	if (to < 0) {
		dev_err(dev, "PCIe link training timeout\n");
		return -EIO;
	}

	return 0;
}

Annotation

Implementation Notes