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 31 #define CTX \ 32 aux110->base.ctx 33 #define REG(reg_name)\ 34 (aux110->regs->reg_name) 35 36 #define DC_LOGGER \ 37 engine->ctx->logger 38 39 #include "reg_helper.h" 40 41 #define FROM_AUX_ENGINE(ptr) \ 42 container_of((ptr), struct aux_engine_dce110, base) 43 44 #define FROM_ENGINE(ptr) \ 45 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base)) 46 47 #define FROM_AUX_ENGINE_ENGINE(ptr) \ 48 container_of((ptr), struct dce_aux, base) 49 enum { 50 AUX_INVALID_REPLY_RETRY_COUNTER = 1, 51 AUX_TIMED_OUT_RETRY_COUNTER = 2, 52 AUX_DEFER_RETRY_COUNTER = 6 53 }; 54 static void release_engine( 55 struct dce_aux *engine) 56 { 57 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 58 59 dal_ddc_close(engine->ddc); 60 61 engine->ddc = NULL; 62 63 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1); 64 } 65 66 #define SW_CAN_ACCESS_AUX 1 67 #define DMCU_CAN_ACCESS_AUX 2 68 69 static bool is_engine_available( 70 struct dce_aux *engine) 71 { 72 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 73 74 uint32_t value = REG_READ(AUX_ARB_CONTROL); 75 uint32_t field = get_reg_field_value( 76 value, 77 AUX_ARB_CONTROL, 78 AUX_REG_RW_CNTL_STATUS); 79 80 return (field != DMCU_CAN_ACCESS_AUX); 81 } 82 static bool acquire_engine( 83 struct dce_aux *engine) 84 { 85 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 86 87 uint32_t value = REG_READ(AUX_ARB_CONTROL); 88 uint32_t field = get_reg_field_value( 89 value, 90 AUX_ARB_CONTROL, 91 AUX_REG_RW_CNTL_STATUS); 92 if (field == DMCU_CAN_ACCESS_AUX) 93 return false; 94 /* enable AUX before request SW to access AUX */ 95 value = REG_READ(AUX_CONTROL); 96 field = get_reg_field_value(value, 97 AUX_CONTROL, 98 AUX_EN); 99 100 if (field == 0) { 101 set_reg_field_value( 102 value, 103 1, 104 AUX_CONTROL, 105 AUX_EN); 106 107 if (REG(AUX_RESET_MASK)) { 108 /*DP_AUX block as part of the enable sequence*/ 109 set_reg_field_value( 110 value, 111 1, 112 AUX_CONTROL, 113 AUX_RESET); 114 } 115 116 REG_WRITE(AUX_CONTROL, value); 117 118 if (REG(AUX_RESET_MASK)) { 119 /*poll HW to make sure reset it done*/ 120 121 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1, 122 1, 11); 123 124 set_reg_field_value( 125 value, 126 0, 127 AUX_CONTROL, 128 AUX_RESET); 129 130 REG_WRITE(AUX_CONTROL, value); 131 132 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0, 133 1, 11); 134 } 135 } /*if (field)*/ 136 137 /* request SW to access AUX */ 138 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1); 139 140 value = REG_READ(AUX_ARB_CONTROL); 141 field = get_reg_field_value( 142 value, 143 AUX_ARB_CONTROL, 144 AUX_REG_RW_CNTL_STATUS); 145 146 return (field == SW_CAN_ACCESS_AUX); 147 } 148 149 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \ 150 ((command) | ((0xF0000 & (address)) >> 16)) 151 152 #define COMPOSE_AUX_SW_DATA_8_15(address) \ 153 ((0xFF00 & (address)) >> 8) 154 155 #define COMPOSE_AUX_SW_DATA_0_7(address) \ 156 (0xFF & (address)) 157 158 static void submit_channel_request( 159 struct dce_aux *engine, 160 struct aux_request_transaction_data *request) 161 { 162 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 163 uint32_t value; 164 uint32_t length; 165 166 bool is_write = 167 ((request->type == AUX_TRANSACTION_TYPE_DP) && 168 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) || 169 ((request->type == AUX_TRANSACTION_TYPE_I2C) && 170 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) || 171 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT))); 172 if (REG(AUXN_IMPCAL)) { 173 /* clear_aux_error */ 174 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 175 AUXN_CALOUT_ERROR_AK, 1, 176 AUXN_CALOUT_ERROR_AK, 0); 177 178 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 179 AUXP_CALOUT_ERROR_AK, 1, 180 AUXP_CALOUT_ERROR_AK, 0); 181 182 /* force_default_calibrate */ 183 REG_UPDATE_SEQ_2(AUXN_IMPCAL, 184 AUXN_IMPCAL_ENABLE, 1, 185 AUXN_IMPCAL_OVERRIDE_ENABLE, 0); 186 187 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */ 188 189 REG_UPDATE_SEQ_2(AUXP_IMPCAL, 190 AUXP_IMPCAL_OVERRIDE_ENABLE, 1, 191 AUXP_IMPCAL_OVERRIDE_ENABLE, 0); 192 } 193 194 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 195 196 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 197 10, aux110->timeout_period/10); 198 199 /* set the delay and the number of bytes to write */ 200 201 /* The length include 202 * the 4 bit header and the 20 bit address 203 * (that is 3 byte). 204 * If the requested length is non zero this means 205 * an addition byte specifying the length is required. 206 */ 207 208 length = request->length ? 4 : 3; 209 if (is_write) 210 length += request->length; 211 212 REG_UPDATE_2(AUX_SW_CONTROL, 213 AUX_SW_START_DELAY, request->delay, 214 AUX_SW_WR_BYTES, length); 215 216 /* program action and address and payload data (if 'is_write') */ 217 value = REG_UPDATE_4(AUX_SW_DATA, 218 AUX_SW_INDEX, 0, 219 AUX_SW_DATA_RW, 0, 220 AUX_SW_AUTOINCREMENT_DISABLE, 1, 221 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 222 223 value = REG_SET_2(AUX_SW_DATA, value, 224 AUX_SW_AUTOINCREMENT_DISABLE, 0, 225 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 226 227 value = REG_SET(AUX_SW_DATA, value, 228 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 229 230 if (request->length) { 231 value = REG_SET(AUX_SW_DATA, value, 232 AUX_SW_DATA, request->length - 1); 233 } 234 235 if (is_write) { 236 /* Load the HW buffer with the Data to be sent. 237 * This is relevant for write operation. 238 * For read, the data recived data will be 239 * processed in process_channel_reply(). 240 */ 241 uint32_t i = 0; 242 243 while (i < request->length) { 244 value = REG_SET(AUX_SW_DATA, value, 245 AUX_SW_DATA, request->data[i]); 246 247 ++i; 248 } 249 } 250 251 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 252 } 253 254 static int read_channel_reply(struct dce_aux *engine, uint32_t size, 255 uint8_t *buffer, uint8_t *reply_result, 256 uint32_t *sw_status) 257 { 258 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 259 uint32_t bytes_replied; 260 uint32_t reply_result_32; 261 262 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 263 &bytes_replied); 264 265 /* In case HPD is LOW, exit AUX transaction */ 266 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 267 return -1; 268 269 /* Need at least the status byte */ 270 if (!bytes_replied) 271 return -1; 272 273 REG_UPDATE_SEQ_3(AUX_SW_DATA, 274 AUX_SW_INDEX, 0, 275 AUX_SW_AUTOINCREMENT_DISABLE, 1, 276 AUX_SW_DATA_RW, 1); 277 278 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 279 reply_result_32 = reply_result_32 >> 4; 280 if (reply_result != NULL) 281 *reply_result = (uint8_t)reply_result_32; 282 283 if (reply_result_32 == 0) { /* ACK */ 284 uint32_t i = 0; 285 286 /* First byte was already used to get the command status */ 287 --bytes_replied; 288 289 /* Do not overflow buffer */ 290 if (bytes_replied > size) 291 return -1; 292 293 while (i < bytes_replied) { 294 uint32_t aux_sw_data_val; 295 296 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 297 buffer[i] = aux_sw_data_val; 298 ++i; 299 } 300 301 return i; 302 } 303 304 return 0; 305 } 306 307 static enum aux_channel_operation_result get_channel_status( 308 struct dce_aux *engine, 309 uint8_t *returned_bytes) 310 { 311 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 312 313 uint32_t value; 314 315 if (returned_bytes == NULL) { 316 /*caller pass NULL pointer*/ 317 ASSERT_CRITICAL(false); 318 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; 319 } 320 *returned_bytes = 0; 321 322 /* poll to make sure that SW_DONE is asserted */ 323 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 324 10, aux110->timeout_period/10); 325 326 value = REG_READ(AUX_SW_STATUS); 327 /* in case HPD is LOW, exit AUX transaction */ 328 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 329 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; 330 331 /* Note that the following bits are set in 'status.bits' 332 * during CTS 4.2.1.2 (FW 3.3.1): 333 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 334 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 335 * 336 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 337 * HW debugging bit and should be ignored. 338 */ 339 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 340 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 341 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 342 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 343 344 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 345 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 346 (value & 347 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 348 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 349 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 350 351 *returned_bytes = get_reg_field_value(value, 352 AUX_SW_STATUS, 353 AUX_SW_REPLY_BYTE_COUNT); 354 355 if (*returned_bytes == 0) 356 return 357 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 358 else { 359 *returned_bytes -= 1; 360 return AUX_CHANNEL_OPERATION_SUCCEEDED; 361 } 362 } else { 363 /*time_elapsed >= aux_engine->timeout_period 364 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 365 */ 366 ASSERT_CRITICAL(false); 367 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 368 } 369 } 370 371 enum i2caux_engine_type get_engine_type( 372 const struct dce_aux *engine) 373 { 374 return I2CAUX_ENGINE_TYPE_AUX; 375 } 376 377 static bool acquire( 378 struct dce_aux *engine, 379 struct ddc *ddc) 380 { 381 enum gpio_result result; 382 383 if (!is_engine_available(engine)) 384 return false; 385 386 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 387 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 388 389 if (result != GPIO_RESULT_OK) 390 return false; 391 392 if (!acquire_engine(engine)) { 393 dal_ddc_close(ddc); 394 return false; 395 } 396 397 engine->ddc = ddc; 398 399 return true; 400 } 401 402 void dce110_engine_destroy(struct dce_aux **engine) 403 { 404 405 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 406 407 kfree(engine110); 408 *engine = NULL; 409 410 } 411 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 412 struct dc_context *ctx, 413 uint32_t inst, 414 uint32_t timeout_period, 415 const struct dce110_aux_registers *regs) 416 { 417 aux_engine110->base.ddc = NULL; 418 aux_engine110->base.ctx = ctx; 419 aux_engine110->base.delay = 0; 420 aux_engine110->base.max_defer_write_retry = 0; 421 aux_engine110->base.inst = inst; 422 aux_engine110->timeout_period = timeout_period; 423 aux_engine110->regs = regs; 424 425 return &aux_engine110->base; 426 } 427 428 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) 429 { 430 if (payload->i2c_over_aux) { 431 if (payload->write) { 432 if (payload->mot) 433 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; 434 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 435 } 436 if (payload->mot) 437 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; 438 return I2CAUX_TRANSACTION_ACTION_I2C_READ; 439 } 440 if (payload->write) 441 return I2CAUX_TRANSACTION_ACTION_DP_WRITE; 442 return I2CAUX_TRANSACTION_ACTION_DP_READ; 443 } 444 445 int dce_aux_transfer_raw(struct ddc_service *ddc, 446 struct aux_payload *payload, 447 enum aux_channel_operation_result *operation_result) 448 { 449 struct ddc *ddc_pin = ddc->ddc_pin; 450 struct dce_aux *aux_engine; 451 struct aux_request_transaction_data aux_req; 452 struct aux_reply_transaction_data aux_rep; 453 uint8_t returned_bytes = 0; 454 int res = -1; 455 uint32_t status; 456 457 memset(&aux_req, 0, sizeof(aux_req)); 458 memset(&aux_rep, 0, sizeof(aux_rep)); 459 460 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 461 if (!acquire(aux_engine, ddc_pin)) 462 return -1; 463 464 if (payload->i2c_over_aux) 465 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 466 else 467 aux_req.type = AUX_TRANSACTION_TYPE_DP; 468 469 aux_req.action = i2caux_action_from_payload(payload); 470 471 aux_req.address = payload->address; 472 aux_req.delay = payload->defer_delay * 10; 473 aux_req.length = payload->length; 474 aux_req.data = payload->data; 475 476 submit_channel_request(aux_engine, &aux_req); 477 *operation_result = get_channel_status(aux_engine, &returned_bytes); 478 479 if (*operation_result == AUX_CHANNEL_OPERATION_SUCCEEDED) { 480 read_channel_reply(aux_engine, payload->length, 481 payload->data, payload->reply, 482 &status); 483 res = returned_bytes; 484 } else { 485 res = -1; 486 } 487 488 release_engine(aux_engine); 489 return res; 490 } 491 492 #define AUX_MAX_RETRIES 7 493 #define AUX_MAX_DEFER_RETRIES 7 494 #define AUX_MAX_I2C_DEFER_RETRIES 7 495 #define AUX_MAX_INVALID_REPLY_RETRIES 2 496 #define AUX_MAX_TIMEOUT_RETRIES 3 497 498 bool dce_aux_transfer_with_retries(struct ddc_service *ddc, 499 struct aux_payload *payload) 500 { 501 int i, ret = 0; 502 uint8_t reply; 503 bool payload_reply = true; 504 enum aux_channel_operation_result operation_result; 505 int aux_ack_retries = 0, 506 aux_defer_retries = 0, 507 aux_i2c_defer_retries = 0, 508 aux_timeout_retries = 0, 509 aux_invalid_reply_retries = 0; 510 511 if (!payload->reply) { 512 payload_reply = false; 513 payload->reply = &reply; 514 } 515 516 for (i = 0; i < AUX_MAX_RETRIES; i++) { 517 ret = dce_aux_transfer_raw(ddc, payload, &operation_result); 518 switch (operation_result) { 519 case AUX_CHANNEL_OPERATION_SUCCEEDED: 520 aux_timeout_retries = 0; 521 aux_invalid_reply_retries = 0; 522 523 switch (*payload->reply) { 524 case AUX_TRANSACTION_REPLY_AUX_ACK: 525 if (!payload->write && payload->length != ret) { 526 if (++aux_ack_retries >= AUX_MAX_RETRIES) 527 goto fail; 528 else 529 udelay(300); 530 } else 531 return true; 532 break; 533 534 case AUX_TRANSACTION_REPLY_AUX_DEFER: 535 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 536 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 537 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) 538 goto fail; 539 break; 540 541 case AUX_TRANSACTION_REPLY_I2C_DEFER: 542 aux_defer_retries = 0; 543 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) 544 goto fail; 545 break; 546 547 case AUX_TRANSACTION_REPLY_AUX_NACK: 548 case AUX_TRANSACTION_REPLY_HPD_DISCON: 549 default: 550 goto fail; 551 } 552 break; 553 554 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: 555 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) 556 goto fail; 557 else 558 udelay(400); 559 break; 560 561 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: 562 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) 563 goto fail; 564 else { 565 /* 566 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts 567 * According to the DP spec there should be 3 retries total 568 * with a 400us wait inbetween each. Hardware already waits 569 * for 550us therefore no wait is required here. 570 */ 571 } 572 break; 573 574 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: 575 case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN: 576 default: 577 goto fail; 578 } 579 } 580 581 fail: 582 if (!payload_reply) 583 payload->reply = NULL; 584 return false; 585 } 586