From 64eebcfd899a5d2ebe211a593ec13ec24630f1a3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Mon, 20 Sep 2010 08:43:07 +0000 Subject: sfc: Add filter table management Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/sfc/Makefile') diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index 1047b19c60a5..fd9272b5873a 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile @@ -1,4 +1,4 @@ -sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o \ +sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ falcon_gmac.o falcon_xmac.o mcdi_mac.o \ selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o -- cgit v1.2.3 From 8fbca791309b5a57bec53e5fd7da912c16416ed3 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 22 Sep 2010 10:00:11 +0000 Subject: sfc: Remove support for SFN4111T, SFT9001 and Falcon GMAC SFN4111T never reached production and is not being used for internal or customer testing. Since we have no production Falcon boards using the SFT9001 or the GMAC, remove support for them as well. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/Makefile | 2 +- drivers/net/sfc/falcon.c | 117 ++--------- drivers/net/sfc/falcon_boards.c | 127 +----------- drivers/net/sfc/falcon_gmac.c | 230 ---------------------- drivers/net/sfc/mac.h | 1 - drivers/net/sfc/mdio_10g.c | 30 +-- drivers/net/sfc/net_driver.h | 2 - drivers/net/sfc/phy.h | 7 +- drivers/net/sfc/tenxpress.c | 424 +++------------------------------------- drivers/net/sfc/workarounds.h | 9 +- 10 files changed, 56 insertions(+), 893 deletions(-) delete mode 100644 drivers/net/sfc/falcon_gmac.c (limited to 'drivers/net/sfc/Makefile') diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index fd9272b5873a..39f7c1bc2405 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile @@ -1,5 +1,5 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ - falcon_gmac.o falcon_xmac.o mcdi_mac.o \ + falcon_xmac.o mcdi_mac.o \ selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o sfc-$(CONFIG_SFC_MTD) += mtd.o diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index b398a4198042..254a599935c1 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -446,30 +446,19 @@ static void falcon_reset_macs(struct efx_nic *efx) /* It's not safe to use GLB_CTL_REG to reset the * macs, so instead use the internal MAC resets */ - if (!EFX_IS10G(efx)) { - EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 1); - efx_writeo(efx, ®, FR_AB_GM_CFG1); - udelay(1000); - - EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_SW_RST, 0); - efx_writeo(efx, ®, FR_AB_GM_CFG1); - udelay(1000); - return; - } else { - EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1); - efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); - - for (count = 0; count < 10000; count++) { - efx_reado(efx, ®, FR_AB_XM_GLB_CFG); - if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) == - 0) - return; - udelay(10); - } - - netif_err(efx, hw, efx->net_dev, - "timed out waiting for XMAC core reset\n"); + EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_CORE_RST, 1); + efx_writeo(efx, ®, FR_AB_XM_GLB_CFG); + + for (count = 0; count < 10000; count++) { + efx_reado(efx, ®, FR_AB_XM_GLB_CFG); + if (EFX_OWORD_FIELD(reg, FRF_AB_XM_CORE_RST) == + 0) + return; + udelay(10); } + + netif_err(efx, hw, efx->net_dev, + "timed out waiting for XMAC core reset\n"); } /* Mac stats will fail whist the TX fifo is draining */ @@ -508,7 +497,6 @@ static void falcon_reset_macs(struct efx_nic *efx) * are re-enabled by the caller */ efx_writeo(efx, &mac_ctrl, FR_AB_MAC_CTRL); - /* This can run even when the GMAC is selected */ falcon_setup_xaui(efx); } @@ -646,8 +634,6 @@ static void falcon_stats_timer_func(unsigned long context) spin_unlock(&efx->stats_lock); } -static void falcon_switch_mac(struct efx_nic *efx); - static bool falcon_loopback_link_poll(struct efx_nic *efx) { struct efx_link_state old_state = efx->link_state; @@ -658,11 +644,7 @@ static bool falcon_loopback_link_poll(struct efx_nic *efx) efx->link_state.fd = true; efx->link_state.fc = efx->wanted_fc; efx->link_state.up = true; - - if (efx->loopback_mode == LOOPBACK_GMAC) - efx->link_state.speed = 1000; - else - efx->link_state.speed = 10000; + efx->link_state.speed = 10000; return !efx_link_state_equal(&efx->link_state, &old_state); } @@ -685,7 +667,7 @@ static int falcon_reconfigure_port(struct efx_nic *efx) falcon_stop_nic_stats(efx); falcon_deconfigure_mac_wrapper(efx); - falcon_switch_mac(efx); + falcon_reset_macs(efx); efx->phy_op->reconfigure(efx); rc = efx->mac_op->reconfigure(efx); @@ -835,69 +817,16 @@ out: return rc; } -static void falcon_clock_mac(struct efx_nic *efx) -{ - unsigned strap_val; - efx_oword_t nic_stat; - - /* Configure the NIC generated MAC clock correctly */ - efx_reado(efx, &nic_stat, FR_AB_NIC_STAT); - strap_val = EFX_IS10G(efx) ? 5 : 3; - if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) { - EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1); - EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val); - efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT); - } else { - /* Falcon A1 does not support 1G/10G speed switching - * and must not be used with a PHY that does. */ - BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) != - strap_val); - } -} - -static void falcon_switch_mac(struct efx_nic *efx) -{ - struct efx_mac_operations *old_mac_op = efx->mac_op; - struct falcon_nic_data *nic_data = efx->nic_data; - unsigned int stats_done_offset; - - WARN_ON(!mutex_is_locked(&efx->mac_lock)); - WARN_ON(nic_data->stats_disable_count == 0); - - efx->mac_op = (EFX_IS10G(efx) ? - &falcon_xmac_operations : &falcon_gmac_operations); - - if (EFX_IS10G(efx)) - stats_done_offset = XgDmaDone_offset; - else - stats_done_offset = GDmaDone_offset; - nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset; - - if (old_mac_op == efx->mac_op) - return; - - falcon_clock_mac(efx); - - netif_dbg(efx, hw, efx->net_dev, "selected %cMAC\n", - EFX_IS10G(efx) ? 'X' : 'G'); - /* Not all macs support a mac-level link state */ - efx->xmac_poll_required = false; - falcon_reset_macs(efx); -} - /* This call is responsible for hooking in the MAC and PHY operations */ static int falcon_probe_port(struct efx_nic *efx) { + struct falcon_nic_data *nic_data = efx->nic_data; int rc; switch (efx->phy_type) { case PHY_TYPE_SFX7101: efx->phy_op = &falcon_sfx7101_phy_ops; break; - case PHY_TYPE_SFT9001A: - case PHY_TYPE_SFT9001B: - efx->phy_op = &falcon_sft9001_phy_ops; - break; case PHY_TYPE_QT2022C2: case PHY_TYPE_QT2025C: efx->phy_op = &falcon_qt202x_phy_ops; @@ -937,6 +866,7 @@ static int falcon_probe_port(struct efx_nic *efx) (u64)efx->stats_buffer.dma_addr, efx->stats_buffer.addr, (u64)virt_to_phys(efx->stats_buffer.addr)); + nic_data->stats_dma_done = efx->stats_buffer.addr + XgDmaDone_offset; return 0; } @@ -1201,7 +1131,7 @@ static void falcon_monitor(struct efx_nic *efx) falcon_stop_nic_stats(efx); falcon_deconfigure_mac_wrapper(efx); - falcon_switch_mac(efx); + falcon_reset_macs(efx); rc = efx->mac_op->reconfigure(efx); BUG_ON(rc); @@ -1210,8 +1140,7 @@ static void falcon_monitor(struct efx_nic *efx) efx_link_status_changed(efx); } - if (EFX_IS10G(efx)) - falcon_poll_xmac(efx); + falcon_poll_xmac(efx); } /* Zeroes out the SRAM contents. This routine must be called in @@ -1604,16 +1533,6 @@ static int falcon_init_nic(struct efx_nic *efx) EFX_SET_OWORD_FIELD(temp, FRF_AB_ONCHIP_SRAM, 1); efx_writeo(efx, &temp, FR_AB_NIC_STAT); - /* Set the source of the GMAC clock */ - if (efx_nic_rev(efx) == EFX_REV_FALCON_B0) { - efx_reado(efx, &temp, FR_AB_GPIO_CTL); - EFX_SET_OWORD_FIELD(temp, FRF_AB_USE_NIC_CLK, true); - efx_writeo(efx, &temp, FR_AB_GPIO_CTL); - } - - /* Select the correct MAC */ - falcon_clock_mac(efx); - rc = falcon_reset_sram(efx); if (rc) return rc; diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index 3d950c2cf205..bf029b3d3b0a 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c @@ -26,7 +26,6 @@ /* Board types */ #define FALCON_BOARD_SFE4001 0x01 #define FALCON_BOARD_SFE4002 0x02 -#define FALCON_BOARD_SFN4111T 0x51 #define FALCON_BOARD_SFN4112F 0x52 /* Board temperature is about 15°C above ambient when air flow is @@ -142,17 +141,17 @@ static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask) #endif /* CONFIG_SENSORS_LM87 */ /***************************************************************************** - * Support for the SFE4001 and SFN4111T NICs. + * Support for the SFE4001 NIC. * * The SFE4001 does not power-up fully at reset due to its high power * consumption. We control its power via a PCA9539 I/O expander. - * Both boards have a MAX6647 temperature monitor which we expose to + * It also has a MAX6647 temperature monitor which we expose to * the lm90 driver. * * This also provides minimal support for reflashing the PHY, which is * initiated by resetting it with the FLASH_CFG_1 pin pulled down. * On SFE4001 rev A2 and later this is connected to the 3V3X output of - * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3. + * the IO-expander. * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually * exclusive with the network device being open. */ @@ -304,34 +303,6 @@ fail_on: return rc; } -static int sfn4111t_reset(struct efx_nic *efx) -{ - struct falcon_board *board = falcon_board(efx); - efx_oword_t reg; - - /* GPIO 3 and the GPIO register are shared with I2C, so block that */ - i2c_lock_adapter(&board->i2c_adap); - - /* Pull RST_N (GPIO 2) low then let it up again, setting the - * FLASH_CFG_1 strap (GPIO 3) appropriately. Only change the - * output enables; the output levels should always be 0 (low) - * and we rely on external pull-ups. */ - efx_reado(efx, ®, FR_AB_GPIO_CTL); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, true); - efx_writeo(efx, ®, FR_AB_GPIO_CTL); - msleep(1000); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO2_OEN, false); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GPIO3_OEN, - !!(efx->phy_mode & PHY_MODE_SPECIAL)); - efx_writeo(efx, ®, FR_AB_GPIO_CTL); - msleep(1); - - i2c_unlock_adapter(&board->i2c_adap); - - ssleep(1); - return 0; -} - static ssize_t show_phy_flash_cfg(struct device *dev, struct device_attribute *attr, char *buf) { @@ -363,10 +334,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev, efx->phy_mode = new_mode; if (new_mode & PHY_MODE_SPECIAL) falcon_stop_nic_stats(efx); - if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001) - err = sfe4001_poweron(efx); - else - err = sfn4111t_reset(efx); + err = sfe4001_poweron(efx); if (!err) err = efx_reconfigure_port(efx); if (!(new_mode & PHY_MODE_SPECIAL)) @@ -479,83 +447,6 @@ fail_hwmon: return rc; } -static int sfn4111t_check_hw(struct efx_nic *efx) -{ - s32 status; - - /* If XAUI link is up then do not monitor */ - if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required) - return 0; - - /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */ - status = i2c_smbus_read_byte_data(falcon_board(efx)->hwmon_client, - MAX664X_REG_RSL); - if (status < 0) - return -EIO; - if (status & 0x57) - return -ERANGE; - return 0; -} - -static void sfn4111t_fini(struct efx_nic *efx) -{ - netif_info(efx, drv, efx->net_dev, "%s\n", __func__); - - device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - i2c_unregister_device(falcon_board(efx)->hwmon_client); -} - -static struct i2c_board_info sfn4111t_a0_hwmon_info = { - I2C_BOARD_INFO("max6647", 0x4e), -}; - -static struct i2c_board_info sfn4111t_r5_hwmon_info = { - I2C_BOARD_INFO("max6646", 0x4d), -}; - -static void sfn4111t_init_phy(struct efx_nic *efx) -{ - if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { - if (sft9001_wait_boot(efx) != -EINVAL) - return; - - efx->phy_mode = PHY_MODE_SPECIAL; - falcon_stop_nic_stats(efx); - } - - sfn4111t_reset(efx); - sft9001_wait_boot(efx); -} - -static int sfn4111t_init(struct efx_nic *efx) -{ - struct falcon_board *board = falcon_board(efx); - int rc; - - board->hwmon_client = - i2c_new_device(&board->i2c_adap, - (board->minor < 5) ? - &sfn4111t_a0_hwmon_info : - &sfn4111t_r5_hwmon_info); - if (!board->hwmon_client) - return -EIO; - - rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg); - if (rc) - goto fail_hwmon; - - if (efx->phy_mode & PHY_MODE_SPECIAL) - /* PHY may not generate a 156.25 MHz clock and MAC - * stats fetch will fail. */ - falcon_stop_nic_stats(efx); - - return 0; - -fail_hwmon: - i2c_unregister_device(board->hwmon_client); - return rc; -} - /***************************************************************************** * Support for the SFE4002 * @@ -712,16 +603,6 @@ static const struct falcon_board_type board_types[] = { .set_id_led = sfe4002_set_id_led, .monitor = sfe4002_check_hw, }, - { - .id = FALCON_BOARD_SFN4111T, - .ref_model = "SFN4111T", - .gen_type = "100/1000/10GBASE-T adapter", - .init = sfn4111t_init, - .init_phy = sfn4111t_init_phy, - .fini = sfn4111t_fini, - .set_id_led = tenxpress_set_id_led, - .monitor = sfn4111t_check_hw, - }, { .id = FALCON_BOARD_SFN4112F, .ref_model = "SFN4112F", diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c deleted file mode 100644 index 7dadfcbd6ce7..000000000000 --- a/drivers/net/sfc/falcon_gmac.c +++ /dev/null @@ -1,230 +0,0 @@ -/**************************************************************************** - * Driver for Solarflare Solarstorm network controllers and boards - * Copyright 2005-2006 Fen Systems Ltd. - * Copyright 2006-2009 Solarflare Communications Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, incorporated herein by reference. - */ - -#include -#include "net_driver.h" -#include "efx.h" -#include "nic.h" -#include "mac.h" -#include "regs.h" -#include "io.h" - -/************************************************************************** - * - * MAC operations - * - *************************************************************************/ - -static int falcon_reconfigure_gmac(struct efx_nic *efx) -{ - struct efx_link_state *link_state = &efx->link_state; - bool loopback, tx_fc, rx_fc, bytemode; - int if_mode; - unsigned int max_frame_len; - efx_oword_t reg; - - /* Configuration register 1 */ - tx_fc = (link_state->fc & EFX_FC_TX) || !link_state->fd; - rx_fc = !!(link_state->fc & EFX_FC_RX); - loopback = (efx->loopback_mode == LOOPBACK_GMAC); - bytemode = (link_state->speed == 1000); - - EFX_POPULATE_OWORD_5(reg, - FRF_AB_GM_LOOP, loopback, - FRF_AB_GM_TX_EN, 1, - FRF_AB_GM_TX_FC_EN, tx_fc, - FRF_AB_GM_RX_EN, 1, - FRF_AB_GM_RX_FC_EN, rx_fc); - efx_writeo(efx, ®, FR_AB_GM_CFG1); - udelay(10); - - /* Configuration register 2 */ - if_mode = (bytemode) ? 2 : 1; - EFX_POPULATE_OWORD_5(reg, - FRF_AB_GM_IF_MODE, if_mode, - FRF_AB_GM_PAD_CRC_EN, 1, - FRF_AB_GM_LEN_CHK, 1, - FRF_AB_GM_FD, link_state->fd, - FRF_AB_GM_PAMBL_LEN, 0x7/*datasheet recommended */); - - efx_writeo(efx, ®, FR_AB_GM_CFG2); - udelay(10); - - /* Max frame len register */ - max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu); - EFX_POPULATE_OWORD_1(reg, FRF_AB_GM_MAX_FLEN, max_frame_len); - efx_writeo(efx, ®, FR_AB_GM_MAX_FLEN); - udelay(10); - - /* FIFO configuration register 0 */ - EFX_POPULATE_OWORD_5(reg, - FRF_AB_GMF_FTFENREQ, 1, - FRF_AB_GMF_STFENREQ, 1, - FRF_AB_GMF_FRFENREQ, 1, - FRF_AB_GMF_SRFENREQ, 1, - FRF_AB_GMF_WTMENREQ, 1); - efx_writeo(efx, ®, FR_AB_GMF_CFG0); - udelay(10); - - /* FIFO configuration register 1 */ - EFX_POPULATE_OWORD_2(reg, - FRF_AB_GMF_CFGFRTH, 0x12, - FRF_AB_GMF_CFGXOFFRTX, 0xffff); - efx_writeo(efx, ®, FR_AB_GMF_CFG1); - udelay(10); - - /* FIFO configuration register 2 */ - EFX_POPULATE_OWORD_2(reg, - FRF_AB_GMF_CFGHWM, 0x3f, - FRF_AB_GMF_CFGLWM, 0xa); - efx_writeo(efx, ®, FR_AB_GMF_CFG2); - udelay(10); - - /* FIFO configuration register 3 */ - EFX_POPULATE_OWORD_2(reg, - FRF_AB_GMF_CFGHWMFT, 0x1c, - FRF_AB_GMF_CFGFTTH, 0x08); - efx_writeo(efx, ®, FR_AB_GMF_CFG3); - udelay(10); - - /* FIFO configuration register 4 */ - EFX_POPULATE_OWORD_1(reg, FRF_AB_GMF_HSTFLTRFRM_PAUSE, 1); - efx_writeo(efx, ®, FR_AB_GMF_CFG4); - udelay(10); - - /* FIFO configuration register 5 */ - efx_reado(efx, ®, FR_AB_GMF_CFG5); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGBYTMODE, bytemode); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_CFGHDPLX, !link_state->fd); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTDRPLT64, !link_state->fd); - EFX_SET_OWORD_FIELD(reg, FRF_AB_GMF_HSTFLTRFRMDC_PAUSE, 0); - efx_writeo(efx, ®, FR_AB_GMF_CFG5); - udelay(10); - - /* MAC address */ - EFX_POPULATE_OWORD_4(reg, - FRF_AB_GM_ADR_B0, efx->net_dev->dev_addr[5], - FRF_AB_GM_ADR_B1, efx->net_dev->dev_addr[4], - FRF_AB_GM_ADR_B2, efx->net_dev->dev_addr[3], - FRF_AB_GM_ADR_B3, efx->net_dev->dev_addr[2]); - efx_writeo(efx, ®, FR_AB_GM_ADR1); - udelay(10); - EFX_POPULATE_OWORD_2(reg, - FRF_AB_GM_ADR_B4, efx->net_dev->dev_addr[1], - FRF_AB_GM_ADR_B5, efx->net_dev->dev_addr[0]); - efx_writeo(efx, ®, FR_AB_GM_ADR2); - udelay(10); - - falcon_reconfigure_mac_wrapper(efx); - - return 0; -} - -static void falcon_update_stats_gmac(struct efx_nic *efx) -{ - struct efx_mac_stats *mac_stats = &efx->mac_stats; - unsigned long old_rx_pause, old_tx_pause; - unsigned long new_rx_pause, new_tx_pause; - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - old_rx_pause = mac_stats->rx_pause; - old_tx_pause = mac_stats->tx_pause; - - /* Update MAC stats from DMAed values */ - FALCON_STAT(efx, GRxGoodOct, rx_good_bytes); - FALCON_STAT(efx, GRxBadOct, rx_bad_bytes); - FALCON_STAT(efx, GRxMissPkt, rx_missed); - FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier); - FALCON_STAT(efx, GRxPausePkt, rx_pause); - FALCON_STAT(efx, GRxBadPkt, rx_bad); - FALCON_STAT(efx, GRxUcastPkt, rx_unicast); - FALCON_STAT(efx, GRxMcastPkt, rx_multicast); - FALCON_STAT(efx, GRxBcastPkt, rx_broadcast); - FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64); - FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64); - FALCON_STAT(efx, GRx64Pkt, rx_64); - FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127); - FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255); - FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511); - FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023); - FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx); - FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo); - FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo); - FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx); - FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo); - FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo); - FALCON_STAT(efx, GTxGoodBadOct, tx_bytes); - FALCON_STAT(efx, GTxGoodOct, tx_good_bytes); - FALCON_STAT(efx, GTxSglColPkt, tx_single_collision); - FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision); - FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision); - FALCON_STAT(efx, GTxDefPkt, tx_deferred); - FALCON_STAT(efx, GTxLateCol, tx_late_collision); - FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred); - FALCON_STAT(efx, GTxPausePkt, tx_pause); - FALCON_STAT(efx, GTxBadPkt, tx_bad); - FALCON_STAT(efx, GTxUcastPkt, tx_unicast); - FALCON_STAT(efx, GTxMcastPkt, tx_multicast); - FALCON_STAT(efx, GTxBcastPkt, tx_broadcast); - FALCON_STAT(efx, GTxLt64Pkt, tx_lt64); - FALCON_STAT(efx, GTx64Pkt, tx_64); - FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127); - FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255); - FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511); - FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023); - FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx); - FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo); - FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo); - FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp); - FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error); - FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error); - - /* Pause frames are erroneously counted as errors (SFC bug 3269) */ - new_rx_pause = mac_stats->rx_pause; - new_tx_pause = mac_stats->tx_pause; - mac_stats->rx_bad -= (new_rx_pause - old_rx_pause); - mac_stats->tx_bad -= (new_tx_pause - old_tx_pause); - - /* Derive stats that the MAC doesn't provide directly */ - mac_stats->tx_bad_bytes = - mac_stats->tx_bytes - mac_stats->tx_good_bytes; - mac_stats->tx_packets = - mac_stats->tx_lt64 + mac_stats->tx_64 + - mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 + - mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 + - mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo + - mac_stats->tx_gtjumbo; - mac_stats->tx_collision = - mac_stats->tx_single_collision + - mac_stats->tx_multiple_collision + - mac_stats->tx_excessive_collision + - mac_stats->tx_late_collision; - mac_stats->rx_bytes = - mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes; - mac_stats->rx_packets = - mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 + - mac_stats->rx_64 + mac_stats->rx_65_to_127 + - mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 + - mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx + - mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo; - mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad; - mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64; -} - -static bool falcon_gmac_check_fault(struct efx_nic *efx) -{ - return false; -} - -struct efx_mac_operations falcon_gmac_operations = { - .reconfigure = falcon_reconfigure_gmac, - .update_stats = falcon_update_stats_gmac, - .check_fault = falcon_gmac_check_fault, -}; diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h index f1aa5f374890..7a6e5ca0290e 100644 --- a/drivers/net/sfc/mac.h +++ b/drivers/net/sfc/mac.h @@ -13,7 +13,6 @@ #include "net_driver.h" -extern struct efx_mac_operations falcon_gmac_operations; extern struct efx_mac_operations falcon_xmac_operations; extern struct efx_mac_operations efx_mcdi_mac_operations; extern void falcon_reconfigure_xmac_core(struct efx_nic *efx); diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index eeaf0bd64bd3..98d946020429 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -286,46 +286,24 @@ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) */ void efx_mdio_an_reconfigure(struct efx_nic *efx) { - bool xnp = (efx->link_advertising & ADVERTISED_10000baseT_Full - || EFX_WORKAROUND_13204(efx)); int reg; WARN_ON(!(efx->mdio.mmds & MDIO_DEVS_AN)); /* Set up the base page */ - reg = ADVERTISE_CSMA; - if (efx->link_advertising & ADVERTISED_10baseT_Half) - reg |= ADVERTISE_10HALF; - if (efx->link_advertising & ADVERTISED_10baseT_Full) - reg |= ADVERTISE_10FULL; - if (efx->link_advertising & ADVERTISED_100baseT_Half) - reg |= ADVERTISE_100HALF; - if (efx->link_advertising & ADVERTISED_100baseT_Full) - reg |= ADVERTISE_100FULL; - if (xnp) - reg |= ADVERTISE_RESV; - else if (efx->link_advertising & (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) - reg |= ADVERTISE_NPAGE; + reg = ADVERTISE_CSMA | ADVERTISE_RESV; if (efx->link_advertising & ADVERTISED_Pause) reg |= ADVERTISE_PAUSE_CAP; if (efx->link_advertising & ADVERTISED_Asym_Pause) reg |= ADVERTISE_PAUSE_ASYM; efx_mdio_write(efx, MDIO_MMD_AN, MDIO_AN_ADVERTISE, reg); - /* Set up the (extended) next page if necessary */ - if (efx->phy_op->set_npage_adv) - efx->phy_op->set_npage_adv(efx, efx->link_advertising); + /* Set up the (extended) next page */ + efx->phy_op->set_npage_adv(efx, efx->link_advertising); /* Enable and restart AN */ reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_CTRL1); - reg |= MDIO_AN_CTRL1_ENABLE; - if (!(EFX_WORKAROUND_15195(efx) && LOOPBACK_EXTERNAL(efx))) - reg |= MDIO_AN_CTRL1_RESTART; - if (xnp) - reg |= MDIO_AN_CTRL1_XNP; - else - reg &= ~MDIO_AN_CTRL1_XNP; + reg |= MDIO_AN_CTRL1_ENABLE | MDIO_AN_CTRL1_RESTART | MDIO_AN_CTRL1_XNP; efx_mdio_write(efx, MDIO_MMD_AN, MDIO_CTRL1, reg); } diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index b3f2bf436735..845be71bef63 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -406,8 +406,6 @@ enum efx_int_mode { }; #define EFX_INT_MODE_USE_MSI(x) (((x)->interrupt_mode) <= EFX_INT_MODE_MSI) -#define EFX_IS10G(efx) ((efx)->link_state.speed == 10000) - enum nic_state { STATE_INIT = 0, STATE_RUNNING = 1, diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h index 5bc26137257b..7ab07575c6d3 100644 --- a/drivers/net/sfc/phy.h +++ b/drivers/net/sfc/phy.h @@ -11,17 +11,12 @@ #define EFX_PHY_H /**************************************************************************** - * 10Xpress (SFX7101 and SFT9001) PHYs + * 10Xpress (SFX7101) PHY */ extern struct efx_phy_operations falcon_sfx7101_phy_ops; -extern struct efx_phy_operations falcon_sft9001_phy_ops; extern void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode); -/* Wait for the PHY to boot. Return 0 on success, -EINVAL if the PHY failed - * to boot due to corrupt flash, or some other negative error code. */ -extern int sft9001_wait_boot(struct efx_nic *efx); - /**************************************************************************** * AMCC/Quake QT202x PHYs */ diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 6791be90c2fe..1bc6c48c96ee 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -19,10 +19,7 @@ #include "workarounds.h" #include "selftest.h" -/* We expect these MMDs to be in the package. SFT9001 also has a - * clause 22 extension MMD, but since it doesn't have all the generic - * MMD registers it is pointless to include it here. - */ +/* We expect these MMDs to be in the package. */ #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ MDIO_DEVS_PCS | \ MDIO_DEVS_PHYXS | \ @@ -33,12 +30,6 @@ (1 << LOOPBACK_PMAPMD) | \ (1 << LOOPBACK_PHYXS_WS)) -#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ - (1 << LOOPBACK_PHYXS) | \ - (1 << LOOPBACK_PCS) | \ - (1 << LOOPBACK_PMAPMD) | \ - (1 << LOOPBACK_PHYXS_WS)) - /* We complain if we fail to see the link partner as 10G capable this many * times in a row (must be > 1 as sampling the autoneg. registers is racy) */ @@ -50,9 +41,8 @@ #define PMA_PMD_EXT_GMII_EN_WIDTH 1 #define PMA_PMD_EXT_CLK_OUT_LBN 2 #define PMA_PMD_EXT_CLK_OUT_WIDTH 1 -#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */ +#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 #define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 -#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */ #define PMA_PMD_EXT_CLK312_WIDTH 1 #define PMA_PMD_EXT_LPOWER_LBN 12 #define PMA_PMD_EXT_LPOWER_WIDTH 1 @@ -84,7 +74,6 @@ #define PMA_PMD_LED_FLASH (3) #define PMA_PMD_LED_MASK 3 /* All LEDs under hardware control */ -#define SFT9001_PMA_PMD_LED_DEFAULT 0 /* Green and Amber under hardware control, Red off */ #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) @@ -98,31 +87,7 @@ #define PMA_PMD_SPEED_LBN 4 #define PMA_PMD_SPEED_WIDTH 4 -/* Cable diagnostics - SFT9001 only */ -#define PMA_PMD_CDIAG_CTRL_REG 49213 -#define CDIAG_CTRL_IMMED_LBN 15 -#define CDIAG_CTRL_BRK_LINK_LBN 12 -#define CDIAG_CTRL_IN_PROG_LBN 11 -#define CDIAG_CTRL_LEN_UNIT_LBN 10 -#define CDIAG_CTRL_LEN_METRES 1 -#define PMA_PMD_CDIAG_RES_REG 49174 -#define CDIAG_RES_A_LBN 12 -#define CDIAG_RES_B_LBN 8 -#define CDIAG_RES_C_LBN 4 -#define CDIAG_RES_D_LBN 0 -#define CDIAG_RES_WIDTH 4 -#define CDIAG_RES_OPEN 2 -#define CDIAG_RES_OK 1 -#define CDIAG_RES_INVALID 0 -/* Set of 4 registers for pairs A-D */ -#define PMA_PMD_CDIAG_LEN_REG 49175 - -/* Serdes control registers - SFT9001 only */ -#define PMA_PMD_CSERDES_CTRL_REG 64258 -/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */ -#define PMA_PMD_CSERDES_DEFAULT 0x000f - -/* Misc register defines - SFX7101 only */ +/* Misc register defines */ #define PCS_CLOCK_CTRL_REG 55297 #define PLL312_RST_N_LBN 2 @@ -185,121 +150,17 @@ struct tenxpress_phy_data { int bad_lp_tries; }; -static ssize_t show_phy_short_reach(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - int reg; - - reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR); - return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT)); -} - -static ssize_t set_phy_short_reach(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); - int rc; - - rtnl_lock(); - if (efx->state != STATE_RUNNING) { - rc = -EBUSY; - } else { - efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, - MDIO_PMA_10GBT_TXPWR_SHORT, - count != 0 && *buf != '0'); - rc = efx_reconfigure_port(efx); - } - rtnl_unlock(); - - return rc < 0 ? rc : (ssize_t)count; -} - -static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, - set_phy_short_reach); - -int sft9001_wait_boot(struct efx_nic *efx) -{ - unsigned long timeout = jiffies + HZ + 1; - int boot_stat; - - for (;;) { - boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS, - PCS_BOOT_STATUS_REG); - if (boot_stat >= 0) { - netif_dbg(efx, hw, efx->net_dev, - "PHY boot status = %#x\n", boot_stat); - switch (boot_stat & - ((1 << PCS_BOOT_FATAL_ERROR_LBN) | - (3 << PCS_BOOT_PROGRESS_LBN) | - (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) | - (1 << PCS_BOOT_CODE_STARTED_LBN))) { - case ((1 << PCS_BOOT_FATAL_ERROR_LBN) | - (PCS_BOOT_PROGRESS_CHECKSUM << - PCS_BOOT_PROGRESS_LBN)): - case ((1 << PCS_BOOT_FATAL_ERROR_LBN) | - (PCS_BOOT_PROGRESS_INIT << - PCS_BOOT_PROGRESS_LBN) | - (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)): - return -EINVAL; - case ((PCS_BOOT_PROGRESS_WAIT_MDIO << - PCS_BOOT_PROGRESS_LBN) | - (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)): - return (efx->phy_mode & PHY_MODE_SPECIAL) ? - 0 : -EIO; - case ((PCS_BOOT_PROGRESS_JUMP << - PCS_BOOT_PROGRESS_LBN) | - (1 << PCS_BOOT_CODE_STARTED_LBN)): - case ((PCS_BOOT_PROGRESS_JUMP << - PCS_BOOT_PROGRESS_LBN) | - (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) | - (1 << PCS_BOOT_CODE_STARTED_LBN)): - return (efx->phy_mode & PHY_MODE_SPECIAL) ? - -EIO : 0; - default: - if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN)) - return -EIO; - break; - } - } - - if (time_after_eq(jiffies, timeout)) - return -ETIMEDOUT; - - msleep(50); - } -} - static int tenxpress_init(struct efx_nic *efx) { - int reg; - - if (efx->phy_type == PHY_TYPE_SFX7101) { - /* Enable 312.5 MHz clock */ - efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, - 1 << CLK312_EN_LBN); - } else { - /* Enable 312.5 MHz clock and GMII */ - reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); - reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | - (1 << PMA_PMD_EXT_CLK_OUT_LBN) | - (1 << PMA_PMD_EXT_CLK312_LBN) | - (1 << PMA_PMD_EXT_ROBUST_LBN)); - - efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); - efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, - GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN, - false); - } + /* Enable 312.5 MHz clock */ + efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, + 1 << CLK312_EN_LBN); /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ - if (efx->phy_type == PHY_TYPE_SFX7101) { - efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, - 1 << PMA_PMA_LED_ACTIVITY_LBN, true); - efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, - SFX7101_PMA_PMD_LED_DEFAULT); - } + efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, + 1 << PMA_PMA_LED_ACTIVITY_LBN, true); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, + SFX7101_PMA_PMD_LED_DEFAULT); return 0; } @@ -307,7 +168,6 @@ static int tenxpress_init(struct efx_nic *efx) static int tenxpress_phy_probe(struct efx_nic *efx) { struct tenxpress_phy_data *phy_data; - int rc; /* Allocate phy private storage */ phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); @@ -316,42 +176,15 @@ static int tenxpress_phy_probe(struct efx_nic *efx) efx->phy_data = phy_data; phy_data->phy_mode = efx->phy_mode; - /* Create any special files */ - if (efx->phy_type == PHY_TYPE_SFT9001B) { - rc = device_create_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - if (rc) - goto fail; - } - - if (efx->phy_type == PHY_TYPE_SFX7101) { - efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; - efx->mdio.mode_support = MDIO_SUPPORTS_C45; - - efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; + efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; + efx->mdio.mode_support = MDIO_SUPPORTS_C45; - efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | - ADVERTISED_10000baseT_Full); - } else { - efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; - efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; - efx->loopback_modes = (SFT9001_LOOPBACKS | - FALCON_XMAC_LOOPBACKS | - FALCON_GMAC_LOOPBACKS); - - efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | - ADVERTISED_10000baseT_Full | - ADVERTISED_1000baseT_Full | - ADVERTISED_100baseT_Full); - } + efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full); return 0; - -fail: - kfree(efx->phy_data); - efx->phy_data = NULL; - return rc; } static int tenxpress_phy_init(struct efx_nic *efx) @@ -361,16 +194,6 @@ static int tenxpress_phy_init(struct efx_nic *efx) falcon_board(efx)->type->init_phy(efx); if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { - if (efx->phy_type == PHY_TYPE_SFT9001A) { - int reg; - reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG); - reg |= (1 << PMA_PMD_EXT_SSR_LBN); - efx_mdio_write(efx, MDIO_MMD_PMAPMD, - PMA_PMD_XCONTROL_REG, reg); - mdelay(200); - } - rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); if (rc < 0) return rc; @@ -403,7 +226,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) { int rc, reg; - /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so + /* The XGMAC clock is driven from the SFX7101 312MHz clock, so * a special software reset can glitch the XGMAC sufficiently for stats * requests to fail. */ falcon_stop_nic_stats(efx); @@ -484,53 +307,18 @@ static bool sfx7101_link_ok(struct efx_nic *efx) MDIO_DEVS_PHYXS); } -static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) -{ - u32 reg; - - if (efx_phy_mode_disabled(efx->phy_mode)) - return false; - else if (efx->loopback_mode == LOOPBACK_GPHY) - return true; - else if (efx->loopback_mode) - return efx_mdio_links_ok(efx, - MDIO_DEVS_PMAPMD | - MDIO_DEVS_PHYXS); - - /* We must use the same definition of link state as LASI, - * otherwise we can miss a link state transition - */ - if (ecmd->speed == 10000) { - reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); - return reg & MDIO_PCS_10GBRT_STAT1_BLKLK; - } else { - reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG); - return reg & (1 << C22EXT_STATUS_LINK_LBN); - } -} - static void tenxpress_ext_loopback(struct efx_nic *efx) { efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1, 1 << LOOPBACK_NEAR_LBN, efx->loopback_mode == LOOPBACK_PHYXS); - if (efx->phy_type != PHY_TYPE_SFX7101) - efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG, - 1 << GPHY_LOOPBACK_NEAR_LBN, - efx->loopback_mode == LOOPBACK_GPHY); } static void tenxpress_low_power(struct efx_nic *efx) { - if (efx->phy_type == PHY_TYPE_SFX7101) - efx_mdio_set_mmds_lpower( - efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), - TENXPRESS_REQUIRED_DEVS); - else - efx_mdio_set_flag( - efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, - 1 << PMA_PMD_EXT_LPOWER_LBN, - !!(efx->phy_mode & PHY_MODE_LOW_POWER)); + efx_mdio_set_mmds_lpower( + efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), + TENXPRESS_REQUIRED_DEVS); } static int tenxpress_phy_reconfigure(struct efx_nic *efx) @@ -550,12 +338,7 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx) if (loop_reset || phy_mode_change) { tenxpress_special_reset(efx); - - /* Reset XAUI if we were in 10G, and are staying - * in 10G. If we're moving into and out of 10G - * then xaui will be reset anyway */ - if (EFX_IS10G(efx)) - falcon_reset_xaui(efx); + falcon_reset_xaui(efx); } tenxpress_low_power(efx); @@ -578,29 +361,12 @@ static bool tenxpress_phy_poll(struct efx_nic *efx) { struct efx_link_state old_state = efx->link_state; - if (efx->phy_type == PHY_TYPE_SFX7101) { - efx->link_state.up = sfx7101_link_ok(efx); - efx->link_state.speed = 10000; - efx->link_state.fd = true; - efx->link_state.fc = efx_mdio_get_pause(efx); - - sfx7101_check_bad_lp(efx, efx->link_state.up); - } else { - struct ethtool_cmd ecmd; - - /* Check the LASI alarm first */ - if (efx->loopback_mode == LOOPBACK_NONE && - !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) & - MDIO_PMA_LASI_LSALARM)) - return false; + efx->link_state.up = sfx7101_link_ok(efx); + efx->link_state.speed = 10000; + efx->link_state.fd = true; + efx->link_state.fc = efx_mdio_get_pause(efx); - tenxpress_get_settings(efx, &ecmd); - - efx->link_state.up = sft9001_link_ok(efx, &ecmd); - efx->link_state.speed = ecmd.speed; - efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL); - efx->link_state.fc = efx_mdio_get_pause(efx); - } + sfx7101_check_bad_lp(efx, efx->link_state.up); return !efx_link_state_equal(&efx->link_state, &old_state); } @@ -621,10 +387,6 @@ static void sfx7101_phy_fini(struct efx_nic *efx) static void tenxpress_phy_remove(struct efx_nic *efx) { - if (efx->phy_type == PHY_TYPE_SFT9001B) - device_remove_file(&efx->pci_dev->dev, - &dev_attr_phy_short_reach); - kfree(efx->phy_data); efx->phy_data = NULL; } @@ -647,10 +409,7 @@ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) (PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN); break; default: - if (efx->phy_type == PHY_TYPE_SFX7101) - reg = SFX7101_PMA_PMD_LED_DEFAULT; - else - reg = SFT9001_PMA_PMD_LED_DEFAULT; + reg = SFX7101_PMA_PMD_LED_DEFAULT; break; } @@ -685,102 +444,12 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) return rc; } -static const char *const sft9001_test_names[] = { - "bist", - "cable.pairA.status", - "cable.pairB.status", - "cable.pairC.status", - "cable.pairD.status", - "cable.pairA.length", - "cable.pairB.length", - "cable.pairC.length", - "cable.pairD.length", -}; - -static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index) -{ - if (index < ARRAY_SIZE(sft9001_test_names)) - return sft9001_test_names[index]; - return NULL; -} - -static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) -{ - int rc = 0, rc2, i, ctrl_reg, res_reg; - - /* Initialise cable diagnostic results to unknown failure */ - for (i = 1; i < 9; ++i) - results[i] = -1; - - /* Run cable diagnostics; wait up to 5 seconds for them to complete. - * A cable fault is not a self-test failure, but a timeout is. */ - ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) | - (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN)); - if (flags & ETH_TEST_FL_OFFLINE) { - /* Break the link in order to run full diagnostics. We - * must reset the PHY to resume normal service. */ - ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN); - } - efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG, - ctrl_reg); - i = 0; - while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) & - (1 << CDIAG_CTRL_IN_PROG_LBN)) { - if (++i == 50) { - rc = -ETIMEDOUT; - goto out; - } - msleep(100); - } - res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG); - for (i = 0; i < 4; i++) { - int pair_res = - (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH)) - & ((1 << CDIAG_RES_WIDTH) - 1); - int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, - PMA_PMD_CDIAG_LEN_REG + i); - if (pair_res == CDIAG_RES_OK) - results[1 + i] = 1; - else if (pair_res == CDIAG_RES_INVALID) - results[1 + i] = -1; - else - results[1 + i] = -pair_res; - if (pair_res != CDIAG_RES_INVALID && - pair_res != CDIAG_RES_OPEN && - len_reg != 0xffff) - results[5 + i] = len_reg; - } - -out: - if (flags & ETH_TEST_FL_OFFLINE) { - /* Reset, running the BIST and then resuming normal service. */ - rc2 = tenxpress_special_reset(efx); - results[0] = rc2 ? -1 : 1; - if (!rc) - rc = rc2; - - efx_mdio_an_reconfigure(efx); - } - - return rc; -} - static void tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { u32 adv = 0, lpa = 0; int reg; - if (efx->phy_type != PHY_TYPE_SFX7101) { - reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL); - if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) - adv |= ADVERTISED_1000baseT_Full; - reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS); - if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) - lpa |= ADVERTISED_1000baseT_Half; - if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) - lpa |= ADVERTISED_1000baseT_Full; - } reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); if (reg & MDIO_AN_10GBT_CTRL_ADV10G) adv |= ADVERTISED_10000baseT_Full; @@ -790,23 +459,9 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); - if (efx->phy_type != PHY_TYPE_SFX7101) { - ecmd->supported |= (SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full); - if (ecmd->speed != SPEED_10000) { - ecmd->eth_tp_mdix = - (efx_mdio_read(efx, MDIO_MMD_PMAPMD, - PMA_PMD_XSTATUS_REG) & - (1 << PMA_PMD_XSTAT_MDIX_LBN)) - ? ETH_TP_MDI_X : ETH_TP_MDI; - } - } - /* In loopback, the PHY automatically brings up the correct interface, * but doesn't advertise the correct speed. So override it */ - if (efx->loopback_mode == LOOPBACK_GPHY) - ecmd->speed = SPEED_1000; - else if (LOOPBACK_EXTERNAL(efx)) + if (LOOPBACK_EXTERNAL(efx)) ecmd->speed = SPEED_10000; } @@ -825,16 +480,6 @@ static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) advertising & ADVERTISED_10000baseT_Full); } -static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) -{ - efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL, - 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, - advertising & ADVERTISED_1000baseT_Full); - efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, - MDIO_AN_10GBT_CTRL_ADV10G, - advertising & ADVERTISED_10000baseT_Full); -} - struct efx_phy_operations falcon_sfx7101_phy_ops = { .probe = tenxpress_phy_probe, .init = tenxpress_phy_init, @@ -849,18 +494,3 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { .test_name = sfx7101_test_name, .run_tests = sfx7101_run_tests, }; - -struct efx_phy_operations falcon_sft9001_phy_ops = { - .probe = tenxpress_phy_probe, - .init = tenxpress_phy_init, - .reconfigure = tenxpress_phy_reconfigure, - .poll = tenxpress_phy_poll, - .fini = efx_port_dummy_op_void, - .remove = tenxpress_phy_remove, - .get_settings = tenxpress_get_settings, - .set_settings = tenxpress_set_settings, - .set_npage_adv = sft9001_set_npage_adv, - .test_alive = efx_mdio_test_alive, - .test_name = sft9001_test_name, - .run_tests = sft9001_run_tests, -}; diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h index 782e45a613d6..e0d63083c3a8 100644 --- a/drivers/net/sfc/workarounds.h +++ b/drivers/net/sfc/workarounds.h @@ -19,9 +19,7 @@ #define EFX_WORKAROUND_FALCON_A(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) #define EFX_WORKAROUND_FALCON_AB(efx) (efx_nic_rev(efx) <= EFX_REV_FALCON_B0) #define EFX_WORKAROUND_SIENA(efx) (efx_nic_rev(efx) == EFX_REV_SIENA_A0) -#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx) -#define EFX_WORKAROUND_SFT9001(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A || \ - (efx)->phy_type == PHY_TYPE_SFT9001B) +#define EFX_WORKAROUND_10G(efx) 1 /* XAUI resets if link not detected */ #define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS @@ -58,9 +56,4 @@ /* Leak overlength packets rather than free */ #define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A -/* Need to send XNP pages for 100BaseT */ -#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001 -/* Don't restart AN in near-side loopback */ -#define EFX_WORKAROUND_15195 EFX_WORKAROUND_SFT9001 - #endif /* EFX_WORKAROUNDS_H */ -- cgit v1.2.3 From 7e51b439f147670c4ddd2bf6ca4567592b5312de Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 22 Sep 2010 10:00:47 +0000 Subject: sfc: Add support for SFE4003 board and TXC43128 PHY This board never went into production, but some engineering samples are in use. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/Makefile | 3 +- drivers/net/sfc/falcon.c | 3 + drivers/net/sfc/falcon_boards.c | 80 ++++++ drivers/net/sfc/phy.h | 11 + drivers/net/sfc/txc43128_phy.c | 560 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 656 insertions(+), 1 deletion(-) create mode 100644 drivers/net/sfc/txc43128_phy.c (limited to 'drivers/net/sfc/Makefile') diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index 39f7c1bc2405..ab31c7124db1 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile @@ -1,7 +1,8 @@ sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ falcon_xmac.o mcdi_mac.o \ selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ - tenxpress.o falcon_boards.o mcdi.o mcdi_phy.o + tenxpress.o txc43128_phy.o falcon_boards.o \ + mcdi.o mcdi_phy.o sfc-$(CONFIG_SFC_MTD) += mtd.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 254a599935c1..267019bb2b15 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -831,6 +831,9 @@ static int falcon_probe_port(struct efx_nic *efx) case PHY_TYPE_QT2025C: efx->phy_op = &falcon_qt202x_phy_ops; break; + case PHY_TYPE_TXC43128: + efx->phy_op = &falcon_txc_phy_ops; + break; default: netif_err(efx, probe, efx->net_dev, "Unknown PHY type %d\n", efx->phy_type); diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c index bf029b3d3b0a..cfc6a5b5a477 100644 --- a/drivers/net/sfc/falcon_boards.c +++ b/drivers/net/sfc/falcon_boards.c @@ -26,6 +26,7 @@ /* Board types */ #define FALCON_BOARD_SFE4001 0x01 #define FALCON_BOARD_SFE4002 0x02 +#define FALCON_BOARD_SFE4003 0x03 #define FALCON_BOARD_SFN4112F 0x52 /* Board temperature is about 15°C above ambient when air flow is @@ -582,6 +583,75 @@ static int sfn4112f_init(struct efx_nic *efx) return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs); } +/***************************************************************************** + * Support for the SFE4003 + * + */ +static u8 sfe4003_lm87_channel = 0x03; /* use AIN not FAN inputs */ + +static const u8 sfe4003_lm87_regs[] = { + LM87_IN_LIMITS(0, 0x67, 0x7f), /* 2.5V: 1.5V +/- 10% */ + LM87_IN_LIMITS(1, 0x4c, 0x5e), /* Vccp1: 1.2V +/- 10% */ + LM87_IN_LIMITS(2, 0xac, 0xd4), /* 3.3V: 3.3V +/- 10% */ + LM87_IN_LIMITS(4, 0xac, 0xe0), /* 12V: 10.8-14V */ + LM87_IN_LIMITS(5, 0x3f, 0x4f), /* Vccp2: 1.0V +/- 10% */ + LM87_TEMP_INT_LIMITS(0, 70 + FALCON_BOARD_TEMP_BIAS), + 0 +}; + +static struct i2c_board_info sfe4003_hwmon_info = { + I2C_BOARD_INFO("lm87", 0x2e), + .platform_data = &sfe4003_lm87_channel, +}; + +/* Board-specific LED info. */ +#define SFE4003_RED_LED_GPIO 11 +#define SFE4003_LED_ON 1 +#define SFE4003_LED_OFF 0 + +static void sfe4003_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) +{ + struct falcon_board *board = falcon_board(efx); + + /* The LEDs were not wired to GPIOs before A3 */ + if (board->minor < 3 && board->major == 0) + return; + + falcon_txc_set_gpio_val( + efx, SFE4003_RED_LED_GPIO, + (mode == EFX_LED_ON) ? SFE4003_LED_ON : SFE4003_LED_OFF); +} + +static void sfe4003_init_phy(struct efx_nic *efx) +{ + struct falcon_board *board = falcon_board(efx); + + /* The LEDs were not wired to GPIOs before A3 */ + if (board->minor < 3 && board->major == 0) + return; + + falcon_txc_set_gpio_dir(efx, SFE4003_RED_LED_GPIO, TXC_GPIO_DIR_OUTPUT); + falcon_txc_set_gpio_val(efx, SFE4003_RED_LED_GPIO, SFE4003_LED_OFF); +} + +static int sfe4003_check_hw(struct efx_nic *efx) +{ + struct falcon_board *board = falcon_board(efx); + + /* A0/A1/A2 board rev. 4003s report a temperature fault the whole time + * (bad sensor) so we mask it out. */ + unsigned alarm_mask = + (board->major == 0 && board->minor <= 2) ? + ~LM87_ALARM_TEMP_EXT1 : ~0; + + return efx_check_lm87(efx, alarm_mask); +} + +static int sfe4003_init(struct efx_nic *efx) +{ + return efx_init_lm87(efx, &sfe4003_hwmon_info, sfe4003_lm87_regs); +} + static const struct falcon_board_type board_types[] = { { .id = FALCON_BOARD_SFE4001, @@ -603,6 +673,16 @@ static const struct falcon_board_type board_types[] = { .set_id_led = sfe4002_set_id_led, .monitor = sfe4002_check_hw, }, + { + .id = FALCON_BOARD_SFE4003, + .ref_model = "SFE4003", + .gen_type = "10GBASE-CX4 adapter", + .init = sfe4003_init, + .init_phy = sfe4003_init_phy, + .fini = efx_fini_lm87, + .set_id_led = sfe4003_set_id_led, + .monitor = sfe4003_check_hw, + }, { .id = FALCON_BOARD_SFN4112F, .ref_model = "SFN4112F", diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h index 7ab07575c6d3..1dab609757fb 100644 --- a/drivers/net/sfc/phy.h +++ b/drivers/net/sfc/phy.h @@ -36,6 +36,17 @@ extern struct efx_phy_operations falcon_qt202x_phy_ops; extern void falcon_qt202x_set_led(struct efx_nic *p, int led, int state); +/**************************************************************************** +* Transwitch CX4 retimer +*/ +extern struct efx_phy_operations falcon_txc_phy_ops; + +#define TXC_GPIO_DIR_INPUT 0 +#define TXC_GPIO_DIR_OUTPUT 1 + +extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir); +extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val); + /**************************************************************************** * Siena managed PHYs */ diff --git a/drivers/net/sfc/txc43128_phy.c b/drivers/net/sfc/txc43128_phy.c new file mode 100644 index 000000000000..351794a79215 --- /dev/null +++ b/drivers/net/sfc/txc43128_phy.c @@ -0,0 +1,560 @@ +/**************************************************************************** + * Driver for Solarflare Solarstorm network controllers and boards + * Copyright 2006-2010 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +/* + * Driver for Transwitch/Mysticom CX4 retimer + * see www.transwitch.com, part is TXC-43128 + */ + +#include +#include +#include "efx.h" +#include "mdio_10g.h" +#include "phy.h" +#include "nic.h" + +/* We expect these MMDs to be in the package */ +#define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS | \ + MDIO_DEVS_PMAPMD | \ + MDIO_DEVS_PHYXS) + +#define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \ + (1 << LOOPBACK_PMAPMD) | \ + (1 << LOOPBACK_PHYXS_WS)) + +/************************************************************************** + * + * Compile-time config + * + ************************************************************************** + */ +#define TXCNAME "TXC43128" +/* Total length of time we'll wait for the PHY to come out of reset (ms) */ +#define TXC_MAX_RESET_TIME 500 +/* Interval between checks (ms) */ +#define TXC_RESET_WAIT 10 +/* How long to run BIST (us) */ +#define TXC_BIST_DURATION 50 + +/************************************************************************** + * + * Register definitions + * + ************************************************************************** + */ + +/* Command register */ +#define TXC_GLRGS_GLCMD 0xc004 +/* Useful bits in command register */ +/* Lane power-down */ +#define TXC_GLCMD_L01PD_LBN 5 +#define TXC_GLCMD_L23PD_LBN 6 +/* Limited SW reset: preserves configuration but + * initiates a logic reset. Self-clearing */ +#define TXC_GLCMD_LMTSWRST_LBN 14 + +/* Signal Quality Control */ +#define TXC_GLRGS_GSGQLCTL 0xc01a +/* Enable bit */ +#define TXC_GSGQLCT_SGQLEN_LBN 15 +/* Lane selection */ +#define TXC_GSGQLCT_LNSL_LBN 13 +#define TXC_GSGQLCT_LNSL_WIDTH 2 + +/* Analog TX control */ +#define TXC_ALRGS_ATXCTL 0xc040 +/* Lane power-down */ +#define TXC_ATXCTL_TXPD3_LBN 15 +#define TXC_ATXCTL_TXPD2_LBN 14 +#define TXC_ATXCTL_TXPD1_LBN 13 +#define TXC_ATXCTL_TXPD0_LBN 12 + +/* Amplitude on lanes 0, 1 */ +#define TXC_ALRGS_ATXAMP0 0xc041 +/* Amplitude on lanes 2, 3 */ +#define TXC_ALRGS_ATXAMP1 0xc042 +/* Bit position of value for lane 0 (or 2) */ +#define TXC_ATXAMP_LANE02_LBN 3 +/* Bit position of value for lane 1 (or 3) */ +#define TXC_ATXAMP_LANE13_LBN 11 + +#define TXC_ATXAMP_1280_mV 0 +#define TXC_ATXAMP_1200_mV 8 +#define TXC_ATXAMP_1120_mV 12 +#define TXC_ATXAMP_1060_mV 14 +#define TXC_ATXAMP_0820_mV 25 +#define TXC_ATXAMP_0720_mV 26 +#define TXC_ATXAMP_0580_mV 27 +#define TXC_ATXAMP_0440_mV 28 + +#define TXC_ATXAMP_0820_BOTH \ + ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \ + | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN)) + +#define TXC_ATXAMP_DEFAULT 0x6060 /* From databook */ + +/* Preemphasis on lanes 0, 1 */ +#define TXC_ALRGS_ATXPRE0 0xc043 +/* Preemphasis on lanes 2, 3 */ +#define TXC_ALRGS_ATXPRE1 0xc044 + +#define TXC_ATXPRE_NONE 0 +#define TXC_ATXPRE_DEFAULT 0x1010 /* From databook */ + +#define TXC_ALRGS_ARXCTL 0xc045 +/* Lane power-down */ +#define TXC_ARXCTL_RXPD3_LBN 15 +#define TXC_ARXCTL_RXPD2_LBN 14 +#define TXC_ARXCTL_RXPD1_LBN 13 +#define TXC_ARXCTL_RXPD0_LBN 12 + +/* Main control */ +#define TXC_MRGS_CTL 0xc340 +/* Bits in main control */ +#define TXC_MCTL_RESET_LBN 15 /* Self clear */ +#define TXC_MCTL_TXLED_LBN 14 /* 1 to show align status */ +#define TXC_MCTL_RXLED_LBN 13 /* 1 to show align status */ + +/* GPIO output */ +#define TXC_GPIO_OUTPUT 0xc346 +#define TXC_GPIO_DIR 0xc348 + +/* Vendor-specific BIST registers */ +#define TXC_BIST_CTL 0xc280 +#define TXC_BIST_TXFRMCNT 0xc281 +#define TXC_BIST_RX0FRMCNT 0xc282 +#define TXC_BIST_RX1FRMCNT 0xc283 +#define TXC_BIST_RX2FRMCNT 0xc284 +#define TXC_BIST_RX3FRMCNT 0xc285 +#define TXC_BIST_RX0ERRCNT 0xc286 +#define TXC_BIST_RX1ERRCNT 0xc287 +#define TXC_BIST_RX2ERRCNT 0xc288 +#define TXC_BIST_RX3ERRCNT 0xc289 + +/* BIST type (controls bit patter in test) */ +#define TXC_BIST_CTRL_TYPE_LBN 10 +#define TXC_BIST_CTRL_TYPE_TSD 0 /* TranSwitch Deterministic */ +#define TXC_BIST_CTRL_TYPE_CRP 1 /* CRPAT standard */ +#define TXC_BIST_CTRL_TYPE_CJP 2 /* CJPAT standard */ +#define TXC_BIST_CTRL_TYPE_TSR 3 /* TranSwitch pseudo-random */ +/* Set this to 1 for 10 bit and 0 for 8 bit */ +#define TXC_BIST_CTRL_B10EN_LBN 12 +/* Enable BIST (write 0 to disable) */ +#define TXC_BIST_CTRL_ENAB_LBN 13 +/* Stop BIST (self-clears when stop complete) */ +#define TXC_BIST_CTRL_STOP_LBN 14 +/* Start BIST (cleared by writing 1 to STOP) */ +#define TXC_BIST_CTRL_STRT_LBN 15 + +/* Mt. Diablo test configuration */ +#define TXC_MTDIABLO_CTRL 0xc34f +#define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN 10 + +struct txc43128_data { + unsigned long bug10934_timer; + enum efx_phy_mode phy_mode; + enum efx_loopback_mode loopback_mode; +}; + +/* The PHY sometimes needs a reset to bring the link back up. So long as + * it reports link down, we reset it every 5 seconds. + */ +#define BUG10934_RESET_INTERVAL (5 * HZ) + +/* Perform a reset that doesn't clear configuration changes */ +static void txc_reset_logic(struct efx_nic *efx); + +/* Set the output value of a gpio */ +void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int on) +{ + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on); +} + +/* Set up the GPIO direction register */ +void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir) +{ + efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir); +} + +/* Reset the PMA/PMD MMD. The documentation is explicit that this does a + * global reset (it's less clear what reset of other MMDs does).*/ +static int txc_reset_phy(struct efx_nic *efx) +{ + int rc = efx_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD, + TXC_MAX_RESET_TIME / TXC_RESET_WAIT, + TXC_RESET_WAIT); + if (rc < 0) + goto fail; + + /* Check that all the MMDs we expect are present and responding. */ + rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0); + if (rc < 0) + goto fail; + + return 0; + +fail: + netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n"); + 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; + + /* 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) { + netif_err(efx, hw, efx->net_dev, 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) { + netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. " + "Lane %d got 0 frames\n", lane); + rc = -EIO; + } + } + + if (rc == 0) + netif_info(efx, hw, efx->net_dev, 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; +} + +static int txc_bist(struct efx_nic *efx) +{ + return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD); +} + +/* Push the non-configurable defaults into the PHY. This must be + * done after every full reset */ +static void txc_apply_defaults(struct efx_nic *efx) +{ + int mctrl; + + /* Turn amplitude down and preemphasis off on the host side + * (PHY<->MAC) as this is believed less likely to upset Falcon + * and no adverse effects have been noted. It probably also + * saves a picowatt or two */ + + /* Turn off preemphasis */ + efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE); + efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE); + + /* Turn down the amplitude */ + efx_mdio_write(efx, MDIO_MMD_PHYXS, + TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH); + efx_mdio_write(efx, MDIO_MMD_PHYXS, + TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH); + + /* Set the line side amplitude and preemphasis to the databook + * defaults as an erratum causes them to be 0 on at least some + * PHY rev.s */ + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT); + efx_mdio_write(efx, MDIO_MMD_PMAPMD, + TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT); + + /* Set up the LEDs */ + mctrl = efx_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL); + + /* Set the Green and Red LEDs to their default modes */ + mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN)); + efx_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl); + + /* Databook recommends doing this after configuration changes */ + txc_reset_logic(efx); + + falcon_board(efx)->type->init_phy(efx); +} + +static int txc43128_phy_probe(struct efx_nic *efx) +{ + struct txc43128_data *phy_data; + + /* Allocate phy private storage */ + phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); + if (!phy_data) + return -ENOMEM; + efx->phy_data = phy_data; + phy_data->phy_mode = efx->phy_mode; + + efx->mdio.mmds = TXC_REQUIRED_DEVS; + efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; + + efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS; + + return 0; +} + +/* Initialisation entry point for this PHY driver */ +static int txc43128_phy_init(struct efx_nic *efx) +{ + int rc; + + 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; +} + +/* Set the lane power down state in the global registers */ +static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd) +{ + int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN); + int ctl = efx_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); + + if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) + ctl &= ~pd; + else + ctl |= pd; + + efx_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl); +} + +/* Set the lane power down state in the analog control registers */ +static void txc_analog_lane_power(struct efx_nic *efx, int mmd) +{ + int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN) + | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN); + int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN) + | (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN); + int txctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL); + int rxctl = efx_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL); + + if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) { + txctl &= ~txpd; + rxctl &= ~rxpd; + } else { + txctl |= txpd; + rxctl |= rxpd; + } + + efx_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl); + efx_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl); +} + +static void txc_set_power(struct efx_nic *efx) +{ + /* According to the data book, all the MMDs can do low power */ + efx_mdio_set_mmds_lpower(efx, + !!(efx->phy_mode & PHY_MODE_LOW_POWER), + TXC_REQUIRED_DEVS); + + /* Global register bank is in PCS, PHY XS. These control the host + * side and line side settings respectively. */ + txc_glrgs_lane_power(efx, MDIO_MMD_PCS); + txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS); + + /* Analog register bank in PMA/PMD, PHY XS */ + txc_analog_lane_power(efx, MDIO_MMD_PMAPMD); + txc_analog_lane_power(efx, MDIO_MMD_PHYXS); +} + +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) + netif_info(efx, hw, efx->net_dev, + TXCNAME " Logic reset timed out!\n"); +} + +/* Perform a logic reset. This preserves the configuration registers + * and is needed for some configuration changes to take effect */ +static void txc_reset_logic(struct efx_nic *efx) +{ + /* The data sheet claims we can do the logic reset on either the + * PCS or the PHYXS and the result is a reset of both host- and + * line-side logic. */ + txc_reset_logic_mmd(efx, MDIO_MMD_PCS); +} + +static bool txc43128_phy_read_link(struct efx_nic *efx) +{ + return efx_mdio_links_ok(efx, TXC_REQUIRED_DEVS); +} + +static int txc43128_phy_reconfigure(struct efx_nic *efx) +{ + struct txc43128_data *phy_data = efx->phy_data; + enum efx_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode; + bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS); + + if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) { + txc_reset_phy(efx); + txc_apply_defaults(efx); + falcon_reset_xaui(efx); + mode_change &= ~PHY_MODE_TX_DISABLED; + } + + efx_mdio_transmit_disable(efx); + efx_mdio_phy_reconfigure(efx); + if (mode_change & PHY_MODE_LOW_POWER) + txc_set_power(efx); + + /* The data sheet claims this is required after every reconfiguration + * (note at end of 7.1), but we mustn't do it when nothing changes as + * it glitches the link, and reconfigure gets called on link change, + * so we get an IRQ storm on link up. */ + if (loop_change || mode_change) + txc_reset_logic(efx); + + phy_data->phy_mode = efx->phy_mode; + phy_data->loopback_mode = efx->loopback_mode; + + return 0; +} + +static void txc43128_phy_fini(struct efx_nic *efx) +{ + /* Disable link events */ + efx_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0); +} + +static void txc43128_phy_remove(struct efx_nic *efx) +{ + kfree(efx->phy_data); + efx->phy_data = NULL; +} + +/* Periodic callback: this exists mainly to poll link status as we + * don't use LASI interrupts */ +static bool txc43128_phy_poll(struct efx_nic *efx) +{ + struct txc43128_data *data = efx->phy_data; + bool was_up = efx->link_state.up; + + efx->link_state.up = txc43128_phy_read_link(efx); + efx->link_state.speed = 10000; + efx->link_state.fd = true; + efx->link_state.fc = efx->wanted_fc; + + if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) { + data->bug10934_timer = jiffies; + } else { + if (time_after_eq(jiffies, (data->bug10934_timer + + BUG10934_RESET_INTERVAL))) { + data->bug10934_timer = jiffies; + txc_reset_logic(efx); + } + } + + return efx->link_state.up != was_up; +} + +static const char *txc43128_test_names[] = { + "bist" +}; + +static const char *txc43128_test_name(struct efx_nic *efx, unsigned int index) +{ + if (index < ARRAY_SIZE(txc43128_test_names)) + return txc43128_test_names[index]; + return NULL; +} + +static int txc43128_run_tests(struct efx_nic *efx, int *results, unsigned flags) +{ + int rc; + + if (!(flags & ETH_TEST_FL_OFFLINE)) + return 0; + + rc = txc_reset_phy(efx); + if (rc < 0) + return rc; + + rc = txc_bist(efx); + txc_apply_defaults(efx); + results[0] = rc ? -1 : 1; + return rc; +} + +static void txc43128_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) +{ + mdio45_ethtool_gset(&efx->mdio, ecmd); +} + +struct efx_phy_operations falcon_txc_phy_ops = { + .probe = txc43128_phy_probe, + .init = txc43128_phy_init, + .reconfigure = txc43128_phy_reconfigure, + .poll = txc43128_phy_poll, + .fini = txc43128_phy_fini, + .remove = txc43128_phy_remove, + .get_settings = txc43128_get_settings, + .set_settings = efx_mdio_set_settings, + .test_alive = efx_mdio_test_alive, + .run_tests = txc43128_run_tests, + .test_name = txc43128_test_name, +}; -- cgit v1.2.3