static int xfp_phy_init(struct efx_nic *efx) { struct xfp_phy_data *phy_data; u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); int rc; phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); if (!phy_data) return -ENOMEM; efx->phy_data = phy_data; EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), MDIO_ID_REV(devid)); phy_data->phy_mode = efx->phy_mode; rc = xfp_reset_phy(efx); EFX_INFO(efx, "XFP: PHY init %s.\n", rc ? "failed" : "successful"); if (rc < 0) goto fail; return 0; fail: kfree(efx->phy_data); efx->phy_data = NULL; return rc; }
/* Initialisation entry point for this PHY driver */ static int txc43128_phy_init(struct efx_nic *efx) { u32 devid; int rc; devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); EFX_INFO(efx, ""TXCNAME ": PHY ID reg %x (OUI %06x model %02x " "revision %x)\n", devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), efx_mdio_id_rev(devid)); EFX_INFO(efx, ""TXCNAME ": Silicon ID %x\n", efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_GLRGS_SLID) & TXC_GLRGS_SLID_MASK); rc = txc_reset_phy(efx); if (rc < 0) return rc; rc = txc_bist(efx); if (rc < 0) return rc; txc_apply_defaults(efx); return 0; }
static void sfn4111t_fini(struct efx_nic *efx) { EFX_INFO(efx, "%s\n", __func__); device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); i2c_unregister_device(falcon_board(efx)->hwmon_client); }
static void sfe4001_fini(struct efx_nic *efx) { struct falcon_board *board = falcon_board(efx); EFX_INFO(efx, "%s\n", __func__); device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); sfe4001_poweroff(efx); i2c_unregister_device(board->ioexp_client); i2c_unregister_device(board->hwmon_client); }
/* This board uses an I2C expander to provider power to the PHY, which needs to * be turned on before the PHY can be used. * Context: Process context, rtnl lock held */ static int sfe4001_init(struct efx_nic *efx) { struct falcon_board *board = falcon_board(efx); int rc; #if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE) board->hwmon_client = i2c_new_device(&board->i2c_adap, &sfe4001_hwmon_info); #else board->hwmon_client = i2c_new_dummy(&board->i2c_adap, sfe4001_hwmon_info.addr); #endif if (!board->hwmon_client) return -EIO; /* Raise board/PHY high limit from 85 to 90 degrees Celsius */ rc = i2c_smbus_write_byte_data(board->hwmon_client, MAX664X_REG_WLHO, 90); if (rc) goto fail_hwmon; board->ioexp_client = i2c_new_dummy(&board->i2c_adap, PCA9539); if (!board->ioexp_client) { rc = -EIO; goto fail_hwmon; } if (efx->phy_mode & PHY_MODE_SPECIAL) { /* PHY won't generate a 156.25 MHz clock and MAC stats fetch * will fail. */ falcon_stop_nic_stats(efx); } rc = sfe4001_poweron(efx); if (rc) goto fail_ioexp; rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); if (rc) goto fail_on; EFX_INFO(efx, "PHY is powered on\n"); return 0; fail_on: sfe4001_poweroff(efx); fail_ioexp: i2c_unregister_device(board->ioexp_client); fail_hwmon: i2c_unregister_device(board->hwmon_client); return rc; }
static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd) { int val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); int tries = 50; val |= (1 << TXC_GLCMD_LMTSWRST_LBN); efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val); while (tries--) { val = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN))) break; udelay(1); } if (!tries) EFX_INFO(efx, TXCNAME " Logic reset timed out!\n"); }
int efx_set_board_info(struct efx_nic *efx, u16 revision_info) { int rc = 0; struct efx_board_data *data; if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) { EFX_ERR(efx, "squashing unknown board type %d\n", BOARD_TYPE(revision_info)); revision_info = 0; } if (BOARD_TYPE(revision_info) == 0) { efx->board_info.major = 0; efx->board_info.minor = 0; /* For early boards that don't have revision info. there is * only 1 board for each PHY type, so we can work it out, with * the exception of the PHY-less boards. */ switch (efx->phy_type) { case PHY_TYPE_10XPRESS: efx->board_info.type = EFX_BOARD_SFE4001; break; case PHY_TYPE_XFP: efx->board_info.type = EFX_BOARD_SFE4002; break; default: efx->board_info.type = 0; break; } } else { efx->board_info.type = BOARD_TYPE(revision_info); efx->board_info.major = BOARD_MAJOR(revision_info); efx->board_info.minor = BOARD_MINOR(revision_info); } data = &board_data[efx->board_info.type]; /* Report the board model number or generic type for recognisable * boards. */ if (efx->board_info.type != 0) EFX_INFO(efx, "board is %s rev %c%d\n", (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC) ? data->ref_model : data->gen_type, 'A' + efx->board_info.major, efx->board_info.minor); efx->board_info.init = data->init; return rc; }
static bool falcon_xgmii_status(struct efx_nic *efx) { efx_oword_t reg; if (falcon_rev(efx) < FALCON_REV_B0) return true; /* The ISR latches, so clear it and re-read */ falcon_read(efx, ®, XM_MGT_INT_REG_B0); falcon_read(efx, ®, XM_MGT_INT_REG_B0); if (EFX_OWORD_FIELD(reg, XM_LCLFLT) || EFX_OWORD_FIELD(reg, XM_RMTFLT)) { EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); return false; } return true; }
void falcon_probe_board(struct efx_nic *efx, u16 revision_info) { struct falcon_board *board = falcon_board(efx); u8 type_id = FALCON_BOARD_TYPE(revision_info); int i; board->major = FALCON_BOARD_MAJOR(revision_info); board->minor = FALCON_BOARD_MINOR(revision_info); for (i = 0; i < ARRAY_SIZE(board_types); i++) if (board_types[i].id == type_id) board->type = &board_types[i]; if (board->type) { EFX_INFO(efx, "board is %s rev %c%d\n", (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC) ? board->type->ref_model : board->type->gen_type, 'A' + board->major, board->minor); } else { EFX_ERR(efx, "unknown board type %d\n", type_id); board->type = &falcon_dummy_board; } }
void efx_set_board_info(struct efx_nic *efx, u16 revision_info) { struct efx_board_data *data = NULL; int i; efx->board_info.type = BOARD_TYPE(revision_info); efx->board_info.major = BOARD_MAJOR(revision_info); efx->board_info.minor = BOARD_MINOR(revision_info); for (i = 0; i < ARRAY_SIZE(board_data); i++) if (board_data[i].type == efx->board_info.type) data = &board_data[i]; if (data) { EFX_INFO(efx, "board is %s rev %c%d\n", (efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC) ? data->ref_model : data->gen_type, 'A' + efx->board_info.major, efx->board_info.minor); efx->board_info.init = data->init; } else { EFX_ERR(efx, "unknown board type %d\n", efx->board_info.type); } }
static int sfe4001_poweron(struct efx_nic *efx) { struct i2c_client *ioexp_client = falcon_board(efx)->ioexp_client; struct i2c_client *hwmon_client = falcon_board(efx)->hwmon_client; unsigned int i, j; int rc; u8 out; /* Clear any previous over-temperature alert */ rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL); if (rc < 0) return rc; /* Enable port 0 and port 1 outputs on IO expander */ rc = i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0x00); if (rc) return rc; rc = i2c_smbus_write_byte_data(ioexp_client, P1_CONFIG, 0xff & ~(1 << P1_SPARE_LBN)); if (rc) goto fail_on; /* If PHY power is on, turn it all off and wait 1 second to * ensure a full reset. */ rc = i2c_smbus_read_byte_data(ioexp_client, P0_OUT); if (rc < 0) goto fail_on; out = 0xff & ~((0 << P0_EN_1V2_LBN) | (0 << P0_EN_2V5_LBN) | (0 << P0_EN_3V3X_LBN) | (0 << P0_EN_5V_LBN) | (0 << P0_EN_1V0X_LBN)); if (rc != out) { EFX_INFO(efx, "power-cycling PHY\n"); rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); if (rc) goto fail_on; schedule_timeout_uninterruptible(HZ); } for (i = 0; i < 20; ++i) { /* Turn on 1.2V, 2.5V, 3.3V and 5V power rails */ out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) | (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) | (1 << P0_X_TRST_LBN)); if (efx->phy_mode & PHY_MODE_SPECIAL) out |= 1 << P0_EN_3V3X_LBN; rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); if (rc) goto fail_on; msleep(10); /* Turn on 1V power rail */ out &= ~(1 << P0_EN_1V0X_LBN); rc = i2c_smbus_write_byte_data(ioexp_client, P0_OUT, out); if (rc) goto fail_on; EFX_INFO(efx, "waiting for DSP boot (attempt %d)...\n", i); /* In flash config mode, DSP does not turn on AFE, so * just wait 1 second. */ if (efx->phy_mode & PHY_MODE_SPECIAL) { schedule_timeout_uninterruptible(HZ); return 0; } for (j = 0; j < 10; ++j) { msleep(100); /* Check DSP has asserted AFE power line */ rc = i2c_smbus_read_byte_data(ioexp_client, P1_IN); if (rc < 0) goto fail_on; if (rc & (1 << P1_AFE_PWD_LBN)) return 0; } } EFX_INFO(efx, "timed out waiting for DSP boot\n"); rc = -ETIMEDOUT; fail_on: sfe4001_poweroff(efx); return rc; }
/* Run a single BIST on one MMD*/ static int txc_bist_one(struct efx_nic *efx, int mmd, int test) { int ctrl, bctl; int lane; int rc = 0; EFX_INFO(efx, "" TXCNAME ": running BIST on %s MMD\n", efx_mdio_mmd_name(mmd)); /* Set PMA to test into loopback using Mt Diablo reg as per app note */ ctrl = efx_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL); ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl); /* The BIST app. note lists these as 3 distinct steps. */ /* Set the BIST type */ bctl = (test << TXC_BIST_CTRL_TYPE_LBN); efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); /* Set the BSTEN bit in the BIST Control register to enable */ bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN); efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); /* Set the BSTRT bit in the BIST Control register */ efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl | (1 << TXC_BIST_CTRL_STRT_LBN)); /* Wait. */ udelay(TXC_BIST_DURATION); /* Set the BSTOP bit in the BIST Control register */ bctl |= (1 << TXC_BIST_CTRL_STOP_LBN); efx_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); /* The STOP bit should go off when things have stopped */ while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN)) bctl = efx_mdio_read(efx, mmd, TXC_BIST_CTL); /* Check all the error counts are 0 and all the frame counts are non-zero */ for (lane = 0; lane < 4; lane++) { int count = efx_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane); if (count != 0) { EFX_ERR(efx, ""TXCNAME": BIST error. " "Lane %d had %d errs\n", lane, count); rc = -EIO; } count = efx_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane); if (count == 0) { EFX_ERR(efx, ""TXCNAME": BIST error. " "Lane %d got 0 frames\n", lane); rc = -EIO; } } if (rc == 0) EFX_INFO(efx, ""TXCNAME": BIST pass\n"); /* Disable BIST */ efx_mdio_write(efx, mmd, TXC_BIST_CTL, 0); /* Turn off loopback */ ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); efx_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl); return rc; }