xref: /aosp_15_r20/external/coreboot/src/include/device/mmio.h (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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  */
buffer_to_fifo32(const void * buffer,size_t size,void * fifo,int fifo_stride,int fifo_width)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(&reg, 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(&reg, 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(&reg, 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(&reg, 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(&reg) & 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 
read8p(const uintptr_t addr)225 static __always_inline uint8_t read8p(const uintptr_t addr)
226 {
227 	return read8((void *)addr);
228 }
229 
read16p(const uintptr_t addr)230 static __always_inline uint16_t read16p(const uintptr_t addr)
231 {
232 	return read16((void *)addr);
233 }
234 
read32p(const uintptr_t addr)235 static __always_inline uint32_t read32p(const uintptr_t addr)
236 {
237 	return read32((void *)addr);
238 }
239 
read64p(const uintptr_t addr)240 static __always_inline uint64_t read64p(const uintptr_t addr)
241 {
242 	return read64((void *)addr);
243 }
244 
write8p(const uintptr_t addr,const uint8_t value)245 static __always_inline void write8p(const uintptr_t addr, const uint8_t value)
246 {
247 	write8((void *)addr, value);
248 }
249 
write16p(const uintptr_t addr,const uint16_t value)250 static __always_inline void write16p(const uintptr_t addr, const uint16_t value)
251 {
252 	write16((void *)addr, value);
253 }
254 
write32p(const uintptr_t addr,const uint32_t value)255 static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
256 {
257 	write32((void *)addr, value);
258 }
259 
write64p(const uintptr_t addr,const uint64_t value)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__ */
266