summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/ti/cpts.c
diff options
context:
space:
mode:
authorGrygorii Strashko <grygorii.strashko@ti.com>2020-04-23 17:20:21 +0300
committerDavid S. Miller <davem@davemloft.net>2020-04-23 12:50:21 -0700
commitb78aba495df0eaee4f4a779b2354d6e2a43a3d70 (patch)
tree24e56a5f468ec6c8ba12f0f6729cdf793ba7e2ca /drivers/net/ethernet/ti/cpts.c
parent85624412a03dc61eabddeb1cfbbc8325e3544694 (diff)
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 <grygorii.strashko@ti.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/ti/cpts.c')
-rw-r--r--drivers/net/ethernet/ti/cpts.c49
1 files changed, 48 insertions, 1 deletions
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().