1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Faraday 10/100Mbps Ethernet Controller 4 * 5 * (C) Copyright 2013 Faraday Technology 6 * Dante Su <dantesu@faraday-tech.com> 7 */ 8 9 #include <common.h> 10 #include <command.h> 11 #include <malloc.h> 12 #include <net.h> 13 #include <linux/errno.h> 14 #include <asm/io.h> 15 #include <asm/dma-mapping.h> 16 17 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 18 #include <miiphy.h> 19 #endif 20 21 #include "ftmac110.h" 22 23 #define CFG_RXDES_NUM 8 24 #define CFG_TXDES_NUM 2 25 #define CFG_XBUF_SIZE 1536 26 27 #define CFG_MDIORD_TIMEOUT (CONFIG_SYS_HZ >> 1) /* 500 ms */ 28 #define CFG_MDIOWR_TIMEOUT (CONFIG_SYS_HZ >> 1) /* 500 ms */ 29 #define CFG_LINKUP_TIMEOUT (CONFIG_SYS_HZ << 2) /* 4 sec */ 30 31 /* 32 * FTMAC110 DMA design issue 33 * 34 * Its DMA engine has a weird restriction that its Rx DMA engine 35 * accepts only 16-bits aligned address, 32-bits aligned is not 36 * acceptable. However this restriction does not apply to Tx DMA. 37 * 38 * Conclusion: 39 * (1) Tx DMA Buffer Address: 40 * 1 bytes aligned: Invalid 41 * 2 bytes aligned: O.K 42 * 4 bytes aligned: O.K (-> u-boot ZeroCopy is possible) 43 * (2) Rx DMA Buffer Address: 44 * 1 bytes aligned: Invalid 45 * 2 bytes aligned: O.K 46 * 4 bytes aligned: Invalid 47 */ 48 49 struct ftmac110_chip { 50 void __iomem *regs; 51 uint32_t imr; 52 uint32_t maccr; 53 uint32_t lnkup; 54 uint32_t phy_addr; 55 56 struct ftmac110_desc *rxd; 57 ulong rxd_dma; 58 uint32_t rxd_idx; 59 60 struct ftmac110_desc *txd; 61 ulong txd_dma; 62 uint32_t txd_idx; 63 }; 64 65 static int ftmac110_reset(struct eth_device *dev); 66 67 static uint16_t mdio_read(struct eth_device *dev, 68 uint8_t phyaddr, uint8_t phyreg) 69 { 70 struct ftmac110_chip *chip = dev->priv; 71 struct ftmac110_regs *regs = chip->regs; 72 uint32_t tmp, ts; 73 uint16_t ret = 0xffff; 74 75 tmp = PHYCR_READ 76 | (phyaddr << PHYCR_ADDR_SHIFT) 77 | (phyreg << PHYCR_REG_SHIFT); 78 79 writel(tmp, ®s->phycr); 80 81 for (ts = get_timer(0); get_timer(ts) < CFG_MDIORD_TIMEOUT; ) { 82 tmp = readl(®s->phycr); 83 if (tmp & PHYCR_READ) 84 continue; 85 break; 86 } 87 88 if (tmp & PHYCR_READ) 89 printf("ftmac110: mdio read timeout\n"); 90 else 91 ret = (uint16_t)(tmp & 0xffff); 92 93 return ret; 94 } 95 96 static void mdio_write(struct eth_device *dev, 97 uint8_t phyaddr, uint8_t phyreg, uint16_t phydata) 98 { 99 struct ftmac110_chip *chip = dev->priv; 100 struct ftmac110_regs *regs = chip->regs; 101 uint32_t tmp, ts; 102 103 tmp = PHYCR_WRITE 104 | (phyaddr << PHYCR_ADDR_SHIFT) 105 | (phyreg << PHYCR_REG_SHIFT); 106 107 writel(phydata, ®s->phydr); 108 writel(tmp, ®s->phycr); 109 110 for (ts = get_timer(0); get_timer(ts) < CFG_MDIOWR_TIMEOUT; ) { 111 if (readl(®s->phycr) & PHYCR_WRITE) 112 continue; 113 break; 114 } 115 116 if (readl(®s->phycr) & PHYCR_WRITE) 117 printf("ftmac110: mdio write timeout\n"); 118 } 119 120 static uint32_t ftmac110_phyqry(struct eth_device *dev) 121 { 122 ulong ts; 123 uint32_t maccr; 124 uint16_t pa, tmp, bmsr, bmcr; 125 struct ftmac110_chip *chip = dev->priv; 126 127 /* Default = 100Mbps Full */ 128 maccr = MACCR_100M | MACCR_FD; 129 130 /* 1. find the phy device */ 131 for (pa = 0; pa < 32; ++pa) { 132 tmp = mdio_read(dev, pa, MII_PHYSID1); 133 if (tmp == 0xFFFF || tmp == 0x0000) 134 continue; 135 chip->phy_addr = pa; 136 break; 137 } 138 if (pa >= 32) { 139 puts("ftmac110: phy device not found!\n"); 140 goto exit; 141 } 142 143 /* 2. wait until link-up & auto-negotiation complete */ 144 chip->lnkup = 0; 145 bmcr = mdio_read(dev, chip->phy_addr, MII_BMCR); 146 ts = get_timer(0); 147 do { 148 bmsr = mdio_read(dev, chip->phy_addr, MII_BMSR); 149 chip->lnkup = (bmsr & BMSR_LSTATUS) ? 1 : 0; 150 if (!chip->lnkup) 151 continue; 152 if (!(bmcr & BMCR_ANENABLE) || (bmsr & BMSR_ANEGCOMPLETE)) 153 break; 154 } while (get_timer(ts) < CFG_LINKUP_TIMEOUT); 155 if (!chip->lnkup) { 156 puts("ftmac110: link down\n"); 157 goto exit; 158 } 159 if (!(bmcr & BMCR_ANENABLE)) 160 puts("ftmac110: auto negotiation disabled\n"); 161 else if (!(bmsr & BMSR_ANEGCOMPLETE)) 162 puts("ftmac110: auto negotiation timeout\n"); 163 164 /* 3. derive MACCR */ 165 if ((bmcr & BMCR_ANENABLE) && (bmsr & BMSR_ANEGCOMPLETE)) { 166 tmp = mdio_read(dev, chip->phy_addr, MII_ADVERTISE); 167 tmp &= mdio_read(dev, chip->phy_addr, MII_LPA); 168 if (tmp & LPA_100FULL) /* 100Mbps full-duplex */ 169 maccr = MACCR_100M | MACCR_FD; 170 else if (tmp & LPA_100HALF) /* 100Mbps half-duplex */ 171 maccr = MACCR_100M; 172 else if (tmp & LPA_10FULL) /* 10Mbps full-duplex */ 173 maccr = MACCR_FD; 174 else if (tmp & LPA_10HALF) /* 10Mbps half-duplex */ 175 maccr = 0; 176 } else { 177 if (bmcr & BMCR_SPEED100) 178 maccr = MACCR_100M; 179 else 180 maccr = 0; 181 if (bmcr & BMCR_FULLDPLX) 182 maccr |= MACCR_FD; 183 } 184 185 exit: 186 printf("ftmac110: %d Mbps, %s\n", 187 (maccr & MACCR_100M) ? 100 : 10, 188 (maccr & MACCR_FD) ? "Full" : "half"); 189 return maccr; 190 } 191 192 static int ftmac110_reset(struct eth_device *dev) 193 { 194 uint8_t *a; 195 uint32_t i, maccr; 196 struct ftmac110_chip *chip = dev->priv; 197 struct ftmac110_regs *regs = chip->regs; 198 199 /* 1. MAC reset */ 200 writel(MACCR_RESET, ®s->maccr); 201 for (i = get_timer(0); get_timer(i) < 1000; ) { 202 if (readl(®s->maccr) & MACCR_RESET) 203 continue; 204 break; 205 } 206 if (readl(®s->maccr) & MACCR_RESET) { 207 printf("ftmac110: reset failed\n"); 208 return -ENXIO; 209 } 210 211 /* 1-1. Init tx ring */ 212 for (i = 0; i < CFG_TXDES_NUM; ++i) { 213 /* owned by SW */ 214 chip->txd[i].ctrl &= cpu_to_le64(FTMAC110_TXD_CLRMASK); 215 } 216 chip->txd_idx = 0; 217 218 /* 1-2. Init rx ring */ 219 for (i = 0; i < CFG_RXDES_NUM; ++i) { 220 /* owned by HW */ 221 chip->rxd[i].ctrl &= cpu_to_le64(FTMAC110_RXD_CLRMASK); 222 chip->rxd[i].ctrl |= cpu_to_le64(FTMAC110_RXD_OWNER); 223 } 224 chip->rxd_idx = 0; 225 226 /* 2. PHY status query */ 227 maccr = ftmac110_phyqry(dev); 228 229 /* 3. Fix up the MACCR value */ 230 chip->maccr = maccr | MACCR_CRCAPD | MACCR_RXALL | MACCR_RXRUNT 231 | MACCR_RXEN | MACCR_TXEN | MACCR_RXDMAEN | MACCR_TXDMAEN; 232 233 /* 4. MAC address setup */ 234 a = dev->enetaddr; 235 writel(a[1] | (a[0] << 8), ®s->mac[0]); 236 writel(a[5] | (a[4] << 8) | (a[3] << 16) 237 | (a[2] << 24), ®s->mac[1]); 238 239 /* 5. MAC registers setup */ 240 writel(chip->rxd_dma, ®s->rxba); 241 writel(chip->txd_dma, ®s->txba); 242 /* interrupt at each tx/rx */ 243 writel(ITC_DEFAULT, ®s->itc); 244 /* no tx pool, rx poll = 1 normal cycle */ 245 writel(APTC_DEFAULT, ®s->aptc); 246 /* rx threshold = [6/8 fifo, 2/8 fifo] */ 247 writel(DBLAC_DEFAULT, ®s->dblac); 248 /* disable & clear all interrupt status */ 249 chip->imr = 0; 250 writel(ISR_ALL, ®s->isr); 251 writel(chip->imr, ®s->imr); 252 /* enable mac */ 253 writel(chip->maccr, ®s->maccr); 254 255 return 0; 256 } 257 258 static int ftmac110_probe(struct eth_device *dev, bd_t *bis) 259 { 260 debug("ftmac110: probe\n"); 261 262 if (ftmac110_reset(dev)) 263 return -1; 264 265 return 0; 266 } 267 268 static void ftmac110_halt(struct eth_device *dev) 269 { 270 struct ftmac110_chip *chip = dev->priv; 271 struct ftmac110_regs *regs = chip->regs; 272 273 writel(0, ®s->imr); 274 writel(0, ®s->maccr); 275 276 debug("ftmac110: halt\n"); 277 } 278 279 static int ftmac110_send(struct eth_device *dev, void *pkt, int len) 280 { 281 struct ftmac110_chip *chip = dev->priv; 282 struct ftmac110_regs *regs = chip->regs; 283 struct ftmac110_desc *txd; 284 uint64_t ctrl; 285 286 if (!chip->lnkup) 287 return 0; 288 289 if (len <= 0 || len > CFG_XBUF_SIZE) { 290 printf("ftmac110: bad tx pkt len(%d)\n", len); 291 return 0; 292 } 293 294 len = max(60, len); 295 296 txd = &chip->txd[chip->txd_idx]; 297 ctrl = le64_to_cpu(txd->ctrl); 298 if (ctrl & FTMAC110_TXD_OWNER) { 299 /* kick-off Tx DMA */ 300 writel(0xffffffff, ®s->txpd); 301 printf("ftmac110: out of txd\n"); 302 return 0; 303 } 304 305 memcpy(txd->vbuf, (void *)pkt, len); 306 dma_map_single(txd->vbuf, len, DMA_TO_DEVICE); 307 308 /* clear control bits */ 309 ctrl &= FTMAC110_TXD_CLRMASK; 310 /* set len, fts and lts */ 311 ctrl |= FTMAC110_TXD_LEN(len) | FTMAC110_TXD_FTS | FTMAC110_TXD_LTS; 312 /* set owner bit */ 313 ctrl |= FTMAC110_TXD_OWNER; 314 /* write back to descriptor */ 315 txd->ctrl = cpu_to_le64(ctrl); 316 317 /* kick-off Tx DMA */ 318 writel(0xffffffff, ®s->txpd); 319 320 chip->txd_idx = (chip->txd_idx + 1) % CFG_TXDES_NUM; 321 322 return len; 323 } 324 325 static int ftmac110_recv(struct eth_device *dev) 326 { 327 struct ftmac110_chip *chip = dev->priv; 328 struct ftmac110_desc *rxd; 329 uint32_t len, rlen = 0; 330 uint64_t ctrl; 331 uint8_t *buf; 332 333 if (!chip->lnkup) 334 return 0; 335 336 do { 337 rxd = &chip->rxd[chip->rxd_idx]; 338 ctrl = le64_to_cpu(rxd->ctrl); 339 if (ctrl & FTMAC110_RXD_OWNER) 340 break; 341 342 len = (uint32_t)FTMAC110_RXD_LEN(ctrl); 343 buf = rxd->vbuf; 344 345 if (ctrl & FTMAC110_RXD_ERRMASK) { 346 printf("ftmac110: rx error\n"); 347 } else { 348 dma_map_single(buf, len, DMA_FROM_DEVICE); 349 net_process_received_packet(buf, len); 350 rlen += len; 351 } 352 353 /* owned by hardware */ 354 ctrl &= FTMAC110_RXD_CLRMASK; 355 ctrl |= FTMAC110_RXD_OWNER; 356 rxd->ctrl |= cpu_to_le64(ctrl); 357 358 chip->rxd_idx = (chip->rxd_idx + 1) % CFG_RXDES_NUM; 359 } while (0); 360 361 return rlen; 362 } 363 364 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 365 366 static int ftmac110_mdio_read(struct mii_dev *bus, int addr, int devad, 367 int reg) 368 { 369 uint16_t value = 0; 370 int ret = 0; 371 struct eth_device *dev; 372 373 dev = eth_get_dev_by_name(bus->name); 374 if (dev == NULL) { 375 printf("%s: no such device\n", bus->name); 376 ret = -1; 377 } else { 378 value = mdio_read(dev, addr, reg); 379 } 380 381 if (ret < 0) 382 return ret; 383 return value; 384 } 385 386 static int ftmac110_mdio_write(struct mii_dev *bus, int addr, int devad, 387 int reg, u16 value) 388 { 389 int ret = 0; 390 struct eth_device *dev; 391 392 dev = eth_get_dev_by_name(bus->name); 393 if (dev == NULL) { 394 printf("%s: no such device\n", bus->name); 395 ret = -1; 396 } else { 397 mdio_write(dev, addr, reg, value); 398 } 399 400 return ret; 401 } 402 403 #endif /* #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) */ 404 405 int ftmac110_initialize(bd_t *bis) 406 { 407 int i, card_nr = 0; 408 struct eth_device *dev; 409 struct ftmac110_chip *chip; 410 411 dev = malloc(sizeof(*dev) + sizeof(*chip)); 412 if (dev == NULL) { 413 panic("ftmac110: out of memory 1\n"); 414 return -1; 415 } 416 chip = (struct ftmac110_chip *)(dev + 1); 417 memset(dev, 0, sizeof(*dev) + sizeof(*chip)); 418 419 sprintf(dev->name, "FTMAC110#%d", card_nr); 420 421 dev->iobase = CONFIG_FTMAC110_BASE; 422 chip->regs = (void __iomem *)dev->iobase; 423 dev->priv = chip; 424 dev->init = ftmac110_probe; 425 dev->halt = ftmac110_halt; 426 dev->send = ftmac110_send; 427 dev->recv = ftmac110_recv; 428 429 /* allocate tx descriptors (it must be 16 bytes aligned) */ 430 chip->txd = dma_alloc_coherent( 431 sizeof(struct ftmac110_desc) * CFG_TXDES_NUM, &chip->txd_dma); 432 if (!chip->txd) 433 panic("ftmac110: out of memory 3\n"); 434 memset(chip->txd, 0, 435 sizeof(struct ftmac110_desc) * CFG_TXDES_NUM); 436 for (i = 0; i < CFG_TXDES_NUM; ++i) { 437 void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE); 438 439 if (!va) 440 panic("ftmac110: out of memory 4\n"); 441 chip->txd[i].vbuf = va; 442 chip->txd[i].pbuf = cpu_to_le32(virt_to_phys(va)); 443 chip->txd[i].ctrl = 0; /* owned by SW */ 444 } 445 chip->txd[i - 1].ctrl |= cpu_to_le64(FTMAC110_TXD_END); 446 chip->txd_idx = 0; 447 448 /* allocate rx descriptors (it must be 16 bytes aligned) */ 449 chip->rxd = dma_alloc_coherent( 450 sizeof(struct ftmac110_desc) * CFG_RXDES_NUM, &chip->rxd_dma); 451 if (!chip->rxd) 452 panic("ftmac110: out of memory 4\n"); 453 memset((void *)chip->rxd, 0, 454 sizeof(struct ftmac110_desc) * CFG_RXDES_NUM); 455 for (i = 0; i < CFG_RXDES_NUM; ++i) { 456 void *va = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE + 2); 457 458 if (!va) 459 panic("ftmac110: out of memory 5\n"); 460 /* it needs to be exactly 2 bytes aligned */ 461 va = ((uint8_t *)va + 2); 462 chip->rxd[i].vbuf = va; 463 chip->rxd[i].pbuf = cpu_to_le32(virt_to_phys(va)); 464 chip->rxd[i].ctrl = cpu_to_le64(FTMAC110_RXD_OWNER 465 | FTMAC110_RXD_BUFSZ(CFG_XBUF_SIZE)); 466 } 467 chip->rxd[i - 1].ctrl |= cpu_to_le64(FTMAC110_RXD_END); 468 chip->rxd_idx = 0; 469 470 eth_register(dev); 471 472 #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) 473 int retval; 474 struct mii_dev *mdiodev = mdio_alloc(); 475 if (!mdiodev) 476 return -ENOMEM; 477 strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN); 478 mdiodev->read = ftmac110_mdio_read; 479 mdiodev->write = ftmac110_mdio_write; 480 481 retval = mdio_register(mdiodev); 482 if (retval < 0) 483 return retval; 484 #endif 485 486 card_nr++; 487 488 return card_nr; 489 } 490