0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027 #include "core_types.h"
0028 #include "dce_aux.h"
0029 #include "dce/dce_11_0_sh_mask.h"
0030 #include "dm_event_log.h"
0031 #include "dm_helpers.h"
0032 #include "dmub/inc/dmub_cmd.h"
0033
0034 #define CTX \
0035 aux110->base.ctx
0036 #define REG(reg_name)\
0037 (aux110->regs->reg_name)
0038
0039 #define DC_LOGGER \
0040 engine->ctx->logger
0041
0042 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)
0043 #define IS_DC_I2CAUX_LOGGING_ENABLED() (false)
0044 #define LOG_FLAG_Error_I2cAux LOG_ERROR
0045 #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX
0046
0047 #include "reg_helper.h"
0048
0049 #undef FN
0050 #define FN(reg_name, field_name) \
0051 aux110->shift->field_name, aux110->mask->field_name
0052
0053 #define FROM_AUX_ENGINE(ptr) \
0054 container_of((ptr), struct aux_engine_dce110, base)
0055
0056 #define FROM_ENGINE(ptr) \
0057 FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base))
0058
0059 #define FROM_AUX_ENGINE_ENGINE(ptr) \
0060 container_of((ptr), struct dce_aux, base)
0061 enum {
0062 AUX_INVALID_REPLY_RETRY_COUNTER = 1,
0063 AUX_TIMED_OUT_RETRY_COUNTER = 2,
0064 AUX_DEFER_RETRY_COUNTER = 6
0065 };
0066
0067 #define TIME_OUT_INCREMENT 1016
0068 #define TIME_OUT_MULTIPLIER_8 8
0069 #define TIME_OUT_MULTIPLIER_16 16
0070 #define TIME_OUT_MULTIPLIER_32 32
0071 #define TIME_OUT_MULTIPLIER_64 64
0072 #define MAX_TIMEOUT_LENGTH 127
0073 #define DEFAULT_AUX_ENGINE_MULT 0
0074 #define DEFAULT_AUX_ENGINE_LENGTH 69
0075
0076 #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)
0077
0078 static void release_engine(
0079 struct dce_aux *engine)
0080 {
0081 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0082
0083 dal_ddc_close(engine->ddc);
0084
0085 engine->ddc = NULL;
0086
0087 REG_UPDATE_2(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1,
0088 AUX_SW_USE_AUX_REG_REQ, 0);
0089 }
0090
0091 #define SW_CAN_ACCESS_AUX 1
0092 #define DMCU_CAN_ACCESS_AUX 2
0093
0094 static bool is_engine_available(
0095 struct dce_aux *engine)
0096 {
0097 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0098
0099 uint32_t value = REG_READ(AUX_ARB_CONTROL);
0100 uint32_t field = get_reg_field_value(
0101 value,
0102 AUX_ARB_CONTROL,
0103 AUX_REG_RW_CNTL_STATUS);
0104
0105 return (field != DMCU_CAN_ACCESS_AUX);
0106 }
0107 static bool acquire_engine(
0108 struct dce_aux *engine)
0109 {
0110 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0111
0112 uint32_t value = REG_READ(AUX_ARB_CONTROL);
0113 uint32_t field = get_reg_field_value(
0114 value,
0115 AUX_ARB_CONTROL,
0116 AUX_REG_RW_CNTL_STATUS);
0117 if (field == DMCU_CAN_ACCESS_AUX)
0118 return false;
0119
0120 value = REG_READ(AUX_CONTROL);
0121 field = get_reg_field_value(value,
0122 AUX_CONTROL,
0123 AUX_EN);
0124
0125 if (field == 0) {
0126 set_reg_field_value(
0127 value,
0128 1,
0129 AUX_CONTROL,
0130 AUX_EN);
0131
0132 if (REG(AUX_RESET_MASK)) {
0133
0134 set_reg_field_value(
0135 value,
0136 1,
0137 AUX_CONTROL,
0138 AUX_RESET);
0139 }
0140
0141 REG_WRITE(AUX_CONTROL, value);
0142
0143 if (REG(AUX_RESET_MASK)) {
0144
0145
0146 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
0147 1, 11);
0148
0149 set_reg_field_value(
0150 value,
0151 0,
0152 AUX_CONTROL,
0153 AUX_RESET);
0154
0155 REG_WRITE(AUX_CONTROL, value);
0156
0157 REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
0158 1, 11);
0159 }
0160 }
0161
0162
0163 REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
0164
0165 value = REG_READ(AUX_ARB_CONTROL);
0166 field = get_reg_field_value(
0167 value,
0168 AUX_ARB_CONTROL,
0169 AUX_REG_RW_CNTL_STATUS);
0170
0171 return (field == SW_CAN_ACCESS_AUX);
0172 }
0173
0174 #define COMPOSE_AUX_SW_DATA_16_20(command, address) \
0175 ((command) | ((0xF0000 & (address)) >> 16))
0176
0177 #define COMPOSE_AUX_SW_DATA_8_15(address) \
0178 ((0xFF00 & (address)) >> 8)
0179
0180 #define COMPOSE_AUX_SW_DATA_0_7(address) \
0181 (0xFF & (address))
0182
0183 static void submit_channel_request(
0184 struct dce_aux *engine,
0185 struct aux_request_transaction_data *request)
0186 {
0187 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0188 uint32_t value;
0189 uint32_t length;
0190
0191 bool is_write =
0192 ((request->type == AUX_TRANSACTION_TYPE_DP) &&
0193 (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
0194 ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
0195 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
0196 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
0197 if (REG(AUXN_IMPCAL)) {
0198
0199 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
0200 AUXN_CALOUT_ERROR_AK, 1,
0201 AUXN_CALOUT_ERROR_AK, 0);
0202
0203 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
0204 AUXP_CALOUT_ERROR_AK, 1,
0205 AUXP_CALOUT_ERROR_AK, 0);
0206
0207
0208 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
0209 AUXN_IMPCAL_ENABLE, 1,
0210 AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
0211
0212
0213
0214 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
0215 AUXP_IMPCAL_OVERRIDE_ENABLE, 1,
0216 AUXP_IMPCAL_OVERRIDE_ENABLE, 0);
0217 }
0218
0219 REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
0220
0221 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
0222 10, aux110->polling_timeout_period/10);
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233 length = request->length ? 4 : 3;
0234 if (is_write)
0235 length += request->length;
0236
0237 REG_UPDATE_2(AUX_SW_CONTROL,
0238 AUX_SW_START_DELAY, request->delay,
0239 AUX_SW_WR_BYTES, length);
0240
0241
0242 value = REG_UPDATE_4(AUX_SW_DATA,
0243 AUX_SW_INDEX, 0,
0244 AUX_SW_DATA_RW, 0,
0245 AUX_SW_AUTOINCREMENT_DISABLE, 1,
0246 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
0247
0248 value = REG_SET_2(AUX_SW_DATA, value,
0249 AUX_SW_AUTOINCREMENT_DISABLE, 0,
0250 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
0251
0252 value = REG_SET(AUX_SW_DATA, value,
0253 AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
0254
0255 if (request->length) {
0256 value = REG_SET(AUX_SW_DATA, value,
0257 AUX_SW_DATA, request->length - 1);
0258 }
0259
0260 if (is_write) {
0261
0262
0263
0264
0265
0266 uint32_t i = 0;
0267
0268 while (i < request->length) {
0269 value = REG_SET(AUX_SW_DATA, value,
0270 AUX_SW_DATA, request->data[i]);
0271
0272 ++i;
0273 }
0274 }
0275
0276 REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
0277 EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
0278 request->action, request->address, request->length, request->data);
0279 }
0280
0281 static int read_channel_reply(struct dce_aux *engine, uint32_t size,
0282 uint8_t *buffer, uint8_t *reply_result,
0283 uint32_t *sw_status)
0284 {
0285 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0286 uint32_t bytes_replied;
0287 uint32_t reply_result_32;
0288
0289 *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
0290 &bytes_replied);
0291
0292
0293 if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
0294 return -1;
0295
0296
0297 if (!bytes_replied)
0298 return -1;
0299
0300 REG_UPDATE_SEQ_3(AUX_SW_DATA,
0301 AUX_SW_INDEX, 0,
0302 AUX_SW_AUTOINCREMENT_DISABLE, 1,
0303 AUX_SW_DATA_RW, 1);
0304
0305 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
0306 reply_result_32 = reply_result_32 >> 4;
0307 if (reply_result != NULL)
0308 *reply_result = (uint8_t)reply_result_32;
0309
0310 if (reply_result_32 == 0) {
0311 uint32_t i = 0;
0312
0313
0314 --bytes_replied;
0315
0316
0317 if (bytes_replied > size)
0318 return -1;
0319
0320 while (i < bytes_replied) {
0321 uint32_t aux_sw_data_val;
0322
0323 REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
0324 buffer[i] = aux_sw_data_val;
0325 ++i;
0326 }
0327
0328 return i;
0329 }
0330
0331 return 0;
0332 }
0333
0334 static enum aux_return_code_type get_channel_status(
0335 struct dce_aux *engine,
0336 uint8_t *returned_bytes)
0337 {
0338 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
0339
0340 uint32_t value;
0341
0342 if (returned_bytes == NULL) {
0343
0344 ASSERT_CRITICAL(false);
0345 return AUX_RET_ERROR_UNKNOWN;
0346 }
0347 *returned_bytes = 0;
0348
0349
0350 REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
0351 10, aux110->polling_timeout_period/10);
0352
0353 value = REG_READ(AUX_SW_STATUS);
0354
0355 if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
0356 return AUX_RET_ERROR_HPD_DISCON;
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366 if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
0367 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
0368 (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
0369 return AUX_RET_ERROR_TIMEOUT;
0370
0371 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
0372 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
0373 (value &
0374 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
0375 (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
0376 return AUX_RET_ERROR_INVALID_REPLY;
0377
0378 *returned_bytes = get_reg_field_value(value,
0379 AUX_SW_STATUS,
0380 AUX_SW_REPLY_BYTE_COUNT);
0381
0382 if (*returned_bytes == 0)
0383 return
0384 AUX_RET_ERROR_INVALID_REPLY;
0385 else {
0386 *returned_bytes -= 1;
0387 return AUX_RET_SUCCESS;
0388 }
0389 } else {
0390
0391
0392
0393 ASSERT_CRITICAL(false);
0394 return AUX_RET_ERROR_TIMEOUT;
0395 }
0396 }
0397
0398 static bool acquire(
0399 struct dce_aux *engine,
0400 struct ddc *ddc)
0401 {
0402 enum gpio_result result;
0403
0404 if ((engine == NULL) || !is_engine_available(engine))
0405 return false;
0406
0407 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
0408 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
0409
0410 if (result != GPIO_RESULT_OK)
0411 return false;
0412
0413 if (!acquire_engine(engine)) {
0414 engine->ddc = ddc;
0415 release_engine(engine);
0416 return false;
0417 }
0418
0419 engine->ddc = ddc;
0420
0421 return true;
0422 }
0423
0424 void dce110_engine_destroy(struct dce_aux **engine)
0425 {
0426
0427 struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
0428
0429 kfree(engine110);
0430 *engine = NULL;
0431
0432 }
0433
0434 static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
0435 uint32_t timeout_in_us)
0436 {
0437 uint32_t multiplier = 0;
0438 uint32_t length = 0;
0439 uint32_t prev_length = 0;
0440 uint32_t prev_mult = 0;
0441 uint32_t prev_timeout_val = 0;
0442 struct ddc *ddc_pin = ddc->ddc_pin;
0443 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
0444 struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
0445
0446
0447 aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
0448
0449
0450 if (timeout_in_us == 0) {
0451 multiplier = DEFAULT_AUX_ENGINE_MULT;
0452 length = DEFAULT_AUX_ENGINE_LENGTH;
0453 } else if (timeout_in_us <= TIME_OUT_INCREMENT) {
0454 multiplier = 0;
0455 length = timeout_in_us/TIME_OUT_MULTIPLIER_8;
0456 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0)
0457 length++;
0458 } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) {
0459 multiplier = 1;
0460 length = timeout_in_us/TIME_OUT_MULTIPLIER_16;
0461 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0)
0462 length++;
0463 } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) {
0464 multiplier = 2;
0465 length = timeout_in_us/TIME_OUT_MULTIPLIER_32;
0466 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0)
0467 length++;
0468 } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) {
0469 multiplier = 3;
0470 length = timeout_in_us/TIME_OUT_MULTIPLIER_64;
0471 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0)
0472 length++;
0473 }
0474
0475 length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH;
0476
0477 REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult);
0478
0479 switch (prev_mult) {
0480 case 0:
0481 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8;
0482 break;
0483 case 1:
0484 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16;
0485 break;
0486 case 2:
0487 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32;
0488 break;
0489 case 3:
0490 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64;
0491 break;
0492 default:
0493 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8;
0494 break;
0495 }
0496
0497 REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier);
0498
0499 return prev_timeout_val;
0500 }
0501
0502 static struct dce_aux_funcs aux_functions = {
0503 .configure_timeout = NULL,
0504 .destroy = NULL,
0505 };
0506
0507 struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
0508 struct dc_context *ctx,
0509 uint32_t inst,
0510 uint32_t timeout_period,
0511 const struct dce110_aux_registers *regs,
0512 const struct dce110_aux_registers_mask *mask,
0513 const struct dce110_aux_registers_shift *shift,
0514 bool is_ext_aux_timeout_configurable)
0515 {
0516 aux_engine110->base.ddc = NULL;
0517 aux_engine110->base.ctx = ctx;
0518 aux_engine110->base.delay = 0;
0519 aux_engine110->base.max_defer_write_retry = 0;
0520 aux_engine110->base.inst = inst;
0521 aux_engine110->polling_timeout_period = timeout_period;
0522 aux_engine110->regs = regs;
0523
0524 aux_engine110->mask = mask;
0525 aux_engine110->shift = shift;
0526 aux_engine110->base.funcs = &aux_functions;
0527 if (is_ext_aux_timeout_configurable)
0528 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout;
0529
0530 return &aux_engine110->base;
0531 }
0532
0533 static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
0534 {
0535 if (payload->i2c_over_aux) {
0536 if (payload->write_status_update) {
0537 if (payload->mot)
0538 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT;
0539 else
0540 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
0541 }
0542 if (payload->write) {
0543 if (payload->mot)
0544 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
0545 else
0546 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
0547 }
0548 if (payload->mot)
0549 return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
0550
0551 return I2CAUX_TRANSACTION_ACTION_I2C_READ;
0552 }
0553 if (payload->write)
0554 return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
0555
0556 return I2CAUX_TRANSACTION_ACTION_DP_READ;
0557 }
0558
0559 int dce_aux_transfer_raw(struct ddc_service *ddc,
0560 struct aux_payload *payload,
0561 enum aux_return_code_type *operation_result)
0562 {
0563 struct ddc *ddc_pin = ddc->ddc_pin;
0564 struct dce_aux *aux_engine;
0565 struct aux_request_transaction_data aux_req;
0566 uint8_t returned_bytes = 0;
0567 int res = -1;
0568 uint32_t status;
0569
0570 memset(&aux_req, 0, sizeof(aux_req));
0571
0572 if (ddc_pin == NULL) {
0573 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
0574 return -1;
0575 }
0576
0577 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
0578 if (!acquire(aux_engine, ddc_pin)) {
0579 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
0580 return -1;
0581 }
0582
0583 if (payload->i2c_over_aux)
0584 aux_req.type = AUX_TRANSACTION_TYPE_I2C;
0585 else
0586 aux_req.type = AUX_TRANSACTION_TYPE_DP;
0587
0588 aux_req.action = i2caux_action_from_payload(payload);
0589
0590 aux_req.address = payload->address;
0591 aux_req.delay = 0;
0592 aux_req.length = payload->length;
0593 aux_req.data = payload->data;
0594
0595 submit_channel_request(aux_engine, &aux_req);
0596 *operation_result = get_channel_status(aux_engine, &returned_bytes);
0597
0598 if (*operation_result == AUX_RET_SUCCESS) {
0599 int __maybe_unused bytes_replied = 0;
0600
0601 bytes_replied = read_channel_reply(aux_engine, payload->length,
0602 payload->data, payload->reply,
0603 &status);
0604 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en,
0605 EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply,
0606 bytes_replied, payload->data);
0607 res = returned_bytes;
0608 } else {
0609 res = -1;
0610 }
0611
0612 release_engine(aux_engine);
0613 return res;
0614 }
0615
0616 int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
0617 struct aux_payload *payload,
0618 enum aux_return_code_type *operation_result)
0619 {
0620 struct ddc *ddc_pin = ddc->ddc_pin;
0621
0622 if (ddc_pin != NULL) {
0623 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
0624
0625 if (!acquire(aux_engine, ddc_pin)) {
0626 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
0627 return -1;
0628 }
0629 release_engine(aux_engine);
0630 }
0631
0632 return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result);
0633 }
0634
0635 #define AUX_MAX_RETRIES 7
0636 #define AUX_MIN_DEFER_RETRIES 7
0637 #define AUX_MAX_DEFER_TIMEOUT_MS 50
0638 #define AUX_MAX_I2C_DEFER_RETRIES 7
0639 #define AUX_MAX_INVALID_REPLY_RETRIES 2
0640 #define AUX_MAX_TIMEOUT_RETRIES 3
0641 #define AUX_DEFER_DELAY_FOR_DPIA 4
0642
0643 static void dce_aux_log_payload(const char *payload_name,
0644 unsigned char *payload, uint32_t length, uint32_t max_length_to_log)
0645 {
0646 if (!IS_DC_I2CAUX_LOGGING_ENABLED())
0647 return;
0648
0649 if (payload && length) {
0650 char hex_str[128] = {0};
0651 char *hex_str_ptr = &hex_str[0];
0652 uint32_t hex_str_remaining = sizeof(hex_str);
0653 unsigned char *payload_ptr = payload;
0654 unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length);
0655 unsigned int count;
0656 char *padding = "";
0657
0658 while (payload_ptr < payload_max_to_log_ptr) {
0659 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr);
0660 padding = " ";
0661 hex_str_remaining -= count;
0662 hex_str_ptr += count;
0663 payload_ptr++;
0664 }
0665
0666 count = snprintf_count(hex_str_ptr, hex_str_remaining, " ");
0667 hex_str_remaining -= count;
0668 hex_str_ptr += count;
0669
0670 payload_ptr = payload;
0671 while (payload_ptr < payload_max_to_log_ptr) {
0672 count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c",
0673 *payload_ptr >= ' ' ? *payload_ptr : '.');
0674 hex_str_remaining -= count;
0675 hex_str_ptr += count;
0676 payload_ptr++;
0677 }
0678
0679 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
0680 LOG_FLAG_I2cAux_DceAux,
0681 "dce_aux_log_payload: %s: length=%u: data: %s%s",
0682 payload_name,
0683 length,
0684 hex_str,
0685 (length > max_length_to_log ? " (...)" : " "));
0686 } else {
0687 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
0688 LOG_FLAG_I2cAux_DceAux,
0689 "dce_aux_log_payload: %s: length=%u: data: <empty payload>",
0690 payload_name,
0691 length);
0692 }
0693 }
0694
0695 bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
0696 struct aux_payload *payload)
0697 {
0698 int i, ret = 0;
0699 uint8_t reply;
0700 bool payload_reply = true;
0701 enum aux_return_code_type operation_result;
0702 bool retry_on_defer = false;
0703 struct ddc *ddc_pin = ddc->ddc_pin;
0704 struct dce_aux *aux_engine = NULL;
0705 struct aux_engine_dce110 *aux110 = NULL;
0706 uint32_t defer_time_in_ms = 0;
0707
0708 int aux_ack_retries = 0,
0709 aux_defer_retries = 0,
0710 aux_i2c_defer_retries = 0,
0711 aux_timeout_retries = 0,
0712 aux_invalid_reply_retries = 0,
0713 aux_ack_m_retries = 0;
0714
0715 if (ddc_pin) {
0716 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
0717 aux110 = FROM_AUX_ENGINE(aux_engine);
0718 }
0719
0720 if (!payload->reply) {
0721 payload_reply = false;
0722 payload->reply = &reply;
0723 }
0724
0725 for (i = 0; i < AUX_MAX_RETRIES; i++) {
0726 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0727 LOG_FLAG_I2cAux_DceAux,
0728 "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: address=0x%04x length=%u write=%d mot=%d",
0729 ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
0730 i + 1,
0731 (int)AUX_MAX_RETRIES,
0732 payload->address,
0733 payload->length,
0734 (unsigned int) payload->write,
0735 (unsigned int) payload->mot);
0736 if (payload->write)
0737 dce_aux_log_payload(" write", payload->data, payload->length, 16);
0738 ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
0739 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0740 LOG_FLAG_I2cAux_DceAux,
0741 "dce_aux_transfer_with_retries: link_index=%u: END: retry %d of %d: address=0x%04x length=%u write=%d mot=%d: ret=%d operation_result=%d payload->reply=%u",
0742 ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
0743 i + 1,
0744 (int)AUX_MAX_RETRIES,
0745 payload->address,
0746 payload->length,
0747 (unsigned int) payload->write,
0748 (unsigned int) payload->mot,
0749 ret,
0750 (int)operation_result,
0751 (unsigned int) *payload->reply);
0752 if (!payload->write)
0753 dce_aux_log_payload(" read", payload->data, ret > 0 ? ret : 0, 16);
0754
0755 switch (operation_result) {
0756 case AUX_RET_SUCCESS:
0757 aux_timeout_retries = 0;
0758 aux_invalid_reply_retries = 0;
0759
0760 switch (*payload->reply) {
0761 case AUX_TRANSACTION_REPLY_AUX_ACK:
0762 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0763 LOG_FLAG_I2cAux_DceAux,
0764 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK");
0765 if (!payload->write && payload->length != ret) {
0766 if (++aux_ack_retries >= AUX_MAX_RETRIES) {
0767 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0768 LOG_FLAG_Error_I2cAux,
0769 "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d",
0770 aux_defer_retries,
0771 AUX_MAX_RETRIES);
0772 goto fail;
0773 } else
0774 udelay(300);
0775 } else if (payload->write && ret > 0) {
0776
0777 if (++aux_ack_m_retries >= AUX_MAX_RETRIES) {
0778 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0779 LOG_FLAG_Error_I2cAux,
0780 "dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d",
0781 aux_ack_m_retries,
0782 AUX_MAX_RETRIES);
0783 goto fail;
0784 }
0785
0786
0787
0788
0789 payload->write = false;
0790 payload->write_status_update = true;
0791 payload->length = 0;
0792 udelay(300);
0793
0794 } else
0795 return true;
0796 break;
0797
0798 case AUX_TRANSACTION_REPLY_AUX_DEFER:
0799 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0800 LOG_FLAG_I2cAux_DceAux,
0801 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER");
0802
0803
0804 if (aux110)
0805 defer_time_in_ms += aux110->polling_timeout_period / 1000;
0806 else
0807 defer_time_in_ms += AUX_DEFER_DELAY_FOR_DPIA;
0808 ++aux_defer_retries;
0809 fallthrough;
0810 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
0811 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)
0812 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0813 LOG_FLAG_I2cAux_DceAux,
0814 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER");
0815
0816 retry_on_defer = true;
0817 fallthrough;
0818 case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
0819 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK)
0820 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0821 LOG_FLAG_I2cAux_DceAux,
0822 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK");
0823
0824 if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES
0825 && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) {
0826 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0827 LOG_FLAG_Error_I2cAux,
0828 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d && defer_time_in_ms=%d >= AUX_MAX_DEFER_TIMEOUT_MS=%d",
0829 aux_defer_retries,
0830 AUX_MIN_DEFER_RETRIES,
0831 defer_time_in_ms,
0832 AUX_MAX_DEFER_TIMEOUT_MS);
0833 goto fail;
0834 } else {
0835 if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
0836 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
0837 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0838 LOG_FLAG_I2cAux_DceAux,
0839 "dce_aux_transfer_with_retries: payload->defer_delay=%u",
0840 payload->defer_delay);
0841 if (payload->defer_delay > 1) {
0842 msleep(payload->defer_delay);
0843 defer_time_in_ms += payload->defer_delay;
0844 } else if (payload->defer_delay <= 1) {
0845 udelay(payload->defer_delay * 1000);
0846 defer_time_in_ms += payload->defer_delay;
0847 }
0848 }
0849 }
0850 break;
0851
0852 case AUX_TRANSACTION_REPLY_I2C_DEFER:
0853 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0854 LOG_FLAG_I2cAux_DceAux,
0855 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER");
0856
0857 aux_defer_retries = 0;
0858 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) {
0859 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0860 LOG_FLAG_Error_I2cAux,
0861 "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d",
0862 aux_i2c_defer_retries,
0863 AUX_MAX_I2C_DEFER_RETRIES);
0864 goto fail;
0865 }
0866 break;
0867
0868 case AUX_TRANSACTION_REPLY_AUX_NACK:
0869 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0870 LOG_FLAG_I2cAux_DceAux,
0871 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK");
0872 goto fail;
0873
0874 case AUX_TRANSACTION_REPLY_HPD_DISCON:
0875 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0876 LOG_FLAG_I2cAux_DceAux,
0877 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON");
0878 goto fail;
0879
0880 default:
0881 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0882 LOG_FLAG_Error_I2cAux,
0883 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case. Reply: %d", *payload->reply);
0884 goto fail;
0885 }
0886 break;
0887
0888 case AUX_RET_ERROR_INVALID_REPLY:
0889 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0890 LOG_FLAG_I2cAux_DceAux,
0891 "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY");
0892 if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) {
0893 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0894 LOG_FLAG_Error_I2cAux,
0895 "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d",
0896 aux_invalid_reply_retries,
0897 AUX_MAX_INVALID_REPLY_RETRIES);
0898 goto fail;
0899 } else
0900 udelay(400);
0901 break;
0902
0903 case AUX_RET_ERROR_TIMEOUT:
0904 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0905 LOG_FLAG_I2cAux_DceAux,
0906 "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT");
0907
0908
0909 if (retry_on_defer) {
0910 if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) {
0911 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0912 LOG_FLAG_Error_I2cAux,
0913 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d",
0914 aux_defer_retries,
0915 AUX_MIN_DEFER_RETRIES);
0916 goto fail;
0917 } else if (payload->defer_delay > 0) {
0918 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0919 LOG_FLAG_I2cAux_DceAux,
0920 "dce_aux_transfer_with_retries: payload->defer_delay=%u",
0921 payload->defer_delay);
0922 msleep(payload->defer_delay);
0923 }
0924 } else {
0925 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) {
0926 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0927 LOG_FLAG_Error_I2cAux,
0928 "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d",
0929 aux_timeout_retries,
0930 AUX_MAX_TIMEOUT_RETRIES);
0931 goto fail;
0932 } else {
0933
0934
0935
0936
0937
0938
0939 }
0940 }
0941 break;
0942
0943 case AUX_RET_ERROR_HPD_DISCON:
0944 case AUX_RET_ERROR_ENGINE_ACQUIRE:
0945 case AUX_RET_ERROR_UNKNOWN:
0946 default:
0947 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
0948 LOG_FLAG_I2cAux_DceAux,
0949 "dce_aux_transfer_with_retries: Failure: operation_result=%d",
0950 (int)operation_result);
0951 goto fail;
0952 }
0953 }
0954
0955 fail:
0956 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0957 LOG_FLAG_Error_I2cAux,
0958 "dce_aux_transfer_with_retries: FAILURE");
0959 if (!payload_reply)
0960 payload->reply = NULL;
0961
0962 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
0963 WPP_BIT_FLAG_DC_ERROR,
0964 "AUX transaction failed. Result: %d",
0965 operation_result);
0966
0967 return false;
0968 }