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
34void 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
41static 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
55static 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
68static 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
76static 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}
101static 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}
122static 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
179static 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}
239static 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}
276static 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
298static 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
323static 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
367void 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
381bool 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}
397bool 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
425void 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}
468bool 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}
496bool 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}
527struct 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}
545