Commit 34ec4de4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'devicetree-for-linus' of git://

Pull device tree fixes and reverts from Grant Likely:
 "One bug fix and three reverts.  The reverts back out the slightly
  controversial feeding the entire device tree into the random pool and
  the reserved-memory binding which isn't fully baked yet.  Expect the
  reserved-memory patches at least to resurface for v3.13.

  The bug fixes removes a scary but harmless warning on SPARC that was
  introduced in the v3.12 merge window.  v3.13 will contain a proper fix
  that makes the new code work on SPARC.

  On the plus side, the diffstat looks *awesome*.  I love removing lines
  of code"

* tag 'devicetree-for-linus' of git://
  Revert "drivers: of: add initialization code for dma reserved memory"
  Revert "ARM: init: add support for reserved memory defined by device tree"
  Revert "of: Feed entire flattened device tree into the random pool"
  of: fix unnecessary warning on missing /cpus node
parents ba0a062e 1931ee14
*** Memory binding ***
The /memory node provides basic information about the address and size
of the physical memory. This node is usually filled or updated by the
bootloader, depending on the actual memory configuration of the given
The memory layout is described by the following node:
/ {
#address-cells = <(n)>;
#size-cells = <(m)>;
memory {
device_type = "memory";
reg = <(baseaddr1) (size1)
(baseaddr2) (size2)
(baseaddrN) (sizeN)>;
A memory node follows the typical device tree rules for "reg" property:
n: number of cells used to store base address value
m: number of cells used to store size value
baseaddrX: defines a base address of the defined memory bank
sizeX: the size of the defined memory bank
More than one memory bank can be defined.
*** Reserved memory regions ***
In /memory/reserved-memory node one can create child nodes describing
particular reserved (excluded from normal use) memory regions. Such
memory regions are usually designed for the special usage by various
device drivers. A good example are contiguous memory allocations or
memory sharing with other operating system on the same hardware board.
Those special memory regions might depend on the board configuration and
devices used on the target system.
Parameters for each memory region can be encoded into the device tree
with the following convention:
[(label):] (name) {
compatible = "linux,contiguous-memory-region", "reserved-memory-region";
reg = <(address) (size)>;
compatible: one or more of:
- "linux,contiguous-memory-region" - enables binding of this
region to Contiguous Memory Allocator (special region for
contiguous memory allocations, shared with movable system
memory, Linux kernel-specific).
- "reserved-memory-region" - compatibility is defined, given
region is assigned for exclusive usage for by the respective
reg: standard property defining the base address and size of
the memory region
linux,default-contiguous-region: property indicating that the region
is the default region for all contiguous memory
allocations, Linux specific (optional)
It is optional to specify the base address, so if one wants to use
autoconfiguration of the base address, '0' can be specified as a base
address in the 'reg' property.
The /memory/reserved-memory node must contain the same #address-cells
and #size-cells value as the root node.
*** Device node's properties ***
Once regions in the /memory/reserved-memory node have been defined, they
may be referenced by other device nodes. Bindings that wish to reference
memory regions should explicitly document their use of the following
memory-region = <&phandle_to_defined_region>;
This property indicates that the device driver should use the memory
region pointed by the given phandle.
*** Example ***
This example defines a memory consisting of 4 memory banks. 3 contiguous
regions are defined for Linux kernel, one default of all device drivers
(named contig_mem, placed at 0x72000000, 64MiB), one dedicated to the
framebuffer device (labelled display_mem, placed at 0x78000000, 8MiB)
and one for multimedia processing (labelled multimedia_mem, placed at
0x77000000, 64MiB). 'display_mem' region is then assigned to fb@12300000
device for DMA memory allocations (Linux kernel drivers will use CMA is
available or dma-exclusive usage otherwise). 'multimedia_mem' is
assigned to scaler@12500000 and codec@12600000 devices for contiguous
memory allocations when CMA driver is enabled.
The reason for creating a separate region for framebuffer device is to
match the framebuffer base address to the one configured by bootloader,
so once Linux kernel drivers starts no glitches on the displayed boot
logo appears. Scaller and codec drivers should share the memory
/ {
#address-cells = <1>;
#size-cells = <1>;
/* ... */
memory {
reg = <0x40000000 0x10000000
0x50000000 0x10000000
0x60000000 0x10000000
0x70000000 0x10000000>;
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
* global autoconfigured region for contiguous allocations
* (used only with Contiguous Memory Allocator)
contig_region@0 {
compatible = "linux,contiguous-memory-region";
reg = <0x0 0x4000000>;
* special region for framebuffer
display_region: region@78000000 {
compatible = "linux,contiguous-memory-region", "reserved-memory-region";
reg = <0x78000000 0x800000>;
* special region for multimedia processing devices
multimedia_region: region@77000000 {
compatible = "linux,contiguous-memory-region";
reg = <0x77000000 0x4000000>;
/* ... */
fb0: fb@12300000 {
status = "okay";
memory-region = <&display_region>;
scaler: scaler@12500000 {
status = "okay";
memory-region = <&multimedia_region>;
codec: codec@12600000 {
status = "okay";
memory-region = <&multimedia_region>;
......@@ -17,7 +17,6 @@
#include <linux/nodemask.h>
#include <linux/initrd.h>
#include <linux/of_fdt.h>
#include <linux/of_reserved_mem.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
#include <linux/memblock.h>
......@@ -379,8 +378,6 @@ void __init arm_memblock_init(struct meminfo *mi,
if (mdesc->reserve)
* reserve memory for DMA contigouos allocations,
* must come from DMA area inside low memory
......@@ -74,10 +74,4 @@ config OF_MTD
depends on MTD
def_bool y
def_bool y
Initialization code for DMA reserved memory
endmenu # OF
......@@ -9,4 +9,3 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o
obj-$(CONFIG_OF_PCI) += of_pci.o
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
obj-$(CONFIG_OF_MTD) += of_mtd.o
obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o
......@@ -303,10 +303,8 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
struct device_node *cpun, *cpus;
cpus = of_find_node_by_path("/cpus");
if (!cpus) {
pr_warn("Missing cpus node, bailing out\n");
if (!cpus)
return NULL;
for_each_child_of_node(cpus, cpun) {
if (of_node_cmp(cpun->type, "cpu"))
......@@ -18,7 +18,6 @@
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/random.h>
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
......@@ -803,14 +802,3 @@ void __init unflatten_device_tree(void)
/* Feed entire flattened device tree into the random pool */
static int __init add_fdt_randomness(void)
if (initial_boot_params)
return 0;
* Device tree based initialization code for reserved memory.
* Copyright (c) 2013 Samsung Electronics Co., Ltd.
* Author: Marek Szyprowski <>
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License or (at your optional) any later version of the license.
#include <linux/memblock.h>
#include <linux/err.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/mm.h>
#include <linux/sizes.h>
#include <linux/mm_types.h>
#include <linux/dma-contiguous.h>
#include <linux/dma-mapping.h>
#include <linux/of_reserved_mem.h>
struct reserved_mem {
phys_addr_t base;
unsigned long size;
struct cma *cma;
char name[32];
static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS];
static int reserved_mem_count;
static int __init fdt_scan_reserved_mem(unsigned long node, const char *uname,
int depth, void *data)
struct reserved_mem *rmem = &reserved_mem[reserved_mem_count];
phys_addr_t base, size;
int is_cma, is_reserved;
unsigned long len;
const char *status;
__be32 *prop;
of_flat_dt_is_compatible(node, "linux,contiguous-memory-region");
is_reserved = of_flat_dt_is_compatible(node, "reserved-memory-region");
if (!is_reserved && !is_cma) {
/* ignore node and scan next one */
return 0;
status = of_get_flat_dt_prop(node, "status", &len);
if (status && strcmp(status, "okay") != 0) {
/* ignore disabled node nad scan next one */
return 0;
prop = of_get_flat_dt_prop(node, "reg", &len);
if (!prop || (len < (dt_root_size_cells + dt_root_addr_cells) *
sizeof(__be32))) {
pr_err("Reserved mem: node %s, incorrect \"reg\" property\n",
/* ignore node and scan next one */
return 0;
base = dt_mem_next_cell(dt_root_addr_cells, &prop);
size = dt_mem_next_cell(dt_root_size_cells, &prop);
if (!size) {
/* ignore node and scan next one */
return 0;
pr_info("Reserved mem: found %s, memory base %lx, size %ld MiB\n",
uname, (unsigned long)base, (unsigned long)size / SZ_1M);
if (reserved_mem_count == ARRAY_SIZE(reserved_mem))
return -ENOSPC;
rmem->base = base;
rmem->size = size;
strlcpy(rmem->name, uname, sizeof(rmem->name));
if (is_cma) {
struct cma *cma;
if (dma_contiguous_reserve_area(size, base, 0, &cma) == 0) {
rmem->cma = cma;
if (of_get_flat_dt_prop(node,
} else if (is_reserved) {
if (memblock_remove(base, size) == 0)
pr_err("Failed to reserve memory for %s\n", uname);
return 0;
static struct reserved_mem *get_dma_memory_region(struct device *dev)
struct device_node *node;
const char *name;
int i;
node = of_parse_phandle(dev->of_node, "memory-region", 0);
if (!node)
return NULL;
name = kbasename(node->full_name);
for (i = 0; i < reserved_mem_count; i++)
if (strcmp(name, reserved_mem[i].name) == 0)
return &reserved_mem[i];
return NULL;
* of_reserved_mem_device_init() - assign reserved memory region to given device
* This function assign memory region pointed by "memory-region" device tree
* property to the given device.
void of_reserved_mem_device_init(struct device *dev)
struct reserved_mem *region = get_dma_memory_region(dev);
if (!region)
if (region->cma) {
dev_set_cma_area(dev, region->cma);
pr_info("Assigned CMA %s to %s device\n", region->name,
} else {
if (dma_declare_coherent_memory(dev, region->base, region->base,
pr_info("Declared reserved memory %s to %s device\n",
region->name, dev_name(dev));
* of_reserved_mem_device_release() - release reserved memory device structures
* This function releases structures allocated for memory region handling for
* the given device.
void of_reserved_mem_device_release(struct device *dev)
struct reserved_mem *region = get_dma_memory_region(dev);
if (!region && !region->cma)
* early_init_dt_scan_reserved_mem() - create reserved memory regions
* This function grabs memory from early allocator for device exclusive use
* defined in device tree structures. It should be called by arch specific code
* once the early allocator (memblock) has been activated and all other
* subsystems have already allocated/reserved memory.
void __init early_init_dt_scan_reserved_mem(void)
fdt_scan_reserved_mem, NULL);
......@@ -21,7 +21,6 @@
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
const struct of_device_id of_default_bus_match_table[] = {
......@@ -219,8 +218,6 @@ static struct platform_device *of_platform_device_create_pdata(
dev->dev.bus = &platform_bus_type;
dev->dev.platform_data = platform_data;
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
......@@ -228,7 +225,6 @@ static struct platform_device *of_platform_device_create_pdata(
if (of_device_add(dev) != 0) {
return NULL;
void of_reserved_mem_device_init(struct device *dev);
void of_reserved_mem_device_release(struct device *dev);
void early_init_dt_scan_reserved_mem(void);
static inline void of_reserved_mem_device_init(struct device *dev) { }
static inline void of_reserved_mem_device_release(struct device *dev) { }
static inline void early_init_dt_scan_reserved_mem(void) { }
#endif /* __OF_RESERVED_MEM_H */
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment