OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [lib/] [devres.c] - Blame information for rev 79

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
#include <linux/pci.h>
2
#include <linux/io.h>
3
#include <linux/module.h>
4
 
5
static void devm_ioremap_release(struct device *dev, void *res)
6
{
7
        iounmap(*(void __iomem **)res);
8
}
9
 
10
static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
11
{
12
        return *(void **)res == match_data;
13
}
14
 
15
/**
16
 * devm_ioremap - Managed ioremap()
17
 * @dev: Generic device to remap IO address for
18
 * @offset: BUS offset to map
19
 * @size: Size of map
20
 *
21
 * Managed ioremap().  Map is automatically unmapped on driver detach.
22
 */
23
void __iomem *devm_ioremap(struct device *dev, unsigned long offset,
24
                           unsigned long size)
25
{
26
        void __iomem **ptr, *addr;
27
 
28
        ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
29
        if (!ptr)
30
                return NULL;
31
 
32
        addr = ioremap(offset, size);
33
        if (addr) {
34
                *ptr = addr;
35
                devres_add(dev, ptr);
36
        } else
37
                devres_free(ptr);
38
 
39
        return addr;
40
}
41
EXPORT_SYMBOL(devm_ioremap);
42
 
43
/**
44
 * devm_ioremap_nocache - Managed ioremap_nocache()
45
 * @dev: Generic device to remap IO address for
46
 * @offset: BUS offset to map
47
 * @size: Size of map
48
 *
49
 * Managed ioremap_nocache().  Map is automatically unmapped on driver
50
 * detach.
51
 */
52
void __iomem *devm_ioremap_nocache(struct device *dev, unsigned long offset,
53
                                   unsigned long size)
54
{
55
        void __iomem **ptr, *addr;
56
 
57
        ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
58
        if (!ptr)
59
                return NULL;
60
 
61
        addr = ioremap_nocache(offset, size);
62
        if (addr) {
63
                *ptr = addr;
64
                devres_add(dev, ptr);
65
        } else
66
                devres_free(ptr);
67
 
68
        return addr;
69
}
70
EXPORT_SYMBOL(devm_ioremap_nocache);
71
 
72
/**
73
 * devm_iounmap - Managed iounmap()
74
 * @dev: Generic device to unmap for
75
 * @addr: Address to unmap
76
 *
77
 * Managed iounmap().  @addr must have been mapped using devm_ioremap*().
78
 */
79
void devm_iounmap(struct device *dev, void __iomem *addr)
80
{
81
        iounmap(addr);
82
        WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
83
                               (void *)addr));
84
}
85
EXPORT_SYMBOL(devm_iounmap);
86
 
87
#ifdef CONFIG_HAS_IOPORT
88
/*
89
 * Generic iomap devres
90
 */
91
static void devm_ioport_map_release(struct device *dev, void *res)
92
{
93
        ioport_unmap(*(void __iomem **)res);
94
}
95
 
96
static int devm_ioport_map_match(struct device *dev, void *res,
97
                                 void *match_data)
98
{
99
        return *(void **)res == match_data;
100
}
101
 
102
/**
103
 * devm_ioport_map - Managed ioport_map()
104
 * @dev: Generic device to map ioport for
105
 * @port: Port to map
106
 * @nr: Number of ports to map
107
 *
108
 * Managed ioport_map().  Map is automatically unmapped on driver
109
 * detach.
110
 */
111
void __iomem * devm_ioport_map(struct device *dev, unsigned long port,
112
                               unsigned int nr)
113
{
114
        void __iomem **ptr, *addr;
115
 
116
        ptr = devres_alloc(devm_ioport_map_release, sizeof(*ptr), GFP_KERNEL);
117
        if (!ptr)
118
                return NULL;
119
 
120
        addr = ioport_map(port, nr);
121
        if (addr) {
122
                *ptr = addr;
123
                devres_add(dev, ptr);
124
        } else
125
                devres_free(ptr);
126
 
127
        return addr;
128
}
129
EXPORT_SYMBOL(devm_ioport_map);
130
 
131
/**
132
 * devm_ioport_unmap - Managed ioport_unmap()
133
 * @dev: Generic device to unmap for
134
 * @addr: Address to unmap
135
 *
136
 * Managed ioport_unmap().  @addr must have been mapped using
137
 * devm_ioport_map().
138
 */
139
void devm_ioport_unmap(struct device *dev, void __iomem *addr)
140
{
141
        ioport_unmap(addr);
142
        WARN_ON(devres_destroy(dev, devm_ioport_map_release,
143
                               devm_ioport_map_match, (void *)addr));
144
}
145
EXPORT_SYMBOL(devm_ioport_unmap);
146
 
147
#ifdef CONFIG_PCI
148
/*
149
 * PCI iomap devres
150
 */
151
#define PCIM_IOMAP_MAX  PCI_ROM_RESOURCE
152
 
153
struct pcim_iomap_devres {
154
        void __iomem *table[PCIM_IOMAP_MAX];
155
};
156
 
157
static void pcim_iomap_release(struct device *gendev, void *res)
158
{
159
        struct pci_dev *dev = container_of(gendev, struct pci_dev, dev);
160
        struct pcim_iomap_devres *this = res;
161
        int i;
162
 
163
        for (i = 0; i < PCIM_IOMAP_MAX; i++)
164
                if (this->table[i])
165
                        pci_iounmap(dev, this->table[i]);
166
}
167
 
