1*d39a76e7Sxw161283 /* 2*d39a76e7Sxw161283 * CDDL HEADER START 3*d39a76e7Sxw161283 * 4*d39a76e7Sxw161283 * The contents of this file are subject to the terms of the 5*d39a76e7Sxw161283 * Common Development and Distribution License (the "License"). 6*d39a76e7Sxw161283 * You may not use this file except in compliance with the License. 7*d39a76e7Sxw161283 * 8*d39a76e7Sxw161283 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*d39a76e7Sxw161283 * or http://www.opensolaris.org/os/licensing. 10*d39a76e7Sxw161283 * See the License for the specific language governing permissions 11*d39a76e7Sxw161283 * and limitations under the License. 12*d39a76e7Sxw161283 * 13*d39a76e7Sxw161283 * When distributing Covered Code, include this CDDL HEADER in each 14*d39a76e7Sxw161283 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*d39a76e7Sxw161283 * If applicable, add the following below this CDDL HEADER, with the 16*d39a76e7Sxw161283 * fields enclosed by brackets "[]" replaced with your own identifying 17*d39a76e7Sxw161283 * information: Portions Copyright [yyyy] [name of copyright owner] 18*d39a76e7Sxw161283 * 19*d39a76e7Sxw161283 * CDDL HEADER END 20*d39a76e7Sxw161283 */ 21*d39a76e7Sxw161283 22*d39a76e7Sxw161283 /* 23*d39a76e7Sxw161283 * Copyright (C) 2003-2005 Chelsio Communications. All rights reserved. 24*d39a76e7Sxw161283 */ 25*d39a76e7Sxw161283 26*d39a76e7Sxw161283 #pragma ident "%Z%%M% %I% %E% SMI" /* xpak.c */ 27*d39a76e7Sxw161283 28*d39a76e7Sxw161283 #include "cphy.h" 29*d39a76e7Sxw161283 #include "elmer0.h" 30*d39a76e7Sxw161283 31*d39a76e7Sxw161283 /* ARGSUSED */ 32*d39a76e7Sxw161283 static int xpak_reset(struct cphy *cphy, int wait) 33*d39a76e7Sxw161283 { 34*d39a76e7Sxw161283 return 0; 35*d39a76e7Sxw161283 } 36*d39a76e7Sxw161283 37*d39a76e7Sxw161283 /* ARGSUSED */ 38*d39a76e7Sxw161283 static int xpak_interrupt_enable(struct cphy *cphy) 39*d39a76e7Sxw161283 { 40*d39a76e7Sxw161283 return 0; 41*d39a76e7Sxw161283 } 42*d39a76e7Sxw161283 43*d39a76e7Sxw161283 /* ARGSUSED */ 44*d39a76e7Sxw161283 static int xpak_interrupt_disable(struct cphy *cphy) 45*d39a76e7Sxw161283 { 46*d39a76e7Sxw161283 return 0; 47*d39a76e7Sxw161283 } 48*d39a76e7Sxw161283 49*d39a76e7Sxw161283 /* ARGSUSED */ 50*d39a76e7Sxw161283 static int xpak_interrupt_clear(struct cphy *cphy) 51*d39a76e7Sxw161283 { 52*d39a76e7Sxw161283 return 0; 53*d39a76e7Sxw161283 } 54*d39a76e7Sxw161283 55*d39a76e7Sxw161283 /* ARGSUSED */ 56*d39a76e7Sxw161283 static int xpak_set_loopback(struct cphy *cphy, int on) 57*d39a76e7Sxw161283 { 58*d39a76e7Sxw161283 return 0; 59*d39a76e7Sxw161283 } 60*d39a76e7Sxw161283 61*d39a76e7Sxw161283 /* ARGSUSED */ 62*d39a76e7Sxw161283 static int xpak_get_link_status(struct cphy *cphy, int *link_ok, int *speed, 63*d39a76e7Sxw161283 int *duplex, int *fc) 64*d39a76e7Sxw161283 { 65*d39a76e7Sxw161283 if (link_ok) 66*d39a76e7Sxw161283 *link_ok = 1; 67*d39a76e7Sxw161283 if (speed) 68*d39a76e7Sxw161283 *speed = SPEED_10000; 69*d39a76e7Sxw161283 if (duplex) 70*d39a76e7Sxw161283 *duplex = DUPLEX_FULL; 71*d39a76e7Sxw161283 if (fc) 72*d39a76e7Sxw161283 *fc = PAUSE_RX | PAUSE_TX; 73*d39a76e7Sxw161283 return 0; 74*d39a76e7Sxw161283 } 75*d39a76e7Sxw161283 76*d39a76e7Sxw161283 static void xpak_destroy(struct cphy *cphy) 77*d39a76e7Sxw161283 { 78*d39a76e7Sxw161283 t1_os_free((void *)cphy, sizeof(*cphy)); 79*d39a76e7Sxw161283 } 80*d39a76e7Sxw161283 81*d39a76e7Sxw161283 #ifdef C99_NOT_SUPPORTED 82*d39a76e7Sxw161283 static struct cphy_ops xpak_ops = { 83*d39a76e7Sxw161283 xpak_destroy, 84*d39a76e7Sxw161283 xpak_reset, 85*d39a76e7Sxw161283 xpak_interrupt_enable, 86*d39a76e7Sxw161283 xpak_interrupt_disable, 87*d39a76e7Sxw161283 xpak_interrupt_clear, 88*d39a76e7Sxw161283 NULL, 89*d39a76e7Sxw161283 NULL, 90*d39a76e7Sxw161283 NULL, 91*d39a76e7Sxw161283 NULL, 92*d39a76e7Sxw161283 NULL, 93*d39a76e7Sxw161283 xpak_set_loopback, 94*d39a76e7Sxw161283 NULL, 95*d39a76e7Sxw161283 xpak_get_link_status, 96*d39a76e7Sxw161283 }; 97*d39a76e7Sxw161283 #else 98*d39a76e7Sxw161283 static struct cphy_ops xpak_ops = { 99*d39a76e7Sxw161283 .destroy = xpak_destroy, 100*d39a76e7Sxw161283 .reset = xpak_reset, 101*d39a76e7Sxw161283 .interrupt_enable = xpak_interrupt_enable, 102*d39a76e7Sxw161283 .interrupt_disable = xpak_interrupt_disable, 103*d39a76e7Sxw161283 .interrupt_clear = xpak_interrupt_clear, 104*d39a76e7Sxw161283 .get_link_status = xpak_get_link_status, 105*d39a76e7Sxw161283 .set_loopback = xpak_set_loopback, 106*d39a76e7Sxw161283 }; 107*d39a76e7Sxw161283 #endif 108*d39a76e7Sxw161283 109*d39a76e7Sxw161283 /* ARGSUSED */ 110*d39a76e7Sxw161283 static struct cphy *xpak_phy_create(adapter_t * adapter, int phy_addr, 111*d39a76e7Sxw161283 struct mdio_ops *mdio_ops) 112*d39a76e7Sxw161283 { 113*d39a76e7Sxw161283 struct cphy *cphy = t1_os_malloc_wait_zero(sizeof(*cphy)); 114*d39a76e7Sxw161283 115*d39a76e7Sxw161283 if (!cphy) 116*d39a76e7Sxw161283 return NULL; 117*d39a76e7Sxw161283 118*d39a76e7Sxw161283 cphy->ops = &xpak_ops; 119*d39a76e7Sxw161283 cphy->adapter = adapter; 120*d39a76e7Sxw161283 cphy->mdio_read = mdio_ops->read; 121*d39a76e7Sxw161283 cphy->mdio_write = mdio_ops->write; 122*d39a76e7Sxw161283 return cphy; 123*d39a76e7Sxw161283 } 124*d39a76e7Sxw161283 125*d39a76e7Sxw161283 static int xpak_phy_reset(adapter_t *adapter) 126*d39a76e7Sxw161283 { 127*d39a76e7Sxw161283 u32 val; 128*d39a76e7Sxw161283 129*d39a76e7Sxw161283 (void) t1_tpi_read(adapter, A_ELMER0_GPO, &val); 130*d39a76e7Sxw161283 val &= ~4; 131*d39a76e7Sxw161283 (void) t1_tpi_write(adapter, A_ELMER0_GPO, val); 132*d39a76e7Sxw161283 DELAY_MS(100); 133*d39a76e7Sxw161283 134*d39a76e7Sxw161283 /* 135*d39a76e7Sxw161283 * Errata #26 states to wait 5 seconds after reset before transceiver 136*d39a76e7Sxw161283 * becomes operational. 137*d39a76e7Sxw161283 */ 138*d39a76e7Sxw161283 (void) t1_tpi_write(adapter, A_ELMER0_GPO, val | 4); 139*d39a76e7Sxw161283 DELAY_MS(5000); 140*d39a76e7Sxw161283 141*d39a76e7Sxw161283 /* Now lets enable the Laser. Delay 100us 142*d39a76e7Sxw161283 * as defined in XPAK errata. 143*d39a76e7Sxw161283 */ 144*d39a76e7Sxw161283 (void) t1_tpi_read(adapter, A_ELMER0_GPO, &val); 145*d39a76e7Sxw161283 val |= 0x8000; 146*d39a76e7Sxw161283 (void) t1_tpi_write(adapter, A_ELMER0_GPO, val); 147*d39a76e7Sxw161283 DELAY_US(100); 148*d39a76e7Sxw161283 return 0; 149*d39a76e7Sxw161283 } 150*d39a76e7Sxw161283 151*d39a76e7Sxw161283 struct gphy t1_xpak_ops = { 152*d39a76e7Sxw161283 xpak_phy_create, 153*d39a76e7Sxw161283 xpak_phy_reset 154*d39a76e7Sxw161283 }; 155*d39a76e7Sxw161283 156