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_hw.h" 15 #include "../aq_hw_utils.h" 16 #include "../aq_pci_func.h" 17 #include "../aq_ring.h" 18 #include "../aq_vec.h" 19 #include "hw_atl_utils.h" 20 #include "hw_atl_llh.h" 21 22 #include <linux/random.h> 23 24 #define HW_ATL_UCP_0X370_REG 0x0370U 25 26 #define HW_ATL_FW_SM_RAM 0x2U 27 #define HW_ATL_MPI_CONTROL_ADR 0x0368U 28 #define HW_ATL_MPI_STATE_ADR 0x036CU 29 30 #define HW_ATL_MPI_STATE_MSK 0x00FFU 31 #define HW_ATL_MPI_STATE_SHIFT 0U 32 #define HW_ATL_MPI_SPEED_MSK 0xFFFFU 33 #define HW_ATL_MPI_SPEED_SHIFT 16U 34 35 static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, 36 u32 *p, u32 cnt) 37 { 38 int err = 0; 39 40 AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(self, 41 HW_ATL_FW_SM_RAM) == 1U, 42 1U, 10000U); 43 44 if (err < 0) { 45 bool is_locked; 46 47 reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 48 is_locked = reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); 49 if (!is_locked) { 50 err = -ETIME; 51 goto err_exit; 52 } 53 } 54 55 aq_hw_write_reg(self, 0x00000208U, a); 56 57 for (++cnt; --cnt;) { 58 u32 i = 0U; 59 60 aq_hw_write_reg(self, 0x00000200U, 0x00008000U); 61 62 for (i = 1024U; 63 (0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) { 64 } 65 66 *(p++) = aq_hw_read_reg(self, 0x0000020CU); 67 } 68 69 reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 70 71 err_exit: 72 return err; 73 } 74 75 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p, 76 u32 cnt) 77 { 78 int err = 0; 79 bool is_locked; 80 81 is_locked = reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM); 82 if (!is_locked) { 83 err = -ETIME; 84 goto err_exit; 85 } 86 87 aq_hw_write_reg(self, 0x00000208U, a); 88 89 for (++cnt; --cnt;) { 90 u32 i = 0U; 91 92 aq_hw_write_reg(self, 0x0000020CU, *(p++)); 93 aq_hw_write_reg(self, 0x00000200U, 0xC000U); 94 95 for (i = 1024U; 96 (0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) { 97 } 98 } 99 100 reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM); 101 102 err_exit: 103 return err; 104 } 105 106 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual) 107 { 108 int err = 0; 109 const u32 dw_major_mask = 0xff000000U; 110 const u32 dw_minor_mask = 0x00ffffffU; 111 112 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0; 113 if (err < 0) 114 goto err_exit; 115 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ? 116 -EOPNOTSUPP : 0; 117 err_exit: 118 return err; 119 } 120 121 static int hw_atl_utils_init_ucp(struct aq_hw_s *self, 122 struct aq_hw_caps_s *aq_hw_caps) 123 { 124 int err = 0; 125 126 if (!aq_hw_read_reg(self, 0x370U)) { 127 unsigned int rnd = 0U; 128 unsigned int ucp_0x370 = 0U; 129 130 get_random_bytes(&rnd, sizeof(unsigned int)); 131 132 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd); 133 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); 134 } 135 136 reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U); 137 138 /* check 10 times by 1ms */ 139 AQ_HW_WAIT_FOR(0U != (PHAL_ATLANTIC_A0->mbox_addr = 140 aq_hw_read_reg(self, 0x360U)), 1000U, 10U); 141 142 err = hw_atl_utils_ver_match(aq_hw_caps->fw_ver_expected, 143 aq_hw_read_reg(self, 0x18U)); 144 return err; 145 } 146 147 #define HW_ATL_RPC_CONTROL_ADR 0x0338U 148 #define HW_ATL_RPC_STATE_ADR 0x033CU 149 150 struct aq_hw_atl_utils_fw_rpc_tid_s { 151 union { 152 u32 val; 153 struct { 154 u16 tid; 155 u16 len; 156 }; 157 }; 158 }; 159 160 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL) 161 162 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size) 163 { 164 int err = 0; 165 struct aq_hw_atl_utils_fw_rpc_tid_s sw; 166 167 if (!IS_CHIP_FEATURE(MIPS)) { 168 err = -1; 169 goto err_exit; 170 } 171 err = hw_atl_utils_fw_upload_dwords(self, PHAL_ATLANTIC->rpc_addr, 172 (u32 *)(void *)&PHAL_ATLANTIC->rpc, 173 (rpc_size + sizeof(u32) - 174 sizeof(u8)) / sizeof(u32)); 175 if (err < 0) 176 goto err_exit; 177 178 sw.tid = 0xFFFFU & (++PHAL_ATLANTIC->rpc_tid); 179 sw.len = (u16)rpc_size; 180 aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val); 181 182 err_exit: 183 return err; 184 } 185 186 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self, 187 struct hw_aq_atl_utils_fw_rpc **rpc) 188 { 189 int err = 0; 190 struct aq_hw_atl_utils_fw_rpc_tid_s sw; 191 struct aq_hw_atl_utils_fw_rpc_tid_s fw; 192 193 do { 194 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR); 195 196 PHAL_ATLANTIC->rpc_tid = sw.tid; 197 198 AQ_HW_WAIT_FOR(sw.tid == 199 (fw.val = 200 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR), 201 fw.tid), 1000U, 100U); 202 if (err < 0) 203 goto err_exit; 204 205 if (fw.len == 0xFFFFU) { 206 err = hw_atl_utils_fw_rpc_call(self, sw.len); 207 if (err < 0) 208 goto err_exit; 209 } 210 } while (sw.tid != fw.tid || 0xFFFFU == fw.len); 211 if (err < 0) 212 goto err_exit; 213 214 if (rpc) { 215 if (fw.len) { 216 err = 217 hw_atl_utils_fw_downld_dwords(self, 218 PHAL_ATLANTIC->rpc_addr, 219 (u32 *)(void *) 220 &PHAL_ATLANTIC->rpc, 221 (fw.len + sizeof(u32) - 222 sizeof(u8)) / 223 sizeof(u32)); 224 if (err < 0) 225 goto err_exit; 226 } 227 228 *rpc = &PHAL_ATLANTIC->rpc; 229 } 230 231 err_exit: 232 return err; 233 } 234 235 static int hw_atl_utils_mpi_create(struct aq_hw_s *self, 236 struct aq_hw_caps_s *aq_hw_caps) 237 { 238 int err = 0; 239 240 err = hw_atl_utils_init_ucp(self, aq_hw_caps); 241 if (err < 0) 242 goto err_exit; 243 244 err = hw_atl_utils_fw_rpc_init(self); 245 if (err < 0) 246 goto err_exit; 247 248 err_exit: 249 return err; 250 } 251 252 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, 253 struct hw_aq_atl_utils_mbox *pmbox) 254 { 255 int err = 0; 256 257 err = hw_atl_utils_fw_downld_dwords(self, 258 PHAL_ATLANTIC->mbox_addr, 259 (u32 *)(void *)pmbox, 260 sizeof(*pmbox) / sizeof(u32)); 261 if (err < 0) 262 goto err_exit; 263 264 if (pmbox != &PHAL_ATLANTIC->mbox) 265 memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox)); 266 267 if (IS_CHIP_FEATURE(REVISION_A0)) { 268 unsigned int mtu = self->aq_nic_cfg ? 269 self->aq_nic_cfg->mtu : 1514U; 270 pmbox->stats.ubrc = pmbox->stats.uprc * mtu; 271 pmbox->stats.ubtc = pmbox->stats.uptc * mtu; 272 pmbox->stats.dpc = atomic_read(&PHAL_ATLANTIC_A0->dpc); 273 } else { 274 pmbox->stats.dpc = reg_rx_dma_stat_counter7get(self); 275 } 276 277 err_exit:; 278 } 279 280 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed, 281 enum hal_atl_utils_fw_state_e state) 282 { 283 u32 ucp_0x368 = 0; 284 285 ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state; 286 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368); 287 288 return 0; 289 } 290 291 void hw_atl_utils_mpi_set(struct aq_hw_s *self, 292 enum hal_atl_utils_fw_state_e state, u32 speed) 293 { 294 int err = 0; 295 u32 transaction_id = 0; 296 297 if (state == MPI_RESET) { 298 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox); 299 300 transaction_id = PHAL_ATLANTIC->mbox.transaction_id; 301 302 AQ_HW_WAIT_FOR(transaction_id != 303 (hw_atl_utils_mpi_read_stats 304 (self, &PHAL_ATLANTIC->mbox), 305 PHAL_ATLANTIC->mbox.transaction_id), 306 1000U, 100U); 307 if (err < 0) 308 goto err_exit; 309 } 310 311 err = hw_atl_utils_mpi_set_speed(self, speed, state); 312 313 err_exit:; 314 } 315 316 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self, 317 struct aq_hw_link_status_s *link_status) 318 { 319 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR); 320 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT; 321 322 if (!link_speed_mask) { 323 link_status->mbps = 0U; 324 } else { 325 switch (link_speed_mask) { 326 case HAL_ATLANTIC_RATE_10G: 327 link_status->mbps = 10000U; 328 break; 329 330 case HAL_ATLANTIC_RATE_5G: 331 case HAL_ATLANTIC_RATE_5GSR: 332 link_status->mbps = 5000U; 333 break; 334 335 case HAL_ATLANTIC_RATE_2GS: 336 link_status->mbps = 2500U; 337 break; 338 339 case HAL_ATLANTIC_RATE_1G: 340 link_status->mbps = 1000U; 341 break; 342 343 case HAL_ATLANTIC_RATE_100M: 344 link_status->mbps = 100U; 345 break; 346 347 default: 348 link_status->mbps = 0U; 349 break; 350 } 351 } 352 353 return 0; 354 } 355 356 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, 357 struct aq_hw_caps_s *aq_hw_caps, 358 u8 *mac) 359 { 360 int err = 0; 361 u32 h = 0U; 362 u32 l = 0U; 363 u32 mac_addr[2]; 364 365 self->mmio = aq_pci_func_get_mmio(self->aq_pci_func); 366 367 hw_atl_utils_hw_chip_features_init(self, 368 &PHAL_ATLANTIC_A0->chip_features); 369 370 err = hw_atl_utils_mpi_create(self, aq_hw_caps); 371 if (err < 0) 372 goto err_exit; 373 374 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) { 375 unsigned int rnd = 0; 376 unsigned int ucp_0x370 = 0; 377 378 get_random_bytes(&rnd, sizeof(unsigned int)); 379 380 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd); 381 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370); 382 } 383 384 err = hw_atl_utils_fw_downld_dwords(self, 385 aq_hw_read_reg(self, 0x00000374U) + 386 (40U * 4U), 387 mac_addr, 388 AQ_DIMOF(mac_addr)); 389 if (err < 0) { 390 mac_addr[0] = 0U; 391 mac_addr[1] = 0U; 392 err = 0; 393 } else { 394 mac_addr[0] = __swab32(mac_addr[0]); 395 mac_addr[1] = __swab32(mac_addr[1]); 396 } 397 398 ether_addr_copy(mac, (u8 *)mac_addr); 399 400 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { 401 /* chip revision */ 402 l = 0xE3000000U 403 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) 404 | (0x00 << 16); 405 h = 0x8001300EU; 406 407 mac[5] = (u8)(0xFFU & l); 408 l >>= 8; 409 mac[4] = (u8)(0xFFU & l); 410 l >>= 8; 411 mac[3] = (u8)(0xFFU & l); 412 l >>= 8; 413 mac[2] = (u8)(0xFFU & l); 414 mac[1] = (u8)(0xFFU & h); 415 h >>= 8; 416 mac[0] = (u8)(0xFFU & h); 417 } 418 419 err_exit: 420 return err; 421 } 422 423 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps) 424 { 425 unsigned int ret = 0U; 426 427 switch (mbps) { 428 case 100U: 429 ret = 5U; 430 break; 431 432 case 1000U: 433 ret = 4U; 434 break; 435 436 case 2500U: 437 ret = 3U; 438 break; 439 440 case 5000U: 441 ret = 1U; 442 break; 443 444 case 10000U: 445 ret = 0U; 446 break; 447 448 default: 449 break; 450 } 451 return ret; 452 } 453 454 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p) 455 { 456 u32 chip_features = 0U; 457 u32 val = reg_glb_mif_id_get(self); 458 u32 mif_rev = val & 0xFFU; 459 460 if ((3U & mif_rev) == 1U) { 461 chip_features |= 462 HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 | 463 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ | 464 HAL_ATLANTIC_UTILS_CHIP_MIPS; 465 } else if ((3U & mif_rev) == 2U) { 466 chip_features |= 467 HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 | 468 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ | 469 HAL_ATLANTIC_UTILS_CHIP_MIPS | 470 HAL_ATLANTIC_UTILS_CHIP_TPO2 | 471 HAL_ATLANTIC_UTILS_CHIP_RPF2; 472 } 473 474 *p = chip_features; 475 } 476 477 int hw_atl_utils_hw_deinit(struct aq_hw_s *self) 478 { 479 hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U); 480 return 0; 481 } 482 483 int hw_atl_utils_hw_set_power(struct aq_hw_s *self, 484 unsigned int power_state) 485 { 486 hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U); 487 return 0; 488 } 489 490 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self, 491 u64 *data, unsigned int *p_count) 492 { 493 struct hw_atl_stats_s *stats = NULL; 494 int i = 0; 495 496 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox); 497 498 stats = &PHAL_ATLANTIC->mbox.stats; 499 500 data[i] = stats->uprc + stats->mprc + stats->bprc; 501 data[++i] = stats->uprc; 502 data[++i] = stats->mprc; 503 data[++i] = stats->bprc; 504 data[++i] = stats->erpt; 505 data[++i] = stats->uptc + stats->mptc + stats->bptc; 506 data[++i] = stats->uptc; 507 data[++i] = stats->mptc; 508 data[++i] = stats->bptc; 509 data[++i] = stats->ubrc; 510 data[++i] = stats->ubtc; 511 data[++i] = stats->mbrc; 512 data[++i] = stats->mbtc; 513 data[++i] = stats->bbrc; 514 data[++i] = stats->bbtc; 515 data[++i] = stats->ubrc + stats->mbrc + stats->bbrc; 516 data[++i] = stats->ubtc + stats->mbtc + stats->bbtc; 517 data[++i] = stats_rx_dma_good_pkt_counterlsw_get(self); 518 data[++i] = stats_tx_dma_good_pkt_counterlsw_get(self); 519 data[++i] = stats_rx_dma_good_octet_counterlsw_get(self); 520 data[++i] = stats_tx_dma_good_octet_counterlsw_get(self); 521 data[++i] = stats->dpc; 522 523 if (p_count) 524 *p_count = ++i; 525 526 return 0; 527 } 528 529 static const u32 hw_atl_utils_hw_mac_regs[] = { 530 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U, 531 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U, 532 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U, 533 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U, 534 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U, 535 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U, 536 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U, 537 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U, 538 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U, 539 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U, 540 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U, 541 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U, 542 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U, 543 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U, 544 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U, 545 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U, 546 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU, 547 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU, 548 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U, 549 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U, 550 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U, 551 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U, 552 }; 553 554 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, 555 struct aq_hw_caps_s *aq_hw_caps, 556 u32 *regs_buff) 557 { 558 unsigned int i = 0U; 559 560 for (i = 0; i < aq_hw_caps->mac_regs_count; i++) 561 regs_buff[i] = aq_hw_read_reg(self, 562 hw_atl_utils_hw_mac_regs[i]); 563 return 0; 564 } 565 566 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) 567 { 568 *fw_version = aq_hw_read_reg(self, 0x18U); 569 return 0; 570 } 571