xref: /dragonfly/sys/dev/drm/amd/display/dc/i2caux/i2c_sw_engine.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1 /*
2  * Copyright 2012-15 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 "dm_services.h"
27 
28 /*
29  * Pre-requisites: headers required by header of this unit
30  */
31 #include "include/i2caux_interface.h"
32 #include "engine.h"
33 #include "i2c_engine.h"
34 
35 /*
36  * Header of this unit
37  */
38 
39 #include "i2c_sw_engine.h"
40 
41 /*
42  * Post-requisites: headers required by this unit
43  */
44 
45 /*
46  * This unit
47  */
48 
49 #define SCL false
50 #define SDA true
51 
read_bit_from_ddc(struct ddc * ddc,bool data_nor_clock)52 static inline bool read_bit_from_ddc(
53           struct ddc *ddc,
54           bool data_nor_clock)
55 {
56           uint32_t value = 0;
57 
58           if (data_nor_clock)
59                     dal_gpio_get_value(ddc->pin_data, &value);
60           else
61                     dal_gpio_get_value(ddc->pin_clock, &value);
62 
63           return (value != 0);
64 }
65 
write_bit_to_ddc(struct ddc * ddc,bool data_nor_clock,bool bit)66 static inline void write_bit_to_ddc(
67           struct ddc *ddc,
68           bool data_nor_clock,
69           bool bit)
70 {
71           uint32_t value = bit ? 1 : 0;
72 
73           if (data_nor_clock)
74                     dal_gpio_set_value(ddc->pin_data, value);
75           else
76                     dal_gpio_set_value(ddc->pin_clock, value);
77 }
78 
wait_for_scl_high(struct dc_context * ctx,struct ddc * ddc,uint16_t clock_delay_div_4)79 static bool wait_for_scl_high(
80           struct dc_context *ctx,
81           struct ddc *ddc,
82           uint16_t clock_delay_div_4)
83 {
84           uint32_t scl_retry = 0;
85           uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
86 
87           udelay(clock_delay_div_4);
88 
89           /* 3 milliseconds delay
90            * to wake up some displays from "low power" state.
91            */
92 
93           do {
94                     if (read_bit_from_ddc(ddc, SCL))
95                               return true;
96 
97                     udelay(clock_delay_div_4);
98 
99                     ++scl_retry;
100           } while (scl_retry <= scl_retry_max);
101 
102           return false;
103 }
104 
start_sync(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4)105 static bool start_sync(
106           struct dc_context *ctx,
107           struct ddc *ddc_handle,
108           uint16_t clock_delay_div_4)
109 {
110           uint32_t retry = 0;
111 
112           /* The I2C communications start signal is:
113            * the SDA going low from high, while the SCL is high. */
114 
115           write_bit_to_ddc(ddc_handle, SCL, true);
116 
117           udelay(clock_delay_div_4);
118 
119           do {
120                     write_bit_to_ddc(ddc_handle, SDA, true);
121 
122                     if (!read_bit_from_ddc(ddc_handle, SDA)) {
123                               ++retry;
124                               continue;
125                     }
126 
127                     udelay(clock_delay_div_4);
128 
129                     write_bit_to_ddc(ddc_handle, SCL, true);
130 
131                     if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
132                               break;
133 
134                     write_bit_to_ddc(ddc_handle, SDA, false);
135 
136                     udelay(clock_delay_div_4);
137 
138                     write_bit_to_ddc(ddc_handle, SCL, false);
139 
140                     udelay(clock_delay_div_4);
141 
142                     return true;
143           } while (retry <= I2C_SW_RETRIES);
144 
145           return false;
146 }
147 
stop_sync(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4)148 static bool stop_sync(
149           struct dc_context *ctx,
150           struct ddc *ddc_handle,
151           uint16_t clock_delay_div_4)
152 {
153           uint32_t retry = 0;
154 
155           /* The I2C communications stop signal is:
156            * the SDA going high from low, while the SCL is high. */
157 
158           write_bit_to_ddc(ddc_handle, SCL, false);
159 
160           udelay(clock_delay_div_4);
161 
162           write_bit_to_ddc(ddc_handle, SDA, false);
163 
164           udelay(clock_delay_div_4);
165 
166           write_bit_to_ddc(ddc_handle, SCL, true);
167 
168           if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
169                     return false;
170 
171           write_bit_to_ddc(ddc_handle, SDA, true);
172 
173           do {
174                     udelay(clock_delay_div_4);
175 
176                     if (read_bit_from_ddc(ddc_handle, SDA))
177                               return true;
178 
179                     ++retry;
180           } while (retry <= 2);
181 
182           return false;
183 }
184 
write_byte(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4,uint8_t byte)185 static bool write_byte(
186           struct dc_context *ctx,
187           struct ddc *ddc_handle,
188           uint16_t clock_delay_div_4,
189           uint8_t byte)
190 {
191           int32_t shift = 7;
192           bool ack;
193 
194           /* bits are transmitted serially, starting from MSB */
195 
196           do {
197                     udelay(clock_delay_div_4);
198 
199                     write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
200 
201                     udelay(clock_delay_div_4);
202 
203                     write_bit_to_ddc(ddc_handle, SCL, true);
204 
205                     if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
206                               return false;
207 
208                     write_bit_to_ddc(ddc_handle, SCL, false);
209 
210                     --shift;
211           } while (shift >= 0);
212 
213           /* The display sends ACK by preventing the SDA from going high
214            * after the SCL pulse we use to send our last data bit.
215            * If the SDA goes high after that bit, it's a NACK */
216 
217           udelay(clock_delay_div_4);
218 
219           write_bit_to_ddc(ddc_handle, SDA, true);
220 
221           udelay(clock_delay_div_4);
222 
223           write_bit_to_ddc(ddc_handle, SCL, true);
224 
225           if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
226                     return false;
227 
228           /* read ACK bit */
229 
230           ack = !read_bit_from_ddc(ddc_handle, SDA);
231 
232           udelay(clock_delay_div_4 << 1);
233 
234           write_bit_to_ddc(ddc_handle, SCL, false);
235 
236           udelay(clock_delay_div_4 << 1);
237 
238           return ack;
239 }
240 
read_byte(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4,uint8_t * byte,bool more)241 static bool read_byte(
242           struct dc_context *ctx,
243           struct ddc *ddc_handle,
244           uint16_t clock_delay_div_4,
245           uint8_t *byte,
246           bool more)
247 {
248           int32_t shift = 7;
249 
250           uint8_t data = 0;
251 
252           /* The data bits are read from MSB to LSB;
253            * bit is read while SCL is high */
254 
255           do {
256                     write_bit_to_ddc(ddc_handle, SCL, true);
257 
258                     if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
259                               return false;
260 
261                     if (read_bit_from_ddc(ddc_handle, SDA))
262                               data |= (1 << shift);
263 
264                     write_bit_to_ddc(ddc_handle, SCL, false);
265 
266                     udelay(clock_delay_div_4 << 1);
267 
268                     --shift;
269           } while (shift >= 0);
270 
271           /* read only whole byte */
272 
273           *byte = data;
274 
275           udelay(clock_delay_div_4);
276 
277           /* send the acknowledge bit:
278            * SDA low means ACK, SDA high means NACK */
279 
280           write_bit_to_ddc(ddc_handle, SDA, !more);
281 
282           udelay(clock_delay_div_4);
283 
284           write_bit_to_ddc(ddc_handle, SCL, true);
285 
286           if (!wait_for_scl_high(ctx, ddc_handle, clock_delay_div_4))
287                     return false;
288 
289           write_bit_to_ddc(ddc_handle, SCL, false);
290 
291           udelay(clock_delay_div_4);
292 
293           write_bit_to_ddc(ddc_handle, SDA, true);
294 
295           udelay(clock_delay_div_4);
296 
297           return true;
298 }
299 
i2c_write(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4,uint8_t address,uint32_t length,const uint8_t * data)300 static bool i2c_write(
301           struct dc_context *ctx,
302           struct ddc *ddc_handle,
303           uint16_t clock_delay_div_4,
304           uint8_t address,
305           uint32_t length,
306           const uint8_t *data)
307 {
308           uint32_t i = 0;
309 
310           if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
311                     return false;
312 
313           while (i < length) {
314                     if (!write_byte(ctx, ddc_handle, clock_delay_div_4, data[i]))
315                               return false;
316                     ++i;
317           }
318 
319           return true;
320 }
321 
i2c_read(struct dc_context * ctx,struct ddc * ddc_handle,uint16_t clock_delay_div_4,uint8_t address,uint32_t length,uint8_t * data)322 static bool i2c_read(
323           struct dc_context *ctx,
324           struct ddc *ddc_handle,
325           uint16_t clock_delay_div_4,
326           uint8_t address,
327           uint32_t length,
328           uint8_t *data)
329 {
330           uint32_t i = 0;
331 
332           if (!write_byte(ctx, ddc_handle, clock_delay_div_4, address))
333                     return false;
334 
335           while (i < length) {
336                     if (!read_byte(ctx, ddc_handle, clock_delay_div_4, data + i,
337                               i < length - 1))
338                               return false;
339                     ++i;
340           }
341 
342           return true;
343 }
344 
345 /*
346  * @brief
347  * Cast 'struct i2c_engine *'
348  * to 'struct i2c_sw_engine *'
349  */
350 #define FROM_I2C_ENGINE(ptr) \
351           container_of((ptr), struct i2c_sw_engine, base)
352 
353 /*
354  * @brief
355  * Cast 'struct engine *'
356  * to 'struct i2c_sw_engine *'
357  */
358 #define FROM_ENGINE(ptr) \
359           FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
360 
dal_i2c_sw_engine_get_engine_type(const struct engine * engine)361 enum i2caux_engine_type dal_i2c_sw_engine_get_engine_type(
362           const struct engine *engine)
363 {
364           return I2CAUX_ENGINE_TYPE_I2C_SW;
365 }
366 
dal_i2c_sw_engine_submit_request(struct engine * engine,struct i2caux_transaction_request * i2caux_request,bool middle_of_transaction)367 bool dal_i2c_sw_engine_submit_request(
368           struct engine *engine,
369           struct i2caux_transaction_request *i2caux_request,
370           bool middle_of_transaction)
371 {
372           struct i2c_sw_engine *sw_engine = FROM_ENGINE(engine);
373 
374           struct i2c_engine *base = &sw_engine->base;
375 
376           struct i2c_request_transaction_data request;
377           bool operation_succeeded = false;
378 
379           if (i2caux_request->operation == I2CAUX_TRANSACTION_READ)
380                     request.action = middle_of_transaction ?
381                               I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT :
382                               I2CAUX_TRANSACTION_ACTION_I2C_READ;
383           else if (i2caux_request->operation == I2CAUX_TRANSACTION_WRITE)
384                     request.action = middle_of_transaction ?
385                               I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT :
386                               I2CAUX_TRANSACTION_ACTION_I2C_WRITE;
387           else {
388                     i2caux_request->status =
389                               I2CAUX_TRANSACTION_STATUS_FAILED_INVALID_OPERATION;
390                     /* in DAL2, there was no "return false" */
391                     return false;
392           }
393 
394           request.address = (uint8_t)i2caux_request->payload.address;
395           request.length = i2caux_request->payload.length;
396           request.data = i2caux_request->payload.data;
397 
398           base->funcs->submit_channel_request(base, &request);
399 
400           if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
401                     (request.status == I2C_CHANNEL_OPERATION_FAILED))
402                     i2caux_request->status =
403                               I2CAUX_TRANSACTION_STATUS_FAILED_CHANNEL_BUSY;
404           else {
405                     enum i2c_channel_operation_result operation_result;
406 
407                     do {
408                               operation_result =
409                                         base->funcs->get_channel_status(base, NULL);
410 
411                               switch (operation_result) {
412                               case I2C_CHANNEL_OPERATION_SUCCEEDED:
413                                         i2caux_request->status =
414                                                   I2CAUX_TRANSACTION_STATUS_SUCCEEDED;
415                                         operation_succeeded = true;
416                               break;
417                               case I2C_CHANNEL_OPERATION_NO_RESPONSE:
418                                         i2caux_request->status =
419                                                   I2CAUX_TRANSACTION_STATUS_FAILED_NACK;
420                               break;
421                               case I2C_CHANNEL_OPERATION_TIMEOUT:
422                                         i2caux_request->status =
423                                         I2CAUX_TRANSACTION_STATUS_FAILED_TIMEOUT;
424                               break;
425                               case I2C_CHANNEL_OPERATION_FAILED:
426                                         i2caux_request->status =
427                                         I2CAUX_TRANSACTION_STATUS_FAILED_INCOMPLETE;
428                               break;
429                               default:
430                                         i2caux_request->status =
431                                         I2CAUX_TRANSACTION_STATUS_FAILED_OPERATION;
432                               break;
433                               }
434                     } while (operation_result == I2C_CHANNEL_OPERATION_ENGINE_BUSY);
435           }
436 
437           return operation_succeeded;
438 }
439 
dal_i2c_sw_engine_get_speed(const struct i2c_engine * engine)440 uint32_t dal_i2c_sw_engine_get_speed(
441           const struct i2c_engine *engine)
442 {
443           return FROM_I2C_ENGINE(engine)->speed;
444 }
445 
dal_i2c_sw_engine_set_speed(struct i2c_engine * engine,uint32_t speed)446 void dal_i2c_sw_engine_set_speed(
447           struct i2c_engine *engine,
448           uint32_t speed)
449 {
450           struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
451 
452           ASSERT(speed);
453 
454           sw_engine->speed = speed ? speed : I2CAUX_DEFAULT_I2C_SW_SPEED;
455 
456           sw_engine->clock_delay = 1000 / sw_engine->speed;
457 
458           if (sw_engine->clock_delay < 12)
459                     sw_engine->clock_delay = 12;
460 }
461 
dal_i2caux_i2c_sw_engine_acquire_engine(struct i2c_engine * engine,struct ddc * ddc)462 bool dal_i2caux_i2c_sw_engine_acquire_engine(
463           struct i2c_engine *engine,
464           struct ddc *ddc)
465 {
466           enum gpio_result result;
467 
468           result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
469                     GPIO_DDC_CONFIG_TYPE_MODE_I2C);
470 
471           if (result != GPIO_RESULT_OK)
472                     return false;
473 
474           engine->base.ddc = ddc;
475 
476           return true;
477 }
478 
dal_i2c_sw_engine_submit_channel_request(struct i2c_engine * engine,struct i2c_request_transaction_data * req)479 void dal_i2c_sw_engine_submit_channel_request(
480           struct i2c_engine *engine,
481           struct i2c_request_transaction_data *req)
482 {
483           struct i2c_sw_engine *sw_engine = FROM_I2C_ENGINE(engine);
484 
485           struct ddc *ddc = engine->base.ddc;
486           uint16_t clock_delay_div_4 = sw_engine->clock_delay >> 2;
487 
488           /* send sync (start / repeated start) */
489 
490           bool result = start_sync(engine->base.ctx, ddc, clock_delay_div_4);
491 
492           /* process payload */
493 
494           if (result) {
495                     switch (req->action) {
496                     case I2CAUX_TRANSACTION_ACTION_I2C_WRITE:
497                     case I2CAUX_TRANSACTION_ACTION_I2C_WRITE_MOT:
498                               result = i2c_write(engine->base.ctx, ddc, clock_delay_div_4,
499                                         req->address, req->length, req->data);
500                     break;
501                     case I2CAUX_TRANSACTION_ACTION_I2C_READ:
502                     case I2CAUX_TRANSACTION_ACTION_I2C_READ_MOT:
503                               result = i2c_read(engine->base.ctx, ddc, clock_delay_div_4,
504                                         req->address, req->length, req->data);
505                     break;
506                     default:
507                               result = false;
508                     break;
509                     }
510           }
511 
512           /* send stop if not 'mot' or operation failed */
513 
514           if (!result ||
515                     (req->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
516                     (req->action == I2CAUX_TRANSACTION_ACTION_I2C_READ))
517                     if (!stop_sync(engine->base.ctx, ddc, clock_delay_div_4))
518                               result = false;
519 
520           req->status = result ?
521                     I2C_CHANNEL_OPERATION_SUCCEEDED :
522                     I2C_CHANNEL_OPERATION_FAILED;
523 }
524 
dal_i2c_sw_engine_get_channel_status(struct i2c_engine * engine,uint8_t * returned_bytes)525 enum i2c_channel_operation_result dal_i2c_sw_engine_get_channel_status(
526           struct i2c_engine *engine,
527           uint8_t *returned_bytes)
528 {
529           /* No arbitration with VBIOS is performed since DCE 6.0 */
530           return I2C_CHANNEL_OPERATION_SUCCEEDED;
531 }
532 
dal_i2c_sw_engine_destruct(struct i2c_sw_engine * engine)533 void dal_i2c_sw_engine_destruct(
534           struct i2c_sw_engine *engine)
535 {
536           dal_i2c_engine_destruct(&engine->base);
537 }
538 
destroy(struct i2c_engine ** ptr)539 static void destroy(
540           struct i2c_engine **ptr)
541 {
542           dal_i2c_sw_engine_destruct(FROM_I2C_ENGINE(*ptr));
543 
544           kfree(*ptr);
545           *ptr = NULL;
546 }
547 
548 static const struct i2c_engine_funcs i2c_engine_funcs = {
549           .acquire_engine = dal_i2caux_i2c_sw_engine_acquire_engine,
550           .destroy = destroy,
551           .get_speed = dal_i2c_sw_engine_get_speed,
552           .set_speed = dal_i2c_sw_engine_set_speed,
553           .setup_engine = dal_i2c_engine_setup_i2c_engine,
554           .submit_channel_request = dal_i2c_sw_engine_submit_channel_request,
555           .process_channel_reply = dal_i2c_engine_process_channel_reply,
556           .get_channel_status = dal_i2c_sw_engine_get_channel_status,
557 };
558 
release_engine(struct engine * engine)559 static void release_engine(
560           struct engine *engine)
561 {
562 
563 }
564 
565 static const struct engine_funcs engine_funcs = {
566           .release_engine = release_engine,
567           .get_engine_type = dal_i2c_sw_engine_get_engine_type,
568           .acquire = dal_i2c_engine_acquire,
569           .submit_request = dal_i2c_sw_engine_submit_request,
570 };
571 
dal_i2c_sw_engine_construct(struct i2c_sw_engine * engine,const struct i2c_sw_engine_create_arg * arg)572 void dal_i2c_sw_engine_construct(
573           struct i2c_sw_engine *engine,
574           const struct i2c_sw_engine_create_arg *arg)
575 {
576           dal_i2c_engine_construct(&engine->base, arg->ctx);
577           dal_i2c_sw_engine_set_speed(&engine->base, arg->default_speed);
578           engine->base.funcs = &i2c_engine_funcs;
579           engine->base.base.funcs = &engine_funcs;
580 }
581 
dal_i2c_sw_engine_create(const struct i2c_sw_engine_create_arg * arg)582 struct i2c_engine *dal_i2c_sw_engine_create(
583           const struct i2c_sw_engine_create_arg *arg)
584 {
585           struct i2c_sw_engine *engine;
586 
587           if (!arg) {
588                     BREAK_TO_DEBUGGER();
589                     return NULL;
590           }
591 
592           engine = kzalloc(sizeof(struct i2c_sw_engine), GFP_KERNEL);
593 
594           if (!engine) {
595                     BREAK_TO_DEBUGGER();
596                     return NULL;
597           }
598 
599           dal_i2c_sw_engine_construct(engine, arg);
600           return &engine->base;
601 }
602