net: dsa: microchip: ptp: Initial hardware time stamping support
This patch adds the routine for get_ts_info, hwstamp_get, set. This enables the PTP support towards userspace applications such as linuxptp. Signed-off-by: Christian Eggers <ceggers@arri.de> Co-developed-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: Arun Ramadoss <arun.ramadoss@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
eac1ea2026
commit
c59e12a140
@ -2977,6 +2977,9 @@ static const struct dsa_switch_ops ksz_switch_ops = {
|
||||
.get_pause_stats = ksz_get_pause_stats,
|
||||
.port_change_mtu = ksz_change_mtu,
|
||||
.port_max_mtu = ksz_max_mtu,
|
||||
.get_ts_info = ksz_get_ts_info,
|
||||
.port_hwtstamp_get = ksz_hwtstamp_get,
|
||||
.port_hwtstamp_set = ksz_hwtstamp_set,
|
||||
};
|
||||
|
||||
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
|
||||
|
@ -102,6 +102,9 @@ struct ksz_port {
|
||||
struct ksz_device *ksz_dev;
|
||||
struct ksz_irq pirq;
|
||||
u8 num;
|
||||
#if IS_ENABLED(CONFIG_NET_DSA_MICROCHIP_KSZ_PTP)
|
||||
struct hwtstamp_config tstamp_config;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct ksz_device {
|
||||
|
@ -24,6 +24,107 @@
|
||||
#define KSZ_PTP_INC_NS 40ULL /* HW clock is incremented every 40 ns (by 40) */
|
||||
#define KSZ_PTP_SUBNS_BITS 32
|
||||
|
||||
/* The function is return back the capability of timestamping feature when
|
||||
* requested through ethtool -T <interface> utility
|
||||
*/
|
||||
int ksz_get_ts_info(struct dsa_switch *ds, int port, struct ethtool_ts_info *ts)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct ksz_ptp_data *ptp_data;
|
||||
|
||||
ptp_data = &dev->ptp_data;
|
||||
|
||||
if (!ptp_data->clock)
|
||||
return -ENODEV;
|
||||
|
||||
ts->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RX_HARDWARE |
|
||||
SOF_TIMESTAMPING_RAW_HARDWARE;
|
||||
|
||||
ts->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ONESTEP_P2P);
|
||||
|
||||
ts->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
|
||||
BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
|
||||
BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
|
||||
BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
|
||||
|
||||
ts->phc_index = ptp_clock_index(ptp_data->clock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksz_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct hwtstamp_config *config;
|
||||
struct ksz_port *prt;
|
||||
|
||||
prt = &dev->ports[port];
|
||||
config = &prt->tstamp_config;
|
||||
|
||||
return copy_to_user(ifr->ifr_data, config, sizeof(*config)) ?
|
||||
-EFAULT : 0;
|
||||
}
|
||||
|
||||
static int ksz_set_hwtstamp_config(struct ksz_device *dev,
|
||||
struct hwtstamp_config *config)
|
||||
{
|
||||
if (config->flags)
|
||||
return -EINVAL;
|
||||
|
||||
switch (config->tx_type) {
|
||||
case HWTSTAMP_TX_OFF:
|
||||
case HWTSTAMP_TX_ONESTEP_P2P:
|
||||
break;
|
||||
default:
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
switch (config->rx_filter) {
|
||||
case HWTSTAMP_FILTER_NONE:
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
|
||||
break;
|
||||
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||
config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
|
||||
break;
|
||||
default:
|
||||
config->rx_filter = HWTSTAMP_FILTER_NONE;
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksz_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
struct hwtstamp_config config;
|
||||
struct ksz_port *prt;
|
||||
int ret;
|
||||
|
||||
prt = &dev->ports[port];
|
||||
|
||||
ret = copy_from_user(&config, ifr->ifr_data, sizeof(config));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ksz_set_hwtstamp_config(dev, &config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
memcpy(&prt->tstamp_config, &config, sizeof(config));
|
||||
|
||||
return copy_to_user(ifr->ifr_data, &config, sizeof(config));
|
||||
}
|
||||
|
||||
static int _ksz_ptp_gettime(struct ksz_device *dev, struct timespec64 *ts)
|
||||
{
|
||||
u32 nanoseconds;
|
||||
|
@ -23,6 +23,11 @@ int ksz_ptp_clock_register(struct dsa_switch *ds);
|
||||
|
||||
void ksz_ptp_clock_unregister(struct dsa_switch *ds);
|
||||
|
||||
int ksz_get_ts_info(struct dsa_switch *ds, int port,
|
||||
struct ethtool_ts_info *ts);
|
||||
int ksz_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
int ksz_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
|
||||
|
||||
#else
|
||||
|
||||
struct ksz_ptp_data {
|
||||
@ -37,6 +42,12 @@ static inline int ksz_ptp_clock_register(struct dsa_switch *ds)
|
||||
|
||||
static inline void ksz_ptp_clock_unregister(struct dsa_switch *ds) { }
|
||||
|
||||
#define ksz_get_ts_info NULL
|
||||
|
||||
#define ksz_hwtstamp_get NULL
|
||||
|
||||
#define ksz_hwtstamp_set NULL
|
||||
|
||||
#endif /* End of CONFIG_NET_DSA_MICROCHIP_KSZ_PTP */
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user