0001
0002
0003
0004
0005
0006
0007
0008 #include "cgx.h"
0009 #include "lmac_common.h"
0010
0011 static struct mac_ops rpm_mac_ops = {
0012 .name = "rpm",
0013 .csr_offset = 0x4e00,
0014 .lmac_offset = 20,
0015 .int_register = RPMX_CMRX_SW_INT,
0016 .int_set_reg = RPMX_CMRX_SW_INT_ENA_W1S,
0017 .irq_offset = 1,
0018 .int_ena_bit = BIT_ULL(0),
0019 .lmac_fwi = RPM_LMAC_FWI,
0020 .non_contiguous_serdes_lane = true,
0021 .rx_stats_cnt = 43,
0022 .tx_stats_cnt = 34,
0023 .get_nr_lmacs = rpm_get_nr_lmacs,
0024 .get_lmac_type = rpm_get_lmac_type,
0025 .lmac_fifo_len = rpm_get_lmac_fifo_len,
0026 .mac_lmac_intl_lbk = rpm_lmac_internal_loopback,
0027 .mac_get_rx_stats = rpm_get_rx_stats,
0028 .mac_get_tx_stats = rpm_get_tx_stats,
0029 .mac_enadis_rx_pause_fwding = rpm_lmac_enadis_rx_pause_fwding,
0030 .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status,
0031 .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm,
0032 .mac_pause_frm_config = rpm_lmac_pause_frm_config,
0033 .mac_enadis_ptp_config = rpm_lmac_ptp_config,
0034 .mac_rx_tx_enable = rpm_lmac_rx_tx_enable,
0035 .mac_tx_enable = rpm_lmac_tx_enable,
0036 .pfc_config = rpm_lmac_pfc_config,
0037 .mac_get_pfc_frm_cfg = rpm_lmac_get_pfc_frm_cfg,
0038 };
0039
0040 struct mac_ops *rpm_get_mac_ops(void)
0041 {
0042 return &rpm_mac_ops;
0043 }
0044
0045 static void rpm_write(rpm_t *rpm, u64 lmac, u64 offset, u64 val)
0046 {
0047 cgx_write(rpm, lmac, offset, val);
0048 }
0049
0050 static u64 rpm_read(rpm_t *rpm, u64 lmac, u64 offset)
0051 {
0052 return cgx_read(rpm, lmac, offset);
0053 }
0054
0055 int rpm_get_nr_lmacs(void *rpmd)
0056 {
0057 rpm_t *rpm = rpmd;
0058
0059 return hweight8(rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS) & 0xFULL);
0060 }
0061
0062 int rpm_lmac_tx_enable(void *rpmd, int lmac_id, bool enable)
0063 {
0064 rpm_t *rpm = rpmd;
0065 u64 cfg, last;
0066
0067 if (!is_lmac_valid(rpm, lmac_id))
0068 return -ENODEV;
0069
0070 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0071 last = cfg;
0072 if (enable)
0073 cfg |= RPM_TX_EN;
0074 else
0075 cfg &= ~(RPM_TX_EN);
0076
0077 if (cfg != last)
0078 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0079 return !!(last & RPM_TX_EN);
0080 }
0081
0082 int rpm_lmac_rx_tx_enable(void *rpmd, int lmac_id, bool enable)
0083 {
0084 rpm_t *rpm = rpmd;
0085 u64 cfg;
0086
0087 if (!is_lmac_valid(rpm, lmac_id))
0088 return -ENODEV;
0089
0090 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0091 if (enable)
0092 cfg |= RPM_RX_EN | RPM_TX_EN;
0093 else
0094 cfg &= ~(RPM_RX_EN | RPM_TX_EN);
0095 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0096 return 0;
0097 }
0098
0099 void rpm_lmac_enadis_rx_pause_fwding(void *rpmd, int lmac_id, bool enable)
0100 {
0101 rpm_t *rpm = rpmd;
0102 struct lmac *lmac;
0103 u64 cfg;
0104
0105 if (!rpm)
0106 return;
0107
0108 lmac = lmac_pdata(lmac_id, rpm);
0109 if (!lmac)
0110 return;
0111
0112
0113 if (!bitmap_weight(lmac->rx_fc_pfvf_bmap.bmap, lmac->rx_fc_pfvf_bmap.max))
0114 return;
0115
0116 if (enable) {
0117 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0118 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE;
0119 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0120 } else {
0121 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0122 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE;
0123 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0124 }
0125 }
0126
0127 int rpm_lmac_get_pause_frm_status(void *rpmd, int lmac_id,
0128 u8 *tx_pause, u8 *rx_pause)
0129 {
0130 rpm_t *rpm = rpmd;
0131 u64 cfg;
0132
0133 if (!is_lmac_valid(rpm, lmac_id))
0134 return -ENODEV;
0135
0136 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0137 if (!(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE)) {
0138 *rx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE);
0139 *tx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE);
0140 }
0141
0142 return 0;
0143 }
0144
0145 static void rpm_cfg_pfc_quanta_thresh(rpm_t *rpm, int lmac_id,
0146 unsigned long pfc_en,
0147 bool enable)
0148 {
0149 u64 quanta_offset = 0, quanta_thresh = 0, cfg;
0150 int i, shift;
0151
0152
0153 for_each_set_bit(i, &pfc_en, 16) {
0154 switch (i) {
0155 case 0:
0156 case 1:
0157 quanta_offset = RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA;
0158 quanta_thresh = RPMX_MTI_MAC100X_CL01_QUANTA_THRESH;
0159 break;
0160 case 2:
0161 case 3:
0162 quanta_offset = RPMX_MTI_MAC100X_CL23_PAUSE_QUANTA;
0163 quanta_thresh = RPMX_MTI_MAC100X_CL23_QUANTA_THRESH;
0164 break;
0165 case 4:
0166 case 5:
0167 quanta_offset = RPMX_MTI_MAC100X_CL45_PAUSE_QUANTA;
0168 quanta_thresh = RPMX_MTI_MAC100X_CL45_QUANTA_THRESH;
0169 break;
0170 case 6:
0171 case 7:
0172 quanta_offset = RPMX_MTI_MAC100X_CL67_PAUSE_QUANTA;
0173 quanta_thresh = RPMX_MTI_MAC100X_CL67_QUANTA_THRESH;
0174 break;
0175 case 8:
0176 case 9:
0177 quanta_offset = RPMX_MTI_MAC100X_CL89_PAUSE_QUANTA;
0178 quanta_thresh = RPMX_MTI_MAC100X_CL89_QUANTA_THRESH;
0179 break;
0180 case 10:
0181 case 11:
0182 quanta_offset = RPMX_MTI_MAC100X_CL1011_PAUSE_QUANTA;
0183 quanta_thresh = RPMX_MTI_MAC100X_CL1011_QUANTA_THRESH;
0184 break;
0185 case 12:
0186 case 13:
0187 quanta_offset = RPMX_MTI_MAC100X_CL1213_PAUSE_QUANTA;
0188 quanta_thresh = RPMX_MTI_MAC100X_CL1213_QUANTA_THRESH;
0189 break;
0190 case 14:
0191 case 15:
0192 quanta_offset = RPMX_MTI_MAC100X_CL1415_PAUSE_QUANTA;
0193 quanta_thresh = RPMX_MTI_MAC100X_CL1415_QUANTA_THRESH;
0194 break;
0195 }
0196
0197 if (!quanta_offset || !quanta_thresh)
0198 continue;
0199
0200 shift = (i % 2) ? 1 : 0;
0201 cfg = rpm_read(rpm, lmac_id, quanta_offset);
0202 if (enable) {
0203 cfg |= ((u64)RPM_DEFAULT_PAUSE_TIME << shift * 16);
0204 } else {
0205 if (!shift)
0206 cfg &= ~GENMASK_ULL(15, 0);
0207 else
0208 cfg &= ~GENMASK_ULL(31, 16);
0209 }
0210 rpm_write(rpm, lmac_id, quanta_offset, cfg);
0211
0212 cfg = rpm_read(rpm, lmac_id, quanta_thresh);
0213 if (enable) {
0214 cfg |= ((u64)(RPM_DEFAULT_PAUSE_TIME / 2) << shift * 16);
0215 } else {
0216 if (!shift)
0217 cfg &= ~GENMASK_ULL(15, 0);
0218 else
0219 cfg &= ~GENMASK_ULL(31, 16);
0220 }
0221 rpm_write(rpm, lmac_id, quanta_thresh, cfg);
0222 }
0223 }
0224
0225 int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause,
0226 u8 rx_pause)
0227 {
0228 rpm_t *rpm = rpmd;
0229 u64 cfg;
0230
0231 if (!is_lmac_valid(rpm, lmac_id))
0232 return -ENODEV;
0233
0234 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0235 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE;
0236 cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE;
0237 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE;
0238 cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE;
0239 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0240
0241 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0242 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
0243 cfg |= tx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
0244 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0245
0246 cfg = rpm_read(rpm, 0, RPMX_CMR_RX_OVR_BP);
0247 if (tx_pause) {
0248
0249 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 1, true);
0250 cfg &= ~RPMX_CMR_RX_OVR_BP_EN(lmac_id);
0251 } else {
0252
0253 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xffff, false);
0254 cfg |= RPMX_CMR_RX_OVR_BP_EN(lmac_id);
0255 cfg &= ~RPMX_CMR_RX_OVR_BP_BP(lmac_id);
0256 }
0257 rpm_write(rpm, 0, RPMX_CMR_RX_OVR_BP, cfg);
0258 return 0;
0259 }
0260
0261 void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable)
0262 {
0263 rpm_t *rpm = rpmd;
0264 u64 cfg;
0265
0266
0267 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0268 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE;
0269 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0270
0271
0272 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0273 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE;
0274 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0275
0276
0277 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0278 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
0279 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0280
0281
0282 cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
0283 cfg = FIELD_SET(RPM_PFC_CLASS_MASK, 0, cfg);
0284 rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, cfg);
0285
0286
0287 rpm_write(rpm, 0, RPMX_CMR_CHAN_MSK_OR, ~0ULL);
0288 }
0289
0290 int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat)
0291 {
0292 rpm_t *rpm = rpmd;
0293 u64 val_lo, val_hi;
0294
0295 if (!rpm || lmac_id >= rpm->lmac_count)
0296 return -ENODEV;
0297
0298 mutex_lock(&rpm->lock);
0299
0300
0301 idx += lmac_id * rpm->mac_ops->rx_stats_cnt;
0302
0303
0304 val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_RX_STAT_PAGES_COUNTERX +
0305 (idx * 8));
0306
0307
0308
0309
0310 val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
0311
0312 *rx_stat = (val_hi << 32 | val_lo);
0313
0314 mutex_unlock(&rpm->lock);
0315 return 0;
0316 }
0317
0318 int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat)
0319 {
0320 rpm_t *rpm = rpmd;
0321 u64 val_lo, val_hi;
0322
0323 if (!rpm || lmac_id >= rpm->lmac_count)
0324 return -ENODEV;
0325
0326 mutex_lock(&rpm->lock);
0327
0328
0329 idx += lmac_id * rpm->mac_ops->tx_stats_cnt;
0330
0331 val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_TX_STAT_PAGES_COUNTERX +
0332 (idx * 8));
0333 val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC);
0334
0335 *tx_stat = (val_hi << 32 | val_lo);
0336
0337 mutex_unlock(&rpm->lock);
0338 return 0;
0339 }
0340
0341 u8 rpm_get_lmac_type(void *rpmd, int lmac_id)
0342 {
0343 rpm_t *rpm = rpmd;
0344 u64 req = 0, resp;
0345 int err;
0346
0347 req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req);
0348 err = cgx_fwi_cmd_generic(req, &resp, rpm, 0);
0349 if (!err)
0350 return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp);
0351 return err;
0352 }
0353
0354 u32 rpm_get_lmac_fifo_len(void *rpmd, int lmac_id)
0355 {
0356 rpm_t *rpm = rpmd;
0357 u64 hi_perf_lmac;
0358 u8 num_lmacs;
0359 u32 fifo_len;
0360
0361 fifo_len = rpm->mac_ops->fifo_len;
0362 num_lmacs = rpm->mac_ops->get_nr_lmacs(rpm);
0363
0364 switch (num_lmacs) {
0365 case 1:
0366 return fifo_len;
0367 case 2:
0368 return fifo_len / 2;
0369 case 3:
0370
0371 hi_perf_lmac = rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS);
0372 hi_perf_lmac = (hi_perf_lmac >> 4) & 0x3ULL;
0373 if (lmac_id == hi_perf_lmac)
0374 return fifo_len / 2;
0375 return fifo_len / 4;
0376 case 4:
0377 default:
0378 return fifo_len / 4;
0379 }
0380 return 0;
0381 }
0382
0383 int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable)
0384 {
0385 rpm_t *rpm = rpmd;
0386 u8 lmac_type;
0387 u64 cfg;
0388
0389 if (!rpm || lmac_id >= rpm->lmac_count)
0390 return -ENODEV;
0391 lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id);
0392
0393 if (lmac_type == LMAC_MODE_QSGMII || lmac_type == LMAC_MODE_SGMII) {
0394 dev_err(&rpm->pdev->dev, "loopback not supported for LPC mode\n");
0395 return 0;
0396 }
0397
0398 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1);
0399
0400 if (enable)
0401 cfg |= RPMX_MTI_PCS_LBK;
0402 else
0403 cfg &= ~RPMX_MTI_PCS_LBK;
0404 rpm_write(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1, cfg);
0405
0406 return 0;
0407 }
0408
0409 void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable)
0410 {
0411 rpm_t *rpm = rpmd;
0412 u64 cfg;
0413
0414 if (!is_lmac_valid(rpm, lmac_id))
0415 return;
0416
0417 cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG);
0418 if (enable)
0419 cfg |= RPMX_RX_TS_PREPEND;
0420 else
0421 cfg &= ~RPMX_RX_TS_PREPEND;
0422 rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg);
0423 }
0424
0425 int rpm_lmac_pfc_config(void *rpmd, int lmac_id, u8 tx_pause, u8 rx_pause, u16 pfc_en)
0426 {
0427 rpm_t *rpm = rpmd;
0428 u64 cfg, class_en;
0429
0430 if (!is_lmac_valid(rpm, lmac_id))
0431 return -ENODEV;
0432
0433 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0434 class_en = rpm_read(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL);
0435 pfc_en |= FIELD_GET(RPM_PFC_CLASS_MASK, class_en);
0436
0437 if (rx_pause) {
0438 cfg &= ~(RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE |
0439 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE |
0440 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD);
0441 } else {
0442 cfg |= (RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE |
0443 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE |
0444 RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_FWD);
0445 }
0446
0447 if (tx_pause) {
0448 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, pfc_en, true);
0449 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
0450 class_en = FIELD_SET(RPM_PFC_CLASS_MASK, pfc_en, class_en);
0451 } else {
0452 rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 0xfff, false);
0453 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE;
0454 class_en = FIELD_SET(RPM_PFC_CLASS_MASK, 0, class_en);
0455 }
0456
0457 if (!rx_pause && !tx_pause)
0458 cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE;
0459 else
0460 cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE;
0461
0462 rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg);
0463
0464 rpm_write(rpm, lmac_id, RPMX_CMRX_PRT_CBFC_CTL, class_en);
0465
0466 return 0;
0467 }
0468
0469 int rpm_lmac_get_pfc_frm_cfg(void *rpmd, int lmac_id, u8 *tx_pause, u8 *rx_pause)
0470 {
0471 rpm_t *rpm = rpmd;
0472 u64 cfg;
0473
0474 if (!is_lmac_valid(rpm, lmac_id))
0475 return -ENODEV;
0476
0477 cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG);
0478 if (cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE) {
0479 *rx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE);
0480 *tx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE);
0481 }
0482
0483 return 0;
0484 }