1 /* $NetBSD: dm9000.c,v 1.4 2021/12/12 13:05:13 andvar Exp $ */ 2 3 /*- 4 * Copyright (c) 2012 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Tohru Nishimura. 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 #include <sys/param.h> 33 #include <netinet/in.h> 34 #include <netinet/in_systm.h> 35 36 #include <lib/libsa/stand.h> 37 #include <lib/libsa/net.h> 38 39 /* 40 * This DM9000 is wired as a 16bit device and manages Tx/Rx SRAM buffer 41 * in 16bit quantity. MRCMD/MWCMD access increments buffer pointer 42 * by two regardless of r/w size. Mixing 16/8bit access is not possible. 43 * Byte read would end up with loosing every odd indexed datum. 44 * 45 * The DM9000 CMD pin is tied with SoC LADDR2 address line. SA9-SA4 46 * pins are hardwired to fixed decoding 0x300. Thus address [26:3] in 47 * CS4 range 0x2000'0000 are don't-care bits to manipulate the chip. 48 * The DM9000 INDEX port is accessed at the address b'000 while the 49 * DATA port at the address b'100. 50 * 51 * This code assumes Little endian CPU. 52 */ 53 54 #define NCR 0x00 /* control */ 55 #define NCR_FDX (1<<3) /* FDX link detection report */ 56 #define NCR_RST (1<<0) /* instruct reset, goes 0 at done */ 57 #define NSR 0x01 /* status */ 58 #define NSR_SPEED (1<<7) /* 1->100M, 0->10M, when link is up */ 59 #define NSR_LINKST (1<<6) /* 1->linkup, 0->linkdown */ 60 #define NSR_TX2END (1<<3) /* Tx frame #2 completed */ 61 #define NSR_TX1END (1<<2) /* Tx frame #1 completed */ 62 #define NSR_RXOV (1<<1) /* Rx FIFO overflow detected */ 63 #define TCR 0x02 /* Tx control */ 64 #define TCR_TXREQ 0x01 /* request to start transmit, goes 0 at done */ 65 #define TCR2 0x2d /* Tx control #2 */ 66 #define TCR2_ONEPM 0x10 /* send single Tx frame at a time */ 67 #define RCR 0x05 /* Rx control */ 68 #define RCR_WTDIS 0x40 /* disable frame receipt watchdog timer */ 69 #define RCR_DIS_LONG 0x20 /* discard too-long Rx frame */ 70 #define RCR_DIS_CRC 0x10 /* discard CRC error Rx frame */ 71 #define RCR_ALL 0x08 /* accept MCAST frames */ 72 #define RCR_RUNT 0x04 /* accept runt Rx frame */ 73 #define RCR_PRMSC 0x02 /* promiscuous */ 74 #define RCR_RXEN 0x01 /* enable frame reception */ 75 #define RSR 0x06 /* RX status */ 76 #define RSR_MF (1<<6) /* bcast/mcast frame found */ 77 #define FCR 0x0a /* flow control */ 78 #define FCR_FLCE 0x01 /* enable Tx/Rx flow control */ 79 #define EPCR 0x0b /* EEPROM and PHY control */ 80 #define EP_EPOS (1<<3) /* 1 for PHY op, 0 for EEPROM op */ 81 #define EP_ERPRR (1<<2) /* instruct to start read op */ 82 #define EP_ERPRW (1<<1) /* instruct to start write op */ 83 #define EP_ERRE (1<<0) /* 1 while operation is in progress */ 84 #define EPAR 0x0c /* [7:6] for PHY#, [5:0] for addr */ 85 #define EPDRL 0x0d /* EEPROM/PHY data low byte */ 86 #define EPDRH 0x0e /* EEPROM/PHY data high byte */ 87 #define PAR 0x10 /* station address */ 88 #define MAR 0x16 /* multicast filter hash value */ 89 #define GPR 0x1f /* gpio control */ 90 #define GPR_PHYPWROFF 0x01 /* powerdown internal PHY */ 91 #define VID0 0x28 /* vendor ID low byte */ 92 #define VID1 0x29 /* vendor ID high byte */ 93 #define PID0 0x2a /* product ID low byte */ 94 #define PID1 0x2b /* product ID high byte */ 95 #define CHIPR 0x2c /* chip revision */ 96 #define MRCMDX 0xf0 /* read data w/o pointer incr */ 97 #define MRCMD 0xf2 /* read data with pointer auto incr */ 98 #define MWCMD 0xf8 /* write data with pointer auto incr */ 99 #define TXPLL 0xfc /* Tx frame length low byte */ 100 #define TXPLH 0xfd /* Tx frame length high byte */ 101 #define ISR 0xfe /* interrupt status report */ 102 #define ISR_LNKCHG 0x20 /* link status change detected */ 103 #define ISR_UDRUN 0x10 /* transmit underrun detected */ 104 #define ISR_PTM (1<<1) /* frame Tx completed */ 105 #define ISR_PRS (1<<0) /* frame Rx completed */ 106 #define IMR 0xff /* interrupt mask */ 107 #define IMR_PAR (1<<7) /* use 3/13K SRAM partitioning with autowrap */ 108 #define IMR_PRM (1<<0) /* post interrupt when Rx completed */ 109 110 #ifndef DM9000MAC 111 #define DM9000MAC 0x08,0x08,0x11,0x18,0x12,0x27 112 #endif 113 114 struct local { 115 unsigned int csr; 116 unsigned int phy, bmsr, anlpar; 117 uint8_t en[6]; 118 }; 119 120 static struct local dm9000local; 121 122 int dm9k_match(unsigned int, void *); 123 void *dm9k_init(unsigned int, void *); 124 int dm9k_send(void *, char *, unsigned int); 125 int dm9k_recv(void *, char *, unsigned int, unsigned int); 126 127 static unsigned mii_read(struct local *, int, int); 128 static void mii_write(struct local *, int, int, int); 129 static void mii_dealan(struct local *, unsigned int); 130 131 extern void usleep(int); 132 133 static inline int 134 CSR_READ_1(struct local *l, int reg) 135 { 136 *(volatile uint8_t *)(l->csr) = reg; 137 return *(volatile uint8_t*)(l->csr + 4); 138 } 139 140 static inline int 141 CSR_READ_2(struct local *l, int reg) 142 { 143 *(volatile uint8_t *)(l->csr) = reg; 144 return *(volatile uint16_t *)(l->csr + 4); 145 } 146 147 static inline void 148 CSR_WRITE_1(struct local *l, int reg, int data) 149 { 150 *(volatile uint8_t *)(l->csr) = reg; 151 *(volatile uint8_t *)(l->csr + 4) = data; 152 } 153 154 static inline void 155 CSR_WRITE_2(struct local *l, int reg, int data) 156 { 157 *(volatile uint8_t *)(l->csr) = reg; 158 *(volatile uint16_t *)(l->csr + 4) = data; 159 } 160 161 int 162 dm9k_match(unsigned int tag, void *aux) 163 { 164 struct local *l = &dm9000local; 165 uint8_t *en = aux; 166 uint8_t std[6] = { DM9000MAC }; 167 int val; 168 169 l->csr = 0x20000000; 170 val = CSR_READ_1(l, PID0); 171 val |= CSR_READ_1(l, PID1) << 8; 172 val |= CSR_READ_1(l, VID0) << 16; 173 val |= CSR_READ_1(l, VID1) << 24; 174 if (val != 0x0a469000) { 175 printf("DM9000 not found at 0x%x\n", l->csr); 176 return 0; 177 } 178 if (en != NULL 179 && en[0] && en[1] && en[2] && en[3] && en[4] && en[5]) 180 memcpy(l->en, en, 6); 181 else if (en != NULL) { 182 memcpy(en, std, 6); 183 memcpy(l->en, std, 6); 184 } 185 return 1; 186 } 187 188 void * 189 dm9k_init(unsigned int tag, void *aux) 190 { 191 struct local *l = &dm9000local; 192 uint8_t *en = l->en; 193 unsigned int val, fdx; 194 195 val = CSR_READ_1(l, CHIPR); 196 printf("DM9000 rev. %#x", val); 197 val = CSR_READ_1(l, ISR); 198 printf(", %d bit mode\n", (val & 1<<7) ? 8 : 16); 199 200 CSR_WRITE_1(l, NCR, 0); /* use internal PHY */ 201 l->phy = 1; 202 203 /* force PHY poweroff */ 204 CSR_WRITE_1(l, GPR, GPR_PHYPWROFF); 205 206 CSR_WRITE_1(l, IMR, 0); 207 CSR_WRITE_1(l, TCR, 0); 208 CSR_WRITE_1(l, RCR, 0); 209 210 /* SW reset */ 211 CSR_WRITE_1(l, NCR, NCR_RST); 212 do { 213 usleep(1); 214 } while (NCR_RST & CSR_READ_1(l, NCR)); 215 216 /* negate PHY poweroff condition */ 217 CSR_WRITE_1(l, GPR, 0); 218 219 /* SW reset, again */ 220 CSR_WRITE_1(l, NCR, NCR_RST); 221 do { 222 usleep(1); 223 } while (NCR_RST & CSR_READ_1(l, NCR)); 224 225 /* clear NSR bits */ 226 (void) CSR_READ_1(l, NSR); 227 228 printf("MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", 229 en[0], en[1], en[2], en[3], en[4], en[5]); 230 CSR_WRITE_1(l, PAR + 0, en[0]); 231 CSR_WRITE_1(l, PAR + 1, en[1]); 232 CSR_WRITE_1(l, PAR + 2, en[2]); 233 CSR_WRITE_1(l, PAR + 3, en[3]); 234 CSR_WRITE_1(l, PAR + 4, en[4]); 235 CSR_WRITE_1(l, PAR + 5, en[5]); 236 237 /* make sure not to receive bcast/mcast frames */ 238 CSR_WRITE_1(l, MAR + 0, 0); 239 CSR_WRITE_1(l, MAR + 1, 0); 240 CSR_WRITE_1(l, MAR + 2, 0); 241 CSR_WRITE_1(l, MAR + 3, 0); 242 CSR_WRITE_1(l, MAR + 4, 0); 243 CSR_WRITE_1(l, MAR + 5, 0); 244 CSR_WRITE_1(l, MAR + 6, 0); 245 CSR_WRITE_1(l, MAR + 7, 0); 246 247 /* perform link auto-negotiation */ 248 printf("waiting for linkup ... "); 249 mii_dealan(l, 5); 250 251 val = CSR_READ_1(l, NSR); 252 if ((val & NSR_LINKST) == 0) { 253 printf("failed; cable problem?\n"); 254 return NULL; 255 } 256 257 /* 258 * speed and duplexity can be seen in MII 17. 259 * bit15 100Mbps-FDX 260 * bit14 100Mbps 261 * bit13 10Mbps-FDX 262 * bit12 10Mbps 263 * also available in NSR[SPEED] and NCR[FDX] respectively. 264 */ 265 val = mii_read(l, l->phy, 17); 266 if (val & (03 << 14)) 267 printf("100Mbps"); 268 if (val & (03 << 12)) 269 printf("10Mbps"); 270 fdx = !!(val & (05 << 13)); 271 if (fdx) { 272 printf("-FDX"); 273 val = CSR_READ_1(l, FCR); 274 CSR_WRITE_1(l, FCR, val | FCR_FLCE); 275 } 276 printf("\n"); 277 278 CSR_WRITE_1(l, NSR, ~0); 279 CSR_WRITE_1(l, ISR, ~0); 280 281 /* 282 * - send one frame at a time. 283 * - disable Rx watchdog timer, discard too-long/CRC error frames. 284 * - 3/13K SRAM partitioning, r/w pointer autowrap. 285 */ 286 CSR_WRITE_1(l, TCR2, TCR2_ONEPM); 287 CSR_WRITE_1(l, RCR, RCR_RXEN | RCR_WTDIS | RCR_DIS_LONG | RCR_DIS_CRC); 288 CSR_WRITE_1(l, IMR, IMR_PAR); 289 290 memcpy(aux, l->en, 6); 291 return l; 292 } 293 294 int 295 dm9k_send(void *dev, char *buf, unsigned int len) 296 { 297 struct local *l = dev; 298 unsigned int val, cnt, bound; 299 300 if (len > 1520) { 301 printf("dm9k_send: len > 1520 (%u)\n", len); 302 len = 1520; 303 } 304 305 CSR_WRITE_1(l, ISR, ISR_PTM); /* clear ISR Tx complete bit */ 306 for (cnt = 0; cnt < len; cnt += 2) { 307 val = (buf[1] << 8) | buf[0]; 308 CSR_WRITE_2(l, MWCMD, val); 309 buf += 2; 310 } 311 CSR_WRITE_1(l, TXPLL, len); 312 CSR_WRITE_1(l, TXPLH, len >> 8); 313 CSR_WRITE_1(l, TCR, TCR_TXREQ); /* request to transmit */ 314 315 bound = getsecs() + 1; 316 do { 317 val = CSR_READ_1(l, TCR); 318 if ((val & TCR_TXREQ) == 0) 319 goto done; 320 } while (getsecs() < bound); 321 printf("xmit failed\n"); 322 return -1; 323 done: 324 return len; 325 } 326 327 int 328 dm9k_recv(void *dev, char *buf, unsigned int maxlen, unsigned int timo) 329 { 330 struct local *l = dev; 331 unsigned int bound, val, mark, stat, len, upto, cnt; 332 char *ptr; 333 334 bound = getsecs() + timo; /* second */ 335 again: 336 do { 337 /* wait for Rx completion */ 338 val = CSR_READ_1(l, ISR); 339 if (val & ISR_PRS) 340 goto gotone; 341 /* usleep(10); this makes a stuck in mid transfer */ 342 } while (getsecs() < bound); 343 printf("receive timeout (%d seconds wait)\n", timo); 344 errno = 0; 345 return -1; 346 gotone: 347 CSR_WRITE_1(l, ISR, ISR_PRS); /* clear ISR Rx complete bit */ 348 (void) CSR_READ_2(l, MRCMDX); /* dummy read */ 349 mark = CSR_READ_2(l, MRCMDX); /* mark in [7:0] */ 350 if ((mark & 03) != 01) { 351 stat = CSR_READ_1(l, RSR); 352 printf("dm9k_recv: mark %x, RSR %x\n", mark, stat); 353 /* XXX got hosed, need full scale reinitialise XXX */ 354 goto again; 355 } 356 357 stat = CSR_READ_2(l, MRCMD); /* stat in [15:8] */ 358 len = CSR_READ_2(l, MRCMD); 359 360 /* should not happen, make sure to discard bcast/mcast frames */ 361 if (stat & (RSR_MF<<8)) { 362 for (cnt = 0; cnt < len; cnt += 2) 363 (void) CSR_READ_2(l, MRCMD); 364 printf("bcast/mcast frame, len = %d\n", len); 365 goto again; 366 } 367 368 upto = len - 4; /* HASFCS */ 369 if (upto > maxlen) 370 upto = maxlen; 371 ptr = buf; 372 for (cnt = 0; cnt < upto; cnt += 2) { 373 val = CSR_READ_2(l, MRCMD); 374 ptr[0] = val; 375 ptr[1] = val >> 8; 376 ptr += 2; 377 } 378 /* discard trailing bytes */ 379 for (; cnt < len; cnt += 2) 380 (void) CSR_READ_2(l, MRCMD); 381 382 return upto; 383 } 384 385 static unsigned int 386 mii_read(struct local *l, int phy, int reg) 387 { 388 int v; 389 390 CSR_WRITE_1(l, EPAR, phy << 6 | reg); 391 CSR_WRITE_1(l, EPCR, EP_EPOS | EP_ERPRR); 392 do { 393 v = CSR_READ_1(l, EPCR); 394 } while (v & EP_ERRE); 395 CSR_WRITE_1(l, EPCR, 0); 396 v = (CSR_READ_1(l, EPDRH) << 8) | CSR_READ_1(l, EPDRL); 397 return v; 398 } 399 400 static void 401 mii_write(struct local *l, int phy, int reg, int data) 402 { 403 int v; 404 405 CSR_WRITE_1(l, EPAR, phy << 6 | reg); 406 CSR_WRITE_1(l, EPDRL, data); 407 CSR_WRITE_1(l, EPDRH, data >> 8); 408 CSR_WRITE_1(l, EPCR, EP_EPOS | EP_ERPRW); 409 do { 410 v = CSR_READ_1(l, EPCR); 411 } while (v & EP_ERRE); 412 CSR_WRITE_1(l, EPCR, 0); 413 } 414 415 #define MII_BMCR 0x00 /* Basic mode control register (rw) */ 416 #define BMCR_RESET 0x8000 /* reset */ 417 #define BMCR_AUTOEN 0x1000 /* autonegotiation enable */ 418 #define BMCR_ISO 0x0400 /* isolate */ 419 #define BMCR_STARTNEG 0x0200 /* restart autonegotiation */ 420 #define MII_BMSR 0x01 /* Basic mode status register (ro) */ 421 #define BMSR_ACOMP 0x0020 /* Autonegotiation complete */ 422 #define BMSR_LINK 0x0004 /* Link status */ 423 #define MII_ANAR 0x04 /* Autonegotiation advertisement (rw) */ 424 #define ANAR_FC 0x0400 /* local device supports PAUSE */ 425 #define ANAR_TX_FD 0x0100 /* local device supports 100bTx FD */ 426 #define ANAR_TX 0x0080 /* local device supports 100bTx */ 427 #define ANAR_10_FD 0x0040 /* local device supports 10bT FD */ 428 #define ANAR_10 0x0020 /* local device supports 10bT */ 429 #define ANAR_CSMA 0x0001 /* protocol selector CSMA/CD */ 430 #define MII_ANLPAR 0x05 /* Autonegotiation lnk partner abilities (rw) */ 431 432 static void 433 mii_dealan(struct local *l, unsigned int timo) 434 { 435 unsigned int bound; 436 437 mii_write(l, l->phy, MII_ANAR, ANAR_TX_FD | ANAR_TX | ANAR_10_FD | 438 ANAR_10 | ANAR_CSMA | ANAR_FC); 439 mii_write(l, l->phy, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 440 l->anlpar = 0; 441 bound = getsecs() + timo; 442 do { 443 l->bmsr = mii_read(l, l->phy, MII_BMSR) | 444 mii_read(l, l->phy, MII_BMSR); /* read twice */ 445 if ((l->bmsr & BMSR_LINK) && (l->bmsr & BMSR_ACOMP)) { 446 l->anlpar = mii_read(l, l->phy, MII_ANLPAR); 447 break; 448 } 449 usleep(10 * 1000); 450 } while (getsecs() < bound); 451 return; 452 } 453