Merge refs/heads/devtree from rsync://oak/kernels/iseries/work/.git
authorPaul Mackerras <paulus@samba.org>
Mon, 26 Sep 2005 06:20:49 +0000 (16:20 +1000)
committerPaul Mackerras <paulus@samba.org>
Mon, 26 Sep 2005 06:20:49 +0000 (16:20 +1000)
12 files changed:
arch/ppc64/Kconfig
arch/ppc64/kernel/Makefile
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iSeries_htab.c
arch/ppc64/kernel/iSeries_irq.c
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/kernel/iSeries_smp.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/time.c
arch/ppc64/mm/hash_utils.c
include/asm-ppc64/mmu.h
include/asm-ppc64/processor.h

index 32951bfc7f659a8f3a76f70cc4620b9401d19d92..246212115a48fcdfcf5e24c84eddf0d324e4b915 100644 (file)
@@ -357,7 +357,6 @@ config HOTPLUG_CPU
 
 config PROC_DEVICETREE
        bool "Support for Open Firmware device tree in /proc"
-       depends on !PPC_ISERIES
        help
          This option adds a device-tree directory under /proc which contains
          an image of the device tree that the kernel copies from Open
index 813718df4f8245caeb3cf1c971b403bcc57b9412..afadb6e4a6dc9df43293de31a7b9ff6f33452b75 100644 (file)
@@ -11,7 +11,7 @@ obj-y               :=        setup.o entry.o traps.o irq.o idle.o dma.o \
                        udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
                        ptrace32.o signal32.o rtc.o init_task.o \
                        lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
-                       iommu.o sysfs.o vdso.o pmc.o firmware.o
+                       iommu.o sysfs.o vdso.o pmc.o firmware.o prom.o
 obj-y += vdso32/ vdso64/
 
 obj-$(CONFIG_PPC_OF) +=        of_device.o
@@ -27,7 +27,7 @@ obj-$(CONFIG_PPC_ISERIES) += HvCall.o HvLpConfig.o LparData.o \
                             mf.o HvLpEvent.o iSeries_proc.o iSeries_htab.o \
                             iSeries_iommu.o
 
-obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o prom.o
+obj-$(CONFIG_PPC_MULTIPLATFORM) += nvram.o i8259.o prom_init.o
 
 obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \
                             pSeries_nvram.o rtasd.o ras.o pSeries_reconfig.o \
index 22a5ee07e1ea00a7a90a0f33d0604c6cd7ae1335..eb526c480b6c1724ff1e1915da8e7ec4b1161286 100644 (file)
@@ -1364,6 +1364,7 @@ _STATIC(__start_initialization_iSeries)
        addi    r2,r2,0x4000
 
        bl      .iSeries_early_setup
+       bl      .early_setup
 
        /* relocation is on at this point */
 
@@ -1970,20 +1971,22 @@ _GLOBAL(hmt_start_secondary)
        blr
 #endif
 
-#if defined(CONFIG_KEXEC) || (defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES))
+#if defined(CONFIG_KEXEC) || defined(CONFIG_SMP)
 _GLOBAL(smp_release_cpus)
        /* All secondary cpus are spinning on a common
         * spinloop, release them all now so they can start
         * to spin on their individual paca spinloops.
         * For non SMP kernels, the secondary cpus never
         * get out of the common spinloop.
+        * XXX This does nothing useful on iSeries, secondaries are
+        * already waiting on their paca.
         */
        li      r3,1
        LOADADDR(r5,__secondary_hold_spinloop)
        std     r3,0(r5)
        sync
        blr
