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 				     struct aq_hw_link_status_s *link_status)
318 {
319 	u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
320 	u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
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 }
571