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