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" 283a1627b0SNicholas Kazlauskas #include "../dmub/inc/dmub_srv.h" 293a1627b0SNicholas Kazlauskas 303a1627b0SNicholas Kazlauskas static void dc_dmub_srv_construct(struct dc_dmub_srv *dc_srv, struct dc *dc, 313a1627b0SNicholas Kazlauskas struct dmub_srv *dmub) 323a1627b0SNicholas Kazlauskas { 333a1627b0SNicholas Kazlauskas dc_srv->dmub = dmub; 343a1627b0SNicholas Kazlauskas dc_srv->ctx = dc->ctx; 353a1627b0SNicholas Kazlauskas } 363a1627b0SNicholas Kazlauskas 373a1627b0SNicholas Kazlauskas struct dc_dmub_srv *dc_dmub_srv_create(struct dc *dc, struct dmub_srv *dmub) 383a1627b0SNicholas Kazlauskas { 393a1627b0SNicholas Kazlauskas struct dc_dmub_srv *dc_srv = 403a1627b0SNicholas Kazlauskas kzalloc(sizeof(struct dc_dmub_srv), GFP_KERNEL); 413a1627b0SNicholas Kazlauskas 423a1627b0SNicholas Kazlauskas if (dc_srv == NULL) { 433a1627b0SNicholas Kazlauskas BREAK_TO_DEBUGGER(); 443a1627b0SNicholas Kazlauskas return NULL; 453a1627b0SNicholas Kazlauskas } 463a1627b0SNicholas Kazlauskas 473a1627b0SNicholas Kazlauskas dc_dmub_srv_construct(dc_srv, dc, dmub); 483a1627b0SNicholas Kazlauskas 493a1627b0SNicholas Kazlauskas return dc_srv; 503a1627b0SNicholas Kazlauskas } 513a1627b0SNicholas Kazlauskas 523a1627b0SNicholas Kazlauskas void dc_dmub_srv_destroy(struct dc_dmub_srv **dmub_srv) 533a1627b0SNicholas Kazlauskas { 543a1627b0SNicholas Kazlauskas if (*dmub_srv) { 553a1627b0SNicholas Kazlauskas kfree(*dmub_srv); 563a1627b0SNicholas Kazlauskas *dmub_srv = NULL; 573a1627b0SNicholas Kazlauskas } 583a1627b0SNicholas Kazlauskas } 593a1627b0SNicholas Kazlauskas 603a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_queue(struct dc_dmub_srv *dc_dmub_srv, 610ed3bcc4SNicholas Kazlauskas union dmub_rb_cmd *cmd) 623a1627b0SNicholas Kazlauskas { 633a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 643a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 653a1627b0SNicholas Kazlauskas enum dmub_status status; 663a1627b0SNicholas Kazlauskas 673a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_queue(dmub, cmd); 683a1627b0SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 693a1627b0SNicholas Kazlauskas return; 703a1627b0SNicholas Kazlauskas 713a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_QUEUE_FULL) 723a1627b0SNicholas Kazlauskas goto error; 733a1627b0SNicholas Kazlauskas 743a1627b0SNicholas Kazlauskas /* Execute and wait for queue to become empty again. */ 753a1627b0SNicholas Kazlauskas dc_dmub_srv_cmd_execute(dc_dmub_srv); 763a1627b0SNicholas Kazlauskas dc_dmub_srv_wait_idle(dc_dmub_srv); 773a1627b0SNicholas Kazlauskas 783a1627b0SNicholas Kazlauskas /* Requeue the command. */ 793a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_queue(dmub, cmd); 803a1627b0SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 813a1627b0SNicholas Kazlauskas return; 823a1627b0SNicholas Kazlauskas 833a1627b0SNicholas Kazlauskas error: 843a1627b0SNicholas Kazlauskas DC_ERROR("Error queuing DMUB command: status=%d\n", status); 853a1627b0SNicholas Kazlauskas } 863a1627b0SNicholas Kazlauskas 873a1627b0SNicholas Kazlauskas void dc_dmub_srv_cmd_execute(struct dc_dmub_srv *dc_dmub_srv) 883a1627b0SNicholas Kazlauskas { 893a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 903a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 913a1627b0SNicholas Kazlauskas enum dmub_status status; 923a1627b0SNicholas Kazlauskas 933a1627b0SNicholas Kazlauskas status = dmub_srv_cmd_execute(dmub); 943a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_OK) 95243a8f41SColin Ian King DC_ERROR("Error starting DMUB execution: status=%d\n", status); 963a1627b0SNicholas Kazlauskas } 973a1627b0SNicholas Kazlauskas 983a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv) 993a1627b0SNicholas Kazlauskas { 1003a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 1013a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 1023a1627b0SNicholas Kazlauskas enum dmub_status status; 1033a1627b0SNicholas Kazlauskas 1043a1627b0SNicholas Kazlauskas status = dmub_srv_wait_for_idle(dmub, 100000); 1053a1627b0SNicholas Kazlauskas if (status != DMUB_STATUS_OK) 1063a1627b0SNicholas Kazlauskas DC_ERROR("Error waiting for DMUB idle: status=%d\n", status); 1073a1627b0SNicholas Kazlauskas } 1083a1627b0SNicholas Kazlauskas 1093a1627b0SNicholas Kazlauskas void dc_dmub_srv_wait_phy_init(struct dc_dmub_srv *dc_dmub_srv) 1103a1627b0SNicholas Kazlauskas { 1113a1627b0SNicholas Kazlauskas struct dmub_srv *dmub = dc_dmub_srv->dmub; 1123a1627b0SNicholas Kazlauskas struct dc_context *dc_ctx = dc_dmub_srv->ctx; 1133a1627b0SNicholas Kazlauskas enum dmub_status status; 1143a1627b0SNicholas Kazlauskas 115a6e4da40SNicholas Kazlauskas for (;;) { 116a6e4da40SNicholas Kazlauskas /* Wait up to a second for PHY init. */ 117a6e4da40SNicholas Kazlauskas status = dmub_srv_wait_for_phy_init(dmub, 1000000); 118a6e4da40SNicholas Kazlauskas if (status == DMUB_STATUS_OK) 119a6e4da40SNicholas Kazlauskas /* Initialization OK */ 120a6e4da40SNicholas Kazlauskas break; 121a6e4da40SNicholas Kazlauskas 122a6e4da40SNicholas Kazlauskas DC_ERROR("DMCUB PHY init failed: status=%d\n", status); 12356fc13feSNicholas Kazlauskas ASSERT(0); 124a6e4da40SNicholas Kazlauskas 125a6e4da40SNicholas Kazlauskas if (status != DMUB_STATUS_TIMEOUT) 126a6e4da40SNicholas Kazlauskas /* 127a6e4da40SNicholas Kazlauskas * Server likely initialized or we don't have 128a6e4da40SNicholas Kazlauskas * DMCUB HW support - this won't end. 129a6e4da40SNicholas Kazlauskas */ 130a6e4da40SNicholas Kazlauskas break; 131a6e4da40SNicholas Kazlauskas 132a6e4da40SNicholas Kazlauskas /* Continue spinning so we don't hang the ASIC. */ 13356fc13feSNicholas Kazlauskas } 1343a1627b0SNicholas Kazlauskas } 135