18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2005-2008 Chelsio, Inc. All rights reserved. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 58c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 68c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 78c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 88c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 118c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 128c2ecf20Sopenharmony_ci * conditions are met: 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 158c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 168c2ecf20Sopenharmony_ci * disclaimer. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 198c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 208c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 218c2ecf20Sopenharmony_ci * provided with the distribution. 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 248c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 258c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 268c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 278c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 288c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 298c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 308c2ecf20Sopenharmony_ci * SOFTWARE. 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#include "common.h" 348c2ecf20Sopenharmony_ci#include "regs.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cienum { 378c2ecf20Sopenharmony_ci /* MDIO_DEV_PMA_PMD registers */ 388c2ecf20Sopenharmony_ci AQ_LINK_STAT = 0xe800, 398c2ecf20Sopenharmony_ci AQ_IMASK_PMA = 0xf000, 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* MDIO_DEV_XGXS registers */ 428c2ecf20Sopenharmony_ci AQ_XAUI_RX_CFG = 0xc400, 438c2ecf20Sopenharmony_ci AQ_XAUI_TX_CFG = 0xe400, 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci /* MDIO_DEV_ANEG registers */ 468c2ecf20Sopenharmony_ci AQ_1G_CTRL = 0xc400, 478c2ecf20Sopenharmony_ci AQ_ANEG_STAT = 0xc800, 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci /* MDIO_DEV_VEND1 registers */ 508c2ecf20Sopenharmony_ci AQ_FW_VERSION = 0x0020, 518c2ecf20Sopenharmony_ci AQ_IFLAG_GLOBAL = 0xfc00, 528c2ecf20Sopenharmony_ci AQ_IMASK_GLOBAL = 0xff00, 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cienum { 568c2ecf20Sopenharmony_ci IMASK_PMA = 1 << 2, 578c2ecf20Sopenharmony_ci IMASK_GLOBAL = 1 << 15, 588c2ecf20Sopenharmony_ci ADV_1G_FULL = 1 << 15, 598c2ecf20Sopenharmony_ci ADV_1G_HALF = 1 << 14, 608c2ecf20Sopenharmony_ci ADV_10G_FULL = 1 << 12, 618c2ecf20Sopenharmony_ci AQ_RESET = (1 << 14) | (1 << 15), 628c2ecf20Sopenharmony_ci AQ_LOWPOWER = 1 << 12, 638c2ecf20Sopenharmony_ci}; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int aq100x_reset(struct cphy *phy, int wait) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci /* 688c2ecf20Sopenharmony_ci * Ignore the caller specified wait time; always wait for the reset to 698c2ecf20Sopenharmony_ci * complete. Can take up to 3s. 708c2ecf20Sopenharmony_ci */ 718c2ecf20Sopenharmony_ci int err = t3_phy_reset(phy, MDIO_MMD_VEND1, 3000); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (err) 748c2ecf20Sopenharmony_ci CH_WARN(phy->adapter, "PHY%d: reset failed (0x%x).\n", 758c2ecf20Sopenharmony_ci phy->mdio.prtad, err); 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci return err; 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic int aq100x_intr_enable(struct cphy *phy) 818c2ecf20Sopenharmony_ci{ 828c2ecf20Sopenharmony_ci int err = t3_mdio_write(phy, MDIO_MMD_PMAPMD, AQ_IMASK_PMA, IMASK_PMA); 838c2ecf20Sopenharmony_ci if (err) 848c2ecf20Sopenharmony_ci return err; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci err = t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, IMASK_GLOBAL); 878c2ecf20Sopenharmony_ci return err; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic int aq100x_intr_disable(struct cphy *phy) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci return t3_mdio_write(phy, MDIO_MMD_VEND1, AQ_IMASK_GLOBAL, 0); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int aq100x_intr_clear(struct cphy *phy) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci unsigned int v; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &v); 1008c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return 0; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic int aq100x_intr_handler(struct cphy *phy) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci int err; 1088c2ecf20Sopenharmony_ci unsigned int cause, v; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci err = t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_IFLAG_GLOBAL, &cause); 1118c2ecf20Sopenharmony_ci if (err) 1128c2ecf20Sopenharmony_ci return err; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Read (and reset) the latching version of the status */ 1158c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_PMAPMD, MDIO_STAT1, &v); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return cphy_cause_link_change; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int aq100x_power_down(struct cphy *phy, int off) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci return mdio_set_flag(&phy->mdio, phy->mdio.prtad, 1238c2ecf20Sopenharmony_ci MDIO_MMD_PMAPMD, MDIO_CTRL1, 1248c2ecf20Sopenharmony_ci MDIO_CTRL1_LPOWER, off); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int aq100x_autoneg_enable(struct cphy *phy) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int err; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci err = aq100x_power_down(phy, 0); 1328c2ecf20Sopenharmony_ci if (!err) 1338c2ecf20Sopenharmony_ci err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, 1348c2ecf20Sopenharmony_ci MDIO_MMD_AN, MDIO_CTRL1, 1358c2ecf20Sopenharmony_ci BMCR_ANENABLE | BMCR_ANRESTART, 1); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci return err; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int aq100x_autoneg_restart(struct cphy *phy) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci int err; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci err = aq100x_power_down(phy, 0); 1458c2ecf20Sopenharmony_ci if (!err) 1468c2ecf20Sopenharmony_ci err = mdio_set_flag(&phy->mdio, phy->mdio.prtad, 1478c2ecf20Sopenharmony_ci MDIO_MMD_AN, MDIO_CTRL1, 1488c2ecf20Sopenharmony_ci BMCR_ANENABLE | BMCR_ANRESTART, 1); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return err; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic int aq100x_advertise(struct cphy *phy, unsigned int advertise_map) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci unsigned int adv; 1568c2ecf20Sopenharmony_ci int err; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* 10G advertisement */ 1598c2ecf20Sopenharmony_ci adv = 0; 1608c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_10000baseT_Full) 1618c2ecf20Sopenharmony_ci adv |= ADV_10G_FULL; 1628c2ecf20Sopenharmony_ci err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, 1638c2ecf20Sopenharmony_ci ADV_10G_FULL, adv); 1648c2ecf20Sopenharmony_ci if (err) 1658c2ecf20Sopenharmony_ci return err; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci /* 1G advertisement */ 1688c2ecf20Sopenharmony_ci adv = 0; 1698c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_1000baseT_Full) 1708c2ecf20Sopenharmony_ci adv |= ADV_1G_FULL; 1718c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_1000baseT_Half) 1728c2ecf20Sopenharmony_ci adv |= ADV_1G_HALF; 1738c2ecf20Sopenharmony_ci err = t3_mdio_change_bits(phy, MDIO_MMD_AN, AQ_1G_CTRL, 1748c2ecf20Sopenharmony_ci ADV_1G_FULL | ADV_1G_HALF, adv); 1758c2ecf20Sopenharmony_ci if (err) 1768c2ecf20Sopenharmony_ci return err; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci /* 100M, pause advertisement */ 1798c2ecf20Sopenharmony_ci adv = 0; 1808c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_100baseT_Half) 1818c2ecf20Sopenharmony_ci adv |= ADVERTISE_100HALF; 1828c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_100baseT_Full) 1838c2ecf20Sopenharmony_ci adv |= ADVERTISE_100FULL; 1848c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_Pause) 1858c2ecf20Sopenharmony_ci adv |= ADVERTISE_PAUSE_CAP; 1868c2ecf20Sopenharmony_ci if (advertise_map & ADVERTISED_Asym_Pause) 1878c2ecf20Sopenharmony_ci adv |= ADVERTISE_PAUSE_ASYM; 1888c2ecf20Sopenharmony_ci err = t3_mdio_change_bits(phy, MDIO_MMD_AN, MDIO_AN_ADVERTISE, 1898c2ecf20Sopenharmony_ci 0xfe0, adv); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return err; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic int aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci return mdio_set_flag(&phy->mdio, phy->mdio.prtad, 1978c2ecf20Sopenharmony_ci MDIO_MMD_PMAPMD, MDIO_CTRL1, 1988c2ecf20Sopenharmony_ci BMCR_LOOPBACK, enable); 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic int aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci /* no can do */ 2048c2ecf20Sopenharmony_ci return -1; 2058c2ecf20Sopenharmony_ci} 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_cistatic int aq100x_get_link_status(struct cphy *phy, int *link_ok, 2088c2ecf20Sopenharmony_ci int *speed, int *duplex, int *fc) 2098c2ecf20Sopenharmony_ci{ 2108c2ecf20Sopenharmony_ci int err; 2118c2ecf20Sopenharmony_ci unsigned int v; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (link_ok) { 2148c2ecf20Sopenharmony_ci err = t3_mdio_read(phy, MDIO_MMD_PMAPMD, AQ_LINK_STAT, &v); 2158c2ecf20Sopenharmony_ci if (err) 2168c2ecf20Sopenharmony_ci return err; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci *link_ok = v & 1; 2198c2ecf20Sopenharmony_ci if (!*link_ok) 2208c2ecf20Sopenharmony_ci return 0; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci err = t3_mdio_read(phy, MDIO_MMD_AN, AQ_ANEG_STAT, &v); 2248c2ecf20Sopenharmony_ci if (err) 2258c2ecf20Sopenharmony_ci return err; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (speed) { 2288c2ecf20Sopenharmony_ci switch (v & 0x6) { 2298c2ecf20Sopenharmony_ci case 0x6: 2308c2ecf20Sopenharmony_ci *speed = SPEED_10000; 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci case 0x4: 2338c2ecf20Sopenharmony_ci *speed = SPEED_1000; 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci case 0x2: 2368c2ecf20Sopenharmony_ci *speed = SPEED_100; 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci case 0x0: 2398c2ecf20Sopenharmony_ci *speed = SPEED_10; 2408c2ecf20Sopenharmony_ci break; 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (duplex) 2458c2ecf20Sopenharmony_ci *duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return 0; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic const struct cphy_ops aq100x_ops = { 2518c2ecf20Sopenharmony_ci .reset = aq100x_reset, 2528c2ecf20Sopenharmony_ci .intr_enable = aq100x_intr_enable, 2538c2ecf20Sopenharmony_ci .intr_disable = aq100x_intr_disable, 2548c2ecf20Sopenharmony_ci .intr_clear = aq100x_intr_clear, 2558c2ecf20Sopenharmony_ci .intr_handler = aq100x_intr_handler, 2568c2ecf20Sopenharmony_ci .autoneg_enable = aq100x_autoneg_enable, 2578c2ecf20Sopenharmony_ci .autoneg_restart = aq100x_autoneg_restart, 2588c2ecf20Sopenharmony_ci .advertise = aq100x_advertise, 2598c2ecf20Sopenharmony_ci .set_loopback = aq100x_set_loopback, 2608c2ecf20Sopenharmony_ci .set_speed_duplex = aq100x_set_speed_duplex, 2618c2ecf20Sopenharmony_ci .get_link_status = aq100x_get_link_status, 2628c2ecf20Sopenharmony_ci .power_down = aq100x_power_down, 2638c2ecf20Sopenharmony_ci .mmds = MDIO_DEVS_PMAPMD | MDIO_DEVS_PCS | MDIO_DEVS_PHYXS, 2648c2ecf20Sopenharmony_ci}; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ciint t3_aq100x_phy_prep(struct cphy *phy, struct adapter *adapter, int phy_addr, 2678c2ecf20Sopenharmony_ci const struct mdio_ops *mdio_ops) 2688c2ecf20Sopenharmony_ci{ 2698c2ecf20Sopenharmony_ci unsigned int v, v2, gpio, wait; 2708c2ecf20Sopenharmony_ci int err; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci cphy_init(phy, adapter, phy_addr, &aq100x_ops, mdio_ops, 2738c2ecf20Sopenharmony_ci SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full | 2748c2ecf20Sopenharmony_ci SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI, 2758c2ecf20Sopenharmony_ci "1000/10GBASE-T"); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* 2788c2ecf20Sopenharmony_ci * The PHY has been out of reset ever since the system powered up. So 2798c2ecf20Sopenharmony_ci * we do a hard reset over here. 2808c2ecf20Sopenharmony_ci */ 2818c2ecf20Sopenharmony_ci gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL; 2828c2ecf20Sopenharmony_ci t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0); 2838c2ecf20Sopenharmony_ci msleep(1); 2848c2ecf20Sopenharmony_ci t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci /* 2878c2ecf20Sopenharmony_ci * Give it enough time to load the firmware and get ready for mdio. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_ci msleep(1000); 2908c2ecf20Sopenharmony_ci wait = 500; /* in 10ms increments */ 2918c2ecf20Sopenharmony_ci do { 2928c2ecf20Sopenharmony_ci err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); 2938c2ecf20Sopenharmony_ci if (err || v == 0xffff) { 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* Allow prep_adapter to succeed when ffff is read */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n", 2988c2ecf20Sopenharmony_ci phy_addr, err, v); 2998c2ecf20Sopenharmony_ci goto done; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci v &= AQ_RESET; 3038c2ecf20Sopenharmony_ci if (v) 3048c2ecf20Sopenharmony_ci msleep(10); 3058c2ecf20Sopenharmony_ci } while (v && --wait); 3068c2ecf20Sopenharmony_ci if (v) { 3078c2ecf20Sopenharmony_ci CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n", 3088c2ecf20Sopenharmony_ci phy_addr, v); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci goto done; /* let prep_adapter succeed */ 3118c2ecf20Sopenharmony_ci } 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* Datasheet says 3s max but this has been observed */ 3148c2ecf20Sopenharmony_ci wait = (500 - wait) * 10 + 1000; 3158c2ecf20Sopenharmony_ci if (wait > 3000) 3168c2ecf20Sopenharmony_ci CH_WARN(adapter, "PHY%d: reset took %ums\n", phy_addr, wait); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* Firmware version check. */ 3198c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_VEND1, AQ_FW_VERSION, &v); 3208c2ecf20Sopenharmony_ci if (v != 101) 3218c2ecf20Sopenharmony_ci CH_WARN(adapter, "PHY%d: unsupported firmware %d\n", 3228c2ecf20Sopenharmony_ci phy_addr, v); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* 3258c2ecf20Sopenharmony_ci * The PHY should start in really-low-power mode. Prepare it for normal 3268c2ecf20Sopenharmony_ci * operations. 3278c2ecf20Sopenharmony_ci */ 3288c2ecf20Sopenharmony_ci err = t3_mdio_read(phy, MDIO_MMD_VEND1, MDIO_CTRL1, &v); 3298c2ecf20Sopenharmony_ci if (err) 3308c2ecf20Sopenharmony_ci return err; 3318c2ecf20Sopenharmony_ci if (v & AQ_LOWPOWER) { 3328c2ecf20Sopenharmony_ci err = t3_mdio_change_bits(phy, MDIO_MMD_VEND1, MDIO_CTRL1, 3338c2ecf20Sopenharmony_ci AQ_LOWPOWER, 0); 3348c2ecf20Sopenharmony_ci if (err) 3358c2ecf20Sopenharmony_ci return err; 3368c2ecf20Sopenharmony_ci msleep(10); 3378c2ecf20Sopenharmony_ci } else 3388c2ecf20Sopenharmony_ci CH_WARN(adapter, "PHY%d does not start in low power mode.\n", 3398c2ecf20Sopenharmony_ci phy_addr); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci /* 3428c2ecf20Sopenharmony_ci * Verify XAUI settings, but let prep succeed no matter what. 3438c2ecf20Sopenharmony_ci */ 3448c2ecf20Sopenharmony_ci v = v2 = 0; 3458c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_RX_CFG, &v); 3468c2ecf20Sopenharmony_ci t3_mdio_read(phy, MDIO_MMD_PHYXS, AQ_XAUI_TX_CFG, &v2); 3478c2ecf20Sopenharmony_ci if (v != 0x1b || v2 != 0x1b) 3488c2ecf20Sopenharmony_ci CH_WARN(adapter, 3498c2ecf20Sopenharmony_ci "PHY%d: incorrect XAUI settings (0x%x, 0x%x).\n", 3508c2ecf20Sopenharmony_ci phy_addr, v, v2); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cidone: 3538c2ecf20Sopenharmony_ci return err; 3548c2ecf20Sopenharmony_ci} 355