Skip to content

Commit

Permalink
Merge branch 'ptp_qoriq'
Browse files Browse the repository at this point in the history
Yangbo Lu says:

====================
External trigger stamp fifo support for ptp_qoriq

This patch-set is to add external trigger stamp fifo support by a new
binding "fsl,extts-fifo", and to add fiper pulse loopback support which
is very useful for validating trigger without external hardware.
Also fixed issues in interrupt enabling/handling.

"fsl,extts-fifo" is required to be added into 1588 timer dts node whose
hardware supports it. The work will be done for some QorIQ platforms dts in
the near future.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jan 23, 2019
2 parents ed175d9 + 53deab2 commit a2ff7e4
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 45 deletions.
2 changes: 2 additions & 0 deletions Documentation/devicetree/bindings/ptp/ptp-qoriq.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Clock Properties:
- fsl,tmr-fiper1 Fixed interval period pulse generator.
- fsl,tmr-fiper2 Fixed interval period pulse generator.
- fsl,max-adj Maximum frequency adjustment in parts per billion.
- fsl,extts-fifo The presence of this property indicates hardware
support for the external trigger stamp FIFO.

These properties set the operational parameters for the PTP
clock. You must choose these carefully for the clock to work right.
Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -6087,6 +6087,7 @@ M: Yangbo Lu <yangbo.lu@nxp.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/ptp/ptp_qoriq.c
F: drivers/ptp/ptp_qoriq_debugfs.c
F: include/linux/fsl/ptp_qoriq.h
F: Documentation/devicetree/bindings/ptp/ptp-qoriq.txt

Expand Down
1 change: 1 addition & 0 deletions arch/arm/boot/dts/ls1021a.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,7 @@
fsl,tmr-fiper1 = <999999995>;
fsl,tmr-fiper2 = <99990>;
fsl,max-adj = <499999999>;
fsl,extts-fifo;
};

enet0: ethernet@2d10000 {
Expand Down
2 changes: 1 addition & 1 deletion drivers/ptp/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ config PTP_1588_CLOCK_QORIQ
packets using the SO_TIMESTAMPING API.

To compile this driver as a module, choose M here: the module
will be called ptp_qoriq.
will be called ptp-qoriq.

config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock"
Expand Down
4 changes: 3 additions & 1 deletion drivers/ptp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o
obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o
obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o
obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp_qoriq.o
obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp-qoriq.o
ptp-qoriq-y += ptp_qoriq.o
ptp-qoriq-$(CONFIG_DEBUG_FS) += ptp_qoriq_debugfs.o
129 changes: 86 additions & 43 deletions drivers/ptp/ptp_qoriq.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,49 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp)
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
*/
Expand All @@ -98,33 +141,28 @@ static irqreturn_t isr(int irq, void *priv)
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
struct ptp_clock_event event;
u64 ns;
u32 ack = 0, lo, hi, mask, val;
u32 ack = 0, lo, hi, mask, val, irqs;

spin_lock(&qoriq_ptp->lock);

val = qoriq_read(&regs->ctrl_regs->tmr_tevent);
mask = qoriq_read(&regs->ctrl_regs->tmr_temask);

spin_unlock(&qoriq_ptp->lock);

if (val & ETS1) {
irqs = val & mask;

if (irqs & ETS1) {
ack |= ETS1;
hi = qoriq_read(&regs->etts_regs->tmr_etts1_h);
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);
extts_clean_up(qoriq_ptp, 0, true);
}

if (val & ETS2) {
if (irqs & ETS2) {
ack |= ETS2;
hi = qoriq_read(&regs->etts_regs->tmr_etts2_h);
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);
extts_clean_up(qoriq_ptp, 1, true);
}

if (val & ALM2) {
if (irqs & ALM2) {
ack |= ALM2;
if (qoriq_ptp->alarm_value) {
event.type = PTP_CLOCK_ALARM;
Expand All @@ -136,13 +174,10 @@ static irqreturn_t isr(int irq, void *priv)
ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval;
hi = ns >> 32;
lo = ns & 0xffffffff;
spin_lock(&qoriq_ptp->lock);
qoriq_write(&regs->alarm_regs->tmr_alarm2_l, lo);
qoriq_write(&regs->alarm_regs->tmr_alarm2_h, hi);
spin_unlock(&qoriq_ptp->lock);
qoriq_ptp->alarm_value = ns;
} else {
qoriq_write(&regs->ctrl_regs->tmr_tevent, ALM2);
spin_lock(&qoriq_ptp->lock);
mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
mask &= ~ALM2EN;
Expand All @@ -153,7 +188,7 @@ static irqreturn_t isr(int irq, void *priv)
}
}

if (val & PP1) {
if (irqs & PP1) {
ack |= PP1;
event.type = PTP_CLOCK_PPS;
ptp_clock_event(qoriq_ptp->clock, &event);
Expand Down Expand Up @@ -260,7 +295,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
unsigned long flags;
u32 bit, mask;
u32 bit, mask = 0;

switch (rq->type) {
case PTP_CLK_REQ_EXTTS:
Expand All @@ -274,32 +309,32 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
default:
return -EINVAL;
}
spin_lock_irqsave(&qoriq_ptp->lock, flags);
mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on)
mask |= bit;
else
mask &= ~bit;
qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;

case PTP_CLK_REQ_PPS:
spin_lock_irqsave(&qoriq_ptp->lock, flags);
mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on)
mask |= PP1EN;
else
mask &= ~PP1EN;
qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;
extts_clean_up(qoriq_ptp, rq->extts.index, false);

default:
break;
case PTP_CLK_REQ_PPS:
bit = PP1EN;
break;
default:
return -EOPNOTSUPP;
}

spin_lock_irqsave(&qoriq_ptp->lock, flags);

mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
if (on) {
mask |= bit;
qoriq_write(&regs->ctrl_regs->tmr_tevent, bit);
} else {
mask &= ~bit;
}

return -EOPNOTSUPP;
qoriq_write(&regs->ctrl_regs->tmr_temask, mask);

spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0;
}

static const struct ptp_clock_info ptp_qoriq_caps = {
Expand Down Expand Up @@ -436,11 +471,17 @@ static int qoriq_ptp_probe(struct platform_device *dev)

err = -EINVAL;

qoriq_ptp->dev = &dev->dev;
qoriq_ptp->caps = ptp_qoriq_caps;

if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->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,
"fsl,tclk-period", &qoriq_ptp->tclk_period) ||
of_property_read_u32(node,
Expand Down Expand Up @@ -532,6 +573,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
}
qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock);

ptp_qoriq_create_debugfs(qoriq_ptp);
platform_set_drvdata(dev, qoriq_ptp);

return 0;
Expand All @@ -557,6 +599,7 @@ static int qoriq_ptp_remove(struct platform_device *dev)
qoriq_write(&regs->ctrl_regs->tmr_temask, 0);
qoriq_write(&regs->ctrl_regs->tmr_ctrl, 0);

ptp_qoriq_remove_debugfs(qoriq_ptp);
ptp_clock_unregister(qoriq_ptp->clock);
iounmap(qoriq_ptp->base);
release_resource(qoriq_ptp->rsrc);
Expand Down
101 changes: 101 additions & 0 deletions drivers/ptp/ptp_qoriq_debugfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: GPL-2.0+
/* Copyright 2019 NXP
*/
#include <linux/device.h>
#include <linux/debugfs.h>
#include <linux/fsl/ptp_qoriq.h>

static int ptp_qoriq_fiper1_lpbk_get(void *data, u64 *val)
{
struct qoriq_ptp *qoriq_ptp = data;
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 ctrl;

ctrl = qoriq_read(&regs->ctrl_regs->tmr_ctrl);
*val = ctrl & PP1L ? 1 : 0;

return 0;
}

static int ptp_qoriq_fiper1_lpbk_set(void *data, u64 val)
{
struct qoriq_ptp *qoriq_ptp = data;
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 ctrl;

ctrl = qoriq_read(&regs->ctrl_regs->tmr_ctrl);
if (val == 0)
ctrl &= ~PP1L;
else
ctrl |= PP1L;

qoriq_write(&regs->ctrl_regs->tmr_ctrl, ctrl);
return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper1_fops, ptp_qoriq_fiper1_lpbk_get,
ptp_qoriq_fiper1_lpbk_set, "%llu\n");

static int ptp_qoriq_fiper2_lpbk_get(void *data, u64 *val)
{
struct qoriq_ptp *qoriq_ptp = data;
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 ctrl;

ctrl = qoriq_read(&regs->ctrl_regs->tmr_ctrl);
*val = ctrl & PP2L ? 1 : 0;

return 0;
}

static int ptp_qoriq_fiper2_lpbk_set(void *data, u64 val)
{
struct qoriq_ptp *qoriq_ptp = data;
struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
u32 ctrl;

ctrl = qoriq_read(&regs->ctrl_regs->tmr_ctrl);
if (val == 0)
ctrl &= ~PP2L;
else
ctrl |= PP2L;

qoriq_write(&regs->ctrl_regs->tmr_ctrl, ctrl);
return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(ptp_qoriq_fiper2_fops, ptp_qoriq_fiper2_lpbk_get,
ptp_qoriq_fiper2_lpbk_set, "%llu\n");

void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp)
{
struct dentry *root;

root = debugfs_create_dir(dev_name(qoriq_ptp->dev), NULL);
if (IS_ERR(root))
return;
if (!root)
goto err_root;

qoriq_ptp->debugfs_root = root;

if (!debugfs_create_file("fiper1-loopback", 0600, root, qoriq_ptp,
&ptp_qoriq_fiper1_fops))
goto err_node;
if (!debugfs_create_file("fiper2-loopback", 0600, root, qoriq_ptp,
&ptp_qoriq_fiper2_fops))
goto err_node;
return;

err_node:
debugfs_remove_recursive(root);
qoriq_ptp->debugfs_root = NULL;
err_root:
dev_err(qoriq_ptp->dev, "failed to initialize debugfs\n");
}

void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp)
{
debugfs_remove_recursive(qoriq_ptp->debugfs_root);
qoriq_ptp->debugfs_root = NULL;
}
15 changes: 15 additions & 0 deletions include/linux/fsl/ptp_qoriq.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ struct qoriq_ptp_registers {
/* Bit definitions for the TMR_STAT register */
#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */
#define STAT_VEC_MASK (0x3f)
#define ETS1_VLD (1<<24)
#define ETS2_VLD (1<<25)

/* Bit definitions for the TMR_PRSC register */
#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */
Expand All @@ -141,6 +143,9 @@ struct qoriq_ptp {
struct ptp_clock *clock;
struct ptp_clock_info caps;
struct resource *rsrc;
struct dentry *debugfs_root;
struct device *dev;
bool extts_fifo_support;
int irq;
int phc_index;
u64 alarm_interval; /* for periodic alarm */
Expand All @@ -166,4 +171,14 @@ static inline void qoriq_write(unsigned __iomem *addr, u32 val)
iowrite32be(val, addr);
}

#ifdef CONFIG_DEBUG_FS
void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp);
void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp);
#else
static inline void ptp_qoriq_create_debugfs(struct qoriq_ptp *qoriq_ptp)
{ }
static inline void ptp_qoriq_remove_debugfs(struct qoriq_ptp *qoriq_ptp)
{ }
#endif

#endif

0 comments on commit a2ff7e4

Please sign in to comment.