-#endif /* CONFIG_SMP && !CONFIG_PPC_ISERIES */
+#endif /* CONFIG_SMP */
 
 
 /*
index 2192055a90a07ba3f34f074e70cb75225d124fdb..9a2be3abf3494191853ab848fe70f6095e617338 100644 (file)
@@ -84,6 +84,25 @@ static long iSeries_hpte_insert(unsigned long hpte_group, unsigned long va,
        return (secondary << 3) | (slot & 7);
 }
 
+long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
+               unsigned long va, unsigned long prpn, unsigned long vflags,
+               unsigned long rflags)
+{
+       long slot;
+       hpte_t lhpte;
+
+       slot = HvCallHpt_findValid(&lhpte, va >> PAGE_SHIFT);
+
+       if (lhpte.v & HPTE_V_VALID) {
+               /* Bolt the existing HPTE */
+               HvCallHpt_setSwBits(slot, 0x10, 0);
+               HvCallHpt_setPp(slot, PP_RWXX);
+               return 0;
+       }
+
+       return iSeries_hpte_insert(hpte_group, va, prpn, vflags, rflags);
+}
+
 static unsigned long iSeries_hpte_getword0(unsigned long slot)
 {
        hpte_t hpte;
index 77376c1bd611326c44bfcd71e3681f9d1508b197..0170682a8ca595b736b3878de96d92efac2781cd 100644 (file)
@@ -351,3 +351,16 @@ int __init iSeries_allocate_IRQ(HvBusNumber busNumber,
        irq_desc[virtirq].handler = &iSeries_IRQ_handler;
        return virtirq;
 }
+
+int virt_irq_create_mapping(unsigned int real_irq)
+{
+       BUG(); /* Don't call this on iSeries, yet */
+
+       return 0;
+}
+
+void virt_irq_init(void)
+{
+       return;
+}
+
index 3ffefbbc6623a9e27e262691f5cb877bad32feb2..9daf734adbd555bd05f9aeacacd8eead78b20b7d 100644 (file)
@@ -74,8 +74,8 @@ extern void hvlog(char *fmt, ...);
 extern void ppcdbg_initialize(void);
 
 static void build_iSeries_Memory_Map(void);
-static void setup_iSeries_cache_sizes(void);
-static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr);
+static int iseries_shared_idle(void);
+static int iseries_dedicated_idle(void);
 #ifdef CONFIG_PCI
 extern void iSeries_pci_final_fixup(void);
 #else
@@ -83,14 +83,6 @@ static void iSeries_pci_final_fixup(void) { }
 #endif
 
 /* Global Variables */
-static unsigned long procFreqHz;
-static unsigned long procFreqMhz;
-static unsigned long procFreqMhzHundreths;
-
-static unsigned long tbFreqHz;
-static unsigned long tbFreqMhz;
-static unsigned long tbFreqMhzHundreths;
-
 int piranha_simulator;
 
 extern int rd_size;            /* Defined in drivers/block/rd.c */
@@ -319,6 +311,8 @@ static void __init iSeries_init_early(void)
 
        ppcdbg_initialize();
 
+       ppc64_interrupt_controller = IC_ISERIES;
+
 #if defined(CONFIG_BLK_DEV_INITRD)
        /*
         * If the init RAM disk has been configured and there is
@@ -340,12 +334,6 @@ static void __init iSeries_init_early(void)
        iSeries_recal_tb = get_tb();
        iSeries_recal_titan = HvCallXm_loadTod();
 
-       /*
-        * Cache sizes must be initialized before hpte_init_iSeries is called
-        * as the later need them for flush_icache_range()
-        */
-       setup_iSeries_cache_sizes();
-
        /*
         * Initialize the hash table management pointers
         */
@@ -356,12 +344,6 @@ static void __init iSeries_init_early(void)
         */
        iommu_init_early_iSeries();
 
-       /*
-        * Initialize the table which translate Linux physical addresses to
-        * AS/400 absolute addresses
-        */
-       build_iSeries_Memory_Map();
-
        iSeries_get_cmdline();
 
        /* Save unparsed command line copy for /proc/cmdline */
@@ -379,14 +361,6 @@ static void __init iSeries_init_early(void)
                }
        }
 
-       /* Bolt kernel mappings for all of memory (or just a bit if we've got a limit) */
-       iSeries_bolt_kernel(0, systemcfg->physicalMemorySize);
-
-       lmb_init();
-       lmb_add(0, systemcfg->physicalMemorySize);
-       lmb_analyze();
-       lmb_reserve(0, __pa(klimit));
-
        /* Initialize machine-dependency vectors */
 #ifdef CONFIG_SMP
        smp_init_iSeries();
@@ -591,103 +565,6 @@ static void __init build_iSeries_Memory_Map(void)
        systemcfg->physicalMemorySize = chunk_to_addr(nextPhysChunk);
 }
 
