Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Procedures for creating, accessing and interpreting the device tree.
0004  *
0005  * Paul Mackerras   August 1996.
0006  * Copyright (C) 1996-2005 Paul Mackerras.
0007  * 
0008  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
0009  *    {engebret|bergner}@us.ibm.com 
0010  *
0011  *  Adapted for sparc32 by David S. Miller davem@davemloft.net
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/types.h>
0016 #include <linux/string.h>
0017 #include <linux/mm.h>
0018 #include <linux/memblock.h>
0019 
0020 #include <asm/prom.h>
0021 #include <asm/oplib.h>
0022 #include <asm/leon.h>
0023 #include <asm/leon_amba.h>
0024 
0025 #include "prom.h"
0026 
0027 void * __init prom_early_alloc(unsigned long size)
0028 {
0029     void *ret;
0030 
0031     ret = memblock_alloc(size, SMP_CACHE_BYTES);
0032     if (!ret)
0033         panic("%s: Failed to allocate %lu bytes\n", __func__, size);
0034 
0035     prom_early_allocated += size;
0036 
0037     return ret;
0038 }
0039 
0040 /* The following routines deal with the black magic of fully naming a
0041  * node.
0042  *
0043  * Certain well known named nodes are just the simple name string.
0044  *
0045  * Actual devices have an address specifier appended to the base name
0046  * string, like this "foo@addr".  The "addr" can be in any number of
0047  * formats, and the platform plus the type of the node determine the
0048  * format and how it is constructed.
0049  *
0050  * For children of the ROOT node, the naming convention is fixed and
0051  * determined by whether this is a sun4u or sun4v system.
0052  *
0053  * For children of other nodes, it is bus type specific.  So
0054  * we walk up the tree until we discover a "device_type" property
0055  * we recognize and we go from there.
0056  */
0057 static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
0058 {
0059     const char *name = of_get_property(dp, "name", NULL);
0060     struct linux_prom_registers *regs;
0061     struct property *rprop;
0062 
0063     rprop = of_find_property(dp, "reg", NULL);
0064     if (!rprop)
0065         return;
0066 
0067     regs = rprop->value;
0068     sprintf(tmp_buf, "%s@%x,%x",
0069         name,
0070         regs->which_io, regs->phys_addr);
0071 }
0072 
0073 /* "name@slot,offset"  */
0074 static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
0075 {
0076     const char *name = of_get_property(dp, "name", NULL);
0077     struct linux_prom_registers *regs;
0078     struct property *prop;
0079 
0080     prop = of_find_property(dp, "reg", NULL);
0081     if (!prop)
0082         return;
0083 
0084     regs = prop->value;
0085     sprintf(tmp_buf, "%s@%x,%x",
0086         name,
0087         regs->which_io,
0088         regs->phys_addr);
0089 }
0090 
0091 /* "name@devnum[,func]" */
0092 static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
0093 {
0094     const char *name = of_get_property(dp, "name", NULL);
0095     struct linux_prom_pci_registers *regs;
0096     struct property *prop;
0097     unsigned int devfn;
0098 
0099     prop = of_find_property(dp, "reg", NULL);
0100     if (!prop)
0101         return;
0102 
0103     regs = prop->value;
0104     devfn = (regs->phys_hi >> 8) & 0xff;
0105     if (devfn & 0x07) {
0106         sprintf(tmp_buf, "%s@%x,%x",
0107             name,
0108             devfn >> 3,
0109             devfn & 0x07);
0110     } else {
0111         sprintf(tmp_buf, "%s@%x",
0112             name,
0113             devfn >> 3);
0114     }
0115 }
0116 
0117 /* "name@addrhi,addrlo" */
0118 static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
0119 {
0120     const char *name = of_get_property(dp, "name", NULL);
0121     struct linux_prom_registers *regs;
0122     struct property *prop;
0123 
0124     prop = of_find_property(dp, "reg", NULL);
0125     if (!prop)
0126         return;
0127 
0128     regs = prop->value;
0129 
0130     sprintf(tmp_buf, "%s@%x,%x",
0131         name,
0132         regs->which_io, regs->phys_addr);
0133 }
0134 
0135 /* "name@irq,addrlo" */
0136 static void __init ambapp_path_component(struct device_node *dp, char *tmp_buf)
0137 {
0138     const char *name = of_get_property(dp, "name", NULL);
0139     struct amba_prom_registers *regs;
0140     unsigned int *intr;
0141     unsigned int reg0;
0142     struct property *prop;
0143     int interrupt = 0;
0144 
0145     /* In order to get a unique ID in the device tree (multiple AMBA devices
0146      * may have the same name) the node number is printed
0147      */
0148     prop = of_find_property(dp, "reg", NULL);
0149     if (!prop) {
0150         reg0 = (unsigned int)dp->phandle;
0151     } else {
0152         regs = prop->value;
0153         reg0 = regs->phys_addr;
0154     }
0155 
0156     /* Not all cores have Interrupt */
0157     prop = of_find_property(dp, "interrupts", NULL);
0158     if (!prop)
0159         intr = &interrupt; /* IRQ0 does not exist */
0160     else
0161         intr = prop->value;
0162 
0163     sprintf(tmp_buf, "%s@%x,%x", name, *intr, reg0);
0164 }
0165 
0166 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
0167 {
0168     struct device_node *parent = dp->parent;
0169 
0170     if (parent != NULL) {
0171         if (of_node_is_type(parent, "pci") ||
0172             of_node_is_type(parent, "pciex"))
0173             return pci_path_component(dp, tmp_buf);
0174         if (of_node_is_type(parent, "sbus"))
0175             return sbus_path_component(dp, tmp_buf);
0176         if (of_node_is_type(parent, "ebus"))
0177             return ebus_path_component(dp, tmp_buf);
0178         if (of_node_is_type(parent, "ambapp"))
0179             return ambapp_path_component(dp, tmp_buf);
0180 
0181         /* "isa" is handled with platform naming */
0182     }
0183 
0184     /* Use platform naming convention.  */
0185     return sparc32_path_component(dp, tmp_buf);
0186 }
0187 
0188 char * __init build_path_component(struct device_node *dp)
0189 {
0190     const char *name = of_get_property(dp, "name", NULL);
0191     char tmp_buf[64], *n;
0192 
0193     tmp_buf[0] = '\0';
0194     __build_path_component(dp, tmp_buf);
0195     if (tmp_buf[0] == '\0')
0196         strcpy(tmp_buf, name);
0197 
0198     n = prom_early_alloc(strlen(tmp_buf) + 1);
0199     strcpy(n, tmp_buf);
0200 
0201     return n;
0202 }
0203 
0204 extern void restore_current(void);
0205 
0206 void __init of_console_init(void)
0207 {
0208     char *msg = "OF stdout device is: %s\n";
0209     struct device_node *dp;
0210     unsigned long flags;
0211     const char *type;
0212     phandle node;
0213     int skip, tmp, fd;
0214 
0215     of_console_path = prom_early_alloc(256);
0216 
0217     switch (prom_vers) {
0218     case PROM_V0:
0219         skip = 0;
0220         switch (*romvec->pv_stdout) {
0221         case PROMDEV_SCREEN:
0222             type = "display";
0223             break;
0224 
0225         case PROMDEV_TTYB:
0226             skip = 1;
0227             fallthrough;
0228 
0229         case PROMDEV_TTYA:
0230             type = "serial";
0231             break;
0232 
0233         default:
0234             prom_printf("Invalid PROM_V0 stdout value %u\n",
0235                     *romvec->pv_stdout);
0236             prom_halt();
0237         }
0238 
0239         tmp = skip;
0240         for_each_node_by_type(dp, type) {
0241             if (!tmp--)
0242                 break;
0243         }
0244         if (!dp) {
0245             prom_printf("Cannot find PROM_V0 console node.\n");
0246             prom_halt();
0247         }
0248         of_console_device = dp;
0249 
0250         sprintf(of_console_path, "%pOF", dp);
0251         if (!strcmp(type, "serial")) {
0252             strcat(of_console_path,
0253                    (skip ? ":b" : ":a"));
0254         }
0255         break;
0256 
0257     default:
0258     case PROM_V2:
0259     case PROM_V3:
0260         fd = *romvec->pv_v2bootargs.fd_stdout;
0261 
0262         spin_lock_irqsave(&prom_lock, flags);
0263         node = (*romvec->pv_v2devops.v2_inst2pkg)(fd);
0264         restore_current();
0265         spin_unlock_irqrestore(&prom_lock, flags);
0266 
0267         if (!node) {
0268             prom_printf("Cannot resolve stdout node from "
0269                     "instance %08x.\n", fd);
0270             prom_halt();
0271         }
0272         dp = of_find_node_by_phandle(node);
0273 
0274         if (!of_node_is_type(dp, "display") &&
0275             !of_node_is_type(dp, "serial")) {
0276             prom_printf("Console device_type is neither display "
0277                     "nor serial.\n");
0278             prom_halt();
0279         }
0280 
0281         of_console_device = dp;
0282 
0283         if (prom_vers == PROM_V2) {
0284             sprintf(of_console_path, "%pOF", dp);
0285             switch (*romvec->pv_stdout) {
0286             case PROMDEV_TTYA:
0287                 strcat(of_console_path, ":a");
0288                 break;
0289             case PROMDEV_TTYB:
0290                 strcat(of_console_path, ":b");
0291                 break;
0292             }
0293         } else {
0294             const char *path;
0295 
0296             dp = of_find_node_by_path("/");
0297             path = of_get_property(dp, "stdout-path", NULL);
0298             if (!path) {
0299                 prom_printf("No stdout-path in root node.\n");
0300                 prom_halt();
0301             }
0302             strcpy(of_console_path, path);
0303         }
0304         break;
0305     }
0306 
0307     of_console_options = strrchr(of_console_path, ':');
0308     if (of_console_options) {
0309         of_console_options++;
0310         if (*of_console_options == '\0')
0311             of_console_options = NULL;
0312     }
0313 
0314     printk(msg, of_console_path);
0315 }
0316 
0317 void __init of_fill_in_cpu_data(void)
0318 {
0319 }
0320 
0321 void __init irq_trans_init(struct device_node *dp)
0322 {
0323 }