Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2018 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 #include "dce_i2c.h"
0027 #include "dce_i2c_sw.h"
0028 #include "include/gpio_service_interface.h"
0029 #define SCL false
0030 #define SDA true
0031 
0032 void dce_i2c_sw_construct(
0033     struct dce_i2c_sw *dce_i2c_sw,
0034     struct dc_context *ctx)
0035 {
0036     dce_i2c_sw->ctx = ctx;
0037 }
0038 
0039 static inline bool read_bit_from_ddc(
0040     struct ddc *ddc,
0041     bool data_nor_clock)
0042 {
0043     uint32_t value = 0;
0044 
0045     if (data_nor_clock)
0046         dal_gpio_get_value(ddc->pin_data, &value);
0047     else
0048         dal_gpio_get_value(ddc->pin_clock, &value);
0049 
0050     return (value != 0);
0051 }
0052 
0053 static inline void write_bit_to_ddc(
0054     struct ddc *ddc,
0055     bool data_nor_clock,
0056     bool bit)
0057 {
0058     uint32_t value = bit ? 1 : 0;
0059 
0060     if (data_nor_clock)
0061         dal_gpio_set_value(ddc->pin_data, value);
0062     else
0063         dal_gpio_set_value(ddc->pin_clock, value);
0064 }
0065 
0066 static void release_engine_dce_sw(
0067     struct resource_pool *pool,
0068     struct dce_i2c_sw *dce_i2c_sw)
0069 {
0070     dal_ddc_close(dce_i2c_sw->ddc);
0071     dce_i2c_sw->ddc = NULL;
0072 }
0073 
0074 static bool wait_for_scl_high_sw(
0075     struct dc_context *ctx,
0076     struct ddc *ddc,
0077     uint16_t clock_delay_div_4)
0078 {
0079     uint32_t scl_retry = 0;
0080     uint32_t scl_retry_max = I2C_SW_TIMEOUT_DELAY / clock_delay_div_4;
0081 
0082     udelay(clock_delay_div_4);
0083 
0084     do {
0085         if (read_bit_from_ddc(ddc, SCL))
0086             return true;
0087 
0088         udelay(clock_delay_div_4);
0089 
0090         ++scl_retry;
0091     } while (scl_retry <= scl_retry_max);
0092 
0093     return false;
0094 }
0095 static bool write_byte_sw(
0096     struct dc_context *ctx,
0097     struct ddc *ddc_handle,
0098     uint16_t clock_delay_div_4,
0099     uint8_t byte)
0100 {
0101     int32_t shift = 7;
0102     bool ack;
0103 
0104     /* bits are transmitted serially, starting from MSB */
0105 
0106     do {
0107         udelay(clock_delay_div_4);
0108 
0109         write_bit_to_ddc(ddc_handle, SDA, (byte >> shift) & 1);
0110 
0111         udelay(clock_delay_div_4);
0112 
0113         write_bit_to_ddc(ddc_handle, SCL, true);
0114 
0115         if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0116             return false;
0117 
0118         write_bit_to_ddc(ddc_handle, SCL, false);
0119 
0120         --shift;
0121     } while (shift >= 0);
0122 
0123     /* The display sends ACK by preventing the SDA from going high
0124      * after the SCL pulse we use to send our last data bit.
0125      * If the SDA goes high after that bit, it's a NACK
0126      */
0127 
0128     udelay(clock_delay_div_4);
0129 
0130     write_bit_to_ddc(ddc_handle, SDA, true);
0131 
0132     udelay(clock_delay_div_4);
0133 
0134     write_bit_to_ddc(ddc_handle, SCL, true);
0135 
0136     if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0137         return false;
0138 
0139     /* read ACK bit */
0140 
0141     ack = !read_bit_from_ddc(ddc_handle, SDA);
0142 
0143     udelay(clock_delay_div_4 << 1);
0144 
0145     write_bit_to_ddc(ddc_handle, SCL, false);
0146 
0147     udelay(clock_delay_div_4 << 1);
0148 
0149     return ack;
0150 }
0151 
0152 static bool read_byte_sw(
0153     struct dc_context *ctx,
0154     struct ddc *ddc_handle,
0155     uint16_t clock_delay_div_4,
0156     uint8_t *byte,
0157     bool more)
0158 {
0159     int32_t shift = 7;
0160 
0161     uint8_t data = 0;
0162 
0163     /* The data bits are read from MSB to LSB;
0164      * bit is read while SCL is high
0165      */
0166 
0167     do {
0168         write_bit_to_ddc(ddc_handle, SCL, true);
0169 
0170         if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0171             return false;
0172 
0173         if (read_bit_from_ddc(ddc_handle, SDA))
0174             data |= (1 << shift);
0175 
0176         write_bit_to_ddc(ddc_handle, SCL, false);
0177 
0178         udelay(clock_delay_div_4 << 1);
0179 
0180         --shift;
0181     } while (shift >= 0);
0182 
0183     /* read only whole byte */
0184 
0185     *byte = data;
0186 
0187     udelay(clock_delay_div_4);
0188 
0189     /* send the acknowledge bit:
0190      * SDA low means ACK, SDA high means NACK
0191      */
0192 
0193     write_bit_to_ddc(ddc_handle, SDA, !more);
0194 
0195     udelay(clock_delay_div_4);
0196 
0197     write_bit_to_ddc(ddc_handle, SCL, true);
0198 
0199     if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0200         return false;
0201 
0202     write_bit_to_ddc(ddc_handle, SCL, false);
0203 
0204     udelay(clock_delay_div_4);
0205 
0206     write_bit_to_ddc(ddc_handle, SDA, true);
0207 
0208     udelay(clock_delay_div_4);
0209 
0210     return true;
0211 }
0212 static bool stop_sync_sw(
0213     struct dc_context *ctx,
0214     struct ddc *ddc_handle,
0215     uint16_t clock_delay_div_4)
0216 {
0217     uint32_t retry = 0;
0218 
0219     /* The I2C communications stop signal is:
0220      * the SDA going high from low, while the SCL is high.
0221      */
0222 
0223     write_bit_to_ddc(ddc_handle, SCL, false);
0224 
0225     udelay(clock_delay_div_4);
0226 
0227     write_bit_to_ddc(ddc_handle, SDA, false);
0228 
0229     udelay(clock_delay_div_4);
0230 
0231     write_bit_to_ddc(ddc_handle, SCL, true);
0232 
0233     if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0234         return false;
0235 
0236     write_bit_to_ddc(ddc_handle, SDA, true);
0237 
0238     do {
0239         udelay(clock_delay_div_4);
0240 
0241         if (read_bit_from_ddc(ddc_handle, SDA))
0242             return true;
0243 
0244         ++retry;
0245     } while (retry <= 2);
0246 
0247     return false;
0248 }
0249 static bool i2c_write_sw(
0250     struct dc_context *ctx,
0251     struct ddc *ddc_handle,
0252     uint16_t clock_delay_div_4,
0253     uint8_t address,
0254     uint32_t length,
0255     const uint8_t *data)
0256 {
0257     uint32_t i = 0;
0258 
0259     if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
0260         return false;
0261 
0262     while (i < length) {
0263         if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, data[i]))
0264             return false;
0265         ++i;
0266     }
0267 
0268     return true;
0269 }
0270 
0271 static bool i2c_read_sw(
0272     struct dc_context *ctx,
0273     struct ddc *ddc_handle,
0274     uint16_t clock_delay_div_4,
0275     uint8_t address,
0276     uint32_t length,
0277     uint8_t *data)
0278 {
0279     uint32_t i = 0;
0280 
0281     if (!write_byte_sw(ctx, ddc_handle, clock_delay_div_4, address))
0282         return false;
0283 
0284     while (i < length) {
0285         if (!read_byte_sw(ctx, ddc_handle, clock_delay_div_4, data + i,
0286             i < length - 1))
0287             return false;
0288         ++i;
0289     }
0290 
0291     return true;
0292 }
0293 
0294 
0295 
0296 static bool start_sync_sw(
0297     struct dc_context *ctx,
0298     struct ddc *ddc_handle,
0299     uint16_t clock_delay_div_4)
0300 {
0301     uint32_t retry = 0;
0302 
0303     /* The I2C communications start signal is:
0304      * the SDA going low from high, while the SCL is high.
0305      */
0306 
0307     write_bit_to_ddc(ddc_handle, SCL, true);
0308 
0309     udelay(clock_delay_div_4);
0310 
0311     do {
0312         write_bit_to_ddc(ddc_handle, SDA, true);
0313 
0314         if (!read_bit_from_ddc(ddc_handle, SDA)) {
0315             ++retry;
0316             continue;
0317         }
0318 
0319         udelay(clock_delay_div_4);
0320 
0321         write_bit_to_ddc(ddc_handle, SCL, true);
0322 
0323         if (!wait_for_scl_high_sw(ctx, ddc_handle, clock_delay_div_4))
0324             break;
0325 
0326         write_bit_to_ddc(ddc_handle, SDA, false);
0327 
0328         udelay(clock_delay_div_4);
0329 
0330         write_bit_to_ddc(ddc_handle, SCL, false);
0331 
0332         udelay(clock_delay_div_4);
0333 
0334         return true;
0335     } while (retry <= I2C_SW_RETRIES);
0336 
0337     return false;
0338 }
0339 
0340 static void dce_i2c_sw_engine_set_speed(
0341     struct dce_i2c_sw *engine,
0342     uint32_t speed)
0343 {
0344     ASSERT(speed);
0345 
0346     engine->speed = speed ? speed : DCE_I2C_DEFAULT_I2C_SW_SPEED;
0347 
0348     engine->clock_delay = 1000 / engine->speed;
0349 
0350     if (engine->clock_delay < 12)
0351         engine->clock_delay = 12;
0352 }
0353 
0354 static bool dce_i2c_sw_engine_acquire_engine(
0355     struct dce_i2c_sw *engine,
0356     struct ddc *ddc)
0357 {
0358     enum gpio_result result;
0359 
0360     result = dal_ddc_open(ddc, GPIO_MODE_FAST_OUTPUT,
0361         GPIO_DDC_CONFIG_TYPE_MODE_I2C);
0362 
0363     if (result != GPIO_RESULT_OK)
0364         return false;
0365 
0366     engine->ddc = ddc;
0367 
0368     return true;
0369 }
0370 bool dce_i2c_engine_acquire_sw(
0371     struct dce_i2c_sw *dce_i2c_sw,
0372     struct ddc *ddc_handle)
0373 {
0374     uint32_t counter = 0;
0375     bool result;
0376 
0377     do {
0378 
0379         result = dce_i2c_sw_engine_acquire_engine(
0380                 dce_i2c_sw, ddc_handle);
0381 
0382         if (result)
0383             break;
0384 
0385         /* i2c_engine is busy by VBios, lets wait and retry */
0386 
0387         udelay(10);
0388 
0389         ++counter;
0390     } while (counter < 2);
0391 
0392     return result;
0393 }
0394 
0395 
0396 
0397 
0398 static void dce_i2c_sw_engine_submit_channel_request(
0399     struct dce_i2c_sw *engine,
0400     struct i2c_request_transaction_data *req)
0401 {
0402     struct ddc *ddc = engine->ddc;
0403     uint16_t clock_delay_div_4 = engine->clock_delay >> 2;
0404 
0405     /* send sync (start / repeated start) */
0406 
0407     bool result = start_sync_sw(engine->ctx, ddc, clock_delay_div_4);
0408 
0409     /* process payload */
0410 
0411     if (result) {
0412         switch (req->action) {
0413         case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE:
0414         case DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT:
0415             result = i2c_write_sw(engine->ctx, ddc, clock_delay_div_4,
0416                 req->address, req->length, req->data);
0417         break;
0418         case DCE_I2C_TRANSACTION_ACTION_I2C_READ:
0419         case DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT:
0420             result = i2c_read_sw(engine->ctx, ddc, clock_delay_div_4,
0421                 req->address, req->length, req->data);
0422         break;
0423         default:
0424             result = false;
0425         break;
0426         }
0427     }
0428 
0429     /* send stop if not 'mot' or operation failed */
0430 
0431     if (!result ||
0432         (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_WRITE) ||
0433         (req->action == DCE_I2C_TRANSACTION_ACTION_I2C_READ))
0434         if (!stop_sync_sw(engine->ctx, ddc, clock_delay_div_4))
0435             result = false;
0436 
0437     req->status = result ?
0438         I2C_CHANNEL_OPERATION_SUCCEEDED :
0439         I2C_CHANNEL_OPERATION_FAILED;
0440 }
0441 
0442 static bool dce_i2c_sw_engine_submit_payload(
0443     struct dce_i2c_sw *engine,
0444     struct i2c_payload *payload,
0445     bool middle_of_transaction)
0446 {
0447     struct i2c_request_transaction_data request;
0448 
0449     if (!payload->write)
0450         request.action = middle_of_transaction ?
0451             DCE_I2C_TRANSACTION_ACTION_I2C_READ_MOT :
0452             DCE_I2C_TRANSACTION_ACTION_I2C_READ;
0453     else
0454         request.action = middle_of_transaction ?
0455             DCE_I2C_TRANSACTION_ACTION_I2C_WRITE_MOT :
0456             DCE_I2C_TRANSACTION_ACTION_I2C_WRITE;
0457 
0458     request.address = (uint8_t) ((payload->address << 1) | !payload->write);
0459     request.length = payload->length;
0460     request.data = payload->data;
0461 
0462     dce_i2c_sw_engine_submit_channel_request(engine, &request);
0463 
0464     if ((request.status == I2C_CHANNEL_OPERATION_ENGINE_BUSY) ||
0465         (request.status == I2C_CHANNEL_OPERATION_FAILED))
0466         return false;
0467 
0468     return true;
0469 }
0470 bool dce_i2c_submit_command_sw(
0471     struct resource_pool *pool,
0472     struct ddc *ddc,
0473     struct i2c_command *cmd,
0474     struct dce_i2c_sw *dce_i2c_sw)
0475 {
0476     uint8_t index_of_payload = 0;
0477     bool result;
0478 
0479     dce_i2c_sw_engine_set_speed(dce_i2c_sw, cmd->speed);
0480 
0481     result = true;
0482 
0483     while (index_of_payload < cmd->number_of_payloads) {
0484         bool mot = (index_of_payload != cmd->number_of_payloads - 1);
0485 
0486         struct i2c_payload *payload = cmd->payloads + index_of_payload;
0487 
0488         if (!dce_i2c_sw_engine_submit_payload(
0489             dce_i2c_sw, payload, mot)) {
0490             result = false;
0491             break;
0492         }
0493 
0494         ++index_of_payload;
0495     }
0496 
0497     release_engine_dce_sw(pool, dce_i2c_sw);
0498 
0499     return result;
0500 }