This source file includes following definitions.
- dce_i2c_sw_construct
- read_bit_from_ddc
- write_bit_to_ddc
- release_engine_dce_sw
- get_hw_supported_ddc_line
- wait_for_scl_high_sw
- write_byte_sw
- read_byte_sw
- stop_sync_sw
- i2c_write_sw
- i2c_read_sw
- start_sync_sw
- dce_i2c_sw_engine_set_speed
- dce_i2c_sw_engine_acquire_engine
- dce_i2c_engine_acquire_sw
- dce_i2c_sw_engine_submit_channel_request
- dce_i2c_sw_engine_submit_payload
- dce_i2c_submit_command_sw
- dce_i2c_acquire_i2c_sw_engine
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include <linux/delay.h>
27
28 #include "dce_i2c.h"
29 #include "dce_i2c_sw.h"
30 #include "include/gpio_service_interface.h"
31 #define SCL false
32 #define SDA true
33
34 void dce_i2c_sw_construct(
35 struct dce_i2c_sw *dce_i2c_sw,
36 struct dc_context *ctx)
37 {
38 dce_i2c_sw->ctx = ctx;
39 }
40
41 static inline bool read_bit_from_ddc(
42 struct ddc *ddc,
43 bool data_nor_clock)
44 {
45 uint32_t value = 0;
46
47 if (data_nor_clock)
48 dal_gpio_get_value(ddc->pin_data, &value);
49 else
50 dal_gpio_get_value(ddc->pin_clock, &value);
51
52 return (value != 0);
53 }
54
55 static inline void write_bit_to_ddc(
56 struct ddc *ddc,
57 bool data_nor_clock,
58 bool bit)
59 {
60 uint32_t value = bit ? 1 : 0;
61
62 if (data_nor_clock)
63 dal_gpio_set_value(ddc->pin_data, value);
64 else
65 dal_gpio_set_value(ddc->pin_clock, value);
66 }
67
68 static void release_engine_dce_sw(
69 struct resource_pool *pool,
70 struct dce_i2c_sw *dce_i2c_sw)
71 {
72 dal_ddc_close(dce_i2c_sw->ddc);
73 dce_i2c_sw->ddc = NULL;
74 }
75
76 static bool get_hw_supported_ddc_line(
77 struct ddc *ddc,
78 enum gpio_ddc_line *line)
79 {
80 enum gpio_ddc_line line_found;
81
82 *line = GPIO_DDC_LINE_UNKNOWN;
83
84 if (!ddc) {
85 BREAK_TO_DEBUGGER();
86 return false;
87 }
88
89 if (!ddc->hw_info.hw_supported)
90 return false;
91
92 line_found = dal_ddc_get_line(ddc);
93
94 if (line_found >= GPIO_DDC_LINE_COUNT)
95 return false;
96
97 *line = line_found;
98
99 return true;
100 }
101 static bool wait_for_scl_high_sw(
102 struct dc_context *ctx,
103 struct ddc *ddc,
104 uint16_t clock_delay_div_4)
105 {
106 uint32_t scl_retry = 0;
107 uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
108
109 udelay(clock_delay_div_4);
110
111 do {
112 if (read_bit_from_ddc(ddc, SCL))
113 return true;
114
115 udelay(clock_delay_div_4);
116
117 ++scl_retry;
118 } while (scl_retry <= scl_retry_max);
119
120 return false;
121 }
122 static bool write_byte_sw(
123 struct dc_context *ctx,
124 struct ddc *ddc_handle,
125 uint16_t clock_delay_div_4,
126 uint8_t byte)
127 {
128 int32_t shift = 7;
129 bool ack;
130
131
132
133 do {
134 udelay(clock_delay_div_4);
135
136 write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
137
138 udelay(clock_delay_div_4);
139
140 write_bit_to_ddc(ddc_handle, SCL, true);
141
142 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
143 return false;
144
145 write_bit_to_ddc(ddc_handle, SCL, false);
146
147 --shift;
148 } while (shift >= 0);
149
150
151
152
153
154
155 udelay(clock_delay_div_4);
156
157 write_bit_to_ddc(ddc_handle, SDA, true);
158
159 udelay(clock_delay_div_4);
160
161 write_bit_to_ddc(ddc_handle, SCL, true);
162
163 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
164 return false;
165
166
167
168 ack = !read_bit_from_ddc(ddc_handle, SDA);
169
170 udelay(clock_delay_div_4 << 1);
171
172 write_bit_to_ddc(ddc_handle, SCL, false);
173
174 udelay(clock_delay_div_4 << 1);
175
176 return ack;
177 }
178
179 static bool read_byte_sw(
180 struct dc_context *ctx,
181 struct ddc *ddc_handle,
182 uint16_t clock_delay_div_4,
183 uint8_t *byte,
184 bool more)
185 {
186 int32_t shift = 7;
187
188 uint8_t data = 0;
189
190
191
192
193
194 do {
195 write_bit_to_ddc(ddc_handle, SCL, true);
196
197 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
198 return false;
199
200 if (read_bit_from_ddc(ddc_handle, SDA))
201 data |= (1 << shift);
202
203 write_bit_to_ddc(ddc_handle, SCL, false);
204
205 udelay(clock_delay_div_4 << 1);
206
207 --shift;
208 } while (shift >= 0);
209
210
211
212 *byte = data;
213
214 udelay(clock_delay_div_4);
215
216
217
218
219
220 write_bit_to_ddc(ddc_handle, SDA, !more);
221
222 udelay(clock_delay_div_4);
223
224 write_bit_to_ddc(ddc_handle, SCL, true);
225
226 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
227 return false;
228
229 write_bit_to_ddc(ddc_handle, SCL, false);
230
231 udelay(clock_delay_div_4);
232
233 write_bit_to_ddc(ddc_handle, SDA, true);
234
235 udelay(clock_delay_div_4);
236
237 return true;
238 }
239 static bool stop_sync_sw(
240 struct dc_context *ctx,
241 struct ddc *ddc_handle,
242 uint16_t clock_delay_div_4)
243 {
244 uint32_t retry = 0;
245
246
247
248
249
250 write_bit_to_ddc(ddc_handle, SCL, false);
251
252 udelay(clock_delay_div_4);
253
254 write_bit_to_ddc(ddc_handle, SDA, false);
255
256 udelay(clock_delay_div_4);
257
258 write_bit_to_ddc(ddc_handle, SCL, true);
259
260 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
261 return false;
262
263 write_bit_to_ddc(ddc_handle, SDA, true);
264
265 do {
266 udelay(clock_delay_div_4);
267
268 if (read_bit_from_ddc(ddc_handle, SDA))
269 return true;
270
271 ++retry;
272 } while (retry <= 2);
273
274 return false;
275 }
276 static bool i2c_write_sw(
277 struct dc_context *ctx,
278 struct ddc *ddc_handle,
279 uint16_t clock_delay_div_4,
280 uint8_t address,
281 uint32_t length,
282 const uint8_t *data)
283 {
284 uint32_t i = 0;
285
286 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
287 return false;
288
289 while (i < length) {
290 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
291 return false;
292 ++i;
293 }
294
295 return true;
296 }
297
298 static bool i2c_read_sw(
299 struct dc_context *ctx,
300 struct ddc *ddc_handle,
301 uint16_t clock_delay_div_4,
302 uint8_t address,
303 uint32_t length,
304 uint8_t *data)
305 {
306 uint32_t i = 0;
307
308 if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
309 return false;
310
311 while (i < length) {
312 if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
313 i < length - 1))
314 return false;
315 ++i;
316 }
317
318 return true;
319 }
320
321
322
323 static bool start_sync_sw(
324 struct dc_context *ctx,
325 struct ddc *ddc_handle,
326 uint16_t clock_delay_div_4)
327 {
328 uint32_t retry = 0;
329
330
331
332
333
334 write_bit_to_ddc(ddc_handle, SCL, true);
335
336 udelay(clock_delay_div_4);
337
338 do {
339 write_bit_to_ddc(ddc_handle, SDA, true);
340
341 if (!read_bit_from_ddc(ddc_handle, SDA)) {
342 ++retry;
343 continue;
344 }
345
346 udelay(clock_delay_div_4);
347
348 write_bit_to_ddc(ddc_handle, SCL, true);
349
350 if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
351 break;
352
353 write_bit_to_ddc(ddc_handle, SDA, false);
354
355 udelay(clock_delay_div_4);
356
357 write_bit_to_ddc(ddc_handle, SCL, false);
358
359 udelay(clock_delay_div_4);
360
361 return true;
362 } while (retry <= I2C_SW_RETRIES);
363
364 return false;
365 }
366
367 void dce_i2c_sw_engine_set_speed(
368 struct dce_i2c_sw *engine,
369 uint32_t speed)
370 {
371 ASSERT(speed);
372
373 engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
374
375 engine->clock_delay = 1000 / engine->speed;
376
377 if (engine->clock_delay < 12)
378 engine->clock_delay = 12;
379 }
380
381 bool dce_i2c_sw_engine_acquire_engine(
382 struct dce_i2c_sw *engine,
383 struct ddc *ddc)
384 {
385 enum gpio_result result;
386
387 result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
388 GPIO_DDC_CONFIG_TYPE_MODE_I2C);
389
390 if (result != GPIO_RESULT_OK)
391 return false;
392
393 engine->ddc = ddc;
394
395 return true;
396 }
397 bool dce_i2c_engine_acquire_sw(
398 struct dce_i2c_sw *dce_i2c_sw,
399 struct ddc *ddc_handle)
400 {
401 uint32_t counter = 0;
402 bool result;
403
404 do {
405
406 result = dce_i2c_sw_engine_acquire_engine(
407 dce_i2c_sw, ddc_handle);
408
409 if (result)
410 break;
411
412
413
414 udelay(10);
415
416 ++counter;
417 } while (counter < 2);
418
419 return result;
420 }
421
422
423
424
425 void dce_i2c_sw_engine_submit_channel_request(
426 struct dce_i2c_sw *engine,
427 struct i2c_request_transaction_data *req)
428 {
429 struct ddc *ddc = engine->ddc;
430 uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
431
432
433
434 bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
435
436
437
438 if (result) {
439 switch (req->action) {
440 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
441 case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
442 result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
443 req->address, req->length, req->data);
444 break;
445 case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
446 case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
447 result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
448 req->address, req->length, req->data);
449 break;
450 default:
451 result = false;
452 break;
453 }
454 }
455
456
457
458 if (!result ||
459 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
460 (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
461 if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
462 result = false;
463
464 req->status = result ?
465 I2C_CHANNEL_OPERATION_SUCCEEDED :
466 I2C_CHANNEL_OPERATION_FAILED;
467 }
468 bool dce_i2c_sw_engine_submit_payload(
469 struct dce_i2c_sw *engine,
470 struct i2c_payload *payload,
471 bool middle_of_transaction)
472 {
473 struct i2c_request_transaction_data request;
474
475 if (!payload->write)
476 request.action = middle_of_transaction ?
477 DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
478 DCE_I2C_TRANSACTION_ACTION_I2C_READ;
479 else
480 request.action = middle_of_transaction ?
481 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
482 DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
483
484 request.address = (uint8_t) ((payload->address << 1) | !payload->write);
485 request.length = payload->length;
486 request.data = payload->data;
487
488 dce_i2c_sw_engine_submit_channel_request(engine, &request);
489
490 if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
491 (request.status == I2C_CHANNEL_OPERATION_FAILED))
492 return false;
493
494 return true;
495 }
496 bool dce_i2c_submit_command_sw(
497 struct resource_pool *pool,
498 struct ddc *ddc,
499 struct i2c_command *cmd,
500 struct dce_i2c_sw *dce_i2c_sw)
501 {
502 uint8_t index_of_payload = 0;
503 bool result;
504
505 dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
506
507 result = true;
508
509 while (index_of_payload < cmd->number_of_payloads) {
510 bool mot = (index_of_payload != cmd->number_of_payloads - 1);
511
512 struct i2c_payload *payload = cmd->payloads + index_of_payload;
513
514 if (!dce_i2c_sw_engine_submit_payload(
515 dce_i2c_sw, payload, mot)) {
516 result = false;
517 break;
518 }
519
520 ++index_of_payload;
521 }
522
523 release_engine_dce_sw(pool, dce_i2c_sw);
524
525 return result;
526 }
527 struct dce_i2c_sw *dce_i2c_acquire_i2c_sw_engine(
528 struct resource_pool *pool,
529 struct ddc *ddc)
530 {
531 enum gpio_ddc_line line;
532 struct dce_i2c_sw *engine = NULL;
533
534 if (get_hw_supported_ddc_line(ddc, &line))
535 engine = pool->sw_i2cs[line];
536
537 if (!engine)
538 return NULL;
539
540 if (!dce_i2c_engine_acquire_sw(engine, ddc))
541 return NULL;
542
543 return engine;
544 }