Commit 6815d8b0 authored by Yangbo Lu's avatar Yangbo Lu Committed by David S. Miller

ptp_qoriq: support external trigger stamp FIFO

The external trigger stamp FIFO was introduced as a new feature
for QorIQ 1588 timer IP block. This patch is to support it by
adding a new dts property "fsl,extts-fifo". Any QorIQ 1588 timer
supporting this feature is required to add this property in its
dts node.

In addition, the FIFO should be cleaned up before enabling external
trigger interrupts. Otherwise, there will be interrupts immediately
just after enabling external trigger interrupts.
Signed-off-by: default avatarYangbo Lu <yangbo.lu@nxp.com>
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b0bc10cc
...@@ -88,6 +88,49 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp) ...@@ -88,6 +88,49 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp)
qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
} }
static int extts_clean_up(struct qoriq_ptp *qoriq_ptp, int index,
bool update_event)
{
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
struct ptp_clock_event event;
void __iomem *reg_etts_l;
void __iomem *reg_etts_h;
u32 valid, stat, lo, hi;
switch (index) {
case 0:
valid = ETS1_VLD;
reg_etts_l = &regs->etts_regs->tmr_etts1_l;
reg_etts_h = &regs->etts_regs->tmr_etts1_h;
break;
case 1:
valid = ETS2_VLD;
reg_etts_l = &regs->etts_regs->tmr_etts2_l;
reg_etts_h = &regs->etts_regs->tmr_etts2_h;
break;
default:
return -EINVAL;
}
event.type = PTP_CLOCK_EXTTS;
event.index = index;
do {
lo = qoriq_read(reg_etts_l);
hi = qoriq_read(reg_etts_h);
if (update_event) {
event.timestamp = ((u64) hi) << 32;
event.timestamp |= lo;
ptp_clock_event(qoriq_ptp->clock, &event);
}
stat = qoriq_read(&regs->ctrl_regs->tmr_stat);
} while (qoriq_ptp->extts_fifo_support && (stat & valid));
return 0;
}
/* /*
* Interrupt service routine * Interrupt service routine
*/ */
...@@ -111,24 +154,12 @@ static irqreturn_t isr(int irq, void *priv) ...@@ -111,24 +154,12 @@ static irqreturn_t isr(int irq, void *priv)
if (irqs & ETS1) { if (irqs & ETS1) {
ack |= ETS1; ack |= ETS1;
hi = qoriq_read(&regs->etts_regs->tmr_etts1_h); extts_clean_up(qoriq_ptp, 0, true);
lo = qoriq_read(&regs->etts_regs->tmr_etts1_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 0;
event.timestamp = ((u64) hi) << 32;
event.timestamp |= lo;
ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (irqs & ETS2) { if (irqs & ETS2) {
ack |= ETS2; ack |= ETS2;
hi = qoriq_read(&regs->etts_regs->tmr_etts2_h); extts_clean_up(qoriq_ptp, 1, true);
lo = qoriq_read(&regs->etts_regs->tmr_etts2_l);
event.type = PTP_CLOCK_EXTTS;
event.index = 1;
event.timestamp = ((u64) hi) << 32;
event.timestamp |= lo;
ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (irqs & ALM2) { if (irqs & ALM2) {
...@@ -278,6 +309,10 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp, ...@@ -278,6 +309,10 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
default: default:
return -EINVAL; return -EINVAL;
} }
if (on)
extts_clean_up(qoriq_ptp, rq->extts.index, false);
break; break;
case PTP_CLK_REQ_PPS: case PTP_CLK_REQ_PPS:
bit = PP1EN; bit = PP1EN;
...@@ -441,6 +476,11 @@ static int qoriq_ptp_probe(struct platform_device *dev) ...@@ -441,6 +476,11 @@ static int qoriq_ptp_probe(struct platform_device *dev)
if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel)) if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel))
qoriq_ptp->cksel = DEFAULT_CKSEL; qoriq_ptp->cksel = DEFAULT_CKSEL;
if (of_property_read_bool(node, "fsl,extts-fifo"))
qoriq_ptp->extts_fifo_support = true;
else
qoriq_ptp->extts_fifo_support = false;
if (of_property_read_u32(node, if (of_property_read_u32(node,
"fsl,tclk-period", &qoriq_ptp->tclk_period) || "fsl,tclk-period", &qoriq_ptp->tclk_period) ||
of_property_read_u32(node, of_property_read_u32(node,
......
...@@ -120,6 +120,8 @@ struct qoriq_ptp_registers { ...@@ -120,6 +120,8 @@ struct qoriq_ptp_registers {
/* Bit definitions for the TMR_STAT register */ /* Bit definitions for the TMR_STAT register */
#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ #define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */
#define STAT_VEC_MASK (0x3f) #define STAT_VEC_MASK (0x3f)
#define ETS1_VLD (1<<24)
#define ETS2_VLD (1<<25)
/* Bit definitions for the TMR_PRSC register */ /* Bit definitions for the TMR_PRSC register */
#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ #define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */
...@@ -141,6 +143,7 @@ struct qoriq_ptp { ...@@ -141,6 +143,7 @@ struct qoriq_ptp {
struct ptp_clock *clock; struct ptp_clock *clock;
struct ptp_clock_info caps; struct ptp_clock_info caps;
struct resource *rsrc; struct resource *rsrc;
bool extts_fifo_support;
int irq; int irq;
int phc_index; int phc_index;
u64 alarm_interval; /* for periodic alarm */ u64 alarm_interval; /* for periodic alarm */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment