diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/83xx/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc834x_sys.c | 243 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc834x_sys.h | 23 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/mpc83xx.h | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/83xx/pci.c | 99 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/pci.c | 27 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/setup.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/chrp/time.c | 7 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/irq.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/misc.S | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/setup.c | 8 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/smp.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/pci.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/setup.c | 85 | ||||
-rw-r--r-- | arch/powerpc/platforms/maple/time.c | 23 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 100 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 20 |
18 files changed, 594 insertions, 79 deletions
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index b20812d460e6..7675e675dce1 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig @@ -7,6 +7,7 @@ choice config MPC834x_SYS bool "Freescale MPC834x SYS" + select DEFAULT_UIMAGE help This option enables support for the MPC 834x SYS evaluation board. diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.c b/arch/powerpc/platforms/83xx/mpc834x_sys.c new file mode 100644 index 000000000000..2098dd05a773 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.c @@ -0,0 +1,243 @@ +/* + * arch/powerpc/platforms/83xx/mpc834x_sys.c + * + * MPC834x SYS board specific routines + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/reboot.h> +#include <linux/pci.h> +#include <linux/kdev_t.h> +#include <linux/major.h> +#include <linux/console.h> +#include <linux/delay.h> +#include <linux/seq_file.h> +#include <linux/root_dev.h> +#include <linux/module.h> +#include <linux/fsl_devices.h> + +#include <asm/system.h> +#include <asm/pgtable.h> +#include <asm/page.h> +#include <asm/atomic.h> +#include <asm/time.h> +#include <asm/io.h> +#include <asm/machdep.h> +#include <asm/ipic.h> +#include <asm/bootinfo.h> +#include <asm/pci-bridge.h> +#include <asm/mpc83xx.h> +#include <asm/irq.h> +#include <mm/mmu_decl.h> +#include <asm/prom.h> +#include <asm/udbg.h> +#include <sysdev/fsl_soc.h> + +#include "mpc83xx.h" + +#ifndef CONFIG_PCI +unsigned long isa_io_base = 0; +unsigned long isa_mem_base = 0; +#endif + +#ifdef CONFIG_PCI +extern int mpc83xx_pci2_busno; + +static int +mpc83xx_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) +{ + static char pci_irq_table[][4] = + /* + * PCI IDSEL/INTPIN->INTLINE + * A B C D + */ + { + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x11 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x12 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x13 */ + {0, 0, 0, 0}, + {PIRQA, PIRQB, PIRQC, PIRQD}, /* idsel 0x15 */ + {PIRQD, PIRQA, PIRQB, PIRQC}, /* idsel 0x16 */ + {PIRQC, PIRQD, PIRQA, PIRQB}, /* idsel 0x17 */ + {PIRQB, PIRQC, PIRQD, PIRQA}, /* idsel 0x18 */ + {0, 0, 0, 0}, /* idsel 0x19 */ + {0, 0, 0, 0}, /* idsel 0x20 */ + }; + + const long min_idsel = 0x11, max_idsel = 0x20, irqs_per_slot = 4; + return PCI_IRQ_TABLE_LOOKUP; +} + +static int +mpc83xx_exclude_device(u_char bus, u_char devfn) +{ + if (bus == 0 && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + if (mpc83xx_pci2_busno) + if (bus == (mpc83xx_pci2_busno) && PCI_SLOT(devfn) == 0) + return PCIBIOS_DEVICE_NOT_FOUND; + return PCIBIOS_SUCCESSFUL; +} +#endif /* CONFIG_PCI */ + +/* ************************************************************************ + * + * Setup the architecture + * + */ +static void __init +mpc834x_sys_setup_arch(void) +{ + struct device_node *np; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_setup_arch()", 0); + + np = of_find_node_by_type(NULL, "cpu"); + if (np != 0) { + unsigned int *fp = (int *) get_property(np, "clock-frequency", NULL); + if (fp != 0) + loops_per_jiffy = *fp / HZ; + else + loops_per_jiffy = 50000000 / HZ; + of_node_put(np); + } + +#ifdef CONFIG_PCI + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) + add_bridge(np); + + ppc_md.pci_swizzle = common_swizzle; + ppc_md.pci_map_irq = mpc83xx_map_irq; + ppc_md.pci_exclude_device = mpc83xx_exclude_device; +#endif + +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif +} + +void __init +mpc834x_sys_init_IRQ(void) +{ + u8 senses[8] = { + 0, /* EXT 0 */ + IRQ_SENSE_LEVEL, /* EXT 1 */ + IRQ_SENSE_LEVEL, /* EXT 2 */ + 0, /* EXT 3 */ +#ifdef CONFIG_PCI + IRQ_SENSE_LEVEL, /* EXT 4 */ + IRQ_SENSE_LEVEL, /* EXT 5 */ + IRQ_SENSE_LEVEL, /* EXT 6 */ + IRQ_SENSE_LEVEL, /* EXT 7 */ +#else + 0, /* EXT 4 */ + 0, /* EXT 5 */ + 0, /* EXT 6 */ + 0, /* EXT 7 */ +#endif + }; + + ipic_init(get_immrbase() + 0x00700, 0, 0, senses, 8); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + ipic_set_default_priority(); +} + +#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374) +extern ulong ds1374_get_rtc_time(void); +extern int ds1374_set_rtc_time(ulong); + +static int __init +mpc834x_rtc_hookup(void) +{ + struct timespec tv; + + ppc_md.get_rtc_time = ds1374_get_rtc_time; + ppc_md.set_rtc_time = ds1374_set_rtc_time; + + tv.tv_nsec = 0; + tv.tv_sec = (ppc_md.get_rtc_time)(); + do_settimeofday(&tv); + + return 0; +} +late_initcall(mpc834x_rtc_hookup); +#endif + +static void +mpc83xx_restart(char *cmd) +{ +#define RST_OFFSET 0x00000900 +#define RST_PROT_REG 0x00000018 +#define RST_CTRL_REG 0x0000001c + __be32 __iomem *reg; + + // map reset register space + reg = ioremap(get_immrbase() + 0x900, 0xff); + + local_irq_disable(); + + /* enable software reset "RSTE" */ + out_be32(reg + (RST_PROT_REG >> 2), 0x52535445); + + /* set software hard reset */ + out_be32(reg + (RST_CTRL_REG >> 2), 0x52535445); + for(;;); +} + +static long __init +mpc83xx_time_init(void) +{ +#define SPCR_OFFSET 0x00000110 +#define SPCR_TBEN 0x00400000 + __be32 __iomem *spcr = ioremap(get_immrbase() + SPCR_OFFSET, 4); + __be32 tmp; + + tmp = in_be32(spcr); + out_be32(spcr, tmp|SPCR_TBEN); + + iounmap(spcr); + + return 0; +} +void __init +platform_init(void) +{ + /* setup the PowerPC module struct */ + ppc_md.setup_arch = mpc834x_sys_setup_arch; + + ppc_md.init_IRQ = mpc834x_sys_init_IRQ; + ppc_md.get_irq = ipic_get_irq; + + ppc_md.restart = mpc83xx_restart; + + ppc_md.time_init = mpc83xx_time_init; + ppc_md.set_rtc_time = NULL; + ppc_md.get_rtc_time = NULL; + ppc_md.calibrate_decr = generic_calibrate_decr; + + ppc_md.progress = udbg_progress; + + if (ppc_md.progress) + ppc_md.progress("mpc834x_sys_init(): exit", 0); + + return; +} + + diff --git a/arch/powerpc/platforms/83xx/mpc834x_sys.h b/arch/powerpc/platforms/83xx/mpc834x_sys.h new file mode 100644 index 000000000000..e4ca39f6a862 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc834x_sys.h @@ -0,0 +1,23 @@ +/* + * arch/powerppc/platforms/83xx/mpc834x_sys.h + * + * MPC834X SYS common board definitions + * + * Maintainer: Kumar Gala <galak@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#ifndef __MACH_MPC83XX_SYS_H__ +#define __MACH_MPC83XX_SYS_H__ + +#define PIRQA MPC83xx_IRQ_EXT4 +#define PIRQB MPC83xx_IRQ_EXT5 +#define PIRQC MPC83xx_IRQ_EXT6 +#define PIRQD MPC83xx_IRQ_EXT7 + +#endif /* __MACH_MPC83XX_SYS_H__ */ diff --git a/arch/powerpc/platforms/83xx/mpc83xx.h b/arch/powerpc/platforms/83xx/mpc83xx.h new file mode 100644 index 000000000000..ce9e66abef24 --- /dev/null +++ b/arch/powerpc/platforms/83xx/mpc83xx.h @@ -0,0 +1,14 @@ +#ifndef __MPC83XX_H__ +#define __MPC83XX_H__ + +#include <linux/init.h> +#include <linux/device.h> + +/* + * Declaration for the various functions exported by the + * mpc83xx_* files. Mostly for use by mpc83xx_setup + */ + +extern int add_bridge(struct device_node *dev); + +#endif /* __MPC83XX_H__ */ diff --git a/arch/powerpc/platforms/83xx/pci.c b/arch/powerpc/platforms/83xx/pci.c new file mode 100644 index 000000000000..469cdacc5bd4 --- /dev/null +++ b/arch/powerpc/platforms/83xx/pci.c @@ -0,0 +1,99 @@ +/* + * FSL SoC setup code + * + * Maintained by Kumar Gala (see MAINTAINERS for contact information) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/config.h> +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/errno.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/irq.h> +#include <linux/module.h> + +#include <asm/system.h> +#include <asm/atomic.h> +#include <asm/io.h> +#include <asm/pci-bridge.h> +#include <asm/prom.h> +#include <sysdev/fsl_soc.h> + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +int mpc83xx_pci2_busno; + +#ifdef CONFIG_PCI +int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + struct resource rsrc; + int *bus_range; + int primary = 1, has_address = 0; + phys_addr_t immr = get_immrbase(); + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + /* Fetch host bridge registers address */ + has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); + + /* Get bus range if any */ + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume" + " bus 0\n", dev->full_name); + } + + hose = pcibios_alloc_controller(); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->set_cfg_type = 1; + + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + /* MPC83xx supports up to two host controllers one at 0x8500 from immrbar + * the other at 0x8600, we consider the 0x8500 the primary controller + */ + /* PCI 1 */ + if ((rsrc.start & 0xfffff) == 0x8500) { + setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304); + } + /* PCI 2*/ + if ((rsrc.start & 0xfffff) == 0x8600) { + setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384); + primary = 0; + hose->bus_offset = hose->first_busno; + mpc83xx_pci2_busno = hose->first_busno; + } + + printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%08lx. " + "Firmware bus number: %d->%d\n", + rsrc.start, hose->first_busno, hose->last_busno); + + DBG(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", + hose, hose->cfg_addr, hose->cfg_data); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pci_process_bridge_OF_ranges(hose, dev, primary); + + return 0; +} + +#endif diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 82c429d487f3..00c52f27ef4f 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c @@ -135,12 +135,13 @@ int __init hydra_init(void) { struct device_node *np; + struct resource r; np = find_devices("mac-io"); - if (np == NULL || np->n_addrs == 0) + if (np == NULL || of_address_to_resource(np, 0, &r)) return 0; - Hydra = ioremap(np->addrs[0].address, np->addrs[0].size); - printk("Hydra Mac I/O at %lx\n", np->addrs[0].address); + Hydra = ioremap(r.start, r.end-r.start); + printk("Hydra Mac I/O at %lx\n", r.start); printk("Hydra Feature_Control was %x", in_le32(&Hydra->Feature_Control)); out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN | @@ -177,18 +178,24 @@ setup_python(struct pci_controller *hose, struct device_node *dev) { u32 __iomem *reg; u32 val; - unsigned long addr = dev->addrs[0].address; + struct resource r; - setup_indirect_pci(hose, addr + 0xf8000, addr + 0xf8010); + if (of_address_to_resource(dev, 0, &r)) { + printk(KERN_ERR "No address for Python PCI controller\n"); + return; + } /* Clear the magic go-slow bit */ - reg = ioremap(dev->addrs[0].address + 0xf6000, 0x40); + reg = ioremap(r.start + 0xf6000, 0x40); + BUG_ON(!reg); val = in_be32(®[12]); if (val & PRG_CL_RESET_VALID) { out_be32(®[12], val & ~PRG_CL_RESET_VALID); in_be32(®[12]); } iounmap(reg); + + setup_indirect_pci(hose, r.start + 0xf8000, r.start + 0xf8010); } /* Marvell Discovery II based Pegasos 2 */ @@ -218,7 +225,7 @@ chrp_find_bridges(void) char *model, *machine; int is_longtrail = 0, is_mot = 0, is_pegasos = 0; struct device_node *root = find_path_device("/"); - + struct resource r; /* * The PCI host bridge nodes on some machines don't have * properties to adequately identify them, so we have to @@ -238,7 +245,7 @@ chrp_find_bridges(void) continue; ++index; /* The GG2 bridge on the LongTrail doesn't have an address */ - if (dev->n_addrs < 1 && !is_longtrail) { + if (of_address_to_resource(dev, 0, &r) && !is_longtrail) { printk(KERN_WARNING "Can't use %s: no address\n", dev->full_name); continue; @@ -255,8 +262,8 @@ chrp_find_bridges(void) printk(KERN_INFO "PCI buses %d..%d", bus_range[0], bus_range[1]); printk(" controlled by %s", dev->type); - if (dev->n_addrs > 0) - printk(" at %lx", dev->addrs[0].address); + if (!is_longtrail) + printk(" at %lx", r.start); printk("\n"); hose = pcibios_alloc_controller(); diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 4ec8ba737e7d..2dc87aa5962f 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c @@ -352,9 +352,10 @@ static void __init chrp_find_openpic(void) opaddr = opprop[na-1]; /* assume 32-bit */ oplen /= na * sizeof(unsigned int); } else { - if (np->n_addrs == 0) + struct resource r; + if (of_address_to_resource(np, 0, &r)) return; - opaddr = np->addrs[0].address; + opaddr = r.start; oplen = 0; } @@ -377,7 +378,7 @@ static void __init chrp_find_openpic(void) */ if (oplen < len) { printk(KERN_ERR "Insufficient addresses for distributed" - " OpenPIC (%d < %d)\n", np->n_addrs, len); + " OpenPIC (%d < %d)\n", oplen, len); len = oplen; } diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 737ee5d9f0aa..36a0f97bb7b1 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -21,6 +21,7 @@ #include <linux/mc146818rtc.h> #include <linux/init.h> #include <linux/bcd.h> +#include <linux/ioport.h> #include <asm/io.h> #include <asm/nvram.h> @@ -37,14 +38,16 @@ static int nvram_data = NVRAM_DATA; long __init chrp_time_init(void) { struct device_node *rtcs; + struct resource r; int base; rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); if (rtcs == NULL) rtcs = find_compatible_devices("rtc", "ds1385-rtc"); - if (rtcs == NULL || rtcs->addrs == NULL) + if (rtcs == NULL || of_address_to_resource(rtcs, 0, &r)) return 0; - base = rtcs->addrs[0].address; + + base = r.start; nvram_as1 = 0; nvram_as0 = base; nvram_data = base + 1; diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c index 83442ea77476..be3fbfc24e6c 100644 --- a/arch/powerpc/platforms/iseries/irq.c +++ b/arch/powerpc/platforms/iseries/irq.c @@ -334,14 +334,12 @@ int __init iSeries_allocate_IRQ(HvBusNumber bus, */ int iSeries_get_irq(struct pt_regs *regs) { - struct paca_struct *lpaca; /* -2 means ignore this interrupt */ int irq = -2; - lpaca = get_paca(); #ifdef CONFIG_SMP - if (lpaca->lppaca.int_dword.fields.ipi_cnt) { - lpaca->lppaca.int_dword.fields.ipi_cnt = 0; + if (get_lppaca()->int_dword.fields.ipi_cnt) { + get_lppaca()->int_dword.fields.ipi_cnt = 0; iSeries_smp_message_recv(regs); } #endif /* CONFIG_SMP */ diff --git a/arch/powerpc/platforms/iseries/misc.S b/arch/powerpc/platforms/iseries/misc.S index dfe7aa1ba098..7641fc7e550a 100644 --- a/arch/powerpc/platforms/iseries/misc.S +++ b/arch/powerpc/platforms/iseries/misc.S @@ -44,7 +44,8 @@ _GLOBAL(local_irq_restore) /* Check pending interrupts */ /* A decrementer, IPI or PMC interrupt may have occurred * while we were in the hypervisor (which enables) */ - ld r4,PACALPPACA+LPPACAANYINT(r13) + ld r4,PACALPPACAPTR(r13) + ld r4,LPPACAANYINT(r4) cmpdi r4,0 beqlr diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index c6bbe5c25107..3f8790146b00 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c @@ -538,7 +538,7 @@ static unsigned long __init build_iSeries_Memory_Map(void) */ static void __init iSeries_setup_arch(void) { - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { ppc_md.idle_loop = iseries_shared_idle; printk(KERN_INFO "Using shared processor idle loop\n"); } else { @@ -647,7 +647,7 @@ static void yield_shared_processor(void) * The decrementer stops during the yield. Force a fake decrementer * here and let the timer_interrupt code sort out the actual time. */ - get_paca()->lppaca.int_dword.fields.decr_int = 1; + get_lppaca()->int_dword.fields.decr_int = 1; process_iSeries_events(); } @@ -883,7 +883,7 @@ void dt_cpus(struct iseries_flat_dt *dt) pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); for (i = 0; i < NR_CPUS; i++) { - if (paca[i].lppaca.dyn_proc_status >= 2) + if (lppaca[i].dyn_proc_status >= 2) continue; snprintf(p, 32 - (p - buf), "@%d", i); @@ -891,7 +891,7 @@ void dt_cpus(struct iseries_flat_dt *dt) dt_prop_str(dt, "device_type", "cpu"); - index = paca[i].lppaca.dyn_hv_phys_proc_index; + index = lppaca[i].dyn_hv_phys_proc_index; d = &xIoHriProcessorVpd[index]; dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index fcb094ec6aec..6f9d407a709f 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c @@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) BUG_ON((nr < 0) || (nr >= NR_CPUS)); /* Verify that our partition has a processor nr */ - if (paca[nr].lppaca.dyn_proc_status >= 2) + if (lppaca[nr].dyn_proc_status >= 2) return; /* The processor is currently spinning, waiting diff --git a/arch/powerpc/platforms/maple/pci.c b/arch/powerpc/platforms/maple/pci.c index f40451da037c..7d4099a34f92 100644 --- a/arch/powerpc/platforms/maple/pci.c +++ b/arch/powerpc/platforms/maple/pci.c @@ -316,7 +316,6 @@ static int __init add_bridge(struct device_node *dev) char* disp_name; int *bus_range; int primary = 1; - struct property *of_prop; DBG("Adding PCI host bridge %s\n", dev->full_name); diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index a1cb4d236720..ec5c1e10c407 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c @@ -71,38 +71,60 @@ #define DBG(fmt...) #endif +static unsigned long maple_find_nvram_base(void) +{ + struct device_node *rtcs; + unsigned long result = 0; + + /* find NVRAM device */ + rtcs = of_find_compatible_node(NULL, "nvram", "AMD8111"); + if (rtcs) { + struct resource r; + if (of_address_to_resource(rtcs, 0, &r)) { + printk(KERN_EMERG "Maple: Unable to translate NVRAM" + " address\n"); + goto bail; + } + if (!(r.flags & IORESOURCE_IO)) { + printk(KERN_EMERG "Maple: NVRAM address isn't PIO!\n"); + goto bail; + } + result = r.start; + } else + printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); + bail: + of_node_put(rtcs); + return result; +} + static void maple_restart(char *cmd) { unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *rtcs; + struct device_node *sp; - /* find NVRAM device */ - rtcs = find_compatible_devices("nvram", "AMD8111"); - if (rtcs && rtcs->addrs) { - maple_nvram_base = rtcs->addrs[0].address; - } else { - printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); - printk(KERN_EMERG "Maple: Manual Restart Required\n"); - return; - } + maple_nvram_base = maple_find_nvram_base(); + if (maple_nvram_base == 0) + goto fail; /* find service processor device */ - rtcs = find_devices("service-processor"); - if (!rtcs) { + sp = of_find_node_by_name(NULL, "service-processor"); + if (!sp) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - printk(KERN_EMERG "Maple: Manual Restart Required\n"); - return; + goto fail; } - maple_nvram_offset = *(unsigned int*) get_property(rtcs, + maple_nvram_offset = *(unsigned int*) get_property(sp, "restart-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(rtcs, + maple_nvram_command = *(unsigned int*) get_property(sp, "restart-value", NULL); + of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; + fail: + printk(KERN_EMERG "Maple: Manual Restart Required\n"); } static void maple_power_off(void) @@ -110,33 +132,29 @@ static void maple_power_off(void) unsigned int maple_nvram_base; unsigned int maple_nvram_offset; unsigned int maple_nvram_command; - struct device_node *rtcs; + struct device_node *sp; - /* find NVRAM device */ - rtcs = find_compatible_devices("nvram", "AMD8111"); - if (rtcs && rtcs->addrs) { - maple_nvram_base = rtcs->addrs[0].address; - } else { - printk(KERN_EMERG "Maple: Unable to find NVRAM\n"); - printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); - return; - } + maple_nvram_base = maple_find_nvram_base(); + if (maple_nvram_base == 0) + goto fail; /* find service processor device */ - rtcs = find_devices("service-processor"); - if (!rtcs) { + sp = of_find_node_by_name(NULL, "service-processor"); + if (!sp) { printk(KERN_EMERG "Maple: Unable to find Service Processor\n"); - printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); - return; + goto fail; } - maple_nvram_offset = *(unsigned int*) get_property(rtcs, + maple_nvram_offset = *(unsigned int*) get_property(sp, "power-off-addr", NULL); - maple_nvram_command = *(unsigned int*) get_property(rtcs, + maple_nvram_command = *(unsigned int*) get_property(sp, "power-off-value", NULL); + of_node_put(sp); /* send command */ outb_p(maple_nvram_command, maple_nvram_base + maple_nvram_offset); for (;;) ; + fail: + printk(KERN_EMERG "Maple: Manual Power-Down Required\n"); } static void maple_halt(void) @@ -179,9 +197,6 @@ void __init maple_setup_arch(void) */ static void __init maple_init_early(void) { - unsigned int default_speed; - u64 physport; - DBG(" -> maple_init_early\n"); /* Initialize hash table, from now on, we can take hash faults diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index 15846cc938ac..50bc4eb85353 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c @@ -168,11 +168,24 @@ unsigned long __init maple_get_boot_time(void) struct rtc_time tm; struct device_node *rtcs; - rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); - if (rtcs && rtcs->addrs) { - maple_rtc_addr = rtcs->addrs[0].address; - printk(KERN_INFO "Maple: Found RTC at 0x%x\n", maple_rtc_addr); - } else { + rtcs = of_find_compatible_node(NULL, "rtc", "pnpPNP,b00"); + if (rtcs) { + struct resource r; + if (of_address_to_resource(rtcs, 0, &r)) { + printk(KERN_EMERG "Maple: Unable to translate RTC" + " address\n"); + goto bail; + } + if (!(r.flags & IORESOURCE_IO)) { + printk(KERN_EMERG "Maple: RTC address isn't PIO!\n"); + goto bail; + } + maple_rtc_addr = r.start; + printk(KERN_INFO "Maple: Found RTC at IO 0x%x\n", + maple_rtc_addr); + } + bail: + if (maple_rtc_addr == 0) { maple_rtc_addr = RTC_PORT(0); /* legacy address */ printk(KERN_INFO "Maple: No device node for RTC, assuming " "legacy address (0x%x)\n", maple_rtc_addr); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 1fe445ab78a6..8952528d31ac 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -254,11 +254,11 @@ out: void vpa_init(int cpu) { int hwcpu = get_hard_smp_processor_id(cpu); - unsigned long vpa = __pa(&paca[cpu].lppaca); + unsigned long vpa = __pa(&lppaca[cpu]); long ret; if (cpu_has_feature(CPU_FTR_ALTIVEC)) - paca[cpu].lppaca.vmxregs_in_use = 1; + lppaca[cpu].vmxregs_in_use = 1; ret = register_vpa(hwcpu, vpa); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index d8864164dbe8..86cfa6ecdcf3 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -350,6 +350,100 @@ static int do_remove_node(char *buf) return rv; } +static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) +{ + char *handle_str; + phandle handle; + *npp = NULL; + + handle_str = buf; + + buf = strchr(buf, ' '); + if (!buf) + return NULL; + *buf = '\0'; + buf++; + + handle = simple_strtoul(handle_str, NULL, 10); + + *npp = of_find_node_by_phandle(handle); + return buf; +} + +static int do_add_property(char *buf, size_t bufsize) +{ + struct property *prop = NULL; + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + end = buf + bufsize; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + prop = new_property(name, length, value, NULL); + if (!prop) + return -ENOMEM; + + prom_add_property(np, prop); + + return 0; +} + +static int do_remove_property(char *buf, size_t bufsize) +{ + struct device_node *np; + char *tmp; + struct property *prop; + buf = parse_node(buf, bufsize, &np); + + if (!np) + return -ENODEV; + + tmp = strchr(buf,' '); + if (tmp) + *tmp = '\0'; + + if (strlen(buf) == 0) + return -EINVAL; + + prop = of_find_property(np, buf, NULL); + + return prom_remove_property(np, prop); +} + +static int do_update_property(char *buf, size_t bufsize) +{ + struct device_node *np; + unsigned char *value; + char *name, *end; + int length; + struct property *newprop, *oldprop; + buf = parse_node(buf, bufsize, &np); + end = buf + bufsize; + + if (!np) + return -ENODEV; + + if (parse_next_property(buf, end, &name, &length, &value) == NULL) + return -EINVAL; + + newprop = new_property(name, length, value, NULL); + if (!newprop) + return -ENOMEM; + + oldprop = of_find_property(np, name,NULL); + if (!oldprop) + return -ENODEV; + + return prom_update_property(np, newprop, oldprop); +} + /** * ofdt_write - perform operations on the Open Firmware device tree * @@ -392,6 +486,12 @@ static ssize_t ofdt_write(struct file *file, const char __user *buf, size_t coun rv = do_add_node(tmp, count - (tmp - kbuf)); else if (!strcmp(kbuf, "remove_node")) rv = do_remove_node(tmp); + else if (!strcmp(kbuf, "add_property")) + rv = do_add_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "remove_property")) + rv = do_remove_property(tmp, count - (tmp - kbuf)); + else if (!strcmp(kbuf, "update_property")) + rv = do_update_property(tmp, count - (tmp - kbuf)); else rv = -EINVAL; out: diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 68b7f086d63d..da6cebaf72cd 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -190,7 +190,7 @@ static void pseries_lpar_enable_pmcs(void) /* instruct hypervisor to maintain PMCs */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) - get_paca()->lppaca.pmcregs_in_use = 1; + get_lppaca()->pmcregs_in_use = 1; } static void __init pSeries_setup_arch(void) @@ -234,7 +234,7 @@ static void __init pSeries_setup_arch(void) /* Choose an idle loop */ if (firmware_has_feature(FW_FEATURE_SPLPAR)) { vpa_init(boot_cpuid); - if (get_paca()->lppaca.shared_proc) { + if (get_lppaca()->shared_proc) { printk(KERN_INFO "Using shared processor idle loop\n"); ppc_md.idle_loop = pseries_shared_idle; } else { @@ -444,10 +444,10 @@ DECLARE_PER_CPU(unsigned long, smt_snooze_delay); static inline void dedicated_idle_sleep(unsigned int cpu) { - struct paca_struct *ppaca = &paca[cpu ^ 1]; + struct lppaca *plppaca = &lppaca[cpu ^ 1]; /* Only sleep if the other thread is not idle */ - if (!(ppaca->lppaca.idle)) { + if (!(plppaca->idle)) { local_irq_disable(); /* @@ -480,7 +480,6 @@ static inline void dedicated_idle_sleep(unsigned int cpu) static void pseries_dedicated_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); unsigned long start_snooze; unsigned long *smt_snooze_delay = &__get_cpu_var(smt_snooze_delay); @@ -491,7 +490,7 @@ static void pseries_dedicated_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; if (!need_resched()) { start_snooze = get_tb() + @@ -518,7 +517,7 @@ static void pseries_dedicated_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -532,7 +531,6 @@ static void pseries_dedicated_idle(void) static void pseries_shared_idle(void) { - struct paca_struct *lpaca = get_paca(); unsigned int cpu = smp_processor_id(); while (1) { @@ -540,7 +538,7 @@ static void pseries_shared_idle(void) * Indicate to the HV that we are idle. Now would be * a good time to find other work to dispatch. */ - lpaca->lppaca.idle = 1; + get_lppaca()->idle = 1; while (!need_resched() && !cpu_is_offline(cpu)) { local_irq_disable(); @@ -564,7 +562,7 @@ static void pseries_shared_idle(void) HMT_medium(); } - lpaca->lppaca.idle = 0; + get_lppaca()->idle = 0; ppc64_runlatch_on(); preempt_enable_no_resched(); @@ -588,7 +586,7 @@ static void pseries_kexec_cpu_down(int crash_shutdown, int secondary) { /* Don't risk a hypervisor call if we're crashing */ if (!crash_shutdown) { - unsigned long vpa = __pa(&get_paca()->lppaca); + unsigned long vpa = __pa(get_lppaca()); if (unregister_vpa(hard_smp_processor_id(), vpa)) { printk("VPA deregistration of cpu %u (hw_cpu_id %d) " |