Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/parisc/lib/iomap.c
10817 views
1
/*
2
* iomap.c - Implement iomap interface for PA-RISC
3
* Copyright (c) 2004 Matthew Wilcox
4
*/
5
6
#include <linux/ioport.h>
7
#include <linux/pci.h>
8
#include <asm/io.h>
9
10
/*
11
* The iomap space on 32-bit PA-RISC is intended to look like this:
12
* 00000000-7fffffff virtual mapped IO
13
* 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
14
* 90000000-9fffffff Dino port space
15
* a0000000-afffffff Astro port space
16
* b0000000-bfffffff PAT port space
17
* c0000000-cfffffff non-swapped memory IO
18
* f0000000-ffffffff legacy IO memory pointers
19
*
20
* For the moment, here's what it looks like:
21
* 80000000-8fffffff All ISA/EISA port space
22
* f0000000-ffffffff legacy IO memory pointers
23
*
24
* On 64-bit, everything is extended, so:
25
* 8000000000000000-8fffffffffffffff All ISA/EISA port space
26
* f000000000000000-ffffffffffffffff legacy IO memory pointers
27
*/
28
29
/*
30
* Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
31
* but that's slow and we know it'll be within the first 2GB.
32
*/
33
#ifdef CONFIG_64BIT
34
#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<63) != 0)
35
#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 60) & 7)
36
#define IOPORT_MAP_BASE (8UL << 60)
37
#else
38
#define INDIRECT_ADDR(addr) (((unsigned long)(addr) & 1UL<<31) != 0)
39
#define ADDR_TO_REGION(addr) (((unsigned long)addr >> 28) & 7)
40
#define IOPORT_MAP_BASE (8UL << 28)
41
#endif
42
43
struct iomap_ops {
44
unsigned int (*read8)(void __iomem *);
45
unsigned int (*read16)(void __iomem *);
46
unsigned int (*read16be)(void __iomem *);
47
unsigned int (*read32)(void __iomem *);
48
unsigned int (*read32be)(void __iomem *);
49
void (*write8)(u8, void __iomem *);
50
void (*write16)(u16, void __iomem *);
51
void (*write16be)(u16, void __iomem *);
52
void (*write32)(u32, void __iomem *);
53
void (*write32be)(u32, void __iomem *);
54
void (*read8r)(void __iomem *, void *, unsigned long);
55
void (*read16r)(void __iomem *, void *, unsigned long);
56
void (*read32r)(void __iomem *, void *, unsigned long);
57
void (*write8r)(void __iomem *, const void *, unsigned long);
58
void (*write16r)(void __iomem *, const void *, unsigned long);
59
void (*write32r)(void __iomem *, const void *, unsigned long);
60
};
61
62
/* Generic ioport ops. To be replaced later by specific dino/elroy/wax code */
63
64
#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
65
66
static unsigned int ioport_read8(void __iomem *addr)
67
{
68
return inb(ADDR2PORT(addr));
69
}
70
71
static unsigned int ioport_read16(void __iomem *addr)
72
{
73
return inw(ADDR2PORT(addr));
74
}
75
76
static unsigned int ioport_read32(void __iomem *addr)
77
{
78
return inl(ADDR2PORT(addr));
79
}
80
81
static void ioport_write8(u8 datum, void __iomem *addr)
82
{
83
outb(datum, ADDR2PORT(addr));
84
}
85
86
static void ioport_write16(u16 datum, void __iomem *addr)
87
{
88
outw(datum, ADDR2PORT(addr));
89
}
90
91
static void ioport_write32(u32 datum, void __iomem *addr)
92
{
93
outl(datum, ADDR2PORT(addr));
94
}
95
96
static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
97
{
98
insb(ADDR2PORT(addr), dst, count);
99
}
100
101
static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
102
{
103
insw(ADDR2PORT(addr), dst, count);
104
}
105
106
static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
107
{
108
insl(ADDR2PORT(addr), dst, count);
109
}
110
111
static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
112
{
113
outsb(ADDR2PORT(addr), s, n);
114
}
115
116
static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
117
{
118
outsw(ADDR2PORT(addr), s, n);
119
}
120
121
static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
122
{
123
outsl(ADDR2PORT(addr), s, n);
124
}
125
126
static const struct iomap_ops ioport_ops = {
127
ioport_read8,
128
ioport_read16,
129
ioport_read16,
130
ioport_read32,
131
ioport_read32,
132
ioport_write8,
133
ioport_write16,
134
ioport_write16,
135
ioport_write32,
136
ioport_write32,
137
ioport_read8r,
138
ioport_read16r,
139
ioport_read32r,
140
ioport_write8r,
141
ioport_write16r,
142
ioport_write32r,
143
};
144
145
/* Legacy I/O memory ops */
146
147
static unsigned int iomem_read8(void __iomem *addr)
148
{
149
return readb(addr);
150
}
151
152
static unsigned int iomem_read16(void __iomem *addr)
153
{
154
return readw(addr);
155
}
156
157
static unsigned int iomem_read16be(void __iomem *addr)
158
{
159
return __raw_readw(addr);
160
}
161
162
static unsigned int iomem_read32(void __iomem *addr)
163
{
164
return readl(addr);
165
}
166
167
static unsigned int iomem_read32be(void __iomem *addr)
168
{
169
return __raw_readl(addr);
170
}
171
172
static void iomem_write8(u8 datum, void __iomem *addr)
173
{
174
writeb(datum, addr);
175
}
176
177
static void iomem_write16(u16 datum, void __iomem *addr)
178
{
179
writew(datum, addr);
180
}
181
182
static void iomem_write16be(u16 datum, void __iomem *addr)
183
{
184
__raw_writew(datum, addr);
185
}
186
187
static void iomem_write32(u32 datum, void __iomem *addr)
188
{
189
writel(datum, addr);
190
}
191
192
static void iomem_write32be(u32 datum, void __iomem *addr)
193
{
194
__raw_writel(datum, addr);
195
}
196
197
static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
198
{
199
while (count--) {
200
*(u8 *)dst = __raw_readb(addr);
201
dst++;
202
}
203
}
204
205
static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
206
{
207
while (count--) {
208
*(u16 *)dst = __raw_readw(addr);
209
dst += 2;
210
}
211
}
212
213
static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
214
{
215
while (count--) {
216
*(u32 *)dst = __raw_readl(addr);
217
dst += 4;
218
}
219
}
220
221
static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
222
{
223
while (n--) {
224
__raw_writeb(*(u8 *)s, addr);
225
s++;
226
}
227
}
228
229
static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
230
{
231
while (n--) {
232
__raw_writew(*(u16 *)s, addr);
233
s += 2;
234
}
235
}
236
237
static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
238
{
239
while (n--) {
240
__raw_writel(*(u32 *)s, addr);
241
s += 4;
242
}
243
}
244
245
static const struct iomap_ops iomem_ops = {
246
iomem_read8,
247
iomem_read16,
248
iomem_read16be,
249
iomem_read32,
250
iomem_read32be,
251
iomem_write8,
252
iomem_write16,
253
iomem_write16be,
254
iomem_write32,
255
iomem_write32be,
256
iomem_read8r,
257
iomem_read16r,
258
iomem_read32r,
259
iomem_write8r,
260
iomem_write16r,
261
iomem_write32r,
262
};
263
264
static const struct iomap_ops *iomap_ops[8] = {
265
[0] = &ioport_ops,
266
[7] = &iomem_ops
267
};
268
269
270
unsigned int ioread8(void __iomem *addr)
271
{
272
if (unlikely(INDIRECT_ADDR(addr)))
273
return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
274
return *((u8 *)addr);
275
}
276
277
unsigned int ioread16(void __iomem *addr)
278
{
279
if (unlikely(INDIRECT_ADDR(addr)))
280
return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
281
return le16_to_cpup((u16 *)addr);
282
}
283
284
unsigned int ioread16be(void __iomem *addr)
285
{
286
if (unlikely(INDIRECT_ADDR(addr)))
287
return iomap_ops[ADDR_TO_REGION(addr)]->read16be(addr);
288
return *((u16 *)addr);
289
}
290
291
unsigned int ioread32(void __iomem *addr)
292
{
293
if (unlikely(INDIRECT_ADDR(addr)))
294
return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
295
return le32_to_cpup((u32 *)addr);
296
}
297
298
unsigned int ioread32be(void __iomem *addr)
299
{
300
if (unlikely(INDIRECT_ADDR(addr)))
301
return iomap_ops[ADDR_TO_REGION(addr)]->read32be(addr);
302
return *((u32 *)addr);
303
}
304
305
void iowrite8(u8 datum, void __iomem *addr)
306
{
307
if (unlikely(INDIRECT_ADDR(addr))) {
308
iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
309
} else {
310
*((u8 *)addr) = datum;
311
}
312
}
313
314
void iowrite16(u16 datum, void __iomem *addr)
315
{
316
if (unlikely(INDIRECT_ADDR(addr))) {
317
iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
318
} else {
319
*((u16 *)addr) = cpu_to_le16(datum);
320
}
321
}
322
323
void iowrite16be(u16 datum, void __iomem *addr)
324
{
325
if (unlikely(INDIRECT_ADDR(addr))) {
326
iomap_ops[ADDR_TO_REGION(addr)]->write16be(datum, addr);
327
} else {
328
*((u16 *)addr) = datum;
329
}
330
}
331
332
void iowrite32(u32 datum, void __iomem *addr)
333
{
334
if (unlikely(INDIRECT_ADDR(addr))) {
335
iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
336
} else {
337
*((u32 *)addr) = cpu_to_le32(datum);
338
}
339
}
340
341
void iowrite32be(u32 datum, void __iomem *addr)
342
{
343
if (unlikely(INDIRECT_ADDR(addr))) {
344
iomap_ops[ADDR_TO_REGION(addr)]->write32be(datum, addr);
345
} else {
346
*((u32 *)addr) = datum;
347
}
348
}
349
350
/* Repeating interfaces */
351
352
void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
353
{
354
if (unlikely(INDIRECT_ADDR(addr))) {
355
iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
356
} else {
357
while (count--) {
358
*(u8 *)dst = *(u8 *)addr;
359
dst++;
360
}
361
}
362
}
363
364
void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
365
{
366
if (unlikely(INDIRECT_ADDR(addr))) {
367
iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
368
} else {
369
while (count--) {
370
*(u16 *)dst = *(u16 *)addr;
371
dst += 2;
372
}
373
}
374
}
375
376
void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
377
{
378
if (unlikely(INDIRECT_ADDR(addr))) {
379
iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
380
} else {
381
while (count--) {
382
*(u32 *)dst = *(u32 *)addr;
383
dst += 4;
384
}
385
}
386
}
387
388
void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
389
{
390
if (unlikely(INDIRECT_ADDR(addr))) {
391
iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
392
} else {
393
while (count--) {
394
*(u8 *)addr = *(u8 *)src;
395
src++;
396
}
397
}
398
}
399
400
void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
401
{
402
if (unlikely(INDIRECT_ADDR(addr))) {
403
iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
404
} else {
405
while (count--) {
406
*(u16 *)addr = *(u16 *)src;
407
src += 2;
408
}
409
}
410
}
411
412
void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
413
{
414
if (unlikely(INDIRECT_ADDR(addr))) {
415
iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
416
} else {
417
while (count--) {
418
*(u32 *)addr = *(u32 *)src;
419
src += 4;
420
}
421
}
422
}
423
424
/* Mapping interfaces */
425
426
void __iomem *ioport_map(unsigned long port, unsigned int nr)
427
{
428
return (void __iomem *)(IOPORT_MAP_BASE | port);
429
}
430
431
void ioport_unmap(void __iomem *addr)
432
{
433
if (!INDIRECT_ADDR(addr)) {
434
iounmap(addr);
435
}
436
}
437
438
/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
439
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
440
{
441
resource_size_t start = pci_resource_start(dev, bar);
442
resource_size_t len = pci_resource_len(dev, bar);
443
unsigned long flags = pci_resource_flags(dev, bar);
444
445
if (!len || !start)
446
return NULL;
447
if (maxlen && len > maxlen)
448
len = maxlen;
449
if (flags & IORESOURCE_IO)
450
return ioport_map(start, len);
451
if (flags & IORESOURCE_MEM) {
452
if (flags & IORESOURCE_CACHEABLE)
453
return ioremap(start, len);
454
return ioremap_nocache(start, len);
455
}
456
/* What? */
457
return NULL;
458
}
459
460
void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
461
{
462
if (!INDIRECT_ADDR(addr)) {
463
iounmap(addr);
464
}
465
}
466
467
EXPORT_SYMBOL(ioread8);
468
EXPORT_SYMBOL(ioread16);
469
EXPORT_SYMBOL(ioread16be);
470
EXPORT_SYMBOL(ioread32);
471
EXPORT_SYMBOL(ioread32be);
472
EXPORT_SYMBOL(iowrite8);
473
EXPORT_SYMBOL(iowrite16);
474
EXPORT_SYMBOL(iowrite16be);
475
EXPORT_SYMBOL(iowrite32);
476
EXPORT_SYMBOL(iowrite32be);
477
EXPORT_SYMBOL(ioread8_rep);
478
EXPORT_SYMBOL(ioread16_rep);
479
EXPORT_SYMBOL(ioread32_rep);
480
EXPORT_SYMBOL(iowrite8_rep);
481
EXPORT_SYMBOL(iowrite16_rep);
482
EXPORT_SYMBOL(iowrite32_rep);
483
EXPORT_SYMBOL(ioport_map);
484
EXPORT_SYMBOL(ioport_unmap);
485
EXPORT_SYMBOL(pci_iomap);
486
EXPORT_SYMBOL(pci_iounmap);
487
488