1219820Sjeff/*-
2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc.
3219820Sjeff * Copyright (c) 2010 iX Systems, Inc.
4219820Sjeff * Copyright (c) 2010 Panasas, Inc.
5290706Shselasky * Copyright (c) 2013-2015 Mellanox Technologies, Ltd.
6219820Sjeff * All rights reserved.
7219820Sjeff *
8219820Sjeff * Redistribution and use in source and binary forms, with or without
9219820Sjeff * modification, are permitted provided that the following conditions
10219820Sjeff * are met:
11219820Sjeff * 1. Redistributions of source code must retain the above copyright
12219820Sjeff *    notice unmodified, this list of conditions, and the following
13219820Sjeff *    disclaimer.
14219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
15219820Sjeff *    notice, this list of conditions and the following disclaimer in the
16219820Sjeff *    documentation and/or other materials provided with the distribution.
17219820Sjeff *
18219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28289644Shselasky *
29289644Shselasky * $FreeBSD: stable/11/sys/compat/linuxkpi/common/include/linux/io.h 363149 2020-07-13 15:29:11Z hselasky $
30219820Sjeff */
31219820Sjeff#ifndef	_LINUX_IO_H_
32219820Sjeff#define	_LINUX_IO_H_
33219820Sjeff
34277396Shselasky#include <sys/endian.h>
35290335Shselasky#include <sys/types.h>
36219820Sjeff
37363149Shselasky#include <machine/vm.h>
38363149Shselasky
39299364Shselasky#include <linux/compiler.h>
40328653Shselasky#include <linux/types.h>
41299364Shselasky
42339734Stijl/*
43339734Stijl * XXX This is all x86 specific.  It should be bus space access.
44339734Stijl */
45339734Stijl
46339734Stijl/* Access MMIO registers atomically without barriers and byte swapping. */
47339734Stijl
48339734Stijlstatic inline uint8_t
49339734Stijl__raw_readb(const volatile void *addr)
50339734Stijl{
51339734Stijl	return (*(const volatile uint8_t *)addr);
52339734Stijl}
53339734Stijl#define	__raw_readb(addr)	__raw_readb(addr)
54339734Stijl
55339734Stijlstatic inline void
56339734Stijl__raw_writeb(uint8_t v, volatile void *addr)
57339734Stijl{
58339734Stijl	*(volatile uint8_t *)addr = v;
59339734Stijl}
60339734Stijl#define	__raw_writeb(v, addr)	__raw_writeb(v, addr)
61339734Stijl
62339734Stijlstatic inline uint16_t
63339734Stijl__raw_readw(const volatile void *addr)
64339734Stijl{
65339734Stijl	return (*(const volatile uint16_t *)addr);
66339734Stijl}
67339734Stijl#define	__raw_readw(addr)	__raw_readw(addr)
68339734Stijl
69339734Stijlstatic inline void
70339734Stijl__raw_writew(uint16_t v, volatile void *addr)
71339734Stijl{
72339734Stijl	*(volatile uint16_t *)addr = v;
73339734Stijl}
74339734Stijl#define	__raw_writew(v, addr)	__raw_writew(v, addr)
75339734Stijl
76219820Sjeffstatic inline uint32_t
77219820Sjeff__raw_readl(const volatile void *addr)
78219820Sjeff{
79339734Stijl	return (*(const volatile uint32_t *)addr);
80219820Sjeff}
81339734Stijl#define	__raw_readl(addr)	__raw_readl(addr)
82219820Sjeff
83219820Sjeffstatic inline void
84339734Stijl__raw_writel(uint32_t v, volatile void *addr)
85219820Sjeff{
86339734Stijl	*(volatile uint32_t *)addr = v;
87219820Sjeff}
88339734Stijl#define	__raw_writel(v, addr)	__raw_writel(v, addr)
89219820Sjeff
90339734Stijl#ifdef __LP64__
91219820Sjeffstatic inline uint64_t
92219820Sjeff__raw_readq(const volatile void *addr)
93219820Sjeff{
94339734Stijl	return (*(const volatile uint64_t *)addr);
95219820Sjeff}
96339734Stijl#define	__raw_readq(addr)	__raw_readq(addr)
97219820Sjeff
98219820Sjeffstatic inline void
99339734Stijl__raw_writeq(uint64_t v, volatile void *addr)
100219820Sjeff{
101339734Stijl	*(volatile uint64_t *)addr = v;
102219820Sjeff}
103339734Stijl#define	__raw_writeq(v, addr)	__raw_writeq(v, addr)
104339734Stijl#endif
105219820Sjeff
106299364Shselasky#define	mmiowb()	barrier()
107219820Sjeff
108339734Stijl/* Access little-endian MMIO registers atomically with memory barriers. */
109339734Stijl
110339734Stijl#undef readb
111339734Stijlstatic inline uint8_t
112339734Stijlreadb(const volatile void *addr)
113339734Stijl{
114339734Stijl	uint8_t v;
115339734Stijl
116339734Stijl	__compiler_membar();
117339734Stijl	v = *(const volatile uint8_t *)addr;
118339734Stijl	__compiler_membar();
119339734Stijl	return (v);
120339734Stijl}
121339734Stijl#define	readb(addr)		readb(addr)
122339734Stijl
123339734Stijl#undef writeb
124219820Sjeffstatic inline void
125339734Stijlwriteb(uint8_t v, volatile void *addr)
126219820Sjeff{
127339734Stijl	__compiler_membar();
128339734Stijl	*(volatile uint8_t *)addr = v;
129339734Stijl	__compiler_membar();
130219820Sjeff}
131339734Stijl#define	writeb(v, addr)		writeb(v, addr)
132219820Sjeff
133339734Stijl#undef readw
134339734Stijlstatic inline uint16_t
135339734Stijlreadw(const volatile void *addr)
136339734Stijl{
137339734Stijl	uint16_t v;
138339734Stijl
139339734Stijl	__compiler_membar();
140339734Stijl	v = *(const volatile uint16_t *)addr;
141339734Stijl	__compiler_membar();
142339734Stijl	return (v);
143339734Stijl}
144339734Stijl#define	readw(addr)		readw(addr)
145339734Stijl
146339734Stijl#undef writew
147330857Shselaskystatic inline void
148339734Stijlwritew(uint16_t v, volatile void *addr)
149330857Shselasky{
150339734Stijl	__compiler_membar();
151339734Stijl	*(volatile uint16_t *)addr = v;
152339734Stijl	__compiler_membar();
153330857Shselasky}
154339734Stijl#define	writew(v, addr)		writew(v, addr)
155330857Shselasky
156339734Stijl#undef readl
157339734Stijlstatic inline uint32_t
158339734Stijlreadl(const volatile void *addr)
159339734Stijl{
160339734Stijl	uint32_t v;
161339734Stijl
162339734Stijl	__compiler_membar();
163339734Stijl	v = *(const volatile uint32_t *)addr;
164339734Stijl	__compiler_membar();
165339734Stijl	return (v);
166339734Stijl}
167339734Stijl#define	readl(addr)		readl(addr)
168339734Stijl
169339734Stijl#undef writel
170339734Stijlstatic inline void
171339734Stijlwritel(uint32_t v, volatile void *addr)
172339734Stijl{
173339734Stijl	__compiler_membar();
174339734Stijl	*(volatile uint32_t *)addr = v;
175339734Stijl	__compiler_membar();
176339734Stijl}
177339734Stijl#define	writel(v, addr)		writel(v, addr)
178339734Stijl
179339734Stijl#undef readq
180219820Sjeff#undef writeq
181339734Stijl#ifdef __LP64__
182339734Stijlstatic inline uint64_t
183339734Stijlreadq(const volatile void *addr)
184339734Stijl{
185339734Stijl	uint64_t v;
186339734Stijl
187339734Stijl	__compiler_membar();
188339734Stijl	v = *(const volatile uint64_t *)addr;
189339734Stijl	__compiler_membar();
190339734Stijl	return (v);
191339734Stijl}
192339734Stijl#define	readq(addr)		readq(addr)
193339734Stijl
194219820Sjeffstatic inline void
195339734Stijlwriteq(uint64_t v, volatile void *addr)
196219820Sjeff{
197339734Stijl	__compiler_membar();
198339734Stijl	*(volatile uint64_t *)addr = v;
199339734Stijl	__compiler_membar();
200219820Sjeff}
201339734Stijl#define	writeq(v, addr)		writeq(v, addr)
202339734Stijl#endif
203219820Sjeff
204339734Stijl/* Access little-endian MMIO registers atomically without memory barriers. */
205339734Stijl
206339734Stijl#undef readb_relaxed
207339734Stijlstatic inline uint8_t
208339734Stijlreadb_relaxed(const volatile void *addr)
209339734Stijl{
210339734Stijl	return (*(const volatile uint8_t *)addr);
211339734Stijl}
212339734Stijl#define	readb_relaxed(addr)	readb_relaxed(addr)
213339734Stijl
214339734Stijl#undef writeb_relaxed
215219820Sjeffstatic inline void
216339734Stijlwriteb_relaxed(uint8_t v, volatile void *addr)
217219820Sjeff{
218339734Stijl	*(volatile uint8_t *)addr = v;
219219820Sjeff}
220339734Stijl#define	writeb_relaxed(v, addr)	writeb_relaxed(v, addr)
221219820Sjeff
222339734Stijl#undef readw_relaxed
223339734Stijlstatic inline uint16_t
224339734Stijlreadw_relaxed(const volatile void *addr)
225339734Stijl{
226339734Stijl	return (*(const volatile uint16_t *)addr);
227339734Stijl}
228339734Stijl#define	readw_relaxed(addr)	readw_relaxed(addr)
229339734Stijl
230339734Stijl#undef writew_relaxed
231219820Sjeffstatic inline void
232339734Stijlwritew_relaxed(uint16_t v, volatile void *addr)
233219820Sjeff{
234339734Stijl	*(volatile uint16_t *)addr = v;
235219820Sjeff}
236339734Stijl#define	writew_relaxed(v, addr)	writew_relaxed(v, addr)
237219820Sjeff
238339734Stijl#undef readl_relaxed
239339734Stijlstatic inline uint32_t
240339734Stijlreadl_relaxed(const volatile void *addr)
241339734Stijl{
242339734Stijl	return (*(const volatile uint32_t *)addr);
243339734Stijl}
244339734Stijl#define	readl_relaxed(addr)	readl_relaxed(addr)
245339734Stijl
246339734Stijl#undef writel_relaxed
247339734Stijlstatic inline void
248339734Stijlwritel_relaxed(uint32_t v, volatile void *addr)
249339734Stijl{
250339734Stijl	*(volatile uint32_t *)addr = v;
251339734Stijl}
252339734Stijl#define	writel_relaxed(v, addr)	writel_relaxed(v, addr)
253339734Stijl
254339734Stijl#undef readq_relaxed
255339734Stijl#undef writeq_relaxed
256339734Stijl#ifdef __LP64__
257339734Stijlstatic inline uint64_t
258339734Stijlreadq_relaxed(const volatile void *addr)
259339734Stijl{
260339734Stijl	return (*(const volatile uint64_t *)addr);
261339734Stijl}
262339734Stijl#define	readq_relaxed(addr)	readq_relaxed(addr)
263339734Stijl
264339734Stijlstatic inline void
265339734Stijlwriteq_relaxed(uint64_t v, volatile void *addr)
266339734Stijl{
267339734Stijl	*(volatile uint64_t *)addr = v;
268339734Stijl}
269339734Stijl#define	writeq_relaxed(v, addr)	writeq_relaxed(v, addr)
270339734Stijl#endif
271339734Stijl
272339734Stijl/* XXX On Linux ioread and iowrite handle both MMIO and port IO. */
273339734Stijl
274299364Shselasky#undef ioread8
275299364Shselaskystatic inline uint8_t
276299364Shselaskyioread8(const volatile void *addr)
277299364Shselasky{
278339734Stijl	return (readb(addr));
279299364Shselasky}
280339734Stijl#define	ioread8(addr)		ioread8(addr)
281299364Shselasky
282299364Shselasky#undef ioread16
283299364Shselaskystatic inline uint16_t
284299364Shselaskyioread16(const volatile void *addr)
285299364Shselasky{
286339734Stijl	return (readw(addr));
287299364Shselasky}
288339734Stijl#define	ioread16(addr)		ioread16(addr)
289299364Shselasky
290328653Shselasky#undef ioread16be
291328653Shselaskystatic inline uint16_t
292328653Shselaskyioread16be(const volatile void *addr)
293328653Shselasky{
294339734Stijl	return (bswap16(readw(addr)));
295328653Shselasky}
296339734Stijl#define	ioread16be(addr)	ioread16be(addr)
297328653Shselasky
298299364Shselasky#undef ioread32
299299364Shselaskystatic inline uint32_t
300299364Shselaskyioread32(const volatile void *addr)
301299364Shselasky{
302339734Stijl	return (readl(addr));
303299364Shselasky}
304339734Stijl#define	ioread32(addr)		ioread32(addr)
305299364Shselasky
306277396Shselasky#undef ioread32be
307277396Shselaskystatic inline uint32_t
308277396Shselaskyioread32be(const volatile void *addr)
309277396Shselasky{
310339734Stijl	return (bswap32(readl(addr)));
311277396Shselasky}
312339734Stijl#define	ioread32be(addr)	ioread32be(addr)
313277396Shselasky
314299364Shselasky#undef iowrite8
315299364Shselaskystatic inline void
316299364Shselaskyiowrite8(uint8_t v, volatile void *addr)
317299364Shselasky{
318339734Stijl	writeb(v, addr);
319299364Shselasky}
320339734Stijl#define	iowrite8(v, addr)	iowrite8(v, addr)
321299364Shselasky
322299364Shselasky#undef iowrite16
323299364Shselaskystatic inline void
324299364Shselaskyiowrite16(uint16_t v, volatile void *addr)
325299364Shselasky{
326339734Stijl	writew(v, addr);
327299364Shselasky}
328339734Stijl#define	iowrite16	iowrite16
329299364Shselasky
330299364Shselasky#undef iowrite32
331299364Shselaskystatic inline void
332299364Shselaskyiowrite32(uint32_t v, volatile void *addr)
333299364Shselasky{
334339734Stijl	writel(v, addr);
335299364Shselasky}
336339734Stijl#define	iowrite32(v, addr)	iowrite32(v, addr)
337299364Shselasky
338277396Shselasky#undef iowrite32be
339277396Shselaskystatic inline void
340277396Shselaskyiowrite32be(uint32_t v, volatile void *addr)
341277396Shselasky{
342339734Stijl	writel(bswap32(v), addr);
343277396Shselasky}
344339734Stijl#define	iowrite32be(v, addr)	iowrite32be(v, addr)
345277396Shselasky
346290706Shselasky#if defined(__i386__) || defined(__amd64__)
347300494Shselaskystatic inline void
348300494Shselasky_outb(u_char data, u_int port)
349300494Shselasky{
350300494Shselasky	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
351300494Shselasky}
352300494Shselasky#endif
353300494Shselasky
354328653Shselasky#if defined(__i386__) || defined(__amd64__) || defined(__powerpc__)
355219820Sjeffvoid *_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr);
356290706Shselasky#else
357290706Shselasky#define	_ioremap_attr(...) NULL
358290706Shselasky#endif
359290706Shselasky
360352330Shselasky#ifdef VM_MEMATTR_DEVICE
361219820Sjeff#define	ioremap_nocache(addr, size)					\
362352330Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_DEVICE)
363352330Shselasky#define	ioremap_wt(addr, size)						\
364352330Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_DEVICE)
365352330Shselasky#define	ioremap(addr, size)						\
366352330Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_DEVICE)
367352330Shselasky#else
368352330Shselasky#define	ioremap_nocache(addr, size)					\
369233547Sjhb    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
370352330Shselasky#define	ioremap_wt(addr, size)						\
371352330Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_THROUGH)
372352330Shselasky#define	ioremap(addr, size)						\
373352330Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
374352330Shselasky#endif
375219820Sjeff#define	ioremap_wc(addr, size)						\
376219820Sjeff    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_COMBINING)
377299364Shselasky#define	ioremap_wb(addr, size)						\
378299364Shselasky    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_BACK)
379219820Sjeffvoid iounmap(void *addr);
380219820Sjeff
381219820Sjeff#define	memset_io(a, b, c)	memset((a), (b), (c))
382219820Sjeff#define	memcpy_fromio(a, b, c)	memcpy((a), (b), (c))
383219820Sjeff#define	memcpy_toio(a, b, c)	memcpy((a), (b), (c))
384219820Sjeff
385219820Sjeffstatic inline void
386300594Skevlo__iowrite32_copy(void *to, void *from, size_t count)
387300594Skevlo{
388300594Skevlo	uint32_t *src;
389300594Skevlo	uint32_t *dst;
390300594Skevlo	int i;
391300594Skevlo
392300594Skevlo	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
393300594Skevlo		__raw_writel(*src, dst);
394300594Skevlo}
395300594Skevlo
396300594Skevlostatic inline void
397219820Sjeff__iowrite64_copy(void *to, void *from, size_t count)
398219820Sjeff{
399219820Sjeff#ifdef __LP64__
400219820Sjeff	uint64_t *src;
401219820Sjeff	uint64_t *dst;
402219820Sjeff	int i;
403219820Sjeff
404219820Sjeff	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
405219820Sjeff		__raw_writeq(*src, dst);
406219820Sjeff#else
407300594Skevlo	__iowrite32_copy(to, from, count * 2);
408219820Sjeff#endif
409219820Sjeff}
410219820Sjeff
411299364Shselaskyenum {
412299364Shselasky	MEMREMAP_WB = 1 << 0,
413299364Shselasky	MEMREMAP_WT = 1 << 1,
414299364Shselasky	MEMREMAP_WC = 1 << 2,
415299364Shselasky};
416219820Sjeff
417299364Shselaskystatic inline void *
418299364Shselaskymemremap(resource_size_t offset, size_t size, unsigned long flags)
419299364Shselasky{
420299364Shselasky	void *addr = NULL;
421299364Shselasky
422299364Shselasky	if ((flags & MEMREMAP_WB) &&
423299364Shselasky	    (addr = ioremap_wb(offset, size)) != NULL)
424299364Shselasky		goto done;
425299364Shselasky	if ((flags & MEMREMAP_WT) &&
426299379Shselasky	    (addr = ioremap_wt(offset, size)) != NULL)
427299364Shselasky		goto done;
428299364Shselasky	if ((flags & MEMREMAP_WC) &&
429299364Shselasky	    (addr = ioremap_wc(offset, size)) != NULL)
430299364Shselasky		goto done;
431299364Shselaskydone:
432299364Shselasky	return (addr);
433299364Shselasky}
434299364Shselasky
435299364Shselaskystatic inline void
436299364Shselaskymemunmap(void *addr)
437299364Shselasky{
438299364Shselasky	/* XXX May need to check if this is RAM */
439299364Shselasky	iounmap(addr);
440299364Shselasky}
441299364Shselasky
442219820Sjeff#endif	/* _LINUX_IO_H_ */
443