drivers/of/fdt_address.c

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

File Facts

System
Linux kernel
Corpus path
drivers/of/fdt_address.c
Extension
.c
Size
5937 bytes
Lines
237
Domain
Driver Families
Bucket
drivers/of
Inferred role
Driver Families: implementation source
Status
source 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 {
	void		(*count_cells)(const void *blob, int parentoffset,
				int *addrc, int *sizec);
	u64		(*map)(__be32 *addr, const __be32 *range,
				int na, int ns, int pna);
	int		(*translate)(__be32 *addr, u64 offset, int na);
};

/* Default translator (generic bus) */
static void __init fdt_bus_default_count_cells(const void *blob, int parentoffset,
					       int *addrc, int *sizec)
{
	const __be32 *prop;

	if (addrc) {
		prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
		if (prop)
			*addrc = be32_to_cpup(prop);
		else
			*addrc = -1;
	}

	if (sizec) {
		prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
		if (prop)
			*sizec = be32_to_cpup(prop);
		else
			*sizec = -1;
	}
}

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

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

	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 __init fdt_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_fdt32(a >> 32);
	addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu);

	return 0;
}

/* Array of bus specific translators */
static const struct of_bus of_busses[] __initconst = {
	/* Default */
	{
		.count_cells = fdt_bus_default_count_cells,
		.map = fdt_bus_default_map,
		.translate = fdt_bus_default_translate,
	},
};

static int __init fdt_translate_one(const void *blob, int parent,
				    const struct of_bus *bus,
				    const struct of_bus *pbus, __be32 *addr,
				    int na, int ns, int pna, const char *rprop)
{
	const __be32 *ranges;
	int rlen;
	int rone;
	u64 offset = OF_BAD_ADDR;

	ranges = fdt_getprop(blob, parent, rprop, &rlen);
	if (!ranges)
		return 1;
	if (rlen == 0) {
		offset = of_read_number(addr, na);
		memset(addr, 0, pna * 4);
		pr_debug("empty ranges, 1:1 translation\n");
		goto finish;
	}

Annotation

Implementation Notes