]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/net/ep93xx_eth.c
1c09f1004a7090102279255b7b3650b4102a295f
[karo-tx-uboot.git] / drivers / net / ep93xx_eth.c
1 /*
2  * Cirrus Logic EP93xx ethernet MAC / MII driver.
3  *
4  * Copyright (C) 2010, 2009
5  * Matthias Kaehlcke <matthias@kaehlcke.net>
6  *
7  * Copyright (C) 2004, 2005
8  * Cory T. Tusar, Videon Central, Inc., <ctusar@videon-central.com>
9  *
10  * Based on the original eth.[ch] Cirrus Logic EP93xx Rev D. Ethernet Driver,
11  * which is
12  *
13  * (C) Copyright 2002 2003
14  * Adam Bezanson, Network Audio Technologies, Inc.
15  * <bezanson@netaudiotech.com>
16  *
17  * SPDX-License-Identifier:     GPL-2.0+
18  */
19
20 #include <command.h>
21 #include <common.h>
22 #include <asm/arch/ep93xx.h>
23 #include <asm/io.h>
24 #include <malloc.h>
25 #include <miiphy.h>
26 #include <linux/types.h>
27 #include "ep93xx_eth.h"
28
29 #define GET_PRIV(eth_dev)       ((struct ep93xx_priv *)(eth_dev)->priv)
30 #define GET_REGS(eth_dev)       (GET_PRIV(eth_dev)->regs)
31
32 /* ep93xx_miiphy ops forward declarations */
33 static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
34                         unsigned char const reg, unsigned short * const value);
35 static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
36                         unsigned char const reg, unsigned short const value);
37
38 #if defined(EP93XX_MAC_DEBUG)
39 /**
40  * Dump ep93xx_mac values to the terminal.
41  */
42 static void dump_dev(struct eth_device *dev)
43 {
44         struct ep93xx_priv *priv = GET_PRIV(dev);
45         int i;
46
47         printf("\ndump_dev()\n");
48         printf("  rx_dq.base         %p\n", priv->rx_dq.base);
49         printf("  rx_dq.current      %p\n", priv->rx_dq.current);
50         printf("  rx_dq.end          %p\n", priv->rx_dq.end);
51         printf("  rx_sq.base         %p\n", priv->rx_sq.base);
52         printf("  rx_sq.current      %p\n", priv->rx_sq.current);
53         printf("  rx_sq.end          %p\n", priv->rx_sq.end);
54
55         for (i = 0; i < NUMRXDESC; i++)
56                 printf("  rx_buffer[%2.d]      %p\n", i, NetRxPackets[i]);
57
58         printf("  tx_dq.base         %p\n", priv->tx_dq.base);
59         printf("  tx_dq.current      %p\n", priv->tx_dq.current);
60         printf("  tx_dq.end          %p\n", priv->tx_dq.end);
61         printf("  tx_sq.base         %p\n", priv->tx_sq.base);
62         printf("  tx_sq.current      %p\n", priv->tx_sq.current);
63         printf("  tx_sq.end          %p\n", priv->tx_sq.end);
64 }
65
66 /**
67  * Dump all RX status queue entries to the terminal.
68  */
69 static void dump_rx_status_queue(struct eth_device *dev)
70 {
71         struct ep93xx_priv *priv = GET_PRIV(dev);
72         int i;
73
74         printf("\ndump_rx_status_queue()\n");
75         printf("  descriptor address     word1           word2\n");
76         for (i = 0; i < NUMRXDESC; i++) {
77                 printf("  [ %p ]             %08X        %08X\n",
78                         priv->rx_sq.base + i,
79                         (priv->rx_sq.base + i)->word1,
80                         (priv->rx_sq.base + i)->word2);
81         }
82 }
83
84 /**
85  * Dump all RX descriptor queue entries to the terminal.
86  */
87 static void dump_rx_descriptor_queue(struct eth_device *dev)
88 {
89         struct ep93xx_priv *priv = GET_PRIV(dev);
90         int i;
91
92         printf("\ndump_rx_descriptor_queue()\n");
93         printf("  descriptor address     word1           word2\n");
94         for (i = 0; i < NUMRXDESC; i++) {
95                 printf("  [ %p ]             %08X        %08X\n",
96                         priv->rx_dq.base + i,
97                         (priv->rx_dq.base + i)->word1,
98                         (priv->rx_dq.base + i)->word2);
99         }
100 }
101
102 /**
103  * Dump all TX descriptor queue entries to the terminal.
104  */
105 static void dump_tx_descriptor_queue(struct eth_device *dev)
106 {
107         struct ep93xx_priv *priv = GET_PRIV(dev);
108         int i;
109
110         printf("\ndump_tx_descriptor_queue()\n");
111         printf("  descriptor address     word1           word2\n");
112         for (i = 0; i < NUMTXDESC; i++) {
113                 printf("  [ %p ]             %08X        %08X\n",
114                         priv->tx_dq.base + i,
115                         (priv->tx_dq.base + i)->word1,
116                         (priv->tx_dq.base + i)->word2);
117         }
118 }
119
120 /**
121  * Dump all TX status queue entries to the terminal.
122  */
123 static void dump_tx_status_queue(struct eth_device *dev)
124 {
125         struct ep93xx_priv *priv = GET_PRIV(dev);
126         int i;
127
128         printf("\ndump_tx_status_queue()\n");
129         printf("  descriptor address     word1\n");
130         for (i = 0; i < NUMTXDESC; i++) {
131                 printf("  [ %p ]             %08X\n",
132                         priv->rx_sq.base + i,
133                         (priv->rx_sq.base + i)->word1);
134         }
135 }
136 #else
137 #define dump_dev(x)
138 #define dump_rx_descriptor_queue(x)
139 #define dump_rx_status_queue(x)
140 #define dump_tx_descriptor_queue(x)
141 #define dump_tx_status_queue(x)
142 #endif  /* defined(EP93XX_MAC_DEBUG) */
143
144 /**
145  * Reset the EP93xx MAC by twiddling the soft reset bit and spinning until
146  * it's cleared.
147  */
148 static void ep93xx_mac_reset(struct eth_device *dev)
149 {
150         struct mac_regs *mac = GET_REGS(dev);
151         uint32_t value;
152
153         debug("+ep93xx_mac_reset");
154
155         value = readl(&mac->selfctl);
156         value |= SELFCTL_RESET;
157         writel(value, &mac->selfctl);
158
159         while (readl(&mac->selfctl) & SELFCTL_RESET)
160                 ; /* noop */
161
162         debug("-ep93xx_mac_reset");
163 }
164
165 /* Eth device open */
166 static int ep93xx_eth_open(struct eth_device *dev, bd_t *bd)
167 {
168         struct ep93xx_priv *priv = GET_PRIV(dev);
169         struct mac_regs *mac = GET_REGS(dev);
170         uchar *mac_addr = dev->enetaddr;
171         int i;
172
173         debug("+ep93xx_eth_open");
174
175         /* Reset the MAC */
176         ep93xx_mac_reset(dev);
177
178         /* Reset the descriptor queues' current and end address values */
179         priv->tx_dq.current = priv->tx_dq.base;
180         priv->tx_dq.end = (priv->tx_dq.base + NUMTXDESC);
181
182         priv->tx_sq.current = priv->tx_sq.base;
183         priv->tx_sq.end = (priv->tx_sq.base + NUMTXDESC);
184
185         priv->rx_dq.current = priv->rx_dq.base;
186         priv->rx_dq.end = (priv->rx_dq.base + NUMRXDESC);
187
188         priv->rx_sq.current = priv->rx_sq.base;
189         priv->rx_sq.end = (priv->rx_sq.base + NUMRXDESC);
190
191         /*
192          * Set the transmit descriptor and status queues' base address,
193          * current address, and length registers.  Set the maximum frame
194          * length and threshold. Enable the transmit descriptor processor.
195          */
196         writel((uint32_t)priv->tx_dq.base, &mac->txdq.badd);
197         writel((uint32_t)priv->tx_dq.base, &mac->txdq.curadd);
198         writel(sizeof(struct tx_descriptor) * NUMTXDESC, &mac->txdq.blen);
199
200         writel((uint32_t)priv->tx_sq.base, &mac->txstsq.badd);
201         writel((uint32_t)priv->tx_sq.base, &mac->txstsq.curadd);
202         writel(sizeof(struct tx_status) * NUMTXDESC, &mac->txstsq.blen);
203
204         writel(0x00040000, &mac->txdthrshld);
205         writel(0x00040000, &mac->txststhrshld);
206
207         writel((TXSTARTMAX << 0) | (PKTSIZE_ALIGN << 16), &mac->maxfrmlen);
208         writel(BMCTL_TXEN, &mac->bmctl);
209
210         /*
211          * Set the receive descriptor and status queues' base address,
212          * current address, and length registers.  Enable the receive
213          * descriptor processor.
214          */
215         writel((uint32_t)priv->rx_dq.base, &mac->rxdq.badd);
216         writel((uint32_t)priv->rx_dq.base, &mac->rxdq.curadd);
217         writel(sizeof(struct rx_descriptor) * NUMRXDESC, &mac->rxdq.blen);
218
219         writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.badd);
220         writel((uint32_t)priv->rx_sq.base, &mac->rxstsq.curadd);
221         writel(sizeof(struct rx_status) * NUMRXDESC, &mac->rxstsq.blen);
222
223         writel(0x00040000, &mac->rxdthrshld);
224
225         writel(BMCTL_RXEN, &mac->bmctl);
226
227         writel(0x00040000, &mac->rxststhrshld);
228
229         /* Wait until the receive descriptor processor is active */
230         while (!(readl(&mac->bmsts) & BMSTS_RXACT))
231                 ; /* noop */
232
233         /*
234          * Initialize the RX descriptor queue. Clear the TX descriptor queue.
235          * Clear the RX and TX status queues. Enqueue the RX descriptor and
236          * status entries to the MAC.
237          */
238         for (i = 0; i < NUMRXDESC; i++) {
239                 /* set buffer address */
240                 (priv->rx_dq.base + i)->word1 = (uint32_t)NetRxPackets[i];
241
242                 /* set buffer length, clear buffer index and NSOF */
243                 (priv->rx_dq.base + i)->word2 = PKTSIZE_ALIGN;
244         }
245
246         memset(priv->tx_dq.base, 0,
247                 (sizeof(struct tx_descriptor) * NUMTXDESC));
248         memset(priv->rx_sq.base, 0,
249                 (sizeof(struct rx_status) * NUMRXDESC));
250         memset(priv->tx_sq.base, 0,
251                 (sizeof(struct tx_status) * NUMTXDESC));
252
253         writel(NUMRXDESC, &mac->rxdqenq);
254         writel(NUMRXDESC, &mac->rxstsqenq);
255
256         /* Set the primary MAC address */
257         writel(AFP_IAPRIMARY, &mac->afp);
258         writel(mac_addr[0] | (mac_addr[1] << 8) |
259                 (mac_addr[2] << 16) | (mac_addr[3] << 24),
260                 &mac->indad);
261         writel(mac_addr[4] | (mac_addr[5] << 8), &mac->indad_upper);
262
263         /* Turn on RX and TX */
264         writel(RXCTL_IA0 | RXCTL_BA | RXCTL_SRXON |
265                 RXCTL_RCRCA | RXCTL_MA, &mac->rxctl);
266         writel(TXCTL_STXON, &mac->txctl);
267
268         /* Dump data structures if we're debugging */
269         dump_dev(dev);
270         dump_rx_descriptor_queue(dev);
271         dump_rx_status_queue(dev);
272         dump_tx_descriptor_queue(dev);
273         dump_tx_status_queue(dev);
274
275         debug("-ep93xx_eth_open");
276
277         return 1;
278 }
279
280 /**
281  * Halt EP93xx MAC transmit and receive by clearing the TxCTL and RxCTL
282  * registers.
283  */
284 static void ep93xx_eth_close(struct eth_device *dev)
285 {
286         struct mac_regs *mac = GET_REGS(dev);
287
288         debug("+ep93xx_eth_close");
289
290         writel(0x00000000, &mac->rxctl);
291         writel(0x00000000, &mac->txctl);
292
293         debug("-ep93xx_eth_close");
294 }
295
296 /**
297  * Copy a frame of data from the MAC into the protocol layer for further
298  * processing.
299  */
300 static int ep93xx_eth_rcv_packet(struct eth_device *dev)
301 {
302         struct mac_regs *mac = GET_REGS(dev);
303         struct ep93xx_priv *priv = GET_PRIV(dev);
304         int len = -1;
305
306         debug("+ep93xx_eth_rcv_packet");
307
308         if (RX_STATUS_RFP(priv->rx_sq.current)) {
309                 if (RX_STATUS_RWE(priv->rx_sq.current)) {
310                         /*
311                          * We have a good frame. Extract the frame's length
312                          * from the current rx_status_queue entry, and copy
313                          * the frame's data into NetRxPackets[] of the
314                          * protocol stack. We track the total number of
315                          * bytes in the frame (nbytes_frame) which will be
316                          * used when we pass the data off to the protocol
317                          * layer via NetReceive().
318                          */
319                         len = RX_STATUS_FRAME_LEN(priv->rx_sq.current);
320
321                         NetReceive((uchar *)priv->rx_dq.current->word1, len);
322
323                         debug("reporting %d bytes...\n", len);
324                 } else {
325                         /* Do we have an erroneous packet? */
326                         error("packet rx error, status %08X %08X",
327                                 priv->rx_sq.current->word1,
328                                 priv->rx_sq.current->word2);
329                         dump_rx_descriptor_queue(dev);
330                         dump_rx_status_queue(dev);
331                 }
332
333                 /*
334                  * Clear the associated status queue entry, and
335                  * increment our current pointers to the next RX
336                  * descriptor and status queue entries (making sure
337                  * we wrap properly).
338                  */
339                 memset((void *)priv->rx_sq.current, 0,
340                         sizeof(struct rx_status));
341
342                 priv->rx_sq.current++;
343                 if (priv->rx_sq.current >= priv->rx_sq.end)
344                         priv->rx_sq.current = priv->rx_sq.base;
345
346                 priv->rx_dq.current++;
347                 if (priv->rx_dq.current >= priv->rx_dq.end)
348                         priv->rx_dq.current = priv->rx_dq.base;
349
350                 /*
351                  * Finally, return the RX descriptor and status entries
352                  * back to the MAC engine, and loop again, checking for
353                  * more descriptors to process.
354                  */
355                 writel(1, &mac->rxdqenq);
356                 writel(1, &mac->rxstsqenq);
357         } else {
358                 len = 0;
359         }
360
361         debug("-ep93xx_eth_rcv_packet %d", len);
362         return len;
363 }
364
365 /**
366  * Send a block of data via ethernet.
367  */
368 static int ep93xx_eth_send_packet(struct eth_device *dev,
369                                 void * const packet, int const length)
370 {
371         struct mac_regs *mac = GET_REGS(dev);
372         struct ep93xx_priv *priv = GET_PRIV(dev);
373         int ret = -1;
374
375         debug("+ep93xx_eth_send_packet");
376
377         /* Parameter check */
378         BUG_ON(packet == NULL);
379
380         /*
381          * Initialize the TX descriptor queue with the new packet's info.
382          * Clear the associated status queue entry. Enqueue the packet
383          * to the MAC for transmission.
384          */
385
386         /* set buffer address */
387         priv->tx_dq.current->word1 = (uint32_t)packet;
388
389         /* set buffer length and EOF bit */
390         priv->tx_dq.current->word2 = length | TX_DESC_EOF;
391
392         /* clear tx status */
393         priv->tx_sq.current->word1 = 0;
394
395         /* enqueue the TX descriptor */
396         writel(1, &mac->txdqenq);
397
398         /* wait for the frame to become processed */
399         while (!TX_STATUS_TXFP(priv->tx_sq.current))
400                 ; /* noop */
401
402         if (!TX_STATUS_TXWE(priv->tx_sq.current)) {
403                 error("packet tx error, status %08X",
404                         priv->tx_sq.current->word1);
405                 dump_tx_descriptor_queue(dev);
406                 dump_tx_status_queue(dev);
407
408                 /* TODO: Add better error handling? */
409                 goto eth_send_out;
410         }
411
412         ret = 0;
413         /* Fall through */
414
415 eth_send_out:
416         debug("-ep93xx_eth_send_packet %d", ret);
417         return ret;
418 }
419
420 #if defined(CONFIG_MII)
421 int ep93xx_miiphy_initialize(bd_t * const bd)
422 {
423         miiphy_register("ep93xx_eth0", ep93xx_miiphy_read, ep93xx_miiphy_write);
424         return 0;
425 }
426 #endif
427
428 /**
429  * Initialize the EP93xx MAC.  The MAC hardware is reset.  Buffers are
430  * allocated, if necessary, for the TX and RX descriptor and status queues,
431  * as well as for received packets.  The EP93XX MAC hardware is initialized.
432  * Transmit and receive operations are enabled.
433  */
434 int ep93xx_eth_initialize(u8 dev_num, int base_addr)
435 {
436         int ret = -1;
437         struct eth_device *dev;
438         struct ep93xx_priv *priv;
439
440         debug("+ep93xx_eth_initialize");
441
442         priv = malloc(sizeof(*priv));
443         if (!priv) {
444                 error("malloc() failed");
445                 goto eth_init_failed_0;
446         }
447         memset(priv, 0, sizeof(*priv));
448
449         priv->regs = (struct mac_regs *)base_addr;
450
451         priv->tx_dq.base = calloc(NUMTXDESC,
452                                 sizeof(struct tx_descriptor));
453         if (priv->tx_dq.base == NULL) {
454                 error("calloc() failed");
455                 goto eth_init_failed_1;
456         }
457
458         priv->tx_sq.base = calloc(NUMTXDESC,
459                                 sizeof(struct tx_status));
460         if (priv->tx_sq.base == NULL) {
461                 error("calloc() failed");
462                 goto eth_init_failed_2;
463         }
464
465         priv->rx_dq.base = calloc(NUMRXDESC,
466                                 sizeof(struct rx_descriptor));
467         if (priv->rx_dq.base == NULL) {
468                 error("calloc() failed");
469                 goto eth_init_failed_3;
470         }
471
472         priv->rx_sq.base = calloc(NUMRXDESC,
473                                 sizeof(struct rx_status));
474         if (priv->rx_sq.base == NULL) {
475                 error("calloc() failed");
476                 goto eth_init_failed_4;
477         }
478
479         dev = malloc(sizeof *dev);
480         if (dev == NULL) {
481                 error("malloc() failed");
482                 goto eth_init_failed_5;
483         }
484         memset(dev, 0, sizeof *dev);
485
486         dev->iobase = base_addr;
487         dev->priv = priv;
488         dev->init = ep93xx_eth_open;
489         dev->halt = ep93xx_eth_close;
490         dev->send = ep93xx_eth_send_packet;
491         dev->recv = ep93xx_eth_rcv_packet;
492
493         sprintf(dev->name, "ep93xx_eth-%hu", dev_num);
494
495         eth_register(dev);
496
497         /* Done! */
498         ret = 1;
499         goto eth_init_done;
500
501 eth_init_failed_5:
502         free(priv->rx_sq.base);
503         /* Fall through */
504
505 eth_init_failed_4:
506         free(priv->rx_dq.base);
507         /* Fall through */
508
509 eth_init_failed_3:
510         free(priv->tx_sq.base);
511         /* Fall through */
512
513 eth_init_failed_2:
514         free(priv->tx_dq.base);
515         /* Fall through */
516
517 eth_init_failed_1:
518         free(priv);
519         /* Fall through */
520
521 eth_init_failed_0:
522         /* Fall through */
523
524 eth_init_done:
525         debug("-ep93xx_eth_initialize %d", ret);
526         return ret;
527 }
528
529 #if defined(CONFIG_MII)
530
531 /**
532  * Maximum MII address we support
533  */
534 #define MII_ADDRESS_MAX                 31
535
536 /**
537  * Maximum MII register address we support
538  */
539 #define MII_REGISTER_MAX                31
540
541 /**
542  * Read a 16-bit value from an MII register.
543  */
544 static int ep93xx_miiphy_read(const char * const dev, unsigned char const addr,
545                         unsigned char const reg, unsigned short * const value)
546 {
547         struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
548         int ret = -1;
549         uint32_t self_ctl;
550
551         debug("+ep93xx_miiphy_read");
552
553         /* Parameter checks */
554         BUG_ON(dev == NULL);
555         BUG_ON(addr > MII_ADDRESS_MAX);
556         BUG_ON(reg > MII_REGISTER_MAX);
557         BUG_ON(value == NULL);
558
559         /*
560          * Save the current SelfCTL register value.  Set MAC to suppress
561          * preamble bits.  Wait for any previous MII command to complete
562          * before issuing the new command.
563          */
564         self_ctl = readl(&mac->selfctl);
565 #if defined(CONFIG_MII_SUPPRESS_PREAMBLE)
566         writel(self_ctl & ~(1 << 8), &mac->selfctl);
567 #endif  /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
568
569         while (readl(&mac->miists) & MIISTS_BUSY)
570                 ; /* noop */
571
572         /*
573          * Issue the MII 'read' command.  Wait for the command to complete.
574          * Read the MII data value.
575          */
576         writel(MIICMD_OPCODE_READ | ((uint32_t)addr << 5) | (uint32_t)reg,
577                 &mac->miicmd);
578         while (readl(&mac->miists) & MIISTS_BUSY)
579                 ; /* noop */
580
581         *value = (unsigned short)readl(&mac->miidata);
582
583         /* Restore the saved SelfCTL value and return. */
584         writel(self_ctl, &mac->selfctl);
585
586         ret = 0;
587         /* Fall through */
588
589         debug("-ep93xx_miiphy_read");
590         return ret;
591 }
592
593 /**
594  * Write a 16-bit value to an MII register.
595  */
596 static int ep93xx_miiphy_write(const char * const dev, unsigned char const addr,
597                         unsigned char const reg, unsigned short const value)
598 {
599         struct mac_regs *mac = (struct mac_regs *)MAC_BASE;
600         int ret = -1;
601         uint32_t self_ctl;
602
603         debug("+ep93xx_miiphy_write");
604
605         /* Parameter checks */
606         BUG_ON(dev == NULL);
607         BUG_ON(addr > MII_ADDRESS_MAX);
608         BUG_ON(reg > MII_REGISTER_MAX);
609
610         /*
611          * Save the current SelfCTL register value.  Set MAC to suppress
612          * preamble bits.  Wait for any previous MII command to complete
613          * before issuing the new command.
614          */
615         self_ctl = readl(&mac->selfctl);
616 #if defined(CONFIG_MII_SUPPRESS_PREAMBLE)
617         writel(self_ctl & ~(1 << 8), &mac->selfctl);
618 #endif  /* defined(CONFIG_MII_SUPPRESS_PREAMBLE) */
619
620         while (readl(&mac->miists) & MIISTS_BUSY)
621                 ; /* noop */
622
623         /* Issue the MII 'write' command.  Wait for the command to complete. */
624         writel((uint32_t)value, &mac->miidata);
625         writel(MIICMD_OPCODE_WRITE | ((uint32_t)addr << 5) | (uint32_t)reg,
626                 &mac->miicmd);
627         while (readl(&mac->miists) & MIISTS_BUSY)
628                 ; /* noop */
629
630         /* Restore the saved SelfCTL value and return. */
631         writel(self_ctl, &mac->selfctl);
632
633         ret = 0;
634         /* Fall through */
635
636         debug("-ep93xx_miiphy_write");
637         return ret;
638 }
639 #endif  /* defined(CONFIG_MII) */