*/
static int cpts_fifo_read(struct cpts *cpts, int match)
{
+ struct cpts_event *event;
+ unsigned long flags;
int i, type = -1;
u32 hi, lo;
- struct cpts_event *event;
+
+ spin_lock_irqsave(&cpts->lock, flags);
for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
if (cpts_fifo_pop(cpts, &hi, &lo))
if (list_empty(&cpts->pool) && cpts_purge_events(cpts)) {
dev_warn(cpts->dev, "cpts: event pool empty\n");
- return -1;
+ break;
}
event = list_first_entry(&cpts->pool, struct cpts_event, list);
if (type == match)
break;
}
+
+ spin_unlock_irqrestore(&cpts->lock, flags);
+
return type == match ? 0 : -1;
}
static void cpts_update_cur_time(struct cpts *cpts, int match,
struct ptp_system_timestamp *sts)
{
+ unsigned long flags;
+
+ /* use spin_lock_irqsave() here as it has to run very fast */
+ spin_lock_irqsave(&cpts->lock, flags);
ptp_read_system_prets(sts);
cpts_write32(cpts, TS_PUSH, ts_push);
cpts_read32(cpts, ts_push);
ptp_read_system_postts(sts);
+ spin_unlock_irqrestore(&cpts->lock, flags);
if (cpts_fifo_read(cpts, match) && match != -1)
dev_err(cpts->dev, "cpts: unable to obtain a time stamp\n");
static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
{
- u64 adj;
- u32 diff, mult;
- int neg_adj = 0;
- unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
+ int neg_adj = 0;
+ u32 diff, mult;
+ u64 adj;
if (ppb < 0) {
neg_adj = 1;
adj *= ppb;
diff = div_u64(adj, 1000000000ULL);
- spin_lock_irqsave(&cpts->lock, flags);
+ mutex_lock(&cpts->ptp_clk_mutex);
cpts->mult_new = neg_adj ? mult - diff : mult + diff;
cpts_update_cur_time(cpts, CPTS_EV_PUSH, NULL);
- spin_unlock_irqrestore(&cpts->lock, flags);
-
+ mutex_unlock(&cpts->ptp_clk_mutex);
return 0;
}
static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
{
- unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
- spin_lock_irqsave(&cpts->lock, flags);
+ mutex_lock(&cpts->ptp_clk_mutex);
timecounter_adjtime(&cpts->tc, delta);
- spin_unlock_irqrestore(&cpts->lock, flags);
+ mutex_unlock(&cpts->ptp_clk_mutex);
return 0;
}
struct ptp_system_timestamp *sts)
{
struct cpts *cpts = container_of(ptp, struct cpts, info);
- unsigned long flags;
u64 ns;
- spin_lock_irqsave(&cpts->lock, flags);
+ mutex_lock(&cpts->ptp_clk_mutex);
cpts_update_cur_time(cpts, CPTS_EV_PUSH, sts);
ns = timecounter_read(&cpts->tc);
- spin_unlock_irqrestore(&cpts->lock, flags);
+ mutex_unlock(&cpts->ptp_clk_mutex);
*ts = ns_to_timespec64(ns);
static int cpts_ptp_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts)
{
- u64 ns;
- unsigned long flags;
struct cpts *cpts = container_of(ptp, struct cpts, info);
+ u64 ns;
ns = timespec64_to_ns(ts);
- spin_lock_irqsave(&cpts->lock, flags);
+ mutex_lock(&cpts->ptp_clk_mutex);
timecounter_init(&cpts->tc, &cpts->cc, ns);
- spin_unlock_irqrestore(&cpts->lock, flags);
+ mutex_unlock(&cpts->ptp_clk_mutex);
return 0;
}
unsigned long flags;
u64 ns;
- spin_lock_irqsave(&cpts->lock, flags);
- cpts_update_cur_time(cpts, -1, NULL);
- spin_unlock_irqrestore(&cpts->lock, flags);
+ mutex_lock(&cpts->ptp_clk_mutex);
+ cpts_update_cur_time(cpts, -1, NULL);
ns = timecounter_read(&cpts->tc);
cpts_process_events(cpts);
spin_unlock_irqrestore(&cpts->txq.lock, flags);
dev_dbg(cpts->dev, "cpts overflow check at %lld\n", ns);
+ mutex_unlock(&cpts->ptp_clk_mutex);
return (long)delay;
}
u32 mtype_seqid;
u64 ns = 0;
- spin_lock_irqsave(&cpts->lock, flags);
cpts_fifo_read(cpts, -1);
+ spin_lock_irqsave(&cpts->lock, flags);
list_for_each_safe(this, next, &cpts->events) {
event = list_entry(this, struct cpts_event, list);
if (event_expired(event)) {
cpts->dev = dev;
cpts->reg = (struct cpsw_cpts __iomem *)regs;
spin_lock_init(&cpts->lock);
+ mutex_init(&cpts->ptp_clk_mutex);
ret = cpts_of_parse(cpts, node);
if (ret)