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