110393SSaurabh.Mishra@Sun.COM /*
210393SSaurabh.Mishra@Sun.COM * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
310393SSaurabh.Mishra@Sun.COM * All rights reserved.
410393SSaurabh.Mishra@Sun.COM *
510393SSaurabh.Mishra@Sun.COM * Redistribution and use in source and binary forms, with or without
610393SSaurabh.Mishra@Sun.COM * modification, are permitted provided that the following conditions
710393SSaurabh.Mishra@Sun.COM * are met:
810393SSaurabh.Mishra@Sun.COM * 1. Redistributions of source code must retain the above copyright
910393SSaurabh.Mishra@Sun.COM * notice unmodified, this list of conditions, and the following
1010393SSaurabh.Mishra@Sun.COM * disclaimer.
1110393SSaurabh.Mishra@Sun.COM * 2. Redistributions in binary form must reproduce the above copyright
1210393SSaurabh.Mishra@Sun.COM * notice, this list of conditions and the following disclaimer in the
1310393SSaurabh.Mishra@Sun.COM * documentation and/or other materials provided with the distribution.
1410393SSaurabh.Mishra@Sun.COM *
1510393SSaurabh.Mishra@Sun.COM * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1610393SSaurabh.Mishra@Sun.COM * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1710393SSaurabh.Mishra@Sun.COM * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1810393SSaurabh.Mishra@Sun.COM * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1910393SSaurabh.Mishra@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2010393SSaurabh.Mishra@Sun.COM * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2110393SSaurabh.Mishra@Sun.COM * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2210393SSaurabh.Mishra@Sun.COM * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2310393SSaurabh.Mishra@Sun.COM * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2410393SSaurabh.Mishra@Sun.COM * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2510393SSaurabh.Mishra@Sun.COM * SUCH DAMAGE.
2610393SSaurabh.Mishra@Sun.COM */
2710393SSaurabh.Mishra@Sun.COM
2810393SSaurabh.Mishra@Sun.COM #include <sys/mii.h>
2910393SSaurabh.Mishra@Sun.COM #include <sys/miiregs.h>
3010393SSaurabh.Mishra@Sun.COM
3110393SSaurabh.Mishra@Sun.COM #include "atge.h"
3210393SSaurabh.Mishra@Sun.COM #include "atge_cmn_reg.h"
3310393SSaurabh.Mishra@Sun.COM #include "atge_l1e_reg.h"
34*11353SSaurabh.Mishra@Sun.COM #include "atge_l1_reg.h"
3510393SSaurabh.Mishra@Sun.COM
3610393SSaurabh.Mishra@Sun.COM uint16_t
atge_mii_read(void * arg,uint8_t phy,uint8_t reg)3710393SSaurabh.Mishra@Sun.COM atge_mii_read(void *arg, uint8_t phy, uint8_t reg)
3810393SSaurabh.Mishra@Sun.COM {
3910393SSaurabh.Mishra@Sun.COM atge_t *atgep = arg;
4010393SSaurabh.Mishra@Sun.COM uint32_t v;
4110393SSaurabh.Mishra@Sun.COM int i;
4210393SSaurabh.Mishra@Sun.COM
4310393SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_mii_lock);
4410393SSaurabh.Mishra@Sun.COM
4510393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
4610393SSaurabh.Mishra@Sun.COM MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
4710393SSaurabh.Mishra@Sun.COM
4810393SSaurabh.Mishra@Sun.COM for (i = PHY_TIMEOUT; i > 0; i--) {
4910393SSaurabh.Mishra@Sun.COM drv_usecwait(5);
5010393SSaurabh.Mishra@Sun.COM v = INL(atgep, ATGE_MDIO);
5110393SSaurabh.Mishra@Sun.COM if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
5210393SSaurabh.Mishra@Sun.COM break;
5310393SSaurabh.Mishra@Sun.COM }
5410393SSaurabh.Mishra@Sun.COM
5510393SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_mii_lock);
5610393SSaurabh.Mishra@Sun.COM
5710393SSaurabh.Mishra@Sun.COM if (i == 0) {
5810393SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "PHY (%d) read timeout : %d",
5910393SSaurabh.Mishra@Sun.COM phy, reg);
6010393SSaurabh.Mishra@Sun.COM
6110393SSaurabh.Mishra@Sun.COM return (0xffff);
6210393SSaurabh.Mishra@Sun.COM }
6310393SSaurabh.Mishra@Sun.COM
6410518SSaurabh.Mishra@Sun.COM /*
6510518SSaurabh.Mishra@Sun.COM * Some fast ethernet chips may not be able to auto-nego with
6610518SSaurabh.Mishra@Sun.COM * switches even though they have 1000T based PHY. Hence we mask
6710518SSaurabh.Mishra@Sun.COM * 1000T based capabilities.
6810518SSaurabh.Mishra@Sun.COM */
6910518SSaurabh.Mishra@Sun.COM if (atgep->atge_flags & ATGE_FLAG_FASTETHER) {
7010518SSaurabh.Mishra@Sun.COM if (reg == MII_STATUS)
7110518SSaurabh.Mishra@Sun.COM v &= ~MII_STATUS_EXTSTAT;
7210518SSaurabh.Mishra@Sun.COM else if (reg == MII_EXTSTATUS)
7310518SSaurabh.Mishra@Sun.COM v = 0;
7410518SSaurabh.Mishra@Sun.COM }
7510518SSaurabh.Mishra@Sun.COM
7610393SSaurabh.Mishra@Sun.COM return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
7710393SSaurabh.Mishra@Sun.COM }
7810393SSaurabh.Mishra@Sun.COM
7910393SSaurabh.Mishra@Sun.COM void
atge_mii_write(void * arg,uint8_t phy,uint8_t reg,uint16_t val)8010393SSaurabh.Mishra@Sun.COM atge_mii_write(void *arg, uint8_t phy, uint8_t reg, uint16_t val)
8110393SSaurabh.Mishra@Sun.COM {
8210393SSaurabh.Mishra@Sun.COM atge_t *atgep = arg;
8310393SSaurabh.Mishra@Sun.COM uint32_t v;
8410393SSaurabh.Mishra@Sun.COM int i;
8510393SSaurabh.Mishra@Sun.COM
8610393SSaurabh.Mishra@Sun.COM mutex_enter(&atgep->atge_mii_lock);
8710393SSaurabh.Mishra@Sun.COM
8810393SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
8910393SSaurabh.Mishra@Sun.COM (val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
9010393SSaurabh.Mishra@Sun.COM MDIO_SUP_PREAMBLE | MDIO_CLK_25_4 | MDIO_REG_ADDR(reg));
9110393SSaurabh.Mishra@Sun.COM
9210393SSaurabh.Mishra@Sun.COM for (i = PHY_TIMEOUT; i > 0; i--) {
9310393SSaurabh.Mishra@Sun.COM drv_usecwait(1);
9410393SSaurabh.Mishra@Sun.COM v = INL(atgep, ATGE_MDIO);
9510393SSaurabh.Mishra@Sun.COM if ((v & (MDIO_OP_EXECUTE | MDIO_OP_BUSY)) == 0)
9610393SSaurabh.Mishra@Sun.COM break;
9710393SSaurabh.Mishra@Sun.COM }
9810393SSaurabh.Mishra@Sun.COM
9910393SSaurabh.Mishra@Sun.COM mutex_exit(&atgep->atge_mii_lock);
10010393SSaurabh.Mishra@Sun.COM
10110393SSaurabh.Mishra@Sun.COM if (i == 0) {
10210393SSaurabh.Mishra@Sun.COM atge_error(atgep->atge_dip, "PHY (%d) write timeout:reg %d,"
10310393SSaurabh.Mishra@Sun.COM " val :%d", phy, reg, val);
10410393SSaurabh.Mishra@Sun.COM }
10510393SSaurabh.Mishra@Sun.COM }
10610393SSaurabh.Mishra@Sun.COM
10710393SSaurabh.Mishra@Sun.COM void
atge_l1e_mii_reset(void * arg)10810393SSaurabh.Mishra@Sun.COM atge_l1e_mii_reset(void *arg)
10910393SSaurabh.Mishra@Sun.COM {
11010393SSaurabh.Mishra@Sun.COM atge_t *atgep = arg;
11110393SSaurabh.Mishra@Sun.COM int phyaddr;
11210393SSaurabh.Mishra@Sun.COM
11310393SSaurabh.Mishra@Sun.COM phyaddr = mii_get_addr(atgep->atge_mii);
11410393SSaurabh.Mishra@Sun.COM
115*11353SSaurabh.Mishra@Sun.COM OUTW(atgep, ATGE_GPHY_CTRL,
11610393SSaurabh.Mishra@Sun.COM GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE | GPHY_CTRL_SEL_ANA_RESET |
11710393SSaurabh.Mishra@Sun.COM GPHY_CTRL_PHY_PLL_ON);
11810393SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
11910393SSaurabh.Mishra@Sun.COM
120*11353SSaurabh.Mishra@Sun.COM OUTW(atgep, ATGE_GPHY_CTRL,
12110393SSaurabh.Mishra@Sun.COM GPHY_CTRL_EXT_RESET | GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE |
12210393SSaurabh.Mishra@Sun.COM GPHY_CTRL_SEL_ANA_RESET | GPHY_CTRL_PHY_PLL_ON);
12310393SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
12410393SSaurabh.Mishra@Sun.COM
12510518SSaurabh.Mishra@Sun.COM /*
12610518SSaurabh.Mishra@Sun.COM * Some fast ethernet chips may not be able to auto-nego with
12710518SSaurabh.Mishra@Sun.COM * switches even though they have 1000T based PHY. Hence we need
12810518SSaurabh.Mishra@Sun.COM * to write 0 to MII_MSCONTROL control register.
12910518SSaurabh.Mishra@Sun.COM */
13010518SSaurabh.Mishra@Sun.COM if (atgep->atge_flags & ATGE_FLAG_FASTETHER)
13110518SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, MII_MSCONTROL, 0x0);
13210518SSaurabh.Mishra@Sun.COM
13310393SSaurabh.Mishra@Sun.COM /* Enable hibernation mode. */
13410393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x0B);
13510393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0xBC00);
13610393SSaurabh.Mishra@Sun.COM
13710393SSaurabh.Mishra@Sun.COM /* Set Class A/B for all modes. */
13810393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x00);
13910393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x02EF);
14010393SSaurabh.Mishra@Sun.COM
14110393SSaurabh.Mishra@Sun.COM /* Enable 10BT power saving. */
14210393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x12);
14310393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x4C04);
14410393SSaurabh.Mishra@Sun.COM
14510393SSaurabh.Mishra@Sun.COM /* Adjust 1000T power. */
14610393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x04);
14710393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x8BBB);
14810393SSaurabh.Mishra@Sun.COM
14910393SSaurabh.Mishra@Sun.COM /* 10BT center tap voltage. */
15010393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0x05);
15110393SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x2C46);
15210393SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
15310393SSaurabh.Mishra@Sun.COM }
154*11353SSaurabh.Mishra@Sun.COM
155*11353SSaurabh.Mishra@Sun.COM void
atge_l1_mii_reset(void * arg)156*11353SSaurabh.Mishra@Sun.COM atge_l1_mii_reset(void *arg)
157*11353SSaurabh.Mishra@Sun.COM {
158*11353SSaurabh.Mishra@Sun.COM atge_t *atgep = arg;
159*11353SSaurabh.Mishra@Sun.COM int linkup, i;
160*11353SSaurabh.Mishra@Sun.COM uint16_t reg, pn;
161*11353SSaurabh.Mishra@Sun.COM int phyaddr;
162*11353SSaurabh.Mishra@Sun.COM
163*11353SSaurabh.Mishra@Sun.COM phyaddr = mii_get_addr(atgep->atge_mii);
164*11353SSaurabh.Mishra@Sun.COM
165*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_GPHY_CTRL, GPHY_CTRL_RST);
166*11353SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
167*11353SSaurabh.Mishra@Sun.COM
168*11353SSaurabh.Mishra@Sun.COM OUTL(atgep, ATGE_GPHY_CTRL, GPHY_CTRL_CLR);
169*11353SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
170*11353SSaurabh.Mishra@Sun.COM
171*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, MII_CONTROL, MII_CONTROL_RESET);
172*11353SSaurabh.Mishra@Sun.COM
173*11353SSaurabh.Mishra@Sun.COM for (linkup = 0, pn = 0; pn < 4; pn++) {
174*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_CDTC,
175*11353SSaurabh.Mishra@Sun.COM (pn << PHY_CDTC_POFF) | PHY_CDTC_ENB);
176*11353SSaurabh.Mishra@Sun.COM
177*11353SSaurabh.Mishra@Sun.COM for (i = 200; i > 0; i--) {
178*11353SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
179*11353SSaurabh.Mishra@Sun.COM
180*11353SSaurabh.Mishra@Sun.COM reg = atge_mii_read(atgep, phyaddr, ATPHY_CDTC);
181*11353SSaurabh.Mishra@Sun.COM
182*11353SSaurabh.Mishra@Sun.COM if ((reg & PHY_CDTC_ENB) == 0)
183*11353SSaurabh.Mishra@Sun.COM break;
184*11353SSaurabh.Mishra@Sun.COM }
185*11353SSaurabh.Mishra@Sun.COM
186*11353SSaurabh.Mishra@Sun.COM drv_usecwait(1000);
187*11353SSaurabh.Mishra@Sun.COM
188*11353SSaurabh.Mishra@Sun.COM reg = atge_mii_read(atgep, phyaddr, ATPHY_CDTS);
189*11353SSaurabh.Mishra@Sun.COM
190*11353SSaurabh.Mishra@Sun.COM if ((reg & PHY_CDTS_STAT_MASK) != PHY_CDTS_STAT_OPEN) {
191*11353SSaurabh.Mishra@Sun.COM linkup++;
192*11353SSaurabh.Mishra@Sun.COM break;
193*11353SSaurabh.Mishra@Sun.COM }
194*11353SSaurabh.Mishra@Sun.COM }
195*11353SSaurabh.Mishra@Sun.COM
196*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, MII_CONTROL,
197*11353SSaurabh.Mishra@Sun.COM MII_CONTROL_RESET | MII_CONTROL_ANE | MII_CONTROL_RSAN);
198*11353SSaurabh.Mishra@Sun.COM
199*11353SSaurabh.Mishra@Sun.COM if (linkup == 0) {
200*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
201*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x124E);
202*11353SSaurabh.Mishra@Sun.COM
203*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 1);
204*11353SSaurabh.Mishra@Sun.COM reg = atge_mii_read(atgep, phyaddr, ATPHY_DBG_DATA);
205*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, reg | 0x03);
206*11353SSaurabh.Mishra@Sun.COM
207*11353SSaurabh.Mishra@Sun.COM drv_usecwait(1500 * 1000);
208*11353SSaurabh.Mishra@Sun.COM
209*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_ADDR, 0);
210*11353SSaurabh.Mishra@Sun.COM atge_mii_write(atgep, phyaddr, ATPHY_DBG_DATA, 0x024E);
211*11353SSaurabh.Mishra@Sun.COM }
212*11353SSaurabh.Mishra@Sun.COM }
213