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