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

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: default avatarYangbo Lu <yangbo.lu@nxp.com>
Acked-by: default avatarRichard Cochran <richardcochran@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b1d2e4e0
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -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
+7 −7
Original line number Original line Diff line number Diff line
@@ -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"
+1 −0
Original line number Original line Diff line number Diff line
@@ -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
+166 −154
Original line number Original line Diff line number Diff line
/*
/*
 * 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");