xref: /openbmc/linux/drivers/net/ethernet/freescale/fs_enet/mac-fec.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1ec21e2ecSJeff Kirsher /*
2ec21e2ecSJeff Kirsher  * Freescale Ethernet controllers
3ec21e2ecSJeff Kirsher  *
4ec21e2ecSJeff Kirsher  * Copyright (c) 2005 Intracom S.A.
5ec21e2ecSJeff Kirsher  *  by Pantelis Antoniou <panto@intracom.gr>
6ec21e2ecSJeff Kirsher  *
7ec21e2ecSJeff Kirsher  * 2005 (c) MontaVista Software, Inc.
8ec21e2ecSJeff Kirsher  * Vitaly Bordug <vbordug@ru.mvista.com>
9ec21e2ecSJeff Kirsher  *
10ec21e2ecSJeff Kirsher  * This file is licensed under the terms of the GNU General Public License
11ec21e2ecSJeff Kirsher  * version 2. This program is licensed "as is" without any warranty of any
12ec21e2ecSJeff Kirsher  * kind, whether express or implied.
13ec21e2ecSJeff Kirsher  */
14ec21e2ecSJeff Kirsher 
15ec21e2ecSJeff Kirsher #include <linux/module.h>
16ec21e2ecSJeff Kirsher #include <linux/kernel.h>
17ec21e2ecSJeff Kirsher #include <linux/types.h>
18ec21e2ecSJeff Kirsher #include <linux/string.h>
19ec21e2ecSJeff Kirsher #include <linux/ptrace.h>
20ec21e2ecSJeff Kirsher #include <linux/errno.h>
21d805f6a8SKrzysztof Kozlowski #include <linux/crc32.h>
22ec21e2ecSJeff Kirsher #include <linux/ioport.h>
23ec21e2ecSJeff Kirsher #include <linux/interrupt.h>
24ec21e2ecSJeff Kirsher #include <linux/delay.h>
25ec21e2ecSJeff Kirsher #include <linux/netdevice.h>
26ec21e2ecSJeff Kirsher #include <linux/etherdevice.h>
27ec21e2ecSJeff Kirsher #include <linux/skbuff.h>
28ec21e2ecSJeff Kirsher #include <linux/spinlock.h>
29ec21e2ecSJeff Kirsher #include <linux/mii.h>
30ec21e2ecSJeff Kirsher #include <linux/ethtool.h>
31ec21e2ecSJeff Kirsher #include <linux/bitops.h>
32ec21e2ecSJeff Kirsher #include <linux/fs.h>
33ec21e2ecSJeff Kirsher #include <linux/platform_device.h>
345af50730SRob Herring #include <linux/of_address.h>
355af50730SRob Herring #include <linux/of_irq.h>
36ec21e2ecSJeff Kirsher #include <linux/gfp.h>
37ec21e2ecSJeff Kirsher 
38ec21e2ecSJeff Kirsher #include <asm/irq.h>
397c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
40ec21e2ecSJeff Kirsher 
41ec21e2ecSJeff Kirsher #include "fs_enet.h"
42ec21e2ecSJeff Kirsher #include "fec.h"
43ec21e2ecSJeff Kirsher 
44ec21e2ecSJeff Kirsher /*************************************************/
45ec21e2ecSJeff Kirsher 
46ec21e2ecSJeff Kirsher #if defined(CONFIG_CPM1)
47ec21e2ecSJeff Kirsher /* for a CPM1 __raw_xxx's are sufficient */
48ec21e2ecSJeff Kirsher #define __fs_out32(addr, x)	__raw_writel(x, addr)
49ec21e2ecSJeff Kirsher #define __fs_out16(addr, x)	__raw_writew(x, addr)
50ec21e2ecSJeff Kirsher #define __fs_in32(addr)	__raw_readl(addr)
51ec21e2ecSJeff Kirsher #define __fs_in16(addr)	__raw_readw(addr)
52ec21e2ecSJeff Kirsher #else
53ec21e2ecSJeff Kirsher /* for others play it safe */
54ec21e2ecSJeff Kirsher #define __fs_out32(addr, x)	out_be32(addr, x)
55ec21e2ecSJeff Kirsher #define __fs_out16(addr, x)	out_be16(addr, x)
56ec21e2ecSJeff Kirsher #define __fs_in32(addr)	in_be32(addr)
57ec21e2ecSJeff Kirsher #define __fs_in16(addr)	in_be16(addr)
58ec21e2ecSJeff Kirsher #endif
59ec21e2ecSJeff Kirsher 
60ec21e2ecSJeff Kirsher /* write */
61ec21e2ecSJeff Kirsher #define FW(_fecp, _reg, _v) __fs_out32(&(_fecp)->fec_ ## _reg, (_v))
62ec21e2ecSJeff Kirsher 
63ec21e2ecSJeff Kirsher /* read */
64ec21e2ecSJeff Kirsher #define FR(_fecp, _reg)	__fs_in32(&(_fecp)->fec_ ## _reg)
65ec21e2ecSJeff Kirsher 
66ec21e2ecSJeff Kirsher /* set bits */
67ec21e2ecSJeff Kirsher #define FS(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) | (_v))
68ec21e2ecSJeff Kirsher 
69ec21e2ecSJeff Kirsher /* clear bits */
70ec21e2ecSJeff Kirsher #define FC(_fecp, _reg, _v) FW(_fecp, _reg, FR(_fecp, _reg) & ~(_v))
71ec21e2ecSJeff Kirsher 
72ec21e2ecSJeff Kirsher /*
73ec21e2ecSJeff Kirsher  * Delay to wait for FEC reset command to complete (in us)
74ec21e2ecSJeff Kirsher  */
75ec21e2ecSJeff Kirsher #define FEC_RESET_DELAY		50
76ec21e2ecSJeff Kirsher 
whack_reset(struct fec __iomem * fecp)77ec21e2ecSJeff Kirsher static int whack_reset(struct fec __iomem *fecp)
78ec21e2ecSJeff Kirsher {
79ec21e2ecSJeff Kirsher 	int i;
80ec21e2ecSJeff Kirsher 
81ec21e2ecSJeff Kirsher 	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET);
82ec21e2ecSJeff Kirsher 	for (i = 0; i < FEC_RESET_DELAY; i++) {
83ec21e2ecSJeff Kirsher 		if ((FR(fecp, ecntrl) & FEC_ECNTRL_RESET) == 0)
84ec21e2ecSJeff Kirsher 			return 0;	/* OK */
85ec21e2ecSJeff Kirsher 		udelay(1);
86ec21e2ecSJeff Kirsher 	}
87ec21e2ecSJeff Kirsher 
88ec21e2ecSJeff Kirsher 	return -1;
89ec21e2ecSJeff Kirsher }
90ec21e2ecSJeff Kirsher 
do_pd_setup(struct fs_enet_private * fep)91ec21e2ecSJeff Kirsher static int do_pd_setup(struct fs_enet_private *fep)
92ec21e2ecSJeff Kirsher {
93ec21e2ecSJeff Kirsher 	struct platform_device *ofdev = to_platform_device(fep->dev);
94ec21e2ecSJeff Kirsher 
95f7578496SThierry Reding 	fep->interrupt = irq_of_parse_and_map(ofdev->dev.of_node, 0);
9699c1790eSMichael Ellerman 	if (!fep->interrupt)
97ec21e2ecSJeff Kirsher 		return -EINVAL;
98ec21e2ecSJeff Kirsher 
99ec21e2ecSJeff Kirsher 	fep->fec.fecp = of_iomap(ofdev->dev.of_node, 0);
100*ec3f06b5SZheng Yongjun 	if (!fep->fec.fecp)
101ec21e2ecSJeff Kirsher 		return -EINVAL;
102ec21e2ecSJeff Kirsher 
103ec21e2ecSJeff Kirsher 	return 0;
104ec21e2ecSJeff Kirsher }
105ec21e2ecSJeff Kirsher 
1068572763aSChristophe Leroy #define FEC_NAPI_EVENT_MSK	(FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_TXF)
1078572763aSChristophe Leroy #define FEC_EVENT		(FEC_ENET_RXF | FEC_ENET_TXF)
108ec21e2ecSJeff Kirsher #define FEC_ERR_EVENT_MSK	(FEC_ENET_HBERR | FEC_ENET_BABR | \
109ec21e2ecSJeff Kirsher 				 FEC_ENET_BABT | FEC_ENET_EBERR)
110ec21e2ecSJeff Kirsher 
setup_data(struct net_device * dev)111ec21e2ecSJeff Kirsher static int setup_data(struct net_device *dev)
112ec21e2ecSJeff Kirsher {
113ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
114ec21e2ecSJeff Kirsher 
115ec21e2ecSJeff Kirsher 	if (do_pd_setup(fep) != 0)
116ec21e2ecSJeff Kirsher 		return -EINVAL;
117ec21e2ecSJeff Kirsher 
118ec21e2ecSJeff Kirsher 	fep->fec.hthi = 0;
119ec21e2ecSJeff Kirsher 	fep->fec.htlo = 0;
120ec21e2ecSJeff Kirsher 
1218572763aSChristophe Leroy 	fep->ev_napi = FEC_NAPI_EVENT_MSK;
1228572763aSChristophe Leroy 	fep->ev = FEC_EVENT;
123ec21e2ecSJeff Kirsher 	fep->ev_err = FEC_ERR_EVENT_MSK;
124ec21e2ecSJeff Kirsher 
125ec21e2ecSJeff Kirsher 	return 0;
126ec21e2ecSJeff Kirsher }
127ec21e2ecSJeff Kirsher 
allocate_bd(struct net_device * dev)128ec21e2ecSJeff Kirsher static int allocate_bd(struct net_device *dev)
129ec21e2ecSJeff Kirsher {
130ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
131ec21e2ecSJeff Kirsher 	const struct fs_platform_info *fpi = fep->fpi;
132ec21e2ecSJeff Kirsher 
133ec21e2ecSJeff Kirsher 	fep->ring_base = (void __force __iomem *)dma_alloc_coherent(fep->dev,
134ec21e2ecSJeff Kirsher 					    (fpi->tx_ring + fpi->rx_ring) *
135ec21e2ecSJeff Kirsher 					    sizeof(cbd_t), &fep->ring_mem_addr,
136ec21e2ecSJeff Kirsher 					    GFP_KERNEL);
137ec21e2ecSJeff Kirsher 	if (fep->ring_base == NULL)
138ec21e2ecSJeff Kirsher 		return -ENOMEM;
139ec21e2ecSJeff Kirsher 
140ec21e2ecSJeff Kirsher 	return 0;
141ec21e2ecSJeff Kirsher }
142ec21e2ecSJeff Kirsher 
free_bd(struct net_device * dev)143ec21e2ecSJeff Kirsher static void free_bd(struct net_device *dev)
144ec21e2ecSJeff Kirsher {
145ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
146ec21e2ecSJeff Kirsher 	const struct fs_platform_info *fpi = fep->fpi;
147ec21e2ecSJeff Kirsher 
148ec21e2ecSJeff Kirsher 	if(fep->ring_base)
149ec21e2ecSJeff Kirsher 		dma_free_coherent(fep->dev, (fpi->tx_ring + fpi->rx_ring)
150ec21e2ecSJeff Kirsher 					* sizeof(cbd_t),
151ec21e2ecSJeff Kirsher 					(void __force *)fep->ring_base,
152ec21e2ecSJeff Kirsher 					fep->ring_mem_addr);
153ec21e2ecSJeff Kirsher }
154ec21e2ecSJeff Kirsher 
cleanup_data(struct net_device * dev)155ec21e2ecSJeff Kirsher static void cleanup_data(struct net_device *dev)
156ec21e2ecSJeff Kirsher {
157ec21e2ecSJeff Kirsher 	/* nothing */
158ec21e2ecSJeff Kirsher }
159ec21e2ecSJeff Kirsher 
set_promiscuous_mode(struct net_device * dev)160ec21e2ecSJeff Kirsher static void set_promiscuous_mode(struct net_device *dev)
161ec21e2ecSJeff Kirsher {
162ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
163ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
164ec21e2ecSJeff Kirsher 
165ec21e2ecSJeff Kirsher 	FS(fecp, r_cntrl, FEC_RCNTRL_PROM);
166ec21e2ecSJeff Kirsher }
167ec21e2ecSJeff Kirsher 
set_multicast_start(struct net_device * dev)168ec21e2ecSJeff Kirsher static void set_multicast_start(struct net_device *dev)
169ec21e2ecSJeff Kirsher {
170ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
171ec21e2ecSJeff Kirsher 
172ec21e2ecSJeff Kirsher 	fep->fec.hthi = 0;
173ec21e2ecSJeff Kirsher 	fep->fec.htlo = 0;
174ec21e2ecSJeff Kirsher }
175ec21e2ecSJeff Kirsher 
set_multicast_one(struct net_device * dev,const u8 * mac)176ec21e2ecSJeff Kirsher static void set_multicast_one(struct net_device *dev, const u8 *mac)
177ec21e2ecSJeff Kirsher {
178ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
179d805f6a8SKrzysztof Kozlowski 	int temp, hash_index;
180ec21e2ecSJeff Kirsher 	u32 crc, csrVal;
181ec21e2ecSJeff Kirsher 
182d805f6a8SKrzysztof Kozlowski 	crc = ether_crc(6, mac);
183ec21e2ecSJeff Kirsher 
184ec21e2ecSJeff Kirsher 	temp = (crc & 0x3f) >> 1;
185ec21e2ecSJeff Kirsher 	hash_index = ((temp & 0x01) << 4) |
186ec21e2ecSJeff Kirsher 		     ((temp & 0x02) << 2) |
187ec21e2ecSJeff Kirsher 		     ((temp & 0x04)) |
188ec21e2ecSJeff Kirsher 		     ((temp & 0x08) >> 2) |
189ec21e2ecSJeff Kirsher 		     ((temp & 0x10) >> 4);
190ec21e2ecSJeff Kirsher 	csrVal = 1 << hash_index;
191ec21e2ecSJeff Kirsher 	if (crc & 1)
192ec21e2ecSJeff Kirsher 		fep->fec.hthi |= csrVal;
193ec21e2ecSJeff Kirsher 	else
194ec21e2ecSJeff Kirsher 		fep->fec.htlo |= csrVal;
195ec21e2ecSJeff Kirsher }
196ec21e2ecSJeff Kirsher 
set_multicast_finish(struct net_device * dev)197ec21e2ecSJeff Kirsher static void set_multicast_finish(struct net_device *dev)
198ec21e2ecSJeff Kirsher {
199ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
200ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
201ec21e2ecSJeff Kirsher 
202ec21e2ecSJeff Kirsher 	/* if all multi or too many multicasts; just enable all */
203ec21e2ecSJeff Kirsher 	if ((dev->flags & IFF_ALLMULTI) != 0 ||
204ec21e2ecSJeff Kirsher 	    netdev_mc_count(dev) > FEC_MAX_MULTICAST_ADDRS) {
205ec21e2ecSJeff Kirsher 		fep->fec.hthi = 0xffffffffU;
206ec21e2ecSJeff Kirsher 		fep->fec.htlo = 0xffffffffU;
207ec21e2ecSJeff Kirsher 	}
208ec21e2ecSJeff Kirsher 
209ec21e2ecSJeff Kirsher 	FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
210ec21e2ecSJeff Kirsher 	FW(fecp, grp_hash_table_high, fep->fec.hthi);
211ec21e2ecSJeff Kirsher 	FW(fecp, grp_hash_table_low, fep->fec.htlo);
212ec21e2ecSJeff Kirsher }
213ec21e2ecSJeff Kirsher 
set_multicast_list(struct net_device * dev)214ec21e2ecSJeff Kirsher static void set_multicast_list(struct net_device *dev)
215ec21e2ecSJeff Kirsher {
216ec21e2ecSJeff Kirsher 	struct netdev_hw_addr *ha;
217ec21e2ecSJeff Kirsher 
218ec21e2ecSJeff Kirsher 	if ((dev->flags & IFF_PROMISC) == 0) {
219ec21e2ecSJeff Kirsher 		set_multicast_start(dev);
220ec21e2ecSJeff Kirsher 		netdev_for_each_mc_addr(ha, dev)
221ec21e2ecSJeff Kirsher 			set_multicast_one(dev, ha->addr);
222ec21e2ecSJeff Kirsher 		set_multicast_finish(dev);
223ec21e2ecSJeff Kirsher 	} else
224ec21e2ecSJeff Kirsher 		set_promiscuous_mode(dev);
225ec21e2ecSJeff Kirsher }
226ec21e2ecSJeff Kirsher 
restart(struct net_device * dev)227ec21e2ecSJeff Kirsher static void restart(struct net_device *dev)
228ec21e2ecSJeff Kirsher {
229ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
230ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
231ec21e2ecSJeff Kirsher 	const struct fs_platform_info *fpi = fep->fpi;
232ec21e2ecSJeff Kirsher 	dma_addr_t rx_bd_base_phys, tx_bd_base_phys;
233ec21e2ecSJeff Kirsher 	int r;
234ec21e2ecSJeff Kirsher 	u32 addrhi, addrlo;
235ec21e2ecSJeff Kirsher 
236c1c511a2SPhilippe Reynes 	struct mii_bus *mii = dev->phydev->mdio.bus;
237ec21e2ecSJeff Kirsher 	struct fec_info* fec_inf = mii->priv;
238ec21e2ecSJeff Kirsher 
239ec21e2ecSJeff Kirsher 	r = whack_reset(fep->fec.fecp);
240ec21e2ecSJeff Kirsher 	if (r != 0)
241ec21e2ecSJeff Kirsher 		dev_err(fep->dev, "FEC Reset FAILED!\n");
242ec21e2ecSJeff Kirsher 	/*
243ec21e2ecSJeff Kirsher 	 * Set station address.
244ec21e2ecSJeff Kirsher 	 */
245ec21e2ecSJeff Kirsher 	addrhi = ((u32) dev->dev_addr[0] << 24) |
246ec21e2ecSJeff Kirsher 		 ((u32) dev->dev_addr[1] << 16) |
247ec21e2ecSJeff Kirsher 		 ((u32) dev->dev_addr[2] <<  8) |
248ec21e2ecSJeff Kirsher 		  (u32) dev->dev_addr[3];
249ec21e2ecSJeff Kirsher 	addrlo = ((u32) dev->dev_addr[4] << 24) |
250ec21e2ecSJeff Kirsher 		 ((u32) dev->dev_addr[5] << 16);
251ec21e2ecSJeff Kirsher 	FW(fecp, addr_low, addrhi);
252ec21e2ecSJeff Kirsher 	FW(fecp, addr_high, addrlo);
253ec21e2ecSJeff Kirsher 
254ec21e2ecSJeff Kirsher 	/*
255ec21e2ecSJeff Kirsher 	 * Reset all multicast.
256ec21e2ecSJeff Kirsher 	 */
257ec21e2ecSJeff Kirsher 	FW(fecp, grp_hash_table_high, fep->fec.hthi);
258ec21e2ecSJeff Kirsher 	FW(fecp, grp_hash_table_low, fep->fec.htlo);
259ec21e2ecSJeff Kirsher 
260ec21e2ecSJeff Kirsher 	/*
261ec21e2ecSJeff Kirsher 	 * Set maximum receive buffer size.
262ec21e2ecSJeff Kirsher 	 */
263ec21e2ecSJeff Kirsher 	FW(fecp, r_buff_size, PKT_MAXBLR_SIZE);
264ec21e2ecSJeff Kirsher #ifdef CONFIG_FS_ENET_MPC5121_FEC
265ec21e2ecSJeff Kirsher 	FW(fecp, r_cntrl, PKT_MAXBUF_SIZE << 16);
266ec21e2ecSJeff Kirsher #else
267ec21e2ecSJeff Kirsher 	FW(fecp, r_hash, PKT_MAXBUF_SIZE);
268ec21e2ecSJeff Kirsher #endif
269ec21e2ecSJeff Kirsher 
270ec21e2ecSJeff Kirsher 	/* get physical address */
271ec21e2ecSJeff Kirsher 	rx_bd_base_phys = fep->ring_mem_addr;
272ec21e2ecSJeff Kirsher 	tx_bd_base_phys = rx_bd_base_phys + sizeof(cbd_t) * fpi->rx_ring;
273ec21e2ecSJeff Kirsher 
274ec21e2ecSJeff Kirsher 	/*
275ec21e2ecSJeff Kirsher 	 * Set receive and transmit descriptor base.
276ec21e2ecSJeff Kirsher 	 */
277ec21e2ecSJeff Kirsher 	FW(fecp, r_des_start, rx_bd_base_phys);
278ec21e2ecSJeff Kirsher 	FW(fecp, x_des_start, tx_bd_base_phys);
279ec21e2ecSJeff Kirsher 
280ec21e2ecSJeff Kirsher 	fs_init_bds(dev);
281ec21e2ecSJeff Kirsher 
282ec21e2ecSJeff Kirsher 	/*
283ec21e2ecSJeff Kirsher 	 * Enable big endian and don't care about SDMA FC.
284ec21e2ecSJeff Kirsher 	 */
285ec21e2ecSJeff Kirsher #ifdef CONFIG_FS_ENET_MPC5121_FEC
286ec21e2ecSJeff Kirsher 	FS(fecp, dma_control, 0xC0000000);
287ec21e2ecSJeff Kirsher #else
288ec21e2ecSJeff Kirsher 	FW(fecp, fun_code, 0x78000000);
289ec21e2ecSJeff Kirsher #endif
290ec21e2ecSJeff Kirsher 
291ec21e2ecSJeff Kirsher 	/*
292ec21e2ecSJeff Kirsher 	 * Set MII speed.
293ec21e2ecSJeff Kirsher 	 */
294ec21e2ecSJeff Kirsher 	FW(fecp, mii_speed, fec_inf->mii_speed);
295ec21e2ecSJeff Kirsher 
296ec21e2ecSJeff Kirsher 	/*
297ec21e2ecSJeff Kirsher 	 * Clear any outstanding interrupt.
298ec21e2ecSJeff Kirsher 	 */
299ec21e2ecSJeff Kirsher 	FW(fecp, ievent, 0xffc0);
300ec21e2ecSJeff Kirsher #ifndef CONFIG_FS_ENET_MPC5121_FEC
301ec21e2ecSJeff Kirsher 	FW(fecp, ivec, (virq_to_hw(fep->interrupt) / 2) << 29);
302ec21e2ecSJeff Kirsher 
303ec21e2ecSJeff Kirsher 	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
304ec21e2ecSJeff Kirsher #else
305ec21e2ecSJeff Kirsher 	/*
306ba568335SVladimir Ermakov 	 * Only set MII/RMII mode - do not touch maximum frame length
307ec21e2ecSJeff Kirsher 	 * configured before.
308ec21e2ecSJeff Kirsher 	 */
309ba568335SVladimir Ermakov 	FS(fecp, r_cntrl, fpi->use_rmii ?
310ba568335SVladimir Ermakov 			FEC_RCNTRL_RMII_MODE : FEC_RCNTRL_MII_MODE);
311ec21e2ecSJeff Kirsher #endif
312ec21e2ecSJeff Kirsher 	/*
313ec21e2ecSJeff Kirsher 	 * adjust to duplex mode
314ec21e2ecSJeff Kirsher 	 */
315c1c511a2SPhilippe Reynes 	if (dev->phydev->duplex) {
316ec21e2ecSJeff Kirsher 		FC(fecp, r_cntrl, FEC_RCNTRL_DRT);
317ec21e2ecSJeff Kirsher 		FS(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD enable */
318ec21e2ecSJeff Kirsher 	} else {
319ec21e2ecSJeff Kirsher 		FS(fecp, r_cntrl, FEC_RCNTRL_DRT);
320ec21e2ecSJeff Kirsher 		FC(fecp, x_cntrl, FEC_TCNTRL_FDEN);	/* FD disable */
321ec21e2ecSJeff Kirsher 	}
322ec21e2ecSJeff Kirsher 
3238751b12cSLEROY Christophe 	/* Restore multicast and promiscuous settings */
3248751b12cSLEROY Christophe 	set_multicast_list(dev);
3258751b12cSLEROY Christophe 
326ec21e2ecSJeff Kirsher 	/*
327ec21e2ecSJeff Kirsher 	 * Enable interrupts we wish to service.
328ec21e2ecSJeff Kirsher 	 */
329ec21e2ecSJeff Kirsher 	FW(fecp, imask, FEC_ENET_TXF | FEC_ENET_TXB |
330ec21e2ecSJeff Kirsher 	   FEC_ENET_RXF | FEC_ENET_RXB);
331ec21e2ecSJeff Kirsher 
332ec21e2ecSJeff Kirsher 	/*
333ec21e2ecSJeff Kirsher 	 * And last, enable the transmit and receive processing.
334ec21e2ecSJeff Kirsher 	 */
335ec21e2ecSJeff Kirsher 	FW(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
336ec21e2ecSJeff Kirsher 	FW(fecp, r_des_active, 0x01000000);
337ec21e2ecSJeff Kirsher }
338ec21e2ecSJeff Kirsher 
stop(struct net_device * dev)339ec21e2ecSJeff Kirsher static void stop(struct net_device *dev)
340ec21e2ecSJeff Kirsher {
341ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
342ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
343ec21e2ecSJeff Kirsher 	int i;
344ec21e2ecSJeff Kirsher 
345ec21e2ecSJeff Kirsher 	if ((FR(fecp, ecntrl) & FEC_ECNTRL_ETHER_EN) == 0)
346ec21e2ecSJeff Kirsher 		return;		/* already down */
347ec21e2ecSJeff Kirsher 
348ec21e2ecSJeff Kirsher 	FW(fecp, x_cntrl, 0x01);	/* Graceful transmit stop */
349ec21e2ecSJeff Kirsher 	for (i = 0; ((FR(fecp, ievent) & 0x10000000) == 0) &&
350ec21e2ecSJeff Kirsher 	     i < FEC_RESET_DELAY; i++)
351ec21e2ecSJeff Kirsher 		udelay(1);
352ec21e2ecSJeff Kirsher 
353ec21e2ecSJeff Kirsher 	if (i == FEC_RESET_DELAY)
354ec21e2ecSJeff Kirsher 		dev_warn(fep->dev, "FEC timeout on graceful transmit stop\n");
355ec21e2ecSJeff Kirsher 	/*
356ec21e2ecSJeff Kirsher 	 * Disable FEC. Let only MII interrupts.
357ec21e2ecSJeff Kirsher 	 */
358ec21e2ecSJeff Kirsher 	FW(fecp, imask, 0);
359ec21e2ecSJeff Kirsher 	FC(fecp, ecntrl, FEC_ECNTRL_ETHER_EN);
360ec21e2ecSJeff Kirsher 
361ec21e2ecSJeff Kirsher 	fs_cleanup_bds(dev);
362ec21e2ecSJeff Kirsher }
363ec21e2ecSJeff Kirsher 
napi_clear_event_fs(struct net_device * dev)3648572763aSChristophe Leroy static void napi_clear_event_fs(struct net_device *dev)
365ec21e2ecSJeff Kirsher {
366ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
367ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
368ec21e2ecSJeff Kirsher 
3698572763aSChristophe Leroy 	FW(fecp, ievent, FEC_NAPI_EVENT_MSK);
370ec21e2ecSJeff Kirsher }
371ec21e2ecSJeff Kirsher 
napi_enable_fs(struct net_device * dev)3728572763aSChristophe Leroy static void napi_enable_fs(struct net_device *dev)
373ec21e2ecSJeff Kirsher {
374ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
375ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
376ec21e2ecSJeff Kirsher 
3778572763aSChristophe Leroy 	FS(fecp, imask, FEC_NAPI_EVENT_MSK);
378ec21e2ecSJeff Kirsher }
379ec21e2ecSJeff Kirsher 
napi_disable_fs(struct net_device * dev)3808572763aSChristophe Leroy static void napi_disable_fs(struct net_device *dev)
381ec21e2ecSJeff Kirsher {
382ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
383ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
384ec21e2ecSJeff Kirsher 
3858572763aSChristophe Leroy 	FC(fecp, imask, FEC_NAPI_EVENT_MSK);
386d43a396aSLEROY Christophe }
387d43a396aSLEROY Christophe 
rx_bd_done(struct net_device * dev)388ec21e2ecSJeff Kirsher static void rx_bd_done(struct net_device *dev)
389ec21e2ecSJeff Kirsher {
390ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
391ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
392ec21e2ecSJeff Kirsher 
393ec21e2ecSJeff Kirsher 	FW(fecp, r_des_active, 0x01000000);
394ec21e2ecSJeff Kirsher }
395ec21e2ecSJeff Kirsher 
tx_kickstart(struct net_device * dev)396ec21e2ecSJeff Kirsher static void tx_kickstart(struct net_device *dev)
397ec21e2ecSJeff Kirsher {
398ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
399ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
400ec21e2ecSJeff Kirsher 
401ec21e2ecSJeff Kirsher 	FW(fecp, x_des_active, 0x01000000);
402ec21e2ecSJeff Kirsher }
403ec21e2ecSJeff Kirsher 
get_int_events(struct net_device * dev)404ec21e2ecSJeff Kirsher static u32 get_int_events(struct net_device *dev)
405ec21e2ecSJeff Kirsher {
406ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
407ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
408ec21e2ecSJeff Kirsher 
409ec21e2ecSJeff Kirsher 	return FR(fecp, ievent) & FR(fecp, imask);
410ec21e2ecSJeff Kirsher }
411ec21e2ecSJeff Kirsher 
clear_int_events(struct net_device * dev,u32 int_events)412ec21e2ecSJeff Kirsher static void clear_int_events(struct net_device *dev, u32 int_events)
413ec21e2ecSJeff Kirsher {
414ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
415ec21e2ecSJeff Kirsher 	struct fec __iomem *fecp = fep->fec.fecp;
416ec21e2ecSJeff Kirsher 
417ec21e2ecSJeff Kirsher 	FW(fecp, ievent, int_events);
418ec21e2ecSJeff Kirsher }
419ec21e2ecSJeff Kirsher 
ev_error(struct net_device * dev,u32 int_events)420ec21e2ecSJeff Kirsher static void ev_error(struct net_device *dev, u32 int_events)
421ec21e2ecSJeff Kirsher {
422ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
423ec21e2ecSJeff Kirsher 
424ec21e2ecSJeff Kirsher 	dev_warn(fep->dev, "FEC ERROR(s) 0x%x\n", int_events);
425ec21e2ecSJeff Kirsher }
426ec21e2ecSJeff Kirsher 
get_regs(struct net_device * dev,void * p,int * sizep)427ec21e2ecSJeff Kirsher static int get_regs(struct net_device *dev, void *p, int *sizep)
428ec21e2ecSJeff Kirsher {
429ec21e2ecSJeff Kirsher 	struct fs_enet_private *fep = netdev_priv(dev);
430ec21e2ecSJeff Kirsher 
431ec21e2ecSJeff Kirsher 	if (*sizep < sizeof(struct fec))
432ec21e2ecSJeff Kirsher 		return -EINVAL;
433ec21e2ecSJeff Kirsher 
434ec21e2ecSJeff Kirsher 	memcpy_fromio(p, fep->fec.fecp, sizeof(struct fec));
435ec21e2ecSJeff Kirsher 
436ec21e2ecSJeff Kirsher 	return 0;
437ec21e2ecSJeff Kirsher }
438ec21e2ecSJeff Kirsher 
get_regs_len(struct net_device * dev)439ec21e2ecSJeff Kirsher static int get_regs_len(struct net_device *dev)
440ec21e2ecSJeff Kirsher {
441ec21e2ecSJeff Kirsher 	return sizeof(struct fec);
442ec21e2ecSJeff Kirsher }
443ec21e2ecSJeff Kirsher 
tx_restart(struct net_device * dev)444ec21e2ecSJeff Kirsher static void tx_restart(struct net_device *dev)
445ec21e2ecSJeff Kirsher {
446ec21e2ecSJeff Kirsher 	/* nothing */
447ec21e2ecSJeff Kirsher }
448ec21e2ecSJeff Kirsher 
449ec21e2ecSJeff Kirsher /*************************************************************************/
450ec21e2ecSJeff Kirsher 
451ec21e2ecSJeff Kirsher const struct fs_ops fs_fec_ops = {
452ec21e2ecSJeff Kirsher 	.setup_data		= setup_data,
453ec21e2ecSJeff Kirsher 	.cleanup_data		= cleanup_data,
454ec21e2ecSJeff Kirsher 	.set_multicast_list	= set_multicast_list,
455ec21e2ecSJeff Kirsher 	.restart		= restart,
456ec21e2ecSJeff Kirsher 	.stop			= stop,
4578572763aSChristophe Leroy 	.napi_clear_event	= napi_clear_event_fs,
4588572763aSChristophe Leroy 	.napi_enable		= napi_enable_fs,
4598572763aSChristophe Leroy 	.napi_disable		= napi_disable_fs,
460ec21e2ecSJeff Kirsher 	.rx_bd_done		= rx_bd_done,
461ec21e2ecSJeff Kirsher 	.tx_kickstart		= tx_kickstart,
462ec21e2ecSJeff Kirsher 	.get_int_events		= get_int_events,
463ec21e2ecSJeff Kirsher 	.clear_int_events	= clear_int_events,
464ec21e2ecSJeff Kirsher 	.ev_error		= ev_error,
465ec21e2ecSJeff Kirsher 	.get_regs		= get_regs,
466ec21e2ecSJeff Kirsher 	.get_regs_len		= get_regs_len,
467ec21e2ecSJeff Kirsher 	.tx_restart		= tx_restart,
468ec21e2ecSJeff Kirsher 	.allocate_bd		= allocate_bd,
469ec21e2ecSJeff Kirsher 	.free_bd		= free_bd,
470ec21e2ecSJeff Kirsher };
471ec21e2ecSJeff Kirsher 
472