-/*
- * Set up the variables that describe the cache line sizes
- * for this machine.
- */
-static void __init setup_iSeries_cache_sizes(void)
-{
-       unsigned int i, n;
-       unsigned int procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
-
-       systemcfg->icache_size =
-       ppc64_caches.isize = xIoHriProcessorVpd[procIx].xInstCacheSize * 1024;
-       systemcfg->icache_line_size =
-       ppc64_caches.iline_size =
-               xIoHriProcessorVpd[procIx].xInstCacheOperandSize;
-       systemcfg->dcache_size =
-       ppc64_caches.dsize =
-               xIoHriProcessorVpd[procIx].xDataL1CacheSizeKB * 1024;
-       systemcfg->dcache_line_size =
-       ppc64_caches.dline_size =
-               xIoHriProcessorVpd[procIx].xDataCacheOperandSize;
-       ppc64_caches.ilines_per_page = PAGE_SIZE / ppc64_caches.iline_size;
-       ppc64_caches.dlines_per_page = PAGE_SIZE / ppc64_caches.dline_size;
-
-       i = ppc64_caches.iline_size;
-       n = 0;
-       while ((i = (i / 2)))
-               ++n;
-       ppc64_caches.log_iline_size = n;
-
-       i = ppc64_caches.dline_size;
-       n = 0;
-       while ((i = (i / 2)))
-               ++n;
-       ppc64_caches.log_dline_size = n;
-
-       printk("D-cache line size = %d\n",
-                       (unsigned int)ppc64_caches.dline_size);
-       printk("I-cache line size = %d\n",
-                       (unsigned int)ppc64_caches.iline_size);
-}
-
-/*
- * Create a pte. Used during initialization only.
- */
-static void iSeries_make_pte(unsigned long va, unsigned long pa,
-                            int mode)
-{
-       hpte_t local_hpte, rhpte;
-       unsigned long hash, vpn;
-       long slot;
-
-       vpn = va >> PAGE_SHIFT;
-       hash = hpt_hash(vpn, 0);
-
-       local_hpte.r = pa | mode;
-       local_hpte.v = ((va >> 23) << HPTE_V_AVPN_SHIFT)
-               | HPTE_V_BOLTED | HPTE_V_VALID;
-
-       slot = HvCallHpt_findValid(&rhpte, vpn);
-       if (slot < 0) {
-               /* Must find space in primary group */
-               panic("hash_page: hpte already exists\n");
-       }
-       HvCallHpt_addValidate(slot, 0, &local_hpte);
-}
-
-/*
- * Bolt the kernel addr space into the HPT
- */
-static void __init iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr)
-{
-       unsigned long pa;
-       unsigned long mode_rw = _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX;
-       hpte_t hpte;
-
-       for (pa = saddr; pa < eaddr ;pa += PAGE_SIZE) {
-               unsigned long ea = (unsigned long)__va(pa);
-               unsigned long vsid = get_kernel_vsid(ea);
-               unsigned long va = (vsid << 28) | (pa & 0xfffffff);
-               unsigned long vpn = va >> PAGE_SHIFT;
-               unsigned long slot = HvCallHpt_findValid(&hpte, vpn);
-
-               /* Make non-kernel text non-executable */
-               if (!in_kernel_text(ea))
-                       mode_rw |= HW_NO_EXEC;
-
-               if (hpte.v & HPTE_V_VALID) {
-                       /* HPTE exists, so just bolt it */
-                       HvCallHpt_setSwBits(slot, 0x10, 0);
-                       /* And make sure the pp bits are correct */
-                       HvCallHpt_setPp(slot, PP_RWXX);
-               } else
-                       /* No HPTE exists, so create a new bolted one */
-                       iSeries_make_pte(va, phys_to_abs(pa), mode_rw);
-       }
-}
-
 /*
  * Document me.
  */
