@@ -99,6 +99,7 @@ static void cpts_purge_txq(struct cpts *cpts)
*/
static int cpts_fifo_read(struct cpts *cpts, int match)
{
+ bool need_schedule = false;
struct cpts_event *event;
unsigned long flags;
int i, type = -1;
@@ -131,6 +132,8 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
cpts->cc.mult = cpts->mult_new;
cpts->mult_new = 0;
}
+ if (!cpts->irq_poll)
+ complete(&cpts->ts_push_complete);
break;
case CPTS_EV_TX:
case CPTS_EV_RX:
@@ -139,6 +142,7 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
list_del_init(&event->list);
list_add_tail(&event->list, &cpts->events);
+ need_schedule = true;
break;
case CPTS_EV_ROLL:
case CPTS_EV_HALF:
@@ -154,9 +158,17 @@ static int cpts_fifo_read(struct cpts *cpts, int match)
spin_unlock_irqrestore(&cpts->lock, flags);
+ if (!cpts->irq_poll && need_schedule)
+ ptp_schedule_worker(cpts->clock, 0);
+
return type == match ? 0 : -1;
}
+void cpts_misc_interrupt(struct cpts *cpts)
+{
+ cpts_fifo_read(cpts, -1);
+}
+
static u64 cpts_systim_read(const struct cyclecounter *cc)
{
struct cpts *cpts = container_of(cc, struct cpts, cc);
@@ -169,6 +181,8 @@ static void cpts_update_cur_time(struct cpts *cpts, int match,
{
unsigned long flags;
+ reinit_completion(&cpts->ts_push_complete);
+
/* use spin_lock_irqsave() here as it has to run very fast */
spin_lock_irqsave(&cpts->lock, flags);
ptp_read_system_prets(sts);
@@ -177,8 +191,12 @@ static void cpts_update_cur_time(struct cpts *cpts, int match,
ptp_read_system_postts(sts);
spin_unlock_irqrestore(&cpts->lock, flags);
- if (cpts_fifo_read(cpts, match) && match != -1)
+ if (cpts->irq_poll && cpts_fifo_read(cpts, match) && match != -1)
dev_err(cpts->dev, "cpts: unable to obtain a time stamp\n");
+
+ if (!cpts->irq_poll &&
+ !wait_for_completion_timeout(&cpts->ts_push_complete, HZ))
+ dev_err(cpts->dev, "cpts: obtain a time stamp timeout\n");
}
/* PTP clock operations */
@@ -708,8 +726,10 @@ struct cpts *cpts_create(struct device *dev, void __iomem *regs,
cpts->dev = dev;
cpts->reg = (struct cpsw_cpts __iomem *)regs;
+ cpts->irq_poll = true;
spin_lock_init(&cpts->lock);
mutex_init(&cpts->ptp_clk_mutex);
+ init_completion(&cpts->ts_push_complete);
ret = cpts_of_parse(cpts, node);
if (ret)
@@ -118,6 +118,8 @@ struct cpts {
u64 cur_timestamp;
u32 mult_new;
struct mutex ptp_clk_mutex; /* sync PTP interface and worker */
+ bool irq_poll;
+ struct completion ts_push_complete;
};
void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
@@ -127,6 +129,7 @@ void cpts_unregister(struct cpts *cpts);
struct cpts *cpts_create(struct device *dev, void __iomem *regs,
struct device_node *node);
void cpts_release(struct cpts *cpts);
+void cpts_misc_interrupt(struct cpts *cpts);
static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
@@ -138,6 +141,11 @@ static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
return true;
}
+static inline void cpts_set_irqpoll(struct cpts *cpts, bool en)
+{
+ cpts->irq_poll = en;
+}
+
#else
struct cpts;
@@ -173,6 +181,14 @@ static inline bool cpts_can_timestamp(struct cpts *cpts, struct sk_buff *skb)
{
return false;
}
+
+static inline void cpts_misc_interrupt(struct cpts *cpts)
+{
+}
+
+static inline void cpts_set_irqpoll(struct cpts *cpts, bool en)
+{
+}
#endif