drivers/of/address.c

Source file repositories/reference/linux-study-clean/drivers/of/address.c

File Facts

System
Linux kernel
Corpus path
drivers/of/address.c
Extension
.c
Size
30545 bytes
Lines
1171
Domain
Driver Families
Bucket
drivers/of
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct of_bus {
	const char	*name;
	const char	*addresses;
	int		(*match)(struct device_node *parent);
	void		(*count_cells)(struct device_node *child,
				       int *addrc, int *sizec);
	u64		(*map)(__be32 *addr, const __be32 *range,
				int na, int ns, int pna, int fna);
	int		(*translate)(__be32 *addr, u64 offset, int na);
	int		flag_cells;
	unsigned int	(*get_flags)(const __be32 *addr);
};

/*
 * Default translator (generic bus)
 */

static void of_bus_default_count_cells(struct device_node *dev,
				       int *addrc, int *sizec)
{
	if (addrc)
		*addrc = of_n_addr_cells(dev);
	if (sizec)
		*sizec = of_n_size_cells(dev);
}

static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
		int na, int ns, int pna, int fna)
{
	u64 cp, s, da;

	cp = of_read_number(range + fna, na - fna);
	s  = of_read_number(range + na + pna, ns);
	da = of_read_number(addr + fna, na - fna);

	pr_debug("default map, cp=%llx, s=%llx, da=%llx\n", cp, s, da);

	if (da < cp || da >= (cp + s))
		return OF_BAD_ADDR;
	return da - cp;
}

static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
{
	u64 a = of_read_number(addr, na);
	memset(addr, 0, na * 4);
	a += offset;
	if (na > 1)
		addr[na - 2] = cpu_to_be32(a >> 32);
	addr[na - 1] = cpu_to_be32(a & 0xffffffffu);

	return 0;
}

static unsigned int of_bus_default_flags_get_flags(const __be32 *addr)
{
	return of_read_number(addr, 1);
}

static unsigned int of_bus_default_get_flags(const __be32 *addr)
{
	return IORESOURCE_MEM;
}

static u64 of_bus_default_flags_map(__be32 *addr, const __be32 *range, int na,
				    int ns, int pna, int fna)
{
	/* Check that flags match */
	if (*addr != *range)
		return OF_BAD_ADDR;

	return of_bus_default_map(addr, range, na, ns, pna, fna);
}

static int of_bus_default_flags_translate(__be32 *addr, u64 offset, int na)
{
	/* Keep "flags" part (high cell) in translated address */
	return of_bus_default_translate(addr + 1, offset, na - 1);
}

#ifdef CONFIG_PCI
static unsigned int of_bus_pci_get_flags(const __be32 *addr)
{
	unsigned int flags = 0;
	u32 w = be32_to_cpup(addr);

	if (!IS_ENABLED(CONFIG_PCI))
		return 0;

	switch((w >> 24) & 0x03) {

Annotation

Implementation Notes