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