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

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

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/dwc/pcie-eswin.c
Extension
.c
Size
10651 bytes
Lines
409
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 eswin_pcie_data {
	bool skip_l23;
};

struct eswin_pcie_port {
	struct list_head list;
	struct reset_control *perst;
	int num_lanes;
};

struct eswin_pcie {
	struct dw_pcie pci;
	struct clk_bulk_data *clks;
	struct reset_control_bulk_data resets[ESWIN_NUM_RSTS];
	struct list_head ports;
	const struct eswin_pcie_data *data;
	int num_clks;
};

#define to_eswin_pcie(x) dev_get_drvdata((x)->dev)

static int eswin_pcie_start_link(struct dw_pcie *pci)
{
	u32 val;

	/* Enable LTSSM */
	val = readl_relaxed(pci->elbi_base + PCIEELBI_CTRL0_OFFSET);
	val |= PCIEELBI_APP_LTSSM_ENABLE;
	writel_relaxed(val, pci->elbi_base + PCIEELBI_CTRL0_OFFSET);

	return 0;
}

static bool eswin_pcie_link_up(struct dw_pcie *pci)
{
	u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
	u16 val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);

	return val & PCI_EXP_LNKSTA_DLLLA;
}

static int eswin_pcie_perst_reset(struct eswin_pcie_port *port,
				  struct eswin_pcie *pcie)
{
	int ret;

	ret = reset_control_assert(port->perst);
	if (ret) {
		dev_err(pcie->pci.dev, "Failed to assert PERST#\n");
		return ret;
	}

	/* Ensure that PERST# has been asserted for at least 100 ms */
	msleep(PCIE_T_PVPERL_MS);

	ret = reset_control_deassert(port->perst);
	if (ret) {
		dev_err(pcie->pci.dev, "Failed to deassert PERST#\n");
		return ret;
	}

	return 0;
}

static void eswin_pcie_assert(struct eswin_pcie *pcie)
{
	struct eswin_pcie_port *port;

	list_for_each_entry(port, &pcie->ports, list)
		reset_control_assert(port->perst);
	reset_control_bulk_assert(ESWIN_NUM_RSTS, pcie->resets);
}

static int eswin_pcie_parse_port(struct eswin_pcie *pcie,
				 struct device_node *node)
{
	struct device *dev = pcie->pci.dev;
	struct eswin_pcie_port *port;

	port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
	if (!port)
		return -ENOMEM;

	port->perst = of_reset_control_get_exclusive(node, "perst");
	if (IS_ERR(port->perst)) {
		dev_err(dev, "Failed to get PERST# reset\n");
		return PTR_ERR(port->perst);
	}

	/*

Annotation

Implementation Notes