]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
net:ethernet:aquantia: Fix for incorrect speed index.
[karo-tx-linux.git] / drivers / net / ethernet / aquantia / atlantic / hw_atl / hw_atl_utils.c
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 {
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;
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 }