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