1 /* 2 * Copyright 2012-15 Advanced Micro Devices, Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 22 * Authors: AMD 23 * 24 */ 25 26 #include <linux/delay.h> 27 #include <linux/slab.h> 28 29 #include "dm_services.h" 30 #include "core_types.h" 31 #include "dce_aux.h" 32 #include "dce/dce_11_0_sh_mask.h" 33 #include "dm_event_log.h" 34 #include "dm_helpers.h" 35 #include "dmub/inc/dmub_cmd.h" 36 37 #define CTX \ 38 aux110->base.ctx 39 #define REG(reg_name)\ 40 (aux110->regs->reg_name) 41 42 #define DC_LOGGER \ 43 engine->ctx->logger 44 45 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) 46 #define IS_DC_I2CAUX_LOGGING_ENABLED() (false) 47 #define LOG_FLAG_Error_I2cAux LOG_ERROR 48 #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX 49 50 #include "reg_helper.h" 51 52 #undef FN 53 #define FN(reg_name, field_name) \ 54 aux110->shift->field_name, aux110->mask->field_name 55 56 #define FROM_AUX_ENGINE(ptr) \ 57 container_of((ptr), struct aux_engine_dce110, base) 58 59 #define FROM_ENGINE(ptr) \ 60 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) 61 62 #define FROM_AUX_ENGINE_ENGINE(ptr) \ 63 container_of((ptr), struct dce_aux, base) 64 enum { 65 AUX_INVALID_REPLY_RETRY_COUNTER = 1, 66 AUX_TIMED_OUT_RETRY_COUNTER = 2, 67 AUX_DEFER_RETRY_COUNTER = 6 68 }; 69 70 #define TIME_OUT_INCREMENT 1016 71 #define TIME_OUT_MULTIPLIER_8 8 72 #define TIME_OUT_MULTIPLIER_16 16 73 #define TIME_OUT_MULTIPLIER_32 32 74 #define TIME_OUT_MULTIPLIER_64 64 75 #define MAX_TIMEOUT_LENGTH 127 76 #define DEFAULT_AUX_ENGINE_MULT 0 77 #define DEFAULT_AUX_ENGINE_LENGTH 69 78 79 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0) 80 81 static void release_engine( 82 struct dce_aux *engine) 83 { 84 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 85 86 dal_ddc_close(engine->ddc); 87 88 engine->ddc = NULL; 89 90 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); 91 } 92 93 #define SW_CAN_ACCESS_AUX 1 94 #define DMCU_CAN_ACCESS_AUX 2 95 96 static bool is_engine_available( 97 struct dce_aux *engine) 98 { 99 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 100 101 uint32_t value = REG_READ(AUX_ARB_CONTROL); 102 uint32_t field = get_reg_field_value( 103 value, 104 AUX_ARB_CONTROL, 105 AUX_REG_RW_CNTL_STATUS); 106 107 return (field != DMCU_CAN_ACCESS_AUX); 108 } 109 static bool acquire_engine( 110 struct dce_aux *engine) 111 { 112 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 113 114 uint32_t value = REG_READ(AUX_ARB_CONTROL); 115 uint32_t field = get_reg_field_value( 116 value, 117 AUX_ARB_CONTROL, 118 AUX_REG_RW_CNTL_STATUS); 119 if (field == DMCU_CAN_ACCESS_AUX) 120 return false; 121 /* enable AUX before request SW to access AUX */ 122 value = REG_READ(AUX_CONTROL); 123 field = get_reg_field_value(value, 124 AUX_CONTROL, 125 AUX_EN); 126 127 if (field == 0) { 128 set_reg_field_value( 129 value, 130 1, 131 AUX_CONTROL, 132 AUX_EN); 133 134 if (REG(AUX_RESET_MASK)) { 135 /*DP_AUX block as part of the enable sequence*/ 136 set_reg_field_value( 137 value, 138 1, 139 AUX_CONTROL, 140 AUX_RESET); 141 } 142 143 REG_WRITE(AUX_CONTROL, value); 144 145 if (REG(AUX_RESET_MASK)) { 146 /*poll HW to make sure reset it done*/ 147 148 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, 149 1, 11); 150 151 set_reg_field_value( 152 value, 153 0, 154 AUX_CONTROL, 155 AUX_RESET); 156 157 REG_WRITE(AUX_CONTROL, value); 158 159 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, 160 1, 11); 161 } 162 } /*if (field)*/ 163 164 /* request SW to access AUX */ 165 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); 166 167 value = REG_READ(AUX_ARB_CONTROL); 168 field = get_reg_field_value( 169 value, 170 AUX_ARB_CONTROL, 171 AUX_REG_RW_CNTL_STATUS); 172 173 return (field == SW_CAN_ACCESS_AUX); 174 } 175 176 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \ 177 ((command) | ((0xF0000 & (address)) >> 16)) 178 179 #define COMPOSE_AUX_SW_DATA_8_15(address) \ 180 ((0xFF00 & (address)) >> 8) 181 182 #define COMPOSE_AUX_SW_DATA_0_7(address) \ 183 (0xFF & (address)) 184 185 static void submit_channel_request( 186 struct dce_aux *engine, 187 struct aux_request_transaction_data *request) 188 { 189 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 190 uint32_t value; 191 uint32_t length; 192 193 bool is_write = 194 ((request->type == AUX_TRANSACTION_TYPE_DP) && 195 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || 196 ((request->type == AUX_TRANSACTION_TYPE_I2C) && 197 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || 198 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); 199 if (REG(AUXN_IMPCAL)) { 200 /* clear_aux_error */ 201 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 202 AUXN_CALOUT_ERROR_AK, 1, 203 AUXN_CALOUT_ERROR_AK, 0); 204 205 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 206 AUXP_CALOUT_ERROR_AK, 1, 207 AUXP_CALOUT_ERROR_AK, 0); 208 209 /* force_default_calibrate */ 210 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 211 AUXN_IMPCAL_ENABLE, 1, 212 AUXN_IMPCAL_OVERRIDE_ENABLE, 0); 213 214 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ 215 216 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 217 AUXP_IMPCAL_OVERRIDE_ENABLE, 1, 218 AUXP_IMPCAL_OVERRIDE_ENABLE, 0); 219 } 220 221 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 222 223 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 224 10, aux110->polling_timeout_period/10); 225 226 /* set the delay and the number of bytes to write */ 227 228 /* The length include 229 * the 4 bit header and the 20 bit address 230 * (that is 3 byte). 231 * If the requested length is non zero this means 232 * an addition byte specifying the length is required. 233 */ 234 235 length = request->length ? 4 : 3; 236 if (is_write) 237 length += request->length; 238 239 REG_UPDATE_2(AUX_SW_CONTROL, 240 AUX_SW_START_DELAY, request->delay, 241 AUX_SW_WR_BYTES, length); 242 243 /* program action and address and payload data (if 'is_write') */ 244 value = REG_UPDATE_4(AUX_SW_DATA, 245 AUX_SW_INDEX, 0, 246 AUX_SW_DATA_RW, 0, 247 AUX_SW_AUTOINCREMENT_DISABLE, 1, 248 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 249 250 value = REG_SET_2(AUX_SW_DATA, value, 251 AUX_SW_AUTOINCREMENT_DISABLE, 0, 252 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 253 254 value = REG_SET(AUX_SW_DATA, value, 255 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 256 257 if (request->length) { 258 value = REG_SET(AUX_SW_DATA, value, 259 AUX_SW_DATA, request->length - 1); 260 } 261 262 if (is_write) { 263 /* Load the HW buffer with the Data to be sent. 264 * This is relevant for write operation. 265 * For read, the data recived data will be 266 * processed in process_channel_reply(). 267 */ 268 uint32_t i = 0; 269 270 while (i < request->length) { 271 value = REG_SET(AUX_SW_DATA, value, 272 AUX_SW_DATA, request->data[i]); 273 274 ++i; 275 } 276 } 277 278 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 279 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE, 280 request->action, request->address, request->length, request->data); 281 } 282 283 static int read_channel_reply(struct dce_aux *engine, uint32_t size, 284 uint8_t *buffer, uint8_t *reply_result, 285 uint32_t *sw_status) 286 { 287 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 288 uint32_t bytes_replied; 289 uint32_t reply_result_32; 290 291 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 292 &bytes_replied); 293 294 /* In case HPD is LOW, exit AUX transaction */ 295 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 296 return -1; 297 298 /* Need at least the status byte */ 299 if (!bytes_replied) 300 return -1; 301 302 REG_UPDATE_SEQ_3(AUX_SW_DATA, 303 AUX_SW_INDEX, 0, 304 AUX_SW_AUTOINCREMENT_DISABLE, 1, 305 AUX_SW_DATA_RW, 1); 306 307 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 308 reply_result_32 = reply_result_32 >> 4; 309 if (reply_result != NULL) 310 *reply_result = (uint8_t)reply_result_32; 311 312 if (reply_result_32 == 0) { /* ACK */ 313 uint32_t i = 0; 314 315 /* First byte was already used to get the command status */ 316 --bytes_replied; 317 318 /* Do not overflow buffer */ 319 if (bytes_replied > size) 320 return -1; 321 322 while (i < bytes_replied) { 323 uint32_t aux_sw_data_val; 324 325 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 326 buffer[i] = aux_sw_data_val; 327 ++i; 328 } 329 330 return i; 331 } 332 333 return 0; 334 } 335 336 static enum aux_return_code_type get_channel_status( 337 struct dce_aux *engine, 338 uint8_t *returned_bytes) 339 { 340 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 341 342 uint32_t value; 343 344 if (returned_bytes == NULL) { 345 /*caller pass NULL pointer*/ 346 ASSERT_CRITICAL(false); 347 return AUX_RET_ERROR_UNKNOWN; 348 } 349 *returned_bytes = 0; 350 351 /* poll to make sure that SW_DONE is asserted */ 352 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 353 10, aux110->polling_timeout_period/10); 354 355 value = REG_READ(AUX_SW_STATUS); 356 /* in case HPD is LOW, exit AUX transaction */ 357 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 358 return AUX_RET_ERROR_HPD_DISCON; 359 360 /* Note that the following bits are set in 'status.bits' 361 * during CTS 4.2.1.2 (FW 3.3.1): 362 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 363 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 364 * 365 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 366 * HW debugging bit and should be ignored. 367 */ 368 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 369 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 370 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 371 return AUX_RET_ERROR_TIMEOUT; 372 373 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 374 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 375 (value & 376 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 377 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 378 return AUX_RET_ERROR_INVALID_REPLY; 379 380 *returned_bytes = get_reg_field_value(value, 381 AUX_SW_STATUS, 382 AUX_SW_REPLY_BYTE_COUNT); 383 384 if (*returned_bytes == 0) 385 return 386 AUX_RET_ERROR_INVALID_REPLY; 387 else { 388 *returned_bytes -= 1; 389 return AUX_RET_SUCCESS; 390 } 391 } else { 392 /*time_elapsed >= aux_engine->timeout_period 393 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 394 */ 395 ASSERT_CRITICAL(false); 396 return AUX_RET_ERROR_TIMEOUT; 397 } 398 } 399 400 static bool acquire( 401 struct dce_aux *engine, 402 struct ddc *ddc) 403 { 404 enum gpio_result result; 405 406 if ((engine == NULL) || !is_engine_available(engine)) 407 return false; 408 409 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 410 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 411 412 if (result != GPIO_RESULT_OK) 413 return false; 414 415 if (!acquire_engine(engine)) { 416 engine->ddc = ddc; 417 release_engine(engine); 418 return false; 419 } 420 421 engine->ddc = ddc; 422 423 return true; 424 } 425 426 void dce110_engine_destroy(struct dce_aux **engine) 427 { 428 429 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 430 431 kfree(engine110); 432 *engine = NULL; 433 434 } 435 436 static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc, 437 uint32_t timeout_in_us) 438 { 439 uint32_t multiplier = 0; 440 uint32_t length = 0; 441 uint32_t prev_length = 0; 442 uint32_t prev_mult = 0; 443 uint32_t prev_timeout_val = 0; 444 struct ddc *ddc_pin = ddc->ddc_pin; 445 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 446 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine); 447 448 /* 1-Update polling timeout period */ 449 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER; 450 451 /* 2-Update aux timeout period length and multiplier */ 452 if (timeout_in_us == 0) { 453 multiplier = DEFAULT_AUX_ENGINE_MULT; 454 length = DEFAULT_AUX_ENGINE_LENGTH; 455 } else if (timeout_in_us <= TIME_OUT_INCREMENT) { 456 multiplier = 0; 457 length = timeout_in_us/TIME_OUT_MULTIPLIER_8; 458 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0) 459 length++; 460 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) { 461 multiplier = 1; 462 length = timeout_in_us/TIME_OUT_MULTIPLIER_16; 463 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0) 464 length++; 465 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) { 466 multiplier = 2; 467 length = timeout_in_us/TIME_OUT_MULTIPLIER_32; 468 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0) 469 length++; 470 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) { 471 multiplier = 3; 472 length = timeout_in_us/TIME_OUT_MULTIPLIER_64; 473 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0) 474 length++; 475 } 476 477 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH; 478 479 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult); 480 481 switch (prev_mult) { 482 case 0: 483 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8; 484 break; 485 case 1: 486 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16; 487 break; 488 case 2: 489 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32; 490 break; 491 case 3: 492 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64; 493 break; 494 default: 495 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8; 496 break; 497 } 498 499 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier); 500 501 return prev_timeout_val; 502 } 503 504 static struct dce_aux_funcs aux_functions = { 505 .configure_timeout = NULL, 506 .destroy = NULL, 507 }; 508 509 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 510 struct dc_context *ctx, 511 uint32_t inst, 512 uint32_t timeout_period, 513 const struct dce110_aux_registers *regs, 514 const struct dce110_aux_registers_mask *mask, 515 const struct dce110_aux_registers_shift *shift, 516 bool is_ext_aux_timeout_configurable) 517 { 518 aux_engine110->base.ddc = NULL; 519 aux_engine110->base.ctx = ctx; 520 aux_engine110->base.delay = 0; 521 aux_engine110->base.max_defer_write_retry = 0; 522 aux_engine110->base.inst = inst; 523 aux_engine110->polling_timeout_period = timeout_period; 524 aux_engine110->regs = regs; 525 526 aux_engine110->mask = mask; 527 aux_engine110->shift = shift; 528 aux_engine110->base.funcs = &aux_functions; 529 if (is_ext_aux_timeout_configurable) 530 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout; 531 532 return &aux_engine110->base; 533 } 534 535 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) 536 { 537 if (payload->i2c_over_aux) { 538 if (payload->write_status_update) { 539 if (payload->mot) 540 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT; 541 else 542 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; 543 } 544 if (payload->write) { 545 if (payload->mot) 546 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; 547 else 548 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 549 } 550 if (payload->mot) 551 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; 552 553 return I2CAUX_TRANSACTION_ACTION_I2C_READ; 554 } 555 if (payload->write) 556 return I2CAUX_TRANSACTION_ACTION_DP_WRITE; 557 558 return I2CAUX_TRANSACTION_ACTION_DP_READ; 559 } 560 561 int dce_aux_transfer_raw(struct ddc_service *ddc, 562 struct aux_payload *payload, 563 enum aux_return_code_type *operation_result) 564 { 565 struct ddc *ddc_pin = ddc->ddc_pin; 566 struct dce_aux *aux_engine; 567 struct aux_request_transaction_data aux_req; 568 struct aux_reply_transaction_data aux_rep; 569 uint8_t returned_bytes = 0; 570 int res = -1; 571 uint32_t status; 572 573 memset(&aux_req, 0, sizeof(aux_req)); 574 memset(&aux_rep, 0, sizeof(aux_rep)); 575 576 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 577 if (!acquire(aux_engine, ddc_pin)) { 578 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 579 return -1; 580 } 581 582 if (payload->i2c_over_aux) 583 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 584 else 585 aux_req.type = AUX_TRANSACTION_TYPE_DP; 586 587 aux_req.action = i2caux_action_from_payload(payload); 588 589 aux_req.address = payload->address; 590 aux_req.delay = 0; 591 aux_req.length = payload->length; 592 aux_req.data = payload->data; 593 594 submit_channel_request(aux_engine, &aux_req); 595 *operation_result = get_channel_status(aux_engine, &returned_bytes); 596 597 if (*operation_result == AUX_RET_SUCCESS) { 598 int __maybe_unused bytes_replied = 0; 599 600 bytes_replied = read_channel_reply(aux_engine, payload->length, 601 payload->data, payload->reply, 602 &status); 603 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en, 604 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply, 605 bytes_replied, payload->data); 606 res = returned_bytes; 607 } else { 608 res = -1; 609 } 610 611 release_engine(aux_engine); 612 return res; 613 } 614 615 int dce_aux_transfer_dmub_raw(struct ddc_service *ddc, 616 struct aux_payload *payload, 617 enum aux_return_code_type *operation_result) 618 { 619 struct ddc *ddc_pin = ddc->ddc_pin; 620 621 if (ddc_pin != NULL) { 622 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 623 /* XXX: Workaround to configure ddc channels for aux transactions */ 624 if (!acquire(aux_engine, ddc_pin)) { 625 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE; 626 return -1; 627 } 628 release_engine(aux_engine); 629 } 630 631 return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result); 632 } 633 634 #define AUX_MAX_RETRIES 7 635 #define AUX_MIN_DEFER_RETRIES 7 636 #define AUX_MAX_DEFER_TIMEOUT_MS 50 637 #define AUX_MAX_I2C_DEFER_RETRIES 7 638 #define AUX_MAX_INVALID_REPLY_RETRIES 2 639 #define AUX_MAX_TIMEOUT_RETRIES 3 640 #define AUX_DEFER_DELAY_FOR_DPIA 4 /*ms*/ 641 642 static void dce_aux_log_payload(const char *payload_name, 643 unsigned char *payload, uint32_t length, uint32_t max_length_to_log) 644 { 645 if (!IS_DC_I2CAUX_LOGGING_ENABLED()) 646 return; 647 648 if (payload && length) { 649 char hex_str[128] = {0}; 650 char *hex_str_ptr = &hex_str[0]; 651 uint32_t hex_str_remaining = sizeof(hex_str); 652 unsigned char *payload_ptr = payload; 653 unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length); 654 unsigned int count; 655 char *padding = ""; 656 657 while (payload_ptr < payload_max_to_log_ptr) { 658 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr); 659 padding = " "; 660 hex_str_remaining -= count; 661 hex_str_ptr += count; 662 payload_ptr++; 663 } 664 665 count = snprintf_count(hex_str_ptr, hex_str_remaining, " "); 666 hex_str_remaining -= count; 667 hex_str_ptr += count; 668 669 payload_ptr = payload; 670 while (payload_ptr < payload_max_to_log_ptr) { 671 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c", 672 *payload_ptr >= ' ' ? *payload_ptr : '.'); 673 hex_str_remaining -= count; 674 hex_str_ptr += count; 675 payload_ptr++; 676 } 677 678 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 679 LOG_FLAG_I2cAux_DceAux, 680 "dce_aux_log_payload: %s: length=%u: data: %s%s", 681 payload_name, 682 length, 683 hex_str, 684 (length > max_length_to_log ? " (...)" : " ")); 685 } else { 686 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE, 687 LOG_FLAG_I2cAux_DceAux, 688 "dce_aux_log_payload: %s: length=%u: data: <empty payload>", 689 payload_name, 690 length); 691 } 692 } 693 694 bool dce_aux_transfer_with_retries(struct ddc_service *ddc, 695 struct aux_payload *payload) 696 { 697 int i, ret = 0; 698 uint8_t reply; 699 bool payload_reply = true; 700 enum aux_return_code_type operation_result; 701 bool retry_on_defer = false; 702 struct ddc *ddc_pin = ddc->ddc_pin; 703 struct dce_aux *aux_engine = NULL; 704 struct aux_engine_dce110 *aux110 = NULL; 705 uint32_t defer_time_in_ms = 0; 706 707 int aux_ack_retries = 0, 708 aux_defer_retries = 0, 709 aux_i2c_defer_retries = 0, 710 aux_timeout_retries = 0, 711 aux_invalid_reply_retries = 0, 712 aux_ack_m_retries = 0; 713 714 if (ddc_pin) { 715 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 716 aux110 = FROM_AUX_ENGINE(aux_engine); 717 } 718 719 if (!payload->reply) { 720 payload_reply = false; 721 payload->reply = &reply; 722 } 723 724 for (i = 0; i < AUX_MAX_RETRIES; i++) { 725 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 726 LOG_FLAG_I2cAux_DceAux, 727 "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: address=0x%04x length=%u write=%d mot=%d", 728 ddc && ddc->link ? ddc->link->link_index : UINT_MAX, 729 i + 1, 730 (int)AUX_MAX_RETRIES, 731 payload->address, 732 payload->length, 733 (unsigned int) payload->write, 734 (unsigned int) payload->mot); 735 if (payload->write) 736 dce_aux_log_payload(" write", payload->data, payload->length, 16); 737 ret = dce_aux_transfer_raw(ddc, payload, &operation_result); 738 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 739 LOG_FLAG_I2cAux_DceAux, 740 "dce_aux_transfer_with_retries: link_index=%u: END: retry %d of %d: address=0x%04x length=%u write=%d mot=%d: ret=%d operation_result=%d payload->reply=%u", 741 ddc && ddc->link ? ddc->link->link_index : UINT_MAX, 742 i + 1, 743 (int)AUX_MAX_RETRIES, 744 payload->address, 745 payload->length, 746 (unsigned int) payload->write, 747 (unsigned int) payload->mot, 748 ret, 749 (int)operation_result, 750 (unsigned int) *payload->reply); 751 if (!payload->write) 752 dce_aux_log_payload(" read", payload->data, ret > 0 ? ret : 0, 16); 753 754 switch (operation_result) { 755 case AUX_RET_SUCCESS: 756 aux_timeout_retries = 0; 757 aux_invalid_reply_retries = 0; 758 759 switch (*payload->reply) { 760 case AUX_TRANSACTION_REPLY_AUX_ACK: 761 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 762 LOG_FLAG_I2cAux_DceAux, 763 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK"); 764 if (!payload->write && payload->length != ret) { 765 if (++aux_ack_retries >= AUX_MAX_RETRIES) { 766 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 767 LOG_FLAG_Error_I2cAux, 768 "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d", 769 aux_defer_retries, 770 AUX_MAX_RETRIES); 771 goto fail; 772 } else 773 udelay(300); 774 } else if (payload->write && ret > 0) { 775 /* sink requested more time to complete the write via AUX_ACKM */ 776 if (++aux_ack_m_retries >= AUX_MAX_RETRIES) { 777 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 778 LOG_FLAG_Error_I2cAux, 779 "dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d", 780 aux_ack_m_retries, 781 AUX_MAX_RETRIES); 782 goto fail; 783 } 784 785 /* retry reading the write status until complete 786 * NOTE: payload is modified here 787 */ 788 payload->write = false; 789 payload->write_status_update = true; 790 payload->length = 0; 791 udelay(300); 792 793 } else 794 return true; 795 break; 796 797 case AUX_TRANSACTION_REPLY_AUX_DEFER: 798 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 799 LOG_FLAG_I2cAux_DceAux, 800 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER"); 801 802 /* polling_timeout_period is in us */ 803 if (aux110) 804 defer_time_in_ms += aux110->polling_timeout_period / 1000; 805 else 806 defer_time_in_ms += AUX_DEFER_DELAY_FOR_DPIA; 807 ++aux_defer_retries; 808 fallthrough; 809 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 810 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER) 811 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 812 LOG_FLAG_I2cAux_DceAux, 813 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER"); 814 815 retry_on_defer = true; 816 fallthrough; 817 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 818 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK) 819 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 820 LOG_FLAG_I2cAux_DceAux, 821 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK"); 822 823 if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES 824 && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) { 825 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 826 LOG_FLAG_Error_I2cAux, 827 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d && defer_time_in_ms=%d >= AUX_MAX_DEFER_TIMEOUT_MS=%d", 828 aux_defer_retries, 829 AUX_MIN_DEFER_RETRIES, 830 defer_time_in_ms, 831 AUX_MAX_DEFER_TIMEOUT_MS); 832 goto fail; 833 } else { 834 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) || 835 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) { 836 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 837 LOG_FLAG_I2cAux_DceAux, 838 "dce_aux_transfer_with_retries: payload->defer_delay=%u", 839 payload->defer_delay); 840 if (payload->defer_delay > 1) { 841 msleep(payload->defer_delay); 842 defer_time_in_ms += payload->defer_delay; 843 } else if (payload->defer_delay <= 1) { 844 udelay(payload->defer_delay * 1000); 845 defer_time_in_ms += payload->defer_delay; 846 } 847 } 848 } 849 break; 850 851 case AUX_TRANSACTION_REPLY_I2C_DEFER: 852 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 853 LOG_FLAG_I2cAux_DceAux, 854 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER"); 855 856 aux_defer_retries = 0; 857 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) { 858 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 859 LOG_FLAG_Error_I2cAux, 860 "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d", 861 aux_i2c_defer_retries, 862 AUX_MAX_I2C_DEFER_RETRIES); 863 goto fail; 864 } 865 break; 866 867 case AUX_TRANSACTION_REPLY_AUX_NACK: 868 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 869 LOG_FLAG_I2cAux_DceAux, 870 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK"); 871 goto fail; 872 873 case AUX_TRANSACTION_REPLY_HPD_DISCON: 874 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 875 LOG_FLAG_I2cAux_DceAux, 876 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON"); 877 goto fail; 878 879 default: 880 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 881 LOG_FLAG_Error_I2cAux, 882 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case. Reply: %d", *payload->reply); 883 goto fail; 884 } 885 break; 886 887 case AUX_RET_ERROR_INVALID_REPLY: 888 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 889 LOG_FLAG_I2cAux_DceAux, 890 "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY"); 891 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) { 892 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 893 LOG_FLAG_Error_I2cAux, 894 "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d", 895 aux_invalid_reply_retries, 896 AUX_MAX_INVALID_REPLY_RETRIES); 897 goto fail; 898 } else 899 udelay(400); 900 break; 901 902 case AUX_RET_ERROR_TIMEOUT: 903 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 904 LOG_FLAG_I2cAux_DceAux, 905 "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT"); 906 // Check whether a DEFER had occurred before the timeout. 907 // If so, treat timeout as a DEFER. 908 if (retry_on_defer) { 909 if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) { 910 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 911 LOG_FLAG_Error_I2cAux, 912 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d", 913 aux_defer_retries, 914 AUX_MIN_DEFER_RETRIES); 915 goto fail; 916 } else if (payload->defer_delay > 0) { 917 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 918 LOG_FLAG_I2cAux_DceAux, 919 "dce_aux_transfer_with_retries: payload->defer_delay=%u", 920 payload->defer_delay); 921 msleep(payload->defer_delay); 922 } 923 } else { 924 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) { 925 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 926 LOG_FLAG_Error_I2cAux, 927 "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d", 928 aux_timeout_retries, 929 AUX_MAX_TIMEOUT_RETRIES); 930 goto fail; 931 } else { 932 /* 933 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts 934 * According to the DP spec there should be 3 retries total 935 * with a 400us wait inbetween each. Hardware already waits 936 * for 550us therefore no wait is required here. 937 */ 938 } 939 } 940 break; 941 942 case AUX_RET_ERROR_HPD_DISCON: 943 case AUX_RET_ERROR_ENGINE_ACQUIRE: 944 case AUX_RET_ERROR_UNKNOWN: 945 default: 946 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, 947 LOG_FLAG_I2cAux_DceAux, 948 "dce_aux_transfer_with_retries: Failure: operation_result=%d", 949 (int)operation_result); 950 goto fail; 951 } 952 } 953 954 fail: 955 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 956 LOG_FLAG_Error_I2cAux, 957 "dce_aux_transfer_with_retries: FAILURE"); 958 if (!payload_reply) 959 payload->reply = NULL; 960 961 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR, 962 WPP_BIT_FLAG_DC_ERROR, 963 "AUX transaction failed. Result: %d", 964 operation_result); 965 966 return false; 967 } 968