ptp: rework gianfar_ptp as QorIQ common PTP driver

gianfar_ptp was the PTP clock driver for 1588 timer
module of Freescale QorIQ eTSEC (Enhanced Three-Speed
Ethernet Controllers) platforms. Actually QorIQ DPAA
(Data Path Acceleration Architecture) platforms is
also using the same 1588 timer module in hardware.

This patch is to rework gianfar_ptp as QorIQ common
PTP driver to support both DPAA and eTSEC. Moved
gianfar_ptp.c to drivers/ptp/, renamed it as
ptp_qoriq.c, and renamed many variables. There were
not any function changes.

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Yangbo Lu 2018-05-25 12:40:34 +08:00 committed by David S. Miller
parent b1d2e4e03f
commit ceefc71d4c
4 changed files with 174 additions and 162 deletions

View File

@ -14,7 +14,6 @@ obj-$(CONFIG_FS_ENET) += fs_enet/
obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o obj-$(CONFIG_FSL_PQ_MDIO) += fsl_pq_mdio.o
obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o obj-$(CONFIG_FSL_XGMAC_MDIO) += xgmac_mdio.o
obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_GIANFAR) += gianfar_driver.o
obj-$(CONFIG_PTP_1588_CLOCK_GIANFAR) += gianfar_ptp.o
gianfar_driver-objs := gianfar.o \ gianfar_driver-objs := gianfar.o \
gianfar_ethtool.o gianfar_ethtool.o
obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o

View File

@ -41,19 +41,19 @@ config PTP_1588_CLOCK_DTE
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called ptp_dte. will be called ptp_dte.
config PTP_1588_CLOCK_GIANFAR config PTP_1588_CLOCK_QORIQ
tristate "Freescale eTSEC as PTP clock" tristate "Freescale QorIQ 1588 timer as PTP clock"
depends on GIANFAR depends on GIANFAR
depends on PTP_1588_CLOCK depends on PTP_1588_CLOCK
default y default y
help help
This driver adds support for using the eTSEC as a PTP This driver adds support for using the Freescale QorIQ 1588
clock. This clock is only useful if your PTP programs are timer as a PTP clock. This clock is only useful if your PTP
getting hardware time stamps on the PTP Ethernet packets programs are getting hardware time stamps on the PTP Ethernet
using the SO_TIMESTAMPING API. packets using the SO_TIMESTAMPING API.
To compile this driver as a module, choose M here: the module To compile this driver as a module, choose M here: the module
will be called gianfar_ptp. will be called ptp_qoriq.
config PTP_1588_CLOCK_IXP46X config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock" tristate "Intel IXP46x as PTP clock"

View File

@ -9,3 +9,4 @@ obj-$(CONFIG_PTP_1588_CLOCK_DTE) += ptp_dte.o
obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o obj-$(CONFIG_PTP_1588_CLOCK_IXP46X) += ptp_ixp46x.o
obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o obj-$(CONFIG_PTP_1588_CLOCK_PCH) += ptp_pch.o
obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o obj-$(CONFIG_PTP_1588_CLOCK_KVM) += ptp_kvm.o
obj-$(CONFIG_PTP_1588_CLOCK_QORIQ) += ptp_qoriq.o

View File

