diff options
Diffstat (limited to 'lib/devres.c')
| -rw-r--r-- | lib/devres.c | 55 |
1 files changed, 53 insertions, 2 deletions
diff --git a/lib/devres.c b/lib/devres.c index 7c0e953a7486..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 |
| @@ -348,5 +399,5 @@ void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask) | |||
| 348 | } | 399 | } |
| 349 | } | 400 | } |
| 350 | EXPORT_SYMBOL(pcim_iounmap_regions); | 401 | EXPORT_SYMBOL(pcim_iounmap_regions); |
| 351 | #endif | 402 | #endif /* CONFIG_PCI */ |
| 352 | #endif | 403 | #endif /* CONFIG_HAS_IOPORT */ |
