Skip to content

Commit

Permalink
net: ethernet: ti: cpts: add support for HW_TS_PUSH events
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Grygorii Strashko authored and David S. Miller committed Apr 23, 2020
1 parent 8562441 commit b78aba4
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 5 deletions.
5 changes: 4 additions & 1 deletion drivers/net/ethernet/ti/cpsw_priv.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "cpsw_sl.h"
#include "davinci_cpdma.h"

#define CPTS_N_ETX_TS 4

int (*cpsw_slave_index)(struct cpsw_common *cpsw, struct cpsw_priv *priv);

void cpsw_intr_enable(struct cpsw_common *cpsw)
Expand Down Expand Up @@ -522,7 +524,8 @@ int cpsw_init_common(struct cpsw_common *cpsw, void __iomem *ss_regs,
if (!cpts_node)
cpts_node = cpsw->dev->of_node;

cpsw->cpts = cpts_create(cpsw->dev, cpts_regs, cpts_node);
cpsw->cpts = cpts_create(cpsw->dev, cpts_regs, cpts_node,
CPTS_N_ETX_TS);
if (IS_ERR(cpsw->cpts)) {
ret = PTR_ERR(cpsw->cpts);
cpdma_ctlr_destroy(cpsw->dma);
Expand Down
49 changes: 48 additions & 1 deletion drivers/net/ethernet/ti/cpts.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -716,7 +760,7 @@ static int cpts_of_parse(struct cpts *cpts, struct device_node *node)
}

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;
Expand Down Expand Up @@ -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().
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/ti/cpts.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,15 @@ struct cpts {
struct mutex ptp_clk_mutex; /* sync PTP interface and worker */
bool irq_poll;
struct completion ts_push_complete;
u32 hw_ts_enable;
};

void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
int cpts_register(struct cpts *cpts);
void cpts_unregister(struct cpts *cpts);
struct cpts *cpts_create(struct device *dev, void __iomem *regs,
struct device_node *node);
struct device_node *node, u32 n_ext_ts);
void cpts_release(struct cpts *cpts);
void cpts_misc_interrupt(struct cpts *cpts);

Expand Down Expand Up @@ -158,7 +159,7 @@ static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)

static inline
struct cpts *cpts_create(struct device *dev, void __iomem *regs,
struct device_node *node)
struct device_node *node, u32 n_ext_ts)
{
return NULL;
}
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/ti/netcp_ethss.c
Original file line number Diff line number Diff line change
Expand Up @@ -3716,7 +3716,8 @@ static int gbe_probe(struct netcp_device *netcp_device, struct device *dev,
if (!cpts_node)
cpts_node = of_node_get(node);

gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg, cpts_node);
gbe_dev->cpts = cpts_create(gbe_dev->dev, gbe_dev->cpts_reg,
cpts_node, 0);
of_node_put(cpts_node);
if (IS_ENABLED(CONFIG_TI_CPTS) && IS_ERR(gbe_dev->cpts)) {
ret = PTR_ERR(gbe_dev->cpts);
Expand Down

0 comments on commit b78aba4

Please sign in to comment.