cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dce_i2c_hw.c (18785B)


      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
     43static void execute_transaction(
     44	struct dce_i2c_hw *dce_i2c_hw)
     45{
     46	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	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	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	dce_i2c_hw->transaction_count = 0;
     68	dce_i2c_hw->buffer_used_bytes = 0;
     69}
     70
     71static enum i2c_channel_operation_result get_channel_status(
     72	struct dce_i2c_hw *dce_i2c_hw,
     73	uint8_t *returned_bytes)
     74{
     75	uint32_t i2c_sw_status = 0;
     76	uint32_t value =
     77		REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
     78	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
     79		return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
     80	else if (value & dce_i2c_hw->masks->DC_I2C_SW_STOPPED_ON_NACK)
     81		return I2C_CHANNEL_OPERATION_NO_RESPONSE;
     82	else if (value & dce_i2c_hw->masks->DC_I2C_SW_TIMEOUT)
     83		return I2C_CHANNEL_OPERATION_TIMEOUT;
     84	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
     96static uint32_t get_hw_buffer_available_size(
     97	const struct dce_i2c_hw *dce_i2c_hw)
     98{
     99	return dce_i2c_hw->buffer_size -
    100			dce_i2c_hw->buffer_used_bytes;
    101}
    102
    103static void process_channel_reply(
    104	struct dce_i2c_hw *dce_i2c_hw,
    105	struct i2c_payload *reply)
    106{
    107	uint32_t length = reply->length;
    108	uint8_t *buffer = reply->data;
    109
    110	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	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		REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
    125		*buffer++ = i2c_data;
    126
    127		--length;
    128	}
    129}
    130
    131static bool is_engine_available(struct dce_i2c_hw *dce_i2c_hw)
    132{
    133	unsigned int arbitrate;
    134	unsigned int i2c_hw_status;
    135
    136	REG_GET(HW_STATUS, DC_I2C_DDC1_HW_STATUS, &i2c_hw_status);
    137	if (i2c_hw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW)
    138		return false;
    139
    140	REG_GET(DC_I2C_ARBITRATION, DC_I2C_REG_RW_CNTL_STATUS, &arbitrate);
    141	if (arbitrate == DC_I2C_REG_RW_CNTL_STATUS_DMCU_ONLY)
    142		return false;
    143
    144	return true;
    145}
    146
    147static bool is_hw_busy(struct dce_i2c_hw *dce_i2c_hw)
    148{
    149	uint32_t i2c_sw_status = 0;
    150
    151	REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
    152	if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
    153		return false;
    154
    155	if (is_engine_available(dce_i2c_hw))
    156		return false;
    157
    158	return true;
    159}
    160
    161static bool process_transaction(
    162	struct dce_i2c_hw *dce_i2c_hw,
    163	struct i2c_request_transaction_data *request)
    164{
    165	uint32_t length = request->length;
    166	uint8_t *buffer = request->data;
    167
    168	bool last_transaction = false;
    169	uint32_t value = 0;
    170
    171	if (is_hw_busy(dce_i2c_hw)) {
    172		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
    173		return false;
    174	}
    175
    176	last_transaction = ((dce_i2c_hw->transaction_count == 3) ||
    177			(request->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
    178			(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ));
    179
    180
    181	switch (dce_i2c_hw->transaction_count) {
    182	case 0:
    183		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		break;
    190	case 1:
    191		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		break;
    198	case 2:
    199		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		break;
    206	case 3:
    207		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		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	if (dce_i2c_hw->transaction_count == 0) {
    227		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		dce_i2c_hw->buffer_used_write = 0;
    233	} else
    234		value = REG_SET_2(DC_I2C_DATA, 0,
    235			  DC_I2C_DATA_RW, false,
    236			  DC_I2C_DATA, request->address);
    237
    238	dce_i2c_hw->buffer_used_write++;
    239
    240	if (!(request->action & DCE_I2C_TRANSACTION_ACTION_I2C_READ)) {
    241		while (length) {
    242			REG_SET_2(DC_I2C_DATA, value,
    243				  DC_I2C_INDEX_WRITE, 0,
    244				  DC_I2C_DATA, *buffer++);
    245			dce_i2c_hw->buffer_used_write++;
    246			--length;
    247		}
    248	}
    249
    250	++dce_i2c_hw->transaction_count;
    251	dce_i2c_hw->buffer_used_bytes += length + 1;
    252
    253	return last_transaction;
    254}
    255
    256static inline void reset_hw_engine(struct dce_i2c_hw *dce_i2c_hw)
    257{
    258	REG_UPDATE_2(DC_I2C_CONTROL,
    259		     DC_I2C_SW_STATUS_RESET, 1,
    260		     DC_I2C_SW_STATUS_RESET, 1);
    261}
    262
    263static void set_speed(
    264	struct dce_i2c_hw *dce_i2c_hw,
    265	uint32_t speed)
    266{
    267	uint32_t xtal_ref_div = 0, ref_base_div = 0;
    268	uint32_t prescale = 0;
    269	uint32_t i2c_ref_clock = 0;
    270
    271	if (speed == 0)
    272		return;
    273
    274	REG_GET_2(MICROSECOND_TIME_BASE_DIV, MICROSECOND_TIME_BASE_DIV, &ref_base_div,
    275		XTAL_REF_DIV, &xtal_ref_div);
    276
    277	if (xtal_ref_div == 0)
    278		xtal_ref_div = 2;
    279
    280	if (ref_base_div == 0)
    281		i2c_ref_clock = (dce_i2c_hw->reference_frequency * 2);
    282	else
    283		i2c_ref_clock = ref_base_div * 1000;
    284
    285	prescale = (i2c_ref_clock / xtal_ref_div) / speed;
    286
    287	if (dce_i2c_hw->masks->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
    288		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		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
    298static bool setup_engine(
    299	struct dce_i2c_hw *dce_i2c_hw)
    300{
    301	uint32_t i2c_setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
    302	uint32_t  reset_length = 0;
    303
    304        if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
    305	     if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL) {
    306		     REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 0);
    307		     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	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	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	set_speed(dce_i2c_hw, dce_i2c_hw->ctx->dc->caps.i2c_speed_in_khz);
    319
    320	if (dce_i2c_hw->setup_limit != 0)
    321		i2c_setup_limit = dce_i2c_hw->setup_limit;
    322
    323	/* Program pin select */
    324	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	if (dce_i2c_hw->send_reset_length == 0) {
    334		/*pre-dcn*/
    335		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		reset_length = dce_i2c_hw->send_reset_length;
    340		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	REG_UPDATE(DC_I2C_ARBITRATION,
    351			DC_I2C_NO_QUEUED_SW_GO, 0);
    352
    353	return true;
    354}
    355
    356static 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		uint32_t i2c_sw_status = 0;
    365
    366		REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
    367		/* if used by SW, safe to reset */
    368		safe_to_reset = (i2c_sw_status == 1);
    369	}
    370
    371	if (safe_to_reset)
    372		REG_UPDATE_2(DC_I2C_CONTROL,
    373			     DC_I2C_SOFT_RESET, 1,
    374			     DC_I2C_SW_STATUS_RESET, 1);
    375	else
    376		REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
    377	/* HW I2c engine - clock gating feature */
    378	if (!dce_i2c_hw->engine_keep_power_up_count)
    379		REG_UPDATE_N(SETUP, 1, FN(SETUP, DC_I2C_DDC1_ENABLE), 0);
    380
    381	/*for HW HDCP Ri polling failure w/a test*/
    382	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	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	if (dce_i2c_hw->ctx->dc->debug.enable_mem_low_power.bits.i2c) {
    388		if (dce_i2c_hw->regs->DIO_MEM_PWR_CTRL)
    389			REG_UPDATE(DIO_MEM_PWR_CTRL, I2C_LIGHT_SLEEP_FORCE, 1);
    390	}
    391}
    392
    393struct dce_i2c_hw *acquire_i2c_hw_engine(
    394	struct resource_pool *pool,
    395	struct ddc *ddc)
    396{
    397	uint32_t counter = 0;
    398	enum gpio_result result;
    399	struct dce_i2c_hw *dce_i2c_hw = NULL;
    400
    401	if (!ddc)
    402		return NULL;
    403
    404	if (ddc->hw_info.hw_supported) {
    405		enum gpio_ddc_line line = dal_ddc_get_line(ddc);
    406
    407		if (line < pool->res_cap->num_ddc)
    408			dce_i2c_hw = pool->hw_i2cs[line];
    409	}
    410
    411	if (!dce_i2c_hw)
    412		return NULL;
    413
    414	if (pool->i2c_hw_buffer_in_use || !is_engine_available(dce_i2c_hw))
    415		return NULL;
    416
    417	do {
    418		result = dal_ddc_open(ddc, GPIO_MODE_HARDWARE,
    419			GPIO_DDC_CONFIG_TYPE_MODE_I2C);
    420
    421		if (result == GPIO_RESULT_OK)
    422			break;
    423
    424		/* i2c_engine is busy by VBios, lets wait and retry */
    425
    426		udelay(10);
    427
    428		++counter;
    429	} while (counter < 2);
    430
    431	if (result != GPIO_RESULT_OK)
    432		return NULL;
    433
    434	dce_i2c_hw->ddc = ddc;
    435
    436	if (!setup_engine(dce_i2c_hw)) {
    437		release_engine(dce_i2c_hw);
    438		return NULL;
    439	}
    440
    441	pool->i2c_hw_buffer_in_use = true;
    442	return dce_i2c_hw;
    443}
    444
    445static 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	uint32_t i = 0;
    452
    453	if (!timeout)
    454		return I2C_CHANNEL_OPERATION_SUCCEEDED;
    455
    456	do {
    457
    458		result = get_channel_status(
    459				dce_i2c_hw, NULL);
    460
    461		if (result != expected_result)
    462			break;
    463
    464		udelay(1);
    465
    466		++i;
    467	} while (i < timeout);
    468	return result;
    469}
    470
    471static void submit_channel_request_hw(
    472	struct dce_i2c_hw *dce_i2c_hw,
    473	struct i2c_request_transaction_data *request)
    474{
    475	request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
    476
    477	if (!process_transaction(dce_i2c_hw, request))
    478		return;
    479
    480	if (is_hw_busy(dce_i2c_hw)) {
    481		request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
    482		return;
    483	}
    484	reset_hw_engine(dce_i2c_hw);
    485
    486	execute_transaction(dce_i2c_hw);
    487
    488
    489}
    490
    491static 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	if (!speed)
    500		return 0;
    501
    502	period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
    503
    504	num_of_clock_stretches = 1 + (length << 3) + 1;
    505	num_of_clock_stretches +=
    506		(dce_i2c_hw->buffer_used_bytes << 3) +
    507		(dce_i2c_hw->transaction_count << 1);
    508
    509	return period_timeout * num_of_clock_stretches;
    510}
    511
    512static 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	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	if (payload->length >=
    533			get_hw_buffer_available_size(dce_i2c_hw)) {
    534		return false;
    535	}
    536
    537	if (!payload->write)
    538		request.action = middle_of_transaction ?
    539			DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
    540			DCE_I2C_TRANSACTION_ACTION_I2C_READ;
    541	else
    542		request.action = middle_of_transaction ?
    543			DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
    544			DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
    545
    546
    547	request.address = (uint8_t) ((payload->address << 1) | !payload->write);
    548	request.length = payload->length;
    549	request.data = payload->data;
    550
    551	/* obtain timeout value before submitting request */
    552
    553	transaction_timeout = get_transaction_timeout_hw(
    554		dce_i2c_hw, payload->length + 1, speed);
    555
    556	submit_channel_request_hw(
    557		dce_i2c_hw, &request);
    558
    559	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	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	if (operation_result == I2C_CHANNEL_OPERATION_SUCCEEDED)
    573		result = true;
    574
    575	if (result && (!payload->write))
    576		process_channel_reply(dce_i2c_hw, payload);
    577
    578	return result;
    579}
    580
    581bool 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	uint8_t index_of_payload = 0;
    588	bool result;
    589
    590	set_speed(dce_i2c_hw, cmd->speed);
    591
    592	result = true;
    593
    594	while (index_of_payload < cmd->number_of_payloads) {
    595		bool mot = (index_of_payload != cmd->number_of_payloads - 1);
    596
    597		struct i2c_payload *payload = cmd->payloads + index_of_payload;
    598
    599		if (!dce_i2c_hw_engine_submit_payload(
    600				dce_i2c_hw, payload, mot, cmd->speed)) {
    601			result = false;
    602			break;
    603		}
    604
    605		++index_of_payload;
    606	}
    607
    608	pool->i2c_hw_buffer_in_use = false;
    609
    610	release_engine(dce_i2c_hw);
    611	dal_ddc_close(dce_i2c_hw->ddc);
    612
    613	dce_i2c_hw->ddc = NULL;
    614
    615	return result;
    616}
    617
    618void 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	dce_i2c_hw->ctx = ctx;
    627	dce_i2c_hw->engine_id = engine_id;
    628	dce_i2c_hw->reference_frequency = (ctx->dc_bios->fw_info.pll_info.crystal_frequency) >> 1;
    629	dce_i2c_hw->regs = regs;
    630	dce_i2c_hw->shifts = shifts;
    631	dce_i2c_hw->masks = masks;
    632	dce_i2c_hw->buffer_used_bytes = 0;
    633	dce_i2c_hw->transaction_count = 0;
    634	dce_i2c_hw->engine_keep_power_up_count = 1;
    635	dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED;
    636	dce_i2c_hw->send_reset_length = 0;
    637	dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCE;
    638	dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE;
    639}
    640
    641void 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	dce_i2c_hw_construct(dce_i2c_hw,
    650			ctx,
    651			engine_id,
    652			regs,
    653			shifts,
    654			masks);
    655	dce_i2c_hw->buffer_size = I2C_HW_BUFFER_SIZE_DCE100;
    656}
    657
    658void 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	dce100_i2c_hw_construct(dce_i2c_hw,
    667			ctx,
    668			engine_id,
    669			regs,
    670			shifts,
    671			masks);
    672	dce_i2c_hw->default_speed = DEFAULT_I2C_HW_SPEED_100KHZ;
    673}
    674
    675void 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	dce112_i2c_hw_construct(dce_i2c_hw,
    684			ctx,
    685			engine_id,
    686			regs,
    687			shifts,
    688			masks);
    689	dce_i2c_hw->setup_limit = I2C_SETUP_TIME_LIMIT_DCN;
    690}
    691
    692void 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	dcn1_i2c_hw_construct(dce_i2c_hw,
    701			ctx,
    702			engine_id,
    703			regs,
    704			shifts,
    705			masks);
    706	dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_9;
    707	if (ctx->dc->debug.scl_reset_length10)
    708		dce_i2c_hw->send_reset_length = I2C_SEND_RESET_LENGTH_10;
    709}