linux/arch/riscv/include/asm/io.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * {read,write}{b,w,l,q} based on arch/arm64/include/asm/io.h
   4 *   which was based on arch/arm/include/io.h
   5 *
   6 * Copyright (C) 1996-2000 Russell King
   7 * Copyright (C) 2012 ARM Ltd.
   8 * Copyright (C) 2014 Regents of the University of California
   9 */
  10
  11#ifndef _ASM_RISCV_IO_H
  12#define _ASM_RISCV_IO_H
  13
  14#include <linux/types.h>
  15#include <linux/pgtable.h>
  16#include <asm/mmiowb.h>
  17#include <asm/early_ioremap.h>
  18
  19/*
  20 * MMIO access functions are separated out to break dependency cycles
  21 * when using {read,write}* fns in low-level headers
  22 */
  23#include <asm/mmio.h>
  24
  25/*
  26 *  I/O port access constants.
  27 */
  28#ifdef CONFIG_MMU
  29#define IO_SPACE_LIMIT          (PCI_IO_SIZE - 1)
  30#define PCI_IOBASE              ((void __iomem *)PCI_IO_START)
  31#endif /* CONFIG_MMU */
  32
  33/*
  34 * Emulation routines for the port-mapped IO space used by some PCI drivers.
  35 * These are defined as being "fully synchronous", but also "not guaranteed to
  36 * be fully ordered with respect to other memory and I/O operations".  We're
  37 * going to be on the safe side here and just make them:
  38 *  - Fully ordered WRT each other, by bracketing them with two fences.  The
  39 *    outer set contains both I/O so inX is ordered with outX, while the inner just
  40 *    needs the type of the access (I for inX and O for outX).
  41 *  - Ordered in the same manner as readX/writeX WRT memory by subsuming their
  42 *    fences.
  43 *  - Ordered WRT timer reads, so udelay and friends don't get elided by the
  44 *    implementation.
  45 * Note that there is no way to actually enforce that outX is a non-posted
  46 * operation on RISC-V, but hopefully the timer ordering constraint is
  47 * sufficient to ensure this works sanely on controllers that support I/O
  48 * writes.
  49 */
  50#define __io_pbr()      __asm__ __volatile__ ("fence io,i"  : : : "memory");
  51#define __io_par(v)     __asm__ __volatile__ ("fence i,ior" : : : "memory");
  52#define __io_pbw()      __asm__ __volatile__ ("fence iow,o" : : : "memory");
  53#define __io_paw()      __asm__ __volatile__ ("fence o,io"  : : : "memory");
  54
  55#define inb(c)          ({ u8  __v; __io_pbr(); __v = readb_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
  56#define inw(c)          ({ u16 __v; __io_pbr(); __v = readw_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
  57#define inl(c)          ({ u32 __v; __io_pbr(); __v = readl_cpu((void*)(PCI_IOBASE + (c))); __io_par(__v); __v; })
  58
  59#define outb(v,c)       ({ __io_pbw(); writeb_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
  60#define outw(v,c)       ({ __io_pbw(); writew_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
  61#define outl(v,c)       ({ __io_pbw(); writel_cpu((v),(void*)(PCI_IOBASE + (c))); __io_paw(); })
  62
  63#ifdef CONFIG_64BIT
  64#define inq(c)          ({ u64 __v; __io_pbr(); __v = readq_cpu((void*)(c)); __io_par(__v); __v; })
  65#define outq(v,c)       ({ __io_pbw(); writeq_cpu((v),(void*)(c)); __io_paw(); })
  66#endif
  67
  68/*
  69 * Accesses from a single hart to a single I/O address must be ordered.  This
  70 * allows us to use the raw read macros, but we still need to fence before and
  71 * after the block to ensure ordering WRT other macros.  These are defined to
  72 * perform host-endian accesses so we use __raw instead of __cpu.
  73 */
  74#define __io_reads_ins(port, ctype, len, bfence, afence)                        \
  75        static inline void __ ## port ## len(const volatile void __iomem *addr, \
  76                                             void *buffer,                      \
  77                                             unsigned int count)                \
  78        {                                                                       \
  79                bfence;                                                         \
  80                if (count) {                                                    \
  81                        ctype *buf = buffer;                                    \
  82                                                                                \
  83                        do {                                                    \
  84                                ctype x = __raw_read ## len(addr);              \
  85                                *buf++ = x;                                     \
  86                        } while (--count);                                      \
  87                }                                                               \
  88                afence;                                                         \
  89        }
  90
  91#define __io_writes_outs(port, ctype, len, bfence, afence)                      \
  92        static inline void __ ## port ## len(volatile void __iomem *addr,       \
  93                                             const void *buffer,                \
  94                                             unsigned int count)                \
  95        {                                                                       \
  96                bfence;                                                         \
  97                if (count) {                                                    \
  98                        const ctype *buf = buffer;                              \
  99                                                                                \
 100                        do {                                                    \
 101                                __raw_write ## len(*buf++, addr);               \
 102                        } while (--count);                                      \
 103                }                                                               \
 104                afence;                                                         \
 105        }
 106
 107__io_reads_ins(reads,  u8, b, __io_br(), __io_ar(addr))
 108__io_reads_ins(reads, u16, w, __io_br(), __io_ar(addr))
 109__io_reads_ins(reads, u32, l, __io_br(), __io_ar(addr))
 110#define readsb(addr, buffer, count) __readsb(addr, buffer, count)
 111#define readsw(addr, buffer, count) __readsw(addr, buffer, count)
 112#define readsl(addr, buffer, count) __readsl(addr, buffer, count)
 113
 114__io_reads_ins(ins,  u8, b, __io_pbr(), __io_par(addr))
 115__io_reads_ins(ins, u16, w, __io_pbr(), __io_par(addr))
 116__io_reads_ins(ins, u32, l, __io_pbr(), __io_par(addr))
 117#define insb(addr, buffer, count) __insb((void __iomem *)(long)addr, buffer, count)
 118#define insw(addr, buffer, count) __insw((void __iomem *)(long)addr, buffer, count)
 119#define insl(addr, buffer, count) __insl((void __iomem *)(long)addr, buffer, count)
 120
 121__io_writes_outs(writes,  u8, b, __io_bw(), __io_aw())
 122__io_writes_outs(writes, u16, w, __io_bw(), __io_aw())
 123__io_writes_outs(writes, u32, l, __io_bw(), __io_aw())
 124#define writesb(addr, buffer, count) __writesb(addr, buffer, count)
 125#define writesw(addr, buffer, count) __writesw(addr, buffer, count)
 126#define writesl(addr, buffer, count) __writesl(addr, buffer, count)
 127
 128__io_writes_outs(outs,  u8, b, __io_pbw(), __io_paw())
 129__io_writes_outs(outs, u16, w, __io_pbw(), __io_paw())
 130__io_writes_outs(outs, u32, l, __io_pbw(), __io_paw())
 131#define outsb(addr, buffer, count) __outsb((void __iomem *)(long)addr, buffer, count)
 132#define outsw(addr, buffer, count) __outsw((void __iomem *)(long)addr, buffer, count)
 133#define outsl(addr, buffer, count) __outsl((void __iomem *)(long)addr, buffer, count)
 134
 135#ifdef CONFIG_64BIT
 136__io_reads_ins(reads, u64, q, __io_br(), __io_ar(addr))
 137#define readsq(addr, buffer, count) __readsq(addr, buffer, count)
 138
 139__io_reads_ins(ins, u64, q, __io_pbr(), __io_par(addr))
 140#define insq(addr, buffer, count) __insq((void __iomem *)addr, buffer, count)
 141
 142__io_writes_outs(writes, u64, q, __io_bw(), __io_aw())
 143#define writesq(addr, buffer, count) __writesq(addr, buffer, count)
 144
 145__io_writes_outs(outs, u64, q, __io_pbr(), __io_paw())
 146#define outsq(addr, buffer, count) __outsq((void __iomem *)addr, buffer, count)
 147#endif
 148
 149#include <asm-generic/io.h>
 150
 151#endif /* _ASM_RISCV_IO_H */
 152