diff options
author | Michael Chan <mchan@broadcom.com> | 2005-12-19 19:27:04 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2005-12-19 19:27:04 -0500 |
commit | b401e9e2ec44a5fc1d8053546276bff584b7118e (patch) | |
tree | 3f554445d377269c941688d2ce23479bd198d8a3 /drivers/net/tg3.c | |
parent | dc56b7d46dd2b303a844166ef931270b882bf08c (diff) |
[TG3]: Add tw32_wait_f() for some sensitive registers
The tw32_f() function (register write with immediate read flush) can
hang when used on some registers to switch clock frequencies and
power. A new tw32_wait_f() is added for such registers with the
delay before the read and after the read.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r-- | drivers/net/tg3.c | 151 |
1 files changed, 77 insertions, 74 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index de898f175d73..b0d963c83746 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -341,6 +341,16 @@ static struct { | |||
341 | { "interrupt test (offline)" }, | 341 | { "interrupt test (offline)" }, |
342 | }; | 342 | }; |
343 | 343 | ||
344 | static void tg3_write32(struct tg3 *tp, u32 off, u32 val) | ||
345 | { | ||
346 | writel(val, tp->regs + off); | ||
347 | } | ||
348 | |||
349 | static u32 tg3_read32(struct tg3 *tp, u32 off) | ||
350 | { | ||
351 | return (readl(tp->regs + off)); | ||
352 | } | ||
353 | |||
344 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) | 354 | static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val) |
345 | { | 355 | { |
346 | unsigned long flags; | 356 | unsigned long flags; |
@@ -411,13 +421,29 @@ static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off) | |||
411 | return val; | 421 | return val; |
412 | } | 422 | } |
413 | 423 | ||
414 | static void _tw32_flush(struct tg3 *tp, u32 off, u32 val) | 424 | /* usec_wait specifies the wait time in usec when writing to certain registers |
425 | * where it is unsafe to read back the register without some delay. | ||
426 | * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power. | ||
427 | * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed. | ||
428 | */ | ||
429 | static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait) | ||
415 | { | 430 | { |
416 | tp->write32(tp, off, val); | 431 | if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) || |
417 | if (!(tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) && | 432 | (tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) |
418 | !(tp->tg3_flags & TG3_FLAG_5701_REG_WRITE_BUG) && | 433 | /* Non-posted methods */ |
419 | !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)) | 434 | tp->write32(tp, off, val); |
420 | tp->read32(tp, off); /* flush */ | 435 | else { |
436 | /* Posted method */ | ||
437 | tg3_write32(tp, off, val); | ||
438 | if (usec_wait) | ||
439 | udelay(usec_wait); | ||
440 | tp->read32(tp, off); | ||
441 | } | ||
442 | /* Wait again after the read for the posted method to guarantee that | ||
443 | * the wait time is met. | ||
444 | */ | ||
445 | if (usec_wait) | ||
446 | udelay(usec_wait); | ||
421 | } | 447 | } |
422 | 448 | ||
423 | static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) | 449 | static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val) |
@@ -438,16 +464,6 @@ static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val) | |||
438 | readl(mbox); | 464 | readl(mbox); |
439 | } | 465 | } |
440 | 466 | ||
441 | static void tg3_write32(struct tg3 *tp, u32 off, u32 val) | ||
442 | { | ||
443 | writel(val, tp->regs + off); | ||
444 | } | ||
445 | |||
446 | static u32 tg3_read32(struct tg3 *tp, u32 off) | ||
447 | { | ||
448 | return (readl(tp->regs + off)); | ||
449 | } | ||
450 | |||
451 | #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) | 467 | #define tw32_mailbox(reg, val) tp->write32_mbox(tp, reg, val) |
452 | #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) | 468 | #define tw32_mailbox_f(reg, val) tw32_mailbox_flush(tp, (reg), (val)) |
453 | #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) | 469 | #define tw32_rx_mbox(reg, val) tp->write32_rx_mbox(tp, reg, val) |
@@ -455,7 +471,8 @@ static u32 tg3_read32(struct tg3 *tp, u32 off) | |||
455 | #define tr32_mailbox(reg) tp->read32_mbox(tp, reg) | 471 | #define tr32_mailbox(reg) tp->read32_mbox(tp, reg) |
456 | 472 | ||
457 | #define tw32(reg,val) tp->write32(tp, reg, val) | 473 | #define tw32(reg,val) tp->write32(tp, reg, val) |
458 | #define tw32_f(reg,val) _tw32_flush(tp,(reg),(val)) | 474 | #define tw32_f(reg,val) _tw32_flush(tp,(reg),(val), 0) |
475 | #define tw32_wait_f(reg,val,us) _tw32_flush(tp,(reg),(val), (us)) | ||
459 | #define tr32(reg) tp->read32(tp, reg) | 476 | #define tr32(reg) tp->read32(tp, reg) |
460 | 477 | ||
461 | static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) | 478 | static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val) |
@@ -595,21 +612,19 @@ static void tg3_switch_clocks(struct tg3 *tp) | |||
595 | 612 | ||
596 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { | 613 | if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) { |
597 | if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { | 614 | if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) { |
598 | tw32_f(TG3PCI_CLOCK_CTRL, | 615 | tw32_wait_f(TG3PCI_CLOCK_CTRL, |
599 | clock_ctrl | CLOCK_CTRL_625_CORE); | 616 | clock_ctrl | CLOCK_CTRL_625_CORE, 40); |
600 | udelay(40); | ||
601 | } | 617 | } |
602 | } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { | 618 | } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) { |
603 | tw32_f(TG3PCI_CLOCK_CTRL, | 619 | tw32_wait_f(TG3PCI_CLOCK_CTRL, |
604 | clock_ctrl | | 620 | clock_ctrl | |
605 | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK)); | 621 | (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK), |
606 | udelay(40); | 622 | 40); |
607 | tw32_f(TG3PCI_CLOCK_CTRL, | 623 | tw32_wait_f(TG3PCI_CLOCK_CTRL, |
608 | clock_ctrl | (CLOCK_CTRL_ALTCLK)); | 624 | clock_ctrl | (CLOCK_CTRL_ALTCLK), |
609 | udelay(40); | 625 | 40); |
610 | } | 626 | } |
611 | tw32_f(TG3PCI_CLOCK_CTRL, clock_ctrl); | 627 | tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl, 40); |
612 | udelay(40); | ||
613 | } | 628 | } |
614 | 629 | ||
615 | #define PHY_BUSY_LOOPS 5000 | 630 | #define PHY_BUSY_LOOPS 5000 |
@@ -1033,13 +1048,13 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1033 | (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { | 1048 | (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) { |
1034 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || | 1049 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 || |
1035 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { | 1050 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) { |
1036 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1051 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1037 | (GRC_LCLCTRL_GPIO_OE0 | | 1052 | (GRC_LCLCTRL_GPIO_OE0 | |
1038 | GRC_LCLCTRL_GPIO_OE1 | | 1053 | GRC_LCLCTRL_GPIO_OE1 | |
1039 | GRC_LCLCTRL_GPIO_OE2 | | 1054 | GRC_LCLCTRL_GPIO_OE2 | |
1040 | GRC_LCLCTRL_GPIO_OUTPUT0 | | 1055 | GRC_LCLCTRL_GPIO_OUTPUT0 | |
1041 | GRC_LCLCTRL_GPIO_OUTPUT1)); | 1056 | GRC_LCLCTRL_GPIO_OUTPUT1), |
1042 | udelay(100); | 1057 | 100); |
1043 | } else { | 1058 | } else { |
1044 | u32 no_gpio2; | 1059 | u32 no_gpio2; |
1045 | u32 grc_local_ctrl = 0; | 1060 | u32 grc_local_ctrl = 0; |
@@ -1052,9 +1067,8 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1052 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == | 1067 | if (GET_ASIC_REV(tp->pci_chip_rev_id) == |
1053 | ASIC_REV_5714) { | 1068 | ASIC_REV_5714) { |
1054 | grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; | 1069 | grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3; |
1055 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1070 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1056 | grc_local_ctrl); | 1071 | grc_local_ctrl, 100); |
1057 | udelay(100); | ||
1058 | } | 1072 | } |
1059 | 1073 | ||
1060 | /* On 5753 and variants, GPIO2 cannot be used. */ | 1074 | /* On 5753 and variants, GPIO2 cannot be used. */ |
@@ -1070,21 +1084,18 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1070 | grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | | 1084 | grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 | |
1071 | GRC_LCLCTRL_GPIO_OUTPUT2); | 1085 | GRC_LCLCTRL_GPIO_OUTPUT2); |
1072 | } | 1086 | } |
1073 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1087 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1074 | grc_local_ctrl); | 1088 | grc_local_ctrl, 100); |
1075 | udelay(100); | ||
1076 | 1089 | ||
1077 | grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; | 1090 | grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0; |
1078 | 1091 | ||
1079 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1092 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1080 | grc_local_ctrl); | 1093 | grc_local_ctrl, 100); |
1081 | udelay(100); | ||
1082 | 1094 | ||
1083 | if (!no_gpio2) { | 1095 | if (!no_gpio2) { |
1084 | grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; | 1096 | grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2; |
1085 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1097 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1086 | grc_local_ctrl); | 1098 | grc_local_ctrl, 100); |
1087 | udelay(100); | ||
1088 | } | 1099 | } |
1089 | } | 1100 | } |
1090 | } else { | 1101 | } else { |
@@ -1094,19 +1105,16 @@ static void tg3_frob_aux_power(struct tg3 *tp) | |||
1094 | (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) | 1105 | (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0) |
1095 | return; | 1106 | return; |
1096 | 1107 | ||
1097 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1108 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1098 | (GRC_LCLCTRL_GPIO_OE1 | | 1109 | (GRC_LCLCTRL_GPIO_OE1 | |
1099 | GRC_LCLCTRL_GPIO_OUTPUT1)); | 1110 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); |
1100 | udelay(100); | ||
1101 | 1111 | ||
1102 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1112 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1103 | (GRC_LCLCTRL_GPIO_OE1)); | 1113 | GRC_LCLCTRL_GPIO_OE1, 100); |
1104 | udelay(100); | ||
1105 | 1114 | ||
1106 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | | 1115 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl | |
1107 | (GRC_LCLCTRL_GPIO_OE1 | | 1116 | (GRC_LCLCTRL_GPIO_OE1 | |
1108 | GRC_LCLCTRL_GPIO_OUTPUT1)); | 1117 | GRC_LCLCTRL_GPIO_OUTPUT1), 100); |
1109 | udelay(100); | ||
1110 | } | 1118 | } |
1111 | } | 1119 | } |
1112 | } | 1120 | } |
@@ -1149,10 +1157,8 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1149 | udelay(100); /* Delay after power state change */ | 1157 | udelay(100); /* Delay after power state change */ |
1150 | 1158 | ||
1151 | /* Switch out of Vaux if it is not a LOM */ | 1159 | /* Switch out of Vaux if it is not a LOM */ |
1152 | if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) { | 1160 | if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) |
1153 | tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl); | 1161 | tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl, 100); |
1154 | udelay(100); | ||
1155 | } | ||
1156 | 1162 | ||
1157 | return 0; | 1163 | return 0; |
1158 | 1164 | ||
@@ -1251,10 +1257,8 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1251 | base_val |= (CLOCK_CTRL_RXCLK_DISABLE | | 1257 | base_val |= (CLOCK_CTRL_RXCLK_DISABLE | |
1252 | CLOCK_CTRL_TXCLK_DISABLE); | 1258 | CLOCK_CTRL_TXCLK_DISABLE); |
1253 | 1259 | ||
1254 | tw32_f(TG3PCI_CLOCK_CTRL, base_val | | 1260 | tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK | |
1255 | CLOCK_CTRL_ALTCLK | | 1261 | CLOCK_CTRL_PWRDOWN_PLL133, 40); |
1256 | CLOCK_CTRL_PWRDOWN_PLL133); | ||
1257 | udelay(40); | ||
1258 | } else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { | 1262 | } else if (tp->tg3_flags2 & TG3_FLG2_5780_CLASS) { |
1259 | /* do nothing */ | 1263 | /* do nothing */ |
1260 | } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && | 1264 | } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) && |
@@ -1275,11 +1279,11 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1275 | newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; | 1279 | newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE; |
1276 | } | 1280 | } |
1277 | 1281 | ||
1278 | tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1); | 1282 | tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1, |
1279 | udelay(40); | 1283 | 40); |
1280 | 1284 | ||
1281 | tw32_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2); | 1285 | tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2, |
1282 | udelay(40); | 1286 | 40); |
1283 | 1287 | ||
1284 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { | 1288 | if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) { |
1285 | u32 newbits3; | 1289 | u32 newbits3; |
@@ -1293,9 +1297,8 @@ static int tg3_set_power_state(struct tg3 *tp, int state) | |||
1293 | newbits3 = CLOCK_CTRL_44MHZ_CORE; | 1297 | newbits3 = CLOCK_CTRL_44MHZ_CORE; |
1294 | } | 1298 | } |
1295 | 1299 | ||
1296 | tw32_f(TG3PCI_CLOCK_CTRL, | 1300 | tw32_wait_f(TG3PCI_CLOCK_CTRL, |
1297 | tp->pci_clock_ctrl | newbits3); | 1301 | tp->pci_clock_ctrl | newbits3, 40); |
1298 | udelay(40); | ||
1299 | } | 1302 | } |
1300 | } | 1303 | } |
1301 | 1304 | ||