Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a8f62d0c authored by Yangbo Lu's avatar Yangbo Lu Committed by David S. Miller
Browse files

ptp: support DPAA FMan 1588 timer in ptp_qoriq



This patch is to support DPAA (Data Path Acceleration Architecture)
1588 timer by adding "fsl,fman-ptp-timer" compatible, sharing
interrupt with FMan, adding FSL_DPAA_ETH dependency, and fixing
up register offset.

Signed-off-by: default avatarYangbo Lu <yangbo.lu@nxp.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Acked-by: default avatarMadalin Bucur <madalin.bucur@nxp.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c4015302
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ config PTP_1588_CLOCK_DTE

config PTP_1588_CLOCK_QORIQ
	tristate "Freescale QorIQ 1588 timer as PTP clock"
	depends on GIANFAR
	depends on GIANFAR || FSL_DPAA_ETH
	depends on PTP_1588_CLOCK
	default y
	help
+66 −38
Original line number Diff line number Diff line
@@ -39,11 +39,12 @@
/* Caller must hold qoriq_ptp->lock. */
static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
{
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
	u64 ns;
	u32 lo, hi;

	lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
	hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
	lo = qoriq_read(&regs->ctrl_regs->tmr_cnt_l);
	hi = qoriq_read(&regs->ctrl_regs->tmr_cnt_h);
	ns = ((u64) hi) << 32;
	ns |= lo;
	return ns;
@@ -52,16 +53,18 @@ static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
/* Caller must hold qoriq_ptp->lock. */
static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
{
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
	u32 hi = ns >> 32;
	u32 lo = ns & 0xffffffff;

	qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
	qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
	qoriq_write(&regs->ctrl_regs->tmr_cnt_l, lo);
	qoriq_write(&regs->ctrl_regs->tmr_cnt_h, hi);
}

/* Caller must hold qoriq_ptp->lock. */
static void set_alarm(struct qoriq_ptp *qoriq_ptp)
{
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
	u64 ns;
	u32 lo, hi;

@@ -70,16 +73,18 @@ static void set_alarm(struct qoriq_ptp *qoriq_ptp)
	ns -= qoriq_ptp->tclk_period;
	hi = ns >> 32;
	lo = ns & 0xffffffff;
	qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
	qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
	qoriq_write(&regs->alarm_regs->tmr_alarm1_l, lo);
	qoriq_write(&regs->alarm_regs->tmr_alarm1_h, hi);
}

/* Caller must hold qoriq_ptp->lock. */
static void set_fipers(struct qoriq_ptp *qoriq_ptp)
{
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;

	set_alarm(qoriq_ptp);
	qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
	qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
	qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
	qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
}

/*
@@ -89,16 +94,17 @@ static void set_fipers(struct qoriq_ptp *qoriq_ptp)
static irqreturn_t isr(int irq, void *priv)
{
	struct qoriq_ptp *qoriq_ptp = priv;
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;
	struct ptp_clock_event event;
	u64 ns;
	u32 ack = 0, lo, hi, mask, val;

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

	if (val & ETS1) {
		ack |= ETS1;
		hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
		lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
		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;
@@ -108,8 +114,8 @@ static irqreturn_t isr(int irq, void *priv)

	if (val & ETS2) {
		ack |= ETS2;
		hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
		lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
		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;
@@ -130,16 +136,16 @@ static irqreturn_t isr(int irq, void *priv)
			hi = ns >> 32;
			lo = ns & 0xffffffff;
			spin_lock(&qoriq_ptp->lock);
			qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo);
			qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi);
			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(&qoriq_ptp->regs->tmr_tevent, ALM2);
			qoriq_write(&regs->ctrl_regs->tmr_tevent, ALM2);
			spin_lock(&qoriq_ptp->lock);
			mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
			mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
			mask &= ~ALM2EN;
			qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
			qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
			spin_unlock(&qoriq_ptp->lock);
			qoriq_ptp->alarm_value = 0;
			qoriq_ptp->alarm_interval = 0;
@@ -153,7 +159,7 @@ static irqreturn_t isr(int irq, void *priv)
	}

	if (ack) {
		qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
		qoriq_write(&regs->ctrl_regs->tmr_tevent, ack);
		return IRQ_HANDLED;
	} else
		return IRQ_NONE;
@@ -169,6 +175,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
	u32 tmr_add;
	int neg_adj = 0;
	struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;

	if (scaled_ppm < 0) {
		neg_adj = 1;
@@ -186,7 +193,7 @@ static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)

	tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;

	qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
	qoriq_write(&regs->ctrl_regs->tmr_add, tmr_add);

	return 0;
}
@@ -250,6 +257,7 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
			      struct ptp_clock_request *rq, int on)
{
	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;

@@ -266,23 +274,23 @@ static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
			return -EINVAL;
		}
		spin_lock_irqsave(&qoriq_ptp->lock, flags);
		mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
		mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
		if (on)
			mask |= bit;
		else
			mask &= ~bit;
		qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
		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(&qoriq_ptp->regs->tmr_temask);
		mask = qoriq_read(&regs->ctrl_regs->tmr_temask);
		if (on)
			mask |= PP1EN;
		else
			mask &= ~PP1EN;
		qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
		qoriq_write(&regs->ctrl_regs->tmr_temask, mask);
		spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
		return 0;

@@ -313,10 +321,12 @@ static int qoriq_ptp_probe(struct platform_device *dev)
{
	struct device_node *node = dev->dev.of_node;
	struct qoriq_ptp *qoriq_ptp;
	struct qoriq_ptp_registers *regs;
	struct timespec64 now;
	int err = -ENOMEM;
	u32 tmr_ctrl;
	unsigned long flags;
	void __iomem *base;

	qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
	if (!qoriq_ptp)
@@ -351,7 +361,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
		pr_err("irq not in device tree\n");
		goto no_node;
	}
	if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
	if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) {
		pr_err("request_irq failed\n");
		goto no_node;
	}
@@ -368,12 +378,27 @@ static int qoriq_ptp_probe(struct platform_device *dev)

	spin_lock_init(&qoriq_ptp->lock);

	qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
	base = ioremap(qoriq_ptp->rsrc->start,
		       resource_size(qoriq_ptp->rsrc));
	if (!qoriq_ptp->regs) {
	if (!base) {
		pr_err("ioremap ptp registers failed\n");
		goto no_ioremap;
	}

	qoriq_ptp->base = base;

	if (of_device_is_compatible(node, "fsl,fman-ptp-timer")) {
		qoriq_ptp->regs.ctrl_regs = base + FMAN_CTRL_REGS_OFFSET;
		qoriq_ptp->regs.alarm_regs = base + FMAN_ALARM_REGS_OFFSET;
		qoriq_ptp->regs.fiper_regs = base + FMAN_FIPER_REGS_OFFSET;
		qoriq_ptp->regs.etts_regs = base + FMAN_ETTS_REGS_OFFSET;
	} else {
		qoriq_ptp->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
		qoriq_ptp->regs.alarm_regs = base + ALARM_REGS_OFFSET;
		qoriq_ptp->regs.fiper_regs = base + FIPER_REGS_OFFSET;
		qoriq_ptp->regs.etts_regs = base + ETTS_REGS_OFFSET;
	}

	ktime_get_real_ts64(&now);
	ptp_qoriq_settime(&qoriq_ptp->caps, &now);

@@ -383,13 +408,14 @@ static int qoriq_ptp_probe(struct platform_device *dev)

	spin_lock_irqsave(&qoriq_ptp->lock, flags);

	qoriq_write(&qoriq_ptp->regs->tmr_ctrl,   tmr_ctrl);
	qoriq_write(&qoriq_ptp->regs->tmr_add,    qoriq_ptp->tmr_add);
	qoriq_write(&qoriq_ptp->regs->tmr_prsc,   qoriq_ptp->tmr_prsc);
	qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
	qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
	regs = &qoriq_ptp->regs;
	qoriq_write(&regs->ctrl_regs->tmr_ctrl,   tmr_ctrl);
	qoriq_write(&regs->ctrl_regs->tmr_add,    qoriq_ptp->tmr_add);
	qoriq_write(&regs->ctrl_regs->tmr_prsc,   qoriq_ptp->tmr_prsc);
	qoriq_write(&regs->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
	qoriq_write(&regs->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
	set_alarm(qoriq_ptp);
	qoriq_write(&qoriq_ptp->regs->tmr_ctrl,   tmr_ctrl|FIPERST|RTPE|TE|FRD);
	qoriq_write(&regs->ctrl_regs->tmr_ctrl,   tmr_ctrl|FIPERST|RTPE|TE|FRD);

	spin_unlock_irqrestore(&qoriq_ptp->lock, flags);

@@ -405,7 +431,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
	return 0;

no_clock:
	iounmap(qoriq_ptp->regs);
	iounmap(qoriq_ptp->base);
no_ioremap:
	release_resource(qoriq_ptp->rsrc);
no_resource:
@@ -419,12 +445,13 @@ static int qoriq_ptp_probe(struct platform_device *dev)
static int qoriq_ptp_remove(struct platform_device *dev)
{
	struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
	struct qoriq_ptp_registers *regs = &qoriq_ptp->regs;

	qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
	qoriq_write(&qoriq_ptp->regs->tmr_ctrl,   0);
	qoriq_write(&regs->ctrl_regs->tmr_temask, 0);
	qoriq_write(&regs->ctrl_regs->tmr_ctrl,   0);

	ptp_clock_unregister(qoriq_ptp->clock);
	iounmap(qoriq_ptp->regs);
	iounmap(qoriq_ptp->base);
	release_resource(qoriq_ptp->rsrc);
	free_irq(qoriq_ptp->irq, qoriq_ptp);
	kfree(qoriq_ptp);
@@ -434,6 +461,7 @@ static int qoriq_ptp_remove(struct platform_device *dev)

static const struct of_device_id match_table[] = {
	{ .compatible = "fsl,etsec-ptp" },
	{ .compatible = "fsl,fman-ptp-timer" },
	{},
};
MODULE_DEVICE_TABLE(of, match_table);
+31 −7
Original line number Diff line number Diff line
@@ -11,9 +11,8 @@

/*
 * qoriq ptp registers
 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
 */
struct qoriq_ptp_registers {
struct ctrl_regs {
	u32 tmr_ctrl;     /* Timer control register */
	u32 tmr_tevent;   /* Timestamp event register */
	u32 tmr_temask;   /* Timer event mask register */
@@ -28,22 +27,47 @@ struct qoriq_ptp_registers {
	u8  res1[4];
	u32 tmroff_h;     /* Timer offset high */
	u32 tmroff_l;     /* Timer offset low */
	u8  res2[8];
};

struct alarm_regs {
	u32 tmr_alarm1_h; /* Timer alarm 1 high register */
	u32 tmr_alarm1_l; /* Timer alarm 1 high register */
	u32 tmr_alarm2_h; /* Timer alarm 2 high register */
	u32 tmr_alarm2_l; /* Timer alarm 2 high register */
	u8  res3[48];
};

struct fiper_regs {
	u32 tmr_fiper1;   /* Timer fixed period interval */
	u32 tmr_fiper2;   /* Timer fixed period interval */
	u32 tmr_fiper3;   /* Timer fixed period interval */
	u8  res4[20];
};

struct etts_regs {
	u32 tmr_etts1_h;  /* Timestamp of general purpose external trigger */
	u32 tmr_etts1_l;  /* Timestamp of general purpose external trigger */
	u32 tmr_etts2_h;  /* Timestamp of general purpose external trigger */
	u32 tmr_etts2_l;  /* Timestamp of general purpose external trigger */
};

struct qoriq_ptp_registers {
	struct ctrl_regs __iomem *ctrl_regs;
	struct alarm_regs __iomem *alarm_regs;
	struct fiper_regs __iomem *fiper_regs;
	struct etts_regs __iomem *etts_regs;
};

/* Offset definitions for the four register groups */
#define CTRL_REGS_OFFSET	0x0
#define ALARM_REGS_OFFSET	0x40
#define FIPER_REGS_OFFSET	0x80
#define ETTS_REGS_OFFSET	0xa0

#define FMAN_CTRL_REGS_OFFSET	0x80
#define FMAN_ALARM_REGS_OFFSET	0xb8
#define FMAN_FIPER_REGS_OFFSET	0xd0
#define FMAN_ETTS_REGS_OFFSET	0xe0


/* Bit definitions for the TMR_CTRL register */
#define ALM1P                 (1<<31) /* Alarm1 output polarity */
#define ALM2P                 (1<<30) /* Alarm2 output polarity */
@@ -105,10 +129,10 @@ struct qoriq_ptp_registers {
#define DRIVER		"ptp_qoriq"
#define DEFAULT_CKSEL	1
#define N_EXT_TS	2
#define REG_SIZE	sizeof(struct qoriq_ptp_registers)

struct qoriq_ptp {
	struct qoriq_ptp_registers __iomem *regs;
	void __iomem *base;
	struct qoriq_ptp_registers regs;
	spinlock_t lock; /* protects regs */
	struct ptp_clock *clock;
	struct ptp_clock_info caps;