iPXE
Data Structures | Defines | Functions | Variables
tg3_phy.c File Reference
#include <mii.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <byteswap.h>
#include <ipxe/pci.h>
#include "tg3.h"

Go to the source code of this file.

Data Structures

struct  subsys_tbl_ent
struct  tg3_fiber_aneginfo

Defines

#define PHY_BUSY_LOOPS   5000
#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)
#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp)
#define ADVERTISED_Autoneg   (1 << 6)
#define ADVERTISED_Pause   (1 << 13)
#define ADVERTISED_TP   (1 << 7)
#define ADVERTISED_FIBRE   (1 << 10)
#define AUTONEG_ENABLE   0x01
#define ANEG_STATE_UNKNOWN   0
#define ANEG_STATE_AN_ENABLE   1
#define ANEG_STATE_RESTART_INIT   2
#define ANEG_STATE_RESTART   3
#define ANEG_STATE_DISABLE_LINK_OK   4
#define ANEG_STATE_ABILITY_DETECT_INIT   5
#define ANEG_STATE_ABILITY_DETECT   6
#define ANEG_STATE_ACK_DETECT_INIT   7
#define ANEG_STATE_ACK_DETECT   8
#define ANEG_STATE_COMPLETE_ACK_INIT   9
#define ANEG_STATE_COMPLETE_ACK   10
#define ANEG_STATE_IDLE_DETECT_INIT   11
#define ANEG_STATE_IDLE_DETECT   12
#define ANEG_STATE_LINK_OK   13
#define ANEG_STATE_NEXT_PAGE_WAIT_INIT   14
#define ANEG_STATE_NEXT_PAGE_WAIT   15
#define MR_AN_ENABLE   0x00000001
#define MR_RESTART_AN   0x00000002
#define MR_AN_COMPLETE   0x00000004
#define MR_PAGE_RX   0x00000008
#define MR_NP_LOADED   0x00000010
#define MR_TOGGLE_TX   0x00000020
#define MR_LP_ADV_FULL_DUPLEX   0x00000040
#define MR_LP_ADV_HALF_DUPLEX   0x00000080
#define MR_LP_ADV_SYM_PAUSE   0x00000100
#define MR_LP_ADV_ASYM_PAUSE   0x00000200
#define MR_LP_ADV_REMOTE_FAULT1   0x00000400
#define MR_LP_ADV_REMOTE_FAULT2   0x00000800
#define MR_LP_ADV_NEXT_PAGE   0x00001000
#define MR_TOGGLE_RX   0x00002000
#define MR_NP_RX   0x00004000
#define MR_LINK_OK   0x80000000
#define ANEG_CFG_NP   0x00000080
#define ANEG_CFG_ACK   0x00000040
#define ANEG_CFG_RF2   0x00000020
#define ANEG_CFG_RF1   0x00000010
#define ANEG_CFG_PS2   0x00000001
#define ANEG_CFG_PS1   0x00008000
#define ANEG_CFG_HD   0x00004000
#define ANEG_CFG_FD   0x00002000
#define ANEG_CFG_INVAL   0x00001f06
#define ANEG_OK   0
#define ANEG_DONE   1
#define ANEG_TIMER_ENAB   2
#define ANEG_FAILED   -1
#define ANEG_STATE_SETTLE_TIME   10000

Functions

static void tg3_link_report (struct tg3 *tp)
void tg3_mdio_init (struct tg3 *tp)
static int tg3_issue_otp_command (struct tg3 *tp, u32 cmd)
u32 tg3_read_otp_phycfg (struct tg3 *tp)
 int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);
int tg3_readphy (struct tg3 *tp, int reg, u32 *val)
static struct subsys_tbl_enttg3_lookup_by_subsys (struct tg3 *tp)
int tg3_writephy (struct tg3 *tp, int reg, u32 val)
static int tg3_bmcr_reset (struct tg3 *tp)
static int tg3_wait_macro_done (struct tg3 *tp)
static int tg3_phy_write_and_check_testpat (struct tg3 *tp, int *resetp)
static int tg3_phy_reset_chanpat (struct tg3 *tp)
static int tg3_phydsp_write (struct tg3 *tp, u32 reg, u32 val)
static int tg3_phy_auxctl_write (struct tg3 *tp, int reg, u32 set)
static int tg3_phy_reset_5703_4_5 (struct tg3 *tp)
static void tg3_phy_apply_otp (struct tg3 *tp)
static int tg3_phy_auxctl_read (struct tg3 *tp, int reg, u32 *val)
static void tg3_phy_toggle_automdix (struct tg3 *tp, int enable)
static void tg3_phy_set_wirespeed (struct tg3 *tp)
int tg3_phy_reset (struct tg3 *tp)
static int tg3_copper_is_advertising_all (struct tg3 *tp, u32 mask)
static u16 tg3_advert_flowctrl_1000T (u8 flow_ctrl)
static int tg3_phy_autoneg_cfg (struct tg3 *tp, u32 advertise, u32 flowctrl)
static int tg3_init_5401phy_dsp (struct tg3 *tp)
static void tg3_phy_init_link_config (struct tg3 *tp)
int tg3_phy_probe (struct tg3 *tp)
void tg3_poll_link (struct tg3 *tp)
static void tg3_aux_stat_to_speed_duplex (struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
static int tg3_adv_1000T_flowctrl_ok (struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
static u8 tg3_resolve_flowctrl_1000X (u16 lcladv, u16 rmtadv)
static void tg3_setup_flow_control (struct tg3 *tp, u32 lcladv, u32 rmtadv)
static void tg3_phy_copper_begin (struct tg3 *tp)
static int tg3_5700_link_polarity (struct tg3 *tp, u32 speed)
static void tg3_ump_link_report (struct tg3 *tp)
static u16 tg3_advert_flowctrl_1000X (u8 flow_ctrl)
static void tg3_init_bcm8002 (struct tg3 *tp)
static int tg3_setup_fiber_hw_autoneg (struct tg3 *tp, u32 mac_status)
static int tg3_fiber_aneg_smachine (struct tg3 *tp, struct tg3_fiber_aneginfo *ap)
static int fiber_autoneg (struct tg3 *tp, u32 *txflags, u32 *rxflags)
static int tg3_setup_fiber_by_hand (struct tg3 *tp, u32 mac_status)
static int tg3_test_and_report_link_chg (struct tg3 *tp, int curr_link_up)
static void tg3_clear_mac_status (struct tg3 *tp)
static int tg3_setup_fiber_phy (struct tg3 *tp, int force_reset)
static int tg3_setup_fiber_mii_phy (struct tg3 *tp, int force_reset)
static int tg3_setup_copper_phy (struct tg3 *tp, int force_reset)
int tg3_setup_phy (struct tg3 *tp, int force_reset)

Variables

static struct subsys_tbl_ent subsys_id_to_phy_id []

Define Documentation

#define PHY_BUSY_LOOPS   5000

Definition at line 83 of file tg3_phy.c.

Referenced by tg3_readphy(), and tg3_writephy().

#define ADVERTISED_Autoneg   (1 << 6)

Definition at line 858 of file tg3_phy.c.

Referenced by tg3_phy_init_link_config().

#define ADVERTISED_Pause   (1 << 13)
#define ADVERTISED_TP   (1 << 7)

Definition at line 860 of file tg3_phy.c.

Referenced by tg3_phy_init_link_config().

#define ADVERTISED_FIBRE   (1 << 10)

Definition at line 861 of file tg3_phy.c.

Referenced by tg3_phy_init_link_config().

#define AUTONEG_ENABLE   0x01
#define ANEG_STATE_UNKNOWN   0

Definition at line 1292 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define ANEG_STATE_AN_ENABLE   1

Definition at line 1293 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_RESTART_INIT   2

Definition at line 1294 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_RESTART   3

Definition at line 1295 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

Definition at line 1296 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

Definition at line 1297 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_ABILITY_DETECT   6

Definition at line 1298 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

Definition at line 1299 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_ACK_DETECT   8

Definition at line 1300 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

Definition at line 1301 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_COMPLETE_ACK   10

Definition at line 1302 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_IDLE_DETECT_INIT   11

Definition at line 1303 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_IDLE_DETECT   12

Definition at line 1304 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_LINK_OK   13

Definition at line 1305 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

Definition at line 1306 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_STATE_NEXT_PAGE_WAIT   15

Definition at line 1307 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_AN_ENABLE   0x00000001

Definition at line 1310 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define MR_RESTART_AN   0x00000002

Definition at line 1311 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_AN_COMPLETE   0x00000004

Definition at line 1312 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define MR_PAGE_RX   0x00000008

Definition at line 1313 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_NP_LOADED   0x00000010

Definition at line 1314 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_TOGGLE_TX   0x00000020

Definition at line 1315 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_LP_ADV_FULL_DUPLEX   0x00000040

Definition at line 1316 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define MR_LP_ADV_HALF_DUPLEX   0x00000080

Definition at line 1317 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_LP_ADV_SYM_PAUSE   0x00000100

Definition at line 1318 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine(), and tg3_setup_fiber_by_hand().

#define MR_LP_ADV_ASYM_PAUSE   0x00000200

Definition at line 1319 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine(), and tg3_setup_fiber_by_hand().

#define MR_LP_ADV_REMOTE_FAULT1   0x00000400

Definition at line 1320 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_LP_ADV_REMOTE_FAULT2   0x00000800

Definition at line 1321 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_LP_ADV_NEXT_PAGE   0x00001000

Definition at line 1322 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_TOGGLE_RX   0x00002000

Definition at line 1323 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_NP_RX   0x00004000

Definition at line 1324 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define MR_LINK_OK   0x80000000

Definition at line 1326 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define ANEG_CFG_NP   0x00000080

Definition at line 1336 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_ACK   0x00000040

Definition at line 1337 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_RF2   0x00000020

Definition at line 1338 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_RF1   0x00000010

Definition at line 1339 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_PS2   0x00000001

Definition at line 1340 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine(), and tg3_setup_fiber_by_hand().

#define ANEG_CFG_PS1   0x00008000

Definition at line 1341 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine(), and tg3_setup_fiber_by_hand().

#define ANEG_CFG_HD   0x00004000

Definition at line 1342 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_FD   0x00002000

Definition at line 1343 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_CFG_INVAL   0x00001f06

Definition at line 1344 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_OK   0

Definition at line 1347 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_DONE   1

Definition at line 1348 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define ANEG_TIMER_ENAB   2

Definition at line 1349 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().

#define ANEG_FAILED   -1

Definition at line 1350 of file tg3_phy.c.

Referenced by fiber_autoneg(), and tg3_fiber_aneg_smachine().

#define ANEG_STATE_SETTLE_TIME   10000

Definition at line 1352 of file tg3_phy.c.

Referenced by tg3_fiber_aneg_smachine().


Function Documentation

static void tg3_link_report ( struct tg3 tp) [static]

Definition at line 1260 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_flowctrl, tg3_link_config::active_speed, DBGC, DBGP, tg3::dev, DUPLEX_FULL, FLOW_CTRL_RX, FLOW_CTRL_TX, tg3::link_config, netdev_link_ok(), tg3::phy_flags, tg3::setlpicnt, SPEED_100, SPEED_1000, TG3_PHYFLG_EEE_CAP, and tg3_ump_link_report().

Referenced by tg3_phy_reset(), tg3_setup_copper_phy(), tg3_setup_fiber_phy(), and tg3_test_and_report_link_chg().

{       DBGP("%s\n", __func__);

        if (!netdev_link_ok(tp->dev)) {
                DBGC(tp->dev, "Link is down\n");
                tg3_ump_link_report(tp);
        } else {
                DBGC(tp->dev, "Link is up at %d Mbps, %s duplex\n",
                            (tp->link_config.active_speed == SPEED_1000 ?
                             1000 :
                             (tp->link_config.active_speed == SPEED_100 ?
                              100 : 10)),
                            (tp->link_config.active_duplex == DUPLEX_FULL ?
                             "full" : "half"));

                DBGC(tp->dev, "Flow control is %s for TX and %s for RX\n",
                            (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
                            "on" : "off",
                            (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
                            "on" : "off");

                if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
                        DBGC(tp->dev, "EEE is %s\n",
                                    tp->setlpicnt ? "enabled" : "disabled");

                tg3_ump_link_report(tp);
        }
}
void tg3_mdio_init ( struct tg3 tp)
static int tg3_issue_otp_command ( struct tg3 tp,
u32  cmd 
) [static]

Definition at line 32 of file tg3_phy.c.

References DBGP, EBUSY, OTP_CTRL, OTP_CTRL_OTP_CMD_START, OTP_STATUS, OTP_STATUS_CMD_DONE, tr32, tw32, udelay(), and val.

Referenced by tg3_read_otp_phycfg().

{       DBGP("%s\n", __func__);

        int i;
        u32 val;

        tw32(OTP_CTRL, cmd | OTP_CTRL_OTP_CMD_START);
        tw32(OTP_CTRL, cmd);

        /* Wait for up to 1 ms for command to execute. */
        for (i = 0; i < 100; i++) {
                val = tr32(OTP_STATUS);
                if (val & OTP_STATUS_CMD_DONE)
                        break;
                udelay(10);
        }

        return (val & OTP_STATUS_CMD_DONE) ? 0 : -EBUSY;
}
u32 tg3_read_otp_phycfg ( struct tg3 tp)

int tg3_rx_prodring_init(struct tg3 *tp, struct tg3_rx_prodring_set *tpr);

Definition at line 56 of file tg3_phy.c.

References DBGP, OTP_ADDRESS, OTP_ADDRESS_MAGIC1, OTP_ADDRESS_MAGIC2, OTP_CTRL_OTP_CMD_INIT, OTP_CTRL_OTP_CMD_READ, OTP_MODE, OTP_MODE_OTP_THRU_GRC, OTP_READ_DATA, tg3_issue_otp_command(), tr32, and tw32.

Referenced by tg3_get_invariants().

{       DBGP("%s\n", __func__);

        u32 bhalf_otp, thalf_otp;

        tw32(OTP_MODE, OTP_MODE_OTP_THRU_GRC);

        if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_INIT))
                return 0;

        tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC1);

        if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
                return 0;

        thalf_otp = tr32(OTP_READ_DATA);

        tw32(OTP_ADDRESS, OTP_ADDRESS_MAGIC2);

        if (tg3_issue_otp_command(tp, OTP_CTRL_OTP_CMD_READ))
                return 0;

        bhalf_otp = tr32(OTP_READ_DATA);

        return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
}
int tg3_readphy ( struct tg3 tp,
int  reg,
u32 val 
)

Definition at line 85 of file tg3_phy.c.

References DBGP, EBUSY, MAC_MI_COM, MAC_MI_MODE, MAC_MI_MODE_AUTO_POLL, MI_COM_BUSY, MI_COM_CMD_READ, MI_COM_DATA_MASK, MI_COM_PHY_ADDR_MASK, MI_COM_PHY_ADDR_SHIFT, MI_COM_REG_ADDR_MASK, MI_COM_REG_ADDR_SHIFT, MI_COM_START, tg3::mi_mode, tg3::phy_addr, PHY_BUSY_LOOPS, ret, tr32, tw32_f, and udelay().

Referenced by tg3_adv_1000T_flowctrl_ok(), tg3_bmcr_reset(), tg3_copper_is_advertising_all(), tg3_phy_auxctl_read(), tg3_phy_probe(), tg3_phy_reset(), tg3_phy_reset_5703_4_5(), tg3_phy_toggle_automdix(), tg3_phy_write_and_check_testpat(), tg3_reset_hw(), tg3_setup_copper_phy(), tg3_setup_fiber_mii_phy(), tg3_ump_link_report(), and tg3_wait_macro_done().

{       DBGP("%s\n", __func__);

        u32 frame_val;
        unsigned int loops;
        int ret;

        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE,
                     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
                udelay(80);
        }

        *val = 0x0;

        frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
                      MI_COM_PHY_ADDR_MASK);
        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
                      MI_COM_REG_ADDR_MASK);
        frame_val |= (MI_COM_CMD_READ | MI_COM_START);

        tw32_f(MAC_MI_COM, frame_val);

        loops = PHY_BUSY_LOOPS;
        while (loops != 0) {
                udelay(10);
                frame_val = tr32(MAC_MI_COM);

                if ((frame_val & MI_COM_BUSY) == 0) {
                        udelay(5);
                        frame_val = tr32(MAC_MI_COM);
                        break;
                }
                loops -= 1;
        }

        ret = -EBUSY;
        if (loops != 0) {
                *val = frame_val & MI_COM_DATA_MASK;
                ret = 0;
        }

        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE, tp->mi_mode);
                udelay(80);
        }

        return ret;
}
static struct subsys_tbl_ent* tg3_lookup_by_subsys ( struct tg3 tp) [static, read]

