xref: /dpdk/drivers/net/r8169/r8169_dash.c (revision b574fb4cc855f4e86659d37ded01e7a218c38865)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2024 Realtek Corporation. All rights reserved
3  */
4 
5 #include <stdio.h>
6 #include <errno.h>
7 #include <stdint.h>
8 
9 #include <rte_ether.h>
10 #include <ethdev_driver.h>
11 
12 #include "r8169_compat.h"
13 #include "r8169_dash.h"
14 #include "r8169_hw.h"
15 
16 bool
17 rtl_is_allow_access_dash_ocp(struct rtl_hw *hw)
18 {
19 	bool allow_access = false;
20 	u16 mac_ocp_data;
21 
22 	if (!HW_DASH_SUPPORT_DASH(hw))
23 		goto exit;
24 
25 	allow_access = true;
26 	switch (hw->mcfg) {
27 	case CFG_METHOD_48:
28 	case CFG_METHOD_49:
29 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xd460);
30 		if (mac_ocp_data == 0xffff || !(mac_ocp_data & BIT_0))
31 			allow_access = false;
32 		break;
33 	case CFG_METHOD_54:
34 	case CFG_METHOD_55:
35 		mac_ocp_data = rtl_mac_ocp_read(hw, 0xd4c0);
36 		if (mac_ocp_data == 0xffff || (mac_ocp_data & BIT_3))
37 			allow_access = false;
38 		break;
39 	default:
40 		goto exit;
41 	}
42 exit:
43 	return allow_access;
44 }
45 
46 static u32
47 rtl_get_dash_fw_ver(struct rtl_hw *hw)
48 {
49 	u32 ver = 0xffffffff;
50 
51 	if (HW_DASH_SUPPORT_GET_FIRMWARE_VERSION(hw) == FALSE)
52 		goto exit;
53 
54 	ver = rtl_ocp_read(hw, OCP_REG_FIRMWARE_MAJOR_VERSION, 4);
55 
56 exit:
57 	return ver;
58 }
59 
60 static int
61 _rtl_check_dash(struct rtl_hw *hw)
62 {
63 	if (!hw->AllowAccessDashOcp)
64 		return 0;
65 
66 	if (HW_DASH_SUPPORT_TYPE_2(hw) || HW_DASH_SUPPORT_TYPE_4(hw)) {
67 		if (rtl_ocp_read(hw, 0x128, 1) & BIT_0)
68 			return 1;
69 	}
70 
71 	return 0;
72 }
73 
74 int
75 rtl_check_dash(struct rtl_hw *hw)
76 {
77 	u32 ver;
78 
79 	if (_rtl_check_dash(hw)) {
80 		ver = rtl_get_dash_fw_ver(hw);
81 		if (!(ver == 0 || ver == 0xffffffff))
82 			return 1;
83 	}
84 
85 	return 0;
86 }
87 
88 static void
89 rtl8125_dash2_disable_tx(struct rtl_hw *hw)
90 {
91 	u16 wait_cnt = 0;
92 	u8 tmp_uchar;
93 
94 	if (!HW_DASH_SUPPORT_CMAC(hw))
95 		return;
96 
97 	if (!hw->DASH)
98 		return;
99 
100 	/* Disable oob Tx */
101 	RTL_CMAC_W8(hw, CMAC_IBCR2, RTL_CMAC_R8(hw, CMAC_IBCR2) & ~BIT_0);
102 
103 	/* Wait oob Tx disable */
104 	do {
105 		tmp_uchar = RTL_CMAC_R8(hw, CMAC_IBISR0);
106 		if (tmp_uchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE)
107 			break;
108 
109 		rte_delay_us(50);
110 		wait_cnt++;
111 	} while (wait_cnt < 2000);
112 
113 	/* Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE */
114 	RTL_CMAC_W8(hw, CMAC_IBISR0, RTL_CMAC_R8(hw, CMAC_IBISR0) |
115 		    ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE);
116 }
117 
118 static void
119 rtl8125_dash2_disable_rx(struct rtl_hw *hw)
120 {
121 	if (!HW_DASH_SUPPORT_CMAC(hw))
122 		return;
123 
124 	if (!hw->DASH)
125 		return;
126 
127 	RTL_CMAC_W8(hw, CMAC_IBCR0, RTL_CMAC_R8(hw, CMAC_IBCR0) & ~BIT_0);
128 }
129 
130 void
131 rtl8125_dash2_disable_txrx(struct rtl_hw *hw)
132 {
133 	if (!HW_DASH_SUPPORT_CMAC(hw))
134 		return;
135 
136 	rtl8125_dash2_disable_tx(hw);
137 	rtl8125_dash2_disable_rx(hw);
138 }
139 
140 static void
141 rtl8125_notify_dash_oob_cmac(struct rtl_hw *hw, u32 cmd)
142 {
143 	u32 tmp_value;
144 
145 	if (!HW_DASH_SUPPORT_CMAC(hw))
146 		return;
147 
148 	rtl_ocp_write(hw, 0x180, 4, cmd);
149 	tmp_value = rtl_ocp_read(hw, 0x30, 4);
150 	tmp_value |= BIT_0;
151 	rtl_ocp_write(hw, 0x30, 4, tmp_value);
152 }
153 
154 static void
155 rtl8125_notify_dash_oob_ipc2(struct rtl_hw *hw, u32 cmd)
156 {
157 	if (HW_DASH_SUPPORT_TYPE_4(hw) == FALSE)
158 		return;
159 
160 	rtl_ocp_write(hw, IB2SOC_DATA, 4, cmd);
161 	rtl_ocp_write(hw, IB2SOC_CMD, 4, 0x00);
162 	rtl_ocp_write(hw, IB2SOC_SET, 4, 0x01);
163 }
164 
165 static void
166 rtl8125_notify_dash_oob(struct rtl_hw *hw, u32 cmd)
167 {
168 	switch (hw->HwSuppDashVer) {
169 	case 2:
170 	case 3:
171 		rtl8125_notify_dash_oob_cmac(hw, cmd);
172 		break;
173 	case 4:
174 		rtl8125_notify_dash_oob_ipc2(hw, cmd);
175 		break;
176 	default:
177 		break;
178 	}
179 }
180 
181 static int
182 rtl8125_wait_dash_fw_ready(struct rtl_hw *hw)
183 {
184 	int rc = -1;
185 	int timeout;
186 
187 	if (!hw->DASH)
188 		goto out;
189 
190 	for (timeout = 0; timeout < 10; timeout++) {
191 		rte_delay_ms(10);
192 		if (rtl_ocp_read(hw, 0x124, 1) & BIT_0) {
193 			rc = 1;
194 			goto out;
195 		}
196 	}
197 
198 	rc = 0;
199 
200 out:
201 	return rc;
202 }
203 
204 void
205 rtl8125_driver_start(struct rtl_hw *hw)
206 {
207 	if (!hw->AllowAccessDashOcp)
208 		return;
209 
210 	rtl8125_notify_dash_oob(hw, OOB_CMD_DRIVER_START);
211 
212 	rtl8125_wait_dash_fw_ready(hw);
213 }
214 
215 void
216 rtl8125_driver_stop(struct rtl_hw *hw)
217 {
218 	if (!hw->AllowAccessDashOcp)
219 		return;
220 
221 	if (HW_DASH_SUPPORT_CMAC(hw))
222 		rtl8125_dash2_disable_txrx(hw);
223 
224 	rtl8125_notify_dash_oob(hw, OOB_CMD_DRIVER_STOP);
225 
226 	rtl8125_wait_dash_fw_ready(hw);
227 }
228