aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/iSeries_setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/iSeries_setup.c')
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c460
1 files changed, 245 insertions, 215 deletions
diff --git a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
index 3ffefbbc6623..9daf734adbd5 100644
--- a/arch/ppc64/kernel/iSeries_setup.c
+++ b/arch/ppc64/kernel/iSeries_setup.c
@@ -74,8 +74,8 @@ extern void hvlog(char *fmt, ...);
74extern void ppcdbg_initialize(void); 74extern void ppcdbg_initialize(void);
75 75
76static void build_iSeries_Memory_Map(void); 76static void build_iSeries_Memory_Map(void);
77static void setup_iSeries_cache_sizes(void); 77static int iseries_shared_idle(void);
78static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); 78static int iseries_dedicated_idle(void);
79#ifdef CONFIG_PCI 79#ifdef CONFIG_PCI
80extern void iSeries_pci_final_fixup(void); 80extern void iSeries_pci_final_fixup(void);
81#else 81#else
@@ -83,14 +83,6 @@ static void iSeries_pci_final_fixup(void) { }
83#endif 83#endif
84 84
85/* Global Variables */ 85/* Global Variables */
86static unsigned long procFreqHz;
87static unsigned long procFreqMhz;
88static unsigned long procFreqMhzHundreths;
89
90static unsigned long tbFreqHz;
91static unsigned long tbFreqMhz;
92static unsigned long tbFreqMhzHundreths;
93
94int piranha_simulator; 86int piranha_simulator;
95 87
96extern int rd_size; /* Defined in drivers/block/rd.c */ 88extern int rd_size; /* Defined in drivers/block/rd.c */
@@ -319,6 +311,8 @@ static void __init iSeries_init_early(void)
319 311
320 ppcdbg_initialize(); 312 ppcdbg_initialize();
321 313
314 ppc64_interrupt_controller = IC_ISERIES;
315
322#if defined(CONFIG_BLK_DEV_INITRD) 316#if defined(CONFIG_BLK_DEV_INITRD)
323 /* 317 /*
324 * If the init RAM disk has been configured and there is 318 * If the init RAM disk has been configured and there is
@@ -341,12 +335,6 @@ static void __init iSeries_init_early(void)
341 iSeries_recal_titan = HvCallXm_loadTod(); 335 iSeries_recal_titan = HvCallXm_loadTod();
342 336
343 /* 337 /*
344 * Cache sizes must be initialized before hpte_init_iSeries is called
345 * as the later need them for flush_icache_range()
346 */
347 setup_iSeries_cache_sizes();
348
349 /*
350 * Initialize the hash table management pointers 338 * Initialize the hash table management pointers
351 */ 339 */
352 hpte_init_iSeries(); 340 hpte_init_iSeries();
@@ -356,12 +344,6 @@ static void __init iSeries_init_early(void)
356 */ 344 */
357 iommu_init_early_iSeries(); 345 iommu_init_early_iSeries();
358 346
359 /*
360 * Initialize the table which translate Linux physical addresses to
361 * AS/400 absolute addresses
362 */
363 build_iSeries_Memory_Map();
364
365 iSeries_get_cmdline(); 347 iSeries_get_cmdline();
366 348
367 /* Save unparsed command line copy for /proc/cmdline */ 349 /* Save unparsed command line copy for /proc/cmdline */
@@ -379,14 +361,6 @@ static void __init iSeries_init_early(void)
379 } 361 }
380 } 362 }
381 363
382 /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
383 iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
384
385 lmb_init();
386 lmb_add(0, systemcfg->physicalMemorySize);
387 lmb_analyze();
388 lmb_reserve(0, __pa(klimit));
389
390 /* Initialize machine-dependency vectors */ 364 /* Initialize machine-dependency vectors */
391#ifdef CONFIG_SMP 365#ifdef CONFIG_SMP
392 smp_init_iSeries(); 366 smp_init_iSeries();
@@ -592,139 +566,28 @@ static void __init build_iSeries_Memory_Map(void)
592} 566}
593 567
594/* 568/*
595 * Set up the variables that describe the cache line sizes
596 * for this machine.
597 */
598static void __init setup_iSeries_cache_sizes(void)
599{
600 unsigned int i, n;
601 unsigned int procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
602
603 systemcfg->icache_size =
604 ppc64_caches.isize = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024;
605 systemcfg->icache_line_size =
606 ppc64_caches.iline_size =
607 xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
608 systemcfg->dcache_size =
609 ppc64_caches.dsize =
610 xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024;
611 systemcfg->dcache_line_size =
612 ppc64_caches.dline_size =
613 xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
614 ppc64_caches.ilines_per_page = PAGE_SIZE / ppc64_caches.iline_size;
615 ppc64_caches.dlines_per_page = PAGE_SIZE / ppc64_caches.dline_size;
616
617 i = ppc64_caches.iline_size;
618 n = 0;
619 while ((i = (i / 2)))
620 ++n;
621 ppc64_caches.log_iline_size = n;
622
623 i = ppc64_caches.dline_size;
624 n = 0;
625 while ((i = (i / 2)))
626 ++n;
627 ppc64_caches.log_dline_size = n;
628
629 printk("D-cache line size = %d\n",
630 (unsigned int)ppc64_caches.dline_size);
631 printk("I-cache line size = %d\n",
632 (unsigned int)ppc64_caches.iline_size);
633}
634
635/*
636 * Create a pte. Used during initialization only.
637 */
638static void iSeries_make_pte(unsigned long va, unsigned long pa,
639 int mode)
640{
641 hpte_t local_hpte, rhpte;
642 unsigned long hash, vpn;
643 long slot;
644
645 vpn = va >> PAGE_SHIFT;
646 hash = hpt_hash(vpn, 0);
647
648 local_hpte.r = pa | mode;
649 local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
650 | HPTE_V_BOLTED | HPTE_V_VALID;
651
652 slot = HvCallHpt_findValid(&rhpte, vpn);
653 if (slot < 0) {
654 /* Must find space in primary group */
655 panic("hash_page: hpte already exists\n");
656 }
657 HvCallHpt_addValidate(slot, 0, &local_hpte);
658}
659
660/*
661 * Bolt the kernel addr space into the HPT
662 */
663static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
664{
665 unsigned long pa;
666 unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
667 hpte_t hpte;
668
669 for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
670 unsigned long ea = (unsigned long)__va(pa);
671 unsigned long vsid = get_kernel_vsid(ea);
672 unsigned long va = (vsid << 28) | (pa & 0xfffffff);
673 unsigned long vpn = va >> PAGE_SHIFT;
674 unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
675
676 /* Make non-kernel text non-executable */
677 if (!in_kernel_text(ea))
678 mode_rw |= HW_NO_EXEC;
679
680 if (hpte.v & HPTE_V_VALID) {
681 /* HPTE exists, so just bolt it */
682 HvCallHpt_setSwBits(slot, 0x10, 0);
683 /* And make sure the pp bits are correct */
684 HvCallHpt_setPp(slot, PP_RWXX);
685 } else
686 /* No HPTE exists, so create a new bolted one */
687 iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
688 }
689}
690
691/*
692 * Document me. 569 * Document me.
693 */ 570 */
694static void __init iSeries_setup_arch(void) 571static void __init iSeries_setup_arch(void)
695{ 572{
696 unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index; 573 unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
697 574
698 /* Add an eye catcher and the systemcfg layout version number */ 575 if (get_paca()->lppaca.shared_proc) {
699 strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64"); 576 ppc_md.idle_loop = iseries_shared_idle;
700 systemcfg->version.major = SYSTEMCFG_MAJOR; 577 printk(KERN_INFO "Using shared processor idle loop\n");
701 systemcfg->version.minor = SYSTEMCFG_MINOR; 578 } else {
579 ppc_md.idle_loop = iseries_dedicated_idle;
580 printk(KERN_INFO "Using dedicated idle loop\n");
581 }
702 582
703 /* Setup the Lp Event Queue */ 583 /* Setup the Lp Event Queue */
704 setup_hvlpevent_queue(); 584 setup_hvlpevent_queue();
705 585
706 /* Compute processor frequency */
707 procFreqHz = ((1UL << 34) * 1000000) /
708 xIoHriProcessorVpd[procIx].xProcFreq;
709 procFreqMhz = procFreqHz / 1000000;
710 procFreqMhzHundreths = (procFreqHz / 10000) - (procFreqMhz * 100);
711 ppc_proc_freq = procFreqHz;
712
713 /* Compute time base frequency */
714 tbFreqHz = ((1UL << 32) * 1000000) /
715 xIoHriProcessorVpd[procIx].xTimeBaseFreq;
716 tbFreqMhz = tbFreqHz / 1000000;
717 tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100);
718 ppc_tb_freq = tbFreqHz;
719
720 printk("Max logical processors = %d\n", 586 printk("Max logical processors = %d\n",
721 itVpdAreas.xSlicMaxLogicalProcs); 587 itVpdAreas.xSlicMaxLogicalProcs);
722 printk("Max physical processors = %d\n", 588 printk("Max physical processors = %d\n",
723 itVpdAreas.xSlicMaxPhysicalProcs); 589 itVpdAreas.xSlicMaxPhysicalProcs);
724 printk("Processor frequency = %lu.%02lu\n", procFreqMhz, 590
725 procFreqMhzHundreths);
726 printk("Time base frequency = %lu.%02lu\n", tbFreqMhz,
727 tbFreqMhzHundreths);
728 systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR; 591 systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
729 printk("Processor version = %x\n", systemcfg->processor); 592 printk("Processor version = %x\n", systemcfg->processor);
730} 593}
@@ -768,49 +631,6 @@ static void iSeries_halt(void)
768 mf_power_off(); 631 mf_power_off();
769} 632}
770 633
771/*
772 * void __init iSeries_calibrate_decr()
773 *
774 * Description:
775 * This routine retrieves the internal processor frequency from the VPD,
776 * and sets up the kernel timer decrementer based on that value.
777 *
778 */
779static void __init iSeries_calibrate_decr(void)
780{
781 unsigned long cyclesPerUsec;
782 struct div_result divres;
783
784 /* Compute decrementer (and TB) frequency in cycles/sec */
785 cyclesPerUsec = ppc_tb_freq / 1000000;
786
787 /*
788 * Set the amount to refresh the decrementer by. This
789 * is the number of decrementer ticks it takes for
790 * 1/HZ seconds.
791 */
792 tb_ticks_per_jiffy = ppc_tb_freq / HZ;
793
794#if 0
795 /* TEST CODE FOR ADJTIME */
796 tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
797 /* END OF TEST CODE */
798#endif
799
800 /*
801 * tb_ticks_per_sec = freq; would give better accuracy
802 * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
803 * that jiffies (and xtime) will match the time returned
804 * by do_gettimeofday.
805 */
806 tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
807 tb_ticks_per_usec = cyclesPerUsec;
808 tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
809 div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres);
810 tb_to_xs = divres.result_low;
811 setup_default_decr();
812}
813
814static void __init iSeries_progress(char * st, unsigned short code) 634static void __init iSeries_progress(char * st, unsigned short code)
815{ 635{
816 printk("Progress: [%04x] - %s\n", (unsigned)code, st); 636 printk("Progress: [%04x] - %s\n", (unsigned)code, st);
@@ -942,36 +762,246 @@ static int iseries_dedicated_idle(void)
942void __init iSeries_init_IRQ(void) { } 762void __init iSeries_init_IRQ(void) { }
943#endif 763#endif
944 764
945void __init iSeries_early_setup(void) 765static int __init iseries_probe(int platform)
946{ 766{
947 iSeries_fixup_klimit(); 767 return PLATFORM_ISERIES_LPAR == platform;
768}
948 769
949 ppc_md.setup_arch = iSeries_setup_arch; 770struct machdep_calls __initdata iseries_md = {
950 ppc_md.get_cpuinfo = iSeries_get_cpuinfo; 771 .setup_arch = iSeries_setup_arch,
951 ppc_md.init_IRQ = iSeries_init_IRQ; 772 .get_cpuinfo = iSeries_get_cpuinfo,
952 ppc_md.get_irq = iSeries_get_irq; 773 .init_IRQ = iSeries_init_IRQ,
953 ppc_md.init_early = iSeries_init_early, 774 .get_irq = iSeries_get_irq,
775 .init_early = iSeries_init_early,
776 .pcibios_fixup = iSeries_pci_final_fixup,
777 .restart = iSeries_restart,
778 .power_off = iSeries_power_off,
779 .halt = iSeries_halt,
780 .get_boot_time = iSeries_get_boot_time,
781 .set_rtc_time = iSeries_set_rtc_time,
782 .get_rtc_time = iSeries_get_rtc_time,
783 .calibrate_decr = generic_calibrate_decr,
784 .progress = iSeries_progress,
785 .probe = iseries_probe,
786 /* XXX Implement enable_pmcs for iSeries */
787};
954 788
955 ppc_md.pcibios_fixup = iSeries_pci_final_fixup; 789struct blob {
790 unsigned char data[PAGE_SIZE];
791 unsigned long next;
792};
956 793
957 ppc_md.restart = iSeries_restart; 794struct iseries_flat_dt {
958 ppc_md.power_off = iSeries_power_off; 795 struct boot_param_header header;
959 ppc_md.halt = iSeries_halt; 796 u64 reserve_map[2];
797 struct blob dt;
798 struct blob strings;
799};
960 800
961 ppc_md.get_boot_time = iSeries_get_boot_time; 801struct iseries_flat_dt iseries_dt;
962 ppc_md.set_rtc_time = iSeries_set_rtc_time;
963 ppc_md.get_rtc_time = iSeries_get_rtc_time;
964 ppc_md.calibrate_decr = iSeries_calibrate_decr;
965 ppc_md.progress = iSeries_progress;
966 802
967 /* XXX Implement enable_pmcs for iSeries */ 803void dt_init(struct iseries_flat_dt *dt)
804{
805 dt->header.off_mem_rsvmap =
806 offsetof(struct iseries_flat_dt, reserve_map);
807 dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
808 dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
809 dt->header.totalsize = sizeof(struct iseries_flat_dt);
810 dt->header.dt_strings_size = sizeof(struct blob);
968 811
969 if (get_paca()->lppaca.shared_proc) { 812 /* There is no notion of hardware cpu id on iSeries */
970 ppc_md.idle_loop = iseries_shared_idle; 813 dt->header.boot_cpuid_phys = smp_processor_id();
971 printk(KERN_INFO "Using shared processor idle loop\n"); 814
972 } else { 815 dt->dt.next = (unsigned long)&dt->dt.data;
973 ppc_md.idle_loop = iseries_dedicated_idle; 816 dt->strings.next = (unsigned long)&dt->strings.data;
974 printk(KERN_INFO "Using dedicated idle loop\n"); 817
818 dt->header.magic = OF_DT_HEADER;
819 dt->header.version = 0x10;
820 dt->header.last_comp_version = 0x10;
821
822 dt->reserve_map[0] = 0;
823 dt->reserve_map[1] = 0;
824}
825
826void dt_check_blob(struct blob *b)
827{
828 if (b->next >= (unsigned long)&b->next) {
829 DBG("Ran out of space in flat device tree blob!\n");
830 BUG();
975 } 831 }
976} 832}
977 833
834void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
835{
836 *((u32*)dt->dt.next) = value;
837 dt->dt.next += sizeof(u32);
838
839 dt_check_blob(&dt->dt);
840}
841
842void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
843{
844 *((u64*)dt->dt.next) = value;
845 dt->dt.next += sizeof(u64);
846
847 dt_check_blob(&dt->dt);
848}
849
850unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
851{
852 unsigned long start = blob->next - (unsigned long)blob->data;
853
854 memcpy((char *)blob->next, data, len);
855 blob->next = _ALIGN(blob->next + len, 4);
856
857 dt_check_blob(blob);
858
859 return start;
860}
861
862void dt_start_node(struct iseries_flat_dt *dt, char *name)
863{
864 dt_push_u32(dt, OF_DT_BEGIN_NODE);
865 dt_push_bytes(&dt->dt, name, strlen(name) + 1);
866}
867
868#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
869
870void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
871{
872 unsigned long offset;
873
874 dt_push_u32(dt, OF_DT_PROP);
875
876 /* Length of the data */
877 dt_push_u32(dt, len);
878
879 /* Put the property name in the string blob. */
880 offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
881
882 /* The offset of the properties name in the string blob. */
883 dt_push_u32(dt, (u32)offset);
884
885 /* The actual data. */
886 dt_push_bytes(&dt->dt, data, len);
887}
888
889void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
890{
891 dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
892}
893
894void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
895{
896 dt_prop(dt, name, (char *)&data, sizeof(u32));
897}
898
899void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
900{
901 dt_prop(dt, name, (char *)&data, sizeof(u64));
902}
903
904void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
905{
906 dt_prop(dt, name, (char *)data, sizeof(u64) * n);
907}
908
909void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
910{
911 dt_prop(dt, name, NULL, 0);
912}
913
914void dt_cpus(struct iseries_flat_dt *dt)
915{
916 unsigned char buf[32];
917 unsigned char *p;
918 unsigned int i, index;
919 struct IoHriProcessorVpd *d;
920
921 /* yuck */
922 snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
923 p = strchr(buf, ' ');
924 if (!p) p = buf + strlen(buf);
925
926 dt_start_node(dt, "cpus");
927 dt_prop_u32(dt, "#address-cells", 1);
928 dt_prop_u32(dt, "#size-cells", 0);
929
930 for (i = 0; i < NR_CPUS; i++) {
931 if (paca[i].lppaca.dyn_proc_status >= 2)
932 continue;
933
934 snprintf(p, 32 - (p - buf), "@%d", i);
935 dt_start_node(dt, buf);
936
937 dt_prop_str(dt, "device_type", "cpu");
938
939 index = paca[i].lppaca.dyn_hv_phys_proc_index;
940 d = &xIoHriProcessorVpd[index];
941
942 dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
943 dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
944
945 dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
946 dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
947
948 /* magic conversions to Hz copied from old code */
949 dt_prop_u32(dt, "clock-frequency",
950 ((1UL << 34) * 1000000) / d->xProcFreq);
951 dt_prop_u32(dt, "timebase-frequency",
952 ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
953
954 dt_prop_u32(dt, "reg", i);
955
956 dt_end_node(dt);
957 }
958
959 dt_end_node(dt);
960}
961
962void build_flat_dt(struct iseries_flat_dt *dt)
963{
964 u64 tmp[2];
965
966 dt_init(dt);
967
968 dt_start_node(dt, "");
969
970 dt_prop_u32(dt, "#address-cells", 2);
971 dt_prop_u32(dt, "#size-cells", 2);
972
973 /* /memory */
974 dt_start_node(dt, "memory@0");
975 dt_prop_str(dt, "name", "memory");
976 dt_prop_str(dt, "device_type", "memory");
977 tmp[0] = 0;
978 tmp[1] = systemcfg->physicalMemorySize;
979 dt_prop_u64_list(dt, "reg", tmp, 2);
980 dt_end_node(dt);
981
982 /* /chosen */
983 dt_start_node(dt, "chosen");
984 dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
985 dt_end_node(dt);
986
987 dt_cpus(dt);
988
989 dt_end_node(dt);
990
991 dt_push_u32(dt, OF_DT_END);
992}
993
994void * __init iSeries_early_setup(void)
995{
996 iSeries_fixup_klimit();
997
998 /*
999 * Initialize the table which translate Linux physical addresses to
1000 * AS/400 absolute addresses
1001 */
1002 build_iSeries_Memory_Map();
1003
1004 build_flat_dt(&iseries_dt);
1005
1006 return (void *) __pa(&iseries_dt);
1007}