Home | History | Annotate | Line # | Download | only in gpio
      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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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