174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2baf0fbfeSJeff Kirsher /*
3baf0fbfeSJeff Kirsher  * Faraday FTMAC100 10/100 Ethernet
4baf0fbfeSJeff Kirsher  *
5baf0fbfeSJeff Kirsher  * (C) Copyright 2009-2011 Faraday Technology
6baf0fbfeSJeff Kirsher  * Po-Yu Chuang <ratbert@faraday-tech.com>
7baf0fbfeSJeff Kirsher  */
8baf0fbfeSJeff Kirsher 
9baf0fbfeSJeff Kirsher #define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
10baf0fbfeSJeff Kirsher 
11baf0fbfeSJeff Kirsher #include <linux/dma-mapping.h>
12baf0fbfeSJeff Kirsher #include <linux/etherdevice.h>
13baf0fbfeSJeff Kirsher #include <linux/ethtool.h>
1437c84890SSergei Antonov #include <linux/if_ether.h>
1530f837b7SVladimir Oltean #include <linux/if_vlan.h>
16baf0fbfeSJeff Kirsher #include <linux/init.h>
1717f1bbcaSThomas Faber #include <linux/interrupt.h>
18baf0fbfeSJeff Kirsher #include <linux/io.h>
19baf0fbfeSJeff Kirsher #include <linux/mii.h>
20baf0fbfeSJeff Kirsher #include <linux/module.h>
21ac316725SRandy Dunlap #include <linux/mod_devicetable.h>
22baf0fbfeSJeff Kirsher #include <linux/netdevice.h>
23baf0fbfeSJeff Kirsher #include <linux/platform_device.h>
24baf0fbfeSJeff Kirsher 
25baf0fbfeSJeff Kirsher #include "ftmac100.h"
26baf0fbfeSJeff Kirsher 
27baf0fbfeSJeff Kirsher #define DRV_NAME	"ftmac100"
28baf0fbfeSJeff Kirsher 
29baf0fbfeSJeff Kirsher #define RX_QUEUE_ENTRIES	128	/* must be power of 2 */
30baf0fbfeSJeff Kirsher #define TX_QUEUE_ENTRIES	16	/* must be power of 2 */
31baf0fbfeSJeff Kirsher 
32baf0fbfeSJeff Kirsher #define RX_BUF_SIZE		2044	/* must be smaller than 0x7ff */
3337c84890SSergei Antonov #define MAX_PKT_SIZE		RX_BUF_SIZE /* multi-segment not supported */
34baf0fbfeSJeff Kirsher 
35baf0fbfeSJeff Kirsher #if MAX_PKT_SIZE > 0x7ff
36baf0fbfeSJeff Kirsher #error invalid MAX_PKT_SIZE
37baf0fbfeSJeff Kirsher #endif
38baf0fbfeSJeff Kirsher 
39baf0fbfeSJeff Kirsher #if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
40baf0fbfeSJeff Kirsher #error invalid RX_BUF_SIZE
41baf0fbfeSJeff Kirsher #endif
42baf0fbfeSJeff Kirsher 
43baf0fbfeSJeff Kirsher /******************************************************************************
44baf0fbfeSJeff Kirsher  * private data
45baf0fbfeSJeff Kirsher  *****************************************************************************/
46baf0fbfeSJeff Kirsher struct ftmac100_descs {
47baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
48baf0fbfeSJeff Kirsher 	struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
49baf0fbfeSJeff Kirsher };
50baf0fbfeSJeff Kirsher 
51baf0fbfeSJeff Kirsher struct ftmac100 {
52baf0fbfeSJeff Kirsher 	struct resource *res;
53baf0fbfeSJeff Kirsher 	void __iomem *base;
54baf0fbfeSJeff Kirsher 	int irq;
55baf0fbfeSJeff Kirsher 
56baf0fbfeSJeff Kirsher 	struct ftmac100_descs *descs;
57baf0fbfeSJeff Kirsher 	dma_addr_t descs_dma_addr;
58baf0fbfeSJeff Kirsher 
59baf0fbfeSJeff Kirsher 	unsigned int rx_pointer;
60baf0fbfeSJeff Kirsher 	unsigned int tx_clean_pointer;
61baf0fbfeSJeff Kirsher 	unsigned int tx_pointer;
62baf0fbfeSJeff Kirsher 	unsigned int tx_pending;
63baf0fbfeSJeff Kirsher 
64baf0fbfeSJeff Kirsher 	spinlock_t tx_lock;
65baf0fbfeSJeff Kirsher 
66baf0fbfeSJeff Kirsher 	struct net_device *netdev;
67baf0fbfeSJeff Kirsher 	struct device *dev;
68baf0fbfeSJeff Kirsher 	struct napi_struct napi;
69baf0fbfeSJeff Kirsher 
70baf0fbfeSJeff Kirsher 	struct mii_if_info mii;
71baf0fbfeSJeff Kirsher };
72baf0fbfeSJeff Kirsher 
73baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
74baf0fbfeSJeff Kirsher 				  struct ftmac100_rxdes *rxdes, gfp_t gfp);
75baf0fbfeSJeff Kirsher 
76baf0fbfeSJeff Kirsher /******************************************************************************
77baf0fbfeSJeff Kirsher  * internal functions (hardware register access)
78baf0fbfeSJeff Kirsher  *****************************************************************************/
79baf0fbfeSJeff Kirsher #define INT_MASK_ALL_ENABLED	(FTMAC100_INT_RPKT_FINISH	| \
80baf0fbfeSJeff Kirsher 				 FTMAC100_INT_NORXBUF		| \
81baf0fbfeSJeff Kirsher 				 FTMAC100_INT_XPKT_OK		| \
82baf0fbfeSJeff Kirsher 				 FTMAC100_INT_XPKT_LOST		| \
83baf0fbfeSJeff Kirsher 				 FTMAC100_INT_RPKT_LOST		| \
84baf0fbfeSJeff Kirsher 				 FTMAC100_INT_AHB_ERR		| \
85baf0fbfeSJeff Kirsher 				 FTMAC100_INT_PHYSTS_CHG)
86baf0fbfeSJeff Kirsher 
87baf0fbfeSJeff Kirsher #define INT_MASK_ALL_DISABLED	0
88baf0fbfeSJeff Kirsher 
89baf0fbfeSJeff Kirsher static void ftmac100_enable_all_int(struct ftmac100 *priv)
90baf0fbfeSJeff Kirsher {
91baf0fbfeSJeff Kirsher 	iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
92baf0fbfeSJeff Kirsher }
93baf0fbfeSJeff Kirsher 
94baf0fbfeSJeff Kirsher static void ftmac100_disable_all_int(struct ftmac100 *priv)
95baf0fbfeSJeff Kirsher {
96baf0fbfeSJeff Kirsher 	iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
97baf0fbfeSJeff Kirsher }
98baf0fbfeSJeff Kirsher 
99baf0fbfeSJeff Kirsher static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
100baf0fbfeSJeff Kirsher {
101baf0fbfeSJeff Kirsher 	iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
102baf0fbfeSJeff Kirsher }
103baf0fbfeSJeff Kirsher 
104baf0fbfeSJeff Kirsher static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
105baf0fbfeSJeff Kirsher {
106baf0fbfeSJeff Kirsher 	iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
107baf0fbfeSJeff Kirsher }
108baf0fbfeSJeff Kirsher 
109baf0fbfeSJeff Kirsher static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
110baf0fbfeSJeff Kirsher {
111baf0fbfeSJeff Kirsher 	iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
112baf0fbfeSJeff Kirsher }
113baf0fbfeSJeff Kirsher 
114baf0fbfeSJeff Kirsher static int ftmac100_reset(struct ftmac100 *priv)
115baf0fbfeSJeff Kirsher {
116baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
117baf0fbfeSJeff Kirsher 	int i;
118baf0fbfeSJeff Kirsher 
119baf0fbfeSJeff Kirsher 	/* NOTE: reset clears all registers */
120baf0fbfeSJeff Kirsher 	iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
121baf0fbfeSJeff Kirsher 
122baf0fbfeSJeff Kirsher 	for (i = 0; i < 5; i++) {
123baf0fbfeSJeff Kirsher 		unsigned int maccr;
124baf0fbfeSJeff Kirsher 
125baf0fbfeSJeff Kirsher 		maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
126baf0fbfeSJeff Kirsher 		if (!(maccr & FTMAC100_MACCR_SW_RST)) {
127baf0fbfeSJeff Kirsher 			/*
128baf0fbfeSJeff Kirsher 			 * FTMAC100_MACCR_SW_RST cleared does not indicate
129baf0fbfeSJeff Kirsher 			 * that hardware reset completed (what the f*ck).
130baf0fbfeSJeff Kirsher 			 * We still need to wait for a while.
131baf0fbfeSJeff Kirsher 			 */
132baf0fbfeSJeff Kirsher 			udelay(500);
133baf0fbfeSJeff Kirsher 			return 0;
134baf0fbfeSJeff Kirsher 		}
135baf0fbfeSJeff Kirsher 
136baf0fbfeSJeff Kirsher 		udelay(1000);
137baf0fbfeSJeff Kirsher 	}
138baf0fbfeSJeff Kirsher 
139baf0fbfeSJeff Kirsher 	netdev_err(netdev, "software reset failed\n");
140baf0fbfeSJeff Kirsher 	return -EIO;
141baf0fbfeSJeff Kirsher }
142baf0fbfeSJeff Kirsher 
143baf0fbfeSJeff Kirsher static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
144baf0fbfeSJeff Kirsher {
145baf0fbfeSJeff Kirsher 	unsigned int maddr = mac[0] << 8 | mac[1];
146baf0fbfeSJeff Kirsher 	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
147baf0fbfeSJeff Kirsher 
148baf0fbfeSJeff Kirsher 	iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
149baf0fbfeSJeff Kirsher 	iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
150baf0fbfeSJeff Kirsher }
151baf0fbfeSJeff Kirsher 
152baf0fbfeSJeff Kirsher #define MACCR_ENABLE_ALL	(FTMAC100_MACCR_XMT_EN	| \
153baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RCV_EN	| \
154baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_XDMA_EN	| \
155baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RDMA_EN	| \
156baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_CRC_APD	| \
157baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_FULLDUP	| \
158baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RX_RUNT	| \
159baf0fbfeSJeff Kirsher 				 FTMAC100_MACCR_RX_BROADPKT)
160baf0fbfeSJeff Kirsher 
161baf0fbfeSJeff Kirsher static int ftmac100_start_hw(struct ftmac100 *priv)
162baf0fbfeSJeff Kirsher {
163baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
16437c84890SSergei Antonov 	unsigned int maccr = MACCR_ENABLE_ALL;
165baf0fbfeSJeff Kirsher 
166baf0fbfeSJeff Kirsher 	if (ftmac100_reset(priv))
167baf0fbfeSJeff Kirsher 		return -EIO;
168baf0fbfeSJeff Kirsher 
169baf0fbfeSJeff Kirsher 	/* setup ring buffer base registers */
170baf0fbfeSJeff Kirsher 	ftmac100_set_rx_ring_base(priv,
171baf0fbfeSJeff Kirsher 				  priv->descs_dma_addr +
172baf0fbfeSJeff Kirsher 				  offsetof(struct ftmac100_descs, rxdes));
173baf0fbfeSJeff Kirsher 	ftmac100_set_tx_ring_base(priv,
174baf0fbfeSJeff Kirsher 				  priv->descs_dma_addr +
175baf0fbfeSJeff Kirsher 				  offsetof(struct ftmac100_descs, txdes));
176baf0fbfeSJeff Kirsher 
177baf0fbfeSJeff Kirsher 	iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
178baf0fbfeSJeff Kirsher 
179baf0fbfeSJeff Kirsher 	ftmac100_set_mac(priv, netdev->dev_addr);
180baf0fbfeSJeff Kirsher 
18137c84890SSergei Antonov 	 /* See ftmac100_change_mtu() */
18237c84890SSergei Antonov 	if (netdev->mtu > ETH_DATA_LEN)
18337c84890SSergei Antonov 		maccr |= FTMAC100_MACCR_RX_FTL;
18437c84890SSergei Antonov 
185*75943bc9SSergei Antonov 	/* Add other bits as needed */
186*75943bc9SSergei Antonov 	if (netdev->flags & IFF_PROMISC)
187*75943bc9SSergei Antonov 		maccr |= FTMAC100_MACCR_RCV_ALL;
188*75943bc9SSergei Antonov 	if (netdev->flags & IFF_ALLMULTI)
189*75943bc9SSergei Antonov 		maccr |= FTMAC100_MACCR_RX_MULTIPKT;
190*75943bc9SSergei Antonov 
19137c84890SSergei Antonov 	iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR);
192baf0fbfeSJeff Kirsher 	return 0;
193baf0fbfeSJeff Kirsher }
194baf0fbfeSJeff Kirsher 
195baf0fbfeSJeff Kirsher static void ftmac100_stop_hw(struct ftmac100 *priv)
196baf0fbfeSJeff Kirsher {
197baf0fbfeSJeff Kirsher 	iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
198baf0fbfeSJeff Kirsher }
199baf0fbfeSJeff Kirsher 
200baf0fbfeSJeff Kirsher /******************************************************************************
201baf0fbfeSJeff Kirsher  * internal functions (receive descriptor)
202baf0fbfeSJeff Kirsher  *****************************************************************************/
203baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
204baf0fbfeSJeff Kirsher {
205baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
206baf0fbfeSJeff Kirsher }
207baf0fbfeSJeff Kirsher 
208baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
209baf0fbfeSJeff Kirsher {
210baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
211baf0fbfeSJeff Kirsher }
212baf0fbfeSJeff Kirsher 
213baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
214baf0fbfeSJeff Kirsher {
215baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
216baf0fbfeSJeff Kirsher }
217baf0fbfeSJeff Kirsher 
218baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
219baf0fbfeSJeff Kirsher {
220baf0fbfeSJeff Kirsher 	/* clear status bits */
221baf0fbfeSJeff Kirsher 	rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
222baf0fbfeSJeff Kirsher }
223baf0fbfeSJeff Kirsher 
224baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
225baf0fbfeSJeff Kirsher {
226baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
227baf0fbfeSJeff Kirsher }
228baf0fbfeSJeff Kirsher 
229baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
230baf0fbfeSJeff Kirsher {
231baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
232baf0fbfeSJeff Kirsher }
233baf0fbfeSJeff Kirsher 
234baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
235baf0fbfeSJeff Kirsher {
236baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
237baf0fbfeSJeff Kirsher }
238baf0fbfeSJeff Kirsher 
239baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
240baf0fbfeSJeff Kirsher {
241baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
242baf0fbfeSJeff Kirsher }
243baf0fbfeSJeff Kirsher 
244baf0fbfeSJeff Kirsher static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
245baf0fbfeSJeff Kirsher {
246baf0fbfeSJeff Kirsher 	return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
247baf0fbfeSJeff Kirsher }
248baf0fbfeSJeff Kirsher 
249baf0fbfeSJeff Kirsher static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
250baf0fbfeSJeff Kirsher {
251baf0fbfeSJeff Kirsher 	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
252baf0fbfeSJeff Kirsher }
253baf0fbfeSJeff Kirsher 
254baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
255baf0fbfeSJeff Kirsher 					   unsigned int size)
256baf0fbfeSJeff Kirsher {
257baf0fbfeSJeff Kirsher 	rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
258baf0fbfeSJeff Kirsher 	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
259baf0fbfeSJeff Kirsher }
260baf0fbfeSJeff Kirsher 
261baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
262baf0fbfeSJeff Kirsher {
263baf0fbfeSJeff Kirsher 	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
264baf0fbfeSJeff Kirsher }
265baf0fbfeSJeff Kirsher 
266baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
267baf0fbfeSJeff Kirsher 					dma_addr_t addr)
268baf0fbfeSJeff Kirsher {
269baf0fbfeSJeff Kirsher 	rxdes->rxdes2 = cpu_to_le32(addr);
270baf0fbfeSJeff Kirsher }
271baf0fbfeSJeff Kirsher 
272baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
273baf0fbfeSJeff Kirsher {
274baf0fbfeSJeff Kirsher 	return le32_to_cpu(rxdes->rxdes2);
275baf0fbfeSJeff Kirsher }
276baf0fbfeSJeff Kirsher 
277baf0fbfeSJeff Kirsher /*
278baf0fbfeSJeff Kirsher  * rxdes3 is not used by hardware. We use it to keep track of page.
279baf0fbfeSJeff Kirsher  * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
280baf0fbfeSJeff Kirsher  */
281baf0fbfeSJeff Kirsher static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
282baf0fbfeSJeff Kirsher {
283baf0fbfeSJeff Kirsher 	rxdes->rxdes3 = (unsigned int)page;
284baf0fbfeSJeff Kirsher }
285baf0fbfeSJeff Kirsher 
286baf0fbfeSJeff Kirsher static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
287baf0fbfeSJeff Kirsher {
288baf0fbfeSJeff Kirsher 	return (struct page *)rxdes->rxdes3;
289baf0fbfeSJeff Kirsher }
290baf0fbfeSJeff Kirsher 
291baf0fbfeSJeff Kirsher /******************************************************************************
292baf0fbfeSJeff Kirsher  * internal functions (receive)
293baf0fbfeSJeff Kirsher  *****************************************************************************/
294baf0fbfeSJeff Kirsher static int ftmac100_next_rx_pointer(int pointer)
295baf0fbfeSJeff Kirsher {
296baf0fbfeSJeff Kirsher 	return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
297baf0fbfeSJeff Kirsher }
298baf0fbfeSJeff Kirsher 
299baf0fbfeSJeff Kirsher static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
300baf0fbfeSJeff Kirsher {
301baf0fbfeSJeff Kirsher 	priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
302baf0fbfeSJeff Kirsher }
303baf0fbfeSJeff Kirsher 
304baf0fbfeSJeff Kirsher static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
305baf0fbfeSJeff Kirsher {
306baf0fbfeSJeff Kirsher 	return &priv->descs->rxdes[priv->rx_pointer];
307baf0fbfeSJeff Kirsher }
308baf0fbfeSJeff Kirsher 
309baf0fbfeSJeff Kirsher static struct ftmac100_rxdes *
310baf0fbfeSJeff Kirsher ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
311baf0fbfeSJeff Kirsher {
312baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
313baf0fbfeSJeff Kirsher 
314baf0fbfeSJeff Kirsher 	while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
315baf0fbfeSJeff Kirsher 		if (ftmac100_rxdes_first_segment(rxdes))
316baf0fbfeSJeff Kirsher 			return rxdes;
317baf0fbfeSJeff Kirsher 
318baf0fbfeSJeff Kirsher 		ftmac100_rxdes_set_dma_own(rxdes);
319baf0fbfeSJeff Kirsher 		ftmac100_rx_pointer_advance(priv);
320baf0fbfeSJeff Kirsher 		rxdes = ftmac100_current_rxdes(priv);
321baf0fbfeSJeff Kirsher 	}
322baf0fbfeSJeff Kirsher 
323baf0fbfeSJeff Kirsher 	return NULL;
324baf0fbfeSJeff Kirsher }
325baf0fbfeSJeff Kirsher 
326baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
327baf0fbfeSJeff Kirsher 				     struct ftmac100_rxdes *rxdes)
328baf0fbfeSJeff Kirsher {
329baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
330baf0fbfeSJeff Kirsher 	bool error = false;
331baf0fbfeSJeff Kirsher 
332baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
333baf0fbfeSJeff Kirsher 		if (net_ratelimit())
334baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx err\n");
335baf0fbfeSJeff Kirsher 
336baf0fbfeSJeff Kirsher 		netdev->stats.rx_errors++;
337baf0fbfeSJeff Kirsher 		error = true;
338baf0fbfeSJeff Kirsher 	}
339baf0fbfeSJeff Kirsher 
340baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
341baf0fbfeSJeff Kirsher 		if (net_ratelimit())
342baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx crc err\n");
343baf0fbfeSJeff Kirsher 
344baf0fbfeSJeff Kirsher 		netdev->stats.rx_crc_errors++;
345baf0fbfeSJeff Kirsher 		error = true;
346baf0fbfeSJeff Kirsher 	}
347baf0fbfeSJeff Kirsher 
34855f6f3dbSVladimir Oltean 	if (unlikely(ftmac100_rxdes_runt(rxdes))) {
349baf0fbfeSJeff Kirsher 		if (net_ratelimit())
350baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx runt\n");
351baf0fbfeSJeff Kirsher 
352baf0fbfeSJeff Kirsher 		netdev->stats.rx_length_errors++;
353baf0fbfeSJeff Kirsher 		error = true;
354baf0fbfeSJeff Kirsher 	} else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
355baf0fbfeSJeff Kirsher 		if (net_ratelimit())
356baf0fbfeSJeff Kirsher 			netdev_info(netdev, "rx odd nibble\n");
357baf0fbfeSJeff Kirsher 
358baf0fbfeSJeff Kirsher 		netdev->stats.rx_length_errors++;
359baf0fbfeSJeff Kirsher 		error = true;
360baf0fbfeSJeff Kirsher 	}
36155f6f3dbSVladimir Oltean 	/*
36255f6f3dbSVladimir Oltean 	 * FTMAC100_RXDES0_FTL is not an error, it just indicates that the
36355f6f3dbSVladimir Oltean 	 * frame is longer than 1518 octets. Receiving these is possible when
36455f6f3dbSVladimir Oltean 	 * we told the hardware not to drop them, via FTMAC100_MACCR_RX_FTL.
36555f6f3dbSVladimir Oltean 	 */
366baf0fbfeSJeff Kirsher 
367baf0fbfeSJeff Kirsher 	return error;
368baf0fbfeSJeff Kirsher }
369baf0fbfeSJeff Kirsher 
370baf0fbfeSJeff Kirsher static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
371baf0fbfeSJeff Kirsher {
372baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
373baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
374baf0fbfeSJeff Kirsher 	bool done = false;
375baf0fbfeSJeff Kirsher 
376baf0fbfeSJeff Kirsher 	if (net_ratelimit())
377baf0fbfeSJeff Kirsher 		netdev_dbg(netdev, "drop packet %p\n", rxdes);
378baf0fbfeSJeff Kirsher 
379baf0fbfeSJeff Kirsher 	do {
380baf0fbfeSJeff Kirsher 		if (ftmac100_rxdes_last_segment(rxdes))
381baf0fbfeSJeff Kirsher 			done = true;
382baf0fbfeSJeff Kirsher 
383baf0fbfeSJeff Kirsher 		ftmac100_rxdes_set_dma_own(rxdes);
384baf0fbfeSJeff Kirsher 		ftmac100_rx_pointer_advance(priv);
385baf0fbfeSJeff Kirsher 		rxdes = ftmac100_current_rxdes(priv);
386baf0fbfeSJeff Kirsher 	} while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
387baf0fbfeSJeff Kirsher 
388baf0fbfeSJeff Kirsher 	netdev->stats.rx_dropped++;
389baf0fbfeSJeff Kirsher }
390baf0fbfeSJeff Kirsher 
391baf0fbfeSJeff Kirsher static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
392baf0fbfeSJeff Kirsher {
393baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
394baf0fbfeSJeff Kirsher 	struct ftmac100_rxdes *rxdes;
395baf0fbfeSJeff Kirsher 	struct sk_buff *skb;
396baf0fbfeSJeff Kirsher 	struct page *page;
397baf0fbfeSJeff Kirsher 	dma_addr_t map;
398baf0fbfeSJeff Kirsher 	int length;
3995bca178eSGustavo A. R. Silva 	bool ret;
400baf0fbfeSJeff Kirsher 
401baf0fbfeSJeff Kirsher 	rxdes = ftmac100_rx_locate_first_segment(priv);
402baf0fbfeSJeff Kirsher 	if (!rxdes)
403baf0fbfeSJeff Kirsher 		return false;
404baf0fbfeSJeff Kirsher 
405baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
406baf0fbfeSJeff Kirsher 		ftmac100_rx_drop_packet(priv);
407baf0fbfeSJeff Kirsher 		return true;
408baf0fbfeSJeff Kirsher 	}
409baf0fbfeSJeff Kirsher 
41055f6f3dbSVladimir Oltean 	/* We don't support multi-segment packets for now, so drop them. */
4115bca178eSGustavo A. R. Silva 	ret = ftmac100_rxdes_last_segment(rxdes);
41255f6f3dbSVladimir Oltean 	if (unlikely(!ret)) {
41355f6f3dbSVladimir Oltean 		netdev->stats.rx_length_errors++;
41455f6f3dbSVladimir Oltean 		ftmac100_rx_drop_packet(priv);
41555f6f3dbSVladimir Oltean 		return true;
41655f6f3dbSVladimir Oltean 	}
417baf0fbfeSJeff Kirsher 
418baf0fbfeSJeff Kirsher 	/* start processing */
419baf0fbfeSJeff Kirsher 	skb = netdev_alloc_skb_ip_align(netdev, 128);
420baf0fbfeSJeff Kirsher 	if (unlikely(!skb)) {
421baf0fbfeSJeff Kirsher 		if (net_ratelimit())
422baf0fbfeSJeff Kirsher 			netdev_err(netdev, "rx skb alloc failed\n");
423baf0fbfeSJeff Kirsher 
424baf0fbfeSJeff Kirsher 		ftmac100_rx_drop_packet(priv);
425baf0fbfeSJeff Kirsher 		return true;
426baf0fbfeSJeff Kirsher 	}
427baf0fbfeSJeff Kirsher 
428baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_rxdes_multicast(rxdes)))
429baf0fbfeSJeff Kirsher 		netdev->stats.multicast++;
430baf0fbfeSJeff Kirsher 
431baf0fbfeSJeff Kirsher 	map = ftmac100_rxdes_get_dma_addr(rxdes);
432baf0fbfeSJeff Kirsher 	dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
433baf0fbfeSJeff Kirsher 
434baf0fbfeSJeff Kirsher 	length = ftmac100_rxdes_frame_length(rxdes);
435baf0fbfeSJeff Kirsher 	page = ftmac100_rxdes_get_page(rxdes);
436baf0fbfeSJeff Kirsher 	skb_fill_page_desc(skb, 0, page, 0, length);
437baf0fbfeSJeff Kirsher 	skb->len += length;
438baf0fbfeSJeff Kirsher 	skb->data_len += length;
43996cd8951SEric Dumazet 
4406ecd09ddSEric Dumazet 	if (length > 128) {
44196cd8951SEric Dumazet 		skb->truesize += PAGE_SIZE;
4426ecd09ddSEric Dumazet 		/* We pull the minimum amount into linear part */
4436ecd09ddSEric Dumazet 		__pskb_pull_tail(skb, ETH_HLEN);
4446ecd09ddSEric Dumazet 	} else {
4456ecd09ddSEric Dumazet 		/* Small frames are copied into linear part to free one page */
4466ecd09ddSEric Dumazet 		__pskb_pull_tail(skb, length);
4476ecd09ddSEric Dumazet 	}
448baf0fbfeSJeff Kirsher 	ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
449baf0fbfeSJeff Kirsher 
450baf0fbfeSJeff Kirsher 	ftmac100_rx_pointer_advance(priv);
451baf0fbfeSJeff Kirsher 
452baf0fbfeSJeff Kirsher 	skb->protocol = eth_type_trans(skb, netdev);
453baf0fbfeSJeff Kirsher 
454baf0fbfeSJeff Kirsher 	netdev->stats.rx_packets++;
455baf0fbfeSJeff Kirsher 	netdev->stats.rx_bytes += skb->len;
456baf0fbfeSJeff Kirsher 
457baf0fbfeSJeff Kirsher 	/* push packet to protocol stack */
458baf0fbfeSJeff Kirsher 	netif_receive_skb(skb);
459baf0fbfeSJeff Kirsher 
460baf0fbfeSJeff Kirsher 	(*processed)++;
461baf0fbfeSJeff Kirsher 	return true;
462baf0fbfeSJeff Kirsher }
463baf0fbfeSJeff Kirsher 
464baf0fbfeSJeff Kirsher /******************************************************************************
465baf0fbfeSJeff Kirsher  * internal functions (transmit descriptor)
466baf0fbfeSJeff Kirsher  *****************************************************************************/
467baf0fbfeSJeff Kirsher static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
468baf0fbfeSJeff Kirsher {
469baf0fbfeSJeff Kirsher 	/* clear all except end of ring bit */
470baf0fbfeSJeff Kirsher 	txdes->txdes0 = 0;
471baf0fbfeSJeff Kirsher 	txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
472baf0fbfeSJeff Kirsher 	txdes->txdes2 = 0;
473baf0fbfeSJeff Kirsher 	txdes->txdes3 = 0;
474baf0fbfeSJeff Kirsher }
475baf0fbfeSJeff Kirsher 
476baf0fbfeSJeff Kirsher static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
477baf0fbfeSJeff Kirsher {
478baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
479baf0fbfeSJeff Kirsher }
480baf0fbfeSJeff Kirsher 
481baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
482baf0fbfeSJeff Kirsher {
483baf0fbfeSJeff Kirsher 	/*
484baf0fbfeSJeff Kirsher 	 * Make sure dma own bit will not be set before any other
485baf0fbfeSJeff Kirsher 	 * descriptor fields.
486baf0fbfeSJeff Kirsher 	 */
487baf0fbfeSJeff Kirsher 	wmb();
488baf0fbfeSJeff Kirsher 	txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
489baf0fbfeSJeff Kirsher }
490baf0fbfeSJeff Kirsher 
491baf0fbfeSJeff Kirsher static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
492baf0fbfeSJeff Kirsher {
493baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
494baf0fbfeSJeff Kirsher }
495baf0fbfeSJeff Kirsher 
496baf0fbfeSJeff Kirsher static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
497baf0fbfeSJeff Kirsher {
498baf0fbfeSJeff Kirsher 	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
499baf0fbfeSJeff Kirsher }
500baf0fbfeSJeff Kirsher 
501baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
502baf0fbfeSJeff Kirsher {
503baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
504baf0fbfeSJeff Kirsher }
505baf0fbfeSJeff Kirsher 
506baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
507baf0fbfeSJeff Kirsher {
508baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
509baf0fbfeSJeff Kirsher }
510baf0fbfeSJeff Kirsher 
511baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
512baf0fbfeSJeff Kirsher {
513baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
514baf0fbfeSJeff Kirsher }
515baf0fbfeSJeff Kirsher 
516baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
517baf0fbfeSJeff Kirsher {
518baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
519baf0fbfeSJeff Kirsher }
520baf0fbfeSJeff Kirsher 
521baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
522baf0fbfeSJeff Kirsher 					   unsigned int len)
523baf0fbfeSJeff Kirsher {
524baf0fbfeSJeff Kirsher 	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
525baf0fbfeSJeff Kirsher }
526baf0fbfeSJeff Kirsher 
527baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
528baf0fbfeSJeff Kirsher 					dma_addr_t addr)
529baf0fbfeSJeff Kirsher {
530baf0fbfeSJeff Kirsher 	txdes->txdes2 = cpu_to_le32(addr);
531baf0fbfeSJeff Kirsher }
532baf0fbfeSJeff Kirsher 
533baf0fbfeSJeff Kirsher static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
534baf0fbfeSJeff Kirsher {
535baf0fbfeSJeff Kirsher 	return le32_to_cpu(txdes->txdes2);
536baf0fbfeSJeff Kirsher }
537baf0fbfeSJeff Kirsher 
538baf0fbfeSJeff Kirsher /*
539baf0fbfeSJeff Kirsher  * txdes3 is not used by hardware. We use it to keep track of socket buffer.
540baf0fbfeSJeff Kirsher  * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
541baf0fbfeSJeff Kirsher  */
542baf0fbfeSJeff Kirsher static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
543baf0fbfeSJeff Kirsher {
544baf0fbfeSJeff Kirsher 	txdes->txdes3 = (unsigned int)skb;
545baf0fbfeSJeff Kirsher }
546baf0fbfeSJeff Kirsher 
547baf0fbfeSJeff Kirsher static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
548baf0fbfeSJeff Kirsher {
549baf0fbfeSJeff Kirsher 	return (struct sk_buff *)txdes->txdes3;
550baf0fbfeSJeff Kirsher }
551baf0fbfeSJeff Kirsher 
552baf0fbfeSJeff Kirsher /******************************************************************************
553baf0fbfeSJeff Kirsher  * internal functions (transmit)
554baf0fbfeSJeff Kirsher  *****************************************************************************/
555baf0fbfeSJeff Kirsher static int ftmac100_next_tx_pointer(int pointer)
556baf0fbfeSJeff Kirsher {
557baf0fbfeSJeff Kirsher 	return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
558baf0fbfeSJeff Kirsher }
559baf0fbfeSJeff Kirsher 
560baf0fbfeSJeff Kirsher static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
561baf0fbfeSJeff Kirsher {
562baf0fbfeSJeff Kirsher 	priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
563baf0fbfeSJeff Kirsher }
564baf0fbfeSJeff Kirsher 
565baf0fbfeSJeff Kirsher static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
566baf0fbfeSJeff Kirsher {
567baf0fbfeSJeff Kirsher 	priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
568baf0fbfeSJeff Kirsher }
569baf0fbfeSJeff Kirsher 
570baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
571baf0fbfeSJeff Kirsher {
572baf0fbfeSJeff Kirsher 	return &priv->descs->txdes[priv->tx_pointer];
573baf0fbfeSJeff Kirsher }
574baf0fbfeSJeff Kirsher 
575baf0fbfeSJeff Kirsher static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
576baf0fbfeSJeff Kirsher {
577baf0fbfeSJeff Kirsher 	return &priv->descs->txdes[priv->tx_clean_pointer];
578baf0fbfeSJeff Kirsher }
579baf0fbfeSJeff Kirsher 
580baf0fbfeSJeff Kirsher static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
581baf0fbfeSJeff Kirsher {
582baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
583baf0fbfeSJeff Kirsher 	struct ftmac100_txdes *txdes;
584baf0fbfeSJeff Kirsher 	struct sk_buff *skb;
585baf0fbfeSJeff Kirsher 	dma_addr_t map;
586baf0fbfeSJeff Kirsher 
587baf0fbfeSJeff Kirsher 	if (priv->tx_pending == 0)
588baf0fbfeSJeff Kirsher 		return false;
589baf0fbfeSJeff Kirsher 
590baf0fbfeSJeff Kirsher 	txdes = ftmac100_current_clean_txdes(priv);
591baf0fbfeSJeff Kirsher 
592baf0fbfeSJeff Kirsher 	if (ftmac100_txdes_owned_by_dma(txdes))
593baf0fbfeSJeff Kirsher 		return false;
594baf0fbfeSJeff Kirsher 
595baf0fbfeSJeff Kirsher 	skb = ftmac100_txdes_get_skb(txdes);
596baf0fbfeSJeff Kirsher 	map = ftmac100_txdes_get_dma_addr(txdes);
597baf0fbfeSJeff Kirsher 
598baf0fbfeSJeff Kirsher 	if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
599baf0fbfeSJeff Kirsher 		     ftmac100_txdes_late_collision(txdes))) {
600baf0fbfeSJeff Kirsher 		/*
601baf0fbfeSJeff Kirsher 		 * packet transmitted to ethernet lost due to late collision
602baf0fbfeSJeff Kirsher 		 * or excessive collision
603baf0fbfeSJeff Kirsher 		 */
604baf0fbfeSJeff Kirsher 		netdev->stats.tx_aborted_errors++;
605baf0fbfeSJeff Kirsher 	} else {
606baf0fbfeSJeff Kirsher 		netdev->stats.tx_packets++;
607baf0fbfeSJeff Kirsher 		netdev->stats.tx_bytes += skb->len;
608baf0fbfeSJeff Kirsher 	}
609baf0fbfeSJeff Kirsher 
610baf0fbfeSJeff Kirsher 	dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
611baf0fbfeSJeff Kirsher 	dev_kfree_skb(skb);
612baf0fbfeSJeff Kirsher 
613baf0fbfeSJeff Kirsher 	ftmac100_txdes_reset(txdes);
614baf0fbfeSJeff Kirsher 
615baf0fbfeSJeff Kirsher 	ftmac100_tx_clean_pointer_advance(priv);
616baf0fbfeSJeff Kirsher 
617baf0fbfeSJeff Kirsher 	spin_lock(&priv->tx_lock);
618baf0fbfeSJeff Kirsher 	priv->tx_pending--;
619baf0fbfeSJeff Kirsher 	spin_unlock(&priv->tx_lock);
620baf0fbfeSJeff Kirsher 	netif_wake_queue(netdev);
621baf0fbfeSJeff Kirsher 
622baf0fbfeSJeff Kirsher 	return true;
623baf0fbfeSJeff Kirsher }
624baf0fbfeSJeff Kirsher 
625baf0fbfeSJeff Kirsher static void ftmac100_tx_complete(struct ftmac100 *priv)
626baf0fbfeSJeff Kirsher {
627baf0fbfeSJeff Kirsher 	while (ftmac100_tx_complete_packet(priv))
628baf0fbfeSJeff Kirsher 		;
629baf0fbfeSJeff Kirsher }
630baf0fbfeSJeff Kirsher 
6310a715156SYueHaibing static netdev_tx_t ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
632baf0fbfeSJeff Kirsher 				 dma_addr_t map)
633baf0fbfeSJeff Kirsher {
634baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
635baf0fbfeSJeff Kirsher 	struct ftmac100_txdes *txdes;
636baf0fbfeSJeff Kirsher 	unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
637baf0fbfeSJeff Kirsher 
638baf0fbfeSJeff Kirsher 	txdes = ftmac100_current_txdes(priv);
639baf0fbfeSJeff Kirsher 	ftmac100_tx_pointer_advance(priv);
640baf0fbfeSJeff Kirsher 
641baf0fbfeSJeff Kirsher 	/* setup TX descriptor */
642baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_skb(txdes, skb);
643baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_dma_addr(txdes, map);
644baf0fbfeSJeff Kirsher 
645baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_first_segment(txdes);
646baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_last_segment(txdes);
647baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_txint(txdes);
648baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_buffer_size(txdes, len);
649baf0fbfeSJeff Kirsher 
650baf0fbfeSJeff Kirsher 	spin_lock(&priv->tx_lock);
651baf0fbfeSJeff Kirsher 	priv->tx_pending++;
652baf0fbfeSJeff Kirsher 	if (priv->tx_pending == TX_QUEUE_ENTRIES)
653baf0fbfeSJeff Kirsher 		netif_stop_queue(netdev);
654baf0fbfeSJeff Kirsher 
655baf0fbfeSJeff Kirsher 	/* start transmit */
656baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_dma_own(txdes);
657baf0fbfeSJeff Kirsher 	spin_unlock(&priv->tx_lock);
658baf0fbfeSJeff Kirsher 
659baf0fbfeSJeff Kirsher 	ftmac100_txdma_start_polling(priv);
660baf0fbfeSJeff Kirsher 	return NETDEV_TX_OK;
661baf0fbfeSJeff Kirsher }
662baf0fbfeSJeff Kirsher 
663baf0fbfeSJeff Kirsher /******************************************************************************
664baf0fbfeSJeff Kirsher  * internal functions (buffer)
665baf0fbfeSJeff Kirsher  *****************************************************************************/
666baf0fbfeSJeff Kirsher static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
667baf0fbfeSJeff Kirsher 				  struct ftmac100_rxdes *rxdes, gfp_t gfp)
668baf0fbfeSJeff Kirsher {
669baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
670baf0fbfeSJeff Kirsher 	struct page *page;
671baf0fbfeSJeff Kirsher 	dma_addr_t map;
672baf0fbfeSJeff Kirsher 
673baf0fbfeSJeff Kirsher 	page = alloc_page(gfp);
674baf0fbfeSJeff Kirsher 	if (!page) {
675baf0fbfeSJeff Kirsher 		if (net_ratelimit())
676baf0fbfeSJeff Kirsher 			netdev_err(netdev, "failed to allocate rx page\n");
677baf0fbfeSJeff Kirsher 		return -ENOMEM;
678baf0fbfeSJeff Kirsher 	}
679baf0fbfeSJeff Kirsher 
680baf0fbfeSJeff Kirsher 	map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
681baf0fbfeSJeff Kirsher 	if (unlikely(dma_mapping_error(priv->dev, map))) {
682baf0fbfeSJeff Kirsher 		if (net_ratelimit())
683baf0fbfeSJeff Kirsher 			netdev_err(netdev, "failed to map rx page\n");
684baf0fbfeSJeff Kirsher 		__free_page(page);
685baf0fbfeSJeff Kirsher 		return -ENOMEM;
686baf0fbfeSJeff Kirsher 	}
687baf0fbfeSJeff Kirsher 
688baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_page(rxdes, page);
689baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_dma_addr(rxdes, map);
690baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
691baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_dma_own(rxdes);
692baf0fbfeSJeff Kirsher 	return 0;
693baf0fbfeSJeff Kirsher }
694baf0fbfeSJeff Kirsher 
695baf0fbfeSJeff Kirsher static void ftmac100_free_buffers(struct ftmac100 *priv)
696baf0fbfeSJeff Kirsher {
697baf0fbfeSJeff Kirsher 	int i;
698baf0fbfeSJeff Kirsher 
699baf0fbfeSJeff Kirsher 	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
700baf0fbfeSJeff Kirsher 		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
701baf0fbfeSJeff Kirsher 		struct page *page = ftmac100_rxdes_get_page(rxdes);
702baf0fbfeSJeff Kirsher 		dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
703baf0fbfeSJeff Kirsher 
704baf0fbfeSJeff Kirsher 		if (!page)
705baf0fbfeSJeff Kirsher 			continue;
706baf0fbfeSJeff Kirsher 
707baf0fbfeSJeff Kirsher 		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
708baf0fbfeSJeff Kirsher 		__free_page(page);
709baf0fbfeSJeff Kirsher 	}
710baf0fbfeSJeff Kirsher 
711baf0fbfeSJeff Kirsher 	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
712baf0fbfeSJeff Kirsher 		struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
713baf0fbfeSJeff Kirsher 		struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
714baf0fbfeSJeff Kirsher 		dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
715baf0fbfeSJeff Kirsher 
716baf0fbfeSJeff Kirsher 		if (!skb)
717baf0fbfeSJeff Kirsher 			continue;
718baf0fbfeSJeff Kirsher 
719baf0fbfeSJeff Kirsher 		dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
720baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
721baf0fbfeSJeff Kirsher 	}
722baf0fbfeSJeff Kirsher 
723baf0fbfeSJeff Kirsher 	dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
724baf0fbfeSJeff Kirsher 			  priv->descs, priv->descs_dma_addr);
725baf0fbfeSJeff Kirsher }
726baf0fbfeSJeff Kirsher 
727baf0fbfeSJeff Kirsher static int ftmac100_alloc_buffers(struct ftmac100 *priv)
728baf0fbfeSJeff Kirsher {
729baf0fbfeSJeff Kirsher 	int i;
730baf0fbfeSJeff Kirsher 
731750afb08SLuis Chamberlain 	priv->descs = dma_alloc_coherent(priv->dev,
7321f9061d2SJoe Perches 					 sizeof(struct ftmac100_descs),
733750afb08SLuis Chamberlain 					 &priv->descs_dma_addr, GFP_KERNEL);
734baf0fbfeSJeff Kirsher 	if (!priv->descs)
735baf0fbfeSJeff Kirsher 		return -ENOMEM;
736baf0fbfeSJeff Kirsher 
737baf0fbfeSJeff Kirsher 	/* initialize RX ring */
738baf0fbfeSJeff Kirsher 	ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
739baf0fbfeSJeff Kirsher 
740baf0fbfeSJeff Kirsher 	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
741baf0fbfeSJeff Kirsher 		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
742baf0fbfeSJeff Kirsher 
743baf0fbfeSJeff Kirsher 		if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
744baf0fbfeSJeff Kirsher 			goto err;
745baf0fbfeSJeff Kirsher 	}
746baf0fbfeSJeff Kirsher 
747baf0fbfeSJeff Kirsher 	/* initialize TX ring */
748baf0fbfeSJeff Kirsher 	ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
749baf0fbfeSJeff Kirsher 	return 0;
750baf0fbfeSJeff Kirsher 
751baf0fbfeSJeff Kirsher err:
752baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
753baf0fbfeSJeff Kirsher 	return -ENOMEM;
754baf0fbfeSJeff Kirsher }
755baf0fbfeSJeff Kirsher 
756baf0fbfeSJeff Kirsher /******************************************************************************
757baf0fbfeSJeff Kirsher  * struct mii_if_info functions
758baf0fbfeSJeff Kirsher  *****************************************************************************/
759baf0fbfeSJeff Kirsher static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
760baf0fbfeSJeff Kirsher {
761baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
762baf0fbfeSJeff Kirsher 	unsigned int phycr;
763baf0fbfeSJeff Kirsher 	int i;
764baf0fbfeSJeff Kirsher 
765baf0fbfeSJeff Kirsher 	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
766baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_REGAD(reg) |
767baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_MIIRD;
768baf0fbfeSJeff Kirsher 
769baf0fbfeSJeff Kirsher 	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
770baf0fbfeSJeff Kirsher 
771baf0fbfeSJeff Kirsher 	for (i = 0; i < 10; i++) {
772baf0fbfeSJeff Kirsher 		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
773baf0fbfeSJeff Kirsher 
774baf0fbfeSJeff Kirsher 		if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
775baf0fbfeSJeff Kirsher 			return phycr & FTMAC100_PHYCR_MIIRDATA;
776baf0fbfeSJeff Kirsher 
777baf0fbfeSJeff Kirsher 		udelay(100);
778baf0fbfeSJeff Kirsher 	}
779baf0fbfeSJeff Kirsher 
780baf0fbfeSJeff Kirsher 	netdev_err(netdev, "mdio read timed out\n");
781baf0fbfeSJeff Kirsher 	return 0;
782baf0fbfeSJeff Kirsher }
783baf0fbfeSJeff Kirsher 
784baf0fbfeSJeff Kirsher static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
785baf0fbfeSJeff Kirsher 				int data)
786baf0fbfeSJeff Kirsher {
787baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
788baf0fbfeSJeff Kirsher 	unsigned int phycr;
789baf0fbfeSJeff Kirsher 	int i;
790baf0fbfeSJeff Kirsher 
791baf0fbfeSJeff Kirsher 	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
792baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_REGAD(reg) |
793baf0fbfeSJeff Kirsher 		FTMAC100_PHYCR_MIIWR;
794baf0fbfeSJeff Kirsher 
795baf0fbfeSJeff Kirsher 	data = FTMAC100_PHYWDATA_MIIWDATA(data);
796baf0fbfeSJeff Kirsher 
797baf0fbfeSJeff Kirsher 	iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
798baf0fbfeSJeff Kirsher 	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
799baf0fbfeSJeff Kirsher 
800baf0fbfeSJeff Kirsher 	for (i = 0; i < 10; i++) {
801baf0fbfeSJeff Kirsher 		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
802baf0fbfeSJeff Kirsher 
803baf0fbfeSJeff Kirsher 		if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
804baf0fbfeSJeff Kirsher 			return;
805baf0fbfeSJeff Kirsher 
806baf0fbfeSJeff Kirsher 		udelay(100);
807baf0fbfeSJeff Kirsher 	}
808baf0fbfeSJeff Kirsher 
809baf0fbfeSJeff Kirsher 	netdev_err(netdev, "mdio write timed out\n");
810baf0fbfeSJeff Kirsher }
811baf0fbfeSJeff Kirsher 
812baf0fbfeSJeff Kirsher /******************************************************************************
813baf0fbfeSJeff Kirsher  * struct ethtool_ops functions
814baf0fbfeSJeff Kirsher  *****************************************************************************/
815baf0fbfeSJeff Kirsher static void ftmac100_get_drvinfo(struct net_device *netdev,
816baf0fbfeSJeff Kirsher 				 struct ethtool_drvinfo *info)
817baf0fbfeSJeff Kirsher {
818f029c781SWolfram Sang 	strscpy(info->driver, DRV_NAME, sizeof(info->driver));
819f029c781SWolfram Sang 	strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
820baf0fbfeSJeff Kirsher }
821baf0fbfeSJeff Kirsher 
8229da12b64SPhilippe Reynes static int ftmac100_get_link_ksettings(struct net_device *netdev,
8239da12b64SPhilippe Reynes 				       struct ethtool_link_ksettings *cmd)
824baf0fbfeSJeff Kirsher {
825baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
82682c01a84Syuval.shaia@oracle.com 
82782c01a84Syuval.shaia@oracle.com 	mii_ethtool_get_link_ksettings(&priv->mii, cmd);
82882c01a84Syuval.shaia@oracle.com 
82982c01a84Syuval.shaia@oracle.com 	return 0;
830baf0fbfeSJeff Kirsher }
831baf0fbfeSJeff Kirsher 
8329da12b64SPhilippe Reynes static int ftmac100_set_link_ksettings(struct net_device *netdev,
8339da12b64SPhilippe Reynes 				       const struct ethtool_link_ksettings *cmd)
834baf0fbfeSJeff Kirsher {
835baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
8369da12b64SPhilippe Reynes 	return mii_ethtool_set_link_ksettings(&priv->mii, cmd);
837baf0fbfeSJeff Kirsher }
838baf0fbfeSJeff Kirsher 
839baf0fbfeSJeff Kirsher static int ftmac100_nway_reset(struct net_device *netdev)
840baf0fbfeSJeff Kirsher {
841baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
842baf0fbfeSJeff Kirsher 	return mii_nway_restart(&priv->mii);
843baf0fbfeSJeff Kirsher }
844baf0fbfeSJeff Kirsher 
845baf0fbfeSJeff Kirsher static u32 ftmac100_get_link(struct net_device *netdev)
846baf0fbfeSJeff Kirsher {
847baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
848baf0fbfeSJeff Kirsher 	return mii_link_ok(&priv->mii);
849baf0fbfeSJeff Kirsher }
850baf0fbfeSJeff Kirsher 
851baf0fbfeSJeff Kirsher static const struct ethtool_ops ftmac100_ethtool_ops = {
852baf0fbfeSJeff Kirsher 	.get_drvinfo		= ftmac100_get_drvinfo,
853baf0fbfeSJeff Kirsher 	.nway_reset		= ftmac100_nway_reset,
854baf0fbfeSJeff Kirsher 	.get_link		= ftmac100_get_link,
8559da12b64SPhilippe Reynes 	.get_link_ksettings	= ftmac100_get_link_ksettings,
8569da12b64SPhilippe Reynes 	.set_link_ksettings	= ftmac100_set_link_ksettings,
857baf0fbfeSJeff Kirsher };
858baf0fbfeSJeff Kirsher 
859baf0fbfeSJeff Kirsher /******************************************************************************
860baf0fbfeSJeff Kirsher  * interrupt handler
861baf0fbfeSJeff Kirsher  *****************************************************************************/
862baf0fbfeSJeff Kirsher static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
863baf0fbfeSJeff Kirsher {
864baf0fbfeSJeff Kirsher 	struct net_device *netdev = dev_id;
865baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
866baf0fbfeSJeff Kirsher 
867baf0fbfeSJeff Kirsher 	/* Disable interrupts for polling */
868baf0fbfeSJeff Kirsher 	ftmac100_disable_all_int(priv);
869426a593eSVincent Chen 	if (likely(netif_running(netdev)))
870baf0fbfeSJeff Kirsher 		napi_schedule(&priv->napi);
871baf0fbfeSJeff Kirsher 
872baf0fbfeSJeff Kirsher 	return IRQ_HANDLED;
873baf0fbfeSJeff Kirsher }
874baf0fbfeSJeff Kirsher 
875baf0fbfeSJeff Kirsher /******************************************************************************
876baf0fbfeSJeff Kirsher  * struct napi_struct functions
877baf0fbfeSJeff Kirsher  *****************************************************************************/
878baf0fbfeSJeff Kirsher static int ftmac100_poll(struct napi_struct *napi, int budget)
879baf0fbfeSJeff Kirsher {
880baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
881baf0fbfeSJeff Kirsher 	struct net_device *netdev = priv->netdev;
882baf0fbfeSJeff Kirsher 	unsigned int status;
883baf0fbfeSJeff Kirsher 	bool completed = true;
884baf0fbfeSJeff Kirsher 	int rx = 0;
885baf0fbfeSJeff Kirsher 
886baf0fbfeSJeff Kirsher 	status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
887baf0fbfeSJeff Kirsher 
888baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
889baf0fbfeSJeff Kirsher 		/*
890baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_RPKT_FINISH:
891baf0fbfeSJeff Kirsher 		 *	RX DMA has received packets into RX buffer successfully
892baf0fbfeSJeff Kirsher 		 *
893baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_NORXBUF:
894baf0fbfeSJeff Kirsher 		 *	RX buffer unavailable
895baf0fbfeSJeff Kirsher 		 */
896baf0fbfeSJeff Kirsher 		bool retry;
897baf0fbfeSJeff Kirsher 
898baf0fbfeSJeff Kirsher 		do {
899baf0fbfeSJeff Kirsher 			retry = ftmac100_rx_packet(priv, &rx);
900baf0fbfeSJeff Kirsher 		} while (retry && rx < budget);
901baf0fbfeSJeff Kirsher 
902baf0fbfeSJeff Kirsher 		if (retry && rx == budget)
903baf0fbfeSJeff Kirsher 			completed = false;
904baf0fbfeSJeff Kirsher 	}
905baf0fbfeSJeff Kirsher 
906baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
907baf0fbfeSJeff Kirsher 		/*
908baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_XPKT_OK:
909baf0fbfeSJeff Kirsher 		 *	packet transmitted to ethernet successfully
910baf0fbfeSJeff Kirsher 		 *
911baf0fbfeSJeff Kirsher 		 * FTMAC100_INT_XPKT_LOST:
912baf0fbfeSJeff Kirsher 		 *	packet transmitted to ethernet lost due to late
913baf0fbfeSJeff Kirsher 		 *	collision or excessive collision
914baf0fbfeSJeff Kirsher 		 */
915baf0fbfeSJeff Kirsher 		ftmac100_tx_complete(priv);
916baf0fbfeSJeff Kirsher 	}
917baf0fbfeSJeff Kirsher 
918baf0fbfeSJeff Kirsher 	if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
919baf0fbfeSJeff Kirsher 		      FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
920baf0fbfeSJeff Kirsher 		if (net_ratelimit())
921baf0fbfeSJeff Kirsher 			netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
922baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
923baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
924baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
925baf0fbfeSJeff Kirsher 				    status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
926baf0fbfeSJeff Kirsher 
927baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_NORXBUF) {
928baf0fbfeSJeff Kirsher 			/* RX buffer unavailable */
929baf0fbfeSJeff Kirsher 			netdev->stats.rx_over_errors++;
930baf0fbfeSJeff Kirsher 		}
931baf0fbfeSJeff Kirsher 
932baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_RPKT_LOST) {
933baf0fbfeSJeff Kirsher 			/* received packet lost due to RX FIFO full */
934baf0fbfeSJeff Kirsher 			netdev->stats.rx_fifo_errors++;
935baf0fbfeSJeff Kirsher 		}
936baf0fbfeSJeff Kirsher 
937baf0fbfeSJeff Kirsher 		if (status & FTMAC100_INT_PHYSTS_CHG) {
938baf0fbfeSJeff Kirsher 			/* PHY link status change */
939baf0fbfeSJeff Kirsher 			mii_check_link(&priv->mii);
940baf0fbfeSJeff Kirsher 		}
941baf0fbfeSJeff Kirsher 	}
942baf0fbfeSJeff Kirsher 
943baf0fbfeSJeff Kirsher 	if (completed) {
944baf0fbfeSJeff Kirsher 		/* stop polling */
945baf0fbfeSJeff Kirsher 		napi_complete(napi);
946baf0fbfeSJeff Kirsher 		ftmac100_enable_all_int(priv);
947baf0fbfeSJeff Kirsher 	}
948baf0fbfeSJeff Kirsher 
949baf0fbfeSJeff Kirsher 	return rx;
950baf0fbfeSJeff Kirsher }
951baf0fbfeSJeff Kirsher 
952baf0fbfeSJeff Kirsher /******************************************************************************
953baf0fbfeSJeff Kirsher  * struct net_device_ops functions
954baf0fbfeSJeff Kirsher  *****************************************************************************/
955baf0fbfeSJeff Kirsher static int ftmac100_open(struct net_device *netdev)
956baf0fbfeSJeff Kirsher {
957baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
958baf0fbfeSJeff Kirsher 	int err;
959baf0fbfeSJeff Kirsher 
960baf0fbfeSJeff Kirsher 	err = ftmac100_alloc_buffers(priv);
961baf0fbfeSJeff Kirsher 	if (err) {
962baf0fbfeSJeff Kirsher 		netdev_err(netdev, "failed to allocate buffers\n");
963baf0fbfeSJeff Kirsher 		goto err_alloc;
964baf0fbfeSJeff Kirsher 	}
965baf0fbfeSJeff Kirsher 
966baf0fbfeSJeff Kirsher 	err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
967baf0fbfeSJeff Kirsher 	if (err) {
968baf0fbfeSJeff Kirsher 		netdev_err(netdev, "failed to request irq %d\n", priv->irq);
969baf0fbfeSJeff Kirsher 		goto err_irq;
970baf0fbfeSJeff Kirsher 	}
971baf0fbfeSJeff Kirsher 
972baf0fbfeSJeff Kirsher 	priv->rx_pointer = 0;
973baf0fbfeSJeff Kirsher 	priv->tx_clean_pointer = 0;
974baf0fbfeSJeff Kirsher 	priv->tx_pointer = 0;
975baf0fbfeSJeff Kirsher 	priv->tx_pending = 0;
976baf0fbfeSJeff Kirsher 
977baf0fbfeSJeff Kirsher 	err = ftmac100_start_hw(priv);
978baf0fbfeSJeff Kirsher 	if (err)
979baf0fbfeSJeff Kirsher 		goto err_hw;
980baf0fbfeSJeff Kirsher 
981baf0fbfeSJeff Kirsher 	napi_enable(&priv->napi);
982baf0fbfeSJeff Kirsher 	netif_start_queue(netdev);
983baf0fbfeSJeff Kirsher 
984baf0fbfeSJeff Kirsher 	ftmac100_enable_all_int(priv);
985baf0fbfeSJeff Kirsher 
986baf0fbfeSJeff Kirsher 	return 0;
987baf0fbfeSJeff Kirsher 
988baf0fbfeSJeff Kirsher err_hw:
989baf0fbfeSJeff Kirsher 	free_irq(priv->irq, netdev);
990baf0fbfeSJeff Kirsher err_irq:
991baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
992baf0fbfeSJeff Kirsher err_alloc:
993baf0fbfeSJeff Kirsher 	return err;
994baf0fbfeSJeff Kirsher }
995baf0fbfeSJeff Kirsher 
996baf0fbfeSJeff Kirsher static int ftmac100_stop(struct net_device *netdev)
997baf0fbfeSJeff Kirsher {
998baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
999baf0fbfeSJeff Kirsher 
1000baf0fbfeSJeff Kirsher 	ftmac100_disable_all_int(priv);
1001baf0fbfeSJeff Kirsher 	netif_stop_queue(netdev);
1002baf0fbfeSJeff Kirsher 	napi_disable(&priv->napi);
1003baf0fbfeSJeff Kirsher 	ftmac100_stop_hw(priv);
1004baf0fbfeSJeff Kirsher 	free_irq(priv->irq, netdev);
1005baf0fbfeSJeff Kirsher 	ftmac100_free_buffers(priv);
1006baf0fbfeSJeff Kirsher 
1007baf0fbfeSJeff Kirsher 	return 0;
1008baf0fbfeSJeff Kirsher }
1009baf0fbfeSJeff Kirsher 
10100a715156SYueHaibing static netdev_tx_t
10110a715156SYueHaibing ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
1012baf0fbfeSJeff Kirsher {
1013baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
1014baf0fbfeSJeff Kirsher 	dma_addr_t map;
1015baf0fbfeSJeff Kirsher 
1016baf0fbfeSJeff Kirsher 	if (unlikely(skb->len > MAX_PKT_SIZE)) {
1017baf0fbfeSJeff Kirsher 		if (net_ratelimit())
1018baf0fbfeSJeff Kirsher 			netdev_dbg(netdev, "tx packet too big\n");
1019baf0fbfeSJeff Kirsher 
1020baf0fbfeSJeff Kirsher 		netdev->stats.tx_dropped++;
1021baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
1022baf0fbfeSJeff Kirsher 		return NETDEV_TX_OK;
1023baf0fbfeSJeff Kirsher 	}
1024baf0fbfeSJeff Kirsher 
1025baf0fbfeSJeff Kirsher 	map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
1026baf0fbfeSJeff Kirsher 	if (unlikely(dma_mapping_error(priv->dev, map))) {
1027baf0fbfeSJeff Kirsher 		/* drop packet */
1028baf0fbfeSJeff Kirsher 		if (net_ratelimit())
1029baf0fbfeSJeff Kirsher 			netdev_err(netdev, "map socket buffer failed\n");
1030baf0fbfeSJeff Kirsher 
1031baf0fbfeSJeff Kirsher 		netdev->stats.tx_dropped++;
1032baf0fbfeSJeff Kirsher 		dev_kfree_skb(skb);
1033baf0fbfeSJeff Kirsher 		return NETDEV_TX_OK;
1034baf0fbfeSJeff Kirsher 	}
1035baf0fbfeSJeff Kirsher 
1036baf0fbfeSJeff Kirsher 	return ftmac100_xmit(priv, skb, map);
1037baf0fbfeSJeff Kirsher }
1038baf0fbfeSJeff Kirsher 
1039baf0fbfeSJeff Kirsher /* optional */
1040baf0fbfeSJeff Kirsher static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
1041baf0fbfeSJeff Kirsher {
1042baf0fbfeSJeff Kirsher 	struct ftmac100 *priv = netdev_priv(netdev);
1043baf0fbfeSJeff Kirsher 	struct mii_ioctl_data *data = if_mii(ifr);
1044baf0fbfeSJeff Kirsher 
1045baf0fbfeSJeff Kirsher 	return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
1046baf0fbfeSJeff Kirsher }
1047baf0fbfeSJeff Kirsher 
104837c84890SSergei Antonov static int ftmac100_change_mtu(struct net_device *netdev, int mtu)
104937c84890SSergei Antonov {
105037c84890SSergei Antonov 	struct ftmac100 *priv = netdev_priv(netdev);
105137c84890SSergei Antonov 	unsigned int maccr;
105237c84890SSergei Antonov 
105337c84890SSergei Antonov 	maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
105437c84890SSergei Antonov 	if (mtu > ETH_DATA_LEN) {
105537c84890SSergei Antonov 		/* process long packets in the driver */
105637c84890SSergei Antonov 		maccr |= FTMAC100_MACCR_RX_FTL;
105737c84890SSergei Antonov 	} else {
105837c84890SSergei Antonov 		/* Let the controller drop incoming packets greater
105937c84890SSergei Antonov 		 * than 1518 (that is 1500 + 14 Ethernet + 4 FCS).
106037c84890SSergei Antonov 		 */
106137c84890SSergei Antonov 		maccr &= ~FTMAC100_MACCR_RX_FTL;
106237c84890SSergei Antonov 	}
106337c84890SSergei Antonov 	iowrite32(maccr, priv->base + FTMAC100_OFFSET_MACCR);
106437c84890SSergei Antonov 
106537c84890SSergei Antonov 	netdev->mtu = mtu;
106637c84890SSergei Antonov 
106737c84890SSergei Antonov 	return 0;
106837c84890SSergei Antonov }
106937c84890SSergei Antonov 
1070baf0fbfeSJeff Kirsher static const struct net_device_ops ftmac100_netdev_ops = {
1071baf0fbfeSJeff Kirsher 	.ndo_open		= ftmac100_open,
1072baf0fbfeSJeff Kirsher 	.ndo_stop		= ftmac100_stop,
1073baf0fbfeSJeff Kirsher 	.ndo_start_xmit		= ftmac100_hard_start_xmit,
1074baf0fbfeSJeff Kirsher 	.ndo_set_mac_address	= eth_mac_addr,
1075baf0fbfeSJeff Kirsher 	.ndo_validate_addr	= eth_validate_addr,
1076a7605370SArnd Bergmann 	.ndo_eth_ioctl		= ftmac100_do_ioctl,
107737c84890SSergei Antonov 	.ndo_change_mtu		= ftmac100_change_mtu,
1078baf0fbfeSJeff Kirsher };
1079baf0fbfeSJeff Kirsher 
1080baf0fbfeSJeff Kirsher /******************************************************************************
1081baf0fbfeSJeff Kirsher  * struct platform_driver functions
1082baf0fbfeSJeff Kirsher  *****************************************************************************/
1083baf0fbfeSJeff Kirsher static int ftmac100_probe(struct platform_device *pdev)
1084baf0fbfeSJeff Kirsher {
1085baf0fbfeSJeff Kirsher 	struct resource *res;
1086baf0fbfeSJeff Kirsher 	int irq;
1087baf0fbfeSJeff Kirsher 	struct net_device *netdev;
1088baf0fbfeSJeff Kirsher 	struct ftmac100 *priv;
1089baf0fbfeSJeff Kirsher 	int err;
1090baf0fbfeSJeff Kirsher 
1091baf0fbfeSJeff Kirsher 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1092baf0fbfeSJeff Kirsher 	if (!res)
1093baf0fbfeSJeff Kirsher 		return -ENXIO;
1094baf0fbfeSJeff Kirsher 
1095baf0fbfeSJeff Kirsher 	irq = platform_get_irq(pdev, 0);
1096baf0fbfeSJeff Kirsher 	if (irq < 0)
1097baf0fbfeSJeff Kirsher 		return irq;
1098baf0fbfeSJeff Kirsher 
1099baf0fbfeSJeff Kirsher 	/* setup net_device */
1100baf0fbfeSJeff Kirsher 	netdev = alloc_etherdev(sizeof(*priv));
1101baf0fbfeSJeff Kirsher 	if (!netdev) {
1102baf0fbfeSJeff Kirsher 		err = -ENOMEM;
1103baf0fbfeSJeff Kirsher 		goto err_alloc_etherdev;
1104baf0fbfeSJeff Kirsher 	}
1105baf0fbfeSJeff Kirsher 
1106baf0fbfeSJeff Kirsher 	SET_NETDEV_DEV(netdev, &pdev->dev);
11077ad24ea4SWilfried Klaebe 	netdev->ethtool_ops = &ftmac100_ethtool_ops;
1108baf0fbfeSJeff Kirsher 	netdev->netdev_ops = &ftmac100_netdev_ops;
110930f837b7SVladimir Oltean 	netdev->max_mtu = MAX_PKT_SIZE - VLAN_ETH_HLEN;
1110baf0fbfeSJeff Kirsher 
1111f7650d82SSergei Antonov 	err = platform_get_ethdev_address(&pdev->dev, netdev);
1112f7650d82SSergei Antonov 	if (err == -EPROBE_DEFER)
1113f7650d82SSergei Antonov 		goto defer_get_mac;
1114f7650d82SSergei Antonov 
1115baf0fbfeSJeff Kirsher 	platform_set_drvdata(pdev, netdev);
1116baf0fbfeSJeff Kirsher 
1117baf0fbfeSJeff Kirsher 	/* setup private data */
1118baf0fbfeSJeff Kirsher 	priv = netdev_priv(netdev);
1119baf0fbfeSJeff Kirsher 	priv->netdev = netdev;
1120baf0fbfeSJeff Kirsher 	priv->dev = &pdev->dev;
1121baf0fbfeSJeff Kirsher 
1122baf0fbfeSJeff Kirsher 	spin_lock_init(&priv->tx_lock);
1123baf0fbfeSJeff Kirsher 
1124baf0fbfeSJeff Kirsher 	/* initialize NAPI */
1125b48b89f9SJakub Kicinski 	netif_napi_add(netdev, &priv->napi, ftmac100_poll);
1126baf0fbfeSJeff Kirsher 
1127baf0fbfeSJeff Kirsher 	/* map io memory */
1128baf0fbfeSJeff Kirsher 	priv->res = request_mem_region(res->start, resource_size(res),
1129baf0fbfeSJeff Kirsher 				       dev_name(&pdev->dev));
1130baf0fbfeSJeff Kirsher 	if (!priv->res) {
1131baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Could not reserve memory region\n");
1132baf0fbfeSJeff Kirsher 		err = -ENOMEM;
1133baf0fbfeSJeff Kirsher 		goto err_req_mem;
1134baf0fbfeSJeff Kirsher 	}
1135baf0fbfeSJeff Kirsher 
1136baf0fbfeSJeff Kirsher 	priv->base = ioremap(res->start, resource_size(res));
1137baf0fbfeSJeff Kirsher 	if (!priv->base) {
1138baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
1139baf0fbfeSJeff Kirsher 		err = -EIO;
1140baf0fbfeSJeff Kirsher 		goto err_ioremap;
1141baf0fbfeSJeff Kirsher 	}
1142baf0fbfeSJeff Kirsher 
1143baf0fbfeSJeff Kirsher 	priv->irq = irq;
1144baf0fbfeSJeff Kirsher 
1145baf0fbfeSJeff Kirsher 	/* initialize struct mii_if_info */
1146baf0fbfeSJeff Kirsher 	priv->mii.phy_id	= 0;
1147baf0fbfeSJeff Kirsher 	priv->mii.phy_id_mask	= 0x1f;
1148baf0fbfeSJeff Kirsher 	priv->mii.reg_num_mask	= 0x1f;
1149baf0fbfeSJeff Kirsher 	priv->mii.dev		= netdev;
1150baf0fbfeSJeff Kirsher 	priv->mii.mdio_read	= ftmac100_mdio_read;
1151baf0fbfeSJeff Kirsher 	priv->mii.mdio_write	= ftmac100_mdio_write;
1152baf0fbfeSJeff Kirsher 
1153baf0fbfeSJeff Kirsher 	/* register network device */
1154baf0fbfeSJeff Kirsher 	err = register_netdev(netdev);
1155baf0fbfeSJeff Kirsher 	if (err) {
1156baf0fbfeSJeff Kirsher 		dev_err(&pdev->dev, "Failed to register netdev\n");
1157baf0fbfeSJeff Kirsher 		goto err_register_netdev;
1158baf0fbfeSJeff Kirsher 	}
1159baf0fbfeSJeff Kirsher 
1160baf0fbfeSJeff Kirsher 	netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
1161baf0fbfeSJeff Kirsher 
1162baf0fbfeSJeff Kirsher 	if (!is_valid_ether_addr(netdev->dev_addr)) {
1163f2cedb63SDanny Kukawka 		eth_hw_addr_random(netdev);
1164baf0fbfeSJeff Kirsher 		netdev_info(netdev, "generated random MAC address %pM\n",
1165baf0fbfeSJeff Kirsher 			    netdev->dev_addr);
1166baf0fbfeSJeff Kirsher 	}
1167baf0fbfeSJeff Kirsher 
1168baf0fbfeSJeff Kirsher 	return 0;
1169baf0fbfeSJeff Kirsher 
1170baf0fbfeSJeff Kirsher err_register_netdev:
1171baf0fbfeSJeff Kirsher 	iounmap(priv->base);
1172baf0fbfeSJeff Kirsher err_ioremap:
1173baf0fbfeSJeff Kirsher 	release_resource(priv->res);
1174baf0fbfeSJeff Kirsher err_req_mem:
1175baf0fbfeSJeff Kirsher 	netif_napi_del(&priv->napi);
1176f7650d82SSergei Antonov defer_get_mac:
1177baf0fbfeSJeff Kirsher 	free_netdev(netdev);
1178baf0fbfeSJeff Kirsher err_alloc_etherdev:
1179baf0fbfeSJeff Kirsher 	return err;
1180baf0fbfeSJeff Kirsher }
1181baf0fbfeSJeff Kirsher 
1182be12502eSDmitry Torokhov static int ftmac100_remove(struct platform_device *pdev)
1183baf0fbfeSJeff Kirsher {
1184baf0fbfeSJeff Kirsher 	struct net_device *netdev;
1185baf0fbfeSJeff Kirsher 	struct ftmac100 *priv;
1186baf0fbfeSJeff Kirsher 
1187baf0fbfeSJeff Kirsher 	netdev = platform_get_drvdata(pdev);
1188baf0fbfeSJeff Kirsher 	priv = netdev_priv(netdev);
1189baf0fbfeSJeff Kirsher 
1190baf0fbfeSJeff Kirsher 	unregister_netdev(netdev);
1191baf0fbfeSJeff Kirsher 
1192baf0fbfeSJeff Kirsher 	iounmap(priv->base);
1193baf0fbfeSJeff Kirsher 	release_resource(priv->res);
1194baf0fbfeSJeff Kirsher 
1195baf0fbfeSJeff Kirsher 	netif_napi_del(&priv->napi);
1196baf0fbfeSJeff Kirsher 	free_netdev(netdev);
1197baf0fbfeSJeff Kirsher 	return 0;
1198baf0fbfeSJeff Kirsher }
1199baf0fbfeSJeff Kirsher 
120047ab37a1SGreentime Hu static const struct of_device_id ftmac100_of_ids[] = {
120147ab37a1SGreentime Hu 	{ .compatible = "andestech,atmac100" },
120247ab37a1SGreentime Hu 	{ }
120347ab37a1SGreentime Hu };
120447ab37a1SGreentime Hu 
1205baf0fbfeSJeff Kirsher static struct platform_driver ftmac100_driver = {
1206baf0fbfeSJeff Kirsher 	.probe		= ftmac100_probe,
1207be12502eSDmitry Torokhov 	.remove		= ftmac100_remove,
1208baf0fbfeSJeff Kirsher 	.driver		= {
1209baf0fbfeSJeff Kirsher 		.name	= DRV_NAME,
121047ab37a1SGreentime Hu 		.of_match_table = ftmac100_of_ids
1211baf0fbfeSJeff Kirsher 	},
1212baf0fbfeSJeff Kirsher };
1213baf0fbfeSJeff Kirsher 
1214baf0fbfeSJeff Kirsher /******************************************************************************
1215baf0fbfeSJeff Kirsher  * initialization / finalization
1216baf0fbfeSJeff Kirsher  *****************************************************************************/
1217d280a2c2SZhichao Cai module_platform_driver(ftmac100_driver);
1218baf0fbfeSJeff Kirsher 
1219baf0fbfeSJeff Kirsher MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
1220baf0fbfeSJeff Kirsher MODULE_DESCRIPTION("FTMAC100 driver");
1221baf0fbfeSJeff Kirsher MODULE_LICENSE("GPL");
122247ab37a1SGreentime Hu MODULE_DEVICE_TABLE(of, ftmac100_of_ids);
1223