@ -1,5 +1,5 @@
/* /*
* PTP 1588 clock using the eTSEC * PTP 1588 clock for Freescale QorIQ 1588 timer
* *
* Copyright (C) 2010 OMICRON electronics GmbH * Copyright (C) 2010 OMICRON electronics GmbH
* *
@ -29,16 +29,15 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/timex.h> #include <linux/timex.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h>
#include <linux/ptp_clock_kernel.h> #include <linux/ptp_clock_kernel.h>
#include "gianfar.h"
/* /*
* gianfar ptp registers * qoriq ptp registers
* Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010 * Generated by regen.tcl on Thu May 13 01:38:57 PM CEST 2010
*/ */
struct gianfar_ptp_registers { struct qoriq_ptp_registers {
u32 tmr_ctrl; /* Timer control register */ u32 tmr_ctrl; /* Timer control register */
u32 tmr_tevent; /* Timestamp event register */ u32 tmr_tevent; /* Timestamp event register */
u32 tmr_temask; /* Timer event mask register */ u32 tmr_temask; /* Timer event mask register */
@ -127,18 +126,19 @@ struct gianfar_ptp_registers {
#define PRSC_OCK_MASK (0xffff) #define PRSC_OCK_MASK (0xffff)
#define DRIVER "gianfar_ptp" #define DRIVER "ptp_qoriq"
#define DEFAULT_CKSEL 1 #define DEFAULT_CKSEL 1
#define N_EXT_TS 2 #define N_EXT_TS 2
#define REG_SIZE sizeof(struct gianfar_ptp_registers) #define REG_SIZE sizeof(struct qoriq_ptp_registers)
struct etsects { struct qoriq_ptp {
struct gianfar_ptp_registers __iomem *regs; struct qoriq_ptp_registers __iomem *regs;
spinlock_t lock; /* protects regs */ spinlock_t lock; /* protects regs */
struct ptp_clock *clock; struct ptp_clock *clock;
struct ptp_clock_info caps; struct ptp_clock_info caps;
struct resource *rsrc; struct resource *rsrc;
int irq; int irq;
int phc_index;
u64 alarm_interval; /* for periodic alarm */ u64 alarm_interval; /* for periodic alarm */
u64 alarm_value; u64 alarm_value;
u32 tclk_period; /* nanoseconds */ u32 tclk_period; /* nanoseconds */
@ -149,54 +149,67 @@ struct etsects {
u32 tmr_fiper2; 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);
}
/* /*
* Register access functions * Register access functions
*/ */
/* Caller must hold etsects->lock. */ /* Caller must hold qoriq_ptp->lock. */
static u64 tmr_cnt_read(struct etsects *etsects) static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp)
{ {
u64 ns; u64 ns;
u32 lo, hi; u32 lo, hi;
lo = gfar_read(&etsects->regs->tmr_cnt_l); lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l);
hi = gfar_read(&etsects->regs->tmr_cnt_h); hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h);
ns = ((u64) hi) << 32; ns = ((u64) hi) << 32;
ns |= lo; ns |= lo;
return ns; return ns;
} }
/* Caller must hold etsects->lock. */ /* Caller must hold qoriq_ptp->lock. */
static void tmr_cnt_write(struct etsects *etsects, u64 ns) static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns)
{ {
u32 hi = ns >> 32; u32 hi = ns >> 32;
u32 lo = ns & 0xffffffff; u32 lo = ns & 0xffffffff;
gfar_write(&etsects->regs->tmr_cnt_l, lo); qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo);
gfar_write(&etsects->regs->tmr_cnt_h, hi); qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi);
} }
/* Caller must hold etsects->lock. */ /* Caller must hold qoriq_ptp->lock. */
static void set_alarm(struct etsects *etsects) static void set_alarm(struct qoriq_ptp *qoriq_ptp)
{ {
u64 ns; u64 ns;
u32 lo, hi; u32 lo, hi;
ns = tmr_cnt_read(etsects) + 1500000000ULL; ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL;
ns = div_u64(ns, 1000000000UL) * 1000000000ULL; ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
ns -= etsects->tclk_period; ns -= qoriq_ptp->tclk_period;
hi = ns >> 32; hi = ns >> 32;
lo = ns & 0xffffffff; lo = ns & 0xffffffff;
gfar_write(&etsects->regs->tmr_alarm1_l, lo); qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo);
gfar_write(&etsects->regs->tmr_alarm1_h, hi); qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi);
} }
/* Caller must hold etsects->lock. */ /* Caller must hold qoriq_ptp->lock. */
static void set_fipers(struct etsects *etsects) static void set_fipers(struct qoriq_ptp *qoriq_ptp)
{ {
set_alarm(etsects); set_alarm(qoriq_ptp);
gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
} }
/* /*
@ -205,72 +218,72 @@ static void set_fipers(struct etsects *etsects)
static irqreturn_t isr(int irq, void *priv) static irqreturn_t isr(int irq, void *priv)
{ {
struct etsects *etsects = priv; struct qoriq_ptp *qoriq_ptp = priv;
struct ptp_clock_event event; struct ptp_clock_event event;
u64 ns; u64 ns;
u32 ack = 0, lo, hi, mask, val; u32 ack = 0, lo, hi, mask, val;
val = gfar_read(&etsects->regs->tmr_tevent); val = qoriq_read(&qoriq_ptp->regs->tmr_tevent);
if (val & ETS1) { if (val & ETS1) {
ack |= ETS1; ack |= ETS1;
hi = gfar_read(&etsects->regs->tmr_etts1_h); hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h);
lo = gfar_read(&etsects->regs->tmr_etts1_l); lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l);
event.type = PTP_CLOCK_EXTTS; event.type = PTP_CLOCK_EXTTS;
event.index = 0; event.index = 0;
event.timestamp = ((u64) hi) << 32; event.timestamp = ((u64) hi) << 32;
event.timestamp |= lo; event.timestamp |= lo;
ptp_clock_event(etsects->clock, &event); ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (val & ETS2) { if (val & ETS2) {
ack |= ETS2; ack |= ETS2;
hi = gfar_read(&etsects->regs->tmr_etts2_h); hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h);
lo = gfar_read(&etsects->regs->tmr_etts2_l); lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l);
event.type = PTP_CLOCK_EXTTS; event.type = PTP_CLOCK_EXTTS;
event.index = 1; event.index = 1;
event.timestamp = ((u64) hi) << 32; event.timestamp = ((u64) hi) << 32;
event.timestamp |= lo; event.timestamp |= lo;
ptp_clock_event(etsects->clock, &event); ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (val & ALM2) { if (val & ALM2) {
ack |= ALM2; ack |= ALM2;
if (etsects->alarm_value) { if (qoriq_ptp->alarm_value) {
event.type = PTP_CLOCK_ALARM; event.type = PTP_CLOCK_ALARM;
event.index = 0; event.index = 0;
event.timestamp = etsects->alarm_value; event.timestamp = qoriq_ptp->alarm_value;
ptp_clock_event(etsects->clock, &event); ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (etsects->alarm_interval) { if (qoriq_ptp->alarm_interval) {
ns = etsects->alarm_value + etsects->alarm_interval; ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval;
hi = ns >> 32; hi = ns >> 32;
lo = ns & 0xffffffff; lo = ns & 0xffffffff;
spin_lock(&etsects->lock); spin_lock(&qoriq_ptp->lock);
gfar_write(&etsects->regs->tmr_alarm2_l, lo); qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo);
gfar_write(&etsects->regs->tmr_alarm2_h, hi); qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi);
spin_unlock(&etsects->lock); spin_unlock(&qoriq_ptp->lock);
etsects->alarm_value = ns; qoriq_ptp->alarm_value = ns;
} else { } else {
gfar_write(&etsects->regs->tmr_tevent, ALM2); qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2);
spin_lock(&etsects->lock); spin_lock(&qoriq_ptp->lock);
mask = gfar_read(&etsects->regs->tmr_temask); mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
mask &= ~ALM2EN; mask &= ~ALM2EN;
gfar_write(&etsects->regs->tmr_temask, mask); qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
spin_unlock(&etsects->lock); spin_unlock(&qoriq_ptp->lock);
etsects->alarm_value = 0; qoriq_ptp->alarm_value = 0;
etsects->alarm_interval = 0; qoriq_ptp->alarm_interval = 0;
} }
} }
if (val & PP1) { if (val & PP1) {
ack |= PP1; ack |= PP1;
event.type = PTP_CLOCK_PPS; event.type = PTP_CLOCK_PPS;
ptp_clock_event(etsects->clock, &event); ptp_clock_event(qoriq_ptp->clock, &event);
} }
if (ack) { if (ack) {
gfar_write(&etsects->regs->tmr_tevent, ack); qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack);
return IRQ_HANDLED; return IRQ_HANDLED;
} else } else
return IRQ_NONE; return IRQ_NONE;
@ -280,18 +293,18 @@ static irqreturn_t isr(int irq, void *priv)
* PTP clock operations * PTP clock operations
*/ */
static int ptp_gianfar_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
{ {
u64 adj, diff; u64 adj, diff;
u32 tmr_add; u32 tmr_add;
int neg_adj = 0; int neg_adj = 0;
struct etsects *etsects = container_of(ptp, struct etsects, caps); struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
if (scaled_ppm < 0) { if (scaled_ppm < 0) {
neg_adj = 1; neg_adj = 1;
scaled_ppm = -scaled_ppm; scaled_ppm = -scaled_ppm;
} }
tmr_add = etsects->tmr_add; tmr_add = qoriq_ptp->tmr_add;
adj = tmr_add; adj = tmr_add;
/* calculate diff as adj*(scaled_ppm/65536)/1000000 /* calculate diff as adj*(scaled_ppm/65536)/1000000
@ -303,70 +316,70 @@ static int ptp_gianfar_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
gfar_write(&etsects->regs->tmr_add, tmr_add); qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add);
return 0; return 0;
} }
static int ptp_gianfar_adjtime(struct ptp_clock_info *ptp, s64 delta) static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
{ {
s64 now; s64 now;
unsigned long flags; unsigned long flags;
struct etsects *etsects = container_of(ptp, struct etsects, caps); struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
now = tmr_cnt_read(etsects); now = tmr_cnt_read(qoriq_ptp);
now += delta; now += delta;
tmr_cnt_write(etsects, now); tmr_cnt_write(qoriq_ptp, now);
set_fipers(etsects); set_fipers(qoriq_ptp);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0; return 0;
} }
static int ptp_gianfar_gettime(struct ptp_clock_info *ptp, static int ptp_qoriq_gettime(struct ptp_clock_info *ptp,
struct timespec64 *ts) struct timespec64 *ts)
{ {
u64 ns; u64 ns;
unsigned long flags; unsigned long flags;
struct etsects *etsects = container_of(ptp, struct etsects, caps); struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
ns = tmr_cnt_read(etsects); ns = tmr_cnt_read(qoriq_ptp);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
*ts = ns_to_timespec64(ns); *ts = ns_to_timespec64(ns);
return 0; return 0;
} }
static int ptp_gianfar_settime(struct ptp_clock_info *ptp, static int ptp_qoriq_settime(struct ptp_clock_info *ptp,
const struct timespec64 *ts) const struct timespec64 *ts)
{ {
u64 ns; u64 ns;
unsigned long flags; unsigned long flags;
struct etsects *etsects = container_of(ptp, struct etsects, caps); struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
ns = timespec64_to_ns(ts); ns = timespec64_to_ns(ts);
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
tmr_cnt_write(etsects, ns); tmr_cnt_write(qoriq_ptp, ns);
set_fipers(etsects); set_fipers(qoriq_ptp);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0; return 0;
} }
static int ptp_gianfar_enable(struct ptp_clock_info *ptp, static int ptp_qoriq_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on) struct ptp_clock_request *rq, int on)
{ {
struct etsects *etsects = container_of(ptp, struct etsects, caps); struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps);
unsigned long flags; unsigned long flags;
u32 bit, mask; u32 bit, mask;
@ -382,25 +395,25 @@ static int ptp_gianfar_enable(struct ptp_clock_info *ptp,
default: default:
return -EINVAL; return -EINVAL;
} }
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
mask = gfar_read(&etsects->regs->tmr_temask); mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
if (on) if (on)
mask |= bit; mask |= bit;
else else
mask &= ~bit; mask &= ~bit;
gfar_write(&etsects->regs->tmr_temask, mask); qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0; return 0;
case PTP_CLK_REQ_PPS: case PTP_CLK_REQ_PPS:
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
mask = gfar_read(&etsects->regs->tmr_temask); mask = qoriq_read(&qoriq_ptp->regs->tmr_temask);
if (on) if (on)
mask |= PP1EN; mask |= PP1EN;
else else
mask &= ~PP1EN; mask &= ~PP1EN;
gfar_write(&etsects->regs->tmr_temask, mask); qoriq_write(&qoriq_ptp->regs->tmr_temask, mask);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
return 0; return 0;
default: default:
@ -410,142 +423,141 @@ static int ptp_gianfar_enable(struct ptp_clock_info *ptp,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static const struct ptp_clock_info ptp_gianfar_caps = { static const struct ptp_clock_info ptp_qoriq_caps = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "gianfar clock", .name = "qoriq ptp clock",
.max_adj = 512000, .max_adj = 512000,
.n_alarm = 0, .n_alarm = 0,
.n_ext_ts = N_EXT_TS, .n_ext_ts = N_EXT_TS,
.n_per_out = 0, .n_per_out = 0,
.n_pins = 0, .n_pins = 0,
.pps = 1, .pps = 1,
.adjfine = ptp_gianfar_adjfine, .adjfine = ptp_qoriq_adjfine,
.adjtime = ptp_gianfar_adjtime, .adjtime = ptp_qoriq_adjtime,
.gettime64 = ptp_gianfar_gettime, .gettime64 = ptp_qoriq_gettime,
.settime64 = ptp_gianfar_settime, .settime64 = ptp_qoriq_settime,
.enable = ptp_gianfar_enable, .enable = ptp_qoriq_enable,
}; };
static int gianfar_ptp_probe(struct platform_device *dev) static int qoriq_ptp_probe(struct platform_device *dev)
{ {
struct device_node *node = dev->dev.of_node; struct device_node *node = dev->dev.of_node;
struct etsects *etsects; struct qoriq_ptp *qoriq_ptp;
struct timespec64 now; struct timespec64 now;
int err = -ENOMEM; int err = -ENOMEM;
u32 tmr_ctrl; u32 tmr_ctrl;
unsigned long flags; unsigned long flags;
etsects = kzalloc(sizeof(*etsects), GFP_KERNEL); qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL);
if (!etsects) if (!qoriq_ptp)
goto no_memory; goto no_memory;
err = -ENODEV; err = -ENODEV;
etsects->caps = ptp_gianfar_caps; qoriq_ptp->caps = ptp_qoriq_caps;
if (of_property_read_u32(node, "fsl,cksel", &etsects->cksel)) if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel))
etsects->cksel = DEFAULT_CKSEL; qoriq_ptp->cksel = DEFAULT_CKSEL;
if (of_property_read_u32(node, if (of_property_read_u32(node,
"fsl,tclk-period", &etsects->tclk_period) || "fsl,tclk-period", &qoriq_ptp->tclk_period) ||
of_property_read_u32(node, of_property_read_u32(node,
"fsl,tmr-prsc", &etsects->tmr_prsc) || "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) ||
of_property_read_u32(node, of_property_read_u32(node,
"fsl,tmr-add", &etsects->tmr_add) || "fsl,tmr-add", &qoriq_ptp->tmr_add) ||
of_property_read_u32(node, of_property_read_u32(node,
"fsl,tmr-fiper1", &etsects->tmr_fiper1) || "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) ||
of_property_read_u32(node, of_property_read_u32(node,
"fsl,tmr-fiper2", &etsects->tmr_fiper2) || "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) ||
of_property_read_u32(node, of_property_read_u32(node,
"fsl,max-adj", &etsects->caps.max_adj)) { "fsl,max-adj", &qoriq_ptp->caps.max_adj)) {
pr_err("device tree node missing required elements\n"); pr_err("device tree node missing required elements\n");
goto no_node; goto no_node;
} }
etsects->irq = platform_get_irq(dev, 0); qoriq_ptp->irq = platform_get_irq(dev, 0);
if (etsects->irq < 0) { if (qoriq_ptp->irq < 0) {
pr_err("irq not in device tree\n"); pr_err("irq not in device tree\n");
goto no_node; goto no_node;
} }
if (request_irq(etsects->irq, isr, 0, DRIVER, etsects)) { if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) {
pr_err("request_irq failed\n"); pr_err("request_irq failed\n");
goto no_node; goto no_node;
} }
etsects->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (!etsects->rsrc) { if (!qoriq_ptp->rsrc) {
pr_err("no resource\n"); pr_err("no resource\n");
goto no_resource; goto no_resource;
} }
if (request_resource(&iomem_resource, etsects->rsrc)) { if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) {
pr_err("resource busy\n"); pr_err("resource busy\n");
goto no_resource; goto no_resource;
} }
spin_lock_init(&etsects->lock); spin_lock_init(&qoriq_ptp->lock);
etsects->regs = ioremap(etsects->rsrc->start, qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start,
resource_size(etsects->rsrc)); resource_size(qoriq_ptp->rsrc));
if (!etsects->regs) { if (!qoriq_ptp->regs) {
pr_err("ioremap ptp registers failed\n"); pr_err("ioremap ptp registers failed\n");
goto no_ioremap; goto no_ioremap;
} }
getnstimeofday64(&now); getnstimeofday64(&now);
ptp_gianfar_settime(&etsects->caps, &now); ptp_qoriq_settime(&qoriq_ptp->caps, &now);
tmr_ctrl = tmr_ctrl =
(etsects->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
(etsects->cksel & CKSEL_MASK) << CKSEL_SHIFT; (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT;
spin_lock_irqsave(&etsects->lock, flags); spin_lock_irqsave(&qoriq_ptp->lock, flags);
gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl); qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl);
gfar_write(&etsects->regs->tmr_add, etsects->tmr_add); qoriq_write(&qoriq_ptp->regs->tmr_add, qoriq_ptp->tmr_add);
gfar_write(&etsects->regs->tmr_prsc, etsects->tmr_prsc); qoriq_write(&qoriq_ptp->regs->tmr_prsc, qoriq_ptp->tmr_prsc);
gfar_write(&etsects->regs->tmr_fiper1, etsects->tmr_fiper1); qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1);
gfar_write(&etsects->regs->tmr_fiper2, etsects->tmr_fiper2); qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2);
set_alarm(etsects); set_alarm(qoriq_ptp);
gfar_write(&etsects->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD);
spin_unlock_irqrestore(&etsects->lock, flags); spin_unlock_irqrestore(&qoriq_ptp->lock, flags);
etsects->clock = ptp_clock_register(&etsects->caps, &dev->dev); qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev);
if (IS_ERR(etsects->clock)) { if (IS_ERR(qoriq_ptp->clock)) {
err = PTR_ERR(etsects->clock); err = PTR_ERR(qoriq_ptp->clock);
goto no_clock; goto no_clock;
} }
gfar_phc_index = ptp_clock_index(etsects->clock); qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock);
platform_set_drvdata(dev, etsects); platform_set_drvdata(dev, qoriq_ptp);
return 0; return 0;
no_clock: no_clock:
iounmap(etsects->regs); iounmap(qoriq_ptp->regs);
no_ioremap: no_ioremap:
release_resource(etsects->rsrc); release_resource(qoriq_ptp->rsrc);
no_resource: no_resource:
free_irq(etsects->irq, etsects); free_irq(qoriq_ptp->irq, qoriq_ptp);
no_node: no_node:
kfree(etsects); kfree(qoriq_ptp);
no_memory: no_memory:
return err; return err;
} }
static int gianfar_ptp_remove(struct platform_device *dev) static int qoriq_ptp_remove(struct platform_device *dev)
{ {
struct etsects *etsects = platform_get_drvdata(dev); struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev);
gfar_write(&etsects->regs->tmr_temask, 0); qoriq_write(&qoriq_ptp->regs->tmr_temask, 0);
gfar_write(&etsects->regs->tmr_ctrl, 0); qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0);
gfar_phc_index = -1; ptp_clock_unregister(qoriq_ptp->clock);
ptp_clock_unregister(etsects->clock); iounmap(qoriq_ptp->regs);
iounmap(etsects->regs); release_resource(qoriq_ptp->rsrc);
release_resource(etsects->rsrc); free_irq(qoriq_ptp->irq, qoriq_ptp);
free_irq(etsects->irq, etsects); kfree(qoriq_ptp);
kfree(etsects);
return 0; return 0;
} }
@ -556,17 +568,17 @@ static const struct of_device_id match_table[] = {
}; };
MODULE_DEVICE_TABLE(of, match_table); MODULE_DEVICE_TABLE(of, match_table);
static struct platform_driver gianfar_ptp_driver = { static struct platform_driver qoriq_ptp_driver = {
.driver = { .driver = {
.name = "gianfar_ptp", .name = "ptp_qoriq",
.of_match_table = match_table, .of_match_table = match_table,
}, },
.probe = gianfar_ptp_probe, .probe = qoriq_ptp_probe,
.remove = gianfar_ptp_remove, .remove = qoriq_ptp_remove,
}; };
module_platform_driver(gianfar_ptp_driver); module_platform_driver(qoriq_ptp_driver);
MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>"); MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
MODULE_DESCRIPTION("PTP clock using the eTSEC"); MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");