OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | --- a/drivers/net/ethernet/atheros/Makefile |
2 | +++ b/drivers/net/ethernet/atheros/Makefile |
||
3 | @@ -8,3 +8,4 @@ obj-$(CONFIG_ATL2) += atlx/ |
||
4 | obj-$(CONFIG_ATL1E) += atl1e/ |
||
5 | obj-$(CONFIG_ATL1C) += atl1c/ |
||
6 | obj-$(CONFIG_ALX) += alx/ |
||
7 | +obj-$(CONFIG_NET_AR231X) += ar231x/ |
||
8 | --- a/drivers/net/ethernet/atheros/Kconfig |
||
9 | +++ b/drivers/net/ethernet/atheros/Kconfig |
||
10 | @@ -5,7 +5,7 @@ |
||
11 | config NET_VENDOR_ATHEROS |
||
12 | bool "Atheros devices" |
||
13 | default y |
||
14 | - depends on PCI |
||
15 | + depends on (PCI || ATH25) |
||
16 | ---help--- |
||
17 | If you have a network (Ethernet) card belonging to this class, say Y. |
||
18 | |||
19 | @@ -78,4 +78,10 @@ config ALX |
||
20 | To compile this driver as a module, choose M here. The module |
||
21 | will be called alx. |
||
22 | |||
23 | +config NET_AR231X |
||
24 | + tristate "Atheros AR231X built-in Ethernet support" |
||
25 | + depends on ATH25 |
||
26 | + help |
||
27 | + Support for the AR231x/531x ethernet controller |
||
28 | + |
||
29 | endif # NET_VENDOR_ATHEROS |
||
30 | --- /dev/null |
||
31 | +++ b/drivers/net/ethernet/atheros/ar231x/Makefile |
||
32 | @@ -0,0 +1 @@ |
||
33 | +obj-$(CONFIG_NET_AR231X) += ar231x.o |
||
34 | --- /dev/null |
||
35 | +++ b/drivers/net/ethernet/atheros/ar231x/ar231x.c |
||
36 | @@ -0,0 +1,1119 @@ |
||
37 | +/* |
||
38 | + * ar231x.c: Linux driver for the Atheros AR231x Ethernet device. |
||
39 | + * |
||
40 | + * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> |
||
41 | + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> |
||
42 | + * Copyright (C) 2006-2009 Felix Fietkau <nbd@nbd.name> |
||
43 | + * |
||
44 | + * Thanks to Atheros for providing hardware and documentation |
||
45 | + * enabling me to write this driver. |
||
46 | + * |
||
47 | + * This program is free software; you can redistribute it and/or modify |
||
48 | + * it under the terms of the GNU General Public License as published by |
||
49 | + * the Free Software Foundation; either version 2 of the License, or |
||
50 | + * (at your option) any later version. |
||
51 | + * |
||
52 | + * Additional credits: |
||
53 | + * This code is taken from John Taylor's Sibyte driver and then |
||
54 | + * modified for the AR2313. |
||
55 | + */ |
||
56 | + |
||
57 | +#include <linux/module.h> |
||
58 | +#include <linux/types.h> |
||
59 | +#include <linux/errno.h> |
||
60 | +#include <linux/ioport.h> |
||
61 | +#include <linux/netdevice.h> |
||
62 | +#include <linux/etherdevice.h> |
||
63 | +#include <linux/interrupt.h> |
||
64 | +#include <linux/skbuff.h> |
||
65 | +#include <linux/init.h> |
||
66 | +#include <linux/delay.h> |
||
67 | +#include <linux/mm.h> |
||
68 | +#include <linux/mii.h> |
||
69 | +#include <linux/phy.h> |
||
70 | +#include <linux/platform_device.h> |
||
71 | +#include <linux/io.h> |
||
72 | + |
||
73 | +#define AR2313_MTU 1692 |
||
74 | +#define AR2313_PRIOS 1 |
||
75 | +#define AR2313_QUEUES (2*AR2313_PRIOS) |
||
76 | +#define AR2313_DESCR_ENTRIES 64 |
||
77 | + |
||
78 | +#ifndef min |
||
79 | +#define min(a, b) (((a) < (b)) ? (a) : (b)) |
||
80 | +#endif |
||
81 | + |
||
82 | +#ifndef SMP_CACHE_BYTES |
||
83 | +#define SMP_CACHE_BYTES L1_CACHE_BYTES |
||
84 | +#endif |
||
85 | + |
||
86 | +#define AR2313_MBOX_SET_BIT 0x8 |
||
87 | + |
||
88 | +#include "ar231x.h" |
||
89 | + |
||
90 | +/** |
||
91 | + * New interrupt handler strategy: |
||
92 | + * |
||
93 | + * An old interrupt handler worked using the traditional method of |
||
94 | + * replacing an skbuff with a new one when a packet arrives. However |
||
95 | + * the rx rings do not need to contain a static number of buffer |
||
96 | + * descriptors, thus it makes sense to move the memory allocation out |
||
97 | + * of the main interrupt handler and do it in a bottom half handler |
||
98 | + * and only allocate new buffers when the number of buffers in the |
||
99 | + * ring is below a certain threshold. In order to avoid starving the |
||
100 | + * NIC under heavy load it is however necessary to force allocation |
||
101 | + * when hitting a minimum threshold. The strategy for alloction is as |
||
102 | + * follows: |
||
103 | + * |
||
104 | + * RX_LOW_BUF_THRES - allocate buffers in the bottom half |
||
105 | + * RX_PANIC_LOW_THRES - we are very low on buffers, allocate |
||
106 | + * the buffers in the interrupt handler |
||
107 | + * RX_RING_THRES - maximum number of buffers in the rx ring |
||
108 | + * |
||
109 | + * One advantagous side effect of this allocation approach is that the |
||
110 | + * entire rx processing can be done without holding any spin lock |
||
111 | + * since the rx rings and registers are totally independent of the tx |
||
112 | + * ring and its registers. This of course includes the kmalloc's of |
||
113 | + * new skb's. Thus start_xmit can run in parallel with rx processing |
||
114 | + * and the memory allocation on SMP systems. |
||
115 | + * |
||
116 | + * Note that running the skb reallocation in a bottom half opens up |
||
117 | + * another can of races which needs to be handled properly. In |
||
118 | + * particular it can happen that the interrupt handler tries to run |
||
119 | + * the reallocation while the bottom half is either running on another |
||
120 | + * CPU or was interrupted on the same CPU. To get around this the |
||
121 | + * driver uses bitops to prevent the reallocation routines from being |
||
122 | + * reentered. |
||
123 | + * |
||
124 | + * TX handling can also be done without holding any spin lock, wheee |
||
125 | + * this is fun! since tx_csm is only written to by the interrupt |
||
126 | + * handler. |
||
127 | + */ |
||
128 | + |
||
129 | +/** |
||
130 | + * Threshold values for RX buffer allocation - the low water marks for |
||
131 | + * when to start refilling the rings are set to 75% of the ring |
||
132 | + * sizes. It seems to make sense to refill the rings entirely from the |
||
133 | + * intrrupt handler once it gets below the panic threshold, that way |
||
134 | + * we don't risk that the refilling is moved to another CPU when the |
||
135 | + * one running the interrupt handler just got the slab code hot in its |
||
136 | + * cache. |
||
137 | + */ |
||
138 | +#define RX_RING_SIZE AR2313_DESCR_ENTRIES |
||
139 | +#define RX_PANIC_THRES (RX_RING_SIZE/4) |
||
140 | +#define RX_LOW_THRES ((3*RX_RING_SIZE)/4) |
||
141 | +#define CRC_LEN 4 |
||
142 | +#define RX_OFFSET 2 |
||
143 | + |
||
144 | +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) |
||
145 | +#define VLAN_HDR 4 |
||
146 | +#else |
||
147 | +#define VLAN_HDR 0 |
||
148 | +#endif |
||
149 | + |
||
150 | +#define AR2313_BUFSIZE (AR2313_MTU + VLAN_HDR + ETH_HLEN + CRC_LEN + \ |
||
151 | + RX_OFFSET) |
||
152 | + |
||
153 | +#ifdef MODULE |
||
154 | +MODULE_LICENSE("GPL"); |
||
155 | +MODULE_AUTHOR("Sameer Dekate <sdekate@arubanetworks.com>, Imre Kaloz <kaloz@openwrt.org>, Felix Fietkau <nbd@nbd.name>"); |
||
156 | +MODULE_DESCRIPTION("AR231x Ethernet driver"); |
||
157 | +#endif |
||
158 | + |
||
159 | +#define virt_to_phys(x) ((u32)(x) & 0x1fffffff) |
||
160 | + |
||
161 | +/* prototypes */ |
||
162 | +static void ar231x_halt(struct net_device *dev); |
||
163 | +static void rx_tasklet_func(unsigned long data); |
||
164 | +static void rx_tasklet_cleanup(struct net_device *dev); |
||
165 | +static void ar231x_multicast_list(struct net_device *dev); |
||
166 | +static void ar231x_tx_timeout(struct net_device *dev); |
||
167 | + |
||
168 | +static int ar231x_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum); |
||
169 | +static int ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, |
||
170 | + u16 value); |
||
171 | +static int ar231x_mdiobus_reset(struct mii_bus *bus); |
||
172 | +static int ar231x_mdiobus_probe(struct net_device *dev); |
||
173 | +static void ar231x_adjust_link(struct net_device *dev); |
||
174 | + |
||
175 | +#ifndef ERR |
||
176 | +#define ERR(fmt, args...) printk("%s: " fmt, __func__, ##args) |
||
177 | +#endif |
||
178 | + |
||
179 | +#ifdef CONFIG_NET_POLL_CONTROLLER |
||
180 | +static void |
||
181 | +ar231x_netpoll(struct net_device *dev) |
||
182 | +{ |
||
183 | + unsigned long flags; |
||
184 | + |
||
185 | + local_irq_save(flags); |
||
186 | + ar231x_interrupt(dev->irq, dev); |
||
187 | + local_irq_restore(flags); |
||
188 | +} |
||
189 | +#endif |
||
190 | + |
||
191 | +static const struct net_device_ops ar231x_ops = { |
||
192 | + .ndo_open = ar231x_open, |
||
193 | + .ndo_stop = ar231x_close, |
||
194 | + .ndo_start_xmit = ar231x_start_xmit, |
||
195 | + .ndo_set_rx_mode = ar231x_multicast_list, |
||
196 | + .ndo_do_ioctl = ar231x_ioctl, |
||
197 | + .ndo_change_mtu = eth_change_mtu, |
||
198 | + .ndo_validate_addr = eth_validate_addr, |
||
199 | + .ndo_set_mac_address = eth_mac_addr, |
||
200 | + .ndo_tx_timeout = ar231x_tx_timeout, |
||
201 | +#ifdef CONFIG_NET_POLL_CONTROLLER |
||
202 | + .ndo_poll_controller = ar231x_netpoll, |
||
203 | +#endif |
||
204 | +}; |
||
205 | + |
||
206 | +static int ar231x_probe(struct platform_device *pdev) |
||
207 | +{ |
||
208 | + struct net_device *dev; |
||
209 | + struct ar231x_private *sp; |
||
210 | + struct resource *res; |
||
211 | + unsigned long ar_eth_base; |
||
212 | + char buf[64]; |
||
213 | + |
||
214 | + dev = alloc_etherdev(sizeof(struct ar231x_private)); |
||
215 | + |
||
216 | + if (dev == NULL) { |
||
217 | + printk(KERN_ERR |
||
218 | + "ar231x: Unable to allocate net_device structure!\n"); |
||
219 | + return -ENOMEM; |
||
220 | + } |
||
221 | + |
||
222 | + platform_set_drvdata(pdev, dev); |
||
223 | + |
||
224 | + SET_NETDEV_DEV(dev, &pdev->dev); |
||
225 | + |
||
226 | + sp = netdev_priv(dev); |
||
227 | + sp->dev = dev; |
||
228 | + sp->cfg = pdev->dev.platform_data; |
||
229 | + |
||
230 | + sprintf(buf, "eth%d_membase", pdev->id); |
||
231 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, buf); |
||
232 | + if (!res) |
||
233 | + return -ENODEV; |
||
234 | + |
||
235 | + sp->link = 0; |
||
236 | + ar_eth_base = res->start; |
||
237 | + |
||
238 | + sprintf(buf, "eth%d_irq", pdev->id); |
||
239 | + dev->irq = platform_get_irq_byname(pdev, buf); |
||
240 | + |
||
241 | + spin_lock_init(&sp->lock); |
||
242 | + |
||
243 | + dev->features |= NETIF_F_HIGHDMA; |
||
244 | + dev->netdev_ops = &ar231x_ops; |
||
245 | + |
||
246 | + tasklet_init(&sp->rx_tasklet, rx_tasklet_func, (unsigned long)dev); |
||
247 | + tasklet_disable(&sp->rx_tasklet); |
||
248 | + |
||
249 | + sp->eth_regs = ioremap_nocache(ar_eth_base, sizeof(*sp->eth_regs)); |
||
250 | + if (!sp->eth_regs) { |
||
251 | + printk("Can't remap eth registers\n"); |
||
252 | + return -ENXIO; |
||
253 | + } |
||
254 | + |
||
255 | + /** |
||
256 | + * When there's only one MAC, PHY regs are typically on ENET0, |
||
257 | + * even though the MAC might be on ENET1. |
||
258 | + * So remap PHY regs separately. |
||
259 | + */ |
||
260 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "eth0_mii"); |
||
261 | + if (!res) { |
||
262 | + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
||
263 | + "eth1_mii"); |
||
264 | + if (!res) |
||
265 | + return -ENODEV; |
||
266 | + } |
||
267 | + sp->phy_regs = ioremap_nocache(res->start, resource_size(res)); |
||
268 | + if (!sp->phy_regs) { |
||
269 | + printk("Can't remap phy registers\n"); |
||
270 | + return -ENXIO; |
||
271 | + } |
||
272 | + |
||
273 | + sp->dma_regs = ioremap_nocache(ar_eth_base + 0x1000, |
||
274 | + sizeof(*sp->dma_regs)); |
||
275 | + if (!sp->dma_regs) { |
||
276 | + printk("Can't remap DMA registers\n"); |
||
277 | + return -ENXIO; |
||
278 | + } |
||
279 | + dev->base_addr = ar_eth_base + 0x1000; |
||
280 | + |
||
281 | + strncpy(sp->name, "Atheros AR231x", sizeof(sp->name) - 1); |
||
282 | + sp->name[sizeof(sp->name) - 1] = '\0'; |
||
283 | + memcpy(dev->dev_addr, sp->cfg->macaddr, 6); |
||
284 | + |
||
285 | + if (ar231x_init(dev)) { |
||
286 | + /* ar231x_init() calls ar231x_init_cleanup() on error */ |
||
287 | + kfree(dev); |
||
288 | + return -ENODEV; |
||
289 | + } |
||
290 | + |
||
291 | + if (register_netdev(dev)) { |
||
292 | + printk("%s: register_netdev failed\n", __func__); |
||
293 | + return -1; |
||
294 | + } |
||
295 | + |
||
296 | + printk("%s: %s: %pM, irq %d\n", dev->name, sp->name, dev->dev_addr, |
||
297 | + dev->irq); |
||
298 | + |
||
299 | + sp->mii_bus = mdiobus_alloc(); |
||
300 | + if (sp->mii_bus == NULL) |
||
301 | + return -1; |
||
302 | + |
||
303 | + sp->mii_bus->priv = dev; |
||
304 | + sp->mii_bus->read = ar231x_mdiobus_read; |
||
305 | + sp->mii_bus->write = ar231x_mdiobus_write; |
||
306 | + sp->mii_bus->reset = ar231x_mdiobus_reset; |
||
307 | + sp->mii_bus->name = "ar231x_eth_mii"; |
||
308 | + snprintf(sp->mii_bus->id, MII_BUS_ID_SIZE, "%d", pdev->id); |
||
309 | + |
||
310 | + mdiobus_register(sp->mii_bus); |
||
311 | + |
||
312 | + if (ar231x_mdiobus_probe(dev) != 0) { |
||
313 | + printk(KERN_ERR "%s: mdiobus_probe failed\n", dev->name); |
||
314 | + rx_tasklet_cleanup(dev); |
||
315 | + ar231x_init_cleanup(dev); |
||
316 | + unregister_netdev(dev); |
||
317 | + kfree(dev); |
||
318 | + return -ENODEV; |
||
319 | + } |
||
320 | + |
||
321 | + return 0; |
||
322 | +} |
||
323 | + |
||
324 | +static void ar231x_multicast_list(struct net_device *dev) |
||
325 | +{ |
||
326 | + struct ar231x_private *sp = netdev_priv(dev); |
||
327 | + unsigned int filter; |
||
328 | + |
||
329 | + filter = sp->eth_regs->mac_control; |
||
330 | + |
||
331 | + if (dev->flags & IFF_PROMISC) |
||
332 | + filter |= MAC_CONTROL_PR; |
||
333 | + else |
||
334 | + filter &= ~MAC_CONTROL_PR; |
||
335 | + if ((dev->flags & IFF_ALLMULTI) || (netdev_mc_count(dev) > 0)) |
||
336 | + filter |= MAC_CONTROL_PM; |
||
337 | + else |
||
338 | + filter &= ~MAC_CONTROL_PM; |
||
339 | + |
||
340 | + sp->eth_regs->mac_control = filter; |
||
341 | +} |
||
342 | + |
||
343 | +static void rx_tasklet_cleanup(struct net_device *dev) |
||
344 | +{ |
||
345 | + struct ar231x_private *sp = netdev_priv(dev); |
||
346 | + |
||
347 | + /** |
||
348 | + * Tasklet may be scheduled. Need to get it removed from the list |
||
349 | + * since we're about to free the struct. |
||
350 | + */ |
||
351 | + |
||
352 | + sp->unloading = 1; |
||
353 | + tasklet_enable(&sp->rx_tasklet); |
||
354 | + tasklet_kill(&sp->rx_tasklet); |
||
355 | +} |
||
356 | + |
||
357 | +static int ar231x_remove(struct platform_device *pdev) |
||
358 | +{ |
||
359 | + struct net_device *dev = platform_get_drvdata(pdev); |
||
360 | + struct ar231x_private *sp = netdev_priv(dev); |
||
361 | + |
||
362 | + rx_tasklet_cleanup(dev); |
||
363 | + ar231x_init_cleanup(dev); |
||
364 | + unregister_netdev(dev); |
||
365 | + mdiobus_unregister(sp->mii_bus); |
||
366 | + mdiobus_free(sp->mii_bus); |
||
367 | + kfree(dev); |
||
368 | + return 0; |
||
369 | +} |
||
370 | + |
||
371 | +/** |
||
372 | + * Restart the AR2313 ethernet controller. |
||
373 | + */ |
||
374 | +static int ar231x_restart(struct net_device *dev) |
||
375 | +{ |
||
376 | + /* disable interrupts */ |
||
377 | + disable_irq(dev->irq); |
||
378 | + |
||
379 | + /* stop mac */ |
||
380 | + ar231x_halt(dev); |
||
381 | + |
||
382 | + /* initialize */ |
||
383 | + ar231x_init(dev); |
||
384 | + |
||
385 | + /* enable interrupts */ |
||
386 | + enable_irq(dev->irq); |
||
387 | + |
||
388 | + return 0; |
||
389 | +} |
||
390 | + |
||
391 | +static struct platform_driver ar231x_driver = { |
||
392 | + .driver.name = "ar231x-eth", |
||
393 | + .probe = ar231x_probe, |
||
394 | + .remove = ar231x_remove, |
||
395 | +}; |
||
396 | + |
||
397 | +module_platform_driver(ar231x_driver); |
||
398 | + |
||
399 | +static void ar231x_free_descriptors(struct net_device *dev) |
||
400 | +{ |
||
401 | + struct ar231x_private *sp = netdev_priv(dev); |
||
402 | + |
||
403 | + if (sp->rx_ring != NULL) { |
||
404 | + kfree((void *)KSEG0ADDR(sp->rx_ring)); |
||
405 | + sp->rx_ring = NULL; |
||
406 | + sp->tx_ring = NULL; |
||
407 | + } |
||
408 | +} |
||
409 | + |
||
410 | +static int ar231x_allocate_descriptors(struct net_device *dev) |
||
411 | +{ |
||
412 | + struct ar231x_private *sp = netdev_priv(dev); |
||
413 | + int size; |
||
414 | + int j; |
||
415 | + ar231x_descr_t *space; |
||
416 | + |
||
417 | + if (sp->rx_ring != NULL) { |
||
418 | + printk("%s: already done.\n", __func__); |
||
419 | + return 0; |
||
420 | + } |
||
421 | + |
||
422 | + size = sizeof(ar231x_descr_t) * (AR2313_DESCR_ENTRIES * AR2313_QUEUES); |
||
423 | + space = kmalloc(size, GFP_KERNEL); |
||
424 | + if (space == NULL) |
||
425 | + return 1; |
||
426 | + |
||
427 | + /* invalidate caches */ |
||
428 | + dma_cache_inv((unsigned int)space, size); |
||
429 | + |
||
430 | + /* now convert pointer to KSEG1 */ |
||
431 | + space = (ar231x_descr_t *)KSEG1ADDR(space); |
||
432 | + |
||
433 | + memset((void *)space, 0, size); |
||
434 | + |
||
435 | + sp->rx_ring = space; |
||
436 | + space += AR2313_DESCR_ENTRIES; |
||
437 | + |
||
438 | + sp->tx_ring = space; |
||
439 | + space += AR2313_DESCR_ENTRIES; |
||
440 | + |
||
441 | + /* Initialize the transmit Descriptors */ |
||
442 | + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { |
||
443 | + ar231x_descr_t *td = &sp->tx_ring[j]; |
||
444 | + |
||
445 | + td->status = 0; |
||
446 | + td->devcs = DMA_TX1_CHAINED; |
||
447 | + td->addr = 0; |
||
448 | + td->descr = virt_to_phys(&sp->tx_ring[DSC_NEXT(j)]); |
||
449 | + } |
||
450 | + |
||
451 | + return 0; |
||
452 | +} |
||
453 | + |
||
454 | +/** |
||
455 | + * Generic cleanup handling data allocated during init. Used when the |
||
456 | + * module is unloaded or if an error occurs during initialization |
||
457 | + */ |
||
458 | +static void ar231x_init_cleanup(struct net_device *dev) |
||
459 | +{ |
||
460 | + struct ar231x_private *sp = netdev_priv(dev); |
||
461 | + struct sk_buff *skb; |
||
462 | + int j; |
||
463 | + |
||
464 | + ar231x_free_descriptors(dev); |
||
465 | + |
||
466 | + if (sp->eth_regs) |
||
467 | + iounmap((void *)sp->eth_regs); |
||
468 | + if (sp->dma_regs) |
||
469 | + iounmap((void *)sp->dma_regs); |
||
470 | + if (sp->phy_regs) |
||
471 | + iounmap((void *)sp->phy_regs); |
||
472 | + |
||
473 | + if (sp->rx_skb) { |
||
474 | + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { |
||
475 | + skb = sp->rx_skb[j]; |
||
476 | + if (skb) { |
||
477 | + sp->rx_skb[j] = NULL; |
||
478 | + dev_kfree_skb(skb); |
||
479 | + } |
||
480 | + } |
||
481 | + kfree(sp->rx_skb); |
||
482 | + sp->rx_skb = NULL; |
||
483 | + } |
||
484 | + |
||
485 | + if (sp->tx_skb) { |
||
486 | + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { |
||
487 | + skb = sp->tx_skb[j]; |
||
488 | + if (skb) { |
||
489 | + sp->tx_skb[j] = NULL; |
||
490 | + dev_kfree_skb(skb); |
||
491 | + } |
||
492 | + } |
||
493 | + kfree(sp->tx_skb); |
||
494 | + sp->tx_skb = NULL; |
||
495 | + } |
||
496 | +} |
||
497 | + |
||
498 | +static int ar231x_reset_reg(struct net_device *dev) |
||
499 | +{ |
||
500 | + struct ar231x_private *sp = netdev_priv(dev); |
||
501 | + unsigned int ethsal, ethsah; |
||
502 | + unsigned int flags; |
||
503 | + |
||
504 | + sp->cfg->reset_set(sp->cfg->reset_mac); |
||
505 | + mdelay(10); |
||
506 | + sp->cfg->reset_clear(sp->cfg->reset_mac); |
||
507 | + mdelay(10); |
||
508 | + sp->cfg->reset_set(sp->cfg->reset_phy); |
||
509 | + mdelay(10); |
||
510 | + sp->cfg->reset_clear(sp->cfg->reset_phy); |
||
511 | + mdelay(10); |
||
512 | + |
||
513 | + sp->dma_regs->bus_mode = (DMA_BUS_MODE_SWR); |
||
514 | + mdelay(10); |
||
515 | + sp->dma_regs->bus_mode = |
||
516 | + ((32 << DMA_BUS_MODE_PBL_SHIFT) | DMA_BUS_MODE_BLE); |
||
517 | + |
||
518 | + /* enable interrupts */ |
||
519 | + sp->dma_regs->intr_ena = DMA_STATUS_AIS | DMA_STATUS_NIS | |
||
520 | + DMA_STATUS_RI | DMA_STATUS_TI | |
||
521 | + DMA_STATUS_FBE; |
||
522 | + sp->dma_regs->xmt_base = virt_to_phys(sp->tx_ring); |
||
523 | + sp->dma_regs->rcv_base = virt_to_phys(sp->rx_ring); |
||
524 | + sp->dma_regs->control = |
||
525 | + (DMA_CONTROL_SR | DMA_CONTROL_ST | DMA_CONTROL_SF); |
||
526 | + |
||
527 | + sp->eth_regs->flow_control = (FLOW_CONTROL_FCE); |
||
528 | + sp->eth_regs->vlan_tag = (0x8100); |
||
529 | + |
||
530 | + /* Enable Ethernet Interface */ |
||
531 | + flags = (MAC_CONTROL_TE | /* transmit enable */ |
||
532 | + MAC_CONTROL_PM | /* pass mcast */ |
||
533 | + MAC_CONTROL_F | /* full duplex */ |
||
534 | + MAC_CONTROL_HBD); /* heart beat disabled */ |
||
535 | + |
||
536 | + if (dev->flags & IFF_PROMISC) { /* set promiscuous mode */ |
||
537 | + flags |= MAC_CONTROL_PR; |
||
538 | + } |
||
539 | + sp->eth_regs->mac_control = flags; |
||
540 | + |
||
541 | + /* Set all Ethernet station address registers to their initial values */ |
||
542 | + ethsah = (((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | |
||
543 | + (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF); |
||
544 | + |
||
545 | + ethsal = (((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | |
||
546 | + (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | |
||
547 | + (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | |
||
548 | + (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF); |
||
549 | + |
||
550 | + sp->eth_regs->mac_addr[0] = ethsah; |
||
551 | + sp->eth_regs->mac_addr[1] = ethsal; |
||
552 | + |
||
553 | + mdelay(10); |
||
554 | + |
||
555 | + return 0; |
||
556 | +} |
||
557 | + |
||
558 | +static int ar231x_init(struct net_device *dev) |
||
559 | +{ |
||
560 | + struct ar231x_private *sp = netdev_priv(dev); |
||
561 | + int ecode = 0; |
||
562 | + |
||
563 | + /* Allocate descriptors */ |
||
564 | + if (ar231x_allocate_descriptors(dev)) { |
||
565 | + printk("%s: %s: ar231x_allocate_descriptors failed\n", |
||
566 | + dev->name, __func__); |
||
567 | + ecode = -EAGAIN; |
||
568 | + goto init_error; |
||
569 | + } |
||
570 | + |
||
571 | + /* Get the memory for the skb rings */ |
||
572 | + if (sp->rx_skb == NULL) { |
||
573 | + sp->rx_skb = |
||
574 | + kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, |
||
575 | + GFP_KERNEL); |
||
576 | + if (!(sp->rx_skb)) { |
||
577 | + printk("%s: %s: rx_skb kmalloc failed\n", |
||
578 | + dev->name, __func__); |
||
579 | + ecode = -EAGAIN; |
||
580 | + goto init_error; |
||
581 | + } |
||
582 | + } |
||
583 | + memset(sp->rx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); |
||
584 | + |
||
585 | + if (sp->tx_skb == NULL) { |
||
586 | + sp->tx_skb = |
||
587 | + kmalloc(sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES, |
||
588 | + GFP_KERNEL); |
||
589 | + if (!(sp->tx_skb)) { |
||
590 | + printk("%s: %s: tx_skb kmalloc failed\n", |
||
591 | + dev->name, __func__); |
||
592 | + ecode = -EAGAIN; |
||
593 | + goto init_error; |
||
594 | + } |
||
595 | + } |
||
596 | + memset(sp->tx_skb, 0, sizeof(struct sk_buff *) * AR2313_DESCR_ENTRIES); |
||
597 | + |
||
598 | + /** |
||
599 | + * Set tx_csm before we start receiving interrupts, otherwise |
||
600 | + * the interrupt handler might think it is supposed to process |
||
601 | + * tx ints before we are up and running, which may cause a null |
||
602 | + * pointer access in the int handler. |
||
603 | + */ |
||
604 | + sp->rx_skbprd = 0; |
||
605 | + sp->cur_rx = 0; |
||
606 | + sp->tx_prd = 0; |
||
607 | + sp->tx_csm = 0; |
||
608 | + |
||
609 | + /* Zero the stats before starting the interface */ |
||
610 | + memset(&dev->stats, 0, sizeof(dev->stats)); |
||
611 | + |
||
612 | + /** |
||
613 | + * We load the ring here as there seem to be no way to tell the |
||
614 | + * firmware to wipe the ring without re-initializing it. |
||
615 | + */ |
||
616 | + ar231x_load_rx_ring(dev, RX_RING_SIZE); |
||
617 | + |
||
618 | + /* Init hardware */ |
||
619 | + ar231x_reset_reg(dev); |
||
620 | + |
||
621 | + /* Get the IRQ */ |
||
622 | + ecode = request_irq(dev->irq, &ar231x_interrupt, 0, |
||
623 | + dev->name, dev); |
||
624 | + if (ecode) { |
||
625 | + printk(KERN_WARNING "%s: %s: Requested IRQ %d is busy\n", |
||
626 | + dev->name, __func__, dev->irq); |
||
627 | + goto init_error; |
||
628 | + } |
||
629 | + |
||
630 | + tasklet_enable(&sp->rx_tasklet); |
||
631 | + |
||
632 | + return 0; |
||
633 | + |
||
634 | +init_error: |
||
635 | + ar231x_init_cleanup(dev); |
||
636 | + return ecode; |
||
637 | +} |
||
638 | + |
||
639 | +/** |
||
640 | + * Load the rx ring. |
||
641 | + * |
||
642 | + * Loading rings is safe without holding the spin lock since this is |
||
643 | + * done only before the device is enabled, thus no interrupts are |
||
644 | + * generated and by the interrupt handler/tasklet handler. |
||
645 | + */ |
||
646 | +static void ar231x_load_rx_ring(struct net_device *dev, int nr_bufs) |
||
647 | +{ |
||
648 | + struct ar231x_private *sp = netdev_priv(dev); |
||
649 | + short i, idx; |
||
650 | + |
||
651 | + idx = sp->rx_skbprd; |
||
652 | + |
||
653 | + for (i = 0; i < nr_bufs; i++) { |
||
654 | + struct sk_buff *skb; |
||
655 | + ar231x_descr_t *rd; |
||
656 | + |
||
657 | + if (sp->rx_skb[idx]) |
||
658 | + break; |
||
659 | + |
||
660 | + skb = netdev_alloc_skb_ip_align(dev, AR2313_BUFSIZE); |
||
661 | + if (!skb) { |
||
662 | + printk("\n\n\n\n %s: No memory in system\n\n\n\n", |
||
663 | + __func__); |
||
664 | + break; |
||
665 | + } |
||
666 | + |
||
667 | + /* Make sure IP header starts on a fresh cache line */ |
||
668 | + skb->dev = dev; |
||
669 | + sp->rx_skb[idx] = skb; |
||
670 | + |
||
671 | + rd = (ar231x_descr_t *)&sp->rx_ring[idx]; |
||
672 | + |
||
673 | + /* initialize dma descriptor */ |
||
674 | + rd->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | |
||
675 | + DMA_RX1_CHAINED); |
||
676 | + rd->addr = virt_to_phys(skb->data); |
||
677 | + rd->descr = virt_to_phys(&sp->rx_ring[DSC_NEXT(idx)]); |
||
678 | + rd->status = DMA_RX_OWN; |
||
679 | + |
||
680 | + idx = DSC_NEXT(idx); |
||
681 | + } |
||
682 | + |
||
683 | + if (i) |
||
684 | + sp->rx_skbprd = idx; |
||
685 | +} |
||
686 | + |
||
687 | +#define AR2313_MAX_PKTS_PER_CALL 64 |
||
688 | + |
||
689 | +static int ar231x_rx_int(struct net_device *dev) |
||
690 | +{ |
||
691 | + struct ar231x_private *sp = netdev_priv(dev); |
||
692 | + struct sk_buff *skb, *skb_new; |
||
693 | + ar231x_descr_t *rxdesc; |
||
694 | + unsigned int status; |
||
695 | + u32 idx; |
||
696 | + int pkts = 0; |
||
697 | + int rval; |
||
698 | + |
||
699 | + idx = sp->cur_rx; |
||
700 | + |
||
701 | + /* process at most the entire ring and then wait for another int */ |
||
702 | + while (1) { |
||
703 | + rxdesc = &sp->rx_ring[idx]; |
||
704 | + status = rxdesc->status; |
||
705 | + |
||
706 | + if (status & DMA_RX_OWN) { |
||
707 | + /* SiByte owns descriptor or descr not yet filled in */ |
||
708 | + rval = 0; |
||
709 | + break; |
||
710 | + } |
||
711 | + |
||
712 | + if (++pkts > AR2313_MAX_PKTS_PER_CALL) { |
||
713 | + rval = 1; |
||
714 | + break; |
||
715 | + } |
||
716 | + |
||
717 | + if ((status & DMA_RX_ERROR) && !(status & DMA_RX_LONG)) { |
||
718 | + dev->stats.rx_errors++; |
||
719 | + dev->stats.rx_dropped++; |
||
720 | + |
||
721 | + /* add statistics counters */ |
||
722 | + if (status & DMA_RX_ERR_CRC) |
||
723 | + dev->stats.rx_crc_errors++; |
||
724 | + if (status & DMA_RX_ERR_COL) |
||
725 | + dev->stats.rx_over_errors++; |
||
726 | + if (status & DMA_RX_ERR_LENGTH) |
||
727 | + dev->stats.rx_length_errors++; |
||
728 | + if (status & DMA_RX_ERR_RUNT) |
||
729 | + dev->stats.rx_over_errors++; |
||
730 | + if (status & DMA_RX_ERR_DESC) |
||
731 | + dev->stats.rx_over_errors++; |
||
732 | + |
||
733 | + } else { |
||
734 | + /* alloc new buffer. */ |
||
735 | + skb_new = netdev_alloc_skb_ip_align(dev, |
||
736 | + AR2313_BUFSIZE); |
||
737 | + if (skb_new != NULL) { |
||
738 | + skb = sp->rx_skb[idx]; |
||
739 | + /* set skb */ |
||
740 | + skb_put(skb, ((status >> DMA_RX_LEN_SHIFT) & |
||
741 | + 0x3fff) - CRC_LEN); |
||
742 | + |
||
743 | + dev->stats.rx_bytes += skb->len; |
||
744 | + skb->protocol = eth_type_trans(skb, dev); |
||
745 | + /* pass the packet to upper layers */ |
||
746 | + netif_rx(skb); |
||
747 | + |
||
748 | + skb_new->dev = dev; |
||
749 | + /* reset descriptor's curr_addr */ |
||
750 | + rxdesc->addr = virt_to_phys(skb_new->data); |
||
751 | + |
||
752 | + dev->stats.rx_packets++; |
||
753 | + sp->rx_skb[idx] = skb_new; |
||
754 | + } else { |
||
755 | + dev->stats.rx_dropped++; |
||
756 | + } |
||
757 | + } |
||
758 | + |
||
759 | + rxdesc->devcs = ((AR2313_BUFSIZE << DMA_RX1_BSIZE_SHIFT) | |
||
760 | + DMA_RX1_CHAINED); |
||
761 | + rxdesc->status = DMA_RX_OWN; |
||
762 | + |
||
763 | + idx = DSC_NEXT(idx); |
||
764 | + } |
||
765 | + |
||
766 | + sp->cur_rx = idx; |
||
767 | + |
||
768 | + return rval; |
||
769 | +} |
||
770 | + |
||
771 | +static void ar231x_tx_int(struct net_device *dev) |
||
772 | +{ |
||
773 | + struct ar231x_private *sp = netdev_priv(dev); |
||
774 | + u32 idx; |
||
775 | + struct sk_buff *skb; |
||
776 | + ar231x_descr_t *txdesc; |
||
777 | + unsigned int status = 0; |
||
778 | + |
||
779 | + idx = sp->tx_csm; |
||
780 | + |
||
781 | + while (idx != sp->tx_prd) { |
||
782 | + txdesc = &sp->tx_ring[idx]; |
||
783 | + status = txdesc->status; |
||
784 | + |
||
785 | + if (status & DMA_TX_OWN) { |
||
786 | + /* ar231x dma still owns descr */ |
||
787 | + break; |
||
788 | + } |
||
789 | + /* done with this descriptor */ |
||
790 | + dma_unmap_single(NULL, txdesc->addr, |
||
791 | + txdesc->devcs & DMA_TX1_BSIZE_MASK, |
||
792 | + DMA_TO_DEVICE); |
||
793 | + txdesc->status = 0; |
||
794 | + |
||
795 | + if (status & DMA_TX_ERROR) { |
||
796 | + dev->stats.tx_errors++; |
||
797 | + dev->stats.tx_dropped++; |
||
798 | + if (status & DMA_TX_ERR_UNDER) |
||
799 | + dev->stats.tx_fifo_errors++; |
||
800 | + if (status & DMA_TX_ERR_HB) |
||
801 | + dev->stats.tx_heartbeat_errors++; |
||
802 | + if (status & (DMA_TX_ERR_LOSS | DMA_TX_ERR_LINK)) |
||
803 | + dev->stats.tx_carrier_errors++; |
||
804 | + if (status & (DMA_TX_ERR_LATE | DMA_TX_ERR_COL | |
||
805 | + DMA_TX_ERR_JABBER | DMA_TX_ERR_DEFER)) |
||
806 | + dev->stats.tx_aborted_errors++; |
||
807 | + } else { |
||
808 | + /* transmit OK */ |
||
809 | + dev->stats.tx_packets++; |
||
810 | + } |
||
811 | + |
||
812 | + skb = sp->tx_skb[idx]; |
||
813 | + sp->tx_skb[idx] = NULL; |
||
814 | + idx = DSC_NEXT(idx); |
||
815 | + dev->stats.tx_bytes += skb->len; |
||
816 | + dev_kfree_skb_irq(skb); |
||
817 | + } |
||
818 | + |
||
819 | + sp->tx_csm = idx; |
||
820 | +} |
||
821 | + |
||
822 | +static void rx_tasklet_func(unsigned long data) |
||
823 | +{ |
||
824 | + struct net_device *dev = (struct net_device *)data; |
||
825 | + struct ar231x_private *sp = netdev_priv(dev); |
||
826 | + |
||
827 | + if (sp->unloading) |
||
828 | + return; |
||
829 | + |
||
830 | + if (ar231x_rx_int(dev)) { |
||
831 | + tasklet_hi_schedule(&sp->rx_tasklet); |
||
832 | + } else { |
||
833 | + unsigned long flags; |
||
834 | + |
||
835 | + spin_lock_irqsave(&sp->lock, flags); |
||
836 | + sp->dma_regs->intr_ena |= DMA_STATUS_RI; |
||
837 | + spin_unlock_irqrestore(&sp->lock, flags); |
||
838 | + } |
||
839 | +} |
||
840 | + |
||
841 | +static void rx_schedule(struct net_device *dev) |
||
842 | +{ |
||
843 | + struct ar231x_private *sp = netdev_priv(dev); |
||
844 | + |
||
845 | + sp->dma_regs->intr_ena &= ~DMA_STATUS_RI; |
||
846 | + |
||
847 | + tasklet_hi_schedule(&sp->rx_tasklet); |
||
848 | +} |
||
849 | + |
||
850 | +static irqreturn_t ar231x_interrupt(int irq, void *dev_id) |
||
851 | +{ |
||
852 | + struct net_device *dev = (struct net_device *)dev_id; |
||
853 | + struct ar231x_private *sp = netdev_priv(dev); |
||
854 | + unsigned int status, enabled; |
||
855 | + |
||
856 | + /* clear interrupt */ |
||
857 | + /* Don't clear RI bit if currently disabled */ |
||
858 | + status = sp->dma_regs->status; |
||
859 | + enabled = sp->dma_regs->intr_ena; |
||
860 | + sp->dma_regs->status = status & enabled; |
||
861 | + |
||
862 | + if (status & DMA_STATUS_NIS) { |
||
863 | + /* normal status */ |
||
864 | + /** |
||
865 | + * Don't schedule rx processing if interrupt |
||
866 | + * is already disabled. |
||
867 | + */ |
||
868 | + if (status & enabled & DMA_STATUS_RI) { |
||
869 | + /* receive interrupt */ |
||
870 | + rx_schedule(dev); |
||
871 | + } |
||
872 | + if (status & DMA_STATUS_TI) { |
||
873 | + /* transmit interrupt */ |
||
874 | + ar231x_tx_int(dev); |
||
875 | + } |
||
876 | + } |
||
877 | + |
||
878 | + /* abnormal status */ |
||
879 | + if (status & (DMA_STATUS_FBE | DMA_STATUS_TPS)) |
||
880 | + ar231x_restart(dev); |
||
881 | + |
||
882 | + return IRQ_HANDLED; |
||
883 | +} |
||
884 | + |
||
885 | +static int ar231x_open(struct net_device *dev) |
||
886 | +{ |
||
887 | + struct ar231x_private *sp = netdev_priv(dev); |
||
888 | + unsigned int ethsal, ethsah; |
||
889 | + |
||
890 | + /* reset the hardware, in case the MAC address changed */ |
||
891 | + ethsah = (((u_int) (dev->dev_addr[5]) << 8) & (u_int) 0x0000FF00) | |
||
892 | + (((u_int) (dev->dev_addr[4]) << 0) & (u_int) 0x000000FF); |
||
893 | + |
||
894 | + ethsal = (((u_int) (dev->dev_addr[3]) << 24) & (u_int) 0xFF000000) | |
||
895 | + (((u_int) (dev->dev_addr[2]) << 16) & (u_int) 0x00FF0000) | |
||
896 | + (((u_int) (dev->dev_addr[1]) << 8) & (u_int) 0x0000FF00) | |
||
897 | + (((u_int) (dev->dev_addr[0]) << 0) & (u_int) 0x000000FF); |
||
898 | + |
||
899 | + sp->eth_regs->mac_addr[0] = ethsah; |
||
900 | + sp->eth_regs->mac_addr[1] = ethsal; |
||
901 | + |
||
902 | + mdelay(10); |
||
903 | + |
||
904 | + dev->mtu = 1500; |
||
905 | + netif_start_queue(dev); |
||
906 | + |
||
907 | + sp->eth_regs->mac_control |= MAC_CONTROL_RE; |
||
908 | + |
||
909 | + phy_start(sp->phy_dev); |
||
910 | + |
||
911 | + return 0; |
||
912 | +} |
||
913 | + |
||
914 | +static void ar231x_tx_timeout(struct net_device *dev) |
||
915 | +{ |
||
916 | + struct ar231x_private *sp = netdev_priv(dev); |
||
917 | + unsigned long flags; |
||
918 | + |
||
919 | + spin_lock_irqsave(&sp->lock, flags); |
||
920 | + ar231x_restart(dev); |
||
921 | + spin_unlock_irqrestore(&sp->lock, flags); |
||
922 | +} |
||
923 | + |
||
924 | +static void ar231x_halt(struct net_device *dev) |
||
925 | +{ |
||
926 | + struct ar231x_private *sp = netdev_priv(dev); |
||
927 | + int j; |
||
928 | + |
||
929 | + tasklet_disable(&sp->rx_tasklet); |
||
930 | + |
||
931 | + /* kill the MAC */ |
||
932 | + sp->eth_regs->mac_control &= ~(MAC_CONTROL_RE | /* disable Receives */ |
||
933 | + MAC_CONTROL_TE); /* disable Transmits */ |
||
934 | + /* stop dma */ |
||
935 | + sp->dma_regs->control = 0; |
||
936 | + sp->dma_regs->bus_mode = DMA_BUS_MODE_SWR; |
||
937 | + |
||
938 | + /* place phy and MAC in reset */ |
||
939 | + sp->cfg->reset_set(sp->cfg->reset_mac); |
||
940 | + sp->cfg->reset_set(sp->cfg->reset_phy); |
||
941 | + |
||
942 | + /* free buffers on tx ring */ |
||
943 | + for (j = 0; j < AR2313_DESCR_ENTRIES; j++) { |
||
944 | + struct sk_buff *skb; |
||
945 | + ar231x_descr_t *txdesc; |
||
946 | + |
||
947 | + txdesc = &sp->tx_ring[j]; |
||
948 | + txdesc->descr = 0; |
||
949 | + |
||
950 | + skb = sp->tx_skb[j]; |
||
951 | + if (skb) { |
||
952 | + dev_kfree_skb(skb); |
||
953 | + sp->tx_skb[j] = NULL; |
||
954 | + } |
||
955 | + } |
||
956 | +} |
||
957 | + |
||
958 | +/** |
||
959 | + * close should do nothing. Here's why. It's called when |
||
960 | + * 'ifconfig bond0 down' is run. If it calls free_irq then |
||
961 | + * the irq is gone forever ! When bond0 is made 'up' again, |
||
962 | + * the ar231x_open () does not call request_irq (). Worse, |
||
963 | + * the call to ar231x_halt() generates a WDOG reset due to |
||
964 | + * the write to reset register and the box reboots. |
||
965 | + * Commenting this out is good since it allows the |
||
966 | + * system to resume when bond0 is made up again. |
||
967 | + */ |
||
968 | +static int ar231x_close(struct net_device *dev) |
||
969 | +{ |
||
970 | + struct ar231x_private *sp = netdev_priv(dev); |
||
971 | +#if 0 |
||
972 | + /* Disable interrupts */ |
||
973 | + disable_irq(dev->irq); |
||
974 | + |
||
975 | + /** |
||
976 | + * Without (or before) releasing irq and stopping hardware, this |
||
977 | + * is an absolute non-sense, by the way. It will be reset instantly |
||
978 | + * by the first irq. |
||
979 | + */ |
||
980 | + netif_stop_queue(dev); |
||
981 | + |
||
982 | + /* stop the MAC and DMA engines */ |
||
983 | + ar231x_halt(dev); |
||
984 | + |
||
985 | + /* release the interrupt */ |
||
986 | + free_irq(dev->irq, dev); |
||
987 | + |
||
988 | +#endif |
||
989 | + |
||
990 | + phy_stop(sp->phy_dev); |
||
991 | + |
||
992 | + return 0; |
||
993 | +} |
||
994 | + |
||
995 | +static int ar231x_start_xmit(struct sk_buff *skb, struct net_device *dev) |
||
996 | +{ |
||
997 | + struct ar231x_private *sp = netdev_priv(dev); |
||
998 | + ar231x_descr_t *td; |
||
999 | + u32 idx; |
||
1000 | + |
||
1001 | + idx = sp->tx_prd; |
||
1002 | + td = &sp->tx_ring[idx]; |
||
1003 | + |
||
1004 | + if (td->status & DMA_TX_OWN) { |
||
1005 | + /* free skbuf and lie to the caller that we sent it out */ |
||
1006 | + dev->stats.tx_dropped++; |
||
1007 | + dev_kfree_skb(skb); |
||
1008 | + |
||
1009 | + /* restart transmitter in case locked */ |
||
1010 | + sp->dma_regs->xmt_poll = 0; |
||
1011 | + return 0; |
||
1012 | + } |
||
1013 | + |
||
1014 | + /* Setup the transmit descriptor. */ |
||
1015 | + td->devcs = ((skb->len << DMA_TX1_BSIZE_SHIFT) | |
||
1016 | + (DMA_TX1_LS | DMA_TX1_IC | DMA_TX1_CHAINED)); |
||
1017 | + td->addr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE); |
||
1018 | + td->status = DMA_TX_OWN; |
||
1019 | + |
||
1020 | + /* kick transmitter last */ |
||
1021 | + sp->dma_regs->xmt_poll = 0; |
||
1022 | + |
||
1023 | + sp->tx_skb[idx] = skb; |
||
1024 | + idx = DSC_NEXT(idx); |
||
1025 | + sp->tx_prd = idx; |
||
1026 | + |
||
1027 | + return 0; |
||
1028 | +} |
||
1029 | + |
||
1030 | +static int ar231x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
||
1031 | +{ |
||
1032 | + struct ar231x_private *sp = netdev_priv(dev); |
||
1033 | + |
||
1034 | + switch (cmd) { |
||
1035 | + case SIOCGMIIPHY: |
||
1036 | + case SIOCGMIIREG: |
||
1037 | + case SIOCSMIIREG: |
||
1038 | + return phy_mii_ioctl(sp->phy_dev, ifr, cmd); |
||
1039 | + |
||
1040 | + default: |
||
1041 | + break; |
||
1042 | + } |
||
1043 | + |
||
1044 | + return -EOPNOTSUPP; |
||
1045 | +} |
||
1046 | + |
||
1047 | +static void ar231x_adjust_link(struct net_device *dev) |
||
1048 | +{ |
||
1049 | + struct ar231x_private *sp = netdev_priv(dev); |
||
1050 | + struct phy_device *phydev = sp->phy_dev; |
||
1051 | + u32 mc; |
||
1052 | + |
||
1053 | + if (!phydev->link) { |
||
1054 | + if (sp->link) { |
||
1055 | + pr_info("%s: link down\n", dev->name); |
||
1056 | + sp->link = 0; |
||
1057 | + } |
||
1058 | + return; |
||
1059 | + } |
||
1060 | + sp->link = 1; |
||
1061 | + |
||
1062 | + pr_info("%s: link up (%uMbps/%s duplex)\n", dev->name, |
||
1063 | + phydev->speed, phydev->duplex ? "full" : "half"); |
||
1064 | + |
||
1065 | + mc = sp->eth_regs->mac_control; |
||
1066 | + if (phydev->duplex) |
||
1067 | + mc = (mc | MAC_CONTROL_F) & ~MAC_CONTROL_DRO; |
||
1068 | + else |
||
1069 | + mc = (mc | MAC_CONTROL_DRO) & ~MAC_CONTROL_F; |
||
1070 | + sp->eth_regs->mac_control = mc; |
||
1071 | + sp->duplex = phydev->duplex; |
||
1072 | +} |
||
1073 | + |
||
1074 | +#define MII_ADDR(phy, reg) \ |
||
1075 | + ((reg << MII_ADDR_REG_SHIFT) | (phy << MII_ADDR_PHY_SHIFT)) |
||
1076 | + |
||
1077 | +static int |
||
1078 | +ar231x_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum) |
||
1079 | +{ |
||
1080 | + struct net_device *const dev = bus->priv; |
||
1081 | + struct ar231x_private *sp = netdev_priv(dev); |
||
1082 | + volatile MII *ethernet = sp->phy_regs; |
||
1083 | + |
||
1084 | + ethernet->mii_addr = MII_ADDR(phy_addr, regnum); |
||
1085 | + while (ethernet->mii_addr & MII_ADDR_BUSY) |
||
1086 | + ; |
||
1087 | + return ethernet->mii_data >> MII_DATA_SHIFT; |
||
1088 | +} |
||
1089 | + |
||
1090 | +static int |
||
1091 | +ar231x_mdiobus_write(struct mii_bus *bus, int phy_addr, int regnum, u16 value) |
||
1092 | +{ |
||
1093 | + struct net_device *const dev = bus->priv; |
||
1094 | + struct ar231x_private *sp = netdev_priv(dev); |
||
1095 | + volatile MII *ethernet = sp->phy_regs; |
||
1096 | + |
||
1097 | + while (ethernet->mii_addr & MII_ADDR_BUSY) |
||
1098 | + ; |
||
1099 | + ethernet->mii_data = value << MII_DATA_SHIFT; |
||
1100 | + ethernet->mii_addr = MII_ADDR(phy_addr, regnum) | MII_ADDR_WRITE; |
||
1101 | + |
||
1102 | + return 0; |
||
1103 | +} |
||
1104 | + |
||
1105 | +static int ar231x_mdiobus_reset(struct mii_bus *bus) |
||
1106 | +{ |
||
1107 | + struct net_device *const dev = bus->priv; |
||
1108 | + |
||
1109 | + ar231x_reset_reg(dev); |
||
1110 | + |
||
1111 | + return 0; |
||
1112 | +} |
||
1113 | + |
||
1114 | +static int ar231x_mdiobus_probe(struct net_device *dev) |
||
1115 | +{ |
||
1116 | + struct ar231x_private *const sp = netdev_priv(dev); |
||
1117 | + struct phy_device *phydev = NULL; |
||
1118 | + |
||
1119 | + /* find the first (lowest address) PHY on the current MAC's MII bus */ |
||
1120 | + phydev = phy_find_first(sp->mii_bus); |
||
1121 | + if (!phydev) { |
||
1122 | + printk(KERN_ERR "ar231x: %s: no PHY found\n", dev->name); |
||
1123 | + return -1; |
||
1124 | + } |
||
1125 | + |
||
1126 | + /* now we are supposed to have a proper phydev, to attach to... */ |
||
1127 | + BUG_ON(phydev->attached_dev); |
||
1128 | + |
||
1129 | + phydev = phy_connect(dev, phydev_name(phydev), &ar231x_adjust_link, |
||
1130 | + PHY_INTERFACE_MODE_MII); |
||
1131 | + if (IS_ERR(phydev)) { |
||
1132 | + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); |
||
1133 | + return PTR_ERR(phydev); |
||
1134 | + } |
||
1135 | + |
||
1136 | + /* mask with MAC supported features */ |
||
1137 | + phydev->supported &= (SUPPORTED_10baseT_Half |
||
1138 | + | SUPPORTED_10baseT_Full |
||
1139 | + | SUPPORTED_100baseT_Half |
||
1140 | + | SUPPORTED_100baseT_Full |
||
1141 | + | SUPPORTED_Autoneg |
||
1142 | + /* | SUPPORTED_Pause | SUPPORTED_Asym_Pause */ |
||
1143 | + | SUPPORTED_MII |
||
1144 | + | SUPPORTED_TP); |
||
1145 | + |
||
1146 | + phydev->advertising = phydev->supported; |
||
1147 | + |
||
1148 | + sp->phy_dev = phydev; |
||
1149 | + |
||
1150 | + printk(KERN_INFO "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n", |
||
1151 | + dev->name, phydev->drv->name, phydev_name(phydev)); |
||
1152 | + |
||
1153 | + return 0; |
||
1154 | +} |
||
1155 | + |
||
1156 | --- /dev/null |
||
1157 | +++ b/drivers/net/ethernet/atheros/ar231x/ar231x.h |
||
1158 | @@ -0,0 +1,281 @@ |
||
1159 | +/* |
||
1160 | + * ar231x.h: Linux driver for the Atheros AR231x Ethernet device. |
||
1161 | + * |
||
1162 | + * Copyright (C) 2004 by Sameer Dekate <sdekate@arubanetworks.com> |
||
1163 | + * Copyright (C) 2006 Imre Kaloz <kaloz@openwrt.org> |
||
1164 | + * Copyright (C) 2006-2009 Felix Fietkau <nbd@nbd.name> |
||
1165 | + * |
||
1166 | + * Thanks to Atheros for providing hardware and documentation |
||
1167 | + * enabling me to write this driver. |
||
1168 | + * |
||
1169 | + * This program is free software; you can redistribute it and/or modify |
||
1170 | + * it under the terms of the GNU General Public License as published by |
||
1171 | + * the Free Software Foundation; either version 2 of the License, or |
||
1172 | + * (at your option) any later version. |
||
1173 | + */ |
||
1174 | + |
||
1175 | +#ifndef _AR2313_H_ |
||
1176 | +#define _AR2313_H_ |
||
1177 | + |
||
1178 | +#include <linux/interrupt.h> |
||
1179 | +#include <generated/autoconf.h> |
||
1180 | +#include <linux/bitops.h> |
||
1181 | +#include <ath25_platform.h> |
||
1182 | + |
||
1183 | +/* probe link timer - 5 secs */ |
||
1184 | +#define LINK_TIMER (5*HZ) |
||
1185 | + |
||
1186 | +#define IS_DMA_TX_INT(X) (((X) & (DMA_STATUS_TI)) != 0) |
||
1187 | +#define IS_DMA_RX_INT(X) (((X) & (DMA_STATUS_RI)) != 0) |
||
1188 | +#define IS_DRIVER_OWNED(X) (((X) & (DMA_TX_OWN)) == 0) |
||
1189 | + |
||
1190 | +#define AR2313_TX_TIMEOUT (HZ/4) |
||
1191 | + |
||
1192 | +/* Rings */ |
||
1193 | +#define DSC_RING_ENTRIES_SIZE (AR2313_DESCR_ENTRIES * sizeof(struct desc)) |
||
1194 | +#define DSC_NEXT(idx) ((idx + 1) & (AR2313_DESCR_ENTRIES - 1)) |
||
1195 | + |
||
1196 | +#define AR2313_MBGET 2 |
||
1197 | +#define AR2313_MBSET 3 |
||
1198 | +#define AR2313_PCI_RECONFIG 4 |
||
1199 | +#define AR2313_PCI_DUMP 5 |
||
1200 | +#define AR2313_TEST_PANIC 6 |
||
1201 | +#define AR2313_TEST_NULLPTR 7 |
||
1202 | +#define AR2313_READ_DATA 8 |
||
1203 | +#define AR2313_WRITE_DATA 9 |
||
1204 | +#define AR2313_GET_VERSION 10 |
||
1205 | +#define AR2313_TEST_HANG 11 |
||
1206 | +#define AR2313_SYNC 12 |
||
1207 | + |
||
1208 | +#define DMA_RX_ERR_CRC BIT(1) |
||
1209 | +#define DMA_RX_ERR_DRIB BIT(2) |
||
1210 | +#define DMA_RX_ERR_MII BIT(3) |
||
1211 | +#define DMA_RX_EV2 BIT(5) |
||
1212 | +#define DMA_RX_ERR_COL BIT(6) |
||
1213 | +#define DMA_RX_LONG BIT(7) |
||
1214 | +#define DMA_RX_LS BIT(8) /* last descriptor */ |
||
1215 | +#define DMA_RX_FS BIT(9) /* first descriptor */ |
||
1216 | +#define DMA_RX_MF BIT(10) /* multicast frame */ |
||
1217 | +#define DMA_RX_ERR_RUNT BIT(11) /* runt frame */ |
||
1218 | +#define DMA_RX_ERR_LENGTH BIT(12) /* length error */ |
||
1219 | +#define DMA_RX_ERR_DESC BIT(14) /* descriptor error */ |
||
1220 | +#define DMA_RX_ERROR BIT(15) /* error summary */ |
||
1221 | +#define DMA_RX_LEN_MASK 0x3fff0000 |
||
1222 | +#define DMA_RX_LEN_SHIFT 16 |
||
1223 | +#define DMA_RX_FILT BIT(30) |
||
1224 | +#define DMA_RX_OWN BIT(31) /* desc owned by DMA controller */ |
||
1225 | + |
||
1226 | +#define DMA_RX1_BSIZE_MASK 0x000007ff |
||
1227 | +#define DMA_RX1_BSIZE_SHIFT 0 |
||
1228 | +#define DMA_RX1_CHAINED BIT(24) |
||
1229 | +#define DMA_RX1_RER BIT(25) |
||
1230 | + |
||
1231 | +#define DMA_TX_ERR_UNDER BIT(1) /* underflow error */ |
||
1232 | +#define DMA_TX_ERR_DEFER BIT(2) /* excessive deferral */ |
||
1233 | +#define DMA_TX_COL_MASK 0x78 |
||
1234 | +#define DMA_TX_COL_SHIFT 3 |
||
1235 | +#define DMA_TX_ERR_HB BIT(7) /* hearbeat failure */ |
||
1236 | +#define DMA_TX_ERR_COL BIT(8) /* excessive collisions */ |
||
1237 | +#define DMA_TX_ERR_LATE BIT(9) /* late collision */ |
||
1238 | +#define DMA_TX_ERR_LINK BIT(10) /* no carrier */ |
||
1239 | +#define DMA_TX_ERR_LOSS BIT(11) /* loss of carrier */ |
||
1240 | +#define DMA_TX_ERR_JABBER BIT(14) /* transmit jabber timeout */ |
||
1241 | +#define DMA_TX_ERROR BIT(15) /* frame aborted */ |
||
1242 | +#define DMA_TX_OWN BIT(31) /* descr owned by DMA controller */ |
||
1243 | + |
||
1244 | +#define DMA_TX1_BSIZE_MASK 0x000007ff |
||
1245 | +#define DMA_TX1_BSIZE_SHIFT 0 |
||
1246 | +#define DMA_TX1_CHAINED BIT(24) /* chained descriptors */ |
||
1247 | +#define DMA_TX1_TER BIT(25) /* transmit end of ring */ |
||
1248 | +#define DMA_TX1_FS BIT(29) /* first segment */ |
||
1249 | +#define DMA_TX1_LS BIT(30) /* last segment */ |
||
1250 | +#define DMA_TX1_IC BIT(31) /* interrupt on completion */ |
||
1251 | + |
||
1252 | +#define RCVPKT_LENGTH(X) (X >> 16) /* Received pkt Length */ |
||
1253 | + |
||
1254 | +#define MAC_CONTROL_RE BIT(2) /* receive enable */ |
||
1255 | +#define MAC_CONTROL_TE BIT(3) /* transmit enable */ |
||
1256 | +#define MAC_CONTROL_DC BIT(5) /* Deferral check */ |
||
1257 | +#define MAC_CONTROL_ASTP BIT(8) /* Auto pad strip */ |
||
1258 | +#define MAC_CONTROL_DRTY BIT(10) /* Disable retry */ |
||
1259 | +#define MAC_CONTROL_DBF BIT(11) /* Disable bcast frames */ |
||
1260 | +#define MAC_CONTROL_LCC BIT(12) /* late collision ctrl */ |
||
1261 | +#define MAC_CONTROL_HP BIT(13) /* Hash Perfect filtering */ |
||
1262 | +#define MAC_CONTROL_HASH BIT(14) /* Unicast hash filtering */ |
||
1263 | +#define MAC_CONTROL_HO BIT(15) /* Hash only filtering */ |
||
1264 | +#define MAC_CONTROL_PB BIT(16) /* Pass Bad frames */ |
||
1265 | +#define MAC_CONTROL_IF BIT(17) /* Inverse filtering */ |
||
1266 | +#define MAC_CONTROL_PR BIT(18) /* promis mode (valid frames only) */ |
||
1267 | +#define MAC_CONTROL_PM BIT(19) /* pass multicast */ |
||
1268 | +#define MAC_CONTROL_F BIT(20) /* full-duplex */ |
||
1269 | +#define MAC_CONTROL_DRO BIT(23) /* Disable Receive Own */ |
||
1270 | +#define MAC_CONTROL_HBD BIT(28) /* heart-beat disabled (MUST BE SET) */ |
||
1271 | +#define MAC_CONTROL_BLE BIT(30) /* big endian mode */ |
||
1272 | +#define MAC_CONTROL_RA BIT(31) /* rcv all (valid and invalid frames) */ |
||
1273 | + |
||
1274 | +#define MII_ADDR_BUSY BIT(0) |
||
1275 | +#define MII_ADDR_WRITE BIT(1) |
||
1276 | +#define MII_ADDR_REG_SHIFT 6 |
||
1277 | +#define MII_ADDR_PHY_SHIFT 11 |
||
1278 | +#define MII_DATA_SHIFT 0 |
||
1279 | + |
||
1280 | +#define FLOW_CONTROL_FCE BIT(1) |
||
1281 | + |
||
1282 | +#define DMA_BUS_MODE_SWR BIT(0) /* software reset */ |
||
1283 | +#define DMA_BUS_MODE_BLE BIT(7) /* big endian mode */ |
||
1284 | +#define DMA_BUS_MODE_PBL_SHIFT 8 /* programmable burst length 32 */ |
||
1285 | +#define DMA_BUS_MODE_DBO BIT(20) /* big-endian descriptors */ |
||
1286 | + |
||
1287 | +#define DMA_STATUS_TI BIT(0) /* transmit interrupt */ |
||
1288 | +#define DMA_STATUS_TPS BIT(1) /* transmit process stopped */ |
||
1289 | +#define DMA_STATUS_TU BIT(2) /* transmit buffer unavailable */ |
||
1290 | +#define DMA_STATUS_TJT BIT(3) /* transmit buffer timeout */ |
||
1291 | +#define DMA_STATUS_UNF BIT(5) /* transmit underflow */ |
||
1292 | +#define DMA_STATUS_RI BIT(6) /* receive interrupt */ |
||
1293 | +#define DMA_STATUS_RU BIT(7) /* receive buffer unavailable */ |
||
1294 | +#define DMA_STATUS_RPS BIT(8) /* receive process stopped */ |
||
1295 | +#define DMA_STATUS_ETI BIT(10) /* early transmit interrupt */ |
||
1296 | +#define DMA_STATUS_FBE BIT(13) /* fatal bus interrupt */ |
||
1297 | +#define DMA_STATUS_ERI BIT(14) /* early receive interrupt */ |
||
1298 | +#define DMA_STATUS_AIS BIT(15) /* abnormal interrupt summary */ |
||
1299 | +#define DMA_STATUS_NIS BIT(16) /* normal interrupt summary */ |
||
1300 | +#define DMA_STATUS_RS_SHIFT 17 /* receive process state */ |
||
1301 | +#define DMA_STATUS_TS_SHIFT 20 /* transmit process state */ |
||
1302 | +#define DMA_STATUS_EB_SHIFT 23 /* error bits */ |
||
1303 | + |
||
1304 | +#define DMA_CONTROL_SR BIT(1) /* start receive */ |
||
1305 | +#define DMA_CONTROL_ST BIT(13) /* start transmit */ |
||
1306 | +#define DMA_CONTROL_SF BIT(21) /* store and forward */ |
||
1307 | + |
||
1308 | +typedef struct { |
||
1309 | + volatile unsigned int status; /* OWN, Device control and status. */ |
||
1310 | + volatile unsigned int devcs; /* pkt Control bits + Length */ |
||
1311 | + volatile unsigned int addr; /* Current Address. */ |
||
1312 | + volatile unsigned int descr; /* Next descriptor in chain. */ |
||
1313 | +} ar231x_descr_t; |
||
1314 | + |
||
1315 | +/** |
||
1316 | + * New Combo structure for Both Eth0 AND eth1 |
||
1317 | + * |
||
1318 | + * Don't directly access MII related regs since phy chip could be actually |
||
1319 | + * connected to another ethernet block. |
||
1320 | + */ |
||
1321 | +typedef struct { |
||
1322 | + volatile unsigned int mac_control; /* 0x00 */ |
||
1323 | + volatile unsigned int mac_addr[2]; /* 0x04 - 0x08 */ |
||
1324 | + volatile unsigned int mcast_table[2]; /* 0x0c - 0x10 */ |
||
1325 | + volatile unsigned int __mii_addr; /* 0x14 */ |
||
1326 | + volatile unsigned int __mii_data; /* 0x18 */ |
||
1327 | + volatile unsigned int flow_control; /* 0x1c */ |
||
1328 | + volatile unsigned int vlan_tag; /* 0x20 */ |
||
1329 | + volatile unsigned int pad[7]; /* 0x24 - 0x3c */ |
||
1330 | + volatile unsigned int ucast_table[8]; /* 0x40-0x5c */ |
||
1331 | +} ETHERNET_STRUCT; |
||
1332 | + |
||
1333 | +typedef struct { |
||
1334 | + volatile unsigned int mii_addr; |
||
1335 | + volatile unsigned int mii_data; |
||
1336 | +} MII; |
||
1337 | + |
||
1338 | +/******************************************************************** |
||
1339 | + * Interrupt controller |
||
1340 | + ********************************************************************/ |
||
1341 | + |
||
1342 | +typedef struct { |
||
1343 | + volatile unsigned int wdog_control; /* 0x08 */ |
||
1344 | + volatile unsigned int wdog_timer; /* 0x0c */ |
||
1345 | + volatile unsigned int misc_status; /* 0x10 */ |
||
1346 | + volatile unsigned int misc_mask; /* 0x14 */ |
||
1347 | + volatile unsigned int global_status; /* 0x18 */ |
||
1348 | + volatile unsigned int reserved; /* 0x1c */ |
||
1349 | + volatile unsigned int reset_control; /* 0x20 */ |
||
1350 | +} INTERRUPT; |
||
1351 | + |
||
1352 | +/******************************************************************** |
||
1353 | + * DMA controller |
||
1354 | + ********************************************************************/ |
||
1355 | +typedef struct { |
||
1356 | + volatile unsigned int bus_mode; /* 0x00 (CSR0) */ |
||
1357 | + volatile unsigned int xmt_poll; /* 0x04 (CSR1) */ |
||
1358 | + volatile unsigned int rcv_poll; /* 0x08 (CSR2) */ |
||
1359 | + volatile unsigned int rcv_base; /* 0x0c (CSR3) */ |
||
1360 | + volatile unsigned int xmt_base; /* 0x10 (CSR4) */ |
||
1361 | + volatile unsigned int status; /* 0x14 (CSR5) */ |
||
1362 | + volatile unsigned int control; /* 0x18 (CSR6) */ |
||
1363 | + volatile unsigned int intr_ena; /* 0x1c (CSR7) */ |
||
1364 | + volatile unsigned int rcv_missed; /* 0x20 (CSR8) */ |
||
1365 | + volatile unsigned int reserved[11]; /* 0x24-0x4c (CSR9-19) */ |
||
1366 | + volatile unsigned int cur_tx_buf_addr; /* 0x50 (CSR20) */ |
||
1367 | + volatile unsigned int cur_rx_buf_addr; /* 0x50 (CSR21) */ |
||
1368 | +} DMA; |
||
1369 | + |
||
1370 | +/** |
||
1371 | + * Struct private for the Sibyte. |
||
1372 | + * |
||
1373 | + * Elements are grouped so variables used by the tx handling goes |
||
1374 | + * together, and will go into the same cache lines etc. in order to |
||
1375 | + * avoid cache line contention between the rx and tx handling on SMP. |
||
1376 | + * |
||
1377 | + * Frequently accessed variables are put at the beginning of the |
||
1378 | + * struct to help the compiler generate better/shorter code. |
||
1379 | + */ |
||
1380 | +struct ar231x_private { |
||
1381 | + struct net_device *dev; |
||
1382 | + int version; |
||
1383 | + u32 mb[2]; |
||
1384 | + |
||
1385 | + volatile MII *phy_regs; |
||
1386 | + volatile ETHERNET_STRUCT *eth_regs; |
||
1387 | + volatile DMA *dma_regs; |
||
1388 | + struct ar231x_eth *cfg; |
||
1389 | + |
||
1390 | + spinlock_t lock; /* Serialise access to device */ |
||
1391 | + |
||
1392 | + /* RX and TX descriptors, must be adjacent */ |
||
1393 | + ar231x_descr_t *rx_ring; |
||
1394 | + ar231x_descr_t *tx_ring; |
||
1395 | + |
||
1396 | + struct sk_buff **rx_skb; |
||
1397 | + struct sk_buff **tx_skb; |
||
1398 | + |
||
1399 | + /* RX elements */ |
||
1400 | + u32 rx_skbprd; |
||
1401 | + u32 cur_rx; |
||
1402 | + |
||
1403 | + /* TX elements */ |
||
1404 | + u32 tx_prd; |
||
1405 | + u32 tx_csm; |
||
1406 | + |
||
1407 | + /* Misc elements */ |
||
1408 | + char name[48]; |
||
1409 | + struct { |
||
1410 | + u32 address; |
||
1411 | + u32 length; |
||
1412 | + char *mapping; |
||
1413 | + } desc; |
||
1414 | + |
||
1415 | + unsigned short link; /* 0 - link down, 1 - link up */ |
||
1416 | + unsigned short duplex; /* 0 - half, 1 - full */ |
||
1417 | + |
||
1418 | + struct tasklet_struct rx_tasklet; |
||
1419 | + int unloading; |
||
1420 | + |
||
1421 | + struct phy_device *phy_dev; |
||
1422 | + struct mii_bus *mii_bus; |
||
1423 | +}; |
||
1424 | + |
||
1425 | +/* Prototypes */ |
||
1426 | +static int ar231x_init(struct net_device *dev); |
||
1427 | +#ifdef TX_TIMEOUT |
||
1428 | +static void ar231x_tx_timeout(struct net_device *dev); |
||
1429 | +#endif |
||
1430 | +static int ar231x_restart(struct net_device *dev); |
||
1431 | +static void ar231x_load_rx_ring(struct net_device *dev, int bufs); |
||
1432 | +static irqreturn_t ar231x_interrupt(int irq, void *dev_id); |
||
1433 | +static int ar231x_open(struct net_device *dev); |
||
1434 | +static int ar231x_start_xmit(struct sk_buff *skb, struct net_device *dev); |
||
1435 | +static int ar231x_close(struct net_device *dev); |
||
1436 | +static int ar231x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); |
||
1437 | +static void ar231x_init_cleanup(struct net_device *dev); |
||
1438 | + |
||
1439 | +#endif /* _AR2313_H_ */ |
||
1440 | --- a/arch/mips/ath25/ar2315_regs.h |
||
1441 | +++ b/arch/mips/ath25/ar2315_regs.h |
||
1442 | @@ -57,6 +57,9 @@ |
||
1443 | #define AR2315_PCI_EXT_BASE 0x80000000 /* PCI external */ |
||
1444 | #define AR2315_PCI_EXT_SIZE 0x40000000 |
||
1445 | |||
1446 | +/* MII registers offset inside Ethernet MMR region */ |
||
1447 | +#define AR2315_ENET0_MII_BASE (AR2315_ENET0_BASE + 0x14) |
||
1448 | + |
||
1449 | /* |
||
1450 | * Configuration registers |
||
1451 | */ |
||
1452 | --- a/arch/mips/ath25/ar5312_regs.h |
||
1453 | +++ b/arch/mips/ath25/ar5312_regs.h |
||
1454 | @@ -64,6 +64,10 @@ |
||
1455 | #define AR5312_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ |
||
1456 | #define AR5312_AR2313_REV8 0x0058 /* AR2313 WMAC (AP43-030) */ |
||
1457 | |||
1458 | +/* MII registers offset inside Ethernet MMR region */ |
||
1459 | +#define AR5312_ENET0_MII_BASE (AR5312_ENET0_BASE + 0x14) |
||
1460 | +#define AR5312_ENET1_MII_BASE (AR5312_ENET1_BASE + 0x14) |
||
1461 | + |
||
1462 | /* Reset/Timer Block Address Map */ |
||
1463 | #define AR5312_TIMER 0x0000 /* countdown timer */ |
||
1464 | #define AR5312_RELOAD 0x0004 /* timer reload value */ |
||
1465 | --- a/arch/mips/ath25/ar2315.c |
||
1466 | +++ b/arch/mips/ath25/ar2315.c |
||
1467 | @@ -136,6 +136,8 @@ static void ar2315_irq_dispatch(void) |
||
1468 | |||
1469 | if (pending & CAUSEF_IP3) |
||
1470 | do_IRQ(AR2315_IRQ_WLAN0); |
||
1471 | + else if (pending & CAUSEF_IP4) |
||
1472 | + do_IRQ(AR2315_IRQ_ENET0); |
||
1473 | #ifdef CONFIG_PCI_AR2315 |
||
1474 | else if (pending & CAUSEF_IP5) |
||
1475 | do_IRQ(AR2315_IRQ_LCBUS_PCI); |
||
1476 | @@ -169,6 +171,29 @@ void __init ar2315_arch_init_irq(void) |
||
1477 | ar2315_misc_irq_domain = domain; |
||
1478 | } |
||
1479 | |||
1480 | +static void ar2315_device_reset_set(u32 mask) |
||
1481 | +{ |
||
1482 | + u32 val; |
||
1483 | + |
||
1484 | + val = ar2315_rst_reg_read(AR2315_RESET); |
||
1485 | + ar2315_rst_reg_write(AR2315_RESET, val | mask); |
||
1486 | +} |
||
1487 | + |
||
1488 | +static void ar2315_device_reset_clear(u32 mask) |
||
1489 | +{ |
||
1490 | + u32 val; |
||
1491 | + |
||
1492 | + val = ar2315_rst_reg_read(AR2315_RESET); |
||
1493 | + ar2315_rst_reg_write(AR2315_RESET, val & ~mask); |
||
1494 | +} |
||
1495 | + |
||
1496 | +static struct ar231x_eth ar2315_eth_data = { |
||
1497 | + .reset_set = ar2315_device_reset_set, |
||
1498 | + .reset_clear = ar2315_device_reset_clear, |
||
1499 | + .reset_mac = AR2315_RESET_ENET0, |
||
1500 | + .reset_phy = AR2315_RESET_EPHY0, |
||
1501 | +}; |
||
1502 | + |
||
1503 | static struct resource ar2315_gpio_res[] = { |
||
1504 | { |
||
1505 | .name = "ar2315-gpio", |
||
1506 | @@ -205,6 +230,11 @@ void __init ar2315_init_devices(void) |
||
1507 | ar2315_gpio_res[1].end = ar2315_gpio_res[1].start; |
||
1508 | platform_device_register(&ar2315_gpio); |
||
1509 | |||
1510 | + ar2315_eth_data.macaddr = ath25_board.config->enet0_mac; |
||
1511 | + ath25_add_ethernet(0, AR2315_ENET0_BASE, "eth0_mii", |
||
1512 | + AR2315_ENET0_MII_BASE, AR2315_IRQ_ENET0, |
||
1513 | + &ar2315_eth_data); |
||
1514 | + |
||
1515 | ath25_add_wmac(0, AR2315_WLAN0_BASE, AR2315_IRQ_WLAN0); |
||
1516 | } |
||
1517 | |||
1518 | --- a/arch/mips/ath25/ar5312.c |
||
1519 | +++ b/arch/mips/ath25/ar5312.c |
||
1520 | @@ -132,6 +132,10 @@ static void ar5312_irq_dispatch(void) |
||
1521 | |||
1522 | if (pending & CAUSEF_IP2) |
||
1523 | do_IRQ(AR5312_IRQ_WLAN0); |
||
1524 | + else if (pending & CAUSEF_IP3) |
||
1525 | + do_IRQ(AR5312_IRQ_ENET0); |
||
1526 | + else if (pending & CAUSEF_IP4) |
||
1527 | + do_IRQ(AR5312_IRQ_ENET1); |
||
1528 | else if (pending & CAUSEF_IP5) |
||
1529 | do_IRQ(AR5312_IRQ_WLAN1); |
||
1530 | else if (pending & CAUSEF_IP6) |
||
1531 | @@ -163,6 +167,36 @@ void __init ar5312_arch_init_irq(void) |
||
1532 | ar5312_misc_irq_domain = domain; |
||
1533 | } |
||
1534 | |||
1535 | +static void ar5312_device_reset_set(u32 mask) |
||
1536 | +{ |
||
1537 | + u32 val; |
||
1538 | + |
||
1539 | + val = ar5312_rst_reg_read(AR5312_RESET); |
||
1540 | + ar5312_rst_reg_write(AR5312_RESET, val | mask); |
||
1541 | +} |
||
1542 | + |
||
1543 | +static void ar5312_device_reset_clear(u32 mask) |
||
1544 | +{ |
||
1545 | + u32 val; |
||
1546 | + |
||
1547 | + val = ar5312_rst_reg_read(AR5312_RESET); |
||
1548 | + ar5312_rst_reg_write(AR5312_RESET, val & ~mask); |
||
1549 | +} |
||
1550 | + |
||
1551 | +static struct ar231x_eth ar5312_eth0_data = { |
||
1552 | + .reset_set = ar5312_device_reset_set, |
||
1553 | + .reset_clear = ar5312_device_reset_clear, |
||
1554 | + .reset_mac = AR5312_RESET_ENET0, |
||
1555 | + .reset_phy = AR5312_RESET_EPHY0, |
||
1556 | +}; |
||
1557 | + |
||
1558 | +static struct ar231x_eth ar5312_eth1_data = { |
||
1559 | + .reset_set = ar5312_device_reset_set, |
||
1560 | + .reset_clear = ar5312_device_reset_clear, |
||
1561 | + .reset_mac = AR5312_RESET_ENET1, |
||
1562 | + .reset_phy = AR5312_RESET_EPHY1, |
||
1563 | +}; |
||
1564 | + |
||
1565 | static struct physmap_flash_data ar5312_flash_data = { |
||
1566 | .width = 2, |
||
1567 | }; |
||
1568 | @@ -243,6 +277,7 @@ static void __init ar5312_flash_init(voi |
||
1569 | void __init ar5312_init_devices(void) |
||
1570 | { |
||
1571 | struct ath25_boarddata *config; |
||
1572 | + u8 *c; |
||
1573 | |||
1574 | ar5312_flash_init(); |
||
1575 | |||
1576 | @@ -266,8 +301,30 @@ void __init ar5312_init_devices(void) |
||
1577 | |||
1578 | platform_device_register(&ar5312_gpio); |
||
1579 | |||
1580 | + /* Fix up MAC addresses if necessary */ |
||
1581 | + if (is_broadcast_ether_addr(config->enet0_mac)) |
||
1582 | + ether_addr_copy(config->enet0_mac, config->enet1_mac); |
||
1583 | + |
||
1584 | + /* If ENET0 and ENET1 have the same mac address, |
||
1585 | + * increment the one from ENET1 */ |
||
1586 | + if (ether_addr_equal(config->enet0_mac, config->enet1_mac)) { |
||
1587 | + c = config->enet1_mac + 5; |
||
1588 | + while ((c >= config->enet1_mac) && !(++(*c))) |
||
1589 | + c--; |
||
1590 | + } |
||
1591 | + |
||
1592 | switch (ath25_soc) { |
||
1593 | case ATH25_SOC_AR5312: |
||
1594 | + ar5312_eth0_data.macaddr = config->enet0_mac; |
||
1595 | + ath25_add_ethernet(0, AR5312_ENET0_BASE, "eth0_mii", |
||
1596 | + AR5312_ENET0_MII_BASE, AR5312_IRQ_ENET0, |
||
1597 | + &ar5312_eth0_data); |
||
1598 | + |
||
1599 | + ar5312_eth1_data.macaddr = config->enet1_mac; |
||
1600 | + ath25_add_ethernet(1, AR5312_ENET1_BASE, "eth1_mii", |
||
1601 | + AR5312_ENET1_MII_BASE, AR5312_IRQ_ENET1, |
||
1602 | + &ar5312_eth1_data); |
||
1603 | + |
||
1604 | if (!ath25_board.radio) |
||
1605 | return; |
||
1606 | |||
1607 | @@ -276,8 +333,18 @@ void __init ar5312_init_devices(void) |
||
1608 | |||
1609 | ath25_add_wmac(0, AR5312_WLAN0_BASE, AR5312_IRQ_WLAN0); |
||
1610 | break; |
||
1611 | + /* |
||
1612 | + * AR2312/3 ethernet uses the PHY of ENET0, but the MAC |
||
1613 | + * of ENET1. Atheros calls it 'twisted' for a reason :) |
||
1614 | + */ |
||
1615 | case ATH25_SOC_AR2312: |
||
1616 | case ATH25_SOC_AR2313: |
||
1617 | + ar5312_eth1_data.reset_phy = ar5312_eth0_data.reset_phy; |
||
1618 | + ar5312_eth1_data.macaddr = config->enet0_mac; |
||
1619 | + ath25_add_ethernet(1, AR5312_ENET1_BASE, "eth0_mii", |
||
1620 | + AR5312_ENET0_MII_BASE, AR5312_IRQ_ENET1, |
||
1621 | + &ar5312_eth1_data); |
||
1622 | + |
||
1623 | if (!ath25_board.radio) |
||
1624 | return; |
||
1625 | break; |
||
1626 | --- a/arch/mips/ath25/devices.h |
||
1627 | +++ b/arch/mips/ath25/devices.h |
||
1628 | @@ -33,6 +33,8 @@ extern struct ar231x_board_config ath25_ |
||
1629 | extern void (*ath25_irq_dispatch)(void); |
||
1630 | |||
1631 | int ath25_find_config(phys_addr_t offset, unsigned long size); |
||
1632 | +int ath25_add_ethernet(int nr, u32 base, const char *mii_name, u32 mii_base, |
||
1633 | + int irq, void *pdata); |
||
1634 | void ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk); |
||
1635 | int ath25_add_wmac(int nr, u32 base, int irq); |
||
1636 | |||
1637 | --- a/arch/mips/ath25/devices.c |
||
1638 | +++ b/arch/mips/ath25/devices.c |
||
1639 | @@ -13,6 +13,51 @@ |
||
1640 | struct ar231x_board_config ath25_board; |
||
1641 | enum ath25_soc_type ath25_soc = ATH25_SOC_UNKNOWN; |
||
1642 | |||
1643 | +static struct resource ath25_eth0_res[] = { |
||
1644 | + { |
||
1645 | + .name = "eth0_membase", |
||
1646 | + .flags = IORESOURCE_MEM, |
||
1647 | + }, |
||
1648 | + { |
||
1649 | + .name = "eth0_mii", |
||
1650 | + .flags = IORESOURCE_MEM, |
||
1651 | + }, |
||
1652 | + { |
||
1653 | + .name = "eth0_irq", |
||
1654 | + .flags = IORESOURCE_IRQ, |
||
1655 | + } |
||
1656 | +}; |
||
1657 | + |
||
1658 | +static struct resource ath25_eth1_res[] = { |
||
1659 | + { |
||
1660 | + .name = "eth1_membase", |
||
1661 | + .flags = IORESOURCE_MEM, |
||
1662 | + }, |
||
1663 | + { |
||
1664 | + .name = "eth1_mii", |
||
1665 | + .flags = IORESOURCE_MEM, |
||
1666 | + }, |
||
1667 | + { |
||
1668 | + .name = "eth1_irq", |
||
1669 | + .flags = IORESOURCE_IRQ, |
||
1670 | + } |
||
1671 | +}; |
||
1672 | + |
||
1673 | +static struct platform_device ath25_eth[] = { |
||
1674 | + { |
||
1675 | + .id = 0, |
||
1676 | + .name = "ar231x-eth", |
||
1677 | + .resource = ath25_eth0_res, |
||
1678 | + .num_resources = ARRAY_SIZE(ath25_eth0_res) |
||
1679 | + }, |
||
1680 | + { |
||
1681 | + .id = 1, |
||
1682 | + .name = "ar231x-eth", |
||
1683 | + .resource = ath25_eth1_res, |
||
1684 | + .num_resources = ARRAY_SIZE(ath25_eth1_res) |
||
1685 | + } |
||
1686 | +}; |
||
1687 | + |
||
1688 | static struct resource ath25_wmac0_res[] = { |
||
1689 | { |
||
1690 | .name = "wmac0_membase", |
||
1691 | @@ -71,6 +116,25 @@ const char *get_system_type(void) |
||
1692 | return soc_type_strings[ath25_soc]; |
||
1693 | } |
||
1694 | |||
1695 | +int __init ath25_add_ethernet(int nr, u32 base, const char *mii_name, |
||
1696 | + u32 mii_base, int irq, void *pdata) |
||
1697 | +{ |
||
1698 | + struct resource *res; |
||
1699 | + |
||
1700 | + ath25_eth[nr].dev.platform_data = pdata; |
||
1701 | + res = &ath25_eth[nr].resource[0]; |
||
1702 | + res->start = base; |
||
1703 | + res->end = base + 0x2000 - 1; |
||
1704 | + res++; |
||
1705 | + res->name = mii_name; |
||
1706 | + res->start = mii_base; |
||
1707 | + res->end = mii_base + 8 - 1; |
||
1708 | + res++; |
||
1709 | + res->start = irq; |
||
1710 | + res->end = irq; |
||
1711 | + return platform_device_register(&ath25_eth[nr]); |
||
1712 | +} |
||
1713 | + |
||
1714 | void __init ath25_serial_setup(u32 mapbase, int irq, unsigned int uartclk) |
||
1715 | { |
||
1716 | struct uart_port s; |
||
1717 | --- a/arch/mips/include/asm/mach-ath25/ath25_platform.h |
||
1718 | +++ b/arch/mips/include/asm/mach-ath25/ath25_platform.h |
||
1719 | @@ -71,4 +71,15 @@ struct ar231x_board_config { |
||
1720 | const char *radio; |
||
1721 | }; |
||
1722 | |||
1723 | +/* |
||
1724 | + * Platform device information for the Ethernet MAC |
||
1725 | + */ |
||
1726 | +struct ar231x_eth { |
||
1727 | + void (*reset_set)(u32); |
||
1728 | + void (*reset_clear)(u32); |
||
1729 | + u32 reset_mac; |
||
1730 | + u32 reset_phy; |
||
1731 | + char *macaddr; |
||
1732 | +}; |
||
1733 | + |
||
1734 | #endif /* __ASM_MACH_ATH25_PLATFORM_H */ |