File Index
Files and directories
Sign in
FILE

prom_32.c

File preview with syntax highlighting.

linux-6.19.14/arch/sparc/kernel/prom_32.c C
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 * Procedures for creating, accessing and interpreting the device tree.
  4 *
  5 * Paul Mackerras	August 1996.
  6 * Copyright (C) 1996-2005 Paul Mackerras.
  7 * 
  8 *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
  9 *    {engebret|bergner}@us.ibm.com 
 10 *
 11 *  Adapted for sparc32 by David S. Miller davem@davemloft.net
 12 */
 13
 14#include <linux/kernel.h>
 15#include <linux/types.h>
 16#include <linux/string.h>
 17#include <linux/mm.h>
 18#include <linux/memblock.h>
 19
 20#include <asm/prom.h>
 21#include <asm/oplib.h>
 22#include <asm/leon.h>
 23#include <asm/leon_amba.h>
 24
 25#include "prom.h"
 26
 27void * __init prom_early_alloc(unsigned long size)
 28{
 29	void *ret;
 30
 31	ret = memblock_alloc_or_panic(size, SMP_CACHE_BYTES);
 32
 33	prom_early_allocated += size;
 34
 35	return ret;
 36}
 37
 38/* The following routines deal with the black magic of fully naming a
 39 * node.
 40 *
 41 * Certain well known named nodes are just the simple name string.
 42 *
 43 * Actual devices have an address specifier appended to the base name
 44 * string, like this "foo@addr".  The "addr" can be in any number of
 45 * formats, and the platform plus the type of the node determine the
 46 * format and how it is constructed.
 47 *
 48 * For children of the ROOT node, the naming convention is fixed and
 49 * determined by whether this is a sun4u or sun4v system.
 50 *
 51 * For children of other nodes, it is bus type specific.  So
 52 * we walk up the tree until we discover a "device_type" property
 53 * we recognize and we go from there.
 54 */
 55static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
 56{
 57	const char *name = of_get_property(dp, "name", NULL);
 58	struct linux_prom_registers *regs;
 59	struct property *rprop;
 60
 61	rprop = of_find_property(dp, "reg", NULL);
 62	if (!rprop)
 63		return;
 64
 65	regs = rprop->value;
 66	sprintf(tmp_buf, "%s@%x,%x",
 67		name,
 68		regs->which_io, regs->phys_addr);
 69}
 70
 71/* "name@slot,offset"  */
 72static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
 73{
 74	const char *name = of_get_property(dp, "name", NULL);
 75	struct linux_prom_registers *regs;
 76	struct property *prop;
 77
 78	prop = of_find_property(dp, "reg", NULL);
 79	if (!prop)
 80		return;
 81
 82	regs = prop->value;
 83	sprintf(tmp_buf, "%s@%x,%x",
 84		name,
 85		regs->which_io,
 86		regs->phys_addr);
 87}
 88
 89/* "name@devnum[,func]" */
 90static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
 91{
 92	const char *name = of_get_property(dp, "name", NULL);
 93	struct linux_prom_pci_registers *regs;
 94	struct property *prop;
 95	unsigned int devfn;
 96
 97	prop = of_find_property(dp, "reg", NULL);
 98	if (!prop)
 99		return;
100
101	regs = prop->value;
102	devfn = (regs->phys_hi >> 8) & 0xff;
103	if (devfn & 0x07) {
104		sprintf(tmp_buf, "%s@%x,%x",
105			name,
106			devfn >> 3,
107			devfn & 0x07);
108	} else {
109		sprintf(tmp_buf, "%s@%x",
110			name,
111			devfn >> 3);
112	}
113}
114
115/* "name@addrhi,addrlo" */
116static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
117{
118	const char *name = of_get_property(dp, "name", NULL);
119	struct linux_prom_registers *regs;
120	struct property *prop;
121
122	prop = of_find_property(dp, "reg", NULL);
123	if (!prop)
124		return;
125
126	regs = prop->value;
127
128	sprintf(tmp_buf, "%s@%x,%x",
129		name,
130		regs->which_io, regs->phys_addr);
131}
132
133/* "name@irq,addrlo" */
134static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
135{
136	const char *name = of_get_property(dp, "name", NULL);
137	struct amba_prom_registers *regs;
138	unsigned int *intr;
139	unsigned int reg0;
140	struct property *prop;
141	int interrupt = 0;
142
143	/* In order to get a unique ID in the device tree (multiple AMBA devices
144	 * may have the same name) the node number is printed
145	 */
146	prop = of_find_property(dp, "reg", NULL);
147	if (!prop) {
148		reg0 = (unsigned int)dp->phandle;
149	} else {
150		regs = prop->value;
151		reg0 = regs->phys_addr;
152	}
153
154	/* Not all cores have Interrupt */
155	prop = of_find_property(dp, "interrupts", NULL);
156	if (!prop)
157		intr = &interrupt; /* IRQ0 does not exist */
158	else
159		intr = prop->value;
160
161	sprintf(tmp_buf, "%s@%x,%x", name, *intr, reg0);
162}
163
164static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
165{
166	struct device_node *parent = dp->parent;
167
168	if (parent != NULL) {
169		if (of_node_is_type(parent, "pci") ||
170		    of_node_is_type(parent, "pciex"))
171			return pci_path_component(dp, tmp_buf);
172		if (of_node_is_type(parent, "sbus"))
173			return sbus_path_component(dp, tmp_buf);
174		if (of_node_is_type(parent, "ebus"))
175			return ebus_path_component(dp, tmp_buf);
176		if (of_node_is_type(parent, "ambapp"))
177			return ambapp_path_component(dp, tmp_buf);
178
179		/* "isa" is handled with platform naming */
180	}
181
182	/* Use platform naming convention.  */
183	return sparc32_path_component(dp, tmp_buf);
184}
185
186char * __init build_path_component(struct device_node *dp)
187{
188	const char *name = of_get_property(dp, "name", NULL);
189	char tmp_buf[64], *n;
190	size_t n_sz;
191
192	tmp_buf[0] = '\0';
193	__build_path_component(dp, tmp_buf);
194	if (tmp_buf[0] == '\0')
195		strscpy(tmp_buf, name);
196
197	n_sz = strlen(tmp_buf) + 1;
198	n = prom_early_alloc(n_sz);
199	strscpy(n, tmp_buf, n_sz);
200
201	return n;
202}
203
204extern void restore_current(void);
205
206void __init of_console_init(void)
207{
208	char *msg = "OF stdout device is: %s\n";
209	const size_t of_console_path_sz = 256;
210	struct device_node *dp;
211	unsigned long flags;
212	const char *type;
213	phandle node;
214	int skip, tmp, fd;
215
216	of_console_path = prom_early_alloc(of_console_path_sz);
217
218	switch (prom_vers) {
219	case PROM_V0:
220		skip = 0;
221		switch (*romvec->pv_stdout) {
222		case PROMDEV_SCREEN:
223			type = "display";
224			break;
225
226		case PROMDEV_TTYB:
227			skip = 1;
228			fallthrough;
229
230		case PROMDEV_TTYA:
231			type = "serial";
232			break;
233
234		default:
235			prom_printf("Invalid PROM_V0 stdout value %u\n",
236				    *romvec->pv_stdout);
237			prom_halt();
238		}
239
240		tmp = skip;
241		for_each_node_by_type(dp, type) {
242			if (!tmp--)
243				break;
244		}
245		if (!dp) {
246			prom_printf("Cannot find PROM_V0 console node.\n");
247			prom_halt();
248		}
249		of_console_device = dp;
250
251		sprintf(of_console_path, "%pOF", dp);
252		if (!strcmp(type, "serial")) {
253			strcat(of_console_path,
254			       (skip ? ":b" : ":a"));
255		}
256		break;
257
258	default:
259	case PROM_V2:
260	case PROM_V3:
261		fd = *romvec->pv_v2bootargs.fd_stdout;
262
263		spin_lock_irqsave(&prom_lock, flags);
264		node = (*romvec->pv_v2devops.v2_inst2pkg)(fd);
265		restore_current();
266		spin_unlock_irqrestore(&prom_lock, flags);
267
268		if (!node) {
269			prom_printf("Cannot resolve stdout node from "
270				    "instance %08x.\n", fd);
271			prom_halt();
272		}
273		dp = of_find_node_by_phandle(node);
274
275		if (!of_node_is_type(dp, "display") &&
276		    !of_node_is_type(dp, "serial")) {
277			prom_printf("Console device_type is neither display "
278				    "nor serial.\n");
279			prom_halt();
280		}
281
282		of_console_device = dp;
283
284		if (prom_vers == PROM_V2) {
285			sprintf(of_console_path, "%pOF", dp);
286			switch (*romvec->pv_stdout) {
287			case PROMDEV_TTYA:
288				strcat(of_console_path, ":a");
289				break;
290			case PROMDEV_TTYB:
291				strcat(of_console_path, ":b");
292				break;
293			}
294		} else {
295			const char *path;
296
297			dp = of_find_node_by_path("/");
298			path = of_get_property(dp, "stdout-path", NULL);
299			if (!path) {
300				prom_printf("No stdout-path in root node.\n");
301				prom_halt();
302			}
303			strscpy(of_console_path, path, of_console_path_sz);
304		}
305		break;
306	}
307
308	of_console_options = strrchr(of_console_path, ':');
309	if (of_console_options) {
310		of_console_options++;
311		if (*of_console_options == '\0')
312			of_console_options = NULL;
313	}
314
315	printk(msg, of_console_path);
316}
317
318void __init of_fill_in_cpu_data(void)
319{
320}
321
322void __init irq_trans_init(struct device_node *dp)
323{
324}
~/ Read-only file preview.