diff options
author | Wolfram Sang <w.sang@pengutronix.de> | 2011-10-25 09:16:47 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-11-15 19:07:39 -0500 |
commit | 72f8c0bfa0de64c68ee59f40eb9b2683bffffbb0 (patch) | |
tree | 44fa0c66dbb41d9154e170d4d97455e5665a5f12 /lib | |
parent | 571806a9f70fc4a4c575ab796555dfb401c2dfc1 (diff) |
lib: devres: add convenience function to remap a resource
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/devres.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/devres.c b/lib/devres.c index 78777aea5b34..4fbc09e6e9e6 100644 --- a/lib/devres.c +++ b/lib/devres.c | |||
@@ -85,6 +85,57 @@ void devm_iounmap(struct device *dev, void __iomem *addr) | |||
85 | } | 85 | } |
86 | EXPORT_SYMBOL(devm_iounmap); | 86 | EXPORT_SYMBOL(devm_iounmap); |
87 | 87 | ||
88 | /** | ||
89 | * devm_request_and_ioremap() - Check, request region, and ioremap resource | ||
90 | * @dev: Generic device to handle the resource for | ||
91 | * @res: resource to be handled | ||
92 | * | ||
93 | * Takes all necessary steps to ioremap a mem resource. Uses managed device, so | ||
94 | * everything is undone on driver detach. Checks arguments, so you can feed | ||
95 | * it the result from e.g. platform_get_resource() directly. Returns the | ||
96 | * remapped pointer or NULL on error. Usage example: | ||
97 | * | ||
98 | * res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
99 | * base = devm_request_and_ioremap(&pdev->dev, res); | ||
100 | * if (!base) | ||
101 | * return -EADDRNOTAVAIL; | ||
102 | */ | ||
103 | void __iomem *devm_request_and_ioremap(struct device *dev, | ||
104 | struct resource *res) | ||
105 | { | ||
106 | resource_size_t size; | ||
107 | const char *name; | ||
108 | void __iomem *dest_ptr; | ||
109 | |||
110 | BUG_ON(!dev); | ||
111 | |||
112 | if (!res || resource_type(res) != IORESOURCE_MEM) { | ||
113 | dev_err(dev, "invalid resource\n"); | ||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | size = resource_size(res); | ||
118 | name = res->name ?: dev_name(dev); | ||
119 | |||
120 | if (!devm_request_mem_region(dev, res->start, size, name)) { | ||
121 | dev_err(dev, "can't request region for resource %pR\n", res); | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | if (res->flags & IORESOURCE_CACHEABLE) | ||
126 | dest_ptr = devm_ioremap(dev, res->start, size); | ||
127 | else | ||
128 | dest_ptr = devm_ioremap_nocache(dev, res->start, size); | ||
129 | |||
130 | if (!dest_ptr) { | ||
131 | dev_err(dev, "ioremap failed for resource %pR\n", res); | ||
132 | devm_release_mem_region(dev, res->start, size); | ||
133 | } | ||
134 | |||
135 | return dest_ptr; | ||
136 | } | ||
137 | EXPORT_SYMBOL(devm_request_and_ioremap); | ||
138 | |||
88 | #ifdef CONFIG_HAS_IOPORT | 139 | #ifdef CONFIG_HAS_IOPORT |
89 | /* | 140 | /* |
90 | * Generic iomap devres | 141 | * Generic iomap devres |