emac3.c revision 1.13 1 /* $NetBSD: emac3.c,v 1.13 2019/01/22 03:42:26 msaitoh 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.13 2019/01/22 03:42:26 msaitoh Exp $");
38
39 #include "debug_playstation2.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43
44 #include <sys/device.h>
45 #include <sys/socket.h>
46 #include <sys/pmf.h>
47
48 #include <net/if.h>
49 #include <net/if_ether.h>
50 #include <net/if_media.h>
51
52 #include <dev/mii/mii.h>
53 #include <dev/mii/miivar.h>
54
55 #include <playstation2/ee/eevar.h>
56 #include <playstation2/dev/emac3reg.h>
57 #include <playstation2/dev/emac3var.h>
58
59 #ifdef EMAC3_DEBUG
60 #define STATIC
61 int emac3_debug = 0;
62 #define DPRINTF(fmt, args...) \
63 if (emac3_debug) \
64 printf("%s: " fmt, __func__ , ##args)
65 #define DPRINTFN(n, arg) \
66 if (emac3_debug > (n)) \
67 printf("%s: " fmt, __func__ , ##args)
68 #else
69 #define STATIC static
70 #define DPRINTF(arg...) ((void)0)
71 #define DPRINTFN(n, arg...) ((void)0)
72 #endif
73
74 /* SMAP specific EMAC3 define */
75 #define EMAC3_BASE MIPS_PHYS_TO_KSEG1(0x14002000)
76 static inline u_int32_t
77 _emac3_reg_read_4(int ofs)
78 {
79 bus_addr_t a_ = EMAC3_BASE + ofs;
80
81 return (_reg_read_2(a_) << 16) | _reg_read_2(a_ + 2);
82 }
83
84 static inline void
85 _emac3_reg_write_4(int ofs, u_int32_t v)
86 {
87 bus_addr_t a_ = EMAC3_BASE + ofs;
88
89 _reg_write_2(a_, (v >> 16) & 0xffff);
90 _reg_write_2(a_ + 2, v & 0xffff);
91 }
92
93 STATIC int emac3_phy_ready(void);
94 STATIC int emac3_soft_reset(void);
95 STATIC void emac3_config(const u_int8_t *);
96
97 int
98 emac3_init(struct emac3_softc *sc)
99 {
100 u_int32_t r;
101
102 /* save current mode before reset */
103 r = _emac3_reg_read_4(EMAC3_MR1);
104
105 if (emac3_soft_reset() != 0) {
106 printf("%s: reset failed.\n", sc->dev.dv_xname);
107 return (1);
108 }
109
110 /* set operation mode */
111 r |= MR1_RFS_2KB | MR1_TFS_1KB | MR1_TR0_SINGLE | MR1_TR1_SINGLE;
112 _emac3_reg_write_4(EMAC3_MR1, r);
113
114 sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
115
116 emac3_intr_clear();
117 emac3_intr_disable();
118
119 emac3_config(sc->eaddr);
120
121 return (0);
122 }
123
124 void
125 emac3_exit(struct emac3_softc *sc)
126 {
127 int retry = 10000;
128
129 /* wait for kicked transmission */
130 while (((_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0) != 0) &&
131 --retry > 0)
132 ;
133
134 if (retry == 0)
135 printf("%s: still running.\n", sc->dev.dv_xname);
136 }
137
138 int
139 emac3_reset(struct emac3_softc *sc)
140 {
141
142 if (emac3_soft_reset() != 0) {
143 printf("%s: reset failed.\n", sc->dev.dv_xname);
144 return (1);
145 }
146
147 /* restore previous mode */
148 _emac3_reg_write_4(EMAC3_MR1, sc->mode1_reg);
149
150 emac3_config(sc->eaddr);
151
152 return (0);
153 }
154
155 void
156 emac3_enable(void)
157 {
158
159 _emac3_reg_write_4(EMAC3_MR0, MR0_TXE | MR0_RXE);
160 }
161
162 void
163 emac3_disable(void)
164 {
165 int retry = 10000;
166
167 _emac3_reg_write_4(EMAC3_MR0,
168 _emac3_reg_read_4(EMAC3_MR0) & ~(MR0_TXE | MR0_RXE));
169
170 /* wait for idling state */
171 while (((_emac3_reg_read_4(EMAC3_MR0) & (MR0_RXI | MR0_TXI)) !=
172 (MR0_RXI | MR0_TXI)) && --retry > 0)
173 ;
174
175 if (retry == 0)
176 printf("emac3 running.\n");
177 }
178
179 void
180 emac3_intr_enable(void)
181 {
182
183 _emac3_reg_write_4(EMAC3_ISER, ~0);
184 }
185
186 void
187 emac3_intr_disable(void)
188 {
189
190 _emac3_reg_write_4(EMAC3_ISER, 0);
191 }
192
193 void
194 emac3_intr_clear(void)
195 {
196
197 _emac3_reg_write_4(EMAC3_ISR, _emac3_reg_read_4(EMAC3_ISR));
198 }
199
200 int
201 emac3_intr(void *arg)
202 {
203 u_int32_t r = _emac3_reg_read_4(EMAC3_ISR);
204
205 DPRINTF("%08x\n", r);
206 _emac3_reg_write_4(EMAC3_ISR, r);
207
208 return (1);
209 }
210
211 void
212 emac3_tx_kick(void)
213 {
214
215 _emac3_reg_write_4(EMAC3_TMR0, TMR0_GNP0);
216 }
217
218 int
219 emac3_tx_done(void)
220 {
221
222 return (_emac3_reg_read_4(EMAC3_TMR0) & TMR0_GNP0);
223 }
224
225 void
226 emac3_setmulti(struct emac3_softc *sc, struct ethercom *ec)
227 {
228 struct ether_multi *enm;
229 struct ether_multistep step;
230 struct ifnet *ifp = &ec->ec_if;
231 u_int32_t r;
232
233 r = _emac3_reg_read_4(EMAC3_RMR);
234 r &= ~(RMR_PME | RMR_PMME | RMR_MIAE);
235
236 if (ifp->if_flags & IFF_PROMISC) {
237 allmulti:
238 ifp->if_flags |= IFF_ALLMULTI;
239 r |= RMR_PME;
240 _emac3_reg_write_4(EMAC3_RMR, r);
241
242 return;
243 }
244
245 ETHER_FIRST_MULTI(step, ec, enm);
246 while (enm != NULL) {
247 if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
248 ETHER_ADDR_LEN) != 0)
249 goto allmulti;
250
251 ETHER_NEXT_MULTI(step, enm);
252 }
253
254 /* XXX always multicast promiscuous mode. XXX use hash table.. */
255 ifp->if_flags |= IFF_ALLMULTI;
256 r |= RMR_PMME;
257 _emac3_reg_write_4(EMAC3_RMR, r);
258 }
259
260 int
261 emac3_soft_reset(void)
262 {
263 int retry = 10000;
264
265 _emac3_reg_write_4(EMAC3_MR0, MR0_SRST);
266
267 while ((_emac3_reg_read_4(EMAC3_MR0) & MR0_SRST) == MR0_SRST &&
268 --retry > 0)
269 ;
270
271 return (retry == 0);
272 }
273
274 void
275 emac3_config(const u_int8_t *eaddr)
276 {
277
278 /* set ethernet address */
279 _emac3_reg_write_4(EMAC3_IAHR, (eaddr[0] << 8) | eaddr[1]);
280 _emac3_reg_write_4(EMAC3_IALR, (eaddr[2] << 24) | (eaddr[3] << 16) |
281 (eaddr[4] << 8) | eaddr[5]);
282
283 /* inter-frame GAP */
284 _emac3_reg_write_4(EMAC3_IPGVR, 4);
285
286 /* RX mode */
287 _emac3_reg_write_4(EMAC3_RMR,
288 RMR_SP | /* strip padding */
289 RMR_SFCS | /* strip FCS */
290 RMR_IAE | /* individual address enable */
291 RMR_BAE); /* boradcast address enable */
292
293 /* TX mode */
294 _emac3_reg_write_4(EMAC3_TMR1,
295 ((7 << TMR1_TLR_SHIFT) & TMR1_TLR_MASK) | /* 16 word burst */
296 ((15 << TMR1_TUR_SHIFT) & TMR1_TUR_MASK));
297
298 /* TX threshold */
299 _emac3_reg_write_4(EMAC3_TRTR,
300 (12 << TRTR_SHIFT) & TRTR_MASK); /* 832 bytes */
301
302 /* RX watermark */
303 _emac3_reg_write_4(EMAC3_RWMR,
304 ((16 << RWMR_RLWM_SHIFT) & RWMR_RLWM_MASK) |
305 ((128 << RWMR_RHWM_SHIFT) & RWMR_RHWM_MASK));
306 }
307
308 /*
309 * PHY/MII
310 */
311 int
312 emac3_phy_writereg(device_t self, int phy, int reg, uint16_t val)
313 {
314 int rv;
315
316 if ((rv = emac3_phy_ready()) != 0)
317 return rv;
318
319 _emac3_reg_write_4(EMAC3_STACR, STACR_WRITE |
320 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
321 ((reg << STACR_PRASHIFT) & STACR_PRA) | /* register addr */
322 ((val << STACR_PHYDSHIFT) & STACR_PHYD)); /* data */
323
324 return emac3_phy_ready();
325 }
326
327 int
328 emac3_phy_readreg(device_t self, int phy, int reg, uint16_t *val)
329 {
330 int rv;
331
332 if ((rv = emac3_phy_ready()) != 0)
333 return rv;
334
335 _emac3_reg_write_4(EMAC3_STACR, STACR_READ |
336 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/
337 ((reg << STACR_PRASHIFT) & STACR_PRA)); /* register addr */
338
339 if ((rv = emac3_phy_ready()) != 0)
340 return rv;
341
342 *val =(_emac3_reg_read_4(EMAC3_STACR) >> STACR_PHYDSHIFT) & 0xffff;
343 return 0;
344 }
345
346 void
347 emac3_phy_statchg(struct ifnet *ifp)
348 {
349 #define EMAC3_FDX (MR1_FDE | MR1_EIFC | MR1_APP)
350 struct emac3_softc *sc = ifp->if_softc;
351 int media;
352 u_int32_t r;
353
354 media = sc->mii.mii_media_active;
355
356 r = _emac3_reg_read_4(EMAC3_MR1);
357
358 r &= ~(MR1_MF_MASK | MR1_IST | EMAC3_FDX);
359
360 switch (media & 0x1f) {
361 default:
362 printf("unknown media type. %08x", media);
363 /* FALLTHROUGH */
364 case IFM_100_TX:
365 r |= (MR1_MF_100MBS | MR1_IST);
366 if (media & IFM_FDX)
367 r |= EMAC3_FDX;
368
369 break;
370 case IFM_10_T:
371 r |= MR1_MF_10MBS;
372 if (media & IFM_FDX)
373 r |= (EMAC3_FDX | MR1_IST);
374 break;
375 }
376
377 _emac3_reg_write_4(EMAC3_MR1, r);
378
379 /* store current state for re-initialize */
380 sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1);
381 #undef EMAC3_FDX
382 }
383
384 int
385 emac3_phy_ready(void)
386 {
387 int retry = 10000;
388
389 while ((_emac3_reg_read_4(EMAC3_STACR) & STACR_OC) == 0 &&
390 --retry > 0)
391 ;
392 if (retry == 0) {
393 printf("emac3: phy busy.\n");
394 return ETIMEDOUT;
395 }
396
397 return (0);
398 }
399
400