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 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 read from the same address. This macro 18 * enforces compiler to access memory only once. 19 */ 20 #define READ_ONCE(p) __compiler_atomic_load(&(p)) 21 22 static inline void io_write8(vaddr_t addr, uint8_t val) 23 { 24 *(volatile uint8_t *)addr = val; 25 } 26 27 static inline void io_write16(vaddr_t addr, uint16_t val) 28 { 29 *(volatile uint16_t *)addr = val; 30 } 31 32 static inline void io_write32(vaddr_t addr, uint32_t val) 33 { 34 *(volatile uint32_t *)addr = val; 35 } 36 37 static inline uint8_t io_read8(vaddr_t addr) 38 { 39 return *(volatile uint8_t *)addr; 40 } 41 42 static inline uint16_t io_read16(vaddr_t addr) 43 { 44 return *(volatile uint16_t *)addr; 45 } 46 47 static inline uint32_t io_read32(vaddr_t addr) 48 { 49 return *(volatile uint32_t *)addr; 50 } 51 52 static inline void io_mask8(vaddr_t addr, uint8_t val, uint8_t mask) 53 { 54 io_write8(addr, (io_read8(addr) & ~mask) | (val & mask)); 55 } 56 57 static inline void io_mask16(vaddr_t addr, uint16_t val, uint16_t mask) 58 { 59 io_write16(addr, (io_read16(addr) & ~mask) | (val & mask)); 60 } 61 62 static inline void io_mask32(vaddr_t addr, uint32_t val, uint32_t mask) 63 { 64 io_write32(addr, (io_read32(addr) & ~mask) | (val & mask)); 65 } 66 67 static inline uint64_t get_be64(const void *p) 68 { 69 return TEE_U64_FROM_BIG_ENDIAN(*(const uint64_t *)p); 70 } 71 72 static inline void put_be64(void *p, uint64_t val) 73 { 74 *(uint64_t *)p = TEE_U64_TO_BIG_ENDIAN(val); 75 } 76 77 static inline uint32_t get_be32(const void *p) 78 { 79 return TEE_U32_FROM_BIG_ENDIAN(*(const uint32_t *)p); 80 } 81 82 static inline void put_be32(void *p, uint32_t val) 83 { 84 *(uint32_t *)p = TEE_U32_TO_BIG_ENDIAN(val); 85 } 86 87 static inline uint16_t get_be16(const void *p) 88 { 89 return TEE_U16_FROM_BIG_ENDIAN(*(const uint16_t *)p); 90 } 91 92 static inline void put_be16(void *p, uint16_t val) 93 { 94 *(uint16_t *)p = TEE_U16_TO_BIG_ENDIAN(val); 95 } 96 97 static inline void put_le32(const void *p, uint32_t val) 98 { 99 *(uint32_t *)p = val; 100 } 101 102 static inline uint32_t get_le32(const void *p) 103 { 104 return *(const uint32_t *)p; 105 } 106 107 static inline void put_le64(const void *p, uint64_t val) 108 { 109 *(uint64_t *)p = val; 110 } 111 112 static inline uint64_t get_le64(const void *p) 113 { 114 return *(const uint64_t *)p; 115 } 116 117 /* 118 * Set and clear bits helpers. 119 * 120 * @addr is the address of the memory cell accessed 121 * @set_mask represents the bit mask of the bit(s) to set, aka set to 1 122 * @clear_mask represents the bit mask of the bit(s) to clear, aka reset to 0 123 * 124 * io_clrsetbits32() clears then sets the target bits in this order. If a bit 125 * position is defined by both @set_mask and @clear_mask, the bit will be set. 126 */ 127 static inline void io_setbits32(vaddr_t addr, uint32_t set_mask) 128 { 129 io_write32(addr, io_read32(addr) | set_mask); 130 } 131 132 static inline void io_clrbits32(vaddr_t addr, uint32_t clear_mask) 133 { 134 io_write32(addr, io_read32(addr) & ~clear_mask); 135 } 136 137 static inline void io_clrsetbits32(vaddr_t addr, uint32_t clear_mask, 138 uint32_t set_mask) 139 { 140 io_write32(addr, (io_read32(addr) & ~clear_mask) | set_mask); 141 } 142 143 static inline void io_setbits16(vaddr_t addr, uint16_t set_mask) 144 { 145 io_write16(addr, io_read16(addr) | set_mask); 146 } 147 148 static inline void io_clrbits16(vaddr_t addr, uint16_t clear_mask) 149 { 150 io_write16(addr, io_read16(addr) & ~clear_mask); 151 } 152 153 static inline void io_clrsetbits16(vaddr_t addr, uint16_t clear_mask, 154 uint16_t set_mask) 155 { 156 io_write16(addr, (io_read16(addr) & ~clear_mask) | set_mask); 157 } 158 159 static inline void io_setbits8(vaddr_t addr, uint8_t set_mask) 160 { 161 io_write8(addr, io_read8(addr) | set_mask); 162 } 163 164 static inline void io_clrbits8(vaddr_t addr, uint8_t clear_mask) 165 { 166 io_write8(addr, io_read8(addr) & ~clear_mask); 167 } 168 169 static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, 170 uint8_t set_mask) 171 { 172 io_write8(addr, (io_read8(addr) & ~clear_mask) | set_mask); 173 } 174 175 #endif /*IO_H*/ 176