diff options
Diffstat (limited to 'arch/ppc/8260_io/fcc_enet.c')
-rw-r--r-- | arch/ppc/8260_io/fcc_enet.c | 2379 |
1 files changed, 0 insertions, 2379 deletions
diff --git a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c deleted file mode 100644 index d38b57e24cee..000000000000 --- a/arch/ppc/8260_io/fcc_enet.c +++ /dev/null | |||
@@ -1,2379 +0,0 @@ | |||
1 | /* | ||
2 | * Fast Ethernet Controller (FCC) driver for Motorola MPC8260. | ||
3 | * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net) | ||
4 | * | ||
5 | * This version of the driver is a combination of the 8xx fec and | ||
6 | * 8260 SCC Ethernet drivers. This version has some additional | ||
7 | * configuration options, which should probably be moved out of | ||
8 | * here. This driver currently works for the EST SBC8260, | ||
9 | * SBS Diablo/BCM, Embedded Planet RPX6, TQM8260, and others. | ||
10 | * | ||
11 | * Right now, I am very watseful with the buffers. I allocate memory | ||
12 | * pages and then divide them into 2K frame buffers. This way I know I | ||
13 | * have buffers large enough to hold one frame within one buffer descriptor. | ||
14 | * Once I get this working, I will use 64 or 128 byte CPM buffers, which | ||
15 | * will be much more memory efficient and will easily handle lots of | ||
16 | * small packets. Since this is a cache coherent processor and CPM, | ||
17 | * I could also preallocate SKB's and use them directly on the interface. | ||
18 | * | ||
19 | * 2004-12 Leo Li (leoli@freescale.com) | ||
20 | * - Rework the FCC clock configuration part, make it easier to configure. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/ptrace.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/ioport.h> | ||
30 | #include <linux/slab.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/delay.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <linux/etherdevice.h> | ||
36 | #include <linux/skbuff.h> | ||
37 | #include <linux/spinlock.h> | ||
38 | #include <linux/mii.h> | ||
39 | #include <linux/workqueue.h> | ||
40 | #include <linux/bitops.h> | ||
41 | |||
42 | #include <asm/immap_cpm2.h> | ||
43 | #include <asm/pgtable.h> | ||
44 | #include <asm/mpc8260.h> | ||
45 | #include <asm/irq.h> | ||
46 | #include <asm/uaccess.h> | ||
47 | #include <asm/signal.h> | ||
48 | |||
49 | /* We can't use the PHY interrupt if we aren't using MDIO. */ | ||
50 | #if !defined(CONFIG_USE_MDIO) | ||
51 | #undef PHY_INTERRUPT | ||
52 | #endif | ||
53 | |||
54 | /* If we have a PHY interrupt, we will advertise both full-duplex and half- | ||
55 | * duplex capabilities. If we don't have a PHY interrupt, then we will only | ||
56 | * advertise half-duplex capabilities. | ||
57 | */ | ||
58 | #define MII_ADVERTISE_HALF (ADVERTISE_100HALF | ADVERTISE_10HALF | \ | ||
59 | ADVERTISE_CSMA) | ||
60 | #define MII_ADVERTISE_ALL (ADVERTISE_100FULL | ADVERTISE_10FULL | \ | ||
61 | MII_ADVERTISE_HALF) | ||
62 | #ifdef PHY_INTERRUPT | ||
63 | #define MII_ADVERTISE_DEFAULT MII_ADVERTISE_ALL | ||
64 | #else | ||
65 | #define MII_ADVERTISE_DEFAULT MII_ADVERTISE_HALF | ||
66 | #endif | ||
67 | #include <asm/cpm2.h> | ||
68 | |||
69 | /* The transmitter timeout | ||
70 | */ | ||
71 | #define TX_TIMEOUT (2*HZ) | ||
72 | |||
73 | #ifdef CONFIG_USE_MDIO | ||
74 | /* Forward declarations of some structures to support different PHYs */ | ||
75 | |||
76 | typedef struct { | ||
77 | uint mii_data; | ||
78 | void (*funct)(uint mii_reg, struct net_device *dev); | ||
79 | } phy_cmd_t; | ||
80 | |||
81 | typedef struct { | ||
82 | uint id; | ||
83 | char *name; | ||
84 | |||
85 | const phy_cmd_t *config; | ||
86 | const phy_cmd_t *startup; | ||
87 | const phy_cmd_t *ack_int; | ||
88 | const phy_cmd_t *shutdown; | ||
89 | } phy_info_t; | ||
90 | |||
91 | /* values for phy_status */ | ||
92 | |||
93 | #define PHY_CONF_ANE 0x0001 /* 1 auto-negotiation enabled */ | ||
94 | #define PHY_CONF_LOOP 0x0002 /* 1 loopback mode enabled */ | ||
95 | #define PHY_CONF_SPMASK 0x00f0 /* mask for speed */ | ||
96 | #define PHY_CONF_10HDX 0x0010 /* 10 Mbit half duplex supported */ | ||
97 | #define PHY_CONF_10FDX 0x0020 /* 10 Mbit full duplex supported */ | ||
98 | #define PHY_CONF_100HDX 0x0040 /* 100 Mbit half duplex supported */ | ||
99 | #define PHY_CONF_100FDX 0x0080 /* 100 Mbit full duplex supported */ | ||
100 | |||
101 | #define PHY_STAT_LINK 0x0100 /* 1 up - 0 down */ | ||
102 | #define PHY_STAT_FAULT 0x0200 /* 1 remote fault */ | ||
103 | #define PHY_STAT_ANC 0x0400 /* 1 auto-negotiation complete */ | ||
104 | #define PHY_STAT_SPMASK 0xf000 /* mask for speed */ | ||
105 | #define PHY_STAT_10HDX 0x1000 /* 10 Mbit half duplex selected */ | ||
106 | #define PHY_STAT_10FDX 0x2000 /* 10 Mbit full duplex selected */ | ||
107 | #define PHY_STAT_100HDX 0x4000 /* 100 Mbit half duplex selected */ | ||
108 | #define PHY_STAT_100FDX 0x8000 /* 100 Mbit full duplex selected */ | ||
109 | #endif /* CONFIG_USE_MDIO */ | ||
110 | |||
111 | /* The number of Tx and Rx buffers. These are allocated from the page | ||
112 | * pool. The code may assume these are power of two, so it is best | ||
113 | * to keep them that size. | ||
114 | * We don't need to allocate pages for the transmitter. We just use | ||
115 | * the skbuffer directly. | ||
116 | */ | ||
117 | #define FCC_ENET_RX_PAGES 16 | ||
118 | #define FCC_ENET_RX_FRSIZE 2048 | ||
119 | #define FCC_ENET_RX_FRPPG (PAGE_SIZE / FCC_ENET_RX_FRSIZE) | ||
120 | #define RX_RING_SIZE (FCC_ENET_RX_FRPPG * FCC_ENET_RX_PAGES) | ||
121 | #define TX_RING_SIZE 16 /* Must be power of two */ | ||
122 | #define TX_RING_MOD_MASK 15 /* for this to work */ | ||
123 | |||
124 | /* The FCC stores dest/src/type, data, and checksum for receive packets. | ||
125 | * size includes support for VLAN | ||
126 | */ | ||
127 | #define PKT_MAXBUF_SIZE 1522 | ||
128 | #define PKT_MINBUF_SIZE 64 | ||
129 | |||
130 | /* Maximum input DMA size. Must be a should(?) be a multiple of 4. | ||
131 | * size includes support for VLAN | ||
132 | */ | ||
133 | #define PKT_MAXDMA_SIZE 1524 | ||
134 | |||
135 | /* Maximum input buffer size. Must be a multiple of 32. | ||
136 | */ | ||
137 | #define PKT_MAXBLR_SIZE 1536 | ||
138 | |||
139 | static int fcc_enet_open(struct net_device *dev); | ||
140 | static int fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev); | ||
141 | static int fcc_enet_rx(struct net_device *dev); | ||
142 | static irqreturn_t fcc_enet_interrupt(int irq, void *dev_id); | ||
143 | static int fcc_enet_close(struct net_device *dev); | ||
144 | static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev); | ||
145 | /* static void set_multicast_list(struct net_device *dev); */ | ||
146 | static void fcc_restart(struct net_device *dev, int duplex); | ||
147 | static void fcc_stop(struct net_device *dev); | ||
148 | static int fcc_enet_set_mac_address(struct net_device *dev, void *addr); | ||
149 | |||
150 | /* These will be configurable for the FCC choice. | ||
151 | * Multiple ports can be configured. There is little choice among the | ||
152 | * I/O pins to the PHY, except the clocks. We will need some board | ||
153 | * dependent clock selection. | ||
154 | * Why in the hell did I put these inside #ifdef's? I dunno, maybe to | ||
155 | * help show what pins are used for each device. | ||
156 | */ | ||
157 | |||
158 | /* Since the CLK setting changes greatly from board to board, I changed | ||
159 | * it to a easy way. You just need to specify which CLK number to use. | ||
160 | * Note that only limited choices can be make on each port. | ||
161 | */ | ||
162 | |||
163 | /* FCC1 Clock Source Configuration. There are board specific. | ||
164 | Can only choose from CLK9-12 */ | ||
165 | #ifdef CONFIG_SBC82xx | ||
166 | #define F1_RXCLK 9 | ||
167 | #define F1_TXCLK 10 | ||
168 | #else | ||
169 | #define F1_RXCLK 12 | ||
170 | #define F1_TXCLK 11 | ||
171 | #endif | ||
172 | |||
173 | /* FCC2 Clock Source Configuration. There are board specific. | ||
174 | Can only choose from CLK13-16 */ | ||
175 | #define F2_RXCLK 13 | ||
176 | #define F2_TXCLK 14 | ||
177 | |||
178 | /* FCC3 Clock Source Configuration. There are board specific. | ||
179 | Can only choose from CLK13-16 */ | ||
180 | #define F3_RXCLK 15 | ||
181 | #define F3_TXCLK 16 | ||
182 | |||
183 | /* Automatically generates register configurations */ | ||
184 | #define PC_CLK(x) ((uint)(1<<(x-1))) /* FCC CLK I/O ports */ | ||
185 | |||
186 | #define CMXFCR_RF1CS(x) ((uint)((x-5)<<27)) /* FCC1 Receive Clock Source */ | ||
187 | #define CMXFCR_TF1CS(x) ((uint)((x-5)<<24)) /* FCC1 Transmit Clock Source */ | ||
188 | #define CMXFCR_RF2CS(x) ((uint)((x-9)<<19)) /* FCC2 Receive Clock Source */ | ||
189 | #define CMXFCR_TF2CS(x) ((uint)((x-9)<<16)) /* FCC2 Transmit Clock Source */ | ||
190 | #define CMXFCR_RF3CS(x) ((uint)((x-9)<<11)) /* FCC3 Receive Clock Source */ | ||
191 | #define CMXFCR_TF3CS(x) ((uint)((x-9)<<8)) /* FCC3 Transmit Clock Source */ | ||
192 | |||
193 | #define PC_F1RXCLK PC_CLK(F1_RXCLK) | ||
194 | #define PC_F1TXCLK PC_CLK(F1_TXCLK) | ||
195 | #define CMX1_CLK_ROUTE (CMXFCR_RF1CS(F1_RXCLK) | CMXFCR_TF1CS(F1_TXCLK)) | ||
196 | #define CMX1_CLK_MASK ((uint)0xff000000) | ||
197 | |||
198 | #define PC_F2RXCLK PC_CLK(F2_RXCLK) | ||
199 | #define PC_F2TXCLK PC_CLK(F2_TXCLK) | ||
200 | #define CMX2_CLK_ROUTE (CMXFCR_RF2CS(F2_RXCLK) | CMXFCR_TF2CS(F2_TXCLK)) | ||
201 | #define CMX2_CLK_MASK ((uint)0x00ff0000) | ||
202 | |||
203 | #define PC_F3RXCLK PC_CLK(F3_RXCLK) | ||
204 | #define PC_F3TXCLK PC_CLK(F3_TXCLK) | ||
205 | #define CMX3_CLK_ROUTE (CMXFCR_RF3CS(F3_RXCLK) | CMXFCR_TF3CS(F3_TXCLK)) | ||
206 | #define CMX3_CLK_MASK ((uint)0x0000ff00) | ||
207 | |||
208 | |||
209 | /* I/O Pin assignment for FCC1. I don't yet know the best way to do this, | ||
210 | * but there is little variation among the choices. | ||
211 | */ | ||
212 | #define PA1_COL ((uint)0x00000001) | ||
213 | #define PA1_CRS ((uint)0x00000002) | ||
214 | #define PA1_TXER ((uint)0x00000004) | ||
215 | #define PA1_TXEN ((uint)0x00000008) | ||
216 | #define PA1_RXDV ((uint)0x00000010) | ||
217 | #define PA1_RXER ((uint)0x00000020) | ||
218 | #define PA1_TXDAT ((uint)0x00003c00) | ||
219 | #define PA1_RXDAT ((uint)0x0003c000) | ||
220 | #define PA1_PSORA_BOUT (PA1_RXDAT | PA1_TXDAT) | ||
221 | #define PA1_PSORA_BIN (PA1_COL | PA1_CRS | PA1_TXER | PA1_TXEN | \ | ||
222 | PA1_RXDV | PA1_RXER) | ||
223 | #define PA1_DIRA_BOUT (PA1_RXDAT | PA1_CRS | PA1_COL | PA1_RXER | PA1_RXDV) | ||
224 | #define PA1_DIRA_BIN (PA1_TXDAT | PA1_TXEN | PA1_TXER) | ||
225 | |||
226 | |||
227 | /* I/O Pin assignment for FCC2. I don't yet know the best way to do this, | ||
228 | * but there is little variation among the choices. | ||
229 | */ | ||
230 | #define PB2_TXER ((uint)0x00000001) | ||
231 | #define PB2_RXDV ((uint)0x00000002) | ||
232 | #define PB2_TXEN ((uint)0x00000004) | ||
233 | #define PB2_RXER ((uint)0x00000008) | ||
234 | #define PB2_COL ((uint)0x00000010) | ||
235 | #define PB2_CRS ((uint)0x00000020) | ||
236 | #define PB2_TXDAT ((uint)0x000003c0) | ||
237 | #define PB2_RXDAT ((uint)0x00003c00) | ||
238 | #define PB2_PSORB_BOUT (PB2_RXDAT | PB2_TXDAT | PB2_CRS | PB2_COL | \ | ||
239 | PB2_RXER | PB2_RXDV | PB2_TXER) | ||
240 | #define PB2_PSORB_BIN (PB2_TXEN) | ||
241 | #define PB2_DIRB_BOUT (PB2_RXDAT | PB2_CRS | PB2_COL | PB2_RXER | PB2_RXDV) | ||
242 | #define PB2_DIRB_BIN (PB2_TXDAT | PB2_TXEN | PB2_TXER) | ||
243 | |||
244 | |||
245 | /* I/O Pin assignment for FCC3. I don't yet know the best way to do this, | ||
246 | * but there is little variation among the choices. | ||
247 | */ | ||
248 | #define PB3_RXDV ((uint)0x00004000) | ||
249 | #define PB3_RXER ((uint)0x00008000) | ||
250 | #define PB3_TXER ((uint)0x00010000) | ||
251 | #define PB3_TXEN ((uint)0x00020000) | ||
252 | #define PB3_COL ((uint)0x00040000) | ||
253 | #define PB3_CRS ((uint)0x00080000) | ||
254 | #ifndef CONFIG_RPX8260 | ||
255 | #define PB3_TXDAT ((uint)0x0f000000) | ||
256 | #define PC3_TXDAT ((uint)0x00000000) | ||
257 | #else | ||
258 | #define PB3_TXDAT ((uint)0x0f000000) | ||
259 | #define PC3_TXDAT 0 | ||
260 | #endif | ||
261 | #define PB3_RXDAT ((uint)0x00f00000) | ||
262 | #define PB3_PSORB_BOUT (PB3_RXDAT | PB3_TXDAT | PB3_CRS | PB3_COL | \ | ||
263 | PB3_RXER | PB3_RXDV | PB3_TXER | PB3_TXEN) | ||
264 | #define PB3_PSORB_BIN (0) | ||
265 | #define PB3_DIRB_BOUT (PB3_RXDAT | PB3_CRS | PB3_COL | PB3_RXER | PB3_RXDV) | ||
266 | #define PB3_DIRB_BIN (PB3_TXDAT | PB3_TXEN | PB3_TXER) | ||
267 | |||
268 | #define PC3_PSORC_BOUT (PC3_TXDAT) | ||
269 | #define PC3_PSORC_BIN (0) | ||
270 | #define PC3_DIRC_BOUT (0) | ||
271 | #define PC3_DIRC_BIN (PC3_TXDAT) | ||
272 | |||
273 | |||
274 | /* MII status/control serial interface. | ||
275 | */ | ||
276 | #if defined(CONFIG_RPX8260) | ||
277 | /* The EP8260 doesn't use Port C for MDIO */ | ||
278 | #define PC_MDIO ((uint)0x00000000) | ||
279 | #define PC_MDCK ((uint)0x00000000) | ||
280 | #elif defined(CONFIG_TQM8260) | ||
281 | /* TQM8260 has MDIO and MDCK on PC30 and PC31 respectively */ | ||
282 | #define PC_MDIO ((uint)0x00000002) | ||
283 | #define PC_MDCK ((uint)0x00000001) | ||
284 | #elif defined(CONFIG_EST8260) || defined(CONFIG_ADS8260) | ||
285 | #define PC_MDIO ((uint)0x00400000) | ||
286 | #define PC_MDCK ((uint)0x00200000) | ||
287 | #else | ||
288 | #define PC_MDIO ((uint)0x00000004) | ||
289 | #define PC_MDCK ((uint)0x00000020) | ||
290 | #endif | ||
291 | |||
292 | #if defined(CONFIG_USE_MDIO) && (!defined(PC_MDIO) || !defined(PC_MDCK)) | ||
293 | #error "Must define PC_MDIO and PC_MDCK if using MDIO" | ||
294 | #endif | ||
295 | |||
296 | /* PHY addresses */ | ||
297 | /* default to dynamic config of phy addresses */ | ||
298 | #define FCC1_PHY_ADDR 0 | ||
299 | #ifdef CONFIG_PQ2FADS | ||
300 | #define FCC2_PHY_ADDR 0 | ||
301 | #else | ||
302 | #define FCC2_PHY_ADDR 2 | ||
303 | #endif | ||
304 | #define FCC3_PHY_ADDR 3 | ||
305 | |||
306 | /* A table of information for supporting FCCs. This does two things. | ||
307 | * First, we know how many FCCs we have and they are always externally | ||
308 | * numbered from zero. Second, it holds control register and I/O | ||
309 | * information that could be different among board designs. | ||
310 | */ | ||
311 | typedef struct fcc_info { | ||
312 | uint fc_fccnum; | ||
313 | uint fc_phyaddr; | ||
314 | uint fc_cpmblock; | ||
315 | uint fc_cpmpage; | ||
316 | uint fc_proff; | ||
317 | uint fc_interrupt; | ||
318 | uint fc_trxclocks; | ||
319 | uint fc_clockroute; | ||
320 | uint fc_clockmask; | ||
321 | uint fc_mdio; | ||
322 | uint fc_mdck; | ||
323 | } fcc_info_t; | ||
324 | |||
325 | static fcc_info_t fcc_ports[] = { | ||
326 | #ifdef CONFIG_FCC1_ENET | ||
327 | { 0, FCC1_PHY_ADDR, CPM_CR_FCC1_SBLOCK, CPM_CR_FCC1_PAGE, PROFF_FCC1, SIU_INT_FCC1, | ||
328 | (PC_F1RXCLK | PC_F1TXCLK), CMX1_CLK_ROUTE, CMX1_CLK_MASK, | ||
329 | PC_MDIO, PC_MDCK }, | ||
330 | #endif | ||
331 | #ifdef CONFIG_FCC2_ENET | ||
332 | { 1, FCC2_PHY_ADDR, CPM_CR_FCC2_SBLOCK, CPM_CR_FCC2_PAGE, PROFF_FCC2, SIU_INT_FCC2, | ||
333 | (PC_F2RXCLK | PC_F2TXCLK), CMX2_CLK_ROUTE, CMX2_CLK_MASK, | ||
334 | PC_MDIO, PC_MDCK }, | ||
335 | #endif | ||
336 | #ifdef CONFIG_FCC3_ENET | ||
337 | { 2, FCC3_PHY_ADDR, CPM_CR_FCC3_SBLOCK, CPM_CR_FCC3_PAGE, PROFF_FCC3, SIU_INT_FCC3, | ||
338 | (PC_F3RXCLK | PC_F3TXCLK), CMX3_CLK_ROUTE, CMX3_CLK_MASK, | ||
339 | PC_MDIO, PC_MDCK }, | ||
340 | #endif | ||
341 | }; | ||
342 | |||
343 | /* The FCC buffer descriptors track the ring buffers. The rx_bd_base and | ||
344 | * tx_bd_base always point to the base of the buffer descriptors. The | ||
345 | * cur_rx and cur_tx point to the currently available buffer. | ||
346 | * The dirty_tx tracks the current buffer that is being sent by the | ||
347 | * controller. The cur_tx and dirty_tx are equal under both completely | ||
348 | * empty and completely full conditions. The empty/ready indicator in | ||
349 | * the buffer descriptor determines the actual condition. | ||
350 | */ | ||
351 | struct fcc_enet_private { | ||
352 | /* The saved address of a sent-in-place packet/buffer, for skfree(). */ | ||
353 | struct sk_buff* tx_skbuff[TX_RING_SIZE]; | ||
354 | ushort skb_cur; | ||
355 | ushort skb_dirty; | ||
356 | |||
357 | /* CPM dual port RAM relative addresses. | ||
358 | */ | ||
359 | cbd_t *rx_bd_base; /* Address of Rx and Tx buffers. */ | ||
360 | cbd_t *tx_bd_base; | ||
361 | cbd_t *cur_rx, *cur_tx; /* The next free ring entry */ | ||
362 | cbd_t *dirty_tx; /* The ring entries to be free()ed. */ | ||
363 | volatile fcc_t *fccp; | ||
364 | volatile fcc_enet_t *ep; | ||
365 | struct net_device_stats stats; | ||
366 | uint tx_free; | ||
367 | spinlock_t lock; | ||
368 | |||
369 | #ifdef CONFIG_USE_MDIO | ||
370 | uint phy_id; | ||
371 | uint phy_id_done; | ||
372 | uint phy_status; | ||
373 | phy_info_t *phy; | ||
374 | struct work_struct phy_relink; | ||
375 | struct work_struct phy_display_config; | ||
376 | struct net_device *dev; | ||
377 | |||
378 | uint sequence_done; | ||
379 | |||
380 | uint phy_addr; | ||
381 | #endif /* CONFIG_USE_MDIO */ | ||
382 | |||
383 | int link; | ||
384 | int old_link; | ||
385 | int full_duplex; | ||
386 | |||
387 | fcc_info_t *fip; | ||
388 | }; | ||
389 | |||
390 | static void init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep, | ||
391 | volatile cpm2_map_t *immap); | ||
392 | static void init_fcc_startup(fcc_info_t *fip, struct net_device *dev); | ||
393 | static void init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io, | ||
394 | volatile cpm2_map_t *immap); | ||
395 | static void init_fcc_param(fcc_info_t *fip, struct net_device *dev, | ||
396 | volatile cpm2_map_t *immap); | ||
397 | |||
398 | #ifdef CONFIG_USE_MDIO | ||
399 | static int mii_queue(struct net_device *dev, int request, void (*func)(uint, struct net_device *)); | ||
400 | static uint mii_send_receive(fcc_info_t *fip, uint cmd); | ||
401 | static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c); | ||
402 | |||
403 | /* Make MII read/write commands for the FCC. | ||
404 | */ | ||
405 | #define mk_mii_read(REG) (0x60020000 | (((REG) & 0x1f) << 18)) | ||
406 | #define mk_mii_write(REG, VAL) (0x50020000 | (((REG) & 0x1f) << 18) | \ | ||
407 | ((VAL) & 0xffff)) | ||
408 | #define mk_mii_end 0 | ||
409 | #endif /* CONFIG_USE_MDIO */ | ||
410 | |||
411 | |||
412 | static int | ||
413 | fcc_enet_start_xmit(struct sk_buff *skb, struct net_device *dev) | ||
414 | { | ||
415 | struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv; | ||
416 | volatile cbd_t *bdp; | ||
417 | |||
418 | /* Fill in a Tx ring entry */ | ||
419 | bdp = cep->cur_tx; | ||
420 | |||
421 | #ifndef final_version | ||
422 | if (!cep->tx_free || (bdp->cbd_sc & BD_ENET_TX_READY)) { | ||
423 | /* Ooops. All transmit buffers are full. Bail out. | ||
424 | * This should not happen, since the tx queue should be stopped. | ||
425 | */ | ||
426 | printk("%s: tx queue full!.\n", dev->name); | ||
427 | return 1; | ||
428 | } | ||
429 | #endif | ||
430 | |||
431 | /* Clear all of the status flags. */ | ||
432 | bdp->cbd_sc &= ~BD_ENET_TX_STATS; | ||
433 | |||
434 | /* If the frame is short, tell CPM to pad it. */ | ||
435 | if (skb->len <= ETH_ZLEN) | ||
436 | bdp->cbd_sc |= BD_ENET_TX_PAD; | ||
437 | else | ||
438 | bdp->cbd_sc &= ~BD_ENET_TX_PAD; | ||
439 | |||
440 | /* Set buffer length and buffer pointer. */ | ||
441 | bdp->cbd_datlen = skb->len; | ||
442 | bdp->cbd_bufaddr = __pa(skb->data); | ||
443 | |||
444 | spin_lock_irq(&cep->lock); | ||
445 | |||
446 | /* Save skb pointer. */ | ||
447 | cep->tx_skbuff[cep->skb_cur] = skb; | ||
448 | |||
449 | cep->stats.tx_bytes += skb->len; | ||
450 | cep->skb_cur = (cep->skb_cur+1) & TX_RING_MOD_MASK; | ||
451 | |||
452 | /* Send it on its way. Tell CPM its ready, interrupt when done, | ||
453 | * its the last BD of the frame, and to put the CRC on the end. | ||
454 | */ | ||
455 | bdp->cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | BD_ENET_TX_LAST | BD_ENET_TX_TC); | ||
456 | |||
457 | #if 0 | ||
458 | /* Errata says don't do this. */ | ||
459 | cep->fccp->fcc_ftodr = 0x8000; | ||
460 | #endif | ||
461 | dev->trans_start = jiffies; | ||
462 | |||
463 | /* If this was the last BD in the ring, start at the beginning again. */ | ||
464 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) | ||
465 | bdp = cep->tx_bd_base; | ||
466 | else | ||
467 | bdp++; | ||
468 | |||
469 | if (!--cep->tx_free) | ||
470 | netif_stop_queue(dev); | ||
471 | |||
472 | cep->cur_tx = (cbd_t *)bdp; | ||
473 | |||
474 | spin_unlock_irq(&cep->lock); | ||
475 | |||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | |||
480 | static void | ||
481 | fcc_enet_timeout(struct net_device *dev) | ||
482 | { | ||
483 | struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv; | ||
484 | |||
485 | printk("%s: transmit timed out.\n", dev->name); | ||
486 | cep->stats.tx_errors++; | ||
487 | #ifndef final_version | ||
488 | { | ||
489 | int i; | ||
490 | cbd_t *bdp; | ||
491 | printk(" Ring data dump: cur_tx %p tx_free %d cur_rx %p.\n", | ||
492 | cep->cur_tx, cep->tx_free, | ||
493 | cep->cur_rx); | ||
494 | bdp = cep->tx_bd_base; | ||
495 | printk(" Tx @base %p :\n", bdp); | ||
496 | for (i = 0 ; i < TX_RING_SIZE; i++, bdp++) | ||
497 | printk("%04x %04x %08x\n", | ||
498 | bdp->cbd_sc, | ||
499 | bdp->cbd_datlen, | ||
500 | bdp->cbd_bufaddr); | ||
501 | bdp = cep->rx_bd_base; | ||
502 | printk(" Rx @base %p :\n", bdp); | ||
503 | for (i = 0 ; i < RX_RING_SIZE; i++, bdp++) | ||
504 | printk("%04x %04x %08x\n", | ||
505 | bdp->cbd_sc, | ||
506 | bdp->cbd_datlen, | ||
507 | bdp->cbd_bufaddr); | ||
508 | } | ||
509 | #endif | ||
510 | if (cep->tx_free) | ||
511 | netif_wake_queue(dev); | ||
512 | } | ||
513 | |||
514 | /* The interrupt handler. */ | ||
515 | static irqreturn_t | ||
516 | fcc_enet_interrupt(int irq, void *dev_id) | ||
517 | { | ||
518 | struct net_device *dev = dev_id; | ||
519 | volatile struct fcc_enet_private *cep; | ||
520 | volatile cbd_t *bdp; | ||
521 | ushort int_events; | ||
522 | int must_restart; | ||
523 | |||
524 | cep = dev->priv; | ||
525 | |||
526 | /* Get the interrupt events that caused us to be here. | ||
527 | */ | ||
528 | int_events = cep->fccp->fcc_fcce; | ||
529 | cep->fccp->fcc_fcce = (int_events & cep->fccp->fcc_fccm); | ||
530 | must_restart = 0; | ||
531 | |||
532 | #ifdef PHY_INTERRUPT | ||
533 | /* We have to be careful here to make sure that we aren't | ||
534 | * interrupted by a PHY interrupt. | ||
535 | */ | ||
536 | disable_irq_nosync(PHY_INTERRUPT); | ||
537 | #endif | ||
538 | |||
539 | /* Handle receive event in its own function. | ||
540 | */ | ||
541 | if (int_events & FCC_ENET_RXF) | ||
542 | fcc_enet_rx(dev_id); | ||
543 | |||
544 | /* Check for a transmit error. The manual is a little unclear | ||
545 | * about this, so the debug code until I get it figured out. It | ||
546 | * appears that if TXE is set, then TXB is not set. However, | ||
547 | * if carrier sense is lost during frame transmission, the TXE | ||
548 | * bit is set, "and continues the buffer transmission normally." | ||
549 | * I don't know if "normally" implies TXB is set when the buffer | ||
550 | * descriptor is closed.....trial and error :-). | ||
551 | */ | ||
552 | |||
553 | /* Transmit OK, or non-fatal error. Update the buffer descriptors. | ||
554 | */ | ||
555 | if (int_events & (FCC_ENET_TXE | FCC_ENET_TXB)) { | ||
556 | spin_lock(&cep->lock); | ||
557 | bdp = cep->dirty_tx; | ||
558 | while ((bdp->cbd_sc&BD_ENET_TX_READY)==0) { | ||
559 | if (cep->tx_free == TX_RING_SIZE) | ||
560 | break; | ||
561 | |||
562 | if (bdp->cbd_sc & BD_ENET_TX_HB) /* No heartbeat */ | ||
563 | cep->stats.tx_heartbeat_errors++; | ||
564 | if (bdp->cbd_sc & BD_ENET_TX_LC) /* Late collision */ | ||
565 | cep->stats.tx_window_errors++; | ||
566 | if (bdp->cbd_sc & BD_ENET_TX_RL) /* Retrans limit */ | ||
567 | cep->stats.tx_aborted_errors++; | ||
568 | if (bdp->cbd_sc & BD_ENET_TX_UN) /* Underrun */ | ||
569 | cep->stats.tx_fifo_errors++; | ||
570 | if (bdp->cbd_sc & BD_ENET_TX_CSL) /* Carrier lost */ | ||
571 | cep->stats.tx_carrier_errors++; | ||
572 | |||
573 | |||
574 | /* No heartbeat or Lost carrier are not really bad errors. | ||
575 | * The others require a restart transmit command. | ||
576 | */ | ||
577 | if (bdp->cbd_sc & | ||
578 | (BD_ENET_TX_LC | BD_ENET_TX_RL | BD_ENET_TX_UN)) { | ||
579 | must_restart = 1; | ||
580 | cep->stats.tx_errors++; | ||
581 | } | ||
582 | |||
583 | cep->stats.tx_packets++; | ||
584 | |||
585 | /* Deferred means some collisions occurred during transmit, | ||
586 | * but we eventually sent the packet OK. | ||
587 | */ | ||
588 | if (bdp->cbd_sc & BD_ENET_TX_DEF) | ||
589 | cep->stats.collisions++; | ||
590 | |||
591 | /* Free the sk buffer associated with this last transmit. */ | ||
592 | dev_kfree_skb_irq(cep->tx_skbuff[cep->skb_dirty]); | ||
593 | cep->tx_skbuff[cep->skb_dirty] = NULL; | ||
594 | cep->skb_dirty = (cep->skb_dirty + 1) & TX_RING_MOD_MASK; | ||
595 | |||
596 | /* Update pointer to next buffer descriptor to be transmitted. */ | ||
597 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) | ||
598 | bdp = cep->tx_bd_base; | ||
599 | else | ||
600 | bdp++; | ||
601 | |||
602 | /* I don't know if we can be held off from processing these | ||
603 | * interrupts for more than one frame time. I really hope | ||
604 | * not. In such a case, we would now want to check the | ||
605 | * currently available BD (cur_tx) and determine if any | ||
606 | * buffers between the dirty_tx and cur_tx have also been | ||
607 | * sent. We would want to process anything in between that | ||
608 | * does not have BD_ENET_TX_READY set. | ||
609 | */ | ||
610 | |||
611 | /* Since we have freed up a buffer, the ring is no longer | ||
612 | * full. | ||
613 | */ | ||
614 | if (!cep->tx_free++) { | ||
615 | if (netif_queue_stopped(dev)) { | ||
616 | netif_wake_queue(dev); | ||
617 | } | ||
618 | } | ||
619 | |||
620 | cep->dirty_tx = (cbd_t *)bdp; | ||
621 | } | ||
622 | |||
623 | if (must_restart) { | ||
624 | volatile cpm_cpm2_t *cp; | ||
625 | |||
626 | /* Some transmit errors cause the transmitter to shut | ||
627 | * down. We now issue a restart transmit. Since the | ||
628 | * errors close the BD and update the pointers, the restart | ||
629 | * _should_ pick up without having to reset any of our | ||
630 | * pointers either. Also, To workaround 8260 device erratum | ||
631 | * CPM37, we must disable and then re-enable the transmitter | ||
632 | * following a Late Collision, Underrun, or Retry Limit error. | ||
633 | */ | ||
634 | cep->fccp->fcc_gfmr &= ~FCC_GFMR_ENT; | ||
635 | udelay(10); /* wait a few microseconds just on principle */ | ||
636 | cep->fccp->fcc_gfmr |= FCC_GFMR_ENT; | ||
637 | |||
638 | cp = cpmp; | ||
639 | cp->cp_cpcr = | ||
640 | mk_cr_cmd(cep->fip->fc_cpmpage, cep->fip->fc_cpmblock, | ||
641 | 0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG; | ||
642 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
643 | } | ||
644 | spin_unlock(&cep->lock); | ||
645 | } | ||
646 | |||
647 | /* Check for receive busy, i.e. packets coming but no place to | ||
648 | * put them. | ||
649 | */ | ||
650 | if (int_events & FCC_ENET_BSY) { | ||
651 | cep->fccp->fcc_fcce = FCC_ENET_BSY; | ||
652 | cep->stats.rx_dropped++; | ||
653 | } | ||
654 | |||
655 | #ifdef PHY_INTERRUPT | ||
656 | enable_irq(PHY_INTERRUPT); | ||
657 | #endif | ||
658 | return IRQ_HANDLED; | ||
659 | } | ||
660 | |||
661 | /* During a receive, the cur_rx points to the current incoming buffer. | ||
662 | * When we update through the ring, if the next incoming buffer has | ||
663 | * not been given to the system, we just set the empty indicator, | ||
664 | * effectively tossing the packet. | ||
665 | */ | ||
666 | static int | ||
667 | fcc_enet_rx(struct net_device *dev) | ||
668 | { | ||
669 | struct fcc_enet_private *cep; | ||
670 | volatile cbd_t *bdp; | ||
671 | struct sk_buff *skb; | ||
672 | ushort pkt_len; | ||
673 | |||
674 | cep = dev->priv; | ||
675 | |||
676 | /* First, grab all of the stats for the incoming packet. | ||
677 | * These get messed up if we get called due to a busy condition. | ||
678 | */ | ||
679 | bdp = cep->cur_rx; | ||
680 | |||
681 | for (;;) { | ||
682 | if (bdp->cbd_sc & BD_ENET_RX_EMPTY) | ||
683 | break; | ||
684 | |||
685 | #ifndef final_version | ||
686 | /* Since we have allocated space to hold a complete frame, both | ||
687 | * the first and last indicators should be set. | ||
688 | */ | ||
689 | if ((bdp->cbd_sc & (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) != | ||
690 | (BD_ENET_RX_FIRST | BD_ENET_RX_LAST)) | ||
691 | printk("CPM ENET: rcv is not first+last\n"); | ||
692 | #endif | ||
693 | |||
694 | /* Frame too long or too short. */ | ||
695 | if (bdp->cbd_sc & (BD_ENET_RX_LG | BD_ENET_RX_SH)) | ||
696 | cep->stats.rx_length_errors++; | ||
697 | if (bdp->cbd_sc & BD_ENET_RX_NO) /* Frame alignment */ | ||
698 | cep->stats.rx_frame_errors++; | ||
699 | if (bdp->cbd_sc & BD_ENET_RX_CR) /* CRC Error */ | ||
700 | cep->stats.rx_crc_errors++; | ||
701 | if (bdp->cbd_sc & BD_ENET_RX_OV) /* FIFO overrun */ | ||
702 | cep->stats.rx_crc_errors++; | ||
703 | if (bdp->cbd_sc & BD_ENET_RX_CL) /* Late Collision */ | ||
704 | cep->stats.rx_frame_errors++; | ||
705 | |||
706 | if (!(bdp->cbd_sc & | ||
707 | (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO | BD_ENET_RX_CR | ||
708 | | BD_ENET_RX_OV | BD_ENET_RX_CL))) | ||
709 | { | ||
710 | /* Process the incoming frame. */ | ||
711 | cep->stats.rx_packets++; | ||
712 | |||
713 | /* Remove the FCS from the packet length. */ | ||
714 | pkt_len = bdp->cbd_datlen - 4; | ||
715 | cep->stats.rx_bytes += pkt_len; | ||
716 | |||
717 | /* This does 16 byte alignment, much more than we need. */ | ||
718 | skb = dev_alloc_skb(pkt_len); | ||
719 | |||
720 | if (skb == NULL) { | ||
721 | printk("%s: Memory squeeze, dropping packet.\n", dev->name); | ||
722 | cep->stats.rx_dropped++; | ||
723 | } | ||
724 | else { | ||
725 | skb_put(skb,pkt_len); /* Make room */ | ||
726 | skb_copy_to_linear_data(skb, | ||
727 | (unsigned char *)__va(bdp->cbd_bufaddr), | ||
728 | pkt_len); | ||
729 | skb->protocol=eth_type_trans(skb,dev); | ||
730 | netif_rx(skb); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | /* Clear the status flags for this buffer. */ | ||
735 | bdp->cbd_sc &= ~BD_ENET_RX_STATS; | ||
736 | |||
737 | /* Mark the buffer empty. */ | ||
738 | bdp->cbd_sc |= BD_ENET_RX_EMPTY; | ||
739 | |||
740 | /* Update BD pointer to next entry. */ | ||
741 | if (bdp->cbd_sc & BD_ENET_RX_WRAP) | ||
742 | bdp = cep->rx_bd_base; | ||
743 | else | ||
744 | bdp++; | ||
745 | |||
746 | } | ||
747 | cep->cur_rx = (cbd_t *)bdp; | ||
748 | |||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | static int | ||
753 | fcc_enet_close(struct net_device *dev) | ||
754 | { | ||
755 | #ifdef CONFIG_USE_MDIO | ||
756 | struct fcc_enet_private *fep = dev->priv; | ||
757 | #endif | ||
758 | |||
759 | netif_stop_queue(dev); | ||
760 | fcc_stop(dev); | ||
761 | #ifdef CONFIG_USE_MDIO | ||
762 | if (fep->phy) | ||
763 | mii_do_cmd(dev, fep->phy->shutdown); | ||
764 | #endif | ||
765 | |||
766 | return 0; | ||
767 | } | ||
768 | |||
769 | static struct net_device_stats *fcc_enet_get_stats(struct net_device *dev) | ||
770 | { | ||
771 | struct fcc_enet_private *cep = (struct fcc_enet_private *)dev->priv; | ||
772 | |||
773 | return &cep->stats; | ||
774 | } | ||
775 | |||
776 | #ifdef CONFIG_USE_MDIO | ||
777 | |||
778 | /* NOTE: Most of the following comes from the FEC driver for 860. The | ||
779 | * overall structure of MII code has been retained (as it's proved stable | ||
780 | * and well-tested), but actual transfer requests are processed "at once" | ||
781 | * instead of being queued (there's no interrupt-driven MII transfer | ||
782 | * mechanism, one has to toggle the data/clock bits manually). | ||
783 | */ | ||
784 | static int | ||
785 | mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *)) | ||
786 | { | ||
787 | struct fcc_enet_private *fep; | ||
788 | int retval, tmp; | ||
789 | |||
790 | /* Add PHY address to register command. */ | ||
791 | fep = dev->priv; | ||
792 | regval |= fep->phy_addr << 23; | ||
793 | |||
794 | retval = 0; | ||
795 | |||
796 | tmp = mii_send_receive(fep->fip, regval); | ||
797 | if (func) | ||
798 | func(tmp, dev); | ||
799 | |||
800 | return retval; | ||
801 | } | ||
802 | |||
803 | static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c) | ||
804 | { | ||
805 | int k; | ||
806 | |||
807 | if(!c) | ||
808 | return; | ||
809 | |||
810 | for(k = 0; (c+k)->mii_data != mk_mii_end; k++) | ||
811 | mii_queue(dev, (c+k)->mii_data, (c+k)->funct); | ||
812 | } | ||
813 | |||
814 | static void mii_parse_sr(uint mii_reg, struct net_device *dev) | ||
815 | { | ||
816 | volatile struct fcc_enet_private *fep = dev->priv; | ||
817 | uint s = fep->phy_status; | ||
818 | |||
819 | s &= ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC); | ||
820 | |||
821 | if (mii_reg & BMSR_LSTATUS) | ||
822 | s |= PHY_STAT_LINK; | ||
823 | if (mii_reg & BMSR_RFAULT) | ||
824 | s |= PHY_STAT_FAULT; | ||
825 | if (mii_reg & BMSR_ANEGCOMPLETE) | ||
826 | s |= PHY_STAT_ANC; | ||
827 | |||
828 | fep->phy_status = s; | ||
829 | } | ||
830 | |||
831 | static void mii_parse_cr(uint mii_reg, struct net_device *dev) | ||
832 | { | ||
833 | volatile struct fcc_enet_private *fep = dev->priv; | ||
834 | uint s = fep->phy_status; | ||
835 | |||
836 | s &= ~(PHY_CONF_ANE | PHY_CONF_LOOP); | ||
837 | |||
838 | if (mii_reg & BMCR_ANENABLE) | ||
839 | s |= PHY_CONF_ANE; | ||
840 | if (mii_reg & BMCR_LOOPBACK) | ||
841 | s |= PHY_CONF_LOOP; | ||
842 | |||
843 | fep->phy_status = s; | ||
844 | } | ||
845 | |||
846 | static void mii_parse_anar(uint mii_reg, struct net_device *dev) | ||
847 | { | ||
848 | volatile struct fcc_enet_private *fep = dev->priv; | ||
849 | uint s = fep->phy_status; | ||
850 | |||
851 | s &= ~(PHY_CONF_SPMASK); | ||
852 | |||
853 | if (mii_reg & ADVERTISE_10HALF) | ||
854 | s |= PHY_CONF_10HDX; | ||
855 | if (mii_reg & ADVERTISE_10FULL) | ||
856 | s |= PHY_CONF_10FDX; | ||
857 | if (mii_reg & ADVERTISE_100HALF) | ||
858 | s |= PHY_CONF_100HDX; | ||
859 | if (mii_reg & ADVERTISE_100FULL) | ||
860 | s |= PHY_CONF_100FDX; | ||
861 | |||
862 | fep->phy_status = s; | ||
863 | } | ||
864 | |||
865 | /* ------------------------------------------------------------------------- */ | ||
866 | /* Generic PHY support. Should work for all PHYs, but does not support link | ||
867 | * change interrupts. | ||
868 | */ | ||
869 | #ifdef CONFIG_FCC_GENERIC_PHY | ||
870 | |||
871 | static phy_info_t phy_info_generic = { | ||
872 | 0x00000000, /* 0-->match any PHY */ | ||
873 | "GENERIC", | ||
874 | |||
875 | (const phy_cmd_t []) { /* config */ | ||
876 | /* advertise only half-duplex capabilities */ | ||
877 | { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_HALF), | ||
878 | mii_parse_anar }, | ||
879 | |||
880 | /* enable auto-negotiation */ | ||
881 | { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr }, | ||
882 | { mk_mii_end, } | ||
883 | }, | ||
884 | (const phy_cmd_t []) { /* startup */ | ||
885 | /* restart auto-negotiation */ | ||
886 | { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART), | ||
887 | NULL }, | ||
888 | { mk_mii_end, } | ||
889 | }, | ||
890 | (const phy_cmd_t []) { /* ack_int */ | ||
891 | /* We don't actually use the ack_int table with a generic | ||
892 | * PHY, but putting a reference to mii_parse_sr here keeps | ||
893 | * us from getting a compiler warning about unused static | ||
894 | * functions in the case where we only compile in generic | ||
895 | * PHY support. | ||
896 | */ | ||
897 | { mk_mii_read(MII_BMSR), mii_parse_sr }, | ||
898 | { mk_mii_end, } | ||
899 | }, | ||
900 | (const phy_cmd_t []) { /* shutdown */ | ||
901 | { mk_mii_end, } | ||
902 | }, | ||
903 | }; | ||
904 | #endif /* ifdef CONFIG_FCC_GENERIC_PHY */ | ||
905 | |||
906 | /* ------------------------------------------------------------------------- */ | ||
907 | /* The Level one LXT970 is used by many boards */ | ||
908 | |||
909 | #ifdef CONFIG_FCC_LXT970 | ||
910 | |||
911 | #define MII_LXT970_MIRROR 16 /* Mirror register */ | ||
912 | #define MII_LXT970_IER 17 /* Interrupt Enable Register */ | ||
913 | #define MII_LXT970_ISR 18 /* Interrupt Status Register */ | ||
914 | #define MII_LXT970_CONFIG 19 /* Configuration Register */ | ||
915 | #define MII_LXT970_CSR 20 /* Chip Status Register */ | ||
916 | |||
917 | static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev) | ||
918 | { | ||
919 | volatile struct fcc_enet_private *fep = dev->priv; | ||
920 | uint s = fep->phy_status; | ||
921 | |||
922 | s &= ~(PHY_STAT_SPMASK); | ||
923 | |||
924 | if (mii_reg & 0x0800) { | ||
925 | if (mii_reg & 0x1000) | ||
926 | s |= PHY_STAT_100FDX; | ||
927 | else | ||
928 | s |= PHY_STAT_100HDX; | ||
929 | } else { | ||
930 | if (mii_reg & 0x1000) | ||
931 | s |= PHY_STAT_10FDX; | ||
932 | else | ||
933 | s |= PHY_STAT_10HDX; | ||
934 | } | ||
935 | |||
936 | fep->phy_status = s; | ||
937 | } | ||
938 | |||
939 | static phy_info_t phy_info_lxt970 = { | ||
940 | 0x07810000, | ||
941 | "LXT970", | ||
942 | |||
943 | (const phy_cmd_t []) { /* config */ | ||
944 | #if 0 | ||
945 | // { mk_mii_write(MII_ADVERTISE, 0x0021), NULL }, | ||
946 | |||
947 | /* Set default operation of 100-TX....for some reason | ||
948 | * some of these bits are set on power up, which is wrong. | ||
949 | */ | ||
950 | { mk_mii_write(MII_LXT970_CONFIG, 0), NULL }, | ||
951 | #endif | ||
952 | { mk_mii_read(MII_BMCR), mii_parse_cr }, | ||
953 | { mk_mii_read(MII_ADVERTISE), mii_parse_anar }, | ||
954 | { mk_mii_end, } | ||
955 | }, | ||
956 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
957 | { mk_mii_write(MII_LXT970_IER, 0x0002), NULL }, | ||
958 | { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */ | ||
959 | { mk_mii_end, } | ||
960 | }, | ||
961 | (const phy_cmd_t []) { /* ack_int */ | ||
962 | /* read SR and ISR to acknowledge */ | ||
963 | |||
964 | { mk_mii_read(MII_BMSR), mii_parse_sr }, | ||
965 | { mk_mii_read(MII_LXT970_ISR), NULL }, | ||
966 | |||
967 | /* find out the current status */ | ||
968 | |||
969 | { mk_mii_read(MII_LXT970_CSR), mii_parse_lxt970_csr }, | ||
970 | { mk_mii_end, } | ||
971 | }, | ||
972 | (const phy_cmd_t []) { /* shutdown - disable interrupts */ | ||
973 | { mk_mii_write(MII_LXT970_IER, 0x0000), NULL }, | ||
974 | { mk_mii_end, } | ||
975 | }, | ||
976 | }; | ||
977 | |||
978 | #endif /* CONFIG_FEC_LXT970 */ | ||
979 | |||
980 | /* ------------------------------------------------------------------------- */ | ||
981 | /* The Level one LXT971 is used on some of my custom boards */ | ||
982 | |||
983 | #ifdef CONFIG_FCC_LXT971 | ||
984 | |||
985 | /* register definitions for the 971 */ | ||
986 | |||
987 | #define MII_LXT971_PCR 16 /* Port Control Register */ | ||
988 | #define MII_LXT971_SR2 17 /* Status Register 2 */ | ||
989 | #define MII_LXT971_IER 18 /* Interrupt Enable Register */ | ||
990 | #define MII_LXT971_ISR 19 /* Interrupt Status Register */ | ||
991 | #define MII_LXT971_LCR 20 /* LED Control Register */ | ||
992 | #define MII_LXT971_TCR 30 /* Transmit Control Register */ | ||
993 | |||
994 | /* | ||
995 | * I had some nice ideas of running the MDIO faster... | ||
996 | * The 971 should support 8MHz and I tried it, but things acted really | ||
997 | * weird, so 2.5 MHz ought to be enough for anyone... | ||
998 | */ | ||
999 | |||
1000 | static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev) | ||
1001 | { | ||
1002 | volatile struct fcc_enet_private *fep = dev->priv; | ||
1003 | uint s = fep->phy_status; | ||
1004 | |||
1005 | s &= ~(PHY_STAT_SPMASK); | ||
1006 | |||
1007 | if (mii_reg & 0x4000) { | ||
1008 | if (mii_reg & 0x0200) | ||
1009 | s |= PHY_STAT_100FDX; | ||
1010 | else | ||
1011 | s |= PHY_STAT_100HDX; | ||
1012 | } else { | ||
1013 | if (mii_reg & 0x0200) | ||
1014 | s |= PHY_STAT_10FDX; | ||
1015 | else | ||
1016 | s |= PHY_STAT_10HDX; | ||
1017 | } | ||
1018 | if (mii_reg & 0x0008) | ||
1019 | s |= PHY_STAT_FAULT; | ||
1020 | |||
1021 | fep->phy_status = s; | ||
1022 | } | ||
1023 | |||
1024 | static phy_info_t phy_info_lxt971 = { | ||
1025 | 0x0001378e, | ||
1026 | "LXT971", | ||
1027 | |||
1028 | (const phy_cmd_t []) { /* config */ | ||
1029 | /* configure link capabilities to advertise */ | ||
1030 | { mk_mii_write(MII_ADVERTISE, MII_ADVERTISE_DEFAULT), | ||
1031 | mii_parse_anar }, | ||
1032 | |||
1033 | /* enable auto-negotiation */ | ||
1034 | { mk_mii_write(MII_BMCR, BMCR_ANENABLE), mii_parse_cr }, | ||
1035 | { mk_mii_end, } | ||
1036 | }, | ||
1037 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
1038 | { mk_mii_write(MII_LXT971_IER, 0x00f2), NULL }, | ||
1039 | |||
1040 | /* restart auto-negotiation */ | ||
1041 | { mk_mii_write(MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART), | ||
1042 | NULL }, | ||
1043 | { mk_mii_end, } | ||
1044 | }, | ||
1045 | (const phy_cmd_t []) { /* ack_int */ | ||
1046 | /* find out the current status */ | ||
1047 | { mk_mii_read(MII_BMSR), NULL }, | ||
1048 | { mk_mii_read(MII_BMSR), mii_parse_sr }, | ||
1049 | { mk_mii_read(MII_LXT971_SR2), mii_parse_lxt971_sr2 }, | ||
1050 | |||
1051 | /* we only need to read ISR to acknowledge */ | ||
1052 | { mk_mii_read(MII_LXT971_ISR), NULL }, | ||
1053 | { mk_mii_end, } | ||
1054 | }, | ||
1055 | (const phy_cmd_t []) { /* shutdown - disable interrupts */ | ||
1056 | { mk_mii_write(MII_LXT971_IER, 0x0000), NULL }, | ||
1057 | { mk_mii_end, } | ||
1058 | }, | ||
1059 | }; | ||
1060 | |||
1061 | #endif /* CONFIG_FCC_LXT971 */ | ||
1062 | |||
1063 | /* ------------------------------------------------------------------------- */ | ||
1064 | /* The Quality Semiconductor QS6612 is used on the RPX CLLF */ | ||
1065 | |||
1066 | #ifdef CONFIG_FCC_QS6612 | ||
1067 | |||
1068 | /* register definitions */ | ||
1069 | |||
1070 | #define MII_QS6612_MCR 17 /* Mode Control Register */ | ||
1071 | #define MII_QS6612_FTR 27 /* Factory Test Register */ | ||
1072 | #define MII_QS6612_MCO 28 /* Misc. Control Register */ | ||
1073 | #define MII_QS6612_ISR 29 /* Interrupt Source Register */ | ||
1074 | #define MII_QS6612_IMR 30 /* Interrupt Mask Register */ | ||
1075 | #define MII_QS6612_PCR 31 /* 100BaseTx PHY Control Reg. */ | ||
1076 | |||
1077 | static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev) | ||
1078 | { | ||
1079 | volatile struct fcc_enet_private *fep = dev->priv; | ||
1080 | uint s = fep->phy_status; | ||
1081 | |||
1082 | s &= ~(PHY_STAT_SPMASK); | ||
1083 | |||
1084 | switch((mii_reg >> 2) & 7) { | ||
1085 | case 1: s |= PHY_STAT_10HDX; break; | ||
1086 | case 2: s |= PHY_STAT_100HDX; break; | ||
1087 | case 5: s |= PHY_STAT_10FDX; break; | ||
1088 | case 6: s |= PHY_STAT_100FDX; break; | ||
1089 | } | ||
1090 | |||
1091 | fep->phy_status = s; | ||
1092 | } | ||
1093 | |||
1094 | static phy_info_t phy_info_qs6612 = { | ||
1095 | 0x00181440, | ||
1096 | "QS6612", | ||
1097 | |||
1098 | (const phy_cmd_t []) { /* config */ | ||
1099 | // { mk_mii_write(MII_ADVERTISE, 0x061), NULL }, /* 10 Mbps */ | ||
1100 | |||
1101 | /* The PHY powers up isolated on the RPX, | ||
1102 | * so send a command to allow operation. | ||
1103 | */ | ||
1104 | |||
1105 | { mk_mii_write(MII_QS6612_PCR, 0x0dc0), NULL }, | ||
1106 | |||
1107 | /* parse cr and anar to get some info */ | ||
1108 | |||
1109 | { mk_mii_read(MII_BMCR), mii_parse_cr }, | ||
1110 | { mk_mii_read(MII_ADVERTISE), mii_parse_anar }, | ||
1111 | { mk_mii_end, } | ||
1112 | }, | ||
1113 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
1114 | { mk_mii_write(MII_QS6612_IMR, 0x003a), NULL }, | ||
1115 | { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */ | ||
1116 | { mk_mii_end, } | ||
1117 | }, | ||
1118 | (const phy_cmd_t []) { /* ack_int */ | ||
1119 | |||
1120 | /* we need to read ISR, SR and ANER to acknowledge */ | ||
1121 | |||
1122 | { mk_mii_read(MII_QS6612_ISR), NULL }, | ||
1123 | { mk_mii_read(MII_BMSR), mii_parse_sr }, | ||
1124 | { mk_mii_read(MII_EXPANSION), NULL }, | ||
1125 | |||
1126 | /* read pcr to get info */ | ||
1127 | |||
1128 | { mk_mii_read(MII_QS6612_PCR), mii_parse_qs6612_pcr }, | ||
1129 | { mk_mii_end, } | ||
1130 | }, | ||
1131 | (const phy_cmd_t []) { /* shutdown - disable interrupts */ | ||
1132 | { mk_mii_write(MII_QS6612_IMR, 0x0000), NULL }, | ||
1133 | { mk_mii_end, } | ||
1134 | }, | ||
1135 | }; | ||
1136 | |||
1137 | |||
1138 | #endif /* CONFIG_FEC_QS6612 */ | ||
1139 | |||
1140 | |||
1141 | /* ------------------------------------------------------------------------- */ | ||
1142 | /* The Davicom DM9131 is used on the HYMOD board */ | ||
1143 | |||
1144 | #ifdef CONFIG_FCC_DM9131 | ||
1145 | |||
1146 | /* register definitions */ | ||
1147 | |||
1148 | #define MII_DM9131_ACR 16 /* Aux. Config Register */ | ||
1149 | #define MII_DM9131_ACSR 17 /* Aux. Config/Status Register */ | ||
1150 | #define MII_DM9131_10TCSR 18 /* 10BaseT Config/Status Reg. */ | ||
1151 | #define MII_DM9131_INTR 21 /* Interrupt Register */ | ||
1152 | #define MII_DM9131_RECR 22 /* Receive Error Counter Reg. */ | ||
1153 | #define MII_DM9131_DISCR 23 /* Disconnect Counter Register */ | ||
1154 | |||
1155 | static void mii_parse_dm9131_acsr(uint mii_reg, struct net_device *dev) | ||
1156 | { | ||
1157 | volatile struct fcc_enet_private *fep = dev->priv; | ||
1158 | uint s = fep->phy_status; | ||
1159 | |||
1160 | s &= ~(PHY_STAT_SPMASK); | ||
1161 | |||
1162 | switch ((mii_reg >> 12) & 0xf) { | ||
1163 | case 1: s |= PHY_STAT_10HDX; break; | ||
1164 | case 2: s |= PHY_STAT_10FDX; break; | ||
1165 | case 4: s |= PHY_STAT_100HDX; break; | ||
1166 | case 8: s |= PHY_STAT_100FDX; break; | ||
1167 | } | ||
1168 | |||
1169 | fep->phy_status = s; | ||
1170 | } | ||
1171 | |||
1172 | static phy_info_t phy_info_dm9131 = { | ||
1173 | 0x00181b80, | ||
1174 | "DM9131", | ||
1175 | |||
1176 | (const phy_cmd_t []) { /* config */ | ||
1177 | /* parse cr and anar to get some info */ | ||
1178 | { mk_mii_read(MII_BMCR), mii_parse_cr }, | ||
1179 | { mk_mii_read(MII_ADVERTISE), mii_parse_anar }, | ||
1180 | { mk_mii_end, } | ||
1181 | }, | ||
1182 | (const phy_cmd_t []) { /* startup - enable interrupts */ | ||
1183 | { mk_mii_write(MII_DM9131_INTR, 0x0002), NULL }, | ||
1184 | { mk_mii_write(MII_BMCR, 0x1200), NULL }, /* autonegotiate */ | ||
1185 | { mk_mii_end, } | ||
1186 | }, | ||
1187 | (const phy_cmd_t []) { /* ack_int */ | ||
1188 | |||
1189 | /* we need to read INTR, SR and ANER to acknowledge */ | ||
1190 | |||
1191 | { mk_mii_read(MII_DM9131_INTR), NULL }, | ||
1192 | { mk_mii_read(MII_BMSR), mii_parse_sr }, | ||
1193 | { mk_mii_read(MII_EXPANSION), NULL }, | ||
1194 | |||
1195 | /* read acsr to get info */ | ||
1196 | |||
1197 | { mk_mii_read(MII_DM9131_ACSR), mii_parse_dm9131_acsr }, | ||
1198 | { mk_mii_end, } | ||
1199 | }, | ||
1200 | (const phy_cmd_t []) { /* shutdown - disable interrupts */ | ||
1201 | { mk_mii_write(MII_DM9131_INTR, 0x0f00), NULL }, | ||
1202 | { mk_mii_end, } | ||
1203 | }, | ||
1204 | }; | ||
1205 | |||
1206 | |||
1207 | #endif /* CONFIG_FEC_DM9131 */ | ||
1208 | #ifdef CONFIG_FCC_DM9161 | ||
1209 | /* ------------------------------------------------------------------------- */ | ||
1210 | /* DM9161 Control register values */ | ||
1211 | #define MIIM_DM9161_CR_STOP 0x0400 | ||
1212 | #define MIIM_DM9161_CR_RSTAN 0x1200 | ||
1213 | |||
1214 | #define MIIM_DM9161_SCR 0x10 | ||
1215 | #define MIIM_DM9161_SCR_INIT 0x0610 | ||
1216 | |||
1217 | /* DM9161 Specified Configuration and Status Register */ | ||
1218 | #define MIIM_DM9161_SCSR 0x11 | ||
1219 | #define MIIM_DM9161_SCSR_100F 0x8000 | ||
1220 | #define MIIM_DM9161_SCSR_100H 0x4000 | ||
1221 | #define MIIM_DM9161_SCSR_10F 0x2000 | ||
1222 | #define MIIM_DM9161_SCSR_10H 0x1000 | ||
1223 | /* DM9161 10BT register */ | ||
1224 | #define MIIM_DM9161_10BTCSR 0x12 | ||
1225 | #define MIIM_DM9161_10BTCSR_INIT 0x7800 | ||
1226 | /* DM9161 Interrupt Register */ | ||
1227 | #define MIIM_DM9161_INTR 0x15 | ||
1228 | #define MIIM_DM9161_INTR_PEND 0x8000 | ||
1229 | #define MIIM_DM9161_INTR_DPLX_MASK 0x0800 | ||
1230 | #define MIIM_DM9161_INTR_SPD_MASK 0x0400 | ||
1231 | #define MIIM_DM9161_INTR_LINK_MASK 0x0200 | ||
1232 | #define MIIM_DM9161_INTR_MASK 0x0100 | ||
1233 | #define MIIM_DM9161_INTR_DPLX_CHANGE 0x0010 | ||
1234 | #define MIIM_DM9161_INTR_SPD_CHANGE 0x0008 | ||
1235 | #define MIIM_DM9161_INTR_LINK_CHANGE 0x0004 | ||
1236 | #define MIIM_DM9161_INTR_INIT 0x0000 | ||
1237 | #define MIIM_DM9161_INTR_STOP \ | ||
1238 | (MIIM_DM9161_INTR_DPLX_MASK | MIIM_DM9161_INTR_SPD_MASK \ | ||
1239 | | MIIM_DM9161_INTR_LINK_MASK | MIIM_DM9161_INTR_MASK) | ||
1240 | |||
1241 | static void mii_parse_dm9161_sr(uint mii_reg, struct net_device * dev) | ||
1242 | { | ||
1243 | volatile struct fcc_enet_private *fep = dev->priv; | ||
1244 | uint regstat, timeout=0xffff; | ||
1245 | |||
1246 | while(!(mii_reg & 0x0020) && timeout--) | ||
1247 | { | ||
1248 | regstat=mk_mii_read(MII_BMSR); | ||
1249 | regstat |= fep->phy_addr <<23; | ||
1250 | mii_reg = mii_send_receive(fep->fip,regstat); | ||
1251 | } | ||
1252 | |||
1253 | mii_parse_sr(mii_reg, dev); | ||
1254 | } | ||
1255 | |||
1256 | static void mii_parse_dm9161_scsr(uint mii_reg, struct net_device * dev) | ||
1257 | { | ||
1258 | volatile struct fcc_enet_private *fep = dev->priv; | ||
1259 | uint s = fep->phy_status; | ||
1260 | |||
1261 | s &= ~(PHY_STAT_SPMASK); | ||
1262 | switch((mii_reg >>12) & 0xf) { | ||
1263 | case 1: | ||
1264 | { | ||
1265 | s |= PHY_STAT_10HDX; | ||
1266 | printk("10BaseT Half Duplex\n"); | ||
1267 | break; | ||
1268 | } | ||
1269 | case 2: | ||
1270 | { | ||
1271 | s |= PHY_STAT_10FDX; | ||
1272 | printk("10BaseT Full Duplex\n"); | ||
1273 | break; | ||
1274 | } | ||
1275 | case 4: | ||
1276 | { | ||
1277 | s |= PHY_STAT_100HDX; | ||
1278 | printk("100BaseT Half Duplex\n"); | ||
1279 | break; | ||
1280 | } | ||
1281 | case 8: | ||
1282 | { | ||
1283 | s |= PHY_STAT_100FDX; | ||
1284 | printk("100BaseT Full Duplex\n"); | ||
1285 | break; | ||
1286 | } | ||
1287 | } | ||
1288 | |||
1289 | fep->phy_status = s; | ||
1290 | |||
1291 | } | ||
1292 | |||
1293 | static void mii_dm9161_wait(uint mii_reg, struct net_device *dev) | ||
1294 | { | ||
1295 | int timeout = HZ; | ||
1296 | |||
1297 | /* Davicom takes a bit to come up after a reset, | ||
1298 | * so wait here for a bit */ | ||
1299 | schedule_timeout_uninterruptible(timeout); | ||
1300 | } | ||
1301 | |||
1302 | static phy_info_t phy_info_dm9161 = { | ||
1303 | 0x00181b88, | ||
1304 | "Davicom DM9161E", | ||
1305 | (const phy_cmd_t[]) { /* config */ | ||
1306 | { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_STOP), NULL}, | ||
1307 | /* Do not bypass the scrambler/descrambler */ | ||
1308 | { mk_mii_write(MIIM_DM9161_SCR, MIIM_DM9161_SCR_INIT), NULL}, | ||
1309 | /* Configure 10BTCSR register */ | ||
1310 | { mk_mii_write(MIIM_DM9161_10BTCSR, MIIM_DM9161_10BTCSR_INIT),NULL}, | ||
1311 | /* Configure some basic stuff */ | ||
1312 | { mk_mii_write(MII_BMCR, 0x1000), NULL}, | ||
1313 | { mk_mii_read(MII_BMCR), mii_parse_cr }, | ||
1314 | { mk_mii_read(MII_ADVERTISE), mii_parse_anar }, | ||
1315 | { mk_mii_end,} | ||
1316 | }, | ||
1317 | (const phy_cmd_t[]) { /* startup */ | ||
1318 | /* Restart Auto Negotiation */ | ||
1319 | { mk_mii_write(MII_BMCR, MIIM_DM9161_CR_RSTAN), NULL}, | ||
1320 | /* Status is read once to clear old link state */ | ||
1321 | { mk_mii_read(MII_BMSR), mii_dm9161_wait}, | ||
1322 | /* Auto-negotiate */ | ||
1323 | { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr}, | ||
1324 | /* Read the status */ | ||
1325 | { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr}, | ||
1326 | /* Clear any pending interrupts */ | ||
1327 | { mk_mii_read(MIIM_DM9161_INTR), NULL}, | ||
1328 | /* Enable Interrupts */ | ||
1329 | { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_INIT), NULL}, | ||
1330 | { mk_mii_end,} | ||
1331 | }, | ||
1332 | (const phy_cmd_t[]) { /* ack_int */ | ||
1333 | { mk_mii_read(MIIM_DM9161_INTR), NULL}, | ||
1334 | #if 0 | ||
1335 | { mk_mii_read(MII_BMSR), NULL}, | ||
1336 | { mk_mii_read(MII_BMSR), mii_parse_dm9161_sr}, | ||
1337 | { mk_mii_read(MIIM_DM9161_SCSR), mii_parse_dm9161_scsr}, | ||
1338 | #endif | ||
1339 | { mk_mii_end,} | ||
1340 | }, | ||
1341 | (const phy_cmd_t[]) { /* shutdown */ | ||
1342 | { mk_mii_read(MIIM_DM9161_INTR),NULL}, | ||
1343 | { mk_mii_write(MIIM_DM9161_INTR, MIIM_DM9161_INTR_STOP), NULL}, | ||
1344 | { mk_mii_end,} | ||
1345 | }, | ||
1346 | }; | ||
1347 | #endif /* CONFIG_FCC_DM9161 */ | ||
1348 | |||
1349 | static phy_info_t *phy_info[] = { | ||
1350 | |||
1351 | #ifdef CONFIG_FCC_LXT970 | ||
1352 | &phy_info_lxt970, | ||
1353 | #endif /* CONFIG_FEC_LXT970 */ | ||
1354 | |||
1355 | #ifdef CONFIG_FCC_LXT971 | ||
1356 | &phy_info_lxt971, | ||
1357 | #endif /* CONFIG_FEC_LXT971 */ | ||
1358 | |||
1359 | #ifdef CONFIG_FCC_QS6612 | ||
1360 | &phy_info_qs6612, | ||
1361 | #endif /* CONFIG_FEC_QS6612 */ | ||
1362 | |||
1363 | #ifdef CONFIG_FCC_DM9131 | ||
1364 | &phy_info_dm9131, | ||
1365 | #endif /* CONFIG_FEC_DM9131 */ | ||
1366 | |||
1367 | #ifdef CONFIG_FCC_DM9161 | ||
1368 | &phy_info_dm9161, | ||
1369 | #endif /* CONFIG_FCC_DM9161 */ | ||
1370 | |||
1371 | #ifdef CONFIG_FCC_GENERIC_PHY | ||
1372 | /* Generic PHY support. This must be the last PHY in the table. | ||
1373 | * It will be used to support any PHY that doesn't match a previous | ||
1374 | * entry in the table. | ||
1375 | */ | ||
1376 | &phy_info_generic, | ||
1377 | #endif /* CONFIG_FCC_GENERIC_PHY */ | ||
1378 | |||
1379 | NULL | ||
1380 | }; | ||
1381 | |||
1382 | static void mii_display_status(struct work_struct *work) | ||
1383 | { | ||
1384 | volatile struct fcc_enet_private *fep = | ||
1385 | container_of(work, struct fcc_enet_private, phy_relink); | ||
1386 | struct net_device *dev = fep->dev; | ||
1387 | uint s = fep->phy_status; | ||
1388 | |||
1389 | if (!fep->link && !fep->old_link) { | ||
1390 | /* Link is still down - don't print anything */ | ||
1391 | return; | ||
1392 | } | ||
1393 | |||
1394 | printk("%s: status: ", dev->name); | ||
1395 | |||
1396 | if (!fep->link) { | ||
1397 | printk("link down"); | ||
1398 | } else { | ||
1399 | printk("link up"); | ||
1400 | |||
1401 | switch(s & PHY_STAT_SPMASK) { | ||
1402 | case PHY_STAT_100FDX: printk(", 100 Mbps Full Duplex"); break; | ||
1403 | case PHY_STAT_100HDX: printk(", 100 Mbps Half Duplex"); break; | ||
1404 | case PHY_STAT_10FDX: printk(", 10 Mbps Full Duplex"); break; | ||
1405 | case PHY_STAT_10HDX: printk(", 10 Mbps Half Duplex"); break; | ||
1406 | default: | ||
1407 | printk(", Unknown speed/duplex"); | ||
1408 | } | ||
1409 | |||
1410 | if (s & PHY_STAT_ANC) | ||
1411 | printk(", auto-negotiation complete"); | ||
1412 | } | ||
1413 | |||
1414 | if (s & PHY_STAT_FAULT) | ||
1415 | printk(", remote fault"); | ||
1416 | |||
1417 | printk(".\n"); | ||
1418 | } | ||
1419 | |||
1420 | static void mii_display_config(struct work_struct *work) | ||
1421 | { | ||
1422 | volatile struct fcc_enet_private *fep = | ||
1423 | container_of(work, struct fcc_enet_private, | ||
1424 | phy_display_config); | ||
1425 | struct net_device *dev = fep->dev; | ||
1426 | uint s = fep->phy_status; | ||
1427 | |||
1428 | printk("%s: config: auto-negotiation ", dev->name); | ||
1429 | |||
1430 | if (s & PHY_CONF_ANE) | ||
1431 | printk("on"); | ||
1432 | else | ||
1433 | printk("off"); | ||
1434 | |||
1435 | if (s & PHY_CONF_100FDX) | ||
1436 | printk(", 100FDX"); | ||
1437 | if (s & PHY_CONF_100HDX) | ||
1438 | printk(", 100HDX"); | ||
1439 | if (s & PHY_CONF_10FDX) | ||
1440 | printk(", 10FDX"); | ||
1441 | if (s & PHY_CONF_10HDX) | ||
1442 | printk(", 10HDX"); | ||
1443 | if (!(s & PHY_CONF_SPMASK)) | ||
1444 | printk(", No speed/duplex selected?"); | ||
1445 | |||
1446 | if (s & PHY_CONF_LOOP) | ||
1447 | printk(", loopback enabled"); | ||
1448 | |||
1449 | printk(".\n"); | ||
1450 | |||
1451 | fep->sequence_done = 1; | ||
1452 | } | ||
1453 | |||
1454 | static void mii_relink(struct net_device *dev) | ||
1455 | { | ||
1456 | struct fcc_enet_private *fep = dev->priv; | ||
1457 | int duplex = 0; | ||
1458 | |||
1459 | fep->old_link = fep->link; | ||
1460 | fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0; | ||
1461 | |||
1462 | #ifdef MDIO_DEBUG | ||
1463 | printk(" mii_relink: link=%d\n", fep->link); | ||
1464 | #endif | ||
1465 | |||
1466 | if (fep->link) { | ||
1467 | if (fep->phy_status | ||
1468 | & (PHY_STAT_100FDX | PHY_STAT_10FDX)) | ||
1469 | duplex = 1; | ||
1470 | fcc_restart(dev, duplex); | ||
1471 | #ifdef MDIO_DEBUG | ||
1472 | printk(" mii_relink: duplex=%d\n", duplex); | ||
1473 | #endif | ||
1474 | } | ||
1475 | } | ||
1476 | |||
1477 | static void mii_queue_relink(uint mii_reg, struct net_device *dev) | ||
1478 | { | ||
1479 | struct fcc_enet_private *fep = dev->priv; | ||
1480 | |||
1481 | mii_relink(dev); | ||
1482 | |||
1483 | schedule_work(&fep->phy_relink); | ||
1484 | } | ||
1485 | |||
1486 | static void mii_queue_config(uint mii_reg, struct net_device *dev) | ||
1487 | { | ||
1488 | struct fcc_enet_private *fep = dev->priv; | ||
1489 | |||
1490 | schedule_work(&fep->phy_display_config); | ||
1491 | } | ||
1492 | |||
1493 | phy_cmd_t phy_cmd_relink[] = { { mk_mii_read(MII_BMCR), mii_queue_relink }, | ||
1494 | { mk_mii_end, } }; | ||
1495 | phy_cmd_t phy_cmd_config[] = { { mk_mii_read(MII_BMCR), mii_queue_config }, | ||
1496 | { mk_mii_end, } }; | ||
1497 | |||
1498 | |||
1499 | /* Read remainder of PHY ID. | ||
1500 | */ | ||
1501 | static void | ||
1502 | mii_discover_phy3(uint mii_reg, struct net_device *dev) | ||
1503 | { | ||
1504 | struct fcc_enet_private *fep; | ||
1505 | int i; | ||
1506 | |||
1507 | fep = dev->priv; | ||
1508 | printk("mii_reg: %08x\n", mii_reg); | ||
1509 | fep->phy_id |= (mii_reg & 0xffff); | ||
1510 | |||
1511 | for(i = 0; phy_info[i]; i++) | ||
1512 | if((phy_info[i]->id == (fep->phy_id >> 4)) || !phy_info[i]->id) | ||
1513 | break; | ||
1514 | |||
1515 | if(!phy_info[i]) | ||
1516 | panic("%s: PHY id 0x%08x is not supported!\n", | ||
1517 | dev->name, fep->phy_id); | ||
1518 | |||
1519 | fep->phy = phy_info[i]; | ||
1520 | fep->phy_id_done = 1; | ||
1521 | |||
1522 | printk("%s: Phy @ 0x%x, type %s (0x%08x)\n", | ||
1523 | dev->name, fep->phy_addr, fep->phy->name, fep->phy_id); | ||
1524 | } | ||
1525 | |||
1526 | /* Scan all of the MII PHY addresses looking for someone to respond | ||
1527 | * with a valid ID. This usually happens quickly. | ||
1528 | */ | ||
1529 | static void | ||
1530 | mii_discover_phy(uint mii_reg, struct net_device *dev) | ||
1531 | { | ||
1532 | struct fcc_enet_private *fep; | ||
1533 | uint phytype; | ||
1534 | |||
1535 | fep = dev->priv; | ||
1536 | |||
1537 | if ((phytype = (mii_reg & 0xffff)) != 0xffff) { | ||
1538 | |||
1539 | /* Got first part of ID, now get remainder. */ | ||
1540 | fep->phy_id = phytype << 16; | ||
1541 | mii_queue(dev, mk_mii_read(MII_PHYSID2), mii_discover_phy3); | ||
1542 | } else { | ||
1543 | fep->phy_addr++; | ||
1544 | if (fep->phy_addr < 32) { | ||
1545 | mii_queue(dev, mk_mii_read(MII_PHYSID1), | ||
1546 | mii_discover_phy); | ||
1547 | } else { | ||
1548 | printk("fec: No PHY device found.\n"); | ||
1549 | } | ||
1550 | } | ||
1551 | } | ||
1552 | #endif /* CONFIG_USE_MDIO */ | ||
1553 | |||
1554 | #ifdef PHY_INTERRUPT | ||
1555 | /* This interrupt occurs when the PHY detects a link change. */ | ||
1556 | static irqreturn_t | ||
1557 | mii_link_interrupt(int irq, void * dev_id) | ||
1558 | { | ||
1559 | struct net_device *dev = dev_id; | ||
1560 | struct fcc_enet_private *fep = dev->priv; | ||
1561 | fcc_info_t *fip = fep->fip; | ||
1562 | |||
1563 | if (fep->phy) { | ||
1564 | /* We don't want to be interrupted by an FCC | ||
1565 | * interrupt here. | ||
1566 | */ | ||
1567 | disable_irq_nosync(fip->fc_interrupt); | ||
1568 | |||
1569 | mii_do_cmd(dev, fep->phy->ack_int); | ||
1570 | /* restart and display status */ | ||
1571 | mii_do_cmd(dev, phy_cmd_relink); | ||
1572 | |||
1573 | enable_irq(fip->fc_interrupt); | ||
1574 | } | ||
1575 | return IRQ_HANDLED; | ||
1576 | } | ||
1577 | #endif /* ifdef PHY_INTERRUPT */ | ||
1578 | |||
1579 | #if 0 /* This should be fixed someday */ | ||
1580 | /* Set or clear the multicast filter for this adaptor. | ||
1581 | * Skeleton taken from sunlance driver. | ||
1582 | * The CPM Ethernet implementation allows Multicast as well as individual | ||
1583 | * MAC address filtering. Some of the drivers check to make sure it is | ||
1584 | * a group multicast address, and discard those that are not. I guess I | ||
1585 | * will do the same for now, but just remove the test if you want | ||
1586 | * individual filtering as well (do the upper net layers want or support | ||
1587 | * this kind of feature?). | ||
1588 | */ | ||
1589 | static void | ||
1590 | set_multicast_list(struct net_device *dev) | ||
1591 | { | ||
1592 | struct fcc_enet_private *cep; | ||
1593 | struct dev_mc_list *dmi; | ||
1594 | u_char *mcptr, *tdptr; | ||
1595 | volatile fcc_enet_t *ep; | ||
1596 | int i, j; | ||
1597 | |||
1598 | cep = (struct fcc_enet_private *)dev->priv; | ||
1599 | |||
1600 | return; | ||
1601 | /* Get pointer to FCC area in parameter RAM. | ||
1602 | */ | ||
1603 | ep = (fcc_enet_t *)dev->base_addr; | ||
1604 | |||
1605 | if (dev->flags&IFF_PROMISC) { | ||
1606 | |||
1607 | /* Log any net taps. */ | ||
1608 | printk("%s: Promiscuous mode enabled.\n", dev->name); | ||
1609 | cep->fccp->fcc_fpsmr |= FCC_PSMR_PRO; | ||
1610 | } else { | ||
1611 | |||
1612 | cep->fccp->fcc_fpsmr &= ~FCC_PSMR_PRO; | ||
1613 | |||
1614 | if (dev->flags & IFF_ALLMULTI) { | ||
1615 | /* Catch all multicast addresses, so set the | ||
1616 | * filter to all 1's. | ||
1617 | */ | ||
1618 | ep->fen_gaddrh = 0xffffffff; | ||
1619 | ep->fen_gaddrl = 0xffffffff; | ||
1620 | } | ||
1621 | else { | ||
1622 | /* Clear filter and add the addresses in the list. | ||
1623 | */ | ||
1624 | ep->fen_gaddrh = 0; | ||
1625 | ep->fen_gaddrl = 0; | ||
1626 | |||
1627 | dmi = dev->mc_list; | ||
1628 | |||
1629 | for (i=0; i<dev->mc_count; i++, dmi = dmi->next) { | ||
1630 | |||
1631 | /* Only support group multicast for now. | ||
1632 | */ | ||
1633 | if (!(dmi->dmi_addr[0] & 1)) | ||
1634 | continue; | ||
1635 | |||
1636 | /* The address in dmi_addr is LSB first, | ||
1637 | * and taddr is MSB first. We have to | ||
1638 | * copy bytes MSB first from dmi_addr. | ||
1639 | */ | ||
1640 | mcptr = (u_char *)dmi->dmi_addr + 5; | ||
1641 | tdptr = (u_char *)&ep->fen_taddrh; | ||
1642 | for (j=0; j<6; j++) | ||
1643 | *tdptr++ = *mcptr--; | ||
1644 | |||
1645 | /* Ask CPM to run CRC and set bit in | ||
1646 | * filter mask. | ||
1647 | */ | ||
1648 | cpmp->cp_cpcr = mk_cr_cmd(cep->fip->fc_cpmpage, | ||
1649 | cep->fip->fc_cpmblock, 0x0c, | ||
1650 | CPM_CR_SET_GADDR) | CPM_CR_FLG; | ||
1651 | udelay(10); | ||
1652 | while (cpmp->cp_cpcr & CPM_CR_FLG); | ||
1653 | } | ||
1654 | } | ||
1655 | } | ||
1656 | } | ||
1657 | #endif /* if 0 */ | ||
1658 | |||
1659 | |||
1660 | /* Set the individual MAC address. | ||
1661 | */ | ||
1662 | int fcc_enet_set_mac_address(struct net_device *dev, void *p) | ||
1663 | { | ||
1664 | struct sockaddr *addr= (struct sockaddr *) p; | ||
1665 | struct fcc_enet_private *cep; | ||
1666 | volatile fcc_enet_t *ep; | ||
1667 | unsigned char *eap; | ||
1668 | int i; | ||
1669 | |||
1670 | cep = (struct fcc_enet_private *)(dev->priv); | ||
1671 | ep = cep->ep; | ||
1672 | |||
1673 | if (netif_running(dev)) | ||
1674 | return -EBUSY; | ||
1675 | |||
1676 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
1677 | |||
1678 | eap = (unsigned char *) &(ep->fen_paddrh); | ||
1679 | for (i=5; i>=0; i--) | ||
1680 | *eap++ = addr->sa_data[i]; | ||
1681 | |||
1682 | return 0; | ||
1683 | } | ||
1684 | |||
1685 | |||
1686 | /* Initialize the CPM Ethernet on FCC. | ||
1687 | */ | ||
1688 | static int __init fec_enet_init(void) | ||
1689 | { | ||
1690 | struct net_device *dev; | ||
1691 | struct fcc_enet_private *cep; | ||
1692 | fcc_info_t *fip; | ||
1693 | int i, np, err; | ||
1694 | volatile cpm2_map_t *immap; | ||
1695 | volatile iop_cpm2_t *io; | ||
1696 | |||
1697 | immap = (cpm2_map_t *)CPM_MAP_ADDR; /* and to internal registers */ | ||
1698 | io = &immap->im_ioport; | ||
1699 | |||
1700 | np = sizeof(fcc_ports) / sizeof(fcc_info_t); | ||
1701 | fip = fcc_ports; | ||
1702 | |||
1703 | while (np-- > 0) { | ||
1704 | /* Create an Ethernet device instance. | ||
1705 | */ | ||
1706 | dev = alloc_etherdev(sizeof(*cep)); | ||
1707 | if (!dev) | ||
1708 | return -ENOMEM; | ||
1709 | |||
1710 | cep = dev->priv; | ||
1711 | spin_lock_init(&cep->lock); | ||
1712 | cep->fip = fip; | ||
1713 | |||
1714 | init_fcc_shutdown(fip, cep, immap); | ||
1715 | init_fcc_ioports(fip, io, immap); | ||
1716 | init_fcc_param(fip, dev, immap); | ||
1717 | |||
1718 | dev->base_addr = (unsigned long)(cep->ep); | ||
1719 | |||
1720 | /* The CPM Ethernet specific entries in the device | ||
1721 | * structure. | ||
1722 | */ | ||
1723 | dev->open = fcc_enet_open; | ||
1724 | dev->hard_start_xmit = fcc_enet_start_xmit; | ||
1725 | dev->tx_timeout = fcc_enet_timeout; | ||
1726 | dev->watchdog_timeo = TX_TIMEOUT; | ||
1727 | dev->stop = fcc_enet_close; | ||
1728 | dev->get_stats = fcc_enet_get_stats; | ||
1729 | /* dev->set_multicast_list = set_multicast_list; */ | ||
1730 | dev->set_mac_address = fcc_enet_set_mac_address; | ||
1731 | |||
1732 | init_fcc_startup(fip, dev); | ||
1733 | |||
1734 | err = register_netdev(dev); | ||
1735 | if (err) { | ||
1736 | free_netdev(dev); | ||
1737 | return err; | ||
1738 | } | ||
1739 | |||
1740 | printk("%s: FCC ENET Version 0.3, ", dev->name); | ||
1741 | for (i=0; i<5; i++) | ||
1742 | printk("%02x:", dev->dev_addr[i]); | ||
1743 | printk("%02x\n", dev->dev_addr[5]); | ||
1744 | |||
1745 | #ifdef CONFIG_USE_MDIO | ||
1746 | /* Queue up command to detect the PHY and initialize the | ||
1747 | * remainder of the interface. | ||
1748 | */ | ||
1749 | cep->phy_id_done = 0; | ||
1750 | cep->phy_addr = fip->fc_phyaddr; | ||
1751 | mii_queue(dev, mk_mii_read(MII_PHYSID1), mii_discover_phy); | ||
1752 | INIT_WORK(&cep->phy_relink, mii_display_status); | ||
1753 | INIT_WORK(&cep->phy_display_config, mii_display_config); | ||
1754 | cep->dev = dev; | ||
1755 | #endif /* CONFIG_USE_MDIO */ | ||
1756 | |||
1757 | fip++; | ||
1758 | } | ||
1759 | |||
1760 | return 0; | ||
1761 | } | ||
1762 | module_init(fec_enet_init); | ||
1763 | |||
1764 | /* Make sure the device is shut down during initialization. | ||
1765 | */ | ||
1766 | static void __init | ||
1767 | init_fcc_shutdown(fcc_info_t *fip, struct fcc_enet_private *cep, | ||
1768 | volatile cpm2_map_t *immap) | ||
1769 | { | ||
1770 | volatile fcc_enet_t *ep; | ||
1771 | volatile fcc_t *fccp; | ||
1772 | |||
1773 | /* Get pointer to FCC area in parameter RAM. | ||
1774 | */ | ||
1775 | ep = (fcc_enet_t *)(&immap->im_dprambase[fip->fc_proff]); | ||
1776 | |||
1777 | /* And another to the FCC register area. | ||
1778 | */ | ||
1779 | fccp = (volatile fcc_t *)(&immap->im_fcc[fip->fc_fccnum]); | ||
1780 | cep->fccp = fccp; /* Keep the pointers handy */ | ||
1781 | cep->ep = ep; | ||
1782 | |||
1783 | /* Disable receive and transmit in case someone left it running. | ||
1784 | */ | ||
1785 | fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT); | ||
1786 | } | ||
1787 | |||
1788 | /* Initialize the I/O pins for the FCC Ethernet. | ||
1789 | */ | ||
1790 | static void __init | ||
1791 | init_fcc_ioports(fcc_info_t *fip, volatile iop_cpm2_t *io, | ||
1792 | volatile cpm2_map_t *immap) | ||
1793 | { | ||
1794 | |||
1795 | /* FCC1 pins are on port A/C. FCC2/3 are port B/C. | ||
1796 | */ | ||
1797 | if (fip->fc_proff == PROFF_FCC1) { | ||
1798 | /* Configure port A and C pins for FCC1 Ethernet. | ||
1799 | */ | ||
1800 | io->iop_pdira &= ~PA1_DIRA_BOUT; | ||
1801 | io->iop_pdira |= PA1_DIRA_BIN; | ||
1802 | io->iop_psora &= ~PA1_PSORA_BOUT; | ||
1803 | io->iop_psora |= PA1_PSORA_BIN; | ||
1804 | io->iop_ppara |= (PA1_DIRA_BOUT | PA1_DIRA_BIN); | ||
1805 | } | ||
1806 | if (fip->fc_proff == PROFF_FCC2) { | ||
1807 | /* Configure port B and C pins for FCC Ethernet. | ||
1808 | */ | ||
1809 | io->iop_pdirb &= ~PB2_DIRB_BOUT; | ||
1810 | io->iop_pdirb |= PB2_DIRB_BIN; | ||
1811 | io->iop_psorb &= ~PB2_PSORB_BOUT; | ||
1812 | io->iop_psorb |= PB2_PSORB_BIN; | ||
1813 | io->iop_pparb |= (PB2_DIRB_BOUT | PB2_DIRB_BIN); | ||
1814 | } | ||
1815 | if (fip->fc_proff == PROFF_FCC3) { | ||
1816 | /* Configure port B and C pins for FCC Ethernet. | ||
1817 | */ | ||
1818 | io->iop_pdirb &= ~PB3_DIRB_BOUT; | ||
1819 | io->iop_pdirb |= PB3_DIRB_BIN; | ||
1820 | io->iop_psorb &= ~PB3_PSORB_BOUT; | ||
1821 | io->iop_psorb |= PB3_PSORB_BIN; | ||
1822 | io->iop_pparb |= (PB3_DIRB_BOUT | PB3_DIRB_BIN); | ||
1823 | |||
1824 | io->iop_pdirc &= ~PC3_DIRC_BOUT; | ||
1825 | io->iop_pdirc |= PC3_DIRC_BIN; | ||
1826 | io->iop_psorc &= ~PC3_PSORC_BOUT; | ||
1827 | io->iop_psorc |= PC3_PSORC_BIN; | ||
1828 | io->iop_pparc |= (PC3_DIRC_BOUT | PC3_DIRC_BIN); | ||
1829 | |||
1830 | } | ||
1831 | |||
1832 | /* Port C has clocks...... | ||
1833 | */ | ||
1834 | io->iop_psorc &= ~(fip->fc_trxclocks); | ||
1835 | io->iop_pdirc &= ~(fip->fc_trxclocks); | ||
1836 | io->iop_pparc |= fip->fc_trxclocks; | ||
1837 | |||
1838 | #ifdef CONFIG_USE_MDIO | ||
1839 | /* ....and the MII serial clock/data. | ||
1840 | */ | ||
1841 | io->iop_pdatc |= (fip->fc_mdio | fip->fc_mdck); | ||
1842 | io->iop_podrc &= ~(fip->fc_mdio | fip->fc_mdck); | ||
1843 | io->iop_pdirc |= (fip->fc_mdio | fip->fc_mdck); | ||
1844 | io->iop_pparc &= ~(fip->fc_mdio | fip->fc_mdck); | ||
1845 | #endif /* CONFIG_USE_MDIO */ | ||
1846 | |||
1847 | /* Configure Serial Interface clock routing. | ||
1848 | * First, clear all FCC bits to zero, | ||
1849 | * then set the ones we want. | ||
1850 | */ | ||
1851 | immap->im_cpmux.cmx_fcr &= ~(fip->fc_clockmask); | ||
1852 | immap->im_cpmux.cmx_fcr |= fip->fc_clockroute; | ||
1853 | } | ||
1854 | |||
1855 | static void __init | ||
1856 | init_fcc_param(fcc_info_t *fip, struct net_device *dev, | ||
1857 | volatile cpm2_map_t *immap) | ||
1858 | { | ||
1859 | unsigned char *eap; | ||
1860 | unsigned long mem_addr; | ||
1861 | bd_t *bd; | ||
1862 | int i, j; | ||
1863 | struct fcc_enet_private *cep; | ||
1864 | volatile fcc_enet_t *ep; | ||
1865 | volatile cbd_t *bdp; | ||
1866 | volatile cpm_cpm2_t *cp; | ||
1867 | |||
1868 | cep = (struct fcc_enet_private *)(dev->priv); | ||
1869 | ep = cep->ep; | ||
1870 | cp = cpmp; | ||
1871 | |||
1872 | bd = (bd_t *)__res; | ||
1873 | |||
1874 | /* Zero the whole thing.....I must have missed some individually. | ||
1875 | * It works when I do this. | ||
1876 | */ | ||
1877 | memset((char *)ep, 0, sizeof(fcc_enet_t)); | ||
1878 | |||
1879 | /* Allocate space for the buffer descriptors from regular memory. | ||
1880 | * Initialize base addresses for the buffer descriptors. | ||
1881 | */ | ||
1882 | cep->rx_bd_base = kmalloc(sizeof(cbd_t) * RX_RING_SIZE, | ||
1883 | GFP_KERNEL | GFP_DMA); | ||
1884 | ep->fen_genfcc.fcc_rbase = __pa(cep->rx_bd_base); | ||
1885 | cep->tx_bd_base = kmalloc(sizeof(cbd_t) * TX_RING_SIZE, | ||
1886 | GFP_KERNEL | GFP_DMA); | ||
1887 | ep->fen_genfcc.fcc_tbase = __pa(cep->tx_bd_base); | ||
1888 | |||
1889 | cep->dirty_tx = cep->cur_tx = cep->tx_bd_base; | ||
1890 | cep->cur_rx = cep->rx_bd_base; | ||
1891 | |||
1892 | ep->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24; | ||
1893 | ep->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24; | ||
1894 | |||
1895 | /* Set maximum bytes per receive buffer. | ||
1896 | * It must be a multiple of 32. | ||
1897 | */ | ||
1898 | ep->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE; | ||
1899 | |||
1900 | /* Allocate space in the reserved FCC area of DPRAM for the | ||
1901 | * internal buffers. No one uses this space (yet), so we | ||
1902 | * can do this. Later, we will add resource management for | ||
1903 | * this area. | ||
1904 | */ | ||
1905 | mem_addr = CPM_FCC_SPECIAL_BASE + (fip->fc_fccnum * 128); | ||
1906 | ep->fen_genfcc.fcc_riptr = mem_addr; | ||
1907 | ep->fen_genfcc.fcc_tiptr = mem_addr+32; | ||
1908 | ep->fen_padptr = mem_addr+64; | ||
1909 | memset((char *)(&(immap->im_dprambase[(mem_addr+64)])), 0x88, 32); | ||
1910 | |||
1911 | ep->fen_genfcc.fcc_rbptr = 0; | ||
1912 | ep->fen_genfcc.fcc_tbptr = 0; | ||
1913 | ep->fen_genfcc.fcc_rcrc = 0; | ||
1914 | ep->fen_genfcc.fcc_tcrc = 0; | ||
1915 | ep->fen_genfcc.fcc_res1 = 0; | ||
1916 | ep->fen_genfcc.fcc_res2 = 0; | ||
1917 | |||
1918 | ep->fen_camptr = 0; /* CAM isn't used in this driver */ | ||
1919 | |||
1920 | /* Set CRC preset and mask. | ||
1921 | */ | ||
1922 | ep->fen_cmask = 0xdebb20e3; | ||
1923 | ep->fen_cpres = 0xffffffff; | ||
1924 | |||
1925 | ep->fen_crcec = 0; /* CRC Error counter */ | ||
1926 | ep->fen_alec = 0; /* alignment error counter */ | ||
1927 | ep->fen_disfc = 0; /* discard frame counter */ | ||
1928 | ep->fen_retlim = 15; /* Retry limit threshold */ | ||
1929 | ep->fen_pper = 0; /* Normal persistence */ | ||
1930 | |||
1931 | /* Clear hash filter tables. | ||
1932 | */ | ||
1933 | ep->fen_gaddrh = 0; | ||
1934 | ep->fen_gaddrl = 0; | ||
1935 | ep->fen_iaddrh = 0; | ||
1936 | ep->fen_iaddrl = 0; | ||
1937 | |||
1938 | /* Clear the Out-of-sequence TxBD. | ||
1939 | */ | ||
1940 | ep->fen_tfcstat = 0; | ||
1941 | ep->fen_tfclen = 0; | ||
1942 | ep->fen_tfcptr = 0; | ||
1943 | |||
1944 | ep->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */ | ||
1945 | ep->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */ | ||
1946 | |||
1947 | /* Set Ethernet station address. | ||
1948 | * | ||
1949 | * This is supplied in the board information structure, so we | ||
1950 | * copy that into the controller. | ||
1951 | * So, far we have only been given one Ethernet address. We make | ||
1952 | * it unique by setting a few bits in the upper byte of the | ||
1953 | * non-static part of the address. | ||
1954 | */ | ||
1955 | eap = (unsigned char *)&(ep->fen_paddrh); | ||
1956 | for (i=5; i>=0; i--) { | ||
1957 | |||
1958 | /* | ||
1959 | * The EP8260 only uses FCC3, so we can safely give it the real | ||
1960 | * MAC address. | ||
1961 | */ | ||
1962 | #ifdef CONFIG_SBC82xx | ||
1963 | if (i == 5) { | ||
1964 | /* bd->bi_enetaddr holds the SCC0 address; the FCC | ||
1965 | devices count up from there */ | ||
1966 | dev->dev_addr[i] = bd->bi_enetaddr[i] & ~3; | ||
1967 | dev->dev_addr[i] += 1 + fip->fc_fccnum; | ||
1968 | *eap++ = dev->dev_addr[i]; | ||
1969 | } | ||
1970 | #else | ||
1971 | #ifndef CONFIG_RPX8260 | ||
1972 | if (i == 3) { | ||
1973 | dev->dev_addr[i] = bd->bi_enetaddr[i]; | ||
1974 | dev->dev_addr[i] |= (1 << (7 - fip->fc_fccnum)); | ||
1975 | *eap++ = dev->dev_addr[i]; | ||
1976 | } else | ||
1977 | #endif | ||
1978 | { | ||
1979 | *eap++ = dev->dev_addr[i] = bd->bi_enetaddr[i]; | ||
1980 | } | ||
1981 | #endif | ||
1982 | } | ||
1983 | |||
1984 | ep->fen_taddrh = 0; | ||
1985 | ep->fen_taddrm = 0; | ||
1986 | ep->fen_taddrl = 0; | ||
1987 | |||
1988 | ep->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */ | ||
1989 | ep->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */ | ||
1990 | |||
1991 | /* Clear stat counters, in case we ever enable RMON. | ||
1992 | */ | ||
1993 | ep->fen_octc = 0; | ||
1994 | ep->fen_colc = 0; | ||
1995 | ep->fen_broc = 0; | ||
1996 | ep->fen_mulc = 0; | ||
1997 | ep->fen_uspc = 0; | ||
1998 | ep->fen_frgc = 0; | ||
1999 | ep->fen_ospc = 0; | ||
2000 | ep->fen_jbrc = 0; | ||
2001 | ep->fen_p64c = 0; | ||
2002 | ep->fen_p65c = 0; | ||
2003 | ep->fen_p128c = 0; | ||
2004 | ep->fen_p256c = 0; | ||
2005 | ep->fen_p512c = 0; | ||
2006 | ep->fen_p1024c = 0; | ||
2007 | |||
2008 | ep->fen_rfthr = 0; /* Suggested by manual */ | ||
2009 | ep->fen_rfcnt = 0; | ||
2010 | ep->fen_cftype = 0; | ||
2011 | |||
2012 | /* Now allocate the host memory pages and initialize the | ||
2013 | * buffer descriptors. | ||
2014 | */ | ||
2015 | bdp = cep->tx_bd_base; | ||
2016 | for (i=0; i<TX_RING_SIZE; i++) { | ||
2017 | |||
2018 | /* Initialize the BD for every fragment in the page. | ||
2019 | */ | ||
2020 | bdp->cbd_sc = 0; | ||
2021 | bdp->cbd_datlen = 0; | ||
2022 | bdp->cbd_bufaddr = 0; | ||
2023 | bdp++; | ||
2024 | } | ||
2025 | |||
2026 | /* Set the last buffer to wrap. | ||
2027 | */ | ||
2028 | bdp--; | ||
2029 | bdp->cbd_sc |= BD_SC_WRAP; | ||
2030 | |||
2031 | bdp = cep->rx_bd_base; | ||
2032 | for (i=0; i<FCC_ENET_RX_PAGES; i++) { | ||
2033 | |||
2034 | /* Allocate a page. | ||
2035 | */ | ||
2036 | mem_addr = __get_free_page(GFP_KERNEL); | ||
2037 | |||
2038 | /* Initialize the BD for every fragment in the page. | ||
2039 | */ | ||
2040 | for (j=0; j<FCC_ENET_RX_FRPPG; j++) { | ||
2041 | bdp->cbd_sc = BD_ENET_RX_EMPTY | BD_ENET_RX_INTR; | ||
2042 | bdp->cbd_datlen = 0; | ||
2043 | bdp->cbd_bufaddr = __pa(mem_addr); | ||
2044 | mem_addr += FCC_ENET_RX_FRSIZE; | ||
2045 | bdp++; | ||
2046 | } | ||
2047 | } | ||
2048 | |||
2049 | /* Set the last buffer to wrap. | ||
2050 | */ | ||
2051 | bdp--; | ||
2052 | bdp->cbd_sc |= BD_SC_WRAP; | ||
2053 | |||
2054 | /* Let's re-initialize the channel now. We have to do it later | ||
2055 | * than the manual describes because we have just now finished | ||
2056 | * the BD initialization. | ||
2057 | */ | ||
2058 | cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, 0x0c, | ||
2059 | CPM_CR_INIT_TRX) | CPM_CR_FLG; | ||
2060 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
2061 | |||
2062 | cep->skb_cur = cep->skb_dirty = 0; | ||
2063 | } | ||
2064 | |||
2065 | /* Let 'er rip. | ||
2066 | */ | ||
2067 | static void __init | ||
2068 | init_fcc_startup(fcc_info_t *fip, struct net_device *dev) | ||
2069 | { | ||
2070 | volatile fcc_t *fccp; | ||
2071 | struct fcc_enet_private *cep; | ||
2072 | |||
2073 | cep = (struct fcc_enet_private *)(dev->priv); | ||
2074 | fccp = cep->fccp; | ||
2075 | |||
2076 | #ifdef CONFIG_RPX8260 | ||
2077 | #ifdef PHY_INTERRUPT | ||
2078 | /* Route PHY interrupt to IRQ. The following code only works for | ||
2079 | * IRQ1 - IRQ7. It does not work for Port C interrupts. | ||
2080 | */ | ||
2081 | *((volatile u_char *) (RPX_CSR_ADDR + 13)) &= ~BCSR13_FETH_IRQMASK; | ||
2082 | *((volatile u_char *) (RPX_CSR_ADDR + 13)) |= | ||
2083 | ((PHY_INTERRUPT - SIU_INT_IRQ1 + 1) << 4); | ||
2084 | #endif | ||
2085 | /* Initialize MDIO pins. */ | ||
2086 | *((volatile u_char *) (RPX_CSR_ADDR + 4)) &= ~BCSR4_MII_MDC; | ||
2087 | *((volatile u_char *) (RPX_CSR_ADDR + 4)) |= | ||
2088 | BCSR4_MII_READ | BCSR4_MII_MDIO; | ||
2089 | /* Enable external LXT971 PHY. */ | ||
2090 | *((volatile u_char *) (RPX_CSR_ADDR + 4)) |= BCSR4_EN_PHY; | ||
2091 | udelay(1000); | ||
2092 | *((volatile u_char *) (RPX_CSR_ADDR+ 4)) |= BCSR4_EN_MII; | ||
2093 | udelay(1000); | ||
2094 | #endif /* ifdef CONFIG_RPX8260 */ | ||
2095 | |||
2096 | fccp->fcc_fcce = 0xffff; /* Clear any pending events */ | ||
2097 | |||
2098 | /* Leave FCC interrupts masked for now. Will be unmasked by | ||
2099 | * fcc_restart(). | ||
2100 | */ | ||
2101 | fccp->fcc_fccm = 0; | ||
2102 | |||
2103 | /* Install our interrupt handler. | ||
2104 | */ | ||
2105 | if (request_irq(fip->fc_interrupt, fcc_enet_interrupt, 0, "fenet", | ||
2106 | dev) < 0) | ||
2107 | printk("Can't get FCC IRQ %d\n", fip->fc_interrupt); | ||
2108 | |||
2109 | #ifdef PHY_INTERRUPT | ||
2110 | /* Make IRQn edge triggered. This does not work if PHY_INTERRUPT is | ||
2111 | * on Port C. | ||
2112 | */ | ||
2113 | ((volatile cpm2_map_t *) CPM_MAP_ADDR)->im_intctl.ic_siexr |= | ||
2114 | (1 << (14 - (PHY_INTERRUPT - SIU_INT_IRQ1))); | ||
2115 | |||
2116 | if (request_irq(PHY_INTERRUPT, mii_link_interrupt, 0, | ||
2117 | "mii", dev) < 0) | ||
2118 | printk(KERN_CRIT "Can't get MII IRQ %d\n", PHY_INTERRUPT); | ||
2119 | #endif /* PHY_INTERRUPT */ | ||
2120 | |||
2121 | /* Set GFMR to enable Ethernet operating mode. | ||
2122 | */ | ||
2123 | fccp->fcc_gfmr = (FCC_GFMR_TCI | FCC_GFMR_MODE_ENET); | ||
2124 | |||
2125 | /* Set sync/delimiters. | ||
2126 | */ | ||
2127 | fccp->fcc_fdsr = 0xd555; | ||
2128 | |||
2129 | /* Set protocol specific processing mode for Ethernet. | ||
2130 | * This has to be adjusted for Full Duplex operation after we can | ||
2131 | * determine how to detect that. | ||
2132 | */ | ||
2133 | fccp->fcc_fpsmr = FCC_PSMR_ENCRC; | ||
2134 | |||
2135 | #ifdef CONFIG_PQ2ADS | ||
2136 | /* Enable the PHY. */ | ||
2137 | *(volatile uint *)(BCSR_ADDR + 4) &= ~BCSR1_FETHIEN; | ||
2138 | *(volatile uint *)(BCSR_ADDR + 4) |= BCSR1_FETH_RST; | ||
2139 | #endif | ||
2140 | #if defined(CONFIG_PQ2ADS) || defined(CONFIG_PQ2FADS) | ||
2141 | /* Enable the 2nd PHY. */ | ||
2142 | *(volatile uint *)(BCSR_ADDR + 12) &= ~BCSR3_FETHIEN2; | ||
2143 | *(volatile uint *)(BCSR_ADDR + 12) |= BCSR3_FETH2_RST; | ||
2144 | #endif | ||
2145 | |||
2146 | #if defined(CONFIG_USE_MDIO) || defined(CONFIG_TQM8260) | ||
2147 | /* start in full duplex mode, and negotiate speed | ||
2148 | */ | ||
2149 | fcc_restart (dev, 1); | ||
2150 | #else | ||
2151 | /* start in half duplex mode | ||
2152 | */ | ||
2153 | fcc_restart (dev, 0); | ||
2154 | #endif | ||
2155 | } | ||
2156 | |||
2157 | #ifdef CONFIG_USE_MDIO | ||
2158 | /* MII command/status interface. | ||
2159 | * I'm not going to describe all of the details. You can find the | ||
2160 | * protocol definition in many other places, including the data sheet | ||
2161 | * of most PHY parts. | ||
2162 | * I wonder what "they" were thinking (maybe weren't) when they leave | ||
2163 | * the I2C in the CPM but I have to toggle these bits...... | ||
2164 | */ | ||
2165 | #ifdef CONFIG_RPX8260 | ||
2166 | /* The EP8260 has the MDIO pins in a BCSR instead of on Port C | ||
2167 | * like most other boards. | ||
2168 | */ | ||
2169 | #define MDIO_ADDR ((volatile u_char *)(RPX_CSR_ADDR + 4)) | ||
2170 | #define MAKE_MDIO_OUTPUT *MDIO_ADDR &= ~BCSR4_MII_READ | ||
2171 | #define MAKE_MDIO_INPUT *MDIO_ADDR |= BCSR4_MII_READ | BCSR4_MII_MDIO | ||
2172 | #define OUT_MDIO(bit) \ | ||
2173 | if (bit) \ | ||
2174 | *MDIO_ADDR |= BCSR4_MII_MDIO; \ | ||
2175 | else \ | ||
2176 | *MDIO_ADDR &= ~BCSR4_MII_MDIO; | ||
2177 | #define IN_MDIO (*MDIO_ADDR & BCSR4_MII_MDIO) | ||
2178 | #define OUT_MDC(bit) \ | ||
2179 | if (bit) \ | ||
2180 | *MDIO_ADDR |= BCSR4_MII_MDC; \ | ||
2181 | else \ | ||
2182 | *MDIO_ADDR &= ~BCSR4_MII_MDC; | ||
2183 | #else /* ifdef CONFIG_RPX8260 */ | ||
2184 | /* This is for the usual case where the MDIO pins are on Port C. | ||
2185 | */ | ||
2186 | #define MDIO_ADDR (((volatile cpm2_map_t *)CPM_MAP_ADDR)->im_ioport) | ||
2187 | #define MAKE_MDIO_OUTPUT MDIO_ADDR.iop_pdirc |= fip->fc_mdio | ||
2188 | #define MAKE_MDIO_INPUT MDIO_ADDR.iop_pdirc &= ~fip->fc_mdio | ||
2189 | #define OUT_MDIO(bit) \ | ||
2190 | if (bit) \ | ||
2191 | MDIO_ADDR.iop_pdatc |= fip->fc_mdio; \ | ||
2192 | else \ | ||
2193 | MDIO_ADDR.iop_pdatc &= ~fip->fc_mdio; | ||
2194 | #define IN_MDIO ((MDIO_ADDR.iop_pdatc) & fip->fc_mdio) | ||
2195 | #define OUT_MDC(bit) \ | ||
2196 | if (bit) \ | ||
2197 | MDIO_ADDR.iop_pdatc |= fip->fc_mdck; \ | ||
2198 | else \ | ||
2199 | MDIO_ADDR.iop_pdatc &= ~fip->fc_mdck; | ||
2200 | #endif /* ifdef CONFIG_RPX8260 */ | ||
2201 | |||
2202 | static uint | ||
2203 | mii_send_receive(fcc_info_t *fip, uint cmd) | ||
2204 | { | ||
2205 | uint retval; | ||
2206 | int read_op, i, off; | ||
2207 | const int us = 1; | ||
2208 | |||
2209 | read_op = ((cmd & 0xf0000000) == 0x60000000); | ||
2210 | |||
2211 | /* Write preamble | ||
2212 | */ | ||
2213 | OUT_MDIO(1); | ||
2214 | MAKE_MDIO_OUTPUT; | ||
2215 | OUT_MDIO(1); | ||
2216 | for (i = 0; i < 32; i++) | ||
2217 | { | ||
2218 | udelay(us); | ||
2219 | OUT_MDC(1); | ||
2220 | udelay(us); | ||
2221 | OUT_MDC(0); | ||
2222 | } | ||
2223 | |||
2224 | /* Write data | ||
2225 | */ | ||
2226 | for (i = 0, off = 31; i < (read_op ? 14 : 32); i++, --off) | ||
2227 | { | ||
2228 | OUT_MDIO((cmd >> off) & 0x00000001); | ||
2229 | udelay(us); | ||
2230 | OUT_MDC(1); | ||
2231 | udelay(us); | ||
2232 | OUT_MDC(0); | ||
2233 | } | ||
2234 | |||
2235 | retval = cmd; | ||
2236 | |||
2237 | if (read_op) | ||
2238 | { | ||
2239 | retval >>= 16; | ||
2240 | |||
2241 | MAKE_MDIO_INPUT; | ||
2242 | udelay(us); | ||
2243 | OUT_MDC(1); | ||
2244 | udelay(us); | ||
2245 | OUT_MDC(0); | ||
2246 | |||
2247 | for (i = 0; i < 16; i++) | ||
2248 | { | ||
2249 | udelay(us); | ||
2250 | OUT_MDC(1); | ||
2251 | udelay(us); | ||
2252 | retval <<= 1; | ||
2253 | if (IN_MDIO) | ||
2254 | retval++; | ||
2255 | OUT_MDC(0); | ||
2256 | } | ||
2257 | } | ||
2258 | |||
2259 | MAKE_MDIO_INPUT; | ||
2260 | udelay(us); | ||
2261 | OUT_MDC(1); | ||
2262 | udelay(us); | ||
2263 | OUT_MDC(0); | ||
2264 | |||
2265 | return retval; | ||
2266 | } | ||
2267 | #endif /* CONFIG_USE_MDIO */ | ||
2268 | |||
2269 | static void | ||
2270 | fcc_stop(struct net_device *dev) | ||
2271 | { | ||
2272 | struct fcc_enet_private *fep= (struct fcc_enet_private *)(dev->priv); | ||
2273 | volatile fcc_t *fccp = fep->fccp; | ||
2274 | fcc_info_t *fip = fep->fip; | ||
2275 | volatile fcc_enet_t *ep = fep->ep; | ||
2276 | volatile cpm_cpm2_t *cp = cpmp; | ||
2277 | volatile cbd_t *bdp; | ||
2278 | int i; | ||
2279 | |||
2280 | if ((fccp->fcc_gfmr & (FCC_GFMR_ENR | FCC_GFMR_ENT)) == 0) | ||
2281 | return; /* already down */ | ||
2282 | |||
2283 | fccp->fcc_fccm = 0; | ||
2284 | |||
2285 | /* issue the graceful stop tx command */ | ||
2286 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
2287 | cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, | ||
2288 | 0x0c, CPM_CR_GRA_STOP_TX) | CPM_CR_FLG; | ||
2289 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
2290 | |||
2291 | /* Disable transmit/receive */ | ||
2292 | fccp->fcc_gfmr &= ~(FCC_GFMR_ENR | FCC_GFMR_ENT); | ||
2293 | |||
2294 | /* issue the restart tx command */ | ||
2295 | fccp->fcc_fcce = FCC_ENET_GRA; | ||
2296 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
2297 | cp->cp_cpcr = mk_cr_cmd(fip->fc_cpmpage, fip->fc_cpmblock, | ||
2298 | 0x0c, CPM_CR_RESTART_TX) | CPM_CR_FLG; | ||
2299 | while (cp->cp_cpcr & CPM_CR_FLG); | ||
2300 | |||
2301 | /* free tx buffers */ | ||
2302 | fep->skb_cur = fep->skb_dirty = 0; | ||
2303 | for (i=0; i<=TX_RING_MOD_MASK; i++) { | ||
2304 | if (fep->tx_skbuff[i] != NULL) { | ||
2305 | dev_kfree_skb(fep->tx_skbuff[i]); | ||
2306 | fep->tx_skbuff[i] = NULL; | ||
2307 | } | ||
2308 | } | ||
2309 | fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; | ||
2310 | fep->tx_free = TX_RING_SIZE; | ||
2311 | ep->fen_genfcc.fcc_tbptr = ep->fen_genfcc.fcc_tbase; | ||
2312 | |||
2313 | /* Initialize the tx buffer descriptors. */ | ||
2314 | bdp = fep->tx_bd_base; | ||
2315 | for (i=0; i<TX_RING_SIZE; i++) { | ||
2316 | bdp->cbd_sc = 0; | ||
2317 | bdp->cbd_datlen = 0; | ||
2318 | bdp->cbd_bufaddr = 0; | ||
2319 | bdp++; | ||
2320 | } | ||
2321 | /* Set the last buffer to wrap. */ | ||
2322 | bdp--; | ||
2323 | bdp->cbd_sc |= BD_SC_WRAP; | ||
2324 | } | ||
2325 | |||
2326 | static void | ||
2327 | fcc_restart(struct net_device *dev, int duplex) | ||
2328 | { | ||
2329 | struct fcc_enet_private *fep = (struct fcc_enet_private *)(dev->priv); | ||
2330 | volatile fcc_t *fccp = fep->fccp; | ||
2331 | |||
2332 | /* stop any transmissions in progress */ | ||
2333 | fcc_stop(dev); | ||
2334 | |||
2335 | if (duplex) | ||
2336 | fccp->fcc_fpsmr |= FCC_PSMR_FDE | FCC_PSMR_LPB; | ||
2337 | else | ||
2338 | fccp->fcc_fpsmr &= ~(FCC_PSMR_FDE | FCC_PSMR_LPB); | ||
2339 | |||
2340 | /* Enable interrupts for transmit error, complete frame | ||
2341 | * received, and any transmit buffer we have also set the | ||
2342 | * interrupt flag. | ||
2343 | */ | ||
2344 | fccp->fcc_fccm = (FCC_ENET_TXE | FCC_ENET_RXF | FCC_ENET_TXB); | ||
2345 | |||
2346 | /* Enable transmit/receive */ | ||
2347 | fccp->fcc_gfmr |= FCC_GFMR_ENR | FCC_GFMR_ENT; | ||
2348 | } | ||
2349 | |||
2350 | static int | ||
2351 | fcc_enet_open(struct net_device *dev) | ||
2352 | { | ||
2353 | struct fcc_enet_private *fep = dev->priv; | ||
2354 | |||
2355 | #ifdef CONFIG_USE_MDIO | ||
2356 | fep->sequence_done = 0; | ||
2357 | fep->link = 0; | ||
2358 | |||
2359 | if (fep->phy) { | ||
2360 | fcc_restart(dev, 0); /* always start in half-duplex */ | ||
2361 | mii_do_cmd(dev, fep->phy->ack_int); | ||
2362 | mii_do_cmd(dev, fep->phy->config); | ||
2363 | mii_do_cmd(dev, phy_cmd_config); /* display configuration */ | ||
2364 | while(!fep->sequence_done) | ||
2365 | schedule(); | ||
2366 | |||
2367 | mii_do_cmd(dev, fep->phy->startup); | ||
2368 | netif_start_queue(dev); | ||
2369 | return 0; /* Success */ | ||
2370 | } | ||
2371 | return -ENODEV; /* No PHY we understand */ | ||
2372 | #else | ||
2373 | fep->link = 1; | ||
2374 | fcc_restart(dev, 0); /* always start in half-duplex */ | ||
2375 | netif_start_queue(dev); | ||
2376 | return 0; /* Always succeed */ | ||
2377 | #endif /* CONFIG_USE_MDIO */ | ||
2378 | } | ||
2379 | |||