diff options
Diffstat (limited to 'arch/powerpc/platforms/iseries/setup.c')
-rw-r--r-- | arch/powerpc/platforms/iseries/setup.c | 271 |
1 files changed, 3 insertions, 268 deletions
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index a6fd9bedb074..617c724c4590 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <asm/iseries/hv_call_xm.h> | 50 | #include <asm/iseries/hv_call_xm.h> |
51 | #include <asm/iseries/it_lp_queue.h> | 51 | #include <asm/iseries/it_lp_queue.h> |
52 | #include <asm/iseries/mf.h> | 52 | #include <asm/iseries/mf.h> |
53 | #include <asm/iseries/it_exp_vpd_panel.h> | ||
54 | #include <asm/iseries/hv_lp_event.h> | 53 | #include <asm/iseries/hv_lp_event.h> |
55 | #include <asm/iseries/lpar_map.h> | 54 | #include <asm/iseries/lpar_map.h> |
56 | #include <asm/udbg.h> | 55 | #include <asm/udbg.h> |
@@ -81,9 +80,6 @@ extern void iSeries_pci_final_fixup(void); | |||
81 | static void iSeries_pci_final_fixup(void) { } | 80 | static void iSeries_pci_final_fixup(void) { } |
82 | #endif | 81 | #endif |
83 | 82 | ||
84 | /* Global Variables */ | ||
85 | int piranha_simulator; | ||
86 | |||
87 | extern int rd_size; /* Defined in drivers/block/rd.c */ | 83 | extern int rd_size; /* Defined in drivers/block/rd.c */ |
88 | extern unsigned long embedded_sysmap_start; | 84 | extern unsigned long embedded_sysmap_start; |
89 | extern unsigned long embedded_sysmap_end; | 85 | extern unsigned long embedded_sysmap_end; |
@@ -91,8 +87,6 @@ extern unsigned long embedded_sysmap_end; | |||
91 | extern unsigned long iSeries_recal_tb; | 87 | extern unsigned long iSeries_recal_tb; |
92 | extern unsigned long iSeries_recal_titan; | 88 | extern unsigned long iSeries_recal_titan; |
93 | 89 | ||
94 | static unsigned long cmd_mem_limit; | ||
95 | |||
96 | struct MemoryBlock { | 90 | struct MemoryBlock { |
97 | unsigned long absStart; | 91 | unsigned long absStart; |
98 | unsigned long absEnd; | 92 | unsigned long absEnd; |
@@ -340,8 +334,6 @@ static void __init iSeries_init_early(void) | |||
340 | #ifdef CONFIG_SMP | 334 | #ifdef CONFIG_SMP |
341 | smp_init_iSeries(); | 335 | smp_init_iSeries(); |
342 | #endif | 336 | #endif |
343 | if (itLpNaca.xPirEnvironMode == 0) | ||
344 | piranha_simulator = 1; | ||
345 | 337 | ||
346 | /* Associate Lp Event Queue 0 with processor 0 */ | 338 | /* Associate Lp Event Queue 0 with processor 0 */ |
347 | HvCallEvent_setLpEventQueueInterruptProc(0, 0); | 339 | HvCallEvent_setLpEventQueueInterruptProc(0, 0); |
@@ -536,10 +528,10 @@ static void __init iSeries_setup_arch(void) | |||
536 | { | 528 | { |
537 | if (get_lppaca()->shared_proc) { | 529 | if (get_lppaca()->shared_proc) { |
538 | ppc_md.idle_loop = iseries_shared_idle; | 530 | ppc_md.idle_loop = iseries_shared_idle; |
539 | printk(KERN_INFO "Using shared processor idle loop\n"); | 531 | printk(KERN_DEBUG "Using shared processor idle loop\n"); |
540 | } else { | 532 | } else { |
541 | ppc_md.idle_loop = iseries_dedicated_idle; | 533 | ppc_md.idle_loop = iseries_dedicated_idle; |
542 | printk(KERN_INFO "Using dedicated idle loop\n"); | 534 | printk(KERN_DEBUG "Using dedicated idle loop\n"); |
543 | } | 535 | } |
544 | 536 | ||
545 | /* Setup the Lp Event Queue */ | 537 | /* Setup the Lp Event Queue */ |
@@ -714,243 +706,6 @@ define_machine(iseries) { | |||
714 | /* XXX Implement enable_pmcs for iSeries */ | 706 | /* XXX Implement enable_pmcs for iSeries */ |
715 | }; | 707 | }; |
716 | 708 | ||
717 | struct blob { | ||
718 | unsigned char data[PAGE_SIZE]; | ||
719 | unsigned long next; | ||
720 | }; | ||
721 | |||
722 | struct iseries_flat_dt { | ||
723 | struct boot_param_header header; | ||
724 | u64 reserve_map[2]; | ||
725 | struct blob dt; | ||
726 | struct blob strings; | ||
727 | }; | ||
728 | |||
729 | struct iseries_flat_dt iseries_dt; | ||
730 | |||
731 | void dt_init(struct iseries_flat_dt *dt) | ||
732 | { | ||
733 | dt->header.off_mem_rsvmap = | ||
734 | offsetof(struct iseries_flat_dt, reserve_map); | ||
735 | dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt); | ||
736 | dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings); | ||
737 | dt->header.totalsize = sizeof(struct iseries_flat_dt); | ||
738 | dt->header.dt_strings_size = sizeof(struct blob); | ||
739 | |||
740 | /* There is no notion of hardware cpu id on iSeries */ | ||
741 | dt->header.boot_cpuid_phys = smp_processor_id(); | ||
742 | |||
743 | dt->dt.next = (unsigned long)&dt->dt.data; | ||
744 | dt->strings.next = (unsigned long)&dt->strings.data; | ||
745 | |||
746 | dt->header.magic = OF_DT_HEADER; | ||
747 | dt->header.version = 0x10; | ||
748 | dt->header.last_comp_version = 0x10; | ||
749 | |||
750 | dt->reserve_map[0] = 0; | ||
751 | dt->reserve_map[1] = 0; | ||
752 | } | ||
753 | |||
754 | void dt_check_blob(struct blob *b) | ||
755 | { | ||
756 | if (b->next >= (unsigned long)&b->next) { | ||
757 | DBG("Ran out of space in flat device tree blob!\n"); | ||
758 | BUG(); | ||
759 | } | ||
760 | } | ||
761 | |||
762 | void dt_push_u32(struct iseries_flat_dt *dt, u32 value) | ||
763 | { | ||
764 | *((u32*)dt->dt.next) = value; | ||
765 | dt->dt.next += sizeof(u32); | ||
766 | |||
767 | dt_check_blob(&dt->dt); | ||
768 | } | ||
769 | |||
770 | void dt_push_u64(struct iseries_flat_dt *dt, u64 value) | ||
771 | { | ||
772 | *((u64*)dt->dt.next) = value; | ||
773 | dt->dt.next += sizeof(u64); | ||
774 | |||
775 | dt_check_blob(&dt->dt); | ||
776 | } | ||
777 | |||
778 | unsigned long dt_push_bytes(struct blob *blob, char *data, int len) | ||
779 | { | ||
780 | unsigned long start = blob->next - (unsigned long)blob->data; | ||
781 | |||
782 | memcpy((char *)blob->next, data, len); | ||
783 | blob->next = _ALIGN(blob->next + len, 4); | ||
784 | |||
785 | dt_check_blob(blob); | ||
786 | |||
787 | return start; | ||
788 | } | ||
789 | |||
790 | void dt_start_node(struct iseries_flat_dt *dt, char *name) | ||
791 | { | ||
792 | dt_push_u32(dt, OF_DT_BEGIN_NODE); | ||
793 | dt_push_bytes(&dt->dt, name, strlen(name) + 1); | ||
794 | } | ||
795 | |||
796 | #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) | ||
797 | |||
798 | void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) | ||
799 | { | ||
800 | unsigned long offset; | ||
801 | |||
802 | dt_push_u32(dt, OF_DT_PROP); | ||
803 | |||
804 | /* Length of the data */ | ||
805 | dt_push_u32(dt, len); | ||
806 | |||
807 | /* Put the property name in the string blob. */ | ||
808 | offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1); | ||
809 | |||
810 | /* The offset of the properties name in the string blob. */ | ||
811 | dt_push_u32(dt, (u32)offset); | ||
812 | |||
813 | /* The actual data. */ | ||
814 | dt_push_bytes(&dt->dt, data, len); | ||
815 | } | ||
816 | |||
817 | void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) | ||
818 | { | ||
819 | dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ | ||
820 | } | ||
821 | |||
822 | void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) | ||
823 | { | ||
824 | dt_prop(dt, name, (char *)&data, sizeof(u32)); | ||
825 | } | ||
826 | |||
827 | void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) | ||
828 | { | ||
829 | dt_prop(dt, name, (char *)&data, sizeof(u64)); | ||
830 | } | ||
831 | |||
832 | void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) | ||
833 | { | ||
834 | dt_prop(dt, name, (char *)data, sizeof(u64) * n); | ||
835 | } | ||
836 | |||
837 | void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) | ||
838 | { | ||
839 | dt_prop(dt, name, (char *)data, sizeof(u32) * n); | ||
840 | } | ||
841 | |||
842 | void dt_prop_empty(struct iseries_flat_dt *dt, char *name) | ||
843 | { | ||
844 | dt_prop(dt, name, NULL, 0); | ||
845 | } | ||
846 | |||
847 | void dt_cpus(struct iseries_flat_dt *dt) | ||
848 | { | ||
849 | unsigned char buf[32]; | ||
850 | unsigned char *p; | ||
851 | unsigned int i, index; | ||
852 | struct IoHriProcessorVpd *d; | ||
853 | u32 pft_size[2]; | ||
854 | |||
855 | /* yuck */ | ||
856 | snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name); | ||
857 | p = strchr(buf, ' '); | ||
858 | if (!p) p = buf + strlen(buf); | ||
859 | |||
860 | dt_start_node(dt, "cpus"); | ||
861 | dt_prop_u32(dt, "#address-cells", 1); | ||
862 | dt_prop_u32(dt, "#size-cells", 0); | ||
863 | |||
864 | pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA */ | ||
865 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); | ||
866 | |||
867 | for (i = 0; i < NR_CPUS; i++) { | ||
868 | if (lppaca[i].dyn_proc_status >= 2) | ||
869 | continue; | ||
870 | |||
871 | snprintf(p, 32 - (p - buf), "@%d", i); | ||
872 | dt_start_node(dt, buf); | ||
873 | |||
874 | dt_prop_str(dt, "device_type", "cpu"); | ||
875 | |||
876 | index = lppaca[i].dyn_hv_phys_proc_index; | ||
877 | d = &xIoHriProcessorVpd[index]; | ||
878 | |||
879 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); | ||
880 | dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize); | ||
881 | |||
882 | dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024); | ||
883 | dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize); | ||
884 | |||
885 | /* magic conversions to Hz copied from old code */ | ||
886 | dt_prop_u32(dt, "clock-frequency", | ||
887 | ((1UL << 34) * 1000000) / d->xProcFreq); | ||
888 | dt_prop_u32(dt, "timebase-frequency", | ||
889 | ((1UL << 32) * 1000000) / d->xTimeBaseFreq); | ||
890 | |||
891 | dt_prop_u32(dt, "reg", i); | ||
892 | |||
893 | dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2); | ||
894 | |||
895 | dt_end_node(dt); | ||
896 | } | ||
897 | |||
898 | dt_end_node(dt); | ||
899 | } | ||
900 | |||
901 | void dt_model(struct iseries_flat_dt *dt) | ||
902 | { | ||
903 | char buf[16] = "IBM,"; | ||
904 | |||
905 | /* "IBM," + mfgId[2:3] + systemSerial[1:5] */ | ||
906 | strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2); | ||
907 | strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5); | ||
908 | buf[11] = '\0'; | ||
909 | dt_prop_str(dt, "system-id", buf); | ||
910 | |||
911 | /* "IBM," + machineType[0:4] */ | ||
912 | strne2a(buf + 4, xItExtVpdPanel.machineType, 4); | ||
913 | buf[8] = '\0'; | ||
914 | dt_prop_str(dt, "model", buf); | ||
915 | |||
916 | dt_prop_str(dt, "compatible", "IBM,iSeries"); | ||
917 | } | ||
918 | |||
919 | void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) | ||
920 | { | ||
921 | u64 tmp[2]; | ||
922 | |||
923 | dt_init(dt); | ||
924 | |||
925 | dt_start_node(dt, ""); | ||
926 | |||
927 | dt_prop_u32(dt, "#address-cells", 2); | ||
928 | dt_prop_u32(dt, "#size-cells", 2); | ||
929 | dt_model(dt); | ||
930 | |||
931 | /* /memory */ | ||
932 | dt_start_node(dt, "memory@0"); | ||
933 | dt_prop_str(dt, "name", "memory"); | ||
934 | dt_prop_str(dt, "device_type", "memory"); | ||
935 | tmp[0] = 0; | ||
936 | tmp[1] = phys_mem_size; | ||
937 | dt_prop_u64_list(dt, "reg", tmp, 2); | ||
938 | dt_end_node(dt); | ||
939 | |||
940 | /* /chosen */ | ||
941 | dt_start_node(dt, "chosen"); | ||
942 | dt_prop_str(dt, "bootargs", cmd_line); | ||
943 | if (cmd_mem_limit) | ||
944 | dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit); | ||
945 | dt_end_node(dt); | ||
946 | |||
947 | dt_cpus(dt); | ||
948 | |||
949 | dt_end_node(dt); | ||
950 | |||
951 | dt_push_u32(dt, OF_DT_END); | ||
952 | } | ||
953 | |||
954 | void * __init iSeries_early_setup(void) | 709 | void * __init iSeries_early_setup(void) |
955 | { | 710 | { |
956 | unsigned long phys_mem_size; | 711 | unsigned long phys_mem_size; |
@@ -965,28 +720,8 @@ void * __init iSeries_early_setup(void) | |||
965 | 720 | ||
966 | iSeries_get_cmdline(); | 721 | iSeries_get_cmdline(); |
967 | 722 | ||
968 | /* Save unparsed command line copy for /proc/cmdline */ | 723 | return (void *) __pa(build_flat_dt(phys_mem_size)); |
969 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | ||
970 | |||
971 | /* Parse early parameters, in particular mem=x */ | ||
972 | parse_early_param(); | ||
973 | |||
974 | build_flat_dt(&iseries_dt, phys_mem_size); | ||
975 | |||
976 | return (void *) __pa(&iseries_dt); | ||
977 | } | ||
978 | |||
979 | /* | ||
980 | * On iSeries we just parse the mem=X option from the command line. | ||
981 | * On pSeries it's a bit more complicated, see prom_init_mem() | ||
982 | */ | ||
983 | static int __init early_parsemem(char *p) | ||
984 | { | ||
985 | if (p) | ||
986 | cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE); | ||
987 | return 0; | ||
988 | } | 724 | } |
989 | early_param("mem", early_parsemem); | ||
990 | 725 | ||
991 | static void hvputc(char c) | 726 | static void hvputc(char c) |
992 | { | 727 | { |