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