Blame view

lib/iomap.c 9.15 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  // SPDX-License-Identifier: GPL-2.0
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
  /*
   * Implement the default iomap interfaces
   *
   * (C) Copyright 2004 Linus Torvalds
   */
  #include <linux/pci.h>
9ac7849e3   Tejun Heo   devres: device re...
8
  #include <linux/io.h>
8bc3bcc93   Paul Gortmaker   lib: reduce the u...
9
  #include <linux/export.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
  
  /*
   * Read/write from/to an (offsettable) iomem cookie. It might be a PIO
   * access or a MMIO access, these functions don't care. The info is
   * encoded in the hardware mapping set up by the mapping functions
   * (or the cookie itself, depending on implementation and hw).
   *
   * The generic routines don't assume any hardware mappings, and just
   * encode the PIO/MMIO as part of the cookie. They coldly assume that
   * the MMIO IO mappings are not in the low address range.
   *
   * Architectures for which this is not true can't use this generic
   * implementation and should do their own copy.
   */
  
  #ifndef HAVE_ARCH_PIO_SIZE
  /*
   * We encode the physical PIO addresses (0-0xffff) into the
   * pointer by offsetting them with a constant (0x10000) and
   * assuming that all the low addresses are always PIO. That means
   * we can do some sanity checks on the low bits, and don't
   * need to just take things for granted.
   */
  #define PIO_OFFSET	0x10000UL
  #define PIO_MASK	0x0ffffUL
  #define PIO_RESERVED	0x40000UL
  #endif
