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