1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 2 /* Copyright (C) 2014-2017 aQuantia Corporation. */ 3 4 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware 5 * abstraction layer. 6 */ 7 8 #include <stdio.h> 9 #include <errno.h> 10 #include <stdint.h> 11 #include <string.h> 12 #include <unistd.h> 13 #include <stdarg.h> 14 #include <inttypes.h> 15 #include <rte_ether.h> 16 #include "../atl_hw_regs.h" 17 18 #include "hw_atl_llh.h" 19 #include "hw_atl_llh_internal.h" 20 #include "../atl_logs.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 51 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); 52 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, 53 enum hal_atl_utils_fw_state_e state); 54 55 56 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) 57 { 58 int err = 0; 59 60 err = hw_atl_utils_soft_reset(self); 61 if (err) 62 return err; 63 64 hw_atl_utils_hw_chip_features_init(self, 65 &self->chip_features); 66 67 hw_atl_utils_get_fw_version(self, &self->fw_ver_actual); 68 69 if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, 70 self->fw_ver_actual) == 0) { 71 *fw_ops = &aq_fw_1x_ops; 72 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, 73 self->fw_ver_actual) == 0) { 74 *fw_ops = &aq_fw_2x_ops; 75 } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, 76 self->fw_ver_actual) == 0) { 77 *fw_ops = &aq_fw_2x_ops; 78 } else { 79 PMD_DRV_LOG(ERR, "Bad FW version detected: %x\n", 80 self->fw_ver_actual); 81 return -EOPNOTSUPP; 82 } 83 self->aq_fw_ops = *fw_ops; 84 err = self->aq_fw_ops->init(self); 85 return err; 86 } 87 88 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self) 89 { 90 u32 gsr, val; 91 int k = 0; 92 93 aq_hw_write_reg(self, 0x404, 0x40e1); 94 AQ_HW_SLEEP(50); 95 96 /* Cleanup SPI */ 97 val = aq_hw_read_reg(self, 0x53C); 98 aq_hw_write_reg(self, 0x53C, val | 0x10); 99 100 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); 101 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000); 102 103 /* Kickstart MAC */ 104 aq_hw_write_reg(self, 0x404, 0x80e0); 105 aq_hw_write_reg(self, 0x32a8, 0x0); 106 aq_hw_write_reg(self, 0x520, 0x1); 107 108 /* Reset SPI again because of possible interrupted SPI burst */ 109 val = aq_hw_read_reg(self, 0x53C); 110 aq_hw_write_reg(self, 0x53C, val | 0x10); 111 AQ_HW_SLEEP(10); 112 /* Clear SPI reset state */ 113 aq_hw_write_reg(self, 0x53C, val & ~0x10); 114 115 aq_hw_write_reg(self, 0x404, 0x180e0); 116 117 for (k = 0; k < 1000; k++) { 118 u32 flb_status = aq_hw_read_reg(self, 119 HW_ATL_MPI_DAISY_CHAIN_STATUS); 120 121 flb_status = flb_status & 0x10; 122 if (flb_status) 123 break; 124 AQ_HW_SLEEP(10); 125 } 126 if (k == 1000) { 127 PMD_DRV_LOG(ERR, "MAC kickstart failed\n"); 128 return -EIO; 129 } 130 131 /* FW reset */ 132 aq_hw_write_reg(self, 0x404, 0x80e0); 133 AQ_HW_SLEEP(50); 134 aq_hw_write_reg(self, 0x3a0, 0x1); 135 136 /* Kickstart PHY - skipped */ 137 138 /* Global software reset*/ 139 hw_atl_rx_rx_reg_res_dis_set(self, 0U); 140 hw_atl_tx_tx_reg_res_dis_set(self, 0U); 141 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL, 142 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT), 143 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0); 144 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); 145 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000); 146 147 for (k = 0; k < 1000; k++) { 148 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION); 149 150 if (fw_state) 151 break; 152 AQ_HW_SLEEP(10); 153 } 154 if (k == 1000) { 155 PMD_DRV_LOG(ERR, "FW kickstart failed\n"); 156 return -EIO; 157 } 158 /* Old FW requires fixed delay after init */ 159 AQ_HW_SLEEP(15); 160 161 return 0; 162 } 163 164 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) 165 { 166 u32 gsr, val, rbl_status; 167 int k; 168 169 aq_hw_write_reg(self, 0x404, 0x40e1); 170 aq_hw_write_reg(self, 0x3a0, 0x1); 171 aq_hw_write_reg(self, 0x32a8, 0x0); 172 173 /* Alter RBL status */ 174 aq_hw_write_reg(self, 0x388, 0xDEAD); 175 176 /* Cleanup SPI */ 177 val = aq_hw_read_reg(self, 0x53C); 178 aq_hw_write_reg(self, 0x53C, val | 0x10); 179 180 /* Global software reset*/ 181 hw_atl_rx_rx_reg_res_dis_set(self, 0U); 182 hw_atl_tx_tx_reg_res_dis_set(self, 0U); 183 aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL, 184 BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT), 185 HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0); 186 gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); 187 aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, 188 (gsr & 0xFFFFBFFF) | 0x8000); 189 190 if (FORCE_FLASHLESS) 191 aq_hw_write_reg(self, 0x534, 0x0); 192 193 aq_hw_write_reg(self, 0x404, 0x40e0); 194 195 /* Wait for RBL boot */ 196 for (k = 0; k < 1000; k++) { 197 rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF; 198 if (rbl_status && rbl_status != 0xDEAD) 199 break; 200 AQ_HW_SLEEP(10); 201 } 202 if (!rbl_status || rbl_status == 0xDEAD) { 203 PMD_DRV_LOG(ERR, "RBL Restart failed"); 204 return -EIO; 205 } 206 207 /* Restore NVR */ 208 if (FORCE_FLASHLESS) 209 aq_hw_write_reg(self, 0x534, 0xA0); 210 211 if (rbl_status == 0xF1A7) { 212 PMD_DRV_LOG(ERR, "No FW detected. Dynamic FW load not implemented\n"); 213 return -EOPNOTSUPP; 214 } 215 216 for (k = 0; k < 1000; k++) { 217 u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION); 218 219 if (fw_state) 220 break; 221 AQ_HW_SLEEP(10); 222 } 223 if (k == 1000) { 224 PMD_DRV_LOG(ERR, "FW kickstart failed\n"); 225 return -EIO; 226 } 227 /* Old FW requires fixed delay after init */ 228 AQ_HW_SLEEP(15); 229 230 return 0; 231 } 232 233 int hw_atl_utils_soft_reset(struct aq_hw_s *self) 234 { 235 int err = 0; 236 int k; 237 u32 boot_exit_code = 0; 238 239 for (k = 0; k < 1000; ++k) { 240 u32 flb_status = aq_hw_read_reg(self, 241 HW_ATL_MPI_DAISY_CHAIN_STATUS); 242 boot_exit_code = aq_hw_read_reg(self, 243 HW_ATL_MPI_BOOT_EXIT_CODE); 244 if (flb_status != 0x06000000 || boot_exit_code != 0) 245 break; 246 } 247 248 if (k == 1000) { 249 PMD_DRV_LOG(ERR, "Neither RBL nor FLB firmware started\n"); 250 return -EOPNOTSUPP; 251 } 252 253 self->rbl_enabled = (boot_exit_code != 0); 254 255 /* FW 1.x may bootup in an invalid POWER state (WOL feature). 256 * We should work around this by forcing its state back to DEINIT 257 */ 258 if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, 259 aq_hw_read_reg(self, 260 HW_ATL_MPI_FW_VERSION))) { 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 err = hw_atl_utils_soft_reset_rbl(self); 269 else 270 err = hw_atl_utils_soft_reset_flb(self); 271 272 return err; 273 } 274 275 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, 276 u32 *p, u32 cnt) 277 { 278 int err = 0; 279 280 AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self, 281 HW_ATL_FW_SM_RAM) == 1U, 282 1U, 10000U); 283 284 if (err < 0) { 285 bool is_locked; 286 287 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 288 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); 289 if (!is_locked) { 290 err = -ETIMEDOUT; 291 goto err_exit; 292 } 293 } 294 295 aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a); 296 297 for (++cnt; --cnt && !err;) { 298 aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U); 299 300 if (IS_CHIP_FEATURE(REVISION_B1)) 301 AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self, 302 HW_ATL_MIF_ADDR), 303 1, 1000U); 304 else 305 AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self, 306 HW_ATL_MIF_CMD)), 307 1, 1000U); 308 309 *(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL); 310 a += 4; 311 } 312 313 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 314 315 err_exit: 316 return err; 317 } 318 319 int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, 320 u32 cnt) 321 { 322 int err = 0; 323 bool is_locked; 324 325 is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); 326 if (!is_locked) { 327 err = -ETIMEDOUT; 328 goto err_exit; 329 } 330 if (IS_CHIP_FEATURE(REVISION_B1)) { 331 u32 offset = 0; 332 333 for (; offset < cnt; ++offset) { 334 aq_hw_write_reg(self, 0x328, p[offset]); 335 aq_hw_write_reg(self, 0x32C, 336 (0x80000000 | (0xFFFF & (offset * 4)))); 337 hw_atl_mcp_up_force_intr_set(self, 1); 338 /* 1000 times by 10us = 10ms */ 339 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 340 0x32C) & 0xF0000000) != 0x80000000, 341 10, 1000); 342 } 343 } else { 344 u32 offset = 0; 345 346 aq_hw_write_reg(self, 0x208, a); 347 348 for (; offset < cnt; ++offset) { 349 aq_hw_write_reg(self, 0x20C, p[offset]); 350 aq_hw_write_reg(self, 0x200, 0xC000); 351 352 AQ_HW_WAIT_FOR((aq_hw_read_reg(self, 0x200U) 353 & 0x100) == 0, 10, 1000); 354 } 355 } 356 357 hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 358 359 err_exit: 360 return err; 361 } 362 363 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) 364 { 365 int err = 0; 366 const u32 dw_major_mask = 0xff000000U; 367 const u32 dw_minor_mask = 0x00ffffffU; 368 369 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0; 370 if (err < 0) 371 goto err_exit; 372 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? 373 -EOPNOTSUPP : 0; 374 err_exit: 375 return err; 376 } 377 378 static int hw_atl_utils_init_ucp(struct aq_hw_s *self) 379 { 380 int err = 0; 381 382 if (!aq_hw_read_reg(self, 0x370U)) { 383 unsigned int rnd = (uint32_t)rte_rand(); 384 unsigned int ucp_0x370 = 0U; 385 386 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd); 387 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); 388 } 389 390 hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U); 391 392 /* check 10 times by 1ms */ 393 AQ_HW_WAIT_FOR(0U != (self->mbox_addr = 394 aq_hw_read_reg(self, 0x360U)), 1000U, 10U); 395 AQ_HW_WAIT_FOR(0U != (self->rpc_addr = 396 aq_hw_read_reg(self, 0x334U)), 1000U, 100U); 397 398 return err; 399 } 400 401 #define HW_ATL_RPC_CONTROL_ADR 0x0338U 402 #define HW_ATL_RPC_STATE_ADR 0x033CU 403 404 struct 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 416 int 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 436 err_exit: 437 return err; 438 } 439 440 int 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 485 err_exit: 486 return err; 487 } 488 489 static 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); 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 501 err_exit: 502 return err; 503 } 504 505 int 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 514 void 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 = 1514; 528 pmbox->stats.ubrc = pmbox->stats.uprc * mtu; 529 pmbox->stats.ubtc = pmbox->stats.uptc * mtu; 530 } else { 531 pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); 532 } 533 534 err_exit:; 535 } 536 537 static 538 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed) 539 { 540 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); 541 542 val = val & ~HW_ATL_MPI_SPEED_MSK; 543 val |= speed << HW_ATL_MPI_SPEED_SHIFT; 544 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); 545 546 return 0; 547 } 548 549 int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, 550 enum hal_atl_utils_fw_state_e state) 551 { 552 int err = 0; 553 u32 transaction_id = 0; 554 struct hw_aq_atl_utils_mbox_header mbox; 555 u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); 556 557 if (state == MPI_RESET) { 558 hw_atl_utils_mpi_read_mbox(self, &mbox); 559 560 transaction_id = mbox.transaction_id; 561 562 AQ_HW_WAIT_FOR(transaction_id != 563 (hw_atl_utils_mpi_read_mbox(self, &mbox), 564 mbox.transaction_id), 565 1000U, 100U); 566 if (err < 0) 567 goto err_exit; 568 } 569 /* On interface DEINIT we disable DW (raise bit) 570 * Otherwise enable DW (clear bit) 571 */ 572 if (state == MPI_DEINIT || state == MPI_POWER) 573 val |= HW_ATL_MPI_DIRTY_WAKE_MSK; 574 else 575 val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK; 576 577 /* Set new state bits */ 578 val = val & ~HW_ATL_MPI_STATE_MSK; 579 val |= state & HW_ATL_MPI_STATE_MSK; 580 581 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); 582 err_exit: 583 return err; 584 } 585 586 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) 587 { 588 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR); 589 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT; 590 struct aq_hw_link_status_s *link_status = &self->aq_link_status; 591 592 if (!link_speed_mask) { 593 link_status->mbps = 0U; 594 } else { 595 switch (link_speed_mask) { 596 case HAL_ATLANTIC_RATE_10G: 597 link_status->mbps = 10000U; 598 break; 599 600 case HAL_ATLANTIC_RATE_5G: 601 case HAL_ATLANTIC_RATE_5GSR: 602 link_status->mbps = 5000U; 603 break; 604 605 case HAL_ATLANTIC_RATE_2GS: 606 link_status->mbps = 2500U; 607 break; 608 609 case HAL_ATLANTIC_RATE_1G: 610 link_status->mbps = 1000U; 611 break; 612 613 case HAL_ATLANTIC_RATE_100M: 614 link_status->mbps = 100U; 615 break; 616 617 default: 618 return -EBUSY; 619 } 620 } 621 622 return 0; 623 } 624 625 static int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, 626 u8 *mac) 627 { 628 int err = 0; 629 u32 h = 0U; 630 u32 l = 0U; 631 u32 mac_addr[2]; 632 633 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) { 634 unsigned int rnd = (uint32_t)rte_rand(); 635 unsigned int ucp_0x370 = 0; 636 637 //get_random_bytes(&rnd, sizeof(unsigned int)); 638 639 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd); 640 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); 641 } 642 643 err = hw_atl_utils_fw_downld_dwords(self, 644 aq_hw_read_reg(self, 0x00000374U) + 645 (40U * 4U), 646 mac_addr, 647 ARRAY_SIZE(mac_addr)); 648 if (err < 0) { 649 mac_addr[0] = 0U; 650 mac_addr[1] = 0U; 651 err = 0; 652 } else { 653 mac_addr[0] = rte_constant_bswap32(mac_addr[0]); 654 mac_addr[1] = rte_constant_bswap32(mac_addr[1]); 655 } 656 657 ether_addr_copy((struct ether_addr *)mac_addr, 658 (struct ether_addr *)mac); 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 682 unsigned 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 713 void 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 740 static 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 747 int hw_atl_utils_update_stats(struct aq_hw_s *self) 748 { 749 struct hw_aq_atl_utils_mbox mbox; 750 751 hw_atl_utils_mpi_read_stats(self, &mbox); 752 753 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \ 754 mbox.stats._N_ - self->last_stats._N_) 755 756 if (1) {//self->aq_link_status.mbps) { 757 AQ_SDELTA(uprc); 758 AQ_SDELTA(mprc); 759 AQ_SDELTA(bprc); 760 AQ_SDELTA(erpt); 761 762 AQ_SDELTA(uptc); 763 AQ_SDELTA(mptc); 764 AQ_SDELTA(bptc); 765 AQ_SDELTA(erpr); 766 AQ_SDELTA(ubrc); 767 AQ_SDELTA(ubtc); 768 AQ_SDELTA(mbrc); 769 AQ_SDELTA(mbtc); 770 AQ_SDELTA(bbrc); 771 AQ_SDELTA(bbtc); 772 AQ_SDELTA(dpc); 773 } 774 #undef AQ_SDELTA 775 self->curr_stats.dma_pkt_rc = 776 hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self) + 777 ((u64)hw_atl_stats_rx_dma_good_pkt_countermsw_get(self) << 32); 778 self->curr_stats.dma_pkt_tc = 779 hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self) + 780 ((u64)hw_atl_stats_tx_dma_good_pkt_countermsw_get(self) << 32); 781 self->curr_stats.dma_oct_rc = 782 hw_atl_stats_rx_dma_good_octet_counterlsw_get(self) + 783 ((u64)hw_atl_stats_rx_dma_good_octet_countermsw_get(self) << 32); 784 self->curr_stats.dma_oct_tc = 785 hw_atl_stats_tx_dma_good_octet_counterlsw_get(self) + 786 ((u64)hw_atl_stats_tx_dma_good_octet_countermsw_get(self) << 32); 787 788 self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); 789 790 memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats)); 791 792 return 0; 793 } 794 795 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self) 796 { 797 return &self->curr_stats; 798 } 799 800 static const u32 hw_atl_utils_hw_mac_regs[] = { 801 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U, 802 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U, 803 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U, 804 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U, 805 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U, 806 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U, 807 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U, 808 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U, 809 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U, 810 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U, 811 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U, 812 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U, 813 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U, 814 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U, 815 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U, 816 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U, 817 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU, 818 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU, 819 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U, 820 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U, 821 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U, 822 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U, 823 }; 824 825 unsigned int hw_atl_utils_hw_get_reg_length(void) 826 { 827 return ARRAY_SIZE(hw_atl_utils_hw_mac_regs); 828 } 829 830 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, 831 u32 *regs_buff) 832 { 833 unsigned int i = 0U; 834 unsigned int mac_regs_count = hw_atl_utils_hw_get_reg_length(); 835 836 for (i = 0; i < mac_regs_count; i++) 837 regs_buff[i] = aq_hw_read_reg(self, 838 hw_atl_utils_hw_mac_regs[i]); 839 return 0; 840 } 841 842 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) 843 { 844 *fw_version = aq_hw_read_reg(self, 0x18U); 845 return 0; 846 } 847 848 static int aq_fw1x_set_wol(struct aq_hw_s *self, bool wol_enabled, u8 *mac) 849 { 850 struct hw_aq_atl_utils_fw_rpc *prpc = NULL; 851 unsigned int rpc_size = 0U; 852 int err = 0; 853 854 err = hw_atl_utils_fw_rpc_wait(self, &prpc); 855 if (err < 0) 856 goto err_exit; 857 858 memset(prpc, 0, sizeof(*prpc)); 859 860 if (wol_enabled) { 861 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_wol); 862 863 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD; 864 prpc->msg_wol.priority = 0x10000000; /* normal priority */ 865 prpc->msg_wol.pattern_id = 1U; 866 prpc->msg_wol.wol_packet_type = 2U; /* Magic Packet */ 867 868 ether_addr_copy((struct ether_addr *)mac, 869 (struct ether_addr *)&prpc->msg_wol.wol_pattern); 870 } else { 871 rpc_size = sizeof(prpc->msg_id) + sizeof(prpc->msg_del_id); 872 873 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL; 874 prpc->msg_wol.pattern_id = 1U; 875 } 876 877 err = hw_atl_utils_fw_rpc_call(self, rpc_size); 878 if (err < 0) 879 goto err_exit; 880 err_exit: 881 return err; 882 } 883 884 static 885 int aq_fw1x_set_power(struct aq_hw_s *self, 886 unsigned int power_state __rte_unused, 887 u8 *mac) 888 { 889 struct hw_aq_atl_utils_fw_rpc *prpc = NULL; 890 unsigned int rpc_size = 0U; 891 int err = 0; 892 if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { 893 err = aq_fw1x_set_wol(self, 1, mac); 894 895 if (err < 0) 896 goto err_exit; 897 898 rpc_size = sizeof(prpc->msg_id) + 899 sizeof(prpc->msg_enable_wakeup); 900 901 err = hw_atl_utils_fw_rpc_wait(self, &prpc); 902 903 if (err < 0) 904 goto err_exit; 905 906 memset(prpc, 0, rpc_size); 907 908 prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP; 909 prpc->msg_enable_wakeup.pattern_mask = 0x00000002; 910 911 err = hw_atl_utils_fw_rpc_call(self, rpc_size); 912 if (err < 0) 913 goto err_exit; 914 } 915 916 hw_atl_utils_mpi_set_speed(self, 0); 917 hw_atl_utils_mpi_set_state(self, MPI_POWER); 918 err_exit: 919 return err; 920 } 921 922 923 924 const struct aq_fw_ops aq_fw_1x_ops = { 925 .init = hw_atl_utils_mpi_create, 926 .deinit = hw_atl_fw1x_deinit, 927 .reset = NULL, 928 .get_mac_permanent = hw_atl_utils_get_mac_permanent, 929 .set_link_speed = hw_atl_utils_mpi_set_speed, 930 .set_state = hw_atl_utils_mpi_set_state, 931 .update_link_status = hw_atl_utils_mpi_get_link_status, 932 .update_stats = hw_atl_utils_update_stats, 933 .set_power = aq_fw1x_set_power, 934 .get_temp = NULL, 935 .get_cable_len = NULL, 936 .set_eee_rate = NULL, 937 .get_eee_rate = NULL, 938 .set_flow_control = NULL, 939 .led_control = NULL, 940 .get_eeprom = NULL, 941 .set_eeprom = NULL, 942 }; 943