aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/fdt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-12 02:52:17 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-12 02:52:17 -0500
commit10d0c9705e80bbd3d587c5fad24599aabaca6688 (patch)
tree9456083a1b04b8d98da08d88e937cfeff80e2a7d /drivers/of/fdt.c
parent85b656cf1560e27a89354a23f2c10ba229d2f173 (diff)
parentc11eede69b6ad0ac44ebc1e021a8d2699c5f1f8f (diff)
Merge tag 'devicetree-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree updates from Rob Herring: "DeviceTree updates for 3.13. This is a bit larger pull request than usual for this cycle with lots of clean-up. - Cross arch clean-up and consolidation of early DT scanning code. - Clean-up and removal of arch prom.h headers. Makes arch specific prom.h optional on all but Sparc. - Addition of interrupts-extended property for devices connected to multiple interrupt controllers. - Refactoring of DT interrupt parsing code in preparation for deferred probe of interrupts. - ARM cpu and cpu topology bindings documentation. - Various DT vendor binding documentation updates" * tag 'devicetree-for-3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: (82 commits) powerpc: add missing explicit OF includes for ppc dt/irq: add empty of_irq_count for !OF_IRQ dt: disable self-tests for !OF_IRQ of: irq: Fix interrupt-map entry matching MIPS: Netlogic: replace early_init_devtree() call of: Add Panasonic Corporation vendor prefix of: Add Chunghwa Picture Tubes Ltd. vendor prefix of: Add AU Optronics Corporation vendor prefix of/irq: Fix potential buffer overflow of/irq: Fix bug in interrupt parsing refactor. of: set dma_mask to point to coherent_dma_mask of: add vendor prefix for PHYTEC Messtechnik GmbH DT: sort vendor-prefixes.txt of: Add vendor prefix for Cadence of: Add empty for_each_available_child_of_node() macro definition arm/versatile: Fix versatile irq specifications. of/irq: create interrupts-extended property microblaze/pci: Drop PowerPC-ism from irq parsing of/irq: Create of_irq_parse_and_map_pci() to consolidate arch code. of/irq: Use irq_of_parse_and_map() ...
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r--drivers/of/fdt.c138
1 files changed, 135 insertions, 3 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index a4fa9ad31b8f..2fa024b97c43 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -618,12 +618,72 @@ int __init of_scan_flat_dt_by_path(const char *path,
618 return ret; 618 return ret;
619} 619}
620 620
621const char * __init of_flat_dt_get_machine_name(void)
622{
623 const char *name;
624 unsigned long dt_root = of_get_flat_dt_root();
625
626 name = of_get_flat_dt_prop(dt_root, "model", NULL);
627 if (!name)
628 name = of_get_flat_dt_prop(dt_root, "compatible", NULL);
629 return name;
630}
631
632/**
633 * of_flat_dt_match_machine - Iterate match tables to find matching machine.
634 *
635 * @default_match: A machine specific ptr to return in case of no match.
636 * @get_next_compat: callback function to return next compatible match table.
637 *
638 * Iterate through machine match tables to find the best match for the machine
639 * compatible string in the FDT.
640 */
641const void * __init of_flat_dt_match_machine(const void *default_match,
642 const void * (*get_next_compat)(const char * const**))
643{
644 const void *data = NULL;
645 const void *best_data = default_match;
646 const char *const *compat;
647 unsigned long dt_root;
648 unsigned int best_score = ~1, score = 0;
649
650 dt_root = of_get_flat_dt_root();
651 while ((data = get_next_compat(&compat))) {
652 score = of_flat_dt_match(dt_root, compat);
653 if (score > 0 && score < best_score) {
654 best_data = data;
655 best_score = score;
656 }
657 }
658 if (!best_data) {
659 const char *prop;
660 long size;
661
662 pr_err("\n unrecognized device tree list:\n[ ");
663
664 prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
665 if (prop) {
666 while (size > 0) {
667 printk("'%s' ", prop);
668 size -= strlen(prop) + 1;
669 prop += strlen(prop) + 1;
670 }
671 }
672 printk("]\n\n");
673 return NULL;
674 }
675
676 pr_info("Machine model: %s\n", of_flat_dt_get_machine_name());
677
678 return best_data;
679}
680
621#ifdef CONFIG_BLK_DEV_INITRD 681#ifdef CONFIG_BLK_DEV_INITRD
622/** 682/**
623 * early_init_dt_check_for_initrd - Decode initrd location from flat tree 683 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
624 * @node: reference to node containing initrd location ('chosen') 684 * @node: reference to node containing initrd location ('chosen')
625 */ 685 */
626void __init early_init_dt_check_for_initrd(unsigned long node) 686static void __init early_init_dt_check_for_initrd(unsigned long node)
627{ 687{
628 u64 start, end; 688 u64 start, end;
629 unsigned long len; 689 unsigned long len;
@@ -641,12 +701,15 @@ void __init early_init_dt_check_for_initrd(unsigned long node)
641 return; 701 return;
642 end = of_read_number(prop, len/4); 702 end = of_read_number(prop, len/4);
643 703
644 early_init_dt_setup_initrd_arch(start, end); 704 initrd_start = (unsigned long)__va(start);
705 initrd_end = (unsigned long)__va(end);
706 initrd_below_start_ok = 1;
707
645 pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", 708 pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n",
646 (unsigned long long)start, (unsigned long long)end); 709 (unsigned long long)start, (unsigned long long)end);
647} 710}
648#else 711#else
649inline void early_init_dt_check_for_initrd(unsigned long node) 712static inline void early_init_dt_check_for_initrd(unsigned long node)
650{ 713{
651} 714}
652#endif /* CONFIG_BLK_DEV_INITRD */ 715#endif /* CONFIG_BLK_DEV_INITRD */
@@ -774,6 +837,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
774} 837}
775 838
776#ifdef CONFIG_HAVE_MEMBLOCK 839#ifdef CONFIG_HAVE_MEMBLOCK
840void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size)
841{
842 const u64 phys_offset = __pa(PAGE_OFFSET);
843 base &= PAGE_MASK;
844 size &= PAGE_MASK;
845 if (base + size < phys_offset) {
846 pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
847 base, base + size);
848 return;
849 }
850 if (base < phys_offset) {
851 pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
852 base, phys_offset);
853 size -= phys_offset - base;
854 base = phys_offset;
855 }
856 memblock_add(base, size);
857}
858
777/* 859/*
778 * called from unflatten_device_tree() to bootstrap devicetree itself 860 * called from unflatten_device_tree() to bootstrap devicetree itself
779 * Architectures can override this definition if memblock isn't used 861 * Architectures can override this definition if memblock isn't used
@@ -784,6 +866,32 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align)
784} 866}
785#endif 867#endif
786 868
869bool __init early_init_dt_scan(void *params)
870{
871 if (!params)
872 return false;
873
874 /* Setup flat device-tree pointer */
875 initial_boot_params = params;
876
877 /* check device tree validity */
878 if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
879 initial_boot_params = NULL;
880 return false;
881 }
882
883 /* Retrieve various information from the /chosen node */
884 of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);
885
886 /* Initialize {size,address}-cells info */
887 of_scan_flat_dt(early_init_dt_scan_root, NULL);
888
889 /* Setup memory, calling early_init_dt_add_memory_arch */
890 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
891
892 return true;
893}
894
787/** 895/**
788 * unflatten_device_tree - create tree of device_nodes from flat blob 896 * unflatten_device_tree - create tree of device_nodes from flat blob
789 * 897 *
@@ -801,4 +909,28 @@ void __init unflatten_device_tree(void)
801 of_alias_scan(early_init_dt_alloc_memory_arch); 909 of_alias_scan(early_init_dt_alloc_memory_arch);
802} 910}
803 911
912/**
913 * unflatten_and_copy_device_tree - copy and create tree of device_nodes from flat blob
914 *
915 * Copies and unflattens the device-tree passed by the firmware, creating the
916 * tree of struct device_node. It also fills the "name" and "type"
917 * pointers of the nodes so the normal device-tree walking functions
918 * can be used. This should only be used when the FDT memory has not been
919 * reserved such is the case when the FDT is built-in to the kernel init
920 * section. If the FDT memory is reserved already then unflatten_device_tree
921 * should be used instead.
922 */
923void __init unflatten_and_copy_device_tree(void)
924{
925 int size = __be32_to_cpu(initial_boot_params->totalsize);
926 void *dt = early_init_dt_alloc_memory_arch(size,
927 __alignof__(struct boot_param_header));
928
929 if (dt) {
930 memcpy(dt, initial_boot_params, size);
931 initial_boot_params = dt;
932 }
933 unflatten_device_tree();
934}
935
804#endif /* CONFIG_OF_EARLY_FLATTREE */ 936#endif /* CONFIG_OF_EARLY_FLATTREE */