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