1 // SPDX-License-Identifier: GPL-2.0 2 /* Marvell CN10K RPM driver 3 * 4 * Copyright (C) 2020 Marvell. 5 * 6 */ 7 8 #include "cgx.h" 9 #include "lmac_common.h" 10 11 static struct mac_ops rpm_mac_ops = { 12 .name = "rpm", 13 .csr_offset = 0x4e00, 14 .lmac_offset = 20, 15 .int_register = RPMX_CMRX_SW_INT, 16 .int_set_reg = RPMX_CMRX_SW_INT_ENA_W1S, 17 .irq_offset = 1, 18 .int_ena_bit = BIT_ULL(0), 19 .lmac_fwi = RPM_LMAC_FWI, 20 .non_contiguous_serdes_lane = true, 21 .rx_stats_cnt = 43, 22 .tx_stats_cnt = 34, 23 .dmac_filter_count = 32, 24 .get_nr_lmacs = rpm_get_nr_lmacs, 25 .get_lmac_type = rpm_get_lmac_type, 26 .lmac_fifo_len = rpm_get_lmac_fifo_len, 27 .mac_lmac_intl_lbk = rpm_lmac_internal_loopback, 28 .mac_get_rx_stats = rpm_get_rx_stats, 29 .mac_get_tx_stats = rpm_get_tx_stats, 30 .get_fec_stats = rpm_get_fec_stats, 31 .mac_enadis_rx_pause_fwding = rpm_lmac_enadis_rx_pause_fwding, 32 .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status, 33 .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm, 34 .mac_pause_frm_config = rpm_lmac_pause_frm_config, 35 .mac_enadis_ptp_config = rpm_lmac_ptp_config, 36 .mac_rx_tx_enable = rpm_lmac_rx_tx_enable, 37 .mac_tx_enable = rpm_lmac_tx_enable, 38 .pfc_config = rpm_lmac_pfc_config, 39 .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, 40 .mac_reset = rpm_lmac_reset, 41 .mac_stats_reset = rpm_stats_reset, 42 .mac_x2p_reset = rpm_x2p_reset, 43 .mac_enadis_rx = rpm_enadis_rx, 44 }; 45 46 static struct mac_ops rpm2_mac_ops = { 47 .name = "rpm", 48 .csr_offset = RPM2_CSR_OFFSET, 49 .lmac_offset = 20, 50 .int_register = RPM2_CMRX_SW_INT, 51 .int_set_reg = RPM2_CMRX_SW_INT_ENA_W1S, 52 .irq_offset = 1, 53 .int_ena_bit = BIT_ULL(0), 54 .lmac_fwi = RPM2_LMAC_FWI, 55 .non_contiguous_serdes_lane = true, 56 .rx_stats_cnt = 43, 57 .tx_stats_cnt = 34, 58 .dmac_filter_count = 64, 59 .get_nr_lmacs = rpm2_get_nr_lmacs, 60 .get_lmac_type = rpm_get_lmac_type, 61 .lmac_fifo_len = rpm2_get_lmac_fifo_len, 62 .mac_lmac_intl_lbk = rpm_lmac_internal_loopback, 63 .mac_get_rx_stats = rpm_get_rx_stats, 64 .mac_get_tx_stats = rpm_get_tx_stats, 65 .get_fec_stats = rpm_get_fec_stats, 66 .mac_enadis_rx_pause_fwding = rpm_lmac_enadis_rx_pause_fwding, 67 .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status, 68 .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm, 69 .mac_pause_frm_config = rpm_lmac_pause_frm_config, 70 .mac_enadis_ptp_config = rpm_lmac_ptp_config, 71 .mac_rx_tx_enable = rpm_lmac_rx_tx_enable, 72 .mac_tx_enable = rpm_lmac_tx_enable, 73 .pfc_config = rpm_lmac_pfc_config, 74 .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg, 75 .mac_reset = rpm_lmac_reset, 76 .mac_stats_reset = rpm_stats_reset, 77 .mac_x2p_reset = rpm_x2p_reset, 78 .mac_enadis_rx = rpm_enadis_rx, 79 }; 80 81 bool is_dev_rpm2(void *rpmd) 82 { 83 rpm_t *rpm = rpmd; 84 85 return (rpm->pdev->device == PCI_DEVID_CN10KB_RPM); 86 } 87 88 struct mac_ops *rpm_get_mac_ops(rpm_t *rpm) 89 { 90 if (is_dev_rpm2(rpm)) 91 return &rpm2_mac_ops; 92 else 93 return &rpm_mac_ops; 94 } 95 96 static void rpm_write(rpm_t *rpm, u64 lmac, u64 offset, u64 val) 97 { 98 cgx_write(rpm, lmac, offset, val); 99 } 100 101 static u64 rpm_read(rpm_t *rpm, u64 lmac, u64 offset) 102 { 103 return cgx_read(rpm, lmac, offset); 104 } 105 106 /* Read HW major version to determine RPM 107 * MAC type 100/USX 108 */ 109 static bool is_mac_rpmusx(void *rpmd) 110 { 111 rpm_t *rpm = rpmd; 112 113 return rpm_read(rpm, 0, RPMX_CONST1) & 0x700ULL; 114 } 115 116 int rpm_get_nr_lmacs(void *rpmd) 117 { 118 rpm_t *rpm = rpmd; 119 120 return hweight8(rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS) & 0xFULL); 121 } 122 123 int rpm2_get_nr_lmacs(void *rpmd) 124 { 125 rpm_t *rpm = rpmd; 126 127 return hweight8(rpm_read(rpm, 0, RPM2_CMRX_RX_LMACS) & 0xFFULL); 128 } 129 130 int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable) 131 { 132 rpm_t *rpm = rpmd; 133 u64 cfg, last; 134 135 if (!is_lmac_valid(rpm, lmac_id)) 136 return -ENODEV; 137 138 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 139 last = cfg; 140 if (enable) 141 cfg |= RPM_TX_EN; 142 else 143 cfg &= ~(RPM_TX_EN); 144 145 if (cfg != last) 146 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 147 return !!(last & RPM_TX_EN); 148 } 149 150 int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable) 151 { 152 rpm_t *rpm = rpmd; 153 u64 cfg; 154 155 if (!is_lmac_valid(rpm, lmac_id)) 156 return -ENODEV; 157 158 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 159 if (enable) 160 cfg |= RPM_RX_EN | RPM_TX_EN; 161 else 162 cfg &= ~(RPM_RX_EN | RPM_TX_EN); 163 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 164 return 0; 165 } 166 167 void rpm_lmac_enadis_rx_pause_fwding(void *rpmd, int lmac_id, bool enable) 168 { 169 rpm_t *rpm = rpmd; 170 struct lmac *lmac; 171 u64 cfg; 172 173 if (!rpm) 174 return; 175 176 lmac = lmac_pdata(lmac_id, rpm); 177 if (!lmac) 178 return; 179 180 /* Pause frames are not enabled just return */ 181 if (!bitmap_weight(lmac->rx_fc_pfvf_bmap.bmap, lmac->rx_fc_pfvf_bmap.max)) 182 return; 183 184 if (enable) { 185 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 186 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 187 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 188 } else { 189 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 190 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 191 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 192 } 193 } 194 195 int rpm_lmac_get_pause_frm_status(void *rpmd, int lmac_id, 196 u8 *tx_pause, u8 *rx_pause) 197 { 198 rpm_t *rpm = rpmd; 199 u64 cfg; 200 201 if (!is_lmac_valid(rpm, lmac_id)) 202 return -ENODEV; 203 204 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 205 if (!(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE)) { 206 *rx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE); 207 *tx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE); 208 } 209 210 return 0; 211 } 212 213 static void rpm_cfg_pfc_quanta_thresh(rpm_t *rpm, int lmac_id, 214 unsigned long pfc_en, 215 bool enable) 216 { 217 u64 quanta_offset = 0, quanta_thresh = 0, cfg; 218 int i, shift; 219 220 /* Set pause time and interval */ 221 for_each_set_bit(i, &pfc_en, 16) { 222 switch (i) { 223 case 0: 224 case 1: 225 quanta_offset = RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA; 226 quanta_thresh = RPMX_MTI_MAC100X_CL01_QUANTA_THRESH; 227 break; 228 case 2: 229 case 3: 230 quanta_offset = RPMX_MTI_MAC100X_CL23_PAUSE_QUANTA; 231 quanta_thresh = RPMX_MTI_MAC100X_CL23_QUANTA_THRESH; 232 break; 233 case 4: 234 case 5: 235 quanta_offset = RPMX_MTI_MAC100X_CL45_PAUSE_QUANTA; 236 quanta_thresh = RPMX_MTI_MAC100X_CL45_QUANTA_THRESH; 237 break; 238 case 6: 239 case 7: 240 quanta_offset = RPMX_MTI_MAC100X_CL67_PAUSE_QUANTA; 241 quanta_thresh = RPMX_MTI_MAC100X_CL67_QUANTA_THRESH; 242 break; 243 case 8: 244 case 9: 245 quanta_offset = RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA; 246 quanta_thresh = RPMX_MTI_MAC100X_CL89_QUANTA_THRESH; 247 break; 248 case 10: 249 case 11: 250 quanta_offset = RPMX_MTI_MAC100X_CL1011_PAUSE_QUANTA; 251 quanta_thresh = RPMX_MTI_MAC100X_CL1011_QUANTA_THRESH; 252 break; 253 case 12: 254 case 13: 255 quanta_offset = RPMX_MTI_MAC100X_CL1213_PAUSE_QUANTA; 256 quanta_thresh = RPMX_MTI_MAC100X_CL1213_QUANTA_THRESH; 257 break; 258 case 14: 259 case 15: 260 quanta_offset = RPMX_MTI_MAC100X_CL1415_PAUSE_QUANTA; 261 quanta_thresh = RPMX_MTI_MAC100X_CL1415_QUANTA_THRESH; 262 break; 263 } 264 265 if (!quanta_offset || !quanta_thresh) 266 continue; 267 268 shift = (i % 2) ? 1 : 0; 269 cfg = rpm_read(rpm, lmac_id, quanta_offset); 270 if (enable) { 271 cfg |= ((u64)RPM_DEFAULT_PAUSE_TIME << shift * 16); 272 } else { 273 if (!shift) 274 cfg &= ~GENMASK_ULL(15, 0); 275 else 276 cfg &= ~GENMASK_ULL(31, 16); 277 } 278 rpm_write(rpm, lmac_id, quanta_offset, cfg); 279 280 cfg = rpm_read(rpm, lmac_id, quanta_thresh); 281 if (enable) { 282 cfg |= ((u64)(RPM_DEFAULT_PAUSE_TIME / 2) << shift * 16); 283 } else { 284 if (!shift) 285 cfg &= ~GENMASK_ULL(15, 0); 286 else 287 cfg &= ~GENMASK_ULL(31, 16); 288 } 289 rpm_write(rpm, lmac_id, quanta_thresh, cfg); 290 } 291 } 292 293 static void rpm2_lmac_cfg_bp(rpm_t *rpm, int lmac_id, u8 tx_pause, u8 rx_pause) 294 { 295 u64 cfg; 296 297 cfg = rpm_read(rpm, lmac_id, RPM2_CMR_RX_OVR_BP); 298 if (tx_pause) { 299 /* Configure CL0 Pause Quanta & threshold 300 * for 802.3X frames 301 */ 302 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 1, true); 303 cfg &= ~RPM2_CMR_RX_OVR_BP_EN; 304 } else { 305 /* Disable all Pause Quanta & threshold values */ 306 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xffff, false); 307 cfg |= RPM2_CMR_RX_OVR_BP_EN; 308 cfg &= ~RPM2_CMR_RX_OVR_BP_BP; 309 } 310 rpm_write(rpm, lmac_id, RPM2_CMR_RX_OVR_BP, cfg); 311 } 312 313 static void rpm_lmac_cfg_bp(rpm_t *rpm, int lmac_id, u8 tx_pause, u8 rx_pause) 314 { 315 u64 cfg; 316 317 cfg = rpm_read(rpm, 0, RPMX_CMR_RX_OVR_BP); 318 if (tx_pause) { 319 /* Configure CL0 Pause Quanta & threshold for 320 * 802.3X frames 321 */ 322 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 1, true); 323 cfg &= ~RPMX_CMR_RX_OVR_BP_EN(lmac_id); 324 } else { 325 /* Disable all Pause Quanta & threshold values */ 326 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xffff, false); 327 cfg |= RPMX_CMR_RX_OVR_BP_EN(lmac_id); 328 cfg &= ~RPMX_CMR_RX_OVR_BP_BP(lmac_id); 329 } 330 rpm_write(rpm, 0, RPMX_CMR_RX_OVR_BP, cfg); 331 } 332 333 int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, 334 u8 rx_pause) 335 { 336 rpm_t *rpm = rpmd; 337 u64 cfg; 338 339 if (!is_lmac_valid(rpm, lmac_id)) 340 return -ENODEV; 341 342 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 343 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 344 cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 345 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 346 cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 347 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 348 349 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 350 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 351 cfg |= tx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 352 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 353 354 if (is_dev_rpm2(rpm)) 355 rpm2_lmac_cfg_bp(rpm, lmac_id, tx_pause, rx_pause); 356 else 357 rpm_lmac_cfg_bp(rpm, lmac_id, tx_pause, rx_pause); 358 359 return 0; 360 } 361 362 void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) 363 { 364 u64 cfg, pfc_class_mask_cfg; 365 rpm_t *rpm = rpmd; 366 367 /* ALL pause frames received are completely ignored */ 368 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 369 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 370 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 371 372 /* Disable forward pause to TX block */ 373 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 374 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 375 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 376 377 /* Disable pause frames transmission */ 378 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 379 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 380 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 381 382 /* Disable forward pause to driver */ 383 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 384 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD; 385 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 386 387 /* Enable channel mask for all LMACS */ 388 if (is_dev_rpm2(rpm)) 389 rpm_write(rpm, lmac_id, RPM2_CMR_CHAN_MSK_OR, 0xffff); 390 else 391 rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL); 392 393 /* Disable all PFC classes */ 394 pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : 395 RPMX_CMRX_PRT_CBFC_CTL; 396 cfg = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); 397 cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg); 398 rpm_write(rpm, lmac_id, pfc_class_mask_cfg, cfg); 399 } 400 401 int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat) 402 { 403 rpm_t *rpm = rpmd; 404 u64 val_lo, val_hi; 405 406 if (!is_lmac_valid(rpm, lmac_id)) 407 return -ENODEV; 408 409 mutex_lock(&rpm->lock); 410 411 /* Update idx to point per lmac Rx statistics page */ 412 idx += lmac_id * rpm->mac_ops->rx_stats_cnt; 413 414 /* Read lower 32 bits of counter */ 415 val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_RX_STAT_PAGES_COUNTERX + 416 (idx * 8)); 417 418 /* upon read of lower 32 bits, higher 32 bits are written 419 * to RPMX_MTI_STAT_DATA_HI_CDC 420 */ 421 val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); 422 423 *rx_stat = (val_hi << 32 | val_lo); 424 425 mutex_unlock(&rpm->lock); 426 return 0; 427 } 428 429 int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat) 430 { 431 rpm_t *rpm = rpmd; 432 u64 val_lo, val_hi; 433 434 if (!is_lmac_valid(rpm, lmac_id)) 435 return -ENODEV; 436 437 mutex_lock(&rpm->lock); 438 439 /* Update idx to point per lmac Tx statistics page */ 440 idx += lmac_id * rpm->mac_ops->tx_stats_cnt; 441 442 val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_TX_STAT_PAGES_COUNTERX + 443 (idx * 8)); 444 val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); 445 446 *tx_stat = (val_hi << 32 | val_lo); 447 448 mutex_unlock(&rpm->lock); 449 return 0; 450 } 451 452 int rpm_stats_reset(void *rpmd, int lmac_id) 453 { 454 rpm_t *rpm = rpmd; 455 u64 cfg; 456 457 if (!is_lmac_valid(rpm, lmac_id)) 458 return -ENODEV; 459 460 cfg = rpm_read(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL); 461 cfg |= RPMX_CMD_CLEAR_TX | RPMX_CMD_CLEAR_RX | BIT_ULL(lmac_id); 462 rpm_write(rpm, 0, RPMX_MTI_STAT_STATN_CONTROL, cfg); 463 464 return 0; 465 } 466 467 u8 rpm_get_lmac_type(void *rpmd, int lmac_id) 468 { 469 rpm_t *rpm = rpmd; 470 u64 req = 0, resp; 471 int err; 472 473 req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req); 474 err = cgx_fwi_cmd_generic(req, &resp, rpm, lmac_id); 475 if (!err) 476 return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp); 477 return err; 478 } 479 480 u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id) 481 { 482 rpm_t *rpm = rpmd; 483 u64 hi_perf_lmac; 484 u8 num_lmacs; 485 u32 fifo_len; 486 487 fifo_len = rpm->fifo_len; 488 num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm); 489 490 switch (num_lmacs) { 491 case 1: 492 return fifo_len; 493 case 2: 494 return fifo_len / 2; 495 case 3: 496 /* LMAC marked as hi_perf gets half of the FIFO and rest 1/4th */ 497 hi_perf_lmac = rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS); 498 hi_perf_lmac = (hi_perf_lmac >> 4) & 0x3ULL; 499 if (lmac_id == hi_perf_lmac) 500 return fifo_len / 2; 501 return fifo_len / 4; 502 case 4: 503 default: 504 return fifo_len / 4; 505 } 506 return 0; 507 } 508 509 static int rpmusx_lmac_internal_loopback(rpm_t *rpm, int lmac_id, bool enable) 510 { 511 u64 cfg; 512 513 cfg = rpm_read(rpm, lmac_id, RPM2_USX_PCSX_CONTROL1); 514 515 if (enable) 516 cfg |= RPM2_USX_PCS_LBK; 517 else 518 cfg &= ~RPM2_USX_PCS_LBK; 519 rpm_write(rpm, lmac_id, RPM2_USX_PCSX_CONTROL1, cfg); 520 521 return 0; 522 } 523 524 u32 rpm2_get_lmac_fifo_len(void *rpmd, int lmac_id) 525 { 526 u64 hi_perf_lmac, lmac_info; 527 rpm_t *rpm = rpmd; 528 u8 num_lmacs; 529 u32 fifo_len; 530 u16 max_lmac; 531 532 lmac_info = rpm_read(rpm, 0, RPM2_CMRX_RX_LMACS); 533 /* LMACs are divided into two groups and each group 534 * gets half of the FIFO 535 * Group0 lmac_id range {0..3} 536 * Group1 lmac_id range {4..7} 537 */ 538 max_lmac = (rpm_read(rpm, 0, CGX_CONST) >> 24) & 0xFF; 539 if (max_lmac > 4) 540 fifo_len = rpm->fifo_len / 2; 541 else 542 fifo_len = rpm->fifo_len; 543 544 if (lmac_id < 4) { 545 num_lmacs = hweight8(lmac_info & 0xF); 546 hi_perf_lmac = (lmac_info >> 8) & 0x3ULL; 547 } else { 548 num_lmacs = hweight8(lmac_info & 0xF0); 549 hi_perf_lmac = (lmac_info >> 10) & 0x3ULL; 550 hi_perf_lmac += 4; 551 } 552 553 switch (num_lmacs) { 554 case 1: 555 return fifo_len; 556 case 2: 557 return fifo_len / 2; 558 case 3: 559 /* LMAC marked as hi_perf gets half of the FIFO 560 * and rest 1/4th 561 */ 562 if (lmac_id == hi_perf_lmac) 563 return fifo_len / 2; 564 return fifo_len / 4; 565 case 4: 566 default: 567 return fifo_len / 4; 568 } 569 return 0; 570 } 571 572 int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable) 573 { 574 rpm_t *rpm = rpmd; 575 struct lmac *lmac; 576 u64 cfg; 577 578 if (!is_lmac_valid(rpm, lmac_id)) 579 return -ENODEV; 580 581 lmac = lmac_pdata(lmac_id, rpm); 582 if (lmac->lmac_type == LMAC_MODE_QSGMII || 583 lmac->lmac_type == LMAC_MODE_SGMII) { 584 dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n"); 585 return 0; 586 } 587 588 if (is_dev_rpm2(rpm) && is_mac_rpmusx(rpm)) 589 return rpmusx_lmac_internal_loopback(rpm, lmac_id, enable); 590 591 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1); 592 593 if (enable) 594 cfg |= RPMX_MTI_PCS_LBK; 595 else 596 cfg &= ~RPMX_MTI_PCS_LBK; 597 rpm_write(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1, cfg); 598 599 return 0; 600 } 601 602 void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable) 603 { 604 rpm_t *rpm = rpmd; 605 u64 cfg; 606 607 if (!is_lmac_valid(rpm, lmac_id)) 608 return; 609 610 cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG); 611 if (enable) { 612 cfg |= RPMX_RX_TS_PREPEND; 613 cfg |= RPMX_TX_PTP_1S_SUPPORT; 614 } else { 615 cfg &= ~RPMX_RX_TS_PREPEND; 616 cfg &= ~RPMX_TX_PTP_1S_SUPPORT; 617 } 618 619 rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg); 620 621 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_XIF_MODE); 622 623 if (enable) { 624 cfg |= RPMX_ONESTEP_ENABLE; 625 cfg &= ~RPMX_TS_BINARY_MODE; 626 } else { 627 cfg &= ~RPMX_ONESTEP_ENABLE; 628 } 629 630 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_XIF_MODE, cfg); 631 } 632 633 int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 pfc_en) 634 { 635 u64 cfg, class_en, pfc_class_mask_cfg; 636 rpm_t *rpm = rpmd; 637 638 if (!is_lmac_valid(rpm, lmac_id)) 639 return -ENODEV; 640 641 pfc_class_mask_cfg = is_dev_rpm2(rpm) ? RPM2_CMRX_PRT_CBFC_CTL : 642 RPMX_CMRX_PRT_CBFC_CTL; 643 644 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 645 class_en = rpm_read(rpm, lmac_id, pfc_class_mask_cfg); 646 pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en); 647 648 if (rx_pause) { 649 cfg &= ~(RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE | 650 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE); 651 } else { 652 cfg |= (RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE | 653 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE); 654 } 655 656 if (tx_pause) { 657 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, pfc_en, true); 658 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 659 class_en = FIELD_SET(RPM_PFC_CLASS_MASK, pfc_en, class_en); 660 } else { 661 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xfff, false); 662 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 663 class_en = FIELD_SET(RPM_PFC_CLASS_MASK, 0, class_en); 664 } 665 666 if (!rx_pause && !tx_pause) 667 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE; 668 else 669 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE; 670 671 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 672 rpm_write(rpm, lmac_id, pfc_class_mask_cfg, class_en); 673 674 return 0; 675 } 676 677 int rpm_lmac_get_pfc_frm_cfg(void *rpmd, int lmac_id, u8 *tx_pause, u8 *rx_pause) 678 { 679 rpm_t *rpm = rpmd; 680 u64 cfg; 681 682 if (!is_lmac_valid(rpm, lmac_id)) 683 return -ENODEV; 684 685 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 686 if (cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE) { 687 *rx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE); 688 *tx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE); 689 } 690 691 return 0; 692 } 693 694 int rpm_get_fec_stats(void *rpmd, int lmac_id, struct cgx_fec_stats_rsp *rsp) 695 { 696 u64 val_lo, val_hi; 697 rpm_t *rpm = rpmd; 698 u64 cfg; 699 700 if (!is_lmac_valid(rpm, lmac_id)) 701 return -ENODEV; 702 703 if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_NONE) 704 return 0; 705 706 /* latched registers FCFECX_CW_HI/RSFEC_STAT_FAST_DATA_HI_CDC are common 707 * for all counters. Acquire lock to ensure serialized reads 708 */ 709 mutex_lock(&rpm->lock); 710 if (rpm->lmac_idmap[lmac_id]->link_info.fec == OTX2_FEC_BASER) { 711 val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_CCW_LO(lmac_id)); 712 val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id)); 713 rsp->fec_corr_blks = (val_hi << 16 | val_lo); 714 715 val_lo = rpm_read(rpm, 0, RPMX_MTI_FCFECX_VL0_NCCW_LO(lmac_id)); 716 val_hi = rpm_read(rpm, 0, RPMX_MTI_FCFECX_CW_HI(lmac_id)); 717 rsp->fec_uncorr_blks = (val_hi << 16 | val_lo); 718 719 /* 50G uses 2 Physical serdes lines */ 720 if (rpm->lmac_idmap[lmac_id]->link_info.lmac_type_id == 721 LMAC_MODE_50G_R) { 722 val_lo = rpm_read(rpm, 0, 723 RPMX_MTI_FCFECX_VL1_CCW_LO(lmac_id)); 724 val_hi = rpm_read(rpm, 0, 725 RPMX_MTI_FCFECX_CW_HI(lmac_id)); 726 rsp->fec_corr_blks += (val_hi << 16 | val_lo); 727 728 val_lo = rpm_read(rpm, 0, 729 RPMX_MTI_FCFECX_VL1_NCCW_LO(lmac_id)); 730 val_hi = rpm_read(rpm, 0, 731 RPMX_MTI_FCFECX_CW_HI(lmac_id)); 732 rsp->fec_uncorr_blks += (val_hi << 16 | val_lo); 733 } 734 } else { 735 /* enable RS-FEC capture */ 736 cfg = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL); 737 cfg |= RPMX_RSFEC_RX_CAPTURE | BIT(lmac_id); 738 rpm_write(rpm, 0, RPMX_MTI_RSFEC_STAT_STATN_CONTROL, cfg); 739 740 val_lo = rpm_read(rpm, 0, 741 RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_2); 742 val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC); 743 rsp->fec_corr_blks = (val_hi << 32 | val_lo); 744 745 val_lo = rpm_read(rpm, 0, 746 RPMX_MTI_RSFEC_STAT_COUNTER_CAPTURE_3); 747 val_hi = rpm_read(rpm, 0, RPMX_MTI_RSFEC_STAT_FAST_DATA_HI_CDC); 748 rsp->fec_uncorr_blks = (val_hi << 32 | val_lo); 749 } 750 mutex_unlock(&rpm->lock); 751 752 return 0; 753 } 754 755 int rpm_lmac_reset(void *rpmd, int lmac_id, u8 pf_req_flr) 756 { 757 u64 rx_logl_xon, cfg; 758 rpm_t *rpm = rpmd; 759 760 if (!is_lmac_valid(rpm, lmac_id)) 761 return -ENODEV; 762 763 /* Resetting PFC related CSRs */ 764 rx_logl_xon = is_dev_rpm2(rpm) ? RPM2_CMRX_RX_LOGL_XON : 765 RPMX_CMRX_RX_LOGL_XON; 766 cfg = 0xff; 767 768 rpm_write(rpm, lmac_id, rx_logl_xon, cfg); 769 770 if (pf_req_flr) 771 rpm_lmac_internal_loopback(rpm, lmac_id, false); 772 773 return 0; 774 } 775 776 void rpm_x2p_reset(void *rpmd, bool enable) 777 { 778 rpm_t *rpm = rpmd; 779 int lmac_id; 780 u64 cfg; 781 782 if (enable) { 783 for_each_set_bit(lmac_id, &rpm->lmac_bmap, rpm->max_lmac_per_mac) 784 rpm->mac_ops->mac_enadis_rx(rpm, lmac_id, false); 785 786 usleep_range(1000, 2000); 787 788 cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG); 789 rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg | RPM_NIX0_RESET); 790 } else { 791 cfg = rpm_read(rpm, 0, RPMX_CMR_GLOBAL_CFG); 792 cfg &= ~RPM_NIX0_RESET; 793 rpm_write(rpm, 0, RPMX_CMR_GLOBAL_CFG, cfg); 794 } 795 } 796 797 int rpm_enadis_rx(void *rpmd, int lmac_id, bool enable) 798 { 799 rpm_t *rpm = rpmd; 800 u64 cfg; 801 802 if (!is_lmac_valid(rpm, lmac_id)) 803 return -ENODEV; 804 805 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 806 if (enable) 807 cfg |= RPM_RX_EN; 808 else 809 cfg &= ~RPM_RX_EN; 810 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 811 return 0; 812 } 813