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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * MII overrides for Quality Semiconductor PHYs. 28 */ 29 30 #include <sys/types.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 #include <sys/mii.h> 34 #include <sys/miiregs.h> 35 #include "miipriv.h" 36 37 #define QS_IMASK_REG 30 38 #define QS_BTXPC 31 39 #define QS_BTXPC_SCRAM_DIS 0x1 40 41 static int 42 qs6612_reset(phy_handle_t *ph) 43 { 44 /* Ordinary reset. */ 45 if (phy_reset(ph) != DDI_SUCCESS) { 46 return (DDI_FAILURE); 47 } 48 49 /* Disable QS6612 proprietary interrupts. */ 50 phy_write(ph, QS_IMASK_REG, 0); 51 52 return (DDI_SUCCESS); 53 } 54 55 static int 56 qs6612_check(phy_handle_t *ph) 57 { 58 link_state_t link; 59 int rv; 60 61 /* 62 * Apparently some *ancient* Synoptics 28115 firwmare has a bug that 63 * doesn't connect with certain devices. While I'm fairly sure we 64 * could probably remove this workaround (for another vendor's bug!) 65 * at this point, it might crop up as a regression. 66 * 67 * Apparently, the workaround is to disable the scrambler for a bit 68 * once 100 Mbps link is achieved, and then reactivate. This lets 69 * the busted switch work. We only do it when first bringing up 70 * the 100 Mbps link. 71 * 72 * Yes, I resent having to do this. But the code is carried over 73 * from old hme/qfe. See 4071199 for details. 74 */ 75 link = ph->phy_link; 76 77 rv = phy_check(ph); 78 79 if ((ph->phy_link == LINK_STATE_UP) && (link != LINK_STATE_UP) && 80 (ph->phy_speed == 100)) { 81 uint16_t val; 82 val = phy_read(ph, QS_BTXPC); 83 phy_write(ph, QS_BTXPC, val | QS_BTXPC_SCRAM_DIS); 84 drv_usecwait(20); 85 phy_write(ph, QS_BTXPC, val); 86 } 87 88 return (rv); 89 } 90 91 boolean_t 92 phy_qualsemi_probe(phy_handle_t *ph) 93 { 94 if ((MII_PHY_MFG(ph->phy_id) == MII_OUI_QUALITY_SEMI) && 95 (MII_PHY_MODEL(ph->phy_id) == MII_MODEL_QUALITY_SEMI_QS6612)) { 96 ph->phy_vendor = "Quality Semiconductor"; 97 ph->phy_model = "QS6612"; 98 ph->phy_reset = qs6612_reset; 99 ph->phy_check = qs6612_check; 100 return (B_TRUE); 101 } 102 return (B_FALSE); 103 } 104