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 /* 98 * Set and clear bits helpers. 99 * 100 * @addr is the address of the memory cell accessed 101 * @set_mask represents the bit mask of the bit(s) to set, aka set to 1 102 * @clear_mask represents the bit mask of the bit(s) to clear, aka reset to 0 103 * 104 * io_clrsetbits32() clears then sets the target bits in this order. If a bit 105 * position is defined by both @set_mask and @clear_mask, the bit will be set. 106 */ 107 static inline void io_setbits32(vaddr_t addr, uint32_t set_mask) 108 { 109 io_write32(addr, io_read32(addr) | set_mask); 110 } 111 112 static inline void io_clrbits32(vaddr_t addr, uint32_t clear_mask) 113 { 114 io_write32(addr, io_read32(addr) & ~clear_mask); 115 } 116 117 static inline void io_clrsetbits32(vaddr_t addr, uint32_t clear_mask, 118 uint32_t set_mask) 119 { 120 io_write32(addr, (io_read32(addr) & ~clear_mask) | set_mask); 121 } 122 123 static inline void io_setbits16(vaddr_t addr, uint16_t set_mask) 124 { 125 io_write16(addr, io_read16(addr) | set_mask); 126 } 127 128 static inline void io_clrbits16(vaddr_t addr, uint16_t clear_mask) 129 { 130 io_write16(addr, io_read16(addr) & ~clear_mask); 131 } 132 133 static inline void io_clrsetbits16(vaddr_t addr, uint16_t clear_mask, 134 uint16_t set_mask) 135 { 136 io_write16(addr, (io_read16(addr) & ~clear_mask) | set_mask); 137 } 138 139 static inline void io_setbits8(vaddr_t addr, uint8_t set_mask) 140 { 141 io_write8(addr, io_read8(addr) | set_mask); 142 } 143 144 static inline void io_clrbits8(vaddr_t addr, uint8_t clear_mask) 145 { 146 io_write8(addr, io_read8(addr) & ~clear_mask); 147 } 148 149 static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask, 150 uint8_t set_mask) 151 { 152 io_write8(addr, (io_read8(addr) & ~clear_mask) | set_mask); 153 } 154 155 #endif /*IO_H*/ 156