1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * aQuantia Corporation Network Driver 4 * Copyright (C) 2014-2019 aQuantia Corporation. All rights reserved 5 */ 6 7 /* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for 8 * Atlantic hardware abstraction layer. 9 */ 10 11 #include "../aq_hw.h" 12 #include "../aq_hw_utils.h" 13 #include "../aq_pci_func.h" 14 #include "../aq_ring.h" 15 #include "../aq_vec.h" 16 #include "../aq_nic.h" 17 #include "hw_atl_utils.h" 18 #include "hw_atl_llh.h" 19 20 #define HW_ATL_FW2X_MPI_LED_ADDR 0x31c 21 #define HW_ATL_FW2X_MPI_RPC_ADDR 0x334 22 23 #define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 24 #define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 25 #define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 26 #define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C 27 #define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 28 #define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 29 30 #define HW_ATL_FW3X_EXT_CONTROL_ADDR 0x378 31 #define HW_ATL_FW3X_EXT_STATE_ADDR 0x37c 32 33 #define HW_ATL_FW2X_CAP_PAUSE BIT(CAPS_HI_PAUSE) 34 #define HW_ATL_FW2X_CAP_ASYM_PAUSE BIT(CAPS_HI_ASYMMETRIC_PAUSE) 35 #define HW_ATL_FW2X_CAP_SLEEP_PROXY BIT(CAPS_HI_SLEEP_PROXY) 36 #define HW_ATL_FW2X_CAP_WOL BIT(CAPS_HI_WOL) 37 38 #define HW_ATL_FW2X_CTRL_WAKE_ON_LINK BIT(CTRL_WAKE_ON_LINK) 39 #define HW_ATL_FW2X_CTRL_SLEEP_PROXY BIT(CTRL_SLEEP_PROXY) 40 #define HW_ATL_FW2X_CTRL_WOL BIT(CTRL_WOL) 41 #define HW_ATL_FW2X_CTRL_LINK_DROP BIT(CTRL_LINK_DROP) 42 #define HW_ATL_FW2X_CTRL_PAUSE BIT(CTRL_PAUSE) 43 #define HW_ATL_FW2X_CTRL_TEMPERATURE BIT(CTRL_TEMPERATURE) 44 #define HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE BIT(CTRL_ASYMMETRIC_PAUSE) 45 #define HW_ATL_FW2X_CTRL_INT_LOOPBACK BIT(CTRL_INT_LOOPBACK) 46 #define HW_ATL_FW2X_CTRL_EXT_LOOPBACK BIT(CTRL_EXT_LOOPBACK) 47 #define HW_ATL_FW2X_CTRL_DOWNSHIFT BIT(CTRL_DOWNSHIFT) 48 #define HW_ATL_FW2X_CTRL_FORCE_RECONNECT BIT(CTRL_FORCE_RECONNECT) 49 50 #define HW_ATL_FW2X_CAP_EEE_1G_MASK BIT(CAPS_HI_1000BASET_FD_EEE) 51 #define HW_ATL_FW2X_CAP_EEE_2G5_MASK BIT(CAPS_HI_2P5GBASET_FD_EEE) 52 #define HW_ATL_FW2X_CAP_EEE_5G_MASK BIT(CAPS_HI_5GBASET_FD_EEE) 53 #define HW_ATL_FW2X_CAP_EEE_10G_MASK BIT(CAPS_HI_10GBASET_FD_EEE) 54 55 #define HAL_ATLANTIC_WOL_FILTERS_COUNT 8 56 #define HAL_ATLANTIC_UTILS_FW2X_MSG_WOL 0x0E 57 58 #define HW_ATL_FW_VER_LED 0x03010026U 59 #define HW_ATL_FW_VER_MEDIA_CONTROL 0x0301005aU 60 61 struct __packed fw2x_msg_wol_pattern { 62 u8 mask[16]; 63 u32 crc; 64 }; 65 66 struct __packed fw2x_msg_wol { 67 u32 msg_id; 68 u8 hw_addr[ETH_ALEN]; 69 u8 magic_packet_enabled; 70 u8 filter_count; 71 struct fw2x_msg_wol_pattern filter[HAL_ATLANTIC_WOL_FILTERS_COUNT]; 72 u8 link_up_enabled; 73 u8 link_down_enabled; 74 u16 reserved; 75 u32 link_up_timeout; 76 u32 link_down_timeout; 77 }; 78 79 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed); 80 static int aq_fw2x_set_state(struct aq_hw_s *self, 81 enum hal_atl_utils_fw_state_e state); 82 83 static u32 aq_fw2x_mbox_get(struct aq_hw_s *self); 84 static u32 aq_fw2x_rpc_get(struct aq_hw_s *self); 85 static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr); 86 static u32 aq_fw2x_state2_get(struct aq_hw_s *self); 87 88 static int aq_fw2x_init(struct aq_hw_s *self) 89 { 90 int err = 0; 91 92 /* check 10 times by 1ms */ 93 err = readx_poll_timeout_atomic(aq_fw2x_mbox_get, 94 self, self->mbox_addr, 95 self->mbox_addr != 0U, 96 1000U, 10000U); 97 98 err = readx_poll_timeout_atomic(aq_fw2x_rpc_get, 99 self, self->rpc_addr, 100 self->rpc_addr != 0U, 101 1000U, 100000U); 102 103 err = aq_fw2x_settings_get(self, &self->settings_addr); 104 105 return err; 106 } 107 108 static int aq_fw2x_deinit(struct aq_hw_s *self) 109 { 110 int err = aq_fw2x_set_link_speed(self, 0); 111 112 if (!err) 113 err = aq_fw2x_set_state(self, MPI_DEINIT); 114 115 return err; 116 } 117 118 static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) 119 { 120 enum hw_atl_fw2x_rate rate = 0; 121 122 if (speed & AQ_NIC_RATE_10G) 123 rate |= FW2X_RATE_10G; 124 125 if (speed & AQ_NIC_RATE_5G) 126 rate |= FW2X_RATE_5G; 127 128 if (speed & AQ_NIC_RATE_5GSR) 129 rate |= FW2X_RATE_5G; 130 131 if (speed & AQ_NIC_RATE_2GS) 132 rate |= FW2X_RATE_2G5; 133 134 if (speed & AQ_NIC_RATE_1G) 135 rate |= FW2X_RATE_1G; 136 137 if (speed & AQ_NIC_RATE_100M) 138 rate |= FW2X_RATE_100M; 139 140 return rate; 141 } 142 143 static u32 fw2x_to_eee_mask(u32 speed) 144 { 145 u32 rate = 0; 146 147 if (speed & HW_ATL_FW2X_CAP_EEE_10G_MASK) 148 rate |= AQ_NIC_RATE_EEE_10G; 149 if (speed & HW_ATL_FW2X_CAP_EEE_5G_MASK) 150 rate |= AQ_NIC_RATE_EEE_5G; 151 if (speed & HW_ATL_FW2X_CAP_EEE_2G5_MASK) 152 rate |= AQ_NIC_RATE_EEE_2GS; 153 if (speed & HW_ATL_FW2X_CAP_EEE_1G_MASK) 154 rate |= AQ_NIC_RATE_EEE_1G; 155 156 return rate; 157 } 158 159 static u32 eee_mask_to_fw2x(u32 speed) 160 { 161 u32 rate = 0; 162 163 if (speed & AQ_NIC_RATE_EEE_10G) 164 rate |= HW_ATL_FW2X_CAP_EEE_10G_MASK; 165 if (speed & AQ_NIC_RATE_EEE_5G) 166 rate |= HW_ATL_FW2X_CAP_EEE_5G_MASK; 167 if (speed & AQ_NIC_RATE_EEE_2GS) 168 rate |= HW_ATL_FW2X_CAP_EEE_2G5_MASK; 169 if (speed & AQ_NIC_RATE_EEE_1G) 170 rate |= HW_ATL_FW2X_CAP_EEE_1G_MASK; 171 172 return rate; 173 } 174 175 static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed) 176 { 177 u32 val = link_speed_mask_2fw2x_ratemask(speed); 178 179 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val); 180 181 return 0; 182 } 183 184 static void aq_fw2x_upd_flow_control_bits(struct aq_hw_s *self, 185 u32 *mpi_state, u32 fc) 186 { 187 *mpi_state &= ~(HW_ATL_FW2X_CTRL_PAUSE | 188 HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE); 189 190 switch (fc) { 191 /* There is not explicit mode of RX only pause frames, 192 * thus, we join this mode with FC full. 193 * FC full is either Rx, either Tx, or both. 194 */ 195 case AQ_NIC_FC_FULL: 196 case AQ_NIC_FC_RX: 197 *mpi_state |= HW_ATL_FW2X_CTRL_PAUSE | 198 HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; 199 break; 200 case AQ_NIC_FC_TX: 201 *mpi_state |= HW_ATL_FW2X_CTRL_ASYMMETRIC_PAUSE; 202 break; 203 } 204 } 205 206 static void aq_fw2x_upd_eee_rate_bits(struct aq_hw_s *self, u32 *mpi_opts, 207 u32 eee_speeds) 208 { 209 *mpi_opts &= ~(HW_ATL_FW2X_CAP_EEE_1G_MASK | 210 HW_ATL_FW2X_CAP_EEE_2G5_MASK | 211 HW_ATL_FW2X_CAP_EEE_5G_MASK | 212 HW_ATL_FW2X_CAP_EEE_10G_MASK); 213 214 *mpi_opts |= eee_mask_to_fw2x(eee_speeds); 215 } 216 217 static int aq_fw2x_set_state(struct aq_hw_s *self, 218 enum hal_atl_utils_fw_state_e state) 219 { 220 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 221 struct aq_nic_cfg_s *cfg = self->aq_nic_cfg; 222 223 switch (state) { 224 case MPI_INIT: 225 mpi_state &= ~BIT(CAPS_HI_LINK_DROP); 226 aq_fw2x_upd_eee_rate_bits(self, &mpi_state, cfg->eee_speeds); 227 aq_fw2x_upd_flow_control_bits(self, &mpi_state, 228 self->aq_nic_cfg->fc.req); 229 break; 230 case MPI_DEINIT: 231 mpi_state |= BIT(CAPS_HI_LINK_DROP); 232 break; 233 case MPI_RESET: 234 case MPI_POWER: 235 /* No actions */ 236 break; 237 } 238 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); 239 240 return 0; 241 } 242 243 static int aq_fw2x_update_link_status(struct aq_hw_s *self) 244 { 245 struct aq_hw_link_status_s *link_status = &self->aq_link_status; 246 u32 mpi_state; 247 u32 speed; 248 249 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); 250 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | 251 FW2X_RATE_2G5 | FW2X_RATE_5G | 252 FW2X_RATE_10G); 253 254 if (speed) { 255 if (speed & FW2X_RATE_10G) 256 link_status->mbps = 10000; 257 else if (speed & FW2X_RATE_5G) 258 link_status->mbps = 5000; 259 else if (speed & FW2X_RATE_2G5) 260 link_status->mbps = 2500; 261 else if (speed & FW2X_RATE_1G) 262 link_status->mbps = 1000; 263 else if (speed & FW2X_RATE_100M) 264 link_status->mbps = 100; 265 else 266 link_status->mbps = 10000; 267 } else { 268 link_status->mbps = 0; 269 } 270 271 return 0; 272 } 273 274 static int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) 275 { 276 u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); 277 u32 mac_addr[2] = { 0 }; 278 int err = 0; 279 u32 h = 0U; 280 u32 l = 0U; 281 282 if (efuse_addr != 0) { 283 err = hw_atl_utils_fw_downld_dwords(self, 284 efuse_addr + (40U * 4U), 285 mac_addr, 286 ARRAY_SIZE(mac_addr)); 287 if (err) 288 return err; 289 mac_addr[0] = __swab32(mac_addr[0]); 290 mac_addr[1] = __swab32(mac_addr[1]); 291 } 292 293 ether_addr_copy(mac, (u8 *)mac_addr); 294 295 if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { 296 unsigned int rnd = 0; 297 298 get_random_bytes(&rnd, sizeof(unsigned int)); 299 300 l = 0xE3000000U | (0xFFFFU & rnd) | (0x00 << 16); 301 h = 0x8001300EU; 302 303 mac[5] = (u8)(0xFFU & l); 304 l >>= 8; 305 mac[4] = (u8)(0xFFU & l); 306 l >>= 8; 307 mac[3] = (u8)(0xFFU & l); 308 l >>= 8; 309 mac[2] = (u8)(0xFFU & l); 310 mac[1] = (u8)(0xFFU & h); 311 h >>= 8; 312 mac[0] = (u8)(0xFFU & h); 313 } 314 315 return err; 316 } 317 318 static int aq_fw2x_update_stats(struct aq_hw_s *self) 319 { 320 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 321 u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); 322 u32 stats_val; 323 int err = 0; 324 325 /* Toggle statistics bit for FW to update */ 326 mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); 327 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 328 329 /* Wait FW to report back */ 330 err = readx_poll_timeout_atomic(aq_fw2x_state2_get, 331 self, stats_val, 332 orig_stats_val != (stats_val & 333 BIT(CAPS_HI_STATISTICS)), 334 1U, 10000U); 335 if (err) 336 return err; 337 338 return hw_atl_utils_update_stats(self); 339 } 340 341 static int aq_fw2x_get_phy_temp(struct aq_hw_s *self, int *temp) 342 { 343 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 344 u32 temp_val = mpi_opts & HW_ATL_FW2X_CTRL_TEMPERATURE; 345 u32 phy_temp_offset; 346 u32 temp_res; 347 int err = 0; 348 u32 val; 349 350 phy_temp_offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, 351 info.phy_temperature); 352 353 /* Toggle statistics bit for FW to 0x36C.18 (CTRL_TEMPERATURE) */ 354 mpi_opts = mpi_opts ^ HW_ATL_FW2X_CTRL_TEMPERATURE; 355 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 356 /* Wait FW to report back */ 357 err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, 358 temp_val != 359 (val & HW_ATL_FW2X_CTRL_TEMPERATURE), 360 1U, 10000U); 361 err = hw_atl_utils_fw_downld_dwords(self, phy_temp_offset, 362 &temp_res, 1); 363 364 if (err) 365 return err; 366 367 /* Convert PHY temperature from 1/256 degree Celsius 368 * to 1/1000 degree Celsius. 369 */ 370 *temp = (temp_res & 0xFFFF) * 1000 / 256; 371 372 return 0; 373 } 374 375 static int aq_fw2x_set_wol(struct aq_hw_s *self, u8 *mac) 376 { 377 struct hw_atl_utils_fw_rpc *rpc = NULL; 378 struct offload_info *info = NULL; 379 u32 wol_bits = 0; 380 u32 rpc_size; 381 int err = 0; 382 u32 val; 383 384 if (self->aq_nic_cfg->wol & WAKE_PHY) { 385 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, 386 HW_ATL_FW2X_CTRL_LINK_DROP); 387 readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, 388 (val & 389 HW_ATL_FW2X_CTRL_LINK_DROP) != 0, 390 1000, 100000); 391 wol_bits |= HW_ATL_FW2X_CTRL_WAKE_ON_LINK; 392 } 393 394 if (self->aq_nic_cfg->wol & WAKE_MAGIC) { 395 wol_bits |= HW_ATL_FW2X_CTRL_SLEEP_PROXY | 396 HW_ATL_FW2X_CTRL_WOL; 397 398 err = hw_atl_utils_fw_rpc_wait(self, &rpc); 399 if (err < 0) 400 goto err_exit; 401 402 rpc_size = sizeof(*info) + 403 offsetof(struct hw_atl_utils_fw_rpc, fw2x_offloads); 404 memset(rpc, 0, rpc_size); 405 info = &rpc->fw2x_offloads; 406 memcpy(info->mac_addr, mac, ETH_ALEN); 407 info->len = sizeof(*info); 408 409 err = hw_atl_utils_fw_rpc_call(self, rpc_size); 410 if (err < 0) 411 goto err_exit; 412 } 413 414 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, wol_bits); 415 416 err_exit: 417 return err; 418 } 419 420 static int aq_fw2x_set_power(struct aq_hw_s *self, unsigned int power_state, 421 u8 *mac) 422 { 423 int err = 0; 424 425 if (self->aq_nic_cfg->wol) 426 err = aq_fw2x_set_wol(self, mac); 427 428 return err; 429 } 430 431 static int aq_fw2x_send_fw_request(struct aq_hw_s *self, 432 const struct hw_fw_request_iface *fw_req, 433 size_t size) 434 { 435 u32 ctrl2, orig_ctrl2; 436 u32 dword_cnt; 437 int err = 0; 438 u32 val; 439 440 /* Write data to drvIface Mailbox */ 441 dword_cnt = size / sizeof(u32); 442 if (size % sizeof(u32)) 443 dword_cnt++; 444 err = hw_atl_write_fwcfg_dwords(self, (void *)fw_req, dword_cnt); 445 if (err < 0) 446 goto err_exit; 447 448 /* Toggle statistics bit for FW to update */ 449 ctrl2 = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 450 orig_ctrl2 = ctrl2 & BIT(CAPS_HI_FW_REQUEST); 451 ctrl2 = ctrl2 ^ BIT(CAPS_HI_FW_REQUEST); 452 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, ctrl2); 453 454 /* Wait FW to report back */ 455 err = readx_poll_timeout_atomic(aq_fw2x_state2_get, self, val, 456 orig_ctrl2 != (val & 457 BIT(CAPS_HI_FW_REQUEST)), 458 1U, 10000U); 459 460 err_exit: 461 return err; 462 } 463 464 static void aq_fw3x_enable_ptp(struct aq_hw_s *self, int enable) 465 { 466 u32 ptp_opts = aq_hw_read_reg(self, HW_ATL_FW3X_EXT_STATE_ADDR); 467 u32 all_ptp_features = BIT(CAPS_EX_PHY_PTP_EN) | 468 BIT(CAPS_EX_PTP_GPIO_EN); 469 470 if (enable) 471 ptp_opts |= all_ptp_features; 472 else 473 ptp_opts &= ~all_ptp_features; 474 475 aq_hw_write_reg(self, HW_ATL_FW3X_EXT_CONTROL_ADDR, ptp_opts); 476 } 477 478 static int aq_fw2x_led_control(struct aq_hw_s *self, u32 mode) 479 { 480 if (self->fw_ver_actual < HW_ATL_FW_VER_LED) 481 return -EOPNOTSUPP; 482 483 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_LED_ADDR, mode); 484 485 return 0; 486 } 487 488 static int aq_fw2x_set_eee_rate(struct aq_hw_s *self, u32 speed) 489 { 490 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 491 492 aq_fw2x_upd_eee_rate_bits(self, &mpi_opts, speed); 493 494 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 495 496 return 0; 497 } 498 499 static int aq_fw2x_get_eee_rate(struct aq_hw_s *self, u32 *rate, 500 u32 *supported_rates) 501 { 502 u32 mpi_state; 503 u32 caps_hi; 504 int err = 0; 505 u32 offset; 506 507 offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, 508 info.caps_hi); 509 510 err = hw_atl_utils_fw_downld_dwords(self, offset, &caps_hi, 1); 511 512 if (err) 513 return err; 514 515 *supported_rates = fw2x_to_eee_mask(caps_hi); 516 517 mpi_state = aq_fw2x_state2_get(self); 518 *rate = fw2x_to_eee_mask(mpi_state); 519 520 return err; 521 } 522 523 static int aq_fw2x_renegotiate(struct aq_hw_s *self) 524 { 525 u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 526 527 mpi_opts |= BIT(CTRL_FORCE_RECONNECT); 528 529 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 530 531 return 0; 532 } 533 534 static int aq_fw2x_set_flow_control(struct aq_hw_s *self) 535 { 536 u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 537 538 aq_fw2x_upd_flow_control_bits(self, &mpi_state, 539 self->aq_nic_cfg->fc.req); 540 541 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_state); 542 543 return 0; 544 } 545 546 static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) 547 { 548 u32 mpi_state = aq_fw2x_state2_get(self); 549 *fcmode = 0; 550 551 if (mpi_state & HW_ATL_FW2X_CAP_PAUSE) 552 *fcmode |= AQ_NIC_FC_RX; 553 554 if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) 555 *fcmode |= AQ_NIC_FC_TX; 556 557 return 0; 558 } 559 560 static int aq_fw2x_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) 561 { 562 u32 mpi_opts; 563 564 switch (mode) { 565 case AQ_HW_LOOPBACK_PHYINT_SYS: 566 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 567 if (enable) 568 mpi_opts |= HW_ATL_FW2X_CTRL_INT_LOOPBACK; 569 else 570 mpi_opts &= ~HW_ATL_FW2X_CTRL_INT_LOOPBACK; 571 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 572 break; 573 case AQ_HW_LOOPBACK_PHYEXT_SYS: 574 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); 575 if (enable) 576 mpi_opts |= HW_ATL_FW2X_CTRL_EXT_LOOPBACK; 577 else 578 mpi_opts &= ~HW_ATL_FW2X_CTRL_EXT_LOOPBACK; 579 aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); 580 break; 581 default: 582 return -EINVAL; 583 } 584 585 return 0; 586 } 587 588 static u32 aq_fw2x_mbox_get(struct aq_hw_s *self) 589 { 590 return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR); 591 } 592 593 static u32 aq_fw2x_rpc_get(struct aq_hw_s *self) 594 { 595 return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_RPC_ADDR); 596 } 597 598 static int aq_fw2x_settings_get(struct aq_hw_s *self, u32 *addr) 599 { 600 int err = 0; 601 u32 offset; 602 603 offset = self->mbox_addr + offsetof(struct hw_atl_utils_mbox, 604 info.setting_address); 605 606 err = hw_atl_utils_fw_downld_dwords(self, offset, addr, 1); 607 608 return err; 609 } 610 611 static u32 aq_fw2x_state2_get(struct aq_hw_s *self) 612 { 613 return aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); 614 } 615 616 const struct aq_fw_ops aq_fw_2x_ops = { 617 .init = aq_fw2x_init, 618 .deinit = aq_fw2x_deinit, 619 .reset = NULL, 620 .renegotiate = aq_fw2x_renegotiate, 621 .get_mac_permanent = aq_fw2x_get_mac_permanent, 622 .set_link_speed = aq_fw2x_set_link_speed, 623 .set_state = aq_fw2x_set_state, 624 .update_link_status = aq_fw2x_update_link_status, 625 .update_stats = aq_fw2x_update_stats, 626 .get_phy_temp = aq_fw2x_get_phy_temp, 627 .set_power = aq_fw2x_set_power, 628 .set_eee_rate = aq_fw2x_set_eee_rate, 629 .get_eee_rate = aq_fw2x_get_eee_rate, 630 .set_flow_control = aq_fw2x_set_flow_control, 631 .get_flow_control = aq_fw2x_get_flow_control, 632 .send_fw_request = aq_fw2x_send_fw_request, 633 .enable_ptp = aq_fw3x_enable_ptp, 634 .led_control = aq_fw2x_led_control, 635 .set_phyloopback = aq_fw2x_set_phyloopback, 636 }; 637