diff options
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/Kconfig | 6 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/Makefile | 6 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/cpm1.c | 74 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_lbc.c | 53 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.c | 109 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_msi.h | 8 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_pci.c | 58 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_soc.c | 111 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/fsl_soc.h | 8 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpc8xxx_gpio.c | 171 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 59 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic_msi.c | 123 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic_pasemi_msi.c | 24 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic_u3msi.c | 22 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/msi_bitmap.c | 247 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mv64x60_dev.c | 6 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/ppc4xx_gpio.c | 217 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/ppc4xx_pci.c | 48 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/qe_lib/Kconfig | 9 | 
20 files changed, 952 insertions, 409 deletions
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index 72fb35b9ebc..396582835cb 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig @@ -6,3 +6,9 @@ config PPC4xx_PCI_EXPRESS  	bool  	depends on PCI && 4xx  	default n + +config PPC_MSI_BITMAP +	bool +	depends on PCI_MSI +	default y if MPIC +	default y if FSL_PCI diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index a90054b56d5..5afce115ab1 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile @@ -5,6 +5,7 @@ endif  mpic-msi-obj-$(CONFIG_PCI_MSI)	+= mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o  obj-$(CONFIG_MPIC)		+= mpic.o $(mpic-msi-obj-y)  fsl-msi-obj-$(CONFIG_PCI_MSI)	+= fsl_msi.o +obj-$(CONFIG_PPC_MSI_BITMAP)	+= msi_bitmap.o  obj-$(CONFIG_PPC_MPC106)	+= grackle.o  obj-$(CONFIG_PPC_DCR_NATIVE)	+= dcr-low.o @@ -15,6 +16,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o  obj-$(CONFIG_FSL_PCI)		+= fsl_pci.o $(fsl-msi-obj-y)  obj-$(CONFIG_FSL_LBC)		+= fsl_lbc.o  obj-$(CONFIG_FSL_GTM)		+= fsl_gtm.o +obj-$(CONFIG_MPC8xxx_GPIO)	+= mpc8xxx_gpio.o  obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o  obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o  obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/ @@ -35,16 +37,14 @@ obj-$(CONFIG_OF_RTC)		+= of_rtc.o  ifeq ($(CONFIG_PCI),y)  obj-$(CONFIG_4xx)		+= ppc4xx_pci.o  endif +obj-$(CONFIG_PPC4xx_GPIO)	+= ppc4xx_gpio.o -# Temporary hack until we have migrated to asm-powerpc -ifeq ($(ARCH),powerpc)  obj-$(CONFIG_CPM)		+= cpm_common.o  obj-$(CONFIG_CPM2)		+= cpm2.o cpm2_pic.o  obj-$(CONFIG_QUICC_ENGINE)	+= cpm_common.o  obj-$(CONFIG_PPC_DCR)		+= dcr.o  obj-$(CONFIG_8xx)		+= mpc8xx_pic.o cpm1.o  obj-$(CONFIG_UCODE_PATCH)	+= micropatch.o -endif  ifeq ($(CONFIG_SUSPEND),y)  obj-$(CONFIG_6xx)		+= 6xx-suspend.o diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 4a04823e842..490473ce810 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c @@ -546,15 +546,11 @@ static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio)  	return !!(in_be16(&iop->dat) & pin_mask);  } -static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) +static void __cpm1_gpio16_set(struct of_mm_gpio_chip *mm_gc, u16 pin_mask, +	int value)  { -	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);  	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);  	struct cpm_ioport16 __iomem *iop = mm_gc->regs; -	unsigned long flags; -	u16 pin_mask = 1 << (15 - gpio); - -	spin_lock_irqsave(&cpm1_gc->lock, flags);  	if (value)  		cpm1_gc->cpdata |= pin_mask; @@ -562,6 +558,18 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)  		cpm1_gc->cpdata &= ~pin_mask;  	out_be16(&iop->dat, cpm1_gc->cpdata); +} + +static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); +	unsigned long flags; +	u16 pin_mask = 1 << (15 - gpio); + +	spin_lock_irqsave(&cpm1_gc->lock, flags); + +	__cpm1_gpio16_set(mm_gc, pin_mask, value);  	spin_unlock_irqrestore(&cpm1_gc->lock, flags);  } @@ -569,14 +577,17 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)  static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  {  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);  	struct cpm_ioport16 __iomem *iop = mm_gc->regs; -	u16 pin_mask; +	unsigned long flags; +	u16 pin_mask = 1 << (15 - gpio); -	pin_mask = 1 << (15 - gpio); +	spin_lock_irqsave(&cpm1_gc->lock, flags);  	setbits16(&iop->dir, pin_mask); +	__cpm1_gpio16_set(mm_gc, pin_mask, val); -	cpm1_gpio16_set(gc, gpio, val); +	spin_unlock_irqrestore(&cpm1_gc->lock, flags);  	return 0;  } @@ -584,13 +595,17 @@ static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)  {  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc);  	struct cpm_ioport16 __iomem *iop = mm_gc->regs; -	u16 pin_mask; +	unsigned long flags; +	u16 pin_mask = 1 << (15 - gpio); -	pin_mask = 1 << (15 - gpio); +	spin_lock_irqsave(&cpm1_gc->lock, flags);  	clrbits16(&iop->dir, pin_mask); +	spin_unlock_irqrestore(&cpm1_gc->lock, flags); +  	return 0;  } @@ -655,15 +670,11 @@ static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio)  	return !!(in_be32(&iop->dat) & pin_mask);  } -static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) +static void __cpm1_gpio32_set(struct of_mm_gpio_chip *mm_gc, u32 pin_mask, +	int value)  { -	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);  	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);  	struct cpm_ioport32b __iomem *iop = mm_gc->regs; -	unsigned long flags; -	u32 pin_mask = 1 << (31 - gpio); - -	spin_lock_irqsave(&cpm1_gc->lock, flags);  	if (value)  		cpm1_gc->cpdata |= pin_mask; @@ -671,6 +682,18 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)  		cpm1_gc->cpdata &= ~pin_mask;  	out_be32(&iop->dat, cpm1_gc->cpdata); +} + +static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); +	unsigned long flags; +	u32 pin_mask = 1 << (31 - gpio); + +	spin_lock_irqsave(&cpm1_gc->lock, flags); + +	__cpm1_gpio32_set(mm_gc, pin_mask, value);  	spin_unlock_irqrestore(&cpm1_gc->lock, flags);  } @@ -678,14 +701,17 @@ static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value)  static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  {  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);  	struct cpm_ioport32b __iomem *iop = mm_gc->regs; -	u32 pin_mask; +	unsigned long flags; +	u32 pin_mask = 1 << (31 - gpio); -	pin_mask = 1 << (31 - gpio); +	spin_lock_irqsave(&cpm1_gc->lock, flags);  	setbits32(&iop->dir, pin_mask); +	__cpm1_gpio32_set(mm_gc, pin_mask, val); -	cpm1_gpio32_set(gc, gpio, val); +	spin_unlock_irqrestore(&cpm1_gc->lock, flags);  	return 0;  } @@ -693,13 +719,17 @@ static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)  static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)  {  	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc);  	struct cpm_ioport32b __iomem *iop = mm_gc->regs; -	u32 pin_mask; +	unsigned long flags; +	u32 pin_mask = 1 << (31 - gpio); -	pin_mask = 1 << (31 - gpio); +	spin_lock_irqsave(&cpm1_gc->lock, flags);  	clrbits32(&iop->dir, pin_mask); +	spin_unlock_irqrestore(&cpm1_gc->lock, flags); +  	return 0;  } diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c index 422c8faef59..0494ee55920 100644 --- a/arch/powerpc/sysdev/fsl_lbc.c +++ b/arch/powerpc/sysdev/fsl_lbc.c @@ -11,14 +11,19 @@   * (at your option) any later version.   */ +#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/io.h>  #include <linux/of.h> +#include <asm/prom.h>  #include <asm/fsl_lbc.h> -spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); - -struct fsl_lbc_regs __iomem *fsl_lbc_regs; -EXPORT_SYMBOL(fsl_lbc_regs); +static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); +static struct fsl_lbc_regs __iomem *fsl_lbc_regs;  static char __initdata *compat_lbc[] = {  	"fsl,pq2-localbus", @@ -127,3 +132,43 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)  	return 0;  }  EXPORT_SYMBOL(fsl_upm_find); + +/** + * fsl_upm_run_pattern - actually run an UPM pattern + * @upm:	pointer to the fsl_upm structure obtained via fsl_upm_find + * @io_base:	remapped pointer to where memory access should happen + * @mar:	MAR register content during pattern execution + * + * This function triggers dummy write to the memory specified by the io_base, + * thus UPM pattern actually executed. Note that mar usage depends on the + * pre-programmed AMX bits in the UPM RAM. + */ +int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) +{ +	int ret = 0; +	unsigned long flags; + +	spin_lock_irqsave(&fsl_lbc_lock, flags); + +	out_be32(&fsl_lbc_regs->mar, mar << (32 - upm->width)); + +	switch (upm->width) { +	case 8: +		out_8(io_base, 0x0); +		break; +	case 16: +		out_be16(io_base, 0x0); +		break; +	case 32: +		out_be32(io_base, 0x0); +		break; +	default: +		ret = -EINVAL; +		break; +	} + +	spin_unlock_irqrestore(&fsl_lbc_lock, flags); + +	return ret; +} +EXPORT_SYMBOL(fsl_upm_run_pattern); diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 2c5187cc8a2..f25ce818d40 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c @@ -14,7 +14,6 @@   */  #include <linux/irq.h>  #include <linux/bootmem.h> -#include <linux/bitmap.h>  #include <linux/msi.h>  #include <linux/pci.h>  #include <linux/of_platform.h> @@ -67,95 +66,22 @@ static struct irq_host_ops fsl_msi_host_ops = {  	.map = fsl_msi_host_map,  }; -static irq_hw_number_t fsl_msi_alloc_hwirqs(struct fsl_msi *msi, int num) -{ -	unsigned long flags; -	int order = get_count_order(num); -	int offset; - -	spin_lock_irqsave(&msi->bitmap_lock, flags); - -	offset = bitmap_find_free_region(msi->fsl_msi_bitmap, -					NR_MSI_IRQS, order); - -	spin_unlock_irqrestore(&msi->bitmap_lock, flags); - -	pr_debug("%s: allocated 0x%x (2^%d) at offset 0x%x\n", -		__func__, num, order, offset); - -	return offset; -} - -static void fsl_msi_free_hwirqs(struct fsl_msi *msi, int offset, int num) -{ -	unsigned long flags; -	int order = get_count_order(num); - -	pr_debug("%s: freeing 0x%x (2^%d) at offset 0x%x\n", -		__func__, num, order, offset); - -	spin_lock_irqsave(&msi->bitmap_lock, flags); -	bitmap_release_region(msi->fsl_msi_bitmap, offset, order); -	spin_unlock_irqrestore(&msi->bitmap_lock, flags); -} - -static int fsl_msi_free_dt_hwirqs(struct fsl_msi *msi) -{ -	int i; -	int len; -	const u32 *p; - -	bitmap_allocate_region(msi->fsl_msi_bitmap, 0, -		       get_count_order(NR_MSI_IRQS)); - -	p = of_get_property(msi->of_node, "msi-available-ranges", &len); - -	if (!p) { -		/* No msi-available-ranges property, -		 * All the 256 MSI interrupts can be used -		 */ -		fsl_msi_free_hwirqs(msi, 0, 0x100); -		return 0; -	} - -	if ((len % (2 * sizeof(u32))) != 0) { -		printk(KERN_WARNING "fsl_msi: Malformed msi-available-ranges " -		       "property on %s\n", msi->of_node->full_name); -		return -EINVAL; -	} - -	/* Format is: (<u32 start> <u32 count>)+ */ -	len /= 2 * sizeof(u32); -	for (i = 0; i < len; i++, p += 2) -		fsl_msi_free_hwirqs(msi, *p, *(p + 1)); - -	return 0; -} -  static int fsl_msi_init_allocator(struct fsl_msi *msi_data)  {  	int rc; -	int size = BITS_TO_LONGS(NR_MSI_IRQS) * sizeof(u32); -	msi_data->fsl_msi_bitmap = kzalloc(size, GFP_KERNEL); +	rc = msi_bitmap_alloc(&msi_data->bitmap, NR_MSI_IRQS, +			      msi_data->irqhost->of_node); +	if (rc) +		return rc; -	if (msi_data->fsl_msi_bitmap == NULL) { -		pr_debug("%s: ENOMEM allocating allocator bitmap!\n", -				__func__); -		return -ENOMEM; +	rc = msi_bitmap_reserve_dt_hwirqs(&msi_data->bitmap); +	if (rc < 0) { +		msi_bitmap_free(&msi_data->bitmap); +		return rc;  	} -	rc = fsl_msi_free_dt_hwirqs(msi_data); -	if (rc) -		goto out_free; -  	return 0; -out_free: -	kfree(msi_data->fsl_msi_bitmap); - -	msi_data->fsl_msi_bitmap = NULL; -	return rc; -  }  static int fsl_msi_check_device(struct pci_dev *pdev, int nvec, int type) @@ -175,7 +101,8 @@ static void fsl_teardown_msi_irqs(struct pci_dev *pdev)  		if (entry->irq == NO_IRQ)  			continue;  		set_irq_msi(entry->irq, NULL); -		fsl_msi_free_hwirqs(msi_data, virq_to_hw(entry->irq), 1); +		msi_bitmap_free_hwirqs(&msi_data->bitmap, +				       virq_to_hw(entry->irq), 1);  		irq_dispose_mapping(entry->irq);  	} @@ -197,15 +124,14 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq,  static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  { -	irq_hw_number_t hwirq; -	int rc; +	int rc, hwirq;  	unsigned int virq;  	struct msi_desc *entry;  	struct msi_msg msg;  	struct fsl_msi *msi_data = fsl_msi;  	list_for_each_entry(entry, &pdev->msi_list, list) { -		hwirq = fsl_msi_alloc_hwirqs(msi_data, 1); +		hwirq = msi_bitmap_alloc_hwirqs(&msi_data->bitmap, 1);  		if (hwirq < 0) {  			rc = hwirq;  			pr_debug("%s: fail allocating msi interrupt\n", @@ -216,9 +142,9 @@ static int fsl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		virq = irq_create_mapping(msi_data->irqhost, hwirq);  		if (virq == NO_IRQ) { -			pr_debug("%s: fail mapping hwirq 0x%lx\n", +			pr_debug("%s: fail mapping hwirq 0x%x\n",  					__func__, hwirq); -			fsl_msi_free_hwirqs(msi_data, hwirq, 1); +			msi_bitmap_free_hwirqs(&msi_data->bitmap, hwirq, 1);  			rc = -ENOSPC;  			goto out_free;  		} @@ -317,14 +243,11 @@ static int __devinit fsl_of_msi_probe(struct of_device *dev,  		goto error_out;  	} -	msi->of_node = of_node_get(dev->node); +	msi->irqhost = irq_alloc_host(dev->node, IRQ_HOST_MAP_LINEAR, +				      NR_MSI_IRQS, &fsl_msi_host_ops, 0); -	msi->irqhost = irq_alloc_host(of_node_get(dev->node), -				IRQ_HOST_MAP_LINEAR, -				NR_MSI_IRQS, &fsl_msi_host_ops, 0);  	if (msi->irqhost == NULL) {  		dev_err(&dev->dev, "No memory for MSI irqhost\n"); -		of_node_put(dev->node);  		err = -ENOMEM;  		goto error_out;  	} diff --git a/arch/powerpc/sysdev/fsl_msi.h b/arch/powerpc/sysdev/fsl_msi.h index a653468521f..331c7e7025b 100644 --- a/arch/powerpc/sysdev/fsl_msi.h +++ b/arch/powerpc/sysdev/fsl_msi.h @@ -13,6 +13,8 @@  #ifndef _POWERPC_SYSDEV_FSL_MSI_H  #define _POWERPC_SYSDEV_FSL_MSI_H +#include <asm/msi_bitmap.h> +  #define NR_MSI_REG		8  #define IRQS_PER_MSI_REG	32  #define NR_MSI_IRQS	(NR_MSI_REG * IRQS_PER_MSI_REG) @@ -22,9 +24,6 @@  #define FSL_PIC_IP_IPIC	0x00000002  struct fsl_msi { -	/* Device node of the MSI interrupt*/ -	struct device_node *of_node; -  	struct irq_host *irqhost;  	unsigned long cascade_irq; @@ -34,8 +33,7 @@ struct fsl_msi {  	void __iomem *msi_regs;  	u32 feature; -	unsigned long *fsl_msi_bitmap; -	spinlock_t bitmap_lock; +	struct msi_bitmap bitmap;  };  #endif /* _POWERPC_SYSDEV_FSL_MSI_H */ diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 61e6d77efa4..5b264eb4b1f 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c @@ -1,7 +1,7 @@  /* - * MPC85xx/86xx PCI/PCIE support routing. + * MPC83xx/85xx/86xx PCI/PCIE support routing.   * - * Copyright 2007 Freescale Semiconductor, Inc + * Copyright 2007,2008 Freescale Semiconductor, Inc   *   * Initial author: Xianghua Xiao <x.xiao@freescale.com>   * Recode: ZHANG WEI <wei.zhang@freescale.com> @@ -251,20 +251,47 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8641D, quirk_fsl_pcie_header);  DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);  #endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ -#if defined(CONFIG_PPC_83xx) +#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)  int __init mpc83xx_add_bridge(struct device_node *dev)  {  	int len;  	struct pci_controller *hose; -	struct resource rsrc; +	struct resource rsrc_reg; +	struct resource rsrc_cfg;  	const int *bus_range; -	int primary = 1, has_address = 0; -	phys_addr_t immr = get_immrbase(); +	int primary;  	pr_debug("Adding PCI host bridge %s\n", dev->full_name);  	/* Fetch host bridge registers address */ -	has_address = (of_address_to_resource(dev, 0, &rsrc) == 0); +	if (of_address_to_resource(dev, 0, &rsrc_reg)) { +		printk(KERN_WARNING "Can't get pci register base!\n"); +		return -ENOMEM; +	} + +	memset(&rsrc_cfg, 0, sizeof(rsrc_cfg)); + +	if (of_address_to_resource(dev, 1, &rsrc_cfg)) { +		printk(KERN_WARNING +			"No pci config register base in dev tree, " +			"using default\n"); +		/* +		 * MPC83xx supports up to two host controllers +		 * 	one at 0x8500 has config space registers at 0x8300 +		 * 	one at 0x8600 has config space registers at 0x8380 +		 */ +		if ((rsrc_reg.start & 0xfffff) == 0x8500) +			rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8300; +		else if ((rsrc_reg.start & 0xfffff) == 0x8600) +			rsrc_cfg.start = (rsrc_reg.start & 0xfff00000) + 0x8380; +	} +	/* +	 * Controller at offset 0x8500 is primary +	 */ +	if ((rsrc_reg.start & 0xfffff) == 0x8500) +		primary = 1; +	else +		primary = 0;  	/* Get bus range if any */  	bus_range = of_get_property(dev, "bus-range", &len); @@ -281,22 +308,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev)  	hose->first_busno = bus_range ? bus_range[0] : 0;  	hose->last_busno = bus_range ? bus_range[1] : 0xff; -	/* MPC83xx supports up to two host controllers one at 0x8500 from immrbar -	 * the other at 0x8600, we consider the 0x8500 the primary controller -	 */ -	/* PCI 1 */ -	if ((rsrc.start & 0xfffff) == 0x8500) { -		setup_indirect_pci(hose, immr + 0x8300, immr + 0x8304, 0); -	} -	/* PCI 2 */ -	if ((rsrc.start & 0xfffff) == 0x8600) { -		setup_indirect_pci(hose, immr + 0x8380, immr + 0x8384, 0); -		primary = 0; -	} +	setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); -	printk(KERN_INFO "Found MPC83xx PCI host bridge at 0x%016llx. " +	printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "  	       "Firmware bus number: %d->%d\n", -	       (unsigned long long)rsrc.start, hose->first_busno, +	       (unsigned long long)rsrc_reg.start, hose->first_busno,  	       hose->last_busno);  	pr_debug(" ->Hose at 0x%p, cfg_addr=0x%p,cfg_data=0x%p\n", diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index 214388e1180..26ecb96f973 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c @@ -223,6 +223,8 @@ static int gfar_mdio_of_init_one(struct device_node *np)  	if (ret)  		return ret; +	/* The gianfar device will try to use the same ID created below to find +	 * this bus, to coordinate register access (since they share).  */  	mdio_dev = platform_device_register_simple("fsl-gianfar_mdio",  			res.start&0xfffff, &res, 1);  	if (IS_ERR(mdio_dev)) @@ -394,6 +396,30 @@ static int __init gfar_of_init(void)  			of_node_put(mdio);  		} +		/* Get MDIO bus controlled by this eTSEC, if any.  Normally only +		 * eTSEC 1 will control an MDIO bus, not necessarily the same +		 * bus that its PHY is on ('mdio' above), so we can't just use +		 * that.  What we do is look for a gianfar mdio device that has +		 * overlapping registers with this device.  That's really the +		 * whole point, to find the device sharing our registers to +		 * coordinate access with it. +		 */ +		for_each_compatible_node(mdio, NULL, "fsl,gianfar-mdio") { +			if (of_address_to_resource(mdio, 0, &res)) +				continue; + +			if (res.start >= r[0].start && res.end <= r[0].end) { +				/* Get the ID the mdio bus platform device was +				 * registered with.  gfar_data.bus_id is +				 * different because it's for finding a PHY, +				 * while this is for finding a MII bus. +				 */ +				gfar_data.mdio_bus = res.start&0xfffff; +				of_node_put(mdio); +				break; +			} +		} +  		ret =  		    platform_device_add_data(gfar_dev, &gfar_data,  					     sizeof(struct @@ -412,53 +438,6 @@ err:  arch_initcall(gfar_of_init); - -#ifdef CONFIG_PPC_83xx -static int __init mpc83xx_wdt_init(void) -{ -	struct resource r; -	struct device_node *np; -	struct platform_device *dev; -	u32 freq = fsl_get_sys_freq(); -	int ret; - -	np = of_find_compatible_node(NULL, "watchdog", "mpc83xx_wdt"); - -	if (!np) { -		ret = -ENODEV; -		goto nodev; -	} - -	memset(&r, 0, sizeof(r)); - -	ret = of_address_to_resource(np, 0, &r); -	if (ret) -		goto err; - -	dev = platform_device_register_simple("mpc83xx_wdt", 0, &r, 1); -	if (IS_ERR(dev)) { -		ret = PTR_ERR(dev); -		goto err; -	} - -	ret = platform_device_add_data(dev, &freq, sizeof(freq)); -	if (ret) -		goto unreg; - -	of_node_put(np); -	return 0; - -unreg: -	platform_device_unregister(dev); -err: -	of_node_put(np); -nodev: -	return ret; -} - -arch_initcall(mpc83xx_wdt_init); -#endif -  static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)  {  	if (!phy_type) @@ -767,42 +746,6 @@ void fsl_rstcr_restart(char *cmd)  #endif  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) -struct platform_diu_data_ops diu_ops = { -	.diu_size = 1280 * 1024 * 4,	/* default one 1280x1024 buffer */ -}; +struct platform_diu_data_ops diu_ops;  EXPORT_SYMBOL(diu_ops); - -int __init preallocate_diu_videomemory(void) -{ -	pr_debug("diu_size=%lu\n", diu_ops.diu_size); - -	diu_ops.diu_mem = __alloc_bootmem(diu_ops.diu_size, 8, 0); -	if (!diu_ops.diu_mem) { -		printk(KERN_ERR "fsl-diu: cannot allocate %lu bytes\n", -			diu_ops.diu_size); -		return -ENOMEM; -	} - -	pr_debug("diu_mem=%p\n", diu_ops.diu_mem); - -	rh_init(&diu_ops.diu_rh_info, 4096, ARRAY_SIZE(diu_ops.diu_rh_block), -		diu_ops.diu_rh_block); -	return rh_attach_region(&diu_ops.diu_rh_info, -				(unsigned long) diu_ops.diu_mem, -				diu_ops.diu_size); -} - -static int __init early_parse_diufb(char *p) -{ -	if (!p) -		return 1; - -	diu_ops.diu_size = _ALIGN_UP(memparse(p, &p), 8); - -	pr_debug("diu_size=%lu\n", diu_ops.diu_size); - -	return 0; -} -early_param("diufb", early_parse_diufb); -  #endif diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index 02429988735..60f7f227327 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h @@ -20,14 +20,7 @@ extern int fsl_spi_init(struct spi_board_info *board_infos,  extern void fsl_rstcr_restart(char *cmd);  #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) -#include <linux/bootmem.h> -#include <asm/rheap.h>  struct platform_diu_data_ops { -	rh_block_t diu_rh_block[16]; -	rh_info_t diu_rh_info; -	unsigned long diu_size; -	void *diu_mem; -  	unsigned int (*get_pixel_format) (unsigned int bits_per_pixel,  		int monitor_port);  	void (*set_gamma_table) (int monitor_port, char *gamma_table_base); @@ -38,7 +31,6 @@ struct platform_diu_data_ops {  };  extern struct platform_diu_data_ops diu_ops; -int __init preallocate_diu_videomemory(void);  #endif  #endif diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c new file mode 100644 index 00000000000..103eace3619 --- /dev/null +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c @@ -0,0 +1,171 @@ +/* + * GPIOs on MPC8349/8572/8610 and compatible + * + * Copyright (C) 2008 Peter Korsgaard <jacmet@sunsite.dk> + * + * This file is licensed under the terms of the GNU General Public License + * version 2.  This program is licensed "as is" without any warranty of any + * kind, whether express or implied. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/gpio.h> + +#define MPC8XXX_GPIO_PINS	32 + +#define GPIO_DIR		0x00 +#define GPIO_ODR		0x04 +#define GPIO_DAT		0x08 +#define GPIO_IER		0x0c +#define GPIO_IMR		0x10 +#define GPIO_ICR		0x14 + +struct mpc8xxx_gpio_chip { +	struct of_mm_gpio_chip mm_gc; +	spinlock_t lock; + +	/* +	 * shadowed data register to be able to clear/set output pins in +	 * open drain mode safely +	 */ +	u32 data; +}; + +static inline u32 mpc8xxx_gpio2mask(unsigned int gpio) +{ +	return 1u << (MPC8XXX_GPIO_PINS - 1 - gpio); +} + +static inline struct mpc8xxx_gpio_chip * +to_mpc8xxx_gpio_chip(struct of_mm_gpio_chip *mm) +{ +	return container_of(mm, struct mpc8xxx_gpio_chip, mm_gc); +} + +static void mpc8xxx_gpio_save_regs(struct of_mm_gpio_chip *mm) +{ +	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + +	mpc8xxx_gc->data = in_be32(mm->regs + GPIO_DAT); +} + +static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ +	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); + +	return in_be32(mm->regs + GPIO_DAT) & mpc8xxx_gpio2mask(gpio); +} + +static void mpc8xxx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ +	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); +	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); +	unsigned long flags; + +	spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +	if (val) +		mpc8xxx_gc->data |= mpc8xxx_gpio2mask(gpio); +	else +		mpc8xxx_gc->data &= ~mpc8xxx_gpio2mask(gpio); + +	out_be32(mm->regs + GPIO_DAT, mpc8xxx_gc->data); + +	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); +} + +static int mpc8xxx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ +	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); +	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); +	unsigned long flags; + +	spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +	clrbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + +	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +	return 0; +} + +static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ +	struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); +	struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); +	unsigned long flags; + +	mpc8xxx_gpio_set(gc, gpio, val); + +	spin_lock_irqsave(&mpc8xxx_gc->lock, flags); + +	setbits32(mm->regs + GPIO_DIR, mpc8xxx_gpio2mask(gpio)); + +	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags); + +	return 0; +} + +static void __init mpc8xxx_add_controller(struct device_node *np) +{ +	struct mpc8xxx_gpio_chip *mpc8xxx_gc; +	struct of_mm_gpio_chip *mm_gc; +	struct of_gpio_chip *of_gc; +	struct gpio_chip *gc; +	int ret; + +	mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL); +	if (!mpc8xxx_gc) { +		ret = -ENOMEM; +		goto err; +	} + +	spin_lock_init(&mpc8xxx_gc->lock); + +	mm_gc = &mpc8xxx_gc->mm_gc; +	of_gc = &mm_gc->of_gc; +	gc = &of_gc->gc; + +	mm_gc->save_regs = mpc8xxx_gpio_save_regs; +	of_gc->gpio_cells = 2; +	gc->ngpio = MPC8XXX_GPIO_PINS; +	gc->direction_input = mpc8xxx_gpio_dir_in; +	gc->direction_output = mpc8xxx_gpio_dir_out; +	gc->get = mpc8xxx_gpio_get; +	gc->set = mpc8xxx_gpio_set; + +	ret = of_mm_gpiochip_add(np, mm_gc); +	if (ret) +		goto err; + +	return; + +err: +	pr_err("%s: registration failed with status %d\n", +	       np->full_name, ret); +	kfree(mpc8xxx_gc); + +	return; +} + +static int __init mpc8xxx_add_gpiochips(void) +{ +	struct device_node *np; + +	for_each_compatible_node(np, NULL, "fsl,mpc8349-gpio") +		mpc8xxx_add_controller(np); + +	for_each_compatible_node(np, NULL, "fsl,mpc8572-gpio") +		mpc8xxx_add_controller(np); + +	for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") +		mpc8xxx_add_controller(np); + +	return 0; +} +arch_initcall(mpc8xxx_add_gpiochips); diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8e3478c995e..f6299cca781 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -563,6 +563,51 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)  #endif /* CONFIG_MPIC_U3_HT_IRQS */ +#ifdef CONFIG_SMP +static int irq_choose_cpu(unsigned int virt_irq) +{ +	cpumask_t mask = irq_desc[virt_irq].affinity; +	int cpuid; + +	if (cpus_equal(mask, CPU_MASK_ALL)) { +		static int irq_rover; +		static DEFINE_SPINLOCK(irq_rover_lock); +		unsigned long flags; + +		/* Round-robin distribution... */ +	do_round_robin: +		spin_lock_irqsave(&irq_rover_lock, flags); + +		while (!cpu_online(irq_rover)) { +			if (++irq_rover >= NR_CPUS) +				irq_rover = 0; +		} +		cpuid = irq_rover; +		do { +			if (++irq_rover >= NR_CPUS) +				irq_rover = 0; +		} while (!cpu_online(irq_rover)); + +		spin_unlock_irqrestore(&irq_rover_lock, flags); +	} else { +		cpumask_t tmp; + +		cpus_and(tmp, cpu_online_map, mask); + +		if (cpus_empty(tmp)) +			goto do_round_robin; + +		cpuid = first_cpu(tmp); +	} + +	return cpuid; +} +#else +static int irq_choose_cpu(unsigned int virt_irq) +{ +	return hard_smp_processor_id(); +} +#endif  #define mpic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq) @@ -777,12 +822,18 @@ void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)  	struct mpic *mpic = mpic_from_irq(irq);  	unsigned int src = mpic_irq_to_hw(irq); -	cpumask_t tmp; +	if (mpic->flags & MPIC_SINGLE_DEST_CPU) { +		int cpuid = irq_choose_cpu(irq); -	cpus_and(tmp, cpumask, cpu_online_map); +		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); +	} else { +		cpumask_t tmp; -	mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), -		       mpic_physmask(cpus_addr(tmp)[0]));	 +		cpus_and(tmp, cpumask, cpu_online_map); + +		mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), +			       mpic_physmask(cpus_addr(tmp)[0])); +	}  }  static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) diff --git a/arch/powerpc/sysdev/mpic.h b/arch/powerpc/sysdev/mpic.h index fbf8a266941..6209c62a426 100644 --- a/arch/powerpc/sysdev/mpic.h +++ b/arch/powerpc/sysdev/mpic.h @@ -14,8 +14,6 @@  #ifdef CONFIG_PCI_MSI  extern void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq);  extern int mpic_msi_init_allocator(struct mpic *mpic); -extern irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num); -extern void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num);  extern int mpic_u3msi_init(struct mpic *mpic);  extern int mpic_pasemi_msi_init(struct mpic *mpic);  #else diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index de3e5e8bc32..1d44eee80fa 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c @@ -15,59 +15,17 @@  #include <asm/prom.h>  #include <asm/hw_irq.h>  #include <asm/ppc-pci.h> +#include <asm/msi_bitmap.h>  #include <sysdev/mpic.h> -static void __mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq) -{ -	pr_debug("mpic: reserving hwirq 0x%lx\n", hwirq); -	bitmap_allocate_region(mpic->hwirq_bitmap, hwirq, 0); -} -  void mpic_msi_reserve_hwirq(struct mpic *mpic, irq_hw_number_t hwirq)  { -	unsigned long flags; -  	/* The mpic calls this even when there is no allocator setup */ -	if (!mpic->hwirq_bitmap) +	if (!mpic->msi_bitmap.bitmap)  		return; -	spin_lock_irqsave(&mpic->bitmap_lock, flags); -	__mpic_msi_reserve_hwirq(mpic, hwirq); -	spin_unlock_irqrestore(&mpic->bitmap_lock, flags); -} - -irq_hw_number_t mpic_msi_alloc_hwirqs(struct mpic *mpic, int num) -{ -	unsigned long flags; -	int offset, order = get_count_order(num); - -	spin_lock_irqsave(&mpic->bitmap_lock, flags); -	/* -	 * This is fast, but stricter than we need. We might want to add -	 * a fallback routine which does a linear search with no alignment. -	 */ -	offset = bitmap_find_free_region(mpic->hwirq_bitmap, mpic->irq_count, -					 order); -	spin_unlock_irqrestore(&mpic->bitmap_lock, flags); - -	pr_debug("mpic: allocated 0x%x (2^%d) at offset 0x%x\n", -		 num, order, offset); - -	return offset; -} - -void mpic_msi_free_hwirqs(struct mpic *mpic, int offset, int num) -{ -	unsigned long flags; -	int order = get_count_order(num); - -	pr_debug("mpic: freeing 0x%x (2^%d) at offset 0x%x\n", -		 num, order, offset); - -	spin_lock_irqsave(&mpic->bitmap_lock, flags); -	bitmap_release_region(mpic->hwirq_bitmap, offset, order); -	spin_unlock_irqrestore(&mpic->bitmap_lock, flags); +	msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);  }  #ifdef CONFIG_MPIC_U3_HT_IRQS @@ -83,13 +41,13 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  	/* Reserve source numbers we know are reserved in the HW */  	for (i = 0;   i < 8;   i++) -		__mpic_msi_reserve_hwirq(mpic, i); +		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);  	for (i = 42;  i < 46;  i++) -		__mpic_msi_reserve_hwirq(mpic, i); +		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);  	for (i = 100; i < 105; i++) -		__mpic_msi_reserve_hwirq(mpic, i); +		msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, i);  	np = NULL;  	while ((np = of_find_all_nodes(np))) { @@ -99,7 +57,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  		while (of_irq_map_one(np, index++, &oirq) == 0) {  			ops->xlate(mpic->irqhost, NULL, oirq.specifier,  						oirq.size, &hwirq, &flags); -			__mpic_msi_reserve_hwirq(mpic, hwirq); +			msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq);  		}  	} @@ -112,70 +70,25 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic)  }  #endif -static int mpic_msi_reserve_dt_hwirqs(struct mpic *mpic) -{ -	int i, len; -	const u32 *p; - -	p = of_get_property(mpic->irqhost->of_node, -			    "msi-available-ranges", &len); -	if (!p) { -		pr_debug("mpic: no msi-available-ranges property found on %s\n", -			  mpic->irqhost->of_node->full_name); -		return -ENODEV; -	} - -	if (len % 8 != 0) { -		printk(KERN_WARNING "mpic: Malformed msi-available-ranges " -		       "property on %s\n", mpic->irqhost->of_node->full_name); -		return -EINVAL; -	} - -	bitmap_allocate_region(mpic->hwirq_bitmap, 0, -			       get_count_order(mpic->irq_count)); - -	/* Format is: (<u32 start> <u32 count>)+ */ -	len /= sizeof(u32); -	for (i = 0; i < len / 2; i++, p += 2) -		mpic_msi_free_hwirqs(mpic, *p, *(p + 1)); - -	return 0; -} -  int mpic_msi_init_allocator(struct mpic *mpic)  { -	int rc, size; - -	BUG_ON(mpic->hwirq_bitmap); -	spin_lock_init(&mpic->bitmap_lock); +	int rc; -	size = BITS_TO_LONGS(mpic->irq_count) * sizeof(long); -	pr_debug("mpic: allocator bitmap size is 0x%x bytes\n", size); +	rc = msi_bitmap_alloc(&mpic->msi_bitmap, mpic->irq_count, +			      mpic->irqhost->of_node); +	if (rc) +		return rc; -	mpic->hwirq_bitmap = alloc_maybe_bootmem(size, GFP_KERNEL); - -	if (!mpic->hwirq_bitmap) { -		pr_debug("mpic: ENOMEM allocating allocator bitmap!\n"); -		return -ENOMEM; -	} - -	memset(mpic->hwirq_bitmap, 0, size); - -	rc = mpic_msi_reserve_dt_hwirqs(mpic); -	if (rc) { +	rc = msi_bitmap_reserve_dt_hwirqs(&mpic->msi_bitmap); +	if (rc > 0) {  		if (mpic->flags & MPIC_U3_HT_IRQS)  			rc = mpic_msi_reserve_u3_hwirqs(mpic); -		if (rc) -			goto out_free; +		if (rc) { +			msi_bitmap_free(&mpic->msi_bitmap); +			return rc; +		}  	}  	return 0; - - out_free: -	if (mem_init_done) -		kfree(mpic->hwirq_bitmap); - -	mpic->hwirq_bitmap = NULL; -	return rc;  } diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 68aff607667..656cb772b69 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c @@ -22,6 +22,7 @@  #include <asm/prom.h>  #include <asm/hw_irq.h>  #include <asm/ppc-pci.h> +#include <asm/msi_bitmap.h>  #include "mpic.h" @@ -81,8 +82,8 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)  			continue;  		set_irq_msi(entry->irq, NULL); -		mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), -				     ALLOC_CHUNK); +		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, +				       virq_to_hw(entry->irq), ALLOC_CHUNK);  		irq_dispose_mapping(entry->irq);  	} @@ -91,11 +92,10 @@ static void pasemi_msi_teardown_msi_irqs(struct pci_dev *pdev)  static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  { -	irq_hw_number_t hwirq;  	unsigned int virq;  	struct msi_desc *entry;  	struct msi_msg msg; -	int ret; +	int hwirq;  	pr_debug("pasemi_msi_setup_msi_irqs, pdev %p nvec %d type %d\n",  		 pdev, nvec, type); @@ -109,17 +109,19 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		 * few MSIs for someone, but restrictions will apply to how the  		 * sources can be changed independently.  		 */ -		ret = mpic_msi_alloc_hwirqs(msi_mpic, ALLOC_CHUNK); -		hwirq = ret; -		if (ret < 0) { +		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, +						ALLOC_CHUNK); +		if (hwirq < 0) {  			pr_debug("pasemi_msi: failed allocating hwirq\n");  			return hwirq;  		}  		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);  		if (virq == NO_IRQ) { -			pr_debug("pasemi_msi: failed mapping hwirq 0x%lx\n", hwirq); -			mpic_msi_free_hwirqs(msi_mpic, hwirq, ALLOC_CHUNK); +			pr_debug("pasemi_msi: failed mapping hwirq 0x%x\n", +				  hwirq); +			msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, +					       ALLOC_CHUNK);  			return -ENOSPC;  		} @@ -133,8 +135,8 @@ static int pasemi_msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		set_irq_chip(virq, &mpic_pasemi_msi_chip);  		set_irq_type(virq, IRQ_TYPE_EDGE_RISING); -		pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%lx) addr 0x%x\n", -			  virq, hwirq, msg.address_lo); +		pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \ +			 "addr 0x%x\n", virq, hwirq, msg.address_lo);  		/* Likewise, the device writes [0...511] into the target  		 * register to generate MSI [512...1023] diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index 6e2f8686fdf..0a8f5a9e87c 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c @@ -16,6 +16,7 @@  #include <asm/prom.h>  #include <asm/hw_irq.h>  #include <asm/ppc-pci.h> +#include <asm/msi_bitmap.h>  #include "mpic.h" @@ -101,7 +102,8 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)  			continue;  		set_irq_msi(entry->irq, NULL); -		mpic_msi_free_hwirqs(msi_mpic, virq_to_hw(entry->irq), 1); +		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, +				       virq_to_hw(entry->irq), 1);  		irq_dispose_mapping(entry->irq);  	} @@ -110,29 +112,27 @@ static void u3msi_teardown_msi_irqs(struct pci_dev *pdev)  static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  { -	irq_hw_number_t hwirq;  	unsigned int virq;  	struct msi_desc *entry;  	struct msi_msg msg;  	u64 addr; -	int ret; +	int hwirq;  	addr = find_ht_magic_addr(pdev);  	msg.address_lo = addr & 0xFFFFFFFF;  	msg.address_hi = addr >> 32;  	list_for_each_entry(entry, &pdev->msi_list, list) { -		ret = mpic_msi_alloc_hwirqs(msi_mpic, 1); -		if (ret < 0) { +		hwirq = msi_bitmap_alloc_hwirqs(&msi_mpic->msi_bitmap, 1); +		if (hwirq < 0) {  			pr_debug("u3msi: failed allocating hwirq\n"); -			return ret; +			return hwirq;  		} -		hwirq = ret;  		virq = irq_create_mapping(msi_mpic->irqhost, hwirq);  		if (virq == NO_IRQ) { -			pr_debug("u3msi: failed mapping hwirq 0x%lx\n", hwirq); -			mpic_msi_free_hwirqs(msi_mpic, hwirq, 1); +			pr_debug("u3msi: failed mapping hwirq 0x%x\n", hwirq); +			msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap, hwirq, 1);  			return -ENOSPC;  		} @@ -140,8 +140,8 @@ static int u3msi_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)  		set_irq_chip(virq, &mpic_u3msi_chip);  		set_irq_type(virq, IRQ_TYPE_EDGE_RISING); -		pr_debug("u3msi: allocated virq 0x%x (hw 0x%lx) addr 0x%lx\n", -			  virq, hwirq, addr); +		pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n", +			  virq, hwirq, (unsigned long)addr);  		msg.data = hwirq;  		write_msi_msg(virq, &msg); diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c new file mode 100644 index 00000000000..f84217b8863 --- /dev/null +++ b/arch/powerpc/sysdev/msi_bitmap.c @@ -0,0 +1,247 @@ +/* + * Copyright 2006-2008, Michael Ellerman, 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; version 2 of the + * License. + * + */ + +#include <linux/kernel.h> +#include <linux/bitmap.h> +#include <asm/msi_bitmap.h> + +int msi_bitmap_alloc_hwirqs(struct msi_bitmap *bmp, int num) +{ +	unsigned long flags; +	int offset, order = get_count_order(num); + +	spin_lock_irqsave(&bmp->lock, flags); +	/* +	 * This is fast, but stricter than we need. We might want to add +	 * a fallback routine which does a linear search with no alignment. +	 */ +	offset = bitmap_find_free_region(bmp->bitmap, bmp->irq_count, order); +	spin_unlock_irqrestore(&bmp->lock, flags); + +	pr_debug("msi_bitmap: allocated 0x%x (2^%d) at offset 0x%x\n", +		 num, order, offset); + +	return offset; +} + +void msi_bitmap_free_hwirqs(struct msi_bitmap *bmp, unsigned int offset, +			    unsigned int num) +{ +	unsigned long flags; +	int order = get_count_order(num); + +	pr_debug("msi_bitmap: freeing 0x%x (2^%d) at offset 0x%x\n", +		 num, order, offset); + +	spin_lock_irqsave(&bmp->lock, flags); +	bitmap_release_region(bmp->bitmap, offset, order); +	spin_unlock_irqrestore(&bmp->lock, flags); +} + +void msi_bitmap_reserve_hwirq(struct msi_bitmap *bmp, unsigned int hwirq) +{ +	unsigned long flags; + +	pr_debug("msi_bitmap: reserving hwirq 0x%x\n", hwirq); + +	spin_lock_irqsave(&bmp->lock, flags); +	bitmap_allocate_region(bmp->bitmap, hwirq, 0); +	spin_unlock_irqrestore(&bmp->lock, flags); +} + +/** + * msi_bitmap_reserve_dt_hwirqs - Reserve irqs specified in the device tree. + * @bmp: pointer to the MSI bitmap. + * + * Looks in the device tree to see if there is a property specifying which + * irqs can be used for MSI. If found those irqs reserved in the device tree + * are reserved in the bitmap. + * + * Returns 0 for success, < 0 if there was an error, and > 0 if no property + * was found in the device tree. + **/ +int msi_bitmap_reserve_dt_hwirqs(struct msi_bitmap *bmp) +{ +	int i, j, len; +	const u32 *p; + +	if (!bmp->of_node) +		return 1; + +	p = of_get_property(bmp->of_node, "msi-available-ranges", &len); +	if (!p) { +		pr_debug("msi_bitmap: no msi-available-ranges property " \ +			 "found on %s\n", bmp->of_node->full_name); +		return 1; +	} + +	if (len % (2 * sizeof(u32)) != 0) { +		printk(KERN_WARNING "msi_bitmap: Malformed msi-available-ranges" +		       " property on %s\n", bmp->of_node->full_name); +		return -EINVAL; +	} + +	bitmap_allocate_region(bmp->bitmap, 0, get_count_order(bmp->irq_count)); + +	spin_lock(&bmp->lock); + +	/* Format is: (<u32 start> <u32 count>)+ */ +	len /= 2 * sizeof(u32); +	for (i = 0; i < len; i++, p += 2) { +		for (j = 0; j < *(p + 1); j++) +			bitmap_release_region(bmp->bitmap, *p + j, 0); +	} + +	spin_unlock(&bmp->lock); + +	return 0; +} + +int msi_bitmap_alloc(struct msi_bitmap *bmp, unsigned int irq_count, +		     struct device_node *of_node) +{ +	int size; + +	if (!irq_count) +		return -EINVAL; + +	size = BITS_TO_LONGS(irq_count) * sizeof(long); +	pr_debug("msi_bitmap: allocator bitmap size is 0x%x bytes\n", size); + +	bmp->bitmap = zalloc_maybe_bootmem(size, GFP_KERNEL); +	if (!bmp->bitmap) { +		pr_debug("msi_bitmap: ENOMEM allocating allocator bitmap!\n"); +		return -ENOMEM; +	} + +	/* We zalloc'ed the bitmap, so all irqs are free by default */ +	spin_lock_init(&bmp->lock); +	bmp->of_node = of_node_get(of_node); +	bmp->irq_count = irq_count; + +	return 0; +} + +void msi_bitmap_free(struct msi_bitmap *bmp) +{ +	/* we can't free the bitmap we don't know if it's bootmem etc. */ +	of_node_put(bmp->of_node); +	bmp->bitmap = NULL; +} + +#ifdef CONFIG_MSI_BITMAP_SELFTEST + +#define check(x)	\ +	if (!(x)) printk("msi_bitmap: test failed at line %d\n", __LINE__); + +void test_basics(void) +{ +	struct msi_bitmap bmp; +	int i, size = 512; + +	/* Can't allocate a bitmap of 0 irqs */ +	check(msi_bitmap_alloc(&bmp, 0, NULL) != 0); + +	/* of_node may be NULL */ +	check(0 == msi_bitmap_alloc(&bmp, size, NULL)); + +	/* Should all be free by default */ +	check(0 == bitmap_find_free_region(bmp.bitmap, size, +					   get_count_order(size))); +	bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); + +	/* With no node, there's no msi-available-ranges, so expect > 0 */ +	check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0); + +	/* Should all still be free */ +	check(0 == bitmap_find_free_region(bmp.bitmap, size, +					   get_count_order(size))); +	bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); + +	/* Check we can fill it up and then no more */ +	for (i = 0; i < size; i++) +		check(msi_bitmap_alloc_hwirqs(&bmp, 1) >= 0); + +	check(msi_bitmap_alloc_hwirqs(&bmp, 1) < 0); + +	/* Should all be allocated */ +	check(bitmap_find_free_region(bmp.bitmap, size, 0) < 0); + +	/* And if we free one we can then allocate another */ +	msi_bitmap_free_hwirqs(&bmp, size / 2, 1); +	check(msi_bitmap_alloc_hwirqs(&bmp, 1) == size / 2); + +	msi_bitmap_free(&bmp); + +	/* Clients may check bitmap == NULL for "not-allocated" */ +	check(bmp.bitmap == NULL); + +	kfree(bmp.bitmap); +} + +void test_of_node(void) +{ +	u32 prop_data[] = { 10, 10, 25, 3, 40, 1, 100, 100, 200, 20 }; +	const char *expected_str = "0-9,20-24,28-39,41-99,220-255"; +	char *prop_name = "msi-available-ranges"; +	char *node_name = "/fakenode"; +	struct device_node of_node; +	struct property prop; +	struct msi_bitmap bmp; +	int size = 256; +	DECLARE_BITMAP(expected, size); + +	/* There should really be a struct device_node allocator */ +	memset(&of_node, 0, sizeof(of_node)); +	kref_init(&of_node.kref); +	of_node.full_name = node_name; + +	check(0 == msi_bitmap_alloc(&bmp, size, &of_node)); + +	/* No msi-available-ranges, so expect > 0 */ +	check(msi_bitmap_reserve_dt_hwirqs(&bmp) > 0); + +	/* Should all still be free */ +	check(0 == bitmap_find_free_region(bmp.bitmap, size, +					   get_count_order(size))); +	bitmap_release_region(bmp.bitmap, 0, get_count_order(size)); + +	/* Now create a fake msi-available-ranges property */ + +	/* There should really .. oh whatever */ +	memset(&prop, 0, sizeof(prop)); +	prop.name = prop_name; +	prop.value = &prop_data; +	prop.length = sizeof(prop_data); + +	of_node.properties = ∝ + +	/* msi-available-ranges, so expect == 0 */ +	check(msi_bitmap_reserve_dt_hwirqs(&bmp) == 0); + +	/* Check we got the expected result */ +	check(0 == bitmap_parselist(expected_str, expected, size)); +	check(bitmap_equal(expected, bmp.bitmap, size)); + +	msi_bitmap_free(&bmp); +	kfree(bmp.bitmap); +} + +int msi_bitmap_selftest(void) +{ +	printk(KERN_DEBUG "Running MSI bitmap self-tests ...\n"); + +	test_basics(); +	test_of_node(); + +	return 0; +} +late_initcall(msi_bitmap_selftest); +#endif /* CONFIG_MSI_BITMAP_SELFTEST */ diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 32e0ad0ebea..b6bd775d2e2 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c @@ -293,10 +293,8 @@ static int __init mv64x60_eth_device_setup(struct device_node *np, int id,  		return -ENODEV;  	prop = of_get_property(phy, "reg", NULL); -	if (prop) { -		pdata.force_phy_addr = 1; -		pdata.phy_addr = *prop; -	} +	if (prop) +		pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop);  	of_node_put(phy); diff --git a/arch/powerpc/sysdev/ppc4xx_gpio.c b/arch/powerpc/sysdev/ppc4xx_gpio.c new file mode 100644 index 00000000000..110efe2a54f --- /dev/null +++ b/arch/powerpc/sysdev/ppc4xx_gpio.c @@ -0,0 +1,217 @@ +/* + * PPC4xx gpio driver + * + * Copyright (c) 2008 Harris Corporation + * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * Copyright (c) MontaVista Software, Inc. 2008. + * + * Author: Steve Falco <sfalco@harris.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/of_gpio.h> +#include <linux/gpio.h> +#include <linux/types.h> + +#define GPIO_MASK(gpio)		(0x80000000 >> (gpio)) +#define GPIO_MASK2(gpio)	(0xc0000000 >> ((gpio) * 2)) + +/* Physical GPIO register layout */ +struct ppc4xx_gpio { +	__be32 or; +	__be32 tcr; +	__be32 osrl; +	__be32 osrh; +	__be32 tsrl; +	__be32 tsrh; +	__be32 odr; +	__be32 ir; +	__be32 rr1; +	__be32 rr2; +	__be32 rr3; +	__be32 reserved1; +	__be32 isr1l; +	__be32 isr1h; +	__be32 isr2l; +	__be32 isr2h; +	__be32 isr3l; +	__be32 isr3h; +}; + +struct ppc4xx_gpio_chip { +	struct of_mm_gpio_chip mm_gc; +	spinlock_t lock; +}; + +/* + * GPIO LIB API implementation for GPIOs + * + * There are a maximum of 32 gpios in each gpio controller. + */ + +static inline struct ppc4xx_gpio_chip * +to_ppc4xx_gpiochip(struct of_mm_gpio_chip *mm_gc) +{ +	return container_of(mm_gc, struct ppc4xx_gpio_chip, mm_gc); +} + +static int ppc4xx_gpio_get(struct gpio_chip *gc, unsigned int gpio) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct ppc4xx_gpio __iomem *regs = mm_gc->regs; + +	return in_be32(®s->ir) & GPIO_MASK(gpio); +} + +static inline void +__ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct ppc4xx_gpio __iomem *regs = mm_gc->regs; + +	if (val) +		setbits32(®s->or, GPIO_MASK(gpio)); +	else +		clrbits32(®s->or, GPIO_MASK(gpio)); +} + +static void +ppc4xx_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); +	unsigned long flags; + +	spin_lock_irqsave(&chip->lock, flags); + +	__ppc4xx_gpio_set(gc, gpio, val); + +	spin_unlock_irqrestore(&chip->lock, flags); + +	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); +} + +static int ppc4xx_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); +	struct ppc4xx_gpio __iomem *regs = mm_gc->regs; +	unsigned long flags; + +	spin_lock_irqsave(&chip->lock, flags); + +	/* Disable open-drain function */ +	clrbits32(®s->odr, GPIO_MASK(gpio)); + +	/* Float the pin */ +	clrbits32(®s->tcr, GPIO_MASK(gpio)); + +	/* Bits 0-15 use TSRL/OSRL, bits 16-31 use TSRH/OSRH */ +	if (gpio < 16) { +		clrbits32(®s->osrl, GPIO_MASK2(gpio)); +		clrbits32(®s->tsrl, GPIO_MASK2(gpio)); +	} else { +		clrbits32(®s->osrh, GPIO_MASK2(gpio)); +		clrbits32(®s->tsrh, GPIO_MASK2(gpio)); +	} + +	spin_unlock_irqrestore(&chip->lock, flags); + +	return 0; +} + +static int +ppc4xx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) +{ +	struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); +	struct ppc4xx_gpio_chip *chip = to_ppc4xx_gpiochip(mm_gc); +	struct ppc4xx_gpio __iomem *regs = mm_gc->regs; +	unsigned long flags; + +	spin_lock_irqsave(&chip->lock, flags); + +	/* First set initial value */ +	__ppc4xx_gpio_set(gc, gpio, val); + +	/* Disable open-drain function */ +	clrbits32(®s->odr, GPIO_MASK(gpio)); + +	/* Drive the pin */ +	setbits32(®s->tcr, GPIO_MASK(gpio)); + +	/* Bits 0-15 use TSRL, bits 16-31 use TSRH */ +	if (gpio < 16) { +		clrbits32(®s->osrl, GPIO_MASK2(gpio)); +		clrbits32(®s->tsrl, GPIO_MASK2(gpio)); +	} else { +		clrbits32(®s->osrh, GPIO_MASK2(gpio)); +		clrbits32(®s->tsrh, GPIO_MASK2(gpio)); +	} + +	spin_unlock_irqrestore(&chip->lock, flags); + +	pr_debug("%s: gpio: %d val: %d\n", __func__, gpio, val); + +	return 0; +} + +static int __init ppc4xx_add_gpiochips(void) +{ +	struct device_node *np; + +	for_each_compatible_node(np, NULL, "ibm,ppc4xx-gpio") { +		int ret; +		struct ppc4xx_gpio_chip *ppc4xx_gc; +		struct of_mm_gpio_chip *mm_gc; +		struct of_gpio_chip *of_gc; +		struct gpio_chip *gc; + +		ppc4xx_gc = kzalloc(sizeof(*ppc4xx_gc), GFP_KERNEL); +		if (!ppc4xx_gc) { +			ret = -ENOMEM; +			goto err; +		} + +		spin_lock_init(&ppc4xx_gc->lock); + +		mm_gc = &ppc4xx_gc->mm_gc; +		of_gc = &mm_gc->of_gc; +		gc = &of_gc->gc; + +		of_gc->gpio_cells = 2; +		gc->ngpio = 32; +		gc->direction_input = ppc4xx_gpio_dir_in; +		gc->direction_output = ppc4xx_gpio_dir_out; +		gc->get = ppc4xx_gpio_get; +		gc->set = ppc4xx_gpio_set; + +		ret = of_mm_gpiochip_add(np, mm_gc); +		if (ret) +			goto err; +		continue; +err: +		pr_err("%s: registration failed with status %d\n", +		       np->full_name, ret); +		kfree(ppc4xx_gc); +		/* try others anyway */ +	} +	return 0; +} +arch_initcall(ppc4xx_add_gpiochips); diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c index fb368dfde5d..d3e4d61030b 100644 --- a/arch/powerpc/sysdev/ppc4xx_pci.c +++ b/arch/powerpc/sysdev/ppc4xx_pci.c @@ -30,24 +30,19 @@  #include <asm/machdep.h>  #include <asm/dcr.h>  #include <asm/dcr-regs.h> +#include <mm/mmu_decl.h>  #include "ppc4xx_pci.h"  static int dma_offset_set; -/* Move that to a useable header */ -extern unsigned long total_memory; -  #define U64_TO_U32_LOW(val)	((u32)((val) & 0x00000000ffffffffULL))  #define U64_TO_U32_HIGH(val)	((u32)((val) >> 32)) -#ifdef CONFIG_RESOURCES_64BIT -#define RES_TO_U32_LOW(val)	U64_TO_U32_LOW(val) -#define RES_TO_U32_HIGH(val)	U64_TO_U32_HIGH(val) -#else -#define RES_TO_U32_LOW(val)	(val) -#define RES_TO_U32_HIGH(val)	(0) -#endif +#define RES_TO_U32_LOW(val)	\ +	((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_LOW(val) : (val)) +#define RES_TO_U32_HIGH(val)	\ +	((sizeof(resource_size_t) > sizeof(u32)) ? U64_TO_U32_HIGH(val) : (0))  static inline int ppc440spe_revA(void)  { @@ -105,7 +100,8 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,  	/* Default */  	res->start = 0; -	res->end = size = 0x80000000; +	size = 0x80000000; +	res->end = size - 1;  	res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;  	/* Get dma-ranges property */ @@ -145,12 +141,11 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,  		/* Use that */  		res->start = pci_addr; -#ifndef CONFIG_RESOURCES_64BIT  		/* Beware of 32 bits resources */ -		if ((pci_addr + size) > 0x100000000ull) +		if (sizeof(resource_size_t) == sizeof(u32) && +		    (pci_addr + size) > 0x100000000ull)  			res->end = 0xffffffff;  		else -#endif  			res->end = res->start + size - 1;  		break;  	} @@ -167,13 +162,13 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,  	 */  	if (size < total_memory) {  		printk(KERN_ERR "%s: dma-ranges too small " -		       "(size=%llx total_memory=%lx)\n", -		       hose->dn->full_name, size, total_memory); +		       "(size=%llx total_memory=%llx)\n", +		       hose->dn->full_name, size, (u64)total_memory);  		return -ENXIO;  	}  	/* Check we are a power of 2 size and that base is a multiple of size*/ -	if (!is_power_of_2(size) || +	if ((size & (size - 1)) != 0  ||  	    (res->start & (size - 1)) != 0) {  		printk(KERN_ERR "%s: dma-ranges unaligned\n",  		       hose->dn->full_name); @@ -277,9 +272,16 @@ static void __init ppc4xx_probe_pci_bridge(struct device_node *np)  	const int *bus_range;  	int primary = 0; +	/* Check if device is enabled */ +	if (!of_device_is_available(np)) { +		printk(KERN_INFO "%s: Port disabled via device-tree\n", +		       np->full_name); +		return; +	} +  	/* Fetch config space registers address */  	if (of_address_to_resource(np, 0, &rsrc_cfg)) { -		printk(KERN_ERR "%s:Can't get PCI config register base !", +		printk(KERN_ERR "%s: Can't get PCI config register base !",  		       np->full_name);  		return;  	} @@ -810,7 +812,7 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  	switch (port->index) {  	case 0:  		mtdcri(SDR0, PESDR0_460EX_L0CDRCTL, 0x00003230); -		mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000136); +		mtdcri(SDR0, PESDR0_460EX_L0DRV, 0x00000130);  		mtdcri(SDR0, PESDR0_460EX_L0CLK, 0x00000006);  		mtdcri(SDR0, PESDR0_460EX_PHY_CTL_RST,0x10000000); @@ -821,10 +823,10 @@ static int ppc460ex_pciex_init_port_hw(struct ppc4xx_pciex_port *port)  		mtdcri(SDR0, PESDR1_460EX_L1CDRCTL, 0x00003230);  		mtdcri(SDR0, PESDR1_460EX_L2CDRCTL, 0x00003230);  		mtdcri(SDR0, PESDR1_460EX_L3CDRCTL, 0x00003230); -		mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000136); -		mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000136); -		mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000136); -		mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000136); +		mtdcri(SDR0, PESDR1_460EX_L0DRV, 0x00000130); +		mtdcri(SDR0, PESDR1_460EX_L1DRV, 0x00000130); +		mtdcri(SDR0, PESDR1_460EX_L2DRV, 0x00000130); +		mtdcri(SDR0, PESDR1_460EX_L3DRV, 0x00000130);  		mtdcri(SDR0, PESDR1_460EX_L0CLK, 0x00000006);  		mtdcri(SDR0, PESDR1_460EX_L1CLK, 0x00000006);  		mtdcri(SDR0, PESDR1_460EX_L2CLK, 0x00000006); diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig index 1ce546462be..76ffbc48d4b 100644 --- a/arch/powerpc/sysdev/qe_lib/Kconfig +++ b/arch/powerpc/sysdev/qe_lib/Kconfig @@ -24,12 +24,3 @@ config QE_USB  	bool  	help  	  QE USB Host Controller support - -config QE_GPIO -	bool "QE GPIO support" -	depends on QUICC_ENGINE -	select GENERIC_GPIO -	select ARCH_REQUIRE_GPIOLIB -	help -	  Say Y here if you're going to use hardware that connects to the -	  QE GPIOs.  | 
