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