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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2018 Advanced Micro Devices, Inc.
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice shall be included in
      12             :  * all copies or substantial portions of the Software.
      13             :  *
      14             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      17             :  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
      18             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      19             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      20             :  * OTHER DEALINGS IN THE SOFTWARE.
      21             :  *
      22             :  * Authors: AMD
      23             :  *
      24             :  */
      25             : 
      26             : #include <linux/delay.h>
      27             : 
      28             : #include "resource.h"
      29             : #include "dce_i2c.h"
      30             : #include "dce_i2c_hw.h"
      31             : #include "reg_helper.h"
      32             : #include "include/gpio_service_interface.h"
      33             : 
      34             : #define CTX \
      35             :         dce_i2c_hw->ctx
      36             : #define REG(reg)\
      37             :         dce_i2c_hw->regs->reg
      38             : 
      39             : #undef FN
      40             : #define FN(reg_name, field_name) \
      41             :         dce_i2c_hw->shifts->field_name, dce_i2c_hw->masks->field_name
      42             : 
      43           0 : static void execute_transaction(
      44             :         struct dce_i2c_hw *dce_i2c_hw)
      45             : {
      46           0 :         REG_UPDATE_N(SETUP, 5,
      47             :                      FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
      48             :                      FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
      49             :                      FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
      50             :                      FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
      51             :                      FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
      52             : 
      53             : 
      54           0 :         REG_UPDATE_5(DC_I2C_CONTROL,
      55             :                      DC_I2C_SOFT_RESET, 0,
      56             :                      DC_I2C_SW_STATUS_RESET, 0,
      57             :                      DC_I2C_SEND_RESET, 0,
      58             :                      DC_I2C_GO, 0,
      59             :                      DC_I2C_TRANSACTION_COUNT, dce_i2c_hw->transaction_count - 1);
      60             : 
      61             :         /* start I2C transfer */
      62           0 :         REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
      63             : 
      64             :         /* all transactions were executed and HW buffer became empty
      65             :          * (even though it actually happens when status becomes DONE)
      66             :          */
      67           0 :         dce_i2c_hw->transaction_count = 0;
      68           0 :         dce_i2c_hw->buffer_used_bytes = 0;
      69           0 : }
      70             : 
      71           0 : static enum i2c_channel_operation_result get_channel_status(
      72             :         struct dce_i2c_hw *dce_i2c_hw,
      73             :         uint8_t *returned_bytes)
      74             : {
      75           0 :         uint32_t i2c_sw_status = 0;
      76           0 :         uint32_t value =
      77           0 :                 REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
      78           0 :         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
      79             :                 return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
      80           0 :         else if (value & dce_i2c_hw->masks->DC_I2C_SW_STOPPED_ON_NACK)
      81             :                 return I2C_CHANNEL_OPERATION_NO_RESPONSE;
      82           0 :         else if (value & dce_i2c_hw->masks->DC_I2C_SW_TIMEOUT)
      83             :                 return I2C_CHANNEL_OPERATION_TIMEOUT;
      84           0 :         else if (value & dce_i2c_hw->masks->DC_I2C_SW_ABORTED)
      85             :                 return I2C_CHANNEL_OPERATION_FAILED;
      86             :         else if (value & dce_i2c_hw->masks->DC_I2C_SW_DONE)
      87             :                 return I2C_CHANNEL_OPERATION_SUCCEEDED;
      88             : 
      89             :         /*
      90             :          * this is the case when HW used for communication, I2C_SW_STATUS
      91             :          * could be zero
      92             :          */
      93             :         return I2C_CHANNEL_OPERATION_SUCCEEDED;
      94             : }
      95             : 
      96             : static uint32_t get_hw_buffer_available_size(
      97             :         const struct dce_i2c_hw *dce_i2c_hw)
      98             : {
      99           0 :         return dce_i2c_hw->buffer_size -
     100             :                         dce_i2c_hw->buffer_used_bytes;
     101             : }
     102             : 
     103           0 : static void process_channel_reply(
     104             :         struct dce_i2c_hw *dce_i2c_hw,
     105             :         struct i2c_payload *reply)
     106             : {
     107           0 :         uint32_t length = reply->length;
     108           0 :         uint8_t *buffer = reply->data;
     109             : 
     110           0 :         REG_SET_3(DC_I2C_DATA, 0,
     111             :                  DC_I2C_INDEX, dce_i2c_hw->buffer_used_write,
     112             :                  DC_I2C_DATA_RW, 1,
     113             :                  DC_I2C_INDEX_WRITE, 1);
     114             : 
     115           0 :         while (length) {
     116             :                 /* after reading the status,
     117             :                  * if the I2C operation executed successfully
     118             :                  * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
     119             :                  * should read data bytes from I2C circular data buffer
     120             :                  */
     121             : 
     122             :                 uint32_t i2c_data;
     123             : 
     124           0 :                 REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
     125           0 :                 *buffer++ = i2c_data;
     126             : 
     127           0 :                 --length;
     128             :         }
     129           0 : }
     130             : 
     131           0 : static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
     132             : {
     133             :         unsigned int arbitrate;
     134             :         unsigned int i2c_hw_status;
     135             : 
     136           0 :         REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status);
     137           0 :         if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW)
     138             :                 return false;
     139             : 
     140           0 :         REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
     141           0 :         if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
     142             :                 return false;
     143             : 
     144           0 :         return true;
     145             : }
     146             : 
     147           0 : static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
     148             : {
     149           0 :         uint32_t i2c_sw_status = 0;
     150             : 
     151           0 :         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
     152           0 :         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
     153             :                 return false;
     154             : 
     155           0 :         if (is_engine_available(dce_i2c_hw))
     156             :                 return false;
     157             : 
     158           0 :         return true;
     159             : }
     160             : 
     161           0 : static bool process_transaction(
     162             :         struct dce_i2c_hw *dce_i2c_hw,
     163             :         struct i2c_request_transaction_data *request)
     164             : {
     165           0 :         uint32_t length = request->length;
     166           0 :         uint8_t *buffer = request->data;
     167             : 
     168           0 :         bool last_transaction = false;
     169           0 :         uint32_t value = 0;
     170             : 
     171           0 :         if (is_hw_busy(dce_i2c_hw)) {
     172           0 :                 request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
     173           0 :                 return false;
     174             :         }
     175             : 
     176           0 :         last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
     177           0 :                         (request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
     178           0 :                         (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
     179             : 
     180             : 
     181           0 :         switch (dce_i2c_hw->transaction_count) {
     182             :         case 0:
     183           0 :                 REG_UPDATE_5(DC_I2C_TRANSACTION0,
     184             :                                  DC_I2C_STOP_ON_NACK0, 1,
     185             :                                  DC_I2C_START0, 1,
     186             :                                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
     187             :                                  DC_I2C_COUNT0, length,
     188             :                                  DC_I2C_STOP0, last_transaction ? 1 : 0);
     189           0 :                 break;
     190             :         case 1:
     191           0 :                 REG_UPDATE_5(DC_I2C_TRANSACTION1,
     192             :                                  DC_I2C_STOP_ON_NACK0, 1,
     193             :                                  DC_I2C_START0, 1,
     194             :                                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
     195             :                                  DC_I2C_COUNT0, length,
     196             :                                  DC_I2C_STOP0, last_transaction ? 1 : 0);
     197           0 :                 break;
     198             :         case 2:
     199           0 :                 REG_UPDATE_5(DC_I2C_TRANSACTION2,
     200             :                                  DC_I2C_STOP_ON_NACK0, 1,
     201             :                                  DC_I2C_START0, 1,
     202             :                                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
     203             :                                  DC_I2C_COUNT0, length,
     204             :                                  DC_I2C_STOP0, last_transaction ? 1 : 0);
     205           0 :                 break;
     206             :         case 3:
     207           0 :                 REG_UPDATE_5(DC_I2C_TRANSACTION3,
     208             :                                  DC_I2C_STOP_ON_NACK0, 1,
     209             :                                  DC_I2C_START0, 1,
     210             :                                  DC_I2C_RW0, 0 != (request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ),
     211             :                                  DC_I2C_COUNT0, length,
     212             :                                  DC_I2C_STOP0, last_transaction ? 1 : 0);
     213           0 :                 break;
     214             :         default:
     215             :                 /* TODO Warning ? */
     216             :                 break;
     217             :         }
     218             : 
     219             :         /* Write the I2C address and I2C data
     220             :          * into the hardware circular buffer, one byte per entry.
     221             :          * As an example, the 7-bit I2C slave address for CRT monitor
     222             :          * for reading DDC/EDID information is 0b1010001.
     223             :          * For an I2C send operation, the LSB must be programmed to 0;
     224             :          * for I2C receive operation, the LSB must be programmed to 1.
     225             :          */
     226           0 :         if (dce_i2c_hw->transaction_count == 0) {
     227           0 :                 value = REG_SET_4(DC_I2C_DATA, 0,
     228             :                                   DC_I2C_DATA_RW, false,
     229             :                                   DC_I2C_DATA, request->address,
     230             :                                   DC_I2C_INDEX, 0,
     231             :                                   DC_I2C_INDEX_WRITE, 1);
     232           0 :                 dce_i2c_hw->buffer_used_write = 0;
     233             :         } else
     234           0 :                 value = REG_SET_2(DC_I2C_DATA, 0,
     235             :                           DC_I2C_DATA_RW, false,
     236             :                           DC_I2C_DATA, request->address);
     237             : 
     238           0 :         dce_i2c_hw->buffer_used_write++;
     239             : 
     240           0 :         if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
     241           0 :                 while (length) {
     242           0 :                         REG_SET_2(DC_I2C_DATA, value,
     243             :                                   DC_I2C_INDEX_WRITE, 0,
     244             :                                   DC_I2C_DATA, *buffer++);
     245           0 :                         dce_i2c_hw->buffer_used_write++;
     246           0 :                         --length;
     247             :                 }
     248             :         }
     249             : 
     250           0 :         ++dce_i2c_hw->transaction_count;
     251           0 :         dce_i2c_hw->buffer_used_bytes += length + 1;
     252             : 
     253           0 :         return last_transaction;
     254             : }
     255             : 
     256           0 : static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
     257             : {
     258           0 :         REG_UPDATE_2(DC_I2C_CONTROL,
     259             :                      DC_I2C_SW_STATUS_RESET, 1,
     260             :                      DC_I2C_SW_STATUS_RESET, 1);
     261           0 : }
     262             : 
     263           0 : static void set_speed(
     264             :         struct dce_i2c_hw *dce_i2c_hw,
     265             :         uint32_t speed)
     266             : {
     267           0 :         uint32_t xtal_ref_div = 0, ref_base_div = 0;
     268           0 :         uint32_t prescale = 0;
     269           0 :         uint32_t i2c_ref_clock = 0;
     270             : 
     271           0 :         if (speed == 0)
     272           0 :                 return;
     273             : 
     274           0 :         REG_GET_2(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, &ref_base_div,
     275             :                 XTAL_REF_DIV, &xtal_ref_div);
     276             : 
     277           0 :         if (xtal_ref_div == 0)
     278           0 :                 xtal_ref_div = 2;
     279             : 
     280           0 :         if (ref_base_div == 0)
     281           0 :                 i2c_ref_clock = (dce_i2c_hw->reference_frequency * 2);
     282             :         else
     283           0 :                 i2c_ref_clock = ref_base_div * 1000;
     284             : 
     285           0 :         prescale = (i2c_ref_clock / xtal_ref_div) / speed;
     286             : 
     287           0 :         if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
     288           0 :                 REG_UPDATE_N(SPEED, 3,
     289             :                              FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
     290             :                              FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
     291             :                              FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
     292             :         else
     293           0 :                 REG_UPDATE_N(SPEED, 2,
     294             :                              FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), prescale,
     295             :                              FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
     296             : }
     297             : 
     298           0 : static bool setup_engine(
     299             :         struct dce_i2c_hw *dce_i2c_hw)
     300             : {
     301           0 :         uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
     302           0 :         uint32_t  reset_length = 0;
     303             : 
     304           0 :         if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
     305           0 :              if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) {
     306           0 :                      REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0);
     307           0 :                      REG_WAIT(DIO_MEM_PWR_STATUS, I2C_MEM_PWR_STATE, 0, 0, 5);
     308             :                      }
     309             :              }
     310             : 
     311             :         /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/
     312           0 :         REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1);
     313             : 
     314             :         /* we have checked I2c not used by DMCU, set SW use I2C REQ to 1 to indicate SW using it*/
     315           0 :         REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_USE_I2C_REG_REQ, 1);
     316             : 
     317             :         /*set SW requested I2c speed to default, if API calls in it will be override later*/
     318           0 :         set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz);
     319             : 
     320           0 :         if (dce_i2c_hw->setup_limit != 0)
     321           0 :                 i2c_setup_limit = dce_i2c_hw->setup_limit;
     322             : 
     323             :         /* Program pin select */
     324           0 :         REG_UPDATE_6(DC_I2C_CONTROL,
     325             :                      DC_I2C_GO, 0,
     326             :                      DC_I2C_SOFT_RESET, 0,
     327             :                      DC_I2C_SEND_RESET, 0,
     328             :                      DC_I2C_SW_STATUS_RESET, 1,
     329             :                      DC_I2C_TRANSACTION_COUNT, 0,
     330             :                      DC_I2C_DDC_SELECT, dce_i2c_hw->engine_id);
     331             : 
     332             :         /* Program time limit */
     333           0 :         if (dce_i2c_hw->send_reset_length == 0) {
     334             :                 /*pre-dcn*/
     335           0 :                 REG_UPDATE_N(SETUP, 2,
     336             :                              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
     337             :                              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
     338             :         } else {
     339           0 :                 reset_length = dce_i2c_hw->send_reset_length;
     340           0 :                 REG_UPDATE_N(SETUP, 3,
     341             :                              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), i2c_setup_limit,
     342             :                              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_SEND_RESET_LENGTH), reset_length,
     343             :                              FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
     344             :         }
     345             :         /* Program HW priority
     346             :          * set to High - interrupt software I2C at any time
     347             :          * Enable restart of SW I2C that was interrupted by HW
     348             :          * disable queuing of software while I2C is in use by HW
     349             :          */
     350           0 :         REG_UPDATE(DC_I2C_ARBITRATION,
     351             :                         DC_I2C_NO_QUEUED_SW_GO, 0);
     352             : 
     353           0 :         return true;
     354             : }
     355             : 
     356           0 : static void release_engine(
     357             :         struct dce_i2c_hw *dce_i2c_hw)
     358             : {
     359             :         bool safe_to_reset;
     360             : 
     361             : 
     362             :         /* Reset HW engine */
     363             :         {
     364           0 :                 uint32_t i2c_sw_status = 0;
     365             : 
     366           0 :                 REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
     367             :                 /* if used by SW, safe to reset */
     368           0 :                 safe_to_reset = (i2c_sw_status == 1);
     369             :         }
     370             : 
     371           0 :         if (safe_to_reset)
     372           0 :                 REG_UPDATE_2(DC_I2C_CONTROL,
     373             :                              DC_I2C_SOFT_RESET, 1,
     374             :                              DC_I2C_SW_STATUS_RESET, 1);
     375             :         else
     376           0 :                 REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
     377             :         /* HW I2c engine - clock gating feature */
     378           0 :         if (!dce_i2c_hw->engine_keep_power_up_count)
     379           0 :                 REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
     380             : 
     381             :         /*for HW HDCP Ri polling failure w/a test*/
     382           0 :         set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz_hdcp);
     383             :         /* Release I2C after reset, so HW or DMCU could use it */
     384           0 :         REG_UPDATE_2(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1,
     385             :                 DC_I2C_SW_USE_I2C_REG_REQ, 0);
     386             : 
     387           0 :         if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
     388           0 :                 if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL)
     389           0 :                         REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
     390             :         }
     391           0 : }
     392             : 
     393           0 : struct dce_i2c_hw *acquire_i2c_hw_engine(
     394             :         struct resource_pool *pool,
     395             :         struct ddc *ddc)
     396             : {
     397           0 :         uint32_t counter = 0;
     398             :         enum gpio_result result;
     399           0 :         struct dce_i2c_hw *dce_i2c_hw = NULL;
     400             : 
     401           0 :         if (!ddc)
     402             :                 return NULL;
     403             : 
     404           0 :         if (ddc->hw_info.hw_supported) {
     405           0 :                 enum gpio_ddc_line line = dal_ddc_get_line(ddc);
     406             : 
     407           0 :                 if (line < pool->res_cap->num_ddc)
     408           0 :                         dce_i2c_hw = pool->hw_i2cs[line];
     409             :         }
     410             : 
     411           0 :         if (!dce_i2c_hw)
     412             :                 return NULL;
     413             : 
     414           0 :         if (pool->i2c_hw_buffer_in_use || !is_engine_available(dce_i2c_hw))
     415             :                 return NULL;
     416             : 
     417             :         do {
     418           0 :                 result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
     419             :                         GPIO_DDC_CONFIG_TYPE_MODE_I2C);
     420             : 
     421           0 :                 if (result == GPIO_RESULT_OK)
     422             :                         break;
     423             : 
     424             :                 /* i2c_engine is busy by VBios, lets wait and retry */
     425             : 
     426           0 :                 udelay(10);
     427             : 
     428           0 :                 ++counter;
     429           0 :         } while (counter < 2);
     430             : 
     431           0 :         if (result != GPIO_RESULT_OK)
     432             :                 return NULL;
     433             : 
     434           0 :         dce_i2c_hw->ddc = ddc;
     435             : 
     436           0 :         if (!setup_engine(dce_i2c_hw)) {
     437           0 :                 release_engine(dce_i2c_hw);
     438           0 :                 return NULL;
     439             :         }
     440             : 
     441           0 :         pool->i2c_hw_buffer_in_use = true;
     442           0 :         return dce_i2c_hw;
     443             : }
     444             : 
     445           0 : static enum i2c_channel_operation_result dce_i2c_hw_engine_wait_on_operation_result(
     446             :         struct dce_i2c_hw *dce_i2c_hw,
     447             :         uint32_t timeout,
     448             :         enum i2c_channel_operation_result expected_result)
     449             : {
     450             :         enum i2c_channel_operation_result result;
     451           0 :         uint32_t i = 0;
     452             : 
     453           0 :         if (!timeout)
     454             :                 return I2C_CHANNEL_OPERATION_SUCCEEDED;
     455             : 
     456             :         do {
     457             : 
     458           0 :                 result = get_channel_status(
     459             :                                 dce_i2c_hw, NULL);
     460             : 
     461           0 :                 if (result != expected_result)
     462             :                         break;
     463             : 
     464           0 :                 udelay(1);
     465             : 
     466           0 :                 ++i;
     467           0 :         } while (i < timeout);
     468             :         return result;
     469             : }
     470             : 
     471           0 : static void submit_channel_request_hw(
     472             :         struct dce_i2c_hw *dce_i2c_hw,
     473             :         struct i2c_request_transaction_data *request)
     474             : {
     475           0 :         request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
     476             : 
     477           0 :         if (!process_transaction(dce_i2c_hw, request))
     478             :                 return;
     479             : 
     480           0 :         if (is_hw_busy(dce_i2c_hw)) {
     481           0 :                 request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
     482           0 :                 return;
     483             :         }
     484           0 :         reset_hw_engine(dce_i2c_hw);
     485             : 
     486           0 :         execute_transaction(dce_i2c_hw);
     487             : 
     488             : 
     489             : }
     490             : 
     491             : static uint32_t get_transaction_timeout_hw(
     492             :         const struct dce_i2c_hw *dce_i2c_hw,
     493             :         uint32_t length,
     494             :         uint32_t speed)
     495             : {
     496             :         uint32_t period_timeout;
     497             :         uint32_t num_of_clock_stretches;
     498             : 
     499           0 :         if (!speed)
     500             :                 return 0;
     501             : 
     502           0 :         period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
     503             : 
     504           0 :         num_of_clock_stretches = 1 + (length << 3) + 1;
     505           0 :         num_of_clock_stretches +=
     506           0 :                 (dce_i2c_hw->buffer_used_bytes << 3) +
     507           0 :                 (dce_i2c_hw->transaction_count << 1);
     508             : 
     509           0 :         return period_timeout * num_of_clock_stretches;
     510             : }
     511             : 
     512           0 : static bool dce_i2c_hw_engine_submit_payload(
     513             :         struct dce_i2c_hw *dce_i2c_hw,
     514             :         struct i2c_payload *payload,
     515             :         bool middle_of_transaction,
     516             :         uint32_t speed)
     517             : {
     518             : 
     519             :         struct i2c_request_transaction_data request;
     520             : 
     521             :         uint32_t transaction_timeout;
     522             : 
     523             :         enum i2c_channel_operation_result operation_result;
     524             : 
     525           0 :         bool result = false;
     526             : 
     527             :         /* We need following:
     528             :          * transaction length will not exceed
     529             :          * the number of free bytes in HW buffer (minus one for address)
     530             :          */
     531             : 
     532           0 :         if (payload->length >=
     533           0 :                         get_hw_buffer_available_size(dce_i2c_hw)) {
     534             :                 return false;
     535             :         }
     536             : 
     537           0 :         if (!payload->write)
     538           0 :                 request.action = middle_of_transaction ?
     539           0 :                         DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
     540             :                         DCE_I2C_TRANSACTION_ACTION_I2C_READ;
     541             :         else
     542           0 :                 request.action = middle_of_transaction ?
     543           0 :                         DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
     544             :                         DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
     545             : 
     546             : 
     547           0 :         request.address = (uint8_t) ((payload->address << 1) | !payload->write);
     548           0 :         request.length = payload->length;
     549           0 :         request.data = payload->data;
     550             : 
     551             :         /* obtain timeout value before submitting request */
     552             : 
     553           0 :         transaction_timeout = get_transaction_timeout_hw(
     554             :                 dce_i2c_hw, payload->length + 1, speed);
     555             : 
     556           0 :         submit_channel_request_hw(
     557             :                 dce_i2c_hw, &request);
     558             : 
     559           0 :         if ((request.status == I2C_CHANNEL_OPERATION_FAILED) ||
     560             :                 (request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY))
     561             :                 return false;
     562             : 
     563             :         /* wait until transaction proceed */
     564             : 
     565           0 :         operation_result = dce_i2c_hw_engine_wait_on_operation_result(
     566             :                 dce_i2c_hw,
     567             :                 transaction_timeout,
     568             :                 I2C_CHANNEL_OPERATION_ENGINE_BUSY);
     569             : 
     570             :         /* update transaction status */
     571             : 
     572           0 :         if (operation_result == I2C_CHANNEL_OPERATION_SUCCEEDED)
     573           0 :                 result = true;
     574             : 
     575           0 :         if (result && (!payload->write))
     576           0 :                 process_channel_reply(dce_i2c_hw, payload);
     577             : 
     578             :         return result;
     579             : }
     580             : 
     581           0 : bool dce_i2c_submit_command_hw(
     582             :         struct resource_pool *pool,
     583             :         struct ddc *ddc,
     584             :         struct i2c_command *cmd,
     585             :         struct dce_i2c_hw *dce_i2c_hw)
     586             : {
     587           0 :         uint8_t index_of_payload = 0;
     588             :         bool result;
     589             : 
     590           0 :         set_speed(dce_i2c_hw, cmd->speed);
     591             : 
     592           0 :         result = true;
     593             : 
     594           0 :         while (index_of_payload < cmd->number_of_payloads) {
     595           0 :                 bool mot = (index_of_payload != cmd->number_of_payloads - 1);
     596             : 
     597           0 :                 struct i2c_payload *payload = cmd->payloads + index_of_payload;
     598             : 
     599           0 :                 if (!dce_i2c_hw_engine_submit_payload(
     600             :                                 dce_i2c_hw, payload, mot, cmd->speed)) {
     601             :                         result = false;
     602             :                         break;
     603             :                 }
     604             : 
     605           0 :                 ++index_of_payload;
     606             :         }
     607             : 
     608           0 :         pool->i2c_hw_buffer_in_use = false;
     609             : 
     610           0 :         release_engine(dce_i2c_hw);
     611           0 :         dal_ddc_close(dce_i2c_hw->ddc);
     612             : 
     613           0 :         dce_i2c_hw->ddc = NULL;
     614             : 
     615           0 :         return result;
     616             : }
     617             : 
     618           0 : void dce_i2c_hw_construct(
     619             :         struct dce_i2c_hw *dce_i2c_hw,
     620             :         struct dc_context *ctx,
     621             :         uint32_t engine_id,
     622             :         const struct dce_i2c_registers *regs,
     623             :         const struct dce_i2c_shift *shifts,
     624             :         const struct dce_i2c_mask *masks)
     625             : {
     626           0 :         dce_i2c_hw->ctx = ctx;
     627           0 :         dce_i2c_hw->engine_id = engine_id;
     628           0 :         dce_i2c_hw->reference_frequency = (ctx->dc_bios->fw_info.pll_info.crystal_frequency) >> 1;
     629           0 :         dce_i2c_hw->regs = regs;
     630           0 :         dce_i2c_hw->shifts = shifts;
     631           0 :         dce_i2c_hw->masks = masks;
     632           0 :         dce_i2c_hw->buffer_used_bytes = 0;
     633           0 :         dce_i2c_hw->transaction_count = 0;
     634           0 :         dce_i2c_hw->engine_keep_power_up_count = 1;
     635           0 :         dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED;
     636           0 :         dce_i2c_hw->send_reset_length = 0;
     637           0 :         dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
     638           0 :         dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE;
     639           0 : }
     640             : 
     641           0 : void dce100_i2c_hw_construct(
     642             :         struct dce_i2c_hw *dce_i2c_hw,
     643             :         struct dc_context *ctx,
     644             :         uint32_t engine_id,
     645             :         const struct dce_i2c_registers *regs,
     646             :         const struct dce_i2c_shift *shifts,
     647             :         const struct dce_i2c_mask *masks)
     648             : {
     649           0 :         dce_i2c_hw_construct(dce_i2c_hw,
     650             :                         ctx,
     651             :                         engine_id,
     652             :                         regs,
     653             :                         shifts,
     654             :                         masks);
     655           0 :         dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE100;
     656           0 : }
     657             : 
     658           0 : void dce112_i2c_hw_construct(
     659             :         struct dce_i2c_hw *dce_i2c_hw,
     660             :         struct dc_context *ctx,
     661             :         uint32_t engine_id,
     662             :         const struct dce_i2c_registers *regs,
     663             :         const struct dce_i2c_shift *shifts,
     664             :         const struct dce_i2c_mask *masks)
     665             : {
     666           0 :         dce100_i2c_hw_construct(dce_i2c_hw,
     667             :                         ctx,
     668             :                         engine_id,
     669             :                         regs,
     670             :                         shifts,
     671             :                         masks);
     672           0 :         dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED_100KHZ;
     673           0 : }
     674             : 
     675           0 : void dcn1_i2c_hw_construct(
     676             :         struct dce_i2c_hw *dce_i2c_hw,
     677             :         struct dc_context *ctx,
     678             :         uint32_t engine_id,
     679             :         const struct dce_i2c_registers *regs,
     680             :         const struct dce_i2c_shift *shifts,
     681             :         const struct dce_i2c_mask *masks)
     682             : {
     683           0 :         dce112_i2c_hw_construct(dce_i2c_hw,
     684             :                         ctx,
     685             :                         engine_id,
     686             :                         regs,
     687             :                         shifts,
     688             :                         masks);
     689           0 :         dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCN;
     690           0 : }
     691             : 
     692           0 : void dcn2_i2c_hw_construct(
     693             :         struct dce_i2c_hw *dce_i2c_hw,
     694             :         struct dc_context *ctx,
     695             :         uint32_t engine_id,
     696             :         const struct dce_i2c_registers *regs,
     697             :         const struct dce_i2c_shift *shifts,
     698             :         const struct dce_i2c_mask *masks)
     699             : {
     700           0 :         dcn1_i2c_hw_construct(dce_i2c_hw,
     701             :                         ctx,
     702             :                         engine_id,
     703             :                         regs,
     704             :                         shifts,
     705             :                         masks);
     706           0 :         dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_9;
     707           0 :         if (ctx->dc->debug.scl_reset_length10)
     708           0 :                 dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_10;
     709           0 : }

Generated by: LCOV version 1.14