diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_ptp.c | 46 |
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 */ |