X-Git-Url: http://git.openwrt.org/?p=openwrt%2Fstaging%2Fdedeckeh.git;a=blobdiff_plain;f=target%2Flinux%2Flayerscape%2Fpatches-4.14%2F824-ptp-support-layerscape.patch;fp=target%2Flinux%2Flayerscape%2Fpatches-4.14%2F824-ptp-support-layerscape.patch;h=0000000000000000000000000000000000000000;hp=5664e18094a8320360cbc0bfb82ab00660b574c9;hb=4bbc0e735754acfd7c37eb87c2f2ceb46bafdb16;hpb=b1604b744b716a592841757c43bc5156c7772aca diff --git a/target/linux/layerscape/patches-4.14/824-ptp-support-layerscape.patch b/target/linux/layerscape/patches-4.14/824-ptp-support-layerscape.patch deleted file mode 100644 index 5664e18094..0000000000 --- a/target/linux/layerscape/patches-4.14/824-ptp-support-layerscape.patch +++ /dev/null @@ -1,1399 +0,0 @@ -From bba7af6efb0aad1d52ee5e7d80f9e2ab59d85e20 Mon Sep 17 00:00:00 2001 -From: Biwen Li -Date: Wed, 17 Apr 2019 18:58:52 +0800 -Subject: [PATCH] ptp: support layerscape - -This is an integrated patch of ptp for layerscape - -Signed-off-by: Arnd Bergmann -Signed-off-by: Biwen Li -Signed-off-by: David S. Miller -Signed-off-by: Yangbo Lu ---- - drivers/net/ethernet/freescale/Makefile | 1 - - drivers/net/ethernet/freescale/gianfar_ptp.c | 572 ------------------ - drivers/ptp/Makefile | 1 + - drivers/ptp/ptp_chardev.c | 4 +- - drivers/ptp/ptp_qoriq.c | 589 +++++++++++++++++++ - include/linux/fsl/ptp_qoriq.h | 169 ++++++ - 6 files changed, 761 insertions(+), 575 deletions(-) - delete mode 100644 drivers/net/ethernet/freescale/gianfar_ptp.c - create mode 100644 drivers/ptp/ptp_qoriq.c - create mode 100644 include/linux/fsl/ptp_qoriq.h - ---- a/drivers/net/ethernet/freescale/Makefile -+++ b/drivers/net/ethernet/freescale/Makefile -@@ -14,7 +14,6 @@ obj-$(CONFIG_FS_ENET) += fs_enet/ - obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o - obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o - obj-$(CONFIG_GIANFAR) += gianfar_driver.o --obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o - gianfar_driver-objs := gianfar.o \ - gianfar_ethtool.o - obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o ---- a/drivers/net/ethernet/freescale/gianfar_ptp.c -+++ /dev/null -@@ -1,572 +0,0 @@ --/* -- * PTP 1588 clock using the eTSEC -- * -- * Copyright (C) 2010 OMICRON electronics GmbH -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -- */ -- --#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -- --#include --#include --#include --#include --#include --#include --#include --#include --#include -- --#include -- --#include "gianfar.h" -- --/* -- * gianfar ptp registers -- * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010 -- */ --struct gianfar_ptp_registers { -- u32 tmr_ctrl; /* Timer control register */ -- u32 tmr_tevent; /* Timestamp event register */ -- u32 tmr_temask; /* Timer event mask register */ -- u32 tmr_pevent; /* Timestamp event register */ -- u32 tmr_pemask; /* Timer event mask register */ -- u32 tmr_stat; /* Timestamp status register */ -- u32 tmr_cnt_h; /* Timer counter high register */ -- u32 tmr_cnt_l; /* Timer counter low register */ -- u32 tmr_add; /* Timer drift compensation addend register */ -- u32 tmr_acc; /* Timer accumulator register */ -- u32 tmr_prsc; /* Timer prescale */ -- u8 res1[4]; -- u32 tmroff_h; /* Timer offset high */ -- u32 tmroff_l; /* Timer offset low */ -- u8 res2[8]; -- 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]; -- u32 tmr_fiper1; /* Timer fixed period interval */ -- u32 tmr_fiper2; /* Timer fixed period interval */ -- u32 tmr_fiper3; /* Timer fixed period interval */ -- u8 res4[20]; -- 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 */ --}; -- --/* Bit definitions for the TMR_CTRL register */ --#define ALM1P (1<<31) /* Alarm1 output polarity */ --#define ALM2P (1<<30) /* Alarm2 output polarity */ --#define FIPERST (1<<28) /* FIPER start indication */ --#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ --#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ --#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ --#define TCLK_PERIOD_MASK (0x3ff) --#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ --#define FRD (1<<14) /* FIPER Realignment Disable */ --#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ --#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ --#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ --#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ --#define COPH (1<<7) /* Generated clock output phase. */ --#define CIPH (1<<6) /* External oscillator input clock phase */ --#define TMSR (1<<5) /* Timer soft reset. */ --#define BYP (1<<3) /* Bypass drift compensated clock */ --#define TE (1<<2) /* 1588 timer enable. */ --#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ --#define CKSEL_MASK (0x3) -- --/* Bit definitions for the TMR_TEVENT register */ --#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ --#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ --#define ALM2 (1<<17) /* Current time = alarm time register 2 */ --#define ALM1 (1<<16) /* Current time = alarm time register 1 */ --#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ --#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ --#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ -- --/* Bit definitions for the TMR_TEMASK register */ --#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ --#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ --#define ALM2EN (1<<17) /* Timer ALM2 event enable */ --#define ALM1EN (1<<16) /* Timer ALM1 event enable */ --#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ --#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ -- --/* Bit definitions for the TMR_PEVENT register */ --#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ --#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ --#define RXP (1<<0) /* PTP frame has been received */ -- --/* Bit definitions for the TMR_PEMASK register */ --#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ --#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ --#define RXPEN (1<<0) /* Receive PTP packet event enable */ -- --/* Bit definitions for the TMR_STAT register */ --#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ --#define STAT_VEC_MASK (0x3f) -- --/* Bit definitions for the TMR_PRSC register */ --#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ --#define PRSC_OCK_MASK (0xffff) -- -- --#define DRIVER "gianfar_ptp" --#define DEFAULT_CKSEL 1 --#define N_EXT_TS 2 --#define REG_SIZE sizeof(struct gianfar_ptp_registers) -- --struct etsects { -- struct gianfar_ptp_registers __iomem *regs; -- spinlock_t lock; /* protects regs */ -- struct ptp_clock *clock; -- struct ptp_clock_info caps; -- struct resource *rsrc; -- int irq; -- u64 alarm_interval; /* for periodic alarm */ -- u64 alarm_value; -- u32 tclk_period; /* nanoseconds */ -- u32 tmr_prsc; -- u32 tmr_add; -- u32 cksel; -- u32 tmr_fiper1; -- u32 tmr_fiper2; --}; -- --/* -- * Register access functions -- */ -- --/* Caller must hold etsects->lock. */ --static u64 tmr_cnt_read(struct etsects *etsects) --{ -- u64 ns; -- u32 lo, hi; -- -- lo = gfar_read(&etsects->regs->tmr_cnt_l); -- hi = gfar_read(&etsects->regs->tmr_cnt_h); -- ns = ((u64) hi) << 32; -- ns |= lo; -- return ns; --} -- --/* Caller must hold etsects->lock. */ --static void tmr_cnt_write(struct etsects *etsects, u64 ns) --{ -- u32 hi = ns >> 32; -- u32 lo = ns & 0xffffffff; -- -- gfar_write(&etsects->regs->tmr_cnt_l, lo); -- gfar_write(&etsects->regs->tmr_cnt_h, hi); --} -- --/* Caller must hold etsects->lock. */ --static void set_alarm(struct etsects *etsects) --{ -- u64 ns; -- u32 lo, hi; -- -- ns = tmr_cnt_read(etsects) + 1500000000ULL; -- ns = div_u64(ns, 1000000000UL) * 1000000000ULL; -- ns -= etsects->tclk_period; -- hi = ns >> 32; -- lo = ns & 0xffffffff; -- gfar_write(&etsects->regs->tmr_alarm1_l, lo); -- gfar_write(&etsects->regs->tmr_alarm1_h, hi); --} -- --/* Caller must hold etsects->lock. */ --static void set_fipers(struct etsects *etsects) --{ -- set_alarm(etsects); -- gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); -- gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); --} -- --/* -- * Interrupt service routine -- */ -- --static irqreturn_t isr(int irq, void *priv) --{ -- struct etsects *etsects = priv; -- struct ptp_clock_event event; -- u64 ns; -- u32 ack = 0, lo, hi, mask, val; -- -- val = gfar_read(&etsects->regs->tmr_tevent); -- -- if (val & ETS1) { -- ack |= ETS1; -- hi = gfar_read(&etsects->regs->tmr_etts1_h); -- lo = gfar_read(&etsects->regs->tmr_etts1_l); -- event.type = PTP_CLOCK_EXTTS; -- event.index = 0; -- event.timestamp = ((u64) hi) << 32; -- event.timestamp |= lo; -- ptp_clock_event(etsects->clock, &event); -- } -- -- if (val & ETS2) { -- ack |= ETS2; -- hi = gfar_read(&etsects->regs->tmr_etts2_h); -- lo = gfar_read(&etsects->regs->tmr_etts2_l); -- event.type = PTP_CLOCK_EXTTS; -- event.index = 1; -- event.timestamp = ((u64) hi) << 32; -- event.timestamp |= lo; -- ptp_clock_event(etsects->clock, &event); -- } -- -- if (val & ALM2) { -- ack |= ALM2; -- if (etsects->alarm_value) { -- event.type = PTP_CLOCK_ALARM; -- event.index = 0; -- event.timestamp = etsects->alarm_value; -- ptp_clock_event(etsects->clock, &event); -- } -- if (etsects->alarm_interval) { -- ns = etsects->alarm_value + etsects->alarm_interval; -- hi = ns >> 32; -- lo = ns & 0xffffffff; -- spin_lock(&etsects->lock); -- gfar_write(&etsects->regs->tmr_alarm2_l, lo); -- gfar_write(&etsects->regs->tmr_alarm2_h, hi); -- spin_unlock(&etsects->lock); -- etsects->alarm_value = ns; -- } else { -- gfar_write(&etsects->regs->tmr_tevent, ALM2); -- spin_lock(&etsects->lock); -- mask = gfar_read(&etsects->regs->tmr_temask); -- mask &= ~ALM2EN; -- gfar_write(&etsects->regs->tmr_temask, mask); -- spin_unlock(&etsects->lock); -- etsects->alarm_value = 0; -- etsects->alarm_interval = 0; -- } -- } -- -- if (val & PP1) { -- ack |= PP1; -- event.type = PTP_CLOCK_PPS; -- ptp_clock_event(etsects->clock, &event); -- } -- -- if (ack) { -- gfar_write(&etsects->regs->tmr_tevent, ack); -- return IRQ_HANDLED; -- } else -- return IRQ_NONE; --} -- --/* -- * PTP clock operations -- */ -- --static int ptp_gianfar_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) --{ -- u64 adj, diff; -- u32 tmr_add; -- int neg_adj = 0; -- struct etsects *etsects = container_of(ptp, struct etsects, caps); -- -- if (scaled_ppm < 0) { -- neg_adj = 1; -- scaled_ppm = -scaled_ppm; -- } -- tmr_add = etsects->tmr_add; -- adj = tmr_add; -- -- /* calculate diff as adj*(scaled_ppm/65536)/1000000 -- * and round() to the nearest integer -- */ -- adj *= scaled_ppm; -- diff = div_u64(adj, 8000000); -- diff = (diff >> 13) + ((diff >> 12) & 1); -- -- tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; -- -- gfar_write(&etsects->regs->tmr_add, tmr_add); -- -- return 0; --} -- --static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) --{ -- s64 now; -- unsigned long flags; -- struct etsects *etsects = container_of(ptp, struct etsects, caps); -- -- spin_lock_irqsave(&etsects->lock, flags); -- -- now = tmr_cnt_read(etsects); -- now += delta; -- tmr_cnt_write(etsects, now); -- set_fipers(etsects); -- -- spin_unlock_irqrestore(&etsects->lock, flags); -- -- return 0; --} -- --static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, -- struct timespec64 *ts) --{ -- u64 ns; -- unsigned long flags; -- struct etsects *etsects = container_of(ptp, struct etsects, caps); -- -- spin_lock_irqsave(&etsects->lock, flags); -- -- ns = tmr_cnt_read(etsects); -- -- spin_unlock_irqrestore(&etsects->lock, flags); -- -- *ts = ns_to_timespec64(ns); -- -- return 0; --} -- --static int ptp_gianfar_settime(struct ptp_clock_info *ptp, -- const struct timespec64 *ts) --{ -- u64 ns; -- unsigned long flags; -- struct etsects *etsects = container_of(ptp, struct etsects, caps); -- -- ns = timespec64_to_ns(ts); -- -- spin_lock_irqsave(&etsects->lock, flags); -- -- tmr_cnt_write(etsects, ns); -- set_fipers(etsects); -- -- spin_unlock_irqrestore(&etsects->lock, flags); -- -- return 0; --} -- --static int ptp_gianfar_enable(struct ptp_clock_info *ptp, -- struct ptp_clock_request *rq, int on) --{ -- struct etsects *etsects = container_of(ptp, struct etsects, caps); -- unsigned long flags; -- u32 bit, mask; -- -- switch (rq->type) { -- case PTP_CLK_REQ_EXTTS: -- switch (rq->extts.index) { -- case 0: -- bit = ETS1EN; -- break; -- case 1: -- bit = ETS2EN; -- break; -- default: -- return -EINVAL; -- } -- spin_lock_irqsave(&etsects->lock, flags); -- mask = gfar_read(&etsects->regs->tmr_temask); -- if (on) -- mask |= bit; -- else -- mask &= ~bit; -- gfar_write(&etsects->regs->tmr_temask, mask); -- spin_unlock_irqrestore(&etsects->lock, flags); -- return 0; -- -- case PTP_CLK_REQ_PPS: -- spin_lock_irqsave(&etsects->lock, flags); -- mask = gfar_read(&etsects->regs->tmr_temask); -- if (on) -- mask |= PP1EN; -- else -- mask &= ~PP1EN; -- gfar_write(&etsects->regs->tmr_temask, mask); -- spin_unlock_irqrestore(&etsects->lock, flags); -- return 0; -- -- default: -- break; -- } -- -- return -EOPNOTSUPP; --} -- --static const struct ptp_clock_info ptp_gianfar_caps = { -- .owner = THIS_MODULE, -- .name = "gianfar clock", -- .max_adj = 512000, -- .n_alarm = 0, -- .n_ext_ts = N_EXT_TS, -- .n_per_out = 0, -- .n_pins = 0, -- .pps = 1, -- .adjfine = ptp_gianfar_adjfine, -- .adjtime = ptp_gianfar_adjtime, -- .gettime64 = ptp_gianfar_gettime, -- .settime64 = ptp_gianfar_settime, -- .enable = ptp_gianfar_enable, --}; -- --static int gianfar_ptp_probe(struct platform_device *dev) --{ -- struct device_node *node = dev->dev.of_node; -- struct etsects *etsects; -- struct timespec64 now; -- int err = -ENOMEM; -- u32 tmr_ctrl; -- unsigned long flags; -- -- etsects = kzalloc(sizeof(*etsects), GFP_KERNEL); -- if (!etsects) -- goto no_memory; -- -- err = -ENODEV; -- -- etsects->caps = ptp_gianfar_caps; -- -- if (of_property_read_u32(node, "fsl,cksel", &etsects->cksel)) -- etsects->cksel = DEFAULT_CKSEL; -- -- if (of_property_read_u32(node, -- "fsl,tclk-period", &etsects->tclk_period) || -- of_property_read_u32(node, -- "fsl,tmr-prsc", &etsects->tmr_prsc) || -- of_property_read_u32(node, -- "fsl,tmr-add", &etsects->tmr_add) || -- of_property_read_u32(node, -- "fsl,tmr-fiper1", &etsects->tmr_fiper1) || -- of_property_read_u32(node, -- "fsl,tmr-fiper2", &etsects->tmr_fiper2) || -- of_property_read_u32(node, -- "fsl,max-adj", &etsects->caps.max_adj)) { -- pr_err("device tree node missing required elements\n"); -- goto no_node; -- } -- -- etsects->irq = platform_get_irq(dev, 0); -- -- if (etsects->irq < 0) { -- pr_err("irq not in device tree\n"); -- goto no_node; -- } -- if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) { -- pr_err("request_irq failed\n"); -- goto no_node; -- } -- -- etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); -- if (!etsects->rsrc) { -- pr_err("no resource\n"); -- goto no_resource; -- } -- if (request_resource(&iomem_resource, etsects->rsrc)) { -- pr_err("resource busy\n"); -- goto no_resource; -- } -- -- spin_lock_init(&etsects->lock); -- -- etsects->regs = ioremap(etsects->rsrc->start, -- resource_size(etsects->rsrc)); -- if (!etsects->regs) { -- pr_err("ioremap ptp registers failed\n"); -- goto no_ioremap; -- } -- getnstimeofday64(&now); -- ptp_gianfar_settime(&etsects->caps, &now); -- -- tmr_ctrl = -- (etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | -- (etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT; -- -- spin_lock_irqsave(&etsects->lock, flags); -- -- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl); -- gfar_write(&etsects->regs->tmr_add, etsects->tmr_add); -- gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); -- gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); -- gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); -- set_alarm(etsects); -- gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); -- -- spin_unlock_irqrestore(&etsects->lock, flags); -- -- etsects->clock = ptp_clock_register(&etsects->caps, &dev->dev); -- if (IS_ERR(etsects->clock)) { -- err = PTR_ERR(etsects->clock); -- goto no_clock; -- } -- gfar_phc_index = ptp_clock_index(etsects->clock); -- -- platform_set_drvdata(dev, etsects); -- -- return 0; -- --no_clock: -- iounmap(etsects->regs); --no_ioremap: -- release_resource(etsects->rsrc); --no_resource: -- free_irq(etsects->irq, etsects); --no_node: -- kfree(etsects); --no_memory: -- return err; --} -- --static int gianfar_ptp_remove(struct platform_device *dev) --{ -- struct etsects *etsects = platform_get_drvdata(dev); -- -- gfar_write(&etsects->regs->tmr_temask, 0); -- gfar_write(&etsects->regs->tmr_ctrl, 0); -- -- gfar_phc_index = -1; -- ptp_clock_unregister(etsects->clock); -- iounmap(etsects->regs); -- release_resource(etsects->rsrc); -- free_irq(etsects->irq, etsects); -- kfree(etsects); -- -- return 0; --} -- --static const struct of_device_id match_table[] = { -- { .compatible = "fsl,etsec-ptp" }, -- {}, --}; --MODULE_DEVICE_TABLE(of, match_table); -- --static struct platform_driver gianfar_ptp_driver = { -- .driver = { -- .name = "gianfar_ptp", -- .of_match_table = match_table, -- }, -- .probe = gianfar_ptp_probe, -- .remove = gianfar_ptp_remove, --}; -- --module_platform_driver(gianfar_ptp_driver); -- --MODULE_AUTHOR("Richard Cochran "); --MODULE_DESCRIPTION("PTP clock using the eTSEC"); --MODULE_LICENSE("GPL"); ---- a/drivers/ptp/Makefile -+++ b/drivers/ptp/Makefile -@@ -9,3 +9,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_ - 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 ---- a/drivers/ptp/ptp_chardev.c -+++ b/drivers/ptp/ptp_chardev.c -@@ -224,7 +224,7 @@ long ptp_ioctl(struct posix_clock *pc, u - } - pct = &sysoff->ts[0]; - for (i = 0; i < sysoff->n_samples; i++) { -- getnstimeofday64(&ts); -+ ktime_get_real_ts64(&ts); - pct->sec = ts.tv_sec; - pct->nsec = ts.tv_nsec; - pct++; -@@ -235,7 +235,7 @@ long ptp_ioctl(struct posix_clock *pc, u - pct->nsec = ts.tv_nsec; - pct++; - } -- getnstimeofday64(&ts); -+ ktime_get_real_ts64(&ts); - pct->sec = ts.tv_sec; - pct->nsec = ts.tv_nsec; - if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff))) ---- /dev/null -+++ b/drivers/ptp/ptp_qoriq.c -@@ -0,0 +1,589 @@ -+/* -+ * PTP 1588 clock for Freescale QorIQ 1588 timer -+ * -+ * Copyright (C) 2010 OMICRON electronics GmbH -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+/* -+ * Register access functions -+ */ -+ -+/* 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(®s->ctrl_regs->tmr_cnt_l); -+ hi = qoriq_read(®s->ctrl_regs->tmr_cnt_h); -+ ns = ((u64) hi) << 32; -+ ns |= lo; -+ return ns; -+} -+ -+/* 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(®s->ctrl_regs->tmr_cnt_l, lo); -+ qoriq_write(®s->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; -+ -+ ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL; -+ ns = div_u64(ns, 1000000000UL) * 1000000000ULL; -+ ns -= qoriq_ptp->tclk_period; -+ hi = ns >> 32; -+ lo = ns & 0xffffffff; -+ qoriq_write(®s->alarm_regs->tmr_alarm1_l, lo); -+ qoriq_write(®s->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(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); -+ qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); -+} -+ -+/* -+ * Interrupt service routine -+ */ -+ -+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(®s->ctrl_regs->tmr_tevent); -+ -+ if (val & ETS1) { -+ ack |= ETS1; -+ hi = qoriq_read(®s->etts_regs->tmr_etts1_h); -+ lo = qoriq_read(®s->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 (val & ETS2) { -+ ack |= ETS2; -+ hi = qoriq_read(®s->etts_regs->tmr_etts2_h); -+ lo = qoriq_read(®s->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 (val & ALM2) { -+ ack |= ALM2; -+ if (qoriq_ptp->alarm_value) { -+ event.type = PTP_CLOCK_ALARM; -+ event.index = 0; -+ event.timestamp = qoriq_ptp->alarm_value; -+ ptp_clock_event(qoriq_ptp->clock, &event); -+ } -+ if (qoriq_ptp->alarm_interval) { -+ ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval; -+ hi = ns >> 32; -+ lo = ns & 0xffffffff; -+ spin_lock(&qoriq_ptp->lock); -+ qoriq_write(®s->alarm_regs->tmr_alarm2_l, lo); -+ qoriq_write(®s->alarm_regs->tmr_alarm2_h, hi); -+ spin_unlock(&qoriq_ptp->lock); -+ qoriq_ptp->alarm_value = ns; -+ } else { -+ qoriq_write(®s->ctrl_regs->tmr_tevent, ALM2); -+ spin_lock(&qoriq_ptp->lock); -+ mask = qoriq_read(®s->ctrl_regs->tmr_temask); -+ mask &= ~ALM2EN; -+ qoriq_write(®s->ctrl_regs->tmr_temask, mask); -+ spin_unlock(&qoriq_ptp->lock); -+ qoriq_ptp->alarm_value = 0; -+ qoriq_ptp->alarm_interval = 0; -+ } -+ } -+ -+ if (val & PP1) { -+ ack |= PP1; -+ event.type = PTP_CLOCK_PPS; -+ ptp_clock_event(qoriq_ptp->clock, &event); -+ } -+ -+ if (ack) { -+ qoriq_write(®s->ctrl_regs->tmr_tevent, ack); -+ return IRQ_HANDLED; -+ } else -+ return IRQ_NONE; -+} -+ -+/* -+ * PTP clock operations -+ */ -+ -+static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) -+{ -+ u64 adj, diff; -+ 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; -+ scaled_ppm = -scaled_ppm; -+ } -+ tmr_add = qoriq_ptp->tmr_add; -+ adj = tmr_add; -+ -+ /* calculate diff as adj*(scaled_ppm/65536)/1000000 -+ * and round() to the nearest integer -+ */ -+ adj *= scaled_ppm; -+ diff = div_u64(adj, 8000000); -+ diff = (diff >> 13) + ((diff >> 12) & 1); -+ -+ tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; -+ -+ qoriq_write(®s->ctrl_regs->tmr_add, tmr_add); -+ -+ return 0; -+} -+ -+static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) -+{ -+ s64 now; -+ unsigned long flags; -+ struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); -+ -+ spin_lock_irqsave(&qoriq_ptp->lock, flags); -+ -+ now = tmr_cnt_read(qoriq_ptp); -+ now += delta; -+ tmr_cnt_write(qoriq_ptp, now); -+ set_fipers(qoriq_ptp); -+ -+ spin_unlock_irqrestore(&qoriq_ptp->lock, flags); -+ -+ return 0; -+} -+ -+static int ptp_qoriq_gettime(struct ptp_clock_info *ptp, -+ struct timespec64 *ts) -+{ -+ u64 ns; -+ unsigned long flags; -+ struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); -+ -+ spin_lock_irqsave(&qoriq_ptp->lock, flags); -+ -+ ns = tmr_cnt_read(qoriq_ptp); -+ -+ spin_unlock_irqrestore(&qoriq_ptp->lock, flags); -+ -+ *ts = ns_to_timespec64(ns); -+ -+ return 0; -+} -+ -+static int ptp_qoriq_settime(struct ptp_clock_info *ptp, -+ const struct timespec64 *ts) -+{ -+ u64 ns; -+ unsigned long flags; -+ struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); -+ -+ ns = timespec64_to_ns(ts); -+ -+ spin_lock_irqsave(&qoriq_ptp->lock, flags); -+ -+ tmr_cnt_write(qoriq_ptp, ns); -+ set_fipers(qoriq_ptp); -+ -+ spin_unlock_irqrestore(&qoriq_ptp->lock, flags); -+ -+ return 0; -+} -+ -+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; -+ -+ switch (rq->type) { -+ case PTP_CLK_REQ_EXTTS: -+ switch (rq->extts.index) { -+ case 0: -+ bit = ETS1EN; -+ break; -+ case 1: -+ bit = ETS2EN; -+ break; -+ default: -+ return -EINVAL; -+ } -+ spin_lock_irqsave(&qoriq_ptp->lock, flags); -+ mask = qoriq_read(®s->ctrl_regs->tmr_temask); -+ if (on) -+ mask |= bit; -+ else -+ mask &= ~bit; -+ qoriq_write(®s->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(®s->ctrl_regs->tmr_temask); -+ if (on) -+ mask |= PP1EN; -+ else -+ mask &= ~PP1EN; -+ qoriq_write(®s->ctrl_regs->tmr_temask, mask); -+ spin_unlock_irqrestore(&qoriq_ptp->lock, flags); -+ return 0; -+ -+ default: -+ break; -+ } -+ -+ return -EOPNOTSUPP; -+} -+ -+static const struct ptp_clock_info ptp_qoriq_caps = { -+ .owner = THIS_MODULE, -+ .name = "qoriq ptp clock", -+ .max_adj = 512000, -+ .n_alarm = 0, -+ .n_ext_ts = N_EXT_TS, -+ .n_per_out = 0, -+ .n_pins = 0, -+ .pps = 1, -+ .adjfine = ptp_qoriq_adjfine, -+ .adjtime = ptp_qoriq_adjtime, -+ .gettime64 = ptp_qoriq_gettime, -+ .settime64 = ptp_qoriq_settime, -+ .enable = ptp_qoriq_enable, -+}; -+ -+/** -+ * qoriq_ptp_nominal_freq - calculate nominal frequency according to -+ * reference clock frequency -+ * -+ * @clk_src: reference clock frequency -+ * -+ * The nominal frequency is the desired clock frequency. -+ * It should be less than the reference clock frequency. -+ * It should be a factor of 1000MHz. -+ * -+ * Return the nominal frequency -+ */ -+static u32 qoriq_ptp_nominal_freq(u32 clk_src) -+{ -+ u32 remainder = 0; -+ -+ clk_src /= 1000000; -+ remainder = clk_src % 100; -+ if (remainder) { -+ clk_src -= remainder; -+ clk_src += 100; -+ } -+ -+ do { -+ clk_src -= 100; -+ -+ } while (1000 % clk_src); -+ -+ return clk_src * 1000000; -+} -+ -+/** -+ * qoriq_ptp_auto_config - calculate a set of default configurations -+ * -+ * @qoriq_ptp: pointer to qoriq_ptp -+ * @node: pointer to device_node -+ * -+ * If below dts properties are not provided, this function will be -+ * called to calculate a set of default configurations for them. -+ * "fsl,tclk-period" -+ * "fsl,tmr-prsc" -+ * "fsl,tmr-add" -+ * "fsl,tmr-fiper1" -+ * "fsl,tmr-fiper2" -+ * "fsl,max-adj" -+ * -+ * Return 0 if success -+ */ -+static int qoriq_ptp_auto_config(struct qoriq_ptp *qoriq_ptp, -+ struct device_node *node) -+{ -+ struct clk *clk; -+ u64 freq_comp; -+ u64 max_adj; -+ u32 nominal_freq; -+ u32 remainder = 0; -+ u32 clk_src = 0; -+ -+ qoriq_ptp->cksel = DEFAULT_CKSEL; -+ -+ clk = of_clk_get(node, 0); -+ if (!IS_ERR(clk)) { -+ clk_src = clk_get_rate(clk); -+ clk_put(clk); -+ } -+ -+ if (clk_src <= 100000000UL) { -+ pr_err("error reference clock value, or lower than 100MHz\n"); -+ return -EINVAL; -+ } -+ -+ nominal_freq = qoriq_ptp_nominal_freq(clk_src); -+ if (!nominal_freq) -+ return -EINVAL; -+ -+ qoriq_ptp->tclk_period = 1000000000UL / nominal_freq; -+ qoriq_ptp->tmr_prsc = DEFAULT_TMR_PRSC; -+ -+ /* Calculate initial frequency compensation value for TMR_ADD register. -+ * freq_comp = ceil(2^32 / freq_ratio) -+ * freq_ratio = reference_clock_freq / nominal_freq -+ */ -+ freq_comp = ((u64)1 << 32) * nominal_freq; -+ freq_comp = div_u64_rem(freq_comp, clk_src, &remainder); -+ if (remainder) -+ freq_comp++; -+ -+ qoriq_ptp->tmr_add = freq_comp; -+ qoriq_ptp->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - qoriq_ptp->tclk_period; -+ qoriq_ptp->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - qoriq_ptp->tclk_period; -+ -+ /* max_adj = 1000000000 * (freq_ratio - 1.0) - 1 -+ * freq_ratio = reference_clock_freq / nominal_freq -+ */ -+ max_adj = 1000000000ULL * (clk_src - nominal_freq); -+ max_adj = div_u64(max_adj, nominal_freq) - 1; -+ qoriq_ptp->caps.max_adj = max_adj; -+ -+ return 0; -+} -+ -+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) -+ goto no_memory; -+ -+ err = -EINVAL; -+ -+ 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_u32(node, -+ "fsl,tclk-period", &qoriq_ptp->tclk_period) || -+ of_property_read_u32(node, -+ "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) || -+ of_property_read_u32(node, -+ "fsl,tmr-add", &qoriq_ptp->tmr_add) || -+ of_property_read_u32(node, -+ "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) || -+ of_property_read_u32(node, -+ "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) || -+ of_property_read_u32(node, -+ "fsl,max-adj", &qoriq_ptp->caps.max_adj)) { -+ pr_warn("device tree node missing required elements, try automatic configuration\n"); -+ -+ if (qoriq_ptp_auto_config(qoriq_ptp, node)) -+ goto no_config; -+ } -+ -+ err = -ENODEV; -+ -+ qoriq_ptp->irq = platform_get_irq(dev, 0); -+ -+ if (qoriq_ptp->irq < 0) { -+ pr_err("irq not in device tree\n"); -+ goto no_node; -+ } -+ if (request_irq(qoriq_ptp->irq, isr, IRQF_SHARED, DRIVER, qoriq_ptp)) { -+ pr_err("request_irq failed\n"); -+ goto no_node; -+ } -+ -+ qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); -+ if (!qoriq_ptp->rsrc) { -+ pr_err("no resource\n"); -+ goto no_resource; -+ } -+ if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) { -+ pr_err("resource busy\n"); -+ goto no_resource; -+ } -+ -+ spin_lock_init(&qoriq_ptp->lock); -+ -+ base = ioremap(qoriq_ptp->rsrc->start, -+ resource_size(qoriq_ptp->rsrc)); -+ 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); -+ -+ tmr_ctrl = -+ (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | -+ (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT; -+ -+ spin_lock_irqsave(&qoriq_ptp->lock, flags); -+ -+ regs = &qoriq_ptp->regs; -+ qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl); -+ qoriq_write(®s->ctrl_regs->tmr_add, qoriq_ptp->tmr_add); -+ qoriq_write(®s->ctrl_regs->tmr_prsc, qoriq_ptp->tmr_prsc); -+ qoriq_write(®s->fiper_regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); -+ qoriq_write(®s->fiper_regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); -+ set_alarm(qoriq_ptp); -+ qoriq_write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); -+ -+ spin_unlock_irqrestore(&qoriq_ptp->lock, flags); -+ -+ qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev); -+ if (IS_ERR(qoriq_ptp->clock)) { -+ err = PTR_ERR(qoriq_ptp->clock); -+ goto no_clock; -+ } -+ qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock); -+ -+ platform_set_drvdata(dev, qoriq_ptp); -+ -+ return 0; -+ -+no_clock: -+ iounmap(qoriq_ptp->base); -+no_ioremap: -+ release_resource(qoriq_ptp->rsrc); -+no_resource: -+ free_irq(qoriq_ptp->irq, qoriq_ptp); -+no_config: -+no_node: -+ kfree(qoriq_ptp); -+no_memory: -+ return err; -+} -+ -+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(®s->ctrl_regs->tmr_temask, 0); -+ qoriq_write(®s->ctrl_regs->tmr_ctrl, 0); -+ -+ ptp_clock_unregister(qoriq_ptp->clock); -+ iounmap(qoriq_ptp->base); -+ release_resource(qoriq_ptp->rsrc); -+ free_irq(qoriq_ptp->irq, qoriq_ptp); -+ kfree(qoriq_ptp); -+ -+ return 0; -+} -+ -+static const struct of_device_id match_table[] = { -+ { .compatible = "fsl,etsec-ptp" }, -+ { .compatible = "fsl,fman-ptp-timer" }, -+ {}, -+}; -+MODULE_DEVICE_TABLE(of, match_table); -+ -+static struct platform_driver qoriq_ptp_driver = { -+ .driver = { -+ .name = "ptp_qoriq", -+ .of_match_table = match_table, -+ }, -+ .probe = qoriq_ptp_probe, -+ .remove = qoriq_ptp_remove, -+}; -+ -+module_platform_driver(qoriq_ptp_driver); -+ -+MODULE_AUTHOR("Richard Cochran "); -+MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer"); -+MODULE_LICENSE("GPL"); ---- /dev/null -+++ b/include/linux/fsl/ptp_qoriq.h -@@ -0,0 +1,169 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* -+ * Copyright (C) 2010 OMICRON electronics GmbH -+ * Copyright 2018 NXP -+ */ -+#ifndef __PTP_QORIQ_H__ -+#define __PTP_QORIQ_H__ -+ -+#include -+#include -+ -+/* -+ * 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 */ -+ u32 tmr_pevent; /* Timestamp event register */ -+ u32 tmr_pemask; /* Timer event mask register */ -+ u32 tmr_stat; /* Timestamp status register */ -+ u32 tmr_cnt_h; /* Timer counter high register */ -+ u32 tmr_cnt_l; /* Timer counter low register */ -+ u32 tmr_add; /* Timer drift compensation addend register */ -+ u32 tmr_acc; /* Timer accumulator register */ -+ u32 tmr_prsc; /* Timer prescale */ -+ u8 res1[4]; -+ u32 tmroff_h; /* Timer offset high */ -+ u32 tmroff_l; /* Timer offset low */ -+}; -+ -+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 */ -+}; -+ -+struct fiper_regs { -+ u32 tmr_fiper1; /* Timer fixed period interval */ -+ u32 tmr_fiper2; /* Timer fixed period interval */ -+ u32 tmr_fiper3; /* Timer fixed period interval */ -+}; -+ -+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 */ -+#define FIPERST (1<<28) /* FIPER start indication */ -+#define PP1L (1<<27) /* Fiper1 pulse loopback mode enabled. */ -+#define PP2L (1<<26) /* Fiper2 pulse loopback mode enabled. */ -+#define TCLK_PERIOD_SHIFT (16) /* 1588 timer reference clock period. */ -+#define TCLK_PERIOD_MASK (0x3ff) -+#define RTPE (1<<15) /* Record Tx Timestamp to PAL Enable. */ -+#define FRD (1<<14) /* FIPER Realignment Disable */ -+#define ESFDP (1<<11) /* External Tx/Rx SFD Polarity. */ -+#define ESFDE (1<<10) /* External Tx/Rx SFD Enable. */ -+#define ETEP2 (1<<9) /* External trigger 2 edge polarity */ -+#define ETEP1 (1<<8) /* External trigger 1 edge polarity */ -+#define COPH (1<<7) /* Generated clock output phase. */ -+#define CIPH (1<<6) /* External oscillator input clock phase */ -+#define TMSR (1<<5) /* Timer soft reset. */ -+#define BYP (1<<3) /* Bypass drift compensated clock */ -+#define TE (1<<2) /* 1588 timer enable. */ -+#define CKSEL_SHIFT (0) /* 1588 Timer reference clock source */ -+#define CKSEL_MASK (0x3) -+ -+/* Bit definitions for the TMR_TEVENT register */ -+#define ETS2 (1<<25) /* External trigger 2 timestamp sampled */ -+#define ETS1 (1<<24) /* External trigger 1 timestamp sampled */ -+#define ALM2 (1<<17) /* Current time = alarm time register 2 */ -+#define ALM1 (1<<16) /* Current time = alarm time register 1 */ -+#define PP1 (1<<7) /* periodic pulse generated on FIPER1 */ -+#define PP2 (1<<6) /* periodic pulse generated on FIPER2 */ -+#define PP3 (1<<5) /* periodic pulse generated on FIPER3 */ -+ -+/* Bit definitions for the TMR_TEMASK register */ -+#define ETS2EN (1<<25) /* External trigger 2 timestamp enable */ -+#define ETS1EN (1<<24) /* External trigger 1 timestamp enable */ -+#define ALM2EN (1<<17) /* Timer ALM2 event enable */ -+#define ALM1EN (1<<16) /* Timer ALM1 event enable */ -+#define PP1EN (1<<7) /* Periodic pulse event 1 enable */ -+#define PP2EN (1<<6) /* Periodic pulse event 2 enable */ -+ -+/* Bit definitions for the TMR_PEVENT register */ -+#define TXP2 (1<<9) /* PTP transmitted timestamp im TXTS2 */ -+#define TXP1 (1<<8) /* PTP transmitted timestamp in TXTS1 */ -+#define RXP (1<<0) /* PTP frame has been received */ -+ -+/* Bit definitions for the TMR_PEMASK register */ -+#define TXP2EN (1<<9) /* Transmit PTP packet event 2 enable */ -+#define TXP1EN (1<<8) /* Transmit PTP packet event 1 enable */ -+#define RXPEN (1<<0) /* Receive PTP packet event enable */ -+ -+/* Bit definitions for the TMR_STAT register */ -+#define STAT_VEC_SHIFT (0) /* Timer general purpose status vector */ -+#define STAT_VEC_MASK (0x3f) -+ -+/* Bit definitions for the TMR_PRSC register */ -+#define PRSC_OCK_SHIFT (0) /* Output clock division/prescale factor. */ -+#define PRSC_OCK_MASK (0xffff) -+ -+ -+#define DRIVER "ptp_qoriq" -+#define N_EXT_TS 2 -+ -+#define DEFAULT_CKSEL 1 -+#define DEFAULT_TMR_PRSC 2 -+#define DEFAULT_FIPER1_PERIOD 1000000000 -+#define DEFAULT_FIPER2_PERIOD 100000 -+ -+struct qoriq_ptp { -+ void __iomem *base; -+ struct qoriq_ptp_registers regs; -+ spinlock_t lock; /* protects regs */ -+ struct ptp_clock *clock; -+ struct ptp_clock_info caps; -+ struct resource *rsrc; -+ int irq; -+ int phc_index; -+ u64 alarm_interval; /* for periodic alarm */ -+ u64 alarm_value; -+ u32 tclk_period; /* nanoseconds */ -+ u32 tmr_prsc; -+ u32 tmr_add; -+ u32 cksel; -+ u32 tmr_fiper1; -+ u32 tmr_fiper2; -+}; -+ -+static inline u32 qoriq_read(unsigned __iomem *addr) -+{ -+ u32 val; -+ -+ val = ioread32be(addr); -+ return val; -+} -+ -+static inline void qoriq_write(unsigned __iomem *addr, u32 val) -+{ -+ iowrite32be(val, addr); -+} -+ -+#endif