/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * MII overrides for Quality Semiconductor PHYs. */ #include #include #include #include #include #include "miipriv.h" #define QS_IMASK_REG 30 #define QS_BTXPC 31 #define QS_BTXPC_SCRAM_DIS 0x1 static int qs6612_reset(phy_handle_t *ph) { /* Ordinary reset. */ if (phy_reset(ph) != DDI_SUCCESS) { return (DDI_FAILURE); } /* Disable QS6612 proprietary interrupts. */ phy_write(ph, QS_IMASK_REG, 0); return (DDI_SUCCESS); } static int qs6612_check(phy_handle_t *ph) { link_state_t link; int rv; /* * Apparently some *ancient* Synoptics 28115 firwmare has a bug that * doesn't connect with certain devices. While I'm fairly sure we * could probably remove this workaround (for another vendor's bug!) * at this point, it might crop up as a regression. * * Apparently, the workaround is to disable the scrambler for a bit * once 100 Mbps link is achieved, and then reactivate. This lets * the busted switch work. We only do it when first bringing up * the 100 Mbps link. * * Yes, I resent having to do this. But the code is carried over * from old hme/qfe. See 4071199 for details. */ link = ph->phy_link; rv = phy_check(ph); if ((ph->phy_link == LINK_STATE_UP) && (link != LINK_STATE_UP) && (ph->phy_speed == 100)) { uint16_t val; val = phy_read(ph, QS_BTXPC); phy_write(ph, QS_BTXPC, val | QS_BTXPC_SCRAM_DIS); drv_usecwait(20); phy_write(ph, QS_BTXPC, val); } return (rv); } boolean_t phy_qualsemi_probe(phy_handle_t *ph) { if ((MII_PHY_MFG(ph->phy_id) == MII_OUI_QUALITY_SEMI) && (MII_PHY_MODEL(ph->phy_id) == MII_MODEL_QUALITY_SEMI_QS6612)) { ph->phy_vendor = "Quality Semiconductor"; ph->phy_model = "QS6612"; ph->phy_reset = qs6612_reset; ph->phy_check = qs6612_check; return (B_TRUE); } return (B_FALSE); }