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