xref: /openbmc/linux/arch/arm/kernel/devtree.c (revision ecea4ab6d3d8bb4122522398200f1cd2a06af6d5)
19eb8f674SGrant Likely /*
29eb8f674SGrant Likely  *  linux/arch/arm/kernel/devtree.c
39eb8f674SGrant Likely  *
49eb8f674SGrant Likely  *  Copyright (C) 2009 Canonical Ltd. <jeremy.kerr@canonical.com>
59eb8f674SGrant Likely  *
69eb8f674SGrant Likely  * This program is free software; you can redistribute it and/or modify
79eb8f674SGrant Likely  * it under the terms of the GNU General Public License version 2 as
89eb8f674SGrant Likely  * published by the Free Software Foundation.
99eb8f674SGrant Likely  */
109eb8f674SGrant Likely 
119eb8f674SGrant Likely #include <linux/init.h>
12*ecea4ab6SPaul Gortmaker #include <linux/export.h>
139eb8f674SGrant Likely #include <linux/errno.h>
149eb8f674SGrant Likely #include <linux/types.h>
159eb8f674SGrant Likely #include <linux/bootmem.h>
169eb8f674SGrant Likely #include <linux/memblock.h>
179eb8f674SGrant Likely #include <linux/of.h>
189eb8f674SGrant Likely #include <linux/of_fdt.h>
199eb8f674SGrant Likely #include <linux/of_irq.h>
209eb8f674SGrant Likely #include <linux/of_platform.h>
219eb8f674SGrant Likely 
229eb8f674SGrant Likely #include <asm/setup.h>
239eb8f674SGrant Likely #include <asm/page.h>
2493c02ab4SGrant Likely #include <asm/mach/arch.h>
2593c02ab4SGrant Likely #include <asm/mach-types.h>
269eb8f674SGrant Likely 
279eb8f674SGrant Likely void __init early_init_dt_add_memory_arch(u64 base, u64 size)
289eb8f674SGrant Likely {
299eb8f674SGrant Likely 	arm_add_memory(base, size);
309eb8f674SGrant Likely }
319eb8f674SGrant Likely 
329eb8f674SGrant Likely void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
339eb8f674SGrant Likely {
349eb8f674SGrant Likely 	return alloc_bootmem_align(size, align);
359eb8f674SGrant Likely }
369eb8f674SGrant Likely 
3793c02ab4SGrant Likely void __init arm_dt_memblock_reserve(void)
3893c02ab4SGrant Likely {
3993c02ab4SGrant Likely 	u64 *reserve_map, base, size;
4093c02ab4SGrant Likely 
4193c02ab4SGrant Likely 	if (!initial_boot_params)
4293c02ab4SGrant Likely 		return;
4393c02ab4SGrant Likely 
4493c02ab4SGrant Likely 	/* Reserve the dtb region */
4593c02ab4SGrant Likely 	memblock_reserve(virt_to_phys(initial_boot_params),
4693c02ab4SGrant Likely 			 be32_to_cpu(initial_boot_params->totalsize));
4793c02ab4SGrant Likely 
4893c02ab4SGrant Likely 	/*
4993c02ab4SGrant Likely 	 * Process the reserve map.  This will probably overlap the initrd
5093c02ab4SGrant Likely 	 * and dtb locations which are already reserved, but overlaping
5193c02ab4SGrant Likely 	 * doesn't hurt anything
5293c02ab4SGrant Likely 	 */
5393c02ab4SGrant Likely 	reserve_map = ((void*)initial_boot_params) +
5493c02ab4SGrant Likely 			be32_to_cpu(initial_boot_params->off_mem_rsvmap);
5593c02ab4SGrant Likely 	while (1) {
5693c02ab4SGrant Likely 		base = be64_to_cpup(reserve_map++);
5793c02ab4SGrant Likely 		size = be64_to_cpup(reserve_map++);
5893c02ab4SGrant Likely 		if (!size)
5993c02ab4SGrant Likely 			break;
6093c02ab4SGrant Likely 		memblock_reserve(base, size);
6193c02ab4SGrant Likely 	}
6293c02ab4SGrant Likely }
6393c02ab4SGrant Likely 
6493c02ab4SGrant Likely /**
6593c02ab4SGrant Likely  * setup_machine_fdt - Machine setup when an dtb was passed to the kernel
6693c02ab4SGrant Likely  * @dt_phys: physical address of dt blob
6793c02ab4SGrant Likely  *
6893c02ab4SGrant Likely  * If a dtb was passed to the kernel in r2, then use it to choose the
6993c02ab4SGrant Likely  * correct machine_desc and to setup the system.
7093c02ab4SGrant Likely  */
7193c02ab4SGrant Likely struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
7293c02ab4SGrant Likely {
7393c02ab4SGrant Likely 	struct boot_param_header *devtree;
7493c02ab4SGrant Likely 	struct machine_desc *mdesc, *mdesc_best = NULL;
7593c02ab4SGrant Likely 	unsigned int score, mdesc_score = ~1;
7693c02ab4SGrant Likely 	unsigned long dt_root;
7793c02ab4SGrant Likely 	const char *model;
7893c02ab4SGrant Likely 
79f506cd48SNicolas Pitre 	if (!dt_phys)
80f506cd48SNicolas Pitre 		return NULL;
81f506cd48SNicolas Pitre 
8293c02ab4SGrant Likely 	devtree = phys_to_virt(dt_phys);
8393c02ab4SGrant Likely 
8493c02ab4SGrant Likely 	/* check device tree validity */
8593c02ab4SGrant Likely 	if (be32_to_cpu(devtree->magic) != OF_DT_HEADER)
8693c02ab4SGrant Likely 		return NULL;
8793c02ab4SGrant Likely 
8893c02ab4SGrant Likely 	/* Search the mdescs for the 'best' compatible value match */
8993c02ab4SGrant Likely 	initial_boot_params = devtree;
9093c02ab4SGrant Likely 	dt_root = of_get_flat_dt_root();
9193c02ab4SGrant Likely 	for_each_machine_desc(mdesc) {
9293c02ab4SGrant Likely 		score = of_flat_dt_match(dt_root, mdesc->dt_compat);
9393c02ab4SGrant Likely 		if (score > 0 && score < mdesc_score) {
9493c02ab4SGrant Likely 			mdesc_best = mdesc;
9593c02ab4SGrant Likely 			mdesc_score = score;
9693c02ab4SGrant Likely 		}
9793c02ab4SGrant Likely 	}
9893c02ab4SGrant Likely 	if (!mdesc_best) {
9993c02ab4SGrant Likely 		const char *prop;
10093c02ab4SGrant Likely 		long size;
10193c02ab4SGrant Likely 
10293c02ab4SGrant Likely 		early_print("\nError: unrecognized/unsupported "
10393c02ab4SGrant Likely 			    "device tree compatible list:\n[ ");
10493c02ab4SGrant Likely 
10593c02ab4SGrant Likely 		prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
10693c02ab4SGrant Likely 		while (size > 0) {
10793c02ab4SGrant Likely 			early_print("'%s' ", prop);
10893c02ab4SGrant Likely 			size -= strlen(prop) + 1;
10993c02ab4SGrant Likely 			prop += strlen(prop) + 1;
11093c02ab4SGrant Likely 		}
11193c02ab4SGrant Likely 		early_print("]\n\n");
11293c02ab4SGrant Likely 
11393c02ab4SGrant Likely 		dump_machine_table(); /* does not return */
11493c02ab4SGrant Likely 	}
11593c02ab4SGrant Likely 
11693c02ab4SGrant Likely 	model = of_get_flat_dt_prop(dt_root, "model", NULL);
11793c02ab4SGrant Likely 	if (!model)
11893c02ab4SGrant Likely 		model = of_get_flat_dt_prop(dt_root, "compatible", NULL);
11993c02ab4SGrant Likely 	if (!model)
12093c02ab4SGrant Likely 		model = "<unknown>";
12193c02ab4SGrant Likely 	pr_info("Machine: %s, model: %s\n", mdesc_best->name, model);
12293c02ab4SGrant Likely 
12393c02ab4SGrant Likely 	/* Retrieve various information from the /chosen node */
12493c02ab4SGrant Likely 	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
12593c02ab4SGrant Likely 	/* Initialize {size,address}-cells info */
12693c02ab4SGrant Likely 	of_scan_flat_dt(early_init_dt_scan_root, NULL);
12793c02ab4SGrant Likely 	/* Setup memory, calling early_init_dt_add_memory_arch */
12893c02ab4SGrant Likely 	of_scan_flat_dt(early_init_dt_scan_memory, NULL);
12993c02ab4SGrant Likely 
13093c02ab4SGrant Likely 	/* Change machine number to match the mdesc we're using */
13193c02ab4SGrant Likely 	__machine_arch_type = mdesc_best->nr;
13293c02ab4SGrant Likely 
13393c02ab4SGrant Likely 	return mdesc_best;
13493c02ab4SGrant Likely }
135