Definition at line 204 of file tg3_phy.c.

References ARRAY_SIZE, DBGC, DBGP, tg3::dev, NULL, subsys_tbl_ent::subsys_devid, subsys_tbl_ent::subsys_vendor, tg3::subsystem_device, and tg3::subsystem_vendor.

Referenced by tg3_phy_probe().

{       DBGP("%s\n", __func__);

        int i;

        DBGC(tp->dev, "Matching with: %x:%x\n", tp->subsystem_vendor, tp->subsystem_device);

        for (i = 0; i < (int) ARRAY_SIZE(subsys_id_to_phy_id); i++) {
                if ((subsys_id_to_phy_id[i].subsys_vendor ==
                     tp->subsystem_vendor) &&
                    (subsys_id_to_phy_id[i].subsys_devid ==
                     tp->subsystem_device))
                        return &subsys_id_to_phy_id[i];
        }
        return NULL;
}
int tg3_writephy ( struct tg3 tp,
int  reg,
u32  val 
)

Definition at line 221 of file tg3_phy.c.

References DBGP, EBUSY, MAC_MI_COM, MAC_MI_MODE, MAC_MI_MODE_AUTO_POLL, MI_COM_BUSY, MI_COM_CMD_WRITE, MI_COM_DATA_MASK, MI_COM_PHY_ADDR_MASK, MI_COM_PHY_ADDR_SHIFT, MI_COM_REG_ADDR_MASK, MI_COM_REG_ADDR_SHIFT, MI_COM_START, tg3::mi_mode, MII_TG3_AUX_CTRL, MII_TG3_CTRL, tg3::phy_addr, PHY_BUSY_LOOPS, tg3::phy_flags, ret, TG3_PHYFLG_IS_FET, tr32, tw32_f, and udelay().

Referenced by tg3_adv_1000T_flowctrl_ok(), tg3_bmcr_reset(), tg3_init_bcm8002(), tg3_phy_autoneg_cfg(), tg3_phy_auxctl_read(), tg3_phy_auxctl_write(), tg3_phy_copper_begin(), tg3_phy_probe(), tg3_phy_reset(), tg3_phy_reset_5703_4_5(), tg3_phy_reset_chanpat(), tg3_phy_toggle_automdix(), tg3_phy_write_and_check_testpat(), tg3_phydsp_write(), tg3_reset_hw(), tg3_setup_copper_phy(), and tg3_setup_fiber_mii_phy().

{       DBGP("%s\n", __func__);

        u32 frame_val;
        unsigned int loops;
        int ret;

        if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
            (reg == MII_TG3_CTRL || reg == MII_TG3_AUX_CTRL))
                return 0;

        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE,
                     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
                udelay(80);
        }

        frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
                      MI_COM_PHY_ADDR_MASK);
        frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
                      MI_COM_REG_ADDR_MASK);
        frame_val |= (val & MI_COM_DATA_MASK);
        frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);

        tw32_f(MAC_MI_COM, frame_val);

        loops = PHY_BUSY_LOOPS;
        while (loops != 0) {
                udelay(10);
                frame_val = tr32(MAC_MI_COM);
                if ((frame_val & MI_COM_BUSY) == 0) {
                        udelay(5);
                        frame_val = tr32(MAC_MI_COM);
                        break;
                }
                loops -= 1;
        }

        ret = -EBUSY;
        if (loops != 0)
                ret = 0;

        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE, tp->mi_mode);
                udelay(80);
        }

        return ret;
}
static int tg3_bmcr_reset ( struct tg3 tp) [static]

Definition at line 271 of file tg3_phy.c.

References BMCR_RESET, DBGP, EBUSY, limit, MII_BMCR, tg3_readphy(), tg3_writephy(), and udelay().

Referenced by tg3_phy_reset(), and tg3_phy_reset_5703_4_5().

{       DBGP("%s\n", __func__);

        u32 phy_control;
        int limit, err;

        /* OK, reset it, and poll the BMCR_RESET bit until it
         * clears or we time out.
         */
        phy_control = BMCR_RESET;
        err = tg3_writephy(tp, MII_BMCR, phy_control);
        if (err != 0)
                return -EBUSY;

        limit = 5000;
        while (limit--) {
                err = tg3_readphy(tp, MII_BMCR, &phy_control);
                if (err != 0)
                        return -EBUSY;

                if ((phy_control & BMCR_RESET) == 0) {
                        udelay(40);
                        break;
                }
                udelay(10);
        }
        if (limit < 0)
                return -EBUSY;

        return 0;
}
static int tg3_wait_macro_done ( struct tg3 tp) [static]

Definition at line 303 of file tg3_phy.c.

References DBGP, EBUSY, limit, MII_TG3_DSP_CONTROL, and tg3_readphy().

Referenced by tg3_phy_reset_chanpat(), and tg3_phy_write_and_check_testpat().

{       DBGP("%s\n", __func__);

        int limit = 100;

        while (limit--) {
                u32 tmp32;

                if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
                        if ((tmp32 & 0x1000) == 0)
                                break;
                }
        }
        if (limit < 0)
                return -EBUSY;

        return 0;
}
static int tg3_phy_write_and_check_testpat ( struct tg3 tp,
int *  resetp 
) [static]

Definition at line 322 of file tg3_phy.c.

References DBGP, EBUSY, high, low, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_CONTROL, MII_TG3_DSP_RW_PORT, tg3_readphy(), tg3_wait_macro_done(), and tg3_writephy().

Referenced by tg3_phy_reset_5703_4_5().

{       DBGP("%s\n", __func__);

        static const u32 test_pat[4][6] = {
        { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
        { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
        { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
        { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
        };
        int chan;

        for (chan = 0; chan < 4; chan++) {
                int i;

                tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
                             (chan * 0x2000) | 0x0200);
                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);

                for (i = 0; i < 6; i++)
                        tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
                                     test_pat[chan][i]);

                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
                if (tg3_wait_macro_done(tp)) {
                        *resetp = 1;
                        return -EBUSY;
                }

                tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
                             (chan * 0x2000) | 0x0200);
                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
                if (tg3_wait_macro_done(tp)) {
                        *resetp = 1;
                        return -EBUSY;
                }

                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
                if (tg3_wait_macro_done(tp)) {
                        *resetp = 1;
                        return -EBUSY;
                }

                for (i = 0; i < 6; i += 2) {
                        u32 low, high;

                        if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
                            tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
                            tg3_wait_macro_done(tp)) {
                                *resetp = 1;
                                return -EBUSY;
                        }
                        low &= 0x7fff;
                        high &= 0x000f;
                        if (low != test_pat[chan][i] ||
                            high != test_pat[chan][i+1]) {
                                tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);

                                return -EBUSY;
                        }
                }
        }

        return 0;
}
static int tg3_phy_reset_chanpat ( struct tg3 tp) [static]

Definition at line 389 of file tg3_phy.c.

References DBGP, EBUSY, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_CONTROL, MII_TG3_DSP_RW_PORT, tg3_wait_macro_done(), and tg3_writephy().

Referenced by tg3_phy_reset_5703_4_5().

{       DBGP("%s\n", __func__);

        int chan;

        for (chan = 0; chan < 4; chan++) {
                int i;

                tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
                             (chan * 0x2000) | 0x0200);
                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
                for (i = 0; i < 6; i++)
                        tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
                tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
                if (tg3_wait_macro_done(tp))
                        return -EBUSY;
        }

        return 0;
}
static int tg3_phydsp_write ( struct tg3 tp,
u32  reg,
u32  val 
) [static]

Definition at line 410 of file tg3_phy.c.

References DBGP, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_RW_PORT, and tg3_writephy().

Referenced by tg3_init_5401phy_dsp(), tg3_phy_apply_otp(), tg3_phy_reset(), and tg3_phy_reset_5703_4_5().

{       DBGP("%s\n", __func__);

        int err;

        err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
        if (!err)
                err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);

        return err;
}
static int tg3_phy_auxctl_write ( struct tg3 tp,
int  reg,
u32  set 
) [static]
static int tg3_phy_reset_5703_4_5 ( struct tg3 tp) [static]

Definition at line 440 of file tg3_phy.c.

References BMCR_FULLDPLX, DBGP, EBUSY, MII_BMCR, MII_TG3_CTRL, MII_TG3_CTRL_AS_MASTER, MII_TG3_CTRL_ENABLE_AS_MASTER, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_CONTROL, MII_TG3_EXT_CTRL, tg3_bmcr_reset(), TG3_BMCR_SPEED1000, TG3_PHY_AUXCTL_SMDSP_DISABLE, TG3_PHY_AUXCTL_SMDSP_ENABLE, tg3_phy_reset_chanpat(), tg3_phy_write_and_check_testpat(), tg3_phydsp_write(), tg3_readphy(), and tg3_writephy().

Referenced by tg3_phy_reset().

