aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu/mpc85xx/portals.c
blob: 782874d79d7ccf836a2647ff2c85c84f15efe68f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright 2008-2011 Freescale Semiconductor, Inc.
 */

#include <linux/libfdt.h>
#include <fdt_support.h>

#include <asm/processor.h>
#include <asm/io.h>

#include <asm/fsl_portals.h>
#include <asm/fsl_liodn.h>

/* Update portal containter to match LAW setup of portal in phy map */
void fdt_portal(void *blob, const char *compat, const char *container,
			u64 addr, u32 size)
{
	int off;

	off = fdt_node_offset_by_compatible(blob, -1, compat);
	if (off < 0)
		return;

	off = fdt_parent_offset(blob, off);
	/* if non-zero assume we have a container */
	if (off > 0) {
		char buf[60];
		const char *p, *name;
		u32 *range;
		int len;

		/* fixup ranges */
		range = fdt_getprop_w(blob, off, "ranges", &len);
		if (range == NULL) {
			printf("ERROR: container for %s has no ranges", compat);
			return;
		}

		range[0] = 0;
		if (len == 16) {
			range[1] = addr >> 32;
			range[2] = addr & 0xffffffff;
			range[3] = size;
		} else {
			range[1] = addr & 0xffffffff;
			range[2] = size;
		}
		fdt_setprop_inplace(blob, off, "ranges", range, len);

		/* fixup the name */
		name = fdt_get_name(blob, off, &len);
		p = memchr(name, '@', len);

		if (p)
			len = p - name;

		/* if we are given a container name check it
		 * against what we found, if it doesnt match exit out */
		if (container && (memcmp(container, name, len))) {
			printf("WARNING: container names didn't match %s %s\n",
				container, name);
			return;
		}

		memcpy(&buf, name, len);
		len += sprintf(&buf[len], "@%llx", addr);
		fdt_set_name(blob, off, buf);
		return;
	}

	printf("ERROR: %s isn't in a container.  Not supported\n", compat);
}