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