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