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