[PATCH] drivers/of: Add devm_of_iomap()

From: Benjamin Herrenschmidt
Date: Mon Jun 11 2018 - 20:01:21 EST


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.

Drivers doing that currently open code the whole thing, which is error
proe.

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 necessary)
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@xxxxxxxxxxxxxxxxxxx>
---

I'm cooking a driver that uses this, if there's no objection I'd like
to carry it in my pull request for that driver (it can also exist in
the DT tree of course). Just let me know.

drivers/of/address.c | 35 +++++++++++++++++++++++++++++++++++
include/linux/of_address.h | 5 +++++
2 files changed, 40 insertions(+)

diff --git a/drivers/of/address.c b/drivers/of/address.c
index cf83c05f5650..b7d49ee7b690 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -807,6 +807,41 @@ void __iomem *of_io_request_and_map(struct device_node *np, int index,
}
EXPORT_SYMBOL(of_io_request_and_map);

+/*
+ * devm_of_iomap - Requests a resource and maps the memory mapped IO
+ * for a given device_node managed by a given device
+ *
+ * Checks that a resource is a valid memory region, requests the memory
+ * region and ioremaps it. All operations are managed and will be undone
+ * on driver detach of the device.
+ *
+ * This is to be used when a device requests/maps resources described
+ * by other device tree nodes (children or otherwise).
+ *
+ * @dev: The device "managing" the resource
+ * @node: The device-tree node where the resource resides
+ * @index: index of the MMIO range in the "reg" property
+ * @size: Returns the size of the resource (pass NULL if not needed)
+ * Returns a pointer to the requested and mapped memory or an ERR_PTR() encoded
+ * error code on failure. Usage example:
+ *
+ * base = devm_of_iomap(&pdev->dev, node, 0, NULL);
+ * if (IS_ERR(base))
+ * return PTR_ERR(base);
+ */
+void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
+ resource_size_t *size)
+{
+ struct resource res;
+
+ if (of_address_to_resource(node, index, &res))
+ return IOMEM_ERR_PTR(-EINVAL);
+ if (size)
+ *size = resource_size(&res);
+ return devm_ioremap_resource(dev, &res);
+}
+EXPORT_SYMBOL(devm_of_iomap);
+
/**
* of_dma_get_range - Get DMA range info
* @np: device node to get DMA range info
diff --git a/include/linux/of_address.h b/include/linux/of_address.h
index 37864734ca50..2649232a2b26 100644
--- a/include/linux/of_address.h
+++ b/include/linux/of_address.h
@@ -40,6 +40,11 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
void __iomem *of_io_request_and_map(struct device_node *device,
int index, const char *name);

+/* Request and map, wrapper on devm_ioremap_resource */
+extern void __iomem *devm_of_iomap(struct device *dev,
+ struct device_node *node, int index,
+ resource_size_t *size);
+
/* Extract an address from a device, returns the region size and
* the address space flags too. The PCI version uses a BAR number
* instead of an absolute index