From b78aba495df0eaee4f4a779b2354d6e2a43a3d70 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 23 Apr 2020 17:20:21 +0300 Subject: net: ethernet: ti: cpts: add support for HW_TS_PUSH events Hence CPTS IRQ support is in place the W_TS_PUSH events can be added. PWM capable DmTimers can be used to generete input signals for CPTS on TI AM335x/AM437x/DRA7 SoCs to be timestamped: AM335x/AM437x: timer4 - timer7 DRA7/AM57xx: timer13 - timer16 Signed-off-by: Grygorii Strashko Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/ti/cpts.c | 49 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'drivers/net/ethernet/ti/cpts.c') diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index 339796c87bf6..7c55d395de2c 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -32,6 +32,11 @@ struct cpts_skb_cb_data { #define cpts_read32(c, r) readl_relaxed(&c->reg->r) #define cpts_write32(c, v, r) writel_relaxed(v, &c->reg->r) +static int cpts_event_port(struct cpts_event *event) +{ + return (event->high >> PORT_NUMBER_SHIFT) & PORT_NUMBER_MASK; +} + static int event_expired(struct cpts_event *event) { return time_after(jiffies, event->tmo); @@ -99,6 +104,7 @@ static void cpts_purge_txq(struct cpts *cpts) */ static int cpts_fifo_read(struct cpts *cpts, int match) { + struct ptp_clock_event pevent; bool need_schedule = false; struct cpts_event *event; unsigned long flags; @@ -146,7 +152,12 @@ static int cpts_fifo_read(struct cpts *cpts, int match) break; case CPTS_EV_ROLL: case CPTS_EV_HALF: + break; case CPTS_EV_HW: + pevent.timestamp = event->timestamp; + pevent.type = PTP_CLOCK_EXTTS; + pevent.index = cpts_event_port(event) - 1; + ptp_clock_event(cpts->clock, &pevent); break; default: dev_err(cpts->dev, "cpts: unknown event type\n"); @@ -273,9 +284,42 @@ static int cpts_ptp_settime(struct ptp_clock_info *ptp, return 0; } +static int cpts_extts_enable(struct cpts *cpts, u32 index, int on) +{ + u32 v; + + if (((cpts->hw_ts_enable & BIT(index)) >> index) == on) + return 0; + + mutex_lock(&cpts->ptp_clk_mutex); + + v = cpts_read32(cpts, control); + if (on) { + v |= BIT(8 + index); + cpts->hw_ts_enable |= BIT(index); + } else { + v &= ~BIT(8 + index); + cpts->hw_ts_enable &= ~BIT(index); + } + cpts_write32(cpts, v, control); + + mutex_unlock(&cpts->ptp_clk_mutex); + + return 0; +} + static int cpts_ptp_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) { + struct cpts *cpts = container_of(ptp, struct cpts, info); + + switch (rq->type) { + case PTP_CLK_REQ_EXTTS: + return cpts_extts_enable(cpts, rq->extts.index, on); + default: + break; + } + return -EOPNOTSUPP; } @@ -716,7 +760,7 @@ of_error: } struct cpts *cpts_create(struct device *dev, void __iomem *regs, - struct device_node *node) + struct device_node *node, u32 n_ext_ts) { struct cpts *cpts; int ret; @@ -755,6 +799,9 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs, cpts->cc.mask = CLOCKSOURCE_MASK(32); cpts->info = cpts_info; + if (n_ext_ts) + cpts->info.n_ext_ts = n_ext_ts; + cpts_calc_mult_shift(cpts); /* save cc.mult original value as it can be modified * by cpts_ptp_adjfreq(). -- cgit v1.2.3