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 /*
27 * Pre-requisites: headers required by header of this unit
28 */
29
30 #include "dm_services.h"
31 #include "include/gpio_interface.h"
32 #include "include/gpio_service_interface.h"
33 #include "hw_translate.h"
34 #include "hw_factory.h"
35
36 /*
37 * Header of this unit
38 */
39
40 #include "gpio_service.h"
41
42 /*
43 * Post-requisites: headers required by this unit
44 */
45
46 #include "hw_gpio.h"
47
48 /*
49 * @brief
50 * Public API.
51 */
52
dal_gpio_service_create(enum dce_version dce_version_major,enum dce_version dce_version_minor,struct dc_context * ctx)53 struct gpio_service *dal_gpio_service_create(
54 enum dce_version dce_version_major,
55 enum dce_version dce_version_minor,
56 struct dc_context *ctx)
57 {
58 struct gpio_service *service;
59
60 uint32_t index_of_id;
61
62 service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
63
64 if (!service) {
65 BREAK_TO_DEBUGGER();
66 return NULL;
67 }
68
69 if (!dal_hw_translate_init(&service->translate, dce_version_major,
70 dce_version_minor)) {
71 BREAK_TO_DEBUGGER();
72 goto failure_1;
73 }
74
75 if (!dal_hw_factory_init(&service->factory, dce_version_major,
76 dce_version_minor)) {
77 BREAK_TO_DEBUGGER();
78 goto failure_1;
79 }
80
81 /* allocate and initialize business storage */
82 {
83 const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
84
85 index_of_id = 0;
86 service->ctx = ctx;
87
88 do {
89 uint32_t number_of_bits =
90 service->factory.number_of_pins[index_of_id];
91
92 uint32_t number_of_uints =
93 (number_of_bits + bits_per_uint - 1) /
94 bits_per_uint;
95
96 uint32_t *slot;
97
98 if (number_of_bits) {
99 uint32_t index_of_uint = 0;
100
101 slot = kcalloc(number_of_uints,
102 sizeof(uint32_t),
103 GFP_KERNEL);
104
105 if (!slot) {
106 BREAK_TO_DEBUGGER();
107 goto failure_2;
108 }
109
110 do {
111 slot[index_of_uint] = 0;
112
113 ++index_of_uint;
114 } while (index_of_uint < number_of_uints);
115 } else
116 slot = NULL;
117
118 service->busyness[index_of_id] = slot;
119
120 ++index_of_id;
121 } while (index_of_id < GPIO_ID_COUNT);
122 }
123
124 return service;
125
126 failure_2:
127 while (index_of_id) {
128 uint32_t *slot;
129
130 --index_of_id;
131
132 slot = service->busyness[index_of_id];
133
134 kfree(slot);
135 }
136
137 failure_1:
138 kfree(service);
139
140 return NULL;
141 }
142
dal_gpio_service_create_irq(struct gpio_service * service,uint32_t offset,uint32_t mask)143 struct gpio *dal_gpio_service_create_irq(
144 struct gpio_service *service,
145 uint32_t offset,
146 uint32_t mask)
147 {
148 enum gpio_id id;
149 uint32_t en;
150
151 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
152 ASSERT_CRITICAL(false);
153 return NULL;
154 }
155
156 return dal_gpio_create_irq(service, id, en);
157 }
158
dal_gpio_service_destroy(struct gpio_service ** ptr)159 void dal_gpio_service_destroy(
160 struct gpio_service **ptr)
161 {
162 if (!ptr || !*ptr) {
163 BREAK_TO_DEBUGGER();
164 return;
165 }
166
167 /* free business storage */
168 {
169 uint32_t index_of_id = 0;
170
171 do {
172 uint32_t *slot = (*ptr)->busyness[index_of_id];
173
174 kfree(slot);
175
176 ++index_of_id;
177 } while (index_of_id < GPIO_ID_COUNT);
178 }
179
180 kfree(*ptr);
181
182 *ptr = NULL;
183 }
184
185 /*
186 * @brief
187 * Private API.
188 */
189
is_pin_busy(const struct gpio_service * service,enum gpio_id id,uint32_t en)190 static bool is_pin_busy(
191 const struct gpio_service *service,
192 enum gpio_id id,
193 uint32_t en)
194 {
195 const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
196
197 const uint32_t *slot = service->busyness[id] + (en / bits_per_uint);
198
199 return 0 != (*slot & (1 << (en % bits_per_uint)));
200 }
201
set_pin_busy(struct gpio_service * service,enum gpio_id id,uint32_t en)202 static void set_pin_busy(
203 struct gpio_service *service,
204 enum gpio_id id,
205 uint32_t en)
206 {
207 const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
208
209 service->busyness[id][en / bits_per_uint] |=
210 (1 << (en % bits_per_uint));
211 }
212
set_pin_free(struct gpio_service * service,enum gpio_id id,uint32_t en)213 static void set_pin_free(
214 struct gpio_service *service,
215 enum gpio_id id,
216 uint32_t en)
217 {
218 const uint32_t bits_per_uint = sizeof(uint32_t) << 3;
219
220 service->busyness[id][en / bits_per_uint] &=
221 ~(1 << (en % bits_per_uint));
222 }
223
dal_gpio_service_open(struct gpio_service * service,enum gpio_id id,uint32_t en,enum gpio_mode mode,struct hw_gpio_pin ** ptr)224 enum gpio_result dal_gpio_service_open(
225 struct gpio_service *service,
226 enum gpio_id id,
227 uint32_t en,
228 enum gpio_mode mode,
229 struct hw_gpio_pin **ptr)
230 {
231 struct hw_gpio_pin *pin;
232
233 if (!service->busyness[id]) {
234 ASSERT_CRITICAL(false);
235 return GPIO_RESULT_OPEN_FAILED;
236 }
237
238 if (is_pin_busy(service, id, en)) {
239 ASSERT_CRITICAL(false);
240 return GPIO_RESULT_DEVICE_BUSY;
241 }
242
243 switch (id) {
244 case GPIO_ID_DDC_DATA:
245 pin = service->factory.funcs->create_ddc_data(
246 service->ctx, id, en);
247 service->factory.funcs->define_ddc_registers(pin, en);
248 break;
249 case GPIO_ID_DDC_CLOCK:
250 pin = service->factory.funcs->create_ddc_clock(
251 service->ctx, id, en);
252 service->factory.funcs->define_ddc_registers(pin, en);
253 break;
254 case GPIO_ID_GENERIC:
255 pin = service->factory.funcs->create_generic(
256 service->ctx, id, en);
257 break;
258 case GPIO_ID_HPD:
259 pin = service->factory.funcs->create_hpd(
260 service->ctx, id, en);
261 service->factory.funcs->define_hpd_registers(pin, en);
262 break;
263 case GPIO_ID_SYNC:
264 pin = service->factory.funcs->create_sync(
265 service->ctx, id, en);
266 break;
267 case GPIO_ID_GSL:
268 pin = service->factory.funcs->create_gsl(
269 service->ctx, id, en);
270 break;
271 default:
272 ASSERT_CRITICAL(false);
273 return GPIO_RESULT_NON_SPECIFIC_ERROR;
274 }
275
276 if (!pin) {
277 ASSERT_CRITICAL(false);
278 return GPIO_RESULT_NON_SPECIFIC_ERROR;
279 }
280
281 if (!pin->funcs->open(pin, mode)) {
282 ASSERT_CRITICAL(false);
283 dal_gpio_service_close(service, &pin);
284 return GPIO_RESULT_OPEN_FAILED;
285 }
286
287 set_pin_busy(service, id, en);
288 *ptr = pin;
289 return GPIO_RESULT_OK;
290 }
291
dal_gpio_service_close(struct gpio_service * service,struct hw_gpio_pin ** ptr)292 void dal_gpio_service_close(
293 struct gpio_service *service,
294 struct hw_gpio_pin **ptr)
295 {
296 struct hw_gpio_pin *pin;
297
298 if (!ptr) {
299 ASSERT_CRITICAL(false);
300 return;
301 }
302
303 pin = *ptr;
304
305 if (pin) {
306 set_pin_free(service, pin->id, pin->en);
307
308 pin->funcs->close(pin);
309
310 pin->funcs->destroy(ptr);
311 }
312 }
313
314
dal_irq_get_source(const struct gpio * irq)315 enum dc_irq_source dal_irq_get_source(
316 const struct gpio *irq)
317 {
318 enum gpio_id id = dal_gpio_get_id(irq);
319
320 switch (id) {
321 case GPIO_ID_HPD:
322 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
323 dal_gpio_get_enum(irq));
324 case GPIO_ID_GPIO_PAD:
325 return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
326 dal_gpio_get_enum(irq));
327 default:
328 return DC_IRQ_SOURCE_INVALID;
329 }
330 }
331
dal_irq_get_rx_source(const struct gpio * irq)332 enum dc_irq_source dal_irq_get_rx_source(
333 const struct gpio *irq)
334 {
335 enum gpio_id id = dal_gpio_get_id(irq);
336
337 switch (id) {
338 case GPIO_ID_HPD:
339 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
340 dal_gpio_get_enum(irq));
341 default:
342 return DC_IRQ_SOURCE_INVALID;
343 }
344 }
345
dal_irq_setup_hpd_filter(struct gpio * irq,struct gpio_hpd_config * config)346 enum gpio_result dal_irq_setup_hpd_filter(
347 struct gpio *irq,
348 struct gpio_hpd_config *config)
349 {
350 struct gpio_config_data config_data;
351
352 if (!config)
353 return GPIO_RESULT_INVALID_DATA;
354
355 config_data.type = GPIO_CONFIG_TYPE_HPD;
356 config_data.config.hpd = *config;
357
358 return dal_gpio_set_config(irq, &config_data);
359 }
360
361 /*
362 * @brief
363 * Creation and destruction
364 */
365
dal_gpio_create_irq(struct gpio_service * service,enum gpio_id id,uint32_t en)366 struct gpio *dal_gpio_create_irq(
367 struct gpio_service *service,
368 enum gpio_id id,
369 uint32_t en)
370 {
371 struct gpio *irq;
372
373 switch (id) {
374 case GPIO_ID_HPD:
375 case GPIO_ID_GPIO_PAD:
376 break;
377 default:
378 id = GPIO_ID_HPD;
379 ASSERT_CRITICAL(false);
380 return NULL;
381 }
382
383 irq = dal_gpio_create(
384 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
385
386 if (irq)
387 return irq;
388
389 ASSERT_CRITICAL(false);
390 return NULL;
391 }
392
dal_gpio_destroy_irq(struct gpio ** irq)393 void dal_gpio_destroy_irq(
394 struct gpio **irq)
395 {
396 if (!irq || !*irq) {
397 ASSERT_CRITICAL(false);
398 return;
399 }
400
401 dal_gpio_close(*irq);
402 dal_gpio_destroy(irq);
403 kfree(*irq);
404
405 *irq = NULL;
406 }
407
dal_gpio_create_ddc(struct gpio_service * service,uint32_t offset,uint32_t mask,struct gpio_ddc_hw_info * info)408 struct ddc *dal_gpio_create_ddc(
409 struct gpio_service *service,
410 uint32_t offset,
411 uint32_t mask,
412 struct gpio_ddc_hw_info *info)
413 {
414 enum gpio_id id;
415 uint32_t en;
416 struct ddc *ddc;
417
418 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
419 return NULL;
420
421 ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
422
423 if (!ddc) {
424 BREAK_TO_DEBUGGER();
425 return NULL;
426 }
427
428 ddc->pin_data = dal_gpio_create(
429 service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
430
431 if (!ddc->pin_data) {
432 BREAK_TO_DEBUGGER();
433 goto failure_1;
434 }
435
436 ddc->pin_clock = dal_gpio_create(
437 service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
438
439 if (!ddc->pin_clock) {
440 BREAK_TO_DEBUGGER();
441 goto failure_2;
442 }
443
444 ddc->hw_info = *info;
445
446 ddc->ctx = service->ctx;
447
448 return ddc;
449
450 failure_2:
451 dal_gpio_destroy(&ddc->pin_data);
452
453 failure_1:
454 kfree(ddc);
455
456 return NULL;
457 }
458
dal_gpio_destroy_ddc(struct ddc ** ddc)459 void dal_gpio_destroy_ddc(
460 struct ddc **ddc)
461 {
462 if (!ddc || !*ddc) {
463 BREAK_TO_DEBUGGER();
464 return;
465 }
466
467 dal_ddc_close(*ddc);
468 dal_gpio_destroy(&(*ddc)->pin_data);
469 dal_gpio_destroy(&(*ddc)->pin_clock);
470 kfree(*ddc);
471
472 *ddc = NULL;
473 }
474
dal_ddc_open(struct ddc * ddc,enum gpio_mode mode,enum gpio_ddc_config_type config_type)475 enum gpio_result dal_ddc_open(
476 struct ddc *ddc,
477 enum gpio_mode mode,
478 enum gpio_ddc_config_type config_type)
479 {
480 enum gpio_result result;
481
482 struct gpio_config_data config_data;
483 struct hw_gpio *hw_data;
484 struct hw_gpio *hw_clock;
485
486 result = dal_gpio_open_ex(ddc->pin_data, mode);
487
488 if (result != GPIO_RESULT_OK) {
489 BREAK_TO_DEBUGGER();
490 return result;
491 }
492
493 result = dal_gpio_open_ex(ddc->pin_clock, mode);
494
495 if (result != GPIO_RESULT_OK) {
496 BREAK_TO_DEBUGGER();
497 goto failure;
498 }
499
500 /* DDC clock and data pins should belong
501 * to the same DDC block id,
502 * we use the data pin to set the pad mode. */
503
504 if (mode == GPIO_MODE_INPUT)
505 /* this is from detect_sink_type,
506 * we need extra delay there */
507 config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
508 else
509 config_data.type = GPIO_CONFIG_TYPE_DDC;
510
511 config_data.config.ddc.type = config_type;
512
513 hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
514 hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
515
516 config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
517 config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
518
519 result = dal_gpio_set_config(ddc->pin_data, &config_data);
520
521 if (result == GPIO_RESULT_OK)
522 return result;
523
524 BREAK_TO_DEBUGGER();
525
526 dal_gpio_close(ddc->pin_clock);
527
528 failure:
529 dal_gpio_close(ddc->pin_data);
530
531 return result;
532 }
533
dal_ddc_change_mode(struct ddc * ddc,enum gpio_mode mode)534 enum gpio_result dal_ddc_change_mode(
535 struct ddc *ddc,
536 enum gpio_mode mode)
537 {
538 enum gpio_result result;
539
540 enum gpio_mode original_mode =
541 dal_gpio_get_mode(ddc->pin_data);
542
543 result = dal_gpio_change_mode(ddc->pin_data, mode);
544
545 /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
546 * in case of failures;
547 * set_mode() is so that, in case of failure,
548 * we must explicitly set original mode */
549
550 if (result != GPIO_RESULT_OK)
551 goto failure;
552
553 result = dal_gpio_change_mode(ddc->pin_clock, mode);
554
555 if (result == GPIO_RESULT_OK)
556 return result;
557
558 dal_gpio_change_mode(ddc->pin_clock, original_mode);
559
560 failure:
561 dal_gpio_change_mode(ddc->pin_data, original_mode);
562
563 return result;
564 }
565
dal_ddc_get_line(const struct ddc * ddc)566 enum gpio_ddc_line dal_ddc_get_line(
567 const struct ddc *ddc)
568 {
569 return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
570 }
571
dal_ddc_set_config(struct ddc * ddc,enum gpio_ddc_config_type config_type)572 enum gpio_result dal_ddc_set_config(
573 struct ddc *ddc,
574 enum gpio_ddc_config_type config_type)
575 {
576 struct gpio_config_data config_data;
577
578 config_data.type = GPIO_CONFIG_TYPE_DDC;
579
580 config_data.config.ddc.type = config_type;
581 config_data.config.ddc.data_en_bit_present = false;
582 config_data.config.ddc.clock_en_bit_present = false;
583
584 return dal_gpio_set_config(ddc->pin_data, &config_data);
585 }
586
dal_ddc_close(struct ddc * ddc)587 void dal_ddc_close(
588 struct ddc *ddc)
589 {
590 dal_gpio_close(ddc->pin_clock);
591 dal_gpio_close(ddc->pin_data);
592 }
593
594