1fb4d8502Sjsg /* 2fb4d8502Sjsg * Copyright 2012-15 Advanced Micro Devices, Inc. 3fb4d8502Sjsg * 4fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 5fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"), 6fb4d8502Sjsg * to deal in the Software without restriction, including without limitation 7fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the 9fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions: 10fb4d8502Sjsg * 11fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in 12fb4d8502Sjsg * all copies or substantial portions of the Software. 13fb4d8502Sjsg * 14fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE. 21fb4d8502Sjsg * 22fb4d8502Sjsg * Authors: AMD 23fb4d8502Sjsg * 24fb4d8502Sjsg */ 25fb4d8502Sjsg 26fb4d8502Sjsg /* 27fb4d8502Sjsg * Pre-requisites: headers required by header of this unit 28fb4d8502Sjsg */ 29fb4d8502Sjsg 30fb4d8502Sjsg #include "dm_services.h" 31fb4d8502Sjsg #include "include/gpio_interface.h" 32fb4d8502Sjsg #include "include/gpio_service_interface.h" 33fb4d8502Sjsg #include "hw_translate.h" 34fb4d8502Sjsg #include "hw_factory.h" 35fb4d8502Sjsg 36fb4d8502Sjsg /* 37fb4d8502Sjsg * Header of this unit 38fb4d8502Sjsg */ 39fb4d8502Sjsg 40fb4d8502Sjsg #include "gpio_service.h" 41fb4d8502Sjsg 42fb4d8502Sjsg /* 43fb4d8502Sjsg * Post-requisites: headers required by this unit 44fb4d8502Sjsg */ 45fb4d8502Sjsg 46fb4d8502Sjsg #include "hw_gpio.h" 47fb4d8502Sjsg 48fb4d8502Sjsg /* 49fb4d8502Sjsg * @brief 50fb4d8502Sjsg * Public API. 51fb4d8502Sjsg */ 52fb4d8502Sjsg 53fb4d8502Sjsg struct gpio_service *dal_gpio_service_create( 545ca02815Sjsg enum dce_version dce_version, 555ca02815Sjsg enum dce_environment dce_environment, 56fb4d8502Sjsg struct dc_context *ctx) 57fb4d8502Sjsg { 58fb4d8502Sjsg struct gpio_service *service; 59*4dffd2f4Sjsg int32_t index_of_id; 60fb4d8502Sjsg 61fb4d8502Sjsg service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL); 62fb4d8502Sjsg 63fb4d8502Sjsg if (!service) { 64fb4d8502Sjsg BREAK_TO_DEBUGGER(); 65fb4d8502Sjsg return NULL; 66fb4d8502Sjsg } 67fb4d8502Sjsg 685ca02815Sjsg if (!dal_hw_translate_init(&service->translate, dce_version, 695ca02815Sjsg dce_environment)) { 70fb4d8502Sjsg BREAK_TO_DEBUGGER(); 71fb4d8502Sjsg goto failure_1; 72fb4d8502Sjsg } 73fb4d8502Sjsg 745ca02815Sjsg if (!dal_hw_factory_init(&service->factory, dce_version, 755ca02815Sjsg dce_environment)) { 76fb4d8502Sjsg BREAK_TO_DEBUGGER(); 77fb4d8502Sjsg goto failure_1; 78fb4d8502Sjsg } 79fb4d8502Sjsg 80c349dbc7Sjsg /* allocate and initialize busyness storage */ 81fb4d8502Sjsg { 82fb4d8502Sjsg index_of_id = 0; 83fb4d8502Sjsg service->ctx = ctx; 84fb4d8502Sjsg 85fb4d8502Sjsg do { 86fb4d8502Sjsg uint32_t number_of_bits = 87fb4d8502Sjsg service->factory.number_of_pins[index_of_id]; 88c349dbc7Sjsg uint32_t i = 0; 89fb4d8502Sjsg 90fb4d8502Sjsg if (number_of_bits) { 91c349dbc7Sjsg service->busyness[index_of_id] = 92c349dbc7Sjsg kcalloc(number_of_bits, sizeof(char), 93fb4d8502Sjsg GFP_KERNEL); 94fb4d8502Sjsg 95c349dbc7Sjsg if (!service->busyness[index_of_id]) { 96fb4d8502Sjsg BREAK_TO_DEBUGGER(); 97fb4d8502Sjsg goto failure_2; 98fb4d8502Sjsg } 99fb4d8502Sjsg 100fb4d8502Sjsg do { 101c349dbc7Sjsg service->busyness[index_of_id][i] = 0; 102c349dbc7Sjsg ++i; 103c349dbc7Sjsg } while (i < number_of_bits); 104c349dbc7Sjsg } else { 105c349dbc7Sjsg service->busyness[index_of_id] = NULL; 106c349dbc7Sjsg } 107fb4d8502Sjsg 108fb4d8502Sjsg ++index_of_id; 109fb4d8502Sjsg } while (index_of_id < GPIO_ID_COUNT); 110fb4d8502Sjsg } 111fb4d8502Sjsg 112fb4d8502Sjsg return service; 113fb4d8502Sjsg 114fb4d8502Sjsg failure_2: 115*4dffd2f4Sjsg while (index_of_id > 0) { 116fb4d8502Sjsg --index_of_id; 117c349dbc7Sjsg kfree(service->busyness[index_of_id]); 118fb4d8502Sjsg } 119fb4d8502Sjsg 120fb4d8502Sjsg failure_1: 121fb4d8502Sjsg kfree(service); 122fb4d8502Sjsg 123fb4d8502Sjsg return NULL; 124fb4d8502Sjsg } 125fb4d8502Sjsg 126fb4d8502Sjsg struct gpio *dal_gpio_service_create_irq( 127fb4d8502Sjsg struct gpio_service *service, 128fb4d8502Sjsg uint32_t offset, 129fb4d8502Sjsg uint32_t mask) 130fb4d8502Sjsg { 131fb4d8502Sjsg enum gpio_id id; 132fb4d8502Sjsg uint32_t en; 133fb4d8502Sjsg 134fb4d8502Sjsg if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { 135fb4d8502Sjsg ASSERT_CRITICAL(false); 136fb4d8502Sjsg return NULL; 137fb4d8502Sjsg } 138fb4d8502Sjsg 139fb4d8502Sjsg return dal_gpio_create_irq(service, id, en); 140fb4d8502Sjsg } 141fb4d8502Sjsg 142c349dbc7Sjsg struct gpio *dal_gpio_service_create_generic_mux( 143c349dbc7Sjsg struct gpio_service *service, 144c349dbc7Sjsg uint32_t offset, 145c349dbc7Sjsg uint32_t mask) 146c349dbc7Sjsg { 147c349dbc7Sjsg enum gpio_id id; 148c349dbc7Sjsg uint32_t en; 149c349dbc7Sjsg struct gpio *generic; 150c349dbc7Sjsg 151c349dbc7Sjsg if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { 152c349dbc7Sjsg ASSERT_CRITICAL(false); 153c349dbc7Sjsg return NULL; 154c349dbc7Sjsg } 155c349dbc7Sjsg 156c349dbc7Sjsg generic = dal_gpio_create( 157c349dbc7Sjsg service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 158c349dbc7Sjsg 159c349dbc7Sjsg return generic; 160c349dbc7Sjsg } 161c349dbc7Sjsg 162c349dbc7Sjsg void dal_gpio_destroy_generic_mux( 163c349dbc7Sjsg struct gpio **mux) 164c349dbc7Sjsg { 165c349dbc7Sjsg if (!mux || !*mux) { 166c349dbc7Sjsg ASSERT_CRITICAL(false); 167c349dbc7Sjsg return; 168c349dbc7Sjsg } 169c349dbc7Sjsg 170c349dbc7Sjsg dal_gpio_destroy(mux); 171c349dbc7Sjsg kfree(*mux); 172c349dbc7Sjsg 173c349dbc7Sjsg *mux = NULL; 174c349dbc7Sjsg } 175c349dbc7Sjsg 176c349dbc7Sjsg struct gpio_pin_info dal_gpio_get_generic_pin_info( 177c349dbc7Sjsg struct gpio_service *service, 178c349dbc7Sjsg enum gpio_id id, 179c349dbc7Sjsg uint32_t en) 180c349dbc7Sjsg { 181c349dbc7Sjsg struct gpio_pin_info pin; 182c349dbc7Sjsg 183c349dbc7Sjsg if (service->translate.funcs->id_to_offset) { 184c349dbc7Sjsg service->translate.funcs->id_to_offset(id, en, &pin); 185c349dbc7Sjsg } else { 186c349dbc7Sjsg pin.mask = 0xFFFFFFFF; 187c349dbc7Sjsg pin.offset = 0xFFFFFFFF; 188c349dbc7Sjsg } 189c349dbc7Sjsg 190c349dbc7Sjsg return pin; 191c349dbc7Sjsg } 192c349dbc7Sjsg 193fb4d8502Sjsg void dal_gpio_service_destroy( 194fb4d8502Sjsg struct gpio_service **ptr) 195fb4d8502Sjsg { 196fb4d8502Sjsg if (!ptr || !*ptr) { 197fb4d8502Sjsg BREAK_TO_DEBUGGER(); 198fb4d8502Sjsg return; 199fb4d8502Sjsg } 200fb4d8502Sjsg 201fb4d8502Sjsg /* free business storage */ 202fb4d8502Sjsg { 203fb4d8502Sjsg uint32_t index_of_id = 0; 204fb4d8502Sjsg 205fb4d8502Sjsg do { 206c349dbc7Sjsg kfree((*ptr)->busyness[index_of_id]); 207fb4d8502Sjsg 208fb4d8502Sjsg ++index_of_id; 209fb4d8502Sjsg } while (index_of_id < GPIO_ID_COUNT); 210fb4d8502Sjsg } 211fb4d8502Sjsg 212fb4d8502Sjsg kfree(*ptr); 213fb4d8502Sjsg 214fb4d8502Sjsg *ptr = NULL; 215fb4d8502Sjsg } 216fb4d8502Sjsg 217c349dbc7Sjsg enum gpio_result dal_mux_setup_config( 218c349dbc7Sjsg struct gpio *mux, 219c349dbc7Sjsg struct gpio_generic_mux_config *config) 220c349dbc7Sjsg { 221c349dbc7Sjsg struct gpio_config_data config_data; 222c349dbc7Sjsg 223c349dbc7Sjsg if (!config) 224c349dbc7Sjsg return GPIO_RESULT_INVALID_DATA; 225c349dbc7Sjsg 226c349dbc7Sjsg config_data.config.generic_mux = *config; 227c349dbc7Sjsg config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX; 228c349dbc7Sjsg 229c349dbc7Sjsg return dal_gpio_set_config(mux, &config_data); 230c349dbc7Sjsg } 231c349dbc7Sjsg 232fb4d8502Sjsg /* 233fb4d8502Sjsg * @brief 234fb4d8502Sjsg * Private API. 235fb4d8502Sjsg */ 236fb4d8502Sjsg 237fb4d8502Sjsg static bool is_pin_busy( 238fb4d8502Sjsg const struct gpio_service *service, 239fb4d8502Sjsg enum gpio_id id, 240fb4d8502Sjsg uint32_t en) 241fb4d8502Sjsg { 242a691e319Sjsg if (id == GPIO_ID_UNKNOWN) 243a691e319Sjsg return false; 244a691e319Sjsg 245c349dbc7Sjsg return service->busyness[id][en]; 246fb4d8502Sjsg } 247fb4d8502Sjsg 248fb4d8502Sjsg static void set_pin_busy( 249fb4d8502Sjsg struct gpio_service *service, 250fb4d8502Sjsg enum gpio_id id, 251fb4d8502Sjsg uint32_t en) 252fb4d8502Sjsg { 253a691e319Sjsg if (id == GPIO_ID_UNKNOWN) 254a691e319Sjsg return; 255a691e319Sjsg 256c349dbc7Sjsg service->busyness[id][en] = true; 257fb4d8502Sjsg } 258fb4d8502Sjsg 259fb4d8502Sjsg static void set_pin_free( 260fb4d8502Sjsg struct gpio_service *service, 261fb4d8502Sjsg enum gpio_id id, 262fb4d8502Sjsg uint32_t en) 263fb4d8502Sjsg { 264a691e319Sjsg if (id == GPIO_ID_UNKNOWN) 265a691e319Sjsg return; 266a691e319Sjsg 267c349dbc7Sjsg service->busyness[id][en] = false; 268c349dbc7Sjsg } 269fb4d8502Sjsg 270c349dbc7Sjsg enum gpio_result dal_gpio_service_lock( 271c349dbc7Sjsg struct gpio_service *service, 272c349dbc7Sjsg enum gpio_id id, 273c349dbc7Sjsg uint32_t en) 274c349dbc7Sjsg { 275a691e319Sjsg if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) { 276c349dbc7Sjsg ASSERT_CRITICAL(false); 277c349dbc7Sjsg return GPIO_RESULT_OPEN_FAILED; 278c349dbc7Sjsg } 279c349dbc7Sjsg 280c349dbc7Sjsg set_pin_busy(service, id, en); 281c349dbc7Sjsg return GPIO_RESULT_OK; 282c349dbc7Sjsg } 283c349dbc7Sjsg 284c349dbc7Sjsg enum gpio_result dal_gpio_service_unlock( 285c349dbc7Sjsg struct gpio_service *service, 286c349dbc7Sjsg enum gpio_id id, 287c349dbc7Sjsg uint32_t en) 288c349dbc7Sjsg { 289a691e319Sjsg if (id != GPIO_ID_UNKNOWN && !service->busyness[id]) { 290c349dbc7Sjsg ASSERT_CRITICAL(false); 291c349dbc7Sjsg return GPIO_RESULT_OPEN_FAILED; 292c349dbc7Sjsg } 293c349dbc7Sjsg 294c349dbc7Sjsg set_pin_free(service, id, en); 295c349dbc7Sjsg return GPIO_RESULT_OK; 296fb4d8502Sjsg } 297fb4d8502Sjsg 298fb4d8502Sjsg enum gpio_result dal_gpio_service_open( 299c349dbc7Sjsg struct gpio *gpio) 300fb4d8502Sjsg { 301c349dbc7Sjsg struct gpio_service *service = gpio->service; 302c349dbc7Sjsg enum gpio_id id = gpio->id; 303c349dbc7Sjsg uint32_t en = gpio->en; 304c349dbc7Sjsg enum gpio_mode mode = gpio->mode; 305c349dbc7Sjsg 306c349dbc7Sjsg struct hw_gpio_pin **pin = &gpio->pin; 307c349dbc7Sjsg 308fb4d8502Sjsg 309fb4d8502Sjsg if (!service->busyness[id]) { 310fb4d8502Sjsg ASSERT_CRITICAL(false); 311fb4d8502Sjsg return GPIO_RESULT_OPEN_FAILED; 312fb4d8502Sjsg } 313fb4d8502Sjsg 314fb4d8502Sjsg if (is_pin_busy(service, id, en)) { 315fb4d8502Sjsg ASSERT_CRITICAL(false); 316fb4d8502Sjsg return GPIO_RESULT_DEVICE_BUSY; 317fb4d8502Sjsg } 318fb4d8502Sjsg 319fb4d8502Sjsg switch (id) { 320fb4d8502Sjsg case GPIO_ID_DDC_DATA: 321c349dbc7Sjsg *pin = service->factory.funcs->get_ddc_pin(gpio); 322c349dbc7Sjsg service->factory.funcs->define_ddc_registers(*pin, en); 323fb4d8502Sjsg break; 324fb4d8502Sjsg case GPIO_ID_DDC_CLOCK: 325c349dbc7Sjsg *pin = service->factory.funcs->get_ddc_pin(gpio); 326c349dbc7Sjsg service->factory.funcs->define_ddc_registers(*pin, en); 327fb4d8502Sjsg break; 328fb4d8502Sjsg case GPIO_ID_GENERIC: 329c349dbc7Sjsg *pin = service->factory.funcs->get_generic_pin(gpio); 330c349dbc7Sjsg service->factory.funcs->define_generic_registers(*pin, en); 331fb4d8502Sjsg break; 332fb4d8502Sjsg case GPIO_ID_HPD: 333c349dbc7Sjsg *pin = service->factory.funcs->get_hpd_pin(gpio); 334c349dbc7Sjsg service->factory.funcs->define_hpd_registers(*pin, en); 335fb4d8502Sjsg break; 336c349dbc7Sjsg 337c349dbc7Sjsg //TODO: gsl and sync support? create_sync and create_gsl are NULL 338fb4d8502Sjsg case GPIO_ID_SYNC: 339fb4d8502Sjsg case GPIO_ID_GSL: 340fb4d8502Sjsg break; 341fb4d8502Sjsg default: 342fb4d8502Sjsg ASSERT_CRITICAL(false); 343fb4d8502Sjsg return GPIO_RESULT_NON_SPECIFIC_ERROR; 344fb4d8502Sjsg } 345fb4d8502Sjsg 346c349dbc7Sjsg if (!*pin) { 347fb4d8502Sjsg ASSERT_CRITICAL(false); 348fb4d8502Sjsg return GPIO_RESULT_NON_SPECIFIC_ERROR; 349fb4d8502Sjsg } 350fb4d8502Sjsg 351c349dbc7Sjsg if (!(*pin)->funcs->open(*pin, mode)) { 352fb4d8502Sjsg ASSERT_CRITICAL(false); 353c349dbc7Sjsg dal_gpio_service_close(service, pin); 354fb4d8502Sjsg return GPIO_RESULT_OPEN_FAILED; 355fb4d8502Sjsg } 356fb4d8502Sjsg 357fb4d8502Sjsg set_pin_busy(service, id, en); 358fb4d8502Sjsg return GPIO_RESULT_OK; 359fb4d8502Sjsg } 360fb4d8502Sjsg 361fb4d8502Sjsg void dal_gpio_service_close( 362fb4d8502Sjsg struct gpio_service *service, 363fb4d8502Sjsg struct hw_gpio_pin **ptr) 364fb4d8502Sjsg { 365fb4d8502Sjsg struct hw_gpio_pin *pin; 366fb4d8502Sjsg 367fb4d8502Sjsg if (!ptr) { 368fb4d8502Sjsg ASSERT_CRITICAL(false); 369fb4d8502Sjsg return; 370fb4d8502Sjsg } 371fb4d8502Sjsg 372fb4d8502Sjsg pin = *ptr; 373fb4d8502Sjsg 374fb4d8502Sjsg if (pin) { 375fb4d8502Sjsg set_pin_free(service, pin->id, pin->en); 376fb4d8502Sjsg 377fb4d8502Sjsg pin->funcs->close(pin); 378fb4d8502Sjsg 379c349dbc7Sjsg *ptr = NULL; 380fb4d8502Sjsg } 381fb4d8502Sjsg } 382fb4d8502Sjsg 383fb4d8502Sjsg enum dc_irq_source dal_irq_get_source( 384fb4d8502Sjsg const struct gpio *irq) 385fb4d8502Sjsg { 386fb4d8502Sjsg enum gpio_id id = dal_gpio_get_id(irq); 387fb4d8502Sjsg 388fb4d8502Sjsg switch (id) { 389fb4d8502Sjsg case GPIO_ID_HPD: 390fb4d8502Sjsg return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 + 391fb4d8502Sjsg dal_gpio_get_enum(irq)); 392fb4d8502Sjsg case GPIO_ID_GPIO_PAD: 393fb4d8502Sjsg return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 + 394fb4d8502Sjsg dal_gpio_get_enum(irq)); 395fb4d8502Sjsg default: 396fb4d8502Sjsg return DC_IRQ_SOURCE_INVALID; 397fb4d8502Sjsg } 398fb4d8502Sjsg } 399fb4d8502Sjsg 400fb4d8502Sjsg enum dc_irq_source dal_irq_get_rx_source( 401fb4d8502Sjsg const struct gpio *irq) 402fb4d8502Sjsg { 403fb4d8502Sjsg enum gpio_id id = dal_gpio_get_id(irq); 404fb4d8502Sjsg 405fb4d8502Sjsg switch (id) { 406fb4d8502Sjsg case GPIO_ID_HPD: 407fb4d8502Sjsg return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX + 408fb4d8502Sjsg dal_gpio_get_enum(irq)); 409fb4d8502Sjsg default: 410fb4d8502Sjsg return DC_IRQ_SOURCE_INVALID; 411fb4d8502Sjsg } 412fb4d8502Sjsg } 413fb4d8502Sjsg 414fb4d8502Sjsg enum gpio_result dal_irq_setup_hpd_filter( 415fb4d8502Sjsg struct gpio *irq, 416fb4d8502Sjsg struct gpio_hpd_config *config) 417fb4d8502Sjsg { 418fb4d8502Sjsg struct gpio_config_data config_data; 419fb4d8502Sjsg 420fb4d8502Sjsg if (!config) 421fb4d8502Sjsg return GPIO_RESULT_INVALID_DATA; 422fb4d8502Sjsg 423fb4d8502Sjsg config_data.type = GPIO_CONFIG_TYPE_HPD; 424fb4d8502Sjsg config_data.config.hpd = *config; 425fb4d8502Sjsg 426fb4d8502Sjsg return dal_gpio_set_config(irq, &config_data); 427fb4d8502Sjsg } 428fb4d8502Sjsg 429fb4d8502Sjsg /* 430fb4d8502Sjsg * @brief 431fb4d8502Sjsg * Creation and destruction 432fb4d8502Sjsg */ 433fb4d8502Sjsg 434fb4d8502Sjsg struct gpio *dal_gpio_create_irq( 435fb4d8502Sjsg struct gpio_service *service, 436fb4d8502Sjsg enum gpio_id id, 437fb4d8502Sjsg uint32_t en) 438fb4d8502Sjsg { 439fb4d8502Sjsg struct gpio *irq; 440fb4d8502Sjsg 441fb4d8502Sjsg switch (id) { 442fb4d8502Sjsg case GPIO_ID_HPD: 443fb4d8502Sjsg case GPIO_ID_GPIO_PAD: 444fb4d8502Sjsg break; 445fb4d8502Sjsg default: 446fb4d8502Sjsg id = GPIO_ID_HPD; 447fb4d8502Sjsg ASSERT_CRITICAL(false); 448fb4d8502Sjsg return NULL; 449fb4d8502Sjsg } 450fb4d8502Sjsg 451fb4d8502Sjsg irq = dal_gpio_create( 452fb4d8502Sjsg service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 453fb4d8502Sjsg 454fb4d8502Sjsg if (irq) 455fb4d8502Sjsg return irq; 456fb4d8502Sjsg 457fb4d8502Sjsg ASSERT_CRITICAL(false); 458fb4d8502Sjsg return NULL; 459fb4d8502Sjsg } 460fb4d8502Sjsg 461fb4d8502Sjsg void dal_gpio_destroy_irq( 462fb4d8502Sjsg struct gpio **irq) 463fb4d8502Sjsg { 464fb4d8502Sjsg if (!irq || !*irq) { 465fb4d8502Sjsg ASSERT_CRITICAL(false); 466fb4d8502Sjsg return; 467fb4d8502Sjsg } 468fb4d8502Sjsg 469fb4d8502Sjsg dal_gpio_destroy(irq); 470fb4d8502Sjsg kfree(*irq); 471fb4d8502Sjsg 472fb4d8502Sjsg *irq = NULL; 473fb4d8502Sjsg } 474fb4d8502Sjsg 475fb4d8502Sjsg struct ddc *dal_gpio_create_ddc( 476fb4d8502Sjsg struct gpio_service *service, 477fb4d8502Sjsg uint32_t offset, 478fb4d8502Sjsg uint32_t mask, 479fb4d8502Sjsg struct gpio_ddc_hw_info *info) 480fb4d8502Sjsg { 481fb4d8502Sjsg enum gpio_id id; 482fb4d8502Sjsg uint32_t en; 483fb4d8502Sjsg struct ddc *ddc; 484fb4d8502Sjsg 485fb4d8502Sjsg if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) 486fb4d8502Sjsg return NULL; 487fb4d8502Sjsg 488fb4d8502Sjsg ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL); 489fb4d8502Sjsg 490fb4d8502Sjsg if (!ddc) { 491fb4d8502Sjsg BREAK_TO_DEBUGGER(); 492fb4d8502Sjsg return NULL; 493fb4d8502Sjsg } 494fb4d8502Sjsg 495fb4d8502Sjsg ddc->pin_data = dal_gpio_create( 496fb4d8502Sjsg service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 497fb4d8502Sjsg 498fb4d8502Sjsg if (!ddc->pin_data) { 499fb4d8502Sjsg BREAK_TO_DEBUGGER(); 500fb4d8502Sjsg goto failure_1; 501fb4d8502Sjsg } 502fb4d8502Sjsg 503fb4d8502Sjsg ddc->pin_clock = dal_gpio_create( 504fb4d8502Sjsg service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 505fb4d8502Sjsg 506fb4d8502Sjsg if (!ddc->pin_clock) { 507fb4d8502Sjsg BREAK_TO_DEBUGGER(); 508fb4d8502Sjsg goto failure_2; 509fb4d8502Sjsg } 510fb4d8502Sjsg 511fb4d8502Sjsg ddc->hw_info = *info; 512fb4d8502Sjsg 513fb4d8502Sjsg ddc->ctx = service->ctx; 514fb4d8502Sjsg 515fb4d8502Sjsg return ddc; 516fb4d8502Sjsg 517fb4d8502Sjsg failure_2: 518fb4d8502Sjsg dal_gpio_destroy(&ddc->pin_data); 519fb4d8502Sjsg 520fb4d8502Sjsg failure_1: 521fb4d8502Sjsg kfree(ddc); 522fb4d8502Sjsg 523fb4d8502Sjsg return NULL; 524fb4d8502Sjsg } 525fb4d8502Sjsg 526fb4d8502Sjsg void dal_gpio_destroy_ddc( 527fb4d8502Sjsg struct ddc **ddc) 528fb4d8502Sjsg { 529fb4d8502Sjsg if (!ddc || !*ddc) { 530fb4d8502Sjsg BREAK_TO_DEBUGGER(); 531fb4d8502Sjsg return; 532fb4d8502Sjsg } 533fb4d8502Sjsg 534fb4d8502Sjsg dal_ddc_close(*ddc); 535fb4d8502Sjsg dal_gpio_destroy(&(*ddc)->pin_data); 536fb4d8502Sjsg dal_gpio_destroy(&(*ddc)->pin_clock); 537fb4d8502Sjsg kfree(*ddc); 538fb4d8502Sjsg 539fb4d8502Sjsg *ddc = NULL; 540fb4d8502Sjsg } 541fb4d8502Sjsg 542fb4d8502Sjsg enum gpio_result dal_ddc_open( 543fb4d8502Sjsg struct ddc *ddc, 544fb4d8502Sjsg enum gpio_mode mode, 545fb4d8502Sjsg enum gpio_ddc_config_type config_type) 546fb4d8502Sjsg { 547fb4d8502Sjsg enum gpio_result result; 548fb4d8502Sjsg 549fb4d8502Sjsg struct gpio_config_data config_data; 550fb4d8502Sjsg struct hw_gpio *hw_data; 551fb4d8502Sjsg struct hw_gpio *hw_clock; 552fb4d8502Sjsg 553fb4d8502Sjsg result = dal_gpio_open_ex(ddc->pin_data, mode); 554fb4d8502Sjsg 555fb4d8502Sjsg if (result != GPIO_RESULT_OK) { 556fb4d8502Sjsg BREAK_TO_DEBUGGER(); 557fb4d8502Sjsg return result; 558fb4d8502Sjsg } 559fb4d8502Sjsg 560fb4d8502Sjsg result = dal_gpio_open_ex(ddc->pin_clock, mode); 561fb4d8502Sjsg 562fb4d8502Sjsg if (result != GPIO_RESULT_OK) { 563fb4d8502Sjsg BREAK_TO_DEBUGGER(); 564fb4d8502Sjsg goto failure; 565fb4d8502Sjsg } 566fb4d8502Sjsg 567fb4d8502Sjsg /* DDC clock and data pins should belong 568fb4d8502Sjsg * to the same DDC block id, 569fb4d8502Sjsg * we use the data pin to set the pad mode. */ 570fb4d8502Sjsg 571fb4d8502Sjsg if (mode == GPIO_MODE_INPUT) 572fb4d8502Sjsg /* this is from detect_sink_type, 573fb4d8502Sjsg * we need extra delay there */ 574fb4d8502Sjsg config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; 575fb4d8502Sjsg else 576fb4d8502Sjsg config_data.type = GPIO_CONFIG_TYPE_DDC; 577fb4d8502Sjsg 578fb4d8502Sjsg config_data.config.ddc.type = config_type; 579fb4d8502Sjsg 580fb4d8502Sjsg hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin); 581fb4d8502Sjsg hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin); 582fb4d8502Sjsg 583fb4d8502Sjsg config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0; 584fb4d8502Sjsg config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0; 585fb4d8502Sjsg 586fb4d8502Sjsg result = dal_gpio_set_config(ddc->pin_data, &config_data); 587fb4d8502Sjsg 588fb4d8502Sjsg if (result == GPIO_RESULT_OK) 589fb4d8502Sjsg return result; 590fb4d8502Sjsg 591fb4d8502Sjsg BREAK_TO_DEBUGGER(); 592fb4d8502Sjsg 593fb4d8502Sjsg dal_gpio_close(ddc->pin_clock); 594fb4d8502Sjsg 595fb4d8502Sjsg failure: 596fb4d8502Sjsg dal_gpio_close(ddc->pin_data); 597fb4d8502Sjsg 598fb4d8502Sjsg return result; 599fb4d8502Sjsg } 600fb4d8502Sjsg 601fb4d8502Sjsg enum gpio_result dal_ddc_change_mode( 602fb4d8502Sjsg struct ddc *ddc, 603fb4d8502Sjsg enum gpio_mode mode) 604fb4d8502Sjsg { 605fb4d8502Sjsg enum gpio_result result; 606fb4d8502Sjsg 607fb4d8502Sjsg enum gpio_mode original_mode = 608fb4d8502Sjsg dal_gpio_get_mode(ddc->pin_data); 609fb4d8502Sjsg 610fb4d8502Sjsg result = dal_gpio_change_mode(ddc->pin_data, mode); 611fb4d8502Sjsg 612fb4d8502Sjsg /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR 613fb4d8502Sjsg * in case of failures; 614fb4d8502Sjsg * set_mode() is so that, in case of failure, 615fb4d8502Sjsg * we must explicitly set original mode */ 616fb4d8502Sjsg 617fb4d8502Sjsg if (result != GPIO_RESULT_OK) 618fb4d8502Sjsg goto failure; 619fb4d8502Sjsg 620fb4d8502Sjsg result = dal_gpio_change_mode(ddc->pin_clock, mode); 621fb4d8502Sjsg 622fb4d8502Sjsg if (result == GPIO_RESULT_OK) 623fb4d8502Sjsg return result; 624fb4d8502Sjsg 625fb4d8502Sjsg dal_gpio_change_mode(ddc->pin_clock, original_mode); 626fb4d8502Sjsg 627fb4d8502Sjsg failure: 628fb4d8502Sjsg dal_gpio_change_mode(ddc->pin_data, original_mode); 629fb4d8502Sjsg 630fb4d8502Sjsg return result; 631fb4d8502Sjsg } 632fb4d8502Sjsg 633fb4d8502Sjsg enum gpio_ddc_line dal_ddc_get_line( 634fb4d8502Sjsg const struct ddc *ddc) 635fb4d8502Sjsg { 636fb4d8502Sjsg return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data); 637fb4d8502Sjsg } 638fb4d8502Sjsg 639fb4d8502Sjsg enum gpio_result dal_ddc_set_config( 640fb4d8502Sjsg struct ddc *ddc, 641fb4d8502Sjsg enum gpio_ddc_config_type config_type) 642fb4d8502Sjsg { 643fb4d8502Sjsg struct gpio_config_data config_data; 644fb4d8502Sjsg 645fb4d8502Sjsg config_data.type = GPIO_CONFIG_TYPE_DDC; 646fb4d8502Sjsg 647fb4d8502Sjsg config_data.config.ddc.type = config_type; 648fb4d8502Sjsg config_data.config.ddc.data_en_bit_present = false; 649fb4d8502Sjsg config_data.config.ddc.clock_en_bit_present = false; 650fb4d8502Sjsg 651fb4d8502Sjsg return dal_gpio_set_config(ddc->pin_data, &config_data); 652fb4d8502Sjsg } 653fb4d8502Sjsg 654fb4d8502Sjsg void dal_ddc_close( 655fb4d8502Sjsg struct ddc *ddc) 656fb4d8502Sjsg { 6571bb76ff1Sjsg if (ddc != NULL) { 658fb4d8502Sjsg dal_gpio_close(ddc->pin_clock); 659fb4d8502Sjsg dal_gpio_close(ddc->pin_data); 660fb4d8502Sjsg } 6611bb76ff1Sjsg } 662fb4d8502Sjsg 663