Commit d2705064 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'devicetree-for-3.16' of...

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
  ...
parents b77279bc 43cb4367
...@@ -13,7 +13,7 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties ...@@ -13,7 +13,7 @@ Refer to clk/clock-bindings.txt for generic clock consumer properties
Optional properties: Optional properties:
- phys: phy provider specifier - 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 Refer to phy/phy-bindings.txt for generic phy consumer properties
Example: Example:
......
...@@ -77,6 +77,7 @@ lsi LSI Corp. (LSI Logic) ...@@ -77,6 +77,7 @@ lsi LSI Corp. (LSI Logic)
lltc Linear Technology Corporation lltc Linear Technology Corporation
marvell Marvell Technology Group Ltd. marvell Marvell Technology Group Ltd.
maxim Maxim Integrated Products maxim Maxim Integrated Products
micrel Micrel Inc.
microchip Microchip Technology Inc. microchip Microchip Technology Inc.
mosaixtech Mosaix Technologies, Inc. mosaixtech Mosaix Technologies, Inc.
moxa Moxa moxa Moxa
......
...@@ -12,6 +12,5 @@ ...@@ -12,6 +12,5 @@
#include <asm-generic/sections.h> #include <asm-generic/sections.h>
extern char __arc_dccm_base[]; extern char __arc_dccm_base[];
extern char __dtb_start[];
#endif #endif
...@@ -42,7 +42,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt) ...@@ -42,7 +42,7 @@ const struct machine_desc * __init setup_machine_fdt(void *dt)
const struct machine_desc *mdesc; const struct machine_desc *mdesc;
unsigned long dt_root; unsigned long dt_root;
void *clk; void *clk;
unsigned long len; int len;
if (!early_init_dt_scan(dt)) if (!early_init_dt_scan(dt))
return NULL; return NULL;
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#ifdef CONFIG_OF #ifdef CONFIG_OF
extern const struct machine_desc *setup_machine_fdt(unsigned int dt_phys); 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); extern void __init arm_dt_init_cpu_maps(void);
#else /* CONFIG_OF */ #else /* CONFIG_OF */
...@@ -24,7 +23,6 @@ static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys) ...@@ -24,7 +23,6 @@ static inline const struct machine_desc *setup_machine_fdt(unsigned int dt_phys)
return NULL; return NULL;
} }
static inline void arm_dt_memblock_reserve(void) { }
static inline void arm_dt_init_cpu_maps(void) { } static inline void arm_dt_init_cpu_maps(void) { }
#endif /* CONFIG_OF */ #endif /* CONFIG_OF */
......
...@@ -32,51 +32,22 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) ...@@ -32,51 +32,22 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
arm_add_memory(base, size); arm_add_memory(base, size);
} }
void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) #ifdef CONFIG_SMP
{ extern struct of_cpu_method __cpu_method_of_table[];
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));
/* static const struct of_cpu_method __cpu_method_of_table_sentinel
* Process the reserve map. This will probably overlap the initrd __used __section(__cpu_method_of_table_end);
* 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[];
static int __init set_smp_ops_by_method(struct device_node *node) static int __init set_smp_ops_by_method(struct device_node *node)
{ {
const char *method; 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)) if (of_property_read_string(node, "enable-method", &method))
return 0; return 0;
for (; m < __cpu_method_of_table_end; m++) for (; m->method; m++)
if (!strcmp(m->method, method)) { if (!strcmp(m->method, method)) {
smp_set_ops(m->ops); smp_set_ops(m->ops);
return 1; return 1;
...@@ -252,7 +223,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys) ...@@ -252,7 +223,7 @@ const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
if (!mdesc) { if (!mdesc) {
const char *prop; const char *prop;
long size; int size;
unsigned long dt_root; unsigned long dt_root;
early_print("\nError: unrecognized/unsupported " early_print("\nError: unrecognized/unsupported "
......
...@@ -202,7 +202,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname, ...@@ -202,7 +202,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
{ {
struct map_desc iodesc; struct map_desc iodesc;
__be32 *reg; __be32 *reg;
unsigned long len; int len;
if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") && if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
!of_flat_dt_is_compatible(node, "samsung,exynos5440-clock")) !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
......
...@@ -289,14 +289,12 @@ int __init mx35_clocks_init(void) ...@@ -289,14 +289,12 @@ int __init mx35_clocks_init(void)
return 0; 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.clks = clk;
clk_data.clk_num = ARRAY_SIZE(clk); clk_data.clk_num = ARRAY_SIZE(clk);
of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data); of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
mx35_clocks_init(); mx35_clocks_init();
return 0;
} }
CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt); CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt);
...@@ -317,7 +317,6 @@ void __init arm_memblock_init(struct meminfo *mi, ...@@ -317,7 +317,6 @@ void __init arm_memblock_init(struct meminfo *mi,
#endif #endif
arm_mm_memblock_reserve(); arm_mm_memblock_reserve();
arm_dt_memblock_reserve();
/* reserve any platform specific memblock areas */ /* reserve any platform specific memblock areas */
if (mdesc->reserve) if (mdesc->reserve)
......
...@@ -125,8 +125,8 @@ device_initcall(s5p_mfc_memory_init); ...@@ -125,8 +125,8 @@ device_initcall(s5p_mfc_memory_init);
int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname, int __init s5p_fdt_alloc_mfc_mem(unsigned long node, const char *uname,
int depth, void *data) int depth, void *data)
{ {
__be32 *prop; const __be32 *prop;
unsigned long len; int len;
struct s5p_mfc_dt_meminfo mfc_mem; struct s5p_mfc_dt_meminfo mfc_mem;
if (!data) if (!data)
......
...@@ -126,8 +126,6 @@ static void arm64_memory_present(void) ...@@ -126,8 +126,6 @@ static void arm64_memory_present(void)
void __init arm64_memblock_init(void) void __init arm64_memblock_init(void)
{ {
u64 *reserve_map, base, size;
/* Register the kernel text, kernel data and initrd with memblock */ /* Register the kernel text, kernel data and initrd with memblock */
memblock_reserve(__pa(_text), _end - _text); memblock_reserve(__pa(_text), _end - _text);
#ifdef CONFIG_BLK_DEV_INITRD #ifdef CONFIG_BLK_DEV_INITRD
...@@ -142,25 +140,6 @@ void __init arm64_memblock_init(void) ...@@ -142,25 +140,6 @@ void __init arm64_memblock_init(void)
memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE); memblock_reserve(__pa(swapper_pg_dir), SWAPPER_DIR_SIZE);
memblock_reserve(__pa(idmap_pg_dir), IDMAP_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(); early_init_fdt_scan_reserved_mem();
dma_contiguous_reserve(0); dma_contiguous_reserve(0);
......
...@@ -265,8 +265,8 @@ int __init c6x_add_memory(phys_addr_t start, unsigned long size) ...@@ -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) notrace void __init machine_init(unsigned long dt_ptr)
{ {
struct boot_param_header *dtb = __va(dt_ptr); const void *dtb = __va(dt_ptr);
struct boot_param_header *fdt = (struct boot_param_header *)_fdt_start; const void *fdt = _fdt_start;
/* interrupts must be masked */ /* interrupts must be masked */
set_creg(IER, 2); set_creg(IER, 2);
......
...@@ -105,10 +105,6 @@ ...@@ -105,10 +105,6 @@
extern char _heap_start[]; extern char _heap_start[];
#ifdef CONFIG_METAG_BUILTIN_DTB
extern u32 __dtb_start[];
#endif
#ifdef CONFIG_DA_CONSOLE #ifdef CONFIG_DA_CONSOLE
/* Our early channel based console driver */ /* Our early channel based console driver */
extern struct console dash_console; extern struct console dash_console;
......
...@@ -43,13 +43,13 @@ ...@@ -43,13 +43,13 @@
#include <asm/pci-bridge.h> #include <asm/pci-bridge.h>
#ifdef CONFIG_EARLY_PRINTK #ifdef CONFIG_EARLY_PRINTK
static char *stdout; static const char *stdout;
static int __init early_init_dt_scan_chosen_serial(unsigned long node, static int __init early_init_dt_scan_chosen_serial(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
unsigned long l; int l;
char *p; const char *p;
pr_debug("%s: depth: %d, uname: %s\n", __func__, depth, uname); 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, ...@@ -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,opb-uartlite", 17) == 0) ||
(strncmp(p, "xlnx,axi-uartlite", 17) == 0) || (strncmp(p, "xlnx,axi-uartlite", 17) == 0) ||
(strncmp(p, "xlnx,mdm", 8) == 0)) { (strncmp(p, "xlnx,mdm", 8) == 0)) {
unsigned int *addrp; const unsigned int *addrp;
*(u32 *)data = UARTLITE; *(u32 *)data = UARTLITE;
...@@ -114,34 +114,3 @@ void __init early_init_devtree(void *params) ...@@ -114,34 +114,3 @@ void __init early_init_devtree(void *params)
pr_debug(" <- early_init_devtree()\n"); 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) ...@@ -1053,36 +1053,26 @@ void prom_free_prom_memory(void)
int octeon_prune_device_tree(void); int octeon_prune_device_tree(void);
extern const char __dtb_octeon_3xxx_begin; 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_begin;
extern const char __dtb_octeon_68xx_end;
void __init device_tree_init(void) void __init device_tree_init(void)
{ {
int dt_size; const void *fdt;
struct boot_param_header *fdt;
bool do_prune; bool do_prune;
if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) { if (octeon_bootinfo->minor_version >= 3 && octeon_bootinfo->fdt_addr) {
fdt = phys_to_virt(octeon_bootinfo->fdt_addr); fdt = phys_to_virt(octeon_bootinfo->fdt_addr);
if (fdt_check_header(fdt)) if (fdt_check_header(fdt))
panic("Corrupt Device Tree passed to kernel."); panic("Corrupt Device Tree passed to kernel.");
dt_size = be32_to_cpu(fdt->totalsize);
do_prune = false; do_prune = false;
} else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) { } else if (OCTEON_IS_MODEL(OCTEON_CN68XX)) {
fdt = (struct boot_param_header *)&__dtb_octeon_68xx_begin; fdt = &__dtb_octeon_68xx_begin;
dt_size = &__dtb_octeon_68xx_end - &__dtb_octeon_68xx_begin;
do_prune = true; do_prune = true;
} else { } else {
fdt = (struct boot_param_header *)&__dtb_octeon_3xxx_begin; fdt = &__dtb_octeon_3xxx_begin;
dt_size = &__dtb_octeon_3xxx_end - &__dtb_octeon_3xxx_begin;
do_prune = true; do_prune = true;
} }
/* Copy the default tree from init memory. */ initial_boot_params = (void *)fdt;
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);
if (do_prune) { if (do_prune) {
octeon_prune_device_tree(); octeon_prune_device_tree();
...@@ -1090,7 +1080,7 @@ void __init device_tree_init(void) ...@@ -1090,7 +1080,7 @@ void __init device_tree_init(void)
} else { } else {
pr_info("Using passed Device Tree.\n"); pr_info("Using passed Device Tree.\n");
} }
unflatten_device_tree(); unflatten_and_copy_device_tree();
} }
static int __initdata disable_octeon_edac_p; static int __initdata disable_octeon_edac_p;
......
...@@ -67,10 +67,6 @@ ...@@ -67,10 +67,6 @@
extern int mips_revision_sconid; extern int mips_revision_sconid;
#ifdef CONFIG_OF
extern struct boot_param_header __dtb_start;
#endif
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
extern void mips_pcibios_init(void); extern void mips_pcibios_init(void);
#else #else
......
...@@ -21,13 +21,13 @@ extern void device_tree_init(void); ...@@ -21,13 +21,13 @@ extern void device_tree_init(void);
struct boot_param_header; 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) \ #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 */ #else /* CONFIG_OF */
......
...@@ -47,7 +47,7 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) ...@@ -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)); 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)) if (!early_init_dt_scan(bph))
return; return;
......
...@@ -71,23 +71,12 @@ void __init plat_mem_setup(void) ...@@ -71,23 +71,12 @@ void __init plat_mem_setup(void)
* Load the builtin devicetree. This causes the chosen node to be * Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing * parsed resulting in our memory appearing
*/ */
__dt_setup_arch(&__dtb_start); __dt_setup_arch(__dtb_start);
} }
void __init device_tree_init(void) void __init device_tree_init(void)
{ {
unsigned long base, size; unflatten_and_copy_device_tree();
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();
} }
void __init prom_init(void) void __init prom_init(void)
......
...@@ -26,6 +26,4 @@ struct ltq_soc_info { ...@@ -26,6 +26,4 @@ struct ltq_soc_info {
extern void ltq_soc_detect(struct ltq_soc_info *i); extern void ltq_soc_detect(struct ltq_soc_info *i);
extern void ltq_soc_init(void); extern void ltq_soc_init(void);
extern struct boot_param_header __dtb_start;
#endif #endif
...@@ -69,17 +69,17 @@ static void __init parse_memsize_param(void) ...@@ -69,17 +69,17 @@ static void __init parse_memsize_param(void)
if (!memsize) if (!memsize)
return; return;
offset = fdt_path_offset(&__dtb_start, "/memory"); offset = fdt_path_offset(__dtb_start, "/memory");
if (offset > 0) { if (offset > 0) {
uint64_t new_value; uint64_t new_value;
/* /*
* reg contains 2 32-bits BE values, offset and size. We just * reg contains 2 32-bits BE values, offset and size. We just
* want to replace the size value without affecting the offset * 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 = be64_to_cpu(*prop_value);
new_value = (new_value & ~0xffffffffllu) | memsize; 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) ...@@ -92,7 +92,7 @@ void __init plat_mem_setup(void)
* Load the builtin devicetree. This causes the chosen node to be * Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing * parsed resulting in our memory appearing
*/ */
__dt_setup_arch(&__dtb_start); __dt_setup_arch(__dtb_start);
} }
void __init device_tree_init(void) void __init device_tree_init(void)
......
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
#include <asm/prom.h> #include <asm/prom.h>
extern u32 __dtb_xlp_evp_begin[], __dtb_xlp_svp_begin[], 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; static void *xlp_fdt_blob;
void __init *xlp_dt_init(void *fdtp) void __init *xlp_dt_init(void *fdtp)
...@@ -87,22 +87,7 @@ void __init xlp_early_init_devtree(void) ...@@ -87,22 +87,7 @@ void __init xlp_early_init_devtree(void)
void __init device_tree_init(void) void __init device_tree_init(void)
{ {
unsigned long base, size; unflatten_and_copy_device_tree();
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);
} }
static struct of_device_id __initdata xlp_ids[] = { static struct of_device_id __initdata xlp_ids[] = {
......
...@@ -28,8 +28,6 @@ ...@@ -28,8 +28,6 @@
__iomem void *rt_sysc_membase; __iomem void *rt_sysc_membase;
__iomem void *rt_memc_membase; __iomem void *rt_memc_membase;
extern struct boot_param_header __dtb_start;
__iomem void *plat_of_remap_node(const char *node) __iomem void *plat_of_remap_node(const char *node)
{ {
struct resource res; struct resource res;
...@@ -52,30 +50,7 @@ __iomem void *plat_of_remap_node(const char *node) ...@@ -52,30 +50,7 @@ __iomem void *plat_of_remap_node(const char *node)
void __init device_tree_init(void) void __init device_tree_init(void)
{ {
unsigned long base, size; unflatten_and_copy_device_tree();
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);
} }
void __init plat_mem_setup(void) void __init plat_mem_setup(void)
...@@ -86,7 +61,7 @@ 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 * Load the builtin devicetree. This causes the chosen node to be
* parsed resulting in our memory appearing * parsed resulting in our memory appearing
*/ */
__dt_setup_arch(&__dtb_start); __dt_setup_arch(__dtb_start);
if (soc_info.mem_size) if (soc_info.mem_size)
add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M, add_memory_region(soc_info.mem_base, soc_info.mem_size * SZ_1M,
......
...@@ -5,6 +5,4 @@ ...@@ -5,6 +5,4 @@
extern char __initrd_start, __initrd_end; extern char __initrd_start, __initrd_end;
#endif #endif
extern u32 __dtb_start[];
#endif #endif
...@@ -51,10 +51,6 @@ static inline void dcr_write_mmio(dcr_host_mmio_t host, ...@@ -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); 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 /* __KERNEL__ */
#endif /* _ASM_POWERPC_DCR_MMIO_H */ #endif /* _ASM_POWERPC_DCR_MMIO_H */
......
...@@ -26,6 +26,45 @@ ...@@ -26,6 +26,45 @@
#include <linux/of_irq.h> #include <linux/of_irq.h>
#include <linux/platform_device.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 * OF address retreival & translation
*/ */
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
# Makefile for the linux kernel. # Makefile for the linux kernel.
# #
CFLAGS_prom.o = -I$(src)/../../../scripts/dtc/libfdt
CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' CFLAGS_ptrace.o += -DUTS_MACHINE='"$(UTS_MACHINE)"'
subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
......
...@@ -36,7 +36,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node, ...@@ -36,7 +36,7 @@ static int __init early_init_dt_scan_epapr(unsigned long node,
int depth, void *data) int depth, void *data)
{ {
const u32 *insts; const u32 *insts;
unsigned long len; int len;
int i; int i;
insts = of_get_flat_dt_prop(node, "hcall-instructions", &len); insts = of_get_flat_dt_prop(node, "hcall-instructions", &len);
......
...@@ -55,9 +55,9 @@ int crash_mem_ranges; ...@@ -55,9 +55,9 @@ int crash_mem_ranges;
int __init early_init_dt_scan_fw_dump(unsigned long node, int __init early_init_dt_scan_fw_dump(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
__be32 *sections; const __be32 *sections;
int i, num_sections; int i, num_sections;
unsigned long size; int size;
const int *token; const int *token;
if (depth != 1 || strcmp(uname, "rtas") != 0) if (depth != 1 || strcmp(uname, "rtas") != 0)
......
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/debugfs.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/libfdt.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/rtas.h> #include <asm/rtas.h>
...@@ -118,14 +118,14 @@ static void __init move_device_tree(void) ...@@ -118,14 +118,14 @@ static void __init move_device_tree(void)
DBG("-> move_device_tree\n"); DBG("-> move_device_tree\n");
start = __pa(initial_boot_params); 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) || if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
overlaps_crashkernel(start, size) || overlaps_crashkernel(start, size) ||
overlaps_initrd(start, size)) { overlaps_initrd(start, size)) {
p = __va(memblock_alloc(size, PAGE_SIZE)); p = __va(memblock_alloc(size, PAGE_SIZE));
memcpy(p, initial_boot_params, 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); DBG("Moved device tree to 0x%p\n", p);
} }
...@@ -163,7 +163,7 @@ static struct ibm_pa_feature { ...@@ -163,7 +163,7 @@ static struct ibm_pa_feature {
{CPU_FTR_REAL_LE, PPC_FEATURE_TRUE_LE, 5, 0, 0}, {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, unsigned long tablelen,
struct ibm_pa_feature *fp, struct ibm_pa_feature *fp,
unsigned long ft_size) unsigned long ft_size)
...@@ -202,8 +202,8 @@ static void __init scan_features(unsigned long node, unsigned char *ftrs, ...@@ -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) static void __init check_cpu_pa_features(unsigned long node)
{ {
unsigned char *pa_ftrs; const unsigned char *pa_ftrs;
unsigned long tablelen; int tablelen;
pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen); pa_ftrs = of_get_flat_dt_prop(node, "ibm,pa-features", &tablelen);
if (pa_ftrs == NULL) if (pa_ftrs == NULL)
...@@ -216,7 +216,7 @@ static void __init check_cpu_pa_features(unsigned long node) ...@@ -216,7 +216,7 @@ static void __init check_cpu_pa_features(unsigned long node)
#ifdef CONFIG_PPC_STD_MMU_64 #ifdef CONFIG_PPC_STD_MMU_64
static void __init check_cpu_slb_size(unsigned long node) 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); slb_size_ptr = of_get_flat_dt_prop(node, "slb-size", NULL);
if (slb_size_ptr != NULL) { if (slb_size_ptr != NULL) {
...@@ -257,7 +257,7 @@ static struct feature_property { ...@@ -257,7 +257,7 @@ static struct feature_property {
static inline void identical_pvr_fixup(unsigned long node) static inline void identical_pvr_fixup(unsigned long node)
{ {
unsigned int pvr; 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, * 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, ...@@ -295,11 +295,11 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) 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 *prop;
const __be32 *intserv; const __be32 *intserv;
int i, nthreads; int i, nthreads;
unsigned long len; int len;
int found = -1; int found = -1;
int found_thread = 0; int found_thread = 0;
...@@ -325,9 +325,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node, ...@@ -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 * version 2 of the kexec param format adds the phys cpuid of
* booted proc. * booted proc.
*/ */
if (be32_to_cpu(initial_boot_params->version) >= 2) { if (fdt_version(initial_boot_params) >= 2) {
if (be32_to_cpu(intserv[i]) == 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 = boot_cpu_count;
found_thread = i; found_thread = i;
} }
...@@ -392,7 +392,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node, ...@@ -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 __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
int depth, void *data) 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 */ /* Use common scan routine to determine if this is the chosen node */
if (early_init_dt_scan_chosen(node, uname, depth, data) == 0) 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, ...@@ -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) static int __init early_init_dt_scan_drconf_memory(unsigned long node)
{ {
__be32 *dm, *ls, *usm; const __be32 *dm, *ls, *usm;
unsigned long l, n, flags; int l;
unsigned long n, flags;
u64 base, size, memblock_size; u64 base, size, memblock_size;
unsigned int is_kexec_kdump = 0, rngs; unsigned int is_kexec_kdump = 0, rngs;
...@@ -564,9 +565,12 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) ...@@ -564,9 +565,12 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size)
static void __init early_reserve_mem_dt(void) static void __init early_reserve_mem_dt(void)
{ {
unsigned long i, len, dt_root; unsigned long i, dt_root;
int len;
const __be32 *prop; const __be32 *prop;
early_init_fdt_scan_reserved_mem();
dt_root = of_get_flat_dt_root(); dt_root = of_get_flat_dt_root();
prop = of_get_flat_dt_prop(dt_root, "reserved-ranges", &len); prop = of_get_flat_dt_prop(dt_root, "reserved-ranges", &len);
...@@ -589,24 +593,14 @@ static void __init early_reserve_mem_dt(void) ...@@ -589,24 +593,14 @@ static void __init early_reserve_mem_dt(void)
memblock_reserve(base, size); memblock_reserve(base, size);
} }
} }
early_init_fdt_scan_reserved_mem();
} }
static void __init early_reserve_mem(void) static void __init early_reserve_mem(void)
{ {
u64 base, size;
__be64 *reserve_map; __be64 *reserve_map;
unsigned long self_base;
unsigned long self_size;
reserve_map = (__be64 *)(((unsigned long)initial_boot_params) + reserve_map = (__be64 *)(((unsigned long)initial_boot_params) +
be32_to_cpu(initial_boot_params->off_mem_rsvmap)); fdt_off_mem_rsvmap(initial_boot_params));
/* 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);
/* Look for the new "reserved-regions" property in the DT */ /* Look for the new "reserved-regions" property in the DT */
early_reserve_mem_dt(); early_reserve_mem_dt();
...@@ -636,26 +630,12 @@ static void __init early_reserve_mem(void) ...@@ -636,26 +630,12 @@ static void __init early_reserve_mem(void)
size_32 = be32_to_cpup(reserve_map_32++); size_32 = be32_to_cpup(reserve_map_32++);
if (size_32 == 0) if (size_32 == 0)
break; 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); DBG("reserving: %x -> %x\n", base_32, size_32);
memblock_reserve(base_32, size_32); memblock_reserve(base_32, size_32);
} }
return; return;
} }
#endif #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) void __init early_init_devtree(void *params)
...@@ -922,23 +902,3 @@ bool arch_match_cpu_phys_id(int cpu, u64 phys_id) ...@@ -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); 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) ...@@ -1142,7 +1142,7 @@ void __init rtas_initialize(void)
int __init early_init_dt_scan_rtas(unsigned long node, int __init early_init_dt_scan_rtas(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
u32 *basep, *entryp, *sizep; const u32 *basep, *entryp, *sizep;
if (depth != 1 || strcmp(uname, "rtas") != 0) if (depth != 1 || strcmp(uname, "rtas") != 0)
return 0; return 0;
......
...@@ -269,9 +269,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, ...@@ -269,9 +269,9 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) 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);
__be32 *prop; const __be32 *prop;
unsigned long size = 0; int size = 0;
/* We are scanning "cpu" nodes only */ /* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0) if (type == NULL || strcmp(type, "cpu") != 0)
...@@ -324,9 +324,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, ...@@ -324,9 +324,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) 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);
__be32 *prop; const __be32 *prop;
unsigned long size = 0; int size = 0;
/* We are scanning "cpu" nodes only */ /* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0) if (type == NULL || strcmp(type, "cpu") != 0)
...@@ -406,9 +406,9 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, ...@@ -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, static int __init htab_dt_scan_hugepage_blocks(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) { 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);
__be64 *addr_prop; const __be64 *addr_prop;
__be32 *page_count_prop; const __be32 *page_count_prop;
unsigned int expected_pages; unsigned int expected_pages;
long unsigned int phys_addr; long unsigned int phys_addr;
long unsigned int block_size; long unsigned int block_size;
...@@ -550,8 +550,8 @@ static int __init htab_dt_scan_pftsize(unsigned long node, ...@@ -550,8 +550,8 @@ static int __init htab_dt_scan_pftsize(unsigned long node,
const char *uname, int depth, const char *uname, int depth,
void *data) 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);
__be32 *prop; const __be32 *prop;
/* We are scanning "cpu" nodes only */ /* We are scanning "cpu" nodes only */
if (type == NULL || strcmp(type, "cpu") != 0) if (type == NULL || strcmp(type, "cpu") != 0)
......
...@@ -199,8 +199,8 @@ static void __init efika_setup_arch(void) ...@@ -199,8 +199,8 @@ static void __init efika_setup_arch(void)
static int __init efika_probe(void) static int __init efika_probe(void)
{ {
char *model = of_get_flat_dt_prop(of_get_flat_dt_root(), const char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
"model", NULL); "model", NULL);
if (model == NULL) if (model == NULL)
return 0; return 0;
......
...@@ -574,8 +574,8 @@ chrp_init2(void) ...@@ -574,8 +574,8 @@ chrp_init2(void)
static int __init chrp_probe(void) static int __init chrp_probe(void)
{ {
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(), const char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
"device_type", NULL); "device_type", NULL);
if (dtype == NULL) if (dtype == NULL)
return 0; return 0;
if (strcmp(dtype, "chrp")) if (strcmp(dtype, "chrp"))
......
...@@ -61,7 +61,7 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -61,7 +61,7 @@ int __init early_init_dt_scan_opal(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
const void *basep, *entryp, *sizep; const void *basep, *entryp, *sizep;
unsigned long basesz, entrysz, runtimesz; int basesz, entrysz, runtimesz;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0) if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
return 0; return 0;
...@@ -77,11 +77,11 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -77,11 +77,11 @@ int __init early_init_dt_scan_opal(unsigned long node,
opal.entry = of_read_number(entryp, entrysz/4); opal.entry = of_read_number(entryp, entrysz/4);
opal.size = of_read_number(sizep, runtimesz/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); 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); 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); opal.size, sizep, runtimesz);
powerpc_firmware_features |= FW_FEATURE_OPAL; powerpc_firmware_features |= FW_FEATURE_OPAL;
...@@ -102,7 +102,7 @@ int __init early_init_dt_scan_opal(unsigned long node, ...@@ -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, int __init early_init_dt_scan_recoverable_ranges(unsigned long node,
const char *uname, int depth, void *data) const char *uname, int depth, void *data)
{ {
unsigned long i, psize, size; int i, psize, size;
const __be32 *prop; const __be32 *prop;
if (depth != 1 || strcmp(uname, "ibm,opal") != 0) if (depth != 1 || strcmp(uname, "ibm,opal") != 0)
...@@ -359,7 +359,7 @@ int opal_get_chars(uint32_t vtermno, char *buf, int count) ...@@ -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) if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0)
return 0; return 0;
len = cpu_to_be64(count); len = cpu_to_be64(count);
rc = opal_console_read(vtermno, &len, buf); rc = opal_console_read(vtermno, &len, buf);
if (rc == OPAL_SUCCESS) if (rc == OPAL_SUCCESS)
return be64_to_cpu(len); return be64_to_cpu(len);
return 0; return 0;
......
...@@ -665,7 +665,7 @@ static int __init pseries_probe_fw_features(unsigned long node, ...@@ -665,7 +665,7 @@ static int __init pseries_probe_fw_features(unsigned long node,
void *data) void *data)
{ {
const char *prop; const char *prop;
unsigned long len; int len;
static int hypertas_found; static int hypertas_found;
static int vec5_found; static int vec5_found;
...@@ -698,7 +698,7 @@ static int __init pseries_probe_fw_features(unsigned long node, ...@@ -698,7 +698,7 @@ static int __init pseries_probe_fw_features(unsigned long node,
static int __init pSeries_probe(void) static int __init pSeries_probe(void)
{ {
unsigned long root = of_get_flat_dt_root(); 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) if (dtype == NULL)
return 0; return 0;
......
...@@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len); ...@@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len);
#ifdef CONFIG_PPC_DCR_MMIO #ifdef CONFIG_PPC_DCR_MMIO
u64 of_translate_dcr_address(struct device_node *dev, static u64 of_translate_dcr_address(struct device_node *dev,
unsigned int dcr_n, unsigned int dcr_n,
unsigned int *out_stride) unsigned int *out_stride)
{ {
struct device_node *dp; struct device_node *dp;
const u32 *p; const u32 *p;
......
...@@ -206,23 +206,21 @@ static void __init dtb_apic_setup(void) ...@@ -206,23 +206,21 @@ static void __init dtb_apic_setup(void)
static void __init x86_flattree_get_config(void) static void __init x86_flattree_get_config(void)
{ {
u32 size, map_len; u32 size, map_len;
struct boot_param_header *dt; void *dt;
if (!initial_dtb) if (!initial_dtb)
return; return;
map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK), (u64)128);
(u64)sizeof(struct boot_param_header));
dt = early_memremap(initial_dtb, map_len); initial_boot_params = dt = early_memremap(initial_dtb, map_len);
size = be32_to_cpu(dt->totalsize); size = of_get_flat_dt_size();
if (map_len < size) { if (map_len < size) {
early_iounmap(dt, map_len); early_iounmap(dt, map_len);
dt = early_memremap(initial_dtb, size); initial_boot_params = dt = early_memremap(initial_dtb, size);
map_len = size; map_len = size;
} }
initial_boot_params = dt;
unflatten_and_copy_device_tree(); unflatten_and_copy_device_tree();
early_iounmap(dt, map_len); early_iounmap(dt, map_len);
} }
......
...@@ -74,7 +74,6 @@ extern int initrd_below_start_ok; ...@@ -74,7 +74,6 @@ extern int initrd_below_start_ok;
#endif #endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
extern u32 __dtb_start[];
void *dtb_start = __dtb_start; void *dtb_start = __dtb_start;
#endif #endif
...@@ -199,7 +198,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname, ...@@ -199,7 +198,7 @@ static int __init xtensa_dt_io_area(unsigned long node, const char *uname,
int depth, void *data) int depth, void *data)
{ {
const __be32 *ranges; const __be32 *ranges;
unsigned long len; int len;
if (depth > 1) if (depth > 1)
return 0; return 0;
......
...@@ -131,9 +131,12 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname); ...@@ -131,9 +131,12 @@ EXPORT_SYMBOL_GPL(platform_get_resource_byname);
*/ */
int platform_get_irq_byname(struct platform_device *dev, const char *name) int platform_get_irq_byname(struct platform_device *dev, const char *name)
{ {
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, struct resource *r;
name);
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; return r ? r->start : -ENXIO;
} }
EXPORT_SYMBOL_GPL(platform_get_irq_byname); EXPORT_SYMBOL_GPL(platform_get_irq_byname);
......
...@@ -24,8 +24,7 @@ static DEFINE_SPINLOCK(clk_lock); ...@@ -24,8 +24,7 @@ static DEFINE_SPINLOCK(clk_lock);
* Gate clocks * Gate clocks
*/ */
static void __init rk2928_gate_clk_init(struct device_node *node, static void __init rk2928_gate_clk_init(struct device_node *node)
void *data)
{ {
struct clk_onecell_data *clk_data; struct clk_onecell_data *clk_data;
const char *clk_parent; const char *clk_parent;
......
...@@ -1278,8 +1278,7 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat ...@@ -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; const struct of_device_id *match;
void (*setup_function)(struct device_node *, const void *) = function; void (*setup_function)(struct device_node *, const void *) = function;
for_each_matching_node(np, clk_match) { for_each_matching_node_and_match(np, clk_match, &match) {
match = of_match_node(clk_match, np);
data = match->data; data = match->data;
setup_function(np, data); setup_function(np, data);
} }
...@@ -1310,7 +1309,7 @@ static void __init sunxi_clock_protect(void) ...@@ -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 */ /* Register factor clocks */
of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); 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) ...@@ -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); _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) static void __init of_ti_wait_gate_clk_setup(struct device_node *node)
{ {
......
...@@ -27,7 +27,7 @@ void __init clocksource_of_init(void) ...@@ -27,7 +27,7 @@ void __init clocksource_of_init(void)
{ {
struct device_node *np; struct device_node *np;
const struct of_device_id *match; const struct of_device_id *match;
clocksource_of_init_fn init_func; of_init_fn_1 init_func;
unsigned clocksources = 0; unsigned clocksources = 0;
for_each_matching_node_and_match(np, __clksrc_of_table, &match) { for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
......
...@@ -96,7 +96,7 @@ static struct irq_domain_ops icoll_irq_domain_ops = { ...@@ -96,7 +96,7 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
.xlate = irq_domain_xlate_onecell, .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) struct device_node *interrupt_parent)
{ {
icoll_base = of_iomap(np, 0); icoll_base = of_iomap(np, 0);
...@@ -110,6 +110,6 @@ static void __init icoll_of_init(struct device_node *np, ...@@ -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_domain = irq_domain_add_linear(np, ICOLL_NUM_IRQS,
&icoll_irq_domain_ops, NULL); &icoll_irq_domain_ops, NULL);
WARN_ON(!icoll_domain); return icoll_domain ? 0 : -ENODEV;
} }
IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init); IRQCHIP_DECLARE(mxs, "fsl,icoll", icoll_of_init);
...@@ -1323,8 +1323,7 @@ static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = { ...@@ -1323,8 +1323,7 @@ static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
}; };
int __init s3c2410_init_intc_of(struct device_node *np, int __init s3c2410_init_intc_of(struct device_node *np,
struct device_node *interrupt_parent, struct device_node *interrupt_parent)
struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
{ {
return s3c_init_intc_of(np, interrupt_parent, return s3c_init_intc_of(np, interrupt_parent,
s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl)); s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
...@@ -1346,8 +1345,7 @@ static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = { ...@@ -1346,8 +1345,7 @@ static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
}; };
int __init s3c2416_init_intc_of(struct device_node *np, int __init s3c2416_init_intc_of(struct device_node *np,
struct device_node *interrupt_parent, struct device_node *interrupt_parent)
struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
{ {
return s3c_init_intc_of(np, interrupt_parent, return s3c_init_intc_of(np, interrupt_parent,
s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl)); s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
......
...@@ -19,11 +19,11 @@ ...@@ -19,11 +19,11 @@
* special section. * special section.
*/ */
static const struct of_device_id 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) void __init irqchip_init(void)
{ {
of_irq_init(__irqchip_begin); of_irq_init(__irqchip_of_table);
} }
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#ifndef _IRQCHIP_H #ifndef _IRQCHIP_H
#define _IRQCHIP_H #define _IRQCHIP_H
#include <linux/of.h>
/* /*
* This macro must be used by the different irqchip drivers to declare * This macro must be used by the different irqchip drivers to declare
* the association between their DT compatible string and their * the association between their DT compatible string and their
...@@ -21,9 +23,6 @@ ...@@ -21,9 +23,6 @@
* @compstr: compatible string of the irqchip driver * @compstr: compatible string of the irqchip driver
* @fn: initialization function * @fn: initialization function
*/ */
#define IRQCHIP_DECLARE(name,compstr,fn) \ #define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn)
static const struct of_device_id irqchip_of_match_##name \
__used __section(__irqchip_of_table) \
= { .compatible = compstr, .data = fn }
#endif #endif
...@@ -20,6 +20,7 @@ config OF_SELFTEST ...@@ -20,6 +20,7 @@ config OF_SELFTEST
config OF_FLATTREE config OF_FLATTREE
bool bool
select DTC select DTC
select LIBFDT
config OF_EARLY_FLATTREE config OF_EARLY_FLATTREE
bool bool
......
obj-y = base.o device.o platform.o obj-y = base.o device.o platform.o
obj-$(CONFIG_OF_FLATTREE) += fdt.o obj-$(CONFIG_OF_FLATTREE) += fdt.o
obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
obj-$(CONFIG_OF_PROMTREE) += pdt.o obj-$(CONFIG_OF_PROMTREE) += pdt.o
obj-$(CONFIG_OF_ADDRESS) += address.o obj-$(CONFIG_OF_ADDRESS) += address.o
obj-$(CONFIG_OF_IRQ) += irq.o obj-$(CONFIG_OF_IRQ) += irq.o
...@@ -10,3 +11,6 @@ obj-$(CONFIG_OF_PCI) += of_pci.o ...@@ -10,3 +11,6 @@ obj-$(CONFIG_OF_PCI) += of_pci.o
obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o
obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_MTD) += of_mtd.o
obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.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, ...@@ -498,8 +498,7 @@ static u64 __of_translate_address(struct device_node *dev,
/* Count address cells & copy address locally */ /* Count address cells & copy address locally */
bus->count_cells(dev, &na, &ns); bus->count_cells(dev, &na, &ns);
if (!OF_CHECK_COUNTS(na, ns)) { if (!OF_CHECK_COUNTS(na, ns)) {
printk(KERN_ERR "prom_parse: Bad cell count for %s\n", pr_debug("OF: Bad cell count for %s\n", of_node_full_name(dev));
of_node_full_name(dev));
goto bail; goto bail;
} }
memcpy(addr, in_addr, na * 4); memcpy(addr, in_addr, na * 4);
...@@ -564,25 +563,6 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr) ...@@ -564,25 +563,6 @@ u64 of_translate_dma_address(struct device_node *dev, const __be32 *in_addr)
} }
EXPORT_SYMBOL(of_translate_dma_address); 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, const __be32 *of_get_address(struct device_node *dev, int index, u64 *size,
unsigned int *flags) unsigned int *flags)
{ {
......
...@@ -695,6 +695,25 @@ struct device_node *of_get_next_parent(struct device_node *node) ...@@ -695,6 +695,25 @@ struct device_node *of_get_next_parent(struct device_node *node)
} }
EXPORT_SYMBOL(of_get_next_parent); 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 * of_get_next_child - Iterate a node childs
* @node: parent node * @node: parent node
...@@ -710,11 +729,7 @@ struct device_node *of_get_next_child(const struct device_node *node, ...@@ -710,11 +729,7 @@ struct device_node *of_get_next_child(const struct device_node *node,
unsigned long flags; unsigned long flags;
raw_spin_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child; next = __of_get_next_child(node, prev);
for (; next; next = next->sibling)
if (of_node_get(next))
break;
of_node_put(prev);
raw_spin_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next; return next;
} }
...@@ -734,6 +749,9 @@ struct device_node *of_get_next_available_child(const struct device_node *node, ...@@ -734,6 +749,9 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
struct device_node *next; struct device_node *next;
unsigned long flags; unsigned long flags;
if (!node)
return NULL;
raw_spin_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child; next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) { for (; next; next = next->sibling) {
...@@ -771,23 +789,78 @@ struct device_node *of_get_child_by_name(const struct device_node *node, ...@@ -771,23 +789,78 @@ struct device_node *of_get_child_by_name(const struct device_node *node,
} }
EXPORT_SYMBOL(of_get_child_by_name); 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 * 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 * Returns a node pointer with refcount incremented, use
* of_node_put() on it when done. * of_node_put() on it when done.
*/ */
struct device_node *of_find_node_by_path(const char *path) 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; 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); raw_spin_lock_irqsave(&devtree_lock, flags);
for (; np; np = np->allnext) { if (!np)
if (np->full_name && (of_node_cmp(np->full_name, path) == 0) np = of_node_get(of_allnodes);
&& of_node_get(np)) while (np && *path == '/') {
break; path++; /* Increment past '/' delimiter */
np = __of_find_node_by_path(np, path);
path = strchrnul(path, '/');
} }
raw_spin_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
...@@ -1800,7 +1873,7 @@ int of_update_property(struct device_node *np, struct property *newprop) ...@@ -1800,7 +1873,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
{ {
struct property **next, *oldprop; struct property **next, *oldprop;
unsigned long flags; unsigned long flags;
int rc, found = 0; int rc;
rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
if (rc) if (rc)
...@@ -1809,34 +1882,34 @@ int of_update_property(struct device_node *np, struct property *newprop) ...@@ -1809,34 +1882,34 @@ int of_update_property(struct device_node *np, struct property *newprop)
if (!newprop->name) if (!newprop->name)
return -EINVAL; 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); raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties; 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) { if (*next == oldprop) {
/* found the node */
newprop->next = oldprop->next; newprop->next = oldprop->next;
*next = newprop; *next = newprop;
oldprop->next = np->deadprops; oldprop->next = np->deadprops;
np->deadprops = oldprop; np->deadprops = oldprop;
found = 1;
break; break;
} }
next = &(*next)->next; next = &(*next)->next;
} }
raw_spin_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
if (!found) if (rc)
return -ENODEV; return rc;
/* At early boot, bail out and defer setup to of_init() */ /* At early boot, bail out and defer setup to of_init() */
if (!of_kset) if (!of_kset)
return found ? 0 : -ENODEV; return 0;
/* Update the sysfs attribute */ /* 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); __of_add_property_sysfs(np, newprop);
return 0; return 0;
......
This diff is collapsed.
/*
* 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) ...@@ -405,6 +405,28 @@ int of_irq_get(struct device_node *dev, int index)
return irq_create_of_mapping(&oirq); 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 * of_irq_count - Count the number of IRQs a node uses
* @dev: pointer to device tree node * @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 ...@@ -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 device_node *dn, *ppnode;
struct pci_dev *ppdev; struct pci_dev *ppdev;
u32 lspec;
__be32 lspec_be;
__be32 laddr[3]; __be32 laddr[3];
u8 pin; u8 pin;
int rc; int rc;
...@@ -46,7 +44,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq ...@@ -46,7 +44,6 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq
return -ENODEV; return -ENODEV;
/* Now we walk up the PCI tree */ /* Now we walk up the PCI tree */
lspec = pin;
for (;;) { for (;;) {
/* Get the pci_dev of our parent */ /* Get the pci_dev of our parent */
ppdev = pdev->bus->self; ppdev = pdev->bus->self;
...@@ -80,14 +77,13 @@ int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args *out_irq ...@@ -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, /* We can only get here if we hit a P2P bridge with no node,
* let's do standard swizzling and try again * let's do standard swizzling and try again
*/ */
lspec = pci_swizzle_interrupt_pin(pdev, lspec); pin = pci_swizzle_interrupt_pin(pdev, pin);
pdev = ppdev; pdev = ppdev;
} }
out_irq->np = ppnode; out_irq->np = ppnode;
out_irq->args_count = 1; out_irq->args_count = 1;
out_irq->args[0] = lspec; out_irq->args[0] = pin;
lspec_be = cpu_to_be32(lspec);
laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8)); laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
laddr[1] = laddr[2] = cpu_to_be32(0); laddr[1] = laddr[2] = cpu_to_be32(0);
return of_irq_parse_raw(laddr, out_irq); return of_irq_parse_raw(laddr, out_irq);
......
...@@ -95,8 +95,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ...@@ -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); int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32);
phys_addr_t start = 0, end = 0; phys_addr_t start = 0, end = 0;
phys_addr_t base = 0, align = 0, size; phys_addr_t base = 0, align = 0, size;
unsigned long len; int len;
__be32 *prop; const __be32 *prop;
int nomap; int nomap;
int ret; int ret;
...@@ -188,7 +188,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem) ...@@ -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)) if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
continue; 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", pr_info("Reserved memory: initialized node %s, compatible id %s\n",
rmem->name, compat); rmem->name, compat);
return 0; return 0;
......
...@@ -51,10 +51,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np) ...@@ -51,10 +51,6 @@ struct platform_device *of_find_device_by_node(struct device_node *np)
} }
EXPORT_SYMBOL(of_find_device_by_node); EXPORT_SYMBOL(of_find_device_by_node);
#if defined(CONFIG_PPC_DCR)
#include <asm/dcr.h>
#endif
#ifdef CONFIG_OF_ADDRESS #ifdef CONFIG_OF_ADDRESS
/* /*
* The following routines scan a subtree and registers a device for * The following routines scan a subtree and registers a device for
...@@ -68,66 +64,35 @@ EXPORT_SYMBOL(of_find_device_by_node); ...@@ -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 * 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 * @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 * This routine will first try using the translated bus address to
* value to derive a unique name. As a last resort it will use the node * derive a unique name. If it cannot, then it will prepend names from
* name followed by a unique number. * parent nodes until a unique name can be derived.
*/ */
void of_device_make_bus_id(struct device *dev) void of_device_make_bus_id(struct device *dev)
{ {
static atomic_t bus_no_reg_magic;
struct device_node *node = dev->of_node; struct device_node *node = dev->of_node;
const __be32 *reg; const __be32 *reg;
u64 addr; u64 addr;
const __be32 *addrp;
int magic;
#ifdef CONFIG_PPC_DCR /* Construct the name, using parent nodes if necessary to ensure uniqueness */
/* while (node->parent) {
* If it's a DCR based device, use 'd' for native DCRs /*
* and 'D' for MMIO DCRs. * 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, "dcr-reg", NULL); */
if (reg) { reg = of_get_property(node, "reg", NULL);
#ifdef CONFIG_PPC_DCR_NATIVE if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) {
dev_set_name(dev, "d%x.%s", *reg, node->name); dev_set_name(dev, dev_name(dev) ? "%llx.%s:%s" : "%llx.%s",
#else /* CONFIG_PPC_DCR_NATIVE */ (unsigned long long)addr, node->name,
u64 addr = of_translate_dcr_address(node, *reg, NULL); dev_name(dev));
if (addr != OF_BAD_ADDR) {
dev_set_name(dev, "D%llx.%s",
(unsigned long long)addr, node->name);
return; return;
} }
#endif /* !CONFIG_PPC_DCR_NATIVE */
}
#endif /* CONFIG_PPC_DCR */
/* /* format arguments only used if dev_name() resolves to NULL */
* For MMIO, get the physical address dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s",
*/ strrchr(node->full_name, '/') + 1, dev_name(dev));
reg = of_get_property(node, "reg", NULL); node = node->parent;
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;
}
} }
/*
* 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, ...@@ -149,9 +114,8 @@ struct platform_device *of_device_alloc(struct device_node *np,
return NULL; return NULL;
/* count the io and irq resources */ /* count the io and irq resources */
if (of_can_translate_address(np)) while (of_address_to_resource(np, num_reg, &temp_res) == 0)
while (of_address_to_resource(np, num_reg, &temp_res) == 0) num_reg++;
num_reg++;
num_irq = of_irq_count(np); num_irq = of_irq_count(np);
/* Populate the resource table */ /* Populate the resource table */
......
...@@ -31,6 +31,51 @@ static struct selftest_results { ...@@ -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) static void __init of_selftest_dynamic(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -431,8 +476,12 @@ static void __init of_selftest_match_node(void) ...@@ -431,8 +476,12 @@ static void __init of_selftest_match_node(void)
static void __init of_selftest_platform_populate(void) static void __init of_selftest_platform_populate(void)
{ {
int irq; int irq;
struct device_node *np; struct device_node *np, *child;
struct platform_device *pdev; struct platform_device *pdev;
struct of_device_id match[] = {
{ .compatible = "test-device", },
{}
};
np = of_find_node_by_path("/testcase-data"); np = of_find_node_by_path("/testcase-data");
of_platform_populate(np, of_default_bus_match_table, NULL, NULL); of_platform_populate(np, of_default_bus_match_table, NULL, NULL);
...@@ -440,22 +489,32 @@ static void __init of_selftest_platform_populate(void) ...@@ -440,22 +489,32 @@ static void __init of_selftest_platform_populate(void)
/* Test that a missing irq domain returns -EPROBE_DEFER */ /* Test that a missing irq domain returns -EPROBE_DEFER */
np = of_find_node_by_path("/testcase-data/testcase-device1"); np = of_find_node_by_path("/testcase-data/testcase-device1");
pdev = of_find_device_by_node(np); pdev = of_find_device_by_node(np);
if (!pdev) selftest(pdev, "device 1 creation failed\n");
selftest(0, "device 1 creation failed\n");
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq != -EPROBE_DEFER) selftest(irq == -EPROBE_DEFER, "device deferred probe failed - %d\n", irq);
selftest(0, "device deferred probe failed - %d\n", irq);
/* Test that a parsing failure does not return -EPROBE_DEFER */ /* Test that a parsing failure does not return -EPROBE_DEFER */
np = of_find_node_by_path("/testcase-data/testcase-device2"); np = of_find_node_by_path("/testcase-data/testcase-device2");
pdev = of_find_device_by_node(np); pdev = of_find_device_by_node(np);
if (!pdev) selftest(pdev, "device 2 creation failed\n");
selftest(0, "device 2 creation failed\n");
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq >= 0 || irq == -EPROBE_DEFER) selftest(irq < 0 && irq != -EPROBE_DEFER, "device parsing error failed - %d\n", irq);
selftest(0, "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) static int __init of_selftest(void)
...@@ -470,6 +529,7 @@ static int __init of_selftest(void) ...@@ -470,6 +529,7 @@ static int __init of_selftest(void)
of_node_put(np); of_node_put(np);
pr_info("start of selftest - you will see error messages\n"); pr_info("start of selftest - you will see error messages\n");
of_selftest_find_node_by_name();
of_selftest_dynamic(); of_selftest_dynamic();
of_selftest_parse_phandle_with_args(); of_selftest_parse_phandle_with_args();
of_selftest_property_match_string(); of_selftest_property_match_string();
......
#include "tests-phandle.dtsi" #include "tests-phandle.dtsi"
#include "tests-interrupts.dtsi" #include "tests-interrupts.dtsi"
#include "tests-match.dtsi" #include "tests-match.dtsi"
#include "tests-platform.dtsi"
/ { / {
testcase-data { aliases {
testcase-alias = &testcase;
};
testcase: testcase-data {
security-password = "password"; security-password = "password";
duplicate-name = "duplicate"; duplicate-name = "duplicate";
duplicate-name { }; duplicate-name { };
......
/ {
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, ...@@ -2072,6 +2072,7 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
return 0; return 0;
} }
EARLYCON_DECLARE(pl011, pl011_early_console_setup); EARLYCON_DECLARE(pl011, pl011_early_console_setup);
OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
#else #else
#define AMBA_CONSOLE NULL #define AMBA_CONSOLE NULL
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/sizes.h>
#include <linux/mod_devicetable.h>
#ifdef CONFIG_FIX_EARLYCON_MEM #ifdef CONFIG_FIX_EARLYCON_MEM
#include <asm/fixmap.h> #include <asm/fixmap.h>
...@@ -32,6 +34,9 @@ static struct earlycon_device early_console_dev = { ...@@ -32,6 +34,9 @@ static struct earlycon_device early_console_dev = {
.con = &early_con, .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) static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
{ {
void __iomem *base; void __iomem *base;
...@@ -142,3 +147,26 @@ int __init setup_earlycon(char *buf, const char *match, ...@@ -142,3 +147,26 @@ int __init setup_earlycon(char *buf, const char *match,
register_console(early_console_dev.con); register_console(early_console_dev.con);
return 0; 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 @@ ...@@ -139,52 +139,23 @@
#define TRACE_SYSCALLS() #define TRACE_SYSCALLS()
#endif #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 ___OF_TABLE(cfg, name) _OF_TABLE_##cfg(name)
#define IRQCHIP_OF_MATCH_TABLE() \ #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); \ . = ALIGN(8); \
VMLINUX_SYMBOL(__irqchip_begin) = .; \ VMLINUX_SYMBOL(__##name##_of_table) = .; \
*(__irqchip_of_table) \ *(__##name##_of_table) \
*(__irqchip_of_end) *(__##name##_of_table_end)
#else
#define IRQCHIP_OF_MATCH_TABLE()
#endif
#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 CLKSRC_OF_TABLES() OF_TABLE(CONFIG_CLKSRC_OF, clksrc)
#define CPU_METHOD_OF_TABLES() . = ALIGN(8); \ #define IRQCHIP_OF_MATCH_TABLE() OF_TABLE(CONFIG_IRQCHIP, irqchip)
VMLINUX_SYMBOL(__cpu_method_of_table_begin) = .; \ #define CLK_OF_TABLES() OF_TABLE(CONFIG_COMMON_CLK, clk)
*(__cpu_method_of_table) \ #define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
VMLINUX_SYMBOL(__cpu_method_of_table_end) = .; #define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
#else #define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
#define CPU_METHOD_OF_TABLES()
#endif
#define KERNEL_DTB() \ #define KERNEL_DTB() \
STRUCT_ALIGN(); \ STRUCT_ALIGN(); \
...@@ -513,7 +484,8 @@ ...@@ -513,7 +484,8 @@
CLKSRC_OF_TABLES() \ CLKSRC_OF_TABLES() \
CPU_METHOD_OF_TABLES() \ CPU_METHOD_OF_TABLES() \
KERNEL_DTB() \ KERNEL_DTB() \
IRQCHIP_OF_MATCH_TABLE() IRQCHIP_OF_MATCH_TABLE() \
EARLYCON_OF_TABLES()
#define INIT_TEXT \ #define INIT_TEXT \
*(.init.text) \ *(.init.text) \
......
...@@ -529,10 +529,7 @@ struct clk_onecell_data { ...@@ -529,10 +529,7 @@ struct clk_onecell_data {
extern struct of_device_id __clk_of_table; extern struct of_device_id __clk_of_table;
#define CLK_OF_DECLARE(name, compat, fn) \ #define CLK_OF_DECLARE(name, compat, fn) OF_DECLARE_1(clk, name, compat, fn)
static const struct of_device_id __clk_of_table_##name \
__used __section(__clk_of_table) \
= { .compatible = compat, .data = fn };
#ifdef CONFIG_OF #ifdef CONFIG_OF
int of_clk_add_provider(struct device_node *np, int of_clk_add_provider(struct device_node *np,
......
...@@ -339,23 +339,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *, ...@@ -339,23 +339,13 @@ extern int clocksource_mmio_init(void __iomem *, const char *,
extern int clocksource_i8253_init(void); extern int clocksource_i8253_init(void);
struct device_node; #define CLOCKSOURCE_OF_DECLARE(name, compat, fn) \
typedef void(*clocksource_of_init_fn)(struct device_node *); OF_DECLARE_1(clksrc, name, compat, fn)
#ifdef CONFIG_CLKSRC_OF #ifdef CONFIG_CLKSRC_OF
extern void clocksource_of_init(void); 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 #else
static inline void clocksource_of_init(void) {} 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
#endif /* _LINUX_CLOCKSOURCE_H */ #endif /* _LINUX_CLOCKSOURCE_H */
...@@ -764,4 +764,26 @@ static inline int of_get_available_child_count(const struct device_node *np) ...@@ -764,4 +764,26 @@ static inline int of_get_available_child_count(const struct device_node *np)
return num; 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 */ #endif /* _LINUX_OF_H */
...@@ -40,7 +40,6 @@ extern u64 of_translate_dma_address(struct device_node *dev, ...@@ -40,7 +40,6 @@ extern u64 of_translate_dma_address(struct device_node *dev,
#ifdef CONFIG_OF_ADDRESS #ifdef CONFIG_OF_ADDRESS
extern u64 of_translate_address(struct device_node *np, const __be32 *addr); 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, extern int of_address_to_resource(struct device_node *dev, int index,
struct resource *r); struct resource *r);
extern struct device_node *of_find_matching_node_by_address( extern struct device_node *of_find_matching_node_by_address(
......
...@@ -17,60 +17,23 @@ ...@@ -17,60 +17,23 @@
/* Definitions used by the flattened device tree */ /* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */ #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__ #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) #if defined(CONFIG_OF_FLATTREE)
struct device_node; struct device_node;
/* For scanning an arbitrary device-tree at any time */ /* For scanning an arbitrary device-tree at any time */
extern char *of_fdt_get_string(struct boot_param_header *blob, u32 offset); extern char *of_fdt_get_string(const void *blob, u32 offset);
extern void *of_fdt_get_property(struct boot_param_header *blob, extern void *of_fdt_get_property(const void *blob,
unsigned long node, unsigned long node,
const char *name, const char *name,
unsigned long *size); int *size);
extern int of_fdt_is_compatible(struct boot_param_header *blob, extern int of_fdt_is_compatible(const void *blob,
unsigned long node, unsigned long node,
const char *compat); 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); const char *const *compat);
extern void of_fdt_unflatten_tree(unsigned long *blob, extern void of_fdt_unflatten_tree(unsigned long *blob,
struct device_node **mynodes); struct device_node **mynodes);
...@@ -78,21 +41,21 @@ extern void of_fdt_unflatten_tree(unsigned long *blob, ...@@ -78,21 +41,21 @@ extern void of_fdt_unflatten_tree(unsigned long *blob,
/* TBD: Temporary export of fdt globals - remove when code fully merged */ /* TBD: Temporary export of fdt globals - remove when code fully merged */
extern int __initdata dt_root_addr_cells; extern int __initdata dt_root_addr_cells;
extern int __initdata dt_root_size_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 */ /* 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, extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname,
int depth, void *data), int depth, void *data),
void *data); void *data);
extern void *of_get_flat_dt_prop(unsigned long node, const char *name, extern const void *of_get_flat_dt_prop(unsigned long node, const char *name,
unsigned long *size); int *size);
extern int of_flat_dt_is_compatible(unsigned long node, const char *name); 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 int of_flat_dt_match(unsigned long node, const char *const *matches);
extern unsigned long of_get_flat_dt_root(void); extern unsigned long of_get_flat_dt_root(void);
extern int of_scan_flat_dt_by_path(const char *path, extern int of_get_flat_dt_size(void);
int (*it)(unsigned long node, const char *name, int depth, void *data),
void *data);
extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
int depth, void *data); int depth, void *data);
...@@ -103,7 +66,7 @@ extern void early_init_dt_add_memory_arch(u64 base, u64 size); ...@@ -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, extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size,
bool no_map); bool no_map);
extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); 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 */ /* Early flat tree scan hooks */
extern int early_init_dt_scan_root(unsigned long node, const char *uname, extern int early_init_dt_scan_root(unsigned long node, const char *uname,
...@@ -120,6 +83,7 @@ extern void unflatten_device_tree(void); ...@@ -120,6 +83,7 @@ extern void unflatten_device_tree(void);
extern void unflatten_and_copy_device_tree(void); extern void unflatten_and_copy_device_tree(void);
extern void early_init_devtree(void *); extern void early_init_devtree(void *);
extern void early_get_first_memblock_info(void *, phys_addr_t *); 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 */ #else /* CONFIG_OF_FLATTREE */
static inline void early_init_fdt_scan_reserved_mem(void) {} static inline void early_init_fdt_scan_reserved_mem(void) {}
static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } 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); ...@@ -45,6 +45,7 @@ extern void of_irq_init(const struct of_device_id *matches);
#ifdef CONFIG_OF_IRQ #ifdef CONFIG_OF_IRQ
extern int of_irq_count(struct device_node *dev); 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(struct device_node *dev, int index);
extern int of_irq_get_byname(struct device_node *dev, const char *name);
#else #else
static inline int of_irq_count(struct device_node *dev) 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) ...@@ -54,6 +55,10 @@ static inline int of_irq_get(struct device_node *dev, int index)
{ {
return 0; return 0;
} }
static inline int of_irq_get_byname(struct device_node *dev, const char *name)
{
return 0;
}
#endif #endif
#if defined(CONFIG_OF) #if defined(CONFIG_OF)
......
...@@ -6,14 +6,44 @@ ...@@ -6,14 +6,44 @@
struct pci_dev; struct pci_dev;
struct of_phandle_args; 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; 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, struct device_node *of_pci_find_child_device(struct device_node *parent,
unsigned int devfn); unsigned int devfn);
int of_pci_get_devfn(struct device_node *np); 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); 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) #if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
int of_pci_msi_chip_add(struct msi_chip *chip); int of_pci_msi_chip_add(struct msi_chip *chip);
......
...@@ -21,33 +21,19 @@ struct reserved_mem_ops { ...@@ -21,33 +21,19 @@ struct reserved_mem_ops {
struct device *dev); struct device *dev);
}; };
typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem);
unsigned long node, const char *uname);
#define RESERVEDMEM_OF_DECLARE(name, compat, init) \
_OF_DECLARE(reservedmem, name, compat, init, reservedmem_of_init_fn)
#ifdef CONFIG_OF_RESERVED_MEM #ifdef CONFIG_OF_RESERVED_MEM
void fdt_init_reserved_mem(void); void fdt_init_reserved_mem(void);
void fdt_reserved_mem_save_node(unsigned long node, const char *uname, void fdt_reserved_mem_save_node(unsigned long node, const char *uname,
phys_addr_t base, phys_addr_t size); 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 #else
static inline void fdt_init_reserved_mem(void) { } static inline void fdt_init_reserved_mem(void) { }
static inline void fdt_reserved_mem_save_node(unsigned long node, static inline void fdt_reserved_mem_save_node(unsigned long node,
const char *uname, phys_addr_t base, phys_addr_t size) { } 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
#endif /* __OF_RESERVED_MEM_H */ #endif /* __OF_RESERVED_MEM_H */
...@@ -294,6 +294,9 @@ struct earlycon_device { ...@@ -294,6 +294,9 @@ struct earlycon_device {
int setup_earlycon(char *buf, const char *match, int setup_earlycon(char *buf, const char *match,
int (*setup)(struct earlycon_device *, const char *)); 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) \ #define EARLYCON_DECLARE(name, func) \
static int __init name ## _setup_earlycon(char *buf) \ static int __init name ## _setup_earlycon(char *buf) \
{ \ { \
...@@ -301,6 +304,9 @@ 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); 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 uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c); struct console *c);
void uart_parse_options(char *options, int *baud, int *parity, int *bits, 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); ...@@ -52,6 +52,9 @@ extern int strncasecmp(const char *s1, const char *s2, size_t n);
#ifndef __HAVE_ARCH_STRCHR #ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int); extern char * strchr(const char *,int);
#endif #endif
#ifndef __HAVE_ARCH_STRCHRNUL
extern char * strchrnul(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRNCHR #ifndef __HAVE_ARCH_STRNCHR
extern char * strnchr(const char *, size_t, int); extern char * strnchr(const char *, size_t, int);
#endif #endif
......
...@@ -301,6 +301,24 @@ char *strchr(const char *s, int c) ...@@ -301,6 +301,24 @@ char *strchr(const char *s, int c)
EXPORT_SYMBOL(strchr); EXPORT_SYMBOL(strchr);
#endif #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 #ifndef __HAVE_ARCH_STRRCHR
/** /**
* strrchr - Find the last occurrence of a character in a string * strrchr - Find the last occurrence of a character in a string
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment