lib: devres: add convenience function to remap a resource
authorWolfram Sang <w.sang@pengutronix.de>
Tue, 25 Oct 2011 13:16:47 +0000 (15:16 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 16 Nov 2011 00:07:39 +0000 (16:07 -0800)
Almost every platform_driver does the three steps get_resource,
request_mem_region, ioremap. This does not only lead to a lot of code
duplication, but also a huge number of similar error strings and
inconsistent error codes on failure. So, introduce a helper function
which simplifies remapping a resource and make it hard to do something
wrong and add documentation for it.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Documentation/driver-model/devres.txt
include/linux/device.h
lib/devres.c

index d79aead9418be01011cdf87c0b37084186ae39fb..10c64c8a13d4f2aec7bebb0bd6a44ce401aa78cc 100644 (file)
@@ -262,6 +262,7 @@ IOMAP
   devm_ioremap()
   devm_ioremap_nocache()
   devm_iounmap()
+  devm_request_and_ioremap() : checks resource, requests region, ioremaps
   pcim_iomap()
   pcim_iounmap()
   pcim_iomap_table()   : array of mapped addresses indexed by BAR
index ffbcf95cd97dbb3b7e12f9be778c90f1977a9a1a..c6335982774ce24e4ac2e7efc6db0e930a8811e1 100644 (file)
@@ -490,6 +490,9 @@ extern int devres_release_group(struct device *dev, void *id);
 extern void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp);
 extern void devm_kfree(struct device *dev, void *p);
 
+void __iomem *devm_request_and_ioremap(struct device *dev,
+                       struct resource *res);
+
 struct device_dma_parameters {
        /*
         * a low level driver may set these to teach IOMMU code about
index 78777aea5b3426189b977bb852e4898578c34818..4fbc09e6e9e6f9a83dbdc14ba99bfb1328bef577 100644 (file)
@@ -85,6 +85,57 @@ void devm_iounmap(struct device *dev, void __iomem *addr)
 }
 EXPORT_SYMBOL(devm_iounmap);
 
+/**
+ * devm_request_and_ioremap() - Check, request region, and ioremap resource
+ * @dev: Generic device to handle the resource for
+ * @res: resource to be handled
+ *
+ * Takes all necessary steps to ioremap a mem resource. Uses managed device, so
+ * everything is undone on driver detach. Checks arguments, so you can feed
+ * it the result from e.g. platform_get_resource() directly. Returns the
+ * remapped pointer or NULL on error. Usage example:
+ *
+ *     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *     base = devm_request_and_ioremap(&pdev->dev, res);
+ *     if (!base)
+ *             return -EADDRNOTAVAIL;
+ */
+void __iomem *devm_request_and_ioremap(struct device *dev,
+                       struct resource *res)
+{
+       resource_size_t size;
+       const char *name;
+       void __iomem *dest_ptr;
+
+       BUG_ON(!dev);
+
+       if (!res || resource_type(res) != IORESOURCE_MEM) {
+               dev_err(dev, "invalid resource\n");
+               return NULL;
+       }
+
+       size = resource_size(res);
+       name = res->name ?: dev_name(dev);
+
+       if (!devm_request_mem_region(dev, res->start, size, name)) {
+               dev_err(dev, "can't request region for resource %pR\n", res);
+               return NULL;
+       }
+
+       if (res->flags & IORESOURCE_CACHEABLE)
+               dest_ptr = devm_ioremap(dev, res->start, size);
+       else
+               dest_ptr = devm_ioremap_nocache(dev, res->start, size);
+
+       if (!dest_ptr) {
+               dev_err(dev, "ioremap failed for resource %pR\n", res);
+               devm_release_mem_region(dev, res->start, size);
+       }
+
+       return dest_ptr;
+}
+EXPORT_SYMBOL(devm_request_and_ioremap);
+
 #ifdef CONFIG_HAS_IOPORT
 /*
  * Generic iomap devres