blob: 2b9949e05a2cf5cbbe2ae1b66d3bb71ce34eaebf [file] [log] [blame]
Angel Pons32859fc2020-04-02 23:48:27 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Kyösti Mälkki13f66502019-03-03 08:01:05 +02002
3#ifndef __DEVICE_MMIO_H__
4#define __DEVICE_MMIO_H__
5
Elyes Haouas35c3ae3b2022-10-27 12:25:12 +02006#include <arch/mmio.h> /* IWYU pragma: export */
Yu-Ping Wu941db0e2021-07-23 16:17:11 +08007#include <commonlib/helpers.h>
Kyösti Mälkki3ee8b752019-03-03 00:35:15 +02008#include <endian.h>
Julius Wernerdb7f6fb2019-08-12 16:45:21 -07009#include <types.h>
Kyösti Mälkki13f66502019-03-03 08:01:05 +020010
Julius Werner1c371572019-12-02 18:02:51 -080011#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
Michael Niewöhnerdf8677c2022-06-20 21:32:56 +020029#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
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070044/*
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 */
50void 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 */
Julius Wernerea03d002021-09-16 15:53:32 -070060void buffer_to_fifo32_prefix(const void *buffer, u32 prefix, int prefsz, size_t size,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070061 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 */
Julius Wernerea03d002021-09-16 15:53:32 -070069static inline void buffer_to_fifo32(const void *buffer, size_t size, void *fifo,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070070 int fifo_stride, int fifo_width)
71{
Julius Werner9f19dd92019-11-18 18:21:27 -080072 buffer_to_fifo32_prefix(buffer, 0, 0, size, fifo,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070073 fifo_stride, fifo_width);
74}
Hung-Te Lin0962b1f2019-09-19 11:23:30 +080075
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 *
Hung-Te Lindafb6612019-10-04 14:48:46 +080087 * To define a field with a single bit:
88 *
89 * DEFINE_BIT(name, bit)
90 *
Hung-Te Lin0962b1f2019-09-19 11:23:30 +080091 * 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)
Hung-Te Lindafb6612019-10-04 14:48:46 +0800113 * DEFINE_BIT(DISP_EN, 0)
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800114 *
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 *
Julius Werner55009af2019-12-02 22:03:27 -0800126 * clrsetbits32(&disp_regs.ctrl, 0x6, 0x4);
127 * clrsetbits32(&disp_regs.ctrl, 0x1, 0x0);
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800128 *
Julius Werner55009af2019-12-02 22:03:27 -0800129 * clrsetbits32(&disp_regs.ctrl, 0x7, 0x3);
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800130 * 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
Hung-Te Lindafb6612019-10-04 14:48:46 +0800146#define DEFINE_BIT(name, bit) DEFINE_BITFIELD(name, bit, bit)
147
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800148#define _BF_MASK(name, value) \
Yu-Ping Wu941db0e2021-07-23 16:17:11 +0800149 ((u32)GENMASK(name##_BITFIELD_SHIFT + name##_BITFIELD_SIZE - 1, \
150 name##_BITFIELD_SHIFT))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800151
152#define _BF_VALUE(name, value) \
Hung-Te Lin85ecdb12020-04-15 20:54:14 +0800153 (((u32)(value) << name##_BITFIELD_SHIFT) & _BF_MASK(name, 0))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800154
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__))
Huayang Duan232d8a82020-06-23 12:25:24 +0800170#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__))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800186#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, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800191 n9, v9, n10, v10, n11, v11, n12, v12, n13, v13, n14, v14, n15, v15, n16, v16, \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800192 NARGS, ...) \
193 \
194 op(addr, \
195 _BF_APPLY##NARGS(_BF_MASK, n1, v1, n2, v2, n3, v3, n4, v4, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800196 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), \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800199 _BF_APPLY##NARGS(_BF_VALUE, n1, v1, n2, v2, n3, v3, n4, v4, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800200 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))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800203
204#define _BF_IMPL(op, addr, ...) \
205 _BF_IMPL2(op, addr, __VA_ARGS__, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800206 16, INVALID, 15, INVALID, 14, INVALID, 13, INVALID, \
207 12, INVALID, 11, INVALID, 10, INVALID, 9, INVALID, \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800208 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, ...) \
Julius Werner55009af2019-12-02 22:03:27 -0800217 _BF_IMPL(clrsetbits32, addr, __VA_ARGS__)
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800218
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
Jianjun Wang8565b94a2022-03-02 10:20:26 +0800225static __always_inline uint8_t read8p(const uintptr_t addr)
226{
227 return read8((void *)addr);
228}
229
230static __always_inline uint16_t read16p(const uintptr_t addr)
231{
232 return read16((void *)addr);
233}
234
235static __always_inline uint32_t read32p(const uintptr_t addr)
236{
237 return read32((void *)addr);
238}
239
240static __always_inline uint64_t read64p(const uintptr_t addr)
241{
242 return read64((void *)addr);
243}
244
245static __always_inline void write8p(const uintptr_t addr, const uint8_t value)
246{
247 write8((void *)addr, value);
248}
249
250static __always_inline void write16p(const uintptr_t addr, const uint16_t value)
251{
252 write16((void *)addr, value);
253}
254
255static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
256{
257 write32((void *)addr, value);
258}
259
260static __always_inline void write64p(const uintptr_t addr, const uint64_t value)
261{
262 write64((void *)addr, value);
263}
264
Julius Wernerdb7f6fb2019-08-12 16:45:21 -0700265#endif /* __DEVICE_MMIO_H__ */