@@ -695,36 +572,22 @@ static void __init iSeries_setup_arch(void)
 {
        unsigned procIx = get_paca()->lppaca.dyn_hv_phys_proc_index;
 
-       /* Add an eye catcher and the systemcfg layout version number */
-       strcpy(systemcfg->eye_catcher, "SYSTEMCFG:PPC64");
-       systemcfg->version.major = SYSTEMCFG_MAJOR;
-       systemcfg->version.minor = SYSTEMCFG_MINOR;
+       if (get_paca()->lppaca.shared_proc) {
+               ppc_md.idle_loop = iseries_shared_idle;
+               printk(KERN_INFO "Using shared processor idle loop\n");
+       } else {
+               ppc_md.idle_loop = iseries_dedicated_idle;
+               printk(KERN_INFO "Using dedicated idle loop\n");
+       }
 
        /* Setup the Lp Event Queue */
        setup_hvlpevent_queue();
 
-       /* Compute processor frequency */
-       procFreqHz = ((1UL << 34) * 1000000) /
-                       xIoHriProcessorVpd[procIx].xProcFreq;
-       procFreqMhz = procFreqHz / 1000000;
-       procFreqMhzHundreths = (procFreqHz / 10000) - (procFreqMhz * 100);
-       ppc_proc_freq = procFreqHz;
-
-       /* Compute time base frequency */
-       tbFreqHz = ((1UL << 32) * 1000000) /
-               xIoHriProcessorVpd[procIx].xTimeBaseFreq;
-       tbFreqMhz = tbFreqHz / 1000000;
-       tbFreqMhzHundreths = (tbFreqHz / 10000) - (tbFreqMhz * 100);
-       ppc_tb_freq = tbFreqHz;
-
        printk("Max  logical processors = %d\n",
                        itVpdAreas.xSlicMaxLogicalProcs);
        printk("Max physical processors = %d\n",
                        itVpdAreas.xSlicMaxPhysicalProcs);
-       printk("Processor frequency = %lu.%02lu\n", procFreqMhz,
-                       procFreqMhzHundreths);
-       printk("Time base frequency = %lu.%02lu\n", tbFreqMhz,
-                       tbFreqMhzHundreths);
+
        systemcfg->processor = xIoHriProcessorVpd[procIx].xPVR;
        printk("Processor version = %x\n", systemcfg->processor);
 }
@@ -768,49 +631,6 @@ static void iSeries_halt(void)
        mf_power_off();
 }
 
