xref: /dragonfly/sys/dev/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.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 #include "../i2c_hw_engine.h"
35 #include "../i2c_generic_hw_engine.h"
36 /*
37  * Header of this unit
38  */
39 
40 #include "i2c_hw_engine_dce80.h"
41 
42 /*
43  * Post-requisites: headers required by this unit
44  */
45 
46 #include "dce/dce_8_0_d.h"
47 #include "dce/dce_8_0_sh_mask.h"
48 /*
49  * This unit
50  */
51 
52 enum dc_i2c_status {
53           DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
54           DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
55           DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
56 };
57 
58 enum dc_i2c_arbitration {
59           DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
60           DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
61 };
62 
63 enum {
64           /* No timeout in HW
65            * (timeout implemented in SW by querying status) */
66           I2C_SETUP_TIME_LIMIT = 255,
67           I2C_HW_BUFFER_SIZE = 144
68 };
69 
70 /*
71  * @brief
72  * Cast 'struct i2c_hw_engine *'
73  * to 'struct i2c_hw_engine_dce80 *'
74  */
75 #define FROM_I2C_HW_ENGINE(ptr) \
76           container_of((ptr), struct i2c_hw_engine_dce80, base)
77 
78 /*
79  * @brief
80  * Cast pointer to 'struct i2c_engine *'
81  * to pointer to 'struct i2c_hw_engine_dce80 *'
82  */
83 #define FROM_I2C_ENGINE(ptr) \
84           FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
85 
86 /*
87  * @brief
88  * Cast pointer to 'struct engine *'
89  * to 'pointer to struct i2c_hw_engine_dce80 *'
90  */
91 #define FROM_ENGINE(ptr) \
92           FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
93 
disable_i2c_hw_engine(struct i2c_hw_engine_dce80 * engine)94 static void disable_i2c_hw_engine(
95           struct i2c_hw_engine_dce80 *engine)
96 {
97           const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
98           uint32_t value = 0;
99 
100           struct dc_context *ctx = NULL;
101 
102           ctx = engine->base.base.base.ctx;
103 
104           value = dm_read_reg(ctx, addr);
105 
106           set_reg_field_value(
107                     value,
108                     0,
109                     DC_I2C_DDC1_SETUP,
110                     DC_I2C_DDC1_ENABLE);
111 
112           dm_write_reg(ctx, addr, value);
113 }
114 
release_engine(struct engine * engine)115 static void release_engine(
116           struct engine *engine)
117 {
118           struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine);
119 
120           struct i2c_engine *base = NULL;
121           bool safe_to_reset;
122           uint32_t value = 0;
123 
124           base = &hw_engine->base.base;
125 
126           /* Restore original HW engine speed */
127 
128           base->funcs->set_speed(base, hw_engine->base.original_speed);
129 
130           /* Release I2C */
131           {
132                     value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
133 
134                     set_reg_field_value(
135                                         value,
136                                         1,
137                                         DC_I2C_ARBITRATION,
138                                         DC_I2C_SW_DONE_USING_I2C_REG);
139 
140                     dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
141           }
142 
143           /* Reset HW engine */
144           {
145                     uint32_t i2c_sw_status = 0;
146 
147                     value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
148 
149                     i2c_sw_status = get_reg_field_value(
150                                         value,
151                                         DC_I2C_SW_STATUS,
152                                         DC_I2C_SW_STATUS);
153                     /* if used by SW, safe to reset */
154                     safe_to_reset = (i2c_sw_status == 1);
155           }
156           {
157                     value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
158 
159                     if (safe_to_reset)
160                               set_reg_field_value(
161                                         value,
162                                         1,
163                                         DC_I2C_CONTROL,
164                                         DC_I2C_SOFT_RESET);
165 
166                     set_reg_field_value(
167                               value,
168                               1,
169                               DC_I2C_CONTROL,
170                               DC_I2C_SW_STATUS_RESET);
171 
172                     dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
173           }
174 
175           /* HW I2c engine - clock gating feature */
176           if (!hw_engine->engine_keep_power_up_count)
177                     disable_i2c_hw_engine(hw_engine);
178 }
179 
destruct(struct i2c_hw_engine_dce80 * engine)180 static void destruct(
181           struct i2c_hw_engine_dce80 *engine)
182 {
183           dal_i2c_hw_engine_destruct(&engine->base);
184 }
185 
destroy(struct i2c_engine ** i2c_engine)186 static void destroy(
187           struct i2c_engine **i2c_engine)
188 {
189           struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine);
190 
191           destruct(engine);
192 
193           kfree(engine);
194 
195           *i2c_engine = NULL;
196 }
197 
setup_engine(struct i2c_engine * i2c_engine)198 static bool setup_engine(
199           struct i2c_engine *i2c_engine)
200 {
201           uint32_t value = 0;
202           struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
203 
204           /* Program pin select */
205           {
206                     const uint32_t addr = mmDC_I2C_CONTROL;
207 
208                     value = dm_read_reg(i2c_engine->base.ctx, addr);
209 
210                     set_reg_field_value(
211                               value,
212                               0,
213                               DC_I2C_CONTROL,
214                               DC_I2C_GO);
215 
216                     set_reg_field_value(
217                               value,
218                               0,
219                               DC_I2C_CONTROL,
220                               DC_I2C_SOFT_RESET);
221 
222                     set_reg_field_value(
223                               value,
224                               0,
225                               DC_I2C_CONTROL,
226                               DC_I2C_SEND_RESET);
227 
228                     set_reg_field_value(
229                               value,
230                               0,
231                               DC_I2C_CONTROL,
232                               DC_I2C_SW_STATUS_RESET);
233 
234                     set_reg_field_value(
235                               value,
236                               0,
237                               DC_I2C_CONTROL,
238                               DC_I2C_TRANSACTION_COUNT);
239 
240                     set_reg_field_value(
241                               value,
242                               engine->engine_id,
243                               DC_I2C_CONTROL,
244                               DC_I2C_DDC_SELECT);
245 
246                     dm_write_reg(i2c_engine->base.ctx, addr, value);
247           }
248 
249           /* Program time limit */
250           {
251                     const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
252 
253                     value = dm_read_reg(i2c_engine->base.ctx, addr);
254 
255                     set_reg_field_value(
256                               value,
257                               I2C_SETUP_TIME_LIMIT,
258                               DC_I2C_DDC1_SETUP,
259                               DC_I2C_DDC1_TIME_LIMIT);
260 
261                     set_reg_field_value(
262                               value,
263                               1,
264                               DC_I2C_DDC1_SETUP,
265                               DC_I2C_DDC1_ENABLE);
266 
267                     dm_write_reg(i2c_engine->base.ctx, addr, value);
268           }
269 
270           /* Program HW priority
271            * set to High - interrupt software I2C at any time
272            * Enable restart of SW I2C that was interrupted by HW
273            * disable queuing of software while I2C is in use by HW */
274           {
275                     value = dm_read_reg(i2c_engine->base.ctx,
276                                         mmDC_I2C_ARBITRATION);
277 
278                     set_reg_field_value(
279                               value,
280                               0,
281                               DC_I2C_ARBITRATION,
282                               DC_I2C_NO_QUEUED_SW_GO);
283 
284                     set_reg_field_value(
285                               value,
286                               DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
287                               DC_I2C_ARBITRATION,
288                               DC_I2C_SW_PRIORITY);
289 
290                     dm_write_reg(i2c_engine->base.ctx,
291                                         mmDC_I2C_ARBITRATION, value);
292           }
293 
294           return true;
295 }
296 
get_speed(const struct i2c_engine * i2c_engine)297 static uint32_t get_speed(
298           const struct i2c_engine *i2c_engine)
299 {
300           const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
301 
302           const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
303 
304           uint32_t pre_scale = 0;
305 
306           uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
307 
308           pre_scale = get_reg_field_value(
309                               value,
310                               DC_I2C_DDC1_SPEED,
311                               DC_I2C_DDC1_PRESCALE);
312 
313           /* [anaumov] it seems following is unnecessary */
314           /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
315 
316           return pre_scale ?
317                     engine->reference_frequency / pre_scale :
318                     engine->base.default_speed;
319 }
320 
set_speed(struct i2c_engine * i2c_engine,uint32_t speed)321 static void set_speed(
322           struct i2c_engine *i2c_engine,
323           uint32_t speed)
324 {
325           struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
326 
327           if (speed) {
328                     const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
329 
330                     uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
331 
332                     set_reg_field_value(
333                               value,
334                               engine->reference_frequency / speed,
335                               DC_I2C_DDC1_SPEED,
336                               DC_I2C_DDC1_PRESCALE);
337 
338                     set_reg_field_value(
339                               value,
340                               2,
341                               DC_I2C_DDC1_SPEED,
342                               DC_I2C_DDC1_THRESHOLD);
343 
344                     dm_write_reg(i2c_engine->base.ctx, addr, value);
345           }
346 }
347 
reset_hw_engine(struct engine * engine)348 static inline void reset_hw_engine(struct engine *engine)
349 {
350           uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
351 
352           set_reg_field_value(
353                     value,
354                     1,
355                     DC_I2C_CONTROL,
356                     DC_I2C_SOFT_RESET);
357 
358           set_reg_field_value(
359                     value,
360                     1,
361                     DC_I2C_CONTROL,
362                     DC_I2C_SW_STATUS_RESET);
363 
364           dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
365 }
366 
is_hw_busy(struct engine * engine)367 static bool is_hw_busy(struct engine *engine)
368 {
369           uint32_t i2c_sw_status = 0;
370 
371           uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
372 
373           i2c_sw_status = get_reg_field_value(
374                               value,
375                               DC_I2C_SW_STATUS,
376                               DC_I2C_SW_STATUS);
377 
378           if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
379                     return false;
380 
381           reset_hw_engine(engine);
382 
383           value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
384 
385           i2c_sw_status = get_reg_field_value(
386                               value,
387                               DC_I2C_SW_STATUS,
388                               DC_I2C_SW_STATUS);
389 
390           return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
391 }
392 
393 /*
394  * @brief
395  * DC_GPIO_DDC MM register offsets
396  */
397 static const uint32_t transaction_addr[] = {
398           mmDC_I2C_TRANSACTION0,
399           mmDC_I2C_TRANSACTION1,
400           mmDC_I2C_TRANSACTION2,
401           mmDC_I2C_TRANSACTION3
402 };
403 
process_transaction(struct i2c_hw_engine_dce80 * engine,struct i2c_request_transaction_data * request)404 static bool process_transaction(
405           struct i2c_hw_engine_dce80 *engine,
406           struct i2c_request_transaction_data *request)
407 {
408           uint32_t length = request->length;
409           uint8_t *buffer = request->data;
410 
411           bool last_transaction = false;
412           uint32_t value = 0;
413 
414           struct dc_context *ctx = NULL;
415 
416           ctx = engine->base.base.base.ctx;
417 
418           {
419                     const uint32_t addr =
420                               transaction_addr[engine->transaction_count];
421 
422                     value = dm_read_reg(ctx, addr);
423 
424                     set_reg_field_value(
425                               value,
426                               1,
427                               DC_I2C_TRANSACTION0,
428                               DC_I2C_STOP_ON_NACK0);
429 
430                     set_reg_field_value(
431                               value,
432                               1,
433                               DC_I2C_TRANSACTION0,
434                               DC_I2C_START0);
435 
436                     if ((engine->transaction_count == 3) ||
437                     (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
438                     (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
439 
440                               set_reg_field_value(
441                                         value,
442                                         1,
443                                         DC_I2C_TRANSACTION0,
444                                         DC_I2C_STOP0);
445 
446                               last_transaction = true;
447                     } else
448                               set_reg_field_value(
449                                         value,
450                                         0,
451                                         DC_I2C_TRANSACTION0,
452                                         DC_I2C_STOP0);
453 
454                     set_reg_field_value(
455                               value,
456                               (0 != (request->action &
457                                                   I2CAUX_TRANSACTION_ACTION_I2C_READ)),
458                               DC_I2C_TRANSACTION0,
459                               DC_I2C_RW0);
460 
461                     set_reg_field_value(
462                               value,
463                               length,
464                               DC_I2C_TRANSACTION0,
465                               DC_I2C_COUNT0);
466 
467                     dm_write_reg(ctx, addr, value);
468           }
469 
470           /* Write the I2C address and I2C data
471            * into the hardware circular buffer, one byte per entry.
472            * As an example, the 7-bit I2C slave address for CRT monitor
473            * for reading DDC/EDID information is 0b1010001.
474            * For an I2C send operation, the LSB must be programmed to 0;
475            * for I2C receive operation, the LSB must be programmed to 1. */
476 
477           {
478                     value = 0;
479 
480                     set_reg_field_value(
481                               value,
482                               false,
483                               DC_I2C_DATA,
484                               DC_I2C_DATA_RW);
485 
486                     set_reg_field_value(
487                               value,
488                               request->address,
489                               DC_I2C_DATA,
490                               DC_I2C_DATA);
491 
492                     if (engine->transaction_count == 0) {
493                               set_reg_field_value(
494                                         value,
495                                         0,
496                                         DC_I2C_DATA,
497                                         DC_I2C_INDEX);
498 
499                               /*enable index write*/
500                               set_reg_field_value(
501                                         value,
502                                         1,
503                                         DC_I2C_DATA,
504                                         DC_I2C_INDEX_WRITE);
505                     }
506 
507                     dm_write_reg(ctx, mmDC_I2C_DATA, value);
508 
509                     if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
510 
511                               set_reg_field_value(
512                                         value,
513                                         0,
514                                         DC_I2C_DATA,
515                                         DC_I2C_INDEX_WRITE);
516 
517                               while (length) {
518 
519                                         set_reg_field_value(
520                                                   value,
521                                                   *buffer++,
522                                                   DC_I2C_DATA,
523                                                   DC_I2C_DATA);
524 
525                                         dm_write_reg(ctx, mmDC_I2C_DATA, value);
526                                         --length;
527                               }
528                     }
529           }
530 
531           ++engine->transaction_count;
532           engine->buffer_used_bytes += length + 1;
533 
534           return last_transaction;
535 }
536 
execute_transaction(struct i2c_hw_engine_dce80 * engine)537 static void execute_transaction(
538           struct i2c_hw_engine_dce80 *engine)
539 {
540           uint32_t value = 0;
541           struct dc_context *ctx = NULL;
542 
543           ctx = engine->base.base.base.ctx;
544 
545           {
546                     const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
547 
548                     value = dm_read_reg(ctx, addr);
549 
550                     set_reg_field_value(
551                               value,
552                               0,
553                               DC_I2C_DDC1_SETUP,
554                               DC_I2C_DDC1_DATA_DRIVE_EN);
555 
556                     set_reg_field_value(
557                               value,
558                               0,
559                               DC_I2C_DDC1_SETUP,
560                               DC_I2C_DDC1_CLK_DRIVE_EN);
561 
562                     set_reg_field_value(
563                               value,
564                               0,
565                               DC_I2C_DDC1_SETUP,
566                               DC_I2C_DDC1_DATA_DRIVE_SEL);
567 
568                     set_reg_field_value(
569                               value,
570                               0,
571                               DC_I2C_DDC1_SETUP,
572                               DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
573 
574                     set_reg_field_value(
575                               value,
576                               0,
577                               DC_I2C_DDC1_SETUP,
578                               DC_I2C_DDC1_INTRA_BYTE_DELAY);
579 
580                     dm_write_reg(ctx, addr, value);
581           }
582 
583           {
584                     const uint32_t addr = mmDC_I2C_CONTROL;
585 
586                     value = dm_read_reg(ctx, addr);
587 
588                     set_reg_field_value(
589                               value,
590                               0,
591                               DC_I2C_CONTROL,
592                               DC_I2C_SOFT_RESET);
593 
594                     set_reg_field_value(
595                               value,
596                               0,
597                               DC_I2C_CONTROL,
598                               DC_I2C_SW_STATUS_RESET);
599 
600                     set_reg_field_value(
601                               value,
602                               0,
603                               DC_I2C_CONTROL,
604                               DC_I2C_SEND_RESET);
605 
606                     set_reg_field_value(
607                               value,
608                               0,
609                               DC_I2C_CONTROL,
610                               DC_I2C_GO);
611 
612                     set_reg_field_value(
613                               value,
614                               engine->transaction_count - 1,
615                               DC_I2C_CONTROL,
616                               DC_I2C_TRANSACTION_COUNT);
617 
618                     dm_write_reg(ctx, addr, value);
619           }
620 
621           /* start I2C transfer */
622           {
623                     const uint32_t addr = mmDC_I2C_CONTROL;
624 
625                     value     = dm_read_reg(ctx, addr);
626 
627                     set_reg_field_value(
628                               value,
629                               1,
630                               DC_I2C_CONTROL,
631                               DC_I2C_GO);
632 
633                     dm_write_reg(ctx, addr, value);
634           }
635 
636           /* all transactions were executed and HW buffer became empty
637            * (even though it actually happens when status becomes DONE) */
638           engine->transaction_count = 0;
639           engine->buffer_used_bytes = 0;
640 }
641 
submit_channel_request(struct i2c_engine * engine,struct i2c_request_transaction_data * request)642 static void submit_channel_request(
643           struct i2c_engine *engine,
644           struct i2c_request_transaction_data *request)
645 {
646           request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
647 
648           if (!process_transaction(FROM_I2C_ENGINE(engine), request))
649                     return;
650 
651           if (is_hw_busy(&engine->base)) {
652                     request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
653                     return;
654           }
655 
656           execute_transaction(FROM_I2C_ENGINE(engine));
657 }
658 
process_channel_reply(struct i2c_engine * engine,struct i2c_reply_transaction_data * reply)659 static void process_channel_reply(
660           struct i2c_engine *engine,
661           struct i2c_reply_transaction_data *reply)
662 {
663           uint32_t length = reply->length;
664           uint8_t *buffer = reply->data;
665 
666           uint32_t value = 0;
667 
668           /*set index*/
669           set_reg_field_value(
670                     value,
671                     length - 1,
672                     DC_I2C_DATA,
673                     DC_I2C_INDEX);
674 
675           set_reg_field_value(
676                     value,
677                     1,
678                     DC_I2C_DATA,
679                     DC_I2C_DATA_RW);
680 
681           set_reg_field_value(
682                     value,
683                     1,
684                     DC_I2C_DATA,
685                     DC_I2C_INDEX_WRITE);
686 
687           dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
688 
689           while (length) {
690                     /* after reading the status,
691                      * if the I2C operation executed successfully
692                      * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
693                      * should read data bytes from I2C circular data buffer */
694 
695                     value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
696 
697                     *buffer++ = get_reg_field_value(
698                                         value,
699                                         DC_I2C_DATA,
700                                         DC_I2C_DATA);
701 
702                     --length;
703           }
704 }
705 
get_channel_status(struct i2c_engine * engine,uint8_t * returned_bytes)706 static enum i2c_channel_operation_result get_channel_status(
707           struct i2c_engine *engine,
708           uint8_t *returned_bytes)
709 {
710           uint32_t i2c_sw_status = 0;
711           uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
712 
713           i2c_sw_status = get_reg_field_value(
714                               value,
715                               DC_I2C_SW_STATUS,
716                               DC_I2C_SW_STATUS);
717 
718           if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
719                     return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
720           else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
721                     return I2C_CHANNEL_OPERATION_NO_RESPONSE;
722           else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
723                     return I2C_CHANNEL_OPERATION_TIMEOUT;
724           else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
725                     return I2C_CHANNEL_OPERATION_FAILED;
726           else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
727                     return I2C_CHANNEL_OPERATION_SUCCEEDED;
728 
729           /*
730            * this is the case when HW used for communication, I2C_SW_STATUS
731            * could be zero
732            */
733           return I2C_CHANNEL_OPERATION_SUCCEEDED;
734 }
735 
get_hw_buffer_available_size(const struct i2c_hw_engine * engine)736 static uint32_t get_hw_buffer_available_size(
737           const struct i2c_hw_engine *engine)
738 {
739           return I2C_HW_BUFFER_SIZE -
740                     FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
741 }
742 
get_transaction_timeout(const struct i2c_hw_engine * engine,uint32_t length)743 static uint32_t get_transaction_timeout(
744           const struct i2c_hw_engine *engine,
745           uint32_t length)
746 {
747           uint32_t speed = engine->base.funcs->get_speed(&engine->base);
748 
749           uint32_t period_timeout;
750           uint32_t num_of_clock_stretches;
751 
752           if (!speed)
753                     return 0;
754 
755           period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
756 
757           num_of_clock_stretches = 1 + (length << 3) + 1;
758           num_of_clock_stretches +=
759                     (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
760                     (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
761 
762           return period_timeout * num_of_clock_stretches;
763 }
764 
765 /*
766  * @brief
767  * DC_I2C_DDC1_SETUP MM register offsets
768  *
769  * @note
770  * The indices of this offset array are DDC engine IDs
771  */
772 static const int32_t ddc_setup_offset[] = {
773 
774           mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
775           mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
776           mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
777           mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
778           mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
779           mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
780           mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
781 };
782 
783 /*
784  * @brief
785  * DC_I2C_DDC1_SPEED MM register offsets
786  *
787  * @note
788  * The indices of this offset array are DDC engine IDs
789  */
790 static const int32_t ddc_speed_offset[] = {
791           mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
792           mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
793           mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
794           mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
795           mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
796           mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
797           mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
798 };
799 
800 static const struct i2c_engine_funcs i2c_engine_funcs = {
801           .destroy = destroy,
802           .get_speed = get_speed,
803           .set_speed = set_speed,
804           .setup_engine = setup_engine,
805           .submit_channel_request = submit_channel_request,
806           .process_channel_reply = process_channel_reply,
807           .get_channel_status = get_channel_status,
808           .acquire_engine = dal_i2c_hw_engine_acquire_engine,
809 };
810 
811 static const struct engine_funcs engine_funcs = {
812           .release_engine = release_engine,
813           .get_engine_type = dal_i2c_hw_engine_get_engine_type,
814           .acquire = dal_i2c_engine_acquire,
815           .submit_request = dal_i2c_hw_engine_submit_request,
816 };
817 
818 static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
819           .get_hw_buffer_available_size =
820                     get_hw_buffer_available_size,
821           .get_transaction_timeout =
822                     get_transaction_timeout,
823           .wait_on_operation_result =
824                     dal_i2c_hw_engine_wait_on_operation_result,
825 };
826 
construct(struct i2c_hw_engine_dce80 * engine,const struct i2c_hw_engine_dce80_create_arg * arg)827 static void construct(
828           struct i2c_hw_engine_dce80 *engine,
829           const struct i2c_hw_engine_dce80_create_arg *arg)
830 {
831           dal_i2c_hw_engine_construct(&engine->base, arg->ctx);
832 
833           engine->base.base.base.funcs = &engine_funcs;
834           engine->base.base.funcs = &i2c_engine_funcs;
835           engine->base.funcs = &i2c_hw_engine_funcs;
836           engine->base.default_speed = arg->default_speed;
837           engine->addr.DC_I2C_DDCX_SETUP =
838                     mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
839           engine->addr.DC_I2C_DDCX_SPEED =
840                     mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
841 
842           engine->engine_id = arg->engine_id;
843           engine->reference_frequency = arg->reference_frequency;
844           engine->buffer_used_bytes = 0;
845           engine->transaction_count = 0;
846           engine->engine_keep_power_up_count = 1;
847 }
848 
dal_i2c_hw_engine_dce80_create(const struct i2c_hw_engine_dce80_create_arg * arg)849 struct i2c_engine *dal_i2c_hw_engine_dce80_create(
850           const struct i2c_hw_engine_dce80_create_arg *arg)
851 {
852           struct i2c_hw_engine_dce80 *engine;
853 
854           if (!arg) {
855                     BREAK_TO_DEBUGGER();
856                     return NULL;
857           }
858 
859           if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) ||
860               (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) ||
861               !arg->reference_frequency) {
862                     BREAK_TO_DEBUGGER();
863                     return NULL;
864           }
865 
866           engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL);
867 
868           if (!engine) {
869                     BREAK_TO_DEBUGGER();
870                     return NULL;
871           }
872 
873           construct(engine, arg);
874           return &engine->base.base;
875 }
876