]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/gpu/drm/amd/display/dc/i2caux/dce110/i2c_hw_engine_dce110.c
drm/amd/display: define DC_LOGGER for logger
[linux.git] / drivers / gpu / drm / amd / display / dc / i2caux / dce110 / i2c_hw_engine_dce110.c
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 #include "include/logger_interface.h"
28 /*
29  * Pre-requisites: headers required by header of this unit
30  */
31
32 #include "include/i2caux_interface.h"
33 #include "../engine.h"
34 #include "../i2c_engine.h"
35 #include "../i2c_hw_engine.h"
36 #include "../i2c_generic_hw_engine.h"
37 /*
38  * Header of this unit
39  */
40
41 #include "i2c_hw_engine_dce110.h"
42
43 /*
44  * Post-requisites: headers required by this unit
45  */
46 #include "reg_helper.h"
47
48 /*
49  * This unit
50  */
51 #define DC_LOGGER \
52                 hw_engine->base.base.base.ctx->logger
53
54 enum dc_i2c_status {
55         DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
56         DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
57         DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
58 };
59
60 enum dc_i2c_arbitration {
61         DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
62         DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
63 };
64
65 enum {
66         /* No timeout in HW
67          * (timeout implemented in SW by querying status) */
68         I2C_SETUP_TIME_LIMIT = 255,
69         I2C_HW_BUFFER_SIZE = 538
70 };
71
72 /*
73  * @brief
74  * Cast pointer to 'struct i2c_hw_engine *'
75  * to pointer 'struct i2c_hw_engine_dce110 *'
76  */
77 #define FROM_I2C_HW_ENGINE(ptr) \
78         container_of((ptr), struct i2c_hw_engine_dce110, base)
79 /*
80  * @brief
81  * Cast pointer to 'struct i2c_engine *'
82  * to pointer to 'struct i2c_hw_engine_dce110 *'
83  */
84 #define FROM_I2C_ENGINE(ptr) \
85         FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
86
87 /*
88  * @brief
89  * Cast pointer to 'struct engine *'
90  * to 'pointer to struct i2c_hw_engine_dce110 *'
91  */
92 #define FROM_ENGINE(ptr) \
93         FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
94
95 #define CTX \
96                 hw_engine->base.base.base.ctx
97
98 #define REG(reg_name)\
99         (hw_engine->regs->reg_name)
100
101 #undef FN
102 #define FN(reg_name, field_name) \
103         hw_engine->i2c_shift->field_name, hw_engine->i2c_mask->field_name
104
105 #include "reg_helper.h"
106
107 static void disable_i2c_hw_engine(
108         struct i2c_hw_engine_dce110 *hw_engine)
109 {
110         REG_UPDATE_N(SETUP, 1, FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 0);
111 }
112
113 static void release_engine(
114         struct engine *engine)
115 {
116         struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
117
118         struct i2c_engine *base = NULL;
119         bool safe_to_reset;
120
121         base = &hw_engine->base.base;
122
123         /* Restore original HW engine speed */
124
125         base->funcs->set_speed(base, hw_engine->base.original_speed);
126
127         /* Release I2C */
128         REG_UPDATE(DC_I2C_ARBITRATION, DC_I2C_SW_DONE_USING_I2C_REG, 1);
129
130         /* Reset HW engine */
131         {
132                 uint32_t i2c_sw_status = 0;
133                 REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
134                 /* if used by SW, safe to reset */
135                 safe_to_reset = (i2c_sw_status == 1);
136         }
137
138         if (safe_to_reset)
139                 REG_UPDATE_2(
140                         DC_I2C_CONTROL,
141                         DC_I2C_SOFT_RESET, 1,
142                         DC_I2C_SW_STATUS_RESET, 1);
143         else
144                 REG_UPDATE(DC_I2C_CONTROL, DC_I2C_SW_STATUS_RESET, 1);
145
146         /* HW I2c engine - clock gating feature */
147         if (!hw_engine->engine_keep_power_up_count)
148                 disable_i2c_hw_engine(hw_engine);
149 }
150
151 static bool setup_engine(
152         struct i2c_engine *i2c_engine)
153 {
154         struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
155
156         /* Program pin select */
157         REG_UPDATE_6(
158                         DC_I2C_CONTROL,
159                         DC_I2C_GO, 0,
160                         DC_I2C_SOFT_RESET, 0,
161                         DC_I2C_SEND_RESET, 0,
162                         DC_I2C_SW_STATUS_RESET, 1,
163                         DC_I2C_TRANSACTION_COUNT, 0,
164                         DC_I2C_DDC_SELECT, hw_engine->engine_id);
165
166         /* Program time limit */
167         REG_UPDATE_N(
168                         SETUP, 2,
169                         FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_TIME_LIMIT), I2C_SETUP_TIME_LIMIT,
170                         FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE), 1);
171
172         /* Program HW priority
173          * set to High - interrupt software I2C at any time
174          * Enable restart of SW I2C that was interrupted by HW
175          * disable queuing of software while I2C is in use by HW */
176         REG_UPDATE_2(
177                         DC_I2C_ARBITRATION,
178                         DC_I2C_NO_QUEUED_SW_GO, 0,
179                         DC_I2C_SW_PRIORITY, DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL);
180
181         return true;
182 }
183
184 static uint32_t get_speed(
185         const struct i2c_engine *i2c_engine)
186 {
187         const struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
188         uint32_t pre_scale = 0;
189
190         REG_GET(SPEED, DC_I2C_DDC1_PRESCALE, &pre_scale);
191
192         /* [anaumov] it seems following is unnecessary */
193         /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
194         return pre_scale ?
195                 hw_engine->reference_frequency / pre_scale :
196                 hw_engine->base.default_speed;
197 }
198
199 static void set_speed(
200         struct i2c_engine *i2c_engine,
201         uint32_t speed)
202 {
203         struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
204
205         if (speed) {
206                 if (hw_engine->i2c_mask->DC_I2C_DDC1_START_STOP_TIMING_CNTL)
207                         REG_UPDATE_N(
208                                 SPEED, 3,
209                                 FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
210                                 FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2,
211                                 FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_START_STOP_TIMING_CNTL), speed > 50 ? 2:1);
212                 else
213                         REG_UPDATE_N(
214                                 SPEED, 2,
215                                 FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_PRESCALE), hw_engine->reference_frequency / speed,
216                                 FN(DC_I2C_DDC1_SPEED, DC_I2C_DDC1_THRESHOLD), 2);
217         }
218 }
219
220 static inline void reset_hw_engine(struct engine *engine)
221 {
222         struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
223
224         REG_UPDATE_2(
225                         DC_I2C_CONTROL,
226                         DC_I2C_SW_STATUS_RESET, 1,
227                         DC_I2C_SW_STATUS_RESET, 1);
228 }
229
230 static bool is_hw_busy(struct engine *engine)
231 {
232         struct i2c_hw_engine_dce110 *hw_engine = FROM_ENGINE(engine);
233         uint32_t i2c_sw_status = 0;
234
235         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
236         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
237                 return false;
238
239         reset_hw_engine(engine);
240
241         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
242         return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
243 }
244
245
246 #define STOP_TRANS_PREDICAT \
247                 ((hw_engine->transaction_count == 3) || \
248                                 (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||     \
249                                 (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ))
250
251 #define SET_I2C_TRANSACTION(id) \
252                 do {    \
253                         REG_UPDATE_N(DC_I2C_TRANSACTION##id, 5, \
254                                 FN(DC_I2C_TRANSACTION0, DC_I2C_STOP_ON_NACK0), 1,       \
255                                 FN(DC_I2C_TRANSACTION0, DC_I2C_START0), 1,      \
256                                 FN(DC_I2C_TRANSACTION0, DC_I2C_STOP0), STOP_TRANS_PREDICAT ? 1:0,       \
257                                 FN(DC_I2C_TRANSACTION0, DC_I2C_RW0), (0 != (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)),     \
258                                 FN(DC_I2C_TRANSACTION0, DC_I2C_COUNT0), length);        \
259                                 if (STOP_TRANS_PREDICAT)        \
260                                         last_transaction = true;        \
261                 } while (false)
262
263
264 static bool process_transaction(
265         struct i2c_hw_engine_dce110 *hw_engine,
266         struct i2c_request_transaction_data *request)
267 {
268         uint32_t length = request->length;
269         uint8_t *buffer = request->data;
270         uint32_t value = 0;
271
272         bool last_transaction = false;
273
274         struct dc_context *ctx = NULL;
275
276         ctx = hw_engine->base.base.base.ctx;
277
278
279
280         switch (hw_engine->transaction_count) {
281         case 0:
282                 SET_I2C_TRANSACTION(0);
283                 break;
284         case 1:
285                 SET_I2C_TRANSACTION(1);
286                 break;
287         case 2:
288                 SET_I2C_TRANSACTION(2);
289                 break;
290         case 3:
291                 SET_I2C_TRANSACTION(3);
292                 break;
293         default:
294                 /* TODO Warning ? */
295                 break;
296         }
297
298
299         /* Write the I2C address and I2C data
300          * into the hardware circular buffer, one byte per entry.
301          * As an example, the 7-bit I2C slave address for CRT monitor
302          * for reading DDC/EDID information is 0b1010001.
303          * For an I2C send operation, the LSB must be programmed to 0;
304          * for I2C receive operation, the LSB must be programmed to 1. */
305         if (hw_engine->transaction_count == 0) {
306                 value = REG_SET_4(DC_I2C_DATA, 0,
307                                   DC_I2C_DATA_RW, false,
308                                   DC_I2C_DATA, request->address,
309                                   DC_I2C_INDEX, 0,
310                                   DC_I2C_INDEX_WRITE, 1);
311                 hw_engine->buffer_used_write = 0;
312         } else
313                 value = REG_SET_2(DC_I2C_DATA, 0,
314                                   DC_I2C_DATA_RW, false,
315                                   DC_I2C_DATA, request->address);
316
317         hw_engine->buffer_used_write++;
318
319         if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
320                 while (length) {
321                         REG_SET_2(DC_I2C_DATA, value,
322                                         DC_I2C_INDEX_WRITE, 0,
323                                         DC_I2C_DATA, *buffer++);
324                         hw_engine->buffer_used_write++;
325                         --length;
326                 }
327         }
328
329         ++hw_engine->transaction_count;
330         hw_engine->buffer_used_bytes += length + 1;
331
332         return last_transaction;
333 }
334
335 static void execute_transaction(
336         struct i2c_hw_engine_dce110 *hw_engine)
337 {
338         REG_UPDATE_N(SETUP, 5,
339                 FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_EN), 0,
340                 FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_CLK_DRIVE_EN), 0,
341                 FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_DATA_DRIVE_SEL), 0,
342                 FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_TRANSACTION_DELAY), 0,
343                 FN(DC_I2C_DDC1_SETUP, DC_I2C_DDC1_INTRA_BYTE_DELAY), 0);
344
345
346         REG_UPDATE_5(DC_I2C_CONTROL,
347                 DC_I2C_SOFT_RESET, 0,
348                 DC_I2C_SW_STATUS_RESET, 0,
349                 DC_I2C_SEND_RESET, 0,
350                 DC_I2C_GO, 0,
351                 DC_I2C_TRANSACTION_COUNT, hw_engine->transaction_count - 1);
352
353         /* start I2C transfer */
354         REG_UPDATE(DC_I2C_CONTROL, DC_I2C_GO, 1);
355
356         /* all transactions were executed and HW buffer became empty
357          * (even though it actually happens when status becomes DONE) */
358         hw_engine->transaction_count = 0;
359         hw_engine->buffer_used_bytes = 0;
360 }
361
362 static void submit_channel_request(
363         struct i2c_engine *engine,
364         struct i2c_request_transaction_data *request)
365 {
366         request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
367
368         if (!process_transaction(FROM_I2C_ENGINE(engine), request))
369                 return;
370
371         if (is_hw_busy(&engine->base)) {
372                 request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
373                 return;
374         }
375
376         execute_transaction(FROM_I2C_ENGINE(engine));
377 }
378
379 static void process_channel_reply(
380         struct i2c_engine *engine,
381         struct i2c_reply_transaction_data *reply)
382 {
383         uint32_t length = reply->length;
384         uint8_t *buffer = reply->data;
385
386         struct i2c_hw_engine_dce110 *hw_engine =
387                 FROM_I2C_ENGINE(engine);
388
389
390         REG_SET_3(DC_I2C_DATA, 0,
391                         DC_I2C_INDEX, hw_engine->buffer_used_write,
392                         DC_I2C_DATA_RW, 1,
393                         DC_I2C_INDEX_WRITE, 1);
394
395         while (length) {
396                 /* after reading the status,
397                  * if the I2C operation executed successfully
398                  * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
399                  * should read data bytes from I2C circular data buffer */
400
401                 uint32_t i2c_data;
402
403                 REG_GET(DC_I2C_DATA, DC_I2C_DATA, &i2c_data);
404                 *buffer++ = i2c_data;
405
406                 --length;
407         }
408 }
409
410 static enum i2c_channel_operation_result get_channel_status(
411         struct i2c_engine *i2c_engine,
412         uint8_t *returned_bytes)
413 {
414         uint32_t i2c_sw_status = 0;
415         struct i2c_hw_engine_dce110 *hw_engine = FROM_I2C_ENGINE(i2c_engine);
416         uint32_t value =
417                         REG_GET(DC_I2C_SW_STATUS, DC_I2C_SW_STATUS, &i2c_sw_status);
418
419         if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
420                 return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
421         else if (value & hw_engine->i2c_mask->DC_I2C_SW_STOPPED_ON_NACK)
422                 return I2C_CHANNEL_OPERATION_NO_RESPONSE;
423         else if (value & hw_engine->i2c_mask->DC_I2C_SW_TIMEOUT)
424                 return I2C_CHANNEL_OPERATION_TIMEOUT;
425         else if (value & hw_engine->i2c_mask->DC_I2C_SW_ABORTED)
426                 return I2C_CHANNEL_OPERATION_FAILED;
427         else if (value & hw_engine->i2c_mask->DC_I2C_SW_DONE)
428                 return I2C_CHANNEL_OPERATION_SUCCEEDED;
429
430         /*
431          * this is the case when HW used for communication, I2C_SW_STATUS
432          * could be zero
433          */
434         return I2C_CHANNEL_OPERATION_SUCCEEDED;
435 }
436
437 static uint32_t get_hw_buffer_available_size(
438         const struct i2c_hw_engine *engine)
439 {
440         return I2C_HW_BUFFER_SIZE -
441                 FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
442 }
443
444 static uint32_t get_transaction_timeout(
445         const struct i2c_hw_engine *engine,
446         uint32_t length)
447 {
448         uint32_t speed = engine->base.funcs->get_speed(&engine->base);
449
450         uint32_t period_timeout;
451         uint32_t num_of_clock_stretches;
452
453         if (!speed)
454                 return 0;
455
456         period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
457
458         num_of_clock_stretches = 1 + (length << 3) + 1;
459         num_of_clock_stretches +=
460                 (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
461                 (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
462
463         return period_timeout * num_of_clock_stretches;
464 }
465
466 static void destroy(
467         struct i2c_engine **i2c_engine)
468 {
469         struct i2c_hw_engine_dce110 *engine_dce110 =
470                         FROM_I2C_ENGINE(*i2c_engine);
471
472         dal_i2c_hw_engine_destruct(&engine_dce110->base);
473
474         kfree(engine_dce110);
475
476         *i2c_engine = NULL;
477 }
478
479 static const struct i2c_engine_funcs i2c_engine_funcs = {
480         .destroy = destroy,
481         .get_speed = get_speed,
482         .set_speed = set_speed,
483         .setup_engine = setup_engine,
484         .submit_channel_request = submit_channel_request,
485         .process_channel_reply = process_channel_reply,
486         .get_channel_status = get_channel_status,
487         .acquire_engine = dal_i2c_hw_engine_acquire_engine,
488 };
489
490 static const struct engine_funcs engine_funcs = {
491         .release_engine = release_engine,
492         .get_engine_type = dal_i2c_hw_engine_get_engine_type,
493         .acquire = dal_i2c_engine_acquire,
494         .submit_request = dal_i2c_hw_engine_submit_request,
495 };
496
497 static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
498         .get_hw_buffer_available_size = get_hw_buffer_available_size,
499         .get_transaction_timeout = get_transaction_timeout,
500         .wait_on_operation_result = dal_i2c_hw_engine_wait_on_operation_result,
501 };
502
503 static void construct(
504         struct i2c_hw_engine_dce110 *hw_engine,
505         const struct i2c_hw_engine_dce110_create_arg *arg)
506 {
507         uint32_t xtal_ref_div = 0;
508
509         dal_i2c_hw_engine_construct(&hw_engine->base, arg->ctx);
510
511         hw_engine->base.base.base.funcs = &engine_funcs;
512         hw_engine->base.base.funcs = &i2c_engine_funcs;
513         hw_engine->base.funcs = &i2c_hw_engine_funcs;
514         hw_engine->base.default_speed = arg->default_speed;
515
516         hw_engine->regs = arg->regs;
517         hw_engine->i2c_shift = arg->i2c_shift;
518         hw_engine->i2c_mask = arg->i2c_mask;
519
520         hw_engine->engine_id = arg->engine_id;
521
522         hw_engine->buffer_used_bytes = 0;
523         hw_engine->transaction_count = 0;
524         hw_engine->engine_keep_power_up_count = 1;
525
526
527         REG_GET(MICROSECOND_TIME_BASE_DIV, XTAL_REF_DIV, &xtal_ref_div);
528
529         if (xtal_ref_div == 0) {
530                 DC_LOG_WARNING("Invalid base timer divider\n",
531                                 __func__);
532                 xtal_ref_div = 2;
533         }
534
535         /*Calculating Reference Clock by divding original frequency by
536          * XTAL_REF_DIV.
537          * At upper level, uint32_t reference_frequency =
538          *  dal_i2caux_get_reference_clock(as) >> 1
539          *  which already divided by 2. So we need x2 to get original
540          *  reference clock from ppll_info
541          */
542         hw_engine->reference_frequency =
543                 (arg->reference_frequency * 2) / xtal_ref_div;
544 }
545
546 struct i2c_engine *dal_i2c_hw_engine_dce110_create(
547         const struct i2c_hw_engine_dce110_create_arg *arg)
548 {
549         struct i2c_hw_engine_dce110 *engine_dce10;
550
551         if (!arg) {
552                 ASSERT_CRITICAL(false);
553                 return NULL;
554         }
555         if (!arg->reference_frequency) {
556                 ASSERT_CRITICAL(false);
557                 return NULL;
558         }
559
560         engine_dce10 = kzalloc(sizeof(struct i2c_hw_engine_dce110),
561                                GFP_KERNEL);
562
563         if (!engine_dce10) {
564                 ASSERT_CRITICAL(false);
565                 return NULL;
566         }
567
568         construct(engine_dce10, arg);
569         return &engine_dce10->base.base;
570 }