Line data Source code
1 : /* $OpenBSD: luphy.c,v 1.6 2015/03/14 03:38:48 jsg Exp $ */
2 :
3 : /*-
4 : * Copyright (c) 2004 Marius Strobl
5 : * All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 : * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 : * SUCH DAMAGE.
27 : */
28 :
29 : /*
30 : * Driver for the Lucent Technologies LU6612 Ethernet 10/100 PHY, which
31 : * is pin-compatible to the Quality Semiconductor QS6612 but uses a
32 : * different register layout. Sun Microsystems uses the LU6612 together
33 : * with their HME chip on a couple of bords originally designed for the
34 : * QS6612. At least on these boards none of the LU6612 must be isolated
35 : * otherwise the MII bus wedges and the other one (there can be a maximum
36 : * of two PHYs connected to the HME) no longer can communicate with the
37 : * HME (powering down the unused PHY etc. also doesn't help). This is
38 : * why we can't use the ukphy driver for the LU6612.
39 : * The datasheet for the LU6612 is no longer available on lucent.com or
40 : * www.agere.com (former Lucent Microelectronics Group) but you still
41 : * should be able to find it when searching for DS00355.pdf or LU6612.pdf.
42 : */
43 :
44 : #include <sys/param.h>
45 : #include <sys/systm.h>
46 : #include <sys/device.h>
47 : #include <sys/socket.h>
48 :
49 : #include <net/if.h>
50 : #include <net/if_var.h>
51 : #include <net/if_media.h>
52 :
53 : #include <dev/mii/mii.h>
54 : #include <dev/mii/miivar.h>
55 : #include <dev/mii/miidevs.h>
56 :
57 : int luphymatch(struct device *, void *, void *);
58 : void luphyattach(struct device *, struct device *, void *);
59 :
60 : struct cfattach luphy_ca = {
61 : sizeof(struct mii_softc), luphymatch, luphyattach, mii_phy_detach
62 : };
63 :
64 : struct cfdriver luphy_cd = {
65 : NULL, "luphy", DV_DULL
66 : };
67 :
68 : int luphy_service(struct mii_softc *, struct mii_data *, int);
69 :
70 : const struct mii_phy_funcs luphy_funcs = {
71 : luphy_service, ukphy_status, mii_phy_reset,
72 : };
73 :
74 : static const struct mii_phydesc luphys[] = {
75 : { MII_OUI_LUCENT, MII_MODEL_LUCENT_LU6612,
76 : MII_STR_LUCENT_LU6612 },
77 :
78 : { 0, 0,
79 : NULL },
80 : };
81 :
82 : int
83 0 : luphymatch(struct device *parent, void *match, void *aux)
84 : {
85 0 : struct mii_attach_args *ma = aux;
86 :
87 0 : if (mii_phy_match(ma, luphys) != NULL)
88 0 : return (10);
89 :
90 0 : return (0);
91 0 : }
92 :
93 : void
94 0 : luphyattach(struct device *parent, struct device *self, void *aux)
95 : {
96 0 : struct mii_softc *sc = (struct mii_softc *)self;
97 0 : struct mii_attach_args *ma = aux;
98 0 : struct mii_data *mii = ma->mii_data;
99 : const struct mii_phydesc *mpd;
100 :
101 0 : mpd = mii_phy_match(ma, luphys);
102 0 : printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
103 :
104 0 : sc->mii_inst = mii->mii_instance;
105 0 : sc->mii_phy = ma->mii_phyno;
106 0 : sc->mii_funcs = &luphy_funcs;
107 0 : sc->mii_pdata = mii;
108 0 : sc->mii_flags = ma->mii_flags;
109 :
110 0 : sc->mii_flags |= MIIF_NOISOLATE;
111 :
112 0 : PHY_RESET(sc);
113 :
114 0 : sc->mii_capabilities =
115 0 : PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
116 0 : if (sc->mii_capabilities & BMSR_MEDIAMASK)
117 0 : mii_phy_add_media(sc);
118 0 : }
119 :
120 : int
121 0 : luphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
122 : {
123 0 : struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
124 :
125 0 : switch (cmd) {
126 : case MII_POLLSTAT:
127 : /*
128 : * If we're not polling our PHY instance, just return.
129 : */
130 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst)
131 0 : return (0);
132 : break;
133 :
134 : case MII_MEDIACHG:
135 : /*
136 : * If the media indicates a different PHY instance,
137 : * just return. Isolating unused PHYs from the bus
138 : * causes at least the MII bus of the HME to wedge.
139 : */
140 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst)
141 0 : return (0);
142 :
143 : /*
144 : * If the interface is not up, don't do anything.
145 : */
146 0 : if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
147 : break;
148 :
149 0 : mii_phy_setmedia(sc);
150 0 : break;
151 :
152 : case MII_TICK:
153 : /*
154 : * If we're not currently selected, just return.
155 : */
156 0 : if (IFM_INST(ife->ifm_media) != sc->mii_inst)
157 0 : return (0);
158 :
159 0 : if (mii_phy_tick(sc) == EJUSTRETURN)
160 0 : return (0);
161 : break;
162 :
163 : case MII_DOWN:
164 0 : mii_phy_down(sc);
165 0 : return (0);
166 : }
167 :
168 : /* Update the media status. */
169 0 : mii_phy_status(sc);
170 :
171 : /* Callback if something changed. */
172 0 : mii_phy_update(sc, cmd);
173 0 : return (0);
174 0 : }
|