Skip to content

Commit e37425c

Browse files
florineliordachedavem330
authored andcommitted
fsl/fman: implement several errata workarounds
Implemented workarounds for the following dTSEC Erratum: A002, A004, A0012, A0014, A004839 on several operations that involve MAC CFG register changes: adjust link, rx pause frames, modify MAC address. Signed-off-by: Florinel Iordache <[email protected]> Acked-by: Madalin Bucur <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 720a847 commit e37425c

File tree

1 file changed

+93
-25
lines changed

1 file changed

+93
-25
lines changed

drivers/net/ethernet/freescale/fman/fman_dtsec.c

Lines changed: 93 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
#define DTSEC_ECNTRL_R100M 0x00000008
124124
#define DTSEC_ECNTRL_QSGMIIM 0x00000001
125125

126-
#define DTSEC_TCTRL_GTS 0x00000020
126+
#define TCTRL_GTS 0x00000020
127127

128128
#define RCTRL_PAL_MASK 0x001f0000
129129
#define RCTRL_PAL_SHIFT 16
@@ -863,6 +863,52 @@ int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
863863
return 0;
864864
}
865865

866+
static void graceful_start(struct fman_mac *dtsec, enum comm_mode mode)
867+
{
868+
struct dtsec_regs __iomem *regs = dtsec->regs;
869+
870+
if (mode & COMM_MODE_TX)
871+
iowrite32be(ioread32be(&regs->tctrl) &
872+
~TCTRL_GTS, &regs->tctrl);
873+
if (mode & COMM_MODE_RX)
874+
iowrite32be(ioread32be(&regs->rctrl) &
875+
~RCTRL_GRS, &regs->rctrl);
876+
}
877+
878+
static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode)
879+
{
880+
struct dtsec_regs __iomem *regs = dtsec->regs;
881+
u32 tmp;
882+
883+
/* Graceful stop - Assert the graceful Rx stop bit */
884+
if (mode & COMM_MODE_RX) {
885+
tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
886+
iowrite32be(tmp, &regs->rctrl);
887+
888+
if (dtsec->fm_rev_info.major == 2) {
889+
/* Workaround for dTSEC Errata A002 */
890+
usleep_range(100, 200);
891+
} else {
892+
/* Workaround for dTSEC Errata A004839 */
893+
usleep_range(10, 50);
894+
}
895+
}
896+
897+
/* Graceful stop - Assert the graceful Tx stop bit */
898+
if (mode & COMM_MODE_TX) {
899+
if (dtsec->fm_rev_info.major == 2) {
900+
/* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
901+
pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
902+
} else {
903+
tmp = ioread32be(&regs->tctrl) | TCTRL_GTS;
904+
iowrite32be(tmp, &regs->tctrl);
905+
906+
/* Workaround for dTSEC Errata A0012, A0014 */
907+
usleep_range(10, 50);
908+
}
909+
}
910+
}
911+
866912
int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
867913
{
868914
struct dtsec_regs __iomem *regs = dtsec->regs;
@@ -880,13 +926,8 @@ int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
880926

881927
iowrite32be(tmp, &regs->maccfg1);
882928

883-
/* Graceful start - clear the graceful receive stop bit */
884-
if (mode & COMM_MODE_TX)
885-
iowrite32be(ioread32be(&regs->tctrl) & ~DTSEC_TCTRL_GTS,
886-
&regs->tctrl);
887-
if (mode & COMM_MODE_RX)
888-
iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS,
889-
&regs->rctrl);
929+
/* Graceful start - clear the graceful Rx/Tx stop bit */
930+
graceful_start(dtsec, mode);
890931

891932
return 0;
892933
}
@@ -899,23 +940,8 @@ int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
899940
if (!is_init_done(dtsec->dtsec_drv_param))
900941
return -EINVAL;
901942

902-
/* Gracefull stop - Assert the graceful transmit stop bit */
903-
if (mode & COMM_MODE_RX) {
904-
tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
905-
iowrite32be(tmp, &regs->rctrl);
906-
907-
if (dtsec->fm_rev_info.major == 2)
908-
usleep_range(100, 200);
909-
else
910-
udelay(10);
911-
}
912-
913-
if (mode & COMM_MODE_TX) {
914-
if (dtsec->fm_rev_info.major == 2)
915-
pr_debug("GTS not supported due to DTSEC_A004 errata.\n");
916-
else
917-
pr_debug("GTS not supported due to DTSEC_A0014 errata.\n");
918-
}
943+
/* Graceful stop - Assert the graceful Rx/Tx stop bit */
944+
graceful_stop(dtsec, mode);
919945

