diff options
author | Guo-Fu Tseng <cooldavid@cooldavid.org> | 2011-02-13 13:27:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-02-13 23:43:22 -0500 |
commit | 854a2e7c331a36244169626ba8e11e15d134cb5f (patch) | |
tree | e06c5ec5967eee5d078181b0e3b8958192dfe80f /drivers/net/jme.c | |
parent | 3903c023570446303a10f152cfc120dcbf9a4ccf (diff) |
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: Guo-Fu Tseng <cooldavid@cooldavid.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/jme.c')
-rw-r--r-- | drivers/net/jme.c | 152 |
1 files changed, 117 insertions, 35 deletions
diff --git a/drivers/net/jme.c b/drivers/net/jme.c index 6996d04e1de4..dd4132443b7b 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c | |||
@@ -161,6 +161,67 @@ jme_setup_wakeup_frame(struct jme_adapter *jme, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | static inline void | 163 | static inline void |
164 | jme_mac_rxclk_off(struct jme_adapter *jme) | ||
165 | { | ||
166 | jme->reg_gpreg1 |= GPREG1_RXCLKOFF; | ||
167 | jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); | ||
168 | } | ||
169 | |||
170 | static inline void | ||
171 | jme_mac_rxclk_on(struct jme_adapter *jme) | ||
172 | { | ||
173 | jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF; | ||
174 | jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1); | ||
175 | } | ||
176 | |||
177 | static inline void | ||
178 | jme_mac_txclk_off(struct jme_adapter *jme) | ||
179 | { | ||
180 | jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC); | ||
181 | jwrite32f(jme, JME_GHC, jme->reg_ghc); | ||
182 | } | ||
183 | |||
184 | static inline void | ||
185 | jme_mac_txclk_on(struct jme_adapter *jme) | ||
186 | { | ||
187 | u32 speed = jme->reg_ghc & GHC_SPEED; | ||
188 | if (speed == GHC_SPEED_1000M) | ||
189 | jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY; | ||
190 | else | ||
191 | jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; | ||
192 | jwrite32f(jme, JME_GHC, jme->reg_ghc); | ||
193 | } | ||
194 | |||
195 | static inline void | ||
196 | jme_reset_ghc_speed(struct jme_adapter *jme) | ||
197 | { | ||
198 | jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX); | ||
199 | jwrite32f(jme, JME_GHC, jme->reg_ghc); | ||
200 | } | ||
201 | |||
202 | static inline void | ||
203 | jme_reset_250A2_workaround(struct jme_adapter *jme) | ||
204 | { | ||
205 | jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | | ||
206 | GPREG1_RSSPATCH); | ||
207 | jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); | ||
208 | } | ||
209 | |||
210 | static inline void | ||
211 | jme_assert_ghc_reset(struct jme_adapter *jme) | ||
212 | { | ||
213 | jme->reg_ghc |= GHC_SWRST; | ||
214 | jwrite32f(jme, JME_GHC, jme->reg_ghc); | ||
215 | } | ||
216 | |||
217 | static inline void | ||
218 | jme_clear_ghc_reset(struct jme_adapter *jme) | ||
219 | { | ||
220 | jme->reg_ghc &= ~GHC_SWRST; | ||
221 | jwrite32f(jme, JME_GHC, jme->reg_ghc); | ||
222 | } | ||
223 | |||
224 | static inline void | ||
164 | jme_reset_mac_processor(struct jme_adapter *jme) | 225 | jme_reset_mac_processor(struct jme_adapter *jme) |
165 | { | 226 | { |
166 | static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0}; | 227 | static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0}; |
@@ -168,9 +229,24 @@ jme_reset_mac_processor(struct jme_adapter *jme) | |||
168 | u32 gpreg0; | 229 | u32 gpreg0; |
169 | int i; | 230 | int i; |
170 | 231 | ||
171 | jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST); | 232 | jme_reset_ghc_speed(jme); |
172 | udelay(2); | 233 | jme_reset_250A2_workaround(jme); |
173 | jwrite32(jme, JME_GHC, jme->reg_ghc); | 234 | |
235 | jme_mac_rxclk_on(jme); | ||
236 | jme_mac_txclk_on(jme); | ||
237 | udelay(1); | ||
238 | jme_assert_ghc_reset(jme); | ||
239 | udelay(1); | ||
240 | jme_mac_rxclk_off(jme); | ||
241 | jme_mac_txclk_off(jme); | ||
242 | udelay(1); | ||
243 | jme_clear_ghc_reset(jme); | ||
244 | udelay(1); | ||
245 | jme_mac_rxclk_on(jme); | ||
246 | jme_mac_txclk_on(jme); | ||
247 | udelay(1); | ||
248 | jme_mac_rxclk_off(jme); | ||
249 | jme_mac_txclk_off(jme); | ||
174 | 250 | ||
175 | jwrite32(jme, JME_RXDBA_LO, 0x00000000); | 251 | jwrite32(jme, JME_RXDBA_LO, 0x00000000); |
176 | jwrite32(jme, JME_RXDBA_HI, 0x00000000); | 252 | jwrite32(jme, JME_RXDBA_HI, 0x00000000); |
@@ -190,14 +266,6 @@ jme_reset_mac_processor(struct jme_adapter *jme) | |||
190 | else | 266 | else |
191 | gpreg0 = GPREG0_DEFAULT; | 267 | gpreg0 = GPREG0_DEFAULT; |
192 | jwrite32(jme, JME_GPREG0, gpreg0); | 268 | jwrite32(jme, JME_GPREG0, gpreg0); |
193 | jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT); | ||
194 | } | ||
195 | |||
196 | static inline void | ||
197 | jme_reset_ghc_speed(struct jme_adapter *jme) | ||
198 | { | ||
199 | jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX); | ||
200 | jwrite32(jme, JME_GHC, jme->reg_ghc); | ||
201 | } | 269 | } |
202 | 270 | ||
203 | static inline void | 271 | static inline void |
@@ -351,7 +419,7 @@ static int | |||
351 | jme_check_link(struct net_device *netdev, int testonly) | 419 | jme_check_link(struct net_device *netdev, int testonly) |
352 | { | 420 | { |
353 | struct jme_adapter *jme = netdev_priv(netdev); | 421 | struct jme_adapter *jme = netdev_priv(netdev); |
354 | u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1; | 422 | u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr; |
355 | char linkmsg[64]; | 423 | char linkmsg[64]; |
356 | int rc = 0; | 424 | int rc = 0; |
357 | 425 | ||
@@ -414,23 +482,21 @@ jme_check_link(struct net_device *netdev, int testonly) | |||
414 | 482 | ||
415 | jme->phylink = phylink; | 483 | jme->phylink = phylink; |
416 | 484 | ||
417 | ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX | | 485 | /* |
418 | GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE | | 486 | * The speed/duplex setting of jme->reg_ghc already cleared |
419 | GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY); | 487 | * by jme_reset_mac_processor() |
488 | */ | ||
420 | switch (phylink & PHY_LINK_SPEED_MASK) { | 489 | switch (phylink & PHY_LINK_SPEED_MASK) { |
421 | case PHY_LINK_SPEED_10M: | 490 | case PHY_LINK_SPEED_10M: |
422 | ghc |= GHC_SPEED_10M | | 491 | jme->reg_ghc |= GHC_SPEED_10M; |
423 | GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; | ||
424 | strcat(linkmsg, "10 Mbps, "); | 492 | strcat(linkmsg, "10 Mbps, "); |
425 | break; | 493 | break; |
426 | case PHY_LINK_SPEED_100M: | 494 | case PHY_LINK_SPEED_100M: |
427 | ghc |= GHC_SPEED_100M | | 495 | jme->reg_ghc |= GHC_SPEED_100M; |
428 | GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE; | ||
429 | strcat(linkmsg, "100 Mbps, "); | 496 | strcat(linkmsg, "100 Mbps, "); |
430 | break; | 497 | break; |
431 | case PHY_LINK_SPEED_1000M: | 498 | case PHY_LINK_SPEED_1000M: |
432 | ghc |= GHC_SPEED_1000M | | 499 | jme->reg_ghc |= GHC_SPEED_1000M; |
433 | GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY; | ||
434 | strcat(linkmsg, "1000 Mbps, "); | 500 | strcat(linkmsg, "1000 Mbps, "); |
435 | break; | 501 | break; |
436 | default: | 502 | default: |
@@ -440,7 +506,7 @@ jme_check_link(struct net_device *netdev, int testonly) | |||
440 | if (phylink & PHY_LINK_DUPLEX) { | 506 | if (phylink & PHY_LINK_DUPLEX) { |
441 | jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); | 507 | jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT); |
442 | jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX); | 508 | jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX); |
443 | ghc |= GHC_DPX; | 509 | jme->reg_ghc |= GHC_DPX; |
444 | } else { | 510 | } else { |
445 | jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | | 511 | jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT | |
446 | TXMCS_BACKOFF | | 512 | TXMCS_BACKOFF | |
@@ -449,18 +515,21 @@ jme_check_link(struct net_device *netdev, int testonly) | |||
449 | jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX); | 515 | jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX); |
450 | } | 516 | } |
451 | 517 | ||
452 | gpreg1 = GPREG1_DEFAULT; | 518 | jwrite32(jme, JME_GHC, jme->reg_ghc); |
519 | |||
453 | if (is_buggy250(jme->pdev->device, jme->chiprev)) { | 520 | if (is_buggy250(jme->pdev->device, jme->chiprev)) { |
521 | jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH | | ||
522 | GPREG1_RSSPATCH); | ||
454 | if (!(phylink & PHY_LINK_DUPLEX)) | 523 | if (!(phylink & PHY_LINK_DUPLEX)) |
455 | gpreg1 |= GPREG1_HALFMODEPATCH; | 524 | jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH; |
456 | switch (phylink & PHY_LINK_SPEED_MASK) { | 525 | switch (phylink & PHY_LINK_SPEED_MASK) { |
457 | case PHY_LINK_SPEED_10M: | 526 | case PHY_LINK_SPEED_10M: |
458 | jme_set_phyfifo_8level(jme); | 527 | jme_set_phyfifo_8level(jme); |
459 | gpreg1 |= GPREG1_RSSPATCH; | 528 | jme->reg_gpreg1 |= GPREG1_RSSPATCH; |
460 | break; | 529 | break; |
461 | case PHY_LINK_SPEED_100M: | 530 | case PHY_LINK_SPEED_100M: |
462 | jme_set_phyfifo_5level(jme); | 531 | jme_set_phyfifo_5level(jme); |
463 | gpreg1 |= GPREG1_RSSPATCH; | 532 | jme->reg_gpreg1 |= GPREG1_RSSPATCH; |
464 | break; | 533 | break; |
465 | case PHY_LINK_SPEED_1000M: | 534 | case PHY_LINK_SPEED_1000M: |
466 | jme_set_phyfifo_8level(jme); | 535 | jme_set_phyfifo_8level(jme); |
@@ -469,10 +538,7 @@ jme_check_link(struct net_device *netdev, int testonly) | |||
469 | break; | 538 | break; |
470 | } | 539 | } |
471 | } | 540 | } |
472 | 541 | jwrite32(jme, JME_GPREG1, jme->reg_gpreg1); | |
473 | jwrite32(jme, JME_GPREG1, gpreg1); | ||
474 | jwrite32(jme, JME_GHC, ghc); | ||
475 | jme->reg_ghc = ghc; | ||
476 | 542 | ||
477 | strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? | 543 | strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ? |
478 | "Full-Duplex, " : | 544 | "Full-Duplex, " : |
@@ -611,10 +677,14 @@ jme_enable_tx_engine(struct jme_adapter *jme) | |||
611 | * Enable TX Engine | 677 | * Enable TX Engine |
612 | */ | 678 | */ |
613 | wmb(); | 679 | wmb(); |
614 | jwrite32(jme, JME_TXCS, jme->reg_txcs | | 680 | jwrite32f(jme, JME_TXCS, jme->reg_txcs | |
615 | TXCS_SELECT_QUEUE0 | | 681 | TXCS_SELECT_QUEUE0 | |
616 | TXCS_ENABLE); | 682 | TXCS_ENABLE); |
617 | 683 | ||
684 | /* | ||
685 | * Start clock for TX MAC Processor | ||
686 | */ | ||
687 | jme_mac_txclk_on(jme); | ||
618 | } | 688 | } |
619 | 689 | ||
620 | static inline void | 690 | static inline void |
@@ -649,6 +719,11 @@ jme_disable_tx_engine(struct jme_adapter *jme) | |||
649 | 719 | ||
650 | if (!i) | 720 | if (!i) |
651 | pr_err("Disable TX engine timeout\n"); | 721 | pr_err("Disable TX engine timeout\n"); |
722 | |||
723 | /* | ||
724 | * Stop clock for TX MAC Processor | ||
725 | */ | ||
726 | jme_mac_txclk_off(jme); | ||
652 | } | 727 | } |
653 | 728 | ||
654 | static void | 729 | static void |
@@ -829,10 +904,15 @@ jme_enable_rx_engine(struct jme_adapter *jme) | |||
829 | * Enable RX Engine | 904 | * Enable RX Engine |
830 | */ | 905 | */ |
831 | wmb(); | 906 | wmb(); |
832 | jwrite32(jme, JME_RXCS, jme->reg_rxcs | | 907 | jwrite32f(jme, JME_RXCS, jme->reg_rxcs | |
833 | RXCS_QUEUESEL_Q0 | | 908 | RXCS_QUEUESEL_Q0 | |
834 | RXCS_ENABLE | | 909 | RXCS_ENABLE | |
835 | RXCS_QST); | 910 | RXCS_QST); |
911 | |||
912 | /* | ||
913 | * Start clock for RX MAC Processor | ||
914 | */ | ||
915 | jme_mac_rxclk_on(jme); | ||
836 | } | 916 | } |
837 | 917 | ||
838 | static inline void | 918 | static inline void |
@@ -869,6 +949,10 @@ jme_disable_rx_engine(struct jme_adapter *jme) | |||
869 | if (!i) | 949 | if (!i) |
870 | pr_err("Disable RX engine timeout\n"); | 950 | pr_err("Disable RX engine timeout\n"); |
871 | 951 | ||
952 | /* | ||
953 | * Stop clock for RX MAC Processor | ||
954 | */ | ||
955 | jme_mac_rxclk_off(jme); | ||
872 | } | 956 | } |
873 | 957 | ||
874 | static int | 958 | static int |
@@ -1205,7 +1289,6 @@ jme_link_change_tasklet(unsigned long arg) | |||
1205 | tasklet_disable(&jme->rxempty_task); | 1289 | tasklet_disable(&jme->rxempty_task); |
1206 | 1290 | ||
1207 | if (netif_carrier_ok(netdev)) { | 1291 | if (netif_carrier_ok(netdev)) { |
1208 | jme_reset_ghc_speed(jme); | ||
1209 | jme_disable_rx_engine(jme); | 1292 | jme_disable_rx_engine(jme); |
1210 | jme_disable_tx_engine(jme); | 1293 | jme_disable_tx_engine(jme); |
1211 | jme_reset_mac_processor(jme); | 1294 | jme_reset_mac_processor(jme); |
@@ -1735,7 +1818,6 @@ jme_close(struct net_device *netdev) | |||
1735 | tasklet_disable(&jme->rxclean_task); | 1818 | tasklet_disable(&jme->rxclean_task); |
1736 | tasklet_disable(&jme->rxempty_task); | 1819 | tasklet_disable(&jme->rxempty_task); |
1737 | 1820 | ||
1738 | jme_reset_ghc_speed(jme); | ||
1739 | jme_disable_rx_engine(jme); | 1821 | jme_disable_rx_engine(jme); |
1740 | jme_disable_tx_engine(jme); | 1822 | jme_disable_tx_engine(jme); |
1741 | jme_reset_mac_processor(jme); | 1823 | jme_reset_mac_processor(jme); |
@@ -2921,6 +3003,7 @@ jme_init_one(struct pci_dev *pdev, | |||
2921 | jme->reg_rxmcs = RXMCS_DEFAULT; | 3003 | jme->reg_rxmcs = RXMCS_DEFAULT; |
2922 | jme->reg_txpfc = 0; | 3004 | jme->reg_txpfc = 0; |
2923 | jme->reg_pmcs = PMCS_MFEN; | 3005 | jme->reg_pmcs = PMCS_MFEN; |
3006 | jme->reg_gpreg1 = GPREG1_DEFAULT; | ||
2924 | set_bit(JME_FLAG_TXCSUM, &jme->flags); | 3007 | set_bit(JME_FLAG_TXCSUM, &jme->flags); |
2925 | set_bit(JME_FLAG_TSO, &jme->flags); | 3008 | set_bit(JME_FLAG_TSO, &jme->flags); |
2926 | 3009 | ||
@@ -3076,7 +3159,6 @@ jme_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3076 | jme_polling_mode(jme); | 3159 | jme_polling_mode(jme); |
3077 | 3160 | ||
3078 | jme_stop_pcc_timer(jme); | 3161 | jme_stop_pcc_timer(jme); |
3079 | jme_reset_ghc_speed(jme); | ||
3080 | jme_disable_rx_engine(jme); | 3162 | jme_disable_rx_engine(jme); |
3081 | jme_disable_tx_engine(jme); | 3163 | jme_disable_tx_engine(jme); |
3082 | jme_reset_mac_processor(jme); | 3164 | jme_reset_mac_processor(jme); |