x86/mm: Limit mmap() of /dev/mem to valid physical addresses
[sfrench/cifs-2.6.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 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
259                                  struct hw_aq_atl_utils_mbox *pmbox)
260 {
261         int err = 0;
262
263         err = hw_atl_utils_fw_downld_dwords(self,
264                                             PHAL_ATLANTIC->mbox_addr,
265                                             (u32 *)(void *)pmbox,
266                                             sizeof(*pmbox) / sizeof(u32));
267         if (err < 0)
268                 goto err_exit;
269
270         if (pmbox != &PHAL_ATLANTIC->mbox)
271                 memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox));
272
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);
279         } else {
280                 pmbox->stats.dpc = reg_rx_dma_stat_counter7get(self);
281         }
282
283 err_exit:;
284 }
285
286 int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed,
287                                enum hal_atl_utils_fw_state_e state)
288 {
289         u32 ucp_0x368 = 0;
290
291         ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state;
292         aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368);
293
294         return 0;
295 }
296
297 void hw_atl_utils_mpi_set(struct aq_hw_s *self,
298                           enum hal_atl_utils_fw_state_e state, u32 speed)
299 {
300         int err = 0;
301         u32 transaction_id = 0;
302
303         if (state == MPI_RESET) {
304                 hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
305
306                 transaction_id = PHAL_ATLANTIC->mbox.transaction_id;
307
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),
312                                         1000U, 100U);
313                 if (err < 0)
314                         goto err_exit;
315         }
316
317         err = hw_atl_utils_mpi_set_speed(self, speed, state);
318
319 err_exit:;
320 }
321
322 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
323 {
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;
327
328         if (!link_speed_mask) {
329                 link_status->mbps = 0U;
330         } else {
331                 switch (link_speed_mask) {
332                 case HAL_ATLANTIC_RATE_10G:
333                         link_status->mbps = 10000U;
334                         break;
335
336                 case HAL_ATLANTIC_RATE_5G:
337                 case HAL_ATLANTIC_RATE_5GSR:
338                         link_status->mbps = 5000U;
339                         break;
340
341                 case HAL_ATLANTIC_RATE_2GS:
342                         link_status->mbps = 2500U;
343                         break;
344
345                 case HAL_ATLANTIC_RATE_1G:
346                         link_status->mbps = 1000U;
347                         break;
348
349                 case HAL_ATLANTIC_RATE_100M:
350                         link_status->mbps = 100U;
351                         break;
352
353                 default:
354                         return -EBUSY;
355                 }
356         }
357
358         return 0;
359 }
360
361 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
362                                    struct aq_hw_caps_s *aq_hw_caps,
363                                    u8 *mac)
364 {
365         int err = 0;
366         u32 h = 0U;
367         u32 l = 0U;
368         u32 mac_addr[2];
369
370         self->mmio = aq_pci_func_get_mmio(self->aq_pci_func);
371
372         hw_atl_utils_hw_chip_features_init(self,
373                                            &PHAL_ATLANTIC_A0->chip_features);
374
375         err = hw_atl_utils_mpi_create(self, aq_hw_caps);
376         if (err < 0)
377                 goto err_exit;
378
379         if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
380                 unsigned int rnd = 0;
381                 unsigned int ucp_0x370 = 0;
382
383                 get_random_bytes(&rnd, sizeof(unsigned int));
384
385                 ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
386                 aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
387         }
388
389         err = hw_atl_utils_fw_downld_dwords(self,
390                                             aq_hw_read_reg(self, 0x00000374U) +
391                                             (40U * 4U),
392                                             mac_addr,
393                                             AQ_DIMOF(mac_addr));
394         if (err < 0) {
395                 mac_addr[0] = 0U;
396                 mac_addr[1] = 0U;
397                 err = 0;
398         } else {
399                 mac_addr[0] = __swab32(mac_addr[0]);
400                 mac_addr[1] = __swab32(mac_addr[1]);
401         }
402
403         ether_addr_copy(mac, (u8 *)mac_addr);
404
405         if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
406                 /* chip revision */
407                 l = 0xE3000000U
408                         | (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
409                         | (0x00 << 16);
410                 h = 0x8001300EU;
411
412                 mac[5] = (u8)(0xFFU & l);
413                 l >>= 8;
414                 mac[4] = (u8)(0xFFU & l);
415                 l >>= 8;
416                 mac[3] = (u8)(0xFFU & l);
417                 l >>= 8;
418                 mac[2] = (u8)(0xFFU & l);
419                 mac[1] = (u8)(0xFFU & h);
420                 h >>= 8;
421                 mac[0] = (u8)(0xFFU & h);
422         }
423
424 err_exit:
425         return err;
426 }
427
428 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
429 {
430         unsigned int ret = 0U;
431
432         switch (mbps) {
433         case 100U:
434                 ret = 5U;
435                 break;
436
437         case 1000U:
438                 ret = 4U;
439                 break;
440
441         case 2500U:
442                 ret = 3U;
443                 break;
444
445         case 5000U:
446                 ret = 1U;
447                 break;
448
449         case 10000U:
450                 ret = 0U;
451                 break;
452
453         default:
454                 break;
455         }
456         return ret;
457 }
458
459 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
460 {
461         u32 chip_features = 0U;
462         u32 val = reg_glb_mif_id_get(self);
463         u32 mif_rev = val & 0xFFU;
464
465         if ((3U & mif_rev) == 1U) {
466                 chip_features |=
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) {
471                 chip_features |=
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;
477         }
478
479         *p = chip_features;
480 }
481
482 int hw_atl_utils_hw_deinit(struct aq_hw_s *self)
483 {
484         hw_atl_utils_mpi_set(self, MPI_DEINIT, 0x0U);
485         return 0;
486 }
487
488 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
489                               unsigned int power_state)
490 {
491         hw_atl_utils_mpi_set(self, MPI_POWER, 0x0U);
492         return 0;
493 }
494
495 int hw_atl_utils_get_hw_stats(struct aq_hw_s *self,
496                               u64 *data, unsigned int *p_count)
497 {
498         struct hw_atl_stats_s *stats = NULL;
499         int i = 0;
500
501         hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox);
502
503         stats = &PHAL_ATLANTIC->mbox.stats;
504
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;
527
528         if (p_count)
529                 *p_count = ++i;
530
531         return 0;
532 }
533
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,
557 };
558
559 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
560                              struct aq_hw_caps_s *aq_hw_caps,
561                              u32 *regs_buff)
562 {
563         unsigned int i = 0U;
564
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]);
568         return 0;
569 }
570
571 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
572 {
573         *fw_version = aq_hw_read_reg(self, 0x18U);
574         return 0;
575 }