diff options
author | Bryan Wu <bryan.wu@analog.com> | 2007-07-17 02:43:44 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-18 18:38:25 -0400 |
commit | e190d6b140079c104ba57e5130a9b4ebea618e92 (patch) | |
tree | 9c7230ac7520ac1a4afe7903f8d212951643e67d | |
parent | 308a90683da9a3e3da1023a88496f76f95c5dcd8 (diff) |
Blackfin ethernet driver: on chip ethernet MAC controller driver
This patch implements the driver necessary use the Analog Devices
Blackfin processor's on-chip ethernet MAC controller.
[try#2]
- add timeout control
- kill dma_config_reg bitfields
- some trivial cleanup
[try#3]
- add endianess check
- add DRV_NAME, DRV_VERSION... driver information string
- add some comments for silicon anomaly and dma API confusion
- some code trivial cleanup
[try#4]
- add Blackfin latest GPIO pin mux opertion with Michael Hennerich's
help and Dan's review
- rewrite the DMA descriptor list operation in a more readable way
by Joe's review
[try#5]
- cleanup some coding style by Joe's review.
[try#6]
- 1.1 version fix a bug when set up multicast list pointed by Mr. yoshfuji
- rearrange the desc_list_free function.
Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Cc: Michael Buesch <mb@bu3sch.de>
Cc: Mike Frysinger <vapier.adi@gmail.com>
Cc: Jeff Garzik <jeff@garzik.org>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dan Williams <dcbw@redhat.com>
Cc: Joe Perches <joe@perches.com>
Cc: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | MAINTAINERS | 7 | ||||
-rw-r--r-- | drivers/net/Kconfig | 44 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/bfin_mac.c | 1009 | ||||
-rw-r--r-- | drivers/net/bfin_mac.h | 132 |
5 files changed, 1193 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e78f62f13bac..f6b2665ccb2b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -732,6 +732,13 @@ L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) | |||
732 | W: http://blackfin.uclinux.org | 732 | W: http://blackfin.uclinux.org |
733 | S: Supported | 733 | S: Supported |
734 | 734 | ||
735 | BLACKFIN EMAC DRIVER | ||
736 | P: Bryan Wu | ||
737 | M: bryan.wu@analog.com | ||
738 | L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only) | ||
739 | W: http://blackfin.uclinux.org | ||
740 | S: Supported | ||
741 | |||
735 | BLACKFIN RTC DRIVER | 742 | BLACKFIN RTC DRIVER |
736 | P: Mike Frysinger | 743 | P: Mike Frysinger |
737 | M: michael.frysinger@analog.com | 744 | M: michael.frysinger@analog.com |
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5fb659f8b20e..3073f679584b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -838,6 +838,50 @@ config ULTRA32 | |||
838 | <file:Documentation/networking/net-modules.txt>. The module | 838 | <file:Documentation/networking/net-modules.txt>. The module |
839 | will be called smc-ultra32. | 839 | will be called smc-ultra32. |
840 | 840 | ||
841 | config BFIN_MAC | ||
842 | tristate "Blackfin 536/537 on-chip mac support" | ||
843 | depends on NET_ETHERNET && (BF537 || BF536) && (!BF537_PORT_H) | ||
844 | select CRC32 | ||
845 | select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE | ||
846 | help | ||
847 | This is the driver for blackfin on-chip mac device. Say Y if you want it | ||
848 | compiled into the kernel. This driver is also available as a module | ||
849 | ( = code which can be inserted in and removed from the running kernel | ||
850 | whenever you want). The module will be called bfin_mac. | ||
851 | |||
852 | config BFIN_MAC_USE_L1 | ||
853 | bool "Use L1 memory for rx/tx packets" | ||
854 | depends on BFIN_MAC && BF537 | ||
855 | default y | ||
856 | help | ||
857 | To get maximum network performace, you should use L1 memory as rx/tx buffers. | ||
858 | Say N here if you want to reserve L1 memory for other uses. | ||
859 | |||
860 | config BFIN_TX_DESC_NUM | ||
861 | int "Number of transmit buffer packets" | ||
862 | depends on BFIN_MAC | ||
863 | range 6 10 if BFIN_MAC_USE_L1 | ||
864 | range 10 100 | ||
865 | default "10" | ||
866 | help | ||
867 | Set the number of buffer packets used in driver. | ||
868 | |||
869 | config BFIN_RX_DESC_NUM | ||
870 | int "Number of receive buffer packets" | ||
871 | depends on BFIN_MAC | ||
872 | range 20 100 if BFIN_MAC_USE_L1 | ||
873 | range 20 800 | ||
874 | default "20" | ||
875 | help | ||
876 | Set the number of buffer packets used in driver. | ||
877 | |||
878 | config BFIN_MAC_RMII | ||
879 | bool "RMII PHY Interface (EXPERIMENTAL)" | ||
880 | depends on BFIN_MAC && EXPERIMENTAL | ||
881 | default n | ||
882 | help | ||
883 | Use Reduced PHY MII Interface | ||
884 | |||
841 | config SMC9194 | 885 | config SMC9194 |
842 | tristate "SMC 9194 support" | 886 | tristate "SMC 9194 support" |
843 | depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN) | 887 | depends on NET_VENDOR_SMC && (ISA || MAC && BROKEN) |
diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 0e286ab8855a..aaaa0a04bb46 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile | |||
@@ -200,6 +200,7 @@ obj-$(CONFIG_S2IO) += s2io.o | |||
200 | obj-$(CONFIG_MYRI10GE) += myri10ge/ | 200 | obj-$(CONFIG_MYRI10GE) += myri10ge/ |
201 | obj-$(CONFIG_SMC91X) += smc91x.o | 201 | obj-$(CONFIG_SMC91X) += smc91x.o |
202 | obj-$(CONFIG_SMC911X) += smc911x.o | 202 | obj-$(CONFIG_SMC911X) += smc911x.o |
203 | obj-$(CONFIG_BFIN_MAC) += bfin_mac.o | ||
203 | obj-$(CONFIG_DM9000) += dm9000.o | 204 | obj-$(CONFIG_DM9000) += dm9000.o |
204 | obj-$(CONFIG_FEC_8XX) += fec_8xx/ | 205 | obj-$(CONFIG_FEC_8XX) += fec_8xx/ |
205 | obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o | 206 | obj-$(CONFIG_PASEMI_MAC) += pasemi_mac.o |
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c new file mode 100644 index 000000000000..9a08d656f1ce --- /dev/null +++ b/drivers/net/bfin_mac.c | |||
@@ -0,0 +1,1009 @@ | |||
1 | /* | ||
2 | * File: drivers/net/bfin_mac.c | ||
3 | * Based on: | ||
4 | * Maintainer: | ||
5 | * Bryan Wu <bryan.wu@analog.com> | ||
6 | * | ||
7 | * Original author: | ||
8 | * Luke Yang <luke.yang@analog.com> | ||
9 | * | ||
10 | * Created: | ||
11 | * Description: | ||
12 | * | ||
13 | * Modified: | ||
14 | * Copyright 2004-2006 Analog Devices Inc. | ||
15 | * | ||
16 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
17 | * | ||
18 | * This program is free software ; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation ; either version 2, or (at your option) | ||
21 | * any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program ; see the file COPYING. | ||
30 | * If not, write to the Free Software Foundation, | ||
31 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
32 | */ | ||
33 | |||
34 | #include <linux/init.h> | ||
35 | #include <linux/module.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/sched.h> | ||
38 | #include <linux/slab.h> | ||
39 | #include <linux/delay.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <linux/errno.h> | ||
42 | #include <linux/irq.h> | ||
43 | #include <linux/io.h> | ||
44 | #include <linux/ioport.h> | ||
45 | #include <linux/crc32.h> | ||
46 | #include <linux/device.h> | ||
47 | #include <linux/spinlock.h> | ||
48 | #include <linux/ethtool.h> | ||
49 | #include <linux/mii.h> | ||
50 | |||
51 | #include <linux/netdevice.h> | ||
52 | #include <linux/etherdevice.h> | ||
53 | #include <linux/skbuff.h> | ||
54 | |||
55 | #include <linux/platform_device.h> | ||
56 | #include <linux/netdevice.h> | ||
57 | #include <linux/etherdevice.h> | ||
58 | #include <linux/skbuff.h> | ||
59 | |||
60 | #include <asm/dma.h> | ||
61 | #include <linux/dma-mapping.h> | ||
62 | |||
63 | #include <asm/blackfin.h> | ||
64 | #include <asm/cacheflush.h> | ||
65 | #include <asm/portmux.h> | ||
66 | |||
67 | #include "bfin_mac.h" | ||
68 | |||
69 | #define DRV_NAME "bfin_mac" | ||
70 | #define DRV_VERSION "1.1" | ||
71 | #define DRV_AUTHOR "Bryan Wu, Luke Yang" | ||
72 | #define DRV_DESC "Blackfin BF53[67] on-chip Ethernet MAC driver" | ||
73 | |||
74 | MODULE_AUTHOR(DRV_AUTHOR); | ||
75 | MODULE_LICENSE("GPL"); | ||
76 | MODULE_DESCRIPTION(DRV_DESC); | ||
77 | |||
78 | #if defined(CONFIG_BFIN_MAC_USE_L1) | ||
79 | # define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) | ||
80 | # define bfin_mac_free(dma_handle, ptr) l1_data_sram_free(ptr) | ||
81 | #else | ||
82 | # define bfin_mac_alloc(dma_handle, size) \ | ||
83 | dma_alloc_coherent(NULL, size, dma_handle, GFP_KERNEL) | ||
84 | # define bfin_mac_free(dma_handle, ptr) \ | ||
85 | dma_free_coherent(NULL, sizeof(*ptr), ptr, dma_handle) | ||
86 | #endif | ||
87 | |||
88 | #define PKT_BUF_SZ 1580 | ||
89 | |||
90 | #define MAX_TIMEOUT_CNT 500 | ||
91 | |||
92 | /* pointers to maintain transmit list */ | ||
93 | static struct net_dma_desc_tx *tx_list_head; | ||
94 | static struct net_dma_desc_tx *tx_list_tail; | ||
95 | static struct net_dma_desc_rx *rx_list_head; | ||
96 | static struct net_dma_desc_rx *rx_list_tail; | ||
97 | static struct net_dma_desc_rx *current_rx_ptr; | ||
98 | static struct net_dma_desc_tx *current_tx_ptr; | ||
99 | static struct net_dma_desc_tx *tx_desc; | ||
100 | static struct net_dma_desc_rx *rx_desc; | ||
101 | |||
102 | static void desc_list_free(void) | ||
103 | { | ||
104 | struct net_dma_desc_rx *r; | ||
105 | struct net_dma_desc_tx *t; | ||
106 | int i; | ||
107 | #if !defined(CONFIG_BFIN_MAC_USE_L1) | ||
108 | dma_addr_t dma_handle = 0; | ||
109 | #endif | ||
110 | |||
111 | if (tx_desc) { | ||
112 | t = tx_list_head; | ||
113 | for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { | ||
114 | if (t) { | ||
115 | if (t->skb) { | ||
116 | dev_kfree_skb(t->skb); | ||
117 | t->skb = NULL; | ||
118 | } | ||
119 | t = t->next; | ||
120 | } | ||
121 | } | ||
122 | bfin_mac_free(dma_handle, tx_desc); | ||
123 | } | ||
124 | |||
125 | if (rx_desc) { | ||
126 | r = rx_list_head; | ||
127 | for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { | ||
128 | if (r) { | ||
129 | if (r->skb) { | ||
130 | dev_kfree_skb(r->skb); | ||
131 | r->skb = NULL; | ||
132 | } | ||
133 | r = r->next; | ||
134 | } | ||
135 | } | ||
136 | bfin_mac_free(dma_handle, rx_desc); | ||
137 | } | ||
138 | } | ||
139 | |||
140 | static int desc_list_init(void) | ||
141 | { | ||
142 | int i; | ||
143 | struct sk_buff *new_skb; | ||
144 | #if !defined(CONFIG_BFIN_MAC_USE_L1) | ||
145 | /* | ||
146 | * This dma_handle is useless in Blackfin dma_alloc_coherent(). | ||
147 | * The real dma handler is the return value of dma_alloc_coherent(). | ||
148 | */ | ||
149 | dma_addr_t dma_handle; | ||
150 | #endif | ||
151 | |||
152 | tx_desc = bfin_mac_alloc(&dma_handle, | ||
153 | sizeof(struct net_dma_desc_tx) * | ||
154 | CONFIG_BFIN_TX_DESC_NUM); | ||
155 | if (tx_desc == NULL) | ||
156 | goto init_error; | ||
157 | |||
158 | rx_desc = bfin_mac_alloc(&dma_handle, | ||
159 | sizeof(struct net_dma_desc_rx) * | ||
160 | CONFIG_BFIN_RX_DESC_NUM); | ||
161 | if (rx_desc == NULL) | ||
162 | goto init_error; | ||
163 | |||
164 | /* init tx_list */ | ||
165 | tx_list_head = tx_list_tail = tx_desc; | ||
166 | |||
167 | for (i = 0; i < CONFIG_BFIN_TX_DESC_NUM; i++) { | ||
168 | struct net_dma_desc_tx *t = tx_desc + i; | ||
169 | struct dma_descriptor *a = &(t->desc_a); | ||
170 | struct dma_descriptor *b = &(t->desc_b); | ||
171 | |||
172 | /* | ||
173 | * disable DMA | ||
174 | * read from memory WNR = 0 | ||
175 | * wordsize is 32 bits | ||
176 | * 6 half words is desc size | ||
177 | * large desc flow | ||
178 | */ | ||
179 | a->config = WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; | ||
180 | a->start_addr = (unsigned long)t->packet; | ||
181 | a->x_count = 0; | ||
182 | a->next_dma_desc = b; | ||
183 | |||
184 | /* | ||
185 | * enabled DMA | ||
186 | * write to memory WNR = 1 | ||
187 | * wordsize is 32 bits | ||
188 | * disable interrupt | ||
189 | * 6 half words is desc size | ||
190 | * large desc flow | ||
191 | */ | ||
192 | b->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; | ||
193 | b->start_addr = (unsigned long)(&(t->status)); | ||
194 | b->x_count = 0; | ||
195 | |||
196 | t->skb = NULL; | ||
197 | tx_list_tail->desc_b.next_dma_desc = a; | ||
198 | tx_list_tail->next = t; | ||
199 | tx_list_tail = t; | ||
200 | } | ||
201 | tx_list_tail->next = tx_list_head; /* tx_list is a circle */ | ||
202 | tx_list_tail->desc_b.next_dma_desc = &(tx_list_head->desc_a); | ||
203 | current_tx_ptr = tx_list_head; | ||
204 | |||
205 | /* init rx_list */ | ||
206 | rx_list_head = rx_list_tail = rx_desc; | ||
207 | |||
208 | for (i = 0; i < CONFIG_BFIN_RX_DESC_NUM; i++) { | ||
209 | struct net_dma_desc_rx *r = rx_desc + i; | ||
210 | struct dma_descriptor *a = &(r->desc_a); | ||
211 | struct dma_descriptor *b = &(r->desc_b); | ||
212 | |||
213 | /* allocate a new skb for next time receive */ | ||
214 | new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); | ||
215 | if (!new_skb) { | ||
216 | printk(KERN_NOTICE DRV_NAME | ||
217 | ": init: low on mem - packet dropped\n"); | ||
218 | goto init_error; | ||
219 | } | ||
220 | skb_reserve(new_skb, 2); | ||
221 | r->skb = new_skb; | ||
222 | |||
223 | /* | ||
224 | * enabled DMA | ||
225 | * write to memory WNR = 1 | ||
226 | * wordsize is 32 bits | ||
227 | * disable interrupt | ||
228 | * 6 half words is desc size | ||
229 | * large desc flow | ||
230 | */ | ||
231 | a->config = DMAEN | WNR | WDSIZE_32 | NDSIZE_6 | DMAFLOW_LARGE; | ||
232 | /* since RXDWA is enabled */ | ||
233 | a->start_addr = (unsigned long)new_skb->data - 2; | ||
234 | a->x_count = 0; | ||
235 | a->next_dma_desc = b; | ||
236 | |||
237 | /* | ||
238 | * enabled DMA | ||
239 | * write to memory WNR = 1 | ||
240 | * wordsize is 32 bits | ||
241 | * enable interrupt | ||
242 | * 6 half words is desc size | ||
243 | * large desc flow | ||
244 | */ | ||
245 | b->config = DMAEN | WNR | WDSIZE_32 | DI_EN | | ||
246 | NDSIZE_6 | DMAFLOW_LARGE; | ||
247 | b->start_addr = (unsigned long)(&(r->status)); | ||
248 | b->x_count = 0; | ||
249 | |||
250 | rx_list_tail->desc_b.next_dma_desc = a; | ||
251 | rx_list_tail->next = r; | ||
252 | rx_list_tail = r; | ||
253 | } | ||
254 | rx_list_tail->next = rx_list_head; /* rx_list is a circle */ | ||
255 | rx_list_tail->desc_b.next_dma_desc = &(rx_list_head->desc_a); | ||
256 | current_rx_ptr = rx_list_head; | ||
257 | |||
258 | return 0; | ||
259 | |||
260 | init_error: | ||
261 | desc_list_free(); | ||
262 | printk(KERN_ERR DRV_NAME ": kmalloc failed\n"); | ||
263 | return -ENOMEM; | ||
264 | } | ||
265 | |||
266 | |||
267 | /*---PHY CONTROL AND CONFIGURATION-----------------------------------------*/ | ||
268 | |||
269 | /* Set FER regs to MUX in Ethernet pins */ | ||
270 | static int setup_pin_mux(int action) | ||
271 | { | ||
272 | #if defined(CONFIG_BFIN_MAC_RMII) | ||
273 | u16 pin_req[] = P_RMII0; | ||
274 | #else | ||
275 | u16 pin_req[] = P_MII0; | ||
276 | #endif | ||
277 | |||
278 | if (action) { | ||
279 | if (peripheral_request_list(pin_req, DRV_NAME)) { | ||
280 | printk(KERN_ERR DRV_NAME | ||
281 | ": Requesting Peripherals failed\n"); | ||
282 | return -EFAULT; | ||
283 | } | ||
284 | } else | ||
285 | peripheral_free_list(pin_req); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | /* Wait until the previous MDC/MDIO transaction has completed */ | ||
291 | static void poll_mdc_done(void) | ||
292 | { | ||
293 | int timeout_cnt = MAX_TIMEOUT_CNT; | ||
294 | |||
295 | /* poll the STABUSY bit */ | ||
296 | while ((bfin_read_EMAC_STAADD()) & STABUSY) { | ||
297 | mdelay(10); | ||
298 | if (timeout_cnt-- < 0) { | ||
299 | printk(KERN_ERR DRV_NAME | ||
300 | ": wait MDC/MDIO transaction to complete timeout\n"); | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | } | ||
305 | |||
306 | /* Read an off-chip register in a PHY through the MDC/MDIO port */ | ||
307 | static u16 read_phy_reg(u16 PHYAddr, u16 RegAddr) | ||
308 | { | ||
309 | poll_mdc_done(); | ||
310 | /* read mode */ | ||
311 | bfin_write_EMAC_STAADD(SET_PHYAD(PHYAddr) | | ||
312 | SET_REGAD(RegAddr) | | ||
313 | STABUSY); | ||
314 | poll_mdc_done(); | ||
315 | |||
316 | return (u16) bfin_read_EMAC_STADAT(); | ||
317 | } | ||
318 | |||
319 | /* Write an off-chip register in a PHY through the MDC/MDIO port */ | ||
320 | static void raw_write_phy_reg(u16 PHYAddr, u16 RegAddr, u32 Data) | ||
321 | { | ||
322 | bfin_write_EMAC_STADAT(Data); | ||
323 | |||
324 | /* write mode */ | ||
325 | bfin_write_EMAC_STAADD(SET_PHYAD(PHYAddr) | | ||
326 | SET_REGAD(RegAddr) | | ||
327 | STAOP | | ||
328 | STABUSY); | ||
329 | |||
330 | poll_mdc_done(); | ||
331 | } | ||
332 | |||
333 | static void write_phy_reg(u16 PHYAddr, u16 RegAddr, u32 Data) | ||
334 | { | ||
335 | poll_mdc_done(); | ||
336 | raw_write_phy_reg(PHYAddr, RegAddr, Data); | ||
337 | } | ||
338 | |||
339 | /* set up the phy */ | ||
340 | static void bf537mac_setphy(struct net_device *dev) | ||
341 | { | ||
342 | u16 phydat; | ||
343 | struct bf537mac_local *lp = netdev_priv(dev); | ||
344 | |||
345 | /* Program PHY registers */ | ||
346 | pr_debug("start setting up phy\n"); | ||
347 | |||
348 | /* issue a reset */ | ||
349 | raw_write_phy_reg(lp->PhyAddr, PHYREG_MODECTL, 0x8000); | ||
350 | |||
351 | /* wait half a second */ | ||
352 | msleep(500); | ||
353 | |||
354 | phydat = read_phy_reg(lp->PhyAddr, PHYREG_MODECTL); | ||
355 | |||
356 | /* advertise flow control supported */ | ||
357 | phydat = read_phy_reg(lp->PhyAddr, PHYREG_ANAR); | ||
358 | phydat |= (1 << 10); | ||
359 | write_phy_reg(lp->PhyAddr, PHYREG_ANAR, phydat); | ||
360 | |||
361 | phydat = 0; | ||
362 | if (lp->Negotiate) | ||
363 | phydat |= 0x1000; /* enable auto negotiation */ | ||
364 | else { | ||
365 | if (lp->FullDuplex) | ||
366 | phydat |= (1 << 8); /* full duplex */ | ||
367 | else | ||
368 | phydat &= (~(1 << 8)); /* half duplex */ | ||
369 | |||
370 | if (!lp->Port10) | ||
371 | phydat |= (1 << 13); /* 100 Mbps */ | ||
372 | else | ||
373 | phydat &= (~(1 << 13)); /* 10 Mbps */ | ||
374 | } | ||
375 | |||
376 | if (lp->Loopback) | ||
377 | phydat |= (1 << 14); /* enable TX->RX loopback */ | ||
378 | |||
379 | write_phy_reg(lp->PhyAddr, PHYREG_MODECTL, phydat); | ||
380 | msleep(500); | ||
381 | |||
382 | phydat = read_phy_reg(lp->PhyAddr, PHYREG_MODECTL); | ||
383 | /* check for SMSC PHY */ | ||
384 | if ((read_phy_reg(lp->PhyAddr, PHYREG_PHYID1) == 0x7) && | ||
385 | ((read_phy_reg(lp->PhyAddr, PHYREG_PHYID2) & 0xfff0) == 0xC0A0)) { | ||
386 | /* | ||
387 | * we have SMSC PHY so reqest interrupt | ||
388 | * on link down condition | ||
389 | */ | ||
390 | |||
391 | /* enable interrupts */ | ||
392 | write_phy_reg(lp->PhyAddr, 30, 0x0ff); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | /**************************************************************************/ | ||
397 | void setup_system_regs(struct net_device *dev) | ||
398 | { | ||
399 | int phyaddr; | ||
400 | unsigned short sysctl, phydat; | ||
401 | u32 opmode; | ||
402 | struct bf537mac_local *lp = netdev_priv(dev); | ||
403 | int count = 0; | ||
404 | |||
405 | phyaddr = lp->PhyAddr; | ||
406 | |||
407 | /* Enable PHY output */ | ||
408 | if (!(bfin_read_VR_CTL() & PHYCLKOE)) | ||
409 | bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE); | ||
410 | |||
411 | /* MDC = 2.5 MHz */ | ||
412 | sysctl = SET_MDCDIV(24); | ||
413 | /* Odd word alignment for Receive Frame DMA word */ | ||
414 | /* Configure checksum support and rcve frame word alignment */ | ||
415 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | ||
416 | sysctl |= RXDWA | RXCKS; | ||
417 | #else | ||
418 | sysctl |= RXDWA; | ||
419 | #endif | ||
420 | bfin_write_EMAC_SYSCTL(sysctl); | ||
421 | /* auto negotiation on */ | ||
422 | /* full duplex */ | ||
423 | /* 100 Mbps */ | ||
424 | phydat = PHY_ANEG_EN | PHY_DUPLEX | PHY_SPD_SET; | ||
425 | write_phy_reg(phyaddr, PHYREG_MODECTL, phydat); | ||
426 | |||
427 | /* test if full duplex supported */ | ||
428 | do { | ||
429 | msleep(100); | ||
430 | phydat = read_phy_reg(phyaddr, PHYREG_MODESTAT); | ||
431 | if (count > 30) { | ||
432 | printk(KERN_NOTICE DRV_NAME ": Link is down\n"); | ||
433 | printk(KERN_NOTICE DRV_NAME | ||
434 | "please check your network connection\n"); | ||
435 | break; | ||
436 | } | ||
437 | count++; | ||
438 | } while (!(phydat & 0x0004)); | ||
439 | |||
440 | phydat = read_phy_reg(phyaddr, PHYREG_ANLPAR); | ||
441 | |||
442 | if ((phydat & 0x0100) || (phydat & 0x0040)) { | ||
443 | opmode = FDMODE; | ||
444 | } else { | ||
445 | opmode = 0; | ||
446 | printk(KERN_INFO DRV_NAME | ||
447 | ": Network is set to half duplex\n"); | ||
448 | } | ||
449 | |||
450 | #if defined(CONFIG_BFIN_MAC_RMII) | ||
451 | opmode |= RMII; /* For Now only 100MBit are supported */ | ||
452 | #endif | ||
453 | |||
454 | bfin_write_EMAC_OPMODE(opmode); | ||
455 | |||
456 | bfin_write_EMAC_MMC_CTL(RSTC | CROLL); | ||
457 | |||
458 | /* Initialize the TX DMA channel registers */ | ||
459 | bfin_write_DMA2_X_COUNT(0); | ||
460 | bfin_write_DMA2_X_MODIFY(4); | ||
461 | bfin_write_DMA2_Y_COUNT(0); | ||
462 | bfin_write_DMA2_Y_MODIFY(0); | ||
463 | |||
464 | /* Initialize the RX DMA channel registers */ | ||
465 | bfin_write_DMA1_X_COUNT(0); | ||
466 | bfin_write_DMA1_X_MODIFY(4); | ||
467 | bfin_write_DMA1_Y_COUNT(0); | ||
468 | bfin_write_DMA1_Y_MODIFY(0); | ||
469 | } | ||
470 | |||
471 | void setup_mac_addr(u8 * mac_addr) | ||
472 | { | ||
473 | u32 addr_low = le32_to_cpu(*(__le32 *) & mac_addr[0]); | ||
474 | u16 addr_hi = le16_to_cpu(*(__le16 *) & mac_addr[4]); | ||
475 | |||
476 | /* this depends on a little-endian machine */ | ||
477 | bfin_write_EMAC_ADDRLO(addr_low); | ||
478 | bfin_write_EMAC_ADDRHI(addr_hi); | ||
479 | } | ||
480 | |||
481 | static void adjust_tx_list(void) | ||
482 | { | ||
483 | int timeout_cnt = MAX_TIMEOUT_CNT; | ||
484 | |||
485 | if (tx_list_head->status.status_word != 0 | ||
486 | && current_tx_ptr != tx_list_head) { | ||
487 | goto adjust_head; /* released something, just return; */ | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * if nothing released, check wait condition | ||
492 | * current's next can not be the head, | ||
493 | * otherwise the dma will not stop as we want | ||
494 | */ | ||
495 | if (current_tx_ptr->next->next == tx_list_head) { | ||
496 | while (tx_list_head->status.status_word == 0) { | ||
497 | mdelay(10); | ||
498 | if (tx_list_head->status.status_word != 0 | ||
499 | || !(bfin_read_DMA2_IRQ_STATUS() & 0x08)) { | ||
500 | goto adjust_head; | ||
501 | } | ||
502 | if (timeout_cnt-- < 0) { | ||
503 | printk(KERN_ERR DRV_NAME | ||
504 | ": wait for adjust tx list head timeout\n"); | ||
505 | break; | ||
506 | } | ||
507 | } | ||
508 | if (tx_list_head->status.status_word != 0) { | ||
509 | goto adjust_head; | ||
510 | } | ||
511 | } | ||
512 | |||
513 | return; | ||
514 | |||
515 | adjust_head: | ||
516 | do { | ||
517 | tx_list_head->desc_a.config &= ~DMAEN; | ||
518 | tx_list_head->status.status_word = 0; | ||
519 | if (tx_list_head->skb) { | ||
520 | dev_kfree_skb(tx_list_head->skb); | ||
521 | tx_list_head->skb = NULL; | ||
522 | } else { | ||
523 | printk(KERN_ERR DRV_NAME | ||
524 | ": no sk_buff in a transmitted frame!\n"); | ||
525 | } | ||
526 | tx_list_head = tx_list_head->next; | ||
527 | } while (tx_list_head->status.status_word != 0 | ||
528 | && current_tx_ptr != tx_list_head); | ||
529 | return; | ||
530 | |||
531 | } | ||
532 | |||
533 | static int bf537mac_hard_start_xmit(struct sk_buff *skb, | ||
534 | struct net_device *dev) | ||
535 | { | ||
536 | struct bf537mac_local *lp = netdev_priv(dev); | ||
537 | unsigned int data; | ||
538 | |||
539 | current_tx_ptr->skb = skb; | ||
540 | |||
541 | /* | ||
542 | * Is skb->data always 16-bit aligned? | ||
543 | * Do we need to memcpy((char *)(tail->packet + 2), skb->data, len)? | ||
544 | */ | ||
545 | if ((((unsigned int)(skb->data)) & 0x02) == 2) { | ||
546 | /* move skb->data to current_tx_ptr payload */ | ||
547 | data = (unsigned int)(skb->data) - 2; | ||
548 | *((unsigned short *)data) = (unsigned short)(skb->len); | ||
549 | current_tx_ptr->desc_a.start_addr = (unsigned long)data; | ||
550 | /* this is important! */ | ||
551 | blackfin_dcache_flush_range(data, (data + (skb->len)) + 2); | ||
552 | |||
553 | } else { | ||
554 | *((unsigned short *)(current_tx_ptr->packet)) = | ||
555 | (unsigned short)(skb->len); | ||
556 | memcpy((char *)(current_tx_ptr->packet + 2), skb->data, | ||
557 | (skb->len)); | ||
558 | current_tx_ptr->desc_a.start_addr = | ||
559 | (unsigned long)current_tx_ptr->packet; | ||
560 | if (current_tx_ptr->status.status_word != 0) | ||
561 | current_tx_ptr->status.status_word = 0; | ||
562 | blackfin_dcache_flush_range((unsigned int)current_tx_ptr-> | ||
563 | packet, | ||
564 | (unsigned int)(current_tx_ptr-> | ||
565 | packet + skb->len) + | ||
566 | 2); | ||
567 | } | ||
568 | |||
569 | /* enable this packet's dma */ | ||
570 | current_tx_ptr->desc_a.config |= DMAEN; | ||
571 | |||
572 | /* tx dma is running, just return */ | ||
573 | if (bfin_read_DMA2_IRQ_STATUS() & 0x08) | ||
574 | goto out; | ||
575 | |||
576 | /* tx dma is not running */ | ||
577 | bfin_write_DMA2_NEXT_DESC_PTR(&(current_tx_ptr->desc_a)); | ||
578 | /* dma enabled, read from memory, size is 6 */ | ||
579 | bfin_write_DMA2_CONFIG(current_tx_ptr->desc_a.config); | ||
580 | /* Turn on the EMAC tx */ | ||
581 | bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); | ||
582 | |||
583 | out: | ||
584 | adjust_tx_list(); | ||
585 | current_tx_ptr = current_tx_ptr->next; | ||
586 | dev->trans_start = jiffies; | ||
587 | lp->stats.tx_packets++; | ||
588 | lp->stats.tx_bytes += (skb->len); | ||
589 | return 0; | ||
590 | } | ||
591 | |||
592 | static void bf537mac_rx(struct net_device *dev) | ||
593 | { | ||
594 | struct sk_buff *skb, *new_skb; | ||
595 | struct bf537mac_local *lp = netdev_priv(dev); | ||
596 | unsigned short len; | ||
597 | |||
598 | /* allocate a new skb for next time receive */ | ||
599 | skb = current_rx_ptr->skb; | ||
600 | new_skb = dev_alloc_skb(PKT_BUF_SZ + 2); | ||
601 | if (!new_skb) { | ||
602 | printk(KERN_NOTICE DRV_NAME | ||
603 | ": rx: low on mem - packet dropped\n"); | ||
604 | lp->stats.rx_dropped++; | ||
605 | goto out; | ||
606 | } | ||
607 | /* reserve 2 bytes for RXDWA padding */ | ||
608 | skb_reserve(new_skb, 2); | ||
609 | current_rx_ptr->skb = new_skb; | ||
610 | current_rx_ptr->desc_a.start_addr = (unsigned long)new_skb->data - 2; | ||
611 | |||
612 | len = (unsigned short)((current_rx_ptr->status.status_word) & RX_FRLEN); | ||
613 | skb_put(skb, len); | ||
614 | blackfin_dcache_invalidate_range((unsigned long)skb->head, | ||
615 | (unsigned long)skb->tail); | ||
616 | |||
617 | dev->last_rx = jiffies; | ||
618 | skb->dev = dev; | ||
619 | skb->protocol = eth_type_trans(skb, dev); | ||
620 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | ||
621 | skb->csum = current_rx_ptr->status.ip_payload_csum; | ||
622 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
623 | #endif | ||
624 | |||
625 | netif_rx(skb); | ||
626 | lp->stats.rx_packets++; | ||
627 | lp->stats.rx_bytes += len; | ||
628 | current_rx_ptr->status.status_word = 0x00000000; | ||
629 | current_rx_ptr = current_rx_ptr->next; | ||
630 | |||
631 | out: | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | /* interrupt routine to handle rx and error signal */ | ||
636 | static irqreturn_t bf537mac_interrupt(int irq, void *dev_id) | ||
637 | { | ||
638 | struct net_device *dev = dev_id; | ||
639 | int number = 0; | ||
640 | |||
641 | get_one_packet: | ||
642 | if (current_rx_ptr->status.status_word == 0) { | ||
643 | /* no more new packet received */ | ||
644 | if (number == 0) { | ||
645 | if (current_rx_ptr->next->status.status_word != 0) { | ||
646 | current_rx_ptr = current_rx_ptr->next; | ||
647 | goto real_rx; | ||
648 | } | ||
649 | } | ||
650 | bfin_write_DMA1_IRQ_STATUS(bfin_read_DMA1_IRQ_STATUS() | | ||
651 | DMA_DONE | DMA_ERR); | ||
652 | return IRQ_HANDLED; | ||
653 | } | ||
654 | |||
655 | real_rx: | ||
656 | bf537mac_rx(dev); | ||
657 | number++; | ||
658 | goto get_one_packet; | ||
659 | } | ||
660 | |||
661 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
662 | static void bf537mac_poll(struct net_device *dev) | ||
663 | { | ||
664 | disable_irq(IRQ_MAC_RX); | ||
665 | bf537mac_interrupt(IRQ_MAC_RX, dev); | ||
666 | enable_irq(IRQ_MAC_RX); | ||
667 | } | ||
668 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | ||
669 | |||
670 | static void bf537mac_reset(void) | ||
671 | { | ||
672 | unsigned int opmode; | ||
673 | |||
674 | opmode = bfin_read_EMAC_OPMODE(); | ||
675 | opmode &= (~RE); | ||
676 | opmode &= (~TE); | ||
677 | /* Turn off the EMAC */ | ||
678 | bfin_write_EMAC_OPMODE(opmode); | ||
679 | } | ||
680 | |||
681 | /* | ||
682 | * Enable Interrupts, Receive, and Transmit | ||
683 | */ | ||
684 | static int bf537mac_enable(struct net_device *dev) | ||
685 | { | ||
686 | u32 opmode; | ||
687 | |||
688 | pr_debug("%s: %s\n", dev->name, __FUNCTION__); | ||
689 | |||
690 | /* Set RX DMA */ | ||
691 | bfin_write_DMA1_NEXT_DESC_PTR(&(rx_list_head->desc_a)); | ||
692 | bfin_write_DMA1_CONFIG(rx_list_head->desc_a.config); | ||
693 | |||
694 | /* Wait MII done */ | ||
695 | poll_mdc_done(); | ||
696 | |||
697 | /* We enable only RX here */ | ||
698 | /* ASTP : Enable Automatic Pad Stripping | ||
699 | PR : Promiscuous Mode for test | ||
700 | PSF : Receive frames with total length less than 64 bytes. | ||
701 | FDMODE : Full Duplex Mode | ||
702 | LB : Internal Loopback for test | ||
703 | RE : Receiver Enable */ | ||
704 | opmode = bfin_read_EMAC_OPMODE(); | ||
705 | if (opmode & FDMODE) | ||
706 | opmode |= PSF; | ||
707 | else | ||
708 | opmode |= DRO | DC | PSF; | ||
709 | opmode |= RE; | ||
710 | |||
711 | #if defined(CONFIG_BFIN_MAC_RMII) | ||
712 | opmode |= RMII; /* For Now only 100MBit are supported */ | ||
713 | #ifdef CONFIG_BF_REV_0_2 | ||
714 | opmode |= TE; | ||
715 | #endif | ||
716 | #endif | ||
717 | /* Turn on the EMAC rx */ | ||
718 | bfin_write_EMAC_OPMODE(opmode); | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | /* Our watchdog timed out. Called by the networking layer */ | ||
724 | static void bf537mac_timeout(struct net_device *dev) | ||
725 | { | ||
726 | pr_debug("%s: %s\n", dev->name, __FUNCTION__); | ||
727 | |||
728 | bf537mac_reset(); | ||
729 | |||
730 | /* reset tx queue */ | ||
731 | tx_list_tail = tx_list_head->next; | ||
732 | |||
733 | bf537mac_enable(dev); | ||
734 | |||
735 | /* We can accept TX packets again */ | ||
736 | dev->trans_start = jiffies; | ||
737 | netif_wake_queue(dev); | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | * Get the current statistics. | ||
742 | * This may be called with the card open or closed. | ||
743 | */ | ||
744 | static struct net_device_stats *bf537mac_query_statistics(struct net_device | ||
745 | *dev) | ||
746 | { | ||
747 | struct bf537mac_local *lp = netdev_priv(dev); | ||
748 | |||
749 | pr_debug("%s: %s\n", dev->name, __FUNCTION__); | ||
750 | |||
751 | return &lp->stats; | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * This routine will, depending on the values passed to it, | ||
756 | * either make it accept multicast packets, go into | ||
757 | * promiscuous mode (for TCPDUMP and cousins) or accept | ||
758 | * a select set of multicast packets | ||
759 | */ | ||
760 | static void bf537mac_set_multicast_list(struct net_device *dev) | ||
761 | { | ||
762 | u32 sysctl; | ||
763 | |||
764 | if (dev->flags & IFF_PROMISC) { | ||
765 | printk(KERN_INFO "%s: set to promisc mode\n", dev->name); | ||
766 | sysctl = bfin_read_EMAC_OPMODE(); | ||
767 | sysctl |= RAF; | ||
768 | bfin_write_EMAC_OPMODE(sysctl); | ||
769 | } else if (dev->flags & IFF_ALLMULTI || dev->mc_count) { | ||
770 | /* accept all multicast */ | ||
771 | sysctl = bfin_read_EMAC_OPMODE(); | ||
772 | sysctl |= PAM; | ||
773 | bfin_write_EMAC_OPMODE(sysctl); | ||
774 | } else { | ||
775 | /* clear promisc or multicast mode */ | ||
776 | sysctl = bfin_read_EMAC_OPMODE(); | ||
777 | sysctl &= ~(RAF | PAM); | ||
778 | bfin_write_EMAC_OPMODE(sysctl); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | /* | ||
783 | * this puts the device in an inactive state | ||
784 | */ | ||
785 | static void bf537mac_shutdown(struct net_device *dev) | ||
786 | { | ||
787 | /* Turn off the EMAC */ | ||
788 | bfin_write_EMAC_OPMODE(0x00000000); | ||
789 | /* Turn off the EMAC RX DMA */ | ||
790 | bfin_write_DMA1_CONFIG(0x0000); | ||
791 | bfin_write_DMA2_CONFIG(0x0000); | ||
792 | } | ||
793 | |||
794 | /* | ||
795 | * Open and Initialize the interface | ||
796 | * | ||
797 | * Set up everything, reset the card, etc.. | ||
798 | */ | ||
799 | static int bf537mac_open(struct net_device *dev) | ||
800 | { | ||
801 | pr_debug("%s: %s\n", dev->name, __FUNCTION__); | ||
802 | |||
803 | /* | ||
804 | * Check that the address is valid. If its not, refuse | ||
805 | * to bring the device up. The user must specify an | ||
806 | * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx | ||
807 | */ | ||
808 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
809 | printk(KERN_WARNING DRV_NAME ": no valid ethernet hw addr\n"); | ||
810 | return -EINVAL; | ||
811 | } | ||
812 | |||
813 | /* initial rx and tx list */ | ||
814 | desc_list_init(); | ||
815 | |||
816 | bf537mac_setphy(dev); | ||
817 | setup_system_regs(dev); | ||
818 | bf537mac_reset(); | ||
819 | bf537mac_enable(dev); | ||
820 | |||
821 | pr_debug("hardware init finished\n"); | ||
822 | netif_start_queue(dev); | ||
823 | netif_carrier_on(dev); | ||
824 | |||
825 | return 0; | ||
826 | } | ||
827 | |||
828 | /* | ||
829 | * | ||
830 | * this makes the board clean up everything that it can | ||
831 | * and not talk to the outside world. Caused by | ||
832 | * an 'ifconfig ethX down' | ||
833 | */ | ||
834 | static int bf537mac_close(struct net_device *dev) | ||
835 | { | ||
836 | pr_debug("%s: %s\n", dev->name, __FUNCTION__); | ||
837 | |||
838 | netif_stop_queue(dev); | ||
839 | netif_carrier_off(dev); | ||
840 | |||
841 | /* clear everything */ | ||
842 | bf537mac_shutdown(dev); | ||
843 | |||
844 | /* free the rx/tx buffers */ | ||
845 | desc_list_free(); | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int __init bf537mac_probe(struct net_device *dev) | ||
851 | { | ||
852 | struct bf537mac_local *lp = netdev_priv(dev); | ||
853 | int retval; | ||
854 | |||
855 | /* Grab the MAC address in the MAC */ | ||
856 | *(__le32 *) (&(dev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); | ||
857 | *(__le16 *) (&(dev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI()); | ||
858 | |||
859 | /* probe mac */ | ||
860 | /*todo: how to proble? which is revision_register */ | ||
861 | bfin_write_EMAC_ADDRLO(0x12345678); | ||
862 | if (bfin_read_EMAC_ADDRLO() != 0x12345678) { | ||
863 | pr_debug("can't detect bf537 mac!\n"); | ||
864 | retval = -ENODEV; | ||
865 | goto err_out; | ||
866 | } | ||
867 | |||
868 | /* set the GPIO pins to Ethernet mode */ | ||
869 | retval = setup_pin_mux(1); | ||
870 | |||
871 | if (retval) | ||
872 | return retval; | ||
873 | |||
874 | /*Is it valid? (Did bootloader initialize it?) */ | ||
875 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
876 | /* Grab the MAC from the board somehow - this is done in the | ||
877 | arch/blackfin/mach-bf537/boards/eth_mac.c */ | ||
878 | get_bf537_ether_addr(dev->dev_addr); | ||
879 | } | ||
880 | |||
881 | /* If still not valid, get a random one */ | ||
882 | if (!is_valid_ether_addr(dev->dev_addr)) { | ||
883 | random_ether_addr(dev->dev_addr); | ||
884 | } | ||
885 | |||
886 | setup_mac_addr(dev->dev_addr); | ||
887 | |||
888 | /* Fill in the fields of the device structure with ethernet values. */ | ||
889 | ether_setup(dev); | ||
890 | |||
891 | dev->open = bf537mac_open; | ||
892 | dev->stop = bf537mac_close; | ||
893 | dev->hard_start_xmit = bf537mac_hard_start_xmit; | ||
894 | dev->tx_timeout = bf537mac_timeout; | ||
895 | dev->get_stats = bf537mac_query_statistics; | ||
896 | dev->set_multicast_list = bf537mac_set_multicast_list; | ||
897 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
898 | dev->poll_controller = bf537mac_poll; | ||
899 | #endif | ||
900 | |||
901 | /* fill in some of the fields */ | ||
902 | lp->version = 1; | ||
903 | lp->PhyAddr = 0x01; | ||
904 | lp->CLKIN = 25; | ||
905 | lp->FullDuplex = 0; | ||
906 | lp->Negotiate = 1; | ||
907 | lp->FlowControl = 0; | ||
908 | spin_lock_init(&lp->lock); | ||
909 | |||
910 | /* now, enable interrupts */ | ||
911 | /* register irq handler */ | ||
912 | if (request_irq | ||
913 | (IRQ_MAC_RX, bf537mac_interrupt, IRQF_DISABLED | IRQF_SHARED, | ||
914 | "BFIN537_MAC_RX", dev)) { | ||
915 | printk(KERN_WARNING DRV_NAME | ||
916 | ": Unable to attach BlackFin MAC RX interrupt\n"); | ||
917 | return -EBUSY; | ||
918 | } | ||
919 | |||
920 | /* Enable PHY output early */ | ||
921 | if (!(bfin_read_VR_CTL() & PHYCLKOE)) | ||
922 | bfin_write_VR_CTL(bfin_read_VR_CTL() | PHYCLKOE); | ||
923 | |||
924 | retval = register_netdev(dev); | ||
925 | if (retval == 0) { | ||
926 | /* now, print out the card info, in a short format.. */ | ||
927 | printk(KERN_INFO "%s: Version %s, %s\n", | ||
928 | DRV_NAME, DRV_VERSION, DRV_DESC); | ||
929 | } | ||
930 | |||
931 | err_out: | ||
932 | return retval; | ||
933 | } | ||
934 | |||
935 | static int bfin_mac_probe(struct platform_device *pdev) | ||
936 | { | ||
937 | struct net_device *ndev; | ||
938 | |||
939 | ndev = alloc_etherdev(sizeof(struct bf537mac_local)); | ||
940 | if (!ndev) { | ||
941 | printk(KERN_WARNING DRV_NAME ": could not allocate device\n"); | ||
942 | return -ENOMEM; | ||
943 | } | ||
944 | |||
945 | SET_MODULE_OWNER(ndev); | ||
946 | SET_NETDEV_DEV(ndev, &pdev->dev); | ||
947 | |||
948 | platform_set_drvdata(pdev, ndev); | ||
949 | |||
950 | if (bf537mac_probe(ndev) != 0) { | ||
951 | platform_set_drvdata(pdev, NULL); | ||
952 | free_netdev(ndev); | ||
953 | printk(KERN_WARNING DRV_NAME ": not found\n"); | ||
954 | return -ENODEV; | ||
955 | } | ||
956 | |||
957 | return 0; | ||
958 | } | ||
959 | |||
960 | static int bfin_mac_remove(struct platform_device *pdev) | ||
961 | { | ||
962 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
963 | |||
964 | platform_set_drvdata(pdev, NULL); | ||
965 | |||
966 | unregister_netdev(ndev); | ||
967 | |||
968 | free_irq(IRQ_MAC_RX, ndev); | ||
969 | |||
970 | free_netdev(ndev); | ||
971 | |||
972 | setup_pin_mux(0); | ||
973 | |||
974 | return 0; | ||
975 | } | ||
976 | |||
977 | static int bfin_mac_suspend(struct platform_device *pdev, pm_message_t state) | ||
978 | { | ||
979 | return 0; | ||
980 | } | ||
981 | |||
982 | static int bfin_mac_resume(struct platform_device *pdev) | ||
983 | { | ||
984 | return 0; | ||
985 | } | ||
986 | |||
987 | static struct platform_driver bfin_mac_driver = { | ||
988 | .probe = bfin_mac_probe, | ||
989 | .remove = bfin_mac_remove, | ||
990 | .resume = bfin_mac_resume, | ||
991 | .suspend = bfin_mac_suspend, | ||
992 | .driver = { | ||
993 | .name = DRV_NAME, | ||
994 | }, | ||
995 | }; | ||
996 | |||
997 | static int __init bfin_mac_init(void) | ||
998 | { | ||
999 | return platform_driver_register(&bfin_mac_driver); | ||
1000 | } | ||
1001 | |||
1002 | module_init(bfin_mac_init); | ||
1003 | |||
1004 | static void __exit bfin_mac_cleanup(void) | ||
1005 | { | ||
1006 | platform_driver_unregister(&bfin_mac_driver); | ||
1007 | } | ||
1008 | |||
1009 | module_exit(bfin_mac_cleanup); | ||
diff --git a/drivers/net/bfin_mac.h b/drivers/net/bfin_mac.h new file mode 100644 index 000000000000..af87189b85fa --- /dev/null +++ b/drivers/net/bfin_mac.h | |||
@@ -0,0 +1,132 @@ | |||
1 | /* | ||
2 | * File: drivers/net/bfin_mac.c | ||
3 | * Based on: | ||
4 | * Maintainer: | ||
5 | * Bryan Wu <bryan.wu@analog.com> | ||
6 | * | ||
7 | * Original author: | ||
8 | * Luke Yang <luke.yang@analog.com> | ||
9 | * | ||
10 | * Created: | ||
11 | * Description: | ||
12 | * | ||
13 | * Modified: | ||
14 | * Copyright 2004-2006 Analog Devices Inc. | ||
15 | * | ||
16 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | ||
17 | * | ||
18 | * This program is free software ; you can redistribute it and/or modify | ||
19 | * it under the terms of the GNU General Public License as published by | ||
20 | * the Free Software Foundation ; either version 2, or (at your option) | ||
21 | * any later version. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY ; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program ; see the file COPYING. | ||
30 | * If not, write to the Free Software Foundation, | ||
31 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | * PHY REGISTER NAMES | ||
36 | */ | ||
37 | #define PHYREG_MODECTL 0x0000 | ||
38 | #define PHYREG_MODESTAT 0x0001 | ||
39 | #define PHYREG_PHYID1 0x0002 | ||
40 | #define PHYREG_PHYID2 0x0003 | ||
41 | #define PHYREG_ANAR 0x0004 | ||
42 | #define PHYREG_ANLPAR 0x0005 | ||
43 | #define PHYREG_ANER 0x0006 | ||
44 | #define PHYREG_NSR 0x0010 | ||
45 | #define PHYREG_LBREMR 0x0011 | ||
46 | #define PHYREG_REC 0x0012 | ||
47 | #define PHYREG_10CFG 0x0013 | ||
48 | #define PHYREG_PHY1_1 0x0014 | ||
49 | #define PHYREG_PHY1_2 0x0015 | ||
50 | #define PHYREG_PHY2 0x0016 | ||
51 | #define PHYREG_TW_1 0x0017 | ||
52 | #define PHYREG_TW_2 0x0018 | ||
53 | #define PHYREG_TEST 0x0019 | ||
54 | |||
55 | #define PHY_RESET 0x8000 | ||
56 | #define PHY_ANEG_EN 0x1000 | ||
57 | #define PHY_DUPLEX 0x0100 | ||
58 | #define PHY_SPD_SET 0x2000 | ||
59 | |||
60 | #define BFIN_MAC_CSUM_OFFLOAD | ||
61 | |||
62 | struct dma_descriptor { | ||
63 | struct dma_descriptor *next_dma_desc; | ||
64 | unsigned long start_addr; | ||
65 | unsigned short config; | ||
66 | unsigned short x_count; | ||
67 | }; | ||
68 | |||
69 | struct status_area_rx { | ||
70 | #if defined(BFIN_MAC_CSUM_OFFLOAD) | ||
71 | unsigned short ip_hdr_csum; /* ip header checksum */ | ||
72 | /* ip payload(udp or tcp or others) checksum */ | ||
73 | unsigned short ip_payload_csum; | ||
74 | #endif | ||
75 | unsigned long status_word; /* the frame status word */ | ||
76 | }; | ||
77 | |||
78 | struct status_area_tx { | ||
79 | unsigned long status_word; /* the frame status word */ | ||
80 | }; | ||
81 | |||
82 | /* use two descriptors for a packet */ | ||
83 | struct net_dma_desc_rx { | ||
84 | struct net_dma_desc_rx *next; | ||
85 | struct sk_buff *skb; | ||
86 | struct dma_descriptor desc_a; | ||
87 | struct dma_descriptor desc_b; | ||
88 | struct status_area_rx status; | ||
89 | }; | ||
90 | |||
91 | /* use two descriptors for a packet */ | ||
92 | struct net_dma_desc_tx { | ||
93 | struct net_dma_desc_tx *next; | ||
94 | struct sk_buff *skb; | ||
95 | struct dma_descriptor desc_a; | ||
96 | struct dma_descriptor desc_b; | ||
97 | unsigned char packet[1560]; | ||
98 | struct status_area_tx status; | ||
99 | }; | ||
100 | |||
101 | struct bf537mac_local { | ||
102 | /* | ||
103 | * these are things that the kernel wants me to keep, so users | ||
104 | * can find out semi-useless statistics of how well the card is | ||
105 | * performing | ||
106 | */ | ||
107 | struct net_device_stats stats; | ||
108 | |||
109 | int version; | ||
110 | |||
111 | int FlowEnabled; /* record if data flow is active */ | ||
112 | int EtherIntIVG; /* IVG for the ethernet interrupt */ | ||
113 | int RXIVG; /* IVG for the RX completion */ | ||
114 | int TXIVG; /* IVG for the TX completion */ | ||
115 | int PhyAddr; /* PHY address */ | ||
116 | int OpMode; /* set these bits n the OPMODE regs */ | ||
117 | int Port10; /* set port speed to 10 Mbit/s */ | ||
118 | int GenChksums; /* IP checksums to be calculated */ | ||
119 | int NoRcveLnth; /* dont insert recv length at start of buffer */ | ||
120 | int StripPads; /* remove trailing pad bytes */ | ||
121 | int FullDuplex; /* set full duplex mode */ | ||
122 | int Negotiate; /* enable auto negotiation */ | ||
123 | int Loopback; /* loopback at the PHY */ | ||
124 | int Cache; /* Buffers may be cached */ | ||
125 | int FlowControl; /* flow control active */ | ||
126 | int CLKIN; /* clock in value in MHZ */ | ||
127 | unsigned short IntMask; /* interrupt mask */ | ||
128 | unsigned char Mac[6]; /* MAC address of the board */ | ||
129 | spinlock_t lock; | ||
130 | }; | ||
131 | |||
132 | extern void get_bf537_ether_addr(char *addr); | ||