diff options
Diffstat (limited to 'arch/arm/mach-integrator/impd1.c')
| -rw-r--r-- | arch/arm/mach-integrator/impd1.c | 95 | 
1 files changed, 58 insertions, 37 deletions
diff --git a/arch/arm/mach-integrator/impd1.c b/arch/arm/mach-integrator/impd1.c index 9f82f9dcbb9..3ce880729cf 100644 --- a/arch/arm/mach-integrator/impd1.c +++ b/arch/arm/mach-integrator/impd1.c @@ -23,10 +23,11 @@  #include <linux/io.h>  #include <linux/platform_data/clk-integrator.h>  #include <linux/slab.h> +#include <linux/irqchip/arm-vic.h> -#include <mach/lm.h> -#include <mach/impd1.h>  #include <asm/sizes.h> +#include "lm.h" +#include "impd1.h"  static int module_id; @@ -35,6 +36,7 @@ MODULE_PARM_DESC(lmid, "logic module stack position");  struct impd1_module {  	void __iomem	*base; +	void __iomem	*vic_base;  };  void impd1_tweak_control(struct device *dev, u32 mask, u32 val) @@ -262,9 +264,6 @@ struct impd1_device {  static struct impd1_device impd1_devs[] = {  	{ -		.offset	= 0x03000000, -		.id	= 0x00041190, -	}, {  		.offset	= 0x00100000,  		.irq	= { 1 },  		.id	= 0x00141011, @@ -304,46 +303,77 @@ static struct impd1_device impd1_devs[] = {  	}  }; -static int impd1_probe(struct lm_device *dev) +/* + * Valid IRQs: 0 thru 9 and 11, 10 unused. + */ +#define IMPD1_VALID_IRQS 0x00000bffU + +/* + * As this module is bool, it is OK to have this as __init_refok() - no + * probe calls will be done after the initial system bootup, as devices + * are discovered as part of the machine startup. + */ +static int __init_refok impd1_probe(struct lm_device *dev)  {  	struct impd1_module *impd1; -	int i, ret; +	int irq_base; +	int i;  	if (dev->id != module_id)  		return -EINVAL; -	if (!request_mem_region(dev->resource.start, SZ_4K, "LM registers")) +	if (!devm_request_mem_region(&dev->dev, dev->resource.start, +				     SZ_4K, "LM registers"))  		return -EBUSY; -	impd1 = kzalloc(sizeof(struct impd1_module), GFP_KERNEL); -	if (!impd1) { -		ret = -ENOMEM; -		goto release_lm; -	} +	impd1 = devm_kzalloc(&dev->dev, sizeof(struct impd1_module), +			     GFP_KERNEL); +	if (!impd1) +		return -ENOMEM; -	impd1->base = ioremap(dev->resource.start, SZ_4K); -	if (!impd1->base) { -		ret = -ENOMEM; -		goto free_impd1; -	} +	impd1->base = devm_ioremap(&dev->dev, dev->resource.start, SZ_4K); +	if (!impd1->base) +		return -ENOMEM; -	lm_set_drvdata(dev, impd1); +	integrator_impd1_clk_init(impd1->base, dev->id); -	printk("IM-PD1 found at 0x%08lx\n", -		(unsigned long)dev->resource.start); +	if (!devm_request_mem_region(&dev->dev, +				     dev->resource.start + 0x03000000, +				     SZ_4K, "VIC")) +		return -EBUSY; -	integrator_impd1_clk_init(impd1->base, dev->id); +	impd1->vic_base = devm_ioremap(&dev->dev, +				       dev->resource.start + 0x03000000, +				       SZ_4K); +	if (!impd1->vic_base) +		return -ENOMEM; + +	irq_base = vic_init_cascaded(impd1->vic_base, dev->irq, +				     IMPD1_VALID_IRQS, 0); + +	lm_set_drvdata(dev, impd1); + +	dev_info(&dev->dev, "IM-PD1 found at 0x%08lx\n", +		 (unsigned long)dev->resource.start);  	for (i = 0; i < ARRAY_SIZE(impd1_devs); i++) {  		struct impd1_device *idev = impd1_devs + i;  		struct amba_device *d;  		unsigned long pc_base;  		char devname[32]; +		int irq1 = idev->irq[0]; +		int irq2 = idev->irq[1]; + +		/* Translate IRQs to IM-PD1 local numberspace */ +		if (irq1) +			irq1 += irq_base; +		if (irq2) +			irq2 += irq_base;  		pc_base = dev->resource.start + idev->offset;  		snprintf(devname, 32, "lm%x:%5.5lx", dev->id, idev->offset >> 12);  		d = amba_ahb_device_add_res(&dev->dev, devname, pc_base, SZ_4K, -					    dev->irq, dev->irq, +					    irq1, irq2,  					    idev->platform_data, idev->id,  					    &dev->resource);  		if (IS_ERR(d)) { @@ -353,14 +383,6 @@ static int impd1_probe(struct lm_device *dev)  	}  	return 0; - - free_impd1: -	if (impd1 && impd1->base) -		iounmap(impd1->base); -	kfree(impd1); - release_lm: -	release_mem_region(dev->resource.start, SZ_4K); -	return ret;  }  static int impd1_remove_one(struct device *dev, void *data) @@ -371,21 +393,20 @@ static int impd1_remove_one(struct device *dev, void *data)  static void impd1_remove(struct lm_device *dev)  { -	struct impd1_module *impd1 = lm_get_drvdata(dev); -  	device_for_each_child(&dev->dev, NULL, impd1_remove_one);  	integrator_impd1_clk_exit(dev->id);  	lm_set_drvdata(dev, NULL); - -	iounmap(impd1->base); -	kfree(impd1); -	release_mem_region(dev->resource.start, SZ_4K);  }  static struct lm_driver impd1_driver = {  	.drv = {  		.name	= "impd1", +		/* +		 * As we're dropping the probe() function, suppress driver +		 * binding from sysfs. +		 */ +		.suppress_bind_attrs = true,  	},  	.probe		= impd1_probe,  	.remove		= impd1_remove,  | 
