186d36773SIgor Russkikh // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0) 286d36773SIgor Russkikh /* Copyright (C) 2014-2017 aQuantia Corporation. */ 386d36773SIgor Russkikh 486d36773SIgor Russkikh /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for 586d36773SIgor Russkikh * Atlantic hardware abstraction layer. 686d36773SIgor Russkikh */ 786d36773SIgor Russkikh 886d36773SIgor Russkikh #include <rte_ether.h> 9e9924638SPavel Belous #include <pthread.h> 1086d36773SIgor Russkikh #include "../atl_hw_regs.h" 1186d36773SIgor Russkikh 1286d36773SIgor Russkikh #include "../atl_types.h" 1386d36773SIgor Russkikh #include "hw_atl_utils.h" 1486d36773SIgor Russkikh #include "hw_atl_llh.h" 1586d36773SIgor Russkikh 1686d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 1786d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 1886d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 1986d36773SIgor Russkikh 2086d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 2186d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C 2286d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_LED_ADDR 0x31c 2386d36773SIgor Russkikh 2486d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 2586d36773SIgor Russkikh #define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 2686d36773SIgor Russkikh 2786d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY) 2886d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL) 2986d36773SIgor Russkikh 3086d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE) 3186d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_EEE_2G5_MASK BIT(CAPS_HI_2P5GBASET_FD_EEE) 3286d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_EEE_5G_MASK BIT(CAPS_HI_5GBASET_FD_EEE) 3386d36773SIgor Russkikh #define HW_ATL_FW2X_CAP_EEE_10G_MASK BIT(CAPS_HI_10GBASET_FD_EEE) 3486d36773SIgor Russkikh 3586d36773SIgor Russkikh #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8 3686d36773SIgor Russkikh #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E 3786d36773SIgor Russkikh 3886d36773SIgor Russkikh #define HW_ATL_FW_FEATURE_LED 0x03010026 3986d36773SIgor Russkikh 40*e7750639SAndre Muezerie struct __rte_packed_begin fw2x_msg_wol_pattern { 4186d36773SIgor Russkikh u8 mask[16]; 4286d36773SIgor Russkikh u32 crc; 43*e7750639SAndre Muezerie } __rte_packed_end; 4486d36773SIgor Russkikh 45*e7750639SAndre Muezerie struct __rte_packed_begin fw2x_msg_wol { 4686d36773SIgor Russkikh u32 msg_id; 4786d36773SIgor Russkikh u8 hw_addr[6]; 4886d36773SIgor Russkikh u8 magic_packet_enabled; 4986d36773SIgor Russkikh u8 filter_count; 5086d36773SIgor Russkikh struct fw2x_msg_wol_pattern filter[HAL_ATLANTIC_WOL_FILTERS_COUNT]; 5186d36773SIgor Russkikh u8 link_up_enabled; 5286d36773SIgor Russkikh u8 link_down_enabled; 5386d36773SIgor Russkikh u16 reserved; 5486d36773SIgor Russkikh u32 link_up_timeout; 5586d36773SIgor Russkikh u32 link_down_timeout; 56*e7750639SAndre Muezerie } __rte_packed_end; 5786d36773SIgor Russkikh 5886d36773SIgor Russkikh static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed); 5986d36773SIgor Russkikh static int aq_fw2x_set_state(struct aq_hw_s *self, 6086d36773SIgor Russkikh enum hal_atl_utils_fw_state_e state); 6186d36773SIgor Russkikh 6286d36773SIgor Russkikh static int aq_fw2x_init(struct aq_hw_s *self) 6386d36773SIgor Russkikh { 6486d36773SIgor Russkikh int err = 0; 652f40244bSPavel Belous struct hw_aq_atl_utils_mbox mbox; 6686d36773SIgor Russkikh 6786d36773SIgor Russkikh /* check 10 times by 1ms */ 6886d36773SIgor Russkikh AQ_HW_WAIT_FOR(0U != (self->mbox_addr = 6986d36773SIgor Russkikh aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)), 7086d36773SIgor Russkikh 1000U, 10U); 7186d36773SIgor Russkikh AQ_HW_WAIT_FOR(0U != (self->rpc_addr = 7286d36773SIgor Russkikh aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR)), 7386d36773SIgor Russkikh 1000U, 100U); 742f40244bSPavel Belous 752f40244bSPavel Belous /* Read caps */ 762f40244bSPavel Belous hw_atl_utils_mpi_read_stats(self, &mbox); 772f40244bSPavel Belous 782f40244bSPavel Belous self->caps_lo = mbox.info.caps_lo; 792f40244bSPavel Belous 8086d36773SIgor Russkikh return err; 8186d36773SIgor Russkikh } 8286d36773SIgor Russkikh 8386d36773SIgor Russkikh static int aq_fw2x_deinit(struct aq_hw_s *self) 8486d36773SIgor Russkikh { 8586d36773SIgor Russkikh int err = aq_fw2x_set_link_speed(self, 0); 8686d36773SIgor Russkikh 8786d36773SIgor Russkikh if (!err) 8886d36773SIgor Russkikh err = aq_fw2x_set_state(self, MPI_DEINIT); 8986d36773SIgor Russkikh 9086d36773SIgor Russkikh return err; 9186d36773SIgor Russkikh } 9286d36773SIgor Russkikh 9386d36773SIgor Russkikh static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) 9486d36773SIgor Russkikh { 9586d36773SIgor Russkikh enum hw_atl_fw2x_rate rate = 0; 9686d36773SIgor Russkikh 9786d36773SIgor Russkikh if (speed & AQ_NIC_RATE_10G) 9886d36773SIgor Russkikh rate |= FW2X_RATE_10G; 9986d36773SIgor Russkikh 10086d36773SIgor Russkikh if (speed & AQ_NIC_RATE_5G) 10186d36773SIgor Russkikh rate |= FW2X_RATE_5G; 10286d36773SIgor Russkikh 10386d36773SIgor Russkikh if (speed & AQ_NIC_RATE_5G5R) 10486d36773SIgor Russkikh rate |= FW2X_RATE_5G; 10586d36773SIgor Russkikh 10686d36773SIgor Russkikh if (speed & AQ_NIC_RATE_2G5) 10786d36773SIgor Russkikh rate |= FW2X_RATE_2G5; 10886d36773SIgor Russkikh 10986d36773SIgor Russkikh if (speed & AQ_NIC_RATE_1G) 11086d36773SIgor Russkikh rate |= FW2X_RATE_1G; 11186d36773SIgor Russkikh 11286d36773SIgor Russkikh if (speed & AQ_NIC_RATE_100M) 11386d36773SIgor Russkikh rate |= FW2X_RATE_100M; 11486d36773SIgor Russkikh 11586d36773SIgor Russkikh return rate; 11686d36773SIgor Russkikh } 11786d36773SIgor Russkikh 11886d36773SIgor Russkikh static u32 fw2x_to_eee_mask(u32 speed) 11986d36773SIgor Russkikh { 12086d36773SIgor Russkikh u32 rate = 0; 12186d36773SIgor Russkikh 12286d36773SIgor Russkikh if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK) 12386d36773SIgor Russkikh rate |= AQ_NIC_RATE_EEE_10G; 12486d36773SIgor Russkikh 12586d36773SIgor Russkikh if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK) 12686d36773SIgor Russkikh rate |= AQ_NIC_RATE_EEE_5G; 12786d36773SIgor Russkikh 12886d36773SIgor Russkikh if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK) 12986d36773SIgor Russkikh rate |= AQ_NIC_RATE_EEE_2G5; 13086d36773SIgor Russkikh 13186d36773SIgor Russkikh if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK) 13286d36773SIgor Russkikh rate |= AQ_NIC_RATE_EEE_1G; 13386d36773SIgor Russkikh 13486d36773SIgor Russkikh return rate; 13586d36773SIgor Russkikh } 13686d36773SIgor Russkikh 13786d36773SIgor Russkikh static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed) 13886d36773SIgor Russkikh { 139f73061d5SPavel Belous u32 rate_mask = link_speed_mask_2fw2x_ratemask(speed); 140f73061d5SPavel Belous u32 reg_val = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); 141f73061d5SPavel Belous u32 val = rate_mask | ((BIT(CAPS_LO_SMBUS_READ) | 142f73061d5SPavel Belous BIT(CAPS_LO_SMBUS_WRITE) | 143f73061d5SPavel Belous BIT(CAPS_LO_MACSEC)) & reg_val); 14486d36773SIgor Russkikh 14586d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val); 14686d36773SIgor Russkikh 14786d36773SIgor Russkikh return 0; 14886d36773SIgor Russkikh } 14986d36773SIgor Russkikh 15086d36773SIgor Russkikh static void aq_fw2x_set_mpi_flow_control(struct aq_hw_s *self, u32 *mpi_state) 15186d36773SIgor Russkikh { 15286d36773SIgor Russkikh if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) 15386d36773SIgor Russkikh *mpi_state |= BIT(CAPS_HI_PAUSE); 15486d36773SIgor Russkikh else 15586d36773SIgor Russkikh *mpi_state &= ~BIT(CAPS_HI_PAUSE); 15686d36773SIgor Russkikh 15786d36773SIgor Russkikh if (self->aq_nic_cfg->flow_control & AQ_NIC_FC_TX) 15886d36773SIgor Russkikh *mpi_state |= BIT(CAPS_HI_ASYMMETRIC_PAUSE); 15986d36773SIgor Russkikh else 16086d36773SIgor Russkikh *mpi_state &= ~BIT(CAPS_HI_ASYMMETRIC_PAUSE); 16186d36773SIgor Russkikh } 16286d36773SIgor Russkikh 16386d36773SIgor Russkikh static int aq_fw2x_set_state(struct aq_hw_s *self, 16486d36773SIgor Russkikh enum hal_atl_utils_fw_state_e state) 16586d36773SIgor Russkikh { 16686d36773SIgor Russkikh u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 16786d36773SIgor Russkikh 16886d36773SIgor Russkikh switch (state) { 16986d36773SIgor Russkikh case MPI_INIT: 17086d36773SIgor Russkikh mpi_state &= ~BIT(CAPS_HI_LINK_DROP); 17186d36773SIgor Russkikh aq_fw2x_set_mpi_flow_control(self, &mpi_state); 17286d36773SIgor Russkikh break; 17386d36773SIgor Russkikh case MPI_DEINIT: 17486d36773SIgor Russkikh mpi_state |= BIT(CAPS_HI_LINK_DROP); 17586d36773SIgor Russkikh break; 17686d36773SIgor Russkikh case MPI_RESET: 17786d36773SIgor Russkikh case MPI_POWER: 17886d36773SIgor Russkikh /* No actions */ 17986d36773SIgor Russkikh break; 18086d36773SIgor Russkikh } 18186d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); 18286d36773SIgor Russkikh return 0; 18386d36773SIgor Russkikh } 18486d36773SIgor Russkikh 18586d36773SIgor Russkikh static int aq_fw2x_update_link_status(struct aq_hw_s *self) 18686d36773SIgor Russkikh { 18786d36773SIgor Russkikh u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); 18886d36773SIgor Russkikh u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | 18986d36773SIgor Russkikh FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G); 19086d36773SIgor Russkikh struct aq_hw_link_status_s *link_status = &self->aq_link_status; 19186d36773SIgor Russkikh 19286d36773SIgor Russkikh if (speed) { 19386d36773SIgor Russkikh if (speed & FW2X_RATE_10G) 19486d36773SIgor Russkikh link_status->mbps = 10000; 19586d36773SIgor Russkikh else if (speed & FW2X_RATE_5G) 19686d36773SIgor Russkikh link_status->mbps = 5000; 19786d36773SIgor Russkikh else if (speed & FW2X_RATE_2G5) 19886d36773SIgor Russkikh link_status->mbps = 2500; 19986d36773SIgor Russkikh else if (speed & FW2X_RATE_1G) 20086d36773SIgor Russkikh link_status->mbps = 1000; 20186d36773SIgor Russkikh else if (speed & FW2X_RATE_100M) 20286d36773SIgor Russkikh link_status->mbps = 100; 20386d36773SIgor Russkikh else 20486d36773SIgor Russkikh link_status->mbps = 10000; 20586d36773SIgor Russkikh } else { 20686d36773SIgor Russkikh link_status->mbps = 0; 20786d36773SIgor Russkikh } 20886d36773SIgor Russkikh 20986d36773SIgor Russkikh return 0; 21086d36773SIgor Russkikh } 21186d36773SIgor Russkikh 21286d36773SIgor Russkikh static 21386d36773SIgor Russkikh int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) 21486d36773SIgor Russkikh { 21586d36773SIgor Russkikh int err = 0; 21686d36773SIgor Russkikh u32 h = 0U; 21786d36773SIgor Russkikh u32 l = 0U; 21886d36773SIgor Russkikh u32 mac_addr[2] = { 0 }; 21986d36773SIgor Russkikh u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); 22086d36773SIgor Russkikh 221e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 222e9924638SPavel Belous 22386d36773SIgor Russkikh if (efuse_addr != 0) { 22486d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, 22586d36773SIgor Russkikh efuse_addr + (40U * 4U), 22686d36773SIgor Russkikh mac_addr, 22786d36773SIgor Russkikh ARRAY_SIZE(mac_addr)); 22886d36773SIgor Russkikh if (err) 229e9924638SPavel Belous goto exit; 23086d36773SIgor Russkikh mac_addr[0] = rte_constant_bswap32(mac_addr[0]); 23186d36773SIgor Russkikh mac_addr[1] = rte_constant_bswap32(mac_addr[1]); 23286d36773SIgor Russkikh } 23386d36773SIgor Russkikh 234538da7a1SOlivier Matz rte_ether_addr_copy((struct rte_ether_addr *)mac_addr, 2356d13ea8eSOlivier Matz (struct rte_ether_addr *)mac); 23686d36773SIgor Russkikh 23786d36773SIgor Russkikh if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { 23886d36773SIgor Russkikh unsigned int rnd = (uint32_t)rte_rand(); 23986d36773SIgor Russkikh 24086d36773SIgor Russkikh //get_random_bytes(&rnd, sizeof(unsigned int)); 24186d36773SIgor Russkikh 24286d36773SIgor Russkikh l = 0xE3000000U 24386d36773SIgor Russkikh | (0xFFFFU & rnd) 24486d36773SIgor Russkikh | (0x00 << 16); 24586d36773SIgor Russkikh h = 0x8001300EU; 24686d36773SIgor Russkikh 24786d36773SIgor Russkikh mac[5] = (u8)(0xFFU & l); 24886d36773SIgor Russkikh l >>= 8; 24986d36773SIgor Russkikh mac[4] = (u8)(0xFFU & l); 25086d36773SIgor Russkikh l >>= 8; 25186d36773SIgor Russkikh mac[3] = (u8)(0xFFU & l); 25286d36773SIgor Russkikh l >>= 8; 25386d36773SIgor Russkikh mac[2] = (u8)(0xFFU & l); 25486d36773SIgor Russkikh mac[1] = (u8)(0xFFU & h); 25586d36773SIgor Russkikh h >>= 8; 25686d36773SIgor Russkikh mac[0] = (u8)(0xFFU & h); 25786d36773SIgor Russkikh } 258e9924638SPavel Belous 259e9924638SPavel Belous exit: 260e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 261e9924638SPavel Belous 26286d36773SIgor Russkikh return err; 26386d36773SIgor Russkikh } 26486d36773SIgor Russkikh 26586d36773SIgor Russkikh static int aq_fw2x_update_stats(struct aq_hw_s *self) 26686d36773SIgor Russkikh { 26786d36773SIgor Russkikh int err = 0; 26886d36773SIgor Russkikh u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 26986d36773SIgor Russkikh u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); 27086d36773SIgor Russkikh 271e9924638SPavel Belous 272e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 273e9924638SPavel Belous 27486d36773SIgor Russkikh /* Toggle statistics bit for FW to update */ 27586d36773SIgor Russkikh mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); 27686d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 27786d36773SIgor Russkikh 27886d36773SIgor Russkikh /* Wait FW to report back */ 27986d36773SIgor Russkikh AQ_HW_WAIT_FOR(orig_stats_val != 28086d36773SIgor Russkikh (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & 28186d36773SIgor Russkikh BIT(CAPS_HI_STATISTICS)), 28286d36773SIgor Russkikh 1U, 10000U); 28386d36773SIgor Russkikh if (err) 284e9924638SPavel Belous goto exit; 285e9924638SPavel Belous 286e9924638SPavel Belous err = hw_atl_utils_update_stats(self); 287e9924638SPavel Belous 288e9924638SPavel Belous exit: 289e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 290e9924638SPavel Belous 29186d36773SIgor Russkikh return err; 29286d36773SIgor Russkikh 29386d36773SIgor Russkikh } 29486d36773SIgor Russkikh 29586d36773SIgor Russkikh static int aq_fw2x_get_temp(struct aq_hw_s *self, int *temp) 29686d36773SIgor Russkikh { 29786d36773SIgor Russkikh int err = 0; 29886d36773SIgor Russkikh u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 29986d36773SIgor Russkikh u32 temp_val = mpi_opts & BIT(CAPS_HI_TEMPERATURE); 30086d36773SIgor Russkikh u32 temp_res; 30186d36773SIgor Russkikh 302e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 303e9924638SPavel Belous 30486d36773SIgor Russkikh /* Toggle statistics bit for FW to 0x36C.18 (CAPS_HI_TEMPERATURE) */ 30586d36773SIgor Russkikh mpi_opts = mpi_opts ^ BIT(CAPS_HI_TEMPERATURE); 30686d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 30786d36773SIgor Russkikh 30886d36773SIgor Russkikh /* Wait FW to report back */ 30986d36773SIgor Russkikh AQ_HW_WAIT_FOR(temp_val != 31086d36773SIgor Russkikh (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & 31186d36773SIgor Russkikh BIT(CAPS_HI_TEMPERATURE)), 1U, 10000U); 31286d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, 31386d36773SIgor Russkikh self->mbox_addr + 31486d36773SIgor Russkikh offsetof(struct hw_aq_atl_utils_mbox, info) + 31586d36773SIgor Russkikh offsetof(struct hw_aq_info, phy_temperature), 31686d36773SIgor Russkikh &temp_res, 31786d36773SIgor Russkikh sizeof(temp_res) / sizeof(u32)); 31886d36773SIgor Russkikh 319e9924638SPavel Belous 320e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 321e9924638SPavel Belous 32286d36773SIgor Russkikh if (err) 32386d36773SIgor Russkikh return err; 32486d36773SIgor Russkikh 32586d36773SIgor Russkikh *temp = temp_res * 100 / 256; 32686d36773SIgor Russkikh return 0; 32786d36773SIgor Russkikh } 32886d36773SIgor Russkikh 32986d36773SIgor Russkikh static int aq_fw2x_get_cable_len(struct aq_hw_s *self, int *cable_len) 33086d36773SIgor Russkikh { 33186d36773SIgor Russkikh int err = 0; 33286d36773SIgor Russkikh u32 cable_len_res; 33386d36773SIgor Russkikh 33486d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, 33586d36773SIgor Russkikh self->mbox_addr + 33686d36773SIgor Russkikh offsetof(struct hw_aq_atl_utils_mbox, info) + 33786d36773SIgor Russkikh offsetof(struct hw_aq_info, phy_temperature), 33886d36773SIgor Russkikh &cable_len_res, 33986d36773SIgor Russkikh sizeof(cable_len_res) / sizeof(u32)); 34086d36773SIgor Russkikh 34186d36773SIgor Russkikh if (err) 34286d36773SIgor Russkikh return err; 34386d36773SIgor Russkikh 34486d36773SIgor Russkikh *cable_len = (cable_len_res >> 16) & 0xFF; 34586d36773SIgor Russkikh return 0; 34686d36773SIgor Russkikh } 34786d36773SIgor Russkikh 34886d36773SIgor Russkikh #ifndef ETH_ALEN 34986d36773SIgor Russkikh #define ETH_ALEN 6 35086d36773SIgor Russkikh #endif 35186d36773SIgor Russkikh 35286d36773SIgor Russkikh static int aq_fw2x_set_sleep_proxy(struct aq_hw_s *self, u8 *mac) 35386d36773SIgor Russkikh { 35486d36773SIgor Russkikh int err = 0; 35586d36773SIgor Russkikh struct hw_aq_atl_utils_fw_rpc *rpc = NULL; 35686d36773SIgor Russkikh struct offload_info *cfg = NULL; 35786d36773SIgor Russkikh unsigned int rpc_size = 0U; 35886d36773SIgor Russkikh u32 mpi_opts; 35986d36773SIgor Russkikh 36086d36773SIgor Russkikh rpc_size = sizeof(rpc->msg_id) + sizeof(*cfg); 36186d36773SIgor Russkikh 36286d36773SIgor Russkikh err = hw_atl_utils_fw_rpc_wait(self, &rpc); 36386d36773SIgor Russkikh if (err < 0) 36486d36773SIgor Russkikh goto err_exit; 36586d36773SIgor Russkikh 36686d36773SIgor Russkikh memset(rpc, 0, rpc_size); 36786d36773SIgor Russkikh cfg = (struct offload_info *)(&rpc->msg_id + 1); 36886d36773SIgor Russkikh 36986d36773SIgor Russkikh memcpy(cfg->mac_addr, mac, ETH_ALEN); 37086d36773SIgor Russkikh cfg->len = sizeof(*cfg); 37186d36773SIgor Russkikh 37286d36773SIgor Russkikh /* Clear bit 0x36C.23 */ 37386d36773SIgor Russkikh mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 37486d36773SIgor Russkikh mpi_opts &= ~HW_ATL_FW2X_CAP_SLEEP_PROXY; 37586d36773SIgor Russkikh 37686d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 37786d36773SIgor Russkikh 37886d36773SIgor Russkikh err = hw_atl_utils_fw_rpc_call(self, rpc_size); 37986d36773SIgor Russkikh if (err < 0) 38086d36773SIgor Russkikh goto err_exit; 38186d36773SIgor Russkikh 38286d36773SIgor Russkikh /* Set bit 0x36C.23 */ 38386d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_SLEEP_PROXY; 38486d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 38586d36773SIgor Russkikh 38686d36773SIgor Russkikh AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & 38786d36773SIgor Russkikh HW_ATL_FW2X_CAP_SLEEP_PROXY), 1U, 10000U); 38886d36773SIgor Russkikh err_exit: 38986d36773SIgor Russkikh return err; 39086d36773SIgor Russkikh } 39186d36773SIgor Russkikh 39286d36773SIgor Russkikh static int aq_fw2x_set_wol_params(struct aq_hw_s *self, u8 *mac) 39386d36773SIgor Russkikh { 39486d36773SIgor Russkikh int err = 0; 39586d36773SIgor Russkikh struct fw2x_msg_wol *msg = NULL; 39686d36773SIgor Russkikh u32 mpi_opts; 39786d36773SIgor Russkikh 39886d36773SIgor Russkikh struct hw_aq_atl_utils_fw_rpc *rpc = NULL; 39986d36773SIgor Russkikh 40086d36773SIgor Russkikh err = hw_atl_utils_fw_rpc_wait(self, &rpc); 40186d36773SIgor Russkikh if (err < 0) 40286d36773SIgor Russkikh goto err_exit; 40386d36773SIgor Russkikh 40486d36773SIgor Russkikh msg = (struct fw2x_msg_wol *)rpc; 40586d36773SIgor Russkikh 40686d36773SIgor Russkikh msg->msg_id = HAL_ATLANTIC_UTILS_FW2X_MSG_WOL; 40786d36773SIgor Russkikh msg->magic_packet_enabled = true; 40886d36773SIgor Russkikh memcpy(msg->hw_addr, mac, ETH_ALEN); 40986d36773SIgor Russkikh 41086d36773SIgor Russkikh mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 41186d36773SIgor Russkikh mpi_opts &= ~(HW_ATL_FW2X_CAP_SLEEP_PROXY | HW_ATL_FW2X_CAP_WOL); 41286d36773SIgor Russkikh 41386d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 41486d36773SIgor Russkikh 41586d36773SIgor Russkikh err = hw_atl_utils_fw_rpc_call(self, sizeof(*msg)); 41686d36773SIgor Russkikh if (err < 0) 41786d36773SIgor Russkikh goto err_exit; 41886d36773SIgor Russkikh 41986d36773SIgor Russkikh /* Set bit 0x36C.24 */ 42086d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_WOL; 42186d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 42286d36773SIgor Russkikh 42386d36773SIgor Russkikh AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & 42486d36773SIgor Russkikh HW_ATL_FW2X_CAP_WOL), 1U, 10000U); 42586d36773SIgor Russkikh err_exit: 42686d36773SIgor Russkikh return err; 42786d36773SIgor Russkikh } 42886d36773SIgor Russkikh 42986d36773SIgor Russkikh static int aq_fw2x_set_power(struct aq_hw_s *self, 43086d36773SIgor Russkikh unsigned int power_state __rte_unused, 43186d36773SIgor Russkikh u8 *mac) 43286d36773SIgor Russkikh { 43386d36773SIgor Russkikh int err = 0; 43486d36773SIgor Russkikh 43586d36773SIgor Russkikh if (self->aq_nic_cfg->wol & AQ_NIC_WOL_ENABLED) { 43686d36773SIgor Russkikh err = aq_fw2x_set_sleep_proxy(self, mac); 43786d36773SIgor Russkikh if (err < 0) 43886d36773SIgor Russkikh goto err_exit; 43986d36773SIgor Russkikh err = aq_fw2x_set_wol_params(self, mac); 44086d36773SIgor Russkikh if (err < 0) 44186d36773SIgor Russkikh goto err_exit; 44286d36773SIgor Russkikh } 44386d36773SIgor Russkikh err_exit: 44486d36773SIgor Russkikh return err; 44586d36773SIgor Russkikh } 44686d36773SIgor Russkikh 44786d36773SIgor Russkikh static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) 44886d36773SIgor Russkikh { 44986d36773SIgor Russkikh u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 45086d36773SIgor Russkikh mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK | 45186d36773SIgor Russkikh HW_ATL_FW2X_CAP_EEE_2G5_MASK | HW_ATL_FW2X_CAP_EEE_5G_MASK | 45286d36773SIgor Russkikh HW_ATL_FW2X_CAP_EEE_10G_MASK); 45386d36773SIgor Russkikh 45486d36773SIgor Russkikh if (speed & AQ_NIC_RATE_EEE_10G) 45586d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_EEE_10G_MASK; 45686d36773SIgor Russkikh 45786d36773SIgor Russkikh if (speed & AQ_NIC_RATE_EEE_5G) 45886d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_EEE_5G_MASK; 45986d36773SIgor Russkikh 46086d36773SIgor Russkikh if (speed & AQ_NIC_RATE_EEE_2G5) 46186d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_EEE_2G5_MASK; 46286d36773SIgor Russkikh 46386d36773SIgor Russkikh if (speed & AQ_NIC_RATE_EEE_1G) 46486d36773SIgor Russkikh mpi_opts |= HW_ATL_FW2X_CAP_EEE_1G_MASK; 46586d36773SIgor Russkikh 46686d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 46786d36773SIgor Russkikh 46886d36773SIgor Russkikh return 0; 46986d36773SIgor Russkikh } 47086d36773SIgor Russkikh 47186d36773SIgor Russkikh static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, 47286d36773SIgor Russkikh u32 *supported_rates) 47386d36773SIgor Russkikh { 47486d36773SIgor Russkikh int err = 0; 47586d36773SIgor Russkikh u32 caps_hi; 47686d36773SIgor Russkikh u32 mpi_state; 47786d36773SIgor Russkikh 47886d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, 47986d36773SIgor Russkikh self->mbox_addr + 48086d36773SIgor Russkikh offsetof(struct hw_aq_atl_utils_mbox, info) + 48186d36773SIgor Russkikh offsetof(struct hw_aq_info, caps_hi), 48286d36773SIgor Russkikh &caps_hi, 48386d36773SIgor Russkikh sizeof(caps_hi) / sizeof(u32)); 48486d36773SIgor Russkikh 48586d36773SIgor Russkikh if (err) 48686d36773SIgor Russkikh return err; 48786d36773SIgor Russkikh 48886d36773SIgor Russkikh *supported_rates = fw2x_to_eee_mask(caps_hi); 48986d36773SIgor Russkikh 49086d36773SIgor Russkikh mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); 49186d36773SIgor Russkikh *rate = fw2x_to_eee_mask(mpi_state); 49286d36773SIgor Russkikh 49386d36773SIgor Russkikh return err; 49486d36773SIgor Russkikh } 49586d36773SIgor Russkikh 496921eb6b8SPavel Belous static int aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fc) 497921eb6b8SPavel Belous { 498921eb6b8SPavel Belous u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 49986d36773SIgor Russkikh 500921eb6b8SPavel Belous *fc = ((mpi_state & BIT(CAPS_HI_PAUSE)) ? AQ_NIC_FC_RX : 0) | 501921eb6b8SPavel Belous ((mpi_state & BIT(CAPS_HI_ASYMMETRIC_PAUSE)) ? AQ_NIC_FC_TX : 0); 502921eb6b8SPavel Belous 503921eb6b8SPavel Belous return 0; 504921eb6b8SPavel Belous } 50586d36773SIgor Russkikh 50686d36773SIgor Russkikh static int aq_fw2x_set_flow_control(struct aq_hw_s *self) 50786d36773SIgor Russkikh { 50886d36773SIgor Russkikh u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 50986d36773SIgor Russkikh 51086d36773SIgor Russkikh aq_fw2x_set_mpi_flow_control(self, &mpi_state); 51186d36773SIgor Russkikh 51286d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); 51386d36773SIgor Russkikh 51486d36773SIgor Russkikh return 0; 51586d36773SIgor Russkikh } 51686d36773SIgor Russkikh 51786d36773SIgor Russkikh static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) 51886d36773SIgor Russkikh { 51986d36773SIgor Russkikh if (self->fw_ver_actual < HW_ATL_FW_FEATURE_LED) 52086d36773SIgor Russkikh return -EOPNOTSUPP; 52186d36773SIgor Russkikh 52286d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode); 52386d36773SIgor Russkikh return 0; 52486d36773SIgor Russkikh } 52586d36773SIgor Russkikh 526f73061d5SPavel Belous static int aq_fw2x_get_eeprom(struct aq_hw_s *self, int dev_addr, 527f73061d5SPavel Belous u32 *data, u32 len, u32 offset) 52886d36773SIgor Russkikh { 52905d5b1d6SPavel Belous u32 bytes_remains = len % sizeof(u32); 53005d5b1d6SPavel Belous u32 num_dwords = len / sizeof(u32); 53105d5b1d6SPavel Belous struct smbus_request request; 53286d36773SIgor Russkikh u32 result = 0; 53305d5b1d6SPavel Belous u32 mpi_opts; 53405d5b1d6SPavel Belous int err = 0; 53586d36773SIgor Russkikh 5363d19de22SPavel Belous if ((self->caps_lo & BIT(CAPS_LO_SMBUS_READ)) == 0) 53786d36773SIgor Russkikh return -EOPNOTSUPP; 53886d36773SIgor Russkikh 539e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 540e9924638SPavel Belous 54105d5b1d6SPavel Belous request.msg_id = 0; 542f73061d5SPavel Belous request.device_id = dev_addr; 543f73061d5SPavel Belous request.address = offset; 54486d36773SIgor Russkikh request.length = len; 54586d36773SIgor Russkikh 54686d36773SIgor Russkikh /* Write SMBUS request to cfg memory */ 54786d36773SIgor Russkikh err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, 54886d36773SIgor Russkikh (u32 *)(void *)&request, 549e09a7beeSPavel Belous sizeof(request) / sizeof(u32)); 55086d36773SIgor Russkikh 55186d36773SIgor Russkikh if (err < 0) 552e9924638SPavel Belous goto exit; 55386d36773SIgor Russkikh 554f73061d5SPavel Belous /* Toggle 0x368.CAPS_LO_SMBUS_READ bit */ 55586d36773SIgor Russkikh mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); 556f73061d5SPavel Belous mpi_opts ^= BIT(CAPS_LO_SMBUS_READ); 55786d36773SIgor Russkikh 55886d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts); 55986d36773SIgor Russkikh 56086d36773SIgor Russkikh /* Wait until REQUEST_BIT matched in 0x370 */ 56186d36773SIgor Russkikh 56286d36773SIgor Russkikh AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) & 563f73061d5SPavel Belous BIT(CAPS_LO_SMBUS_READ)) == (mpi_opts & BIT(CAPS_LO_SMBUS_READ)), 56486d36773SIgor Russkikh 10U, 10000U); 56586d36773SIgor Russkikh 56686d36773SIgor Russkikh if (err < 0) 567e9924638SPavel Belous goto exit; 56886d36773SIgor Russkikh 56986d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32), 57086d36773SIgor Russkikh &result, 571e09a7beeSPavel Belous sizeof(result) / sizeof(u32)); 57286d36773SIgor Russkikh 57386d36773SIgor Russkikh if (err < 0) 574e9924638SPavel Belous goto exit; 57586d36773SIgor Russkikh 576e9924638SPavel Belous if (result) { 577e9924638SPavel Belous err = -EIO; 578e9924638SPavel Belous goto exit; 579e9924638SPavel Belous } 580d940a707SPavel Belous 581d940a707SPavel Belous if (num_dwords) { 58286d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, 58386d36773SIgor Russkikh self->rpc_addr + sizeof(u32) * 2, 58486d36773SIgor Russkikh data, 585d940a707SPavel Belous num_dwords); 58686d36773SIgor Russkikh 58786d36773SIgor Russkikh if (err < 0) 588e9924638SPavel Belous goto exit; 58986d36773SIgor Russkikh } 59086d36773SIgor Russkikh 591d940a707SPavel Belous if (bytes_remains) { 592d940a707SPavel Belous u32 val = 0; 593d940a707SPavel Belous 594d940a707SPavel Belous err = hw_atl_utils_fw_downld_dwords(self, 59505d5b1d6SPavel Belous self->rpc_addr + (sizeof(u32) * 2) + 59605d5b1d6SPavel Belous (num_dwords * sizeof(u32)), 597d940a707SPavel Belous &val, 59805d5b1d6SPavel Belous 1); 599d940a707SPavel Belous 600d940a707SPavel Belous if (err < 0) 601e9924638SPavel Belous goto exit; 602d940a707SPavel Belous 603d940a707SPavel Belous rte_memcpy((u8 *)data + len - bytes_remains, 604d940a707SPavel Belous &val, bytes_remains); 605d940a707SPavel Belous } 606d940a707SPavel Belous 607e9924638SPavel Belous exit: 608e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 609e9924638SPavel Belous 610e9924638SPavel Belous return err; 61186d36773SIgor Russkikh } 61286d36773SIgor Russkikh 61386d36773SIgor Russkikh 614f73061d5SPavel Belous static int aq_fw2x_set_eeprom(struct aq_hw_s *self, int dev_addr, 61505d5b1d6SPavel Belous u32 *data, u32 len, u32 offset) 61686d36773SIgor Russkikh { 61705d5b1d6SPavel Belous struct smbus_request request; 61886d36773SIgor Russkikh u32 mpi_opts, result = 0; 61986d36773SIgor Russkikh int err = 0; 62086d36773SIgor Russkikh 6213d19de22SPavel Belous if ((self->caps_lo & BIT(CAPS_LO_SMBUS_WRITE)) == 0) 62286d36773SIgor Russkikh return -EOPNOTSUPP; 62386d36773SIgor Russkikh 62405d5b1d6SPavel Belous request.msg_id = 0; 625f73061d5SPavel Belous request.device_id = dev_addr; 62605d5b1d6SPavel Belous request.address = offset; 62786d36773SIgor Russkikh request.length = len; 62886d36773SIgor Russkikh 629e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 630e9924638SPavel Belous 63186d36773SIgor Russkikh /* Write SMBUS request to cfg memory */ 63286d36773SIgor Russkikh err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, 63386d36773SIgor Russkikh (u32 *)(void *)&request, 634e09a7beeSPavel Belous sizeof(request) / sizeof(u32)); 63586d36773SIgor Russkikh 63686d36773SIgor Russkikh if (err < 0) 637e9924638SPavel Belous goto exit; 63886d36773SIgor Russkikh 63986d36773SIgor Russkikh /* Write SMBUS data to cfg memory */ 64005d5b1d6SPavel Belous u32 num_dwords = len / sizeof(u32); 64105d5b1d6SPavel Belous u32 bytes_remains = len % sizeof(u32); 64205d5b1d6SPavel Belous 64305d5b1d6SPavel Belous if (num_dwords) { 64486d36773SIgor Russkikh err = hw_atl_utils_fw_upload_dwords(self, 64586d36773SIgor Russkikh self->rpc_addr + sizeof(request), 64686d36773SIgor Russkikh (u32 *)(void *)data, 64705d5b1d6SPavel Belous num_dwords); 64886d36773SIgor Russkikh 64986d36773SIgor Russkikh if (err < 0) 650e9924638SPavel Belous goto exit; 65105d5b1d6SPavel Belous } 65205d5b1d6SPavel Belous 65305d5b1d6SPavel Belous if (bytes_remains) { 65405d5b1d6SPavel Belous u32 val = 0; 65505d5b1d6SPavel Belous 65605d5b1d6SPavel Belous rte_memcpy(&val, (u8 *)data + (sizeof(u32) * num_dwords), 65705d5b1d6SPavel Belous bytes_remains); 65805d5b1d6SPavel Belous 65905d5b1d6SPavel Belous err = hw_atl_utils_fw_upload_dwords(self, 66005d5b1d6SPavel Belous self->rpc_addr + sizeof(request) + 66105d5b1d6SPavel Belous (num_dwords * sizeof(u32)), 66205d5b1d6SPavel Belous &val, 66305d5b1d6SPavel Belous 1); 66405d5b1d6SPavel Belous 66505d5b1d6SPavel Belous if (err < 0) 666e9924638SPavel Belous goto exit; 66705d5b1d6SPavel Belous } 66886d36773SIgor Russkikh 669f73061d5SPavel Belous /* Toggle 0x368.CAPS_LO_SMBUS_WRITE bit */ 67086d36773SIgor Russkikh mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); 671f73061d5SPavel Belous mpi_opts ^= BIT(CAPS_LO_SMBUS_WRITE); 67286d36773SIgor Russkikh 67386d36773SIgor Russkikh aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts); 67486d36773SIgor Russkikh 67586d36773SIgor Russkikh /* Wait until REQUEST_BIT matched in 0x370 */ 67686d36773SIgor Russkikh AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) & 677f73061d5SPavel Belous BIT(CAPS_LO_SMBUS_WRITE)) == (mpi_opts & BIT(CAPS_LO_SMBUS_WRITE)), 67886d36773SIgor Russkikh 10U, 10000U); 67986d36773SIgor Russkikh 68086d36773SIgor Russkikh if (err < 0) 681e9924638SPavel Belous goto exit; 68286d36773SIgor Russkikh 68386d36773SIgor Russkikh /* Read status of write operation */ 68486d36773SIgor Russkikh err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32), 68586d36773SIgor Russkikh &result, 686e09a7beeSPavel Belous sizeof(result) / sizeof(u32)); 68786d36773SIgor Russkikh 68886d36773SIgor Russkikh if (err < 0) 689e9924638SPavel Belous goto exit; 690e9924638SPavel Belous 691e9924638SPavel Belous if (result) { 692e9924638SPavel Belous err = -EIO; 693e9924638SPavel Belous goto exit; 694e9924638SPavel Belous } 695e9924638SPavel Belous 696e9924638SPavel Belous exit: 697e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 698e9924638SPavel Belous 69986d36773SIgor Russkikh return err; 70086d36773SIgor Russkikh } 70186d36773SIgor Russkikh 7022f40244bSPavel Belous static int aq_fw2x_send_macsec_request(struct aq_hw_s *self, 7032f40244bSPavel Belous struct macsec_msg_fw_request *req, 7042f40244bSPavel Belous struct macsec_msg_fw_response *response) 7052f40244bSPavel Belous { 7062f40244bSPavel Belous int err = 0; 7072f40244bSPavel Belous u32 mpi_opts = 0; 7082f40244bSPavel Belous 709e949eaa5SIgor Russkikh if (!req || !response) 7102f40244bSPavel Belous return 0; 7112f40244bSPavel Belous 7122f40244bSPavel Belous if ((self->caps_lo & BIT(CAPS_LO_MACSEC)) == 0) 7132f40244bSPavel Belous return -EOPNOTSUPP; 7142f40244bSPavel Belous 715e9924638SPavel Belous pthread_mutex_lock(&self->mbox_mutex); 716e9924638SPavel Belous 7172f40244bSPavel Belous /* Write macsec request to cfg memory */ 7182f40244bSPavel Belous err = hw_atl_utils_fw_upload_dwords(self, self->rpc_addr, 7192f40244bSPavel Belous (u32 *)(void *)req, 7202f40244bSPavel Belous RTE_ALIGN(sizeof(*req) / sizeof(u32), sizeof(u32))); 7212f40244bSPavel Belous 7222f40244bSPavel Belous if (err < 0) 723e9924638SPavel Belous goto exit; 7242f40244bSPavel Belous 7252f40244bSPavel Belous /* Toggle 0x368.CAPS_LO_MACSEC bit */ 7262f40244bSPavel Belous mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR); 7272f40244bSPavel Belous mpi_opts ^= BIT(CAPS_LO_MACSEC); 7282f40244bSPavel Belous 7292f40244bSPavel Belous aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, mpi_opts); 7302f40244bSPavel Belous 7312f40244bSPavel Belous /* Wait until REQUEST_BIT matched in 0x370 */ 7322f40244bSPavel Belous AQ_HW_WAIT_FOR((aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR) & 7332f40244bSPavel Belous BIT(CAPS_LO_MACSEC)) == (mpi_opts & BIT(CAPS_LO_MACSEC)), 7342f40244bSPavel Belous 1000U, 10000U); 7352f40244bSPavel Belous 7362f40244bSPavel Belous if (err < 0) 737e9924638SPavel Belous goto exit; 7382f40244bSPavel Belous 7392f40244bSPavel Belous /* Read status of write operation */ 7402f40244bSPavel Belous err = hw_atl_utils_fw_downld_dwords(self, self->rpc_addr + sizeof(u32), 7412f40244bSPavel Belous (u32 *)(void *)response, 7422f40244bSPavel Belous RTE_ALIGN(sizeof(*response) / sizeof(u32), sizeof(u32))); 7432f40244bSPavel Belous 744e9924638SPavel Belous exit: 745e9924638SPavel Belous pthread_mutex_unlock(&self->mbox_mutex); 746e9924638SPavel Belous 7472f40244bSPavel Belous return err; 7482f40244bSPavel Belous } 7492f40244bSPavel Belous 75086d36773SIgor Russkikh const struct aq_fw_ops aq_fw_2x_ops = { 75186d36773SIgor Russkikh .init = aq_fw2x_init, 75286d36773SIgor Russkikh .deinit = aq_fw2x_deinit, 75386d36773SIgor Russkikh .reset = NULL, 75486d36773SIgor Russkikh .get_mac_permanent = aq_fw2x_get_mac_permanent, 75586d36773SIgor Russkikh .set_link_speed = aq_fw2x_set_link_speed, 75686d36773SIgor Russkikh .set_state = aq_fw2x_set_state, 75786d36773SIgor Russkikh .update_link_status = aq_fw2x_update_link_status, 75886d36773SIgor Russkikh .update_stats = aq_fw2x_update_stats, 75986d36773SIgor Russkikh .set_power = aq_fw2x_set_power, 76086d36773SIgor Russkikh .get_temp = aq_fw2x_get_temp, 76186d36773SIgor Russkikh .get_cable_len = aq_fw2x_get_cable_len, 76286d36773SIgor Russkikh .set_eee_rate = aq_fw2x_set_eee_rate, 76386d36773SIgor Russkikh .get_eee_rate = aq_fw2x_get_eee_rate, 764921eb6b8SPavel Belous .get_flow_control = aq_fw2x_get_flow_control, 76586d36773SIgor Russkikh .set_flow_control = aq_fw2x_set_flow_control, 76686d36773SIgor Russkikh .led_control = aq_fw2x_led_control, 76786d36773SIgor Russkikh .get_eeprom = aq_fw2x_get_eeprom, 76886d36773SIgor Russkikh .set_eeprom = aq_fw2x_set_eeprom, 7692f40244bSPavel Belous .send_macsec_req = aq_fw2x_send_macsec_request, 77086d36773SIgor Russkikh }; 771