1 /* SPDX-License-Identifier: BSD-2-Clause */ 2 /* 3 * Copyright (c) 2014-2019, Linaro Limited 4 */ 5 #ifndef IO_H 6 #define IO_H 7 8 #include <compiler.h> 9 #include <stdint.h> 10 #include <types_ext.h> 11 #include <utee_defines.h> 12 13 /* 14 * Make sure that compiler reads/writes given variable only once. This is needed 15 * in cases when we have normal shared memory, and this memory can be changed 16 * at any moment. Compiler does not knows about this, so it can optimize memory 17 * access in any way, including repeated accesses from the same address. 18 * These macro enforce compiler to access memory only once. 19 */ 20 #define READ_ONCE(p) __compiler_atomic_load(&(p)) 21 #define WRITE_ONCE(p, v) __compiler_atomic_store(&(p), (v)) 22 23 static inline void io_write8(vaddr_t addr, uint8_t val) 24 { 25 *(volatile uint8_t *)addr = val; 26 } 27 28 static inline void io_write16(vaddr_t addr, uint16_t val) 29 { 30 *(volatile uint16_t *)addr = val; 31 } 32 33 static inline void io_write32(vaddr_t addr, uint32_t val) 34 { 35 *(volatile uint32_t *)addr = val; 36 } 37 38 static inline void io_write64(vaddr_t addr, uint64_t val) 39 { 40 *(volatile uint64_t *)addr = val; 41 } 42 43 static inline uint8_t io_read8(vaddr_t addr) 44 { 45 return *(volatile uint8_t *)addr; 46 } 47 48 static inline uint16_t io_read16(vaddr_t addr) 49 { 50 return *(volatile uint16_t *)addr; 51 } 52 53 static inline uint32_t io_read32(vaddr_t addr) 54 { 55 return *(volatile uint32_t *)addr; 56 } 57 58 static inline uint64_t io_read64(vaddr_t addr) 59 { 60 return *(volatile uint64_t *)addr; 61 } 62 63 static inline void io_mask8(vaddr_t addr, uint8_t val, uint8_t mask) 64 { 65 io_write8(addr, (io_read8(addr) & ~mask) | (val & mask)); 66 } 67 68 static inline void io_mask16(vaddr_t addr, uint16_t val, uint16_t mask) 69 { 70 io_write16(addr, (io_read16(addr) & ~mask) | (val & mask)); 71 } 72 73 static inline void io_mask32(vaddr_t addr, uint32_t val, uint32_t mask) 74 { 75 io_write32(addr, (io_read32(addr) & ~mask) | (val & mask)); 76 } 77 78 static inline uint64_t get_be64(const void *p) 79 { 80 return TEE_U64_FROM_BIG_ENDIAN(*(const uint64_t *)p); 81 } 82 83 static inline void put_be64(void *p, uint64_t val) 84 { 85 *(uint64_t *)p = TEE_U64_TO_BIG_ENDIAN(val); 86 } 87 88 static inline uint32_t get_be32(const void *p) 89 { 90 return TEE_U32_FROM_BIG_ENDIAN(*(const uint32_t *)p); 91 } 92 93 static inline void put_be32(void *p, uint32_t val) 94 { 95 *(uint32_t *)p = TEE_U32_TO_BIG_ENDIAN(val); 96 } 97 98 static inline uint16_t get_be16(const void *p) 99 { 100 return TEE_U16_FROM_BIG_ENDIAN(*(const uint16_t *)p); 101 } 102 103 static inline void put_be16(void *p, uint16_t val) 104 { 105 *(uint16_t *)p = TEE_U16_TO_BIG_ENDIAN(val); 106 } 107 108 static inline void put_le32(const void *p, uint32_t val) 109 { 110 *(uint32_t *)p = val; 111 } 112 113 static inline uint32_t get_le32(const void *p) 114 { 115 return *(const uint32_t *)p; 116 } 117 118 static inline void put_le64(const void *p, uint64_t val) 119 { 120 *(uint64_t *)p = val; 121 } 122 123 static inline uint64_t get_le64(const void *p) 124 { 125 return *(const uint64_t *)p; 126 } 127 128 /* Unaligned accesses */ 129 130 struct __unaligned_u16_t { uint16_t x; } __packed; 131 struct __unaligned_u32_t { uint32_t x; } __packed; 132 struct __unaligned_u64_t { uint64_t x; } __packed; 133 134 static inline uint64_t get_unaligned_be64(const void *p) 135 { 136 const struct __unaligned_u64_t *tmp = p; 137 138 return TEE_U64_FROM_BIG_ENDIAN(tmp->x); 139 } 140 141 static inline void put_unaligned_be64(void *p, uint64_t val) 142 { 143 struct __unaligned_u64_t *tmp = p; 144 145 tmp->x = TEE_U64_TO_BIG_ENDIAN(val); 146 } 147 148 static inline uint32_t get_unaligned_be32(const void *p) 149 { 150 const struct __unaligned_u32_t *tmp = p; 151 152 return TEE_U32_FROM_BIG_ENDIAN(tmp->x); 153 } 154 155 static inline void put_unaligned_be32(void *p, uint32_t val) 156 { 157 struct __unaligned_u32_t *tmp = p; 158 159 tmp->x = TEE_U32_TO_BIG_ENDIAN(val); 160 } 161 162 static inline uint16_t get_unaligned_be16(const void *p) 163 { 164 const struct __unaligned_u16_t *tmp = p; 165 166 return TEE_U16_FROM_BIG_ENDIAN(tmp->x); 167 } 168 169 static inline void put_unaligned_be16(void *p, uint16_t val) 170 { 171 struct __unaligned_u16_t *tmp = p; 172 173 tmp->x = TEE_U16_TO_BIG_ENDIAN(val); 174 } 175 176 static inline void put_unaligned_le64(void *p, uint64_t val) 177 { 178 struct __unaligned_u64_t *tmp = p; 179 180 tmp->x = val; 181 } 182 183 static inline uint64_t get_unaligned_le64(const void *p) 184 { 185 const struct __unaligned_u64_t *tmp = p; 186 187 return tmp->x; 188 } 189 190 static inline void put_unaligned_le32(void *p, uint32_t val) 191 { 192 struct __unaligned_u32_t *tmp = p; 193 194 tmp->x = val; 195 } 196 197 static inline uint32_t get_unaligned_le32(const void *p) 198 { 199 const struct __unaligned_u32_t *tmp = p; 200 201 return tmp->x; 202 } 203 204 static inline void put_unaligned_le16(void *p, uint16_t val) 205 { 206 struct __unaligned_u16_t *tmp = p; 207 208 tmp->x = val; 209 } 210 211 static inline uint16_t get_unaligned_le16(const void *p) 212 { 213 const struct __unaligned_u16_t *tmp = p; 214 215 return tmp->x; 216 } 217 218 /* 219 * Set and clear bits helpers. 220 * 221 * @addr is the address of the memory cell accessed 222 * @set_mask represents the bit mask of the bit(s) to set, aka set to 1 223 * @clear_mask represents the bit mask of the bit(s) to clear, aka reset to 0 224 * 225 * io_clrsetbits32() clears then sets the target bits in this order. If a bit 226 * position is defined by both @set_mask and @clear_mask, the bit will be set. 227 */ 228 static inline void io_setbits32(vaddr_t addr, uint32_t set_mask) 229 { 230 io_write32(addr, io_read32(addr) | set_mask); 231 } 232 233 static inline void io_clrbits32(vaddr_t addr, uint32_t clear_mask) 234 { 235 io_write32(addr, io_read32(addr) & ~clear_mask); 236 } 237 238 static inline void io_clrsetbits32(vaddr_t addr, uint32_t clear_mask, 239 uint32_t set_mask) 240 { 241 io_write32(addr, (io_read32(addr) & ~clear_mask) | set_mask); 242 } 243 244 static inline void io_setbits16(vaddr_t addr, uint16_t set_mask) 245 { 246 io_write16(addr, io_read16(addr) | set_mask); 247 } 248 249 static inline void io_clrbits16(vaddr_t addr, uint16_t clear_mask) 250 { 251 io_write16(addr, io_read16(addr) & ~clear_mask); 252 } 253 254 static inline void io_clrsetbits16(vaddr_t addr, uint16_t clear_mask, 255 uint16_t set_mask) 256 { 257 io_write16(addr, (io_read16(addr) & ~clear_mask) | set_mask); 258 } 259 260 static inline void io_setbits8(vaddr_t addr, uint8_t set_mask) 261 { 262 io_write8(addr, io_read8(addr) | set_mask); 263 } 264 265 static inline void io_clrbits8(vaddr_t addr, uint8_t clear_mask) 266 { 267 io_write8(addr, io_read8(addr) & ~clear_mask); 268 } 269 270 static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, 271 uint8_t set_mask) 272 { 273 io_write8(addr, (io_read8(addr) & ~clear_mask) | set_mask); 274 } 275 276 #endif /*IO_H*/ 277