ia64/linux-2.6.18-xen.hg

annotate drivers/net/sfc/txc43128_phy.c @ 847:ad4d307bf9ce

net sfc: Update sfc and sfc_resource driver to latest release

...and update sfc_netfront, sfc_netback, sfc_netutil for any API changes

sfc_netback: Fix asymmetric use of SFC buffer table alloc and free
sfc_netback: Clean up if no SFC accel device found
sfc_netback: Gracefully handle case where page grant fails
sfc_netback: Disable net acceleration if the physical link goes down
sfc_netfront: Less verbose error messages, more verbose counters for
rx discard errors
sfc_netfront: Gracefully handle case where SFC netfront fails during
initialisation

Signed-off-by: Kieran Mansley <kmansley@solarflare.com>
author Keir Fraser <keir.fraser@citrix.com>
date Tue Mar 31 11:59:10 2009 +0100 (2009-03-31)
parents 8c8a097cae69
children
rev   line source
keir@424 1 /****************************************************************************
keir@424 2 * Driver for Solarflare network controllers
keir@424 3 * (including support for SFE4001 10GBT NIC)
keir@424 4 *
keir@424 5 * Copyright 2006-2008: Solarflare Communications Inc,
keir@424 6 * 9501 Jeronimo Road, Suite 250,
keir@424 7 * Irvine, CA 92618, USA
keir@424 8 *
keir@424 9 * Developed by Solarflare Communications <linux-net-drivers@solarflare.com>
keir@424 10 *
keir@424 11 * This program is free software; you can redistribute it and/or modify it
keir@424 12 * under the terms of the GNU General Public License version 2 as published
keir@424 13 * by the Free Software Foundation, incorporated herein by reference.
keir@424 14 *
keir@424 15 * This program is distributed in the hope that it will be useful,
keir@424 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@424 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@424 18 * GNU General Public License for more details.
keir@424 19 *
keir@424 20 * You should have received a copy of the GNU General Public License
keir@424 21 * along with this program; if not, write to the Free Software
keir@424 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
keir@424 23 ****************************************************************************
keir@424 24 */
keir@424 25 /*
keir@424 26 * Driver for Transwitch/Mysticom CX4 retimer
keir@424 27 * see www.transwitch.com, part is TXC-43128
keir@424 28 */
keir@424 29
keir@424 30 #include <linux/delay.h>
keir@424 31 #include <linux/seq_file.h>
keir@424 32 #include "efx.h"
keir@424 33 #include "debugfs.h"
keir@424 34 #include "gmii.h"
keir@424 35 #include "mdio_10g.h"
keir@424 36 #include "xenpack.h"
keir@424 37 #include "phy.h"
keir@424 38 #include "lm87_support.h"
keir@424 39 #include "falcon.h"
keir@424 40 #include "workarounds.h"
keir@424 41
keir@424 42 /* We expect these MMDs to be in the package */
keir@424 43 #define TXC_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \
keir@424 44 MDIO_MMDREG_DEVS0_PMAPMD | \
keir@424 45 MDIO_MMDREG_DEVS0_PHYXS)
keir@424 46
keir@424 47 #define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \
keir@424 48 (1 << LOOPBACK_PMAPMD) | \
keir@424 49 (1 << LOOPBACK_NETWORK))
keir@424 50
keir@424 51 /**************************************************************************
keir@424 52 *
keir@424 53 * Compile-time config
keir@424 54 *
keir@424 55 **************************************************************************
keir@424 56 */
keir@424 57 #define TXCNAME "TXC43128"
keir@424 58 /* Total length of time we'll wait for the PHY to come out of reset */
keir@424 59 #define TXC_MAX_RESET_TIME 500
keir@424 60 /* Interval between checks */
keir@424 61 #define TXC_RESET_WAIT 10
keir@424 62 /* How long to run BIST: At 10Gbps 50 microseconds should be plenty to get
keir@424 63 * some stats */
keir@424 64 #define TXC_BIST_DURATION (50)
keir@424 65
keir@424 66 #define BER_INTERVAL (10 * efx_monitor_interval)
keir@424 67
keir@424 68 /**************************************************************************
keir@424 69 *
keir@424 70 * Register definitions
keir@424 71 *
keir@424 72 **************************************************************************
keir@424 73 */
keir@424 74 #define XAUI_NUM_LANES (4)
keir@424 75
keir@424 76 /*** Global register bank */
keir@424 77 /* Silicon ID register */
keir@424 78 #define TXC_GLRGS_SLID (0xc000)
keir@424 79 #define TXC_GLRGS_SLID_MASK (0x1f)
keir@424 80
keir@424 81 /* Command register */
keir@424 82 #define TXC_GLRGS_GLCMD (0xc004)
keir@424 83 /* Useful bits in command register */
keir@424 84 /* Lane power-down */
keir@424 85 #define TXC_GLCMD_L01PD_LBN (5)
keir@424 86 #define TXC_GLCMD_L23PD_LBN (6)
keir@424 87 /* Limited SW reset: preserves configuration but
keir@424 88 * initiates a logic reset. Self-clearing */
keir@424 89 #define TXC_GLCMD_LMTSWRST_LBN (14)
keir@424 90
keir@424 91 /* Signal Quality Control */
keir@424 92 #define TXC_GLRGS_GSGQLCTL (0xc01a)
keir@424 93 /* Enable bit */
keir@424 94 #define TXC_GSGQLCT_SGQLEN_LBN (15)
keir@424 95 /* Lane selection */
keir@424 96 #define TXC_GSGQLCT_LNSL_LBN (13)
keir@424 97 #define TXC_GSGQLCT_LNSL_WIDTH (2)
keir@424 98
keir@424 99 /* Signal Quality Input */
keir@424 100 #define TXC_GLRGS_GSGQLIN (0xc01b)
keir@424 101 /* Signal Quality Grade */
keir@424 102 #define TXC_GLRGS_GSGQLGRD (0xc01c)
keir@424 103 /* Drift sign */
keir@424 104 #define TXC_GSGQLGRD_DRFTSGN_LBN (15)
keir@424 105 /* Grade valid flag */
keir@424 106 #define TXC_GSGQLGRD_GRDVAL_LBN (14)
keir@424 107 /* Remaining bits are the actual grade */
keir@424 108 #define TXC_GSGQLGRD_GRADE_LBN (0)
keir@424 109 #define TXC_GSGQLGRD_GRADE_WIDTH (14)
keir@424 110
keir@424 111 /* Signal Quality Drift: 16-bit drift value */
keir@424 112 #define TXC_GLRGS_GSGQLDRFT (0xc01d)
keir@424 113
keir@424 114 /**** Analog register bank */
keir@424 115 #define TXC_ALRGS_ATXCTL (0xc040)
keir@424 116 /* Lane power-down */
keir@424 117 #define TXC_ATXCTL_TXPD3_LBN (15)
keir@424 118 #define TXC_ATXCTL_TXPD2_LBN (14)
keir@424 119 #define TXC_ATXCTL_TXPD1_LBN (13)
keir@424 120 #define TXC_ATXCTL_TXPD0_LBN (12)
keir@424 121
keir@424 122 /* Amplitude on lanes 0, 1 */
keir@424 123 #define TXC_ALRGS_ATXAMP0 (0xc041)
keir@424 124 /* Amplitude on lanes 2, 3 */
keir@424 125 #define TXC_ALRGS_ATXAMP1 (0xc042)
keir@424 126 /* Bit position of value for lane 0 (or 2) */
keir@424 127 #define TXC_ATXAMP_LANE02_LBN (3)
keir@424 128 /* Bit position of value for lane 1 (or 3) */
keir@424 129 #define TXC_ATXAMP_LANE13_LBN (11)
keir@424 130
keir@424 131 #define TXC_ATXAMP_1280_mV (0)
keir@424 132 #define TXC_ATXAMP_1200_mV (8)
keir@424 133 #define TXC_ATXAMP_1120_mV (12)
keir@424 134 #define TXC_ATXAMP_1060_mV (14)
keir@424 135 #define TXC_ATXAMP_0820_mV (25)
keir@424 136 #define TXC_ATXAMP_0720_mV (26)
keir@424 137 #define TXC_ATXAMP_0580_mV (27)
keir@424 138 #define TXC_ATXAMP_0440_mV (28)
keir@424 139
keir@424 140 #define TXC_ATXAMP_0820_BOTH \
keir@424 141 ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \
keir@424 142 | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN))
keir@424 143
keir@424 144 #define TXC_ATXAMP_DEFAULT (0x6060) /* From databook */
keir@424 145
keir@424 146 /* Preemphasis on lanes 0, 1 */
keir@424 147 #define TXC_ALRGS_ATXPRE0 (0xc043)
keir@424 148 /* Preemphasis on lanes 2, 3 */
keir@424 149 #define TXC_ALRGS_ATXPRE1 (0xc044)
keir@424 150
keir@424 151 #define TXC_ATXPRE_NONE (0)
keir@424 152 #define TXC_ATXPRE_DEFAULT (0x1010) /* From databook */
keir@424 153
keir@424 154 #define TXC_ALRGS_ARXCTL (0xc045)
keir@424 155 /* Lane power-down */
keir@424 156 #define TXC_ARXCTL_RXPD3_LBN (15)
keir@424 157 #define TXC_ARXCTL_RXPD2_LBN (14)
keir@424 158 #define TXC_ARXCTL_RXPD1_LBN (13)
keir@424 159 #define TXC_ARXCTL_RXPD0_LBN (12)
keir@424 160
keir@424 161 /*** receiver control registers: Bit Error Rate measurement */
keir@424 162 /* Per lane BER timers */
keir@424 163 #define TXC_RXCTL_BERTMR0 (0xc0d4)
keir@424 164 #define TXC_RXCTL_BERTMR1 (0xc154)
keir@424 165 #define TXC_RXCTL_BERTMR2 (0xc1d4)
keir@424 166 #define TXC_RXCTL_BERTMR3 (0xc254)
keir@424 167 /* Per lane BER counters */
keir@424 168 #define TXC_RXCTL_BERCNT0 (0xc0d5)
keir@424 169 #define TXC_RXCTL_BERCNT1 (0xc155)
keir@424 170 #define TXC_RXCTL_BERCNT2 (0xc1d5)
keir@424 171 #define TXC_RXCTL_BERCNT3 (0xc255)
keir@424 172
keir@424 173 #define BER_REG_SPACING (TXC_RXCTL_BERTMR1 - TXC_RXCTL_BERTMR0)
keir@424 174
keir@424 175 /*** Main user-defined register set */
keir@424 176 /* Main control */
keir@424 177 #define TXC_MRGS_CTL (0xc340)
keir@424 178 /* Bits in main control */
keir@424 179 #define TXC_MCTL_RESET_LBN (15) /* Self clear */
keir@424 180 #define TXC_MCTL_TXLED_LBN (14) /* 1 to show align status */
keir@424 181 #define TXC_MCTL_RXLED_LBN (13) /* 1 to show align status */
keir@424 182
keir@424 183 /* GPIO output */
keir@424 184 #define TXC_GPIO_OUTPUT (0xc346)
keir@424 185 #define TXC_GPIO_DIR (0xc348)
keir@424 186
keir@424 187 /*** Vendor-specific BIST registers */
keir@424 188 #define TXC_BIST_CTL (0xc280)
keir@424 189 #define TXC_BIST_TXFRMCNT (0xc281)
keir@424 190 #define TXC_BIST_RX0FRMCNT (0xc282)
keir@424 191 #define TXC_BIST_RX1FRMCNT (0xc283)
keir@424 192 #define TXC_BIST_RX2FRMCNT (0xc284)
keir@424 193 #define TXC_BIST_RX3FRMCNT (0xc285)
keir@424 194 #define TXC_BIST_RX0ERRCNT (0xc286)
keir@424 195 #define TXC_BIST_RX1ERRCNT (0xc287)
keir@424 196 #define TXC_BIST_RX2ERRCNT (0xc288)
keir@424 197 #define TXC_BIST_RX3ERRCNT (0xc289)
keir@424 198
keir@424 199 /*** BIST control bits */
keir@424 200 /* BIST type (controls bit patter in test) */
keir@424 201 #define TXC_BIST_CTRL_TYPE_LBN (10)
keir@424 202 #define TXC_BIST_CTRL_TYPE_TSD (0) /* TranSwitch Deterministic */
keir@424 203 #define TXC_BIST_CTRL_TYPE_CRP (1) /* CRPAT standard */
keir@424 204 #define TXC_BIST_CTRL_TYPE_CJP (2) /* CJPAT standard */
keir@424 205 #define TXC_BIST_CTRL_TYPE_TSR (3) /* TranSwitch pseudo-random */
keir@424 206 /* Set this to 1 for 10 bit and 0 for 8 bit */
keir@424 207 #define TXC_BIST_CTRL_B10EN_LBN (12)
keir@424 208 /* Enable BIST (write 0 to disable) */
keir@424 209 #define TXC_BIST_CTRL_ENAB_LBN (13)
keir@424 210 /*Stop BIST (self-clears when stop complete) */
keir@424 211 #define TXC_BIST_CTRL_STOP_LBN (14)
keir@424 212 /* Start BIST (cleared by writing 1 to STOP) */
keir@424 213 #define TXC_BIST_CTRL_STRT_LBN (15)
keir@424 214
keir@424 215 /* Mt. Diablo test configuration */
keir@424 216 #define TXC_MTDIABLO_CTRL (0xc34f)
keir@424 217 #define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN (10)
keir@424 218
keir@424 219 struct txc43128_data {
keir@424 220 #ifdef CONFIG_SFC_DEBUGFS
keir@424 221 /* BER stats update from check_hw. Note that this is in errors/second,
keir@424 222 * converting it to errors/bit is left as an exercise for user-space.
keir@424 223 */
keir@424 224 unsigned phy_ber_pcs[4];
keir@424 225 unsigned phy_ber_phyxs[4];
keir@424 226 #endif
keir@424 227 unsigned bug10934_timer;
keir@424 228 int phy_powered;
keir@424 229 int tx_disabled;
keir@424 230 enum efx_loopback_mode loopback_mode;
keir@424 231 };
keir@424 232
keir@424 233 /* Perform the bug 10934 workaround every 5s */
keir@424 234 #define BUG10934_RESET_INTERVAL (5 * HZ)
keir@424 235
keir@424 236
keir@424 237 /* Perform a reset that doesn't clear configuration changes */
keir@424 238 static void txc_reset_logic(struct efx_nic *efx);
keir@424 239
keir@424 240 /* Set the output value of a gpio */
keir@424 241 void txc_set_gpio_val(struct efx_nic *efx, int pin, int on)
keir@424 242 {
keir@424 243 int outputs;
keir@424 244
keir@424 245 outputs = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 246 MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT);
keir@424 247
keir@424 248 outputs = (outputs & ~(1 << pin)) | (on << pin);
keir@424 249
keir@424 250 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 251 MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT,
keir@424 252 outputs);
keir@424 253 }
keir@424 254
keir@424 255 /* Set up the GPIO direction register */
keir@424 256 void txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir)
keir@424 257 {
keir@424 258 int dirs;
keir@424 259
keir@424 260 if (efx->board_info.minor < 3 &&
keir@424 261 efx->board_info.major == 0)
keir@424 262 return;
keir@424 263
keir@424 264 dirs = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 265 MDIO_MMD_PHYXS, TXC_GPIO_DIR);
keir@424 266 dirs = (dir & ~(1 << pin)) | (dir << pin);
keir@424 267 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 268 MDIO_MMD_PHYXS, TXC_GPIO_DIR, dirs);
keir@424 269
keir@424 270 }
keir@424 271
keir@424 272 /* Reset the PMA/PMD MMD. The documentation is explicit that this does a
keir@424 273 * global reset (it's less clear what reset of other MMDs does).*/
keir@424 274 static int txc_reset_phy(struct efx_nic *efx)
keir@424 275 {
keir@424 276 int rc = mdio_clause45_reset_mmd(efx, MDIO_MMD_PMAPMD,
keir@424 277 TXC_MAX_RESET_TIME / TXC_RESET_WAIT,
keir@424 278 TXC_RESET_WAIT);
keir@424 279 if (rc < 0)
keir@424 280 goto fail;
keir@424 281
keir@424 282 /* Check that all the MMDs we expect are present and responding. We
keir@424 283 * expect faults on some if the link is down, but not on the PHY XS */
keir@424 284 rc = mdio_clause45_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
keir@424 285 if (rc < 0)
keir@424 286 goto fail;
keir@424 287
keir@424 288 return 0;
keir@424 289
keir@424 290 fail:
keir@424 291 EFX_ERR(efx, TXCNAME ": reset timed out!\n");
keir@424 292 return rc;
keir@424 293 }
keir@424 294
keir@424 295 /* Run a single BIST on one MMD*/
keir@424 296 static int txc_bist_one(struct efx_nic *efx, int mmd, int test)
keir@424 297 {
keir@424 298 int phy = efx->mii.phy_id;
keir@424 299 int ctrl, bctl;
keir@424 300 int lane;
keir@424 301 int rc = 0;
keir@424 302
keir@424 303 EFX_INFO(efx, "" TXCNAME ": running BIST on %s MMD\n",
keir@424 304 mdio_clause45_mmd_name(mmd));
keir@424 305
keir@424 306 /* Set PMA to test into loopback using Mt Diablo reg as per app note */
keir@424 307 ctrl = mdio_clause45_read(efx, phy, MDIO_MMD_PCS,
keir@424 308 TXC_MTDIABLO_CTRL);
keir@424 309 ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
keir@424 310 mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
keir@424 311 TXC_MTDIABLO_CTRL, ctrl);
keir@424 312
keir@424 313
keir@424 314 /* The BIST app. note lists these as 3 distinct steps. */
keir@424 315 /* Set the BIST type */
keir@424 316 bctl = (test << TXC_BIST_CTRL_TYPE_LBN);
keir@424 317 mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
keir@424 318
keir@424 319 /* Set the BSTEN bit in the BIST Control register to enable */
keir@424 320 bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN);
keir@424 321 mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
keir@424 322
keir@424 323 /* Set the BSTRT bit in the BIST Control register */
keir@424 324 mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl |
keir@424 325 (1 << TXC_BIST_CTRL_STRT_LBN));
keir@424 326
keir@424 327 /* Wait. */
keir@424 328 udelay(TXC_BIST_DURATION);
keir@424 329
keir@424 330 /* Set the BSTOP bit in the BIST Control register */
keir@424 331 bctl |= (1 << TXC_BIST_CTRL_STOP_LBN);
keir@424 332 mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, bctl);
keir@424 333
keir@424 334 /* The STOP bit should go off when things have stopped */
keir@424 335 while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN))
keir@424 336 bctl = mdio_clause45_read(efx, phy, mmd, TXC_BIST_CTL);
keir@424 337
keir@424 338 /* Check all the error counts are 0 and all the frame counts are
keir@424 339 non-zero */
keir@424 340 for (lane = 0; lane < 4; lane++) {
keir@424 341 int count = mdio_clause45_read(efx, phy, mmd,
keir@424 342 TXC_BIST_RX0ERRCNT + lane);
keir@424 343 if (count != 0) {
keir@424 344 EFX_ERR(efx, ""TXCNAME": BIST error. "
keir@424 345 "Lane %d had %d errs\n", lane, count);
keir@424 346 rc = -EIO;
keir@424 347 }
keir@424 348 count = mdio_clause45_read(efx, phy, mmd,
keir@424 349 TXC_BIST_RX0FRMCNT + lane);
keir@424 350 if (count == 0) {
keir@424 351 EFX_ERR(efx, ""TXCNAME": BIST error. "
keir@424 352 "Lane %d got 0 frames\n", lane);
keir@424 353 rc = -EIO;
keir@424 354 }
keir@424 355 }
keir@424 356
keir@424 357 if (rc == 0)
keir@424 358 EFX_INFO(efx, ""TXCNAME": BIST pass\n");
keir@424 359
keir@424 360 /* Disable BIST */
keir@424 361 mdio_clause45_write(efx, phy, mmd, TXC_BIST_CTL, 0);
keir@424 362
keir@424 363 /* Turn off loopback */
keir@424 364 ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN);
keir@424 365 mdio_clause45_write(efx, phy, MDIO_MMD_PCS,
keir@424 366 TXC_MTDIABLO_CTRL, ctrl);
keir@424 367
keir@424 368 return rc;
keir@424 369 }
keir@424 370
keir@424 371 /* Run all the desired BIST tests for the PHY */
keir@424 372 static int txc_bist(struct efx_nic *efx)
keir@424 373 {
keir@424 374 int rc;
keir@424 375 /*!\todo: experiment with running more of the BIST patterns to
keir@424 376 * see if it actually shows up more problems. */
keir@424 377 rc = txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD);
keir@424 378 return rc;
keir@424 379 }
keir@424 380
keir@424 381 #ifdef CONFIG_SFC_DEBUGFS
keir@424 382
keir@424 383 /* debugfs entries for this PHY */
keir@424 384 static struct efx_debugfs_parameter debug_entries[] = {
keir@424 385 EFX_PER_LANE_PARAMETER("phy_ber_lane", "_pcs",
keir@424 386 struct txc43128_data, phy_ber_pcs,
keir@424 387 unsigned, efx_debugfs_read_uint),
keir@424 388 EFX_PER_LANE_PARAMETER("phy_ber_lane", "_phyxs",
keir@424 389 struct txc43128_data, phy_ber_phyxs,
keir@424 390 unsigned, efx_debugfs_read_uint),
keir@424 391 EFX_INT_PARAMETER(struct txc43128_data, phy_powered),
keir@424 392 {NULL}
keir@424 393 };
keir@424 394
keir@424 395 #endif /* CONFIG_SFC_DEBUGFS */
keir@424 396
keir@424 397 /* Push the non-configurable defaults into the PHY. This must be
keir@424 398 * done after every full reset */
keir@424 399 static void txc_apply_defaults(struct efx_nic *efx)
keir@424 400 {
keir@424 401 int mctrl;
keir@424 402
keir@424 403 /* Turn amplitude down and preemphasis off on the host side
keir@424 404 * (PHY<->MAC) as this is believed less likely to upset Falcon
keir@424 405 * and no adverse effects have been noted. It probably also
keir@424 406 * saves a picowatt or two */
keir@424 407
keir@424 408 /* Turn off preemphasis */
keir@424 409 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
keir@424 410 TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE);
keir@424 411 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
keir@424 412 TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE);
keir@424 413
keir@424 414 /* Turn down the amplitude */
keir@424 415 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
keir@424 416 TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH);
keir@424 417 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PHYXS,
keir@424 418 TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH);
keir@424 419
keir@424 420 /* Set the line side amplitude and preemphasis to the databook
keir@424 421 * defaults as an erratum causes them to be 0 on at least some
keir@424 422 * PHY rev.s */
keir@424 423 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
keir@424 424 TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT);
keir@424 425 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
keir@424 426 TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT);
keir@424 427 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
keir@424 428 TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT);
keir@424 429 mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
keir@424 430 TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT);
keir@424 431
keir@424 432 /* Set up the LEDs */
keir@424 433 mctrl = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 434 MDIO_MMD_PHYXS, TXC_MRGS_CTL);
keir@424 435
keir@424 436 /* Set the Green and Red LEDs to their default modes */
keir@424 437 mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN));
keir@424 438 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 439 MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl);
keir@424 440
keir@424 441 /* Databook recommends doing this after configuration changes */
keir@424 442 txc_reset_logic(efx);
keir@424 443
keir@424 444 efx->board_info.init_leds(efx);
keir@424 445 }
keir@424 446
keir@424 447 /* Initialisation entry point for this PHY driver */
keir@424 448 static int txc43128_phy_init(struct efx_nic *efx)
keir@424 449 {
keir@424 450 u32 devid;
keir@424 451 int rc = 0;
keir@424 452 struct txc43128_data *phy_data;
keir@424 453
keir@424 454 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS);
keir@424 455
keir@424 456 phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
keir@424 457 efx->phy_data = phy_data;
keir@424 458
keir@424 459 /* This is the default after reset */
keir@424 460 phy_data->phy_powered = efx->phy_powered;
keir@424 461 phy_data->tx_disabled = efx->tx_disabled;
keir@424 462
keir@424 463 #ifdef CONFIG_SFC_DEBUGFS
keir@424 464 rc = efx_extend_debugfs_port(efx, phy_data, debug_entries);
keir@424 465 if (rc < 0)
keir@424 466 goto fail1;
keir@424 467 #endif
keir@424 468 EFX_INFO(efx, ""TXCNAME ": PHY ID reg %x (OUI %x model %x "
keir@424 469 "revision %x)\n", devid, MDIO_ID_OUI(devid),
keir@424 470 MDIO_ID_MODEL(devid), MDIO_ID_REV(devid));
keir@424 471
keir@424 472 EFX_INFO(efx, ""TXCNAME ": Silicon ID %x\n",
keir@424 473 mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 474 MDIO_MMD_PHYXS, TXC_GLRGS_SLID) &
keir@424 475 TXC_GLRGS_SLID_MASK);
keir@424 476
keir@424 477 rc = txc_reset_phy(efx);
keir@424 478 if (rc < 0)
keir@424 479 goto fail2;
keir@424 480
keir@424 481 rc = txc_bist(efx);
keir@424 482 if (rc < 0)
keir@424 483 goto fail2;
keir@424 484
keir@424 485 txc_apply_defaults(efx);
keir@424 486
keir@424 487 return 0;
keir@424 488
keir@424 489 fail2:
keir@424 490 #ifdef CONFIG_SFC_DEBUGFS
keir@424 491 efx_trim_debugfs_port(efx, debug_entries);
keir@424 492 /* fall-thru */
keir@424 493 fail1:
keir@424 494 #endif
keir@424 495 kfree(efx->phy_data);
keir@424 496 efx->phy_data = NULL;
keir@424 497 return rc;
keir@424 498 }
keir@424 499
keir@424 500 /* Set the lane power down state in the global registers */
keir@424 501 static void txc_glrgs_lane_power(struct efx_nic *efx, int mmd)
keir@424 502 {
keir@424 503 int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN);
keir@424 504 int ctl = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 505 mmd, TXC_GLRGS_GLCMD);
keir@424 506
keir@424 507 if (efx->phy_powered)
keir@424 508 ctl &= ~pd;
keir@424 509 else
keir@424 510 ctl |= pd;
keir@424 511
keir@424 512 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 513 mmd, TXC_GLRGS_GLCMD, ctl);
keir@424 514 }
keir@424 515
keir@424 516 /* Set the lane power down state in the analog control registers */
keir@424 517 static void txc_analog_lane_power(struct efx_nic *efx, int mmd)
keir@424 518 {
keir@424 519 int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
keir@424 520 | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
keir@424 521
keir@424 522 int rxpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN)
keir@424 523 | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN);
keir@424 524
keir@424 525 int txctl = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 526 mmd, TXC_ALRGS_ATXCTL);
keir@424 527 int rxctl = mdio_clause45_read(efx, efx->mii.phy_id,
keir@424 528 mmd, TXC_ALRGS_ARXCTL);
keir@424 529
keir@424 530 if (efx->phy_powered) {
keir@424 531 txctl &= ~txpd;
keir@424 532 rxctl &= ~rxpd;
keir@424 533 } else {
keir@424 534 txctl |= txpd;
keir@424 535 rxctl |= rxpd;
keir@424 536 }
keir@424 537
keir@424 538 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 539 mmd, TXC_ALRGS_ATXCTL, txctl);
keir@424 540 mdio_clause45_write(efx, efx->mii.phy_id,
keir@424 541 mmd, TXC_ALRGS_ARXCTL, rxctl);
keir@424 542 }
keir@424 543
keir@424 544 static void txc_set_power(struct efx_nic *efx)
keir@424 545 {
keir@424 546 /* According to the data book, all the MMDs can do low power */
keir@424 547 mdio_clause45_set_mmds_lpower(efx, !efx->phy_powered,
keir@424 548 TXC_REQUIRED_DEVS);
keir@424 549
keir@424 550 /* Global register bank is in PCS, PHY XS. These control the host
keir@424 551 * side and line side settings respectively. */
keir@424 552 txc_glrgs_lane_power(efx, MDIO_MMD_PCS);
keir@424 553 txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS);
keir@424 554
keir@424 555 /* Analog register bank in PMA/PMD, PHY XS */
keir@424 556 txc_analog_lane_power(efx, MDIO_MMD_PMAPMD);
keir@424 557 txc_analog_lane_power(efx, MDIO_MMD_PHYXS);
keir@424 558 }
keir@424 559
keir@424 560
keir@424 561 static void txc_reset_logic_mmd(struct efx_nic *efx, int mmd)
keir@424 562 {
keir@424 563 int portid = efx->mii.phy_id;
keir@424 564 int val = mdio_clause45_read(efx, portid, mmd, TXC_GLRGS_GLCMD);
keir@424 565 int tries = 50;
keir@424 566 val |= (1 << TXC_GLCMD_LMTSWRST_LBN);
keir@424 567 mdio_clause45_write(efx, portid, mmd, TXC_GLRGS_GLCMD, val);
keir@424 568 while (tries--) {
keir@424 569 val = mdio_clause45_read(efx, portid, mmd,
keir@424 570 TXC_GLRGS_GLCMD);
keir@424 571 if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN)))
keir@424 572 break;
keir@424 573 udelay(1);
keir@424 574 }
keir@424 575 if (!tries)
keir@424 576 EFX_INFO(efx, TXCNAME " Logic reset timed out!\n");
keir@424 577 }
keir@424 578
keir@424 579
keir@424 580 /* Perform a logic reset. This preserves the configuration registers
keir@424 581 * and is needed for some configuration changes to take effect */
keir@424 582 static void txc_reset_logic(struct efx_nic *efx)
keir@424 583 {
keir@424 584 /* The data sheet claims we can do the logic reset on either the
keir@424 585 * PCS or the PHYXS and the result is a reset of both host- and
keir@424 586 * line-side logic. */
keir@424 587 txc_reset_logic_mmd(efx, MDIO_MMD_PCS);
keir@424 588 }
keir@424 589
keir@424 590 static int txc43128_phy_read_link(struct efx_nic *efx)
keir@424 591 {
keir@424 592 return mdio_clause45_links_ok(efx, TXC_REQUIRED_DEVS);
keir@424 593 }
keir@424 594
keir@424 595 static void txc43128_phy_reconfigure(struct efx_nic *efx)
keir@424 596 {
keir@424 597 struct txc43128_data *phy_data = efx->phy_data;
keir@424 598 int power_change = (efx->phy_powered != phy_data->phy_powered);
keir@424 599 int loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS);
keir@424 600 int disable_change = (efx->tx_disabled != phy_data->tx_disabled);
keir@424 601
keir@424 602 if (!phy_data->tx_disabled && efx->tx_disabled) {
keir@424 603 txc_reset_phy(efx);
keir@424 604 txc_apply_defaults(efx);
keir@424 605 falcon_reset_xaui(efx);
keir@424 606 disable_change = 0;
keir@424 607 }
keir@424 608
keir@424 609 mdio_clause45_transmit_disable(efx, efx->tx_disabled);
keir@424 610 mdio_clause45_phy_reconfigure(efx);
keir@424 611 if (power_change)
keir@424 612 txc_set_power(efx);
keir@424 613
keir@424 614 /* The data sheet claims this is required after every reconfiguration
keir@424 615 * (note at end of 7.1), but we mustn't do it when nothing changes as
keir@424 616 * it glitches the link, and reconfigure gets called on link change,
keir@424 617 * so we get an IRQ storm on link up. */
keir@424 618 if (loop_change || power_change || disable_change)
keir@424 619 txc_reset_logic(efx);
keir@424 620
keir@424 621 phy_data->phy_powered = efx->phy_powered;
keir@424 622 phy_data->loopback_mode = efx->loopback_mode;
keir@424 623 phy_data->tx_disabled = efx->tx_disabled;
keir@424 624 efx->link_up = txc43128_phy_read_link(efx);
keir@424 625 efx->link_options = GM_LPA_10000FULL;
keir@424 626 }
keir@424 627
keir@424 628 static void txc43128_phy_fini(struct efx_nic *efx)
keir@424 629 {
keir@424 630 efx->board_info.blink(efx, 0);
keir@424 631
keir@424 632 /* Disable link events */
keir@424 633 xenpack_disable_lasi_irqs(efx);
keir@424 634
keir@424 635 #ifdef CONFIG_SFC_DEBUGFS
keir@424 636 /* Remove the extra debug entries and free data */
keir@424 637 efx_trim_debugfs_port(efx, debug_entries);
keir@424 638 #endif
keir@424 639 kfree(efx->phy_data);
keir@424 640 efx->phy_data = NULL;
keir@424 641 }
keir@424 642
keir@424 643 /* Periodic callback: this exists mainly to poll link status as we currently
keir@424 644 * don't use LASI interrupts. Also update the BER counters and poll the lm87 */
keir@424 645 static int txc43128_phy_check_hw(struct efx_nic *efx)
keir@424 646 {
keir@433 647 struct txc43128_data *data = efx->phy_data;
keir@424 648 #ifdef CONFIG_SFC_DEBUGFS
keir@424 649 int phy = efx->mii.phy_id;
keir@424 650 int timer, count, i, mmd;
keir@424 651 #endif
keir@424 652 int rc = 0;
keir@424 653 int link_up = txc43128_phy_read_link(efx);
keir@424 654
keir@424 655 /* Simulate a PHY event if link state has changed */
keir@847 656 if (link_up != efx->link_up)
keir@424 657 efx->mac_op->fake_phy_event(efx);
keir@847 658 else if (EFX_WORKAROUND_10934(efx)) {
keir@424 659 if (link_up || (efx->loopback_mode != LOOPBACK_NONE))
keir@424 660 data->bug10934_timer = jiffies;
keir@424 661 else {
keir@424 662 int delta = jiffies - data->bug10934_timer;
keir@424 663 if (delta >= BUG10934_RESET_INTERVAL) {
keir@424 664 data->bug10934_timer = jiffies;
keir@424 665 txc_reset_logic(efx);
keir@424 666 }
keir@424 667 }
keir@424 668 }
keir@424 669
keir@424 670 rc = efx->board_info.monitor(efx);
keir@424 671 if (rc) {
keir@424 672 EFX_ERR(efx, "" TXCNAME
keir@424 673 ": sensor alert! Putting PHY into low power.\n");
keir@424 674 efx->phy_powered = 0;
keir@424 675 txc_set_power(efx);
keir@424 676 }
keir@424 677
keir@424 678 #ifdef CONFIG_SFC_DEBUGFS
keir@424 679 /* There are 2 MMDs with RX BER counters: PCS and PHY XS,
keir@424 680 * which happen to be consecutively numbered */
keir@424 681 for (mmd = MDIO_MMD_PCS; mmd <= MDIO_MMD_PHYXS; mmd++) {
keir@424 682 for (i = 0; i < XAUI_NUM_LANES; i++) {
keir@424 683 timer = mdio_clause45_read(efx, phy, mmd,
keir@424 684 TXC_RXCTL_BERTMR0 +
keir@424 685 i * BER_REG_SPACING);
keir@424 686 count = mdio_clause45_read(efx, phy, mmd,
keir@424 687 TXC_RXCTL_BERCNT0 +
keir@424 688 i * BER_REG_SPACING);
keir@424 689 /* The BER timer counts down in seconds. If it would
keir@424 690 * expire before the next check_hw, update the stats &
keir@424 691 * restart the timer (clears the count) */
keir@424 692 if (timer * HZ < efx_monitor_interval) {
keir@424 693 /* Record count, allowing for the fact that the
keir@424 694 * timer may not have reached zero */
keir@424 695 unsigned ber = (count * BER_INTERVAL) /
keir@424 696 (BER_INTERVAL - timer * HZ);
keir@424 697 if (mmd == MDIO_MMD_PCS)
keir@424 698 data->phy_ber_pcs[i] = ber;
keir@424 699 else
keir@424 700 data->phy_ber_phyxs[i] = ber;
keir@424 701 /* Reprogram the timer */
keir@424 702 mdio_clause45_write(efx, phy, mmd,
keir@424 703 TXC_RXCTL_BERTMR0 +
keir@424 704 i * BER_REG_SPACING,
keir@424 705 BER_INTERVAL / HZ);
keir@424 706 }
keir@424 707 }
keir@424 708 mmd = (mmd == MDIO_MMD_PCS) ? MDIO_MMD_PHYXS : 0;
keir@424 709 }
keir@424 710 #endif /* CONFIG_SFC_DEBUGFS */
keir@424 711 return rc;
keir@424 712 }
keir@424 713
keir@424 714 struct efx_phy_operations falcon_txc_phy_ops = {
keir@424 715 .init = txc43128_phy_init,
keir@424 716 .reconfigure = txc43128_phy_reconfigure,
keir@424 717 .check_hw = txc43128_phy_check_hw,
keir@424 718 .fini = txc43128_phy_fini,
keir@424 719 .clear_interrupt = efx_port_dummy_op_void,
keir@424 720 .reset_xaui = efx_port_dummy_op_void,
keir@424 721 .mmds = TXC_REQUIRED_DEVS,
keir@424 722 .loopbacks = TXC_LOOPBACKS,
keir@424 723 .startup_loopback = LOOPBACK_PMAPMD,
keir@424 724 };