920946
tmp = ioread32be(&regs->maccfg1);
921947
if (mode & COMM_MODE_RX)
@@ -933,11 +959,19 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
933959
u16 pause_time, u16 __maybe_unused thresh_time)
934960
{
935961
struct dtsec_regs __iomem *regs = dtsec->regs;
962+
enum comm_mode mode = COMM_MODE_NONE;
936963
u32 ptv = 0;
937964

938965
if (!is_init_done(dtsec->dtsec_drv_param))
939966
return -EINVAL;
940967

968+
if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
969+
mode |= COMM_MODE_RX;
970+
if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
971+
mode |= COMM_MODE_TX;
972+
973+
graceful_stop(dtsec, mode);
974+
941975
if (pause_time) {
942976
/* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */
943977
if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) {
@@ -958,38 +992,62 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
958992
iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
959993
&regs->maccfg1);
960994

995+
graceful_start(dtsec, mode);
996+
961997
return 0;
962998
}
963999

9641000
int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
9651001
{
9661002
struct dtsec_regs __iomem *regs = dtsec->regs;
1003+
enum comm_mode mode = COMM_MODE_NONE;
9671004
u32 tmp;
9681005

9691006
if (!is_init_done(dtsec->dtsec_drv_param))
9701007
return -EINVAL;
9711008

1009+
if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
1010+
mode |= COMM_MODE_RX;
1011+
if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
1012+
mode |= COMM_MODE_TX;
1013+
1014+
graceful_stop(dtsec, mode);
1015+
9721016
tmp = ioread32be(&regs->maccfg1);
9731017
if (en)
9741018
tmp |= MACCFG1_RX_FLOW;
9751019
else
9761020
tmp &= ~MACCFG1_RX_FLOW;
9771021
iowrite32be(tmp, &regs->maccfg1);
9781022

1023+
graceful_start(dtsec, mode);
1024+
9791025
return 0;
9801026
}
9811027

9821028
int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr)
9831029
{
1030+
struct dtsec_regs __iomem *regs = dtsec->regs;
1031+
enum comm_mode mode = COMM_MODE_NONE;
1032+
9841033
if (!is_init_done(dtsec->dtsec_drv_param))
9851034
return -EINVAL;
9861035

1036+
if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
1037+
mode |= COMM_MODE_RX;
1038+
if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
1039+
mode |= COMM_MODE_TX;
1040+
1041+
graceful_stop(dtsec, mode);
1042+
9871043
/* Initialize MAC Station Address registers (1 & 2)
9881044
* Station address have to be swapped (big endian to little endian
9891045
*/
9901046
dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr);
9911047
set_mac_address(dtsec->regs, (u8 *)(*enet_addr));
9921048

1049+
graceful_start(dtsec, mode);
1050+
9931051
return 0;
9941052
}
9951053

@@ -1162,11 +1220,19 @@ int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
11621220
int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
11631221
{
11641222
struct dtsec_regs __iomem *regs = dtsec->regs;
1223+
enum comm_mode mode = COMM_MODE_NONE;
11651224
u32 tmp;
11661225

11671226
if (!is_init_done(dtsec->dtsec_drv_param))
11681227
return -EINVAL;
11691228

1229+
if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
1230+
mode |= COMM_MODE_RX;
1231+
if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
1232+
mode |= COMM_MODE_TX;
1233+
1234+
graceful_stop(dtsec, mode);
1235+
11701236
tmp = ioread32be(&regs->maccfg2);
11711237

11721238
/* Full Duplex */
@@ -1186,6 +1252,8 @@ int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
11861252
tmp &= ~DTSEC_ECNTRL_R100M;
11871253
iowrite32be(tmp, &regs->ecntrl);
11881254

1255+
graceful_start(dtsec, mode);
1256+
11891257
return 0;
11901258
}
11911259

0 commit comments

Comments
 (0)