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));
146 pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n",
148 aq_hw_caps->fw_ver_expected,
149 aq_hw_read_reg(self, 0x18U));
153 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
154 #define HW_ATL_RPC_STATE_ADR 0x033CU
156 struct aq_hw_atl_utils_fw_rpc_tid_s {
166 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
168 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
171 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
173 if (!IS_CHIP_FEATURE(MIPS)) {
177 err = hw_atl_utils_fw_upload_dwords(self, PHAL_ATLANTIC->rpc_addr,
178 (u32 *)(void *)&PHAL_ATLANTIC->rpc,
179 (rpc_size + sizeof(u32) -
180 sizeof(u8)) / sizeof(u32));
184 sw.tid = 0xFFFFU & (++PHAL_ATLANTIC->rpc_tid);
185 sw.len = (u16)rpc_size;
186 aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
192 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
193 struct hw_aq_atl_utils_fw_rpc **rpc)
196 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
197 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
200 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
202 PHAL_ATLANTIC->rpc_tid = sw.tid;
204 AQ_HW_WAIT_FOR(sw.tid ==
206 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
207 fw.tid), 1000U, 100U);
211 if (fw.len == 0xFFFFU) {
212 err = hw_atl_utils_fw_rpc_call(self, sw.len);
216 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
223 hw_atl_utils_fw_downld_dwords(self,
224 PHAL_ATLANTIC->rpc_addr,
227 (fw.len + sizeof(u32) -
234 *rpc = &PHAL_ATLANTIC->rpc;
241 static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
242 struct aq_hw_caps_s *aq_hw_caps)
246 err = hw_atl_utils_init_ucp(self, aq_hw_caps);
250 err = hw_atl_utils_fw_rpc_init(self);
258 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
259 struct hw_aq_atl_utils_mbox *pmbox)
263 err = hw_atl_utils_fw_downld_dwords(self,
264 PHAL_ATLANTIC->mbox_addr,
265 (u32 *)(void *)pmbox,
266 sizeof(*pmbox) / sizeof(u32));
270 if (pmbox != &PHAL_ATLANTIC->mbox)
271 memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));
273 if (IS_CHIP_FEATURE(REVISION_A0)) {
274 unsigned int mtu = self->aq_nic_cfg ?
275 self->aq_nic_cfg->mtu : 1514U;
276 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
277 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
278 pmbox->stats.dpc = atomic_read(&PHAL_ATLANTIC_A0->dpc);
280 pmbox->stats.dpc = reg_rx_dma_stat_counter7get(self);
286 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
287 enum hal_atl_utils_fw_state_e state)
291 ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state;
292 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368);
297 void hw_atl_utils_mpi_set(struct aq_hw_s *self,
298 enum hal_atl_utils_fw_state_e state, u32 speed)
301 u32 transaction_id = 0;
303 if (state == MPI_RESET) {
304 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
306 transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
308 AQ_HW_WAIT_FOR(transaction_id !=
309 (hw_atl_utils_mpi_read_stats
310 (self, &PHAL_ATLANTIC->mbox),
311 PHAL_ATLANTIC->mbox.transaction_id),
317 err = hw_atl_utils_mpi_set_speed(self, speed, state);
322 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
324 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
325 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
326 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
328 if (!link_speed_mask) {
329 link_status->mbps = 0U;
331 switch (link_speed_mask) {
332 case HAL_ATLANTIC_RATE_10G:
333 link_status->mbps = 10000U;
336 case HAL_ATLANTIC_RATE_5G:
337 case HAL_ATLANTIC_RATE_5GSR:
338 link_status->mbps = 5000U;
341 case HAL_ATLANTIC_RATE_2GS:
342 link_status->mbps = 2500U;
345 case HAL_ATLANTIC_RATE_1G:
346 link_status->mbps = 1000U;
349 case HAL_ATLANTIC_RATE_100M:
350 link_status->mbps = 100U;
361 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
362 struct aq_hw_caps_s *aq_hw_caps,
370 self->mmio = aq_pci_func_get_mmio(self->aq_pci_func);
372 hw_atl_utils_hw_chip_features_init(self,
373 &PHAL_ATLANTIC_A0->chip_features);
375 err = hw_atl_utils_mpi_create(self, aq_hw_caps);
379 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
380 unsigned int rnd = 0;
381 unsigned int ucp_0x370 = 0;
383 get_random_bytes(&rnd, sizeof(unsigned int));
385 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
386 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
389 err = hw_atl_utils_fw_downld_dwords(self,
390 aq_hw_read_reg(self, 0x00000374U) +
399 mac_addr[0] = __swab32(mac_addr[0]);
400 mac_addr[1] = __swab32(mac_addr[1]);
403 ether_addr_copy(mac, (u8 *)mac_addr);
405 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
408 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
412 mac[5] = (u8)(0xFFU & l);
414 mac[4] = (u8)(0xFFU & l);
416 mac[3] = (u8)(0xFFU & l);
418 mac[2] = (u8)(0xFFU & l);
419 mac[1] = (u8)(0xFFU & h);
421 mac[0] = (u8)(0xFFU & h);
428 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
430 unsigned int ret = 0U;
459 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
461 u32 chip_features = 0U;
462 u32 val = reg_glb_mif_id_get(self);
463 u32 mif_rev = val & 0xFFU;
465 if ((3U & mif_rev) == 1U) {
467 HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
468 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
469 HAL_ATLANTIC_UTILS_CHIP_MIPS;
470 } else if ((3U & mif_rev) == 2U) {
472 HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
473 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
474 HAL_ATLANTIC_UTILS_CHIP_MIPS |
475 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
476 HAL_ATLANTIC_UTILS_CHIP_RPF2;
482 int hw_atl_utils_hw_deinit(struct aq_hw_s *self)
484 hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U);
488 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
489 unsigned int power_state)
491 hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U);
495 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
496 u64 *data, unsigned int *p_count)
498 struct hw_atl_stats_s *stats = NULL;
501 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
503 stats = &PHAL_ATLANTIC->mbox.stats;
505 data[i] = stats->uprc + stats->mprc + stats->bprc;
506 data[++i] = stats->uprc;
507 data[++i] = stats->mprc;
508 data[++i] = stats->bprc;
509 data[++i] = stats->erpt;
510 data[++i] = stats->uptc + stats->mptc + stats->bptc;
511 data[++i] = stats->uptc;
512 data[++i] = stats->mptc;
513 data[++i] = stats->bptc;
514 data[++i] = stats->ubrc;
515 data[++i] = stats->ubtc;
516 data[++i] = stats->mbrc;
517 data[++i] = stats->mbtc;
518 data[++i] = stats->bbrc;
519 data[++i] = stats->bbtc;
520 data[++i] = stats->ubrc + stats->mbrc + stats->bbrc;
521 data[++i] = stats->ubtc + stats->mbtc + stats->bbtc;
522 data[++i] = stats_rx_dma_good_pkt_counterlsw_get(self);
523 data[++i] = stats_tx_dma_good_pkt_counterlsw_get(self);
524 data[++i] = stats_rx_dma_good_octet_counterlsw_get(self);
525 data[++i] = stats_tx_dma_good_octet_counterlsw_get(self);
526 data[++i] = stats->dpc;
534 static const u32 hw_atl_utils_hw_mac_regs[] = {
535 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
536 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
537 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
538 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
539 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
540 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
541 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
542 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
543 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
544 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
545 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
546 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
547 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
548 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
549 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
550 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
551 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
552 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
553 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
554 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
555 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
556 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
559 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
560 struct aq_hw_caps_s *aq_hw_caps,
565 for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
566 regs_buff[i] = aq_hw_read_reg(self,
567 hw_atl_utils_hw_mac_regs[i]);
571 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
573 *fw_version = aq_hw_read_reg(self, 0x18U);