1c349dbc7Sjsg /*
2c349dbc7Sjsg  * Copyright 2019 Advanced Micro Devices, Inc.
3c349dbc7Sjsg  *
4c349dbc7Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
5c349dbc7Sjsg  * copy of this software and associated documentation files (the "Software"),
6c349dbc7Sjsg  * to deal in the Software without restriction, including without limitation
7c349dbc7Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8c349dbc7Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
9c349dbc7Sjsg  * Software is furnished to do so, subject to the following conditions:
10c349dbc7Sjsg  *
11c349dbc7Sjsg  * The above copyright notice and this permission notice shall be included in
12c349dbc7Sjsg  * all copies or substantial portions of the Software.
13c349dbc7Sjsg  *
14c349dbc7Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15c349dbc7Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16c349dbc7Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17c349dbc7Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18c349dbc7Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19c349dbc7Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20c349dbc7Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
21c349dbc7Sjsg  *
22c349dbc7Sjsg  * Authors: AMD
23c349dbc7Sjsg  *
24c349dbc7Sjsg  */
25c349dbc7Sjsg 
26ad8b1aafSjsg #include "../dmub_srv.h"
27c349dbc7Sjsg #include "dmub_reg.h"
28c349dbc7Sjsg #include "dmub_dcn20.h"
29c349dbc7Sjsg 
30c349dbc7Sjsg #include "dcn/dcn_2_0_0_offset.h"
31c349dbc7Sjsg #include "dcn/dcn_2_0_0_sh_mask.h"
32c349dbc7Sjsg #include "soc15_hw_ip.h"
33c349dbc7Sjsg #include "vega10_ip_offset.h"
34c349dbc7Sjsg 
35c349dbc7Sjsg #define BASE_INNER(seg) DCN_BASE__INST0_SEG##seg
36c349dbc7Sjsg #define CTX dmub
37c349dbc7Sjsg #define REGS dmub->regs
38c349dbc7Sjsg 
39c349dbc7Sjsg /* Registers. */
40c349dbc7Sjsg 
41c349dbc7Sjsg const struct dmub_srv_common_regs dmub_srv_dcn20_regs = {
42c349dbc7Sjsg #define DMUB_SR(reg) REG_OFFSET(reg),
435ca02815Sjsg 	{
445ca02815Sjsg 		DMUB_COMMON_REGS()
455ca02815Sjsg 		DMCUB_INTERNAL_REGS()
465ca02815Sjsg 	},
47c349dbc7Sjsg #undef DMUB_SR
48c349dbc7Sjsg 
49c349dbc7Sjsg #define DMUB_SF(reg, field) FD_MASK(reg, field),
50c349dbc7Sjsg 	{ DMUB_COMMON_FIELDS() },
51c349dbc7Sjsg #undef DMUB_SF
52c349dbc7Sjsg 
53c349dbc7Sjsg #define DMUB_SF(reg, field) FD_SHIFT(reg, field),
54c349dbc7Sjsg 	{ DMUB_COMMON_FIELDS() },
55c349dbc7Sjsg #undef DMUB_SF
56c349dbc7Sjsg };
57c349dbc7Sjsg 
58c349dbc7Sjsg /* Shared functions. */
59c349dbc7Sjsg 
dmub_dcn20_get_fb_base_offset(struct dmub_srv * dmub,uint64_t * fb_base,uint64_t * fb_offset)60c349dbc7Sjsg static void dmub_dcn20_get_fb_base_offset(struct dmub_srv *dmub,
61c349dbc7Sjsg 					  uint64_t *fb_base,
62c349dbc7Sjsg 					  uint64_t *fb_offset)
63c349dbc7Sjsg {
64c349dbc7Sjsg 	uint32_t tmp;
65c349dbc7Sjsg 
66c349dbc7Sjsg 	if (dmub->fb_base || dmub->fb_offset) {
67c349dbc7Sjsg 		*fb_base = dmub->fb_base;
68c349dbc7Sjsg 		*fb_offset = dmub->fb_offset;
69c349dbc7Sjsg 		return;
70c349dbc7Sjsg 	}
71c349dbc7Sjsg 
72c349dbc7Sjsg 	REG_GET(DCN_VM_FB_LOCATION_BASE, FB_BASE, &tmp);
73c349dbc7Sjsg 	*fb_base = (uint64_t)tmp << 24;
74c349dbc7Sjsg 
75c349dbc7Sjsg 	REG_GET(DCN_VM_FB_OFFSET, FB_OFFSET, &tmp);
76c349dbc7Sjsg 	*fb_offset = (uint64_t)tmp << 24;
77c349dbc7Sjsg }
78c349dbc7Sjsg 
dmub_dcn20_translate_addr(const union dmub_addr * addr_in,uint64_t fb_base,uint64_t fb_offset,union dmub_addr * addr_out)79c349dbc7Sjsg static inline void dmub_dcn20_translate_addr(const union dmub_addr *addr_in,
80c349dbc7Sjsg 					     uint64_t fb_base,
81c349dbc7Sjsg 					     uint64_t fb_offset,
82c349dbc7Sjsg 					     union dmub_addr *addr_out)
83c349dbc7Sjsg {
84c349dbc7Sjsg 	addr_out->quad_part = addr_in->quad_part - fb_base + fb_offset;
85c349dbc7Sjsg }
86c349dbc7Sjsg 
dmub_dcn20_use_cached_inbox(struct dmub_srv * dmub)875ca02815Sjsg bool dmub_dcn20_use_cached_inbox(struct dmub_srv *dmub)
885ca02815Sjsg {
895ca02815Sjsg 	/* Cached inbox is not supported in this fw version range */
905ca02815Sjsg 	return !(dmub->fw_version >= DMUB_FW_VERSION(1, 0, 0) &&
915ca02815Sjsg 		 dmub->fw_version <= DMUB_FW_VERSION(1, 10, 0));
925ca02815Sjsg }
935ca02815Sjsg 
dmub_dcn20_reset(struct dmub_srv * dmub)94c349dbc7Sjsg void dmub_dcn20_reset(struct dmub_srv *dmub)
95c349dbc7Sjsg {
96c349dbc7Sjsg 	union dmub_gpint_data_register cmd;
97c349dbc7Sjsg 	const uint32_t timeout = 30;
98c349dbc7Sjsg 	uint32_t in_reset, scratch, i;
99c349dbc7Sjsg 
100c349dbc7Sjsg 	REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &in_reset);
101c349dbc7Sjsg 
102c349dbc7Sjsg 	if (in_reset == 0) {
103c349dbc7Sjsg 		cmd.bits.status = 1;
104c349dbc7Sjsg 		cmd.bits.command_code = DMUB_GPINT__STOP_FW;
105c349dbc7Sjsg 		cmd.bits.param = 0;
106c349dbc7Sjsg 
107c349dbc7Sjsg 		dmub->hw_funcs.set_gpint(dmub, cmd);
108c349dbc7Sjsg 
109c349dbc7Sjsg 		/**
110c349dbc7Sjsg 		 * Timeout covers both the ACK and the wait
111c349dbc7Sjsg 		 * for remaining work to finish.
112c349dbc7Sjsg 		 *
113c349dbc7Sjsg 		 * This is mostly bound by the PHY disable sequence.
114c349dbc7Sjsg 		 * Each register check will be greater than 1us, so
115c349dbc7Sjsg 		 * don't bother using udelay.
116c349dbc7Sjsg 		 */
117c349dbc7Sjsg 
118c349dbc7Sjsg 		for (i = 0; i < timeout; ++i) {
119c349dbc7Sjsg 			if (dmub->hw_funcs.is_gpint_acked(dmub, cmd))
120c349dbc7Sjsg 				break;
121c349dbc7Sjsg 		}
122c349dbc7Sjsg 
123c349dbc7Sjsg 		for (i = 0; i < timeout; ++i) {
124c349dbc7Sjsg 			scratch = dmub->hw_funcs.get_gpint_response(dmub);
125c349dbc7Sjsg 			if (scratch == DMUB_GPINT__STOP_FW_RESPONSE)
126c349dbc7Sjsg 				break;
127c349dbc7Sjsg 		}
128c349dbc7Sjsg 
129c349dbc7Sjsg 		/* Clear the GPINT command manually so we don't reset again. */
130c349dbc7Sjsg 		cmd.all = 0;
131c349dbc7Sjsg 		dmub->hw_funcs.set_gpint(dmub, cmd);
132c349dbc7Sjsg 
133c349dbc7Sjsg 		/* Force reset in case we timed out, DMCUB is likely hung. */
134c349dbc7Sjsg 	}
135c349dbc7Sjsg 
136c349dbc7Sjsg 	REG_UPDATE(DMCUB_CNTL, DMCUB_SOFT_RESET, 1);
137c349dbc7Sjsg 	REG_UPDATE(DMCUB_CNTL, DMCUB_ENABLE, 0);
138c349dbc7Sjsg 	REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 1);
139c349dbc7Sjsg 	REG_WRITE(DMCUB_INBOX1_RPTR, 0);
140c349dbc7Sjsg 	REG_WRITE(DMCUB_INBOX1_WPTR, 0);
1415ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX1_RPTR, 0);
1425ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX1_WPTR, 0);
143c349dbc7Sjsg 	REG_WRITE(DMCUB_SCRATCH0, 0);
144c349dbc7Sjsg }
145c349dbc7Sjsg 
dmub_dcn20_reset_release(struct dmub_srv * dmub)146c349dbc7Sjsg void dmub_dcn20_reset_release(struct dmub_srv *dmub)
147c349dbc7Sjsg {
148c349dbc7Sjsg 	REG_UPDATE(MMHUBBUB_SOFT_RESET, DMUIF_SOFT_RESET, 0);
149c349dbc7Sjsg 	REG_WRITE(DMCUB_SCRATCH15, dmub->psp_version & 0x001100FF);
150c349dbc7Sjsg 	REG_UPDATE_2(DMCUB_CNTL, DMCUB_ENABLE, 1, DMCUB_TRACEPORT_EN, 1);
151c349dbc7Sjsg 	REG_UPDATE(DMCUB_CNTL, DMCUB_SOFT_RESET, 0);
152c349dbc7Sjsg }
153c349dbc7Sjsg 
dmub_dcn20_backdoor_load(struct dmub_srv * dmub,const struct dmub_window * cw0,const struct dmub_window * cw1)154c349dbc7Sjsg void dmub_dcn20_backdoor_load(struct dmub_srv *dmub,
155c349dbc7Sjsg 			      const struct dmub_window *cw0,
156c349dbc7Sjsg 			      const struct dmub_window *cw1)
157c349dbc7Sjsg {
158c349dbc7Sjsg 	union dmub_addr offset;
159c349dbc7Sjsg 	uint64_t fb_base, fb_offset;
160c349dbc7Sjsg 
161c349dbc7Sjsg 	dmub_dcn20_get_fb_base_offset(dmub, &fb_base, &fb_offset);
162c349dbc7Sjsg 
163c349dbc7Sjsg 	REG_UPDATE(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 1);
164c349dbc7Sjsg 	REG_UPDATE_2(DMCUB_MEM_CNTL, DMCUB_MEM_READ_SPACE, 0x3,
165c349dbc7Sjsg 		     DMCUB_MEM_WRITE_SPACE, 0x3);
166c349dbc7Sjsg 
167c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw0->offset, fb_base, fb_offset, &offset);
168c349dbc7Sjsg 
169c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW0_OFFSET, offset.u.low_part);
170c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW0_OFFSET_HIGH, offset.u.high_part);
171c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW0_BASE_ADDRESS, cw0->region.base);
172c349dbc7Sjsg 	REG_SET_2(DMCUB_REGION3_CW0_TOP_ADDRESS, 0,
173c349dbc7Sjsg 		  DMCUB_REGION3_CW0_TOP_ADDRESS, cw0->region.top,
174c349dbc7Sjsg 		  DMCUB_REGION3_CW0_ENABLE, 1);
175c349dbc7Sjsg 
176c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw1->offset, fb_base, fb_offset, &offset);
177c349dbc7Sjsg 
178c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW1_OFFSET, offset.u.low_part);
179c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW1_OFFSET_HIGH, offset.u.high_part);
180c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW1_BASE_ADDRESS, cw1->region.base);
181c349dbc7Sjsg 	REG_SET_2(DMCUB_REGION3_CW1_TOP_ADDRESS, 0,
182c349dbc7Sjsg 		  DMCUB_REGION3_CW1_TOP_ADDRESS, cw1->region.top,
183c349dbc7Sjsg 		  DMCUB_REGION3_CW1_ENABLE, 1);
184c349dbc7Sjsg 
185c349dbc7Sjsg 	REG_UPDATE_2(DMCUB_SEC_CNTL, DMCUB_SEC_RESET, 0, DMCUB_MEM_UNIT_ID,
186c349dbc7Sjsg 		     0x20);
187c349dbc7Sjsg }
188c349dbc7Sjsg 
dmub_dcn20_setup_windows(struct dmub_srv * dmub,const struct dmub_window * cw2,const struct dmub_window * cw3,const struct dmub_window * cw4,const struct dmub_window * cw5,const struct dmub_window * cw6)189c349dbc7Sjsg void dmub_dcn20_setup_windows(struct dmub_srv *dmub,
190c349dbc7Sjsg 			      const struct dmub_window *cw2,
191c349dbc7Sjsg 			      const struct dmub_window *cw3,
192c349dbc7Sjsg 			      const struct dmub_window *cw4,
193c349dbc7Sjsg 			      const struct dmub_window *cw5,
194c349dbc7Sjsg 			      const struct dmub_window *cw6)
195c349dbc7Sjsg {
196c349dbc7Sjsg 	union dmub_addr offset;
197c349dbc7Sjsg 	uint64_t fb_base, fb_offset;
198c349dbc7Sjsg 
199c349dbc7Sjsg 	dmub_dcn20_get_fb_base_offset(dmub, &fb_base, &fb_offset);
200c349dbc7Sjsg 
201ad8b1aafSjsg 	if (cw2->region.base != cw2->region.top) {
202ad8b1aafSjsg 		dmub_dcn20_translate_addr(&cw2->offset, fb_base, fb_offset,
203ad8b1aafSjsg 					  &offset);
204c349dbc7Sjsg 
205c349dbc7Sjsg 		REG_WRITE(DMCUB_REGION3_CW2_OFFSET, offset.u.low_part);
206c349dbc7Sjsg 		REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, offset.u.high_part);
207c349dbc7Sjsg 		REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, cw2->region.base);
208c349dbc7Sjsg 		REG_SET_2(DMCUB_REGION3_CW2_TOP_ADDRESS, 0,
209c349dbc7Sjsg 			  DMCUB_REGION3_CW2_TOP_ADDRESS, cw2->region.top,
210c349dbc7Sjsg 			  DMCUB_REGION3_CW2_ENABLE, 1);
211ad8b1aafSjsg 	} else {
212ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW2_OFFSET, 0);
213ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW2_OFFSET_HIGH, 0);
214ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW2_BASE_ADDRESS, 0);
215ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW2_TOP_ADDRESS, 0);
216ad8b1aafSjsg 	}
217c349dbc7Sjsg 
218c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw3->offset, fb_base, fb_offset, &offset);
219c349dbc7Sjsg 
220c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW3_OFFSET, offset.u.low_part);
221c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW3_OFFSET_HIGH, offset.u.high_part);
222c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW3_BASE_ADDRESS, cw3->region.base);
223c349dbc7Sjsg 	REG_SET_2(DMCUB_REGION3_CW3_TOP_ADDRESS, 0,
224c349dbc7Sjsg 		  DMCUB_REGION3_CW3_TOP_ADDRESS, cw3->region.top,
225c349dbc7Sjsg 		  DMCUB_REGION3_CW3_ENABLE, 1);
226c349dbc7Sjsg 
227c349dbc7Sjsg 	/* TODO: Move this to CW4. */
228c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw4->offset, fb_base, fb_offset, &offset);
229c349dbc7Sjsg 
230ad8b1aafSjsg 	/* New firmware can support CW4. */
2315ca02815Sjsg 	if (dmub_dcn20_use_cached_inbox(dmub)) {
232ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW4_OFFSET, offset.u.low_part);
233ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW4_OFFSET_HIGH, offset.u.high_part);
234ad8b1aafSjsg 		REG_WRITE(DMCUB_REGION3_CW4_BASE_ADDRESS, cw4->region.base);
235ad8b1aafSjsg 		REG_SET_2(DMCUB_REGION3_CW4_TOP_ADDRESS, 0,
236ad8b1aafSjsg 			  DMCUB_REGION3_CW4_TOP_ADDRESS, cw4->region.top,
237ad8b1aafSjsg 			  DMCUB_REGION3_CW4_ENABLE, 1);
238ad8b1aafSjsg 	} else {
239c349dbc7Sjsg 		REG_WRITE(DMCUB_REGION4_OFFSET, offset.u.low_part);
240c349dbc7Sjsg 		REG_WRITE(DMCUB_REGION4_OFFSET_HIGH, offset.u.high_part);
241ad8b1aafSjsg 		REG_SET_2(DMCUB_REGION4_TOP_ADDRESS, 0,
242ad8b1aafSjsg 			  DMCUB_REGION4_TOP_ADDRESS,
243ad8b1aafSjsg 			  cw4->region.top - cw4->region.base - 1,
244ad8b1aafSjsg 			  DMCUB_REGION4_ENABLE, 1);
245ad8b1aafSjsg 	}
246c349dbc7Sjsg 
247c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw5->offset, fb_base, fb_offset, &offset);
248c349dbc7Sjsg 
249c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW5_OFFSET, offset.u.low_part);
250c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW5_OFFSET_HIGH, offset.u.high_part);
251c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW5_BASE_ADDRESS, cw5->region.base);
252c349dbc7Sjsg 	REG_SET_2(DMCUB_REGION3_CW5_TOP_ADDRESS, 0,
253c349dbc7Sjsg 		  DMCUB_REGION3_CW5_TOP_ADDRESS, cw5->region.top,
254c349dbc7Sjsg 		  DMCUB_REGION3_CW5_ENABLE, 1);
255c349dbc7Sjsg 
2565ca02815Sjsg 	REG_WRITE(DMCUB_REGION5_OFFSET, offset.u.low_part);
2575ca02815Sjsg 	REG_WRITE(DMCUB_REGION5_OFFSET_HIGH, offset.u.high_part);
2585ca02815Sjsg 	REG_SET_2(DMCUB_REGION5_TOP_ADDRESS, 0,
2595ca02815Sjsg 		  DMCUB_REGION5_TOP_ADDRESS,
2605ca02815Sjsg 		  cw5->region.top - cw5->region.base - 1,
2615ca02815Sjsg 		  DMCUB_REGION5_ENABLE, 1);
2625ca02815Sjsg 
263c349dbc7Sjsg 	dmub_dcn20_translate_addr(&cw6->offset, fb_base, fb_offset, &offset);
264c349dbc7Sjsg 
265c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW6_OFFSET, offset.u.low_part);
266c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW6_OFFSET_HIGH, offset.u.high_part);
267c349dbc7Sjsg 	REG_WRITE(DMCUB_REGION3_CW6_BASE_ADDRESS, cw6->region.base);
268c349dbc7Sjsg 	REG_SET_2(DMCUB_REGION3_CW6_TOP_ADDRESS, 0,
269c349dbc7Sjsg 		  DMCUB_REGION3_CW6_TOP_ADDRESS, cw6->region.top,
270c349dbc7Sjsg 		  DMCUB_REGION3_CW6_ENABLE, 1);
271c349dbc7Sjsg }
272c349dbc7Sjsg 
dmub_dcn20_setup_mailbox(struct dmub_srv * dmub,const struct dmub_region * inbox1)273c349dbc7Sjsg void dmub_dcn20_setup_mailbox(struct dmub_srv *dmub,
274c349dbc7Sjsg 			      const struct dmub_region *inbox1)
275c349dbc7Sjsg {
276ad8b1aafSjsg 	/* New firmware can support CW4 for the inbox. */
2775ca02815Sjsg 	if (dmub_dcn20_use_cached_inbox(dmub))
278ad8b1aafSjsg 		REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, inbox1->base);
279ad8b1aafSjsg 	else
280c349dbc7Sjsg 		REG_WRITE(DMCUB_INBOX1_BASE_ADDRESS, 0x80000000);
281ad8b1aafSjsg 
282c349dbc7Sjsg 	REG_WRITE(DMCUB_INBOX1_SIZE, inbox1->top - inbox1->base);
283c349dbc7Sjsg }
284c349dbc7Sjsg 
dmub_dcn20_get_inbox1_wptr(struct dmub_srv * dmub)285*69703a93Sjsg uint32_t dmub_dcn20_get_inbox1_wptr(struct dmub_srv *dmub)
286*69703a93Sjsg {
287*69703a93Sjsg 	return REG_READ(DMCUB_INBOX1_WPTR);
288*69703a93Sjsg }
289*69703a93Sjsg 
dmub_dcn20_get_inbox1_rptr(struct dmub_srv * dmub)290c349dbc7Sjsg uint32_t dmub_dcn20_get_inbox1_rptr(struct dmub_srv *dmub)
291c349dbc7Sjsg {
292c349dbc7Sjsg 	return REG_READ(DMCUB_INBOX1_RPTR);
293c349dbc7Sjsg }
294c349dbc7Sjsg 
dmub_dcn20_set_inbox1_wptr(struct dmub_srv * dmub,uint32_t wptr_offset)295c349dbc7Sjsg void dmub_dcn20_set_inbox1_wptr(struct dmub_srv *dmub, uint32_t wptr_offset)
296c349dbc7Sjsg {
297c349dbc7Sjsg 	REG_WRITE(DMCUB_INBOX1_WPTR, wptr_offset);
298c349dbc7Sjsg }
299c349dbc7Sjsg 
dmub_dcn20_setup_out_mailbox(struct dmub_srv * dmub,const struct dmub_region * outbox1)3005ca02815Sjsg void dmub_dcn20_setup_out_mailbox(struct dmub_srv *dmub,
3015ca02815Sjsg 			      const struct dmub_region *outbox1)
3025ca02815Sjsg {
3035ca02815Sjsg 	/* New firmware can support CW4 for the outbox. */
3045ca02815Sjsg 	if (dmub_dcn20_use_cached_inbox(dmub))
3055ca02815Sjsg 		REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, outbox1->base);
3065ca02815Sjsg 	else
3075ca02815Sjsg 		REG_WRITE(DMCUB_OUTBOX1_BASE_ADDRESS, 0x80002000);
3085ca02815Sjsg 
3095ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX1_SIZE, outbox1->top - outbox1->base);
3105ca02815Sjsg }
3115ca02815Sjsg 
dmub_dcn20_get_outbox1_wptr(struct dmub_srv * dmub)3125ca02815Sjsg uint32_t dmub_dcn20_get_outbox1_wptr(struct dmub_srv *dmub)
3135ca02815Sjsg {
3145ca02815Sjsg 	/**
3155ca02815Sjsg 	 * outbox1 wptr register is accessed without locks (dal & dc)
3165ca02815Sjsg 	 * and to be called only by dmub_srv_stat_get_notification()
3175ca02815Sjsg 	 */
3185ca02815Sjsg 	return REG_READ(DMCUB_OUTBOX1_WPTR);
3195ca02815Sjsg }
3205ca02815Sjsg 
dmub_dcn20_set_outbox1_rptr(struct dmub_srv * dmub,uint32_t rptr_offset)3215ca02815Sjsg void dmub_dcn20_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
3225ca02815Sjsg {
3235ca02815Sjsg 	/**
3245ca02815Sjsg 	 * outbox1 rptr register is accessed without locks (dal & dc)
3255ca02815Sjsg 	 * and to be called only by dmub_srv_stat_get_notification()
3265ca02815Sjsg 	 */
3275ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX1_RPTR, rptr_offset);
3285ca02815Sjsg }
3295ca02815Sjsg 
dmub_dcn20_setup_outbox0(struct dmub_srv * dmub,const struct dmub_region * outbox0)3305ca02815Sjsg void dmub_dcn20_setup_outbox0(struct dmub_srv *dmub,
3315ca02815Sjsg 			      const struct dmub_region *outbox0)
3325ca02815Sjsg {
3335ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX0_BASE_ADDRESS, outbox0->base);
3345ca02815Sjsg 
3355ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX0_SIZE, outbox0->top - outbox0->base);
3365ca02815Sjsg }
3375ca02815Sjsg 
dmub_dcn20_get_outbox0_wptr(struct dmub_srv * dmub)3385ca02815Sjsg uint32_t dmub_dcn20_get_outbox0_wptr(struct dmub_srv *dmub)
3395ca02815Sjsg {
3405ca02815Sjsg 	return REG_READ(DMCUB_OUTBOX0_WPTR);
3415ca02815Sjsg }
3425ca02815Sjsg 
dmub_dcn20_set_outbox0_rptr(struct dmub_srv * dmub,uint32_t rptr_offset)3435ca02815Sjsg void dmub_dcn20_set_outbox0_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
3445ca02815Sjsg {
3455ca02815Sjsg 	REG_WRITE(DMCUB_OUTBOX0_RPTR, rptr_offset);
3465ca02815Sjsg }
3475ca02815Sjsg 
dmub_dcn20_is_hw_init(struct dmub_srv * dmub)348c349dbc7Sjsg bool dmub_dcn20_is_hw_init(struct dmub_srv *dmub)
349c349dbc7Sjsg {
350ad8b1aafSjsg 	uint32_t is_hw_init;
351ad8b1aafSjsg 
352ad8b1aafSjsg 	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
353ad8b1aafSjsg 
354ad8b1aafSjsg 	return is_hw_init != 0;
355c349dbc7Sjsg }
356c349dbc7Sjsg 
dmub_dcn20_is_supported(struct dmub_srv * dmub)357c349dbc7Sjsg bool dmub_dcn20_is_supported(struct dmub_srv *dmub)
358c349dbc7Sjsg {
359c349dbc7Sjsg 	uint32_t supported = 0;
360c349dbc7Sjsg 
361c349dbc7Sjsg 	REG_GET(CC_DC_PIPE_DIS, DC_DMCUB_ENABLE, &supported);
362c349dbc7Sjsg 
363c349dbc7Sjsg 	return supported;
364c349dbc7Sjsg }
365c349dbc7Sjsg 
dmub_dcn20_set_gpint(struct dmub_srv * dmub,union dmub_gpint_data_register reg)366c349dbc7Sjsg void dmub_dcn20_set_gpint(struct dmub_srv *dmub,
367c349dbc7Sjsg 			  union dmub_gpint_data_register reg)
368c349dbc7Sjsg {
369c349dbc7Sjsg 	REG_WRITE(DMCUB_GPINT_DATAIN1, reg.all);
370c349dbc7Sjsg }
371c349dbc7Sjsg 
dmub_dcn20_is_gpint_acked(struct dmub_srv * dmub,union dmub_gpint_data_register reg)372c349dbc7Sjsg bool dmub_dcn20_is_gpint_acked(struct dmub_srv *dmub,
373c349dbc7Sjsg 			       union dmub_gpint_data_register reg)
374c349dbc7Sjsg {
375c349dbc7Sjsg 	union dmub_gpint_data_register test;
376c349dbc7Sjsg 
377c349dbc7Sjsg 	reg.bits.status = 0;
378c349dbc7Sjsg 	test.all = REG_READ(DMCUB_GPINT_DATAIN1);
379c349dbc7Sjsg 
380c349dbc7Sjsg 	return test.all == reg.all;
381c349dbc7Sjsg }
382c349dbc7Sjsg 
dmub_dcn20_get_gpint_response(struct dmub_srv * dmub)383c349dbc7Sjsg uint32_t dmub_dcn20_get_gpint_response(struct dmub_srv *dmub)
384c349dbc7Sjsg {
385c349dbc7Sjsg 	return REG_READ(DMCUB_SCRATCH7);
386c349dbc7Sjsg }
3875ca02815Sjsg 
dmub_dcn20_get_fw_boot_status(struct dmub_srv * dmub)3885ca02815Sjsg union dmub_fw_boot_status dmub_dcn20_get_fw_boot_status(struct dmub_srv *dmub)
3895ca02815Sjsg {
3905ca02815Sjsg 	union dmub_fw_boot_status status;
3915ca02815Sjsg 
3925ca02815Sjsg 	status.all = REG_READ(DMCUB_SCRATCH0);
3935ca02815Sjsg 	return status;
3945ca02815Sjsg }
3955ca02815Sjsg 
dmub_dcn20_enable_dmub_boot_options(struct dmub_srv * dmub,const struct dmub_srv_hw_params * params)3965ca02815Sjsg void dmub_dcn20_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params)
3975ca02815Sjsg {
3985ca02815Sjsg 	union dmub_fw_boot_options boot_options = {0};
3995ca02815Sjsg 
4005ca02815Sjsg 	REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
4015ca02815Sjsg }
4025ca02815Sjsg 
dmub_dcn20_skip_dmub_panel_power_sequence(struct dmub_srv * dmub,bool skip)4035ca02815Sjsg void dmub_dcn20_skip_dmub_panel_power_sequence(struct dmub_srv *dmub, bool skip)
4045ca02815Sjsg {
4055ca02815Sjsg 	union dmub_fw_boot_options boot_options;
4065ca02815Sjsg 	boot_options.all = REG_READ(DMCUB_SCRATCH14);
4075ca02815Sjsg 	boot_options.bits.skip_phy_init_panel_sequence = skip;
4085ca02815Sjsg 	REG_WRITE(DMCUB_SCRATCH14, boot_options.all);
4095ca02815Sjsg }
4105ca02815Sjsg 
dmub_dcn20_get_current_time(struct dmub_srv * dmub)4115ca02815Sjsg uint32_t dmub_dcn20_get_current_time(struct dmub_srv *dmub)
4125ca02815Sjsg {
4135ca02815Sjsg 	return REG_READ(DMCUB_TIMER_CURRENT);
4145ca02815Sjsg }
4155ca02815Sjsg 
dmub_dcn20_get_diagnostic_data(struct dmub_srv * dmub,struct dmub_diagnostic_data * diag_data)4165ca02815Sjsg void dmub_dcn20_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
4175ca02815Sjsg {
4185ca02815Sjsg 	uint32_t is_dmub_enabled, is_soft_reset, is_sec_reset;
4195ca02815Sjsg 	uint32_t is_traceport_enabled, is_cw0_enabled, is_cw6_enabled;
4205ca02815Sjsg 
4215ca02815Sjsg 	if (!dmub || !diag_data)
4225ca02815Sjsg 		return;
4235ca02815Sjsg 
4245ca02815Sjsg 	memset(diag_data, 0, sizeof(*diag_data));
4255ca02815Sjsg 
4265ca02815Sjsg 	diag_data->dmcub_version = dmub->fw_version;
4275ca02815Sjsg 
4285ca02815Sjsg 	diag_data->scratch[0] = REG_READ(DMCUB_SCRATCH0);
4295ca02815Sjsg 	diag_data->scratch[1] = REG_READ(DMCUB_SCRATCH1);
4305ca02815Sjsg 	diag_data->scratch[2] = REG_READ(DMCUB_SCRATCH2);
4315ca02815Sjsg 	diag_data->scratch[3] = REG_READ(DMCUB_SCRATCH3);
4325ca02815Sjsg 	diag_data->scratch[4] = REG_READ(DMCUB_SCRATCH4);
4335ca02815Sjsg 	diag_data->scratch[5] = REG_READ(DMCUB_SCRATCH5);
4345ca02815Sjsg 	diag_data->scratch[6] = REG_READ(DMCUB_SCRATCH6);
4355ca02815Sjsg 	diag_data->scratch[7] = REG_READ(DMCUB_SCRATCH7);
4365ca02815Sjsg 	diag_data->scratch[8] = REG_READ(DMCUB_SCRATCH8);
4375ca02815Sjsg 	diag_data->scratch[9] = REG_READ(DMCUB_SCRATCH9);
4385ca02815Sjsg 	diag_data->scratch[10] = REG_READ(DMCUB_SCRATCH10);
4395ca02815Sjsg 	diag_data->scratch[11] = REG_READ(DMCUB_SCRATCH11);
4405ca02815Sjsg 	diag_data->scratch[12] = REG_READ(DMCUB_SCRATCH12);
4415ca02815Sjsg 	diag_data->scratch[13] = REG_READ(DMCUB_SCRATCH13);
4425ca02815Sjsg 	diag_data->scratch[14] = REG_READ(DMCUB_SCRATCH14);
4435ca02815Sjsg 	diag_data->scratch[15] = REG_READ(DMCUB_SCRATCH15);
4445ca02815Sjsg 
4455ca02815Sjsg 	diag_data->undefined_address_fault_addr = REG_READ(DMCUB_UNDEFINED_ADDRESS_FAULT_ADDR);
4465ca02815Sjsg 	diag_data->inst_fetch_fault_addr = REG_READ(DMCUB_INST_FETCH_FAULT_ADDR);
4475ca02815Sjsg 	diag_data->data_write_fault_addr = REG_READ(DMCUB_DATA_WRITE_FAULT_ADDR);
4485ca02815Sjsg 
4495ca02815Sjsg 	diag_data->inbox1_rptr = REG_READ(DMCUB_INBOX1_RPTR);
4505ca02815Sjsg 	diag_data->inbox1_wptr = REG_READ(DMCUB_INBOX1_WPTR);
4515ca02815Sjsg 	diag_data->inbox1_size = REG_READ(DMCUB_INBOX1_SIZE);
4525ca02815Sjsg 
4535ca02815Sjsg 	diag_data->inbox0_rptr = REG_READ(DMCUB_INBOX0_RPTR);
4545ca02815Sjsg 	diag_data->inbox0_wptr = REG_READ(DMCUB_INBOX0_WPTR);
4555ca02815Sjsg 	diag_data->inbox0_size = REG_READ(DMCUB_INBOX0_SIZE);
4565ca02815Sjsg 
4575ca02815Sjsg 	REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_dmub_enabled);
4585ca02815Sjsg 	diag_data->is_dmcub_enabled = is_dmub_enabled;
4595ca02815Sjsg 
4605ca02815Sjsg 	REG_GET(DMCUB_CNTL, DMCUB_SOFT_RESET, &is_soft_reset);
4615ca02815Sjsg 	diag_data->is_dmcub_soft_reset = is_soft_reset;
4625ca02815Sjsg 
4635ca02815Sjsg 	REG_GET(DMCUB_SEC_CNTL, DMCUB_SEC_RESET_STATUS, &is_sec_reset);
4645ca02815Sjsg 	diag_data->is_dmcub_secure_reset = is_sec_reset;
4655ca02815Sjsg 
4665ca02815Sjsg 	REG_GET(DMCUB_CNTL, DMCUB_TRACEPORT_EN, &is_traceport_enabled);
4675ca02815Sjsg 	diag_data->is_traceport_en  = is_traceport_enabled;
4685ca02815Sjsg 
4695ca02815Sjsg 	REG_GET(DMCUB_REGION3_CW0_TOP_ADDRESS, DMCUB_REGION3_CW0_ENABLE, &is_cw0_enabled);
4705ca02815Sjsg 	diag_data->is_cw0_enabled = is_cw0_enabled;
4715ca02815Sjsg 
4725ca02815Sjsg 	REG_GET(DMCUB_REGION3_CW6_TOP_ADDRESS, DMCUB_REGION3_CW6_ENABLE, &is_cw6_enabled);
4735ca02815Sjsg 	diag_data->is_cw6_enabled = is_cw6_enabled;
4745ca02815Sjsg }
475