linux/arch/microblaze/kernel/prom.c
<<
>>
Prefs
   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 *      This program is free software; you can redistribute it and/or
  11 *      modify it under the terms of the GNU General Public License
  12 *      as published by the Free Software Foundation; either version
  13 *      2 of the License, or (at your option) any later version.
  14 */
  15
  16#include <stdarg.h>
  17#include <linux/kernel.h>
  18#include <linux/string.h>
  19#include <linux/init.h>
  20#include <linux/threads.h>
  21#include <linux/spinlock.h>
  22#include <linux/types.h>
  23#include <linux/pci.h>
  24#include <linux/stringify.h>
  25#include <linux/delay.h>
  26#include <linux/initrd.h>
  27#include <linux/bitops.h>
  28#include <linux/module.h>
  29#include <linux/kexec.h>
  30#include <linux/debugfs.h>
  31#include <linux/irq.h>
  32#include <linux/lmb.h>
  33
  34#include <asm/prom.h>
  35#include <asm/page.h>
  36#include <asm/processor.h>
  37#include <asm/irq.h>
  38#include <linux/io.h>
  39#include <asm/system.h>
  40#include <asm/mmu.h>
  41#include <asm/pgtable.h>
  42#include <asm/sections.h>
  43#include <asm/pci-bridge.h>
  44
  45static int __initdata dt_root_addr_cells;
  46static int __initdata dt_root_size_cells;
  47
  48typedef u32 cell_t;
  49
  50static struct boot_param_header *initial_boot_params;
  51
  52/* export that to outside world */
  53struct device_node *of_chosen;
  54
  55static inline char *find_flat_dt_string(u32 offset)
  56{
  57        return ((char *)initial_boot_params) +
  58                initial_boot_params->off_dt_strings + offset;
  59}
  60
  61/**
  62 * This function is used to scan the flattened device-tree, it is
  63 * used to extract the memory informations at boot before we can
  64 * unflatten the tree
  65 */
  66int __init of_scan_flat_dt(int (*it)(unsigned long node,
  67                                     const char *uname, int depth,
  68                                     void *data),
  69                           void *data)
  70{
  71        unsigned long p = ((unsigned long)initial_boot_params) +
  72                initial_boot_params->off_dt_struct;
  73        int rc = 0;
  74        int depth = -1;
  75
  76        do {
  77                u32 tag = *((u32 *)p);
  78                char *pathp;
  79
  80                p += 4;
  81                if (tag == OF_DT_END_NODE) {
  82                        depth--;
  83                        continue;
  84                }
  85                if (tag == OF_DT_NOP)
  86                        continue;
  87                if (tag == OF_DT_END)
  88                        break;
  89                if (tag == OF_DT_PROP) {
  90                        u32 sz = *((u32 *)p);
  91                        p += 8;
  92                        if (initial_boot_params->version < 0x10)
  93                                p = _ALIGN(p, sz >= 8 ? 8 : 4);
  94                        p += sz;
  95                        p = _ALIGN(p, 4);
  96                        continue;
  97                }
  98                if (tag != OF_DT_BEGIN_NODE) {
  99                        printk(KERN_WARNING "Invalid tag %x scanning flattened"
 100                                " device tree !\n", tag);
 101                        return -EINVAL;
 102                }
 103                depth++;
 104                pathp = (char *)p;
 105                p = _ALIGN(p + strlen(pathp) + 1, 4);
 106                if ((*pathp) == '/') {
 107                        char *lp, *np;
 108                        for (lp = NULL, np = pathp; *np; np++)
 109                                if ((*np) == '/')
 110                                        lp = np+1;
 111                        if (lp != NULL)
 112                                pathp = lp;
 113                }
 114                rc = it(p, pathp, depth, data);
 115                if (rc != 0)
 116                        break;
 117        } while (1);
 118
 119        return rc;
 120}
 121
 122unsigned long __init of_get_flat_dt_root(void)
 123{
 124        unsigned long p = ((unsigned long)initial_boot_params) +
 125                initial_boot_params->off_dt_struct;
 126
 127        while (*((u32 *)p) == OF_DT_NOP)
 128                p += 4;
 129        BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE);
 130        p += 4;
 131        return _ALIGN(p + strlen((char *)p) + 1, 4);
 132}
 133
 134/**
 135 * This function can be used within scan_flattened_dt callback to get
 136 * access to properties
 137 */
 138void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
 139                                unsigned long *size)
 140{
 141        unsigned long p = node;
 142
 143        do {
 144                u32 tag = *((u32 *)p);
 145                u32 sz, noff;
 146                const char *nstr;
 147
 148                p += 4;
 149                if (tag == OF_DT_NOP)
 150                        continue;
 151                if (tag != OF_DT_PROP)
 152                        return NULL;
 153
 154                sz = *((u32 *)p);
 155                noff = *((u32 *)(p + 4));
 156                p += 8;
 157                if (initial_boot_params->version < 0x10)
 158                        p = _ALIGN(p, sz >= 8 ? 8 : 4);
 159
 160                nstr = find_flat_dt_string(noff);
 161                if (nstr == NULL) {
 162                        printk(KERN_WARNING "Can't find property index"
 163                                " name !\n");
 164                        return NULL;
 165                }
 166                if (strcmp(name, nstr) == 0) {
 167                        if (size)
 168                                *size = sz;
 169                        return (void *)p;
 170                }
 171                p += sz;
 172                p = _ALIGN(p, 4);
 173        } while (1);
 174}
 175
 176int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
 177{
 178        const char *cp;
 179        unsigned long cplen, l;
 180
 181        cp = of_get_flat_dt_prop(node, "compatible", &cplen);
 182        if (cp == NULL)
 183                return 0;
 184        while (cplen > 0) {
 185                if (strncasecmp(cp, compat, strlen(compat)) == 0)
 186                        return 1;
 187                l = strlen(cp) + 1;
 188                cp += l;
 189                cplen -= l;
 190        }
 191
 192        return 0;
 193}
 194
 195static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
 196                                        unsigned long align)
 197{
 198        void *res;
 199
 200        *mem = _ALIGN(*mem, align);
 201        res = (void *)*mem;
 202        *mem += size;
 203
 204        return res;
 205}
 206
 207static unsigned long __init unflatten_dt_node(unsigned long mem,
 208                                        unsigned long *p,
 209                                        struct device_node *dad,
 210                                        struct device_node ***allnextpp,
 211                                        unsigned long fpsize)
 212{
 213        struct device_node *np;
 214        struct property *pp, **prev_pp = NULL;
 215        char *pathp;
 216        u32 tag;
 217        unsigned int l, allocl;
 218        int has_name = 0;
 219        int new_format = 0;
 220
 221        tag = *((u32 *)(*p));
 222        if (tag != OF_DT_BEGIN_NODE) {
 223                printk("Weird tag at start of node: %x\n", tag);
 224                return mem;
 225        }
 226        *p += 4;
 227        pathp = (char *)*p;
 228        l = allocl = strlen(pathp) + 1;
 229        *p = _ALIGN(*p + l, 4);
 230
 231        /* version 0x10 has a more compact unit name here instead of the full
 232         * path. we accumulate the full path size using "fpsize", we'll rebuild
 233         * it later. We detect this because the first character of the name is
 234         * not '/'.
 235         */
 236        if ((*pathp) != '/') {
 237                new_format = 1;
 238                if (fpsize == 0) {
 239                        /* root node: special case. fpsize accounts for path
 240                         * plus terminating zero. root node only has '/', so
 241                         * fpsize should be 2, but we want to avoid the first
 242                         * level nodes to have two '/' so we use fpsize 1 here
 243                         */
 244                        fpsize = 1;
 245                        allocl = 2;
 246                } else {
 247                        /* account for '/' and path size minus terminal 0
 248                         * already in 'l'
 249                         */
 250                        fpsize += l;
 251                        allocl = fpsize;
 252                }
 253        }
 254
 255        np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
 256                                __alignof__(struct device_node));
 257        if (allnextpp) {
 258                memset(np, 0, sizeof(*np));
 259                np->full_name = ((char *)np) + sizeof(struct device_node);
 260                if (new_format) {
 261                        char *p2 = np->full_name;
 262                        /* rebuild full path for new format */
 263                        if (dad && dad->parent) {
 264                                strcpy(p2, dad->full_name);
 265#ifdef DEBUG
 266                                if ((strlen(p2) + l + 1) != allocl) {
 267                                        pr_debug("%s: p: %d, l: %d, a: %d\n",
 268                                                pathp, (int)strlen(p2),
 269                                                l, allocl);
 270                                }
 271#endif
 272                                p2 += strlen(p2);
 273                        }
 274                        *(p2++) = '/';
 275                        memcpy(p2, pathp, l);
 276                } else
 277                        memcpy(np->full_name, pathp, l);
 278                prev_pp = &np->properties;
 279                **allnextpp = np;
 280                *allnextpp = &np->allnext;
 281                if (dad != NULL) {
 282                        np->parent = dad;
 283                        /* we temporarily use the next field as `last_child'*/
 284                        if (dad->next == NULL)
 285                                dad->child = np;
 286                        else
 287                                dad->next->sibling = np;
 288                        dad->next = np;
 289                }
 290                kref_init(&np->kref);
 291        }
 292        while (1) {
 293                u32 sz, noff;
 294                char *pname;
 295
 296                tag = *((u32 *)(*p));
 297                if (tag == OF_DT_NOP) {
 298                        *p += 4;
 299                        continue;
 300                }
 301                if (tag != OF_DT_PROP)
 302                        break;
 303                *p += 4;
 304                sz = *((u32 *)(*p));
 305                noff = *((u32 *)((*p) + 4));
 306                *p += 8;
 307                if (initial_boot_params->version < 0x10)
 308                        *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
 309
 310                pname = find_flat_dt_string(noff);
 311                if (pname == NULL) {
 312                        printk(KERN_INFO
 313                                "Can't find property name in list !\n");
 314                        break;
 315                }
 316                if (strcmp(pname, "name") == 0)
 317                        has_name = 1;
 318                l = strlen(pname) + 1;
 319                pp = unflatten_dt_alloc(&mem, sizeof(struct property),
 320                                        __alignof__(struct property));
 321                if (allnextpp) {
 322                        if (strcmp(pname, "linux,phandle") == 0) {
 323                                np->node = *((u32 *)*p);
 324                                if (np->linux_phandle == 0)
 325                                        np->linux_phandle = np->node;
 326                        }
 327                        if (strcmp(pname, "ibm,phandle") == 0)
 328                                np->linux_phandle = *((u32 *)*p);
 329                        pp->name = pname;
 330                        pp->length = sz;
 331                        pp->value = (void *)*p;
 332                        *prev_pp = pp;
 333                        prev_pp = &pp->next;
 334                }
 335                *p = _ALIGN((*p) + sz, 4);
 336        }
 337        /* with version 0x10 we may not have the name property, recreate
 338         * it here from the unit name if absent
 339         */
 340        if (!has_name) {
 341                char *p1 = pathp, *ps = pathp, *pa = NULL;
 342                int sz;
 343
 344                while (*p1) {
 345                        if ((*p1) == '@')
 346                                pa = p1;
 347                        if ((*p1) == '/')
 348                                ps = p1 + 1;
 349                        p1++;
 350                }
 351                if (pa < ps)
 352                        pa = p1;
 353                sz = (pa - ps) + 1;
 354                pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
 355                                        __alignof__(struct property));
 356                if (allnextpp) {
 357                        pp->name = "name";
 358                        pp->length = sz;
 359                        pp->value = pp + 1;
 360                        *prev_pp = pp;
 361                        prev_pp = &pp->next;
 362                        memcpy(pp->value, ps, sz - 1);
 363                        ((char *)pp->value)[sz - 1] = 0;
 364                        pr_debug("fixed up name for %s -> %s\n", pathp,
 365                                (char *)pp->value);
 366                }
 367        }
 368        if (allnextpp) {
 369                *prev_pp = NULL;
 370                np->name = of_get_property(np, "name", NULL);
 371                np->type = of_get_property(np, "device_type", NULL);
 372
 373                if (!np->name)
 374                        np->name = "<NULL>";
 375                if (!np->type)
 376                        np->type = "<NULL>";
 377        }
 378        while (tag == OF_DT_BEGIN_NODE) {
 379                mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
 380                tag = *((u32 *)(*p));
 381        }
 382        if (tag != OF_DT_END_NODE) {
 383                printk(KERN_INFO "Weird tag at end of node: %x\n", tag);
 384                return mem;
 385        }
 386        *p += 4;
 387        return mem;
 388}
 389
 390/**
 391 * unflattens the device-tree passed by the firmware, creating the
 392 * tree of struct device_node. It also fills the "name" and "type"
 393 * pointers of the nodes so the normal device-tree walking functions
 394 * can be used (this used to be done by finish_device_tree)
 395 */
 396void __init unflatten_device_tree(void)
 397{
 398        unsigned long start, mem, size;
 399        struct device_node **allnextp = &allnodes;
 400
 401        pr_debug(" -> unflatten_device_tree()\n");
 402
 403        /* First pass, scan for size */
 404        start = ((unsigned long)initial_boot_params) +
 405                initial_boot_params->off_dt_struct;
 406        size = unflatten_dt_node(0, &start, NULL, NULL, 0);
 407        size = (size | 3) + 1;
 408
 409        pr_debug("  size is %lx, allocating...\n", size);
 410
 411        /* Allocate memory for the expanded device tree */
 412        mem = lmb_alloc(size + 4, __alignof__(struct device_node));
 413        mem = (unsigned long) __va(mem);
 414
 415        ((u32 *)mem)[size / 4] = 0xdeadbeef;
 416
 417        pr_debug("  unflattening %lx...\n", mem);
 418
 419        /* Second pass, do actual unflattening */
 420        start = ((unsigned long)initial_boot_params) +
 421                initial_boot_params->off_dt_struct;
 422        unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
 423        if (*((u32 *)start) != OF_DT_END)
 424                printk(KERN_WARNING "Weird tag at end of tree: %08x\n",
 425                        *((u32 *)start));
 426        if (((u32 *)mem)[size / 4] != 0xdeadbeef)
 427                printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
 428                        ((u32 *)mem)[size / 4]);
 429        *allnextp = NULL;
 430
 431        /* Get pointer to OF "/chosen" node for use everywhere */
 432        of_chosen = of_find_node_by_path("/chosen");
 433        if (of_chosen == NULL)
 434                of_chosen = of_find_node_by_path("/chosen@0");
 435
 436        pr_debug(" <- unflatten_device_tree()\n");
 437}
 438
 439#define early_init_dt_scan_drconf_memory(node) 0
 440
 441static int __init early_init_dt_scan_cpus(unsigned long node,
 442                                          const char *uname, int depth,
 443                                          void *data)
 444{
 445        static int logical_cpuid;
 446        char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 447        const u32 *intserv;
 448        int i, nthreads;
 449        int found = 0;
 450
 451        /* We are scanning "cpu" nodes only */
 452        if (type == NULL || strcmp(type, "cpu") != 0)
 453                return 0;
 454
 455        /* Get physical cpuid */
 456        intserv = of_get_flat_dt_prop(node, "reg", NULL);
 457        nthreads = 1;
 458
 459        /*
 460         * Now see if any of these threads match our boot cpu.
 461         * NOTE: This must match the parsing done in smp_setup_cpu_maps.
 462         */
 463        for (i = 0; i < nthreads; i++) {
 464                /*
 465                 * version 2 of the kexec param format adds the phys cpuid of
 466                 * booted proc.
 467                 */
 468                if (initial_boot_params && initial_boot_params->version >= 2) {
 469                        if (intserv[i] ==
 470                                        initial_boot_params->boot_cpuid_phys) {
 471                                found = 1;
 472                                break;
 473                        }
 474                } else {
 475                        /*
 476                         * Check if it's the boot-cpu, set it's hw index now,
 477                         * unfortunately this format did not support booting
 478                         * off secondary threads.
 479                         */
 480                        if (of_get_flat_dt_prop(node,
 481                                        "linux,boot-cpu", NULL) != NULL) {
 482                                found = 1;
 483                                break;
 484                        }
 485                }
 486
 487#ifdef CONFIG_SMP
 488                /* logical cpu id is always 0 on UP kernels */
 489                logical_cpuid++;
 490#endif
 491        }
 492
 493        if (found) {
 494                pr_debug("boot cpu: logical %d physical %d\n", logical_cpuid,
 495                        intserv[i]);
 496                boot_cpuid = logical_cpuid;
 497        }
 498
 499        return 0;
 500}
 501
 502#ifdef CONFIG_BLK_DEV_INITRD
 503static void __init early_init_dt_check_for_initrd(unsigned long node)
 504{
 505        unsigned long l;
 506        u32 *prop;
 507
 508        pr_debug("Looking for initrd properties... ");
 509
 510        prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
 511        if (prop) {
 512                initrd_start = (unsigned long)
 513                                        __va((u32)of_read_ulong(prop, l/4));
 514
 515                prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
 516                if (prop) {
 517                        initrd_end = (unsigned long)
 518                                        __va((u32)of_read_ulong(prop, 1/4));
 519                        initrd_below_start_ok = 1;
 520                } else {
 521                        initrd_start = 0;
 522                }
 523        }
 524
 525        pr_debug("initrd_start=0x%lx  initrd_end=0x%lx\n",
 526                                        initrd_start, initrd_end);
 527}
 528#else
 529static inline void early_init_dt_check_for_initrd(unsigned long node)
 530{
 531}
 532#endif /* CONFIG_BLK_DEV_INITRD */
 533
 534static int __init early_init_dt_scan_chosen(unsigned long node,
 535                                const char *uname, int depth, void *data)
 536{
 537        unsigned long l;
 538        char *p;
 539
 540        pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
 541
 542        if (depth != 1 ||
 543                (strcmp(uname, "chosen") != 0 &&
 544                                strcmp(uname, "chosen@0") != 0))
 545                return 0;
 546
 547#ifdef CONFIG_KEXEC
 548        lprop = (u64 *)of_get_flat_dt_prop(node,
 549                                "linux,crashkernel-base", NULL);
 550        if (lprop)
 551                crashk_res.start = *lprop;
 552
 553        lprop = (u64 *)of_get_flat_dt_prop(node,
 554                                "linux,crashkernel-size", NULL);
 555        if (lprop)
 556                crashk_res.end = crashk_res.start + *lprop - 1;
 557#endif
 558
 559        early_init_dt_check_for_initrd(node);
 560
 561        /* Retreive command line */
 562        p = of_get_flat_dt_prop(node, "bootargs", &l);
 563        if (p != NULL && l > 0)
 564                strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
 565
 566#ifdef CONFIG_CMDLINE
 567#ifndef CONFIG_CMDLINE_FORCE
 568        if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
 569#endif
 570                strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 571#endif /* CONFIG_CMDLINE */
 572
 573        pr_debug("Command line is: %s\n", cmd_line);
 574
 575        /* break now */
 576        return 1;
 577}
 578
 579static int __init early_init_dt_scan_root(unsigned long node,
 580                                const char *uname, int depth, void *data)
 581{
 582        u32 *prop;
 583
 584        if (depth != 0)
 585                return 0;
 586
 587        prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
 588        dt_root_size_cells = (prop == NULL) ? 1 : *prop;
 589        pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
 590
 591        prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
 592        dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
 593        pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
 594
 595        /* break now */
 596        return 1;
 597}
 598
 599static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
 600{
 601        cell_t *p = *cellp;
 602
 603        *cellp = p + s;
 604        return of_read_number(p, s);
 605}
 606
 607static int __init early_init_dt_scan_memory(unsigned long node,
 608                                const char *uname, int depth, void *data)
 609{
 610        char *type = of_get_flat_dt_prop(node, "device_type", NULL);
 611        cell_t *reg, *endp;
 612        unsigned long l;
 613
 614        /* Look for the ibm,dynamic-reconfiguration-memory node */
 615/*      if (depth == 1 &&
 616                strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
 617                return early_init_dt_scan_drconf_memory(node);
 618*/
 619        /* We are scanning "memory" nodes only */
 620        if (type == NULL) {
 621                /*
 622                 * The longtrail doesn't have a device_type on the
 623                 * /memory node, so look for the node called /memory@0.
 624                 */
 625                if (depth != 1 || strcmp(uname, "memory@0") != 0)
 626                        return 0;
 627        } else if (strcmp(type, "memory") != 0)
 628                return 0;
 629
 630        reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
 631        if (reg == NULL)
 632                reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
 633        if (reg == NULL)
 634                return 0;
 635
 636        endp = reg + (l / sizeof(cell_t));
 637
 638        pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
 639                uname, l, reg[0], reg[1], reg[2], reg[3]);
 640
 641        while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
 642                u64 base, size;
 643
 644                base = dt_mem_next_cell(dt_root_addr_cells, &reg);
 645                size = dt_mem_next_cell(dt_root_size_cells, &reg);
 646
 647                if (size == 0)
 648                        continue;
 649                pr_debug(" - %llx ,  %llx\n", (unsigned long long)base,
 650                        (unsigned long long)size);
 651
 652                lmb_add(base, size);
 653        }
 654        return 0;
 655}
 656
 657#ifdef CONFIG_PHYP_DUMP
 658/**
 659 * phyp_dump_calculate_reserve_size() - reserve variable boot area 5% or arg
 660 *
 661 * Function to find the largest size we need to reserve
 662 * during early boot process.
 663 *
 664 * It either looks for boot param and returns that OR
 665 * returns larger of 256 or 5% rounded down to multiples of 256MB.
 666 *
 667 */
 668static inline unsigned long phyp_dump_calculate_reserve_size(void)
 669{
 670        unsigned long tmp;
 671
 672        if (phyp_dump_info->reserve_bootvar)
 673                return phyp_dump_info->reserve_bootvar;
 674
 675        /* divide by 20 to get 5% of value */
 676        tmp = lmb_end_of_DRAM();
 677        do_div(tmp, 20);
 678
 679        /* round it down in multiples of 256 */
 680        tmp = tmp & ~0x0FFFFFFFUL;
 681
 682        return (tmp > PHYP_DUMP_RMR_END ? tmp : PHYP_DUMP_RMR_END);
 683}
 684
 685/**
 686 * phyp_dump_reserve_mem() - reserve all not-yet-dumped mmemory
 687 *
 688 * This routine may reserve memory regions in the kernel only
 689 * if the system is supported and a dump was taken in last
 690 * boot instance or if the hardware is supported and the
 691 * scratch area needs to be setup. In other instances it returns
 692 * without reserving anything. The memory in case of dump being
 693 * active is freed when the dump is collected (by userland tools).
 694 */
 695static void __init phyp_dump_reserve_mem(void)
 696{
 697        unsigned long base, size;
 698        unsigned long variable_reserve_size;
 699
 700        if (!phyp_dump_info->phyp_dump_configured) {
 701                printk(KERN_ERR "Phyp-dump not supported on this hardware\n");
 702                return;
 703        }
 704
 705        if (!phyp_dump_info->phyp_dump_at_boot) {
 706                printk(KERN_INFO "Phyp-dump disabled at boot time\n");
 707                return;
 708        }
 709
 710        variable_reserve_size = phyp_dump_calculate_reserve_size();
 711
 712        if (phyp_dump_info->phyp_dump_is_active) {
 713                /* Reserve *everything* above RMR.Area freed by userland tools*/
 714                base = variable_reserve_size;
 715                size = lmb_end_of_DRAM() - base;
 716
 717                /* XXX crashed_ram_end is wrong, since it may be beyond
 718                 * the memory_limit, it will need to be adjusted. */
 719                lmb_reserve(base, size);
 720
 721                phyp_dump_info->init_reserve_start = base;
 722                phyp_dump_info->init_reserve_size = size;
 723        } else {
 724                size = phyp_dump_info->cpu_state_size +
 725                        phyp_dump_info->hpte_region_size +
 726                        variable_reserve_size;
 727                base = lmb_end_of_DRAM() - size;
 728                lmb_reserve(base, size);
 729                phyp_dump_info->init_reserve_start = base;
 730                phyp_dump_info->init_reserve_size = size;
 731        }
 732}
 733#else
 734static inline void __init phyp_dump_reserve_mem(void) {}
 735#endif /* CONFIG_PHYP_DUMP  && CONFIG_PPC_RTAS */
 736
 737#ifdef CONFIG_EARLY_PRINTK
 738/* MS this is Microblaze specifig function */
 739static int __init early_init_dt_scan_serial(unsigned long node,
 740                                const char *uname, int depth, void *data)
 741{
 742        unsigned long l;
 743        char *p;
 744        int *addr;
 745
 746        pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
 747
 748/* find all serial nodes */
 749        if (strncmp(uname, "serial", 6) != 0)
 750                return 0;
 751
 752        early_init_dt_check_for_initrd(node);
 753
 754/* find compatible node with uartlite */
 755        p = of_get_flat_dt_prop(node, "compatible", &l);
 756        if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
 757                        (strncmp(p, "xlnx,opb-uartlite", 17) != 0))
 758                return 0;
 759
 760        addr = of_get_flat_dt_prop(node, "reg", &l);
 761        return *addr; /* return address */
 762}
 763
 764/* this function is looking for early uartlite console - Microblaze specific */
 765int __init early_uartlite_console(void)
 766{
 767        return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
 768}
 769#endif
 770
 771void __init early_init_devtree(void *params)
 772{
 773        pr_debug(" -> early_init_devtree(%p)\n", params);
 774
 775        /* Setup flat device-tree pointer */
 776        initial_boot_params = params;
 777
 778#ifdef CONFIG_PHYP_DUMP
 779        /* scan tree to see if dump occured during last boot */
 780        of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 781#endif
 782
 783        /* Retrieve various informations from the /chosen node of the
 784         * device-tree, including the platform type, initrd location and
 785         * size, TCE reserve, and more ...
 786         */
 787        of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
 788
 789        /* Scan memory nodes and rebuild LMBs */
 790        lmb_init();
 791        of_scan_flat_dt(early_init_dt_scan_root, NULL);
 792        of_scan_flat_dt(early_init_dt_scan_memory, NULL);
 793
 794        /* Save command line for /proc/cmdline and then parse parameters */
 795        strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
 796        parse_early_param();
 797
 798        lmb_analyze();
 799
 800        pr_debug("Phys. mem: %lx\n", (unsigned long) lmb_phys_mem_size());
 801
 802        pr_debug("Scanning CPUs ...\n");
 803
 804        /* Retreive CPU related informations from the flat tree
 805         * (altivec support, boot CPU ID, ...)
 806         */
 807        of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
 808
 809        pr_debug(" <- early_init_devtree()\n");
 810}
 811
 812/**
 813 * Indicates whether the root node has a given value in its
 814 * compatible property.
 815 */
 816int machine_is_compatible(const char *compat)
 817{
 818        struct device_node *root;
 819        int rc = 0;
 820
 821        root = of_find_node_by_path("/");
 822        if (root) {
 823                rc = of_device_is_compatible(root, compat);
 824                of_node_put(root);
 825        }
 826        return rc;
 827}
 828EXPORT_SYMBOL(machine_is_compatible);
 829
 830/*******
 831 *
 832 * New implementation of the OF "find" APIs, return a refcounted
 833 * object, call of_node_put() when done.  The device tree and list
 834 * are protected by a rw_lock.
 835 *
 836 * Note that property management will need some locking as well,
 837 * this isn't dealt with yet.
 838 *
 839 *******/
 840
 841/**
 842 *      of_find_node_by_phandle - Find a node given a phandle
 843 *      @handle:        phandle of the node to find
 844 *
 845 *      Returns a node pointer with refcount incremented, use
 846 *      of_node_put() on it when done.
 847 */
 848struct device_node *of_find_node_by_phandle(phandle handle)
 849{
 850        struct device_node *np;
 851
 852        read_lock(&devtree_lock);
 853        for (np = allnodes; np != NULL; np = np->allnext)
 854                if (np->linux_phandle == handle)
 855                        break;
 856        of_node_get(np);
 857        read_unlock(&devtree_lock);
 858        return np;
 859}
 860EXPORT_SYMBOL(of_find_node_by_phandle);
 861
 862/**
 863 *      of_find_all_nodes - Get next node in global list
 864 *      @prev:  Previous node or NULL to start iteration
 865 *              of_node_put() will be called on it
 866 *
 867 *      Returns a node pointer with refcount incremented, use
 868 *      of_node_put() on it when done.
 869 */
 870struct device_node *of_find_all_nodes(struct device_node *prev)
 871{
 872        struct device_node *np;
 873
 874        read_lock(&devtree_lock);
 875        np = prev ? prev->allnext : allnodes;
 876        for (; np != NULL; np = np->allnext)
 877                if (of_node_get(np))
 878                        break;
 879        of_node_put(prev);
 880        read_unlock(&devtree_lock);
 881        return np;
 882}
 883EXPORT_SYMBOL(of_find_all_nodes);
 884
 885/**
 886 *      of_node_get - Increment refcount of a node
 887 *      @node:  Node to inc refcount, NULL is supported to
 888 *              simplify writing of callers
 889 *
 890 *      Returns node.
 891 */
 892struct device_node *of_node_get(struct device_node *node)
 893{
 894        if (node)
 895                kref_get(&node->kref);
 896        return node;
 897}
 898EXPORT_SYMBOL(of_node_get);
 899
 900static inline struct device_node *kref_to_device_node(struct kref *kref)
 901{
 902        return container_of(kref, struct device_node, kref);
 903}
 904
 905/**
 906 *      of_node_release - release a dynamically allocated node
 907 *      @kref:  kref element of the node to be released
 908 *
 909 *      In of_node_put() this function is passed to kref_put()
 910 *      as the destructor.
 911 */
 912static void of_node_release(struct kref *kref)
 913{
 914        struct device_node *node = kref_to_device_node(kref);
 915        struct property *prop = node->properties;
 916
 917        /* We should never be releasing nodes that haven't been detached. */
 918        if (!of_node_check_flag(node, OF_DETACHED)) {
 919                printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n",
 920                        node->full_name);
 921                dump_stack();
 922                kref_init(&node->kref);
 923                return;
 924        }
 925
 926        if (!of_node_check_flag(node, OF_DYNAMIC))
 927                return;
 928
 929        while (prop) {
 930                struct property *next = prop->next;
 931                kfree(prop->name);
 932                kfree(prop->value);
 933                kfree(prop);
 934                prop = next;
 935
 936                if (!prop) {
 937                        prop = node->deadprops;
 938                        node->deadprops = NULL;
 939                }
 940        }
 941        kfree(node->full_name);
 942        kfree(node->data);
 943        kfree(node);
 944}
 945
 946/**
 947 *      of_node_put - Decrement refcount of a node
 948 *      @node:  Node to dec refcount, NULL is supported to
 949 *              simplify writing of callers
 950 *
 951 */
 952void of_node_put(struct device_node *node)
 953{
 954        if (node)
 955                kref_put(&node->kref, of_node_release);
 956}
 957EXPORT_SYMBOL(of_node_put);
 958
 959/*
 960 * Plug a device node into the tree and global list.
 961 */
 962void of_attach_node(struct device_node *np)
 963{
 964        unsigned long flags;
 965
 966        write_lock_irqsave(&devtree_lock, flags);
 967        np->sibling = np->parent->child;
 968        np->allnext = allnodes;
 969        np->parent->child = np;
 970        allnodes = np;
 971        write_unlock_irqrestore(&devtree_lock, flags);
 972}
 973
 974/*
 975 * "Unplug" a node from the device tree.  The caller must hold
 976 * a reference to the node.  The memory associated with the node
 977 * is not freed until its refcount goes to zero.
 978 */
 979void of_detach_node(struct device_node *np)
 980{
 981        struct device_node *parent;
 982        unsigned long flags;
 983
 984        write_lock_irqsave(&devtree_lock, flags);
 985
 986        parent = np->parent;
 987        if (!parent)
 988                goto out_unlock;
 989
 990        if (allnodes == np)
 991                allnodes = np->allnext;
 992        else {
 993                struct device_node *prev;
 994                for (prev = allnodes;
 995                     prev->allnext != np;
 996                     prev = prev->allnext)
 997                        ;
 998                prev->allnext = np->allnext;
 999        }
1000
1001        if (parent->child == np)
1002                parent->child = np->sibling;
1003        else {
1004                struct device_node *prevsib;
1005                for (prevsib = np->parent->child;
1006                     prevsib->sibling != np;
1007                     prevsib = prevsib->sibling)
1008                        ;
1009                prevsib->sibling = np->sibling;
1010        }
1011
1012        of_node_set_flag(np, OF_DETACHED);
1013
1014out_unlock:
1015        write_unlock_irqrestore(&devtree_lock, flags);
1016}
1017
1018/*
1019 * Add a property to a node
1020 */
1021int prom_add_property(struct device_node *np, struct property *prop)
1022{
1023        struct property **next;
1024        unsigned long flags;
1025
1026        prop->next = NULL;
1027        write_lock_irqsave(&devtree_lock, flags);
1028        next = &np->properties;
1029        while (*next) {
1030                if (strcmp(prop->name, (*next)->name) == 0) {
1031                        /* duplicate ! don't insert it */
1032                        write_unlock_irqrestore(&devtree_lock, flags);
1033                        return -1;
1034                }
1035                next = &(*next)->next;
1036        }
1037        *next = prop;
1038        write_unlock_irqrestore(&devtree_lock, flags);
1039
1040#ifdef CONFIG_PROC_DEVICETREE
1041        /* try to add to proc as well if it was initialized */
1042        if (np->pde)
1043                proc_device_tree_add_prop(np->pde, prop);
1044#endif /* CONFIG_PROC_DEVICETREE */
1045
1046        return 0;
1047}
1048
1049/*
1050 * Remove a property from a node.  Note that we don't actually
1051 * remove it, since we have given out who-knows-how-many pointers
1052 * to the data using get-property.  Instead we just move the property
1053 * to the "dead properties" list, so it won't be found any more.
1054 */
1055int prom_remove_property(struct device_node *np, struct property *prop)
1056{
1057        struct property **next;
1058        unsigned long flags;
1059        int found = 0;
1060
1061        write_lock_irqsave(&devtree_lock, flags);
1062        next = &np->properties;
1063        while (*next) {
1064                if (*next == prop) {
1065                        /* found the node */
1066                        *next = prop->next;
1067                        prop->next = np->deadprops;
1068                        np->deadprops = prop;
1069                        found = 1;
1070                        break;
1071                }
1072                next = &(*next)->next;
1073        }
1074        write_unlock_irqrestore(&devtree_lock, flags);
1075
1076        if (!found)
1077                return -ENODEV;
1078
1079#ifdef CONFIG_PROC_DEVICETREE
1080        /* try to remove the proc node as well */
1081        if (np->pde)
1082                proc_device_tree_remove_prop(np->pde, prop);
1083#endif /* CONFIG_PROC_DEVICETREE */
1084
1085        return 0;
1086}
1087
1088/*
1089 * Update a property in a node.  Note that we don't actually
1090 * remove it, since we have given out who-knows-how-many pointers
1091 * to the data using get-property.  Instead we just move the property
1092 * to the "dead properties" list, and add the new property to the
1093 * property list
1094 */
1095int prom_update_property(struct device_node *np,
1096                         struct property *newprop,
1097                         struct property *oldprop)
1098{
1099        struct property **next;
1100        unsigned long flags;
1101        int found = 0;
1102
1103        write_lock_irqsave(&devtree_lock, flags);
1104        next = &np->properties;
1105        while (*next) {
1106                if (*next == oldprop) {
1107                        /* found the node */
1108                        newprop->next = oldprop->next;
1109                        *next = newprop;
1110                        oldprop->next = np->deadprops;
1111                        np->deadprops = oldprop;
1112                        found = 1;
1113                        break;
1114                }
1115                next = &(*next)->next;
1116        }
1117        write_unlock_irqrestore(&devtree_lock, flags);
1118
1119        if (!found)
1120                return -ENODEV;
1121
1122#ifdef CONFIG_PROC_DEVICETREE
1123        /* try to add to proc as well if it was initialized */
1124        if (np->pde)
1125                proc_device_tree_update_prop(np->pde, newprop, oldprop);
1126#endif /* CONFIG_PROC_DEVICETREE */
1127
1128        return 0;
1129}
1130
1131#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
1132static struct debugfs_blob_wrapper flat_dt_blob;
1133
1134static int __init export_flat_device_tree(void)
1135{
1136        struct dentry *d;
1137
1138        flat_dt_blob.data = initial_boot_params;
1139        flat_dt_blob.size = initial_boot_params->totalsize;
1140
1141        d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
1142                                of_debugfs_root, &flat_dt_blob);
1143        if (!d)
1144                return 1;
1145
1146        return 0;
1147}
1148device_initcall(export_flat_device_tree);
1149#endif
1150
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.