aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-09-26 02:20:49 -0400
committerPaul Mackerras <paulus@samba.org>2005-09-26 02:20:49 -0400
commit51a0885ed7f883758462926b35fbd6f09f9c717c (patch)
tree3789f94f7b599222bef32dc20dc2213b9cf9d948 /arch/ppc64
parent14cf11af6cf608eb8c23e989ddb17a715ddce109 (diff)
parent3d8a66cc9ec475baaf22de139deff67ffe8e7cf2 (diff)
Merge refs/heads/devtree from rsync://oak/kernels/iseries/work/.git
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/Kconfig1
-rw-r--r--arch/ppc64/kernel/Makefile4
-rw-r--r--arch/ppc64/kernel/head.S7
-rw-r--r--arch/ppc64/kernel/iSeries_htab.c19
-rw-r--r--arch/ppc64/kernel/iSeries_irq.c13
-rw-r--r--arch/ppc64/kernel/iSeries_setup.c460
-rw-r--r--arch/ppc64/kernel/iSeries_smp.c30
-rw-r--r--arch/ppc64/kernel/setup.c30
-rw-r--r--arch/ppc64/kernel/time.c2
-rw-r--r--arch/ppc64/mm/hash_utils.c15
10 files changed, 308 insertions, 273 deletions
diff --git a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
index 32951bfc7f65..246212115a48 100644
--- a/arch/ppc64/Kconfig
+++ b/arch/ppc64/Kconfig
@@ -357,7 +357,6 @@ config HOTPLUG_CPU
357 357
358config PROC_DEVICETREE 358config PROC_DEVICETREE
359 bool "Support for Open Firmware device tree in /proc" 359 bool "Support for Open Firmware device tree in /proc"
360 depends on !PPC_ISERIES
361 help 360 help
362 This option adds a device-tree directory under /proc which contains 361 This option adds a device-tree directory under /proc which contains
363 an image of the device tree that the kernel copies from Open 362 an image of the device tree that the kernel copies from Open
diff --git a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
index 813718df4f82..afadb6e4a6dc 100644
--- a/arch/ppc64/kernel/Makefile
+++ b/arch/ppc64/kernel/Makefile
@@ -11,7 +11,7 @@ obj-y := setup.o entry.o traps.o irq.o idle.o dma.o \
11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ 11 udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
12 ptrace32.o signal32.o rtc.o init_task.o \ 12 ptrace32.o signal32.o rtc.o init_task.o \
13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \ 13 lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
14 iommu.o sysfs.o vdso.o pmc.o firmware.o 14 iommu.o sysfs.o vdso.o pmc.o firmware.o prom.o
15obj-y += vdso32/ vdso64/ 15obj-y += vdso32/ vdso64/
16 16
17obj-$(CONFIG_PPC_OF) += of_device.o 17obj-$(CONFIG_PPC_OF) += of_device.o
@@ -27,7 +27,7 @@ obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
27 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \ 27 mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
28 iSeries_iommu.o 28 iSeries_iommu.o
29 29
30obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o 30obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o
31 31
32obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ 32obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
33 pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \ 33 pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
diff --git a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
index 22a5ee07e1ea..eb526c480b6c 100644
--- a/arch/ppc64/kernel/head.S
+++ b/arch/ppc64/kernel/head.S
@@ -1364,6 +1364,7 @@ _STATIC(__start_initialization_iSeries)
1364 addi r2,r2,0x4000 1364 addi r2,r2,0x4000
1365 1365
1366 bl .iSeries_early_setup 1366 bl .iSeries_early_setup
1367 bl .early_setup
1367 1368
1368 /* relocation is on at this point */ 1369 /* relocation is on at this point */
1369 1370
@@ -1970,20 +1971,22 @@ _GLOBAL(hmt_start_secondary)
1970 blr 1971 blr
1971#endif 1972#endif
1972 1973
1973#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)) 1974#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
1974_GLOBAL(smp_release_cpus) 1975_GLOBAL(smp_release_cpus)
1975 /* All secondary cpus are spinning on a common 1976 /* All secondary cpus are spinning on a common
1976 * spinloop, release them all now so they can start 1977 * spinloop, release them all now so they can start
1977 * to spin on their individual paca spinloops. 1978 * to spin on their individual paca spinloops.
1978 * For non SMP kernels, the secondary cpus never 1979 * For non SMP kernels, the secondary cpus never
1979 * get out of the common spinloop. 1980 * get out of the common spinloop.
1981 * XXX This does nothing useful on iSeries, secondaries are
1982 * already waiting on their paca.
1980 */ 1983 */
1981 li r3,1 1984 li r3,1
1982 LOADADDR(r5,__secondary_hold_spinloop) 1985 LOADADDR(r5,__secondary_hold_spinloop)
1983 std r3,0(r5) 1986 std r3,0(r5)
1984 sync 1987 sync
1985 blr 1988 blr
1986#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */ 1989#endif /* CONFIG_SMP */
1987 1990
1988 1991
1989/* 1992/*
diff --git a/arch/ppc64/kernel/iSeries_htab.c b/arch/ppc64/kernel/iSeries_htab.c
index 2192055a90a0..9a2be3abf349 100644
--- a/arch/ppc64/kernel/iSeries_htab.c
+++ b/arch/ppc64/kernel/iSeries_htab.c
@@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
84 return (secondary << 3) | (slot & 7); 84 return (secondary << 3) | (slot & 7);
85} 85}
86 86
87long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
88 unsigned long va, unsigned long prpn, unsigned long vflags,
89 unsigned long rflags)
90{
91 long slot;
92 hpte_t lhpte;
93
94 slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
95
96 if (lhpte.v & HPTE_V_VALID) {
97 /* Bolt the existing HPTE */
98 HvCallHpt_setSwBits(slot, 0x10, 0);
99 HvCallHpt_setPp(slot, PP_RWXX);
100 return 0;
101 }
102
103 return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
104}
105
87static unsigned long iSeries_hpte_getword0(unsigned long slot) 106static unsigned long iSeries_hpte_getword0(unsigned long slot)
88{ 107{
89 hpte_t hpte; 108 hpte_t hpte;
diff --git a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c
index 77376c1bd611..0170682a8ca5 100644
--- a/arch/ppc64/kernel/iSeries_irq.c
+++ b/arch/ppc64/kernel/iSeries_irq.c
@@ -351,3 +351,16 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
351 irq_desc[virtirq].handler = &iSeries_IRQ_handler; 351 irq_desc[virtirq].handler = &iSeries_IRQ_handler;
352 return virtirq; 352 return virtirq;
353} 353}
354
355int virt_irq_create_mapping(unsigned int real_irq)
356{
357 BUG(); /* Don't call this on iSeries, yet */
358
359 return 0;
360}
361
362void virt_irq_init(void)
363{
364 return;
365}
366
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}
diff --git a/arch/ppc64/kernel/iSeries_smp.c b/arch/ppc64/kernel/iSeries_smp.c
index f74386e31638..f982e5b805f4 100644
--- a/arch/ppc64/kernel/iSeries_smp.c
+++ b/arch/ppc64/kernel/iSeries_smp.c
@@ -82,35 +82,9 @@ static void smp_iSeries_message_pass(int target, int msg)
82 } 82 }
83} 83}
84 84
85static int smp_iSeries_numProcs(void)
86{
87 unsigned np, i;
88
89 np = 0;
90 for (i=0; i < NR_CPUS; ++i) {
91 if (paca[i].lppaca.dyn_proc_status < 2) {
92 cpu_set(i, cpu_possible_map);
93 cpu_set(i, cpu_present_map);
94 cpu_set(i, cpu_sibling_map[i]);
95 ++np;
96 }
97 }
98 return np;
99}
100
101static int smp_iSeries_probe(void) 85static int smp_iSeries_probe(void)
102{ 86{
103 unsigned i; 87 return cpus_weight(cpu_possible_map);
104 unsigned np = 0;
105
106 for (i=0; i < NR_CPUS; ++i) {
107 if (paca[i].lppaca.dyn_proc_status < 2) {
108 /*paca[i].active = 1;*/
109 ++np;
110 }
111 }
112
113 return np;
114} 88}
115 89
116static void smp_iSeries_kick_cpu(int nr) 90static void smp_iSeries_kick_cpu(int nr)
@@ -144,6 +118,4 @@ static struct smp_ops_t iSeries_smp_ops = {
144void __init smp_init_iSeries(void) 118void __init smp_init_iSeries(void)
145{ 119{
146 smp_ops = &iSeries_smp_ops; 120 smp_ops = &iSeries_smp_ops;
147 systemcfg->processorCount = smp_iSeries_numProcs();
148} 121}
149
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
index 5ac48bd64891..776b55b45e1b 100644
--- a/arch/ppc64/kernel/setup.c
+++ b/arch/ppc64/kernel/setup.c
@@ -58,6 +58,7 @@
58#include <asm/mmu.h> 58#include <asm/mmu.h>
59#include <asm/lmb.h> 59#include <asm/lmb.h>
60#include <asm/iSeries/ItLpNaca.h> 60#include <asm/iSeries/ItLpNaca.h>
61#include <asm/firmware.h>
61 62
62#ifdef DEBUG 63#ifdef DEBUG
63#define DBG(fmt...) udbg_printf(fmt) 64#define DBG(fmt...) udbg_printf(fmt)
@@ -153,7 +154,7 @@ struct screen_info screen_info = {
153 .orig_video_points = 16 154 .orig_video_points = 16
154}; 155};
155 156
156#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) 157#ifdef CONFIG_SMP
157 158
158static int smt_enabled_cmdline; 159static int smt_enabled_cmdline;
159 160
@@ -306,15 +307,13 @@ static void __init setup_cpu_maps(void)
306 307
307 systemcfg->processorCount = num_present_cpus(); 308 systemcfg->processorCount = num_present_cpus();
308} 309}
309#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */ 310#endif /* CONFIG_SMP */
310
311
312#ifdef CONFIG_PPC_MULTIPLATFORM
313 311
314extern struct machdep_calls pSeries_md; 312extern struct machdep_calls pSeries_md;
315extern struct machdep_calls pmac_md; 313extern struct machdep_calls pmac_md;
316extern struct machdep_calls maple_md; 314extern struct machdep_calls maple_md;
317extern struct machdep_calls bpa_md; 315extern struct machdep_calls bpa_md;
316extern struct machdep_calls iseries_md;
318 317
319/* Ultimately, stuff them in an elf section like initcalls... */ 318/* Ultimately, stuff them in an elf section like initcalls... */
320static struct machdep_calls __initdata *machines[] = { 319static struct machdep_calls __initdata *machines[] = {
@@ -330,6 +329,9 @@ static struct machdep_calls __initdata *machines[] = {
330#ifdef CONFIG_PPC_BPA 329#ifdef CONFIG_PPC_BPA
331 &bpa_md, 330 &bpa_md,
332#endif 331#endif
332#ifdef CONFIG_PPC_ISERIES
333 &iseries_md,
334#endif
333 NULL 335 NULL
334}; 336};
335 337
@@ -401,7 +403,8 @@ void __init early_setup(unsigned long dt_ptr)
401 /* 403 /*
402 * Initialize stab / SLB management 404 * Initialize stab / SLB management
403 */ 405 */
404 stab_initialize(lpaca->stab_real); 406 if (!firmware_has_feature(FW_FEATURE_ISERIES))
407 stab_initialize(lpaca->stab_real);
405 408
406 /* 409 /*
407 * Initialize the MMU Hash table and create the linear mapping 410 * Initialize the MMU Hash table and create the linear mapping
@@ -532,8 +535,6 @@ static void __init check_for_initrd(void)
532#endif /* CONFIG_BLK_DEV_INITRD */ 535#endif /* CONFIG_BLK_DEV_INITRD */
533} 536}
534 537
535#endif /* CONFIG_PPC_MULTIPLATFORM */
536
537/* 538/*
538 * Do some initial setup of the system. The parameters are those which 539 * Do some initial setup of the system. The parameters are those which
539 * were passed in from the bootloader. 540 * were passed in from the bootloader.
@@ -542,14 +543,6 @@ void __init setup_system(void)
542{ 543{
543 DBG(" -> setup_system()\n"); 544 DBG(" -> setup_system()\n");
544 545
545#ifdef CONFIG_PPC_ISERIES
546 /* pSeries systems are identified in prom.c via OF. */
547 if (itLpNaca.xLparInstalled == 1)
548 systemcfg->platform = PLATFORM_ISERIES_LPAR;
549
550 ppc_md.init_early();
551#else /* CONFIG_PPC_ISERIES */
552
553 /* 546 /*
554 * Unflatten the device-tree passed by prom_init or kexec 547 * Unflatten the device-tree passed by prom_init or kexec
555 */ 548 */
@@ -607,9 +600,8 @@ void __init setup_system(void)
607 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); 600 strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
608 601
609 parse_early_param(); 602 parse_early_param();
610#endif /* !CONFIG_PPC_ISERIES */
611 603
612#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) 604#ifdef CONFIG_SMP
613 /* 605 /*
614 * iSeries has already initialized the cpu maps at this point. 606 * iSeries has already initialized the cpu maps at this point.
615 */ 607 */
@@ -619,7 +611,7 @@ void __init setup_system(void)
619 * we can map physical -> logical CPU ids 611 * we can map physical -> logical CPU ids
620 */ 612 */
621 smp_release_cpus(); 613 smp_release_cpus();
622#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */ 614#endif
623 615
624 printk("Starting Linux PPC64 %s\n", system_utsname.version); 616 printk("Starting Linux PPC64 %s\n", system_utsname.version);
625 617
diff --git a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
index fb4bf0ad8f32..7f63755eddfd 100644
--- a/arch/ppc64/kernel/time.c
+++ b/arch/ppc64/kernel/time.c
@@ -465,7 +465,7 @@ int do_settimeofday(struct timespec *tv)
465 465
466EXPORT_SYMBOL(do_settimeofday); 466EXPORT_SYMBOL(do_settimeofday);
467 467
468#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA) 468#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA) || defined(CONFIG_PPC_ISERIES)
469void __init generic_calibrate_decr(void) 469void __init generic_calibrate_decr(void)
470{ 470{
471 struct device_node *cpu; 471 struct device_node *cpu;
diff --git a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
index 36cf474b3d36..83507438d6a0 100644
--- a/arch/ppc64/mm/hash_utils.c
+++ b/arch/ppc64/mm/hash_utils.c
@@ -90,7 +90,6 @@ static inline void loop_forever(void)
90 ; 90 ;
91} 91}
92 92
93#ifdef CONFIG_PPC_MULTIPLATFORM
94static inline void create_pte_mapping(unsigned long start, unsigned long end, 93static inline void create_pte_mapping(unsigned long start, unsigned long end,
95 unsigned long mode, int large) 94 unsigned long mode, int large)
96{ 95{
@@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
111 unsigned long vpn, hash, hpteg; 110 unsigned long vpn, hash, hpteg;
112 unsigned long vsid = get_kernel_vsid(addr); 111 unsigned long vsid = get_kernel_vsid(addr);
113 unsigned long va = (vsid << 28) | (addr & 0xfffffff); 112 unsigned long va = (vsid << 28) | (addr & 0xfffffff);
114 int ret; 113 int ret = -1;
115 114
116 if (large) 115 if (large)
117 vpn = va >> HPAGE_SHIFT; 116 vpn = va >> HPAGE_SHIFT;
@@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
129 128
130 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); 129 hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
131 130
131#ifdef CONFIG_PPC_ISERIES
132 if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
133 ret = iSeries_hpte_bolt_or_insert(hpteg, va,
134 virt_to_abs(addr) >> PAGE_SHIFT,
135 vflags, tmp_mode);
136 else
137#endif
132#ifdef CONFIG_PPC_PSERIES 138#ifdef CONFIG_PPC_PSERIES
133 if (systemcfg->platform & PLATFORM_LPAR) 139 if (systemcfg->platform & PLATFORM_LPAR)
134 ret = pSeries_lpar_hpte_insert(hpteg, va, 140 ret = pSeries_lpar_hpte_insert(hpteg, va,
135 virt_to_abs(addr) >> PAGE_SHIFT, 141 virt_to_abs(addr) >> PAGE_SHIFT,
136 vflags, tmp_mode); 142 vflags, tmp_mode);
137 else 143 else
138#endif /* CONFIG_PPC_PSERIES */ 144#endif
145#ifdef CONFIG_PPC_MULTIPLATFORM
139 ret = native_hpte_insert(hpteg, va, 146 ret = native_hpte_insert(hpteg, va,
140 virt_to_abs(addr) >> PAGE_SHIFT, 147 virt_to_abs(addr) >> PAGE_SHIFT,
141 vflags, tmp_mode); 148 vflags, tmp_mode);
149#endif
142 150
143 if (ret == -1) { 151 if (ret == -1) {
144 ppc64_terminate_msg(0x20, "create_pte_mapping"); 152 ppc64_terminate_msg(0x20, "create_pte_mapping");
@@ -261,7 +269,6 @@ void __init htab_initialize(void)
261} 269}
262#undef KB 270#undef KB
263#undef MB 271#undef MB
264#endif /* CONFIG_PPC_MULTIPLATFORM */
265 272
266/* 273/*
267 * Called by asm hashtable.S for doing lazy icache flush 274 * Called by asm hashtable.S for doing lazy icache flush