Merge tag 'devicetree-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree updates from Rob Herring: "DeviceTree updates for 3.13. This is a bit larger pull request than usual for this cycle with lots of clean-up. - Cross arch clean-up and consolidation of early DT scanning code. - Clean-up and removal of arch prom.h headers. Makes arch specific prom.h optional on all but Sparc. - Addition of interrupts-extended property for devices connected to multiple interrupt controllers. - Refactoring of DT interrupt parsing code in preparation for deferred probe of interrupts. - ARM cpu and cpu topology bindings documentation. - Various DT vendor binding documentation updates" * tag 'devicetree-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (82 commits) powerpc: add missing explicit OF includes for ppc dt/irq: add empty of_irq_count for !OF_IRQ dt: disable self-tests for !OF_IRQ of: irq: Fix interrupt-map entry matching MIPS: Netlogic: replace early_init_devtree() call of: Add Panasonic Corporation vendor prefix of: Add Chunghwa Picture Tubes Ltd. vendor prefix of: Add AU Optronics Corporation vendor prefix of/irq: Fix potential buffer overflow of/irq: Fix bug in interrupt parsing refactor. of: set dma_mask to point to coherent_dma_mask of: add vendor prefix for PHYTEC Messtechnik GmbH DT: sort vendor-prefixes.txt of: Add vendor prefix for Cadence of: Add empty for_each_available_child_of_node() macro definition arm/versatile: Fix versatile irq specifications. of/irq: create interrupts-extended property microblaze/pci: Drop PowerPC-ism from irq parsing of/irq: Create of_irq_parse_and_map_pci() to consolidate arch code. of/irq: Use irq_of_parse_and_map() ...
This commit is contained in:
138
drivers/of/fdt.c
138
drivers/of/fdt.c
@@ -618,12 +618,72 @@ int __init of_scan_flat_dt_by_path(const char *path,
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char * __init of_flat_dt_get_machine_name(void)
|
||||
{
|
||||
const char *name;
|
||||
unsigned long dt_root = of_get_flat_dt_root();
|
||||
|
||||
name = of_get_flat_dt_prop(dt_root, "model", NULL);
|
||||
if (!name)
|
||||
name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_flat_dt_match_machine - Iterate match tables to find matching machine.
|
||||
*
|
||||
* @default_match: A machine specific ptr to return in case of no match.
|
||||
* @get_next_compat: callback function to return next compatible match table.
|
||||
*
|
||||
* Iterate through machine match tables to find the best match for the machine
|
||||
* compatible string in the FDT.
|
||||
*/
|
||||
const void * __init of_flat_dt_match_machine(const void *default_match,
|
||||
const void * (*get_next_compat)(const char * const**))
|
||||
{
|
||||
const void *data = NULL;
|
||||
const void *best_data = default_match;
|
||||
const char *const *compat;
|
||||
unsigned long dt_root;
|
||||
unsigned int best_score = ~1, score = 0;
|
||||
|
||||
dt_root = of_get_flat_dt_root();
|
||||
while ((data = get_next_compat(&compat))) {
|
||||
score = of_flat_dt_match(dt_root, compat);
|
||||
if (score > 0 && score < best_score) {
|
||||
best_data = data;
|
||||
best_score = score;
|
||||
}
|
||||
}
|
||||
if (!best_data) {
|
||||
const char *prop;
|
||||
long size;
|
||||
|
||||
pr_err("\n unrecognized device tree list:\n[ ");
|
||||
|
||||
prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
|
||||
if (prop) {
|
||||
while (size > 0) {
|
||||
printk("'%s' ", prop);
|
||||
size -= strlen(prop) + 1;
|
||||
prop += strlen(prop) + 1;
|
||||
}
|
||||
}
|
||||
printk("]\n\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
|
||||
|
||||
return best_data;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
/**
|
||||
* early_init_dt_check_for_initrd - Decode initrd location from flat tree
|
||||
* @node: reference to node containing initrd location ('chosen')
|
||||
*/
|
||||
void __init early_init_dt_check_for_initrd(unsigned long node)
|
||||
static void __init early_init_dt_check_for_initrd(unsigned long node)
|
||||
{
|
||||
u64 start, end;
|
||||
unsigned long len;
|
||||
@@ -641,12 +701,15 @@ void __init early_init_dt_check_for_initrd(unsigned long node)
|
||||
return;
|
||||
end = of_read_number(prop, len/4);
|
||||
|
||||
early_init_dt_setup_initrd_arch(start, end);
|
||||
initrd_start = (unsigned long)__va(start);
|
||||
initrd_end = (unsigned long)__va(end);
|
||||
initrd_below_start_ok = 1;
|
||||
|
||||
pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n",
|
||||
(unsigned long long)start, (unsigned long long)end);
|
||||
}
|
||||
#else
|
||||
inline void early_init_dt_check_for_initrd(unsigned long node)
|
||||
static inline void early_init_dt_check_for_initrd(unsigned long node)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
@@ -774,6 +837,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_MEMBLOCK
|
||||
void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
|
||||
{
|
||||
const u64 phys_offset = __pa(PAGE_OFFSET);
|
||||
base &= PAGE_MASK;
|
||||
size &= PAGE_MASK;
|
||||
if (base + size < phys_offset) {
|
||||
pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
|
||||
base, base + size);
|
||||
return;
|
||||
}
|
||||
if (base < phys_offset) {
|
||||
pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
|
||||
base, phys_offset);
|
||||
size -= phys_offset - base;
|
||||
base = phys_offset;
|
||||
}
|
||||
memblock_add(base, size);
|
||||
}
|
||||
|
||||
/*
|
||||
* called from unflatten_device_tree() to bootstrap devicetree itself
|
||||
* Architectures can override this definition if memblock isn't used
|
||||
@@ -784,6 +866,32 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool __init early_init_dt_scan(void *params)
|
||||
{
|
||||
if (!params)
|
||||
return false;
|
||||
|
||||
/* Setup flat device-tree pointer */
|
||||
initial_boot_params = params;
|
||||
|
||||
/* check device tree validity */
|
||||
if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
|
||||
initial_boot_params = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Retrieve various information from the /chosen node */
|
||||
of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
|
||||
|
||||
/* Initialize {size,address}-cells info */
|
||||
of_scan_flat_dt(early_init_dt_scan_root, NULL);
|
||||
|
||||
/* Setup memory, calling early_init_dt_add_memory_arch */
|
||||
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* unflatten_device_tree - create tree of device_nodes from flat blob
|
||||
*
|
||||
@@ -801,4 +909,28 @@ void __init unflatten_device_tree(void)
|
||||
of_alias_scan(early_init_dt_alloc_memory_arch);
|
||||
}
|
||||
|
||||
/**
|
||||
* unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
|
||||
*
|
||||
* Copies and unflattens the device-tree passed by the firmware, creating the
|
||||
* tree of struct device_node. It also fills the "name" and "type"
|
||||
* pointers of the nodes so the normal device-tree walking functions
|
||||
* can be used. This should only be used when the FDT memory has not been
|
||||
* reserved such is the case when the FDT is built-in to the kernel init
|
||||
* section. If the FDT memory is reserved already then unflatten_device_tree
|
||||
* should be used instead.
|
||||
*/
|
||||
void __init unflatten_and_copy_device_tree(void)
|
||||
{
|
||||
int size = __be32_to_cpu(initial_boot_params->totalsize);
|
||||
void *dt = early_init_dt_alloc_memory_arch(size,
|
||||
__alignof__(struct boot_param_header));
|
||||
|
||||
if (dt) {
|
||||
memcpy(dt, initial_boot_params, size);
|
||||
initial_boot_params = dt;
|
||||
}
|
||||
unflatten_device_tree();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_OF_EARLY_FLATTREE */
|
||||
|
Reference in New Issue
Block a user