191c6945eSHariprasad Kelam // SPDX-License-Identifier: GPL-2.0 2c7cd6c5aSSunil Goutham /* Marvell CN10K RPM driver 391c6945eSHariprasad Kelam * 491c6945eSHariprasad Kelam * Copyright (C) 2020 Marvell. 591c6945eSHariprasad Kelam * 691c6945eSHariprasad Kelam */ 791c6945eSHariprasad Kelam 891c6945eSHariprasad Kelam #include "cgx.h" 991c6945eSHariprasad Kelam #include "lmac_common.h" 1091c6945eSHariprasad Kelam 1191c6945eSHariprasad Kelam static struct mac_ops rpm_mac_ops = { 1291c6945eSHariprasad Kelam .name = "rpm", 1391c6945eSHariprasad Kelam .csr_offset = 0x4e00, 1491c6945eSHariprasad Kelam .lmac_offset = 20, 1591c6945eSHariprasad Kelam .int_register = RPMX_CMRX_SW_INT, 1691c6945eSHariprasad Kelam .int_set_reg = RPMX_CMRX_SW_INT_ENA_W1S, 1791c6945eSHariprasad Kelam .irq_offset = 1, 1891c6945eSHariprasad Kelam .int_ena_bit = BIT_ULL(0), 1991c6945eSHariprasad Kelam .lmac_fwi = RPM_LMAC_FWI, 2091c6945eSHariprasad Kelam .non_contiguous_serdes_lane = true, 21ce7a6c31SHariprasad Kelam .rx_stats_cnt = 43, 22ce7a6c31SHariprasad Kelam .tx_stats_cnt = 34, 2391c6945eSHariprasad Kelam .get_nr_lmacs = rpm_get_nr_lmacs, 243ad3f8f9SHariprasad Kelam .get_lmac_type = rpm_get_lmac_type, 253ad3f8f9SHariprasad Kelam .mac_lmac_intl_lbk = rpm_lmac_internal_loopback, 26ce7a6c31SHariprasad Kelam .mac_get_rx_stats = rpm_get_rx_stats, 27ce7a6c31SHariprasad Kelam .mac_get_tx_stats = rpm_get_tx_stats, 281845ada4SRakesh Babu .mac_enadis_rx_pause_fwding = rpm_lmac_enadis_rx_pause_fwding, 291845ada4SRakesh Babu .mac_get_pause_frm_status = rpm_lmac_get_pause_frm_status, 301845ada4SRakesh Babu .mac_enadis_pause_frm = rpm_lmac_enadis_pause_frm, 311845ada4SRakesh Babu .mac_pause_frm_config = rpm_lmac_pause_frm_config, 32*d1489208SHariprasad Kelam .mac_enadis_ptp_config = rpm_lmac_ptp_config, 3391c6945eSHariprasad Kelam }; 3491c6945eSHariprasad Kelam 3591c6945eSHariprasad Kelam struct mac_ops *rpm_get_mac_ops(void) 3691c6945eSHariprasad Kelam { 3791c6945eSHariprasad Kelam return &rpm_mac_ops; 3891c6945eSHariprasad Kelam } 3991c6945eSHariprasad Kelam 401845ada4SRakesh Babu static void rpm_write(rpm_t *rpm, u64 lmac, u64 offset, u64 val) 411845ada4SRakesh Babu { 421845ada4SRakesh Babu cgx_write(rpm, lmac, offset, val); 431845ada4SRakesh Babu } 441845ada4SRakesh Babu 4591c6945eSHariprasad Kelam static u64 rpm_read(rpm_t *rpm, u64 lmac, u64 offset) 4691c6945eSHariprasad Kelam { 4791c6945eSHariprasad Kelam return cgx_read(rpm, lmac, offset); 4891c6945eSHariprasad Kelam } 4991c6945eSHariprasad Kelam 5091c6945eSHariprasad Kelam int rpm_get_nr_lmacs(void *rpmd) 5191c6945eSHariprasad Kelam { 5291c6945eSHariprasad Kelam rpm_t *rpm = rpmd; 5391c6945eSHariprasad Kelam 5491c6945eSHariprasad Kelam return hweight8(rpm_read(rpm, 0, CGXX_CMRX_RX_LMACS) & 0xFULL); 5591c6945eSHariprasad Kelam } 561845ada4SRakesh Babu 571845ada4SRakesh Babu void rpm_lmac_enadis_rx_pause_fwding(void *rpmd, int lmac_id, bool enable) 581845ada4SRakesh Babu { 59ce7a6c31SHariprasad Kelam rpm_t *rpm = rpmd; 601845ada4SRakesh Babu u64 cfg; 611845ada4SRakesh Babu 621845ada4SRakesh Babu if (!rpm) 631845ada4SRakesh Babu return; 641845ada4SRakesh Babu 651845ada4SRakesh Babu if (enable) { 661845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 671845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 681845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 691845ada4SRakesh Babu } else { 701845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 711845ada4SRakesh Babu cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 721845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 731845ada4SRakesh Babu } 741845ada4SRakesh Babu } 751845ada4SRakesh Babu 761845ada4SRakesh Babu int rpm_lmac_get_pause_frm_status(void *rpmd, int lmac_id, 771845ada4SRakesh Babu u8 *tx_pause, u8 *rx_pause) 781845ada4SRakesh Babu { 791845ada4SRakesh Babu rpm_t *rpm = rpmd; 801845ada4SRakesh Babu u64 cfg; 811845ada4SRakesh Babu 821845ada4SRakesh Babu if (!is_lmac_valid(rpm, lmac_id)) 831845ada4SRakesh Babu return -ENODEV; 841845ada4SRakesh Babu 851845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 861845ada4SRakesh Babu *rx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE); 871845ada4SRakesh Babu 881845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 891845ada4SRakesh Babu *tx_pause = !(cfg & RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE); 901845ada4SRakesh Babu return 0; 911845ada4SRakesh Babu } 921845ada4SRakesh Babu 931845ada4SRakesh Babu int rpm_lmac_enadis_pause_frm(void *rpmd, int lmac_id, u8 tx_pause, 941845ada4SRakesh Babu u8 rx_pause) 951845ada4SRakesh Babu { 961845ada4SRakesh Babu rpm_t *rpm = rpmd; 971845ada4SRakesh Babu u64 cfg; 981845ada4SRakesh Babu 991845ada4SRakesh Babu if (!is_lmac_valid(rpm, lmac_id)) 1001845ada4SRakesh Babu return -ENODEV; 1011845ada4SRakesh Babu 1021845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1031845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 1041845ada4SRakesh Babu cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 1051845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 1061845ada4SRakesh Babu cfg |= rx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 1071845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1081845ada4SRakesh Babu 1091845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1101845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 1111845ada4SRakesh Babu cfg |= tx_pause ? 0x0 : RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 1121845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1131845ada4SRakesh Babu 1141845ada4SRakesh Babu cfg = rpm_read(rpm, 0, RPMX_CMR_RX_OVR_BP); 1151845ada4SRakesh Babu if (tx_pause) { 1161845ada4SRakesh Babu cfg &= ~RPMX_CMR_RX_OVR_BP_EN(lmac_id); 1171845ada4SRakesh Babu } else { 1181845ada4SRakesh Babu cfg |= RPMX_CMR_RX_OVR_BP_EN(lmac_id); 1191845ada4SRakesh Babu cfg &= ~RPMX_CMR_RX_OVR_BP_BP(lmac_id); 1201845ada4SRakesh Babu } 1211845ada4SRakesh Babu rpm_write(rpm, 0, RPMX_CMR_RX_OVR_BP, cfg); 1221845ada4SRakesh Babu return 0; 1231845ada4SRakesh Babu } 1241845ada4SRakesh Babu 1251845ada4SRakesh Babu void rpm_lmac_pause_frm_config(void *rpmd, int lmac_id, bool enable) 1261845ada4SRakesh Babu { 1271845ada4SRakesh Babu rpm_t *rpm = rpmd; 1281845ada4SRakesh Babu u64 cfg; 1291845ada4SRakesh Babu 1301845ada4SRakesh Babu if (enable) { 1311845ada4SRakesh Babu /* Enable 802.3 pause frame mode */ 1321845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1331845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PFC_MODE; 1341845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1351845ada4SRakesh Babu 1361845ada4SRakesh Babu /* Enable receive pause frames */ 1371845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1381845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 1391845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1401845ada4SRakesh Babu 1411845ada4SRakesh Babu /* Enable forward pause to TX block */ 1421845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1431845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 1441845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1451845ada4SRakesh Babu 1461845ada4SRakesh Babu /* Enable pause frames transmission */ 1471845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1481845ada4SRakesh Babu cfg &= ~RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 1491845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1501845ada4SRakesh Babu 1511845ada4SRakesh Babu /* Set pause time and interval */ 1521845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, 1531845ada4SRakesh Babu RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA); 1541845ada4SRakesh Babu cfg &= ~0xFFFFULL; 1551845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_CL01_PAUSE_QUANTA, 1561845ada4SRakesh Babu cfg | RPM_DEFAULT_PAUSE_TIME); 1571845ada4SRakesh Babu /* Set pause interval as the hardware default is too short */ 1581845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, 1591845ada4SRakesh Babu RPMX_MTI_MAC100X_CL01_QUANTA_THRESH); 1601845ada4SRakesh Babu cfg &= ~0xFFFFULL; 1611845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_CL01_QUANTA_THRESH, 1621845ada4SRakesh Babu cfg | (RPM_DEFAULT_PAUSE_TIME / 2)); 1631845ada4SRakesh Babu 1641845ada4SRakesh Babu } else { 1651845ada4SRakesh Babu /* ALL pause frames received are completely ignored */ 1661845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1671845ada4SRakesh Babu cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_RX_P_DISABLE; 1681845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1691845ada4SRakesh Babu 1701845ada4SRakesh Babu /* Disable forward pause to TX block */ 1711845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1721845ada4SRakesh Babu cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_PAUSE_IGNORE; 1731845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1741845ada4SRakesh Babu 1751845ada4SRakesh Babu /* Disable pause frames transmission */ 1761845ada4SRakesh Babu cfg = rpm_read(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG); 1771845ada4SRakesh Babu cfg |= RPMX_MTI_MAC100X_COMMAND_CONFIG_TX_P_DISABLE; 1781845ada4SRakesh Babu rpm_write(rpm, lmac_id, RPMX_MTI_MAC100X_COMMAND_CONFIG, cfg); 1791845ada4SRakesh Babu } 1801845ada4SRakesh Babu } 181ce7a6c31SHariprasad Kelam 182ce7a6c31SHariprasad Kelam int rpm_get_rx_stats(void *rpmd, int lmac_id, int idx, u64 *rx_stat) 183ce7a6c31SHariprasad Kelam { 184ce7a6c31SHariprasad Kelam rpm_t *rpm = rpmd; 185ce7a6c31SHariprasad Kelam u64 val_lo, val_hi; 186ce7a6c31SHariprasad Kelam 187ce7a6c31SHariprasad Kelam if (!rpm || lmac_id >= rpm->lmac_count) 188ce7a6c31SHariprasad Kelam return -ENODEV; 189ce7a6c31SHariprasad Kelam 190ce7a6c31SHariprasad Kelam mutex_lock(&rpm->lock); 191ce7a6c31SHariprasad Kelam 192ce7a6c31SHariprasad Kelam /* Update idx to point per lmac Rx statistics page */ 193ce7a6c31SHariprasad Kelam idx += lmac_id * rpm->mac_ops->rx_stats_cnt; 194ce7a6c31SHariprasad Kelam 195ce7a6c31SHariprasad Kelam /* Read lower 32 bits of counter */ 196ce7a6c31SHariprasad Kelam val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_RX_STAT_PAGES_COUNTERX + 197ce7a6c31SHariprasad Kelam (idx * 8)); 198ce7a6c31SHariprasad Kelam 199ce7a6c31SHariprasad Kelam /* upon read of lower 32 bits, higher 32 bits are written 200ce7a6c31SHariprasad Kelam * to RPMX_MTI_STAT_DATA_HI_CDC 201ce7a6c31SHariprasad Kelam */ 202ce7a6c31SHariprasad Kelam val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); 203ce7a6c31SHariprasad Kelam 204ce7a6c31SHariprasad Kelam *rx_stat = (val_hi << 32 | val_lo); 205ce7a6c31SHariprasad Kelam 206ce7a6c31SHariprasad Kelam mutex_unlock(&rpm->lock); 207ce7a6c31SHariprasad Kelam return 0; 208ce7a6c31SHariprasad Kelam } 209ce7a6c31SHariprasad Kelam 210ce7a6c31SHariprasad Kelam int rpm_get_tx_stats(void *rpmd, int lmac_id, int idx, u64 *tx_stat) 211ce7a6c31SHariprasad Kelam { 212ce7a6c31SHariprasad Kelam rpm_t *rpm = rpmd; 213ce7a6c31SHariprasad Kelam u64 val_lo, val_hi; 214ce7a6c31SHariprasad Kelam 215ce7a6c31SHariprasad Kelam if (!rpm || lmac_id >= rpm->lmac_count) 216ce7a6c31SHariprasad Kelam return -ENODEV; 217ce7a6c31SHariprasad Kelam 218ce7a6c31SHariprasad Kelam mutex_lock(&rpm->lock); 219ce7a6c31SHariprasad Kelam 220ce7a6c31SHariprasad Kelam /* Update idx to point per lmac Tx statistics page */ 221ce7a6c31SHariprasad Kelam idx += lmac_id * rpm->mac_ops->tx_stats_cnt; 222ce7a6c31SHariprasad Kelam 223ce7a6c31SHariprasad Kelam val_lo = rpm_read(rpm, 0, RPMX_MTI_STAT_TX_STAT_PAGES_COUNTERX + 224ce7a6c31SHariprasad Kelam (idx * 8)); 225ce7a6c31SHariprasad Kelam val_hi = rpm_read(rpm, 0, RPMX_MTI_STAT_DATA_HI_CDC); 226ce7a6c31SHariprasad Kelam 227ce7a6c31SHariprasad Kelam *tx_stat = (val_hi << 32 | val_lo); 228ce7a6c31SHariprasad Kelam 229ce7a6c31SHariprasad Kelam mutex_unlock(&rpm->lock); 230ce7a6c31SHariprasad Kelam return 0; 231ce7a6c31SHariprasad Kelam } 2323ad3f8f9SHariprasad Kelam 2333ad3f8f9SHariprasad Kelam u8 rpm_get_lmac_type(void *rpmd, int lmac_id) 2343ad3f8f9SHariprasad Kelam { 2353ad3f8f9SHariprasad Kelam rpm_t *rpm = rpmd; 2363ad3f8f9SHariprasad Kelam u64 req = 0, resp; 2373ad3f8f9SHariprasad Kelam int err; 2383ad3f8f9SHariprasad Kelam 2393ad3f8f9SHariprasad Kelam req = FIELD_SET(CMDREG_ID, CGX_CMD_GET_LINK_STS, req); 2403ad3f8f9SHariprasad Kelam err = cgx_fwi_cmd_generic(req, &resp, rpm, 0); 2413ad3f8f9SHariprasad Kelam if (!err) 2423ad3f8f9SHariprasad Kelam return FIELD_GET(RESP_LINKSTAT_LMAC_TYPE, resp); 2433ad3f8f9SHariprasad Kelam return err; 2443ad3f8f9SHariprasad Kelam } 2453ad3f8f9SHariprasad Kelam 2463ad3f8f9SHariprasad Kelam int rpm_lmac_internal_loopback(void *rpmd, int lmac_id, bool enable) 2473ad3f8f9SHariprasad Kelam { 2483ad3f8f9SHariprasad Kelam rpm_t *rpm = rpmd; 2493ad3f8f9SHariprasad Kelam u8 lmac_type; 2503ad3f8f9SHariprasad Kelam u64 cfg; 2513ad3f8f9SHariprasad Kelam 2523ad3f8f9SHariprasad Kelam if (!rpm || lmac_id >= rpm->lmac_count) 2533ad3f8f9SHariprasad Kelam return -ENODEV; 2543ad3f8f9SHariprasad Kelam lmac_type = rpm->mac_ops->get_lmac_type(rpm, lmac_id); 2553ad3f8f9SHariprasad Kelam if (lmac_type == LMAC_MODE_100G_R) { 2563ad3f8f9SHariprasad Kelam cfg = rpm_read(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1); 2573ad3f8f9SHariprasad Kelam 2583ad3f8f9SHariprasad Kelam if (enable) 2593ad3f8f9SHariprasad Kelam cfg |= RPMX_MTI_PCS_LBK; 2603ad3f8f9SHariprasad Kelam else 2613ad3f8f9SHariprasad Kelam cfg &= ~RPMX_MTI_PCS_LBK; 2623ad3f8f9SHariprasad Kelam rpm_write(rpm, lmac_id, RPMX_MTI_PCS100X_CONTROL1, cfg); 2633ad3f8f9SHariprasad Kelam } else { 2643ad3f8f9SHariprasad Kelam cfg = rpm_read(rpm, lmac_id, RPMX_MTI_LPCSX_CONTROL1); 2653ad3f8f9SHariprasad Kelam if (enable) 2663ad3f8f9SHariprasad Kelam cfg |= RPMX_MTI_PCS_LBK; 2673ad3f8f9SHariprasad Kelam else 2683ad3f8f9SHariprasad Kelam cfg &= ~RPMX_MTI_PCS_LBK; 2693ad3f8f9SHariprasad Kelam rpm_write(rpm, lmac_id, RPMX_MTI_LPCSX_CONTROL1, cfg); 2703ad3f8f9SHariprasad Kelam } 2713ad3f8f9SHariprasad Kelam 2723ad3f8f9SHariprasad Kelam return 0; 2733ad3f8f9SHariprasad Kelam } 274*d1489208SHariprasad Kelam 275*d1489208SHariprasad Kelam void rpm_lmac_ptp_config(void *rpmd, int lmac_id, bool enable) 276*d1489208SHariprasad Kelam { 277*d1489208SHariprasad Kelam rpm_t *rpm = rpmd; 278*d1489208SHariprasad Kelam u64 cfg; 279*d1489208SHariprasad Kelam 280*d1489208SHariprasad Kelam if (!is_lmac_valid(rpm, lmac_id)) 281*d1489208SHariprasad Kelam return; 282*d1489208SHariprasad Kelam 283*d1489208SHariprasad Kelam cfg = rpm_read(rpm, lmac_id, RPMX_CMRX_CFG); 284*d1489208SHariprasad Kelam if (enable) 285*d1489208SHariprasad Kelam cfg |= RPMX_RX_TS_PREPEND; 286*d1489208SHariprasad Kelam else 287*d1489208SHariprasad Kelam cfg &= ~RPMX_RX_TS_PREPEND; 288*d1489208SHariprasad Kelam rpm_write(rpm, lmac_id, RPMX_CMRX_CFG, cfg); 289*d1489208SHariprasad Kelam } 290