Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 339562
b: refs/heads/master
c: a0ae024
h: refs/heads/master
v: v3
  • Loading branch information
Lorenzo Pieralisi committed Nov 19, 2012
1 parent cc7c06b commit 7c5cc8f
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cb8cf4f821044f140ea5b9c8d4f816f0c05fab44
refs/heads/master: a0ae02405076ac32bd17ece976e914b5b6075bb0
77 changes: 77 additions & 0 deletions trunk/Documentation/devicetree/bindings/arm/cpus.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
* ARM CPUs binding description

The device tree allows to describe the layout of CPUs in a system through
the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
defining properties for every cpu.

Bindings for CPU nodes follow the ePAPR standard, available from:

http://devicetree.org

For the ARM architecture every CPU node must contain the following properties:

- device_type: must be "cpu"
- reg: property matching the CPU MPIDR[23:0] register bits
reg[31:24] bits must be set to 0
- compatible: should be one of:
"arm,arm1020"
"arm,arm1020e"
"arm,arm1022"
"arm,arm1026"
"arm,arm720"
"arm,arm740"
"arm,arm7tdmi"
"arm,arm920"
"arm,arm922"
"arm,arm925"
"arm,arm926"
"arm,arm940"
"arm,arm946"
"arm,arm9tdmi"
"arm,cortex-a5"
"arm,cortex-a7"
"arm,cortex-a8"
"arm,cortex-a9"
"arm,cortex-a15"
"arm,arm1136"
"arm,arm1156"
"arm,arm1176"
"arm,arm11mpcore"
"faraday,fa526"
"intel,sa110"
"intel,sa1100"
"marvell,feroceon"
"marvell,mohawk"
"marvell,xsc3"
"marvell,xscale"

Example:

cpus {
#size-cells = <0>;
#address-cells = <1>;

CPU0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x0>;
};

CPU1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a15";
reg = <0x1>;
};

CPU2: cpu@100 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x100>;
};

CPU3: cpu@101 {
device_type = "cpu";
compatible = "arm,cortex-a7";
reg = <0x101>;
};
};
2 changes: 2 additions & 0 deletions trunk/arch/arm/include/asm/prom.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

extern struct machine_desc *setup_machine_fdt(unsigned int dt_phys);
extern void arm_dt_memblock_reserve(void);
extern void __init arm_dt_init_cpu_maps(void);

#else /* CONFIG_OF */

Expand All @@ -24,6 +25,7 @@ static inline struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
}

static inline void arm_dt_memblock_reserve(void) { }
static inline void arm_dt_init_cpu_maps(void) { }

#endif /* CONFIG_OF */
#endif /* ASMARM_PROM_H */
100 changes: 100 additions & 0 deletions trunk/arch/arm/kernel/devtree.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
#include <linux/of_irq.h>
#include <linux/of_platform.h>

#include <asm/cputype.h>
#include <asm/setup.h>
#include <asm/page.h>
#include <asm/smp_plat.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>

Expand Down Expand Up @@ -61,6 +63,104 @@ void __init arm_dt_memblock_reserve(void)
}
}

/*
* arm_dt_init_cpu_maps - Function retrieves cpu nodes from the device tree
* and builds the cpu logical map array containing MPIDR values related to
* logical cpus
*
* Updates the cpu possible mask with the number of parsed cpu nodes
*/
void __init arm_dt_init_cpu_maps(void)
{
/*
* Temp logical map is initialized with UINT_MAX values that are
* considered invalid logical map entries since the logical map must
* contain a list of MPIDR[23:0] values where MPIDR[31:24] must
* read as 0.
*/
struct device_node *cpu, *cpus;
u32 i, j, cpuidx = 1;
u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;

u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS-1] = UINT_MAX };
bool bootcpu_valid = false;
cpus = of_find_node_by_path("/cpus");

if (!cpus)
return;

for_each_child_of_node(cpus, cpu) {
u32 hwid;

pr_debug(" * %s...\n", cpu->full_name);
/*
* A device tree containing CPU nodes with missing "reg"
* properties is considered invalid to build the
* cpu_logical_map.
*/
if (of_property_read_u32(cpu, "reg", &hwid)) {
pr_debug(" * %s missing reg property\n",
cpu->full_name);
return;
}

/*
* 8 MSBs must be set to 0 in the DT since the reg property
* defines the MPIDR[23:0].
*/
if (hwid & ~MPIDR_HWID_BITMASK)
return;

/*
* Duplicate MPIDRs are a recipe for disaster.
* Scan all initialized entries and check for
* duplicates. If any is found just bail out.
* temp values were initialized to UINT_MAX
* to avoid matching valid MPIDR[23:0] values.
*/
for (j = 0; j < cpuidx; j++)
if (WARN(tmp_map[j] == hwid, "Duplicate /cpu reg "
"properties in the DT\n"))
return;

/*
* Build a stashed array of MPIDR values. Numbering scheme
* requires that if detected the boot CPU must be assigned
* logical id 0. Other CPUs get sequential indexes starting
* from 1. If a CPU node with a reg property matching the
* boot CPU MPIDR is detected, this is recorded so that the
* logical map built from DT is validated and can be used
* to override the map created in smp_setup_processor_id().
*/
if (hwid == mpidr) {
i = 0;
bootcpu_valid = true;
} else {
i = cpuidx++;
}

tmp_map[i] = hwid;

if (cpuidx > nr_cpu_ids)
break;
}

if (WARN(!bootcpu_valid, "DT missing boot CPU MPIDR[23:0], "
"fall back to default cpu_logical_map\n"))
return;

/*
* Since the boot CPU node contains proper data, and all nodes have
* a reg property, the DT CPU list can be considered valid and the
* logical map created in smp_setup_processor_id() can be overridden
*/
for (i = 0; i < cpuidx; i++) {
set_cpu_possible(i, true);
cpu_logical_map(i) = tmp_map[i];
pr_debug("cpu logical map 0x%x\n", cpu_logical_map(i));
}
}

/**
* setup_machine_fdt - Machine setup when an dtb was passed to the kernel
* @dt_phys: physical address of dt blob
Expand Down

0 comments on commit 7c5cc8f

Please sign in to comment.