root/arch/sparc/kernel/prom_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prom_early_alloc
  2. sparc32_path_component
  3. sbus_path_component
  4. pci_path_component
  5. ebus_path_component
  6. ambapp_path_component
  7. __build_path_component
  8. build_path_component
  9. of_console_init
  10. of_fill_in_cpu_data
  11. irq_trans_init

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

/* [<][>][^][v][top][bottom][index][help] */