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 
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 
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 
180 static void destruct(
181 	struct i2c_hw_engine_dce80 *engine)
182 {
183 	dal_i2c_hw_engine_destruct(&engine->base);
184 }
185 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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