diff options
author | Xie Xiaobo <r63061@freescale.com> | 2010-12-24 11:59:56 +0800 |
---|---|---|
committer | Frank Li <Frank.Li@freescale.com> | 2010-12-24 15:59:20 +0800 |
commit | dcb5f3248d52d9120068a721081c88abef62959a (patch) | |
tree | 287495e11bec6416f973ec9e71dc1648702140c7 /drivers | |
parent | 00d336a50e6a06f41e95675b64c26c76a7f01bc9 (diff) |
ENGR00137339 PTP: Synchronize fec1 timer to fec0 timer in i.MX28
When enable fec0 and fec1 1588 timer in the same time,
enalbe fec1 1588 timer to FRC_SLAVE mode in i.MX28.
Signed-off-by: Xie Xiaobo <X.Xie@freescale.com>
(cherry picked from commit e90197be678342bf9a09c4f64f5fe25a84cf75c7)
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/fec_1588.c | 89 | ||||
-rw-r--r-- | drivers/net/fec_1588.h | 4 |
2 files changed, 78 insertions, 15 deletions
diff --git a/drivers/net/fec_1588.c b/drivers/net/fec_1588.c index 152a8dc58972..0b53cb52991d 100644 --- a/drivers/net/fec_1588.c +++ b/drivers/net/fec_1588.c @@ -154,13 +154,41 @@ int fec_ptp_start(struct fec_ptp_private *priv) { struct fec_ptp_private *fpp = priv; - /* Select 1588 Timer source and enable module for starting Tmr Clock */ - writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL); - writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, fpp->hwp + FEC_ATIME_INC); - writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD); - /* start counter */ - writel(FEC_T_CTRL_PERIOD_RST | FEC_T_CTRL_ENABLE, - fpp->hwp + FEC_ATIME_CTRL); + /* Select 1588 Timer source and enable module for starting Tmr Clock * + * When enable both FEC0 and FEC1 1588 Timer in the same time, * + * enable FEC1 timer's slave mode. */ + if ((fpp == ptp_private[0]) || !(ptp_private[0]->ptp_active)) { + writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL); + writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + fpp->hwp + FEC_ATIME_INC); + writel(FEC_T_PERIOD_ONE_SEC, fpp->hwp + FEC_ATIME_EVT_PERIOD); + /* start counter */ + writel(FEC_T_CTRL_PERIOD_RST | FEC_T_CTRL_ENABLE, + fpp->hwp + FEC_ATIME_CTRL); + fpp->ptp_slave = 0; + fpp->ptp_active = 1; + /* if the FEC1 timer was enabled, set it to slave mode */ + if ((fpp == ptp_private[0]) && (ptp_private[1]->ptp_active)) { + writel(0, ptp_private[1]->hwp + FEC_ATIME_CTRL); + fpp->prtc = ptp_private[1]->prtc; + writel(FEC_T_CTRL_RESTART, + ptp_private[1]->hwp + FEC_ATIME_CTRL); + writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + ptp_private[1]->hwp + FEC_ATIME_INC); + /* Set the timer as slave mode */ + writel(FEC_T_CTRL_SLAVE, + ptp_private[1]->hwp + FEC_ATIME_CTRL); + ptp_private[1]->ptp_slave = 1; + ptp_private[1]->ptp_active = 1; + } + } else { + writel(FEC_T_INC_40MHZ << FEC_T_INC_OFFSET, + fpp->hwp + FEC_ATIME_INC); + /* Set the timer as slave mode */ + writel(FEC_T_CTRL_SLAVE, fpp->hwp + FEC_ATIME_CTRL); + fpp->ptp_slave = 1; + fpp->ptp_active = 1; + } return 0; } @@ -173,6 +201,8 @@ void fec_ptp_stop(struct fec_ptp_private *priv) writel(0, fpp->hwp + FEC_ATIME_CTRL); writel(FEC_T_CTRL_RESTART, fpp->hwp + FEC_ATIME_CTRL); + priv->ptp_active = 0; + priv->ptp_slave = 0; } @@ -180,17 +210,23 @@ static void fec_get_curr_cnt(struct fec_ptp_private *priv, struct ptp_rtc_time *curr_time) { u32 tempval; + struct fec_ptp_private *tmp_priv; + + if (!priv->ptp_slave) + tmp_priv = priv; + else + tmp_priv = ptp_private[0]; writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); curr_time->rtc_time.nsec = readl(priv->hwp + FEC_ATIME); - curr_time->rtc_time.sec = priv->prtc; + curr_time->rtc_time.sec = tmp_priv->prtc; writel(FEC_T_CTRL_CAPTURE, priv->hwp + FEC_ATIME_CTRL); tempval = readl(priv->hwp + FEC_ATIME); if (tempval < curr_time->rtc_time.nsec) { curr_time->rtc_time.nsec = tempval; - curr_time->rtc_time.sec = priv->prtc; + curr_time->rtc_time.sec = tmp_priv->prtc; } } @@ -200,12 +236,18 @@ static void fec_set_1588cnt(struct fec_ptp_private *priv, { u32 tempval; unsigned long flags; + struct fec_ptp_private *tmp_priv; + + if (!priv->ptp_slave) + tmp_priv = priv; + else + tmp_priv = ptp_private[0]; spin_lock_irqsave(&priv->cnt_lock, flags); - priv->prtc = fec_time->rtc_time.sec; + tmp_priv->prtc = fec_time->rtc_time.sec; tempval = fec_time->rtc_time.nsec; - writel(tempval, priv->hwp + FEC_ATIME); + writel(tempval, tmp_priv->hwp + FEC_ATIME); spin_unlock_irqrestore(&priv->cnt_lock, flags); } @@ -235,10 +277,15 @@ void fec_ptp_store_txstamp(struct fec_ptp_private *priv, { int msg_type, seq_id, control; struct fec_ptp_data_t tmp_tx_time; - struct fec_ptp_private *fpp = priv; + struct fec_ptp_private *fpp; unsigned char *sp_id; unsigned short portnum; + if (!priv->ptp_slave) + fpp = priv; + else + fpp = ptp_private[0]; + seq_id = *((u16 *)(skb->data + FEC_PTP_SEQ_ID_OFFS)); control = *((u8 *)(skb->data + FEC_PTP_CTRL_OFFS)); sp_id = skb->data + FEC_PTP_SPORT_ID_OFFS; @@ -292,12 +339,17 @@ void fec_ptp_store_rxstamp(struct fec_ptp_private *priv, { int msg_type, seq_id, control; struct fec_ptp_data_t tmp_rx_time; - struct fec_ptp_private *fpp = priv; + struct fec_ptp_private *fpp; struct iphdr *iph; struct udphdr *udph; unsigned char *sp_id; unsigned short portnum; + if (!priv->ptp_slave) + fpp = priv; + else + fpp = ptp_private[0]; + /* Check for UDP, and Check if port is 319 for PTP Event */ iph = (struct iphdr *)(skb->data + FEC_PTP_IP_OFFS); if (iph->protocol != FEC_PACKET_TYPE_UDP) @@ -562,7 +614,7 @@ static void fec_set_drift(struct fec_ptp_private *priv, struct ptp_set_comp *comp) { struct ptp_time_correct tc; - struct fec_ptp_private *fpp = priv; + struct fec_ptp_private *fpp; u32 tmp, corr_ns; memset(&tc, 0, sizeof(struct ptp_time_correct)); @@ -575,6 +627,10 @@ static void fec_set_drift(struct fec_ptp_private *priv, else corr_ns = FEC_T_INC_40MHZ - tc.corr_inc; + if (!priv->ptp_slave) + fpp = priv; + else + fpp = ptp_private[0]; tmp = readl(fpp->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK; tmp |= corr_ns << FEC_T_INC_CORR_OFFSET; writel(tmp, fpp->hwp + FEC_ATIME_INC); @@ -678,7 +734,9 @@ static const struct file_operations ptp_fops = { static int init_ptp(void) { if (register_chrdev(PTP_MAJOR, "ptp", &ptp_fops)) - printk(KERN_ERR "Unable to register PTP deivce as char\n"); + printk(KERN_ERR "Unable to register PTP device as char\n"); + else + printk(KERN_INFO "Register PTP device as char /dev/ptp\n"); return 0; } @@ -706,6 +764,7 @@ int fec_ptp_init(struct fec_ptp_private *priv, int id) spin_lock_init(&priv->ptp_lock); spin_lock_init(&priv->cnt_lock); ptp_private[id] = priv; + priv->dev_id = id; if (id == 0) init_ptp(); return 0; diff --git a/drivers/net/fec_1588.h b/drivers/net/fec_1588.h index 1cd26278196f..bb43c66f3bc1 100644 --- a/drivers/net/fec_1588.h +++ b/drivers/net/fec_1588.h @@ -30,6 +30,7 @@ #define TRUE 1 /* FEC 1588 register bits */ +#define FEC_T_CTRL_SLAVE 0x00002000 #define FEC_T_CTRL_CAPTURE 0x00000800 #define FEC_T_CTRL_RESTART 0x00000200 #define FEC_T_CTRL_PERIOD_RST 0x00000030 @@ -150,6 +151,7 @@ struct ptp_time_correct { struct fec_ptp_private { void __iomem *hwp; + int dev_id; struct circ_buf rx_time_sync; struct circ_buf rx_time_del_req; @@ -163,6 +165,8 @@ struct fec_ptp_private { spinlock_t cnt_lock; u64 prtc; + u8 ptp_active; + u8 ptp_slave; struct circ_buf txstamp; }; |