diff options
author | Nimrod Andy <B38611@freescale.com> | 2014-10-15 05:30:12 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-15 16:40:11 -0400 |
commit | 28b5f058cf1d268d965894ce42a614d13f853dd6 (patch) | |
tree | 279c57e8845b5024e5c9363989560fe3d079d2c6 /drivers/net | |
parent | 001586a737ee8c11a1198c352c5635f19fd090ed (diff) |
net: fec: ptp: fix convergence issue to support LinuxPTP stack
iMX6SX IEEE 1588 module has one hw issue in capturing the ATVR register.
The current SW flow is:
ENET0->ATCR |= ENET_ATCR_CAPTURE_MASK;
ts_counter_ns = ENET0->ATVR;
The ATVR value is not expected value that cause LinuxPTP stack cannot be convergent.
ENET Block Guide/ Chapter for the iMX6SX (PELE) address the issue:
After set ENET_ATCR[Capture], there need some time cycles before the counter
value is capture in the register clock domain. The wait-time-cycles is at least
6 clock cycles of the slower clock between the register clock and the 1588 clock.
So need something like:
ENET0->ATCR |= ENET_ATCR_CAPTURE_MASK;
wait();
ts_counter_ns = ENET0->ATVR;
For iMX6SX, the 1588 ts_clk is fixed to 25Mhz, register clock is 66Mhz, so the
wait-time-cycles must be greater than 240ns (40ns * 6). The patch add 1us delay
before cpu read ATVR register.
Changes V2:
Modify the commit/comments log to describe the issue clearly.
Signed-off-by: Fugang Duan <B38611@freescale.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 50 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 43 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec_ptp.c | 5 |
3 files changed, 56 insertions, 42 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 1e65917a9381..9af296a1ca99 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h | |||
@@ -367,6 +367,56 @@ struct bufdesc_ex { | |||
367 | #define FEC_VLAN_TAG_LEN 0x04 | 367 | #define FEC_VLAN_TAG_LEN 0x04 |
368 | #define FEC_ETHTYPE_LEN 0x02 | 368 | #define FEC_ETHTYPE_LEN 0x02 |
369 | 369 | ||
370 | /* Controller is ENET-MAC */ | ||
371 | #define FEC_QUIRK_ENET_MAC (1 << 0) | ||
372 | /* Controller needs driver to swap frame */ | ||
373 | #define FEC_QUIRK_SWAP_FRAME (1 << 1) | ||
374 | /* Controller uses gasket */ | ||
375 | #define FEC_QUIRK_USE_GASKET (1 << 2) | ||
376 | /* Controller has GBIT support */ | ||
377 | #define FEC_QUIRK_HAS_GBIT (1 << 3) | ||
378 | /* Controller has extend desc buffer */ | ||
379 | #define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) | ||
380 | /* Controller has hardware checksum support */ | ||
381 | #define FEC_QUIRK_HAS_CSUM (1 << 5) | ||
382 | /* Controller has hardware vlan support */ | ||
383 | #define FEC_QUIRK_HAS_VLAN (1 << 6) | ||
384 | /* ENET IP errata ERR006358 | ||
385 | * | ||
386 | * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously | ||
387 | * detected as not set during a prior frame transmission, then the | ||
388 | * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs | ||
389 | * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in | ||
390 | * frames not being transmitted until there is a 0-to-1 transition on | ||
391 | * ENET_TDAR[TDAR]. | ||
392 | */ | ||
393 | #define FEC_QUIRK_ERR006358 (1 << 7) | ||
394 | /* ENET IP hw AVB | ||
395 | * | ||
396 | * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support. | ||
397 | * - Two class indicators on receive with configurable priority | ||
398 | * - Two class indicators and line speed timer on transmit allowing | ||
399 | * implementation class credit based shapers externally | ||
400 | * - Additional DMA registers provisioned to allow managing up to 3 | ||
401 | * independent rings | ||
402 | */ | ||
403 | #define FEC_QUIRK_HAS_AVB (1 << 8) | ||
404 | /* There is a TDAR race condition for mutliQ when the software sets TDAR | ||
405 | * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). | ||
406 | * This will cause the udma_tx and udma_tx_arbiter state machines to hang. | ||
407 | * The issue exist at i.MX6SX enet IP. | ||
408 | */ | ||
409 | #define FEC_QUIRK_ERR007885 (1 << 9) | ||
410 | /* ENET Block Guide/ Chapter for the iMX6SX (PELE) address one issue: | ||
411 | * After set ENET_ATCR[Capture], there need some time cycles before the counter | ||
412 | * value is capture in the register clock domain. | ||
413 | * The wait-time-cycles is at least 6 clock cycles of the slower clock between | ||
414 | * the register clock and the 1588 clock. The 1588 ts_clk is fixed to 25Mhz, | ||
415 | * register clock is 66Mhz, so the wait-time-cycles must be greater than 240ns | ||
416 | * (40ns * 6). | ||
417 | */ | ||
418 | #define FEC_QUIRK_BUG_CAPTURE (1 << 10) | ||
419 | |||
370 | struct fec_enet_priv_tx_q { | 420 | struct fec_enet_priv_tx_q { |
371 | int index; | 421 | int index; |
372 | unsigned char *tx_bounce[TX_RING_SIZE]; | 422 | unsigned char *tx_bounce[TX_RING_SIZE]; |
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index e364d1fc7bdc..81b96cf87574 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
@@ -78,47 +78,6 @@ static void fec_enet_itr_coal_init(struct net_device *ndev); | |||
78 | #define FEC_ENET_RAFL_V 0x8 | 78 | #define FEC_ENET_RAFL_V 0x8 |
79 | #define FEC_ENET_OPD_V 0xFFF0 | 79 | #define FEC_ENET_OPD_V 0xFFF0 |
80 | 80 | ||
81 | /* Controller is ENET-MAC */ | ||
82 | #define FEC_QUIRK_ENET_MAC (1 << 0) | ||
83 | /* Controller needs driver to swap frame */ | ||
84 | #define FEC_QUIRK_SWAP_FRAME (1 << 1) | ||
85 | /* Controller uses gasket */ | ||
86 | #define FEC_QUIRK_USE_GASKET (1 << 2) | ||
87 | /* Controller has GBIT support */ | ||
88 | #define FEC_QUIRK_HAS_GBIT (1 << 3) | ||
89 | /* Controller has extend desc buffer */ | ||
90 | #define FEC_QUIRK_HAS_BUFDESC_EX (1 << 4) | ||
91 | /* Controller has hardware checksum support */ | ||
92 | #define FEC_QUIRK_HAS_CSUM (1 << 5) | ||
93 | /* Controller has hardware vlan support */ | ||
94 | #define FEC_QUIRK_HAS_VLAN (1 << 6) | ||
95 | /* ENET IP errata ERR006358 | ||
96 | * | ||
97 | * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously | ||
98 | * detected as not set during a prior frame transmission, then the | ||
99 | * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs | ||
100 | * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in | ||
101 | * frames not being transmitted until there is a 0-to-1 transition on | ||
102 | * ENET_TDAR[TDAR]. | ||
103 | */ | ||
104 | #define FEC_QUIRK_ERR006358 (1 << 7) | ||
105 | /* ENET IP hw AVB | ||
106 | * | ||
107 | * i.MX6SX ENET IP add Audio Video Bridging (AVB) feature support. | ||
108 | * - Two class indicators on receive with configurable priority | ||
109 | * - Two class indicators and line speed timer on transmit allowing | ||
110 | * implementation class credit based shapers externally | ||
111 | * - Additional DMA registers provisioned to allow managing up to 3 | ||
112 | * independent rings | ||
113 | */ | ||
114 | #define FEC_QUIRK_HAS_AVB (1 << 8) | ||
115 | /* There is a TDAR race condition for mutliQ when the software sets TDAR | ||
116 | * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). | ||
117 | * This will cause the udma_tx and udma_tx_arbiter state machines to hang. | ||
118 | * The issue exist at i.MX6SX enet IP. | ||
119 | */ | ||
120 | #define FEC_QUIRK_ERR007885 (1 << 9) | ||
121 | |||
122 | static struct platform_device_id fec_devtype[] = { | 81 | static struct platform_device_id fec_devtype[] = { |
123 | { | 82 | { |
124 | /* keep it for coldfire */ | 83 | /* keep it for coldfire */ |
@@ -146,7 +105,7 @@ static struct platform_device_id fec_devtype[] = { | |||
146 | .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | | 105 | .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | |
147 | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | | 106 | FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | |
148 | FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | | 107 | FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB | |
149 | FEC_QUIRK_ERR007885, | 108 | FEC_QUIRK_ERR007885 | FEC_QUIRK_BUG_CAPTURE, |
150 | }, { | 109 | }, { |
151 | /* sentinel */ | 110 | /* sentinel */ |
152 | } | 111 | } |
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 0fdcdc9ea028..992c8c3db553 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c | |||
@@ -236,12 +236,17 @@ static cycle_t fec_ptp_read(const struct cyclecounter *cc) | |||
236 | { | 236 | { |
237 | struct fec_enet_private *fep = | 237 | struct fec_enet_private *fep = |
238 | container_of(cc, struct fec_enet_private, cc); | 238 | container_of(cc, struct fec_enet_private, cc); |
239 | const struct platform_device_id *id_entry = | ||
240 | platform_get_device_id(fep->pdev); | ||
239 | u32 tempval; | 241 | u32 tempval; |
240 | 242 | ||
241 | tempval = readl(fep->hwp + FEC_ATIME_CTRL); | 243 | tempval = readl(fep->hwp + FEC_ATIME_CTRL); |
242 | tempval |= FEC_T_CTRL_CAPTURE; | 244 | tempval |= FEC_T_CTRL_CAPTURE; |
243 | writel(tempval, fep->hwp + FEC_ATIME_CTRL); | 245 | writel(tempval, fep->hwp + FEC_ATIME_CTRL); |
244 | 246 | ||
247 | if (id_entry->driver_data & FEC_QUIRK_BUG_CAPTURE) | ||
248 | udelay(1); | ||
249 | |||
245 | return readl(fep->hwp + FEC_ATIME); | 250 | return readl(fep->hwp + FEC_ATIME); |
246 | } | 251 | } |
247 | 252 | ||