/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2017-08-24 chinesebear first version * 2020-08-10 lizhirui porting to ls2k */ #include "synopGMAC_Dev.h" #include #include #define UNUSED 1 /** * Function to set the MDC clock for mdio transactiona * * @param[in] pointer to device structure. * @param[in] clk divider value. * \return Reuturns 0 on success else return the error value. */ s32 synopGMAC_set_mdc_clk_div(synopGMACdevice *gmacdev, u32 clk_div_val) { u32 orig_data; orig_data = synopGMACReadReg(gmacdev -> MacBase, GmacGmiiAddr); //set the mdc clock to the user defined value orig_data &= (~GmiiCsrClkMask); orig_data |= clk_div_val; synopGMACWriteReg(gmacdev -> MacBase, GmacGmiiAddr, orig_data); return 0; } /** * Returns the current MDC divider value programmed in the ip. * * @param[in] pointer to device structure. * @param[in] clk divider value. * \return Returns the MDC divider value read. */ u32 synopGMAC_get_mdc_clk_div(synopGMACdevice *gmacdev) { u32 data; data = synopGMACReadReg(gmacdev->MacBase, GmacGmiiAddr); data &= GmiiCsrClkMask; return data; } /** * Function to read the Phy register. The access to phy register * is a slow process as the data is moved accross MDI/MDO interface * @param[in] pointer to Register Base (It is the mac base in our case) . * @param[in] PhyBase register is the index of one of supported 32 PHY devices. * @param[in] Register offset is the index of one of the 32 phy register. * @param[out] u16 data read from the respective phy register (only valid iff return value is 0). * \return Returns 0 on success else return the error status. */ s32 synopGMAC_read_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 *data) { u64 addr; u32 loop_variable; addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiCsrClk3; //sw: add GmiiCsrClk addr = addr | GmiiBusy ; //Gmii busy bit synopGMACWriteReg(RegBase, GmacGmiiAddr, addr); //write the address from where the data to be read in GmiiGmiiAddr register of synopGMAC ip for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { //Wait till the busy bit gets cleared within a certain amount of time if (!(synopGMACReadReg(RegBase, GmacGmiiAddr) & GmiiBusy)) { break; } plat_delay(DEFAULT_DELAY_VARIABLE); } if (loop_variable < DEFAULT_LOOP_VARIABLE) { *data = (u16)(synopGMACReadReg(RegBase, GmacGmiiData) & 0xFFFF); } else { TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); return -ESYNOPGMACPHYERR; } //sw #if SYNOP_REG_DEBUG printf("read phy reg: offset = 0x%x\tdata = 0x%x\n", RegOffset, *data); #endif return -ESYNOPGMACNOERR; } /** * Function to write to the Phy register. The access to phy register * is a slow process as the data is moved accross MDI/MDO interface * @param[in] pointer to Register Base (It is the mac base in our case) . * @param[in] PhyBase register is the index of one of supported 32 PHY devices. * @param[in] Register offset is the index of one of the 32 phy register. * @param[in] data to be written to the respective phy register. * \return Returns 0 on success else return the error status. */ s32 synopGMAC_write_phy_reg(u64 RegBase, u32 PhyBase, u32 RegOffset, u16 data) { u32 addr; u32 loop_variable; synopGMACWriteReg(RegBase, GmacGmiiData, data); // write the data in to GmacGmiiData register of synopGMAC ip addr = ((PhyBase << GmiiDevShift) & GmiiDevMask) | ((RegOffset << GmiiRegShift) & GmiiRegMask) | GmiiWrite | GmiiCsrClk3; //sw: add GmiiCsrclk addr = addr | GmiiBusy ; //set Gmii clk to 20-35 Mhz and Gmii busy bit synopGMACWriteReg(RegBase, GmacGmiiAddr, addr); for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) { if (!(synopGMACReadReg(RegBase, GmacGmiiAddr) & GmiiBusy)) { break; } plat_delay(DEFAULT_DELAY_VARIABLE); } if (loop_variable < DEFAULT_LOOP_VARIABLE) { return -ESYNOPGMACNOERR; } else { TR("Error::: PHY not responding Busy bit didnot get cleared !!!!!!\n"); return -ESYNOPGMACPHYERR; } #if SYNOP_REG_DEBUG printf("write phy reg: offset = 0x%x\tdata = 0x%x", RegOffset, data); #endif } /** * Function to configure the phy in loopback mode. * * @param[in] pointer to synopGMACdevice. * @param[in] enable or disable the loopback. * \return 0 on success else return the error status. * \note Don't get confused with mac loop-back synopGMAC_loopback_on(synopGMACdevice *) * and synopGMAC_loopback_off(synopGMACdevice *) functions. */ #if UNUSED s32 synopGMAC_phy_loopback(synopGMACdevice *gmacdev, bool loopback) { s32 status = -ESYNOPGMACNOERR; u16 temp; status = synopGMAC_read_phy_reg(gmacdev -> MacBase, gmacdev -> PhyBase, PHY_CONTROL_REG, &temp); if (loopback) { temp |= 0x4000; } else { temp = temp; } status = synopGMAC_write_phy_reg(gmacdev -> MacBase, gmacdev -> PhyBase, PHY_CONTROL_REG, temp); return status; } #endif /** * Function to read the GMAC IP Version and populates the same in device data structure. * @param[in] pointer to synopGMACdevice. * \return Always return 0. */ s32 synopGMAC_read_version(synopGMACdevice *gmacdev) { u32 data = 0; data = synopGMACReadReg(gmacdev -> MacBase, GmacVersion); gmacdev -> Version = data; return 0; } /** * Function to reset the GMAC core. * This reests the DMA and GMAC core. After reset all the registers holds their respective reset value * @param[in] pointer to synopGMACdevice. * \return 0 on success else return the error status. */ s32 synopGMAC_reset(synopGMACdevice *gmacdev) { u32 data = 0; synopGMACWriteReg(gmacdev -> DmaBase, DmaBusMode, DmaResetOn); plat_delay(DEFAULT_LOOP_VARIABLE); data = synopGMACReadReg(gmacdev -> DmaBase, DmaBusMode); TR("DATA after Reset = %08x\n", data); return 0; } /** * Function to program DMA bus mode register. * * The Bus Mode register is programmed with the value given. The bits to be set are * bit wise or'ed and sent as the second argument to this function. * @param[in] pointer to synopGMACdevice. * @param[in] the data to be programmed. * \return 0 on success else return the error status. */ s32 synopGMAC_dma_bus_mode_init(synopGMACdevice *gmacdev, u32 init_value) { synopGMACWriteReg(gmacdev -> DmaBase, DmaBusMode, init_value); return 0; } /** * Function to program DMA Control register(Operation Mode Register 0x18). * * The Dma Control register is programmed with the value given. The bits to be set are * bit wise or'ed and sent as the second argument to this function. * @param[in] pointer to synopGMACdevice. * @param[in] the data to be programmed. * \return 0 on success else return the error status. */ s32 synopGMAC_dma_control_init(synopGMACdevice *gmacdev, u32 init_value) { synopGMACWriteReg(gmacdev -> DmaBase, DmaControl, init_value); return 0; } /*Gmac configuration functions*/ /** * Enable the watchdog timer on the receiver. * When enabled, Gmac enables Watchdog timer, and GMAC allows no more than * 2048 bytes of data (10,240 if Jumbo frame enabled). * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_wd_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacWatchdog); return; } /** * Disable the watchdog timer on the receiver. * When disabled, Gmac disabled watchdog timer, and can receive frames up to * 16,384 bytes. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_wd_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacWatchdog); return; } /** * Enables the Jabber frame support. * When enabled, GMAC disabled the jabber timer, and can transfer 16,384 byte frames. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_jab_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacJabber); return; } /** * Disables the Jabber frame support. * When disabled, GMAC enables jabber timer. It cuts of transmitter if application * sends more than 2048 bytes of data (10240 if Jumbo frame enabled). * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_jab_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacJabber); return; } #endif /** * Enables Frame bursting (Only in Half Duplex Mode). * When enabled, GMAC allows frame bursting in GMII Half Duplex mode. * Reserved in 10/100 and Full-Duplex configurations. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_frame_burst_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFrameBurst); return; } /** * Disables Frame bursting. * When Disabled, frame bursting is not supported. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_frame_burst_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacFrameBurst); return; } #endif /** * Enable Jumbo frame support. * When Enabled GMAC supports jumbo frames of 9018/9022(VLAN tagged). * Giant frame error is not reported in receive frame status. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_jumbo_frame_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacJumboFrame); return; } #endif /** * Disable Jumbo frame support. * When Disabled GMAC does not supports jumbo frames. * Giant frame error is reported in receive frame status. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_jumbo_frame_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacJumboFrame); return; } /** * Disable Carrier sense. * When Disabled GMAC ignores CRS signal during frame transmission * in half duplex mode. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_disable_crs(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDisableCrs); return; } #endif /** * Selects the GMII port. * When called GMII (1000Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_select_gmii(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacMiiGmii); return; } /** * Selects the MII port. * When called MII (10/100Mbps) port is selected (programmable only in 10/100/1000 Mbps configuration). * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_select_mii(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacMiiGmii); return; } /** * Enables Receive Own bit (Only in Half Duplex Mode). * When enaled GMAC receives all the packets given by phy while transmitting. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_rx_own_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRxOwn); return; } /** * Disables Receive Own bit (Only in Half Duplex Mode). * When enaled GMAC disables the reception of frames when gmii_txen_o is asserted. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_rx_own_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRxOwn); return; } #endif /** * Sets the GMAC in loopback mode. * When on GMAC operates in loop-back mode at GMII/MII. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note (G)MII Receive clock is required for loopback to work properly, as transmit clock is * not looped back internally. */ void synopGMAC_loopback_on(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacLoopback); return; } /** * Sets the GMAC in Normal mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_loopback_off(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacLoopback); return; } /** * Sets the GMAC core in Full-Duplex mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_set_full_duplex(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDuplex); return; } /** * Sets the GMAC core in Half-Duplex mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_set_half_duplex(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacDuplex); return; } /** * GMAC tries retransmission (Only in Half Duplex mode). * If collision occurs on the GMII/MII, GMAC attempt retries based on the * back off limit configured. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note This function is tightly coupled with synopGMAC_back_off_limit(synopGMACdev *, u32). */ void synopGMAC_retry_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRetry); return; } /** * GMAC tries only one transmission (Only in Half Duplex mode). * If collision occurs on the GMII/MII, GMAC will ignore the current frami * transmission and report a frame abort with excessive collision in tranmit frame status. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_retry_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRetry); return; } #endif /** * GMAC strips the Pad/FCS field of incoming frames. * This is true only if the length field value is less than or equal to * 1500 bytes. All received frames with length field greater than or equal to * 1501 bytes are passed to the application without stripping the Pad/FCS field. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_pad_crc_strip_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacPadCrcStrip); return; } #endif /** * GMAC doesnot strips the Pad/FCS field of incoming frames. * GMAC will pass all the incoming frames to Host unmodified. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_pad_crc_strip_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacPadCrcStrip); u32 status = synopGMACReadReg(gmacdev -> MacBase, GmacConfig); DEBUG_MES("strips status : %u\n", status & GmacPadCrcStrip); return; } /** * GMAC programmed with the back off limit value. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note This function is tightly coupled with synopGMAC_retry_enable(synopGMACdevice * gmacdev) */ void synopGMAC_back_off_limit(synopGMACdevice *gmacdev, u32 value) { u32 data; data = synopGMACReadReg(gmacdev -> MacBase, GmacConfig); data &= (~GmacBackoffLimit); data |= value; synopGMACWriteReg(gmacdev -> MacBase, GmacConfig, data); return; } /** * Enables the Deferral check in GMAC (Only in Half Duplex mode) * GMAC issues a Frame Abort Status, along with the excessive deferral error bit set in the * transmit frame status when transmit state machine is deferred for more than * - 24,288 bit times in 10/100Mbps mode * - 155,680 bit times in 1000Mbps mode or Jumbo frame mode in 10/100Mbps operation. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note Deferral begins when transmitter is ready to transmit, but is prevented because of * an active CRS (carrier sense) */ #if UNUSED void synopGMAC_deferral_check_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacDeferralCheck); return; } #endif /** * Disables the Deferral check in GMAC (Only in Half Duplex mode). * GMAC defers until the CRS signal goes inactive. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_deferral_check_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacDeferralCheck); return; } /** * Enable the reception of frames on GMII/MII. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_rx_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacRx); return; } /** * Disable the reception of frames on GMII/MII. * GMAC receive state machine is disabled after completion of reception of current frame. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_rx_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacRx); return; } #endif /** * Enable the transmission of frames on GMII/MII. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_tx_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacTx); return; } /** * Disable the transmission of frames on GMII/MII. * GMAC transmit state machine is disabled after completion of transmission of current frame. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_tx_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacConfig, GmacTx); return; } #endif /*Receive frame filter configuration functions*/ /** * Disables reception of all the frames to application. * GMAC passes only those received frames to application which * pass SA/DA address filtering. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_frame_filter_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacFilter); return; } /** * Enables reception of all the frames to application. * GMAC passes all the frames received to application irrespective of whether they * pass SA/DA address filtering or not. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_frame_filter_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacFilter); return; } /** * Populates the Hash High register with the data supplied. * This function is called when the Hash filtering is to be enabled. * @param[in] pointer to synopGMACdevice. * @param[in] data to be written to hash table high register. * \return void. */ #if UNUSED void synopGMAC_write_hash_table_high(synopGMACdevice *gmacdev, u32 data) { synopGMACWriteReg(gmacdev -> MacBase, GmacHashHigh, data); return; } #endif /** * Populates the Hash Low register with the data supplied. * This function is called when the Hash filtering is to be enabled. * @param[in] pointer to synopGMACdevice. * @param[in] data to be written to hash table low register. * \return void. */ #if UNUSED void synopGMAC_write_hash_table_low(synopGMACdevice *gmacdev, u32 data) { synopGMACWriteReg(gmacdev -> MacBase, GmacHashLow, data); return; } #endif /** * Enables Hash or Perfect filter (only if Hash filter is enabled in H/W). * Only frames matching either perfect filtering or Hash Filtering as per HMC and HUC * configuration are sent to application. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_hash_perfect_filter_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacHashPerfectFilter); return; } #endif /** * Enables only Hash(only if Hash filter is enabled in H/W). * Only frames matching Hash Filtering as per HMC and HUC * configuration are sent to application. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_Hash_filter_only_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacHashPerfectFilter); return; } #endif /** * Enables Source address filtering. * When enabled source address filtering is performed. Only frames matching SA filtering are passed to application with * SAMatch bit of RxStatus is set. GMAC drops failed frames. * @param[in] pointer to synopGMACdevice. * \return void. * \note This function is overriden by synopGMAC_frame_filter_disable(synopGMACdevice *) */ #if UNUSED void synopGMAC_src_addr_filter_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacSrcAddrFilter); return; } #endif /** * Disables Source address filtering. * When disabled GMAC forwards the received frames with updated SAMatch bit in RxStatus. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_src_addr_filter_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacSrcAddrFilter); return; } /** * Enables Inverse Destination address filtering. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_dst_addr_filter_inverse(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacDestAddrFilterInv); return; } #endif /** * Enables the normal Destination address filtering. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_dst_addr_filter_normal(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacDestAddrFilterInv); return; } /** * Enables forwarding of control frames. * When set forwards all the control frames (incl. unicast and multicast PAUSE frames). * @param[in] pointer to synopGMACdevice. * \return void. * \note Depends on RFE of FlowControlRegister[2] */ void synopGMAC_set_pass_control(synopGMACdevice *gmacdev, u32 passcontrol) { u32 data; data = synopGMACReadReg(gmacdev -> MacBase, GmacFrameFilter); data &= (~GmacPassControl); data |= passcontrol; synopGMACWriteReg(gmacdev -> MacBase, GmacFrameFilter, data); return; } /** * Enables Broadcast frames. * When enabled Address filtering module passes all incoming broadcast frames. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_broadcast_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacBroadcast); return; } /** * Disable Broadcast frames. * When disabled Address filtering module filters all incoming broadcast frames. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_broadcast_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacFrameFilter, GmacBroadcast); return; } #endif /** * Enables Multicast frames. * When enabled all multicast frames are passed. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_multicast_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacMulticastFilter); return; } #endif /** * Disable Multicast frames. * When disabled multicast frame filtering depends on HMC bit. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_multicast_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacMulticastFilter); return; } /** * Enables multicast hash filtering. * When enabled GMAC performs teh destination address filtering according to the hash table. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_multicast_hash_filter_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacMcastHashFilter); return; } #endif /** * Disables multicast hash filtering. * When disabled GMAC performs perfect destination address filtering for multicast frames, it compares * DA field with the value programmed in DA register. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_multicast_hash_filter_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacMcastHashFilter); return; } /** * Enables promiscous mode. * When enabled Address filter modules pass all incoming frames regardless of their Destination * and source addresses. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_promisc_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacPromiscuousMode); return; } #endif /** * Clears promiscous mode. * When called the GMAC falls back to normal operation from promiscous mode. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_promisc_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacPromiscuousMode); return; } /** * Enables unicast hash filtering. * When enabled GMAC performs the destination address filtering of unicast frames according to the hash table. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_unicast_hash_filter_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFrameFilter, GmacUcastHashFilter); return; } #endif /** * Disables multicast hash filtering. * When disabled GMAC performs perfect destination address filtering for unicast frames, it compares * DA field with the value programmed in DA register. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_unicast_hash_filter_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFrameFilter, GmacUcastHashFilter); return; } /*Flow control configuration functions*/ /** * Enables detection of pause frames with stations unicast address. * When enabled GMAC detects the pause frames with stations unicast address in addition to the * detection of pause frames with unique multicast address. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_unicast_pause_frame_detect_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacUnicastPauseFrame); return; } #endif /** * Disables detection of pause frames with stations unicast address. * When disabled GMAC only detects with the unique multicast address (802.3x). * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_unicast_pause_frame_detect_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacUnicastPauseFrame); return; } /** * Rx flow control enable. * When Enabled GMAC will decode the rx pause frame and disable the tx for a specified time. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_rx_flow_control_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacRxFlowControl); return; } /** * Rx flow control disable. * When disabled GMAC will not decode pause frame. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_rx_flow_control_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacRxFlowControl); return; } /** * Tx flow control enable. * When Enabled * - In full duplex GMAC enables flow control operation to transmit pause frames. * - In Half duplex GMAC enables the back pressure operation * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_tx_flow_control_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacTxFlowControl); return; } /** * Tx flow control disable. * When Disabled * - In full duplex GMAC will not transmit any pause frames. * - In Half duplex GMAC disables the back pressure feature. * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_tx_flow_control_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev -> MacBase, GmacFlowControl, GmacTxFlowControl); return; } /** * Initiate Flowcontrol operation. * When Set * - In full duplex GMAC initiates pause control frame. * - In Half duplex GMAC initiates back pressure function. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_tx_activate_flow_control(synopGMACdevice *gmacdev) { //In case of full duplex check for this bit to b'0. if it is read as b'1 indicates that //control frame transmission is in progress. if (gmacdev -> Speed == FULLDUPLEX) { if (!synopGMACCheckBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure)) { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure); } } else//if half duplex mode { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure); } return; } #endif /** * stops Flowcontrol operation. * @param[in] pointer to synopGMACdevice. * \return void. */ #if UNUSED void synopGMAC_tx_deactivate_flow_control(synopGMACdevice *gmacdev) { //In full duplex this bit is automatically cleared after transmitting a pause control frame. if (gmacdev->Speed == HALFDUPLEX) { synopGMACSetBits(gmacdev -> MacBase, GmacFlowControl, GmacFlowControlBackPressure); } return; } #endif /** * This enables the pause frame generation after programming the appropriate registers. * presently activation is set at 3k and deactivation set at 4k. These may have to tweaked * if found any issues * @param[in] pointer to synopGMACdevice. * \return void. */ void synopGMAC_pause_control(synopGMACdevice *gmacdev) { u32 omr_reg; u32 mac_flow_control_reg; omr_reg = synopGMACReadReg(gmacdev -> DmaBase, DmaControl); omr_reg |= DmaRxFlowCtrlAct4K | DmaRxFlowCtrlDeact5K | DmaEnHwFlowCtrl; synopGMACWriteReg(gmacdev -> DmaBase, DmaControl, omr_reg); mac_flow_control_reg = synopGMACReadReg(gmacdev -> MacBase, GmacFlowControl); mac_flow_control_reg |= GmacRxFlowControl | GmacTxFlowControl | 0xFFFF0000; synopGMACWriteReg(gmacdev -> MacBase, GmacFlowControl, mac_flow_control_reg); return; } /** * Example mac initialization sequence. * This function calls the initialization routines to initialize the GMAC register. * One can change the functions invoked here to have different configuration as per the requirement * @param[in] pointer to synopGMACdevice. * \return Returns 0 on success. */ s32 synopGMAC_mac_init(synopGMACdevice *gmacdev) { u32 PHYreg; if (gmacdev->DuplexMode == FULLDUPLEX) { TR("\n===phy FULLDUPLEX MODE\n"); //sw: debug synopGMAC_wd_enable(gmacdev); synopGMAC_jab_enable(gmacdev); synopGMAC_frame_burst_enable(gmacdev); synopGMAC_jumbo_frame_disable(gmacdev); synopGMAC_rx_own_enable(gmacdev); #if SYNOP_LOOPBACK_MODE synopGMAC_loopback_on(gmacdev); #else synopGMAC_loopback_off(gmacdev); #endif synopGMAC_set_full_duplex(gmacdev); //1 synopGMAC_retry_enable(gmacdev); synopGMAC_pad_crc_strip_disable(gmacdev); synopGMAC_back_off_limit(gmacdev, GmacBackoffLimit0); synopGMAC_deferral_check_disable(gmacdev); synopGMAC_tx_enable(gmacdev); //according to Tang Dan's commitment synopGMAC_rx_enable(gmacdev); synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaStoreAndForward); //3 synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaFwdErrorFrames); if (gmacdev -> Speed == SPEED1000) { synopGMAC_select_gmii(gmacdev); } else { synopGMAC_select_mii(gmacdev); if (gmacdev -> Speed == SPEED100) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed100); } else { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed10); } } /*Frame Filter Configuration*/ //synopGMAC_frame_filter_enable(gmacdev); //2 synopGMAC_frame_filter_disable(gmacdev); //2 synopGMAC_set_pass_control(gmacdev, GmacPassControl0); synopGMAC_broadcast_enable(gmacdev); synopGMAC_src_addr_filter_disable(gmacdev); synopGMAC_multicast_disable(gmacdev); synopGMAC_dst_addr_filter_normal(gmacdev); //scl //synopGMAC_dst_addr_filter_inverse(gmacdev); synopGMAC_multicast_hash_filter_disable(gmacdev); synopGMAC_promisc_disable(gmacdev); synopGMAC_unicast_hash_filter_disable(gmacdev); /*Flow Control Configuration*/ synopGMAC_unicast_pause_frame_detect_disable(gmacdev); synopGMAC_rx_flow_control_enable(gmacdev); synopGMAC_tx_flow_control_enable(gmacdev); } else//for Half Duplex configuration { TR("\n===phy HALFDUPLEX MODE\n"); //sw: debug synopGMAC_wd_enable(gmacdev); synopGMAC_jab_enable(gmacdev); synopGMAC_frame_burst_enable(gmacdev); synopGMAC_jumbo_frame_disable(gmacdev); synopGMAC_rx_own_enable(gmacdev); #if SYNOP_LOOPBACK_MODE synopGMAC_loopback_on(gmacdev); #else synopGMAC_loopback_off(gmacdev); #endif synopGMAC_set_half_duplex(gmacdev); synopGMAC_retry_enable(gmacdev); synopGMAC_pad_crc_strip_disable(gmacdev); synopGMAC_back_off_limit(gmacdev, GmacBackoffLimit0); synopGMAC_deferral_check_disable(gmacdev); //sw: set efe & tsf synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaStoreAndForward); synopGMACSetBits(gmacdev -> DmaBase, DmaControl, DmaFwdErrorFrames); //sw: put it in the end synopGMAC_tx_enable(gmacdev); synopGMAC_rx_enable(gmacdev); if (gmacdev -> Speed == SPEED1000) synopGMAC_select_gmii(gmacdev); else { synopGMAC_select_mii(gmacdev); if (gmacdev -> Speed == SPEED100) { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed100); } else { synopGMACSetBits(gmacdev -> MacBase, GmacConfig, GmacFESpeed10); } } // synopGMACSetBits(gmacdev->MacBase, GmacConfig, GmacDisableCrs); // synopGMAC_select_gmii(gmacdev); /*Frame Filter Configuration*/ synopGMAC_frame_filter_enable(gmacdev); // synopGMAC_frame_filter_disable(gmacdev); synopGMAC_set_pass_control(gmacdev, GmacPassControl0); synopGMAC_broadcast_enable(gmacdev); synopGMAC_src_addr_filter_disable(gmacdev); synopGMAC_multicast_disable(gmacdev); synopGMAC_dst_addr_filter_normal(gmacdev); synopGMAC_multicast_hash_filter_disable(gmacdev); synopGMAC_promisc_disable(gmacdev); // synopGMAC_promisc_enable(gmacdev); synopGMAC_unicast_hash_filter_disable(gmacdev); //sw: loopback mode // synopGMAC_loopback_on(gmacdev); /*Flow Control Configuration*/ synopGMAC_unicast_pause_frame_detect_disable(gmacdev); synopGMAC_rx_flow_control_disable(gmacdev); synopGMAC_tx_flow_control_disable(gmacdev); /*To set PHY register to enable CRS on Transmit*/ } return 0; } /** * Sets the Mac address in to GMAC register. * This function sets the MAC address to the MAC register in question. * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. * @param[in] Register offset for Mac address high * @param[in] Register offset for Mac address low * @param[in] buffer containing mac address to be programmed. * \return 0 upon success. Error code upon failure. */ s32 synopGMAC_set_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr) { u32 data; data = (MacAddr[5] << 8) | MacAddr[4]; synopGMACWriteReg(gmacdev -> MacBase, MacHigh, data); data = (MacAddr[3] << 24) | (MacAddr[2] << 16) | (MacAddr[1] << 8) | MacAddr[0]; synopGMACWriteReg(gmacdev -> MacBase, MacLow, data); return 0; } /** * Get the Mac address in to the address specified. * The mac register contents are read and written to buffer passed. * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. * @param[in] Register offset for Mac address high * @param[in] Register offset for Mac address low * @param[out] buffer containing the device mac address. * \return 0 upon success. Error code upon failure. */ s32 synopGMAC_get_mac_addr(synopGMACdevice *gmacdev, u32 MacHigh, u32 MacLow, u8 *MacAddr) { u32 data; data = synopGMACReadReg(gmacdev -> MacBase, MacHigh); MacAddr[5] = (data >> 8) & 0xff; MacAddr[4] = (data) & 0xff; data = synopGMACReadReg(gmacdev -> MacBase, MacLow); MacAddr[3] = (data >> 24) & 0xff; MacAddr[2] = (data >> 16) & 0xff; MacAddr[1] = (data >> 8) & 0xff; MacAddr[0] = (data) & 0xff; // rt_kprintf("MacAddr = 0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]); return 0; } /** * Attaches the synopGMAC device structure to the hardware. * Device structure is populated with MAC/DMA and PHY base addresses. * @param[in] pointer to synopGMACdevice to populate mac dma and phy addresses. * @param[in] GMAC IP mac base address. * @param[in] GMAC IP dma base address. * @param[in] GMAC IP phy base address. * \return 0 upon success. Error code upon failure. * \note This is important function. No kernel api provided by Synopsys */ s32 synopGMAC_attach(synopGMACdevice *gmacdev, u64 macBase, u64 dmaBase, u64 phyBase, u8 *mac_addr) { /*Make sure the Device data strucure is cleared before we proceed further*/ rt_memset((void *)gmacdev, 0, sizeof(synopGMACdevice)); /*Populate the mac and dma base addresses*/ gmacdev -> MacBase = macBase; gmacdev -> DmaBase = dmaBase; gmacdev -> PhyBase = phyBase; // rt_kprintf("gmacdev->DmaBase = 0x%x\n", gmacdev->DmaBase); // rt_kprintf("dmaBase = 0x%x\n", dmaBase); { int i, j; u16 data; for (i = phyBase, j = 0; j < 32; i = (i + 1) & 0x1f, j++) { synopGMAC_read_phy_reg(gmacdev -> MacBase, i, 2, &data); if (data != 0 && data != 0xffff) { break; } synopGMAC_read_phy_reg(gmacdev -> MacBase, i, 3, &data); if (data != 0 && data != 0xffff) { break; } } if (j == 32) { rt_kprintf("phy_detect: can't find PHY!\n"); } gmacdev -> PhyBase = i; } // synopGMAC_get_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr); /* Program/flash in the station/IP's Mac address */ synopGMAC_set_mac_addr(gmacdev, GmacAddr0High, GmacAddr0Low, mac_addr); return 0; } /** * Initialize the rx descriptors for ring or chain mode operation. * - Status field is initialized to 0. * - EndOfRing set for the last descriptor. * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) * - data1 and data2 set to 0. (note) * @param[in] pointer to DmaDesc structure. * @param[in] whether end of ring * \return void. * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. */ void synopGMAC_rx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) { desc -> length = last_ring_desc ? RxDescEndOfRing : 0; desc -> status = 0; desc -> buffer1 = 0; desc -> buffer2 = 0; desc -> data1 = 0; desc -> data2 = 0; //desc -> dummy1 = 0; //desc -> dummy2 = 0; return; } void synopGMAC_rx_desc_recycle(DmaDesc *desc, bool last_ring_desc) { desc -> status = DescOwnByDma; desc -> length = last_ring_desc ? RxDescEndOfRing : 0; //desc->buffer1 = 0; //desc->buffer2 = 0; //desc->data1 = 0; //desc->data2 = 0; //desc -> dummy1 = 0; //desc -> dummy2 = 0; return; } /** * Initialize the tx descriptors for ring or chain mode operation. * - Status field is initialized to 0. * - EndOfRing set for the last descriptor. * - buffer1 and buffer2 set to 0 for ring mode of operation. (note) * - data1 and data2 set to 0. (note) * @param[in] pointer to DmaDesc structure. * @param[in] whether end of ring * \return void. * \note Initialization of the buffer1, buffer2, data1,data2 and status are not done here. This only initializes whether one wants to use this descriptor * in chain mode or ring mode. For chain mode of operation the buffer2 and data2 are programmed before calling this function. */ void synopGMAC_tx_desc_init_ring(DmaDesc *desc, bool last_ring_desc) { #ifdef ENH_DESC desc -> status = last_ring_desc ? TxDescEndOfRing : 0; desc -> length = 0; #else desc -> length = last_ring_desc ? TxDescEndOfRing : 0; desc -> status = 0; #endif //sw desc -> buffer1 = 0; desc -> buffer2 = 0; desc -> data1 = 0; desc -> data2 = 0; //desc -> dummy1 = 0; //desc -> dummy2 = 0; return; } /** * Initialize the rx descriptors for chain mode of operation. * - Status field is initialized to 0. * - EndOfRing set for the last descriptor. * - buffer1 and buffer2 set to 0. * - data1 and data2 set to 0. * @param[in] pointer to DmaDesc structure. * @param[in] whether end of ring * \return void. */ void synopGMAC_rx_desc_init_chain(DmaDesc *desc) { desc -> status = 0; desc -> length = RxDescChain; desc -> buffer1 = 0; desc -> data1 = 0; return; } /** * Initialize the rx descriptors for chain mode of operation. * - Status field is initialized to 0. * - EndOfRing set for the last descriptor. * - buffer1 and buffer2 set to 0. * - data1 and data2 set to 0. * @param[in] pointer to DmaDesc structure. * @param[in] whether end of ring * \return void. */ void synopGMAC_tx_desc_init_chain(DmaDesc *desc) { #ifdef ENH_DESC desc -> status = TxDescChain; desc -> length = 0; #else desc -> length = TxDescChain; #endif desc -> buffer1 = 0; desc -> data1 = 0; return; } s32 synopGMAC_init_tx_rx_desc_queue(synopGMACdevice *gmacdev) { s32 i; for (i = 0; i < gmacdev -> TxDescCount; i++) { synopGMAC_tx_desc_init_ring(gmacdev -> TxDesc + i, i == gmacdev -> TxDescCount - 1); } TR("At line %d\n", __LINE__); for (i = 0; i < gmacdev -> RxDescCount; i++) { synopGMAC_rx_desc_init_ring(gmacdev -> RxDesc + i, i == gmacdev -> RxDescCount - 1); } gmacdev -> TxNext = 0; gmacdev -> TxBusy = 0; gmacdev -> RxNext = 0; gmacdev -> RxBusy = 0; return -ESYNOPGMACNOERR; } /** * Programs the DmaRxBaseAddress with the Rx descriptor base address. * Rx Descriptor's base address is available in the gmacdev structure. This function progrms the * Dma Rx Base address with the starting address of the descriptor ring or chain. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_init_rx_desc_base(synopGMACdevice *gmacdev) { DEBUG_MES("gmacdev->RxDescDma = %08x\n", gmacdev -> RxDescDma); synopGMACWriteReg(gmacdev -> DmaBase, DmaRxBaseAddr, (u32)gmacdev -> RxDescDma); return; } /** * Programs the DmaTxBaseAddress with the Tx descriptor base address. * Tx Descriptor's base address is available in the gmacdev structure. This function progrms the * Dma Tx Base address with the starting address of the descriptor ring or chain. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_init_tx_desc_base(synopGMACdevice *gmacdev) { synopGMACWriteReg(gmacdev -> DmaBase, DmaTxBaseAddr, (u32)gmacdev -> TxDescDma); return; } /** * Makes the Dma as owner for this descriptor. * This function sets the own bit of status field of the DMA descriptor, * indicating the DMA is the owner for this descriptor. * @param[in] pointer to DmaDesc structure. * \return returns void. */ void synopGMAC_set_owner_dma(DmaDesc *desc) { desc -> status |= DescOwnByDma; } /** * set tx descriptor to indicate SOF. * This Descriptor contains the start of ethernet frame. * @param[in] pointer to DmaDesc structure. * \return returns void. */ void synopGMAC_set_desc_sof(DmaDesc *desc) { #ifdef ENH_DESC desc -> status |= DescTxFirst;//ENH_DESC #else desc -> length |= DescTxFirst; #endif } /** * set tx descriptor to indicate EOF. * This descriptor contains the End of ethernet frame. * @param[in] pointer to DmaDesc structure. * \return returns void. */ void synopGMAC_set_desc_eof(DmaDesc *desc) { #ifdef ENH_DESC desc -> status |= DescTxLast;//ENH_DESC #else desc -> length |= DescTxLast; #endif } /** * checks whether this descriptor contains start of frame. * This function is to check whether the descriptor's data buffer * contains a fresh ethernet frame? * @param[in] pointer to DmaDesc structure. * \return returns true if SOF in current descriptor, else returns fail. */ bool synopGMAC_is_sof_in_rx_desc(DmaDesc *desc) { return ((desc -> status & DescRxFirst) == DescRxFirst); } /** * checks whether this descriptor contains end of frame. * This function is to check whether the descriptor's data buffer * contains end of ethernet frame? * @param[in] pointer to DmaDesc structure. * \return returns true if SOF in current descriptor, else returns fail. */ bool synopGMAC_is_eof_in_rx_desc(DmaDesc *desc) { return ((desc -> status & DescRxLast) == DescRxLast); } /** * checks whether destination address filter failed in the rx frame. * @param[in] pointer to DmaDesc structure. * \return returns true if Failed, false if not. */ bool synopGMAC_is_da_filter_failed(DmaDesc *desc) { return ((desc -> status & DescDAFilterFail) == DescDAFilterFail); } /** * checks whether source address filter failed in the rx frame. * @param[in] pointer to DmaDesc structure. * \return returns true if Failed, false if not. */ bool synopGMAC_is_sa_filter_failed(DmaDesc *desc) { return ((desc -> status & DescSAFilterFail) == DescSAFilterFail); } /** * Checks whether the descriptor is owned by DMA. * If descriptor is owned by DMA then the OWN bit is set to 1. This API is same for both ring and chain mode. * @param[in] pointer to DmaDesc structure. * \return returns true if Dma owns descriptor and false if not. */ bool synopGMAC_is_desc_owned_by_dma(DmaDesc *desc) { return ((desc -> status & DescOwnByDma) == DescOwnByDma); } /** * returns the byte length of received frame including CRC. * This returns the no of bytes received in the received ethernet frame including CRC(FCS). * @param[in] pointer to DmaDesc structure. * \return returns the length of received frame lengths in bytes. */ u32 synopGMAC_get_rx_desc_frame_length(u32 status) { return ((status & DescFrameLengthMask) >> DescFrameLengthShift); } /** * Checks whether the descriptor is valid * if no errors such as CRC/Receive Error/Watchdog Timeout/Late collision/Giant Frame/Overflow/Descriptor * error the descritpor is said to be a valid descriptor. * @param[in] pointer to DmaDesc structure. * \return True if desc valid. false if error. */ bool synopGMAC_is_desc_valid(u32 status) { return ((status & DescError) == 0); } /** * Checks whether the descriptor is empty. * If the buffer1 and buffer2 lengths are zero in ring mode descriptor is empty. * In chain mode buffer2 length is 0 but buffer2 itself contains the next descriptor address. * @param[in] pointer to DmaDesc structure. * \return returns true if descriptor is empty, false if not empty. */ bool synopGMAC_is_desc_empty(DmaDesc *desc) { //if both the buffer1 length and buffer2 length are zero desc is empty return (((desc -> length & DescSize1Mask) == 0) && ((desc -> length & DescSize2Mask) == 0)); } /** * Checks whether the rx descriptor is valid. * if rx descripor is not in error and complete frame is available in the same descriptor * @param[in] pointer to DmaDesc structure. * \return returns true if no error and first and last desc bits are set, otherwise it returns false. */ bool synopGMAC_is_rx_desc_valid(u32 status) { return ((status & DescError) == 0) && ((status & DescRxFirst) == DescRxFirst) && ((status & DescRxLast) == DescRxLast); } /** * Checks whether the tx is aborted due to collisions. * @param[in] pointer to DmaDesc structure. * \return returns true if collisions, else returns false. */ bool synopGMAC_is_tx_aborted(u32 status) { return (((status & DescTxLateCollision) == DescTxLateCollision) | ((status & DescTxExcCollisions) == DescTxExcCollisions)); } /** * Checks whether the tx carrier error. * @param[in] pointer to DmaDesc structure. * \return returns true if carrier error occured, else returns falser. */ bool synopGMAC_is_tx_carrier_error(u32 status) { return (((status & DescTxLostCarrier) == DescTxLostCarrier) | ((status & DescTxNoCarrier) == DescTxNoCarrier)); } /** * Gives the transmission collision count. * returns the transmission collision count indicating number of collisions occured before the frame was transmitted. * Make sure to check excessive collision didnot happen to ensure the count is valid. * @param[in] pointer to DmaDesc structure. * \return returns the count value of collision. */ u32 synopGMAC_get_tx_collision_count(u32 status) { return ((status & DescTxCollMask) >> DescTxCollShift); } u32 synopGMAC_is_exc_tx_collisions(u32 status) { return ((status & DescTxExcCollisions) == DescTxExcCollisions); } /** * Check for damaged frame due to overflow or collision. * Retruns true if rx frame was damaged due to buffer overflow in MTL or late collision in half duplex mode. * @param[in] pointer to DmaDesc structure. * \return returns true if error else returns false. */ bool synopGMAC_is_rx_frame_damaged(u32 status) { //bool synopGMAC_dma_rx_collisions(u32 status) return (((status & DescRxDamaged) == DescRxDamaged) | ((status & DescRxCollision) == DescRxCollision)); } /** * Check for damaged frame due to collision. * Retruns true if rx frame was damaged due to late collision in half duplex mode. * @param[in] pointer to DmaDesc structure. * \return returns true if error else returns false. */ bool synopGMAC_is_rx_frame_collision(u32 status) { //bool synopGMAC_dma_rx_collisions(u32 status) return ((status & DescRxCollision) == DescRxCollision); } /** * Check for receive CRC error. * Retruns true if rx frame CRC error occured. * @param[in] pointer to DmaDesc structure. * \return returns true if error else returns false. */ bool synopGMAC_is_rx_crc(u32 status) { //u32 synopGMAC_dma_rx_crc(u32 status) return ((status & DescRxCrc) == DescRxCrc); } /** * Indicates rx frame has non integer multiple of bytes. (odd nibbles). * Retruns true if dribbling error in rx frame. * @param[in] pointer to DmaDesc structure. * \return returns true if error else returns false. */ bool synopGMAC_is_frame_dribbling_errors(u32 status) { //u32 synopGMAC_dma_rx_frame_errors(u32 status) return ((status & DescRxDribbling) == DescRxDribbling); } /** * Indicates error in rx frame length. * Retruns true if received frame length doesnot match with the length field * @param[in] pointer to DmaDesc structure. * \return returns true if error else returns false. */ bool synopGMAC_is_rx_frame_length_errors(u32 status) { //u32 synopGMAC_dma_rx_length_errors(u32 status) return ((status & DescRxLengthError) == DescRxLengthError); } /** * Checks whether this rx descriptor is last rx descriptor. * This returns true if it is last descriptor either in ring mode or in chain mode. * @param[in] pointer to devic structure. * @param[in] pointer to DmaDesc structure. * \return returns true if it is last descriptor, false if not. * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). */ bool synopGMAC_is_last_rx_desc(synopGMACdevice *gmacdev, DmaDesc *desc) { //bool synopGMAC_is_last_desc(DmaDesc *desc) return (((desc -> length & RxDescEndOfRing) == RxDescEndOfRing) || ((u64)gmacdev -> RxDesc == desc -> data2)); } /** * Checks whether this tx descriptor is last tx descriptor. * This returns true if it is last descriptor either in ring mode or in chain mode. * @param[in] pointer to devic structure. * @param[in] pointer to DmaDesc structure. * \return returns true if it is last descriptor, false if not. * \note This function should not be called before initializing the descriptor using synopGMAC_desc_init(). */ bool synopGMAC_is_last_tx_desc(synopGMACdevice *gmacdev, DmaDesc *desc) { //bool synopGMAC_is_last_desc(DmaDesc *desc) #ifdef ENH_DESC return (((desc->status & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2)); #else return (((desc->length & TxDescEndOfRing) == TxDescEndOfRing) || ((u64)gmacdev -> TxDesc == desc -> data2)); #endif } /** * Checks whether this rx descriptor is in chain mode. * This returns true if it is this descriptor is in chain mode. * @param[in] pointer to DmaDesc structure. * \return returns true if chain mode is set, false if not. */ bool synopGMAC_is_rx_desc_chained(DmaDesc *desc) { return ((desc -> length & RxDescChain) == RxDescChain); } /** * Checks whether this tx descriptor is in chain mode. * This returns true if it is this descriptor is in chain mode. * @param[in] pointer to DmaDesc structure. * \return returns true if chain mode is set, false if not. */ bool synopGMAC_is_tx_desc_chained(DmaDesc *desc) { #ifdef ENH_DESC return ((desc -> status & TxDescChain) == TxDescChain); #else return ((desc -> length & TxDescChain) == TxDescChain); #endif } /** * Driver Api to get the descriptor field information. * This returns the status, dma-able address of buffer1, the length of buffer1, virtual address of buffer1 * dma-able address of buffer2, length of buffer2, virtural adddress of buffer2. * @param[in] pointer to DmaDesc structure. * @param[out] pointer to status field fo descriptor. * @param[out] dma-able address of buffer1. * @param[out] length of buffer1. * @param[out] virtual address of buffer1. * @param[out] dma-able address of buffer2. * @param[out] length of buffer2. * @param[out] virtual address of buffer2. * \return returns void. */ void synopGMAC_get_desc_data(DmaDesc *desc, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2) { if (Status != 0) { *Status = desc -> status; } if (Buffer1 != 0) { *Buffer1 = desc -> buffer1; } if (Length1 != 0) { *Length1 = (desc -> length & DescSize1Mask) >> DescSize1Shift; } if (Data1 != 0) { *Data1 = desc -> data1; } if (Buffer2 != 0) { *Buffer2 = desc -> buffer2; } if (Length2 != 0) { *Length2 = (desc -> length & DescSize2Mask) >> DescSize2Shift; } if (Data2 != 0) { *Data2 = desc -> data2; } return; } #ifdef ENH_DESC_8W /** * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor * Get the index and address of Tx desc. * This api is same for both ring mode and chain mode. * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is * over. This returns the descriptor fields to the caller. * @param[in] pointer to synopGMACdevice. * @param[out] status field of the descriptor. * @param[out] Dma-able buffer1 pointer. * @param[out] length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. * \return returns present tx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_tx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2, u32 *Ext_Status, u32 *Time_Stamp_High, u32 *Time_Stamp_Low) { u32 txover = gmacdev->TxBusy; DmaDesc *txdesc = gmacdev->TxBusyDesc; if (synopGMAC_is_desc_owned_by_dma(txdesc)) return -1; if (synopGMAC_is_desc_empty(txdesc)) return -1; (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now if (Status != 0) *Status = txdesc->status; if (Ext_Status != 0) *Ext_Status = txdesc->extstatus; if (Time_Stamp_High != 0) *Time_Stamp_High = txdesc->timestamphigh; if (Time_Stamp_Low != 0) *Time_Stamp_High = txdesc->timestamplow; if (Buffer1 != 0) *Buffer1 = txdesc->buffer1; if (Length1 != 0) *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; if (Data1 != 0) *Data1 = txdesc->data1; if (Buffer2 != 0) *Buffer2 = txdesc->buffer2; if (Length2 != 0) *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift; if (Data1 != 0) *Data2 = txdesc->data2; gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txover + 1; if (synopGMAC_is_tx_desc_chained(txdesc)) { gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2; synopGMAC_tx_desc_init_chain(txdesc); } else { gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1); synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev, txdesc)); } TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", txover, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2); return txover; } #else /** * Get the index and address of Tx desc. * This api is same for both ring mode and chain mode. * This function tracks the tx descriptor the DMA just closed after the transmission of data from this descriptor is * over. This returns the descriptor fields to the caller. * @param[in] pointer to synopGMACdevice. * @param[out] status field of the descriptor. * @param[out] Dma-able buffer1 pointer. * @param[out] length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * @param[out] u32 data indicating whether the descriptor is in ring mode or chain mode. * \return returns present tx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_tx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2) { u32 txover = gmacdev->TxBusy; DmaDesc *txdesc = gmacdev->TxBusyDesc; int i; //sw: dbg //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_R); //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); #if SYNOP_TX_DEBUG printf("Cache sync before get a used tx dma desc!\n"); printf("\n==%02d %08x %08x %08x %08x %08x %08x %08x\n", txover, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2); #endif if (synopGMAC_is_desc_owned_by_dma(txdesc)) { return -1; } // gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? 0 : txover + 1; // gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev,txdesc) ? gmacdev->TxDesc : (txdesc + 1); if (synopGMAC_is_desc_empty(txdesc)) { return -1; } (gmacdev->BusyTxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now if (Status != 0) *Status = txdesc->status; if (Buffer1 != 0) *Buffer1 = txdesc->buffer1; if (Length1 != 0) *Length1 = (txdesc->length & DescSize1Mask) >> DescSize1Shift; if (Data1 != 0) *Data1 = txdesc->data1; if (Buffer2 != 0) *Buffer2 = txdesc->buffer2; if (Length2 != 0) *Length2 = (txdesc->length & DescSize2Mask) >> DescSize2Shift; if (Data1 != 0) *Data2 = txdesc->data2; gmacdev->TxBusy = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txover + 1; if (synopGMAC_is_tx_desc_chained(txdesc)) { gmacdev->TxBusyDesc = (DmaDesc *)txdesc->data2; synopGMAC_tx_desc_init_chain(txdesc); } else { gmacdev->TxBusyDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1); synopGMAC_tx_desc_init_ring(txdesc, synopGMAC_is_last_tx_desc(gmacdev, txdesc)); } //printf("%02d %08x %08x %08x %08x %08x %08x %08x\n",txover,(u32)txdesc,txdesc->status,txdesc->length,txdesc->buffer1,txdesc->buffer2,txdesc->data1,txdesc->data2); //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); #if SYNOP_TX_DEBUG printf("Cache sync after re-init a tx dma desc!\n"); #endif return txover; } #endif /** * Populate the tx desc structure with the buffer address. * Once the driver has a packet ready to be transmitted, this function is called with the * valid dma-able buffer addresses and their lengths. This function populates the descriptor * and make the DMA the owner for the descriptor. This function also controls whether Checksum * offloading to be done in hardware or not. * This api is same for both ring mode and chain mode. * @param[in] pointer to synopGMACdevice. * @param[in] Dma-able buffer1 pointer. * @param[in] length of buffer1 (Max is 2048). * @param[in] virtual pointer for buffer1. * @param[in] Dma-able buffer2 pointer. * @param[in] length of buffer2 (Max is 2048). * @param[in] virtual pointer for buffer2. * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. * @param[in] u32 indicating whether the checksum offloading in HW/SW. * \return returns present tx descriptor index on success. Negative value if error. */ u32 len; s32 synopGMAC_set_tx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2, u32 offload_needed, u32 *index, DmaDesc *Dpr) { u32 txnext = gmacdev->TxNext; DmaDesc *txdesc = gmacdev->TxNextDesc; *index = txnext; Dpr = txdesc; if (!synopGMAC_is_desc_empty(txdesc)) { TR("set tx qptr: desc empty!\n"); return -1; } (gmacdev->BusyTxDesc)++; //busy tx descriptor is reduced by one as it will be handed over to Processor now if (synopGMAC_is_tx_desc_chained(txdesc)) { txdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask); #ifdef ENH_DESC txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC #else txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor #endif txdesc->buffer1 = Buffer1; txdesc->data1 = Data1; if (offload_needed) { /* Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, before calling any of the functions given below. */ synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); // synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); } #ifdef ENH_DESC txdesc->status |= DescOwnByDma;//ENH_DESC #else txdesc->status = DescOwnByDma; #endif gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txnext + 1; gmacdev->TxNextDesc = (DmaDesc *)txdesc->data2; } else { // printf("synopGMAC_set_tx_qptr:in ring mode\n"); txdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask)); #ifdef ENH_DESC txdesc->status |= (DescTxFirst | DescTxLast | DescTxIntEnable); //ENH_DESC #else txdesc->length |= (DescTxFirst | DescTxLast | DescTxIntEnable); //Its always assumed that complete data will fit in to one descriptor #endif txdesc->buffer1 = Buffer1; txdesc->data1 = Data1; txdesc->buffer2 = Buffer2; txdesc->data2 = Data2; if (offload_needed) { /* Make sure that the OS you are running supports the IP and TCP checkusm offloaidng, before calling any of the functions given below. */ //sw: i am not sure about the checksum.so i omit it in the outside synopGMAC_tx_checksum_offload_ipv4hdr(gmacdev, txdesc); synopGMAC_tx_checksum_offload_tcponly(gmacdev, txdesc); // synopGMAC_tx_checksum_offload_tcp_pseudo(gmacdev, txdesc); } #ifdef ENH_DESC txdesc->status |= DescOwnByDma;//ENH_DESC #else // printf("synopGMAC_set_tx_qptr:give the tx descroptor to dma\n"); txdesc->status = DescOwnByDma; #endif gmacdev->TxNext = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? 0 : txnext + 1; gmacdev->TxNextDesc = synopGMAC_is_last_tx_desc(gmacdev, txdesc) ? gmacdev->TxDesc : (txdesc + 1); } #if SYNOP_TX_DEBUG printf("%02d %08x %08x %08x %08x %08x %08x %08x\n", txnext, (u32)txdesc, txdesc->status, txdesc->length, txdesc->buffer1, txdesc->buffer2, txdesc->data1, txdesc->data2); #endif //pci_sync_cache(0, (vm_offset_t)txdesc, 64, SYNC_W); #if SYNOP_TX_DEBUG printf("Cache sync to set a tx desc!\n"); #endif //pci_sync_cache(0, (vm_offset_t)(txdesc->data1), 32, SYNC_W); #if SYNOP_TX_DEBUG //printf("Cache sync for data in the buf of the tx desc!\n"); #endif return txnext; } #ifdef ENH_DESC_8W /** * Prepares the descriptor to receive packets. * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields * and handed over to DMA by setting the ownership. After successful return from this function the * descriptor is added to the receive descriptor pool/queue. * This api is same for both ring mode and chain mode. * @param[in] pointer to synopGMACdevice. * @param[in] Dma-able buffer1 pointer. * @param[in] length of buffer1 (Max is 2048). * @param[in] Dma-able buffer2 pointer. * @param[in] length of buffer2 (Max is 2048). * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. * \return returns present rx descriptor index on success. Negative value if error. */ // dma_addr RX_BUF_SIZE skb s32 synopGMAC_set_rx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) { u32 rxnext = gmacdev->RxNext; DmaDesc *rxdesc = gmacdev->RxNextDesc; if (!synopGMAC_is_desc_empty(rxdesc)) return -1; if (synopGMAC_is_rx_desc_chained(rxdesc)) { rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; rxdesc->extstatus = 0; rxdesc->reserved1 = 0; rxdesc->timestamplow = 0; rxdesc->timestamphigh = 0; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; } else { rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask)); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; rxdesc->extstatus = 0; rxdesc->reserved1 = 0; rxdesc->timestamplow = 0; rxdesc->timestamphigh = 0; rxdesc->buffer2 = Buffer2; rxdesc->data2 = Data2; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); } #if SYNOP_RX_DEBUG TR("%02d %08x %08x %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2, rxdesc->dummy1, rxdesc->dummy2); #endif (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one //pci_sync_cache(0, (vm_offset_t)rxdesc,64, SYNC_W); return rxnext; } #else /** * Prepares the descriptor to receive packets. * The descriptor is allocated with the valid buffer addresses (sk_buff address) and the length fields * and handed over to DMA by setting the ownership. After successful return from this function the * descriptor is added to the receive descriptor pool/queue. * This api is same for both ring mode and chain mode. * @param[in] pointer to synopGMACdevice. * @param[in] Dma-able buffer1 pointer. * @param[in] length of buffer1 (Max is 2048). * @param[in] Dma-able buffer2 pointer. * @param[in] length of buffer2 (Max is 2048). * @param[in] u32 data indicating whether the descriptor is in ring mode or chain mode. * \return returns present rx descriptor index on success. Negative value if error. */ s32 synopGMAC_set_rx_qptr(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) { u32 rxnext = gmacdev->RxNext; DmaDesc *rxdesc = gmacdev->RxNextDesc; if (!synopGMAC_is_desc_empty(rxdesc)) return -1; if (synopGMAC_is_rx_desc_chained(rxdesc)) { rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; } else { rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask)); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; rxdesc->buffer2 = Buffer2; rxdesc->data2 = Data2; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); } #if SYNOP_RX_DEBUG TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2); #endif (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one return rxnext; } s32 synopGMAC_set_rx_qptr_init(synopGMACdevice *gmacdev, u32 Buffer1, u32 Length1, u64 Data1, u32 Buffer2, u32 Length2, u64 Data2) { u32 rxnext = gmacdev->RxNext; DmaDesc *rxdesc = gmacdev->RxNextDesc; /* sw if(synopGMAC_is_desc_owned_by_dma(rxdesc)) return -1; */ if (!synopGMAC_is_desc_empty(rxdesc)) return -1; if (synopGMAC_is_rx_desc_chained(rxdesc)) { rxdesc->length |= ((Length1 << DescSize1Shift) & DescSize1Mask); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; rxdesc->status = 0; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = (DmaDesc *)rxdesc->data2; } else { rxdesc->length |= (((Length1 << DescSize1Shift) & DescSize1Mask) | ((Length2 << DescSize2Shift) & DescSize2Mask)); rxdesc->buffer1 = Buffer1; rxdesc->data1 = Data1; rxdesc->buffer2 = Buffer2; rxdesc->data2 = Data2; if ((rxnext % MODULO_INTERRUPT) != 0) rxdesc->length |= RxDisIntCompl; rxdesc->status = DescOwnByDma; rxdesc->status = 0; gmacdev->RxNext = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; gmacdev->RxNextDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); } TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2); (gmacdev->BusyRxDesc)++; //One descriptor will be given to Hardware. So busy count incremented by one return rxnext; } #endif #ifdef ENH_DESC_8W /** * This function is defined two times. Once when the code is compiled for ENHANCED DESCRIPTOR SUPPORT and Once for Normal descriptor * Get back the descriptor from DMA after data has been received. * When the DMA indicates that the data is received (interrupt is generated), this function should be * called to get the descriptor and hence the data buffers received. With successful return from this * function caller gets the descriptor fields for processing. check the parameters to understand the * fields returned.` * @param[in] pointer to synopGMACdevice. * @param[out] pointer to hold the status of DMA. * @param[out] Dma-able buffer1 pointer. * @param[out] pointer to hold length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] pointer to hold length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * \return returns present rx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_rx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2, u32 *Ext_Status, u32 *Time_Stamp_High, u32 *Time_Stamp_Low) { u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data //is spread over multiple buffers/descriptors DmaDesc *rxdesc = gmacdev->RxBusyDesc; if (synopGMAC_is_desc_owned_by_dma(rxdesc)) return -1; if (synopGMAC_is_desc_empty(rxdesc)) return -1; if (Status != 0) *Status = rxdesc->status;// send the status of this descriptor if (Ext_Status != 0) *Ext_Status = rxdesc->extstatus; if (Time_Stamp_High != 0) *Time_Stamp_High = rxdesc->timestamphigh; if (Time_Stamp_Low != 0) *Time_Stamp_Low = rxdesc->timestamplow; if (Length1 != 0) *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; if (Buffer1 != 0) *Buffer1 = rxdesc->buffer1; if (Data1 != 0) *Data1 = rxdesc->data1; if (Length2 != 0) *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift; if (Buffer2 != 0) *Buffer2 = rxdesc->buffer2; if (Data1 != 0) *Data2 = rxdesc->data2; gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; if (synopGMAC_is_rx_desc_chained(rxdesc)) { gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2; synopGMAC_rx_desc_init_chain(rxdesc); //synopGMAC_desc_init_chain(rxdesc, synopGMAC_is_last_rx_desc(gmacdev,rxdesc),0,0); } else { gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev, rxdesc)); } TR("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2); (gmacdev->BusyRxDesc)--; //busy tx descriptor is reduced by one as it will be handed over to Processor now return (rxnext); } #else /** * Get back the descriptor from DMA after data has been received. * When the DMA indicates that the data is received (interrupt is generated), this function should be * called to get the descriptor and hence the data buffers received. With successful return from this * function caller gets the descriptor fields for processing. check the parameters to understand the * fields returned.` * @param[in] pointer to synopGMACdevice. * @param[out] pointer to hold the status of DMA. * @param[out] Dma-able buffer1 pointer. * @param[out] pointer to hold length of buffer1 (Max is 2048). * @param[out] virtual pointer for buffer1. * @param[out] Dma-able buffer2 pointer. * @param[out] pointer to hold length of buffer2 (Max is 2048). * @param[out] virtual pointer for buffer2. * \return returns present rx descriptor index on success. Negative value if error. */ s32 synopGMAC_get_rx_qptr(synopGMACdevice *gmacdev, u32 *Status, u32 *Buffer1, u32 *Length1, u64 *Data1, u32 *Buffer2, u32 *Length2, u64 *Data2) { u32 rxnext = gmacdev->RxBusy; // index of descriptor the DMA just completed. May be useful when data //is spread over multiple buffers/descriptors DmaDesc *rxdesc = gmacdev->RxBusyDesc; u32 len; if (synopGMAC_is_desc_owned_by_dma(rxdesc)) { DEBUG_MES("synopGMAC_get_rx_qptr:DMA descriptor is owned by GMAC!\n"); return -1; } if (synopGMAC_is_desc_empty(rxdesc)) { DEBUG_MES("synopGMAC_get_rx_qptr:rx desc is empty!\n"); return -1; } if (Status != 0) *Status = rxdesc->status;// send the status of this descriptor if (Length1 != 0) *Length1 = (rxdesc->length & DescSize1Mask) >> DescSize1Shift; if (Buffer1 != 0) *Buffer1 = rxdesc->buffer1; if (Data1 != 0) *Data1 = rxdesc->data1; if (Length2 != 0) *Length2 = (rxdesc->length & DescSize2Mask) >> DescSize2Shift; if (Buffer2 != 0) *Buffer2 = rxdesc->buffer2; if (Data1 != 0) *Data2 = rxdesc->data2; len = synopGMAC_get_rx_desc_frame_length(*Status); DEBUG_MES("Cache sync for data buffer in rx dma desc: length = 0x%x\n", len); gmacdev->RxBusy = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? 0 : rxnext + 1; if (synopGMAC_is_rx_desc_chained(rxdesc)) { gmacdev->RxBusyDesc = (DmaDesc *)rxdesc->data2; synopGMAC_rx_desc_init_chain(rxdesc); } else { gmacdev->RxBusyDesc = synopGMAC_is_last_rx_desc(gmacdev, rxdesc) ? gmacdev->RxDesc : (rxdesc + 1); //sw: raw data #if SYNOP_RX_DEBUG DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2); #endif synopGMAC_rx_desc_init_ring(rxdesc, synopGMAC_is_last_rx_desc(gmacdev, rxdesc)); } #if SYNOP_RX_DEBUG DEBUG_MES("%02d %08x %08x %08x %08x %08x %08x %08x\n", rxnext, (u32)rxdesc, rxdesc->status, rxdesc->length, rxdesc->buffer1, rxdesc->buffer2, rxdesc->data1, rxdesc->data2); #endif (gmacdev->BusyRxDesc)--; //This returns one descriptor to processor. So busy count will be decremented by one return (rxnext); } #endif /** * Clears all the pending interrupts. * If the Dma status register is read then all the interrupts gets cleared * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_clear_interrupt(synopGMACdevice *gmacdev) { u32 data; data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); TR("DMA status reg = 0x%x before cleared!\n", data); synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, data); // plat_delay(DEFAULT_LOOP_VARIABLE); // data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); TR("DMA status reg = 0x%x after cleared!\n", data); } /** * Returns the all unmasked interrupt status after reading the DmaStatus register. * @param[in] pointer to synopGMACdevice. * \return 0 upon success. Error code upon failure. */ u32 synopGMAC_get_interrupt_type(synopGMACdevice *gmacdev) { u32 data; u32 interrupts = 0; data = synopGMACReadReg(gmacdev->DmaBase, DmaStatus); //data = data & ~0x84; //sw: some bits shoud not be cleaned synopGMACWriteReg(gmacdev->DmaBase, DmaStatus, data); //manju: I think this is the appropriate location to clear the interrupts plat_delay(DEFAULT_LOOP_VARIABLE); if (data & DmaIntErrorMask) interrupts |= synopGMACDmaError; if (data & DmaIntRxNormMask) interrupts |= synopGMACDmaRxNormal; if (data & DmaIntRxAbnMask) interrupts |= synopGMACDmaRxAbnormal; if (data & DmaIntRxStoppedMask) interrupts |= synopGMACDmaRxStopped; if (data & DmaIntTxNormMask) interrupts |= synopGMACDmaTxNormal; if (data & DmaIntTxAbnMask) interrupts |= synopGMACDmaTxAbnormal; if (data & DmaIntTxStoppedMask) interrupts |= synopGMACDmaTxStopped; return interrupts; } /** * Returns the interrupt mask. * @param[in] pointer to synopGMACdevice. * \return 0 upon success. Error code upon failure. */ #if UNUSED u32 synopGMAC_get_interrupt_mask(synopGMACdevice *gmacdev) { return (synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt)); } #endif /** * Enable all the interrupts. * Enables the DMA interrupt as specified by the bit mask. * @param[in] pointer to synopGMACdevice. * @param[in] bit mask of interrupts to be enabled. * \return returns void. */ #if UNUSED void synopGMAC_enable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) { synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, interrupts); return; } #endif /** * Disable all the interrupts. * Disables all DMA interrupts. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note This function disabled all the interrupts, if you want to disable a particular interrupt then * use synopGMAC_disable_interrupt(). */ void synopGMAC_disable_interrupt_all(synopGMACdevice *gmacdev) { // rt_kprintf("dmabase = 0x%x\n",gmacdev->DmaBase); synopGMACWriteReg(gmacdev->DmaBase, DmaInterrupt, DmaIntDisable); // synopGMACReadReg(gmacdev->DmaBase, DmaInterrupt); return; } /** * Disable interrupt according to the bitfield supplied. * Disables only those interrupts specified in the bit mask in second argument. * @param[in] pointer to synopGMACdevice. * @param[in] bit mask for interrupts to be disabled. * \return returns void. */ #if UNUSED void synopGMAC_disable_interrupt(synopGMACdevice *gmacdev, u32 interrupts) { synopGMACClearBits(gmacdev->DmaBase, DmaInterrupt, interrupts); return; } #endif /** * Enable the DMA Reception. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_enable_dma_rx(synopGMACdevice *gmacdev) { // synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaRxStart); u32 data; data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); data |= DmaRxStart; TR0(" ===33334\n"); synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data); TR0(" ===33344\n"); } /** * Enable the DMA Transmission. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_enable_dma_tx(synopGMACdevice *gmacdev) { // synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaTxStart); u32 data; data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); data |= DmaTxStart; synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data); } /** * Resumes the DMA Transmission. * the DmaTxPollDemand is written. (the data writeen could be anything). * This forces the DMA to resume transmission. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_resume_dma_tx(synopGMACdevice *gmacdev) { synopGMACWriteReg(gmacdev->DmaBase, DmaTxPollDemand, 1); } /** * Resumes the DMA Reception. * the DmaRxPollDemand is written. (the data writeen could be anything). * This forces the DMA to resume reception. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_resume_dma_rx(synopGMACdevice *gmacdev) { synopGMACWriteReg(gmacdev->DmaBase, DmaRxPollDemand, 0); } /** * Take ownership of this Descriptor. * The function is same for both the ring mode and the chain mode DMA structures. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_take_desc_ownership(DmaDesc *desc) { if (desc) { desc->status &= ~DescOwnByDma; //Clear the DMA own bit // desc->status |= DescError; // Set the error to indicate this descriptor is bad } } /** * Take ownership of all the rx Descriptors. * This function is called when there is fatal error in DMA transmission. * When called it takes the ownership of all the rx descriptor in rx descriptor pool/queue from DMA. * The function is same for both the ring mode and the chain mode DMA structures. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. */ void synopGMAC_take_desc_ownership_rx(synopGMACdevice *gmacdev) { s32 i; DmaDesc *desc; desc = gmacdev->RxDesc; for (i = 0; i < gmacdev->RxDescCount; i++) { if (synopGMAC_is_rx_desc_chained(desc)) //This descriptor is in chain mode { synopGMAC_take_desc_ownership(desc); desc = (DmaDesc *)desc->data2; } else { synopGMAC_take_desc_ownership(desc + i); } } } /** * Take ownership of all the rx Descriptors. * This function is called when there is fatal error in DMA transmission. * When called it takes the ownership of all the tx descriptor in tx descriptor pool/queue from DMA. * The function is same for both the ring mode and the chain mode DMA structures. * @param[in] pointer to synopGMACdevice. * \return returns void. * \note Make sure to disable the transmission before calling this function, otherwise may result in racing situation. */ void synopGMAC_take_desc_ownership_tx(synopGMACdevice *gmacdev) { s32 i; DmaDesc *desc; desc = gmacdev->TxDesc; for (i = 0; i < gmacdev->TxDescCount; i++) { if (synopGMAC_is_tx_desc_chained(desc)) //This descriptor is in chain mode { synopGMAC_take_desc_ownership(desc); desc = (DmaDesc *)desc->data2; } else { synopGMAC_take_desc_ownership(desc + i); } } } /** * Disable the DMA for Transmission. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_disable_dma_tx(synopGMACdevice *gmacdev) { // synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaTxStart); u32 data; data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); data &= (~DmaTxStart); synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data); } /** * Disable the DMA for Reception. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_disable_dma_rx(synopGMACdevice *gmacdev) { // synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaRxStart); u32 data; data = synopGMACReadReg(gmacdev->DmaBase, DmaControl); data &= (~DmaRxStart); synopGMACWriteReg(gmacdev->DmaBase, DmaControl, data); } /*******************PMT APIs***************************************/ /** * Enables the assertion of PMT interrupt. * This enables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame * reception. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_pmt_int_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); return; } #endif /** * Disables the assertion of PMT interrupt. * This disables the assertion of PMT interrupt due to Magic Pkt or Wakeup frame * reception. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_pmt_int_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); return; } /** * Enables the power down mode of GMAC. * This function puts the Gmac in power down mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_power_down_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown); return; } #endif /** * Disables the powerd down setting of GMAC. * If the driver wants to bring up the GMAC from powerdown mode, even though the magic packet or the * wake up frames received from the network, this function should be called. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_power_down_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtPowerDown); return; } #endif /** * Enables the pmt interrupt generation in powerdown mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_enable_pmt_interrupt(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); } #endif /** * Disables the pmt interrupt generation in powerdown mode. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_disable_pmt_interrupt(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); } #endif /** * Enables GMAC to look for Magic packet. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_magic_packet_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtMagicPktEnable); return; } #endif /** * Enables GMAC to look for wake up frame. * Wake up frame is defined by the user. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_wakeup_frame_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtWakeupFrameEnable); return; } #endif /** * Enables wake-up frame filter to handle unicast packets. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_pmt_unicast_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtGlobalUnicast); return; } #endif /** * Checks whether the packet received is a magic packet?. * @param[in] pointer to synopGMACdevice. * \return returns True if magic packet received else returns false. */ bool synopGMAC_is_magic_packet_received(synopGMACdevice *gmacdev) { u32 data; data = synopGMACReadReg(gmacdev->MacBase, GmacPmtCtrlStatus); return ((data & GmacPmtMagicPktReceived) == GmacPmtMagicPktReceived); } /** * Checks whether the packet received is a wakeup frame?. * @param[in] pointer to synopGMACdevice. * \return returns true if wakeup frame received else returns false. */ bool synopGMAC_is_wakeup_frame_received(synopGMACdevice *gmacdev) { u32 data; data = synopGMACReadReg(gmacdev->MacBase, GmacPmtCtrlStatus); return ((data & GmacPmtWakeupFrameReceived) == GmacPmtWakeupFrameReceived); } /** * Populates the remote wakeup frame registers. * Consecutive 8 writes to GmacWakeupAddr writes the wakeup frame filter registers. * Before commensing a new write, frame filter pointer is reset to 0x0000. * A small delay is introduced to allow frame filter pointer reset operation. * @param[in] pointer to synopGMACdevice. * @param[in] pointer to frame filter contents array. * \return returns void. */ #if UNUSED void synopGMAC_write_wakeup_frame_register(synopGMACdevice *gmacdev, u32 *filter_contents) { s32 i; synopGMACSetBits(gmacdev->MacBase, GmacPmtCtrlStatus, GmacPmtFrmFilterPtrReset); plat_delay(10); for (i = 0; i < WAKEUP_REG_LENGTH; i++) synopGMACWriteReg(gmacdev->MacBase, GmacWakeupAddr, *(filter_contents + i)); return; } #endif /*******************PMT APIs***************************************/ /*******************MMC APIs***************************************/ /** * Freezes the MMC counters. * This function call freezes the MMC counters. None of the MMC counters are updated * due to any tx or rx frames until synopGMAC_mmc_counters_resume is called. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_mmc_counters_stop(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze); return; } #endif /** * Resumes the MMC counter updation. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_mmc_counters_resume(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterFreeze); return; } #endif /** * Configures the MMC in Self clearing mode. * Programs MMC interface so that counters are cleared when the counters are read. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_mmc_counters_set_selfclear(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead); return; } #endif /** * Configures the MMC in non-Self clearing mode. * Programs MMC interface so that counters are cleared when the counters are read. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_mmc_counters_reset_selfclear(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterResetOnRead); return; } #endif /** * Configures the MMC to stop rollover. * Programs MMC interface so that counters will not rollover after reaching maximum value. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_mmc_counters_disable_rollover(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover); return; } /** * Configures the MMC to rollover. * Programs MMC interface so that counters will rollover after reaching maximum value. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_mmc_counters_enable_rollover(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacMmcCntrl, GmacMmcCounterStopRollover); return; } /** * Read the MMC Counter. * @param[in] pointer to synopGMACdevice. * @param[in] the counter to be read. * \return returns the read count value. */ u32 synopGMAC_read_mmc_counter(synopGMACdevice *gmacdev, u32 counter) { return (synopGMACReadReg(gmacdev->MacBase, counter)); } #endif /** * Read the MMC Rx interrupt status. * @param[in] pointer to synopGMACdevice. * \return returns the Rx interrupt status. */ u32 synopGMAC_read_mmc_rx_int_status(synopGMACdevice *gmacdev) { return (synopGMACReadReg(gmacdev->MacBase, GmacMmcIntrRx)); } /** * Read the MMC Tx interrupt status. * @param[in] pointer to synopGMACdevice. * \return returns the Tx interrupt status. */ u32 synopGMAC_read_mmc_tx_int_status(synopGMACdevice *gmacdev) { return (synopGMACReadReg(gmacdev->MacBase, GmacMmcIntrTx)); } /** * Disable the MMC Tx interrupt. * The MMC tx interrupts are masked out as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] tx interrupt bit mask for which interrupts needs to be disabled. * \return returns void. */ void synopGMAC_disable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACSetBits(gmacdev->MacBase, GmacMmcIntrMaskTx, mask); return; } /** * Enable the MMC Tx interrupt. * The MMC tx interrupts are enabled as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] tx interrupt bit mask for which interrupts needs to be enabled. * \return returns void. */ #if UNUSED void synopGMAC_enable_mmc_tx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACClearBits(gmacdev->MacBase, GmacMmcIntrMaskTx, mask); } #endif /** * Disable the MMC Rx interrupt. * The MMC rx interrupts are masked out as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. * \return returns void. */ void synopGMAC_disable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACSetBits(gmacdev->MacBase, GmacMmcIntrMaskRx, mask); return; } /** * Enable the MMC Rx interrupt. * The MMC rx interrupts are enabled as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. * \return returns void. */ #if UNUSED void synopGMAC_enable_mmc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACClearBits(gmacdev->MacBase, GmacMmcIntrMaskRx, mask); return; } #endif /** * Disable the MMC ipc rx checksum offload interrupt. * The MMC ipc rx checksum offload interrupts are masked out as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] rx interrupt bit mask for which interrupts needs to be disabled. * \return returns void. */ void synopGMAC_disable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACSetBits(gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask); return; } /** * Enable the MMC ipc rx checksum offload interrupt. * The MMC ipc rx checksum offload interrupts are enabled as per the mask specified. * @param[in] pointer to synopGMACdevice. * @param[in] rx interrupt bit mask for which interrupts needs to be enabled. * \return returns void. */ #if UNUSED void synopGMAC_enable_mmc_ipc_rx_interrupt(synopGMACdevice *gmacdev, u32 mask) { synopGMACClearBits(gmacdev->MacBase, GmacMmcRxIpcIntrMask, mask); return; } #endif /*******************MMC APIs***************************************/ /*******************Ip checksum offloading APIs***************************************/ /** * Enables the ip checksum offloading in receive path. * When set GMAC calculates 16 bit 1's complement of all received ethernet frame payload. * It also checks IPv4 Header checksum is correct. GMAC core appends the 16 bit checksum calculated * for payload of IP datagram and appends it to Ethernet frame transferred to the application. * @param[in] pointer to synopGMACdevice. * \return returns void. */ #if UNUSED void synopGMAC_enable_rx_chksum_offload(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacConfig, GmacRxIpcOffload); return; } /** * Disable the ip checksum offloading in receive path. * Ip checksum offloading is disabled in the receive path. * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_disable_rx_Ipchecksum_offload(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacConfig, GmacRxIpcOffload); } /** * Instruct the DMA to drop the packets fails tcp ip checksum. * This is to instruct the receive DMA engine to drop the recevied packet if they * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_rx_tcpip_chksum_drop_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs); return; } /** * Instruct the DMA not to drop the packets even if it fails tcp ip checksum. * This is to instruct the receive DMA engine to allow the packets even if recevied packet * fails the tcp/ip checksum in hardware. Valid only when full checksum offloading is enabled(type-2). * @param[in] pointer to synopGMACdevice. * \return returns void. */ void synopGMAC_rx_tcpip_chksum_drop_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->DmaBase, DmaControl, DmaDisableDropTcpCs); return; } #endif /** * When the Enhanced Descriptor is enabled then the bit 0 of RDES0 indicates whether the * Extended Status is available (RDES4). Time Stamp feature and the Checksum Offload Engine2 * makes use of this extended status to provide the status of the received packet. * @param[in] pointer to synopGMACdevice * \return returns TRUE or FALSE */ #ifdef ENH_DESC_8W /** * This function indicates whether extended status is available in the RDES0. * Any function which accesses the fields of extended status register must ensure a check on this has been made * This is valid only for Enhanced Descriptor. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns TRUE or FALSE. */ bool synopGMAC_is_ext_status(synopGMACdevice *gmacdev, u32 status) // extended status present indicates that the RDES4 need to be probed { return ((status & DescRxEXTsts) != 0); // if extstatus set then it returns 1 } /** * This function returns true if the IP header checksum bit is set in the extended status. * Valid only when enhaced status available is set in RDES0 bit 0. * This is valid only for Enhanced Descriptor. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns TRUE or FALSE. */ bool synopGMAC_ES_is_IP_header_error(synopGMACdevice *gmacdev, u32 ext_status) // IP header (IPV4) checksum error { return ((ext_status & DescRxIpHeaderError) != 0); // if IPV4 header error return 1 } /** * This function returns true if the Checksum is bypassed in the hardware. * Valid only when enhaced status available is set in RDES0 bit 0. * This is valid only for Enhanced Descriptor. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns TRUE or FALSE. */ bool synopGMAC_ES_is_rx_checksum_bypassed(synopGMACdevice *gmacdev, u32 ext_status) // Hardware engine bypassed the checksum computation/checking { return ((ext_status & DescRxChkSumBypass) != 0); // if checksum offloading bypassed return 1 } /** * This function returns true if payload checksum error is set in the extended status. * Valid only when enhaced status available is set in RDES0 bit 0. * This is valid only for Enhanced Descriptor. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns TRUE or FALSE. */ bool synopGMAC_ES_is_IP_payload_error(synopGMACdevice *gmacdev, u32 ext_status) // IP payload checksum is in error (UDP/TCP/ICMP checksum error) { return ((ext_status & DescRxIpPayloadError) != 0); // if IP payload error return 1 } #endif /** * Decodes the Rx Descriptor status to various checksum error conditions. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns decoded enum (u32) indicating the status. */ u32 synopGMAC_is_rx_checksum_error(synopGMACdevice *gmacdev, u32 status) { if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) return RxLenLT600; else if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) return RxIpHdrPayLoadChkBypass; else if (((status & DescRxChkBit5) == 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) return RxChkBypass; else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) == 0)) return RxNoChkError; else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) == 0) && ((status & DescRxChkBit0) != 0)) return RxPayLoadChkError; else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) == 0)) return RxIpHdrChkError; else if (((status & DescRxChkBit5) != 0) && ((status & DescRxChkBit7) != 0) && ((status & DescRxChkBit0) != 0)) return RxIpHdrPayLoadChkError; else return RxIpHdrPayLoadRes; } /** * Checks if any Ipv4 header checksum error in the frame just transmitted. * This serves as indication that error occureed in the IPv4 header checksum insertion. * The sent out frame doesnot carry any ipv4 header checksum inserted by the hardware. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns true if error in ipv4 header checksum, else returns false. */ bool synopGMAC_is_tx_ipv4header_checksum_error(synopGMACdevice *gmacdev, u32 status) { return ((status & DescTxIpv4ChkError) == DescTxIpv4ChkError); } /** * Checks if any payload checksum error in the frame just transmitted. * This serves as indication that error occureed in the payload checksum insertion. * The sent out frame doesnot carry any payload checksum inserted by the hardware. * @param[in] pointer to synopGMACdevice. * @param[in] u32 status field of the corresponding descriptor. * \return returns true if error in ipv4 header checksum, else returns false. */ bool synopGMAC_is_tx_payload_checksum_error(synopGMACdevice *gmacdev, u32 status) { return ((status & DescTxPayChkError) == DescTxPayChkError); } /** * The check summ offload engine is bypassed in the tx path. * Checksum is not computed in the Hardware. * @param[in] pointer to synopGMACdevice. * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. * \return returns void. */ void synopGMAC_tx_checksum_offload_bypass(synopGMACdevice *gmacdev, DmaDesc *desc) { #ifdef ENH_DESC desc->status = (desc->length & (~DescTxCisMask));//ENH_DESC #else desc->length = (desc->length & (~DescTxCisMask)); #endif } /** * The check summ offload engine is enabled to do only IPV4 header checksum. * IPV4 header Checksum is computed in the Hardware. * @param[in] pointer to synopGMACdevice. * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. * \return returns void. */ void synopGMAC_tx_checksum_offload_ipv4hdr(synopGMACdevice *gmacdev, DmaDesc *desc) { #ifdef ENH_DESC desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisIpv4HdrCs);//ENH_DESC #else desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisIpv4HdrCs); #endif } /** * The check summ offload engine is enabled to do TCPIP checsum assuming Pseudo header is available. * Hardware computes the tcp ip checksum assuming pseudo header checksum is computed in software. * Ipv4 header checksum is also inserted. * @param[in] pointer to synopGMACdevice. * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. * \return returns void. */ void synopGMAC_tx_checksum_offload_tcponly(synopGMACdevice *gmacdev, DmaDesc *desc) { #ifdef ENH_DESC desc->status = ((desc->status & (~DescTxCisMask)) | DescTxCisTcpOnlyCs);//ENH_DESC #else desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpOnlyCs); #endif } /** * The check summ offload engine is enabled to do complete checksum computation. * Hardware computes the tcp ip checksum including the pseudo header checksum. * Here the tcp payload checksum field should be set to 0000. * Ipv4 header checksum is also inserted. * @param[in] pointer to synopGMACdevice. * @param[in] Pointer to tx descriptor for which ointer to synopGMACdevice. * \return returns void. */ void synopGMAC_tx_checksum_offload_tcp_pseudo(synopGMACdevice *gmacdev, DmaDesc *desc) { #ifdef ENH_DESC desc->status = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); #else desc->length = ((desc->length & (~DescTxCisMask)) | DescTxCisTcpPseudoCs); #endif } /*******************Ip checksum offloading APIs***************************************/ /*******************IEEE 1588 Timestamping API***************************************/ /* * At this time the driver supports the IEEE time stamping feature when the Enhanced Descriptors are enabled. * For normal descriptor and the IEEE time stamp (version 1), driver support is not proviced * Please make sure you have enabled the Advanced timestamp feature in the hardware and the driver should * be compiled with the ADV_TME_STAMP feature. * Some of the APIs provided here may not be valid for all configurations. Please make sure you call the * API with due care. */ /** * This function enables the timestamping. This enables the timestamping for transmit and receive frames. * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. * @param[in] pointer to synopGMACdevice * \return returns void */ #if UNUSED void synopGMAC_TS_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENA); return; } /** * This function disables the timestamping. * When disabled timestamp is not added to tx and receive frames and timestamp generator is suspended. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacTSIntMask); return; } /** * Enable the interrupt to get timestamping interrupt. * This enables the host to get the interrupt when (1) system time is greater or equal to the * target time high and low register or (2) there is a overflow in th esecond register. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_int_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); return; } /** * Disable the interrupt to get timestamping interrupt. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_int_disable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacInterruptMask, GmacPmtIntMask); return; } /** * Enable MAC address for PTP frame filtering. * When enabled, uses MAC address (apart from MAC address 0) to filter the PTP frames when * PTP is sent directly over Ethernet. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_mac_addr_filt_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENMACADDR); return; } /** * Disables MAC address for PTP frame filtering. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_mac_addr_filt_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSENMACADDR); return; } /** * Selet the type of clock mode for PTP. * Please note to use one of the follwoing as the clk_type argument. * GmacTSOrdClk = 0x00000000, 00=> Ordinary clock * GmacTSBouClk = 0x00010000, 01=> Boundary clock * GmacTSEtoEClk = 0x00020000, 10=> End-to-End transparent clock * GmacTSPtoPClk = 0x00030000, 11=> P-to-P transparent clock * @param[in] pointer to synopGMACdevice * @param[in] u32 value representing one of the above clk value * \return returns void */ void synopGMAC_TS_set_clk_type(synopGMACdevice *gmacdev, u32 clk_type) { u32 clkval; clkval = synopGMACReadReg(gmacdev->MacBase, GmacTSControl); //set the mdc clock to the user defined value clkval = clkval | clk_type; synopGMACWriteReg(gmacdev->MacBase, GmacTSControl, clkval); return; } /** * Enable Snapshot for messages relevant to Master. * When enabled, snapshot is taken for messages relevant to master mode only, else snapshot is taken for messages relevant * to slave node. * Valid only for Ordinary clock and Boundary clock * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_master_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSMSTRENA); return; } /** * Disable Snapshot for messages relevant to Master. * When disabled, snapshot is taken for messages relevant * to slave node. * Valid only for Ordinary clock and Boundary clock * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_master_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSMSTRENA); return; } /** * Enable Snapshot for Event messages. * When enabled, snapshot is taken for event messages only (SYNC, Delay_Req, Pdelay_Req or Pdelay_Resp) * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_event_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSEVNTENA); return; } /** * Disable Snapshot for Event messages. * When disabled, snapshot is taken for all messages except Announce, Management and Signaling. * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_event_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSEVNTENA); return; } /** * Enable time stamp snapshot for IPV4 frames. * When enabled, time stamp snapshot is taken for IPV4 frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_IPV4_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV4ENA); return; } /** * Disable time stamp snapshot for IPV4 frames. * When disabled, time stamp snapshot is not taken for IPV4 frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_IPV4_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV4ENA); return; } // Only for "Advanced Time Stamp" /** * Enable time stamp snapshot for IPV6 frames. * When enabled, time stamp snapshot is taken for IPV6 frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_IPV6_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV6ENA); return; } /** * Disable time stamp snapshot for IPV6 frames. * When disabled, time stamp snapshot is not taken for IPV6 frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_IPV6_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPV6ENA); return; } /** * Enable time stamp snapshot for PTP over Ethernet frames. * When enabled, time stamp snapshot is taken for PTP over Ethernet frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_ptp_over_ethernet_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSIPENA); return; } /** * Disable time stamp snapshot for PTP over Ethernet frames. * When disabled, time stamp snapshot is not taken for PTP over Ethernet frames * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_ptp_over_ethernet_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSIPENA); return; } /** * Snoop PTP packet for version 2 format * When set the PTP packets are snooped using the version 2 format. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_pkt_snoop_ver2(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSVER2ENA); return; } /** * Snoop PTP packet for version 2 format * When set the PTP packets are snooped using the version 2 format. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_pkt_snoop_ver1(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSVER2ENA); return; } /** * Timestamp digital rollover * When set the timestamp low register rolls over after 0x3B9A_C9FF value. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_digital_rollover_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSCTRLSSR); return; } /** * Timestamp binary rollover * When set the timestamp low register rolls over after 0x7FFF_FFFF value. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_binary_rollover_enable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSCTRLSSR); return; } /** * Enable Time Stamp for All frames * When set the timestamp snap shot is enabled for all frames received by the core. * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_all_frames_enable(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSENALL); return; } /** * Disable Time Stamp for All frames * When reset the timestamp snap shot is not enabled for all frames received by the core. * Reserved when "Advanced Time Stamp" is not selected * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_all_frames_disable(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSENALL); return; } /** * Addend Register Update * This function loads the contents of Time stamp addend register with the supplied 32 value. * This is reserved function when only coarse correction option is selected * @param[in] pointer to synopGMACdevice * @param[in] 32 bit addend value * \return returns 0 for Success or else Failure */ s32 synopGMAC_TS_addend_update(synopGMACdevice *gmacdev, u32 addend_value) { u32 loop_variable; synopGMACWriteReg(gmacdev->MacBase, GmacTSAddend, addend_value); // Load the addend_value in to Addend register for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time { if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSADDREG)) // if it is cleared then break { break; } plat_delay(DEFAULT_DELAY_VARIABLE); } if (loop_variable < DEFAULT_LOOP_VARIABLE) synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSADDREG); else { TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); return -ESYNOPGMACPHYERR; } return -ESYNOPGMACNOERR; } /** * time stamp Update * This function updates (adds/subtracts) with the value specified in the Timestamp High Update and * Timestamp Low Update register. * @param[in] pointer to synopGMACdevice * @param[in] Timestamp High Update value * @param[in] Timestamp Low Update value * \return returns 0 for Success or else Failure */ s32 synopGMAC_TS_timestamp_update(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) { u32 loop_variable; synopGMACWriteReg(gmacdev->MacBase, GmacTSHighUpdate, high_value); // Load the high value to Timestamp High register synopGMACWriteReg(gmacdev->MacBase, GmacTSLowUpdate, low_value); // Load the high value to Timestamp High register for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time { if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSUPDT)) // if it is cleared then break { break; } plat_delay(DEFAULT_DELAY_VARIABLE); } if (loop_variable < DEFAULT_LOOP_VARIABLE) synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSUPDT); else { TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); return -ESYNOPGMACPHYERR; } return -ESYNOPGMACNOERR; } /** * time stamp Initialize * This function Loads/Initializes h the value specified in the Timestamp High Update and * Timestamp Low Update register. * @param[in] pointer to synopGMACdevice * @param[in] Timestamp High Load value * @param[in] Timestamp Low Load value * \return returns 0 for Success or else Failure */ s32 synopGMAC_TS_timestamp_init(synopGMACdevice *gmacdev, u32 high_value, u32 low_value) { u32 loop_variable; synopGMACWriteReg(gmacdev->MacBase, GmacTSHighUpdate, high_value); // Load the high value to Timestamp High register synopGMACWriteReg(gmacdev->MacBase, GmacTSLowUpdate, low_value); // Load the high value to Timestamp High register for (loop_variable = 0; loop_variable < DEFAULT_LOOP_VARIABLE; loop_variable++) //Wait till the busy bit gets cleared with in a certain amount of time { if (!((synopGMACReadReg(gmacdev->MacBase, GmacTSControl)) & GmacTSINT)) // if it is cleared then break { break; } plat_delay(DEFAULT_DELAY_VARIABLE); } if (loop_variable < DEFAULT_LOOP_VARIABLE) synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSINT); else { TR("Error::: The TSADDREG bit is not getting cleared !!!!!!\n"); return -ESYNOPGMACPHYERR; } return -ESYNOPGMACNOERR; } /** * Time Stamp Update Coarse * When reset the timestamp update is done using coarse method. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_coarse_update(synopGMACdevice *gmacdev) { synopGMACClearBits(gmacdev->MacBase, GmacTSControl, GmacTSCFUPDT); return; } /** * Time Stamp Update Fine * When reset the timestamp update is done using Fine method. * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_fine_update(synopGMACdevice *gmacdev) { synopGMACSetBits(gmacdev->MacBase, GmacTSControl, GmacTSCFUPDT); return; } /** * Load the Sub Second Increment value in to Sub Second increment register * @param[in] pointer to synopGMACdevice * \return returns void */ void synopGMAC_TS_subsecond_init(synopGMACdevice *gmacdev, u32 sub_sec_inc_value) { synopGMACWriteReg(gmacdev->MacBase, GmacTSSubSecIncr, (sub_sec_inc_value & GmacSSINCMsk)); return; } /** * Reads the time stamp contents in to the respective pointers * These registers are readonly. * This function returns the 48 bit time stamp assuming Version 2 timestamp with higher word is selected. * @param[in] pointer to synopGMACdevice * @param[in] pointer to hold 16 higher bit second register contents * @param[in] pointer to hold 32 bit second register contents * @param[in] pointer to hold 32 bit subnanosecond register contents * \return returns void * \note Please note that since the atomic access to the timestamp registers is not possible, * the contents read may be different from the actual time stamp. */ void synopGMAC_TS_read_timestamp(synopGMACdevice *gmacdev, u16 *higher_sec_val, u32 *sec_val, u32 *sub_sec_val) { * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase, GmacTSHighWord) & GmacTSHighWordMask); * sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSHigh); * sub_sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSLow); return; } /** * Loads the time stamp higher sec value from the value supplied * @param[in] pointer to synopGMACdevice * @param[in] 16 higher bit second register contents passed as 32 bit value * \return returns void */ void synopGMAC_TS_load_timestamp_higher_val(synopGMACdevice *gmacdev, u32 higher_sec_val) { synopGMACWriteReg(gmacdev->MacBase, GmacTSHighWord, (higher_sec_val & GmacTSHighWordMask)); return; } /** * Reads the time stamp higher sec value to respective pointers * @param[in] pointer to synopGMACdevice * @param[in] pointer to hold 16 higher bit second register contents * \return returns void */ void synopGMAC_TS_read_timestamp_higher_val(synopGMACdevice *gmacdev, u16 *higher_sec_val) { * higher_sec_val = (u16)(synopGMACReadReg(gmacdev->MacBase, GmacTSHighWord) & GmacTSHighWordMask); return; } /** * Load the Target time stamp registers * This function Loads the target time stamp registers with the values proviced * @param[in] pointer to synopGMACdevice * @param[in] target Timestamp High value * @param[in] target Timestamp Low value * \return returns 0 for Success or else Failure */ void synopGMAC_TS_load_target_timestamp(synopGMACdevice *gmacdev, u32 sec_val, u32 sub_sec_val) { synopGMACWriteReg(gmacdev->MacBase, GmacTSTargetTimeHigh, sec_val); synopGMACWriteReg(gmacdev->MacBase, GmacTSTargetTimeLow, sub_sec_val); return; } /** * Reads the Target time stamp registers * This function Loads the target time stamp registers with the values proviced * @param[in] pointer to synopGMACdevice * @param[in] pointer to hold target Timestamp High value * @param[in] pointer to hold target Timestamp Low value * \return returns 0 for Success or else Failure */ void synopGMAC_TS_read_target_timestamp(synopGMACdevice *gmacdev, u32 *sec_val, u32 *sub_sec_val) { * sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSTargetTimeHigh); * sub_sec_val = synopGMACReadReg(gmacdev->MacBase, GmacTSTargetTimeLow); return; } #endif