xref: /dpdk/drivers/net/r8169/r8169_dash.c (revision b574fb4cc855f4e86659d37ded01e7a218c38865)
17d502791SHoward Wang /* SPDX-License-Identifier: BSD-3-Clause
27d502791SHoward Wang  * Copyright(c) 2024 Realtek Corporation. All rights reserved
37d502791SHoward Wang  */
47d502791SHoward Wang 
57d502791SHoward Wang #include <stdio.h>
67d502791SHoward Wang #include <errno.h>
77d502791SHoward Wang #include <stdint.h>
87d502791SHoward Wang 
97d502791SHoward Wang #include <rte_ether.h>
107d502791SHoward Wang #include <ethdev_driver.h>
117d502791SHoward Wang 
127d502791SHoward Wang #include "r8169_compat.h"
137d502791SHoward Wang #include "r8169_dash.h"
147d502791SHoward Wang #include "r8169_hw.h"
157d502791SHoward Wang 
167d502791SHoward Wang bool
177d502791SHoward Wang rtl_is_allow_access_dash_ocp(struct rtl_hw *hw)
187d502791SHoward Wang {
197d502791SHoward Wang 	bool allow_access = false;
207d502791SHoward Wang 	u16 mac_ocp_data;
217d502791SHoward Wang 
227d502791SHoward Wang 	if (!HW_DASH_SUPPORT_DASH(hw))
237d502791SHoward Wang 		goto exit;
247d502791SHoward Wang 
257d502791SHoward Wang 	allow_access = true;
267d502791SHoward Wang 	switch (hw->mcfg) {
27*b574fb4cSHoward Wang 	case CFG_METHOD_48:
28*b574fb4cSHoward Wang 	case CFG_METHOD_49:
297d502791SHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xd460);
307d502791SHoward Wang 		if (mac_ocp_data == 0xffff || !(mac_ocp_data & BIT_0))
317d502791SHoward Wang 			allow_access = false;
327d502791SHoward Wang 		break;
33*b574fb4cSHoward Wang 	case CFG_METHOD_54:
34*b574fb4cSHoward Wang 	case CFG_METHOD_55:
357d502791SHoward Wang 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xd4c0);
367d502791SHoward Wang 		if (mac_ocp_data == 0xffff || (mac_ocp_data & BIT_3))
377d502791SHoward Wang 			allow_access = false;
387d502791SHoward Wang 		break;
397d502791SHoward Wang 	default:
407d502791SHoward Wang 		goto exit;
417d502791SHoward Wang 	}
427d502791SHoward Wang exit:
437d502791SHoward Wang 	return allow_access;
447d502791SHoward Wang }
457d502791SHoward Wang 
467d502791SHoward Wang static u32
477d502791SHoward Wang rtl_get_dash_fw_ver(struct rtl_hw *hw)
487d502791SHoward Wang {
497d502791SHoward Wang 	u32 ver = 0xffffffff;
507d502791SHoward Wang 
517d502791SHoward Wang 	if (HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(hw) == FALSE)
527d502791SHoward Wang 		goto exit;
537d502791SHoward Wang 
547d502791SHoward Wang 	ver = rtl_ocp_read(hw, OCP_REG_FIRMWARE_MAJOR_VERSION, 4);
557d502791SHoward Wang 
567d502791SHoward Wang exit:
577d502791SHoward Wang 	return ver;
587d502791SHoward Wang }
597d502791SHoward Wang 
607d502791SHoward Wang static int
617d502791SHoward Wang _rtl_check_dash(struct rtl_hw *hw)
627d502791SHoward Wang {
637d502791SHoward Wang 	if (!hw->AllowAccessDashOcp)
647d502791SHoward Wang 		return 0;
657d502791SHoward Wang 
667d502791SHoward Wang 	if (HW_DASH_SUPPORT_TYPE_2(hw) || HW_DASH_SUPPORT_TYPE_4(hw)) {
677d502791SHoward Wang 		if (rtl_ocp_read(hw, 0x128, 1) & BIT_0)
687d502791SHoward Wang 			return 1;
697d502791SHoward Wang 	}
707d502791SHoward Wang 
717d502791SHoward Wang 	return 0;
727d502791SHoward Wang }
737d502791SHoward Wang 
747d502791SHoward Wang int
757d502791SHoward Wang rtl_check_dash(struct rtl_hw *hw)
767d502791SHoward Wang {
777d502791SHoward Wang 	u32 ver;
787d502791SHoward Wang 
797d502791SHoward Wang 	if (_rtl_check_dash(hw)) {
807d502791SHoward Wang 		ver = rtl_get_dash_fw_ver(hw);
817d502791SHoward Wang 		if (!(ver == 0 || ver == 0xffffffff))
827d502791SHoward Wang 			return 1;
837d502791SHoward Wang 	}
847d502791SHoward Wang 
857d502791SHoward Wang 	return 0;
867d502791SHoward Wang }
87*b574fb4cSHoward Wang 
88*b574fb4cSHoward Wang static void
89*b574fb4cSHoward Wang rtl8125_dash2_disable_tx(struct rtl_hw *hw)
90*b574fb4cSHoward Wang {
91*b574fb4cSHoward Wang 	u16 wait_cnt = 0;
92*b574fb4cSHoward Wang 	u8 tmp_uchar;
93*b574fb4cSHoward Wang 
94*b574fb4cSHoward Wang 	if (!HW_DASH_SUPPORT_CMAC(hw))
95*b574fb4cSHoward Wang 		return;
96*b574fb4cSHoward Wang 
97*b574fb4cSHoward Wang 	if (!hw->DASH)
98*b574fb4cSHoward Wang 		return;
99*b574fb4cSHoward Wang 
100*b574fb4cSHoward Wang 	/* Disable oob Tx */
101*b574fb4cSHoward Wang 	RTL_CMAC_W8(hw, CMAC_IBCR2, RTL_CMAC_R8(hw, CMAC_IBCR2) & ~BIT_0);
102*b574fb4cSHoward Wang 
103*b574fb4cSHoward Wang 	/* Wait oob Tx disable */
104*b574fb4cSHoward Wang 	do {
105*b574fb4cSHoward Wang 		tmp_uchar = RTL_CMAC_R8(hw, CMAC_IBISR0);
106*b574fb4cSHoward Wang 		if (tmp_uchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE)
107*b574fb4cSHoward Wang 			break;
108*b574fb4cSHoward Wang 
109*b574fb4cSHoward Wang 		rte_delay_us(50);
110*b574fb4cSHoward Wang 		wait_cnt++;
111*b574fb4cSHoward Wang 	} while (wait_cnt < 2000);
112*b574fb4cSHoward Wang 
113*b574fb4cSHoward Wang 	/* Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE */
114*b574fb4cSHoward Wang 	RTL_CMAC_W8(hw, CMAC_IBISR0, RTL_CMAC_R8(hw, CMAC_IBISR0) |
115*b574fb4cSHoward Wang 		    ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE);
116*b574fb4cSHoward Wang }
117*b574fb4cSHoward Wang 
118*b574fb4cSHoward Wang static void
119*b574fb4cSHoward Wang rtl8125_dash2_disable_rx(struct rtl_hw *hw)
120*b574fb4cSHoward Wang {
121*b574fb4cSHoward Wang 	if (!HW_DASH_SUPPORT_CMAC(hw))
122*b574fb4cSHoward Wang 		return;
123*b574fb4cSHoward Wang 
124*b574fb4cSHoward Wang 	if (!hw->DASH)
125*b574fb4cSHoward Wang 		return;
126*b574fb4cSHoward Wang 
127*b574fb4cSHoward Wang 	RTL_CMAC_W8(hw, CMAC_IBCR0, RTL_CMAC_R8(hw, CMAC_IBCR0) & ~BIT_0);
128*b574fb4cSHoward Wang }
129*b574fb4cSHoward Wang 
130*b574fb4cSHoward Wang void
131*b574fb4cSHoward Wang rtl8125_dash2_disable_txrx(struct rtl_hw *hw)
132*b574fb4cSHoward Wang {
133*b574fb4cSHoward Wang 	if (!HW_DASH_SUPPORT_CMAC(hw))
134*b574fb4cSHoward Wang 		return;
135*b574fb4cSHoward Wang 
136*b574fb4cSHoward Wang 	rtl8125_dash2_disable_tx(hw);
137*b574fb4cSHoward Wang 	rtl8125_dash2_disable_rx(hw);
138*b574fb4cSHoward Wang }
139*b574fb4cSHoward Wang 
140*b574fb4cSHoward Wang static void
141*b574fb4cSHoward Wang rtl8125_notify_dash_oob_cmac(struct rtl_hw *hw, u32 cmd)
142*b574fb4cSHoward Wang {
143*b574fb4cSHoward Wang 	u32 tmp_value;
144*b574fb4cSHoward Wang 
145*b574fb4cSHoward Wang 	if (!HW_DASH_SUPPORT_CMAC(hw))
146*b574fb4cSHoward Wang 		return;
147*b574fb4cSHoward Wang 
148*b574fb4cSHoward Wang 	rtl_ocp_write(hw, 0x180, 4, cmd);
149*b574fb4cSHoward Wang 	tmp_value = rtl_ocp_read(hw, 0x30, 4);
150*b574fb4cSHoward Wang 	tmp_value |= BIT_0;
151*b574fb4cSHoward Wang 	rtl_ocp_write(hw, 0x30, 4, tmp_value);
152*b574fb4cSHoward Wang }
153*b574fb4cSHoward Wang 
154*b574fb4cSHoward Wang static void
155*b574fb4cSHoward Wang rtl8125_notify_dash_oob_ipc2(struct rtl_hw *hw, u32 cmd)
156*b574fb4cSHoward Wang {
157*b574fb4cSHoward Wang 	if (HW_DASH_SUPPORT_TYPE_4(hw) == FALSE)
158*b574fb4cSHoward Wang 		return;
159*b574fb4cSHoward Wang 
160*b574fb4cSHoward Wang 	rtl_ocp_write(hw, IB2SOC_DATA, 4, cmd);
161*b574fb4cSHoward Wang 	rtl_ocp_write(hw, IB2SOC_CMD, 4, 0x00);
162*b574fb4cSHoward Wang 	rtl_ocp_write(hw, IB2SOC_SET, 4, 0x01);
163*b574fb4cSHoward Wang }
164*b574fb4cSHoward Wang 
165*b574fb4cSHoward Wang static void
166*b574fb4cSHoward Wang rtl8125_notify_dash_oob(struct rtl_hw *hw, u32 cmd)
167*b574fb4cSHoward Wang {
168*b574fb4cSHoward Wang 	switch (hw->HwSuppDashVer) {
169*b574fb4cSHoward Wang 	case 2:
170*b574fb4cSHoward Wang 	case 3:
171*b574fb4cSHoward Wang 		rtl8125_notify_dash_oob_cmac(hw, cmd);
172*b574fb4cSHoward Wang 		break;
173*b574fb4cSHoward Wang 	case 4:
174*b574fb4cSHoward Wang 		rtl8125_notify_dash_oob_ipc2(hw, cmd);
175*b574fb4cSHoward Wang 		break;
176*b574fb4cSHoward Wang 	default:
177*b574fb4cSHoward Wang 		break;
178*b574fb4cSHoward Wang 	}
179*b574fb4cSHoward Wang }
180*b574fb4cSHoward Wang 
181*b574fb4cSHoward Wang static int
182*b574fb4cSHoward Wang rtl8125_wait_dash_fw_ready(struct rtl_hw *hw)
183*b574fb4cSHoward Wang {
184*b574fb4cSHoward Wang 	int rc = -1;
185*b574fb4cSHoward Wang 	int timeout;
186*b574fb4cSHoward Wang 
187*b574fb4cSHoward Wang 	if (!hw->DASH)
188*b574fb4cSHoward Wang 		goto out;
189*b574fb4cSHoward Wang 
190*b574fb4cSHoward Wang 	for (timeout = 0; timeout < 10; timeout++) {
191*b574fb4cSHoward Wang 		rte_delay_ms(10);
192*b574fb4cSHoward Wang 		if (rtl_ocp_read(hw, 0x124, 1) & BIT_0) {
193*b574fb4cSHoward Wang 			rc = 1;
194*b574fb4cSHoward Wang 			goto out;
195*b574fb4cSHoward Wang 		}
196*b574fb4cSHoward Wang 	}
197*b574fb4cSHoward Wang 
198*b574fb4cSHoward Wang 	rc = 0;
199*b574fb4cSHoward Wang 
200*b574fb4cSHoward Wang out:
201*b574fb4cSHoward Wang 	return rc;
202*b574fb4cSHoward Wang }
203*b574fb4cSHoward Wang 
204*b574fb4cSHoward Wang void
205*b574fb4cSHoward Wang rtl8125_driver_start(struct rtl_hw *hw)
206*b574fb4cSHoward Wang {
207*b574fb4cSHoward Wang 	if (!hw->AllowAccessDashOcp)
208*b574fb4cSHoward Wang 		return;
209*b574fb4cSHoward Wang 
210*b574fb4cSHoward Wang 	rtl8125_notify_dash_oob(hw, OOB_CMD_DRIVER_START);
211*b574fb4cSHoward Wang 
212*b574fb4cSHoward Wang 	rtl8125_wait_dash_fw_ready(hw);
213*b574fb4cSHoward Wang }
214*b574fb4cSHoward Wang 
215*b574fb4cSHoward Wang void
216*b574fb4cSHoward Wang rtl8125_driver_stop(struct rtl_hw *hw)
217*b574fb4cSHoward Wang {
218*b574fb4cSHoward Wang 	if (!hw->AllowAccessDashOcp)
219*b574fb4cSHoward Wang 		return;
220*b574fb4cSHoward Wang 
221*b574fb4cSHoward Wang 	if (HW_DASH_SUPPORT_CMAC(hw))
222*b574fb4cSHoward Wang 		rtl8125_dash2_disable_txrx(hw);
223*b574fb4cSHoward Wang 
224*b574fb4cSHoward Wang 	rtl8125_notify_dash_oob(hw, OOB_CMD_DRIVER_STOP);
225*b574fb4cSHoward Wang 
226*b574fb4cSHoward Wang 	rtl8125_wait_dash_fw_ready(hw);
227*b574fb4cSHoward Wang }
228