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 = kzalloc(number_of_uints * sizeof(uint32_t), 102 GFP_KERNEL); 103 104 if (!slot) { 105 BREAK_TO_DEBUGGER(); 106 goto failure_2; 107 } 108 109 do { 110 slot[index_of_uint] = 0; 111 112 ++index_of_uint; 113 } while (index_of_uint < number_of_uints); 114 } else 115 slot = NULL; 116 117 service->busyness[index_of_id] = slot; 118 119 ++index_of_id; 120 } while (index_of_id < GPIO_ID_COUNT); 121 } 122 123 return service; 124 125 failure_2: 126 while (index_of_id) { 127 uint32_t *slot; 128 129 --index_of_id; 130 131 slot = service->busyness[index_of_id]; 132 133 kfree(slot); 134 } 135 136 failure_1: 137 kfree(service); 138 139 return NULL; 140 } 141 142 struct gpio *dal_gpio_service_create_irq( 143 struct gpio_service *service, 144 uint32_t offset, 145 uint32_t mask) 146 { 147 enum gpio_id id; 148 uint32_t en; 149 150 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) { 151 ASSERT_CRITICAL(false); 152 return NULL; 153 } 154 155 return dal_gpio_create_irq(service, id, en); 156 } 157 158 void dal_gpio_service_destroy( 159 struct gpio_service **ptr) 160 { 161 if (!ptr || !*ptr) { 162 BREAK_TO_DEBUGGER(); 163 return; 164 } 165 166 /* free business storage */ 167 { 168 uint32_t index_of_id = 0; 169 170 do { 171 uint32_t *slot = (*ptr)->busyness[index_of_id]; 172 173 kfree(slot); 174 175 ++index_of_id; 176 } while (index_of_id < GPIO_ID_COUNT); 177 } 178 179 kfree(*ptr); 180 181 *ptr = NULL; 182 } 183 184 /* 185 * @brief 186 * Private API. 187 */ 188 189 static bool is_pin_busy( 190 const struct gpio_service *service, 191 enum gpio_id id, 192 uint32_t en) 193 { 194 const uint32_t bits_per_uint = sizeof(uint32_t) << 3; 195 196 const uint32_t *slot = service->busyness[id] + (en / bits_per_uint); 197 198 return 0 != (*slot & (1 << (en % bits_per_uint))); 199 } 200 201 static void set_pin_busy( 202 struct gpio_service *service, 203 enum gpio_id id, 204 uint32_t en) 205 { 206 const uint32_t bits_per_uint = sizeof(uint32_t) << 3; 207 208 service->busyness[id][en / bits_per_uint] |= 209 (1 << (en % bits_per_uint)); 210 } 211 212 static void set_pin_free( 213 struct gpio_service *service, 214 enum gpio_id id, 215 uint32_t en) 216 { 217 const uint32_t bits_per_uint = sizeof(uint32_t) << 3; 218 219 service->busyness[id][en / bits_per_uint] &= 220 ~(1 << (en % bits_per_uint)); 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 ASSERT_CRITICAL(false); 378 return NULL; 379 } 380 381 irq = dal_gpio_create( 382 service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 383 384 if (irq) 385 return irq; 386 387 ASSERT_CRITICAL(false); 388 return NULL; 389 } 390 391 void dal_gpio_destroy_irq( 392 struct gpio **irq) 393 { 394 if (!irq || !*irq) { 395 ASSERT_CRITICAL(false); 396 return; 397 } 398 399 dal_gpio_close(*irq); 400 dal_gpio_destroy(irq); 401 kfree(*irq); 402 403 *irq = NULL; 404 } 405 406 struct ddc *dal_gpio_create_ddc( 407 struct gpio_service *service, 408 uint32_t offset, 409 uint32_t mask, 410 struct gpio_ddc_hw_info *info) 411 { 412 enum gpio_id id; 413 uint32_t en; 414 struct ddc *ddc; 415 416 if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) 417 return NULL; 418 419 ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL); 420 421 if (!ddc) { 422 BREAK_TO_DEBUGGER(); 423 return NULL; 424 } 425 426 ddc->pin_data = dal_gpio_create( 427 service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 428 429 if (!ddc->pin_data) { 430 BREAK_TO_DEBUGGER(); 431 goto failure_1; 432 } 433 434 ddc->pin_clock = dal_gpio_create( 435 service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); 436 437 if (!ddc->pin_clock) { 438 BREAK_TO_DEBUGGER(); 439 goto failure_2; 440 } 441 442 ddc->hw_info = *info; 443 444 ddc->ctx = service->ctx; 445 446 return ddc; 447 448 failure_2: 449 dal_gpio_destroy(&ddc->pin_data); 450 451 failure_1: 452 kfree(ddc); 453 454 return NULL; 455 } 456 457 void dal_gpio_destroy_ddc( 458 struct ddc **ddc) 459 { 460 if (!ddc || !*ddc) { 461 BREAK_TO_DEBUGGER(); 462 return; 463 } 464 465 dal_ddc_close(*ddc); 466 dal_gpio_destroy(&(*ddc)->pin_data); 467 dal_gpio_destroy(&(*ddc)->pin_clock); 468 kfree(*ddc); 469 470 *ddc = NULL; 471 } 472 473 enum gpio_result dal_ddc_open( 474 struct ddc *ddc, 475 enum gpio_mode mode, 476 enum gpio_ddc_config_type config_type) 477 { 478 enum gpio_result result; 479 480 struct gpio_config_data config_data; 481 struct hw_gpio *hw_data; 482 struct hw_gpio *hw_clock; 483 484 result = dal_gpio_open_ex(ddc->pin_data, mode); 485 486 if (result != GPIO_RESULT_OK) { 487 BREAK_TO_DEBUGGER(); 488 return result; 489 } 490 491 result = dal_gpio_open_ex(ddc->pin_clock, mode); 492 493 if (result != GPIO_RESULT_OK) { 494 BREAK_TO_DEBUGGER(); 495 goto failure; 496 } 497 498 /* DDC clock and data pins should belong 499 * to the same DDC block id, 500 * we use the data pin to set the pad mode. */ 501 502 if (mode == GPIO_MODE_INPUT) 503 /* this is from detect_sink_type, 504 * we need extra delay there */ 505 config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE; 506 else 507 config_data.type = GPIO_CONFIG_TYPE_DDC; 508 509 config_data.config.ddc.type = config_type; 510 511 hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin); 512 hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin); 513 514 config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0; 515 config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0; 516 517 result = dal_gpio_set_config(ddc->pin_data, &config_data); 518 519 if (result == GPIO_RESULT_OK) 520 return result; 521 522 BREAK_TO_DEBUGGER(); 523 524 dal_gpio_close(ddc->pin_clock); 525 526 failure: 527 dal_gpio_close(ddc->pin_data); 528 529 return result; 530 } 531 532 enum gpio_result dal_ddc_change_mode( 533 struct ddc *ddc, 534 enum gpio_mode mode) 535 { 536 enum gpio_result result; 537 538 enum gpio_mode original_mode = 539 dal_gpio_get_mode(ddc->pin_data); 540 541 result = dal_gpio_change_mode(ddc->pin_data, mode); 542 543 /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR 544 * in case of failures; 545 * set_mode() is so that, in case of failure, 546 * we must explicitly set original mode */ 547 548 if (result != GPIO_RESULT_OK) 549 goto failure; 550 551 result = dal_gpio_change_mode(ddc->pin_clock, mode); 552 553 if (result == GPIO_RESULT_OK) 554 return result; 555 556 dal_gpio_change_mode(ddc->pin_clock, original_mode); 557 558 failure: 559 dal_gpio_change_mode(ddc->pin_data, original_mode); 560 561 return result; 562 } 563 564 enum gpio_ddc_line dal_ddc_get_line( 565 const struct ddc *ddc) 566 { 567 return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data); 568 } 569 570 enum gpio_result dal_ddc_set_config( 571 struct ddc *ddc, 572 enum gpio_ddc_config_type config_type) 573 { 574 struct gpio_config_data config_data; 575 576 config_data.type = GPIO_CONFIG_TYPE_DDC; 577 578 config_data.config.ddc.type = config_type; 579 config_data.config.ddc.data_en_bit_present = false; 580 config_data.config.ddc.clock_en_bit_present = false; 581 582 return dal_gpio_set_config(ddc->pin_data, &config_data); 583 } 584 585 void dal_ddc_close( 586 struct ddc *ddc) 587 { 588 dal_gpio_close(ddc->pin_clock); 589 dal_gpio_close(ddc->pin_data); 590 } 591 592