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