2 * aQuantia Corporation Network Driver
3 * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved
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.
10 /* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
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"
22 #include <linux/random.h>
24 #define HW_ATL_UCP_0X370_REG 0x0370U
26 #define HW_ATL_FW_SM_RAM 0x2U
27 #define HW_ATL_MPI_CONTROL_ADR 0x0368U
28 #define HW_ATL_MPI_STATE_ADR 0x036CU
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
35 static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
40 AQ_HW_WAIT_FOR(reg_glb_cpu_sem_get(self,
41 HW_ATL_FW_SM_RAM) == 1U,
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);
55 aq_hw_write_reg(self, 0x00000208U, a);
60 aq_hw_write_reg(self, 0x00000200U, 0x00008000U);
63 (0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
66 *(p++) = aq_hw_read_reg(self, 0x0000020CU);
69 reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
75 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
81 is_locked = reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
87 aq_hw_write_reg(self, 0x00000208U, a);
92 aq_hw_write_reg(self, 0x0000020CU, *(p++));
93 aq_hw_write_reg(self, 0x00000200U, 0xC000U);
96 (0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
100 reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
106 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
109 const u32 dw_major_mask = 0xff000000U;
110 const u32 dw_minor_mask = 0x00ffffffU;
112 err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
115 err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
121 static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
122 struct aq_hw_caps_s *aq_hw_caps)
126 if (!aq_hw_read_reg(self, 0x370U)) {
127 unsigned int rnd = 0U;
128 unsigned int ucp_0x370 = 0U;
130 get_random_bytes(&rnd, sizeof(unsigned int));
132 ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
133 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
136 reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
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);
142 err = hw_atl_utils_ver_match(aq_hw_caps->fw_ver_expected,
143 aq_hw_read_reg(self, 0x18U));
147 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
148 #define HW_ATL_RPC_STATE_ADR 0x033CU
150 struct aq_hw_atl_utils_fw_rpc_tid_s {
160 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
162 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
165 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
167 if (!IS_CHIP_FEATURE(MIPS)) {
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));
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);
186 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
187 struct hw_aq_atl_utils_fw_rpc **rpc)
190 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
191 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
194 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
196 PHAL_ATLANTIC->rpc_tid = sw.tid;
198 AQ_HW_WAIT_FOR(sw.tid ==
200 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
201 fw.tid), 1000U, 100U);
205 if (fw.len == 0xFFFFU) {
206 err = hw_atl_utils_fw_rpc_call(self, sw.len);
210 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
217 hw_atl_utils_fw_downld_dwords(self,
218 PHAL_ATLANTIC->rpc_addr,
221 (fw.len + sizeof(u32) -
228 *rpc = &PHAL_ATLANTIC->rpc;
235 static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
236 struct aq_hw_caps_s *aq_hw_caps)
240 err = hw_atl_utils_init_ucp(self, aq_hw_caps);
244 err = hw_atl_utils_fw_rpc_init(self);
252 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
253 struct hw_aq_atl_utils_mbox *pmbox)
257 err = hw_atl_utils_fw_downld_dwords(self,
258 PHAL_ATLANTIC->mbox_addr,
259 (u32 *)(void *)pmbox,
260 sizeof(*pmbox) / sizeof(u32));
264 if (pmbox != &PHAL_ATLANTIC->mbox)
265 memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));
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);
274 pmbox->stats.dpc = reg_rx_dma_stat_counter7get(self);
280 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
281 enum hal_atl_utils_fw_state_e state)
285 ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state;
286 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368);
291 void hw_atl_utils_mpi_set(struct aq_hw_s *self,
292 enum hal_atl_utils_fw_state_e state, u32 speed)
295 u32 transaction_id = 0;
297 if (state == MPI_RESET) {
298 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
300 transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
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),
311 err = hw_atl_utils_mpi_set_speed(self, speed, state);
316 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
318 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
319 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
320 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
322 if (!link_speed_mask) {
323 link_status->mbps = 0U;
325 switch (link_speed_mask) {
326 case HAL_ATLANTIC_RATE_10G:
327 link_status->mbps = 10000U;
330 case HAL_ATLANTIC_RATE_5G:
331 case HAL_ATLANTIC_RATE_5GSR:
332 link_status->mbps = 5000U;
335 case HAL_ATLANTIC_RATE_2GS:
336 link_status->mbps = 2500U;
339 case HAL_ATLANTIC_RATE_1G:
340 link_status->mbps = 1000U;
343 case HAL_ATLANTIC_RATE_100M:
344 link_status->mbps = 100U;
348 link_status->mbps = 0U;
356 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
357 struct aq_hw_caps_s *aq_hw_caps,
365 self->mmio = aq_pci_func_get_mmio(self->aq_pci_func);
367 hw_atl_utils_hw_chip_features_init(self,
368 &PHAL_ATLANTIC_A0->chip_features);
370 err = hw_atl_utils_mpi_create(self, aq_hw_caps);
374 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
375 unsigned int rnd = 0;
376 unsigned int ucp_0x370 = 0;
378 get_random_bytes(&rnd, sizeof(unsigned int));
380 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
381 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
384 err = hw_atl_utils_fw_downld_dwords(self,
385 aq_hw_read_reg(self, 0x00000374U) +
394 mac_addr[0] = __swab32(mac_addr[0]);
395 mac_addr[1] = __swab32(mac_addr[1]);
398 ether_addr_copy(mac, (u8 *)mac_addr);
400 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
403 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
407 mac[5] = (u8)(0xFFU & l);
409 mac[4] = (u8)(0xFFU & l);
411 mac[3] = (u8)(0xFFU & l);
413 mac[2] = (u8)(0xFFU & l);
414 mac[1] = (u8)(0xFFU & h);
416 mac[0] = (u8)(0xFFU & h);
423 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
425 unsigned int ret = 0U;
454 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
456 u32 chip_features = 0U;
457 u32 val = reg_glb_mif_id_get(self);
458 u32 mif_rev = val & 0xFFU;
460 if ((3U & mif_rev) == 1U) {
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) {
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;
477 int hw_atl_utils_hw_deinit(struct aq_hw_s *self)
479 hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U);
483 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
484 unsigned int power_state)
486 hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U);
490 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
491 u64 *data, unsigned int *p_count)
493 struct hw_atl_stats_s *stats = NULL;
496 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
498 stats = &PHAL_ATLANTIC->mbox.stats;
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;
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,
554 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
555 struct aq_hw_caps_s *aq_hw_caps,
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]);
566 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
568 *fw_version = aq_hw_read_reg(self, 0x18U);