cxgb_ael1002.c revision 176472
1167514Skmacy/************************************************************************** 2167514Skmacy 3167514SkmacyCopyright (c) 2007, Chelsio Inc. 4167514SkmacyAll rights reserved. 5167514Skmacy 6167514SkmacyRedistribution and use in source and binary forms, with or without 7167514Skmacymodification, are permitted provided that the following conditions are met: 8167514Skmacy 9167514Skmacy 1. Redistributions of source code must retain the above copyright notice, 10167514Skmacy this list of conditions and the following disclaimer. 11167514Skmacy 12170076Skmacy 2. Neither the name of the Chelsio Corporation nor the names of its 13167514Skmacy contributors may be used to endorse or promote products derived from 14167514Skmacy this software without specific prior written permission. 15167514Skmacy 16167514SkmacyTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17167514SkmacyAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18167514SkmacyIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19167514SkmacyARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20167514SkmacyLIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21167514SkmacyCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22167514SkmacySUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23167514SkmacyINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24167514SkmacyCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25167514SkmacyARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26167514SkmacyPOSSIBILITY OF SUCH DAMAGE. 27167514Skmacy 28167514Skmacy***************************************************************************/ 29167514Skmacy 30167514Skmacy#include <sys/cdefs.h> 31167514Skmacy__FBSDID("$FreeBSD: head/sys/dev/cxgb/common/cxgb_ael1002.c 176472 2008-02-23 01:06:17Z kmacy $"); 32167514Skmacy 33170076Skmacy#ifdef CONFIG_DEFINED 34170076Skmacy#include <cxgb_include.h> 35170076Skmacy#else 36170076Skmacy#include <dev/cxgb/cxgb_include.h> 37170076Skmacy#endif 38167514Skmacy 39176472Skmacy#undef msleep 40176472Skmacy#define msleep t3_os_sleep 41176472Skmacy 42167514Skmacyenum { 43167514Skmacy AEL100X_TX_DISABLE = 9, 44167514Skmacy AEL100X_TX_CONFIG1 = 0xc002, 45167514Skmacy AEL1002_PWR_DOWN_HI = 0xc011, 46167514Skmacy AEL1002_PWR_DOWN_LO = 0xc012, 47167514Skmacy AEL1002_XFI_EQL = 0xc015, 48167514Skmacy AEL1002_LB_EN = 0xc017, 49167514Skmacy 50167514Skmacy LASI_CTRL = 0x9002, 51167514Skmacy LASI_STAT = 0x9005 52167514Skmacy}; 53167514Skmacy 54167514Skmacystatic void ael100x_txon(struct cphy *phy) 55167514Skmacy{ 56167514Skmacy int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; 57167514Skmacy 58176472Skmacy msleep(100); 59167514Skmacy t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); 60176472Skmacy msleep(30); 61167514Skmacy} 62167514Skmacy 63167514Skmacystatic int ael1002_power_down(struct cphy *phy, int enable) 64167514Skmacy{ 65167514Skmacy int err; 66167514Skmacy 67167514Skmacy err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); 68167514Skmacy if (!err) 69167514Skmacy err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 70167514Skmacy BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 71167514Skmacy return err; 72167514Skmacy} 73167514Skmacy 74167514Skmacystatic int ael1002_reset(struct cphy *phy, int wait) 75167514Skmacy{ 76167514Skmacy int err; 77167514Skmacy 78167514Skmacy if ((err = ael1002_power_down(phy, 0)) || 79167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || 80167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || 81167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || 82167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || 83167514Skmacy (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, 84167514Skmacy 0, 1 << 5))) 85167514Skmacy return err; 86167514Skmacy return 0; 87167514Skmacy} 88167514Skmacy 89167514Skmacystatic int ael1002_intr_noop(struct cphy *phy) 90167514Skmacy{ 91167514Skmacy return 0; 92167514Skmacy} 93167514Skmacy 94167514Skmacystatic int ael100x_get_link_status(struct cphy *phy, int *link_ok, 95167514Skmacy int *speed, int *duplex, int *fc) 96167514Skmacy{ 97167514Skmacy if (link_ok) { 98167514Skmacy unsigned int status; 99167514Skmacy int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status); 100167514Skmacy 101167514Skmacy /* 102167514Skmacy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it 103167514Skmacy * once more to get the current link state. 104167514Skmacy */ 105167514Skmacy if (!err && !(status & BMSR_LSTATUS)) 106167514Skmacy err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, 107167514Skmacy &status); 108167514Skmacy if (err) 109167514Skmacy return err; 110167514Skmacy *link_ok = !!(status & BMSR_LSTATUS); 111167514Skmacy } 112167514Skmacy if (speed) 113167514Skmacy *speed = SPEED_10000; 114167514Skmacy if (duplex) 115167514Skmacy *duplex = DUPLEX_FULL; 116167514Skmacy return 0; 117167514Skmacy} 118167514Skmacy 119167514Skmacy#ifdef C99_NOT_SUPPORTED 120167514Skmacystatic struct cphy_ops ael1002_ops = { 121167514Skmacy ael1002_reset, 122167514Skmacy ael1002_intr_noop, 123167514Skmacy ael1002_intr_noop, 124167514Skmacy ael1002_intr_noop, 125167514Skmacy ael1002_intr_noop, 126167514Skmacy NULL, 127167514Skmacy NULL, 128167514Skmacy NULL, 129167514Skmacy NULL, 130167514Skmacy NULL, 131167514Skmacy ael100x_get_link_status, 132167514Skmacy ael1002_power_down, 133167514Skmacy}; 134167514Skmacy#else 135167514Skmacystatic struct cphy_ops ael1002_ops = { 136167514Skmacy .reset = ael1002_reset, 137167514Skmacy .intr_enable = ael1002_intr_noop, 138167514Skmacy .intr_disable = ael1002_intr_noop, 139167514Skmacy .intr_clear = ael1002_intr_noop, 140167514Skmacy .intr_handler = ael1002_intr_noop, 141167514Skmacy .get_link_status = ael100x_get_link_status, 142167514Skmacy .power_down = ael1002_power_down, 143167514Skmacy}; 144167514Skmacy#endif 145167514Skmacy 146176472Skmacyint t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 147176472Skmacy const struct mdio_ops *mdio_ops) 148167514Skmacy{ 149176472Skmacy cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops, 150176472Skmacy SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 151176472Skmacy "10GBASE-XR"); 152167514Skmacy ael100x_txon(phy); 153176472Skmacy return 0; 154167514Skmacy} 155167514Skmacy 156167514Skmacystatic int ael1006_reset(struct cphy *phy, int wait) 157167514Skmacy{ 158167514Skmacy return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 159167514Skmacy} 160167514Skmacy 161167514Skmacystatic int ael1006_intr_enable(struct cphy *phy) 162167514Skmacy{ 163167514Skmacy return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); 164167514Skmacy} 165167514Skmacy 166167514Skmacystatic int ael1006_intr_disable(struct cphy *phy) 167167514Skmacy{ 168167514Skmacy return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); 169167514Skmacy} 170167514Skmacy 171167514Skmacystatic int ael1006_intr_clear(struct cphy *phy) 172167514Skmacy{ 173167514Skmacy u32 val; 174167514Skmacy 175167514Skmacy return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); 176167514Skmacy} 177167514Skmacy 178167514Skmacystatic int ael1006_intr_handler(struct cphy *phy) 179167514Skmacy{ 180167514Skmacy unsigned int status; 181167514Skmacy int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); 182167514Skmacy 183167514Skmacy if (err) 184167514Skmacy return err; 185167514Skmacy return (status & 1) ? cphy_cause_link_change : 0; 186167514Skmacy} 187167514Skmacy 188167514Skmacystatic int ael1006_power_down(struct cphy *phy, int enable) 189167514Skmacy{ 190167514Skmacy return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 191167514Skmacy BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 192167514Skmacy} 193167514Skmacy 194167514Skmacy#ifdef C99_NOT_SUPPORTED 195167514Skmacystatic struct cphy_ops ael1006_ops = { 196167514Skmacy ael1006_reset, 197167514Skmacy ael1006_intr_enable, 198167514Skmacy ael1006_intr_disable, 199167514Skmacy ael1006_intr_clear, 200167514Skmacy ael1006_intr_handler, 201167514Skmacy NULL, 202167514Skmacy NULL, 203167514Skmacy NULL, 204167514Skmacy NULL, 205167514Skmacy NULL, 206167514Skmacy ael100x_get_link_status, 207167514Skmacy ael1006_power_down, 208167514Skmacy}; 209167514Skmacy#else 210167514Skmacystatic struct cphy_ops ael1006_ops = { 211167514Skmacy .reset = ael1006_reset, 212167514Skmacy .intr_enable = ael1006_intr_enable, 213167514Skmacy .intr_disable = ael1006_intr_disable, 214167514Skmacy .intr_clear = ael1006_intr_clear, 215167514Skmacy .intr_handler = ael1006_intr_handler, 216167514Skmacy .get_link_status = ael100x_get_link_status, 217167514Skmacy .power_down = ael1006_power_down, 218167514Skmacy}; 219167514Skmacy#endif 220167514Skmacy 221176472Skmacyint t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 222176472Skmacy const struct mdio_ops *mdio_ops) 223167514Skmacy{ 224176472Skmacy cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops, 225176472Skmacy SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_FIBRE, 226176472Skmacy "10GBASE-SR"); 227167514Skmacy ael100x_txon(phy); 228176472Skmacy return 0; 229167514Skmacy} 230167514Skmacy 231167514Skmacy#ifdef C99_NOT_SUPPORTED 232167514Skmacystatic struct cphy_ops qt2045_ops = { 233167514Skmacy ael1006_reset, 234167514Skmacy ael1006_intr_enable, 235167514Skmacy ael1006_intr_disable, 236167514Skmacy ael1006_intr_clear, 237167514Skmacy ael1006_intr_handler, 238167514Skmacy NULL, 239167514Skmacy NULL, 240167514Skmacy NULL, 241167514Skmacy NULL, 242167514Skmacy NULL, 243167514Skmacy ael100x_get_link_status, 244167514Skmacy ael1006_power_down, 245167514Skmacy}; 246167514Skmacy#else 247167514Skmacystatic struct cphy_ops qt2045_ops = { 248167514Skmacy .reset = ael1006_reset, 249167514Skmacy .intr_enable = ael1006_intr_enable, 250167514Skmacy .intr_disable = ael1006_intr_disable, 251167514Skmacy .intr_clear = ael1006_intr_clear, 252167514Skmacy .intr_handler = ael1006_intr_handler, 253167514Skmacy .get_link_status = ael100x_get_link_status, 254167514Skmacy .power_down = ael1006_power_down, 255167514Skmacy}; 256167514Skmacy#endif 257167514Skmacy 258176472Skmacyint t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 259176472Skmacy const struct mdio_ops *mdio_ops) 260167514Skmacy{ 261167514Skmacy unsigned int stat; 262167514Skmacy 263176472Skmacy cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops, 264176472Skmacy SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 265176472Skmacy "10GBASE-CX4"); 266167514Skmacy 267167514Skmacy /* 268167514Skmacy * Some cards where the PHY is supposed to be at address 0 actually 269167514Skmacy * have it at 1. 270167514Skmacy */ 271167514Skmacy if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && 272167514Skmacy stat == 0xffff) 273167514Skmacy phy->addr = 1; 274176472Skmacy return 0; 275167514Skmacy} 276167514Skmacy 277167514Skmacystatic int xaui_direct_reset(struct cphy *phy, int wait) 278167514Skmacy{ 279167514Skmacy return 0; 280167514Skmacy} 281167514Skmacy 282167514Skmacystatic int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, 283167514Skmacy int *speed, int *duplex, int *fc) 284167514Skmacy{ 285167514Skmacy if (link_ok) { 286167514Skmacy unsigned int status; 287167514Skmacy 288167514Skmacy status = t3_read_reg(phy->adapter, 289170654Skmacy XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | 290170654Skmacy t3_read_reg(phy->adapter, 291170654Skmacy XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | 292170654Skmacy t3_read_reg(phy->adapter, 293170654Skmacy XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | 294170654Skmacy t3_read_reg(phy->adapter, 295170654Skmacy XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); 296167514Skmacy *link_ok = !(status & F_LOWSIG0); 297167514Skmacy } 298167514Skmacy if (speed) 299167514Skmacy *speed = SPEED_10000; 300167514Skmacy if (duplex) 301167514Skmacy *duplex = DUPLEX_FULL; 302167514Skmacy return 0; 303167514Skmacy} 304167514Skmacy 305167514Skmacystatic int xaui_direct_power_down(struct cphy *phy, int enable) 306167514Skmacy{ 307167514Skmacy return 0; 308167514Skmacy} 309167514Skmacy 310167514Skmacy#ifdef C99_NOT_SUPPORTED 311167514Skmacystatic struct cphy_ops xaui_direct_ops = { 312167514Skmacy xaui_direct_reset, 313167514Skmacy ael1002_intr_noop, 314167514Skmacy ael1002_intr_noop, 315167514Skmacy ael1002_intr_noop, 316167514Skmacy ael1002_intr_noop, 317167514Skmacy NULL, 318167514Skmacy NULL, 319167514Skmacy NULL, 320167514Skmacy NULL, 321167514Skmacy NULL, 322167514Skmacy xaui_direct_get_link_status, 323167514Skmacy xaui_direct_power_down, 324167514Skmacy}; 325167514Skmacy#else 326167514Skmacystatic struct cphy_ops xaui_direct_ops = { 327167514Skmacy .reset = xaui_direct_reset, 328167514Skmacy .intr_enable = ael1002_intr_noop, 329167514Skmacy .intr_disable = ael1002_intr_noop, 330167514Skmacy .intr_clear = ael1002_intr_noop, 331167514Skmacy .intr_handler = ael1002_intr_noop, 332167514Skmacy .get_link_status = xaui_direct_get_link_status, 333167514Skmacy .power_down = xaui_direct_power_down, 334167514Skmacy}; 335167514Skmacy#endif 336167514Skmacy 337176472Skmacyint t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 338176472Skmacy const struct mdio_ops *mdio_ops) 339167514Skmacy{ 340176472Skmacy cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops, 341176472Skmacy SUPPORTED_10000baseT_Full | SUPPORTED_AUI | SUPPORTED_TP, 342176472Skmacy "10GBASE-CX4"); 343176472Skmacy return 0; 344167514Skmacy} 345