aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/sysdev
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r--arch/powerpc/sysdev/Kconfig10
-rw-r--r--arch/powerpc/sysdev/Makefile2
-rw-r--r--arch/powerpc/sysdev/axonram.c21
-rw-r--r--arch/powerpc/sysdev/cpm2_pic.c1
-rw-r--r--arch/powerpc/sysdev/cpm_common.c1
-rw-r--r--arch/powerpc/sysdev/dart_iommu.c6
-rw-r--r--arch/powerpc/sysdev/dcr.c6
-rw-r--r--arch/powerpc/sysdev/ehv_pic.c11
-rw-r--r--arch/powerpc/sysdev/fsl_gtm.c11
-rw-r--r--arch/powerpc/sysdev/fsl_ifc.c306
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c31
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c189
-rw-r--r--arch/powerpc/sysdev/fsl_pci.h8
-rw-r--r--arch/powerpc/sysdev/fsl_pmc.c1
-rw-r--r--arch/powerpc/sysdev/fsl_rio.c13
-rw-r--r--arch/powerpc/sysdev/fsl_rmu.c7
-rw-r--r--arch/powerpc/sysdev/fsl_soc.c32
-rw-r--r--arch/powerpc/sysdev/fsl_soc.h3
-rw-r--r--arch/powerpc/sysdev/ge/ge_pic.h1
-rw-r--r--arch/powerpc/sysdev/i8259.c1
-rw-r--r--arch/powerpc/sysdev/indirect_pci.c6
-rw-r--r--arch/powerpc/sysdev/mpc8xx_pic.c1
-rw-r--r--arch/powerpc/sysdev/mpic.c62
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c6
-rw-r--r--arch/powerpc/sysdev/mpic_msi.c8
-rw-r--r--arch/powerpc/sysdev/mpic_timer.c12
-rw-r--r--arch/powerpc/sysdev/msi_bitmap.c2
-rw-r--r--arch/powerpc/sysdev/mv64x60_dev.c4
-rw-r--r--arch/powerpc/sysdev/mv64x60_udbg.c2
-rw-r--r--arch/powerpc/sysdev/of_rtc.c1
-rw-r--r--arch/powerpc/sysdev/ppc4xx_hsta_msi.c215
-rw-r--r--arch/powerpc/sysdev/ppc4xx_ocm.c3
-rw-r--r--arch/powerpc/sysdev/ppc4xx_pci.c23
-rw-r--r--arch/powerpc/sysdev/ppc4xx_soc.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/qe_io.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_fast.c1
-rw-r--r--arch/powerpc/sysdev/qe_lib/ucc_slow.c1
-rw-r--r--arch/powerpc/sysdev/scom.c168
-rw-r--r--arch/powerpc/sysdev/udbg_memcons.c1
-rw-r--r--arch/powerpc/sysdev/xics/icp-hv.c1
-rw-r--r--arch/powerpc/sysdev/xics/icp-native.c9
-rw-r--r--arch/powerpc/sysdev/xics/ics-opal.c17
-rw-r--r--arch/powerpc/sysdev/xilinx_intc.c2
44 files changed, 665 insertions, 544 deletions
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig
index ab4cb547647..a19332a3871 100644
--- a/arch/powerpc/sysdev/Kconfig
+++ b/arch/powerpc/sysdev/Kconfig
@@ -7,6 +7,12 @@ config PPC4xx_PCI_EXPRESS
depends on PCI && 4xx
default n
+config PPC4xx_HSTA_MSI
+ bool
+ depends on PCI_MSI
+ depends on PCI && 4xx
+ default n
+
config PPC4xx_MSI
bool
depends on PCI_MSI
@@ -19,7 +25,7 @@ config PPC_MSI_BITMAP
default y if MPIC
default y if FSL_PCI
default y if PPC4xx_MSI
- default y if POWERNV_MSI
+ default y if PPC_POWERNV
source "arch/powerpc/sysdev/xics/Kconfig"
@@ -28,7 +34,7 @@ config PPC_SCOM
config SCOM_DEBUGFS
bool "Expose SCOM controllers via debugfs"
- depends on PPC_SCOM
+ depends on PPC_SCOM && DEBUG_FS
default n
config GE_FPGA
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index f67ac900d87..f7cb2a1b01f 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -21,7 +21,6 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o fsl_mpic_err.o
obj-$(CONFIG_FSL_PCI) += fsl_pci.o $(fsl-msi-obj-y)
obj-$(CONFIG_FSL_PMC) += fsl_pmc.o
obj-$(CONFIG_FSL_LBC) += fsl_lbc.o
-obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_FSL_GTM) += fsl_gtm.o
obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o
@@ -46,6 +45,7 @@ obj-$(CONFIG_OF_RTC) += of_rtc.o
ifeq ($(CONFIG_PCI),y)
obj-$(CONFIG_4xx) += ppc4xx_pci.o
endif
+obj-$(CONFIG_PPC4xx_HSTA_MSI) += ppc4xx_hsta_msi.o
obj-$(CONFIG_PPC4xx_MSI) += ppc4xx_msi.o
obj-$(CONFIG_PPC4xx_CPM) += ppc4xx_cpm.o
obj-$(CONFIG_PPC4xx_GPIO) += ppc4xx_gpio.o
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 1c16141c031..47b6b9f81d4 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -109,27 +109,28 @@ axon_ram_make_request(struct request_queue *queue, struct bio *bio)
struct axon_ram_bank *bank = bio->bi_bdev->bd_disk->private_data;
unsigned long phys_mem, phys_end;
void *user_mem;
- struct bio_vec *vec;
+ struct bio_vec vec;
unsigned int transfered;
- unsigned short idx;
+ struct bvec_iter iter;
- phys_mem = bank->io_addr + (bio->bi_sector << AXON_RAM_SECTOR_SHIFT);
+ phys_mem = bank->io_addr + (bio->bi_iter.bi_sector <<
+ AXON_RAM_SECTOR_SHIFT);
phys_end = bank->io_addr + bank->size;
transfered = 0;
- bio_for_each_segment(vec, bio, idx) {
- if (unlikely(phys_mem + vec->bv_len > phys_end)) {
+ bio_for_each_segment(vec, bio, iter) {
+ if (unlikely(phys_mem + vec.bv_len > phys_end)) {
bio_io_error(bio);
return;
}
- user_mem = page_address(vec->bv_page) + vec->bv_offset;
+ user_mem = page_address(vec.bv_page) + vec.bv_offset;
if (bio_data_dir(bio) == READ)
- memcpy(user_mem, (void *) phys_mem, vec->bv_len);
+ memcpy(user_mem, (void *) phys_mem, vec.bv_len);
else
- memcpy((void *) phys_mem, user_mem, vec->bv_len);
+ memcpy((void *) phys_mem, user_mem, vec.bv_len);
- phys_mem += vec->bv_len;
- transfered += vec->bv_len;
+ phys_mem += vec.bv_len;
+ transfered += vec.bv_len;
}
bio_endio(bio, 0);
}
diff --git a/arch/powerpc/sysdev/cpm2_pic.c b/arch/powerpc/sysdev/cpm2_pic.c
index 10386b676d8..a11bd1d433a 100644
--- a/arch/powerpc/sysdev/cpm2_pic.c
+++ b/arch/powerpc/sysdev/cpm2_pic.c
@@ -27,7 +27,6 @@
*/
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 4dd534194ae..4f786957129 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -22,6 +22,7 @@
#include <linux/spinlock.h>
#include <linux/export.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/slab.h>
#include <asm/udbg.h>
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c
index bd968a43a48..9e5353ff6d1 100644
--- a/arch/powerpc/sysdev/dart_iommu.c
+++ b/arch/powerpc/sysdev/dart_iommu.c
@@ -292,6 +292,7 @@ static void iommu_table_dart_setup(void)
iommu_table_dart.it_offset = 0;
/* it_size is in number of entries */
iommu_table_dart.it_size = dart_tablesize / sizeof(u32);
+ iommu_table_dart.it_page_shift = IOMMU_PAGE_SHIFT_4K;
/* Initialize the common IOMMU code */
iommu_table_dart.it_base = (unsigned long)dart_vbase;
@@ -475,6 +476,11 @@ void __init alloc_dart_table(void)
*/
dart_tablebase = (unsigned long)
__va(memblock_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+ /*
+ * The DART space is later unmapped from the kernel linear mapping and
+ * accessing dart_tablebase during kmemleak scanning will fault.
+ */
+ kmemleak_no_scan((void *)dart_tablebase);
printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
}
diff --git a/arch/powerpc/sysdev/dcr.c b/arch/powerpc/sysdev/dcr.c
index 1bd0eba4d35..e9056e43857 100644
--- a/arch/powerpc/sysdev/dcr.c
+++ b/arch/powerpc/sysdev/dcr.c
@@ -152,9 +152,9 @@ EXPORT_SYMBOL_GPL(dcr_resource_len);
#ifdef CONFIG_PPC_DCR_MMIO
-u64 of_translate_dcr_address(struct device_node *dev,
- unsigned int dcr_n,
- unsigned int *out_stride)
+static u64 of_translate_dcr_address(struct device_node *dev,
+ unsigned int dcr_n,
+ unsigned int *out_stride)
{
struct device_node *dp;
const u32 *p;
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c
index 9cd0e60716f..2d20f10a420 100644
--- a/arch/powerpc/sysdev/ehv_pic.c
+++ b/arch/powerpc/sysdev/ehv_pic.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -27,8 +28,6 @@
#include <asm/ehv_pic.h>
#include <asm/fsl_hcalls.h>
-#include "../../../kernel/irq/settings.h"
-
static struct ehv_pic *global_ehv_pic;
static DEFINE_SPINLOCK(ehv_pic_lock);
@@ -112,17 +111,13 @@ static unsigned int ehv_pic_type_to_vecpri(unsigned int type)
int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
{
unsigned int src = virq_to_hw(d->irq);
- struct irq_desc *desc = irq_to_desc(d->irq);
unsigned int vecpri, vold, vnew, prio, cpu_dest;
unsigned long flags;
if (flow_type == IRQ_TYPE_NONE)
flow_type = IRQ_TYPE_LEVEL_LOW;
- irq_settings_clr_level(desc);
- irq_settings_set_trigger_mask(desc, flow_type);
- if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- irq_settings_set_level(desc);
+ irqd_set_trigger_type(d, flow_type);
vecpri = ehv_pic_type_to_vecpri(flow_type);
@@ -143,7 +138,7 @@ int ehv_pic_set_irq_type(struct irq_data *d, unsigned int flow_type)
ev_int_set_config(src, vecpri, prio, cpu_dest);
spin_unlock_irqrestore(&ehv_pic_lock, flags);
- return 0;
+ return IRQ_SET_MASK_OK_NOCOPY;
}
static struct irq_chip ehv_pic_irq_chip = {
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c
index 0eb871cc343..06ac3c61b3d 100644
--- a/arch/powerpc/sysdev/fsl_gtm.c
+++ b/arch/powerpc/sysdev/fsl_gtm.c
@@ -19,6 +19,8 @@
#include <linux/list.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <linux/bitops.h>
#include <linux/slab.h>
@@ -401,16 +403,15 @@ static int __init fsl_gtm_init(void)
gtm->clock = *clock;
for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) {
- int ret;
- struct resource irq;
+ unsigned int irq;
- ret = of_irq_to_resource(np, i, &irq);
- if (ret == NO_IRQ) {
+ irq = irq_of_parse_and_map(np, i);
+ if (irq == NO_IRQ) {
pr_err("%s: not enough interrupts specified\n",
np->full_name);
goto err;
}
- gtm->timers[i].irq = irq.start;
+ gtm->timers[i].irq = irq;
gtm->timers[i].gtm = gtm;
}
diff --git a/arch/powerpc/sysdev/fsl_ifc.c b/arch/powerpc/sysdev/fsl_ifc.c
deleted file mode 100644
index d7fc7223914..00000000000
--- a/arch/powerpc/sysdev/fsl_ifc.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc
- *
- * Freescale Integrated Flash Controller
- *
- * Author: Dipen Dudhat <Dipen.Dudhat@freescale.com>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/compiler.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <asm/prom.h>
-#include <asm/fsl_ifc.h>
-
-struct fsl_ifc_ctrl *fsl_ifc_ctrl_dev;
-EXPORT_SYMBOL(fsl_ifc_ctrl_dev);
-
-/*
- * convert_ifc_address - convert the base address
- * @addr_base: base address of the memory bank
- */
-unsigned int convert_ifc_address(phys_addr_t addr_base)
-{
- return addr_base & CSPR_BA;
-}
-EXPORT_SYMBOL(convert_ifc_address);
-
-/*
- * fsl_ifc_find - find IFC bank
- * @addr_base: base address of the memory bank
- *
- * This function walks IFC banks comparing "Base address" field of the CSPR
- * registers with the supplied addr_base argument. When bases match this
- * function returns bank number (starting with 0), otherwise it returns
- * appropriate errno value.
- */
-int fsl_ifc_find(phys_addr_t addr_base)
-{
- int i = 0;
-
- if (!fsl_ifc_ctrl_dev || !fsl_ifc_ctrl_dev->regs)
- return -ENODEV;
-
- for (i = 0; i < ARRAY_SIZE(fsl_ifc_ctrl_dev->regs->cspr_cs); i++) {
- u32 cspr = in_be32(&fsl_ifc_ctrl_dev->regs->cspr_cs[i].cspr);
- if (cspr & CSPR_V && (cspr & CSPR_BA) ==
- convert_ifc_address(addr_base))
- return i;
- }
-
- return -ENOENT;
-}
-EXPORT_SYMBOL(fsl_ifc_find);
-
-static int fsl_ifc_ctrl_init(struct fsl_ifc_ctrl *ctrl)
-{
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
-
- /*
- * Clear all the common status and event registers
- */
- if (in_be32(&ifc->cm_evter_stat) & IFC_CM_EVTER_STAT_CSER)
- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
- /* enable all error and events */
- out_be32(&ifc->cm_evter_en, IFC_CM_EVTER_EN_CSEREN);
-
- /* enable all error and event interrupts */
- out_be32(&ifc->cm_evter_intr_en, IFC_CM_EVTER_INTR_EN_CSERIREN);
- out_be32(&ifc->cm_erattr0, 0x0);
- out_be32(&ifc->cm_erattr1, 0x0);
-
- return 0;
-}
-
-static int fsl_ifc_ctrl_remove(struct platform_device *dev)
-{
- struct fsl_ifc_ctrl *ctrl = dev_get_drvdata(&dev->dev);
-
- free_irq(ctrl->nand_irq, ctrl);
- free_irq(ctrl->irq, ctrl);
-
- irq_dispose_mapping(ctrl->nand_irq);
- irq_dispose_mapping(ctrl->irq);
-
- iounmap(ctrl->regs);
-
- dev_set_drvdata(&dev->dev, NULL);
- kfree(ctrl);
-
- return 0;
-}
-
-/*
- * NAND events are split between an operational interrupt which only
- * receives OPC, and an error interrupt that receives everything else,
- * including non-NAND errors. Whichever interrupt gets to it first
- * records the status and wakes the wait queue.
- */
-static DEFINE_SPINLOCK(nand_irq_lock);
-
-static u32 check_nand_stat(struct fsl_ifc_ctrl *ctrl)
-{
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
- unsigned long flags;
- u32 stat;
-
- spin_lock_irqsave(&nand_irq_lock, flags);
-
- stat = in_be32(&ifc->ifc_nand.nand_evter_stat);
- if (stat) {
- out_be32(&ifc->ifc_nand.nand_evter_stat, stat);
- ctrl->nand_stat = stat;
- wake_up(&ctrl->nand_wait);
- }
-
- spin_unlock_irqrestore(&nand_irq_lock, flags);
-
- return stat;
-}
-
-static irqreturn_t fsl_ifc_nand_irq(int irqno, void *data)
-{
- struct fsl_ifc_ctrl *ctrl = data;
-
- if (check_nand_stat(ctrl))
- return IRQ_HANDLED;
-
- return IRQ_NONE;
-}
-
-/*
- * NOTE: This interrupt is used to report ifc events of various kinds,
- * such as transaction errors on the chipselects.
- */
-static irqreturn_t fsl_ifc_ctrl_irq(int irqno, void *data)
-{
- struct fsl_ifc_ctrl *ctrl = data;
- struct fsl_ifc_regs __iomem *ifc = ctrl->regs;
- u32 err_axiid, err_srcid, status, cs_err, err_addr;
- irqreturn_t ret = IRQ_NONE;
-
- /* read for chip select error */
- cs_err = in_be32(&ifc->cm_evter_stat);
- if (cs_err) {
- dev_err(ctrl->dev, "transaction sent to IFC is not mapped to"
- "any memory bank 0x%08X\n", cs_err);
- /* clear the chip select error */
- out_be32(&ifc->cm_evter_stat, IFC_CM_EVTER_STAT_CSER);
-
- /* read error attribute registers print the error information */
- status = in_be32(&ifc->cm_erattr0);
- err_addr = in_be32(&ifc->cm_erattr1);
-
- if (status & IFC_CM_ERATTR0_ERTYP_READ)
- dev_err(ctrl->dev, "Read transaction error"
- "CM_ERATTR0 0x%08X\n", status);
- else
- dev_err(ctrl->dev, "Write transaction error"
- "CM_ERATTR0 0x%08X\n", status);
-
- err_axiid = (status & IFC_CM_ERATTR0_ERAID) >>
- IFC_CM_ERATTR0_ERAID_SHIFT;
- dev_err(ctrl->dev, "AXI ID of the error"
- "transaction 0x%08X\n", err_axiid);
-
- err_srcid = (status & IFC_CM_ERATTR0_ESRCID) >>
- IFC_CM_ERATTR0_ESRCID_SHIFT;
- dev_err(ctrl->dev, "SRC ID of the error"
- "transaction 0x%08X\n", err_srcid);
-
- dev_err(ctrl->dev, "Transaction Address corresponding to error"
- "ERADDR 0x%08X\n", err_addr);
-
- ret = IRQ_HANDLED;
- }
-
- if (check_nand_stat(ctrl))
- ret = IRQ_HANDLED;
-
- return ret;
-}
-
-/*
- * fsl_ifc_ctrl_probe
- *
- * called by device layer when it finds a device matching
- * one our driver can handled. This code allocates all of
- * the resources needed for the controller only. The
- * resources for the NAND banks themselves are allocated
- * in the chip probe function.
-*/
-static int fsl_ifc_ctrl_probe(struct platform_device *dev)
-{
- int ret = 0;
-
-
- dev_info(&dev->dev, "Freescale Integrated Flash Controller\n");
-
- fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL);
- if (!fsl_ifc_ctrl_dev)
- return -ENOMEM;
-
- dev_set_drvdata(&dev->dev, fsl_ifc_ctrl_dev);
-
- /* IOMAP the entire IFC region */
- fsl_ifc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
- if (!fsl_ifc_ctrl_dev->regs) {
- dev_err(&dev->dev, "failed to get memory region\n");
- ret = -ENODEV;
- goto err;
- }
-
- /* get the Controller level irq */
- fsl_ifc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
- if (fsl_ifc_ctrl_dev->irq == NO_IRQ) {
- dev_err(&dev->dev, "failed to get irq resource "
- "for IFC\n");
- ret = -ENODEV;
- goto err;
- }
-
- /* get the nand machine irq */
- fsl_ifc_ctrl_dev->nand_irq =
- irq_of_parse_and_map(dev->dev.of_node, 1);
-
- fsl_ifc_ctrl_dev->dev = &dev->dev;
-
- ret = fsl_ifc_ctrl_init(fsl_ifc_ctrl_dev);
- if (ret < 0)
- goto err;
-
- init_waitqueue_head(&fsl_ifc_ctrl_dev->nand_wait);
-
- ret = request_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_irq, IRQF_SHARED,
- "fsl-ifc", fsl_ifc_ctrl_dev);
- if (ret != 0) {
- dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_ifc_ctrl_dev->irq);
- goto err_irq;
- }
-
- if (fsl_ifc_ctrl_dev->nand_irq) {
- ret = request_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_nand_irq,
- 0, "fsl-ifc-nand", fsl_ifc_ctrl_dev);
- if (ret != 0) {
- dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_ifc_ctrl_dev->nand_irq);
- goto err_nandirq;
- }
- }
-
- return 0;
-
-err_nandirq:
- free_irq(fsl_ifc_ctrl_dev->nand_irq, fsl_ifc_ctrl_dev);
- irq_dispose_mapping(fsl_ifc_ctrl_dev->nand_irq);
-err_irq:
- free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev);
- irq_dispose_mapping(fsl_ifc_ctrl_dev->irq);
-err:
- return ret;
-}
-
-static const struct of_device_id fsl_ifc_match[] = {
- {
- .compatible = "fsl,ifc",
- },
- {},
-};
-
-static struct platform_driver fsl_ifc_ctrl_driver = {
- .driver = {
- .name = "fsl-ifc",
- .of_match_table = fsl_ifc_match,
- },
- .probe = fsl_ifc_ctrl_probe,
- .remove = fsl_ifc_ctrl_remove,
-};
-
-module_platform_driver(fsl_ifc_ctrl_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Freescale Semiconductor");
-MODULE_DESCRIPTION("Freescale Integrated Flash Controller driver");
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index 6bc5a546d49..d631022ffb4 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -214,10 +214,14 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
struct fsl_lbc_ctrl *ctrl = data;
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
u32 status;
+ unsigned long flags;
+ spin_lock_irqsave(&fsl_lbc_lock, flags);
status = in_be32(&lbc->ltesr);
- if (!status)
+ if (!status) {
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
return IRQ_NONE;
+ }
out_be32(&lbc->ltesr, LTESR_CLEAR);
out_be32(&lbc->lteatr, 0);
@@ -260,6 +264,7 @@ static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
if (status & ~LTESR_MASK)
dev_err(ctrl->dev, "Unknown error: "
"LTESR 0x%08X\n", status);
+ spin_unlock_irqrestore(&fsl_lbc_lock, flags);
return IRQ_HANDLED;
}
@@ -298,8 +303,8 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
goto err;
}
- fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
- if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
+ fsl_lbc_ctrl_dev->irq[0] = irq_of_parse_and_map(dev->dev.of_node, 0);
+ if (!fsl_lbc_ctrl_dev->irq[0]) {
dev_err(&dev->dev, "failed to get irq resource\n");
ret = -ENODEV;
goto err;
@@ -311,20 +316,34 @@ static int fsl_lbc_ctrl_probe(struct platform_device *dev)
if (ret < 0)
goto err;
- ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
+ ret = request_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_irq, 0,
"fsl-lbc", fsl_lbc_ctrl_dev);
if (ret != 0) {
dev_err(&dev->dev, "failed to install irq (%d)\n",
- fsl_lbc_ctrl_dev->irq);
- ret = fsl_lbc_ctrl_dev->irq;
+ fsl_lbc_ctrl_dev->irq[0]);
+ ret = fsl_lbc_ctrl_dev->irq[0];
goto err;
}
+ fsl_lbc_ctrl_dev->irq[1] = irq_of_parse_and_map(dev->dev.of_node, 1);
+ if (fsl_lbc_ctrl_dev->irq[1]) {
+ ret = request_irq(fsl_lbc_ctrl_dev->irq[1], fsl_lbc_ctrl_irq,
+ IRQF_SHARED, "fsl-lbc-err", fsl_lbc_ctrl_dev);
+ if (ret) {
+ dev_err(&dev->dev, "failed to install irq (%d)\n",
+ fsl_lbc_ctrl_dev->irq[1]);
+ ret = fsl_lbc_ctrl_dev->irq[1];
+ goto err1;
+ }
+ }
+
/* Enable interrupts for any detected events */
out_be32(&fsl_lbc_ctrl_dev->regs->lteir, LTEIR_ENABLE);
return 0;
+err1:
+ free_irq(fsl_lbc_ctrl_dev->irq[0], fsl_lbc_ctrl_dev);
err:
iounmap(fsl_lbc_ctrl_dev->regs);
kfree(fsl_lbc_ctrl_dev);
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index ccfb50ddfe3..4bd091a0558 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -22,10 +22,13 @@
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/bootmem.h>
#include <linux/memblock.h>
#include <linux/log2.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <linux/syscore_ops.h>
#include <linux/uaccess.h>
#include <asm/io.h>
@@ -40,12 +43,12 @@
static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
-static void quirk_fsl_pcie_header(struct pci_dev *dev)
+static void quirk_fsl_pcie_early(struct pci_dev *dev)
{
u8 hdr_type;
/* if we aren't a PCIe don't bother */
- if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
+ if (!pci_is_pcie(dev))
return;
/* if we aren't in host mode don't bother */
@@ -122,7 +125,7 @@ static int fsl_pci_dma_set_mask(struct device *dev, u64 dma_mask)
* address width of the SoC such that we can address any internal
* SoC address from across PCI if needed
*/
- if ((dev->bus == &pci_bus_type) &&
+ if ((dev_is_pci(dev)) &&
dma_mask >= DMA_BIT_MASK(MAX_PHYS_ADDR_BITS)) {
set_dma_ops(dev, &dma_direct_ops);
set_dma_offset(dev, pci64_dma_offset);
@@ -454,7 +457,7 @@ void fsl_pcibios_fixup_bus(struct pci_bus *bus)
}
}
-int __init fsl_add_bridge(struct platform_device *pdev, int is_primary)
+int fsl_add_bridge(struct platform_device *pdev, int is_primary)
{
int len;
struct pci_controller *hose;
@@ -562,7 +565,8 @@ no_bridge:
}
#endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID,
+ quirk_fsl_pcie_early);
#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
struct mpc83xx_pcie_priv {
@@ -867,6 +871,14 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
pci_bus_read_config_dword(hose->bus,
PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base);
+
+ /*
+ * For PEXCSRBAR, bit 3-0 indicate prefetchable and
+ * address type. So when getting base address, these
+ * bits should be masked
+ */
+ base &= PCI_BASE_ADDRESS_MEM_MASK;
+
return base;
}
#endif
@@ -1034,6 +1046,7 @@ static const struct of_device_id pci_ids[] = {
{ .compatible = "fsl,mpc8548-pcie", },
{ .compatible = "fsl,mpc8610-pci", },
{ .compatible = "fsl,mpc8641-pcie", },
+ { .compatible = "fsl,qoriq-pcie", },
{ .compatible = "fsl,qoriq-pcie-v2.1", },
{ .compatible = "fsl,qoriq-pcie-v2.2", },
{ .compatible = "fsl,qoriq-pcie-v2.3", },
@@ -1084,55 +1097,170 @@ void fsl_pci_assign_primary(void)
}
}
-static int fsl_pci_probe(struct platform_device *pdev)
+#ifdef CONFIG_PM_SLEEP
+static irqreturn_t fsl_pci_pme_handle(int irq, void *dev_id)
{
- int ret;
- struct device_node *node;
+ struct pci_controller *hose = dev_id;
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
- node = pdev->dev.of_node;
- ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (!dr)
+ return IRQ_NONE;
- mpc85xx_pci_err_probe(pdev);
+ out_be32(&pci->pex_pme_mes_dr, dr);
- return 0;
+ return IRQ_HANDLED;
}
-#ifdef CONFIG_PM
-static int fsl_pci_resume(struct device *dev)
+static int fsl_pci_pme_probe(struct pci_controller *hose)
{
- struct pci_controller *hose;
- struct resource pci_rsrc;
+ struct ccsr_pci __iomem *pci;
+ struct pci_dev *dev;
+ int pme_irq;
+ int res;
+ u16 pms;
- hose = pci_find_hose_for_OF_device(dev->of_node);
- if (!hose)
- return -ENODEV;
+ /* Get hose's pci_dev */
+ dev = list_first_entry(&hose->bus->devices, typeof(*dev), bus_list);
+
+ /* PME Disable */
+ pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pms);
+ pms &= ~PCI_PM_CTRL_PME_ENABLE;
+ pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pms);
+
+ pme_irq = irq_of_parse_and_map(hose->dn, 0);
+ if (!pme_irq) {
+ dev_err(&dev->dev, "Failed to map PME interrupt.\n");
+
+ return -ENXIO;
+ }
+
+ res = devm_request_irq(hose->parent, pme_irq,
+ fsl_pci_pme_handle,
+ IRQF_SHARED,
+ "[PCI] PME", hose);
+ if (res < 0) {
+ dev_err(&dev->dev, "Unable to requiest irq %d for PME\n", pme_irq);
+ irq_dispose_mapping(pme_irq);
- if (of_address_to_resource(dev->of_node, 0, &pci_rsrc)) {
- dev_err(dev, "Get pci register base failed.");
return -ENODEV;
}
- setup_pci_atmu(hose);
+ pci = hose->private_data;
+
+ /* Enable PTOD, ENL23D & EXL23D */
+ clrbits32(&pci->pex_pme_mes_disr,
+ PME_DISR_EN_PTOD | PME_DISR_EN_ENL23D | PME_DISR_EN_EXL23D);
+
+ out_be32(&pci->pex_pme_mes_ier, 0);
+ setbits32(&pci->pex_pme_mes_ier,
+ PME_DISR_EN_PTOD | PME_DISR_EN_ENL23D | PME_DISR_EN_EXL23D);
+
+ /* PME Enable */
+ pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pms);
+ pms |= PCI_PM_CTRL_PME_ENABLE;
+ pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pms);
return 0;
}
-static const struct dev_pm_ops pci_pm_ops = {
- .resume = fsl_pci_resume,
-};
+static void send_pme_turnoff_message(struct pci_controller *hose)
+{
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
+ int i;
-#define PCI_PM_OPS (&pci_pm_ops)
+ /* Send PME_Turn_Off Message Request */
+ setbits32(&pci->pex_pmcr, PEX_PMCR_PTOMR);
-#else
+ /* Wait trun off done */
+ for (i = 0; i < 150; i++) {
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (dr) {
+ out_be32(&pci->pex_pme_mes_dr, dr);
+ break;
+ }
+
+ udelay(1000);
+ }
+}
+
+static void fsl_pci_syscore_do_suspend(struct pci_controller *hose)
+{
+ send_pme_turnoff_message(hose);
+}
+
+static int fsl_pci_syscore_suspend(void)
+{
+ struct pci_controller *hose, *tmp;
-#define PCI_PM_OPS NULL
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ fsl_pci_syscore_do_suspend(hose);
+ return 0;
+}
+
+static void fsl_pci_syscore_do_resume(struct pci_controller *hose)
+{
+ struct ccsr_pci __iomem *pci = hose->private_data;
+ u32 dr;
+ int i;
+
+ /* Send Exit L2 State Message */
+ setbits32(&pci->pex_pmcr, PEX_PMCR_EXL2S);
+
+ /* Wait exit done */
+ for (i = 0; i < 150; i++) {
+ dr = in_be32(&pci->pex_pme_mes_dr);
+ if (dr) {
+ out_be32(&pci->pex_pme_mes_dr, dr);
+ break;
+ }
+
+ udelay(1000);
+ }
+
+ setup_pci_atmu(hose);
+}
+
+static void fsl_pci_syscore_resume(void)
+{
+ struct pci_controller *hose, *tmp;
+
+ list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
+ fsl_pci_syscore_do_resume(hose);
+}
+
+static struct syscore_ops pci_syscore_pm_ops = {
+ .suspend = fsl_pci_syscore_suspend,
+ .resume = fsl_pci_syscore_resume,
+};
#endif
+void fsl_pcibios_fixup_phb(struct pci_controller *phb)
+{
+#ifdef CONFIG_PM_SLEEP
+ fsl_pci_pme_probe(phb);
+#endif
+}
+
+static int fsl_pci_probe(struct platform_device *pdev)
+{
+ struct device_node *node;
+ int ret;
+
+ node = pdev->dev.of_node;
+ ret = fsl_add_bridge(pdev, fsl_pci_primary == node);
+
+ mpc85xx_pci_err_probe(pdev);
+
+ return 0;
+}
+
static struct platform_driver fsl_pci_driver = {
.driver = {
.name = "fsl-pci",
- .pm = PCI_PM_OPS,
.of_match_table = pci_ids,
},
.probe = fsl_pci_probe,
@@ -1140,6 +1268,9 @@ static struct platform_driver fsl_pci_driver = {
static int __init fsl_pci_init(void)
{
+#ifdef CONFIG_PM_SLEEP
+ register_syscore_ops(&pci_syscore_pm_ops);
+#endif
return platform_driver_register(&fsl_pci_driver);
}
arch_initcall(fsl_pci_init);
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index 8d455df5847..c1cec771d5e 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -32,6 +32,13 @@ struct platform_device;
#define PIWAR_WRITE_SNOOP 0x00005000
#define PIWAR_SZ_MASK 0x0000003f
+#define PEX_PMCR_PTOMR 0x1
+#define PEX_PMCR_EXL2S 0x2
+
+#define PME_DISR_EN_PTOD 0x00008000
+#define PME_DISR_EN_ENL23D 0x00002000
+#define PME_DISR_EN_EXL23D 0x00001000
+
/* PCI/PCI Express outbound window reg */
struct pci_outbound_window_regs {
__be32 potar; /* 0x.0 - Outbound translation address register */
@@ -111,6 +118,7 @@ struct ccsr_pci {
extern int fsl_add_bridge(struct platform_device *pdev, int is_primary);
extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
+extern void fsl_pcibios_fixup_phb(struct pci_controller *phb);
extern int mpc83xx_add_bridge(struct device_node *dev);
u64 fsl_pci_immrbar_base(struct pci_controller *hose);
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c
index 592a0f8d527..8cf4aa0e3a2 100644
--- a/arch/powerpc/sysdev/fsl_pmc.c
+++ b/arch/powerpc/sysdev/fsl_pmc.c
@@ -18,6 +18,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
struct pmc_regs {
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
index e2fb3171f41..c04b718307c 100644
--- a/arch/powerpc/sysdev/fsl_rio.c
+++ b/arch/powerpc/sysdev/fsl_rio.c
@@ -28,6 +28,8 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/delay.h>
#include <linux/slab.h>
@@ -389,8 +391,10 @@ int fsl_rio_setup(struct platform_device *dev)
ops->get_inb_message = fsl_get_inb_message;
rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
- if (!rmu_node)
+ if (!rmu_node) {
+ dev_err(&dev->dev, "No valid fsl,srio-rmu-handle property\n");
goto err_rmu;
+ }
rc = of_address_to_resource(rmu_node, 0, &rmu_regs);
if (rc) {
dev_err(&dev->dev, "Can't get %s property 'reg'\n",
@@ -411,6 +415,7 @@ int fsl_rio_setup(struct platform_device *dev)
/*set up doobell node*/
np = of_find_compatible_node(NULL, NULL, "fsl,srio-dbell-unit");
if (!np) {
+ dev_err(&dev->dev, "No fsl,srio-dbell-unit node\n");
rc = -ENODEV;
goto err_dbell;
}
@@ -439,6 +444,7 @@ int fsl_rio_setup(struct platform_device *dev)
/*set up port write node*/
np = of_find_compatible_node(NULL, NULL, "fsl,srio-port-write-unit");
if (!np) {
+ dev_err(&dev->dev, "No fsl,srio-port-write-unit node\n");
rc = -ENODEV;
goto err_pw;
}
@@ -529,6 +535,7 @@ int fsl_rio_setup(struct platform_device *dev)
sprintf(port->name, "RIO mport %d", i);
priv->dev = &dev->dev;
+ port->dev.parent = &dev->dev;
port->ops = ops;
port->priv = priv;
port->phys_efptr = 0x100;
@@ -630,14 +637,18 @@ int fsl_rio_setup(struct platform_device *dev)
return 0;
err:
kfree(pw);
+ pw = NULL;
err_pw:
kfree(dbell);
+ dbell = NULL;
err_dbell:
iounmap(rmu_regs_win);
+ rmu_regs_win = NULL;
err_rmu:
kfree(ops);
err_ops:
iounmap(rio_regs_win);
+ rio_regs_win = NULL;
err_rio_regs:
return rc;
}
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c
index 14bd5221f28..b48197ae44d 100644
--- a/arch/powerpc/sysdev/fsl_rmu.c
+++ b/arch/powerpc/sysdev/fsl_rmu.c
@@ -27,6 +27,7 @@
#include <linux/types.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -880,9 +881,9 @@ fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0,
"msg_rx", (void *)mport);
if (rc < 0) {
- dma_free_coherent(priv->dev, RIO_MSG_BUFFER_SIZE,
- rmu->msg_tx_ring.virt_buffer[i],
- rmu->msg_tx_ring.phys_buffer[i]);
+ dma_free_coherent(priv->dev,
+ rmu->msg_rx_ring.size * RIO_MAX_MSG_SIZE,
+ rmu->msg_rx_ring.virt, rmu->msg_rx_ring.phys);
goto out;
}
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 228cf91b91c..ffd1169ebaa 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -25,7 +25,6 @@
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
-#include <linux/phy_fixed.h>
#include <linux/spi/spi.h>
#include <linux/fsl_devices.h>
#include <linux/fs_enet_pd.h>
@@ -178,37 +177,6 @@ u32 get_baudrate(void)
EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */
-#ifdef CONFIG_FIXED_PHY
-static int __init of_add_fixed_phys(void)
-{
- int ret;
- struct device_node *np;
- u32 *fixed_link;
- struct fixed_phy_status status = {};
-
- for_each_node_by_name(np, "ethernet") {
- fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
- if (!fixed_link)
- continue;
-
- status.link = 1;
- status.duplex = fixed_link[1];
- status.speed = fixed_link[2];
- status.pause = fixed_link[3];
- status.asym_pause = fixed_link[4];
-
- ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
- if (ret) {
- of_node_put(np);
- return ret;
- }
- }
-
- return 0;
-}
-arch_initcall(of_add_fixed_phys);
-#endif /* CONFIG_FIXED_PHY */
-
#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
static __be32 __iomem *rstcr;
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h
index c6d00736f07..4c5a19ef4f0 100644
--- a/arch/powerpc/sysdev/fsl_soc.h
+++ b/arch/powerpc/sysdev/fsl_soc.h
@@ -21,8 +21,6 @@ struct device_node;
extern void fsl_rstcr_restart(char *cmd);
-#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
-
/* The different ports that the DIU can be connected to */
enum fsl_diu_monitor_port {
FSL_DIU_PORT_DVI, /* DVI */
@@ -43,7 +41,6 @@ struct platform_diu_data_ops {
};
extern struct platform_diu_data_ops diu_ops;
-#endif
void fsl_hv_restart(char *cmd);
void fsl_hv_halt(void);
diff --git a/arch/powerpc/sysdev/ge/ge_pic.h b/arch/powerpc/sysdev/ge/ge_pic.h
index 6149916da3f..908dbd9826b 100644
--- a/arch/powerpc/sysdev/ge/ge_pic.h
+++ b/arch/powerpc/sysdev/ge/ge_pic.h
@@ -1,7 +1,6 @@
#ifndef __GEF_PIC_H__
#define __GEF_PIC_H__
-#include <linux/init.h>
void gef_pic_cascade(unsigned int, struct irq_desc *);
unsigned int gef_pic_get_irq(void);
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
index 997df6a7ab5..45598da0b32 100644
--- a/arch/powerpc/sysdev/i8259.c
+++ b/arch/powerpc/sysdev/i8259.c
@@ -8,7 +8,6 @@
*/
#undef DEBUG
-#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
diff --git a/arch/powerpc/sysdev/indirect_pci.c b/arch/powerpc/sysdev/indirect_pci.c
index c6c8b526a4f..1f6c570d66d 100644
--- a/arch/powerpc/sysdev/indirect_pci.c
+++ b/arch/powerpc/sysdev/indirect_pci.c
@@ -152,10 +152,8 @@ static struct pci_ops indirect_pci_ops =
.write = indirect_write_config,
};
-void __init
-setup_indirect_pci(struct pci_controller* hose,
- resource_size_t cfg_addr,
- resource_size_t cfg_data, u32 flags)
+void setup_indirect_pci(struct pci_controller *hose, resource_size_t cfg_addr,
+ resource_size_t cfg_data, u32 flags)
{
resource_size_t base = cfg_addr & PAGE_MASK;
void __iomem *mbase;
diff --git a/arch/powerpc/sysdev/mpc8xx_pic.c b/arch/powerpc/sysdev/mpc8xx_pic.c
index b724622c3a0..c4828c0be5b 100644
--- a/arch/powerpc/sysdev/mpc8xx_pic.c
+++ b/arch/powerpc/sysdev/mpc8xx_pic.c
@@ -1,6 +1,5 @@
#include <linux/kernel.h>
#include <linux/stddef.h>
-#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/irq.h>
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 1be54faf60d..be33c9768ea 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -535,7 +535,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
}
}
-
+
static void __init mpic_scan_ht_pics(struct mpic *mpic)
{
@@ -886,25 +886,25 @@ int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
/* Default: read HW settings */
if (flow_type == IRQ_TYPE_DEFAULT) {
- switch(vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
- MPIC_INFO(VECPRI_SENSE_MASK))) {
- case MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE):
- flow_type = IRQ_TYPE_EDGE_RISING;
- break;
- case MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
- flow_type = IRQ_TYPE_EDGE_FALLING;
- break;
- case MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE):
- flow_type = IRQ_TYPE_LEVEL_HIGH;
- break;
- case MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE):
- flow_type = IRQ_TYPE_LEVEL_LOW;
- break;
- }
+ int vold_ps;
+
+ vold_ps = vold & (MPIC_INFO(VECPRI_POLARITY_MASK) |
+ MPIC_INFO(VECPRI_SENSE_MASK));
+
+ if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+ flow_type = IRQ_TYPE_EDGE_RISING;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_EDGE) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+ flow_type = IRQ_TYPE_EDGE_FALLING;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_POSITIVE)))
+ flow_type = IRQ_TYPE_LEVEL_HIGH;
+ else if (vold_ps == (MPIC_INFO(VECPRI_SENSE_LEVEL) |
+ MPIC_INFO(VECPRI_POLARITY_NEGATIVE)))
+ flow_type = IRQ_TYPE_LEVEL_LOW;
+ else
+ WARN_ONCE(1, "mpic: unknown IRQ type %d\n", vold);
}
/* Apply to irq desc */
@@ -1088,8 +1088,14 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
* is done here.
*/
if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+ int cpu;
+
+ preempt_disable();
+ cpu = mpic_processor_id(mpic);
+ preempt_enable();
+
mpic_set_vector(virq, hw);
- mpic_set_destination(virq, mpic_processor_id(mpic));
+ mpic_set_destination(virq, cpu);
mpic_irq_set_priority(virq, 8);
}
@@ -1475,7 +1481,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
* as a default instead of the value read from the HW.
*/
last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
- >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
+ >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
if (isu_size)
last_irq = isu_size * MPIC_MAX_ISU - 1;
of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
@@ -1582,10 +1588,6 @@ void __init mpic_init(struct mpic *mpic)
num_timers = 8;
}
- /* FSL mpic error interrupt intialization */
- if (mpic->flags & MPIC_FSL_HAS_EIMR)
- mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
-
/* Initialize timers to our reserved vectors and mask them for now */
for (i = 0; i < num_timers; i++) {
unsigned int offset = mpic_tm_offset(mpic, i);
@@ -1625,7 +1627,7 @@ void __init mpic_init(struct mpic *mpic)
/* start with vector = source number, and masked */
u32 vecpri = MPIC_VECPRI_MASK | i |
(8 << MPIC_VECPRI_PRIORITY_SHIFT);
-
+
/* check if protected */
if (mpic->protected && test_bit(i, mpic->protected))
continue;
@@ -1634,7 +1636,7 @@ void __init mpic_init(struct mpic *mpic)
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
}
}
-
+
/* Init spurious vector */
mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec);
@@ -1669,6 +1671,10 @@ void __init mpic_init(struct mpic *mpic)
irq_set_chained_handler(virq, &mpic_cascade);
}
}
+
+ /* FSL mpic error interrupt intialization */
+ if (mpic->flags & MPIC_FSL_HAS_EIMR)
+ mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
}
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index c75325865a8..2c9b52aa266 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -237,15 +237,13 @@ static int mpic_msgr_probe(struct platform_device *dev)
raw_spin_lock_init(&msgr->lock);
if (receive_mask & (1 << i)) {
- struct resource irq;
-
- if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) {
+ msgr->irq = irq_of_parse_and_map(np, irq_index);
+ if (msgr->irq == NO_IRQ) {
dev_err(&dev->dev,
"Missing interrupt specifier");
kfree(msgr);
return -EFAULT;
}
- msgr->irq = irq.start;
irq_index += 1;
} else {
msgr->irq = NO_IRQ;
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c
index bbf342c8831..7dc39f35a4c 100644
--- a/arch/powerpc/sysdev/mpic_msi.c
+++ b/arch/powerpc/sysdev/mpic_msi.c
@@ -35,7 +35,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
const struct irq_domain_ops *ops = mpic->irqhost->ops;
struct device_node *np;
int flags, index, i;
- struct of_irq oirq;
+ struct of_phandle_args oirq;
pr_debug("mpic: found U3, guessing msi allocator setup\n");
@@ -63,9 +63,9 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)
pr_debug("mpic: mapping hwirqs for %s\n", np->full_name);
index = 0;
- while (of_irq_map_one(np, index++, &oirq) == 0) {
- ops->xlate(mpic->irqhost, NULL, oirq.specifier,
- oirq.size, &hwirq, &flags);
+ while (of_irq_parse_one(np, index++, &oirq) == 0) {
+ ops->xlate(mpic->irqhost, NULL, oirq.args,
+ oirq.args_count, &hwirq, &flags);
msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);
}
}
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c
index c06db92a4fb..9d9b06217f8 100644
--- a/arch/powerpc/sysdev/mpic_timer.c
+++ b/arch/powerpc/sysdev/mpic_timer.c
@@ -19,7 +19,9 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <linux/syscore_ops.h>
#include <sysdev/fsl_soc.h>
#include <asm/io.h>
@@ -39,6 +41,7 @@
#define MPIC_TIMER_TCR_ROVR_OFFSET 24
#define TIMER_STOP 0x80000000
+#define GTCCR_TOG 0x80000000
#define TIMERS_PER_GROUP 4
#define MAX_TICKS (~0U >> 1)
#define MAX_TICKS_CASCADE (~0U)
@@ -94,8 +97,11 @@ static void convert_ticks_to_time(struct timer_group_priv *priv,
time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq);
tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq;
- time->tv_usec = (__kernel_suseconds_t)
- div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
+ time->tv_usec = 0;
+
+ if (tmp_sec <= ticks)
+ time->tv_usec = (__kernel_suseconds_t)
+ div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq);
return;
}
@@ -325,11 +331,13 @@ void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time)
casc_priv = priv->timer[handle->num].cascade_handle;
if (casc_priv) {
tmp_ticks = in_be32(&priv->regs[handle->num].gtccr);
+ tmp_ticks &= ~GTCCR_TOG;
ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE;
tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr);
ticks += tmp_ticks;
} else {
ticks = in_be32(&priv->regs[handle->num].gtccr);
+ ticks &= ~GTCCR_TOG;
}
convert_ticks_to_time(priv, ticks, time);
diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c
index 0968b66b4cf..2ff630267e9 100644
--- a/arch/powerpc/sysdev/msi_bitmap.c
+++ b/arch/powerpc/sysdev/msi_bitmap.c
@@ -202,7 +202,7 @@ void __init test_of_node(void)
/* There should really be a struct device_node allocator */
memset(&of_node, 0, sizeof(of_node));
- kref_init(&of_node.kref);
+ of_node_init(&of_node);
of_node.full_name = node_name;
check(0 == msi_bitmap_alloc(&bmp, size, &of_node));
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c
index 4a25c26f0bf..c2dba7db71a 100644
--- a/arch/powerpc/sysdev/mv64x60_dev.c
+++ b/arch/powerpc/sysdev/mv64x60_dev.c
@@ -228,7 +228,7 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev(
if (id == 0) {
pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1);
- if (!pdev)
+ if (IS_ERR(pdev))
return pdev;
}
@@ -448,7 +448,7 @@ static int __init mv64x60_device_setup(void)
int err;
id = 0;
- for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") {
err = mv64x60_mpsc_device_setup(np, id++);
if (err)
printk(KERN_ERR "Failed to initialize MV64x60 "
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c
index 50a81387e9b..3b8734b870e 100644
--- a/arch/powerpc/sysdev/mv64x60_udbg.c
+++ b/arch/powerpc/sysdev/mv64x60_udbg.c
@@ -85,7 +85,7 @@ static void mv64x60_udbg_init(void)
if (!stdout)
return;
- for_each_compatible_node(np, "serial", "marvell,mv64360-mpsc") {
+ for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") {
if (np == stdout)
break;
}
diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c
index c9e803f3e26..6f54b54b132 100644
--- a/arch/powerpc/sysdev/of_rtc.c
+++ b/arch/powerpc/sysdev/of_rtc.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/init.h>
+#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
diff --git a/arch/powerpc/sysdev/ppc4xx_hsta_msi.c b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
new file mode 100644
index 00000000000..11c888416f0
--- /dev/null
+++ b/arch/powerpc/sysdev/ppc4xx_hsta_msi.c
@@ -0,0 +1,215 @@
+/*
+ * MSI support for PPC4xx SoCs using High Speed Transfer Assist (HSTA) for
+ * generation of the interrupt.
+ *
+ * Copyright © 2013 Alistair Popple <alistair@popple.id.au> IBM Corporation
+ *
+ * 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/msi.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pci.h>
+#include <linux/semaphore.h>
+#include <asm/msi_bitmap.h>
+
+struct ppc4xx_hsta_msi {
+ struct device *dev;
+
+ /* The ioremapped HSTA MSI IO space */
+ u32 __iomem *data;
+
+ /* Physical address of HSTA MSI IO space */
+ u64 address;
+ struct msi_bitmap bmp;
+
+ /* An array mapping offsets to hardware IRQs */
+ int *irq_map;
+
+ /* Number of hwirqs supported */
+ int irq_count;
+};
+static struct ppc4xx_hsta_msi ppc4xx_hsta_msi;
+
+static int hsta_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
+{
+ struct msi_msg msg;
+ struct msi_desc *entry;
+ int irq, hwirq;
+ u64 addr;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ irq = msi_bitmap_alloc_hwirqs(&ppc4xx_hsta_msi.bmp, 1);
+ if (irq < 0) {
+ pr_debug("%s: Failed to allocate msi interrupt\n",
+ __func__);
+ return irq;
+ }
+
+ hwirq = ppc4xx_hsta_msi.irq_map[irq];
+ if (hwirq == NO_IRQ) {
+ pr_err("%s: Failed mapping irq %d\n", __func__, irq);
+ return -EINVAL;
+ }
+
+ /*
+ * HSTA generates interrupts on writes to 128-bit aligned
+ * addresses.
+ */
+ addr = ppc4xx_hsta_msi.address + irq*0x10;
+ msg.address_hi = upper_32_bits(addr);
+ msg.address_lo = lower_32_bits(addr);
+
+ /* Data is not used by the HSTA. */
+ msg.data = 0;
+
+ pr_debug("%s: Setup irq %d (0x%0llx)\n", __func__, hwirq,
+ (((u64) msg.address_hi) << 32) | msg.address_lo);
+
+ if (irq_set_msi_desc(hwirq, entry)) {
+ pr_err(
+ "%s: Invalid hwirq %d specified in device tree\n",
+ __func__, hwirq);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ return -EINVAL;
+ }
+ write_msi_msg(hwirq, &msg);
+ }
+
+ return 0;
+}
+
+static int hsta_find_hwirq_offset(int hwirq)
+{
+ int irq;
+
+ /* Find the offset given the hwirq */
+ for (irq = 0; irq < ppc4xx_hsta_msi.irq_count; irq++)
+ if (ppc4xx_hsta_msi.irq_map[irq] == hwirq)
+ return irq;
+
+ return -EINVAL;
+}
+
+static void hsta_teardown_msi_irqs(struct pci_dev *dev)
+{
+ struct msi_desc *entry;
+ int irq;
+
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (entry->irq == NO_IRQ)
+ continue;
+
+ irq = hsta_find_hwirq_offset(entry->irq);
+
+ /* entry->irq should always be in irq_map */
+ BUG_ON(irq < 0);
+ irq_set_msi_desc(entry->irq, NULL);
+ msi_bitmap_free_hwirqs(&ppc4xx_hsta_msi.bmp, irq, 1);
+ pr_debug("%s: Teardown IRQ %u (index %u)\n", __func__,
+ entry->irq, irq);
+ }
+}
+
+static int hsta_msi_check_device(struct pci_dev *pdev, int nvec, int type)
+{
+ /* We don't support MSI-X */
+ if (type == PCI_CAP_ID_MSIX) {
+ pr_debug("%s: MSI-X not supported.\n", __func__);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int hsta_msi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *mem;
+ int irq, ret, irq_count;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (IS_ERR(mem)) {
+ dev_err(dev, "Unable to get mmio space\n");
+ return -EINVAL;
+ }
+
+ irq_count = of_irq_count(dev->of_node);
+ if (!irq_count) {
+ dev_err(dev, "Unable to find IRQ range\n");
+ return -EINVAL;
+ }
+
+ ppc4xx_hsta_msi.dev = dev;
+ ppc4xx_hsta_msi.address = mem->start;
+ ppc4xx_hsta_msi.data = ioremap(mem->start, resource_size(mem));
+ ppc4xx_hsta_msi.irq_count = irq_count;
+ if (IS_ERR(ppc4xx_hsta_msi.data)) {
+ dev_err(dev, "Unable to map memory\n");
+ return -ENOMEM;
+ }
+
+ ret = msi_bitmap_alloc(&ppc4xx_hsta_msi.bmp, irq_count, dev->of_node);
+ if (ret)
+ goto out;
+
+ ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL);
+ if (IS_ERR(ppc4xx_hsta_msi.irq_map)) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ /* Setup a mapping from irq offsets to hardware irq numbers */
+ for (irq = 0; irq < irq_count; irq++) {
+ ppc4xx_hsta_msi.irq_map[irq] =
+ irq_of_parse_and_map(dev->of_node, irq);
+ if (ppc4xx_hsta_msi.irq_map[irq] == NO_IRQ) {
+ dev_err(dev, "Unable to map IRQ\n");
+ ret = -EINVAL;
+ goto out2;
+ }
+ }
+
+ ppc_md.setup_msi_irqs = hsta_setup_msi_irqs;
+ ppc_md.teardown_msi_irqs = hsta_teardown_msi_irqs;
+ ppc_md.msi_check_device = hsta_msi_check_device;
+ return 0;
+
+out2:
+ kfree(ppc4xx_hsta_msi.irq_map);
+
+out1:
+ msi_bitmap_free(&ppc4xx_hsta_msi.bmp);
+
+out:
+ iounmap(ppc4xx_hsta_msi.data);
+ return ret;
+}
+
+static const struct of_device_id hsta_msi_ids[] = {
+ {
+ .compatible = "ibm,hsta-msi",
+ },
+ {}
+};
+
+static struct platform_driver hsta_msi_driver = {
+ .probe = hsta_msi_probe,
+ .driver = {
+ .name = "hsta-msi",
+ .owner = THIS_MODULE,
+ .of_match_table = hsta_msi_ids,
+ },
+};
+
+static int hsta_msi_init(void)
+{
+ return platform_driver_register(&hsta_msi_driver);
+}
+subsys_initcall(hsta_msi_init);
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c
index 1b15f93479c..85d9e37f5cc 100644
--- a/arch/powerpc/sysdev/ppc4xx_ocm.c
+++ b/arch/powerpc/sysdev/ppc4xx_ocm.c
@@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/rheap.h>
#include <asm/ppc4xx_ocm.h>
#include <linux/slab.h>
@@ -338,7 +339,7 @@ void *ppc4xx_ocm_alloc(phys_addr_t *phys, int size, int align,
if (IS_ERR_VALUE(offset))
continue;
- ocm_blk = kzalloc(sizeof(struct ocm_block *), GFP_KERNEL);
+ ocm_blk = kzalloc(sizeof(struct ocm_block), GFP_KERNEL);
if (!ocm_blk) {
printk(KERN_ERR "PPC4XX OCM: could not allocate ocm block");
rh_free(ocm_reg->rh, offset);
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 64603a10b86..df6e2fc4ff9 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -176,8 +176,12 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
return -ENXIO;
}
- /* Check that we are fully contained within 32 bits space */
- if (res->end > 0xffffffff) {
+ /* Check that we are fully contained within 32 bits space if we are not
+ * running on a 460sx or 476fpe which have 64 bit bus addresses.
+ */
+ if (res->end > 0xffffffff &&
+ !(of_device_is_compatible(hose->dn, "ibm,plb-pciex-460sx")
+ || of_device_is_compatible(hose->dn, "ibm,plb-pciex-476fpe"))) {
printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
hose->dn->full_name);
return -ENXIO;
@@ -1058,7 +1062,7 @@ static int __init apm821xx_pciex_core_init(struct device_node *np)
return 1;
}
-static int apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
+static int __init apm821xx_pciex_init_port_hw(struct ppc4xx_pciex_port *port)
{
u32 val;
@@ -1440,7 +1444,8 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
#endif
#ifdef CONFIG_476FPE
- if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe"))
+ if (of_device_is_compatible(np, "ibm,plb-pciex-476fpe")
+ || of_device_is_compatible(np, "ibm,plb-pciex-476gtr"))
ppc4xx_pciex_hwops = &ppc_476fpe_pcie_hwops;
#endif
if (ppc4xx_pciex_hwops == NULL) {
@@ -1751,7 +1756,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
- else if (of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ else if (of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_476FPE_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
@@ -1881,7 +1889,10 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
- of_device_is_compatible(port->node, "ibm,plb-pciex-476fpe"))
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476fpe") ||
+ of_device_is_compatible(
+ port->node, "ibm,plb-pciex-476gtr"))
sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c
index 0debcc31ad7..5c77c9ba33a 100644
--- a/arch/powerpc/sysdev/ppc4xx_soc.c
+++ b/arch/powerpc/sysdev/ppc4xx_soc.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/dcr.h>
diff --git a/arch/powerpc/sysdev/qe_lib/qe_io.c b/arch/powerpc/sysdev/qe_lib/qe_io.c
index a88807b3dd5..d09994164da 100644
--- a/arch/powerpc/sysdev/qe_lib/qe_io.c
+++ b/arch/powerpc/sysdev/qe_lib/qe_io.c
@@ -16,7 +16,6 @@
#include <linux/stddef.h>
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/ioport.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc.c b/arch/powerpc/sysdev/qe_lib/ucc.c
index 134b07d2943..621575b7e84 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc.c
@@ -14,7 +14,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/stddef.h>
#include <linux/spinlock.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_fast.c b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
index cceb2e36673..65aaf15032a 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_fast.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_fast.c
@@ -13,7 +13,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 1c062f48f1a..befaf1123f7 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -13,7 +13,6 @@
* option) any later version.
*/
#include <linux/kernel.h>
-#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c
index 9193e12df69..6f5a8d177c4 100644
--- a/arch/powerpc/sysdev/scom.c
+++ b/arch/powerpc/sysdev/scom.c
@@ -25,6 +25,7 @@
#include <asm/debug.h>
#include <asm/prom.h>
#include <asm/scom.h>
+#include <asm/uaccess.h>
const struct scom_controller *scom_controller;
EXPORT_SYMBOL_GPL(scom_controller);
@@ -53,7 +54,7 @@ scom_map_t scom_map_device(struct device_node *dev, int index)
{
struct device_node *parent;
unsigned int cells, size;
- const u32 *prop;
+ const __be32 *prop, *sprop;
u64 reg, cnt;
scom_map_t ret;
@@ -62,12 +63,24 @@ scom_map_t scom_map_device(struct device_node *dev, int index)
if (parent == NULL)
return 0;
- prop = of_get_property(parent, "#scom-cells", NULL);
- cells = prop ? *prop : 1;
-
+ /*
+ * We support "scom-reg" properties for adding scom registers
+ * to a random device-tree node with an explicit scom-parent
+ *
+ * We also support the simple "reg" property if the device is
+ * a direct child of a scom controller.
+ *
+ * In case both exist, "scom-reg" takes precedence.
+ */
prop = of_get_property(dev, "scom-reg", &size);
+ sprop = of_get_property(parent, "#scom-cells", NULL);
+ if (!prop && parent == dev->parent) {
+ prop = of_get_property(dev, "reg", &size);
+ sprop = of_get_property(parent, "#address-cells", NULL);
+ }
if (!prop)
- return 0;
+ return NULL;
+ cells = sprop ? be32_to_cpup(sprop) : 1;
size >>= 2;
if (index >= (size / (2*cells)))
@@ -86,62 +99,89 @@ EXPORT_SYMBOL_GPL(scom_map_device);
#ifdef CONFIG_SCOM_DEBUGFS
struct scom_debug_entry {
struct device_node *dn;
- unsigned long addr;
- scom_map_t map;
- spinlock_t lock;
- char name[8];
- struct debugfs_blob_wrapper blob;
+ struct debugfs_blob_wrapper path;
+ char name[16];
};
-static int scom_addr_set(void *data, u64 val)
+static ssize_t scom_debug_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct scom_debug_entry *ent = data;
-
- ent->addr = 0;
- scom_unmap(ent->map);
-
- ent->map = scom_map(ent->dn, val, 1);
- if (scom_map_ok(ent->map))
- ent->addr = val;
- else
- return -EFAULT;
-
- return 0;
-}
-
-static int scom_addr_get(void *data, u64 *val)
-{
- struct scom_debug_entry *ent = data;
- *val = ent->addr;
- return 0;
+ struct scom_debug_entry *ent = filp->private_data;
+ u64 __user *ubuf64 = (u64 __user *)ubuf;
+ loff_t off = *ppos;
+ ssize_t done = 0;
+ u64 reg, reg_cnt, val;
+ scom_map_t map;
+ int rc;
+
+ if (off < 0 || (off & 7) || (count & 7))
+ return -EINVAL;
+ reg = off >> 3;
+ reg_cnt = count >> 3;
+
+ map = scom_map(ent->dn, reg, reg_cnt);
+ if (!scom_map_ok(map))
+ return -ENXIO;
+
+ for (reg = 0; reg < reg_cnt; reg++) {
+ rc = scom_read(map, reg, &val);
+ if (!rc)
+ rc = put_user(val, ubuf64);
+ if (rc) {
+ if (!done)
+ done = rc;
+ break;
+ }
+ ubuf64++;
+ *ppos += 8;
+ done += 8;
+ }
+ scom_unmap(map);
+ return done;
}
-DEFINE_SIMPLE_ATTRIBUTE(scom_addr_fops, scom_addr_get, scom_addr_set,
- "0x%llx\n");
-static int scom_val_set(void *data, u64 val)
+static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct scom_debug_entry *ent = data;
-
- if (!scom_map_ok(ent->map))
- return -EFAULT;
-
- scom_write(ent->map, 0, val);
-
- return 0;
+ struct scom_debug_entry *ent = filp->private_data;
+ u64 __user *ubuf64 = (u64 __user *)ubuf;
+ loff_t off = *ppos;
+ ssize_t done = 0;
+ u64 reg, reg_cnt, val;
+ scom_map_t map;
+ int rc;
+
+ if (off < 0 || (off & 7) || (count & 7))
+ return -EINVAL;
+ reg = off >> 3;
+ reg_cnt = count >> 3;
+
+ map = scom_map(ent->dn, reg, reg_cnt);
+ if (!scom_map_ok(map))
+ return -ENXIO;
+
+ for (reg = 0; reg < reg_cnt; reg++) {
+ rc = get_user(val, ubuf64);
+ if (!rc)
+ rc = scom_write(map, reg, val);
+ if (rc) {
+ if (!done)
+ done = rc;
+ break;
+ }
+ ubuf64++;
+ done += 8;
+ }
+ scom_unmap(map);
+ return done;
}
-static int scom_val_get(void *data, u64 *val)
-{
- struct scom_debug_entry *ent = data;
-
- if (!scom_map_ok(ent->map))
- return -EFAULT;
-
- *val = scom_read(ent->map, 0);
- return 0;
-}
-DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set,
- "0x%llx\n");
+static const struct file_operations scom_debug_fops = {
+ .read = scom_debug_read,
+ .write = scom_debug_write,
+ .open = simple_open,
+ .llseek = default_llseek,
+};
static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
int i)
@@ -154,11 +194,9 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
return -ENOMEM;
ent->dn = of_node_get(dn);
- ent->map = SCOM_MAP_INVALID;
- spin_lock_init(&ent->lock);
- snprintf(ent->name, 8, "scom%d", i);
- ent->blob.data = (void*) dn->full_name;
- ent->blob.size = strlen(dn->full_name);
+ snprintf(ent->name, 16, "%08x", i);
+ ent->path.data = (void*) dn->full_name;
+ ent->path.size = strlen(dn->full_name);
dir = debugfs_create_dir(ent->name, root);
if (!dir) {
@@ -167,9 +205,8 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn,
return -1;
}
- debugfs_create_file("addr", 0600, dir, ent, &scom_addr_fops);
- debugfs_create_file("value", 0600, dir, ent, &scom_val_fops);
- debugfs_create_blob("path", 0400, dir, &ent->blob);
+ debugfs_create_blob("devspec", 0400, dir, &ent->path);
+ debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops);
return 0;
}
@@ -185,8 +222,13 @@ static int scom_debug_init(void)
return -1;
i = rc = 0;
- for_each_node_with_property(dn, "scom-controller")
- rc |= scom_debug_init_one(root, dn, i++);
+ for_each_node_with_property(dn, "scom-controller") {
+ int id = of_get_ibm_chip_id(dn);
+ if (id == -1)
+ id = i;
+ rc |= scom_debug_init_one(root, dn, id);
+ i++;
+ }
return rc;
}
diff --git a/arch/powerpc/sysdev/udbg_memcons.c b/arch/powerpc/sysdev/udbg_memcons.c
index ce5a7b489e4..9998c0de12d 100644
--- a/arch/powerpc/sysdev/udbg_memcons.c
+++ b/arch/powerpc/sysdev/udbg_memcons.c
@@ -18,7 +18,6 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/init.h>
#include <linux/kernel.h>
#include <asm/barrier.h>
#include <asm/page.h>
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
index df0fc582146..c1917cf67c3 100644
--- a/arch/powerpc/sysdev/xics/icp-hv.c
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -12,7 +12,6 @@
#include <linux/irq.h>
#include <linux/smp.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
#include <linux/cpu.h>
#include <linux/of.h>
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c
index 9dee47071af..de8d9483bbe 100644
--- a/arch/powerpc/sysdev/xics/icp-native.c
+++ b/arch/powerpc/sysdev/xics/icp-native.c
@@ -26,6 +26,7 @@
#include <asm/errno.h>
#include <asm/xics.h>
#include <asm/kvm_ppc.h>
+#include <asm/dbell.h>
struct icp_ipl {
union {
@@ -145,7 +146,13 @@ static unsigned int icp_native_get_irq(void)
static void icp_native_cause_ipi(int cpu, unsigned long data)
{
kvmppc_set_host_ipi(cpu, 1);
- icp_native_set_qirr(cpu, IPI_PRIORITY);
+#ifdef CONFIG_PPC_DOORBELL
+ if (cpu_has_feature(CPU_FTR_DBELL) &&
+ (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id()))))
+ doorbell_cause_ipi(cpu, data);
+ else
+#endif
+ icp_native_set_qirr(cpu, IPI_PRIORITY);
}
void xics_wake_cpu(int cpu)
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c
index 39d72212655..3c6ee1b64e5 100644
--- a/arch/powerpc/sysdev/xics/ics-opal.c
+++ b/arch/powerpc/sysdev/xics/ics-opal.c
@@ -112,6 +112,7 @@ static int ics_opal_set_affinity(struct irq_data *d,
bool force)
{
unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+ __be16 oserver;
int16_t server;
int8_t priority;
int64_t rc;
@@ -120,13 +121,13 @@ static int ics_opal_set_affinity(struct irq_data *d,
if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)
return -1;
- rc = opal_get_xive(hw_irq, &server, &priority);
+ rc = opal_get_xive(hw_irq, &oserver, &priority);
if (rc != OPAL_SUCCESS) {
- pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)"
- " error %lld\n",
- __func__, d->irq, hw_irq, server, rc);
+ pr_err("%s: opal_get_xive(irq=%d [hw 0x%x]) error %lld\n",
+ __func__, d->irq, hw_irq, rc);
return -1;
}
+ server = be16_to_cpu(oserver);
wanted_server = xics_get_irq_server(d->irq, cpumask, 1);
if (wanted_server < 0) {
@@ -181,7 +182,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq)
{
unsigned int hw_irq = (unsigned int)virq_to_hw(virq);
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS))
@@ -201,7 +202,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq)
static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
{
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
/* Check if HAL knows about this interrupt */
@@ -215,14 +216,14 @@ static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec)
static long ics_opal_get_server(struct ics *ics, unsigned long vec)
{
int64_t rc;
- int16_t server;
+ __be16 server;
int8_t priority;
/* Check if HAL knows about this interrupt */
rc = opal_get_xive(vec, &server, &priority);
if (rc != OPAL_SUCCESS)
return -1;
- return ics_opal_unmangle_server(server);
+ return ics_opal_unmangle_server(be16_to_cpu(server));
}
int __init ics_opal_init(void)
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c
index 8d73c3c0bee..83f943a8e0d 100644
--- a/arch/powerpc/sysdev/xilinx_intc.c
+++ b/arch/powerpc/sysdev/xilinx_intc.c
@@ -23,6 +23,8 @@
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <asm/io.h>
#include <asm/processor.h>
#include <asm/i8259.h>