133965Sjdp/*-
278828Sobrien * Copyright (c) 2010 Isilon Systems, Inc.
3218822Sdim * Copyright (c) 2010 iX Systems, Inc.
433965Sjdp * Copyright (c) 2010 Panasas, Inc.
533965Sjdp * Copyright (c) 2013-2015 Mellanox Technologies, Ltd.
633965Sjdp * All rights reserved.
733965Sjdp *
833965Sjdp * Redistribution and use in source and binary forms, with or without
933965Sjdp * modification, are permitted provided that the following conditions
1033965Sjdp * are met:
1133965Sjdp * 1. Redistributions of source code must retain the above copyright
1233965Sjdp *    notice unmodified, this list of conditions, and the following
1333965Sjdp *    disclaimer.
1433965Sjdp * 2. Redistributions in binary form must reproduce the above copyright
1533965Sjdp *    notice, this list of conditions and the following disclaimer in the
1633965Sjdp *    documentation and/or other materials provided with the distribution.
1733965Sjdp *
1833965Sjdp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1933965Sjdp * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20218822Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21218822Sdim * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2233965Sjdp * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23130561Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24218822Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25218822Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26218822Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27218822Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2833965Sjdp *
29218822Sdim * $FreeBSD: releng/11.0/sys/compat/linuxkpi/common/include/linux/io.h 300594 2016-05-24 09:23:04Z kevlo $
3033965Sjdp */
3133965Sjdp#ifndef	_LINUX_IO_H_
3233965Sjdp#define	_LINUX_IO_H_
3333965Sjdp
3433965Sjdp#include <machine/vm.h>
3533965Sjdp#include <sys/endian.h>
3633965Sjdp#include <sys/types.h>
3760484Sobrien
3833965Sjdp#include <linux/compiler.h>
3933965Sjdp
4033965Sjdpstatic inline uint32_t
4133965Sjdp__raw_readl(const volatile void *addr)
4233965Sjdp{
4333965Sjdp	return *(const volatile uint32_t *)addr;
4433965Sjdp}
4533965Sjdp
46104834Sobrienstatic inline void
47104834Sobrien__raw_writel(uint32_t b, volatile void *addr)
48104834Sobrien{
4933965Sjdp	*(volatile uint32_t *)addr = b;
5060484Sobrien}
5177298Sobrien
5260484Sobrienstatic inline uint64_t
5360484Sobrien__raw_readq(const volatile void *addr)
5460484Sobrien{
5560484Sobrien	return *(const volatile uint64_t *)addr;
5660484Sobrien}
5733965Sjdp
5833965Sjdpstatic inline void
5933965Sjdp__raw_writeq(uint64_t b, volatile void *addr)
6033965Sjdp{
6133965Sjdp	*(volatile uint64_t *)addr = b;
6233965Sjdp}
6333965Sjdp
6433965Sjdp/*
6533965Sjdp * XXX This is all x86 specific.  It should be bus space access.
6633965Sjdp */
6733965Sjdp#define	mmiowb()	barrier()
6833965Sjdp
6933965Sjdp#undef writel
7033965Sjdpstatic inline void
7138889Sjdpwritel(uint32_t b, void *addr)
7238889Sjdp{
7338889Sjdp        *(volatile uint32_t *)addr = b;
7438889Sjdp}
7560484Sobrien
7660484Sobrien#undef writeq
7760484Sobrienstatic inline void
7838889Sjdpwriteq(uint64_t b, void *addr)
7938889Sjdp{
8089857Sobrien        *(volatile uint64_t *)addr = b;
8133965Sjdp}
8233965Sjdp
8333965Sjdp#undef writeb
8489857Sobrienstatic inline void
8533965Sjdpwriteb(uint8_t b, void *addr)
8633965Sjdp{
8733965Sjdp        *(volatile uint8_t *)addr = b;
8833965Sjdp}
89130561Sobrien
9033965Sjdp#undef writew
9133965Sjdpstatic inline void
9233965Sjdpwritew(uint16_t b, void *addr)
9377298Sobrien{
9433965Sjdp        *(volatile uint16_t *)addr = b;
9577298Sobrien}
96130561Sobrien
9733965Sjdp#undef ioread8
9833965Sjdpstatic inline uint8_t
9960484Sobrienioread8(const volatile void *addr)
10033965Sjdp{
10133965Sjdp	return *(const volatile uint8_t *)addr;
10233965Sjdp}
10338889Sjdp
10433965Sjdp#undef ioread16
10533965Sjdpstatic inline uint16_t
10633965Sjdpioread16(const volatile void *addr)
10760484Sobrien{
10860484Sobrien	return *(const volatile uint16_t *)addr;
10960484Sobrien}
11033965Sjdp
11160484Sobrien#undef ioread32
11233965Sjdpstatic inline uint32_t
11333965Sjdpioread32(const volatile void *addr)
11433965Sjdp{
11560484Sobrien	return *(const volatile uint32_t *)addr;
116130561Sobrien}
11733965Sjdp
11833965Sjdp#undef ioread32be
11933965Sjdpstatic inline uint32_t
12033965Sjdpioread32be(const volatile void *addr)
12133965Sjdp{
12233965Sjdp	return be32toh(*(const volatile uint32_t *)addr);
12333965Sjdp}
12433965Sjdp
12533965Sjdp#undef iowrite8
12633965Sjdpstatic inline void
12733965Sjdpiowrite8(uint8_t v, volatile void *addr)
12833965Sjdp{
12933965Sjdp	*(volatile uint8_t *)addr = v;
13033965Sjdp}
131130561Sobrien
13233965Sjdp#undef iowrite16
13360484Sobrienstatic inline void
13460484Sobrieniowrite16(uint16_t v, volatile void *addr)
13560484Sobrien{
13660484Sobrien	*(volatile uint16_t *)addr = v;
13760484Sobrien}
13860484Sobrien
13960484Sobrien#undef iowrite32
14060484Sobrienstatic inline void
14160484Sobrieniowrite32(uint32_t v, volatile void *addr)
14260484Sobrien{
14360484Sobrien	*(volatile uint32_t *)addr = v;
14460484Sobrien}
14560484Sobrien
14633965Sjdp#undef iowrite32be
14733965Sjdpstatic inline void
14833965Sjdpiowrite32be(uint32_t v, volatile void *addr)
14933965Sjdp{
15033965Sjdp	*(volatile uint32_t *)addr = htobe32(v);
151130561Sobrien}
15233965Sjdp
15333965Sjdp#undef readb
154130561Sobrienstatic inline uint8_t
15533965Sjdpreadb(const volatile void *addr)
15633965Sjdp{
157130561Sobrien	return *(const volatile uint8_t *)addr;
15833965Sjdp}
15989857Sobrien
16089857Sobrien#undef readw
16189857Sobrienstatic inline uint16_t
16289857Sobrienreadw(const volatile void *addr)
163130561Sobrien{
16489857Sobrien	return *(const volatile uint16_t *)addr;
16589857Sobrien}
16633965Sjdp
16733965Sjdp#undef readl
16833965Sjdpstatic inline uint32_t
169130561Sobrienreadl(const volatile void *addr)
17033965Sjdp{
17160484Sobrien	return *(const volatile uint32_t *)addr;
17233965Sjdp}
17333965Sjdp
17433965Sjdp#if defined(__i386__) || defined(__amd64__)
17533965Sjdpstatic inline void
17633965Sjdp_outb(u_char data, u_int port)
17733965Sjdp{
178130561Sobrien	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
17933965Sjdp}
18033965Sjdp#endif
18160484Sobrien
18238889Sjdp#if defined(__i386__) || defined(__amd64__)
18338889Sjdpvoid *_ioremap_attr(vm_paddr_t phys_addr, unsigned long size, int attr);
18438889Sjdp#else
18538889Sjdp#define	_ioremap_attr(...) NULL
18660484Sobrien#endif
18738889Sjdp
18838889Sjdp#define	ioremap_nocache(addr, size)					\
18960484Sobrien    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
190130561Sobrien#define	ioremap_wc(addr, size)						\
19160484Sobrien    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_COMBINING)
19260484Sobrien#define	ioremap_wb(addr, size)						\
193130561Sobrien    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_BACK)
19433965Sjdp#define	ioremap_wt(addr, size)						\
195130561Sobrien    _ioremap_attr((addr), (size), VM_MEMATTR_WRITE_THROUGH)
19633965Sjdp#define	ioremap(addr, size)						\
19733965Sjdp    _ioremap_attr((addr), (size), VM_MEMATTR_UNCACHEABLE)
19833965Sjdpvoid iounmap(void *addr);
19933965Sjdp
20033965Sjdp#define	memset_io(a, b, c)	memset((a), (b), (c))
20133965Sjdp#define	memcpy_fromio(a, b, c)	memcpy((a), (b), (c))
20233965Sjdp#define	memcpy_toio(a, b, c)	memcpy((a), (b), (c))
20360484Sobrien
20433965Sjdpstatic inline void
20533965Sjdp__iowrite32_copy(void *to, void *from, size_t count)
20633965Sjdp{
20733965Sjdp	uint32_t *src;
20833965Sjdp	uint32_t *dst;
20933965Sjdp	int i;
21033965Sjdp
21133965Sjdp	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
212130561Sobrien		__raw_writel(*src, dst);
213130561Sobrien}
21477298Sobrien
21577298Sobrienstatic inline void
21677298Sobrien__iowrite64_copy(void *to, void *from, size_t count)
21777298Sobrien{
21877298Sobrien#ifdef __LP64__
21977298Sobrien	uint64_t *src;
22077298Sobrien	uint64_t *dst;
22160484Sobrien	int i;
22277298Sobrien
22360484Sobrien	for (i = 0, src = from, dst = to; i < count; i++, src++, dst++)
22477298Sobrien		__raw_writeq(*src, dst);
22577298Sobrien#else
22660484Sobrien	__iowrite32_copy(to, from, count * 2);
22777298Sobrien#endif
22860484Sobrien}
22977298Sobrien
23033965Sjdpenum {
23133965Sjdp	MEMREMAP_WB = 1 << 0,
232130561Sobrien	MEMREMAP_WT = 1 << 1,
23333965Sjdp	MEMREMAP_WC = 1 << 2,
23433965Sjdp};
23533965Sjdp
23633965Sjdpstatic inline void *
23733965Sjdpmemremap(resource_size_t offset, size_t size, unsigned long flags)
23833965Sjdp{
23933965Sjdp	void *addr = NULL;
24033965Sjdp
24133965Sjdp	if ((flags & MEMREMAP_WB) &&
24260484Sobrien	    (addr = ioremap_wb(offset, size)) != NULL)
24360484Sobrien		goto done;
24460484Sobrien	if ((flags & MEMREMAP_WT) &&
24560484Sobrien	    (addr = ioremap_wt(offset, size)) != NULL)
24660484Sobrien		goto done;
24760484Sobrien	if ((flags & MEMREMAP_WC) &&
24860484Sobrien	    (addr = ioremap_wc(offset, size)) != NULL)
24960484Sobrien		goto done;
25060484Sobriendone:
25133965Sjdp	return (addr);
25260484Sobrien}
25333965Sjdp
25433965Sjdpstatic inline void
25560484Sobrienmemunmap(void *addr)
25660484Sobrien{
25760484Sobrien	/* XXX May need to check if this is RAM */
25833965Sjdp	iounmap(addr);
25977298Sobrien}
26033965Sjdp
26133965Sjdp#endif	/* _LINUX_IO_H_ */
26233965Sjdp