1// SPDX-License-Identifier: GPL-2.0-only
2/* Atlantic Network Driver
3 *
4 * Copyright (C) 2014-2019 aQuantia Corporation
5 * Copyright (C) 2019-2020 Marvell International Ltd.
6 */
7
8/* File hw_atl_utils.c: Definition of common functions for Atlantic hardware
9 * abstraction layer.
10 */
11
12#include "../aq_nic.h"
13#include "../aq_hw_utils.h"
14#include "hw_atl_utils.h"
15#include "hw_atl_llh.h"
16#include "hw_atl_llh_internal.h"
17
18#include <linux/random.h>
19
20#define HW_ATL_UCP_0X370_REG    0x0370U
21
22#define HW_ATL_MIF_CMD          0x0200U
23#define HW_ATL_MIF_ADDR         0x0208U
24#define HW_ATL_MIF_VAL          0x020CU
25
26#define HW_ATL_MPI_RPC_ADDR     0x0334U
27#define HW_ATL_RPC_CONTROL_ADR  0x0338U
28#define HW_ATL_RPC_STATE_ADR    0x033CU
29
30#define HW_ATL_MPI_FW_VERSION	0x18
31#define HW_ATL_MPI_CONTROL_ADR  0x0368U
32#define HW_ATL_MPI_STATE_ADR    0x036CU
33
34#define HW_ATL_MPI_STATE_MSK      0x00FFU
35#define HW_ATL_MPI_STATE_SHIFT    0U
36#define HW_ATL_MPI_SPEED_MSK      0x00FF0000U
37#define HW_ATL_MPI_SPEED_SHIFT    16U
38#define HW_ATL_MPI_DIRTY_WAKE_MSK 0x02000000U
39
40#define HW_ATL_MPI_DAISY_CHAIN_STATUS	0x704
41#define HW_ATL_MPI_BOOT_EXIT_CODE	0x388
42
43#define HW_ATL_MAC_PHY_CONTROL	0x4000
44#define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D
45
46#define HW_ATL_FW_VER_1X 0x01050006U
47#define HW_ATL_FW_VER_2X 0x02000000U
48#define HW_ATL_FW_VER_3X 0x03000000U
49#define HW_ATL_FW_VER_4X 0x04000000U
50
51#define FORCE_FLASHLESS 0
52
53enum mcp_area {
54	MCP_AREA_CONFIG = 0x80000000,
55	MCP_AREA_SETTINGS = 0x20000000,
56};
57
58static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
59				      enum hal_atl_utils_fw_state_e state);
60static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self);
61static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self);
62static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self);
63static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self);
64static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self);
65static u32 aq_fw1x_rpc_get(struct aq_hw_s *self);
66
67int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops)
68{
69	int err = 0;
70
71	hw_atl_utils_hw_chip_features_init(self,
72					   &self->chip_features);
73
74	self->fw_ver_actual = hw_atl_utils_get_fw_version(self);
75
76	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual)) {
77		*fw_ops = &aq_fw_1x_ops;
78	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, self->fw_ver_actual)) {
79		*fw_ops = &aq_fw_2x_ops;
80	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, self->fw_ver_actual)) {
81		*fw_ops = &aq_fw_2x_ops;
82	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, self->fw_ver_actual)) {
83		*fw_ops = &aq_fw_2x_ops;
84	} else {
85		aq_pr_err("Bad FW version detected: %x\n",
86			  self->fw_ver_actual);
87		return -EOPNOTSUPP;
88	}
89	self->aq_fw_ops = *fw_ops;
90	err = self->aq_fw_ops->init(self);
91
92	return err;
93}
94
95static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self)
96{
97	u32 gsr, val;
98	int k = 0;
99
100	aq_hw_write_reg(self, 0x404, 0x40e1);
101	AQ_HW_SLEEP(50);
102
103	/* Cleanup SPI */
104	val = aq_hw_read_reg(self, 0x53C);
105	aq_hw_write_reg(self, 0x53C, val | 0x10);
106
107	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
108	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
109
110	/* Kickstart MAC */
111	aq_hw_write_reg(self, 0x404, 0x80e0);
112	aq_hw_write_reg(self, 0x32a8, 0x0);
113	aq_hw_write_reg(self, 0x520, 0x1);
114
115	/* Reset SPI again because of possible interrupted SPI burst */
116	val = aq_hw_read_reg(self, 0x53C);
117	aq_hw_write_reg(self, 0x53C, val | 0x10);
118	AQ_HW_SLEEP(10);
119	/* Clear SPI reset state */
120	aq_hw_write_reg(self, 0x53C, val & ~0x10);
121
122	aq_hw_write_reg(self, 0x404, 0x180e0);
123
124	for (k = 0; k < 1000; k++) {
125		u32 flb_status = aq_hw_read_reg(self,
126						HW_ATL_MPI_DAISY_CHAIN_STATUS);
127
128		flb_status = flb_status & 0x10;
129		if (flb_status)
130			break;
131		AQ_HW_SLEEP(10);
132	}
133	if (k == 1000) {
134		aq_pr_err("MAC kickstart failed\n");
135		return -EIO;
136	}
137
138	/* FW reset */
139	aq_hw_write_reg(self, 0x404, 0x80e0);
140	AQ_HW_SLEEP(50);
141	aq_hw_write_reg(self, 0x3a0, 0x1);
142
143	/* Kickstart PHY - skipped */
144
145	/* Global software reset*/
146	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
147	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
148	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
149			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
150			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
151	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
152	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000);
153
154	for (k = 0; k < 1000; k++) {
155		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
156
157		if (fw_state)
158			break;
159		AQ_HW_SLEEP(10);
160	}
161	if (k == 1000) {
162		aq_pr_err("FW kickstart failed\n");
163		return -EIO;
164	}
165	/* Old FW requires fixed delay after init */
166	AQ_HW_SLEEP(15);
167
168	return 0;
169}
170
171static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self)
172{
173	u32 gsr, val, rbl_status;
174	int k;
175
176	aq_hw_write_reg(self, 0x404, 0x40e1);
177	aq_hw_write_reg(self, 0x3a0, 0x1);
178	aq_hw_write_reg(self, 0x32a8, 0x0);
179
180	/* Alter RBL status */
181	aq_hw_write_reg(self, 0x388, 0xDEAD);
182
183	/* Cleanup SPI */
184	val = aq_hw_read_reg(self, 0x53C);
185	aq_hw_write_reg(self, 0x53C, val | 0x10);
186
187	/* Global software reset*/
188	hw_atl_rx_rx_reg_res_dis_set(self, 0U);
189	hw_atl_tx_tx_reg_res_dis_set(self, 0U);
190	aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL,
191			    BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT),
192			    HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0);
193	gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR);
194	aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR,
195			(gsr & 0xFFFFBFFF) | 0x8000);
196
197	if (FORCE_FLASHLESS)
198		aq_hw_write_reg(self, 0x534, 0x0);
199
200	aq_hw_write_reg(self, 0x404, 0x40e0);
201
202	/* Wait for RBL boot */
203	for (k = 0; k < 1000; k++) {
204		rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF;
205		if (rbl_status && rbl_status != 0xDEAD)
206			break;
207		AQ_HW_SLEEP(10);
208	}
209	if (!rbl_status || rbl_status == 0xDEAD) {
210		aq_pr_err("RBL Restart failed");
211		return -EIO;
212	}
213
214	/* Restore NVR */
215	if (FORCE_FLASHLESS)
216		aq_hw_write_reg(self, 0x534, 0xA0);
217
218	if (rbl_status == 0xF1A7) {
219		aq_pr_err("No FW detected. Dynamic FW load not implemented\n");
220		return -EOPNOTSUPP;
221	}
222
223	for (k = 0; k < 1000; k++) {
224		u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
225
226		if (fw_state)
227			break;
228		AQ_HW_SLEEP(10);
229	}
230	if (k == 1000) {
231		aq_pr_err("FW kickstart failed\n");
232		return -EIO;
233	}
234	/* Old FW requires fixed delay after init */
235	AQ_HW_SLEEP(15);
236
237	return 0;
238}
239
240int hw_atl_utils_soft_reset(struct aq_hw_s *self)
241{
242	int ver = hw_atl_utils_get_fw_version(self);
243	u32 boot_exit_code = 0;
244	u32 val;
245	int k;
246
247	for (k = 0; k < 1000; ++k) {
248		u32 flb_status = aq_hw_read_reg(self,
249						HW_ATL_MPI_DAISY_CHAIN_STATUS);
250		boot_exit_code = aq_hw_read_reg(self,
251						HW_ATL_MPI_BOOT_EXIT_CODE);
252		if (flb_status != 0x06000000 || boot_exit_code != 0)
253			break;
254	}
255
256	if (k == 1000) {
257		aq_pr_err("Neither RBL nor FLB firmware started\n");
258		return -EOPNOTSUPP;
259	}
260
261	self->rbl_enabled = (boot_exit_code != 0);
262
263	if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, ver)) {
264		int err = 0;
265
266		/* FW 1.x may bootup in an invalid POWER state (WOL feature).
267		 * We should work around this by forcing its state back to DEINIT
268		 */
269		hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
270		err = readx_poll_timeout_atomic(hw_atl_utils_mpi_get_state,
271						self, val,
272						(val & HW_ATL_MPI_STATE_MSK) ==
273						 MPI_DEINIT,
274						10, 10000U);
275		if (err)
276			return err;
277	} else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_4X, ver)) {
278		u64 sem_timeout = aq_hw_read_reg(self, HW_ATL_MIF_RESET_TIMEOUT_ADR);
279
280		/* Acquire 2 semaphores before issuing reset for FW 4.x */
281		if (sem_timeout > 3000)
282			sem_timeout = 3000;
283		sem_timeout = sem_timeout * 1000;
284
285		if (sem_timeout != 0) {
286			int err;
287
288			err = readx_poll_timeout_atomic(hw_atl_sem_reset1_get, self, val,
289							val == 1U, 1U, sem_timeout);
290			if (err)
291				aq_pr_err("reset sema1 timeout");
292
293			err = readx_poll_timeout_atomic(hw_atl_sem_reset2_get, self, val,
294							val == 1U, 1U, sem_timeout);
295			if (err)
296				aq_pr_err("reset sema2 timeout");
297		}
298	}
299
300	if (self->rbl_enabled)
301		return hw_atl_utils_soft_reset_rbl(self);
302	else
303		return hw_atl_utils_soft_reset_flb(self);
304}
305
306int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a,
307				  u32 *p, u32 cnt)
308{
309	int err = 0;
310	u32 val;
311
312	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get,
313					self, val, val == 1U,
314					1U, 10000U);
315
316	if (err < 0) {
317		bool is_locked;
318
319		hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
320		is_locked = hw_atl_sem_ram_get(self);
321		if (!is_locked) {
322			err = -ETIME;
323			goto err_exit;
324		}
325	}
326
327	aq_hw_write_reg(self, HW_ATL_MIF_ADDR, a);
328
329	for (++cnt; --cnt && !err;) {
330		aq_hw_write_reg(self, HW_ATL_MIF_CMD, 0x00008000U);
331
332		if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1))
333			err = readx_poll_timeout_atomic(hw_atl_utils_mif_addr_get,
334							self, val, val != a,
335							1U, 1000U);
336		else
337			err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
338							self, val,
339							!(val & 0x100),
340							1U, 1000U);
341
342		*(p++) = aq_hw_read_reg(self, HW_ATL_MIF_VAL);
343		a += 4;
344	}
345
346	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
347
348err_exit:
349	return err;
350}
351
352static int hw_atl_utils_write_b1_mbox(struct aq_hw_s *self, u32 addr,
353				      u32 *p, u32 cnt, enum mcp_area area)
354{
355	u32 data_offset = 0;
356	u32 offset = addr;
357	int err = 0;
358	u32 val;
359
360	switch (area) {
361	case MCP_AREA_CONFIG:
362		offset -= self->rpc_addr;
363		break;
364
365	case MCP_AREA_SETTINGS:
366		offset -= self->settings_addr;
367		break;
368	}
369
370	offset = offset / sizeof(u32);
371
372	for (; data_offset < cnt; ++data_offset, ++offset) {
373		aq_hw_write_reg(self, 0x328, p[data_offset]);
374		aq_hw_write_reg(self, 0x32C,
375				(area | (0xFFFF & (offset * 4))));
376		hw_atl_mcp_up_force_intr_set(self, 1);
377		/* 1000 times by 10us = 10ms */
378		err = readx_poll_timeout_atomic(hw_atl_scrpad12_get,
379						self, val,
380						(val & 0xF0000000) !=
381						area,
382						10U, 10000U);
383
384		if (err < 0)
385			break;
386	}
387
388	return err;
389}
390
391static int hw_atl_utils_write_b0_mbox(struct aq_hw_s *self, u32 addr,
392				      u32 *p, u32 cnt)
393{
394	u32 offset = 0;
395	int err = 0;
396	u32 val;
397
398	aq_hw_write_reg(self, 0x208, addr);
399
400	for (; offset < cnt; ++offset) {
401		aq_hw_write_reg(self, 0x20C, p[offset]);
402		aq_hw_write_reg(self, 0x200, 0xC000);
403
404		err = readx_poll_timeout_atomic(hw_atl_utils_mif_cmd_get,
405						self, val,
406						(val & 0x100) == 0U,
407						10U, 10000U);
408
409		if (err < 0)
410			break;
411	}
412
413	return err;
414}
415
416static int hw_atl_utils_fw_upload_dwords(struct aq_hw_s *self, u32 addr, u32 *p,
417					 u32 cnt, enum mcp_area area)
418{
419	int err = 0;
420	u32 val;
421
422	err = readx_poll_timeout_atomic(hw_atl_sem_ram_get, self,
423					val, val == 1U,
424					10U, 100000U);
425	if (err < 0)
426		goto err_exit;
427
428	if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_B1))
429		err = hw_atl_utils_write_b1_mbox(self, addr, p, cnt, area);
430	else
431		err = hw_atl_utils_write_b0_mbox(self, addr, p, cnt);
432
433	hw_atl_reg_glb_cpu_sem_set(self, 1U, HW_ATL_FW_SM_RAM);
434
435	if (err < 0)
436		goto err_exit;
437
438	err = aq_hw_err_from_flags(self);
439
440err_exit:
441	return err;
442}
443
444int hw_atl_write_fwcfg_dwords(struct aq_hw_s *self, u32 *p, u32 cnt)
445{
446	return hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, p,
447					     cnt, MCP_AREA_CONFIG);
448}
449
450int hw_atl_write_fwsettings_dwords(struct aq_hw_s *self, u32 offset, u32 *p,
451				   u32 cnt)
452{
453	return hw_atl_utils_fw_upload_dwords(self, self->settings_addr + offset,
454					     p, cnt, MCP_AREA_SETTINGS);
455}
456
457bool hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual)
458{
459	const u32 dw_major_mask = 0xff000000U;
460	const u32 dw_minor_mask = 0x00ffffffU;
461	bool ver_match;
462
463	ver_match = (dw_major_mask & (ver_expected ^ ver_actual)) ? false : true;
464	if (!ver_match)
465		goto err_exit;
466	ver_match = ((dw_minor_mask & ver_expected) > (dw_minor_mask & ver_actual)) ?
467		false : true;
468
469err_exit:
470	return ver_match;
471}
472
473static int hw_atl_utils_init_ucp(struct aq_hw_s *self,
474				 const struct aq_hw_caps_s *aq_hw_caps)
475{
476	int err = 0;
477
478	if (!aq_hw_read_reg(self, 0x370U)) {
479		unsigned int rnd = 0U;
480		unsigned int ucp_0x370 = 0U;
481
482		get_random_bytes(&rnd, sizeof(unsigned int));
483
484		ucp_0x370 = 0x02020202U | (0xFEFEFEFEU & rnd);
485		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
486	}
487
488	hw_atl_reg_glb_cpu_scratch_scp_set(self, 0x00000000U, 25U);
489
490	/* check 10 times by 1ms */
491	err = readx_poll_timeout_atomic(hw_atl_scrpad25_get,
492					self, self->mbox_addr,
493					self->mbox_addr != 0U,
494					1000U, 10000U);
495	err = readx_poll_timeout_atomic(aq_fw1x_rpc_get, self,
496					self->rpc_addr,
497					self->rpc_addr != 0U,
498					1000U, 100000U);
499
500	return err;
501}
502
503struct aq_hw_atl_utils_fw_rpc_tid_s {
504	union {
505		u32 val;
506		struct {
507			u16 tid;
508			u16 len;
509		};
510	};
511};
512
513#define hw_atl_utils_fw_rpc_init(_H_) hw_atl_utils_fw_rpc_wait(_H_, NULL)
514
515int hw_atl_utils_fw_rpc_call(struct aq_hw_s *self, unsigned int rpc_size)
516{
517	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
518	int err = 0;
519
520	if (!ATL_HW_IS_CHIP_FEATURE(self, MIPS)) {
521		err = -1;
522		goto err_exit;
523	}
524	err = hw_atl_write_fwcfg_dwords(self, (u32 *)(void *)&self->rpc,
525					(rpc_size + sizeof(u32) -
526					 sizeof(u8)) / sizeof(u32));
527	if (err < 0)
528		goto err_exit;
529
530	sw.tid = 0xFFFFU & (++self->rpc_tid);
531	sw.len = (u16)rpc_size;
532	aq_hw_write_reg(self, HW_ATL_RPC_CONTROL_ADR, sw.val);
533
534err_exit:
535	return err;
536}
537
538int hw_atl_utils_fw_rpc_wait(struct aq_hw_s *self,
539			     struct hw_atl_utils_fw_rpc **rpc)
540{
541	struct aq_hw_atl_utils_fw_rpc_tid_s sw;
542	struct aq_hw_atl_utils_fw_rpc_tid_s fw;
543	int err = 0;
544
545	do {
546		sw.val = aq_hw_read_reg(self, HW_ATL_RPC_CONTROL_ADR);
547
548		self->rpc_tid = sw.tid;
549
550		err = readx_poll_timeout_atomic(hw_atl_utils_rpc_state_get,
551						self, fw.val,
552						sw.tid == fw.tid,
553						1000U, 100000U);
554		if (err < 0)
555			goto err_exit;
556
557		err = aq_hw_err_from_flags(self);
558		if (err < 0)
559			goto err_exit;
560
561		if (fw.len == 0xFFFFU) {
562			if (sw.len > sizeof(self->rpc)) {
563				printk(KERN_INFO "Invalid sw len: %x\n", sw.len);
564				err = -EINVAL;
565				goto err_exit;
566			}
567			err = hw_atl_utils_fw_rpc_call(self, sw.len);
568			if (err < 0)
569				goto err_exit;
570		}
571	} while (sw.tid != fw.tid || 0xFFFFU == fw.len);
572
573	if (rpc) {
574		if (fw.len) {
575			if (fw.len > sizeof(self->rpc)) {
576				printk(KERN_INFO "Invalid fw len: %x\n", fw.len);
577				err = -EINVAL;
578				goto err_exit;
579			}
580			err =
581			hw_atl_utils_fw_downld_dwords(self,
582						      self->rpc_addr,
583						      (u32 *)(void *)
584						      &self->rpc,
585						      (fw.len + sizeof(u32) -
586						       sizeof(u8)) /
587						      sizeof(u32));
588			if (err < 0)
589				goto err_exit;
590		}
591
592		*rpc = &self->rpc;
593	}
594
595err_exit:
596	return err;
597}
598
599static int hw_atl_utils_mpi_create(struct aq_hw_s *self)
600{
601	int err = 0;
602
603	err = hw_atl_utils_init_ucp(self, self->aq_nic_cfg->aq_hw_caps);
604	if (err < 0)
605		goto err_exit;
606
607	err = hw_atl_utils_fw_rpc_init(self);
608	if (err < 0)
609		goto err_exit;
610
611err_exit:
612	return err;
613}
614
615int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self,
616			       struct hw_atl_utils_mbox_header *pmbox)
617{
618	return hw_atl_utils_fw_downld_dwords(self,
619					     self->mbox_addr,
620					     (u32 *)(void *)pmbox,
621					     sizeof(*pmbox) / sizeof(u32));
622}
623
624void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self,
625				 struct hw_atl_utils_mbox *pmbox)
626{
627	int err = 0;
628
629	err = hw_atl_utils_fw_downld_dwords(self,
630					    self->mbox_addr,
631					    (u32 *)(void *)pmbox,
632					    sizeof(*pmbox) / sizeof(u32));
633	if (err < 0)
634		goto err_exit;
635
636	if (ATL_HW_IS_CHIP_FEATURE(self, REVISION_A0)) {
637		unsigned int mtu = self->aq_nic_cfg ?
638					self->aq_nic_cfg->mtu : 1514U;
639		pmbox->stats.ubrc = pmbox->stats.uprc * mtu;
640		pmbox->stats.ubtc = pmbox->stats.uptc * mtu;
641		pmbox->stats.dpc = atomic_read(&self->dpc);
642	} else {
643		pmbox->stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self);
644	}
645
646err_exit:;
647}
648
649static int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed)
650{
651	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
652
653	val = val & ~HW_ATL_MPI_SPEED_MSK;
654	val |= speed << HW_ATL_MPI_SPEED_SHIFT;
655	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
656
657	return 0;
658}
659
660static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self,
661				      enum hal_atl_utils_fw_state_e state)
662{
663	u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR);
664	struct hw_atl_utils_mbox_header mbox;
665	u32 transaction_id = 0;
666	int err = 0;
667
668	if (state == MPI_RESET) {
669		hw_atl_utils_mpi_read_mbox(self, &mbox);
670
671		transaction_id = mbox.transaction_id;
672
673		err = readx_poll_timeout_atomic(hw_atl_utils_get_mpi_mbox_tid,
674						self, mbox.transaction_id,
675						transaction_id !=
676						mbox.transaction_id,
677						1000U, 100000U);
678		if (err < 0)
679			goto err_exit;
680	}
681	/* On interface DEINIT we disable DW (raise bit)
682	 * Otherwise enable DW (clear bit)
683	 */
684	if (state == MPI_DEINIT || state == MPI_POWER)
685		val |= HW_ATL_MPI_DIRTY_WAKE_MSK;
686	else
687		val &= ~HW_ATL_MPI_DIRTY_WAKE_MSK;
688
689	/* Set new state bits */
690	val = val & ~HW_ATL_MPI_STATE_MSK;
691	val |= state & HW_ATL_MPI_STATE_MSK;
692
693	aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val);
694
695err_exit:
696	return err;
697}
698
699int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
700{
701	struct aq_hw_link_status_s *link_status = &self->aq_link_status;
702	u32 mpi_state;
703	u32 speed;
704
705	mpi_state = hw_atl_utils_mpi_get_state(self);
706	speed = mpi_state >> HW_ATL_MPI_SPEED_SHIFT;
707
708	if (!speed) {
709		link_status->mbps = 0U;
710	} else {
711		switch (speed) {
712		case HAL_ATLANTIC_RATE_10G:
713			link_status->mbps = 10000U;
714			break;
715
716		case HAL_ATLANTIC_RATE_5G:
717		case HAL_ATLANTIC_RATE_5GSR:
718			link_status->mbps = 5000U;
719			break;
720
721		case HAL_ATLANTIC_RATE_2G5:
722			link_status->mbps = 2500U;
723			break;
724
725		case HAL_ATLANTIC_RATE_1G:
726			link_status->mbps = 1000U;
727			break;
728
729		case HAL_ATLANTIC_RATE_100M:
730			link_status->mbps = 100U;
731			break;
732
733		default:
734			return -EBUSY;
735		}
736	}
737	link_status->full_duplex = true;
738
739	return 0;
740}
741
742int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self,
743				   u8 *mac)
744{
745	u32 mac_addr[2];
746	u32 efuse_addr;
747	int err = 0;
748	u32 h = 0U;
749	u32 l = 0U;
750
751	if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) {
752		unsigned int ucp_0x370 = 0;
753		unsigned int rnd = 0;
754
755		get_random_bytes(&rnd, sizeof(unsigned int));
756
757		ucp_0x370 = 0x02020202 | (0xFEFEFEFE & rnd);
758		aq_hw_write_reg(self, HW_ATL_UCP_0X370_REG, ucp_0x370);
759	}
760
761	efuse_addr = aq_hw_read_reg(self, 0x00000374U);
762
763	err = hw_atl_utils_fw_downld_dwords(self, efuse_addr + (40U * 4U),
764					    mac_addr, ARRAY_SIZE(mac_addr));
765	if (err < 0) {
766		mac_addr[0] = 0U;
767		mac_addr[1] = 0U;
768		err = 0;
769	} else {
770		mac_addr[0] = __swab32(mac_addr[0]);
771		mac_addr[1] = __swab32(mac_addr[1]);
772	}
773
774	ether_addr_copy(mac, (u8 *)mac_addr);
775
776	if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) {
777		/* chip revision */
778		l = 0xE3000000U |
779		    (0xFFFFU & aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) |
780		    (0x00 << 16);
781		h = 0x8001300EU;
782
783		mac[5] = (u8)(0xFFU & l);
784		l >>= 8;
785		mac[4] = (u8)(0xFFU & l);
786		l >>= 8;
787		mac[3] = (u8)(0xFFU & l);
788		l >>= 8;
789		mac[2] = (u8)(0xFFU & l);
790		mac[1] = (u8)(0xFFU & h);
791		h >>= 8;
792		mac[0] = (u8)(0xFFU & h);
793	}
794
795	return err;
796}
797
798unsigned int hw_atl_utils_mbps_2_speed_index(unsigned int mbps)
799{
800	unsigned int ret = 0U;
801
802	switch (mbps) {
803	case 100U:
804		ret = 5U;
805		break;
806
807	case 1000U:
808		ret = 4U;
809		break;
810
811	case 2500U:
812		ret = 3U;
813		break;
814
815	case 5000U:
816		ret = 1U;
817		break;
818
819	case 10000U:
820		ret = 0U;
821		break;
822
823	default:
824		break;
825	}
826
827	return ret;
828}
829
830void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p)
831{
832	u32 val = hw_atl_reg_glb_mif_id_get(self);
833	u32 mif_rev = val & 0xFFU;
834	u32 chip_features = 0U;
835
836	chip_features |= ATL_HW_CHIP_ATLANTIC;
837
838	if ((0xFU & mif_rev) == 1U) {
839		chip_features |= ATL_HW_CHIP_REVISION_A0 |
840			ATL_HW_CHIP_MPI_AQ |
841			ATL_HW_CHIP_MIPS;
842	} else if ((0xFU & mif_rev) == 2U) {
843		chip_features |= ATL_HW_CHIP_REVISION_B0 |
844			ATL_HW_CHIP_MPI_AQ |
845			ATL_HW_CHIP_MIPS |
846			ATL_HW_CHIP_TPO2 |
847			ATL_HW_CHIP_RPF2;
848	} else if ((0xFU & mif_rev) == 0xAU) {
849		chip_features |= ATL_HW_CHIP_REVISION_B1 |
850			ATL_HW_CHIP_MPI_AQ |
851			ATL_HW_CHIP_MIPS |
852			ATL_HW_CHIP_TPO2 |
853			ATL_HW_CHIP_RPF2;
854	}
855
856	*p = chip_features;
857}
858
859static int hw_atl_fw1x_deinit(struct aq_hw_s *self)
860{
861	hw_atl_utils_mpi_set_speed(self, 0);
862	hw_atl_utils_mpi_set_state(self, MPI_DEINIT);
863
864	return 0;
865}
866
867int hw_atl_utils_update_stats(struct aq_hw_s *self)
868{
869	struct aq_stats_s *cs = &self->curr_stats;
870	struct aq_stats_s curr_stats = *cs;
871	struct hw_atl_utils_mbox mbox;
872	bool corrupted_stats = false;
873
874	hw_atl_utils_mpi_read_stats(self, &mbox);
875
876#define AQ_SDELTA(_N_)  \
877do { \
878	if (!corrupted_stats && \
879	    ((s64)(mbox.stats._N_ - self->last_stats._N_)) >= 0) \
880		curr_stats._N_ += mbox.stats._N_ - self->last_stats._N_; \
881	else \
882		corrupted_stats = true; \
883} while (0)
884
885	if (self->aq_link_status.mbps) {
886		AQ_SDELTA(uprc);
887		AQ_SDELTA(mprc);
888		AQ_SDELTA(bprc);
889		AQ_SDELTA(erpt);
890
891		AQ_SDELTA(uptc);
892		AQ_SDELTA(mptc);
893		AQ_SDELTA(bptc);
894		AQ_SDELTA(erpr);
895
896		AQ_SDELTA(ubrc);
897		AQ_SDELTA(ubtc);
898		AQ_SDELTA(mbrc);
899		AQ_SDELTA(mbtc);
900		AQ_SDELTA(bbrc);
901		AQ_SDELTA(bbtc);
902		AQ_SDELTA(dpc);
903
904		if (!corrupted_stats)
905			*cs = curr_stats;
906	}
907#undef AQ_SDELTA
908
909	cs->dma_pkt_rc = hw_atl_stats_rx_dma_good_pkt_counter_get(self);
910	cs->dma_pkt_tc = hw_atl_stats_tx_dma_good_pkt_counter_get(self);
911	cs->dma_oct_rc = hw_atl_stats_rx_dma_good_octet_counter_get(self);
912	cs->dma_oct_tc = hw_atl_stats_tx_dma_good_octet_counter_get(self);
913
914	memcpy(&self->last_stats, &mbox.stats, sizeof(mbox.stats));
915
916	return 0;
917}
918
919struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self)
920{
921	return &self->curr_stats;
922}
923
924static const u32 hw_atl_utils_hw_mac_regs[] = {
925	0x00005580U, 0x00005590U, 0x000055B0U, 0x000055B4U,
926	0x000055C0U, 0x00005B00U, 0x00005B04U, 0x00005B08U,
927	0x00005B0CU, 0x00005B10U, 0x00005B14U, 0x00005B18U,
928	0x00005B1CU, 0x00005B20U, 0x00005B24U, 0x00005B28U,
929	0x00005B2CU, 0x00005B30U, 0x00005B34U, 0x00005B38U,
930	0x00005B3CU, 0x00005B40U, 0x00005B44U, 0x00005B48U,
931	0x00005B4CU, 0x00005B50U, 0x00005B54U, 0x00005B58U,
932	0x00005B5CU, 0x00005B60U, 0x00005B64U, 0x00005B68U,
933	0x00005B6CU, 0x00005B70U, 0x00005B74U, 0x00005B78U,
934	0x00005B7CU, 0x00007C00U, 0x00007C04U, 0x00007C08U,
935	0x00007C0CU, 0x00007C10U, 0x00007C14U, 0x00007C18U,
936	0x00007C1CU, 0x00007C20U, 0x00007C40U, 0x00007C44U,
937	0x00007C48U, 0x00007C4CU, 0x00007C50U, 0x00007C54U,
938	0x00007C58U, 0x00007C5CU, 0x00007C60U, 0x00007C80U,
939	0x00007C84U, 0x00007C88U, 0x00007C8CU, 0x00007C90U,
940	0x00007C94U, 0x00007C98U, 0x00007C9CU, 0x00007CA0U,
941	0x00007CC0U, 0x00007CC4U, 0x00007CC8U, 0x00007CCCU,
942	0x00007CD0U, 0x00007CD4U, 0x00007CD8U, 0x00007CDCU,
943	0x00007CE0U, 0x00000300U, 0x00000304U, 0x00000308U,
944	0x0000030cU, 0x00000310U, 0x00000314U, 0x00000318U,
945	0x0000031cU, 0x00000360U, 0x00000364U, 0x00000368U,
946	0x0000036cU, 0x00000370U, 0x00000374U, 0x00006900U,
947};
948
949int hw_atl_utils_hw_get_regs(struct aq_hw_s *self,
950			     const struct aq_hw_caps_s *aq_hw_caps,
951			     u32 *regs_buff)
952{
953	unsigned int i = 0U;
954
955	for (i = 0; i < aq_hw_caps->mac_regs_count; i++)
956		regs_buff[i] = aq_hw_read_reg(self,
957					      hw_atl_utils_hw_mac_regs[i]);
958
959	return 0;
960}
961
962u32 hw_atl_utils_get_fw_version(struct aq_hw_s *self)
963{
964	return aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION);
965}
966
967static int aq_fw1x_set_wake_magic(struct aq_hw_s *self, bool wol_enabled,
968				  const u8 *mac)
969{
970	struct hw_atl_utils_fw_rpc *prpc = NULL;
971	unsigned int rpc_size = 0U;
972	int err = 0;
973
974	err = hw_atl_utils_fw_rpc_wait(self, &prpc);
975	if (err < 0)
976		goto err_exit;
977
978	memset(prpc, 0, sizeof(*prpc));
979
980	if (wol_enabled) {
981		rpc_size = offsetof(struct hw_atl_utils_fw_rpc, msg_wol_add) +
982			   sizeof(prpc->msg_wol_add);
983
984
985		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_ADD;
986		prpc->msg_wol_add.priority =
987				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PRIOR;
988		prpc->msg_wol_add.pattern_id =
989				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
990		prpc->msg_wol_add.packet_type =
991				HAL_ATLANTIC_UTILS_FW_MSG_WOL_MAG_PKT;
992
993		ether_addr_copy((u8 *)&prpc->msg_wol_add.magic_packet_pattern,
994				mac);
995	} else {
996		rpc_size = sizeof(prpc->msg_wol_remove) +
997			   offsetof(struct hw_atl_utils_fw_rpc, msg_wol_remove);
998
999		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_WOL_DEL;
1000		prpc->msg_wol_add.pattern_id =
1001				HAL_ATLANTIC_UTILS_FW_MSG_WOL_PATTERN;
1002	}
1003
1004	err = hw_atl_utils_fw_rpc_call(self, rpc_size);
1005
1006err_exit:
1007	return err;
1008}
1009
1010static int aq_fw1x_set_power(struct aq_hw_s *self, unsigned int power_state,
1011			     const u8 *mac)
1012{
1013	struct hw_atl_utils_fw_rpc *prpc = NULL;
1014	unsigned int rpc_size = 0U;
1015	int err = 0;
1016
1017	if (self->aq_nic_cfg->wol & WAKE_MAGIC) {
1018		err = aq_fw1x_set_wake_magic(self, 1, mac);
1019
1020		if (err < 0)
1021			goto err_exit;
1022
1023		rpc_size = sizeof(prpc->msg_id) +
1024			   sizeof(prpc->msg_enable_wakeup);
1025
1026		err = hw_atl_utils_fw_rpc_wait(self, &prpc);
1027
1028		if (err < 0)
1029			goto err_exit;
1030
1031		memset(prpc, 0, rpc_size);
1032
1033		prpc->msg_id = HAL_ATLANTIC_UTILS_FW_MSG_ENABLE_WAKEUP;
1034		prpc->msg_enable_wakeup.pattern_mask = 0x00000002;
1035
1036		err = hw_atl_utils_fw_rpc_call(self, rpc_size);
1037		if (err < 0)
1038			goto err_exit;
1039	}
1040	hw_atl_utils_mpi_set_speed(self, 0);
1041	hw_atl_utils_mpi_set_state(self, MPI_POWER);
1042
1043err_exit:
1044	return err;
1045}
1046
1047static u32 hw_atl_utils_get_mpi_mbox_tid(struct aq_hw_s *self)
1048{
1049	struct hw_atl_utils_mbox_header mbox;
1050
1051	hw_atl_utils_mpi_read_mbox(self, &mbox);
1052
1053	return mbox.transaction_id;
1054}
1055
1056static u32 hw_atl_utils_mpi_get_state(struct aq_hw_s *self)
1057{
1058	return aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR);
1059}
1060
1061static u32 hw_atl_utils_mif_cmd_get(struct aq_hw_s *self)
1062{
1063	return aq_hw_read_reg(self, HW_ATL_MIF_CMD);
1064}
1065
1066static u32 hw_atl_utils_mif_addr_get(struct aq_hw_s *self)
1067{
1068	return aq_hw_read_reg(self, HW_ATL_MIF_ADDR);
1069}
1070
1071static u32 hw_atl_utils_rpc_state_get(struct aq_hw_s *self)
1072{
1073	return aq_hw_read_reg(self, HW_ATL_RPC_STATE_ADR);
1074}
1075
1076static u32 aq_fw1x_rpc_get(struct aq_hw_s *self)
1077{
1078	return aq_hw_read_reg(self, HW_ATL_MPI_RPC_ADDR);
1079}
1080
1081const struct aq_fw_ops aq_fw_1x_ops = {
1082	.init = hw_atl_utils_mpi_create,
1083	.deinit = hw_atl_fw1x_deinit,
1084	.reset = NULL,
1085	.get_mac_permanent = hw_atl_utils_get_mac_permanent,
1086	.set_link_speed = hw_atl_utils_mpi_set_speed,
1087	.set_state = hw_atl_utils_mpi_set_state,
1088	.update_link_status = hw_atl_utils_mpi_get_link_status,
1089	.update_stats = hw_atl_utils_update_stats,
1090	.get_mac_temp = NULL,
1091	.get_phy_temp = NULL,
1092	.set_power = aq_fw1x_set_power,
1093	.set_eee_rate = NULL,
1094	.get_eee_rate = NULL,
1095	.set_flow_control = NULL,
1096	.send_fw_request = NULL,
1097	.enable_ptp = NULL,
1098	.led_control = NULL,
1099};
1100