Commit 854a2e7c authored by Guo-Fu Tseng's avatar Guo-Fu Tseng Committed by David S. Miller

jme: Safer MAC processor reset sequence

Adding control to clk_rx, and makes the control of clk_{rx|tx|tcp}
with safer sequence.
This sequence is provided by JMicron.
Signed-off-by: default avatarGuo-Fu Tseng <cooldavid@cooldavid.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3903c023
...@@ -160,6 +160,67 @@ jme_setup_wakeup_frame(struct jme_adapter *jme, ...@@ -160,6 +160,67 @@ jme_setup_wakeup_frame(struct jme_adapter *jme,
} }
} }
static inline void
jme_mac_rxclk_off(struct jme_adapter *jme)
{
jme->reg_gpreg1 |= GPREG1_RXCLKOFF;
jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
}
static inline void
jme_mac_rxclk_on(struct jme_adapter *jme)
{
jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF;
jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
}
static inline void
jme_mac_txclk_off(struct jme_adapter *jme)
{
jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC);
jwrite32f(jme, JME_GHC, jme->reg_ghc);
}
static inline void
jme_mac_txclk_on(struct jme_adapter *jme)
{
u32 speed = jme->reg_ghc & GHC_SPEED;
if (speed == GHC_SPEED_1000M)
jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
else
jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
jwrite32f(jme, JME_GHC, jme->reg_ghc);
}
static inline void
jme_reset_ghc_speed(struct jme_adapter *jme)
{
jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX);
jwrite32f(jme, JME_GHC, jme->reg_ghc);
}
static inline void
jme_reset_250A2_workaround(struct jme_adapter *jme)
{
jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
GPREG1_RSSPATCH);
jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
}
static inline void
jme_assert_ghc_reset(struct jme_adapter *jme)
{
jme->reg_ghc |= GHC_SWRST;
jwrite32f(jme, JME_GHC, jme->reg_ghc);
}
static inline void
jme_clear_ghc_reset(struct jme_adapter *jme)
{
jme->reg_ghc &= ~GHC_SWRST;
jwrite32f(jme, JME_GHC, jme->reg_ghc);
}
static inline void static inline void
jme_reset_mac_processor(struct jme_adapter *jme) jme_reset_mac_processor(struct jme_adapter *jme)
{ {
...@@ -168,9 +229,24 @@ jme_reset_mac_processor(struct jme_adapter *jme) ...@@ -168,9 +229,24 @@ jme_reset_mac_processor(struct jme_adapter *jme)
u32 gpreg0; u32 gpreg0;
int i; int i;
jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST); jme_reset_ghc_speed(jme);
udelay(2); jme_reset_250A2_workaround(jme);
jwrite32(jme, JME_GHC, jme->reg_ghc);
jme_mac_rxclk_on(jme);
jme_mac_txclk_on(jme);
udelay(1);
jme_assert_ghc_reset(jme);
udelay(1);
jme_mac_rxclk_off(jme);
jme_mac_txclk_off(jme);
udelay(1);
jme_clear_ghc_reset(jme);
udelay(1);
jme_mac_rxclk_on(jme);
jme_mac_txclk_on(jme);
udelay(1);
jme_mac_rxclk_off(jme);
jme_mac_txclk_off(jme);
jwrite32(jme, JME_RXDBA_LO, 0x00000000); jwrite32(jme, JME_RXDBA_LO, 0x00000000);
jwrite32(jme, JME_RXDBA_HI, 0x00000000); jwrite32(jme, JME_RXDBA_HI, 0x00000000);
...@@ -190,14 +266,6 @@ jme_reset_mac_processor(struct jme_adapter *jme) ...@@ -190,14 +266,6 @@ jme_reset_mac_processor(struct jme_adapter *jme)
else else
gpreg0 = GPREG0_DEFAULT; gpreg0 = GPREG0_DEFAULT;
jwrite32(jme, JME_GPREG0, gpreg0); jwrite32(jme, JME_GPREG0, gpreg0);
jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
}
static inline void
jme_reset_ghc_speed(struct jme_adapter *jme)
{
jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX);
jwrite32(jme, JME_GHC, jme->reg_ghc);
} }
static inline void static inline void
...@@ -351,7 +419,7 @@ static int ...@@ -351,7 +419,7 @@ static int
jme_check_link(struct net_device *netdev, int testonly) jme_check_link(struct net_device *netdev, int testonly)
{ {
struct jme_adapter *jme = netdev_priv(netdev); struct jme_adapter *jme = netdev_priv(netdev);
u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1; u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr;
char linkmsg[64]; char linkmsg[64];
int rc = 0; int rc = 0;
...@@ -414,23 +482,21 @@ jme_check_link(struct net_device *netdev, int testonly) ...@@ -414,23 +482,21 @@ jme_check_link(struct net_device *netdev, int testonly)
jme->phylink = phylink; jme->phylink = phylink;
ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX | /*
GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE | * The speed/duplex setting of jme->reg_ghc already cleared
GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY); * by jme_reset_mac_processor()
*/
switch (phylink & PHY_LINK_SPEED_MASK) { switch (phylink & PHY_LINK_SPEED_MASK) {
case PHY_LINK_SPEED_10M: case PHY_LINK_SPEED_10M:
ghc |= GHC_SPEED_10M | jme->reg_ghc |= GHC_SPEED_10M;
GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "10 Mbps, "); strcat(linkmsg, "10 Mbps, ");
break; break;
case PHY_LINK_SPEED_100M: case PHY_LINK_SPEED_100M:
ghc |= GHC_SPEED_100M | jme->reg_ghc |= GHC_SPEED_100M;
GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "100 Mbps, "); strcat(linkmsg, "100 Mbps, ");
break; break;
case PHY_LINK_SPEED_1000M: case PHY_LINK_SPEED_1000M:
ghc |= GHC_SPEED_1000M | jme->reg_ghc |= GHC_SPEED_1000M;
GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
strcat(linkmsg, "1000 Mbps, "); strcat(linkmsg, "1000 Mbps, ");
break; break;
default: default:
...@@ -440,7 +506,7 @@ jme_check_link(struct net_device *netdev, int testonly) ...@@ -440,7 +506,7 @@ jme_check_link(struct net_device *netdev, int testonly)
if (phylink & PHY_LINK_DUPLEX) { if (phylink & PHY_LINK_DUPLEX) {
jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT);
jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX); jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX);
ghc |= GHC_DPX; jme->reg_ghc |= GHC_DPX;
} else { } else {
jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT |
TXMCS_BACKOFF | TXMCS_BACKOFF |
...@@ -449,18 +515,21 @@ jme_check_link(struct net_device *netdev, int testonly) ...@@ -449,18 +515,21 @@ jme_check_link(struct net_device *netdev, int testonly)
jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX); jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX);
} }
gpreg1 = GPREG1_DEFAULT; jwrite32(jme, JME_GHC, jme->reg_ghc);
if (is_buggy250(jme->pdev->device, jme->chiprev)) { if (is_buggy250(jme->pdev->device, jme->chiprev)) {
jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
GPREG1_RSSPATCH);
if (!(phylink & PHY_LINK_DUPLEX)) if (!(phylink & PHY_LINK_DUPLEX))
gpreg1 |= GPREG1_HALFMODEPATCH; jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH;
switch (phylink & PHY_LINK_SPEED_MASK) { switch (phylink & PHY_LINK_SPEED_MASK) {
case PHY_LINK_SPEED_10M: case PHY_LINK_SPEED_10M:
jme_set_phyfifo_8level(jme); jme_set_phyfifo_8level(jme);
gpreg1 |= GPREG1_RSSPATCH; jme->reg_gpreg1 |= GPREG1_RSSPATCH;
break; break;
case PHY_LINK_SPEED_100M: case PHY_LINK_SPEED_100M:
jme_set_phyfifo_5level(jme); jme_set_phyfifo_5level(jme);
gpreg1 |= GPREG1_RSSPATCH; jme->reg_gpreg1 |= GPREG1_RSSPATCH;
break; break;
case PHY_LINK_SPEED_1000M: case PHY_LINK_SPEED_1000M:
jme_set_phyfifo_8level(jme); jme_set_phyfifo_8level(jme);
...@@ -469,10 +538,7 @@ jme_check_link(struct net_device *netdev, int testonly) ...@@ -469,10 +538,7 @@ jme_check_link(struct net_device *netdev, int testonly)
break; break;
} }
} }
jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
jwrite32(jme, JME_GPREG1, gpreg1);
jwrite32(jme, JME_GHC, ghc);
jme->reg_ghc = ghc;
strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
"Full-Duplex, " : "Full-Duplex, " :
...@@ -611,10 +677,14 @@ jme_enable_tx_engine(struct jme_adapter *jme) ...@@ -611,10 +677,14 @@ jme_enable_tx_engine(struct jme_adapter *jme)
* Enable TX Engine * Enable TX Engine
*/ */
wmb(); wmb();
jwrite32(jme, JME_TXCS, jme->reg_txcs | jwrite32f(jme, JME_TXCS, jme->reg_txcs |
TXCS_SELECT_QUEUE0 | TXCS_SELECT_QUEUE0 |
TXCS_ENABLE); TXCS_ENABLE);
/*
* Start clock for TX MAC Processor
*/
jme_mac_txclk_on(jme);
} }
static inline void static inline void
...@@ -649,6 +719,11 @@ jme_disable_tx_engine(struct jme_adapter *jme) ...@@ -649,6 +719,11 @@ jme_disable_tx_engine(struct jme_adapter *jme)
if (!i) if (!i)
pr_err("Disable TX engine timeout\n"); pr_err("Disable TX engine timeout\n");
/*
* Stop clock for TX MAC Processor
*/
jme_mac_txclk_off(jme);
} }
static void static void
...@@ -829,10 +904,15 @@ jme_enable_rx_engine(struct jme_adapter *jme) ...@@ -829,10 +904,15 @@ jme_enable_rx_engine(struct jme_adapter *jme)
* Enable RX Engine * Enable RX Engine
*/ */
wmb(); wmb();
jwrite32(jme, JME_RXCS, jme->reg_rxcs | jwrite32f(jme, JME_RXCS, jme->reg_rxcs |
RXCS_QUEUESEL_Q0 | RXCS_QUEUESEL_Q0 |
RXCS_ENABLE | RXCS_ENABLE |
RXCS_QST); RXCS_QST);
/*
* Start clock for RX MAC Processor
*/
jme_mac_rxclk_on(jme);
} }
static inline void static inline void
...@@ -869,6 +949,10 @@ jme_disable_rx_engine(struct jme_adapter *jme) ...@@ -869,6 +949,10 @@ jme_disable_rx_engine(struct jme_adapter *jme)
if (!i) if (!i)
pr_err("Disable RX engine timeout\n"); pr_err("Disable RX engine timeout\n");
/*
* Stop clock for RX MAC Processor
*/
jme_mac_rxclk_off(jme);
} }
static int static int
...@@ -1205,7 +1289,6 @@ jme_link_change_tasklet(unsigned long arg) ...@@ -1205,7 +1289,6 @@ jme_link_change_tasklet(unsigned long arg)
tasklet_disable(&jme->rxempty_task); tasklet_disable(&jme->rxempty_task);
if (netif_carrier_ok(netdev)) { if (netif_carrier_ok(netdev)) {
jme_reset_ghc_speed(jme);
jme_disable_rx_engine(jme); jme_disable_rx_engine(jme);
jme_disable_tx_engine(jme); jme_disable_tx_engine(jme);
jme_reset_mac_processor(jme); jme_reset_mac_processor(jme);
...@@ -1735,7 +1818,6 @@ jme_close(struct net_device *netdev) ...@@ -1735,7 +1818,6 @@ jme_close(struct net_device *netdev)
tasklet_disable(&jme->rxclean_task); tasklet_disable(&jme->rxclean_task);
tasklet_disable(&jme->rxempty_task); tasklet_disable(&jme->rxempty_task);
jme_reset_ghc_speed(jme);
jme_disable_rx_engine(jme); jme_disable_rx_engine(jme);
jme_disable_tx_engine(jme); jme_disable_tx_engine(jme);
jme_reset_mac_processor(jme); jme_reset_mac_processor(jme);
...@@ -2921,6 +3003,7 @@ jme_init_one(struct pci_dev *pdev, ...@@ -2921,6 +3003,7 @@ jme_init_one(struct pci_dev *pdev,
jme->reg_rxmcs = RXMCS_DEFAULT; jme->reg_rxmcs = RXMCS_DEFAULT;
jme->reg_txpfc = 0; jme->reg_txpfc = 0;
jme->reg_pmcs = PMCS_MFEN; jme->reg_pmcs = PMCS_MFEN;
jme->reg_gpreg1 = GPREG1_DEFAULT;
set_bit(JME_FLAG_TXCSUM, &jme->flags); set_bit(JME_FLAG_TXCSUM, &jme->flags);
set_bit(JME_FLAG_TSO, &jme->flags); set_bit(JME_FLAG_TSO, &jme->flags);
...@@ -3076,7 +3159,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -3076,7 +3159,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state)
jme_polling_mode(jme); jme_polling_mode(jme);
jme_stop_pcc_timer(jme); jme_stop_pcc_timer(jme);
jme_reset_ghc_speed(jme);
jme_disable_rx_engine(jme); jme_disable_rx_engine(jme);
jme_disable_tx_engine(jme); jme_disable_tx_engine(jme);
jme_reset_mac_processor(jme); jme_reset_mac_processor(jme);
......
...@@ -434,6 +434,7 @@ struct jme_adapter { ...@@ -434,6 +434,7 @@ struct jme_adapter {
u32 reg_rxmcs; u32 reg_rxmcs;
u32 reg_ghc; u32 reg_ghc;
u32 reg_pmcs; u32 reg_pmcs;
u32 reg_gpreg1;
u32 phylink; u32 phylink;
u32 tx_ring_size; u32 tx_ring_size;
u32 tx_ring_mask; u32 tx_ring_mask;
...@@ -821,6 +822,8 @@ static inline u32 smi_phy_addr(int x) ...@@ -821,6 +822,8 @@ static inline u32 smi_phy_addr(int x)
*/ */
enum jme_ghc_bit_mask { enum jme_ghc_bit_mask {
GHC_SWRST = 0x40000000, GHC_SWRST = 0x40000000,
GHC_TO_CLK_SRC = 0x00C00000,
GHC_TXMAC_CLK_SRC = 0x00300000,
GHC_DPX = 0x00000040, GHC_DPX = 0x00000040,
GHC_SPEED = 0x00000030, GHC_SPEED = 0x00000030,
GHC_LINK_POLL = 0x00000001, GHC_LINK_POLL = 0x00000001,
...@@ -999,18 +1002,17 @@ enum jme_gpreg0_vals { ...@@ -999,18 +1002,17 @@ enum jme_gpreg0_vals {
/* /*
* General Purpose REG-1 * General Purpose REG-1
* Note: All theses bits defined here are for
* Chip mode revision 0x11 only
*/ */
enum jme_gpreg1_masks { enum jme_gpreg1_bit_masks {
GPREG1_RXCLKOFF = 0x04000000,
GPREG1_PCREQN = 0x00020000,
GPREG1_HALFMODEPATCH = 0x00000040, /* For Chip revision 0x11 only */
GPREG1_RSSPATCH = 0x00000020, /* For Chip revision 0x11 only */
GPREG1_INTRDELAYUNIT = 0x00000018, GPREG1_INTRDELAYUNIT = 0x00000018,
GPREG1_INTRDELAYENABLE = 0x00000007, GPREG1_INTRDELAYENABLE = 0x00000007,
}; };
enum jme_gpreg1_vals { enum jme_gpreg1_vals {
GPREG1_HALFMODEPATCH = 0x00000040,
GPREG1_RSSPATCH = 0x00000020,
GPREG1_INTDLYUNIT_16NS = 0x00000000, GPREG1_INTDLYUNIT_16NS = 0x00000000,
GPREG1_INTDLYUNIT_256NS = 0x00000008, GPREG1_INTDLYUNIT_256NS = 0x00000008,
GPREG1_INTDLYUNIT_1US = 0x00000010, GPREG1_INTDLYUNIT_1US = 0x00000010,
...@@ -1024,7 +1026,7 @@ enum jme_gpreg1_vals { ...@@ -1024,7 +1026,7 @@ enum jme_gpreg1_vals {
GPREG1_INTDLYEN_6U = 0x00000006, GPREG1_INTDLYEN_6U = 0x00000006,
GPREG1_INTDLYEN_7U = 0x00000007, GPREG1_INTDLYEN_7U = 0x00000007,
GPREG1_DEFAULT = 0x00000000, GPREG1_DEFAULT = GPREG1_PCREQN,
}; };
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment