ramips: image: increase minimum kernel partition size to 896k
[openwrt.git] / target / linux / amazon / files / drivers / net / amazon_sw.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 */
16 //-----------------------------------------------------------------------
17 /*
18 * Description:
19 * Driver for Infineon Amazon 3 port switch
20 */
21 //-----------------------------------------------------------------------
22 /* Author: Wu Qi Ming[Qi-Ming.Wu@infineon.com]
23 * Created: 7-April-2004
24 */
25 //-----------------------------------------------------------------------
26 /* History
27 * Changed on: Jun 28, 2004
28 * Changed by: peng.liu@infineon.com
29 * Reason: add hardware flow control (HFC) (CONFIG_NET_HW_FLOWCONTROL)
30 *
31 * Changed on: Apr 6, 2005
32 * Changed by: mars.lin@infineon.com
33 * Reason : supoort port identification
34 */
35
36
37 // copyright 2004-2005 infineon.com
38
39 // copyright 2007 john crispin <blogic@openwrt.org>
40 // copyright 2007 felix fietkau <nbd@openwrt.org>
41 // copyright 2009 hauke mehrtens <hauke@hauke-m.de>
42
43
44 // TODO
45 // port vlan code from bcrm target... the tawainese code was scrapped due to crappyness
46 // check all the mmi reg settings and possibly document them better
47 // verify the ethtool code
48 // remove the while(1) stuff
49 // further clean up and rework ... but it works for now
50 // check the mode[]=bridge stuff
51 // verify that the ethaddr can be set from u-boot
52
53
54 #ifndef __KERNEL__
55 #define __KERNEL__
56 #endif
57
58
59 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
60 #define MODVERSIONS
61 #endif
62
63 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
64 #include <linux/modversions.h>
65 #endif
66
67 #include <linux/module.h>
68 #include <linux/string.h>
69 #include <linux/sched.h>
70 #include <linux/kernel.h>
71 #include <linux/slab.h>
72 #include <linux/errno.h>
73 #include <linux/types.h>
74 #include <linux/interrupt.h>
75 #include <linux/mii.h>
76 #include <asm/uaccess.h>
77 #include <linux/in.h>
78 #include <linux/netdevice.h>
79 #include <linux/etherdevice.h>
80 #include <linux/ip.h>
81 #include <linux/tcp.h>
82 #include <linux/skbuff.h>
83 #include <linux/in6.h>
84 #include <linux/proc_fs.h>
85 #include <linux/mm.h>
86 #include <linux/ethtool.h>
87 #include <asm/checksum.h>
88 #include <linux/init.h>
89 #include <linux/platform_device.h>
90
91 #include <asm/amazon/amazon.h>
92 #include <asm/amazon/amazon_dma.h>
93 #include <asm/amazon/amazon_sw.h>
94
95 // how many mii ports are there ?
96 #define AMAZON_SW_INT_NO 2
97
98 #define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
99
100 /***************************************** Module Parameters *************************************/
101 char mode[] = "bridge";
102 module_param_array(mode, charp, NULL, 0);
103
104 static int timeout = 1 * HZ;
105 module_param(timeout, int, 0);
106
107 int switch_init(struct net_device *dev);
108 void switch_tx_timeout(struct net_device *dev);
109
110 static struct net_device *switch_devs[2];
111
112 int add_mac_table_entry(u64 entry_value)
113 {
114 int i;
115 u32 data1, data2;
116
117 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = ~7;
118
119 for (i = 0; i < 32; i++) {
120 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | i;
121 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
122 data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1);
123 data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
124 if ((data1 & (0x00700000)) != 0x00700000)
125 continue;
126 AMAZON_SW_REG32(AMAZON_SW_DATA1) = (u32) (entry_value >> 32);
127 AMAZON_SW_REG32(AMAZON_SW_DATA2) = (u32) entry_value & 0xffffffff;
128 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | i;
129 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
130 break;
131 }
132 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) |= 7;
133 if (i >= 32)
134 return -1;
135 return OK;
136 }
137
138 u64 read_mac_table_entry(int index)
139 {
140 u32 data1, data2;
141 u64 value;
142 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0x80000000 | 0x20 | index;
143 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
144 data1 = AMAZON_SW_REG32(AMAZON_SW_DATA1) & 0xffffff;
145 data2 = AMAZON_SW_REG32(AMAZON_SW_DATA2);
146 value = (u64) data1 << 32 | (u64) data2;
147 return value;
148 }
149
150 int write_mac_table_entry(int index, u64 value)
151 {
152 u32 data1, data2;
153 data1 = (u32) (value >> 32);
154 data2 = (u32) value & 0xffffffff;
155 AMAZON_SW_REG32(AMAZON_SW_DATA1) = data1;
156 AMAZON_SW_REG32(AMAZON_SW_DATA2) = data2;
157 AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) = 0xc0000020 | index;
158 while (AMAZON_SW_REG32(AMAZON_SW_CPU_ACTL) & (0x80000000)) {};
159 return OK;
160 }
161
162 u32 get_mdio_reg(int phy_addr, int reg_num)
163 {
164 u32 value;
165 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (3 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16);
166 while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
167 value = AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & 0xffff;
168 return value;
169 }
170
171 int set_mdio_reg(int phy_addr, int reg_num, u32 value)
172 {
173 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = (2 << 30) | ((phy_addr & 0x1f) << 21) | ((reg_num & 0x1f) << 16) | (value & 0xffff);
174 while (AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) & (1 << 31)) {};
175 return OK;
176 }
177
178 int auto_negotiate(int phy_addr)
179 {
180 u32 value = 0;
181 value = get_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG);
182 set_mdio_reg(phy_addr, MDIO_BASE_CONTROL_REG, (value | RESTART_AUTO_NEGOTIATION | AUTO_NEGOTIATION_ENABLE | PHY_RESET));
183 return OK;
184 }
185
186 /*
187 In this version of switch driver, we split the dma channels for the switch.
188 2 for port0 and 2 for port1. So that we can do internal bridging if necessary.
189 In switch mode, packets coming in from port0 or port1 is able to do Destination
190 address lookup. Packets coming from port0 with destination address of port1 should
191 not go to pmac again. The switch hardware should be able to do the switch in the hard
192 ware level. Packets coming from the pmac should not do the DA look up in that the
193 desination is already known for the kernel. It only needs to go to the correct NIC to
194 find its way out.
195 */
196 int amazon_sw_chip_init(void)
197 {
198 u32 tmp1;
199 int i = 0;
200
201 /* Aging tick select: 5mins */
202 tmp1 = 0xa0;
203 if (strcmp(mode, "bridge") == 0) {
204 // bridge mode, set militarised mode to 1, no learning!
205 tmp1 |= 0xC00;
206 } else {
207 // enable learning for P0 and P1,
208 tmp1 |= 3;
209 }
210
211 /* unknown broadcast/multicast/unicast to all ports */
212 AMAZON_SW_REG32(AMAZON_SW_UN_DEST) = 0x1ff;
213
214 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL) = tmp1;
215
216 /* OCS:1 set OCS bit, split the two NIC in rx direction EDL:1 (enable DA lookup) */
217 #if defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT) || defined(CONFIG_IFX_NFEXT_AMAZON_SWITCH_PHYPORT_MODULE)
218 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x700;
219 #else
220 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL) = 0x401;
221 #endif
222
223 /* EPC: 1 split the two NIC in tx direction CRC is generated */
224 AMAZON_SW_REG32(AMAZON_SW_P2_CTL) = 0x6;
225
226 // for bi-directional
227 AMAZON_SW_REG32(AMAZON_SW_P0_WM) = 0x14141412;
228 AMAZON_SW_REG32(AMAZON_SW_P1_WM) = 0x14141412;
229 AMAZON_SW_REG32(AMAZON_SW_P2_WM) = 0x28282826;
230 AMAZON_SW_REG32(AMAZON_SW_GBL_WM) = 0x0;
231
232 AMAZON_SW_REG32(AMAZON_CGU_PLL0SR) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR)) | 0x58000000;
233 // clock for PHY
234 AMAZON_SW_REG32(AMAZON_CGU_IFCCR) = (AMAZON_SW_REG32(AMAZON_CGU_IFCCR)) | 0x80000004;
235 // enable power for PHY
236 AMAZON_SW_REG32(AMAZON_PMU_PWDCR) = (AMAZON_SW_REG32(AMAZON_PMU_PWDCR)) | AMAZON_PMU_PWDCR_EPHY;
237 // set reverse MII, enable MDIO statemachine
238 AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG) = 0x800027bf;
239 while (1)
240 if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG)) & 0x80000000) == 0)
241 break;
242 AMAZON_SW_REG32(AMAZON_SW_EPHY) = 0xff;
243
244 // auto negotiation
245 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC) = 0x83e08000;
246 auto_negotiate(0x1f);
247
248 /* enable all ports */
249 AMAZON_SW_REG32(AMAZON_SW_PS_CTL) = 0x7;
250 for (i = 0; i < 32; i++)
251 write_mac_table_entry(i, 1 << 50);
252 return 0;
253 }
254
255 static unsigned char my_ethaddr[MAX_ADDR_LEN];
256 /* need to get the ether addr from u-boot */
257 static int __init ethaddr_setup(char *line)
258 {
259 char *ep;
260 int i;
261
262 memset(my_ethaddr, 0, MAX_ADDR_LEN);
263 for (i = 0; i < 6; i++) {
264 my_ethaddr[i] = line ? simple_strtoul(line, &ep, 16) : 0;
265 if (line)
266 line = (*ep) ? ep + 1 : ep;
267 }
268 printk(KERN_INFO "amazon_mii0: mac address %2x-%2x-%2x-%2x-%2x-%2x \n", my_ethaddr[0], my_ethaddr[1], my_ethaddr[2], my_ethaddr[3], my_ethaddr[4], my_ethaddr[5]);
269 return 0;
270 }
271
272 __setup("ethaddr=", ethaddr_setup);
273
274 static void open_rx_dma(struct net_device *dev)
275 {
276 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
277 struct dma_device_info *dma_dev = priv->dma_device;
278 int i;
279
280 for (i = 0; i < dma_dev->num_rx_chan; i++)
281 dma_dev->rx_chan[i].control = 1;
282 dma_device_update_rx(dma_dev);
283 }
284
285 #ifdef CONFIG_NET_HW_FLOWCONTROL
286 static void close_rx_dma(struct net_device *dev)
287 {
288 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
289 struct dma_device_info *dma_dev = priv->dma_device;
290 int i;
291
292 for (i = 0; i < dma_dev->num_rx_chan; i++)
293 dma_dev->rx_chan[i].control = 0;
294 dma_device_update_rx(dma_dev);
295 }
296
297 void amazon_xon(struct net_device *dev)
298 {
299 unsigned long flag;
300 local_irq_save(flag);
301 open_rx_dma(dev);
302 local_irq_restore(flag);
303 }
304 #endif
305
306 int switch_open(struct net_device *dev)
307 {
308 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
309 if (!strcmp(dev->name, "eth1")) {
310 priv->mdio_phy_addr = PHY0_ADDR;
311 }
312 open_rx_dma(dev);
313
314 #ifdef CONFIG_NET_HW_FLOWCONTROL
315 if ((priv->fc_bit = netdev_register_fc(dev, amazon_xon)) == 0) {
316 printk(KERN_WARNING "amazon_mii0: Hardware Flow Control register fails\n");
317 }
318 #endif
319
320 netif_start_queue(dev);
321 return OK;
322 }
323
324 int switch_release(struct net_device *dev)
325 {
326 int i;
327 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
328 struct dma_device_info *dma_dev = priv->dma_device;
329
330 for (i = 0; i < dma_dev->num_tx_chan; i++)
331 dma_dev->tx_chan[i].control = 0;
332 for (i = 0; i < dma_dev->num_rx_chan; i++)
333 dma_dev->rx_chan[i].control = 0;
334
335 dma_device_update(dma_dev);
336
337 #ifdef CONFIG_NET_HW_FLOWCONTROL
338 if (priv->fc_bit) {
339 netdev_unregister_fc(priv->fc_bit);
340 }
341 #endif
342 netif_stop_queue(dev);
343
344 return OK;
345 }
346
347
348 void switch_rx(struct net_device *dev, int len, struct sk_buff *skb)
349 {
350 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
351 #ifdef CONFIG_NET_HW_FLOWCONTROL
352 int mit_sel = 0;
353 #endif
354 skb->dev = dev;
355 skb->protocol = eth_type_trans(skb, dev);
356
357 #ifdef CONFIG_NET_HW_FLOWCONTROL
358 mit_sel = netif_rx(skb);
359 switch (mit_sel) {
360 case NET_RX_SUCCESS:
361 case NET_RX_CN_LOW:
362 case NET_RX_CN_MOD:
363 break;
364 case NET_RX_CN_HIGH:
365 break;
366 case NET_RX_DROP:
367 if ((priv->fc_bit)
368 && (!test_and_set_bit(priv->fc_bit, &netdev_fc_xoff))) {
369 close_rx_dma(dev);
370 }
371 break;
372 }
373 #else
374 netif_rx(skb);
375 #endif
376 priv->stats.rx_packets++;
377 priv->stats.rx_bytes += len;
378 return;
379 }
380
381 int asmlinkage switch_hw_tx(char *buf, int len, struct net_device *dev)
382 {
383 struct switch_priv *priv = netdev_priv(dev);
384 struct dma_device_info *dma_dev = priv->dma_device;
385
386 dma_dev->current_tx_chan = 0;
387 return dma_device_write(dma_dev, buf, len, priv->skb);
388 }
389
390 int asmlinkage switch_tx(struct sk_buff *skb, struct net_device *dev)
391 {
392 int len;
393 char *data;
394 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
395
396 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
397 data = skb->data;
398 priv->skb = skb;
399 dev->trans_start = jiffies;
400
401 if (switch_hw_tx(data, len, dev) != len) {
402 dev_kfree_skb_any(skb);
403 return OK;
404 }
405
406 priv->stats.tx_packets++;
407 priv->stats.tx_bytes += len;
408 return OK;
409 }
410
411 void switch_tx_timeout(struct net_device *dev)
412 {
413 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
414 priv->stats.tx_errors++;
415 netif_wake_queue(dev);
416 return;
417 }
418
419 void negotiate(struct net_device *dev)
420 {
421 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
422 unsigned short data = get_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG);
423
424 data &= ~(MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD);
425
426 switch (priv->current_speed_selection) {
427 case 10:
428 if (priv->current_duplex == full)
429 data |= MDIO_ADVERT_10_FD;
430 else if (priv->current_duplex == half)
431 data |= MDIO_ADVERT_10_HD;
432 else
433 data |= MDIO_ADVERT_10_HD | MDIO_ADVERT_10_FD;
434 break;
435
436 case 100:
437 if (priv->current_duplex == full)
438 data |= MDIO_ADVERT_100_FD;
439 else if (priv->current_duplex == half)
440 data |= MDIO_ADVERT_100_HD;
441 else
442 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD;
443 break;
444
445 case 0: /* Auto */
446 if (priv->current_duplex == full)
447 data |= MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD;
448 else if (priv->current_duplex == half)
449 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_10_HD;
450 else
451 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
452 break;
453
454 default: /* assume autoneg speed and duplex */
455 data |= MDIO_ADVERT_100_HD | MDIO_ADVERT_100_FD | MDIO_ADVERT_10_FD | MDIO_ADVERT_10_HD;
456 }
457
458 set_mdio_reg(priv->mdio_phy_addr, MDIO_ADVERTISMENT_REG, data);
459
460 /* Renegotiate with link partner */
461
462 data = get_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG);
463 data |= MDIO_BC_NEGOTIATE;
464
465 set_mdio_reg(priv->mdio_phy_addr, MDIO_BASE_CONTROL_REG, data);
466
467 }
468
469
470 void set_duplex(struct net_device *dev, enum duplex new_duplex)
471 {
472 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
473 if (new_duplex != priv->current_duplex) {
474 priv->current_duplex = new_duplex;
475 negotiate(dev);
476 }
477 }
478
479 void set_speed(struct net_device *dev, unsigned long speed)
480 {
481 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
482 priv->current_speed_selection = speed;
483 negotiate(dev);
484 }
485
486 static int switch_ethtool_ioctl(struct net_device *dev, struct ifreq *ifr)
487 {
488 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
489 struct ethtool_cmd ecmd;
490
491 if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd)))
492 return -EFAULT;
493
494 switch (ecmd.cmd) {
495 case ETHTOOL_GSET:
496 memset((void *) &ecmd, 0, sizeof(ecmd));
497 ecmd.supported = SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
498 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full;
499 ecmd.port = PORT_TP;
500 ecmd.transceiver = XCVR_EXTERNAL;
501 ecmd.phy_address = priv->mdio_phy_addr;
502
503 ecmd.speed = priv->current_speed;
504
505 ecmd.duplex = priv->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
506
507 ecmd.advertising = ADVERTISED_TP;
508 if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
509 ecmd.advertising |= ADVERTISED_Autoneg;
510 else {
511 ecmd.advertising |= ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
512 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
513 if (priv->current_speed_selection == 10)
514 ecmd.advertising &= ~(ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full);
515 else if (priv->current_speed_selection == 100)
516 ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full);
517 if (priv->current_duplex == half)
518 ecmd.advertising &= ~(ADVERTISED_10baseT_Full | ADVERTISED_100baseT_Full);
519 else if (priv->current_duplex == full)
520 ecmd.advertising &= ~(ADVERTISED_10baseT_Half | ADVERTISED_100baseT_Half);
521 }
522 ecmd.autoneg = AUTONEG_ENABLE;
523 if (copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd)))
524 return -EFAULT;
525 break;
526
527 case ETHTOOL_SSET:
528 if (!capable(CAP_NET_ADMIN)) {
529 return -EPERM;
530 }
531 if (ecmd.autoneg == AUTONEG_ENABLE) {
532 set_duplex(dev, autoneg);
533 set_speed(dev, 0);
534 } else {
535 set_duplex(dev, ecmd.duplex == DUPLEX_HALF ? half : full);
536 set_speed(dev, ecmd.speed == SPEED_10 ? 10 : 100);
537 }
538 break;
539
540 case ETHTOOL_GDRVINFO:
541 {
542 struct ethtool_drvinfo info;
543 memset((void *) &info, 0, sizeof(info));
544 strncpy(info.driver, "AMAZONE", sizeof(info.driver) - 1);
545 strncpy(info.fw_version, "N/A", sizeof(info.fw_version) - 1);
546 strncpy(info.bus_info, "N/A", sizeof(info.bus_info) - 1);
547 info.regdump_len = 0;
548 info.eedump_len = 0;
549 info.testinfo_len = 0;
550 if (copy_to_user(ifr->ifr_data, &info, sizeof(info)))
551 return -EFAULT;
552 }
553 break;
554 case ETHTOOL_NWAY_RST:
555 if (priv->current_duplex == autoneg && priv->current_speed_selection == 0)
556 negotiate(dev);
557 break;
558 default:
559 return -EOPNOTSUPP;
560 break;
561 }
562 return 0;
563 }
564
565
566
567 int mac_table_tools_ioctl(struct net_device *dev, struct mac_table_req *req)
568 {
569 int cmd;
570 int i;
571 cmd = req->cmd;
572 switch (cmd) {
573 case RESET_MAC_TABLE:
574 for (i = 0; i < 32; i++) {
575 write_mac_table_entry(i, 0);
576 }
577 break;
578 case READ_MAC_ENTRY:
579 req->entry_value = read_mac_table_entry(req->index);
580 break;
581 case WRITE_MAC_ENTRY:
582 write_mac_table_entry(req->index, req->entry_value);
583 break;
584 case ADD_MAC_ENTRY:
585 add_mac_table_entry(req->entry_value);
586 break;
587 default:
588 return -EINVAL;
589 }
590
591 return 0;
592 }
593
594
595 /*
596 the ioctl for the switch driver is developed in the conventional way
597 the control type falls into some basic categories, among them, the
598 SIOCETHTOOL is the traditional eth interface. VLAN_TOOLS and
599 MAC_TABLE_TOOLS are designed specifically for amazon chip. User
600 should be aware of the data structures used in these interfaces.
601 */
602 int switch_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
603 {
604 struct data_req *switch_data_req = (struct data_req *) ifr->ifr_data;
605 struct mac_table_req *switch_mac_table_req;
606 switch (cmd) {
607 case SIOCETHTOOL:
608 switch_ethtool_ioctl(dev, ifr);
609 break;
610 case SIOCGMIIPHY: /* Get PHY address */
611 break;
612 case SIOCGMIIREG: /* Read MII register */
613 break;
614 case SIOCSMIIREG: /* Write MII register */
615 break;
616 case SET_ETH_SPEED_10: /* 10 Mbps */
617 break;
618 case SET_ETH_SPEED_100: /* 100 Mbps */
619 break;
620 case SET_ETH_SPEED_AUTO: /* Auto negotiate speed */
621 break;
622 case SET_ETH_DUPLEX_HALF: /* Half duplex. */
623 break;
624 case SET_ETH_DUPLEX_FULL: /* Full duplex. */
625 break;
626 case SET_ETH_DUPLEX_AUTO: /* Autonegotiate duplex */
627 break;
628 case SET_ETH_REG:
629 AMAZON_SW_REG32(switch_data_req->index) = switch_data_req->value;
630 break;
631 case MAC_TABLE_TOOLS:
632 switch_mac_table_req = (struct mac_table_req *) ifr->ifr_data;
633 mac_table_tools_ioctl(dev, switch_mac_table_req);
634 break;
635 default:
636 return -EINVAL;
637 }
638
639 return 0;
640 }
641
642 struct net_device_stats *switch_stats(struct net_device *dev)
643 {
644 struct switch_priv *priv = (struct switch_priv *) netdev_priv(dev);
645 return &priv->stats;
646 }
647
648 int switch_change_mtu(struct net_device *dev, int new_mtu)
649 {
650 if (new_mtu >= 1516)
651 new_mtu = 1516;
652 dev->mtu = new_mtu;
653 return 0;
654 }
655
656 int switch_hw_receive(struct net_device *dev, struct dma_device_info *dma_dev)
657 {
658 u8 *buf = NULL;
659 int len = 0;
660 struct sk_buff *skb = NULL;
661
662 len = dma_device_read(dma_dev, &buf, (void **) &skb);
663
664 if (len >= 0x600) {
665 printk(KERN_WARNING "amazon_mii0: packet too large %d\n", len);
666 goto switch_hw_receive_err_exit;
667 }
668
669 /* remove CRC */
670 len -= 4;
671 if (skb == NULL) {
672 printk(KERN_WARNING "amazon_mii0: cannot restore pointer\n");
673 goto switch_hw_receive_err_exit;
674 }
675 if (len > (skb->end - skb->tail)) {
676 printk(KERN_WARNING "amazon_mii0: BUG, len:%d end:%p tail:%p\n", (len + 4), skb->end, skb->tail);
677 goto switch_hw_receive_err_exit;
678 }
679 skb_put(skb, len);
680 skb->dev = dev;
681 switch_rx(dev, len, skb);
682 return OK;
683
684 switch_hw_receive_err_exit:
685 if (skb)
686 dev_kfree_skb_any(skb);
687 return -EIO;
688 }
689
690 int dma_intr_handler(struct dma_device_info *dma_dev, int status)
691 {
692 struct net_device *dev;
693
694 dev = dma_dev->priv;
695 switch (status) {
696 case RCV_INT:
697 switch_hw_receive(dev, dma_dev);
698 break;
699 case TX_BUF_FULL_INT:
700 netif_stop_queue(dev);
701 break;
702 case TRANSMIT_CPT_INT:
703 netif_wake_queue(dev);
704 break;
705 }
706 return OK;
707 }
708
709 /* reserve 2 bytes in front of data pointer*/
710 u8 *dma_buffer_alloc(int len, int *byte_offset, void **opt)
711 {
712 u8 *buffer = NULL;
713 struct sk_buff *skb = NULL;
714 skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE);
715 if (skb == NULL) {
716 return NULL;
717 }
718 buffer = (u8 *) (skb->data);
719 skb_reserve(skb, 2);
720 *(int *) opt = (int) skb;
721 *byte_offset = 2;
722 return buffer;
723 }
724
725 int dma_buffer_free(u8 * dataptr, void *opt)
726 {
727 struct sk_buff *skb = NULL;
728 if (opt == NULL) {
729 kfree(dataptr);
730 } else {
731 skb = (struct sk_buff *) opt;
732 dev_kfree_skb_any(skb);
733 }
734 return OK;
735 }
736
737 int init_dma_device(_dma_device_info * dma_dev, struct net_device *dev)
738 {
739 int i;
740 int num_tx_chan, num_rx_chan;
741 if (strcmp(dma_dev->device_name, "switch1") == 0) {
742 num_tx_chan = 1;
743 num_rx_chan = 2;
744 } else {
745 num_tx_chan = 1;
746 num_rx_chan = 2;
747 }
748 dma_dev->priv = dev;
749
750 dma_dev->weight = 1;
751 dma_dev->num_tx_chan = num_tx_chan;
752 dma_dev->num_rx_chan = num_rx_chan;
753 dma_dev->ack = 1;
754 dma_dev->tx_burst_len = 4;
755 dma_dev->rx_burst_len = 4;
756 for (i = 0; i < dma_dev->num_tx_chan; i++) {
757 dma_dev->tx_chan[i].weight = QOS_DEFAULT_WGT;
758 dma_dev->tx_chan[i].desc_num = 10;
759 dma_dev->tx_chan[i].packet_size = 0;
760 dma_dev->tx_chan[i].control = 0;
761 }
762 for (i = 0; i < num_rx_chan; i++) {
763 dma_dev->rx_chan[i].weight = QOS_DEFAULT_WGT;
764 dma_dev->rx_chan[i].desc_num = 10;
765 dma_dev->rx_chan[i].packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE;
766 dma_dev->rx_chan[i].control = 0;
767 }
768 dma_dev->intr_handler = dma_intr_handler;
769 dma_dev->buffer_alloc = dma_buffer_alloc;
770 dma_dev->buffer_free = dma_buffer_free;
771 return 0;
772 }
773
774 int switch_set_mac_address(struct net_device *dev, void *p)
775 {
776 struct sockaddr *addr = p;
777 memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
778 return OK;
779 }
780
781 static const struct net_device_ops amazon_mii_ops = {
782 .ndo_init = switch_init,
783 .ndo_open = switch_open,
784 .ndo_stop = switch_release,
785 .ndo_start_xmit = switch_tx,
786 .ndo_do_ioctl = switch_ioctl,
787 .ndo_get_stats = switch_stats,
788 .ndo_change_mtu = switch_change_mtu,
789 .ndo_set_mac_address = switch_set_mac_address,
790 .ndo_tx_timeout = switch_tx_timeout,
791 };
792
793 int switch_init(struct net_device *dev)
794 {
795 u64 retval = 0;
796 int i;
797 int result;
798 struct switch_priv *priv;
799 ether_setup(dev); /* assign some of the fields */
800 printk(KERN_INFO "amazon_mii0: %s up using ", dev->name);
801 dev->watchdog_timeo = timeout;
802
803 priv = netdev_priv(dev);
804 priv->dma_device = (struct dma_device_info *) kmalloc(sizeof(struct dma_device_info), GFP_KERNEL);
805 if (priv->num == 0) {
806 sprintf(priv->dma_device->device_name, "switch1");
807 } else if (priv->num == 1) {
808 sprintf(priv->dma_device->device_name, "switch2");
809 }
810 printk("\"%s\"\n", priv->dma_device->device_name);
811 init_dma_device(priv->dma_device, dev);
812 result = dma_device_register(priv->dma_device);
813
814 /* read the mac address from the mac table and put them into the mac table. */
815 for (i = 0; i < 6; i++) {
816 retval += my_ethaddr[i];
817 }
818 /* ethaddr not set in u-boot ? */
819 if (retval == 0) {
820 dev->dev_addr[0] = 0x00;
821 dev->dev_addr[1] = 0x20;
822 dev->dev_addr[2] = 0xda;
823 dev->dev_addr[3] = 0x86;
824 dev->dev_addr[4] = 0x23;
825 dev->dev_addr[5] = 0x74 + (unsigned char) priv->num;
826 } else {
827 for (i = 0; i < 6; i++) {
828 dev->dev_addr[i] = my_ethaddr[i];
829 }
830 dev->dev_addr[5] += +(unsigned char) priv->num;
831 }
832 return OK;
833 }
834
835 static int amazon_mii_probe(struct platform_device *dev)
836 {
837 int i = 0, result, device_present = 0;
838 struct switch_priv *priv;
839
840 for (i = 0; i < AMAZON_SW_INT_NO; i++) {
841 switch_devs[i] = alloc_etherdev(sizeof(struct switch_priv));
842 switch_devs[i]->netdev_ops = &amazon_mii_ops;
843 strcpy(switch_devs[i]->name, "eth%d");
844 priv = (struct switch_priv *) netdev_priv(switch_devs[i]);
845 priv->num = i;
846 if ((result = register_netdev(switch_devs[i])))
847 printk(KERN_WARNING "amazon_mii0: error %i registering device \"%s\"\n", result, switch_devs[i]->name);
848 else
849 device_present++;
850 }
851 amazon_sw_chip_init();
852 return device_present ? 0 : -ENODEV;
853 }
854
855 static int amazon_mii_remove(struct platform_device *dev)
856 {
857 int i;
858 struct switch_priv *priv;
859 for (i = 0; i < AMAZON_SW_INT_NO; i++) {
860 priv = netdev_priv(switch_devs[i]);
861 if (priv->dma_device) {
862 dma_device_unregister(priv->dma_device);
863 kfree(priv->dma_device);
864 }
865 kfree(netdev_priv(switch_devs[i]));
866 unregister_netdev(switch_devs[i]);
867 }
868 return 0;
869 }
870
871 static struct platform_driver amazon_mii_driver = {
872 .probe = amazon_mii_probe,
873 .remove = amazon_mii_remove,
874 .driver = {
875 .name = "amazon_mii0",
876 .owner = THIS_MODULE,
877 },
878 };
879
880 static int __init amazon_mii_init(void)
881 {
882 int ret = platform_driver_register(&amazon_mii_driver);
883 if (ret)
884 printk(KERN_WARNING "amazon_mii0: Error registering platfom driver!\n");
885 return ret;
886 }
887
888 static void __exit amazon_mii_cleanup(void)
889 {
890 platform_driver_unregister(&amazon_mii_driver);
891 }
892
893 module_init(amazon_mii_init);
894 module_exit(amazon_mii_cleanup);
895
896 MODULE_LICENSE("GPL");
897 MODULE_AUTHOR("Wu Qi Ming");
898 MODULE_DESCRIPTION("ethernet driver for AMAZON boards");
899
This page took 0.08612 seconds and 5 git commands to generate.