File Index
Files and directories
Sign in
FILE

dmub_dcn401.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn401.c C
  1// SPDX-License-Identifier: MIT
  2//
  3// Copyright 2024 Advanced Micro Devices, Inc.
  4
  5#include "../dmub_srv.h"
  6#include "dmub_reg.h"
  7#include "dmub_dcn401.h"
  8
  9#include "dcn/dcn_4_1_0_offset.h"
 10#include "dcn/dcn_4_1_0_sh_mask.h"
 11
 12#define DCN_BASE__INST0_SEG2                       0x000034C0
 13
 14#define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
 15#define CTX dmub
 16#define REGS dmub->regs_dcn401
 17#define REG_OFFSET_EXP(reg_name) (BASE(reg##reg_name##_BASE_IDX) + reg##reg_name)
 18
 19const struct dmub_srv_dcn401_regs dmub_srv_dcn401_regs = {
 20#define DMUB_SR(reg) REG_OFFSET_EXP(reg),
 21	{
 22		DMUB_DCN401_REGS()
 23		DMCUB_INTERNAL_REGS()
 24	},
 25#undef DMUB_SR
 26
 27#define DMUB_SF(reg, field) FD_MASK(reg, field),
 28		{ DMUB_DCN401_FIELDS() },
 29#undef DMUB_SF
 30
 31#define DMUB_SF(reg, field) FD_SHIFT(reg, field),
 32		{ DMUB_DCN401_FIELDS() },
 33#undef DMUB_SF
 34};
 35
 36static void dmub_dcn401_get_fb_base_offset(struct dmub_srv *dmub,
 37		uint64_t *fb_base,
 38		uint64_t *fb_offset)
 39{
 40	uint32_t tmp;
 41
 42	if (dmub->fb_base || dmub->fb_offset) {
 43		*fb_base = dmub->fb_base;
 44		*fb_offset = dmub->fb_offset;
 45		return;
 46	}
 47
 48	REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
 49	*fb_base = (uint64_t)tmp << 24;
 50
 51	REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
 52	*fb_offset = (uint64_t)tmp << 24;
 53}
 54
 55static inline void dmub_dcn401_translate_addr(const union dmub_addr *addr_in,
 56		uint64_t fb_base,
 57		uint64_t fb_offset,
 58		union dmub_addr *addr_out)
 59{
 60	addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
 61}
 62
 63void dmub_dcn401_reset(struct dmub_srv *dmub)
 64{
 65	union dmub_gpint_data_register cmd;
 66	const uint32_t timeout_us = 1 * 1000 * 1000; //1s
 67	const uint32_t poll_delay_us = 1; //1us
 68	uint32_t i = 0;
 69	uint32_t enabled, in_reset, scratch, pwait_mode;
 70
 71	REG_GET(DMCUB_CNTL,
 72			DMCUB_ENABLE, &enabled);
 73	REG_GET(DMCUB_CNTL2,
 74			DMCUB_SOFT_RESET, &in_reset);
 75
 76	if (enabled && in_reset == 0) {
 77		cmd.bits.status = 1;
 78		cmd.bits.command_code = DMUB_GPINT__STOP_FW;
 79		cmd.bits.param = 0;
 80
 81		dmub->hw_funcs.set_gpint(dmub, cmd);
 82
 83		for (; i < timeout_us; i++) {
 84			scratch = REG_READ(DMCUB_SCRATCH7);
 85			if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
 86				break;
 87
 88			udelay(poll_delay_us);
 89		}
 90
 91		for (; i < timeout_us; i++) {
 92			REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &pwait_mode);
 93			if (pwait_mode & (1 << 0))
 94				break;
 95
 96			udelay(poll_delay_us);
 97		}
 98	}
 99
