diff --git a/drivers/Kconfig b/drivers/Kconfig index 8301822e73b..ef19b270eca 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -53,6 +53,8 @@ source "drivers/watchdog/Kconfig" source "drivers/clock_control/Kconfig" +source "drivers/ptp_clock/Kconfig" + source "drivers/ipm/Kconfig" source "drivers/aio/Kconfig" diff --git a/drivers/ptp_clock/Kconfig b/drivers/ptp_clock/Kconfig new file mode 100644 index 00000000000..e6067358740 --- /dev/null +++ b/drivers/ptp_clock/Kconfig @@ -0,0 +1,11 @@ +# +# Copyright (c) 2018 Intel Corporation. +# +# SPDX-License-Identifier: Apache-2.0 +# + +menuconfig PTP_CLOCK + bool "Precision Time Protocol Clock driver support" + default n + help + Enable options for Precision Time Protocol Clock drivers. diff --git a/include/net/ethernet.h b/include/net/ethernet.h index be892b85dc5..39af7abd4e5 100644 --- a/include/net/ethernet.h +++ b/include/net/ethernet.h @@ -71,6 +71,9 @@ enum ethernet_hw_caps { /** Changing duplex (half/full) supported */ ETHERNET_DUPLEX_SET = BIT(7), + + /** IEEE 802.1AS (gPTP) clock supported */ + ETHERNET_PTP = BIT(8), }; enum ethernet_config_type { @@ -129,6 +132,11 @@ struct ethernet_api { int (*vlan_setup)(struct device *dev, struct net_if *iface, u16_t tag, bool enable); #endif /* CONFIG_NET_VLAN */ + +#if defined(CONFIG_PTP_CLOCK) + /** Return ptp_clock device that is tied to this ethernet device */ + struct device *(*get_ptp_clock)(struct device *eth_dev); +#endif /* CONFIG_PTP_CLOCK */ }; struct net_eth_hdr { @@ -406,6 +414,16 @@ void net_eth_carrier_on(struct net_if *iface); */ void net_eth_carrier_off(struct net_if *iface); +/** + * @brief Return PTP clock that is tied to this ethernet network interface. + * + * @param iface Network interface + * + * @return Pointer to PTP clock if found, NULL if not found or if this + * ethernet interface does not support PTP. + */ +struct device *net_eth_get_ptp_clock(struct net_if *iface); + #ifdef __cplusplus } #endif diff --git a/include/ptp_clock.h b/include/ptp_clock.h new file mode 100644 index 00000000000..7e56142521c --- /dev/null +++ b/include/ptp_clock.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _PTP_CLOCK_H_ +#define _PTP_CLOCK_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Name of the PTP clock driver */ +#if !defined(PTP_CLOCK_NAME) +#define PTP_CLOCK_NAME "PTP_CLOCK" +#endif + +struct ptp_clock_driver_api { + int (*set)(struct device *dev, struct net_ptp_time *tm); + int (*get)(struct device *dev, struct net_ptp_time *tm); + int (*adjust)(struct device *dev, int increment); + int (*rate_adjust)(struct device *dev, float ratio); +}; + +/** + * @brief Set the time of the PTP clock. + * + * @param dev PTP clock device + * @param tm Time to set + * + * @return 0 if ok, <0 if error + */ +static inline int ptp_clock_set(struct device *dev, struct net_ptp_time *tm) +{ + const struct ptp_clock_driver_api *api = dev->driver_api; + + return api->set(dev, tm); +} + +/** + * @brief Get the time of the PTP clock. + * + * @param dev PTP clock device + * @param tm Where to store the current time. + * + * @return 0 if ok, <0 if error + */ +static inline int ptp_clock_get(struct device *dev, struct net_ptp_time *tm) +{ + const struct ptp_clock_driver_api *api = dev->driver_api; + + return api->get(dev, tm); +} + +/** + * @brief Adjust the PTP clock time. + * + * @param dev PTP clock device + * @param increment Increment of the clock in nanoseconds + * + * @return 0 if ok, <0 if error + */ +static inline int ptp_clock_adjust(struct device *dev, int increment) +{ + const struct ptp_clock_driver_api *api = dev->driver_api; + + return api->adjust(dev, increment); +} + +/** + * @brief Adjust the PTP clock time change rate when compared to its neighbor. + * + * @param dev PTP clock device + * @param rate Rate of the clock time change + * + * @return 0 if ok, <0 if error + */ +static inline int ptp_clock_rate_adjust(struct device *dev, float rate) +{ + const struct ptp_clock_driver_api *api = dev->driver_api; + + return api->rate_adjust(dev, rate); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __PTP_CLOCK_H__ */ diff --git a/subsys/net/ip/l2/ethernet/ethernet.c b/subsys/net/ip/l2/ethernet/ethernet.c index 0f89a84e80f..e4ee8f410ad 100644 --- a/subsys/net/ip/l2/ethernet/ethernet.c +++ b/subsys/net/ip/l2/ethernet/ethernet.c @@ -801,6 +801,26 @@ void net_eth_carrier_off(struct net_if *iface) handle_carrier(ctx, iface, carrier_off); } +struct device *net_eth_get_ptp_clock(struct net_if *iface) +{ +#if defined(CONFIG_PTP_CLOCK) + struct device *dev = net_if_get_device(iface); + const struct ethernet_api *api = dev->driver_api; + + if (net_if_l2(iface) != &NET_L2_GET_NAME(ETHERNET)) { + return NULL; + } + + if (!(api->get_capabilities(dev) & ETHERNET_PTP)) { + return NULL; + } + + return api->get_ptp_clock(net_if_get_device(iface)); +#else + return NULL; +#endif +} + void ethernet_init(struct net_if *iface) { struct ethernet_context *ctx = net_if_l2_data(iface);