linux/drivers/gpu/drm/amd/display/dc/i2caux/dce80/i2c_hw_engine_dce80.c
<<
>>
Prefs
   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#include "dm_services.h"
  27
  28/*
  29 * Pre-requisites: headers required by header of this unit
  30 */
  31#include "include/i2caux_interface.h"
  32#include "../engine.h"
  33#include "../i2c_engine.h"
  34#include "../i2c_hw_engine.h"
  35#include "../i2c_generic_hw_engine.h"
  36/*
  37 * Header of this unit
  38 */
  39
  40#include "i2c_hw_engine_dce80.h"
  41
  42/*
  43 * Post-requisites: headers required by this unit
  44 */
  45
  46#include "dce/dce_8_0_d.h"
  47#include "dce/dce_8_0_sh_mask.h"
  48/*
  49 * This unit
  50 */
  51
  52enum dc_i2c_status {
  53        DC_I2C_STATUS__DC_I2C_STATUS_IDLE,
  54        DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW,
  55        DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_HW
  56};
  57
  58enum dc_i2c_arbitration {
  59        DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
  60        DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_HIGH
  61};
  62
  63enum {
  64        /* No timeout in HW
  65         * (timeout implemented in SW by querying status) */
  66        I2C_SETUP_TIME_LIMIT = 255,
  67        I2C_HW_BUFFER_SIZE = 144
  68};
  69
  70/*
  71 * @brief
  72 * Cast 'struct i2c_hw_engine *'
  73 * to 'struct i2c_hw_engine_dce80 *'
  74 */
  75#define FROM_I2C_HW_ENGINE(ptr) \
  76        container_of((ptr), struct i2c_hw_engine_dce80, base)
  77
  78/*
  79 * @brief
  80 * Cast pointer to 'struct i2c_engine *'
  81 * to pointer to 'struct i2c_hw_engine_dce80 *'
  82 */
  83#define FROM_I2C_ENGINE(ptr) \
  84        FROM_I2C_HW_ENGINE(container_of((ptr), struct i2c_hw_engine, base))
  85
  86/*
  87 * @brief
  88 * Cast pointer to 'struct engine *'
  89 * to 'pointer to struct i2c_hw_engine_dce80 *'
  90 */
  91#define FROM_ENGINE(ptr) \
  92        FROM_I2C_ENGINE(container_of((ptr), struct i2c_engine, base))
  93
  94static void disable_i2c_hw_engine(
  95        struct i2c_hw_engine_dce80 *engine)
  96{
  97        const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
  98        uint32_t value = 0;
  99
 100        struct dc_context *ctx = NULL;
 101
 102        ctx = engine->base.base.base.ctx;
 103
 104        value = dm_read_reg(ctx, addr);
 105
 106        set_reg_field_value(
 107                value,
 108                0,
 109                DC_I2C_DDC1_SETUP,
 110                DC_I2C_DDC1_ENABLE);
 111
 112        dm_write_reg(ctx, addr, value);
 113}
 114
 115static void release_engine(
 116        struct engine *engine)
 117{
 118        struct i2c_hw_engine_dce80 *hw_engine = FROM_ENGINE(engine);
 119
 120        struct i2c_engine *base = NULL;
 121        bool safe_to_reset;
 122        uint32_t value = 0;
 123
 124        base = &hw_engine->base.base;
 125
 126        /* Restore original HW engine speed */
 127
 128        base->funcs->set_speed(base, hw_engine->base.original_speed);
 129
 130        /* Release I2C */
 131        {
 132                value = dm_read_reg(engine->ctx, mmDC_I2C_ARBITRATION);
 133
 134                set_reg_field_value(
 135                                value,
 136                                1,
 137                                DC_I2C_ARBITRATION,
 138                                DC_I2C_SW_DONE_USING_I2C_REG);
 139
 140                dm_write_reg(engine->ctx, mmDC_I2C_ARBITRATION, value);
 141        }
 142
 143        /* Reset HW engine */
 144        {
 145                uint32_t i2c_sw_status = 0;
 146
 147                value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
 148
 149                i2c_sw_status = get_reg_field_value(
 150                                value,
 151                                DC_I2C_SW_STATUS,
 152                                DC_I2C_SW_STATUS);
 153                /* if used by SW, safe to reset */
 154                safe_to_reset = (i2c_sw_status == 1);
 155        }
 156        {
 157                value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
 158
 159                if (safe_to_reset)
 160                        set_reg_field_value(
 161                                value,
 162                                1,
 163                                DC_I2C_CONTROL,
 164                                DC_I2C_SOFT_RESET);
 165
 166                set_reg_field_value(
 167                        value,
 168                        1,
 169                        DC_I2C_CONTROL,
 170                        DC_I2C_SW_STATUS_RESET);
 171
 172                dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
 173        }
 174
 175        /* HW I2c engine - clock gating feature */
 176        if (!hw_engine->engine_keep_power_up_count)
 177                disable_i2c_hw_engine(hw_engine);
 178}
 179
 180static void destruct(
 181        struct i2c_hw_engine_dce80 *engine)
 182{
 183        dal_i2c_hw_engine_destruct(&engine->base);
 184}
 185
 186static void destroy(
 187        struct i2c_engine **i2c_engine)
 188{
 189        struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(*i2c_engine);
 190
 191        destruct(engine);
 192
 193        kfree(engine);
 194
 195        *i2c_engine = NULL;
 196}
 197
 198static bool setup_engine(
 199        struct i2c_engine *i2c_engine)
 200{
 201        uint32_t value = 0;
 202        struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
 203
 204        /* Program pin select */
 205        {
 206                const uint32_t addr = mmDC_I2C_CONTROL;
 207
 208                value = dm_read_reg(i2c_engine->base.ctx, addr);
 209
 210                set_reg_field_value(
 211                        value,
 212                        0,
 213                        DC_I2C_CONTROL,
 214                        DC_I2C_GO);
 215
 216                set_reg_field_value(
 217                        value,
 218                        0,
 219                        DC_I2C_CONTROL,
 220                        DC_I2C_SOFT_RESET);
 221
 222                set_reg_field_value(
 223                        value,
 224                        0,
 225                        DC_I2C_CONTROL,
 226                        DC_I2C_SEND_RESET);
 227
 228                set_reg_field_value(
 229                        value,
 230                        0,
 231                        DC_I2C_CONTROL,
 232                        DC_I2C_SW_STATUS_RESET);
 233
 234                set_reg_field_value(
 235                        value,
 236                        0,
 237                        DC_I2C_CONTROL,
 238                        DC_I2C_TRANSACTION_COUNT);
 239
 240                set_reg_field_value(
 241                        value,
 242                        engine->engine_id,
 243                        DC_I2C_CONTROL,
 244                        DC_I2C_DDC_SELECT);
 245
 246                dm_write_reg(i2c_engine->base.ctx, addr, value);
 247        }
 248
 249        /* Program time limit */
 250        {
 251                const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
 252
 253                value = dm_read_reg(i2c_engine->base.ctx, addr);
 254
 255                set_reg_field_value(
 256                        value,
 257                        I2C_SETUP_TIME_LIMIT,
 258                        DC_I2C_DDC1_SETUP,
 259                        DC_I2C_DDC1_TIME_LIMIT);
 260
 261                set_reg_field_value(
 262                        value,
 263                        1,
 264                        DC_I2C_DDC1_SETUP,
 265                        DC_I2C_DDC1_ENABLE);
 266
 267                dm_write_reg(i2c_engine->base.ctx, addr, value);
 268        }
 269
 270        /* Program HW priority
 271         * set to High - interrupt software I2C at any time
 272         * Enable restart of SW I2C that was interrupted by HW
 273         * disable queuing of software while I2C is in use by HW */
 274        {
 275                value = dm_read_reg(i2c_engine->base.ctx,
 276                                mmDC_I2C_ARBITRATION);
 277
 278                set_reg_field_value(
 279                        value,
 280                        0,
 281                        DC_I2C_ARBITRATION,
 282                        DC_I2C_NO_QUEUED_SW_GO);
 283
 284                set_reg_field_value(
 285                        value,
 286                        DC_I2C_ARBITRATION__DC_I2C_SW_PRIORITY_NORMAL,
 287                        DC_I2C_ARBITRATION,
 288                        DC_I2C_SW_PRIORITY);
 289
 290                dm_write_reg(i2c_engine->base.ctx,
 291                                mmDC_I2C_ARBITRATION, value);
 292        }
 293
 294        return true;
 295}
 296
 297static uint32_t get_speed(
 298        const struct i2c_engine *i2c_engine)
 299{
 300        const struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
 301
 302        const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
 303
 304        uint32_t pre_scale = 0;
 305
 306        uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
 307
 308        pre_scale = get_reg_field_value(
 309                        value,
 310                        DC_I2C_DDC1_SPEED,
 311                        DC_I2C_DDC1_PRESCALE);
 312
 313        /* [anaumov] it seems following is unnecessary */
 314        /*ASSERT(value.bits.DC_I2C_DDC1_PRESCALE);*/
 315
 316        return pre_scale ?
 317                engine->reference_frequency / pre_scale :
 318                engine->base.default_speed;
 319}
 320
 321static void set_speed(
 322        struct i2c_engine *i2c_engine,
 323        uint32_t speed)
 324{
 325        struct i2c_hw_engine_dce80 *engine = FROM_I2C_ENGINE(i2c_engine);
 326
 327        if (speed) {
 328                const uint32_t addr = engine->addr.DC_I2C_DDCX_SPEED;
 329
 330                uint32_t value = dm_read_reg(i2c_engine->base.ctx, addr);
 331
 332                set_reg_field_value(
 333                        value,
 334                        engine->reference_frequency / speed,
 335                        DC_I2C_DDC1_SPEED,
 336                        DC_I2C_DDC1_PRESCALE);
 337
 338                set_reg_field_value(
 339                        value,
 340                        2,
 341                        DC_I2C_DDC1_SPEED,
 342                        DC_I2C_DDC1_THRESHOLD);
 343
 344                dm_write_reg(i2c_engine->base.ctx, addr, value);
 345        }
 346}
 347
 348static inline void reset_hw_engine(struct engine *engine)
 349{
 350        uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_CONTROL);
 351
 352        set_reg_field_value(
 353                value,
 354                1,
 355                DC_I2C_CONTROL,
 356                DC_I2C_SOFT_RESET);
 357
 358        set_reg_field_value(
 359                value,
 360                1,
 361                DC_I2C_CONTROL,
 362                DC_I2C_SW_STATUS_RESET);
 363
 364        dm_write_reg(engine->ctx, mmDC_I2C_CONTROL, value);
 365}
 366
 367static bool is_hw_busy(struct engine *engine)
 368{
 369        uint32_t i2c_sw_status = 0;
 370
 371        uint32_t value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
 372
 373        i2c_sw_status = get_reg_field_value(
 374                        value,
 375                        DC_I2C_SW_STATUS,
 376                        DC_I2C_SW_STATUS);
 377
 378        if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_IDLE)
 379                return false;
 380
 381        reset_hw_engine(engine);
 382
 383        value = dm_read_reg(engine->ctx, mmDC_I2C_SW_STATUS);
 384
 385        i2c_sw_status = get_reg_field_value(
 386                        value,
 387                        DC_I2C_SW_STATUS,
 388                        DC_I2C_SW_STATUS);
 389
 390        return i2c_sw_status != DC_I2C_STATUS__DC_I2C_STATUS_IDLE;
 391}
 392
 393/*
 394 * @brief
 395 * DC_GPIO_DDC MM register offsets
 396 */
 397static const uint32_t transaction_addr[] = {
 398        mmDC_I2C_TRANSACTION0,
 399        mmDC_I2C_TRANSACTION1,
 400        mmDC_I2C_TRANSACTION2,
 401        mmDC_I2C_TRANSACTION3
 402};
 403
 404static bool process_transaction(
 405        struct i2c_hw_engine_dce80 *engine,
 406        struct i2c_request_transaction_data *request)
 407{
 408        uint32_t length = request->length;
 409        uint8_t *buffer = request->data;
 410
 411        bool last_transaction = false;
 412        uint32_t value = 0;
 413
 414        struct dc_context *ctx = NULL;
 415
 416        ctx = engine->base.base.base.ctx;
 417
 418        {
 419                const uint32_t addr =
 420                        transaction_addr[engine->transaction_count];
 421
 422                value = dm_read_reg(ctx, addr);
 423
 424                set_reg_field_value(
 425                        value,
 426                        1,
 427                        DC_I2C_TRANSACTION0,
 428                        DC_I2C_STOP_ON_NACK0);
 429
 430                set_reg_field_value(
 431                        value,
 432                        1,
 433                        DC_I2C_TRANSACTION0,
 434                        DC_I2C_START0);
 435
 436                if ((engine->transaction_count == 3) ||
 437                (request->action == I2CAUX_TRANSACTION_ACTION_I2C_WRITE) ||
 438                (request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
 439
 440                        set_reg_field_value(
 441                                value,
 442                                1,
 443                                DC_I2C_TRANSACTION0,
 444                                DC_I2C_STOP0);
 445
 446                        last_transaction = true;
 447                } else
 448                        set_reg_field_value(
 449                                value,
 450                                0,
 451                                DC_I2C_TRANSACTION0,
 452                                DC_I2C_STOP0);
 453
 454                set_reg_field_value(
 455                        value,
 456                        (0 != (request->action &
 457                                        I2CAUX_TRANSACTION_ACTION_I2C_READ)),
 458                        DC_I2C_TRANSACTION0,
 459                        DC_I2C_RW0);
 460
 461                set_reg_field_value(
 462                        value,
 463                        length,
 464                        DC_I2C_TRANSACTION0,
 465                        DC_I2C_COUNT0);
 466
 467                dm_write_reg(ctx, addr, value);
 468        }
 469
 470        /* Write the I2C address and I2C data
 471         * into the hardware circular buffer, one byte per entry.
 472         * As an example, the 7-bit I2C slave address for CRT monitor
 473         * for reading DDC/EDID information is 0b1010001.
 474         * For an I2C send operation, the LSB must be programmed to 0;
 475         * for I2C receive operation, the LSB must be programmed to 1. */
 476
 477        {
 478                value = 0;
 479
 480                set_reg_field_value(
 481                        value,
 482                        false,
 483                        DC_I2C_DATA,
 484                        DC_I2C_DATA_RW);
 485
 486                set_reg_field_value(
 487                        value,
 488                        request->address,
 489                        DC_I2C_DATA,
 490                        DC_I2C_DATA);
 491
 492                if (engine->transaction_count == 0) {
 493                        set_reg_field_value(
 494                                value,
 495                                0,
 496                                DC_I2C_DATA,
 497                                DC_I2C_INDEX);
 498
 499                        /*enable index write*/
 500                        set_reg_field_value(
 501                                value,
 502                                1,
 503                                DC_I2C_DATA,
 504                                DC_I2C_INDEX_WRITE);
 505                }
 506
 507                dm_write_reg(ctx, mmDC_I2C_DATA, value);
 508
 509                if (!(request->action & I2CAUX_TRANSACTION_ACTION_I2C_READ)) {
 510
 511                        set_reg_field_value(
 512                                value,
 513                                0,
 514                                DC_I2C_DATA,
 515                                DC_I2C_INDEX_WRITE);
 516
 517                        while (length) {
 518
 519                                set_reg_field_value(
 520                                        value,
 521                                        *buffer++,
 522                                        DC_I2C_DATA,
 523                                        DC_I2C_DATA);
 524
 525                                dm_write_reg(ctx, mmDC_I2C_DATA, value);
 526                                --length;
 527                        }
 528                }
 529        }
 530
 531        ++engine->transaction_count;
 532        engine->buffer_used_bytes += length + 1;
 533
 534        return last_transaction;
 535}
 536
 537static void execute_transaction(
 538        struct i2c_hw_engine_dce80 *engine)
 539{
 540        uint32_t value = 0;
 541        struct dc_context *ctx = NULL;
 542
 543        ctx = engine->base.base.base.ctx;
 544
 545        {
 546                const uint32_t addr = engine->addr.DC_I2C_DDCX_SETUP;
 547
 548                value = dm_read_reg(ctx, addr);
 549
 550                set_reg_field_value(
 551                        value,
 552                        0,
 553                        DC_I2C_DDC1_SETUP,
 554                        DC_I2C_DDC1_DATA_DRIVE_EN);
 555
 556                set_reg_field_value(
 557                        value,
 558                        0,
 559                        DC_I2C_DDC1_SETUP,
 560                        DC_I2C_DDC1_CLK_DRIVE_EN);
 561
 562                set_reg_field_value(
 563                        value,
 564                        0,
 565                        DC_I2C_DDC1_SETUP,
 566                        DC_I2C_DDC1_DATA_DRIVE_SEL);
 567
 568                set_reg_field_value(
 569                        value,
 570                        0,
 571                        DC_I2C_DDC1_SETUP,
 572                        DC_I2C_DDC1_INTRA_TRANSACTION_DELAY);
 573
 574                set_reg_field_value(
 575                        value,
 576                        0,
 577                        DC_I2C_DDC1_SETUP,
 578                        DC_I2C_DDC1_INTRA_BYTE_DELAY);
 579
 580                dm_write_reg(ctx, addr, value);
 581        }
 582
 583        {
 584                const uint32_t addr = mmDC_I2C_CONTROL;
 585
 586                value = dm_read_reg(ctx, addr);
 587
 588                set_reg_field_value(
 589                        value,
 590                        0,
 591                        DC_I2C_CONTROL,
 592                        DC_I2C_SOFT_RESET);
 593
 594                set_reg_field_value(
 595                        value,
 596                        0,
 597                        DC_I2C_CONTROL,
 598                        DC_I2C_SW_STATUS_RESET);
 599
 600                set_reg_field_value(
 601                        value,
 602                        0,
 603                        DC_I2C_CONTROL,
 604                        DC_I2C_SEND_RESET);
 605
 606                set_reg_field_value(
 607                        value,
 608                        0,
 609                        DC_I2C_CONTROL,
 610                        DC_I2C_GO);
 611
 612                set_reg_field_value(
 613                        value,
 614                        engine->transaction_count - 1,
 615                        DC_I2C_CONTROL,
 616                        DC_I2C_TRANSACTION_COUNT);
 617
 618                dm_write_reg(ctx, addr, value);
 619        }
 620
 621        /* start I2C transfer */
 622        {
 623                const uint32_t addr = mmDC_I2C_CONTROL;
 624
 625                value   = dm_read_reg(ctx, addr);
 626
 627                set_reg_field_value(
 628                        value,
 629                        1,
 630                        DC_I2C_CONTROL,
 631                        DC_I2C_GO);
 632
 633                dm_write_reg(ctx, addr, value);
 634        }
 635
 636        /* all transactions were executed and HW buffer became empty
 637         * (even though it actually happens when status becomes DONE) */
 638        engine->transaction_count = 0;
 639        engine->buffer_used_bytes = 0;
 640}
 641
 642static void submit_channel_request(
 643        struct i2c_engine *engine,
 644        struct i2c_request_transaction_data *request)
 645{
 646        request->status = I2C_CHANNEL_OPERATION_SUCCEEDED;
 647
 648        if (!process_transaction(FROM_I2C_ENGINE(engine), request))
 649                return;
 650
 651        if (is_hw_busy(&engine->base)) {
 652                request->status = I2C_CHANNEL_OPERATION_ENGINE_BUSY;
 653                return;
 654        }
 655
 656        execute_transaction(FROM_I2C_ENGINE(engine));
 657}
 658
 659static void process_channel_reply(
 660        struct i2c_engine *engine,
 661        struct i2c_reply_transaction_data *reply)
 662{
 663        uint32_t length = reply->length;
 664        uint8_t *buffer = reply->data;
 665
 666        uint32_t value = 0;
 667
 668        /*set index*/
 669        set_reg_field_value(
 670                value,
 671                length - 1,
 672                DC_I2C_DATA,
 673                DC_I2C_INDEX);
 674
 675        set_reg_field_value(
 676                value,
 677                1,
 678                DC_I2C_DATA,
 679                DC_I2C_DATA_RW);
 680
 681        set_reg_field_value(
 682                value,
 683                1,
 684                DC_I2C_DATA,
 685                DC_I2C_INDEX_WRITE);
 686
 687        dm_write_reg(engine->base.ctx, mmDC_I2C_DATA, value);
 688
 689        while (length) {
 690                /* after reading the status,
 691                 * if the I2C operation executed successfully
 692                 * (i.e. DC_I2C_STATUS_DONE = 1) then the I2C controller
 693                 * should read data bytes from I2C circular data buffer */
 694
 695                value = dm_read_reg(engine->base.ctx, mmDC_I2C_DATA);
 696
 697                *buffer++ = get_reg_field_value(
 698                                value,
 699                                DC_I2C_DATA,
 700                                DC_I2C_DATA);
 701
 702                --length;
 703        }
 704}
 705
 706static enum i2c_channel_operation_result get_channel_status(
 707        struct i2c_engine *engine,
 708        uint8_t *returned_bytes)
 709{
 710        uint32_t i2c_sw_status = 0;
 711        uint32_t value = dm_read_reg(engine->base.ctx, mmDC_I2C_SW_STATUS);
 712
 713        i2c_sw_status = get_reg_field_value(
 714                        value,
 715                        DC_I2C_SW_STATUS,
 716                        DC_I2C_SW_STATUS);
 717
 718        if (i2c_sw_status == DC_I2C_STATUS__DC_I2C_STATUS_USED_BY_SW)
 719                return I2C_CHANNEL_OPERATION_ENGINE_BUSY;
 720        else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_STOPPED_ON_NACK_MASK)
 721                return I2C_CHANNEL_OPERATION_NO_RESPONSE;
 722        else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_TIMEOUT_MASK)
 723                return I2C_CHANNEL_OPERATION_TIMEOUT;
 724        else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_ABORTED_MASK)
 725                return I2C_CHANNEL_OPERATION_FAILED;
 726        else if (value & DC_I2C_SW_STATUS__DC_I2C_SW_DONE_MASK)
 727                return I2C_CHANNEL_OPERATION_SUCCEEDED;
 728
 729        /*
 730         * this is the case when HW used for communication, I2C_SW_STATUS
 731         * could be zero
 732         */
 733        return I2C_CHANNEL_OPERATION_SUCCEEDED;
 734}
 735
 736static uint32_t get_hw_buffer_available_size(
 737        const struct i2c_hw_engine *engine)
 738{
 739        return I2C_HW_BUFFER_SIZE -
 740                FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes;
 741}
 742
 743static uint32_t get_transaction_timeout(
 744        const struct i2c_hw_engine *engine,
 745        uint32_t length)
 746{
 747        uint32_t speed = engine->base.funcs->get_speed(&engine->base);
 748
 749        uint32_t period_timeout;
 750        uint32_t num_of_clock_stretches;
 751
 752        if (!speed)
 753                return 0;
 754
 755        period_timeout = (1000 * TRANSACTION_TIMEOUT_IN_I2C_CLOCKS) / speed;
 756
 757        num_of_clock_stretches = 1 + (length << 3) + 1;
 758        num_of_clock_stretches +=
 759                (FROM_I2C_HW_ENGINE(engine)->buffer_used_bytes << 3) +
 760                (FROM_I2C_HW_ENGINE(engine)->transaction_count << 1);
 761
 762        return period_timeout * num_of_clock_stretches;
 763}
 764
 765/*
 766 * @brief
 767 * DC_I2C_DDC1_SETUP MM register offsets
 768 *
 769 * @note
 770 * The indices of this offset array are DDC engine IDs
 771 */
 772static const int32_t ddc_setup_offset[] = {
 773
 774        mmDC_I2C_DDC1_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 1 */
 775        mmDC_I2C_DDC2_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 2 */
 776        mmDC_I2C_DDC3_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 3 */
 777        mmDC_I2C_DDC4_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 4 */
 778        mmDC_I2C_DDC5_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 5 */
 779        mmDC_I2C_DDC6_SETUP - mmDC_I2C_DDC1_SETUP, /* DDC Engine 6 */
 780        mmDC_I2C_DDCVGA_SETUP - mmDC_I2C_DDC1_SETUP /* DDC Engine 7 */
 781};
 782
 783/*
 784 * @brief
 785 * DC_I2C_DDC1_SPEED MM register offsets
 786 *
 787 * @note
 788 * The indices of this offset array are DDC engine IDs
 789 */
 790static const int32_t ddc_speed_offset[] = {
 791        mmDC_I2C_DDC1_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 1 */
 792        mmDC_I2C_DDC2_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 2 */
 793        mmDC_I2C_DDC3_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 3 */
 794        mmDC_I2C_DDC4_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 4 */
 795        mmDC_I2C_DDC5_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 5 */
 796        mmDC_I2C_DDC6_SPEED - mmDC_I2C_DDC1_SPEED, /* DDC Engine 6 */
 797        mmDC_I2C_DDCVGA_SPEED - mmDC_I2C_DDC1_SPEED /* DDC Engine 7 */
 798};
 799
 800static const struct i2c_engine_funcs i2c_engine_funcs = {
 801        .destroy = destroy,
 802        .get_speed = get_speed,
 803        .set_speed = set_speed,
 804        .setup_engine = setup_engine,
 805        .submit_channel_request = submit_channel_request,
 806        .process_channel_reply = process_channel_reply,
 807        .get_channel_status = get_channel_status,
 808        .acquire_engine = dal_i2c_hw_engine_acquire_engine,
 809};
 810
 811static const struct engine_funcs engine_funcs = {
 812        .release_engine = release_engine,
 813        .get_engine_type = dal_i2c_hw_engine_get_engine_type,
 814        .acquire = dal_i2c_engine_acquire,
 815        .submit_request = dal_i2c_hw_engine_submit_request,
 816};
 817
 818static const struct i2c_hw_engine_funcs i2c_hw_engine_funcs = {
 819        .get_hw_buffer_available_size =
 820                get_hw_buffer_available_size,
 821        .get_transaction_timeout =
 822                get_transaction_timeout,
 823        .wait_on_operation_result =
 824                dal_i2c_hw_engine_wait_on_operation_result,
 825};
 826
 827static void construct(
 828        struct i2c_hw_engine_dce80 *engine,
 829        const struct i2c_hw_engine_dce80_create_arg *arg)
 830{
 831        dal_i2c_hw_engine_construct(&engine->base, arg->ctx);
 832
 833        engine->base.base.base.funcs = &engine_funcs;
 834        engine->base.base.funcs = &i2c_engine_funcs;
 835        engine->base.funcs = &i2c_hw_engine_funcs;
 836        engine->base.default_speed = arg->default_speed;
 837        engine->addr.DC_I2C_DDCX_SETUP =
 838                mmDC_I2C_DDC1_SETUP + ddc_setup_offset[arg->engine_id];
 839        engine->addr.DC_I2C_DDCX_SPEED =
 840                mmDC_I2C_DDC1_SPEED + ddc_speed_offset[arg->engine_id];
 841
 842        engine->engine_id = arg->engine_id;
 843        engine->reference_frequency = arg->reference_frequency;
 844        engine->buffer_used_bytes = 0;
 845        engine->transaction_count = 0;
 846        engine->engine_keep_power_up_count = 1;
 847}
 848
 849struct i2c_engine *dal_i2c_hw_engine_dce80_create(
 850        const struct i2c_hw_engine_dce80_create_arg *arg)
 851{
 852        struct i2c_hw_engine_dce80 *engine;
 853
 854        if (!arg) {
 855                BREAK_TO_DEBUGGER();
 856                return NULL;
 857        }
 858
 859        if ((arg->engine_id >= sizeof(ddc_setup_offset) / sizeof(int32_t)) ||
 860            (arg->engine_id >= sizeof(ddc_speed_offset) / sizeof(int32_t)) ||
 861            !arg->reference_frequency) {
 862                BREAK_TO_DEBUGGER();
 863                return NULL;
 864        }
 865
 866        engine = kzalloc(sizeof(struct i2c_hw_engine_dce80), GFP_KERNEL);
 867
 868        if (!engine) {
 869                BREAK_TO_DEBUGGER();
 870                return NULL;
 871        }
 872
 873        construct(engine, arg);
 874        return &engine->base.base;
 875}
 876