]> Pileus Git - ~andy/linux/blobdiff - drivers/net/tg3.c
[TG3]: Workaround 5752 A0 chip ID
[~andy/linux] / drivers / net / tg3.c
index f47b30569192e0c7de02946b50cfdd05886d0f9c..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;
 
@@ -1094,7 +1099,7 @@ static int tg3_set_power_state(struct tg3 *tp, int state)
                     CLOCK_CTRL_ALTCLK |
                     CLOCK_CTRL_PWRDOWN_PLL133);
                udelay(40);
-       } else if (!((GET_ASIC_REV(tp->pci_chip_rev_id) == 5750) &&
+       } else if (!((tp->tg3_flags2 & TG3_FLG2_5750_PLUS) &&
                     (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))) {
                u32 newbits1, newbits2;
 
@@ -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);
 
@@ -5237,8 +5243,11 @@ static int tg3_reset_hw(struct tg3 *tp)
                      RDMAC_MODE_LNGREAD_ENAB);
        if (tp->tg3_flags & TG3_FLAG_SPLIT_MODE)
                rdmac_mode |= RDMAC_MODE_SPLIT_ENABLE;
-       if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
-            tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
+
+       /* If statement applies to 5705 and 5750 PCI devices only */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+            tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
+           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
                if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
                    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
                     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
@@ -5249,6 +5258,9 @@ static int tg3_reset_hw(struct tg3 *tp)
                }
        }
 
+       if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+               rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
+
 #if TG3_TSO_SUPPORT != 0
        if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
                rdmac_mode |= (1 << 27);
@@ -5330,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);
 
@@ -5351,8 +5376,10 @@ static int tg3_reset_hw(struct tg3 *tp)
               WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
               WDMAC_MODE_LNGREAD_ENAB);
 
-       if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
-            tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
+       /* If statement applies to 5705 and 5750 PCI devices only */
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+            tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
                if ((tp->tg3_flags & TG3_FLG2_TSO_CAPABLE) &&
                    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
                     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
@@ -7025,7 +7052,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
                tw32(NVRAM_CFG1, nvcfg1);
        }
 
-       if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
                switch (nvcfg1 & NVRAM_CFG1_VENDOR_MASK) {
                        case FLASH_VENDOR_ATMEL_FLASH_BUFFERED:
                                tp->nvram_jedecnum = JEDEC_ATMEL;
@@ -7422,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);
        }
 
@@ -7469,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);
        }
 
@@ -7534,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;
@@ -7561,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;
@@ -7578,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);
@@ -7645,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.
@@ -7673,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;
 
@@ -7747,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 |
@@ -7914,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);
@@ -7928,15 +7972,14 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        tp->pci_hdr_type     = (cacheline_sz_reg >> 16) & 0xff;
        tp->pci_bist         = (cacheline_sz_reg >> 24) & 0xff;
 
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752))
-               tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
-
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
            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) ||
+           (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
+               tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
+
        if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
                tp->tg3_flags2 |= TG3_FLG2_HW_TSO;
 
@@ -8015,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) {
@@ -8462,7 +8525,8 @@ static int __devinit tg3_test_dma(struct tg3 *tp)
                /* DMA read watermark not used on PCIE */
                tp->dma_rwctrl |= 0x00180000;
        } else if (!(tp->tg3_flags & TG3_FLAG_PCIX_MODE)) {
-               if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
+                   GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
                        tp->dma_rwctrl |= 0x003f0000;
                else
                        tp->dma_rwctrl |= 0x003f000f;
@@ -8628,6 +8692,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        case PHY_ID_BCM5704:    return "5704";
        case PHY_ID_BCM5705:    return "5705";
        case PHY_ID_BCM5750:    return "5750";
+       case PHY_ID_BCM5752:    return "5752";
        case PHY_ID_BCM8002:    return "8002/serdes";
        case 0:                 return "serdes";
        default:                return "unknown";