1 /*
2  * Copyright 2016 Advanced Micro Devices, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Authors: AMD
23  */
24 
25 #ifndef DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
26 #define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
27 
28 #include "dm_services.h"
29 
30 /* macro for register read/write
31  * user of macro need to define
32  *
33  * CTX ==> macro to ptr to dc_context
34  *    eg. aud110->base.ctx
35  *
36  * REG ==> macro to location of register offset
37  *    eg. aud110->regs->reg
38  */
39 #define REG_READ(reg_name) \
40 		dm_read_reg(CTX, REG(reg_name))
41 
42 #define REG_WRITE(reg_name, value) \
43 		dm_write_reg(CTX, REG(reg_name), value)
44 
45 #ifdef REG_SET
46 #undef REG_SET
47 #endif
48 
49 #ifdef REG_GET
50 #undef REG_GET
51 #endif
52 
53 /* macro to set register fields. */
54 #define REG_SET_N(reg_name, n, initial_val, ...)	\
55 		generic_reg_set_ex(CTX, \
56 				REG(reg_name), \
57 				initial_val, \
58 				n, __VA_ARGS__)
59 
60 #define FN(reg_name, field) \
61 	FD(reg_name##__##field)
62 
63 #define REG_SET(reg_name, initial_val, field, val)	\
64 		REG_SET_N(reg_name, 1, initial_val, \
65 				FN(reg_name, field), val)
66 
67 #define REG_SET_2(reg, init_value, f1, v1, f2, v2)	\
68 		REG_SET_N(reg, 2, init_value, \
69 				FN(reg, f1), v1,\
70 				FN(reg, f2), v2)
71 
72 #define REG_SET_3(reg, init_value, f1, v1, f2, v2, f3, v3)	\
73 		REG_SET_N(reg, 3, init_value, \
74 				FN(reg, f1), v1,\
75 				FN(reg, f2), v2,\
76 				FN(reg, f3), v3)
77 
78 #define REG_SET_4(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4)	\
79 		REG_SET_N(reg, 4, init_value, \
80 				FN(reg, f1), v1,\
81 				FN(reg, f2), v2,\
82 				FN(reg, f3), v3,\
83 				FN(reg, f4), v4)
84 
85 #define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
86 		f5, v5)	\
87 		REG_SET_N(reg, 5, init_value, \
88 				FN(reg, f1), v1,\
89 				FN(reg, f2), v2,\
90 				FN(reg, f3), v3,\
91 				FN(reg, f4), v4,\
92 				FN(reg, f5), v5)
93 
94 #define REG_SET_6(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
95 		f5, v5, f6, v6)	\
96 		REG_SET_N(reg, 6, init_value, \
97 				FN(reg, f1), v1,\
98 				FN(reg, f2), v2,\
99 				FN(reg, f3), v3,\
100 				FN(reg, f4), v4,\
101 				FN(reg, f5), v5,\
102 				FN(reg, f6), v6)
103 
104 #define REG_SET_7(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
105 		f5, v5, f6, v6, f7, v7)	\
106 		REG_SET_N(reg, 7, init_value, \
107 				FN(reg, f1), v1,\
108 				FN(reg, f2), v2,\
109 				FN(reg, f3), v3,\
110 				FN(reg, f4), v4,\
111 				FN(reg, f5), v5,\
112 				FN(reg, f6), v6,\
113 				FN(reg, f7), v7)
114 
115 #define REG_SET_8(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
116 		f5, v5, f6, v6, f7, v7, f8, v8)	\
117 		REG_SET_N(reg, 8, init_value, \
118 				FN(reg, f1), v1,\
119 				FN(reg, f2), v2,\
120 				FN(reg, f3), v3,\
121 				FN(reg, f4), v4,\
122 				FN(reg, f5), v5,\
123 				FN(reg, f6), v6,\
124 				FN(reg, f7), v7,\
125 				FN(reg, f8), v8)
126 
127 #define REG_SET_9(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \
128 		v5, f6, v6, f7, v7, f8, v8, f9, v9)	\
129 		REG_SET_N(reg, 9, init_value, \
130 				FN(reg, f1), v1,\
131 				FN(reg, f2), v2, \
132 				FN(reg, f3), v3, \
133 				FN(reg, f4), v4, \
134 				FN(reg, f5), v5, \
135 				FN(reg, f6), v6, \
136 				FN(reg, f7), v7, \
137 				FN(reg, f8), v8, \
138 				FN(reg, f9), v9)
139 
140 #define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \
141 		v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)	\
142 		REG_SET_N(reg, 10, init_value, \
143 				FN(reg, f1), v1,\
144 				FN(reg, f2), v2, \
145 				FN(reg, f3), v3, \
146 				FN(reg, f4), v4, \
147 				FN(reg, f5), v5, \
148 				FN(reg, f6), v6, \
149 				FN(reg, f7), v7, \
150 				FN(reg, f8), v8, \
151 				FN(reg, f9), v9, \
152 				FN(reg, f10), v10)
153 
154 /* macro to get register fields
155  * read given register and fill in field value in output parameter */
156 #define REG_GET(reg_name, field, val)	\
157 		generic_reg_get(CTX, REG(reg_name), \
158 				FN(reg_name, field), val)
159 
160 #define REG_GET_2(reg_name, f1, v1, f2, v2)	\
161 		generic_reg_get2(CTX, REG(reg_name), \
162 				FN(reg_name, f1), v1, \
163 				FN(reg_name, f2), v2)
164 
165 #define REG_GET_3(reg_name, f1, v1, f2, v2, f3, v3)	\
166 		generic_reg_get3(CTX, REG(reg_name), \
167 				FN(reg_name, f1), v1, \
168 				FN(reg_name, f2), v2, \
169 				FN(reg_name, f3), v3)
170 
171 #define REG_GET_4(reg_name, f1, v1, f2, v2, f3, v3, f4, v4)	\
172 		generic_reg_get4(CTX, REG(reg_name), \
173 				FN(reg_name, f1), v1, \
174 				FN(reg_name, f2), v2, \
175 				FN(reg_name, f3), v3, \
176 				FN(reg_name, f4), v4)
177 
178 #define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5)	\
179 		generic_reg_get5(CTX, REG(reg_name), \
180 				FN(reg_name, f1), v1, \
181 				FN(reg_name, f2), v2, \
182 				FN(reg_name, f3), v3, \
183 				FN(reg_name, f4), v4, \
184 				FN(reg_name, f5), v5)
185 
186 #define REG_GET_6(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6)	\
187 		generic_reg_get6(CTX, REG(reg_name), \
188 				FN(reg_name, f1), v1, \
189 				FN(reg_name, f2), v2, \
190 				FN(reg_name, f3), v3, \
191 				FN(reg_name, f4), v4, \
192 				FN(reg_name, f5), v5, \
193 				FN(reg_name, f6), v6)
194 
195 #define REG_GET_7(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7)	\
196 		generic_reg_get7(CTX, REG(reg_name), \
197 				FN(reg_name, f1), v1, \
198 				FN(reg_name, f2), v2, \
199 				FN(reg_name, f3), v3, \
200 				FN(reg_name, f4), v4, \
201 				FN(reg_name, f5), v5, \
202 				FN(reg_name, f6), v6, \
203 				FN(reg_name, f7), v7)
204 
205 #define REG_GET_8(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8)	\
206 		generic_reg_get8(CTX, REG(reg_name), \
207 				FN(reg_name, f1), v1, \
208 				FN(reg_name, f2), v2, \
209 				FN(reg_name, f3), v3, \
210 				FN(reg_name, f4), v4, \
211 				FN(reg_name, f5), v5, \
212 				FN(reg_name, f6), v6, \
213 				FN(reg_name, f7), v7, \
214 				FN(reg_name, f8), v8)
215 
216 /* macro to poll and wait for a register field to read back given value */
217 
218 #define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try)	\
219 		generic_reg_wait(CTX, \
220 				REG(reg_name), FN(reg_name, field), val,\
221 				delay_between_poll_us, max_try, __func__, __LINE__)
222 
223 /* macro to update (read, modify, write) register fields
224  */
225 #define REG_UPDATE_N(reg_name, n, ...)	\
226 		generic_reg_update_ex(CTX, \
227 				REG(reg_name), \
228 				n, __VA_ARGS__)
229 
230 #define REG_UPDATE(reg_name, field, val)	\
231 		REG_UPDATE_N(reg_name, 1, \
232 				FN(reg_name, field), val)
233 
234 #define REG_UPDATE_2(reg, f1, v1, f2, v2)	\
235 		REG_UPDATE_N(reg, 2,\
236 				FN(reg, f1), v1,\
237 				FN(reg, f2), v2)
238 
239 #define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3)	\
240 		REG_UPDATE_N(reg, 3, \
241 				FN(reg, f1), v1,\
242 				FN(reg, f2), v2, \
243 				FN(reg, f3), v3)
244 
245 #define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4)	\
246 		REG_UPDATE_N(reg, 4, \
247 				FN(reg, f1), v1,\
248 				FN(reg, f2), v2, \
249 				FN(reg, f3), v3, \
250 				FN(reg, f4), v4)
251 
252 #define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5)	\
253 		REG_UPDATE_N(reg, 5, \
254 				FN(reg, f1), v1,\
255 				FN(reg, f2), v2, \
256 				FN(reg, f3), v3, \
257 				FN(reg, f4), v4, \
258 				FN(reg, f5), v5)
259 
260 #define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6)	\
261 		REG_UPDATE_N(reg, 6, \
262 				FN(reg, f1), v1,\
263 				FN(reg, f2), v2, \
264 				FN(reg, f3), v3, \
265 				FN(reg, f4), v4, \
266 				FN(reg, f5), v5, \
267 				FN(reg, f6), v6)
268 
269 #define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7)	\
270 		REG_UPDATE_N(reg, 7, \
271 				FN(reg, f1), v1,\
272 				FN(reg, f2), v2, \
273 				FN(reg, f3), v3, \
274 				FN(reg, f4), v4, \
275 				FN(reg, f5), v5, \
276 				FN(reg, f6), v6, \
277 				FN(reg, f7), v7)
278 
279 #define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8)	\
280 		REG_UPDATE_N(reg, 8, \
281 				FN(reg, f1), v1,\
282 				FN(reg, f2), v2, \
283 				FN(reg, f3), v3, \
284 				FN(reg, f4), v4, \
285 				FN(reg, f5), v5, \
286 				FN(reg, f6), v6, \
287 				FN(reg, f7), v7, \
288 				FN(reg, f8), v8)
289 
290 #define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9)	\
291 		REG_UPDATE_N(reg, 9, \
292 				FN(reg, f1), v1,\
293 				FN(reg, f2), v2, \
294 				FN(reg, f3), v3, \
295 				FN(reg, f4), v4, \
296 				FN(reg, f5), v5, \
297 				FN(reg, f6), v6, \
298 				FN(reg, f7), v7, \
299 				FN(reg, f8), v8, \
300 				FN(reg, f9), v9)
301 
302 #define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)\
303 		REG_UPDATE_N(reg, 10, \
304 				FN(reg, f1), v1,\
305 				FN(reg, f2), v2, \
306 				FN(reg, f3), v3, \
307 				FN(reg, f4), v4, \
308 				FN(reg, f5), v5, \
309 				FN(reg, f6), v6, \
310 				FN(reg, f7), v7, \
311 				FN(reg, f8), v8, \
312 				FN(reg, f9), v9, \
313 				FN(reg, f10), v10)
314 
315 #define REG_UPDATE_14(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
316 		v10, f11, v11, f12, v12, f13, v13, f14, v14)\
317 		REG_UPDATE_N(reg, 14, \
318 				FN(reg, f1), v1,\
319 				FN(reg, f2), v2, \
320 				FN(reg, f3), v3, \
321 				FN(reg, f4), v4, \
322 				FN(reg, f5), v5, \
323 				FN(reg, f6), v6, \
324 				FN(reg, f7), v7, \
325 				FN(reg, f8), v8, \
326 				FN(reg, f9), v9, \
327 				FN(reg, f10), v10, \
328 				FN(reg, f11), v11, \
329 				FN(reg, f12), v12, \
330 				FN(reg, f13), v13, \
331 				FN(reg, f14), v14)
332 
333 #define REG_UPDATE_19(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
334 		v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19)\
335 		REG_UPDATE_N(reg, 19, \
336 				FN(reg, f1), v1,\
337 				FN(reg, f2), v2, \
338 				FN(reg, f3), v3, \
339 				FN(reg, f4), v4, \
340 				FN(reg, f5), v5, \
341 				FN(reg, f6), v6, \
342 				FN(reg, f7), v7, \
343 				FN(reg, f8), v8, \
344 				FN(reg, f9), v9, \
345 				FN(reg, f10), v10, \
346 				FN(reg, f11), v11, \
347 				FN(reg, f12), v12, \
348 				FN(reg, f13), v13, \
349 				FN(reg, f14), v14, \
350 				FN(reg, f15), v15, \
351 				FN(reg, f16), v16, \
352 				FN(reg, f17), v17, \
353 				FN(reg, f18), v18, \
354 				FN(reg, f19), v19)
355 
356 #define REG_UPDATE_20(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
357 		v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19, f20, v20)\
358 		REG_UPDATE_N(reg, 20, \
359 				FN(reg, f1), v1,\
360 				FN(reg, f2), v2, \
361 				FN(reg, f3), v3, \
362 				FN(reg, f4), v4, \
363 				FN(reg, f5), v5, \
364 				FN(reg, f6), v6, \
365 				FN(reg, f7), v7, \
366 				FN(reg, f8), v8, \
367 				FN(reg, f9), v9, \
368 				FN(reg, f10), v10, \
369 				FN(reg, f11), v11, \
370 				FN(reg, f12), v12, \
371 				FN(reg, f13), v13, \
372 				FN(reg, f14), v14, \
373 				FN(reg, f15), v15, \
374 				FN(reg, f16), v16, \
375 				FN(reg, f17), v17, \
376 				FN(reg, f18), v18, \
377 				FN(reg, f19), v19, \
378 				FN(reg, f20), v20)
379 /* macro to update a register field to specified values in given sequences.
380  * useful when toggling bits
381  */
382 #define REG_UPDATE_SEQ_2(reg, f1, v1, f2, v2) \
383 {	uint32_t val = REG_UPDATE(reg, f1, v1); \
384 	REG_SET(reg, val, f2, v2); }
385 
386 #define REG_UPDATE_SEQ_3(reg, f1, v1, f2, v2, f3, v3) \
387 {	uint32_t val = REG_UPDATE(reg, f1, v1); \
388 	val = REG_SET(reg, val, f2, v2); \
389 	REG_SET(reg, val, f3, v3); }
390 
391 uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
392 		uint8_t shift, uint32_t mask, uint32_t *field_value);
393 
394 uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
395 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
396 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2);
397 
398 uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
399 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
400 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
401 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3);
402 
403 uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr,
404 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
405 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
406 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
407 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4);
408 
409 uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
410 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
411 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
412 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
413 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
414 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5);
415 
416 uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr,
417 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
418 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
419 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
420 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
421 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
422 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6);
423 
424 uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr,
425 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
426 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
427 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
428 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
429 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
430 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
431 		uint8_t shift7, uint32_t mask7, uint32_t *field_value7);
432 
433 uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr,
434 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
435 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
436 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
437 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
438 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
439 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
440 		uint8_t shift7, uint32_t mask7, uint32_t *field_value7,
441 		uint8_t shift8, uint32_t mask8, uint32_t *field_value8);
442 
443 
444 /* indirect register access */
445 
446 #define IX_REG_SET_N(index_reg_name, data_reg_name, index, n, initial_val, ...)	\
447 		generic_indirect_reg_update_ex(CTX, \
448 				REG(index_reg_name), REG(data_reg_name), IND_REG(index), \
449 				initial_val, \
450 				n, __VA_ARGS__)
451 
452 #define IX_REG_SET_2(index_reg_name, data_reg_name, index, init_value, f1, v1, f2, v2)	\
453 		IX_REG_SET_N(index_reg_name, data_reg_name, index, 2, init_value, \
454 				FN(reg, f1), v1,\
455 				FN(reg, f2), v2)
456 
457 
458 #define IX_REG_READ(index_reg_name, data_reg_name, index) \
459 		generic_read_indirect_reg(CTX, REG(index_reg_name), REG(data_reg_name), IND_REG(index))
460 
461 
462 
463 #define IX_REG_UPDATE_N(index_reg_name, data_reg_name, index, n, ...)	\
464 		generic_indirect_reg_update_ex(CTX, \
465 				REG(index_reg_name), REG(data_reg_name), IND_REG(index), \
466 				IX_REG_READ(index_reg_name, data_reg_name, index), \
467 				n, __VA_ARGS__)
468 
469 #define IX_REG_UPDATE_2(index_reg_name, data_reg_name, index, f1, v1, f2, v2)	\
470 		IX_REG_UPDATE_N(index_reg_name, data_reg_name, index, 2,\
471 				FN(reg, f1), v1,\
472 				FN(reg, f2), v2)
473 
474 void generic_write_indirect_reg(const struct dc_context *ctx,
475 		uint32_t addr_index, uint32_t addr_data,
476 		uint32_t index, uint32_t data);
477 
478 uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
479 		uint32_t addr_index, uint32_t addr_data,
480 		uint32_t index);
481 
482 uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx,
483 		uint32_t addr_index, uint32_t addr_data,
484 		uint32_t index, uint32_t reg_val, int n,
485 		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
486 		...);
487 
488 #endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */
489