1 /* $NetBSD: tlp.c,v 1.3 2007/10/31 13:30:46 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 2007 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 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/socket.h> 41 42 #include <netinet/in.h> 43 #include <netinet/in_systm.h> 44 45 #include <lib/libsa/stand.h> 46 #include <lib/libsa/net.h> 47 48 #include <mips/cpuregs.h> 49 50 #include "boot.h" 51 52 /* 53 * - little endian access for CSR register. 54 * - assume KSEG0 on vtophys() translation. 55 * - PIPT writeback cache aware. 56 */ 57 #define CSR_WRITE(l, r, v) \ 58 do { \ 59 *(volatile uint32_t *)((l)->csr + (r)) = (v); \ 60 } while (0) 61 #define CSR_READ(l, r) (*(volatile uint32_t *)((l)->csr + (r))) 62 #define VTOPHYS(va) MIPS_KSEG0_TO_PHYS(va) 63 #define wb(adr, siz) pdcache_wb((uint32_t)(adr), (u_int)(siz)) 64 #define wbinv(adr, siz) pdcache_wbinv((uint32_t)(adr), (u_int)(siz)) 65 #define inv(adr, siz) pdcache_inv((uint32_t)(adr), (u_int)(siz)) 66 #define DELAY(n) delay(n) 67 #define ALLOC(T, A) (T *)((uint32_t)alloc(sizeof(T) + (A)) & ~((A) - 1)) 68 69 #define T0_OWN (1U<<31) /* desc is ready to tx */ 70 #define T0_ES (1U<<15) /* Tx error summary */ 71 #define T1_LS (1U<<30) /* last segment */ 72 #define T1_FS (1U<<29) /* first segment */ 73 #define T1_SET (1U<<27) /* "setup packet" */ 74 #define T1_TER (1U<<25) /* end of ring mark */ 75 #define T1_TBS_MASK 0x7ff /* segment size 10:0 */ 76 #define R0_OWN (1U<<31) /* desc is empty */ 77 #define R0_FS (1U<<30) /* first desc of frame */ 78 #define R0_LS (1U<<8) /* last desc of frame */ 79 #define R0_ES (1U<<15) /* Rx error summary */ 80 #define R1_RCH (1U<<24) /* Second address chained */ 81 #define R1_RER (1U<<25) /* end of ring mark */ 82 #define R0_FL_MASK 0x3fff0000 /* frame length 29:16 */ 83 #define R1_RBS_MASK 0x7ff /* segment size 10:0 */ 84 85 #define DESCSIZE 16 86 struct desc { 87 volatile uint32_t xd0, xd1, xd2, xd3; 88 #if CACHELINESIZE > DESCSIZE 89 uint8_t pad[CACHELINESIZE - DESCSIZE]; 90 #endif 91 }; 92 93 #define TLP_BMR 0x000 /* 0: bus mode */ 94 #define BMR_RST (1U<< 0) /* software reset */ 95 #define TLP_TPD 0x008 /* 1: instruct Tx to start */ 96 #define TPD_POLL (1U<< 0) /* transmit poll demand */ 97 #define TLP_RPD 0x010 /* 2: instruct Rx to start */ 98 #define RPD_POLL (1U<< 0) /* receive poll demand */ 99 #define TLP_RRBA 0x018 /* 3: Rx descriptor base */ 100 #define TLP_TRBA 0x020 /* 4: Tx descriptor base */ 101 #define TLP_STS 0x028 /* 5: status */ 102 #define STS_TS 0x00700000 /* Tx status */ 103 #define STS_RS 0x000e0000 /* Rx status */ 104 #define TLP_OMR 0x030 /* 6: operation mode */ 105 #define OMR_SDP (1U<<25) /* always ON */ 106 #define OMR_PS (1U<<18) /* port select */ 107 #define OMR_PM (1U<< 6) /* promicuous */ 108 #define OMR_TEN (1U<<13) /* instruct start/stop Tx */ 109 #define OMR_REN (1U<< 1) /* instruct start/stop Rx */ 110 #define OMR_FD (1U<< 9) /* FDX */ 111 #define TLP_IEN 0x38 /* 7: interrupt enable mask */ 112 #define TLP_APROM 0x048 /* 9: SEEPROM and MII management */ 113 #define SROM_RD (1U <<14) /* read operation */ 114 #define SROM_WR (1U <<13) /* write openration */ 115 #define SROM_SR (1U <<11) /* SEEPROM select */ 116 #define TLP_CSR12 0x60 /* SIA status */ 117 118 #define TLP_CSR15 0x78 /* SIA general register */ 119 #define SIAGEN_MD0 (1U<<16) 120 #define SIAGEN_CWE (1U<<28) 121 122 #define FRAMESIZE 1536 123 #define BUFSIZE 2048 124 #define NRXBUF 2 125 #define NEXT_RXBUF(x) (((x) + 1) & (NRXBUF - 1)) 126 127 struct local { 128 struct desc TxD; 129 struct desc RxD[NRXBUF]; 130 uint8_t txstore[BUFSIZE]; 131 uint8_t rxstore[NRXBUF][BUFSIZE]; 132 uint32_t csr, omr; 133 u_int rx; 134 u_int sromsft; 135 u_int phy; 136 uint32_t bmsr, anlpar; 137 }; 138 139 #define COBALT_TLP0_BASE 0x10100000 140 #define SROM_MAC_OFFSET 0 141 142 static void size_srom(struct local *); 143 static u_int read_srom(struct local *, int); 144 #if 0 145 static u_int tlp_mii_read(struct local *, int, int); 146 static void tlp_mii_write(struct local *, int, int, int); 147 static void mii_initphy(struct local *); 148 #endif 149 150 void * 151 tlp_init(void *cookie) 152 { 153 uint32_t val; 154 struct local *l; 155 struct desc *TxD, *RxD; 156 uint8_t *en; 157 int i; 158 159 l = ALLOC(struct local, CACHELINESIZE); 160 memset(l, 0, sizeof(struct local)); 161 162 DPRINTF(("tlp: l = %p, TxD = %p, RxD[0] = %p, RxD[1] = %p\n", 163 l, &l->TxD, &l->RxD[0], &l->RxD[1])); 164 DPRINTF(("tlp: txstore = %p, rxstore[0] = %p, rxstore[1] = %p\n", 165 l->txstore, l->rxstore[0], l->rxstore[1])); 166 167 #if 0 168 /* XXX assume tlp0 at pci0 dev 7 function 0 */ 169 tag = (0 << 16) | ( 7 << 11) | (0 << 8); 170 /* memory map is not initialized by the firmware on cobalt */ 171 l->csr = MIPS_PHYS_TO_KSEG1(pcicfgread(tag, 0x10) & 0xfffffffc); 172 DPRINTF(("%s: CSR = 0x%x\n", __func__, l->csr)); 173 #else 174 l->csr = MIPS_PHYS_TO_KSEG1(COBALT_TLP0_BASE); 175 #endif 176 177 val = CSR_READ(l, TLP_BMR); 178 CSR_WRITE(l, TLP_BMR, val | BMR_RST); 179 DELAY(1000); 180 CSR_WRITE(l, TLP_BMR, val); 181 DELAY(1000); 182 (void)CSR_READ(l, TLP_BMR); 183 184 l->omr = OMR_PS | OMR_SDP; 185 CSR_WRITE(l, TLP_OMR, l->omr); 186 CSR_WRITE(l, TLP_STS, ~0); 187 CSR_WRITE(l, TLP_IEN, 0); 188 189 #if 0 190 mii_initphy(l); 191 #endif 192 size_srom(l); 193 194 en = cookie; 195 /* MAC address is stored at offset 0 in SROM on cobalt */ 196 val = read_srom(l, SROM_MAC_OFFSET / 2 + 0); 197 en[0] = val; 198 en[1] = val >> 8; 199 val = read_srom(l, SROM_MAC_OFFSET / 2 + 1); 200 en[2] = val; 201 en[3] = val >> 8; 202 val = read_srom(l, SROM_MAC_OFFSET / 2 + 2); 203 en[4] = val; 204 en[5] = val >> 8; 205 206 DPRINTF(("tlp: MAC address %x:%x:%x:%x:%x:%x\n", 207 en[0], en[1], en[2], en[3], en[4], en[5])); 208 209 RxD = &l->RxD[0]; 210 for (i = 0; i < NRXBUF; i++) { 211 RxD[i].xd3 = htole32(VTOPHYS(&RxD[NEXT_RXBUF(i)])); 212 RxD[i].xd2 = htole32(VTOPHYS(l->rxstore[i])); 213 RxD[i].xd1 = htole32(R1_RCH|FRAMESIZE); 214 RxD[i].xd0 = htole32(R0_OWN); 215 } 216 CSR_WRITE(l, TLP_RRBA, VTOPHYS(RxD)); 217 218 /* "setup packet" to have own station address */ 219 TxD = &l->TxD; 220 TxD->xd3 = htole32(VTOPHYS(TxD)); 221 TxD->xd2 = htole32(VTOPHYS(l->txstore)); 222 TxD->xd1 = htole32(T1_SET | T1_TER); 223 TxD->xd0 = htole32(0); 224 CSR_WRITE(l, TLP_TRBA, VTOPHYS(TxD)); 225 226 memset(l->txstore, 0, FRAMESIZE); 227 228 /* make sure the entire descriptors transfered to memory */ 229 wbinv(l, sizeof(struct local)); 230 231 l->rx = 0; 232 l->omr |= OMR_FD | OMR_TEN | OMR_REN; 233 234 #if 1 235 /* reset PHY (cobalt quirk from if_tlp_pci.c) */ 236 CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE | SIAGEN_MD0); 237 DELAY(10); 238 CSR_WRITE(l, TLP_CSR15, SIAGEN_CWE); 239 DELAY(10); 240 #endif 241 242 /* start Tx/Rx */ 243 CSR_WRITE(l, TLP_OMR, l->omr); 244 #if 0 245 CSR_WRITE(l, TLP_TPD, TPD_POLL); 246 #endif 247 CSR_WRITE(l, TLP_RPD, RPD_POLL); 248 249 return l; 250 } 251 252 int 253 tlp_send(void *dev, char *buf, u_int len) 254 { 255 struct local *l = dev; 256 struct desc *TxD; 257 u_int loop; 258 259 #if 1 260 wb(buf, len); 261 TxD = &l->TxD; 262 TxD->xd3 = htole32(VTOPHYS(TxD)); 263 TxD->xd2 = htole32(VTOPHYS(buf)); 264 TxD->xd1 = htole32(T1_FS | T1_LS | T1_TER | (len & T1_TBS_MASK)); 265 #else 266 memcpy(l->txstore, buf, len); 267 wb(l->txstore, len); 268 TxD = &l->TxD; 269 TxD->xd3 = htole32(VTOPHYS(TxD)); 270 TxD->xd2 = htole32(VTOPHYS(l->txstore)); 271 TxD->xd1 = htole32(T1_FS | T1_LS | T1_TER | (len & T1_TBS_MASK)); 272 #endif 273 TxD->xd0 = htole32(T0_OWN); 274 wbinv(TxD, sizeof(struct desc)); 275 CSR_WRITE(l, TLP_TPD, TPD_POLL); 276 loop = 100; 277 do { 278 if ((le32toh(TxD->xd0) & T0_OWN) == 0) 279 goto done; 280 inv(TxD, sizeof(struct desc)); 281 DELAY(10); 282 } while (--loop > 0); 283 printf("xmit failed\n"); 284 return -1; 285 done: 286 return len; 287 } 288 289 int 290 tlp_recv(void *dev, char *buf, u_int maxlen, u_int timo) 291 { 292 struct local *l = dev; 293 struct desc *RxD; 294 u_int bound, len; 295 uint32_t rxstat; 296 uint8_t *ptr; 297 298 bound = 1000 * timo; 299 300 again: 301 RxD = &l->RxD[l->rx]; 302 do { 303 rxstat = le32toh(RxD->xd0); 304 inv(RxD, sizeof(struct desc)); 305 if ((rxstat & R0_OWN) == 0) 306 goto gotone; 307 DELAY(1000); /* 1 milli second */ 308 } while (--bound > 0); 309 errno = 0; 310 CSR_WRITE(l, TLP_RPD, RPD_POLL); 311 return -1; 312 gotone: 313 if (rxstat & R0_ES) { 314 RxD->xd0 = htole32(R0_OWN); 315 wbinv(RxD, sizeof(struct desc)); 316 l->rx = NEXT_RXBUF(l->rx); 317 CSR_WRITE(l, TLP_RPD, RPD_POLL); 318 goto again; 319 } 320 /* good frame */ 321 len = ((rxstat & R0_FL_MASK) >> 16) - 4; /* HASFCS */ 322 if (len > maxlen) 323 len = maxlen; 324 ptr = l->rxstore[l->rx]; 325 memcpy(buf, ptr, len); 326 inv(ptr, FRAMESIZE); 327 RxD->xd0 = htole32(R0_OWN); 328 wbinv(RxD, sizeof(struct desc)); 329 l->rx = NEXT_RXBUF(l->rx); 330 CSR_WRITE(l, TLP_OMR, l->omr); /* necessary? */ 331 return len; 332 } 333 334 static void 335 size_srom(struct local *l) 336 { 337 /* determine 8/6 bit addressing SEEPROM */ 338 l->sromsft = 8; 339 l->sromsft = (read_srom(l, 255) & 0x40000) ? 8 : 6; 340 } 341 342 /* 343 * bare SEEPROM access with bitbang'ing 344 */ 345 #define R110 6 /* SEEPROM read op */ 346 #define CS (1U << 0) /* hold chip select */ 347 #define CLK (1U << 1) /* clk bit */ 348 #define D1 (1U << 2) /* bit existence */ 349 #define D0 0 /* bit absence */ 350 #define VV (1U << 3) /* taken 0/1 from SEEPROM */ 351 352 static u_int 353 read_srom(struct local *l, int off) 354 { 355 u_int idx, cnt, ret; 356 uint32_t val, x1, x0, bit; 357 358 idx = off & 0xff; /* A7-A0 */ 359 idx |= R110 << l->sromsft; /* 110 for READ */ 360 361 val = SROM_RD | SROM_SR; 362 CSR_WRITE(l, TLP_APROM, val); 363 val |= CS; /* hold CS */ 364 CSR_WRITE(l, TLP_APROM, val); 365 366 x1 = val | D1; /* 1 */ 367 x0 = val | D0; /* 0 */ 368 /* instruct R110 op. at off in MSB first order */ 369 for (cnt = (1 << (l->sromsft + 2)); cnt > 0; cnt >>= 1) { 370 bit = (idx & cnt) ? x1 : x0; 371 CSR_WRITE(l, TLP_APROM, bit); 372 DELAY(10); 373 CSR_WRITE(l, TLP_APROM, bit | CLK); 374 DELAY(10); 375 } 376 /* read 16bit quantity in MSB first order */ 377 ret = 0; 378 for (cnt = 16; cnt > 0; cnt--) { 379 CSR_WRITE(l, TLP_APROM, val); 380 DELAY(10); 381 CSR_WRITE(l, TLP_APROM, val | CLK); 382 DELAY(10); 383 ret = (ret << 1) | !!(CSR_READ(l, TLP_APROM) & VV); 384 } 385 val &= ~CS; /* turn off chip select */ 386 CSR_WRITE(l, TLP_APROM, val); 387 388 return ret; 389 } 390 391 #if 0 392 393 static u_int 394 tlp_mii_read(struct local *l, int phy, int reg) 395 { 396 /* later ... */ 397 return 0; 398 } 399 400 static void 401 tlp_mii_write(struct local *l, int phy, int reg, int val) 402 { 403 /* later ... */ 404 } 405 406 #define MII_BMCR 0x00 /* Basic mode control register (rw) */ 407 #define BMCR_RESET 0x8000 /* reset */ 408 #define BMCR_AUTOEN 0x1000 /* autonegotiation enable */ 409 #define BMCR_ISO 0x0400 /* isolate */ 410 #define BMCR_STARTNEG 0x0200 /* restart autonegotiation */ 411 #define MII_BMSR 0x01 /* Basic mode status register (ro) */ 412 413 static void 414 mii_initphy(struct local *l) 415 { 416 int phy, bound; 417 uint32_t ctl, sts; 418 419 for (phy = 0; phy < 32; phy++) { 420 ctl = tlp_mii_read(l, phy, MII_BMCR); 421 sts = tlp_mii_read(l, phy, MII_BMSR); 422 if (ctl != 0xffff && sts != 0xffff) 423 goto found; 424 } 425 printf("MII: no PHY found\n"); 426 return; 427 found: 428 ctl = tlp_mii_read(l, phy, MII_BMCR); 429 tlp_mii_write(l, phy, MII_BMCR, ctl | BMCR_RESET); 430 bound = 100; 431 do { 432 DELAY(10); 433 ctl = tlp_mii_read(l, phy, MII_BMCR); 434 if (ctl == 0xffff) { 435 printf("MII: PHY %d has died after reset\n", phy); 436 return; 437 } 438 } while (bound-- > 0 && (ctl & BMCR_RESET)); 439 if (bound == 0) { 440 printf("PHY %d reset failed\n", phy); 441 } 442 ctl &= ~BMCR_ISO; 443 tlp_mii_write(l, phy, MII_BMCR, ctl); 444 sts = tlp_mii_read(l, phy, MII_BMSR) | 445 tlp_mii_read(l, phy, MII_BMSR); /* read twice */ 446 l->phy = phy; 447 l->bmsr = sts; 448 } 449 450 static void 451 mii_dealan(struct local *, u_int timo) 452 { 453 uint32_t anar; 454 u_int bound; 455 456 anar = ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA; 457 tlp_mii_write(l, l->phy, MII_ANAR, anar); 458 tlp_mii_write(l, l->phy, MII_BMCR, BMCR_AUTOEN | BMCR_STARTNEG); 459 l->anlpar = 0; 460 bound = getsecs() + timo; 461 do { 462 l->bmsr = tlp_mii_read(l, l->phy, MII_BMSR) | 463 tlp_mii_read(l, l->phy, MII_BMSR); /* read twice */ 464 if ((l->bmsr & BMSR_LINK) && (l->bmsr & BMSR_ACOMP)) { 465 l->anlpar = tlp_mii_read(l, l->phy, MII_ANLPAR); 466 break; 467 } 468 DELAY(10 * 1000); 469 } while (getsecs() < bound); 470 return; 471 } 472 #endif 473