xref: /openbsd-src/sys/dev/pci/drm/amd/display/dmub/src/dmub_srv.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
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_dcn20.h"
28c349dbc7Sjsg #include "dmub_dcn21.h"
29ad8b1aafSjsg #include "dmub_cmd.h"
30ad8b1aafSjsg #include "dmub_dcn30.h"
315ca02815Sjsg #include "dmub_dcn301.h"
325ca02815Sjsg #include "dmub_dcn302.h"
335ca02815Sjsg #include "dmub_dcn303.h"
345ca02815Sjsg #include "dmub_dcn31.h"
353f3e4deaSjsg #include "dmub_dcn314.h"
361bb76ff1Sjsg #include "dmub_dcn315.h"
371bb76ff1Sjsg #include "dmub_dcn316.h"
381bb76ff1Sjsg #include "dmub_dcn32.h"
39c349dbc7Sjsg #include "os_types.h"
40c349dbc7Sjsg /*
41c349dbc7Sjsg  * Note: the DMUB service is standalone. No additional headers should be
42c349dbc7Sjsg  * added below or above this line unless they reside within the DMUB
43c349dbc7Sjsg  * folder.
44c349dbc7Sjsg  */
45c349dbc7Sjsg 
46c349dbc7Sjsg /* Alignment for framebuffer memory. */
47c349dbc7Sjsg #define DMUB_FB_ALIGNMENT (1024 * 1024)
48c349dbc7Sjsg 
49c349dbc7Sjsg /* Stack size. */
50c349dbc7Sjsg #define DMUB_STACK_SIZE (128 * 1024)
51c349dbc7Sjsg 
52c349dbc7Sjsg /* Context size. */
53c349dbc7Sjsg #define DMUB_CONTEXT_SIZE (512 * 1024)
54c349dbc7Sjsg 
555ca02815Sjsg /* Mailbox size : Ring buffers are required for both inbox and outbox */
565ca02815Sjsg #define DMUB_MAILBOX_SIZE ((2 * DMUB_RB_SIZE))
57c349dbc7Sjsg 
58c349dbc7Sjsg /* Default state size if meta is absent. */
59ad8b1aafSjsg #define DMUB_FW_STATE_SIZE (64 * 1024)
60c349dbc7Sjsg 
61c349dbc7Sjsg /* Default tracebuffer size if meta is absent. */
62ad8b1aafSjsg #define DMUB_TRACE_BUFFER_SIZE (64 * 1024)
63c349dbc7Sjsg 
645ca02815Sjsg 
65c349dbc7Sjsg /* Default scratch mem size. */
66c349dbc7Sjsg #define DMUB_SCRATCH_MEM_SIZE (256)
67c349dbc7Sjsg 
68c349dbc7Sjsg /* Number of windows in use. */
69c349dbc7Sjsg #define DMUB_NUM_WINDOWS (DMUB_WINDOW_TOTAL)
70c349dbc7Sjsg /* Base addresses. */
71c349dbc7Sjsg 
72c349dbc7Sjsg #define DMUB_CW0_BASE (0x60000000)
73c349dbc7Sjsg #define DMUB_CW1_BASE (0x61000000)
74c349dbc7Sjsg #define DMUB_CW3_BASE (0x63000000)
75ad8b1aafSjsg #define DMUB_CW4_BASE (0x64000000)
76c349dbc7Sjsg #define DMUB_CW5_BASE (0x65000000)
77c349dbc7Sjsg #define DMUB_CW6_BASE (0x66000000)
78c349dbc7Sjsg 
795ca02815Sjsg #define DMUB_REGION5_BASE (0xA0000000)
805ca02815Sjsg 
dmub_align(uint32_t val,uint32_t factor)81c349dbc7Sjsg static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
82c349dbc7Sjsg {
83c349dbc7Sjsg 	return (val + factor - 1) / factor * factor;
84c349dbc7Sjsg }
85c349dbc7Sjsg 
dmub_flush_buffer_mem(const struct dmub_fb * fb)86ad8b1aafSjsg void dmub_flush_buffer_mem(const struct dmub_fb *fb)
87c349dbc7Sjsg {
88c349dbc7Sjsg 	const uint8_t *base = (const uint8_t *)fb->cpu_addr;
89c349dbc7Sjsg 	uint8_t buf[64];
90c349dbc7Sjsg 	uint32_t pos, end;
91c349dbc7Sjsg 
92c349dbc7Sjsg 	/**
93c349dbc7Sjsg 	 * Read 64-byte chunks since we don't want to store a
94c349dbc7Sjsg 	 * large temporary buffer for this purpose.
95c349dbc7Sjsg 	 */
96c349dbc7Sjsg 	end = fb->size / sizeof(buf) * sizeof(buf);
97c349dbc7Sjsg 
98c349dbc7Sjsg 	for (pos = 0; pos < end; pos += sizeof(buf))
99c349dbc7Sjsg 		dmub_memcpy(buf, base + pos, sizeof(buf));
100c349dbc7Sjsg 
101c349dbc7Sjsg 	/* Read anything leftover into the buffer. */
102c349dbc7Sjsg 	if (end < fb->size)
103c349dbc7Sjsg 		dmub_memcpy(buf, base + pos, fb->size - end);
104c349dbc7Sjsg }
105c349dbc7Sjsg 
106c349dbc7Sjsg static const struct dmub_fw_meta_info *
dmub_get_fw_meta_info_from_blob(const uint8_t * blob,uint32_t blob_size,uint32_t meta_offset)1071bb76ff1Sjsg dmub_get_fw_meta_info_from_blob(const uint8_t *blob, uint32_t blob_size, uint32_t meta_offset)
108c349dbc7Sjsg {
109c349dbc7Sjsg 	const union dmub_fw_meta *meta;
110ad8b1aafSjsg 
111ad8b1aafSjsg 	if (!blob || !blob_size)
112c349dbc7Sjsg 		return NULL;
113c349dbc7Sjsg 
114ad8b1aafSjsg 	if (blob_size < sizeof(union dmub_fw_meta) + meta_offset)
115c349dbc7Sjsg 		return NULL;
116c349dbc7Sjsg 
117ad8b1aafSjsg 	meta = (const union dmub_fw_meta *)(blob + blob_size - meta_offset -
118c349dbc7Sjsg 					    sizeof(union dmub_fw_meta));
119c349dbc7Sjsg 
120c349dbc7Sjsg 	if (meta->info.magic_value != DMUB_FW_META_MAGIC)
121c349dbc7Sjsg 		return NULL;
122c349dbc7Sjsg 
123c349dbc7Sjsg 	return &meta->info;
124c349dbc7Sjsg }
125c349dbc7Sjsg 
1261bb76ff1Sjsg static const struct dmub_fw_meta_info *
dmub_get_fw_meta_info(const struct dmub_srv_region_params * params)1271bb76ff1Sjsg dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
1281bb76ff1Sjsg {
1291bb76ff1Sjsg 	const struct dmub_fw_meta_info *info = NULL;
1301bb76ff1Sjsg 
1311bb76ff1Sjsg 	if (params->fw_bss_data && params->bss_data_size) {
1321bb76ff1Sjsg 		/* Legacy metadata region. */
1331bb76ff1Sjsg 		info = dmub_get_fw_meta_info_from_blob(params->fw_bss_data,
1341bb76ff1Sjsg 						       params->bss_data_size,
1351bb76ff1Sjsg 						       DMUB_FW_META_OFFSET);
1361bb76ff1Sjsg 	} else if (params->fw_inst_const && params->inst_const_size) {
1371bb76ff1Sjsg 		/* Combined metadata region - can be aligned to 16-bytes. */
1381bb76ff1Sjsg 		uint32_t i;
1391bb76ff1Sjsg 
1401bb76ff1Sjsg 		for (i = 0; i < 16; ++i) {
1411bb76ff1Sjsg 			info = dmub_get_fw_meta_info_from_blob(
1421bb76ff1Sjsg 				params->fw_inst_const, params->inst_const_size, i);
1431bb76ff1Sjsg 
1441bb76ff1Sjsg 			if (info)
1451bb76ff1Sjsg 				break;
1461bb76ff1Sjsg 		}
1471bb76ff1Sjsg 	}
1481bb76ff1Sjsg 
1491bb76ff1Sjsg 	return info;
1501bb76ff1Sjsg }
1511bb76ff1Sjsg 
dmub_srv_hw_setup(struct dmub_srv * dmub,enum dmub_asic asic)152c349dbc7Sjsg static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
153c349dbc7Sjsg {
154c349dbc7Sjsg 	struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs;
155c349dbc7Sjsg 
156c349dbc7Sjsg 	switch (asic) {
157c349dbc7Sjsg 	case DMUB_ASIC_DCN20:
158c349dbc7Sjsg 	case DMUB_ASIC_DCN21:
159ad8b1aafSjsg 	case DMUB_ASIC_DCN30:
1605ca02815Sjsg 	case DMUB_ASIC_DCN301:
1615ca02815Sjsg 	case DMUB_ASIC_DCN302:
1625ca02815Sjsg 	case DMUB_ASIC_DCN303:
163c349dbc7Sjsg 		dmub->regs = &dmub_srv_dcn20_regs;
164c349dbc7Sjsg 
165c349dbc7Sjsg 		funcs->reset = dmub_dcn20_reset;
166c349dbc7Sjsg 		funcs->reset_release = dmub_dcn20_reset_release;
167c349dbc7Sjsg 		funcs->backdoor_load = dmub_dcn20_backdoor_load;
168c349dbc7Sjsg 		funcs->setup_windows = dmub_dcn20_setup_windows;
169c349dbc7Sjsg 		funcs->setup_mailbox = dmub_dcn20_setup_mailbox;
17069703a93Sjsg 		funcs->get_inbox1_wptr = dmub_dcn20_get_inbox1_wptr;
171c349dbc7Sjsg 		funcs->get_inbox1_rptr = dmub_dcn20_get_inbox1_rptr;
172c349dbc7Sjsg 		funcs->set_inbox1_wptr = dmub_dcn20_set_inbox1_wptr;
173c349dbc7Sjsg 		funcs->is_supported = dmub_dcn20_is_supported;
174c349dbc7Sjsg 		funcs->is_hw_init = dmub_dcn20_is_hw_init;
175c349dbc7Sjsg 		funcs->set_gpint = dmub_dcn20_set_gpint;
176c349dbc7Sjsg 		funcs->is_gpint_acked = dmub_dcn20_is_gpint_acked;
177c349dbc7Sjsg 		funcs->get_gpint_response = dmub_dcn20_get_gpint_response;
1785ca02815Sjsg 		funcs->get_fw_status = dmub_dcn20_get_fw_boot_status;
1795ca02815Sjsg 		funcs->enable_dmub_boot_options = dmub_dcn20_enable_dmub_boot_options;
1805ca02815Sjsg 		funcs->skip_dmub_panel_power_sequence = dmub_dcn20_skip_dmub_panel_power_sequence;
1815ca02815Sjsg 		funcs->get_current_time = dmub_dcn20_get_current_time;
1825ca02815Sjsg 
1835ca02815Sjsg 		// Out mailbox register access functions for RN and above
1845ca02815Sjsg 		funcs->setup_out_mailbox = dmub_dcn20_setup_out_mailbox;
1855ca02815Sjsg 		funcs->get_outbox1_wptr = dmub_dcn20_get_outbox1_wptr;
1865ca02815Sjsg 		funcs->set_outbox1_rptr = dmub_dcn20_set_outbox1_rptr;
1875ca02815Sjsg 
1885ca02815Sjsg 		//outbox0 call stacks
1895ca02815Sjsg 		funcs->setup_outbox0 = dmub_dcn20_setup_outbox0;
1905ca02815Sjsg 		funcs->get_outbox0_wptr = dmub_dcn20_get_outbox0_wptr;
1915ca02815Sjsg 		funcs->set_outbox0_rptr = dmub_dcn20_set_outbox0_rptr;
1925ca02815Sjsg 
1935ca02815Sjsg 		funcs->get_diagnostic_data = dmub_dcn20_get_diagnostic_data;
194c349dbc7Sjsg 
195*f005ef32Sjsg 		if (asic == DMUB_ASIC_DCN21)
196c349dbc7Sjsg 			dmub->regs = &dmub_srv_dcn21_regs;
197c349dbc7Sjsg 
198ad8b1aafSjsg 		if (asic == DMUB_ASIC_DCN30) {
199ad8b1aafSjsg 			dmub->regs = &dmub_srv_dcn30_regs;
200ad8b1aafSjsg 
201ad8b1aafSjsg 			funcs->backdoor_load = dmub_dcn30_backdoor_load;
202ad8b1aafSjsg 			funcs->setup_windows = dmub_dcn30_setup_windows;
203ad8b1aafSjsg 		}
2045ca02815Sjsg 		if (asic == DMUB_ASIC_DCN301) {
2055ca02815Sjsg 			dmub->regs = &dmub_srv_dcn301_regs;
2065ca02815Sjsg 
2075ca02815Sjsg 			funcs->backdoor_load = dmub_dcn30_backdoor_load;
2085ca02815Sjsg 			funcs->setup_windows = dmub_dcn30_setup_windows;
2095ca02815Sjsg 		}
2105ca02815Sjsg 		if (asic == DMUB_ASIC_DCN302) {
2115ca02815Sjsg 			dmub->regs = &dmub_srv_dcn302_regs;
2125ca02815Sjsg 
2135ca02815Sjsg 			funcs->backdoor_load = dmub_dcn30_backdoor_load;
2145ca02815Sjsg 			funcs->setup_windows = dmub_dcn30_setup_windows;
2155ca02815Sjsg 		}
2165ca02815Sjsg 		if (asic == DMUB_ASIC_DCN303) {
2175ca02815Sjsg 			dmub->regs = &dmub_srv_dcn303_regs;
2185ca02815Sjsg 
2195ca02815Sjsg 			funcs->backdoor_load = dmub_dcn30_backdoor_load;
2205ca02815Sjsg 			funcs->setup_windows = dmub_dcn30_setup_windows;
2215ca02815Sjsg 		}
2225ca02815Sjsg 		break;
2235ca02815Sjsg 
2245ca02815Sjsg 	case DMUB_ASIC_DCN31:
2251bb76ff1Sjsg 	case DMUB_ASIC_DCN31B:
2261bb76ff1Sjsg 	case DMUB_ASIC_DCN314:
2271bb76ff1Sjsg 	case DMUB_ASIC_DCN315:
2281bb76ff1Sjsg 	case DMUB_ASIC_DCN316:
2295dce7169Sjsg 		if (asic == DMUB_ASIC_DCN314) {
2303f3e4deaSjsg 			dmub->regs_dcn31 = &dmub_srv_dcn314_regs;
231a7a3e763Sjsg 			funcs->is_psrsu_supported = dmub_dcn314_is_psrsu_supported;
2325dce7169Sjsg 		} else if (asic == DMUB_ASIC_DCN315) {
2331bb76ff1Sjsg 			dmub->regs_dcn31 = &dmub_srv_dcn315_regs;
2345dce7169Sjsg 		} else if (asic == DMUB_ASIC_DCN316) {
2351bb76ff1Sjsg 			dmub->regs_dcn31 = &dmub_srv_dcn316_regs;
2365dce7169Sjsg 		} else {
2375ca02815Sjsg 			dmub->regs_dcn31 = &dmub_srv_dcn31_regs;
2385dce7169Sjsg 			funcs->is_psrsu_supported = dmub_dcn31_is_psrsu_supported;
2395dce7169Sjsg 		}
2405ca02815Sjsg 		funcs->reset = dmub_dcn31_reset;
2415ca02815Sjsg 		funcs->reset_release = dmub_dcn31_reset_release;
2425ca02815Sjsg 		funcs->backdoor_load = dmub_dcn31_backdoor_load;
2435ca02815Sjsg 		funcs->setup_windows = dmub_dcn31_setup_windows;
2445ca02815Sjsg 		funcs->setup_mailbox = dmub_dcn31_setup_mailbox;
24569703a93Sjsg 		funcs->get_inbox1_wptr = dmub_dcn31_get_inbox1_wptr;
2465ca02815Sjsg 		funcs->get_inbox1_rptr = dmub_dcn31_get_inbox1_rptr;
2475ca02815Sjsg 		funcs->set_inbox1_wptr = dmub_dcn31_set_inbox1_wptr;
2485ca02815Sjsg 		funcs->setup_out_mailbox = dmub_dcn31_setup_out_mailbox;
2495ca02815Sjsg 		funcs->get_outbox1_wptr = dmub_dcn31_get_outbox1_wptr;
2505ca02815Sjsg 		funcs->set_outbox1_rptr = dmub_dcn31_set_outbox1_rptr;
2515ca02815Sjsg 		funcs->is_supported = dmub_dcn31_is_supported;
2525ca02815Sjsg 		funcs->is_hw_init = dmub_dcn31_is_hw_init;
2535ca02815Sjsg 		funcs->set_gpint = dmub_dcn31_set_gpint;
2545ca02815Sjsg 		funcs->is_gpint_acked = dmub_dcn31_is_gpint_acked;
2555ca02815Sjsg 		funcs->get_gpint_response = dmub_dcn31_get_gpint_response;
2565ca02815Sjsg 		funcs->get_gpint_dataout = dmub_dcn31_get_gpint_dataout;
2575ca02815Sjsg 		funcs->get_fw_status = dmub_dcn31_get_fw_boot_status;
258*f005ef32Sjsg 		funcs->get_fw_boot_option = dmub_dcn31_get_fw_boot_option;
2595ca02815Sjsg 		funcs->enable_dmub_boot_options = dmub_dcn31_enable_dmub_boot_options;
2605ca02815Sjsg 		funcs->skip_dmub_panel_power_sequence = dmub_dcn31_skip_dmub_panel_power_sequence;
2615ca02815Sjsg 		//outbox0 call stacks
2625ca02815Sjsg 		funcs->setup_outbox0 = dmub_dcn31_setup_outbox0;
2635ca02815Sjsg 		funcs->get_outbox0_wptr = dmub_dcn31_get_outbox0_wptr;
2645ca02815Sjsg 		funcs->set_outbox0_rptr = dmub_dcn31_set_outbox0_rptr;
2655ca02815Sjsg 
2665ca02815Sjsg 		funcs->get_diagnostic_data = dmub_dcn31_get_diagnostic_data;
2671bb76ff1Sjsg 		funcs->should_detect = dmub_dcn31_should_detect;
2685ca02815Sjsg 		funcs->get_current_time = dmub_dcn31_get_current_time;
2695ca02815Sjsg 
270c349dbc7Sjsg 		break;
271c349dbc7Sjsg 
2721bb76ff1Sjsg 	case DMUB_ASIC_DCN32:
2731bb76ff1Sjsg 	case DMUB_ASIC_DCN321:
2741bb76ff1Sjsg 		dmub->regs_dcn32 = &dmub_srv_dcn32_regs;
2751bb76ff1Sjsg 		funcs->configure_dmub_in_system_memory = dmub_dcn32_configure_dmub_in_system_memory;
2761bb76ff1Sjsg 		funcs->send_inbox0_cmd = dmub_dcn32_send_inbox0_cmd;
2771bb76ff1Sjsg 		funcs->clear_inbox0_ack_register = dmub_dcn32_clear_inbox0_ack_register;
2781bb76ff1Sjsg 		funcs->read_inbox0_ack_register = dmub_dcn32_read_inbox0_ack_register;
2791bb76ff1Sjsg 		funcs->reset = dmub_dcn32_reset;
2801bb76ff1Sjsg 		funcs->reset_release = dmub_dcn32_reset_release;
2811bb76ff1Sjsg 		funcs->backdoor_load = dmub_dcn32_backdoor_load;
2821bb76ff1Sjsg 		funcs->backdoor_load_zfb_mode = dmub_dcn32_backdoor_load_zfb_mode;
2831bb76ff1Sjsg 		funcs->setup_windows = dmub_dcn32_setup_windows;
2841bb76ff1Sjsg 		funcs->setup_mailbox = dmub_dcn32_setup_mailbox;
28569703a93Sjsg 		funcs->get_inbox1_wptr = dmub_dcn32_get_inbox1_wptr;
2861bb76ff1Sjsg 		funcs->get_inbox1_rptr = dmub_dcn32_get_inbox1_rptr;
2871bb76ff1Sjsg 		funcs->set_inbox1_wptr = dmub_dcn32_set_inbox1_wptr;
2881bb76ff1Sjsg 		funcs->setup_out_mailbox = dmub_dcn32_setup_out_mailbox;
2891bb76ff1Sjsg 		funcs->get_outbox1_wptr = dmub_dcn32_get_outbox1_wptr;
2901bb76ff1Sjsg 		funcs->set_outbox1_rptr = dmub_dcn32_set_outbox1_rptr;
2911bb76ff1Sjsg 		funcs->is_supported = dmub_dcn32_is_supported;
2921bb76ff1Sjsg 		funcs->is_hw_init = dmub_dcn32_is_hw_init;
2931bb76ff1Sjsg 		funcs->set_gpint = dmub_dcn32_set_gpint;
2941bb76ff1Sjsg 		funcs->is_gpint_acked = dmub_dcn32_is_gpint_acked;
2951bb76ff1Sjsg 		funcs->get_gpint_response = dmub_dcn32_get_gpint_response;
2961bb76ff1Sjsg 		funcs->get_gpint_dataout = dmub_dcn32_get_gpint_dataout;
2971bb76ff1Sjsg 		funcs->get_fw_status = dmub_dcn32_get_fw_boot_status;
2981bb76ff1Sjsg 		funcs->enable_dmub_boot_options = dmub_dcn32_enable_dmub_boot_options;
2991bb76ff1Sjsg 		funcs->skip_dmub_panel_power_sequence = dmub_dcn32_skip_dmub_panel_power_sequence;
3001bb76ff1Sjsg 
3011bb76ff1Sjsg 		/* outbox0 call stacks */
3021bb76ff1Sjsg 		funcs->setup_outbox0 = dmub_dcn32_setup_outbox0;
3031bb76ff1Sjsg 		funcs->get_outbox0_wptr = dmub_dcn32_get_outbox0_wptr;
3041bb76ff1Sjsg 		funcs->set_outbox0_rptr = dmub_dcn32_set_outbox0_rptr;
3051bb76ff1Sjsg 		funcs->get_current_time = dmub_dcn32_get_current_time;
3061bb76ff1Sjsg 		funcs->get_diagnostic_data = dmub_dcn32_get_diagnostic_data;
3071bb76ff1Sjsg 
3081bb76ff1Sjsg 		break;
3091bb76ff1Sjsg 
310c349dbc7Sjsg 	default:
311c349dbc7Sjsg 		return false;
312c349dbc7Sjsg 	}
313c349dbc7Sjsg 
314c349dbc7Sjsg 	return true;
315c349dbc7Sjsg }
316c349dbc7Sjsg 
dmub_srv_create(struct dmub_srv * dmub,const struct dmub_srv_create_params * params)317c349dbc7Sjsg enum dmub_status dmub_srv_create(struct dmub_srv *dmub,
318c349dbc7Sjsg 				 const struct dmub_srv_create_params *params)
319c349dbc7Sjsg {
320c349dbc7Sjsg 	enum dmub_status status = DMUB_STATUS_OK;
321c349dbc7Sjsg 
322c349dbc7Sjsg 	dmub_memset(dmub, 0, sizeof(*dmub));
323c349dbc7Sjsg 
324c349dbc7Sjsg 	dmub->funcs = params->funcs;
325c349dbc7Sjsg 	dmub->user_ctx = params->user_ctx;
326c349dbc7Sjsg 	dmub->asic = params->asic;
327ad8b1aafSjsg 	dmub->fw_version = params->fw_version;
328c349dbc7Sjsg 	dmub->is_virtual = params->is_virtual;
329c349dbc7Sjsg 
330c349dbc7Sjsg 	/* Setup asic dependent hardware funcs. */
331c349dbc7Sjsg 	if (!dmub_srv_hw_setup(dmub, params->asic)) {
332c349dbc7Sjsg 		status = DMUB_STATUS_INVALID;
333c349dbc7Sjsg 		goto cleanup;
334c349dbc7Sjsg 	}
335c349dbc7Sjsg 
336c349dbc7Sjsg 	/* Override (some) hardware funcs based on user params. */
337c349dbc7Sjsg 	if (params->hw_funcs) {
338ad8b1aafSjsg 		if (params->hw_funcs->emul_get_inbox1_rptr)
339ad8b1aafSjsg 			dmub->hw_funcs.emul_get_inbox1_rptr =
340ad8b1aafSjsg 				params->hw_funcs->emul_get_inbox1_rptr;
341c349dbc7Sjsg 
342ad8b1aafSjsg 		if (params->hw_funcs->emul_set_inbox1_wptr)
343ad8b1aafSjsg 			dmub->hw_funcs.emul_set_inbox1_wptr =
344ad8b1aafSjsg 				params->hw_funcs->emul_set_inbox1_wptr;
345c349dbc7Sjsg 
346c349dbc7Sjsg 		if (params->hw_funcs->is_supported)
347c349dbc7Sjsg 			dmub->hw_funcs.is_supported =
348c349dbc7Sjsg 				params->hw_funcs->is_supported;
349c349dbc7Sjsg 	}
350c349dbc7Sjsg 
351c349dbc7Sjsg 	/* Sanity checks for required hw func pointers. */
352c349dbc7Sjsg 	if (!dmub->hw_funcs.get_inbox1_rptr ||
353c349dbc7Sjsg 	    !dmub->hw_funcs.set_inbox1_wptr) {
354c349dbc7Sjsg 		status = DMUB_STATUS_INVALID;
355c349dbc7Sjsg 		goto cleanup;
356c349dbc7Sjsg 	}
357c349dbc7Sjsg 
358c349dbc7Sjsg cleanup:
359c349dbc7Sjsg 	if (status == DMUB_STATUS_OK)
360c349dbc7Sjsg 		dmub->sw_init = true;
361c349dbc7Sjsg 	else
362c349dbc7Sjsg 		dmub_srv_destroy(dmub);
363c349dbc7Sjsg 
364c349dbc7Sjsg 	return status;
365c349dbc7Sjsg }
366c349dbc7Sjsg 
dmub_srv_destroy(struct dmub_srv * dmub)367c349dbc7Sjsg void dmub_srv_destroy(struct dmub_srv *dmub)
368c349dbc7Sjsg {
369c349dbc7Sjsg 	dmub_memset(dmub, 0, sizeof(*dmub));
370c349dbc7Sjsg }
371c349dbc7Sjsg 
372c349dbc7Sjsg enum dmub_status
dmub_srv_calc_region_info(struct dmub_srv * dmub,const struct dmub_srv_region_params * params,struct dmub_srv_region_info * out)373c349dbc7Sjsg dmub_srv_calc_region_info(struct dmub_srv *dmub,
374c349dbc7Sjsg 			  const struct dmub_srv_region_params *params,
375c349dbc7Sjsg 			  struct dmub_srv_region_info *out)
376c349dbc7Sjsg {
377c349dbc7Sjsg 	struct dmub_region *inst = &out->regions[DMUB_WINDOW_0_INST_CONST];
378c349dbc7Sjsg 	struct dmub_region *stack = &out->regions[DMUB_WINDOW_1_STACK];
379c349dbc7Sjsg 	struct dmub_region *data = &out->regions[DMUB_WINDOW_2_BSS_DATA];
380c349dbc7Sjsg 	struct dmub_region *bios = &out->regions[DMUB_WINDOW_3_VBIOS];
381c349dbc7Sjsg 	struct dmub_region *mail = &out->regions[DMUB_WINDOW_4_MAILBOX];
382c349dbc7Sjsg 	struct dmub_region *trace_buff = &out->regions[DMUB_WINDOW_5_TRACEBUFF];
383c349dbc7Sjsg 	struct dmub_region *fw_state = &out->regions[DMUB_WINDOW_6_FW_STATE];
384c349dbc7Sjsg 	struct dmub_region *scratch_mem = &out->regions[DMUB_WINDOW_7_SCRATCH_MEM];
385c349dbc7Sjsg 	const struct dmub_fw_meta_info *fw_info;
386c349dbc7Sjsg 	uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
387c349dbc7Sjsg 	uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
388c349dbc7Sjsg 	uint32_t scratch_mem_size = DMUB_SCRATCH_MEM_SIZE;
389cf95312aSjsg 	uint32_t previous_top = 0;
390c349dbc7Sjsg 	if (!dmub->sw_init)
391c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
392c349dbc7Sjsg 
393c349dbc7Sjsg 	memset(out, 0, sizeof(*out));
394c349dbc7Sjsg 
395c349dbc7Sjsg 	out->num_regions = DMUB_NUM_WINDOWS;
396c349dbc7Sjsg 
397c349dbc7Sjsg 	inst->base = 0x0;
398c349dbc7Sjsg 	inst->top = inst->base + params->inst_const_size;
399c349dbc7Sjsg 
400c349dbc7Sjsg 	data->base = dmub_align(inst->top, 256);
401c349dbc7Sjsg 	data->top = data->base + params->bss_data_size;
402c349dbc7Sjsg 
403c349dbc7Sjsg 	/*
404c349dbc7Sjsg 	 * All cache windows below should be aligned to the size
405c349dbc7Sjsg 	 * of the DMCUB cache line, 64 bytes.
406c349dbc7Sjsg 	 */
407c349dbc7Sjsg 
408c349dbc7Sjsg 	stack->base = dmub_align(data->top, 256);
409c349dbc7Sjsg 	stack->top = stack->base + DMUB_STACK_SIZE + DMUB_CONTEXT_SIZE;
410c349dbc7Sjsg 
411c349dbc7Sjsg 	bios->base = dmub_align(stack->top, 256);
412c349dbc7Sjsg 	bios->top = bios->base + params->vbios_size;
413c349dbc7Sjsg 
414cf95312aSjsg 	if (params->is_mailbox_in_inbox) {
415cf95312aSjsg 		mail->base = 0;
416cf95312aSjsg 		mail->top = mail->base + DMUB_MAILBOX_SIZE;
417cf95312aSjsg 		previous_top = bios->top;
418cf95312aSjsg 	} else {
419c349dbc7Sjsg 		mail->base = dmub_align(bios->top, 256);
420c349dbc7Sjsg 		mail->top = mail->base + DMUB_MAILBOX_SIZE;
421cf95312aSjsg 		previous_top = mail->top;
422cf95312aSjsg 	}
423c349dbc7Sjsg 
424ad8b1aafSjsg 	fw_info = dmub_get_fw_meta_info(params);
425c349dbc7Sjsg 
426c349dbc7Sjsg 	if (fw_info) {
427c349dbc7Sjsg 		fw_state_size = fw_info->fw_region_size;
428c349dbc7Sjsg 		trace_buffer_size = fw_info->trace_buffer_size;
429ad8b1aafSjsg 
430ad8b1aafSjsg 		/**
431ad8b1aafSjsg 		 * If DM didn't fill in a version, then fill it in based on
432ad8b1aafSjsg 		 * the firmware meta now that we have it.
433ad8b1aafSjsg 		 *
434ad8b1aafSjsg 		 * TODO: Make it easier for driver to extract this out to
435ad8b1aafSjsg 		 * pass during creation.
436ad8b1aafSjsg 		 */
437ad8b1aafSjsg 		if (dmub->fw_version == 0)
438ad8b1aafSjsg 			dmub->fw_version = fw_info->fw_version;
439c349dbc7Sjsg 	}
440c349dbc7Sjsg 
441cf95312aSjsg 	trace_buff->base = dmub_align(previous_top, 256);
442c349dbc7Sjsg 	trace_buff->top = trace_buff->base + dmub_align(trace_buffer_size, 64);
443c349dbc7Sjsg 
444c349dbc7Sjsg 	fw_state->base = dmub_align(trace_buff->top, 256);
445c349dbc7Sjsg 	fw_state->top = fw_state->base + dmub_align(fw_state_size, 64);
446c349dbc7Sjsg 
447c349dbc7Sjsg 	scratch_mem->base = dmub_align(fw_state->top, 256);
448c349dbc7Sjsg 	scratch_mem->top = scratch_mem->base + dmub_align(scratch_mem_size, 64);
449c349dbc7Sjsg 
450c349dbc7Sjsg 	out->fb_size = dmub_align(scratch_mem->top, 4096);
451c349dbc7Sjsg 
452cf95312aSjsg 	if (params->is_mailbox_in_inbox)
453cf95312aSjsg 		out->inbox_size = dmub_align(mail->top, 4096);
454cf95312aSjsg 
455c349dbc7Sjsg 	return DMUB_STATUS_OK;
456c349dbc7Sjsg }
457c349dbc7Sjsg 
dmub_srv_calc_mem_info(struct dmub_srv * dmub,const struct dmub_srv_memory_params * params,struct dmub_srv_fb_info * out)458cf95312aSjsg enum dmub_status dmub_srv_calc_mem_info(struct dmub_srv *dmub,
459cf95312aSjsg 				       const struct dmub_srv_memory_params *params,
460c349dbc7Sjsg 				       struct dmub_srv_fb_info *out)
461c349dbc7Sjsg {
462c349dbc7Sjsg 	uint8_t *cpu_base;
463c349dbc7Sjsg 	uint64_t gpu_base;
464c349dbc7Sjsg 	uint32_t i;
465c349dbc7Sjsg 
466c349dbc7Sjsg 	if (!dmub->sw_init)
467c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
468c349dbc7Sjsg 
469c349dbc7Sjsg 	memset(out, 0, sizeof(*out));
470c349dbc7Sjsg 
471c349dbc7Sjsg 	if (params->region_info->num_regions != DMUB_NUM_WINDOWS)
472c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
473c349dbc7Sjsg 
474cf95312aSjsg 	cpu_base = (uint8_t *)params->cpu_fb_addr;
475cf95312aSjsg 	gpu_base = params->gpu_fb_addr;
476c349dbc7Sjsg 
477c349dbc7Sjsg 	for (i = 0; i < DMUB_NUM_WINDOWS; ++i) {
478c349dbc7Sjsg 		const struct dmub_region *reg =
479c349dbc7Sjsg 			&params->region_info->regions[i];
480c349dbc7Sjsg 
481c349dbc7Sjsg 		out->fb[i].cpu_addr = cpu_base + reg->base;
482c349dbc7Sjsg 		out->fb[i].gpu_addr = gpu_base + reg->base;
483cf95312aSjsg 
484cf95312aSjsg 		if (i == DMUB_WINDOW_4_MAILBOX && params->cpu_inbox_addr != 0) {
485cf95312aSjsg 			out->fb[i].cpu_addr = (uint8_t *)params->cpu_inbox_addr + reg->base;
486cf95312aSjsg 			out->fb[i].gpu_addr = params->gpu_inbox_addr + reg->base;
487cf95312aSjsg 		}
488cf95312aSjsg 
489c349dbc7Sjsg 		out->fb[i].size = reg->top - reg->base;
490c349dbc7Sjsg 	}
491c349dbc7Sjsg 
492c349dbc7Sjsg 	out->num_fb = DMUB_NUM_WINDOWS;
493c349dbc7Sjsg 
494c349dbc7Sjsg 	return DMUB_STATUS_OK;
495c349dbc7Sjsg }
496c349dbc7Sjsg 
dmub_srv_has_hw_support(struct dmub_srv * dmub,bool * is_supported)497c349dbc7Sjsg enum dmub_status dmub_srv_has_hw_support(struct dmub_srv *dmub,
498c349dbc7Sjsg 					 bool *is_supported)
499c349dbc7Sjsg {
500c349dbc7Sjsg 	*is_supported = false;
501c349dbc7Sjsg 
502c349dbc7Sjsg 	if (!dmub->sw_init)
503c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
504c349dbc7Sjsg 
505c349dbc7Sjsg 	if (dmub->hw_funcs.is_supported)
506c349dbc7Sjsg 		*is_supported = dmub->hw_funcs.is_supported(dmub);
507c349dbc7Sjsg 
508c349dbc7Sjsg 	return DMUB_STATUS_OK;
509c349dbc7Sjsg }
510c349dbc7Sjsg 
dmub_srv_is_hw_init(struct dmub_srv * dmub,bool * is_hw_init)511c349dbc7Sjsg enum dmub_status dmub_srv_is_hw_init(struct dmub_srv *dmub, bool *is_hw_init)
512c349dbc7Sjsg {
513c349dbc7Sjsg 	*is_hw_init = false;
514c349dbc7Sjsg 
515c349dbc7Sjsg 	if (!dmub->sw_init)
516c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
517c349dbc7Sjsg 
518c349dbc7Sjsg 	if (!dmub->hw_init)
519c349dbc7Sjsg 		return DMUB_STATUS_OK;
520c349dbc7Sjsg 
521c349dbc7Sjsg 	if (dmub->hw_funcs.is_hw_init)
522c349dbc7Sjsg 		*is_hw_init = dmub->hw_funcs.is_hw_init(dmub);
523c349dbc7Sjsg 
524c349dbc7Sjsg 	return DMUB_STATUS_OK;
525c349dbc7Sjsg }
526c349dbc7Sjsg 
dmub_srv_hw_init(struct dmub_srv * dmub,const struct dmub_srv_hw_params * params)527c349dbc7Sjsg enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
528c349dbc7Sjsg 				  const struct dmub_srv_hw_params *params)
529c349dbc7Sjsg {
530c349dbc7Sjsg 	struct dmub_fb *inst_fb = params->fb[DMUB_WINDOW_0_INST_CONST];
531c349dbc7Sjsg 	struct dmub_fb *stack_fb = params->fb[DMUB_WINDOW_1_STACK];
532c349dbc7Sjsg 	struct dmub_fb *data_fb = params->fb[DMUB_WINDOW_2_BSS_DATA];
533c349dbc7Sjsg 	struct dmub_fb *bios_fb = params->fb[DMUB_WINDOW_3_VBIOS];
534c349dbc7Sjsg 	struct dmub_fb *mail_fb = params->fb[DMUB_WINDOW_4_MAILBOX];
535c349dbc7Sjsg 	struct dmub_fb *tracebuff_fb = params->fb[DMUB_WINDOW_5_TRACEBUFF];
536c349dbc7Sjsg 	struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE];
537c349dbc7Sjsg 	struct dmub_fb *scratch_mem_fb = params->fb[DMUB_WINDOW_7_SCRATCH_MEM];
538c349dbc7Sjsg 
5395ca02815Sjsg 	struct dmub_rb_init_params rb_params, outbox0_rb_params;
540c349dbc7Sjsg 	struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6;
5415ca02815Sjsg 	struct dmub_region inbox1, outbox1, outbox0;
542c349dbc7Sjsg 
543c349dbc7Sjsg 	if (!dmub->sw_init)
544c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
545c349dbc7Sjsg 
5465ca02815Sjsg 	if (!inst_fb || !stack_fb || !data_fb || !bios_fb || !mail_fb ||
5475ca02815Sjsg 		!tracebuff_fb || !fw_state_fb || !scratch_mem_fb) {
5485ca02815Sjsg 		ASSERT(0);
5495ca02815Sjsg 		return DMUB_STATUS_INVALID;
5505ca02815Sjsg 	}
5515ca02815Sjsg 
552c349dbc7Sjsg 	dmub->fb_base = params->fb_base;
553c349dbc7Sjsg 	dmub->fb_offset = params->fb_offset;
554c349dbc7Sjsg 	dmub->psp_version = params->psp_version;
555c349dbc7Sjsg 
5565ca02815Sjsg 	if (dmub->hw_funcs.reset)
5575ca02815Sjsg 		dmub->hw_funcs.reset(dmub);
5585ca02815Sjsg 
5596150e708Sjsg 	/* reset the cache of the last wptr as well now that hw is reset */
5606150e708Sjsg 	dmub->inbox1_last_wptr = 0;
5616150e708Sjsg 
562c349dbc7Sjsg 	cw0.offset.quad_part = inst_fb->gpu_addr;
563c349dbc7Sjsg 	cw0.region.base = DMUB_CW0_BASE;
564c349dbc7Sjsg 	cw0.region.top = cw0.region.base + inst_fb->size - 1;
565c349dbc7Sjsg 
566c349dbc7Sjsg 	cw1.offset.quad_part = stack_fb->gpu_addr;
567c349dbc7Sjsg 	cw1.region.base = DMUB_CW1_BASE;
568c349dbc7Sjsg 	cw1.region.top = cw1.region.base + stack_fb->size - 1;
569c349dbc7Sjsg 
5701bb76ff1Sjsg 	if (params->fw_in_system_memory && dmub->hw_funcs.configure_dmub_in_system_memory)
5711bb76ff1Sjsg 		dmub->hw_funcs.configure_dmub_in_system_memory(dmub);
5721bb76ff1Sjsg 
5735ca02815Sjsg 	if (params->load_inst_const && dmub->hw_funcs.backdoor_load) {
574c349dbc7Sjsg 		/**
575c349dbc7Sjsg 		 * Read back all the instruction memory so we don't hang the
576c349dbc7Sjsg 		 * DMCUB when backdoor loading if the write from x86 hasn't been
577c349dbc7Sjsg 		 * flushed yet. This only occurs in backdoor loading.
578c349dbc7Sjsg 		 */
579c349dbc7Sjsg 		dmub_flush_buffer_mem(inst_fb);
5801bb76ff1Sjsg 
5811bb76ff1Sjsg 		if (params->fw_in_system_memory && dmub->hw_funcs.backdoor_load_zfb_mode)
5821bb76ff1Sjsg 			dmub->hw_funcs.backdoor_load_zfb_mode(dmub, &cw0, &cw1);
5831bb76ff1Sjsg 		else
584c349dbc7Sjsg 			dmub->hw_funcs.backdoor_load(dmub, &cw0, &cw1);
585c349dbc7Sjsg 	}
586c349dbc7Sjsg 
587c349dbc7Sjsg 	cw2.offset.quad_part = data_fb->gpu_addr;
588c349dbc7Sjsg 	cw2.region.base = DMUB_CW0_BASE + inst_fb->size;
589c349dbc7Sjsg 	cw2.region.top = cw2.region.base + data_fb->size;
590c349dbc7Sjsg 
591c349dbc7Sjsg 	cw3.offset.quad_part = bios_fb->gpu_addr;
592c349dbc7Sjsg 	cw3.region.base = DMUB_CW3_BASE;
593c349dbc7Sjsg 	cw3.region.top = cw3.region.base + bios_fb->size;
594c349dbc7Sjsg 
595c349dbc7Sjsg 	cw4.offset.quad_part = mail_fb->gpu_addr;
596ad8b1aafSjsg 	cw4.region.base = DMUB_CW4_BASE;
597c349dbc7Sjsg 	cw4.region.top = cw4.region.base + mail_fb->size;
598c349dbc7Sjsg 
5995ca02815Sjsg 	/**
6005ca02815Sjsg 	 * Doubled the mailbox region to accomodate inbox and outbox.
6015ca02815Sjsg 	 * Note: Currently, currently total mailbox size is 16KB. It is split
6025ca02815Sjsg 	 * equally into 8KB between inbox and outbox. If this config is
6035ca02815Sjsg 	 * changed, then uncached base address configuration of outbox1
6045ca02815Sjsg 	 * has to be updated in funcs->setup_out_mailbox.
6055ca02815Sjsg 	 */
606c349dbc7Sjsg 	inbox1.base = cw4.region.base;
6075ca02815Sjsg 	inbox1.top = cw4.region.base + DMUB_RB_SIZE;
6085ca02815Sjsg 	outbox1.base = inbox1.top;
6095ca02815Sjsg 	outbox1.top = cw4.region.top;
610c349dbc7Sjsg 
611c349dbc7Sjsg 	cw5.offset.quad_part = tracebuff_fb->gpu_addr;
612c349dbc7Sjsg 	cw5.region.base = DMUB_CW5_BASE;
613c349dbc7Sjsg 	cw5.region.top = cw5.region.base + tracebuff_fb->size;
614c349dbc7Sjsg 
6155ca02815Sjsg 	outbox0.base = DMUB_REGION5_BASE + TRACE_BUFFER_ENTRY_OFFSET;
6165ca02815Sjsg 	outbox0.top = outbox0.base + tracebuff_fb->size - TRACE_BUFFER_ENTRY_OFFSET;
6175ca02815Sjsg 
618c349dbc7Sjsg 	cw6.offset.quad_part = fw_state_fb->gpu_addr;
619c349dbc7Sjsg 	cw6.region.base = DMUB_CW6_BASE;
620c349dbc7Sjsg 	cw6.region.top = cw6.region.base + fw_state_fb->size;
621c349dbc7Sjsg 
622c349dbc7Sjsg 	dmub->fw_state = fw_state_fb->cpu_addr;
623c349dbc7Sjsg 
624c349dbc7Sjsg 	dmub->scratch_mem_fb = *scratch_mem_fb;
625c349dbc7Sjsg 
626c349dbc7Sjsg 	if (dmub->hw_funcs.setup_windows)
6275ca02815Sjsg 		dmub->hw_funcs.setup_windows(dmub, &cw2, &cw3, &cw4, &cw5, &cw6);
6285ca02815Sjsg 
6295ca02815Sjsg 	if (dmub->hw_funcs.setup_outbox0)
6305ca02815Sjsg 		dmub->hw_funcs.setup_outbox0(dmub, &outbox0);
631c349dbc7Sjsg 
632c349dbc7Sjsg 	if (dmub->hw_funcs.setup_mailbox)
633c349dbc7Sjsg 		dmub->hw_funcs.setup_mailbox(dmub, &inbox1);
6345ca02815Sjsg 	if (dmub->hw_funcs.setup_out_mailbox)
6355ca02815Sjsg 		dmub->hw_funcs.setup_out_mailbox(dmub, &outbox1);
636c349dbc7Sjsg 
637c349dbc7Sjsg 	dmub_memset(&rb_params, 0, sizeof(rb_params));
638c349dbc7Sjsg 	rb_params.ctx = dmub;
639c349dbc7Sjsg 	rb_params.base_address = mail_fb->cpu_addr;
640c349dbc7Sjsg 	rb_params.capacity = DMUB_RB_SIZE;
641c349dbc7Sjsg 	dmub_rb_init(&dmub->inbox1_rb, &rb_params);
6425ca02815Sjsg 
6435ca02815Sjsg 	// Initialize outbox1 ring buffer
6445ca02815Sjsg 	rb_params.ctx = dmub;
6455ca02815Sjsg 	rb_params.base_address = (void *) ((uint8_t *) (mail_fb->cpu_addr) + DMUB_RB_SIZE);
6465ca02815Sjsg 	rb_params.capacity = DMUB_RB_SIZE;
6475ca02815Sjsg 	dmub_rb_init(&dmub->outbox1_rb, &rb_params);
6485ca02815Sjsg 
6495ca02815Sjsg 	dmub_memset(&outbox0_rb_params, 0, sizeof(outbox0_rb_params));
6505ca02815Sjsg 	outbox0_rb_params.ctx = dmub;
6515ca02815Sjsg 	outbox0_rb_params.base_address = (void *)((uintptr_t)(tracebuff_fb->cpu_addr) + TRACE_BUFFER_ENTRY_OFFSET);
6525ca02815Sjsg 	outbox0_rb_params.capacity = tracebuff_fb->size - dmub_align(TRACE_BUFFER_ENTRY_OFFSET, 64);
6535ca02815Sjsg 	dmub_rb_init(&dmub->outbox0_rb, &outbox0_rb_params);
6545ca02815Sjsg 
6555ca02815Sjsg 	/* Report to DMUB what features are supported by current driver */
6565ca02815Sjsg 	if (dmub->hw_funcs.enable_dmub_boot_options)
6575ca02815Sjsg 		dmub->hw_funcs.enable_dmub_boot_options(dmub, params);
658c349dbc7Sjsg 
659*f005ef32Sjsg 	if (dmub->hw_funcs.skip_dmub_panel_power_sequence && !dmub->is_virtual)
6601bb76ff1Sjsg 		dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub,
6611bb76ff1Sjsg 			params->skip_panel_power_sequence);
6621bb76ff1Sjsg 
663*f005ef32Sjsg 	if (dmub->hw_funcs.reset_release && !dmub->is_virtual)
664c349dbc7Sjsg 		dmub->hw_funcs.reset_release(dmub);
665c349dbc7Sjsg 
666c349dbc7Sjsg 	dmub->hw_init = true;
667c349dbc7Sjsg 
668c349dbc7Sjsg 	return DMUB_STATUS_OK;
669c349dbc7Sjsg }
670c349dbc7Sjsg 
dmub_srv_sync_inbox1(struct dmub_srv * dmub)67169703a93Sjsg enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub)
67269703a93Sjsg {
67369703a93Sjsg 	if (!dmub->sw_init)
67469703a93Sjsg 		return DMUB_STATUS_INVALID;
67569703a93Sjsg 
67669703a93Sjsg 	if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) {
6771c155a16Sjsg 		uint32_t rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
6781c155a16Sjsg 		uint32_t wptr = dmub->hw_funcs.get_inbox1_wptr(dmub);
6791c155a16Sjsg 
6801c155a16Sjsg 		if (rptr > dmub->inbox1_rb.capacity || wptr > dmub->inbox1_rb.capacity) {
6811c155a16Sjsg 			return DMUB_STATUS_HW_FAILURE;
6821c155a16Sjsg 		} else {
6831c155a16Sjsg 			dmub->inbox1_rb.rptr = rptr;
6841c155a16Sjsg 			dmub->inbox1_rb.wrpt = wptr;
68569703a93Sjsg 			dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
68669703a93Sjsg 		}
6871c155a16Sjsg 	}
68869703a93Sjsg 
68969703a93Sjsg 	return DMUB_STATUS_OK;
69069703a93Sjsg }
69169703a93Sjsg 
dmub_srv_hw_reset(struct dmub_srv * dmub)692c349dbc7Sjsg enum dmub_status dmub_srv_hw_reset(struct dmub_srv *dmub)
693c349dbc7Sjsg {
694c349dbc7Sjsg 	if (!dmub->sw_init)
695c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
696c349dbc7Sjsg 
697c349dbc7Sjsg 	if (dmub->hw_funcs.reset)
698c349dbc7Sjsg 		dmub->hw_funcs.reset(dmub);
699c349dbc7Sjsg 
7006150e708Sjsg 	/* mailboxes have been reset in hw, so reset the sw state as well */
7016150e708Sjsg 	dmub->inbox1_last_wptr = 0;
7026150e708Sjsg 	dmub->inbox1_rb.wrpt = 0;
7036150e708Sjsg 	dmub->inbox1_rb.rptr = 0;
7046150e708Sjsg 	dmub->outbox0_rb.wrpt = 0;
7056150e708Sjsg 	dmub->outbox0_rb.rptr = 0;
7066150e708Sjsg 	dmub->outbox1_rb.wrpt = 0;
7076150e708Sjsg 	dmub->outbox1_rb.rptr = 0;
7086150e708Sjsg 
709c349dbc7Sjsg 	dmub->hw_init = false;
710c349dbc7Sjsg 
711c349dbc7Sjsg 	return DMUB_STATUS_OK;
712c349dbc7Sjsg }
713c349dbc7Sjsg 
dmub_srv_cmd_queue(struct dmub_srv * dmub,const union dmub_rb_cmd * cmd)714c349dbc7Sjsg enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub,
715ad8b1aafSjsg 				    const union dmub_rb_cmd *cmd)
716c349dbc7Sjsg {
717c349dbc7Sjsg 	if (!dmub->hw_init)
718c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
719c349dbc7Sjsg 
7201c155a16Sjsg 	if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity ||
7211c155a16Sjsg 	    dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) {
7221c155a16Sjsg 		return DMUB_STATUS_HW_FAILURE;
7231c155a16Sjsg 	}
7241c155a16Sjsg 
725c349dbc7Sjsg 	if (dmub_rb_push_front(&dmub->inbox1_rb, cmd))
726c349dbc7Sjsg 		return DMUB_STATUS_OK;
727c349dbc7Sjsg 
728c349dbc7Sjsg 	return DMUB_STATUS_QUEUE_FULL;
729c349dbc7Sjsg }
730c349dbc7Sjsg 
dmub_srv_cmd_execute(struct dmub_srv * dmub)731c349dbc7Sjsg enum dmub_status dmub_srv_cmd_execute(struct dmub_srv *dmub)
732c349dbc7Sjsg {
7331bb76ff1Sjsg 	struct dmub_rb flush_rb;
7341bb76ff1Sjsg 
735c349dbc7Sjsg 	if (!dmub->hw_init)
736c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
737c349dbc7Sjsg 
738c349dbc7Sjsg 	/**
739c349dbc7Sjsg 	 * Read back all the queued commands to ensure that they've
740c349dbc7Sjsg 	 * been flushed to framebuffer memory. Otherwise DMCUB might
741c349dbc7Sjsg 	 * read back stale, fully invalid or partially invalid data.
742c349dbc7Sjsg 	 */
7431bb76ff1Sjsg 	flush_rb = dmub->inbox1_rb;
7441bb76ff1Sjsg 	flush_rb.rptr = dmub->inbox1_last_wptr;
7451bb76ff1Sjsg 	dmub_rb_flush_pending(&flush_rb);
746c349dbc7Sjsg 
747c349dbc7Sjsg 	dmub->hw_funcs.set_inbox1_wptr(dmub, dmub->inbox1_rb.wrpt);
7481bb76ff1Sjsg 
7491bb76ff1Sjsg 	dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt;
7501bb76ff1Sjsg 
751c349dbc7Sjsg 	return DMUB_STATUS_OK;
752c349dbc7Sjsg }
753c349dbc7Sjsg 
dmub_srv_wait_for_auto_load(struct dmub_srv * dmub,uint32_t timeout_us)754c349dbc7Sjsg enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
755c349dbc7Sjsg 					     uint32_t timeout_us)
756c349dbc7Sjsg {
757c349dbc7Sjsg 	uint32_t i;
758c349dbc7Sjsg 
759c349dbc7Sjsg 	if (!dmub->hw_init)
760c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
761c349dbc7Sjsg 
762c349dbc7Sjsg 	for (i = 0; i <= timeout_us; i += 100) {
7635ca02815Sjsg 		union dmub_fw_boot_status status = dmub->hw_funcs.get_fw_status(dmub);
7645ca02815Sjsg 
7655ca02815Sjsg 		if (status.bits.dal_fw && status.bits.mailbox_rdy)
766c349dbc7Sjsg 			return DMUB_STATUS_OK;
767c349dbc7Sjsg 
768c349dbc7Sjsg 		udelay(100);
769c349dbc7Sjsg 	}
770c349dbc7Sjsg 
771c349dbc7Sjsg 	return DMUB_STATUS_TIMEOUT;
772c349dbc7Sjsg }
773c349dbc7Sjsg 
dmub_srv_wait_for_idle(struct dmub_srv * dmub,uint32_t timeout_us)774c349dbc7Sjsg enum dmub_status dmub_srv_wait_for_idle(struct dmub_srv *dmub,
775c349dbc7Sjsg 					uint32_t timeout_us)
776c349dbc7Sjsg {
7771bb76ff1Sjsg 	uint32_t i, rptr;
778c349dbc7Sjsg 
779c349dbc7Sjsg 	if (!dmub->hw_init)
780c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
781c349dbc7Sjsg 
782c349dbc7Sjsg 	for (i = 0; i <= timeout_us; ++i) {
7831bb76ff1Sjsg 		rptr = dmub->hw_funcs.get_inbox1_rptr(dmub);
7841bb76ff1Sjsg 
7851bb76ff1Sjsg 		if (rptr > dmub->inbox1_rb.capacity)
7861bb76ff1Sjsg 			return DMUB_STATUS_HW_FAILURE;
7871bb76ff1Sjsg 
7881bb76ff1Sjsg 		dmub->inbox1_rb.rptr = rptr;
7891bb76ff1Sjsg 
790c349dbc7Sjsg 		if (dmub_rb_empty(&dmub->inbox1_rb))
791c349dbc7Sjsg 			return DMUB_STATUS_OK;
792c349dbc7Sjsg 
793c349dbc7Sjsg 		udelay(1);
794c349dbc7Sjsg 	}
795c349dbc7Sjsg 
796c349dbc7Sjsg 	return DMUB_STATUS_TIMEOUT;
797c349dbc7Sjsg }
798c349dbc7Sjsg 
799c349dbc7Sjsg enum dmub_status
dmub_srv_send_gpint_command(struct dmub_srv * dmub,enum dmub_gpint_command command_code,uint16_t param,uint32_t timeout_us)800c349dbc7Sjsg dmub_srv_send_gpint_command(struct dmub_srv *dmub,
801c349dbc7Sjsg 			    enum dmub_gpint_command command_code,
802c349dbc7Sjsg 			    uint16_t param, uint32_t timeout_us)
803c349dbc7Sjsg {
804c349dbc7Sjsg 	union dmub_gpint_data_register reg;
805c349dbc7Sjsg 	uint32_t i;
806c349dbc7Sjsg 
807c349dbc7Sjsg 	if (!dmub->sw_init)
808c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
809c349dbc7Sjsg 
810c349dbc7Sjsg 	if (!dmub->hw_funcs.set_gpint)
811c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
812c349dbc7Sjsg 
813c349dbc7Sjsg 	if (!dmub->hw_funcs.is_gpint_acked)
814c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
815c349dbc7Sjsg 
816c349dbc7Sjsg 	reg.bits.status = 1;
817c349dbc7Sjsg 	reg.bits.command_code = command_code;
818c349dbc7Sjsg 	reg.bits.param = param;
819c349dbc7Sjsg 
820c349dbc7Sjsg 	dmub->hw_funcs.set_gpint(dmub, reg);
821c349dbc7Sjsg 
822c349dbc7Sjsg 	for (i = 0; i < timeout_us; ++i) {
8235ca02815Sjsg 		udelay(1);
8245ca02815Sjsg 
825c349dbc7Sjsg 		if (dmub->hw_funcs.is_gpint_acked(dmub, reg))
826c349dbc7Sjsg 			return DMUB_STATUS_OK;
827c349dbc7Sjsg 	}
828c349dbc7Sjsg 
829c349dbc7Sjsg 	return DMUB_STATUS_TIMEOUT;
830c349dbc7Sjsg }
831c349dbc7Sjsg 
dmub_srv_get_gpint_response(struct dmub_srv * dmub,uint32_t * response)832c349dbc7Sjsg enum dmub_status dmub_srv_get_gpint_response(struct dmub_srv *dmub,
833c349dbc7Sjsg 					     uint32_t *response)
834c349dbc7Sjsg {
835c349dbc7Sjsg 	*response = 0;
836c349dbc7Sjsg 
837c349dbc7Sjsg 	if (!dmub->sw_init)
838c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
839c349dbc7Sjsg 
840c349dbc7Sjsg 	if (!dmub->hw_funcs.get_gpint_response)
841c349dbc7Sjsg 		return DMUB_STATUS_INVALID;
842c349dbc7Sjsg 
843c349dbc7Sjsg 	*response = dmub->hw_funcs.get_gpint_response(dmub);
844c349dbc7Sjsg 
845c349dbc7Sjsg 	return DMUB_STATUS_OK;
846c349dbc7Sjsg }
8475ca02815Sjsg 
dmub_srv_get_gpint_dataout(struct dmub_srv * dmub,uint32_t * dataout)8485ca02815Sjsg enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
8495ca02815Sjsg 					     uint32_t *dataout)
8505ca02815Sjsg {
8515ca02815Sjsg 	*dataout = 0;
8525ca02815Sjsg 
8535ca02815Sjsg 	if (!dmub->sw_init)
8545ca02815Sjsg 		return DMUB_STATUS_INVALID;
8555ca02815Sjsg 
8565ca02815Sjsg 	if (!dmub->hw_funcs.get_gpint_dataout)
8575ca02815Sjsg 		return DMUB_STATUS_INVALID;
8585ca02815Sjsg 
8595ca02815Sjsg 	*dataout = dmub->hw_funcs.get_gpint_dataout(dmub);
8605ca02815Sjsg 
8615ca02815Sjsg 	return DMUB_STATUS_OK;
8625ca02815Sjsg }
8635ca02815Sjsg 
dmub_srv_get_fw_boot_status(struct dmub_srv * dmub,union dmub_fw_boot_status * status)8645ca02815Sjsg enum dmub_status dmub_srv_get_fw_boot_status(struct dmub_srv *dmub,
8655ca02815Sjsg 					     union dmub_fw_boot_status *status)
8665ca02815Sjsg {
8675ca02815Sjsg 	status->all = 0;
8685ca02815Sjsg 
8695ca02815Sjsg 	if (!dmub->sw_init)
8705ca02815Sjsg 		return DMUB_STATUS_INVALID;
8715ca02815Sjsg 
8725ca02815Sjsg 	if (dmub->hw_funcs.get_fw_status)
8735ca02815Sjsg 		*status = dmub->hw_funcs.get_fw_status(dmub);
8745ca02815Sjsg 
8755ca02815Sjsg 	return DMUB_STATUS_OK;
8765ca02815Sjsg }
8775ca02815Sjsg 
dmub_srv_get_fw_boot_option(struct dmub_srv * dmub,union dmub_fw_boot_options * option)878*f005ef32Sjsg enum dmub_status dmub_srv_get_fw_boot_option(struct dmub_srv *dmub,
879*f005ef32Sjsg 					     union dmub_fw_boot_options *option)
880*f005ef32Sjsg {
881*f005ef32Sjsg 	option->all = 0;
882*f005ef32Sjsg 
883*f005ef32Sjsg 	if (!dmub->sw_init)
884*f005ef32Sjsg 		return DMUB_STATUS_INVALID;
885*f005ef32Sjsg 
886*f005ef32Sjsg 	if (dmub->hw_funcs.get_fw_boot_option)
887*f005ef32Sjsg 		*option = dmub->hw_funcs.get_fw_boot_option(dmub);
888*f005ef32Sjsg 
889*f005ef32Sjsg 	return DMUB_STATUS_OK;
890*f005ef32Sjsg }
891*f005ef32Sjsg 
dmub_srv_set_skip_panel_power_sequence(struct dmub_srv * dmub,bool skip)892*f005ef32Sjsg enum dmub_status dmub_srv_set_skip_panel_power_sequence(struct dmub_srv *dmub,
893*f005ef32Sjsg 					     bool skip)
894*f005ef32Sjsg {
895*f005ef32Sjsg 	if (!dmub->sw_init)
896*f005ef32Sjsg 		return DMUB_STATUS_INVALID;
897*f005ef32Sjsg 
898*f005ef32Sjsg 	if (dmub->hw_funcs.skip_dmub_panel_power_sequence && !dmub->is_virtual)
899*f005ef32Sjsg 		dmub->hw_funcs.skip_dmub_panel_power_sequence(dmub, skip);
900*f005ef32Sjsg 
901*f005ef32Sjsg 	return DMUB_STATUS_OK;
902*f005ef32Sjsg }
903*f005ef32Sjsg 
dmub_srv_cmd_with_reply_data(struct dmub_srv * dmub,union dmub_rb_cmd * cmd)9045ca02815Sjsg enum dmub_status dmub_srv_cmd_with_reply_data(struct dmub_srv *dmub,
9055ca02815Sjsg 					      union dmub_rb_cmd *cmd)
9065ca02815Sjsg {
9075ca02815Sjsg 	enum dmub_status status = DMUB_STATUS_OK;
9085ca02815Sjsg 
9095ca02815Sjsg 	// Queue command
9105ca02815Sjsg 	status = dmub_srv_cmd_queue(dmub, cmd);
9115ca02815Sjsg 
9125ca02815Sjsg 	if (status != DMUB_STATUS_OK)
9135ca02815Sjsg 		return status;
9145ca02815Sjsg 
9155ca02815Sjsg 	// Execute command
9165ca02815Sjsg 	status = dmub_srv_cmd_execute(dmub);
9175ca02815Sjsg 
9185ca02815Sjsg 	if (status != DMUB_STATUS_OK)
9195ca02815Sjsg 		return status;
9205ca02815Sjsg 
9215ca02815Sjsg 	// Wait for DMUB to process command
9225ca02815Sjsg 	status = dmub_srv_wait_for_idle(dmub, 100000);
9235ca02815Sjsg 
9245ca02815Sjsg 	if (status != DMUB_STATUS_OK)
9255ca02815Sjsg 		return status;
9265ca02815Sjsg 
9275ca02815Sjsg 	// Copy data back from ring buffer into command
9285ca02815Sjsg 	dmub_rb_get_return_data(&dmub->inbox1_rb, cmd);
9295ca02815Sjsg 
9305ca02815Sjsg 	return status;
9315ca02815Sjsg }
9325ca02815Sjsg 
dmub_rb_out_trace_buffer_front(struct dmub_rb * rb,void * entry)9335ca02815Sjsg static inline bool dmub_rb_out_trace_buffer_front(struct dmub_rb *rb,
9345ca02815Sjsg 				 void *entry)
9355ca02815Sjsg {
9365ca02815Sjsg 	const uint64_t *src = (const uint64_t *)(rb->base_address) + rb->rptr / sizeof(uint64_t);
9375ca02815Sjsg 	uint64_t *dst = (uint64_t *)entry;
9385ca02815Sjsg 	uint8_t i;
9395ca02815Sjsg 	uint8_t loop_count;
9405ca02815Sjsg 
9415ca02815Sjsg 	if (rb->rptr == rb->wrpt)
9425ca02815Sjsg 		return false;
9435ca02815Sjsg 
9445ca02815Sjsg 	loop_count = sizeof(struct dmcub_trace_buf_entry) / sizeof(uint64_t);
9455ca02815Sjsg 	// copying data
9465ca02815Sjsg 	for (i = 0; i < loop_count; i++)
9475ca02815Sjsg 		*dst++ = *src++;
9485ca02815Sjsg 
9495ca02815Sjsg 	rb->rptr += sizeof(struct dmcub_trace_buf_entry);
9505ca02815Sjsg 
9515ca02815Sjsg 	rb->rptr %= rb->capacity;
9525ca02815Sjsg 
9535ca02815Sjsg 	return true;
9545ca02815Sjsg }
9555ca02815Sjsg 
dmub_srv_get_outbox0_msg(struct dmub_srv * dmub,struct dmcub_trace_buf_entry * entry)9565ca02815Sjsg bool dmub_srv_get_outbox0_msg(struct dmub_srv *dmub, struct dmcub_trace_buf_entry *entry)
9575ca02815Sjsg {
9585ca02815Sjsg 	dmub->outbox0_rb.wrpt = dmub->hw_funcs.get_outbox0_wptr(dmub);
9595ca02815Sjsg 
9605ca02815Sjsg 	return dmub_rb_out_trace_buffer_front(&dmub->outbox0_rb, (void *)entry);
9615ca02815Sjsg }
9625ca02815Sjsg 
dmub_srv_get_diagnostic_data(struct dmub_srv * dmub,struct dmub_diagnostic_data * diag_data)9635ca02815Sjsg bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub, struct dmub_diagnostic_data *diag_data)
9645ca02815Sjsg {
9655ca02815Sjsg 	if (!dmub || !dmub->hw_funcs.get_diagnostic_data || !diag_data)
9665ca02815Sjsg 		return false;
9675ca02815Sjsg 	dmub->hw_funcs.get_diagnostic_data(dmub, diag_data);
9685ca02815Sjsg 	return true;
9695ca02815Sjsg }
9701bb76ff1Sjsg 
dmub_srv_should_detect(struct dmub_srv * dmub)9711bb76ff1Sjsg bool dmub_srv_should_detect(struct dmub_srv *dmub)
9721bb76ff1Sjsg {
9731bb76ff1Sjsg 	if (!dmub->hw_init || !dmub->hw_funcs.should_detect)
9741bb76ff1Sjsg 		return false;
9751bb76ff1Sjsg 
9761bb76ff1Sjsg 	return dmub->hw_funcs.should_detect(dmub);
9771bb76ff1Sjsg }
9781bb76ff1Sjsg 
dmub_srv_clear_inbox0_ack(struct dmub_srv * dmub)9791bb76ff1Sjsg enum dmub_status dmub_srv_clear_inbox0_ack(struct dmub_srv *dmub)
9801bb76ff1Sjsg {
9811bb76ff1Sjsg 	if (!dmub->hw_init || !dmub->hw_funcs.clear_inbox0_ack_register)
9821bb76ff1Sjsg 		return DMUB_STATUS_INVALID;
9831bb76ff1Sjsg 
9841bb76ff1Sjsg 	dmub->hw_funcs.clear_inbox0_ack_register(dmub);
9851bb76ff1Sjsg 	return DMUB_STATUS_OK;
9861bb76ff1Sjsg }
9871bb76ff1Sjsg 
dmub_srv_wait_for_inbox0_ack(struct dmub_srv * dmub,uint32_t timeout_us)9881bb76ff1Sjsg enum dmub_status dmub_srv_wait_for_inbox0_ack(struct dmub_srv *dmub, uint32_t timeout_us)
9891bb76ff1Sjsg {
9901bb76ff1Sjsg 	uint32_t i = 0;
9911bb76ff1Sjsg 	uint32_t ack = 0;
9921bb76ff1Sjsg 
9931bb76ff1Sjsg 	if (!dmub->hw_init || !dmub->hw_funcs.read_inbox0_ack_register)
9941bb76ff1Sjsg 		return DMUB_STATUS_INVALID;
9951bb76ff1Sjsg 
9961bb76ff1Sjsg 	for (i = 0; i <= timeout_us; i++) {
9971bb76ff1Sjsg 		ack = dmub->hw_funcs.read_inbox0_ack_register(dmub);
9981bb76ff1Sjsg 		if (ack)
9991bb76ff1Sjsg 			return DMUB_STATUS_OK;
100022b9dc14Sjsg 		udelay(1);
10011bb76ff1Sjsg 	}
10021bb76ff1Sjsg 	return DMUB_STATUS_TIMEOUT;
10031bb76ff1Sjsg }
10041bb76ff1Sjsg 
dmub_srv_send_inbox0_cmd(struct dmub_srv * dmub,union dmub_inbox0_data_register data)10051bb76ff1Sjsg enum dmub_status dmub_srv_send_inbox0_cmd(struct dmub_srv *dmub,
10061bb76ff1Sjsg 		union dmub_inbox0_data_register data)
10071bb76ff1Sjsg {
10081bb76ff1Sjsg 	if (!dmub->hw_init || !dmub->hw_funcs.send_inbox0_cmd)
10091bb76ff1Sjsg 		return DMUB_STATUS_INVALID;
10101bb76ff1Sjsg 
10111bb76ff1Sjsg 	dmub->hw_funcs.send_inbox0_cmd(dmub, data);
10121bb76ff1Sjsg 	return DMUB_STATUS_OK;
10131bb76ff1Sjsg }
1014