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