0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dce_i2c.h"
0027 #include "dce_i2c_sw.h"
0028 #include "include/gpio_service_interface.h"
0029 #define SCL false
0030 #define SDA true
0031
0032 void dce_i2c_sw_construct(
0033 struct dce_i2c_sw *dce_i2c_sw,
0034 struct dc_context *ctx)
0035 {
0036 dce_i2c_sw->ctx = ctx;
0037 }
0038
0039 static inline bool read_bit_from_ddc(
0040 struct ddc *ddc,
0041 bool data_nor_clock)
0042 {
0043 uint32_t value = 0;
0044
0045 if (data_nor_clock)
0046 dal_gpio_get_value(ddc->pin_data, &value);
0047 else
0048 dal_gpio_get_value(ddc->pin_clock, &value);
0049
0050 return (value != 0);
0051 }
0052
0053 static inline void write_bit_to_ddc(
0054 struct ddc *ddc,
0055 bool data_nor_clock,
0056 bool bit)
0057 {
0058 uint32_t value = bit ? 1 : 0;
0059
0060 if (data_nor_clock)
0061 dal_gpio_set_value(ddc->pin_data, value);
0062 else
0063 dal_gpio_set_value(ddc->pin_clock, value);
0064 }
0065
0066 static void release_engine_dce_sw(
0067 struct resource_pool *pool,
0068 struct dce_i2c_sw *dce_i2c_sw)
0069 {
0070 dal_ddc_close(dce_i2c_sw->ddc);
0071 dce_i2c_sw->ddc = NULL;
0072 }
0073
0074 static bool wait_for_scl_high_sw(
0075 struct dc_context *ctx,
0076 struct ddc *ddc,
0077 uint16_t clock_delay_div_4)
0078 {
0079 uint32_t scl_retry = 0;
0080 uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
0081
0082 udelay(clock_delay_div_4);
0083
0084 do {
0085 if (read_bit_from_ddc(ddc, SCL))
0086 return true;
0087
0088 udelay(clock_delay_div_4);
0089
0090 ++scl_retry;
0091 } while (scl_retry <= scl_retry_max);
0092
0093 return false;
0094 }
0095 static bool write_byte_sw(
0096 struct dc_context *ctx,
0097 struct ddc *ddc_handle,
0098 uint16_t clock_delay_div_4,
0099 uint8_t byte)
0100 {
0101 int32_t shift = 7;
0102 bool ack;
0103
0104
0105
0106 do {
0107 udelay(clock_delay_div_4);
0108
0109 write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
0110
0111 udelay(clock_delay_div_4);
0112
0113 write_bit_to_ddc(ddc_handle, SCL, true);
0114
0115 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0116 return false;
0117
0118 write_bit_to_ddc(ddc_handle, SCL, false);
0119
0120 --shift;
0121 } while (shift >= 0);
0122
0123
0124
0125
0126
0127
0128 udelay(clock_delay_div_4);
0129
0130 write_bit_to_ddc(ddc_handle, SDA, true);
0131
0132 udelay(clock_delay_div_4);
0133
0134 write_bit_to_ddc(ddc_handle, SCL, true);
0135
0136 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0137 return false;
0138
0139
0140
0141 ack = !read_bit_from_ddc(ddc_handle, SDA);
0142
0143 udelay(clock_delay_div_4 << 1);
0144
0145 write_bit_to_ddc(ddc_handle, SCL, false);
0146
0147 udelay(clock_delay_div_4 << 1);
0148
0149 return ack;
0150 }
0151
0152 static bool read_byte_sw(
0153 struct dc_context *ctx,
0154 struct ddc *ddc_handle,
0155 uint16_t clock_delay_div_4,
0156 uint8_t *byte,
0157 bool more)
0158 {
0159 int32_t shift = 7;
0160
0161 uint8_t data = 0;
0162
0163
0164
0165
0166
0167 do {
0168 write_bit_to_ddc(ddc_handle, SCL, true);
0169
0170 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0171 return false;
0172
0173 if (read_bit_from_ddc(ddc_handle, SDA))
0174 data |= (1 << shift);
0175
0176 write_bit_to_ddc(ddc_handle, SCL, false);
0177
0178 udelay(clock_delay_div_4 << 1);
0179
0180 --shift;
0181 } while (shift >= 0);
0182
0183
0184
0185 *byte = data;
0186
0187 udelay(clock_delay_div_4);
0188
0189
0190
0191
0192
0193 write_bit_to_ddc(ddc_handle, SDA, !more);
0194
0195 udelay(clock_delay_div_4);
0196
0197 write_bit_to_ddc(ddc_handle, SCL, true);
0198
0199 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0200 return false;
0201
0202 write_bit_to_ddc(ddc_handle, SCL, false);
0203
0204 udelay(clock_delay_div_4);
0205
0206 write_bit_to_ddc(ddc_handle, SDA, true);
0207
0208 udelay(clock_delay_div_4);
0209
0210 return true;
0211 }
0212 static bool stop_sync_sw(
0213 struct dc_context *ctx,
0214 struct ddc *ddc_handle,
0215 uint16_t clock_delay_div_4)
0216 {
0217 uint32_t retry = 0;
0218
0219
0220
0221
0222
0223 write_bit_to_ddc(ddc_handle, SCL, false);
0224
0225 udelay(clock_delay_div_4);
0226
0227 write_bit_to_ddc(ddc_handle, SDA, false);
0228
0229 udelay(clock_delay_div_4);
0230
0231 write_bit_to_ddc(ddc_handle, SCL, true);
0232
0233 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0234 return false;
0235
0236 write_bit_to_ddc(ddc_handle, SDA, true);
0237
0238 do {
0239 udelay(clock_delay_div_4);
0240
0241 if (read_bit_from_ddc(ddc_handle, SDA))
0242 return true;
0243
0244 ++retry;
0245 } while (retry <= 2);
0246
0247 return false;
0248 }
0249 static bool i2c_write_sw(
0250 struct dc_context *ctx,
0251 struct ddc *ddc_handle,
0252 uint16_t clock_delay_div_4,
0253 uint8_t address,
0254 uint32_t length,
0255 const uint8_t *data)
0256 {
0257 uint32_t i = 0;
0258
0259 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
0260 return false;
0261
0262 while (i < length) {
0263 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
0264 return false;
0265 ++i;
0266 }
0267
0268 return true;
0269 }
0270
0271 static bool i2c_read_sw(
0272 struct dc_context *ctx,
0273 struct ddc *ddc_handle,
0274 uint16_t clock_delay_div_4,
0275 uint8_t address,
0276 uint32_t length,
0277 uint8_t *data)
0278 {
0279 uint32_t i = 0;
0280
0281 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
0282 return false;
0283
0284 while (i < length) {
0285 if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
0286 i < length - 1))
0287 return false;
0288 ++i;
0289 }
0290
0291 return true;
0292 }
0293
0294
0295
0296 static bool start_sync_sw(
0297 struct dc_context *ctx,
0298 struct ddc *ddc_handle,
0299 uint16_t clock_delay_div_4)
0300 {
0301 uint32_t retry = 0;
0302
0303
0304
0305
0306
0307 write_bit_to_ddc(ddc_handle, SCL, true);
0308
0309 udelay(clock_delay_div_4);
0310
0311 do {
0312 write_bit_to_ddc(ddc_handle, SDA, true);
0313
0314 if (!read_bit_from_ddc(ddc_handle, SDA)) {
0315 ++retry;
0316 continue;
0317 }
0318
0319 udelay(clock_delay_div_4);
0320
0321 write_bit_to_ddc(ddc_handle, SCL, true);
0322
0323 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0324 break;
0325
0326 write_bit_to_ddc(ddc_handle, SDA, false);
0327
0328 udelay(clock_delay_div_4);
0329
0330 write_bit_to_ddc(ddc_handle, SCL, false);
0331
0332 udelay(clock_delay_div_4);
0333
0334 return true;
0335 } while (retry <= I2C_SW_RETRIES);
0336
0337 return false;
0338 }
0339
0340 static void dce_i2c_sw_engine_set_speed(
0341 struct dce_i2c_sw *engine,
0342 uint32_t speed)
0343 {
0344 ASSERT(speed);
0345
0346 engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
0347
0348 engine->clock_delay = 1000 / engine->speed;
0349
0350 if (engine->clock_delay < 12)
0351 engine->clock_delay = 12;
0352 }
0353
0354 static bool dce_i2c_sw_engine_acquire_engine(
0355 struct dce_i2c_sw *engine,
0356 struct ddc *ddc)
0357 {
0358 enum gpio_result result;
0359
0360 result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
0361 GPIO_DDC_CONFIG_TYPE_MODE_I2C);
0362
0363 if (result != GPIO_RESULT_OK)
0364 return false;
0365
0366 engine->ddc = ddc;
0367
0368 return true;
0369 }
0370 bool dce_i2c_engine_acquire_sw(
0371 struct dce_i2c_sw *dce_i2c_sw,
0372 struct ddc *ddc_handle)
0373 {
0374 uint32_t counter = 0;
0375 bool result;
0376
0377 do {
0378
0379 result = dce_i2c_sw_engine_acquire_engine(
0380 dce_i2c_sw, ddc_handle);
0381
0382 if (result)
0383 break;
0384
0385
0386
0387 udelay(10);
0388
0389 ++counter;
0390 } while (counter < 2);
0391
0392 return result;
0393 }
0394
0395
0396
0397
0398 static void dce_i2c_sw_engine_submit_channel_request(
0399 struct dce_i2c_sw *engine,
0400 struct i2c_request_transaction_data *req)
0401 {
0402 struct ddc *ddc = engine->ddc;
0403 uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
0404
0405
0406
0407 bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
0408
0409
0410
0411 if (result) {
0412 switch (req->action) {
0413 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
0414 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
0415 result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
0416 req->address, req->length, req->data);
0417 break;
0418 case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
0419 case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
0420 result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
0421 req->address, req->length, req->data);
0422 break;
0423 default:
0424 result = false;
0425 break;
0426 }
0427 }
0428
0429
0430
0431 if (!result ||
0432 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
0433 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
0434 if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
0435 result = false;
0436
0437 req->status = result ?
0438 I2C_CHANNEL_OPERATION_SUCCEEDED :
0439 I2C_CHANNEL_OPERATION_FAILED;
0440 }
0441
0442 static bool dce_i2c_sw_engine_submit_payload(
0443 struct dce_i2c_sw *engine,
0444 struct i2c_payload *payload,
0445 bool middle_of_transaction)
0446 {
0447 struct i2c_request_transaction_data request;
0448
0449 if (!payload->write)
0450 request.action = middle_of_transaction ?
0451 DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
0452 DCE_I2C_TRANSACTION_ACTION_I2C_READ;
0453 else
0454 request.action = middle_of_transaction ?
0455 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
0456 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
0457
0458 request.address = (uint8_t) ((payload->address << 1) | !payload->write);
0459 request.length = payload->length;
0460 request.data = payload->data;
0461
0462 dce_i2c_sw_engine_submit_channel_request(engine, &request);
0463
0464 if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
0465 (request.status == I2C_CHANNEL_OPERATION_FAILED))
0466 return false;
0467
0468 return true;
0469 }
0470 bool dce_i2c_submit_command_sw(
0471 struct resource_pool *pool,
0472 struct ddc *ddc,
0473 struct i2c_command *cmd,
0474 struct dce_i2c_sw *dce_i2c_sw)
0475 {
0476 uint8_t index_of_payload = 0;
0477 bool result;
0478
0479 dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
0480
0481 result = true;
0482
0483 while (index_of_payload < cmd->number_of_payloads) {
0484 bool mot = (index_of_payload != cmd->number_of_payloads - 1);
0485
0486 struct i2c_payload *payload = cmd->payloads + index_of_payload;
0487
0488 if (!dce_i2c_sw_engine_submit_payload(
0489 dce_i2c_sw, payload, mot)) {
0490 result = false;
0491 break;
0492 }
0493
0494 ++index_of_payload;
0495 }
0496
0497 release_engine_dce_sw(pool, dce_i2c_sw);
0498
0499 return result;
0500 }