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 /* set the delay and the number of bytes to write */ 194 195 /* The length include 196 * the 4 bit header and the 20 bit address 197 * (that is 3 byte). 198 * If the requested length is non zero this means 199 * an addition byte specifying the length is required. 200 */ 201 202 length = request->length ? 4 : 3; 203 if (is_write) 204 length += request->length; 205 206 REG_UPDATE_2(AUX_SW_CONTROL, 207 AUX_SW_START_DELAY, request->delay, 208 AUX_SW_WR_BYTES, length); 209 210 /* program action and address and payload data (if 'is_write') */ 211 value = REG_UPDATE_4(AUX_SW_DATA, 212 AUX_SW_INDEX, 0, 213 AUX_SW_DATA_RW, 0, 214 AUX_SW_AUTOINCREMENT_DISABLE, 1, 215 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address)); 216 217 value = REG_SET_2(AUX_SW_DATA, value, 218 AUX_SW_AUTOINCREMENT_DISABLE, 0, 219 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address)); 220 221 value = REG_SET(AUX_SW_DATA, value, 222 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address)); 223 224 if (request->length) { 225 value = REG_SET(AUX_SW_DATA, value, 226 AUX_SW_DATA, request->length - 1); 227 } 228 229 if (is_write) { 230 /* Load the HW buffer with the Data to be sent. 231 * This is relevant for write operation. 232 * For read, the data recived data will be 233 * processed in process_channel_reply(). 234 */ 235 uint32_t i = 0; 236 237 while (i < request->length) { 238 value = REG_SET(AUX_SW_DATA, value, 239 AUX_SW_DATA, request->data[i]); 240 241 ++i; 242 } 243 } 244 245 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1); 246 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0, 247 10, aux110->timeout_period/10); 248 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1); 249 } 250 251 static int read_channel_reply(struct dce_aux *engine, uint32_t size, 252 uint8_t *buffer, uint8_t *reply_result, 253 uint32_t *sw_status) 254 { 255 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 256 uint32_t bytes_replied; 257 uint32_t reply_result_32; 258 259 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT, 260 &bytes_replied); 261 262 /* In case HPD is LOW, exit AUX transaction */ 263 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 264 return -1; 265 266 /* Need at least the status byte */ 267 if (!bytes_replied) 268 return -1; 269 270 REG_UPDATE_SEQ_3(AUX_SW_DATA, 271 AUX_SW_INDEX, 0, 272 AUX_SW_AUTOINCREMENT_DISABLE, 1, 273 AUX_SW_DATA_RW, 1); 274 275 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32); 276 reply_result_32 = reply_result_32 >> 4; 277 if (reply_result != NULL) 278 *reply_result = (uint8_t)reply_result_32; 279 280 if (reply_result_32 == 0) { /* ACK */ 281 uint32_t i = 0; 282 283 /* First byte was already used to get the command status */ 284 --bytes_replied; 285 286 /* Do not overflow buffer */ 287 if (bytes_replied > size) 288 return -1; 289 290 while (i < bytes_replied) { 291 uint32_t aux_sw_data_val; 292 293 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val); 294 buffer[i] = aux_sw_data_val; 295 ++i; 296 } 297 298 return i; 299 } 300 301 return 0; 302 } 303 304 static enum aux_channel_operation_result get_channel_status( 305 struct dce_aux *engine, 306 uint8_t *returned_bytes) 307 { 308 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine); 309 310 uint32_t value; 311 312 if (returned_bytes == NULL) { 313 /*caller pass NULL pointer*/ 314 ASSERT_CRITICAL(false); 315 return AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN; 316 } 317 *returned_bytes = 0; 318 319 /* poll to make sure that SW_DONE is asserted */ 320 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1, 321 10, aux110->timeout_period/10); 322 323 value = REG_READ(AUX_SW_STATUS); 324 /* in case HPD is LOW, exit AUX transaction */ 325 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) 326 return AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON; 327 328 /* Note that the following bits are set in 'status.bits' 329 * during CTS 4.2.1.2 (FW 3.3.1): 330 * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP, 331 * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H. 332 * 333 * AUX_SW_RX_MIN_COUNT_VIOL is an internal, 334 * HW debugging bit and should be ignored. 335 */ 336 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) { 337 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) || 338 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK)) 339 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 340 341 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) || 342 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) || 343 (value & 344 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) || 345 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK)) 346 return AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 347 348 *returned_bytes = get_reg_field_value(value, 349 AUX_SW_STATUS, 350 AUX_SW_REPLY_BYTE_COUNT); 351 352 if (*returned_bytes == 0) 353 return 354 AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY; 355 else { 356 *returned_bytes -= 1; 357 return AUX_CHANNEL_OPERATION_SUCCEEDED; 358 } 359 } else { 360 /*time_elapsed >= aux_engine->timeout_period 361 * AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point 362 */ 363 ASSERT_CRITICAL(false); 364 return AUX_CHANNEL_OPERATION_FAILED_TIMEOUT; 365 } 366 } 367 368 enum i2caux_engine_type get_engine_type( 369 const struct dce_aux *engine) 370 { 371 return I2CAUX_ENGINE_TYPE_AUX; 372 } 373 374 static bool acquire( 375 struct dce_aux *engine, 376 struct ddc *ddc) 377 { 378 enum gpio_result result; 379 380 if (!is_engine_available(engine)) 381 return false; 382 383 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE, 384 GPIO_DDC_CONFIG_TYPE_MODE_AUX); 385 386 if (result != GPIO_RESULT_OK) 387 return false; 388 389 if (!acquire_engine(engine)) { 390 dal_ddc_close(ddc); 391 return false; 392 } 393 394 engine->ddc = ddc; 395 396 return true; 397 } 398 399 void dce110_engine_destroy(struct dce_aux **engine) 400 { 401 402 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine); 403 404 kfree(engine110); 405 *engine = NULL; 406 407 } 408 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110, 409 struct dc_context *ctx, 410 uint32_t inst, 411 uint32_t timeout_period, 412 const struct dce110_aux_registers *regs) 413 { 414 aux_engine110->base.ddc = NULL; 415 aux_engine110->base.ctx = ctx; 416 aux_engine110->base.delay = 0; 417 aux_engine110->base.max_defer_write_retry = 0; 418 aux_engine110->base.inst = inst; 419 aux_engine110->timeout_period = timeout_period; 420 aux_engine110->regs = regs; 421 422 return &aux_engine110->base; 423 } 424 425 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload) 426 { 427 if (payload->i2c_over_aux) { 428 if (payload->write) { 429 if (payload->mot) 430 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT; 431 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE; 432 } 433 if (payload->mot) 434 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT; 435 return I2CAUX_TRANSACTION_ACTION_I2C_READ; 436 } 437 if (payload->write) 438 return I2CAUX_TRANSACTION_ACTION_DP_WRITE; 439 return I2CAUX_TRANSACTION_ACTION_DP_READ; 440 } 441 442 int dce_aux_transfer_raw(struct ddc_service *ddc, 443 struct aux_payload *payload, 444 enum aux_channel_operation_result *operation_result) 445 { 446 struct ddc *ddc_pin = ddc->ddc_pin; 447 struct dce_aux *aux_engine; 448 struct aux_request_transaction_data aux_req; 449 struct aux_reply_transaction_data aux_rep; 450 uint8_t returned_bytes = 0; 451 int res = -1; 452 uint32_t status; 453 454 memset(&aux_req, 0, sizeof(aux_req)); 455 memset(&aux_rep, 0, sizeof(aux_rep)); 456 457 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en]; 458 if (!acquire(aux_engine, ddc_pin)) 459 return -1; 460 461 if (payload->i2c_over_aux) 462 aux_req.type = AUX_TRANSACTION_TYPE_I2C; 463 else 464 aux_req.type = AUX_TRANSACTION_TYPE_DP; 465 466 aux_req.action = i2caux_action_from_payload(payload); 467 468 aux_req.address = payload->address; 469 aux_req.delay = payload->defer_delay * 10; 470 aux_req.length = payload->length; 471 aux_req.data = payload->data; 472 473 submit_channel_request(aux_engine, &aux_req); 474 *operation_result = get_channel_status(aux_engine, &returned_bytes); 475 476 if (*operation_result == AUX_CHANNEL_OPERATION_SUCCEEDED) { 477 read_channel_reply(aux_engine, payload->length, 478 payload->data, payload->reply, 479 &status); 480 res = returned_bytes; 481 } else { 482 res = -1; 483 } 484 485 release_engine(aux_engine); 486 return res; 487 } 488 489 #define AUX_MAX_RETRIES 7 490 #define AUX_MAX_DEFER_RETRIES 7 491 #define AUX_MAX_I2C_DEFER_RETRIES 7 492 #define AUX_MAX_INVALID_REPLY_RETRIES 2 493 #define AUX_MAX_TIMEOUT_RETRIES 3 494 495 bool dce_aux_transfer_with_retries(struct ddc_service *ddc, 496 struct aux_payload *payload) 497 { 498 int i, ret = 0; 499 uint8_t reply; 500 bool payload_reply = true; 501 enum aux_channel_operation_result operation_result; 502 int aux_ack_retries = 0, 503 aux_defer_retries = 0, 504 aux_i2c_defer_retries = 0, 505 aux_timeout_retries = 0, 506 aux_invalid_reply_retries = 0; 507 508 if (!payload->reply) { 509 payload_reply = false; 510 payload->reply = &reply; 511 } 512 513 for (i = 0; i < AUX_MAX_RETRIES; i++) { 514 ret = dce_aux_transfer_raw(ddc, payload, &operation_result); 515 switch (operation_result) { 516 case AUX_CHANNEL_OPERATION_SUCCEEDED: 517 aux_timeout_retries = 0; 518 aux_invalid_reply_retries = 0; 519 520 switch (*payload->reply) { 521 case AUX_TRANSACTION_REPLY_AUX_ACK: 522 if (!payload->write && payload->length != ret) { 523 if (++aux_ack_retries >= AUX_MAX_RETRIES) 524 goto fail; 525 else 526 udelay(300); 527 } else 528 return true; 529 break; 530 531 case AUX_TRANSACTION_REPLY_AUX_DEFER: 532 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK: 533 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER: 534 if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) 535 goto fail; 536 break; 537 538 case AUX_TRANSACTION_REPLY_I2C_DEFER: 539 aux_defer_retries = 0; 540 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) 541 goto fail; 542 break; 543 544 case AUX_TRANSACTION_REPLY_AUX_NACK: 545 case AUX_TRANSACTION_REPLY_HPD_DISCON: 546 default: 547 goto fail; 548 } 549 break; 550 551 case AUX_CHANNEL_OPERATION_FAILED_INVALID_REPLY: 552 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) 553 goto fail; 554 else 555 udelay(400); 556 break; 557 558 case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT: 559 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) 560 goto fail; 561 else { 562 /* 563 * DP 1.4, 2.8.2: AUX Transaction Response/Reply Timeouts 564 * According to the DP spec there should be 3 retries total 565 * with a 400us wait inbetween each. Hardware already waits 566 * for 550us therefore no wait is required here. 567 */ 568 } 569 break; 570 571 case AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON: 572 case AUX_CHANNEL_OPERATION_FAILED_REASON_UNKNOWN: 573 default: 574 goto fail; 575 } 576 } 577 578 fail: 579 if (!payload_reply) 580 payload->reply = NULL; 581 return false; 582 } 583