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