b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100 1) // SPDX-License-Identifier: GPL-2.0
f4a18312f46a6 (Thierry Reding 2013-01-22 22:24:46 +0100 2) #include <linux/err.h>
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 3) #include <linux/pci.h>
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 4) #include <linux/io.h>
5a0e3ad6af866 (Tejun Heo 2010-03-24 17:04:11 +0900 5) #include <linux/gfp.h>
8bc3bcc93a2b4 (Paul Gortmaker 2011-11-16 21:29:17 -0500 6) #include <linux/export.h>
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 7) #include <linux/of_address.h>
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 8)
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 9) enum devm_ioremap_type {
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 10) DEVM_IOREMAP = 0,
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 11) DEVM_IOREMAP_UC,
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 12) DEVM_IOREMAP_WC,
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 13) DEVM_IOREMAP_NP,
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 14) };
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 15)
b41e5fffe8b81 (Emil Medve 2008-05-03 06:34:04 +1000 16) void devm_ioremap_release(struct device *dev, void *res)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 17) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 18) iounmap(*(void __iomem **)res);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 19) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 20)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 21) static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 22) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 23) return *(void **)res == match_data;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 24) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 25)
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 26) static void __iomem *__devm_ioremap(struct device *dev, resource_size_t offset,
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 27) resource_size_t size,
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 28) enum devm_ioremap_type type)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 29) {
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 30) void __iomem **ptr, *addr = NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 31)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 32) ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 33) if (!ptr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 34) return NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 35)
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 36) switch (type) {
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 37) case DEVM_IOREMAP:
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 38) addr = ioremap(offset, size);
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 39) break;
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 40) case DEVM_IOREMAP_UC:
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 41) addr = ioremap_uc(offset, size);
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 42) break;
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 43) case DEVM_IOREMAP_WC:
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 44) addr = ioremap_wc(offset, size);
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 45) break;
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 46) case DEVM_IOREMAP_NP:
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 47) addr = ioremap_np(offset, size);
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 48) break;
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 49) }
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 50)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 51) if (addr) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 52) *ptr = addr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 53) devres_add(dev, ptr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 54) } else
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 55) devres_free(ptr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 56)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 57) return addr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 58) }
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 59)
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 60) /**
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 61) * devm_ioremap - Managed ioremap()
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 62) * @dev: Generic device to remap IO address for
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 63) * @offset: Resource address to map
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 64) * @size: Size of map
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 65) *
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 66) * Managed ioremap(). Map is automatically unmapped on driver detach.
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 67) */
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 68) void __iomem *devm_ioremap(struct device *dev, resource_size_t offset,
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 69) resource_size_t size)
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 70) {
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 71) return __devm_ioremap(dev, offset, size, DEVM_IOREMAP);
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 72) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 73) EXPORT_SYMBOL(devm_ioremap);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 74)
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 75) /**
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 76) * devm_ioremap_uc - Managed ioremap_uc()
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 77) * @dev: Generic device to remap IO address for
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 78) * @offset: Resource address to map
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 79) * @size: Size of map
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 80) *
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 81) * Managed ioremap_uc(). Map is automatically unmapped on driver detach.
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 82) */
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 83) void __iomem *devm_ioremap_uc(struct device *dev, resource_size_t offset,
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 84) resource_size_t size)
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 85) {
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 86) return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_UC);
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 87) }
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 88) EXPORT_SYMBOL_GPL(devm_ioremap_uc);
e537654b7039a (Tuowen Zhao 2019-10-16 15:06:28 -0600 89)
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 90) /**
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 91) * devm_ioremap_wc - Managed ioremap_wc()
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 92) * @dev: Generic device to remap IO address for
6524754eff305 (Lorenzo Pieralisi 2017-04-19 17:48:54 +0100 93) * @offset: Resource address to map
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 94) * @size: Size of map
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 95) *
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 96) * Managed ioremap_wc(). Map is automatically unmapped on driver detach.
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 97) */
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 98) void __iomem *devm_ioremap_wc(struct device *dev, resource_size_t offset,
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 99) resource_size_t size)
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 100) {
1b723413aada7 (Yisheng Xie 2018-01-29 19:48:16 +0800 101) return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_WC);
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 102) }
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 103) EXPORT_SYMBOL(devm_ioremap_wc);
34644524bce91 (Abhilash Kesavan 2015-02-06 19:15:27 +0530 104)
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 105) /**
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 106) * devm_ioremap_np - Managed ioremap_np()
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 107) * @dev: Generic device to remap IO address for
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 108) * @offset: Resource address to map
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 109) * @size: Size of map
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 110) *
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 111) * Managed ioremap_np(). Map is automatically unmapped on driver detach.
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 112) */
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 113) void __iomem *devm_ioremap_np(struct device *dev, resource_size_t offset,
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 114) resource_size_t size)
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 115) {
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 116) return __devm_ioremap(dev, offset, size, DEVM_IOREMAP_NP);
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 117) }
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 118) EXPORT_SYMBOL(devm_ioremap_np);
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 119)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 120) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 121) * devm_iounmap - Managed iounmap()
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 122) * @dev: Generic device to unmap for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 123) * @addr: Address to unmap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 124) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 125) * Managed iounmap(). @addr must have been mapped using devm_ioremap*().
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 126) */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 127) void devm_iounmap(struct device *dev, void __iomem *addr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 128) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 129) WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
b104d6a5a82a5 (Steven Rostedt 2014-04-03 14:49:07 -0700 130) (__force void *)addr));
ae891a1b93bf6 (Maxin B John 2011-07-25 17:12:59 -0700 131) iounmap(addr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 132) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 133) EXPORT_SYMBOL(devm_iounmap);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 134)
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 135) static void __iomem *
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 136) __devm_ioremap_resource(struct device *dev, const struct resource *res,
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 137) enum devm_ioremap_type type)
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 138) {
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 139) resource_size_t size;
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 140) void __iomem *dest_ptr;
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 141) char *pretty_name;
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 142)
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 143) BUG_ON(!dev);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 144)
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 145) if (!res || resource_type(res) != IORESOURCE_MEM) {
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 146) dev_err(dev, "invalid resource\n");
b104d6a5a82a5 (Steven Rostedt 2014-04-03 14:49:07 -0700 147) return IOMEM_ERR_PTR(-EINVAL);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 148) }
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 149)
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 150) if (type == DEVM_IOREMAP && res->flags & IORESOURCE_MEM_NONPOSTED)
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 151) type = DEVM_IOREMAP_NP;
7c566bb5e4d5f (Hector Martin 2021-02-11 21:35:46 +0900 152)
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 153) size = resource_size(res);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 154)
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 155) if (res->name)
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 156) pretty_name = devm_kasprintf(dev, GFP_KERNEL, "%s %s",
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 157) dev_name(dev), res->name);
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 158) else
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 159) pretty_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 160) if (!pretty_name)
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 161) return IOMEM_ERR_PTR(-ENOMEM);
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 162)
35bd8c07db2ce (Vladimir Oltean 2020-06-01 12:58:26 +0300 163) if (!devm_request_mem_region(dev, res->start, size, pretty_name)) {
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 164) dev_err(dev, "can't request region for resource %pR\n", res);
b104d6a5a82a5 (Steven Rostedt 2014-04-03 14:49:07 -0700 165) return IOMEM_ERR_PTR(-EBUSY);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 166) }
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 167)
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 168) dest_ptr = __devm_ioremap(dev, res->start, size, type);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 169) if (!dest_ptr) {
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 170) dev_err(dev, "ioremap failed for resource %pR\n", res);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 171) devm_release_mem_region(dev, res->start, size);
b104d6a5a82a5 (Steven Rostedt 2014-04-03 14:49:07 -0700 172) dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 173) }
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 174)
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 175) return dest_ptr;
72f8c0bfa0de6 (Wolfram Sang 2011-10-25 15:16:47 +0200 176) }
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 177)
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 178) /**
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 179) * devm_ioremap_resource() - check, request region, and ioremap resource
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 180) * @dev: generic device to handle the resource for
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 181) * @res: resource to be handled
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 182) *
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 183) * Checks that a resource is a valid memory region, requests the memory
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 184) * region and ioremaps it. All operations are managed and will be undone
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 185) * on driver detach.
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 186) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 187) * Usage example:
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 188) *
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 189) * res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 190) * base = devm_ioremap_resource(&pdev->dev, res);
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 191) * if (IS_ERR(base))
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 192) * return PTR_ERR(base);
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 193) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 194) * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 195) * on failure.
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 196) */
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 197) void __iomem *devm_ioremap_resource(struct device *dev,
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 198) const struct resource *res)
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 199) {
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 200) return __devm_ioremap_resource(dev, res, DEVM_IOREMAP);
6e924822752cb (Bartosz Golaszewski 2019-10-22 10:43:12 +0200 201) }
75096579c3ac3 (Thierry Reding 2013-01-21 11:08:54 +0100 202) EXPORT_SYMBOL(devm_ioremap_resource);
75096579c3ac3 (Thierry Reding 2013-01-21 11:08:54 +0100 203)
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 204) /**
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 205) * devm_ioremap_resource_wc() - write-combined variant of
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 206) * devm_ioremap_resource()
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 207) * @dev: generic device to handle the resource for
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 208) * @res: resource to be handled
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 209) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 210) * Return: a pointer to the remapped memory or an ERR_PTR() encoded error code
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 211) * on failure.
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 212) */
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 213) void __iomem *devm_ioremap_resource_wc(struct device *dev,
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 214) const struct resource *res)
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 215) {
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 216) return __devm_ioremap_resource(dev, res, DEVM_IOREMAP_WC);
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 217) }
b873af620e588 (Bartosz Golaszewski 2019-10-22 10:43:13 +0200 218)
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 219) /*
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 220) * devm_of_iomap - Requests a resource and maps the memory mapped IO
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 221) * for a given device_node managed by a given device
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 222) *
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 223) * Checks that a resource is a valid memory region, requests the memory
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 224) * region and ioremaps it. All operations are managed and will be undone
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 225) * on driver detach of the device.
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 226) *
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 227) * This is to be used when a device requests/maps resources described
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 228) * by other device tree nodes (children or otherwise).
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 229) *
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 230) * @dev: The device "managing" the resource
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 231) * @node: The device-tree node where the resource resides
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 232) * @index: index of the MMIO range in the "reg" property
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 233) * @size: Returns the size of the resource (pass NULL if not needed)
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 234) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 235) * Usage example:
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 236) *
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 237) * base = devm_of_iomap(&pdev->dev, node, 0, NULL);
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 238) * if (IS_ERR(base))
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 239) * return PTR_ERR(base);
7ae731a8441d7 (Dan Carpenter 2020-06-09 13:46:42 +0300 240) *
7ae731a8441d7 (Dan Carpenter 2020-06-09 13:46:42 +0300 241) * Please Note: This is not a one-to-one replacement for of_iomap() because the
7ae731a8441d7 (Dan Carpenter 2020-06-09 13:46:42 +0300 242) * of_iomap() function does not track whether the region is already mapped. If
7ae731a8441d7 (Dan Carpenter 2020-06-09 13:46:42 +0300 243) * two drivers try to map the same memory, the of_iomap() function will succeed
28d9fdf04573c (Randy Dunlap 2020-08-22 21:04:43 -0700 244) * but the devm_of_iomap() function will return -EBUSY.
7ae731a8441d7 (Dan Carpenter 2020-06-09 13:46:42 +0300 245) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 246) * Return: a pointer to the requested and mapped memory or an ERR_PTR() encoded
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 247) * error code on failure.
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 248) */
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 249) void __iomem *devm_of_iomap(struct device *dev, struct device_node *node, int index,
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 250) resource_size_t *size)
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 251) {
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 252) struct resource res;
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 253)
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 254) if (of_address_to_resource(node, index, &res))
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 255) return IOMEM_ERR_PTR(-EINVAL);
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 256) if (size)
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 257) *size = resource_size(&res);
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 258) return devm_ioremap_resource(dev, &res);
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 259) }
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 260) EXPORT_SYMBOL(devm_of_iomap);
d5e838275c80a (Benjamin Herrenschmidt 2018-06-05 13:21:26 +1000 261)
ce816fa88cca0 (Uwe Kleine-König 2014-04-07 15:39:19 -0700 262) #ifdef CONFIG_HAS_IOPORT_MAP
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 263) /*
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 264) * Generic iomap devres
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 265) */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 266) static void devm_ioport_map_release(struct device *dev, void *res)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 267) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 268) ioport_unmap(*(void __iomem **)res);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 269) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 270)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 271) static int devm_ioport_map_match(struct device *dev, void *res,
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 272) void *match_data)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 273) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 274) return *(void **)res == match_data;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 275) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 276)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 277) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 278) * devm_ioport_map - Managed ioport_map()
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 279) * @dev: Generic device to map ioport for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 280) * @port: Port to map
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 281) * @nr: Number of ports to map
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 282) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 283) * Managed ioport_map(). Map is automatically unmapped on driver
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 284) * detach.
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 285) *
0c7a6b91d2276 (Stephen Boyd 2020-09-09 23:04:40 -0700 286) * Return: a pointer to the remapped memory or NULL on failure.
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 287) */
5cbb00cc4aae5 (Fabian Frederick 2014-05-23 22:30:50 +0200 288) void __iomem *devm_ioport_map(struct device *dev, unsigned long port,
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 289) unsigned int nr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 290) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 291) void __iomem **ptr, *addr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 292)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 293) ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 294) if (!ptr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 295) return NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 296)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 297) addr = ioport_map(port, nr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 298) if (addr) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 299) *ptr = addr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 300) devres_add(dev, ptr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 301) } else
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 302) devres_free(ptr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 303)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 304) return addr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 305) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 306) EXPORT_SYMBOL(devm_ioport_map);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 307)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 308) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 309) * devm_ioport_unmap - Managed ioport_unmap()
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 310) * @dev: Generic device to unmap for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 311) * @addr: Address to unmap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 312) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 313) * Managed ioport_unmap(). @addr must have been mapped using
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 314) * devm_ioport_map().
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 315) */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 316) void devm_ioport_unmap(struct device *dev, void __iomem *addr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 317) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 318) ioport_unmap(addr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 319) WARN_ON(devres_destroy(dev, devm_ioport_map_release,
b104d6a5a82a5 (Steven Rostedt 2014-04-03 14:49:07 -0700 320) devm_ioport_map_match, (__force void *)addr));
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 321) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 322) EXPORT_SYMBOL(devm_ioport_unmap);
ce816fa88cca0 (Uwe Kleine-König 2014-04-07 15:39:19 -0700 323) #endif /* CONFIG_HAS_IOPORT_MAP */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 324)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 325) #ifdef CONFIG_PCI
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 326) /*
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 327) * PCI iomap devres
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 328) */
c9c13ba428ef9 (Denis Efremov 2019-09-28 02:43:08 +0300 329) #define PCIM_IOMAP_MAX PCI_STD_NUM_BARS
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 330)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 331) struct pcim_iomap_devres {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 332) void __iomem *table[PCIM_IOMAP_MAX];
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 333) };
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 334)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 335) static void pcim_iomap_release(struct device *gendev, void *res)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 336) {
20af74ef140f0 (Geliang Tang 2015-12-27 18:46:05 +0800 337) struct pci_dev *dev = to_pci_dev(gendev);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 338) struct pcim_iomap_devres *this = res;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 339) int i;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 340)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 341) for (i = 0; i < PCIM_IOMAP_MAX; i++)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 342) if (this->table[i])
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 343) pci_iounmap(dev, this->table[i]);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 344) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 345)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 346) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 347) * pcim_iomap_table - access iomap allocation table
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 348) * @pdev: PCI device to access iomap table for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 349) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 350) * Access iomap allocation table for @dev. If iomap table doesn't
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 351) * exist and @pdev is managed, it will be allocated. All iomaps
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 352) * recorded in the iomap table are automatically unmapped on driver
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 353) * detach.
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 354) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 355) * This function might sleep when the table is first allocated but can
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 356) * be safely called without context and guaranteed to succed once
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 357) * allocated.
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 358) */
5cbb00cc4aae5 (Fabian Frederick 2014-05-23 22:30:50 +0200 359) void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 360) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 361) struct pcim_iomap_devres *dr, *new_dr;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 362)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 363) dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 364) if (dr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 365) return dr->table;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 366)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 367) new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 368) if (!new_dr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 369) return NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 370) dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 371) return dr->table;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 372) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 373) EXPORT_SYMBOL(pcim_iomap_table);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 374)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 375) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 376) * pcim_iomap - Managed pcim_iomap()
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 377) * @pdev: PCI device to iomap for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 378) * @bar: BAR to iomap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 379) * @maxlen: Maximum length of iomap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 380) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 381) * Managed pci_iomap(). Map is automatically unmapped on driver
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 382) * detach.
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 383) */
5cbb00cc4aae5 (Fabian Frederick 2014-05-23 22:30:50 +0200 384) void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 385) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 386) void __iomem **tbl;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 387)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 388) BUG_ON(bar >= PCIM_IOMAP_MAX);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 389)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 390) tbl = (void __iomem **)pcim_iomap_table(pdev);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 391) if (!tbl || tbl[bar]) /* duplicate mappings not allowed */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 392) return NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 393)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 394) tbl[bar] = pci_iomap(pdev, bar, maxlen);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 395) return tbl[bar];
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 396) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 397) EXPORT_SYMBOL(pcim_iomap);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 398)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 399) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 400) * pcim_iounmap - Managed pci_iounmap()
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 401) * @pdev: PCI device to iounmap for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 402) * @addr: Address to unmap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 403) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 404) * Managed pci_iounmap(). @addr must have been mapped using pcim_iomap().
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 405) */
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 406) void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 407) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 408) void __iomem **tbl;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 409) int i;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 410)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 411) pci_iounmap(pdev, addr);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 412)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 413) tbl = (void __iomem **)pcim_iomap_table(pdev);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 414) BUG_ON(!tbl);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 415)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 416) for (i = 0; i < PCIM_IOMAP_MAX; i++)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 417) if (tbl[i] == addr) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 418) tbl[i] = NULL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 419) return;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 420) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 421) WARN_ON(1);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 422) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 423) EXPORT_SYMBOL(pcim_iounmap);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 424)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 425) /**
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 426) * pcim_iomap_regions - Request and iomap PCI BARs
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 427) * @pdev: PCI device to map IO resources for
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 428) * @mask: Mask of BARs to request and iomap
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 429) * @name: Name used when requesting regions
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 430) *
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 431) * Request and iomap regions specified by @mask.
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 432) */
fb7ebfe4108e2 (Yinghai Lu 2012-01-04 15:50:02 -0800 433) int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 434) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 435) void __iomem * const *iomap;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 436) int i, rc;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 437)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 438) iomap = pcim_iomap_table(pdev);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 439) if (!iomap)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 440) return -ENOMEM;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 441)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 442) for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 443) unsigned long len;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 444)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 445) if (!(mask & (1 << i)))
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 446) continue;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 447)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 448) rc = -EINVAL;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 449) len = pci_resource_len(pdev, i);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 450) if (!len)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 451) goto err_inval;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 452)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 453) rc = pci_request_region(pdev, i, name);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 454) if (rc)
fb4d64e78ceab (Frederik Deweerdt 2007-02-16 01:27:15 -0800 455) goto err_inval;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 456)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 457) rc = -ENOMEM;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 458) if (!pcim_iomap(pdev, i, 0))
fb4d64e78ceab (Frederik Deweerdt 2007-02-16 01:27:15 -0800 459) goto err_region;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 460) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 461)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 462) return 0;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 463)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 464) err_region:
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 465) pci_release_region(pdev, i);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 466) err_inval:
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 467) while (--i >= 0) {
fb4d64e78ceab (Frederik Deweerdt 2007-02-16 01:27:15 -0800 468) if (!(mask & (1 << i)))
fb4d64e78ceab (Frederik Deweerdt 2007-02-16 01:27:15 -0800 469) continue;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 470) pcim_iounmap(pdev, iomap[i]);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 471) pci_release_region(pdev, i);
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 472) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 473)
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 474) return rc;
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 475) }
5ea8176994003 (Al Viro 2007-02-11 15:41:31 +0000 476) EXPORT_SYMBOL(pcim_iomap_regions);
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 477)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 478) /**
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 479) * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 480) * @pdev: PCI device to map IO resources for
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 481) * @mask: Mask of BARs to iomap
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 482) * @name: Name used when requesting regions
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 483) *
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 484) * Request all PCI BARs and iomap regions specified by @mask.
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 485) */
fb7ebfe4108e2 (Yinghai Lu 2012-01-04 15:50:02 -0800 486) int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 487) const char *name)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 488) {
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 489) int request_mask = ((1 << 6) - 1) & ~mask;
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 490) int rc;
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 491)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 492) rc = pci_request_selected_regions(pdev, request_mask, name);
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 493) if (rc)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 494) return rc;
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 495)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 496) rc = pcim_iomap_regions(pdev, mask, name);
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 497) if (rc)
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 498) pci_release_selected_regions(pdev, request_mask);
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 499) return rc;
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 500) }
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 501) EXPORT_SYMBOL(pcim_iomap_regions_request_all);
916fbfb7ae5f8 (Tejun Heo 2008-03-12 15:26:34 +0900 502)
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 503) /**
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 504) * pcim_iounmap_regions - Unmap and release PCI BARs
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 505) * @pdev: PCI device to map IO resources for
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 506) * @mask: Mask of BARs to unmap and release
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 507) *
4d45ada36b36a (Kulikov Vasiliy 2010-07-10 14:07:41 +0400 508) * Unmap and release regions specified by @mask.
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 509) */
fb7ebfe4108e2 (Yinghai Lu 2012-01-04 15:50:02 -0800 510) void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 511) {
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 512) void __iomem * const *iomap;
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 513) int i;
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 514)
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 515) iomap = pcim_iomap_table(pdev);
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 516) if (!iomap)
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 517) return;
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 518)
1f35d04a02a65 (Dan Carpenter 2015-09-21 19:21:51 +0300 519) for (i = 0; i < PCIM_IOMAP_MAX; i++) {
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 520) if (!(mask & (1 << i)))
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 521) continue;
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 522)
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 523) pcim_iounmap(pdev, iomap[i]);
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 524) pci_release_region(pdev, i);
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 525) }
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 526) }
ec04b075843d1 (Tejun Heo 2007-03-09 19:45:58 +0900 527) EXPORT_SYMBOL(pcim_iounmap_regions);
571806a9f70fc (Wolfram Sang 2011-10-25 15:03:42 +0200 528) #endif /* CONFIG_PCI */