]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/blob - drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
ASoC: ep93xx-ac97: Fix platform_get_irq's error checking
[mirror_ubuntu-disco-kernel.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
145 if (err < 0)
146 pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n",
147 AQ_CFG_DRV_NAME,
148 aq_hw_caps->fw_ver_expected,
149 aq_hw_read_reg(self, 0x18U));
150 return err;
151 }
152
153 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
154 #define HW_ATL_RPC_STATE_ADR 0x033CU
155
156 struct aq_hw_atl_utils_fw_rpc_tid_s {
157 union {
158 u32 val;
159 struct {
160 u16 tid;
161 u16 len;
162 };
163 };
164 };
165
166 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
167
168 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
169 {
170 int err = 0;
171 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
172
173 if (!IS_CHIP_FEATURE(MIPS)) {
174 err = -1;
175 goto err_exit;
176 }
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));
181 if (err < 0)
182 goto err_exit;
183
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);
187
188 err_exit:
189 return err;
190 }
191
192 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
193 struct hw_aq_atl_utils_fw_rpc **rpc)
194 {
195 int err = 0;
196 struct aq_hw_atl_utils_fw_rpc_tid_s sw;
197 struct aq_hw_atl_utils_fw_rpc_tid_s fw;
198
199 do {
200 sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
201
202 PHAL_ATLANTIC->rpc_tid = sw.tid;
203
204 AQ_HW_WAIT_FOR(sw.tid ==
205 (fw.val =
206 aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
207 fw.tid), 1000U, 100U);
208 if (err < 0)
209 goto err_exit;
210
211 if (fw.len == 0xFFFFU) {
212 err = hw_atl_utils_fw_rpc_call(self, sw.len);
213 if (err < 0)
214 goto err_exit;
215 }
216 } while (sw.tid != fw.tid || 0xFFFFU == fw.len);
217 if (err < 0)
218 goto err_exit;
219
220 if (rpc) {
221 if (fw.len) {
222 err =
223 hw_atl_utils_fw_downld_dwords(self,
224 PHAL_ATLANTIC->rpc_addr,
225 (u32 *)(void *)
226 &PHAL_ATLANTIC->rpc,
227 (fw.len + sizeof(u32) -
228 sizeof(u8)) /
229 sizeof(u32));
230 if (err < 0)
231 goto err_exit;
232 }
233
234 *rpc = &PHAL_ATLANTIC->rpc;
235 }
236
237 err_exit:
238 return err;
239 }
240
241 static int hw_atl_utils_mpi_create(struct aq_hw_s *self,
242 struct aq_hw_caps_s *aq_hw_caps)
243 {
244 int err = 0;
245
246 err = hw_atl_utils_init_ucp(self, aq_hw_caps);
247 if (err < 0)
248 goto err_exit;
249
250 err = hw_atl_utils_fw_rpc_init(self);
251 if (err < 0)
252 goto err_exit;
253
254 err_exit:
255 return err;
256 }
257
258 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
259 struct hw_aq_atl_utils_mbox_header *pmbox)
260 {
261 return hw_atl_utils_fw_downld_dwords(self,
262 PHAL_ATLANTIC->mbox_addr,
263 (u32 *)(void *)pmbox,
264 sizeof(*pmbox) / sizeof(u32));
265 }
266
267 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
268 struct hw_aq_atl_utils_mbox *pmbox)
269 {
270 int err = 0;
271
272 err = hw_atl_utils_fw_downld_dwords(self,
273 PHAL_ATLANTIC->mbox_addr,
274 (u32 *)(void *)pmbox,
275 sizeof(*pmbox) / sizeof(u32));
276 if (err < 0)
277 goto err_exit;
278
279 if (IS_CHIP_FEATURE(REVISION_A0)) {
280 unsigned int mtu = self->aq_nic_cfg ?
281 self->aq_nic_cfg->mtu : 1514U;
282 pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
283 pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
284 pmbox->stats.dpc = atomic_read(&PHAL_ATLANTIC_A0->dpc);
285 } else {
286 pmbox->stats.dpc = reg_rx_dma_stat_counter7get(self);
287 }
288
289 err_exit:;
290 }
291
292 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
293 enum hal_atl_utils_fw_state_e state)
294 {
295 u32 ucp_0x368 = 0;
296
297 ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state;
298 aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368);
299
300 return 0;
301 }
302
303 void hw_atl_utils_mpi_set(struct aq_hw_s *self,
304 enum hal_atl_utils_fw_state_e state, u32 speed)
305 {
306 int err = 0;
307 u32 transaction_id = 0;
308 struct hw_aq_atl_utils_mbox_header mbox;
309
310 if (state == MPI_RESET) {
311 hw_atl_utils_mpi_read_mbox(self, &mbox);
312
313 transaction_id = mbox.transaction_id;
314
315 AQ_HW_WAIT_FOR(transaction_id !=
316 (hw_atl_utils_mpi_read_mbox(self, &mbox),
317 mbox.transaction_id),
318 1000U, 100U);
319 if (err < 0)
320 goto err_exit;
321 }
322
323 err = hw_atl_utils_mpi_set_speed(self, speed, state);
324
325 err_exit:;
326 }
327
328 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
329 {
330 u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
331 u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
332 struct aq_hw_link_status_s *link_status = &self->aq_link_status;
333
334 if (!link_speed_mask) {
335 link_status->mbps = 0U;
336 } else {
337 switch (link_speed_mask) {
338 case HAL_ATLANTIC_RATE_10G:
339 link_status->mbps = 10000U;
340 break;
341
342 case HAL_ATLANTIC_RATE_5G:
343 case HAL_ATLANTIC_RATE_5GSR:
344 link_status->mbps = 5000U;
345 break;
346
347 case HAL_ATLANTIC_RATE_2GS:
348 link_status->mbps = 2500U;
349 break;
350
351 case HAL_ATLANTIC_RATE_1G:
352 link_status->mbps = 1000U;
353 break;
354
355 case HAL_ATLANTIC_RATE_100M:
356 link_status->mbps = 100U;
357 break;
358
359 default:
360 return -EBUSY;
361 }
362 }
363
364 return 0;
365 }
366
367 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
368 struct aq_hw_caps_s *aq_hw_caps,
369 u8 *mac)
370 {
371 int err = 0;
372 u32 h = 0U;
373 u32 l = 0U;
374 u32 mac_addr[2];
375
376 self->mmio = aq_pci_func_get_mmio(self->aq_pci_func);
377
378 hw_atl_utils_hw_chip_features_init(self,
379 &PHAL_ATLANTIC_A0->chip_features);
380
381 err = hw_atl_utils_mpi_create(self, aq_hw_caps);
382 if (err < 0)
383 goto err_exit;
384
385 if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
386 unsigned int rnd = 0;
387 unsigned int ucp_0x370 = 0;
388
389 get_random_bytes(&rnd, sizeof(unsigned int));
390
391 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
392 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
393 }
394
395 err = hw_atl_utils_fw_downld_dwords(self,
396 aq_hw_read_reg(self, 0x00000374U) +
397 (40U * 4U),
398 mac_addr,
399 AQ_DIMOF(mac_addr));
400 if (err < 0) {
401 mac_addr[0] = 0U;
402 mac_addr[1] = 0U;
403 err = 0;
404 } else {
405 mac_addr[0] = __swab32(mac_addr[0]);
406 mac_addr[1] = __swab32(mac_addr[1]);
407 }
408
409 ether_addr_copy(mac, (u8 *)mac_addr);
410
411 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
412 /* chip revision */
413 l = 0xE3000000U
414 | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
415 | (0x00 << 16);
416 h = 0x8001300EU;
417
418 mac[5] = (u8)(0xFFU & l);
419 l >>= 8;
420 mac[4] = (u8)(0xFFU & l);
421 l >>= 8;
422 mac[3] = (u8)(0xFFU & l);
423 l >>= 8;
424 mac[2] = (u8)(0xFFU & l);
425 mac[1] = (u8)(0xFFU & h);
426 h >>= 8;
427 mac[0] = (u8)(0xFFU & h);
428 }
429
430 err_exit:
431 return err;
432 }
433
434 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
435 {
436 unsigned int ret = 0U;
437
438 switch (mbps) {
439 case 100U:
440 ret = 5U;
441 break;
442
443 case 1000U:
444 ret = 4U;
445 break;
446
447 case 2500U:
448 ret = 3U;
449 break;
450
451 case 5000U:
452 ret = 1U;
453 break;
454
455 case 10000U:
456 ret = 0U;
457 break;
458
459 default:
460 break;
461 }
462 return ret;
463 }
464
465 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
466 {
467 u32 chip_features = 0U;
468 u32 val = reg_glb_mif_id_get(self);
469 u32 mif_rev = val & 0xFFU;
470
471 if ((3U & mif_rev) == 1U) {
472 chip_features |=
473 HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
474 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
475 HAL_ATLANTIC_UTILS_CHIP_MIPS;
476 } else if ((3U & mif_rev) == 2U) {
477 chip_features |=
478 HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
479 HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
480 HAL_ATLANTIC_UTILS_CHIP_MIPS |
481 HAL_ATLANTIC_UTILS_CHIP_TPO2 |
482 HAL_ATLANTIC_UTILS_CHIP_RPF2;
483 }
484
485 *p = chip_features;
486 }
487
488 int hw_atl_utils_hw_deinit(struct aq_hw_s *self)
489 {
490 hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U);
491 return 0;
492 }
493
494 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
495 unsigned int power_state)
496 {
497 hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U);
498 return 0;
499 }
500
501 int hw_atl_utils_update_stats(struct aq_hw_s *self)
502 {
503 struct hw_atl_s *hw_self = PHAL_ATLANTIC;
504 struct hw_aq_atl_utils_mbox mbox;
505
506 if (!self->aq_link_status.mbps)
507 return 0;
508
509 hw_atl_utils_mpi_read_stats(self, &mbox);
510
511 #define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \
512 mbox.stats._N_ - hw_self->last_stats._N_)
513
514 AQ_SDELTA(uprc);
515 AQ_SDELTA(mprc);
516 AQ_SDELTA(bprc);
517 AQ_SDELTA(erpt);
518
519 AQ_SDELTA(uptc);
520 AQ_SDELTA(mptc);
521 AQ_SDELTA(bptc);
522 AQ_SDELTA(erpr);
523
524 AQ_SDELTA(ubrc);
525 AQ_SDELTA(ubtc);
526 AQ_SDELTA(mbrc);
527 AQ_SDELTA(mbtc);
528 AQ_SDELTA(bbrc);
529 AQ_SDELTA(bbtc);
530 AQ_SDELTA(dpc);
531
532 #undef AQ_SDELTA
533
534 memcpy(&hw_self->last_stats, &mbox.stats, sizeof(mbox.stats));
535
536 return 0;
537 }
538
539 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
540 u64 *data, unsigned int *p_count)
541 {
542 struct hw_atl_s *hw_self = PHAL_ATLANTIC;
543 struct hw_atl_stats_s *stats = &hw_self->curr_stats;
544 int i = 0;
545
546 data[i] = stats->uprc + stats->mprc + stats->bprc;
547 data[++i] = stats->uprc;
548 data[++i] = stats->mprc;
549 data[++i] = stats->bprc;
550 data[++i] = stats->erpt;
551 data[++i] = stats->uptc + stats->mptc + stats->bptc;
552 data[++i] = stats->uptc;
553 data[++i] = stats->mptc;
554 data[++i] = stats->bptc;
555 data[++i] = stats->ubrc;
556 data[++i] = stats->ubtc;
557 data[++i] = stats->mbrc;
558 data[++i] = stats->mbtc;
559 data[++i] = stats->bbrc;
560 data[++i] = stats->bbtc;
561 data[++i] = stats->ubrc + stats->mbrc + stats->bbrc;
562 data[++i] = stats->ubtc + stats->mbtc + stats->bbtc;
563 data[++i] = stats_rx_dma_good_pkt_counterlsw_get(self);
564 data[++i] = stats_tx_dma_good_pkt_counterlsw_get(self);
565 data[++i] = stats_rx_dma_good_octet_counterlsw_get(self);
566 data[++i] = stats_tx_dma_good_octet_counterlsw_get(self);
567 data[++i] = stats->dpc;
568
569 if (p_count)
570 *p_count = ++i;
571
572 return 0;
573 }
574
575 static const u32 hw_atl_utils_hw_mac_regs[] = {
576 0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
577 0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
578 0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
579 0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
580 0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
581 0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
582 0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
583 0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
584 0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
585 0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
586 0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
587 0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
588 0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
589 0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
590 0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
591 0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
592 0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
593 0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
594 0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
595 0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
596 0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
597 0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
598 };
599
600 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
601 struct aq_hw_caps_s *aq_hw_caps,
602 u32 *regs_buff)
603 {
604 unsigned int i = 0U;
605
606 for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
607 regs_buff[i] = aq_hw_read_reg(self,
608 hw_atl_utils_hw_mac_regs[i]);
609 return 0;
610 }
611
612 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
613 {
614 *fw_version = aq_hw_read_reg(self, 0x18U);
615 return 0;
616 }