17e51b439SBen Hutchings /**************************************************************************** 2f7a6d2c4SBen Hutchings * Driver for Solarflare network controllers and boards 30a6f40c6SBen Hutchings * Copyright 2006-2011 Solarflare Communications Inc. 47e51b439SBen Hutchings * 57e51b439SBen Hutchings * This program is free software; you can redistribute it and/or modify it 67e51b439SBen Hutchings * under the terms of the GNU General Public License version 2 as published 77e51b439SBen Hutchings * by the Free Software Foundation, incorporated herein by reference. 87e51b439SBen Hutchings */ 97e51b439SBen Hutchings 107e51b439SBen Hutchings /* 117e51b439SBen Hutchings * Driver for Transwitch/Mysticom CX4 retimer 127e51b439SBen Hutchings * see www.transwitch.com, part is TXC-43128 137e51b439SBen Hutchings */ 147e51b439SBen Hutchings 157e51b439SBen Hutchings #include <linux/delay.h> 167e51b439SBen Hutchings #include <linux/slab.h> 177e51b439SBen Hutchings #include "efx.h" 187e51b439SBen Hutchings #include "mdio_10g.h" 197e51b439SBen Hutchings #include "phy.h" 207e51b439SBen Hutchings #include "nic.h" 217e51b439SBen Hutchings 227e51b439SBen Hutchings /* We expect these MMDs to be in the package */ 237e51b439SBen Hutchings #define TXC_REQUIRED_DEVS (MDIO_DEVS_PCS | \ 247e51b439SBen Hutchings MDIO_DEVS_PMAPMD | \ 257e51b439SBen Hutchings MDIO_DEVS_PHYXS) 267e51b439SBen Hutchings 277e51b439SBen Hutchings #define TXC_LOOPBACKS ((1 << LOOPBACK_PCS) | \ 287e51b439SBen Hutchings (1 << LOOPBACK_PMAPMD) | \ 297e51b439SBen Hutchings (1 << LOOPBACK_PHYXS_WS)) 307e51b439SBen Hutchings 317e51b439SBen Hutchings /************************************************************************** 327e51b439SBen Hutchings * 337e51b439SBen Hutchings * Compile-time config 347e51b439SBen Hutchings * 357e51b439SBen Hutchings ************************************************************************** 367e51b439SBen Hutchings */ 377e51b439SBen Hutchings #define TXCNAME "TXC43128" 387e51b439SBen Hutchings /* Total length of time we'll wait for the PHY to come out of reset (ms) */ 397e51b439SBen Hutchings #define TXC_MAX_RESET_TIME 500 407e51b439SBen Hutchings /* Interval between checks (ms) */ 417e51b439SBen Hutchings #define TXC_RESET_WAIT 10 427e51b439SBen Hutchings /* How long to run BIST (us) */ 437e51b439SBen Hutchings #define TXC_BIST_DURATION 50 447e51b439SBen Hutchings 457e51b439SBen Hutchings /************************************************************************** 467e51b439SBen Hutchings * 477e51b439SBen Hutchings * Register definitions 487e51b439SBen Hutchings * 497e51b439SBen Hutchings ************************************************************************** 507e51b439SBen Hutchings */ 517e51b439SBen Hutchings 527e51b439SBen Hutchings /* Command register */ 537e51b439SBen Hutchings #define TXC_GLRGS_GLCMD 0xc004 547e51b439SBen Hutchings /* Useful bits in command register */ 557e51b439SBen Hutchings /* Lane power-down */ 567e51b439SBen Hutchings #define TXC_GLCMD_L01PD_LBN 5 577e51b439SBen Hutchings #define TXC_GLCMD_L23PD_LBN 6 587e51b439SBen Hutchings /* Limited SW reset: preserves configuration but 597e51b439SBen Hutchings * initiates a logic reset. Self-clearing */ 607e51b439SBen Hutchings #define TXC_GLCMD_LMTSWRST_LBN 14 617e51b439SBen Hutchings 627e51b439SBen Hutchings /* Signal Quality Control */ 637e51b439SBen Hutchings #define TXC_GLRGS_GSGQLCTL 0xc01a 647e51b439SBen Hutchings /* Enable bit */ 657e51b439SBen Hutchings #define TXC_GSGQLCT_SGQLEN_LBN 15 667e51b439SBen Hutchings /* Lane selection */ 677e51b439SBen Hutchings #define TXC_GSGQLCT_LNSL_LBN 13 687e51b439SBen Hutchings #define TXC_GSGQLCT_LNSL_WIDTH 2 697e51b439SBen Hutchings 707e51b439SBen Hutchings /* Analog TX control */ 717e51b439SBen Hutchings #define TXC_ALRGS_ATXCTL 0xc040 727e51b439SBen Hutchings /* Lane power-down */ 737e51b439SBen Hutchings #define TXC_ATXCTL_TXPD3_LBN 15 747e51b439SBen Hutchings #define TXC_ATXCTL_TXPD2_LBN 14 757e51b439SBen Hutchings #define TXC_ATXCTL_TXPD1_LBN 13 767e51b439SBen Hutchings #define TXC_ATXCTL_TXPD0_LBN 12 777e51b439SBen Hutchings 787e51b439SBen Hutchings /* Amplitude on lanes 0, 1 */ 797e51b439SBen Hutchings #define TXC_ALRGS_ATXAMP0 0xc041 807e51b439SBen Hutchings /* Amplitude on lanes 2, 3 */ 817e51b439SBen Hutchings #define TXC_ALRGS_ATXAMP1 0xc042 827e51b439SBen Hutchings /* Bit position of value for lane 0 (or 2) */ 837e51b439SBen Hutchings #define TXC_ATXAMP_LANE02_LBN 3 847e51b439SBen Hutchings /* Bit position of value for lane 1 (or 3) */ 857e51b439SBen Hutchings #define TXC_ATXAMP_LANE13_LBN 11 867e51b439SBen Hutchings 877e51b439SBen Hutchings #define TXC_ATXAMP_1280_mV 0 887e51b439SBen Hutchings #define TXC_ATXAMP_1200_mV 8 897e51b439SBen Hutchings #define TXC_ATXAMP_1120_mV 12 907e51b439SBen Hutchings #define TXC_ATXAMP_1060_mV 14 917e51b439SBen Hutchings #define TXC_ATXAMP_0820_mV 25 927e51b439SBen Hutchings #define TXC_ATXAMP_0720_mV 26 937e51b439SBen Hutchings #define TXC_ATXAMP_0580_mV 27 947e51b439SBen Hutchings #define TXC_ATXAMP_0440_mV 28 957e51b439SBen Hutchings 967e51b439SBen Hutchings #define TXC_ATXAMP_0820_BOTH \ 977e51b439SBen Hutchings ((TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE02_LBN) \ 987e51b439SBen Hutchings | (TXC_ATXAMP_0820_mV << TXC_ATXAMP_LANE13_LBN)) 997e51b439SBen Hutchings 1007e51b439SBen Hutchings #define TXC_ATXAMP_DEFAULT 0x6060 /* From databook */ 1017e51b439SBen Hutchings 1027e51b439SBen Hutchings /* Preemphasis on lanes 0, 1 */ 1037e51b439SBen Hutchings #define TXC_ALRGS_ATXPRE0 0xc043 1047e51b439SBen Hutchings /* Preemphasis on lanes 2, 3 */ 1057e51b439SBen Hutchings #define TXC_ALRGS_ATXPRE1 0xc044 1067e51b439SBen Hutchings 1077e51b439SBen Hutchings #define TXC_ATXPRE_NONE 0 1087e51b439SBen Hutchings #define TXC_ATXPRE_DEFAULT 0x1010 /* From databook */ 1097e51b439SBen Hutchings 1107e51b439SBen Hutchings #define TXC_ALRGS_ARXCTL 0xc045 1117e51b439SBen Hutchings /* Lane power-down */ 1127e51b439SBen Hutchings #define TXC_ARXCTL_RXPD3_LBN 15 1137e51b439SBen Hutchings #define TXC_ARXCTL_RXPD2_LBN 14 1147e51b439SBen Hutchings #define TXC_ARXCTL_RXPD1_LBN 13 1157e51b439SBen Hutchings #define TXC_ARXCTL_RXPD0_LBN 12 1167e51b439SBen Hutchings 1177e51b439SBen Hutchings /* Main control */ 1187e51b439SBen Hutchings #define TXC_MRGS_CTL 0xc340 1197e51b439SBen Hutchings /* Bits in main control */ 1207e51b439SBen Hutchings #define TXC_MCTL_RESET_LBN 15 /* Self clear */ 1217e51b439SBen Hutchings #define TXC_MCTL_TXLED_LBN 14 /* 1 to show align status */ 1227e51b439SBen Hutchings #define TXC_MCTL_RXLED_LBN 13 /* 1 to show align status */ 1237e51b439SBen Hutchings 1247e51b439SBen Hutchings /* GPIO output */ 1257e51b439SBen Hutchings #define TXC_GPIO_OUTPUT 0xc346 1267e51b439SBen Hutchings #define TXC_GPIO_DIR 0xc348 1277e51b439SBen Hutchings 1287e51b439SBen Hutchings /* Vendor-specific BIST registers */ 1297e51b439SBen Hutchings #define TXC_BIST_CTL 0xc280 1307e51b439SBen Hutchings #define TXC_BIST_TXFRMCNT 0xc281 1317e51b439SBen Hutchings #define TXC_BIST_RX0FRMCNT 0xc282 1327e51b439SBen Hutchings #define TXC_BIST_RX1FRMCNT 0xc283 1337e51b439SBen Hutchings #define TXC_BIST_RX2FRMCNT 0xc284 1347e51b439SBen Hutchings #define TXC_BIST_RX3FRMCNT 0xc285 1357e51b439SBen Hutchings #define TXC_BIST_RX0ERRCNT 0xc286 1367e51b439SBen Hutchings #define TXC_BIST_RX1ERRCNT 0xc287 1377e51b439SBen Hutchings #define TXC_BIST_RX2ERRCNT 0xc288 1387e51b439SBen Hutchings #define TXC_BIST_RX3ERRCNT 0xc289 1397e51b439SBen Hutchings 1407e51b439SBen Hutchings /* BIST type (controls bit patter in test) */ 1417e51b439SBen Hutchings #define TXC_BIST_CTRL_TYPE_LBN 10 1427e51b439SBen Hutchings #define TXC_BIST_CTRL_TYPE_TSD 0 /* TranSwitch Deterministic */ 1437e51b439SBen Hutchings #define TXC_BIST_CTRL_TYPE_CRP 1 /* CRPAT standard */ 1447e51b439SBen Hutchings #define TXC_BIST_CTRL_TYPE_CJP 2 /* CJPAT standard */ 1457e51b439SBen Hutchings #define TXC_BIST_CTRL_TYPE_TSR 3 /* TranSwitch pseudo-random */ 1467e51b439SBen Hutchings /* Set this to 1 for 10 bit and 0 for 8 bit */ 1477e51b439SBen Hutchings #define TXC_BIST_CTRL_B10EN_LBN 12 1487e51b439SBen Hutchings /* Enable BIST (write 0 to disable) */ 1497e51b439SBen Hutchings #define TXC_BIST_CTRL_ENAB_LBN 13 1507e51b439SBen Hutchings /* Stop BIST (self-clears when stop complete) */ 1517e51b439SBen Hutchings #define TXC_BIST_CTRL_STOP_LBN 14 1527e51b439SBen Hutchings /* Start BIST (cleared by writing 1 to STOP) */ 1537e51b439SBen Hutchings #define TXC_BIST_CTRL_STRT_LBN 15 1547e51b439SBen Hutchings 1557e51b439SBen Hutchings /* Mt. Diablo test configuration */ 1567e51b439SBen Hutchings #define TXC_MTDIABLO_CTRL 0xc34f 1577e51b439SBen Hutchings #define TXC_MTDIABLO_CTRL_PMA_LOOP_LBN 10 1587e51b439SBen Hutchings 1597e51b439SBen Hutchings struct txc43128_data { 1607e51b439SBen Hutchings unsigned long bug10934_timer; 1615a6681e2SEdward Cree enum ef4_phy_mode phy_mode; 1625a6681e2SEdward Cree enum ef4_loopback_mode loopback_mode; 1637e51b439SBen Hutchings }; 1647e51b439SBen Hutchings 1657e51b439SBen Hutchings /* The PHY sometimes needs a reset to bring the link back up. So long as 1667e51b439SBen Hutchings * it reports link down, we reset it every 5 seconds. 1677e51b439SBen Hutchings */ 1687e51b439SBen Hutchings #define BUG10934_RESET_INTERVAL (5 * HZ) 1697e51b439SBen Hutchings 1707e51b439SBen Hutchings /* Perform a reset that doesn't clear configuration changes */ 1715a6681e2SEdward Cree static void txc_reset_logic(struct ef4_nic *efx); 1727e51b439SBen Hutchings 1737e51b439SBen Hutchings /* Set the output value of a gpio */ 1745a6681e2SEdward Cree void falcon_txc_set_gpio_val(struct ef4_nic *efx, int pin, int on) 1757e51b439SBen Hutchings { 1765a6681e2SEdward Cree ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_OUTPUT, 1 << pin, on); 1777e51b439SBen Hutchings } 1787e51b439SBen Hutchings 1797e51b439SBen Hutchings /* Set up the GPIO direction register */ 1805a6681e2SEdward Cree void falcon_txc_set_gpio_dir(struct ef4_nic *efx, int pin, int dir) 1817e51b439SBen Hutchings { 1825a6681e2SEdward Cree ef4_mdio_set_flag(efx, MDIO_MMD_PHYXS, TXC_GPIO_DIR, 1 << pin, dir); 1837e51b439SBen Hutchings } 1847e51b439SBen Hutchings 1857e51b439SBen Hutchings /* Reset the PMA/PMD MMD. The documentation is explicit that this does a 1867e51b439SBen Hutchings * global reset (it's less clear what reset of other MMDs does).*/ 1875a6681e2SEdward Cree static int txc_reset_phy(struct ef4_nic *efx) 1887e51b439SBen Hutchings { 1895a6681e2SEdward Cree int rc = ef4_mdio_reset_mmd(efx, MDIO_MMD_PMAPMD, 1907e51b439SBen Hutchings TXC_MAX_RESET_TIME / TXC_RESET_WAIT, 1917e51b439SBen Hutchings TXC_RESET_WAIT); 1927e51b439SBen Hutchings if (rc < 0) 1937e51b439SBen Hutchings goto fail; 1947e51b439SBen Hutchings 1957e51b439SBen Hutchings /* Check that all the MMDs we expect are present and responding. */ 1965a6681e2SEdward Cree rc = ef4_mdio_check_mmds(efx, TXC_REQUIRED_DEVS); 1977e51b439SBen Hutchings if (rc < 0) 1987e51b439SBen Hutchings goto fail; 1997e51b439SBen Hutchings 2007e51b439SBen Hutchings return 0; 2017e51b439SBen Hutchings 2027e51b439SBen Hutchings fail: 2037e51b439SBen Hutchings netif_err(efx, hw, efx->net_dev, TXCNAME ": reset timed out!\n"); 2047e51b439SBen Hutchings return rc; 2057e51b439SBen Hutchings } 2067e51b439SBen Hutchings 2077e51b439SBen Hutchings /* Run a single BIST on one MMD */ 2085a6681e2SEdward Cree static int txc_bist_one(struct ef4_nic *efx, int mmd, int test) 2097e51b439SBen Hutchings { 2107e51b439SBen Hutchings int ctrl, bctl; 2117e51b439SBen Hutchings int lane; 2127e51b439SBen Hutchings int rc = 0; 2137e51b439SBen Hutchings 2147e51b439SBen Hutchings /* Set PMA to test into loopback using Mt Diablo reg as per app note */ 2155a6681e2SEdward Cree ctrl = ef4_mdio_read(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL); 2167e51b439SBen Hutchings ctrl |= (1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); 2175a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl); 2187e51b439SBen Hutchings 2197e51b439SBen Hutchings /* The BIST app. note lists these as 3 distinct steps. */ 2207e51b439SBen Hutchings /* Set the BIST type */ 2217e51b439SBen Hutchings bctl = (test << TXC_BIST_CTRL_TYPE_LBN); 2225a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); 2237e51b439SBen Hutchings 2247e51b439SBen Hutchings /* Set the BSTEN bit in the BIST Control register to enable */ 2257e51b439SBen Hutchings bctl |= (1 << TXC_BIST_CTRL_ENAB_LBN); 2265a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); 2277e51b439SBen Hutchings 2287e51b439SBen Hutchings /* Set the BSTRT bit in the BIST Control register */ 2295a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_BIST_CTL, 2307e51b439SBen Hutchings bctl | (1 << TXC_BIST_CTRL_STRT_LBN)); 2317e51b439SBen Hutchings 2327e51b439SBen Hutchings /* Wait. */ 2337e51b439SBen Hutchings udelay(TXC_BIST_DURATION); 2347e51b439SBen Hutchings 2357e51b439SBen Hutchings /* Set the BSTOP bit in the BIST Control register */ 2367e51b439SBen Hutchings bctl |= (1 << TXC_BIST_CTRL_STOP_LBN); 2375a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_BIST_CTL, bctl); 2387e51b439SBen Hutchings 2397e51b439SBen Hutchings /* The STOP bit should go off when things have stopped */ 2407e51b439SBen Hutchings while (bctl & (1 << TXC_BIST_CTRL_STOP_LBN)) 2415a6681e2SEdward Cree bctl = ef4_mdio_read(efx, mmd, TXC_BIST_CTL); 2427e51b439SBen Hutchings 2437e51b439SBen Hutchings /* Check all the error counts are 0 and all the frame counts are 2447e51b439SBen Hutchings non-zero */ 2457e51b439SBen Hutchings for (lane = 0; lane < 4; lane++) { 2465a6681e2SEdward Cree int count = ef4_mdio_read(efx, mmd, TXC_BIST_RX0ERRCNT + lane); 2477e51b439SBen Hutchings if (count != 0) { 2487e51b439SBen Hutchings netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. " 2497e51b439SBen Hutchings "Lane %d had %d errs\n", lane, count); 2507e51b439SBen Hutchings rc = -EIO; 2517e51b439SBen Hutchings } 2525a6681e2SEdward Cree count = ef4_mdio_read(efx, mmd, TXC_BIST_RX0FRMCNT + lane); 2537e51b439SBen Hutchings if (count == 0) { 2547e51b439SBen Hutchings netif_err(efx, hw, efx->net_dev, TXCNAME": BIST error. " 2557e51b439SBen Hutchings "Lane %d got 0 frames\n", lane); 2567e51b439SBen Hutchings rc = -EIO; 2577e51b439SBen Hutchings } 2587e51b439SBen Hutchings } 2597e51b439SBen Hutchings 2607e51b439SBen Hutchings if (rc == 0) 2617e51b439SBen Hutchings netif_info(efx, hw, efx->net_dev, TXCNAME": BIST pass\n"); 2627e51b439SBen Hutchings 2637e51b439SBen Hutchings /* Disable BIST */ 2645a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_BIST_CTL, 0); 2657e51b439SBen Hutchings 2667e51b439SBen Hutchings /* Turn off loopback */ 2677e51b439SBen Hutchings ctrl &= ~(1 << TXC_MTDIABLO_CTRL_PMA_LOOP_LBN); 2685a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PCS, TXC_MTDIABLO_CTRL, ctrl); 2697e51b439SBen Hutchings 2707e51b439SBen Hutchings return rc; 2717e51b439SBen Hutchings } 2727e51b439SBen Hutchings 2735a6681e2SEdward Cree static int txc_bist(struct ef4_nic *efx) 2747e51b439SBen Hutchings { 2757e51b439SBen Hutchings return txc_bist_one(efx, MDIO_MMD_PCS, TXC_BIST_CTRL_TYPE_TSD); 2767e51b439SBen Hutchings } 2777e51b439SBen Hutchings 2787e51b439SBen Hutchings /* Push the non-configurable defaults into the PHY. This must be 2797e51b439SBen Hutchings * done after every full reset */ 2805a6681e2SEdward Cree static void txc_apply_defaults(struct ef4_nic *efx) 2817e51b439SBen Hutchings { 2827e51b439SBen Hutchings int mctrl; 2837e51b439SBen Hutchings 2847e51b439SBen Hutchings /* Turn amplitude down and preemphasis off on the host side 2857e51b439SBen Hutchings * (PHY<->MAC) as this is believed less likely to upset Falcon 2867e51b439SBen Hutchings * and no adverse effects have been noted. It probably also 2877e51b439SBen Hutchings * saves a picowatt or two */ 2887e51b439SBen Hutchings 2897e51b439SBen Hutchings /* Turn off preemphasis */ 2905a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE0, TXC_ATXPRE_NONE); 2915a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_ALRGS_ATXPRE1, TXC_ATXPRE_NONE); 2927e51b439SBen Hutchings 2937e51b439SBen Hutchings /* Turn down the amplitude */ 2945a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PHYXS, 2957e51b439SBen Hutchings TXC_ALRGS_ATXAMP0, TXC_ATXAMP_0820_BOTH); 2965a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PHYXS, 2977e51b439SBen Hutchings TXC_ALRGS_ATXAMP1, TXC_ATXAMP_0820_BOTH); 2987e51b439SBen Hutchings 2997e51b439SBen Hutchings /* Set the line side amplitude and preemphasis to the databook 3007e51b439SBen Hutchings * defaults as an erratum causes them to be 0 on at least some 3017e51b439SBen Hutchings * PHY rev.s */ 3025a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PMAPMD, 3037e51b439SBen Hutchings TXC_ALRGS_ATXPRE0, TXC_ATXPRE_DEFAULT); 3045a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PMAPMD, 3057e51b439SBen Hutchings TXC_ALRGS_ATXPRE1, TXC_ATXPRE_DEFAULT); 3065a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PMAPMD, 3077e51b439SBen Hutchings TXC_ALRGS_ATXAMP0, TXC_ATXAMP_DEFAULT); 3085a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PMAPMD, 3097e51b439SBen Hutchings TXC_ALRGS_ATXAMP1, TXC_ATXAMP_DEFAULT); 3107e51b439SBen Hutchings 3117e51b439SBen Hutchings /* Set up the LEDs */ 3125a6681e2SEdward Cree mctrl = ef4_mdio_read(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL); 3137e51b439SBen Hutchings 3147e51b439SBen Hutchings /* Set the Green and Red LEDs to their default modes */ 3157e51b439SBen Hutchings mctrl &= ~((1 << TXC_MCTL_TXLED_LBN) | (1 << TXC_MCTL_RXLED_LBN)); 3165a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PHYXS, TXC_MRGS_CTL, mctrl); 3177e51b439SBen Hutchings 3187e51b439SBen Hutchings /* Databook recommends doing this after configuration changes */ 3197e51b439SBen Hutchings txc_reset_logic(efx); 3207e51b439SBen Hutchings 3217e51b439SBen Hutchings falcon_board(efx)->type->init_phy(efx); 3227e51b439SBen Hutchings } 3237e51b439SBen Hutchings 3245a6681e2SEdward Cree static int txc43128_phy_probe(struct ef4_nic *efx) 3257e51b439SBen Hutchings { 3267e51b439SBen Hutchings struct txc43128_data *phy_data; 3277e51b439SBen Hutchings 3287e51b439SBen Hutchings /* Allocate phy private storage */ 3297e51b439SBen Hutchings phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); 3307e51b439SBen Hutchings if (!phy_data) 3317e51b439SBen Hutchings return -ENOMEM; 3327e51b439SBen Hutchings efx->phy_data = phy_data; 3337e51b439SBen Hutchings phy_data->phy_mode = efx->phy_mode; 3347e51b439SBen Hutchings 3357e51b439SBen Hutchings efx->mdio.mmds = TXC_REQUIRED_DEVS; 3367e51b439SBen Hutchings efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; 3377e51b439SBen Hutchings 3387e51b439SBen Hutchings efx->loopback_modes = TXC_LOOPBACKS | FALCON_XMAC_LOOPBACKS; 3397e51b439SBen Hutchings 3407e51b439SBen Hutchings return 0; 3417e51b439SBen Hutchings } 3427e51b439SBen Hutchings 3437e51b439SBen Hutchings /* Initialisation entry point for this PHY driver */ 3445a6681e2SEdward Cree static int txc43128_phy_init(struct ef4_nic *efx) 3457e51b439SBen Hutchings { 3467e51b439SBen Hutchings int rc; 3477e51b439SBen Hutchings 3487e51b439SBen Hutchings rc = txc_reset_phy(efx); 3497e51b439SBen Hutchings if (rc < 0) 3507e51b439SBen Hutchings return rc; 3517e51b439SBen Hutchings 3527e51b439SBen Hutchings rc = txc_bist(efx); 3537e51b439SBen Hutchings if (rc < 0) 3547e51b439SBen Hutchings return rc; 3557e51b439SBen Hutchings 3567e51b439SBen Hutchings txc_apply_defaults(efx); 3577e51b439SBen Hutchings 3587e51b439SBen Hutchings return 0; 3597e51b439SBen Hutchings } 3607e51b439SBen Hutchings 3617e51b439SBen Hutchings /* Set the lane power down state in the global registers */ 3625a6681e2SEdward Cree static void txc_glrgs_lane_power(struct ef4_nic *efx, int mmd) 3637e51b439SBen Hutchings { 3647e51b439SBen Hutchings int pd = (1 << TXC_GLCMD_L01PD_LBN) | (1 << TXC_GLCMD_L23PD_LBN); 3655a6681e2SEdward Cree int ctl = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); 3667e51b439SBen Hutchings 3677e51b439SBen Hutchings if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) 3687e51b439SBen Hutchings ctl &= ~pd; 3697e51b439SBen Hutchings else 3707e51b439SBen Hutchings ctl |= pd; 3717e51b439SBen Hutchings 3725a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, ctl); 3737e51b439SBen Hutchings } 3747e51b439SBen Hutchings 3757e51b439SBen Hutchings /* Set the lane power down state in the analog control registers */ 3765a6681e2SEdward Cree static void txc_analog_lane_power(struct ef4_nic *efx, int mmd) 3777e51b439SBen Hutchings { 3787e51b439SBen Hutchings int txpd = (1 << TXC_ATXCTL_TXPD3_LBN) | (1 << TXC_ATXCTL_TXPD2_LBN) 3797e51b439SBen Hutchings | (1 << TXC_ATXCTL_TXPD1_LBN) | (1 << TXC_ATXCTL_TXPD0_LBN); 3807e51b439SBen Hutchings int rxpd = (1 << TXC_ARXCTL_RXPD3_LBN) | (1 << TXC_ARXCTL_RXPD2_LBN) 3817e51b439SBen Hutchings | (1 << TXC_ARXCTL_RXPD1_LBN) | (1 << TXC_ARXCTL_RXPD0_LBN); 3825a6681e2SEdward Cree int txctl = ef4_mdio_read(efx, mmd, TXC_ALRGS_ATXCTL); 3835a6681e2SEdward Cree int rxctl = ef4_mdio_read(efx, mmd, TXC_ALRGS_ARXCTL); 3847e51b439SBen Hutchings 3857e51b439SBen Hutchings if (!(efx->phy_mode & PHY_MODE_LOW_POWER)) { 3867e51b439SBen Hutchings txctl &= ~txpd; 3877e51b439SBen Hutchings rxctl &= ~rxpd; 3887e51b439SBen Hutchings } else { 3897e51b439SBen Hutchings txctl |= txpd; 3907e51b439SBen Hutchings rxctl |= rxpd; 3917e51b439SBen Hutchings } 3927e51b439SBen Hutchings 3935a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_ALRGS_ATXCTL, txctl); 3945a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_ALRGS_ARXCTL, rxctl); 3957e51b439SBen Hutchings } 3967e51b439SBen Hutchings 3975a6681e2SEdward Cree static void txc_set_power(struct ef4_nic *efx) 3987e51b439SBen Hutchings { 3997e51b439SBen Hutchings /* According to the data book, all the MMDs can do low power */ 4005a6681e2SEdward Cree ef4_mdio_set_mmds_lpower(efx, 4017e51b439SBen Hutchings !!(efx->phy_mode & PHY_MODE_LOW_POWER), 4027e51b439SBen Hutchings TXC_REQUIRED_DEVS); 4037e51b439SBen Hutchings 4047e51b439SBen Hutchings /* Global register bank is in PCS, PHY XS. These control the host 4057e51b439SBen Hutchings * side and line side settings respectively. */ 4067e51b439SBen Hutchings txc_glrgs_lane_power(efx, MDIO_MMD_PCS); 4077e51b439SBen Hutchings txc_glrgs_lane_power(efx, MDIO_MMD_PHYXS); 4087e51b439SBen Hutchings 4097e51b439SBen Hutchings /* Analog register bank in PMA/PMD, PHY XS */ 4107e51b439SBen Hutchings txc_analog_lane_power(efx, MDIO_MMD_PMAPMD); 4117e51b439SBen Hutchings txc_analog_lane_power(efx, MDIO_MMD_PHYXS); 4127e51b439SBen Hutchings } 4137e51b439SBen Hutchings 4145a6681e2SEdward Cree static void txc_reset_logic_mmd(struct ef4_nic *efx, int mmd) 4157e51b439SBen Hutchings { 4165a6681e2SEdward Cree int val = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); 4177e51b439SBen Hutchings int tries = 50; 4187e51b439SBen Hutchings 4197e51b439SBen Hutchings val |= (1 << TXC_GLCMD_LMTSWRST_LBN); 4205a6681e2SEdward Cree ef4_mdio_write(efx, mmd, TXC_GLRGS_GLCMD, val); 421fe0be35eSDan Carpenter while (--tries) { 4225a6681e2SEdward Cree val = ef4_mdio_read(efx, mmd, TXC_GLRGS_GLCMD); 4237e51b439SBen Hutchings if (!(val & (1 << TXC_GLCMD_LMTSWRST_LBN))) 4247e51b439SBen Hutchings break; 4257e51b439SBen Hutchings udelay(1); 4267e51b439SBen Hutchings } 4277e51b439SBen Hutchings if (!tries) 4287e51b439SBen Hutchings netif_info(efx, hw, efx->net_dev, 4297e51b439SBen Hutchings TXCNAME " Logic reset timed out!\n"); 4307e51b439SBen Hutchings } 4317e51b439SBen Hutchings 4327e51b439SBen Hutchings /* Perform a logic reset. This preserves the configuration registers 4337e51b439SBen Hutchings * and is needed for some configuration changes to take effect */ 4345a6681e2SEdward Cree static void txc_reset_logic(struct ef4_nic *efx) 4357e51b439SBen Hutchings { 4367e51b439SBen Hutchings /* The data sheet claims we can do the logic reset on either the 4377e51b439SBen Hutchings * PCS or the PHYXS and the result is a reset of both host- and 4387e51b439SBen Hutchings * line-side logic. */ 4397e51b439SBen Hutchings txc_reset_logic_mmd(efx, MDIO_MMD_PCS); 4407e51b439SBen Hutchings } 4417e51b439SBen Hutchings 4425a6681e2SEdward Cree static bool txc43128_phy_read_link(struct ef4_nic *efx) 4437e51b439SBen Hutchings { 4445a6681e2SEdward Cree return ef4_mdio_links_ok(efx, TXC_REQUIRED_DEVS); 4457e51b439SBen Hutchings } 4467e51b439SBen Hutchings 4475a6681e2SEdward Cree static int txc43128_phy_reconfigure(struct ef4_nic *efx) 4487e51b439SBen Hutchings { 4497e51b439SBen Hutchings struct txc43128_data *phy_data = efx->phy_data; 4505a6681e2SEdward Cree enum ef4_phy_mode mode_change = efx->phy_mode ^ phy_data->phy_mode; 4517e51b439SBen Hutchings bool loop_change = LOOPBACK_CHANGED(phy_data, efx, TXC_LOOPBACKS); 4527e51b439SBen Hutchings 4537e51b439SBen Hutchings if (efx->phy_mode & mode_change & PHY_MODE_TX_DISABLED) { 4547e51b439SBen Hutchings txc_reset_phy(efx); 4557e51b439SBen Hutchings txc_apply_defaults(efx); 4567e51b439SBen Hutchings falcon_reset_xaui(efx); 4577e51b439SBen Hutchings mode_change &= ~PHY_MODE_TX_DISABLED; 4587e51b439SBen Hutchings } 4597e51b439SBen Hutchings 4605a6681e2SEdward Cree ef4_mdio_transmit_disable(efx); 4615a6681e2SEdward Cree ef4_mdio_phy_reconfigure(efx); 4627e51b439SBen Hutchings if (mode_change & PHY_MODE_LOW_POWER) 4637e51b439SBen Hutchings txc_set_power(efx); 4647e51b439SBen Hutchings 4657e51b439SBen Hutchings /* The data sheet claims this is required after every reconfiguration 4667e51b439SBen Hutchings * (note at end of 7.1), but we mustn't do it when nothing changes as 4677e51b439SBen Hutchings * it glitches the link, and reconfigure gets called on link change, 4687e51b439SBen Hutchings * so we get an IRQ storm on link up. */ 4697e51b439SBen Hutchings if (loop_change || mode_change) 4707e51b439SBen Hutchings txc_reset_logic(efx); 4717e51b439SBen Hutchings 4727e51b439SBen Hutchings phy_data->phy_mode = efx->phy_mode; 4737e51b439SBen Hutchings phy_data->loopback_mode = efx->loopback_mode; 4747e51b439SBen Hutchings 4757e51b439SBen Hutchings return 0; 4767e51b439SBen Hutchings } 4777e51b439SBen Hutchings 4785a6681e2SEdward Cree static void txc43128_phy_fini(struct ef4_nic *efx) 4797e51b439SBen Hutchings { 4807e51b439SBen Hutchings /* Disable link events */ 4815a6681e2SEdward Cree ef4_mdio_write(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_CTRL, 0); 4827e51b439SBen Hutchings } 4837e51b439SBen Hutchings 4845a6681e2SEdward Cree static void txc43128_phy_remove(struct ef4_nic *efx) 4857e51b439SBen Hutchings { 4867e51b439SBen Hutchings kfree(efx->phy_data); 4877e51b439SBen Hutchings efx->phy_data = NULL; 4887e51b439SBen Hutchings } 4897e51b439SBen Hutchings 4907e51b439SBen Hutchings /* Periodic callback: this exists mainly to poll link status as we 4917e51b439SBen Hutchings * don't use LASI interrupts */ 4925a6681e2SEdward Cree static bool txc43128_phy_poll(struct ef4_nic *efx) 4937e51b439SBen Hutchings { 4947e51b439SBen Hutchings struct txc43128_data *data = efx->phy_data; 4957e51b439SBen Hutchings bool was_up = efx->link_state.up; 4967e51b439SBen Hutchings 4977e51b439SBen Hutchings efx->link_state.up = txc43128_phy_read_link(efx); 4987e51b439SBen Hutchings efx->link_state.speed = 10000; 4997e51b439SBen Hutchings efx->link_state.fd = true; 5007e51b439SBen Hutchings efx->link_state.fc = efx->wanted_fc; 5017e51b439SBen Hutchings 5027e51b439SBen Hutchings if (efx->link_state.up || (efx->loopback_mode != LOOPBACK_NONE)) { 5037e51b439SBen Hutchings data->bug10934_timer = jiffies; 5047e51b439SBen Hutchings } else { 5057e51b439SBen Hutchings if (time_after_eq(jiffies, (data->bug10934_timer + 5067e51b439SBen Hutchings BUG10934_RESET_INTERVAL))) { 5077e51b439SBen Hutchings data->bug10934_timer = jiffies; 5087e51b439SBen Hutchings txc_reset_logic(efx); 5097e51b439SBen Hutchings } 5107e51b439SBen Hutchings } 5117e51b439SBen Hutchings 5127e51b439SBen Hutchings return efx->link_state.up != was_up; 5137e51b439SBen Hutchings } 5147e51b439SBen Hutchings 51518e83e4cSBen Hutchings static const char *const txc43128_test_names[] = { 5167e51b439SBen Hutchings "bist" 5177e51b439SBen Hutchings }; 5187e51b439SBen Hutchings 5195a6681e2SEdward Cree static const char *txc43128_test_name(struct ef4_nic *efx, unsigned int index) 5207e51b439SBen Hutchings { 5217e51b439SBen Hutchings if (index < ARRAY_SIZE(txc43128_test_names)) 5227e51b439SBen Hutchings return txc43128_test_names[index]; 5237e51b439SBen Hutchings return NULL; 5247e51b439SBen Hutchings } 5257e51b439SBen Hutchings 5265a6681e2SEdward Cree static int txc43128_run_tests(struct ef4_nic *efx, int *results, unsigned flags) 5277e51b439SBen Hutchings { 5287e51b439SBen Hutchings int rc; 5297e51b439SBen Hutchings 5307e51b439SBen Hutchings if (!(flags & ETH_TEST_FL_OFFLINE)) 5317e51b439SBen Hutchings return 0; 5327e51b439SBen Hutchings 5337e51b439SBen Hutchings rc = txc_reset_phy(efx); 5347e51b439SBen Hutchings if (rc < 0) 5357e51b439SBen Hutchings return rc; 5367e51b439SBen Hutchings 5377e51b439SBen Hutchings rc = txc_bist(efx); 5387e51b439SBen Hutchings txc_apply_defaults(efx); 5397e51b439SBen Hutchings results[0] = rc ? -1 : 1; 5407e51b439SBen Hutchings return rc; 5417e51b439SBen Hutchings } 5427e51b439SBen Hutchings 543*e938ed15SPhilippe Reynes static void txc43128_get_link_ksettings(struct ef4_nic *efx, 544*e938ed15SPhilippe Reynes struct ethtool_link_ksettings *cmd) 5457e51b439SBen Hutchings { 546*e938ed15SPhilippe Reynes mdio45_ethtool_ksettings_get(&efx->mdio, cmd); 5477e51b439SBen Hutchings } 5487e51b439SBen Hutchings 5495a6681e2SEdward Cree const struct ef4_phy_operations falcon_txc_phy_ops = { 5507e51b439SBen Hutchings .probe = txc43128_phy_probe, 5517e51b439SBen Hutchings .init = txc43128_phy_init, 5527e51b439SBen Hutchings .reconfigure = txc43128_phy_reconfigure, 5537e51b439SBen Hutchings .poll = txc43128_phy_poll, 5547e51b439SBen Hutchings .fini = txc43128_phy_fini, 5557e51b439SBen Hutchings .remove = txc43128_phy_remove, 556*e938ed15SPhilippe Reynes .get_link_ksettings = txc43128_get_link_ksettings, 557*e938ed15SPhilippe Reynes .set_link_ksettings = ef4_mdio_set_link_ksettings, 5585a6681e2SEdward Cree .test_alive = ef4_mdio_test_alive, 5597e51b439SBen Hutchings .run_tests = txc43128_run_tests, 5607e51b439SBen Hutchings .test_name = txc43128_test_name, 5617e51b439SBen Hutchings }; 562