]> Pileus Git - ~andy/linux/blobdiff - drivers/net/tg3.c
[TG3]: Workaround 5752 A0 chip ID
[~andy/linux] / drivers / net / tg3.c
index f22f19bbf11aae417e6b7803bc1dff82e07e3529..a4d0d61d6af051a72638f63b67b83471a1d6a88e 100644 (file)
@@ -1005,8 +1005,13 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
                pci_write_config_word(tp->pdev,
                                      pm + PCI_PM_CTRL,
                                      power_control);
-               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
-               udelay(100);
+               udelay(100);    /* Delay after power state change */
+
+               /* Switch out of Vaux if it is not a LOM */
+               if (!(tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT)) {
+                       tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
+                       udelay(100);
+               }
 
                return 0;
 
@@ -1151,6 +1156,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
 
        /* Finally, set the new power state. */
        pci_write_config_word(tp->pdev, pm + PCI_PM_CTRL, power_control);
+       udelay(100);    /* Delay after power state change */
 
        tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 
@@ -5336,10 +5342,23 @@ static int tg3_reset_hw(struct tg3 *tp)
        tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR);
        udelay(40);
 
-       tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
-       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700)
+       /* tp->grc_local_ctrl is partially set up during tg3_get_invariants().
+        * If TG3_FLAG_EEPROM_WRITE_PROT is set, we should read the
+        * register to preserve the GPIO settings for LOMs. The GPIOs,
+        * whether used as inputs or outputs, are set by boot code after
+        * reset.
+        */
+       if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
+               u32 gpio_mask;
+
+               gpio_mask = GRC_LCLCTRL_GPIO_OE0 | GRC_LCLCTRL_GPIO_OE2 |
+                           GRC_LCLCTRL_GPIO_OUTPUT0 | GRC_LCLCTRL_GPIO_OUTPUT2;
+               tp->grc_local_ctrl |= tr32(GRC_LOCAL_CTRL) & gpio_mask;
+
+               /* GPIO1 must be driven high for eeprom write protect */
                tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
                                       GRC_LCLCTRL_GPIO_OUTPUT1);
+       }
        tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
        udelay(100);
 
@@ -7430,8 +7449,8 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
        }
 
        if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
-               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-                      GRC_LCLCTRL_GPIO_OE1);
+               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
+                      ~GRC_LCLCTRL_GPIO_OUTPUT1);
                udelay(40);
        }
 
@@ -7477,8 +7496,7 @@ static int tg3_nvram_write_block(struct tg3 *tp, u32 offset, u32 len, u8 *buf)
        }
 
        if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
-               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
-                      GRC_LCLCTRL_GPIO_OE1 | GRC_LCLCTRL_GPIO_OUTPUT1);
+               tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
                udelay(40);
        }
 
@@ -7542,21 +7560,27 @@ static inline struct subsys_tbl_ent *lookup_by_subsys(struct tg3 *tp)
        return NULL;
 }
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+/* Since this function may be called in D3-hot power state during
+ * tg3_init_one(), only config cycles are allowed.
+ */
+static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
-       u32 eeprom_phy_id, hw_phy_id_1, hw_phy_id_2;
-       u32 hw_phy_id, hw_phy_id_masked;
        u32 val;
-       int eeprom_signature_found, eeprom_phy_serdes, err;
+
+       /* Make sure register accesses (indirect or otherwise)
+        * will function correctly.
+        */
+       pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
+                              tp->misc_host_ctrl);
 
        tp->phy_id = PHY_ID_INVALID;
-       eeprom_phy_id = PHY_ID_INVALID;
-       eeprom_phy_serdes = 0;
-       eeprom_signature_found = 0;
+       tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
        tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
        if (val == NIC_SRAM_DATA_SIG_MAGIC) {
                u32 nic_cfg, led_cfg;
-               u32 nic_phy_id, ver, cfg2 = 0;
+               u32 nic_phy_id, ver, cfg2 = 0, eeprom_phy_id;
+               int eeprom_phy_serdes = 0;
 
                tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg);
                tp->nic_sram_data_cfg = nic_cfg;
