summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/ethernet/freescale/fec.h19
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c41
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c46
3 files changed, 61 insertions, 45 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 8072287d0e89..ff6d7c32ae87 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -262,6 +262,23 @@ struct bufdesc_ex {
#define FALSE 0
#define TRUE 1
+/* Interrupt events/masks. */
+#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
+#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
+#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
+#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
+#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
+#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
+#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
+#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
+#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
+#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
+#define FEC_ENET_TS_AVAIL ((uint)0x00010000)
+#define FEC_ENET_TS_TIMER ((uint)0x00008000)
+
+#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII | FEC_ENET_TS_TIMER)
+#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
+
/* IEEE 1588 definition */
#define FEC_T_PERIOD_ONE_SEC 0x3B9ACA00
@@ -303,6 +320,8 @@ struct bufdesc_ex {
#define FEC_PTP_ORIG_COMP 0x15555555
#define FEC_PTP_SPINNER_2 2
#define FEC_PTP_SPINNER_4 4
+#define FEC_PTP_TIMEOUT_TS 10
+#define FEC_PTP_TIMEOUT_EVENT 1000
/* PTP standard time representation structure */
struct ptp_time{
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index a7ac199ea1c2..a51dc18ed0bf 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -201,23 +201,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
#error "FEC: descriptor ring size constants too large"
#endif
-/* Interrupt events/masks. */
-#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */
-#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */
-#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */
-#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */
-#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */
-#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */
-#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */
-#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */
-#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */
-#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */
-#define FEC_ENET_TS_AVAIL ((uint)0x00010000)
-#define FEC_ENET_TS_TIMER ((uint)0x00008000)
-
-#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
-#define FEC_RX_DISABLED_IMASK (FEC_DEFAULT_IMASK & (~FEC_ENET_RXF))
-
/* The FEC stores dest/src/type/vlan, data, and checksum for receive packets.
*/
#define PKT_MAXBUF_SIZE 1522
@@ -667,13 +650,8 @@ fec_restart(struct net_device *ndev, int duplex)
writel(ecntl, fep->hwp + FEC_ECNTRL);
writel(0, fep->hwp + FEC_R_DES_ACTIVE);
- if (fep->bufdesc_ex) {
+ if (fep->bufdesc_ex)
fec_ptp_start_cyclecounter(ndev);
- /* Enable interrupts we wish to service */
- writel(FEC_DEFAULT_IMASK | FEC_ENET_TS_AVAIL |
- FEC_ENET_TS_TIMER, fep->hwp + FEC_IMASK);
- } else
- writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
/* Enable interrupts we wish to service */
writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1061,7 +1039,16 @@ fec_enet_interrupt(int irq, void *dev_id)
do {
int_events = readl(fep->hwp + FEC_IEVENT);
- writel(int_events, fep->hwp + FEC_IEVENT);
+ writel(int_events & (~FEC_ENET_TS_TIMER),
+ fep->hwp + FEC_IEVENT);
+
+ if ((int_events & FEC_ENET_TS_TIMER) && fep->bufdesc_ex) {
+ ret = IRQ_HANDLED;
+ if (fep->hwts_tx_en_ioctl || fep->hwts_rx_en_ioctl)
+ fep->prtc++;
+
+ writel(FEC_ENET_TS_TIMER, fep->hwp + FEC_IEVENT);
+ }
if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) {
ret = IRQ_HANDLED;
@@ -1074,12 +1061,6 @@ fec_enet_interrupt(int irq, void *dev_id)
}
}
- if ((int_events & FEC_ENET_TS_TIMER) && fep->bufdesc_ex) {
- ret = IRQ_HANDLED;
- if (fep->hwts_tx_en_ioctl || fep->hwts_rx_en_ioctl)
- fep->prtc++;
- }
-
if (int_events & FEC_ENET_MII) {
ret = IRQ_HANDLED;
complete(&fep->mdio_done);
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 2d6997bea89a..2b4a567ac27d 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -225,22 +225,38 @@ void fec_ptp_stop(struct net_device *ndev)
static void fec_get_curr_cnt(struct fec_enet_private *priv,
struct ptp_rtc_time *curr_time)
{
- u32 tempval;
+ u32 tempval, old_sec;
+ u32 timeout_event, timeout_ts = 0;
- tempval = readl(priv->hwp + FEC_ATIME_CTRL);
- tempval |= FEC_T_CTRL_CAPTURE;
+ do {
+ old_sec = priv->prtc;
+ timeout_event = 0;
+
+ tempval = readl(priv->hwp + FEC_ATIME_CTRL);
+ tempval |= FEC_T_CTRL_CAPTURE;
+ writel(tempval, priv->hwp + FEC_ATIME_CTRL);
- writel(tempval, 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.nsec = readl(priv->hwp + FEC_ATIME);
- writel(tempval, priv->hwp + FEC_ATIME_CTRL);
- tempval = readl(priv->hwp + FEC_ATIME);
+ while (readl(priv->hwp + FEC_IEVENT) & FEC_ENET_TS_TIMER) {
+ timeout_event++;
+ udelay(20);
+
+ if (timeout_event >= FEC_PTP_TIMEOUT_EVENT)
+ break;
+ }
- if (tempval < curr_time->rtc_time.nsec) {
- curr_time->rtc_time.nsec = tempval;
curr_time->rtc_time.sec = priv->prtc;
- }
+ timeout_ts++;
+
+ if (timeout_event >= FEC_PTP_TIMEOUT_EVENT)
+ pr_err("timeout: TS TIMER event\n");
+
+ } while (old_sec != curr_time->rtc_time.sec &&
+ timeout_ts < FEC_PTP_TIMEOUT_TS);
+
+ if (timeout_ts >= FEC_PTP_TIMEOUT_TS)
+ pr_err("timeout: current timestamp unmatched\n");
}
/* Set the 1588 timer counter registers */
@@ -392,9 +408,9 @@ void fec_ptp_store_txstamp(struct fec_enet_private *priv,
/* store tx timestamp */
fec_get_curr_cnt(priv, &curr_time);
if (curr_time.rtc_time.nsec < bdp_ex->ts)
- tmp_tx_time.ts.sec = priv->prtc - 1;
+ tmp_tx_time.ts.sec = curr_time.rtc_time.sec - 1;
else
- tmp_tx_time.ts.sec = priv->prtc;
+ tmp_tx_time.ts.sec = curr_time.rtc_time.sec;
tmp_tx_time.ts.nsec = bdp_ex->ts;
/* insert timestamp in circular buffer */
fec_ptp_insert(&(priv->tx_timestamps), &tmp_tx_time);
@@ -437,9 +453,9 @@ void fec_ptp_store_rxstamp(struct fec_enet_private *priv,
/* store rx timestamp */
fec_get_curr_cnt(priv, &curr_time);
if (curr_time.rtc_time.nsec < bdp_ex->ts)
- tmp_rx_time.ts.sec = priv->prtc - 1;
+ tmp_rx_time.ts.sec = curr_time.rtc_time.sec - 1;
else
- tmp_rx_time.ts.sec = priv->prtc;
+ tmp_rx_time.ts.sec = curr_time.rtc_time.sec;
tmp_rx_time.ts.nsec = bdp_ex->ts;
/* insert timestamp in circular buffer */