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