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