diff options
author | Arnd Bergmann | 2012-09-04 15:01:37 +0200 |
---|---|---|
committer | Arnd Bergmann | 2012-09-04 15:01:37 +0200 |
commit | 863e99a8c1ea2b0391491904297f57a0f6a1fdd6 (patch) | |
tree | 0e7789f83c0ba3a1bc3c19d3ccf5ea6f84f19db6 /arch/powerpc/platforms | |
parent | dd9bf78040fa0da4cecc228e1682b9682b8cb180 (diff) | |
parent | a849088aa1552b1a28eea3daff599ee22a734ae3 (diff) |
Merge commit 'a849088aa1' from rmk/fixes into cleanup/io-pci
As Stephen Rothwell reports, a849088aa155 ("ARM: Fix ioremap() of
address zero") from the arm-current tree and commit c2794437091a ("ARM:
Add fixed PCI i/o mapping") from the arm-soc tree conflict in
a nontrivial way in arch/arm/mm/mmu.c.
Rob Herring explains:
The PCI i/o reserved area has a dummy physical address of 0 and
needs to be skipped by ioremap searches. So we don't set
VM_ARM_STATIC_MAPPING to prevent matches by ioremap. The vm_struct
settings don't really matter when we do the real mapping of the
i/o space.
Since commit a849088aa155 is at the start of the fixes branch
in the arm tree, we can merge it into the branch that contains
the other ioremap changes.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/powerpc/platforms')
38 files changed, 750 insertions, 695 deletions
diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c index 583e67fee37e..9f6c33d63a42 100644 --- a/arch/powerpc/platforms/44x/currituck.c +++ b/arch/powerpc/platforms/44x/currituck.c @@ -160,7 +160,7 @@ static void __init ppc47x_setup_arch(void) /* No need to check the DMA config as we /know/ our windows are all of * RAM. Lets hope that doesn't change */ #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > 0xffffffff) { + if ((memblock_end_of_DRAM() - 1) > 0xffffffff) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/82xx/km82xx.c b/arch/powerpc/platforms/82xx/km82xx.c index 3661bcdc326a..cf964e19573a 100644 --- a/arch/powerpc/platforms/82xx/km82xx.c +++ b/arch/powerpc/platforms/82xx/km82xx.c @@ -128,6 +128,11 @@ static __initdata struct cpm_pin km82xx_pins[] = { {3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXP */ {3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXN */ {3, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* RXD */ + + /* SPI */ + {3, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_MISO PD16 */ + {3, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_MOSI PD17 */ + {3, 18, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_CLK PD18 */ }; static void __init init_ioports(void) diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c index a266ba876863..89923d723349 100644 --- a/arch/powerpc/platforms/83xx/km83xx.c +++ b/arch/powerpc/platforms/83xx/km83xx.c @@ -3,7 +3,7 @@ * Author: Heiko Schocher <hs@denx.de> * * Description: - * Keymile KMETER1 board specific routines. + * Keymile 83xx platform specific routines. * * 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 @@ -70,54 +70,88 @@ static void __init mpc83xx_km_setup_arch(void) for_each_node_by_name(np, "spi") par_io_of_config(np); - for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;) + for_each_node_by_name(np, "ucc") par_io_of_config(np); } np = of_find_compatible_node(NULL, "network", "ucc_geth"); if (np != NULL) { - uint svid; + /* + * handle mpc8360E Erratum QE_ENET10: + * RGMII AC values do not meet the specification + */ + uint svid = mfspr(SPRN_SVR); + struct device_node *np_par; + struct resource res; + void __iomem *base; + int ret; + + np_par = of_find_node_by_name(NULL, "par_io"); + if (np_par == NULL) { + printk(KERN_WARNING "%s couldn;t find par_io node\n", + __func__); + return; + } + /* Map Parallel I/O ports registers */ + ret = of_address_to_resource(np_par, 0, &res); + if (ret) { + printk(KERN_WARNING "%s couldn;t map par_io registers\n", + __func__); + return; + } + + base = ioremap(res.start, res.end - res.start + 1); + + /* + * set output delay adjustments to default values according + * table 5 in Errata Rev. 5, 9/2011: + * + * write 0b01 to UCC1 bits 18:19 + * write 0b01 to UCC2 option 1 bits 4:5 + * write 0b01 to UCC2 option 2 bits 16:17 + */ + clrsetbits_be32((base + 0xa8), 0x0c00f000, 0x04005000); + + /* + * set output delay adjustments to default values according + * table 3-13 in Reference Manual Rev.3 05/2010: + * + * write 0b01 to UCC2 option 2 bits 16:17 + * write 0b0101 to UCC1 bits 20:23 + * write 0b0101 to UCC2 option 1 bits 24:27 + */ + clrsetbits_be32((base + 0xac), 0x0000cff0, 0x00004550); - /* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */ - svid = mfspr(SPRN_SVR); if (SVR_REV(svid) == 0x0021) { - struct device_node *np_par; - struct resource res; - void __iomem *base; - int ret; - - np_par = of_find_node_by_name(NULL, "par_io"); - if (np_par == NULL) { - printk(KERN_WARNING "%s couldn;t find par_io node\n", - __func__); - return; - } - /* Map Parallel I/O ports registers */ - ret = of_address_to_resource(np_par, 0, &res); - if (ret) { - printk(KERN_WARNING "%s couldn;t map par_io registers\n", - __func__); - return; - } - base = ioremap(res.start, resource_size(&res)); + /* + * UCC2 option 1: write 0b1010 to bits 24:27 + * at address IMMRBAR+0x14AC + */ + clrsetbits_be32((base + 0xac), 0x000000f0, 0x000000a0); + } else if (SVR_REV(svid) == 0x0020) { + /* + * UCC1: write 0b11 to bits 18:19 + * at address IMMRBAR+0x14A8 + */ + setbits32((base + 0xa8), 0x00003000); /* - * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2) - * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1) + * UCC2 option 1: write 0b11 to bits 4:5 + * at address IMMRBAR+0x14A8 */ - setbits32((base + 0xa8), 0x0c003000); + setbits32((base + 0xa8), 0x0c000000); /* - * IMMR + 0x14AC[20:27] = 10101010 - * (data delay for both UCC's) + * UCC2 option 2: write 0b11 to bits 16:17 + * at address IMMRBAR+0x14AC */ - clrsetbits_be32((base + 0xac), 0xff0, 0xaa0); - iounmap(base); - of_node_put(np_par); + setbits32((base + 0xac), 0x0000c000); } + iounmap(base); + of_node_put(np_par); of_node_put(np); } -#endif /* CONFIG_QUICC_ENGINE */ +#endif /* CONFIG_QUICC_ENGINE */ } machine_device_initcall(mpc83xx_km, mpc83xx_declare_of_platform_devices); diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index f000d81c4e31..159c01e91463 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig @@ -23,6 +23,15 @@ config FSL_85XX_CACHE_SRAM cache-sram-size and cache-sram-offset kernel boot parameters should be passed when this option is enabled. +config BSC9131_RDB + bool "Freescale BSC9131RDB" + select DEFAULT_UIMAGE + help + This option enables support for the Freescale BSC9131RDB board. + The BSC9131 is a heterogeneous SoC containing an e500v2 powerpc and a + StarCore SC3850 DSP + Manufacturer : Freescale Semiconductor, Inc + config MPC8540_ADS bool "Freescale MPC8540 ADS" select DEFAULT_UIMAGE @@ -175,12 +184,6 @@ config SBC8548 help This option enables support for the Wind River SBC8548 board -config SBC8560 - bool "Wind River SBC8560" - select DEFAULT_UIMAGE - help - This option enables support for the Wind River SBC8560 board - config GE_IMP3A bool "GE Intelligent Platforms IMP3A" select DEFAULT_UIMAGE @@ -222,18 +225,6 @@ config P3041_DS help This option enables support for the P3041 DS board -config P3060_QDS - bool "Freescale P3060 QDS" - select DEFAULT_UIMAGE - select PPC_E500MC - select PHYS_64BIT - select SWIOTLB - select GPIO_MPC8XXX - select HAS_RAPIDIO - select PPC_EPAPR_HV_PIC - help - This option enables support for the P3060 QDS board - config P4080_DS bool "Freescale P4080 DS" select DEFAULT_UIMAGE @@ -263,6 +254,22 @@ config P5020_DS help This option enables support for the P5020 DS board +config PPC_QEMU_E500 + bool "QEMU generic e500 platform" + depends on EXPERIMENTAL + select DEFAULT_UIMAGE + help + This option enables support for running as a QEMU guest using + QEMU's generic e500 machine. This is not required if you're + using a QEMU machine that targets a specific board, such as + mpc8544ds. + + Unlike most e500 boards that target a specific CPU, this + platform works with any e500-family CPU that QEMU supports. + Thus, you'll need to make sure CONFIG_PPC_E500MC is set or + unset based on the emulated CPU (or actual host CPU in the case + of KVM). + endif # FSL_SOC_BOOKE config TQM85xx diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 2125d4ca068a..3dfe81175036 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_SMP) += smp.o obj-y += common.o +obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o @@ -17,14 +18,13 @@ obj-$(CONFIG_P1022_DS) += p1022_ds.o obj-$(CONFIG_P1023_RDS) += p1023_rds.o obj-$(CONFIG_P2041_RDB) += p2041_rdb.o corenet_ds.o obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o -obj-$(CONFIG_P3060_QDS) += p3060_qds.o corenet_ds.o obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o obj-$(CONFIG_STX_GP3) += stx_gp3.o obj-$(CONFIG_TQM85xx) += tqm85xx.o -obj-$(CONFIG_SBC8560) += sbc8560.o obj-$(CONFIG_SBC8548) += sbc8548.o obj-$(CONFIG_SOCRATES) += socrates.o socrates_fpga_pic.o obj-$(CONFIG_KSI8560) += ksi8560.o obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o obj-$(CONFIG_GE_IMP3A) += ge_imp3a.o +obj-$(CONFIG_PPC_QEMU_E500) += qemu_e500.o diff --git a/arch/powerpc/platforms/85xx/bsc913x_rdb.c b/arch/powerpc/platforms/85xx/bsc913x_rdb.c new file mode 100644 index 000000000000..9d57bedb940c --- /dev/null +++ b/arch/powerpc/platforms/85xx/bsc913x_rdb.c @@ -0,0 +1,67 @@ +/* + * BSC913xRDB Board Setup + * + * Author: Priyanka Jain <Priyanka.Jain@freescale.com> + * + * Copyright 2011-2012 Freescale Semiconductor Inc. + * + * 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/of_platform.h> +#include <linux/pci.h> +#include <asm/mpic.h> +#include <sysdev/fsl_soc.h> +#include <asm/udbg.h> + +#include "mpc85xx.h" + +void __init bsc913x_rdb_pic_init(void) +{ + struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | + MPIC_SINGLE_DEST_CPU, + 0, 256, " OpenPIC "); + + if (!mpic) + pr_err("bsc913x: Failed to allocate MPIC structure\n"); + else + mpic_init(mpic); +} + +/* + * Setup the architecture + */ +static void __init bsc913x_rdb_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("bsc913x_rdb_setup_arch()", 0); + + pr_info("bsc913x board from Freescale Semiconductor\n"); +} + +machine_device_initcall(bsc9131_rdb, mpc85xx_common_publish_devices); + +/* + * Called very early, device-tree isn't unflattened + */ + +static int __init bsc9131_rdb_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "fsl,bsc9131rdb"); +} + +define_machine(bsc9131_rdb) { + .name = "BSC9131 RDB", + .probe = bsc9131_rdb_probe, + .setup_arch = bsc913x_rdb_setup_arch, + .init_IRQ = bsc913x_rdb_pic_init, + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c index dd3617c531d7..925b02874233 100644 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ b/arch/powerpc/platforms/85xx/corenet_ds.c @@ -77,7 +77,7 @@ void __init corenet_ds_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/85xx/ge_imp3a.c b/arch/powerpc/platforms/85xx/ge_imp3a.c index 18014629416d..b6a728b0a8ca 100644 --- a/arch/powerpc/platforms/85xx/ge_imp3a.c +++ b/arch/powerpc/platforms/85xx/ge_imp3a.c @@ -125,7 +125,7 @@ static void __init ge_imp3a_setup_arch(void) mpc85xx_smp_init(); #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index 585bd22b1406..767c7cf18a9c 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c @@ -75,7 +75,7 @@ static void __init mpc8536_ds_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 1fd91e9e0ffb..6d3265fe7718 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c @@ -114,71 +114,53 @@ void __init mpc85xx_ds_pic_init(void) } #ifdef CONFIG_PCI -static int primary_phb_addr; extern int uli_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn); +static struct device_node *pci_with_uli; + static int mpc85xx_exclude_device(struct pci_controller *hose, u_char bus, u_char devfn) { - struct device_node* node; - struct resource rsrc; - - node = hose->dn; - of_address_to_resource(node, 0, &rsrc); - - if ((rsrc.start & 0xfffff) == primary_phb_addr) { + if (hose->dn == pci_with_uli) return uli_exclude_device(hose, bus, devfn); - } return PCIBIOS_SUCCESSFUL; } #endif /* CONFIG_PCI */ -/* - * Setup the architecture - */ -static void __init mpc85xx_ds_setup_arch(void) +static void __init mpc85xx_ds_pci_init(void) { #ifdef CONFIG_PCI - struct device_node *np; - struct pci_controller *hose; -#endif - dma_addr_t max = 0xffffffff; + struct device_node *node; - if (ppc_md.progress) - ppc_md.progress("mpc85xx_ds_setup_arch()", 0); + fsl_pci_init(); -#ifdef CONFIG_PCI - for_each_node_by_type(np, "pci") { - if (of_device_is_compatible(np, "fsl,mpc8540-pci") || - of_device_is_compatible(np, "fsl,mpc8548-pcie") || - of_device_is_compatible(np, "fsl,p2020-pcie")) { - struct resource rsrc; - of_address_to_resource(np, 0, &rsrc); - if ((rsrc.start & 0xfffff) == primary_phb_addr) - fsl_add_bridge(np, 1); - else - fsl_add_bridge(np, 0); - - hose = pci_find_hose_for_OF_device(np); - max = min(max, hose->dma_window_base_cur + - hose->dma_window_size); + /* See if we have a ULI under the primary */ + + node = of_find_node_by_name(NULL, "uli1575"); + while ((pci_with_uli = of_get_parent(node))) { + of_node_put(node); + node = pci_with_uli; + + if (pci_with_uli == fsl_pci_primary) { + ppc_md.pci_exclude_device = mpc85xx_exclude_device; + break; } } - - ppc_md.pci_exclude_device = mpc85xx_exclude_device; #endif +} - mpc85xx_smp_init(); +/* + * Setup the architecture + */ +static void __init mpc85xx_ds_setup_arch(void) +{ + if (ppc_md.progress) + ppc_md.progress("mpc85xx_ds_setup_arch()", 0); -#ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { - ppc_swiotlb_enable = 1; - set_pci_dma_ops(&swiotlb_dma_ops); - ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; - } -#endif + mpc85xx_ds_pci_init(); + mpc85xx_smp_init(); printk("MPC85xx DS board from Freescale Semiconductor\n"); } @@ -190,14 +172,7 @@ static int __init mpc8544_ds_probe(void) { unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "MPC8544DS")) { -#ifdef CONFIG_PCI - primary_phb_addr = 0xb000; -#endif - return 1; - } - - return 0; + return !!of_flat_dt_is_compatible(root, "MPC8544DS"); } machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices); @@ -215,14 +190,7 @@ static int __init mpc8572_ds_probe(void) { unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) { -#ifdef CONFIG_PCI - primary_phb_addr = 0x8000; -#endif - return 1; - } - - return 0; + return !!of_flat_dt_is_compatible(root, "fsl,MPC8572DS"); } /* @@ -232,14 +200,7 @@ static int __init p2020_ds_probe(void) { unsigned long root = of_get_flat_dt_root(); - if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) { -#ifdef CONFIG_PCI - primary_phb_addr = 0x9000; -#endif - return 1; - } - - return 0; + return !!of_flat_dt_is_compatible(root, "fsl,P2020DS"); } define_machine(mpc8544_ds) { diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index d208ebccb91c..8e4b094c553b 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c @@ -359,7 +359,7 @@ static void __init mpc85xx_mds_setup_arch(void) mpc85xx_mds_qe_init(); #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c index 313fce4f5574..1910fdcb75b2 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_rdb.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_rdb.c @@ -169,6 +169,7 @@ machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices); machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices); machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices); machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices); +machine_device_initcall(p1024_rdb, mpc85xx_common_publish_devices); /* * Called very early, device-tree isn't unflattened @@ -237,6 +238,13 @@ static int __init p1020_utm_pc_probe(void) return of_flat_dt_is_compatible(root, "fsl,P1020UTM-PC"); } +static int __init p1024_rdb_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return of_flat_dt_is_compatible(root, "fsl,P1024RDB"); +} + define_machine(p2020_rdb) { .name = "P2020 RDB", .probe = p2020_rdb_probe, @@ -348,3 +356,17 @@ define_machine(p1020_rdb_pc) { .calibrate_decr = generic_calibrate_decr, .progress = udbg_progress, }; + +define_machine(p1024_rdb) { + .name = "P1024 RDB", + .probe = p1024_rdb_probe, + .setup_arch = mpc85xx_rdb_setup_arch, + .init_IRQ = mpc85xx_rdb_pic_init, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index f700c81a1321..3c732acf331d 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -27,6 +27,7 @@ #include <sysdev/fsl_pci.h> #include <asm/udbg.h> #include <asm/fsl_guts.h> +#include <asm/fsl_lbc.h> #include "smp.h" #include "mpc85xx.h" @@ -142,17 +143,74 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, { } +struct fsl_law { + u32 lawbar; + u32 reserved1; + u32 lawar; + u32 reserved[5]; +}; + +#define LAWBAR_MASK 0x00F00000 +#define LAWBAR_SHIFT 12 + +#define LAWAR_EN 0x80000000 +#define LAWAR_TGT_MASK 0x01F00000 +#define LAW_TRGT_IF_LBC (0x04 << 20) + +#define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK) +#define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC) + +#define BR_BA 0xFFFF8000 + +/* + * Map a BRx value to a physical address + * + * The localbus BRx registers only store the lower 32 bits of the address. To + * obtain the upper four bits, we need to scan the LAW table. The entry which + * maps to the localbus will contain the upper four bits. + */ +static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) +{ +#ifndef CONFIG_PHYS_64BIT + /* + * If we only have 32-bit addressing, then the BRx address *is* the + * physical address. + */ + return br & BR_BA; +#else + const struct fsl_law *law = ecm + 0xc08; + unsigned int i; + + for (i = 0; i < count; i++) { + u64 lawbar = in_be32(&law[i].lawbar); + u32 lawar = in_be32(&law[i].lawar); + + if ((lawar & LAWAR_MASK) == LAWAR_MATCH) + /* Extract the upper four bits */ + return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12); + } + + return 0; +#endif +} + /** * p1022ds_set_monitor_port: switch the output to a different monitor port - * */ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) { struct device_node *guts_node; - struct device_node *indirect_node = NULL; + struct device_node *lbc_node = NULL; + struct device_node *law_node = NULL; struct ccsr_guts __iomem *guts; + struct fsl_lbc_regs *lbc = NULL; + void *ecm = NULL; u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; + phys_addr_t cs0_addr, cs1_addr; + u32 br0, or0, br1, or1; + const __be32 *iprop; + unsigned int num_laws; u8 b; /* Map the global utilities registers. */ @@ -168,22 +226,99 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) goto exit; } - indirect_node = of_find_compatible_node(NULL, NULL, - "fsl,p1022ds-indirect-pixis"); - if (!indirect_node) { - pr_err("p1022ds: missing pixis indirect mode node\n"); + lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); + if (!lbc_node) { + pr_err("p1022ds: missing localbus node\n"); goto exit; } - lbc_lcs0_ba = of_iomap(indirect_node, 0); - if (!lbc_lcs0_ba) { - pr_err("p1022ds: could not map localbus chip select 0\n"); + lbc = of_iomap(lbc_node, 0); + if (!lbc) { + pr_err("p1022ds: could not map localbus node\n"); + goto exit; + } + + law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); + if (!law_node) { + pr_err("p1022ds: missing local access window node\n"); + goto exit; + } + + ecm = of_iomap(law_node, 0); + if (!ecm) { + pr_err("p1022ds: could not map local access window node\n"); + goto exit; + } + + iprop = of_get_property(law_node, "fsl,num-laws", 0); + if (!iprop) { + pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); + goto exit; + } + num_laws = be32_to_cpup(iprop); + + /* + * Indirect mode requires both BR0 and BR1 to be set to "GPCM", + * otherwise writes to these addresses won't actually appear on the + * local bus, and so the PIXIS won't see them. + * + * In FCM mode, writes go to the NAND controller, which does not pass + * them to the localbus directly. So we force BR0 and BR1 into GPCM + * mode, since we don't care about what's behind the localbus any + * more. + */ + br0 = in_be32(&lbc->bank[0].br); + br1 = in_be32(&lbc->bank[1].br); + or0 = in_be32(&lbc->bank[0].or); + or1 = in_be32(&lbc->bank[1].or); + + /* Make sure CS0 and CS1 are programmed */ + if (!(br0 & BR_V) || !(br1 & BR_V)) { + pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); + goto exit; + } + + /* + * Use the existing BRx/ORx values if it's already GPCM. Otherwise, + * force the values to simple 32KB GPCM windows with the most + * conservative timing. + */ + if ((br0 & BR_MSEL) != BR_MS_GPCM) { + br0 = (br0 & BR_BA) | BR_V; + or0 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[0].br, br0); + out_be32(&lbc->bank[0].or, or0); + } + if ((br1 & BR_MSEL) != BR_MS_GPCM) { + br1 = (br1 & BR_BA) | BR_V; + or1 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[1].br, br1); + out_be32(&lbc->bank[1].or, or1); + } + + cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS0" + " (BR0=%08x)\n", br0); + goto exit; + } + cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS1" + " (BR1=%08x)\n", br1); goto exit; } - lbc_lcs1_ba = of_iomap(indirect_node, 1); + lbc_lcs0_ba = ioremap(cs0_addr, 1); + if (!lbc_lcs0_ba) { + pr_err("p1022ds: could not ioremap CS0 address %llx\n", + (unsigned long long)cs0_addr); + goto exit; + } + lbc_lcs1_ba = ioremap(cs1_addr, 1); if (!lbc_lcs1_ba) { - pr_err("p1022ds: could not map localbus chip select 1\n"); + pr_err("p1022ds: could not ioremap CS1 address %llx\n", + (unsigned long long)cs1_addr); goto exit; } @@ -254,10 +389,15 @@ exit: iounmap(lbc_lcs1_ba); if (lbc_lcs0_ba) iounmap(lbc_lcs0_ba); + if (lbc) + iounmap(lbc); + if (ecm) + iounmap(ecm); if (guts) iounmap(guts); - of_node_put(indirect_node); + of_node_put(law_node); + of_node_put(lbc_node); of_node_put(guts_node); } @@ -339,24 +479,6 @@ void __init p1022_ds_pic_init(void) #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) -/* - * Disables a node in the device tree. - * - * This function is called before kmalloc() is available, so the 'new' object - * should be allocated in the global area. The easiest way is to do that is - * to allocate one static local variable for each call to this function. - */ -static void __init disable_one_node(struct device_node *np, struct property *new) -{ - struct property *old; - - old = of_find_property(np, new->name, NULL); - if (old) - prom_update_property(np, new, old); - else - prom_add_property(np, new); -} - /* TRUE if there is a "video=fslfb" command-line parameter. */ static bool fslfb; @@ -419,28 +541,58 @@ static void __init p1022_ds_setup_arch(void) diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; /* - * Disable the NOR flash node if there is video=fslfb... command-line - * parameter. When the DIU is active, NOR flash is unavailable, so we - * have to disable the node before the MTD driver loads. + * Disable the NOR and NAND flash nodes if there is video=fslfb... + * command-line parameter. When the DIU is active, the localbus is + * unavailable, so we have to disable these nodes before the MTD + * driver loads. */ if (fslfb) { struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (np) { - np = of_find_compatible_node(np, NULL, "cfi-flash"); - if (np) { + struct device_node *np2; + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, "cfi-flash"); + if (np2) { static struct property nor_status = { .name = "status", .value = "disabled", .length = sizeof("disabled"), }; + /* + * prom_update_property() is called before + * kmalloc() is available, so the 'new' object + * should be allocated in the global area. + * The easiest way is to do that is to + * allocate one static local variable for each + * call to this function. + */ + pr_info("p1022ds: disabling %s node", + np2->full_name); + prom_update_property(np2, &nor_status); + of_node_put(np2); + } + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, + "fsl,elbc-fcm-nand"); + if (np2) { + static struct property nand_status = { + .name = "status", + .value = "disabled", + .length = sizeof("disabled"), + }; + pr_info("p1022ds: disabling %s node", - np->full_name); - disable_one_node(np, &nor_status); - of_node_put(np); + np2->full_name); + prom_update_property(np2, &nand_status); + of_node_put(np2); } + + of_node_put(np); } } @@ -450,7 +602,7 @@ static void __init p1022_ds_setup_arch(void) mpc85xx_smp_init(); #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c deleted file mode 100644 index 081cf4ac1881..000000000000 --- a/arch/powerpc/platforms/85xx/p3060_qds.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * P3060 QDS Setup - * - * Copyright 2011 Freescale Semiconductor Inc. - * - * 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/kernel.h> -#include <linux/interrupt.h> -#include <linux/phy.h> -#include <asm/machdep.h> -#include <asm/udbg.h> -#include <asm/mpic.h> -#include <linux/of_platform.h> -#include <sysdev/fsl_soc.h> -#include <sysdev/fsl_pci.h> -#include <asm/ehv_pic.h> -#include "corenet_ds.h" - -/* - * Called very early, device-tree isn't unflattened - */ -static int __init p3060_qds_probe(void) -{ - unsigned long root = of_get_flat_dt_root(); -#ifdef CONFIG_SMP - extern struct smp_ops_t smp_85xx_ops; -#endif - - if (of_flat_dt_is_compatible(root, "fsl,P3060QDS")) - return 1; - - /* Check if we're running under the Freescale hypervisor */ - if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) { - ppc_md.init_IRQ = ehv_pic_init; - ppc_md.get_irq = ehv_pic_get_irq; - ppc_md.restart = fsl_hv_restart; - ppc_md.power_off = fsl_hv_halt; - ppc_md.halt = fsl_hv_halt; -#ifdef CONFIG_SMP - /* - * Disable the timebase sync operations because we can't write - * to the timebase registers under the hypervisor. - */ - smp_85xx_ops.give_timebase = NULL; - smp_85xx_ops.take_timebase = NULL; -#endif - return 1; - } - - return 0; -} - -define_machine(p3060_qds) { - .name = "P3060 QDS", - .probe = p3060_qds_probe, - .setup_arch = corenet_ds_setup_arch, - .init_IRQ = corenet_ds_pic_init, -#ifdef CONFIG_PCI - .pcibios_fixup_bus = fsl_pcibios_fixup_bus, -#endif - .get_irq = mpic_get_coreint_irq, - .restart = fsl_rstcr_restart, - .calibrate_decr = generic_calibrate_decr, - .progress = udbg_progress, - .power_save = e500_idle, -}; - -machine_device_initcall(p3060_qds, corenet_ds_publish_devices); - -#ifdef CONFIG_SWIOTLB -machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier); -#endif diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c new file mode 100644 index 000000000000..95a2e53af71b --- /dev/null +++ b/arch/powerpc/platforms/85xx/qemu_e500.c @@ -0,0 +1,72 @@ +/* + * Paravirt target for a generic QEMU e500 machine + * + * This is intended to be a flexible device-tree-driven platform, not fixed + * to a particular piece of hardware or a particular spec of virtual hardware, + * beyond the assumption of an e500-family CPU. Some things are still hardcoded + * here, such as MPIC, but this is a limitation of the current code rather than + * an interface contract with QEMU. + * + * Copyright 2012 Freescale Semiconductor Inc. + * + * 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/kernel.h> +#include <linux/of_fdt.h> +#include <asm/machdep.h> +#include <asm/time.h> +#include <asm/udbg.h> +#include <asm/mpic.h> +#include <sysdev/fsl_soc.h> +#include <sysdev/fsl_pci.h> +#include "smp.h" +#include "mpc85xx.h" + +void __init qemu_e500_pic_init(void) +{ + struct mpic *mpic; + + mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU, + 0, 256, " OpenPIC "); + + BUG_ON(mpic == NULL); + mpic_init(mpic); +} + +static void __init qemu_e500_setup_arch(void) +{ + ppc_md.progress("qemu_e500_setup_arch()", 0); + + fsl_pci_init(); + mpc85xx_smp_init(); +} + +/* + * Called very early, device-tree isn't unflattened + */ +static int __init qemu_e500_probe(void) +{ + unsigned long root = of_get_flat_dt_root(); + + return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500"); +} + +machine_device_initcall(qemu_e500, mpc85xx_common_publish_devices); + +define_machine(qemu_e500) { + .name = "QEMU e500", + .probe = qemu_e500_probe, + .setup_arch = qemu_e500_setup_arch, + .init_IRQ = qemu_e500_pic_init, +#ifdef CONFIG_PCI + .pcibios_fixup_bus = fsl_pcibios_fixup_bus, +#endif + .get_irq = mpic_get_irq, + .restart = fsl_rstcr_restart, + .calibrate_decr = generic_calibrate_decr, + .progress = udbg_progress, +}; diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c deleted file mode 100644 index b1be632ede43..000000000000 --- a/arch/powerpc/platforms/85xx/sbc8560.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Wind River SBC8560 setup and early boot code. - * - * Copyright 2007 Wind River Systems Inc. - * - * By Paul Gortmaker (see MAINTAINERS for contact information) - * - * Based largely on the MPC8560ADS support - Copyright 2005 Freescale Inc. - * - * 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/stddef.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/kdev_t.h> -#include <linux/delay.h> -#include <linux/seq_file.h> -#include <linux/of_platform.h> - -#include <asm/time.h> -#include <asm/machdep.h> -#include <asm/pci-bridge.h> -#include <asm/mpic.h> -#include <mm/mmu_decl.h> -#include <asm/udbg.h> - -#include <sysdev/fsl_soc.h> -#include <sysdev/fsl_pci.h> - -#include "mpc85xx.h" - -#ifdef CONFIG_CPM2 -#include <asm/cpm2.h> -#include <sysdev/cpm2_pic.h> -#endif - -static void __init sbc8560_pic_init(void) -{ - struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN, - 0, 256, " OpenPIC "); - BUG_ON(mpic == NULL); - mpic_init(mpic); - - mpc85xx_cpm2_pic_init(); -} - -/* - * Setup the architecture - */ -#ifdef CONFIG_CPM2 -struct cpm_pin { - int port, pin, flags; -}; - -static const struct cpm_pin sbc8560_pins[] = { - /* SCC1 */ - {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, - {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - - /* SCC2 */ - {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - - /* FCC2 */ - {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY}, - {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */ - {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */ - - /* FCC3 */ - {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, - {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, - {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */ - {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */ -}; - -static void __init init_ioports(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) { - const struct cpm_pin *pin = &sbc8560_pins[i]; - cpm2_set_pin(pin->port, pin->pin, pin->flags); - } - - cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX); - cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX); - cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX); -} -#endif - -static void __init sbc8560_setup_arch(void) -{ -#ifdef CONFIG_PCI - struct device_node *np; -#endif - - if (ppc_md.progress) - ppc_md.progress("sbc8560_setup_arch()", 0); - -#ifdef CONFIG_CPM2 - cpm2_reset(); - init_ioports(); -#endif - -#ifdef CONFIG_PCI - for_each_compatible_node(np, "pci", "fsl,mpc8540-pci") - fsl_add_bridge(np, 1); -#endif -} - -static void sbc8560_show_cpuinfo(struct seq_file *m) -{ - uint pvid, svid, phid1; - - pvid = mfspr(SPRN_PVR); - svid = mfspr(SPRN_SVR); - - seq_printf(m, "Vendor\t\t: Wind River\n"); - seq_printf(m, "PVR\t\t: 0x%x\n", pvid); - seq_printf(m, "SVR\t\t: 0x%x\n", svid); - - /* Display cpu Pll setting */ - phid1 = mfspr(SPRN_HID1); - seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); -} - -machine_device_initcall(sbc8560, mpc85xx_common_publish_devices); - -/* - * Called very early, device-tree isn't unflattened - */ -static int __init sbc8560_probe(void) -{ - unsigned long root = of_get_flat_dt_root(); - - return of_flat_dt_is_compatible(root, "SBC8560"); -} - -#ifdef CONFIG_RTC_DRV_M48T59 -static int __init sbc8560_rtc_init(void) -{ - struct device_node *np; - struct resource res; - struct platform_device *rtc_dev; - - np = of_find_compatible_node(NULL, NULL, "m48t59"); - if (np == NULL) { - printk("No RTC in DTB. Has it been eaten by wild dogs?\n"); - return -ENODEV; - } - - of_address_to_resource(np, 0, &res); - of_node_put(np); - - printk("Found RTC (m48t59) at i/o 0x%x\n", res.start); - - rtc_dev = platform_device_register_simple("rtc-m48t59", 0, &res, 1); - - if (IS_ERR(rtc_dev)) { - printk("Registering sbc8560 RTC device failed\n"); - return PTR_ERR(rtc_dev); - } - - return 0; -} - -arch_initcall(sbc8560_rtc_init); - -#endif /* M48T59 */ - -static __u8 __iomem *brstcr; - -static int __init sbc8560_bdrstcr_init(void) -{ - struct device_node *np; - struct resource res; - - np = of_find_compatible_node(NULL, NULL, "wrs,sbc8560-brstcr"); - if (np == NULL) { - printk(KERN_WARNING "sbc8560: No board specific RSTCR in DTB.\n"); - return -ENODEV; - } - - of_address_to_resource(np, 0, &res); - - printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res); - - brstcr = ioremap(res.start, resource_size(&res)); - if(!brstcr) - printk(KERN_WARNING "sbc8560: ioremap of brstcr failed.\n"); - - of_node_put(np); - - return 0; -} - -arch_initcall(sbc8560_bdrstcr_init); - -void sbc8560_rstcr_restart(char * cmd) -{ - local_irq_disable(); - if(brstcr) - clrbits8(brstcr, 0x80); - - while(1); -} - -define_machine(sbc8560) { - .name = "SBC8560", - .probe = sbc8560_probe, - .setup_arch = sbc8560_setup_arch, - .init_IRQ = sbc8560_pic_init, - .show_cpuinfo = sbc8560_show_cpuinfo, - .get_irq = mpic_get_irq, - .restart = sbc8560_rstcr_restart, - .calibrate_decr = generic_calibrate_decr, - .progress = udbg_progress, -}; diff --git a/arch/powerpc/platforms/85xx/tqm85xx.c b/arch/powerpc/platforms/85xx/tqm85xx.c index 4d786c25d3e5..3e70a2035e53 100644 --- a/arch/powerpc/platforms/85xx/tqm85xx.c +++ b/arch/powerpc/platforms/85xx/tqm85xx.c @@ -102,7 +102,7 @@ static void tqm85xx_show_cpuinfo(struct seq_file *m) seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); } -static void __init tqm85xx_ti1520_fixup(struct pci_dev *pdev) +static void __devinit tqm85xx_ti1520_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_ppc9a.c b/arch/powerpc/platforms/86xx/gef_ppc9a.c index 1fca663f1b25..563aafa8629c 100644 --- a/arch/powerpc/platforms/86xx/gef_ppc9a.c +++ b/arch/powerpc/platforms/86xx/gef_ppc9a.c @@ -164,7 +164,7 @@ static void gef_ppc9a_show_cpuinfo(struct seq_file *m) gef_ppc9a_get_vme_is_syscon() ? "yes" : "no"); } -static void __init gef_ppc9a_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_ppc9a_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc310.c b/arch/powerpc/platforms/86xx/gef_sbc310.c index 14e0e576bcbd..cc6a91ae0889 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc310.c +++ b/arch/powerpc/platforms/86xx/gef_sbc310.c @@ -152,7 +152,7 @@ static void gef_sbc310_show_cpuinfo(struct seq_file *m) } -static void __init gef_sbc310_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc310_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/gef_sbc610.c b/arch/powerpc/platforms/86xx/gef_sbc610.c index 1638f43599f0..aead6b337f4a 100644 --- a/arch/powerpc/platforms/86xx/gef_sbc610.c +++ b/arch/powerpc/platforms/86xx/gef_sbc610.c @@ -141,7 +141,7 @@ static void gef_sbc610_show_cpuinfo(struct seq_file *m) seq_printf(m, "SVR\t\t: 0x%x\n", svid); } -static void __init gef_sbc610_nec_fixup(struct pci_dev *pdev) +static void __devinit gef_sbc610_nec_fixup(struct pci_dev *pdev) { unsigned int val; diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index 3755e61d7ecf..817245bc0219 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -102,7 +102,7 @@ mpc86xx_hpcn_setup_arch(void) #endif #ifdef CONFIG_SWIOTLB - if (memblock_end_of_DRAM() > max) { + if ((memblock_end_of_DRAM() - 1) > max) { ppc_swiotlb_enable = 1; set_pci_dma_ops(&swiotlb_dma_ops); ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb; diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index a35ca44ade66..e7a896acd982 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -25,6 +25,7 @@ source "arch/powerpc/platforms/wsp/Kconfig" config KVM_GUEST bool "KVM Guest support" default n + select EPAPR_PARAVIRT ---help--- This option enables various optimizations for running under the KVM hypervisor. Overhead for the kernel when not running inside KVM should @@ -32,6 +33,14 @@ config KVM_GUEST In case of doubt, say Y +config EPAPR_PARAVIRT + bool "ePAPR para-virtualization support" + default n + help + Enables ePAPR para-virtualization support for guests. + + In case of doubt, say Y + config PPC_NATIVE bool depends on 6xx || PPC64 diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 61c9550819a2..30fd01de6bed 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype @@ -159,6 +159,10 @@ config PPC_E500MC bool "e500mc Support" select PPC_FPU depends on E500 + help + This must be enabled for running on e500mc (and derivatives + such as e5500/e6500), and must be disabled for running on + e500v1 or e500v2. config PPC_FPU bool diff --git a/arch/powerpc/platforms/cell/beat_hvCall.S b/arch/powerpc/platforms/cell/beat_hvCall.S index 74c817448948..96c801907126 100644 --- a/arch/powerpc/platforms/cell/beat_hvCall.S +++ b/arch/powerpc/platforms/cell/beat_hvCall.S @@ -22,8 +22,6 @@ #include <asm/ppc_asm.h> -#define STK_PARM(i) (48 + ((i)-3)*8) - /* Not implemented on Beat, now */ #define HCALL_INST_PRECALL #define HCALL_INST_POSTCALL @@ -74,7 +72,7 @@ _GLOBAL(beat_hcall_norets8) mr r6,r7 mr r7,r8 mr r8,r9 - ld r10,STK_PARM(r10)(r1) + ld r10,STK_PARAM(R10)(r1) HVSC /* invoke the hypervisor */ @@ -94,7 +92,7 @@ _GLOBAL(beat_hcall1) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -108,7 +106,7 @@ _GLOBAL(beat_hcall1) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) lwz r0,8(r1) @@ -125,7 +123,7 @@ _GLOBAL(beat_hcall2) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -139,7 +137,7 @@ _GLOBAL(beat_hcall2) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) @@ -157,7 +155,7 @@ _GLOBAL(beat_hcall3) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -171,7 +169,7 @@ _GLOBAL(beat_hcall3) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -190,7 +188,7 @@ _GLOBAL(beat_hcall4) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -204,7 +202,7 @@ _GLOBAL(beat_hcall4) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -224,7 +222,7 @@ _GLOBAL(beat_hcall5) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -238,7 +236,7 @@ _GLOBAL(beat_hcall5) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -259,7 +257,7 @@ _GLOBAL(beat_hcall6) HCALL_INST_PRECALL - std r4,STK_PARM(r4)(r1) /* save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* save ret buffer */ mr r11,r3 mr r3,r5 @@ -273,7 +271,7 @@ _GLOBAL(beat_hcall6) HCALL_INST_POSTCALL - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c index b9f509a34c01..dca213666747 100644 --- a/arch/powerpc/platforms/cell/iommu.c +++ b/arch/powerpc/platforms/cell/iommu.c @@ -518,7 +518,6 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np, __set_bit(0, window->table.it_map); tce_build_cell(&window->table, window->table.it_offset, 1, (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL); - window->table.it_hint = window->table.it_blocksize; return window; } @@ -552,8 +551,7 @@ static struct iommu_table *cell_get_iommu_table(struct device *dev) iommu = cell_iommu_for_node(dev_to_node(dev)); if (iommu == NULL || list_empty(&iommu->windows)) { printk(KERN_ERR "iommu: missing iommu for %s (node %d)\n", - dev->of_node ? dev->of_node->full_name : "?", - dev_to_node(dev)); + of_node_full_name(dev->of_node), dev_to_node(dev)); return NULL; } window = list_entry(iommu->windows.next, struct iommu_window, list); diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 66519d263da7..dba1ce235da5 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -186,10 +186,13 @@ static void spufs_prune_dir(struct dentry *dir) static int spufs_rmdir(struct inode *parent, struct dentry *dir) { /* remove all entries */ + int res; spufs_prune_dir(dir); d_drop(dir); - - return simple_rmdir(parent, dir); + res = simple_rmdir(parent, dir); + /* We have to give up the mm_struct */ + spu_forget(SPUFS_I(dir->d_inode)->i_ctx); + return res; } static int spufs_fill_dir(struct dentry *dir, @@ -245,9 +248,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file) mutex_unlock(&parent->i_mutex); WARN_ON(ret); - /* We have to give up the mm_struct */ - spu_forget(ctx); - return dcache_dir_close(inode, file); } @@ -317,28 +317,23 @@ out: return ret; } -static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) +static int spufs_context_open(struct path *path) { int ret; struct file *filp; ret = get_unused_fd(); - if (ret < 0) { - dput(dentry); - mntput(mnt); - goto out; - } + if (ret < 0) + return ret; - filp = dentry_open(dentry, mnt, O_RDONLY, current_cred()); + filp = dentry_open(path, O_RDONLY, current_cred()); if (IS_ERR(filp)) { put_unused_fd(ret); - ret = PTR_ERR(filp); - goto out; + return PTR_ERR(filp); } filp->f_op = &spufs_context_fops; fd_install(ret, filp); -out: return ret; } @@ -453,29 +448,26 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, int affinity; struct spu_gang *gang; struct spu_context *neighbor; + struct path path = {.mnt = mnt, .dentry = dentry}; - ret = -EPERM; if ((flags & SPU_CREATE_NOSCHED) && !capable(CAP_SYS_NICE)) - goto out_unlock; + return -EPERM; - ret = -EINVAL; if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE)) == SPU_CREATE_ISOLATE) - goto out_unlock; + return -EINVAL; - ret = -ENODEV; if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader) - goto out_unlock; + return -ENODEV; gang = NULL; neighbor = NULL; affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU); if (affinity) { gang = SPUFS_I(inode)->i_gang; - ret = -EINVAL; if (!gang) - goto out_unlock; + return -EINVAL; mutex_lock(&gang->aff_mutex); neighbor = spufs_assert_affinity(flags, gang, aff_filp); if (IS_ERR(neighbor)) { @@ -495,27 +487,13 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, put_spu_context(neighbor); } - /* - * get references for dget and mntget, will be released - * in error path of *_open(). - */ - ret = spufs_context_open(dget(dentry), mntget(mnt)); - if (ret < 0) { + ret = spufs_context_open(&path); + if (ret < 0) WARN_ON(spufs_rmdir(inode, dentry)); - if (affinity) - mutex_unlock(&gang->aff_mutex); - mutex_unlock(&inode->i_mutex); - spu_forget(SPUFS_I(dentry->d_inode)->i_ctx); - goto out; - } out_aff_unlock: if (affinity) mutex_unlock(&gang->aff_mutex); -out_unlock: - mutex_unlock(&inode->i_mutex); -out: - dput(dentry); return ret; } @@ -556,28 +534,27 @@ out: return ret; } -static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) +static int spufs_gang_open(struct path *path) { int ret; struct file *filp; ret = get_unused_fd(); - if (ret < 0) { - dput(dentry); - mntput(mnt); - goto out; - } + if (ret < 0) + return ret; - filp = dentry_open(dentry, mnt, O_RDONLY, current_cred()); + /* + * get references for dget and mntget, will be released + * in error path of *_open(). + */ + filp = dentry_open(path, O_RDONLY, current_cred()); if (IS_ERR(filp)) { put_unused_fd(ret); - ret = PTR_ERR(filp); - goto out; + return PTR_ERR(filp); } filp->f_op = &simple_dir_operations; fd_install(ret, filp); -out: return ret; } @@ -585,25 +562,17 @@ static int spufs_create_gang(struct inode *inode, struct dentry *dentry, struct vfsmount *mnt, umode_t mode) { + struct path path = {.mnt = mnt, .dentry = dentry}; int ret; ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); - if (ret) - goto out; - - /* - * get references for dget and mntget, will be released - * in error path of *_open(). - */ - ret = spufs_gang_open(dget(dentry), mntget(mnt)); - if (ret < 0) { - int err = simple_rmdir(inode, dentry); - WARN_ON(err); + if (!ret) { + ret = spufs_gang_open(&path); + if (ret < 0) { + int err = simple_rmdir(inode, dentry); + WARN_ON(err); + } } - -out: - mutex_unlock(&inode->i_mutex); - dput(dentry); return ret; } @@ -613,40 +582,32 @@ static struct file_system_type spufs_type; long spufs_create(struct path *path, struct dentry *dentry, unsigned int flags, umode_t mode, struct file *filp) { + struct inode *dir = path->dentry->d_inode; int ret; - ret = -EINVAL; /* check if we are on spufs */ if (path->dentry->d_sb->s_type != &spufs_type) - goto out; + return -EINVAL; /* don't accept undefined flags */ if (flags & (~SPU_CREATE_FLAG_ALL)) - goto out; + return -EINVAL; /* only threads can be underneath a gang */ - if (path->dentry != path->dentry->d_sb->s_root) { - if ((flags & SPU_CREATE_GANG) || - !SPUFS_I(path->dentry->d_inode)->i_gang) - goto out; - } + if (path->dentry != path->dentry->d_sb->s_root) + if ((flags & SPU_CREATE_GANG) || !SPUFS_I(dir)->i_gang) + return -EINVAL; mode &= ~current_umask(); if (flags & SPU_CREATE_GANG) - ret = spufs_create_gang(path->dentry->d_inode, - dentry, path->mnt, mode); + ret = spufs_create_gang(dir, dentry, path->mnt, mode); else - ret = spufs_create_context(path->dentry->d_inode, - dentry, path->mnt, flags, mode, + ret = spufs_create_context(dir, dentry, path->mnt, flags, mode, filp); if (ret >= 0) - fsnotify_mkdir(path->dentry->d_inode, dentry); - return ret; + fsnotify_mkdir(dir, dentry); -out: - mutex_unlock(&path->dentry->d_inode->i_mutex); - dput(dentry); return ret; } diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c index 5665dcc382c7..5b7d8ffbf890 100644 --- a/arch/powerpc/platforms/cell/spufs/syscalls.c +++ b/arch/powerpc/platforms/cell/spufs/syscalls.c @@ -70,7 +70,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags, ret = PTR_ERR(dentry); if (!IS_ERR(dentry)) { ret = spufs_create(&path, dentry, flags, mode, neighbor); - path_put(&path); + done_path_create(&path, dentry); } return ret; diff --git a/arch/powerpc/platforms/powernv/opal-takeover.S b/arch/powerpc/platforms/powernv/opal-takeover.S index 77b48b2b9309..3cd262897c27 100644 --- a/arch/powerpc/platforms/powernv/opal-takeover.S +++ b/arch/powerpc/platforms/powernv/opal-takeover.S @@ -14,8 +14,6 @@ #include <asm/asm-offsets.h> #include <asm/opal.h> -#define STK_PARAM(i) (48 + ((i)-3)*8) - #define H_HAL_TAKEOVER 0x5124 #define H_HAL_TAKEOVER_QUERY_MAGIC -1 @@ -23,14 +21,14 @@ _GLOBAL(opal_query_takeover) mfcr r0 stw r0,8(r1) - std r3,STK_PARAM(r3)(r1) - std r4,STK_PARAM(r4)(r1) + std r3,STK_PARAM(R3)(r1) + std r4,STK_PARAM(R4)(r1) li r3,H_HAL_TAKEOVER li r4,H_HAL_TAKEOVER_QUERY_MAGIC HVSC - ld r10,STK_PARAM(r3)(r1) + ld r10,STK_PARAM(R3)(r1) std r4,0(r10) - ld r10,STK_PARAM(r4)(r1) + ld r10,STK_PARAM(R4)(r1) std r5,0(r10) lwz r0,8(r1) mtcrf 0xff,r0 diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index fbdd74dac3ac..9cda6a1ad0cf 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb, dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER; fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER; parent = pe->pbus->self; - count = pe->pbus->subordinate - pe->pbus->secondary + 1; + count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1; switch(count) { case 1: bcomp = OpalPciBusAll; break; case 2: bcomp = OpalPciBus7Bits; break; @@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev, pe->pdev = NULL; pe->tce32_seg = -1; pe->mve_number = -1; - pe->rid = bus->secondary << 8; + pe->rid = bus->busn_res.start << 8; pe->dma_weight = 0; - pe_info(pe, "Secondary busses %d..%d associated with PE\n", - bus->secondary, bus->subordinate); + pe_info(pe, "Secondary busses %pR associated with PE\n", + &bus->busn_res); if (pnv_ioda_configure_pe(phb, pe)) { /* XXX What do we do here ? */ diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 4cb375c0f8d1..fb506317ebb0 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -85,8 +85,10 @@ static int eeh_event_handler(void * dummy) set_current_state(TASK_INTERRUPTIBLE); /* Don't add to load average */ edev = handle_eeh_events(event); - eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); - pci_dev_put(edev->pdev); + if (edev) { + eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); + pci_dev_put(edev->pdev); + } kfree(event); mutex_unlock(&eeh_event_mutex); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 8752f79a6af8..c33360ec4f4f 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -81,7 +81,7 @@ static int pseries_eeh_init(void) ibm_get_config_addr_info2 = rtas_token("ibm,get-config-addr-info2"); ibm_get_config_addr_info = rtas_token("ibm,get-config-addr-info"); ibm_configure_pe = rtas_token("ibm,configure-pe"); - ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); + ibm_configure_bridge = rtas_token("ibm,configure-bridge"); /* necessary sanity check */ if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { @@ -89,7 +89,7 @@ static int pseries_eeh_init(void) __func__); return -EINVAL; } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) { - pr_warning("%s: RTAS service <ibm, set-slot-reset> invalid\n", + pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n", __func__); return -EINVAL; } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 3ce73d0052b1..444fe7759e55 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S @@ -13,8 +13,6 @@ #include <asm/asm-offsets.h> #include <asm/ptrace.h> -#define STK_PARM(i) (48 + ((i)-3)*8) - #ifdef CONFIG_TRACEPOINTS .section ".toc","aw" @@ -26,7 +24,7 @@ hcall_tracepoint_refcount: .section ".text" /* - * precall must preserve all registers. use unused STK_PARM() + * precall must preserve all registers. use unused STK_PARAM() * areas to save snapshots and opcode. We branch around this * in early init (eg when populating the MMU hashtable) by using an * unconditional cpu feature. @@ -40,28 +38,28 @@ END_FTR_SECTION(0, 1); \ cmpdi r12,0; \ beq+ 1f; \ mflr r0; \ - std r3,STK_PARM(r3)(r1); \ - std r4,STK_PARM(r4)(r1); \ - std r5,STK_PARM(r5)(r1); \ - std r6,STK_PARM(r6)(r1); \ - std r7,STK_PARM(r7)(r1); \ - std r8,STK_PARM(r8)(r1); \ - std r9,STK_PARM(r9)(r1); \ - std r10,STK_PARM(r10)(r1); \ + std r3,STK_PARAM(R3)(r1); \ + std r4,STK_PARAM(R4)(r1); \ + std r5,STK_PARAM(R5)(r1); \ + std r6,STK_PARAM(R6)(r1); \ + std r7,STK_PARAM(R7)(r1); \ + std r8,STK_PARAM(R8)(r1); \ + std r9,STK_PARAM(R9)(r1); \ + std r10,STK_PARAM(R10)(r1); \ std r0,16(r1); \ - addi r4,r1,STK_PARM(FIRST_REG); \ + addi r4,r1,STK_PARAM(FIRST_REG); \ stdu r1,-STACK_FRAME_OVERHEAD(r1); \ bl .__trace_hcall_entry; \ addi r1,r1,STACK_FRAME_OVERHEAD; \ ld r0,16(r1); \ - ld r3,STK_PARM(r3)(r1); \ - ld r4,STK_PARM(r4)(r1); \ - ld r5,STK_PARM(r5)(r1); \ - ld r6,STK_PARM(r6)(r1); \ - ld r7,STK_PARM(r7)(r1); \ - ld r8,STK_PARM(r8)(r1); \ - ld r9,STK_PARM(r9)(r1); \ - ld r10,STK_PARM(r10)(r1); \ + ld r3,STK_PARAM(R3)(r1); \ + ld r4,STK_PARAM(R4)(r1); \ + ld r5,STK_PARAM(R5)(r1); \ + ld r6,STK_PARAM(R6)(r1); \ + ld r7,STK_PARAM(R7)(r1); \ + ld r8,STK_PARAM(R8)(r1); \ + ld r9,STK_PARAM(R9)(r1); \ + ld r10,STK_PARAM(R10)(r1); \ mtlr r0; \ 1: @@ -79,8 +77,8 @@ END_FTR_SECTION(0, 1); \ cmpdi r12,0; \ beq+ 1f; \ mflr r0; \ - ld r6,STK_PARM(r3)(r1); \ - std r3,STK_PARM(r3)(r1); \ + ld r6,STK_PARAM(R3)(r1); \ + std r3,STK_PARAM(R3)(r1); \ mr r4,r3; \ mr r3,r6; \ std r0,16(r1); \ @@ -88,7 +86,7 @@ END_FTR_SECTION(0, 1); \ bl .__trace_hcall_exit; \ addi r1,r1,STACK_FRAME_OVERHEAD; \ ld r0,16(r1); \ - ld r3,STK_PARM(r3)(r1); \ + ld r3,STK_PARAM(R3)(r1); \ mtlr r0; \ 1: @@ -114,7 +112,7 @@ _GLOBAL(plpar_hcall_norets) mfcr r0 stw r0,8(r1) - HCALL_INST_PRECALL(r4) + HCALL_INST_PRECALL(R4) HVSC /* invoke the hypervisor */ @@ -130,9 +128,9 @@ _GLOBAL(plpar_hcall) mfcr r0 stw r0,8(r1) - HCALL_INST_PRECALL(r5) + HCALL_INST_PRECALL(R5) - std r4,STK_PARM(r4)(r1) /* Save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ mr r4,r5 mr r5,r6 @@ -143,7 +141,7 @@ _GLOBAL(plpar_hcall) HVSC /* invoke the hypervisor */ - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -168,7 +166,7 @@ _GLOBAL(plpar_hcall_raw) mfcr r0 stw r0,8(r1) - std r4,STK_PARM(r4)(r1) /* Save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ mr r4,r5 mr r5,r6 @@ -179,7 +177,7 @@ _GLOBAL(plpar_hcall_raw) HVSC /* invoke the hypervisor */ - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -196,9 +194,9 @@ _GLOBAL(plpar_hcall9) mfcr r0 stw r0,8(r1) - HCALL_INST_PRECALL(r5) + HCALL_INST_PRECALL(R5) - std r4,STK_PARM(r4)(r1) /* Save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ mr r4,r5 mr r5,r6 @@ -206,14 +204,14 @@ _GLOBAL(plpar_hcall9) mr r7,r8 mr r8,r9 mr r9,r10 - ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ - ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ - ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ + ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ + ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ + ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ HVSC /* invoke the hypervisor */ mr r0,r12 - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) @@ -238,7 +236,7 @@ _GLOBAL(plpar_hcall9_raw) mfcr r0 stw r0,8(r1) - std r4,STK_PARM(r4)(r1) /* Save ret buffer */ + std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ mr r4,r5 mr r5,r6 @@ -246,14 +244,14 @@ _GLOBAL(plpar_hcall9_raw) mr r7,r8 mr r8,r9 mr r9,r10 - ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ - ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ - ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ + ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ + ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ + ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ HVSC /* invoke the hypervisor */ mr r0,r12 - ld r12,STK_PARM(r4)(r1) + ld r12,STK_PARAM(R4)(r1) std r4, 0(r12) std r5, 8(r12) std r6, 16(r12) diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 2d311c0caf8e..bca220f2873c 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -192,12 +192,15 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long l, limit; long tcenum_start = tcenum, npages_start = npages; int ret = 0; + unsigned long flags; if (npages == 1) { return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction, attrs); } + local_irq_save(flags); /* to protect tcep and the page behind it */ + tcep = __get_cpu_var(tce_page); /* This is safe to do since interrupts are off when we're called @@ -207,6 +210,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, tcep = (u64 *)__get_free_page(GFP_ATOMIC); /* If allocation fails, fall back to the loop implementation */ if (!tcep) { + local_irq_restore(flags); return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction, attrs); } @@ -240,6 +244,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, tcenum += limit; } while (npages > 0 && !rc); + local_irq_restore(flags); + if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { ret = (int)rc; tce_freemulti_pSeriesLP(tbl, tcenum_start, @@ -707,6 +713,21 @@ static int __init disable_ddw_setup(char *str) early_param("disable_ddw", disable_ddw_setup); +static inline void __remove_ddw(struct device_node *np, const u32 *ddw_avail, u64 liobn) +{ + int ret; + + ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn); + if (ret) + pr_warning("%s: failed to remove DMA window: rtas returned " + "%d to ibm,remove-pe-dma-window(%x) %llx\n", + np->full_name, ret, ddw_avail[2], liobn); + else + pr_debug("%s: successfully removed DMA window: rtas returned " + "%d to ibm,remove-pe-dma-window(%x) %llx\n", + np->full_name, ret, ddw_avail[2], liobn); +} + static void remove_ddw(struct device_node *np) { struct dynamic_dma_window_prop *dwp; @@ -736,15 +757,7 @@ static void remove_ddw(struct device_node *np) pr_debug("%s successfully cleared tces in window.\n", np->full_name); - ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn); - if (ret) - pr_warning("%s: failed to remove direct window: rtas returned " - "%d to ibm,remove-pe-dma-window(%x) %llx\n", - np->full_name, ret, ddw_avail[2], liobn); - else - pr_debug("%s: successfully removed direct window: rtas returned " - "%d to ibm,remove-pe-dma-window(%x) %llx\n", - np->full_name, ret, ddw_avail[2], liobn); + __remove_ddw(np, ddw_avail, liobn); delprop: ret = prom_remove_property(np, win64); @@ -869,6 +882,35 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail, return ret; } +static void restore_default_window(struct pci_dev *dev, + u32 ddw_restore_token, unsigned long liobn) +{ + struct eeh_dev *edev; + u32 cfg_addr; + u64 buid; + int ret; + + /* + * Get the config address and phb buid of the PE window. + * Rely on eeh to retrieve this for us. + * Retrieve them from the pci device, not the node with the + * dma-window property + */ + edev = pci_dev_to_eeh_dev(dev); + cfg_addr = edev->config_addr; + if (edev->pe_config_addr) + cfg_addr = edev->pe_config_addr; + buid = edev->phb->buid; + + do { + ret = rtas_call(ddw_restore_token, 3, 1, NULL, cfg_addr, + BUID_HI(buid), BUID_LO(buid)); + } while (rtas_busy_delay(ret)); + dev_info(&dev->dev, + "ibm,reset-pe-dma-windows(%x) %x %x %x returned %d\n", + ddw_restore_token, cfg_addr, BUID_HI(buid), BUID_LO(buid), ret); +} + /* * If the PE supports dynamic dma windows, and there is space for a table * that can map all pages in a linear offset, then setup such a table, @@ -889,9 +931,13 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) u64 dma_addr, max_addr; struct device_node *dn; const u32 *uninitialized_var(ddw_avail); + const u32 *uninitialized_var(ddw_extensions); + u32 ddw_restore_token = 0; struct direct_window *window; struct property *win64; struct dynamic_dma_window_prop *ddwprop; + const void *dma_window = NULL; + unsigned long liobn, offset, size; mutex_lock(&direct_window_init_mutex); @@ -911,7 +957,40 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) if (!ddw_avail || len < 3 * sizeof(u32)) goto out_unlock; - /* + /* + * the extensions property is only required to exist in certain + * levels of firmware and later + * the ibm,ddw-extensions property is a list with the first + * element containing the number of extensions and each + * subsequent entry is a value corresponding to that extension + */ + ddw_extensions = of_get_property(pdn, "ibm,ddw-extensions", &len); + if (ddw_extensions) { + /* + * each new defined extension length should be added to + * the top of the switch so the "earlier" entries also + * get picked up + */ + switch (ddw_extensions[0]) { + /* ibm,reset-pe-dma-windows */ + case 1: + ddw_restore_token = ddw_extensions[1]; + break; + } + } + + /* + * Only remove the existing DMA window if we can restore back to + * the default state. Removing the existing window maximizes the + * resources available to firmware for dynamic window creation. + */ + if (ddw_restore_token) { + dma_window = of_get_property(pdn, "ibm,dma-window", NULL); + of_parse_dma_window(pdn, dma_window, &liobn, &offset, &size); + __remove_ddw(pdn, ddw_avail, liobn); + } + + /* * Query if there is a second window of size to map the * whole partition. Query returns number of windows, largest * block assigned to PE (partition endpoint), and two bitmasks @@ -920,7 +999,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) dn = pci_device_to_OF_node(dev); ret = query_ddw(dev, ddw_avail, &query); if (ret != 0) - goto out_unlock; + goto out_restore_window; if (query.windows_available == 0) { /* @@ -929,7 +1008,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) * trading in for a larger page size. */ dev_dbg(&dev->dev, "no free dynamic windows"); - goto out_unlock; + goto out_restore_window; } if (query.page_size & 4) { page_shift = 24; /* 16MB */ @@ -940,7 +1019,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) } else { dev_dbg(&dev->dev, "no supported direct page size in mask %x", query.page_size); - goto out_unlock; + goto out_restore_window; } /* verify the window * number of ptes will map the partition */ /* check largest block * page size > max memory hotplug addr */ @@ -949,14 +1028,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " "%llu-sized pages\n", max_addr, query.largest_available_block, 1ULL << page_shift); - goto out_unlock; + goto out_restore_window; } len = order_base_2(max_addr); win64 = kzalloc(sizeof(struct property), GFP_KERNEL); if (!win64) { dev_info(&dev->dev, "couldn't allocate property for 64bit dma window\n"); - goto out_unlock; + goto out_restore_window; } win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL); win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL); @@ -1018,6 +1097,10 @@ out_free_prop: kfree(win64->value); kfree(win64); +out_restore_window: + if (ddw_restore_token) + restore_default_window(dev, ddw_restore_token, liobn); + out_unlock: mutex_unlock(&direct_window_init_mutex); return dma_addr; @@ -1051,7 +1134,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev) if (!pdn || !PCI_DN(pdn)) { printk(KERN_WARNING "pci_dma_dev_setup_pSeriesLP: " "no DMA window found for pci dev=%s dn=%s\n", - pci_name(dev), dn? dn->full_name : "<null>"); + pci_name(dev), of_node_full_name(dn)); return; } pr_debug(" parent is %s\n", pdn->full_name); diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index 029a562af373..dd30b12edfe4 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -67,7 +67,6 @@ static int update_dt_property(struct device_node *dn, struct property **prop, const char *name, u32 vd, char *value) { struct property *new_prop = *prop; - struct property *old_prop; int more = 0; /* A negative 'vd' value indicates that only part of the new property @@ -117,12 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop, } if (!more) { - old_prop = of_find_property(dn, new_prop->name, NULL); - if (old_prop) - prom_update_property(dn, new_prop, old_prop); - else - prom_add_property(dn, new_prop); - + prom_update_property(dn, new_prop); new_prop = NULL; } diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 8b7bafa489c2..3ccebc83dc02 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c @@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) if (!num) return; pcibios_setup_bus_devices(bus); - max = bus->secondary; + max = bus->busn_res.start; for (pass=0; pass < 2; pass++) list_for_each_entry(dev, &bus->devices, bus_list) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || diff --git a/arch/powerpc/platforms/pseries/processor_idle.c b/arch/powerpc/platforms/pseries/processor_idle.c index c71be66bd5dc..455760b1fe6e 100644 --- a/arch/powerpc/platforms/pseries/processor_idle.c +++ b/arch/powerpc/platforms/pseries/processor_idle.c @@ -11,6 +11,7 @@ #include <linux/moduleparam.h> #include <linux/cpuidle.h> #include <linux/cpu.h> +#include <linux/notifier.h> #include <asm/paca.h> #include <asm/reg.h> @@ -189,17 +190,40 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = { .enter = &shared_cede_loop }, }; -int pseries_notify_cpuidle_add_cpu(int cpu) +static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, + unsigned long action, void *hcpu) { + int hotcpu = (unsigned long)hcpu; struct cpuidle_device *dev = - per_cpu_ptr(pseries_cpuidle_devices, cpu); + per_cpu_ptr(pseries_cpuidle_devices, hotcpu); + if (dev && cpuidle_get_driver()) { - cpuidle_disable_device(dev); - cpuidle_enable_device(dev); + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + cpuidle_pause_and_lock(); + cpuidle_enable_device(dev); + cpuidle_resume_and_unlock(); + break; + + case CPU_DEAD: + case CPU_DEAD_FROZEN: + cpuidle_pause_and_lock(); + cpuidle_disable_device(dev); + cpuidle_resume_and_unlock(); + break; + + default: + return NOTIFY_DONE; + } } - return 0; + return NOTIFY_OK; } +static struct notifier_block setup_hotplug_notifier = { + .notifier_call = pseries_cpuidle_add_cpu_notifier, +}; + /* * pseries_cpuidle_driver_init() */ @@ -324,6 +348,7 @@ static int __init pseries_processor_idle_init(void) return retval; } + register_cpu_notifier(&setup_hotplug_notifier); printk(KERN_DEBUG "pseries_idle_driver registered\n"); return 0; @@ -332,6 +357,7 @@ static int __init pseries_processor_idle_init(void) static void __exit pseries_processor_idle_exit(void) { + unregister_cpu_notifier(&setup_hotplug_notifier); pseries_idle_devices_uninit(); cpuidle_unregister_driver(&pseries_idle_driver); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 7b3bf76ef834..39f71fba9b38 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -432,7 +432,7 @@ static int do_update_property(char *buf, size_t bufsize) unsigned char *value; char *name, *end, *next_prop; int rc, length; - struct property *newprop, *oldprop; + struct property *newprop; buf = parse_node(buf, bufsize, &np); end = buf + bufsize; @@ -443,6 +443,9 @@ static int do_update_property(char *buf, size_t bufsize) if (!next_prop) return -EINVAL; + if (!strlen(name)) + return -ENODEV; + newprop = new_property(name, length, value, NULL); if (!newprop) return -ENOMEM; @@ -450,18 +453,11 @@ static int do_update_property(char *buf, size_t bufsize) if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size")) slb_set_size(*(int *)value); - oldprop = of_find_property(np, name,NULL); - if (!oldprop) { - if (strlen(name)) - return prom_add_property(np, newprop); - return -ENODEV; - } - upd_value.node = np; upd_value.property = newprop; pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value); - rc = prom_update_property(np, newprop, oldprop); + rc = prom_update_property(np, newprop); if (rc) return rc; @@ -486,7 +482,7 @@ static int do_update_property(char *buf, size_t bufsize) rc = pSeries_reconfig_notify(action, value); if (rc) { - prom_update_property(np, oldprop, newprop); + prom_update_property(np, newprop); return rc; } } diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index e16bb8d48550..71706bc34a0d 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -147,7 +147,6 @@ static void __devinit smp_xics_setup_cpu(int cpu) set_cpu_current_state(cpu, CPU_STATE_ONLINE); set_default_offline_state(cpu); #endif - pseries_notify_cpuidle_add_cpu(cpu); } static int __devinit smp_pSeries_kick_cpu(int nr) |