14562236bSHarry Wentland /*
24562236bSHarry Wentland  * Copyright 2012-15 Advanced Micro Devices, Inc.
34562236bSHarry Wentland  *
44562236bSHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
54562236bSHarry Wentland  * copy of this software and associated documentation files (the "Software"),
64562236bSHarry Wentland  * to deal in the Software without restriction, including without limitation
74562236bSHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84562236bSHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
94562236bSHarry Wentland  * Software is furnished to do so, subject to the following conditions:
104562236bSHarry Wentland  *
114562236bSHarry Wentland  * The above copyright notice and this permission notice shall be included in
124562236bSHarry Wentland  * all copies or substantial portions of the Software.
134562236bSHarry Wentland  *
144562236bSHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154562236bSHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164562236bSHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174562236bSHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184562236bSHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194562236bSHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204562236bSHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
214562236bSHarry Wentland  *
224562236bSHarry Wentland  * Authors: AMD
234562236bSHarry Wentland  *
244562236bSHarry Wentland  */
254562236bSHarry Wentland 
264562236bSHarry Wentland /*
274562236bSHarry Wentland  * Pre-requisites: headers required by header of this unit
284562236bSHarry Wentland  */
294562236bSHarry Wentland 
304562236bSHarry Wentland #include "dm_services.h"
314562236bSHarry Wentland #include "include/gpio_interface.h"
324562236bSHarry Wentland #include "include/gpio_service_interface.h"
334562236bSHarry Wentland #include "hw_translate.h"
344562236bSHarry Wentland #include "hw_factory.h"
354562236bSHarry Wentland 
364562236bSHarry Wentland /*
374562236bSHarry Wentland  * Header of this unit
384562236bSHarry Wentland  */
394562236bSHarry Wentland 
404562236bSHarry Wentland #include "gpio_service.h"
414562236bSHarry Wentland 
424562236bSHarry Wentland /*
434562236bSHarry Wentland  * Post-requisites: headers required by this unit
444562236bSHarry Wentland  */
454562236bSHarry Wentland 
464562236bSHarry Wentland #include "hw_gpio.h"
474562236bSHarry Wentland 
484562236bSHarry Wentland /*
494562236bSHarry Wentland  * @brief
504562236bSHarry Wentland  * Public API.
514562236bSHarry Wentland  */
524562236bSHarry Wentland 
dal_gpio_service_create(enum dce_version dce_version,enum dce_environment dce_environment,struct dc_context * ctx)534562236bSHarry Wentland struct gpio_service *dal_gpio_service_create(
54353f7f3aSLee Jones 	enum dce_version dce_version,
55353f7f3aSLee Jones 	enum dce_environment dce_environment,
564562236bSHarry Wentland 	struct dc_context *ctx)
574562236bSHarry Wentland {
584562236bSHarry Wentland 	struct gpio_service *service;
594562236bSHarry Wentland 	uint32_t index_of_id;
604562236bSHarry Wentland 
612004f45eSHarry Wentland 	service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
624562236bSHarry Wentland 
634562236bSHarry Wentland 	if (!service) {
644562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
654562236bSHarry Wentland 		return NULL;
664562236bSHarry Wentland 	}
674562236bSHarry Wentland 
68353f7f3aSLee Jones 	if (!dal_hw_translate_init(&service->translate, dce_version,
69353f7f3aSLee Jones 			dce_environment)) {
704562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
714562236bSHarry Wentland 		goto failure_1;
724562236bSHarry Wentland 	}
734562236bSHarry Wentland 
74353f7f3aSLee Jones 	if (!dal_hw_factory_init(&service->factory, dce_version,
75353f7f3aSLee Jones 			dce_environment)) {
764562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
774562236bSHarry Wentland 		goto failure_1;
784562236bSHarry Wentland 	}
794562236bSHarry Wentland 
8050f9ca04SYogesh Mohan Marimuthu 	/* allocate and initialize busyness storage */
814562236bSHarry Wentland 	{
824562236bSHarry Wentland 		index_of_id = 0;
834562236bSHarry Wentland 		service->ctx = ctx;
844562236bSHarry Wentland 
854562236bSHarry Wentland 		do {
864562236bSHarry Wentland 			uint32_t number_of_bits =
874562236bSHarry Wentland 				service->factory.number_of_pins[index_of_id];
8850f9ca04SYogesh Mohan Marimuthu 			uint32_t i = 0;
894562236bSHarry Wentland 
904562236bSHarry Wentland 			if (number_of_bits)  {
9150f9ca04SYogesh Mohan Marimuthu 				service->busyness[index_of_id] =
9250f9ca04SYogesh Mohan Marimuthu 					kcalloc(number_of_bits, sizeof(char),
932004f45eSHarry Wentland 						GFP_KERNEL);
944562236bSHarry Wentland 
9550f9ca04SYogesh Mohan Marimuthu 				if (!service->busyness[index_of_id]) {
964562236bSHarry Wentland 					BREAK_TO_DEBUGGER();
974562236bSHarry Wentland 					goto failure_2;
984562236bSHarry Wentland 				}
994562236bSHarry Wentland 
1004562236bSHarry Wentland 				do {
10150f9ca04SYogesh Mohan Marimuthu 					service->busyness[index_of_id][i] = 0;
10250f9ca04SYogesh Mohan Marimuthu 					++i;
10350f9ca04SYogesh Mohan Marimuthu 				} while (i < number_of_bits);
10450f9ca04SYogesh Mohan Marimuthu 			} else {
10550f9ca04SYogesh Mohan Marimuthu 				service->busyness[index_of_id] = NULL;
10650f9ca04SYogesh Mohan Marimuthu 			}
1074562236bSHarry Wentland 
1084562236bSHarry Wentland 			++index_of_id;
1094562236bSHarry Wentland 		} while (index_of_id < GPIO_ID_COUNT);
1104562236bSHarry Wentland 	}
1114562236bSHarry Wentland 
1124562236bSHarry Wentland 	return service;
1134562236bSHarry Wentland 
1144562236bSHarry Wentland failure_2:
1154562236bSHarry Wentland 	while (index_of_id) {
1164562236bSHarry Wentland 		--index_of_id;
11750f9ca04SYogesh Mohan Marimuthu 		kfree(service->busyness[index_of_id]);
1181a7e4f74Skbuild test robot 	}
1194562236bSHarry Wentland 
1204562236bSHarry Wentland failure_1:
1212004f45eSHarry Wentland 	kfree(service);
1224562236bSHarry Wentland 
1234562236bSHarry Wentland 	return NULL;
1244562236bSHarry Wentland }
1254562236bSHarry Wentland 
dal_gpio_service_create_irq(struct gpio_service * service,uint32_t offset,uint32_t mask)1264562236bSHarry Wentland struct gpio *dal_gpio_service_create_irq(
1274562236bSHarry Wentland 	struct gpio_service *service,
1284562236bSHarry Wentland 	uint32_t offset,
1294562236bSHarry Wentland 	uint32_t mask)
1304562236bSHarry Wentland {
1314562236bSHarry Wentland 	enum gpio_id id;
1324562236bSHarry Wentland 	uint32_t en;
1334562236bSHarry Wentland 
1344562236bSHarry Wentland 	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
1354562236bSHarry Wentland 		ASSERT_CRITICAL(false);
1364562236bSHarry Wentland 		return NULL;
1374562236bSHarry Wentland 	}
1384562236bSHarry Wentland 
1394562236bSHarry Wentland 	return dal_gpio_create_irq(service, id, en);
1404562236bSHarry Wentland }
1414562236bSHarry Wentland 
dal_gpio_service_create_generic_mux(struct gpio_service * service,uint32_t offset,uint32_t mask)142c2cd9d04SMurton Liu struct gpio *dal_gpio_service_create_generic_mux(
143c2cd9d04SMurton Liu 	struct gpio_service *service,
144c2cd9d04SMurton Liu 	uint32_t offset,
145c2cd9d04SMurton Liu 	uint32_t mask)
146c2cd9d04SMurton Liu {
147c2cd9d04SMurton Liu 	enum gpio_id id;
148c2cd9d04SMurton Liu 	uint32_t en;
149c2cd9d04SMurton Liu 	struct gpio *generic;
150c2cd9d04SMurton Liu 
15154eef8a4SMurton Liu 	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
15254eef8a4SMurton Liu 		ASSERT_CRITICAL(false);
153c2cd9d04SMurton Liu 		return NULL;
15454eef8a4SMurton Liu 	}
155c2cd9d04SMurton Liu 
156c2cd9d04SMurton Liu 	generic = dal_gpio_create(
157c2cd9d04SMurton Liu 		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
158c2cd9d04SMurton Liu 
159c2cd9d04SMurton Liu 	return generic;
160c2cd9d04SMurton Liu }
161c2cd9d04SMurton Liu 
dal_gpio_destroy_generic_mux(struct gpio ** mux)162c2cd9d04SMurton Liu void dal_gpio_destroy_generic_mux(
163c2cd9d04SMurton Liu 	struct gpio **mux)
164c2cd9d04SMurton Liu {
165c2cd9d04SMurton Liu 	if (!mux || !*mux) {
166c2cd9d04SMurton Liu 		ASSERT_CRITICAL(false);
167c2cd9d04SMurton Liu 		return;
168c2cd9d04SMurton Liu 	}
169c2cd9d04SMurton Liu 
170c2cd9d04SMurton Liu 	dal_gpio_destroy(mux);
171c2cd9d04SMurton Liu 	kfree(*mux);
172c2cd9d04SMurton Liu 
173c2cd9d04SMurton Liu 	*mux = NULL;
174c2cd9d04SMurton Liu }
175c2cd9d04SMurton Liu 
dal_gpio_get_generic_pin_info(struct gpio_service * service,enum gpio_id id,uint32_t en)176c2cd9d04SMurton Liu struct gpio_pin_info dal_gpio_get_generic_pin_info(
177c2cd9d04SMurton Liu 	struct gpio_service *service,
178c2cd9d04SMurton Liu 	enum gpio_id id,
179c2cd9d04SMurton Liu 	uint32_t en)
180c2cd9d04SMurton Liu {
181c2cd9d04SMurton Liu 	struct gpio_pin_info pin;
182c2cd9d04SMurton Liu 
183c2cd9d04SMurton Liu 	if (service->translate.funcs->id_to_offset) {
184c2cd9d04SMurton Liu 		service->translate.funcs->id_to_offset(id, en, &pin);
185c2cd9d04SMurton Liu 	} else {
186c2cd9d04SMurton Liu 		pin.mask = 0xFFFFFFFF;
187c2cd9d04SMurton Liu 		pin.offset = 0xFFFFFFFF;
188c2cd9d04SMurton Liu 	}
189c2cd9d04SMurton Liu 
190c2cd9d04SMurton Liu 	return pin;
191c2cd9d04SMurton Liu }
192c2cd9d04SMurton Liu 
dal_gpio_service_destroy(struct gpio_service ** ptr)1934562236bSHarry Wentland void dal_gpio_service_destroy(
1944562236bSHarry Wentland 	struct gpio_service **ptr)
1954562236bSHarry Wentland {
1964562236bSHarry Wentland 	if (!ptr || !*ptr) {
1974562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
1984562236bSHarry Wentland 		return;
1994562236bSHarry Wentland 	}
2004562236bSHarry Wentland 
2014562236bSHarry Wentland 	/* free business storage */
2024562236bSHarry Wentland 	{
2034562236bSHarry Wentland 		uint32_t index_of_id = 0;
2044562236bSHarry Wentland 
2054562236bSHarry Wentland 		do {
20650f9ca04SYogesh Mohan Marimuthu 			kfree((*ptr)->busyness[index_of_id]);
2074562236bSHarry Wentland 
2084562236bSHarry Wentland 			++index_of_id;
2094562236bSHarry Wentland 		} while (index_of_id < GPIO_ID_COUNT);
2104562236bSHarry Wentland 	}
2114562236bSHarry Wentland 
2122004f45eSHarry Wentland 	kfree(*ptr);
2134562236bSHarry Wentland 
2144562236bSHarry Wentland 	*ptr = NULL;
2154562236bSHarry Wentland }
2164562236bSHarry Wentland 
dal_mux_setup_config(struct gpio * mux,struct gpio_generic_mux_config * config)217c2cd9d04SMurton Liu enum gpio_result dal_mux_setup_config(
218c2cd9d04SMurton Liu 	struct gpio *mux,
219c2cd9d04SMurton Liu 	struct gpio_generic_mux_config *config)
220c2cd9d04SMurton Liu {
221c2cd9d04SMurton Liu 	struct gpio_config_data config_data;
222c2cd9d04SMurton Liu 
223c2cd9d04SMurton Liu 	if (!config)
224c2cd9d04SMurton Liu 		return GPIO_RESULT_INVALID_DATA;
225c2cd9d04SMurton Liu 
226c2cd9d04SMurton Liu 	config_data.config.generic_mux = *config;
227c2cd9d04SMurton Liu 	config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX;
228c2cd9d04SMurton Liu 
229c2cd9d04SMurton Liu 	return dal_gpio_set_config(mux, &config_data);
230c2cd9d04SMurton Liu }
231c2cd9d04SMurton Liu 
2324562236bSHarry Wentland /*
2334562236bSHarry Wentland  * @brief
2344562236bSHarry Wentland  * Private API.
2354562236bSHarry Wentland  */
2364562236bSHarry Wentland 
is_pin_busy(const struct gpio_service * service,enum gpio_id id,uint32_t en)2374562236bSHarry Wentland static bool is_pin_busy(
2384562236bSHarry Wentland 	const struct gpio_service *service,
2394562236bSHarry Wentland 	enum gpio_id id,
2404562236bSHarry Wentland 	uint32_t en)
2414562236bSHarry Wentland {
24250f9ca04SYogesh Mohan Marimuthu 	return service->busyness[id][en];
2434562236bSHarry Wentland }
2444562236bSHarry Wentland 
set_pin_busy(struct gpio_service * service,enum gpio_id id,uint32_t en)2454562236bSHarry Wentland static void set_pin_busy(
2464562236bSHarry Wentland 	struct gpio_service *service,
2474562236bSHarry Wentland 	enum gpio_id id,
2484562236bSHarry Wentland 	uint32_t en)
2494562236bSHarry Wentland {
25050f9ca04SYogesh Mohan Marimuthu 	service->busyness[id][en] = true;
2514562236bSHarry Wentland }
2524562236bSHarry Wentland 
set_pin_free(struct gpio_service * service,enum gpio_id id,uint32_t en)2534562236bSHarry Wentland static void set_pin_free(
2544562236bSHarry Wentland 	struct gpio_service *service,
2554562236bSHarry Wentland 	enum gpio_id id,
2564562236bSHarry Wentland 	uint32_t en)
2574562236bSHarry Wentland {
25850f9ca04SYogesh Mohan Marimuthu 	service->busyness[id][en] = false;
2594562236bSHarry Wentland }
2604562236bSHarry Wentland 
dal_gpio_service_lock(struct gpio_service * service,enum gpio_id id,uint32_t en)261ac627cafSChiawen Huang enum gpio_result dal_gpio_service_lock(
262ac627cafSChiawen Huang 	struct gpio_service *service,
263ac627cafSChiawen Huang 	enum gpio_id id,
264ac627cafSChiawen Huang 	uint32_t en)
265ac627cafSChiawen Huang {
266ac627cafSChiawen Huang 	if (!service->busyness[id]) {
267ac627cafSChiawen Huang 		ASSERT_CRITICAL(false);
268ac627cafSChiawen Huang 		return GPIO_RESULT_OPEN_FAILED;
269ac627cafSChiawen Huang 	}
270ac627cafSChiawen Huang 
271ac627cafSChiawen Huang 	set_pin_busy(service, id, en);
272ac627cafSChiawen Huang 	return GPIO_RESULT_OK;
273ac627cafSChiawen Huang }
274ac627cafSChiawen Huang 
dal_gpio_service_unlock(struct gpio_service * service,enum gpio_id id,uint32_t en)275ac627cafSChiawen Huang enum gpio_result dal_gpio_service_unlock(
276ac627cafSChiawen Huang 	struct gpio_service *service,
277ac627cafSChiawen Huang 	enum gpio_id id,
278ac627cafSChiawen Huang 	uint32_t en)
279ac627cafSChiawen Huang {
280ac627cafSChiawen Huang 	if (!service->busyness[id]) {
281ac627cafSChiawen Huang 		ASSERT_CRITICAL(false);
282ac627cafSChiawen Huang 		return GPIO_RESULT_OPEN_FAILED;
283ac627cafSChiawen Huang 	}
284ac627cafSChiawen Huang 
285ac627cafSChiawen Huang 	set_pin_free(service, id, en);
286ac627cafSChiawen Huang 	return GPIO_RESULT_OK;
287ac627cafSChiawen Huang }
288ac627cafSChiawen Huang 
dal_gpio_service_open(struct gpio * gpio)2894562236bSHarry Wentland enum gpio_result dal_gpio_service_open(
29091db9311SSu Sung Chung 	struct gpio *gpio)
2914562236bSHarry Wentland {
29291db9311SSu Sung Chung 	struct gpio_service *service = gpio->service;
29391db9311SSu Sung Chung 	enum gpio_id id = gpio->id;
29491db9311SSu Sung Chung 	uint32_t en = gpio->en;
29591db9311SSu Sung Chung 	enum gpio_mode mode = gpio->mode;
29691db9311SSu Sung Chung 
29791db9311SSu Sung Chung 	struct hw_gpio_pin **pin = &gpio->pin;
29891db9311SSu Sung Chung 
2994562236bSHarry Wentland 
3004562236bSHarry Wentland 	if (!service->busyness[id]) {
3014562236bSHarry Wentland 		ASSERT_CRITICAL(false);
3024562236bSHarry Wentland 		return GPIO_RESULT_OPEN_FAILED;
3034562236bSHarry Wentland 	}
3044562236bSHarry Wentland 
3054562236bSHarry Wentland 	if (is_pin_busy(service, id, en)) {
3064562236bSHarry Wentland 		ASSERT_CRITICAL(false);
3074562236bSHarry Wentland 		return GPIO_RESULT_DEVICE_BUSY;
3084562236bSHarry Wentland 	}
3094562236bSHarry Wentland 
3104562236bSHarry Wentland 	switch (id) {
3114562236bSHarry Wentland 	case GPIO_ID_DDC_DATA:
31291db9311SSu Sung Chung 		*pin = service->factory.funcs->get_ddc_pin(gpio);
31391db9311SSu Sung Chung 		service->factory.funcs->define_ddc_registers(*pin, en);
3144562236bSHarry Wentland 	break;
3154562236bSHarry Wentland 	case GPIO_ID_DDC_CLOCK:
31691db9311SSu Sung Chung 		*pin = service->factory.funcs->get_ddc_pin(gpio);
31791db9311SSu Sung Chung 		service->factory.funcs->define_ddc_registers(*pin, en);
3184562236bSHarry Wentland 	break;
3194562236bSHarry Wentland 	case GPIO_ID_GENERIC:
32091db9311SSu Sung Chung 		*pin = service->factory.funcs->get_generic_pin(gpio);
32191db9311SSu Sung Chung 		service->factory.funcs->define_generic_registers(*pin, en);
3224562236bSHarry Wentland 	break;
3234562236bSHarry Wentland 	case GPIO_ID_HPD:
32491db9311SSu Sung Chung 		*pin = service->factory.funcs->get_hpd_pin(gpio);
32591db9311SSu Sung Chung 		service->factory.funcs->define_hpd_registers(*pin, en);
3264562236bSHarry Wentland 	break;
32791db9311SSu Sung Chung 
32891db9311SSu Sung Chung 	//TODO: gsl and sync support? create_sync and create_gsl are NULL
3294562236bSHarry Wentland 	case GPIO_ID_SYNC:
3304562236bSHarry Wentland 	case GPIO_ID_GSL:
3314562236bSHarry Wentland 	break;
3324562236bSHarry Wentland 	default:
3334562236bSHarry Wentland 		ASSERT_CRITICAL(false);
3344562236bSHarry Wentland 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
3354562236bSHarry Wentland 	}
3364562236bSHarry Wentland 
33791db9311SSu Sung Chung 	if (!*pin) {
3384562236bSHarry Wentland 		ASSERT_CRITICAL(false);
3394562236bSHarry Wentland 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
3404562236bSHarry Wentland 	}
3414562236bSHarry Wentland 
34291db9311SSu Sung Chung 	if (!(*pin)->funcs->open(*pin, mode)) {
3434562236bSHarry Wentland 		ASSERT_CRITICAL(false);
34491db9311SSu Sung Chung 		dal_gpio_service_close(service, pin);
3454562236bSHarry Wentland 		return GPIO_RESULT_OPEN_FAILED;
3464562236bSHarry Wentland 	}
3474562236bSHarry Wentland 
3484562236bSHarry Wentland 	set_pin_busy(service, id, en);
3494562236bSHarry Wentland 	return GPIO_RESULT_OK;
3504562236bSHarry Wentland }
3514562236bSHarry Wentland 
dal_gpio_service_close(struct gpio_service * service,struct hw_gpio_pin ** ptr)3524562236bSHarry Wentland void dal_gpio_service_close(
3534562236bSHarry Wentland 	struct gpio_service *service,
3544562236bSHarry Wentland 	struct hw_gpio_pin **ptr)
3554562236bSHarry Wentland {
3564562236bSHarry Wentland 	struct hw_gpio_pin *pin;
3574562236bSHarry Wentland 
3584562236bSHarry Wentland 	if (!ptr) {
3594562236bSHarry Wentland 		ASSERT_CRITICAL(false);
3604562236bSHarry Wentland 		return;
3614562236bSHarry Wentland 	}
3624562236bSHarry Wentland 
3634562236bSHarry Wentland 	pin = *ptr;
3644562236bSHarry Wentland 
3654562236bSHarry Wentland 	if (pin) {
3664562236bSHarry Wentland 		set_pin_free(service, pin->id, pin->en);
3674562236bSHarry Wentland 
3684562236bSHarry Wentland 		pin->funcs->close(pin);
3694562236bSHarry Wentland 
37091db9311SSu Sung Chung 		*ptr = NULL;
3714562236bSHarry Wentland 	}
3724562236bSHarry Wentland }
3734562236bSHarry Wentland 
dal_irq_get_source(const struct gpio * irq)3744562236bSHarry Wentland enum dc_irq_source dal_irq_get_source(
3754562236bSHarry Wentland 	const struct gpio *irq)
3764562236bSHarry Wentland {
3774562236bSHarry Wentland 	enum gpio_id id = dal_gpio_get_id(irq);
3784562236bSHarry Wentland 
3794562236bSHarry Wentland 	switch (id) {
3804562236bSHarry Wentland 	case GPIO_ID_HPD:
3814562236bSHarry Wentland 		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
3824562236bSHarry Wentland 			dal_gpio_get_enum(irq));
3834562236bSHarry Wentland 	case GPIO_ID_GPIO_PAD:
3844562236bSHarry Wentland 		return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
3854562236bSHarry Wentland 			dal_gpio_get_enum(irq));
3864562236bSHarry Wentland 	default:
3874562236bSHarry Wentland 		return DC_IRQ_SOURCE_INVALID;
3884562236bSHarry Wentland 	}
3894562236bSHarry Wentland }
3904562236bSHarry Wentland 
dal_irq_get_rx_source(const struct gpio * irq)3914562236bSHarry Wentland enum dc_irq_source dal_irq_get_rx_source(
3924562236bSHarry Wentland 	const struct gpio *irq)
3934562236bSHarry Wentland {
3944562236bSHarry Wentland 	enum gpio_id id = dal_gpio_get_id(irq);
3954562236bSHarry Wentland 
3964562236bSHarry Wentland 	switch (id) {
3974562236bSHarry Wentland 	case GPIO_ID_HPD:
3984562236bSHarry Wentland 		return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
3994562236bSHarry Wentland 			dal_gpio_get_enum(irq));
4004562236bSHarry Wentland 	default:
4014562236bSHarry Wentland 		return DC_IRQ_SOURCE_INVALID;
4024562236bSHarry Wentland 	}
4034562236bSHarry Wentland }
4044562236bSHarry Wentland 
dal_irq_setup_hpd_filter(struct gpio * irq,struct gpio_hpd_config * config)4054562236bSHarry Wentland enum gpio_result dal_irq_setup_hpd_filter(
4064562236bSHarry Wentland 	struct gpio *irq,
4074562236bSHarry Wentland 	struct gpio_hpd_config *config)
4084562236bSHarry Wentland {
4094562236bSHarry Wentland 	struct gpio_config_data config_data;
4104562236bSHarry Wentland 
4114562236bSHarry Wentland 	if (!config)
4124562236bSHarry Wentland 		return GPIO_RESULT_INVALID_DATA;
4134562236bSHarry Wentland 
4144562236bSHarry Wentland 	config_data.type = GPIO_CONFIG_TYPE_HPD;
4154562236bSHarry Wentland 	config_data.config.hpd = *config;
4164562236bSHarry Wentland 
4174562236bSHarry Wentland 	return dal_gpio_set_config(irq, &config_data);
4184562236bSHarry Wentland }
4194562236bSHarry Wentland 
4204562236bSHarry Wentland /*
4214562236bSHarry Wentland  * @brief
4224562236bSHarry Wentland  * Creation and destruction
4234562236bSHarry Wentland  */
4244562236bSHarry Wentland 
dal_gpio_create_irq(struct gpio_service * service,enum gpio_id id,uint32_t en)4254562236bSHarry Wentland struct gpio *dal_gpio_create_irq(
4264562236bSHarry Wentland 	struct gpio_service *service,
4274562236bSHarry Wentland 	enum gpio_id id,
4284562236bSHarry Wentland 	uint32_t en)
4294562236bSHarry Wentland {
4304562236bSHarry Wentland 	struct gpio *irq;
4314562236bSHarry Wentland 
4324562236bSHarry Wentland 	switch (id) {
4334562236bSHarry Wentland 	case GPIO_ID_HPD:
4344562236bSHarry Wentland 	case GPIO_ID_GPIO_PAD:
4354562236bSHarry Wentland 	break;
4364562236bSHarry Wentland 	default:
437613cb725SCharlene Liu 		id = GPIO_ID_HPD;
4384562236bSHarry Wentland 		ASSERT_CRITICAL(false);
4394562236bSHarry Wentland 		return NULL;
4404562236bSHarry Wentland 	}
4414562236bSHarry Wentland 
4424562236bSHarry Wentland 	irq = dal_gpio_create(
4434562236bSHarry Wentland 		service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
4444562236bSHarry Wentland 
4454562236bSHarry Wentland 	if (irq)
4464562236bSHarry Wentland 		return irq;
4474562236bSHarry Wentland 
4484562236bSHarry Wentland 	ASSERT_CRITICAL(false);
4494562236bSHarry Wentland 	return NULL;
4504562236bSHarry Wentland }
4514562236bSHarry Wentland 
dal_gpio_destroy_irq(struct gpio ** irq)4524562236bSHarry Wentland void dal_gpio_destroy_irq(
4534562236bSHarry Wentland 	struct gpio **irq)
4544562236bSHarry Wentland {
4554562236bSHarry Wentland 	if (!irq || !*irq) {
4564562236bSHarry Wentland 		ASSERT_CRITICAL(false);
4574562236bSHarry Wentland 		return;
4584562236bSHarry Wentland 	}
4594562236bSHarry Wentland 
4604562236bSHarry Wentland 	dal_gpio_destroy(irq);
4612004f45eSHarry Wentland 	kfree(*irq);
4624562236bSHarry Wentland 
4634562236bSHarry Wentland 	*irq = NULL;
4644562236bSHarry Wentland }
4654562236bSHarry Wentland 
dal_gpio_create_ddc(struct gpio_service * service,uint32_t offset,uint32_t mask,struct gpio_ddc_hw_info * info)4664562236bSHarry Wentland struct ddc *dal_gpio_create_ddc(
4674562236bSHarry Wentland 	struct gpio_service *service,
4684562236bSHarry Wentland 	uint32_t offset,
4694562236bSHarry Wentland 	uint32_t mask,
4704562236bSHarry Wentland 	struct gpio_ddc_hw_info *info)
4714562236bSHarry Wentland {
4724562236bSHarry Wentland 	enum gpio_id id;
4734562236bSHarry Wentland 	uint32_t en;
4744562236bSHarry Wentland 	struct ddc *ddc;
4754562236bSHarry Wentland 
4764562236bSHarry Wentland 	if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
4774562236bSHarry Wentland 		return NULL;
4784562236bSHarry Wentland 
4792004f45eSHarry Wentland 	ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
4804562236bSHarry Wentland 
4814562236bSHarry Wentland 	if (!ddc) {
4824562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
4834562236bSHarry Wentland 		return NULL;
4844562236bSHarry Wentland 	}
4854562236bSHarry Wentland 
4864562236bSHarry Wentland 	ddc->pin_data = dal_gpio_create(
4874562236bSHarry Wentland 		service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
4884562236bSHarry Wentland 
4894562236bSHarry Wentland 	if (!ddc->pin_data) {
4904562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
4914562236bSHarry Wentland 		goto failure_1;
4924562236bSHarry Wentland 	}
4934562236bSHarry Wentland 
4944562236bSHarry Wentland 	ddc->pin_clock = dal_gpio_create(
4954562236bSHarry Wentland 		service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
4964562236bSHarry Wentland 
4974562236bSHarry Wentland 	if (!ddc->pin_clock) {
4984562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
4994562236bSHarry Wentland 		goto failure_2;
5004562236bSHarry Wentland 	}
5014562236bSHarry Wentland 
5024562236bSHarry Wentland 	ddc->hw_info = *info;
5034562236bSHarry Wentland 
5044562236bSHarry Wentland 	ddc->ctx = service->ctx;
5054562236bSHarry Wentland 
5064562236bSHarry Wentland 	return ddc;
5074562236bSHarry Wentland 
5084562236bSHarry Wentland failure_2:
5094562236bSHarry Wentland 	dal_gpio_destroy(&ddc->pin_data);
5104562236bSHarry Wentland 
5114562236bSHarry Wentland failure_1:
5122004f45eSHarry Wentland 	kfree(ddc);
5134562236bSHarry Wentland 
5144562236bSHarry Wentland 	return NULL;
5154562236bSHarry Wentland }
5164562236bSHarry Wentland 
dal_gpio_destroy_ddc(struct ddc ** ddc)5174562236bSHarry Wentland void dal_gpio_destroy_ddc(
5184562236bSHarry Wentland 	struct ddc **ddc)
5194562236bSHarry Wentland {
5204562236bSHarry Wentland 	if (!ddc || !*ddc) {
5214562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
5224562236bSHarry Wentland 		return;
5234562236bSHarry Wentland 	}
5244562236bSHarry Wentland 
5254562236bSHarry Wentland 	dal_ddc_close(*ddc);
5264562236bSHarry Wentland 	dal_gpio_destroy(&(*ddc)->pin_data);
5274562236bSHarry Wentland 	dal_gpio_destroy(&(*ddc)->pin_clock);
5282004f45eSHarry Wentland 	kfree(*ddc);
5294562236bSHarry Wentland 
5304562236bSHarry Wentland 	*ddc = NULL;
5314562236bSHarry Wentland }
5324562236bSHarry Wentland 
dal_ddc_open(struct ddc * ddc,enum gpio_mode mode,enum gpio_ddc_config_type config_type)5334562236bSHarry Wentland enum gpio_result dal_ddc_open(
5344562236bSHarry Wentland 	struct ddc *ddc,
5354562236bSHarry Wentland 	enum gpio_mode mode,
5364562236bSHarry Wentland 	enum gpio_ddc_config_type config_type)
5374562236bSHarry Wentland {
5384562236bSHarry Wentland 	enum gpio_result result;
5394562236bSHarry Wentland 
5404562236bSHarry Wentland 	struct gpio_config_data config_data;
5414562236bSHarry Wentland 	struct hw_gpio *hw_data;
5424562236bSHarry Wentland 	struct hw_gpio *hw_clock;
5434562236bSHarry Wentland 
5444562236bSHarry Wentland 	result = dal_gpio_open_ex(ddc->pin_data, mode);
5454562236bSHarry Wentland 
5464562236bSHarry Wentland 	if (result != GPIO_RESULT_OK) {
5474562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
5484562236bSHarry Wentland 		return result;
5494562236bSHarry Wentland 	}
5504562236bSHarry Wentland 
5514562236bSHarry Wentland 	result = dal_gpio_open_ex(ddc->pin_clock, mode);
5524562236bSHarry Wentland 
5534562236bSHarry Wentland 	if (result != GPIO_RESULT_OK) {
5544562236bSHarry Wentland 		BREAK_TO_DEBUGGER();
5554562236bSHarry Wentland 		goto failure;
5564562236bSHarry Wentland 	}
5574562236bSHarry Wentland 
5584562236bSHarry Wentland 	/* DDC clock and data pins should belong
5594562236bSHarry Wentland 	 * to the same DDC block id,
5604562236bSHarry Wentland 	 * we use the data pin to set the pad mode. */
5614562236bSHarry Wentland 
5624562236bSHarry Wentland 	if (mode == GPIO_MODE_INPUT)
5634562236bSHarry Wentland 		/* this is from detect_sink_type,
5644562236bSHarry Wentland 		 * we need extra delay there */
5654562236bSHarry Wentland 		config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
5664562236bSHarry Wentland 	else
5674562236bSHarry Wentland 		config_data.type = GPIO_CONFIG_TYPE_DDC;
5684562236bSHarry Wentland 
5694562236bSHarry Wentland 	config_data.config.ddc.type = config_type;
5704562236bSHarry Wentland 
5714562236bSHarry Wentland 	hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
5724562236bSHarry Wentland 	hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
5734562236bSHarry Wentland 
5744562236bSHarry Wentland 	config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
5754562236bSHarry Wentland 	config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
5764562236bSHarry Wentland 
5774562236bSHarry Wentland 	result = dal_gpio_set_config(ddc->pin_data, &config_data);
5784562236bSHarry Wentland 
5794562236bSHarry Wentland 	if (result == GPIO_RESULT_OK)
5804562236bSHarry Wentland 		return result;
5814562236bSHarry Wentland 
5824562236bSHarry Wentland 	BREAK_TO_DEBUGGER();
5834562236bSHarry Wentland 
5844562236bSHarry Wentland 	dal_gpio_close(ddc->pin_clock);
5854562236bSHarry Wentland 
5864562236bSHarry Wentland failure:
5874562236bSHarry Wentland 	dal_gpio_close(ddc->pin_data);
5884562236bSHarry Wentland 
5894562236bSHarry Wentland 	return result;
5904562236bSHarry Wentland }
5914562236bSHarry Wentland 
dal_ddc_change_mode(struct ddc * ddc,enum gpio_mode mode)5924562236bSHarry Wentland enum gpio_result dal_ddc_change_mode(
5934562236bSHarry Wentland 	struct ddc *ddc,
5944562236bSHarry Wentland 	enum gpio_mode mode)
5954562236bSHarry Wentland {
5964562236bSHarry Wentland 	enum gpio_result result;
5974562236bSHarry Wentland 
5984562236bSHarry Wentland 	enum gpio_mode original_mode =
5994562236bSHarry Wentland 		dal_gpio_get_mode(ddc->pin_data);
6004562236bSHarry Wentland 
6014562236bSHarry Wentland 	result = dal_gpio_change_mode(ddc->pin_data, mode);
6024562236bSHarry Wentland 
6034562236bSHarry Wentland 	/* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
6044562236bSHarry Wentland 	 * in case of failures;
6054562236bSHarry Wentland 	 * set_mode() is so that, in case of failure,
6064562236bSHarry Wentland 	 * we must explicitly set original mode */
6074562236bSHarry Wentland 
6084562236bSHarry Wentland 	if (result != GPIO_RESULT_OK)
6094562236bSHarry Wentland 		goto failure;
6104562236bSHarry Wentland 
6114562236bSHarry Wentland 	result = dal_gpio_change_mode(ddc->pin_clock, mode);
6124562236bSHarry Wentland 
6134562236bSHarry Wentland 	if (result == GPIO_RESULT_OK)
6144562236bSHarry Wentland 		return result;
6154562236bSHarry Wentland 
6164562236bSHarry Wentland 	dal_gpio_change_mode(ddc->pin_clock, original_mode);
6174562236bSHarry Wentland 
6184562236bSHarry Wentland failure:
6194562236bSHarry Wentland 	dal_gpio_change_mode(ddc->pin_data, original_mode);
6204562236bSHarry Wentland 
6214562236bSHarry Wentland 	return result;
6224562236bSHarry Wentland }
6234562236bSHarry Wentland 
dal_ddc_get_line(const struct ddc * ddc)6244562236bSHarry Wentland enum gpio_ddc_line dal_ddc_get_line(
6254562236bSHarry Wentland 	const struct ddc *ddc)
6264562236bSHarry Wentland {
6274562236bSHarry Wentland 	return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
6284562236bSHarry Wentland }
6294562236bSHarry Wentland 
dal_ddc_set_config(struct ddc * ddc,enum gpio_ddc_config_type config_type)6304562236bSHarry Wentland enum gpio_result dal_ddc_set_config(
6314562236bSHarry Wentland 	struct ddc *ddc,
6324562236bSHarry Wentland 	enum gpio_ddc_config_type config_type)
6334562236bSHarry Wentland {
6344562236bSHarry Wentland 	struct gpio_config_data config_data;
6354562236bSHarry Wentland 
6364562236bSHarry Wentland 	config_data.type = GPIO_CONFIG_TYPE_DDC;
6374562236bSHarry Wentland 
6384562236bSHarry Wentland 	config_data.config.ddc.type = config_type;
6394562236bSHarry Wentland 	config_data.config.ddc.data_en_bit_present = false;
6404562236bSHarry Wentland 	config_data.config.ddc.clock_en_bit_present = false;
6414562236bSHarry Wentland 
6424562236bSHarry Wentland 	return dal_gpio_set_config(ddc->pin_data, &config_data);
6434562236bSHarry Wentland }
6444562236bSHarry Wentland 
dal_ddc_close(struct ddc * ddc)6454562236bSHarry Wentland void dal_ddc_close(
6464562236bSHarry Wentland 	struct ddc *ddc)
6474562236bSHarry Wentland {
648*2716bc82SJing Zhou 	if (ddc != NULL) {
6494562236bSHarry Wentland 		dal_gpio_close(ddc->pin_clock);
6504562236bSHarry Wentland 		dal_gpio_close(ddc->pin_data);
6514562236bSHarry Wentland 	}
652*2716bc82SJing Zhou }
6534562236bSHarry Wentland 
654