blob: 3c9a83363ffd17d5286afbea186f184eac9683b8 [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
Kyösti Mälkki3ee8b752019-03-03 00:35:15 +02006#include <arch/mmio.h>
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
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070029/*
30 * Reads a transfer buffer from 32-bit FIFO registers. fifo_stride is the
31 * distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit
32 * registers or 0 to read everything from the same register). fifo_width is
33 * the amount of bytes read per register (can be 1 through 4).
34 */
35void buffer_from_fifo32(void *buffer, size_t size, void *fifo,
36 int fifo_stride, int fifo_width);
37
38/*
39 * Version of buffer_to_fifo32() that can prepend a prefix of up to fifo_width
40 * size to the transfer. This is often useful for protocols where a command word
41 * precedes the actual payload data. The prefix must be packed in the low-order
42 * bytes of the 'prefix' u32 parameter and any high-order bytes exceeding prefsz
43 * must be 0. Note that 'size' counts total bytes written, including 'prefsz'.
44 */
Julius Wernerea03d002021-09-16 15:53:32 -070045void buffer_to_fifo32_prefix(const void *buffer, u32 prefix, int prefsz, size_t size,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070046 void *fifo, int fifo_stride, int fifo_width);
47
48/*
49 * Writes a transfer buffer into 32-bit FIFO registers. fifo_stride is the
50 * distance in bytes between registers (e.g. pass 4 for a normal array of 32-bit
51 * registers or 0 to write everything into the same register). fifo_width is
52 * the amount of bytes written per register (can be 1 through 4).
53 */
Julius Wernerea03d002021-09-16 15:53:32 -070054static inline void buffer_to_fifo32(const void *buffer, size_t size, void *fifo,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070055 int fifo_stride, int fifo_width)
56{
Julius Werner9f19dd92019-11-18 18:21:27 -080057 buffer_to_fifo32_prefix(buffer, 0, 0, size, fifo,
Julius Wernerdb7f6fb2019-08-12 16:45:21 -070058 fifo_stride, fifo_width);
59}
Hung-Te Lin0962b1f2019-09-19 11:23:30 +080060
61/*
62 * Utilities to help processing bit fields.
63 *
64 * To define a bit field (usually inside a register), do:
65 *
66 * DEFINE_BITFIELD(name, high_bit, low_bit)
67 *
68 * - name: Name of the field to access.
69 * - high_bit: highest bit that's part of the bit field.
70 * - low_bit: lowest bit in the bit field.
71 *
Hung-Te Lindafb6612019-10-04 14:48:46 +080072 * To define a field with a single bit:
73 *
74 * DEFINE_BIT(name, bit)
75 *
Hung-Te Lin0962b1f2019-09-19 11:23:30 +080076 * To extract one field value from a raw reg value:
77 *
78 * EXTRACT_BITFIELD(value, name);
79 *
80 * To read from an MMIO register and extract one field from it:
81 *
82 * READ32_BITFIELD(&reg, name);
83 *
84 * To write into an MMIO register, set given fields (by names) to specified
85 * values, and all other bits to zero (usually used for resetting a register):
86 *
87 * WRITE32_BITFIELDS(&reg, name, value, [name, value, ...])
88 *
89 * To write into an MMIO register, set given fields (by names) to specified
90 * values, and leaving all others "unchanged" (usually used for updating some
91 * settings):
92 *
93 * SET32_BITFIELDS(&reg, name, value, [name, value, ...])
94 *
95 * Examples:
96 *
97 * DEFINE_BITFIELD(DISP_TYPE, 2, 1)
Hung-Te Lindafb6612019-10-04 14:48:46 +080098 * DEFINE_BIT(DISP_EN, 0)
Hung-Te Lin0962b1f2019-09-19 11:23:30 +080099 *
100 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 2);
101 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_EN, 0);
102 *
103 * SET32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1);
104 * WRITE32_BITFIELDS(&disp_regs.ctrl, DISP_TYPE, 1, DISP_EN, 1);
105 *
106 * READ32_BITFIELD(&reg, DISP_TYPE)
107 * EXTRACT_BITFIELD(value, DISP_TYPE)
108 *
109 * These will be translated to:
110 *
Julius Werner55009af2019-12-02 22:03:27 -0800111 * clrsetbits32(&disp_regs.ctrl, 0x6, 0x4);
112 * clrsetbits32(&disp_regs.ctrl, 0x1, 0x0);
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800113 *
Julius Werner55009af2019-12-02 22:03:27 -0800114 * clrsetbits32(&disp_regs.ctrl, 0x7, 0x3);
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800115 * write32(&disp_regs.ctrl, 0x3);
116 *
117 * (read32(&reg) & 0x6) >> 1
118 * (value & 0x6) >> 1
119 *
120 * The {WRITE,SET}32_BITFIELDS currently only allows setting up to 8 fields at
121 * one invocation.
122 */
123
124#define DEFINE_BITFIELD(name, high_bit, low_bit) \
125 _Static_assert(high_bit >= low_bit, "invalid bit field range"); \
126 enum { \
127 name##_BITFIELD_SHIFT = (low_bit), \
128 name##_BITFIELD_SIZE = (high_bit) - (low_bit) + 1, \
129 };
130
Hung-Te Lindafb6612019-10-04 14:48:46 +0800131#define DEFINE_BIT(name, bit) DEFINE_BITFIELD(name, bit, bit)
132
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800133#define _BF_MASK(name, value) \
Yu-Ping Wu941db0e2021-07-23 16:17:11 +0800134 ((u32)GENMASK(name##_BITFIELD_SHIFT + name##_BITFIELD_SIZE - 1, \
135 name##_BITFIELD_SHIFT))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800136
137#define _BF_VALUE(name, value) \
Hung-Te Lin85ecdb12020-04-15 20:54:14 +0800138 (((u32)(value) << name##_BITFIELD_SHIFT) & _BF_MASK(name, 0))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800139
140#define _BF_APPLY1(op, name, value, ...) (op(name, value))
141#define _BF_APPLY2(op, name, value, ...) ((op(name, value)) | \
142 _BF_APPLY1(op, __VA_ARGS__))
143#define _BF_APPLY3(op, name, value, ...) ((op(name, value)) | \
144 _BF_APPLY2(op, __VA_ARGS__))
145#define _BF_APPLY4(op, name, value, ...) ((op(name, value)) | \
146 _BF_APPLY3(op, __VA_ARGS__))
147#define _BF_APPLY5(op, name, value, ...) ((op(name, value)) | \
148 _BF_APPLY4(op, __VA_ARGS__))
149#define _BF_APPLY6(op, name, value, ...) ((op(name, value)) | \
150 _BF_APPLY5(op, __VA_ARGS__))
151#define _BF_APPLY7(op, name, value, ...) ((op(name, value)) | \
152 _BF_APPLY6(op, __VA_ARGS__))
153#define _BF_APPLY8(op, name, value, ...) ((op(name, value)) | \
154 _BF_APPLY7(op, __VA_ARGS__))
Huayang Duan232d8a82020-06-23 12:25:24 +0800155#define _BF_APPLY9(op, name, value, ...) ((op(name, value)) | \
156 _BF_APPLY8(op, __VA_ARGS__))
157#define _BF_APPLY10(op, name, value, ...) ((op(name, value)) | \
158 _BF_APPLY9(op, __VA_ARGS__))
159#define _BF_APPLY11(op, name, value, ...) ((op(name, value)) | \
160 _BF_APPLY10(op, __VA_ARGS__))
161#define _BF_APPLY12(op, name, value, ...) ((op(name, value)) | \
162 _BF_APPLY11(op, __VA_ARGS__))
163#define _BF_APPLY13(op, name, value, ...) ((op(name, value)) | \
164 _BF_APPLY12(op, __VA_ARGS__))
165#define _BF_APPLY14(op, name, value, ...) ((op(name, value)) | \
166 _BF_APPLY13(op, __VA_ARGS__))
167#define _BF_APPLY15(op, name, value, ...) ((op(name, value)) | \
168 _BF_APPLY14(op, __VA_ARGS__))
169#define _BF_APPLY16(op, name, value, ...) ((op(name, value)) | \
170 _BF_APPLY15(op, __VA_ARGS__))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800171#define _BF_APPLYINVALID(...) \
172 _Static_assert(0, "Invalid arguments for {WRITE,SET}*_BITFIELDS")
173
174#define _BF_IMPL2(op, addr, \
175 n1, v1, n2, v2, n3, v3, n4, v4, n5, v5, n6, v6, n7, v7, n8, v8, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800176 n9, v9, n10, v10, n11, v11, n12, v12, n13, v13, n14, v14, n15, v15, n16, v16, \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800177 NARGS, ...) \
178 \
179 op(addr, \
180 _BF_APPLY##NARGS(_BF_MASK, n1, v1, n2, v2, n3, v3, n4, v4, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800181 n5, v5, n6, v6, n7, v7, n8, v8, \
182 n9, v9, n10, v10, n11, v11, n12, v12, \
183 n13, v13, n14, v14, n15, v15, n16, v16), \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800184 _BF_APPLY##NARGS(_BF_VALUE, n1, v1, n2, v2, n3, v3, n4, v4, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800185 n5, v5, n6, v6, n7, v7, n8, v8,\
186 n9, v9, n10, v10, n11, v11, n12, v12, \
187 n13, v13, n14, v14, n15, v15, n16, v16))
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800188
189#define _BF_IMPL(op, addr, ...) \
190 _BF_IMPL2(op, addr, __VA_ARGS__, \
Huayang Duan232d8a82020-06-23 12:25:24 +0800191 16, INVALID, 15, INVALID, 14, INVALID, 13, INVALID, \
192 12, INVALID, 11, INVALID, 10, INVALID, 9, INVALID, \
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800193 8, INVALID, 7, INVALID, 6, INVALID, 5, INVALID, \
194 4, INVALID, 3, INVALID, 2, INVALID, 1, INVALID)
195
196#define _WRITE32_BITFIELDS_IMPL(addr, masks, values) write32(addr, values)
197
198#define WRITE32_BITFIELDS(addr, ...) \
199 _BF_IMPL(_WRITE32_BITFIELDS_IMPL, addr, __VA_ARGS__)
200
201#define SET32_BITFIELDS(addr, ...) \
Julius Werner55009af2019-12-02 22:03:27 -0800202 _BF_IMPL(clrsetbits32, addr, __VA_ARGS__)
Hung-Te Lin0962b1f2019-09-19 11:23:30 +0800203
204#define EXTRACT_BITFIELD(value, name) \
205 (((value) & _BF_MASK(name, 0)) >> name##_BITFIELD_SHIFT)
206
207#define READ32_BITFIELD(addr, name) \
208 EXTRACT_BITFIELD(read32(addr), name)
209
Julius Wernerdb7f6fb2019-08-12 16:45:21 -0700210#endif /* __DEVICE_MMIO_H__ */