2 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 #include <linux/rculist.h>
14 #include <linux/export.h>
15 #include <linux/ioport.h>
16 #include <linux/module.h>
17 #include <linux/types.h>
19 #include "nfit_test.h"
21 static LIST_HEAD(iomap_head
);
23 static struct iomap_ops
{
24 nfit_test_lookup_fn nfit_test_lookup
;
25 struct list_head list
;
27 .list
= LIST_HEAD_INIT(iomap_ops
.list
),
30 void nfit_test_setup(nfit_test_lookup_fn lookup
)
32 iomap_ops
.nfit_test_lookup
= lookup
;
33 list_add_rcu(&iomap_ops
.list
, &iomap_head
);
35 EXPORT_SYMBOL(nfit_test_setup
);
37 void nfit_test_teardown(void)
39 list_del_rcu(&iomap_ops
.list
);
42 EXPORT_SYMBOL(nfit_test_teardown
);
44 static struct nfit_test_resource
*get_nfit_res(resource_size_t resource
)
46 struct iomap_ops
*ops
;
48 ops
= list_first_or_null_rcu(&iomap_head
, typeof(*ops
), list
);
50 return ops
->nfit_test_lookup(resource
);
54 void __iomem
*__nfit_test_ioremap(resource_size_t offset
, unsigned long size
,
55 void __iomem
*(*fallback_fn
)(resource_size_t
, unsigned long))
57 struct nfit_test_resource
*nfit_res
;
60 nfit_res
= get_nfit_res(offset
);
63 return (void __iomem
*) nfit_res
->buf
+ offset
64 - nfit_res
->res
->start
;
65 return fallback_fn(offset
, size
);
68 void __iomem
*__wrap_devm_ioremap_nocache(struct device
*dev
,
69 resource_size_t offset
, unsigned long size
)
71 struct nfit_test_resource
*nfit_res
;
74 nfit_res
= get_nfit_res(offset
);
77 return (void __iomem
*) nfit_res
->buf
+ offset
78 - nfit_res
->res
->start
;
79 return devm_ioremap_nocache(dev
, offset
, size
);
81 EXPORT_SYMBOL(__wrap_devm_ioremap_nocache
);
83 void *__wrap_devm_memremap(struct device
*dev
, resource_size_t offset
,
84 size_t size
, unsigned long flags
)
86 struct nfit_test_resource
*nfit_res
;
89 nfit_res
= get_nfit_res(offset
);
92 return (void __iomem
*) nfit_res
->buf
+ offset
93 - nfit_res
->res
->start
;
94 return devm_memremap(dev
, offset
, size
, flags
);
96 EXPORT_SYMBOL(__wrap_devm_memremap
);
98 void __iomem
*__wrap_ioremap_nocache(resource_size_t offset
, unsigned long size
)
100 return __nfit_test_ioremap(offset
, size
, ioremap_nocache
);
102 EXPORT_SYMBOL(__wrap_ioremap_nocache
);
104 void __iomem
*__wrap_ioremap_wc(resource_size_t offset
, unsigned long size
)
106 return __nfit_test_ioremap(offset
, size
, ioremap_wc
);
108 EXPORT_SYMBOL(__wrap_ioremap_wc
);
110 void __wrap_iounmap(volatile void __iomem
*addr
)
112 struct nfit_test_resource
*nfit_res
;
115 nfit_res
= get_nfit_res((unsigned long) addr
);
119 return iounmap(addr
);
121 EXPORT_SYMBOL(__wrap_iounmap
);
123 static struct resource
*nfit_test_request_region(struct device
*dev
,
124 struct resource
*parent
, resource_size_t start
,
125 resource_size_t n
, const char *name
, int flags
)
127 struct nfit_test_resource
*nfit_res
;
129 if (parent
== &iomem_resource
) {
131 nfit_res
= get_nfit_res(start
);
134 struct resource
*res
= nfit_res
->res
+ 1;
136 if (start
+ n
> nfit_res
->res
->start
137 + resource_size(nfit_res
->res
)) {
138 pr_debug("%s: start: %llx n: %llx overflow: %pr\n",
145 res
->end
= start
+ n
- 1;
147 res
->flags
= resource_type(parent
);
148 res
->flags
|= IORESOURCE_BUSY
| flags
;
149 pr_debug("%s: %pr\n", __func__
, res
);
154 return __devm_request_region(dev
, parent
, start
, n
, name
);
155 return __request_region(parent
, start
, n
, name
, flags
);
158 struct resource
*__wrap___request_region(struct resource
*parent
,
159 resource_size_t start
, resource_size_t n
, const char *name
,
162 return nfit_test_request_region(NULL
, parent
, start
, n
, name
, flags
);
164 EXPORT_SYMBOL(__wrap___request_region
);
166 struct resource
*__wrap___devm_request_region(struct device
*dev
,
167 struct resource
*parent
, resource_size_t start
,
168 resource_size_t n
, const char *name
)
172 return nfit_test_request_region(dev
, parent
, start
, n
, name
, 0);
174 EXPORT_SYMBOL(__wrap___devm_request_region
);
176 void __wrap___release_region(struct resource
*parent
, resource_size_t start
,
179 struct nfit_test_resource
*nfit_res
;
181 if (parent
== &iomem_resource
) {
183 nfit_res
= get_nfit_res(start
);
186 struct resource
*res
= nfit_res
->res
+ 1;
188 if (start
!= res
->start
|| resource_size(res
) != n
)
189 pr_info("%s: start: %llx n: %llx mismatch: %pr\n",
190 __func__
, start
, n
, res
);
192 memset(res
, 0, sizeof(*res
));
196 __release_region(parent
, start
, n
);
198 EXPORT_SYMBOL(__wrap___release_region
);
200 MODULE_LICENSE("GPL v2");