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;
  53         }
  54 
  55         mutex_exit(&atgep->atge_mii_lock);
  56 
  57         if (i == 0) {
  58                 atge_error(atgep->atge_dip, "PHY (%d) read timeout : %d",
  59                     phy, reg);
  60 
  61                 return (0xffff);
  62         }
  63 
  64         /*
  65          * Some fast ethernet chips may not be able to auto-nego with
  66          * switches even though they have 1000T based PHY. Hence we mask
  67          * 1000T based capabilities.
  68          */
  69         if (atgep->atge_flags & ATGE_FLAG_FASTETHER) {
  70                 if (reg == MII_STATUS)
  71                         v &= ~MII_STATUS_EXTSTAT;
  72                 else if (reg == MII_EXTSTATUS)
  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);
 114 
 115         OUTW(atgep, ATGE_GPHY_CTRL,
 116             GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET |
 117             GPHY_CTRL_PHY_PLL_ON);
 118         drv_usecwait(1000);
 119 
 120         OUTW(atgep, ATGE_GPHY_CTRL,
 121             GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE |
 122             GPHY_CTRL_SEL_ANA_RESET | GPHY_CTRL_PHY_PLL_ON);
 123         drv_usecwait(1000);
 124 
 125         /*
 126          * Some fast ethernet chips may not be able to auto-nego with
 127          * switches even though they have 1000T based PHY. Hence we need
 128          * to write 0 to MII_MSCONTROL control register.
 129          */
 130         if (atgep->atge_flags & ATGE_FLAG_FASTETHER)
 131                 atge_mii_write(atgep, phyaddr, MII_MSCONTROL, 0x0);
 132 
 133         /* Enable hibernation mode. */
 134         atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0B);
 135         atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0xBC00);
 136 
 137         /* Set Class A/B for all modes. */
 138         atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x00);
 139         atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x02EF);
 140 
 141         /* Enable 10BT power saving. */
 142         atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x12);
 143         atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x4C04);
 144 
 145         /* Adjust 1000T power. */
 146         atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x04);
 147         atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x8BBB);
 148 
 149         /* 10BT center tap voltage. */
 150         atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x05);
 151         atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x2C46);
 152         drv_usecwait(1000);
 153 }
 154 
 155 void
 156 atge_l1_mii_reset(void *arg)
 157 {
 158         atge_t *atgep = arg;
 159         int linkup, i;
 160         uint16_t reg, pn;
 161         int phyaddr;
 162 
 163         phyaddr = mii_get_addr(atgep->atge_mii);
 164 
 165         OUTL(atgep, ATGE_GPHY_CTRL, GPHY_CTRL_RST);
 166         drv_usecwait(1000);
 167 
 168         OUTL(atgep, ATGE_GPHY_CTRL, GPHY_CTRL_CLR);
 169         drv_usecwait(1000);
 170 
 171         atge_mii_write(atgep, phyaddr, MII_CONTROL, MII_CONTROL_RESET);
 172 
 173         for (linkup = 0, pn = 0; pn < 4; pn++) {
 174                 atge_mii_write(atgep, phyaddr, ATPHY_CDTC,
 175                     (pn << PHY_CDTC_POFF) | PHY_CDTC_ENB);
 176 
 177                 for (i = 200; i > 0; i--) {
 178                         drv_usecwait(1000);
 179 
 180                         reg = atge_mii_read(atgep, phyaddr, ATPHY_CDTC);
 181 
 182                         if ((reg & PHY_CDTC_ENB) == 0)
 183                                 break;
 184                 }
 185 
 186                 drv_usecwait(1000);
 187 
 188                 reg = atge_mii_read(atgep, phyaddr, ATPHY_CDTS);
 189 
 190                 if ((reg & PHY_CDTS_STAT_MASK) != PHY_CDTS_STAT_OPEN) {
 191                         linkup++;
 192                         break;
 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 }