Home | History | Annotate | Line # | Download | only in gpio
      1 /*	$NetBSD: amdgpu_gpio_base.c,v 1.2 2021/12/18 23:45:04 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_base.c,v 1.2 2021/12/18 23:45:04 riastradh Exp $");
     34 
     35 #include <linux/slab.h>
     36 
     37 #include "dm_services.h"
     38 
     39 #include "include/gpio_interface.h"
     40 #include "include/gpio_service_interface.h"
     41 #include "hw_gpio.h"
     42 #include "hw_translate.h"
     43 #include "hw_factory.h"
     44 #include "gpio_service.h"
     45 
     46 /*
     47  * Post-requisites: headers required by this unit
     48  */
     49 
     50 /*
     51  * This unit
     52  */
     53 
     54 /*
     55  * @brief
     56  * Public API
     57  */
     58 
     59 enum gpio_result dal_gpio_open(
     60 	struct gpio *gpio,
     61 	enum gpio_mode mode)
     62 {
     63 	return dal_gpio_open_ex(gpio, mode);
     64 }
     65 
     66 enum gpio_result dal_gpio_open_ex(
     67 	struct gpio *gpio,
     68 	enum gpio_mode mode)
     69 {
     70 	if (gpio->pin) {
     71 		ASSERT_CRITICAL(false);
     72 		return GPIO_RESULT_ALREADY_OPENED;
     73 	}
     74 
     75 	// No action if allocation failed during gpio construct
     76 	if (!gpio->hw_container.ddc) {
     77 		ASSERT_CRITICAL(false);
     78 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
     79 	}
     80 	gpio->mode = mode;
     81 
     82 	return dal_gpio_service_open(gpio);
     83 }
     84 
     85 enum gpio_result dal_gpio_get_value(
     86 	const struct gpio *gpio,
     87 	uint32_t *value)
     88 {
     89 	if (!gpio->pin) {
     90 		BREAK_TO_DEBUGGER();
     91 		return GPIO_RESULT_NULL_HANDLE;
     92 	}
     93 
     94 	return gpio->pin->funcs->get_value(gpio->pin, value);
     95 }
     96 
     97 enum gpio_result dal_gpio_set_value(
     98 	const struct gpio *gpio,
     99 	uint32_t value)
    100 {
    101 	if (!gpio->pin) {
    102 		BREAK_TO_DEBUGGER();
    103 		return GPIO_RESULT_NULL_HANDLE;
    104 	}
    105 
    106 	return gpio->pin->funcs->set_value(gpio->pin, value);
    107 }
    108 
    109 enum gpio_mode dal_gpio_get_mode(
    110 	const struct gpio *gpio)
    111 {
    112 	return gpio->mode;
    113 }
    114 
    115 enum gpio_result dal_gpio_lock_pin(
    116 	struct gpio *gpio)
    117 {
    118 	return dal_gpio_service_lock(gpio->service, gpio->id, gpio->en);
    119 }
    120 
    121 enum gpio_result dal_gpio_unlock_pin(
    122 	struct gpio *gpio)
    123 {
    124 	return dal_gpio_service_unlock(gpio->service, gpio->id, gpio->en);
    125 }
    126 
    127 enum gpio_result dal_gpio_change_mode(
    128 	struct gpio *gpio,
    129 	enum gpio_mode mode)
    130 {
    131 	if (!gpio->pin) {
    132 		BREAK_TO_DEBUGGER();
    133 		return GPIO_RESULT_NULL_HANDLE;
    134 	}
    135 
    136 	return gpio->pin->funcs->change_mode(gpio->pin, mode);
    137 }
    138 
    139 enum gpio_id dal_gpio_get_id(
    140 	const struct gpio *gpio)
    141 {
    142 	return gpio->id;
    143 }
    144 
    145 uint32_t dal_gpio_get_enum(
    146 	const struct gpio *gpio)
    147 {
    148 	return gpio->en;
    149 }
    150 
    151 enum gpio_result dal_gpio_set_config(
    152 	struct gpio *gpio,
    153 	const struct gpio_config_data *config_data)
    154 {
    155 	if (!gpio->pin) {
    156 		BREAK_TO_DEBUGGER();
    157 		return GPIO_RESULT_NULL_HANDLE;
    158 	}
    159 
    160 	return gpio->pin->funcs->set_config(gpio->pin, config_data);
    161 }
    162 
    163 enum gpio_result dal_gpio_get_pin_info(
    164 	const struct gpio *gpio,
    165 	struct gpio_pin_info *pin_info)
    166 {
    167 	return gpio->service->translate.funcs->id_to_offset(
    168 		gpio->id, gpio->en, pin_info) ?
    169 		GPIO_RESULT_OK : GPIO_RESULT_INVALID_DATA;
    170 }
    171 
    172 enum sync_source dal_gpio_get_sync_source(
    173 	const struct gpio *gpio)
    174 {
    175 	switch (gpio->id) {
    176 	case GPIO_ID_GENERIC:
    177 		switch (gpio->en) {
    178 		case GPIO_GENERIC_A:
    179 			return SYNC_SOURCE_IO_GENERIC_A;
    180 		case GPIO_GENERIC_B:
    181 			return SYNC_SOURCE_IO_GENERIC_B;
    182 		case GPIO_GENERIC_C:
    183 			return SYNC_SOURCE_IO_GENERIC_C;
    184 		case GPIO_GENERIC_D:
    185 			return SYNC_SOURCE_IO_GENERIC_D;
    186 		case GPIO_GENERIC_E:
    187 			return SYNC_SOURCE_IO_GENERIC_E;
    188 		case GPIO_GENERIC_F:
    189 			return SYNC_SOURCE_IO_GENERIC_F;
    190 		default:
    191 			return SYNC_SOURCE_NONE;
    192 		}
    193 	break;
    194 	case GPIO_ID_SYNC:
    195 		switch (gpio->en) {
    196 		case GPIO_SYNC_HSYNC_A:
    197 			return SYNC_SOURCE_IO_HSYNC_A;
    198 		case GPIO_SYNC_VSYNC_A:
    199 			return SYNC_SOURCE_IO_VSYNC_A;
    200 		case GPIO_SYNC_HSYNC_B:
    201 			return SYNC_SOURCE_IO_HSYNC_B;
    202 		case GPIO_SYNC_VSYNC_B:
    203 			return SYNC_SOURCE_IO_VSYNC_B;
    204 		default:
    205 			return SYNC_SOURCE_NONE;
    206 		}
    207 	break;
    208 	case GPIO_ID_HPD:
    209 		switch (gpio->en) {
    210 		case GPIO_HPD_1:
    211 			return SYNC_SOURCE_IO_HPD1;
    212 		case GPIO_HPD_2:
    213 			return SYNC_SOURCE_IO_HPD2;
    214 		default:
    215 			return SYNC_SOURCE_NONE;
    216 		}
    217 	break;
    218 	case GPIO_ID_GSL:
    219 		switch (gpio->en) {
    220 		case GPIO_GSL_GENLOCK_CLOCK:
    221 			return SYNC_SOURCE_GSL_IO_GENLOCK_CLOCK;
    222 		case GPIO_GSL_GENLOCK_VSYNC:
    223 			return SYNC_SOURCE_GSL_IO_GENLOCK_VSYNC;
    224 		case GPIO_GSL_SWAPLOCK_A:
    225 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_A;
    226 		case GPIO_GSL_SWAPLOCK_B:
    227 			return SYNC_SOURCE_GSL_IO_SWAPLOCK_B;
    228 		default:
    229 			return SYNC_SOURCE_NONE;
    230 		}
    231 	break;
    232 	default:
    233 		return SYNC_SOURCE_NONE;
    234 	}
    235 }
    236 
    237 enum gpio_pin_output_state dal_gpio_get_output_state(
    238 	const struct gpio *gpio)
    239 {
    240 	return gpio->output_state;
    241 }
    242 
    243 struct hw_ddc *dal_gpio_get_ddc(struct gpio *gpio)
    244 {
    245 	return gpio->hw_container.ddc;
    246 }
    247 
    248 struct hw_hpd *dal_gpio_get_hpd(struct gpio *gpio)
    249 {
    250 	return gpio->hw_container.hpd;
    251 }
    252 
    253 struct hw_generic *dal_gpio_get_generic(struct gpio *gpio)
    254 {
    255 	return gpio->hw_container.generic;
    256 }
    257 
    258 void dal_gpio_close(
    259 	struct gpio *gpio)
    260 {
    261 	if (!gpio)
    262 		return;
    263 
    264 	dal_gpio_service_close(gpio->service, &gpio->pin);
    265 
    266 	gpio->mode = GPIO_MODE_UNKNOWN;
    267 }
    268 
    269 /*
    270  * @brief
    271  * Creation and destruction
    272  */
    273 
    274 struct gpio *dal_gpio_create(
    275 	struct gpio_service *service,
    276 	enum gpio_id id,
    277 	uint32_t en,
    278 	enum gpio_pin_output_state output_state)
    279 {
    280 	struct gpio *gpio = kzalloc(sizeof(struct gpio), GFP_KERNEL);
    281 
    282 	if (!gpio) {
    283 		ASSERT_CRITICAL(false);
    284 		return NULL;
    285 	}
    286 
    287 	gpio->service = service;
    288 	gpio->pin = NULL;
    289 	gpio->id = id;
    290 	gpio->en = en;
    291 	gpio->mode = GPIO_MODE_UNKNOWN;
    292 	gpio->output_state = output_state;
    293 
    294 	//initialize hw_container union based on id
    295 	switch (gpio->id) {
    296 	case GPIO_ID_DDC_DATA:
    297 		gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en);
    298 		break;
    299 	case GPIO_ID_DDC_CLOCK:
    300 		gpio->service->factory.funcs->init_ddc_data(&gpio->hw_container.ddc, service->ctx, id, en);
    301 		break;
    302 	case GPIO_ID_GENERIC:
    303 		gpio->service->factory.funcs->init_generic(&gpio->hw_container.generic, service->ctx, id, en);
    304 		break;
    305 	case GPIO_ID_HPD:
    306 		gpio->service->factory.funcs->init_hpd(&gpio->hw_container.hpd, service->ctx, id, en);
    307 		break;
    308 	// TODO: currently gpio for sync and gsl does not get created, might need it later
    309 	case GPIO_ID_SYNC:
    310 		break;
    311 	case GPIO_ID_GSL:
    312 		break;
    313 	default:
    314 		ASSERT_CRITICAL(false);
    315 		gpio->pin = NULL;
    316 	}
    317 
    318 	return gpio;
    319 }
    320 
    321 void dal_gpio_destroy(
    322 	struct gpio **gpio)
    323 {
    324 	if (!gpio || !*gpio) {
    325 		ASSERT_CRITICAL(false);
    326 		return;
    327 	}
    328 
    329 	switch ((*gpio)->id) {
    330 	case GPIO_ID_DDC_DATA:
    331 		kfree((*gpio)->hw_container.ddc);
    332 		(*gpio)->hw_container.ddc = NULL;
    333 		break;
    334 	case GPIO_ID_DDC_CLOCK:
    335 		//TODO: might want to change it to init_ddc_clock
    336 		kfree((*gpio)->hw_container.ddc);
    337 		(*gpio)->hw_container.ddc = NULL;
    338 		break;
    339 	case GPIO_ID_GENERIC:
    340 		kfree((*gpio)->hw_container.generic);
    341 		(*gpio)->hw_container.generic = NULL;
    342 		break;
    343 	case GPIO_ID_HPD:
    344 		kfree((*gpio)->hw_container.hpd);
    345 		(*gpio)->hw_container.hpd = NULL;
    346 		break;
    347 	// TODO: currently gpio for sync and gsl does not get created, might need it later
    348 	case GPIO_ID_SYNC:
    349 		break;
    350 	case GPIO_ID_GSL:
    351 		break;
    352 	default:
    353 		break;
    354 	}
    355 
    356 	kfree(*gpio);
    357 
    358 	*gpio = NULL;
    359 }
    360