@@ -7,6 +7,7 @@
#ifndef __KSZ_COMMON_H
#define __KSZ_COMMON_H
+#include <linux/dsa/ksz_common.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
@@ -24,12 +24,22 @@
static int ksz_ptp_enable_mode(struct ksz_device *dev, bool enable)
{
+ struct ksz_ptp_data *ptp_data = &dev->ptp_data;
u16 data = 0;
+ int ret;
/* Enable PTP mode */
- if (enable)
+ if (enable) {
data = PTP_ENABLE;
+ /* Schedule cyclic call of ksz_ptp_do_aux_work() */
+ ret = ptp_schedule_worker(ptp_data->clock, 0);
+ if (ret)
+ return ret;
+ } else {
+ ptp_cancel_worker_sync(ptp_data->clock);
+ }
+
return ksz_rmw16(dev, REG_PTP_MSG_CONF1, PTP_ENABLE, data);
}
@@ -226,6 +236,12 @@ static int ksz_ptp_settime(struct ptp_clock_info *ptp,
/* Load PTP clock from shadow registers */
ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_LOAD_TIME, PTP_LOAD_TIME);
+ if (ret)
+ goto error_return;
+
+ spin_lock_bh(&ptp_data->clock_lock);
+ ptp_data->clock_time = *ts;
+ spin_unlock_bh(&ptp_data->clock_lock);
error_return:
mutex_unlock(&ptp_data->lock);
@@ -280,6 +296,7 @@ static int ksz_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp);
struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data);
+ struct timespec64 delta64 = ns_to_timespec64(delta);
s32 sec, nsec;
u16 data16;
int ret;
@@ -312,15 +329,51 @@ static int ksz_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
data16 |= PTP_STEP_DIR;
ret = ksz_write16(dev, REG_PTP_CLK_CTRL, data16);
+ if (ret)
+ goto error_return;
+
+ spin_lock_bh(&ptp_data->clock_lock);
+ ptp_data->clock_time = timespec64_add(ptp_data->clock_time, delta64);
+ spin_unlock_bh(&ptp_data->clock_lock);
error_return:
mutex_unlock(&ptp_data->lock);
return ret;
}
+/* Function is pointer to the do_aux_work in the ptp_clock capability */
+static long ksz_ptp_do_aux_work(struct ptp_clock_info *ptp)
+{
+ struct ksz_ptp_data *ptp_data = ptp_caps_to_data(ptp);
+ struct ksz_device *dev = ptp_data_to_ksz_dev(ptp_data);
+ struct timespec64 ts;
+
+ mutex_lock(&ptp_data->lock);
+ _ksz_ptp_gettime(dev, &ts);
+ mutex_unlock(&ptp_data->lock);
+
+ spin_lock_bh(&ptp_data->clock_lock);
+ ptp_data->clock_time = ts;
+ spin_unlock_bh(&ptp_data->clock_lock);
+
+ return HZ; /* reschedule in 1 second */
+}
+
static int ksz_ptp_start_clock(struct ksz_device *dev)
{
- return ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ENABLE, PTP_CLK_ENABLE);
+ struct ksz_ptp_data *ptp_data = &dev->ptp_data;
+ int ret;
+
+ ret = ksz_rmw16(dev, REG_PTP_CLK_CTRL, PTP_CLK_ENABLE, PTP_CLK_ENABLE);
+ if (ret)
+ return ret;
+
+ spin_lock_bh(&ptp_data->clock_lock);
+ ptp_data->clock_time.tv_sec = 0;
+ ptp_data->clock_time.tv_nsec = 0;
+ spin_unlock_bh(&ptp_data->clock_lock);
+
+ return 0;
}
static const struct ptp_clock_info ksz_ptp_caps = {
@@ -331,6 +384,7 @@ static const struct ptp_clock_info ksz_ptp_caps = {
.settime64 = ksz_ptp_settime,
.adjfine = ksz_ptp_adjfine,
.adjtime = ksz_ptp_adjtime,
+ .do_aux_work = ksz_ptp_do_aux_work,
};
int ksz_ptp_clock_register(struct dsa_switch *ds)
@@ -340,6 +394,7 @@ int ksz_ptp_clock_register(struct dsa_switch *ds)
int ret;
mutex_init(&ptp_data->lock);
+ spin_lock_init(&ptp_data->clock_lock);
ptp_data->caps = ksz_ptp_caps;
@@ -13,6 +13,9 @@ struct ksz_ptp_data {
struct ptp_clock *clock;
/* Serializes all operations on the PTP hardware clock */
struct mutex lock;
+ /* lock for accessing the clock_time */
+ spinlock_t clock_lock;
+ struct timespec64 clock_time;
};
int ksz_ptp_clock_register(struct dsa_switch *ds);