mmio.h
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #ifndef __DEVICE_MMIO_H__ 4 #define __DEVICE_MMIO_H__ 5 6 #include <arch/mmio.h> /* IWYU pragma: export */ 7 #include <commonlib/helpers.h> 8 #include <endian.h> 9 #include <types.h> 10 11 #define __clrsetbits_impl(bits, addr, clear, set) write##bits(addr, \ 12 (read##bits(addr) & ~((uint##bits##_t)(clear))) | (set)) 13 14 #define clrsetbits8(addr, clear, set) __clrsetbits_impl(8, addr, clear, set) 15 #define clrsetbits16(addr, clear, set) __clrsetbits_impl(16, addr, clear, set) 16 #define clrsetbits32(addr, clear, set) __clrsetbits_impl(32, addr, clear, set) 17 #define clrsetbits64(addr, clear, set) __clrsetbits_impl(64, addr, clear, set) 18 19 #define setbits8(addr, set) clrsetbits8(addr, 0, set) 20 #define setbits16(addr, set) clrsetbits16(addr, 0, set) 21 #define setbits32(addr, set) clrsetbits32(addr, 0, set) 22 #define setbits64(addr, set) clrsetbits64(addr, 0, set) 23 24 #define clrbits8(addr, clear) clrsetbits8(addr, clear, 0) 25 #define clrbits16(addr, clear) clrsetbits16(addr, clear, 0) 26 #define clrbits32(addr, clear) clrsetbits32(addr, clear, 0) 27 #define clrbits64(addr, clear) clrsetbits64(addr, clear, 0) 28 29 #define clrsetbits8p(addr, clear, set) clrsetbits8((void *)((uintptr_t)addr), clear, set) 30 #define clrsetbits16p(addr, clear, set) clrsetbits16((void *)((uintptr_t)addr), clear, set) 31 #define clrsetbits32p(addr, clear, set) clrsetbits32((void *)((uintptr_t)addr), clear, set) 32 #define clrsetbits64p(addr, clear, set) clrsetbits64((void *)((uintptr_t)addr), clear, set) 33 34 #define setbits8p(addr, set) clrsetbits8((void *)((uintptr_t)addr), 0, set) 35 #define setbits16p(addr, set) clrsetbits16((void *)((uintptr_t)addr), 0, set) 36 #define setbits32p(addr, set) clrsetbits32((void *)((uintptr_t)addr), 0, set) 37 #define setbits64p(addr, set) clrsetbits64((void *)((uintptr_t)addr), 0, set) 38 39 #define clrbits8p(addr, clear) clrsetbits8((void *)((uintptr_t)addr), clear, 0) 40 #define clrbits16p(addr, clear) clrsetbits16((void *)((uintptr_t)addr), clear, 0) 41 #define clrbits32p(addr, clear) clrsetbits32((void *)((uintptr_t)addr), clear, 0) 42 #define clrbits64p(addr, clear) clrsetbits64((void *)((uintptr_t)addr), clear, 0) 43 44 /* 45 * Reads a transfer buffer from 32-bit FIFO registers. fifo_stride is the 46 * distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit 47 * registers or 0 to read everything from the same register). fifo_width is 48 * the amount of bytes read per register (can be 1 through 4). 49 */ 50 void buffer_from_fifo32(void *buffer, size_t size, void *fifo, 51 int fifo_stride, int fifo_width); 52 53 /* 54 * Version of buffer_to_fifo32() that can prepend a prefix of up to fifo_width 55 * size to the transfer. This is often useful for protocols where a command word 56 * precedes the actual payload data. The prefix must be packed in the low-order 57 * bytes of the 'prefix' u32 parameter and any high-order bytes exceeding prefsz 58 * must be 0. Note that 'size' counts total bytes written, including 'prefsz'. 59 */ 60 void buffer_to_fifo32_prefix(const void *buffer, u32 prefix, int prefsz, size_t size, 61 void *fifo, int fifo_stride, int fifo_width); 62 63 /* 64 * Writes a transfer buffer into 32-bit FIFO registers. fifo_stride is the 65 * distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit 66 * registers or 0 to write everything into the same register). fifo_width is 67 * the amount of bytes written per register (can be 1 through 4). 68 */ 69 static inline void buffer_to_fifo32(const void *buffer, size_t size, void *fifo, 70 int fifo_stride, int fifo_width) 71 { 72 buffer_to_fifo32_prefix(buffer, 0, 0, size, fifo, 73 fifo_stride, fifo_width); 74 } 75 76 /* 77 * Utilities to help processing bit fields. 78 * 79 * To define a bit field (usually inside a register), do: 80 * 81 * DEFINE_BITFIELD(name, high_bit, low_bit) 82 * 83 * - name: Name of the field to access. 84 * - high_bit: highest bit that's part of the bit field. 85 * - low_bit: lowest bit in the bit field. 86 * 87 * To define a field with a single bit: 88 * 89 * DEFINE_BIT(name, bit) 90 * 91 * To extract one field value from a raw reg value: 92 * 93 * EXTRACT_BITFIELD(value, name); 94 * 95 * To read from an MMIO register and extract one field from it: 96 * 97 * READ32_BITFIELD(®, name); 98 * 99 * To write into an MMIO register, set given fields (by names) to specified 100 * values, and all other bits to zero (usually used for resetting a register): 101 * 102 * WRITE32_BITFIELDS(®, name, value, [name, value, ...]) 103 * 104 * To write into an MMIO register, set given fields (by names) to specified 105 * values, and leaving all others "unchanged" (usually used for updating some 106 * settings): 107 * 108 * SET32_BITFIELDS(®, name, value, [name, value, ...]) 109 * 110 * Examples: 111 * 112 * DEFINE_BITFIELD(DISP_TYPE, 2, 1) 113 * DEFINE_BIT(DISP_EN, 0) 114 * 115 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 2); 116 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_EN, 0); 117 * 118 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1); 119 * WRITE32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1); 120 * 121 * READ32_BITFIELD(®, DISP_TYPE) 122 * EXTRACT_BITFIELD(value, DISP_TYPE) 123 * 124 * These will be translated to: 125 * 126 * clrsetbits32(&disp_regs.ctrl, 0x6, 0x4); 127 * clrsetbits32(&disp_regs.ctrl, 0x1, 0x0); 128 * 129 * clrsetbits32(&disp_regs.ctrl, 0x7, 0x3); 130 * write32(&disp_regs.ctrl, 0x3); 131 * 132 * (read32(®) & 0x6) >> 1 133 * (value & 0x6) >> 1 134 * 135 * The {WRITE,SET}32_BITFIELDS currently only allows setting up to 8 fields at 136 * one invocation. 137 */ 138 139 #define DEFINE_BITFIELD(name, high_bit, low_bit) \ 140 _Static_assert(high_bit >= low_bit, "invalid bit field range"); \ 141 enum { \ 142 name##_BITFIELD_SHIFT = (low_bit), \ 143 name##_BITFIELD_SIZE = (high_bit) - (low_bit) + 1, \ 144 }; 145 146 #define DEFINE_BIT(name, bit) DEFINE_BITFIELD(name, bit, bit) 147 148 #define _BF_MASK(name, value) \ 149 ((u32)GENMASK(name##_BITFIELD_SHIFT + name##_BITFIELD_SIZE - 1, \ 150 name##_BITFIELD_SHIFT)) 151 152 #define _BF_VALUE(name, value) \ 153 (((u32)(value) << name##_BITFIELD_SHIFT) & _BF_MASK(name, 0)) 154 155 #define _BF_APPLY1(op, name, value, ...) (op(name, value)) 156 #define _BF_APPLY2(op, name, value, ...) ((op(name, value)) | \ 157 _BF_APPLY1(op, __VA_ARGS__)) 158 #define _BF_APPLY3(op, name, value, ...) ((op(name, value)) | \ 159 _BF_APPLY2(op, __VA_ARGS__)) 160 #define _BF_APPLY4(op, name, value, ...) ((op(name, value)) | \ 161 _BF_APPLY3(op, __VA_ARGS__)) 162 #define _BF_APPLY5(op, name, value, ...) ((op(name, value)) | \ 163 _BF_APPLY4(op, __VA_ARGS__)) 164 #define _BF_APPLY6(op, name, value, ...) ((op(name, value)) | \ 165 _BF_APPLY5(op, __VA_ARGS__)) 166 #define _BF_APPLY7(op, name, value, ...) ((op(name, value)) | \ 167 _BF_APPLY6(op, __VA_ARGS__)) 168 #define _BF_APPLY8(op, name, value, ...) ((op(name, value)) | \ 169 _BF_APPLY7(op, __VA_ARGS__)) 170 #define _BF_APPLY9(op, name, value, ...) ((op(name, value)) | \ 171 _BF_APPLY8(op, __VA_ARGS__)) 172 #define _BF_APPLY10(op, name, value, ...) ((op(name, value)) | \ 173 _BF_APPLY9(op, __VA_ARGS__)) 174 #define _BF_APPLY11(op, name, value, ...) ((op(name, value)) | \ 175 _BF_APPLY10(op, __VA_ARGS__)) 176 #define _BF_APPLY12(op, name, value, ...) ((op(name, value)) | \ 177 _BF_APPLY11(op, __VA_ARGS__)) 178 #define _BF_APPLY13(op, name, value, ...) ((op(name, value)) | \ 179 _BF_APPLY12(op, __VA_ARGS__)) 180 #define _BF_APPLY14(op, name, value, ...) ((op(name, value)) | \ 181 _BF_APPLY13(op, __VA_ARGS__)) 182 #define _BF_APPLY15(op, name, value, ...) ((op(name, value)) | \ 183 _BF_APPLY14(op, __VA_ARGS__)) 184 #define _BF_APPLY16(op, name, value, ...) ((op(name, value)) | \ 185 _BF_APPLY15(op, __VA_ARGS__)) 186 #define _BF_APPLYINVALID(...) \ 187 _Static_assert(0, "Invalid arguments for {WRITE,SET}*_BITFIELDS") 188 189 #define _BF_IMPL2(op, addr, \ 190 n1, v1, n2, v2, n3, v3, n4, v4, n5, v5, n6, v6, n7, v7, n8, v8, \ 191 n9, v9, n10, v10, n11, v11, n12, v12, n13, v13, n14, v14, n15, v15, n16, v16, \ 192 NARGS, ...) \ 193 \ 194 op(addr, \ 195 _BF_APPLY##NARGS(_BF_MASK, n1, v1, n2, v2, n3, v3, n4, v4, \ 196 n5, v5, n6, v6, n7, v7, n8, v8, \ 197 n9, v9, n10, v10, n11, v11, n12, v12, \ 198 n13, v13, n14, v14, n15, v15, n16, v16), \ 199 _BF_APPLY##NARGS(_BF_VALUE, n1, v1, n2, v2, n3, v3, n4, v4, \ 200 n5, v5, n6, v6, n7, v7, n8, v8,\ 201 n9, v9, n10, v10, n11, v11, n12, v12, \ 202 n13, v13, n14, v14, n15, v15, n16, v16)) 203 204 #define _BF_IMPL(op, addr, ...) \ 205 _BF_IMPL2(op, addr, __VA_ARGS__, \ 206 16, INVALID, 15, INVALID, 14, INVALID, 13, INVALID, \ 207 12, INVALID, 11, INVALID, 10, INVALID, 9, INVALID, \ 208 8, INVALID, 7, INVALID, 6, INVALID, 5, INVALID, \ 209 4, INVALID, 3, INVALID, 2, INVALID, 1, INVALID) 210 211 #define _WRITE32_BITFIELDS_IMPL(addr, masks, values) write32(addr, values) 212 213 #define WRITE32_BITFIELDS(addr, ...) \ 214 _BF_IMPL(_WRITE32_BITFIELDS_IMPL, addr, __VA_ARGS__) 215 216 #define SET32_BITFIELDS(addr, ...) \ 217 _BF_IMPL(clrsetbits32, addr, __VA_ARGS__) 218 219 #define EXTRACT_BITFIELD(value, name) \ 220 (((value) & _BF_MASK(name, 0)) >> name##_BITFIELD_SHIFT) 221 222 #define READ32_BITFIELD(addr, name) \ 223 EXTRACT_BITFIELD(read32(addr), name) 224 225 static __always_inline uint8_t read8p(const uintptr_t addr) 226 { 227 return read8((void *)addr); 228 } 229 230 static __always_inline uint16_t read16p(const uintptr_t addr) 231 { 232 return read16((void *)addr); 233 } 234 235 static __always_inline uint32_t read32p(const uintptr_t addr) 236 { 237 return read32((void *)addr); 238 } 239 240 static __always_inline uint64_t read64p(const uintptr_t addr) 241 { 242 return read64((void *)addr); 243 } 244 245 static __always_inline void write8p(const uintptr_t addr, const uint8_t value) 246 { 247 write8((void *)addr, value); 248 } 249 250 static __always_inline void write16p(const uintptr_t addr, const uint16_t value) 251 { 252 write16((void *)addr, value); 253 } 254 255 static __always_inline void write32p(const uintptr_t addr, const uint32_t value) 256 { 257 write32((void *)addr, value); 258 } 259 260 static __always_inline void write64p(const uintptr_t addr, const uint64_t value) 261 { 262 write64((void *)addr, value); 263 } 264 265 #endif /* __DEVICE_MMIO_H__ */