168
/**
169
 * pcim_iomap_table - access iomap allocation table
170
 * @pdev: PCI device to access iomap table for
171
 *
172
 * Access iomap allocation table for @dev.  If iomap table doesn't
173
 * exist and @pdev is managed, it will be allocated.  All iomaps
174
 * recorded in the iomap table are automatically unmapped on driver
175
 * detach.
176
 *
177
 * This function might sleep when the table is first allocated but can
178
 * be safely called without context and guaranteed to succed once
179
 * allocated.
180
 */
181
void __iomem * const * pcim_iomap_table(struct pci_dev *pdev)
182
{
183
        struct pcim_iomap_devres *dr, *new_dr;
184
 
185
        dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
186
        if (dr)
187
                return dr->table;
188
 
189
        new_dr = devres_alloc(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL);
190
        if (!new_dr)
191
                return NULL;
192
        dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
193
        return dr->table;
194
}
195
EXPORT_SYMBOL(pcim_iomap_table);
196
 
197
/**
198
 * pcim_iomap - Managed pcim_iomap()
199
 * @pdev: PCI device to iomap for
200
 * @bar: BAR to iomap
201
 * @maxlen: Maximum length of iomap
202
 *
203
 * Managed pci_iomap().  Map is automatically unmapped on driver
204
 * detach.
205
 */
206
void __iomem * pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
207
{
208
        void __iomem **tbl;
209
 
210
        BUG_ON(bar >= PCIM_IOMAP_MAX);
211
 
212
        tbl = (void __iomem **)pcim_iomap_table(pdev);
213
        if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
214
                return NULL;
215
 
216
        tbl[bar] = pci_iomap(pdev, bar, maxlen);
217
        return tbl[bar];
218
}
219
EXPORT_SYMBOL(pcim_iomap);
220
 
221
/**
222
 * pcim_iounmap - Managed pci_iounmap()
223
 * @pdev: PCI device to iounmap for
224
 * @addr: Address to unmap
225
 *
226
 * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
227
 */
228
void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
229
{
230
        void __iomem **tbl;
231
        int i;
232
 
233
        pci_iounmap(pdev, addr);
234
 
235
        tbl = (void __iomem **)pcim_iomap_table(pdev);
236
        BUG_ON(!tbl);
237
 
238
        for (i = 0; i < PCIM_IOMAP_MAX; i++)
239
                if (tbl[i] == addr) {
240
                        tbl[i] = NULL;
241
                        return;
242
                }
243
        WARN_ON(1);
244
}
245
EXPORT_SYMBOL(pcim_iounmap);
246
 
247
/**
248
 * pcim_iomap_regions - Request and iomap PCI BARs
249
 * @pdev: PCI device to map IO resources for
250
 * @mask: Mask of BARs to request and iomap
251
 * @name: Name used when requesting regions
252
 *
253
 * Request and iomap regions specified by @mask.
254
 */
255
int pcim_iomap_regions(struct pci_dev *pdev, u16 mask, const char *name)
256
{
257
        void __iomem * const *iomap;
258
        int i, rc;
259
 
260
        iomap = pcim_iomap_table(pdev);
261
        if (!iomap)
262
                return -ENOMEM;
263
 
264
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
265
                unsigned long len;
266
 
267
                if (!(mask & (1 << i)))
268
                        continue;
269
 
270
                rc = -EINVAL;
271
                len = pci_resource_len(pdev, i);
272
                if (!len)
273
                        goto err_inval;
274
 
275
                rc = pci_request_region(pdev, i, name);
276
                if (rc)
277
                        goto err_inval;
278
 
279
                rc = -ENOMEM;
280
                if (!pcim_iomap(pdev, i, 0))
281
                        goto err_region;
282
        }
283
 
284
        return 0;
285
 
286
 err_region:
287
        pci_release_region(pdev, i);
288
 err_inval:
289
        while (--i >= 0) {
290
                if (!(mask & (1 << i)))
291
                        continue;
292
                pcim_iounmap(pdev, iomap[i]);
293
                pci_release_region(pdev, i);
294
        }
295
 
296
        return rc;
297
}
298
EXPORT_SYMBOL(pcim_iomap_regions);
299
 
300
/**
301
 * pcim_iounmap_regions - Unmap and release PCI BARs
302
 * @pdev: PCI device to map IO resources for
303
 * @mask: Mask of BARs to unmap and release
304
 *
305
 * Unamp and release regions specified by @mask.
306
 */
307
void pcim_iounmap_regions(struct pci_dev *pdev, u16 mask)
308
{
309
        void __iomem * const *iomap;
310
        int i;
311
 
312
        iomap = pcim_iomap_table(pdev);
313
        if (!iomap)
314
                return;
315
 
316
        for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
317
                if (!(mask & (1 << i)))
318
                        continue;
319
 
320
                pcim_iounmap(pdev, iomap[i]);
321
                pci_release_region(pdev, i);
322
        }
323
}
324
EXPORT_SYMBOL(pcim_iounmap_regions);
325
#endif
326
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.