{       DBGP("%s\n", __func__);

        u32 reg32, phy9_orig;
        int retries, do_phy_reset, err;

        retries = 10;
        do_phy_reset = 1;
        do {
                if (do_phy_reset) {
                        err = tg3_bmcr_reset(tp);
                        if (err)
                                return err;
                        do_phy_reset = 0;
                }

                /* Disable transmitter and interrupt.  */
                if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
                        continue;

                reg32 |= 0x3000;
                tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);

                /* Set full-duplex, 1000 mbps.  */
                tg3_writephy(tp, MII_BMCR,
                             BMCR_FULLDPLX | TG3_BMCR_SPEED1000);

                /* Set to master mode.  */
                if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
                        continue;

                tg3_writephy(tp, MII_TG3_CTRL,
                             (MII_TG3_CTRL_AS_MASTER |
                              MII_TG3_CTRL_ENABLE_AS_MASTER));

                err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
                if (err)
                        return err;

                /* Block the PHY control access.  */
                tg3_phydsp_write(tp, 0x8005, 0x0800);

                err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
                if (!err)
                        break;
        } while (--retries);

        err = tg3_phy_reset_chanpat(tp);
        if (err)
                return err;

        tg3_phydsp_write(tp, 0x8005, 0x0000);

        tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
        tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);

        TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);

        tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);

        if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
                reg32 &= ~0x3000;
                tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
        } else if (!err)
                err = -EBUSY;

        return err;
}
static void tg3_phy_apply_otp ( struct tg3 tp) [static]

Definition at line 509 of file tg3_phy.c.

References DBGP, MII_TG3_DSP_AADJ1CH0, MII_TG3_DSP_AADJ1CH3, MII_TG3_DSP_AADJ1CH3_ADCCKADJ, MII_TG3_DSP_EXP75, MII_TG3_DSP_EXP96, MII_TG3_DSP_EXP97, MII_TG3_DSP_TAP1, MII_TG3_DSP_TAP1_AGCTGT_DFLT, phy, tg3::phy_otp, TG3_OTP_10BTAMP_MASK, TG3_OTP_10BTAMP_SHIFT, TG3_OTP_AGCTGT_MASK, TG3_OTP_AGCTGT_SHIFT, TG3_OTP_HPFFLTR_MASK, TG3_OTP_HPFFLTR_SHIFT, TG3_OTP_HPFOVER_MASK, TG3_OTP_HPFOVER_SHIFT, TG3_OTP_LPFDIS_MASK, TG3_OTP_LPFDIS_SHIFT, TG3_OTP_RCOFF_MASK, TG3_OTP_RCOFF_SHIFT, TG3_OTP_ROFF_MASK, TG3_OTP_ROFF_SHIFT, TG3_OTP_VDAC_MASK, TG3_OTP_VDAC_SHIFT, TG3_PHY_AUXCTL_SMDSP_DISABLE, TG3_PHY_AUXCTL_SMDSP_ENABLE, and tg3_phydsp_write().

Referenced by tg3_phy_reset().

static int tg3_phy_auxctl_read ( struct tg3 tp,
int  reg,
u32 val 
) [static]
static void tg3_phy_toggle_automdix ( struct tg3 tp,
int  enable 
) [static]
static void tg3_phy_set_wirespeed ( struct tg3 tp) [static]
int tg3_phy_reset ( struct tg3 tp)

Definition at line 621 of file tg3_phy.c.

References ASIC_REV_5703, ASIC_REV_5704, ASIC_REV_5705, ASIC_REV_5784, ASIC_REV_5906, CHIPREV_5761_AX, CHIPREV_5784_AX, CPMU_CTRL_GPHY_10MB_RXONLY, CPMU_LSPD_1000MB_MACCLK_12_5, CPMU_LSPD_1000MB_MACCLK_MASK, DBGCP, DBGP, pci_device::dev, tg3::dev, EBUSY, GET_ASIC_REV, GET_CHIP_REV, GRC_MISC_CFG, GRC_MISC_CFG_EPHY_IDDQ, MII_BMSR, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, MII_TG3_DSP_ADDRESS, MII_TG3_DSP_EXP8, MII_TG3_DSP_EXP8_AEDW, MII_TG3_DSP_EXP8_REJ2MHz, MII_TG3_DSP_RW_PORT, MII_TG3_FET_PTEST, MII_TG3_MISC_SHDW, MII_TG3_TEST1, MII_TG3_TEST1_TRIM_EN, netdev_link_down(), out, tg3::pci_chip_rev_id, tg3::pdev, tg3::phy_flags, tg3::phy_id, tg3_bmcr_reset(), TG3_CPMU_CTRL, TG3_CPMU_LSPD_1000MB_CLK, tg3_flag, tg3_link_report(), tg3_phy_apply_otp(), TG3_PHY_AUXCTL_SMDSP_DISABLE, TG3_PHY_AUXCTL_SMDSP_ENABLE, tg3_phy_auxctl_write(), TG3_PHY_ID_BCM5401, TG3_PHY_ID_MASK, tg3_phy_reset_5703_4_5(), tg3_phy_set_wirespeed(), tg3_phy_toggle_automdix(), tg3_phydsp_write(), TG3_PHYFLG_5704_A0_BUG, TG3_PHYFLG_ADC_BUG, TG3_PHYFLG_ADJUST_TRIM, TG3_PHYFLG_BER_BUG, TG3_PHYFLG_JITTER_BUG, TG3_PHYFLG_MII_SERDES, tg3_readphy(), tg3_writephy(), tr32, tw32, tw32_f, udelay(), and val.

Referenced by tg3_phy_probe(), tg3_reset_hw(), tg3_setup_copper_phy(), and tg3_setup_fiber_mii_phy().

{       DBGP("%s\n", __func__);

        u32 val, cpmuctrl;
        int err;

        DBGCP(&tp->pdev->dev, "%s\n", __func__);

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                val = tr32(GRC_MISC_CFG);
                tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
                udelay(40);
        }
        err  = tg3_readphy(tp, MII_BMSR, &val);
        err |= tg3_readphy(tp, MII_BMSR, &val);
        if (err != 0)
                return -EBUSY;

        netdev_link_down(tp->dev);
        tg3_link_report(tp);

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
                err = tg3_phy_reset_5703_4_5(tp);
                if (err)
                        return err;
                goto out;
        }

        cpmuctrl = 0;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
            GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
                cpmuctrl = tr32(TG3_CPMU_CTRL);
                if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
                        tw32(TG3_CPMU_CTRL,
                             cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
        }

        err = tg3_bmcr_reset(tp);
        if (err)
                return err;

        if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
                val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
                tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);

                tw32(TG3_CPMU_CTRL, cpmuctrl);
        }

        if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
            GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
                val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
                if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
                    CPMU_LSPD_1000MB_MACCLK_12_5) {
                        val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
                        udelay(40);
                        tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
                }
        }

        if (tg3_flag(tp, 5717_PLUS) &&
            (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
                return 0;

        tg3_phy_apply_otp(tp);

out:
        if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
            !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
                tg3_phydsp_write(tp, 0x201f, 0x2aaa);
                tg3_phydsp_write(tp, 0x000a, 0x0323);
                TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
        }

        if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
                tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
                tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
        }

        if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
                if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
                        tg3_phydsp_write(tp, 0x000a, 0x310b);
                        tg3_phydsp_write(tp, 0x201f, 0x9506);
                        tg3_phydsp_write(tp, 0x401f, 0x14e2);
                        TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
                }
        } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
                if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
                        tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
                        if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
                                tg3_writephy(tp, MII_TG3_TEST1,
                                             MII_TG3_TEST1_TRIM_EN | 0x4);
                        } else
                                tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);

                        TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
                }
        }

        if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
                /* Cannot do read-modify-write on 5401 */
                tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
        }

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
                /* adjust output voltage */
                tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
        }

        tg3_phy_toggle_automdix(tp, 1);
        tg3_phy_set_wirespeed(tp);
        return 0;
}
static int tg3_copper_is_advertising_all ( struct tg3 tp,
u32  mask 
) [static]

Definition at line 737 of file tg3_phy.c.

References ADVERTISE_1000FULL, ADVERTISE_1000HALF, ADVERTISE_100FULL, ADVERTISE_100HALF, ADVERTISE_10FULL, ADVERTISE_10HALF, ADVERTISED_1000baseT_Full, ADVERTISED_1000baseT_Half, ADVERTISED_100baseT_Full, ADVERTISED_100baseT_Half, ADVERTISED_10baseT_Full, ADVERTISED_10baseT_Half, DBGP, MII_ADVERTISE, MII_TG3_CTRL, tg3::phy_flags, TG3_PHYFLG_10_100_ONLY, and tg3_readphy().

Referenced by tg3_phy_probe(), and tg3_setup_copper_phy().

{       DBGP("%s\n", __func__);

        u32 adv_reg, all_mask = 0;

        if (mask & ADVERTISED_10baseT_Half)
                all_mask |= ADVERTISE_10HALF;
        if (mask & ADVERTISED_10baseT_Full)
                all_mask |= ADVERTISE_10FULL;
        if (mask & ADVERTISED_100baseT_Half)
                all_mask |= ADVERTISE_100HALF;
        if (mask & ADVERTISED_100baseT_Full)
                all_mask |= ADVERTISE_100FULL;

        if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
                return 0;

        if ((adv_reg & all_mask) != all_mask)
                return 0;
        if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
                u32 tg3_ctrl;

                all_mask = 0;
                if (mask & ADVERTISED_1000baseT_Half)
                        all_mask |= ADVERTISE_1000HALF;
                if (mask & ADVERTISED_1000baseT_Full)
                        all_mask |= ADVERTISE_1000FULL;

                if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
                        return 0;

                if ((tg3_ctrl & all_mask) != all_mask)
                        return 0;
        }
        return 1;
}
static u16 tg3_advert_flowctrl_1000T ( u8  flow_ctrl) [static]

Definition at line 774 of file tg3_phy.c.

References ADVERTISE_PAUSE_ASYM, ADVERTISE_PAUSE_CAP, DBGP, FLOW_CTRL_RX, and FLOW_CTRL_TX.

Referenced by tg3_adv_1000T_flowctrl_ok(), and tg3_phy_autoneg_cfg().

{       DBGP("%s\n", __func__);

        u16 miireg;

        if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
                miireg = ADVERTISE_PAUSE_CAP;
        else if (flow_ctrl & FLOW_CTRL_TX)
                miireg = ADVERTISE_PAUSE_ASYM;
        else if (flow_ctrl & FLOW_CTRL_RX)
                miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
        else
                miireg = 0;

        return miireg;
}
static int tg3_phy_autoneg_cfg ( struct tg3 tp,
u32  advertise,
u32  flowctrl 
) [static]

Definition at line 791 of file tg3_phy.c.

References __unused, ADVERTISE_100FULL, ADVERTISE_100HALF, ADVERTISE_10FULL, ADVERTISE_10HALF, ADVERTISE_CSMA, ADVERTISED_1000baseT_Full, ADVERTISED_1000baseT_Half, ADVERTISED_100baseT_Full, ADVERTISED_100baseT_Half, ADVERTISED_10baseT_Full, ADVERTISED_10baseT_Half, CHIPREV_ID_5701_A0, CHIPREV_ID_5701_B0, DBGP, done, MII_ADVERTISE, MII_TG3_CTRL, MII_TG3_CTRL_ADV_1000_FULL, MII_TG3_CTRL_ADV_1000_HALF, MII_TG3_CTRL_AS_MASTER, MII_TG3_CTRL_ENABLE_AS_MASTER, tg3::pci_chip_rev_id, tg3::phy_flags, tg3_advert_flowctrl_1000T(), TG3_PHYFLG_10_100_ONLY, TG3_PHYFLG_EEE_CAP, tg3_writephy(), and val.

Referenced by tg3_phy_copper_begin(), and tg3_phy_probe().

{       DBGP("%s\n", __func__);

        int err = 0;
        u32 val __unused, new_adv;

        new_adv = ADVERTISE_CSMA;
        if (advertise & ADVERTISED_10baseT_Half)
                new_adv |= ADVERTISE_10HALF;
        if (advertise & ADVERTISED_10baseT_Full)
                new_adv |= ADVERTISE_10FULL;
        if (advertise & ADVERTISED_100baseT_Half)
                new_adv |= ADVERTISE_100HALF;
        if (advertise & ADVERTISED_100baseT_Full)
                new_adv |= ADVERTISE_100FULL;

        new_adv |= tg3_advert_flowctrl_1000T(flowctrl);

        err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
        if (err)
                goto done;

        if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
                goto done;

        new_adv = 0;
        if (advertise & ADVERTISED_1000baseT_Half)
                new_adv |= MII_TG3_CTRL_ADV_1000_HALF;
        if (advertise & ADVERTISED_1000baseT_Full)
                new_adv |= MII_TG3_CTRL_ADV_1000_FULL;

        if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
            tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
                new_adv |= (MII_TG3_CTRL_AS_MASTER |
                            MII_TG3_CTRL_ENABLE_AS_MASTER);

        err = tg3_writephy(tp, MII_TG3_CTRL, new_adv);
        if (err)
                goto done;

        if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
                goto done;

done:
        return err;
}
static int tg3_init_5401phy_dsp ( struct tg3 tp) [static]

