xref: /dpdk/drivers/net/r8169/r8169_hw.c (revision b574fb4cc855f4e86659d37ded01e7a218c38865)
188f5b657SHoward Wang /* SPDX-License-Identifier: BSD-3-Clause
288f5b657SHoward Wang  * Copyright(c) 2024 Realtek Corporation. All rights reserved
388f5b657SHoward Wang  */
488f5b657SHoward Wang 
588f5b657SHoward Wang #include <stdio.h>
688f5b657SHoward Wang #include <errno.h>
788f5b657SHoward Wang #include <stdint.h>
888f5b657SHoward Wang 
988f5b657SHoward Wang #include <rte_ether.h>
1088f5b657SHoward Wang #include <ethdev_driver.h>
1188f5b657SHoward Wang 
1288f5b657SHoward Wang #include "r8169_hw.h"
1388f5b657SHoward Wang #include "r8169_logs.h"
147d502791SHoward Wang #include "r8169_dash.h"
1588f5b657SHoward Wang 
16619f6ebcSHoward Wang static u32
17619f6ebcSHoward Wang rtl_eri_read_with_oob_base_address(struct rtl_hw *hw, int addr, int len,
18619f6ebcSHoward Wang 				   int type, const u32 base_address)
19619f6ebcSHoward Wang {
20619f6ebcSHoward Wang 	int i, val_shift, shift = 0;
21619f6ebcSHoward Wang 	u32 value1 = 0;
22619f6ebcSHoward Wang 	u32 value2 = 0;
23619f6ebcSHoward Wang 	u32 eri_cmd, tmp, mask;
24619f6ebcSHoward Wang 	const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) |
25619f6ebcSHoward Wang 					     (base_address & 0x000FFF);
26619f6ebcSHoward Wang 
27619f6ebcSHoward Wang 	if (len > 4 || len <= 0)
28619f6ebcSHoward Wang 		return -1;
29619f6ebcSHoward Wang 
30619f6ebcSHoward Wang 	while (len > 0) {
31619f6ebcSHoward Wang 		val_shift = addr % ERIAR_Addr_Align;
32619f6ebcSHoward Wang 		addr = addr & ~0x3;
33619f6ebcSHoward Wang 
34619f6ebcSHoward Wang 		eri_cmd = ERIAR_Read | transformed_base_address |
35619f6ebcSHoward Wang 			  type << ERIAR_Type_shift |
36619f6ebcSHoward Wang 			  ERIAR_ByteEn << ERIAR_ByteEn_shift |
37619f6ebcSHoward Wang 			  (addr & 0x0FFF);
38619f6ebcSHoward Wang 		if (addr & 0xF000) {
39619f6ebcSHoward Wang 			tmp = addr & 0xF000;
40619f6ebcSHoward Wang 			tmp >>= 12;
41619f6ebcSHoward Wang 			eri_cmd |= (tmp << 20) & 0x00F00000;
42619f6ebcSHoward Wang 		}
43619f6ebcSHoward Wang 
44619f6ebcSHoward Wang 		RTL_W32(hw, ERIAR, eri_cmd);
45619f6ebcSHoward Wang 
46619f6ebcSHoward Wang 		for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) {
47619f6ebcSHoward Wang 			rte_delay_us(RTL_CHANNEL_WAIT_TIME);
48619f6ebcSHoward Wang 
49619f6ebcSHoward Wang 			/* Check if the NIC has completed ERI read */
50619f6ebcSHoward Wang 			if (RTL_R32(hw, ERIAR) & ERIAR_Flag)
51619f6ebcSHoward Wang 				break;
52619f6ebcSHoward Wang 		}
53619f6ebcSHoward Wang 
54619f6ebcSHoward Wang 		if (len == 1)
55619f6ebcSHoward Wang 			mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF;
56619f6ebcSHoward Wang 		else if (len == 2)
57619f6ebcSHoward Wang 			mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF;
58619f6ebcSHoward Wang 		else if (len == 3)
59619f6ebcSHoward Wang 			mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
60619f6ebcSHoward Wang 		else
61619f6ebcSHoward Wang 			mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
62619f6ebcSHoward Wang 
63619f6ebcSHoward Wang 		value1 = RTL_R32(hw, ERIDR) & mask;
64619f6ebcSHoward Wang 		value2 |= (value1 >> val_shift * 8) << shift * 8;
65619f6ebcSHoward Wang 
66619f6ebcSHoward Wang 		if (len <= 4 - val_shift) {
67619f6ebcSHoward Wang 			len = 0;
68619f6ebcSHoward Wang 		} else {
69619f6ebcSHoward Wang 			len -= (4 - val_shift);
70619f6ebcSHoward Wang 			shift = 4 - val_shift;
71619f6ebcSHoward Wang 			addr += 4;
72619f6ebcSHoward Wang 		}
73619f6ebcSHoward Wang 	}
74619f6ebcSHoward Wang 
75619f6ebcSHoward Wang 	rte_delay_us(RTL_CHANNEL_EXIT_DELAY_TIME);
76619f6ebcSHoward Wang 
77619f6ebcSHoward Wang 	return value2;
78619f6ebcSHoward Wang }
79619f6ebcSHoward Wang 
80619f6ebcSHoward Wang static int
81619f6ebcSHoward Wang rtl_eri_write_with_oob_base_address(struct rtl_hw *hw, int addr,
82619f6ebcSHoward Wang 				    int len, u32 value, int type, const u32 base_address)
83619f6ebcSHoward Wang {
84619f6ebcSHoward Wang 	int i, val_shift, shift = 0;
85619f6ebcSHoward Wang 	u32 value1 = 0;
86619f6ebcSHoward Wang 	u32 eri_cmd, mask, tmp;
87619f6ebcSHoward Wang 	const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) |
88619f6ebcSHoward Wang 					     (base_address & 0x000FFF);
89619f6ebcSHoward Wang 
90619f6ebcSHoward Wang 	if (len > 4 || len <= 0)
91619f6ebcSHoward Wang 		return -1;
92619f6ebcSHoward Wang 
93619f6ebcSHoward Wang 	while (len > 0) {
94619f6ebcSHoward Wang 		val_shift = addr % ERIAR_Addr_Align;
95619f6ebcSHoward Wang 		addr = addr & ~0x3;
96619f6ebcSHoward Wang 
97619f6ebcSHoward Wang 		if (len == 1)
98619f6ebcSHoward Wang 			mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF;
99619f6ebcSHoward Wang 		else if (len == 2)
100619f6ebcSHoward Wang 			mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF;
101619f6ebcSHoward Wang 		else if (len == 3)
102619f6ebcSHoward Wang 			mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
103619f6ebcSHoward Wang 		else
104619f6ebcSHoward Wang 			mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF;
105619f6ebcSHoward Wang 
106619f6ebcSHoward Wang 		value1 = rtl_eri_read_with_oob_base_address(hw, addr, 4, type,
107619f6ebcSHoward Wang 							    base_address) & ~mask;
108619f6ebcSHoward Wang 		value1 |= ((value << val_shift * 8) >> shift * 8);
109619f6ebcSHoward Wang 
110619f6ebcSHoward Wang 		RTL_W32(hw, ERIDR, value1);
111619f6ebcSHoward Wang 
112619f6ebcSHoward Wang 		eri_cmd = ERIAR_Write | transformed_base_address |
113619f6ebcSHoward Wang 			  type << ERIAR_Type_shift |
114619f6ebcSHoward Wang 			  ERIAR_ByteEn << ERIAR_ByteEn_shift |
115619f6ebcSHoward Wang 			  (addr & 0x0FFF);
116619f6ebcSHoward Wang 		if (addr & 0xF000) {
117619f6ebcSHoward Wang 			tmp = addr & 0xF000;
118619f6ebcSHoward Wang 			tmp >>= 12;
119619f6ebcSHoward Wang 			eri_cmd |= (tmp << 20) & 0x00F00000;
120619f6ebcSHoward Wang 		}
121619f6ebcSHoward Wang 
122619f6ebcSHoward Wang 		RTL_W32(hw, ERIAR, eri_cmd);
123619f6ebcSHoward Wang 
124619f6ebcSHoward Wang 		for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) {
125619f6ebcSHoward Wang 			rte_delay_us(RTL_CHANNEL_WAIT_TIME);
126619f6ebcSHoward Wang 
127619f6ebcSHoward Wang 			/* Check if the NIC has completed ERI write */
128619f6ebcSHoward Wang 			if (!(RTL_R32(hw, ERIAR) & ERIAR_Flag))
129619f6ebcSHoward Wang 				break;
130619f6ebcSHoward Wang 		}
131619f6ebcSHoward Wang 
132619f6ebcSHoward Wang 		if (len <= 4 - val_shift) {
133619f6ebcSHoward Wang 			len = 0;
134619f6ebcSHoward Wang 		} else {
135619f6ebcSHoward Wang 			len -= (4 - val_shift);
136619f6ebcSHoward Wang 			shift = 4 - val_shift;
137619f6ebcSHoward Wang 			addr += 4;
138619f6ebcSHoward Wang 		}
139619f6ebcSHoward Wang 	}
140619f6ebcSHoward Wang 
141619f6ebcSHoward Wang 	rte_delay_us(RTL_CHANNEL_EXIT_DELAY_TIME);
142619f6ebcSHoward Wang 
143619f6ebcSHoward Wang 	return 0;
144619f6ebcSHoward Wang }
145619f6ebcSHoward Wang 
146619f6ebcSHoward Wang static u32
147619f6ebcSHoward Wang rtl_ocp_read_with_oob_base_address(struct rtl_hw *hw, u16 addr, u8 len,
148619f6ebcSHoward Wang 				   const u32 base_address)
149619f6ebcSHoward Wang {
150619f6ebcSHoward Wang 	return rtl_eri_read_with_oob_base_address(hw, addr, len, ERIAR_OOB,
151619f6ebcSHoward Wang 						  base_address);
152619f6ebcSHoward Wang }
153619f6ebcSHoward Wang 
154619f6ebcSHoward Wang u32
155619f6ebcSHoward Wang rtl_ocp_read(struct rtl_hw *hw, u16 addr, u8 len)
156619f6ebcSHoward Wang {
157619f6ebcSHoward Wang 	u32 value = 0;
158619f6ebcSHoward Wang 
159619f6ebcSHoward Wang 	if (!hw->AllowAccessDashOcp)
160619f6ebcSHoward Wang 		return 0xffffffff;
161619f6ebcSHoward Wang 
162619f6ebcSHoward Wang 	if (hw->HwSuppOcpChannelVer == 2)
163619f6ebcSHoward Wang 		value = rtl_ocp_read_with_oob_base_address(hw, addr, len, NO_BASE_ADDRESS);
164619f6ebcSHoward Wang 
165619f6ebcSHoward Wang 	return value;
166619f6ebcSHoward Wang }
167619f6ebcSHoward Wang 
168619f6ebcSHoward Wang static u32
169619f6ebcSHoward Wang rtl_ocp_write_with_oob_base_address(struct rtl_hw *hw, u16 addr, u8 len,
170619f6ebcSHoward Wang 				    u32 value, const u32 base_address)
171619f6ebcSHoward Wang {
172619f6ebcSHoward Wang 	return rtl_eri_write_with_oob_base_address(hw, addr, len, value, ERIAR_OOB,
173619f6ebcSHoward Wang 						   base_address);
174619f6ebcSHoward Wang }
175619f6ebcSHoward Wang 
176619f6ebcSHoward Wang void
177619f6ebcSHoward Wang rtl_ocp_write(struct rtl_hw *hw, u16 addr, u8 len, u32 value)
178619f6ebcSHoward Wang {
179619f6ebcSHoward Wang 	if (!hw->AllowAccessDashOcp)
180619f6ebcSHoward Wang 		return;
181619f6ebcSHoward Wang 
182619f6ebcSHoward Wang 	if (hw->HwSuppOcpChannelVer == 2)
183619f6ebcSHoward Wang 		rtl_ocp_write_with_oob_base_address(hw, addr, len, value, NO_BASE_ADDRESS);
184619f6ebcSHoward Wang }
185619f6ebcSHoward Wang 
186619f6ebcSHoward Wang void
187619f6ebcSHoward Wang rtl8125_oob_mutex_lock(struct rtl_hw *hw)
188619f6ebcSHoward Wang {
189619f6ebcSHoward Wang 	u8 reg_16, reg_a0;
190619f6ebcSHoward Wang 	u16 ocp_reg_mutex_ib;
191619f6ebcSHoward Wang 	u16 ocp_reg_mutex_oob;
192619f6ebcSHoward Wang 	u16 ocp_reg_mutex_prio;
193619f6ebcSHoward Wang 	u32 wait_cnt_0, wait_cnt_1;
194619f6ebcSHoward Wang 
195619f6ebcSHoward Wang 	if (!hw->DASH)
196619f6ebcSHoward Wang 		return;
197619f6ebcSHoward Wang 
198619f6ebcSHoward Wang 	switch (hw->mcfg) {
199619f6ebcSHoward Wang 	case CFG_METHOD_48:
200619f6ebcSHoward Wang 	case CFG_METHOD_49:
201619f6ebcSHoward Wang 	case CFG_METHOD_52:
202619f6ebcSHoward Wang 	case CFG_METHOD_54:
203619f6ebcSHoward Wang 	case CFG_METHOD_55:
204619f6ebcSHoward Wang 		ocp_reg_mutex_oob = 0x110;
205619f6ebcSHoward Wang 		ocp_reg_mutex_ib = 0x114;
206619f6ebcSHoward Wang 		ocp_reg_mutex_prio = 0x11C;
207619f6ebcSHoward Wang 		break;
208619f6ebcSHoward Wang 	default:
209619f6ebcSHoward Wang 		return;
210619f6ebcSHoward Wang 	}
211619f6ebcSHoward Wang 
212619f6ebcSHoward Wang 	rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, BIT_0);
213619f6ebcSHoward Wang 	reg_16 = rtl_ocp_read(hw, ocp_reg_mutex_oob, 1);
214619f6ebcSHoward Wang 	wait_cnt_0 = 0;
215619f6ebcSHoward Wang 	while (reg_16) {
216619f6ebcSHoward Wang 		reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 1);
217619f6ebcSHoward Wang 		if (reg_a0) {
218619f6ebcSHoward Wang 			rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, 0x00);
219619f6ebcSHoward Wang 			reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 1);
220619f6ebcSHoward Wang 			wait_cnt_1 = 0;
221619f6ebcSHoward Wang 			while (reg_a0) {
222619f6ebcSHoward Wang 				reg_a0 = rtl_ocp_read(hw, ocp_reg_mutex_prio, 1);
223619f6ebcSHoward Wang 
224619f6ebcSHoward Wang 				wait_cnt_1++;
225619f6ebcSHoward Wang 
226619f6ebcSHoward Wang 				if (wait_cnt_1 > 2000)
227619f6ebcSHoward Wang 					break;
228619f6ebcSHoward Wang 			};
229619f6ebcSHoward Wang 			rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, BIT_0);
230619f6ebcSHoward Wang 		}
231619f6ebcSHoward Wang 		reg_16 = rtl_ocp_read(hw, ocp_reg_mutex_oob, 1);
232619f6ebcSHoward Wang 
233619f6ebcSHoward Wang 		wait_cnt_0++;
234619f6ebcSHoward Wang 
235619f6ebcSHoward Wang 		if (wait_cnt_0 > 2000)
236619f6ebcSHoward Wang 			break;
237619f6ebcSHoward Wang 	};
238619f6ebcSHoward Wang }
239619f6ebcSHoward Wang 
240619f6ebcSHoward Wang void
241619f6ebcSHoward Wang rtl8125_oob_mutex_unlock(struct rtl_hw *hw)
242619f6ebcSHoward Wang {
243619f6ebcSHoward Wang 	u16 ocp_reg_mutex_ib;
244619f6ebcSHoward Wang 	u16 ocp_reg_mutex_prio;
245619f6ebcSHoward Wang 
246619f6ebcSHoward Wang 	if (!hw->DASH)
247619f6ebcSHoward Wang 		return;
248619f6ebcSHoward Wang 
249619f6ebcSHoward Wang 	switch (hw->mcfg) {
250619f6ebcSHoward Wang 	case CFG_METHOD_48:
251619f6ebcSHoward Wang 	case CFG_METHOD_49:
252619f6ebcSHoward Wang 	case CFG_METHOD_52:
253619f6ebcSHoward Wang 	case CFG_METHOD_54:
254619f6ebcSHoward Wang 	case CFG_METHOD_55:
255619f6ebcSHoward Wang 		ocp_reg_mutex_ib = 0x114;
256619f6ebcSHoward Wang 		ocp_reg_mutex_prio = 0x11C;
257619f6ebcSHoward Wang 		break;
258619f6ebcSHoward Wang 	default:
259619f6ebcSHoward Wang 		return;
260619f6ebcSHoward Wang 	}
261619f6ebcSHoward Wang 
262619f6ebcSHoward Wang 	rtl_ocp_write(hw, ocp_reg_mutex_prio, 1, BIT_0);
263619f6ebcSHoward Wang 	rtl_ocp_write(hw, ocp_reg_mutex_ib, 1, 0x00);
264619f6ebcSHoward Wang }
265619f6ebcSHoward Wang 
26688f5b657SHoward Wang void
26788f5b657SHoward Wang rtl_mac_ocp_write(struct rtl_hw *hw, u16 addr, u16 value)
26888f5b657SHoward Wang {
26988f5b657SHoward Wang 	u32 data32;
27088f5b657SHoward Wang 
27188f5b657SHoward Wang 	data32 = addr / 2;
27288f5b657SHoward Wang 	data32 <<= OCPR_Addr_Reg_shift;
27388f5b657SHoward Wang 	data32 += value;
27488f5b657SHoward Wang 	data32 |= OCPR_Write;
27588f5b657SHoward Wang 
27688f5b657SHoward Wang 	RTL_W32(hw, MACOCP, data32);
27788f5b657SHoward Wang }
27888f5b657SHoward Wang 
27988f5b657SHoward Wang u16
28088f5b657SHoward Wang rtl_mac_ocp_read(struct rtl_hw *hw, u16 addr)
28188f5b657SHoward Wang {
28288f5b657SHoward Wang 	u32 data32;
28388f5b657SHoward Wang 	u16 data16 = 0;
28488f5b657SHoward Wang 
28588f5b657SHoward Wang 	data32 = addr / 2;
28688f5b657SHoward Wang 	data32 <<= OCPR_Addr_Reg_shift;
28788f5b657SHoward Wang 
28888f5b657SHoward Wang 	RTL_W32(hw, MACOCP, data32);
28988f5b657SHoward Wang 	data16 = (u16)RTL_R32(hw, MACOCP);
29088f5b657SHoward Wang 
29188f5b657SHoward Wang 	return data16;
29288f5b657SHoward Wang }
29388f5b657SHoward Wang 
29488f5b657SHoward Wang u32
29588f5b657SHoward Wang rtl_csi_read(struct rtl_hw *hw, u32 addr)
29688f5b657SHoward Wang {
29788f5b657SHoward Wang 	u32 cmd;
29888f5b657SHoward Wang 	int i;
29988f5b657SHoward Wang 	u32 value = 0;
30088f5b657SHoward Wang 
30188f5b657SHoward Wang 	cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift |
30288f5b657SHoward Wang 	      (addr & CSIAR_Addr_Mask);
30388f5b657SHoward Wang 
30488f5b657SHoward Wang 	RTL_W32(hw, CSIAR, cmd);
30588f5b657SHoward Wang 
30688f5b657SHoward Wang 	for (i = 0; i < 10; i++) {
30788f5b657SHoward Wang 		rte_delay_us(100);
30888f5b657SHoward Wang 
30988f5b657SHoward Wang 		/* Check if the NIC has completed CSI read */
31088f5b657SHoward Wang 		if (RTL_R32(hw, CSIAR) & CSIAR_Flag) {
31188f5b657SHoward Wang 			value = RTL_R32(hw, CSIDR);
31288f5b657SHoward Wang 			break;
31388f5b657SHoward Wang 		}
31488f5b657SHoward Wang 	}
31588f5b657SHoward Wang 
31688f5b657SHoward Wang 	rte_delay_us(20);
31788f5b657SHoward Wang 
31888f5b657SHoward Wang 	return value;
31988f5b657SHoward Wang }
32088f5b657SHoward Wang 
32188f5b657SHoward Wang void
32288f5b657SHoward Wang rtl_csi_write(struct rtl_hw *hw, u32 addr, u32 value)
32388f5b657SHoward Wang {
32488f5b657SHoward Wang 	u32 cmd;
32588f5b657SHoward Wang 	int i;
32688f5b657SHoward Wang 
32788f5b657SHoward Wang 	RTL_W32(hw, CSIDR, value);
32888f5b657SHoward Wang 	cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift |
32988f5b657SHoward Wang 	      (addr & CSIAR_Addr_Mask);
33088f5b657SHoward Wang 
33188f5b657SHoward Wang 	RTL_W32(hw, CSIAR, cmd);
33288f5b657SHoward Wang 
33388f5b657SHoward Wang 	for (i = 0; i < RTL_CHANNEL_WAIT_COUNT; i++) {
33488f5b657SHoward Wang 		rte_delay_us(RTL_CHANNEL_WAIT_TIME);
33588f5b657SHoward Wang 
33688f5b657SHoward Wang 		/* Check if the NIC has completed CSI write */
33788f5b657SHoward Wang 		if (!(RTL_R32(hw, CSIAR) & CSIAR_Flag))
33888f5b657SHoward Wang 			break;
33988f5b657SHoward Wang 	}
34088f5b657SHoward Wang 
34188f5b657SHoward Wang 	rte_delay_us(RTL_CHANNEL_EXIT_DELAY_TIME);
34288f5b657SHoward Wang }
343619f6ebcSHoward Wang 
344619f6ebcSHoward Wang static void
345619f6ebcSHoward Wang rtl_enable_rxdvgate(struct rtl_hw *hw)
346619f6ebcSHoward Wang {
347619f6ebcSHoward Wang 	switch (hw->mcfg) {
348619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
349619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
350619f6ebcSHoward Wang 		RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) | BIT_3);
351619f6ebcSHoward Wang 		rte_delay_ms(2);
352619f6ebcSHoward Wang 	}
353619f6ebcSHoward Wang }
354619f6ebcSHoward Wang 
355619f6ebcSHoward Wang void
356619f6ebcSHoward Wang rtl_disable_rxdvgate(struct rtl_hw *hw)
357619f6ebcSHoward Wang {
358619f6ebcSHoward Wang 	switch (hw->mcfg) {
3598e852260SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
360c4adac96SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
361619f6ebcSHoward Wang 		RTL_W8(hw, 0xF2, RTL_R8(hw, 0xF2) & ~BIT_3);
362619f6ebcSHoward Wang 		rte_delay_ms(2);
363619f6ebcSHoward Wang 	}
364619f6ebcSHoward Wang }
365619f6ebcSHoward Wang 
366619f6ebcSHoward Wang static void
367619f6ebcSHoward Wang rtl_stop_all_request(struct rtl_hw *hw)
368619f6ebcSHoward Wang {
369619f6ebcSHoward Wang 	int i;
370619f6ebcSHoward Wang 
371619f6ebcSHoward Wang 	RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) | StopReq);
372619f6ebcSHoward Wang 
373619f6ebcSHoward Wang 	switch (hw->mcfg) {
374619f6ebcSHoward Wang 	case CFG_METHOD_48:
375619f6ebcSHoward Wang 	case CFG_METHOD_49:
376619f6ebcSHoward Wang 	case CFG_METHOD_52:
377619f6ebcSHoward Wang 		for (i = 0; i < 20; i++) {
378619f6ebcSHoward Wang 			rte_delay_us(10);
379619f6ebcSHoward Wang 			if (!(RTL_R8(hw, ChipCmd) & StopReq))
380619f6ebcSHoward Wang 				break;
381619f6ebcSHoward Wang 		}
382619f6ebcSHoward Wang 
383619f6ebcSHoward Wang 		break;
384619f6ebcSHoward Wang 	default:
385619f6ebcSHoward Wang 		rte_delay_us(200);
386619f6ebcSHoward Wang 		break;
387619f6ebcSHoward Wang 	}
388619f6ebcSHoward Wang 
389619f6ebcSHoward Wang 	RTL_W8(hw, ChipCmd, RTL_R8(hw, ChipCmd) & (CmdTxEnb | CmdRxEnb));
390619f6ebcSHoward Wang }
391619f6ebcSHoward Wang 
392619f6ebcSHoward Wang static void
393619f6ebcSHoward Wang rtl_wait_txrx_fifo_empty(struct rtl_hw *hw)
394619f6ebcSHoward Wang {
395619f6ebcSHoward Wang 	int i;
396619f6ebcSHoward Wang 
397619f6ebcSHoward Wang 	switch (hw->mcfg) {
398619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
399619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
400619f6ebcSHoward Wang 		for (i = 0; i < 3000; i++) {
401619f6ebcSHoward Wang 			rte_delay_us(50);
402619f6ebcSHoward Wang 			if ((RTL_R8(hw, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) ==
403619f6ebcSHoward Wang 			    (Txfifo_empty | Rxfifo_empty))
404619f6ebcSHoward Wang 				break;
405619f6ebcSHoward Wang 		}
406619f6ebcSHoward Wang 		break;
407619f6ebcSHoward Wang 	}
408619f6ebcSHoward Wang 
409619f6ebcSHoward Wang 	switch (hw->mcfg) {
410619f6ebcSHoward Wang 	case CFG_METHOD_50:
411619f6ebcSHoward Wang 	case CFG_METHOD_51:
412619f6ebcSHoward Wang 	case CFG_METHOD_53 ... CFG_METHOD_57:
413619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
414619f6ebcSHoward Wang 		for (i = 0; i < 3000; i++) {
415619f6ebcSHoward Wang 			rte_delay_us(50);
416619f6ebcSHoward Wang 			if ((RTL_R16(hw, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) ==
417619f6ebcSHoward Wang 			    (BIT_0 | BIT_1 | BIT_8))
418619f6ebcSHoward Wang 				break;
419619f6ebcSHoward Wang 		}
420619f6ebcSHoward Wang 		break;
421619f6ebcSHoward Wang 	}
422619f6ebcSHoward Wang }
423619f6ebcSHoward Wang 
424619f6ebcSHoward Wang static void
425619f6ebcSHoward Wang rtl_disable_rx_packet_filter(struct rtl_hw *hw)
426619f6ebcSHoward Wang {
427619f6ebcSHoward Wang 	RTL_W32(hw, RxConfig, RTL_R32(hw, RxConfig) &
428619f6ebcSHoward Wang 		~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast |
429619f6ebcSHoward Wang 		AcceptMyPhys | AcceptAllPhys));
430619f6ebcSHoward Wang }
431619f6ebcSHoward Wang 
432619f6ebcSHoward Wang void
433619f6ebcSHoward Wang rtl_nic_reset(struct rtl_hw *hw)
434619f6ebcSHoward Wang {
435619f6ebcSHoward Wang 	int i;
436619f6ebcSHoward Wang 
437619f6ebcSHoward Wang 	rtl_disable_rx_packet_filter(hw);
438619f6ebcSHoward Wang 
439619f6ebcSHoward Wang 	rtl_enable_rxdvgate(hw);
440619f6ebcSHoward Wang 
441619f6ebcSHoward Wang 	rtl_stop_all_request(hw);
442619f6ebcSHoward Wang 
443619f6ebcSHoward Wang 	rtl_wait_txrx_fifo_empty(hw);
444619f6ebcSHoward Wang 
445619f6ebcSHoward Wang 	rte_delay_ms(2);
446619f6ebcSHoward Wang 
447619f6ebcSHoward Wang 	/* Soft reset the chip. */
448619f6ebcSHoward Wang 	RTL_W8(hw, ChipCmd, CmdReset);
449619f6ebcSHoward Wang 
450619f6ebcSHoward Wang 	/* Check that the chip has finished the reset. */
451619f6ebcSHoward Wang 	for (i = 100; i > 0; i--) {
452619f6ebcSHoward Wang 		rte_delay_us(100);
453619f6ebcSHoward Wang 		if ((RTL_R8(hw, ChipCmd) & CmdReset) == 0)
454619f6ebcSHoward Wang 			break;
455619f6ebcSHoward Wang 	}
456619f6ebcSHoward Wang }
457619f6ebcSHoward Wang 
458619f6ebcSHoward Wang void
459619f6ebcSHoward Wang rtl_enable_cfg9346_write(struct rtl_hw *hw)
460619f6ebcSHoward Wang {
461619f6ebcSHoward Wang 	RTL_W8(hw, Cfg9346, RTL_R8(hw, Cfg9346) | Cfg9346_Unlock);
462619f6ebcSHoward Wang }
463619f6ebcSHoward Wang 
464619f6ebcSHoward Wang void
465619f6ebcSHoward Wang rtl_disable_cfg9346_write(struct rtl_hw *hw)
466619f6ebcSHoward Wang {
467619f6ebcSHoward Wang 	RTL_W8(hw, Cfg9346, RTL_R8(hw, Cfg9346) & ~Cfg9346_Unlock);
468619f6ebcSHoward Wang }
469619f6ebcSHoward Wang 
470619f6ebcSHoward Wang static void
471619f6ebcSHoward Wang rtl_enable_force_clkreq(struct rtl_hw *hw, bool enable)
472619f6ebcSHoward Wang {
473619f6ebcSHoward Wang 	if (enable)
474619f6ebcSHoward Wang 		RTL_W8(hw, 0xF1, RTL_R8(hw, 0xF1) | BIT_7);
475619f6ebcSHoward Wang 	else
476619f6ebcSHoward Wang 		RTL_W8(hw, 0xF1, RTL_R8(hw, 0xF1) & ~BIT_7);
477619f6ebcSHoward Wang }
478619f6ebcSHoward Wang 
479619f6ebcSHoward Wang static void
480619f6ebcSHoward Wang rtl_enable_aspm_clkreq_lock(struct rtl_hw *hw, bool enable)
481619f6ebcSHoward Wang {
482619f6ebcSHoward Wang 	switch (hw->mcfg) {
483619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
484619f6ebcSHoward Wang 	case CFG_METHOD_69:
485619f6ebcSHoward Wang 		rtl_enable_cfg9346_write(hw);
486619f6ebcSHoward Wang 		if (enable) {
487619f6ebcSHoward Wang 			RTL_W8(hw, Config2, RTL_R8(hw, Config2) | BIT_7);
488619f6ebcSHoward Wang 			RTL_W8(hw, Config5, RTL_R8(hw, Config5) | BIT_0);
489619f6ebcSHoward Wang 		} else {
490619f6ebcSHoward Wang 			RTL_W8(hw, Config2, RTL_R8(hw, Config2) & ~BIT_7);
491619f6ebcSHoward Wang 			RTL_W8(hw, Config5, RTL_R8(hw, Config5) & ~BIT_0);
492619f6ebcSHoward Wang 		}
493619f6ebcSHoward Wang 		rtl_disable_cfg9346_write(hw);
494619f6ebcSHoward Wang 		break;
495619f6ebcSHoward Wang 	case CFG_METHOD_70:
496619f6ebcSHoward Wang 	case CFG_METHOD_71:
497619f6ebcSHoward Wang 		rtl_enable_cfg9346_write(hw);
498619f6ebcSHoward Wang 		if (enable) {
499619f6ebcSHoward Wang 			RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) | BIT_3);
500619f6ebcSHoward Wang 			RTL_W8(hw, Config5, RTL_R8(hw, Config5) | BIT_0);
501619f6ebcSHoward Wang 		} else {
502619f6ebcSHoward Wang 			RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) & ~BIT_3);
503619f6ebcSHoward Wang 			RTL_W8(hw, Config5, RTL_R8(hw, Config5) & ~BIT_0);
504619f6ebcSHoward Wang 		}
505619f6ebcSHoward Wang 		rtl_disable_cfg9346_write(hw);
506619f6ebcSHoward Wang 		break;
507619f6ebcSHoward Wang 	}
508619f6ebcSHoward Wang }
509619f6ebcSHoward Wang 
510619f6ebcSHoward Wang static void
511619f6ebcSHoward Wang rtl_disable_l1_timeout(struct rtl_hw *hw)
512619f6ebcSHoward Wang {
513619f6ebcSHoward Wang 	rtl_csi_write(hw, 0x890, rtl_csi_read(hw, 0x890) & ~BIT_0);
514619f6ebcSHoward Wang }
515619f6ebcSHoward Wang 
516619f6ebcSHoward Wang static void
517619f6ebcSHoward Wang rtl_disable_eee_plus(struct rtl_hw *hw)
518619f6ebcSHoward Wang {
519619f6ebcSHoward Wang 	switch (hw->mcfg) {
520619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
521619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
522619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE080, rtl_mac_ocp_read(hw, 0xE080) & ~BIT_1);
523619f6ebcSHoward Wang 		break;
524619f6ebcSHoward Wang 
525619f6ebcSHoward Wang 	default:
526619f6ebcSHoward Wang 		/* Not support EEEPlus */
527619f6ebcSHoward Wang 		break;
528619f6ebcSHoward Wang 	}
529619f6ebcSHoward Wang }
530619f6ebcSHoward Wang 
531619f6ebcSHoward Wang static void
532619f6ebcSHoward Wang rtl_hw_clear_timer_int(struct rtl_hw *hw)
533619f6ebcSHoward Wang {
534619f6ebcSHoward Wang 	switch (hw->mcfg) {
535619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
536619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
537619f6ebcSHoward Wang 		RTL_W32(hw, TIMER_INT0_8125, 0x0000);
538619f6ebcSHoward Wang 		RTL_W32(hw, TIMER_INT1_8125, 0x0000);
539619f6ebcSHoward Wang 		RTL_W32(hw, TIMER_INT2_8125, 0x0000);
540619f6ebcSHoward Wang 		RTL_W32(hw, TIMER_INT3_8125, 0x0000);
541619f6ebcSHoward Wang 		break;
542619f6ebcSHoward Wang 	}
543619f6ebcSHoward Wang }
544619f6ebcSHoward Wang 
545619f6ebcSHoward Wang static void
546619f6ebcSHoward Wang rtl_hw_clear_int_miti(struct rtl_hw *hw)
547619f6ebcSHoward Wang {
548619f6ebcSHoward Wang 	int i;
549619f6ebcSHoward Wang 
550619f6ebcSHoward Wang 	switch (hw->HwSuppIntMitiVer) {
551619f6ebcSHoward Wang 	case 3:
552619f6ebcSHoward Wang 	case 6:
553619f6ebcSHoward Wang 		/* IntMITI_0-IntMITI_31 */
554619f6ebcSHoward Wang 		for (i = 0xA00; i < 0xB00; i += 4)
555619f6ebcSHoward Wang 			RTL_W32(hw, i, 0x0000);
556619f6ebcSHoward Wang 		break;
557619f6ebcSHoward Wang 	case 4:
558619f6ebcSHoward Wang 	case 5:
559619f6ebcSHoward Wang 		/* IntMITI_0-IntMITI_15 */
560619f6ebcSHoward Wang 		for (i = 0xA00; i < 0xA80; i += 4)
561619f6ebcSHoward Wang 			RTL_W32(hw, i, 0x0000);
562619f6ebcSHoward Wang 
563619f6ebcSHoward Wang 		if (hw->HwSuppIntMitiVer == 5)
564619f6ebcSHoward Wang 			RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) &
565619f6ebcSHoward Wang 			       ~(INT_CFG0_TIMEOUT0_BYPASS_8125 |
566619f6ebcSHoward Wang 			       INT_CFG0_MITIGATION_BYPASS_8125 |
567619f6ebcSHoward Wang 			       INT_CFG0_RDU_BYPASS_8126));
568619f6ebcSHoward Wang 		else
569619f6ebcSHoward Wang 			RTL_W8(hw, INT_CFG0_8125, RTL_R8(hw, INT_CFG0_8125) &
570619f6ebcSHoward Wang 			       ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125));
571619f6ebcSHoward Wang 
572619f6ebcSHoward Wang 		RTL_W16(hw, INT_CFG1_8125, 0x0000);
573619f6ebcSHoward Wang 		break;
574619f6ebcSHoward Wang 	}
575619f6ebcSHoward Wang }
576619f6ebcSHoward Wang 
577619f6ebcSHoward Wang void
578619f6ebcSHoward Wang rtl_hw_config(struct rtl_hw *hw)
579619f6ebcSHoward Wang {
580619f6ebcSHoward Wang 	u32 mac_ocp_data;
581619f6ebcSHoward Wang 
582619f6ebcSHoward Wang 	/* Set RxConfig to default */
583619f6ebcSHoward Wang 	RTL_W32(hw, RxConfig, (RX_DMA_BURST_unlimited << RxCfgDMAShift));
584619f6ebcSHoward Wang 
585619f6ebcSHoward Wang 	rtl_nic_reset(hw);
586619f6ebcSHoward Wang 
587619f6ebcSHoward Wang 	rtl_enable_cfg9346_write(hw);
588619f6ebcSHoward Wang 
589619f6ebcSHoward Wang 	/* Disable aspm clkreq internal */
590619f6ebcSHoward Wang 	switch (hw->mcfg) {
591619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
592619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
593619f6ebcSHoward Wang 		rtl_enable_force_clkreq(hw, 0);
594619f6ebcSHoward Wang 		rtl_enable_aspm_clkreq_lock(hw, 0);
595619f6ebcSHoward Wang 		break;
596619f6ebcSHoward Wang 	}
597619f6ebcSHoward Wang 
598619f6ebcSHoward Wang 	/* Disable magic packet */
599619f6ebcSHoward Wang 	switch (hw->mcfg) {
600619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
601619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
602619f6ebcSHoward Wang 		mac_ocp_data = 0;
603619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC0B6, mac_ocp_data);
604619f6ebcSHoward Wang 		break;
605619f6ebcSHoward Wang 	}
606619f6ebcSHoward Wang 
607619f6ebcSHoward Wang 	/* Set DMA burst size and interframe gap time */
608619f6ebcSHoward Wang 	RTL_W32(hw, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) |
609619f6ebcSHoward Wang 		(InterFrameGap << TxInterFrameGapShift));
610619f6ebcSHoward Wang 
611619f6ebcSHoward Wang 	if (hw->EnableTxNoClose)
612619f6ebcSHoward Wang 		RTL_W32(hw, TxConfig, (RTL_R32(hw, TxConfig) | BIT_6));
613619f6ebcSHoward Wang 
614619f6ebcSHoward Wang 	/* TCAM */
615619f6ebcSHoward Wang 	switch (hw->mcfg) {
616619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_53:
617619f6ebcSHoward Wang 		RTL_W16(hw, 0x382, 0x221B);
618619f6ebcSHoward Wang 		break;
619619f6ebcSHoward Wang 	}
620619f6ebcSHoward Wang 
621619f6ebcSHoward Wang 	switch (hw->mcfg) {
622619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
623619f6ebcSHoward Wang 		rtl_disable_l1_timeout(hw);
624619f6ebcSHoward Wang 		break;
625619f6ebcSHoward Wang 	}
626619f6ebcSHoward Wang 
627619f6ebcSHoward Wang 	switch (hw->mcfg) {
628619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
629619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
630619f6ebcSHoward Wang 
631619f6ebcSHoward Wang 		/* RSS_control_0 */
632619f6ebcSHoward Wang 		RTL_W32(hw, RSS_CTRL_8125, 0x00);
633619f6ebcSHoward Wang 
634619f6ebcSHoward Wang 		/* VMQ_control */
635619f6ebcSHoward Wang 		RTL_W16(hw, Q_NUM_CTRL_8125, 0x0000);
636619f6ebcSHoward Wang 
637619f6ebcSHoward Wang 		/* Disable speed down */
638619f6ebcSHoward Wang 		RTL_W8(hw, Config1, RTL_R8(hw, Config1) & ~0x10);
639619f6ebcSHoward Wang 
640619f6ebcSHoward Wang 		/* CRC disable set */
641619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC140, 0xFFFF);
642619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC142, 0xFFFF);
643619f6ebcSHoward Wang 
644619f6ebcSHoward Wang 		/* New TX desc format */
645619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB58);
646619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
647619f6ebcSHoward Wang 			mac_ocp_data &= ~(BIT_0 | BIT_1);
648619f6ebcSHoward Wang 		mac_ocp_data |= BIT_0;
649619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xEB58, mac_ocp_data);
650619f6ebcSHoward Wang 
651619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
652619f6ebcSHoward Wang 			RTL_W8(hw, 0xD8, RTL_R8(hw, 0xD8) & ~BIT_1);
653619f6ebcSHoward Wang 
654619f6ebcSHoward Wang 		/*
655619f6ebcSHoward Wang 		 * MTPS
656619f6ebcSHoward Wang 		 * 15-8 maximum tx use credit number
657619f6ebcSHoward Wang 		 * 7-0 reserved for pcie product line
658619f6ebcSHoward Wang 		 */
659619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xE614);
660619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8);
661619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_50 || hw->mcfg == CFG_METHOD_51 ||
662619f6ebcSHoward Wang 		    hw->mcfg == CFG_METHOD_53)
663619f6ebcSHoward Wang 			mac_ocp_data |= ((2 & 0x07) << 8);
664619f6ebcSHoward Wang 		else if (hw->mcfg == CFG_METHOD_69 || hw->mcfg == CFG_METHOD_70 ||
665619f6ebcSHoward Wang 			 hw->mcfg == CFG_METHOD_71)
666619f6ebcSHoward Wang 			mac_ocp_data |= ((4 & 0x07) << 8);
667619f6ebcSHoward Wang 		else
668619f6ebcSHoward Wang 			mac_ocp_data |= ((3 & 0x07) << 8);
669619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE614, mac_ocp_data);
670619f6ebcSHoward Wang 
671619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xE63E);
672619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_5 | BIT_4);
673619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
674619f6ebcSHoward Wang 		    hw->mcfg == CFG_METHOD_52 || hw->mcfg == CFG_METHOD_69 ||
675619f6ebcSHoward Wang 		    hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
676619f6ebcSHoward Wang 			mac_ocp_data |= ((0x02 & 0x03) << 4);
677619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE63E, mac_ocp_data);
678619f6ebcSHoward Wang 
679619f6ebcSHoward Wang 		/*
680619f6ebcSHoward Wang 		 * FTR_MCU_CTRL
681619f6ebcSHoward Wang 		 * 3-2 txpla packet valid start
682619f6ebcSHoward Wang 		 */
683619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xC0B4);
684619f6ebcSHoward Wang 		mac_ocp_data &= ~BIT_0;
685619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
686619f6ebcSHoward Wang 		mac_ocp_data |= BIT_0;
687619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
688619f6ebcSHoward Wang 
689619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xC0B4);
690619f6ebcSHoward Wang 		mac_ocp_data |= (BIT_3 | BIT_2);
691619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xC0B4, mac_ocp_data);
692619f6ebcSHoward Wang 
693619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB6A);
694619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 |
695619f6ebcSHoward Wang 				  BIT_0);
696619f6ebcSHoward Wang 		mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0);
697619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xEB6A, mac_ocp_data);
698619f6ebcSHoward Wang 
699619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xEB50);
700619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5);
701619f6ebcSHoward Wang 		mac_ocp_data |= BIT_6;
702619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xEB50, mac_ocp_data);
703619f6ebcSHoward Wang 
704619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xE056);
705619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4);
706619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE056, mac_ocp_data);
707619f6ebcSHoward Wang 
708619f6ebcSHoward Wang 		/* EEE_CR */
709619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xE040);
710619f6ebcSHoward Wang 		mac_ocp_data &= ~BIT_12;
711619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE040, mac_ocp_data);
712619f6ebcSHoward Wang 
713619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xEA1C);
714619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_1 | BIT_0);
715619f6ebcSHoward Wang 		mac_ocp_data |= BIT_0;
716619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xEA1C, mac_ocp_data);
717619f6ebcSHoward Wang 
718619f6ebcSHoward Wang 		switch (hw->mcfg) {
719619f6ebcSHoward Wang 		case CFG_METHOD_48:
720619f6ebcSHoward Wang 		case CFG_METHOD_49:
721619f6ebcSHoward Wang 		case CFG_METHOD_52:
722619f6ebcSHoward Wang 		case CFG_METHOD_54:
723619f6ebcSHoward Wang 		case CFG_METHOD_55:
724619f6ebcSHoward Wang 			rtl8125_oob_mutex_lock(hw);
725619f6ebcSHoward Wang 			break;
726619f6ebcSHoward Wang 		}
727619f6ebcSHoward Wang 
728619f6ebcSHoward Wang 		/* MAC_PWRDWN_CR0 */
729619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE0C0, 0x4000);
730619f6ebcSHoward Wang 
731619f6ebcSHoward Wang 		rtl_set_mac_ocp_bit(hw, 0xE052, (BIT_6 | BIT_5));
732619f6ebcSHoward Wang 		rtl_clear_mac_ocp_bit(hw, 0xE052, (BIT_3 | BIT_7));
733619f6ebcSHoward Wang 
734619f6ebcSHoward Wang 		switch (hw->mcfg) {
735619f6ebcSHoward Wang 		case CFG_METHOD_48:
736619f6ebcSHoward Wang 		case CFG_METHOD_49:
737619f6ebcSHoward Wang 		case CFG_METHOD_52:
738619f6ebcSHoward Wang 		case CFG_METHOD_54:
739619f6ebcSHoward Wang 		case CFG_METHOD_55:
740619f6ebcSHoward Wang 			rtl8125_oob_mutex_unlock(hw);
741619f6ebcSHoward Wang 			break;
742619f6ebcSHoward Wang 		}
743619f6ebcSHoward Wang 
744619f6ebcSHoward Wang 		/*
745619f6ebcSHoward Wang 		 * DMY_PWR_REG_0
746619f6ebcSHoward Wang 		 * (1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask
747619f6ebcSHoward Wang 		 */
748619f6ebcSHoward Wang 		rtl_set_mac_ocp_bit(hw, 0xC0AC,
749619f6ebcSHoward Wang 				    (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12));
750619f6ebcSHoward Wang 
751619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xD430);
752619f6ebcSHoward Wang 		mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 |
753619f6ebcSHoward Wang 				  BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0);
754619f6ebcSHoward Wang 		mac_ocp_data |= 0x45F;
755619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xD430, mac_ocp_data);
756619f6ebcSHoward Wang 
757619f6ebcSHoward Wang 		if (!hw->DASH)
758619f6ebcSHoward Wang 			RTL_W8(hw, 0xD0, RTL_R8(hw, 0xD0) | BIT_6 | BIT_7);
759619f6ebcSHoward Wang 		else
760619f6ebcSHoward Wang 			RTL_W8(hw, 0xD0, RTL_R8(hw, 0xD0) & ~(BIT_6 | BIT_7));
761619f6ebcSHoward Wang 
762619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
763619f6ebcSHoward Wang 		    hw->mcfg == CFG_METHOD_52)
764619f6ebcSHoward Wang 			RTL_W8(hw, MCUCmd_reg, RTL_R8(hw, MCUCmd_reg) | BIT_0);
765619f6ebcSHoward Wang 
766619f6ebcSHoward Wang 		rtl_disable_eee_plus(hw);
767619f6ebcSHoward Wang 
768619f6ebcSHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xEA1C);
769619f6ebcSHoward Wang 		mac_ocp_data &= ~BIT_2;
770619f6ebcSHoward Wang 		if (hw->mcfg == CFG_METHOD_70 || hw->mcfg == CFG_METHOD_71)
771619f6ebcSHoward Wang 			mac_ocp_data &= ~(BIT_9 | BIT_8);
772619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xEA1C, mac_ocp_data);
773619f6ebcSHoward Wang 
774619f6ebcSHoward Wang 		/* Clear TCAM entries */
775619f6ebcSHoward Wang 		rtl_set_mac_ocp_bit(hw, 0xEB54, BIT_0);
776619f6ebcSHoward Wang 		rte_delay_us(1);
777619f6ebcSHoward Wang 		rtl_clear_mac_ocp_bit(hw, 0xEB54, BIT_0);
778619f6ebcSHoward Wang 
779619f6ebcSHoward Wang 		RTL_W16(hw, 0x1880, RTL_R16(hw, 0x1880) & ~(BIT_4 | BIT_5));
780619f6ebcSHoward Wang 
781619f6ebcSHoward Wang 		switch (hw->mcfg) {
782619f6ebcSHoward Wang 		case CFG_METHOD_54 ... CFG_METHOD_57:
783619f6ebcSHoward Wang 			RTL_W8(hw, 0xd8, RTL_R8(hw, 0xd8) & ~EnableRxDescV4_0);
784619f6ebcSHoward Wang 			break;
785619f6ebcSHoward Wang 		}
786619f6ebcSHoward Wang 	}
787619f6ebcSHoward Wang 
788619f6ebcSHoward Wang 	/* Other hw parameters */
789619f6ebcSHoward Wang 	rtl_hw_clear_timer_int(hw);
790619f6ebcSHoward Wang 
791619f6ebcSHoward Wang 	rtl_hw_clear_int_miti(hw);
792619f6ebcSHoward Wang 
793619f6ebcSHoward Wang 	switch (hw->mcfg) {
794619f6ebcSHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
795619f6ebcSHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
796619f6ebcSHoward Wang 		rtl_mac_ocp_write(hw, 0xE098, 0xC302);
797619f6ebcSHoward Wang 		break;
798619f6ebcSHoward Wang 	}
799619f6ebcSHoward Wang 
800619f6ebcSHoward Wang 	rtl_disable_cfg9346_write(hw);
801619f6ebcSHoward Wang 
802619f6ebcSHoward Wang 	rte_delay_us(10);
803619f6ebcSHoward Wang }
8048e852260SHoward Wang 
8058e852260SHoward Wang int
8068e852260SHoward Wang rtl_set_hw_ops(struct rtl_hw *hw)
8078e852260SHoward Wang {
8088e852260SHoward Wang 	switch (hw->mcfg) {
8098e852260SHoward Wang 	/* 8125A */
8108e852260SHoward Wang 	case CFG_METHOD_48:
8118e852260SHoward Wang 	case CFG_METHOD_49:
8128e852260SHoward Wang 		hw->hw_ops = rtl8125a_ops;
8138e852260SHoward Wang 		return 0;
8148e852260SHoward Wang 	/* 8125B */
8158e852260SHoward Wang 	case CFG_METHOD_50:
8168e852260SHoward Wang 	case CFG_METHOD_51:
8178e852260SHoward Wang 		hw->hw_ops = rtl8125b_ops;
8188e852260SHoward Wang 		return 0;
8198e852260SHoward Wang 	/* 8125BP */
8208e852260SHoward Wang 	case CFG_METHOD_54:
8218e852260SHoward Wang 	case CFG_METHOD_55:
8228e852260SHoward Wang 		hw->hw_ops = rtl8125bp_ops;
8238e852260SHoward Wang 		return 0;
8248e852260SHoward Wang 	/* 8125D */
8258e852260SHoward Wang 	case CFG_METHOD_56:
8268e852260SHoward Wang 	case CFG_METHOD_57:
8278e852260SHoward Wang 		hw->hw_ops = rtl8125d_ops;
8288e852260SHoward Wang 		return 0;
8298e852260SHoward Wang 	/* 8126A */
8308e852260SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
8318e852260SHoward Wang 		hw->hw_ops = rtl8126a_ops;
8328e852260SHoward Wang 		return 0;
8338e852260SHoward Wang 	default:
8348e852260SHoward Wang 		return -ENOTSUP;
8358e852260SHoward Wang 	}
8368e852260SHoward Wang }
8378e852260SHoward Wang 
8388e852260SHoward Wang void
8398e852260SHoward Wang rtl_hw_disable_mac_mcu_bps(struct rtl_hw *hw)
8408e852260SHoward Wang {
8418e852260SHoward Wang 	u16 reg_addr;
8428e852260SHoward Wang 
8438e852260SHoward Wang 	rtl_enable_aspm_clkreq_lock(hw, 0);
8448e852260SHoward Wang 
8458e852260SHoward Wang 	switch (hw->mcfg) {
8468e852260SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
8478e852260SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
8488e852260SHoward Wang 		rtl_mac_ocp_write(hw, 0xFC48, 0x0000);
8498e852260SHoward Wang 		break;
8508e852260SHoward Wang 	}
8518e852260SHoward Wang 
8528e852260SHoward Wang 	switch (hw->mcfg) {
8538e852260SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
8548e852260SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
8558e852260SHoward Wang 		for (reg_addr = 0xFC28; reg_addr < 0xFC48; reg_addr += 2)
8568e852260SHoward Wang 			rtl_mac_ocp_write(hw, reg_addr, 0x0000);
8578e852260SHoward Wang 
8588e852260SHoward Wang 		rte_delay_ms(3);
8598e852260SHoward Wang 
8608e852260SHoward Wang 		rtl_mac_ocp_write(hw, 0xFC26, 0x0000);
8618e852260SHoward Wang 		break;
8628e852260SHoward Wang 	}
8638e852260SHoward Wang }
8648e852260SHoward Wang 
8658e852260SHoward Wang static void
8668e852260SHoward Wang rtl_switch_mac_mcu_ram_code_page(struct rtl_hw *hw, u16 page)
8678e852260SHoward Wang {
8688e852260SHoward Wang 	u16 tmp_ushort;
8698e852260SHoward Wang 
8708e852260SHoward Wang 	page &= (BIT_1 | BIT_0);
8718e852260SHoward Wang 	tmp_ushort = rtl_mac_ocp_read(hw, 0xE446);
8728e852260SHoward Wang 	tmp_ushort &= ~(BIT_1 | BIT_0);
8738e852260SHoward Wang 	tmp_ushort |= page;
8748e852260SHoward Wang 	rtl_mac_ocp_write(hw, 0xE446, tmp_ushort);
8758e852260SHoward Wang }
8768e852260SHoward Wang 
8778e852260SHoward Wang static void
8788e852260SHoward Wang _rtl_write_mac_mcu_ram_code(struct rtl_hw *hw, const u16 *entry, u16 entry_cnt)
8798e852260SHoward Wang {
8808e852260SHoward Wang 	u16 i;
8818e852260SHoward Wang 
8828e852260SHoward Wang 	for (i = 0; i < entry_cnt; i++)
8838e852260SHoward Wang 		rtl_mac_ocp_write(hw, 0xF800 + i * 2, entry[i]);
8848e852260SHoward Wang }
8858e852260SHoward Wang 
8868e852260SHoward Wang static void
8878e852260SHoward Wang _rtl_write_mac_mcu_ram_code_with_page(struct rtl_hw *hw, const u16 *entry,
8888e852260SHoward Wang 				      u16 entry_cnt, u16 page_size)
8898e852260SHoward Wang {
8908e852260SHoward Wang 	u16 i;
8918e852260SHoward Wang 	u16 offset;
8928e852260SHoward Wang 	u16 page;
8938e852260SHoward Wang 
8948e852260SHoward Wang 	if (page_size == 0)
8958e852260SHoward Wang 		return;
8968e852260SHoward Wang 
8978e852260SHoward Wang 	for (i = 0; i < entry_cnt; i++) {
8988e852260SHoward Wang 		offset = i % page_size;
8998e852260SHoward Wang 		if (offset == 0) {
9008e852260SHoward Wang 			page = (i / page_size);
9018e852260SHoward Wang 			rtl_switch_mac_mcu_ram_code_page(hw, page);
9028e852260SHoward Wang 		}
9038e852260SHoward Wang 		rtl_mac_ocp_write(hw, 0xF800 + offset * 2, entry[i]);
9048e852260SHoward Wang 	}
9058e852260SHoward Wang }
9068e852260SHoward Wang 
9078e852260SHoward Wang void
9088e852260SHoward Wang rtl_write_mac_mcu_ram_code(struct rtl_hw *hw, const u16 *entry, u16 entry_cnt)
9098e852260SHoward Wang {
9108e852260SHoward Wang 	if (HW_SUPPORT_MAC_MCU(hw) == FALSE)
9118e852260SHoward Wang 		return;
9128e852260SHoward Wang 	if (entry == NULL || entry_cnt == 0)
9138e852260SHoward Wang 		return;
9148e852260SHoward Wang 
9158e852260SHoward Wang 	if (hw->MacMcuPageSize > 0)
9168e852260SHoward Wang 		_rtl_write_mac_mcu_ram_code_with_page(hw, entry, entry_cnt,
9178e852260SHoward Wang 						      hw->MacMcuPageSize);
9188e852260SHoward Wang 	else
9198e852260SHoward Wang 		_rtl_write_mac_mcu_ram_code(hw, entry, entry_cnt);
9208e852260SHoward Wang }
9217d502791SHoward Wang 
9227d502791SHoward Wang bool
9237d502791SHoward Wang rtl_is_speed_mode_valid(u32 speed)
9247d502791SHoward Wang {
9257d502791SHoward Wang 	switch (speed) {
9267d502791SHoward Wang 	case SPEED_5000:
9277d502791SHoward Wang 	case SPEED_2500:
9287d502791SHoward Wang 	case SPEED_1000:
9297d502791SHoward Wang 	case SPEED_100:
9307d502791SHoward Wang 	case SPEED_10:
9317d502791SHoward Wang 		return true;
9327d502791SHoward Wang 	default:
9337d502791SHoward Wang 		return false;
9347d502791SHoward Wang 	}
9357d502791SHoward Wang }
9367d502791SHoward Wang 
9377d502791SHoward Wang static bool
9387d502791SHoward Wang rtl_is_duplex_mode_valid(u8 duplex)
9397d502791SHoward Wang {
9407d502791SHoward Wang 	switch (duplex) {
9417d502791SHoward Wang 	case DUPLEX_FULL:
9427d502791SHoward Wang 	case DUPLEX_HALF:
9437d502791SHoward Wang 		return true;
9447d502791SHoward Wang 	default:
9457d502791SHoward Wang 		return false;
9467d502791SHoward Wang 	}
9477d502791SHoward Wang }
9487d502791SHoward Wang 
9497d502791SHoward Wang static bool
9507d502791SHoward Wang rtl_is_autoneg_mode_valid(u32 autoneg)
9517d502791SHoward Wang {
9527d502791SHoward Wang 	switch (autoneg) {
9537d502791SHoward Wang 	case AUTONEG_ENABLE:
9547d502791SHoward Wang 	case AUTONEG_DISABLE:
9557d502791SHoward Wang 		return true;
9567d502791SHoward Wang 	default:
9577d502791SHoward Wang 		return false;
9587d502791SHoward Wang 	}
9597d502791SHoward Wang }
9607d502791SHoward Wang 
961f7327670SHoward Wang void
9627d502791SHoward Wang rtl_set_link_option(struct rtl_hw *hw, u8 autoneg, u32 speed, u8 duplex,
9637d502791SHoward Wang 		    enum rtl_fc_mode fc)
9647d502791SHoward Wang {
9657d502791SHoward Wang 	u64 adv;
9667d502791SHoward Wang 
9677d502791SHoward Wang 	if (!rtl_is_speed_mode_valid(speed))
9687d502791SHoward Wang 		speed = SPEED_5000;
9697d502791SHoward Wang 
9707d502791SHoward Wang 	if (!rtl_is_duplex_mode_valid(duplex))
9717d502791SHoward Wang 		duplex = DUPLEX_FULL;
9727d502791SHoward Wang 
9737d502791SHoward Wang 	if (!rtl_is_autoneg_mode_valid(autoneg))
9747d502791SHoward Wang 		autoneg = AUTONEG_ENABLE;
9757d502791SHoward Wang 
9767d502791SHoward Wang 	speed = RTE_MIN(speed, hw->HwSuppMaxPhyLinkSpeed);
9777d502791SHoward Wang 
9787d502791SHoward Wang 	adv = 0;
9797d502791SHoward Wang 	switch (speed) {
9807d502791SHoward Wang 	case SPEED_5000:
9817d502791SHoward Wang 		adv |= ADVERTISE_5000_FULL;
9827d502791SHoward Wang 	/* Fall through */
9837d502791SHoward Wang 	case SPEED_2500:
9847d502791SHoward Wang 		adv |= ADVERTISE_2500_FULL;
9857d502791SHoward Wang 	/* Fall through */
9867d502791SHoward Wang 	default:
9877d502791SHoward Wang 		adv |= (ADVERTISE_10_HALF | ADVERTISE_10_FULL |
9887d502791SHoward Wang 			ADVERTISE_100_HALF | ADVERTISE_100_FULL |
9897d502791SHoward Wang 			ADVERTISE_1000_HALF | ADVERTISE_1000_FULL);
9907d502791SHoward Wang 		break;
9917d502791SHoward Wang 	}
9927d502791SHoward Wang 
9937d502791SHoward Wang 	hw->autoneg = autoneg;
9947d502791SHoward Wang 	hw->speed = speed;
9957d502791SHoward Wang 	hw->duplex = duplex;
9967d502791SHoward Wang 	hw->advertising = adv;
9977d502791SHoward Wang 	hw->fcpause = fc;
9987d502791SHoward Wang }
9997d502791SHoward Wang 
10007d502791SHoward Wang static void
10017d502791SHoward Wang rtl_init_software_variable(struct rtl_hw *hw)
10027d502791SHoward Wang {
10037d502791SHoward Wang 	int tx_no_close_enable = 1;
10047d502791SHoward Wang 	unsigned int speed_mode = SPEED_5000;
10057d502791SHoward Wang 	unsigned int duplex_mode = DUPLEX_FULL;
10067d502791SHoward Wang 	unsigned int autoneg_mode = AUTONEG_ENABLE;
10077d502791SHoward Wang 	u8 tmp;
10087d502791SHoward Wang 
10097d502791SHoward Wang 	switch (hw->mcfg) {
10107d502791SHoward Wang 	case CFG_METHOD_48:
10117d502791SHoward Wang 	case CFG_METHOD_49:
10127d502791SHoward Wang 		tmp = (u8)rtl_mac_ocp_read(hw, 0xD006);
10137d502791SHoward Wang 		if (tmp == 0x02 || tmp == 0x04)
10147d502791SHoward Wang 			hw->HwSuppDashVer = 2;
10157d502791SHoward Wang 		break;
10167d502791SHoward Wang 	case CFG_METHOD_54:
10177d502791SHoward Wang 	case CFG_METHOD_55:
10187d502791SHoward Wang 		hw->HwSuppDashVer = 4;
10197d502791SHoward Wang 		break;
10207d502791SHoward Wang 	default:
10217d502791SHoward Wang 		hw->HwSuppDashVer = 0;
10227d502791SHoward Wang 		break;
10237d502791SHoward Wang 	}
10247d502791SHoward Wang 
10257d502791SHoward Wang 	switch (hw->mcfg) {
10267d502791SHoward Wang 	case CFG_METHOD_48:
10277d502791SHoward Wang 	case CFG_METHOD_49:
10287d502791SHoward Wang 		if (HW_DASH_SUPPORT_DASH(hw))
10297d502791SHoward Wang 			hw->HwSuppOcpChannelVer = 2;
10307d502791SHoward Wang 		break;
10317d502791SHoward Wang 	case CFG_METHOD_54:
10327d502791SHoward Wang 	case CFG_METHOD_55:
10337d502791SHoward Wang 		hw->HwSuppOcpChannelVer = 2;
10347d502791SHoward Wang 		break;
10357d502791SHoward Wang 	}
10367d502791SHoward Wang 
10377d502791SHoward Wang 	hw->AllowAccessDashOcp = rtl_is_allow_access_dash_ocp(hw);
10387d502791SHoward Wang 
10397d502791SHoward Wang 	if (HW_DASH_SUPPORT_DASH(hw) && rtl_check_dash(hw))
10407d502791SHoward Wang 		hw->DASH = 1;
10417d502791SHoward Wang 	else
10427d502791SHoward Wang 		hw->DASH = 0;
10437d502791SHoward Wang 
10447d502791SHoward Wang 	if (HW_DASH_SUPPORT_TYPE_2(hw))
10457d502791SHoward Wang 		hw->cmac_ioaddr = hw->mmio_addr;
10467d502791SHoward Wang 
10477d502791SHoward Wang 	switch (hw->mcfg) {
10487d502791SHoward Wang 	case CFG_METHOD_48:
10497d502791SHoward Wang 	case CFG_METHOD_49:
10507d502791SHoward Wang 		hw->chipset_name = RTL8125A;
10517d502791SHoward Wang 		break;
10527d502791SHoward Wang 	case CFG_METHOD_50:
10537d502791SHoward Wang 	case CFG_METHOD_51:
10547d502791SHoward Wang 		hw->chipset_name = RTL8125B;
10557d502791SHoward Wang 		break;
10567d502791SHoward Wang 	case CFG_METHOD_52:
10577d502791SHoward Wang 	case CFG_METHOD_53:
10587d502791SHoward Wang 		hw->chipset_name = RTL8168KB;
10597d502791SHoward Wang 		break;
10607d502791SHoward Wang 	case CFG_METHOD_54:
10617d502791SHoward Wang 	case CFG_METHOD_55:
10627d502791SHoward Wang 		hw->chipset_name = RTL8125BP;
10637d502791SHoward Wang 		break;
10647d502791SHoward Wang 	case CFG_METHOD_56:
10657d502791SHoward Wang 	case CFG_METHOD_57:
10667d502791SHoward Wang 		hw->chipset_name = RTL8125D;
10677d502791SHoward Wang 		break;
10687d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
10697d502791SHoward Wang 		hw->chipset_name = RTL8126A;
10707d502791SHoward Wang 		break;
10717d502791SHoward Wang 	default:
10727d502791SHoward Wang 		hw->chipset_name = UNKNOWN;
10737d502791SHoward Wang 		break;
10747d502791SHoward Wang 	}
10757d502791SHoward Wang 
10767d502791SHoward Wang 	switch (hw->mcfg) {
10777d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
10787d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
10797d502791SHoward Wang 		hw->HwSuppNowIsOobVer = 1;
10807d502791SHoward Wang 	}
10817d502791SHoward Wang 
10827d502791SHoward Wang 	switch (hw->mcfg) {
10837d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
10847d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
10857d502791SHoward Wang 		hw->HwSuppCheckPhyDisableModeVer = 3;
10867d502791SHoward Wang 	}
10877d502791SHoward Wang 
10887d502791SHoward Wang 	switch (hw->mcfg) {
10897d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_51:
10907d502791SHoward Wang 	case CFG_METHOD_54 ... CFG_METHOD_57:
1091f7327670SHoward Wang 		hw->HwSuppMaxPhyLinkSpeed = SPEED_2500;
10927d502791SHoward Wang 		break;
10937d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
1094f7327670SHoward Wang 		hw->HwSuppMaxPhyLinkSpeed = SPEED_5000;
10957d502791SHoward Wang 		break;
10967d502791SHoward Wang 	default:
1097f7327670SHoward Wang 		hw->HwSuppMaxPhyLinkSpeed = SPEED_1000;
10987d502791SHoward Wang 		break;
10997d502791SHoward Wang 	}
11007d502791SHoward Wang 
11017d502791SHoward Wang 	switch (hw->mcfg) {
11027d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_53:
11037d502791SHoward Wang 		hw->HwSuppTxNoCloseVer = 3;
11047d502791SHoward Wang 		break;
11057d502791SHoward Wang 	case CFG_METHOD_54 ... CFG_METHOD_57:
11067d502791SHoward Wang 		hw->HwSuppTxNoCloseVer = 6;
11077d502791SHoward Wang 		break;
11087d502791SHoward Wang 	case CFG_METHOD_69:
11097d502791SHoward Wang 		hw->HwSuppTxNoCloseVer = 4;
11107d502791SHoward Wang 		break;
11117d502791SHoward Wang 	case CFG_METHOD_70:
11127d502791SHoward Wang 	case CFG_METHOD_71:
11137d502791SHoward Wang 		hw->HwSuppTxNoCloseVer = 5;
11147d502791SHoward Wang 		break;
11157d502791SHoward Wang 	}
11167d502791SHoward Wang 
11177d502791SHoward Wang 	switch (hw->HwSuppTxNoCloseVer) {
11187d502791SHoward Wang 	case 5:
11197d502791SHoward Wang 	case 6:
11207d502791SHoward Wang 		hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V4;
11217d502791SHoward Wang 		break;
11227d502791SHoward Wang 	case 4:
11237d502791SHoward Wang 		hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V3;
11247d502791SHoward Wang 		break;
11257d502791SHoward Wang 	case 3:
11267d502791SHoward Wang 		hw->MaxTxDescPtrMask = MAX_TX_NO_CLOSE_DESC_PTR_MASK_V2;
11277d502791SHoward Wang 		break;
11287d502791SHoward Wang 	default:
11297d502791SHoward Wang 		tx_no_close_enable = 0;
11307d502791SHoward Wang 		break;
11317d502791SHoward Wang 	}
11327d502791SHoward Wang 
11337d502791SHoward Wang 	if (hw->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1)
11347d502791SHoward Wang 		hw->EnableTxNoClose = TRUE;
11357d502791SHoward Wang 
11367d502791SHoward Wang 	switch (hw->HwSuppTxNoCloseVer) {
11377d502791SHoward Wang 	case 4:
11387d502791SHoward Wang 	case 5:
11397d502791SHoward Wang 		hw->hw_clo_ptr_reg = HW_CLO_PTR0_8126;
11407d502791SHoward Wang 		hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8126;
11417d502791SHoward Wang 		break;
11427d502791SHoward Wang 	case 6:
11437d502791SHoward Wang 		hw->hw_clo_ptr_reg = HW_CLO_PTR0_8125BP;
11447d502791SHoward Wang 		hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8125BP;
11457d502791SHoward Wang 		break;
11467d502791SHoward Wang 	default:
11477d502791SHoward Wang 		hw->hw_clo_ptr_reg = HW_CLO_PTR0_8125;
11487d502791SHoward Wang 		hw->sw_tail_ptr_reg = SW_TAIL_PTR0_8125;
11497d502791SHoward Wang 		break;
11507d502791SHoward Wang 	}
11517d502791SHoward Wang 
11527d502791SHoward Wang 	switch (hw->mcfg) {
11537d502791SHoward Wang 	case CFG_METHOD_48:
11547d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_48;
11557d502791SHoward Wang 		break;
11567d502791SHoward Wang 	case CFG_METHOD_49:
11577d502791SHoward Wang 	case CFG_METHOD_52:
11587d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_49;
11597d502791SHoward Wang 		break;
11607d502791SHoward Wang 	case CFG_METHOD_50:
11617d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_50;
11627d502791SHoward Wang 		break;
11637d502791SHoward Wang 	case CFG_METHOD_51:
11647d502791SHoward Wang 	case CFG_METHOD_53:
11657d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_51;
11667d502791SHoward Wang 		break;
11677d502791SHoward Wang 	case CFG_METHOD_54:
11687d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_54;
11697d502791SHoward Wang 		break;
11707d502791SHoward Wang 	case CFG_METHOD_55:
11717d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_55;
11727d502791SHoward Wang 		break;
11737d502791SHoward Wang 	case CFG_METHOD_56:
11747d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_56;
11757d502791SHoward Wang 		break;
11767d502791SHoward Wang 	case CFG_METHOD_57:
11777d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_57;
11787d502791SHoward Wang 		break;
11797d502791SHoward Wang 	case CFG_METHOD_69:
11807d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_69;
11817d502791SHoward Wang 		break;
11827d502791SHoward Wang 	case CFG_METHOD_70:
11837d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_70;
11847d502791SHoward Wang 		break;
11857d502791SHoward Wang 	case CFG_METHOD_71:
11867d502791SHoward Wang 		hw->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_71;
11877d502791SHoward Wang 		break;
11887d502791SHoward Wang 	}
11897d502791SHoward Wang 
11907d502791SHoward Wang 	if (hw->HwIcVerUnknown) {
11917d502791SHoward Wang 		hw->NotWrRamCodeToMicroP = TRUE;
11927d502791SHoward Wang 		hw->NotWrMcuPatchCode = TRUE;
11937d502791SHoward Wang 	}
11947d502791SHoward Wang 
11957d502791SHoward Wang 	switch (hw->mcfg) {
11967d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
11977d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
11987d502791SHoward Wang 		hw->HwSuppMacMcuVer = 2;
11997d502791SHoward Wang 		break;
12007d502791SHoward Wang 	}
12017d502791SHoward Wang 
12027d502791SHoward Wang 	switch (hw->mcfg) {
12037d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
12047d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
12057d502791SHoward Wang 		hw->MacMcuPageSize = RTL_MAC_MCU_PAGE_SIZE;
12067d502791SHoward Wang 		break;
12077d502791SHoward Wang 	}
12087d502791SHoward Wang 
12097d502791SHoward Wang 	switch (hw->mcfg) {
12107d502791SHoward Wang 	case CFG_METHOD_49:
12117d502791SHoward Wang 	case CFG_METHOD_52:
12127d502791SHoward Wang 		if ((rtl_mac_ocp_read(hw, 0xD442) & BIT_5) &&
12137d502791SHoward Wang 		    (rtl_mdio_direct_read_phy_ocp(hw, 0xD068) & BIT_1))
12147d502791SHoward Wang 			hw->RequirePhyMdiSwapPatch = TRUE;
12157d502791SHoward Wang 		break;
12167d502791SHoward Wang 	}
12177d502791SHoward Wang 
12187d502791SHoward Wang 	switch (hw->mcfg) {
12197d502791SHoward Wang 	case CFG_METHOD_48:
12207d502791SHoward Wang 	case CFG_METHOD_49:
12217d502791SHoward Wang 	case CFG_METHOD_52:
12227d502791SHoward Wang 		hw->HwSuppIntMitiVer = 3;
12237d502791SHoward Wang 		break;
12247d502791SHoward Wang 	case CFG_METHOD_50:
12257d502791SHoward Wang 	case CFG_METHOD_51:
12267d502791SHoward Wang 	case CFG_METHOD_53:
12277d502791SHoward Wang 	case CFG_METHOD_69:
12287d502791SHoward Wang 		hw->HwSuppIntMitiVer = 4;
12297d502791SHoward Wang 		break;
12307d502791SHoward Wang 	case CFG_METHOD_54 ... CFG_METHOD_57:
12317d502791SHoward Wang 		hw->HwSuppIntMitiVer = 6;
12327d502791SHoward Wang 		break;
12337d502791SHoward Wang 	case CFG_METHOD_70:
12347d502791SHoward Wang 	case CFG_METHOD_71:
12357d502791SHoward Wang 		hw->HwSuppIntMitiVer = 5;
12367d502791SHoward Wang 		break;
12377d502791SHoward Wang 	}
12387d502791SHoward Wang 
12397d502791SHoward Wang 	rtl_set_link_option(hw, autoneg_mode, speed_mode, duplex_mode, rtl_fc_full);
12407d502791SHoward Wang 
12417d502791SHoward Wang 	switch (hw->mcfg) {
12427d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
12437d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
12447d502791SHoward Wang 		hw->mcu_pme_setting = rtl_mac_ocp_read(hw, 0xE00A);
12457d502791SHoward Wang 		break;
12467d502791SHoward Wang 	}
12477d502791SHoward Wang 
12487d502791SHoward Wang 	hw->mtu = RTL_DEFAULT_MTU;
12497d502791SHoward Wang }
12507d502791SHoward Wang 
12517d502791SHoward Wang static void
12527d502791SHoward Wang rtl_exit_realwow(struct rtl_hw *hw)
12537d502791SHoward Wang {
12547d502791SHoward Wang 	/* Disable realwow function */
12557d502791SHoward Wang 	switch (hw->mcfg) {
12567d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
12577d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
12587d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xC0BC, 0x00FF);
12597d502791SHoward Wang 		break;
12607d502791SHoward Wang 	}
12617d502791SHoward Wang }
12627d502791SHoward Wang 
12637d502791SHoward Wang static void
12647d502791SHoward Wang rtl_disable_now_is_oob(struct rtl_hw *hw)
12657d502791SHoward Wang {
12667d502791SHoward Wang 	if (hw->HwSuppNowIsOobVer == 1)
12677d502791SHoward Wang 		RTL_W8(hw, MCUCmd_reg, RTL_R8(hw, MCUCmd_reg) & ~Now_is_oob);
12687d502791SHoward Wang }
12697d502791SHoward Wang 
12707d502791SHoward Wang static void
12717d502791SHoward Wang rtl_wait_ll_share_fifo_ready(struct rtl_hw *hw)
12727d502791SHoward Wang {
12737d502791SHoward Wang 	int i;
12747d502791SHoward Wang 
12757d502791SHoward Wang 	for (i = 0; i < 10; i++) {
12767d502791SHoward Wang 		rte_delay_us(100);
12777d502791SHoward Wang 		if (RTL_R16(hw, 0xD2) & BIT_9)
12787d502791SHoward Wang 			break;
12797d502791SHoward Wang 	}
12807d502791SHoward Wang }
12817d502791SHoward Wang 
12827d502791SHoward Wang static void
12837d502791SHoward Wang rtl_exit_oob(struct rtl_hw *hw)
12847d502791SHoward Wang {
12857d502791SHoward Wang 	u16 data16;
12867d502791SHoward Wang 
12877d502791SHoward Wang 	rtl_disable_rx_packet_filter(hw);
12887d502791SHoward Wang 
1289*b574fb4cSHoward Wang 	if (HW_DASH_SUPPORT_DASH(hw)) {
1290*b574fb4cSHoward Wang 		rtl8125_driver_start(hw);
1291*b574fb4cSHoward Wang 		rtl8125_dash2_disable_txrx(hw);
1292*b574fb4cSHoward Wang 	}
1293*b574fb4cSHoward Wang 
12947d502791SHoward Wang 	rtl_exit_realwow(hw);
12957d502791SHoward Wang 
12967d502791SHoward Wang 	rtl_nic_reset(hw);
12977d502791SHoward Wang 
12987d502791SHoward Wang 	switch (hw->mcfg) {
12997d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
13007d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
13017d502791SHoward Wang 		rtl_disable_now_is_oob(hw);
13027d502791SHoward Wang 
13037d502791SHoward Wang 		data16 = rtl_mac_ocp_read(hw, 0xE8DE) & ~BIT_14;
13047d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xE8DE, data16);
13057d502791SHoward Wang 		rtl_wait_ll_share_fifo_ready(hw);
13067d502791SHoward Wang 
13077d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xC0AA, 0x07D0);
13087d502791SHoward Wang 
13097d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xC0A6, 0x01B5);
13107d502791SHoward Wang 
13117d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xC01E, 0x5555);
13127d502791SHoward Wang 
13137d502791SHoward Wang 		rtl_wait_ll_share_fifo_ready(hw);
13147d502791SHoward Wang 		break;
13157d502791SHoward Wang 	}
13167d502791SHoward Wang }
13177d502791SHoward Wang 
13187d502791SHoward Wang static void
13197d502791SHoward Wang rtl_disable_ups(struct rtl_hw *hw)
13207d502791SHoward Wang {
13217d502791SHoward Wang 	switch (hw->mcfg) {
13227d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
13237d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
13247d502791SHoward Wang 		rtl_mac_ocp_write(hw, 0xD40A, rtl_mac_ocp_read(hw, 0xD40A) & ~BIT_4);
13257d502791SHoward Wang 		break;
13267d502791SHoward Wang 	}
13277d502791SHoward Wang }
13287d502791SHoward Wang 
13297d502791SHoward Wang static void
13307d502791SHoward Wang rtl8125_disable_ocp_phy_power_saving(struct rtl_hw *hw)
13317d502791SHoward Wang {
13327d502791SHoward Wang 	u16 val;
13337d502791SHoward Wang 
13347d502791SHoward Wang 	if (hw->mcfg == CFG_METHOD_48 || hw->mcfg == CFG_METHOD_49 ||
13357d502791SHoward Wang 	    hw->mcfg == CFG_METHOD_52) {
13367d502791SHoward Wang 		val = rtl_mdio_direct_read_phy_ocp(hw, 0xC416);
13377d502791SHoward Wang 		if (val != 0x0050) {
13387d502791SHoward Wang 			rtl_set_phy_mcu_patch_request(hw);
13397d502791SHoward Wang 			rtl_mdio_direct_write_phy_ocp(hw, 0xC416, 0x0000);
13407d502791SHoward Wang 			rtl_mdio_direct_write_phy_ocp(hw, 0xC416, 0x0500);
13417d502791SHoward Wang 			rtl_clear_phy_mcu_patch_request(hw);
13427d502791SHoward Wang 		}
13437d502791SHoward Wang 	}
13447d502791SHoward Wang }
13457d502791SHoward Wang 
13467d502791SHoward Wang static void
13477d502791SHoward Wang rtl_hw_init(struct rtl_hw *hw)
13487d502791SHoward Wang {
13497d502791SHoward Wang 	switch (hw->mcfg) {
13507d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
13517d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
13527d502791SHoward Wang 		rtl_enable_aspm_clkreq_lock(hw, 0);
13537d502791SHoward Wang 		rtl_enable_force_clkreq(hw, 0);
13547d502791SHoward Wang 		break;
13557d502791SHoward Wang 	}
13567d502791SHoward Wang 
13577d502791SHoward Wang 	rtl_disable_ups(hw);
13587d502791SHoward Wang 
13597d502791SHoward Wang 	hw->hw_ops.hw_mac_mcu_config(hw);
13607d502791SHoward Wang 
13617d502791SHoward Wang 	/* Disable ocp phy power saving */
13627d502791SHoward Wang 	rtl8125_disable_ocp_phy_power_saving(hw);
13637d502791SHoward Wang }
13647d502791SHoward Wang 
13657d502791SHoward Wang void
13667d502791SHoward Wang rtl_hw_initialize(struct rtl_hw *hw)
13677d502791SHoward Wang {
13687d502791SHoward Wang 	rtl_init_software_variable(hw);
13697d502791SHoward Wang 
13707d502791SHoward Wang 	rtl_exit_oob(hw);
13717d502791SHoward Wang 
13727d502791SHoward Wang 	rtl_hw_init(hw);
13737d502791SHoward Wang 
13747d502791SHoward Wang 	rtl_nic_reset(hw);
13757d502791SHoward Wang }
13767d502791SHoward Wang 
13777d502791SHoward Wang void
13787d502791SHoward Wang rtl_get_mac_version(struct rtl_hw *hw, struct rte_pci_device *pci_dev)
13797d502791SHoward Wang {
13807d502791SHoward Wang 	u32 reg, val32;
13817d502791SHoward Wang 	u32 ic_version_id;
13827d502791SHoward Wang 
13837d502791SHoward Wang 	val32 = RTL_R32(hw, TxConfig);
13847d502791SHoward Wang 	reg = val32 & 0x7c800000;
13857d502791SHoward Wang 	ic_version_id = val32 & 0x00700000;
13867d502791SHoward Wang 
13877d502791SHoward Wang 	switch (reg) {
13887d502791SHoward Wang 	case 0x60800000:
13897d502791SHoward Wang 		if (ic_version_id == 0x00000000) {
13907d502791SHoward Wang 			hw->mcfg = CFG_METHOD_48;
13917d502791SHoward Wang 
13927d502791SHoward Wang 		} else if (ic_version_id == 0x100000) {
13937d502791SHoward Wang 			hw->mcfg = CFG_METHOD_49;
13947d502791SHoward Wang 
13957d502791SHoward Wang 		} else {
13967d502791SHoward Wang 			hw->mcfg = CFG_METHOD_49;
13977d502791SHoward Wang 			hw->HwIcVerUnknown = TRUE;
13987d502791SHoward Wang 		}
13997d502791SHoward Wang 
14007d502791SHoward Wang 		hw->efuse_ver = EFUSE_SUPPORT_V4;
14017d502791SHoward Wang 		break;
14027d502791SHoward Wang 	case 0x64000000:
14037d502791SHoward Wang 		if (ic_version_id == 0x00000000) {
14047d502791SHoward Wang 			hw->mcfg = CFG_METHOD_50;
14057d502791SHoward Wang 
14067d502791SHoward Wang 		} else if (ic_version_id == 0x100000) {
14077d502791SHoward Wang 			hw->mcfg = CFG_METHOD_51;
14087d502791SHoward Wang 
14097d502791SHoward Wang 		} else {
14107d502791SHoward Wang 			hw->mcfg = CFG_METHOD_51;
14117d502791SHoward Wang 			hw->HwIcVerUnknown = TRUE;
14127d502791SHoward Wang 		}
14137d502791SHoward Wang 
14147d502791SHoward Wang 		hw->efuse_ver = EFUSE_SUPPORT_V4;
14157d502791SHoward Wang 		break;
14167d502791SHoward Wang 	case 0x68000000:
14177d502791SHoward Wang 		if (ic_version_id == 0x00000000) {
14187d502791SHoward Wang 			hw->mcfg = CFG_METHOD_54;
14197d502791SHoward Wang 		} else if (ic_version_id == 0x100000) {
14207d502791SHoward Wang 			hw->mcfg = CFG_METHOD_55;
14217d502791SHoward Wang 		} else {
14227d502791SHoward Wang 			hw->mcfg = CFG_METHOD_55;
14237d502791SHoward Wang 			hw->HwIcVerUnknown = TRUE;
14247d502791SHoward Wang 		}
14257d502791SHoward Wang 
14267d502791SHoward Wang 		hw->efuse_ver = EFUSE_SUPPORT_V4;
14277d502791SHoward Wang 		break;
14287d502791SHoward Wang 	case 0x68800000:
14297d502791SHoward Wang 		if (ic_version_id == 0x00000000) {
14307d502791SHoward Wang 			hw->mcfg = CFG_METHOD_56;
14317d502791SHoward Wang 		} else if (ic_version_id == 0x100000) {
14327d502791SHoward Wang 			hw->mcfg = CFG_METHOD_57;
14337d502791SHoward Wang 		} else {
14347d502791SHoward Wang 			hw->mcfg = CFG_METHOD_57;
14357d502791SHoward Wang 			hw->HwIcVerUnknown = TRUE;
14367d502791SHoward Wang 		}
14377d502791SHoward Wang 
14387d502791SHoward Wang 		hw->efuse_ver = EFUSE_SUPPORT_V4;
14397d502791SHoward Wang 		break;
14407d502791SHoward Wang 	case 0x64800000:
14417d502791SHoward Wang 		if (ic_version_id == 0x00000000) {
14427d502791SHoward Wang 			hw->mcfg = CFG_METHOD_69;
14437d502791SHoward Wang 		} else if (ic_version_id == 0x100000) {
14447d502791SHoward Wang 			hw->mcfg = CFG_METHOD_70;
14457d502791SHoward Wang 		} else if (ic_version_id == 0x200000) {
14467d502791SHoward Wang 			hw->mcfg = CFG_METHOD_71;
14477d502791SHoward Wang 		} else {
14487d502791SHoward Wang 			hw->mcfg = CFG_METHOD_71;
14497d502791SHoward Wang 			hw->HwIcVerUnknown = TRUE;
14507d502791SHoward Wang 		}
14517d502791SHoward Wang 
14527d502791SHoward Wang 		hw->efuse_ver = EFUSE_SUPPORT_V4;
14537d502791SHoward Wang 		break;
14547d502791SHoward Wang 	default:
14557d502791SHoward Wang 		PMD_INIT_LOG(NOTICE, "unknown chip version (%x)", reg);
14567d502791SHoward Wang 		hw->mcfg = CFG_METHOD_DEFAULT;
14577d502791SHoward Wang 		hw->HwIcVerUnknown = TRUE;
14587d502791SHoward Wang 		hw->efuse_ver = EFUSE_NOT_SUPPORT;
14597d502791SHoward Wang 		break;
14607d502791SHoward Wang 	}
14617d502791SHoward Wang 
14627d502791SHoward Wang 	if (pci_dev->id.device_id == 0x8162) {
14637d502791SHoward Wang 		if (hw->mcfg == CFG_METHOD_49)
14647d502791SHoward Wang 			hw->mcfg = CFG_METHOD_52;
14657d502791SHoward Wang 		else if (hw->mcfg == CFG_METHOD_51)
14667d502791SHoward Wang 			hw->mcfg = CFG_METHOD_53;
14677d502791SHoward Wang 	}
14687d502791SHoward Wang }
14697d502791SHoward Wang 
14707d502791SHoward Wang int
14717d502791SHoward Wang rtl_get_mac_address(struct rtl_hw *hw, struct rte_ether_addr *ea)
14727d502791SHoward Wang {
14737d502791SHoward Wang 	u8 mac_addr[MAC_ADDR_LEN];
14747d502791SHoward Wang 
14757d502791SHoward Wang 	switch (hw->mcfg) {
14767d502791SHoward Wang 	case CFG_METHOD_48 ... CFG_METHOD_57:
14777d502791SHoward Wang 	case CFG_METHOD_69 ... CFG_METHOD_71:
14787d502791SHoward Wang 		*(u32 *)&mac_addr[0] = RTL_R32(hw, BACKUP_ADDR0_8125);
14797d502791SHoward Wang 		*(u16 *)&mac_addr[4] = RTL_R16(hw, BACKUP_ADDR1_8125);
14807d502791SHoward Wang 		break;
14817d502791SHoward Wang 	default:
14827d502791SHoward Wang 		break;
14837d502791SHoward Wang 	}
14847d502791SHoward Wang 
14857d502791SHoward Wang 	rte_ether_addr_copy((struct rte_ether_addr *)mac_addr, ea);
14867d502791SHoward Wang 
14877d502791SHoward Wang 	return 0;
14887d502791SHoward Wang }
14897d502791SHoward Wang 
14907d502791SHoward Wang void
14917d502791SHoward Wang rtl_rar_set(struct rtl_hw *hw, uint8_t *addr)
14927d502791SHoward Wang {
14937d502791SHoward Wang 	uint32_t rar_low = 0;
14947d502791SHoward Wang 	uint32_t rar_high = 0;
14957d502791SHoward Wang 
14967d502791SHoward Wang 	rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
14977d502791SHoward Wang 		   ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
14987d502791SHoward Wang 
14997d502791SHoward Wang 	rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
15007d502791SHoward Wang 
15017d502791SHoward Wang 	rtl_enable_cfg9346_write(hw);
15027d502791SHoward Wang 
15037d502791SHoward Wang 	RTL_W32(hw, MAC0, rar_low);
15047d502791SHoward Wang 	RTL_W32(hw, MAC4, rar_high);
15057d502791SHoward Wang 
15067d502791SHoward Wang 	rtl_disable_cfg9346_write(hw);
15077d502791SHoward Wang }
1508fa0b0ad6SHoward Wang 
1509fa0b0ad6SHoward Wang void
1510fa0b0ad6SHoward Wang rtl_get_tally_stats(struct rtl_hw *hw, struct rte_eth_stats *rte_stats)
1511fa0b0ad6SHoward Wang {
1512fa0b0ad6SHoward Wang 	struct rtl_counters *counters;
1513fa0b0ad6SHoward Wang 	uint64_t paddr;
1514fa0b0ad6SHoward Wang 	u32 cmd;
1515fa0b0ad6SHoward Wang 	u32 wait_cnt;
1516fa0b0ad6SHoward Wang 
1517fa0b0ad6SHoward Wang 	counters = hw->tally_vaddr;
1518fa0b0ad6SHoward Wang 	paddr = hw->tally_paddr;
1519fa0b0ad6SHoward Wang 	if (!counters)
1520fa0b0ad6SHoward Wang 		return;
1521fa0b0ad6SHoward Wang 
1522fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrHigh, (u64)paddr >> 32);
1523fa0b0ad6SHoward Wang 	cmd = (u64)paddr & DMA_BIT_MASK(32);
1524fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrLow, cmd);
1525fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrLow, cmd | CounterDump);
1526fa0b0ad6SHoward Wang 
1527fa0b0ad6SHoward Wang 	wait_cnt = 0;
1528fa0b0ad6SHoward Wang 	while (RTL_R32(hw, CounterAddrLow) & CounterDump) {
1529fa0b0ad6SHoward Wang 		rte_delay_us(10);
1530fa0b0ad6SHoward Wang 
1531fa0b0ad6SHoward Wang 		wait_cnt++;
1532fa0b0ad6SHoward Wang 		if (wait_cnt > 20)
1533fa0b0ad6SHoward Wang 			break;
1534fa0b0ad6SHoward Wang 	}
1535fa0b0ad6SHoward Wang 
1536fa0b0ad6SHoward Wang 	/* RX errors */
1537fa0b0ad6SHoward Wang 	rte_stats->imissed = rte_le_to_cpu_64(counters->rx_missed);
1538fa0b0ad6SHoward Wang 	rte_stats->ierrors = rte_le_to_cpu_64(counters->rx_errors);
1539fa0b0ad6SHoward Wang 
1540fa0b0ad6SHoward Wang 	/* TX errors */
1541fa0b0ad6SHoward Wang 	rte_stats->oerrors = rte_le_to_cpu_64(counters->tx_errors);
1542fa0b0ad6SHoward Wang 
1543fa0b0ad6SHoward Wang 	rte_stats->ipackets = rte_le_to_cpu_64(counters->rx_packets);
1544fa0b0ad6SHoward Wang 	rte_stats->opackets = rte_le_to_cpu_64(counters->tx_packets);
1545fa0b0ad6SHoward Wang }
1546fa0b0ad6SHoward Wang 
1547fa0b0ad6SHoward Wang void
1548fa0b0ad6SHoward Wang rtl_clear_tally_stats(struct rtl_hw *hw)
1549fa0b0ad6SHoward Wang {
1550fa0b0ad6SHoward Wang 	if (!hw->tally_paddr)
1551fa0b0ad6SHoward Wang 		return;
1552fa0b0ad6SHoward Wang 
1553fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrHigh, (u64)hw->tally_paddr >> 32);
1554fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrLow,
1555fa0b0ad6SHoward Wang 		((u64)hw->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset);
1556fa0b0ad6SHoward Wang }
1557fa0b0ad6SHoward Wang 
1558fa0b0ad6SHoward Wang int
1559fa0b0ad6SHoward Wang rtl_tally_init(struct rte_eth_dev *dev)
1560fa0b0ad6SHoward Wang {
1561fa0b0ad6SHoward Wang 	struct rtl_adapter *adapter = RTL_DEV_PRIVATE(dev);
1562fa0b0ad6SHoward Wang 	struct rtl_hw *hw = &adapter->hw;
1563fa0b0ad6SHoward Wang 	const struct rte_memzone *mz;
1564fa0b0ad6SHoward Wang 
1565fa0b0ad6SHoward Wang 	mz = rte_eth_dma_zone_reserve(dev, "tally_counters", 0,
1566fa0b0ad6SHoward Wang 				      sizeof(struct rtl_counters), 64, rte_socket_id());
1567fa0b0ad6SHoward Wang 	if (mz == NULL)
1568fa0b0ad6SHoward Wang 		return -ENOMEM;
1569fa0b0ad6SHoward Wang 
1570fa0b0ad6SHoward Wang 	hw->tally_vaddr = mz->addr;
1571fa0b0ad6SHoward Wang 	hw->tally_paddr = mz->iova;
1572fa0b0ad6SHoward Wang 
1573fa0b0ad6SHoward Wang 	/* Fill tally addrs */
1574fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrHigh, (u64)hw->tally_paddr >> 32);
1575fa0b0ad6SHoward Wang 	RTL_W32(hw, CounterAddrLow, (u64)hw->tally_paddr & (DMA_BIT_MASK(32)));
1576fa0b0ad6SHoward Wang 
1577fa0b0ad6SHoward Wang 	/* Reset the hw statistics */
1578fa0b0ad6SHoward Wang 	rtl_clear_tally_stats(hw);
1579fa0b0ad6SHoward Wang 
1580fa0b0ad6SHoward Wang 	return 0;
1581fa0b0ad6SHoward Wang }
1582fa0b0ad6SHoward Wang 
1583fa0b0ad6SHoward Wang void
1584fa0b0ad6SHoward Wang rtl_tally_free(struct rte_eth_dev *dev)
1585fa0b0ad6SHoward Wang {
1586fa0b0ad6SHoward Wang 	rte_eth_dma_zone_free(dev, "tally_counters", 0);
1587fa0b0ad6SHoward Wang }
1588