diff options
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 154 |
1 files changed, 98 insertions, 56 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index d63cd562d9d5..4336390bcf34 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -383,14 +383,14 @@ static int __devinit finish_node_interrupts(struct device_node *np, | |||
383 | /* Apple uses bits in there in a different way, let's | 383 | /* Apple uses bits in there in a different way, let's |
384 | * only keep the real sense bit on macs | 384 | * only keep the real sense bit on macs |
385 | */ | 385 | */ |
386 | if (_machine == PLATFORM_POWERMAC) | 386 | if (machine_is(powermac)) |
387 | sense &= 0x1; | 387 | sense &= 0x1; |
388 | np->intrs[intrcount].sense = map_mpic_senses[sense]; | 388 | np->intrs[intrcount].sense = map_mpic_senses[sense]; |
389 | } | 389 | } |
390 | 390 | ||
391 | #ifdef CONFIG_PPC64 | 391 | #ifdef CONFIG_PPC64 |
392 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ | 392 | /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ |
393 | if (_machine == PLATFORM_POWERMAC && ic && ic->parent) { | 393 | if (machine_is(powermac) && ic && ic->parent) { |
394 | char *name = get_property(ic->parent, "name", NULL); | 394 | char *name = get_property(ic->parent, "name", NULL); |
395 | if (name && !strcmp(name, "u3")) | 395 | if (name && !strcmp(name, "u3")) |
396 | np->intrs[intrcount].line += 128; | 396 | np->intrs[intrcount].line += 128; |
@@ -570,6 +570,18 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node, | |||
570 | return rc; | 570 | return rc; |
571 | } | 571 | } |
572 | 572 | ||
573 | unsigned long __init of_get_flat_dt_root(void) | ||
574 | { | ||
575 | unsigned long p = ((unsigned long)initial_boot_params) + | ||
576 | initial_boot_params->off_dt_struct; | ||
577 | |||
578 | while(*((u32 *)p) == OF_DT_NOP) | ||
579 | p += 4; | ||
580 | BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE); | ||
581 | p += 4; | ||
582 | return _ALIGN(p + strlen((char *)p) + 1, 4); | ||
583 | } | ||
584 | |||
573 | /** | 585 | /** |
574 | * This function can be used within scan_flattened_dt callback to get | 586 | * This function can be used within scan_flattened_dt callback to get |
575 | * access to properties | 587 | * access to properties |
@@ -612,6 +624,25 @@ void* __init of_get_flat_dt_prop(unsigned long node, const char *name, | |||
612 | } while(1); | 624 | } while(1); |
613 | } | 625 | } |
614 | 626 | ||
627 | int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) | ||
628 | { | ||
629 | const char* cp; | ||
630 | unsigned long cplen, l; | ||
631 | |||
632 | cp = of_get_flat_dt_prop(node, "compatible", &cplen); | ||
633 | if (cp == NULL) | ||
634 | return 0; | ||
635 | while (cplen > 0) { | ||
636 | if (strncasecmp(cp, compat, strlen(compat)) == 0) | ||
637 | return 1; | ||
638 | l = strlen(cp) + 1; | ||
639 | cp += l; | ||
640 | cplen -= l; | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
615 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, | 646 | static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, |
616 | unsigned long align) | 647 | unsigned long align) |
617 | { | 648 | { |
@@ -686,7 +717,7 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, | |||
686 | #ifdef DEBUG | 717 | #ifdef DEBUG |
687 | if ((strlen(p) + l + 1) != allocl) { | 718 | if ((strlen(p) + l + 1) != allocl) { |
688 | DBG("%s: p: %d, l: %d, a: %d\n", | 719 | DBG("%s: p: %d, l: %d, a: %d\n", |
689 | pathp, strlen(p), l, allocl); | 720 | pathp, (int)strlen(p), l, allocl); |
690 | } | 721 | } |
691 | #endif | 722 | #endif |
692 | p += strlen(p); | 723 | p += strlen(p); |
@@ -854,35 +885,73 @@ void __init unflatten_device_tree(void) | |||
854 | DBG(" <- unflatten_device_tree()\n"); | 885 | DBG(" <- unflatten_device_tree()\n"); |
855 | } | 886 | } |
856 | 887 | ||
857 | |||
858 | static int __init early_init_dt_scan_cpus(unsigned long node, | 888 | static int __init early_init_dt_scan_cpus(unsigned long node, |
859 | const char *uname, int depth, void *data) | 889 | const char *uname, int depth, |
890 | void *data) | ||
860 | { | 891 | { |
892 | static int logical_cpuid = 0; | ||
893 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | ||
894 | #ifdef CONFIG_ALTIVEC | ||
861 | u32 *prop; | 895 | u32 *prop; |
862 | unsigned long size; | 896 | #endif |
863 | char *type = of_get_flat_dt_prop(node, "device_type", &size); | 897 | u32 *intserv; |
898 | int i, nthreads; | ||
899 | unsigned long len; | ||
900 | int found = 0; | ||
864 | 901 | ||
865 | /* We are scanning "cpu" nodes only */ | 902 | /* We are scanning "cpu" nodes only */ |
866 | if (type == NULL || strcmp(type, "cpu") != 0) | 903 | if (type == NULL || strcmp(type, "cpu") != 0) |
867 | return 0; | 904 | return 0; |
868 | 905 | ||
869 | boot_cpuid = 0; | 906 | /* Get physical cpuid */ |
870 | boot_cpuid_phys = 0; | 907 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); |
871 | if (initial_boot_params && initial_boot_params->version >= 2) { | 908 | if (intserv) { |
872 | /* version 2 of the kexec param format adds the phys cpuid | 909 | nthreads = len / sizeof(int); |
873 | * of booted proc. | ||
874 | */ | ||
875 | boot_cpuid_phys = initial_boot_params->boot_cpuid_phys; | ||
876 | } else { | 910 | } else { |
877 | /* Check if it's the boot-cpu, set it's hw index now */ | 911 | intserv = of_get_flat_dt_prop(node, "reg", NULL); |
878 | if (of_get_flat_dt_prop(node, | 912 | nthreads = 1; |
913 | } | ||
914 | |||
915 | /* | ||
916 | * Now see if any of these threads match our boot cpu. | ||
917 | * NOTE: This must match the parsing done in smp_setup_cpu_maps. | ||
918 | */ | ||
919 | for (i = 0; i < nthreads; i++) { | ||
920 | /* | ||
921 | * version 2 of the kexec param format adds the phys cpuid of | ||
922 | * booted proc. | ||
923 | */ | ||
924 | if (initial_boot_params && initial_boot_params->version >= 2) { | ||
925 | if (intserv[i] == | ||
926 | initial_boot_params->boot_cpuid_phys) { | ||
927 | found = 1; | ||
928 | break; | ||
929 | } | ||
930 | } else { | ||
931 | /* | ||
932 | * Check if it's the boot-cpu, set it's hw index now, | ||
933 | * unfortunately this format did not support booting | ||
934 | * off secondary threads. | ||
935 | */ | ||
936 | if (of_get_flat_dt_prop(node, | ||
879 | "linux,boot-cpu", NULL) != NULL) { | 937 | "linux,boot-cpu", NULL) != NULL) { |
880 | prop = of_get_flat_dt_prop(node, "reg", NULL); | 938 | found = 1; |
881 | if (prop != NULL) | 939 | break; |
882 | boot_cpuid_phys = *prop; | 940 | } |
883 | } | 941 | } |
942 | |||
943 | #ifdef CONFIG_SMP | ||
944 | /* logical cpu id is always 0 on UP kernels */ | ||
945 | logical_cpuid++; | ||
946 | #endif | ||
947 | } | ||
948 | |||
949 | if (found) { | ||
950 | DBG("boot cpu: logical %d physical %d\n", logical_cpuid, | ||
951 | intserv[i]); | ||
952 | boot_cpuid = logical_cpuid; | ||
953 | set_hard_smp_processor_id(boot_cpuid, intserv[i]); | ||
884 | } | 954 | } |
885 | set_hard_smp_processor_id(0, boot_cpuid_phys); | ||
886 | 955 | ||
887 | #ifdef CONFIG_ALTIVEC | 956 | #ifdef CONFIG_ALTIVEC |
888 | /* Check if we have a VMX and eventually update CPU features */ | 957 | /* Check if we have a VMX and eventually update CPU features */ |
@@ -901,16 +970,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
901 | #endif /* CONFIG_ALTIVEC */ | 970 | #endif /* CONFIG_ALTIVEC */ |
902 | 971 | ||
903 | #ifdef CONFIG_PPC_PSERIES | 972 | #ifdef CONFIG_PPC_PSERIES |
904 | /* | 973 | if (nthreads > 1) |
905 | * Check for an SMT capable CPU and set the CPU feature. We do | ||
906 | * this by looking at the size of the ibm,ppc-interrupt-server#s | ||
907 | * property | ||
908 | */ | ||
909 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", | ||
910 | &size); | ||
911 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
912 | if (prop && ((size / sizeof(u32)) > 1)) | ||
913 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; | 974 | cur_cpu_spec->cpu_features |= CPU_FTR_SMT; |
975 | else | ||
976 | cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; | ||
914 | #endif | 977 | #endif |
915 | 978 | ||
916 | return 0; | 979 | return 0; |
@@ -919,7 +982,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
919 | static int __init early_init_dt_scan_chosen(unsigned long node, | 982 | static int __init early_init_dt_scan_chosen(unsigned long node, |
920 | const char *uname, int depth, void *data) | 983 | const char *uname, int depth, void *data) |
921 | { | 984 | { |
922 | u32 *prop; | ||
923 | unsigned long *lprop; | 985 | unsigned long *lprop; |
924 | unsigned long l; | 986 | unsigned long l; |
925 | char *p; | 987 | char *p; |
@@ -930,14 +992,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
930 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) | 992 | (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) |
931 | return 0; | 993 | return 0; |
932 | 994 | ||
933 | /* get platform type */ | ||
934 | prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL); | ||
935 | if (prop == NULL) | ||
936 | return 0; | ||
937 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
938 | _machine = *prop; | ||
939 | #endif | ||
940 | |||
941 | #ifdef CONFIG_PPC64 | 995 | #ifdef CONFIG_PPC64 |
942 | /* check if iommu is forced on or off */ | 996 | /* check if iommu is forced on or off */ |
943 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 997 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
@@ -964,15 +1018,15 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
964 | * set of RTAS infos now if available | 1018 | * set of RTAS infos now if available |
965 | */ | 1019 | */ |
966 | { | 1020 | { |
967 | u64 *basep, *entryp; | 1021 | u64 *basep, *entryp, *sizep; |
968 | 1022 | ||
969 | basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); | 1023 | basep = of_get_flat_dt_prop(node, "linux,rtas-base", NULL); |
970 | entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); | 1024 | entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); |
971 | prop = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); | 1025 | sizep = of_get_flat_dt_prop(node, "linux,rtas-size", NULL); |
972 | if (basep && entryp && prop) { | 1026 | if (basep && entryp && sizep) { |
973 | rtas.base = *basep; | 1027 | rtas.base = *basep; |
974 | rtas.entry = *entryp; | 1028 | rtas.entry = *entryp; |
975 | rtas.size = *prop; | 1029 | rtas.size = *sizep; |
976 | } | 1030 | } |
977 | } | 1031 | } |
978 | #endif /* CONFIG_PPC_RTAS */ | 1032 | #endif /* CONFIG_PPC_RTAS */ |
@@ -1001,25 +1055,13 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1001 | 1055 | ||
1002 | if (strstr(cmd_line, "mem=")) { | 1056 | if (strstr(cmd_line, "mem=")) { |
1003 | char *p, *q; | 1057 | char *p, *q; |
1004 | unsigned long maxmem = 0; | ||
1005 | 1058 | ||
1006 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { | 1059 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { |
1007 | q = p + 4; | 1060 | q = p + 4; |
1008 | if (p > cmd_line && p[-1] != ' ') | 1061 | if (p > cmd_line && p[-1] != ' ') |
1009 | continue; | 1062 | continue; |
1010 | maxmem = simple_strtoul(q, &q, 0); | 1063 | memory_limit = memparse(q, &q); |
1011 | if (*q == 'k' || *q == 'K') { | ||
1012 | maxmem <<= 10; | ||
1013 | ++q; | ||
1014 | } else if (*q == 'm' || *q == 'M') { | ||
1015 | maxmem <<= 20; | ||
1016 | ++q; | ||
1017 | } else if (*q == 'g' || *q == 'G') { | ||
1018 | maxmem <<= 30; | ||
1019 | ++q; | ||
1020 | } | ||
1021 | } | 1064 | } |
1022 | memory_limit = maxmem; | ||
1023 | } | 1065 | } |
1024 | 1066 | ||
1025 | /* break now */ | 1067 | /* break now */ |
@@ -1755,7 +1797,7 @@ static int of_finish_dynamic_node(struct device_node *node) | |||
1755 | /* We don't support that function on PowerMac, at least | 1797 | /* We don't support that function on PowerMac, at least |
1756 | * not yet | 1798 | * not yet |
1757 | */ | 1799 | */ |
1758 | if (_machine == PLATFORM_POWERMAC) | 1800 | if (machine_is(powermac)) |
1759 | return -ENODEV; | 1801 | return -ENODEV; |
1760 | 1802 | ||
1761 | /* fix up new node's linux_phandle field */ | 1803 | /* fix up new node's linux_phandle field */ |