13a1627b0SNicholas Kazlauskas /* 23a1627b0SNicholas Kazlauskas * Copyright 2019 Advanced Micro Devices, Inc. 33a1627b0SNicholas Kazlauskas * 43a1627b0SNicholas Kazlauskas * Permission is hereby granted, free of charge, to any person obtaining a 53a1627b0SNicholas Kazlauskas * copy of this software and associated documentation files (the "Software"), 63a1627b0SNicholas Kazlauskas * to deal in the Software without restriction, including without limitation 73a1627b0SNicholas Kazlauskas * the rights to use, copy, modify, merge, publish, distribute, sublicense, 83a1627b0SNicholas Kazlauskas * and/or sell copies of the Software, and to permit persons to whom the 93a1627b0SNicholas Kazlauskas * Software is furnished to do so, subject to the following conditions: 103a1627b0SNicholas Kazlauskas * 113a1627b0SNicholas Kazlauskas * The above copyright notice and this permission notice shall be included in 123a1627b0SNicholas Kazlauskas * all copies or substantial portions of the Software. 133a1627b0SNicholas Kazlauskas * 143a1627b0SNicholas Kazlauskas * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 153a1627b0SNicholas Kazlauskas * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 163a1627b0SNicholas Kazlauskas * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 173a1627b0SNicholas Kazlauskas * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 183a1627b0SNicholas Kazlauskas * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 193a1627b0SNicholas Kazlauskas * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 203a1627b0SNicholas Kazlauskas * OTHER DEALINGS IN THE SOFTWARE. 213a1627b0SNicholas Kazlauskas * 223a1627b0SNicholas Kazlauskas * Authors: AMD 233a1627b0SNicholas Kazlauskas * 243a1627b0SNicholas Kazlauskas */ 253a1627b0SNicholas Kazlauskas 263a1627b0SNicholas Kazlauskas #include "dc.h" 273a1627b0SNicholas Kazlauskas #include "dc_dmub_srv.h" 28cdca3f21SAnthony Koo #include "../dmub/dmub_srv.h" 2970732504SYongqiang Sun #include "dm_helpers.h" 303a1627b0SNicholas Kazlauskas 31ecdfc5c9SNicholas Kazlauskas #define CTX dc_dmub_srv->ctx 32ecdfc5c9SNicholas Kazlauskas #define DC_LOGGER CTX->logger 33ecdfc5c9SNicholas Kazlauskas 343a1627b0SNicholas Kazlauskas static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc, 353a1627b0SNicholas Kazlauskas struct dmub_srv *dmub) 363a1627b0SNicholas Kazlauskas { 373a1627b0SNicholas Kazlauskas dc_srv->dmub = dmub; 383a1627b0SNicholas Kazlauskas dc_srv->ctx = dc->ctx; 393a1627b0SNicholas Kazlauskas } 403a1627b0SNicholas Kazlauskas 413a1627b0SNicholas Kazlauskas struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub) 423a1627b0SNicholas Kazlauskas { 433a1627b0SNicholas Kazlauskas struct dc_dmub_srv *dc_srv = 443a1627b0SNicholas Kazlauskas kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL); 453a1627b0SNicholas Kazlauskas 463a1627b0SNicholas Kazlauskas if (dc_srv == NULL) { 473a1627b0SNicholas Kazlauskas BREAK_TO_DEBUGGER(); 483a1627b0SNicholas Kazlauskas return NULL; 493a1627b0SNicholas Kazlauskas } 503a1627b0SNicholas Kazlauskas 513a1627b0SNicholas Kazlauskas dc_dmub_srv_construct(dc_srv, dc, dmub); 523a1627b0SNicholas Kazlauskas 533a1627b0SNicholas Kazlauskas return dc_srv; 543a1627b0SNicholas Kazlauskas } 553a1627b0SNicholas Kazlauskas 563a1627b0SNicholas Kazlauskas void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv) 573a1627b0SNicholas Kazlauskas { 583a1627b0SNicholas Kazlauskas if (*dmub_srv) { 593a1627b0SNicholas Kazlauskas kfree(*dmub_srv); 603a1627b0SNicholas Kazlauskas *dmub_srv = NULL; 613a1627b0SNicholas Kazlauskas } 623a1627b0SNicholas Kazlauskas } 633a1627b0SNicholas Kazlauskas 643a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, 650ed3bcc4SNicholas Kazlauskas union dmub_rb_cmd *cmd) 663a1627b0SNicholas Kazlauskas { 673a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 683a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 693a1627b0SNicholas Kazlauskas enum dmub_status status; 703a1627b0SNicholas Kazlauskas 713a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_queue(dmub, cmd); 723a1627b0SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 733a1627b0SNicholas Kazlauskas return; 743a1627b0SNicholas Kazlauskas 753a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_QUEUE_FULL) 763a1627b0SNicholas Kazlauskas goto error; 773a1627b0SNicholas Kazlauskas 783a1627b0SNicholas Kazlauskas /* Execute and wait for queue to become empty again. */ 793a1627b0SNicholas Kazlauskas dc_dmub_srv_cmd_execute(dc_dmub_srv); 803a1627b0SNicholas Kazlauskas dc_dmub_srv_wait_idle(dc_dmub_srv); 813a1627b0SNicholas Kazlauskas 823a1627b0SNicholas Kazlauskas /* Requeue the command. */ 833a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_queue(dmub, cmd); 843a1627b0SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 853a1627b0SNicholas Kazlauskas return; 863a1627b0SNicholas Kazlauskas 873a1627b0SNicholas Kazlauskas error: 883a1627b0SNicholas Kazlauskas DC_ERROR("Error queuing DMUB command: status=%d\n", status); 893a1627b0SNicholas Kazlauskas } 903a1627b0SNicholas Kazlauskas 913a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) 923a1627b0SNicholas Kazlauskas { 933a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 943a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 953a1627b0SNicholas Kazlauskas enum dmub_status status; 963a1627b0SNicholas Kazlauskas 973a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_execute(dmub); 983a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_OK) 99243a8f41SColin Ian King DC_ERROR("Error starting DMUB execution: status=%d\n", status); 1003a1627b0SNicholas Kazlauskas } 1013a1627b0SNicholas Kazlauskas 1023a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) 1033a1627b0SNicholas Kazlauskas { 1043a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 1053a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 1063a1627b0SNicholas Kazlauskas enum dmub_status status; 1073a1627b0SNicholas Kazlauskas 1083a1627b0SNicholas Kazlauskas status = dmub_srv_wait_for_idle(dmub, 100000); 1093a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_OK) 1103a1627b0SNicholas Kazlauskas DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); 1113a1627b0SNicholas Kazlauskas } 1123a1627b0SNicholas Kazlauskas 113*f2973d2aSAlvin Lee void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dmub_srv, 114*f2973d2aSAlvin Lee union dmub_inbox0_data_register data) 115*f2973d2aSAlvin Lee { 116*f2973d2aSAlvin Lee struct dmub_srv *dmub = dmub_srv->dmub; 117*f2973d2aSAlvin Lee if (dmub->hw_funcs.send_inbox0_cmd) 118*f2973d2aSAlvin Lee dmub->hw_funcs.send_inbox0_cmd(dmub, data); 119*f2973d2aSAlvin Lee // TODO: Add wait command -- poll register for ACK 120*f2973d2aSAlvin Lee } 121*f2973d2aSAlvin Lee 122ecdfc5c9SNicholas Kazlauskas bool dc_dmub_srv_cmd_with_reply_data(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd) 123ecdfc5c9SNicholas Kazlauskas { 124ecdfc5c9SNicholas Kazlauskas struct dmub_srv *dmub; 125ecdfc5c9SNicholas Kazlauskas enum dmub_status status; 126ecdfc5c9SNicholas Kazlauskas 127ecdfc5c9SNicholas Kazlauskas if (!dc_dmub_srv || !dc_dmub_srv->dmub) 128ecdfc5c9SNicholas Kazlauskas return false; 129ecdfc5c9SNicholas Kazlauskas 130ecdfc5c9SNicholas Kazlauskas dmub = dc_dmub_srv->dmub; 131ecdfc5c9SNicholas Kazlauskas 132ecdfc5c9SNicholas Kazlauskas status = dmub_srv_cmd_with_reply_data(dmub, cmd); 133ecdfc5c9SNicholas Kazlauskas if (status != DMUB_STATUS_OK) { 134ecdfc5c9SNicholas Kazlauskas DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status); 135ecdfc5c9SNicholas Kazlauskas return false; 136ecdfc5c9SNicholas Kazlauskas } 137ecdfc5c9SNicholas Kazlauskas 138ecdfc5c9SNicholas Kazlauskas return true; 139ecdfc5c9SNicholas Kazlauskas } 140ecdfc5c9SNicholas Kazlauskas 1413a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv) 1423a1627b0SNicholas Kazlauskas { 1433a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 1443a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 1453a1627b0SNicholas Kazlauskas enum dmub_status status; 1463a1627b0SNicholas Kazlauskas 147a6e4da40SNicholas Kazlauskas for (;;) { 148a6e4da40SNicholas Kazlauskas /* Wait up to a second for PHY init. */ 149a6e4da40SNicholas Kazlauskas status = dmub_srv_wait_for_phy_init(dmub, 1000000); 150a6e4da40SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 151a6e4da40SNicholas Kazlauskas /* Initialization OK */ 152a6e4da40SNicholas Kazlauskas break; 153a6e4da40SNicholas Kazlauskas 154a6e4da40SNicholas Kazlauskas DC_ERROR("DMCUB PHY init failed: status=%d\n", status); 15556fc13feSNicholas Kazlauskas ASSERT(0); 156a6e4da40SNicholas Kazlauskas 157a6e4da40SNicholas Kazlauskas if (status != DMUB_STATUS_TIMEOUT) 158a6e4da40SNicholas Kazlauskas /* 159a6e4da40SNicholas Kazlauskas * Server likely initialized or we don't have 160a6e4da40SNicholas Kazlauskas * DMCUB HW support - this won't end. 161a6e4da40SNicholas Kazlauskas */ 162a6e4da40SNicholas Kazlauskas break; 163a6e4da40SNicholas Kazlauskas 164a6e4da40SNicholas Kazlauskas /* Continue spinning so we don't hang the ASIC. */ 16556fc13feSNicholas Kazlauskas } 1663a1627b0SNicholas Kazlauskas } 1670825d965SEric Yang 1680825d965SEric Yang bool dc_dmub_srv_notify_stream_mask(struct dc_dmub_srv *dc_dmub_srv, 1690825d965SEric Yang unsigned int stream_mask) 1700825d965SEric Yang { 1710825d965SEric Yang struct dmub_srv *dmub; 1720825d965SEric Yang const uint32_t timeout = 30; 1730825d965SEric Yang 1740825d965SEric Yang if (!dc_dmub_srv || !dc_dmub_srv->dmub) 1750825d965SEric Yang return false; 1760825d965SEric Yang 1770825d965SEric Yang dmub = dc_dmub_srv->dmub; 1780825d965SEric Yang 1790825d965SEric Yang return dmub_srv_send_gpint_command( 1800825d965SEric Yang dmub, DMUB_GPINT__IDLE_OPT_NOTIFY_STREAM_MASK, 1810825d965SEric Yang stream_mask, timeout) == DMUB_STATUS_OK; 1820825d965SEric Yang } 18370732504SYongqiang Sun 1846804287bSYongqiang Sun bool dc_dmub_srv_get_dmub_outbox0_msg(const struct dc *dc, struct dmcub_trace_buf_entry *entry) 18570732504SYongqiang Sun { 18670732504SYongqiang Sun struct dmub_srv *dmub = dc->ctx->dmub_srv->dmub; 1876804287bSYongqiang Sun return dmub_srv_get_outbox0_msg(dmub, entry); 18870732504SYongqiang Sun } 18970732504SYongqiang Sun 19070732504SYongqiang Sun void dc_dmub_trace_event_control(struct dc *dc, bool enable) 19170732504SYongqiang Sun { 19281927e28SJude Shih dm_helpers_dmub_outbox_interrupt_control(dc->ctx, enable); 19370732504SYongqiang Sun } 194