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