cxgb_ael1002.c revision 170654
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 170654 2007-06-13 05:36:00Z kmacy $"); 32167514Skmacy 33170076Skmacy#ifdef CONFIG_DEFINED 34170076Skmacy#include <cxgb_include.h> 35170076Skmacy#else 36170076Skmacy#include <dev/cxgb/cxgb_include.h> 37170076Skmacy#endif 38167514Skmacy 39167514Skmacyenum { 40167514Skmacy AEL100X_TX_DISABLE = 9, 41167514Skmacy AEL100X_TX_CONFIG1 = 0xc002, 42167514Skmacy AEL1002_PWR_DOWN_HI = 0xc011, 43167514Skmacy AEL1002_PWR_DOWN_LO = 0xc012, 44167514Skmacy AEL1002_XFI_EQL = 0xc015, 45167514Skmacy AEL1002_LB_EN = 0xc017, 46167514Skmacy 47167514Skmacy LASI_CTRL = 0x9002, 48167514Skmacy LASI_STAT = 0x9005 49167514Skmacy}; 50167514Skmacy 51167514Skmacystatic void ael100x_txon(struct cphy *phy) 52167514Skmacy{ 53167514Skmacy int tx_on_gpio = phy->addr == 0 ? F_GPIO7_OUT_VAL : F_GPIO2_OUT_VAL; 54167514Skmacy 55167514Skmacy t3_os_sleep(100); 56167514Skmacy t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN, 0, tx_on_gpio); 57167514Skmacy t3_os_sleep(30); 58167514Skmacy} 59167514Skmacy 60167514Skmacystatic int ael1002_power_down(struct cphy *phy, int enable) 61167514Skmacy{ 62167514Skmacy int err; 63167514Skmacy 64167514Skmacy err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_DISABLE, !!enable); 65167514Skmacy if (!err) 66167514Skmacy err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 67167514Skmacy BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 68167514Skmacy return err; 69167514Skmacy} 70167514Skmacy 71167514Skmacystatic int ael1002_reset(struct cphy *phy, int wait) 72167514Skmacy{ 73167514Skmacy int err; 74167514Skmacy 75167514Skmacy if ((err = ael1002_power_down(phy, 0)) || 76167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL100X_TX_CONFIG1, 1)) || 77167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_HI, 0)) || 78167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_PWR_DOWN_LO, 0)) || 79167514Skmacy (err = mdio_write(phy, MDIO_DEV_PMA_PMD, AEL1002_XFI_EQL, 0x18)) || 80167514Skmacy (err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, AEL1002_LB_EN, 81167514Skmacy 0, 1 << 5))) 82167514Skmacy return err; 83167514Skmacy return 0; 84167514Skmacy} 85167514Skmacy 86167514Skmacystatic int ael1002_intr_noop(struct cphy *phy) 87167514Skmacy{ 88167514Skmacy return 0; 89167514Skmacy} 90167514Skmacy 91167514Skmacystatic int ael100x_get_link_status(struct cphy *phy, int *link_ok, 92167514Skmacy int *speed, int *duplex, int *fc) 93167514Skmacy{ 94167514Skmacy if (link_ok) { 95167514Skmacy unsigned int status; 96167514Skmacy int err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &status); 97167514Skmacy 98167514Skmacy /* 99167514Skmacy * BMSR_LSTATUS is latch-low, so if it is 0 we need to read it 100167514Skmacy * once more to get the current link state. 101167514Skmacy */ 102167514Skmacy if (!err && !(status & BMSR_LSTATUS)) 103167514Skmacy err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, 104167514Skmacy &status); 105167514Skmacy if (err) 106167514Skmacy return err; 107167514Skmacy *link_ok = !!(status & BMSR_LSTATUS); 108167514Skmacy } 109167514Skmacy if (speed) 110167514Skmacy *speed = SPEED_10000; 111167514Skmacy if (duplex) 112167514Skmacy *duplex = DUPLEX_FULL; 113167514Skmacy return 0; 114167514Skmacy} 115167514Skmacy 116167514Skmacy#ifdef C99_NOT_SUPPORTED 117167514Skmacystatic struct cphy_ops ael1002_ops = { 118167514Skmacy NULL, 119167514Skmacy ael1002_reset, 120167514Skmacy ael1002_intr_noop, 121167514Skmacy ael1002_intr_noop, 122167514Skmacy ael1002_intr_noop, 123167514Skmacy ael1002_intr_noop, 124167514Skmacy NULL, 125167514Skmacy NULL, 126167514Skmacy NULL, 127167514Skmacy NULL, 128167514Skmacy NULL, 129167514Skmacy ael100x_get_link_status, 130167514Skmacy ael1002_power_down, 131167514Skmacy}; 132167514Skmacy#else 133167514Skmacystatic struct cphy_ops ael1002_ops = { 134167514Skmacy .reset = ael1002_reset, 135167514Skmacy .intr_enable = ael1002_intr_noop, 136167514Skmacy .intr_disable = ael1002_intr_noop, 137167514Skmacy .intr_clear = ael1002_intr_noop, 138167514Skmacy .intr_handler = ael1002_intr_noop, 139167514Skmacy .get_link_status = ael100x_get_link_status, 140167514Skmacy .power_down = ael1002_power_down, 141167514Skmacy}; 142167514Skmacy#endif 143167514Skmacy 144167514Skmacyvoid t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 145167514Skmacy const struct mdio_ops *mdio_ops) 146167514Skmacy{ 147167514Skmacy cphy_init(phy, adapter, phy_addr, &ael1002_ops, mdio_ops); 148167514Skmacy ael100x_txon(phy); 149167514Skmacy} 150167514Skmacy 151167514Skmacystatic int ael1006_reset(struct cphy *phy, int wait) 152167514Skmacy{ 153167514Skmacy return t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait); 154167514Skmacy} 155167514Skmacy 156167514Skmacystatic int ael1006_intr_enable(struct cphy *phy) 157167514Skmacy{ 158167514Skmacy return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 1); 159167514Skmacy} 160167514Skmacy 161167514Skmacystatic int ael1006_intr_disable(struct cphy *phy) 162167514Skmacy{ 163167514Skmacy return mdio_write(phy, MDIO_DEV_PMA_PMD, LASI_CTRL, 0); 164167514Skmacy} 165167514Skmacy 166167514Skmacystatic int ael1006_intr_clear(struct cphy *phy) 167167514Skmacy{ 168167514Skmacy u32 val; 169167514Skmacy 170167514Skmacy return mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &val); 171167514Skmacy} 172167514Skmacy 173167514Skmacystatic int ael1006_intr_handler(struct cphy *phy) 174167514Skmacy{ 175167514Skmacy unsigned int status; 176167514Skmacy int err = mdio_read(phy, MDIO_DEV_PMA_PMD, LASI_STAT, &status); 177167514Skmacy 178167514Skmacy if (err) 179167514Skmacy return err; 180167514Skmacy return (status & 1) ? cphy_cause_link_change : 0; 181167514Skmacy} 182167514Skmacy 183167514Skmacystatic int ael1006_power_down(struct cphy *phy, int enable) 184167514Skmacy{ 185167514Skmacy return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, 186167514Skmacy BMCR_PDOWN, enable ? BMCR_PDOWN : 0); 187167514Skmacy} 188167514Skmacy 189167514Skmacy#ifdef C99_NOT_SUPPORTED 190167514Skmacystatic struct cphy_ops ael1006_ops = { 191167514Skmacy NULL, 192167514Skmacy ael1006_reset, 193167514Skmacy ael1006_intr_enable, 194167514Skmacy ael1006_intr_disable, 195167514Skmacy ael1006_intr_clear, 196167514Skmacy ael1006_intr_handler, 197167514Skmacy NULL, 198167514Skmacy NULL, 199167514Skmacy NULL, 200167514Skmacy NULL, 201167514Skmacy NULL, 202167514Skmacy ael100x_get_link_status, 203167514Skmacy ael1006_power_down, 204167514Skmacy}; 205167514Skmacy#else 206167514Skmacystatic struct cphy_ops ael1006_ops = { 207167514Skmacy .reset = ael1006_reset, 208167514Skmacy .intr_enable = ael1006_intr_enable, 209167514Skmacy .intr_disable = ael1006_intr_disable, 210167514Skmacy .intr_clear = ael1006_intr_clear, 211167514Skmacy .intr_handler = ael1006_intr_handler, 212167514Skmacy .get_link_status = ael100x_get_link_status, 213167514Skmacy .power_down = ael1006_power_down, 214167514Skmacy}; 215167514Skmacy#endif 216167514Skmacy 217167514Skmacyvoid t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 218167514Skmacy const struct mdio_ops *mdio_ops) 219167514Skmacy{ 220167514Skmacy cphy_init(phy, adapter, phy_addr, &ael1006_ops, mdio_ops); 221167514Skmacy ael100x_txon(phy); 222167514Skmacy} 223167514Skmacy 224167514Skmacy#ifdef C99_NOT_SUPPORTED 225167514Skmacystatic struct cphy_ops qt2045_ops = { 226167514Skmacy NULL, 227167514Skmacy ael1006_reset, 228167514Skmacy ael1006_intr_enable, 229167514Skmacy ael1006_intr_disable, 230167514Skmacy ael1006_intr_clear, 231167514Skmacy ael1006_intr_handler, 232167514Skmacy NULL, 233167514Skmacy NULL, 234167514Skmacy NULL, 235167514Skmacy NULL, 236167514Skmacy NULL, 237167514Skmacy ael100x_get_link_status, 238167514Skmacy ael1006_power_down, 239167514Skmacy}; 240167514Skmacy#else 241167514Skmacystatic struct cphy_ops qt2045_ops = { 242167514Skmacy .reset = ael1006_reset, 243167514Skmacy .intr_enable = ael1006_intr_enable, 244167514Skmacy .intr_disable = ael1006_intr_disable, 245167514Skmacy .intr_clear = ael1006_intr_clear, 246167514Skmacy .intr_handler = ael1006_intr_handler, 247167514Skmacy .get_link_status = ael100x_get_link_status, 248167514Skmacy .power_down = ael1006_power_down, 249167514Skmacy}; 250167514Skmacy#endif 251167514Skmacy 252167514Skmacyvoid t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 253167514Skmacy const struct mdio_ops *mdio_ops) 254167514Skmacy{ 255167514Skmacy unsigned int stat; 256167514Skmacy 257167514Skmacy cphy_init(phy, adapter, phy_addr, &qt2045_ops, mdio_ops); 258167514Skmacy 259167514Skmacy /* 260167514Skmacy * Some cards where the PHY is supposed to be at address 0 actually 261167514Skmacy * have it at 1. 262167514Skmacy */ 263167514Skmacy if (!phy_addr && !mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMSR, &stat) && 264167514Skmacy stat == 0xffff) 265167514Skmacy phy->addr = 1; 266167514Skmacy} 267167514Skmacy 268167514Skmacystatic int xaui_direct_reset(struct cphy *phy, int wait) 269167514Skmacy{ 270167514Skmacy return 0; 271167514Skmacy} 272167514Skmacy 273167514Skmacystatic int xaui_direct_get_link_status(struct cphy *phy, int *link_ok, 274167514Skmacy int *speed, int *duplex, int *fc) 275167514Skmacy{ 276167514Skmacy if (link_ok) { 277167514Skmacy unsigned int status; 278167514Skmacy 279167514Skmacy status = t3_read_reg(phy->adapter, 280170654Skmacy XGM_REG(A_XGM_SERDES_STAT0, phy->addr)) | 281170654Skmacy t3_read_reg(phy->adapter, 282170654Skmacy XGM_REG(A_XGM_SERDES_STAT1, phy->addr)) | 283170654Skmacy t3_read_reg(phy->adapter, 284170654Skmacy XGM_REG(A_XGM_SERDES_STAT2, phy->addr)) | 285170654Skmacy t3_read_reg(phy->adapter, 286170654Skmacy XGM_REG(A_XGM_SERDES_STAT3, phy->addr)); 287167514Skmacy *link_ok = !(status & F_LOWSIG0); 288167514Skmacy } 289167514Skmacy if (speed) 290167514Skmacy *speed = SPEED_10000; 291167514Skmacy if (duplex) 292167514Skmacy *duplex = DUPLEX_FULL; 293167514Skmacy return 0; 294167514Skmacy} 295167514Skmacy 296167514Skmacystatic int xaui_direct_power_down(struct cphy *phy, int enable) 297167514Skmacy{ 298167514Skmacy return 0; 299167514Skmacy} 300167514Skmacy 301167514Skmacy#ifdef C99_NOT_SUPPORTED 302167514Skmacystatic struct cphy_ops xaui_direct_ops = { 303167514Skmacy NULL, 304167514Skmacy xaui_direct_reset, 305167514Skmacy ael1002_intr_noop, 306167514Skmacy ael1002_intr_noop, 307167514Skmacy ael1002_intr_noop, 308167514Skmacy ael1002_intr_noop, 309167514Skmacy NULL, 310167514Skmacy NULL, 311167514Skmacy NULL, 312167514Skmacy NULL, 313167514Skmacy NULL, 314167514Skmacy xaui_direct_get_link_status, 315167514Skmacy xaui_direct_power_down, 316167514Skmacy}; 317167514Skmacy#else 318167514Skmacystatic struct cphy_ops xaui_direct_ops = { 319167514Skmacy .reset = xaui_direct_reset, 320167514Skmacy .intr_enable = ael1002_intr_noop, 321167514Skmacy .intr_disable = ael1002_intr_noop, 322167514Skmacy .intr_clear = ael1002_intr_noop, 323167514Skmacy .intr_handler = ael1002_intr_noop, 324167514Skmacy .get_link_status = xaui_direct_get_link_status, 325167514Skmacy .power_down = xaui_direct_power_down, 326167514Skmacy}; 327167514Skmacy#endif 328167514Skmacy 329167514Skmacyvoid t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr, 330167514Skmacy const struct mdio_ops *mdio_ops) 331167514Skmacy{ 332170654Skmacy cphy_init(phy, adapter, phy_addr, &xaui_direct_ops, mdio_ops); 333167514Skmacy} 334