100	if (enabled) {
101		REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 1);
102		udelay(1);
103		REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
104	}
105
106	if (i >= timeout_us) {
107		/* timeout should never occur */
108		BREAK_TO_DEBUGGER();
109	}
110
111	REG_UPDATE(DMCUB_REGION3_CW2_TOP_ADDRESS, DMCUB_REGION3_CW2_ENABLE, 0);
112	REG_UPDATE(DMCUB_REGION3_CW3_TOP_ADDRESS, DMCUB_REGION3_CW3_ENABLE, 0);
113	REG_UPDATE(DMCUB_REGION3_CW4_TOP_ADDRESS, DMCUB_REGION3_CW4_ENABLE, 0);
114	REG_UPDATE(DMCUB_REGION3_CW5_TOP_ADDRESS, DMCUB_REGION3_CW5_ENABLE, 0);
115	REG_UPDATE(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, 0);
116	REG_UPDATE(DMCUB_REGION3_CW7_TOP_ADDRESS, DMCUB_REGION3_CW7_ENABLE, 0);
117
118	REG_WRITE(DMCUB_INBOX1_RPTR, 0);
119	REG_WRITE(DMCUB_INBOX1_WPTR, 0);
120	REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
121	REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
122	REG_WRITE(DMCUB_OUTBOX0_RPTR, 0);
123	REG_WRITE(DMCUB_OUTBOX0_WPTR, 0);
124	REG_WRITE(DMCUB_SCRATCH0, 0);
125
126	/* Clear the GPINT command manually so we don't reset again. */
127	cmd.all = 0;
128	dmub->hw_funcs.set_gpint(dmub, cmd);
129}
130
131void dmub_dcn401_reset_release(struct dmub_srv *dmub)
132{
133	REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0);
134	REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF);
135	REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1);
136	REG_UPDATE(DMCUB_CNTL2, DMCUB_SOFT_RESET, 0);
137}
138
139void dmub_dcn401_backdoor_load(struct dmub_srv *dmub,
140		const struct dmub_window *cw0,
141		const struct dmub_window *cw1)
142{
143	union dmub_addr offset;
144	uint64_t fb_base, fb_offset;
145
146	dmub_dcn401_get_fb_base_offset(dmub, &fb_base, &fb_offset);
147
148	/* reset and disable DMCUB and MMHUBBUB DMUIF */
149	REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
150	REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
151
152	dmub_dcn401_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
153
154	REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
155	REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
156	REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
157	REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
158			DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
159			DMCUB_REGION3_CW0_ENABLE, 1);
160
161	dmub_dcn401_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
162
163	REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
164	REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
165	REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
166	REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
167			DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
168			DMCUB_REGION3_CW1_ENABLE, 1);
169
170	/* release DMCUB reset only to prevent premature execution */
171	REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
172			0x20);
173}
174
175void dmub_dcn401_backdoor_load_zfb_mode(struct dmub_srv *dmub,
176		      const struct dmub_window *cw0,
177		      const struct dmub_window *cw1)
178{
179	union dmub_addr offset;
180
181	/* reset and disable DMCUB and MMHUBBUB DMUIF */
182	REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
183	REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
184
185	offset = cw0->offset;
186
187	REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
188	REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
189	REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
190	REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
191			DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
192			DMCUB_REGION3_CW0_ENABLE, 1);
193
194	offset = cw1->offset;
195
196	REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
197	REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
198	REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
199	REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
200			DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
201			DMCUB_REGION3_CW1_ENABLE, 1);
202
203	/* release DMCUB reset only to prevent premature execution */
204	REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
205			0x20);
206}
207
208void dmub_dcn401_setup_windows(struct dmub_srv *dmub,
209		const struct dmub_window *cw2,
210		const struct dmub_window *cw3,
211		const struct dmub_window *cw4,
212		const struct dmub_window *cw5,
213		const struct dmub_window *cw6,
214		const struct dmub_window *region6)
215{
216	union dmub_addr offset;
217
218	offset = cw3->offset;
219
220	REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
221	REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
222	REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
223	REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
224			DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
225			DMCUB_REGION3_CW3_ENABLE, 1);
226
227	offset = cw4->offset;
228
229	REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
230	REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
231	REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
232	REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
233			DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
234			DMCUB_REGION3_CW4_ENABLE, 1);
235
236	offset = cw5->offset;
237
238	REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
239	REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
240	REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
241	REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
242			DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
243			DMCUB_REGION3_CW5_ENABLE, 1);
244
245	REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
246	REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
247	REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
248			DMCUB_REGION5_TOP_ADDRESS,
249			cw5->region.top - cw5->region.base - 1,
250			DMCUB_REGION5_ENABLE, 1);
251
252	offset = cw6->offset;
253
254	REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
255	REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
256	REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
257	REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
258			DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
259			DMCUB_REGION3_CW6_ENABLE, 1);
260
261	offset = region6->offset;
262
263	REG_WRITE(DMCUB_REGION6_OFFSET, offset.u.low_part);
264	REG_WRITE(DMCUB_REGION6_OFFSET_HIGH, offset.u.high_part);
265	REG_SET_2(DMCUB_REGION6_TOP_ADDRESS, 0,
266		  DMCUB_REGION6_TOP_ADDRESS,
267		  region6->region.top - region6->region.base - 1,
268		  DMCUB_REGION6_ENABLE, 1);
269}
270
271void dmub_dcn401_setup_mailbox(struct dmub_srv *dmub,
272		const struct dmub_region *inbox1)
273{
274	REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
275	REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
276}
277
278uint32_t dmub_dcn401_get_inbox1_wptr(struct dmub_srv *dmub)
279{
280	return REG_READ(DMCUB_INBOX1_WPTR);
281}
282
283uint32_t dmub_dcn401_get_inbox1_rptr(struct dmub_srv *dmub)
284{
285	return REG_READ(DMCUB_INBOX1_RPTR);
286}
287
288void dmub_dcn401_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset)
289{
290	REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset);
291}
292
293void dmub_dcn401_setup_out_mailbox(struct dmub_srv *dmub,
294		const struct dmub_region *outbox1)
295{
296	REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base);
297	REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base);
298}
299
300uint32_t dmub_dcn401_get_outbox1_wptr(struct dmub_srv *dmub)
301{
302	/**
303	 * outbox1 wptr register is accessed without locks (dal & dc)
304	 * and to be called only by dmub_srv_stat_get_notification()
305	 */
306	return REG_READ(DMCUB_OUTBOX1_WPTR);
307}
308
309void dmub_dcn401_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
310{
311	/**
312	 * outbox1 rptr register is accessed without locks (dal & dc)
313	 * and to be called only by dmub_srv_stat_get_notification()
314	 */
315	REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
316}
317
318bool dmub_dcn401_is_hw_init(struct dmub_srv *dmub)
319{
320	union dmub_fw_boot_status status;
321	uint32_t is_hw_init;
322
323	status.all = REG_READ(DMCUB_SCRATCH0);
324	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
325
326	return is_hw_init != 0 && status.bits.dal_fw;
327}
328
329bool dmub_dcn401_is_supported(struct dmub_srv *dmub)
330{
331	uint32_t supported = 0;
332
333	REG_GET(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE, &supported);
334
335	return supported;
336}
337
338void dmub_dcn401_set_gpint(struct dmub_srv *dmub,
339		union dmub_gpint_data_register reg)
340{
341	REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all);
342}
343
344bool dmub_dcn401_is_gpint_acked(struct dmub_srv *dmub,
345		union dmub_gpint_data_register reg)
346{
347	union dmub_gpint_data_register test;
348
349	reg.bits.status = 0;
350	test.all = REG_READ(DMCUB_GPINT_DATAIN1);
351
352	return test.all == reg.all;
353}
354
355uint32_t dmub_dcn401_get_gpint_response(struct dmub_srv *dmub)
356{
357	return REG_READ(DMCUB_SCRATCH7);
358}
359
360uint32_t dmub_dcn401_get_gpint_dataout(struct dmub_srv *dmub)
361{
362	uint32_t dataout = REG_READ(DMCUB_GPINT_DATAOUT);
363
364	REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 0);
365
366	REG_WRITE(DMCUB_GPINT_DATAOUT, 0);
367	REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 1);
368	REG_UPDATE(DMCUB_INTERRUPT_ACK, DMCUB_GPINT_IH_INT_ACK, 0);
369
370	REG_UPDATE(DMCUB_INTERRUPT_ENABLE, DMCUB_GPINT_IH_INT_EN, 1);
371
372	return dataout;
373}
374
375union dmub_fw_boot_status dmub_dcn401_get_fw_boot_status(struct dmub_srv *dmub)
376{
377	union dmub_fw_boot_status status;
378
379	status.all = REG_READ(DMCUB_SCRATCH0);
380	return status;
381}
382
383void dmub_dcn401_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
384{
385	union dmub_fw_boot_options boot_options = {0};
386
387	boot_options.bits.z10_disable = params->disable_z10;
388
389	boot_options.bits.skip_phy_access = params->disallow_phy_access;
390
391	REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
392}
393
394void dmub_dcn401_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
395{
396	union dmub_fw_boot_options boot_options;
397	boot_options.all = REG_READ(DMCUB_SCRATCH14);
398	boot_options.bits.skip_phy_init_panel_sequence = skip;
399	REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
400}
401
402void dmub_dcn401_setup_outbox0(struct dmub_srv *dmub,
403		const struct dmub_region *outbox0)
404{
405	REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
406
407	REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
408}
409
410uint32_t dmub_dcn401_get_outbox0_wptr(struct dmub_srv *dmub)
411{
412	return REG_READ(DMCUB_OUTBOX0_WPTR);
413}
414
415void dmub_dcn401_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
416{
417	REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
418}
419
420uint32_t dmub_dcn401_get_current_time(struct dmub_srv *dmub)
421{
422	return REG_READ(DMCUB_TIMER_CURRENT);
423}
424
425void dmub_dcn401_get_diagnostic_data(struct dmub_srv *dmub)
426{
427	uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset, is_pwait;
428	uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
429	struct dmub_timeout_info timeout = {0};
430
431	if (!dmub)
432		return;
433
434	/* timeout data filled externally, cache before resetting memory */
435	timeout = dmub->debug.timeout_info;
436	memset(&dmub->debug, 0, sizeof(dmub->debug));
437	dmub->debug.timeout_info = timeout;
438
439	dmub->debug.dmcub_version = dmub->fw_version;
440
441	dmub->debug.scratch[0] = REG_READ(DMCUB_SCRATCH0);
442	dmub->debug.scratch[1] = REG_READ(DMCUB_SCRATCH1);
443	dmub->debug.scratch[2] = REG_READ(DMCUB_SCRATCH2);
444	dmub->debug.scratch[3] = REG_READ(DMCUB_SCRATCH3);
445	dmub->debug.scratch[4] = REG_READ(DMCUB_SCRATCH4);
446	dmub->debug.scratch[5] = REG_READ(DMCUB_SCRATCH5);
447	dmub->debug.scratch[6] = REG_READ(DMCUB_SCRATCH6);
448	dmub->debug.scratch[7] = REG_READ(DMCUB_SCRATCH7);
449	dmub->debug.scratch[8] = REG_READ(DMCUB_SCRATCH8);
450	dmub->debug.scratch[9] = REG_READ(DMCUB_SCRATCH9);
451	dmub->debug.scratch[10] = REG_READ(DMCUB_SCRATCH10);
452	dmub->debug.scratch[11] = REG_READ(DMCUB_SCRATCH11);
453	dmub->debug.scratch[12] = REG_READ(DMCUB_SCRATCH12);
454	dmub->debug.scratch[13] = REG_READ(DMCUB_SCRATCH13);
455	dmub->debug.scratch[14] = REG_READ(DMCUB_SCRATCH14);
456	dmub->debug.scratch[15] = REG_READ(DMCUB_SCRATCH15);
457	dmub->debug.scratch[16] = REG_READ(DMCUB_SCRATCH16);
458
459	dmub->debug.undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
460	dmub->debug.inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
461	dmub->debug.data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
462
463	dmub->debug.inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
464	dmub->debug.inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
465	dmub->debug.inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
466
467	dmub->debug.inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
468	dmub->debug.inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
469	dmub->debug.inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
470
471	dmub->debug.outbox1_rptr = REG_READ(DMCUB_OUTBOX1_RPTR);
472	dmub->debug.outbox1_wptr = REG_READ(DMCUB_OUTBOX1_WPTR);
473	dmub->debug.outbox1_size = REG_READ(DMCUB_OUTBOX1_SIZE);
474
475	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
476	dmub->debug.is_dmcub_enabled = is_dmub_enabled;
477
478	REG_GET(DMCUB_CNTL, DMCUB_PWAIT_MODE_STATUS, &is_pwait);
479	dmub->debug.is_pwait = is_pwait;
480
481	REG_GET(DMCUB_CNTL2, DMCUB_SOFT_RESET, &is_soft_reset);
482	dmub->debug.is_dmcub_soft_reset = is_soft_reset;
483
484	REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
485	dmub->debug.is_dmcub_secure_reset = is_sec_reset;
486
487	REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
488	dmub->debug.is_traceport_en  = is_traceport_enabled;
489
490	REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
491	dmub->debug.is_cw0_enabled = is_cw0_enabled;
492
493	REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
494	dmub->debug.is_cw6_enabled = is_cw6_enabled;
495
496	dmub->debug.gpint_datain0 = REG_READ(DMCUB_GPINT_DATAIN0);
497}
498void dmub_dcn401_configure_dmub_in_system_memory(struct dmub_srv *dmub)
499{
500	/* DMCUB_REGION3_TMR_AXI_SPACE values:
501	 * 0b011 (0x3) - FB physical address
502	 * 0b100 (0x4) - GPU virtual address
503	 *
504	 * Default value is 0x3 (FB Physical address for TMR). When programming
505	 * DMUB to be in system memory, change to 0x4. The system memory allocated
506	 * is accessible by both GPU and CPU, so we use GPU virtual address.
507	 */
508	REG_WRITE(DMCUB_REGION3_TMR_AXI_SPACE, 0x4);
509}
510
511void dmub_dcn401_send_inbox0_cmd(struct dmub_srv *dmub, union dmub_inbox0_data_register data)
512{
513	REG_WRITE(DMCUB_INBOX0_WPTR, data.inbox0_cmd_common.all);
514}
515
516void dmub_dcn401_clear_inbox0_ack_register(struct dmub_srv *dmub)
517{
518	REG_WRITE(DMCUB_SCRATCH17, 0);
519}
520
521uint32_t dmub_dcn401_read_inbox0_ack_register(struct dmub_srv *dmub)
522{
523	return REG_READ(DMCUB_SCRATCH17);
524}
525
526void dmub_dcn401_send_reg_inbox0_cmd_msg(struct dmub_srv *dmub,
527		union dmub_rb_cmd *cmd)
528{
529	uint32_t *dwords = (uint32_t *)cmd;
530	int32_t payload_size_bytes = cmd->cmd_common.header.payload_bytes;
531	uint32_t msg_index;
532	static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch");
533
534	/* read remaining data based on payload size */
535	for (msg_index = 0; msg_index < 15; msg_index++) {
536		if (payload_size_bytes <= msg_index * 4) {
537			break;
538		}
539
540		switch (msg_index) {
541		case 0:
542			REG_WRITE(DMCUB_REG_INBOX0_MSG0, dwords[msg_index + 1]);
543			break;
544		case 1:
545			REG_WRITE(DMCUB_REG_INBOX0_MSG1, dwords[msg_index + 1]);
546			break;
547		case 2:
548			REG_WRITE(DMCUB_REG_INBOX0_MSG2, dwords[msg_index + 1]);
549			break;
550		case 3:
551			REG_WRITE(DMCUB_REG_INBOX0_MSG3, dwords[msg_index + 1]);
552			break;
553		case 4:
554			REG_WRITE(DMCUB_REG_INBOX0_MSG4, dwords[msg_index + 1]);
555			break;
556		case 5:
557			REG_WRITE(DMCUB_REG_INBOX0_MSG5, dwords[msg_index + 1]);
558			break;
559		case 6:
560			REG_WRITE(DMCUB_REG_INBOX0_MSG6, dwords[msg_index + 1]);
561			break;
562		case 7:
563			REG_WRITE(DMCUB_REG_INBOX0_MSG7, dwords[msg_index + 1]);
564			break;
565		case 8:
566			REG_WRITE(DMCUB_REG_INBOX0_MSG8, dwords[msg_index + 1]);
567			break;
568		case 9:
569			REG_WRITE(DMCUB_REG_INBOX0_MSG9, dwords[msg_index + 1]);
570			break;
571		case 10:
572			REG_WRITE(DMCUB_REG_INBOX0_MSG10, dwords[msg_index + 1]);
573			break;
574		case 11:
575			REG_WRITE(DMCUB_REG_INBOX0_MSG11, dwords[msg_index + 1]);
576			break;
577		case 12:
578			REG_WRITE(DMCUB_REG_INBOX0_MSG12, dwords[msg_index + 1]);
579			break;
580		case 13:
581			REG_WRITE(DMCUB_REG_INBOX0_MSG13, dwords[msg_index + 1]);
582			break;
583		case 14:
584			REG_WRITE(DMCUB_REG_INBOX0_MSG14, dwords[msg_index + 1]);
585			break;
586		}
587	}
588
589	/* writing to INBOX RDY register will trigger DMUB REG INBOX0 RDY
590	 * interrupt.
591	 */
592	REG_WRITE(DMCUB_REG_INBOX0_RDY, dwords[0]);
593}
594
595uint32_t dmub_dcn401_read_reg_inbox0_rsp_int_status(struct dmub_srv *dmub)
596{
597	uint32_t status;
598
599	REG_GET(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_STAT, &status);
600	return status;
601}
602
603void dmub_dcn401_read_reg_inbox0_cmd_rsp(struct dmub_srv *dmub,
604		union dmub_rb_cmd *cmd)
605{
606	uint32_t *dwords = (uint32_t *)cmd;
607
608	static_assert(sizeof(*cmd) == 64, "DMUB command size mismatch");
609
610	dwords[0] = REG_READ(DMCUB_REG_INBOX0_RSP);
611	dwords[1] = REG_READ(DMCUB_REG_INBOX0_MSG0);
612	dwords[2] = REG_READ(DMCUB_REG_INBOX0_MSG1);
613	dwords[3] = REG_READ(DMCUB_REG_INBOX0_MSG2);
614	dwords[4] = REG_READ(DMCUB_REG_INBOX0_MSG3);
615	dwords[5] = REG_READ(DMCUB_REG_INBOX0_MSG4);
616	dwords[6] = REG_READ(DMCUB_REG_INBOX0_MSG5);
617	dwords[7] = REG_READ(DMCUB_REG_INBOX0_MSG6);
618	dwords[8] = REG_READ(DMCUB_REG_INBOX0_MSG7);
619	dwords[9] = REG_READ(DMCUB_REG_INBOX0_MSG8);
620	dwords[10] = REG_READ(DMCUB_REG_INBOX0_MSG9);
621	dwords[11] = REG_READ(DMCUB_REG_INBOX0_MSG10);
622	dwords[12] = REG_READ(DMCUB_REG_INBOX0_MSG11);
623	dwords[13] = REG_READ(DMCUB_REG_INBOX0_MSG12);
624	dwords[14] = REG_READ(DMCUB_REG_INBOX0_MSG13);
625	dwords[15] = REG_READ(DMCUB_REG_INBOX0_MSG14);
626}
627
628void dmub_dcn401_write_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub)
629{
630	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 1);
631}
632
633void dmub_dcn401_clear_reg_inbox0_rsp_int_ack(struct dmub_srv *dmub)
634{
635	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_ACK, 0);
636}
637
638void dmub_dcn401_enable_reg_inbox0_rsp_int(struct dmub_srv *dmub, bool enable)
639{
640	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_INBOX0_RSP_INT_EN, enable ? 1:0);
641}
642
643void dmub_dcn401_write_reg_outbox0_rdy_int_ack(struct dmub_srv *dmub)
644{
645	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 1);
646	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_ACK, 0);
647}
648
649void dmub_dcn401_read_reg_outbox0_msg(struct dmub_srv *dmub, uint32_t *msg)
650{
651	*msg = REG_READ(DMCUB_REG_OUTBOX0_MSG0);
652}
653
654void dmub_dcn401_write_reg_outbox0_rsp(struct dmub_srv *dmub, uint32_t *rsp)
655{
656	REG_WRITE(DMCUB_REG_OUTBOX0_RSP, *rsp);
657}
658
659uint32_t dmub_dcn401_read_reg_outbox0_rsp_int_status(struct dmub_srv *dmub)
660{
661	uint32_t status;
662
663	REG_GET(DMCUB_INTERRUPT_STATUS, DMCUB_REG_OUTBOX0_RSP_INT_STAT, &status);
664	return status;
665}
666
667void dmub_dcn401_enable_reg_outbox0_rdy_int(struct dmub_srv *dmub, bool enable)
668{
669	REG_UPDATE(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_EN, enable ? 1:0);
670}
671
672uint32_t dmub_dcn401_read_reg_outbox0_rdy_int_status(struct dmub_srv *dmub)
673{
674	uint32_t status;
675
676	REG_GET(HOST_INTERRUPT_CSR, HOST_REG_OUTBOX0_RDY_INT_STAT, &status);
677	return status;
678}
~/ Read-only file preview.