1 /* $NetBSD: emac3.c,v 1.9 2014/03/31 11:25:49 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.9 2014/03/31 11:25:49 martin 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