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