-/*
- * void __init iSeries_calibrate_decr()
- *
- * Description:
- *   This routine retrieves the internal processor frequency from the VPD,
- *   and sets up the kernel timer decrementer based on that value.
- *
- */
-static void __init iSeries_calibrate_decr(void)
-{
-       unsigned long   cyclesPerUsec;
-       struct div_result divres;
-
-       /* Compute decrementer (and TB) frequency in cycles/sec */
-       cyclesPerUsec = ppc_tb_freq / 1000000;
-
-       /*
-        * Set the amount to refresh the decrementer by.  This
-        * is the number of decrementer ticks it takes for
-        * 1/HZ seconds.
-        */
-       tb_ticks_per_jiffy = ppc_tb_freq / HZ;
-
-#if 0
-       /* TEST CODE FOR ADJTIME */
-       tb_ticks_per_jiffy += tb_ticks_per_jiffy / 5000;
-       /* END OF TEST CODE */
-#endif
-
-       /*
-        * tb_ticks_per_sec = freq; would give better accuracy
-        * but tb_ticks_per_sec = tb_ticks_per_jiffy*HZ; assures
-        * that jiffies (and xtime) will match the time returned
-        * by do_gettimeofday.
-        */
-       tb_ticks_per_sec = tb_ticks_per_jiffy * HZ;
-       tb_ticks_per_usec = cyclesPerUsec;
-       tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000);
-       div128_by_32(1024 * 1024, 0, tb_ticks_per_sec, &divres);
-       tb_to_xs = divres.result_low;
-       setup_default_decr();
-}
-
 static void __init iSeries_progress(char * st, unsigned short code)
 {
        printk("Progress: [%04x] - %s\n", (unsigned)code, st);
@@ -942,36 +762,246 @@ static int iseries_dedicated_idle(void)
 void __init iSeries_init_IRQ(void) { }
 #endif
 
-void __init iSeries_early_setup(void)
+static int __init iseries_probe(int platform)
 {
-       iSeries_fixup_klimit();
+       return PLATFORM_ISERIES_LPAR == platform;
+}
 
-       ppc_md.setup_arch = iSeries_setup_arch;
-       ppc_md.get_cpuinfo = iSeries_get_cpuinfo;
-       ppc_md.init_IRQ = iSeries_init_IRQ;
-       ppc_md.get_irq = iSeries_get_irq;
-       ppc_md.init_early = iSeries_init_early,
+struct machdep_calls __initdata iseries_md = {
+       .setup_arch     = iSeries_setup_arch,
+       .get_cpuinfo    = iSeries_get_cpuinfo,
+       .init_IRQ       = iSeries_init_IRQ,
+       .get_irq        = iSeries_get_irq,
+       .init_early     = iSeries_init_early,
+       .pcibios_fixup  = iSeries_pci_final_fixup,
+       .restart        = iSeries_restart,
+       .power_off      = iSeries_power_off,
+       .halt           = iSeries_halt,
+       .get_boot_time  = iSeries_get_boot_time,
+       .set_rtc_time   = iSeries_set_rtc_time,
+       .get_rtc_time   = iSeries_get_rtc_time,
+       .calibrate_decr = generic_calibrate_decr,
+       .progress       = iSeries_progress,
+       .probe          = iseries_probe,
+       /* XXX Implement enable_pmcs for iSeries */
+};
 
-       ppc_md.pcibios_fixup  = iSeries_pci_final_fixup;
+struct blob {
+       unsigned char data[PAGE_SIZE];
+       unsigned long next;
+};
 
-       ppc_md.restart = iSeries_restart;
-       ppc_md.power_off = iSeries_power_off;
-       ppc_md.halt = iSeries_halt;
+struct iseries_flat_dt {
+       struct boot_param_header header;
+       u64 reserve_map[2];
+       struct blob dt;
+       struct blob strings;
+};
 
-       ppc_md.get_boot_time = iSeries_get_boot_time;
-       ppc_md.set_rtc_time = iSeries_set_rtc_time;
-       ppc_md.get_rtc_time = iSeries_get_rtc_time;
-       ppc_md.calibrate_decr = iSeries_calibrate_decr;
-       ppc_md.progress = iSeries_progress;
+struct iseries_flat_dt iseries_dt;
 
-       /* XXX Implement enable_pmcs for iSeries */
+void dt_init(struct iseries_flat_dt *dt)
+{
+       dt->header.off_mem_rsvmap =
+               offsetof(struct iseries_flat_dt, reserve_map);
+       dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
+       dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
+       dt->header.totalsize = sizeof(struct iseries_flat_dt);
+       dt->header.dt_strings_size = sizeof(struct blob);
 
-       if (get_paca()->lppaca.shared_proc) {
-               ppc_md.idle_loop = iseries_shared_idle;
-               printk(KERN_INFO "Using shared processor idle loop\n");
-       } else {
-               ppc_md.idle_loop = iseries_dedicated_idle;
-               printk(KERN_INFO "Using dedicated idle loop\n");
+       /* There is no notion of hardware cpu id on iSeries */
+       dt->header.boot_cpuid_phys = smp_processor_id();
+
+       dt->dt.next = (unsigned long)&dt->dt.data;
+       dt->strings.next = (unsigned long)&dt->strings.data;
+
+       dt->header.magic = OF_DT_HEADER;
+       dt->header.version = 0x10;
+       dt->header.last_comp_version = 0x10;
+
+       dt->reserve_map[0] = 0;
+       dt->reserve_map[1] = 0;
+}
+
+void dt_check_blob(struct blob *b)
+{
+       if (b->next >= (unsigned long)&b->next) {
+               DBG("Ran out of space in flat device tree blob!\n");
+               BUG();
        }
 }
 
+void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+       *((u32*)dt->dt.next) = value;
+       dt->dt.next += sizeof(u32);
+
+       dt_check_blob(&dt->dt);
+}
+
+void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+       *((u64*)dt->dt.next) = value;
+       dt->dt.next += sizeof(u64);
+
+       dt_check_blob(&dt->dt);
+}
+
+unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
+{
+       unsigned long start = blob->next - (unsigned long)blob->data;
+
+       memcpy((char *)blob->next, data, len);
+       blob->next = _ALIGN(blob->next + len, 4);
+
+       dt_check_blob(blob);
+
+       return start;
+}
+
+void dt_start_node(struct iseries_flat_dt *dt, char *name)
+{
+       dt_push_u32(dt, OF_DT_BEGIN_NODE);
+       dt_push_bytes(&dt->dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
+{
+       unsigned long offset;
+
+       dt_push_u32(dt, OF_DT_PROP);
+
+       /* Length of the data */
+       dt_push_u32(dt, len);
+
+       /* Put the property name in the string blob. */
+       offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
+
+       /* The offset of the properties name in the string blob. */
+       dt_push_u32(dt, (u32)offset);
+
+       /* The actual data. */
+       dt_push_bytes(&dt->dt, data, len);
+}
+
+void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
+{
+       dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+{
+       dt_prop(dt, name, (char *)&data, sizeof(u32));
+}
+
+void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+{
+       dt_prop(dt, name, (char *)&data, sizeof(u64));
+}
+
+void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
+{
+       dt_prop(dt, name, (char *)data, sizeof(u64) * n);
+}
+
+void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+{
+       dt_prop(dt, name, NULL, 0);
+}
+
+void dt_cpus(struct iseries_flat_dt *dt)
+{
+       unsigned char buf[32];
+       unsigned char *p;
+       unsigned int i, index;
+       struct IoHriProcessorVpd *d;
+
+       /* yuck */
+       snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+       p = strchr(buf, ' ');
+       if (!p) p = buf + strlen(buf);
+
+       dt_start_node(dt, "cpus");
+       dt_prop_u32(dt, "#address-cells", 1);
+       dt_prop_u32(dt, "#size-cells", 0);
+
+       for (i = 0; i < NR_CPUS; i++) {
+               if (paca[i].lppaca.dyn_proc_status >= 2)
+                       continue;
+
+               snprintf(p, 32 - (p - buf), "@%d", i);
+               dt_start_node(dt, buf);
+
+               dt_prop_str(dt, "device_type", "cpu");
+
+               index = paca[i].lppaca.dyn_hv_phys_proc_index;
+               d = &xIoHriProcessorVpd[index];
+
+               dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+               dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+               dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+               dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+               /* magic conversions to Hz copied from old code */
+               dt_prop_u32(dt, "clock-frequency",
+                       ((1UL << 34) * 1000000) / d->xProcFreq);
+               dt_prop_u32(dt, "timebase-frequency",
+                       ((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+               dt_prop_u32(dt, "reg", i);
+
+               dt_end_node(dt);
+       }
+
+       dt_end_node(dt);
+}
+
+void build_flat_dt(struct iseries_flat_dt *dt)
+{
+       u64 tmp[2];
+
+       dt_init(dt);
+
+       dt_start_node(dt, "");
+
+       dt_prop_u32(dt, "#address-cells", 2);
+       dt_prop_u32(dt, "#size-cells", 2);
+
+       /* /memory */
+       dt_start_node(dt, "memory@0");
+       dt_prop_str(dt, "name", "memory");
+       dt_prop_str(dt, "device_type", "memory");
+       tmp[0] = 0;
+       tmp[1] = systemcfg->physicalMemorySize;
+       dt_prop_u64_list(dt, "reg", tmp, 2);
+       dt_end_node(dt);
+
+       /* /chosen */
+       dt_start_node(dt, "chosen");
+       dt_prop_u32(dt, "linux,platform", PLATFORM_ISERIES_LPAR);
+       dt_end_node(dt);
+
+       dt_cpus(dt);
+
+       dt_end_node(dt);
+
+       dt_push_u32(dt, OF_DT_END);
+}
+
+void * __init iSeries_early_setup(void)
+{
+       iSeries_fixup_klimit();
+
+       /*
+        * Initialize the table which translate Linux physical addresses to
+        * AS/400 absolute addresses
+        */
+       build_iSeries_Memory_Map();
+
+       build_flat_dt(&iseries_dt);
+
+       return (void *) __pa(&iseries_dt);
+}
index f74386e31638d38185755bcf9cb3ae6d8b2f725c..f982e5b805f49eb9eb2b293cbcfbfd032798da1b 100644 (file)
@@ -82,35 +82,9 @@ static void smp_iSeries_message_pass(int target, int msg)
        }
 }
 
-static int smp_iSeries_numProcs(void)
-{
-       unsigned np, i;
-
-       np = 0;
-        for (i=0; i < NR_CPUS; ++i) {
-                if (paca[i].lppaca.dyn_proc_status < 2) {
-                       cpu_set(i, cpu_possible_map);
-                       cpu_set(i, cpu_present_map);
-                       cpu_set(i, cpu_sibling_map[i]);
-                        ++np;
-                }
-        }
-       return np;
-}
-
 static int smp_iSeries_probe(void)
 {
-       unsigned i;
-       unsigned np = 0;
-
-       for (i=0; i < NR_CPUS; ++i) {
-               if (paca[i].lppaca.dyn_proc_status < 2) {
-                       /*paca[i].active = 1;*/
-                       ++np;
-               }
-       }
-
-       return np;
+       return cpus_weight(cpu_possible_map);
 }
 
 static void smp_iSeries_kick_cpu(int nr)
@@ -144,6 +118,4 @@ static struct smp_ops_t iSeries_smp_ops = {
 void __init smp_init_iSeries(void)
 {
        smp_ops = &iSeries_smp_ops;
-       systemcfg->processorCount       = smp_iSeries_numProcs();
 }
-
index 5ac48bd64891f98e0846ef8f0959ccba01da682b..776b55b45e1b6cad54c77bb1b8d36fa287688b39 100644 (file)
@@ -58,6 +58,7 @@
 #include <asm/mmu.h>
 #include <asm/lmb.h>
 #include <asm/iSeries/ItLpNaca.h>
+#include <asm/firmware.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -153,7 +154,7 @@ struct screen_info screen_info = {
        .orig_video_points = 16
 };
 
-#if defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP)
+#ifdef CONFIG_SMP
 
 static int smt_enabled_cmdline;
 
@@ -306,15 +307,13 @@ static void __init setup_cpu_maps(void)
 
        systemcfg->processorCount = num_present_cpus();
 }
-#endif /* defined(CONFIG_PPC_MULTIPLATFORM) && defined(CONFIG_SMP) */
-
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
+#endif /* CONFIG_SMP */
 
 extern struct machdep_calls pSeries_md;
 extern struct machdep_calls pmac_md;
 extern struct machdep_calls maple_md;
 extern struct machdep_calls bpa_md;
+extern struct machdep_calls iseries_md;
 
 /* Ultimately, stuff them in an elf section like initcalls... */
 static struct machdep_calls __initdata *machines[] = {
@@ -329,6 +328,9 @@ static struct machdep_calls __initdata *machines[] = {
 #endif /* CONFIG_PPC_MAPLE */
 #ifdef CONFIG_PPC_BPA
        &bpa_md,
+#endif
+#ifdef CONFIG_PPC_ISERIES
+       &iseries_md,
 #endif
        NULL
 };
@@ -401,7 +403,8 @@ void __init early_setup(unsigned long dt_ptr)
        /*
         * Initialize stab / SLB management
         */
-       stab_initialize(lpaca->stab_real);
+       if (!firmware_has_feature(FW_FEATURE_ISERIES))
+               stab_initialize(lpaca->stab_real);
 
        /*
         * Initialize the MMU Hash table and create the linear mapping
@@ -532,8 +535,6 @@ static void __init check_for_initrd(void)
 #endif /* CONFIG_BLK_DEV_INITRD */
 }
 
-#endif /* CONFIG_PPC_MULTIPLATFORM */
-
 /*
  * Do some initial setup of the system.  The parameters are those which 
  * were passed in from the bootloader.
@@ -542,14 +543,6 @@ void __init setup_system(void)
 {
        DBG(" -> setup_system()\n");
 
-#ifdef CONFIG_PPC_ISERIES
-       /* pSeries systems are identified in prom.c via OF. */
-       if (itLpNaca.xLparInstalled == 1)
-               systemcfg->platform = PLATFORM_ISERIES_LPAR;
-
-       ppc_md.init_early();
-#else /* CONFIG_PPC_ISERIES */
-
        /*
         * Unflatten the device-tree passed by prom_init or kexec
         */
@@ -607,9 +600,8 @@ void __init setup_system(void)
        strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
 
        parse_early_param();
-#endif /* !CONFIG_PPC_ISERIES */
 
-#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES)
+#ifdef CONFIG_SMP
        /*
         * iSeries has already initialized the cpu maps at this point.
         */
@@ -619,7 +611,7 @@ void __init setup_system(void)
         * we can map physical -> logical CPU ids
         */
        smp_release_cpus();
-#endif /* defined(CONFIG_SMP) && !defined(CONFIG_PPC_ISERIES) */
+#endif
 
        printk("Starting Linux PPC64 %s\n", system_utsname.version);
 
index fb4bf0ad8f3252d70f3e82777c54b446e4d3e9db..7f63755eddfd683bfb8ddba1393fcb2c376ae8fd 100644 (file)
@@ -465,7 +465,7 @@ int do_settimeofday(struct timespec *tv)
 
 EXPORT_SYMBOL(do_settimeofday);
 
-#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA)
+#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_MAPLE) || defined(CONFIG_PPC_BPA) || defined(CONFIG_PPC_ISERIES)
 void __init generic_calibrate_decr(void)
 {
        struct device_node *cpu;
index 36cf474b3d365f4dba63c93834683ba17f5e5c2a..83507438d6a0aa6a178d45c5e1a1e3881cc36442 100644 (file)
@@ -90,7 +90,6 @@ static inline void loop_forever(void)
                ;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
 static inline void create_pte_mapping(unsigned long start, unsigned long end,
                                      unsigned long mode, int large)
 {
@@ -111,7 +110,7 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
                unsigned long vpn, hash, hpteg;
                unsigned long vsid = get_kernel_vsid(addr);
                unsigned long va = (vsid << 28) | (addr & 0xfffffff);
-               int ret;
+               int ret = -1;
 
                if (large)
                        vpn = va >> HPAGE_SHIFT;
@@ -129,16 +128,25 @@ static inline void create_pte_mapping(unsigned long start, unsigned long end,
 
                hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
+#ifdef CONFIG_PPC_ISERIES
+               if (systemcfg->platform & PLATFORM_ISERIES_LPAR)
+                       ret = iSeries_hpte_bolt_or_insert(hpteg, va,
+                               virt_to_abs(addr) >> PAGE_SHIFT,
+                               vflags, tmp_mode);
+               else
+#endif
 #ifdef CONFIG_PPC_PSERIES
                if (systemcfg->platform & PLATFORM_LPAR)
                        ret = pSeries_lpar_hpte_insert(hpteg, va,
                                virt_to_abs(addr) >> PAGE_SHIFT,
                                vflags, tmp_mode);
                else
-#endif /* CONFIG_PPC_PSERIES */
+#endif
+#ifdef CONFIG_PPC_MULTIPLATFORM
                        ret = native_hpte_insert(hpteg, va,
                                virt_to_abs(addr) >> PAGE_SHIFT,
                                vflags, tmp_mode);
+#endif
 
                if (ret == -1) {
                        ppc64_terminate_msg(0x20, "create_pte_mapping");
@@ -261,7 +269,6 @@ void __init htab_initialize(void)
 }
 #undef KB
 #undef MB
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 /*
  * Called by asm hashtable.S for doing lazy icache flush
index d2b0b796d35e14376488a0ca4fc3bea51484ee2e..e0505acb77d9971dff1dc19ee3f364d09f193ec2 100644 (file)
@@ -206,6 +206,10 @@ extern long native_hpte_insert(unsigned long hpte_group, unsigned long va,
                               unsigned long prpn,
                               unsigned long vflags, unsigned long rflags);
 
+extern long iSeries_hpte_bolt_or_insert(unsigned long hpte_group,
+               unsigned long va, unsigned long prpn,
+               unsigned long vflags, unsigned long rflags);
+
 extern void stabs_alloc(void);
 
 #endif /* __ASSEMBLY__ */
index e5fc18531ec11ba2d12d5c76c68d0d56ea067f52..6447fbee7d69bf40d472bc2dc3e4a0e2649362d8 100644 (file)
 #define IC_OPEN_PIC   1
 #define IC_PPC_XIC    2
 #define IC_BPA_IIC    3
+#define IC_ISERIES    4
 
 #define XGLUE(a,b) a##b
 #define GLUE(a,b) XGLUE(a,b)