Definition at line 838 of file tg3_phy.c.

References DBGP, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, tg3_phy_auxctl_write(), tg3_phydsp_write(), and udelay().

Referenced by tg3_phy_probe(), and tg3_setup_copper_phy().

{       DBGP("%s\n", __func__);

        int err;

        /* Turn off tap power management. */
        /* Set Extended packet length bit */
        err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);

        err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
        err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
        err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
        err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
        err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);

        udelay(40);

        return err;
}
static void tg3_phy_init_link_config ( struct tg3 tp) [static]

Definition at line 865 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_speed, ADVERTISED_1000baseT_Full, ADVERTISED_1000baseT_Half, ADVERTISED_100baseT_Full, ADVERTISED_100baseT_Half, ADVERTISED_10baseT_Full, ADVERTISED_10baseT_Half, ADVERTISED_Autoneg, ADVERTISED_FIBRE, ADVERTISED_Pause, ADVERTISED_TP, tg3_link_config::advertising, tg3_link_config::autoneg, AUTONEG_ENABLE, AUTONEG_INVALID, DBGP, tg3_link_config::duplex, DUPLEX_INVALID, tg3::link_config, tg3_link_config::orig_autoneg, tg3_link_config::orig_duplex, tg3_link_config::orig_speed, tg3::phy_flags, tg3_link_config::speed, SPEED_INVALID, TG3_PHYFLG_10_100_ONLY, and TG3_PHYFLG_ANY_SERDES.

Referenced by tg3_phy_probe().

int tg3_phy_probe ( struct tg3 tp)

Definition at line 895 of file tg3_phy.c.

References ADVERTISED_1000baseT_Full, ADVERTISED_1000baseT_Half, ADVERTISED_100baseT_Full, ADVERTISED_100baseT_Half, ADVERTISED_10baseT_Full, ADVERTISED_10baseT_Half, tg3_link_config::advertising, ASIC_REV_57765, BMCR_ANENABLE, BMCR_ANRESTART, BMSR_LSTATUS, CHIPREV_ID_5717_A0, CHIPREV_ID_57765_A0, DBGC, DBGP, pci_device::dev, pci_device::device, ENODEV, FLOW_CTRL_RX, FLOW_CTRL_TX, tg3_link_config::flowctrl, GET_ASIC_REV, tg3::link_config, MII_BMCR, MII_BMSR, MII_PHYSID1, MII_PHYSID2, tg3::pci_chip_rev_id, tg3::pdev, tg3::phy_flags, subsys_tbl_ent::phy_id, tg3::phy_id, tg3_copper_is_advertising_all(), tg3_flag, tg3_flag_set, tg3_init_5401phy_dsp(), TG3_KNOWN_PHY_ID, tg3_lookup_by_subsys(), tg3_phy_autoneg_cfg(), TG3_PHY_ID_BCM5401, TG3_PHY_ID_BCM8002, TG3_PHY_ID_INVALID, TG3_PHY_ID_MASK, tg3_phy_init_link_config(), tg3_phy_reset(), tg3_phy_set_wirespeed(), TG3_PHYFLG_ANY_SERDES, TG3_PHYFLG_EEE_CAP, TG3_PHYFLG_PHY_SERDES, tg3_readphy(), tg3_writephy(), and TG3PCI_DEVICE_TIGON3_5718.

Referenced by tg3_get_invariants().

{       DBGP("%s\n", __func__);

        u32 hw_phy_id_1, hw_phy_id_2;
        u32 hw_phy_id, hw_phy_id_masked;
        int err;

        /* flow control autonegotiation is default behavior */
        tg3_flag_set(tp, PAUSE_AUTONEG);
        tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;

        /* Reading the PHY ID register can conflict with ASF
         * firmware access to the PHY hardware.
         */
        err = 0;
        if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)) {
                hw_phy_id = hw_phy_id_masked = TG3_PHY_ID_INVALID;
        } else {
                /* Now read the physical PHY_ID from the chip and verify
                 * that it is sane.  If it doesn't look good, we fall back
                 * to either the hard-coded table based PHY_ID and failing
                 * that the value found in the eeprom area.
                 */
                err |= tg3_readphy(tp, MII_PHYSID1, &hw_phy_id_1);
                err |= tg3_readphy(tp, MII_PHYSID2, &hw_phy_id_2);

                hw_phy_id  = (hw_phy_id_1 & 0xffff) << 10;
                hw_phy_id |= (hw_phy_id_2 & 0xfc00) << 16;
                hw_phy_id |= (hw_phy_id_2 & 0x03ff) <<  0;

                hw_phy_id_masked = hw_phy_id & TG3_PHY_ID_MASK;
        }

        if (!err && TG3_KNOWN_PHY_ID(hw_phy_id_masked)) {
                tp->phy_id = hw_phy_id;
                if (hw_phy_id_masked == TG3_PHY_ID_BCM8002)
                        tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
                else
                        tp->phy_flags &= ~TG3_PHYFLG_PHY_SERDES;
        } else {
                if (tp->phy_id != TG3_PHY_ID_INVALID) {
                        /* Do nothing, phy ID already set up in
                         * tg3_get_eeprom_hw_cfg().
                         */
                } else {
                        struct subsys_tbl_ent *p;

                        /* No eeprom signature?  Try the hardcoded
                         * subsys device table.
                         */
                        p = tg3_lookup_by_subsys(tp);
                        if (!p) {
                                DBGC(&tp->pdev->dev, "lookup by subsys failed\n");
                                return -ENODEV;
                        }

                        tp->phy_id = p->phy_id;
                        if (!tp->phy_id ||
                            tp->phy_id == TG3_PHY_ID_BCM8002)
                                tp->phy_flags |= TG3_PHYFLG_PHY_SERDES;
                }
        }

        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
            ((tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 &&
              tp->pci_chip_rev_id != CHIPREV_ID_5717_A0) ||
             (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765 &&
              tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
                tp->phy_flags |= TG3_PHYFLG_EEE_CAP;

        tg3_phy_init_link_config(tp);

        if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
            !tg3_flag(tp, ENABLE_APE) &&
            !tg3_flag(tp, ENABLE_ASF)) {
                u32 bmsr;
                u32 mask;

                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    (bmsr & BMSR_LSTATUS))
                        goto skip_phy_reset;

                err = tg3_phy_reset(tp);
                if (err)
                        return err;

                tg3_phy_set_wirespeed(tp);

                mask = (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
                        ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
                        ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full);
                if (!tg3_copper_is_advertising_all(tp, mask)) {
                        tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
                                            tp->link_config.flowctrl);

                        tg3_writephy(tp, MII_BMCR,
                                     BMCR_ANENABLE | BMCR_ANRESTART);
                }
        }

skip_phy_reset:
        if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
                err = tg3_init_5401phy_dsp(tp);
                if (err)
                        return err;

                err = tg3_init_5401phy_dsp(tp);
        }

        return err;
}
void tg3_poll_link ( struct tg3 tp)

Definition at line 1008 of file tg3_phy.c.

References DBGC, DBGP, tg3::dev, tg3::hw_status, SD_STATUS_LINK_CHG, tg3_hw_status::status, and tg3_setup_phy().

Referenced by tg3_poll().

{       DBGP("%s\n", __func__);

        if (tp->hw_status->status & SD_STATUS_LINK_CHG) {
                DBGC(tp->dev,"link_changed\n");
                tp->hw_status->status &= ~SD_STATUS_LINK_CHG;
                tg3_setup_phy(tp, 0);
        }
}
static void tg3_aux_stat_to_speed_duplex ( struct tg3 tp,
u32  val,
u16 speed,
u8 duplex 
) [static]
static int tg3_adv_1000T_flowctrl_ok ( struct tg3 tp,
u32 lcladv,
u32 rmtadv 
) [static]

Definition at line 1066 of file tg3_phy.c.

References tg3_link_config::active_duplex, ADVERTISE_PAUSE_ASYM, ADVERTISE_PAUSE_CAP, DBGP, DUPLEX_FULL, tg3_link_config::flowctrl, tg3::link_config, MII_ADVERTISE, MII_LPA, tg3_advert_flowctrl_1000T(), tg3_flag, tg3_readphy(), and tg3_writephy().

Referenced by tg3_setup_copper_phy().

{       DBGP("%s\n", __func__);

        u32 curadv, reqadv;

        if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
                return 1;

        curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
        reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);

        if (tp->link_config.active_duplex == DUPLEX_FULL) {
                if (curadv != reqadv)
                        return 0;

                if (tg3_flag(tp, PAUSE_AUTONEG))
                        tg3_readphy(tp, MII_LPA, rmtadv);
        } else {
                /* Reprogram the advertisement register, even if it
                 * does not affect the current link.  If the link
                 * gets renegotiated in the future, we can save an
                 * additional renegotiation cycle by advertising
                 * it correctly in the first place.
                 */
                if (curadv != reqadv) {
                        *lcladv &= ~(ADVERTISE_PAUSE_CAP |
                                     ADVERTISE_PAUSE_ASYM);
                        tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
                }
        }

        return 1;
}
static u8 tg3_resolve_flowctrl_1000X ( u16  lcladv,
u16  rmtadv 
) [static]

Definition at line 1100 of file tg3_phy.c.

References ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, DBGP, FLOW_CTRL_RX, FLOW_CTRL_TX, LPA_1000XPAUSE, and LPA_1000XPAUSE_ASYM.

Referenced by tg3_setup_flow_control().

{       DBGP("%s\n", __func__);

        u8 cap = 0;

        if (lcladv & ADVERTISE_1000XPAUSE) {
                if (lcladv & ADVERTISE_1000XPSE_ASYM) {
                        if (rmtadv & LPA_1000XPAUSE)
                                cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
                        else if (rmtadv & LPA_1000XPAUSE_ASYM)
                                cap = FLOW_CTRL_RX;
                } else {
                        if (rmtadv & LPA_1000XPAUSE)
                                cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
                }
        } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
                if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
                        cap = FLOW_CTRL_TX;
        }

        return cap;
}
static void tg3_setup_flow_control ( struct tg3 tp,
u32  lcladv,
u32  rmtadv 
) [static]
static void tg3_phy_copper_begin ( struct tg3 tp) [static]
static int tg3_5700_link_polarity ( struct tg3 tp,
u32  speed 
) [static]

Definition at line 1196 of file tg3_phy.c.

References DBGP, tg3::led_ctrl, LED_CTRL_MODE_PHY_2, tg3::phy_id, SPEED_10, TG3_PHY_ID_BCM5411, and TG3_PHY_ID_MASK.

Referenced by tg3_setup_copper_phy().

{       DBGP("%s\n", __func__);

        if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
                return 1;
        else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
                if (speed != SPEED_10)
                        return 1;
        } else if (speed == SPEED_10)
                return 1;

        return 0;
}
static void tg3_ump_link_report ( struct tg3 tp) [static]

Definition at line 1212 of file tg3_phy.c.

References DBGP, FWCMD_NICDRV_LINK_UPDATE, MII_ADVERTISE, MII_BMCR, MII_BMSR, MII_CTRL1000, MII_LPA, MII_PHYADDR, MII_STAT1000, NIC_SRAM_FW_CMD_DATA_MBOX, NIC_SRAM_FW_CMD_LEN_MBOX, NIC_SRAM_FW_CMD_MBOX, tg3::phy_flags, reg, tg3_flag, tg3_generate_fw_event(), TG3_PHYFLG_MII_SERDES, tg3_readphy(), tg3_wait_for_event_ack(), tg3_write_mem(), and val.

Referenced by tg3_link_report().

{       DBGP("%s\n", __func__);

        u32 reg;
        u32 val;

        if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
                return;

        tg3_wait_for_event_ack(tp);

        tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);

        tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);

        val = 0;
        if (!tg3_readphy(tp, MII_BMCR, &reg))
                val = reg << 16;
        if (!tg3_readphy(tp, MII_BMSR, &reg))
                val |= (reg & 0xffff);
        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);

        val = 0;
        if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
                val = reg << 16;
        if (!tg3_readphy(tp, MII_LPA, &reg))
                val |= (reg & 0xffff);
        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);

        val = 0;
        if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
                if (!tg3_readphy(tp, MII_CTRL1000, &reg))
                        val = reg << 16;
                if (!tg3_readphy(tp, MII_STAT1000, &reg))
                        val |= (reg & 0xffff);
        }
        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);

        if (!tg3_readphy(tp, MII_PHYADDR, &reg))
                val = reg << 16;
        else
                val = 0;
        tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);

        tg3_generate_fw_event(tp);
}
static u16 tg3_advert_flowctrl_1000X ( u8  flow_ctrl) [static]

Definition at line 1354 of file tg3_phy.c.

References ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, FLOW_CTRL_RX, and FLOW_CTRL_TX.

Referenced by tg3_fiber_aneg_smachine(), tg3_setup_fiber_hw_autoneg(), and tg3_setup_fiber_mii_phy().

{
        u16 miireg;

        if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
                miireg = ADVERTISE_1000XPAUSE;
        else if (flow_ctrl & FLOW_CTRL_TX)
                miireg = ADVERTISE_1000XPSE_ASYM;
        else if (flow_ctrl & FLOW_CTRL_RX)
                miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
        else
                miireg = 0;

        return miireg;
}
static void tg3_init_bcm8002 ( struct tg3 tp) [static]

Definition at line 1370 of file tg3_phy.c.

References BMCR_RESET, MAC_STATUS, MAC_STATUS_PCS_SYNCED, MII_BMCR, tg3_flag, tg3_writephy(), tr32, and udelay().

Referenced by tg3_setup_fiber_phy().

{
        u32 mac_status = tr32(MAC_STATUS);
        int i;

        /* Reset when initting first time or we have a link. */
        if (tg3_flag(tp, INIT_COMPLETE) &&
            !(mac_status & MAC_STATUS_PCS_SYNCED))
                return;

        /* Set PLL lock range. */
        tg3_writephy(tp, 0x16, 0x8007);

        /* SW reset */
        tg3_writephy(tp, MII_BMCR, BMCR_RESET);

        /* Wait for reset to complete. */
        /* XXX schedule_timeout() ... */
        for (i = 0; i < 500; i++)
                udelay(10);

        /* Config mode; select PMA/Ch 1 regs. */
        tg3_writephy(tp, 0x10, 0x8411);

        /* Enable auto-lock and comdet, select txclk for tx. */
        tg3_writephy(tp, 0x11, 0x0a10);

        tg3_writephy(tp, 0x18, 0x00a0);
        tg3_writephy(tp, 0x16, 0x41ff);

        /* Assert and deassert POR. */
        tg3_writephy(tp, 0x13, 0x0400);
        udelay(40);
        tg3_writephy(tp, 0x13, 0x0000);

        tg3_writephy(tp, 0x11, 0x0a50);
        udelay(40);
        tg3_writephy(tp, 0x11, 0x0a10);

        /* Wait for signal to stabilize */
        /* XXX schedule_timeout() ... */
        for (i = 0; i < 15000; i++)
                udelay(10);

        /* Deselect the channel register so we can read the PHYID
         * later.
         */
        tg3_writephy(tp, 0x10, 0x8011);
}
static int tg3_setup_fiber_hw_autoneg ( struct tg3 tp,
u32  mac_status 
) [static]

Definition at line 1420 of file tg3_phy.c.

References ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, tg3_link_config::autoneg, AUTONEG_ENABLE, CHIPREV_ID_5704_A0, CHIPREV_ID_5704_A1, DUAL_MAC_CTRL_ID, flowctrl, tg3_link_config::flowctrl, tg3::link_config, LPA_1000XPAUSE, LPA_1000XPAUSE_ASYM, MAC_SERDES_CFG, MAC_STATUS, MAC_STATUS_PCS_SYNCED, MAC_STATUS_RCVD_CFG, MAC_STATUS_SIGNAL_DET, mii_adv_to_ethtool_adv_x(), out, tg3::pci_chip_rev_id, tg3::phy_flags, tg3_link_config::rmt_adv, SERDES_AN_TIMEOUT_5704S, tg3::serdes_counter, SERDES_PARALLEL_DET_TIMEOUT, SG_DIG_ASYM_PAUSE, SG_DIG_AUTONEG_COMPLETE, SG_DIG_COMMON_SETUP, SG_DIG_CTRL, SG_DIG_PARTNER_ASYM_PAUSE, SG_DIG_PARTNER_PAUSE_CAPABLE, SG_DIG_PAUSE_CAP, SG_DIG_SOFT_RESET, SG_DIG_STATUS, SG_DIG_USING_HW_AUTONEG, tg3_advert_flowctrl_1000X(), TG3_PHYFLG_PARALLEL_DETECT, tg3_setup_flow_control(), TG3PCI_DUAL_MAC_CTRL, tr32, tw32_f, udelay(), and val.

Referenced by tg3_setup_fiber_phy().

{
        u16 flowctrl;
        int current_link_up;
        u32 sg_dig_ctrl, sg_dig_status;
        u32 serdes_cfg, expected_sg_dig_ctrl;
        int workaround, port_a;

        serdes_cfg = 0;
        expected_sg_dig_ctrl = 0;
        workaround = 0;
        port_a = 1;
        current_link_up = 0;

        if (tp->pci_chip_rev_id != CHIPREV_ID_5704_A0 &&
            tp->pci_chip_rev_id != CHIPREV_ID_5704_A1) {
                workaround = 1;
                if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
                        port_a = 0;

                /* preserve bits 0-11,13,14 for signal pre-emphasis */
                /* preserve bits 20-23 for voltage regulator */
                serdes_cfg = tr32(MAC_SERDES_CFG) & 0x00f06fff;
        }

        sg_dig_ctrl = tr32(SG_DIG_CTRL);

        if (tp->link_config.autoneg != AUTONEG_ENABLE) {
                if (sg_dig_ctrl & SG_DIG_USING_HW_AUTONEG) {
                        if (workaround) {
                                u32 val = serdes_cfg;

                                if (port_a)
                                        val |= 0xc010000;
                                else
                                        val |= 0x4010000;
                                tw32_f(MAC_SERDES_CFG, val);
                        }

                        tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
                }
                if (mac_status & MAC_STATUS_PCS_SYNCED) {
                        tg3_setup_flow_control(tp, 0, 0);
                        current_link_up = 1;
                }
                goto out;
        }

        /* Want auto-negotiation.  */
        expected_sg_dig_ctrl = SG_DIG_USING_HW_AUTONEG | SG_DIG_COMMON_SETUP;

        flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
        if (flowctrl & ADVERTISE_1000XPAUSE)
                expected_sg_dig_ctrl |= SG_DIG_PAUSE_CAP;
        if (flowctrl & ADVERTISE_1000XPSE_ASYM)
                expected_sg_dig_ctrl |= SG_DIG_ASYM_PAUSE;

        if (sg_dig_ctrl != expected_sg_dig_ctrl) {
                if ((tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT) &&
                    tp->serdes_counter &&
                    ((mac_status & (MAC_STATUS_PCS_SYNCED |
                                    MAC_STATUS_RCVD_CFG)) ==
                     MAC_STATUS_PCS_SYNCED)) {
                        tp->serdes_counter--;
                        current_link_up = 1;
                        goto out;
                }
restart_autoneg:
                if (workaround)
                        tw32_f(MAC_SERDES_CFG, serdes_cfg | 0xc011000);
                tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl | SG_DIG_SOFT_RESET);
                udelay(5);
                tw32_f(SG_DIG_CTRL, expected_sg_dig_ctrl);

                tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
                tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
        } else if (mac_status & (MAC_STATUS_PCS_SYNCED |
                                 MAC_STATUS_SIGNAL_DET)) {
                sg_dig_status = tr32(SG_DIG_STATUS);
                mac_status = tr32(MAC_STATUS);

                if ((sg_dig_status & SG_DIG_AUTONEG_COMPLETE) &&
                    (mac_status & MAC_STATUS_PCS_SYNCED)) {
                        u32 local_adv = 0, remote_adv = 0;

                        if (sg_dig_ctrl & SG_DIG_PAUSE_CAP)
                                local_adv |= ADVERTISE_1000XPAUSE;
                        if (sg_dig_ctrl & SG_DIG_ASYM_PAUSE)
                                local_adv |= ADVERTISE_1000XPSE_ASYM;

                        if (sg_dig_status & SG_DIG_PARTNER_PAUSE_CAPABLE)
                                remote_adv |= LPA_1000XPAUSE;
                        if (sg_dig_status & SG_DIG_PARTNER_ASYM_PAUSE)
                                remote_adv |= LPA_1000XPAUSE_ASYM;

                        tp->link_config.rmt_adv =
                                           mii_adv_to_ethtool_adv_x(remote_adv);

                        tg3_setup_flow_control(tp, local_adv, remote_adv);
                        current_link_up = 1;
                        tp->serdes_counter = 0;
                        tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                } else if (!(sg_dig_status & SG_DIG_AUTONEG_COMPLETE)) {
                        if (tp->serdes_counter)
                                tp->serdes_counter--;
                        else {
                                if (workaround) {
                                        u32 val = serdes_cfg;

                                        if (port_a)
                                                val |= 0xc010000;
                                        else
                                                val |= 0x4010000;

                                        tw32_f(MAC_SERDES_CFG, val);
                                }

                                tw32_f(SG_DIG_CTRL, SG_DIG_COMMON_SETUP);
                                udelay(40);

                                /* Link parallel detection - link is up */
                                /* only if we have PCS_SYNC and not */
                                /* receiving config code words */
                                mac_status = tr32(MAC_STATUS);
                                if ((mac_status & MAC_STATUS_PCS_SYNCED) &&
                                    !(mac_status & MAC_STATUS_RCVD_CFG)) {
                                        tg3_setup_flow_control(tp, 0, 0);
                                        current_link_up = 1;
                                        tp->phy_flags |=
                                                TG3_PHYFLG_PARALLEL_DETECT;
                                        tp->serdes_counter =
                                                SERDES_PARALLEL_DET_TIMEOUT;
                                } else
                                        goto restart_autoneg;
                        }
                }
        } else {
                tp->serdes_counter = SERDES_AN_TIMEOUT_5704S;
                tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
        }

out:
        return current_link_up;
}
static int tg3_fiber_aneg_smachine ( struct tg3 tp,
struct tg3_fiber_aneginfo ap 
) [static]

Definition at line 1565 of file tg3_phy.c.

References tg3_fiber_aneginfo::ability_match, tg3_fiber_aneginfo::ability_match_cfg, tg3_fiber_aneginfo::ability_match_count, tg3_fiber_aneginfo::ack_match, ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, ANEG_CFG_ACK, ANEG_CFG_FD, ANEG_CFG_HD, ANEG_CFG_INVAL, ANEG_CFG_NP, ANEG_CFG_PS1, ANEG_CFG_PS2, ANEG_CFG_RF1, ANEG_CFG_RF2, ANEG_DONE, ANEG_FAILED, ANEG_OK, ANEG_STATE_ABILITY_DETECT, ANEG_STATE_ABILITY_DETECT_INIT, ANEG_STATE_ACK_DETECT, ANEG_STATE_ACK_DETECT_INIT, ANEG_STATE_AN_ENABLE, ANEG_STATE_COMPLETE_ACK, ANEG_STATE_COMPLETE_ACK_INIT, ANEG_STATE_DISABLE_LINK_OK, ANEG_STATE_IDLE_DETECT, ANEG_STATE_IDLE_DETECT_INIT, ANEG_STATE_LINK_OK, ANEG_STATE_NEXT_PAGE_WAIT, ANEG_STATE_NEXT_PAGE_WAIT_INIT, ANEG_STATE_RESTART, ANEG_STATE_RESTART_INIT, ANEG_STATE_SETTLE_TIME, ANEG_STATE_UNKNOWN, ANEG_TIMER_ENAB, tg3_fiber_aneginfo::cur_time, tg3_fiber_aneginfo::flags, flowctrl, tg3_link_config::flowctrl, tg3_fiber_aneginfo::idle_match, tg3::link_config, tg3_fiber_aneginfo::link_time, MAC_MODE, tg3::mac_mode, MAC_MODE_SEND_CONFIGS, MAC_RX_AUTO_NEG, MAC_STATUS, MAC_STATUS_RCVD_CFG, MAC_TX_AUTO_NEG, MR_AN_COMPLETE, MR_AN_ENABLE, MR_LINK_OK, MR_LP_ADV_ASYM_PAUSE, MR_LP_ADV_FULL_DUPLEX, MR_LP_ADV_HALF_DUPLEX, MR_LP_ADV_NEXT_PAGE, MR_LP_ADV_REMOTE_FAULT1, MR_LP_ADV_REMOTE_FAULT2, MR_LP_ADV_SYM_PAUSE, MR_NP_LOADED, MR_NP_RX, MR_PAGE_RX, MR_RESTART_AN, MR_TOGGLE_RX, MR_TOGGLE_TX, ret, tg3_fiber_aneginfo::rxconfig, tg3_fiber_aneginfo::state, tg3_advert_flowctrl_1000X(), tr32, tw32, tw32_f, tg3_fiber_aneginfo::txconfig, and udelay().

Referenced by fiber_autoneg().

