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.
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.
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.
16 //-----------------------------------------------------------------------
19 * Driver for Infineon Amazon 3 port switch
21 //-----------------------------------------------------------------------
22 /* Author: Wu Qi Ming[Qi-Ming.Wu@infineon.com]
23 * Created: 7-April-2004
25 //-----------------------------------------------------------------------
27 * Changed on: Jun 28, 2004
28 * Changed by: peng.liu@infineon.com
29 * Reason: add hardware flow control (HFC) (CONFIG_NET_HW_FLOWCONTROL)
31 * Changed on: Apr 6, 2005
32 * Changed by: mars.lin@infineon.com
33 * Reason : supoort port identification
37 // copyright 2004-2005 infineon.com
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>
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
59 #if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
63 #if defined(MODVERSIONS) && !defined(__GENKSYMS__)
64 #include <linux/modversions.h>
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>
78 #include <linux/netdevice.h>
79 #include <linux/etherdevice.h>
81 #include <linux/tcp.h>
82 #include <linux/skbuff.h>
83 #include <linux/in6.h>
84 #include <linux/proc_fs.h>
86 #include <linux/ethtool.h>
87 #include <asm/checksum.h>
88 #include <linux/init.h>
89 #include <linux/platform_device.h>
91 #include <asm/amazon/amazon.h>
92 #include <asm/amazon/amazon_dma.h>
93 #include <asm/amazon/amazon_sw.h>
95 // how many mii ports are there ?
96 #define AMAZON_SW_INT_NO 2
98 #define ETHERNET_PACKET_DMA_BUFFER_SIZE 1536
100 /***************************************** Module Parameters *************************************/
101 char mode
[] = "bridge";
102 module_param_array(mode
, charp
, NULL
, 0);
104 static int timeout
= 1 * HZ
;
105 module_param(timeout
, int, 0);
107 int switch_init(struct net_device
*dev
);
108 void switch_tx_timeout(struct net_device
*dev
);
110 static struct net_device
*switch_devs
[2];
112 int add_mac_table_entry(u64 entry_value
)
117 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) = ~7;
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)
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)) {};
132 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) |= 7;
138 u64
read_mac_table_entry(int index
)
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
;
150 int write_mac_table_entry(int index
, u64 value
)
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)) {};
162 u32
get_mdio_reg(int phy_addr
, int reg_num
)
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;
171 int set_mdio_reg(int phy_addr
, int reg_num
, u32 value
)
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)) {};
178 int auto_negotiate(int phy_addr
)
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
));
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
196 int amazon_sw_chip_init(void)
201 /* Aging tick select: 5mins */
203 if (strcmp(mode
, "bridge") == 0) {
204 // bridge mode, set militarised mode to 1, no learning!
207 // enable learning for P0 and P1,
211 /* unknown broadcast/multicast/unicast to all ports */
212 AMAZON_SW_REG32(AMAZON_SW_UN_DEST
) = 0x1ff;
214 AMAZON_SW_REG32(AMAZON_SW_ARL_CTL
) = tmp1
;
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;
220 AMAZON_SW_REG32(AMAZON_SW_P2_PCTL
) = 0x401;
223 /* EPC: 1 split the two NIC in tx direction CRC is generated */
224 AMAZON_SW_REG32(AMAZON_SW_P2_CTL
) = 0x6;
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;
232 AMAZON_SW_REG32(AMAZON_CGU_PLL0SR
) = (AMAZON_SW_REG32(AMAZON_CGU_PLL0SR
)) | 0x58000000;
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;
240 if (((AMAZON_SW_REG32(AMAZON_SW_MDIO_CFG
)) & 0x80000000) == 0)
242 AMAZON_SW_REG32(AMAZON_SW_EPHY
) = 0xff;
245 AMAZON_SW_REG32(AMAZON_SW_MDIO_ACC
) = 0x83e08000;
246 auto_negotiate(0x1f);
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);
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
)
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;
266 line
= (*ep
) ? ep
+ 1 : ep
;
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]);
272 __setup("ethaddr=", ethaddr_setup
);
274 static void open_rx_dma(struct net_device
*dev
)
276 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
277 struct dma_device_info
*dma_dev
= priv
->dma_device
;
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
);
285 #ifdef CONFIG_NET_HW_FLOWCONTROL
286 static void close_rx_dma(struct net_device
*dev
)
288 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
289 struct dma_device_info
*dma_dev
= priv
->dma_device
;
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
);
297 void amazon_xon(struct net_device
*dev
)
300 local_irq_save(flag
);
302 local_irq_restore(flag
);
306 int switch_open(struct net_device
*dev
)
308 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
309 if (!strcmp(dev
->name
, "eth1")) {
310 priv
->mdio_phy_addr
= PHY0_ADDR
;
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");
320 netif_start_queue(dev
);
324 int switch_release(struct net_device
*dev
)
327 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
328 struct dma_device_info
*dma_dev
= priv
->dma_device
;
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;
335 dma_device_update(dma_dev
);
337 #ifdef CONFIG_NET_HW_FLOWCONTROL
339 netdev_unregister_fc(priv
->fc_bit
);
342 netif_stop_queue(dev
);
348 void switch_rx(struct net_device
*dev
, int len
, struct sk_buff
*skb
)
350 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
351 #ifdef CONFIG_NET_HW_FLOWCONTROL
355 skb
->protocol
= eth_type_trans(skb
, dev
);
357 #ifdef CONFIG_NET_HW_FLOWCONTROL
358 mit_sel
= netif_rx(skb
);
368 && (!test_and_set_bit(priv
->fc_bit
, &netdev_fc_xoff
))) {
376 priv
->stats
.rx_packets
++;
377 priv
->stats
.rx_bytes
+= len
;
381 int asmlinkage
switch_hw_tx(char *buf
, int len
, struct net_device
*dev
)
383 struct switch_priv
*priv
= netdev_priv(dev
);
384 struct dma_device_info
*dma_dev
= priv
->dma_device
;
386 dma_dev
->current_tx_chan
= 0;
387 return dma_device_write(dma_dev
, buf
, len
, priv
->skb
);
390 int asmlinkage
switch_tx(struct sk_buff
*skb
, struct net_device
*dev
)
394 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
396 len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
399 dev
->trans_start
= jiffies
;
401 if (switch_hw_tx(data
, len
, dev
) != len
) {
402 dev_kfree_skb_any(skb
);
406 priv
->stats
.tx_packets
++;
407 priv
->stats
.tx_bytes
+= len
;
411 void switch_tx_timeout(struct net_device
*dev
)
413 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
414 priv
->stats
.tx_errors
++;
415 netif_wake_queue(dev
);
419 void negotiate(struct net_device
*dev
)
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
);
424 data
&= ~(MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
| MDIO_ADVERT_10_HD
);
426 switch (priv
->current_speed_selection
) {
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
;
433 data
|= MDIO_ADVERT_10_HD
| MDIO_ADVERT_10_FD
;
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
;
442 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
;
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
;
451 data
|= MDIO_ADVERT_100_HD
| MDIO_ADVERT_100_FD
| MDIO_ADVERT_10_FD
| MDIO_ADVERT_10_HD
;
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
;
458 set_mdio_reg(priv
->mdio_phy_addr
, MDIO_ADVERTISMENT_REG
, data
);
460 /* Renegotiate with link partner */
462 data
= get_mdio_reg(priv
->mdio_phy_addr
, MDIO_BASE_CONTROL_REG
);
463 data
|= MDIO_BC_NEGOTIATE
;
465 set_mdio_reg(priv
->mdio_phy_addr
, MDIO_BASE_CONTROL_REG
, data
);
470 void set_duplex(struct net_device
*dev
, enum duplex new_duplex
)
472 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
473 if (new_duplex
!= priv
->current_duplex
) {
474 priv
->current_duplex
= new_duplex
;
479 void set_speed(struct net_device
*dev
, unsigned long speed
)
481 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
482 priv
->current_speed_selection
= speed
;
486 static int switch_ethtool_ioctl(struct net_device
*dev
, struct ifreq
*ifr
)
488 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
489 struct ethtool_cmd ecmd
;
491 if (copy_from_user(&ecmd
, ifr
->ifr_data
, sizeof(ecmd
)))
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
;
500 ecmd
.transceiver
= XCVR_EXTERNAL
;
501 ecmd
.phy_address
= priv
->mdio_phy_addr
;
503 ecmd
.speed
= priv
->current_speed
;
505 ecmd
.duplex
= priv
->full_duplex
? DUPLEX_FULL
: DUPLEX_HALF
;
507 ecmd
.advertising
= ADVERTISED_TP
;
508 if (priv
->current_duplex
== autoneg
&& priv
->current_speed_selection
== 0)
509 ecmd
.advertising
|= ADVERTISED_Autoneg
;
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
);
522 ecmd
.autoneg
= AUTONEG_ENABLE
;
523 if (copy_to_user(ifr
->ifr_data
, &ecmd
, sizeof(ecmd
)))
528 if (!capable(CAP_NET_ADMIN
)) {
531 if (ecmd
.autoneg
== AUTONEG_ENABLE
) {
532 set_duplex(dev
, autoneg
);
535 set_duplex(dev
, ecmd
.duplex
== DUPLEX_HALF
? half
: full
);
536 set_speed(dev
, ecmd
.speed
== SPEED_10
? 10 : 100);
540 case ETHTOOL_GDRVINFO
:
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;
549 info
.testinfo_len
= 0;
550 if (copy_to_user(ifr
->ifr_data
, &info
, sizeof(info
)))
554 case ETHTOOL_NWAY_RST
:
555 if (priv
->current_duplex
== autoneg
&& priv
->current_speed_selection
== 0)
567 int mac_table_tools_ioctl(struct net_device
*dev
, struct mac_table_req
*req
)
573 case RESET_MAC_TABLE
:
574 for (i
= 0; i
< 32; i
++) {
575 write_mac_table_entry(i
, 0);
579 req
->entry_value
= read_mac_table_entry(req
->index
);
581 case WRITE_MAC_ENTRY
:
582 write_mac_table_entry(req
->index
, req
->entry_value
);
585 add_mac_table_entry(req
->entry_value
);
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.
602 int switch_ioctl(struct net_device
*dev
, struct ifreq
*ifr
, int cmd
)
604 struct data_req
*switch_data_req
= (struct data_req
*) ifr
->ifr_data
;
605 struct mac_table_req
*switch_mac_table_req
;
608 switch_ethtool_ioctl(dev
, ifr
);
610 case SIOCGMIIPHY
: /* Get PHY address */
612 case SIOCGMIIREG
: /* Read MII register */
614 case SIOCSMIIREG
: /* Write MII register */
616 case SET_ETH_SPEED_10
: /* 10 Mbps */
618 case SET_ETH_SPEED_100
: /* 100 Mbps */
620 case SET_ETH_SPEED_AUTO
: /* Auto negotiate speed */
622 case SET_ETH_DUPLEX_HALF
: /* Half duplex. */
624 case SET_ETH_DUPLEX_FULL
: /* Full duplex. */
626 case SET_ETH_DUPLEX_AUTO
: /* Autonegotiate duplex */
629 AMAZON_SW_REG32(switch_data_req
->index
) = switch_data_req
->value
;
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
);
642 struct net_device_stats
*switch_stats(struct net_device
*dev
)
644 struct switch_priv
*priv
= (struct switch_priv
*) netdev_priv(dev
);
648 int switch_change_mtu(struct net_device
*dev
, int new_mtu
)
656 int switch_hw_receive(struct net_device
*dev
, struct dma_device_info
*dma_dev
)
660 struct sk_buff
*skb
= NULL
;
662 len
= dma_device_read(dma_dev
, &buf
, (void **) &skb
);
665 printk(KERN_WARNING
"amazon_mii0: packet too large %d\n", len
);
666 goto switch_hw_receive_err_exit
;
672 printk(KERN_WARNING
"amazon_mii0: cannot restore pointer\n");
673 goto switch_hw_receive_err_exit
;
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
;
681 switch_rx(dev
, len
, skb
);
684 switch_hw_receive_err_exit
:
686 dev_kfree_skb_any(skb
);
690 int dma_intr_handler(struct dma_device_info
*dma_dev
, int status
)
692 struct net_device
*dev
;
697 switch_hw_receive(dev
, dma_dev
);
699 case TX_BUF_FULL_INT
:
700 netif_stop_queue(dev
);
702 case TRANSMIT_CPT_INT
:
703 netif_wake_queue(dev
);
709 /* reserve 2 bytes in front of data pointer*/
710 u8
*dma_buffer_alloc(int len
, int *byte_offset
, void **opt
)
713 struct sk_buff
*skb
= NULL
;
714 skb
= dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE
);
718 buffer
= (u8
*) (skb
->data
);
720 *(int *) opt
= (int) skb
;
725 int dma_buffer_free(u8
* dataptr
, void *opt
)
727 struct sk_buff
*skb
= NULL
;
731 skb
= (struct sk_buff
*) opt
;
732 dev_kfree_skb_any(skb
);
737 int init_dma_device(_dma_device_info
* dma_dev
, struct net_device
*dev
)
740 int num_tx_chan
, num_rx_chan
;
741 if (strcmp(dma_dev
->device_name
, "switch1") == 0) {
751 dma_dev
->num_tx_chan
= num_tx_chan
;
752 dma_dev
->num_rx_chan
= num_rx_chan
;
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;
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;
768 dma_dev
->intr_handler
= dma_intr_handler
;
769 dma_dev
->buffer_alloc
= dma_buffer_alloc
;
770 dma_dev
->buffer_free
= dma_buffer_free
;
774 int switch_set_mac_address(struct net_device
*dev
, void *p
)
776 struct sockaddr
*addr
= p
;
777 memcpy(dev
->dev_addr
, addr
->sa_data
, dev
->addr_len
);
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
,
793 int switch_init(struct net_device
*dev
)
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
;
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");
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
);
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
];
818 /* ethaddr not set in u-boot ? */
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
;
827 for (i
= 0; i
< 6; i
++) {
828 dev
->dev_addr
[i
] = my_ethaddr
[i
];
830 dev
->dev_addr
[5] += +(unsigned char) priv
->num
;
835 static int amazon_mii_probe(struct platform_device
*dev
)
837 int i
= 0, result
, device_present
= 0;
838 struct switch_priv
*priv
;
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
]);
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
);
851 amazon_sw_chip_init();
852 return device_present
? 0 : -ENODEV
;
855 static int amazon_mii_remove(struct platform_device
*dev
)
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
);
865 kfree(netdev_priv(switch_devs
[i
]));
866 unregister_netdev(switch_devs
[i
]);
871 static struct platform_driver amazon_mii_driver
= {
872 .probe
= amazon_mii_probe
,
873 .remove
= amazon_mii_remove
,
875 .name
= "amazon_mii0",
876 .owner
= THIS_MODULE
,
880 static int __init
amazon_mii_init(void)
882 int ret
= platform_driver_register(&amazon_mii_driver
);
884 printk(KERN_WARNING
"amazon_mii0: Error registering platfom driver!\n");
888 static void __exit
amazon_mii_cleanup(void)
890 platform_driver_unregister(&amazon_mii_driver
);
893 module_init(amazon_mii_init
);
894 module_exit(amazon_mii_cleanup
);
896 MODULE_LICENSE("GPL");
897 MODULE_AUTHOR("Wu Qi Ming");
898 MODULE_DESCRIPTION("ethernet driver for AMAZON boards");