This source file includes following definitions.
- ciphymatch
- ciphyattach
- ciphy_service
- ciphy_status
- ciphy_reset
- ciphy_fixup
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
36
37
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/device.h>
43 #include <sys/socket.h>
44 #include <sys/errno.h>
45
46 #include <net/if.h>
47 #include <net/if_media.h>
48
49 #ifdef INET
50 #include <netinet/in.h>
51 #include <netinet/if_ether.h>
52 #endif
53
54 #include <dev/pci/pcivar.h>
55
56 #include <dev/mii/mii.h>
57 #include <dev/mii/miivar.h>
58 #include <dev/mii/miidevs.h>
59
60 #include <dev/mii/ciphyreg.h>
61
62 #include <machine/bus.h>
63
64 int ciphymatch(struct device *, void *, void *);
65 void ciphyattach(struct device *, struct device *, void *);
66
67 struct cfattach ciphy_ca = {
68 sizeof(struct mii_softc),
69 ciphymatch,
70 ciphyattach,
71 mii_phy_detach,
72 mii_phy_activate
73 };
74
75 struct cfdriver ciphy_cd = {
76 NULL, "ciphy", DV_DULL
77 };
78
79 int ciphy_service(struct mii_softc *, struct mii_data *, int);
80 void ciphy_status(struct mii_softc *);
81 void ciphy_reset(struct mii_softc *);
82 void ciphy_fixup(struct mii_softc *);
83
84 const struct mii_phy_funcs ciphy_funcs = {
85 ciphy_service, ciphy_status, ciphy_reset,
86 };
87
88 static const struct mii_phydesc ciphys[] = {
89 { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201,
90 MII_STR_CICADA_CS8201 },
91 { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201A,
92 MII_STR_CICADA_CS8201A },
93 { MII_OUI_CICADA, MII_MODEL_CICADA_CS8201B,
94 MII_STR_CICADA_CS8201B },
95 { MII_OUI_xxCICADA, MII_MODEL_xxCICADA_CS8201B,
96 MII_STR_xxCICADA_CS8201B },
97
98 { 0, 0,
99 NULL },
100 };
101
102 int
103 ciphymatch(struct device *parent, void *match, void *aux)
104 {
105 struct mii_attach_args *ma = aux;
106
107 if (mii_phy_match(ma, ciphys) != NULL)
108 return (10);
109
110 return (0);
111 }
112
113 void
114 ciphyattach(struct device *parent, struct device *self, void *aux)
115 {
116 struct mii_softc *sc = (struct mii_softc *)self;
117 struct mii_attach_args *ma = aux;
118 struct mii_data *mii = ma->mii_data;
119 const struct mii_phydesc *mpd;
120
121 mpd = mii_phy_match(ma, ciphys);
122 printf(": %s, rev. %d\n", mpd->mpd_name, MII_REV(ma->mii_id2));
123
124 sc->mii_inst = mii->mii_instance;
125 sc->mii_phy = ma->mii_phyno;
126 sc->mii_funcs = &ciphy_funcs;
127 sc->mii_pdata = mii;
128 sc->mii_flags = ma->mii_flags;
129 sc->mii_anegticks = MII_ANEGTICKS;
130
131 sc->mii_flags |= MIIF_NOISOLATE;
132
133 PHY_RESET(sc);
134
135 sc->mii_capabilities =
136 PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
137 if (sc->mii_capabilities & BMSR_EXTSTAT)
138 sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
139 if ((sc->mii_capabilities & BMSR_MEDIAMASK) ||
140 (sc->mii_capabilities & EXTSR_MEDIAMASK))
141 mii_phy_add_media(sc);
142 }
143
144 int
145 ciphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
146 {
147 struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
148 int reg, speed, gig;
149
150 switch (cmd) {
151 case MII_POLLSTAT:
152
153
154
155 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
156 return (0);
157 break;
158
159 case MII_MEDIACHG:
160
161
162
163
164 if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
165 reg = PHY_READ(sc, MII_BMCR);
166 PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
167 return (0);
168 }
169
170
171
172
173 if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
174 break;
175
176 ciphy_fixup(sc);
177
178 switch (IFM_SUBTYPE(ife->ifm_media)) {
179 case IFM_AUTO:
180 if (mii_phy_auto(sc, 0) == EJUSTRETURN)
181 return (0);
182 break;
183 case IFM_1000_T:
184 speed = CIPHY_S1000;
185 goto setit;
186 case IFM_100_TX:
187 speed = CIPHY_S100;
188 goto setit;
189 case IFM_10_T:
190 speed = CIPHY_S10;
191 setit:
192 if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
193 speed |= CIPHY_BMCR_FDX;
194 gig = CIPHY_1000CTL_AFD;
195 } else {
196 gig = CIPHY_1000CTL_AHD;
197 }
198
199 PHY_WRITE(sc, CIPHY_MII_1000CTL, 0);
200 PHY_WRITE(sc, CIPHY_MII_BMCR, speed);
201 PHY_WRITE(sc, CIPHY_MII_ANAR, CIPHY_SEL_TYPE);
202
203 if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_T)
204 break;
205
206 PHY_WRITE(sc, CIPHY_MII_1000CTL, gig);
207 PHY_WRITE(sc, CIPHY_MII_BMCR,
208 speed|CIPHY_BMCR_AUTOEN|CIPHY_BMCR_STARTNEG);
209
210 if (mii->mii_media.ifm_media & IFM_ETH_MASTER)
211 gig |= CIPHY_1000CTL_MSE|CIPHY_1000CTL_MSC;
212 PHY_WRITE(sc, CIPHY_MII_1000CTL, gig);
213 break;
214 case IFM_NONE:
215 PHY_WRITE(sc, MII_BMCR, BMCR_ISO|BMCR_PDOWN);
216 break;
217 case IFM_100_T4:
218 default:
219 return (EINVAL);
220 }
221 break;
222
223 case MII_TICK:
224
225
226
227 if (IFM_INST(ife->ifm_media) != sc->mii_inst)
228 return (0);
229
230 if (mii_phy_tick(sc) == EJUSTRETURN)
231 return (0);
232 break;
233 }
234
235
236 mii_phy_status(sc);
237
238
239
240
241
242 if (sc->mii_media_active != mii->mii_media_active ||
243 sc->mii_media_status != mii->mii_media_status ||
244 cmd == MII_MEDIACHG) {
245 ciphy_fixup(sc);
246 }
247 mii_phy_update(sc, cmd);
248 return (0);
249 }
250
251 void
252 ciphy_status(struct mii_softc *sc)
253 {
254 struct mii_data *mii = sc->mii_pdata;
255 int bmsr, bmcr, gsr;
256
257 mii->mii_media_status = IFM_AVALID;
258 mii->mii_media_active = IFM_ETHER;
259
260 bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
261
262 if (bmsr & BMSR_LINK)
263 mii->mii_media_status |= IFM_ACTIVE;
264
265 bmcr = PHY_READ(sc, CIPHY_MII_BMCR);
266
267 if (bmcr & CIPHY_BMCR_LOOP)
268 mii->mii_media_active |= IFM_LOOP;
269
270 if (bmcr & CIPHY_BMCR_AUTOEN) {
271 if ((bmsr & CIPHY_BMSR_ACOMP) == 0) {
272
273 mii->mii_media_active |= IFM_NONE;
274 return;
275 }
276 }
277
278 bmsr = PHY_READ(sc, CIPHY_MII_AUXCSR);
279 switch (bmsr & CIPHY_AUXCSR_SPEED) {
280 case CIPHY_SPEED10:
281 mii->mii_media_active |= IFM_10_T;
282 break;
283 case CIPHY_SPEED100:
284 mii->mii_media_active |= IFM_100_TX;
285 break;
286 case CIPHY_SPEED1000:
287 mii->mii_media_active |= IFM_1000_T;
288 break;
289 default:
290 printf("%s: unknown PHY speed %x\n",
291 sc->mii_dev.dv_xname, bmsr & CIPHY_AUXCSR_SPEED);
292 break;
293 }
294
295 if (bmsr & CIPHY_AUXCSR_FDX)
296 mii->mii_media_active |= IFM_FDX;
297 else
298 mii->mii_media_active |= IFM_HDX;
299
300 gsr = PHY_READ(sc, CIPHY_MII_1000STS);
301 if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
302 gsr & CIPHY_1000STS_MSR)
303 mii->mii_media_active |= IFM_ETH_MASTER;
304 }
305
306 void
307 ciphy_reset(struct mii_softc *sc)
308 {
309 mii_phy_reset(sc);
310 DELAY(1000);
311 }
312
313 #define PHY_SETBIT(x, y, z) \
314 PHY_WRITE(x, y, (PHY_READ(x, y) | (z)))
315 #define PHY_CLRBIT(x, y, z) \
316 PHY_WRITE(x, y, (PHY_READ(x, y) & ~(z)))
317
318 void
319 ciphy_fixup(struct mii_softc *sc)
320 {
321 uint16_t model;
322 uint16_t status, speed;
323
324 model = MII_MODEL(PHY_READ(sc, CIPHY_MII_PHYIDR2));
325 status = PHY_READ(sc, CIPHY_MII_AUXCSR);
326 speed = status & CIPHY_AUXCSR_SPEED;
327
328 if (strcmp(sc->mii_dev.dv_parent->dv_cfdata->cf_driver->cd_name, "nfe") == 0) {
329
330 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_INTSEL_RGMII);
331 PHY_SETBIT(sc, CIPHY_MII_ECTL1, CIPHY_IOVOL_2500MV);
332 }
333
334 switch (model) {
335 case MII_MODEL_CICADA_CS8201:
336
337
338 PHY_SETBIT(sc, CIPHY_MII_AUXCSR, CIPHY_AUXCSR_MDPPS);
339
340
341
342
343
344 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
345 (status & CIPHY_AUXCSR_FDX)) {
346 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
347 } else {
348 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
349 }
350
351
352 PHY_SETBIT(sc, CIPHY_MII_LED, CIPHY_LED_LINKACTBLINK);
353
354 break;
355
356 case MII_MODEL_CICADA_CS8201A:
357 case MII_MODEL_CICADA_CS8201B:
358
359
360
361
362
363 if ((speed == CIPHY_SPEED10 || speed == CIPHY_SPEED100) &&
364 (status & CIPHY_AUXCSR_FDX)) {
365 PHY_SETBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
366 } else {
367 PHY_CLRBIT(sc, CIPHY_MII_10BTCSR, CIPHY_10BTCSR_ECHO);
368 }
369
370 break;
371 default:
372 printf("%s: unknown CICADA PHY model %x\n",
373 sc->mii_dev.dv_xname, model);
374 break;
375 }
376 }