drivers/pci/controller/dwc/pci-layerscape.c

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

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pci-layerscape.c
Extension
.c
Size
11310 bytes
Lines
430
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_pcie_drvdata {
	const u32 pf_lut_off;
	const struct dw_pcie_host_ops *ops;
	int (*exit_from_l2)(struct dw_pcie_rp *pp);
	bool scfg_support;
	bool pm_support;
};

struct ls_pcie {
	struct dw_pcie *pci;
	const struct ls_pcie_drvdata *drvdata;
	void __iomem *pf_lut_base;
	struct regmap *scfg;
	int index;
	bool big_endian;
};

#define ls_pcie_pf_lut_readl_addr(addr)	ls_pcie_pf_lut_readl(pcie, addr)
#define to_ls_pcie(x)	dev_get_drvdata((x)->dev)

static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
{
	struct dw_pcie *pci = pcie->pci;
	u32 header_type;

	header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE);
	header_type &= PCI_HEADER_TYPE_MASK;

	return header_type == PCI_HEADER_TYPE_BRIDGE;
}

/* Clear multi-function bit */
static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
{
	struct dw_pcie *pci = pcie->pci;

	iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE);
}

/* Drop MSG TLP except for Vendor MSG */
static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
{
	u32 val;
	struct dw_pcie *pci = pcie->pci;

	val = ioread32(pci->dbi_base + PCIE_STRFMR1);
	val &= 0xDFFFFFFF;
	iowrite32(val, pci->dbi_base + PCIE_STRFMR1);
}

/* Forward error response of outbound non-posted requests */
static void ls_pcie_fix_error_response(struct ls_pcie *pcie)
{
	struct dw_pcie *pci = pcie->pci;

	iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR);
}

static u32 ls_pcie_pf_lut_readl(struct ls_pcie *pcie, u32 off)
{
	if (pcie->big_endian)
		return ioread32be(pcie->pf_lut_base + off);

	return ioread32(pcie->pf_lut_base + off);
}

static void ls_pcie_pf_lut_writel(struct ls_pcie *pcie, u32 off, u32 val)
{
	if (pcie->big_endian)
		iowrite32be(val, pcie->pf_lut_base + off);
	else
		iowrite32(val, pcie->pf_lut_base + off);
}

static void ls_pcie_send_turnoff_msg(struct dw_pcie_rp *pp)
{
	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
	struct ls_pcie *pcie = to_ls_pcie(pci);
	u32 val;
	int ret;

	val = ls_pcie_pf_lut_readl(pcie, LS_PCIE_PF_MCR);
	val |= PF_MCR_PTOMR;
	ls_pcie_pf_lut_writel(pcie, LS_PCIE_PF_MCR, val);

	ret = readx_poll_timeout(ls_pcie_pf_lut_readl_addr, LS_PCIE_PF_MCR,
				 val, !(val & PF_MCR_PTOMR),
				 PCIE_PME_TO_L2_TIMEOUT_US/10,
				 PCIE_PME_TO_L2_TIMEOUT_US);
	if (ret)

Annotation

Implementation Notes