1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Faraday FTMAC100 Ethernet 4 * 5 * (C) Copyright 2009 Faraday Technology 6 * Po-Yu Chuang <ratbert@faraday-tech.com> 7 */ 8 9 #include <config.h> 10 #include <common.h> 11 #include <malloc.h> 12 #include <net.h> 13 #include <linux/io.h> 14 15 #include "ftmac100.h" 16 #ifdef CONFIG_DM_ETH 17 #include <dm.h> 18 DECLARE_GLOBAL_DATA_PTR; 19 #endif 20 #define ETH_ZLEN 60 21 22 struct ftmac100_data { 23 struct ftmac100_txdes txdes[1]; 24 struct ftmac100_rxdes rxdes[PKTBUFSRX]; 25 int rx_index; 26 const char *name; 27 phys_addr_t iobase; 28 }; 29 30 /* 31 * Reset MAC 32 */ 33 static void ftmac100_reset(struct ftmac100_data *priv) 34 { 35 struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase; 36 37 debug ("%s()\n", __func__); 38 39 writel (FTMAC100_MACCR_SW_RST, &ftmac100->maccr); 40 41 while (readl (&ftmac100->maccr) & FTMAC100_MACCR_SW_RST) 42 mdelay(1); 43 /* 44 * When soft reset complete, write mac address immediately maybe fail somehow 45 * Wait for a while can avoid this problem 46 */ 47 mdelay(1); 48 } 49 50 /* 51 * Set MAC address 52 */ 53 static void ftmac100_set_mac(struct ftmac100_data *priv , 54 const unsigned char *mac) 55 { 56 struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase; 57 unsigned int maddr = mac[0] << 8 | mac[1]; 58 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5]; 59 60 debug ("%s(%x %x)\n", __func__, maddr, laddr); 61 62 writel (maddr, &ftmac100->mac_madr); 63 writel (laddr, &ftmac100->mac_ladr); 64 } 65 66 /* 67 * Disable MAC 68 */ 69 static void _ftmac100_halt(struct ftmac100_data *priv) 70 { 71 struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase; 72 debug ("%s()\n", __func__); 73 writel (0, &ftmac100->maccr); 74 } 75 76 /* 77 * Initialize MAC 78 */ 79 static int _ftmac100_init(struct ftmac100_data *priv, unsigned char enetaddr[6]) 80 { 81 struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase; 82 struct ftmac100_txdes *txdes = priv->txdes; 83 struct ftmac100_rxdes *rxdes = priv->rxdes; 84 unsigned int maccr; 85 int i; 86 debug ("%s()\n", __func__); 87 88 ftmac100_reset(priv); 89 90 /* set the ethernet address */ 91 ftmac100_set_mac(priv, enetaddr); 92 93 94 /* disable all interrupts */ 95 96 writel (0, &ftmac100->imr); 97 98 /* initialize descriptors */ 99 100 priv->rx_index = 0; 101 102 txdes[0].txdes1 = FTMAC100_TXDES1_EDOTR; 103 rxdes[PKTBUFSRX - 1].rxdes1 = FTMAC100_RXDES1_EDORR; 104 105 for (i = 0; i < PKTBUFSRX; i++) { 106 /* RXBUF_BADR */ 107 rxdes[i].rxdes2 = (unsigned int)(unsigned long)net_rx_packets[i]; 108 rxdes[i].rxdes1 |= FTMAC100_RXDES1_RXBUF_SIZE (PKTSIZE_ALIGN); 109 rxdes[i].rxdes0 = FTMAC100_RXDES0_RXDMA_OWN; 110 } 111 112 /* transmit ring */ 113 114 writel ((unsigned long)txdes, &ftmac100->txr_badr); 115 116 /* receive ring */ 117 118 writel ((unsigned long)rxdes, &ftmac100->rxr_badr); 119 120 /* poll receive descriptor automatically */ 121 122 writel (FTMAC100_APTC_RXPOLL_CNT (1), &ftmac100->aptc); 123 124 /* enable transmitter, receiver */ 125 126 maccr = FTMAC100_MACCR_XMT_EN | 127 FTMAC100_MACCR_RCV_EN | 128 FTMAC100_MACCR_XDMA_EN | 129 FTMAC100_MACCR_RDMA_EN | 130 FTMAC100_MACCR_CRC_APD | 131 FTMAC100_MACCR_ENRX_IN_HALFTX | 132 FTMAC100_MACCR_RX_RUNT | 133 FTMAC100_MACCR_RX_BROADPKT; 134 135 writel (maccr, &ftmac100->maccr); 136 137 return 0; 138 } 139 140 /* 141 * Free receiving buffer 142 */ 143 static int _ftmac100_free_pkt(struct ftmac100_data *priv) 144 { 145 struct ftmac100_rxdes *curr_des; 146 curr_des = &priv->rxdes[priv->rx_index]; 147 /* release buffer to DMA */ 148 curr_des->rxdes0 |= FTMAC100_RXDES0_RXDMA_OWN; 149 priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX; 150 return 0; 151 } 152 153 /* 154 * Receive a data block via Ethernet 155 */ 156 static int __ftmac100_recv(struct ftmac100_data *priv) 157 { 158 struct ftmac100_rxdes *curr_des; 159 unsigned short rxlen; 160 161 curr_des = &priv->rxdes[priv->rx_index]; 162 if (curr_des->rxdes0 & FTMAC100_RXDES0_RXDMA_OWN) 163 return 0; 164 165 if (curr_des->rxdes0 & (FTMAC100_RXDES0_RX_ERR | 166 FTMAC100_RXDES0_CRC_ERR | 167 FTMAC100_RXDES0_FTL | 168 FTMAC100_RXDES0_RUNT | 169 FTMAC100_RXDES0_RX_ODD_NB)) { 170 return 0; 171 } 172 173 rxlen = FTMAC100_RXDES0_RFL (curr_des->rxdes0); 174 invalidate_dcache_range(curr_des->rxdes2,curr_des->rxdes2+rxlen); 175 debug ("%s(): RX buffer %d, %x received\n", 176 __func__, priv->rx_index, rxlen); 177 178 return rxlen; 179 } 180 181 /* 182 * Send a data block via Ethernet 183 */ 184 static int _ftmac100_send(struct ftmac100_data *priv, void *packet, int length) 185 { 186 struct ftmac100 *ftmac100 = (struct ftmac100 *)priv->iobase; 187 struct ftmac100_txdes *curr_des = priv->txdes; 188 ulong start; 189 190 if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) { 191 debug ("%s(): no TX descriptor available\n", __func__); 192 return -1; 193 } 194 195 debug ("%s(%lx, %x)\n", __func__, (unsigned long)packet, length); 196 197 length = (length < ETH_ZLEN) ? ETH_ZLEN : length; 198 199 /* initiate a transmit sequence */ 200 201 flush_dcache_range((unsigned long)packet,(unsigned long)packet+length); 202 curr_des->txdes2 = (unsigned int)(unsigned long)packet; /* TXBUF_BADR */ 203 204 curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR; 205 curr_des->txdes1 |= FTMAC100_TXDES1_FTS | 206 FTMAC100_TXDES1_LTS | 207 FTMAC100_TXDES1_TXBUF_SIZE (length); 208 209 curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN; 210 211 /* start transmit */ 212 213 writel (1, &ftmac100->txpd); 214 215 /* wait for transfer to succeed */ 216 217 start = get_timer(0); 218 while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) { 219 if (get_timer(start) >= 5) { 220 debug ("%s(): timed out\n", __func__); 221 return -1; 222 } 223 } 224 225 debug ("%s(): packet sent\n", __func__); 226 227 return 0; 228 } 229 230 #ifndef CONFIG_DM_ETH 231 /* 232 * disable transmitter, receiver 233 */ 234 static void ftmac100_halt(struct eth_device *dev) 235 { 236 struct ftmac100_data *priv = dev->priv; 237 return _ftmac100_halt(priv); 238 } 239 240 static int ftmac100_init(struct eth_device *dev, bd_t *bd) 241 { 242 struct ftmac100_data *priv = dev->priv; 243 return _ftmac100_init(priv , dev->enetaddr); 244 } 245 246 static int _ftmac100_recv(struct ftmac100_data *priv) 247 { 248 struct ftmac100_rxdes *curr_des; 249 unsigned short len; 250 curr_des = &priv->rxdes[priv->rx_index]; 251 len = __ftmac100_recv(priv); 252 if (len) { 253 /* pass the packet up to the protocol layers. */ 254 net_process_received_packet((void *)curr_des->rxdes2, len); 255 _ftmac100_free_pkt(priv); 256 } 257 return len ? 1 : 0; 258 } 259 260 /* 261 * Get a data block via Ethernet 262 */ 263 static int ftmac100_recv(struct eth_device *dev) 264 { 265 struct ftmac100_data *priv = dev->priv; 266 return _ftmac100_recv(priv); 267 } 268 269 /* 270 * Send a data block via Ethernet 271 */ 272 static int ftmac100_send(struct eth_device *dev, void *packet, int length) 273 { 274 struct ftmac100_data *priv = dev->priv; 275 return _ftmac100_send(priv , packet , length); 276 } 277 278 int ftmac100_initialize (bd_t *bd) 279 { 280 struct eth_device *dev; 281 struct ftmac100_data *priv; 282 dev = malloc (sizeof *dev); 283 if (!dev) { 284 printf ("%s(): failed to allocate dev\n", __func__); 285 goto out; 286 } 287 /* Transmit and receive descriptors should align to 16 bytes */ 288 priv = memalign (16, sizeof (struct ftmac100_data)); 289 if (!priv) { 290 printf ("%s(): failed to allocate priv\n", __func__); 291 goto free_dev; 292 } 293 memset (dev, 0, sizeof (*dev)); 294 memset (priv, 0, sizeof (*priv)); 295 296 strcpy(dev->name, "FTMAC100"); 297 dev->iobase = CONFIG_FTMAC100_BASE; 298 dev->init = ftmac100_init; 299 dev->halt = ftmac100_halt; 300 dev->send = ftmac100_send; 301 dev->recv = ftmac100_recv; 302 dev->priv = priv; 303 priv->iobase = dev->iobase; 304 eth_register (dev); 305 306 return 1; 307 308 free_dev: 309 free (dev); 310 out: 311 return 0; 312 } 313 #endif 314 315 #ifdef CONFIG_DM_ETH 316 static int ftmac100_start(struct udevice *dev) 317 { 318 struct eth_pdata *plat = dev_get_platdata(dev); 319 struct ftmac100_data *priv = dev_get_priv(dev); 320 321 return _ftmac100_init(priv, plat->enetaddr); 322 } 323 324 static void ftmac100_stop(struct udevice *dev) 325 { 326 struct ftmac100_data *priv = dev_get_priv(dev); 327 _ftmac100_halt(priv); 328 } 329 330 static int ftmac100_send(struct udevice *dev, void *packet, int length) 331 { 332 struct ftmac100_data *priv = dev_get_priv(dev); 333 int ret; 334 ret = _ftmac100_send(priv , packet , length); 335 return ret ? 0 : -ETIMEDOUT; 336 } 337 338 static int ftmac100_recv(struct udevice *dev, int flags, uchar **packetp) 339 { 340 struct ftmac100_data *priv = dev_get_priv(dev); 341 struct ftmac100_rxdes *curr_des; 342 curr_des = &priv->rxdes[priv->rx_index]; 343 int len; 344 len = __ftmac100_recv(priv); 345 if (len) 346 *packetp = (uchar *)(unsigned long)curr_des->rxdes2; 347 348 return len ? len : -EAGAIN; 349 } 350 351 static int ftmac100_free_pkt(struct udevice *dev, uchar *packet, int length) 352 { 353 struct ftmac100_data *priv = dev_get_priv(dev); 354 _ftmac100_free_pkt(priv); 355 return 0; 356 } 357 358 int ftmac100_read_rom_hwaddr(struct udevice *dev) 359 { 360 struct eth_pdata *pdata = dev_get_platdata(dev); 361 eth_env_get_enetaddr("ethaddr", pdata->enetaddr); 362 return 0; 363 } 364 365 static const char *dtbmacaddr(u32 ifno) 366 { 367 int node, len; 368 char enet[16]; 369 const char *mac; 370 const char *path; 371 if (gd->fdt_blob == NULL) { 372 printf("%s: don't have a valid gd->fdt_blob!\n", __func__); 373 return NULL; 374 } 375 node = fdt_path_offset(gd->fdt_blob, "/aliases"); 376 if (node < 0) 377 return NULL; 378 379 sprintf(enet, "ethernet%d", ifno); 380 path = fdt_getprop(gd->fdt_blob, node, enet, NULL); 381 if (!path) { 382 printf("no alias for %s\n", enet); 383 return NULL; 384 } 385 node = fdt_path_offset(gd->fdt_blob, path); 386 mac = fdt_getprop(gd->fdt_blob, node, "mac-address", &len); 387 if (mac && is_valid_ethaddr((u8 *)mac)) 388 return mac; 389 390 return NULL; 391 } 392 393 static int ftmac100_ofdata_to_platdata(struct udevice *dev) 394 { 395 struct ftmac100_data *priv = dev_get_priv(dev); 396 struct eth_pdata *pdata = dev_get_platdata(dev); 397 const char *mac; 398 pdata->iobase = devfdt_get_addr(dev); 399 priv->iobase = pdata->iobase; 400 mac = dtbmacaddr(0); 401 if (mac) 402 memcpy(pdata->enetaddr , mac , 6); 403 404 return 0; 405 } 406 407 static int ftmac100_probe(struct udevice *dev) 408 { 409 struct ftmac100_data *priv = dev_get_priv(dev); 410 priv->name = dev->name; 411 return 0; 412 } 413 414 static int ftmac100_bind(struct udevice *dev) 415 { 416 return device_set_name(dev, dev->name); 417 } 418 419 static const struct eth_ops ftmac100_ops = { 420 .start = ftmac100_start, 421 .send = ftmac100_send, 422 .recv = ftmac100_recv, 423 .stop = ftmac100_stop, 424 .free_pkt = ftmac100_free_pkt, 425 }; 426 427 static const struct udevice_id ftmac100_ids[] = { 428 { .compatible = "andestech,atmac100" }, 429 { } 430 }; 431 432 U_BOOT_DRIVER(ftmac100) = { 433 .name = "nds32_mac", 434 .id = UCLASS_ETH, 435 .of_match = ftmac100_ids, 436 .bind = ftmac100_bind, 437 .ofdata_to_platdata = ftmac100_ofdata_to_platdata, 438 .probe = ftmac100_probe, 439 .ops = &ftmac100_ops, 440 .priv_auto_alloc_size = sizeof(struct ftmac100_data), 441 .platdata_auto_alloc_size = sizeof(struct eth_pdata), 442 .flags = DM_FLAG_ALLOC_PRIV_DMA, 443 }; 444 #endif 445