diff options
Diffstat (limited to 'arch/powerpc/sysdev')
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>  | 