{
        u16 flowctrl;
        unsigned long delta;
        u32 rx_cfg_reg;
        int ret;

        if (ap->state == ANEG_STATE_UNKNOWN) {
                ap->rxconfig = 0;
                ap->link_time = 0;
                ap->cur_time = 0;
                ap->ability_match_cfg = 0;
                ap->ability_match_count = 0;
                ap->ability_match = 0;
                ap->idle_match = 0;
                ap->ack_match = 0;
        }
        ap->cur_time++;

        if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
                rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);

                if (rx_cfg_reg != ap->ability_match_cfg) {
                        ap->ability_match_cfg = rx_cfg_reg;
                        ap->ability_match = 0;
                        ap->ability_match_count = 0;
                } else {
                        if (++ap->ability_match_count > 1) {
                                ap->ability_match = 1;
                                ap->ability_match_cfg = rx_cfg_reg;
                        }
                }
                if (rx_cfg_reg & ANEG_CFG_ACK)
                        ap->ack_match = 1;
                else
                        ap->ack_match = 0;

                ap->idle_match = 0;
        } else {
                ap->idle_match = 1;
                ap->ability_match_cfg = 0;
                ap->ability_match_count = 0;
                ap->ability_match = 0;
                ap->ack_match = 0;

                rx_cfg_reg = 0;
        }

        ap->rxconfig = rx_cfg_reg;
        ret = ANEG_OK;

        switch (ap->state) {
        case ANEG_STATE_UNKNOWN:
                if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
                        ap->state = ANEG_STATE_AN_ENABLE;

                /* fallthru */
        case ANEG_STATE_AN_ENABLE:
                ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
                if (ap->flags & MR_AN_ENABLE) {
                        ap->link_time = 0;
                        ap->cur_time = 0;
                        ap->ability_match_cfg = 0;
                        ap->ability_match_count = 0;
                        ap->ability_match = 0;
                        ap->idle_match = 0;
                        ap->ack_match = 0;

                        ap->state = ANEG_STATE_RESTART_INIT;
                } else {
                        ap->state = ANEG_STATE_DISABLE_LINK_OK;
                }
                break;

        case ANEG_STATE_RESTART_INIT:
                ap->link_time = ap->cur_time;
                ap->flags &= ~(MR_NP_LOADED);
                ap->txconfig = 0;
                tw32(MAC_TX_AUTO_NEG, 0);
                tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);

                ret = ANEG_TIMER_ENAB;
                ap->state = ANEG_STATE_RESTART;

                /* fallthru */
        case ANEG_STATE_RESTART:
                delta = ap->cur_time - ap->link_time;
                if (delta > ANEG_STATE_SETTLE_TIME)
                        ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
                else
                        ret = ANEG_TIMER_ENAB;
                break;

        case ANEG_STATE_DISABLE_LINK_OK:
                ret = ANEG_DONE;
                break;

        case ANEG_STATE_ABILITY_DETECT_INIT:
                ap->flags &= ~(MR_TOGGLE_TX);
                ap->txconfig = ANEG_CFG_FD;
                flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
                if (flowctrl & ADVERTISE_1000XPAUSE)
                        ap->txconfig |= ANEG_CFG_PS1;
                if (flowctrl & ADVERTISE_1000XPSE_ASYM)
                        ap->txconfig |= ANEG_CFG_PS2;
                tw32(MAC_TX_AUTO_NEG, ap->txconfig);
                tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);

                ap->state = ANEG_STATE_ABILITY_DETECT;
                break;

        case ANEG_STATE_ABILITY_DETECT:
                if (ap->ability_match != 0 && ap->rxconfig != 0)
                        ap->state = ANEG_STATE_ACK_DETECT_INIT;
                break;

        case ANEG_STATE_ACK_DETECT_INIT:
                ap->txconfig |= ANEG_CFG_ACK;
                tw32(MAC_TX_AUTO_NEG, ap->txconfig);
                tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);

                ap->state = ANEG_STATE_ACK_DETECT;

                /* fallthru */
        case ANEG_STATE_ACK_DETECT:
                if (ap->ack_match != 0) {
                        if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
                            (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
                                ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
                        } else {
                                ap->state = ANEG_STATE_AN_ENABLE;
                        }
                } else if (ap->ability_match != 0 &&
                           ap->rxconfig == 0) {
                        ap->state = ANEG_STATE_AN_ENABLE;
                }
                break;

        case ANEG_STATE_COMPLETE_ACK_INIT:
                if (ap->rxconfig & ANEG_CFG_INVAL) {
                        ret = ANEG_FAILED;
                        break;
                }
                ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
                               MR_LP_ADV_HALF_DUPLEX |
                               MR_LP_ADV_SYM_PAUSE |
                               MR_LP_ADV_ASYM_PAUSE |
                               MR_LP_ADV_REMOTE_FAULT1 |
                               MR_LP_ADV_REMOTE_FAULT2 |
                               MR_LP_ADV_NEXT_PAGE |
                               MR_TOGGLE_RX |
                               MR_NP_RX);
                if (ap->rxconfig & ANEG_CFG_FD)
                        ap->flags |= MR_LP_ADV_FULL_DUPLEX;
                if (ap->rxconfig & ANEG_CFG_HD)
                        ap->flags |= MR_LP_ADV_HALF_DUPLEX;
                if (ap->rxconfig & ANEG_CFG_PS1)
                        ap->flags |= MR_LP_ADV_SYM_PAUSE;
                if (ap->rxconfig & ANEG_CFG_PS2)
                        ap->flags |= MR_LP_ADV_ASYM_PAUSE;
                if (ap->rxconfig & ANEG_CFG_RF1)
                        ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
                if (ap->rxconfig & ANEG_CFG_RF2)
                        ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
                if (ap->rxconfig & ANEG_CFG_NP)
                        ap->flags |= MR_LP_ADV_NEXT_PAGE;

                ap->link_time = ap->cur_time;

                ap->flags ^= (MR_TOGGLE_TX);
                if (ap->rxconfig & 0x0008)
                        ap->flags |= MR_TOGGLE_RX;
                if (ap->rxconfig & ANEG_CFG_NP)
                        ap->flags |= MR_NP_RX;
                ap->flags |= MR_PAGE_RX;

                ap->state = ANEG_STATE_COMPLETE_ACK;
                ret = ANEG_TIMER_ENAB;
                break;

        case ANEG_STATE_COMPLETE_ACK:
                if (ap->ability_match != 0 &&
                    ap->rxconfig == 0) {
                        ap->state = ANEG_STATE_AN_ENABLE;
                        break;
                }
                delta = ap->cur_time - ap->link_time;
                if (delta > ANEG_STATE_SETTLE_TIME) {
                        if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
                                ap->state = ANEG_STATE_IDLE_DETECT_INIT;
                        } else {
                                if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
                                    !(ap->flags & MR_NP_RX)) {
                                        ap->state = ANEG_STATE_IDLE_DETECT_INIT;
                                } else {
                                        ret = ANEG_FAILED;
                                }
                        }
                }
                break;

        case ANEG_STATE_IDLE_DETECT_INIT:
                ap->link_time = ap->cur_time;
                tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);

                ap->state = ANEG_STATE_IDLE_DETECT;
                ret = ANEG_TIMER_ENAB;
                break;

        case ANEG_STATE_IDLE_DETECT:
                if (ap->ability_match != 0 &&
                    ap->rxconfig == 0) {
                        ap->state = ANEG_STATE_AN_ENABLE;
                        break;
                }
                delta = ap->cur_time - ap->link_time;
                if (delta > ANEG_STATE_SETTLE_TIME) {
                        /* XXX another gem from the Broadcom driver :( */
                        ap->state = ANEG_STATE_LINK_OK;
                }
                break;

        case ANEG_STATE_LINK_OK:
                ap->flags |= (MR_AN_COMPLETE | MR_LINK_OK);
                ret = ANEG_DONE;
                break;

        case ANEG_STATE_NEXT_PAGE_WAIT_INIT:
                /* ??? unimplemented */
                break;

        case ANEG_STATE_NEXT_PAGE_WAIT:
                /* ??? unimplemented */
                break;

        default:
                ret = ANEG_FAILED;
                break;
        }

        return ret;
}
static int fiber_autoneg ( struct tg3 tp,
u32 txflags,
u32 rxflags 
) [static]

Definition at line 1817 of file tg3_phy.c.

References ANEG_DONE, ANEG_FAILED, ANEG_STATE_UNKNOWN, tg3_fiber_aneginfo::cur_time, tg3_fiber_aneginfo::flags, MAC_MODE, tg3::mac_mode, MAC_MODE_PORT_MODE_GMII, MAC_MODE_PORT_MODE_MASK, MAC_MODE_SEND_CONFIGS, MAC_TX_AUTO_NEG, memset(), MR_AN_COMPLETE, MR_AN_ENABLE, MR_LINK_OK, MR_LP_ADV_FULL_DUPLEX, tg3_fiber_aneginfo::state, status, tg3_fiber_aneg_smachine(), tick, tw32_f, tg3_fiber_aneginfo::txconfig, and udelay().

Referenced by tg3_setup_fiber_by_hand().

{
        int res = 0;
        struct tg3_fiber_aneginfo aninfo;
        int status = ANEG_FAILED;
        unsigned int tick;
        u32 tmp;

        tw32_f(MAC_TX_AUTO_NEG, 0);

        tmp = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
        tw32_f(MAC_MODE, tmp | MAC_MODE_PORT_MODE_GMII);
        udelay(40);

        tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_SEND_CONFIGS);
        udelay(40);

        memset(&aninfo, 0, sizeof(aninfo));
        aninfo.flags |= MR_AN_ENABLE;
        aninfo.state = ANEG_STATE_UNKNOWN;
        aninfo.cur_time = 0;
        tick = 0;
        while (++tick < 195000) {
                status = tg3_fiber_aneg_smachine(tp, &aninfo);
                if (status == ANEG_DONE || status == ANEG_FAILED)
                        break;

                udelay(1);
        }

        tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);

        *txflags = aninfo.txconfig;
        *rxflags = aninfo.flags;

        if (status == ANEG_DONE &&
            (aninfo.flags & (MR_AN_COMPLETE | MR_LINK_OK |
                             MR_LP_ADV_FULL_DUPLEX)))
                res = 1;

        return res;
}
static int tg3_setup_fiber_by_hand ( struct tg3 tp,
u32  mac_status 
) [static]

Definition at line 1862 of file tg3_phy.c.

References ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, ANEG_CFG_PS1, ANEG_CFG_PS2, tg3_link_config::autoneg, AUTONEG_ENABLE, fiber_autoneg(), tg3::link_config, LPA_1000XPAUSE, LPA_1000XPAUSE_ASYM, MAC_MODE, tg3::mac_mode, MAC_MODE_SEND_CONFIGS, MAC_STATUS, MAC_STATUS_CFG_CHANGED, MAC_STATUS_PCS_SYNCED, MAC_STATUS_RCVD_CFG, MAC_STATUS_SYNC_CHANGED, mii_adv_to_ethtool_adv_x(), MR_LP_ADV_ASYM_PAUSE, MR_LP_ADV_SYM_PAUSE, out, tg3_link_config::rmt_adv, tg3_setup_flow_control(), tr32, tw32_f, and udelay().

Referenced by tg3_setup_fiber_phy().

{
        int current_link_up = 0;

        if (!(mac_status & MAC_STATUS_PCS_SYNCED))
                goto out;

        if (tp->link_config.autoneg == AUTONEG_ENABLE) {
                u32 txflags, rxflags;
                int i;

                if (fiber_autoneg(tp, &txflags, &rxflags)) {
                        u32 local_adv = 0, remote_adv = 0;

                        if (txflags & ANEG_CFG_PS1)
                                local_adv |= ADVERTISE_1000XPAUSE;
                        if (txflags & ANEG_CFG_PS2)
                                local_adv |= ADVERTISE_1000XPSE_ASYM;

                        if (rxflags & MR_LP_ADV_SYM_PAUSE)
                                remote_adv |= LPA_1000XPAUSE;
                        if (rxflags & MR_LP_ADV_ASYM_PAUSE)
                                remote_adv |= LPA_1000XPAUSE_ASYM;

                        tp->link_config.rmt_adv =
                                           mii_adv_to_ethtool_adv_x(remote_adv);

                        tg3_setup_flow_control(tp, local_adv, remote_adv);

                        current_link_up = 1;
                }
                for (i = 0; i < 30; i++) {
                        udelay(20);
                        tw32_f(MAC_STATUS,
                               (MAC_STATUS_SYNC_CHANGED |
                                MAC_STATUS_CFG_CHANGED));
                        udelay(40);
                        if ((tr32(MAC_STATUS) &
                             (MAC_STATUS_SYNC_CHANGED |
                              MAC_STATUS_CFG_CHANGED)) == 0)
                                break;
                }

                mac_status = tr32(MAC_STATUS);
                if (!current_link_up &&
                    (mac_status & MAC_STATUS_PCS_SYNCED) &&
                    !(mac_status & MAC_STATUS_RCVD_CFG))
                        current_link_up = 1;
        } else {
                tg3_setup_flow_control(tp, 0, 0);

                /* Forcing 1000FD link up. */
                current_link_up = 1;

                tw32_f(MAC_MODE, (tp->mac_mode | MAC_MODE_SEND_CONFIGS));
                udelay(40);

                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);
        }

