1 /* $NetBSD: emac3.c,v 1.11 2016/04/03 10:03:04 martin 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.11 2016/04/03 10:03:04 martin 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 void 312 emac3_phy_writereg(device_t self, int phy, int reg, int data) 313 { 314 315 if (emac3_phy_ready() != 0) 316 return; 317 318 _emac3_reg_write_4(EMAC3_STACR, STACR_WRITE | 319 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/ 320 ((reg << STACR_PRASHIFT) & STACR_PRA) | /* register addr */ 321 ((data << STACR_PHYDSHIFT) & STACR_PHYD)); /* data */ 322 323 if (emac3_phy_ready() != 0) 324 return; 325 } 326 327 int 328 emac3_phy_readreg(device_t self, int phy, int reg) 329 { 330 331 if (emac3_phy_ready() != 0) 332 return (0); 333 334 _emac3_reg_write_4(EMAC3_STACR, STACR_READ | 335 ((phy << STACR_PCDASHIFT) & STACR_PCDA) | /* command dest addr*/ 336 ((reg << STACR_PRASHIFT) & STACR_PRA)); /* register addr */ 337 338 if (emac3_phy_ready() != 0) 339 return (0); 340 341 return ((_emac3_reg_read_4(EMAC3_STACR) >> STACR_PHYDSHIFT) & 0xffff); 342 } 343 344 void 345 emac3_phy_statchg(struct ifnet *ifp) 346 { 347 #define EMAC3_FDX (MR1_FDE | MR1_EIFC | MR1_APP) 348 struct emac3_softc *sc = ifp->if_softc; 349 int media; 350 u_int32_t r; 351 352 media = sc->mii.mii_media_active; 353 354 r = _emac3_reg_read_4(EMAC3_MR1); 355 356 r &= ~(MR1_MF_MASK | MR1_IST | EMAC3_FDX); 357 358 switch (media & 0x1f) { 359 default: 360 printf("unknown media type. %08x", media); 361 /* FALLTHROUGH */ 362 case IFM_100_TX: 363 r |= (MR1_MF_100MBS | MR1_IST); 364 if (media & IFM_FDX) 365 r |= EMAC3_FDX; 366 367 break; 368 case IFM_10_T: 369 r |= MR1_MF_10MBS; 370 if (media & IFM_FDX) 371 r |= (EMAC3_FDX | MR1_IST); 372 break; 373 } 374 375 _emac3_reg_write_4(EMAC3_MR1, r); 376 377 /* store current state for re-initialize */ 378 sc->mode1_reg = _emac3_reg_read_4(EMAC3_MR1); 379 #undef EMAC3_FDX 380 } 381 382 int 383 emac3_phy_ready(void) 384 { 385 int retry = 10000; 386 387 while ((_emac3_reg_read_4(EMAC3_STACR) & STACR_OC) == 0 && 388 --retry > 0) 389 ; 390 if (retry == 0) { 391 printf("emac3: phy busy.\n"); 392 return (1); 393 } 394 395 return (0); 396 } 397 398