Merge tag 'devicetree-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Jun 2014 17:02:38 +0000 (10:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Jun 2014 17:02:38 +0000 (10:02 -0700)
Pull DeviceTree updates from Rob Herring:
 - Another round of clean-up of FDT related code in architecture code.
   This removes knowledge of internal FDT details from most
   architectures except powerpc.
 - Conversion of kernel's custom FDT parsing code to use libfdt.
 - DT based initialization for generic serial earlycon.  The
   introduction of generic serial earlycon support went in through the
   tty tree.
 - Improve the platform device naming for DT probed devices to ensure
   unique naming and use parent names instead of a global index.
 - Fix a race condition in of_update_property.
 - Unify the various linker section OF match tables and fix several
   function prototype errors.
 - Update platform_get_irq_byname to work in deferred probe cases.
 - 2 binding doc updates

* tag 'devicetree-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (58 commits)
  of: handle NULL node in next_child iterators
  of/irq: provide more wrappers for !CONFIG_OF
  devicetree: bindings: Document micrel vendor prefix
  dt: bindings: dwc2: fix required value for the phy-names property
  of_pci_irq: kill useless variable in of_irq_parse_pci()
  of/irq: do irq resolution in platform_get_irq_byname()
  of: Add a testcase for of_find_node_by_path()
  of: Make of_find_node_by_path() handle /aliases
  of: Create unlocked version of for_each_child_of_node()
  lib: add glibc style strchrnul() variant
  of: Handle memory@0 node on PPC32 only
  pci/of: Remove dead code
  of: fix race between search and remove in of_update_property()
  of: Use NULL for pointers
  of: Stop naming platform_device using dcr address
  of: Ensure unique names without sacrificing determinism
  tty/serial: pl011: add DT based earlycon support
  of/fdt: add FDT serial scanning for earlycon
  of/fdt: add FDT address translation support
  serial: earlycon: add DT support
  ...

1  2 
Documentation/devicetree/bindings/vendor-prefixes.txt
arch/arm/mach-exynos/exynos.c
arch/powerpc/kernel/epapr_paravirt.c
arch/powerpc/mm/hash_utils_64.c
drivers/of/base.c
drivers/of/platform.c
include/linux/clk-provider.h
include/linux/of.h

@@@ -13,7 -13,6 +13,7 @@@ allwinner     Allwinner Technology Co., Ltd
  altr  Altera Corp.
  amcc  Applied Micro Circuits Corporation (APM, formally AMCC)
  amd   Advanced Micro Devices (AMD), Inc.
 +ams   AMS AG
  amstaos       AMS-Taos Inc.
  apm   Applied Micro Circuits Corporation (APM)
  arm   ARM Ltd.
@@@ -74,14 -73,13 +74,15 @@@ lantiq     Lantiq Semiconducto
  lg    LG Corporation
  linux Linux-specific binding
  lsi   LSI Corp. (LSI Logic)
 +lltc  Linear Technology Corporation
  marvell       Marvell Technology Group Ltd.
  maxim Maxim Integrated Products
+ micrel        Micrel Inc.
  microchip     Microchip Technology Inc.
  mosaixtech    Mosaix Technologies, Inc.
  moxa  Moxa
  mpl   MPL AG
 +mundoreader   Mundo Reader S.L.
  mxicy Macronix International Co., Ltd.
  national      National Semiconductor
  neonode               Neonode Inc.
