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