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