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