aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFugang Duan <B38611@freescale.com>2014-02-27 02:29:09 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:57:50 -0400
commitf9f3fc39c0238ec761cd951fe3afcb5b97a40628 (patch)
treee82da1b014cf0bc7bf23924785c544d383bfb96d
parent450e9b8883469a675b90fb2fa655ee23e852aedd (diff)
ENGR00301115 net: fec_ptp: fix convergence issue to support IXXAT and LinuxPTP stack
IEEE 1588 module has one hw issue in capturing the ATVR register. According to the user manual it is: ENET0->ATCR |= ENET_ATCR_CAPTURE_MASK; while(ENET0->ATCR & ENET_ATCR_CAPTURE_MASK); ts_counter_ns = ENET0->ATVR; Incorrect behavior for ENET_ATCR[Capture and Restart Bits]. These bits will always read a value zero. According to SPEC, when these bits are set to 1'b1, these should hold value 1'b1 until the counter value is capture in the register clock domain. Unfortunately there is a bug with the way the bit "ENET_ATCR_CAPTURE" clears. So need something like: ENET0->ATCR |= ENET_ATCR_CAPTURE_MASK; wait(); ts_counter_ns = ENET0->ATVR; The wait-time to be at least 6 clock cycle of the slower clock between the register clock and the 1588 clock. The 1588 ts_clk is 25Mhz, register clock is 66Mhz, so the wait-time must be greater than 240ns (40ns * 6). The workaround is that adding 1us delay before read ATVR. Signed-off-by: Fugang Duan <B38611@freescale.com>
-rw-r--r--drivers/net/ethernet/freescale/fec.h61
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c56
-rw-r--r--drivers/net/ethernet/freescale/fec_ptp.c12
3 files changed, 71 insertions, 58 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index a8816cbf40c5..12c8352900b2 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -390,6 +390,67 @@ struct bufdesc_ex {
390#define FEC_PTP_TIMEOUT_TS 10 390#define FEC_PTP_TIMEOUT_TS 10
391#define FEC_PTP_TIMEOUT_EVENT 1000 391#define FEC_PTP_TIMEOUT_EVENT 1000
392 392
393/* Controller is ENET-MAC */
394#define FEC_QUIRK_ENET_MAC (1 << 0)
395/* Controller needs driver to swap frame */
396#define FEC_QUIRK_SWAP_FRAME (1 << 1)
397/* Controller uses gasket */
398#define FEC_QUIRK_USE_GASKET (1 << 2)
399/* Controller has GBIT support */
400#define FEC_QUIRK_HAS_GBIT (1 << 3)
401/* Controller has extend desc buffer */
402#define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4)
403/* Controller has hardware checksum support */
404#define FEC_QUIRK_HAS_CSUM (1 << 5)
405/* Controller has hardware vlan support */
406#define FEC_QUIRK_HAS_VLAN (1 << 6)
407/* Controller is FEC-MAC */
408#define FEC_QUIRK_FEC_MAC (1 << 7)
409/* ENET IP errata ERR006358
410 *
411 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
412 * detected as not set during a prior frame transmission, then the
413 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
414 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
415 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
416 * detected as not set during a prior frame transmission, then the
417 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
418 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
419 * frames not being transmitted until there is a 0-to-1 transition on
420 * ENET_TDAR[TDAR].
421 */
422#define FEC_QUIRK_ERR006358 (1 << 8)
423/*
424 * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx
425 * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
426 * to wait mode.
427 */
428#define FEC_QUIRK_BUG_WAITMODE (1 << 9)
429/*
430 * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support.
431 * ENET IP hw AVB main function:
432 * - Two class indicators on receive with configurable priority
433 * - Two class indicators and line speed timer on transmit allowing
434 * implementation class credit based shapers externally
435 * - Additional DMA registers provisioned to allow managing up to 3
436 * independent rings
437 */
438#define FEC_QUIRK_HAS_AVB (1 << 10)
439/*
440 * There is a TDAR race condition for mutliQ when the software sets TDAR
441 * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles).
442 * This will cause the udma_tx and udma_tx_arbiter state machines to hang.
443 * The issue exist at i.MX6SX enet IP.
444 */
445#define FEC_QUIRK_TKT210582 (1 << 11)
446/*
447 * Incorrect behavior for ENET_ATCR[Capture and Restart Bits].
448 * These bits will always read a value zero. According to SPEC, when these
449 * bits are set to 1'b1, these should hold value 1'b1 until the counter value
450 * is capture in the register clock domain.
451 */
452#define FEC_QUIRK_TKT210590 (1 << 12)
453
393/* PTP standard time representation structure */ 454/* PTP standard time representation structure */
394struct ptp_time{ 455struct ptp_time{
395 u64 sec; /* seconds */ 456 u64 sec; /* seconds */
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index f5e88a25ed1d..e3ffd7aee02f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -93,60 +93,6 @@ static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2};
93#define FEC_ENET_RAFL_V 0x8 93#define FEC_ENET_RAFL_V 0x8
94#define FEC_ENET_OPD_V 0xFFF0 94#define FEC_ENET_OPD_V 0xFFF0
95 95
96/* Controller is ENET-MAC */
97#define FEC_QUIRK_ENET_MAC (1 << 0)
98/* Controller needs driver to swap frame */
99#define FEC_QUIRK_SWAP_FRAME (1 << 1)
100/* Controller uses gasket */
101#define FEC_QUIRK_USE_GASKET (1 << 2)
102/* Controller has GBIT support */
103#define FEC_QUIRK_HAS_GBIT (1 << 3)
104/* Controller has extend desc buffer */
105#define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4)
106/* Controller has hardware checksum support */
107#define FEC_QUIRK_HAS_CSUM (1 << 5)
108/* Controller has hardware vlan support */
109#define FEC_QUIRK_HAS_VLAN (1 << 6)
110/* Controller is FEC-MAC */
111#define FEC_QUIRK_FEC_MAC (1 << 7)
112/* ENET IP errata ERR006358
113 *
114 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
115 * detected as not set during a prior frame transmission, then the
116 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
117 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
118 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
119 * detected as not set during a prior frame transmission, then the
120 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
121 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
122 * frames not being transmitted until there is a 0-to-1 transition on
123 * ENET_TDAR[TDAR].
124 */
125#define FEC_QUIRK_ERR006358 (1 << 8)
126/*
127 * i.MX6Q/DL ENET cannot wake up system in wait mode because ENET tx & rx
128 * interrupt signal don't connect to GPC. So use pm qos to avoid cpu enter
129 * to wait mode.
130 */
131#define FEC_QUIRK_BUG_WAITMODE (1 << 9)
132/*
133 * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support.
134 * ENET IP hw AVB main function:
135 * - Two class indicators on receive with configurable priority
136 * - Two class indicators and line speed timer on transmit allowing
137 * implementation class credit based shapers externally
138 * - Additional DMA registers provisioned to allow managing up to 3
139 * independent rings
140 */
141#define FEC_QUIRK_HAS_AVB (1 << 10)
142/*
143 * There is a TDAR race condition for mutliQ when the software sets TDAR
144 * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles).
145 * This will cause the udma_tx and udma_tx_arbiter state machines to hang.
146 * The issue exist at i.MX6SX enet IP.
147 */
148#define FEC_QUIRK_TKT210582 (1 << 11)
149
150static struct platform_device_id fec_devtype[] = { 96static struct platform_device_id fec_devtype[] = {
151 { 97 {
152 /* keep it for coldfire */ 98 /* keep it for coldfire */
@@ -175,7 +121,7 @@ static struct platform_device_id fec_devtype[] = {
175 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 121 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
176 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 122 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
177 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | 123 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
178 FEC_QUIRK_TKT210582, 124 FEC_QUIRK_TKT210582 | FEC_QUIRK_TKT210590,
179 }, { 125 }, {
180 /* sentinel */ 126 /* sentinel */
181 } 127 }
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index eaf0169dff90..03e10de40e94 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -229,6 +229,8 @@ static void fec_get_curr_cnt(struct fec_enet_private *priv,
229{ 229{
230 u32 tempval, old_sec; 230 u32 tempval, old_sec;
231 u32 timeout_event, timeout_ts = 0; 231 u32 timeout_event, timeout_ts = 0;
232 const struct platform_device_id *id_entry =
233 platform_get_device_id(priv->pdev);
232 234
233 do { 235 do {
234 old_sec = priv->prtc; 236 old_sec = priv->prtc;
@@ -237,7 +239,8 @@ static void fec_get_curr_cnt(struct fec_enet_private *priv,
237 tempval = readl(priv->hwp + FEC_ATIME_CTRL); 239 tempval = readl(priv->hwp + FEC_ATIME_CTRL);
238 tempval |= FEC_T_CTRL_CAPTURE; 240 tempval |= FEC_T_CTRL_CAPTURE;
239 writel(tempval, priv->hwp + FEC_ATIME_CTRL); 241 writel(tempval, priv->hwp + FEC_ATIME_CTRL);
240 242 if (id_entry->driver_data & FEC_QUIRK_TKT210590)
243 udelay(1);
241 curr_time->rtc_time.nsec = readl(priv->hwp + FEC_ATIME); 244 curr_time->rtc_time.nsec = readl(priv->hwp + FEC_ATIME);
242 245
243 while (readl(priv->hwp + FEC_IEVENT) & FEC_ENET_TS_TIMER) { 246 while (readl(priv->hwp + FEC_IEVENT) & FEC_ENET_TS_TIMER) {
@@ -520,7 +523,7 @@ static void fec_handle_ptpdrift(struct fec_enet_private *priv,
520} 523}
521 524
522static void fec_set_drift(struct fec_enet_private *priv, 525static void fec_set_drift(struct fec_enet_private *priv,
523 struct ptp_set_comp *comp) 526 struct ptp_set_comp *comp)
524{ 527{
525 struct ptp_time_correct tc; 528 struct ptp_time_correct tc;
526 u32 tmp, corr_ns; 529 u32 tmp, corr_ns;
@@ -555,12 +558,15 @@ static cycle_t fec_ptp_read(const struct cyclecounter *cc)
555{ 558{
556 struct fec_enet_private *fep = 559 struct fec_enet_private *fep =
557 container_of(cc, struct fec_enet_private, cc); 560 container_of(cc, struct fec_enet_private, cc);
561 const struct platform_device_id *id_entry =
562 platform_get_device_id(fep->pdev);
558 u32 tempval; 563 u32 tempval;
559 564
560 tempval = readl(fep->hwp + FEC_ATIME_CTRL); 565 tempval = readl(fep->hwp + FEC_ATIME_CTRL);
561 tempval |= FEC_T_CTRL_CAPTURE; 566 tempval |= FEC_T_CTRL_CAPTURE;
562 writel(tempval, fep->hwp + FEC_ATIME_CTRL); 567 writel(tempval, fep->hwp + FEC_ATIME_CTRL);
563 568 if (id_entry->driver_data & FEC_QUIRK_TKT210590)
569 udelay(1);
564 return readl(fep->hwp + FEC_ATIME); 570 return readl(fep->hwp + FEC_ATIME);
565} 571}
566 572