emac3.c revision 1.8.16.1 1 /* $NetBSD: emac3.c,v 1.8.16.1 2014/05/18 17:45:21 rmind Exp $ */
2
3 /*-
4 * Copyright (c) 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by UCHIYAMA Yasushi.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * EMAC3 (Ethernet Media Access Controller)
34 */
35
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: emac3.c,v 1.8.16.1 2014/05/18 17:45:21 rmind Exp $");
38
39 #include "debug_playstation2.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43
44 #include <sys/socket.h>
45
46 #include <net/if.h>
47 #include <net/if_ether.h>
48 #include <net/if_media.h>
49
50 #include <dev/mii/mii.h>
51 #include <dev/mii/miivar.h>
52
53 #include <playstation2/ee/eevar.h>
54 #include <playstation2/dev/emac3reg.h>
55 #include <playstation2/dev/emac3var.h>
56
57 #ifdef EMAC3_DEBUG
58 #define STATIC
59 int emac3_debug = 0;
60 #define DPRINTF(fmt, args...) \
61 if (emac3_debug) \
62 printf("%s: " fmt, __func__ , ##args)
63 #define DPRINTFN(n, arg) \
64 if (emac3_debug > (n)) \
65 n printf("%s: " fmt, __func__ , ##args)
66 #else
67 #define STATIC static
68 #define DPRINTF(arg...) ((void)0)
69 #define DPRINTFN(n, arg...) ((void)0)
70 #endif
71
72 /* SMAP specific EMAC3 define */
73 #define EMAC3_BASE MIPS_PHYS_TO_KSEG1(0x14002000)
74 static inline u_int32_t
75 _emac3_reg_read_4(int ofs)
76 {
77 bus_addr_t a_ = EMAC3_BASE + ofs;
78
79 return (_reg_read_2(a_) << 16) | _reg_read_2(a_ + 2);
80 }
81
82 static inline void
83 _emac3_reg_write_4(int ofs, u_int32_t v)
84 {
85 bus_addr_t a_ = EMAC3_BASE + ofs;
86
87 _reg_write_2(a_, (v >> 16) & 0xffff);
88 _reg_write_2(a_ + 2, v & 0xffff);
89 }
90
91 STATIC int emac3_phy_ready(void);
92 STATIC int emac3_soft_reset(void);
93 STATIC void emac3_config(const u_int8_t *);
94
95 int
96 emac3_init(struct emac3_softc *sc)
97 {
98 u_int32_t r;
99
100 /* save current mode before reset */
101 r = _emac3_reg_read_4(EMAC3_MR1);
102
103 if (emac3_soft_reset() != 0) {
104 printf("%s: reset failed.\n", sc->dev.dv_xname);
105 return (1);
106 }
107
108 /* set operation mode */
109 r |= MR1_RFS_2KB | MR1_TFS_1KB | MR1_TR0_SINGLE | MR1_TR1_SINGLE;
110 _emac3_reg_write_4(EMAC3_MR1, r);
111
112 sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
113
114 emac3_intr_clear();
115 emac3_intr_disable();
116
117 emac3_config(sc->eaddr);
118
119 return (0);
120 }
121
122 void
123 emac3_exit(struct emac3_softc *sc)
124 {
125 int retry = 10000;
126
127 /* wait for kicked transmission */
128 while (((_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0) != 0) &&
129 --retry > 0)
130 ;
131
132 if (retry == 0)
133 printf("%s: still running.\n", sc->dev.dv_xname);
134 }
135
136 int
137 emac3_reset(struct emac3_softc *sc)
138 {
139
140 if (emac3_soft_reset() != 0) {
141 printf("%s: reset failed.\n", sc->dev.dv_xname);
142 return (1);
143 }
144
145 /* restore previous mode */
146 _emac3_reg_write_4(EMAC3_MR1, sc->mode1_reg);
147
148 emac3_config(sc->eaddr);
149
150 return (0);
151 }
152
153 void
154 emac3_enable()
155 {
156
157 _emac3_reg_write_4(EMAC3_MR0, MR0_TXE | MR0_RXE);
158 }
159
160 void
161 emac3_disable()
162 {
163 int retry = 10000;
164
165 _emac3_reg_write_4(EMAC3_MR0,
166 _emac3_reg_read_4(EMAC3_MR0) & ~(MR0_TXE | MR0_RXE));
167
168 /* wait for idling state */
169 while (((_emac3_reg_read_4(EMAC3_MR0) & (MR0_RXI | MR0_TXI)) !=
170 (MR0_RXI | MR0_TXI)) && --retry > 0)
171 ;
172
173 if (retry == 0)
174 printf("emac3 running.\n");
175 }
176
177 void
178 emac3_intr_enable()
179 {
180
181 _emac3_reg_write_4(EMAC3_ISER, ~0);
182 }
183
184 void
185 emac3_intr_disable()
186 {
187
188 _emac3_reg_write_4(EMAC3_ISER, 0);
189 }
190
191 void
192 emac3_intr_clear()
193 {
194
195 _emac3_reg_write_4(EMAC3_ISR, _emac3_reg_read_4(EMAC3_ISR));
196 }
197
198 int
199 emac3_intr(void *arg)
200 {
201 u_int32_t r = _emac3_reg_read_4(EMAC3_ISR);
202
203 DPRINTF("%08x\n", r);
204 _emac3_reg_write_4(EMAC3_ISR, r);
205
206 return (1);
207 }
208
209 void
210 emac3_tx_kick()
211 {
212
213 _emac3_reg_write_4(EMAC3_TMR0, TMR0_GNP0);
214 }
215
216 int
217 emac3_tx_done()
218 {
219
220 return (_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0);
221 }
222
223 void
224 emac3_setmulti(struct emac3_softc *sc, struct ethercom *ec)
225 {
226 struct ether_multi *enm;
227 struct ether_multistep step;
228 struct ifnet *ifp = &ec->ec_if;
229 u_int32_t r;
230
231 r = _emac3_reg_read_4(EMAC3_RMR);
232 r &= ~(RMR_PME | RMR_PMME | RMR_MIAE);
233
234 if (ifp->if_flags & IFF_PROMISC) {
235 allmulti:
236 ifp->if_flags |= IFF_ALLMULTI;
237 r |= RMR_PME;
238 _emac3_reg_write_4(EMAC3_RMR, r);
239
240 return;
241 }
242
243 ETHER_FIRST_MULTI(step, ec, enm);
244 while (enm != NULL) {
245 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
246 ETHER_ADDR_LEN) != 0)
247 goto allmulti;
248
249 ETHER_NEXT_MULTI(step, enm)
250 }
251
252 /* XXX always multicast promiscuous mode. XXX use hash table.. */
253 ifp->if_flags |= IFF_ALLMULTI;
254 r |= RMR_PMME;
255 _emac3_reg_write_4(EMAC3_RMR, r);
256 }
257
258 int
259 emac3_soft_reset()
260 {
261 int retry = 10000;
262
263 _emac3_reg_write_4(EMAC3_MR0, MR0_SRST);
264
265 while ((_emac3_reg_read_4(EMAC3_MR0) & MR0_SRST) == MR0_SRST &&
266 --retry > 0)
267 ;
268
269 return (retry == 0);
270 }
271
272 void
273 emac3_config(const u_int8_t *eaddr)
274 {
275
276 /* set ethernet address */
277 _emac3_reg_write_4(EMAC3_IAHR, (eaddr[0] << 8) | eaddr[1]);
278 _emac3_reg_write_4(EMAC3_IALR, (eaddr[2] << 24) | (eaddr[3] << 16) |
279 (eaddr[4] << 8) | eaddr[5]);
280
281 /* inter-frame GAP */
282 _emac3_reg_write_4(EMAC3_IPGVR, 4);
283
284 /* RX mode */
285 _emac3_reg_write_4(EMAC3_RMR,
286 RMR_SP | /* strip padding */
287 RMR_SFCS | /* strip FCS */
288 RMR_IAE | /* individual address enable */
289 RMR_BAE); /* boradcast address enable */
290
291 /* TX mode */
292 _emac3_reg_write_4(EMAC3_TMR1,
293 ((7 << TMR1_TLR_SHIFT) & TMR1_TLR_MASK) | /* 16 word burst */
294 ((15 << TMR1_TUR_SHIFT) & TMR1_TUR_MASK));
295
296 /* TX threshold */
297 _emac3_reg_write_4(EMAC3_TRTR,
298 (12 << TRTR_SHIFT) & TRTR_MASK); /* 832 bytes */
299
300 /* RX watermark */
301 _emac3_reg_write_4(EMAC3_RWMR,
302 ((16 << RWMR_RLWM_SHIFT) & RWMR_RLWM_MASK) |
303 ((128 << RWMR_RHWM_SHIFT) & RWMR_RHWM_MASK));
304 }
305
306 /*
307 * PHY/MII
308 */
309 void
310 emac3_phy_writereg(struct device *self, int phy, int reg, int data)
311 {
312
313 if (emac3_phy_ready() != 0)
314 return;
315
316 _emac3_reg_write_4(EMAC3_STACR, STACR_WRITE |
317 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
318 ((reg << STACR_PRASHIFT) & STACR_PRA) | /* register addr */
319 ((data << STACR_PHYDSHIFT) & STACR_PHYD)); /* data */
320
321 if (emac3_phy_ready() != 0)
322 return;
323 }
324
325 int
326 emac3_phy_readreg(struct device *self, int phy, int reg)
327 {
328
329 if (emac3_phy_ready() != 0)
330 return (0);
331
332 _emac3_reg_write_4(EMAC3_STACR, STACR_READ |
333 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
334 ((reg << STACR_PRASHIFT) & STACR_PRA)); /* register addr */
335
336 if (emac3_phy_ready() != 0)
337 return (0);
338
339 return ((_emac3_reg_read_4(EMAC3_STACR) >> STACR_PHYDSHIFT) & 0xffff);
340 }
341
342 void
343 emac3_phy_statchg(struct device *dev)
344 {
345 #define EMAC3_FDX (MR1_FDE | MR1_EIFC | MR1_APP)
346 struct emac3_softc *sc = (void *)dev;
347 int media;
348 u_int32_t r;
349
350 media = sc->mii.mii_media_active;
351
352 r = _emac3_reg_read_4(EMAC3_MR1);
353
354 r &= ~(MR1_MF_MASK | MR1_IST | EMAC3_FDX);
355
356 switch (media & 0x1f) {
357 default:
358 printf("unknown media type. %08x", media);
359 /* FALLTHROUGH */
360 case IFM_100_TX:
361 r |= (MR1_MF_100MBS | MR1_IST);
362 if (media & IFM_FDX)
363 r |= EMAC3_FDX;
364
365 break;
366 case IFM_10_T:
367 r |= MR1_MF_10MBS;
368 if (media & IFM_FDX)
369 r |= (EMAC3_FDX | MR1_IST);
370 break;
371 }
372
373 _emac3_reg_write_4(EMAC3_MR1, r);
374
375 /* store current state for re-initialize */
376 sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
377 #undef EMAC3_FDX
378 }
379
380 int
381 emac3_phy_ready()
382 {
383 int retry = 10000;
384
385 while ((_emac3_reg_read_4(EMAC3_STACR) & STACR_OC) == 0 &&
386 --retry > 0)
387 ;
388 if (retry == 0) {
389 printf("emac3: phy busy.\n");
390 return (1);
391 }
392
393 return (0);
394 }
395
396