Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Marvell CN10K RPM driver
0003  *
0004  * Copyright (C) 2020 Marvell.
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     /* Pause frames are not enabled just return */
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     /* Set pause time and interval */
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         /* Configure CL0 Pause Quanta & threshold for 802.3X frames */
0249         rpm_cfg_pfc_quanta_thresh(rpm, lmac_id, 1, true);
0250         cfg &= ~RPMX_CMR_RX_OVR_BP_EN(lmac_id);
0251     } else {
0252         /* Disable all Pause Quanta & threshold values */
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     /* ALL pause frames received are completely ignored */
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     /* Disable forward pause to TX block */
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     /* Disable pause frames transmission */
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     /* Disable all PFC classes */
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     /* Enable channel mask for all LMACS */
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     /* Update idx to point per lmac Rx statistics page */
0301     idx += lmac_id * rpm->mac_ops->rx_stats_cnt;
0302 
0303     /* Read lower 32 bits of counter */
0304     val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_RX_STAT_PAGES_COUNTERX +
0305               (idx * 8));
0306 
0307     /* upon read of lower 32 bits, higher 32 bits are written
0308      * to RPMX_MTI_STAT_DATA_HI_CDC
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     /* Update idx to point per lmac Tx statistics page */
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         /* LMAC marked as hi_perf gets half of the FIFO and rest 1/4th */
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 }