Print this page
212 Atheros AR8132 / L1c Gigabit Ethernet Adapter
   1 /*


























   2  * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice unmodified, this list of conditions, and the following
  10  *    disclaimer.
  11  * 2. Redistributions in binary form must reproduce the above copyright
  12  *    notice, this list of conditions and the following disclaimer in the
  13  *    documentation and/or other materials provided with the distribution.
  14  *
  15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25  * SUCH DAMAGE.
  26  */
  27 
  28 #include <sys/mii.h>
  29 #include <sys/miiregs.h>
  30 
  31 #include "atge.h"
  32 #include "atge_cmn_reg.h"

  33 #include "atge_l1e_reg.h"
  34 #include "atge_l1_reg.h"
  35 
  36 uint16_t
  37 atge_mii_read(void *arg, uint8_t phy, uint8_t reg)
  38 {
  39         atge_t  *atgep = arg;
  40         uint32_t v;
  41         int i;
  42 
  43         mutex_enter(&atgep->atge_mii_lock);
  44 
  45         OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
  46             MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
  47 
  48         for (i = PHY_TIMEOUT; i > 0; i--) {
  49                 drv_usecwait(5);
  50                 v = INL(atgep, ATGE_MDIO);
  51                 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
  52                         break;


  73                         v = 0;
  74         }
  75 
  76         return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
  77 }
  78 
  79 void
  80 atge_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
  81 {
  82         atge_t  *atgep = arg;
  83         uint32_t v;
  84         int i;
  85 
  86         mutex_enter(&atgep->atge_mii_lock);
  87 
  88         OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
  89             (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
  90             MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
  91 
  92         for (i = PHY_TIMEOUT; i > 0; i--) {
  93                 drv_usecwait(1);
  94                 v = INL(atgep, ATGE_MDIO);
  95                 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
  96                         break;
  97         }
  98 
  99         mutex_exit(&atgep->atge_mii_lock);
 100 
 101         if (i == 0) {
 102                 atge_error(atgep->atge_dip, "PHY (%d) write timeout:reg %d,"
 103                     "  val :%d", phy, reg, val);
 104         }
 105 }
 106 
 107 void
 108 atge_l1e_mii_reset(void *arg)
 109 {
 110         atge_t *atgep = arg;
 111         int phyaddr;
 112 
 113         phyaddr = mii_get_addr(atgep->atge_mii);


 193                 }
 194         }
 195 
 196         atge_mii_write(atgep, phyaddr, MII_CONTROL,
 197             MII_CONTROL_RESET |  MII_CONTROL_ANE | MII_CONTROL_RSAN);
 198 
 199         if (linkup == 0) {
 200                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
 201                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x124E);
 202 
 203                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 1);
 204                 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA);
 205                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg | 0x03);
 206 
 207                 drv_usecwait(1500 * 1000);
 208 
 209                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
 210                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x024E);
 211         }
 212 }
















































































































































   1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2012 Gary Mills
  24  *
  25  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  26  */
  27 /*
  28  * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
  29  * All rights reserved.
  30  *
  31  * Redistribution and use in source and binary forms, with or without
  32  * modification, are permitted provided that the following conditions
  33  * are met:
  34  * 1. Redistributions of source code must retain the above copyright
  35  *    notice unmodified, this list of conditions, and the following
  36  *    disclaimer.
  37  * 2. Redistributions in binary form must reproduce the above copyright
  38  *    notice, this list of conditions and the following disclaimer in the
  39  *    documentation and/or other materials provided with the distribution.
  40  *
  41  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51  * SUCH DAMAGE.
  52  */
  53 
  54 #include <sys/mii.h>
  55 #include <sys/miiregs.h>
  56 
  57 #include "atge.h"
  58 #include "atge_cmn_reg.h"
  59 #include "atge_l1c_reg.h"
  60 #include "atge_l1e_reg.h"
  61 #include "atge_l1_reg.h"
  62 
  63 uint16_t
  64 atge_mii_read(void *arg, uint8_t phy, uint8_t reg)
  65 {
  66         atge_t  *atgep = arg;
  67         uint32_t v;
  68         int i;
  69 
  70         mutex_enter(&atgep->atge_mii_lock);
  71 
  72         OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
  73             MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
  74 
  75         for (i = PHY_TIMEOUT; i > 0; i--) {
  76                 drv_usecwait(5);
  77                 v = INL(atgep, ATGE_MDIO);
  78                 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
  79                         break;


 100                         v = 0;
 101         }
 102 
 103         return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
 104 }
 105 
 106 void
 107 atge_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
 108 {
 109         atge_t  *atgep = arg;
 110         uint32_t v;
 111         int i;
 112 
 113         mutex_enter(&atgep->atge_mii_lock);
 114 
 115         OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
 116             (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
 117             MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
 118 
 119         for (i = PHY_TIMEOUT; i > 0; i--) {
 120                 drv_usecwait(5);
 121                 v = INL(atgep, ATGE_MDIO);
 122                 if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
 123                         break;
 124         }
 125 
 126         mutex_exit(&atgep->atge_mii_lock);
 127 
 128         if (i == 0) {
 129                 atge_error(atgep->atge_dip, "PHY (%d) write timeout:reg %d,"
 130                     "  val :%d", phy, reg, val);
 131         }
 132 }
 133 
 134 void
 135 atge_l1e_mii_reset(void *arg)
 136 {
 137         atge_t *atgep = arg;
 138         int phyaddr;
 139 
 140         phyaddr = mii_get_addr(atgep->atge_mii);


 220                 }
 221         }
 222 
 223         atge_mii_write(atgep, phyaddr, MII_CONTROL,
 224             MII_CONTROL_RESET |  MII_CONTROL_ANE | MII_CONTROL_RSAN);
 225 
 226         if (linkup == 0) {
 227                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
 228                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x124E);
 229 
 230                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 1);
 231                 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA);
 232                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg | 0x03);
 233 
 234                 drv_usecwait(1500 * 1000);
 235 
 236                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
 237                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x024E);
 238         }
 239 }
 240 
 241 void
 242 atge_l1c_mii_reset(void *arg)
 243 {
 244         atge_t *atgep = arg;
 245         uint16_t data;
 246         int phyaddr;
 247 
 248         phyaddr = mii_get_addr(atgep->atge_mii);
 249 
 250         /* Reset magic from Linux, via Freebsd */
 251         OUTW(atgep, ATGE_GPHY_CTRL,
 252             GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET);
 253         (void) INW(atgep, ATGE_GPHY_CTRL);
 254         drv_usecwait(10 * 1000);
 255 
 256         OUTW(atgep, ATGE_GPHY_CTRL,
 257             GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE |
 258             GPHY_CTRL_SEL_ANA_RESET);
 259         (void) INW(atgep, ATGE_GPHY_CTRL);
 260         drv_usecwait(10 * 1000);
 261 
 262         /*
 263          * Some fast ethernet chips may not be able to auto-nego with
 264          * switches even though they have 1000T based PHY. Hence we need
 265          * to write 0 to MII_MSCONTROL control register.
 266          */
 267         if (atgep->atge_flags & ATGE_FLAG_FASTETHER)
 268                 atge_mii_write(atgep, phyaddr, MII_MSCONTROL, 0x0);
 269 
 270         /* DSP fixup, Vendor magic. */
 271         switch (ATGE_DID(atgep)) {
 272                 uint16_t reg;
 273 
 274         case ATGE_CHIP_AR8152V1_DEV_ID:
 275                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x000A);
 276                 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA);
 277                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg & 0xDFFF);
 278                 /* FALLTHROUGH */
 279         case ATGE_CHIP_AR8151V2_DEV_ID:
 280         case ATGE_CHIP_AR8151V1_DEV_ID:
 281         case ATGE_CHIP_AR8152V2_DEV_ID:
 282                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x003B);
 283                 reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA);
 284                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg & 0xFFF7);
 285                 drv_usecwait(20 * 1000);
 286                 break;
 287         }
 288 
 289         switch (ATGE_DID(atgep)) {
 290         case ATGE_CHIP_AR8151V1_DEV_ID:
 291                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0029);
 292                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x929D);
 293                 break;
 294         case ATGE_CHIP_AR8151V2_DEV_ID:
 295         case ATGE_CHIP_AR8152V2_DEV_ID:
 296         case ATGE_CHIP_L1CG_DEV_ID:
 297         case ATGE_CHIP_L1CF_DEV_ID:
 298                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0029);
 299                 atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0xB6DD);
 300                 break;
 301         }
 302 
 303         /* Load DSP codes, vendor magic. */
 304         data = ANA_LOOP_SEL_10BT | ANA_EN_MASK_TB | ANA_EN_10BT_IDLE |
 305             ((1 << ANA_INTERVAL_SEL_TIMER_SHIFT) &
 306             ANA_INTERVAL_SEL_TIMER_MASK);
 307         atge_mii_write(atgep, phyaddr,
 308             ATPHY_DBG_ADDR, MII_ANA_CFG18);
 309         atge_mii_write(atgep, phyaddr,
 310             ATPHY_DBG_DATA, data);
 311 
 312         data = ((2 << ANA_SERDES_CDR_BW_SHIFT) & ANA_SERDES_CDR_BW_MASK) |
 313             ANA_MS_PAD_DBG | ANA_SERDES_EN_DEEM | ANA_SERDES_SEL_HSP |
 314             ANA_SERDES_EN_PLL | ANA_SERDES_EN_LCKDT;
 315         atge_mii_write(atgep, phyaddr,
 316             ATPHY_DBG_ADDR, MII_ANA_CFG5);
 317         atge_mii_write(atgep, phyaddr,
 318             ATPHY_DBG_DATA, data);
 319 
 320         data = ((44 << ANA_LONG_CABLE_TH_100_SHIFT) &
 321             ANA_LONG_CABLE_TH_100_MASK) |
 322             ((33 << ANA_SHORT_CABLE_TH_100_SHIFT) &
 323             ANA_SHORT_CABLE_TH_100_SHIFT) |
 324             ANA_BP_BAD_LINK_ACCUM | ANA_BP_SMALL_BW;
 325         atge_mii_write(atgep, phyaddr,
 326             ATPHY_DBG_ADDR, MII_ANA_CFG54);
 327         atge_mii_write(atgep, phyaddr,
 328             ATPHY_DBG_DATA, data);
 329 
 330         data = ((11 << ANA_IECHO_ADJ_3_SHIFT) & ANA_IECHO_ADJ_3_MASK) |
 331             ((11 << ANA_IECHO_ADJ_2_SHIFT) & ANA_IECHO_ADJ_2_MASK) |
 332             ((8 << ANA_IECHO_ADJ_1_SHIFT) & ANA_IECHO_ADJ_1_MASK) |
 333             ((8 << ANA_IECHO_ADJ_0_SHIFT) & ANA_IECHO_ADJ_0_MASK);
 334         atge_mii_write(atgep, phyaddr,
 335             ATPHY_DBG_ADDR, MII_ANA_CFG4);
 336         atge_mii_write(atgep, phyaddr,
 337             ATPHY_DBG_DATA, data);
 338 
 339         data = ((7 & ANA_MANUL_SWICH_ON_SHIFT) & ANA_MANUL_SWICH_ON_MASK) |
 340             ANA_RESTART_CAL | ANA_MAN_ENABLE | ANA_SEL_HSP | ANA_EN_HB |
 341             ANA_OEN_125M;
 342         atge_mii_write(atgep, phyaddr,
 343             ATPHY_DBG_ADDR, MII_ANA_CFG0);
 344         atge_mii_write(atgep, phyaddr,
 345             ATPHY_DBG_DATA, data);
 346         drv_usecwait(1000);
 347 }
 348 
 349 uint16_t
 350 atge_l1c_mii_read(void *arg, uint8_t phy, uint8_t reg)
 351 {
 352 
 353         if (phy != 0) {
 354                 /* avoid PHY address alias */
 355                 return (0xffffU);
 356         }
 357 
 358         return (atge_mii_read(arg, phy, reg));
 359 }
 360 
 361 void
 362 atge_l1c_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
 363 {
 364 
 365         if (phy != 0) {
 366                 /* avoid PHY address alias */
 367                 return;
 368         }
 369 
 370         if (reg == MII_CONTROL) {
 371                 /*
 372                  * Don't issue a reset if MII_CONTROL_RESET is set.
 373                  * Otherwise it occasionally
 374                  * advertises incorrect capability.
 375                  */
 376                 if ((val & MII_CONTROL_RESET) == 0) {
 377                         /* RESET bit is required to set mode */
 378                         atge_mii_write(arg, phy, reg, val | MII_CONTROL_RESET);
 379                 }
 380         } else {
 381                 atge_mii_write(arg, phy, reg, val);
 382         }
 383 }