drivers/pci/of_property.c

Source file repositories/reference/linux-study-clean/drivers/pci/of_property.c

File Facts

System
Linux kernel
Corpus path
drivers/pci/of_property.c
Extension
.c
Size
12318 bytes
Lines
508
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 of_pci_addr_pair {
	u32		phys_addr[OF_PCI_ADDRESS_CELLS];
	u32		size[OF_PCI_SIZE_CELLS];
};

/*
 * Each entry in the ranges table is a tuple containing the child address,
 * the parent address, and the size of the region in the child address space.
 * Thus, for PCI, in each entry parent address is an address on the primary
 * side and the child address is the corresponding address on the secondary
 * side.
 */
struct of_pci_range_entry {
	u32		child_addr[OF_PCI_ADDRESS_CELLS];
	u32		parent_addr[OF_PCI_ADDRESS_CELLS];
	u32		size[OF_PCI_SIZE_CELLS];
};

#define OF_PCI_ADDR_SPACE_IO		0x1
#define OF_PCI_ADDR_SPACE_MEM32		0x2
#define OF_PCI_ADDR_SPACE_MEM64		0x3

#define OF_PCI_ADDR_FIELD_NONRELOC	BIT(31)
#define OF_PCI_ADDR_FIELD_SS		GENMASK(25, 24)
#define OF_PCI_ADDR_FIELD_PREFETCH	BIT(30)
#define OF_PCI_ADDR_FIELD_BUS		GENMASK(23, 16)
#define OF_PCI_ADDR_FIELD_DEV		GENMASK(15, 11)
#define OF_PCI_ADDR_FIELD_FUNC		GENMASK(10, 8)
#define OF_PCI_ADDR_FIELD_REG		GENMASK(7, 0)

enum of_pci_prop_compatible {
	PROP_COMPAT_PCI_VVVV_DDDD,
	PROP_COMPAT_PCICLASS_CCSSPP,
	PROP_COMPAT_PCICLASS_CCSS,
	PROP_COMPAT_NUM,
};

static void of_pci_set_address(struct pci_dev *pdev, u32 *prop, u64 addr,
			       u32 reg_num, u32 flags, bool reloc)
{
	if (pdev) {
		prop[0] = FIELD_PREP(OF_PCI_ADDR_FIELD_BUS, pdev->bus->number) |
			  FIELD_PREP(OF_PCI_ADDR_FIELD_DEV, PCI_SLOT(pdev->devfn)) |
			  FIELD_PREP(OF_PCI_ADDR_FIELD_FUNC, PCI_FUNC(pdev->devfn));
	} else
		prop[0] = 0;

	prop[0] |= flags | reg_num;
	if (!reloc) {
		prop[0] |= OF_PCI_ADDR_FIELD_NONRELOC;
		prop[1] = upper_32_bits(addr);
		prop[2] = lower_32_bits(addr);
	}
}

static int of_pci_get_addr_flags(const struct resource *res, u32 *flags)
{
	u32 ss;

	if (res->flags & IORESOURCE_IO)
		ss = OF_PCI_ADDR_SPACE_IO;
	else if (res->flags & IORESOURCE_MEM_64)
		ss = OF_PCI_ADDR_SPACE_MEM64;
	else if (res->flags & IORESOURCE_MEM)
		ss = OF_PCI_ADDR_SPACE_MEM32;
	else
		return -EINVAL;

	*flags = 0;
	if (res->flags & IORESOURCE_PREFETCH)
		*flags |= OF_PCI_ADDR_FIELD_PREFETCH;

	*flags |= FIELD_PREP(OF_PCI_ADDR_FIELD_SS, ss);

	return 0;
}

static int of_pci_prop_bus_range(struct pci_dev *pdev,
				 struct of_changeset *ocs,
				 struct device_node *np)
{
	u32 bus_range[] = { pdev->subordinate->busn_res.start,
			    pdev->subordinate->busn_res.end };

	return of_changeset_add_prop_u32_array(ocs, np, "bus-range", bus_range,
					       ARRAY_SIZE(bus_range));
}

static int of_pci_prop_ranges(struct pci_dev *pdev, struct of_changeset *ocs,
			      struct device_node *np)

Annotation

Implementation Notes