linux/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * aQuantia Corporation Network Driver
   4 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
   5 */
   6
   7/* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
   8 * abstraction layer.
   9 */
  10
  11#include "../aq_nic.h"
  12#include "../aq_hw_utils.h"
  13#include "hw_atl_utils.h"
  14#include "hw_atl_llh.h"
  15#include "hw_atl_llh_internal.h"
  16
  17#include <linux/random.h>
  18
  19#define HW_ATL_UCP_0X370_REG    0x0370U
  20
  21#define HW_ATL_MIF_CMD          0x0200U
  22#define HW_ATL_MIF_ADDR         0x0208U
  23#define HW_ATL_MIF_VAL          0x020CU
  24
  25#define HW_ATL_RPC_CONTROL_ADR  0x0338U
  26#define HW_ATL_RPC_STATE_ADR    0x033CU
  27
  28#define HW_ATL_MPI_FW_VERSION   0x18
  29#define HW_ATL_MPI_CONTROL_ADR  0x0368U
  30#define HW_ATL_MPI_STATE_ADR    0x036CU
  31
  32#define HW_ATL_MPI_STATE_MSK      0x00FFU
  33#define HW_ATL_MPI_STATE_SHIFT    0U
  34#define HW_ATL_MPI_SPEED_MSK      0x00FF0000U
  35#define HW_ATL_MPI_SPEED_SHIFT    16U
  36#define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
  37
  38#define HW_ATL_MPI_DAISY_CHAIN_STATUS   0x704
  39#define HW_ATL_MPI_BOOT_EXIT_CODE       0x388
  40
  41#define HW_ATL_MAC_PHY_CONTROL  0x4000
  42#define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
  43
  44#define HW_ATL_FW_VER_1X 0x01050006U
  45#define HW_ATL_FW_VER_2X 0x02000000U
  46#define HW_ATL_FW_VER_3X 0x03000000U
  47
  48#define FORCE_FLASHLESS 0
  49
  50static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
  51
  52static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
  53                                      enum hal_atl_utils_fw_state_e state);
  54
  55static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
  56static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
  57static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
  58static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
  59static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
  60
  61int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
  62{
  63        int err = 0;
  64
  65        err = hw_atl_utils_soft_reset(self);
  66        if (err)
  67                return err;
  68
  69        hw_atl_utils_hw_chip_features_init(self,
  70                                           &self->chip_features);
  71
  72        hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
  73
  74        if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
  75                                   self->fw_ver_actual) == 0) {
  76                *fw_ops = &aq_fw_1x_ops;
  77        } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
  78                                          self->fw_ver_actual) == 0) {
  79                *fw_ops = &aq_fw_2x_ops;
  80        } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
  81                                          self->fw_ver_actual) == 0) {
  82                *fw_ops = &aq_fw_2x_ops;
  83        } else {
  84                aq_pr_err("Bad FW version detected: %x\n",
  85                          self->fw_ver_actual);
  86                return -EOPNOTSUPP;
  87        }
  88        self->aq_fw_ops = *fw_ops;
  89        err = self->aq_fw_ops->init(self);
  90        return err;
  91}
  92
  93static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
  94{
  95        u32 gsr, val;
  96        int k = 0;
  97
  98        aq_hw_write_reg(self, 0x404, 0x40e1);
  99        AQ_HW_SLEEP(50);
 100
 101        /* Cleanup SPI */
 102        val = aq_hw_read_reg(self, 0x53C);
 103        aq_hw_write_reg(self, 0x53C, val | 0x10);
 104
 105        gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
 106        aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
 107
 108        /* Kickstart MAC */
 109        aq_hw_write_reg(self, 0x404, 0x80e0);
 110        aq_hw_write_reg(self, 0x32a8, 0x0);
 111        aq_hw_write_reg(self, 0x520, 0x1);
 112
 113        /* Reset SPI again because of possible interrupted SPI burst */
 114        val = aq_hw_read_reg(self, 0x53C);
 115        aq_hw_write_reg(self, 0x53C, val | 0x10);
 116        AQ_HW_SLEEP(10);
 117        /* Clear SPI reset state */
 118        aq_hw_write_reg(self, 0x53C, val & ~0x10);
 119
 120        aq_hw_write_reg(self, 0x404, 0x180e0);
 121
 122        for (k = 0; k < 1000; k++) {
 123                u32 flb_status = aq_hw_read_reg(self,
 124                                                HW_ATL_MPI_DAISY_CHAIN_STATUS);
 125
 126                flb_status = flb_status & 0x10;
 127                if (flb_status)
 128                        break;
 129                AQ_HW_SLEEP(10);
 130        }
 131        if (k == 1000) {
 132                aq_pr_err("MAC kickstart failed\n");
 133                return -EIO;
 134        }
 135
 136        /* FW reset */
 137        aq_hw_write_reg(self, 0x404, 0x80e0);
 138        AQ_HW_SLEEP(50);
 139        aq_hw_write_reg(self, 0x3a0, 0x1);
 140
 141        /* Kickstart PHY - skipped */
 142
 143        /* Global software reset*/
 144        hw_atl_rx_rx_reg_res_dis_set(self, 0U);
 145        hw_atl_tx_tx_reg_res_dis_set(self, 0U);
 146        aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
 147                            BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
 148                            HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
 149        gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
 150        aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
 151
 152        for (k = 0; k < 1000; k++) {
 153                u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
 154
 155                if (fw_state)
 156                        break;
 157                AQ_HW_SLEEP(10);
 158        }
 159        if (k == 1000) {
 160                aq_pr_err("FW kickstart failed\n");
 161                return -EIO;
 162        }
 163        /* Old FW requires fixed delay after init */
 164        AQ_HW_SLEEP(15);
 165
 166        return 0;
 167}
 168
 169static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
 170{
 171        u32 gsr, val, rbl_status;
 172        int k;
 173
 174        aq_hw_write_reg(self, 0x404, 0x40e1);
 175        aq_hw_write_reg(self, 0x3a0, 0x1);
 176        aq_hw_write_reg(self, 0x32a8, 0x0);
 177
 178        /* Alter RBL status */
 179        aq_hw_write_reg(self, 0x388, 0xDEAD);
 180
 181        /* Cleanup SPI */
 182        val = aq_hw_read_reg(self, 0x53C);
 183        aq_hw_write_reg(self, 0x53C, val | 0x10);
 184
 185        /* Global software reset*/
 186        hw_atl_rx_rx_reg_res_dis_set(self, 0U);
 187        hw_atl_tx_tx_reg_res_dis_set(self, 0U);
 188        aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
 189                            BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
 190                            HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
 191        gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
 192        aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
 193                        (gsr & 0xFFFFBFFF) | 0x8000);
 194
 195        if (FORCE_FLASHLESS)
 196                aq_hw_write_reg(self, 0x534, 0x0);
 197
 198        aq_hw_write_reg(self, 0x404, 0x40e0);
 199
 200        /* Wait for RBL boot */
 201        for (k = 0; k < 1000; k++) {
 202                rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
 203                if (rbl_status && rbl_status != 0xDEAD)
 204                        break;
 205                AQ_HW_SLEEP(10);
 206        }
 207        if (!rbl_status || rbl_status == 0xDEAD) {
 208                aq_pr_err("RBL Restart failed");
 209                return -EIO;
 210        }
 211
 212        /* Restore NVR */
 213        if (FORCE_FLASHLESS)
 214                aq_hw_write_reg(self, 0x534, 0xA0);
 215
 216        if (rbl_status == 0xF1A7) {
 217                aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
 218                return -ENOTSUPP;
 219        }
 220
 221        for (k = 0; k < 1000; k++) {
 222                u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
 223
 224                if (fw_state)
 225                        break;
 226                AQ_HW_SLEEP(10);
 227        }
 228        if (k == 1000) {
 229                aq_pr_err("FW kickstart failed\n");
 230                return -EIO;
 231        }
 232        /* Old FW requires fixed delay after init */
 233        AQ_HW_SLEEP(15);
 234
 235        return 0;
 236}
 237
 238int hw_atl_utils_soft_reset(struct aq_hw_s *self)
 239{
 240        int k;
 241        u32 boot_exit_code = 0;
 242        u32 val;
 243
 244        for (k = 0; k < 1000; ++k) {
 245                u32 flb_status = aq_hw_read_reg(self,
 246                                                HW_ATL_MPI_DAISY_CHAIN_STATUS);
 247                boot_exit_code = aq_hw_read_reg(self,
 248                                                HW_ATL_MPI_BOOT_EXIT_CODE);
 249                if (flb_status != 0x06000000 || boot_exit_code != 0)
 250                        break;
 251        }
 252
 253        if (k == 1000) {
 254                aq_pr_err("Neither RBL nor FLB firmware started\n");
 255                return -EOPNOTSUPP;
 256        }
 257
 258        self->rbl_enabled = (boot_exit_code != 0);
 259
 260        /* FW 1.x may bootup in an invalid POWER state (WOL feature).
 261         * We should work around this by forcing its state back to DEINIT
 262         */
 263        if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
 264                                    aq_hw_read_reg(self,
 265                                                   HW_ATL_MPI_FW_VERSION))) {
 266                int err = 0;
 267
 268                hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
 269                err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
 270                                                self, val,
 271                                                (val & HW_ATL_MPI_STATE_MSK) ==
 272                                                 MPI_DEINIT,
 273                                                10, 10000U);
 274                if (err)
 275                        return err;
 276        }
 277
 278        if (self->rbl_enabled)
 279                return hw_atl_utils_soft_reset_rbl(self);
 280        else
 281                return hw_atl_utils_soft_reset_flb(self);
 282}
 283
 284int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
 285                                  u32 *p, u32 cnt)
 286{
 287        int err = 0;
 288        u32 val;
 289
 290        err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
 291                                        self, val, val == 1U,
 292                                        1U, 10000U);
 293
 294        if (err < 0) {
 295                bool is_locked;
 296
 297                hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
 298                is_locked = hw_atl_sem_ram_get(self);
 299                if (!is_locked) {
 300                        err = -ETIME;
 301                        goto err_exit;
 302                }
 303        }
 304
 305        aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
 306
 307        for (++cnt; --cnt && !err;) {
 308                aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
 309
 310                if (IS_CHIP_FEATURE(REVISION_B1))
 311                        err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
 312                                                        self, val, val != a,
 313                                                        1U, 1000U);
 314                else
 315                        err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
 316                                                        self, val,
 317                                                        !(val & 0x100),
 318                                                        1U, 1000U);
 319
 320                *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
 321                a += 4;
 322        }
 323
 324        hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
 325
 326err_exit:
 327        return err;
 328}
 329
 330static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
 331                                         u32 cnt)
 332{
 333        u32 val;
 334        int err = 0;
 335
 336        err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
 337                                        val, val == 1U,
 338                                        10U, 100000U);
 339        if (err < 0)
 340                goto err_exit;
 341
 342        if (IS_CHIP_FEATURE(REVISION_B1)) {
 343                u32 offset = 0;
 344
 345                for (; offset < cnt; ++offset) {
 346                        aq_hw_write_reg(self, 0x328, p[offset]);
 347                        aq_hw_write_reg(self, 0x32C,
 348                                        (0x80000000 | (0xFFFF & (offset * 4))));
 349                        hw_atl_mcp_up_force_intr_set(self, 1);
 350                        /* 1000 times by 10us = 10ms */
 351                        err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
 352                                                        self, val,
 353                                                        (val & 0xF0000000) !=
 354                                                        0x80000000,
 355                                                        10U, 10000U);
 356                }
 357        } else {
 358                u32 offset = 0;
 359
 360                aq_hw_write_reg(self, 0x208, a);
 361
 362                for (; offset < cnt; ++offset) {
 363                        aq_hw_write_reg(self, 0x20C, p[offset]);
 364                        aq_hw_write_reg(self, 0x200, 0xC000);
 365
 366                        err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
 367                                                        self, val,
 368                                                        (val & 0x100) == 0,
 369                                                        1000U, 10000U);
 370                }
 371        }
 372
 373        hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
 374
 375err_exit:
 376        return err;
 377}
 378
 379static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
 380{
 381        int err = 0;
 382        const u32 dw_major_mask = 0xff000000U;
 383        const u32 dw_minor_mask = 0x00ffffffU;
 384
 385        err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
 386        if (err < 0)
 387                goto err_exit;
 388        err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
 389                -EOPNOTSUPP : 0;
 390err_exit:
 391        return err;
 392}
 393
 394static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
 395                                 const struct aq_hw_caps_s *aq_hw_caps)
 396{
 397        int err = 0;
 398
 399        if (!aq_hw_read_reg(self, 0x370U)) {
 400                unsigned int rnd = 0U;
 401                unsigned int ucp_0x370 = 0U;
 402
 403                get_random_bytes(&rnd, sizeof(unsigned int));
 404
 405                ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
 406                aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
 407        }
 408
 409        hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
 410
 411        /* check 10 times by 1ms */
 412        err = readx_poll_timeout_atomic(hw_atl_scrpad25_get,
 413                                        self, self->mbox_addr,
 414                                        self->mbox_addr != 0U,
 415                                        1000U, 10000U);
 416
 417        return err;
 418}
 419
 420struct aq_hw_atl_utils_fw_rpc_tid_s {
 421        union {
 422                u32 val;
 423                struct {
 424                        u16 tid;
 425                        u16 len;
 426                };
 427        };
 428};
 429
 430#define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
 431
 432int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
 433{
 434        int err = 0;
 435        struct aq_hw_atl_utils_fw_rpc_tid_s sw;
 436
 437        if (!IS_CHIP_FEATURE(MIPS)) {
 438                err = -1;
 439                goto err_exit;
 440        }
 441        err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
 442                                            (u32 *)(void *)&self->rpc,
 443                                            (rpc_size + sizeof(u32) -
 444                                             sizeof(u8)) / sizeof(u32));
 445        if (err < 0)
 446                goto err_exit;
 447
 448        sw.tid = 0xFFFFU & (++self->rpc_tid);
 449        sw.len = (u16)rpc_size;
 450        aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
 451
 452err_exit:
 453        return err;
 454}
 455
 456int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
 457                             struct hw_atl_utils_fw_rpc **rpc)
 458{
 459        int err = 0;
 460        struct aq_hw_atl_utils_fw_rpc_tid_s sw;
 461        struct aq_hw_atl_utils_fw_rpc_tid_s fw;
 462
 463        do {
 464                sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
 465
 466                self->rpc_tid = sw.tid;
 467
 468                err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get,
 469                                                self, fw.val,
 470                                                sw.tid == fw.tid,
 471                                                1000U, 100000U);
 472
 473                if (fw.len == 0xFFFFU) {
 474                        err = hw_atl_utils_fw_rpc_call(self, sw.len);
 475                        if (err < 0)
 476                                goto err_exit;
 477                }
 478        } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
 479
 480        if (rpc) {
 481                if (fw.len) {
 482                        err =
 483                        hw_atl_utils_fw_downld_dwords(self,
 484                                                      self->rpc_addr,
 485                                                      (u32 *)(void *)
 486                                                      &self->rpc,
 487                                                      (fw.len + sizeof(u32) -
 488                                                       sizeof(u8)) /
 489                                                      sizeof(u32));
 490                        if (err < 0)
 491                                goto err_exit;
 492                }
 493
 494                *rpc = &self->rpc;
 495        }
 496
 497err_exit:
 498        return err;
 499}
 500
 501static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
 502{
 503        int err = 0;
 504
 505        err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
 506        if (err < 0)
 507                goto err_exit;
 508
 509        err = hw_atl_utils_fw_rpc_init(self);
 510        if (err < 0)
 511                goto err_exit;
 512
 513err_exit:
 514        return err;
 515}
 516
 517int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
 518                               struct hw_atl_utils_mbox_header *pmbox)
 519{
 520        return hw_atl_utils_fw_downld_dwords(self,
 521                                             self->mbox_addr,
 522                                             (u32 *)(void *)pmbox,
 523                                             sizeof(*pmbox) / sizeof(u32));
 524}
 525
 526void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
 527                                 struct hw_atl_utils_mbox *pmbox)
 528{
 529        int err = 0;
 530
 531        err = hw_atl_utils_fw_downld_dwords(self,
 532                                            self->mbox_addr,
 533                                            (u32 *)(void *)pmbox,
 534                                            sizeof(*pmbox) / sizeof(u32));
 535        if (err < 0)
 536                goto err_exit;
 537
 538        if (IS_CHIP_FEATURE(REVISION_A0)) {
 539                unsigned int mtu = self->aq_nic_cfg ?
 540                                        self->aq_nic_cfg->mtu : 1514U;
 541                pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
 542                pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
 543                pmbox->stats.dpc = atomic_read(&self->dpc);
 544        } else {
 545                pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
 546        }
 547
 548err_exit:;
 549}
 550
 551static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
 552{
 553        u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
 554
 555        val = val & ~HW_ATL_MPI_SPEED_MSK;
 556        val |= speed << HW_ATL_MPI_SPEED_SHIFT;
 557        aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
 558
 559        return 0;
 560}
 561
 562static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
 563                                      enum hal_atl_utils_fw_state_e state)
 564{
 565        int err = 0;
 566        u32 transaction_id = 0;
 567        struct hw_atl_utils_mbox_header mbox;
 568        u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
 569
 570        if (state == MPI_RESET) {
 571                hw_atl_utils_mpi_read_mbox(self, &mbox);
 572
 573                transaction_id = mbox.transaction_id;
 574
 575                err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid,
 576                                                self, mbox.transaction_id,
 577                                                transaction_id !=
 578                                                mbox.transaction_id,
 579                                                1000U, 100000U);
 580                if (err < 0)
 581                        goto err_exit;
 582        }
 583        /* On interface DEINIT we disable DW (raise bit)
 584         * Otherwise enable DW (clear bit)
 585         */
 586        if (state == MPI_DEINIT || state == MPI_POWER)
 587                val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
 588        else
 589                val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
 590
 591        /* Set new state bits */
 592        val = val & ~HW_ATL_MPI_STATE_MSK;
 593        val |= state & HW_ATL_MPI_STATE_MSK;
 594
 595        aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
 596err_exit:
 597        return err;
 598}
 599
 600int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
 601{
 602        u32 cp0x036C = hw_atl_utils_mpi_get_state(self);
 603        u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
 604        struct aq_hw_link_status_s *link_status = &self->aq_link_status;
 605
 606        if (!link_speed_mask) {
 607                link_status->mbps = 0U;
 608        } else {
 609                switch (link_speed_mask) {
 610                case HAL_ATLANTIC_RATE_10G:
 611                        link_status->mbps = 10000U;
 612                        break;
 613
 614                case HAL_ATLANTIC_RATE_5G:
 615                case HAL_ATLANTIC_RATE_5GSR:
 616                        link_status->mbps = 5000U;
 617                        break;
 618
 619                case HAL_ATLANTIC_RATE_2GS:
 620                        link_status->mbps = 2500U;
 621                        break;
 622
 623                case HAL_ATLANTIC_RATE_1G:
 624                        link_status->mbps = 1000U;
 625                        break;
 626
 627                case HAL_ATLANTIC_RATE_100M:
 628                        link_status->mbps = 100U;
 629                        break;
 630
 631                default:
 632                        return -EBUSY;
 633                }
 634        }
 635
 636        return 0;
 637}
 638
 639int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
 640                                   u8 *mac)
 641{
 642        int err = 0;
 643        u32 h = 0U;
 644        u32 l = 0U;
 645        u32 mac_addr[2];
 646
 647        if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
 648                unsigned int rnd = 0;
 649                unsigned int ucp_0x370 = 0;
 650
 651                get_random_bytes(&rnd, sizeof(unsigned int));
 652
 653                ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
 654                aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
 655        }
 656
 657        err = hw_atl_utils_fw_downld_dwords(self,
 658                                            aq_hw_read_reg(self, 0x00000374U) +
 659                                            (40U * 4U),
 660                                            mac_addr,
 661                                            ARRAY_SIZE(mac_addr));
 662        if (err < 0) {
 663                mac_addr[0] = 0U;
 664                mac_addr[1] = 0U;
 665                err = 0;
 666        } else {
 667                mac_addr[0] = __swab32(mac_addr[0]);
 668                mac_addr[1] = __swab32(mac_addr[1]);
 669        }
 670
 671        ether_addr_copy(mac, (u8 *)mac_addr);
 672
 673        if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
 674                /* chip revision */
 675                l = 0xE3000000U |
 676                    (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) |
 677                    (0x00 << 16);
 678                h = 0x8001300EU;
 679
 680                mac[5] = (u8)(0xFFU & l);
 681                l >>= 8;
 682                mac[4] = (u8)(0xFFU & l);
 683                l >>= 8;
 684                mac[3] = (u8)(0xFFU & l);
 685                l >>= 8;
 686                mac[2] = (u8)(0xFFU & l);
 687                mac[1] = (u8)(0xFFU & h);
 688                h >>= 8;
 689                mac[0] = (u8)(0xFFU & h);
 690        }
 691
 692        return err;
 693}
 694
 695unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
 696{
 697        unsigned int ret = 0U;
 698
 699        switch (mbps) {
 700        case 100U:
 701                ret = 5U;
 702                break;
 703
 704        case 1000U:
 705                ret = 4U;
 706                break;
 707
 708        case 2500U:
 709                ret = 3U;
 710                break;
 711
 712        case 5000U:
 713                ret = 1U;
 714                break;
 715
 716        case 10000U:
 717                ret = 0U;
 718                break;
 719
 720        default:
 721                break;
 722        }
 723        return ret;
 724}
 725
 726void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
 727{
 728        u32 chip_features = 0U;
 729        u32 val = hw_atl_reg_glb_mif_id_get(self);
 730        u32 mif_rev = val & 0xFFU;
 731
 732        if ((0xFU & mif_rev) == 1U) {
 733                chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
 734                        HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
 735                        HAL_ATLANTIC_UTILS_CHIP_MIPS;
 736        } else if ((0xFU & mif_rev) == 2U) {
 737                chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
 738                        HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
 739                        HAL_ATLANTIC_UTILS_CHIP_MIPS |
 740                        HAL_ATLANTIC_UTILS_CHIP_TPO2 |
 741                        HAL_ATLANTIC_UTILS_CHIP_RPF2;
 742        } else if ((0xFU & mif_rev) == 0xAU) {
 743                chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
 744                        HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
 745                        HAL_ATLANTIC_UTILS_CHIP_MIPS |
 746                        HAL_ATLANTIC_UTILS_CHIP_TPO2 |
 747                        HAL_ATLANTIC_UTILS_CHIP_RPF2;
 748        }
 749
 750        *p = chip_features;
 751}
 752
 753static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
 754{
 755        hw_atl_utils_mpi_set_speed(self, 0);
 756        hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
 757        return 0;
 758}
 759
 760int hw_atl_utils_update_stats(struct aq_hw_s *self)
 761{
 762        struct hw_atl_utils_mbox mbox;
 763        struct aq_stats_s *cs = &self->curr_stats;
 764
 765        hw_atl_utils_mpi_read_stats(self, &mbox);
 766
 767#define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
 768                        mbox.stats._N_ - self->last_stats._N_)
 769
 770        if (self->aq_link_status.mbps) {
 771                AQ_SDELTA(uprc);
 772                AQ_SDELTA(mprc);
 773                AQ_SDELTA(bprc);
 774                AQ_SDELTA(erpt);
 775
 776                AQ_SDELTA(uptc);
 777                AQ_SDELTA(mptc);
 778                AQ_SDELTA(bptc);
 779                AQ_SDELTA(erpr);
 780
 781                AQ_SDELTA(ubrc);
 782                AQ_SDELTA(ubtc);
 783                AQ_SDELTA(mbrc);
 784                AQ_SDELTA(mbtc);
 785                AQ_SDELTA(bbrc);
 786                AQ_SDELTA(bbtc);
 787                AQ_SDELTA(dpc);
 788        }
 789#undef AQ_SDELTA
 790
 791        cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
 792        cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
 793        cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
 794        cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
 795
 796        memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
 797
 798        return 0;
 799}
 800
 801struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
 802{
 803        return &self->curr_stats;
 804}
 805
 806static const u32 hw_atl_utils_hw_mac_regs[] = {
 807        0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
 808        0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
 809        0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
 810        0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
 811        0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
 812        0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
 813        0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
 814        0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
 815        0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
 816        0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
 817        0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
 818        0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
 819        0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
 820        0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
 821        0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
 822        0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
 823        0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
 824        0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
 825        0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
 826        0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
 827        0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
 828        0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
 829};
 830
 831int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
 832                             const struct aq_hw_caps_s *aq_hw_caps,
 833                             u32 *regs_buff)
 834{
 835        unsigned int i = 0U;
 836
 837        for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
 838                regs_buff[i] = aq_hw_read_reg(self,
 839                                              hw_atl_utils_hw_mac_regs[i]);
 840        return 0;
 841}
 842
 843int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
 844{
 845        *fw_version = aq_hw_read_reg(self, 0x18U);
 846        return 0;
 847}
 848
 849static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac)
 850{
 851        struct hw_atl_utils_fw_rpc *prpc = NULL;
 852        unsigned int rpc_size = 0U;
 853        int err = 0;
 854
 855        err = hw_atl_utils_fw_rpc_wait(self, &prpc);
 856        if (err < 0)
 857                goto err_exit;
 858
 859        memset(prpc, 0, sizeof(*prpc));
 860
 861        if (wol_enabled) {
 862                rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol);
 863
 864                prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
 865                prpc->msg_wol.priority =
 866                                HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR;
 867                prpc->msg_wol.pattern_id =
 868                                HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
 869                prpc->msg_wol.wol_packet_type =
 870                                HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT;
 871
 872                ether_addr_copy((u8 *)&prpc->msg_wol.wol_pattern, mac);
 873        } else {
 874                rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id);
 875
 876                prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
 877                prpc->msg_wol.pattern_id =
 878                                HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
 879        }
 880
 881        err = hw_atl_utils_fw_rpc_call(self, rpc_size);
 882
 883err_exit:
 884        return err;
 885}
 886
 887static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state,
 888                             u8 *mac)
 889{
 890        struct hw_atl_utils_fw_rpc *prpc = NULL;
 891        unsigned int rpc_size = 0U;
 892        int err = 0;
 893
 894        if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) {
 895                err = aq_fw1x_set_wol(self, 1, mac);
 896
 897                if (err < 0)
 898                        goto err_exit;
 899
 900                rpc_size = sizeof(prpc->msg_id) +
 901                           sizeof(prpc->msg_enable_wakeup);
 902
 903                err = hw_atl_utils_fw_rpc_wait(self, &prpc);
 904
 905                if (err < 0)
 906                        goto err_exit;
 907
 908                memset(prpc, 0, rpc_size);
 909
 910                prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
 911                prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
 912
 913                err = hw_atl_utils_fw_rpc_call(self, rpc_size);
 914                if (err < 0)
 915                        goto err_exit;
 916        }
 917        hw_atl_utils_mpi_set_speed(self, 0);
 918        hw_atl_utils_mpi_set_state(self, MPI_POWER);
 919
 920err_exit:
 921        return err;
 922}
 923
 924static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self)
 925{
 926        struct hw_atl_utils_mbox_header mbox;
 927
 928        hw_atl_utils_mpi_read_mbox(self, &mbox);
 929
 930        return mbox.transaction_id;
 931}
 932
 933static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self)
 934{
 935        return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
 936}
 937
 938static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self)
 939{
 940        return aq_hw_read_reg(self, HW_ATL_MIF_CMD);
 941}
 942
 943static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self)
 944{
 945        return aq_hw_read_reg(self, HW_ATL_MIF_ADDR);
 946}
 947
 948static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
 949{
 950        return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
 951}
 952
 953const struct aq_fw_ops aq_fw_1x_ops = {
 954        .init = hw_atl_utils_mpi_create,
 955        .deinit = hw_atl_fw1x_deinit,
 956        .reset = NULL,
 957        .get_mac_permanent = hw_atl_utils_get_mac_permanent,
 958        .set_link_speed = hw_atl_utils_mpi_set_speed,
 959        .set_state = hw_atl_utils_mpi_set_state,
 960        .update_link_status = hw_atl_utils_mpi_get_link_status,
 961        .update_stats = hw_atl_utils_update_stats,
 962        .get_phy_temp = NULL,
 963        .set_power = aq_fw1x_set_power,
 964        .set_eee_rate = NULL,
 965        .get_eee_rate = NULL,
 966        .set_flow_control = NULL,
 967};
 968