|
@@ -63,7 +63,8 @@ int mfd_cell_disable(struct platform_device *pdev)
|
|
|
EXPORT_SYMBOL(mfd_cell_disable);
|
|
|
|
|
|
static int mfd_platform_add_cell(struct platform_device *pdev,
|
|
|
- const struct mfd_cell *cell)
|
|
|
+ const struct mfd_cell *cell,
|
|
|
+ atomic_t *usage_count)
|
|
|
{
|
|
|
if (!cell)
|
|
|
return 0;
|
|
@@ -72,11 +73,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
|
|
|
if (!pdev->mfd_cell)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ pdev->mfd_cell->usage_count = usage_count;
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static int mfd_add_device(struct device *parent, int id,
|
|
|
- const struct mfd_cell *cell,
|
|
|
+ const struct mfd_cell *cell, atomic_t *usage_count,
|
|
|
struct resource *mem_base,
|
|
|
int irq_base, struct irq_domain *domain)
|
|
|
{
|
|
@@ -115,7 +117,7 @@ static int mfd_add_device(struct device *parent, int id,
|
|
|
goto fail_res;
|
|
|
}
|
|
|
|
|
|
- ret = mfd_platform_add_cell(pdev, cell);
|
|
|
+ ret = mfd_platform_add_cell(pdev, cell, usage_count);
|
|
|
if (ret)
|
|
|
goto fail_res;
|
|
|
|
|
@@ -180,12 +182,12 @@ fail_alloc:
|
|
|
}
|
|
|
|
|
|
int mfd_add_devices(struct device *parent, int id,
|
|
|
- struct mfd_cell *cells, int n_devs,
|
|
|
+ const struct mfd_cell *cells, int n_devs,
|
|
|
struct resource *mem_base,
|
|
|
int irq_base, struct irq_domain *domain)
|
|
|
{
|
|
|
int i;
|
|
|
- int ret = 0;
|
|
|
+ int ret;
|
|
|
atomic_t *cnts;
|
|
|
|
|
|
/* initialize reference counting for all cells */
|
|
@@ -195,16 +197,19 @@ int mfd_add_devices(struct device *parent, int id,
|
|
|
|
|
|
for (i = 0; i < n_devs; i++) {
|
|
|
atomic_set(&cnts[i], 0);
|
|
|
- cells[i].usage_count = &cnts[i];
|
|
|
- ret = mfd_add_device(parent, id, cells + i, mem_base,
|
|
|
+ ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base,
|
|
|
irq_base, domain);
|
|
|
if (ret)
|
|
|
- break;
|
|
|
+ goto fail;
|
|
|
}
|
|
|
|
|
|
- if (ret)
|
|
|
- mfd_remove_devices(parent);
|
|
|
+ return 0;
|
|
|
|
|
|
+fail:
|
|
|
+ if (i)
|
|
|
+ mfd_remove_devices(parent);
|
|
|
+ else
|
|
|
+ kfree(cnts);
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(mfd_add_devices);
|
|
@@ -259,8 +264,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
|
|
|
for (i = 0; i < n_clones; i++) {
|
|
|
cell_entry.name = clones[i];
|
|
|
/* don't give up if a single call fails; just report error */
|
|
|
- if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0,
|
|
|
- NULL))
|
|
|
+ if (mfd_add_device(pdev->dev.parent, -1, &cell_entry,
|
|
|
+ cell_entry.usage_count, NULL, 0, NULL))
|
|
|
dev_err(dev, "failed to create platform device '%s'\n",
|
|
|
clones[i]);
|
|
|
}
|