out:
        return current_link_up;
}
static int tg3_test_and_report_link_chg ( struct tg3 tp,
int  curr_link_up 
) [static]

Definition at line 1927 of file tg3_phy.c.

References tg3::dev, tg3::link_up, netdev_link_down(), netdev_link_up(), tg3::phy_flags, tg3_link_report(), TG3_PHYFLG_MII_SERDES, and TG3_PHYFLG_PARALLEL_DETECT.

Referenced by tg3_setup_fiber_mii_phy(), and tg3_setup_fiber_phy().

{
        if (curr_link_up != tp->link_up) {
                if (curr_link_up) {
                        netdev_link_up(tp->dev);
                } else {
                        netdev_link_down(tp->dev);
                        if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
                                tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                }

                tg3_link_report(tp);
                return 1;
        }

        return 0;
}
static void tg3_clear_mac_status ( struct tg3 tp) [static]
static int tg3_setup_fiber_phy ( struct tg3 tp,
int  force_reset 
) [static]

Definition at line 1957 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_flowctrl, tg3_link_config::active_speed, tg3_link_config::autoneg, AUTONEG_ENABLE, DUPLEX_FULL, tg3::hw_status, tg3::led_ctrl, LED_CTRL_1000MBPS_ON, LED_CTRL_LNKLED_OVERRIDE, LED_CTRL_TRAFFIC_OVERRIDE, tg3::link_config, tg3::link_up, MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED, MAC_LED_CTRL, MAC_MODE, tg3::mac_mode, MAC_MODE_HALF_DUPLEX, MAC_MODE_PORT_MODE_MASK, MAC_MODE_PORT_MODE_TBI, MAC_MODE_SEND_CONFIGS, MAC_STATUS, MAC_STATUS_CFG_CHANGED, MAC_STATUS_LNKSTATE_CHANGED, MAC_STATUS_PCS_SYNCED, MAC_STATUS_RCVD_CFG, MAC_STATUS_SIGNAL_DET, MAC_STATUS_SYNC_CHANGED, MAC_TX_AUTO_NEG, tg3::phy_id, tg3_link_config::rmt_adv, SD_STATUS_LINK_CHG, SD_STATUS_UPDATED, tg3::serdes_counter, SPEED_1000, tg3_hw_status::status, tg3_flag, tg3_init_bcm8002(), tg3_link_report(), TG3_PHY_ID_BCM8002, tg3_setup_fiber_by_hand(), tg3_setup_fiber_hw_autoneg(), tg3_test_and_report_link_chg(), tr32, tw32, tw32_f, and udelay().

Referenced by tg3_setup_phy().

{
        u32 orig_pause_cfg;
        u16 orig_active_speed;
        u8 orig_active_duplex;
        u32 mac_status;
        int current_link_up = force_reset;
        int i;

        orig_pause_cfg = tp->link_config.active_flowctrl;
        orig_active_speed = tp->link_config.active_speed;
        orig_active_duplex = tp->link_config.active_duplex;

        if (!tg3_flag(tp, HW_AUTONEG) &&
            tp->link_up &&
            tg3_flag(tp, INIT_COMPLETE)) {
                mac_status = tr32(MAC_STATUS);
                mac_status &= (MAC_STATUS_PCS_SYNCED |
                               MAC_STATUS_SIGNAL_DET |
                               MAC_STATUS_CFG_CHANGED |
                               MAC_STATUS_RCVD_CFG);
                if (mac_status == (MAC_STATUS_PCS_SYNCED |
                                   MAC_STATUS_SIGNAL_DET)) {
                        tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
                                            MAC_STATUS_CFG_CHANGED));
                        return 0;
                }
        }

        tw32_f(MAC_TX_AUTO_NEG, 0);

        tp->mac_mode &= ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
        tp->mac_mode |= MAC_MODE_PORT_MODE_TBI;
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);

        if (tp->phy_id == TG3_PHY_ID_BCM8002)
                tg3_init_bcm8002(tp);

        /* Enable link change event even when serdes polling.  */
        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
        udelay(40);

        current_link_up = 0;
        tp->link_config.rmt_adv = 0;
        mac_status = tr32(MAC_STATUS);

        if (tg3_flag(tp, HW_AUTONEG))
                current_link_up = tg3_setup_fiber_hw_autoneg(tp, mac_status);
        else
                current_link_up = tg3_setup_fiber_by_hand(tp, mac_status);

        tp->hw_status->status =
                (SD_STATUS_UPDATED |
                 (tp->hw_status->status & ~SD_STATUS_LINK_CHG));

        for (i = 0; i < 100; i++) {
                tw32_f(MAC_STATUS, (MAC_STATUS_SYNC_CHANGED |
                                    MAC_STATUS_CFG_CHANGED));
                udelay(5);
                if ((tr32(MAC_STATUS) & (MAC_STATUS_SYNC_CHANGED |
                                         MAC_STATUS_CFG_CHANGED |
                                         MAC_STATUS_LNKSTATE_CHANGED)) == 0)
                        break;
        }

        mac_status = tr32(MAC_STATUS);
        if ((mac_status & MAC_STATUS_PCS_SYNCED) == 0) {
                current_link_up = 0;
                if (tp->link_config.autoneg == AUTONEG_ENABLE &&
                    tp->serdes_counter == 0) {
                        tw32_f(MAC_MODE, (tp->mac_mode |
                                          MAC_MODE_SEND_CONFIGS));
                        udelay(1);
                        tw32_f(MAC_MODE, tp->mac_mode);
                }
        }

        if (current_link_up) {
                tp->link_config.active_speed = SPEED_1000;
                tp->link_config.active_duplex = DUPLEX_FULL;
                tw32(MAC_LED_CTRL, (tp->led_ctrl |
                                    LED_CTRL_LNKLED_OVERRIDE |
                                    LED_CTRL_1000MBPS_ON));
        } else {
                tp->link_config.active_speed = SPEED_UNKNOWN;
                tp->link_config.active_duplex = DUPLEX_UNKNOWN;
                tw32(MAC_LED_CTRL, (tp->led_ctrl |
                                    LED_CTRL_LNKLED_OVERRIDE |
                                    LED_CTRL_TRAFFIC_OVERRIDE));
        }

        if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
                u32 now_pause_cfg = tp->link_config.active_flowctrl;
                if (orig_pause_cfg != now_pause_cfg ||
                    orig_active_speed != tp->link_config.active_speed ||
                    orig_active_duplex != tp->link_config.active_duplex)
                        tg3_link_report(tp);
        }

        return 0;
}
static int tg3_setup_fiber_mii_phy ( struct tg3 tp,
int  force_reset 
) [static]

Definition at line 2060 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_speed, ADVERTISE_1000XFULL, ADVERTISE_1000XHALF, ADVERTISE_1000XPAUSE, ADVERTISE_1000XPSE_ASYM, ADVERTISE_SLCT, tg3_link_config::advertising, ASIC_REV_5714, ASIC_REV_5719, ASIC_REV_5720, tg3_link_config::autoneg, AUTONEG_ENABLE, BMCR_ANENABLE, BMCR_ANRESTART, BMCR_FULLDPLX, BMCR_SPEED1000, BMSR_LSTATUS, common, tg3::dev, tg3_link_config::duplex, DUPLEX_FULL, DUPLEX_HALF, ethtool_adv_to_mii_adv_x(), tg3_link_config::flowctrl, GET_ASIC_REV, tg3::link_config, tg3::link_up, MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED, MAC_MODE, tg3::mac_mode, MAC_MODE_HALF_DUPLEX, MAC_MODE_PORT_MODE_GMII, MAC_MODE_PORT_MODE_MASK, MAC_MODE_PORT_MODE_MII, MAC_TX_STATUS, mii_adv_to_ethtool_adv_x(), MII_ADVERTISE, MII_BMCR, MII_BMSR, MII_LPA, netdev_link_down(), tg3::pci_chip_rev_id, tg3::phy_flags, tg3_link_config::rmt_adv, SERDES_AN_TIMEOUT_5714S, tg3::serdes_counter, SERDES_TG3_1000X_STATUS, SERDES_TG3_FULL_DUPLEX, SERDES_TG3_LINK_UP, SERDES_TG3_SGMII_MODE, SERDES_TG3_SPEED_100, SERDES_TG3_SPEED_1000, SPEED_10, SPEED_100, SPEED_1000, tg3_advert_flowctrl_1000X(), tg3_clear_mac_status(), tg3_flag, tg3_phy_reset(), TG3_PHYFLG_PARALLEL_DETECT, tg3_readphy(), tg3_setup_flow_control(), tg3_test_and_report_link_chg(), tg3_writephy(), tr32, tw32_f, TX_STATUS_LINK_UP, and udelay().

Referenced by tg3_setup_phy().

{
        int err = 0;
        u32 bmsr, bmcr;
        u16 current_speed = SPEED_UNKNOWN;
        u8 current_duplex = DUPLEX_UNKNOWN;
        int current_link_up = 0;
        u32 local_adv, remote_adv, sgsr;

        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) &&
             !tg3_readphy(tp, SERDES_TG3_1000X_STATUS, &sgsr) &&
             (sgsr & SERDES_TG3_SGMII_MODE)) {

                if (force_reset)
                        tg3_phy_reset(tp);

                tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;

                if (!(sgsr & SERDES_TG3_LINK_UP)) {
                        tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
                } else {
                        current_link_up = 1;
                        if (sgsr & SERDES_TG3_SPEED_1000) {
                                current_speed = SPEED_1000;
                                tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
                        } else if (sgsr & SERDES_TG3_SPEED_100) {
                                current_speed = SPEED_100;
                                tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
                        } else {
                                current_speed = SPEED_10;
                                tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
                        }

                        if (sgsr & SERDES_TG3_FULL_DUPLEX)
                                current_duplex = DUPLEX_FULL;
                        else
                                current_duplex = DUPLEX_HALF;
                }

                tw32_f(MAC_MODE, tp->mac_mode);
                udelay(40);

                tg3_clear_mac_status(tp);

                goto fiber_setup_done;
        }

        tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);

        tg3_clear_mac_status(tp);

        if (force_reset)
                tg3_phy_reset(tp);

        tp->link_config.rmt_adv = 0;

        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
                if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
                        bmsr |= BMSR_LSTATUS;
                else
                        bmsr &= ~BMSR_LSTATUS;
        }

        err |= tg3_readphy(tp, MII_BMCR, &bmcr);

        if ((tp->link_config.autoneg == AUTONEG_ENABLE) && !force_reset &&
            (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
                /* do nothing, just check for link up at the end */
        } else if (tp->link_config.autoneg == AUTONEG_ENABLE) {
                u32 adv, newadv;

                err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
                newadv = adv & ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF |
                                 ADVERTISE_1000XPAUSE |
                                 ADVERTISE_1000XPSE_ASYM |
                                 ADVERTISE_SLCT);

                newadv |= tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
                newadv |= ethtool_adv_to_mii_adv_x(tp->link_config.advertising);

                if ((newadv != adv) || !(bmcr & BMCR_ANENABLE)) {
                        tg3_writephy(tp, MII_ADVERTISE, newadv);
                        bmcr |= BMCR_ANENABLE | BMCR_ANRESTART;
                        tg3_writephy(tp, MII_BMCR, bmcr);

                        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
                        tp->serdes_counter = SERDES_AN_TIMEOUT_5714S;
                        tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;

                        return err;
                }
        } else {
                u32 new_bmcr;

                bmcr &= ~BMCR_SPEED1000;
                new_bmcr = bmcr & ~(BMCR_ANENABLE | BMCR_FULLDPLX);

                if (tp->link_config.duplex == DUPLEX_FULL)
                        new_bmcr |= BMCR_FULLDPLX;

                if (new_bmcr != bmcr) {
                        /* BMCR_SPEED1000 is a reserved bit that needs
                         * to be set on write.
                         */
                        new_bmcr |= BMCR_SPEED1000;

                        /* Force a linkdown */
                        if (tp->link_up) {
                                u32 adv;

                                err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
                                adv &= ~(ADVERTISE_1000XFULL |
                                         ADVERTISE_1000XHALF |
                                         ADVERTISE_SLCT);
                                tg3_writephy(tp, MII_ADVERTISE, adv);
                                tg3_writephy(tp, MII_BMCR, bmcr |
                                                           BMCR_ANRESTART |
                                                           BMCR_ANENABLE);
                                udelay(10);
                                netdev_link_down(tp->dev);
                        }
                        tg3_writephy(tp, MII_BMCR, new_bmcr);
                        bmcr = new_bmcr;
                        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
                        err |= tg3_readphy(tp, MII_BMSR, &bmsr);
                        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
                                if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
                                        bmsr |= BMSR_LSTATUS;
                                else
                                        bmsr &= ~BMSR_LSTATUS;
                        }
                        tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                }
        }

        if (bmsr & BMSR_LSTATUS) {
                current_speed = SPEED_1000;
                current_link_up = 1;
                if (bmcr & BMCR_FULLDPLX)
                        current_duplex = DUPLEX_FULL;
                else
                        current_duplex = DUPLEX_HALF;

                local_adv = 0;
                remote_adv = 0;

                if (bmcr & BMCR_ANENABLE) {
                        u32 common;

                        err |= tg3_readphy(tp, MII_ADVERTISE, &local_adv);
                        err |= tg3_readphy(tp, MII_LPA, &remote_adv);
                        common = local_adv & remote_adv;
                        if (common & (ADVERTISE_1000XHALF |
                                      ADVERTISE_1000XFULL)) {
                                if (common & ADVERTISE_1000XFULL)
                                        current_duplex = DUPLEX_FULL;
                                else
                                        current_duplex = DUPLEX_HALF;

                                tp->link_config.rmt_adv =
                                           mii_adv_to_ethtool_adv_x(remote_adv);
                        } else if (!tg3_flag(tp, 5780_CLASS)) {
                                /* Link is up via parallel detect */
                        } else {
                                current_link_up = 0;
                        }
                }
        }

