|
@@ -123,7 +123,7 @@
|
|
#define DTSEC_ECNTRL_R100M 0x00000008
|
|
#define DTSEC_ECNTRL_R100M 0x00000008
|
|
#define DTSEC_ECNTRL_QSGMIIM 0x00000001
|
|
#define DTSEC_ECNTRL_QSGMIIM 0x00000001
|
|
|
|
|
|
-#define DTSEC_TCTRL_GTS 0x00000020
|
|
|
|
|
|
+#define TCTRL_GTS 0x00000020
|
|
|
|
|
|
#define RCTRL_PAL_MASK 0x001f0000
|
|
#define RCTRL_PAL_MASK 0x001f0000
|
|
#define RCTRL_PAL_SHIFT 16
|
|
#define RCTRL_PAL_SHIFT 16
|
|
@@ -863,6 +863,52 @@ int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void graceful_start(struct fman_mac *dtsec, enum comm_mode mode)
|
|
|
|
+{
|
|
|
|
+ struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+
|
|
|
|
+ if (mode & COMM_MODE_TX)
|
|
|
|
+ iowrite32be(ioread32be(®s->tctrl) &
|
|
|
|
+ ~TCTRL_GTS, ®s->tctrl);
|
|
|
|
+ if (mode & COMM_MODE_RX)
|
|
|
|
+ iowrite32be(ioread32be(®s->rctrl) &
|
|
|
|
+ ~RCTRL_GRS, ®s->rctrl);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode)
|
|
|
|
+{
|
|
|
|
+ struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+ u32 tmp;
|
|
|
|
+
|
|
|
|
+ /* Graceful stop - Assert the graceful Rx stop bit */
|
|
|
|
+ if (mode & COMM_MODE_RX) {
|
|
|
|
+ tmp = ioread32be(®s->rctrl) | RCTRL_GRS;
|
|
|
|
+ iowrite32be(tmp, ®s->rctrl);
|
|
|
|
+
|
|
|
|
+ if (dtsec->fm_rev_info.major == 2) {
|
|
|
|
+ /* Workaround for dTSEC Errata A002 */
|
|
|
|
+ usleep_range(100, 200);
|
|
|
|
+ } else {
|
|
|
|
+ /* Workaround for dTSEC Errata A004839 */
|
|
|
|
+ usleep_range(10, 50);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Graceful stop - Assert the graceful Tx stop bit */
|
|
|
|
+ if (mode & COMM_MODE_TX) {
|
|
|
|
+ if (dtsec->fm_rev_info.major == 2) {
|
|
|
|
+ /* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
|
|
|
|
+ pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
|
|
|
|
+ } else {
|
|
|
|
+ tmp = ioread32be(®s->tctrl) | TCTRL_GTS;
|
|
|
|
+ iowrite32be(tmp, ®s->tctrl);
|
|
|
|
+
|
|
|
|
+ /* Workaround for dTSEC Errata A0012, A0014 */
|
|
|
|
+ usleep_range(10, 50);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
|
|
int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
|
|
{
|
|
{
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
@@ -880,13 +926,8 @@ int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
|
|
|
|
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
|
|
|
|
- /* Graceful start - clear the graceful receive stop bit */
|
|
|
|
- if (mode & COMM_MODE_TX)
|
|
|
|
- iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS,
|
|
|
|
- ®s->tctrl);
|
|
|
|
- if (mode & COMM_MODE_RX)
|
|
|
|
- iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS,
|
|
|
|
- ®s->rctrl);
|
|
|
|
|
|
+ /* Graceful start - clear the graceful Rx/Tx stop bit */
|
|
|
|
+ graceful_start(dtsec, mode);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -899,23 +940,8 @@ int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
- /* Gracefull stop - Assert the graceful transmit stop bit */
|
|
|
|
- if (mode & COMM_MODE_RX) {
|
|
|
|
- tmp = ioread32be(®s->rctrl) | RCTRL_GRS;
|
|
|
|
- iowrite32be(tmp, ®s->rctrl);
|
|
|
|
-
|
|
|
|
- if (dtsec->fm_rev_info.major == 2)
|
|
|
|
- usleep_range(100, 200);
|
|
|
|
- else
|
|
|
|
- udelay(10);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (mode & COMM_MODE_TX) {
|
|
|
|
- if (dtsec->fm_rev_info.major == 2)
|
|
|
|
- pr_debug("GTS not supported due to DTSEC_A004 errata.\n");
|
|
|
|
- else
|
|
|
|
- pr_debug("GTS not supported due to DTSEC_A0014 errata.\n");
|
|
|
|
- }
|
|
|
|
|
|
+ /* Graceful stop - Assert the graceful Rx/Tx stop bit */
|
|
|
|
+ graceful_stop(dtsec, mode);
|
|
|
|
|
|
tmp = ioread32be(®s->maccfg1);
|
|
tmp = ioread32be(®s->maccfg1);
|
|
if (mode & COMM_MODE_RX)
|
|
if (mode & COMM_MODE_RX)
|
|
@@ -933,11 +959,19 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
|
|
u16 pause_time, u16 __maybe_unused thresh_time)
|
|
u16 pause_time, u16 __maybe_unused thresh_time)
|
|
{
|
|
{
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+ enum comm_mode mode = COMM_MODE_NONE;
|
|
u32 ptv = 0;
|
|
u32 ptv = 0;
|
|
|
|
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0)
|
|
|
|
+ mode |= COMM_MODE_RX;
|
|
|
|
+ if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0)
|
|
|
|
+ mode |= COMM_MODE_TX;
|
|
|
|
+
|
|
|
|
+ graceful_stop(dtsec, mode);
|
|
|
|
+
|
|
if (pause_time) {
|
|
if (pause_time) {
|
|
/* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */
|
|
/* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */
|
|
if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) {
|
|
if (dtsec->fm_rev_info.major == 2 && pause_time <= 320) {
|
|
@@ -958,17 +992,27 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
|
|
iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW,
|
|
iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW,
|
|
®s->maccfg1);
|
|
®s->maccfg1);
|
|
|
|
|
|
|
|
+ graceful_start(dtsec, mode);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
|
|
int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
|
|
{
|
|
{
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+ enum comm_mode mode = COMM_MODE_NONE;
|
|
u32 tmp;
|
|
u32 tmp;
|
|
|
|
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0)
|
|
|
|
+ mode |= COMM_MODE_RX;
|
|
|
|
+ if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0)
|
|
|
|
+ mode |= COMM_MODE_TX;
|
|
|
|
+
|
|
|
|
+ graceful_stop(dtsec, mode);
|
|
|
|
+
|
|
tmp = ioread32be(®s->maccfg1);
|
|
tmp = ioread32be(®s->maccfg1);
|
|
if (en)
|
|
if (en)
|
|
tmp |= MACCFG1_RX_FLOW;
|
|
tmp |= MACCFG1_RX_FLOW;
|
|
@@ -976,20 +1020,34 @@ int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
|
|
tmp &= ~MACCFG1_RX_FLOW;
|
|
tmp &= ~MACCFG1_RX_FLOW;
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
iowrite32be(tmp, ®s->maccfg1);
|
|
|
|
|
|
|
|
+ graceful_start(dtsec, mode);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr)
|
|
int dtsec_modify_mac_address(struct fman_mac *dtsec, enet_addr_t *enet_addr)
|
|
{
|
|
{
|
|
|
|
+ struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+ enum comm_mode mode = COMM_MODE_NONE;
|
|
|
|
+
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0)
|
|
|
|
+ mode |= COMM_MODE_RX;
|
|
|
|
+ if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0)
|
|
|
|
+ mode |= COMM_MODE_TX;
|
|
|
|
+
|
|
|
|
+ graceful_stop(dtsec, mode);
|
|
|
|
+
|
|
/* Initialize MAC Station Address registers (1 & 2)
|
|
/* Initialize MAC Station Address registers (1 & 2)
|
|
* Station address have to be swapped (big endian to little endian
|
|
* Station address have to be swapped (big endian to little endian
|
|
*/
|
|
*/
|
|
dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr);
|
|
dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr);
|
|
set_mac_address(dtsec->regs, (u8 *)(*enet_addr));
|
|
set_mac_address(dtsec->regs, (u8 *)(*enet_addr));
|
|
|
|
|
|
|
|
+ graceful_start(dtsec, mode);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1162,11 +1220,19 @@ int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
|
|
int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
|
|
int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
|
|
{
|
|
{
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
struct dtsec_regs __iomem *regs = dtsec->regs;
|
|
|
|
+ enum comm_mode mode = COMM_MODE_NONE;
|
|
u32 tmp;
|
|
u32 tmp;
|
|
|
|
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
if (!is_init_done(dtsec->dtsec_drv_param))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ if ((ioread32be(®s->rctrl) & RCTRL_GRS) == 0)
|
|
|
|
+ mode |= COMM_MODE_RX;
|
|
|
|
+ if ((ioread32be(®s->tctrl) & TCTRL_GTS) == 0)
|
|
|
|
+ mode |= COMM_MODE_TX;
|
|
|
|
+
|
|
|
|
+ graceful_stop(dtsec, mode);
|
|
|
|
+
|
|
tmp = ioread32be(®s->maccfg2);
|
|
tmp = ioread32be(®s->maccfg2);
|
|
|
|
|
|
/* Full Duplex */
|
|
/* Full Duplex */
|
|
@@ -1186,6 +1252,8 @@ int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
|
|
tmp &= ~DTSEC_ECNTRL_R100M;
|
|
tmp &= ~DTSEC_ECNTRL_R100M;
|
|
iowrite32be(tmp, ®s->ecntrl);
|
|
iowrite32be(tmp, ®s->ecntrl);
|
|
|
|
|
|
|
|
+ graceful_start(dtsec, mode);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|