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