1 /*
2 * Copyright (C) 2018-2022 Intel Corporation.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #ifndef IO_H
8 #define IO_H
9
10 #include <types.h>
11
12 /* X86 architecture only supports 16 bits IO space */
13 #define IO_SPACE_BITMASK 0xffffU
14
15 /* Write 1 byte to specified I/O port */
pio_write8(uint8_t value,uint16_t port)16 static inline void pio_write8(uint8_t value, uint16_t port)
17 {
18 asm volatile ("outb %0,%1"::"a" (value), "dN"(port));
19 }
20
21 /* Read 1 byte from specified I/O port */
pio_read8(uint16_t port)22 static inline uint8_t pio_read8(uint16_t port)
23 {
24 uint8_t value;
25
26 asm volatile ("inb %1,%0":"=a" (value):"dN"(port));
27 return value;
28 }
29
30 /* Write 2 bytes to specified I/O port */
pio_write16(uint16_t value,uint16_t port)31 static inline void pio_write16(uint16_t value, uint16_t port)
32 {
33 asm volatile ("outw %0,%1"::"a" (value), "dN"(port));
34 }
35
36 /* Read 2 bytes from specified I/O port */
pio_read16(uint16_t port)37 static inline uint16_t pio_read16(uint16_t port)
38 {
39 uint16_t value;
40
41 asm volatile ("inw %1,%0":"=a" (value):"dN"(port));
42 return value;
43 }
44
45 /* Write 4 bytes to specified I/O port */
pio_write32(uint32_t value,uint16_t port)46 static inline void pio_write32(uint32_t value, uint16_t port)
47 {
48 asm volatile ("outl %0,%1"::"a" (value), "dN"(port));
49 }
50
51 /* Read 4 bytes from specified I/O port */
pio_read32(uint16_t port)52 static inline uint32_t pio_read32(uint16_t port)
53 {
54 uint32_t value;
55
56 asm volatile ("inl %1,%0":"=a" (value):"dN"(port));
57 return value;
58 }
59
pio_write(uint32_t v,uint16_t addr,size_t sz)60 static inline void pio_write(uint32_t v, uint16_t addr, size_t sz)
61 {
62 if (sz == 1U) {
63 pio_write8((uint8_t)v, addr);
64 } else if (sz == 2U) {
65 pio_write16((uint16_t)v, addr);
66 } else {
67 pio_write32(v, addr);
68 }
69 }
70
pio_read(uint16_t addr,size_t sz)71 static inline uint32_t pio_read(uint16_t addr, size_t sz)
72 {
73 uint32_t ret;
74 if (sz == 1U) {
75 ret = pio_read8(addr);
76 } else if (sz == 2U) {
77 ret = pio_read16(addr);
78 } else {
79 ret = pio_read32(addr);
80 }
81 return ret;
82 }
83
84 /** Writes a 64 bit value to a memory mapped IO device.
85 *
86 * @param value The 64 bit value to write.
87 * @param addr The memory address to write to.
88 */
mmio_write64(uint64_t value,void * addr)89 static inline void mmio_write64(uint64_t value, void *addr)
90 {
91 volatile uint64_t *addr64 = (volatile uint64_t *)addr;
92 *addr64 = value;
93 }
94
95 /** Writes a 32 bit value to a memory mapped IO device.
96 *
97 * @param value The 32 bit value to write.
98 * @param addr The memory address to write to.
99 */
mmio_write32(uint32_t value,void * addr)100 static inline void mmio_write32(uint32_t value, void *addr)
101 {
102 volatile uint32_t *addr32 = (volatile uint32_t *)addr;
103 *addr32 = value;
104 }
105
106 /** Writes a 16 bit value to a memory mapped IO device.
107 *
108 * @param value The 16 bit value to write.
109 * @param addr The memory address to write to.
110 */
mmio_write16(uint16_t value,void * addr)111 static inline void mmio_write16(uint16_t value, void *addr)
112 {
113 volatile uint16_t *addr16 = (volatile uint16_t *)addr;
114 *addr16 = value;
115 }
116
117 /** Writes an 8 bit value to a memory mapped IO device.
118 *
119 * @param value The 8 bit value to write.
120 * @param addr The memory address to write to.
121 */
mmio_write8(uint8_t value,void * addr)122 static inline void mmio_write8(uint8_t value, void *addr)
123 {
124 volatile uint8_t *addr8 = (volatile uint8_t *)addr;
125 *addr8 = value;
126 }
127
128 /** Reads a 64 bit value from a memory mapped IO device.
129 *
130 * @param addr The memory address to read from.
131 *
132 * @return The 64 bit value read from the given address.
133 */
mmio_read64(const void * addr)134 static inline uint64_t mmio_read64(const void *addr)
135 {
136 return *((volatile const uint64_t *)addr);
137 }
138
139 /** Reads a 32 bit value from a memory mapped IO device.
140 *
141 * @param addr The memory address to read from.
142 *
143 * @return The 32 bit value read from the given address.
144 */
mmio_read32(const void * addr)145 static inline uint32_t mmio_read32(const void *addr)
146 {
147 return *((volatile const uint32_t *)addr);
148 }
149
150 /** Reads a 16 bit value from a memory mapped IO device.
151 *
152 * @param addr The memory address to read from.
153 *
154 * @return The 16 bit value read from the given address.
155 */
mmio_read16(const void * addr)156 static inline uint16_t mmio_read16(const void *addr)
157 {
158 return *((volatile const uint16_t *)addr);
159 }
160
161 /** Reads an 8 bit value from a memory mapped IO device.
162 *
163 * @param addr The memory address to read from.
164 *
165 * @return The 8 bit value read from the given address.
166 */
mmio_read8(const void * addr)167 static inline uint8_t mmio_read8(const void *addr)
168 {
169 return *((volatile const uint8_t *)addr);
170 }
171
mmio_read(const void * addr,uint64_t sz)172 static inline uint64_t mmio_read(const void *addr, uint64_t sz)
173 {
174 uint64_t val;
175 switch (sz) {
176 case 1U:
177 val = (uint64_t)mmio_read8(addr);
178 break;
179 case 2U:
180 val = (uint64_t)mmio_read16(addr);
181 break;
182 case 4U:
183 val = (uint64_t)mmio_read32(addr);
184 break;
185 default:
186 val = mmio_read64(addr);
187 break;
188 }
189 return val;
190 }
191
mmio_write(void * addr,uint64_t sz,uint64_t val)192 static inline void mmio_write(void *addr, uint64_t sz, uint64_t val)
193 {
194 switch (sz) {
195 case 1U:
196 mmio_write8((uint8_t)val, addr);
197 break;
198 case 2U:
199 mmio_write16((uint16_t)val, addr);
200 break;
201 case 4U:
202 mmio_write32((uint32_t)val, addr);
203 break;
204 default:
205 mmio_write64(val, addr);
206 break;
207 }
208 }
209
210 #endif /* _IO_H defined */
211