diff options
Diffstat (limited to 'drivers/amba/bus.c')
-rw-r--r-- | drivers/amba/bus.c | 147 |
1 files changed, 80 insertions, 67 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 54eaf96ab217..cc273226dbd0 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -247,8 +247,7 @@ static int amba_pm_restore(struct device *dev) /* * Hooks to provide runtime PM of the pclk (bus clock). It is safe to * enable/disable the bus clock at runtime PM suspend/resume as this - * does not result in loss of context. However, disabling vcore power - * would do, so we leave that to the driver. + * does not result in loss of context. */ static int amba_pm_runtime_suspend(struct device *dev) { @@ -354,39 +353,6 @@ static void amba_put_disable_pclk(struct amba_device *pcdev) clk_put(pclk); } -static int amba_get_enable_vcore(struct amba_device *pcdev) -{ - struct regulator *vcore = regulator_get(&pcdev->dev, "vcore"); - int ret; - - pcdev->vcore = vcore; - - if (IS_ERR(vcore)) { - /* It is OK not to supply a vcore regulator */ - if (PTR_ERR(vcore) == -ENODEV) - return 0; - return PTR_ERR(vcore); - } - - ret = regulator_enable(vcore); - if (ret) { - regulator_put(vcore); - pcdev->vcore = ERR_PTR(-ENODEV); - } - - return ret; -} - -static void amba_put_disable_vcore(struct amba_device *pcdev) -{ - struct regulator *vcore = pcdev->vcore; - - if (!IS_ERR(vcore)) { - regulator_disable(vcore); - regulator_put(vcore); - } -} - /* * These are the device model conversion veneers; they convert the * device model structures to our more specific structures. @@ -399,10 +365,6 @@ static int amba_probe(struct device *dev) int ret; do { - ret = amba_get_enable_vcore(pcdev); - if (ret) - break; - ret = amba_get_enable_pclk(pcdev); if (ret) break; @@ -420,7 +382,6 @@ static int amba_probe(struct device *dev) pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); - amba_put_disable_vcore(pcdev); } while (0); return ret; @@ -442,7 +403,6 @@ static int amba_remove(struct device *dev) pm_runtime_put_noidle(dev); amba_put_disable_pclk(pcdev); - amba_put_disable_vcore(pcdev); return ret; } @@ -497,37 +457,22 @@ static void amba_device_release(struct device *dev) } /** - * amba_device_register - register an AMBA device - * @dev: AMBA device to register - * @parent: parent memory resource + * amba_device_add - add a previously allocated AMBA device structure + * @dev: AMBA device allocated by amba_device_alloc + * @parent: resource parent for this devices resources * - * Setup the AMBA device, reading the cell ID if present. - * Claim the resource, and register the AMBA device with - * the Linux device manager. + * Claim the resource, and read the device cell ID if not already + * initialized. Register the AMBA device with the Linux device + * manager. */ -int amba_device_register(struct amba_device *dev, struct resource *parent) +int amba_device_add(struct amba_device *dev, struct resource *parent) { u32 size; void __iomem *tmp; int i, ret; - device_initialize(&dev->dev); - - /* - * Copy from device_add - */ - if (dev->dev.init_name) { - dev_set_name(&dev->dev, "%s", dev->dev.init_name); - dev->dev.init_name = NULL; - } - - dev->dev.release = amba_device_release; - dev->dev.bus = &amba_bustype; - dev->dev.dma_mask = &dev->dma_mask; - dev->res.name = dev_name(&dev->dev); - - if (!dev->dev.coherent_dma_mask && dev->dma_mask) - dev_warn(&dev->dev, "coherent dma mask is unset\n"); + WARN_ON(dev->irq[0] == (unsigned int)-1); + WARN_ON(dev->irq[1] == (unsigned int)-1); ret = request_resource(parent, &dev->res); if (ret) @@ -582,9 +527,9 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) if (ret) goto err_release; - if (dev->irq[0] != NO_IRQ) + if (dev->irq[0] && dev->irq[0] != NO_IRQ) ret = device_create_file(&dev->dev, &dev_attr_irq0); - if (ret == 0 && dev->irq[1] != NO_IRQ) + if (ret == 0 && dev->irq[1] && dev->irq[1] != NO_IRQ) ret = device_create_file(&dev->dev, &dev_attr_irq1); if (ret == 0) return ret; @@ -596,6 +541,74 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) err_out: return ret; } +EXPORT_SYMBOL_GPL(amba_device_add); + +static void amba_device_initialize(struct amba_device *dev, const char *name) +{ + device_initialize(&dev->dev); + if (name) + dev_set_name(&dev->dev, "%s", name); + dev->dev.release = amba_device_release; + dev->dev.bus = &amba_bustype; + dev->dev.dma_mask = &dev->dma_mask; + dev->res.name = dev_name(&dev->dev); +} + +/** + * amba_device_alloc - allocate an AMBA device + * @name: sysfs name of the AMBA device + * @base: base of AMBA device + * @size: size of AMBA device + * + * Allocate and initialize an AMBA device structure. Returns %NULL + * on failure. + */ +struct amba_device *amba_device_alloc(const char *name, resource_size_t base, + size_t size) +{ + struct amba_device *dev; + + dev = kzalloc(sizeof(*dev), GFP_KERNEL); + if (dev) { + amba_device_initialize(dev, name); + dev->res.start = base; + dev->res.end = base + size - 1; + dev->res.flags = IORESOURCE_MEM; + } + + return dev; +} +EXPORT_SYMBOL_GPL(amba_device_alloc); + +/** + * amba_device_register - register an AMBA device + * @dev: AMBA device to register + * @parent: parent memory resource + * + * Setup the AMBA device, reading the cell ID if present. + * Claim the resource, and register the AMBA device with + * the Linux device manager. + */ +int amba_device_register(struct amba_device *dev, struct resource *parent) +{ + amba_device_initialize(dev, dev->dev.init_name); + dev->dev.init_name = NULL; + + if (!dev->dev.coherent_dma_mask && dev->dma_mask) + dev_warn(&dev->dev, "coherent dma mask is unset\n"); + + return amba_device_add(dev, parent); +} + +/** + * amba_device_put - put an AMBA device + * @dev: AMBA device to put + */ +void amba_device_put(struct amba_device *dev) +{ + put_device(&dev->dev); +} +EXPORT_SYMBOL_GPL(amba_device_put); /** * amba_device_unregister - unregister an AMBA device |