diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2018-06-04 23:21:26 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2018-07-23 01:22:39 -0400 |
commit | d5e838275c80aeb96d4c0b81442a851dfef2e948 (patch) | |
tree | e315e83e62b5eab99f716f9cf20dd6813dd5256c | |
parent | d5e748ff2b996d83489ac76c072e8b99f9ecef13 (diff) |
devres: Add devm_of_iomap()
There are still quite a few cases where a device might want
to get to a different node of the device-tree, obtain the
resources and map them.
We have of_iomap() and of_io_request_and_map() but they both
have shortcomings, such as not returning the size of the
resource found (which can be useful) and not being "managed".
This adds a devm_of_iomap() that provides all of these and
should probably replace uses of the above in most drivers.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Reviewed-by: Joel Stanley <joel@jms.id.au>
-rw-r--r-- | include/linux/device.h | 4 | ||||
-rw-r--r-- | lib/devres.c | 36 |
2 files changed, 40 insertions, 0 deletions
diff --git a/include/linux/device.h b/include/linux/device.h index 055a69dbcd18..6aa8d51eabe9 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -696,6 +696,10 @@ extern void devm_free_pages(struct device *dev, unsigned long addr); | |||
696 | 696 | ||
697 | void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); | 697 | void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res); |
698 | 698 | ||
699 | void __iomem *devm_of_iomap(struct device *dev, | ||
700 | struct device_node *node, int index, | ||
701 | resource_size_t *size); | ||
702 | |||
699 | /* allows to add/remove a custom action to devres stack */ | 703 | /* allows to add/remove a custom action to devres stack */ |
700 | int devm_add_action(struct device *dev, void (*action)(void *), void *data); | 704 | int devm_add_action(struct device *dev, void (*action)(void *), void *data); |
701 | void devm_remove_action(struct device *dev, void (*action)(void *), void *data); | 705 | void devm_remove_action(struct device *dev, void (*action)(void *), void *data); |
diff --git a/lib/devres.c b/lib/devres.c index 5bec1120b392..faccf1a037d0 100644 --- a/lib/devres.c +++ b/lib/devres.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/io.h> | 4 | #include <linux/io.h> |
5 | #include <linux/gfp.h> | 5 | #include <linux/gfp.h> |
6 | #include <linux/export.h> | 6 | #include <linux/export.h> |
7 | #include <linux/of_address.h> | ||
7 | 8 | ||
8 | enum devm_ioremap_type { | 9 | enum devm_ioremap_type { |
9 | DEVM_IOREMAP = 0, | 10 | DEVM_IOREMAP = 0, |
@@ -162,6 +163,41 @@ void __iomem *devm_ioremap_resource(struct device *dev, struct resource *res) | |||
162 | } | 163 | } |
163 | EXPORT_SYMBOL(devm_ioremap_resource); | 164 | EXPORT_SYMBOL(devm_ioremap_resource); |
164 | 165 | ||
166 | /* | ||
167 | * devm_of_iomap - Requests a resource and maps the memory mapped IO | ||
168 | * for a given device_node managed by a given device | ||
169 | * | ||
170 | * Checks that a resource is a valid memory region, requests the memory | ||
171 | * region and ioremaps it. All operations are managed and will be undone | ||
172 | * on driver detach of the device. | ||
173 | * | ||
174 | * This is to be used when a device requests/maps resources described | ||
175 | * by other device tree nodes (children or otherwise). | ||
176 | * | ||
177 | * @dev: The device "managing" the resource | ||
178 | * @node: The device-tree node where the resource resides | ||
179 | * @index: index of the MMIO range in the "reg" property | ||
180 | * @size: Returns the size of the resource (pass NULL if not needed) | ||
181 | * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded | ||
182 | * error code on failure. Usage example: | ||
183 | * | ||
184 | * base = devm_of_iomap(&pdev->dev, node, 0, NULL); | ||
185 | * if (IS_ERR(base)) | ||
186 | * return PTR_ERR(base); | ||
187 | */ | ||
188 | void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index, | ||
189 | resource_size_t *size) | ||
190 | { | ||
191 | struct resource res; | ||
192 | |||
193 | if (of_address_to_resource(node, index, &res)) | ||
194 | return IOMEM_ERR_PTR(-EINVAL); | ||
195 | if (size) | ||
196 | *size = resource_size(&res); | ||
197 | return devm_ioremap_resource(dev, &res); | ||
198 | } | ||
199 | EXPORT_SYMBOL(devm_of_iomap); | ||
200 | |||
165 | #ifdef CONFIG_HAS_IOPORT_MAP | 201 | #ifdef CONFIG_HAS_IOPORT_MAP |
166 | /* | 202 | /* |
167 | * Generic iomap devres | 203 | * Generic iomap devres |