@@@ -101,7 -99,6 +102,7 @@@ powervr     PowerVR (deprecated, use img
  qca   Qualcomm Atheros, Inc.
  qcom  Qualcomm Technologies, Inc
  qnap  QNAP Systems, Inc.
 +radxa Radxa
  raidsonic     RaidSonic Technology GmbH
  ralink        Mediatek/Ralink Technology Corp.
  ramtron       Ramtron International
@@@ -127,12 -124,10 +128,12 @@@ stericsson      ST-Ericsso
  synology      Synology, Inc.
  ti    Texas Instruments
  tlm   Trusted Logic Mobility
 +toradex       Toradex AG
  toshiba       Toshiba Corporation
  toumaz        Toumaz
  usi   Universal Scientifc Industrial Co., Ltd.
  v3    V3 Semiconductor
 +variscite     Variscite Ltd.
  via   VIA Technologies, Inc.
  voipac        Voipac Technologies s.r.o.
  winbond Winbond Electronics corp.
@@@ -26,6 -26,8 +26,6 @@@
  #include <asm/mach/map.h>
  #include <asm/memory.h>
  
 -#include <plat/cpu.h>
 -
  #include "common.h"
  #include "mfc.h"
  #include "regs-pmu.h"
@@@ -112,6 -114,51 +112,6 @@@ static struct map_desc exynos4_iodesc[
        },
  };
  
 -static struct map_desc exynos4_iodesc0[] __initdata = {
 -      {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM,
 -              .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      },
 -};
 -
 -static struct map_desc exynos4_iodesc1[] __initdata = {
 -      {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM,
 -              .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      },
 -};
 -
 -static struct map_desc exynos4210_iodesc[] __initdata = {
 -      {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
 -              .pfn            = __phys_to_pfn(EXYNOS4210_PA_SYSRAM_NS),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      },
 -};
 -
 -static struct map_desc exynos4x12_iodesc[] __initdata = {
 -      {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
 -              .pfn            = __phys_to_pfn(EXYNOS4x12_PA_SYSRAM_NS),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      },
 -};
 -
 -static struct map_desc exynos5250_iodesc[] __initdata = {
 -      {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM_NS,
 -              .pfn            = __phys_to_pfn(EXYNOS5250_PA_SYSRAM_NS),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      },
 -};
 -
  static struct map_desc exynos5_iodesc[] __initdata = {
        {
                .virtual        = (unsigned long)S3C_VA_SYS,
                .length         = SZ_4K,
                .type           = MT_DEVICE,
        }, {
 -              .virtual        = (unsigned long)S5P_VA_SYSRAM,
 -              .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
 -              .length         = SZ_4K,
 -              .type           = MT_DEVICE,
 -      }, {
                .virtual        = (unsigned long)S5P_VA_CMU,
                .pfn            = __phys_to_pfn(EXYNOS5_PA_CMU),
                .length         = 144 * SZ_1K,
@@@ -169,16 -221,12 +169,16 @@@ void exynos_restart(enum reboot_mode mo
  }
  
  static struct platform_device exynos_cpuidle = {
 -      .name           = "exynos_cpuidle",
 -      .id             = -1,
 +      .name              = "exynos_cpuidle",
 +      .dev.platform_data = exynos_enter_aftr,
 +      .id                = -1,
  };
  
  void __init exynos_cpuidle_init(void)
  {
 +      if (soc_is_exynos5440())
 +              return;
 +
        platform_device_register(&exynos_cpuidle);
  }
  
@@@ -202,7 -250,7 +202,7 @@@ static int __init exynos_fdt_map_chipid
  {
        struct map_desc iodesc;
        __be32 *reg;
-       unsigned long len;
+       int len;
  
        if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
                !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
@@@ -232,6 -280,20 +232,6 @@@ static void __init exynos_map_io(void
  
        if (soc_is_exynos5())
                iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
 -
 -      if (soc_is_exynos4210()) {
 -              if (samsung_rev() == EXYNOS4210_REV_0)
 -                      iotable_init(exynos4_iodesc0,
 -                                              ARRAY_SIZE(exynos4_iodesc0));
 -              else
 -                      iotable_init(exynos4_iodesc1,
 -                                              ARRAY_SIZE(exynos4_iodesc1));
 -              iotable_init(exynos4210_iodesc, ARRAY_SIZE(exynos4210_iodesc));
 -      }
 -      if (soc_is_exynos4212() || soc_is_exynos4412())
 -              iotable_init(exynos4x12_iodesc, ARRAY_SIZE(exynos4x12_iodesc));
 -      if (soc_is_exynos5250())
 -              iotable_init(exynos5250_iodesc, ARRAY_SIZE(exynos5250_iodesc));
  }
  
  void __init exynos_init_io(void)
        exynos_map_io();
  }
  
 -struct bus_type exynos_subsys = {
 -      .name           = "exynos-core",
 -      .dev_name       = "exynos-core",
 -};
 -
 -static int __init exynos_core_init(void)
 -{
 -      return subsys_system_register(&exynos_subsys, NULL);
 -}
 -core_initcall(exynos_core_init);
 -
  static int __init exynos4_l2x0_cache_init(void)
  {
        int ret;
  
 +      if (!soc_is_exynos4())
 +              return 0;
 +
        ret = l2x0_of_init(L2_AUX_VAL, L2_AUX_MASK);
        if (ret)
                return ret;
@@@ -300,15 -370,12 +300,15 @@@ static void __init exynos_dt_machine_in
  }
  
  static char const *exynos_dt_compat[] __initconst = {
 +      "samsung,exynos3",
 +      "samsung,exynos3250",
        "samsung,exynos4",
        "samsung,exynos4210",
        "samsung,exynos4212",
        "samsung,exynos4412",
        "samsung,exynos5",
        "samsung,exynos5250",
 +      "samsung,exynos5260",
        "samsung,exynos5420",
        "samsung,exynos5440",
        NULL
@@@ -36,7 -36,7 +36,7 @@@ static int __init early_init_dt_scan_ep
                                           int depth, void *data)
  {
        const u32 *insts;
-       unsigned long len;
+       int len;
        int i;
  
        insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
                return -1;
  
        for (i = 0; i < (len / 4); i++) {
 -              patch_instruction(epapr_hypercall_start + i, insts[i]);
 +              u32 inst = be32_to_cpu(insts[i]);
 +              patch_instruction(epapr_hypercall_start + i, inst);
  #if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
 -              patch_instruction(epapr_ev_idle_start + i, insts[i]);
 +              patch_instruction(epapr_ev_idle_start + i, inst);
  #endif
        }
  
@@@ -207,10 -207,6 +207,10 @@@ int htab_bolt_mapping(unsigned long vst
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
  
 +              /* Make kvm guest trampolines executable */
 +              if (overlaps_kvm_tmp(vaddr, vaddr + step))
 +                      tprot &= ~HPTE_R_N;
 +
                /*
                 * If relocatable, check if it overlaps interrupt vectors that
                 * are copied down to real 0. For relocatable kernel
@@@ -269,9 -265,9 +269,9 @@@ static int __init htab_dt_scan_seg_size
                                         const char *uname, int depth,
                                         void *data)
  {
-       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-       __be32 *prop;
-       unsigned long size = 0;
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be32 *prop;
+       int size = 0;
  
        /* We are scanning "cpu" nodes only */
        if (type == NULL || strcmp(type, "cpu") != 0)
@@@ -324,9 -320,9 +324,9 @@@ static int __init htab_dt_scan_page_siz
                                          const char *uname, int depth,
                                          void *data)
  {
-       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-       __be32 *prop;
-       unsigned long size = 0;
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be32 *prop;
+       int size = 0;
  
        /* We are scanning "cpu" nodes only */
        if (type == NULL || strcmp(type, "cpu") != 0)
  static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
                                        const char *uname, int depth,
                                        void *data) {
-       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-       __be64 *addr_prop;
-       __be32 *page_count_prop;
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be64 *addr_prop;
+       const __be32 *page_count_prop;
        unsigned int expected_pages;
        long unsigned int phys_addr;
        long unsigned int block_size;
@@@ -550,8 -546,8 +550,8 @@@ static int __init htab_dt_scan_pftsize(
                                       const char *uname, int depth,
                                       void *data)
  {
-       char *type = of_get_flat_dt_prop(node, "device_type", NULL);
-       __be32 *prop;
+       const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
+       const __be32 *prop;
  
        /* We are scanning "cpu" nodes only */
        if (type == NULL || strcmp(type, "cpu") != 0)
diff --combined drivers/of/base.c
@@@ -695,6 -695,25 +695,25 @@@ struct device_node *of_get_next_parent(
  }
  EXPORT_SYMBOL(of_get_next_parent);
  
+ static struct device_node *__of_get_next_child(const struct device_node *node,
+                                               struct device_node *prev)
+ {
+       struct device_node *next;
+       if (!node)
+               return NULL;
+       next = prev ? prev->sibling : node->child;
+       for (; next; next = next->sibling)
+               if (of_node_get(next))
+                       break;
+       of_node_put(prev);
+       return next;
+ }
+ #define __for_each_child_of_node(parent, child) \
+       for (child = __of_get_next_child(parent, NULL); child != NULL; \
+            child = __of_get_next_child(parent, child))
  /**
   *    of_get_next_child - Iterate a node childs
   *    @node:  parent node
@@@ -710,11 -729,7 +729,7 @@@ struct device_node *of_get_next_child(c
        unsigned long flags;
  
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       next = prev ? prev->sibling : node->child;
-       for (; next; next = next->sibling)
-               if (of_node_get(next))
-                       break;
-       of_node_put(prev);
+       next = __of_get_next_child(node, prev);
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return next;
  }
@@@ -734,6 -749,9 +749,9 @@@ struct device_node *of_get_next_availab
        struct device_node *next;
        unsigned long flags;
  
+       if (!node)
+               return NULL;
        raw_spin_lock_irqsave(&devtree_lock, flags);
        next = prev ? prev->sibling : node->child;
        for (; next; next = next->sibling) {
@@@ -771,23 -789,78 +789,78 @@@ struct device_node *of_get_child_by_nam
  }
  EXPORT_SYMBOL(of_get_child_by_name);
  
+ static struct device_node *__of_find_node_by_path(struct device_node *parent,
+                                               const char *path)
+ {
+       struct device_node *child;
+       int len = strchrnul(path, '/') - path;
+       if (!len)
+               return NULL;
+       __for_each_child_of_node(parent, child) {
+               const char *name = strrchr(child->full_name, '/');
+               if (WARN(!name, "malformed device_node %s\n", child->full_name))
+                       continue;
+               name++;
+               if (strncmp(path, name, len) == 0 && (strlen(name) == len))
+                       return child;
+       }
+       return NULL;
+ }
  /**
   *    of_find_node_by_path - Find a node matching a full OF path
-  *    @path:  The full path to match
+  *    @path: Either the full path to match, or if the path does not
+  *           start with '/', the name of a property of the /aliases
+  *           node (an alias).  In the case of an alias, the node
+  *           matching the alias' value will be returned.
+  *
+  *    Valid paths:
+  *            /foo/bar        Full path
+  *            foo             Valid alias
+  *            foo/bar         Valid alias + relative path
   *
   *    Returns a node pointer with refcount incremented, use
   *    of_node_put() on it when done.
   */
  struct device_node *of_find_node_by_path(const char *path)
  {
-       struct device_node *np = of_allnodes;
+       struct device_node *np = NULL;
+       struct property *pp;
        unsigned long flags;
  
+       if (strcmp(path, "/") == 0)
+               return of_node_get(of_allnodes);
+       /* The path could begin with an alias */
+       if (*path != '/') {
+               char *p = strchrnul(path, '/');
+               int len = p - path;
+               /* of_aliases must not be NULL */
+               if (!of_aliases)
+                       return NULL;
+               for_each_property_of_node(of_aliases, pp) {
+                       if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
+                               np = of_find_node_by_path(pp->value);
+                               break;
+                       }
+               }
+               if (!np)
+                       return NULL;
+               path = p;
+       }
+       /* Step down the tree matching path components */
        raw_spin_lock_irqsave(&devtree_lock, flags);
-       for (; np; np = np->allnext) {
-               if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
-                   && of_node_get(np))
-                       break;
+       if (!np)
+               np = of_node_get(of_allnodes);
+       while (np && *path == '/') {
+               path++; /* Increment past '/' delimiter */
+               np = __of_find_node_by_path(np, path);
+               path = strchrnul(path, '/');
        }
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
        return np;
@@@ -1800,7 -1873,7 +1873,7 @@@ int of_update_property(struct device_no
  {
        struct property **next, *oldprop;
        unsigned long flags;
-       int rc, found = 0;
+       int rc;
  
        rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
        if (rc)
        if (!newprop->name)
                return -EINVAL;
  
-       oldprop = of_find_property(np, newprop->name, NULL);
-       if (!oldprop)
-               return of_add_property(np, newprop);
        raw_spin_lock_irqsave(&devtree_lock, flags);
        next = &np->properties;
-       while (*next) {
+       oldprop = __of_find_property(np, newprop->name, NULL);
+       if (!oldprop) {
+               /* add the new node */
+               rc = __of_add_property(np, newprop);
+       } else while (*next) {
+               /* replace the node */
                if (*next == oldprop) {
-                       /* found the node */
                        newprop->next = oldprop->next;
                        *next = newprop;
                        oldprop->next = np->deadprops;
                        np->deadprops = oldprop;
-                       found = 1;
                        break;
                }
                next = &(*next)->next;
        }
        raw_spin_unlock_irqrestore(&devtree_lock, flags);
-       if (!found)
-               return -ENODEV;
+       if (rc)
+               return rc;
  
        /* At early boot, bail out and defer setup to of_init() */
        if (!of_kset)
-               return found ? 0 : -ENODEV;
+               return 0;
  
        /* Update the sysfs attribute */
-       sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
+       if (oldprop)
+               sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
        __of_add_property_sysfs(np, newprop);
  
        return 0;
@@@ -2040,8 -2113,8 +2113,8 @@@ void of_alias_scan(void * (*dt_alloc)(u
   * @np:               Pointer to the given device_node
   * @stem:     Alias stem of the given device_node
   *
 - * The function travels the lookup table to get alias id for the given
 - * device_node and alias stem.  It returns the alias id if find it.
 + * The function travels the lookup table to get the alias id for the given
 + * device_node and alias stem.  It returns the alias id if found.
   */
  int of_alias_get_id(struct device_node *np, const char *stem)
  {
diff --combined drivers/of/platform.c
@@@ -51,10 -51,6 +51,6 @@@ struct platform_device *of_find_device_
  }
  EXPORT_SYMBOL(of_find_device_by_node);
  
- #if defined(CONFIG_PPC_DCR)
- #include <asm/dcr.h>
- #endif
  #ifdef CONFIG_OF_ADDRESS
  /*
   * The following routines scan a subtree and registers a device for
   * of_device_make_bus_id - Use the device node data to assign a unique name
   * @dev: pointer to device structure that is linked to a device tree node
   *
-  * This routine will first try using either the dcr-reg or the reg property
-  * value to derive a unique name.  As a last resort it will use the node
-  * name followed by a unique number.
+  * This routine will first try using the translated bus address to
+  * derive a unique name. If it cannot, then it will prepend names from
+  * parent nodes until a unique name can be derived.
   */
  void of_device_make_bus_id(struct device *dev)
  {
-       static atomic_t bus_no_reg_magic;
        struct device_node *node = dev->of_node;
        const __be32 *reg;
        u64 addr;
-       const __be32 *addrp;
-       int magic;
- #ifdef CONFIG_PPC_DCR
-       /*
-        * If it's a DCR based device, use 'd' for native DCRs
-        * and 'D' for MMIO DCRs.
-        */
-       reg = of_get_property(node, "dcr-reg", NULL);
-       if (reg) {
- #ifdef CONFIG_PPC_DCR_NATIVE
-               dev_set_name(dev, "d%x.%s", *reg, node->name);
- #else /* CONFIG_PPC_DCR_NATIVE */
-               u64 addr = of_translate_dcr_address(node, *reg, NULL);
-               if (addr != OF_BAD_ADDR) {
-                       dev_set_name(dev, "D%llx.%s",
-                                    (unsigned long long)addr, node->name);
-                       return;
-               }
- #endif /* !CONFIG_PPC_DCR_NATIVE */
-       }
- #endif /* CONFIG_PPC_DCR */
-       /*
-        * For MMIO, get the physical address
-        */
-       reg = of_get_property(node, "reg", NULL);
-       if (reg) {
-               if (of_can_translate_address(node)) {
-                       addr = of_translate_address(node, reg);
-               } else {
-                       addrp = of_get_address(node, 0, NULL, NULL);
-                       if (addrp)
-                               addr = of_read_number(addrp, 1);
-                       else
-                               addr = OF_BAD_ADDR;
-               }
-               if (addr != OF_BAD_ADDR) {
-                       dev_set_name(dev, "%llx.%s",
-                                    (unsigned long long)addr, node->name);
+       /* Construct the name, using parent nodes if necessary to ensure uniqueness */
+       while (node->parent) {
+               /*
+                * If the address can be translated, then that is as much
+                * uniqueness as we need. Make it the first component and return
+                */
+               reg = of_get_property(node, "reg", NULL);
+               if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
+                       dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
+                                    (unsigned long long)addr, node->name,
+                                    dev_name(dev));
                        return;
                }
-       }
  
-       /*
-        * No BusID, use the node name and add a globally incremented
-        * counter (and pray...)
-        */
-       magic = atomic_add_return(1, &bus_no_reg_magic);
-       dev_set_name(dev, "%s.%d", node->name, magic - 1);
+               /* format arguments only used if dev_name() resolves to NULL */
+               dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",
+                            strrchr(node->full_name, '/') + 1, dev_name(dev));
+               node = node->parent;
+       }
  }
  
  /**
@@@ -149,9 -114,8 +114,8 @@@ struct platform_device *of_device_alloc
                return NULL;
  
        /* count the io and irq resources */
-       if (of_can_translate_address(np))
-               while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-                       num_reg++;
+       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
+               num_reg++;
        num_irq = of_irq_count(np);
  
        /* Populate the resource table */
@@@ -206,13 -170,12 +170,13 @@@ static struct platform_device *of_platf
  {
        struct platform_device *dev;
  
 -      if (!of_device_is_available(np))
 +      if (!of_device_is_available(np) ||
 +          of_node_test_and_set_flag(np, OF_POPULATED))
                return NULL;
  
        dev = of_device_alloc(np, bus_id, parent);
        if (!dev)
 -              return NULL;
 +              goto err_clear_flag;
  
  #if defined(CONFIG_MICROBLAZE)
        dev->archdata.dma_mask = 0xffffffffUL;
  
        if (of_device_add(dev) != 0) {
                platform_device_put(dev);
 -              return NULL;
 +              goto err_clear_flag;
        }
  
        return dev;
 +
 +err_clear_flag:
 +      of_node_clear_flag(np, OF_POPULATED);
 +      return NULL;
  }
  
  /**
@@@ -269,15 -228,14 +233,15 @@@ static struct amba_device *of_amba_devi
  
        pr_debug("Creating amba device %s\n", node->full_name);
  
 -      if (!of_device_is_available(node))
 +      if (!of_device_is_available(node) ||
 +          of_node_test_and_set_flag(node, OF_POPULATED))
                return NULL;
  
        dev = amba_device_alloc(NULL, 0, 0);
        if (!dev) {
                pr_err("%s(): amba_device_alloc() failed for %s\n",
                       __func__, node->full_name);
 -              return NULL;
 +              goto err_clear_flag;
        }
  
        /* setup generic device info */
  
  err_free:
        amba_device_put(dev);
 +err_clear_flag:
 +      of_node_clear_flag(node, OF_POPULATED);
        return NULL;
  }
  #else /* CONFIG_ARM_AMBA */
@@@ -495,60 -451,4 +459,60 @@@ int of_platform_populate(struct device_
        return rc;
  }
  EXPORT_SYMBOL_GPL(of_platform_populate);
 +
 +static int of_platform_device_destroy(struct device *dev, void *data)
 +{
 +      bool *children_left = data;
 +
 +      /* Do not touch devices not populated from the device tree */
 +      if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
 +              *children_left = true;
 +              return 0;
 +      }
 +
 +      /* Recurse, but don't touch this device if it has any children left */
 +      if (of_platform_depopulate(dev) != 0) {
 +              *children_left = true;
 +              return 0;
 +      }
 +
 +      if (dev->bus == &platform_bus_type)
 +              platform_device_unregister(to_platform_device(dev));
 +#ifdef CONFIG_ARM_AMBA
 +      else if (dev->bus == &amba_bustype)
 +              amba_device_unregister(to_amba_device(dev));
 +#endif
 +      else {
 +              *children_left = true;
 +              return 0;
 +      }
 +
 +      of_node_clear_flag(dev->of_node, OF_POPULATED);
 +
 +      return 0;
 +}
 +
 +/**
 + * of_platform_depopulate() - Remove devices populated from device tree
 + * @parent: device which childred will be removed
 + *
 + * Complementary to of_platform_populate(), this function removes children
 + * of the given device (and, recurrently, their children) that have been
 + * created from their respective device tree nodes (and only those,
 + * leaving others - eg. manually created - unharmed).
 + *
 + * Returns 0 when all children devices have been removed or
 + * -EBUSY when some children remained.
 + */
 +int of_platform_depopulate(struct device *parent)
 +{
 +      bool children_left = false;
 +
 +      device_for_each_child(parent, &children_left,
 +                            of_platform_device_destroy);
 +
 +      return children_left ? -EBUSY : 0;
 +}
 +EXPORT_SYMBOL_GPL(of_platform_depopulate);
 +
  #endif /* CONFIG_OF_ADDRESS */
@@@ -413,37 -413,6 +413,37 @@@ struct clk *clk_register_fixed_factor(s
                const char *parent_name, unsigned long flags,
                unsigned int mult, unsigned int div);
  
 +/**
 + * struct clk_fractional_divider - adjustable fractional divider clock
 + *
 + * @hw:               handle between common and hardware-specific interfaces
 + * @reg:      register containing the divider
 + * @mshift:   shift to the numerator bit field
 + * @mwidth:   width of the numerator bit field
 + * @nshift:   shift to the denominator bit field
 + * @nwidth:   width of the denominator bit field
 + * @lock:     register lock
 + *
 + * Clock with adjustable fractional divider affecting its output frequency.
 + */
 +
 +struct clk_fractional_divider {
 +      struct clk_hw   hw;
 +      void __iomem    *reg;
 +      u8              mshift;
 +      u32             mmask;
 +      u8              nshift;
 +      u32             nmask;
 +      u8              flags;
 +      spinlock_t      *lock;
 +};
 +
 +extern const struct clk_ops clk_fractional_divider_ops;
 +struct clk *clk_register_fractional_divider(struct device *dev,
 +              const char *name, const char *parent_name, unsigned long flags,
 +              void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
 +              u8 clk_divider_flags, spinlock_t *lock);
 +
  /***
   * struct clk_composite - aggregate clock of mux, divider and gate clocks
   *
@@@ -529,10 -498,7 +529,7 @@@ struct clk_onecell_data 
  
  extern struct of_device_id __clk_of_table;
  
- #define CLK_OF_DECLARE(name, compat, fn)                      \
-       static const struct of_device_id __clk_of_table_##name  \
-               __used __section(__clk_of_table)                \
-               = { .compatible = compat, .data = fn };
+ #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
  
  #ifdef CONFIG_OF
  int of_clk_add_provider(struct device_node *np,
diff --combined include/linux/of.h
@@@ -130,12 -130,6 +130,12 @@@ static inline int of_node_check_flag(st
        return test_bit(flag, &n->_flags);
  }
  
 +static inline int of_node_test_and_set_flag(struct device_node *n,
 +                                          unsigned long flag)
 +{
 +      return test_and_set_bit(flag, &n->_flags);
 +}
 +
  static inline void of_node_set_flag(struct device_node *n, unsigned long flag)
  {
        set_bit(flag, &n->_flags);
@@@ -203,7 -197,6 +203,7 @@@ static inline unsigned long of_read_ulo
  /* flag descriptions */
  #define OF_DYNAMIC    1 /* node and properties were allocated via kmalloc */
  #define OF_DETACHED   2 /* node has been detached from the device tree */
 +#define OF_POPULATED  3 /* device already created for the node */
  
  #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
  #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
@@@ -356,7 -349,7 +356,7 @@@ int of_device_is_stdout_path(struct dev
  
  #else /* CONFIG_OF */
  
 -static inline const char* of_node_full_name(struct device_node *np)
 +static inline const char* of_node_full_name(const struct device_node *np)
  {
        return "<no-node>";
  }
@@@ -764,4 -757,26 +764,26 @@@ static inline int of_get_available_chil
        return num;
  }
  
+ #ifdef CONFIG_OF
+ #define _OF_DECLARE(table, name, compat, fn, fn_type)                 \
+       static const struct of_device_id __of_table_##name              \
+               __used __section(__##table##_of_table)                  \
+                = { .compatible = compat,                              \
+                    .data = (fn == (fn_type)NULL) ? fn : fn  }
+ #else
+ #define _OF_DECLARE(table, name, compat, fn, fn_type)                                 \
+       static const struct of_device_id __of_table_##name              \
+               __attribute__((unused))                                 \
+                = { .compatible = compat,                              \
+                    .data = (fn == (fn_type)NULL) ? fn : fn }
+ #endif
+ typedef int (*of_init_fn_2)(struct device_node *, struct device_node *);
+ typedef void (*of_init_fn_1)(struct device_node *);
+ #define OF_DECLARE_1(table, name, compat, fn) \
+               _OF_DECLARE(table, name, compat, fn, of_init_fn_1)
+ #define OF_DECLARE_2(table, name, compat, fn) \
+               _OF_DECLARE(table, name, compat, fn, of_init_fn_2)
  #endif /* _LINUX_OF_H */