mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
85624412a0
commit
b78aba495d
|
@ -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)
|
||||
|
@ -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);
|
||||
|
|
|
@ -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 @@ 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;
|
||||
|
@ -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().
|
||||
|
|
|
@ -120,6 +120,7 @@ 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);
|
||||
|
@ -127,7 +128,7 @@ 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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue