1 /* $NetBSD: amdgpu_gpio_service.c,v 1.3 2021/12/19 11:22:31 riastradh Exp $ */
2
3 /*
4 * Copyright 2012-15 Advanced Micro Devices, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors: AMD
25 *
26 */
27
28 /*
29 * Pre-requisites: headers required by header of this unit
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: amdgpu_gpio_service.c,v 1.3 2021/12/19 11:22:31 riastradh Exp $");
34
35 #include <linux/slab.h>
36
37 #include "dm_services.h"
38 #include "include/gpio_interface.h"
39 #include "include/gpio_service_interface.h"
40 #include "hw_translate.h"
41 #include "hw_factory.h"
42
43 /*
44 * Header of this unit
45 */
46
47 #include "gpio_service.h"
48
49 /*
50 * Post-requisites: headers required by this unit
51 */
52
53 #include "hw_gpio.h"
54
55 /*
56 * @brief
57 * Public API.
58 */
59
dal_gpio_service_create(enum dce_version dce_version_major,enum dce_environment dce_version_minor,struct dc_context * ctx)60 struct gpio_service *dal_gpio_service_create(
61 enum dce_version dce_version_major,
62 enum dce_environment dce_version_minor,
63 struct dc_context *ctx)
64 {
65 struct gpio_service *service;
66 uint32_t index_of_id;
67
68 service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
69
70 if (!service) {
71 BREAK_TO_DEBUGGER();
72 return NULL;
73 }
74
75 if (!dal_hw_translate_init(&service->translate, dce_version_major,
76 dce_version_minor)) {
77 BREAK_TO_DEBUGGER();
78 goto failure_1;
79 }
80
81 if (!dal_hw_factory_init(&service->factory, dce_version_major,
82 dce_version_minor)) {
83 BREAK_TO_DEBUGGER();
84 goto failure_1;
85 }
86
87 /* allocate and initialize busyness storage */
88 {
89 index_of_id = 0;
90 service->ctx = ctx;
91
92 do {
93 uint32_t number_of_bits =
94 service->factory.number_of_pins[index_of_id];
95 uint32_t i = 0;
96
97 if (number_of_bits) {
98 service->busyness[index_of_id] =
99 kcalloc(number_of_bits, sizeof(char),
100 GFP_KERNEL);
101
102 if (!service->busyness[index_of_id]) {
103 BREAK_TO_DEBUGGER();
104 goto failure_2;
105 }
106
107 do {
108 service->busyness[index_of_id][i] = 0;
109 ++i;
110 } while (i < number_of_bits);
111 } else {
112 service->busyness[index_of_id] = NULL;
113 }
114
115 ++index_of_id;
116 } while (index_of_id < GPIO_ID_COUNT);
117 }
118
119 return service;
120
121 failure_2:
122 while (index_of_id) {
123 --index_of_id;
124 kfree(service->busyness[index_of_id]);
125 }
126
127 failure_1:
128 kfree(service);
129
130 return NULL;
131 }
132
dal_gpio_service_create_irq(struct gpio_service * service,uint32_t offset,uint32_t mask)133 struct gpio *dal_gpio_service_create_irq(
134 struct gpio_service *service,
135 uint32_t offset,
136 uint32_t mask)
137 {
138 enum gpio_id id;
139 uint32_t en;
140
141 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
142 ASSERT_CRITICAL(false);
143 return NULL;
144 }
145
146 return dal_gpio_create_irq(service, id, en);
147 }
148
dal_gpio_service_create_generic_mux(struct gpio_service * service,uint32_t offset,uint32_t mask)149 struct gpio *dal_gpio_service_create_generic_mux(
150 struct gpio_service *service,
151 uint32_t offset,
152 uint32_t mask)
153 {
154 enum gpio_id id;
155 uint32_t en;
156 struct gpio *generic;
157
158 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
159 ASSERT_CRITICAL(false);
160 return NULL;
161 }
162
163 generic = dal_gpio_create(
164 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
165
166 return generic;
167 }
168
dal_gpio_destroy_generic_mux(struct gpio ** mux)169 void dal_gpio_destroy_generic_mux(
170 struct gpio **mux)
171 {
172 if (!mux || !*mux) {
173 ASSERT_CRITICAL(false);
174 return;
175 }
176
177 dal_gpio_destroy(mux);
178 kfree(*mux);
179
180 *mux = NULL;
181 }
182
dal_gpio_get_generic_pin_info(struct gpio_service * service,enum gpio_id id,uint32_t en)183 struct gpio_pin_info dal_gpio_get_generic_pin_info(
184 struct gpio_service *service,
185 enum gpio_id id,
186 uint32_t en)
187 {
188 struct gpio_pin_info pin;
189
190 if (service->translate.funcs->id_to_offset) {
191 service->translate.funcs->id_to_offset(id, en, &pin);
192 } else {
193 pin.mask = 0xFFFFFFFF;
194 pin.offset = 0xFFFFFFFF;
195 }
196
197 return pin;
198 }
199
dal_gpio_service_destroy(struct gpio_service ** ptr)200 void dal_gpio_service_destroy(
201 struct gpio_service **ptr)
202 {
203 if (!ptr || !*ptr) {
204 BREAK_TO_DEBUGGER();
205 return;
206 }
207
208 /* free business storage */
209 {
210 uint32_t index_of_id = 0;
211
212 do {
213 kfree((*ptr)->busyness[index_of_id]);
214
215 ++index_of_id;
216 } while (index_of_id < GPIO_ID_COUNT);
217 }
218
219 kfree(*ptr);
220
221 *ptr = NULL;
222 }
223
dal_mux_setup_config(struct gpio * mux,struct gpio_generic_mux_config * config)224 enum gpio_result dal_mux_setup_config(
225 struct gpio *mux,
226 struct gpio_generic_mux_config *config)
227 {
228 struct gpio_config_data config_data;
229
230 if (!config)
231 return GPIO_RESULT_INVALID_DATA;
232
233 config_data.config.generic_mux = *config;
234 config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX;
235
236 return dal_gpio_set_config(mux, &config_data);
237 }
238
239 /*
240 * @brief
241 * Private API.
242 */
243
is_pin_busy(const struct gpio_service * service,enum gpio_id id,uint32_t en)244 static bool is_pin_busy(
245 const struct gpio_service *service,
246 enum gpio_id id,
247 uint32_t en)
248 {
249 return service->busyness[id][en];
250 }
251
set_pin_busy(struct gpio_service * service,enum gpio_id id,uint32_t en)252 static void set_pin_busy(
253 struct gpio_service *service,
254 enum gpio_id id,
255 uint32_t en)
256 {
257 service->busyness[id][en] = true;
258 }
259
set_pin_free(struct gpio_service * service,enum gpio_id id,uint32_t en)260 static void set_pin_free(
261 struct gpio_service *service,
262 enum gpio_id id,
263 uint32_t en)
264 {
265 service->busyness[id][en] = false;
266 }
267
dal_gpio_service_lock(struct gpio_service * service,enum gpio_id id,uint32_t en)268 enum gpio_result dal_gpio_service_lock(
269 struct gpio_service *service,
270 enum gpio_id id,
271 uint32_t en)
272 {
273 if (!service->busyness[id]) {
274 ASSERT_CRITICAL(false);
275 return GPIO_RESULT_OPEN_FAILED;
276 }
277
278 set_pin_busy(service, id, en);
279 return GPIO_RESULT_OK;
280 }
281
dal_gpio_service_unlock(struct gpio_service * service,enum gpio_id id,uint32_t en)282 enum gpio_result dal_gpio_service_unlock(
283 struct gpio_service *service,
284 enum gpio_id id,
285 uint32_t en)
286 {
287 if (!service->busyness[id]) {
288 ASSERT_CRITICAL(false);
289 return GPIO_RESULT_OPEN_FAILED;
290 }
291
292 set_pin_free(service, id, en);
293 return GPIO_RESULT_OK;
294 }
295
dal_gpio_service_open(struct gpio * gpio)296 enum gpio_result dal_gpio_service_open(
297 struct gpio *gpio)
298 {
299 struct gpio_service *service = gpio->service;
300 enum gpio_id id = gpio->id;
301 uint32_t en = gpio->en;
302 enum gpio_mode mode = gpio->mode;
303
304 struct hw_gpio_pin **pin = &gpio->pin;
305
306
307 if (!service->busyness[id]) {
308 ASSERT_CRITICAL(false);
309 return GPIO_RESULT_OPEN_FAILED;
310 }
311
312 if (is_pin_busy(service, id, en)) {
313 ASSERT_CRITICAL(false);
314 return GPIO_RESULT_DEVICE_BUSY;
315 }
316
317 switch (id) {
318 case GPIO_ID_DDC_DATA:
319 *pin = service->factory.funcs->get_ddc_pin(gpio);
320 service->factory.funcs->define_ddc_registers(*pin, en);
321 break;
322 case GPIO_ID_DDC_CLOCK:
323 *pin = service->factory.funcs->get_ddc_pin(gpio);
324 service->factory.funcs->define_ddc_registers(*pin, en);
325 break;
326 case GPIO_ID_GENERIC:
327 *pin = service->factory.funcs->get_generic_pin(gpio);
328 service->factory.funcs->define_generic_registers(*pin, en);
329 break;
330 case GPIO_ID_HPD:
331 *pin = service->factory.funcs->get_hpd_pin(gpio);
332 service->factory.funcs->define_hpd_registers(*pin, en);
333 break;
334
335 //TODO: gsl and sync support? create_sync and create_gsl are NULL
336 case GPIO_ID_SYNC:
337 case GPIO_ID_GSL:
338 break;
339 default:
340 ASSERT_CRITICAL(false);
341 return GPIO_RESULT_NON_SPECIFIC_ERROR;
342 }
343
344 if (!*pin) {
345 ASSERT_CRITICAL(false);
346 return GPIO_RESULT_NON_SPECIFIC_ERROR;
347 }
348
349 if (!(*pin)->funcs->open(*pin, mode)) {
350 ASSERT_CRITICAL(false);
351 dal_gpio_service_close(service, pin);
352 return GPIO_RESULT_OPEN_FAILED;
353 }
354
355 set_pin_busy(service, id, en);
356 return GPIO_RESULT_OK;
357 }
358
dal_gpio_service_close(struct gpio_service * service,struct hw_gpio_pin ** ptr)359 void dal_gpio_service_close(
360 struct gpio_service *service,
361 struct hw_gpio_pin **ptr)
362 {
363 struct hw_gpio_pin *pin;
364
365 if (!ptr) {
366 ASSERT_CRITICAL(false);
367 return;
368 }
369
370 pin = *ptr;
371
372 if (pin) {
373 set_pin_free(service, pin->id, pin->en);
374
375 pin->funcs->close(pin);
376
377 *ptr = NULL;
378 }
379 }
380
dal_irq_get_source(const struct gpio * irq)381 enum dc_irq_source dal_irq_get_source(
382 const struct gpio *irq)
383 {
384 enum gpio_id id = dal_gpio_get_id(irq);
385
386 switch (id) {
387 case GPIO_ID_HPD:
388 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
389 dal_gpio_get_enum(irq));
390 case GPIO_ID_GPIO_PAD:
391 return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
392 dal_gpio_get_enum(irq));
393 default:
394 return DC_IRQ_SOURCE_INVALID;
395 }
396 }
397
dal_irq_get_rx_source(const struct gpio * irq)398 enum dc_irq_source dal_irq_get_rx_source(
399 const struct gpio *irq)
400 {
401 enum gpio_id id = dal_gpio_get_id(irq);
402
403 switch (id) {
404 case GPIO_ID_HPD:
405 return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
406 dal_gpio_get_enum(irq));
407 default:
408 return DC_IRQ_SOURCE_INVALID;
409 }
410 }
411
dal_irq_setup_hpd_filter(struct gpio * irq,struct gpio_hpd_config * config)412 enum gpio_result dal_irq_setup_hpd_filter(
413 struct gpio *irq,
414 struct gpio_hpd_config *config)
415 {
416 struct gpio_config_data config_data;
417
418 if (!config)
419 return GPIO_RESULT_INVALID_DATA;
420
421 config_data.type = GPIO_CONFIG_TYPE_HPD;
422 config_data.config.hpd = *config;
423
424 return dal_gpio_set_config(irq, &config_data);
425 }
426
427 /*
428 * @brief
429 * Creation and destruction
430 */
431
dal_gpio_create_irq(struct gpio_service * service,enum gpio_id id,uint32_t en)432 struct gpio *dal_gpio_create_irq(
433 struct gpio_service *service,
434 enum gpio_id id,
435 uint32_t en)
436 {
437 struct gpio *irq;
438
439 switch (id) {
440 case GPIO_ID_HPD:
441 case GPIO_ID_GPIO_PAD:
442 break;
443 default:
444 id = GPIO_ID_HPD;
445 ASSERT_CRITICAL(false);
446 return NULL;
447 }
448
449 irq = dal_gpio_create(
450 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
451
452 if (irq)
453 return irq;
454
455 ASSERT_CRITICAL(false);
456 return NULL;
457 }
458
dal_gpio_destroy_irq(struct gpio ** irq)459 void dal_gpio_destroy_irq(
460 struct gpio **irq)
461 {
462 if (!irq || !*irq) {
463 ASSERT_CRITICAL(false);
464 return;
465 }
466
467 dal_gpio_destroy(irq);
468 kfree(*irq);
469
470 *irq = NULL;
471 }
472
dal_gpio_create_ddc(struct gpio_service * service,uint32_t offset,uint32_t mask,struct gpio_ddc_hw_info * info)473 struct ddc *dal_gpio_create_ddc(
474 struct gpio_service *service,
475 uint32_t offset,
476 uint32_t mask,
477 struct gpio_ddc_hw_info *info)
478 {
479 enum gpio_id id;
480 uint32_t en;
481 struct ddc *ddc;
482
483 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
484 return NULL;
485
486 ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
487
488 if (!ddc) {
489 BREAK_TO_DEBUGGER();
490 return NULL;
491 }
492
493 ddc->pin_data = dal_gpio_create(
494 service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
495
496 if (!ddc->pin_data) {
497 BREAK_TO_DEBUGGER();
498 goto failure_1;
499 }
500
501 ddc->pin_clock = dal_gpio_create(
502 service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
503
504 if (!ddc->pin_clock) {
505 BREAK_TO_DEBUGGER();
506 goto failure_2;
507 }
508
509 ddc->hw_info = *info;
510
511 ddc->ctx = service->ctx;
512
513 return ddc;
514
515 failure_2:
516 dal_gpio_destroy(&ddc->pin_data);
517
518 failure_1:
519 kfree(ddc);
520
521 return NULL;
522 }
523
dal_gpio_destroy_ddc(struct ddc ** ddc)524 void dal_gpio_destroy_ddc(
525 struct ddc **ddc)
526 {
527 if (!ddc || !*ddc) {
528 BREAK_TO_DEBUGGER();
529 return;
530 }
531
532 dal_ddc_close(*ddc);
533 dal_gpio_destroy(&(*ddc)->pin_data);
534 dal_gpio_destroy(&(*ddc)->pin_clock);
535 kfree(*ddc);
536
537 *ddc = NULL;
538 }
539
dal_ddc_open(struct ddc * ddc,enum gpio_mode mode,enum gpio_ddc_config_type config_type)540 enum gpio_result dal_ddc_open(
541 struct ddc *ddc,
542 enum gpio_mode mode,
543 enum gpio_ddc_config_type config_type)
544 {
545 enum gpio_result result;
546
547 struct gpio_config_data config_data;
548 struct hw_gpio *hw_data;
549 struct hw_gpio *hw_clock;
550
551 result = dal_gpio_open_ex(ddc->pin_data, mode);
552
553 if (result != GPIO_RESULT_OK) {
554 BREAK_TO_DEBUGGER();
555 return result;
556 }
557
558 result = dal_gpio_open_ex(ddc->pin_clock, mode);
559
560 if (result != GPIO_RESULT_OK) {
561 BREAK_TO_DEBUGGER();
562 goto failure;
563 }
564
565 /* DDC clock and data pins should belong
566 * to the same DDC block id,
567 * we use the data pin to set the pad mode. */
568
569 if (mode == GPIO_MODE_INPUT)
570 /* this is from detect_sink_type,
571 * we need extra delay there */
572 config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
573 else
574 config_data.type = GPIO_CONFIG_TYPE_DDC;
575
576 config_data.config.ddc.type = config_type;
577
578 hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
579 hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
580
581 config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
582 config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
583
584 result = dal_gpio_set_config(ddc->pin_data, &config_data);
585
586 if (result == GPIO_RESULT_OK)
587 return result;
588
589 BREAK_TO_DEBUGGER();
590
591 dal_gpio_close(ddc->pin_clock);
592
593 failure:
594 dal_gpio_close(ddc->pin_data);
595
596 return result;
597 }
598
dal_ddc_change_mode(struct ddc * ddc,enum gpio_mode mode)599 enum gpio_result dal_ddc_change_mode(
600 struct ddc *ddc,
601 enum gpio_mode mode)
602 {
603 enum gpio_result result;
604
605 enum gpio_mode original_mode =
606 dal_gpio_get_mode(ddc->pin_data);
607
608 result = dal_gpio_change_mode(ddc->pin_data, mode);
609
610 /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
611 * in case of failures;
612 * set_mode() is so that, in case of failure,
613 * we must explicitly set original mode */
614
615 if (result != GPIO_RESULT_OK)
616 goto failure;
617
618 result = dal_gpio_change_mode(ddc->pin_clock, mode);
619
620 if (result == GPIO_RESULT_OK)
621 return result;
622
623 dal_gpio_change_mode(ddc->pin_clock, original_mode);
624
625 failure:
626 dal_gpio_change_mode(ddc->pin_data, original_mode);
627
628 return result;
629 }
630
dal_ddc_get_line(const struct ddc * ddc)631 enum gpio_ddc_line dal_ddc_get_line(
632 const struct ddc *ddc)
633 {
634 return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
635 }
636
dal_ddc_set_config(struct ddc * ddc,enum gpio_ddc_config_type config_type)637 enum gpio_result dal_ddc_set_config(
638 struct ddc *ddc,
639 enum gpio_ddc_config_type config_type)
640 {
641 struct gpio_config_data config_data;
642
643 config_data.type = GPIO_CONFIG_TYPE_DDC;
644
645 config_data.config.ddc.type = config_type;
646 config_data.config.ddc.data_en_bit_present = false;
647 config_data.config.ddc.clock_en_bit_present = false;
648
649 return dal_gpio_set_config(ddc->pin_data, &config_data);
650 }
651
dal_ddc_close(struct ddc * ddc)652 void dal_ddc_close(
653 struct ddc *ddc)
654 {
655 dal_gpio_close(ddc->pin_clock);
656 dal_gpio_close(ddc->pin_data);
657 }
658
659