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