Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 /*
0027  * Pre-requisites: headers required by header of this unit
0028  */
0029 
0030 #include "dm_services.h"
0031 #include "include/gpio_interface.h"
0032 #include "include/gpio_service_interface.h"
0033 #include "hw_translate.h"
0034 #include "hw_factory.h"
0035 
0036 /*
0037  * Header of this unit
0038  */
0039 
0040 #include "gpio_service.h"
0041 
0042 /*
0043  * Post-requisites: headers required by this unit
0044  */
0045 
0046 #include "hw_gpio.h"
0047 
0048 /*
0049  * @brief
0050  * Public API.
0051  */
0052 
0053 struct gpio_service *dal_gpio_service_create(
0054     enum dce_version dce_version,
0055     enum dce_environment dce_environment,
0056     struct dc_context *ctx)
0057 {
0058     struct gpio_service *service;
0059     uint32_t index_of_id;
0060 
0061     service = kzalloc(sizeof(struct gpio_service), GFP_KERNEL);
0062 
0063     if (!service) {
0064         BREAK_TO_DEBUGGER();
0065         return NULL;
0066     }
0067 
0068     if (!dal_hw_translate_init(&service->translate, dce_version,
0069             dce_environment)) {
0070         BREAK_TO_DEBUGGER();
0071         goto failure_1;
0072     }
0073 
0074     if (!dal_hw_factory_init(&service->factory, dce_version,
0075             dce_environment)) {
0076         BREAK_TO_DEBUGGER();
0077         goto failure_1;
0078     }
0079 
0080     /* allocate and initialize busyness storage */
0081     {
0082         index_of_id = 0;
0083         service->ctx = ctx;
0084 
0085         do {
0086             uint32_t number_of_bits =
0087                 service->factory.number_of_pins[index_of_id];
0088             uint32_t i = 0;
0089 
0090             if (number_of_bits)  {
0091                 service->busyness[index_of_id] =
0092                     kcalloc(number_of_bits, sizeof(char),
0093                         GFP_KERNEL);
0094 
0095                 if (!service->busyness[index_of_id]) {
0096                     BREAK_TO_DEBUGGER();
0097                     goto failure_2;
0098                 }
0099 
0100                 do {
0101                     service->busyness[index_of_id][i] = 0;
0102                     ++i;
0103                 } while (i < number_of_bits);
0104             } else {
0105                 service->busyness[index_of_id] = NULL;
0106             }
0107 
0108             ++index_of_id;
0109         } while (index_of_id < GPIO_ID_COUNT);
0110     }
0111 
0112     return service;
0113 
0114 failure_2:
0115     while (index_of_id) {
0116         --index_of_id;
0117         kfree(service->busyness[index_of_id]);
0118     }
0119 
0120 failure_1:
0121     kfree(service);
0122 
0123     return NULL;
0124 }
0125 
0126 struct gpio *dal_gpio_service_create_irq(
0127     struct gpio_service *service,
0128     uint32_t offset,
0129     uint32_t mask)
0130 {
0131     enum gpio_id id;
0132     uint32_t en;
0133 
0134     if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
0135         ASSERT_CRITICAL(false);
0136         return NULL;
0137     }
0138 
0139     return dal_gpio_create_irq(service, id, en);
0140 }
0141 
0142 struct gpio *dal_gpio_service_create_generic_mux(
0143     struct gpio_service *service,
0144     uint32_t offset,
0145     uint32_t mask)
0146 {
0147     enum gpio_id id;
0148     uint32_t en;
0149     struct gpio *generic;
0150 
0151     if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) {
0152         ASSERT_CRITICAL(false);
0153         return NULL;
0154     }
0155 
0156     generic = dal_gpio_create(
0157         service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
0158 
0159     return generic;
0160 }
0161 
0162 void dal_gpio_destroy_generic_mux(
0163     struct gpio **mux)
0164 {
0165     if (!mux || !*mux) {
0166         ASSERT_CRITICAL(false);
0167         return;
0168     }
0169 
0170     dal_gpio_destroy(mux);
0171     kfree(*mux);
0172 
0173     *mux = NULL;
0174 }
0175 
0176 struct gpio_pin_info dal_gpio_get_generic_pin_info(
0177     struct gpio_service *service,
0178     enum gpio_id id,
0179     uint32_t en)
0180 {
0181     struct gpio_pin_info pin;
0182 
0183     if (service->translate.funcs->id_to_offset) {
0184         service->translate.funcs->id_to_offset(id, en, &pin);
0185     } else {
0186         pin.mask = 0xFFFFFFFF;
0187         pin.offset = 0xFFFFFFFF;
0188     }
0189 
0190     return pin;
0191 }
0192 
0193 void dal_gpio_service_destroy(
0194     struct gpio_service **ptr)
0195 {
0196     if (!ptr || !*ptr) {
0197         BREAK_TO_DEBUGGER();
0198         return;
0199     }
0200 
0201     /* free business storage */
0202     {
0203         uint32_t index_of_id = 0;
0204 
0205         do {
0206             kfree((*ptr)->busyness[index_of_id]);
0207 
0208             ++index_of_id;
0209         } while (index_of_id < GPIO_ID_COUNT);
0210     }
0211 
0212     kfree(*ptr);
0213 
0214     *ptr = NULL;
0215 }
0216 
0217 enum gpio_result dal_mux_setup_config(
0218     struct gpio *mux,
0219     struct gpio_generic_mux_config *config)
0220 {
0221     struct gpio_config_data config_data;
0222 
0223     if (!config)
0224         return GPIO_RESULT_INVALID_DATA;
0225 
0226     config_data.config.generic_mux = *config;
0227     config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX;
0228 
0229     return dal_gpio_set_config(mux, &config_data);
0230 }
0231 
0232 /*
0233  * @brief
0234  * Private API.
0235  */
0236 
0237 static bool is_pin_busy(
0238     const struct gpio_service *service,
0239     enum gpio_id id,
0240     uint32_t en)
0241 {
0242     return service->busyness[id][en];
0243 }
0244 
0245 static void set_pin_busy(
0246     struct gpio_service *service,
0247     enum gpio_id id,
0248     uint32_t en)
0249 {
0250     service->busyness[id][en] = true;
0251 }
0252 
0253 static void set_pin_free(
0254     struct gpio_service *service,
0255     enum gpio_id id,
0256     uint32_t en)
0257 {
0258     service->busyness[id][en] = false;
0259 }
0260 
0261 enum gpio_result dal_gpio_service_lock(
0262     struct gpio_service *service,
0263     enum gpio_id id,
0264     uint32_t en)
0265 {
0266     if (!service->busyness[id]) {
0267         ASSERT_CRITICAL(false);
0268         return GPIO_RESULT_OPEN_FAILED;
0269     }
0270 
0271     set_pin_busy(service, id, en);
0272     return GPIO_RESULT_OK;
0273 }
0274 
0275 enum gpio_result dal_gpio_service_unlock(
0276     struct gpio_service *service,
0277     enum gpio_id id,
0278     uint32_t en)
0279 {
0280     if (!service->busyness[id]) {
0281         ASSERT_CRITICAL(false);
0282         return GPIO_RESULT_OPEN_FAILED;
0283     }
0284 
0285     set_pin_free(service, id, en);
0286     return GPIO_RESULT_OK;
0287 }
0288 
0289 enum gpio_result dal_gpio_service_open(
0290     struct gpio *gpio)
0291 {
0292     struct gpio_service *service = gpio->service;
0293     enum gpio_id id = gpio->id;
0294     uint32_t en = gpio->en;
0295     enum gpio_mode mode = gpio->mode;
0296 
0297     struct hw_gpio_pin **pin = &gpio->pin;
0298 
0299 
0300     if (!service->busyness[id]) {
0301         ASSERT_CRITICAL(false);
0302         return GPIO_RESULT_OPEN_FAILED;
0303     }
0304 
0305     if (is_pin_busy(service, id, en)) {
0306         ASSERT_CRITICAL(false);
0307         return GPIO_RESULT_DEVICE_BUSY;
0308     }
0309 
0310     switch (id) {
0311     case GPIO_ID_DDC_DATA:
0312         *pin = service->factory.funcs->get_ddc_pin(gpio);
0313         service->factory.funcs->define_ddc_registers(*pin, en);
0314     break;
0315     case GPIO_ID_DDC_CLOCK:
0316         *pin = service->factory.funcs->get_ddc_pin(gpio);
0317         service->factory.funcs->define_ddc_registers(*pin, en);
0318     break;
0319     case GPIO_ID_GENERIC:
0320         *pin = service->factory.funcs->get_generic_pin(gpio);
0321         service->factory.funcs->define_generic_registers(*pin, en);
0322     break;
0323     case GPIO_ID_HPD:
0324         *pin = service->factory.funcs->get_hpd_pin(gpio);
0325         service->factory.funcs->define_hpd_registers(*pin, en);
0326     break;
0327 
0328     //TODO: gsl and sync support? create_sync and create_gsl are NULL
0329     case GPIO_ID_SYNC:
0330     case GPIO_ID_GSL:
0331     break;
0332     default:
0333         ASSERT_CRITICAL(false);
0334         return GPIO_RESULT_NON_SPECIFIC_ERROR;
0335     }
0336 
0337     if (!*pin) {
0338         ASSERT_CRITICAL(false);
0339         return GPIO_RESULT_NON_SPECIFIC_ERROR;
0340     }
0341 
0342     if (!(*pin)->funcs->open(*pin, mode)) {
0343         ASSERT_CRITICAL(false);
0344         dal_gpio_service_close(service, pin);
0345         return GPIO_RESULT_OPEN_FAILED;
0346     }
0347 
0348     set_pin_busy(service, id, en);
0349     return GPIO_RESULT_OK;
0350 }
0351 
0352 void dal_gpio_service_close(
0353     struct gpio_service *service,
0354     struct hw_gpio_pin **ptr)
0355 {
0356     struct hw_gpio_pin *pin;
0357 
0358     if (!ptr) {
0359         ASSERT_CRITICAL(false);
0360         return;
0361     }
0362 
0363     pin = *ptr;
0364 
0365     if (pin) {
0366         set_pin_free(service, pin->id, pin->en);
0367 
0368         pin->funcs->close(pin);
0369 
0370         *ptr = NULL;
0371     }
0372 }
0373 
0374 enum dc_irq_source dal_irq_get_source(
0375     const struct gpio *irq)
0376 {
0377     enum gpio_id id = dal_gpio_get_id(irq);
0378 
0379     switch (id) {
0380     case GPIO_ID_HPD:
0381         return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1 +
0382             dal_gpio_get_enum(irq));
0383     case GPIO_ID_GPIO_PAD:
0384         return (enum dc_irq_source)(DC_IRQ_SOURCE_GPIOPAD0 +
0385             dal_gpio_get_enum(irq));
0386     default:
0387         return DC_IRQ_SOURCE_INVALID;
0388     }
0389 }
0390 
0391 enum dc_irq_source dal_irq_get_rx_source(
0392     const struct gpio *irq)
0393 {
0394     enum gpio_id id = dal_gpio_get_id(irq);
0395 
0396     switch (id) {
0397     case GPIO_ID_HPD:
0398         return (enum dc_irq_source)(DC_IRQ_SOURCE_HPD1RX +
0399             dal_gpio_get_enum(irq));
0400     default:
0401         return DC_IRQ_SOURCE_INVALID;
0402     }
0403 }
0404 
0405 enum gpio_result dal_irq_setup_hpd_filter(
0406     struct gpio *irq,
0407     struct gpio_hpd_config *config)
0408 {
0409     struct gpio_config_data config_data;
0410 
0411     if (!config)
0412         return GPIO_RESULT_INVALID_DATA;
0413 
0414     config_data.type = GPIO_CONFIG_TYPE_HPD;
0415     config_data.config.hpd = *config;
0416 
0417     return dal_gpio_set_config(irq, &config_data);
0418 }
0419 
0420 /*
0421  * @brief
0422  * Creation and destruction
0423  */
0424 
0425 struct gpio *dal_gpio_create_irq(
0426     struct gpio_service *service,
0427     enum gpio_id id,
0428     uint32_t en)
0429 {
0430     struct gpio *irq;
0431 
0432     switch (id) {
0433     case GPIO_ID_HPD:
0434     case GPIO_ID_GPIO_PAD:
0435     break;
0436     default:
0437         id = GPIO_ID_HPD;
0438         ASSERT_CRITICAL(false);
0439         return NULL;
0440     }
0441 
0442     irq = dal_gpio_create(
0443         service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
0444 
0445     if (irq)
0446         return irq;
0447 
0448     ASSERT_CRITICAL(false);
0449     return NULL;
0450 }
0451 
0452 void dal_gpio_destroy_irq(
0453     struct gpio **irq)
0454 {
0455     if (!irq || !*irq) {
0456         ASSERT_CRITICAL(false);
0457         return;
0458     }
0459 
0460     dal_gpio_destroy(irq);
0461     kfree(*irq);
0462 
0463     *irq = NULL;
0464 }
0465 
0466 struct ddc *dal_gpio_create_ddc(
0467     struct gpio_service *service,
0468     uint32_t offset,
0469     uint32_t mask,
0470     struct gpio_ddc_hw_info *info)
0471 {
0472     enum gpio_id id;
0473     uint32_t en;
0474     struct ddc *ddc;
0475 
0476     if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en))
0477         return NULL;
0478 
0479     ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL);
0480 
0481     if (!ddc) {
0482         BREAK_TO_DEBUGGER();
0483         return NULL;
0484     }
0485 
0486     ddc->pin_data = dal_gpio_create(
0487         service, GPIO_ID_DDC_DATA, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
0488 
0489     if (!ddc->pin_data) {
0490         BREAK_TO_DEBUGGER();
0491         goto failure_1;
0492     }
0493 
0494     ddc->pin_clock = dal_gpio_create(
0495         service, GPIO_ID_DDC_CLOCK, en, GPIO_PIN_OUTPUT_STATE_DEFAULT);
0496 
0497     if (!ddc->pin_clock) {
0498         BREAK_TO_DEBUGGER();
0499         goto failure_2;
0500     }
0501 
0502     ddc->hw_info = *info;
0503 
0504     ddc->ctx = service->ctx;
0505 
0506     return ddc;
0507 
0508 failure_2:
0509     dal_gpio_destroy(&ddc->pin_data);
0510 
0511 failure_1:
0512     kfree(ddc);
0513 
0514     return NULL;
0515 }
0516 
0517 void dal_gpio_destroy_ddc(
0518     struct ddc **ddc)
0519 {
0520     if (!ddc || !*ddc) {
0521         BREAK_TO_DEBUGGER();
0522         return;
0523     }
0524 
0525     dal_ddc_close(*ddc);
0526     dal_gpio_destroy(&(*ddc)->pin_data);
0527     dal_gpio_destroy(&(*ddc)->pin_clock);
0528     kfree(*ddc);
0529 
0530     *ddc = NULL;
0531 }
0532 
0533 enum gpio_result dal_ddc_open(
0534     struct ddc *ddc,
0535     enum gpio_mode mode,
0536     enum gpio_ddc_config_type config_type)
0537 {
0538     enum gpio_result result;
0539 
0540     struct gpio_config_data config_data;
0541     struct hw_gpio *hw_data;
0542     struct hw_gpio *hw_clock;
0543 
0544     result = dal_gpio_open_ex(ddc->pin_data, mode);
0545 
0546     if (result != GPIO_RESULT_OK) {
0547         BREAK_TO_DEBUGGER();
0548         return result;
0549     }
0550 
0551     result = dal_gpio_open_ex(ddc->pin_clock, mode);
0552 
0553     if (result != GPIO_RESULT_OK) {
0554         BREAK_TO_DEBUGGER();
0555         goto failure;
0556     }
0557 
0558     /* DDC clock and data pins should belong
0559      * to the same DDC block id,
0560      * we use the data pin to set the pad mode. */
0561 
0562     if (mode == GPIO_MODE_INPUT)
0563         /* this is from detect_sink_type,
0564          * we need extra delay there */
0565         config_data.type = GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE;
0566     else
0567         config_data.type = GPIO_CONFIG_TYPE_DDC;
0568 
0569     config_data.config.ddc.type = config_type;
0570 
0571     hw_data = FROM_HW_GPIO_PIN(ddc->pin_data->pin);
0572     hw_clock = FROM_HW_GPIO_PIN(ddc->pin_clock->pin);
0573 
0574     config_data.config.ddc.data_en_bit_present = hw_data->store.en != 0;
0575     config_data.config.ddc.clock_en_bit_present = hw_clock->store.en != 0;
0576 
0577     result = dal_gpio_set_config(ddc->pin_data, &config_data);
0578 
0579     if (result == GPIO_RESULT_OK)
0580         return result;
0581 
0582     BREAK_TO_DEBUGGER();
0583 
0584     dal_gpio_close(ddc->pin_clock);
0585 
0586 failure:
0587     dal_gpio_close(ddc->pin_data);
0588 
0589     return result;
0590 }
0591 
0592 enum gpio_result dal_ddc_change_mode(
0593     struct ddc *ddc,
0594     enum gpio_mode mode)
0595 {
0596     enum gpio_result result;
0597 
0598     enum gpio_mode original_mode =
0599         dal_gpio_get_mode(ddc->pin_data);
0600 
0601     result = dal_gpio_change_mode(ddc->pin_data, mode);
0602 
0603     /* [anaumov] DAL2 code returns GPIO_RESULT_NON_SPECIFIC_ERROR
0604      * in case of failures;
0605      * set_mode() is so that, in case of failure,
0606      * we must explicitly set original mode */
0607 
0608     if (result != GPIO_RESULT_OK)
0609         goto failure;
0610 
0611     result = dal_gpio_change_mode(ddc->pin_clock, mode);
0612 
0613     if (result == GPIO_RESULT_OK)
0614         return result;
0615 
0616     dal_gpio_change_mode(ddc->pin_clock, original_mode);
0617 
0618 failure:
0619     dal_gpio_change_mode(ddc->pin_data, original_mode);
0620 
0621     return result;
0622 }
0623 
0624 enum gpio_ddc_line dal_ddc_get_line(
0625     const struct ddc *ddc)
0626 {
0627     return (enum gpio_ddc_line)dal_gpio_get_enum(ddc->pin_data);
0628 }
0629 
0630 enum gpio_result dal_ddc_set_config(
0631     struct ddc *ddc,
0632     enum gpio_ddc_config_type config_type)
0633 {
0634     struct gpio_config_data config_data;
0635 
0636     config_data.type = GPIO_CONFIG_TYPE_DDC;
0637 
0638     config_data.config.ddc.type = config_type;
0639     config_data.config.ddc.data_en_bit_present = false;
0640     config_data.config.ddc.clock_en_bit_present = false;
0641 
0642     return dal_gpio_set_config(ddc->pin_data, &config_data);
0643 }
0644 
0645 void dal_ddc_close(
0646     struct ddc *ddc)
0647 {
0648     if (ddc != NULL) {
0649         dal_gpio_close(ddc->pin_clock);
0650         dal_gpio_close(ddc->pin_data);
0651     }
0652 }
0653