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 "dce_aux.h" 28 #include "dce/dce_11_0_sh_mask.h" 29 30 #define CTX \ 31 aux110->base.ctx 32 #define REG(reg_name)\ 33 (aux110->regs->reg_name) 34 35 #define DC_LOGGER \ 36 engine->ctx->logger 37 38 #include "reg_helper.h" 39 40 #define FROM_AUX_ENGINE(ptr) \ 41 container_of((ptr), struct aux_engine_dce110, base) 42 43 #define FROM_ENGINE(ptr) \ 44 FROM_AUX_ENGINE(container_of((ptr), struct aux_engine, base)) 45 46 #define FROM_AUX_ENGINE_ENGINE(ptr) \ 47 container_of((ptr), struct aux_engine, base) 48 enum { 49 AUX_INVALID_REPLY_RETRY_COUNTER = 1, 50 AUX_TIMED_OUT_RETRY_COUNTER = 2, 51 AUX_DEFER_RETRY_COUNTER = 6 52 }; 53 static void release_engine( 54 struct aux_engine *engine) 55 { 56 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 57 58 dal_ddc_close(engine->ddc); 59 60 engine->ddc = NULL; 61 62 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); 63 } 64 65 #define SW_CAN_ACCESS_AUX 1 66 #define DMCU_CAN_ACCESS_AUX 2 67 68 static bool is_engine_available( 69 struct aux_engine *engine) 70 { 71 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 72 73 uint32_t value = REG_READ(AUX_ARB_CONTROL); 74 uint32_t field = get_reg_field_value( 75 value, 76 AUX_ARB_CONTROL, 77 AUX_REG_RW_CNTL_STATUS); 78 79 return (field != DMCU_CAN_ACCESS_AUX); 80 } 81 static bool acquire_engine( 82 struct aux_engine *engine) 83 { 84 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 85 86 uint32_t value = REG_READ(AUX_ARB_CONTROL); 87 uint32_t field = get_reg_field_value( 88 value, 89 AUX_ARB_CONTROL, 90 AUX_REG_RW_CNTL_STATUS); 91 if (field == DMCU_CAN_ACCESS_AUX) 92 return false; 93 /* enable AUX before request SW to access AUX */ 94 value = REG_READ(AUX_CONTROL); 95 field = get_reg_field_value(value, 96 AUX_CONTROL, 97 AUX_EN); 98 99 if (field == 0) { 100 set_reg_field_value( 101 value, 102 1, 103 AUX_CONTROL, 104 AUX_EN); 105 106 if (REG(AUX_RESET_MASK)) { 107 /*DP_AUX block as part of the enable sequence*/ 108 set_reg_field_value( 109 value, 110 1, 111 AUX_CONTROL, 112 AUX_RESET); 113 } 114 115 REG_WRITE(AUX_CONTROL, value); 116 117 if (REG(AUX_RESET_MASK)) { 118 /*poll HW to make sure reset it done*/ 119 120 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, 121 1, 11); 122 123 set_reg_field_value( 124 value, 125 0, 126 AUX_CONTROL, 127 AUX_RESET); 128 129 REG_WRITE(AUX_CONTROL, value); 130 131 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, 132 1, 11); 133 } 134 } /*if (field)*/ 135 136 /* request SW to access AUX */ 137 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); 138 139 value = REG_READ(AUX_ARB_CONTROL); 140 field = get_reg_field_value( 141 value, 142 AUX_ARB_CONTROL, 143 AUX_REG_RW_CNTL_STATUS); 144 145 return (field == SW_CAN_ACCESS_AUX); 146 } 147 148 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \ 149 ((command) | ((0xF0000 & (address)) >> 16)) 150 151 #define COMPOSE_AUX_SW_DATA_8_15(address) \ 152 ((0xFF00 & (address)) >> 8) 153 154 #define COMPOSE_AUX_SW_DATA_0_7(address) \ 155 (0xFF & (address)) 156 157 static void submit_channel_request( 158 struct aux_engine *engine, 159 struct aux_request_transaction_data *request) 160 { 161 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 162 uint32_t value; 163 uint32_t length; 164 165 bool is_write = 166 ((request->type == AUX_TRANSACTION_TYPE_DP) && 167 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || 168 ((request->type == AUX_TRANSACTION_TYPE_I2C) && 169 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || 170 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); 171 if (REG(AUXN_IMPCAL)) { 172 /* clear_aux_error */ 173 REG_UPDATE_SEQ(AUXN_IMPCAL, AUXN_CALOUT_ERROR_AK, 174 1, 175 0); 176 177 REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_CALOUT_ERROR_AK, 178 1, 179 0); 180 181 /* force_default_calibrate */ 182 REG_UPDATE_1BY1_2(AUXN_IMPCAL, 183 AUXN_IMPCAL_ENABLE, 1, 184 AUXN_IMPCAL_OVERRIDE_ENABLE, 0); 185 186 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ 187 188 REG_UPDATE_SEQ(AUXP_IMPCAL, AUXP_IMPCAL_OVERRIDE_ENABLE, 189 1, 190 0); 191 } 192 /* set the delay and the number of bytes to write */ 193 194 /* The length include 195 * the 4 bit header and the 20 bit address 196 * (that is 3 byte). 197 * If the requested length is non zero this means 198 * an addition byte specifying the length is required. 199 */ 200 201 length = request->length ? 4 : 3; 202 if (is_write) 203 length += request->length; 204 205 REG_UPDATE_2(AUX_SW_CONTROL, 206 AUX_SW_START_DELAY, request->delay, 207 AUX_SW_WR_BYTES, length); 208 209 /* program action and address and payload data (if 'is_write') */ 210 value = REG_UPDATE_4(AUX_SW_DATA, 211 AUX_SW_INDEX, 0, 212 AUX_SW_DATA_RW, 0, 213 AUX_SW_AUTOINCREMENT_DISABLE, 1, 214 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 215 216 value = REG_SET_2(AUX_SW_DATA, value, 217 AUX_SW_AUTOINCREMENT_DISABLE, 0, 218 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 219 220 value = REG_SET(AUX_SW_DATA, value, 221 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 222 223 if (request->length) { 224 value = REG_SET(AUX_SW_DATA, value, 225 AUX_SW_DATA, request->length - 1); 226 } 227 228 if (is_write) { 229 /* Load the HW buffer with the Data to be sent. 230 * This is relevant for write operation. 231 * For read, the data recived data will be 232 * processed in process_channel_reply(). 233 */ 234 uint32_t i = 0; 235 236 while (i < request->length) { 237 value = REG_SET(AUX_SW_DATA, value, 238 AUX_SW_DATA, request->data[i]); 239 240 ++i; 241 } 242 } 243 244 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 245 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 246 10, aux110->timeout_period/10); 247 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 248 } 249 250 static int read_channel_reply(struct aux_engine *engine, uint32_t size, 251 uint8_t *buffer, uint8_t *reply_result, 252 uint32_t *sw_status) 253 { 254 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 255 uint32_t bytes_replied; 256 uint32_t reply_result_32; 257 258 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 259 &bytes_replied); 260 261 /* In case HPD is LOW, exit AUX transaction */ 262 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 263 return -1; 264 265 /* Need at least the status byte */ 266 if (!bytes_replied) 267 return -1; 268 269 REG_UPDATE_1BY1_3(AUX_SW_DATA, 270 AUX_SW_INDEX, 0, 271 AUX_SW_AUTOINCREMENT_DISABLE, 1, 272 AUX_SW_DATA_RW, 1); 273 274 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 275 reply_result_32 = reply_result_32 >> 4; 276 *reply_result = (uint8_t)reply_result_32; 277 278 if (reply_result_32 == 0) { /* ACK */ 279 uint32_t i = 0; 280 281 /* First byte was already used to get the command status */ 282 --bytes_replied; 283 284 /* Do not overflow buffer */ 285 if (bytes_replied > size) 286 return -1; 287 288 while (i < bytes_replied) { 289 uint32_t aux_sw_data_val; 290 291 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 292 buffer[i] = aux_sw_data_val; 293 ++i; 294 } 295 296 return i; 297 } 298 299 return 0; 300 } 301 302 static void process_channel_reply( 303 struct aux_engine *engine, 304 struct aux_reply_transaction_data *reply) 305 { 306 int bytes_replied; 307 uint8_t reply_result; 308 uint32_t sw_status; 309 310 bytes_replied = read_channel_reply(engine, reply->length, reply->data, 311 &reply_result, &sw_status); 312 313 /* in case HPD is LOW, exit AUX transaction */ 314 if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { 315 reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON; 316 return; 317 } 318 319 if (bytes_replied < 0) { 320 /* Need to handle an error case... 321 * Hopefully, upper layer function won't call this function if 322 * the number of bytes in the reply was 0, because there was 323 * surely an error that was asserted that should have been 324 * handled for hot plug case, this could happens 325 */ 326 if (!(sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) { 327 reply->status = AUX_TRANSACTION_REPLY_INVALID; 328 ASSERT_CRITICAL(false); 329 return; 330 } 331 } else { 332 333 switch (reply_result) { 334 case 0: /* ACK */ 335 reply->status = AUX_TRANSACTION_REPLY_AUX_ACK; 336 break; 337 case 1: /* NACK */ 338 reply->status = AUX_TRANSACTION_REPLY_AUX_NACK; 339 break; 340 case 2: /* DEFER */ 341 reply->status = AUX_TRANSACTION_REPLY_AUX_DEFER; 342 break; 343 case 4: /* AUX ACK / I2C NACK */ 344 reply->status = AUX_TRANSACTION_REPLY_I2C_NACK; 345 break; 346 case 8: /* AUX ACK / I2C DEFER */ 347 reply->status = AUX_TRANSACTION_REPLY_I2C_DEFER; 348 break; 349 default: 350 reply->status = AUX_TRANSACTION_REPLY_INVALID; 351 } 352 } 353 } 354 355 static enum aux_channel_operation_result get_channel_status( 356 struct aux_engine *engine, 357 uint8_t *returned_bytes) 358 { 359 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 360 361 uint32_t value; 362 363 if (returned_bytes == NULL) { 364 /*caller pass NULL pointer*/ 365 ASSERT_CRITICAL(false); 366 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; 367 } 368 *returned_bytes = 0; 369 370 /* poll to make sure that SW_DONE is asserted */ 371 value = REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 372 10, aux110->timeout_period/10); 373 374 /* in case HPD is LOW, exit AUX transaction */ 375 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 376 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; 377 378 /* Note that the following bits are set in 'status.bits' 379 * during CTS 4.2.1.2 (FW 3.3.1): 380 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 381 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 382 * 383 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 384 * HW debugging bit and should be ignored. 385 */ 386 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 387 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 388 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 389 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 390 391 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 392 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 393 (value & 394 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 395 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 396 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 397 398 *returned_bytes = get_reg_field_value(value, 399 AUX_SW_STATUS, 400 AUX_SW_REPLY_BYTE_COUNT); 401 402 if (*returned_bytes == 0) 403 return 404 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 405 else { 406 *returned_bytes -= 1; 407 return AUX_CHANNEL_OPERATION_SUCCEEDED; 408 } 409 } else { 410 /*time_elapsed >= aux_engine->timeout_period 411 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 412 */ 413 ASSERT_CRITICAL(false); 414 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 415 } 416 } 417 static void process_read_reply( 418 struct aux_engine *engine, 419 struct read_command_context *ctx) 420 { 421 engine->funcs->process_channel_reply(engine, &ctx->reply); 422 423 switch (ctx->reply.status) { 424 case AUX_TRANSACTION_REPLY_AUX_ACK: 425 ctx->defer_retry_aux = 0; 426 if (ctx->returned_byte > ctx->current_read_length) { 427 ctx->status = 428 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; 429 ctx->operation_succeeded = false; 430 } else if (ctx->returned_byte < ctx->current_read_length) { 431 ctx->current_read_length -= ctx->returned_byte; 432 433 ctx->offset += ctx->returned_byte; 434 435 ++ctx->invalid_reply_retry_aux_on_ack; 436 437 if (ctx->invalid_reply_retry_aux_on_ack > 438 AUX_INVALID_REPLY_RETRY_COUNTER) { 439 ctx->status = 440 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; 441 ctx->operation_succeeded = false; 442 } 443 } else { 444 ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; 445 ctx->transaction_complete = true; 446 ctx->operation_succeeded = true; 447 } 448 break; 449 case AUX_TRANSACTION_REPLY_AUX_NACK: 450 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; 451 ctx->operation_succeeded = false; 452 break; 453 case AUX_TRANSACTION_REPLY_AUX_DEFER: 454 ++ctx->defer_retry_aux; 455 456 if (ctx->defer_retry_aux > AUX_DEFER_RETRY_COUNTER) { 457 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 458 ctx->operation_succeeded = false; 459 } 460 break; 461 case AUX_TRANSACTION_REPLY_I2C_DEFER: 462 ctx->defer_retry_aux = 0; 463 464 ++ctx->defer_retry_i2c; 465 466 if (ctx->defer_retry_i2c > AUX_DEFER_RETRY_COUNTER) { 467 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 468 ctx->operation_succeeded = false; 469 } 470 break; 471 case AUX_TRANSACTION_REPLY_HPD_DISCON: 472 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; 473 ctx->operation_succeeded = false; 474 break; 475 default: 476 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; 477 ctx->operation_succeeded = false; 478 } 479 } 480 static void process_read_request( 481 struct aux_engine *engine, 482 struct read_command_context *ctx) 483 { 484 enum aux_channel_operation_result operation_result; 485 486 engine->funcs->submit_channel_request(engine, &ctx->request); 487 488 operation_result = engine->funcs->get_channel_status( 489 engine, &ctx->returned_byte); 490 491 switch (operation_result) { 492 case AUX_CHANNEL_OPERATION_SUCCEEDED: 493 if (ctx->returned_byte > ctx->current_read_length) { 494 ctx->status = 495 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; 496 ctx->operation_succeeded = false; 497 } else { 498 ctx->timed_out_retry_aux = 0; 499 ctx->invalid_reply_retry_aux = 0; 500 501 ctx->reply.length = ctx->returned_byte; 502 ctx->reply.data = ctx->buffer; 503 504 process_read_reply(engine, ctx); 505 } 506 break; 507 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: 508 ++ctx->invalid_reply_retry_aux; 509 510 if (ctx->invalid_reply_retry_aux > 511 AUX_INVALID_REPLY_RETRY_COUNTER) { 512 ctx->status = 513 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; 514 ctx->operation_succeeded = false; 515 } else 516 udelay(400); 517 break; 518 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: 519 ++ctx->timed_out_retry_aux; 520 521 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { 522 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 523 ctx->operation_succeeded = false; 524 } else { 525 /* DP 1.2a, table 2-58: 526 * "S3: AUX Request CMD PENDING: 527 * retry 3 times, with 400usec wait on each" 528 * The HW timeout is set to 550usec, 529 * so we should not wait here 530 */ 531 } 532 break; 533 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: 534 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; 535 ctx->operation_succeeded = false; 536 break; 537 default: 538 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; 539 ctx->operation_succeeded = false; 540 } 541 } 542 static bool read_command( 543 struct aux_engine *engine, 544 struct i2caux_transaction_request *request, 545 bool middle_of_transaction) 546 { 547 struct read_command_context ctx; 548 549 ctx.buffer = request->payload.data; 550 ctx.current_read_length = request->payload.length; 551 ctx.offset = 0; 552 ctx.timed_out_retry_aux = 0; 553 ctx.invalid_reply_retry_aux = 0; 554 ctx.defer_retry_aux = 0; 555 ctx.defer_retry_i2c = 0; 556 ctx.invalid_reply_retry_aux_on_ack = 0; 557 ctx.transaction_complete = false; 558 ctx.operation_succeeded = true; 559 560 if (request->payload.address_space == 561 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { 562 ctx.request.type = AUX_TRANSACTION_TYPE_DP; 563 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_READ; 564 ctx.request.address = request->payload.address; 565 } else if (request->payload.address_space == 566 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { 567 ctx.request.type = AUX_TRANSACTION_TYPE_I2C; 568 ctx.request.action = middle_of_transaction ? 569 I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT : 570 I2CAUX_TRANSACTION_ACTION_I2C_READ; 571 ctx.request.address = request->payload.address >> 1; 572 } else { 573 /* in DAL2, there was no return in such case */ 574 BREAK_TO_DEBUGGER(); 575 return false; 576 } 577 578 ctx.request.delay = 0; 579 580 do { 581 memset(ctx.buffer + ctx.offset, 0, ctx.current_read_length); 582 583 ctx.request.data = ctx.buffer + ctx.offset; 584 ctx.request.length = ctx.current_read_length; 585 586 process_read_request(engine, &ctx); 587 588 request->status = ctx.status; 589 590 if (ctx.operation_succeeded && !ctx.transaction_complete) 591 if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) 592 msleep(engine->delay); 593 } while (ctx.operation_succeeded && !ctx.transaction_complete); 594 595 if (request->payload.address_space == 596 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { 597 DC_LOG_I2C_AUX("READ: addr:0x%x value:0x%x Result:%d", 598 request->payload.address, 599 request->payload.data[0], 600 ctx.operation_succeeded); 601 } 602 603 return ctx.operation_succeeded; 604 } 605 606 static void process_write_reply( 607 struct aux_engine *engine, 608 struct write_command_context *ctx) 609 { 610 engine->funcs->process_channel_reply(engine, &ctx->reply); 611 612 switch (ctx->reply.status) { 613 case AUX_TRANSACTION_REPLY_AUX_ACK: 614 ctx->operation_succeeded = true; 615 616 if (ctx->returned_byte) { 617 ctx->request.action = ctx->mot ? 618 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : 619 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; 620 621 ctx->current_write_length = 0; 622 623 ++ctx->ack_m_retry; 624 625 if (ctx->ack_m_retry > AUX_DEFER_RETRY_COUNTER) { 626 ctx->status = 627 I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 628 ctx->operation_succeeded = false; 629 } else 630 udelay(300); 631 } else { 632 ctx->status = I2CAUX_TRANSACTION_STATUS_SUCCEEDED; 633 ctx->defer_retry_aux = 0; 634 ctx->ack_m_retry = 0; 635 ctx->transaction_complete = true; 636 } 637 break; 638 case AUX_TRANSACTION_REPLY_AUX_NACK: 639 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_NACK; 640 ctx->operation_succeeded = false; 641 break; 642 case AUX_TRANSACTION_REPLY_AUX_DEFER: 643 ++ctx->defer_retry_aux; 644 645 if (ctx->defer_retry_aux > ctx->max_defer_retry) { 646 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 647 ctx->operation_succeeded = false; 648 } 649 break; 650 case AUX_TRANSACTION_REPLY_I2C_DEFER: 651 ctx->defer_retry_aux = 0; 652 ctx->current_write_length = 0; 653 654 ctx->request.action = ctx->mot ? 655 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT : 656 I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST; 657 658 ++ctx->defer_retry_i2c; 659 660 if (ctx->defer_retry_i2c > ctx->max_defer_retry) { 661 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 662 ctx->operation_succeeded = false; 663 } 664 break; 665 case AUX_TRANSACTION_REPLY_HPD_DISCON: 666 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; 667 ctx->operation_succeeded = false; 668 break; 669 default: 670 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; 671 ctx->operation_succeeded = false; 672 } 673 } 674 static void process_write_request( 675 struct aux_engine *engine, 676 struct write_command_context *ctx) 677 { 678 enum aux_channel_operation_result operation_result; 679 680 engine->funcs->submit_channel_request(engine, &ctx->request); 681 682 operation_result = engine->funcs->get_channel_status( 683 engine, &ctx->returned_byte); 684 685 switch (operation_result) { 686 case AUX_CHANNEL_OPERATION_SUCCEEDED: 687 ctx->timed_out_retry_aux = 0; 688 ctx->invalid_reply_retry_aux = 0; 689 690 ctx->reply.length = ctx->returned_byte; 691 ctx->reply.data = ctx->reply_data; 692 693 process_write_reply(engine, ctx); 694 break; 695 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: 696 ++ctx->invalid_reply_retry_aux; 697 698 if (ctx->invalid_reply_retry_aux > 699 AUX_INVALID_REPLY_RETRY_COUNTER) { 700 ctx->status = 701 I2CAUX_TRANSACTION_STATUS_FAILED_PROTOCOL_ERROR; 702 ctx->operation_succeeded = false; 703 } else 704 udelay(400); 705 break; 706 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: 707 ++ctx->timed_out_retry_aux; 708 709 if (ctx->timed_out_retry_aux > AUX_TIMED_OUT_RETRY_COUNTER) { 710 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT; 711 ctx->operation_succeeded = false; 712 } else { 713 /* DP 1.2a, table 2-58: 714 * "S3: AUX Request CMD PENDING: 715 * retry 3 times, with 400usec wait on each" 716 * The HW timeout is set to 550usec, 717 * so we should not wait here 718 */ 719 } 720 break; 721 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: 722 ctx->status = I2CAUX_TRANSACTION_STATUS_FAILED_HPD_DISCON; 723 ctx->operation_succeeded = false; 724 break; 725 default: 726 ctx->status = I2CAUX_TRANSACTION_STATUS_UNKNOWN; 727 ctx->operation_succeeded = false; 728 } 729 } 730 static bool write_command( 731 struct aux_engine *engine, 732 struct i2caux_transaction_request *request, 733 bool middle_of_transaction) 734 { 735 struct write_command_context ctx; 736 737 ctx.mot = middle_of_transaction; 738 ctx.buffer = request->payload.data; 739 ctx.current_write_length = request->payload.length; 740 ctx.timed_out_retry_aux = 0; 741 ctx.invalid_reply_retry_aux = 0; 742 ctx.defer_retry_aux = 0; 743 ctx.defer_retry_i2c = 0; 744 ctx.ack_m_retry = 0; 745 ctx.transaction_complete = false; 746 ctx.operation_succeeded = true; 747 748 if (request->payload.address_space == 749 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { 750 ctx.request.type = AUX_TRANSACTION_TYPE_DP; 751 ctx.request.action = I2CAUX_TRANSACTION_ACTION_DP_WRITE; 752 ctx.request.address = request->payload.address; 753 } else if (request->payload.address_space == 754 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) { 755 ctx.request.type = AUX_TRANSACTION_TYPE_I2C; 756 ctx.request.action = middle_of_transaction ? 757 I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT : 758 I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 759 ctx.request.address = request->payload.address >> 1; 760 } else { 761 /* in DAL2, there was no return in such case */ 762 BREAK_TO_DEBUGGER(); 763 return false; 764 } 765 766 ctx.request.delay = 0; 767 768 ctx.max_defer_retry = 769 (engine->max_defer_write_retry > AUX_DEFER_RETRY_COUNTER) ? 770 engine->max_defer_write_retry : AUX_DEFER_RETRY_COUNTER; 771 772 do { 773 ctx.request.data = ctx.buffer; 774 ctx.request.length = ctx.current_write_length; 775 776 process_write_request(engine, &ctx); 777 778 request->status = ctx.status; 779 780 if (ctx.operation_succeeded && !ctx.transaction_complete) 781 if (ctx.request.type == AUX_TRANSACTION_TYPE_I2C) 782 msleep(engine->delay); 783 } while (ctx.operation_succeeded && !ctx.transaction_complete); 784 785 if (request->payload.address_space == 786 I2CAUX_TRANSACTION_ADDRESS_SPACE_DPCD) { 787 DC_LOG_I2C_AUX("WRITE: addr:0x%x value:0x%x Result:%d", 788 request->payload.address, 789 request->payload.data[0], 790 ctx.operation_succeeded); 791 } 792 793 return ctx.operation_succeeded; 794 } 795 static bool end_of_transaction_command( 796 struct aux_engine *engine, 797 struct i2caux_transaction_request *request) 798 { 799 struct i2caux_transaction_request dummy_request; 800 uint8_t dummy_data; 801 802 /* [tcheng] We only need to send the stop (read with MOT = 0) 803 * for I2C-over-Aux, not native AUX 804 */ 805 806 if (request->payload.address_space != 807 I2CAUX_TRANSACTION_ADDRESS_SPACE_I2C) 808 return false; 809 810 dummy_request.operation = request->operation; 811 dummy_request.payload.address_space = request->payload.address_space; 812 dummy_request.payload.address = request->payload.address; 813 814 /* 815 * Add a dummy byte due to some receiver quirk 816 * where one byte is sent along with MOT = 0. 817 * Ideally this should be 0. 818 */ 819 820 dummy_request.payload.length = 0; 821 dummy_request.payload.data = &dummy_data; 822 823 if (request->operation == I2CAUX_TRANSACTION_READ) 824 return read_command(engine, &dummy_request, false); 825 else 826 return write_command(engine, &dummy_request, false); 827 828 /* according Syed, it does not need now DoDummyMOT */ 829 } 830 static bool submit_request( 831 struct aux_engine *engine, 832 struct i2caux_transaction_request *request, 833 bool middle_of_transaction) 834 { 835 836 bool result; 837 bool mot_used = true; 838 839 switch (request->operation) { 840 case I2CAUX_TRANSACTION_READ: 841 result = read_command(engine, request, mot_used); 842 break; 843 case I2CAUX_TRANSACTION_WRITE: 844 result = write_command(engine, request, mot_used); 845 break; 846 default: 847 result = false; 848 } 849 850 /* [tcheng] 851 * need to send stop for the last transaction to free up the AUX 852 * if the above command fails, this would be the last transaction 853 */ 854 855 if (!middle_of_transaction || !result) 856 end_of_transaction_command(engine, request); 857 858 /* mask AUX interrupt */ 859 860 return result; 861 } 862 enum i2caux_engine_type get_engine_type( 863 const struct aux_engine *engine) 864 { 865 return I2CAUX_ENGINE_TYPE_AUX; 866 } 867 868 static bool acquire( 869 struct aux_engine *engine, 870 struct ddc *ddc) 871 { 872 873 enum gpio_result result; 874 875 if (engine->funcs->is_engine_available) { 876 /*check whether SW could use the engine*/ 877 if (!engine->funcs->is_engine_available(engine)) 878 return false; 879 } 880 881 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 882 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 883 884 if (result != GPIO_RESULT_OK) 885 return false; 886 887 if (!engine->funcs->acquire_engine(engine)) { 888 dal_ddc_close(ddc); 889 return false; 890 } 891 892 engine->ddc = ddc; 893 894 return true; 895 } 896 897 static const struct aux_engine_funcs aux_engine_funcs = { 898 .acquire_engine = acquire_engine, 899 .submit_channel_request = submit_channel_request, 900 .process_channel_reply = process_channel_reply, 901 .read_channel_reply = read_channel_reply, 902 .get_channel_status = get_channel_status, 903 .is_engine_available = is_engine_available, 904 .release_engine = release_engine, 905 .destroy_engine = dce110_engine_destroy, 906 .submit_request = submit_request, 907 .get_engine_type = get_engine_type, 908 .acquire = acquire, 909 }; 910 911 void dce110_engine_destroy(struct aux_engine **engine) 912 { 913 914 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 915 916 kfree(engine110); 917 *engine = NULL; 918 919 } 920 struct aux_engine *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 921 struct dc_context *ctx, 922 uint32_t inst, 923 uint32_t timeout_period, 924 const struct dce110_aux_registers *regs) 925 { 926 aux_engine110->base.ddc = NULL; 927 aux_engine110->base.ctx = ctx; 928 aux_engine110->base.delay = 0; 929 aux_engine110->base.max_defer_write_retry = 0; 930 aux_engine110->base.funcs = &aux_engine_funcs; 931 aux_engine110->base.inst = inst; 932 aux_engine110->timeout_period = timeout_period; 933 aux_engine110->regs = regs; 934 935 return &aux_engine110->base; 936 } 937 938