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