1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Atlantic Network Driver 3 * Copyright (C) 2020 Marvell International Ltd. 4 */ 5 6 #include <linux/iopoll.h> 7 8 #include "aq_hw.h" 9 #include "aq_hw_utils.h" 10 #include "aq_nic.h" 11 #include "hw_atl/hw_atl_llh.h" 12 #include "hw_atl2_utils.h" 13 #include "hw_atl2_llh.h" 14 #include "hw_atl2_internal.h" 15 16 #define AQ_A2_FW_READ_TRY_MAX 1000 17 18 #define hw_atl2_shared_buffer_write(HW, ITEM, VARIABLE) \ 19 {\ 20 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \ 21 sizeof(u32)) != 0,\ 22 "Unaligned write " # ITEM);\ 23 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ 24 "Unaligned write length " # ITEM);\ 25 hw_atl2_mif_shared_buf_write(HW,\ 26 (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ 27 (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\ 28 } 29 30 #define hw_atl2_shared_buffer_get(HW, ITEM, VARIABLE) \ 31 {\ 32 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_in, ITEM) % \ 33 sizeof(u32)) != 0,\ 34 "Unaligned get " # ITEM);\ 35 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ 36 "Unaligned get length " # ITEM);\ 37 hw_atl2_mif_shared_buf_get(HW, \ 38 (offsetof(struct fw_interface_in, ITEM) / sizeof(u32)),\ 39 (u32 *)&(VARIABLE), \ 40 sizeof(VARIABLE) / sizeof(u32));\ 41 } 42 43 /* This should never be used on non atomic fields, 44 * treat any > u32 read as non atomic. 45 */ 46 #define hw_atl2_shared_buffer_read(HW, ITEM, VARIABLE) \ 47 {\ 48 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \ 49 sizeof(u32)) != 0,\ 50 "Unaligned read " # ITEM);\ 51 BUILD_BUG_ON_MSG((sizeof(VARIABLE) % sizeof(u32)) != 0,\ 52 "Unaligned read length " # ITEM);\ 53 BUILD_BUG_ON_MSG(sizeof(VARIABLE) > sizeof(u32),\ 54 "Non atomic read " # ITEM);\ 55 hw_atl2_mif_shared_buf_read(HW, \ 56 (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\ 57 (u32 *)&(VARIABLE), sizeof(VARIABLE) / sizeof(u32));\ 58 } 59 60 #define hw_atl2_shared_buffer_read_safe(HW, ITEM, DATA) \ 61 ({\ 62 BUILD_BUG_ON_MSG((offsetof(struct fw_interface_out, ITEM) % \ 63 sizeof(u32)) != 0,\ 64 "Unaligned read_safe " # ITEM);\ 65 BUILD_BUG_ON_MSG((sizeof(((struct fw_interface_out *)0)->ITEM) % \ 66 sizeof(u32)) != 0,\ 67 "Unaligned read_safe length " # ITEM);\ 68 hw_atl2_shared_buffer_read_block((HW), \ 69 (offsetof(struct fw_interface_out, ITEM) / sizeof(u32)),\ 70 sizeof(((struct fw_interface_out *)0)->ITEM) / sizeof(u32),\ 71 (DATA));\ 72 }) 73 74 static int hw_atl2_shared_buffer_read_block(struct aq_hw_s *self, 75 u32 offset, u32 dwords, void *data) 76 { 77 struct transaction_counter_s tid1, tid2; 78 int cnt = 0; 79 80 do { 81 do { 82 hw_atl2_shared_buffer_read(self, transaction_id, tid1); 83 cnt++; 84 if (cnt > AQ_A2_FW_READ_TRY_MAX) 85 return -ETIME; 86 if (tid1.transaction_cnt_a != tid1.transaction_cnt_b) 87 udelay(1); 88 } while (tid1.transaction_cnt_a != tid1.transaction_cnt_b); 89 90 hw_atl2_mif_shared_buf_read(self, offset, (u32 *)data, dwords); 91 92 hw_atl2_shared_buffer_read(self, transaction_id, tid2); 93 94 cnt++; 95 if (cnt > AQ_A2_FW_READ_TRY_MAX) 96 return -ETIME; 97 } while (tid2.transaction_cnt_a != tid2.transaction_cnt_b || 98 tid1.transaction_cnt_a != tid2.transaction_cnt_a); 99 100 return 0; 101 } 102 103 static inline int hw_atl2_shared_buffer_finish_ack(struct aq_hw_s *self) 104 { 105 u32 val; 106 int err; 107 108 hw_atl2_mif_host_finished_write_set(self, 1U); 109 err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get, 110 self, val, val == 0U, 111 100, 100000U); 112 WARN(err, "hw_atl2_shared_buffer_finish_ack"); 113 114 return err; 115 } 116 117 static int aq_a2_fw_init(struct aq_hw_s *self) 118 { 119 struct link_control_s link_control; 120 u32 mtu; 121 u32 val; 122 int err; 123 124 hw_atl2_shared_buffer_get(self, link_control, link_control); 125 link_control.mode = AQ_HOST_MODE_ACTIVE; 126 hw_atl2_shared_buffer_write(self, link_control, link_control); 127 128 hw_atl2_shared_buffer_get(self, mtu, mtu); 129 mtu = HW_ATL2_MTU_JUMBO; 130 hw_atl2_shared_buffer_write(self, mtu, mtu); 131 132 hw_atl2_mif_host_finished_write_set(self, 1U); 133 err = readx_poll_timeout_atomic(hw_atl2_mif_mcp_finished_read_get, 134 self, val, val == 0U, 135 100, 5000000U); 136 WARN(err, "hw_atl2_shared_buffer_finish_ack"); 137 138 return err; 139 } 140 141 static int aq_a2_fw_deinit(struct aq_hw_s *self) 142 { 143 struct link_control_s link_control; 144 145 hw_atl2_shared_buffer_get(self, link_control, link_control); 146 link_control.mode = AQ_HOST_MODE_SHUTDOWN; 147 hw_atl2_shared_buffer_write(self, link_control, link_control); 148 149 return hw_atl2_shared_buffer_finish_ack(self); 150 } 151 152 static void a2_link_speed_mask2fw(u32 speed, 153 struct link_options_s *link_options) 154 { 155 link_options->rate_10G = !!(speed & AQ_NIC_RATE_10G); 156 link_options->rate_5G = !!(speed & AQ_NIC_RATE_5G); 157 link_options->rate_N5G = !!(speed & AQ_NIC_RATE_5GSR); 158 link_options->rate_2P5G = !!(speed & AQ_NIC_RATE_2G5); 159 link_options->rate_N2P5G = link_options->rate_2P5G; 160 link_options->rate_1G = !!(speed & AQ_NIC_RATE_1G); 161 link_options->rate_100M = !!(speed & AQ_NIC_RATE_100M); 162 link_options->rate_10M = !!(speed & AQ_NIC_RATE_10M); 163 164 link_options->rate_1G_hd = !!(speed & AQ_NIC_RATE_1G_HALF); 165 link_options->rate_100M_hd = !!(speed & AQ_NIC_RATE_100M_HALF); 166 link_options->rate_10M_hd = !!(speed & AQ_NIC_RATE_10M_HALF); 167 } 168 169 static u32 a2_fw_dev_to_eee_mask(struct device_link_caps_s *device_link_caps) 170 { 171 u32 rate = 0; 172 173 if (device_link_caps->eee_10G) 174 rate |= AQ_NIC_RATE_EEE_10G; 175 if (device_link_caps->eee_5G) 176 rate |= AQ_NIC_RATE_EEE_5G; 177 if (device_link_caps->eee_2P5G) 178 rate |= AQ_NIC_RATE_EEE_2G5; 179 if (device_link_caps->eee_1G) 180 rate |= AQ_NIC_RATE_EEE_1G; 181 if (device_link_caps->eee_100M) 182 rate |= AQ_NIC_RATE_EEE_100M; 183 184 return rate; 185 } 186 187 static u32 a2_fw_lkp_to_mask(struct lkp_link_caps_s *lkp_link_caps) 188 { 189 u32 rate = 0; 190 191 if (lkp_link_caps->rate_10G) 192 rate |= AQ_NIC_RATE_10G; 193 if (lkp_link_caps->rate_5G) 194 rate |= AQ_NIC_RATE_5G; 195 if (lkp_link_caps->rate_N5G) 196 rate |= AQ_NIC_RATE_5GSR; 197 if (lkp_link_caps->rate_2P5G) 198 rate |= AQ_NIC_RATE_2G5; 199 if (lkp_link_caps->rate_1G) 200 rate |= AQ_NIC_RATE_1G; 201 if (lkp_link_caps->rate_1G_hd) 202 rate |= AQ_NIC_RATE_1G_HALF; 203 if (lkp_link_caps->rate_100M) 204 rate |= AQ_NIC_RATE_100M; 205 if (lkp_link_caps->rate_100M_hd) 206 rate |= AQ_NIC_RATE_100M_HALF; 207 if (lkp_link_caps->rate_10M) 208 rate |= AQ_NIC_RATE_10M; 209 if (lkp_link_caps->rate_10M_hd) 210 rate |= AQ_NIC_RATE_10M_HALF; 211 212 if (lkp_link_caps->eee_10G) 213 rate |= AQ_NIC_RATE_EEE_10G; 214 if (lkp_link_caps->eee_5G) 215 rate |= AQ_NIC_RATE_EEE_5G; 216 if (lkp_link_caps->eee_2P5G) 217 rate |= AQ_NIC_RATE_EEE_2G5; 218 if (lkp_link_caps->eee_1G) 219 rate |= AQ_NIC_RATE_EEE_1G; 220 if (lkp_link_caps->eee_100M) 221 rate |= AQ_NIC_RATE_EEE_100M; 222 223 return rate; 224 } 225 226 static int aq_a2_fw_set_link_speed(struct aq_hw_s *self, u32 speed) 227 { 228 struct link_options_s link_options; 229 230 hw_atl2_shared_buffer_get(self, link_options, link_options); 231 link_options.link_up = 1U; 232 a2_link_speed_mask2fw(speed, &link_options); 233 hw_atl2_shared_buffer_write(self, link_options, link_options); 234 235 return hw_atl2_shared_buffer_finish_ack(self); 236 } 237 238 static void aq_a2_fw_set_mpi_flow_control(struct aq_hw_s *self, 239 struct link_options_s *link_options) 240 { 241 u32 flow_control = self->aq_nic_cfg->fc.req; 242 243 link_options->pause_rx = !!(flow_control & AQ_NIC_FC_RX); 244 link_options->pause_tx = !!(flow_control & AQ_NIC_FC_TX); 245 } 246 247 static void aq_a2_fw_upd_eee_rate_bits(struct aq_hw_s *self, 248 struct link_options_s *link_options, 249 u32 eee_speeds) 250 { 251 link_options->eee_10G = !!(eee_speeds & AQ_NIC_RATE_EEE_10G); 252 link_options->eee_5G = !!(eee_speeds & AQ_NIC_RATE_EEE_5G); 253 link_options->eee_2P5G = !!(eee_speeds & AQ_NIC_RATE_EEE_2G5); 254 link_options->eee_1G = !!(eee_speeds & AQ_NIC_RATE_EEE_1G); 255 link_options->eee_100M = !!(eee_speeds & AQ_NIC_RATE_EEE_100M); 256 } 257 258 static int aq_a2_fw_set_state(struct aq_hw_s *self, 259 enum hal_atl_utils_fw_state_e state) 260 { 261 struct link_options_s link_options; 262 263 hw_atl2_shared_buffer_get(self, link_options, link_options); 264 265 switch (state) { 266 case MPI_INIT: 267 link_options.link_up = 1U; 268 aq_a2_fw_upd_eee_rate_bits(self, &link_options, 269 self->aq_nic_cfg->eee_speeds); 270 aq_a2_fw_set_mpi_flow_control(self, &link_options); 271 break; 272 case MPI_DEINIT: 273 link_options.link_up = 0U; 274 break; 275 case MPI_RESET: 276 case MPI_POWER: 277 /* No actions */ 278 break; 279 } 280 281 hw_atl2_shared_buffer_write(self, link_options, link_options); 282 283 return hw_atl2_shared_buffer_finish_ack(self); 284 } 285 286 static int aq_a2_fw_update_link_status(struct aq_hw_s *self) 287 { 288 struct lkp_link_caps_s lkp_link_caps; 289 struct link_status_s link_status; 290 291 hw_atl2_shared_buffer_read(self, link_status, link_status); 292 293 switch (link_status.link_rate) { 294 case AQ_A2_FW_LINK_RATE_10G: 295 self->aq_link_status.mbps = 10000; 296 break; 297 case AQ_A2_FW_LINK_RATE_5G: 298 self->aq_link_status.mbps = 5000; 299 break; 300 case AQ_A2_FW_LINK_RATE_2G5: 301 self->aq_link_status.mbps = 2500; 302 break; 303 case AQ_A2_FW_LINK_RATE_1G: 304 self->aq_link_status.mbps = 1000; 305 break; 306 case AQ_A2_FW_LINK_RATE_100M: 307 self->aq_link_status.mbps = 100; 308 break; 309 case AQ_A2_FW_LINK_RATE_10M: 310 self->aq_link_status.mbps = 10; 311 break; 312 default: 313 self->aq_link_status.mbps = 0; 314 } 315 self->aq_link_status.full_duplex = link_status.duplex; 316 317 hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps); 318 319 self->aq_link_status.lp_link_speed_msk = 320 a2_fw_lkp_to_mask(&lkp_link_caps); 321 self->aq_link_status.lp_flow_control = 322 ((lkp_link_caps.pause_rx) ? AQ_NIC_FC_RX : 0) | 323 ((lkp_link_caps.pause_tx) ? AQ_NIC_FC_TX : 0); 324 325 return 0; 326 } 327 328 static int aq_a2_fw_get_mac_permanent(struct aq_hw_s *self, u8 *mac) 329 { 330 struct mac_address_aligned_s mac_address; 331 332 hw_atl2_shared_buffer_get(self, mac_address, mac_address); 333 ether_addr_copy(mac, (u8 *)mac_address.aligned.mac_address); 334 335 return 0; 336 } 337 338 static int aq_a2_fw_update_stats(struct aq_hw_s *self) 339 { 340 struct hw_atl2_priv *priv = (struct hw_atl2_priv *)self->priv; 341 struct statistics_s stats; 342 343 hw_atl2_shared_buffer_read_safe(self, stats, &stats); 344 345 #define AQ_SDELTA(_N_, _F_) (self->curr_stats._N_ += \ 346 stats.msm._F_ - priv->last_stats.msm._F_) 347 348 if (self->aq_link_status.mbps) { 349 AQ_SDELTA(uprc, rx_unicast_frames); 350 AQ_SDELTA(mprc, rx_multicast_frames); 351 AQ_SDELTA(bprc, rx_broadcast_frames); 352 AQ_SDELTA(erpr, rx_error_frames); 353 354 AQ_SDELTA(uptc, tx_unicast_frames); 355 AQ_SDELTA(mptc, tx_multicast_frames); 356 AQ_SDELTA(bptc, tx_broadcast_frames); 357 AQ_SDELTA(erpt, tx_errors); 358 359 AQ_SDELTA(ubrc, rx_unicast_octets); 360 AQ_SDELTA(ubtc, tx_unicast_octets); 361 AQ_SDELTA(mbrc, rx_multicast_octets); 362 AQ_SDELTA(mbtc, tx_multicast_octets); 363 AQ_SDELTA(bbrc, rx_broadcast_octets); 364 AQ_SDELTA(bbtc, tx_broadcast_octets); 365 } 366 #undef AQ_SDELTA 367 self->curr_stats.dma_pkt_rc = 368 hw_atl_stats_rx_dma_good_pkt_counter_get(self); 369 self->curr_stats.dma_pkt_tc = 370 hw_atl_stats_tx_dma_good_pkt_counter_get(self); 371 self->curr_stats.dma_oct_rc = 372 hw_atl_stats_rx_dma_good_octet_counter_get(self); 373 self->curr_stats.dma_oct_tc = 374 hw_atl_stats_tx_dma_good_octet_counter_get(self); 375 self->curr_stats.dpc = hw_atl_rpb_rx_dma_drop_pkt_cnt_get(self); 376 377 memcpy(&priv->last_stats, &stats, sizeof(stats)); 378 379 return 0; 380 } 381 382 static int aq_a2_fw_get_phy_temp(struct aq_hw_s *self, int *temp) 383 { 384 struct phy_health_monitor_s phy_health_monitor; 385 386 hw_atl2_shared_buffer_read_safe(self, phy_health_monitor, 387 &phy_health_monitor); 388 389 *temp = (int8_t)phy_health_monitor.phy_temperature * 1000; 390 return 0; 391 } 392 393 static int aq_a2_fw_get_mac_temp(struct aq_hw_s *self, int *temp) 394 { 395 /* There's only one temperature sensor on A2, use it for 396 * both MAC and PHY. 397 */ 398 return aq_a2_fw_get_phy_temp(self, temp); 399 } 400 401 static int aq_a2_fw_set_eee_rate(struct aq_hw_s *self, u32 speed) 402 { 403 struct link_options_s link_options; 404 405 hw_atl2_shared_buffer_get(self, link_options, link_options); 406 407 aq_a2_fw_upd_eee_rate_bits(self, &link_options, speed); 408 409 hw_atl2_shared_buffer_write(self, link_options, link_options); 410 411 return hw_atl2_shared_buffer_finish_ack(self); 412 } 413 414 static int aq_a2_fw_get_eee_rate(struct aq_hw_s *self, u32 *rate, 415 u32 *supported_rates) 416 { 417 struct device_link_caps_s device_link_caps; 418 struct lkp_link_caps_s lkp_link_caps; 419 420 hw_atl2_shared_buffer_read(self, device_link_caps, device_link_caps); 421 hw_atl2_shared_buffer_read(self, lkp_link_caps, lkp_link_caps); 422 423 *supported_rates = a2_fw_dev_to_eee_mask(&device_link_caps); 424 *rate = a2_fw_lkp_to_mask(&lkp_link_caps); 425 426 return 0; 427 } 428 429 static int aq_a2_fw_renegotiate(struct aq_hw_s *self) 430 { 431 struct link_options_s link_options; 432 int err; 433 434 hw_atl2_shared_buffer_get(self, link_options, link_options); 435 link_options.link_renegotiate = 1U; 436 hw_atl2_shared_buffer_write(self, link_options, link_options); 437 438 err = hw_atl2_shared_buffer_finish_ack(self); 439 440 /* We should put renegotiate status back to zero 441 * after command completes 442 */ 443 link_options.link_renegotiate = 0U; 444 hw_atl2_shared_buffer_write(self, link_options, link_options); 445 446 return err; 447 } 448 449 static int aq_a2_fw_set_flow_control(struct aq_hw_s *self) 450 { 451 struct link_options_s link_options; 452 453 hw_atl2_shared_buffer_get(self, link_options, link_options); 454 455 aq_a2_fw_set_mpi_flow_control(self, &link_options); 456 457 hw_atl2_shared_buffer_write(self, link_options, link_options); 458 459 return hw_atl2_shared_buffer_finish_ack(self); 460 } 461 462 static u32 aq_a2_fw_get_flow_control(struct aq_hw_s *self, u32 *fcmode) 463 { 464 struct link_status_s link_status; 465 466 hw_atl2_shared_buffer_read(self, link_status, link_status); 467 468 *fcmode = ((link_status.pause_rx) ? AQ_NIC_FC_RX : 0) | 469 ((link_status.pause_tx) ? AQ_NIC_FC_TX : 0); 470 return 0; 471 } 472 473 static int aq_a2_fw_set_phyloopback(struct aq_hw_s *self, u32 mode, bool enable) 474 { 475 struct link_options_s link_options; 476 477 hw_atl2_shared_buffer_get(self, link_options, link_options); 478 479 switch (mode) { 480 case AQ_HW_LOOPBACK_PHYINT_SYS: 481 link_options.internal_loopback = enable; 482 break; 483 case AQ_HW_LOOPBACK_PHYEXT_SYS: 484 link_options.external_loopback = enable; 485 break; 486 default: 487 return -EINVAL; 488 } 489 490 hw_atl2_shared_buffer_write(self, link_options, link_options); 491 492 return hw_atl2_shared_buffer_finish_ack(self); 493 } 494 495 u32 hw_atl2_utils_get_fw_version(struct aq_hw_s *self) 496 { 497 struct version_s version; 498 499 hw_atl2_shared_buffer_read_safe(self, version, &version); 500 501 /* A2 FW version is stored in reverse order */ 502 return version.mac.major << 24 | 503 version.mac.minor << 16 | 504 version.mac.build; 505 } 506 507 int hw_atl2_utils_get_action_resolve_table_caps(struct aq_hw_s *self, 508 u8 *base_index, u8 *count) 509 { 510 struct filter_caps_s filter_caps; 511 int err; 512 513 err = hw_atl2_shared_buffer_read_safe(self, filter_caps, &filter_caps); 514 if (err) 515 return err; 516 517 *base_index = filter_caps.rslv_tbl_base_index; 518 *count = filter_caps.rslv_tbl_count; 519 return 0; 520 } 521 522 static int aq_a2_fw_set_downshift(struct aq_hw_s *self, u32 counter) 523 { 524 struct link_options_s link_options; 525 526 hw_atl2_shared_buffer_get(self, link_options, link_options); 527 link_options.downshift = !!counter; 528 link_options.downshift_retry = counter; 529 hw_atl2_shared_buffer_write(self, link_options, link_options); 530 531 return hw_atl2_shared_buffer_finish_ack(self); 532 } 533 534 const struct aq_fw_ops aq_a2_fw_ops = { 535 .init = aq_a2_fw_init, 536 .deinit = aq_a2_fw_deinit, 537 .reset = NULL, 538 .renegotiate = aq_a2_fw_renegotiate, 539 .get_mac_permanent = aq_a2_fw_get_mac_permanent, 540 .set_link_speed = aq_a2_fw_set_link_speed, 541 .set_state = aq_a2_fw_set_state, 542 .update_link_status = aq_a2_fw_update_link_status, 543 .update_stats = aq_a2_fw_update_stats, 544 .get_mac_temp = aq_a2_fw_get_mac_temp, 545 .get_phy_temp = aq_a2_fw_get_phy_temp, 546 .set_eee_rate = aq_a2_fw_set_eee_rate, 547 .get_eee_rate = aq_a2_fw_get_eee_rate, 548 .set_flow_control = aq_a2_fw_set_flow_control, 549 .get_flow_control = aq_a2_fw_get_flow_control, 550 .set_phyloopback = aq_a2_fw_set_phyloopback, 551 .set_downshift = aq_a2_fw_set_downshift, 552 }; 553