Loading drivers/emac-dwc-eqos/Android.mk +9 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,15 @@ KBUILD_OPTIONS += DCONFIG_DEBUGFS_OBJ=1 LOCAL_MODULE := emac_dwc_eqos.ko LOCAL_MODULE := emac_dwc_eqos.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional include $(DLKM_DIR)/AndroidKernelModule.mk include $(DLKM_DIR)/AndroidKernelModule.mk include $(CLEAR_VARS) LOCAL_MODULE := emac_perf_settings.sh LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/emac LOCAL_SRC_FILES := emac_perf_settings.sh include $(BUILD_PREBUILT) endif endif endif endif Loading drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1440,7 +1440,7 @@ static int DWC_ETH_QOS_map_page_buffs(struct DWC_ETH_QOS_prv_data *pdata, DBGPR("-->DWC_ETH_QOS_map_page_buffs\n"); DBGPR("-->DWC_ETH_QOS_map_page_buffs\n"); if (size > DWC_ETH_QOS_MAX_DATA_PER_TX_BUF) { if (size > DWC_ETH_QOS_MAX_DATA_PER_TX_BUF) { if (!prev_buffer->dma2) { if (prev_buffer && !prev_buffer->dma2) { DBGPR("prev_buffer->dma2 is empty\n"); DBGPR("prev_buffer->dma2 is empty\n"); /* fill the first buffer pointer in pre_buffer->dma2 */ /* fill the first buffer pointer in pre_buffer->dma2 */ prev_buffer->dma2 = prev_buffer->dma2 = Loading Loading @@ -1505,7 +1505,7 @@ static int DWC_ETH_QOS_map_page_buffs(struct DWC_ETH_QOS_prv_data *pdata, buffer->buf2_mapped_as_page = Y_TRUE; buffer->buf2_mapped_as_page = Y_TRUE; } } } else { } else { if (!prev_buffer->dma2) { if (prev_buffer && !prev_buffer->dma2) { DBGPR("prev_buffer->dma2 is empty\n"); DBGPR("prev_buffer->dma2 is empty\n"); /* fill the first buffer pointer in pre_buffer->dma2 */ /* fill the first buffer pointer in pre_buffer->dma2 */ prev_buffer->dma2 = dma_map_page(GET_MEM_PDEV_DEV, prev_buffer->dma2 = dma_map_page(GET_MEM_PDEV_DEV, Loading drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c +57 −16 Original line number Original line Diff line number Diff line Loading @@ -1136,8 +1136,9 @@ static INT drop_tx_status_enabled(void) static INT config_sub_second_increment(ULONG ptp_clock) static INT config_sub_second_increment(ULONG ptp_clock) { { ULONG val; ULONG VARMAC_TCR; ULONG VARMAC_TCR; double ss_inc = 0; double sns_inc = 0; MAC_TCR_RGRD(VARMAC_TCR); MAC_TCR_RGRD(VARMAC_TCR); Loading @@ -1145,30 +1146,69 @@ static INT config_sub_second_increment(ULONG ptp_clock) /* formula is : ((1/ptp_clock) * 1000000000) */ /* formula is : ((1/ptp_clock) * 1000000000) */ /* where, ptp_clock = 50MHz if FINE correction */ /* where, ptp_clock = 50MHz if FINE correction */ /* and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */ /* and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */ #ifdef CONFIG_PPS_OUTPUT if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { EMACDBG("Using PTP clock %ld MHz\n", ptp_clock); EMACDBG("Using PTP clock %ld MHz\n", ptp_clock); val = ((1 * 1000000000ull) / ptp_clock); ss_inc = (double)1000000000.0 / (double)ptp_clock; } } else { else { EMACDBG("Using SYSCLOCK for coarse correction\n"); EMACDBG("Using SYSCLOCK for coarse correction\n"); val = ((1 * 1000000000ull) / DWC_ETH_QOS_SYSCLOCK ); ss_inc = (double)1000000000.0 / (double)DWC_ETH_QOS_SYSCLOCK; } } #else if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { /* 0.465ns accuracy */ val = ((1 * 1000000000ull) / 50000000); } else { val = ((1 * 1000000000ull) / ptp_clock); } #endif /* 0.465ns accurecy */ if (GET_VALUE( if (GET_VALUE( VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS, VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS, MAC_TCR_TSCTRLSSR_HPOS) == 0) MAC_TCR_TSCTRLSSR_HPOS) == 0) { val = (val * 1000) / 465; EMACDBG("using 0.465 ns accuracy"); ss_inc /= 0.465; } sns_inc = ss_inc - (int)ss_inc; // take remainder sns_inc *= 256.0; // sns_inc needs to be multiplied by 2^8, per spec. sns_inc += 0.5; // round to nearest int value. MAC_SSIR_SSINC_UDFWR(val); MAC_SSIR_SSINC_UDFWR((int)ss_inc); MAC_SSIR_SNSINC_UDFWR((int)sns_inc); EMACDBG("ss_inc = %d, sns_inc = %d\n", (int)ss_inc, (int)sns_inc); return Y_SUCCESS; } /*! * \brief * \param[in] * \return Success or Failure * \retval 0 Success * \retval -1 Failure */ static INT config_default_addend(struct DWC_ETH_QOS_prv_data *pdata, ULONG ptp_clock) { struct hw_if_struct *hw_if = &pdata->hw_if; u64 temp; /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) */ if (ptp_clock == DWC_ETH_QOS_SYSCLOCK) { // If PTP_CLOCK == SYS_CLOCK, best we can do is 2^32 - 1 pdata->default_addend = 0xFFFFFFFF; } else { temp = (u64)((u64)ptp_clock << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); } hw_if->config_addend(pdata->default_addend); EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n", ptp_clock, (unsigned int)pdata->default_addend); return Y_SUCCESS; return Y_SUCCESS; } } Loading Loading @@ -5114,6 +5154,7 @@ void DWC_ETH_QOS_init_function_ptrs_dev(struct hw_if_struct *hw_if) /* for hw time stamping */ /* for hw time stamping */ hw_if->config_hw_time_stamping = config_hw_time_stamping; hw_if->config_hw_time_stamping = config_hw_time_stamping; hw_if->config_sub_second_increment = config_sub_second_increment; hw_if->config_sub_second_increment = config_sub_second_increment; hw_if->config_default_addend = config_default_addend; hw_if->init_systime = init_systime; hw_if->init_systime = init_systime; hw_if->config_addend = config_addend; hw_if->config_addend = config_addend; hw_if->adjust_systime = adjust_systime; hw_if->adjust_systime = adjust_systime; Loading drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +142 −194 Original line number Original line Diff line number Diff line Loading @@ -784,6 +784,7 @@ void DWC_ETH_QOS_handle_phy_interrupt(struct DWC_ETH_QOS_prv_data *pdata) int micrel_intr_status = 0; int micrel_intr_status = 0; EMACDBG("Enter\n"); EMACDBG("Enter\n"); if ((pdata->phydev->phy_id & pdata->phydev->drv->phy_id_mask) == MICREL_PHY_ID) { DWC_ETH_QOS_mdio_read_direct( DWC_ETH_QOS_mdio_read_direct( pdata, pdata->phyaddr, DWC_ETH_QOS_BASIC_STATUS, &phy_intr_status); pdata, pdata->phyaddr, DWC_ETH_QOS_BASIC_STATUS, &phy_intr_status); EMACDBG( EMACDBG( Loading @@ -809,6 +810,25 @@ void DWC_ETH_QOS_handle_phy_interrupt(struct DWC_ETH_QOS_prv_data *pdata) EMACDBG("Interrupt received for link down with" EMACDBG("Interrupt received for link down with" " auto-negotiation error\n"); " auto-negotiation error\n"); } } } else { DWC_ETH_QOS_mdio_read_direct( pdata, pdata->phyaddr, DWC_ETH_QOS_PHY_INTR_STATUS, &phy_intr_status); EMACDBG("Phy Interrupt status Reg at offset 0x13 = %#x\n", phy_intr_status); /* Interrupt received for link state change */ if (phy_intr_status & LINK_UP_STATE) { pdata->hw_if.stop_mac_tx_rx(); EMACDBG("Interrupt received for link UP state\n"); phy_mac_interrupt(pdata->phydev, LINK_UP); } else if (phy_intr_status & LINK_DOWN_STATE) { EMACDBG("Interrupt received for link DOWN state\n"); phy_mac_interrupt(pdata->phydev, LINK_DOWN); } else if (phy_intr_status & AUTO_NEG_ERROR) { EMACDBG("Interrupt received for link down with" " auto-negotiation error\n"); } else if (phy_intr_status & PHY_WOL) { EMACDBG("Interrupt received for WoL packet\n"); } } EMACDBG("Exit\n"); EMACDBG("Exit\n"); return; return; Loading Loading @@ -2429,6 +2449,7 @@ inline UINT DWC_ETH_QOS_cal_int_mod(struct sk_buff *skb, UINT eth_type, struct DWC_ETH_QOS_prv_data *pdata) struct DWC_ETH_QOS_prv_data *pdata) { { UINT ret = DEFAULT_INT_MOD; UINT ret = DEFAULT_INT_MOD; bool is_udp; #ifdef DWC_ETH_QOS_CONFIG_PTP #ifdef DWC_ETH_QOS_CONFIG_PTP if (eth_type == ETH_P_1588) if (eth_type == ETH_P_1588) Loading @@ -2439,8 +2460,11 @@ inline UINT DWC_ETH_QOS_cal_int_mod(struct sk_buff *skb, UINT eth_type, ret = AVB_INT_MOD; ret = AVB_INT_MOD; } else if (eth_type == ETH_P_IP || eth_type == ETH_P_IPV6) { } else if (eth_type == ETH_P_IP || eth_type == ETH_P_IPV6) { #ifdef DWC_ETH_QOS_CONFIG_PTP #ifdef DWC_ETH_QOS_CONFIG_PTP if (udp_hdr(skb)->dest == htons(PTP_UDP_EV_PORT) is_udp = (eth_type == ETH_P_IP && ip_hdr(skb)->protocol == IPPROTO_UDP) || udp_hdr(skb)->dest == htons(PTP_UDP_GEN_PORT)) { || (eth_type == ETH_P_IPV6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP); if (is_udp && (udp_hdr(skb)->dest == htons(PTP_UDP_EV_PORT) || udp_hdr(skb)->dest == htons(PTP_UDP_GEN_PORT))) { ret = PTP_INT_MOD; ret = PTP_INT_MOD; } else } else #endif #endif Loading Loading @@ -3113,11 +3137,12 @@ static void DWC_ETH_QOS_consume_page_split_hdr( { { if (page2_used) if (page2_used) buffer->page2 = NULL; buffer->page2 = NULL; if (skb != NULL) { skb->len += length; skb->len += length; skb->data_len += length; skb->data_len += length; skb->truesize += length; skb->truesize += length; } } } /* Receive Checksum Offload configuration */ /* Receive Checksum Offload configuration */ static inline void DWC_ETH_QOS_config_rx_csum(struct DWC_ETH_QOS_prv_data *pdata, static inline void DWC_ETH_QOS_config_rx_csum(struct DWC_ETH_QOS_prv_data *pdata, Loading Loading @@ -3224,7 +3249,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( unsigned short payload_len = 0; unsigned short payload_len = 0; unsigned char intermediate_desc_cnt = 0; unsigned char intermediate_desc_cnt = 0; unsigned char buf2_used = 0; unsigned char buf2_used = 0; int ret; int ret = 0; DBGPR("-->DWC_ETH_QOS_clean_split_hdr_rx_irq: qinx = %u, quota = %d\n", DBGPR("-->DWC_ETH_QOS_clean_split_hdr_rx_irq: qinx = %u, quota = %d\n", qinx, quota); qinx, quota); Loading Loading @@ -3323,14 +3348,12 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( } else { } else { /* this is the middle of a chain */ /* this is the middle of a chain */ payload_len = pdata->rx_buffer_len; payload_len = pdata->rx_buffer_len; skb_fill_page_desc(desc_data->skb_top, if (desc_data->skb_top != NULL) skb_shinfo(desc_data->skb_top)->nr_frags, skb_fill_page_desc(desc_data->skb_top,skb_shinfo(desc_data->skb_top)->nr_frags,buffer->page2, 0,payload_len); buffer->page2, 0, payload_len); /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; } } if (desc_data->skb_top != NULL) DWC_ETH_QOS_consume_page_split_hdr(buffer, DWC_ETH_QOS_consume_page_split_hdr(buffer, desc_data->skb_top, desc_data->skb_top, payload_len, buf2_used); payload_len, buf2_used); Loading @@ -3348,16 +3371,14 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( (pdata->rx_buffer_len * intermediate_desc_cnt) - (pdata->rx_buffer_len * intermediate_desc_cnt) - buffer->rx_hdr_size); buffer->rx_hdr_size); } } if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top,skb_shinfo(desc_data->skb_top)->nr_frags,buffer->page2, 0,payload_len); skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, payload_len); /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; skb = desc_data->skb_top; skb = desc_data->skb_top; } desc_data->skb_top = NULL; desc_data->skb_top = NULL; if (skb != NULL) DWC_ETH_QOS_consume_page_split_hdr(buffer, skb, DWC_ETH_QOS_consume_page_split_hdr(buffer, skb, payload_len, buf2_used); payload_len, buf2_used); } else { } else { Loading Loading @@ -3402,11 +3423,13 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( hdr_len = 0; hdr_len = 0; } } if (skb != NULL) { DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); #endif #endif } #ifdef YDEBUG_FILTER #ifdef YDEBUG_FILTER DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); Loading @@ -3415,6 +3438,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { /* get rx tstamp if available */ /* get rx tstamp if available */ if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (skb != NULL ) ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, skb, desc_data, qinx); skb, desc_data, qinx); if (ret == 0) { if (ret == 0) { Loading @@ -3422,6 +3446,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( * time stamp, hence delay the packet reception * time stamp, hence delay the packet reception */ */ buffer->skb = skb; buffer->skb = skb; if (skb != NULL) buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, pdata->rx_buffer_len, DMA_FROM_DEVICE); pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) Loading @@ -3442,8 +3467,10 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( #endif #endif /* update the statistics */ /* update the statistics */ dev->stats.rx_packets++; dev->stats.rx_packets++; if ( skb != NULL) { dev->stats.rx_bytes += skb->len; dev->stats.rx_bytes += skb->len; DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); } received++; received++; next_desc: next_desc: desc_data->dirty_rx++; desc_data->dirty_rx++; Loading Loading @@ -3504,7 +3531,7 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, u16 pkt_len; u16 pkt_len; UCHAR intermediate_desc_cnt = 0; UCHAR intermediate_desc_cnt = 0; unsigned int buf2_used; unsigned int buf2_used; int ret; int ret = 0 ; DBGPR("-->DWC_ETH_QOS_clean_jumbo_rx_irq: qinx = %u, quota = %d\n", DBGPR("-->DWC_ETH_QOS_clean_jumbo_rx_irq: qinx = %u, quota = %d\n", qinx, quota); qinx, quota); Loading Loading @@ -3575,19 +3602,21 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, pdata->rx_buffer_len); pdata->rx_buffer_len); } else { } else { /* this is the middle of a chain */ /* this is the middle of a chain */ if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); DBGPR("RX: pkt in second buffer pointer\n"); DBGPR("RX: pkt in second buffer pointer\n"); skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, buffer->page2, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); } /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; } } if (desc_data->skb_top != NULL ) DWC_ETH_QOS_consume_page(buffer, DWC_ETH_QOS_consume_page(buffer, desc_data->skb_top, desc_data->skb_top, (pdata->rx_buffer_len * 2), (pdata->rx_buffer_len * 2), Loading @@ -3599,18 +3628,20 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, pkt_len = pkt_len = (pkt_len - (pdata->rx_buffer_len * intermediate_desc_cnt)); (pkt_len - (pdata->rx_buffer_len * intermediate_desc_cnt)); if (pkt_len > pdata->rx_buffer_len) { if (pkt_len > pdata->rx_buffer_len) { if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); DBGPR("RX: pkt in second buffer pointer\n"); DBGPR("RX: pkt in second buffer pointer\n"); skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, buffer->page2, 0, (pkt_len - pdata->rx_buffer_len)); (pkt_len - pdata->rx_buffer_len)); } buf2_used = 1; buf2_used = 1; } else { } else { if (desc_data->skb_top != NULL) skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, Loading @@ -3619,8 +3650,10 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, } } /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; if (desc_data->skb_top != NULL) skb = desc_data->skb_top; skb = desc_data->skb_top; desc_data->skb_top = NULL; desc_data->skb_top = NULL; if (skb != NULL) DWC_ETH_QOS_consume_page(buffer, skb, DWC_ETH_QOS_consume_page(buffer, skb, pkt_len, pkt_len, buf2_used); buf2_used); Loading Loading @@ -3671,11 +3704,13 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, intermediate_desc_cnt = 0; intermediate_desc_cnt = 0; } } if (skb != NULL) { DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); #endif #endif } #ifdef YDEBUG_FILTER #ifdef YDEBUG_FILTER DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); Loading @@ -3684,15 +3719,16 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { /* get rx tstamp if available */ /* get rx tstamp if available */ if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, if (skb != NULL) skb, desc_data, qinx); ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, skb, desc_data, qinx); if (ret == 0) { if (ret == 0) { /* device has not yet updated the CONTEXT desc to hold the /* device has not yet updated the CONTEXT desc to hold the * time stamp, hence delay the packet reception * time stamp, hence delay the packet reception */ */ buffer->skb = skb; buffer->skb = skb; buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, if (skb != NULL) pdata->rx_buffer_len, DMA_FROM_DEVICE); buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) dev_alert(&pdata->pdev->dev, "failed to do the RX dma map\n"); dev_alert(&pdata->pdev->dev, "failed to do the RX dma map\n"); Loading @@ -3712,16 +3748,16 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, #endif #endif /* update the statistics */ /* update the statistics */ dev->stats.rx_packets++; dev->stats.rx_packets++; if (skb != NULL) { dev->stats.rx_bytes += skb->len; dev->stats.rx_bytes += skb->len; /* eth type trans needs skb->data to point to something */ /* eth type trans needs skb->data to point to something */ if (!pskb_may_pull(skb, ETH_HLEN)) { if (!pskb_may_pull(skb, ETH_HLEN)) { dev_alert(&pdata->pdev->dev, "pskb_may_pull failed\n"); dev_alert(&pdata->pdev->dev, "pskb_may_pull failed\n"); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); goto next_desc; goto next_desc; } } DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); } received++; received++; next_desc: next_desc: desc_data->dirty_rx++; desc_data->dirty_rx++; Loading Loading @@ -4922,52 +4958,14 @@ static VOID DWC_ETH_QOS_config_timer_registers( { { struct timespec now; struct timespec now; struct hw_if_struct *hw_if = &pdata->hw_if; struct hw_if_struct *hw_if = &pdata->hw_if; u64 temp; DBGPR("-->DWC_ETH_QOS_config_timer_registers\n"); DBGPR("-->DWC_ETH_QOS_config_timer_registers\n"); pdata->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; /* program default addend */ hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* program Sub Second Increment Reg */ /* program Sub Second Increment Reg */ #ifdef CONFIG_PPS_OUTPUT hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* If default_addend is already programmed, then we expect that * sub_second_increment is also programmed already */ if(pdata->default_addend == 0){ hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); // Using default 250MHz } else { u64 pclk; pclk = (u64) (pdata->default_addend) * DWC_ETH_QOS_SYSCLOCK; pclk += 0x8000000; pclk >>= 32; hw_if->config_sub_second_increment((u32)pclk); } #else hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); #endif /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) */ #ifdef CONFIG_PPS_OUTPUT if(pdata->default_addend == 0){ temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); EMACDBG("Using default PTP clock = 250MHz\n"); } #else temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); #endif hw_if->config_addend(pdata->default_addend); /* initialize system time */ /* initialize system time */ getnstimeofday(&now); getnstimeofday(&now); hw_if->init_systime(now.tv_sec, now.tv_nsec); hw_if->init_systime(now.tv_sec, now.tv_nsec); Loading Loading @@ -5105,7 +5103,6 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct hw_if_struct *hw_if = &pdata->hw_if; struct hw_if_struct *hw_if = &pdata->hw_if; int ret = 0; int ret = 0; u64 val; if ((eth_pps_cfg->ppsout_ch < 0) || if ((eth_pps_cfg->ppsout_ch < 0) || (eth_pps_cfg->ppsout_ch >= pdata->hw_feat.pps_out_num)) (eth_pps_cfg->ppsout_ch >= pdata->hw_feat.pps_out_num)) Loading @@ -5119,17 +5116,9 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data eth_pps_cfg->ptpclk_freq ); eth_pps_cfg->ptpclk_freq ); return -1; return -1; } } pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; val = (u64)(1ULL << 32); ret = hw_if->config_default_addend(pdata, (ULONG)eth_pps_cfg->ptpclk_freq); val = val * (eth_pps_cfg->ptpclk_freq); val += (DWC_ETH_QOS_SYSCLOCK/2); val = div_u64(val, DWC_ETH_QOS_SYSCLOCK); if ( val > 0xFFFFFFFF) val = 0xFFFFFFFF; EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n", eth_pps_cfg->ptpclk_freq, (unsigned int)val); pdata->default_addend = val; ret = hw_if->config_addend((unsigned int)val); ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq); ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq); return ret; return ret; Loading Loading @@ -5212,15 +5201,8 @@ void DWC_ETH_QOS_pps_timer_init(struct ifr_data_struct *req) /* Enable timestamping. This is required to start system time generator.*/ /* Enable timestamping. This is required to start system time generator.*/ MAC_TCR_TSENA_UDFWR(0x1); MAC_TCR_TSENA_UDFWR(0x1); /* Configure MAC Sub-second and Sub-nanosecond increment register based on PTP clock. */ MAC_SSIR_SSINC_UDFWR(0x4); // Sub-second increment value for 250MHz and 230.4MHz ptp clock MAC_SSIR_SNSINC_UDFWR(0x0); // Sub-nanosecond increment value for 250 MHz ptp clock EMACDBG("250 clock\n"); MAC_TCR_TSUPDT_UDFWR(0x1); MAC_TCR_TSUPDT_UDFWR(0x1); MAC_TCR_TSCFUPDT_UDFWR(0x0); // Coarse Timestamp Update method. MAC_TCR_TSCFUPDT_UDFWR(0x1); // Fine Timestamp Update method. /* Initialize MAC System Time Update register */ /* Initialize MAC System Time Update register */ MAC_STSUR_TSS_UDFWR(0x0); // MAC system time in seconds MAC_STSUR_TSS_UDFWR(0x0); // MAC system time in seconds Loading Loading @@ -5279,12 +5261,16 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; unsigned int val; unsigned int val; int interval, width; int interval, width; int interval_ns; /*interval in nano seconds*/ struct hw_if_struct *hw_if = &pdata->hw_if; if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1 && /* For lpass we need 19.2Mhz PPS frequency for PPS0. eth_pps_cfg->ptpclk_freq <= 0) { If lpass is enabled don't allow to change the PTP clock /* Set PTP clock to default 250 */ becuase if we change PTP clock then addend & subsecond increament will change & We will not see 19.2Mhz for PPS0. */ if (pdata->res_data->pps_lpass_conn_en ) { eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; EMACDBG("using default ptp clock \n"); } } if ((eth_pps_cfg->ppsout_ch < 0) || if ((eth_pps_cfg->ppsout_ch < 0) || Loading @@ -5303,6 +5289,12 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct eth_pps_cfg->ppsout_duty = 99; eth_pps_cfg->ppsout_duty = 99; } } /* Configure increment values */ hw_if->config_sub_second_increment(eth_pps_cfg->ptpclk_freq); /* Configure addent value as Fine Timestamp method is used */ hw_if->config_default_addend(pdata, eth_pps_cfg->ptpclk_freq); if(0 < eth_pps_cfg->ptpclk_freq) { if(0 < eth_pps_cfg->ptpclk_freq) { pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; interval = (eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq/2) interval = (eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq/2) Loading @@ -5323,17 +5315,9 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct EMACDBG("PPS: PPSOut_Config: interval=%d, width=%d\n", interval, width); EMACDBG("PPS: PPSOut_Config: interval=%d, width=%d\n", interval, width); if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) { //calculate interval & width interval_ns = (1000000000/eth_pps_cfg->ppsout_freq) ; interval = ((interval_ns)/4) - 1; width = ((interval_ns)/(2*4)) - 1; EMACDBG("pps_interval=%d,width=%d\n",interval,width); } switch (eth_pps_cfg->ppsout_ch) { switch (eth_pps_cfg->ppsout_ch) { case DWC_ETH_QOS_PPS_CH_0: case DWC_ETH_QOS_PPS_CH_0: if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) { if (pdata->res_data->pps_lpass_conn_en) { if (eth_pps_cfg->ppsout_start == DWC_ETH_QOS_PPS_START) { if (eth_pps_cfg->ppsout_start == DWC_ETH_QOS_PPS_START) { MAC_PPSC_PPSEN0_UDFWR(0x1); MAC_PPSC_PPSEN0_UDFWR(0x1); MAC_PPS_INTVAL_PPSINT0_UDFWR(DWC_ETH_QOS_PPS_CH_0, interval); MAC_PPS_INTVAL_PPSINT0_UDFWR(DWC_ETH_QOS_PPS_CH_0, interval); Loading Loading @@ -5885,7 +5869,6 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata, u32 ts_event_en = 0; u32 ts_event_en = 0; u32 av_8021asm_en = 0; u32 av_8021asm_en = 0; u32 VARMAC_TCR = 0; u32 VARMAC_TCR = 0; u64 temp = 0; struct timespec now; struct timespec now; DBGPR_PTP("-->DWC_ETH_QOS_handle_hwtstamp_ioctl\n"); DBGPR_PTP("-->DWC_ETH_QOS_handle_hwtstamp_ioctl\n"); Loading Loading @@ -6056,46 +6039,11 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata, hw_if->config_hw_time_stamping(VARMAC_TCR); hw_if->config_hw_time_stamping(VARMAC_TCR); /* program default addend */ hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* program Sub Second Increment Reg */ /* program Sub Second Increment Reg */ #ifdef CONFIG_PPS_OUTPUT hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* If default_addend is already programmed, then we expect that * sub_second_increment is also programmed already */ if (pdata->default_addend == 0) { hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); // Using default 250MHz } else { u64 pclk; pclk = (u64) (pdata->default_addend) * DWC_ETH_QOS_SYSCLOCK; pclk += 0x8000000; pclk >>= 32; hw_if->config_sub_second_increment((u32)pclk); } #else hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); #endif /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) * */ #ifdef CONFIG_PPS_OUTPUT if(pdata->default_addend == 0){ temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); EMACINFO("Using default PTP clock = 250MHz\n"); #else temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); #endif hw_if->config_addend(pdata->default_addend); /* initialize system time */ /* initialize system time */ getnstimeofday(&now); getnstimeofday(&now); Loading drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c +3 −3 Original line number Original line Diff line number Diff line Loading @@ -525,7 +525,7 @@ static int DWC_ETH_QOS_ipa_offload_resume(struct DWC_ETH_QOS_prv_data *pdata) static int DWC_ETH_QOS_ipa_ready(struct DWC_ETH_QOS_prv_data *pdata) static int DWC_ETH_QOS_ipa_ready(struct DWC_ETH_QOS_prv_data *pdata) { { int ret; int ret = 0 ; EMACDBG("Enter \n"); EMACDBG("Enter \n"); Loading Loading @@ -960,8 +960,8 @@ static int DWC_ETH_QOS_ipa_offload_connect(struct DWC_ETH_QOS_prv_data *pdata) struct DWC_ETH_QOS_prv_ipa_data *ntn_ipa = &pdata->prv_ipa; struct DWC_ETH_QOS_prv_ipa_data *ntn_ipa = &pdata->prv_ipa; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_out_params out; struct ipa_uc_offload_conn_out_params out; struct ipa_ntn_setup_info rx_setup_info; struct ipa_ntn_setup_info rx_setup_info = {0}; struct ipa_ntn_setup_info tx_setup_info; struct ipa_ntn_setup_info tx_setup_info = {0}; struct ipa_perf_profile profile; struct ipa_perf_profile profile; int ret = 0; int ret = 0; int i = 0; int i = 0; Loading Loading
drivers/emac-dwc-eqos/Android.mk +9 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,15 @@ KBUILD_OPTIONS += DCONFIG_DEBUGFS_OBJ=1 LOCAL_MODULE := emac_dwc_eqos.ko LOCAL_MODULE := emac_dwc_eqos.ko LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional include $(DLKM_DIR)/AndroidKernelModule.mk include $(DLKM_DIR)/AndroidKernelModule.mk include $(CLEAR_VARS) LOCAL_MODULE := emac_perf_settings.sh LOCAL_MODULE_TAGS := optional LOCAL_MODULE_CLASS := ETC LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/emac LOCAL_SRC_FILES := emac_perf_settings.sh include $(BUILD_PREBUILT) endif endif endif endif Loading
drivers/emac-dwc-eqos/DWC_ETH_QOS_desc.c +2 −2 Original line number Original line Diff line number Diff line Loading @@ -1440,7 +1440,7 @@ static int DWC_ETH_QOS_map_page_buffs(struct DWC_ETH_QOS_prv_data *pdata, DBGPR("-->DWC_ETH_QOS_map_page_buffs\n"); DBGPR("-->DWC_ETH_QOS_map_page_buffs\n"); if (size > DWC_ETH_QOS_MAX_DATA_PER_TX_BUF) { if (size > DWC_ETH_QOS_MAX_DATA_PER_TX_BUF) { if (!prev_buffer->dma2) { if (prev_buffer && !prev_buffer->dma2) { DBGPR("prev_buffer->dma2 is empty\n"); DBGPR("prev_buffer->dma2 is empty\n"); /* fill the first buffer pointer in pre_buffer->dma2 */ /* fill the first buffer pointer in pre_buffer->dma2 */ prev_buffer->dma2 = prev_buffer->dma2 = Loading Loading @@ -1505,7 +1505,7 @@ static int DWC_ETH_QOS_map_page_buffs(struct DWC_ETH_QOS_prv_data *pdata, buffer->buf2_mapped_as_page = Y_TRUE; buffer->buf2_mapped_as_page = Y_TRUE; } } } else { } else { if (!prev_buffer->dma2) { if (prev_buffer && !prev_buffer->dma2) { DBGPR("prev_buffer->dma2 is empty\n"); DBGPR("prev_buffer->dma2 is empty\n"); /* fill the first buffer pointer in pre_buffer->dma2 */ /* fill the first buffer pointer in pre_buffer->dma2 */ prev_buffer->dma2 = dma_map_page(GET_MEM_PDEV_DEV, prev_buffer->dma2 = dma_map_page(GET_MEM_PDEV_DEV, Loading
drivers/emac-dwc-eqos/DWC_ETH_QOS_dev.c +57 −16 Original line number Original line Diff line number Diff line Loading @@ -1136,8 +1136,9 @@ static INT drop_tx_status_enabled(void) static INT config_sub_second_increment(ULONG ptp_clock) static INT config_sub_second_increment(ULONG ptp_clock) { { ULONG val; ULONG VARMAC_TCR; ULONG VARMAC_TCR; double ss_inc = 0; double sns_inc = 0; MAC_TCR_RGRD(VARMAC_TCR); MAC_TCR_RGRD(VARMAC_TCR); Loading @@ -1145,30 +1146,69 @@ static INT config_sub_second_increment(ULONG ptp_clock) /* formula is : ((1/ptp_clock) * 1000000000) */ /* formula is : ((1/ptp_clock) * 1000000000) */ /* where, ptp_clock = 50MHz if FINE correction */ /* where, ptp_clock = 50MHz if FINE correction */ /* and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */ /* and ptp_clock = DWC_ETH_QOS_SYSCLOCK if COARSE correction */ #ifdef CONFIG_PPS_OUTPUT if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { EMACDBG("Using PTP clock %ld MHz\n", ptp_clock); EMACDBG("Using PTP clock %ld MHz\n", ptp_clock); val = ((1 * 1000000000ull) / ptp_clock); ss_inc = (double)1000000000.0 / (double)ptp_clock; } } else { else { EMACDBG("Using SYSCLOCK for coarse correction\n"); EMACDBG("Using SYSCLOCK for coarse correction\n"); val = ((1 * 1000000000ull) / DWC_ETH_QOS_SYSCLOCK ); ss_inc = (double)1000000000.0 / (double)DWC_ETH_QOS_SYSCLOCK; } } #else if (GET_VALUE(VARMAC_TCR, MAC_TCR_TSCFUPDT_LPOS, MAC_TCR_TSCFUPDT_HPOS) == 1) { /* 0.465ns accuracy */ val = ((1 * 1000000000ull) / 50000000); } else { val = ((1 * 1000000000ull) / ptp_clock); } #endif /* 0.465ns accurecy */ if (GET_VALUE( if (GET_VALUE( VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS, VARMAC_TCR, MAC_TCR_TSCTRLSSR_LPOS, MAC_TCR_TSCTRLSSR_HPOS) == 0) MAC_TCR_TSCTRLSSR_HPOS) == 0) { val = (val * 1000) / 465; EMACDBG("using 0.465 ns accuracy"); ss_inc /= 0.465; } sns_inc = ss_inc - (int)ss_inc; // take remainder sns_inc *= 256.0; // sns_inc needs to be multiplied by 2^8, per spec. sns_inc += 0.5; // round to nearest int value. MAC_SSIR_SSINC_UDFWR(val); MAC_SSIR_SSINC_UDFWR((int)ss_inc); MAC_SSIR_SNSINC_UDFWR((int)sns_inc); EMACDBG("ss_inc = %d, sns_inc = %d\n", (int)ss_inc, (int)sns_inc); return Y_SUCCESS; } /*! * \brief * \param[in] * \return Success or Failure * \retval 0 Success * \retval -1 Failure */ static INT config_default_addend(struct DWC_ETH_QOS_prv_data *pdata, ULONG ptp_clock) { struct hw_if_struct *hw_if = &pdata->hw_if; u64 temp; /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) */ if (ptp_clock == DWC_ETH_QOS_SYSCLOCK) { // If PTP_CLOCK == SYS_CLOCK, best we can do is 2^32 - 1 pdata->default_addend = 0xFFFFFFFF; } else { temp = (u64)((u64)ptp_clock << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); } hw_if->config_addend(pdata->default_addend); EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n", ptp_clock, (unsigned int)pdata->default_addend); return Y_SUCCESS; return Y_SUCCESS; } } Loading Loading @@ -5114,6 +5154,7 @@ void DWC_ETH_QOS_init_function_ptrs_dev(struct hw_if_struct *hw_if) /* for hw time stamping */ /* for hw time stamping */ hw_if->config_hw_time_stamping = config_hw_time_stamping; hw_if->config_hw_time_stamping = config_hw_time_stamping; hw_if->config_sub_second_increment = config_sub_second_increment; hw_if->config_sub_second_increment = config_sub_second_increment; hw_if->config_default_addend = config_default_addend; hw_if->init_systime = init_systime; hw_if->init_systime = init_systime; hw_if->config_addend = config_addend; hw_if->config_addend = config_addend; hw_if->adjust_systime = adjust_systime; hw_if->adjust_systime = adjust_systime; Loading
drivers/emac-dwc-eqos/DWC_ETH_QOS_drv.c +142 −194 Original line number Original line Diff line number Diff line Loading @@ -784,6 +784,7 @@ void DWC_ETH_QOS_handle_phy_interrupt(struct DWC_ETH_QOS_prv_data *pdata) int micrel_intr_status = 0; int micrel_intr_status = 0; EMACDBG("Enter\n"); EMACDBG("Enter\n"); if ((pdata->phydev->phy_id & pdata->phydev->drv->phy_id_mask) == MICREL_PHY_ID) { DWC_ETH_QOS_mdio_read_direct( DWC_ETH_QOS_mdio_read_direct( pdata, pdata->phyaddr, DWC_ETH_QOS_BASIC_STATUS, &phy_intr_status); pdata, pdata->phyaddr, DWC_ETH_QOS_BASIC_STATUS, &phy_intr_status); EMACDBG( EMACDBG( Loading @@ -809,6 +810,25 @@ void DWC_ETH_QOS_handle_phy_interrupt(struct DWC_ETH_QOS_prv_data *pdata) EMACDBG("Interrupt received for link down with" EMACDBG("Interrupt received for link down with" " auto-negotiation error\n"); " auto-negotiation error\n"); } } } else { DWC_ETH_QOS_mdio_read_direct( pdata, pdata->phyaddr, DWC_ETH_QOS_PHY_INTR_STATUS, &phy_intr_status); EMACDBG("Phy Interrupt status Reg at offset 0x13 = %#x\n", phy_intr_status); /* Interrupt received for link state change */ if (phy_intr_status & LINK_UP_STATE) { pdata->hw_if.stop_mac_tx_rx(); EMACDBG("Interrupt received for link UP state\n"); phy_mac_interrupt(pdata->phydev, LINK_UP); } else if (phy_intr_status & LINK_DOWN_STATE) { EMACDBG("Interrupt received for link DOWN state\n"); phy_mac_interrupt(pdata->phydev, LINK_DOWN); } else if (phy_intr_status & AUTO_NEG_ERROR) { EMACDBG("Interrupt received for link down with" " auto-negotiation error\n"); } else if (phy_intr_status & PHY_WOL) { EMACDBG("Interrupt received for WoL packet\n"); } } EMACDBG("Exit\n"); EMACDBG("Exit\n"); return; return; Loading Loading @@ -2429,6 +2449,7 @@ inline UINT DWC_ETH_QOS_cal_int_mod(struct sk_buff *skb, UINT eth_type, struct DWC_ETH_QOS_prv_data *pdata) struct DWC_ETH_QOS_prv_data *pdata) { { UINT ret = DEFAULT_INT_MOD; UINT ret = DEFAULT_INT_MOD; bool is_udp; #ifdef DWC_ETH_QOS_CONFIG_PTP #ifdef DWC_ETH_QOS_CONFIG_PTP if (eth_type == ETH_P_1588) if (eth_type == ETH_P_1588) Loading @@ -2439,8 +2460,11 @@ inline UINT DWC_ETH_QOS_cal_int_mod(struct sk_buff *skb, UINT eth_type, ret = AVB_INT_MOD; ret = AVB_INT_MOD; } else if (eth_type == ETH_P_IP || eth_type == ETH_P_IPV6) { } else if (eth_type == ETH_P_IP || eth_type == ETH_P_IPV6) { #ifdef DWC_ETH_QOS_CONFIG_PTP #ifdef DWC_ETH_QOS_CONFIG_PTP if (udp_hdr(skb)->dest == htons(PTP_UDP_EV_PORT) is_udp = (eth_type == ETH_P_IP && ip_hdr(skb)->protocol == IPPROTO_UDP) || udp_hdr(skb)->dest == htons(PTP_UDP_GEN_PORT)) { || (eth_type == ETH_P_IPV6 && ipv6_hdr(skb)->nexthdr == IPPROTO_UDP); if (is_udp && (udp_hdr(skb)->dest == htons(PTP_UDP_EV_PORT) || udp_hdr(skb)->dest == htons(PTP_UDP_GEN_PORT))) { ret = PTP_INT_MOD; ret = PTP_INT_MOD; } else } else #endif #endif Loading Loading @@ -3113,11 +3137,12 @@ static void DWC_ETH_QOS_consume_page_split_hdr( { { if (page2_used) if (page2_used) buffer->page2 = NULL; buffer->page2 = NULL; if (skb != NULL) { skb->len += length; skb->len += length; skb->data_len += length; skb->data_len += length; skb->truesize += length; skb->truesize += length; } } } /* Receive Checksum Offload configuration */ /* Receive Checksum Offload configuration */ static inline void DWC_ETH_QOS_config_rx_csum(struct DWC_ETH_QOS_prv_data *pdata, static inline void DWC_ETH_QOS_config_rx_csum(struct DWC_ETH_QOS_prv_data *pdata, Loading Loading @@ -3224,7 +3249,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( unsigned short payload_len = 0; unsigned short payload_len = 0; unsigned char intermediate_desc_cnt = 0; unsigned char intermediate_desc_cnt = 0; unsigned char buf2_used = 0; unsigned char buf2_used = 0; int ret; int ret = 0; DBGPR("-->DWC_ETH_QOS_clean_split_hdr_rx_irq: qinx = %u, quota = %d\n", DBGPR("-->DWC_ETH_QOS_clean_split_hdr_rx_irq: qinx = %u, quota = %d\n", qinx, quota); qinx, quota); Loading Loading @@ -3323,14 +3348,12 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( } else { } else { /* this is the middle of a chain */ /* this is the middle of a chain */ payload_len = pdata->rx_buffer_len; payload_len = pdata->rx_buffer_len; skb_fill_page_desc(desc_data->skb_top, if (desc_data->skb_top != NULL) skb_shinfo(desc_data->skb_top)->nr_frags, skb_fill_page_desc(desc_data->skb_top,skb_shinfo(desc_data->skb_top)->nr_frags,buffer->page2, 0,payload_len); buffer->page2, 0, payload_len); /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; } } if (desc_data->skb_top != NULL) DWC_ETH_QOS_consume_page_split_hdr(buffer, DWC_ETH_QOS_consume_page_split_hdr(buffer, desc_data->skb_top, desc_data->skb_top, payload_len, buf2_used); payload_len, buf2_used); Loading @@ -3348,16 +3371,14 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( (pdata->rx_buffer_len * intermediate_desc_cnt) - (pdata->rx_buffer_len * intermediate_desc_cnt) - buffer->rx_hdr_size); buffer->rx_hdr_size); } } if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top,skb_shinfo(desc_data->skb_top)->nr_frags,buffer->page2, 0,payload_len); skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, payload_len); /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; skb = desc_data->skb_top; skb = desc_data->skb_top; } desc_data->skb_top = NULL; desc_data->skb_top = NULL; if (skb != NULL) DWC_ETH_QOS_consume_page_split_hdr(buffer, skb, DWC_ETH_QOS_consume_page_split_hdr(buffer, skb, payload_len, buf2_used); payload_len, buf2_used); } else { } else { Loading Loading @@ -3402,11 +3423,13 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( hdr_len = 0; hdr_len = 0; } } if (skb != NULL) { DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); #endif #endif } #ifdef YDEBUG_FILTER #ifdef YDEBUG_FILTER DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); Loading @@ -3415,6 +3438,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { /* get rx tstamp if available */ /* get rx tstamp if available */ if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (skb != NULL ) ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, skb, desc_data, qinx); skb, desc_data, qinx); if (ret == 0) { if (ret == 0) { Loading @@ -3422,6 +3446,7 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( * time stamp, hence delay the packet reception * time stamp, hence delay the packet reception */ */ buffer->skb = skb; buffer->skb = skb; if (skb != NULL) buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, pdata->rx_buffer_len, DMA_FROM_DEVICE); pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) Loading @@ -3442,8 +3467,10 @@ static int DWC_ETH_QOS_clean_split_hdr_rx_irq( #endif #endif /* update the statistics */ /* update the statistics */ dev->stats.rx_packets++; dev->stats.rx_packets++; if ( skb != NULL) { dev->stats.rx_bytes += skb->len; dev->stats.rx_bytes += skb->len; DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); } received++; received++; next_desc: next_desc: desc_data->dirty_rx++; desc_data->dirty_rx++; Loading Loading @@ -3504,7 +3531,7 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, u16 pkt_len; u16 pkt_len; UCHAR intermediate_desc_cnt = 0; UCHAR intermediate_desc_cnt = 0; unsigned int buf2_used; unsigned int buf2_used; int ret; int ret = 0 ; DBGPR("-->DWC_ETH_QOS_clean_jumbo_rx_irq: qinx = %u, quota = %d\n", DBGPR("-->DWC_ETH_QOS_clean_jumbo_rx_irq: qinx = %u, quota = %d\n", qinx, quota); qinx, quota); Loading Loading @@ -3575,19 +3602,21 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, pdata->rx_buffer_len); pdata->rx_buffer_len); } else { } else { /* this is the middle of a chain */ /* this is the middle of a chain */ if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); DBGPR("RX: pkt in second buffer pointer\n"); DBGPR("RX: pkt in second buffer pointer\n"); skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, buffer->page2, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); } /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; } } if (desc_data->skb_top != NULL ) DWC_ETH_QOS_consume_page(buffer, DWC_ETH_QOS_consume_page(buffer, desc_data->skb_top, desc_data->skb_top, (pdata->rx_buffer_len * 2), (pdata->rx_buffer_len * 2), Loading @@ -3599,18 +3628,20 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, pkt_len = pkt_len = (pkt_len - (pdata->rx_buffer_len * intermediate_desc_cnt)); (pkt_len - (pdata->rx_buffer_len * intermediate_desc_cnt)); if (pkt_len > pdata->rx_buffer_len) { if (pkt_len > pdata->rx_buffer_len) { if (desc_data->skb_top != NULL) { skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, pdata->rx_buffer_len); pdata->rx_buffer_len); DBGPR("RX: pkt in second buffer pointer\n"); DBGPR("RX: pkt in second buffer pointer\n"); skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page2, 0, buffer->page2, 0, (pkt_len - pdata->rx_buffer_len)); (pkt_len - pdata->rx_buffer_len)); } buf2_used = 1; buf2_used = 1; } else { } else { if (desc_data->skb_top != NULL) skb_fill_page_desc(desc_data->skb_top, skb_fill_page_desc(desc_data->skb_top, skb_shinfo(desc_data->skb_top)->nr_frags, skb_shinfo(desc_data->skb_top)->nr_frags, buffer->page, 0, buffer->page, 0, Loading @@ -3619,8 +3650,10 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, } } /* re-use this skb, as consumed only the page */ /* re-use this skb, as consumed only the page */ buffer->skb = skb; buffer->skb = skb; if (desc_data->skb_top != NULL) skb = desc_data->skb_top; skb = desc_data->skb_top; desc_data->skb_top = NULL; desc_data->skb_top = NULL; if (skb != NULL) DWC_ETH_QOS_consume_page(buffer, skb, DWC_ETH_QOS_consume_page(buffer, skb, pkt_len, pkt_len, buf2_used); buf2_used); Loading Loading @@ -3671,11 +3704,13 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, intermediate_desc_cnt = 0; intermediate_desc_cnt = 0; } } if (skb != NULL) { DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_config_rx_csum(pdata, skb, RX_NORMAL_DESC); #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG #ifdef DWC_ETH_QOS_ENABLE_VLAN_TAG DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); DWC_ETH_QOS_get_rx_vlan(pdata, skb, RX_NORMAL_DESC); #endif #endif } #ifdef YDEBUG_FILTER #ifdef YDEBUG_FILTER DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); DWC_ETH_QOS_check_rx_filter_status(RX_NORMAL_DESC); Loading @@ -3684,15 +3719,16 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { if ((pdata->hw_feat.tsstssel) && (pdata->hwts_rx_en)) { /* get rx tstamp if available */ /* get rx tstamp if available */ if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { if (hw_if->rx_tstamp_available(RX_NORMAL_DESC)) { ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, if (skb != NULL) skb, desc_data, qinx); ret = DWC_ETH_QOS_get_rx_hwtstamp(pdata, skb, desc_data, qinx); if (ret == 0) { if (ret == 0) { /* device has not yet updated the CONTEXT desc to hold the /* device has not yet updated the CONTEXT desc to hold the * time stamp, hence delay the packet reception * time stamp, hence delay the packet reception */ */ buffer->skb = skb; buffer->skb = skb; buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, if (skb != NULL) pdata->rx_buffer_len, DMA_FROM_DEVICE); buffer->dma = dma_map_single(GET_MEM_PDEV_DEV, skb->data, pdata->rx_buffer_len, DMA_FROM_DEVICE); if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) if (dma_mapping_error(GET_MEM_PDEV_DEV, buffer->dma)) dev_alert(&pdata->pdev->dev, "failed to do the RX dma map\n"); dev_alert(&pdata->pdev->dev, "failed to do the RX dma map\n"); Loading @@ -3712,16 +3748,16 @@ static int DWC_ETH_QOS_clean_jumbo_rx_irq(struct DWC_ETH_QOS_prv_data *pdata, #endif #endif /* update the statistics */ /* update the statistics */ dev->stats.rx_packets++; dev->stats.rx_packets++; if (skb != NULL) { dev->stats.rx_bytes += skb->len; dev->stats.rx_bytes += skb->len; /* eth type trans needs skb->data to point to something */ /* eth type trans needs skb->data to point to something */ if (!pskb_may_pull(skb, ETH_HLEN)) { if (!pskb_may_pull(skb, ETH_HLEN)) { dev_alert(&pdata->pdev->dev, "pskb_may_pull failed\n"); dev_alert(&pdata->pdev->dev, "pskb_may_pull failed\n"); dev_kfree_skb_any(skb); dev_kfree_skb_any(skb); goto next_desc; goto next_desc; } } DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); DWC_ETH_QOS_receive_skb(pdata, dev, skb, qinx); } received++; received++; next_desc: next_desc: desc_data->dirty_rx++; desc_data->dirty_rx++; Loading Loading @@ -4922,52 +4958,14 @@ static VOID DWC_ETH_QOS_config_timer_registers( { { struct timespec now; struct timespec now; struct hw_if_struct *hw_if = &pdata->hw_if; struct hw_if_struct *hw_if = &pdata->hw_if; u64 temp; DBGPR("-->DWC_ETH_QOS_config_timer_registers\n"); DBGPR("-->DWC_ETH_QOS_config_timer_registers\n"); pdata->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; /* program default addend */ hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* program Sub Second Increment Reg */ /* program Sub Second Increment Reg */ #ifdef CONFIG_PPS_OUTPUT hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* If default_addend is already programmed, then we expect that * sub_second_increment is also programmed already */ if(pdata->default_addend == 0){ hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); // Using default 250MHz } else { u64 pclk; pclk = (u64) (pdata->default_addend) * DWC_ETH_QOS_SYSCLOCK; pclk += 0x8000000; pclk >>= 32; hw_if->config_sub_second_increment((u32)pclk); } #else hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); #endif /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) */ #ifdef CONFIG_PPS_OUTPUT if(pdata->default_addend == 0){ temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); EMACDBG("Using default PTP clock = 250MHz\n"); } #else temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); #endif hw_if->config_addend(pdata->default_addend); /* initialize system time */ /* initialize system time */ getnstimeofday(&now); getnstimeofday(&now); hw_if->init_systime(now.tv_sec, now.tv_nsec); hw_if->init_systime(now.tv_sec, now.tv_nsec); Loading Loading @@ -5105,7 +5103,6 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct hw_if_struct *hw_if = &pdata->hw_if; struct hw_if_struct *hw_if = &pdata->hw_if; int ret = 0; int ret = 0; u64 val; if ((eth_pps_cfg->ppsout_ch < 0) || if ((eth_pps_cfg->ppsout_ch < 0) || (eth_pps_cfg->ppsout_ch >= pdata->hw_feat.pps_out_num)) (eth_pps_cfg->ppsout_ch >= pdata->hw_feat.pps_out_num)) Loading @@ -5119,17 +5116,9 @@ static int ETH_PTPCLK_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data eth_pps_cfg->ptpclk_freq ); eth_pps_cfg->ptpclk_freq ); return -1; return -1; } } pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; val = (u64)(1ULL << 32); ret = hw_if->config_default_addend(pdata, (ULONG)eth_pps_cfg->ptpclk_freq); val = val * (eth_pps_cfg->ptpclk_freq); val += (DWC_ETH_QOS_SYSCLOCK/2); val = div_u64(val, DWC_ETH_QOS_SYSCLOCK); if ( val > 0xFFFFFFFF) val = 0xFFFFFFFF; EMACDBG("PPS: PTPCLK_Config: freq=%dHz, addend_reg=0x%x\n", eth_pps_cfg->ptpclk_freq, (unsigned int)val); pdata->default_addend = val; ret = hw_if->config_addend((unsigned int)val); ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq); ret |= hw_if->config_sub_second_increment( (ULONG)eth_pps_cfg->ptpclk_freq); return ret; return ret; Loading Loading @@ -5212,15 +5201,8 @@ void DWC_ETH_QOS_pps_timer_init(struct ifr_data_struct *req) /* Enable timestamping. This is required to start system time generator.*/ /* Enable timestamping. This is required to start system time generator.*/ MAC_TCR_TSENA_UDFWR(0x1); MAC_TCR_TSENA_UDFWR(0x1); /* Configure MAC Sub-second and Sub-nanosecond increment register based on PTP clock. */ MAC_SSIR_SSINC_UDFWR(0x4); // Sub-second increment value for 250MHz and 230.4MHz ptp clock MAC_SSIR_SNSINC_UDFWR(0x0); // Sub-nanosecond increment value for 250 MHz ptp clock EMACDBG("250 clock\n"); MAC_TCR_TSUPDT_UDFWR(0x1); MAC_TCR_TSUPDT_UDFWR(0x1); MAC_TCR_TSCFUPDT_UDFWR(0x0); // Coarse Timestamp Update method. MAC_TCR_TSCFUPDT_UDFWR(0x1); // Fine Timestamp Update method. /* Initialize MAC System Time Update register */ /* Initialize MAC System Time Update register */ MAC_STSUR_TSS_UDFWR(0x0); // MAC system time in seconds MAC_STSUR_TSS_UDFWR(0x0); // MAC system time in seconds Loading Loading @@ -5279,12 +5261,16 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; struct ETH_PPS_Config *eth_pps_cfg = (struct ETH_PPS_Config *)req->ptr; unsigned int val; unsigned int val; int interval, width; int interval, width; int interval_ns; /*interval in nano seconds*/ struct hw_if_struct *hw_if = &pdata->hw_if; if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1 && /* For lpass we need 19.2Mhz PPS frequency for PPS0. eth_pps_cfg->ptpclk_freq <= 0) { If lpass is enabled don't allow to change the PTP clock /* Set PTP clock to default 250 */ becuase if we change PTP clock then addend & subsecond increament will change & We will not see 19.2Mhz for PPS0. */ if (pdata->res_data->pps_lpass_conn_en ) { eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; eth_pps_cfg->ptpclk_freq = DWC_ETH_QOS_DEFAULT_PTP_CLOCK; EMACDBG("using default ptp clock \n"); } } if ((eth_pps_cfg->ppsout_ch < 0) || if ((eth_pps_cfg->ppsout_ch < 0) || Loading @@ -5303,6 +5289,12 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct eth_pps_cfg->ppsout_duty = 99; eth_pps_cfg->ppsout_duty = 99; } } /* Configure increment values */ hw_if->config_sub_second_increment(eth_pps_cfg->ptpclk_freq); /* Configure addent value as Fine Timestamp method is used */ hw_if->config_default_addend(pdata, eth_pps_cfg->ptpclk_freq); if(0 < eth_pps_cfg->ptpclk_freq) { if(0 < eth_pps_cfg->ptpclk_freq) { pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; pdata->ptpclk_freq = eth_pps_cfg->ptpclk_freq; interval = (eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq/2) interval = (eth_pps_cfg->ptpclk_freq + eth_pps_cfg->ppsout_freq/2) Loading @@ -5323,17 +5315,9 @@ int ETH_PPSOUT_Config(struct DWC_ETH_QOS_prv_data *pdata, struct ifr_data_struct EMACDBG("PPS: PPSOut_Config: interval=%d, width=%d\n", interval, width); EMACDBG("PPS: PPSOut_Config: interval=%d, width=%d\n", interval, width); if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) { //calculate interval & width interval_ns = (1000000000/eth_pps_cfg->ppsout_freq) ; interval = ((interval_ns)/4) - 1; width = ((interval_ns)/(2*4)) - 1; EMACDBG("pps_interval=%d,width=%d\n",interval,width); } switch (eth_pps_cfg->ppsout_ch) { switch (eth_pps_cfg->ppsout_ch) { case DWC_ETH_QOS_PPS_CH_0: case DWC_ETH_QOS_PPS_CH_0: if (pdata->emac_hw_version_type == EMAC_HW_v2_3_1) { if (pdata->res_data->pps_lpass_conn_en) { if (eth_pps_cfg->ppsout_start == DWC_ETH_QOS_PPS_START) { if (eth_pps_cfg->ppsout_start == DWC_ETH_QOS_PPS_START) { MAC_PPSC_PPSEN0_UDFWR(0x1); MAC_PPSC_PPSEN0_UDFWR(0x1); MAC_PPS_INTVAL_PPSINT0_UDFWR(DWC_ETH_QOS_PPS_CH_0, interval); MAC_PPS_INTVAL_PPSINT0_UDFWR(DWC_ETH_QOS_PPS_CH_0, interval); Loading Loading @@ -5885,7 +5869,6 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata, u32 ts_event_en = 0; u32 ts_event_en = 0; u32 av_8021asm_en = 0; u32 av_8021asm_en = 0; u32 VARMAC_TCR = 0; u32 VARMAC_TCR = 0; u64 temp = 0; struct timespec now; struct timespec now; DBGPR_PTP("-->DWC_ETH_QOS_handle_hwtstamp_ioctl\n"); DBGPR_PTP("-->DWC_ETH_QOS_handle_hwtstamp_ioctl\n"); Loading Loading @@ -6056,46 +6039,11 @@ static int DWC_ETH_QOS_handle_hwtstamp_ioctl(struct DWC_ETH_QOS_prv_data *pdata, hw_if->config_hw_time_stamping(VARMAC_TCR); hw_if->config_hw_time_stamping(VARMAC_TCR); /* program default addend */ hw_if->config_default_addend(pdata, DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* program Sub Second Increment Reg */ /* program Sub Second Increment Reg */ #ifdef CONFIG_PPS_OUTPUT hw_if->config_sub_second_increment(DWC_ETH_QOS_DEFAULT_PTP_CLOCK); /* If default_addend is already programmed, then we expect that * sub_second_increment is also programmed already */ if (pdata->default_addend == 0) { hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); // Using default 250MHz } else { u64 pclk; pclk = (u64) (pdata->default_addend) * DWC_ETH_QOS_SYSCLOCK; pclk += 0x8000000; pclk >>= 32; hw_if->config_sub_second_increment((u32)pclk); } #else hw_if->config_sub_second_increment(DWC_ETH_QOS_SYSCLOCK); #endif /* formula is : * addend = 2^32/freq_div_ratio; * * where, freq_div_ratio = DWC_ETH_QOS_SYSCLOCK/50MHz * * hence, addend = ((2^32) * 50MHz)/DWC_ETH_QOS_SYSCLOCK; * * NOTE: DWC_ETH_QOS_SYSCLOCK should be >= 50MHz to * achive 20ns accuracy. * * 2^x * y == (y << x), hence * 2^32 * 50000000 ==> (50000000 << 32) * */ #ifdef CONFIG_PPS_OUTPUT if(pdata->default_addend == 0){ temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); EMACINFO("Using default PTP clock = 250MHz\n"); #else temp = (u64)(50000000ULL << 32); pdata->default_addend = div_u64(temp, DWC_ETH_QOS_SYSCLOCK); #endif hw_if->config_addend(pdata->default_addend); /* initialize system time */ /* initialize system time */ getnstimeofday(&now); getnstimeofday(&now); Loading
drivers/emac-dwc-eqos/DWC_ETH_QOS_ipa.c +3 −3 Original line number Original line Diff line number Diff line Loading @@ -525,7 +525,7 @@ static int DWC_ETH_QOS_ipa_offload_resume(struct DWC_ETH_QOS_prv_data *pdata) static int DWC_ETH_QOS_ipa_ready(struct DWC_ETH_QOS_prv_data *pdata) static int DWC_ETH_QOS_ipa_ready(struct DWC_ETH_QOS_prv_data *pdata) { { int ret; int ret = 0 ; EMACDBG("Enter \n"); EMACDBG("Enter \n"); Loading Loading @@ -960,8 +960,8 @@ static int DWC_ETH_QOS_ipa_offload_connect(struct DWC_ETH_QOS_prv_data *pdata) struct DWC_ETH_QOS_prv_ipa_data *ntn_ipa = &pdata->prv_ipa; struct DWC_ETH_QOS_prv_ipa_data *ntn_ipa = &pdata->prv_ipa; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_in_params in; struct ipa_uc_offload_conn_out_params out; struct ipa_uc_offload_conn_out_params out; struct ipa_ntn_setup_info rx_setup_info; struct ipa_ntn_setup_info rx_setup_info = {0}; struct ipa_ntn_setup_info tx_setup_info; struct ipa_ntn_setup_info tx_setup_info = {0}; struct ipa_perf_profile profile; struct ipa_perf_profile profile; int ret = 0; int ret = 0; int i = 0; int i = 0; Loading