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_nic.h"
15 #include "../aq_hw_utils.h"
16 #include "hw_atl_utils.h"
17 #include "hw_atl_llh.h"
18 #include "hw_atl_llh_internal.h"
19 
20 #include <linux/random.h>
21 
22 #define HW_ATL_UCP_0X370_REG    0x0370U
23 
24 #define HW_ATL_MIF_CMD          0x0200U
25 #define HW_ATL_MIF_ADDR         0x0208U
26 #define HW_ATL_MIF_VAL          0x020CU
27 
28 #define HW_ATL_FW_SM_RAM        0x2U
29 #define HW_ATL_MPI_FW_VERSION	0x18
30 #define HW_ATL_MPI_CONTROL_ADR  0x0368U
31 #define HW_ATL_MPI_STATE_ADR    0x036CU
32 
33 #define HW_ATL_MPI_STATE_MSK      0x00FFU
34 #define HW_ATL_MPI_STATE_SHIFT    0U
35 #define HW_ATL_MPI_SPEED_MSK      0x00FF0000U
36 #define HW_ATL_MPI_SPEED_SHIFT    16U
37 #define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
38 
39 #define HW_ATL_MPI_DAISY_CHAIN_STATUS	0x704
40 #define HW_ATL_MPI_BOOT_EXIT_CODE	0x388
41 
42 #define HW_ATL_MAC_PHY_CONTROL	0x4000
43 #define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
44 
45 #define HW_ATL_FW_VER_1X 0x01050006U
46 #define HW_ATL_FW_VER_2X 0x02000000U
47 #define HW_ATL_FW_VER_3X 0x03000000U
48 
49 #define FORCE_FLASHLESS 0
50 
51 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual);
52 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
53 				      enum hal_atl_utils_fw_state_e state);
54 
hw_atl_utils_initfw(struct aq_hw_s * self,const struct aq_fw_ops ** fw_ops)55 int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
56 {
57 	int err = 0;
58 
59 	err = hw_atl_utils_soft_reset(self);
60 	if (err)
61 		return err;
62 
63 	hw_atl_utils_hw_chip_features_init(self,
64 					   &self->chip_features);
65 
66 	hw_atl_utils_get_fw_version(self, &self->fw_ver_actual);
67 
68 	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
69 				   self->fw_ver_actual) == 0) {
70 		*fw_ops = &aq_fw_1x_ops;
71 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X,
72 					self->fw_ver_actual) == 0) {
73 		*fw_ops = &aq_fw_2x_ops;
74 	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X,
75 					self->fw_ver_actual) == 0) {
76 		*fw_ops = &aq_fw_2x_ops;
77 	} else {
78 		aq_pr_err("Bad FW version detected: %x\n",
79 			  self->fw_ver_actual);
80 		return -EOPNOTSUPP;
81 	}
82 	self->aq_fw_ops = *fw_ops;
83 	err = self->aq_fw_ops->init(self);
84 	return err;
85 }
86 
hw_atl_utils_soft_reset_flb(struct aq_hw_s * self)87 static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
88 {
89 	u32 gsr, val;
90 	int k = 0;
91 
92 	aq_hw_write_reg(self, 0x404, 0x40e1);
93 	AQ_HW_SLEEP(50);
94 
95 	/* Cleanup SPI */
96 	val = aq_hw_read_reg(self, 0x53C);
97 	aq_hw_write_reg(self, 0x53C, val | 0x10);
98 
99 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
100 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
101 
102 	/* Kickstart MAC */
103 	aq_hw_write_reg(self, 0x404, 0x80e0);
104 	aq_hw_write_reg(self, 0x32a8, 0x0);
105 	aq_hw_write_reg(self, 0x520, 0x1);
106 
107 	/* Reset SPI again because of possible interrupted SPI burst */
108 	val = aq_hw_read_reg(self, 0x53C);
109 	aq_hw_write_reg(self, 0x53C, val | 0x10);
110 	AQ_HW_SLEEP(10);
111 	/* Clear SPI reset state */
112 	aq_hw_write_reg(self, 0x53C, val & ~0x10);
113 
114 	aq_hw_write_reg(self, 0x404, 0x180e0);
115 
116 	for (k = 0; k < 1000; k++) {
117 		u32 flb_status = aq_hw_read_reg(self,
118 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
119 
120 		flb_status = flb_status & 0x10;
121 		if (flb_status)
122 			break;
123 		AQ_HW_SLEEP(10);
124 	}
125 	if (k == 1000) {
126 		aq_pr_err("MAC kickstart failed\n");
127 		return -EIO;
128 	}
129 
130 	/* FW reset */
131 	aq_hw_write_reg(self, 0x404, 0x80e0);
132 	AQ_HW_SLEEP(50);
133 	aq_hw_write_reg(self, 0x3a0, 0x1);
134 
135 	/* Kickstart PHY - skipped */
136 
137 	/* Global software reset*/
138 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
139 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
140 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
141 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
142 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
143 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
144 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
145 
146 	for (k = 0; k < 1000; k++) {
147 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
148 
149 		if (fw_state)
150 			break;
151 		AQ_HW_SLEEP(10);
152 	}
153 	if (k == 1000) {
154 		aq_pr_err("FW kickstart failed\n");
155 		return -EIO;
156 	}
157 	/* Old FW requires fixed delay after init */
158 	AQ_HW_SLEEP(15);
159 
160 	return 0;
161 }
162 
hw_atl_utils_soft_reset_rbl(struct aq_hw_s * self)163 static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
164 {
165 	u32 gsr, val, rbl_status;
166 	int k;
167 
168 	aq_hw_write_reg(self, 0x404, 0x40e1);
169 	aq_hw_write_reg(self, 0x3a0, 0x1);
170 	aq_hw_write_reg(self, 0x32a8, 0x0);
171 
172 	/* Alter RBL status */
173 	aq_hw_write_reg(self, 0x388, 0xDEAD);
174 
175 	/* Cleanup SPI */
176 	val = aq_hw_read_reg(self, 0x53C);
177 	aq_hw_write_reg(self, 0x53C, val | 0x10);
178 
179 	/* Global software reset*/
180 	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
181 	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
182 	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
183 			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
184 			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
185 	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
186 	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
187 			(gsr & 0xFFFFBFFF) | 0x8000);
188 
189 	if (FORCE_FLASHLESS)
190 		aq_hw_write_reg(self, 0x534, 0x0);
191 
192 	aq_hw_write_reg(self, 0x404, 0x40e0);
193 
194 	/* Wait for RBL boot */
195 	for (k = 0; k < 1000; k++) {
196 		rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
197 		if (rbl_status && rbl_status != 0xDEAD)
198 			break;
199 		AQ_HW_SLEEP(10);
200 	}
201 	if (!rbl_status || rbl_status == 0xDEAD) {
202 		aq_pr_err("RBL Restart failed");
203 		return -EIO;
204 	}
205 
206 	/* Restore NVR */
207 	if (FORCE_FLASHLESS)
208 		aq_hw_write_reg(self, 0x534, 0xA0);
209 
210 	if (rbl_status == 0xF1A7) {
211 		aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
212 		return -ENOTSUPP;
213 	}
214 
215 	for (k = 0; k < 1000; k++) {
216 		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
217 
218 		if (fw_state)
219 			break;
220 		AQ_HW_SLEEP(10);
221 	}
222 	if (k == 1000) {
223 		aq_pr_err("FW kickstart failed\n");
224 		return -EIO;
225 	}
226 	/* Old FW requires fixed delay after init */
227 	AQ_HW_SLEEP(15);
228 
229 	return 0;
230 }
231 
hw_atl_utils_soft_reset(struct aq_hw_s * self)232 int hw_atl_utils_soft_reset(struct aq_hw_s *self)
233 {
234 	int k;
235 	u32 boot_exit_code = 0;
236 
237 	for (k = 0; k < 1000; ++k) {
238 		u32 flb_status = aq_hw_read_reg(self,
239 						HW_ATL_MPI_DAISY_CHAIN_STATUS);
240 		boot_exit_code = aq_hw_read_reg(self,
241 						HW_ATL_MPI_BOOT_EXIT_CODE);
242 		if (flb_status != 0x06000000 || boot_exit_code != 0)
243 			break;
244 	}
245 
246 	if (k == 1000) {
247 		aq_pr_err("Neither RBL nor FLB firmware started\n");
248 		return -EOPNOTSUPP;
249 	}
250 
251 	self->rbl_enabled = (boot_exit_code != 0);
252 
253 	/* FW 1.x may bootup in an invalid POWER state (WOL feature).
254 	 * We should work around this by forcing its state back to DEINIT
255 	 */
256 	if (!hw_atl_utils_ver_match(HW_ATL_FW_VER_1X,
257 				    aq_hw_read_reg(self,
258 						   HW_ATL_MPI_FW_VERSION))) {
259 		int err = 0;
260 
261 		hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
262 		AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR) &
263 			       HW_ATL_MPI_STATE_MSK) == MPI_DEINIT,
264 			       10, 1000U);
265 	}
266 
267 	if (self->rbl_enabled)
268 		return hw_atl_utils_soft_reset_rbl(self);
269 	else
270 		return hw_atl_utils_soft_reset_flb(self);
271 }
272 
hw_atl_utils_fw_downld_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)273 int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
274 				  u32 *p, u32 cnt)
275 {
276 	int err = 0;
277 
278 	AQ_HW_WAIT_FOR(hw_atl_reg_glb_cpu_sem_get(self,
279 						  HW_ATL_FW_SM_RAM) == 1U,
280 						  1U, 10000U);
281 
282 	if (err < 0) {
283 		bool is_locked;
284 
285 		hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
286 		is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
287 		if (!is_locked) {
288 			err = -ETIME;
289 			goto err_exit;
290 		}
291 	}
292 
293 	aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
294 
295 	for (++cnt; --cnt && !err;) {
296 		aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
297 
298 		if (IS_CHIP_FEATURE(REVISION_B1))
299 			AQ_HW_WAIT_FOR(a != aq_hw_read_reg(self,
300 							   HW_ATL_MIF_ADDR),
301 				       1, 1000U);
302 		else
303 			AQ_HW_WAIT_FOR(!(0x100 & aq_hw_read_reg(self,
304 							   HW_ATL_MIF_CMD)),
305 				       1, 1000U);
306 
307 		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
308 		a += 4;
309 	}
310 
311 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
312 
313 err_exit:
314 	return err;
315 }
316 
hw_atl_utils_fw_upload_dwords(struct aq_hw_s * self,u32 a,u32 * p,u32 cnt)317 static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 a, u32 *p,
318 					 u32 cnt)
319 {
320 	int err = 0;
321 	bool is_locked;
322 
323 	is_locked = hw_atl_reg_glb_cpu_sem_get(self, HW_ATL_FW_SM_RAM);
324 	if (!is_locked) {
325 		err = -ETIME;
326 		goto err_exit;
327 	}
328 
329 	aq_hw_write_reg(self, 0x00000208U, a);
330 
331 	for (++cnt; --cnt;) {
332 		u32 i = 0U;
333 
334 		aq_hw_write_reg(self, 0x0000020CU, *(p++));
335 		aq_hw_write_reg(self, 0x00000200U, 0xC000U);
336 
337 		for (i = 1024U;
338 			(0x100U & aq_hw_read_reg(self, 0x00000200U)) && --i;) {
339 		}
340 	}
341 
342 	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
343 
344 err_exit:
345 	return err;
346 }
347 
hw_atl_utils_ver_match(u32 ver_expected,u32 ver_actual)348 static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
349 {
350 	int err = 0;
351 	const u32 dw_major_mask = 0xff000000U;
352 	const u32 dw_minor_mask = 0x00ffffffU;
353 
354 	err = (dw_major_mask & (ver_expected ^ ver_actual)) ? -EOPNOTSUPP : 0;
355 	if (err < 0)
356 		goto err_exit;
357 	err = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
358 		-EOPNOTSUPP : 0;
359 err_exit:
360 	return err;
361 }
362 
hw_atl_utils_init_ucp(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps)363 static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
364 				 const struct aq_hw_caps_s *aq_hw_caps)
365 {
366 	int err = 0;
367 
368 	if (!aq_hw_read_reg(self, 0x370U)) {
369 		unsigned int rnd = 0U;
370 		unsigned int ucp_0x370 = 0U;
371 
372 		get_random_bytes(&rnd, sizeof(unsigned int));
373 
374 		ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
375 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
376 	}
377 
378 	hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
379 
380 	/* check 10 times by 1ms */
381 	AQ_HW_WAIT_FOR(0U != (self->mbox_addr =
382 			aq_hw_read_reg(self, 0x360U)), 1000U, 10U);
383 
384 	return err;
385 }
386 
387 #define HW_ATL_RPC_CONTROL_ADR 0x0338U
388 #define HW_ATL_RPC_STATE_ADR   0x033CU
389 
390 struct aq_hw_atl_utils_fw_rpc_tid_s {
391 	union {
392 		u32 val;
393 		struct {
394 			u16 tid;
395 			u16 len;
396 		};
397 	};
398 };
399 
400 #define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
401 
hw_atl_utils_fw_rpc_call(struct aq_hw_s * self,unsigned int rpc_size)402 static int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
403 {
404 	int err = 0;
405 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
406 
407 	if (!IS_CHIP_FEATURE(MIPS)) {
408 		err = -1;
409 		goto err_exit;
410 	}
411 	err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr,
412 					    (u32 *)(void *)&self->rpc,
413 					    (rpc_size + sizeof(u32) -
414 					    sizeof(u8)) / sizeof(u32));
415 	if (err < 0)
416 		goto err_exit;
417 
418 	sw.tid = 0xFFFFU & (++self->rpc_tid);
419 	sw.len = (u16)rpc_size;
420 	aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
421 
422 err_exit:
423 	return err;
424 }
425 
hw_atl_utils_fw_rpc_wait(struct aq_hw_s * self,struct hw_aq_atl_utils_fw_rpc ** rpc)426 static int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
427 				    struct hw_aq_atl_utils_fw_rpc **rpc)
428 {
429 	int err = 0;
430 	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
431 	struct aq_hw_atl_utils_fw_rpc_tid_s fw;
432 
433 	do {
434 		sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
435 
436 		self->rpc_tid = sw.tid;
437 
438 		AQ_HW_WAIT_FOR(sw.tid ==
439 				(fw.val =
440 				aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR),
441 				fw.tid), 1000U, 100U);
442 		if (err < 0)
443 			goto err_exit;
444 
445 		if (fw.len == 0xFFFFU) {
446 			err = hw_atl_utils_fw_rpc_call(self, sw.len);
447 			if (err < 0)
448 				goto err_exit;
449 		}
450 	} while (sw.tid != fw.tid || 0xFFFFU == fw.len);
451 	if (err < 0)
452 		goto err_exit;
453 
454 	if (rpc) {
455 		if (fw.len) {
456 			err =
457 			hw_atl_utils_fw_downld_dwords(self,
458 						      self->rpc_addr,
459 						      (u32 *)(void *)
460 						      &self->rpc,
461 						      (fw.len + sizeof(u32) -
462 						      sizeof(u8)) /
463 						      sizeof(u32));
464 			if (err < 0)
465 				goto err_exit;
466 		}
467 
468 		*rpc = &self->rpc;
469 	}
470 
471 err_exit:
472 	return err;
473 }
474 
hw_atl_utils_mpi_create(struct aq_hw_s * self)475 static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
476 {
477 	int err = 0;
478 
479 	err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
480 	if (err < 0)
481 		goto err_exit;
482 
483 	err = hw_atl_utils_fw_rpc_init(self);
484 	if (err < 0)
485 		goto err_exit;
486 
487 err_exit:
488 	return err;
489 }
490 
hw_atl_utils_mpi_read_mbox(struct aq_hw_s * self,struct hw_aq_atl_utils_mbox_header * pmbox)491 int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
492 			       struct hw_aq_atl_utils_mbox_header *pmbox)
493 {
494 	return hw_atl_utils_fw_downld_dwords(self,
495 				      self->mbox_addr,
496 				      (u32 *)(void *)pmbox,
497 				      sizeof(*pmbox) / sizeof(u32));
498 }
499 
hw_atl_utils_mpi_read_stats(struct aq_hw_s * self,struct hw_aq_atl_utils_mbox * pmbox)500 void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
501 				 struct hw_aq_atl_utils_mbox *pmbox)
502 {
503 	int err = 0;
504 
505 	err = hw_atl_utils_fw_downld_dwords(self,
506 					    self->mbox_addr,
507 					    (u32 *)(void *)pmbox,
508 					    sizeof(*pmbox) / sizeof(u32));
509 	if (err < 0)
510 		goto err_exit;
511 
512 	if (IS_CHIP_FEATURE(REVISION_A0)) {
513 		unsigned int mtu = self->aq_nic_cfg ?
514 					self->aq_nic_cfg->mtu : 1514U;
515 		pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
516 		pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
517 		pmbox->stats.dpc = atomic_read(&self->dpc);
518 	} else {
519 		pmbox->stats.dpc = hw_atl_reg_rx_dma_stat_counter7get(self);
520 	}
521 
522 err_exit:;
523 }
524 
hw_atl_utils_mpi_set_speed(struct aq_hw_s * self,u32 speed)525 static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
526 {
527 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
528 
529 	val = val & ~HW_ATL_MPI_SPEED_MSK;
530 	val |= speed << HW_ATL_MPI_SPEED_SHIFT;
531 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
532 
533 	return 0;
534 }
535 
hw_atl_utils_mpi_set_state(struct aq_hw_s * self,enum hal_atl_utils_fw_state_e state)536 static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
537 				      enum hal_atl_utils_fw_state_e state)
538 {
539 	int err = 0;
540 	u32 transaction_id = 0;
541 	struct hw_aq_atl_utils_mbox_header mbox;
542 	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
543 
544 	if (state == MPI_RESET) {
545 		hw_atl_utils_mpi_read_mbox(self, &mbox);
546 
547 		transaction_id = mbox.transaction_id;
548 
549 		AQ_HW_WAIT_FOR(transaction_id !=
550 				(hw_atl_utils_mpi_read_mbox(self, &mbox),
551 				 mbox.transaction_id),
552 			       1000U, 100U);
553 		if (err < 0)
554 			goto err_exit;
555 	}
556 	/* On interface DEINIT we disable DW (raise bit)
557 	 * Otherwise enable DW (clear bit)
558 	 */
559 	if (state == MPI_DEINIT || state == MPI_POWER)
560 		val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
561 	else
562 		val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
563 
564 	/* Set new state bits */
565 	val = val & ~HW_ATL_MPI_STATE_MSK;
566 	val |= state & HW_ATL_MPI_STATE_MSK;
567 
568 	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
569 err_exit:
570 	return err;
571 }
572 
hw_atl_utils_mpi_get_link_status(struct aq_hw_s * self)573 int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
574 {
575 	u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
576 	u32 link_speed_mask = cp0x036C >> HW_ATL_MPI_SPEED_SHIFT;
577 	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
578 
579 	if (!link_speed_mask) {
580 		link_status->mbps = 0U;
581 	} else {
582 		switch (link_speed_mask) {
583 		case HAL_ATLANTIC_RATE_10G:
584 			link_status->mbps = 10000U;
585 			break;
586 
587 		case HAL_ATLANTIC_RATE_5G:
588 		case HAL_ATLANTIC_RATE_5GSR:
589 			link_status->mbps = 5000U;
590 			break;
591 
592 		case HAL_ATLANTIC_RATE_2GS:
593 			link_status->mbps = 2500U;
594 			break;
595 
596 		case HAL_ATLANTIC_RATE_1G:
597 			link_status->mbps = 1000U;
598 			break;
599 
600 		case HAL_ATLANTIC_RATE_100M:
601 			link_status->mbps = 100U;
602 			break;
603 
604 		default:
605 			return -EBUSY;
606 		}
607 	}
608 
609 	return 0;
610 }
611 
hw_atl_utils_get_mac_permanent(struct aq_hw_s * self,u8 * mac)612 int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
613 				   u8 *mac)
614 {
615 	int err = 0;
616 	u32 h = 0U;
617 	u32 l = 0U;
618 	u32 mac_addr[2];
619 
620 	if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
621 		unsigned int rnd = 0;
622 		unsigned int ucp_0x370 = 0;
623 
624 		get_random_bytes(&rnd, sizeof(unsigned int));
625 
626 		ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
627 		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
628 	}
629 
630 	err = hw_atl_utils_fw_downld_dwords(self,
631 					    aq_hw_read_reg(self, 0x00000374U) +
632 					    (40U * 4U),
633 					    mac_addr,
634 					    ARRAY_SIZE(mac_addr));
635 	if (err < 0) {
636 		mac_addr[0] = 0U;
637 		mac_addr[1] = 0U;
638 		err = 0;
639 	} else {
640 		mac_addr[0] = __swab32(mac_addr[0]);
641 		mac_addr[1] = __swab32(mac_addr[1]);
642 	}
643 
644 	ether_addr_copy(mac, (u8 *)mac_addr);
645 
646 	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
647 		/* chip revision */
648 		l = 0xE3000000U
649 			| (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG))
650 			| (0x00 << 16);
651 		h = 0x8001300EU;
652 
653 		mac[5] = (u8)(0xFFU & l);
654 		l >>= 8;
655 		mac[4] = (u8)(0xFFU & l);
656 		l >>= 8;
657 		mac[3] = (u8)(0xFFU & l);
658 		l >>= 8;
659 		mac[2] = (u8)(0xFFU & l);
660 		mac[1] = (u8)(0xFFU & h);
661 		h >>= 8;
662 		mac[0] = (u8)(0xFFU & h);
663 	}
664 
665 	return err;
666 }
667 
hw_atl_utils_mbps_2_speed_index(unsigned int mbps)668 unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
669 {
670 	unsigned int ret = 0U;
671 
672 	switch (mbps) {
673 	case 100U:
674 		ret = 5U;
675 		break;
676 
677 	case 1000U:
678 		ret = 4U;
679 		break;
680 
681 	case 2500U:
682 		ret = 3U;
683 		break;
684 
685 	case 5000U:
686 		ret = 1U;
687 		break;
688 
689 	case 10000U:
690 		ret = 0U;
691 		break;
692 
693 	default:
694 		break;
695 	}
696 	return ret;
697 }
698 
hw_atl_utils_hw_chip_features_init(struct aq_hw_s * self,u32 * p)699 void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
700 {
701 	u32 chip_features = 0U;
702 	u32 val = hw_atl_reg_glb_mif_id_get(self);
703 	u32 mif_rev = val & 0xFFU;
704 
705 	if ((0xFU & mif_rev) == 1U) {
706 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_A0 |
707 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
708 			HAL_ATLANTIC_UTILS_CHIP_MIPS;
709 	} else if ((0xFU & mif_rev) == 2U) {
710 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 |
711 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
712 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
713 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
714 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
715 	} else if ((0xFU & mif_rev) == 0xAU) {
716 		chip_features |= HAL_ATLANTIC_UTILS_CHIP_REVISION_B1 |
717 			HAL_ATLANTIC_UTILS_CHIP_MPI_AQ |
718 			HAL_ATLANTIC_UTILS_CHIP_MIPS |
719 			HAL_ATLANTIC_UTILS_CHIP_TPO2 |
720 			HAL_ATLANTIC_UTILS_CHIP_RPF2;
721 	}
722 
723 	*p = chip_features;
724 }
725 
hw_atl_fw1x_deinit(struct aq_hw_s * self)726 static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
727 {
728 	hw_atl_utils_mpi_set_speed(self, 0);
729 	hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
730 	return 0;
731 }
732 
hw_atl_utils_hw_set_power(struct aq_hw_s * self,unsigned int power_state)733 int hw_atl_utils_hw_set_power(struct aq_hw_s *self,
734 			      unsigned int power_state)
735 {
736 	hw_atl_utils_mpi_set_speed(self, 0);
737 	hw_atl_utils_mpi_set_state(self, MPI_POWER);
738 	return 0;
739 }
740 
hw_atl_utils_update_stats(struct aq_hw_s * self)741 int hw_atl_utils_update_stats(struct aq_hw_s *self)
742 {
743 	struct hw_aq_atl_utils_mbox mbox;
744 
745 	hw_atl_utils_mpi_read_stats(self, &mbox);
746 
747 #define AQ_SDELTA(_N_) (self->curr_stats._N_ += \
748 			mbox.stats._N_ - self->last_stats._N_)
749 
750 	if (self->aq_link_status.mbps) {
751 		AQ_SDELTA(uprc);
752 		AQ_SDELTA(mprc);
753 		AQ_SDELTA(bprc);
754 		AQ_SDELTA(erpt);
755 
756 		AQ_SDELTA(uptc);
757 		AQ_SDELTA(mptc);
758 		AQ_SDELTA(bptc);
759 		AQ_SDELTA(erpr);
760 
761 		AQ_SDELTA(ubrc);
762 		AQ_SDELTA(ubtc);
763 		AQ_SDELTA(mbrc);
764 		AQ_SDELTA(mbtc);
765 		AQ_SDELTA(bbrc);
766 		AQ_SDELTA(bbtc);
767 		AQ_SDELTA(dpc);
768 	}
769 #undef AQ_SDELTA
770 	self->curr_stats.dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counterlsw_get(self);
771 	self->curr_stats.dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counterlsw_get(self);
772 	self->curr_stats.dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counterlsw_get(self);
773 	self->curr_stats.dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counterlsw_get(self);
774 
775 	memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
776 
777 	return 0;
778 }
779 
hw_atl_utils_get_hw_stats(struct aq_hw_s * self)780 struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
781 {
782 	return &self->curr_stats;
783 }
784 
785 static const u32 hw_atl_utils_hw_mac_regs[] = {
786 	0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
787 	0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
788 	0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
789 	0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
790 	0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
791 	0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
792 	0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
793 	0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
794 	0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
795 	0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
796 	0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
797 	0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
798 	0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
799 	0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
800 	0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
801 	0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
802 	0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
803 	0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
804 	0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
805 	0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
806 	0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
807 	0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
808 };
809 
hw_atl_utils_hw_get_regs(struct aq_hw_s * self,const struct aq_hw_caps_s * aq_hw_caps,u32 * regs_buff)810 int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
811 			     const struct aq_hw_caps_s *aq_hw_caps,
812 			     u32 *regs_buff)
813 {
814 	unsigned int i = 0U;
815 
816 	for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
817 		regs_buff[i] = aq_hw_read_reg(self,
818 					      hw_atl_utils_hw_mac_regs[i]);
819 	return 0;
820 }
821 
hw_atl_utils_get_fw_version(struct aq_hw_s * self,u32 * fw_version)822 int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version)
823 {
824 	*fw_version = aq_hw_read_reg(self, 0x18U);
825 	return 0;
826 }
827 
828 const struct aq_fw_ops aq_fw_1x_ops = {
829 	.init = hw_atl_utils_mpi_create,
830 	.deinit = hw_atl_fw1x_deinit,
831 	.reset = NULL,
832 	.get_mac_permanent = hw_atl_utils_get_mac_permanent,
833 	.set_link_speed = hw_atl_utils_mpi_set_speed,
834 	.set_state = hw_atl_utils_mpi_set_state,
835 	.update_link_status = hw_atl_utils_mpi_get_link_status,
836 	.update_stats = hw_atl_utils_update_stats,
837 	.set_flow_control = NULL,
838 };
839