diff options
| author | Charles Keepax <ckeepax@opensource.wolfsonmicro.com> | 2013-10-15 15:14:21 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@linaro.org> | 2013-10-23 07:17:08 -0400 |
| commit | 7fcd427465e710d0c4e2737d2f02b2ffa14b9bb3 (patch) | |
| tree | 37baddc5d110188af44ae190dde37ef574df4249 | |
| parent | a06ccd9c3785fa5550917ae036944f4e080b5749 (diff) | |
mfd: Allow mapping regulator supplies to MFD device from children
Occasionally, it is useful to map supplies from a child device onto the
MFD device. A typical usecase for this would be if the MFD device is
represented as a single node in device tree. All supplies will be
defined in device tree as existing on the MFD device. When a child
depends on frameworks which might have no knowledge of MFD to lookup
supplies on its behalf the supply will not be found.
This patch adds a list of supplies that should be looked up on the
parent rather than the child as part of the mfd_cell structure.
Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Mark Brown <broonie@linaro.org>
| -rw-r--r-- | drivers/mfd/mfd-core.c | 22 | ||||
| -rw-r--r-- | include/linux/mfd/core.h | 6 |
2 files changed, 23 insertions, 5 deletions
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f421586f29fb..adc8ea36e7c4 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 21 | #include <linux/irqdomain.h> | 21 | #include <linux/irqdomain.h> |
| 22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 23 | #include <linux/regulator/consumer.h> | ||
| 23 | 24 | ||
| 24 | static struct device_type mfd_dev_type = { | 25 | static struct device_type mfd_dev_type = { |
| 25 | .name = "mfd_device", | 26 | .name = "mfd_device", |
| @@ -99,6 +100,13 @@ static int mfd_add_device(struct device *parent, int id, | |||
| 99 | pdev->dev.dma_mask = parent->dma_mask; | 100 | pdev->dev.dma_mask = parent->dma_mask; |
| 100 | pdev->dev.dma_parms = parent->dma_parms; | 101 | pdev->dev.dma_parms = parent->dma_parms; |
| 101 | 102 | ||
| 103 | ret = devm_regulator_bulk_register_supply_alias( | ||
| 104 | &pdev->dev, cell->parent_supplies, | ||
| 105 | parent, cell->parent_supplies, | ||
| 106 | cell->num_parent_supplies); | ||
| 107 | if (ret < 0) | ||
| 108 | goto fail_res; | ||
| 109 | |||
| 102 | if (parent->of_node && cell->of_compatible) { | 110 | if (parent->of_node && cell->of_compatible) { |
| 103 | for_each_child_of_node(parent->of_node, np) { | 111 | for_each_child_of_node(parent->of_node, np) { |
| 104 | if (of_device_is_compatible(np, cell->of_compatible)) { | 112 | if (of_device_is_compatible(np, cell->of_compatible)) { |
| @@ -112,12 +120,12 @@ static int mfd_add_device(struct device *parent, int id, | |||
| 112 | ret = platform_device_add_data(pdev, | 120 | ret = platform_device_add_data(pdev, |
| 113 | cell->platform_data, cell->pdata_size); | 121 | cell->platform_data, cell->pdata_size); |
| 114 | if (ret) | 122 | if (ret) |
| 115 | goto fail_res; | 123 | goto fail_alias; |
| 116 | } | 124 | } |
| 117 | 125 | ||
| 118 | ret = mfd_platform_add_cell(pdev, cell); | 126 | ret = mfd_platform_add_cell(pdev, cell); |
| 119 | if (ret) | 127 | if (ret) |
| 120 | goto fail_res; | 128 | goto fail_alias; |
| 121 | 129 | ||
| 122 | for (r = 0; r < cell->num_resources; r++) { | 130 | for (r = 0; r < cell->num_resources; r++) { |
| 123 | res[r].name = cell->resources[r].name; | 131 | res[r].name = cell->resources[r].name; |
| @@ -152,17 +160,17 @@ static int mfd_add_device(struct device *parent, int id, | |||
| 152 | if (!cell->ignore_resource_conflicts) { | 160 | if (!cell->ignore_resource_conflicts) { |
| 153 | ret = acpi_check_resource_conflict(&res[r]); | 161 | ret = acpi_check_resource_conflict(&res[r]); |
| 154 | if (ret) | 162 | if (ret) |
| 155 | goto fail_res; | 163 | goto fail_alias; |
| 156 | } | 164 | } |
| 157 | } | 165 | } |
| 158 | 166 | ||
| 159 | ret = platform_device_add_resources(pdev, res, cell->num_resources); | 167 | ret = platform_device_add_resources(pdev, res, cell->num_resources); |
| 160 | if (ret) | 168 | if (ret) |
| 161 | goto fail_res; | 169 | goto fail_alias; |
| 162 | 170 | ||
| 163 | ret = platform_device_add(pdev); | 171 | ret = platform_device_add(pdev); |
| 164 | if (ret) | 172 | if (ret) |
| 165 | goto fail_res; | 173 | goto fail_alias; |
| 166 | 174 | ||
| 167 | if (cell->pm_runtime_no_callbacks) | 175 | if (cell->pm_runtime_no_callbacks) |
| 168 | pm_runtime_no_callbacks(&pdev->dev); | 176 | pm_runtime_no_callbacks(&pdev->dev); |
| @@ -171,6 +179,10 @@ static int mfd_add_device(struct device *parent, int id, | |||
| 171 | 179 | ||
| 172 | return 0; | 180 | return 0; |
| 173 | 181 | ||
| 182 | fail_alias: | ||
| 183 | devm_regulator_bulk_unregister_supply_alias(&pdev->dev, | ||
| 184 | cell->parent_supplies, | ||
| 185 | cell->num_parent_supplies); | ||
| 174 | fail_res: | 186 | fail_res: |
| 175 | kfree(res); | 187 | kfree(res); |
| 176 | fail_device: | 188 | fail_device: |
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index cebe97ee98b8..7314fc4e6d25 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h | |||
| @@ -59,6 +59,12 @@ struct mfd_cell { | |||
| 59 | * pm_runtime_no_callbacks(). | 59 | * pm_runtime_no_callbacks(). |
| 60 | */ | 60 | */ |
| 61 | bool pm_runtime_no_callbacks; | 61 | bool pm_runtime_no_callbacks; |
| 62 | |||
| 63 | /* A list of regulator supplies that should be mapped to the MFD | ||
| 64 | * device rather than the child device when requested | ||
| 65 | */ | ||
| 66 | const char **parent_supplies; | ||
| 67 | int num_parent_supplies; | ||
| 62 | }; | 68 | }; |
| 63 | 69 | ||
| 64 | /* | 70 | /* |