fiber_setup_done:
        if (current_link_up && current_duplex == DUPLEX_FULL)
                tg3_setup_flow_control(tp, local_adv, remote_adv);

        tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
        if (tp->link_config.active_duplex == DUPLEX_HALF)
                tp->mac_mode |= MAC_MODE_HALF_DUPLEX;

        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);

        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);

        tp->link_config.active_speed = current_speed;
        tp->link_config.active_duplex = current_duplex;

        tg3_test_and_report_link_chg(tp, current_link_up);
        return err;
}
static int tg3_setup_copper_phy ( struct tg3 tp,
int  force_reset 
) [static]

Definition at line 2254 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_speed, tg3_link_config::advertising, ASIC_REV_5700, ASIC_REV_5701, ASIC_REV_5703, ASIC_REV_5704, ASIC_REV_5705, BMCR_ANENABLE, BMSR_LSTATUS, CHIPREV_ID_5700_ALTIMA, CHIPREV_ID_5701_A0, CHIPREV_ID_5701_B0, DBGP, tg3::dev, DUPLEX_FULL, DUPLEX_HALF, DUPLEX_INVALID, GET_ASIC_REV, tg3::led_ctrl, LED_CTRL_MODE_PHY_1, tg3::link_config, MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED, MAC_MI_MODE, MAC_MI_MODE_AUTO_POLL, MAC_MODE, tg3::mac_mode, MAC_MODE_HALF_DUPLEX, MAC_MODE_LINK_POLARITY, MAC_MODE_PORT_INT_LPBACK, MAC_MODE_PORT_MODE_GMII, MAC_MODE_PORT_MODE_MASK, MAC_MODE_PORT_MODE_MII, MAC_STATUS, MAC_STATUS_CFG_CHANGED, MAC_STATUS_LNKSTATE_CHANGED, MAC_STATUS_MI_COMPLETION, MAC_STATUS_SYNC_CHANGED, tg3::mi_mode, MII_BMCR, MII_BMSR, MII_TG3_AUX_STAT, MII_TG3_AUXCTL_SHDWSEL_MISCTEST, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_LNK3_LED_MODE, MII_TG3_IMASK, MII_TG3_INT_LINKCHG, MII_TG3_ISTAT, MII_TG3_MISC_SHDW, netdev_link_down(), netdev_link_ok(), netdev_link_up(), NIC_SRAM_FIRMWARE_MBOX, NIC_SRAM_FIRMWARE_MBOX_MAGIC2, tg3::pci_chip_rev_id, PCI_EXP_LNKCTL, PCI_EXP_LNKCTL_CLKREQ_EN, pci_read_config_word(), pci_write_config_word(), tg3::pcie_cap, tg3::pdev, tg3::phy_flags, tg3::phy_id, SPEED_10, SPEED_100, SPEED_1000, SPEED_INVALID, tg3_5700_link_polarity(), tg3_adv_1000T_flowctrl_ok(), tg3_aux_stat_to_speed_duplex(), tg3_copper_is_advertising_all(), tg3_flag, tg3_init_5401phy_dsp(), tg3_link_report(), tg3_phy_auxctl_read(), tg3_phy_auxctl_write(), tg3_phy_copper_begin(), TG3_PHY_ID_BCM5401, TG3_PHY_ID_BCM5411, TG3_PHY_ID_MASK, TG3_PHY_ID_REV_MASK, tg3_phy_reset(), TG3_PHY_REV_BCM5401_B0, TG3_PHYFLG_CAPACITIVE_COUPLING, TG3_PHYFLG_IS_FET, TG3_PHYFLG_USE_MI_INTERRUPT, tg3_readphy(), tg3_setup_flow_control(), tg3_write_mem(), tg3_writephy(), tw32, tw32_f, udelay(), and val.

Referenced by tg3_setup_phy().

{       DBGP("%s\n", __func__);

        int current_link_up;
        u32 bmsr, val;
        u32 lcl_adv, rmt_adv;
        u16 current_speed;
        u8 current_duplex;
        int i, err;

        tw32(MAC_EVENT, 0);

        tw32_f(MAC_STATUS,
             (MAC_STATUS_SYNC_CHANGED |
              MAC_STATUS_CFG_CHANGED |
              MAC_STATUS_MI_COMPLETION |
              MAC_STATUS_LNKSTATE_CHANGED));
        udelay(40);

        if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
                tw32_f(MAC_MI_MODE,
                     (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
                udelay(80);
        }

        tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);

        /* Some third-party PHYs need to be reset on link going
         * down.
         */
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
            netdev_link_ok(tp->dev)) {
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    !(bmsr & BMSR_LSTATUS))
                        force_reset = 1;
        }
        if (force_reset)
                tg3_phy_reset(tp);

        if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
                    !tg3_flag(tp, INIT_COMPLETE))
                        bmsr = 0;

                if (!(bmsr & BMSR_LSTATUS)) {
                        err = tg3_init_5401phy_dsp(tp);
                        if (err)
                                return err;

                        tg3_readphy(tp, MII_BMSR, &bmsr);
                        for (i = 0; i < 1000; i++) {
                                udelay(10);
                                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                                    (bmsr & BMSR_LSTATUS)) {
                                        udelay(40);
                                        break;
                                }
                        }

                        if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
                            TG3_PHY_REV_BCM5401_B0 &&
                            !(bmsr & BMSR_LSTATUS) &&
                            tp->link_config.active_speed == SPEED_1000) {
                                err = tg3_phy_reset(tp);
                                if (!err)
                                        err = tg3_init_5401phy_dsp(tp);
                                if (err)
                                        return err;
                        }
                }
        } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
                   tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
                /* 5701 {A0,B0} CRC bug workaround */
                tg3_writephy(tp, 0x15, 0x0a75);
                tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
                tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
                tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
        }

        /* Clear pending interrupts... */
        tg3_readphy(tp, MII_TG3_ISTAT, &val);
        tg3_readphy(tp, MII_TG3_ISTAT, &val);

        if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
                tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
        else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
                tg3_writephy(tp, MII_TG3_IMASK, ~0);

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
                if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
                        tg3_writephy(tp, MII_TG3_EXT_CTRL,
                                     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
                else
                        tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
        }

        current_link_up = 0;
        current_speed = SPEED_INVALID;
        current_duplex = DUPLEX_INVALID;

        if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
                err = tg3_phy_auxctl_read(tp,
                                          MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
                                          &val);
                if (!err && !(val & (1 << 10))) {
                        tg3_phy_auxctl_write(tp,
                                             MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
                                             val | (1 << 10));
                        goto relink;
                }
        }

        bmsr = 0;
        for (i = 0; i < 100; i++) {
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    (bmsr & BMSR_LSTATUS))
                        break;
                udelay(40);
        }

        if (bmsr & BMSR_LSTATUS) {
                u32 aux_stat, bmcr;

                tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
                for (i = 0; i < 2000; i++) {
                        udelay(10);
                        if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
                            aux_stat)
                                break;
                }

                tg3_aux_stat_to_speed_duplex(tp, aux_stat,
                                             &current_speed,
                                             &current_duplex);

                bmcr = 0;
                for (i = 0; i < 200; i++) {
                        tg3_readphy(tp, MII_BMCR, &bmcr);
                        if (tg3_readphy(tp, MII_BMCR, &bmcr))
                                continue;
                        if (bmcr && bmcr != 0x7fff)
                                break;
                        udelay(10);
                }

                lcl_adv = 0;
                rmt_adv = 0;

                tp->link_config.active_speed = current_speed;
                tp->link_config.active_duplex = current_duplex;

                if ((bmcr & BMCR_ANENABLE) &&
                    tg3_copper_is_advertising_all(tp,
                                        tp->link_config.advertising)) {
                        if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
                                                          &rmt_adv)) {
                                current_link_up = 1;
                        }
                }

                if (current_link_up == 1 &&
                    tp->link_config.active_duplex == DUPLEX_FULL)
                        tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
        }

relink:
        if (current_link_up == 0) {
                tg3_phy_copper_begin(tp);

                tg3_readphy(tp, MII_BMSR, &bmsr);
                if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
                    (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
                        current_link_up = 1;
        }

        tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
        if (current_link_up == 1) {
                if (tp->link_config.active_speed == SPEED_100 ||
                    tp->link_config.active_speed == SPEED_10)
                        tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
                else
                        tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
        } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
                tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
        else
                tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;

        tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
        if (tp->link_config.active_duplex == DUPLEX_HALF)
                tp->mac_mode |= MAC_MODE_HALF_DUPLEX;

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
                if (current_link_up == 1 &&
                    tg3_5700_link_polarity(tp, tp->link_config.active_speed))
                        tp->mac_mode |= MAC_MODE_LINK_POLARITY;
                else
                        tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
        }

        /* ??? Without this setting Netgear GA302T PHY does not
         * ??? send/receive packets...
         */
        if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
            tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
                tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
                tw32_f(MAC_MI_MODE, tp->mi_mode);
                udelay(80);
        }

        tw32_f(MAC_MODE, tp->mac_mode);
        udelay(40);

        /* Enabled attention when the link has changed state. */
        tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
        udelay(40);

        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
            current_link_up == 1 &&
            tp->link_config.active_speed == SPEED_1000 &&
            (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
                udelay(120);
                /* NOTE: this freezes for mdc? */
                tw32_f(MAC_STATUS,
                     (MAC_STATUS_SYNC_CHANGED |
                      MAC_STATUS_CFG_CHANGED));
                udelay(40);
                tg3_write_mem(tp,
                              NIC_SRAM_FIRMWARE_MBOX,
                              NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
        }

        /* Prevent send BD corruption. */
        if (tg3_flag(tp, CLKREQ_BUG)) {
                u16 oldlnkctl, newlnkctl;

                pci_read_config_word(tp->pdev,
                                     tp->pcie_cap + PCI_EXP_LNKCTL,
                                     &oldlnkctl);
                if (tp->link_config.active_speed == SPEED_100 ||
                    tp->link_config.active_speed == SPEED_10)
                        newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
                else
                        newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
                if (newlnkctl != oldlnkctl)
                        pci_write_config_word(tp->pdev,
                                              tp->pcie_cap + PCI_EXP_LNKCTL,
                                              newlnkctl);
        }

        if (current_link_up != netdev_link_ok(tp->dev)) {
                if (current_link_up)
                        netdev_link_up(tp->dev);
                else
                        netdev_link_down(tp->dev);
                tg3_link_report(tp);
        }

        return 0;
}
int tg3_setup_phy ( struct tg3 tp,
int  force_reset 
)

Definition at line 2520 of file tg3_phy.c.

References tg3_link_config::active_duplex, tg3_link_config::active_speed, ASIC_REV_5720, DBGP, DEFAULT_STAT_COAL_TICKS, tg3::dev, DUPLEX_HALF, GET_ASIC_REV, HOSTCC_STAT_COAL_TICKS, tg3::link_config, MAC_TX_LENGTHS, netdev_link_ok(), tg3::pci_chip_rev_id, PCIE_PWR_MGMT_L1_THRESH_MSK, PCIE_PWR_MGMT_THRESH, tg3::phy_flags, SPEED_1000, tg3_flag, TG3_PHYFLG_MII_SERDES, TG3_PHYFLG_PHY_SERDES, tg3_setup_copper_phy(), tg3_setup_fiber_mii_phy(), tg3_setup_fiber_phy(), tr32, tw32, TX_LENGTHS_CNT_DWN_VAL_MSK, TX_LENGTHS_IPG_CRS_SHIFT, TX_LENGTHS_IPG_SHIFT, TX_LENGTHS_JMB_FRM_LEN_MSK, TX_LENGTHS_SLOT_TIME_SHIFT, and val.

Referenced by tg3_init_one(), tg3_poll_link(), and tg3_reset_hw().


Variable Documentation

Definition at line 140 of file tg3_phy.c.