xref: /netbsd-src/sys/external/bsd/drm2/dist/drm/amd/display/dc/gpio/amdgpu_gpio_service.c (revision 7704585247431b17025a5c7795c1c7bc8dde3e5f)
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