@@ -7569,8 +7593,6 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                    (ver > 0) && (ver < 0x100))
                        tg3_read_mem(tp, NIC_SRAM_DATA_CFG_2, &cfg2);
 
-               eeprom_signature_found = 1;
-
                if ((nic_cfg & NIC_SRAM_DATA_CFG_PHY_TYPE_MASK) ==
                    NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER)
                        eeprom_phy_serdes = 1;
@@ -7586,6 +7608,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                } else
                        eeprom_phy_id = 0;
 
+               tp->phy_id = eeprom_phy_id;
+               if (eeprom_phy_serdes)
+                       tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+
                if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                        led_cfg = cfg2 & (NIC_SRAM_DATA_CFG_LED_MODE_MASK |
                                    SHASTA_EXT_LED_MODE_MASK);
@@ -7653,6 +7679,13 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                if (cfg2 & (1 << 18))
                        tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
        }
+}
+
+static int __devinit tg3_phy_probe(struct tg3 *tp)
+{
+       u32 hw_phy_id_1, hw_phy_id_2;
+       u32 hw_phy_id, hw_phy_id_masked;
+       int err;
 
        /* Reading the PHY ID register can conflict with ASF
         * firwmare access to the PHY hardware.
@@ -7681,10 +7714,10 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
                if (hw_phy_id_masked == PHY_ID_BCM8002)
                        tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
        } else {
-               if (eeprom_signature_found) {
-                       tp->phy_id = eeprom_phy_id;
-                       if (eeprom_phy_serdes)
-                               tp->tg3_flags2 |= TG3_FLG2_PHY_SERDES;
+               if (tp->phy_id != PHY_ID_INVALID) {
+                       /* Do nothing, phy ID already set up in
+                        * tg3_get_eeprom_hw_cfg().
+                        */
                } else {
                        struct subsys_tbl_ent *p;
 
@@ -7755,9 +7788,6 @@ skip_phy_reset:
                err = tg3_init_5401phy_dsp(tp);
        }
 
-       if (!eeprom_signature_found)
-               tp->led_ctrl = LED_CTRL_MODE_PHY_1;
-
        if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)
                tp->link_config.advertising =
                        (ADVERTISED_1000baseT_Half |
@@ -7922,6 +7952,12 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        tp->pci_chip_rev_id = (misc_ctrl_reg >>
                               MISC_HOST_CTRL_CHIPREV_SHIFT);
 
+       /* Wrong chip ID in 5752 A0. This code can be removed later
+        * as A0 is not in production.
+        */
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
+               tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
+
        /* Initialize misc host control in PCI block. */
        tp->misc_host_ctrl |= (misc_ctrl_reg &
                               MISC_HOST_CTRL_CHIPREV);
@@ -7937,8 +7973,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752_A0 ||
-           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752_A1)
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
                tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
 
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
@@ -8023,6 +8058,26 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
                pci_write_config_dword(tp->pdev, TG3PCI_PCISTATE, pci_state_reg);
        }
 
+       /* Get eeprom hw config before calling tg3_set_power_state().
+        * In particular, the TG3_FLAG_EEPROM_WRITE_PROT flag must be
+        * determined before calling tg3_set_power_state() so that
+        * we know whether or not to switch out of Vaux power.
+        * When the flag is set, it means that GPIO1 is used for eeprom
+        * write protect and also implies that it is a LOM where GPIOs
+        * are not used to switch power.
+        */ 
+       tg3_get_eeprom_hw_cfg(tp);
+
+       /* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
+        * GPIO1 driven high will bring 5700's external PHY out of reset.
+        * It is also used as eeprom write protect on LOMs.
+        */
+       tp->grc_local_ctrl = GRC_LCLCTRL_INT_ON_ATTN | GRC_LCLCTRL_AUTO_SEEPROM;
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) ||
+           (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT))
+               tp->grc_local_ctrl |= (GRC_LCLCTRL_GPIO_OE1 |
+                                      GRC_LCLCTRL_GPIO_OUTPUT1);
+
        /* Force the chip into D0. */
        err = tg3_set_power_state(tp, 0);
        if (err) {