2 * Copyright 2019 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
27 #include "dc_dmub_srv.h"
28 #include "../dmub/dmub_srv.h"
29 #include "dm_helpers.h"
31 #define CTX dc_dmub_srv->ctx
32 #define DC_LOGGER CTX->logger
34 static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc,
35 struct dmub_srv *dmub)
38 dc_srv->ctx = dc->ctx;
41 struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub)
43 struct dc_dmub_srv *dc_srv =
44 kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL);
51 dc_dmub_srv_construct(dc_srv, dc, dmub);
56 void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv)
64 void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv,
65 union dmub_rb_cmd *cmd)
67 struct dmub_srv *dmub = dc_dmub_srv->dmub;
68 struct dc_context *dc_ctx = dc_dmub_srv->ctx;
69 enum dmub_status status;
71 status = dmub_srv_cmd_queue(dmub, cmd);
72 if (status == DMUB_STATUS_OK)
75 if (status != DMUB_STATUS_QUEUE_FULL)
78 /* Execute and wait for queue to become empty again. */
79 dc_dmub_srv_cmd_execute(dc_dmub_srv);
80 dc_dmub_srv_wait_idle(dc_dmub_srv);
82 /* Requeue the command. */
83 status = dmub_srv_cmd_queue(dmub, cmd);
84 if (status == DMUB_STATUS_OK)
88 DC_ERROR("Error queuing DMUB command: status=%d\n", status);
91 void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv)
93 struct dmub_srv *dmub = dc_dmub_srv->dmub;
94 struct dc_context *dc_ctx = dc_dmub_srv->ctx;
95 enum dmub_status status;
97 status = dmub_srv_cmd_execute(dmub);
98 if (status != DMUB_STATUS_OK)
99 DC_ERROR("Error starting DMUB execution: status=%d\n", status);
102 void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv)
104 struct dmub_srv *dmub = dc_dmub_srv->dmub;
105 struct dc_context *dc_ctx = dc_dmub_srv->ctx;
106 enum dmub_status status;
108 status = dmub_srv_wait_for_idle(dmub, 100000);
109 if (status != DMUB_STATUS_OK)
110 DC_ERROR("Error waiting for DMUB idle: status=%d\n", status);
113 void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv,
114 union dmub_inbox0_data_register data)
116 struct dmub_srv *dmub = dmub_srv->dmub;
117 if (dmub->hw_funcs.send_inbox0_cmd)
118 dmub->hw_funcs.send_inbox0_cmd(dmub, data);
119 // TODO: Add wait command -- poll register for ACK
122 bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd)
124 struct dmub_srv *dmub;
125 enum dmub_status status;
127 if (!dc_dmub_srv || !dc_dmub_srv->dmub)
130 dmub = dc_dmub_srv->dmub;
132 status = dmub_srv_cmd_with_reply_data(dmub, cmd);
133 if (status != DMUB_STATUS_OK) {
134 DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
141 void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv)
143 struct dmub_srv *dmub = dc_dmub_srv->dmub;
144 struct dc_context *dc_ctx = dc_dmub_srv->ctx;
145 enum dmub_status status;
148 /* Wait up to a second for PHY init. */
149 status = dmub_srv_wait_for_phy_init(dmub, 1000000);
150 if (status == DMUB_STATUS_OK)
151 /* Initialization OK */
154 DC_ERROR("DMCUB PHY init failed: status=%d\n", status);
157 if (status != DMUB_STATUS_TIMEOUT)
159 * Server likely initialized or we don't have
160 * DMCUB HW support - this won't end.
164 /* Continue spinning so we don't hang the ASIC. */
168 bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv,
169 unsigned int stream_mask)
171 struct dmub_srv *dmub;
172 const uint32_t timeout = 30;
174 if (!dc_dmub_srv || !dc_dmub_srv->dmub)
177 dmub = dc_dmub_srv->dmub;
179 return dmub_srv_send_gpint_command(
180 dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK,
181 stream_mask, timeout) == DMUB_STATUS_OK;
184 bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry)
186 struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub;
187 return dmub_srv_get_outbox0_msg(dmub, entry);
190 void dc_dmub_trace_event_control(struct dc *dc, bool enable)
192 dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable);