drivers/pci/controller/pcie-rockchip-ep.c

Source file repositories/reference/linux-study-clean/drivers/pci/controller/pcie-rockchip-ep.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/controller/pcie-rockchip-ep.c
Extension
.c
Size
25446 bytes
Lines
911
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 rockchip_pcie_ep {
	struct rockchip_pcie	rockchip;
	struct pci_epc		*epc;
	u32			max_regions;
	unsigned long		ob_region_map;
	phys_addr_t		*ob_addr;
	phys_addr_t		irq_phys_addr;
	void __iomem		*irq_cpu_addr;
	u64			irq_pci_addr;
	u8			irq_pci_fn;
	u8			irq_pending;
	int			perst_irq;
	bool			perst_asserted;
	bool			link_up;
	struct delayed_work	link_training;
};

static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip,
					  u32 region)
{
	rockchip_pcie_write(rockchip, 0,
			    ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(region));
	rockchip_pcie_write(rockchip, 0,
			    ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(region));
	rockchip_pcie_write(rockchip, 0,
			    ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region));
	rockchip_pcie_write(rockchip, 0,
			    ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region));
}

static int rockchip_pcie_ep_ob_atu_num_bits(struct rockchip_pcie *rockchip,
					    u64 pci_addr, size_t size)
{
	int num_pass_bits = fls64(pci_addr ^ (pci_addr + size - 1));

	return clamp(num_pass_bits,
		     ROCKCHIP_PCIE_AT_MIN_NUM_BITS,
		     ROCKCHIP_PCIE_AT_MAX_NUM_BITS);
}

static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn,
					 u32 r, u64 cpu_addr, u64 pci_addr,
					 size_t size)
{
	int num_pass_bits;
	u32 addr0, addr1, desc0;

	num_pass_bits = rockchip_pcie_ep_ob_atu_num_bits(rockchip,
							 pci_addr, size);

	addr0 = ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) |
		(lower_32_bits(pci_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR);
	addr1 = upper_32_bits(pci_addr);
	desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | AXI_WRAPPER_MEM_WRITE;

	/* PCI bus address region */
	rockchip_pcie_write(rockchip, addr0,
			    ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r));
	rockchip_pcie_write(rockchip, addr1,
			    ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r));
	rockchip_pcie_write(rockchip, desc0,
			    ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r));
	rockchip_pcie_write(rockchip, 0,
			    ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r));
}

static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, u8 vfn,
					 struct pci_epf_header *hdr)
{
	u32 reg;
	struct rockchip_pcie_ep *ep = epc_get_drvdata(epc);
	struct rockchip_pcie *rockchip = &ep->rockchip;

	/* All functions share the same vendor ID with function 0 */
	if (fn == 0) {
		rockchip_pcie_write(rockchip,
				    hdr->vendorid | hdr->subsys_vendor_id << 16,
				    PCIE_CORE_CONFIG_VENDOR);
	}

	reg = rockchip_pcie_read(rockchip, PCIE_EP_CONFIG_DID_VID);
	reg = (reg & 0xFFFF) | (hdr->deviceid << 16);
	rockchip_pcie_write(rockchip, reg, PCIE_EP_CONFIG_DID_VID);

	rockchip_pcie_write(rockchip,
			    hdr->revid |
			    hdr->progif_code << 8 |
			    hdr->subclass_code << 16 |
			    hdr->baseclass_code << 24,
			    ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_REVISION_ID);

Annotation

Implementation Notes