This source file includes following definitions.
- bmtphymatch
- bmtphyattach
- bmtphy_service
- bmtphy_status
- bmtphy_reset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/device.h>
39 #include <sys/socket.h>
40 #include <sys/errno.h>
41
42 #include <net/if.h>
43 #include <net/if_media.h>
44
45 #include <dev/mii/mii.h>
46 #include <dev/mii/miivar.h>
47 #include <dev/mii/miidevs.h>
48
49 #include <dev/mii/bmtphyreg.h>
50
51 int bmtphymatch(struct device *, void *, void *);
52 void bmtphyattach(struct device *, struct device *, void *);
53
54 struct cfattach bmtphy_ca = {
55 sizeof(struct mii_softc), bmtphymatch, bmtphyattach, mii_phy_detach,
56 mii_phy_activate
57 };
58
59 struct cfdriver bmtphy_cd = {
60 NULL, "bmtphy", DV_DULL
61 };
62
63 int bmtphy_service(struct mii_softc *, struct mii_data *, int);
64 void bmtphy_status(struct mii_softc *);
65 void bmtphy_reset(struct mii_softc *);
66
67 const struct mii_phy_funcs bmtphy_funcs = {
68 bmtphy_service, bmtphy_status, bmtphy_reset,
69 };
70
71 static const struct mii_phydesc bmtphys[] = {
72 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_3C905B,
73 MII_STR_BROADCOM_3C905B },
74 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_3C905C,
75 MII_STR_BROADCOM_3C905C },
76 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM4401,
77 MII_STR_BROADCOM_BCM4401 },
78 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5201,
79 MII_STR_BROADCOM_BCM5201 },
80 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5214,
81 MII_STR_BROADCOM_BCM5214 },
82 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5220,
83 MII_STR_BROADCOM_BCM5220 },
84 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5221,
85 MII_STR_BROADCOM_BCM5221 },
86 { MII_OUI_BROADCOM, MII_MODEL_BROADCOM_BCM5222,
87 MII_STR_BROADCOM_BCM5222 },
88
89 { 0, 0,
90 NULL },
91 };
92
93 int
94 bmtphymatch(struct device *parent, void *match, void *aux)
95 {
96 struct mii_attach_args *ma = aux;
97
98 if (mii_phy_match(ma, bmtphys) != NULL)
99 return (10);
100
101 return (0);
102 }
103
104 void
105 bmtphyattach(struct device *parent, struct device *self, void *aux)
106 {
107 struct mii_softc *sc = (struct mii_softc *)self;
108 struct mii_attach_args *ma = aux;
109 struct mii_data *mii = ma->mii_data;
110 const struct mii_phydesc *mpd;
111
112 mpd = mii_phy_match(ma, bmtphys);
113 printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
114
115 sc->mii_model = MII_MODEL(ma->mii_id2);
116 sc->mii_inst = mii->mii_instance;
117 sc->mii_phy = ma->mii_phyno;
118 sc->mii_funcs = &bmtphy_funcs;
119 sc->mii_pdata = mii;
120 sc->mii_flags = ma->mii_flags;
121 sc->mii_anegticks = MII_ANEGTICKS;
122
123 PHY_RESET(sc);
124
125
126
127
128
129 sc->mii_capabilities =
130 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
131 if (sc->mii_capabilities & BMSR_MEDIAMASK)
132 mii_phy_add_media(sc);
133 }
134
135 int
136 bmtphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
137 {
138 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
139 int reg;
140
141 if ((sc->mii_dev.dv_flags & DVF_ACTIVE) == 0)
142 return (ENXIO);
143
144 switch (cmd) {
145 case MII_POLLSTAT:
146
147
148
149 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
150 return (0);
151 break;
152
153 case MII_MEDIACHG:
154
155
156
157
158 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
159 reg = PHY_READ(sc, MII_BMCR);
160 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
161 return (0);
162 }
163
164
165
166
167 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
168 break;
169
170 mii_phy_setmedia(sc);
171 break;
172
173 case MII_TICK:
174
175
176
177 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
178 return (0);
179
180 if (mii_phy_tick(sc) == EJUSTRETURN)
181 return (0);
182 break;
183
184 case MII_DOWN:
185 mii_phy_down(sc);
186 return (0);
187 }
188
189
190 mii_phy_status(sc);
191
192
193 mii_phy_update(sc, cmd);
194 return (0);
195 }
196
197 void
198 bmtphy_status(struct mii_softc *sc)
199 {
200 struct mii_data *mii = sc->mii_pdata;
201 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
202 int bmsr, bmcr, aux_csr;
203
204 mii->mii_media_status = IFM_AVALID;
205 mii->mii_media_active = IFM_ETHER;
206
207 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
208 if (bmsr & BMSR_LINK)
209 mii->mii_media_status |= IFM_ACTIVE;
210
211 bmcr = PHY_READ(sc, MII_BMCR);
212 if (bmcr & BMCR_ISO) {
213 mii->mii_media_active |= IFM_NONE;
214 mii->mii_media_status = 0;
215 return;
216 }
217
218 if (bmcr & BMCR_LOOP)
219 mii->mii_media_active |= IFM_LOOP;
220
221 if (bmcr & BMCR_AUTOEN) {
222
223
224
225
226 if ((bmsr & BMSR_ACOMP) == 0) {
227
228 mii->mii_media_active |= IFM_NONE;
229 return;
230 }
231
232 aux_csr = PHY_READ(sc, MII_BMTPHY_AUX_CSR);
233 if (aux_csr & AUX_CSR_SPEED)
234 mii->mii_media_active |= IFM_100_TX;
235 else
236 mii->mii_media_active |= IFM_10_T;
237
238 if (aux_csr & AUX_CSR_FDX)
239 mii->mii_media_active |= IFM_FDX;
240 else
241 mii->mii_media_active |= IFM_HDX;
242 } else
243 mii->mii_media_active = ife->ifm_media;
244 }
245
246 void
247 bmtphy_reset(struct mii_softc *sc)
248 {
249 u_int16_t data;
250
251 mii_phy_reset(sc);
252
253 if (sc->mii_model == MII_MODEL_BROADCOM_BCM5221) {
254
255 data = PHY_READ(sc, 0x1f);
256 PHY_WRITE(sc, 0x1f, data | 0x0080);
257
258
259 data = PHY_READ(sc, MII_BMTPHY_AUX2);
260 PHY_WRITE(sc, MII_BMTPHY_AUX2, data | 0x0020);
261
262
263
264 data = PHY_READ(sc, MII_BMTPHY_INTR);
265 PHY_WRITE(sc, MII_BMTPHY_INTR, data | 0x0004);
266
267
268 data = PHY_READ(sc, 0x1f);
269 PHY_WRITE(sc, 0x1f, data & ~0x0080);
270 }
271 }