// SPDX-License-Identifier: GPL-2.0+ /* Copyright (c) 2013 Broadcom Corporation All Rights Reserved */ #include "dt_access.h" /* impl2 has mib counter as in part of conf, * so mib_base is conf_base + mib_offset. * however, the original mib_offset is meant for the difference * between each unimac's mib register area, which in this case * is the same as conf_offset. */ uintptr_t unimac_conf_base; uintptr_t unimac_mib_base; uintptr_t unimac_top_base; uint32_t conf_offset; uint32_t mib_offset; uint32_t top_offset; uint32_t mib_step; static int unimac_probe(dt_device_t *pdev) { int ret; dt_handle_t node = dt_dev_get_handle(pdev); unimac_conf_base = dt_dev_remap_resource(pdev, 0); if (IS_ERR(unimac_conf_base)) { ret = PTR_ERR(unimac_conf_base); unimac_conf_base = NULL; dev_err(&pdev->dev, "Missing unimac_conf_base entry\n"); goto Exit; } unimac_top_base = dt_dev_remap_resource(pdev, 1); if (IS_ERR(unimac_top_base)) { ret = PTR_ERR(unimac_top_base); unimac_top_base = NULL; dev_err(&pdev->dev, "Missing unimac_top_base entry\n"); goto Exit; } conf_offset = dt_property_read_u32(node, "conf_offset"); if (conf_offset == (uint32_t)(-1)) { ret = -1; dev_err(&pdev->dev, "Missing conf_offset entry\n"); goto Exit; } mib_offset = dt_property_read_u32(node, "mib_offset"); if (mib_offset == (uint32_t)(-1)) { ret = -1; dev_err(&pdev->dev, "Missing mib_offset entry\n"); goto Exit; } unimac_mib_base = unimac_conf_base + mib_offset; mib_offset = conf_offset; top_offset = dt_property_read_u32(node, "top_offset"); if (top_offset == (uint32_t)(-1)) { ret = -1; dev_err(&pdev->dev, "Missing top_offset entry\n"); goto Exit; } mib_step = dt_property_read_u32(node, "mib_step"); if (mib_step == (uint32_t)(-1)) { ret = -1; dev_err(&pdev->dev, "Missing mib_step entry\n"); goto Exit; } dev_dbg(&pdev->dev, "unimac_conf_base=0x%lx\n", unimac_conf_base); dev_dbg(&pdev->dev, "unimac_mib_base=0x%lx\n", unimac_mib_base); dev_dbg(&pdev->dev, "unimac_top_base=0x%lx\n", unimac_top_base); dev_dbg(&pdev->dev, "conf_offset=0x%x\n", conf_offset); dev_dbg(&pdev->dev, "mib_offset=0x%x\n", mib_offset); dev_dbg(&pdev->dev, "top_offset=0x%x\n", top_offset); dev_dbg(&pdev->dev, "mib_step=0x%x\n", mib_step); dev_info(&pdev->dev, "registered\n"); return 0; Exit: return ret; } #ifdef __UBOOT__ static const struct udevice_id unimac_ids[] = { { .compatible = "brcm,unimac" }, { .compatible = "brcm,unimac3" }, { /* end of list */ }, }; U_BOOT_DRIVER(brcm_unimac) = { .name = "brcm-unimac", .id = UCLASS_MISC, .of_match = unimac_ids, .probe = unimac_probe, }; #else static const struct of_device_id of_platform_table[] = { { .compatible = "brcm,unimac" }, { /* end of list */ }, }; static struct platform_driver of_platform_driver = { .driver = { .name = "brcm-unimac", .of_match_table = of_platform_table, }, .probe = unimac_probe, }; module_platform_driver(of_platform_driver); #endif /******************************************************************************/ /* */ /* File Description: */ /* */ /* This file contains the implementation of the HwApiMac for unimac */ /* */ /******************************************************************************/ /*****************************************************************************/ /* */ /* Include files */ /* */ /*****************************************************************************/ #if !(defined(CONFIG_BCM963158) || defined(CONFIG_BCM96846) || defined(CONFIG_BCM96856) || defined(CONFIG_BCM947622) || defined(CONFIG_BCM96878) || defined(CONFIG_BCM963146) || defined(CONFIG_BCM94912)) #ifdef __UBOOT__ static void get_rdp_freq(unsigned int *rdp_freq) {} #else #include "clk_rst.h" #endif #endif #if defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) #include "rdp_drv_bbh.h" #endif #include "unimac_drv.h" /******************************************************************************/ /* */ /* Types and values definitions */ /* */ /******************************************************************************/ #define UNIMAC_SWRESET_ON 1 #define UNIMAC_SWRESET_OFF 0 #define UNIMAC_DEFAULT_IPG 12 #define UNIMAC_DEFAULT_PAUSE_QUANTA 0xffff #define UNIMAC_DEFAULT_PAUSE_TIMER 0x1ffff #define UNIMAC_MAX_FRAME_LENGHT 0xffff #ifdef __UBOOT__ #define mac_unlikely(a) a #else #define mac_unlikely(a) unlikely(a) #endif #define UNIMAC_NUMBER_OF_SPEEDS ( UNIMAC_SPEED_2500 + 1 ) #define UNIMAC_NUMBER_OF_DUPLEXES ( UNIMAC_DUPLEX_FULL + 1 ) static uint32_t ipgSpeedTable[UNIMAC_NUMBER_OF_SPEEDS][UNIMAC_NUMBER_OF_DUPLEXES] = { {0x000a,0x000a}, {0x000a,0x000a}, {0x0005,0x0005}, {0x0005,0x0005} }; static uint32_t enabled_emac; /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_configuration */ /* */ /* Title: */ /* */ /* MAC Driver - get configuration */ /* */ /* Abstract: */ /* */ /* get the configuratin of a mac port ,note that current status of emac */ /* might be different than configuration when working in autoneg */ /* to get the current status use mac_hwapi_get_mac_status API */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* emac_cfg - structure holds the current configuration of the mac port */ /* */ /******************************************************************************/ void mac_hwapi_get_configuration(rdpa_emac emacNum,rdpa_emac_cfg_t *emac_cfg) { S_UNIMAC_CMD_REG mCfgReg; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); emac_cfg->allow_too_long = 0;//no such emac_cfg->back2back_gap = 0;//no such emac_cfg->check_length = !mCfgReg.no_lgth_check; emac_cfg->full_duplex = !mCfgReg.hd_ena; emac_cfg->generate_crc = 0; emac_cfg->loopback = mCfgReg.rmt_loop_ena; emac_cfg->non_back2back_gap = 0;//no such emac_cfg->pad_short = 0;//no such emac_cfg->rate = mCfgReg.eth_speed; emac_cfg->rx_flow_control = !mCfgReg.rx_pause_ignore; emac_cfg->tx_flow_control = !mCfgReg.tx_pause_ignore; UNIMAC_READ_FIELD(emacNum,HD_BKP_CNTL,ipg_config_rx,emac_cfg->min_interframe_gap); UNIMAC_READ_FIELD(emacNum,TX_IPG_LEN,tx_ipg_len,emac_cfg->preamble_length); } EXPORT_SYMBOL(mac_hwapi_get_configuration); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_configuration */ /* */ /* Title: */ /* */ /* MAC Driver - set configuration */ /* */ /* Abstract: */ /* */ /* set the configuratin of a mac port */ /* Input: */ /* */ /* emacNum - emac Port index */ /* emac_cfg - structure holds the current configuration of the mac port */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ void mac_hwapi_set_configuration(rdpa_emac emacNum,rdpa_emac_cfg_t *emac_cfg) { S_UNIMAC_CMD_REG mCfgReg; if (!(enabled_emac & (1 << emacNum))) return; /*first put the mac in reset to enable config change*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,1); UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); /*now mac configuration can be changed */ if(!mCfgReg.ena_ext_config) /* Change only if auto_config is not set */ { mCfgReg.eth_speed = emac_cfg->rate; mCfgReg.hd_ena = !emac_cfg->full_duplex; mCfgReg.rx_pause_ignore = !emac_cfg->rx_flow_control; mCfgReg.tx_pause_ignore = !emac_cfg->tx_flow_control; /*set the interframe gap*/ UNIMAC_WRITE_FIELD(emacNum,HD_BKP_CNTL,ipg_config_rx,ipgSpeedTable[emac_cfg->rate][(unsigned)emac_cfg->full_duplex]); } else { /*set the interframe gap*/ UNIMAC_WRITE_FIELD(emacNum,HD_BKP_CNTL,ipg_config_rx,emac_cfg->min_interframe_gap); } mCfgReg.no_lgth_check = !emac_cfg->check_length; mCfgReg.pad_en = emac_cfg->pad_short; mCfgReg.rmt_loop_ena = emac_cfg->loopback; UNIMAC_WRITE32_REG(emacNum,CMD,mCfgReg); /* set the preamble length */ UNIMAC_WRITE_FIELD(emacNum,TX_IPG_LEN,tx_ipg_len,emac_cfg->preamble_length); /* when link up at 10M, hold unimac reset longer per ASIC team */ if (emac_cfg->rate == rdpa_emac_rate_10m) udelay(1000); /*release the sw_reset bit*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,0); } EXPORT_SYMBOL(mac_hwapi_set_configuration); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_duplex */ /* */ /* Title: */ /* */ /* MAC Driver - get port duplex */ /* */ /* Abstract: */ /* */ /* get the dulplex of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* full_duples : 1 = full dulplex,0 = half_duplex */ /* */ /******************************************************************************/ void mac_hwapi_get_duplex(rdpa_emac emacNum,int32_t *full_duplex) { /*read field and reverse polarity*/ int32_t fieldData; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,CMD,hd_ena,fieldData); *full_duplex = !fieldData; } EXPORT_SYMBOL(mac_hwapi_get_duplex); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_duplex */ /* */ /* Title: */ /* */ /* MAC Driver - set port duplex */ /* */ /* Abstract: */ /* */ /* set the dulplex of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* full_duples : 1 = full dulplex,0 = half_duplex */ /* */ /******************************************************************************/ void mac_hwapi_set_duplex(rdpa_emac emacNum,int32_t full_duplex) { S_UNIMAC_CMD_REG mCfgReg; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); if (!mCfgReg.ena_ext_config) /* Change only if auto_config is not set */ { /*write the dulplex field in reverse polarity,must be set in sw_reset state*/ S_HWAPI_MAC_STATUS macMode; UNIMAC_READ32_REG(emacNum,MODE,macMode); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON); UNIMAC_WRITE_FIELD(emacNum,CMD,hd_ena,full_duplex ? 0 : 1); /*when setting the duplex we have to set new IPG value*/ //UNIMAC_WRITE_FIELD(emacNum,TX_IPG_LEN ,tx_ipg_len,ipgSpeedTable[macMode.mac_speed][macMode.mac_duplex]); /*take the mac out of sw_reset*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF); } } EXPORT_SYMBOL(mac_hwapi_set_duplex); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_speed */ /* */ /* Title: */ /* */ /* MAC Driver - get port speed rate */ /* */ /* Abstract: */ /* */ /* get the speed of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* rate - enum of the speed */ /******************************************************************************/ void mac_hwapi_get_speed(rdpa_emac emacNum,rdpa_emac_rate *rate) { if (!(enabled_emac & (1 << emacNum))) return; /*read the speed field*/ UNIMAC_READ_FIELD(emacNum,CMD,eth_speed,*rate); } EXPORT_SYMBOL(mac_hwapi_get_speed); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_speed */ /* */ /* Title: */ /* */ /* MAC Driver - set port speed rate */ /* */ /* Abstract: */ /* */ /* set the speed of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* rate - enum of the speed */ /* */ /* Output: */ /* */ /******************************************************************************/ void mac_hwapi_set_speed(rdpa_emac emacNum,rdpa_emac_rate rate) { S_UNIMAC_CMD_REG mCfgReg; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); if (!mCfgReg.ena_ext_config) /* Change only if auto_config is not set */ { UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON); UNIMAC_WRITE_FIELD(emacNum,CMD,eth_speed,rate); UNIMAC_WRITE_FIELD(emacNum,HD_BKP_CNTL,ipg_config_rx,ipgSpeedTable[rate][0]); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF); } } EXPORT_SYMBOL(mac_hwapi_set_speed); void mac_hwapi_set_external_conf(rdpa_emac emacNum, int enable) { S_UNIMAC_CMD_REG mCfgReg; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); mCfgReg.ena_ext_config = enable; UNIMAC_WRITE32_REG(emacNum,CMD,mCfgReg); } EXPORT_SYMBOL(mac_hwapi_set_external_conf); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_rxtx_enable */ /* */ /* Title: */ /* */ /* MAC Driver - set tx and rx enable */ /* */ /* Abstract: */ /* */ /* get tx and rx enable */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* rxtxEnable - boolean enable */ /******************************************************************************/ void mac_hwapi_get_rxtx_enable(rdpa_emac emacNum,int32_t *rxEnable,int32_t *txEnable) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,CMD,tx_ena,*txEnable); UNIMAC_READ_FIELD(emacNum,CMD,rx_ena,*rxEnable); } EXPORT_SYMBOL(mac_hwapi_get_rxtx_enable); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_rxtx_enable */ /* */ /* Title: */ /* */ /* MAC Driver - set tx and rx enable */ /* */ /* Abstract: */ /* */ /* set tx and rx enable */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* rxtxEnable - boolean enable */ /* */ /* Output: */ /* */ /******************************************************************************/ void mac_hwapi_set_rxtx_enable(rdpa_emac emacNum,int32_t rxEnable,int32_t txEnable) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_WRITE_FIELD(emacNum,CMD,tx_ena,txEnable); UNIMAC_WRITE_FIELD(emacNum,CMD,rx_ena,rxEnable); } EXPORT_SYMBOL(mac_hwapi_set_rxtx_enable); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_sw_reset */ /* */ /* Title: */ /* */ /* MAC Driver - get port software reset */ /* */ /* Abstract: */ /* */ /* get the sw reset bit of emac port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* swReset : 1 = reset,0 = not reset */ /* */ /******************************************************************************/ void mac_hwapi_get_sw_reset(rdpa_emac emacNum,int32_t *swReset) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,CMD,sw_reset,*swReset); } EXPORT_SYMBOL(mac_hwapi_get_sw_reset); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_sw_reset */ /* */ /* Title: */ /* */ /* MAC Driver - set port software reset */ /* */ /* Abstract: */ /* */ /* set the sw reset bit of emac port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* swReset : 1 = reset,0 = not reset */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ void mac_hwapi_set_sw_reset(rdpa_emac emacNum,int32_t swReset) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,swReset); } EXPORT_SYMBOL(mac_hwapi_set_sw_reset); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_tx_min_pkt_size */ /* */ /* Title: */ /* */ /* MAC Driver - get tx minimum packet size */ /* */ /* Abstract: */ /* */ /* Get the unimac configuration for minimum tx packet size */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* min_pkt_size : 14...125 */ /* */ /******************************************************************************/ void mac_hwapi_get_tx_min_pkt_size(rdpa_emac emacNum,int32_t *min_pkt_size) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,TX_IPG_LEN,tx_min_pkt_size,*min_pkt_size); } EXPORT_SYMBOL(mac_hwapi_get_tx_min_pkt_size); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_tx_min_pkt_size */ /* */ /* Title: */ /* */ /* MAC Driver - set tx minimum packet size */ /* */ /* Abstract: */ /* */ /* Set the unimac configuration for minimum tx packet size */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* min_pkt_size : 14...125 */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ void mac_hwapi_set_tx_min_pkt_size(rdpa_emac emacNum,int32_t min_pkt_size) { if (!(enabled_emac & (1 << emacNum))) return; #if defined(CONFIG_BCM94908) || defined(CONFIG_BCM963158) || defined(CONFIG_BCM947622) UNIMAC_WRITE_FIELD(emacNum,TX_IPG_LEN,tx_min_pkt_size,min_pkt_size); #endif } EXPORT_SYMBOL(mac_hwapi_set_tx_min_pkt_size); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_tx_max_frame_len */ /* */ /* Title: */ /* */ /* MAC Driver - get port TX MTU */ /* */ /* Abstract: */ /* */ /* get the port maximum transmit unit size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* maxTxFrameLen - size of frame in bytes */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_get_tx_max_frame_len(rdpa_emac emacNum,uint32_t *maxTxFrameLen ) { S_UNIMAC_TOPCTRL_MAX_PKT_SZ_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOPCTRL_MIB_MAX_PKT_SIZE + UNIMAC_TOPCTRL_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; READ_32(address,cfgreg); *maxTxFrameLen = cfgreg.max_pkt_size; } #else //!47622 void mac_hwapi_get_tx_max_frame_len(rdpa_emac emacNum,uint32_t *maxTxFrameLen ) { S_UNIMAC_TOP_CFG1_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG1 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; READ_32(address,cfgreg); *maxTxFrameLen = cfgreg.max_pkt_size; } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_get_tx_max_frame_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_tx_max_frame_len */ /* */ /* Title: */ /* */ /* MAC Driver - set port TX MTU */ /* */ /* Abstract: */ /* */ /* set the port maximum transmit unit size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* maxTxFrameLen - size of frame in bytes */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_set_tx_max_frame_len(rdpa_emac emacNum,uint32_t maxTxFrameLen ) { S_UNIMAC_TOPCTRL_MAX_PKT_SZ_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOPCTRL_MIB_MAX_PKT_SIZE + UNIMAC_TOPCTRL_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; /*put emac in sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON ); READ_32(address,cfgreg); cfgreg.max_pkt_size = maxTxFrameLen; WRITE_32(address,cfgreg); UNIMAC_WRITE_FIELD(emacNum,FRM_LEN,frame_length,UNIMAC_MAX_FRAME_LENGHT); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF ); } #else //!47622 void mac_hwapi_set_tx_max_frame_len(rdpa_emac emacNum,uint32_t maxTxFrameLen ) { S_UNIMAC_TOP_CFG1_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG1 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; /*put emac in sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON ); READ_32(address,cfgreg); cfgreg.max_pkt_size = maxTxFrameLen; WRITE_32(address,cfgreg); UNIMAC_WRITE_FIELD(emacNum,FRM_LEN,frame_length,UNIMAC_MAX_FRAME_LENGHT); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF ); } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_set_tx_max_frame_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_rx_max_frame_len */ /* */ /* Title: */ /* */ /* MAC Driver - get port RX MTU */ /* */ /* Abstract: */ /* */ /* get the port maximum receive unit size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* maxRxFrameLen - size of current MRU */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_get_rx_max_frame_len(rdpa_emac emacNum,uint32_t *maxRxFrameLen ) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,FRM_LEN,frame_length,*maxRxFrameLen ); } #else //!47622 void mac_hwapi_get_rx_max_frame_len(rdpa_emac emacNum,uint32_t *maxRxFrameLen ) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,RX_MAX_PKT_SIZE,max_pkt_size,*maxRxFrameLen ); } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_get_rx_max_frame_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_rx_max_frame_len */ /* */ /* Title: */ /* */ /* MAC Driver - set port RX MTU */ /* */ /* Abstract: */ /* */ /* set the port maximum receive unit size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* maxRxFrameLen - size of current MRU */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_set_rx_max_frame_len(rdpa_emac emacNum,uint32_t maxRxFrameLen ) { S_UNIMAC_TOPCTRL_MAX_PKT_SZ_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOPCTRL_MIB_MAX_PKT_SIZE + UNIMAC_TOPCTRL_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; /*put emac in sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON ); READ_32(address,cfgreg); cfgreg.max_pkt_size = maxRxFrameLen; WRITE_32(address,cfgreg); UNIMAC_WRITE_FIELD(emacNum,FRM_LEN,frame_length,maxRxFrameLen); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF ); } #else //!47622 void mac_hwapi_set_rx_max_frame_len(rdpa_emac emacNum,uint32_t maxRxFrameLen ) { S_UNIMAC_TOP_CFG1_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG1 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; /*put emac in sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON ); READ_32(address,cfgreg); cfgreg.max_pkt_size = maxRxFrameLen; WRITE_32(address,cfgreg); UNIMAC_WRITE_FIELD(emacNum,RX_MAX_PKT_SIZE,max_pkt_size,maxRxFrameLen); /*put emac out sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF ); } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_set_rx_max_frame_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_tx_igp_len */ /* */ /* Title: */ /* */ /* MAC Driver - set port inter frame gap */ /* */ /* Abstract: */ /* */ /* set the inter frame gap size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* txIpgLen - length in bytes */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ void mac_hwapi_set_tx_igp_len(rdpa_emac emacNum,uint32_t txIpgLen ) { /*we assume that txIpgLen called with bits time resolution*/ uint32_t newIpg; if (!(enabled_emac & (1 << emacNum))) return; /*put emac in sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON ); txIpgLen += 7; newIpg = txIpgLen / 8; if (newIpg < 8) { newIpg = 8; } else if (newIpg > 27) { newIpg = 27; } UNIMAC_WRITE_FIELD(emacNum,TX_IPG_LEN,tx_ipg_len,newIpg ); /*put emac out sw reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF ); } EXPORT_SYMBOL(mac_hwapi_set_tx_igp_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_tx_igp_len */ /* */ /* Title: */ /* */ /* MAC Driver - get port inter frame gap */ /* */ /* Abstract: */ /* */ /* get the inter frame gap size in bytes */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* txIpgLen - length in bytes */ /* */ /******************************************************************************/ void mac_hwapi_get_tx_igp_len(rdpa_emac emacNum,uint32_t *txIpgLen ) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,TX_IPG_LEN,tx_ipg_len,*txIpgLen ); } EXPORT_SYMBOL(mac_hwapi_get_tx_igp_len); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_mac_status */ /* */ /* Title: */ /* */ /* MAC Driver - set port status */ /* */ /* Abstract: */ /* */ /* set the status of mac */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* macStatus : */ /* */ /******************************************************************************/ void mac_hwapi_get_mac_status(rdpa_emac emacNum,S_HWAPI_MAC_STATUS *macStatus) { } EXPORT_SYMBOL(mac_hwapi_get_mac_status); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_flow_control */ /* */ /* Title: */ /* */ /* MAC Driver - get port flow control */ /* */ /* Abstract: */ /* */ /* get the flow control of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* flowControl - structure with parameters of tx and rx flow control */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_get_flow_control(rdpa_emac emacNum,S_MAC_HWAPI_FLOW_CTRL *flowControl) { uint32_t rxFlow, txFlow; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ_FIELD(emacNum,CMD,rx_pause_ignore,rxFlow); UNIMAC_READ_FIELD(emacNum,CMD,tx_pause_ignore,txFlow); flowControl->rxFlowEnable = !rxFlow; flowControl->txFlowEnable = !txFlow; } #else //!47622 void mac_hwapi_get_flow_control(rdpa_emac emacNum,S_MAC_HWAPI_FLOW_CTRL *flowControl) { uint32_t rxFlow, txFlow, value; uintptr_t misc_top_address; if (!(enabled_emac & (1 << emacNum))) return; misc_top_address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); READ_32(misc_top_address, value); if(value & UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2_BACKPRESSURE_ENABLE_INT) { UNIMAC_READ_FIELD(emacNum,CMD,rx_pause_ignore,rxFlow); UNIMAC_READ_FIELD(emacNum,CMD,tx_pause_ignore,txFlow); flowControl->rxFlowEnable = !rxFlow; flowControl->txFlowEnable = !txFlow; } else { flowControl->rxFlowEnable = 0; flowControl->txFlowEnable = 0; } } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_get_flow_control); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_pause_params */ /* */ /* Title: */ /* */ /* MAC Driver - set port flow control */ /* */ /* Abstract: */ /* */ /* set the flow control of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* flowControl - structure with parameters of tx and rx flow control */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ void mac_hwapi_set_pause_params(rdpa_emac emacNum,int32_t pauseCtrlEnable,uint32_t pauseTimer,uint32_t pauseQuanta) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_WRITE_FIELD(emacNum,PAUSE_CNTRL,pause_control_en,pauseCtrlEnable ); UNIMAC_WRITE_FIELD(emacNum,PAUSE_CNTRL,pause_timer,pauseTimer ); UNIMAC_WRITE_FIELD(emacNum,PAUSE_QUNAT,pause_quant,pauseQuanta ); } EXPORT_SYMBOL(mac_hwapi_set_pause_params); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_flow_control */ /* */ /* Title: */ /* */ /* MAC Driver - set port flow control */ /* */ /* Abstract: */ /* */ /* set the flow control of a port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* flowControl - structure with parameters of tx and rx flow control */ /* */ /* Output: */ /* */ /* */ /******************************************************************************/ #if defined(CONFIG_BCM947622) void mac_hwapi_set_flow_control(rdpa_emac emacNum,S_MAC_HWAPI_FLOW_CTRL *flowControl) { if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_WRITE_FIELD(emacNum,CMD,sw_override_rx, 1); UNIMAC_WRITE_FIELD(emacNum,CMD,sw_override_tx, 1); UNIMAC_WRITE_FIELD(emacNum,CMD,rx_pause_ignore, !flowControl->rxFlowEnable); UNIMAC_WRITE_FIELD(emacNum,CMD,tx_pause_ignore, !flowControl->txFlowEnable); } #else //!47622 void mac_hwapi_set_flow_control(rdpa_emac emacNum,S_MAC_HWAPI_FLOW_CTRL *flowControl) { uintptr_t misc_top_address; uint32_t value; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_WRITE_FIELD(emacNum,CMD,rx_pause_ignore, !flowControl->rxFlowEnable); UNIMAC_WRITE_FIELD(emacNum,CMD,tx_pause_ignore, !flowControl->txFlowEnable); misc_top_address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); READ_32(misc_top_address, value); if(flowControl->rxFlowEnable || flowControl->txFlowEnable) value |= UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2_BACKPRESSURE_ENABLE_INT; else value &= ~UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2_BACKPRESSURE_ENABLE_INT; WRITE_32(misc_top_address, value); } #endif //!47622 EXPORT_SYMBOL(mac_hwapi_set_flow_control); static rdpa_emac_rx_stat_t rxCountersLast[MAX_NUM_OF_EMACS]; #define UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, param) \ do{\ uint32_t paramCurrent = rxCounters->param; \ if(mac_unlikely(rxCounters->param < rxCountersLast[emacNum].param)){ \ rxCounters->param += (0xFFFFFFFF-rxCountersLast[emacNum].param)+1; \ }else{ \ rxCounters->param -= rxCountersLast[emacNum].param; \ } \ rxCountersLast[emacNum].param = paramCurrent; \ }while(0) /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_rx_counters */ /* */ /* Title: */ /* */ /* MAC Driver - get the rx counters of port */ /* */ /* Abstract: */ /* */ /* get the rx counters of port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* rxCounters : structure filled with counters */ /* */ /******************************************************************************/ void mac_hwapi_get_rx_counters(rdpa_emac emacNum,rdpa_emac_rx_stat_t *rxCounters) { uint32_t tempVal; if (!(enabled_emac & (1 << emacNum))) { memset(rxCounters, 0, sizeof(rdpa_emac_rx_stat_t)); return; } UNIMAC_READ32_MIB(emacNum,GRALN,rxCounters->alignment_error); UNIMAC_READ32_MIB(emacNum,GRBCA,rxCounters->broadcast_packet); UNIMAC_READ32_MIB(emacNum,GRUC, rxCounters->unicast_packet); UNIMAC_READ32_MIB(emacNum,GRBYT,rxCounters->byte); UNIMAC_READ32_MIB(emacNum,RRBYT,tempVal); rxCounters->byte += tempVal; UNIMAC_READ32_MIB(emacNum,GRFCR,rxCounters->carrier_sense_error); UNIMAC_READ32_MIB(emacNum,GRCDE,rxCounters->code_error); UNIMAC_READ32_MIB(emacNum,GRXCF,rxCounters->control_frame); UNIMAC_READ32_MIB(emacNum,GRFCS,rxCounters->fcs_error); rxCounters->fragments = 0;//????? UNIMAC_READ32_MIB(emacNum,GR255,rxCounters->frame_128_255); UNIMAC_READ32_MIB(emacNum,GR2047,tempVal); rxCounters->frame_1519_mtu = tempVal; UNIMAC_READ32_MIB(emacNum,GR4095,tempVal); rxCounters->frame_1519_mtu += tempVal; UNIMAC_READ32_MIB(emacNum,GR9216,tempVal); rxCounters->frame_1519_mtu += tempVal; UNIMAC_READ32_MIB(emacNum,GR511,rxCounters->frame_256_511); UNIMAC_READ32_MIB(emacNum,GR1023,rxCounters->frame_512_1023); UNIMAC_READ32_MIB(emacNum,GR1518,rxCounters->frame_1024_1518); UNIMAC_READ32_MIB(emacNum,GR64,rxCounters->frame_64); UNIMAC_READ32_MIB(emacNum,GR127,rxCounters->frame_65_127); UNIMAC_READ32_MIB(emacNum,GRFLR,rxCounters->frame_length_error); UNIMAC_READ32_MIB(emacNum,GRJBR,rxCounters->jabber); UNIMAC_READ32_MIB(emacNum,GRMCA,rxCounters->multicast_packet); rxCounters->overflow = 0;//no matched counter UNIMAC_READ32_MIB(emacNum,GROVR,rxCounters->oversize_packet); UNIMAC_READ32_MIB(emacNum,RRPKT,rxCounters->undersize_packet); UNIMAC_READ32_MIB(emacNum,GRPKT,rxCounters->packet); UNIMAC_READ32_MIB(emacNum,GRXPF,rxCounters->pause_control_frame); UNIMAC_READ32_MIB(emacNum,GRXUO,rxCounters->unknown_opcode); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, alignment_error); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, broadcast_packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, unicast_packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, byte); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, carrier_sense_error); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, code_error); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, control_frame); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, fcs_error); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_64); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_65_127); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_128_255); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_256_511); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_512_1023); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_1024_1518); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_1519_mtu); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, frame_length_error); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, jabber); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, multicast_packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, oversize_packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, undersize_packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, packet); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, pause_control_frame); UNIMAC_CURRENT_RX_COUNTERS(emacNum, rxCounters, unknown_opcode); } EXPORT_SYMBOL(mac_hwapi_get_rx_counters); static rdpa_emac_tx_stat_t txCountersLast[MAX_NUM_OF_EMACS]; #define UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, param) \ do{\ uint32_t paramCurrent = txCounters->param; \ if(mac_unlikely(txCounters->param < txCountersLast[emacNum].param)){ \ txCounters->param += (0xFFFFFFFF-txCountersLast[emacNum].param)+1; \ }else{ \ txCounters->param -= txCountersLast[emacNum].param; \ } \ txCountersLast[emacNum].param = paramCurrent; \ }while(0) /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_tx_counters */ /* */ /* Title: */ /* */ /* MAC Driver - get the tx counters of port */ /* */ /* Abstract: */ /* */ /* get the tx counters of port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* txCounters : structure filled with counters */ /* */ /******************************************************************************/ void mac_hwapi_get_tx_counters(rdpa_emac emacNum,rdpa_emac_tx_stat_t *txCounters) { /*fill the rdpa counters structure*/ uint32_t tempVal; if (!(enabled_emac & (1 << emacNum))) { memset(txCounters, 0, sizeof(rdpa_emac_tx_stat_t)); return; } UNIMAC_READ32_MIB(emacNum,GTBYT,txCounters->byte); UNIMAC_READ32_MIB(emacNum,GTBCA,txCounters->broadcast_packet); UNIMAC_READ32_MIB(emacNum,GTMCA, txCounters->multicast_packet); UNIMAC_READ32_MIB(emacNum,GTUC, txCounters->unicast_packet); UNIMAC_READ32_MIB(emacNum,GTXCF,txCounters->control_frame); UNIMAC_READ32_MIB(emacNum,GTDRF,txCounters->deferral_packet); UNIMAC_READ32_MIB(emacNum,GTNCL,tempVal); txCounters->error = tempVal; UNIMAC_READ32_MIB(emacNum,GTOVR,tempVal); txCounters->error += tempVal; UNIMAC_READ32_MIB(emacNum,GTFCS,tempVal); txCounters->error += tempVal; UNIMAC_READ32_MIB(emacNum,GTEDF,txCounters->excessive_deferral_packet); UNIMAC_READ32_MIB(emacNum,GTFCS,txCounters->fcs_error ); UNIMAC_READ32_MIB(emacNum,GTFRG,txCounters->fragments_frame); UNIMAC_READ32_MIB(emacNum,TR1518,txCounters->frame_1024_1518); UNIMAC_READ32_MIB(emacNum,TR255, txCounters->frame_128_255); UNIMAC_READ32_MIB(emacNum,TR2047, tempVal); txCounters->frame_1519_mtu = tempVal; UNIMAC_READ32_MIB(emacNum,TR4095, tempVal); txCounters->frame_1519_mtu += tempVal; UNIMAC_READ32_MIB(emacNum,TR9216, tempVal); txCounters->frame_1519_mtu += tempVal; UNIMAC_READ32_MIB(emacNum,TR511, txCounters->frame_256_511); UNIMAC_READ32_MIB(emacNum,TR1023, txCounters->frame_512_1023); UNIMAC_READ32_MIB(emacNum,TR64,txCounters->frame_64); UNIMAC_READ32_MIB(emacNum,TR127, txCounters->frame_65_127); UNIMAC_READ32_MIB(emacNum,GTJBR, txCounters->jabber_frame); UNIMAC_READ32_MIB(emacNum,GTLCL, txCounters->late_collision); UNIMAC_READ32_MIB(emacNum,GTMCL, txCounters->multiple_collision); UNIMAC_READ32_MIB(emacNum,GTOVR,txCounters->oversize_frame); UNIMAC_READ32_MIB(emacNum,GTPOK, txCounters->packet); UNIMAC_READ32_MIB(emacNum,GTXPF, txCounters->pause_control_frame); UNIMAC_READ32_MIB(emacNum,GTSCL, txCounters->single_collision); UNIMAC_READ32_MIB(emacNum,GTNCL, txCounters->total_collision); UNIMAC_READ32_MIB(emacNum,GTXCL, txCounters->excessive_collision); txCounters->underrun = 0; txCounters->undersize_frame = 0; UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, byte); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, broadcast_packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, multicast_packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, unicast_packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, deferral_packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, excessive_deferral_packet); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, control_frame); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, jabber_frame); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, oversize_frame); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, pause_control_frame); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, fragments_frame); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, error); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, fcs_error); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_64); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_65_127); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_128_255); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_256_511); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_512_1023); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_1024_1518); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, frame_1519_mtu); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, single_collision); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, total_collision); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, late_collision); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, multiple_collision); UNIMAC_CURRENT_TX_COUNTERS(emacNum, txCounters, excessive_collision); } EXPORT_SYMBOL(mac_hwapi_get_tx_counters); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_init_emac */ /* */ /* Title: */ /* */ /* MAC Driver - init the emac to well known state */ /* */ /* Abstract: */ /* */ /* initialized the emac port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* */ /******************************************************************************/ void mac_hwapi_init_emac(rdpa_emac emacNum) { /*configure the emac and put it in automatic speed mode*/ S_UNIMAC_CMD_REG mCfgReg; uint32_t max_frame_length = UNIMAC_MAX_FRAME_LENGHT; /*before calling this function make sure you pull out of reset the emac */ /*put the emac in sw_reset state*/ //UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON); UNIMAC_READ32_REG(emacNum,CMD,mCfgReg); /* Do the initialization */ mCfgReg.tx_ena = 0; mCfgReg.rx_ena = 0; /* for 63138 - even though the EMAC_1 is connected to SF2 @ 2Gbps, we still set the link to 1G. * Actual speed of the link is derived from SF2 based on the speed set for IMP port#8. */ mCfgReg.eth_speed = UNIMAC_SPEED_1000; mCfgReg.promis_en = 1; mCfgReg.pad_en = 0; mCfgReg.pause_fwd = 1; mCfgReg.crc_fwd = 1; mCfgReg.ena_ext_config = 0; mCfgReg.rx_pause_ignore = 0; mCfgReg.tx_pause_ignore = 0; mCfgReg.tx_addr_ins = 0; mCfgReg.lcl_loop_ena = 0; mCfgReg.cntl_frm_ena = 1; mCfgReg.no_lgth_check = 1; mCfgReg.rmt_loop_ena = 0; mCfgReg.rx_err_disc = 0; mCfgReg.prbl_ena = 0; mCfgReg.cntl_frm_ena = 1; /*write the configuration */ UNIMAC_WRITE32_REG(emacNum,CMD,mCfgReg); UNIMAC_WRITE32_REG(emacNum,FRM_LEN, max_frame_length); /*take out the emac from sw_reset state*/ //UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF); #if 0 /*configure the pause control*/ UNIMAC_WRITE_FIELD(emacNum,PAUSE_CNTRL,pause_timer,UNIMAC_DEFAULT_PAUSE_TIMER); UNIMAC_WRITE_FIELD(emacNum,PAUSE_CNTRL,pause_control_en,1); /*configure the pause quanta*/ UNIMAC_WRITE_FIELD(emacNum,PAUSE_QUNAT,pause_quant,UNIMAC_DEFAULT_PAUSE_QUANTA); /*write default ipg*/ UNIMAC_WRITE_FIELD(emacNum,TX_IPG_LEN,tx_ipg_len,UNIMAC_DEFAULT_IPG); #endif memset(&rxCountersLast, 0, MAX_NUM_OF_EMACS*sizeof(rdpa_emac_rx_stat_t)); memset(&txCountersLast, 0, MAX_NUM_OF_EMACS*sizeof(rdpa_emac_tx_stat_t)); enabled_emac |= (1 << emacNum); /*emac is ready to go!*/ } EXPORT_SYMBOL(mac_hwapi_init_emac); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_get_loopback */ /* */ /* Title: */ /* */ /* MAC Driver - init the emac to well known state */ /* */ /* Abstract: */ /* */ /* initialized the emac port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* */ /******************************************************************************/ void mac_hwapi_get_loopback(rdpa_emac emacNum,MAC_LPBK *loopback) { S_UNIMAC_CMD_REG mCmdReg; if (!(enabled_emac & (1 << emacNum))) return; UNIMAC_READ32_REG(emacNum,CMD,mCmdReg); if (mCmdReg.lcl_loop_ena && mCmdReg.rmt_loop_ena) { *loopback = MAC_LPBK_BOTH; } else if (mCmdReg.lcl_loop_ena) { *loopback = MAC_LPBK_LOCAL; } else if (mCmdReg.rmt_loop_ena) { *loopback = MAC_LPBK_REMOTE; } else { *loopback = MAC_LPBK_NONE; } } EXPORT_SYMBOL(mac_hwapi_get_loopback); /******************************************************************************/ /* */ /* Name: */ /* */ /* mac_hwapi_set_loopback */ /* */ /* Title: */ /* */ /* MAC Driver - set loopback type of the mac */ /* */ /* Abstract: */ /* */ /* initialized the emac port */ /* */ /* Input: */ /* */ /* emacNum - emac Port index */ /* */ /* */ /* Output: */ /* */ /******************************************************************************/ void mac_hwapi_set_loopback(rdpa_emac emacNum,MAC_LPBK loopback) { if (!(enabled_emac & (1 << emacNum))) return; /*put the emac in sw_reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_ON); switch(loopback) { case MAC_LPBK_BOTH: UNIMAC_WRITE_FIELD(emacNum,CMD,rmt_loop_ena,1); UNIMAC_WRITE_FIELD(emacNum,CMD, lcl_loop_ena,1); break; case MAC_LPBK_LOCAL: UNIMAC_WRITE_FIELD(emacNum,CMD, lcl_loop_ena,1); break; case MAC_LPBK_REMOTE: UNIMAC_WRITE_FIELD(emacNum,CMD,rmt_loop_ena,1); break; case MAC_LPBK_NONE: UNIMAC_WRITE_FIELD(emacNum,CMD,rmt_loop_ena,0); UNIMAC_WRITE_FIELD(emacNum,CMD, lcl_loop_ena,0); break; default: break; } /* take out the emac from sw_reset state*/ UNIMAC_WRITE_FIELD(emacNum,CMD,sw_reset,UNIMAC_SWRESET_OFF); } EXPORT_SYMBOL(mac_hwapi_set_loopback); void mac_hwapi_set_unimac_cfg(rdpa_emac emacNum, int32_t enabled) { #if !defined(CONFIG_BCM947622) && !defined(CONFIG_BCM963146) && !defined(CONFIG_BCM94912) S_UNIMAC_CFG_REG cfgreg; uintptr_t address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_CFG + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; READ_32(address,cfgreg); cfgreg.gmii_direct = enabled ? 1 : 0; WRITE_32(address,cfgreg); #endif } EXPORT_SYMBOL(mac_hwapi_set_unimac_cfg); void mac_hwapi_modify_flow_control_pause_pkt_addr ( rdpa_emac emacNum,bdmf_mac_t mac) { uint32_t value = *(uint32_t*)(&(mac.b[4])) >> 16 ; uintptr_t mac_address = (uintptr_t)UNIMAC_CONFIGURATION_UMAC_0_RDP_MAC0 + UNIMAC_CONF_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; WRITE_32(mac_address, *(uint32_t*)mac.b); mac_address = (uintptr_t)UNIMAC_CONFIGURATION_UMAC_0_RDP_MAC1 + UNIMAC_CONF_INSTANCE_OFFSET(emacNum); WRITE_32(mac_address, value); } EXPORT_SYMBOL(mac_hwapi_modify_flow_control_pause_pkt_addr); void mac_hwapi_set_backpressure_ext(rdpa_emac emacNum,int32_t enable) { #if defined(CONFIG_BCM963138) || defined(CONFIG_BCM963148) || defined(CONFIG_BCM94908) || defined(CONFIG_BCM963158) S_UNIMAC_TOP_CFG2_REG cfgreg; uintptr_t misc_top_address = (uintptr_t)UNIMAC_TOP_UNIMAC_MISC_UNIMAC_EXT_CFG2 + UNIMAC_MISC_INSTANCE_OFFSET(emacNum); if (!(enabled_emac & (1 << emacNum))) return; READ_32(misc_top_address,cfgreg); cfgreg.backpressure_enable_ext = (enable ? 1 : 0); WRITE_32(misc_top_address,cfgreg); #endif } EXPORT_SYMBOL(mac_hwapi_set_backpressure_ext); void mac_hwapi_set_eee(rdpa_emac emacNum, int32_t enable) { uint32_t eee_ref_count = 0; uint32_t eee_wake_timer = 0; uint32_t eee_lpi_timer = 0; S_UNIMAC_EEE_CTRL_REG eee_ctrl; S_HWAPI_MAC_STATUS mac_mode; /* Determine EEE timers only when EEE is enabled */ if (enable) { #if defined(CONFIG_BCM963158) || defined(CONFIG_BCM96846) || defined(CONFIG_BCM96856) || defined(CONFIG_BCM947622) || defined(CONFIG_BCM96878) || defined(CONFIG_BCM963146) || defined(CONFIG_BCM94912) eee_ref_count = 0xfa; /* 250 Mhz */; #else get_rdp_freq(&eee_ref_count); eee_ref_count /= 2; #endif /* Read actual mac speed */ UNIMAC_READ32_REG(emacNum, MODE, mac_mode); switch (mac_mode.mac_speed) { case rdpa_emac_rate_100m: /* 100Mbps */ { eee_lpi_timer = 0x3c; /* 60 uS */ eee_wake_timer = 0x1e; /* 30 uS */ break; } case rdpa_emac_rate_1g: /* 1000Mbps */ { eee_lpi_timer = 0x22; /* 34 uS */ eee_wake_timer = 0x11; /* 17 uS */ break; } case rdpa_emac_rate_2_5g: /* 2500Mbps */ { eee_lpi_timer = 0x3c; /* 60 uS */ eee_wake_timer = 0x1e; /* 30 uS */ break; } default: break; } } UNIMAC_READ32_REG(emacNum, EEE_CTRL, eee_ctrl); eee_ctrl.eee_en = enable ? 1 : 0; UNIMAC_WRITE32_REG(emacNum, EEE_CTRL, eee_ctrl); UNIMAC_WRITE32_REG(emacNum, EEE_REF_COUNT, eee_ref_count); #if defined(CONFIG_BCM96856) || defined(CONFIG_BCM947622) if (mac_mode.mac_speed == rdpa_emac_rate_100m) { UNIMAC_WRITE32_REG(emacNum, EEE_MII_LPI_TIMER, eee_lpi_timer); UNIMAC_WRITE32_REG(emacNum, EEE_MII_WAKE_TIMER, eee_wake_timer); } else { UNIMAC_WRITE32_REG(emacNum, EEE_GMII_LPI_TIMER, eee_lpi_timer); UNIMAC_WRITE32_REG(emacNum, EEE_GMII_WAKE_TIMER, eee_wake_timer); } #else UNIMAC_WRITE32_REG(emacNum, EEE_LPI_TIMER, eee_lpi_timer); UNIMAC_WRITE32_REG(emacNum, EEE_WAKE_TIMER, eee_wake_timer); #endif } EXPORT_SYMBOL(mac_hwapi_set_eee);