aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPo-Yu Chuang <ratbert@faraday-tech.com>2011-02-28 15:48:49 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-03 15:19:11 -0500
commit8d77c036b57cf813d838f859e11b6a188acdb1fb (patch)
tree2458f7f1402828fe2aceee52d5f3cd23ba39f07e /drivers
parent29546a6404e3a4b5d13f0a9586eb5cf1c3b25167 (diff)
net: add Faraday FTMAC100 10/100 Ethernet driver
FTMAC100 Ethernet Media Access Controller supports 10/100 Mbps and MII. This driver has been working on some ARM/NDS32 SoC's including Faraday A320 and Andes AG101. Signed-off-by: Po-Yu Chuang <ratbert@faraday-tech.com> Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/Kconfig9
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/ftmac100.c1196
-rw-r--r--drivers/net/ftmac100.h180
4 files changed, 1386 insertions, 0 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6e09d5fea221..fba89ae2926b 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2008,6 +2008,15 @@ config BCM63XX_ENET
2008 This driver supports the ethernet MACs in the Broadcom 63xx 2008 This driver supports the ethernet MACs in the Broadcom 63xx
2009 MIPS chipset family (BCM63XX). 2009 MIPS chipset family (BCM63XX).
2010 2010
2011config FTMAC100
2012 tristate "Faraday FTMAC100 10/100 Ethernet support"
2013 depends on ARM
2014 select MII
2015 help
2016 This driver supports the FTMAC100 10/100 Ethernet controller
2017 from Faraday. It is used on Faraday A320, Andes AG101 and some
2018 other ARM/NDS32 SoC's.
2019
2011source "drivers/net/fs_enet/Kconfig" 2020source "drivers/net/fs_enet/Kconfig"
2012 2021
2013source "drivers/net/octeon/Kconfig" 2022source "drivers/net/octeon/Kconfig"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index b90738d13994..7c2171179f97 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -147,6 +147,7 @@ obj-$(CONFIG_FORCEDETH) += forcedeth.o
147obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o 147obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
148obj-$(CONFIG_AX88796) += ax88796.o 148obj-$(CONFIG_AX88796) += ax88796.o
149obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o 149obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
150obj-$(CONFIG_FTMAC100) += ftmac100.o
150 151
151obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o 152obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
152obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o 153obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c
new file mode 100644
index 000000000000..df70368bf317
--- /dev/null
+++ b/drivers/net/ftmac100.c
@@ -0,0 +1,1196 @@
1/*
2 * Faraday FTMAC100 10/100 Ethernet
3 *
4 * (C) Copyright 2009-2011 Faraday Technology
5 * Po-Yu Chuang <ratbert@faraday-tech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include <linux/dma-mapping.h>
25#include <linux/etherdevice.h>
26#include <linux/ethtool.h>
27#include <linux/init.h>
28#include <linux/io.h>
29#include <linux/mii.h>
30#include <linux/module.h>
31#include <linux/netdevice.h>
32#include <linux/platform_device.h>
33
34#include "ftmac100.h"
35
36#define DRV_NAME "ftmac100"
37#define DRV_VERSION "0.2"
38
39#define RX_QUEUE_ENTRIES 128 /* must be power of 2 */
40#define TX_QUEUE_ENTRIES 16 /* must be power of 2 */
41
42#define MAX_PKT_SIZE 1518
43#define RX_BUF_SIZE 2044 /* must be smaller than 0x7ff */
44
45#if MAX_PKT_SIZE > 0x7ff
46#error invalid MAX_PKT_SIZE
47#endif
48
49#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
50#error invalid RX_BUF_SIZE
51#endif
52
53/******************************************************************************
54 * private data
55 *****************************************************************************/
56struct ftmac100_descs {
57 struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
58 struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
59};
60
61struct ftmac100 {
62 struct resource *res;
63 void __iomem *base;
64 int irq;
65
66 struct ftmac100_descs *descs;
67 dma_addr_t descs_dma_addr;
68
69 unsigned int rx_pointer;
70 unsigned int tx_clean_pointer;
71 unsigned int tx_pointer;
72 unsigned int tx_pending;
73
74 spinlock_t tx_lock;
75
76 struct net_device *netdev;
77 struct device *dev;
78 struct napi_struct napi;
79
80 struct mii_if_info mii;
81};
82
83static int ftmac100_alloc_rx_page(struct ftmac100 *priv, struct ftmac100_rxdes *rxdes);
84
85/******************************************************************************
86 * internal functions (hardware register access)
87 *****************************************************************************/
88#define INT_MASK_ALL_ENABLED (FTMAC100_INT_RPKT_FINISH | \
89 FTMAC100_INT_NORXBUF | \
90 FTMAC100_INT_XPKT_OK | \
91 FTMAC100_INT_XPKT_LOST | \
92 FTMAC100_INT_RPKT_LOST | \
93 FTMAC100_INT_AHB_ERR | \
94 FTMAC100_INT_PHYSTS_CHG)
95
96#define INT_MASK_ALL_DISABLED 0
97
98static void ftmac100_enable_all_int(struct ftmac100 *priv)
99{
100 iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
101}
102
103static void ftmac100_disable_all_int(struct ftmac100 *priv)
104{
105 iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
106}
107
108static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
109{
110 iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
111}
112
113static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
114{
115 iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
116}
117
118static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
119{
120 iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
121}
122
123static int ftmac100_reset(struct ftmac100 *priv)
124{
125 struct net_device *netdev = priv->netdev;
126 int i;
127
128 /* NOTE: reset clears all registers */
129 iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
130
131 for (i = 0; i < 5; i++) {
132 unsigned int maccr;
133
134 maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
135 if (!(maccr & FTMAC100_MACCR_SW_RST)) {
136 /*
137 * FTMAC100_MACCR_SW_RST cleared does not indicate
138 * that hardware reset completed (what the f*ck).
139 * We still need to wait for a while.
140 */
141 usleep_range(500, 1000);
142 return 0;
143 }
144
145 usleep_range(1000, 10000);
146 }
147
148 netdev_err(netdev, "software reset failed\n");
149 return -EIO;
150}
151
152static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
153{
154 unsigned int maddr = mac[0] << 8 | mac[1];
155 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
156
157 iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
158 iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
159}
160
161#define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \
162 FTMAC100_MACCR_RCV_EN | \
163 FTMAC100_MACCR_XDMA_EN | \
164 FTMAC100_MACCR_RDMA_EN | \
165 FTMAC100_MACCR_CRC_APD | \
166 FTMAC100_MACCR_FULLDUP | \
167 FTMAC100_MACCR_RX_RUNT | \
168 FTMAC100_MACCR_RX_BROADPKT)
169
170static int ftmac100_start_hw(struct ftmac100 *priv)
171{
172 struct net_device *netdev = priv->netdev;
173
174 if (ftmac100_reset(priv))
175 return -EIO;
176
177 /* setup ring buffer base registers */
178 ftmac100_set_rx_ring_base(priv,
179 priv->descs_dma_addr +
180 offsetof(struct ftmac100_descs, rxdes));
181 ftmac100_set_tx_ring_base(priv,
182 priv->descs_dma_addr +
183 offsetof(struct ftmac100_descs, txdes));
184
185 iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
186
187 ftmac100_set_mac(priv, netdev->dev_addr);
188
189 iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
190 return 0;
191}
192
193static void ftmac100_stop_hw(struct ftmac100 *priv)
194{
195 iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
196}
197
198/******************************************************************************
199 * internal functions (receive descriptor)
200 *****************************************************************************/
201static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
202{
203 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
204}
205
206static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
207{
208 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
209}
210
211static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
212{
213 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
214}
215
216static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
217{
218 /* clear status bits */
219 rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
220}
221
222static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
223{
224 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
225}
226
227static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
228{
229 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
230}
231
232static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
233{
234 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
235}
236
237static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
238{
239 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
240}
241
242static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
243{
244 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
245}
246
247static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
248{
249 return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
250}
251
252static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
253{
254 return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
255}
256
257static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
258 unsigned int size)
259{
260 rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
261 rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
262}
263
264static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
265{
266 rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
267}
268
269static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
270 dma_addr_t addr)
271{
272 rxdes->rxdes2 = cpu_to_le32(addr);
273}
274
275static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
276{
277 return le32_to_cpu(rxdes->rxdes2);
278}
279
280/*
281 * rxdes3 is not used by hardware. We use it to keep track of page.
282 * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
283 */
284static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
285{
286 rxdes->rxdes3 = (unsigned int)page;
287}
288
289static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
290{
291 return (struct page *)rxdes->rxdes3;
292}
293
294/******************************************************************************
295 * internal functions (receive)
296 *****************************************************************************/
297static int ftmac100_next_rx_pointer(int pointer)
298{
299 return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
300}
301
302static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
303{
304 priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
305}
306
307static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
308{
309 return &priv->descs->rxdes[priv->rx_pointer];
310}
311
312static struct ftmac100_rxdes *
313ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
314{
315 struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
316
317 while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
318 if (ftmac100_rxdes_first_segment(rxdes))
319 return rxdes;
320
321 ftmac100_rxdes_set_dma_own(rxdes);
322 ftmac100_rx_pointer_advance(priv);
323 rxdes = ftmac100_current_rxdes(priv);
324 }
325
326 return NULL;
327}
328
329static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
330 struct ftmac100_rxdes *rxdes)
331{
332 struct net_device *netdev = priv->netdev;
333 bool error = false;
334
335 if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
336 if (net_ratelimit())
337 netdev_info(netdev, "rx err\n");
338
339 netdev->stats.rx_errors++;
340 error = true;
341 }
342
343 if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
344 if (net_ratelimit())
345 netdev_info(netdev, "rx crc err\n");
346
347 netdev->stats.rx_crc_errors++;
348 error = true;
349 }
350
351 if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
352 if (net_ratelimit())
353 netdev_info(netdev, "rx frame too long\n");
354
355 netdev->stats.rx_length_errors++;
356 error = true;
357 } else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
358 if (net_ratelimit())
359 netdev_info(netdev, "rx runt\n");
360
361 netdev->stats.rx_length_errors++;
362 error = true;
363 } else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
364 if (net_ratelimit())
365 netdev_info(netdev, "rx odd nibble\n");
366
367 netdev->stats.rx_length_errors++;
368 error = true;
369 }
370
371 return error;
372}
373
374static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
375{
376 struct net_device *netdev = priv->netdev;
377 struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
378 bool done = false;
379
380 if (net_ratelimit())
381 netdev_dbg(netdev, "drop packet %p\n", rxdes);
382
383 do {
384 if (ftmac100_rxdes_last_segment(rxdes))
385 done = true;
386
387 ftmac100_rxdes_set_dma_own(rxdes);
388 ftmac100_rx_pointer_advance(priv);
389 rxdes = ftmac100_current_rxdes(priv);
390 } while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
391
392 netdev->stats.rx_dropped++;
393}
394
395static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
396{
397 struct net_device *netdev = priv->netdev;
398 struct ftmac100_rxdes *rxdes;
399 struct sk_buff *skb;
400 struct page *page;
401 dma_addr_t map;
402 int length;
403
404 rxdes = ftmac100_rx_locate_first_segment(priv);
405 if (!rxdes)
406 return false;
407
408 if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
409 ftmac100_rx_drop_packet(priv);
410 return true;
411 }
412
413 /*
414 * It is impossible to get multi-segment packets
415 * because we always provide big enough receive buffers.
416 */
417 if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
418 BUG();
419
420 /* start processing */
421 skb = netdev_alloc_skb_ip_align(netdev, 128);
422 if (unlikely(!skb)) {
423 if (net_ratelimit())
424 netdev_err(netdev, "rx skb alloc failed\n");
425
426 ftmac100_rx_drop_packet(priv);
427 return true;
428 }
429
430 if (unlikely(ftmac100_rxdes_multicast(rxdes)))
431 netdev->stats.multicast++;
432
433 map = ftmac100_rxdes_get_dma_addr(rxdes);
434 dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
435
436 length = ftmac100_rxdes_frame_length(rxdes);
437 page = ftmac100_rxdes_get_page(rxdes);
438 skb_fill_page_desc(skb, 0, page, 0, length);
439 skb->len += length;
440 skb->data_len += length;
441 skb->truesize += length;
442 __pskb_pull_tail(skb, min(length, 64));
443
444 ftmac100_alloc_rx_page(priv, rxdes);
445
446 ftmac100_rx_pointer_advance(priv);
447
448 skb->protocol = eth_type_trans(skb, netdev);
449
450 netdev->stats.rx_packets++;
451 netdev->stats.rx_bytes += skb->len;
452
453 /* push packet to protocol stack */
454 netif_receive_skb(skb);
455
456 (*processed)++;
457 return true;
458}
459
460/******************************************************************************
461 * internal functions (transmit descriptor)
462 *****************************************************************************/
463static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
464{
465 /* clear all except end of ring bit */
466 txdes->txdes0 = 0;
467 txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
468 txdes->txdes2 = 0;
469 txdes->txdes3 = 0;
470}
471
472static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
473{
474 return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
475}
476
477static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
478{
479 /*
480 * Make sure dma own bit will not be set before any other
481 * descriptor fields.
482 */
483 wmb();
484 txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
485}
486
487static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
488{
489 return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
490}
491
492static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
493{
494 return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
495}
496
497static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
498{
499 txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
500}
501
502static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
503{
504 txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
505}
506
507static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
508{
509 txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
510}
511
512static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
513{
514 txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
515}
516
517static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
518 unsigned int len)
519{
520 txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
521}
522
523static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
524 dma_addr_t addr)
525{
526 txdes->txdes2 = cpu_to_le32(addr);
527}
528
529static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
530{
531 return le32_to_cpu(txdes->txdes2);
532}
533
534/*
535 * txdes3 is not used by hardware. We use it to keep track of socket buffer.
536 * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
537 */
538static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
539{
540 txdes->txdes3 = (unsigned int)skb;
541}
542
543static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
544{
545 return (struct sk_buff *)txdes->txdes3;
546}
547
548/******************************************************************************
549 * internal functions (transmit)
550 *****************************************************************************/
551static int ftmac100_next_tx_pointer(int pointer)
552{
553 return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
554}
555
556static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
557{
558 priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
559}
560
561static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
562{
563 priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
564}
565
566static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
567{
568 return &priv->descs->txdes[priv->tx_pointer];
569}
570
571static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
572{
573 return &priv->descs->txdes[priv->tx_clean_pointer];
574}
575
576static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
577{
578 struct net_device *netdev = priv->netdev;
579 struct ftmac100_txdes *txdes;
580 struct sk_buff *skb;
581 dma_addr_t map;
582
583 if (priv->tx_pending == 0)
584 return false;
585
586 txdes = ftmac100_current_clean_txdes(priv);
587
588 if (ftmac100_txdes_owned_by_dma(txdes))
589 return false;
590
591 skb = ftmac100_txdes_get_skb(txdes);
592 map = ftmac100_txdes_get_dma_addr(txdes);
593
594 if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
595 ftmac100_txdes_late_collision(txdes))) {
596 /*
597 * packet transmitted to ethernet lost due to late collision
598 * or excessive collision
599 */
600 netdev->stats.tx_aborted_errors++;
601 } else {
602 netdev->stats.tx_packets++;
603 netdev->stats.tx_bytes += skb->len;
604 }
605
606 dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
607 dev_kfree_skb(skb);
608
609 ftmac100_txdes_reset(txdes);
610
611 ftmac100_tx_clean_pointer_advance(priv);
612
613 spin_lock(&priv->tx_lock);
614 priv->tx_pending--;
615 spin_unlock(&priv->tx_lock);
616 netif_wake_queue(netdev);
617
618 return true;
619}
620
621static void ftmac100_tx_complete(struct ftmac100 *priv)
622{
623 while (ftmac100_tx_complete_packet(priv))
624 ;
625}
626
627static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
628 dma_addr_t map)
629{
630 struct net_device *netdev = priv->netdev;
631 struct ftmac100_txdes *txdes;
632 unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
633
634 txdes = ftmac100_current_txdes(priv);
635 ftmac100_tx_pointer_advance(priv);
636
637 /* setup TX descriptor */
638 ftmac100_txdes_set_skb(txdes, skb);
639 ftmac100_txdes_set_dma_addr(txdes, map);
640
641 ftmac100_txdes_set_first_segment(txdes);
642 ftmac100_txdes_set_last_segment(txdes);
643 ftmac100_txdes_set_txint(txdes);
644 ftmac100_txdes_set_buffer_size(txdes, len);
645
646 spin_lock(&priv->tx_lock);
647 priv->tx_pending++;
648 if (priv->tx_pending == TX_QUEUE_ENTRIES)
649 netif_stop_queue(netdev);
650
651 /* start transmit */
652 ftmac100_txdes_set_dma_own(txdes);
653 spin_unlock(&priv->tx_lock);
654
655 ftmac100_txdma_start_polling(priv);
656 return NETDEV_TX_OK;
657}
658
659/******************************************************************************
660 * internal functions (buffer)
661 *****************************************************************************/
662static int ftmac100_alloc_rx_page(struct ftmac100 *priv, struct ftmac100_rxdes *rxdes)
663{
664 struct net_device *netdev = priv->netdev;
665 struct page *page;
666 dma_addr_t map;
667
668 page = alloc_page(GFP_KERNEL);
669 if (!page) {
670 if (net_ratelimit())
671 netdev_err(netdev, "failed to allocate rx page\n");
672 return -ENOMEM;
673 }
674
675 map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
676 if (unlikely(dma_mapping_error(priv->dev, map))) {
677 if (net_ratelimit())
678 netdev_err(netdev, "failed to map rx page\n");
679 __free_page(page);
680 return -ENOMEM;
681 }
682
683 ftmac100_rxdes_set_page(rxdes, page);
684 ftmac100_rxdes_set_dma_addr(rxdes, map);
685 ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
686 ftmac100_rxdes_set_dma_own(rxdes);
687 return 0;
688}
689
690static void ftmac100_free_buffers(struct ftmac100 *priv)
691{
692 int i;
693
694 for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
695 struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
696 struct page *page = ftmac100_rxdes_get_page(rxdes);
697 dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
698
699 if (!page)
700 continue;
701
702 dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
703 __free_page(page);
704 }
705
706 for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
707 struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
708 struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
709 dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
710
711 if (!skb)
712 continue;
713
714 dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
715 dev_kfree_skb(skb);
716 }
717
718 dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
719 priv->descs, priv->descs_dma_addr);
720}
721
722static int ftmac100_alloc_buffers(struct ftmac100 *priv)
723{
724 int i;
725
726 priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
727 &priv->descs_dma_addr, GFP_KERNEL);
728 if (!priv->descs)
729 return -ENOMEM;
730
731 memset(priv->descs, 0, sizeof(struct ftmac100_descs));
732
733 /* initialize RX ring */
734 ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
735
736 for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
737 struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
738
739 if (ftmac100_alloc_rx_page(priv, rxdes))
740 goto err;
741 }
742
743 /* initialize TX ring */
744 ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
745 return 0;
746
747err:
748 ftmac100_free_buffers(priv);
749 return -ENOMEM;
750}
751
752/******************************************************************************
753 * struct mii_if_info functions
754 *****************************************************************************/
755static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
756{
757 struct ftmac100 *priv = netdev_priv(netdev);
758 unsigned int phycr;
759 int i;
760
761 phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
762 FTMAC100_PHYCR_REGAD(reg) |
763 FTMAC100_PHYCR_MIIRD;
764
765 iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
766
767 for (i = 0; i < 10; i++) {
768 phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
769
770 if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
771 return phycr & FTMAC100_PHYCR_MIIRDATA;
772
773 usleep_range(100, 1000);
774 }
775
776 netdev_err(netdev, "mdio read timed out\n");
777 return 0;
778}
779
780static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
781 int data)
782{
783 struct ftmac100 *priv = netdev_priv(netdev);
784 unsigned int phycr;
785 int i;
786
787 phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
788 FTMAC100_PHYCR_REGAD(reg) |
789 FTMAC100_PHYCR_MIIWR;
790
791 data = FTMAC100_PHYWDATA_MIIWDATA(data);
792
793 iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
794 iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
795
796 for (i = 0; i < 10; i++) {
797 phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
798
799 if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
800 return;
801
802 usleep_range(100, 1000);
803 }
804
805 netdev_err(netdev, "mdio write timed out\n");
806}
807
808/******************************************************************************
809 * struct ethtool_ops functions
810 *****************************************************************************/
811static void ftmac100_get_drvinfo(struct net_device *netdev,
812 struct ethtool_drvinfo *info)
813{
814 strcpy(info->driver, DRV_NAME);
815 strcpy(info->version, DRV_VERSION);
816 strcpy(info->bus_info, dev_name(&netdev->dev));
817}
818
819static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
820{
821 struct ftmac100 *priv = netdev_priv(netdev);
822 return mii_ethtool_gset(&priv->mii, cmd);
823}
824
825static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
826{
827 struct ftmac100 *priv = netdev_priv(netdev);
828 return mii_ethtool_sset(&priv->mii, cmd);
829}
830
831static int ftmac100_nway_reset(struct net_device *netdev)
832{
833 struct ftmac100 *priv = netdev_priv(netdev);
834 return mii_nway_restart(&priv->mii);
835}
836
837static u32 ftmac100_get_link(struct net_device *netdev)
838{
839 struct ftmac100 *priv = netdev_priv(netdev);
840 return mii_link_ok(&priv->mii);
841}
842
843static const struct ethtool_ops ftmac100_ethtool_ops = {
844 .set_settings = ftmac100_set_settings,
845 .get_settings = ftmac100_get_settings,
846 .get_drvinfo = ftmac100_get_drvinfo,
847 .nway_reset = ftmac100_nway_reset,
848 .get_link = ftmac100_get_link,
849};
850
851/******************************************************************************
852 * interrupt handler
853 *****************************************************************************/
854static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
855{
856 struct net_device *netdev = dev_id;
857 struct ftmac100 *priv = netdev_priv(netdev);
858
859 if (likely(netif_running(netdev))) {
860 /* Disable interrupts for polling */
861 ftmac100_disable_all_int(priv);
862 napi_schedule(&priv->napi);
863 }
864
865 return IRQ_HANDLED;
866}
867
868/******************************************************************************
869 * struct napi_struct functions
870 *****************************************************************************/
871static int ftmac100_poll(struct napi_struct *napi, int budget)
872{
873 struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
874 struct net_device *netdev = priv->netdev;
875 unsigned int status;
876 bool completed = true;
877 int rx = 0;
878
879 status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
880
881 if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
882 /*
883 * FTMAC100_INT_RPKT_FINISH:
884 * RX DMA has received packets into RX buffer successfully
885 *
886 * FTMAC100_INT_NORXBUF:
887 * RX buffer unavailable
888 */
889 bool retry;
890
891 do {
892 retry = ftmac100_rx_packet(priv, &rx);
893 } while (retry && rx < budget);
894
895 if (retry && rx == budget)
896 completed = false;
897 }
898
899 if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
900 /*
901 * FTMAC100_INT_XPKT_OK:
902 * packet transmitted to ethernet successfully
903 *
904 * FTMAC100_INT_XPKT_LOST:
905 * packet transmitted to ethernet lost due to late
906 * collision or excessive collision
907 */
908 ftmac100_tx_complete(priv);
909 }
910
911 if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
912 FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
913 if (net_ratelimit())
914 netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
915 status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
916 status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
917 status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
918 status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
919
920 if (status & FTMAC100_INT_NORXBUF) {
921 /* RX buffer unavailable */
922 netdev->stats.rx_over_errors++;
923 }
924
925 if (status & FTMAC100_INT_RPKT_LOST) {
926 /* received packet lost due to RX FIFO full */
927 netdev->stats.rx_fifo_errors++;
928 }
929
930 if (status & FTMAC100_INT_PHYSTS_CHG) {
931 /* PHY link status change */
932 mii_check_link(&priv->mii);
933 }
934 }
935
936 if (completed) {
937 /* stop polling */
938 napi_complete(napi);
939 ftmac100_enable_all_int(priv);
940 }
941
942 return rx;
943}
944
945/******************************************************************************
946 * struct net_device_ops functions
947 *****************************************************************************/
948static int ftmac100_open(struct net_device *netdev)
949{
950 struct ftmac100 *priv = netdev_priv(netdev);
951 int err;
952
953 err = ftmac100_alloc_buffers(priv);
954 if (err) {
955 netdev_err(netdev, "failed to allocate buffers\n");
956 goto err_alloc;
957 }
958
959 err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
960 if (err) {
961 netdev_err(netdev, "failed to request irq %d\n", priv->irq);
962 goto err_irq;
963 }
964
965 priv->rx_pointer = 0;
966 priv->tx_clean_pointer = 0;
967 priv->tx_pointer = 0;
968 priv->tx_pending = 0;
969
970 err = ftmac100_start_hw(priv);
971 if (err)
972 goto err_hw;
973
974 napi_enable(&priv->napi);
975 netif_start_queue(netdev);
976
977 ftmac100_enable_all_int(priv);
978
979 return 0;
980
981err_hw:
982 free_irq(priv->irq, netdev);
983err_irq:
984 ftmac100_free_buffers(priv);
985err_alloc:
986 return err;
987}
988
989static int ftmac100_stop(struct net_device *netdev)
990{
991 struct ftmac100 *priv = netdev_priv(netdev);
992
993 ftmac100_disable_all_int(priv);
994 netif_stop_queue(netdev);
995 napi_disable(&priv->napi);
996 ftmac100_stop_hw(priv);
997 free_irq(priv->irq, netdev);
998 ftmac100_free_buffers(priv);
999
1000 return 0;
1001}
1002
1003static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
1004{
1005 struct ftmac100 *priv = netdev_priv(netdev);
1006 dma_addr_t map;
1007
1008 if (unlikely(skb->len > MAX_PKT_SIZE)) {
1009 if (net_ratelimit())
1010 netdev_dbg(netdev, "tx packet too big\n");
1011
1012 netdev->stats.tx_dropped++;
1013 dev_kfree_skb(skb);
1014 return NETDEV_TX_OK;
1015 }
1016
1017 map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
1018 if (unlikely(dma_mapping_error(priv->dev, map))) {
1019 /* drop packet */
1020 if (net_ratelimit())
1021 netdev_err(netdev, "map socket buffer failed\n");
1022
1023 netdev->stats.tx_dropped++;
1024 dev_kfree_skb(skb);
1025 return NETDEV_TX_OK;
1026 }
1027
1028 return ftmac100_xmit(priv, skb, map);
1029}
1030
1031/* optional */
1032static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
1033{
1034 struct ftmac100 *priv = netdev_priv(netdev);
1035 struct mii_ioctl_data *data = if_mii(ifr);
1036
1037 return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
1038}
1039
1040static const struct net_device_ops ftmac100_netdev_ops = {
1041 .ndo_open = ftmac100_open,
1042 .ndo_stop = ftmac100_stop,
1043 .ndo_start_xmit = ftmac100_hard_start_xmit,
1044 .ndo_set_mac_address = eth_mac_addr,
1045 .ndo_validate_addr = eth_validate_addr,
1046 .ndo_do_ioctl = ftmac100_do_ioctl,
1047};
1048
1049/******************************************************************************
1050 * struct platform_driver functions
1051 *****************************************************************************/
1052static int ftmac100_probe(struct platform_device *pdev)
1053{
1054 struct resource *res;
1055 int irq;
1056 struct net_device *netdev;
1057 struct ftmac100 *priv;
1058 int err;
1059
1060 if (!pdev)
1061 return -ENODEV;
1062
1063 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1064 if (!res)
1065 return -ENXIO;
1066
1067 irq = platform_get_irq(pdev, 0);
1068 if (irq < 0)
1069 return irq;
1070
1071 /* setup net_device */
1072 netdev = alloc_etherdev(sizeof(*priv));
1073 if (!netdev) {
1074 err = -ENOMEM;
1075 goto err_alloc_etherdev;
1076 }
1077
1078 SET_NETDEV_DEV(netdev, &pdev->dev);
1079 SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
1080 netdev->netdev_ops = &ftmac100_netdev_ops;
1081
1082 platform_set_drvdata(pdev, netdev);
1083
1084 /* setup private data */
1085 priv = netdev_priv(netdev);
1086 priv->netdev = netdev;
1087 priv->dev = &pdev->dev;
1088
1089 spin_lock_init(&priv->tx_lock);
1090
1091 /* initialize NAPI */
1092 netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
1093
1094 /* map io memory */
1095 priv->res = request_mem_region(res->start, resource_size(res),
1096 dev_name(&pdev->dev));
1097 if (!priv->res) {
1098 dev_err(&pdev->dev, "Could not reserve memory region\n");
1099 err = -ENOMEM;
1100 goto err_req_mem;
1101 }
1102
1103 priv->base = ioremap(res->start, res->end - res->start);
1104 if (!priv->base) {
1105 dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
1106 err = -EIO;
1107 goto err_ioremap;
1108 }
1109
1110 priv->irq = irq;
1111
1112 /* initialize struct mii_if_info */
1113 priv->mii.phy_id = 0;
1114 priv->mii.phy_id_mask = 0x1f;
1115 priv->mii.reg_num_mask = 0x1f;
1116 priv->mii.dev = netdev;
1117 priv->mii.mdio_read = ftmac100_mdio_read;
1118 priv->mii.mdio_write = ftmac100_mdio_write;
1119
1120 /* register network device */
1121 err = register_netdev(netdev);
1122 if (err) {
1123 dev_err(&pdev->dev, "Failed to register netdev\n");
1124 goto err_register_netdev;
1125 }
1126
1127 netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
1128
1129 if (!is_valid_ether_addr(netdev->dev_addr)) {
1130 random_ether_addr(netdev->dev_addr);
1131 netdev_info(netdev, "generated random MAC address %pM\n",
1132 netdev->dev_addr);
1133 }
1134
1135 return 0;
1136
1137err_register_netdev:
1138 iounmap(priv->base);
1139err_ioremap:
1140 release_resource(priv->res);
1141err_req_mem:
1142 netif_napi_del(&priv->napi);
1143 platform_set_drvdata(pdev, NULL);
1144 free_netdev(netdev);
1145err_alloc_etherdev:
1146 return err;
1147}
1148
1149static int __exit ftmac100_remove(struct platform_device *pdev)
1150{
1151 struct net_device *netdev;
1152 struct ftmac100 *priv;
1153
1154 netdev = platform_get_drvdata(pdev);
1155 priv = netdev_priv(netdev);
1156
1157 unregister_netdev(netdev);
1158
1159 iounmap(priv->base);
1160 release_resource(priv->res);
1161
1162 netif_napi_del(&priv->napi);
1163 platform_set_drvdata(pdev, NULL);
1164 free_netdev(netdev);
1165 return 0;
1166}
1167
1168static struct platform_driver ftmac100_driver = {
1169 .probe = ftmac100_probe,
1170 .remove = __exit_p(ftmac100_remove),
1171 .driver = {
1172 .name = DRV_NAME,
1173 .owner = THIS_MODULE,
1174 },
1175};
1176
1177/******************************************************************************
1178 * initialization / finalization
1179 *****************************************************************************/
1180static int __init ftmac100_init(void)
1181{
1182 pr_info("Loading version " DRV_VERSION " ...\n");
1183 return platform_driver_register(&ftmac100_driver);
1184}
1185
1186static void __exit ftmac100_exit(void)
1187{
1188 platform_driver_unregister(&ftmac100_driver);
1189}
1190
1191module_init(ftmac100_init);
1192module_exit(ftmac100_exit);
1193
1194MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
1195MODULE_DESCRIPTION("FTMAC100 driver");
1196MODULE_LICENSE("GPL");
diff --git a/drivers/net/ftmac100.h b/drivers/net/ftmac100.h
new file mode 100644
index 000000000000..46a0c47b1ee1
--- /dev/null
+++ b/drivers/net/ftmac100.h
@@ -0,0 +1,180 @@
1/*
2 * Faraday FTMAC100 10/100 Ethernet
3 *
4 * (C) Copyright 2009-2011 Faraday Technology
5 * Po-Yu Chuang <ratbert@faraday-tech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#ifndef __FTMAC100_H
23#define __FTMAC100_H
24
25#define FTMAC100_OFFSET_ISR 0x00
26#define FTMAC100_OFFSET_IMR 0x04
27#define FTMAC100_OFFSET_MAC_MADR 0x08
28#define FTMAC100_OFFSET_MAC_LADR 0x0c
29#define FTMAC100_OFFSET_MAHT0 0x10
30#define FTMAC100_OFFSET_MAHT1 0x14
31#define FTMAC100_OFFSET_TXPD 0x18
32#define FTMAC100_OFFSET_RXPD 0x1c
33#define FTMAC100_OFFSET_TXR_BADR 0x20
34#define FTMAC100_OFFSET_RXR_BADR 0x24
35#define FTMAC100_OFFSET_ITC 0x28
36#define FTMAC100_OFFSET_APTC 0x2c
37#define FTMAC100_OFFSET_DBLAC 0x30
38#define FTMAC100_OFFSET_MACCR 0x88
39#define FTMAC100_OFFSET_MACSR 0x8c
40#define FTMAC100_OFFSET_PHYCR 0x90
41#define FTMAC100_OFFSET_PHYWDATA 0x94
42#define FTMAC100_OFFSET_FCR 0x98
43#define FTMAC100_OFFSET_BPR 0x9c
44#define FTMAC100_OFFSET_TS 0xc4
45#define FTMAC100_OFFSET_DMAFIFOS 0xc8
46#define FTMAC100_OFFSET_TM 0xcc
47#define FTMAC100_OFFSET_TX_MCOL_SCOL 0xd4
48#define FTMAC100_OFFSET_RPF_AEP 0xd8
49#define FTMAC100_OFFSET_XM_PG 0xdc
50#define FTMAC100_OFFSET_RUNT_TLCC 0xe0
51#define FTMAC100_OFFSET_CRCER_FTL 0xe4
52#define FTMAC100_OFFSET_RLC_RCC 0xe8
53#define FTMAC100_OFFSET_BROC 0xec
54#define FTMAC100_OFFSET_MULCA 0xf0
55#define FTMAC100_OFFSET_RP 0xf4
56#define FTMAC100_OFFSET_XP 0xf8
57
58/*
59 * Interrupt status register & interrupt mask register
60 */
61#define FTMAC100_INT_RPKT_FINISH (1 << 0)
62#define FTMAC100_INT_NORXBUF (1 << 1)
63#define FTMAC100_INT_XPKT_FINISH (1 << 2)
64#define FTMAC100_INT_NOTXBUF (1 << 3)
65#define FTMAC100_INT_XPKT_OK (1 << 4)
66#define FTMAC100_INT_XPKT_LOST (1 << 5)
67#define FTMAC100_INT_RPKT_SAV (1 << 6)
68#define FTMAC100_INT_RPKT_LOST (1 << 7)
69#define FTMAC100_INT_AHB_ERR (1 << 8)
70#define FTMAC100_INT_PHYSTS_CHG (1 << 9)
71
72/*
73 * Interrupt timer control register
74 */
75#define FTMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
76#define FTMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
77#define FTMAC100_ITC_RXINT_TIME_SEL (1 << 7)
78#define FTMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
79#define FTMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
80#define FTMAC100_ITC_TXINT_TIME_SEL (1 << 15)
81
82/*
83 * Automatic polling timer control register
84 */
85#define FTMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
86#define FTMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
87#define FTMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
88#define FTMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
89
90/*
91 * DMA burst length and arbitration control register
92 */
93#define FTMAC100_DBLAC_INCR4_EN (1 << 0)
94#define FTMAC100_DBLAC_INCR8_EN (1 << 1)
95#define FTMAC100_DBLAC_INCR16_EN (1 << 2)
96#define FTMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 3)
97#define FTMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 6)
98#define FTMAC100_DBLAC_RX_THR_EN (1 << 9)
99
100/*
101 * MAC control register
102 */
103#define FTMAC100_MACCR_XDMA_EN (1 << 0)
104#define FTMAC100_MACCR_RDMA_EN (1 << 1)
105#define FTMAC100_MACCR_SW_RST (1 << 2)
106#define FTMAC100_MACCR_LOOP_EN (1 << 3)
107#define FTMAC100_MACCR_CRC_DIS (1 << 4)
108#define FTMAC100_MACCR_XMT_EN (1 << 5)
109#define FTMAC100_MACCR_ENRX_IN_HALFTX (1 << 6)
110#define FTMAC100_MACCR_RCV_EN (1 << 8)
111#define FTMAC100_MACCR_HT_MULTI_EN (1 << 9)
112#define FTMAC100_MACCR_RX_RUNT (1 << 10)
113#define FTMAC100_MACCR_RX_FTL (1 << 11)
114#define FTMAC100_MACCR_RCV_ALL (1 << 12)
115#define FTMAC100_MACCR_CRC_APD (1 << 14)
116#define FTMAC100_MACCR_FULLDUP (1 << 15)
117#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
118#define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
119
120/*
121 * PHY control register
122 */
123#define FTMAC100_PHYCR_MIIRDATA 0xffff
124#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
125#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
126#define FTMAC100_PHYCR_MIIRD (1 << 26)
127#define FTMAC100_PHYCR_MIIWR (1 << 27)
128
129/*
130 * PHY write data register
131 */
132#define FTMAC100_PHYWDATA_MIIWDATA(x) ((x) & 0xffff)
133
134/*
135 * Transmit descriptor, aligned to 16 bytes
136 */
137struct ftmac100_txdes {
138 unsigned int txdes0;
139 unsigned int txdes1;
140 unsigned int txdes2; /* TXBUF_BADR */
141 unsigned int txdes3; /* not used by HW */
142} __attribute__ ((aligned(16)));
143
144#define FTMAC100_TXDES0_TXPKT_LATECOL (1 << 0)
145#define FTMAC100_TXDES0_TXPKT_EXSCOL (1 << 1)
146#define FTMAC100_TXDES0_TXDMA_OWN (1 << 31)
147
148#define FTMAC100_TXDES1_TXBUF_SIZE(x) ((x) & 0x7ff)
149#define FTMAC100_TXDES1_LTS (1 << 27)
150#define FTMAC100_TXDES1_FTS (1 << 28)
151#define FTMAC100_TXDES1_TX2FIC (1 << 29)
152#define FTMAC100_TXDES1_TXIC (1 << 30)
153#define FTMAC100_TXDES1_EDOTR (1 << 31)
154
155/*
156 * Receive descriptor, aligned to 16 bytes
157 */
158struct ftmac100_rxdes {
159 unsigned int rxdes0;
160 unsigned int rxdes1;
161 unsigned int rxdes2; /* RXBUF_BADR */
162 unsigned int rxdes3; /* not used by HW */
163} __attribute__ ((aligned(16)));
164
165#define FTMAC100_RXDES0_RFL 0x7ff
166#define FTMAC100_RXDES0_MULTICAST (1 << 16)
167#define FTMAC100_RXDES0_BROADCAST (1 << 17)
168#define FTMAC100_RXDES0_RX_ERR (1 << 18)
169#define FTMAC100_RXDES0_CRC_ERR (1 << 19)
170#define FTMAC100_RXDES0_FTL (1 << 20)
171#define FTMAC100_RXDES0_RUNT (1 << 21)
172#define FTMAC100_RXDES0_RX_ODD_NB (1 << 22)
173#define FTMAC100_RXDES0_LRS (1 << 28)
174#define FTMAC100_RXDES0_FRS (1 << 29)
175#define FTMAC100_RXDES0_RXDMA_OWN (1 << 31)
176
177#define FTMAC100_RXDES1_RXBUF_SIZE(x) ((x) & 0x7ff)
178#define FTMAC100_RXDES1_EDORR (1 << 31)
179
180#endif /* __FTMAC100_H */