LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/display/dc/dce - dce_aux.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 275 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 13 0.0 %

          Line data    Source code
       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             : #include "dm_event_log.h"
      31             : #include "dm_helpers.h"
      32             : #include "dmub/inc/dmub_cmd.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             : #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)
      43             : #define IS_DC_I2CAUX_LOGGING_ENABLED() (false)
      44             : #define LOG_FLAG_Error_I2cAux LOG_ERROR
      45             : #define LOG_FLAG_I2cAux_DceAux LOG_I2C_AUX
      46             : 
      47             : #include "reg_helper.h"
      48             : 
      49             : #undef FN
      50             : #define FN(reg_name, field_name) \
      51             :         aux110->shift->field_name, aux110->mask->field_name
      52             : 
      53             : #define FROM_AUX_ENGINE(ptr) \
      54             :         container_of((ptr), struct aux_engine_dce110, base)
      55             : 
      56             : #define FROM_ENGINE(ptr) \
      57             :         FROM_AUX_ENGINE(container_of((ptr), struct dce_aux, base))
      58             : 
      59             : #define FROM_AUX_ENGINE_ENGINE(ptr) \
      60             :         container_of((ptr), struct dce_aux, base)
      61             : enum {
      62             :         AUX_INVALID_REPLY_RETRY_COUNTER = 1,
      63             :         AUX_TIMED_OUT_RETRY_COUNTER = 2,
      64             :         AUX_DEFER_RETRY_COUNTER = 6
      65             : };
      66             : 
      67             : #define TIME_OUT_INCREMENT        1016
      68             : #define TIME_OUT_MULTIPLIER_8     8
      69             : #define TIME_OUT_MULTIPLIER_16    16
      70             : #define TIME_OUT_MULTIPLIER_32    32
      71             : #define TIME_OUT_MULTIPLIER_64    64
      72             : #define MAX_TIMEOUT_LENGTH        127
      73             : #define DEFAULT_AUX_ENGINE_MULT   0
      74             : #define DEFAULT_AUX_ENGINE_LENGTH 69
      75             : 
      76             : #define DC_TRACE_LEVEL_MESSAGE(...) do { } while (0)
      77             : 
      78           0 : static void release_engine(
      79             :         struct dce_aux *engine)
      80             : {
      81           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
      82             : 
      83           0 :         dal_ddc_close(engine->ddc);
      84             : 
      85           0 :         engine->ddc = NULL;
      86             : 
      87           0 :         REG_UPDATE_2(AUX_ARB_CONTROL, AUX_SW_DONE_USING_AUX_REG, 1,
      88             :                 AUX_SW_USE_AUX_REG_REQ, 0);
      89           0 : }
      90             : 
      91             : #define SW_CAN_ACCESS_AUX 1
      92             : #define DMCU_CAN_ACCESS_AUX 2
      93             : 
      94             : static bool is_engine_available(
      95             :         struct dce_aux *engine)
      96             : {
      97           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
      98             : 
      99           0 :         uint32_t value = REG_READ(AUX_ARB_CONTROL);
     100           0 :         uint32_t field = get_reg_field_value(
     101             :                         value,
     102             :                         AUX_ARB_CONTROL,
     103             :                         AUX_REG_RW_CNTL_STATUS);
     104             : 
     105             :         return (field != DMCU_CAN_ACCESS_AUX);
     106             : }
     107           0 : static bool acquire_engine(
     108             :         struct dce_aux *engine)
     109             : {
     110           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
     111             : 
     112           0 :         uint32_t value = REG_READ(AUX_ARB_CONTROL);
     113           0 :         uint32_t field = get_reg_field_value(
     114             :                         value,
     115             :                         AUX_ARB_CONTROL,
     116             :                         AUX_REG_RW_CNTL_STATUS);
     117           0 :         if (field == DMCU_CAN_ACCESS_AUX)
     118             :                 return false;
     119             :         /* enable AUX before request SW to access AUX */
     120           0 :         value = REG_READ(AUX_CONTROL);
     121           0 :         field = get_reg_field_value(value,
     122             :                                 AUX_CONTROL,
     123             :                                 AUX_EN);
     124             : 
     125           0 :         if (field == 0) {
     126           0 :                 set_reg_field_value(
     127             :                                 value,
     128             :                                 1,
     129             :                                 AUX_CONTROL,
     130             :                                 AUX_EN);
     131             : 
     132           0 :                 if (REG(AUX_RESET_MASK)) {
     133             :                         /*DP_AUX block as part of the enable sequence*/
     134           0 :                         set_reg_field_value(
     135             :                                 value,
     136             :                                 1,
     137             :                                 AUX_CONTROL,
     138             :                                 AUX_RESET);
     139             :                 }
     140             : 
     141           0 :                 REG_WRITE(AUX_CONTROL, value);
     142             : 
     143           0 :                 if (REG(AUX_RESET_MASK)) {
     144             :                         /*poll HW to make sure reset it done*/
     145             : 
     146           0 :                         REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 1,
     147             :                                         1, 11);
     148             : 
     149           0 :                         set_reg_field_value(
     150             :                                 value,
     151             :                                 0,
     152             :                                 AUX_CONTROL,
     153             :                                 AUX_RESET);
     154             : 
     155           0 :                         REG_WRITE(AUX_CONTROL, value);
     156             : 
     157           0 :                         REG_WAIT(AUX_CONTROL, AUX_RESET_DONE, 0,
     158             :                                         1, 11);
     159             :                 }
     160             :         } /*if (field)*/
     161             : 
     162             :         /* request SW to access AUX */
     163           0 :         REG_UPDATE(AUX_ARB_CONTROL, AUX_SW_USE_AUX_REG_REQ, 1);
     164             : 
     165           0 :         value = REG_READ(AUX_ARB_CONTROL);
     166           0 :         field = get_reg_field_value(
     167             :                         value,
     168             :                         AUX_ARB_CONTROL,
     169             :                         AUX_REG_RW_CNTL_STATUS);
     170             : 
     171           0 :         return (field == SW_CAN_ACCESS_AUX);
     172             : }
     173             : 
     174             : #define COMPOSE_AUX_SW_DATA_16_20(command, address) \
     175             :         ((command) | ((0xF0000 & (address)) >> 16))
     176             : 
     177             : #define COMPOSE_AUX_SW_DATA_8_15(address) \
     178             :         ((0xFF00 & (address)) >> 8)
     179             : 
     180             : #define COMPOSE_AUX_SW_DATA_0_7(address) \
     181             :         (0xFF & (address))
     182             : 
     183           0 : static void submit_channel_request(
     184             :         struct dce_aux *engine,
     185             :         struct aux_request_transaction_data *request)
     186             : {
     187           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
     188             :         uint32_t value;
     189             :         uint32_t length;
     190             : 
     191           0 :         bool is_write =
     192           0 :                 ((request->type == AUX_TRANSACTION_TYPE_DP) &&
     193           0 :                  (request->action == I2CAUX_TRANSACTION_ACTION_DP_WRITE)) ||
     194           0 :                 ((request->type == AUX_TRANSACTION_TYPE_I2C) &&
     195           0 :                 ((request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
     196             :                  (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT)));
     197           0 :         if (REG(AUXN_IMPCAL)) {
     198             :                 /* clear_aux_error */
     199           0 :                 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
     200             :                                 AUXN_CALOUT_ERROR_AK, 1,
     201             :                                 AUXN_CALOUT_ERROR_AK, 0);
     202             : 
     203           0 :                 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
     204             :                                 AUXP_CALOUT_ERROR_AK, 1,
     205             :                                 AUXP_CALOUT_ERROR_AK, 0);
     206             : 
     207             :                 /* force_default_calibrate */
     208           0 :                 REG_UPDATE_SEQ_2(AUXN_IMPCAL,
     209             :                                 AUXN_IMPCAL_ENABLE, 1,
     210             :                                 AUXN_IMPCAL_OVERRIDE_ENABLE, 0);
     211             : 
     212             :                 /* bug? why AUXN update EN and OVERRIDE_EN 1 by 1 while AUX P toggles OVERRIDE? */
     213             : 
     214           0 :                 REG_UPDATE_SEQ_2(AUXP_IMPCAL,
     215             :                                 AUXP_IMPCAL_OVERRIDE_ENABLE, 1,
     216             :                                 AUXP_IMPCAL_OVERRIDE_ENABLE, 0);
     217             :         }
     218             : 
     219           0 :         REG_UPDATE(AUX_INTERRUPT_CONTROL, AUX_SW_DONE_ACK, 1);
     220             : 
     221           0 :         REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 0,
     222             :                                 10, aux110->polling_timeout_period/10);
     223             : 
     224             :         /* set the delay and the number of bytes to write */
     225             : 
     226             :         /* The length include
     227             :          * the 4 bit header and the 20 bit address
     228             :          * (that is 3 byte).
     229             :          * If the requested length is non zero this means
     230             :          * an addition byte specifying the length is required.
     231             :          */
     232             : 
     233           0 :         length = request->length ? 4 : 3;
     234           0 :         if (is_write)
     235           0 :                 length += request->length;
     236             : 
     237           0 :         REG_UPDATE_2(AUX_SW_CONTROL,
     238             :                         AUX_SW_START_DELAY, request->delay,
     239             :                         AUX_SW_WR_BYTES, length);
     240             : 
     241             :         /* program action and address and payload data (if 'is_write') */
     242           0 :         value = REG_UPDATE_4(AUX_SW_DATA,
     243             :                         AUX_SW_INDEX, 0,
     244             :                         AUX_SW_DATA_RW, 0,
     245             :                         AUX_SW_AUTOINCREMENT_DISABLE, 1,
     246             :                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_16_20(request->action, request->address));
     247             : 
     248           0 :         value = REG_SET_2(AUX_SW_DATA, value,
     249             :                         AUX_SW_AUTOINCREMENT_DISABLE, 0,
     250             :                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_8_15(request->address));
     251             : 
     252           0 :         value = REG_SET(AUX_SW_DATA, value,
     253             :                         AUX_SW_DATA, COMPOSE_AUX_SW_DATA_0_7(request->address));
     254             : 
     255           0 :         if (request->length) {
     256           0 :                 value = REG_SET(AUX_SW_DATA, value,
     257             :                                 AUX_SW_DATA, request->length - 1);
     258             :         }
     259             : 
     260           0 :         if (is_write) {
     261             :                 /* Load the HW buffer with the Data to be sent.
     262             :                  * This is relevant for write operation.
     263             :                  * For read, the data recived data will be
     264             :                  * processed in process_channel_reply().
     265             :                  */
     266             :                 uint32_t i = 0;
     267             : 
     268           0 :                 while (i < request->length) {
     269           0 :                         value = REG_SET(AUX_SW_DATA, value,
     270             :                                         AUX_SW_DATA, request->data[i]);
     271             : 
     272           0 :                         ++i;
     273             :                 }
     274             :         }
     275             : 
     276           0 :         REG_UPDATE(AUX_SW_CONTROL, AUX_SW_GO, 1);
     277             :         EVENT_LOG_AUX_REQ(engine->ddc->pin_data->en, EVENT_LOG_AUX_ORIGIN_NATIVE,
     278             :                                         request->action, request->address, request->length, request->data);
     279           0 : }
     280             : 
     281           0 : static int read_channel_reply(struct dce_aux *engine, uint32_t size,
     282             :                               uint8_t *buffer, uint8_t *reply_result,
     283             :                               uint32_t *sw_status)
     284             : {
     285           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
     286             :         uint32_t bytes_replied;
     287             :         uint32_t reply_result_32;
     288             : 
     289           0 :         *sw_status = REG_GET(AUX_SW_STATUS, AUX_SW_REPLY_BYTE_COUNT,
     290             :                              &bytes_replied);
     291             : 
     292             :         /* In case HPD is LOW, exit AUX transaction */
     293           0 :         if ((*sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
     294             :                 return -1;
     295             : 
     296             :         /* Need at least the status byte */
     297           0 :         if (!bytes_replied)
     298             :                 return -1;
     299             : 
     300           0 :         REG_UPDATE_SEQ_3(AUX_SW_DATA,
     301             :                           AUX_SW_INDEX, 0,
     302             :                           AUX_SW_AUTOINCREMENT_DISABLE, 1,
     303             :                           AUX_SW_DATA_RW, 1);
     304             : 
     305           0 :         REG_GET(AUX_SW_DATA, AUX_SW_DATA, &reply_result_32);
     306           0 :         reply_result_32 = reply_result_32 >> 4;
     307           0 :         if (reply_result != NULL)
     308           0 :                 *reply_result = (uint8_t)reply_result_32;
     309             : 
     310           0 :         if (reply_result_32 == 0) { /* ACK */
     311           0 :                 uint32_t i = 0;
     312             : 
     313             :                 /* First byte was already used to get the command status */
     314           0 :                 --bytes_replied;
     315             : 
     316             :                 /* Do not overflow buffer */
     317           0 :                 if (bytes_replied > size)
     318             :                         return -1;
     319             : 
     320           0 :                 while (i < bytes_replied) {
     321             :                         uint32_t aux_sw_data_val;
     322             : 
     323           0 :                         REG_GET(AUX_SW_DATA, AUX_SW_DATA, &aux_sw_data_val);
     324           0 :                         buffer[i] = aux_sw_data_val;
     325           0 :                         ++i;
     326             :                 }
     327             : 
     328           0 :                 return i;
     329             :         }
     330             : 
     331             :         return 0;
     332             : }
     333             : 
     334           0 : static enum aux_return_code_type get_channel_status(
     335             :         struct dce_aux *engine,
     336             :         uint8_t *returned_bytes)
     337             : {
     338           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(engine);
     339             : 
     340             :         uint32_t value;
     341             : 
     342           0 :         if (returned_bytes == NULL) {
     343             :                 /*caller pass NULL pointer*/
     344           0 :                 ASSERT_CRITICAL(false);
     345           0 :                 return AUX_RET_ERROR_UNKNOWN;
     346             :         }
     347           0 :         *returned_bytes = 0;
     348             : 
     349             :         /* poll to make sure that SW_DONE is asserted */
     350           0 :         REG_WAIT(AUX_SW_STATUS, AUX_SW_DONE, 1,
     351             :                                 10, aux110->polling_timeout_period/10);
     352             : 
     353           0 :         value = REG_READ(AUX_SW_STATUS);
     354             :         /* in case HPD is LOW, exit AUX transaction */
     355           0 :         if ((value & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK))
     356             :                 return AUX_RET_ERROR_HPD_DISCON;
     357             : 
     358             :         /* Note that the following bits are set in 'status.bits'
     359             :          * during CTS 4.2.1.2 (FW 3.3.1):
     360             :          * AUX_SW_RX_MIN_COUNT_VIOL, AUX_SW_RX_INVALID_STOP,
     361             :          * AUX_SW_RX_RECV_NO_DET, AUX_SW_RX_RECV_INVALID_H.
     362             :          *
     363             :          * AUX_SW_RX_MIN_COUNT_VIOL is an internal,
     364             :          * HW debugging bit and should be ignored.
     365             :          */
     366           0 :         if (value & AUX_SW_STATUS__AUX_SW_DONE_MASK) {
     367           0 :                 if ((value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_STATE_MASK) ||
     368             :                         (value & AUX_SW_STATUS__AUX_SW_RX_TIMEOUT_MASK))
     369             :                         return AUX_RET_ERROR_TIMEOUT;
     370             : 
     371           0 :                 else if ((value & AUX_SW_STATUS__AUX_SW_RX_INVALID_STOP_MASK) ||
     372             :                         (value & AUX_SW_STATUS__AUX_SW_RX_RECV_NO_DET_MASK) ||
     373             :                         (value &
     374           0 :                                 AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_H_MASK) ||
     375             :                         (value & AUX_SW_STATUS__AUX_SW_RX_RECV_INVALID_L_MASK))
     376             :                         return AUX_RET_ERROR_INVALID_REPLY;
     377             : 
     378           0 :                 *returned_bytes = get_reg_field_value(value,
     379             :                                 AUX_SW_STATUS,
     380             :                                 AUX_SW_REPLY_BYTE_COUNT);
     381             : 
     382           0 :                 if (*returned_bytes == 0)
     383             :                         return
     384             :                         AUX_RET_ERROR_INVALID_REPLY;
     385             :                 else {
     386           0 :                         *returned_bytes -= 1;
     387           0 :                         return AUX_RET_SUCCESS;
     388             :                 }
     389             :         } else {
     390             :                 /*time_elapsed >= aux_engine->timeout_period
     391             :                  *  AUX_SW_STATUS__AUX_SW_HPD_DISCON = at this point
     392             :                  */
     393           0 :                 ASSERT_CRITICAL(false);
     394           0 :                 return AUX_RET_ERROR_TIMEOUT;
     395             :         }
     396             : }
     397             : 
     398           0 : static bool acquire(
     399             :         struct dce_aux *engine,
     400             :         struct ddc *ddc)
     401             : {
     402             :         enum gpio_result result;
     403             : 
     404           0 :         if ((engine == NULL) || !is_engine_available(engine))
     405             :                 return false;
     406             : 
     407           0 :         result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
     408             :                 GPIO_DDC_CONFIG_TYPE_MODE_AUX);
     409             : 
     410           0 :         if (result != GPIO_RESULT_OK)
     411             :                 return false;
     412             : 
     413           0 :         if (!acquire_engine(engine)) {
     414           0 :                 engine->ddc = ddc;
     415           0 :                 release_engine(engine);
     416           0 :                 return false;
     417             :         }
     418             : 
     419           0 :         engine->ddc = ddc;
     420             : 
     421           0 :         return true;
     422             : }
     423             : 
     424           0 : void dce110_engine_destroy(struct dce_aux **engine)
     425             : {
     426             : 
     427           0 :         struct aux_engine_dce110 *engine110 = FROM_AUX_ENGINE(*engine);
     428             : 
     429           0 :         kfree(engine110);
     430           0 :         *engine = NULL;
     431             : 
     432           0 : }
     433             : 
     434           0 : static uint32_t dce_aux_configure_timeout(struct ddc_service *ddc,
     435             :                 uint32_t timeout_in_us)
     436             : {
     437           0 :         uint32_t multiplier = 0;
     438           0 :         uint32_t length = 0;
     439           0 :         uint32_t prev_length = 0;
     440           0 :         uint32_t prev_mult = 0;
     441           0 :         uint32_t prev_timeout_val = 0;
     442           0 :         struct ddc *ddc_pin = ddc->ddc_pin;
     443           0 :         struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
     444           0 :         struct aux_engine_dce110 *aux110 = FROM_AUX_ENGINE(aux_engine);
     445             : 
     446             :         /* 1-Update polling timeout period */
     447           0 :         aux110->polling_timeout_period = timeout_in_us * SW_AUX_TIMEOUT_PERIOD_MULTIPLIER;
     448             : 
     449             :         /* 2-Update aux timeout period length and multiplier */
     450           0 :         if (timeout_in_us == 0) {
     451             :                 multiplier = DEFAULT_AUX_ENGINE_MULT;
     452             :                 length = DEFAULT_AUX_ENGINE_LENGTH;
     453           0 :         } else if (timeout_in_us <= TIME_OUT_INCREMENT) {
     454           0 :                 multiplier = 0;
     455           0 :                 length = timeout_in_us/TIME_OUT_MULTIPLIER_8;
     456           0 :                 if (timeout_in_us % TIME_OUT_MULTIPLIER_8 != 0)
     457           0 :                         length++;
     458           0 :         } else if (timeout_in_us <= 2 * TIME_OUT_INCREMENT) {
     459           0 :                 multiplier = 1;
     460           0 :                 length = timeout_in_us/TIME_OUT_MULTIPLIER_16;
     461           0 :                 if (timeout_in_us % TIME_OUT_MULTIPLIER_16 != 0)
     462           0 :                         length++;
     463           0 :         } else if (timeout_in_us <= 4 * TIME_OUT_INCREMENT) {
     464           0 :                 multiplier = 2;
     465           0 :                 length = timeout_in_us/TIME_OUT_MULTIPLIER_32;
     466           0 :                 if (timeout_in_us % TIME_OUT_MULTIPLIER_32 != 0)
     467           0 :                         length++;
     468             :         } else if (timeout_in_us > 4 * TIME_OUT_INCREMENT) {
     469           0 :                 multiplier = 3;
     470           0 :                 length = timeout_in_us/TIME_OUT_MULTIPLIER_64;
     471           0 :                 if (timeout_in_us % TIME_OUT_MULTIPLIER_64 != 0)
     472           0 :                         length++;
     473             :         }
     474             : 
     475           0 :         length = (length < MAX_TIMEOUT_LENGTH) ? length : MAX_TIMEOUT_LENGTH;
     476             : 
     477           0 :         REG_GET_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, &prev_length, AUX_RX_TIMEOUT_LEN_MUL, &prev_mult);
     478             : 
     479           0 :         switch (prev_mult) {
     480             :         case 0:
     481           0 :                 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_8;
     482           0 :                 break;
     483             :         case 1:
     484           0 :                 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_16;
     485           0 :                 break;
     486             :         case 2:
     487           0 :                 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_32;
     488           0 :                 break;
     489             :         case 3:
     490           0 :                 prev_timeout_val = prev_length * TIME_OUT_MULTIPLIER_64;
     491           0 :                 break;
     492             :         default:
     493             :                 prev_timeout_val = DEFAULT_AUX_ENGINE_LENGTH * TIME_OUT_MULTIPLIER_8;
     494             :                 break;
     495             :         }
     496             : 
     497           0 :         REG_UPDATE_SEQ_2(AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, length, AUX_RX_TIMEOUT_LEN_MUL, multiplier);
     498             : 
     499           0 :         return prev_timeout_val;
     500             : }
     501             : 
     502             : static struct dce_aux_funcs aux_functions = {
     503             :         .configure_timeout = NULL,
     504             :         .destroy = NULL,
     505             : };
     506             : 
     507           0 : struct dce_aux *dce110_aux_engine_construct(struct aux_engine_dce110 *aux_engine110,
     508             :                 struct dc_context *ctx,
     509             :                 uint32_t inst,
     510             :                 uint32_t timeout_period,
     511             :                 const struct dce110_aux_registers *regs,
     512             :                 const struct dce110_aux_registers_mask *mask,
     513             :                 const struct dce110_aux_registers_shift *shift,
     514             :                 bool is_ext_aux_timeout_configurable)
     515             : {
     516           0 :         aux_engine110->base.ddc = NULL;
     517           0 :         aux_engine110->base.ctx = ctx;
     518           0 :         aux_engine110->base.delay = 0;
     519           0 :         aux_engine110->base.max_defer_write_retry = 0;
     520           0 :         aux_engine110->base.inst = inst;
     521           0 :         aux_engine110->polling_timeout_period = timeout_period;
     522           0 :         aux_engine110->regs = regs;
     523             : 
     524           0 :         aux_engine110->mask = mask;
     525           0 :         aux_engine110->shift = shift;
     526           0 :         aux_engine110->base.funcs = &aux_functions;
     527           0 :         if (is_ext_aux_timeout_configurable)
     528           0 :                 aux_engine110->base.funcs->configure_timeout = &dce_aux_configure_timeout;
     529             : 
     530           0 :         return &aux_engine110->base;
     531             : }
     532             : 
     533           0 : static enum i2caux_transaction_action i2caux_action_from_payload(struct aux_payload *payload)
     534             : {
     535           0 :         if (payload->i2c_over_aux) {
     536           0 :                 if (payload->write_status_update) {
     537           0 :                         if (payload->mot)
     538             :                                 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST_MOT;
     539             :                         else
     540           0 :                                 return I2CAUX_TRANSACTION_ACTION_I2C_STATUS_REQUEST;
     541             :                 }
     542           0 :                 if (payload->write) {
     543           0 :                         if (payload->mot)
     544             :                                 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT;
     545             :                         else
     546           0 :                                 return I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
     547             :                 }
     548           0 :                 if (payload->mot)
     549             :                         return I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT;
     550             : 
     551           0 :                 return I2CAUX_TRANSACTION_ACTION_I2C_READ;
     552             :         }
     553           0 :         if (payload->write)
     554             :                 return I2CAUX_TRANSACTION_ACTION_DP_WRITE;
     555             : 
     556           0 :         return I2CAUX_TRANSACTION_ACTION_DP_READ;
     557             : }
     558             : 
     559           0 : int dce_aux_transfer_raw(struct ddc_service *ddc,
     560             :                 struct aux_payload *payload,
     561             :                 enum aux_return_code_type *operation_result)
     562             : {
     563           0 :         struct ddc *ddc_pin = ddc->ddc_pin;
     564             :         struct dce_aux *aux_engine;
     565             :         struct aux_request_transaction_data aux_req;
     566           0 :         uint8_t returned_bytes = 0;
     567           0 :         int res = -1;
     568             :         uint32_t status;
     569             : 
     570           0 :         memset(&aux_req, 0, sizeof(aux_req));
     571             : 
     572           0 :         if (ddc_pin == NULL) {
     573           0 :                 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
     574           0 :                 return -1;
     575             :         }
     576             : 
     577           0 :         aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
     578           0 :         if (!acquire(aux_engine, ddc_pin)) {
     579           0 :                 *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
     580           0 :                 return -1;
     581             :         }
     582             : 
     583           0 :         if (payload->i2c_over_aux)
     584           0 :                 aux_req.type = AUX_TRANSACTION_TYPE_I2C;
     585             :         else
     586           0 :                 aux_req.type = AUX_TRANSACTION_TYPE_DP;
     587             : 
     588           0 :         aux_req.action = i2caux_action_from_payload(payload);
     589             : 
     590           0 :         aux_req.address = payload->address;
     591           0 :         aux_req.delay = 0;
     592           0 :         aux_req.length = payload->length;
     593           0 :         aux_req.data = payload->data;
     594             : 
     595           0 :         submit_channel_request(aux_engine, &aux_req);
     596           0 :         *operation_result = get_channel_status(aux_engine, &returned_bytes);
     597             : 
     598           0 :         if (*operation_result == AUX_RET_SUCCESS) {
     599           0 :                 int __maybe_unused bytes_replied = 0;
     600             : 
     601           0 :                 bytes_replied = read_channel_reply(aux_engine, payload->length,
     602             :                                          payload->data, payload->reply,
     603             :                                          &status);
     604             :                 EVENT_LOG_AUX_REP(aux_engine->ddc->pin_data->en,
     605             :                                         EVENT_LOG_AUX_ORIGIN_NATIVE, *payload->reply,
     606             :                                         bytes_replied, payload->data);
     607           0 :                 res = returned_bytes;
     608             :         } else {
     609             :                 res = -1;
     610             :         }
     611             : 
     612           0 :         release_engine(aux_engine);
     613           0 :         return res;
     614             : }
     615             : 
     616           0 : int dce_aux_transfer_dmub_raw(struct ddc_service *ddc,
     617             :                 struct aux_payload *payload,
     618             :                 enum aux_return_code_type *operation_result)
     619             : {
     620           0 :         struct ddc *ddc_pin = ddc->ddc_pin;
     621             : 
     622           0 :         if (ddc_pin != NULL) {
     623           0 :                 struct dce_aux *aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
     624             :                 /* XXX: Workaround to configure ddc channels for aux transactions */
     625           0 :                 if (!acquire(aux_engine, ddc_pin)) {
     626           0 :                         *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
     627           0 :                         return -1;
     628             :                 }
     629           0 :                 release_engine(aux_engine);
     630             :         }
     631             : 
     632           0 :         return dm_helper_dmub_aux_transfer_sync(ddc->ctx, ddc->link, payload, operation_result);
     633             : }
     634             : 
     635             : #define AUX_MAX_RETRIES 7
     636             : #define AUX_MIN_DEFER_RETRIES 7
     637             : #define AUX_MAX_DEFER_TIMEOUT_MS 50
     638             : #define AUX_MAX_I2C_DEFER_RETRIES 7
     639             : #define AUX_MAX_INVALID_REPLY_RETRIES 2
     640             : #define AUX_MAX_TIMEOUT_RETRIES 3
     641             : #define AUX_DEFER_DELAY_FOR_DPIA 4 /*ms*/
     642             : 
     643             : static void dce_aux_log_payload(const char *payload_name,
     644             :         unsigned char *payload, uint32_t length, uint32_t max_length_to_log)
     645             : {
     646             :         if (!IS_DC_I2CAUX_LOGGING_ENABLED())
     647             :                 return;
     648             : 
     649             :         if (payload && length) {
     650             :                 char hex_str[128] = {0};
     651             :                 char *hex_str_ptr = &hex_str[0];
     652             :                 uint32_t hex_str_remaining = sizeof(hex_str);
     653             :                 unsigned char *payload_ptr = payload;
     654             :                 unsigned char *payload_max_to_log_ptr = payload_ptr + min(max_length_to_log, length);
     655             :                 unsigned int count;
     656             :                 char *padding = "";
     657             : 
     658             :                 while (payload_ptr < payload_max_to_log_ptr) {
     659             :                         count = snprintf_count(hex_str_ptr, hex_str_remaining, "%s%02X", padding, *payload_ptr);
     660             :                         padding = " ";
     661             :                         hex_str_remaining -= count;
     662             :                         hex_str_ptr += count;
     663             :                         payload_ptr++;
     664             :                 }
     665             : 
     666             :                 count = snprintf_count(hex_str_ptr, hex_str_remaining, "   ");
     667             :                 hex_str_remaining -= count;
     668             :                 hex_str_ptr += count;
     669             : 
     670             :                 payload_ptr = payload;
     671             :                 while (payload_ptr < payload_max_to_log_ptr) {
     672             :                         count = snprintf_count(hex_str_ptr, hex_str_remaining, "%c",
     673             :                                 *payload_ptr >= ' ' ? *payload_ptr : '.');
     674             :                         hex_str_remaining -= count;
     675             :                         hex_str_ptr += count;
     676             :                         payload_ptr++;
     677             :                 }
     678             : 
     679             :                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
     680             :                                         LOG_FLAG_I2cAux_DceAux,
     681             :                                         "dce_aux_log_payload: %s: length=%u: data: %s%s",
     682             :                                         payload_name,
     683             :                                         length,
     684             :                                         hex_str,
     685             :                                         (length > max_length_to_log ? " (...)" : " "));
     686             :         } else {
     687             :                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_VERBOSE,
     688             :                                         LOG_FLAG_I2cAux_DceAux,
     689             :                                         "dce_aux_log_payload: %s: length=%u: data: <empty payload>",
     690             :                                         payload_name,
     691             :                                         length);
     692             :         }
     693             : }
     694             : 
     695           0 : bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
     696             :                 struct aux_payload *payload)
     697             : {
     698           0 :         int i, ret = 0;
     699             :         uint8_t reply;
     700           0 :         bool payload_reply = true;
     701             :         enum aux_return_code_type operation_result;
     702           0 :         bool retry_on_defer = false;
     703           0 :         struct ddc *ddc_pin = ddc->ddc_pin;
     704           0 :         struct dce_aux *aux_engine = NULL;
     705           0 :         struct aux_engine_dce110 *aux110 = NULL;
     706           0 :         uint32_t defer_time_in_ms = 0;
     707             : 
     708           0 :         int aux_ack_retries = 0,
     709           0 :                 aux_defer_retries = 0,
     710           0 :                 aux_i2c_defer_retries = 0,
     711           0 :                 aux_timeout_retries = 0,
     712           0 :                 aux_invalid_reply_retries = 0,
     713           0 :                 aux_ack_m_retries = 0;
     714             : 
     715           0 :         if (ddc_pin) {
     716           0 :                 aux_engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
     717           0 :                 aux110 = FROM_AUX_ENGINE(aux_engine);
     718             :         }
     719             : 
     720           0 :         if (!payload->reply) {
     721           0 :                 payload_reply = false;
     722           0 :                 payload->reply = &reply;
     723             :         }
     724             : 
     725           0 :         for (i = 0; i < AUX_MAX_RETRIES; i++) {
     726             :                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     727             :                                         LOG_FLAG_I2cAux_DceAux,
     728             :                                         "dce_aux_transfer_with_retries: link_index=%u: START: retry %d of %d: address=0x%04x length=%u write=%d mot=%d",
     729             :                                         ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
     730             :                                         i + 1,
     731             :                                         (int)AUX_MAX_RETRIES,
     732             :                                         payload->address,
     733             :                                         payload->length,
     734             :                                         (unsigned int) payload->write,
     735             :                                         (unsigned int) payload->mot);
     736             :                 if (payload->write)
     737             :                         dce_aux_log_payload("  write", payload->data, payload->length, 16);
     738           0 :                 ret = dce_aux_transfer_raw(ddc, payload, &operation_result);
     739             :                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     740             :                                         LOG_FLAG_I2cAux_DceAux,
     741             :                                         "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",
     742             :                                         ddc && ddc->link ? ddc->link->link_index : UINT_MAX,
     743             :                                         i + 1,
     744             :                                         (int)AUX_MAX_RETRIES,
     745             :                                         payload->address,
     746             :                                         payload->length,
     747             :                                         (unsigned int) payload->write,
     748             :                                         (unsigned int) payload->mot,
     749             :                                         ret,
     750             :                                         (int)operation_result,
     751             :                                         (unsigned int) *payload->reply);
     752           0 :                 if (!payload->write)
     753             :                         dce_aux_log_payload("  read", payload->data, ret > 0 ? ret : 0, 16);
     754             : 
     755           0 :                 switch (operation_result) {
     756             :                 case AUX_RET_SUCCESS:
     757           0 :                         aux_timeout_retries = 0;
     758           0 :                         aux_invalid_reply_retries = 0;
     759             : 
     760           0 :                         switch (*payload->reply) {
     761             :                         case AUX_TRANSACTION_REPLY_AUX_ACK:
     762             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     763             :                                                         LOG_FLAG_I2cAux_DceAux,
     764             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_ACK");
     765           0 :                                 if (!payload->write && payload->length != ret) {
     766           0 :                                         if (++aux_ack_retries >= AUX_MAX_RETRIES) {
     767             :                                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     768             :                                                                         LOG_FLAG_Error_I2cAux,
     769             :                                                                         "dce_aux_transfer_with_retries: FAILURE: aux_ack_retries=%d >= AUX_MAX_RETRIES=%d",
     770             :                                                                         aux_defer_retries,
     771             :                                                                         AUX_MAX_RETRIES);
     772             :                                                 goto fail;
     773             :                                         } else 
     774             :                                                 udelay(300);
     775           0 :                                 } else if (payload->write && ret > 0) {
     776             :                                         /* sink requested more time to complete the write via AUX_ACKM */
     777           0 :                                         if (++aux_ack_m_retries >= AUX_MAX_RETRIES) {
     778             :                                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     779             :                                                                 LOG_FLAG_Error_I2cAux,
     780             :                                                                 "dce_aux_transfer_with_retries: FAILURE: aux_ack_m_retries=%d >= AUX_MAX_RETRIES=%d",
     781             :                                                                 aux_ack_m_retries,
     782             :                                                                 AUX_MAX_RETRIES);
     783             :                                                 goto fail;
     784             :                                         }
     785             : 
     786             :                                         /* retry reading the write status until complete
     787             :                                          * NOTE: payload is modified here
     788             :                                          */
     789           0 :                                         payload->write = false;
     790           0 :                                         payload->write_status_update = true;
     791           0 :                                         payload->length = 0;
     792             :                                         udelay(300);
     793             : 
     794             :                                 } else
     795             :                                         return true;
     796             :                         break;
     797             : 
     798             :                         case AUX_TRANSACTION_REPLY_AUX_DEFER:
     799             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     800             :                                                         LOG_FLAG_I2cAux_DceAux,
     801             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_DEFER");
     802             : 
     803             :                                 /* polling_timeout_period is in us */
     804           0 :                                 if (aux110)
     805           0 :                                         defer_time_in_ms += aux110->polling_timeout_period / 1000;
     806             :                                 else
     807           0 :                                         defer_time_in_ms += AUX_DEFER_DELAY_FOR_DPIA;
     808           0 :                                 ++aux_defer_retries;
     809             :                                 fallthrough;
     810             :                         case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
     811             :                                 if (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)
     812             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     813             :                                                                 LOG_FLAG_I2cAux_DceAux,
     814             :                                                                 "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER");
     815             : 
     816           0 :                                 retry_on_defer = true;
     817             : 
     818           0 :                                 if (aux_defer_retries >= AUX_MIN_DEFER_RETRIES
     819           0 :                                                 && defer_time_in_ms >= AUX_MAX_DEFER_TIMEOUT_MS) {
     820             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     821             :                                                                 LOG_FLAG_Error_I2cAux,
     822             :                                                                 "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",
     823             :                                                                 aux_defer_retries,
     824             :                                                                 AUX_MIN_DEFER_RETRIES,
     825             :                                                                 defer_time_in_ms,
     826             :                                                                 AUX_MAX_DEFER_TIMEOUT_MS);
     827             :                                         goto fail;
     828             :                                 } else {
     829           0 :                                         if ((*payload->reply == AUX_TRANSACTION_REPLY_AUX_DEFER) ||
     830             :                                                 (*payload->reply == AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER)) {
     831             :                                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     832             :                                                                         LOG_FLAG_I2cAux_DceAux,
     833             :                                                                         "dce_aux_transfer_with_retries: payload->defer_delay=%u",
     834             :                                                                         payload->defer_delay);
     835           0 :                                                 if (payload->defer_delay > 1) {
     836           0 :                                                         msleep(payload->defer_delay);
     837           0 :                                                         defer_time_in_ms += payload->defer_delay;
     838             :                                                 } else if (payload->defer_delay <= 1) {
     839           0 :                                                         udelay(payload->defer_delay * 1000);
     840           0 :                                                         defer_time_in_ms += payload->defer_delay;
     841             :                                                 }
     842             :                                         }
     843             :                                 }
     844             :                                 break;
     845             :                         case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
     846             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     847             :                                                         LOG_FLAG_I2cAux_DceAux,
     848             :                                                         "dce_aux_transfer_with_retries: FAILURE: AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK");
     849             :                                 goto fail;
     850             :                         case AUX_TRANSACTION_REPLY_I2C_DEFER:
     851             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     852             :                                                         LOG_FLAG_I2cAux_DceAux,
     853             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_I2C_DEFER");
     854             : 
     855           0 :                                 aux_defer_retries = 0;
     856           0 :                                 if (++aux_i2c_defer_retries >= AUX_MAX_I2C_DEFER_RETRIES) {
     857             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     858             :                                                                 LOG_FLAG_Error_I2cAux,
     859             :                                                                 "dce_aux_transfer_with_retries: FAILURE: aux_i2c_defer_retries=%d >= AUX_MAX_I2C_DEFER_RETRIES=%d",
     860             :                                                                 aux_i2c_defer_retries,
     861             :                                                                 AUX_MAX_I2C_DEFER_RETRIES);
     862             :                                         goto fail;
     863             :                                 }
     864             :                                 break;
     865             : 
     866             :                         case AUX_TRANSACTION_REPLY_AUX_NACK:
     867             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     868             :                                                         LOG_FLAG_I2cAux_DceAux,
     869             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_AUX_NACK");
     870             :                                 goto fail;
     871             : 
     872             :                         case AUX_TRANSACTION_REPLY_HPD_DISCON:
     873             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     874             :                                                         LOG_FLAG_I2cAux_DceAux,
     875             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: AUX_TRANSACTION_REPLY_HPD_DISCON");
     876             :                                 goto fail;
     877             : 
     878             :                         default:
     879             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     880             :                                                         LOG_FLAG_Error_I2cAux,
     881             :                                                         "dce_aux_transfer_with_retries: AUX_RET_SUCCESS: FAILURE: AUX_TRANSACTION_REPLY_* unknown, default case. Reply: %d", *payload->reply);
     882             :                                 goto fail;
     883             :                         }
     884             :                         break;
     885             : 
     886             :                 case AUX_RET_ERROR_INVALID_REPLY:
     887             :                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     888             :                                                 LOG_FLAG_I2cAux_DceAux,
     889             :                                                 "dce_aux_transfer_with_retries: AUX_RET_ERROR_INVALID_REPLY");
     890           0 :                         if (++aux_invalid_reply_retries >= AUX_MAX_INVALID_REPLY_RETRIES) {
     891             :                                 DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     892             :                                                         LOG_FLAG_Error_I2cAux,
     893             :                                                         "dce_aux_transfer_with_retries: FAILURE: aux_invalid_reply_retries=%d >= AUX_MAX_INVALID_REPLY_RETRIES=%d",
     894             :                                                         aux_invalid_reply_retries,
     895             :                                                         AUX_MAX_INVALID_REPLY_RETRIES);
     896             :                                 goto fail;
     897             :                         } else
     898             :                                 udelay(400);
     899             :                         break;
     900             : 
     901             :                 case AUX_RET_ERROR_TIMEOUT:
     902             :                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     903             :                                                 LOG_FLAG_I2cAux_DceAux,
     904             :                                                 "dce_aux_transfer_with_retries: AUX_RET_ERROR_TIMEOUT");
     905             :                         // Check whether a DEFER had occurred before the timeout.
     906             :                         // If so, treat timeout as a DEFER.
     907           0 :                         if (retry_on_defer) {
     908           0 :                                 if (++aux_defer_retries >= AUX_MIN_DEFER_RETRIES) {
     909             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     910             :                                                                 LOG_FLAG_Error_I2cAux,
     911             :                                                                 "dce_aux_transfer_with_retries: FAILURE: aux_defer_retries=%d >= AUX_MIN_DEFER_RETRIES=%d",
     912             :                                                                 aux_defer_retries,
     913             :                                                                 AUX_MIN_DEFER_RETRIES);
     914             :                                         goto fail;
     915           0 :                                 } else if (payload->defer_delay > 0) {
     916             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     917             :                                                                 LOG_FLAG_I2cAux_DceAux,
     918             :                                                                 "dce_aux_transfer_with_retries: payload->defer_delay=%u",
     919             :                                                                 payload->defer_delay);
     920           0 :                                         msleep(payload->defer_delay);
     921             :                                 }
     922             :                         } else {
     923           0 :                                 if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES) {
     924             :                                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     925             :                                                                 LOG_FLAG_Error_I2cAux,
     926             :                                                                 "dce_aux_transfer_with_retries: FAILURE: aux_timeout_retries=%d >= AUX_MAX_TIMEOUT_RETRIES=%d",
     927             :                                                                 aux_timeout_retries,
     928             :                                                                 AUX_MAX_TIMEOUT_RETRIES);
     929             :                                         goto fail;
     930             :                                 } else {
     931             :                                         /*
     932             :                                          * DP 1.4, 2.8.2:  AUX Transaction Response/Reply Timeouts
     933             :                                          * According to the DP spec there should be 3 retries total
     934             :                                          * with a 400us wait inbetween each. Hardware already waits
     935             :                                          * for 550us therefore no wait is required here.
     936             :                                          */
     937             :                                 }
     938             :                         }
     939             :                         break;
     940             : 
     941             :                 case AUX_RET_ERROR_HPD_DISCON:
     942             :                 case AUX_RET_ERROR_ENGINE_ACQUIRE:
     943             :                 case AUX_RET_ERROR_UNKNOWN:
     944             :                 default:
     945             :                         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION,
     946             :                                                 LOG_FLAG_I2cAux_DceAux,
     947             :                                                 "dce_aux_transfer_with_retries: Failure: operation_result=%d",
     948             :                                                 (int)operation_result);
     949             :                         goto fail;
     950             :                 }
     951             :         }
     952             : 
     953             : fail:
     954             :         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     955             :                                 LOG_FLAG_Error_I2cAux,
     956             :                                 "dce_aux_transfer_with_retries: FAILURE");
     957           0 :         if (!payload_reply)
     958           0 :                 payload->reply = NULL;
     959             : 
     960             :         DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_ERROR,
     961             :                                 WPP_BIT_FLAG_DC_ERROR,
     962             :                                 "AUX transaction failed. Result: %d",
     963             :                                 operation_result);
     964             : 
     965             :         return false;
     966             : }

Generated by: LCOV version 1.14