Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 
0033 #include "common.h"
0034 #include "regs.h"
0035 
0036 enum {
0037     /* MDIO_DEV_PMA_PMD registers */
0038     AQ_LINK_STAT    = 0xe800,
0039     AQ_IMASK_PMA    = 0xf000,
0040 
0041     /* MDIO_DEV_XGXS registers */
0042     AQ_XAUI_RX_CFG  = 0xc400,
0043     AQ_XAUI_TX_CFG  = 0xe400,
0044 
0045     /* MDIO_DEV_ANEG registers */
0046     AQ_1G_CTRL  = 0xc400,
0047     AQ_ANEG_STAT    = 0xc800,
0048 
0049     /* MDIO_DEV_VEND1 registers */
0050     AQ_FW_VERSION   = 0x0020,
0051     AQ_IFLAG_GLOBAL = 0xfc00,
0052     AQ_IMASK_GLOBAL = 0xff00,
0053 };
0054 
0055 enum {
0056     IMASK_PMA   = 1 << 2,
0057     IMASK_GLOBAL    = 1 << 15,
0058     ADV_1G_FULL = 1 << 15,
0059     ADV_1G_HALF = 1 << 14,
0060     ADV_10G_FULL    = 1 << 12,
0061     AQ_RESET    = (1 << 14) | (1 << 15),
0062     AQ_LOWPOWER = 1 << 12,
0063 };
0064 
0065 static int aq100x_reset(struct cphy *phy, int wait)
0066 {
0067     /*
0068      * Ignore the caller specified wait time; always wait for the reset to
0069      * complete. Can take up to 3s.
0070      */
0071     int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000);
0072 
0073     if (err)
0074         CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n",
0075             phy->mdio.prtad, err);
0076 
0077     return err;
0078 }
0079 
0080 static int aq100x_intr_enable(struct cphy *phy)
0081 {
0082     int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA);
0083     if (err)
0084         return err;
0085 
0086     err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL);
0087     return err;
0088 }
0089 
0090 static int aq100x_intr_disable(struct cphy *phy)
0091 {
0092     return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0);
0093 }
0094 
0095 static int aq100x_intr_clear(struct cphy *phy)
0096 {
0097     unsigned int v;
0098 
0099     t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v);
0100     t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
0101 
0102     return 0;
0103 }
0104 
0105 static int aq100x_intr_handler(struct cphy *phy)
0106 {
0107     int err;
0108     unsigned int cause, v;
0109 
0110     err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause);
0111     if (err)
0112         return err;
0113 
0114     /* Read (and reset) the latching version of the status */
0115     t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v);
0116 
0117     return cphy_cause_link_change;
0118 }
0119 
0120 static int aq100x_power_down(struct cphy *phy, int off)
0121 {
0122     return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
0123                  MDIO_MMD_PMAPMD, MDIO_CTRL1,
0124                  MDIO_CTRL1_LPOWER, off);
0125 }
0126 
0127 static int aq100x_autoneg_enable(struct cphy *phy)
0128 {
0129     int err;
0130 
0131     err = aq100x_power_down(phy, 0);
0132     if (!err)
0133         err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
0134                     MDIO_MMD_AN, MDIO_CTRL1,
0135                     BMCR_ANENABLE | BMCR_ANRESTART, 1);
0136 
0137     return err;
0138 }
0139 
0140 static int aq100x_autoneg_restart(struct cphy *phy)
0141 {
0142     int err;
0143 
0144     err = aq100x_power_down(phy, 0);
0145     if (!err)
0146         err = mdio_set_flag(&phy->mdio, phy->mdio.prtad,
0147                     MDIO_MMD_AN, MDIO_CTRL1,
0148                     BMCR_ANENABLE | BMCR_ANRESTART, 1);
0149 
0150     return err;
0151 }
0152 
0153 static int aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
0154 {
0155     unsigned int adv;
0156     int err;
0157 
0158     /* 10G advertisement */
0159     adv = 0;
0160     if (advertise_map & ADVERTISED_10000baseT_Full)
0161         adv |= ADV_10G_FULL;
0162     err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
0163                   ADV_10G_FULL, adv);
0164     if (err)
0165         return err;
0166 
0167     /* 1G advertisement */
0168     adv = 0;
0169     if (advertise_map & ADVERTISED_1000baseT_Full)
0170         adv |= ADV_1G_FULL;
0171     if (advertise_map & ADVERTISED_1000baseT_Half)
0172         adv |= ADV_1G_HALF;
0173     err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL,
0174                   ADV_1G_FULL | ADV_1G_HALF, adv);
0175     if (err)
0176         return err;
0177 
0178     /* 100M, pause advertisement */
0179     adv = 0;
0180     if (advertise_map & ADVERTISED_100baseT_Half)
0181         adv |= ADVERTISE_100HALF;
0182     if (advertise_map & ADVERTISED_100baseT_Full)
0183         adv |= ADVERTISE_100FULL;
0184     if (advertise_map & ADVERTISED_Pause)
0185         adv |= ADVERTISE_PAUSE_CAP;
0186     if (advertise_map & ADVERTISED_Asym_Pause)
0187         adv |= ADVERTISE_PAUSE_ASYM;
0188     err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE,
0189                   0xfe0, adv);
0190 
0191     return err;
0192 }
0193 
0194 static int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
0195 {
0196     return mdio_set_flag(&phy->mdio, phy->mdio.prtad,
0197                  MDIO_MMD_PMAPMD, MDIO_CTRL1,
0198                  BMCR_LOOPBACK, enable);
0199 }
0200 
0201 static int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
0202 {
0203     /* no can do */
0204     return -1;
0205 }
0206 
0207 static int aq100x_get_link_status(struct cphy *phy, int *link_ok,
0208                   int *speed, int *duplex, int *fc)
0209 {
0210     int err;
0211     unsigned int v;
0212 
0213     if (link_ok) {
0214         err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v);
0215         if (err)
0216             return err;
0217 
0218         *link_ok = v & 1;
0219         if (!*link_ok)
0220             return 0;
0221     }
0222 
0223     err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v);
0224     if (err)
0225         return err;
0226 
0227     if (speed) {
0228         switch (v & 0x6) {
0229         case 0x6:
0230             *speed = SPEED_10000;
0231             break;
0232         case 0x4:
0233             *speed = SPEED_1000;
0234             break;
0235         case 0x2:
0236             *speed = SPEED_100;
0237             break;
0238         case 0x0:
0239             *speed = SPEED_10;
0240             break;
0241         }
0242     }
0243 
0244     if (duplex)
0245         *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
0246 
0247     return 0;
0248 }
0249 
0250 static const struct cphy_ops aq100x_ops = {
0251     .reset             = aq100x_reset,
0252     .intr_enable       = aq100x_intr_enable,
0253     .intr_disable      = aq100x_intr_disable,
0254     .intr_clear        = aq100x_intr_clear,
0255     .intr_handler      = aq100x_intr_handler,
0256     .autoneg_enable    = aq100x_autoneg_enable,
0257     .autoneg_restart   = aq100x_autoneg_restart,
0258     .advertise         = aq100x_advertise,
0259     .set_loopback      = aq100x_set_loopback,
0260     .set_speed_duplex  = aq100x_set_speed_duplex,
0261     .get_link_status   = aq100x_get_link_status,
0262     .power_down        = aq100x_power_down,
0263     .mmds          = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS,
0264 };
0265 
0266 int t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr,
0267                const struct mdio_ops *mdio_ops)
0268 {
0269     unsigned int v, v2, gpio, wait;
0270     int err;
0271 
0272     cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops,
0273           SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
0274           SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI,
0275           "1000/10GBASE-T");
0276 
0277     /*
0278      * The PHY has been out of reset ever since the system powered up.  So
0279      * we do a hard reset over here.
0280      */
0281     gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
0282     t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
0283     msleep(1);
0284     t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
0285 
0286     /*
0287      * Give it enough time to load the firmware and get ready for mdio.
0288      */
0289     msleep(1000);
0290     wait = 500; /* in 10ms increments */
0291     do {
0292         err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
0293         if (err || v == 0xffff) {
0294 
0295             /* Allow prep_adapter to succeed when ffff is read */
0296 
0297             CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
0298                 phy_addr, err, v);
0299             goto done;
0300         }
0301 
0302         v &= AQ_RESET;
0303         if (v)
0304             msleep(10);
0305     } while (v && --wait);
0306     if (v) {
0307         CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
0308             phy_addr, v);
0309 
0310         goto done; /* let prep_adapter succeed */
0311     }
0312 
0313     /* Datasheet says 3s max but this has been observed */
0314     wait = (500 - wait) * 10 + 1000;
0315     if (wait > 3000)
0316         CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait);
0317 
0318     /* Firmware version check. */
0319     t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v);
0320     if (v != 101)
0321         CH_WARN(adapter, "PHY%d: unsupported firmware %d\n",
0322             phy_addr, v);
0323 
0324     /*
0325      * The PHY should start in really-low-power mode.  Prepare it for normal
0326      * operations.
0327      */
0328     err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v);
0329     if (err)
0330         return err;
0331     if (v & AQ_LOWPOWER) {
0332         err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1,
0333                       AQ_LOWPOWER, 0);
0334         if (err)
0335             return err;
0336         msleep(10);
0337     } else
0338         CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
0339             phy_addr);
0340 
0341     /*
0342      * Verify XAUI settings, but let prep succeed no matter what.
0343      */
0344     v = v2 = 0;
0345     t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v);
0346     t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2);
0347     if (v != 0x1b || v2 != 0x1b)
0348         CH_WARN(adapter,
0349             "PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n",
0350             phy_addr, v, v2);
0351 
0352 done:
0353     return err;
0354 }