6cbf0c704   Linus Torvalds   iomap: make the d...
37
38
39
40
41
  static void bad_io_access(unsigned long port, const char *access)
  {
  	static int count = 10;
  	if (count) {
  		count--;
5cd2b459d   Arjan van de Ven   Use WARN() in lib/
42
43
  		WARN(1, KERN_ERR "Bad IO access at port %#lx (%s)
  ", port, access);
6cbf0c704   Linus Torvalds   iomap: make the d...
44
45
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
48
  /*
   * Ugly macros are a way of life.
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49
50
  #define IO_COND(addr, is_pio, is_mmio) do {			\
  	unsigned long port = (unsigned long __force)addr;	\
6cbf0c704   Linus Torvalds   iomap: make the d...
51
52
53
  	if (port >= PIO_RESERVED) {				\
  		is_mmio;					\
  	} else if (port > PIO_OFFSET) {				\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
55
  		port &= PIO_MASK;				\
  		is_pio;						\
6cbf0c704   Linus Torvalds   iomap: make the d...
56
57
  	} else							\
  		bad_io_access(port, #is_pio );			\
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
58
  } while (0)
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
59
60
61
62
63
64
  #ifndef pio_read16be
  #define pio_read16be(port) swab16(inw(port))
  #define pio_read32be(port) swab32(inl(port))
  #endif
  
  #ifndef mmio_read16be
aecc787c0   Logan Gunthorpe   iomap: Use non-ra...
65
66
  #define mmio_read16be(addr) swab16(readw(addr))
  #define mmio_read32be(addr) swab32(readl(addr))
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
67
  #define mmio_read64be(addr) swab64(readq(addr))
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
68
  #endif
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
69
  unsigned int ioread8(const void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
  {
  	IO_COND(addr, return inb(port), return readb(addr));
6cbf0c704   Linus Torvalds   iomap: make the d...
72
  	return 0xff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
73
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
74
  unsigned int ioread16(const void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
75
76
  {
  	IO_COND(addr, return inw(port), return readw(addr));
6cbf0c704   Linus Torvalds   iomap: make the d...
77
  	return 0xffff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
79
  unsigned int ioread16be(const void __iomem *addr)
dae409a27   James Bottomley   [PATCH] add Big E...
80
  {
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
81
  	IO_COND(addr, return pio_read16be(port), return mmio_read16be(addr));
6cbf0c704   Linus Torvalds   iomap: make the d...
82
  	return 0xffff;
dae409a27   James Bottomley   [PATCH] add Big E...
83
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
84
  unsigned int ioread32(const void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85
86
  {
  	IO_COND(addr, return inl(port), return readl(addr));
6cbf0c704   Linus Torvalds   iomap: make the d...
87
  	return 0xffffffff;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
89
  unsigned int ioread32be(const void __iomem *addr)
dae409a27   James Bottomley   [PATCH] add Big E...
90
  {
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
91
  	IO_COND(addr, return pio_read32be(port), return mmio_read32be(addr));
6cbf0c704   Linus Torvalds   iomap: make the d...
92
  	return 0xffffffff;
dae409a27   James Bottomley   [PATCH] add Big E...
93
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
  EXPORT_SYMBOL(ioread8);
  EXPORT_SYMBOL(ioread16);
dae409a27   James Bottomley   [PATCH] add Big E...
96
  EXPORT_SYMBOL(ioread16be);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
  EXPORT_SYMBOL(ioread32);
dae409a27   James Bottomley   [PATCH] add Big E...
98
  EXPORT_SYMBOL(ioread32be);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
99

79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  #ifdef readq
  static u64 pio_read64_lo_hi(unsigned long port)
  {
  	u64 lo, hi;
  
  	lo = inl(port);
  	hi = inl(port + sizeof(u32));
  
  	return lo | (hi << 32);
  }
  
  static u64 pio_read64_hi_lo(unsigned long port)
  {
  	u64 lo, hi;
  
  	hi = inl(port + sizeof(u32));
  	lo = inl(port);
  
  	return lo | (hi << 32);
  }
  
  static u64 pio_read64be_lo_hi(unsigned long port)
  {
  	u64 lo, hi;
  
  	lo = pio_read32be(port + sizeof(u32));
  	hi = pio_read32be(port);
  
  	return lo | (hi << 32);
  }
  
  static u64 pio_read64be_hi_lo(unsigned long port)
  {
  	u64 lo, hi;
  
  	hi = pio_read32be(port);
  	lo = pio_read32be(port + sizeof(u32));
  
  	return lo | (hi << 32);
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
140
  u64 ioread64_lo_hi(const void __iomem *addr)
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
141
142
143
144
  {
  	IO_COND(addr, return pio_read64_lo_hi(port), return readq(addr));
  	return 0xffffffffffffffffULL;
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
145
  u64 ioread64_hi_lo(const void __iomem *addr)
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
146
147
148
149
  {
  	IO_COND(addr, return pio_read64_hi_lo(port), return readq(addr));
  	return 0xffffffffffffffffULL;
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
150
  u64 ioread64be_lo_hi(const void __iomem *addr)
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
151
152
153
154
155
  {
  	IO_COND(addr, return pio_read64be_lo_hi(port),
  		return mmio_read64be(addr));
  	return 0xffffffffffffffffULL;
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
156
  u64 ioread64be_hi_lo(const void __iomem *addr)
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
157
158
159
160
161
162
163
164
165
166
167
168
  {
  	IO_COND(addr, return pio_read64be_hi_lo(port),
  		return mmio_read64be(addr));
  	return 0xffffffffffffffffULL;
  }
  
  EXPORT_SYMBOL(ioread64_lo_hi);
  EXPORT_SYMBOL(ioread64_hi_lo);
  EXPORT_SYMBOL(ioread64be_lo_hi);
  EXPORT_SYMBOL(ioread64be_hi_lo);
  
  #endif /* readq */
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
169
170
171
172
173
174
  #ifndef pio_write16be
  #define pio_write16be(val,port) outw(swab16(val),port)
  #define pio_write32be(val,port) outl(swab32(val),port)
  #endif
  
  #ifndef mmio_write16be
aecc787c0   Logan Gunthorpe   iomap: Use non-ra...
175
176
  #define mmio_write16be(val,port) writew(swab16(val),port)
  #define mmio_write32be(val,port) writel(swab32(val),port)
79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
177
  #define mmio_write64be(val,port) writeq(swab64(val),port)
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
178
  #endif
9f741cb8f   Harvey Harrison   lib: remove fastc...
179
  void iowrite8(u8 val, void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
181
182
  {
  	IO_COND(addr, outb(val,port), writeb(val, addr));
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
183
  void iowrite16(u16 val, void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
184
185
186
  {
  	IO_COND(addr, outw(val,port), writew(val, addr));
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
187
  void iowrite16be(u16 val, void __iomem *addr)
dae409a27   James Bottomley   [PATCH] add Big E...
188
  {
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
189
  	IO_COND(addr, pio_write16be(val,port), mmio_write16be(val, addr));
dae409a27   James Bottomley   [PATCH] add Big E...
190
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
191
  void iowrite32(u32 val, void __iomem *addr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
192
193
194
  {
  	IO_COND(addr, outl(val,port), writel(val, addr));
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
195
  void iowrite32be(u32 val, void __iomem *addr)
dae409a27   James Bottomley   [PATCH] add Big E...
196
  {
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
197
  	IO_COND(addr, pio_write32be(val,port), mmio_write32be(val, addr));
dae409a27   James Bottomley   [PATCH] add Big E...
198
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
  EXPORT_SYMBOL(iowrite8);
  EXPORT_SYMBOL(iowrite16);
dae409a27   James Bottomley   [PATCH] add Big E...
201
  EXPORT_SYMBOL(iowrite16be);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  EXPORT_SYMBOL(iowrite32);
dae409a27   James Bottomley   [PATCH] add Big E...
203
  EXPORT_SYMBOL(iowrite32be);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204

79bf0cbd8   Logan Gunthorpe   iomap: introduce ...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
  #ifdef writeq
  static void pio_write64_lo_hi(u64 val, unsigned long port)
  {
  	outl(val, port);
  	outl(val >> 32, port + sizeof(u32));
  }
  
  static void pio_write64_hi_lo(u64 val, unsigned long port)
  {
  	outl(val >> 32, port + sizeof(u32));
  	outl(val, port);
  }
  
  static void pio_write64be_lo_hi(u64 val, unsigned long port)
  {
  	pio_write32be(val, port + sizeof(u32));
  	pio_write32be(val >> 32, port);
  }
  
  static void pio_write64be_hi_lo(u64 val, unsigned long port)
  {
  	pio_write32be(val >> 32, port);
  	pio_write32be(val, port + sizeof(u32));
  }
  
  void iowrite64_lo_hi(u64 val, void __iomem *addr)
  {
  	IO_COND(addr, pio_write64_lo_hi(val, port),
  		writeq(val, addr));
  }
  
  void iowrite64_hi_lo(u64 val, void __iomem *addr)
  {
  	IO_COND(addr, pio_write64_hi_lo(val, port),
  		writeq(val, addr));
  }
  
  void iowrite64be_lo_hi(u64 val, void __iomem *addr)
  {
  	IO_COND(addr, pio_write64be_lo_hi(val, port),
  		mmio_write64be(val, addr));
  }
  
  void iowrite64be_hi_lo(u64 val, void __iomem *addr)
  {
  	IO_COND(addr, pio_write64be_hi_lo(val, port),
  		mmio_write64be(val, addr));
  }
  
  EXPORT_SYMBOL(iowrite64_lo_hi);
  EXPORT_SYMBOL(iowrite64_hi_lo);
  EXPORT_SYMBOL(iowrite64be_lo_hi);
  EXPORT_SYMBOL(iowrite64be_hi_lo);
  
  #endif /* readq */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
  /*
   * These are the "repeat MMIO read/write" functions.
   * Note the "__raw" accesses, since we don't want to
   * convert to CPU byte order. We write in "IO byte
   * order" (we also don't have IO barriers).
   */
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
266
  #ifndef mmio_insb
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
267
  static inline void mmio_insb(const void __iomem *addr, u8 *dst, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
268
269
270
271
272
273
274
  {
  	while (--count >= 0) {
  		u8 data = __raw_readb(addr);
  		*dst = data;
  		dst++;
  	}
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
275
  static inline void mmio_insw(const void __iomem *addr, u16 *dst, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
276
277
278
279
280
281
282
  {
  	while (--count >= 0) {
  		u16 data = __raw_readw(addr);
  		*dst = data;
  		dst++;
  	}
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
283
  static inline void mmio_insl(const void __iomem *addr, u32 *dst, int count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
288
289
290
  {
  	while (--count >= 0) {
  		u32 data = __raw_readl(addr);
  		*dst = data;
  		dst++;
  	}
  }
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
291
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292

34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
293
  #ifndef mmio_outsb
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  static inline void mmio_outsb(void __iomem *addr, const u8 *src, int count)
  {
  	while (--count >= 0) {
  		__raw_writeb(*src, addr);
  		src++;
  	}
  }
  static inline void mmio_outsw(void __iomem *addr, const u16 *src, int count)
  {
  	while (--count >= 0) {
  		__raw_writew(*src, addr);
  		src++;
  	}
  }
  static inline void mmio_outsl(void __iomem *addr, const u32 *src, int count)
  {
  	while (--count >= 0) {
  		__raw_writel(*src, addr);
  		src++;
  	}
  }
34ba8a5cd   Linus Torvalds   [PATCH] Arch prov...
315
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
316

8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
317
  void ioread8_rep(const void __iomem *addr, void *dst, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318
319
320
  {
  	IO_COND(addr, insb(port,dst,count), mmio_insb(addr, dst, count));
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
321
  void ioread16_rep(const void __iomem *addr, void *dst, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
322
323
324
  {
  	IO_COND(addr, insw(port,dst,count), mmio_insw(addr, dst, count));
  }
8f28ca6bd   Krzysztof Kozlowski   iomap: constify i...
325
  void ioread32_rep(const void __iomem *addr, void *dst, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
327
328
329
330
331
  {
  	IO_COND(addr, insl(port,dst,count), mmio_insl(addr, dst, count));
  }
  EXPORT_SYMBOL(ioread8_rep);
  EXPORT_SYMBOL(ioread16_rep);
  EXPORT_SYMBOL(ioread32_rep);
9f741cb8f   Harvey Harrison   lib: remove fastc...
332
  void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
333
334
335
  {
  	IO_COND(addr, outsb(port, src, count), mmio_outsb(addr, src, count));
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
336
  void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
337
338
339
  {
  	IO_COND(addr, outsw(port, src, count), mmio_outsw(addr, src, count));
  }
9f741cb8f   Harvey Harrison   lib: remove fastc...
340
  void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
341
342
343
344
345
346
  {
  	IO_COND(addr, outsl(port, src,count), mmio_outsl(addr, src, count));
  }
  EXPORT_SYMBOL(iowrite8_rep);
  EXPORT_SYMBOL(iowrite16_rep);
  EXPORT_SYMBOL(iowrite32_rep);
ce816fa88   Uwe Kleine-König   Kconfig: rename H...
347
  #ifdef CONFIG_HAS_IOPORT_MAP
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  /* Create a virtual mapping cookie for an IO port range */
  void __iomem *ioport_map(unsigned long port, unsigned int nr)
  {
  	if (port > PIO_MASK)
  		return NULL;
  	return (void __iomem *) (unsigned long) (port + PIO_OFFSET);
  }
  
  void ioport_unmap(void __iomem *addr)
  {
  	/* Nothing to do */
  }
  EXPORT_SYMBOL(ioport_map);
  EXPORT_SYMBOL(ioport_unmap);
ce816fa88   Uwe Kleine-König   Kconfig: rename H...
362
  #endif /* CONFIG_HAS_IOPORT_MAP */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363

82ed223c2   Jonas Bonn   iomap: make IOPOR...
364
  #ifdef CONFIG_PCI
66eab4df2   Michael S. Tsirkin   lib: add GENERIC_...
365
366
  /* Hide the details if this is a MMIO or PIO address space and just do what
   * you expect in the correct way. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
368
369
370
  void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
  {
  	IO_COND(addr, /* nothing */, iounmap(addr));
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
371
  EXPORT_SYMBOL(pci_iounmap);
82ed223c2   Jonas Bonn   iomap: make IOPOR...
372
  #endif /* CONFIG_PCI */