blob: 31a076d86709f2256c9a1ebe4ab93d0a5e7c9c41 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Ralf Baechlef90fdc32006-02-08 23:23:26 +00002 * Copyright (C) 2001,2002,2003,2004 Broadcom Corporation
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01003 * Copyright (c) 2006, 2007 Maciej W. Rozycki
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
Ralf Baechle74b02472005-10-19 15:40:02 +010014 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070015 * You should have received a copy of the GNU General Public License
Jeff Kirsher0ab75ae2013-12-06 06:28:43 -080016 * along with this program; if not, see <http://www.gnu.org/licenses/>.
Linus Torvalds1da177e2005-04-16 15:20:36 -070017 *
18 *
19 * This driver is designed for the Broadcom SiByte SOC built-in
20 * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp.
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010021 *
22 * Updated to the driver model and the PHY abstraction layer
23 * by Maciej W. Rozycki.
Linus Torvalds1da177e2005-04-16 15:20:36 -070024 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010025
26#include <linux/bug.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/string.h>
30#include <linux/timer.h>
31#include <linux/errno.h>
32#include <linux/ioport.h>
33#include <linux/slab.h>
34#include <linux/interrupt.h>
35#include <linux/netdevice.h>
36#include <linux/etherdevice.h>
37#include <linux/skbuff.h>
38#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/bitops.h>
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010040#include <linux/err.h>
41#include <linux/ethtool.h>
42#include <linux/mii.h>
43#include <linux/phy.h>
44#include <linux/platform_device.h>
Paul Gortmaker70c71602011-05-22 16:47:17 -040045#include <linux/prefetch.h>
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010046
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#include <asm/cache.h>
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010048#include <asm/io.h>
49#include <asm/processor.h> /* Processor type for cache alignment. */
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
Linus Torvalds1da177e2005-04-16 15:20:36 -070051/* Operational parameters that usually are not changed. */
52
53#define CONFIG_SBMAC_COALESCE
54
Linus Torvalds1da177e2005-04-16 15:20:36 -070055/* Time in jiffies before concluding the transmitter is hung. */
56#define TX_TIMEOUT (2*HZ)
57
58
59MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
60MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
61
62/* A few user-configurable values which may be modified when a driver
63 module is loaded. */
64
65/* 1 normal messages, 0 quiet .. 7 verbose. */
66static int debug = 1;
67module_param(debug, int, S_IRUGO);
68MODULE_PARM_DESC(debug, "Debug messages");
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#ifdef CONFIG_SBMAC_COALESCE
Mark Mason693aa942007-04-26 00:23:22 -070071static int int_pktcnt_tx = 255;
72module_param(int_pktcnt_tx, int, S_IRUGO);
73MODULE_PARM_DESC(int_pktcnt_tx, "TX packet count");
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Mark Mason693aa942007-04-26 00:23:22 -070075static int int_timeout_tx = 255;
76module_param(int_timeout_tx, int, S_IRUGO);
77MODULE_PARM_DESC(int_timeout_tx, "TX timeout value");
78
79static int int_pktcnt_rx = 64;
80module_param(int_pktcnt_rx, int, S_IRUGO);
81MODULE_PARM_DESC(int_pktcnt_rx, "RX packet count");
82
83static int int_timeout_rx = 64;
84module_param(int_timeout_rx, int, S_IRUGO);
85MODULE_PARM_DESC(int_timeout_rx, "RX timeout value");
Linus Torvalds1da177e2005-04-16 15:20:36 -070086#endif
87
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +010088#include <asm/sibyte/board.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070089#include <asm/sibyte/sb1250.h>
Ralf Baechlef90fdc32006-02-08 23:23:26 +000090#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
91#include <asm/sibyte/bcm1480_regs.h>
92#include <asm/sibyte/bcm1480_int.h>
Mark Mason693aa942007-04-26 00:23:22 -070093#define R_MAC_DMA_OODPKTLOST_RX R_MAC_DMA_OODPKTLOST
Ralf Baechlef90fdc32006-02-08 23:23:26 +000094#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
Linus Torvalds1da177e2005-04-16 15:20:36 -070095#include <asm/sibyte/sb1250_regs.h>
Ralf Baechlef90fdc32006-02-08 23:23:26 +000096#include <asm/sibyte/sb1250_int.h>
97#else
Thomas Weber0b1974d2010-09-23 11:46:48 +020098#error invalid SiByte MAC configuration
Ralf Baechlef90fdc32006-02-08 23:23:26 +000099#endif
100#include <asm/sibyte/sb1250_scd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#include <asm/sibyte/sb1250_mac.h>
102#include <asm/sibyte/sb1250_dma.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103
Ralf Baechlef90fdc32006-02-08 23:23:26 +0000104#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
105#define UNIT_INT(n) (K_BCM1480_INT_MAC_0 + ((n) * 2))
106#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
107#define UNIT_INT(n) (K_INT_MAC_0 + (n))
108#else
Thomas Weber0b1974d2010-09-23 11:46:48 +0200109#error invalid SiByte MAC configuration
Ralf Baechlef90fdc32006-02-08 23:23:26 +0000110#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100112#ifdef K_INT_PHY
113#define SBMAC_PHY_INT K_INT_PHY
114#else
115#define SBMAC_PHY_INT PHY_POLL
116#endif
117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118/**********************************************************************
119 * Simple types
120 ********************************************************************* */
121
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100122enum sbmac_speed {
123 sbmac_speed_none = 0,
124 sbmac_speed_10 = SPEED_10,
125 sbmac_speed_100 = SPEED_100,
126 sbmac_speed_1000 = SPEED_1000,
127};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100129enum sbmac_duplex {
130 sbmac_duplex_none = -1,
131 sbmac_duplex_half = DUPLEX_HALF,
132 sbmac_duplex_full = DUPLEX_FULL,
133};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100135enum sbmac_fc {
136 sbmac_fc_none,
137 sbmac_fc_disabled,
138 sbmac_fc_frame,
139 sbmac_fc_collision,
140 sbmac_fc_carrier,
141};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100143enum sbmac_state {
144 sbmac_state_uninit,
145 sbmac_state_off,
146 sbmac_state_on,
147 sbmac_state_broken,
148};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150
151/**********************************************************************
152 * Macros
153 ********************************************************************* */
154
155
156#define SBDMA_NEXTBUF(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
157 (d)->sbdma_dscrtable : (d)->f+1)
158
159
160#define NUMCACHEBLKS(x) (((x)+SMP_CACHE_BYTES-1)/SMP_CACHE_BYTES)
161
Mark Mason693aa942007-04-26 00:23:22 -0700162#define SBMAC_MAX_TXDESCR 256
163#define SBMAC_MAX_RXDESCR 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164
Ralf Baechle74b02472005-10-19 15:40:02 +0100165#define ENET_PACKET_SIZE 1518
166/*#define ENET_PACKET_SIZE 9216 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
168/**********************************************************************
169 * DMA Descriptor structure
170 ********************************************************************* */
171
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100172struct sbdmadscr {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173 uint64_t dscr_a;
174 uint64_t dscr_b;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100175};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
177/**********************************************************************
178 * DMA Controller structure
179 ********************************************************************* */
180
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100181struct sbmacdma {
Ralf Baechle74b02472005-10-19 15:40:02 +0100182
183 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 * This stuff is used to identify the channel and the registers
185 * associated with it.
186 */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100187 struct sbmac_softc *sbdma_eth; /* back pointer to associated
188 MAC */
189 int sbdma_channel; /* channel number */
190 int sbdma_txdir; /* direction (1=transmit) */
191 int sbdma_maxdescr; /* total # of descriptors
192 in ring */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193#ifdef CONFIG_SBMAC_COALESCE
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100194 int sbdma_int_pktcnt;
195 /* # descriptors rx/tx
196 before interrupt */
197 int sbdma_int_timeout;
198 /* # usec rx/tx interrupt */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199#endif
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100200 void __iomem *sbdma_config0; /* DMA config register 0 */
201 void __iomem *sbdma_config1; /* DMA config register 1 */
202 void __iomem *sbdma_dscrbase;
203 /* descriptor base address */
204 void __iomem *sbdma_dscrcnt; /* descriptor count register */
205 void __iomem *sbdma_curdscr; /* current descriptor
206 address */
207 void __iomem *sbdma_oodpktlost;
208 /* pkt drop (rx only) */
Ralf Baechle74b02472005-10-19 15:40:02 +0100209
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 /*
211 * This stuff is for maintenance of the ring
212 */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100213 void *sbdma_dscrtable_unaligned;
214 struct sbdmadscr *sbdma_dscrtable;
215 /* base of descriptor table */
216 struct sbdmadscr *sbdma_dscrtable_end;
217 /* end of descriptor table */
218 struct sk_buff **sbdma_ctxtable;
219 /* context table, one
220 per descr */
221 dma_addr_t sbdma_dscrtable_phys;
222 /* and also the phys addr */
223 struct sbdmadscr *sbdma_addptr; /* next dscr for sw to add */
224 struct sbdmadscr *sbdma_remptr; /* next dscr for sw
225 to remove */
226};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
228
229/**********************************************************************
230 * Ethernet softc structure
231 ********************************************************************* */
232
233struct sbmac_softc {
Ralf Baechle74b02472005-10-19 15:40:02 +0100234
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 /*
236 * Linux-specific things
237 */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100238 struct net_device *sbm_dev; /* pointer to linux device */
239 struct napi_struct napi;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100240 struct phy_device *phy_dev; /* the associated PHY device */
Lennert Buytenhek298cf9b2008-10-08 16:29:57 -0700241 struct mii_bus *mii_bus; /* the MII bus */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100242 int phy_irq[PHY_MAX_ADDR];
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100243 spinlock_t sbm_lock; /* spin lock */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100244 int sbm_devflags; /* current device flags */
Ralf Baechle74b02472005-10-19 15:40:02 +0100245
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 /*
247 * Controller-specific things
248 */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100249 void __iomem *sbm_base; /* MAC's base address */
250 enum sbmac_state sbm_state; /* current state */
Ralf Baechle74b02472005-10-19 15:40:02 +0100251
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100252 void __iomem *sbm_macenable; /* MAC Enable Register */
253 void __iomem *sbm_maccfg; /* MAC Config Register */
254 void __iomem *sbm_fifocfg; /* FIFO Config Register */
255 void __iomem *sbm_framecfg; /* Frame Config Register */
256 void __iomem *sbm_rxfilter; /* Receive Filter Register */
257 void __iomem *sbm_isr; /* Interrupt Status Register */
258 void __iomem *sbm_imr; /* Interrupt Mask Register */
259 void __iomem *sbm_mdio; /* MDIO Register */
Ralf Baechle74b02472005-10-19 15:40:02 +0100260
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100261 enum sbmac_speed sbm_speed; /* current speed */
262 enum sbmac_duplex sbm_duplex; /* current duplex */
263 enum sbmac_fc sbm_fc; /* cur. flow control setting */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100264 int sbm_pause; /* current pause setting */
265 int sbm_link; /* current link state */
Ralf Baechle74b02472005-10-19 15:40:02 +0100266
Joe Perches104bf3f2011-11-16 09:38:03 +0000267 unsigned char sbm_hwaddr[ETH_ALEN];
Ralf Baechle74b02472005-10-19 15:40:02 +0100268
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100269 struct sbmacdma sbm_txdma; /* only channel 0 for now */
270 struct sbmacdma sbm_rxdma;
271 int rx_hw_checksum;
272 int sbe_idx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273};
274
275
276/**********************************************************************
277 * Externs
278 ********************************************************************* */
279
280/**********************************************************************
281 * Prototypes
282 ********************************************************************* */
283
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100284static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan,
285 int txrx, int maxdescr);
286static void sbdma_channel_start(struct sbmacdma *d, int rxtx);
Stephen Hemminger789585e2008-05-18 04:45:09 +0100287static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
288 struct sk_buff *m);
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100289static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *m);
290static void sbdma_emptyring(struct sbmacdma *d);
Stephen Hemminger789585e2008-05-18 04:45:09 +0100291static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d);
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100292static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d,
293 int work_to_do, int poll);
294static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
295 int poll);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296static int sbmac_initctx(struct sbmac_softc *s);
297static void sbmac_channel_start(struct sbmac_softc *s);
298static void sbmac_channel_stop(struct sbmac_softc *s);
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100299static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *,
300 enum sbmac_state);
301static void sbmac_promiscuous_mode(struct sbmac_softc *sc, int onoff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302static uint64_t sbmac_addr2reg(unsigned char *ptr);
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100303static irqreturn_t sbmac_intr(int irq, void *dev_instance);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev);
305static void sbmac_setmulti(struct sbmac_softc *sc);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100306static int sbmac_init(struct platform_device *pldev, long long base);
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100307static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed);
308static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex,
309 enum sbmac_fc fc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310
311static int sbmac_open(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312static void sbmac_tx_timeout (struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313static void sbmac_set_rx_mode(struct net_device *dev);
314static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
315static int sbmac_close(struct net_device *dev);
Stephen Hemmingerbea33482007-10-03 16:41:36 -0700316static int sbmac_poll(struct napi_struct *napi, int budget);
Mark Mason693aa942007-04-26 00:23:22 -0700317
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100318static void sbmac_mii_poll(struct net_device *dev);
Ralf Baechle59b81822005-10-20 12:01:28 +0100319static int sbmac_mii_probe(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100321static void sbmac_mii_sync(void __iomem *sbm_mdio);
322static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100323 int bitcnt);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100324static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx);
325static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
326 u16 val);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327
328
329/**********************************************************************
330 * Globals
331 ********************************************************************* */
332
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100333static char sbmac_string[] = "sb1250-mac";
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100334
335static char sbmac_mdio_string[] = "sb1250-mac-mdio";
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337
338/**********************************************************************
339 * MDIO constants
340 ********************************************************************* */
341
342#define MII_COMMAND_START 0x01
343#define MII_COMMAND_READ 0x02
344#define MII_COMMAND_WRITE 0x01
345#define MII_COMMAND_ACK 0x02
346
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347#define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */
348
349#define ENABLE 1
350#define DISABLE 0
351
352/**********************************************************************
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100353 * SBMAC_MII_SYNC(sbm_mdio)
Ralf Baechle74b02472005-10-19 15:40:02 +0100354 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 * Synchronize with the MII - send a pattern of bits to the MII
356 * that will guarantee that it is ready to accept a command.
Ralf Baechle74b02472005-10-19 15:40:02 +0100357 *
358 * Input parameters:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100359 * sbm_mdio - address of the MAC's MDIO register
Ralf Baechle74b02472005-10-19 15:40:02 +0100360 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361 * Return value:
362 * nothing
363 ********************************************************************* */
364
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100365static void sbmac_mii_sync(void __iomem *sbm_mdio)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366{
367 int cnt;
368 uint64_t bits;
369 int mac_mdio_genc;
370
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100371 mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
Ralf Baechle74b02472005-10-19 15:40:02 +0100372
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
Ralf Baechle74b02472005-10-19 15:40:02 +0100374
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100375 __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100376
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 for (cnt = 0; cnt < 32; cnt++) {
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100378 __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
379 __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380 }
381}
382
383/**********************************************************************
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100384 * SBMAC_MII_SENDDATA(sbm_mdio, data, bitcnt)
Ralf Baechle74b02472005-10-19 15:40:02 +0100385 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386 * Send some bits to the MII. The bits to be sent are right-
387 * justified in the 'data' parameter.
Ralf Baechle74b02472005-10-19 15:40:02 +0100388 *
389 * Input parameters:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100390 * sbm_mdio - address of the MAC's MDIO register
391 * data - data to send
392 * bitcnt - number of bits to send
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 ********************************************************************* */
394
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100395static void sbmac_mii_senddata(void __iomem *sbm_mdio, unsigned int data,
396 int bitcnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
398 int i;
399 uint64_t bits;
400 unsigned int curmask;
401 int mac_mdio_genc;
402
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100403 mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
Ralf Baechle74b02472005-10-19 15:40:02 +0100404
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405 bits = M_MAC_MDIO_DIR_OUTPUT;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100406 __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 curmask = 1 << (bitcnt - 1);
Ralf Baechle74b02472005-10-19 15:40:02 +0100409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 for (i = 0; i < bitcnt; i++) {
411 if (data & curmask)
412 bits |= M_MAC_MDIO_OUT;
413 else bits &= ~M_MAC_MDIO_OUT;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100414 __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
415 __raw_writeq(bits | M_MAC_MDC | mac_mdio_genc, sbm_mdio);
416 __raw_writeq(bits | mac_mdio_genc, sbm_mdio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 curmask >>= 1;
418 }
419}
420
421
422
423/**********************************************************************
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100424 * SBMAC_MII_READ(bus, phyaddr, regidx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425 * Read a PHY register.
Ralf Baechle74b02472005-10-19 15:40:02 +0100426 *
427 * Input parameters:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100428 * bus - MDIO bus handle
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 * phyaddr - PHY's address
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100430 * regnum - index of register to read
Ralf Baechle74b02472005-10-19 15:40:02 +0100431 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 * Return value:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100433 * value read, or 0xffff if an error occurred.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434 ********************************************************************* */
435
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100436static int sbmac_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100438 struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
439 void __iomem *sbm_mdio = sc->sbm_mdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 int idx;
441 int error;
442 int regval;
443 int mac_mdio_genc;
444
445 /*
446 * Synchronize ourselves so that the PHY knows the next
447 * thing coming down is a command
448 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100449 sbmac_mii_sync(sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100450
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 /*
452 * Send the data to the PHY. The sequence is
453 * a "start" command (2 bits)
454 * a "read" command (2 bits)
455 * the PHY addr (5 bits)
456 * the register index (5 bits)
457 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100458 sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
459 sbmac_mii_senddata(sbm_mdio, MII_COMMAND_READ, 2);
460 sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
461 sbmac_mii_senddata(sbm_mdio, regidx, 5);
Ralf Baechle74b02472005-10-19 15:40:02 +0100462
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100463 mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
Ralf Baechle74b02472005-10-19 15:40:02 +0100464
465 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 * Switch the port around without a clock transition.
467 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100468 __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100469
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 /*
471 * Send out a clock pulse to signal we want the status
472 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100473 __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
474 sbm_mdio);
475 __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100476
477 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 * If an error occurred, the PHY will signal '1' back
479 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100480 error = __raw_readq(sbm_mdio) & M_MAC_MDIO_IN;
Ralf Baechle74b02472005-10-19 15:40:02 +0100481
482 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 * Issue an 'idle' clock pulse, but keep the direction
484 * the same.
485 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100486 __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
487 sbm_mdio);
488 __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100489
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 regval = 0;
Ralf Baechle74b02472005-10-19 15:40:02 +0100491
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 for (idx = 0; idx < 16; idx++) {
493 regval <<= 1;
Ralf Baechle74b02472005-10-19 15:40:02 +0100494
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 if (error == 0) {
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100496 if (__raw_readq(sbm_mdio) & M_MAC_MDIO_IN)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 regval |= 1;
498 }
Ralf Baechle74b02472005-10-19 15:40:02 +0100499
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100500 __raw_writeq(M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc,
501 sbm_mdio);
502 __raw_writeq(M_MAC_MDIO_DIR_INPUT | mac_mdio_genc, sbm_mdio);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 }
Ralf Baechle74b02472005-10-19 15:40:02 +0100504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 /* Switch back to output */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100506 __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100507
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 if (error == 0)
509 return regval;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100510 return 0xffff;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511}
512
513
514/**********************************************************************
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100515 * SBMAC_MII_WRITE(bus, phyaddr, regidx, regval)
Ralf Baechle74b02472005-10-19 15:40:02 +0100516 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 * Write a value to a PHY register.
Ralf Baechle74b02472005-10-19 15:40:02 +0100518 *
519 * Input parameters:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100520 * bus - MDIO bus handle
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 * phyaddr - PHY to use
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100522 * regidx - register within the PHY
523 * regval - data to write to register
Ralf Baechle74b02472005-10-19 15:40:02 +0100524 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 * Return value:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100526 * 0 for success
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 ********************************************************************* */
528
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100529static int sbmac_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
530 u16 regval)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100532 struct sbmac_softc *sc = (struct sbmac_softc *)bus->priv;
533 void __iomem *sbm_mdio = sc->sbm_mdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 int mac_mdio_genc;
535
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100536 sbmac_mii_sync(sbm_mdio);
Ralf Baechle74b02472005-10-19 15:40:02 +0100537
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100538 sbmac_mii_senddata(sbm_mdio, MII_COMMAND_START, 2);
539 sbmac_mii_senddata(sbm_mdio, MII_COMMAND_WRITE, 2);
540 sbmac_mii_senddata(sbm_mdio, phyaddr, 5);
541 sbmac_mii_senddata(sbm_mdio, regidx, 5);
542 sbmac_mii_senddata(sbm_mdio, MII_COMMAND_ACK, 2);
543 sbmac_mii_senddata(sbm_mdio, regval, 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100545 mac_mdio_genc = __raw_readq(sbm_mdio) & M_MAC_GENC;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100547 __raw_writeq(M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc, sbm_mdio);
548
549 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550}
551
552
553
554/**********************************************************************
555 * SBDMA_INITCTX(d,s,chan,txrx,maxdescr)
Ralf Baechle74b02472005-10-19 15:40:02 +0100556 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 * Initialize a DMA channel context. Since there are potentially
558 * eight DMA channels per MAC, it's nice to do this in a standard
Ralf Baechle74b02472005-10-19 15:40:02 +0100559 * way.
560 *
561 * Input parameters:
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100562 * d - struct sbmacdma (DMA channel context)
563 * s - struct sbmac_softc (pointer to a MAC)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 * chan - channel number (0..1 right now)
565 * txrx - Identifies DMA_TX or DMA_RX for channel direction
566 * maxdescr - number of descriptors
Ralf Baechle74b02472005-10-19 15:40:02 +0100567 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 * Return value:
569 * nothing
570 ********************************************************************* */
571
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100572static void sbdma_initctx(struct sbmacdma *d, struct sbmac_softc *s, int chan,
573 int txrx, int maxdescr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
Mark Mason693aa942007-04-26 00:23:22 -0700575#ifdef CONFIG_SBMAC_COALESCE
576 int int_pktcnt, int_timeout;
577#endif
578
Ralf Baechle74b02472005-10-19 15:40:02 +0100579 /*
580 * Save away interesting stuff in the structure
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100582
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 d->sbdma_eth = s;
584 d->sbdma_channel = chan;
585 d->sbdma_txdir = txrx;
Ralf Baechle74b02472005-10-19 15:40:02 +0100586
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587#if 0
588 /* RMON clearing */
589 s->sbe_idx =(s->sbm_base - A_MAC_BASE_0)/MAC_SPACING;
590#endif
591
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +0100592 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BYTES);
593 __raw_writeq(0, s->sbm_base + R_MAC_RMON_COLLISIONS);
594 __raw_writeq(0, s->sbm_base + R_MAC_RMON_LATE_COL);
595 __raw_writeq(0, s->sbm_base + R_MAC_RMON_EX_COL);
596 __raw_writeq(0, s->sbm_base + R_MAC_RMON_FCS_ERROR);
597 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_ABORT);
598 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_BAD);
599 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_GOOD);
600 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_RUNT);
601 __raw_writeq(0, s->sbm_base + R_MAC_RMON_TX_OVERSIZE);
602 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BYTES);
603 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_MCAST);
604 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BCAST);
605 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_BAD);
606 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_GOOD);
607 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_RUNT);
608 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_OVERSIZE);
609 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_FCS_ERROR);
610 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_LENGTH_ERROR);
611 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_CODE_ERROR);
612 __raw_writeq(0, s->sbm_base + R_MAC_RMON_RX_ALIGN_ERROR);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Ralf Baechle74b02472005-10-19 15:40:02 +0100614 /*
615 * initialize register pointers
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100617
618 d->sbdma_config0 =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0);
Ralf Baechle74b02472005-10-19 15:40:02 +0100620 d->sbdma_config1 =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1);
Ralf Baechle74b02472005-10-19 15:40:02 +0100622 d->sbdma_dscrbase =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE);
Ralf Baechle74b02472005-10-19 15:40:02 +0100624 d->sbdma_dscrcnt =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT);
Ralf Baechle74b02472005-10-19 15:40:02 +0100626 d->sbdma_curdscr =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR);
Mark Mason693aa942007-04-26 00:23:22 -0700628 if (d->sbdma_txdir)
629 d->sbdma_oodpktlost = NULL;
630 else
631 d->sbdma_oodpktlost =
632 s->sbm_base + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_OODPKTLOST_RX);
Ralf Baechle74b02472005-10-19 15:40:02 +0100633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 /*
635 * Allocate memory for the ring
636 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100637
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 d->sbdma_maxdescr = maxdescr;
Ralf Baechle74b02472005-10-19 15:40:02 +0100639
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100640 d->sbdma_dscrtable_unaligned = kcalloc(d->sbdma_maxdescr + 1,
641 sizeof(*d->sbdma_dscrtable),
642 GFP_KERNEL);
Ralf Baechle04115de2005-10-10 14:50:36 +0100643
644 /*
645 * The descriptor table must be aligned to at least 16 bytes or the
646 * MAC will corrupt it.
647 */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100648 d->sbdma_dscrtable = (struct sbdmadscr *)
649 ALIGN((unsigned long)d->sbdma_dscrtable_unaligned,
650 sizeof(*d->sbdma_dscrtable));
Ralf Baechle74b02472005-10-19 15:40:02 +0100651
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 d->sbdma_dscrtable_end = d->sbdma_dscrtable + d->sbdma_maxdescr;
Ralf Baechle74b02472005-10-19 15:40:02 +0100653
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 d->sbdma_dscrtable_phys = virt_to_phys(d->sbdma_dscrtable);
Ralf Baechle74b02472005-10-19 15:40:02 +0100655
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 /*
657 * And context table
658 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100659
Mariusz Kozlowskic477f332007-07-31 23:58:36 +0200660 d->sbdma_ctxtable = kcalloc(d->sbdma_maxdescr,
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100661 sizeof(*d->sbdma_ctxtable), GFP_KERNEL);
Ralf Baechle74b02472005-10-19 15:40:02 +0100662
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663#ifdef CONFIG_SBMAC_COALESCE
664 /*
665 * Setup Rx/Tx DMA coalescing defaults
666 */
667
Mark Mason693aa942007-04-26 00:23:22 -0700668 int_pktcnt = (txrx == DMA_TX) ? int_pktcnt_tx : int_pktcnt_rx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669 if ( int_pktcnt ) {
670 d->sbdma_int_pktcnt = int_pktcnt;
671 } else {
672 d->sbdma_int_pktcnt = 1;
673 }
Ralf Baechle74b02472005-10-19 15:40:02 +0100674
Mark Mason693aa942007-04-26 00:23:22 -0700675 int_timeout = (txrx == DMA_TX) ? int_timeout_tx : int_timeout_rx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 if ( int_timeout ) {
677 d->sbdma_int_timeout = int_timeout;
678 } else {
679 d->sbdma_int_timeout = 0;
680 }
681#endif
682
683}
684
685/**********************************************************************
686 * SBDMA_CHANNEL_START(d)
Ralf Baechle74b02472005-10-19 15:40:02 +0100687 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 * Initialize the hardware registers for a DMA channel.
Ralf Baechle74b02472005-10-19 15:40:02 +0100689 *
690 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 * d - DMA channel to init (context must be previously init'd
692 * rxtx - DMA_RX or DMA_TX depending on what type of channel
Ralf Baechle74b02472005-10-19 15:40:02 +0100693 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 * Return value:
695 * nothing
696 ********************************************************************* */
697
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100698static void sbdma_channel_start(struct sbmacdma *d, int rxtx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699{
700 /*
701 * Turn on the DMA channel
702 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704#ifdef CONFIG_SBMAC_COALESCE
Ralf Baechle20399732005-10-19 15:39:05 +0100705 __raw_writeq(V_DMA_INT_TIMEOUT(d->sbdma_int_timeout) |
706 0, d->sbdma_config1);
707 __raw_writeq(M_DMA_EOP_INT_EN |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 V_DMA_RINGSZ(d->sbdma_maxdescr) |
709 V_DMA_INT_PKTCNT(d->sbdma_int_pktcnt) |
Ralf Baechle20399732005-10-19 15:39:05 +0100710 0, d->sbdma_config0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711#else
Ralf Baechle20399732005-10-19 15:39:05 +0100712 __raw_writeq(0, d->sbdma_config1);
713 __raw_writeq(V_DMA_RINGSZ(d->sbdma_maxdescr) |
714 0, d->sbdma_config0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715#endif
716
Ralf Baechle20399732005-10-19 15:39:05 +0100717 __raw_writeq(d->sbdma_dscrtable_phys, d->sbdma_dscrbase);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
719 /*
720 * Initialize ring pointers
721 */
722
723 d->sbdma_addptr = d->sbdma_dscrtable;
724 d->sbdma_remptr = d->sbdma_dscrtable;
725}
726
727/**********************************************************************
728 * SBDMA_CHANNEL_STOP(d)
Ralf Baechle74b02472005-10-19 15:40:02 +0100729 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 * Initialize the hardware registers for a DMA channel.
Ralf Baechle74b02472005-10-19 15:40:02 +0100731 *
732 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 * d - DMA channel to init (context must be previously init'd
Ralf Baechle74b02472005-10-19 15:40:02 +0100734 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 * Return value:
736 * nothing
737 ********************************************************************* */
738
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100739static void sbdma_channel_stop(struct sbmacdma *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740{
741 /*
742 * Turn off the DMA channel
743 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100744
Ralf Baechle20399732005-10-19 15:39:05 +0100745 __raw_writeq(0, d->sbdma_config1);
Ralf Baechle74b02472005-10-19 15:40:02 +0100746
Ralf Baechle20399732005-10-19 15:39:05 +0100747 __raw_writeq(0, d->sbdma_dscrbase);
Ralf Baechle74b02472005-10-19 15:40:02 +0100748
Ralf Baechle20399732005-10-19 15:39:05 +0100749 __raw_writeq(0, d->sbdma_config0);
Ralf Baechle74b02472005-10-19 15:40:02 +0100750
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 /*
752 * Zero ring pointers
753 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100754
Ralf Baechle20399732005-10-19 15:39:05 +0100755 d->sbdma_addptr = NULL;
756 d->sbdma_remptr = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
758
Stephen Hemminger789585e2008-05-18 04:45:09 +0100759static inline void sbdma_align_skb(struct sk_buff *skb,
760 unsigned int power2, unsigned int offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761{
Stephen Hemminger789585e2008-05-18 04:45:09 +0100762 unsigned char *addr = skb->data;
763 unsigned char *newaddr = PTR_ALIGN(addr, power2);
Ralf Baechle74b02472005-10-19 15:40:02 +0100764
Stephen Hemminger789585e2008-05-18 04:45:09 +0100765 skb_reserve(skb, newaddr - addr + offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766}
767
768
769/**********************************************************************
770 * SBDMA_ADD_RCVBUFFER(d,sb)
Ralf Baechle74b02472005-10-19 15:40:02 +0100771 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 * Add a buffer to the specified DMA channel. For receive channels,
773 * this queues a buffer for inbound packets.
Ralf Baechle74b02472005-10-19 15:40:02 +0100774 *
775 * Input parameters:
Stephen Hemminger789585e2008-05-18 04:45:09 +0100776 * sc - softc structure
777 * d - DMA channel descriptor
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 * sb - sk_buff to add, or NULL if we should allocate one
Ralf Baechle74b02472005-10-19 15:40:02 +0100779 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 * Return value:
781 * 0 if buffer could not be added (ring is full)
782 * 1 if buffer added successfully
783 ********************************************************************* */
784
785
Stephen Hemminger789585e2008-05-18 04:45:09 +0100786static int sbdma_add_rcvbuffer(struct sbmac_softc *sc, struct sbmacdma *d,
787 struct sk_buff *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788{
Stephen Hemminger789585e2008-05-18 04:45:09 +0100789 struct net_device *dev = sc->sbm_dev;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100790 struct sbdmadscr *dsc;
791 struct sbdmadscr *nextdsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 struct sk_buff *sb_new = NULL;
793 int pktsize = ENET_PACKET_SIZE;
Ralf Baechle74b02472005-10-19 15:40:02 +0100794
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 /* get pointer to our current place in the ring */
Ralf Baechle74b02472005-10-19 15:40:02 +0100796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 dsc = d->sbdma_addptr;
798 nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
Ralf Baechle74b02472005-10-19 15:40:02 +0100799
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 /*
801 * figure out if the ring is full - if the next descriptor
802 * is the same as the one that we're going to remove from
803 * the ring, the ring is full
804 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100805
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 if (nextdsc == d->sbdma_remptr) {
807 return -ENOSPC;
808 }
809
Ralf Baechle74b02472005-10-19 15:40:02 +0100810 /*
811 * Allocate a sk_buff if we don't already have one.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 * If we do have an sk_buff, reset it so that it's empty.
813 *
814 * Note: sk_buffs don't seem to be guaranteed to have any sort
815 * of alignment when they are allocated. Therefore, allocate enough
816 * extra space to make sure that:
817 *
818 * 1. the data does not start in the middle of a cache line.
819 * 2. The data does not end in the middle of a cache line
Ralf Baechle74b02472005-10-19 15:40:02 +0100820 * 3. The buffer can be aligned such that the IP addresses are
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821 * naturally aligned.
822 *
823 * Remember, the SOCs MAC writes whole cache lines at a time,
824 * without reading the old contents first. So, if the sk_buff's
825 * data portion starts in the middle of a cache line, the SOC
826 * DMA will trash the beginning (and ending) portions.
827 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100828
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 if (sb == NULL) {
Stephen Hemminger789585e2008-05-18 04:45:09 +0100830 sb_new = netdev_alloc_skb(dev, ENET_PACKET_SIZE +
831 SMP_CACHE_BYTES * 2 +
832 NET_IP_ALIGN);
Joe Perches720a43e2013-03-08 15:03:25 +0000833 if (sb_new == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Stephen Hemminger789585e2008-05-18 04:45:09 +0100836 sbdma_align_skb(sb_new, SMP_CACHE_BYTES, NET_IP_ALIGN);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 }
838 else {
839 sb_new = sb;
Ralf Baechle74b02472005-10-19 15:40:02 +0100840 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 * nothing special to reinit buffer, it's already aligned
842 * and sb->data already points to a good place.
843 */
844 }
Ralf Baechle74b02472005-10-19 15:40:02 +0100845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 /*
Ralf Baechle74b02472005-10-19 15:40:02 +0100847 * fill in the descriptor
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100849
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850#ifdef CONFIG_SBMAC_COALESCE
851 /*
852 * Do not interrupt per DMA transfer.
853 */
David S. Miller689be432005-06-28 15:25:31 -0700854 dsc->dscr_a = virt_to_phys(sb_new->data) |
Stephen Hemminger789585e2008-05-18 04:45:09 +0100855 V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) | 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856#else
David S. Miller689be432005-06-28 15:25:31 -0700857 dsc->dscr_a = virt_to_phys(sb_new->data) |
Stephen Hemminger789585e2008-05-18 04:45:09 +0100858 V_DMA_DSCRA_A_SIZE(NUMCACHEBLKS(pktsize + NET_IP_ALIGN)) |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859 M_DMA_DSCRA_INTERRUPT;
860#endif
861
862 /* receiving: no options */
863 dsc->dscr_b = 0;
Ralf Baechle74b02472005-10-19 15:40:02 +0100864
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865 /*
Ralf Baechle74b02472005-10-19 15:40:02 +0100866 * fill in the context
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869 d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb_new;
Ralf Baechle74b02472005-10-19 15:40:02 +0100870
871 /*
872 * point at next packet
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 d->sbdma_addptr = nextdsc;
Ralf Baechle74b02472005-10-19 15:40:02 +0100876
877 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 * Give the buffer to the DMA engine.
879 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100880
Ralf Baechle20399732005-10-19 15:39:05 +0100881 __raw_writeq(1, d->sbdma_dscrcnt);
Ralf Baechle74b02472005-10-19 15:40:02 +0100882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 return 0; /* we did it */
884}
885
886/**********************************************************************
887 * SBDMA_ADD_TXBUFFER(d,sb)
Ralf Baechle74b02472005-10-19 15:40:02 +0100888 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 * Add a transmit buffer to the specified DMA channel, causing a
890 * transmit to start.
Ralf Baechle74b02472005-10-19 15:40:02 +0100891 *
892 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 * d - DMA channel descriptor
894 * sb - sk_buff to add
Ralf Baechle74b02472005-10-19 15:40:02 +0100895 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 * Return value:
897 * 0 transmit queued successfully
898 * otherwise error code
899 ********************************************************************* */
900
901
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100902static int sbdma_add_txbuffer(struct sbmacdma *d, struct sk_buff *sb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903{
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100904 struct sbdmadscr *dsc;
905 struct sbdmadscr *nextdsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 uint64_t phys;
907 uint64_t ncb;
908 int length;
Ralf Baechle74b02472005-10-19 15:40:02 +0100909
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 /* get pointer to our current place in the ring */
Ralf Baechle74b02472005-10-19 15:40:02 +0100911
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 dsc = d->sbdma_addptr;
913 nextdsc = SBDMA_NEXTBUF(d,sbdma_addptr);
Ralf Baechle74b02472005-10-19 15:40:02 +0100914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 /*
916 * figure out if the ring is full - if the next descriptor
917 * is the same as the one that we're going to remove from
918 * the ring, the ring is full
919 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100920
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 if (nextdsc == d->sbdma_remptr) {
922 return -ENOSPC;
923 }
Ralf Baechle74b02472005-10-19 15:40:02 +0100924
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 /*
926 * Under Linux, it's not necessary to copy/coalesce buffers
927 * like it is on NetBSD. We think they're all contiguous,
928 * but that may not be true for GBE.
929 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 length = sb->len;
Ralf Baechle74b02472005-10-19 15:40:02 +0100932
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 /*
934 * fill in the descriptor. Note that the number of cache
935 * blocks in the descriptor is the number of blocks
936 * *spanned*, so we need to add in the offset (if any)
937 * while doing the calculation.
938 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100939
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 phys = virt_to_phys(sb->data);
941 ncb = NUMCACHEBLKS(length+(phys & (SMP_CACHE_BYTES - 1)));
942
Ralf Baechle74b02472005-10-19 15:40:02 +0100943 dsc->dscr_a = phys |
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 V_DMA_DSCRA_A_SIZE(ncb) |
945#ifndef CONFIG_SBMAC_COALESCE
946 M_DMA_DSCRA_INTERRUPT |
947#endif
948 M_DMA_ETHTX_SOP;
Ralf Baechle74b02472005-10-19 15:40:02 +0100949
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 /* transmitting: set outbound options and length */
951
952 dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
953 V_DMA_DSCRB_PKT_SIZE(length);
Ralf Baechle74b02472005-10-19 15:40:02 +0100954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 /*
Ralf Baechle74b02472005-10-19 15:40:02 +0100956 * fill in the context
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100958
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = sb;
Ralf Baechle74b02472005-10-19 15:40:02 +0100960
961 /*
962 * point at next packet
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 d->sbdma_addptr = nextdsc;
Ralf Baechle74b02472005-10-19 15:40:02 +0100966
967 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 * Give the buffer to the DMA engine.
969 */
Ralf Baechle74b02472005-10-19 15:40:02 +0100970
Ralf Baechle20399732005-10-19 15:39:05 +0100971 __raw_writeq(1, d->sbdma_dscrcnt);
Ralf Baechle74b02472005-10-19 15:40:02 +0100972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 return 0; /* we did it */
974}
975
976
977
978
979/**********************************************************************
980 * SBDMA_EMPTYRING(d)
Ralf Baechle74b02472005-10-19 15:40:02 +0100981 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 * Free all allocated sk_buffs on the specified DMA channel;
Ralf Baechle74b02472005-10-19 15:40:02 +0100983 *
984 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 * d - DMA channel
Ralf Baechle74b02472005-10-19 15:40:02 +0100986 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 * Return value:
988 * nothing
989 ********************************************************************* */
990
Maciej W. Rozycki73d73962007-09-20 19:14:01 +0100991static void sbdma_emptyring(struct sbmacdma *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992{
993 int idx;
994 struct sk_buff *sb;
Ralf Baechle74b02472005-10-19 15:40:02 +0100995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 for (idx = 0; idx < d->sbdma_maxdescr; idx++) {
997 sb = d->sbdma_ctxtable[idx];
998 if (sb) {
999 dev_kfree_skb(sb);
1000 d->sbdma_ctxtable[idx] = NULL;
1001 }
1002 }
1003}
1004
1005
1006/**********************************************************************
1007 * SBDMA_FILLRING(d)
Ralf Baechle74b02472005-10-19 15:40:02 +01001008 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 * Fill the specified DMA channel (must be receive channel)
1010 * with sk_buffs
Ralf Baechle74b02472005-10-19 15:40:02 +01001011 *
1012 * Input parameters:
Stephen Hemminger789585e2008-05-18 04:45:09 +01001013 * sc - softc structure
1014 * d - DMA channel
Ralf Baechle74b02472005-10-19 15:40:02 +01001015 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 * Return value:
1017 * nothing
1018 ********************************************************************* */
1019
Stephen Hemminger789585e2008-05-18 04:45:09 +01001020static void sbdma_fillring(struct sbmac_softc *sc, struct sbmacdma *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021{
1022 int idx;
Ralf Baechle74b02472005-10-19 15:40:02 +01001023
Stephen Hemminger789585e2008-05-18 04:45:09 +01001024 for (idx = 0; idx < SBMAC_MAX_RXDESCR - 1; idx++) {
1025 if (sbdma_add_rcvbuffer(sc, d, NULL) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 break;
1027 }
1028}
1029
Deepak Saxenad6830012007-03-19 15:43:11 -07001030#ifdef CONFIG_NET_POLL_CONTROLLER
1031static void sbmac_netpoll(struct net_device *netdev)
1032{
1033 struct sbmac_softc *sc = netdev_priv(netdev);
1034 int irq = sc->sbm_dev->irq;
1035
1036 __raw_writeq(0, sc->sbm_imr);
1037
Yoann Padioleau0da2f0f2007-07-06 02:39:56 -07001038 sbmac_intr(irq, netdev);
Deepak Saxenad6830012007-03-19 15:43:11 -07001039
1040#ifdef CONFIG_SBMAC_COALESCE
1041 __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
1042 ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0),
1043 sc->sbm_imr);
1044#else
Jeff Garzik7d2e3cb2008-05-13 01:41:58 -04001045 __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
Deepak Saxenad6830012007-03-19 15:43:11 -07001046 (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr);
1047#endif
1048}
1049#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051/**********************************************************************
Mark Mason693aa942007-04-26 00:23:22 -07001052 * SBDMA_RX_PROCESS(sc,d,work_to_do,poll)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 *
Ralf Baechle74b02472005-10-19 15:40:02 +01001054 * Process "completed" receive buffers on the specified DMA channel.
Ralf Baechle74b02472005-10-19 15:40:02 +01001055 *
1056 * Input parameters:
Mark Mason693aa942007-04-26 00:23:22 -07001057 * sc - softc structure
1058 * d - DMA channel context
1059 * work_to_do - no. of packets to process before enabling interrupt
1060 * again (for NAPI)
1061 * poll - 1: using polling (for NAPI)
Ralf Baechle74b02472005-10-19 15:40:02 +01001062 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 * Return value:
1064 * nothing
1065 ********************************************************************* */
1066
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001067static int sbdma_rx_process(struct sbmac_softc *sc, struct sbmacdma *d,
1068 int work_to_do, int poll)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069{
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001070 struct net_device *dev = sc->sbm_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 int curidx;
1072 int hwidx;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001073 struct sbdmadscr *dsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 struct sk_buff *sb;
1075 int len;
Mark Mason693aa942007-04-26 00:23:22 -07001076 int work_done = 0;
1077 int dropped = 0;
Ralf Baechle74b02472005-10-19 15:40:02 +01001078
Mark Mason693aa942007-04-26 00:23:22 -07001079 prefetch(d);
1080
1081again:
1082 /* Check if the HW dropped any frames */
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001083 dev->stats.rx_fifo_errors
Mark Mason693aa942007-04-26 00:23:22 -07001084 += __raw_readq(sc->sbm_rxdma.sbdma_oodpktlost) & 0xffff;
1085 __raw_writeq(0, sc->sbm_rxdma.sbdma_oodpktlost);
1086
1087 while (work_to_do-- > 0) {
Ralf Baechle74b02472005-10-19 15:40:02 +01001088 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 * figure out where we are (as an index) and where
1090 * the hardware is (also as an index)
1091 *
Ralf Baechle74b02472005-10-19 15:40:02 +01001092 * This could be done faster if (for example) the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 * descriptor table was page-aligned and contiguous in
1094 * both virtual and physical memory -- you could then
1095 * just compare the low-order bits of the virtual address
1096 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
1097 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001098
Mark Mason693aa942007-04-26 00:23:22 -07001099 dsc = d->sbdma_remptr;
1100 curidx = dsc - d->sbdma_dscrtable;
1101
1102 prefetch(dsc);
1103 prefetch(&d->sbdma_ctxtable[curidx]);
1104
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001105 hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
1106 d->sbdma_dscrtable_phys) /
1107 sizeof(*d->sbdma_dscrtable);
Ralf Baechle74b02472005-10-19 15:40:02 +01001108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 /*
1110 * If they're the same, that means we've processed all
1111 * of the descriptors up to (but not including) the one that
1112 * the hardware is working on right now.
1113 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 if (curidx == hwidx)
Mark Mason693aa942007-04-26 00:23:22 -07001116 goto done;
Ralf Baechle74b02472005-10-19 15:40:02 +01001117
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 /*
1119 * Otherwise, get the packet's sk_buff ptr back
1120 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001121
Linus Torvalds1da177e2005-04-16 15:20:36 -07001122 sb = d->sbdma_ctxtable[curidx];
1123 d->sbdma_ctxtable[curidx] = NULL;
Ralf Baechle74b02472005-10-19 15:40:02 +01001124
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 len = (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b) - 4;
Ralf Baechle74b02472005-10-19 15:40:02 +01001126
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 /*
1128 * Check packet status. If good, process it.
1129 * If not, silently drop it and put it back on the
1130 * receive ring.
1131 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001132
Mark Mason693aa942007-04-26 00:23:22 -07001133 if (likely (!(dsc->dscr_a & M_DMA_ETHRX_BAD))) {
Ralf Baechle74b02472005-10-19 15:40:02 +01001134
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /*
1136 * Add a new buffer to replace the old one. If we fail
1137 * to allocate a buffer, we're going to drop this
1138 * packet and put it right back on the receive ring.
1139 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001140
Stephen Hemminger789585e2008-05-18 04:45:09 +01001141 if (unlikely(sbdma_add_rcvbuffer(sc, d, NULL) ==
1142 -ENOBUFS)) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001143 dev->stats.rx_dropped++;
Stephen Hemminger789585e2008-05-18 04:45:09 +01001144 /* Re-add old buffer */
1145 sbdma_add_rcvbuffer(sc, d, sb);
Mark Mason693aa942007-04-26 00:23:22 -07001146 /* No point in continuing at the moment */
1147 printk(KERN_ERR "dropped packet (1)\n");
1148 d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
1149 goto done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 } else {
1151 /*
1152 * Set length into the packet
1153 */
1154 skb_put(sb,len);
Ralf Baechle74b02472005-10-19 15:40:02 +01001155
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 /*
1157 * Buffer has been replaced on the
1158 * receive ring. Pass the buffer to
1159 * the kernel
1160 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 sb->protocol = eth_type_trans(sb,d->sbdma_eth->sbm_dev);
1162 /* Check hw IPv4/TCP checksum if supported */
1163 if (sc->rx_hw_checksum == ENABLE) {
1164 if (!((dsc->dscr_a) & M_DMA_ETHRX_BADIP4CS) &&
1165 !((dsc->dscr_a) & M_DMA_ETHRX_BADTCPCS)) {
1166 sb->ip_summed = CHECKSUM_UNNECESSARY;
1167 /* don't need to set sb->csum */
1168 } else {
Eric Dumazetbc8acf22010-09-02 13:07:41 -07001169 skb_checksum_none_assert(sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 }
1171 }
Mark Mason693aa942007-04-26 00:23:22 -07001172 prefetch(sb->data);
1173 prefetch((const void *)(((char *)sb->data)+32));
1174 if (poll)
1175 dropped = netif_receive_skb(sb);
1176 else
1177 dropped = netif_rx(sb);
Ralf Baechle74b02472005-10-19 15:40:02 +01001178
Mark Mason693aa942007-04-26 00:23:22 -07001179 if (dropped == NET_RX_DROP) {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001180 dev->stats.rx_dropped++;
Mark Mason693aa942007-04-26 00:23:22 -07001181 d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
1182 goto done;
1183 }
1184 else {
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001185 dev->stats.rx_bytes += len;
1186 dev->stats.rx_packets++;
Mark Mason693aa942007-04-26 00:23:22 -07001187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189 } else {
1190 /*
1191 * Packet was mangled somehow. Just drop it and
1192 * put it back on the receive ring.
1193 */
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001194 dev->stats.rx_errors++;
Stephen Hemminger789585e2008-05-18 04:45:09 +01001195 sbdma_add_rcvbuffer(sc, d, sb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001197
1198
1199 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 * .. and advance to the next buffer.
1201 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
Mark Mason693aa942007-04-26 00:23:22 -07001204 work_done++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 }
Mark Mason693aa942007-04-26 00:23:22 -07001206 if (!poll) {
1207 work_to_do = 32;
1208 goto again; /* collect fifo drop statistics again */
1209 }
1210done:
1211 return work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212}
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214/**********************************************************************
1215 * SBDMA_TX_PROCESS(sc,d)
Ralf Baechle74b02472005-10-19 15:40:02 +01001216 *
1217 * Process "completed" transmit buffers on the specified DMA channel.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 * This is normally called within the interrupt service routine.
1219 * Note that this isn't really ideal for priority channels, since
Ralf Baechle74b02472005-10-19 15:40:02 +01001220 * it processes all of the packets on a given channel before
1221 * returning.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 *
Ralf Baechle74b02472005-10-19 15:40:02 +01001223 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 * sc - softc structure
Mark Mason693aa942007-04-26 00:23:22 -07001225 * d - DMA channel context
1226 * poll - 1: using polling (for NAPI)
Ralf Baechle74b02472005-10-19 15:40:02 +01001227 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 * Return value:
1229 * nothing
1230 ********************************************************************* */
1231
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001232static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
1233 int poll)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234{
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001235 struct net_device *dev = sc->sbm_dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 int curidx;
1237 int hwidx;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001238 struct sbdmadscr *dsc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 struct sk_buff *sb;
1240 unsigned long flags;
Mark Mason693aa942007-04-26 00:23:22 -07001241 int packets_handled = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
1243 spin_lock_irqsave(&(sc->sbm_lock), flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01001244
Mark Mason693aa942007-04-26 00:23:22 -07001245 if (d->sbdma_remptr == d->sbdma_addptr)
1246 goto end_unlock;
1247
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001248 hwidx = ((__raw_readq(d->sbdma_curdscr) & M_DMA_CURDSCR_ADDR) -
1249 d->sbdma_dscrtable_phys) / sizeof(*d->sbdma_dscrtable);
Mark Mason693aa942007-04-26 00:23:22 -07001250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 for (;;) {
Ralf Baechle74b02472005-10-19 15:40:02 +01001252 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253 * figure out where we are (as an index) and where
1254 * the hardware is (also as an index)
1255 *
Ralf Baechle74b02472005-10-19 15:40:02 +01001256 * This could be done faster if (for example) the
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 * descriptor table was page-aligned and contiguous in
1258 * both virtual and physical memory -- you could then
1259 * just compare the low-order bits of the virtual address
1260 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
1261 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 curidx = d->sbdma_remptr - d->sbdma_dscrtable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
1265 /*
1266 * If they're the same, that means we've processed all
1267 * of the descriptors up to (but not including) the one that
1268 * the hardware is working on right now.
1269 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 if (curidx == hwidx)
1272 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 /*
1275 * Otherwise, get the packet's sk_buff ptr back
1276 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001277
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 dsc = &(d->sbdma_dscrtable[curidx]);
1279 sb = d->sbdma_ctxtable[curidx];
1280 d->sbdma_ctxtable[curidx] = NULL;
Ralf Baechle74b02472005-10-19 15:40:02 +01001281
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 /*
1283 * Stats
1284 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001285
Jeff Garzik09f75cd2007-10-03 17:41:50 -07001286 dev->stats.tx_bytes += sb->len;
1287 dev->stats.tx_packets++;
Ralf Baechle74b02472005-10-19 15:40:02 +01001288
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 /*
1290 * for transmits, we just free buffers.
1291 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001292
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 dev_kfree_skb_irq(sb);
Ralf Baechle74b02472005-10-19 15:40:02 +01001294
1295 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 * .. and advance to the next buffer.
1297 */
1298
1299 d->sbdma_remptr = SBDMA_NEXTBUF(d,sbdma_remptr);
Ralf Baechle74b02472005-10-19 15:40:02 +01001300
Mark Mason693aa942007-04-26 00:23:22 -07001301 packets_handled++;
1302
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001304
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 /*
1306 * Decide if we should wake up the protocol or not.
1307 * Other drivers seem to do this when we reach a low
1308 * watermark on the transmit queue.
1309 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001310
Mark Mason693aa942007-04-26 00:23:22 -07001311 if (packets_handled)
1312 netif_wake_queue(d->sbdma_eth->sbm_dev);
Ralf Baechle74b02472005-10-19 15:40:02 +01001313
Mark Mason693aa942007-04-26 00:23:22 -07001314end_unlock:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 spin_unlock_irqrestore(&(sc->sbm_lock), flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01001316
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317}
1318
1319
1320
1321/**********************************************************************
1322 * SBMAC_INITCTX(s)
Ralf Baechle74b02472005-10-19 15:40:02 +01001323 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 * Initialize an Ethernet context structure - this is called
1325 * once per MAC on the 1250. Memory is allocated here, so don't
1326 * call it again from inside the ioctl routines that bring the
1327 * interface up/down
Ralf Baechle74b02472005-10-19 15:40:02 +01001328 *
1329 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 * s - sbmac context structure
Ralf Baechle74b02472005-10-19 15:40:02 +01001331 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 * Return value:
1333 * 0
1334 ********************************************************************* */
1335
1336static int sbmac_initctx(struct sbmac_softc *s)
1337{
Ralf Baechle74b02472005-10-19 15:40:02 +01001338
1339 /*
1340 * figure out the addresses of some ports
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001342
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 s->sbm_macenable = s->sbm_base + R_MAC_ENABLE;
1344 s->sbm_maccfg = s->sbm_base + R_MAC_CFG;
1345 s->sbm_fifocfg = s->sbm_base + R_MAC_THRSH_CFG;
1346 s->sbm_framecfg = s->sbm_base + R_MAC_FRAMECFG;
1347 s->sbm_rxfilter = s->sbm_base + R_MAC_ADFILTER_CFG;
1348 s->sbm_isr = s->sbm_base + R_MAC_STATUS;
1349 s->sbm_imr = s->sbm_base + R_MAC_INT_MASK;
1350 s->sbm_mdio = s->sbm_base + R_MAC_MDIO;
1351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 /*
1353 * Initialize the DMA channels. Right now, only one per MAC is used
1354 * Note: Only do this _once_, as it allocates memory from the kernel!
1355 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001356
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357 sbdma_initctx(&(s->sbm_txdma),s,0,DMA_TX,SBMAC_MAX_TXDESCR);
1358 sbdma_initctx(&(s->sbm_rxdma),s,0,DMA_RX,SBMAC_MAX_RXDESCR);
Ralf Baechle74b02472005-10-19 15:40:02 +01001359
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 /*
1361 * initial state is OFF
1362 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 s->sbm_state = sbmac_state_off;
Ralf Baechle74b02472005-10-19 15:40:02 +01001365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 return 0;
1367}
1368
1369
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001370static void sbdma_uninitctx(struct sbmacdma *d)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371{
Mark Mason693aa942007-04-26 00:23:22 -07001372 if (d->sbdma_dscrtable_unaligned) {
1373 kfree(d->sbdma_dscrtable_unaligned);
1374 d->sbdma_dscrtable_unaligned = d->sbdma_dscrtable = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001376
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 if (d->sbdma_ctxtable) {
1378 kfree(d->sbdma_ctxtable);
1379 d->sbdma_ctxtable = NULL;
1380 }
1381}
1382
1383
1384static void sbmac_uninitctx(struct sbmac_softc *sc)
1385{
1386 sbdma_uninitctx(&(sc->sbm_txdma));
1387 sbdma_uninitctx(&(sc->sbm_rxdma));
1388}
1389
1390
1391/**********************************************************************
1392 * SBMAC_CHANNEL_START(s)
Ralf Baechle74b02472005-10-19 15:40:02 +01001393 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 * Start packet processing on this MAC.
Ralf Baechle74b02472005-10-19 15:40:02 +01001395 *
1396 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 * s - sbmac structure
Ralf Baechle74b02472005-10-19 15:40:02 +01001398 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 * Return value:
1400 * nothing
1401 ********************************************************************* */
1402
1403static void sbmac_channel_start(struct sbmac_softc *s)
1404{
1405 uint64_t reg;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001406 void __iomem *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 uint64_t cfg,fifo,framecfg;
1408 int idx, th_value;
Ralf Baechle74b02472005-10-19 15:40:02 +01001409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 /*
1411 * Don't do this if running
1412 */
1413
1414 if (s->sbm_state == sbmac_state_on)
1415 return;
Ralf Baechle74b02472005-10-19 15:40:02 +01001416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 /*
1418 * Bring the controller out of reset, but leave it off.
1419 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001420
Ralf Baechle20399732005-10-19 15:39:05 +01001421 __raw_writeq(0, s->sbm_macenable);
Ralf Baechle74b02472005-10-19 15:40:02 +01001422
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 /*
1424 * Ignore all received packets
1425 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001426
Ralf Baechle20399732005-10-19 15:39:05 +01001427 __raw_writeq(0, s->sbm_rxfilter);
Ralf Baechle74b02472005-10-19 15:40:02 +01001428
1429 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 * Calculate values for various control registers.
1431 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001432
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 cfg = M_MAC_RETRY_EN |
Ralf Baechle74b02472005-10-19 15:40:02 +01001434 M_MAC_TX_HOLD_SOP_EN |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 V_MAC_TX_PAUSE_CNT_16K |
1436 M_MAC_AP_STAT_EN |
1437 M_MAC_FAST_SYNC |
1438 M_MAC_SS_EN |
1439 0;
Ralf Baechle74b02472005-10-19 15:40:02 +01001440
1441 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 * Be sure that RD_THRSH+WR_THRSH <= 32 for pass1 pars
1443 * and make sure that RD_THRSH + WR_THRSH <=128 for pass2 and above
1444 * Use a larger RD_THRSH for gigabit
1445 */
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001446 if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 th_value = 28;
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001448 else
1449 th_value = 64;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451 fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
1452 ((s->sbm_speed == sbmac_speed_1000)
1453 ? V_MAC_TX_RD_THRSH(th_value) : V_MAC_TX_RD_THRSH(4)) |
1454 V_MAC_TX_RL_THRSH(4) |
1455 V_MAC_RX_PL_THRSH(4) |
1456 V_MAC_RX_RD_THRSH(4) | /* Must be '4' */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 V_MAC_RX_RL_THRSH(8) |
1458 0;
1459
1460 framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
1461 V_MAC_MAX_FRAMESZ_DEFAULT |
1462 V_MAC_BACKOFF_SEL(1);
1463
1464 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001465 * Clear out the hash address map
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001467
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 port = s->sbm_base + R_MAC_HASH_BASE;
1469 for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
Ralf Baechle20399732005-10-19 15:39:05 +01001470 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 port += sizeof(uint64_t);
1472 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001473
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 /*
1475 * Clear out the exact-match table
1476 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001477
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 port = s->sbm_base + R_MAC_ADDR_BASE;
1479 for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
Ralf Baechle20399732005-10-19 15:39:05 +01001480 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 port += sizeof(uint64_t);
1482 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 /*
1485 * Clear out the DMA Channel mapping table registers
1486 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001487
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 port = s->sbm_base + R_MAC_CHUP0_BASE;
1489 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
Ralf Baechle20399732005-10-19 15:39:05 +01001490 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 port += sizeof(uint64_t);
1492 }
1493
1494
1495 port = s->sbm_base + R_MAC_CHLO0_BASE;
1496 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
Ralf Baechle20399732005-10-19 15:39:05 +01001497 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 port += sizeof(uint64_t);
1499 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001500
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 /*
1502 * Program the hardware address. It goes into the hardware-address
1503 * register as well as the first filter register.
1504 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 reg = sbmac_addr2reg(s->sbm_hwaddr);
Ralf Baechle74b02472005-10-19 15:40:02 +01001507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 port = s->sbm_base + R_MAC_ADDR_BASE;
Ralf Baechle20399732005-10-19 15:39:05 +01001509 __raw_writeq(reg, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 port = s->sbm_base + R_MAC_ETHERNET_ADDR;
1511
1512#ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
1513 /*
1514 * Pass1 SOCs do not receive packets addressed to the
1515 * destination address in the R_MAC_ETHERNET_ADDR register.
1516 * Set the value to zero.
1517 */
Ralf Baechle20399732005-10-19 15:39:05 +01001518 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519#else
Ralf Baechle20399732005-10-19 15:39:05 +01001520 __raw_writeq(reg, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521#endif
Ralf Baechle74b02472005-10-19 15:40:02 +01001522
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 /*
1524 * Set the receive filter for no packets, and write values
1525 * to the various config registers
1526 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001527
Ralf Baechle20399732005-10-19 15:39:05 +01001528 __raw_writeq(0, s->sbm_rxfilter);
1529 __raw_writeq(0, s->sbm_imr);
1530 __raw_writeq(framecfg, s->sbm_framecfg);
1531 __raw_writeq(fifo, s->sbm_fifocfg);
1532 __raw_writeq(cfg, s->sbm_maccfg);
Ralf Baechle74b02472005-10-19 15:40:02 +01001533
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 /*
1535 * Initialize DMA channels (rings should be ok now)
1536 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 sbdma_channel_start(&(s->sbm_rxdma), DMA_RX);
1539 sbdma_channel_start(&(s->sbm_txdma), DMA_TX);
Ralf Baechle74b02472005-10-19 15:40:02 +01001540
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 /*
1542 * Configure the speed, duplex, and flow control
1543 */
1544
1545 sbmac_set_speed(s,s->sbm_speed);
1546 sbmac_set_duplex(s,s->sbm_duplex,s->sbm_fc);
Ralf Baechle74b02472005-10-19 15:40:02 +01001547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 /*
1549 * Fill the receive ring
1550 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001551
Stephen Hemminger789585e2008-05-18 04:45:09 +01001552 sbdma_fillring(s, &(s->sbm_rxdma));
Ralf Baechle74b02472005-10-19 15:40:02 +01001553
1554 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 * Turn on the rest of the bits in the enable register
Ralf Baechle74b02472005-10-19 15:40:02 +01001556 */
1557
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001558#if defined(CONFIG_SIBYTE_BCM1x55) || defined(CONFIG_SIBYTE_BCM1x80)
1559 __raw_writeq(M_MAC_RXDMA_EN0 |
1560 M_MAC_TXDMA_EN0, s->sbm_macenable);
1561#elif defined(CONFIG_SIBYTE_SB1250) || defined(CONFIG_SIBYTE_BCM112X)
Ralf Baechle20399732005-10-19 15:39:05 +01001562 __raw_writeq(M_MAC_RXDMA_EN0 |
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 M_MAC_TXDMA_EN0 |
1564 M_MAC_RX_ENABLE |
Ralf Baechle20399732005-10-19 15:39:05 +01001565 M_MAC_TX_ENABLE, s->sbm_macenable);
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001566#else
Thomas Weber0b1974d2010-09-23 11:46:48 +02001567#error invalid SiByte MAC configuration
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001568#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
1570#ifdef CONFIG_SBMAC_COALESCE
Ralf Baechle20399732005-10-19 15:39:05 +01001571 __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
1572 ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0), s->sbm_imr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573#else
Ralf Baechle20399732005-10-19 15:39:05 +01001574 __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
1575 (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), s->sbm_imr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576#endif
Ralf Baechle74b02472005-10-19 15:40:02 +01001577
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001579 * Enable receiving unicasts and broadcasts
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001581
1582 __raw_writeq(M_MAC_UCAST_EN | M_MAC_BCAST_EN, s->sbm_rxfilter);
1583
1584 /*
1585 * we're running now.
1586 */
1587
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 s->sbm_state = sbmac_state_on;
Ralf Baechle74b02472005-10-19 15:40:02 +01001589
1590 /*
1591 * Program multicast addresses
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001593
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 sbmac_setmulti(s);
Ralf Baechle74b02472005-10-19 15:40:02 +01001595
1596 /*
1597 * If channel was in promiscuous mode before, turn that on
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 if (s->sbm_devflags & IFF_PROMISC) {
1601 sbmac_promiscuous_mode(s,1);
1602 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604}
1605
1606
1607/**********************************************************************
1608 * SBMAC_CHANNEL_STOP(s)
Ralf Baechle74b02472005-10-19 15:40:02 +01001609 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 * Stop packet processing on this MAC.
Ralf Baechle74b02472005-10-19 15:40:02 +01001611 *
1612 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 * s - sbmac structure
Ralf Baechle74b02472005-10-19 15:40:02 +01001614 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 * Return value:
1616 * nothing
1617 ********************************************************************* */
1618
1619static void sbmac_channel_stop(struct sbmac_softc *s)
1620{
1621 /* don't do this if already stopped */
Ralf Baechle74b02472005-10-19 15:40:02 +01001622
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623 if (s->sbm_state == sbmac_state_off)
1624 return;
Ralf Baechle74b02472005-10-19 15:40:02 +01001625
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 /* don't accept any packets, disable all interrupts */
Ralf Baechle74b02472005-10-19 15:40:02 +01001627
Ralf Baechle20399732005-10-19 15:39:05 +01001628 __raw_writeq(0, s->sbm_rxfilter);
1629 __raw_writeq(0, s->sbm_imr);
Ralf Baechle74b02472005-10-19 15:40:02 +01001630
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 /* Turn off ticker */
Ralf Baechle74b02472005-10-19 15:40:02 +01001632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 /* XXX */
Ralf Baechle74b02472005-10-19 15:40:02 +01001634
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 /* turn off receiver and transmitter */
Ralf Baechle74b02472005-10-19 15:40:02 +01001636
Ralf Baechle20399732005-10-19 15:39:05 +01001637 __raw_writeq(0, s->sbm_macenable);
Ralf Baechle74b02472005-10-19 15:40:02 +01001638
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 /* We're stopped now. */
Ralf Baechle74b02472005-10-19 15:40:02 +01001640
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 s->sbm_state = sbmac_state_off;
Ralf Baechle74b02472005-10-19 15:40:02 +01001642
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 /*
1644 * Stop DMA channels (rings should be ok now)
1645 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001646
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 sbdma_channel_stop(&(s->sbm_rxdma));
1648 sbdma_channel_stop(&(s->sbm_txdma));
Ralf Baechle74b02472005-10-19 15:40:02 +01001649
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 /* Empty the receive and transmit rings */
Ralf Baechle74b02472005-10-19 15:40:02 +01001651
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 sbdma_emptyring(&(s->sbm_rxdma));
1653 sbdma_emptyring(&(s->sbm_txdma));
Ralf Baechle74b02472005-10-19 15:40:02 +01001654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655}
1656
1657/**********************************************************************
1658 * SBMAC_SET_CHANNEL_STATE(state)
Ralf Baechle74b02472005-10-19 15:40:02 +01001659 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 * Set the channel's state ON or OFF
Ralf Baechle74b02472005-10-19 15:40:02 +01001661 *
1662 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 * state - new state
Ralf Baechle74b02472005-10-19 15:40:02 +01001664 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 * Return value:
1666 * old state
1667 ********************************************************************* */
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001668static enum sbmac_state sbmac_set_channel_state(struct sbmac_softc *sc,
1669 enum sbmac_state state)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001671 enum sbmac_state oldstate = sc->sbm_state;
Ralf Baechle74b02472005-10-19 15:40:02 +01001672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 /*
1674 * If same as previous state, return
1675 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 if (state == oldstate) {
1678 return oldstate;
1679 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001680
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001682 * If new state is ON, turn channel on
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001684
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 if (state == sbmac_state_on) {
1686 sbmac_channel_start(sc);
1687 }
1688 else {
1689 sbmac_channel_stop(sc);
1690 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 /*
1693 * Return previous state
1694 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 return oldstate;
1697}
1698
1699
1700/**********************************************************************
1701 * SBMAC_PROMISCUOUS_MODE(sc,onoff)
Ralf Baechle74b02472005-10-19 15:40:02 +01001702 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 * Turn on or off promiscuous mode
Ralf Baechle74b02472005-10-19 15:40:02 +01001704 *
1705 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 * sc - softc
1707 * onoff - 1 to turn on, 0 to turn off
Ralf Baechle74b02472005-10-19 15:40:02 +01001708 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 * Return value:
1710 * nothing
1711 ********************************************************************* */
1712
1713static void sbmac_promiscuous_mode(struct sbmac_softc *sc,int onoff)
1714{
1715 uint64_t reg;
Ralf Baechle74b02472005-10-19 15:40:02 +01001716
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 if (sc->sbm_state != sbmac_state_on)
1718 return;
Ralf Baechle74b02472005-10-19 15:40:02 +01001719
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 if (onoff) {
Ralf Baechle20399732005-10-19 15:39:05 +01001721 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 reg |= M_MAC_ALLPKT_EN;
Ralf Baechle20399732005-10-19 15:39:05 +01001723 __raw_writeq(reg, sc->sbm_rxfilter);
Ralf Baechle74b02472005-10-19 15:40:02 +01001724 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 else {
Ralf Baechle20399732005-10-19 15:39:05 +01001726 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 reg &= ~M_MAC_ALLPKT_EN;
Ralf Baechle20399732005-10-19 15:39:05 +01001728 __raw_writeq(reg, sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 }
1730}
1731
1732/**********************************************************************
1733 * SBMAC_SETIPHDR_OFFSET(sc,onoff)
Ralf Baechle74b02472005-10-19 15:40:02 +01001734 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 * Set the iphdr offset as 15 assuming ethernet encapsulation
Ralf Baechle74b02472005-10-19 15:40:02 +01001736 *
1737 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 * sc - softc
Ralf Baechle74b02472005-10-19 15:40:02 +01001739 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 * Return value:
1741 * nothing
1742 ********************************************************************* */
1743
1744static void sbmac_set_iphdr_offset(struct sbmac_softc *sc)
1745{
1746 uint64_t reg;
Ralf Baechle74b02472005-10-19 15:40:02 +01001747
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 /* Hard code the off set to 15 for now */
Ralf Baechle20399732005-10-19 15:39:05 +01001749 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750 reg &= ~M_MAC_IPHDR_OFFSET | V_MAC_IPHDR_OFFSET(15);
Ralf Baechle20399732005-10-19 15:39:05 +01001751 __raw_writeq(reg, sc->sbm_rxfilter);
Ralf Baechle74b02472005-10-19 15:40:02 +01001752
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001753 /* BCM1250 pass1 didn't have hardware checksum. Everything
1754 later does. */
1755 if (soc_type == K_SYS_SOC_TYPE_BCM1250 && periph_rev < 2) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 sc->rx_hw_checksum = DISABLE;
Ralf Baechlef90fdc32006-02-08 23:23:26 +00001757 } else {
1758 sc->rx_hw_checksum = ENABLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 }
1760}
1761
1762
1763/**********************************************************************
1764 * SBMAC_ADDR2REG(ptr)
Ralf Baechle74b02472005-10-19 15:40:02 +01001765 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 * Convert six bytes into the 64-bit register value that
1767 * we typically write into the SBMAC's address/mcast registers
Ralf Baechle74b02472005-10-19 15:40:02 +01001768 *
1769 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 * ptr - pointer to 6 bytes
Ralf Baechle74b02472005-10-19 15:40:02 +01001771 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 * Return value:
1773 * register value
1774 ********************************************************************* */
1775
1776static uint64_t sbmac_addr2reg(unsigned char *ptr)
1777{
1778 uint64_t reg = 0;
Ralf Baechle74b02472005-10-19 15:40:02 +01001779
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 ptr += 6;
Ralf Baechle74b02472005-10-19 15:40:02 +01001781
1782 reg |= (uint64_t) *(--ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 reg <<= 8;
Ralf Baechle74b02472005-10-19 15:40:02 +01001784 reg |= (uint64_t) *(--ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785 reg <<= 8;
Ralf Baechle74b02472005-10-19 15:40:02 +01001786 reg |= (uint64_t) *(--ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787 reg <<= 8;
Ralf Baechle74b02472005-10-19 15:40:02 +01001788 reg |= (uint64_t) *(--ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 reg <<= 8;
Ralf Baechle74b02472005-10-19 15:40:02 +01001790 reg |= (uint64_t) *(--ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 reg <<= 8;
Ralf Baechle74b02472005-10-19 15:40:02 +01001792 reg |= (uint64_t) *(--ptr);
1793
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794 return reg;
1795}
1796
1797
1798/**********************************************************************
1799 * SBMAC_SET_SPEED(s,speed)
Ralf Baechle74b02472005-10-19 15:40:02 +01001800 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801 * Configure LAN speed for the specified MAC.
1802 * Warning: must be called when MAC is off!
Ralf Baechle74b02472005-10-19 15:40:02 +01001803 *
1804 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 * s - sbmac structure
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001806 * speed - speed to set MAC to (see enum sbmac_speed)
Ralf Baechle74b02472005-10-19 15:40:02 +01001807 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 * Return value:
1809 * 1 if successful
1810 * 0 indicates invalid parameters
1811 ********************************************************************* */
1812
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001813static int sbmac_set_speed(struct sbmac_softc *s, enum sbmac_speed speed)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814{
1815 uint64_t cfg;
1816 uint64_t framecfg;
1817
1818 /*
1819 * Save new current values
1820 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001821
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 s->sbm_speed = speed;
Ralf Baechle74b02472005-10-19 15:40:02 +01001823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 if (s->sbm_state == sbmac_state_on)
1825 return 0; /* save for next restart */
1826
1827 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001828 * Read current register values
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001830
Ralf Baechle20399732005-10-19 15:39:05 +01001831 cfg = __raw_readq(s->sbm_maccfg);
1832 framecfg = __raw_readq(s->sbm_framecfg);
Ralf Baechle74b02472005-10-19 15:40:02 +01001833
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834 /*
1835 * Mask out the stuff we want to change
1836 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001837
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838 cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
1839 framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
1840 M_MAC_SLOT_SIZE);
Ralf Baechle74b02472005-10-19 15:40:02 +01001841
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 /*
1843 * Now add in the new bits
1844 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846 switch (speed) {
1847 case sbmac_speed_10:
1848 framecfg |= V_MAC_IFG_RX_10 |
1849 V_MAC_IFG_TX_10 |
1850 K_MAC_IFG_THRSH_10 |
1851 V_MAC_SLOT_SIZE_10;
1852 cfg |= V_MAC_SPEED_SEL_10MBPS;
1853 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001854
Linus Torvalds1da177e2005-04-16 15:20:36 -07001855 case sbmac_speed_100:
1856 framecfg |= V_MAC_IFG_RX_100 |
1857 V_MAC_IFG_TX_100 |
1858 V_MAC_IFG_THRSH_100 |
1859 V_MAC_SLOT_SIZE_100;
1860 cfg |= V_MAC_SPEED_SEL_100MBPS ;
1861 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001862
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863 case sbmac_speed_1000:
1864 framecfg |= V_MAC_IFG_RX_1000 |
1865 V_MAC_IFG_TX_1000 |
1866 V_MAC_IFG_THRSH_1000 |
1867 V_MAC_SLOT_SIZE_1000;
1868 cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
1869 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001870
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871 default:
1872 return 0;
1873 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001874
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001876 * Send the bits back to the hardware
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001878
Ralf Baechle20399732005-10-19 15:39:05 +01001879 __raw_writeq(framecfg, s->sbm_framecfg);
1880 __raw_writeq(cfg, s->sbm_maccfg);
Ralf Baechle74b02472005-10-19 15:40:02 +01001881
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882 return 1;
1883}
1884
1885/**********************************************************************
1886 * SBMAC_SET_DUPLEX(s,duplex,fc)
Ralf Baechle74b02472005-10-19 15:40:02 +01001887 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888 * Set Ethernet duplex and flow control options for this MAC
1889 * Warning: must be called when MAC is off!
Ralf Baechle74b02472005-10-19 15:40:02 +01001890 *
1891 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892 * s - sbmac structure
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001893 * duplex - duplex setting (see enum sbmac_duplex)
1894 * fc - flow control setting (see enum sbmac_fc)
Ralf Baechle74b02472005-10-19 15:40:02 +01001895 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896 * Return value:
1897 * 1 if ok
1898 * 0 if an invalid parameter combination was specified
1899 ********************************************************************* */
1900
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01001901static int sbmac_set_duplex(struct sbmac_softc *s, enum sbmac_duplex duplex,
1902 enum sbmac_fc fc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903{
1904 uint64_t cfg;
Ralf Baechle74b02472005-10-19 15:40:02 +01001905
Linus Torvalds1da177e2005-04-16 15:20:36 -07001906 /*
1907 * Save new current values
1908 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001909
Linus Torvalds1da177e2005-04-16 15:20:36 -07001910 s->sbm_duplex = duplex;
1911 s->sbm_fc = fc;
Ralf Baechle74b02472005-10-19 15:40:02 +01001912
Linus Torvalds1da177e2005-04-16 15:20:36 -07001913 if (s->sbm_state == sbmac_state_on)
1914 return 0; /* save for next restart */
Ralf Baechle74b02472005-10-19 15:40:02 +01001915
Linus Torvalds1da177e2005-04-16 15:20:36 -07001916 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001917 * Read current register values
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001919
Ralf Baechle20399732005-10-19 15:39:05 +01001920 cfg = __raw_readq(s->sbm_maccfg);
Ralf Baechle74b02472005-10-19 15:40:02 +01001921
Linus Torvalds1da177e2005-04-16 15:20:36 -07001922 /*
1923 * Mask off the stuff we're about to change
1924 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001925
Linus Torvalds1da177e2005-04-16 15:20:36 -07001926 cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
Ralf Baechle74b02472005-10-19 15:40:02 +01001927
1928
Linus Torvalds1da177e2005-04-16 15:20:36 -07001929 switch (duplex) {
1930 case sbmac_duplex_half:
1931 switch (fc) {
1932 case sbmac_fc_disabled:
1933 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
1934 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001935
Linus Torvalds1da177e2005-04-16 15:20:36 -07001936 case sbmac_fc_collision:
1937 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
1938 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001939
Linus Torvalds1da177e2005-04-16 15:20:36 -07001940 case sbmac_fc_carrier:
1941 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
1942 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001943
Linus Torvalds1da177e2005-04-16 15:20:36 -07001944 case sbmac_fc_frame: /* not valid in half duplex */
1945 default: /* invalid selection */
1946 return 0;
1947 }
1948 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001949
Linus Torvalds1da177e2005-04-16 15:20:36 -07001950 case sbmac_duplex_full:
1951 switch (fc) {
1952 case sbmac_fc_disabled:
1953 cfg |= V_MAC_FC_CMD_DISABLED;
1954 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001955
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956 case sbmac_fc_frame:
1957 cfg |= V_MAC_FC_CMD_ENABLED;
1958 break;
Ralf Baechle74b02472005-10-19 15:40:02 +01001959
Linus Torvalds1da177e2005-04-16 15:20:36 -07001960 case sbmac_fc_collision: /* not valid in full duplex */
1961 case sbmac_fc_carrier: /* not valid in full duplex */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001962 default:
1963 return 0;
1964 }
1965 break;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01001966 default:
1967 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001968 }
Ralf Baechle74b02472005-10-19 15:40:02 +01001969
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01001971 * Send the bits back to the hardware
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 */
Ralf Baechle74b02472005-10-19 15:40:02 +01001973
Ralf Baechle20399732005-10-19 15:39:05 +01001974 __raw_writeq(cfg, s->sbm_maccfg);
Ralf Baechle74b02472005-10-19 15:40:02 +01001975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976 return 1;
1977}
1978
1979
1980
1981
1982/**********************************************************************
1983 * SBMAC_INTR()
Ralf Baechle74b02472005-10-19 15:40:02 +01001984 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001985 * Interrupt handler for MAC interrupts
Ralf Baechle74b02472005-10-19 15:40:02 +01001986 *
1987 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988 * MAC structure
Ralf Baechle74b02472005-10-19 15:40:02 +01001989 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001990 * Return value:
1991 * nothing
1992 ********************************************************************* */
David Howells7d12e782006-10-05 14:55:46 +01001993static irqreturn_t sbmac_intr(int irq,void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994{
1995 struct net_device *dev = (struct net_device *) dev_instance;
1996 struct sbmac_softc *sc = netdev_priv(dev);
1997 uint64_t isr;
1998 int handled = 0;
1999
Mark Mason693aa942007-04-26 00:23:22 -07002000 /*
2001 * Read the ISR (this clears the bits in the real
2002 * register, except for counter addr)
2003 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002004
Mark Mason693aa942007-04-26 00:23:22 -07002005 isr = __raw_readq(sc->sbm_isr) & ~M_MAC_COUNTER_ADDR;
Ralf Baechle74b02472005-10-19 15:40:02 +01002006
Mark Mason693aa942007-04-26 00:23:22 -07002007 if (isr == 0)
2008 return IRQ_RETVAL(0);
2009 handled = 1;
Ralf Baechle74b02472005-10-19 15:40:02 +01002010
Mark Mason693aa942007-04-26 00:23:22 -07002011 /*
2012 * Transmits on channel 0
2013 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002015 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0))
Mark Mason693aa942007-04-26 00:23:22 -07002016 sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
Ralf Baechle74b02472005-10-19 15:40:02 +01002017
Mark Mason693aa942007-04-26 00:23:22 -07002018 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
Ben Hutchings288379f2009-01-19 16:43:59 -08002019 if (napi_schedule_prep(&sc->napi)) {
Mark Mason693aa942007-04-26 00:23:22 -07002020 __raw_writeq(0, sc->sbm_imr);
Ben Hutchings288379f2009-01-19 16:43:59 -08002021 __napi_schedule(&sc->napi);
Mark Mason693aa942007-04-26 00:23:22 -07002022 /* Depend on the exit from poll to reenable intr */
2023 }
2024 else {
2025 /* may leave some packets behind */
2026 sbdma_rx_process(sc,&(sc->sbm_rxdma),
2027 SBMAC_MAX_RXDESCR * 2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 }
2029 }
2030 return IRQ_RETVAL(handled);
2031}
2032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033/**********************************************************************
2034 * SBMAC_START_TX(skb,dev)
Ralf Baechle74b02472005-10-19 15:40:02 +01002035 *
2036 * Start output on the specified interface. Basically, we
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 * queue as many buffers as we can until the ring fills up, or
2038 * we run off the end of the queue, whichever comes first.
Ralf Baechle74b02472005-10-19 15:40:02 +01002039 *
2040 * Input parameters:
2041 *
2042 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043 * Return value:
2044 * nothing
2045 ********************************************************************* */
2046static int sbmac_start_tx(struct sk_buff *skb, struct net_device *dev)
2047{
2048 struct sbmac_softc *sc = netdev_priv(dev);
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002049 unsigned long flags;
Ralf Baechle74b02472005-10-19 15:40:02 +01002050
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051 /* lock eth irq */
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002052 spin_lock_irqsave(&sc->sbm_lock, flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01002053
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054 /*
Ralf Baechle74b02472005-10-19 15:40:02 +01002055 * Put the buffer on the transmit ring. If we
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056 * don't have room, stop the queue.
2057 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002058
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 if (sbdma_add_txbuffer(&(sc->sbm_txdma),skb)) {
2060 /* XXX save skb that we could not send */
2061 netif_stop_queue(dev);
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002062 spin_unlock_irqrestore(&sc->sbm_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Patrick McHardy5b548142009-06-12 06:22:29 +00002064 return NETDEV_TX_BUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002066
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002067 spin_unlock_irqrestore(&sc->sbm_lock, flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01002068
Patrick McHardy6ed10652009-06-23 06:03:08 +00002069 return NETDEV_TX_OK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070}
2071
2072/**********************************************************************
2073 * SBMAC_SETMULTI(sc)
Ralf Baechle74b02472005-10-19 15:40:02 +01002074 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075 * Reprogram the multicast table into the hardware, given
2076 * the list of multicasts associated with the interface
2077 * structure.
Ralf Baechle74b02472005-10-19 15:40:02 +01002078 *
2079 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080 * sc - softc
Ralf Baechle74b02472005-10-19 15:40:02 +01002081 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 * Return value:
2083 * nothing
2084 ********************************************************************* */
2085
2086static void sbmac_setmulti(struct sbmac_softc *sc)
2087{
2088 uint64_t reg;
Maciej W. Rozycki73d73962007-09-20 19:14:01 +01002089 void __iomem *port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 int idx;
Jiri Pirko22bedad32010-04-01 21:22:57 +00002091 struct netdev_hw_addr *ha;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092 struct net_device *dev = sc->sbm_dev;
Ralf Baechle74b02472005-10-19 15:40:02 +01002093
2094 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095 * Clear out entire multicast table. We do this by nuking
2096 * the entire hash table and all the direct matches except
Ralf Baechle74b02472005-10-19 15:40:02 +01002097 * the first one, which is used for our station address
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002099
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100 for (idx = 1; idx < MAC_ADDR_COUNT; idx++) {
2101 port = sc->sbm_base + R_MAC_ADDR_BASE+(idx*sizeof(uint64_t));
Ralf Baechle20399732005-10-19 15:39:05 +01002102 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002104
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
2106 port = sc->sbm_base + R_MAC_HASH_BASE+(idx*sizeof(uint64_t));
Ralf Baechle20399732005-10-19 15:39:05 +01002107 __raw_writeq(0, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002109
Linus Torvalds1da177e2005-04-16 15:20:36 -07002110 /*
2111 * Clear the filter to say we don't want any multicasts.
2112 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002113
Ralf Baechle20399732005-10-19 15:39:05 +01002114 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 reg &= ~(M_MAC_MCAST_INV | M_MAC_MCAST_EN);
Ralf Baechle20399732005-10-19 15:39:05 +01002116 __raw_writeq(reg, sc->sbm_rxfilter);
Ralf Baechle74b02472005-10-19 15:40:02 +01002117
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118 if (dev->flags & IFF_ALLMULTI) {
Ralf Baechle74b02472005-10-19 15:40:02 +01002119 /*
2120 * Enable ALL multicasts. Do this by inverting the
2121 * multicast enable bit.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 */
Ralf Baechle20399732005-10-19 15:39:05 +01002123 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 reg |= (M_MAC_MCAST_INV | M_MAC_MCAST_EN);
Ralf Baechle20399732005-10-19 15:39:05 +01002125 __raw_writeq(reg, sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126 return;
2127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Ralf Baechle74b02472005-10-19 15:40:02 +01002129
2130 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 * Progam new multicast entries. For now, only use the
2132 * perfect filter. In the future we'll need to use the
2133 * hash filter if the perfect filter overflows
2134 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002135
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 /* XXX only using perfect filter for now, need to use hash
2137 * XXX if the table overflows */
Ralf Baechle74b02472005-10-19 15:40:02 +01002138
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139 idx = 1; /* skip station address */
Jiri Pirko22bedad32010-04-01 21:22:57 +00002140 netdev_for_each_mc_addr(ha, dev) {
Jiri Pirko55085902010-02-18 00:42:54 +00002141 if (idx == MAC_ADDR_COUNT)
2142 break;
Jiri Pirko22bedad32010-04-01 21:22:57 +00002143 reg = sbmac_addr2reg(ha->addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144 port = sc->sbm_base + R_MAC_ADDR_BASE+(idx * sizeof(uint64_t));
Ralf Baechle20399732005-10-19 15:39:05 +01002145 __raw_writeq(reg, port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002148
2149 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150 * Enable the "accept multicast bits" if we programmed at least one
Ralf Baechle74b02472005-10-19 15:40:02 +01002151 * multicast.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 if (idx > 1) {
Ralf Baechle20399732005-10-19 15:39:05 +01002155 reg = __raw_readq(sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156 reg |= M_MAC_MCAST_EN;
Ralf Baechle20399732005-10-19 15:39:05 +01002157 __raw_writeq(reg, sc->sbm_rxfilter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 }
2159}
2160
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161static int sb1250_change_mtu(struct net_device *_dev, int new_mtu)
2162{
2163 if (new_mtu > ENET_PACKET_SIZE)
2164 return -EINVAL;
2165 _dev->mtu = new_mtu;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002166 pr_info("changing the mtu to %d\n", new_mtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 return 0;
2168}
2169
Alexander Beregalovb4cf3422009-04-15 12:52:57 +00002170static const struct net_device_ops sbmac_netdev_ops = {
2171 .ndo_open = sbmac_open,
2172 .ndo_stop = sbmac_close,
2173 .ndo_start_xmit = sbmac_start_tx,
Jiri Pirkoafc4b132011-08-16 06:29:01 +00002174 .ndo_set_rx_mode = sbmac_set_rx_mode,
Alexander Beregalovb4cf3422009-04-15 12:52:57 +00002175 .ndo_tx_timeout = sbmac_tx_timeout,
2176 .ndo_do_ioctl = sbmac_mii_ioctl,
2177 .ndo_change_mtu = sb1250_change_mtu,
2178 .ndo_validate_addr = eth_validate_addr,
2179 .ndo_set_mac_address = eth_mac_addr,
2180#ifdef CONFIG_NET_POLL_CONTROLLER
2181 .ndo_poll_controller = sbmac_netpoll,
2182#endif
2183};
2184
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185/**********************************************************************
2186 * SBMAC_INIT(dev)
Ralf Baechle74b02472005-10-19 15:40:02 +01002187 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 * Attach routine - init hardware and hook ourselves into linux
Ralf Baechle74b02472005-10-19 15:40:02 +01002189 *
2190 * Input parameters:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 * dev - net_device structure
Ralf Baechle74b02472005-10-19 15:40:02 +01002192 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 * Return value:
2194 * status
2195 ********************************************************************* */
2196
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002197static int sbmac_init(struct platform_device *pldev, long long base)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198{
Jingoo Han8513fbd2013-05-23 00:52:31 +00002199 struct net_device *dev = platform_get_drvdata(pldev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002200 int idx = pldev->id;
2201 struct sbmac_softc *sc = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 unsigned char *eaddr;
2203 uint64_t ea_reg;
2204 int i;
2205 int err;
Ralf Baechle74b02472005-10-19 15:40:02 +01002206
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 sc->sbm_dev = dev;
2208 sc->sbe_idx = idx;
Ralf Baechle74b02472005-10-19 15:40:02 +01002209
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210 eaddr = sc->sbm_hwaddr;
Ralf Baechle74b02472005-10-19 15:40:02 +01002211
2212 /*
Nick Andrew877d0312009-01-26 11:06:57 +01002213 * Read the ethernet address. The firmware left this programmed
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214 * for us in the ethernet address register for each mac.
2215 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002216
Ralf Baechle20399732005-10-19 15:39:05 +01002217 ea_reg = __raw_readq(sc->sbm_base + R_MAC_ETHERNET_ADDR);
2218 __raw_writeq(0, sc->sbm_base + R_MAC_ETHERNET_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 for (i = 0; i < 6; i++) {
2220 eaddr[i] = (uint8_t) (ea_reg & 0xFF);
2221 ea_reg >>= 8;
2222 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002223
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 for (i = 0; i < 6; i++) {
2225 dev->dev_addr[i] = eaddr[i];
2226 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002227
Ralf Baechle74b02472005-10-19 15:40:02 +01002228 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 * Initialize context (get pointers to registers and stuff), then
2230 * allocate the memory for the descriptor tables.
2231 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002232
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233 sbmac_initctx(sc);
Ralf Baechle74b02472005-10-19 15:40:02 +01002234
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235 /*
2236 * Set up Linux device callins
2237 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002238
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 spin_lock_init(&(sc->sbm_lock));
Ralf Baechle74b02472005-10-19 15:40:02 +01002240
Alexander Beregalovb4cf3422009-04-15 12:52:57 +00002241 dev->netdev_ops = &sbmac_netdev_ops;
2242 dev->watchdog_timeo = TX_TIMEOUT;
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002243
2244 netif_napi_add(dev, &sc->napi, sbmac_poll, 16);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002246 dev->irq = UNIT_INT(idx);
2247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 /* This is needed for PASS2 for Rx H/W checksum feature */
2249 sbmac_set_iphdr_offset(sc);
2250
Lennert Buytenhek298cf9b2008-10-08 16:29:57 -07002251 sc->mii_bus = mdiobus_alloc();
2252 if (sc->mii_bus == NULL) {
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002253 err = -ENOMEM;
2254 goto uninit_ctx;
Lennert Buytenhek298cf9b2008-10-08 16:29:57 -07002255 }
2256
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002257 sc->mii_bus->name = sbmac_mdio_string;
Florian Fainelli446bbc42012-01-09 23:59:10 +00002258 snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
2259 pldev->name, idx);
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002260 sc->mii_bus->priv = sc;
2261 sc->mii_bus->read = sbmac_mii_read;
2262 sc->mii_bus->write = sbmac_mii_write;
2263 sc->mii_bus->irq = sc->phy_irq;
2264 for (i = 0; i < PHY_MAX_ADDR; ++i)
2265 sc->mii_bus->irq[i] = SBMAC_PHY_INT;
2266
2267 sc->mii_bus->parent = &pldev->dev;
2268 /*
2269 * Probe PHY address
2270 */
2271 err = mdiobus_register(sc->mii_bus);
2272 if (err) {
2273 printk(KERN_ERR "%s: unable to register MDIO bus\n",
2274 dev->name);
2275 goto free_mdio;
2276 }
Jingoo Han8513fbd2013-05-23 00:52:31 +00002277 platform_set_drvdata(pldev, sc->mii_bus);
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002278
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 err = register_netdev(dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002280 if (err) {
2281 printk(KERN_ERR "%s.%d: unable to register netdev\n",
2282 sbmac_string, idx);
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002283 goto unreg_mdio;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 }
2285
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002286 pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name);
2287
2288 if (sc->rx_hw_checksum == ENABLE)
2289 pr_info("%s: enabling TCP rcv checksum\n", dev->name);
2290
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 /*
2292 * Display Ethernet address (this is called during the config
2293 * process so we need to finish off the config message that
2294 * was being displayed)
2295 */
Johannes Berge1749612008-10-27 15:59:26 -07002296 pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n",
2297 dev->name, base, eaddr);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 return 0;
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002300unreg_mdio:
2301 mdiobus_unregister(sc->mii_bus);
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002302free_mdio:
2303 mdiobus_free(sc->mii_bus);
2304uninit_ctx:
2305 sbmac_uninitctx(sc);
2306 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307}
2308
2309
2310static int sbmac_open(struct net_device *dev)
2311{
2312 struct sbmac_softc *sc = netdev_priv(dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002313 int err;
Ralf Baechle74b02472005-10-19 15:40:02 +01002314
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002315 if (debug > 1)
2316 pr_debug("%s: sbmac_open() irq %d.\n", dev->name, dev->irq);
Ralf Baechle74b02472005-10-19 15:40:02 +01002317
2318 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319 * map/route interrupt (clear status first, in case something
2320 * weird is pending; we haven't initialized the mac registers
2321 * yet)
2322 */
2323
Ralf Baechle20399732005-10-19 15:39:05 +01002324 __raw_readq(sc->sbm_isr);
Joe Perchesa0607fd2009-11-18 23:29:17 -08002325 err = request_irq(dev->irq, sbmac_intr, IRQF_SHARED, dev->name, dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002326 if (err) {
2327 printk(KERN_ERR "%s: unable to get IRQ %d\n", dev->name,
2328 dev->irq);
2329 goto out_err;
Ralf Baechle59b81822005-10-20 12:01:28 +01002330 }
2331
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002332 sc->sbm_speed = sbmac_speed_none;
2333 sc->sbm_duplex = sbmac_duplex_none;
2334 sc->sbm_fc = sbmac_fc_none;
2335 sc->sbm_pause = -1;
2336 sc->sbm_link = 0;
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002337
Ralf Baechle59b81822005-10-20 12:01:28 +01002338 /*
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002339 * Attach to the PHY
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 */
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002341 err = sbmac_mii_probe(dev);
2342 if (err)
2343 goto out_unregister;
Ralf Baechle74b02472005-10-19 15:40:02 +01002344
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 /*
2346 * Turn on the channel
2347 */
2348
2349 sbmac_set_channel_state(sc,sbmac_state_on);
Ralf Baechle74b02472005-10-19 15:40:02 +01002350
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 netif_start_queue(dev);
Ralf Baechle74b02472005-10-19 15:40:02 +01002352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353 sbmac_set_rx_mode(dev);
Ralf Baechle74b02472005-10-19 15:40:02 +01002354
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002355 phy_start(sc->phy_dev);
2356
2357 napi_enable(&sc->napi);
Ralf Baechle74b02472005-10-19 15:40:02 +01002358
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 return 0;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002360
2361out_unregister:
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002362 free_irq(dev->irq, dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002363out_err:
2364 return err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365}
2366
Ralf Baechle59b81822005-10-20 12:01:28 +01002367static int sbmac_mii_probe(struct net_device *dev)
2368{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 struct sbmac_softc *sc = netdev_priv(dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002370 struct phy_device *phy_dev;
2371 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002373 for (i = 0; i < PHY_MAX_ADDR; i++) {
Lennert Buytenhek298cf9b2008-10-08 16:29:57 -07002374 phy_dev = sc->mii_bus->phy_map[i];
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002375 if (phy_dev)
2376 break;
2377 }
2378 if (!phy_dev) {
2379 printk(KERN_ERR "%s: no PHY found\n", dev->name);
2380 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002382
Florian Fainellif9a8f832013-01-14 00:52:52 +00002383 phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll,
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002384 PHY_INTERFACE_MODE_GMII);
2385 if (IS_ERR(phy_dev)) {
2386 printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
2387 return PTR_ERR(phy_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 }
Ralf Baechle74b02472005-10-19 15:40:02 +01002389
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002390 /* Remove any features not supported by the controller */
2391 phy_dev->supported &= SUPPORTED_10baseT_Half |
2392 SUPPORTED_10baseT_Full |
2393 SUPPORTED_100baseT_Half |
2394 SUPPORTED_100baseT_Full |
2395 SUPPORTED_1000baseT_Half |
2396 SUPPORTED_1000baseT_Full |
2397 SUPPORTED_Autoneg |
2398 SUPPORTED_MII |
2399 SUPPORTED_Pause |
2400 SUPPORTED_Asym_Pause;
2401 phy_dev->advertising = phy_dev->supported;
Ralf Baechle74b02472005-10-19 15:40:02 +01002402
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002403 pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
2404 dev->name, phy_dev->drv->name,
Kay Sieversdb1d7bf2009-01-26 21:12:58 -08002405 dev_name(&phy_dev->dev), phy_dev->irq);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002406
2407 sc->phy_dev = phy_dev;
2408
2409 return 0;
2410}
2411
2412
2413static void sbmac_mii_poll(struct net_device *dev)
2414{
2415 struct sbmac_softc *sc = netdev_priv(dev);
2416 struct phy_device *phy_dev = sc->phy_dev;
2417 unsigned long flags;
2418 enum sbmac_fc fc;
2419 int link_chg, speed_chg, duplex_chg, pause_chg, fc_chg;
2420
2421 link_chg = (sc->sbm_link != phy_dev->link);
2422 speed_chg = (sc->sbm_speed != phy_dev->speed);
2423 duplex_chg = (sc->sbm_duplex != phy_dev->duplex);
2424 pause_chg = (sc->sbm_pause != phy_dev->pause);
2425
2426 if (!link_chg && !speed_chg && !duplex_chg && !pause_chg)
2427 return; /* Hmmm... */
2428
2429 if (!phy_dev->link) {
2430 if (link_chg) {
2431 sc->sbm_link = phy_dev->link;
2432 sc->sbm_speed = sbmac_speed_none;
2433 sc->sbm_duplex = sbmac_duplex_none;
2434 sc->sbm_fc = sbmac_fc_disabled;
2435 sc->sbm_pause = -1;
2436 pr_info("%s: link unavailable\n", dev->name);
2437 }
2438 return;
2439 }
2440
2441 if (phy_dev->duplex == DUPLEX_FULL) {
2442 if (phy_dev->pause)
2443 fc = sbmac_fc_frame;
2444 else
2445 fc = sbmac_fc_disabled;
2446 } else
2447 fc = sbmac_fc_collision;
2448 fc_chg = (sc->sbm_fc != fc);
2449
2450 pr_info("%s: link available: %dbase-%cD\n", dev->name, phy_dev->speed,
2451 phy_dev->duplex == DUPLEX_FULL ? 'F' : 'H');
2452
2453 spin_lock_irqsave(&sc->sbm_lock, flags);
2454
2455 sc->sbm_speed = phy_dev->speed;
2456 sc->sbm_duplex = phy_dev->duplex;
2457 sc->sbm_fc = fc;
2458 sc->sbm_pause = phy_dev->pause;
2459 sc->sbm_link = phy_dev->link;
2460
2461 if ((speed_chg || duplex_chg || fc_chg) &&
2462 sc->sbm_state != sbmac_state_off) {
2463 /*
2464 * something changed, restart the channel
2465 */
2466 if (debug > 1)
2467 pr_debug("%s: restarting channel "
2468 "because PHY state changed\n", dev->name);
2469 sbmac_channel_stop(sc);
2470 sbmac_channel_start(sc);
2471 }
2472
2473 spin_unlock_irqrestore(&sc->sbm_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474}
2475
2476
2477static void sbmac_tx_timeout (struct net_device *dev)
2478{
2479 struct sbmac_softc *sc = netdev_priv(dev);
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002480 unsigned long flags;
Ralf Baechle74b02472005-10-19 15:40:02 +01002481
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002482 spin_lock_irqsave(&sc->sbm_lock, flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01002483
2484
Eric Dumazet1ae5dc32010-05-10 05:01:31 -07002485 dev->trans_start = jiffies; /* prevent tx timeout */
Jeff Garzik09f75cd2007-10-03 17:41:50 -07002486 dev->stats.tx_errors++;
Ralf Baechle74b02472005-10-19 15:40:02 +01002487
Weiwei Wangbe61ea52008-09-18 08:23:48 +08002488 spin_unlock_irqrestore(&sc->sbm_lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
2490 printk (KERN_WARNING "%s: Transmit timed out\n",dev->name);
2491}
2492
2493
2494
2495
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496static void sbmac_set_rx_mode(struct net_device *dev)
2497{
2498 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 struct sbmac_softc *sc = netdev_priv(dev);
2500
2501 spin_lock_irqsave(&sc->sbm_lock, flags);
2502 if ((dev->flags ^ sc->sbm_devflags) & IFF_PROMISC) {
2503 /*
2504 * Promiscuous changed.
2505 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002506
2507 if (dev->flags & IFF_PROMISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 sbmac_promiscuous_mode(sc,1);
2509 }
2510 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 sbmac_promiscuous_mode(sc,0);
2512 }
2513 }
2514 spin_unlock_irqrestore(&sc->sbm_lock, flags);
Ralf Baechle74b02472005-10-19 15:40:02 +01002515
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 /*
2517 * Program the multicasts. Do this every time.
2518 */
Ralf Baechle74b02472005-10-19 15:40:02 +01002519
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 sbmac_setmulti(sc);
Ralf Baechle74b02472005-10-19 15:40:02 +01002521
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522}
2523
2524static int sbmac_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2525{
2526 struct sbmac_softc *sc = netdev_priv(dev);
Ralf Baechle74b02472005-10-19 15:40:02 +01002527
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002528 if (!netif_running(dev) || !sc->phy_dev)
2529 return -EINVAL;
Ralf Baechle74b02472005-10-19 15:40:02 +01002530
Richard Cochran28b04112010-07-17 08:48:55 +00002531 return phy_mii_ioctl(sc->phy_dev, rq, cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532}
2533
2534static int sbmac_close(struct net_device *dev)
2535{
2536 struct sbmac_softc *sc = netdev_priv(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002538 napi_disable(&sc->napi);
2539
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002540 phy_stop(sc->phy_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002542 sbmac_set_channel_state(sc, sbmac_state_off);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
2544 netif_stop_queue(dev);
2545
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002546 if (debug > 1)
2547 pr_debug("%s: Shutting down ethercard\n", dev->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002549 phy_disconnect(sc->phy_dev);
2550 sc->phy_dev = NULL;
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002551 free_irq(dev->irq, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
2553 sbdma_emptyring(&(sc->sbm_txdma));
2554 sbdma_emptyring(&(sc->sbm_rxdma));
Ralf Baechle74b02472005-10-19 15:40:02 +01002555
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 return 0;
2557}
2558
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002559static int sbmac_poll(struct napi_struct *napi, int budget)
Mark Mason693aa942007-04-26 00:23:22 -07002560{
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002561 struct sbmac_softc *sc = container_of(napi, struct sbmac_softc, napi);
Mark Mason693aa942007-04-26 00:23:22 -07002562 int work_done;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002564 work_done = sbdma_rx_process(sc, &(sc->sbm_rxdma), budget, 1);
Mark Mason693aa942007-04-26 00:23:22 -07002565 sbdma_tx_process(sc, &(sc->sbm_txdma), 1);
2566
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002567 if (work_done < budget) {
Ben Hutchings288379f2009-01-19 16:43:59 -08002568 napi_complete(napi);
Mark Mason693aa942007-04-26 00:23:22 -07002569
2570#ifdef CONFIG_SBMAC_COALESCE
2571 __raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
2572 ((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_RX_CH0),
2573 sc->sbm_imr);
2574#else
2575 __raw_writeq((M_MAC_INT_CHANNEL << S_MAC_TX_CH0) |
2576 (M_MAC_INT_CHANNEL << S_MAC_RX_CH0), sc->sbm_imr);
2577#endif
2578 }
2579
Stephen Hemmingerbea33482007-10-03 16:41:36 -07002580 return work_done;
Mark Mason693aa942007-04-26 00:23:22 -07002581}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002583
Bill Pemberton047fc562012-12-03 09:24:23 -05002584static int sbmac_probe(struct platform_device *pldev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585{
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002586 struct net_device *dev;
2587 struct sbmac_softc *sc;
2588 void __iomem *sbm_base;
2589 struct resource *res;
2590 u64 sbmac_orig_hwaddr;
2591 int err;
2592
2593 res = platform_get_resource(pldev, IORESOURCE_MEM, 0);
2594 BUG_ON(!res);
Joe Perches28f65c112011-06-09 09:13:32 -07002595 sbm_base = ioremap_nocache(res->start, resource_size(res));
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002596 if (!sbm_base) {
2597 printk(KERN_ERR "%s: unable to map device registers\n",
Kay Sieversdb1d7bf2009-01-26 21:12:58 -08002598 dev_name(&pldev->dev));
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002599 err = -ENOMEM;
2600 goto out_out;
2601 }
2602
2603 /*
2604 * The R_MAC_ETHERNET_ADDR register will be set to some nonzero
2605 * value for us by the firmware if we're going to use this MAC.
2606 * If we find a zero, skip this MAC.
2607 */
2608 sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR);
Kay Sieversdb1d7bf2009-01-26 21:12:58 -08002609 pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev),
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002610 sbmac_orig_hwaddr ? "" : "not ", (long long)res->start);
2611 if (sbmac_orig_hwaddr == 0) {
2612 err = 0;
2613 goto out_unmap;
2614 }
2615
2616 /*
2617 * Okay, cool. Initialize this MAC.
2618 */
2619 dev = alloc_etherdev(sizeof(struct sbmac_softc));
2620 if (!dev) {
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002621 err = -ENOMEM;
2622 goto out_unmap;
2623 }
2624
Jingoo Han8513fbd2013-05-23 00:52:31 +00002625 platform_set_drvdata(pldev, dev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002626 SET_NETDEV_DEV(dev, &pldev->dev);
2627
2628 sc = netdev_priv(dev);
2629 sc->sbm_base = sbm_base;
2630
2631 err = sbmac_init(pldev, res->start);
2632 if (err)
2633 goto out_kfree;
2634
2635 return 0;
2636
2637out_kfree:
2638 free_netdev(dev);
2639 __raw_writeq(sbmac_orig_hwaddr, sbm_base + R_MAC_ETHERNET_ADDR);
2640
2641out_unmap:
2642 iounmap(sbm_base);
2643
2644out_out:
2645 return err;
2646}
2647
2648static int __exit sbmac_remove(struct platform_device *pldev)
2649{
Jingoo Han8513fbd2013-05-23 00:52:31 +00002650 struct net_device *dev = platform_get_drvdata(pldev);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002651 struct sbmac_softc *sc = netdev_priv(dev);
2652
2653 unregister_netdev(dev);
2654 sbmac_uninitctx(sc);
Sebastian Siewior03f80cc2010-04-28 09:57:01 +00002655 mdiobus_unregister(sc->mii_bus);
Lennert Buytenhek298cf9b2008-10-08 16:29:57 -07002656 mdiobus_free(sc->mii_bus);
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002657 iounmap(sc->sbm_base);
2658 free_netdev(dev);
2659
2660 return 0;
2661}
2662
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002663static struct platform_driver sbmac_driver = {
2664 .probe = sbmac_probe,
2665 .remove = __exit_p(sbmac_remove),
2666 .driver = {
2667 .name = sbmac_string,
Ralf Baechle33b665e2010-07-06 05:18:11 +00002668 .owner = THIS_MODULE,
Maciej W. Rozyckif5279ff2007-09-21 12:52:10 +01002669 },
2670};
2671
Axel Lindb62f682011-11-27 16:44:17 +00002672module_platform_driver(sbmac_driver);