]> git.sur5r.net Git - u-boot/blob - drivers/net/ftgmac100.c
arm: imx6ul: Add Engicam GEAM6UL Starter Kit initial support
[u-boot] / drivers / net / ftgmac100.c
1 /*
2  * Faraday FTGMAC100 Ethernet
3  *
4  * (C) Copyright 2009 Faraday Technology
5  * Po-Yu Chuang <ratbert@faraday-tech.com>
6  *
7  * (C) Copyright 2010 Andes Technology
8  * Macpaul Lin <macpaul@andestech.com>
9  *
10  * SPDX-License-Identifier:     GPL-2.0+
11  */
12
13 #include <config.h>
14 #include <common.h>
15 #include <malloc.h>
16 #include <net.h>
17 #include <asm/io.h>
18 #include <asm/dma-mapping.h>
19 #include <linux/mii.h>
20
21 #include "ftgmac100.h"
22
23 #define ETH_ZLEN        60
24 #define CFG_XBUF_SIZE   1536
25
26 /* RBSR - hw default init value is also 0x640 */
27 #define RBSR_DEFAULT_VALUE      0x640
28
29 /* PKTBUFSTX/PKTBUFSRX must both be power of 2 */
30 #define PKTBUFSTX       4       /* must be power of 2 */
31
32 struct ftgmac100_data {
33         ulong txdes_dma;
34         struct ftgmac100_txdes *txdes;
35         ulong rxdes_dma;
36         struct ftgmac100_rxdes *rxdes;
37         int tx_index;
38         int rx_index;
39         int phy_addr;
40 };
41
42 /*
43  * struct mii_bus functions
44  */
45 static int ftgmac100_mdiobus_read(struct eth_device *dev, int phy_addr,
46         int regnum)
47 {
48         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
49         int phycr;
50         int i;
51
52         phycr = readl(&ftgmac100->phycr);
53
54         /* preserve MDC cycle threshold */
55         phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
56
57         phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr)
58               |  FTGMAC100_PHYCR_REGAD(regnum)
59               |  FTGMAC100_PHYCR_MIIRD;
60
61         writel(phycr, &ftgmac100->phycr);
62
63         for (i = 0; i < 10; i++) {
64                 phycr = readl(&ftgmac100->phycr);
65
66                 if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
67                         int data;
68
69                         data = readl(&ftgmac100->phydata);
70                         return FTGMAC100_PHYDATA_MIIRDATA(data);
71                 }
72
73                 mdelay(10);
74         }
75
76         debug("mdio read timed out\n");
77         return -1;
78 }
79
80 static int ftgmac100_mdiobus_write(struct eth_device *dev, int phy_addr,
81         int regnum, u16 value)
82 {
83         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
84         int phycr;
85         int data;
86         int i;
87
88         phycr = readl(&ftgmac100->phycr);
89
90         /* preserve MDC cycle threshold */
91         phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
92
93         phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr)
94               |  FTGMAC100_PHYCR_REGAD(regnum)
95               |  FTGMAC100_PHYCR_MIIWR;
96
97         data = FTGMAC100_PHYDATA_MIIWDATA(value);
98
99         writel(data, &ftgmac100->phydata);
100         writel(phycr, &ftgmac100->phycr);
101
102         for (i = 0; i < 10; i++) {
103                 phycr = readl(&ftgmac100->phycr);
104
105                 if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0) {
106                         debug("(phycr & FTGMAC100_PHYCR_MIIWR) == 0: " \
107                                 "phy_addr: %x\n", phy_addr);
108                         return 0;
109                 }
110
111                 mdelay(1);
112         }
113
114         debug("mdio write timed out\n");
115         return -1;
116 }
117
118 int ftgmac100_phy_read(struct eth_device *dev, int addr, int reg, u16 *value)
119 {
120         *value = ftgmac100_mdiobus_read(dev , addr, reg);
121
122         if (*value == -1)
123                 return -1;
124
125         return 0;
126 }
127
128 int  ftgmac100_phy_write(struct eth_device *dev, int addr, int reg, u16 value)
129 {
130         if (ftgmac100_mdiobus_write(dev, addr, reg, value) == -1)
131                 return -1;
132
133         return 0;
134 }
135
136 static int ftgmac100_phy_reset(struct eth_device *dev)
137 {
138         struct ftgmac100_data *priv = dev->priv;
139         int i;
140         u16 status, adv;
141
142         adv = ADVERTISE_CSMA | ADVERTISE_ALL;
143
144         ftgmac100_phy_write(dev, priv->phy_addr, MII_ADVERTISE, adv);
145
146         printf("%s: Starting autonegotiation...\n", dev->name);
147
148         ftgmac100_phy_write(dev, priv->phy_addr,
149                 MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART));
150
151         for (i = 0; i < 100000 / 100; i++) {
152                 ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
153
154                 if (status & BMSR_ANEGCOMPLETE)
155                         break;
156                 mdelay(1);
157         }
158
159         if (status & BMSR_ANEGCOMPLETE) {
160                 printf("%s: Autonegotiation complete\n", dev->name);
161         } else {
162                 printf("%s: Autonegotiation timed out (status=0x%04x)\n",
163                        dev->name, status);
164                 return 0;
165         }
166
167         return 1;
168 }
169
170 static int ftgmac100_phy_init(struct eth_device *dev)
171 {
172         struct ftgmac100_data *priv = dev->priv;
173
174         int phy_addr;
175         u16 phy_id, status, adv, lpa, stat_ge;
176         int media, speed, duplex;
177         int i;
178
179         /* Check if the PHY is up to snuff... */
180         for (phy_addr = 0; phy_addr < CONFIG_PHY_MAX_ADDR; phy_addr++) {
181
182                 ftgmac100_phy_read(dev, phy_addr, MII_PHYSID1, &phy_id);
183
184                 /*
185                  * When it is unable to found PHY,
186                  * the interface usually return 0xffff or 0x0000
187                  */
188                 if (phy_id != 0xffff && phy_id != 0x0) {
189                         printf("%s: found PHY at 0x%02x\n",
190                                 dev->name, phy_addr);
191                         priv->phy_addr = phy_addr;
192                         break;
193                 }
194         }
195
196         if (phy_id == 0xffff || phy_id == 0x0) {
197                 printf("%s: no PHY present\n", dev->name);
198                 return 0;
199         }
200
201         ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &status);
202
203         if (!(status & BMSR_LSTATUS)) {
204                 /* Try to re-negotiate if we don't have link already. */
205                 ftgmac100_phy_reset(dev);
206
207                 for (i = 0; i < 100000 / 100; i++) {
208                         ftgmac100_phy_read(dev, priv->phy_addr,
209                                 MII_BMSR, &status);
210                         if (status & BMSR_LSTATUS)
211                                 break;
212                         udelay(100);
213                 }
214         }
215
216         if (!(status & BMSR_LSTATUS)) {
217                 printf("%s: link down\n", dev->name);
218                 return 0;
219         }
220
221 #ifdef CONFIG_FTGMAC100_EGIGA
222         /* 1000 Base-T Status Register */
223         ftgmac100_phy_read(dev, priv->phy_addr,
224                 MII_STAT1000, &stat_ge);
225
226         speed = (stat_ge & (LPA_1000FULL | LPA_1000HALF)
227                  ? 1 : 0);
228
229         duplex = ((stat_ge & LPA_1000FULL)
230                  ? 1 : 0);
231
232         if (speed) { /* Speed is 1000 */
233                 printf("%s: link up, 1000bps %s-duplex\n",
234                         dev->name, duplex ? "full" : "half");
235                 return 0;
236         }
237 #endif
238
239         ftgmac100_phy_read(dev, priv->phy_addr, MII_ADVERTISE, &adv);
240         ftgmac100_phy_read(dev, priv->phy_addr, MII_LPA, &lpa);
241
242         media = mii_nway_result(lpa & adv);
243         speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? 1 : 0);
244         duplex = (media & ADVERTISE_FULL) ? 1 : 0;
245
246         printf("%s: link up, %sMbps %s-duplex\n",
247                dev->name, speed ? "100" : "10", duplex ? "full" : "half");
248
249         return 1;
250 }
251
252 static int ftgmac100_update_link_speed(struct eth_device *dev)
253 {
254         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
255         struct ftgmac100_data *priv = dev->priv;
256
257         unsigned short stat_fe;
258         unsigned short stat_ge;
259         unsigned int maccr;
260
261 #ifdef CONFIG_FTGMAC100_EGIGA
262         /* 1000 Base-T Status Register */
263         ftgmac100_phy_read(dev, priv->phy_addr, MII_STAT1000, &stat_ge);
264 #endif
265
266         ftgmac100_phy_read(dev, priv->phy_addr, MII_BMSR, &stat_fe);
267
268         if (!(stat_fe & BMSR_LSTATUS))  /* link status up? */
269                 return 0;
270
271         /* read MAC control register and clear related bits */
272         maccr = readl(&ftgmac100->maccr) &
273                 ~(FTGMAC100_MACCR_GIGA_MODE |
274                   FTGMAC100_MACCR_FAST_MODE |
275                   FTGMAC100_MACCR_FULLDUP);
276
277 #ifdef CONFIG_FTGMAC100_EGIGA
278         if (stat_ge & LPA_1000FULL) {
279                 /* set gmac for 1000BaseTX and Full Duplex */
280                 maccr |= FTGMAC100_MACCR_GIGA_MODE | FTGMAC100_MACCR_FULLDUP;
281         }
282
283         if (stat_ge & LPA_1000HALF) {
284                 /* set gmac for 1000BaseTX and Half Duplex */
285                 maccr |= FTGMAC100_MACCR_GIGA_MODE;
286         }
287 #endif
288
289         if (stat_fe & BMSR_100FULL) {
290                 /* set MII for 100BaseTX and Full Duplex */
291                 maccr |= FTGMAC100_MACCR_FAST_MODE | FTGMAC100_MACCR_FULLDUP;
292         }
293
294         if (stat_fe & BMSR_10FULL) {
295                 /* set MII for 10BaseT and Full Duplex */
296                 maccr |= FTGMAC100_MACCR_FULLDUP;
297         }
298
299         if (stat_fe & BMSR_100HALF) {
300                 /* set MII for 100BaseTX and Half Duplex */
301                 maccr |= FTGMAC100_MACCR_FAST_MODE;
302         }
303
304         if (stat_fe & BMSR_10HALF) {
305                 /* set MII for 10BaseT and Half Duplex */
306                 /* we have already clear these bits, do nothing */
307                 ;
308         }
309
310         /* update MII config into maccr */
311         writel(maccr, &ftgmac100->maccr);
312
313         return 1;
314 }
315
316 /*
317  * Reset MAC
318  */
319 static void ftgmac100_reset(struct eth_device *dev)
320 {
321         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
322
323         debug("%s()\n", __func__);
324
325         writel(FTGMAC100_MACCR_SW_RST, &ftgmac100->maccr);
326
327         while (readl(&ftgmac100->maccr) & FTGMAC100_MACCR_SW_RST)
328                 ;
329 }
330
331 /*
332  * Set MAC address
333  */
334 static void ftgmac100_set_mac(struct eth_device *dev,
335         const unsigned char *mac)
336 {
337         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
338         unsigned int maddr = mac[0] << 8 | mac[1];
339         unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
340
341         debug("%s(%x %x)\n", __func__, maddr, laddr);
342
343         writel(maddr, &ftgmac100->mac_madr);
344         writel(laddr, &ftgmac100->mac_ladr);
345 }
346
347 static void ftgmac100_set_mac_from_env(struct eth_device *dev)
348 {
349         eth_getenv_enetaddr("ethaddr", dev->enetaddr);
350
351         ftgmac100_set_mac(dev, dev->enetaddr);
352 }
353
354 /*
355  * disable transmitter, receiver
356  */
357 static void ftgmac100_halt(struct eth_device *dev)
358 {
359         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
360
361         debug("%s()\n", __func__);
362
363         writel(0, &ftgmac100->maccr);
364 }
365
366 static int ftgmac100_init(struct eth_device *dev, bd_t *bd)
367 {
368         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
369         struct ftgmac100_data *priv = dev->priv;
370         struct ftgmac100_txdes *txdes;
371         struct ftgmac100_rxdes *rxdes;
372         unsigned int maccr;
373         void *buf;
374         int i;
375
376         debug("%s()\n", __func__);
377
378         if (!priv->txdes) {
379                 txdes = dma_alloc_coherent(
380                         sizeof(*txdes) * PKTBUFSTX, &priv->txdes_dma);
381                 if (!txdes)
382                         panic("ftgmac100: out of memory\n");
383                 memset(txdes, 0, sizeof(*txdes) * PKTBUFSTX);
384                 priv->txdes = txdes;
385         }
386         txdes = priv->txdes;
387
388         if (!priv->rxdes) {
389                 rxdes = dma_alloc_coherent(
390                         sizeof(*rxdes) * PKTBUFSRX, &priv->rxdes_dma);
391                 if (!rxdes)
392                         panic("ftgmac100: out of memory\n");
393                 memset(rxdes, 0, sizeof(*rxdes) * PKTBUFSRX);
394                 priv->rxdes = rxdes;
395         }
396         rxdes = priv->rxdes;
397
398         /* set the ethernet address */
399         ftgmac100_set_mac_from_env(dev);
400
401         /* disable all interrupts */
402         writel(0, &ftgmac100->ier);
403
404         /* initialize descriptors */
405         priv->tx_index = 0;
406         priv->rx_index = 0;
407
408         txdes[PKTBUFSTX - 1].txdes0     = FTGMAC100_TXDES0_EDOTR;
409         rxdes[PKTBUFSRX - 1].rxdes0     = FTGMAC100_RXDES0_EDORR;
410
411         for (i = 0; i < PKTBUFSTX; i++) {
412                 /* TXBUF_BADR */
413                 if (!txdes[i].txdes2) {
414                         buf = memalign(ARCH_DMA_MINALIGN, CFG_XBUF_SIZE);
415                         if (!buf)
416                                 panic("ftgmac100: out of memory\n");
417                         txdes[i].txdes3 = virt_to_phys(buf);
418                         txdes[i].txdes2 = (uint)buf;
419                 }
420                 txdes[i].txdes1 = 0;
421         }
422
423         for (i = 0; i < PKTBUFSRX; i++) {
424                 /* RXBUF_BADR */
425                 if (!rxdes[i].rxdes2) {
426                         buf = net_rx_packets[i];
427                         rxdes[i].rxdes3 = virt_to_phys(buf);
428                         rxdes[i].rxdes2 = (uint)buf;
429                 }
430                 rxdes[i].rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
431         }
432
433         /* transmit ring */
434         writel(priv->txdes_dma, &ftgmac100->txr_badr);
435
436         /* receive ring */
437         writel(priv->rxdes_dma, &ftgmac100->rxr_badr);
438
439         /* poll receive descriptor automatically */
440         writel(FTGMAC100_APTC_RXPOLL_CNT(1), &ftgmac100->aptc);
441
442         /* config receive buffer size register */
443         writel(FTGMAC100_RBSR_SIZE(RBSR_DEFAULT_VALUE), &ftgmac100->rbsr);
444
445         /* enable transmitter, receiver */
446         maccr = FTGMAC100_MACCR_TXMAC_EN |
447                 FTGMAC100_MACCR_RXMAC_EN |
448                 FTGMAC100_MACCR_TXDMA_EN |
449                 FTGMAC100_MACCR_RXDMA_EN |
450                 FTGMAC100_MACCR_CRC_APD |
451                 FTGMAC100_MACCR_FULLDUP |
452                 FTGMAC100_MACCR_RX_RUNT |
453                 FTGMAC100_MACCR_RX_BROADPKT;
454
455         writel(maccr, &ftgmac100->maccr);
456
457         if (!ftgmac100_phy_init(dev)) {
458                 if (!ftgmac100_update_link_speed(dev))
459                         return -1;
460         }
461
462         return 0;
463 }
464
465 /*
466  * Get a data block via Ethernet
467  */
468 static int ftgmac100_recv(struct eth_device *dev)
469 {
470         struct ftgmac100_data *priv = dev->priv;
471         struct ftgmac100_rxdes *curr_des;
472         unsigned short rxlen;
473
474         curr_des = &priv->rxdes[priv->rx_index];
475
476         if (!(curr_des->rxdes0 & FTGMAC100_RXDES0_RXPKT_RDY))
477                 return -1;
478
479         if (curr_des->rxdes0 & (FTGMAC100_RXDES0_RX_ERR |
480                                 FTGMAC100_RXDES0_CRC_ERR |
481                                 FTGMAC100_RXDES0_FTL |
482                                 FTGMAC100_RXDES0_RUNT |
483                                 FTGMAC100_RXDES0_RX_ODD_NB)) {
484                 return -1;
485         }
486
487         rxlen = FTGMAC100_RXDES0_VDBC(curr_des->rxdes0);
488
489         debug("%s(): RX buffer %d, %x received\n",
490                __func__, priv->rx_index, rxlen);
491
492         /* invalidate d-cache */
493         dma_map_single((void *)curr_des->rxdes2, rxlen, DMA_FROM_DEVICE);
494
495         /* pass the packet up to the protocol layers. */
496         net_process_received_packet((void *)curr_des->rxdes2, rxlen);
497
498         /* release buffer to DMA */
499         curr_des->rxdes0 &= ~FTGMAC100_RXDES0_RXPKT_RDY;
500
501         priv->rx_index = (priv->rx_index + 1) % PKTBUFSRX;
502
503         return 0;
504 }
505
506 /*
507  * Send a data block via Ethernet
508  */
509 static int ftgmac100_send(struct eth_device *dev, void *packet, int length)
510 {
511         struct ftgmac100 *ftgmac100 = (struct ftgmac100 *)dev->iobase;
512         struct ftgmac100_data *priv = dev->priv;
513         struct ftgmac100_txdes *curr_des = &priv->txdes[priv->tx_index];
514
515         if (curr_des->txdes0 & FTGMAC100_TXDES0_TXDMA_OWN) {
516                 debug("%s(): no TX descriptor available\n", __func__);
517                 return -1;
518         }
519
520         debug("%s(%x, %x)\n", __func__, (int)packet, length);
521
522         length = (length < ETH_ZLEN) ? ETH_ZLEN : length;
523
524         memcpy((void *)curr_des->txdes2, (void *)packet, length);
525         dma_map_single((void *)curr_des->txdes2, length, DMA_TO_DEVICE);
526
527         /* only one descriptor on TXBUF */
528         curr_des->txdes0 &= FTGMAC100_TXDES0_EDOTR;
529         curr_des->txdes0 |= FTGMAC100_TXDES0_FTS |
530                             FTGMAC100_TXDES0_LTS |
531                             FTGMAC100_TXDES0_TXBUF_SIZE(length) |
532                             FTGMAC100_TXDES0_TXDMA_OWN ;
533
534         /* start transmit */
535         writel(1, &ftgmac100->txpd);
536
537         debug("%s(): packet sent\n", __func__);
538
539         priv->tx_index = (priv->tx_index + 1) % PKTBUFSTX;
540
541         return 0;
542 }
543
544 int ftgmac100_initialize(bd_t *bd)
545 {
546         struct eth_device *dev;
547         struct ftgmac100_data *priv;
548
549         dev = malloc(sizeof *dev);
550         if (!dev) {
551                 printf("%s(): failed to allocate dev\n", __func__);
552                 goto out;
553         }
554
555         /* Transmit and receive descriptors should align to 16 bytes */
556         priv = memalign(16, sizeof(struct ftgmac100_data));
557         if (!priv) {
558                 printf("%s(): failed to allocate priv\n", __func__);
559                 goto free_dev;
560         }
561
562         memset(dev, 0, sizeof(*dev));
563         memset(priv, 0, sizeof(*priv));
564
565         strcpy(dev->name, "FTGMAC100");
566         dev->iobase     = CONFIG_FTGMAC100_BASE;
567         dev->init       = ftgmac100_init;
568         dev->halt       = ftgmac100_halt;
569         dev->send       = ftgmac100_send;
570         dev->recv       = ftgmac100_recv;
571         dev->priv       = priv;
572
573         eth_register(dev);
574
575         ftgmac100_reset(dev);
576
577         return 1;
578
579 free_dev:
580         free(dev);
581 out:
582         return 0;
583 }