mirror of
git://nv-tegra.nvidia.com/kernel/nvethernetrm.git
synced 2025-12-24 10:34:24 +03:00
nvethernetrm: mgbe: add PTP support
Change takes care of - o Enable PTP for MGBE o Added flags for One step/two step and also for PTP master/slave o Getting timestamp from MAC registers for MGBE. Bug 200565914 Change-Id: I17346451f2619f0526a737a4a6bffdf130af4fc0 Signed-off-by: rakesh goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/kernel/nvethernetrm/+/2314201 Reviewed-by: Bhadram Varka <vbhadram@nvidia.com>
This commit is contained in:
committed by
Bhadram Varka
parent
d17a9e4c63
commit
f6cbb32a42
@@ -130,6 +130,8 @@
|
||||
#define OSI_PTP_REQ_CLK_FREQ 250000000U
|
||||
#define OSI_FLOW_CTRL_DISABLE 0U
|
||||
|
||||
#define OSI_POLL_COUNT 1000U
|
||||
|
||||
#define OSI_ADDRESS_32BIT 0
|
||||
#define OSI_ADDRESS_40BIT 1
|
||||
#define OSI_ADDRESS_48BIT 2
|
||||
@@ -143,7 +145,6 @@
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup Helper Helper MACROS
|
||||
*
|
||||
@@ -154,11 +155,15 @@
|
||||
|
||||
/* Logging defines */
|
||||
/* log levels */
|
||||
|
||||
#define OSI_LOG_INFO 1U
|
||||
#define OSI_LOG_WARN 2U
|
||||
#define OSI_LOG_ERR 3U
|
||||
/* Error types */
|
||||
#define OSI_LOG_ARG_OUTOFBOUND 1U
|
||||
#define OSI_LOG_ARG_INVALID 2U
|
||||
#define OSI_LOG_ARG_HW_FAIL 4U
|
||||
#ifndef OSI_STRIPPED_LIB
|
||||
#define OSI_LOG_WARN 2U
|
||||
#define OSI_LOG_ARG_OPNOTSUPP 3U
|
||||
#endif /* !OSI_STRIPPED_LIB */
|
||||
/* Default maximum Giant Packet Size Limit is 16K */
|
||||
|
||||
@@ -76,6 +76,7 @@ typedef my_lint_64 nvel64_t;
|
||||
#define OSI_MAC_TCR_TSMASTERENA OSI_BIT(15)
|
||||
#define OSI_MAC_TCR_SNAPTYPSEL_1 OSI_BIT(16)
|
||||
#define OSI_MAC_TCR_SNAPTYPSEL_2 OSI_BIT(17)
|
||||
#define OSI_MAC_TCR_CSC OSI_BIT(19)
|
||||
#define OSI_MAC_TCR_AV8021ASMEN OSI_BIT(28)
|
||||
#ifndef OSI_STRIPPED_LIB
|
||||
#define OSI_MAC_TCR_SNAPTYPSEL_3 (OSI_BIT(16) | OSI_BIT(17))
|
||||
@@ -115,11 +116,6 @@ typedef my_lint_64 nvel64_t;
|
||||
#define OSI_IPV6_MATCH 1U
|
||||
#define OSI_IPV4_MATCH 0U
|
||||
|
||||
|
||||
#define OSI_LOG_INFO 1U
|
||||
#define OSI_LOG_ARG_HW_FAIL 4U
|
||||
#define OSI_LOG_ARG_OUTOFBOUND 1U
|
||||
|
||||
/* L2 filter operations supported by OSI layer. These operation modes shall be
|
||||
* set by OSD driver as input to update registers accordingly.
|
||||
*/
|
||||
@@ -180,6 +176,8 @@ typedef my_lint_64 nvel64_t;
|
||||
#define VLAN_NUM_VID 4096U
|
||||
#define OSI_VLAN_ACTION_ADD OSI_BIT(31)
|
||||
#define OSI_VLAN_ACTION_DEL 0x0U
|
||||
#define OSI_RXQ_ROUTE_PTP 0U
|
||||
#define OSI_DELAY_1000US 1000U
|
||||
|
||||
/**
|
||||
* @addtogroup RSS related information
|
||||
|
||||
@@ -26,6 +26,19 @@
|
||||
#include <osi_common.h>
|
||||
#include "osi_dma_txrx.h"
|
||||
|
||||
/*
|
||||
* @addtogroup Helper Helper MACROS
|
||||
*
|
||||
* @brief These flags are used for PTP time synchronization
|
||||
* @{
|
||||
*/
|
||||
#define OSI_PTP_SYNC_MASTER OSI_BIT(0)
|
||||
#define OSI_PTP_SYNC_SLAVE OSI_BIT(1)
|
||||
#define OSI_PTP_SYNC_ONESTEP OSI_BIT(2)
|
||||
#define OSI_PTP_SYNC_TWOSTEP OSI_BIT(3)
|
||||
#define OSI_DELAY_1US 1U
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @addtogroup Helper Helper MACROS
|
||||
*
|
||||
@@ -82,8 +95,8 @@
|
||||
* whether checksum offload is to be enabled for the packet upon transmit,
|
||||
* whether IP checksum offload is to be enabled for the packet upon transmit,
|
||||
* whether TCP segmentation offload is to be enabled for the packet,
|
||||
* whether the HW should timestamp transmit/arrival of a packet respectively,
|
||||
* whether tx payload length to be updated
|
||||
* whether the HW should timestamp transmit/arrival of a packet respectively
|
||||
* whether a paged buffer.
|
||||
* @{
|
||||
*/
|
||||
/** VLAN packet */
|
||||
@@ -94,8 +107,10 @@
|
||||
#define OSI_PKT_CX_TSO OSI_BIT(2)
|
||||
/** PTP packet */
|
||||
#define OSI_PKT_CX_PTP OSI_BIT(3)
|
||||
/** Paged buffer */
|
||||
#define OSI_PKT_CX_PAGED_BUF OSI_BIT(4)
|
||||
/** Rx packet has RSS hash */
|
||||
#define OSI_PKT_CX_RSS OSI_BIT(4)
|
||||
#define OSI_PKT_CX_RSS OSI_BIT(5)
|
||||
/** Valid packet */
|
||||
#define OSI_PKT_CX_VALID OSI_BIT(10)
|
||||
/** Update Packet Length in Tx Desc3 */
|
||||
@@ -324,6 +339,11 @@ struct osi_tx_swcx {
|
||||
/** Flag to keep track of whether buffer pointed by buf_phy_addr
|
||||
* is a paged buffer/linear buffer */
|
||||
nveu32_t is_paged_buf;
|
||||
/** Flag to keep track of SWCX
|
||||
* Bit 0 is_paged_buf - whether buffer pointed by buf_phy_addr
|
||||
* is a paged buffer/linear buffer
|
||||
* Bit 1 PTP hwtime form timestamp registers */
|
||||
unsigned int flags;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -519,6 +539,10 @@ struct osi_dma_priv_data {
|
||||
nveu64_t resv_buf_phy_addr;
|
||||
/** Tegra Pre-si platform info */
|
||||
nveu32_t pre_si;
|
||||
/** PTP flags
|
||||
* bit 0 PTP mode master(1) slave(0)
|
||||
* bit 1 PTP sync method twostep(1) onestep(0) */
|
||||
unsigned int ptp_flag;
|
||||
};
|
||||
|
||||
|
||||
|
||||
72
osi/common/mgbe_common.c
Normal file
72
osi/common/mgbe_common.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "../osi/common/common.h"
|
||||
#include "mgbe_common.h"
|
||||
|
||||
/**
|
||||
* @brief mgbe_get_systime_from_mac - Get system time from MAC
|
||||
*
|
||||
* Algorithm: Get current system time
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
nveul64_t mgbe_get_systime_from_mac(void *addr)
|
||||
{
|
||||
nveul64_t ns1, ns2, ns = 0;
|
||||
nveu32_t varmac_stnsr, temp1;
|
||||
nveu32_t varmac_stsr;
|
||||
|
||||
varmac_stnsr = osi_readl((nveu8_t *)addr + MGBE_MAC_STNSR);
|
||||
temp1 = (varmac_stnsr & MGBE_MAC_STNSR_TSSS_MASK);
|
||||
ns1 = (nveul64_t)temp1;
|
||||
|
||||
varmac_stsr = osi_readl((nveu8_t *)addr + MGBE_MAC_STSR);
|
||||
|
||||
varmac_stnsr = osi_readl((nveu8_t *)addr + MGBE_MAC_STNSR);
|
||||
temp1 = (varmac_stnsr & MGBE_MAC_STNSR_TSSS_MASK);
|
||||
ns2 = (nveul64_t)temp1;
|
||||
|
||||
/* if ns1 is greater than ns2, it means nsec counter rollover
|
||||
* happened. In that case read the updated sec counter again
|
||||
*/
|
||||
if (ns1 >= ns2) {
|
||||
varmac_stsr = osi_readl((nveu8_t *)addr + MGBE_MAC_STSR);
|
||||
/* convert sec/high time value to nanosecond */
|
||||
if (varmac_stsr < UINT_MAX) {
|
||||
ns = ns2 + (varmac_stsr * OSI_NSEC_PER_SEC);
|
||||
}
|
||||
} else {
|
||||
/* convert sec/high time value to nanosecond */
|
||||
if (varmac_stsr < UINT_MAX) {
|
||||
ns = ns1 + (varmac_stsr * OSI_NSEC_PER_SEC);
|
||||
}
|
||||
}
|
||||
|
||||
return ns;
|
||||
}
|
||||
38
osi/common/mgbe_common.h
Normal file
38
osi/common/mgbe_common.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_MGBE_COMMON_H
|
||||
#define INCLUDED_MGBE_COMMON_H
|
||||
|
||||
/**
|
||||
* @addtogroup MGBE-MAC MGBE MAC PTP HW feature registers
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define MGBE_MAC_STSR 0x0D08
|
||||
#define MGBE_MAC_STNSR 0x0D0C
|
||||
#define MGBE_MAC_STNSR_TSSS_MASK 0x7FFFFFFFU
|
||||
/** @} */
|
||||
|
||||
nveul64_t mgbe_get_systime_from_mac(void *addr);
|
||||
|
||||
#endif /* INCLUDED_MGBE_COMMON_H */
|
||||
@@ -32,6 +32,8 @@ void common_get_systime_from_mac(void *addr, nveu32_t mac, nveu32_t *sec,
|
||||
|
||||
if (mac == OSI_MAC_HW_EQOS) {
|
||||
ns = eqos_get_systime_from_mac(addr);
|
||||
} else if (mac == OSI_MAC_HW_MGBE) {
|
||||
ns = eqos_get_systime_from_mac(addr);
|
||||
} else {
|
||||
/* Non EQOS HW is supported yet */
|
||||
return;
|
||||
|
||||
@@ -120,7 +120,8 @@ struct core_ops {
|
||||
void (*config_tscr)(struct osi_core_priv_data *const osi_core,
|
||||
const nveu32_t ptp_filter);
|
||||
/** Called to configure the sub second increment register */
|
||||
void (*config_ssir)(struct osi_core_priv_data *const osi_core);
|
||||
void (*config_ssir)(struct osi_core_priv_data *const osi_core,
|
||||
const nveu32_t ptp_clock);
|
||||
/** Called to configure the PTP RX packets Queue */
|
||||
nve32_t (*config_ptp_rxq)(struct osi_core_priv_data *const osi_core,
|
||||
const unsigned int rxq_idx,
|
||||
|
||||
@@ -2740,11 +2740,12 @@ static inline nve32_t eqos_poll_for_tsinit_complete(
|
||||
if ((*mac_tcr & EQOS_MAC_TCR_TSINIT) == 0U) {
|
||||
cond = COND_MET;
|
||||
}
|
||||
|
||||
count++;
|
||||
osi_core->osd_ops.udelay(1000U);
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2779,6 +2780,7 @@ static nve32_t eqos_set_systime_to_mac(
|
||||
nveu32_t mac_tcr;
|
||||
nve32_t ret;
|
||||
|
||||
/* To be sure previous write was flushed (if Any) */
|
||||
ret = eqos_poll_for_tsinit_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
@@ -2852,11 +2854,12 @@ static inline nve32_t eqos_poll_for_addend_complete(
|
||||
if ((*mac_tcr & EQOS_MAC_TCR_TSADDREG) == 0U) {
|
||||
cond = COND_MET;
|
||||
}
|
||||
|
||||
count++;
|
||||
osi_core->osd_ops.udelay(1000U);
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2886,6 +2889,7 @@ static nve32_t eqos_config_addend(struct osi_core_priv_data *const osi_core,
|
||||
nveu32_t mac_tcr;
|
||||
nve32_t ret;
|
||||
|
||||
/* To be sure previous write was flushed (if Any) */
|
||||
ret = eqos_poll_for_addend_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
@@ -2955,11 +2959,12 @@ static inline nve32_t eqos_poll_for_update_ts_complete(
|
||||
if ((*mac_tcr & EQOS_MAC_TCR_TSUPDT) == 0U) {
|
||||
cond = COND_MET;
|
||||
}
|
||||
|
||||
count++;
|
||||
osi_core->osd_ops.udelay(1000U);
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
@@ -3082,58 +3087,54 @@ static void eqos_config_tscr(struct osi_core_priv_data *const osi_core,
|
||||
void *addr = osi_core->base;
|
||||
nveu32_t mac_tcr = 0U, i = 0U, temp = 0U;
|
||||
|
||||
if (ptp_filter == OSI_DISABLE) {
|
||||
if (ptp_filter != OSI_DISABLE) {
|
||||
mac_tcr = (OSI_MAC_TCR_TSENA |
|
||||
OSI_MAC_TCR_TSCFUPDT |
|
||||
OSI_MAC_TCR_TSCTRLSSR);
|
||||
|
||||
for (i = 0U; i < 32U; i++) {
|
||||
temp = ptp_filter & OSI_BIT(i);
|
||||
|
||||
switch (temp) {
|
||||
case OSI_MAC_TCR_SNAPTYPSEL_1:
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_1;
|
||||
break;
|
||||
case OSI_MAC_TCR_SNAPTYPSEL_2:
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_2;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPV4ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV4ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPV6ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV6ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSEVENTENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSEVENTENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSMASTERENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSMASTERENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSVER2ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSVER2ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_AV8021ASMEN:
|
||||
mac_tcr |= OSI_MAC_TCR_AV8021ASMEN;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSENALL:
|
||||
mac_tcr |= OSI_MAC_TCR_TSENALL;
|
||||
break;
|
||||
default:
|
||||
/* To avoid MISRA violation */
|
||||
mac_tcr |= mac_tcr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Disabling the MAC time stamping */
|
||||
mac_tcr = OSI_DISABLE;
|
||||
eqos_core_safety_writel(osi_core, mac_tcr,
|
||||
(nveu8_t *)addr + EQOS_MAC_TCR,
|
||||
EQOS_MAC_TCR_IDX);
|
||||
return;
|
||||
}
|
||||
|
||||
mac_tcr = (OSI_MAC_TCR_TSENA |
|
||||
OSI_MAC_TCR_TSCFUPDT |
|
||||
OSI_MAC_TCR_TSCTRLSSR);
|
||||
|
||||
for (i = 0U; i < 32U; i++) {
|
||||
temp = ptp_filter & OSI_BIT(i);
|
||||
|
||||
switch (temp) {
|
||||
case OSI_MAC_TCR_SNAPTYPSEL_1:
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_1;
|
||||
break;
|
||||
case OSI_MAC_TCR_SNAPTYPSEL_2:
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_2;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPV4ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV4ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPV6ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV6ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSEVENTENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSEVENTENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSMASTERENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSMASTERENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSVER2ENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSVER2ENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSIPENA:
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPENA;
|
||||
break;
|
||||
case OSI_MAC_TCR_AV8021ASMEN:
|
||||
mac_tcr |= OSI_MAC_TCR_AV8021ASMEN;
|
||||
break;
|
||||
case OSI_MAC_TCR_TSENALL:
|
||||
mac_tcr |= OSI_MAC_TCR_TSENALL;
|
||||
break;
|
||||
default:
|
||||
/* To avoid MISRA violation */
|
||||
mac_tcr |= mac_tcr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eqos_core_safety_writel(osi_core, mac_tcr,
|
||||
@@ -3154,12 +3155,12 @@ static void eqos_config_tscr(struct osi_core_priv_data *const osi_core,
|
||||
* - Run time: Yes
|
||||
* - De-initialization: No
|
||||
*/
|
||||
static void eqos_config_ssir(struct osi_core_priv_data *const osi_core)
|
||||
static void eqos_config_ssir(struct osi_core_priv_data *const osi_core,
|
||||
const unsigned int ptp_clock)
|
||||
{
|
||||
nveul64_t val;
|
||||
nveu32_t mac_tcr;
|
||||
void *addr = osi_core->base;
|
||||
nveu32_t ptp_clock = osi_core->ptp_config.ptp_clock;
|
||||
|
||||
mac_tcr = osi_readla(osi_core, (nveu8_t *)addr + EQOS_MAC_TCR);
|
||||
|
||||
|
||||
@@ -815,9 +815,9 @@ static void ivc_config_tscr(struct osi_core_priv_data *const osi_core,
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*/
|
||||
static void ivc_config_ssir(struct osi_core_priv_data *const osi_core)
|
||||
static void ivc_config_ssir(struct osi_core_priv_data *const osi_core,
|
||||
const unsigned int ptp_clock)
|
||||
{
|
||||
nveu32_t ptp_clock = osi_core->ptp_config.ptp_clock;
|
||||
ivc_msg_common msg_common;
|
||||
nve32_t index = 0;
|
||||
|
||||
|
||||
@@ -369,7 +369,6 @@ err_dma_chan:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief mgbe_update_mac_addr_low_high_reg- Update L2 address in filter
|
||||
* register
|
||||
@@ -3382,6 +3381,416 @@ static int mgbe_get_hw_features(struct osi_core_priv_data *osi_core,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_poll_for_tsinit_complete - Poll for time stamp init complete
|
||||
*
|
||||
* Algorithm: Read TSINIT value from MAC TCR register until it is
|
||||
* equal to zero.
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] mac_tcr: Address to store time stamp control register read value
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static inline int mgbe_poll_for_tsinit_complete(
|
||||
struct osi_core_priv_data *osi_core,
|
||||
unsigned int *mac_tcr)
|
||||
{
|
||||
unsigned int retry = 0U;
|
||||
|
||||
while (retry < OSI_POLL_COUNT) {
|
||||
/* Read and Check TSINIT in MAC_Timestamp_Control register */
|
||||
*mac_tcr = osi_readl((unsigned char *)osi_core->base +
|
||||
MGBE_MAC_TCR);
|
||||
if ((*mac_tcr & MGBE_MAC_TCR_TSINIT) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry++;
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_set_systime - Set system time
|
||||
*
|
||||
* Algorithm: Updates system time (seconds and nano seconds)
|
||||
* in hardware registers
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] sec: Seconds to be configured
|
||||
* @param[in] nsec: Nano Seconds to be configured
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static int mgbe_set_systime_to_mac(struct osi_core_priv_data *osi_core,
|
||||
unsigned int sec,
|
||||
unsigned int nsec)
|
||||
{
|
||||
unsigned int mac_tcr;
|
||||
void *addr = osi_core->base;
|
||||
int ret;
|
||||
|
||||
/* To be sure previous write was flushed (if Any) */
|
||||
ret = mgbe_poll_for_tsinit_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write seconds value to MAC_System_Time_Seconds_Update register */
|
||||
osi_writel(sec, (unsigned char *)addr + MGBE_MAC_STSUR);
|
||||
|
||||
/* write nano seconds value to MAC_System_Time_Nanoseconds_Update
|
||||
* register
|
||||
*/
|
||||
osi_writel(nsec, (unsigned char *)addr + MGBE_MAC_STNSUR);
|
||||
|
||||
/* issue command to update the configured secs and nsecs values */
|
||||
mac_tcr |= MGBE_MAC_TCR_TSINIT;
|
||||
osi_writel(mac_tcr, (unsigned char *)addr + MGBE_MAC_TCR);
|
||||
|
||||
ret = mgbe_poll_for_tsinit_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_poll_for_addend_complete - Poll for addend value write complete
|
||||
*
|
||||
* Algorithm: Read TSADDREG value from MAC TCR register until it is
|
||||
* equal to zero.
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] mac_tcr: Address to store time stamp control register read value
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static inline int mgbe_poll_for_addend_complete(
|
||||
struct osi_core_priv_data *osi_core,
|
||||
unsigned int *mac_tcr)
|
||||
{
|
||||
unsigned int retry = 0U;
|
||||
|
||||
/* Poll */
|
||||
while (retry < OSI_POLL_COUNT) {
|
||||
/* Read and Check TSADDREG in MAC_Timestamp_Control register */
|
||||
*mac_tcr = osi_readl((unsigned char *)osi_core->base +
|
||||
MGBE_MAC_TCR);
|
||||
if ((*mac_tcr & MGBE_MAC_TCR_TSADDREG) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry++;
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_config_addend - Configure addend
|
||||
*
|
||||
* Algorithm: Updates the Addend value in HW register
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] addend: Addend value to be configured
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static int mgbe_config_addend(struct osi_core_priv_data *osi_core,
|
||||
unsigned int addend)
|
||||
{
|
||||
unsigned int mac_tcr;
|
||||
void *addr = osi_core->base;
|
||||
int ret;
|
||||
|
||||
/* To be sure previous write was flushed (if Any) */
|
||||
ret = mgbe_poll_for_addend_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write addend value to MAC_Timestamp_Addend register */
|
||||
osi_writel(addend, (unsigned char *)addr + MGBE_MAC_TAR);
|
||||
|
||||
/* issue command to update the configured addend value */
|
||||
mac_tcr |= MGBE_MAC_TCR_TSADDREG;
|
||||
osi_writel(mac_tcr, (unsigned char *)addr + MGBE_MAC_TCR);
|
||||
|
||||
ret = mgbe_poll_for_addend_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_poll_for_update_ts_complete - Poll for update time stamp
|
||||
*
|
||||
* Algorithm: Read time stamp update value from TCR register until it is
|
||||
* equal to zero.
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] mac_tcr: Address to store time stamp control register read value
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static inline int mgbe_poll_for_update_ts_complete(struct osi_core_priv_data *osi_core,
|
||||
unsigned int *mac_tcr)
|
||||
{
|
||||
unsigned int retry = 0U;
|
||||
|
||||
while (retry < OSI_POLL_COUNT) {
|
||||
/* Read and Check TSUPDT in MAC_Timestamp_Control register */
|
||||
*mac_tcr = osi_readl((unsigned char *)osi_core->base +
|
||||
MGBE_MAC_TCR);
|
||||
if ((*mac_tcr & MGBE_MAC_TCR_TSUPDT) == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
retry++;
|
||||
osi_core->osd_ops.udelay(OSI_DELAY_1000US);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_adjust_mactime - Adjust MAC time with system time
|
||||
*
|
||||
* Algorithm: Update MAC time with system time
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] sec: Seconds to be configured
|
||||
* @param[in] nsec: Nano seconds to be configured
|
||||
* @param[in] add_sub: To decide on add/sub with system time
|
||||
* @param[in] one_nsec_accuracy: One nano second accuracy
|
||||
*
|
||||
* @note 1) MAC should be init and started. see osi_start_mac()
|
||||
* 2) osi_core->ptp_config.one_nsec_accuracy need to be set to 1
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -1 on failure.
|
||||
*/
|
||||
static int mgbe_adjust_mactime(struct osi_core_priv_data *osi_core,
|
||||
unsigned int sec, unsigned int nsec,
|
||||
unsigned int add_sub,
|
||||
unsigned int one_nsec_accuracy)
|
||||
{
|
||||
void *addr = osi_core->base;
|
||||
unsigned int mac_tcr;
|
||||
unsigned int value = 0;
|
||||
unsigned long long temp = 0;
|
||||
int ret;
|
||||
|
||||
/* To be sure previous write was flushed (if Any) */
|
||||
ret = mgbe_poll_for_update_ts_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (add_sub != 0U) {
|
||||
/* If the new sec value needs to be subtracted with
|
||||
* the system time, then MAC_STSUR reg should be
|
||||
* programmed with (2^32 – <new_sec_value>)
|
||||
*/
|
||||
temp = (TWO_POWER_32 - sec);
|
||||
if (temp < UINT_MAX) {
|
||||
sec = (unsigned int)temp;
|
||||
} else {
|
||||
/* do nothing here */
|
||||
}
|
||||
|
||||
/* If the new nsec value need to be subtracted with
|
||||
* the system time, then MAC_STNSUR.TSSS field should be
|
||||
* programmed with, (10^9 - <new_nsec_value>) if
|
||||
* MAC_TCR.TSCTRLSSR is set or
|
||||
* (2^32 - <new_nsec_value> if MAC_TCR.TSCTRLSSR is reset)
|
||||
*/
|
||||
if (one_nsec_accuracy == OSI_ENABLE) {
|
||||
if (nsec < UINT_MAX) {
|
||||
nsec = (TEN_POWER_9 - nsec);
|
||||
}
|
||||
} else {
|
||||
if (nsec < UINT_MAX) {
|
||||
nsec = (TWO_POWER_31 - nsec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* write seconds value to MAC_System_Time_Seconds_Update register */
|
||||
osi_writel(sec, (unsigned char *)addr + MGBE_MAC_STSUR);
|
||||
|
||||
/* write nano seconds value and add_sub to
|
||||
* MAC_System_Time_Nanoseconds_Update register
|
||||
*/
|
||||
value |= nsec;
|
||||
value |= (add_sub << MGBE_MAC_STNSUR_ADDSUB_SHIFT);
|
||||
osi_writel(value, (unsigned char *)addr + MGBE_MAC_STNSUR);
|
||||
|
||||
/* issue command to initialize system time with the value
|
||||
* specified in MAC_STSUR and MAC_STNSUR
|
||||
*/
|
||||
mac_tcr |= MGBE_MAC_TCR_TSUPDT;
|
||||
osi_writel(mac_tcr, (unsigned char *)addr + MGBE_MAC_TCR);
|
||||
|
||||
ret = mgbe_poll_for_update_ts_complete(osi_core, &mac_tcr);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_config_tscr - Configure Time Stamp Register
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* @param[in] ptp_filter: PTP rx filter parameters
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*/
|
||||
static void mgbe_config_tscr(struct osi_core_priv_data *osi_core,
|
||||
unsigned int ptp_filter)
|
||||
{
|
||||
unsigned int mac_tcr = 0;
|
||||
void *addr = osi_core->base;
|
||||
|
||||
if (ptp_filter != OSI_DISABLE) {
|
||||
mac_tcr = (OSI_MAC_TCR_TSENA |
|
||||
OSI_MAC_TCR_TSCFUPDT |
|
||||
OSI_MAC_TCR_TSCTRLSSR);
|
||||
|
||||
if ((ptp_filter & OSI_MAC_TCR_SNAPTYPSEL_1) ==
|
||||
OSI_MAC_TCR_SNAPTYPSEL_1) {
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_1;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_SNAPTYPSEL_2) ==
|
||||
OSI_MAC_TCR_SNAPTYPSEL_2) {
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_2;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_SNAPTYPSEL_3) ==
|
||||
OSI_MAC_TCR_SNAPTYPSEL_3) {
|
||||
mac_tcr |= OSI_MAC_TCR_SNAPTYPSEL_3;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSIPV4ENA) ==
|
||||
OSI_MAC_TCR_TSIPV4ENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV4ENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSIPV6ENA) ==
|
||||
OSI_MAC_TCR_TSIPV6ENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPV6ENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSEVENTENA) ==
|
||||
OSI_MAC_TCR_TSEVENTENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSEVENTENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSMASTERENA) ==
|
||||
OSI_MAC_TCR_TSMASTERENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSMASTERENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSVER2ENA) ==
|
||||
OSI_MAC_TCR_TSVER2ENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSVER2ENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSIPENA) ==
|
||||
OSI_MAC_TCR_TSIPENA) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSIPENA;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_AV8021ASMEN) ==
|
||||
OSI_MAC_TCR_AV8021ASMEN) {
|
||||
mac_tcr |= OSI_MAC_TCR_AV8021ASMEN;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_TSENALL) ==
|
||||
OSI_MAC_TCR_TSENALL) {
|
||||
mac_tcr |= OSI_MAC_TCR_TSENALL;
|
||||
}
|
||||
if ((ptp_filter & OSI_MAC_TCR_CSC) ==
|
||||
OSI_MAC_TCR_CSC) {
|
||||
mac_tcr |= OSI_MAC_TCR_CSC;
|
||||
}
|
||||
} else {
|
||||
/* Disabling the MAC time stamping */
|
||||
mac_tcr = OSI_DISABLE;
|
||||
}
|
||||
|
||||
osi_writel(mac_tcr, (unsigned char *)addr + MGBE_MAC_TCR);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_config_ssir - Configure SSIR
|
||||
*
|
||||
* @param[in] addr: Base address indicating the start of
|
||||
* memory mapped IO region of the MAC.
|
||||
* it compiled earlier
|
||||
* @param[in] ptp_clock: PTP required clock frequency
|
||||
*
|
||||
* @note MAC should be init and started. see osi_start_mac()
|
||||
*/
|
||||
static void mgbe_config_ssir(struct osi_core_priv_data *const osi_core,
|
||||
const unsigned int ptp_clock)
|
||||
{
|
||||
unsigned long long val;
|
||||
unsigned int mac_tcr;
|
||||
void *addr = osi_core->base;
|
||||
|
||||
mac_tcr = osi_readl((unsigned char *)addr + MGBE_MAC_TCR);
|
||||
|
||||
/* convert the PTP required clock frequency to nano second.
|
||||
* formula is : ((1/ptp_clock) * 1000000000)
|
||||
* where, ptp_clock = OSI_PTP_REQ_CLK_FREQ if FINE correction
|
||||
* and ptp_clock = PTP reference clock if COARSE correction
|
||||
*/
|
||||
|
||||
if ((mac_tcr & MGBE_MAC_TCR_TSCFUPDT) == MGBE_MAC_TCR_TSCFUPDT) {
|
||||
val = ((1U * OSI_NSEC_PER_SEC) / OSI_PTP_REQ_CLK_FREQ);
|
||||
} else {
|
||||
val = ((1U * OSI_NSEC_PER_SEC) / ptp_clock);
|
||||
}
|
||||
|
||||
/* 0.465ns accurecy */
|
||||
if ((mac_tcr & MGBE_MAC_TCR_TSCTRLSSR) == 0U) {
|
||||
if (val < UINT_MAX) {
|
||||
val = (val * 1000U) / 465U;
|
||||
}
|
||||
}
|
||||
|
||||
val |= (val << MGBE_MAC_SSIR_SSINC_SHIFT);
|
||||
/* update Sub-second Increment Value */
|
||||
if (val < UINT_MAX) {
|
||||
osi_writel((unsigned int)val,
|
||||
(unsigned char *)addr + MGBE_MAC_SSIR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_init_core_ops - Initialize MGBE MAC core operations
|
||||
*/
|
||||
@@ -3421,11 +3830,11 @@ void mgbe_init_core_ops(struct core_ops *ops)
|
||||
ops->update_l4_port_no = mgbe_update_l4_port_no;
|
||||
ops->config_vlan_filtering = mgbe_config_vlan_filtering;
|
||||
ops->update_vlan_id = mgbe_update_vlan_id;
|
||||
ops->set_systime_to_mac = OSI_NULL;
|
||||
ops->config_addend = OSI_NULL;
|
||||
ops->adjust_mactime = OSI_NULL,
|
||||
ops->config_tscr = OSI_NULL;
|
||||
ops->config_ssir = OSI_NULL;
|
||||
ops->set_systime_to_mac = mgbe_set_systime_to_mac;
|
||||
ops->config_addend = mgbe_config_addend;
|
||||
ops->adjust_mactime = mgbe_adjust_mactime;
|
||||
ops->config_tscr = mgbe_config_tscr;
|
||||
ops->config_ssir = mgbe_config_ssir,
|
||||
ops->config_ptp_rxq = mgbe_config_ptp_rxq;
|
||||
ops->write_phy_reg = mgbe_write_phy_reg;
|
||||
ops->read_phy_reg = mgbe_read_phy_reg;
|
||||
|
||||
@@ -377,6 +377,16 @@
|
||||
#define MGBE_MTL_RXQ_SIZE_SHIFT 16U
|
||||
#define MGBE_MAC_RMCR_GPSL_MSK 0x3FFF0000U
|
||||
#define MGBE_MTL_RXQ_OP_MODE_FEP OSI_BIT(4)
|
||||
#define MGBE_MAC_TCR_TSCFUPDT OSI_BIT(1)
|
||||
#define MGBE_MAC_TCR_TSINIT OSI_BIT(2)
|
||||
#define MGBE_MAC_TCR_TSUPDT OSI_BIT(3)
|
||||
#define MGBE_MAC_TCR_TSADDREG OSI_BIT(5)
|
||||
#define MGBE_MAC_TCR_TSCTRLSSR OSI_BIT(9)
|
||||
#define MGBE_MAC_TCR_TSENMACADDR OSI_BIT(18)
|
||||
#define MGBE_MAC_STNSUR_ADDSUB_SHIFT 31U
|
||||
#define MGBE_MAC_SSIR_SSINC_SHIFT 16U
|
||||
#define MGBE_MAC_STNSR_TSSS_MASK 0x7FFFFFFFU
|
||||
#define MGBE_MAC_TCR_SNAPTYPSEL_SHIFT 16
|
||||
#define MGBE_MAC_QX_TX_FLW_CTRL_TFE OSI_BIT(1)
|
||||
#define MGBE_MAC_RX_FLW_CTRL_RFE OSI_BIT(0)
|
||||
#define MGBE_MAC_PAUSE_TIME 0xFFFF0000U
|
||||
|
||||
@@ -667,7 +667,7 @@ nve32_t osi_ptp_configuration(struct osi_core_priv_data *const osi_core,
|
||||
ops_p->config_tscr(osi_core, osi_core->ptp_config.ptp_filter);
|
||||
|
||||
/* Program Sub Second Increment Register */
|
||||
ops_p->config_ssir(osi_core);
|
||||
ops_p->config_ssir(osi_core, osi_core->ptp_config.ptp_clock);
|
||||
|
||||
/* formula for calculating addend value is
|
||||
* TSAR = (2^32 * 1000) / (ptp_ref_clk_rate in MHz * SSINC)
|
||||
|
||||
@@ -101,6 +101,11 @@ struct desc_ops {
|
||||
/** Called to get rx HASH from descriptor */
|
||||
void (*get_rx_hash)(struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx);
|
||||
/** Called to get RX hw timestamp */
|
||||
int (*get_rx_hwstamp)(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_desc *context_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -175,6 +175,70 @@ static void eqos_get_rx_hash(struct osi_rx_desc *rx_desc,
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief eqos_get_rx_hwstamp - Get Rx HW Time stamp
|
||||
*
|
||||
* Algorithm:
|
||||
* 1) Check for TS availability.
|
||||
* 2) call get_tx_tstamp_status if TS is valid or not.
|
||||
* 3) If yes, set a bit and update nano seconds in rx_pkt_cx so that OSD
|
||||
* layer can extract the time by checking this bit.
|
||||
*
|
||||
* @param[in] rx_desc: Rx descriptor
|
||||
* @param[in] context_desc: Rx context descriptor
|
||||
* @param[in] rx_pkt_cx: Rx packet context
|
||||
*
|
||||
* @retval -1 if TimeStamp is not available
|
||||
* @retval 0 if TimeStamp is available.
|
||||
*/
|
||||
static int eqos_get_rx_hwstamp(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_desc *context_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx)
|
||||
{
|
||||
int retry;
|
||||
|
||||
/* Check for RS1V/TSA/TD valid */
|
||||
if (((rx_desc->rdes3 & RDES3_RS1V) == RDES3_RS1V) &&
|
||||
((rx_desc->rdes1 & RDES1_TSA) == RDES1_TSA) &&
|
||||
((rx_desc->rdes1 & RDES1_TD) == 0U)) {
|
||||
for (retry = 0; retry < 10; retry++) {
|
||||
if (((context_desc->rdes3 & RDES3_OWN) == 0U) &&
|
||||
((context_desc->rdes3 & RDES3_CTXT) ==
|
||||
RDES3_CTXT)) {
|
||||
if ((context_desc->rdes0 ==
|
||||
OSI_INVALID_VALUE) &&
|
||||
(context_desc->rdes1 ==
|
||||
OSI_INVALID_VALUE)) {
|
||||
return -1;
|
||||
}
|
||||
/* Update rx pkt context flags to indicate
|
||||
* PTP */
|
||||
rx_pkt_cx->flags |= OSI_PKT_CX_PTP;
|
||||
/* Time Stamp can be read */
|
||||
break;
|
||||
} else {
|
||||
/* TS not available yet, so retrying */
|
||||
osi_dma->osd_ops.udelay(OSI_DELAY_1US);
|
||||
}
|
||||
}
|
||||
if (retry == 10) {
|
||||
/* Timed out waiting for Rx timestamp */
|
||||
return -1;
|
||||
}
|
||||
|
||||
rx_pkt_cx->ns = context_desc->rdes0 +
|
||||
(OSI_NSEC_PER_SEC * context_desc->rdes1);
|
||||
if (rx_pkt_cx->ns < context_desc->rdes0) {
|
||||
/* Will not hit this case */
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void eqos_init_desc_ops(struct desc_ops *d_ops)
|
||||
{
|
||||
@@ -182,4 +246,5 @@ void eqos_init_desc_ops(struct desc_ops *d_ops)
|
||||
d_ops->update_rx_err_stats = eqos_update_rx_err_stats;
|
||||
d_ops->get_rx_vlan = eqos_get_rx_vlan;
|
||||
d_ops->get_rx_hash = eqos_get_rx_hash;
|
||||
d_ops->get_rx_hwstamp = eqos_get_rx_hwstamp;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#define RDES3_CTXT OSI_BIT(30)
|
||||
#define RDES3_IOC OSI_BIT(30)
|
||||
#define RDES3_B1V OSI_BIT(24)
|
||||
#define RDES3_CDA OSI_BIT(27)
|
||||
#define RDES3_LD OSI_BIT(28)
|
||||
#define RDES3_FD OSI_BIT(29)
|
||||
#define RDES3_ERR_CRC OSI_BIT(24)
|
||||
@@ -50,14 +51,16 @@
|
||||
#define RDES3_RS0V OSI_BIT(25)
|
||||
#define RDES3_RS1V OSI_BIT(26)
|
||||
#define RDES3_RSV OSI_BIT(26)
|
||||
#define RDES0_OVT 0x0000FFFFU
|
||||
#define RDES3_TSD OSI_BIT(6)
|
||||
#define RDES3_TSA OSI_BIT(4)
|
||||
#define RDES1_TSA OSI_BIT(14)
|
||||
#define RDES1_TD OSI_BIT(15)
|
||||
#define RDES3_L34T 0x00F00000U
|
||||
#define RDES3_L34T_IPV4_TCP OSI_BIT(20)
|
||||
#define RDES3_L34T_IPV4_UDP OSI_BIT(21)
|
||||
#define RDES3_L34T_IPV6_TCP (OSI_BIT(23) | OSI_BIT(20))
|
||||
#define RDES3_L34T_IPV6_UDP (OSI_BIT(23) | OSI_BIT(21))
|
||||
#define RDES0_OVT 0x0000FFFFU
|
||||
#define RDES1_TSA OSI_BIT(14)
|
||||
#define RDES1_TD OSI_BIT(15)
|
||||
|
||||
#define RDES1_IPCE OSI_BIT(7)
|
||||
#define RDES1_IPCB OSI_BIT(6)
|
||||
@@ -96,6 +99,7 @@
|
||||
#define TDES3_TCMSSV OSI_BIT(26)
|
||||
#define TDES3_FD OSI_BIT(29)
|
||||
#define TDES3_LD OSI_BIT(28)
|
||||
#define TDES3_OSTC OSI_BIT(27)
|
||||
#define TDES3_TSE OSI_BIT(18)
|
||||
#define TDES3_HW_CIC_ALL (OSI_BIT(16) | OSI_BIT(17))
|
||||
#define TDES3_HW_CIC_IP_ONLY (OSI_BIT(16))
|
||||
@@ -106,6 +110,7 @@
|
||||
#define TDES3_THL_SHIFT 19U
|
||||
#define TDES3_VLTV OSI_BIT(16)
|
||||
#define TDES3_TTSS OSI_BIT(17)
|
||||
#define TDES3_PIDV OSI_BIT(25)
|
||||
|
||||
/* Tx Errors */
|
||||
#define TDES3_IP_HEADER_ERR OSI_BIT(0)
|
||||
|
||||
@@ -132,10 +132,73 @@ static void mgbe_get_rx_hash(struct osi_rx_desc *rx_desc,
|
||||
rx_pkt_cx->flags |= OSI_PKT_CX_RSS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief mgbe_get_rx_hwstamp - Get Rx HW Time stamp
|
||||
*
|
||||
* Algorithm:
|
||||
* 1) Check for TS availability.
|
||||
* 2) call get_tx_tstamp_status if TS is valid or not.
|
||||
* 3) If yes, set a bit and update nano seconds in rx_pkt_cx so that OSD
|
||||
* layer can extract the time by checking this bit.
|
||||
*
|
||||
* @param[in] rx_desc: Rx descriptor
|
||||
* @param[in] context_desc: Rx context descriptor
|
||||
* @param[in] rx_pkt_cx: Rx packet context
|
||||
*
|
||||
* @retval -1 if TimeStamp is not available
|
||||
* @retval 0 if TimeStamp is available.
|
||||
*/
|
||||
static int mgbe_get_rx_hwstamp(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_desc *context_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx)
|
||||
{
|
||||
int retry;
|
||||
|
||||
if ((rx_desc->rdes3 & RDES3_CDA) != RDES3_CDA) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (retry = 0; retry < 10; retry++) {
|
||||
if (((context_desc->rdes3 & RDES3_OWN) == 0U) &&
|
||||
((context_desc->rdes3 & RDES3_CTXT) == RDES3_CTXT) &&
|
||||
((context_desc->rdes3 & RDES3_TSA) == RDES3_TSA) &&
|
||||
((context_desc->rdes3 & RDES3_TSD) != RDES3_TSD)) {
|
||||
if ((context_desc->rdes0 == OSI_INVALID_VALUE) &&
|
||||
(context_desc->rdes1 == OSI_INVALID_VALUE)) {
|
||||
/* Invalid time stamp */
|
||||
return -1;
|
||||
}
|
||||
/* Update rx pkt context flags to indicate PTP */
|
||||
rx_pkt_cx->flags |= OSI_PKT_CX_PTP;
|
||||
/* Time Stamp can be read */
|
||||
break;
|
||||
} else {
|
||||
/* TS not available yet, so retrying */
|
||||
osi_dma->osd_ops.udelay(OSI_DELAY_1US);
|
||||
}
|
||||
}
|
||||
|
||||
if (retry == 10) {
|
||||
/* Timed out waiting for Rx timestamp */
|
||||
return -1;
|
||||
}
|
||||
|
||||
rx_pkt_cx->ns = context_desc->rdes0 +
|
||||
(OSI_NSEC_PER_SEC * context_desc->rdes1);
|
||||
if (rx_pkt_cx->ns < context_desc->rdes0) {
|
||||
/* Will not hit this case */
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mgbe_init_desc_ops(struct desc_ops *d_ops)
|
||||
{
|
||||
d_ops->get_rx_csum = mgbe_get_rx_csum;
|
||||
d_ops->update_rx_err_stats = mgbe_update_rx_err_stats;
|
||||
d_ops->get_rx_vlan = mgbe_get_rx_vlan;
|
||||
d_ops->get_rx_hash = mgbe_get_rx_hash;
|
||||
d_ops->get_rx_hwstamp = mgbe_get_rx_hwstamp;
|
||||
}
|
||||
|
||||
@@ -23,6 +23,17 @@
|
||||
#ifndef INCLUDED_MGBE_DMA_H
|
||||
#define INCLUDED_MGBE_DMA_H
|
||||
|
||||
/**
|
||||
* @@addtogroup Timestamp Capture Register
|
||||
* @brief MGBE MAC Timestamp Register offset
|
||||
* @{
|
||||
*/
|
||||
#define MGBE_MAC_TSS 0X0D20
|
||||
#define MGBE_MAC_TS_NSEC 0x0D30
|
||||
#define MGBE_MAC_TS_SEC 0x0D34
|
||||
#define MGBE_MAC_TS_PID 0x0D38
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @addtogroup MGBE_DMA DMA Channel Register offsets
|
||||
*
|
||||
@@ -95,4 +106,24 @@
|
||||
#define MGBE_VIRT_INTR_CHX_CNTRL_TX OSI_BIT(0)
|
||||
#define MGBE_VIRT_INTR_CHX_CNTRL_RX OSI_BIT(1)
|
||||
/** @} */
|
||||
#endif /* INCLUDED_MGBE_DMA_H */
|
||||
|
||||
/**
|
||||
* @addtogroup MGBE MAC timestamp registers bit field.
|
||||
*
|
||||
* @brief Values defined for the MGBE timestamp registers
|
||||
* @{
|
||||
*/
|
||||
#define MGBE_MAC_TSS_TXTSC OSI_BIT(15)
|
||||
#define MGBE_MAC_TS_PID_MASK 0x3FFU
|
||||
#define MGBE_MAC_TS_NSEC_MASK 0x7FFFFFFFU
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief mgbe_get_dma_chan_ops - MGBE get DMA channel operations
|
||||
*
|
||||
* Algorithm: Returns pointer DMA channel operations structure.
|
||||
*
|
||||
* @returns Pointer to DMA channel operations structure
|
||||
*/
|
||||
struct osi_dma_chan_ops *mgbe_get_dma_chan_ops(void);
|
||||
#endif
|
||||
|
||||
@@ -44,6 +44,10 @@ struct desc_ops {
|
||||
/** Called to get rx HASH from descriptor */
|
||||
void (*get_rx_hash)(struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx);
|
||||
/** Called to get RX hw timestamp */
|
||||
int (*get_rx_hwstamp)(struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_desc *context_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -25,119 +25,10 @@
|
||||
#include "../osi/common/type.h"
|
||||
#include "hw_desc.h"
|
||||
#include "../osi/common/common.h"
|
||||
#include "mgbe_dma.h"
|
||||
|
||||
static struct desc_ops d_ops;
|
||||
|
||||
/**
|
||||
* @brief get_rx_tstamp_status - Get Tx Time stamp status
|
||||
*
|
||||
* @note
|
||||
* Algorithm:
|
||||
* - Check if the received descriptor is a context descriptor.
|
||||
* - If yes, check whether the time stamp is valid or not.
|
||||
*
|
||||
* @param[in] context_desc: Rx context descriptor
|
||||
*
|
||||
* @note
|
||||
* API Group:
|
||||
* - Initialization: No
|
||||
* - Run time: Yes
|
||||
* - De-initialization: No
|
||||
*
|
||||
* @retval -1 if TimeStamp is not valid
|
||||
* @retval 0 if TimeStamp is valid.
|
||||
*/
|
||||
static inline nve32_t get_rx_tstamp_status(struct osi_rx_desc *context_desc)
|
||||
{
|
||||
if (((context_desc->rdes3 & RDES3_OWN) != RDES3_OWN) &&
|
||||
((context_desc->rdes3 & RDES3_CTXT) == RDES3_CTXT)) {
|
||||
if (((context_desc->rdes0 == OSI_INVALID_VALUE) &&
|
||||
(context_desc->rdes1 == OSI_INVALID_VALUE))) {
|
||||
/* Invalid time stamp */
|
||||
return -1;
|
||||
}
|
||||
/* tstamp can be read */
|
||||
return 0;
|
||||
}
|
||||
/* Busy */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_rx_hwstamp - Get Rx HW Time stamp
|
||||
*
|
||||
* @note
|
||||
* Algorithm:
|
||||
* - Check for TS availability.
|
||||
* - call get_tx_tstamp_status if TS is valid or not.
|
||||
* - If yes, set a bit and update nano seconds in rx_pkt_cx so that OSD
|
||||
* layer can extract the time by checking this bit.
|
||||
*
|
||||
* @param[in] osi_dma: OSI private data structure.
|
||||
* @param[in] rx_desc: Rx descriptor
|
||||
* @param[in] context_desc: Rx context descriptor
|
||||
* @param[in, out] rx_pkt_cx: Rx packet context
|
||||
*
|
||||
* @note
|
||||
* API Group:
|
||||
* - Initialization: No
|
||||
* - Run time: Yes
|
||||
* - De-initialization: No
|
||||
*
|
||||
* @retval -1 if TimeStamp is not available
|
||||
* @retval 0 if TimeStamp is available.
|
||||
*/
|
||||
static nve32_t get_rx_hwstamp(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_rx_desc *rx_desc,
|
||||
struct osi_rx_desc *context_desc,
|
||||
struct osi_rx_pkt_cx *rx_pkt_cx)
|
||||
{
|
||||
nve32_t retry, ret = -1;
|
||||
|
||||
/* Check for RS1V/TSA/TD valid */
|
||||
if (((rx_desc->rdes3 & RDES3_RS1V) == RDES3_RS1V) &&
|
||||
((rx_desc->rdes1 & RDES1_TSA) == RDES1_TSA) &&
|
||||
((rx_desc->rdes1 & RDES1_TD) != RDES1_TD)) {
|
||||
for (retry = 0; retry < 10; retry++) {
|
||||
ret = get_rx_tstamp_status(context_desc);
|
||||
if (ret == 0) {
|
||||
/* Update rx pkt context flags to indicate PTP */
|
||||
rx_pkt_cx->flags |= OSI_PKT_CX_PTP;
|
||||
/* Time Stamp can be read */
|
||||
break;
|
||||
} else if (ret != -2) {
|
||||
/* Failed to get Rx timestamp */
|
||||
return ret;
|
||||
} else {
|
||||
/* Do nothing here */
|
||||
}
|
||||
/* TS not available yet, so retrying */
|
||||
osi_dma->osd_ops.udelay(1U);
|
||||
}
|
||||
if (ret != 0) {
|
||||
/* Timed out waiting for Rx timestamp */
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (OSI_NSEC_PER_SEC > (OSI_ULLONG_MAX / context_desc->rdes1)) {
|
||||
/* Will not hit this case */
|
||||
} else if ((OSI_ULLONG_MAX -
|
||||
(context_desc->rdes1 * OSI_NSEC_PER_SEC)) <
|
||||
context_desc->rdes0) {
|
||||
/* Will not hit this case */
|
||||
} else {
|
||||
rx_pkt_cx->ns = context_desc->rdes0 +
|
||||
(OSI_NSEC_PER_SEC * context_desc->rdes1);
|
||||
}
|
||||
|
||||
if (rx_pkt_cx->ns < context_desc->rdes0) {
|
||||
/* Will not hit this case */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_rx_err_stats - Detect Errors from Rx Descriptor
|
||||
*
|
||||
@@ -339,8 +230,8 @@ nve32_t osi_process_rx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
|
||||
context_desc = rx_ring->rx_desc + rx_ring->cur_rx_idx;
|
||||
/* Get rx time stamp */
|
||||
ret = get_rx_hwstamp(osi_dma, rx_desc, context_desc,
|
||||
rx_pkt_cx);
|
||||
ret =d_ops.get_rx_hwstamp(osi_dma, rx_desc,
|
||||
context_desc, rx_pkt_cx);
|
||||
if (ret == 0) {
|
||||
ptp_rx_swcx = rx_ring->rx_swcx +
|
||||
rx_ring->cur_rx_idx;
|
||||
@@ -616,8 +507,121 @@ static inline nve32_t validate_tx_completions_arg(
|
||||
return 0;
|
||||
}
|
||||
|
||||
nve32_t osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
nveu32_t chan, nve32_t budget)
|
||||
/**
|
||||
* @brief poll_for_ts_update - Poll for TXTSC bit set for timestamp capture
|
||||
*
|
||||
* Algorithm: This routine will be invoked by get_mac_tx_timestamp to poll
|
||||
* on TXTSC bit to get set or timedout.
|
||||
*
|
||||
* @param[in] addr: Base address
|
||||
* @param[in] chan: Current counter value
|
||||
*
|
||||
* @retval -1 on failure
|
||||
* @retval 0 on success
|
||||
*/
|
||||
static inline int poll_for_ts_update(struct osi_dma_priv_data *osi_dma,
|
||||
unsigned int *count)
|
||||
{
|
||||
unsigned int retry = OSI_POLL_COUNT;
|
||||
unsigned int val = 0U;
|
||||
|
||||
while (*count < retry) {
|
||||
/* Read and Check TXTSC in MAC_Timestamp_Control register */
|
||||
val = osi_readl((unsigned char *)osi_dma->base +
|
||||
MGBE_MAC_TSS);
|
||||
if ((val & MGBE_MAC_TSS_TXTSC) == MGBE_MAC_TSS_TXTSC) {
|
||||
return 0;
|
||||
}
|
||||
(*count)++;
|
||||
osi_dma->osd_ops.udelay(OSI_DELAY_1US);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief get_mac_tx_timestamp - get TX timestamp from timestamp capture
|
||||
* registers
|
||||
*
|
||||
* Algorithm: This routine will be invoked on TX_DONE interrupt and if hw
|
||||
* timestamp capture enabled for that descriptor. SW will check for Packet
|
||||
* id maching with dma channel number as for same DMA all tx are FIFO. If match
|
||||
* update hwtimestamp into local variables.
|
||||
*
|
||||
* @param[in] osi: OSI private data structure.
|
||||
* @param[in] tx_desc: Pointer to tranmit descriptor.
|
||||
* @param[out] txdone_pkt_cx: Pointer to txdone packet descriptor to be filled
|
||||
* @param[in] chan: Rx channel number.
|
||||
*
|
||||
*/
|
||||
static void get_mac_tx_timestamp(struct osi_dma_priv_data *osi_dma,
|
||||
struct osi_tx_desc *tx_desc,
|
||||
struct osi_txdone_pkt_cx *txdone_pkt_cx,
|
||||
unsigned int chan)
|
||||
{
|
||||
unsigned char *addr = (unsigned char *)osi_dma->base;
|
||||
int ret = -1;
|
||||
int found = 1;
|
||||
unsigned int count = 0;
|
||||
unsigned long long var = 0;
|
||||
|
||||
ret = poll_for_ts_update(osi_dma, &count);
|
||||
if (ret < 0) {
|
||||
OSI_DMA_ERR(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||
"timestamp done failed\n", 0ULL);
|
||||
found = 0;
|
||||
}
|
||||
|
||||
/* check if pkt id is also correct for pkt. current implemtation
|
||||
* use dma channel index as pktid, we will use pktid from index 0 to
|
||||
* max DMA channels -1 */
|
||||
while (found == 1) {
|
||||
if (((osi_readl(addr + MGBE_MAC_TS_PID) &
|
||||
MGBE_MAC_TS_PID_MASK) == chan)) {
|
||||
txdone_pkt_cx->flags |= OSI_TXDONE_CX_TS;
|
||||
txdone_pkt_cx->ns = osi_readl(addr + MGBE_MAC_TS_NSEC);
|
||||
txdone_pkt_cx->ns &= MGBE_MAC_TS_NSEC_MASK;
|
||||
var = osi_readl(addr + MGBE_MAC_TS_SEC);
|
||||
if (OSI_NSEC_PER_SEC > (OSI_ULLONG_MAX / var)) {
|
||||
/* Will not hit this case */
|
||||
} else if ((OSI_ULLONG_MAX - (var * OSI_NSEC_PER_SEC)) <
|
||||
txdone_pkt_cx->ns) {
|
||||
/* Will not hit this case */
|
||||
} else {
|
||||
txdone_pkt_cx->ns += var * OSI_NSEC_PER_SEC;
|
||||
}
|
||||
|
||||
found = 0;
|
||||
} else {
|
||||
OSI_DMA_INFO(OSI_NULL, OSI_LOG_ARG_HW_FAIL,
|
||||
"packet ID mismatch \n", 0ULL);
|
||||
ret = poll_for_ts_update(osi_dma, &count);
|
||||
if (ret < 0) {
|
||||
found = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief is_ptp_twostep_or_slave_mode - check for dut in ptp 2step or slave
|
||||
* mode
|
||||
*
|
||||
* @param[in] ptp_flag: osi statructure variable to identify current ptp
|
||||
* configuration
|
||||
*
|
||||
* @retval 1 if condition is true
|
||||
* @retval 0 if condition is false.
|
||||
*/
|
||||
static inline unsigned int is_ptp_twostep_or_slave_mode(unsigned int ptp_flag)
|
||||
{
|
||||
return (((ptp_flag & OSI_PTP_SYNC_SLAVE) == OSI_PTP_SYNC_SLAVE) ||
|
||||
((ptp_flag & OSI_PTP_SYNC_TWOSTEP) == OSI_PTP_SYNC_TWOSTEP)) ?
|
||||
OSI_ENABLE : OSI_DISABLE;
|
||||
}
|
||||
|
||||
int osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
unsigned int chan, int budget)
|
||||
{
|
||||
struct osi_tx_ring *tx_ring = OSI_NULL;
|
||||
struct osi_txdone_pkt_cx *txdone_pkt_cx = OSI_NULL;
|
||||
@@ -690,9 +694,19 @@ nve32_t osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
} else {
|
||||
/* Do nothing here */
|
||||
}
|
||||
} else if (((tx_swcx->flags & OSI_PKT_CX_PTP) ==
|
||||
OSI_PKT_CX_PTP) &&
|
||||
// if not master in onestep mode
|
||||
(is_ptp_twostep_or_slave_mode(osi_dma->ptp_flag) ==
|
||||
OSI_ENABLE) &&
|
||||
((tx_desc->tdes3 & TDES3_CTXT) == 0U)) {
|
||||
get_mac_tx_timestamp(osi_dma, tx_desc, txdone_pkt_cx, chan);
|
||||
} else {
|
||||
/* Do nothing here */
|
||||
}
|
||||
|
||||
if (tx_swcx->is_paged_buf == 1U) {
|
||||
if ((tx_swcx->flags & OSI_PKT_CX_PAGED_BUF) ==
|
||||
OSI_PKT_CX_PAGED_BUF) {
|
||||
txdone_pkt_cx->flags |= OSI_TXDONE_CX_PAGED_BUF;
|
||||
}
|
||||
|
||||
@@ -718,7 +732,7 @@ nve32_t osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
|
||||
tx_swcx->buf_virt_addr = OSI_NULL;
|
||||
tx_swcx->buf_phy_addr = 0;
|
||||
tx_swcx->is_paged_buf = 0;
|
||||
tx_swcx->flags = 0;
|
||||
INCR_TX_DESC_INDEX(entry, 1U);
|
||||
|
||||
/* Don't wait to update tx_ring->clean-idx. It will
|
||||
@@ -743,6 +757,8 @@ nve32_t osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
*
|
||||
* @param[in, out] tx_pkt_cx: Pointer to transmit packet context structure
|
||||
* @param[in, out] tx_desc: Pointer to transmit descriptor to be filled.
|
||||
* @param[in] sync_mode: PTP sync mode to indetify.
|
||||
* @param[in] mac: HW MAC ver
|
||||
*
|
||||
* @note
|
||||
* API Group:
|
||||
@@ -753,40 +769,85 @@ nve32_t osi_process_tx_completions(struct osi_dma_priv_data *osi_dma,
|
||||
* @retval 0 - cntx desc not used
|
||||
* @retval 1 - cntx desc used.
|
||||
*/
|
||||
|
||||
static inline nve32_t need_cntx_desc(struct osi_tx_pkt_cx *tx_pkt_cx,
|
||||
struct osi_tx_desc *tx_desc)
|
||||
struct osi_tx_desc *tx_desc,
|
||||
unsigned int ptp_sync_flag,
|
||||
unsigned int mac)
|
||||
{
|
||||
nve32_t ret = 0;
|
||||
|
||||
if (((tx_pkt_cx->flags & OSI_PKT_CX_VLAN) == OSI_PKT_CX_VLAN) ||
|
||||
((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO)) {
|
||||
/* Set context type */
|
||||
tx_desc->tdes3 |= TDES3_CTXT;
|
||||
((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) ||
|
||||
((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP)) {
|
||||
|
||||
if ((tx_pkt_cx->flags & OSI_PKT_CX_VLAN) == OSI_PKT_CX_VLAN) {
|
||||
/* Set context type */
|
||||
tx_desc->tdes3 |= TDES3_CTXT;
|
||||
/* Remove any overflow bits. VT field is 16bit field */
|
||||
tx_pkt_cx->vtag_id &= TDES3_VT_MASK;
|
||||
/* Fill VLAN Tag ID */
|
||||
tx_desc->tdes3 |= tx_pkt_cx->vtag_id;
|
||||
/* Set VLAN TAG Valid */
|
||||
tx_desc->tdes3 |= TDES3_VLTV;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if ((tx_pkt_cx->flags & OSI_PKT_CX_TSO) == OSI_PKT_CX_TSO) {
|
||||
/* Set context type */
|
||||
tx_desc->tdes3 |= TDES3_CTXT;
|
||||
/* Remove any overflow bits. MSS is 13bit field */
|
||||
tx_pkt_cx->mss &= TDES2_MSS_MASK;
|
||||
/* Fill MSS */
|
||||
tx_desc->tdes2 |= tx_pkt_cx->mss;
|
||||
/* Set MSS valid */
|
||||
tx_desc->tdes3 |= TDES3_TCMSSV;
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
/* This part of code must be at the end of function */
|
||||
if ((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP) {
|
||||
if ((mac == OSI_MAC_HW_EQOS) &&
|
||||
((ptp_sync_flag & OSI_PTP_SYNC_TWOSTEP) ==
|
||||
OSI_PTP_SYNC_TWOSTEP)){
|
||||
/* return the current ret value */
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set context type */
|
||||
tx_desc->tdes3 |= TDES3_CTXT;
|
||||
/* in case of One-step sync */
|
||||
if ((ptp_sync_flag & OSI_PTP_SYNC_ONESTEP) ==
|
||||
OSI_PTP_SYNC_ONESTEP) {
|
||||
/* Set TDES3_OSTC */
|
||||
tx_desc->tdes3 |= TDES3_OSTC;
|
||||
tx_desc->tdes3 &= ~TDES3_TCMSSV;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief is_ptp_onestep_and_master_mode - check for dut is in master and
|
||||
* onestep mode
|
||||
*
|
||||
* @param[in] ptp_flag: osi statructure variable to identify current ptp
|
||||
* configuration
|
||||
*
|
||||
* @retval 1 if condition is true
|
||||
* @retval 0 if condition is false.
|
||||
*/
|
||||
static inline unsigned int is_ptp_onestep_and_master_mode(unsigned int ptp_flag)
|
||||
{
|
||||
return (((ptp_flag & OSI_PTP_SYNC_MASTER) == OSI_PTP_SYNC_MASTER) &&
|
||||
((ptp_flag & OSI_PTP_SYNC_ONESTEP) == OSI_PTP_SYNC_ONESTEP)) ?
|
||||
OSI_ENABLE : OSI_DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fill_first_desc - Helper function to fill the first transmit
|
||||
* descriptor.
|
||||
@@ -812,7 +873,8 @@ static inline nve32_t need_cntx_desc(struct osi_tx_pkt_cx *tx_pkt_cx,
|
||||
static inline void fill_first_desc(struct osi_tx_ring *tx_ring,
|
||||
struct osi_tx_pkt_cx *tx_pkt_cx,
|
||||
struct osi_tx_desc *tx_desc,
|
||||
struct osi_tx_swcx *tx_swcx)
|
||||
struct osi_tx_swcx *tx_swcx,
|
||||
unsigned int ptp_flag)
|
||||
{
|
||||
nveu64_t tmp;
|
||||
|
||||
@@ -850,6 +912,12 @@ static inline void fill_first_desc(struct osi_tx_ring *tx_ring,
|
||||
/* if TS is set enable timestamping */
|
||||
if ((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP) {
|
||||
tx_desc->tdes2 |= TDES2_TTSE;
|
||||
tx_swcx->flags |= OSI_PKT_CX_PTP;
|
||||
//ptp master mode in one step sync
|
||||
if (is_ptp_onestep_and_master_mode(ptp_flag) ==
|
||||
OSI_ENABLE) {
|
||||
tx_desc->tdes2 &= ~TDES2_TTSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* if LEN bit is set, update packet payload len */
|
||||
@@ -954,19 +1022,28 @@ nve32_t hw_transmit(struct osi_dma_priv_data *osi_dma,
|
||||
1UL);
|
||||
}
|
||||
|
||||
cntx_desc_consumed = need_cntx_desc(tx_pkt_cx, tx_desc);
|
||||
cntx_desc_consumed = need_cntx_desc(tx_pkt_cx, tx_desc, osi_dma->ptp_flag,
|
||||
osi_dma->mac);
|
||||
if (cntx_desc_consumed == 1) {
|
||||
if (((tx_pkt_cx->flags & OSI_PKT_CX_PTP) == OSI_PKT_CX_PTP) &&
|
||||
(osi_dma->mac == OSI_MAC_HW_MGBE)) {
|
||||
/* mark packet id valid */
|
||||
tx_desc->tdes3 |= TDES3_PIDV;
|
||||
/* Packet id */
|
||||
tx_desc->tdes0 = chan;
|
||||
}
|
||||
INCR_TX_DESC_INDEX(entry, 1U);
|
||||
|
||||
/* Storing context descriptor to set DMA_OWN at last */
|
||||
cx_desc = tx_desc;
|
||||
tx_desc = tx_ring->tx_desc + entry;
|
||||
tx_swcx = tx_ring->tx_swcx + entry;
|
||||
|
||||
desc_cnt--;
|
||||
}
|
||||
|
||||
/* Fill first descriptor */
|
||||
fill_first_desc(tx_ring, tx_pkt_cx, tx_desc, tx_swcx);
|
||||
fill_first_desc(tx_ring, tx_pkt_cx, tx_desc, tx_swcx, osi_dma->ptp_flag);
|
||||
|
||||
INCR_TX_DESC_INDEX(entry, 1U);
|
||||
|
||||
@@ -1262,7 +1339,7 @@ static nve32_t tx_dma_desc_init(struct osi_dma_priv_data *osi_dma,
|
||||
tx_swcx->len = 0;
|
||||
tx_swcx->buf_virt_addr = OSI_NULL;
|
||||
tx_swcx->buf_phy_addr = 0;
|
||||
tx_swcx->is_paged_buf = 0;
|
||||
tx_swcx->flags = 0;
|
||||
}
|
||||
|
||||
tx_ring->cur_tx_idx = 0;
|
||||
|
||||
Reference in New Issue
Block a user