1/* 2 * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33#include "common.h" 34#include "regs.h" 35 36enum { 37 /* MDIO_DEV_PMA_PMD registers */ 38 AQ_LINK_STAT = 0xe800, 39 AQ_IMASK_PMA = 0xf000, 40 41 /* MDIO_DEV_XGXS registers */ 42 AQ_XAUI_RX_CFG = 0xc400, 43 AQ_XAUI_TX_CFG = 0xe400, 44 45 /* MDIO_DEV_ANEG registers */ 46 AQ_1G_CTRL = 0xc400, 47 AQ_ANEG_STAT = 0xc800, 48 49 /* MDIO_DEV_VEND1 registers */ 50 AQ_FW_VERSION = 0x0020, 51 AQ_IFLAG_GLOBAL = 0xfc00, 52 AQ_IMASK_GLOBAL = 0xff00, 53}; 54 55enum { 56 IMASK_PMA = 1 << 2, 57 IMASK_GLOBAL = 1 << 15, 58 ADV_1G_FULL = 1 << 15, 59 ADV_1G_HALF = 1 << 14, 60 ADV_10G_FULL = 1 << 12, 61 AQ_RESET = (1 << 14) | (1 << 15), 62 AQ_LOWPOWER = 1 << 12, 63}; 64 65static int aq100x_reset(struct cphy *phy, int wait) 66{ 67 /* 68 * Ignore the caller specified wait time; always wait for the reset to 69 * complete. Can take up to 3s. 70 */ 71 int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000); 72 73 if (err) 74 CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n", 75 phy->mdio.prtad, err); 76 77 return err; 78} 79 80static int aq100x_intr_enable(struct cphy *phy) 81{ 82 int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA); 83 if (err) 84 return err; 85 86 err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL); 87 return err; 88} 89 90static int aq100x_intr_disable(struct cphy *phy) 91{ 92 return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0); 93} 94 95static int aq100x_intr_clear(struct cphy *phy) 96{ 97 unsigned int v; 98 99 t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v); 100 t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); 101 102 return 0; 103} 104 105static int aq100x_intr_handler(struct cphy *phy) 106{ 107 int err; 108 unsigned int cause, v; 109 110 err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause); 111 if (err) 112 return err; 113 114 /* Read (and reset) the latching version of the status */ 115 t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); 116 117 return cphy_cause_link_change; 118} 119 120static int aq100x_power_down(struct cphy *phy, int off) 121{ 122 return mdio_set_flag(&phy->mdio, phy->mdio.prtad, 123 MDIO_MMD_PMAPMD, MDIO_CTRL1, 124 MDIO_CTRL1_LPOWER, off); 125} 126 127static int aq100x_autoneg_enable(struct cphy *phy) 128{ 129 int err; 130 131 err = aq100x_power_down(phy, 0); 132 if (!err) 133 err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, 134 MDIO_MMD_AN, MDIO_CTRL1, 135 BMCR_ANENABLE | BMCR_ANRESTART, 1); 136 137 return err; 138} 139 140static int aq100x_autoneg_restart(struct cphy *phy) 141{ 142 int err; 143 144 err = aq100x_power_down(phy, 0); 145 if (!err) 146 err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, 147 MDIO_MMD_AN, MDIO_CTRL1, 148 BMCR_ANENABLE | BMCR_ANRESTART, 1); 149 150 return err; 151} 152 153static int aq100x_advertise(struct cphy *phy, unsigned int advertise_map) 154{ 155 unsigned int adv; 156 int err; 157 158 /* 10G advertisement */ 159 adv = 0; 160 if (advertise_map & ADVERTISED_10000baseT_Full) 161 adv |= ADV_10G_FULL; 162 err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, 163 ADV_10G_FULL, adv); 164 if (err) 165 return err; 166 167 /* 1G advertisement */ 168 adv = 0; 169 if (advertise_map & ADVERTISED_1000baseT_Full) 170 adv |= ADV_1G_FULL; 171 if (advertise_map & ADVERTISED_1000baseT_Half) 172 adv |= ADV_1G_HALF; 173 err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL, 174 ADV_1G_FULL | ADV_1G_HALF, adv); 175 if (err) 176 return err; 177 178 /* 100M, pause advertisement */ 179 adv = 0; 180 if (advertise_map & ADVERTISED_100baseT_Half) 181 adv |= ADVERTISE_100HALF; 182 if (advertise_map & ADVERTISED_100baseT_Full) 183 adv |= ADVERTISE_100FULL; 184 if (advertise_map & ADVERTISED_Pause) 185 adv |= ADVERTISE_PAUSE_CAP; 186 if (advertise_map & ADVERTISED_Asym_Pause) 187 adv |= ADVERTISE_PAUSE_ASYM; 188 err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE, 189 0xfe0, adv); 190 191 return err; 192} 193 194static int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable) 195{ 196 return mdio_set_flag(&phy->mdio, phy->mdio.prtad, 197 MDIO_MMD_PMAPMD, MDIO_CTRL1, 198 BMCR_LOOPBACK, enable); 199} 200 201static int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex) 202{ 203 /* no can do */ 204 return -1; 205} 206 207static int aq100x_get_link_status(struct cphy *phy, int *link_ok, 208 int *speed, int *duplex, int *fc) 209{ 210 int err; 211 unsigned int v; 212 213 if (link_ok) { 214 err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v); 215 if (err) 216 return err; 217 218 *link_ok = v & 1; 219 if (!*link_ok) 220 return 0; 221 } 222 223 err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v); 224 if (err) 225 return err; 226 227 if (speed) { 228 switch (v & 0x6) { 229 case 0x6: 230 *speed = SPEED_10000; 231 break; 232 case 0x4: 233 *speed = SPEED_1000; 234 break; 235 case 0x2: 236 *speed = SPEED_100; 237 break; 238 case 0x0: 239 *speed = SPEED_10; 240 break; 241 } 242 } 243 244 if (duplex) 245 *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF; 246 247 return 0; 248} 249 250static struct cphy_ops aq100x_ops = { 251 .reset = aq100x_reset, 252 .intr_enable = aq100x_intr_enable, 253 .intr_disable = aq100x_intr_disable, 254 .intr_clear = aq100x_intr_clear, 255 .intr_handler = aq100x_intr_handler, 256 .autoneg_enable = aq100x_autoneg_enable, 257 .autoneg_restart = aq100x_autoneg_restart, 258 .advertise = aq100x_advertise, 259 .set_loopback = aq100x_set_loopback, 260 .set_speed_duplex = aq100x_set_speed_duplex, 261 .get_link_status = aq100x_get_link_status, 262 .power_down = aq100x_power_down, 263 .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, 264}; 265 266int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, 267 const struct mdio_ops *mdio_ops) 268{ 269 unsigned int v, v2, gpio, wait; 270 int err; 271 272 cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops, 273 SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full | 274 SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI, 275 "1000/10GBASE-T"); 276 277 /* 278 * The PHY has been out of reset ever since the system powered up. So 279 * we do a hard reset over here. 280 */ 281 gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL; 282 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0); 283 msleep(1); 284 t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio); 285 286 /* 287 * Give it enough time to load the firmware and get ready for mdio. 288 */ 289 msleep(1000); 290 wait = 500; /* in 10ms increments */ 291 do { 292 err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); 293 if (err || v == 0xffff) { 294 295 /* Allow prep_adapter to succeed when ffff is read */ 296 297 CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n", 298 phy_addr, err, v); 299 goto done; 300 } 301 302 v &= AQ_RESET; 303 if (v) 304 msleep(10); 305 } while (v && --wait); 306 if (v) { 307 CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n", 308 phy_addr, v); 309 310 goto done; /* let prep_adapter succeed */ 311 } 312 313 /* Datasheet says 3s max but this has been observed */ 314 wait = (500 - wait) * 10 + 1000; 315 if (wait > 3000) 316 CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait); 317 318 /* Firmware version check. */ 319 t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v); 320 if (v != 101) 321 CH_WARN(adapter, "PHY%d: unsupported firmware %d\n", 322 phy_addr, v); 323 324 /* 325 * The PHY should start in really-low-power mode. Prepare it for normal 326 * operations. 327 */ 328 err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); 329 if (err) 330 return err; 331 if (v & AQ_LOWPOWER) { 332 err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1, 333 AQ_LOWPOWER, 0); 334 if (err) 335 return err; 336 msleep(10); 337 } else 338 CH_WARN(adapter, "PHY%d does not start in low power mode.\n", 339 phy_addr); 340 341 /* 342 * Verify XAUI settings, but let prep succeed no matter what. 343 */ 344 v = v2 = 0; 345 t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v); 346 t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2); 347 if (v != 0x1b || v2 != 0x1b) 348 CH_WARN(adapter, 349 "PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n", 350 phy_addr, v, v2); 351 352done: 353 return err; 354} 355