DeviceTree for 3.16:
- 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 thru 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 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJTjzgyAAoJEMhvYp4jgsXiFsUH/1PMTGo8CyD62VQD5ZKdAoW+ Fq6vCiRQ8assF5i5ZLcW1DqhjtoRaCKYhVbRKa5lj7cZdjlSpacI/qQPrF5Br2Ii bTE3Ff/AQwipQaz/Bj7HqJCgGwfWK8xdfgW0abKsyXMWDN86Bov/zzeu8apmws0x H1XjJRgnc/rzM4m9ny6+lss0iq6YL54SuTYNzHR33+Ywxls69SfHXIhCW0KpZcBl 5U3YUOomt40GfO46sxFA4xApAhypEK4oVq7asyiA2ArTZ/c2Pkc9p5CBqzhDLmlq yioWTwHIISv0q+yMLCuQrVGIsbUDkQyy7RQ15z6U+/e/iGO/M+j3A5yxMc3qOi4= =Onff -----END PGP SIGNATURE----- Merge tag 'devicetree-for-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux into next 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 ...
This commit is contained in:
commit
d27050641e
|
@ -13,7 +13,7 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties
|
|||
|
||||
Optional properties:
|
||||
- phys: phy provider specifier
|
||||
- phy-names: shall be "device"
|
||||
- phy-names: shall be "usb2-phy"
|
||||
Refer to phy/phy-bindings.txt for generic phy consumer properties
|
||||
|
||||
Example:
|
||||
|
|
|
@ -77,6 +77,7 @@ 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
|
||||
|
|
|
@ -12,6 +12,5 @@
|
|||
#include <asm-generic/sections.h>
|
||||
|
||||
extern char __arc_dccm_base[];
|
||||
extern char __dtb_start[];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,7 +42,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
|
|||
const struct machine_desc *mdesc;
|
||||
unsigned long dt_root;
|
||||
void *clk;
|
||||
unsigned long len;
|
||||
int len;
|
||||
|
||||
if (!early_init_dt_scan(dt))
|
||||
return NULL;
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#ifdef CONFIG_OF
|
||||
|
||||
extern const 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 */
|
||||
|
@ -24,7 +23,6 @@ static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline void arm_dt_memblock_reserve(void) { }
|
||||
static inline void arm_dt_init_cpu_maps(void) { }
|
||||
|
||||
#endif /* CONFIG_OF */
|
||||
|
|
|
@ -32,51 +32,22 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||
arm_add_memory(base, size);
|
||||
}
|
||||
|
||||
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
||||
{
|
||||
return memblock_virt_alloc(size, align);
|
||||
}
|
||||
|
||||
void __init arm_dt_memblock_reserve(void)
|
||||
{
|
||||
u64 *reserve_map, base, size;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
/* Reserve the dtb region */
|
||||
memblock_reserve(virt_to_phys(initial_boot_params),
|
||||
be32_to_cpu(initial_boot_params->totalsize));
|
||||
|
||||
/*
|
||||
* Process the reserve map. This will probably overlap the initrd
|
||||
* and dtb locations which are already reserved, but overlaping
|
||||
* doesn't hurt anything
|
||||
*/
|
||||
reserve_map = ((void*)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_mem_rsvmap);
|
||||
while (1) {
|
||||
base = be64_to_cpup(reserve_map++);
|
||||
size = be64_to_cpup(reserve_map++);
|
||||
if (!size)
|
||||
break;
|
||||
memblock_reserve(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern struct of_cpu_method __cpu_method_of_table_begin[];
|
||||
extern struct of_cpu_method __cpu_method_of_table_end[];
|
||||
extern struct of_cpu_method __cpu_method_of_table[];
|
||||
|
||||
static const struct of_cpu_method __cpu_method_of_table_sentinel
|
||||
__used __section(__cpu_method_of_table_end);
|
||||
|
||||
|
||||
static int __init set_smp_ops_by_method(struct device_node *node)
|
||||
{
|
||||
const char *method;
|
||||
struct of_cpu_method *m = __cpu_method_of_table_begin;
|
||||
struct of_cpu_method *m = __cpu_method_of_table;
|
||||
|
||||
if (of_property_read_string(node, "enable-method", &method))
|
||||
return 0;
|
||||
|
||||
for (; m < __cpu_method_of_table_end; m++)
|
||||
for (; m->method; m++)
|
||||
if (!strcmp(m->method, method)) {
|
||||
smp_set_ops(m->ops);
|
||||
return 1;
|
||||
|
@ -252,7 +223,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
|
|||
|
||||
if (!mdesc) {
|
||||
const char *prop;
|
||||
long size;
|
||||
int size;
|
||||
unsigned long dt_root;
|
||||
|
||||
early_print("\nError: unrecognized/unsupported "
|
||||
|
|
|
@ -202,7 +202,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
|
|||
{
|
||||
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"))
|
||||
|
|
|
@ -289,14 +289,12 @@ int __init mx35_clocks_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __init mx35_clocks_init_dt(struct device_node *ccm_node)
|
||||
static void __init mx35_clocks_init_dt(struct device_node *ccm_node)
|
||||
{
|
||||
clk_data.clks = clk;
|
||||
clk_data.clk_num = ARRAY_SIZE(clk);
|
||||
of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
|
||||
|
||||
mx35_clocks_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt);
|
||||
|
|
|
@ -317,7 +317,6 @@ void __init arm_memblock_init(struct meminfo *mi,
|
|||
#endif
|
||||
|
||||
arm_mm_memblock_reserve();
|
||||
arm_dt_memblock_reserve();
|
||||
|
||||
/* reserve any platform specific memblock areas */
|
||||
if (mdesc->reserve)
|
||||
|
|
|
@ -125,8 +125,8 @@ device_initcall(s5p_mfc_memory_init);
|
|||
int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
__be32 *prop;
|
||||
unsigned long len;
|
||||
const __be32 *prop;
|
||||
int len;
|
||||
struct s5p_mfc_dt_meminfo mfc_mem;
|
||||
|
||||
if (!data)
|
||||
|
|
|
@ -126,8 +126,6 @@ static void arm64_memory_present(void)
|
|||
|
||||
void __init arm64_memblock_init(void)
|
||||
{
|
||||
u64 *reserve_map, base, size;
|
||||
|
||||
/* Register the kernel text, kernel data and initrd with memblock */
|
||||
memblock_reserve(__pa(_text), _end - _text);
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
|
@ -142,25 +140,6 @@ void __init arm64_memblock_init(void)
|
|||
memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
|
||||
memblock_reserve(__pa(idmap_pg_dir), IDMAP_DIR_SIZE);
|
||||
|
||||
/* Reserve the dtb region */
|
||||
memblock_reserve(virt_to_phys(initial_boot_params),
|
||||
be32_to_cpu(initial_boot_params->totalsize));
|
||||
|
||||
/*
|
||||
* Process the reserve map. This will probably overlap the initrd
|
||||
* and dtb locations which are already reserved, but overlapping
|
||||
* doesn't hurt anything
|
||||
*/
|
||||
reserve_map = ((void*)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_mem_rsvmap);
|
||||
while (1) {
|
||||
base = be64_to_cpup(reserve_map++);
|
||||
size = be64_to_cpup(reserve_map++);
|
||||
if (!size)
|
||||
break;
|
||||
memblock_reserve(base, size);
|
||||
}
|
||||
|
||||
early_init_fdt_scan_reserved_mem();
|
||||
dma_contiguous_reserve(0);
|
||||
|
||||
|
|
|
@ -265,8 +265,8 @@ int __init c6x_add_memory(phys_addr_t start, unsigned long size)
|
|||
*/
|
||||
notrace void __init machine_init(unsigned long dt_ptr)
|
||||
{
|
||||
struct boot_param_header *dtb = __va(dt_ptr);
|
||||
struct boot_param_header *fdt = (struct boot_param_header *)_fdt_start;
|
||||
const void *dtb = __va(dt_ptr);
|
||||
const void *fdt = _fdt_start;
|
||||
|
||||
/* interrupts must be masked */
|
||||
set_creg(IER, 2);
|
||||
|
|
|
@ -105,10 +105,6 @@
|
|||
|
||||
extern char _heap_start[];
|
||||
|
||||
#ifdef CONFIG_METAG_BUILTIN_DTB
|
||||
extern u32 __dtb_start[];
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DA_CONSOLE
|
||||
/* Our early channel based console driver */
|
||||
extern struct console dash_console;
|
||||
|
|
|
@ -43,13 +43,13 @@
|
|||
#include <asm/pci-bridge.h>
|
||||
|
||||
#ifdef CONFIG_EARLY_PRINTK
|
||||
static char *stdout;
|
||||
static const char *stdout;
|
||||
|
||||
static int __init early_init_dt_scan_chosen_serial(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
unsigned long l;
|
||||
char *p;
|
||||
int l;
|
||||
const char *p;
|
||||
|
||||
pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname);
|
||||
|
||||
|
@ -80,7 +80,7 @@ static int __init early_init_dt_scan_chosen_serial(unsigned long node,
|
|||
(strncmp(p, "xlnx,opb-uartlite", 17) == 0) ||
|
||||
(strncmp(p, "xlnx,axi-uartlite", 17) == 0) ||
|
||||
(strncmp(p, "xlnx,mdm", 8) == 0)) {
|
||||
unsigned int *addrp;
|
||||
const unsigned int *addrp;
|
||||
|
||||
*(u32 *)data = UARTLITE;
|
||||
|
||||
|
@ -114,34 +114,3 @@ void __init early_init_devtree(void *params)
|
|||
|
||||
pr_debug(" <- early_init_devtree()\n");
|
||||
}
|
||||
|
||||
/*******
|
||||
*
|
||||
* New implementation of the OF "find" APIs, return a refcounted
|
||||
* object, call of_node_put() when done. The device tree and list
|
||||
* are protected by a rw_lock.
|
||||
*
|
||||
* Note that property management will need some locking as well,
|
||||
* this isn't dealt with yet.
|
||||
*
|
||||
*******/
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
|
||||
static struct debugfs_blob_wrapper flat_dt_blob;
|
||||
|
||||
static int __init export_flat_device_tree(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
flat_dt_blob.data = initial_boot_params;
|
||||
flat_dt_blob.size = initial_boot_params->totalsize;
|
||||
|
||||
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
|
||||
of_debugfs_root, &flat_dt_blob);
|
||||
if (!d)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
device_initcall(export_flat_device_tree);
|
||||
#endif
|
||||
|
|
|
@ -1053,36 +1053,26 @@ void prom_free_prom_memory(void)
|
|||
int octeon_prune_device_tree(void);
|
||||
|
||||
extern const char __dtb_octeon_3xxx_begin;
|
||||
extern const char __dtb_octeon_3xxx_end;
|
||||
extern const char __dtb_octeon_68xx_begin;
|
||||
extern const char __dtb_octeon_68xx_end;
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
int dt_size;
|
||||
struct boot_param_header *fdt;
|
||||
const void *fdt;
|
||||
bool do_prune;
|
||||
|
||||
if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
|
||||
fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
|
||||
if (fdt_check_header(fdt))
|
||||
panic("Corrupt Device Tree passed to kernel.");
|
||||
dt_size = be32_to_cpu(fdt->totalsize);
|
||||
do_prune = false;
|
||||
} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
|
||||
fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin;
|
||||
dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin;
|
||||
fdt = &__dtb_octeon_68xx_begin;
|
||||
do_prune = true;
|
||||
} else {
|
||||
fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin;
|
||||
dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
|
||||
fdt = &__dtb_octeon_3xxx_begin;
|
||||
do_prune = true;
|
||||
}
|
||||
|
||||
/* Copy the default tree from init memory. */
|
||||
initial_boot_params = early_init_dt_alloc_memory_arch(dt_size, 8);
|
||||
if (initial_boot_params == NULL)
|
||||
panic("Could not allocate initial_boot_params");
|
||||
memcpy(initial_boot_params, fdt, dt_size);
|
||||
initial_boot_params = (void *)fdt;
|
||||
|
||||
if (do_prune) {
|
||||
octeon_prune_device_tree();
|
||||
|
@ -1090,7 +1080,7 @@ void __init device_tree_init(void)
|
|||
} else {
|
||||
pr_info("Using passed Device Tree.\n");
|
||||
}
|
||||
unflatten_device_tree();
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
static int __initdata disable_octeon_edac_p;
|
||||
|
|
|
@ -67,10 +67,6 @@
|
|||
|
||||
extern int mips_revision_sconid;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
extern struct boot_param_header __dtb_start;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern void mips_pcibios_init(void);
|
||||
#else
|
||||
|
|
|
@ -21,13 +21,13 @@ extern void device_tree_init(void);
|
|||
|
||||
struct boot_param_header;
|
||||
|
||||
extern void __dt_setup_arch(struct boot_param_header *bph);
|
||||
extern void __dt_setup_arch(void *bph);
|
||||
|
||||
#define dt_setup_arch(sym) \
|
||||
({ \
|
||||
extern struct boot_param_header __dtb_##sym##_begin; \
|
||||
extern char __dtb_##sym##_begin[]; \
|
||||
\
|
||||
__dt_setup_arch(&__dtb_##sym##_begin); \
|
||||
__dt_setup_arch(__dtb_##sym##_begin); \
|
||||
})
|
||||
|
||||
#else /* CONFIG_OF */
|
||||
|
|
|
@ -47,7 +47,7 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
|||
return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
|
||||
}
|
||||
|
||||
void __init __dt_setup_arch(struct boot_param_header *bph)
|
||||
void __init __dt_setup_arch(void *bph)
|
||||
{
|
||||
if (!early_init_dt_scan(bph))
|
||||
return;
|
||||
|
|
|
@ -71,23 +71,12 @@ void __init plat_mem_setup(void)
|
|||
* Load the builtin devicetree. This causes the chosen node to be
|
||||
* parsed resulting in our memory appearing
|
||||
*/
|
||||
__dt_setup_arch(&__dtb_start);
|
||||
__dt_setup_arch(__dtb_start);
|
||||
}
|
||||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
unsigned long base, size;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
base = virt_to_phys((void *)initial_boot_params);
|
||||
size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
|
||||
/* Before we do anything, lets reserve the dt blob */
|
||||
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
|
||||
|
||||
unflatten_device_tree();
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
|
|
|
@ -26,6 +26,4 @@ struct ltq_soc_info {
|
|||
extern void ltq_soc_detect(struct ltq_soc_info *i);
|
||||
extern void ltq_soc_init(void);
|
||||
|
||||
extern struct boot_param_header __dtb_start;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,17 +69,17 @@ static void __init parse_memsize_param(void)
|
|||
if (!memsize)
|
||||
return;
|
||||
|
||||
offset = fdt_path_offset(&__dtb_start, "/memory");
|
||||
offset = fdt_path_offset(__dtb_start, "/memory");
|
||||
if (offset > 0) {
|
||||
uint64_t new_value;
|
||||
/*
|
||||
* reg contains 2 32-bits BE values, offset and size. We just
|
||||
* want to replace the size value without affecting the offset
|
||||
*/
|
||||
prop_value = fdt_getprop(&__dtb_start, offset, "reg", &prop_len);
|
||||
prop_value = fdt_getprop(__dtb_start, offset, "reg", &prop_len);
|
||||
new_value = be64_to_cpu(*prop_value);
|
||||
new_value = (new_value & ~0xffffffffllu) | memsize;
|
||||
fdt_setprop_inplace_u64(&__dtb_start, offset, "reg", new_value);
|
||||
fdt_setprop_inplace_u64(__dtb_start, offset, "reg", new_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ void __init plat_mem_setup(void)
|
|||
* Load the builtin devicetree. This causes the chosen node to be
|
||||
* parsed resulting in our memory appearing
|
||||
*/
|
||||
__dt_setup_arch(&__dtb_start);
|
||||
__dt_setup_arch(__dtb_start);
|
||||
}
|
||||
|
||||
void __init device_tree_init(void)
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
#include <asm/prom.h>
|
||||
|
||||
extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[],
|
||||
__dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[], __dtb_start[];
|
||||
__dtb_xlp_fvp_begin[], __dtb_xlp_gvp_begin[];
|
||||
static void *xlp_fdt_blob;
|
||||
|
||||
void __init *xlp_dt_init(void *fdtp)
|
||||
|
@ -87,22 +87,7 @@ void __init xlp_early_init_devtree(void)
|
|||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
unsigned long base, size;
|
||||
struct boot_param_header *fdtp = xlp_fdt_blob;
|
||||
|
||||
if (!fdtp)
|
||||
return;
|
||||
|
||||
base = virt_to_phys(fdtp);
|
||||
size = be32_to_cpu(fdtp->totalsize);
|
||||
|
||||
/* Before we do anything, lets reserve the dt blob */
|
||||
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
|
||||
|
||||
unflatten_device_tree();
|
||||
|
||||
/* free the space reserved for the dt blob */
|
||||
free_bootmem(base, size);
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
static struct of_device_id __initdata xlp_ids[] = {
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
__iomem void *rt_sysc_membase;
|
||||
__iomem void *rt_memc_membase;
|
||||
|
||||
extern struct boot_param_header __dtb_start;
|
||||
|
||||
__iomem void *plat_of_remap_node(const char *node)
|
||||
{
|
||||
struct resource res;
|
||||
|
@ -52,30 +50,7 @@ __iomem void *plat_of_remap_node(const char *node)
|
|||
|
||||
void __init device_tree_init(void)
|
||||
{
|
||||
unsigned long base, size;
|
||||
void *fdt_copy;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
base = virt_to_phys((void *)initial_boot_params);
|
||||
size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
|
||||
/* Before we do anything, lets reserve the dt blob */
|
||||
reserve_bootmem(base, size, BOOTMEM_DEFAULT);
|
||||
|
||||
/* The strings in the flattened tree are referenced directly by the
|
||||
* device tree, so copy the flattened device tree from init memory
|
||||
* to regular memory.
|
||||
*/
|
||||
fdt_copy = alloc_bootmem(size);
|
||||
memcpy(fdt_copy, initial_boot_params, size);
|
||||
initial_boot_params = fdt_copy;
|
||||
|
||||
unflatten_device_tree();
|
||||
|
||||
/* free the space reserved for the dt blob */
|
||||
free_bootmem(base, size);
|
||||
unflatten_and_copy_device_tree();
|
||||
}
|
||||
|
||||
void __init plat_mem_setup(void)
|
||||
|
@ -86,7 +61,7 @@ void __init plat_mem_setup(void)
|
|||
* Load the builtin devicetree. This causes the chosen node to be
|
||||
* parsed resulting in our memory appearing
|
||||
*/
|
||||
__dt_setup_arch(&__dtb_start);
|
||||
__dt_setup_arch(__dtb_start);
|
||||
|
||||
if (soc_info.mem_size)
|
||||
add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M,
|
||||
|
|
|
@ -5,6 +5,4 @@
|
|||
extern char __initrd_start, __initrd_end;
|
||||
#endif
|
||||
|
||||
extern u32 __dtb_start[];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -51,10 +51,6 @@ static inline void dcr_write_mmio(dcr_host_mmio_t host,
|
|||
out_be32(host.token + ((host.base + dcr_n) * host.stride), value);
|
||||
}
|
||||
|
||||
extern u64 of_translate_dcr_address(struct device_node *dev,
|
||||
unsigned int dcr_n,
|
||||
unsigned int *stride);
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _ASM_POWERPC_DCR_MMIO_H */
|
||||
|
||||
|
|
|
@ -26,6 +26,45 @@
|
|||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
|
||||
#define OF_DT_END_NODE 0x2 /* End node */
|
||||
#define OF_DT_PROP 0x3 /* Property: name off, size,
|
||||
* content */
|
||||
#define OF_DT_NOP 0x4 /* nop */
|
||||
#define OF_DT_END 0x9
|
||||
|
||||
#define OF_DT_VERSION 0x10
|
||||
|
||||
/*
|
||||
* This is what gets passed to the kernel by prom_init or kexec
|
||||
*
|
||||
* The dt struct contains the device tree structure, full pathes and
|
||||
* property contents. The dt strings contain a separate block with just
|
||||
* the strings for the property names, and is fully page aligned and
|
||||
* self contained in a page, so that it can be kept around by the kernel,
|
||||
* each property name appears only once in this page (cheap compression)
|
||||
*
|
||||
* the mem_rsvmap contains a map of reserved ranges of physical memory,
|
||||
* passing it here instead of in the device-tree itself greatly simplifies
|
||||
* the job of everybody. It's just a list of u64 pairs (base/size) that
|
||||
* ends when size is 0
|
||||
*/
|
||||
struct boot_param_header {
|
||||
__be32 magic; /* magic word OF_DT_HEADER */
|
||||
__be32 totalsize; /* total size of DT block */
|
||||
__be32 off_dt_struct; /* offset to structure */
|
||||
__be32 off_dt_strings; /* offset to strings */
|
||||
__be32 off_mem_rsvmap; /* offset to memory reserve map */
|
||||
__be32 version; /* format version */
|
||||
__be32 last_comp_version; /* last compatible version */
|
||||
/* version 2 fields below */
|
||||
__be32 boot_cpuid_phys; /* Physical CPU id we're booting on */
|
||||
/* version 3 fields below */
|
||||
__be32 dt_strings_size; /* size of the DT strings block */
|
||||
/* version 17 fields below */
|
||||
__be32 dt_struct_size; /* size of the DT structure block */
|
||||
};
|
||||
|
||||
/*
|
||||
* OF address retreival & translation
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
# Makefile for the linux kernel.
|
||||
#
|
||||
|
||||
CFLAGS_prom.o = -I$(src)/../../../scripts/dtc/libfdt
|
||||
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
|
||||
|
||||
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
|
||||
|
|
|
@ -36,7 +36,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
|
|||
int depth, void *data)
|
||||
{
|
||||
const u32 *insts;
|
||||
unsigned long len;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
|
||||
|
|
|
@ -55,9 +55,9 @@ int crash_mem_ranges;
|
|||
int __init early_init_dt_scan_fw_dump(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
__be32 *sections;
|
||||
const __be32 *sections;
|
||||
int i, num_sections;
|
||||
unsigned long size;
|
||||
int size;
|
||||
const int *token;
|
||||
|
||||
if (depth != 1 || strcmp(uname, "rtas") != 0)
|
||||
|
|
|
@ -29,11 +29,11 @@
|
|||
#include <linux/bitops.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/libfdt.h>
|
||||
|
||||
#include <asm/prom.h>
|
||||
#include <asm/rtas.h>
|
||||
|
@ -118,14 +118,14 @@ static void __init move_device_tree(void)
|
|||
DBG("-> move_device_tree\n");
|
||||
|
||||
start = __pa(initial_boot_params);
|
||||
size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
size = fdt_totalsize(initial_boot_params);
|
||||
|
||||
if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
|
||||
overlaps_crashkernel(start, size) ||
|
||||
overlaps_initrd(start, size)) {
|
||||
p = __va(memblock_alloc(size, PAGE_SIZE));
|
||||
memcpy(p, initial_boot_params, size);
|
||||
initial_boot_params = (struct boot_param_header *)p;
|
||||
initial_boot_params = p;
|
||||
DBG("Moved device tree to 0x%p\n", p);
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ static struct ibm_pa_feature {
|
|||
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0},
|
||||
};
|
||||
|
||||
static void __init scan_features(unsigned long node, unsigned char *ftrs,
|
||||
static void __init scan_features(unsigned long node, const unsigned char *ftrs,
|
||||
unsigned long tablelen,
|
||||
struct ibm_pa_feature *fp,
|
||||
unsigned long ft_size)
|
||||
|
@ -202,8 +202,8 @@ static void __init scan_features(unsigned long node, unsigned char *ftrs,
|
|||
|
||||
static void __init check_cpu_pa_features(unsigned long node)
|
||||
{
|
||||
unsigned char *pa_ftrs;
|
||||
unsigned long tablelen;
|
||||
const unsigned char *pa_ftrs;
|
||||
int tablelen;
|
||||
|
||||
pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
|
||||
if (pa_ftrs == NULL)
|
||||
|
@ -216,7 +216,7 @@ static void __init check_cpu_pa_features(unsigned long node)
|
|||
#ifdef CONFIG_PPC_STD_MMU_64
|
||||
static void __init check_cpu_slb_size(unsigned long node)
|
||||
{
|
||||
__be32 *slb_size_ptr;
|
||||
const __be32 *slb_size_ptr;
|
||||
|
||||
slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL);
|
||||
if (slb_size_ptr != NULL) {
|
||||
|
@ -257,7 +257,7 @@ static struct feature_property {
|
|||
static inline void identical_pvr_fixup(unsigned long node)
|
||||
{
|
||||
unsigned int pvr;
|
||||
char *model = of_get_flat_dt_prop(node, "model", NULL);
|
||||
const char *model = of_get_flat_dt_prop(node, "model", NULL);
|
||||
|
||||
/*
|
||||
* Since 440GR(x)/440EP(x) processors have the same pvr,
|
||||
|
@ -295,11 +295,11 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
const char *uname, int depth,
|
||||
void *data)
|
||||
{
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
const __be32 *prop;
|
||||
const __be32 *intserv;
|
||||
int i, nthreads;
|
||||
unsigned long len;
|
||||
int len;
|
||||
int found = -1;
|
||||
int found_thread = 0;
|
||||
|
||||
|
@ -325,9 +325,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
* version 2 of the kexec param format adds the phys cpuid of
|
||||
* booted proc.
|
||||
*/
|
||||
if (be32_to_cpu(initial_boot_params->version) >= 2) {
|
||||
if (fdt_version(initial_boot_params) >= 2) {
|
||||
if (be32_to_cpu(intserv[i]) ==
|
||||
be32_to_cpu(initial_boot_params->boot_cpuid_phys)) {
|
||||
fdt_boot_cpuid_phys(initial_boot_params)) {
|
||||
found = boot_cpu_count;
|
||||
found_thread = i;
|
||||
}
|
||||
|
@ -392,7 +392,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
|
|||
int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
unsigned long *lprop; /* All these set by kernel, so no need to convert endian */
|
||||
const unsigned long *lprop; /* All these set by kernel, so no need to convert endian */
|
||||
|
||||
/* Use common scan routine to determine if this is the chosen node */
|
||||
if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
|
||||
|
@ -443,8 +443,9 @@ int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
|
|||
*/
|
||||
static int __init early_init_dt_scan_drconf_memory(unsigned long node)
|
||||
{
|
||||
__be32 *dm, *ls, *usm;
|
||||
unsigned long l, n, flags;
|
||||
const __be32 *dm, *ls, *usm;
|
||||
int l;
|
||||
unsigned long n, flags;
|
||||
u64 base, size, memblock_size;
|
||||
unsigned int is_kexec_kdump = 0, rngs;
|
||||
|
||||
|
@ -564,9 +565,12 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
|
|||
|
||||
static void __init early_reserve_mem_dt(void)
|
||||
{
|
||||
unsigned long i, len, dt_root;
|
||||
unsigned long i, dt_root;
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
|
||||
early_init_fdt_scan_reserved_mem();
|
||||
|
||||
dt_root = of_get_flat_dt_root();
|
||||
|
||||
prop = of_get_flat_dt_prop(dt_root, "reserved-ranges", &len);
|
||||
|
@ -589,24 +593,14 @@ static void __init early_reserve_mem_dt(void)
|
|||
memblock_reserve(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
early_init_fdt_scan_reserved_mem();
|
||||
}
|
||||
|
||||
static void __init early_reserve_mem(void)
|
||||
{
|
||||
u64 base, size;
|
||||
__be64 *reserve_map;
|
||||
unsigned long self_base;
|
||||
unsigned long self_size;
|
||||
|
||||
reserve_map = (__be64 *)(((unsigned long)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_mem_rsvmap));
|
||||
|
||||
/* before we do anything, lets reserve the dt blob */
|
||||
self_base = __pa((unsigned long)initial_boot_params);
|
||||
self_size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
memblock_reserve(self_base, self_size);
|
||||
fdt_off_mem_rsvmap(initial_boot_params));
|
||||
|
||||
/* Look for the new "reserved-regions" property in the DT */
|
||||
early_reserve_mem_dt();
|
||||
|
@ -636,26 +630,12 @@ static void __init early_reserve_mem(void)
|
|||
size_32 = be32_to_cpup(reserve_map_32++);
|
||||
if (size_32 == 0)
|
||||
break;
|
||||
/* skip if the reservation is for the blob */
|
||||
if (base_32 == self_base && size_32 == self_size)
|
||||
continue;
|
||||
DBG("reserving: %x -> %x\n", base_32, size_32);
|
||||
memblock_reserve(base_32, size_32);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
DBG("Processing reserve map\n");
|
||||
|
||||
/* Handle the reserve map in the fdt blob if it exists */
|
||||
while (1) {
|
||||
base = be64_to_cpup(reserve_map++);
|
||||
size = be64_to_cpup(reserve_map++);
|
||||
if (size == 0)
|
||||
break;
|
||||
DBG("reserving: %llx -> %llx\n", base, size);
|
||||
memblock_reserve(base, size);
|
||||
}
|
||||
}
|
||||
|
||||
void __init early_init_devtree(void *params)
|
||||
|
@ -922,23 +902,3 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id)
|
|||
{
|
||||
return (int)phys_id == get_hard_smp_processor_id(cpu);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
|
||||
static struct debugfs_blob_wrapper flat_dt_blob;
|
||||
|
||||
static int __init export_flat_device_tree(void)
|
||||
{
|
||||
struct dentry *d;
|
||||
|
||||
flat_dt_blob.data = initial_boot_params;
|
||||
flat_dt_blob.size = be32_to_cpu(initial_boot_params->totalsize);
|
||||
|
||||
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
|
||||
powerpc_debugfs_root, &flat_dt_blob);
|
||||
if (!d)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
__initcall(export_flat_device_tree);
|
||||
#endif
|
||||
|
|
|
@ -1142,7 +1142,7 @@ void __init rtas_initialize(void)
|
|||
int __init early_init_dt_scan_rtas(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
u32 *basep, *entryp, *sizep;
|
||||
const u32 *basep, *entryp, *sizep;
|
||||
|
||||
if (depth != 1 || strcmp(uname, "rtas") != 0)
|
||||
return 0;
|
||||
|
|
|
@ -269,9 +269,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node,
|
|||
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 +324,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
|
|||
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)
|
||||
|
@ -406,9 +406,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
|
|||
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 +550,8 @@ static int __init htab_dt_scan_pftsize(unsigned long node,
|
|||
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)
|
||||
|
|
|
@ -199,8 +199,8 @@ static void __init efika_setup_arch(void)
|
|||
|
||||
static int __init efika_probe(void)
|
||||
{
|
||||
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"model", NULL);
|
||||
const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"model", NULL);
|
||||
|
||||
if (model == NULL)
|
||||
return 0;
|
||||
|
|
|
@ -574,8 +574,8 @@ chrp_init2(void)
|
|||
|
||||
static int __init chrp_probe(void)
|
||||
{
|
||||
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"device_type", NULL);
|
||||
const char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
|
||||
"device_type", NULL);
|
||||
if (dtype == NULL)
|
||||
return 0;
|
||||
if (strcmp(dtype, "chrp"))
|
||||
|
|
|
@ -61,7 +61,7 @@ int __init early_init_dt_scan_opal(unsigned long node,
|
|||
const char *uname, int depth, void *data)
|
||||
{
|
||||
const void *basep, *entryp, *sizep;
|
||||
unsigned long basesz, entrysz, runtimesz;
|
||||
int basesz, entrysz, runtimesz;
|
||||
|
||||
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
|
||||
return 0;
|
||||
|
@ -77,11 +77,11 @@ int __init early_init_dt_scan_opal(unsigned long node,
|
|||
opal.entry = of_read_number(entryp, entrysz/4);
|
||||
opal.size = of_read_number(sizep, runtimesz/4);
|
||||
|
||||
pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%ld)\n",
|
||||
pr_debug("OPAL Base = 0x%llx (basep=%p basesz=%d)\n",
|
||||
opal.base, basep, basesz);
|
||||
pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%ld)\n",
|
||||
pr_debug("OPAL Entry = 0x%llx (entryp=%p basesz=%d)\n",
|
||||
opal.entry, entryp, entrysz);
|
||||
pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%ld)\n",
|
||||
pr_debug("OPAL Entry = 0x%llx (sizep=%p runtimesz=%d)\n",
|
||||
opal.size, sizep, runtimesz);
|
||||
|
||||
powerpc_firmware_features |= FW_FEATURE_OPAL;
|
||||
|
@ -102,7 +102,7 @@ int __init early_init_dt_scan_opal(unsigned long node,
|
|||
int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
|
||||
const char *uname, int depth, void *data)
|
||||
{
|
||||
unsigned long i, psize, size;
|
||||
int i, psize, size;
|
||||
const __be32 *prop;
|
||||
|
||||
if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
|
||||
|
@ -359,7 +359,7 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count)
|
|||
if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0)
|
||||
return 0;
|
||||
len = cpu_to_be64(count);
|
||||
rc = opal_console_read(vtermno, &len, buf);
|
||||
rc = opal_console_read(vtermno, &len, buf);
|
||||
if (rc == OPAL_SUCCESS)
|
||||
return be64_to_cpu(len);
|
||||
return 0;
|
||||
|
|
|
@ -665,7 +665,7 @@ static int __init pseries_probe_fw_features(unsigned long node,
|
|||
void *data)
|
||||
{
|
||||
const char *prop;
|
||||
unsigned long len;
|
||||
int len;
|
||||
static int hypertas_found;
|
||||
static int vec5_found;
|
||||
|
||||
|
@ -698,7 +698,7 @@ static int __init pseries_probe_fw_features(unsigned long node,
|
|||
static int __init pSeries_probe(void)
|
||||
{
|
||||
unsigned long root = of_get_flat_dt_root();
|
||||
char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
|
||||
const char *dtype = of_get_flat_dt_prop(root, "device_type", NULL);
|
||||
|
||||
if (dtype == NULL)
|
||||
return 0;
|
||||
|
|
|
@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len);
|
|||
|
||||
#ifdef CONFIG_PPC_DCR_MMIO
|
||||
|
||||
u64 of_translate_dcr_address(struct device_node *dev,
|
||||
unsigned int dcr_n,
|
||||
unsigned int *out_stride)
|
||||
static u64 of_translate_dcr_address(struct device_node *dev,
|
||||
unsigned int dcr_n,
|
||||
unsigned int *out_stride)
|
||||
{
|
||||
struct device_node *dp;
|
||||
const u32 *p;
|
||||
|
|
|
@ -206,23 +206,21 @@ static void __init dtb_apic_setup(void)
|
|||
static void __init x86_flattree_get_config(void)
|
||||
{
|
||||
u32 size, map_len;
|
||||
struct boot_param_header *dt;
|
||||
void *dt;
|
||||
|
||||
if (!initial_dtb)
|
||||
return;
|
||||
|
||||
map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
|
||||
(u64)sizeof(struct boot_param_header));
|
||||
map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
|
||||
|
||||
dt = early_memremap(initial_dtb, map_len);
|
||||
size = be32_to_cpu(dt->totalsize);
|
||||
initial_boot_params = dt = early_memremap(initial_dtb, map_len);
|
||||
size = of_get_flat_dt_size();
|
||||
if (map_len < size) {
|
||||
early_iounmap(dt, map_len);
|
||||
dt = early_memremap(initial_dtb, size);
|
||||
initial_boot_params = dt = early_memremap(initial_dtb, size);
|
||||
map_len = size;
|
||||
}
|
||||
|
||||
initial_boot_params = dt;
|
||||
unflatten_and_copy_device_tree();
|
||||
early_iounmap(dt, map_len);
|
||||
}
|
||||
|
|
|
@ -74,7 +74,6 @@ extern int initrd_below_start_ok;
|
|||
#endif
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
extern u32 __dtb_start[];
|
||||
void *dtb_start = __dtb_start;
|
||||
#endif
|
||||
|
||||
|
@ -199,7 +198,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
|
|||
int depth, void *data)
|
||||
{
|
||||
const __be32 *ranges;
|
||||
unsigned long len;
|
||||
int len;
|
||||
|
||||
if (depth > 1)
|
||||
return 0;
|
||||
|
|
|
@ -131,9 +131,12 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname);
|
|||
*/
|
||||
int platform_get_irq_byname(struct platform_device *dev, const char *name)
|
||||
{
|
||||
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ,
|
||||
name);
|
||||
struct resource *r;
|
||||
|
||||
if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node)
|
||||
return of_irq_get_byname(dev->dev.of_node, name);
|
||||
|
||||
r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
|
||||
return r ? r->start : -ENXIO;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_get_irq_byname);
|
||||
|
|
|
@ -24,8 +24,7 @@ static DEFINE_SPINLOCK(clk_lock);
|
|||
* Gate clocks
|
||||
*/
|
||||
|
||||
static void __init rk2928_gate_clk_init(struct device_node *node,
|
||||
void *data)
|
||||
static void __init rk2928_gate_clk_init(struct device_node *node)
|
||||
{
|
||||
struct clk_onecell_data *clk_data;
|
||||
const char *clk_parent;
|
||||
|
|
|
@ -1278,8 +1278,7 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
|
|||
const struct of_device_id *match;
|
||||
void (*setup_function)(struct device_node *, const void *) = function;
|
||||
|
||||
for_each_matching_node(np, clk_match) {
|
||||
match = of_match_node(clk_match, np);
|
||||
for_each_matching_node_and_match(np, clk_match, &match) {
|
||||
data = match->data;
|
||||
setup_function(np, data);
|
||||
}
|
||||
|
@ -1310,7 +1309,7 @@ static void __init sunxi_clock_protect(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void __init sunxi_init_clocks(void)
|
||||
static void __init sunxi_init_clocks(struct device_node *np)
|
||||
{
|
||||
/* Register factor clocks */
|
||||
of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
|
||||
|
|
|
@ -221,7 +221,7 @@ static void __init of_ti_gate_clk_setup(struct device_node *node)
|
|||
{
|
||||
_of_ti_gate_clk_setup(node, &omap_gate_clk_ops, NULL);
|
||||
}
|
||||
CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup)
|
||||
CLK_OF_DECLARE(ti_gate_clk, "ti,gate-clock", of_ti_gate_clk_setup);
|
||||
|
||||
static void __init of_ti_wait_gate_clk_setup(struct device_node *node)
|
||||
{
|
||||
|
|
|
@ -27,7 +27,7 @@ void __init clocksource_of_init(void)
|
|||
{
|
||||
struct device_node *np;
|
||||
const struct of_device_id *match;
|
||||
clocksource_of_init_fn init_func;
|
||||
of_init_fn_1 init_func;
|
||||
unsigned clocksources = 0;
|
||||
|
||||
for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
|
||||
|
|
|
@ -96,7 +96,7 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
|
|||
.xlate = irq_domain_xlate_onecell,
|
||||
};
|
||||
|
||||
static void __init icoll_of_init(struct device_node *np,
|
||||
static int __init icoll_of_init(struct device_node *np,
|
||||
struct device_node *interrupt_parent)
|
||||
{
|
||||
icoll_base = of_iomap(np, 0);
|
||||
|
@ -110,6 +110,6 @@ static void __init icoll_of_init(struct device_node *np,
|
|||
|
||||
icoll_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
|
||||
&icoll_irq_domain_ops, NULL);
|
||||
WARN_ON(!icoll_domain);
|
||||
return icoll_domain ? 0 : -ENODEV;
|
||||
}
|
||||
IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
|
||||
|
|
|
@ -1323,8 +1323,7 @@ static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
|
|||
};
|
||||
|
||||
int __init s3c2410_init_intc_of(struct device_node *np,
|
||||
struct device_node *interrupt_parent,
|
||||
struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
|
||||
struct device_node *interrupt_parent)
|
||||
{
|
||||
return s3c_init_intc_of(np, interrupt_parent,
|
||||
s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
|
||||
|
@ -1346,8 +1345,7 @@ static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
|
|||
};
|
||||
|
||||
int __init s3c2416_init_intc_of(struct device_node *np,
|
||||
struct device_node *interrupt_parent,
|
||||
struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
|
||||
struct device_node *interrupt_parent)
|
||||
{
|
||||
return s3c_init_intc_of(np, interrupt_parent,
|
||||
s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
* special section.
|
||||
*/
|
||||
static const struct of_device_id
|
||||
irqchip_of_match_end __used __section(__irqchip_of_end);
|
||||
irqchip_of_match_end __used __section(__irqchip_of_table_end);
|
||||
|
||||
extern struct of_device_id __irqchip_begin[];
|
||||
extern struct of_device_id __irqchip_of_table[];
|
||||
|
||||
void __init irqchip_init(void)
|
||||
{
|
||||
of_irq_init(__irqchip_begin);
|
||||
of_irq_init(__irqchip_of_table);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#ifndef _IRQCHIP_H
|
||||
#define _IRQCHIP_H
|
||||
|
||||
#include <linux/of.h>
|
||||
|
||||
/*
|
||||
* This macro must be used by the different irqchip drivers to declare
|
||||
* the association between their DT compatible string and their
|
||||
|
@ -21,9 +23,6 @@
|
|||
* @compstr: compatible string of the irqchip driver
|
||||
* @fn: initialization function
|
||||
*/
|
||||
#define IRQCHIP_DECLARE(name,compstr,fn) \
|
||||
static const struct of_device_id irqchip_of_match_##name \
|
||||
__used __section(__irqchip_of_table) \
|
||||
= { .compatible = compstr, .data = fn }
|
||||
#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@ config OF_SELFTEST
|
|||
config OF_FLATTREE
|
||||
bool
|
||||
select DTC
|
||||
select LIBFDT
|
||||
|
||||
config OF_EARLY_FLATTREE
|
||||
bool
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
obj-y = base.o device.o platform.o
|
||||
obj-$(CONFIG_OF_FLATTREE) += fdt.o
|
||||
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
|
||||
obj-$(CONFIG_OF_PROMTREE) += pdt.o
|
||||
obj-$(CONFIG_OF_ADDRESS) += address.o
|
||||
obj-$(CONFIG_OF_IRQ) += irq.o
|
||||
|
@ -10,3 +11,6 @@ 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
|
||||
|
||||
CFLAGS_fdt.o = -I$(src)/../../scripts/dtc/libfdt
|
||||
CFLAGS_fdt_address.o = -I$(src)/../../scripts/dtc/libfdt
|
||||
|
|
|
@ -498,8 +498,7 @@ static u64 __of_translate_address(struct device_node *dev,
|
|||
/* Count address cells & copy address locally */
|
||||
bus->count_cells(dev, &na, &ns);
|
||||
if (!OF_CHECK_COUNTS(na, ns)) {
|
||||
printk(KERN_ERR "prom_parse: Bad cell count for %s\n",
|
||||
of_node_full_name(dev));
|
||||
pr_debug("OF: Bad cell count for %s\n", of_node_full_name(dev));
|
||||
goto bail;
|
||||
}
|
||||
memcpy(addr, in_addr, na * 4);
|
||||
|
@ -564,25 +563,6 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
|
|||
}
|
||||
EXPORT_SYMBOL(of_translate_dma_address);
|
||||
|
||||
bool of_can_translate_address(struct device_node *dev)
|
||||
{
|
||||
struct device_node *parent;
|
||||
struct of_bus *bus;
|
||||
int na, ns;
|
||||
|
||||
parent = of_get_parent(dev);
|
||||
if (parent == NULL)
|
||||
return false;
|
||||
|
||||
bus = of_match_bus(parent);
|
||||
bus->count_cells(dev, &na, &ns);
|
||||
|
||||
of_node_put(parent);
|
||||
|
||||
return OF_CHECK_COUNTS(na, ns);
|
||||
}
|
||||
EXPORT_SYMBOL(of_can_translate_address);
|
||||
|
||||
const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
|
||||
unsigned int *flags)
|
||||
{
|
||||
|
|
|
@ -695,6 +695,25 @@ struct device_node *of_get_next_parent(struct device_node *node)
|
|||
}
|
||||
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 @@ struct device_node *of_get_next_child(const struct device_node *node,
|
|||
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 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
|
|||
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 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
|
|||
}
|
||||
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 @@ int of_update_property(struct device_node *np, struct property *newprop)
|
|||
{
|
||||
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)
|
||||
|
@ -1809,34 +1882,34 @@ int of_update_property(struct device_node *np, struct property *newprop)
|
|||
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;
|
||||
|
|
448
drivers/of/fdt.c
448
drivers/of/fdt.c
|
@ -12,7 +12,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/initrd.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
@ -20,62 +19,13 @@
|
|||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/serial_core.h>
|
||||
|
||||
#include <asm/setup.h> /* for COMMAND_LINE_SIZE */
|
||||
#ifdef CONFIG_PPC
|
||||
#include <asm/machdep.h>
|
||||
#endif /* CONFIG_PPC */
|
||||
|
||||
#include <asm/page.h>
|
||||
|
||||
char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
|
||||
{
|
||||
return ((char *)blob) +
|
||||
be32_to_cpu(blob->off_dt_strings) + offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_fdt_get_property - Given a node in the given flat blob, return
|
||||
* the property ptr
|
||||
*/
|
||||
void *of_fdt_get_property(struct boot_param_header *blob,
|
||||
unsigned long node, const char *name,
|
||||
unsigned long *size)
|
||||
{
|
||||
unsigned long p = node;
|
||||
|
||||
do {
|
||||
u32 tag = be32_to_cpup((__be32 *)p);
|
||||
u32 sz, noff;
|
||||
const char *nstr;
|
||||
|
||||
p += 4;
|
||||
if (tag == OF_DT_NOP)
|
||||
continue;
|
||||
if (tag != OF_DT_PROP)
|
||||
return NULL;
|
||||
|
||||
sz = be32_to_cpup((__be32 *)p);
|
||||
noff = be32_to_cpup((__be32 *)(p + 4));
|
||||
p += 8;
|
||||
if (be32_to_cpu(blob->version) < 0x10)
|
||||
p = ALIGN(p, sz >= 8 ? 8 : 4);
|
||||
|
||||
nstr = of_fdt_get_string(blob, noff);
|
||||
if (nstr == NULL) {
|
||||
pr_warning("Can't find property index name !\n");
|
||||
return NULL;
|
||||
}
|
||||
if (strcmp(name, nstr) == 0) {
|
||||
if (size)
|
||||
*size = sz;
|
||||
return (void *)p;
|
||||
}
|
||||
p += sz;
|
||||
p = ALIGN(p, 4);
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_fdt_is_compatible - Return true if given node from the given blob has
|
||||
* compat in its compatible list
|
||||
|
@ -86,13 +36,14 @@ void *of_fdt_get_property(struct boot_param_header *blob,
|
|||
* On match, returns a non-zero value with smaller values returned for more
|
||||
* specific compatible values.
|
||||
*/
|
||||
int of_fdt_is_compatible(struct boot_param_header *blob,
|
||||
int of_fdt_is_compatible(const void *blob,
|
||||
unsigned long node, const char *compat)
|
||||
{
|
||||
const char *cp;
|
||||
unsigned long cplen, l, score = 0;
|
||||
int cplen;
|
||||
unsigned long l, score = 0;
|
||||
|
||||
cp = of_fdt_get_property(blob, node, "compatible", &cplen);
|
||||
cp = fdt_getprop(blob, node, "compatible", &cplen);
|
||||
if (cp == NULL)
|
||||
return 0;
|
||||
while (cplen > 0) {
|
||||
|
@ -110,7 +61,7 @@ int of_fdt_is_compatible(struct boot_param_header *blob,
|
|||
/**
|
||||
* of_fdt_match - Return true if node matches a list of compatible values
|
||||
*/
|
||||
int of_fdt_match(struct boot_param_header *blob, unsigned long node,
|
||||
int of_fdt_match(const void *blob, unsigned long node,
|
||||
const char *const *compat)
|
||||
{
|
||||
unsigned int tmp, score = 0;
|
||||
|
@ -149,30 +100,29 @@ static void *unflatten_dt_alloc(void **mem, unsigned long size,
|
|||
* @allnextpp: pointer to ->allnext from last allocated device_node
|
||||
* @fpsize: Size of the node path up at the current depth.
|
||||
*/
|
||||
static void * unflatten_dt_node(struct boot_param_header *blob,
|
||||
static void * unflatten_dt_node(void *blob,
|
||||
void *mem,
|
||||
void **p,
|
||||
int *poffset,
|
||||
struct device_node *dad,
|
||||
struct device_node ***allnextpp,
|
||||
unsigned long fpsize)
|
||||
{
|
||||
const __be32 *p;
|
||||
struct device_node *np;
|
||||
struct property *pp, **prev_pp = NULL;
|
||||
char *pathp;
|
||||
u32 tag;
|
||||
const char *pathp;
|
||||
unsigned int l, allocl;
|
||||
static int depth = 0;
|
||||
int old_depth;
|
||||
int offset;
|
||||
int has_name = 0;
|
||||
int new_format = 0;
|
||||
|
||||
tag = be32_to_cpup(*p);
|
||||
if (tag != OF_DT_BEGIN_NODE) {
|
||||
pr_err("Weird tag at start of node: %x\n", tag);
|
||||
pathp = fdt_get_name(blob, *poffset, &l);
|
||||
if (!pathp)
|
||||
return mem;
|
||||
}
|
||||
*p += 4;
|
||||
pathp = *p;
|
||||
l = allocl = strlen(pathp) + 1;
|
||||
*p = PTR_ALIGN(*p + l, 4);
|
||||
|
||||
allocl = l++;
|
||||
|
||||
/* version 0x10 has a more compact unit name here instead of the full
|
||||
* path. we accumulate the full path size using "fpsize", we'll rebuild
|
||||
|
@ -190,7 +140,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
|
|||
fpsize = 1;
|
||||
allocl = 2;
|
||||
l = 1;
|
||||
*pathp = '\0';
|
||||
pathp = "";
|
||||
} else {
|
||||
/* account for '/' and path size minus terminal 0
|
||||
* already in 'l'
|
||||
|
@ -237,32 +187,23 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
|
|||
}
|
||||
}
|
||||
/* process properties */
|
||||
while (1) {
|
||||
u32 sz, noff;
|
||||
char *pname;
|
||||
for (offset = fdt_first_property_offset(blob, *poffset);
|
||||
(offset >= 0);
|
||||
(offset = fdt_next_property_offset(blob, offset))) {
|
||||
const char *pname;
|
||||
u32 sz;
|
||||
|
||||
tag = be32_to_cpup(*p);
|
||||
if (tag == OF_DT_NOP) {
|
||||
*p += 4;
|
||||
continue;
|
||||
}
|
||||
if (tag != OF_DT_PROP)
|
||||
if (!(p = fdt_getprop_by_offset(blob, offset, &pname, &sz))) {
|
||||
offset = -FDT_ERR_INTERNAL;
|
||||
break;
|
||||
*p += 4;
|
||||
sz = be32_to_cpup(*p);
|
||||
noff = be32_to_cpup(*p + 4);
|
||||
*p += 8;
|
||||
if (be32_to_cpu(blob->version) < 0x10)
|
||||
*p = PTR_ALIGN(*p, sz >= 8 ? 8 : 4);
|
||||
}
|
||||
|
||||
pname = of_fdt_get_string(blob, noff);
|
||||
if (pname == NULL) {
|
||||
pr_info("Can't find property name in list !\n");
|
||||
break;
|
||||
}
|
||||
if (strcmp(pname, "name") == 0)
|
||||
has_name = 1;
|
||||
l = strlen(pname) + 1;
|
||||
pp = unflatten_dt_alloc(&mem, sizeof(struct property),
|
||||
__alignof__(struct property));
|
||||
if (allnextpp) {
|
||||
|
@ -274,26 +215,25 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
|
|||
if ((strcmp(pname, "phandle") == 0) ||
|
||||
(strcmp(pname, "linux,phandle") == 0)) {
|
||||
if (np->phandle == 0)
|
||||
np->phandle = be32_to_cpup((__be32*)*p);
|
||||
np->phandle = be32_to_cpup(p);
|
||||
}
|
||||
/* And we process the "ibm,phandle" property
|
||||
* used in pSeries dynamic device tree
|
||||
* stuff */
|
||||
if (strcmp(pname, "ibm,phandle") == 0)
|
||||
np->phandle = be32_to_cpup((__be32 *)*p);
|
||||
pp->name = pname;
|
||||
np->phandle = be32_to_cpup(p);
|
||||
pp->name = (char *)pname;
|
||||
pp->length = sz;
|
||||
pp->value = *p;
|
||||
pp->value = (__be32 *)p;
|
||||
*prev_pp = pp;
|
||||
prev_pp = &pp->next;
|
||||
}
|
||||
*p = PTR_ALIGN((*p) + sz, 4);
|
||||
}
|
||||
/* with version 0x10 we may not have the name property, recreate
|
||||
* it here from the unit name if absent
|
||||
*/
|
||||
if (!has_name) {
|
||||
char *p1 = pathp, *ps = pathp, *pa = NULL;
|
||||
const char *p1 = pathp, *ps = pathp, *pa = NULL;
|
||||
int sz;
|
||||
|
||||
while (*p1) {
|
||||
|
@ -330,19 +270,18 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
|
|||
if (!np->type)
|
||||
np->type = "<NULL>";
|
||||
}
|
||||
while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) {
|
||||
if (tag == OF_DT_NOP)
|
||||
*p += 4;
|
||||
else
|
||||
mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
|
||||
fpsize);
|
||||
tag = be32_to_cpup(*p);
|
||||
}
|
||||
if (tag != OF_DT_END_NODE) {
|
||||
pr_err("Weird tag at end of node: %x\n", tag);
|
||||
return mem;
|
||||
}
|
||||
*p += 4;
|
||||
|
||||
old_depth = depth;
|
||||
*poffset = fdt_next_node(blob, *poffset, &depth);
|
||||
if (depth < 0)
|
||||
depth = 0;
|
||||
while (*poffset > 0 && depth > old_depth)
|
||||
mem = unflatten_dt_node(blob, mem, poffset, np, allnextpp,
|
||||
fpsize);
|
||||
|
||||
if (*poffset < 0 && *poffset != -FDT_ERR_NOTFOUND)
|
||||
pr_err("unflatten: error %d processing FDT\n", *poffset);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
@ -358,12 +297,13 @@ static void * unflatten_dt_node(struct boot_param_header *blob,
|
|||
* @dt_alloc: An allocator that provides a virtual address to memory
|
||||
* for the resulting tree
|
||||
*/
|
||||
static void __unflatten_device_tree(struct boot_param_header *blob,
|
||||
static void __unflatten_device_tree(void *blob,
|
||||
struct device_node **mynodes,
|
||||
void * (*dt_alloc)(u64 size, u64 align))
|
||||
{
|
||||
unsigned long size;
|
||||
void *start, *mem;
|
||||
int start;
|
||||
void *mem;
|
||||
struct device_node **allnextp = mynodes;
|
||||
|
||||
pr_debug(" -> unflatten_device_tree()\n");
|
||||
|
@ -374,18 +314,18 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
|
|||
}
|
||||
|
||||
pr_debug("Unflattening device tree:\n");
|
||||
pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
|
||||
pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
|
||||
pr_debug("version: %08x\n", be32_to_cpu(blob->version));
|
||||
pr_debug("magic: %08x\n", fdt_magic(blob));
|
||||
pr_debug("size: %08x\n", fdt_totalsize(blob));
|
||||
pr_debug("version: %08x\n", fdt_version(blob));
|
||||
|
||||
if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
|
||||
if (fdt_check_header(blob)) {
|
||||
pr_err("Invalid device tree blob header\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* First pass, scan for size */
|
||||
start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
|
||||
size = (unsigned long)unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
|
||||
start = 0;
|
||||
size = (unsigned long)unflatten_dt_node(blob, NULL, &start, NULL, NULL, 0);
|
||||
size = ALIGN(size, 4);
|
||||
|
||||
pr_debug(" size is %lx, allocating...\n", size);
|
||||
|
@ -399,10 +339,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob,
|
|||
pr_debug(" unflattening %p...\n", mem);
|
||||
|
||||
/* Second pass, do actual unflattening */
|
||||
start = ((void *)blob) + be32_to_cpu(blob->off_dt_struct);
|
||||
start = 0;
|
||||
unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
|
||||
if (be32_to_cpup(start) != OF_DT_END)
|
||||
pr_warning("Weird tag at end of tree: %08x\n", be32_to_cpup(start));
|
||||
if (be32_to_cpup(mem + size) != 0xdeadbeef)
|
||||
pr_warning("End of tree marker overwritten: %08x\n",
|
||||
be32_to_cpup(mem + size));
|
||||
|
@ -427,9 +365,7 @@ static void *kernel_tree_alloc(u64 size, u64 align)
|
|||
void of_fdt_unflatten_tree(unsigned long *blob,
|
||||
struct device_node **mynodes)
|
||||
{
|
||||
struct boot_param_header *device_tree =
|
||||
(struct boot_param_header *)blob;
|
||||
__unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
|
||||
__unflatten_device_tree(blob, mynodes, &kernel_tree_alloc);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
|
||||
|
||||
|
@ -437,7 +373,7 @@ EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
|
|||
int __initdata dt_root_addr_cells;
|
||||
int __initdata dt_root_size_cells;
|
||||
|
||||
struct boot_param_header *initial_boot_params;
|
||||
void *initial_boot_params;
|
||||
|
||||
#ifdef CONFIG_OF_EARLY_FLATTREE
|
||||
|
||||
|
@ -449,8 +385,8 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
|
|||
{
|
||||
int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
|
||||
phys_addr_t base, size;
|
||||
unsigned long len;
|
||||
__be32 *prop;
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
int nomap, first = 1;
|
||||
|
||||
prop = of_get_flat_dt_prop(node, "reg", &len);
|
||||
|
@ -493,7 +429,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node,
|
|||
*/
|
||||
static int __init __reserved_mem_check_root(unsigned long node)
|
||||
{
|
||||
__be32 *prop;
|
||||
const __be32 *prop;
|
||||
|
||||
prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
|
||||
if (!prop || be32_to_cpup(prop) != dt_root_size_cells)
|
||||
|
@ -557,9 +493,25 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname,
|
|||
*/
|
||||
void __init early_init_fdt_scan_reserved_mem(void)
|
||||
{
|
||||
int n;
|
||||
u64 base, size;
|
||||
|
||||
if (!initial_boot_params)
|
||||
return;
|
||||
|
||||
/* Reserve the dtb region */
|
||||
early_init_dt_reserve_memory_arch(__pa(initial_boot_params),
|
||||
fdt_totalsize(initial_boot_params),
|
||||
0);
|
||||
|
||||
/* Process header /memreserve/ fields */
|
||||
for (n = 0; ; n++) {
|
||||
fdt_get_mem_rsv(initial_boot_params, n, &base, &size);
|
||||
if (!size)
|
||||
break;
|
||||
early_init_dt_reserve_memory_arch(base, size, 0);
|
||||
}
|
||||
|
||||
of_scan_flat_dt(__fdt_scan_reserved_mem, NULL);
|
||||
fdt_init_reserved_mem();
|
||||
}
|
||||
|
@ -578,47 +530,19 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
|
|||
void *data),
|
||||
void *data)
|
||||
{
|
||||
unsigned long p = ((unsigned long)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_dt_struct);
|
||||
int rc = 0;
|
||||
int depth = -1;
|
||||
const void *blob = initial_boot_params;
|
||||
const char *pathp;
|
||||
int offset, rc = 0, depth = -1;
|
||||
|
||||
do {
|
||||
u32 tag = be32_to_cpup((__be32 *)p);
|
||||
const char *pathp;
|
||||
for (offset = fdt_next_node(blob, -1, &depth);
|
||||
offset >= 0 && depth >= 0 && !rc;
|
||||
offset = fdt_next_node(blob, offset, &depth)) {
|
||||
|
||||
p += 4;
|
||||
if (tag == OF_DT_END_NODE) {
|
||||
depth--;
|
||||
continue;
|
||||
}
|
||||
if (tag == OF_DT_NOP)
|
||||
continue;
|
||||
if (tag == OF_DT_END)
|
||||
break;
|
||||
if (tag == OF_DT_PROP) {
|
||||
u32 sz = be32_to_cpup((__be32 *)p);
|
||||
p += 8;
|
||||
if (be32_to_cpu(initial_boot_params->version) < 0x10)
|
||||
p = ALIGN(p, sz >= 8 ? 8 : 4);
|
||||
p += sz;
|
||||
p = ALIGN(p, 4);
|
||||
continue;
|
||||
}
|
||||
if (tag != OF_DT_BEGIN_NODE) {
|
||||
pr_err("Invalid tag %x in flat device tree!\n", tag);
|
||||
return -EINVAL;
|
||||
}
|
||||
depth++;
|
||||
pathp = (char *)p;
|
||||
p = ALIGN(p + strlen(pathp) + 1, 4);
|
||||
pathp = fdt_get_name(blob, offset, NULL);
|
||||
if (*pathp == '/')
|
||||
pathp = kbasename(pathp);
|
||||
rc = it(p, pathp, depth, data);
|
||||
if (rc != 0)
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
rc = it(offset, pathp, depth, data);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -627,14 +551,15 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
|
|||
*/
|
||||
unsigned long __init of_get_flat_dt_root(void)
|
||||
{
|
||||
unsigned long p = ((unsigned long)initial_boot_params) +
|
||||
be32_to_cpu(initial_boot_params->off_dt_struct);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
|
||||
p += 4;
|
||||
BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
|
||||
p += 4;
|
||||
return ALIGN(p + strlen((char *)p) + 1, 4);
|
||||
/**
|
||||
* of_get_flat_dt_size - Return the total size of the FDT
|
||||
*/
|
||||
int __init of_get_flat_dt_size(void)
|
||||
{
|
||||
return fdt_totalsize(initial_boot_params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -643,10 +568,10 @@ unsigned long __init of_get_flat_dt_root(void)
|
|||
* This function can be used within scan_flattened_dt callback to get
|
||||
* access to properties
|
||||
*/
|
||||
void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||
unsigned long *size)
|
||||
const void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||
int *size)
|
||||
{
|
||||
return of_fdt_get_property(initial_boot_params, node, name, size);
|
||||
return fdt_getprop(initial_boot_params, node, name, size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -676,73 +601,6 @@ struct fdt_scan_status {
|
|||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
* fdt_scan_node_by_path - iterator for of_scan_flat_dt_by_path function
|
||||
*/
|
||||
static int __init fdt_scan_node_by_path(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
struct fdt_scan_status *st = data;
|
||||
|
||||
/*
|
||||
* if scan at the requested fdt node has been completed,
|
||||
* return -ENXIO to abort further scanning
|
||||
*/
|
||||
if (depth <= st->depth)
|
||||
return -ENXIO;
|
||||
|
||||
/* requested fdt node has been found, so call iterator function */
|
||||
if (st->found)
|
||||
return st->iterator(node, uname, depth, st->data);
|
||||
|
||||
/* check if scanning automata is entering next level of fdt nodes */
|
||||
if (depth == st->depth + 1 &&
|
||||
strncmp(st->name, uname, st->namelen) == 0 &&
|
||||
uname[st->namelen] == 0) {
|
||||
st->depth += 1;
|
||||
if (st->name[st->namelen] == 0) {
|
||||
st->found = 1;
|
||||
} else {
|
||||
const char *next = st->name + st->namelen + 1;
|
||||
st->name = next;
|
||||
st->namelen = strcspn(next, "/");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan next fdt node */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* of_scan_flat_dt_by_path - scan flattened tree blob and call callback on each
|
||||
* child of the given path.
|
||||
* @path: path to start searching for children
|
||||
* @it: callback function
|
||||
* @data: context data pointer
|
||||
*
|
||||
* This function is used to scan the flattened device-tree starting from the
|
||||
* node given by path. It is used to extract information (like reserved
|
||||
* memory), which is required on ealy boot before we can unflatten the tree.
|
||||
*/
|
||||
int __init of_scan_flat_dt_by_path(const char *path,
|
||||
int (*it)(unsigned long node, const char *name, int depth, void *data),
|
||||
void *data)
|
||||
{
|
||||
struct fdt_scan_status st = {path, 0, -1, 0, it, data};
|
||||
int ret = 0;
|
||||
|
||||
if (initial_boot_params)
|
||||
ret = of_scan_flat_dt(fdt_scan_node_by_path, &st);
|
||||
|
||||
if (!st.found)
|
||||
return -ENOENT;
|
||||
else if (ret == -ENXIO) /* scan has been completed */
|
||||
return 0;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char * __init of_flat_dt_get_machine_name(void)
|
||||
{
|
||||
const char *name;
|
||||
|
@ -782,7 +640,7 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
|
|||
}
|
||||
if (!best_data) {
|
||||
const char *prop;
|
||||
long size;
|
||||
int size;
|
||||
|
||||
pr_err("\n unrecognized device tree list:\n[ ");
|
||||
|
||||
|
@ -811,8 +669,8 @@ const void * __init of_flat_dt_match_machine(const void *default_match,
|
|||
static void __init early_init_dt_check_for_initrd(unsigned long node)
|
||||
{
|
||||
u64 start, end;
|
||||
unsigned long len;
|
||||
__be32 *prop;
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
|
||||
pr_debug("Looking for initrd properties... ");
|
||||
|
||||
|
@ -839,13 +697,68 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
|
|||
}
|
||||
#endif /* CONFIG_BLK_DEV_INITRD */
|
||||
|
||||
#ifdef CONFIG_SERIAL_EARLYCON
|
||||
extern struct of_device_id __earlycon_of_table[];
|
||||
|
||||
int __init early_init_dt_scan_chosen_serial(void)
|
||||
{
|
||||
int offset;
|
||||
const char *p;
|
||||
int l;
|
||||
const struct of_device_id *match = __earlycon_of_table;
|
||||
const void *fdt = initial_boot_params;
|
||||
|
||||
offset = fdt_path_offset(fdt, "/chosen");
|
||||
if (offset < 0)
|
||||
offset = fdt_path_offset(fdt, "/chosen@0");
|
||||
if (offset < 0)
|
||||
return -ENOENT;
|
||||
|
||||
p = fdt_getprop(fdt, offset, "stdout-path", &l);
|
||||
if (!p)
|
||||
p = fdt_getprop(fdt, offset, "linux,stdout-path", &l);
|
||||
if (!p || !l)
|
||||
return -ENOENT;
|
||||
|
||||
/* Get the node specified by stdout-path */
|
||||
offset = fdt_path_offset(fdt, p);
|
||||
if (offset < 0)
|
||||
return -ENODEV;
|
||||
|
||||
while (match->compatible) {
|
||||
unsigned long addr;
|
||||
if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
|
||||
match++;
|
||||
continue;
|
||||
}
|
||||
|
||||
addr = fdt_translate_address(fdt, offset);
|
||||
if (!addr)
|
||||
return -ENXIO;
|
||||
|
||||
of_setup_earlycon(addr, match->data);
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int __init setup_of_earlycon(char *buf)
|
||||
{
|
||||
if (buf)
|
||||
return 0;
|
||||
|
||||
return early_init_dt_scan_chosen_serial();
|
||||
}
|
||||
early_param("earlycon", setup_of_earlycon);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* early_init_dt_scan_root - fetch the top level address and size cells
|
||||
*/
|
||||
int __init early_init_dt_scan_root(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
__be32 *prop;
|
||||
const __be32 *prop;
|
||||
|
||||
if (depth != 0)
|
||||
return 0;
|
||||
|
@ -867,9 +780,9 @@ int __init early_init_dt_scan_root(unsigned long node, const char *uname,
|
|||
return 1;
|
||||
}
|
||||
|
||||
u64 __init dt_mem_next_cell(int s, __be32 **cellp)
|
||||
u64 __init dt_mem_next_cell(int s, const __be32 **cellp)
|
||||
{
|
||||
__be32 *p = *cellp;
|
||||
const __be32 *p = *cellp;
|
||||
|
||||
*cellp = p + s;
|
||||
return of_read_number(p, s);
|
||||
|
@ -881,9 +794,9 @@ u64 __init dt_mem_next_cell(int s, __be32 **cellp)
|
|||
int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
__be32 *reg, *endp;
|
||||
unsigned long l;
|
||||
const char *type = of_get_flat_dt_prop(node, "device_type", NULL);
|
||||
const __be32 *reg, *endp;
|
||||
int l;
|
||||
|
||||
/* We are scanning "memory" nodes only */
|
||||
if (type == NULL) {
|
||||
|
@ -891,7 +804,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
|
|||
* The longtrail doesn't have a device_type on the
|
||||
* /memory node, so look for the node called /memory@0.
|
||||
*/
|
||||
if (depth != 1 || strcmp(uname, "memory@0") != 0)
|
||||
if (!IS_ENABLED(CONFIG_PPC32) || depth != 1 || strcmp(uname, "memory@0") != 0)
|
||||
return 0;
|
||||
} else if (strcmp(type, "memory") != 0)
|
||||
return 0;
|
||||
|
@ -904,7 +817,7 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
|
|||
|
||||
endp = reg + (l / sizeof(__be32));
|
||||
|
||||
pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
|
||||
pr_debug("memory scan node %s, reg size %d, data: %x %x %x %x,\n",
|
||||
uname, l, reg[0], reg[1], reg[2], reg[3]);
|
||||
|
||||
while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
|
||||
|
@ -927,8 +840,8 @@ int __init early_init_dt_scan_memory(unsigned long node, const char *uname,
|
|||
int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
||||
int depth, void *data)
|
||||
{
|
||||
unsigned long l;
|
||||
char *p;
|
||||
int l;
|
||||
const char *p;
|
||||
|
||||
pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
|
||||
|
||||
|
@ -1003,8 +916,8 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
|
|||
int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base,
|
||||
phys_addr_t size, bool nomap)
|
||||
{
|
||||
pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n",
|
||||
base, size, nomap ? " (nomap)" : "");
|
||||
pr_err("Reserved memory not supported, ignoring range 0x%pa - 0x%pa%s\n",
|
||||
&base, &size, nomap ? " (nomap)" : "");
|
||||
return -ENOSYS;
|
||||
}
|
||||
#endif
|
||||
|
@ -1018,7 +931,7 @@ bool __init early_init_dt_scan(void *params)
|
|||
initial_boot_params = params;
|
||||
|
||||
/* check device tree validity */
|
||||
if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
|
||||
if (fdt_check_header(params)) {
|
||||
initial_boot_params = NULL;
|
||||
return false;
|
||||
}
|
||||
|
@ -1073,9 +986,9 @@ void __init unflatten_and_copy_device_tree(void)
|
|||
return;
|
||||
}
|
||||
|
||||
size = __be32_to_cpu(initial_boot_params->totalsize);
|
||||
size = fdt_totalsize(initial_boot_params);
|
||||
dt = early_init_dt_alloc_memory_arch(size,
|
||||
__alignof__(struct boot_param_header));
|
||||
roundup_pow_of_two(FDT_V17_SIZE));
|
||||
|
||||
if (dt) {
|
||||
memcpy(dt, initial_boot_params, size);
|
||||
|
@ -1084,4 +997,27 @@ void __init unflatten_and_copy_device_tree(void)
|
|||
unflatten_device_tree();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
|
||||
static struct debugfs_blob_wrapper flat_dt_blob;
|
||||
|
||||
static int __init of_flat_dt_debugfs_export_fdt(void)
|
||||
{
|
||||
struct dentry *d = debugfs_create_dir("device-tree", NULL);
|
||||
|
||||
if (!d)
|
||||
return -ENOENT;
|
||||
|
||||
flat_dt_blob.data = initial_boot_params;
|
||||
flat_dt_blob.size = fdt_totalsize(initial_boot_params);
|
||||
|
||||
d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
|
||||
d, &flat_dt_blob);
|
||||
if (!d)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(of_flat_dt_debugfs_export_fdt);
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_OF_EARLY_FLATTREE */
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* FDT Address translation based on u-boot fdt_support.c which in turn was
|
||||
* based on the kernel unflattened DT address translation code.
|
||||
*
|
||||
* (C) Copyright 2007
|
||||
* Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
|
||||
*
|
||||
* Copyright 2010-2011 Freescale Semiconductor, Inc.
|
||||
*
|
||||
* 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, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/libfdt.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
/* Max address size we deal with */
|
||||
#define OF_MAX_ADDR_CELLS 4
|
||||
#define OF_CHECK_COUNTS(na, ns) ((na) > 0 && (na) <= OF_MAX_ADDR_CELLS && \
|
||||
(ns) > 0)
|
||||
|
||||
/* Debug utility */
|
||||
#ifdef DEBUG
|
||||
static void __init of_dump_addr(const char *s, const __be32 *addr, int na)
|
||||
{
|
||||
pr_debug("%s", s);
|
||||
while(na--)
|
||||
pr_cont(" %08x", *(addr++));
|
||||
pr_debug("\n");
|
||||
}
|
||||
#else
|
||||
static void __init of_dump_addr(const char *s, const __be32 *addr, int na) { }
|
||||
#endif
|
||||
|
||||
/* Callbacks for bus specific translators */
|
||||
struct of_bus {
|
||||
void (*count_cells)(const void *blob, int parentoffset,
|
||||
int *addrc, int *sizec);
|
||||
u64 (*map)(__be32 *addr, const __be32 *range,
|
||||
int na, int ns, int pna);
|
||||
int (*translate)(__be32 *addr, u64 offset, int na);
|
||||
};
|
||||
|
||||
/* Default translator (generic bus) */
|
||||
static void __init fdt_bus_default_count_cells(const void *blob, int parentoffset,
|
||||
int *addrc, int *sizec)
|
||||
{
|
||||
const __be32 *prop;
|
||||
|
||||
if (addrc) {
|
||||
prop = fdt_getprop(blob, parentoffset, "#address-cells", NULL);
|
||||
if (prop)
|
||||
*addrc = be32_to_cpup(prop);
|
||||
else
|
||||
*addrc = dt_root_addr_cells;
|
||||
}
|
||||
|
||||
if (sizec) {
|
||||
prop = fdt_getprop(blob, parentoffset, "#size-cells", NULL);
|
||||
if (prop)
|
||||
*sizec = be32_to_cpup(prop);
|
||||
else
|
||||
*sizec = dt_root_size_cells;
|
||||
}
|
||||
}
|
||||
|
||||
static u64 __init fdt_bus_default_map(__be32 *addr, const __be32 *range,
|
||||
int na, int ns, int pna)
|
||||
{
|
||||
u64 cp, s, da;
|
||||
|
||||
cp = of_read_number(range, na);
|
||||
s = of_read_number(range + na + pna, ns);
|
||||
da = of_read_number(addr, na);
|
||||
|
||||
pr_debug("FDT: default map, cp=%llx, s=%llx, da=%llx\n",
|
||||
cp, s, da);
|
||||
|
||||
if (da < cp || da >= (cp + s))
|
||||
return OF_BAD_ADDR;
|
||||
return da - cp;
|
||||
}
|
||||
|
||||
static int __init fdt_bus_default_translate(__be32 *addr, u64 offset, int na)
|
||||
{
|
||||
u64 a = of_read_number(addr, na);
|
||||
memset(addr, 0, na * 4);
|
||||
a += offset;
|
||||
if (na > 1)
|
||||
addr[na - 2] = cpu_to_fdt32(a >> 32);
|
||||
addr[na - 1] = cpu_to_fdt32(a & 0xffffffffu);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Array of bus specific translators */
|
||||
static const struct of_bus of_busses[] __initconst = {
|
||||
/* Default */
|
||||
{
|
||||
.count_cells = fdt_bus_default_count_cells,
|
||||
.map = fdt_bus_default_map,
|
||||
.translate = fdt_bus_default_translate,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init fdt_translate_one(const void *blob, int parent,
|
||||
const struct of_bus *bus,
|
||||
const struct of_bus *pbus, __be32 *addr,
|
||||
int na, int ns, int pna, const char *rprop)
|
||||
{
|
||||
const __be32 *ranges;
|
||||
int rlen;
|
||||
int rone;
|
||||
u64 offset = OF_BAD_ADDR;
|
||||
|
||||
ranges = fdt_getprop(blob, parent, rprop, &rlen);
|
||||
if (!ranges)
|
||||
return 1;
|
||||
if (rlen == 0) {
|
||||
offset = of_read_number(addr, na);
|
||||
memset(addr, 0, pna * 4);
|
||||
pr_debug("FDT: empty ranges, 1:1 translation\n");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
pr_debug("FDT: walking ranges...\n");
|
||||
|
||||
/* Now walk through the ranges */
|
||||
rlen /= 4;
|
||||
rone = na + pna + ns;
|
||||
for (; rlen >= rone; rlen -= rone, ranges += rone) {
|
||||
offset = bus->map(addr, ranges, na, ns, pna);
|
||||
if (offset != OF_BAD_ADDR)
|
||||
break;
|
||||
}
|
||||
if (offset == OF_BAD_ADDR) {
|
||||
pr_debug("FDT: not found !\n");
|
||||
return 1;
|
||||
}
|
||||
memcpy(addr, ranges + na, 4 * pna);
|
||||
|
||||
finish:
|
||||
of_dump_addr("FDT: parent translation for:", addr, pna);
|
||||
pr_debug("FDT: with offset: %llx\n", offset);
|
||||
|
||||
/* Translate it into parent bus space */
|
||||
return pbus->translate(addr, offset, pna);
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate an address from the device-tree into a CPU physical address,
|
||||
* this walks up the tree and applies the various bus mappings on the
|
||||
* way.
|
||||
*
|
||||
* Note: We consider that crossing any level with #size-cells == 0 to mean
|
||||
* that translation is impossible (that is we are not dealing with a value
|
||||
* that can be mapped to a cpu physical address). This is not really specified
|
||||
* that way, but this is traditionally the way IBM at least do things
|
||||
*/
|
||||
u64 __init fdt_translate_address(const void *blob, int node_offset)
|
||||
{
|
||||
int parent, len;
|
||||
const struct of_bus *bus, *pbus;
|
||||
const __be32 *reg;
|
||||
__be32 addr[OF_MAX_ADDR_CELLS];
|
||||
int na, ns, pna, pns;
|
||||
u64 result = OF_BAD_ADDR;
|
||||
|
||||
pr_debug("FDT: ** translation for device %s **\n",
|
||||
fdt_get_name(blob, node_offset, NULL));
|
||||
|
||||
reg = fdt_getprop(blob, node_offset, "reg", &len);
|
||||
if (!reg) {
|
||||
pr_err("FDT: warning: device tree node '%s' has no address.\n",
|
||||
fdt_get_name(blob, node_offset, NULL));
|
||||
goto bail;
|
||||
}
|
||||
|
||||
/* Get parent & match bus type */
|
||||
parent = fdt_parent_offset(blob, node_offset);
|
||||
if (parent < 0)
|
||||
goto bail;
|
||||
bus = &of_busses[0];
|
||||
|
||||
/* Cound address cells & copy address locally */
|
||||
bus->count_cells(blob, parent, &na, &ns);
|
||||
if (!OF_CHECK_COUNTS(na, ns)) {
|
||||
pr_err("FDT: Bad cell count for %s\n",
|
||||
fdt_get_name(blob, node_offset, NULL));
|
||||
goto bail;
|
||||
}
|
||||
memcpy(addr, reg, na * 4);
|
||||
|
||||
pr_debug("FDT: bus (na=%d, ns=%d) on %s\n",
|
||||
na, ns, fdt_get_name(blob, parent, NULL));
|
||||
of_dump_addr("OF: translating address:", addr, na);
|
||||
|
||||
/* Translate */
|
||||
for (;;) {
|
||||
/* Switch to parent bus */
|
||||
node_offset = parent;
|
||||
parent = fdt_parent_offset(blob, node_offset);
|
||||
|
||||
/* If root, we have finished */
|
||||
if (parent < 0) {
|
||||
pr_debug("FDT: reached root node\n");
|
||||
result = of_read_number(addr, na);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get new parent bus and counts */
|
||||
pbus = &of_busses[0];
|
||||
pbus->count_cells(blob, parent, &pna, &pns);
|
||||
if (!OF_CHECK_COUNTS(pna, pns)) {
|
||||
pr_err("FDT: Bad cell count for %s\n",
|
||||
fdt_get_name(blob, node_offset, NULL));
|
||||
break;
|
||||
}
|
||||
|
||||
pr_debug("FDT: parent bus (na=%d, ns=%d) on %s\n",
|
||||
pna, pns, fdt_get_name(blob, parent, NULL));
|
||||
|
||||
/* Apply bus translation */
|
||||
if (fdt_translate_one(blob, node_offset, bus, pbus,
|
||||
addr, na, ns, pna, "ranges"))
|
||||
break;
|
||||
|
||||
/* Complete the move up one level */
|
||||
na = pna;
|
||||
ns = pns;
|
||||
bus = pbus;
|
||||
|
||||
of_dump_addr("FDT: one level translation:", addr, na);
|
||||
}
|
||||
bail:
|
||||
return result;
|
||||
}
|
|
@ -405,6 +405,28 @@ int of_irq_get(struct device_node *dev, int index)
|
|||
return irq_create_of_mapping(&oirq);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number
|
||||
* @dev: pointer to device tree node
|
||||
* @name: irq name
|
||||
*
|
||||
* Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
|
||||
* is not yet created, or error code in case of any other failure.
|
||||
*/
|
||||
int of_irq_get_byname(struct device_node *dev, const char *name)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (unlikely(!name))
|
||||
return -EINVAL;
|
||||
|
||||
index = of_property_match_string(dev, "interrupt-names", name);
|
||||
if (index < 0)
|
||||
return index;
|
||||
|
||||
return of_irq_get(dev, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* of_irq_count - Count the number of IRQs a node uses
|
||||
* @dev: pointer to device tree node
|
||||
|
|
|
@ -18,8 +18,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
|
|||
{
|
||||
struct device_node *dn, *ppnode;
|
||||
struct pci_dev *ppdev;
|
||||
u32 lspec;
|
||||
__be32 lspec_be;
|
||||
__be32 laddr[3];
|
||||
u8 pin;
|
||||
int rc;
|
||||
|
@ -46,7 +44,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
|
|||
return -ENODEV;
|
||||
|
||||
/* Now we walk up the PCI tree */
|
||||
lspec = pin;
|
||||
for (;;) {
|
||||
/* Get the pci_dev of our parent */
|
||||
ppdev = pdev->bus->self;
|
||||
|
@ -80,14 +77,13 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
|
|||
/* We can only get here if we hit a P2P bridge with no node,
|
||||
* let's do standard swizzling and try again
|
||||
*/
|
||||
lspec = pci_swizzle_interrupt_pin(pdev, lspec);
|
||||
pin = pci_swizzle_interrupt_pin(pdev, pin);
|
||||
pdev = ppdev;
|
||||
}
|
||||
|
||||
out_irq->np = ppnode;
|
||||
out_irq->args_count = 1;
|
||||
out_irq->args[0] = lspec;
|
||||
lspec_be = cpu_to_be32(lspec);
|
||||
out_irq->args[0] = pin;
|
||||
laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
|
||||
laddr[1] = laddr[2] = cpu_to_be32(0);
|
||||
return of_irq_parse_raw(laddr, out_irq);
|
||||
|
|
|
@ -95,8 +95,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node,
|
|||
int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
|
||||
phys_addr_t start = 0, end = 0;
|
||||
phys_addr_t base = 0, align = 0, size;
|
||||
unsigned long len;
|
||||
__be32 *prop;
|
||||
int len;
|
||||
const __be32 *prop;
|
||||
int nomap;
|
||||
int ret;
|
||||
|
||||
|
@ -188,7 +188,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
|
|||
if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
|
||||
continue;
|
||||
|
||||
if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) {
|
||||
if (initfn(rmem) == 0) {
|
||||
pr_info("Reserved memory: initialized node %s, compatible id %s\n",
|
||||
rmem->name, compat);
|
||||
return 0;
|
||||
|
|
|
@ -51,10 +51,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np)
|
|||
}
|
||||
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
|
||||
|
@ -68,66 +64,35 @@ EXPORT_SYMBOL(of_find_device_by_node);
|
|||
* 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);
|
||||
/* 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;
|
||||
}
|
||||
#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);
|
||||
return;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,9 +114,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
|
|||
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 */
|
||||
|
|
|
@ -31,6 +31,51 @@ static struct selftest_results {
|
|||
} \
|
||||
}
|
||||
|
||||
static void __init of_selftest_find_node_by_name(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
||||
np = of_find_node_by_path("/testcase-data");
|
||||
selftest(np && !strcmp("/testcase-data", np->full_name),
|
||||
"find /testcase-data failed\n");
|
||||
of_node_put(np);
|
||||
|
||||
/* Test if trailing '/' works */
|
||||
np = of_find_node_by_path("/testcase-data/");
|
||||
selftest(!np, "trailing '/' on /testcase-data/ should fail\n");
|
||||
|
||||
np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
|
||||
selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),
|
||||
"find /testcase-data/phandle-tests/consumer-a failed\n");
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_node_by_path("testcase-alias");
|
||||
selftest(np && !strcmp("/testcase-data", np->full_name),
|
||||
"find testcase-alias failed\n");
|
||||
of_node_put(np);
|
||||
|
||||
/* Test if trailing '/' works on aliases */
|
||||
np = of_find_node_by_path("testcase-alias/");
|
||||
selftest(!np, "trailing '/' on testcase-alias/ should fail\n");
|
||||
|
||||
np = of_find_node_by_path("testcase-alias/phandle-tests/consumer-a");
|
||||
selftest(np && !strcmp("/testcase-data/phandle-tests/consumer-a", np->full_name),
|
||||
"find testcase-alias/phandle-tests/consumer-a failed\n");
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_node_by_path("/testcase-data/missing-path");
|
||||
selftest(!np, "non-existent path returned node %s\n", np->full_name);
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_node_by_path("missing-alias");
|
||||
selftest(!np, "non-existent alias returned node %s\n", np->full_name);
|
||||
of_node_put(np);
|
||||
|
||||
np = of_find_node_by_path("testcase-alias/missing-path");
|
||||
selftest(!np, "non-existent alias with relative path returned node %s\n", np->full_name);
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
static void __init of_selftest_dynamic(void)
|
||||
{
|
||||
struct device_node *np;
|
||||
|
@ -431,8 +476,12 @@ static void __init of_selftest_match_node(void)
|
|||
static void __init of_selftest_platform_populate(void)
|
||||
{
|
||||
int irq;
|
||||
struct device_node *np;
|
||||
struct device_node *np, *child;
|
||||
struct platform_device *pdev;
|
||||
struct of_device_id match[] = {
|
||||
{ .compatible = "test-device", },
|
||||
{}
|
||||
};
|
||||
|
||||
np = of_find_node_by_path("/testcase-data");
|
||||
of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
|
||||
|
@ -440,22 +489,32 @@ static void __init of_selftest_platform_populate(void)
|
|||
/* Test that a missing irq domain returns -EPROBE_DEFER */
|
||||
np = of_find_node_by_path("/testcase-data/testcase-device1");
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
selftest(0, "device 1 creation failed\n");
|
||||
selftest(pdev, "device 1 creation failed\n");
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq != -EPROBE_DEFER)
|
||||
selftest(0, "device deferred probe failed - %d\n", irq);
|
||||
selftest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq);
|
||||
|
||||
/* Test that a parsing failure does not return -EPROBE_DEFER */
|
||||
np = of_find_node_by_path("/testcase-data/testcase-device2");
|
||||
pdev = of_find_device_by_node(np);
|
||||
if (!pdev)
|
||||
selftest(0, "device 2 creation failed\n");
|
||||
selftest(pdev, "device 2 creation failed\n");
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq >= 0 || irq == -EPROBE_DEFER)
|
||||
selftest(0, "device parsing error failed - %d\n", irq);
|
||||
selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq);
|
||||
|
||||
selftest(1, "passed");
|
||||
np = of_find_node_by_path("/testcase-data/platform-tests");
|
||||
if (!np) {
|
||||
pr_err("No testcase data in device tree\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for_each_child_of_node(np, child) {
|
||||
struct device_node *grandchild;
|
||||
of_platform_populate(child, match, NULL, NULL);
|
||||
for_each_child_of_node(child, grandchild)
|
||||
selftest(of_find_device_by_node(grandchild),
|
||||
"Could not create device for node '%s'\n",
|
||||
grandchild->name);
|
||||
}
|
||||
}
|
||||
|
||||
static int __init of_selftest(void)
|
||||
|
@ -470,6 +529,7 @@ static int __init of_selftest(void)
|
|||
of_node_put(np);
|
||||
|
||||
pr_info("start of selftest - you will see error messages\n");
|
||||
of_selftest_find_node_by_name();
|
||||
of_selftest_dynamic();
|
||||
of_selftest_parse_phandle_with_args();
|
||||
of_selftest_property_match_string();
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include "tests-phandle.dtsi"
|
||||
#include "tests-interrupts.dtsi"
|
||||
#include "tests-match.dtsi"
|
||||
#include "tests-platform.dtsi"
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
|
||||
/ {
|
||||
testcase-data {
|
||||
aliases {
|
||||
testcase-alias = &testcase;
|
||||
};
|
||||
|
||||
testcase: testcase-data {
|
||||
security-password = "password";
|
||||
duplicate-name = "duplicate";
|
||||
duplicate-name { };
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
/ {
|
||||
testcase-data {
|
||||
platform-tests {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
test-device@0 {
|
||||
compatible = "test-device";
|
||||
reg = <0x0>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dev@100 {
|
||||
compatible = "test-sub-device";
|
||||
reg = <0x100>;
|
||||
};
|
||||
};
|
||||
|
||||
test-device@1 {
|
||||
compatible = "test-device";
|
||||
reg = <0x1>;
|
||||
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
dev@100 {
|
||||
compatible = "test-sub-device";
|
||||
reg = <0x100>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -2072,6 +2072,7 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
|
|||
return 0;
|
||||
}
|
||||
EARLYCON_DECLARE(pl011, pl011_early_console_setup);
|
||||
OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
|
||||
|
||||
#else
|
||||
#define AMBA_CONSOLE NULL
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
|
||||
#ifdef CONFIG_FIX_EARLYCON_MEM
|
||||
#include <asm/fixmap.h>
|
||||
|
@ -32,6 +34,9 @@ static struct earlycon_device early_console_dev = {
|
|||
.con = &early_con,
|
||||
};
|
||||
|
||||
static const struct of_device_id __earlycon_of_table_sentinel
|
||||
__used __section(__earlycon_of_table_end);
|
||||
|
||||
static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
|
||||
{
|
||||
void __iomem *base;
|
||||
|
@ -142,3 +147,26 @@ int __init setup_earlycon(char *buf, const char *match,
|
|||
register_console(early_console_dev.con);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init of_setup_earlycon(unsigned long addr,
|
||||
int (*setup)(struct earlycon_device *, const char *))
|
||||
{
|
||||
int err;
|
||||
struct uart_port *port = &early_console_dev.port;
|
||||
|
||||
port->iotype = UPIO_MEM;
|
||||
port->mapbase = addr;
|
||||
port->uartclk = BASE_BAUD * 16;
|
||||
port->membase = earlycon_map(addr, SZ_4K);
|
||||
|
||||
early_console_dev.con->data = &early_console_dev;
|
||||
err = setup(&early_console_dev, NULL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
if (!early_console_dev.con->write)
|
||||
return -ENODEV;
|
||||
|
||||
|
||||
register_console(early_console_dev.con);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -139,52 +139,23 @@
|
|||
#define TRACE_SYSCALLS()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_CLKSRC_OF
|
||||
#define CLKSRC_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__clksrc_of_table) = .; \
|
||||
*(__clksrc_of_table) \
|
||||
*(__clksrc_of_table_end)
|
||||
#else
|
||||
#define CLKSRC_OF_TABLES()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IRQCHIP
|
||||
#define IRQCHIP_OF_MATCH_TABLE() \
|
||||
#define ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name)
|
||||
#define __OF_TABLE(cfg, name) ___OF_TABLE(cfg, name)
|
||||
#define OF_TABLE(cfg, name) __OF_TABLE(config_enabled(cfg), name)
|
||||
#define _OF_TABLE_0(name)
|
||||
#define _OF_TABLE_1(name) \
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__irqchip_begin) = .; \
|
||||
*(__irqchip_of_table) \
|
||||
*(__irqchip_of_end)
|
||||
#else
|
||||
#define IRQCHIP_OF_MATCH_TABLE()
|
||||
#endif
|
||||
VMLINUX_SYMBOL(__##name##_of_table) = .; \
|
||||
*(__##name##_of_table) \
|
||||
*(__##name##_of_table_end)
|
||||
|
||||
#ifdef CONFIG_COMMON_CLK
|
||||
#define CLK_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__clk_of_table) = .; \
|
||||
*(__clk_of_table) \
|
||||
*(__clk_of_table_end)
|
||||
#else
|
||||
#define CLK_OF_TABLES()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OF_RESERVED_MEM
|
||||
#define RESERVEDMEM_OF_TABLES() \
|
||||
. = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__reservedmem_of_table) = .; \
|
||||
*(__reservedmem_of_table) \
|
||||
*(__reservedmem_of_table_end)
|
||||
#else
|
||||
#define RESERVEDMEM_OF_TABLES()
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \
|
||||
VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \
|
||||
*(__cpu_method_of_table) \
|
||||
VMLINUX_SYMBOL(__cpu_method_of_table_end) = .;
|
||||
#else
|
||||
#define CPU_METHOD_OF_TABLES()
|
||||
#endif
|
||||
#define CLKSRC_OF_TABLES() OF_TABLE(CONFIG_CLKSRC_OF, clksrc)
|
||||
#define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)
|
||||
#define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk)
|
||||
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
|
||||
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
|
||||
#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
|
||||
|
||||
#define KERNEL_DTB() \
|
||||
STRUCT_ALIGN(); \
|
||||
|
@ -513,7 +484,8 @@
|
|||
CLKSRC_OF_TABLES() \
|
||||
CPU_METHOD_OF_TABLES() \
|
||||
KERNEL_DTB() \
|
||||
IRQCHIP_OF_MATCH_TABLE()
|
||||
IRQCHIP_OF_MATCH_TABLE() \
|
||||
EARLYCON_OF_TABLES()
|
||||
|
||||
#define INIT_TEXT \
|
||||
*(.init.text) \
|
||||
|
|
|
@ -529,10 +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,
|
||||
|
|
|
@ -339,23 +339,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
|
|||
|
||||
extern int clocksource_i8253_init(void);
|
||||
|
||||
struct device_node;
|
||||
typedef void(*clocksource_of_init_fn)(struct device_node *);
|
||||
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
|
||||
OF_DECLARE_1(clksrc, name, compat, fn)
|
||||
|
||||
#ifdef CONFIG_CLKSRC_OF
|
||||
extern void clocksource_of_init(void);
|
||||
|
||||
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
|
||||
static const struct of_device_id __clksrc_of_table_##name \
|
||||
__used __section(__clksrc_of_table) \
|
||||
= { .compatible = compat, \
|
||||
.data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
|
||||
#else
|
||||
static inline void clocksource_of_init(void) {}
|
||||
#define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
|
||||
static const struct of_device_id __clksrc_of_table_##name \
|
||||
__attribute__((unused)) \
|
||||
= { .compatible = compat, \
|
||||
.data = (fn == (clocksource_of_init_fn)NULL) ? fn : fn }
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_CLOCKSOURCE_H */
|
||||
|
|
|
@ -764,4 +764,26 @@ static inline int of_get_available_child_count(const struct device_node *np)
|
|||
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 */
|
||||
|
|
|
@ -40,7 +40,6 @@ extern u64 of_translate_dma_address(struct device_node *dev,
|
|||
|
||||
#ifdef CONFIG_OF_ADDRESS
|
||||
extern u64 of_translate_address(struct device_node *np, const __be32 *addr);
|
||||
extern bool of_can_translate_address(struct device_node *dev);
|
||||
extern int of_address_to_resource(struct device_node *dev, int index,
|
||||
struct resource *r);
|
||||
extern struct device_node *of_find_matching_node_by_address(
|
||||
|
|
|
@ -17,60 +17,23 @@
|
|||
|
||||
/* Definitions used by the flattened device tree */
|
||||
#define OF_DT_HEADER 0xd00dfeed /* marker */
|
||||
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
|
||||
#define OF_DT_END_NODE 0x2 /* End node */
|
||||
#define OF_DT_PROP 0x3 /* Property: name off, size,
|
||||
* content */
|
||||
#define OF_DT_NOP 0x4 /* nop */
|
||||
#define OF_DT_END 0x9
|
||||
|
||||
#define OF_DT_VERSION 0x10
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
/*
|
||||
* This is what gets passed to the kernel by prom_init or kexec
|
||||
*
|
||||
* The dt struct contains the device tree structure, full pathes and
|
||||
* property contents. The dt strings contain a separate block with just
|
||||
* the strings for the property names, and is fully page aligned and
|
||||
* self contained in a page, so that it can be kept around by the kernel,
|
||||
* each property name appears only once in this page (cheap compression)
|
||||
*
|
||||
* the mem_rsvmap contains a map of reserved ranges of physical memory,
|
||||
* passing it here instead of in the device-tree itself greatly simplifies
|
||||
* the job of everybody. It's just a list of u64 pairs (base/size) that
|
||||
* ends when size is 0
|
||||
*/
|
||||
struct boot_param_header {
|
||||
__be32 magic; /* magic word OF_DT_HEADER */
|
||||
__be32 totalsize; /* total size of DT block */
|
||||
__be32 off_dt_struct; /* offset to structure */
|
||||
__be32 off_dt_strings; /* offset to strings */
|
||||
__be32 off_mem_rsvmap; /* offset to memory reserve map */
|
||||
__be32 version; /* format version */
|
||||
__be32 last_comp_version; /* last compatible version */
|
||||
/* version 2 fields below */
|
||||
__be32 boot_cpuid_phys; /* Physical CPU id we're booting on */
|
||||
/* version 3 fields below */
|
||||
__be32 dt_strings_size; /* size of the DT strings block */
|
||||
/* version 17 fields below */
|
||||
__be32 dt_struct_size; /* size of the DT structure block */
|
||||
};
|
||||
|
||||
#if defined(CONFIG_OF_FLATTREE)
|
||||
|
||||
struct device_node;
|
||||
|
||||
/* For scanning an arbitrary device-tree at any time */
|
||||
extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset);
|
||||
extern void *of_fdt_get_property(struct boot_param_header *blob,
|
||||
extern char *of_fdt_get_string(const void *blob, u32 offset);
|
||||
extern void *of_fdt_get_property(const void *blob,
|
||||
unsigned long node,
|
||||
const char *name,
|
||||
unsigned long *size);
|
||||
extern int of_fdt_is_compatible(struct boot_param_header *blob,
|
||||
int *size);
|
||||
extern int of_fdt_is_compatible(const void *blob,
|
||||
unsigned long node,
|
||||
const char *compat);
|
||||
extern int of_fdt_match(struct boot_param_header *blob, unsigned long node,
|
||||
extern int of_fdt_match(const void *blob, unsigned long node,
|
||||
const char *const *compat);
|
||||
extern void of_fdt_unflatten_tree(unsigned long *blob,
|
||||
struct device_node **mynodes);
|
||||
|
@ -78,21 +41,21 @@ extern void of_fdt_unflatten_tree(unsigned long *blob,
|
|||
/* TBD: Temporary export of fdt globals - remove when code fully merged */
|
||||
extern int __initdata dt_root_addr_cells;
|
||||
extern int __initdata dt_root_size_cells;
|
||||
extern struct boot_param_header *initial_boot_params;
|
||||
extern void *initial_boot_params;
|
||||
|
||||
extern char __dtb_start[];
|
||||
extern char __dtb_end[];
|
||||
|
||||
/* For scanning the flat device-tree at boot time */
|
||||
extern char *find_flat_dt_string(u32 offset);
|
||||
extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname,
|
||||
int depth, void *data),
|
||||
void *data);
|
||||
extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||
unsigned long *size);
|
||||
extern const void *of_get_flat_dt_prop(unsigned long node, const char *name,
|
||||
int *size);
|
||||
extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
|
||||
extern int of_flat_dt_match(unsigned long node, const char *const *matches);
|
||||
extern unsigned long of_get_flat_dt_root(void);
|
||||
extern int of_scan_flat_dt_by_path(const char *path,
|
||||
int (*it)(unsigned long node, const char *name, int depth, void *data),
|
||||
void *data);
|
||||
extern int of_get_flat_dt_size(void);
|
||||
|
||||
extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
|
||||
int depth, void *data);
|
||||
|
@ -103,7 +66,7 @@ extern void early_init_dt_add_memory_arch(u64 base, u64 size);
|
|||
extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
|
||||
bool no_map);
|
||||
extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align);
|
||||
extern u64 dt_mem_next_cell(int s, __be32 **cellp);
|
||||
extern u64 dt_mem_next_cell(int s, const __be32 **cellp);
|
||||
|
||||
/* Early flat tree scan hooks */
|
||||
extern int early_init_dt_scan_root(unsigned long node, const char *uname,
|
||||
|
@ -120,6 +83,7 @@ extern void unflatten_device_tree(void);
|
|||
extern void unflatten_and_copy_device_tree(void);
|
||||
extern void early_init_devtree(void *);
|
||||
extern void early_get_first_memblock_info(void *, phys_addr_t *);
|
||||
extern u64 fdt_translate_address(const void *blob, int node_offset);
|
||||
#else /* CONFIG_OF_FLATTREE */
|
||||
static inline void early_init_fdt_scan_reserved_mem(void) {}
|
||||
static inline const char *of_flat_dt_get_machine_name(void) { return NULL; }
|
||||
|
|
|
@ -45,6 +45,7 @@ extern void of_irq_init(const struct of_device_id *matches);
|
|||
#ifdef CONFIG_OF_IRQ
|
||||
extern int of_irq_count(struct device_node *dev);
|
||||
extern int of_irq_get(struct device_node *dev, int index);
|
||||
extern int of_irq_get_byname(struct device_node *dev, const char *name);
|
||||
#else
|
||||
static inline int of_irq_count(struct device_node *dev)
|
||||
{
|
||||
|
@ -54,6 +55,10 @@ static inline int of_irq_get(struct device_node *dev, int index)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
static inline int of_irq_get_byname(struct device_node *dev, const char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
|
|
|
@ -6,14 +6,44 @@
|
|||
|
||||
struct pci_dev;
|
||||
struct of_phandle_args;
|
||||
int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
|
||||
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
|
||||
|
||||
struct device_node;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq);
|
||||
struct device_node *of_pci_find_child_device(struct device_node *parent,
|
||||
unsigned int devfn);
|
||||
int of_pci_get_devfn(struct device_node *np);
|
||||
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin);
|
||||
int of_pci_parse_bus_range(struct device_node *node, struct resource *res);
|
||||
#else
|
||||
static inline int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct device_node *of_pci_find_child_device(struct device_node *parent,
|
||||
unsigned int devfn)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int of_pci_get_devfn(struct device_node *np)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
of_pci_parse_bus_range(struct device_node *node, struct resource *res)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
|
||||
int of_pci_msi_chip_add(struct msi_chip *chip);
|
||||
|
|
|
@ -21,33 +21,19 @@ struct reserved_mem_ops {
|
|||
struct device *dev);
|
||||
};
|
||||
|
||||
typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem,
|
||||
unsigned long node, const char *uname);
|
||||
typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
|
||||
|
||||
#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
|
||||
_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
|
||||
|
||||
#ifdef CONFIG_OF_RESERVED_MEM
|
||||
void fdt_init_reserved_mem(void);
|
||||
void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
|
||||
phys_addr_t base, phys_addr_t size);
|
||||
|
||||
#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
|
||||
static const struct of_device_id __reservedmem_of_table_##name \
|
||||
__used __section(__reservedmem_of_table) \
|
||||
= { .compatible = compat, \
|
||||
.data = (init == (reservedmem_of_init_fn)NULL) ? \
|
||||
init : init }
|
||||
|
||||
#else
|
||||
static inline void fdt_init_reserved_mem(void) { }
|
||||
static inline void fdt_reserved_mem_save_node(unsigned long node,
|
||||
const char *uname, phys_addr_t base, phys_addr_t size) { }
|
||||
|
||||
#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
|
||||
static const struct of_device_id __reservedmem_of_table_##name \
|
||||
__attribute__((unused)) \
|
||||
= { .compatible = compat, \
|
||||
.data = (init == (reservedmem_of_init_fn)NULL) ? \
|
||||
init : init }
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* __OF_RESERVED_MEM_H */
|
||||
|
|
|
@ -294,6 +294,9 @@ struct earlycon_device {
|
|||
int setup_earlycon(char *buf, const char *match,
|
||||
int (*setup)(struct earlycon_device *, const char *));
|
||||
|
||||
extern int of_setup_earlycon(unsigned long addr,
|
||||
int (*setup)(struct earlycon_device *, const char *));
|
||||
|
||||
#define EARLYCON_DECLARE(name, func) \
|
||||
static int __init name ## _setup_earlycon(char *buf) \
|
||||
{ \
|
||||
|
@ -301,6 +304,9 @@ static int __init name ## _setup_earlycon(char *buf) \
|
|||
} \
|
||||
early_param("earlycon", name ## _setup_earlycon);
|
||||
|
||||
#define OF_EARLYCON_DECLARE(name, compat, fn) \
|
||||
_OF_DECLARE(earlycon, name, compat, fn, void *)
|
||||
|
||||
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
|
||||
struct console *c);
|
||||
void uart_parse_options(char *options, int *baud, int *parity, int *bits,
|
||||
|
|
|
@ -52,6 +52,9 @@ extern int strncasecmp(const char *s1, const char *s2, size_t n);
|
|||
#ifndef __HAVE_ARCH_STRCHR
|
||||
extern char * strchr(const char *,int);
|
||||
#endif
|
||||
#ifndef __HAVE_ARCH_STRCHRNUL
|
||||
extern char * strchrnul(const char *,int);
|
||||
#endif
|
||||
#ifndef __HAVE_ARCH_STRNCHR
|
||||
extern char * strnchr(const char *, size_t, int);
|
||||
#endif
|
||||
|
|
18
lib/string.c
18
lib/string.c
|
@ -301,6 +301,24 @@ char *strchr(const char *s, int c)
|
|||
EXPORT_SYMBOL(strchr);
|
||||
#endif
|
||||
|
||||
#ifndef __HAVE_ARCH_STRCHRNUL
|
||||
/**
|
||||
* strchrnul - Find and return a character in a string, or end of string
|
||||
* @s: The string to be searched
|
||||
* @c: The character to search for
|
||||
*
|
||||
* Returns pointer to first occurrence of 'c' in s. If c is not found, then
|
||||
* return a pointer to the null byte at the end of s.
|
||||
*/
|
||||
char *strchrnul(const char *s, int c)
|
||||
{
|
||||
while (*s && *s != (char)c)
|
||||
s++;
|
||||
return (char *)s;
|
||||
}
|
||||
EXPORT_SYMBOL(strchrnul);
|
||||
#endif
|
||||
|
||||
#ifndef __HAVE_ARCH_STRRCHR
|
||||
/**
|
||||
* strrchr - Find the last occurrence of a character in a string
|
||||
|
|
Loading…
Reference in New Issue