2 * ADM5120 built in ethernet switch driver
4 * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005
6 * Inspiration for this driver came from the original ADMtek 2.4
7 * driver, Copyright ADMtek Inc.
9 #include <linux/autoconf.h>
10 #include <linux/module.h>
11 #include <linux/kernel.h>
12 #include <linux/netdevice.h>
13 #include <linux/etherdevice.h>
14 #include <linux/skbuff.h>
15 #include <linux/errno.h>
16 #include <linux/interrupt.h>
17 #include <linux/ioport.h>
18 #include <asm/mipsregs.h>
21 #include "adm5120sw.h"
23 #include <asm/mach-adm5120/adm5120_info.h>
25 MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)");
26 MODULE_DESCRIPTION("ADM5120 ethernet switch driver");
27 MODULE_LICENSE("GPL");
30 * The ADM5120 uses an internal matrix to determine which ports
31 * belong to which VLAN.
32 * The default generates a VLAN (and device) for each port
33 * (including MII port) and the CPU port is part of all of them.
35 * Another example, one big switch and everything mapped to eth0:
36 * 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00
38 static unsigned char vlan_matrix
[SW_DEVS
] = {
39 0x41, 0x42, 0x44, 0x48, 0x50, 0x60
42 static int adm5120_nrdevs
;
44 static struct net_device
*adm5120_devs
[SW_DEVS
];
45 static struct adm5120_dma
46 adm5120_dma_txh_v
[ADM5120_DMA_TXH
] __attribute__((aligned(16))),
47 adm5120_dma_txl_v
[ADM5120_DMA_TXL
] __attribute__((aligned(16))),
48 adm5120_dma_rxh_v
[ADM5120_DMA_RXH
] __attribute__((aligned(16))),
49 adm5120_dma_rxl_v
[ADM5120_DMA_RXL
] __attribute__((aligned(16))),
55 *adm5120_skb_rxh
[ADM5120_DMA_RXH
],
56 *adm5120_skb_rxl
[ADM5120_DMA_RXL
],
57 *adm5120_skb_txh
[ADM5120_DMA_TXH
],
58 *adm5120_skb_txl
[ADM5120_DMA_TXL
];
59 static int adm5120_rxhi
= 0;
60 static int adm5120_rxli
= 0;
61 /* We don't use high priority tx for now */
62 /*static int adm5120_txhi = 0;*/
63 static int adm5120_txli
= 0;
64 static int adm5120_txhit
= 0;
65 static int adm5120_txlit
= 0;
66 static int adm5120_if_open
= 0;
68 static inline void adm5120_set_reg(unsigned int reg
, unsigned long val
)
70 *(volatile unsigned long*)(SW_BASE
+reg
) = val
;
73 static inline unsigned long adm5120_get_reg(unsigned int reg
)
75 return *(volatile unsigned long*)(SW_BASE
+reg
);
78 static inline void adm5120_rxfixup(struct adm5120_dma
*dma
,
79 struct sk_buff
**skbl
, int num
)
83 /* Resubmit the entire ring */
84 for (i
=0; i
<num
; i
++) {
87 dma
[i
].len
= ADM5120_DMA_RXSIZE
;
88 dma
[i
].data
= ADM5120_DMA_ADDR(skbl
[i
]->data
) |
89 ADM5120_DMA_OWN
| (i
==num
-1 ? ADM5120_DMA_RINGEND
: 0);
93 static inline void adm5120_rx(struct adm5120_dma
*dma
, struct sk_buff
**skbl
,
96 struct sk_buff
*skb
, *skbn
;
97 struct adm5120_sw
*priv
;
98 struct net_device
*dev
;
101 while (!(dma
[*index
].data
& ADM5120_DMA_OWN
)) {
102 port
= (dma
[*index
].status
& ADM5120_DMA_PORTID
);
103 port
>>= ADM5120_DMA_PORTSHIFT
;
104 for (vlan
= 0; vlan
< adm5120_nrdevs
; vlan
++) {
105 if ((1<<port
) & vlan_matrix
[vlan
])
108 if (vlan
== adm5120_nrdevs
)
110 dev
= adm5120_devs
[vlan
];
112 len
= (dma
[*index
].status
& ADM5120_DMA_LEN
);
113 len
>>= ADM5120_DMA_LENSHIFT
;
116 priv
= netdev_priv(dev
);
117 if (len
<= 0 || len
> ADM5120_DMA_RXSIZE
||
118 dma
[*index
].status
& ADM5120_DMA_FCSERR
) {
119 priv
->stats
.rx_errors
++;
122 skbn
= dev_alloc_skb(ADM5120_DMA_RXSIZE
+16);
126 skb
->protocol
= eth_type_trans(skb
, dev
);
127 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
128 dev
->last_rx
= jiffies
;
129 priv
->stats
.rx_packets
++;
130 priv
->stats
.rx_bytes
+=len
;
131 skb_reserve(skbn
, 2);
134 printk(KERN_INFO
"%s recycling!\n", dev
->name
);
138 dma
[*index
].status
= 0;
139 dma
[*index
].cntl
= 0;
140 dma
[*index
].len
= ADM5120_DMA_RXSIZE
;
141 dma
[*index
].data
= ADM5120_DMA_ADDR(skbl
[*index
]->data
) |
143 (num
-1==*index
? ADM5120_DMA_RINGEND
: 0);
151 static inline void adm5120_tx(struct adm5120_dma
*dma
, struct sk_buff
**skbl
,
154 while((dma
[*index
].data
& ADM5120_DMA_OWN
) == 0 && skbl
[*index
]) {
155 dev_kfree_skb_irq(skbl
[*index
]);
162 static irqreturn_t
adm5120_sw_irq(int irq
, void *dev_id
)
164 unsigned long intreg
;
166 adm5120_set_reg(ADM5120_INT_MASK
,
167 adm5120_get_reg(ADM5120_INT_MASK
) | ADM5120_INTHANDLE
);
169 intreg
= adm5120_get_reg(ADM5120_INT_ST
);
170 adm5120_set_reg(ADM5120_INT_ST
, intreg
);
172 if (intreg
& ADM5120_INT_RXH
)
173 adm5120_rx(adm5120_dma_rxh
, adm5120_skb_rxh
, &adm5120_rxhi
,
175 if (intreg
& ADM5120_INT_HFULL
)
176 adm5120_rxfixup(adm5120_dma_rxh
, adm5120_skb_rxh
,
178 if (intreg
& ADM5120_INT_RXL
)
179 adm5120_rx(adm5120_dma_rxl
, adm5120_skb_rxl
, &adm5120_rxli
,
181 if (intreg
& ADM5120_INT_LFULL
)
182 adm5120_rxfixup(adm5120_dma_rxl
, adm5120_skb_rxl
,
184 if (intreg
& ADM5120_INT_TXH
)
185 adm5120_tx(adm5120_dma_txh
, adm5120_skb_txh
, &adm5120_txhit
,
187 if (intreg
& ADM5120_INT_TXL
)
188 adm5120_tx(adm5120_dma_txl
, adm5120_skb_txl
, &adm5120_txlit
,
191 adm5120_set_reg(ADM5120_INT_MASK
,
192 adm5120_get_reg(ADM5120_INT_MASK
) & ~ADM5120_INTHANDLE
);
197 static void adm5120_set_vlan(char *matrix
)
201 val
= matrix
[0] + (matrix
[1]<<8) + (matrix
[2]<<16) + (matrix
[3]<<24);
202 adm5120_set_reg(ADM5120_VLAN_GI
, val
);
203 val
= matrix
[4] + (matrix
[5]<<8);
204 adm5120_set_reg(ADM5120_VLAN_GII
, val
);
207 static int adm5120_sw_open(struct net_device
*dev
)
209 if (!adm5120_if_open
++)
210 adm5120_set_reg(ADM5120_INT_MASK
,
211 adm5120_get_reg(ADM5120_INT_MASK
) & ~ADM5120_INTHANDLE
);
212 netif_start_queue(dev
);
216 static int adm5120_sw_stop(struct net_device
*dev
)
218 netif_stop_queue(dev
);
219 if (!--adm5120_if_open
)
220 adm5120_set_reg(ADM5120_INT_MASK
,
221 adm5120_get_reg(ADM5120_INT_MASK
) | ADM5120_INTMASKALL
);
225 static int adm5120_sw_tx(struct sk_buff
*skb
, struct net_device
*dev
)
227 struct adm5120_dma
*dma
= adm5120_dma_txl
;
228 struct sk_buff
**skbl
= adm5120_skb_txl
;
229 struct adm5120_sw
*priv
= netdev_priv(dev
);
230 int *index
= &adm5120_txli
;
231 int num
= ADM5120_DMA_TXL
;
232 int trigger
= ADM5120_SEND_TRIG_L
;
234 dev
->trans_start
= jiffies
;
235 if (dma
[*index
].data
& ADM5120_DMA_OWN
) {
237 priv
->stats
.tx_dropped
++;
241 dma
[*index
].data
= ADM5120_DMA_ADDR(skb
->data
) | ADM5120_DMA_OWN
;
243 dma
[*index
].data
|= ADM5120_DMA_RINGEND
;
245 ((skb
->len
<ETH_ZLEN
?ETH_ZLEN
:skb
->len
) << ADM5120_DMA_LENSHIFT
) |
247 dma
[*index
].len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
248 priv
->stats
.tx_packets
++;
249 priv
->stats
.tx_bytes
+= skb
->len
;
254 adm5120_set_reg(ADM5120_SEND_TRIG
, trigger
);
259 static void adm5120_tx_timeout(struct net_device
*dev
)
261 netif_wake_queue(dev
);
264 static struct net_device_stats
*adm5120_sw_stats(struct net_device
*dev
)
266 return &((struct adm5120_sw
*)netdev_priv(dev
))->stats
;
269 static void adm5120_set_multicast_list(struct net_device
*dev
)
271 struct adm5120_sw
*priv
= netdev_priv(dev
);
274 portmask
= vlan_matrix
[priv
->port
] & 0x3f;
276 if (dev
->flags
& IFF_PROMISC
)
277 adm5120_set_reg(ADM5120_CPUP_CONF
,
278 adm5120_get_reg(ADM5120_CPUP_CONF
) &
279 ~((portmask
<< ADM5120_DISUNSHIFT
) & ADM5120_DISUNALL
));
281 adm5120_set_reg(ADM5120_CPUP_CONF
,
282 adm5120_get_reg(ADM5120_CPUP_CONF
) |
283 (portmask
<< ADM5120_DISUNSHIFT
));
285 if (dev
->flags
& IFF_PROMISC
|| dev
->flags
& IFF_ALLMULTI
||
287 adm5120_set_reg(ADM5120_CPUP_CONF
,
288 adm5120_get_reg(ADM5120_CPUP_CONF
) &
289 ~((portmask
<< ADM5120_DISMCSHIFT
) & ADM5120_DISMCALL
));
291 adm5120_set_reg(ADM5120_CPUP_CONF
,
292 adm5120_get_reg(ADM5120_CPUP_CONF
) |
293 (portmask
<< ADM5120_DISMCSHIFT
));
296 static void adm5120_write_mac(struct net_device
*dev
)
298 struct adm5120_sw
*priv
= netdev_priv(dev
);
299 unsigned char *mac
= dev
->dev_addr
;
301 adm5120_set_reg(ADM5120_MAC_WT1
,
302 mac
[2] | (mac
[3]<<8) | (mac
[4]<<16) | (mac
[5]<<24));
303 adm5120_set_reg(ADM5120_MAC_WT0
, (priv
->port
<<3) |
304 (mac
[0]<<16) | (mac
[1]<<24) | ADM5120_MAC_WRITE
| ADM5120_VLAN_EN
);
306 while (!(adm5120_get_reg(ADM5120_MAC_WT0
) & ADM5120_MAC_WRITE_DONE
));
309 static int adm5120_sw_set_mac_address(struct net_device
*dev
, void *p
)
311 struct sockaddr
*addr
= p
;
313 memcpy(dev
->dev_addr
, addr
->sa_data
, dev
->addr_len
);
314 adm5120_write_mac(dev
);
318 static int adm5120_do_ioctl(struct net_device
*dev
, struct ifreq
*rq
, int cmd
)
321 struct adm5120_sw_info info
;
322 struct adm5120_sw
*priv
= netdev_priv(dev
);
327 info
.ports
= adm5120_nrdevs
;
328 info
.vlan
= priv
->port
;
329 err
= copy_to_user(rq
->ifr_data
, &info
, sizeof(info
));
334 if (!capable(CAP_NET_ADMIN
))
336 err
= copy_from_user(vlan_matrix
, rq
->ifr_data
,
337 sizeof(vlan_matrix
));
340 adm5120_set_vlan(vlan_matrix
);
343 err
= copy_to_user(rq
->ifr_data
, vlan_matrix
,
344 sizeof(vlan_matrix
));
354 static void adm5120_dma_tx_init(struct adm5120_dma
*dma
, struct sk_buff
**skb
,
357 memset(dma
, 0, sizeof(struct adm5120_dma
)*num
);
358 dma
[num
-1].data
|= ADM5120_DMA_RINGEND
;
359 memset(skb
, 0, sizeof(struct skb
*)*num
);
362 static void adm5120_dma_rx_init(struct adm5120_dma
*dma
, struct sk_buff
**skb
,
367 memset(dma
, 0, sizeof(struct adm5120_dma
)*num
);
368 for (i
=0; i
<num
; i
++) {
369 skb
[i
] = dev_alloc_skb(ADM5120_DMA_RXSIZE
+16);
374 skb_reserve(skb
[i
], 2);
375 dma
[i
].data
= ADM5120_DMA_ADDR(skb
[i
]->data
) | ADM5120_DMA_OWN
;
377 dma
[i
].len
= ADM5120_DMA_RXSIZE
;
380 dma
[i
-1].data
|= ADM5120_DMA_RINGEND
;
383 static int __init
adm5120_sw_init(void)
386 struct net_device
*dev
;
388 err
= request_irq(SW_IRQ
, adm5120_sw_irq
, 0, "ethernet switch", NULL
);
392 adm5120_nrdevs
= adm5120_board
.iface_num
;
393 if (adm5120_nrdevs
> 5 && !adm5120_has_gmii())
396 adm5120_set_reg(ADM5120_CPUP_CONF
,
397 ADM5120_DISCCPUPORT
| ADM5120_CRC_PADDING
|
398 ADM5120_DISUNALL
| ADM5120_DISMCALL
);
399 adm5120_set_reg(ADM5120_PORT_CONF0
, ADM5120_ENMC
| ADM5120_ENBP
);
401 adm5120_set_reg(ADM5120_PHY_CNTL2
, adm5120_get_reg(ADM5120_PHY_CNTL2
) |
402 ADM5120_AUTONEG
| ADM5120_NORMAL
| ADM5120_AUTOMDIX
);
403 adm5120_set_reg(ADM5120_PHY_CNTL3
, adm5120_get_reg(ADM5120_PHY_CNTL3
) |
406 adm5120_set_reg(ADM5120_INT_MASK
, ADM5120_INTMASKALL
);
407 adm5120_set_reg(ADM5120_INT_ST
, ADM5120_INTMASKALL
);
409 adm5120_dma_txh
= (void *)KSEG1ADDR((u32
)adm5120_dma_txh_v
);
410 adm5120_dma_txl
= (void *)KSEG1ADDR((u32
)adm5120_dma_txl_v
);
411 adm5120_dma_rxh
= (void *)KSEG1ADDR((u32
)adm5120_dma_rxh_v
);
412 adm5120_dma_rxl
= (void *)KSEG1ADDR((u32
)adm5120_dma_rxl_v
);
414 adm5120_dma_tx_init(adm5120_dma_txh
, adm5120_skb_txh
, ADM5120_DMA_TXH
);
415 adm5120_dma_tx_init(adm5120_dma_txl
, adm5120_skb_txl
, ADM5120_DMA_TXL
);
416 adm5120_dma_rx_init(adm5120_dma_rxh
, adm5120_skb_rxh
, ADM5120_DMA_RXH
);
417 adm5120_dma_rx_init(adm5120_dma_rxl
, adm5120_skb_rxl
, ADM5120_DMA_RXL
);
418 adm5120_set_reg(ADM5120_SEND_HBADDR
, KSEG1ADDR(adm5120_dma_txh
));
419 adm5120_set_reg(ADM5120_SEND_LBADDR
, KSEG1ADDR(adm5120_dma_txl
));
420 adm5120_set_reg(ADM5120_RECEIVE_HBADDR
, KSEG1ADDR(adm5120_dma_rxh
));
421 adm5120_set_reg(ADM5120_RECEIVE_LBADDR
, KSEG1ADDR(adm5120_dma_rxl
));
423 adm5120_set_vlan(vlan_matrix
);
425 for (i
=0; i
<adm5120_nrdevs
; i
++) {
426 adm5120_devs
[i
] = alloc_etherdev(sizeof(struct adm5120_sw
));
427 if (!adm5120_devs
[i
]) {
432 dev
= adm5120_devs
[i
];
433 SET_MODULE_OWNER(dev
);
434 memset(netdev_priv(dev
), 0, sizeof(struct adm5120_sw
));
435 ((struct adm5120_sw
*)netdev_priv(dev
))->port
= i
;
436 dev
->base_addr
= SW_BASE
;
438 dev
->open
= adm5120_sw_open
;
439 dev
->hard_start_xmit
= adm5120_sw_tx
;
440 dev
->stop
= adm5120_sw_stop
;
441 dev
->get_stats
= adm5120_sw_stats
;
442 dev
->set_multicast_list
= adm5120_set_multicast_list
;
443 dev
->do_ioctl
= adm5120_do_ioctl
;
444 dev
->tx_timeout
= adm5120_tx_timeout
;
445 dev
->watchdog_timeo
= ETH_TX_TIMEOUT
;
446 dev
->set_mac_address
= adm5120_sw_set_mac_address
;
447 /* HACK alert!!! In the original admtek driver it is asumed
448 that you can read the MAC addressess from flash, but edimax
449 decided to leave that space intentionally blank...
451 memcpy(dev
->dev_addr
, "\x00\x50\xfc\x11\x22\x01", 6);
452 dev
->dev_addr
[5] += i
;
453 adm5120_write_mac(dev
);
455 if ((err
= register_netdev(dev
))) {
459 printk(KERN_INFO
"%s: ADM5120 switch port%d\n", dev
->name
, i
);
461 adm5120_set_reg(ADM5120_CPUP_CONF
,
462 ADM5120_CRC_PADDING
| ADM5120_DISUNALL
| ADM5120_DISMCALL
);
467 /* Undo everything that did succeed */
469 unregister_netdev(adm5120_devs
[i
-1]);
470 free_netdev(adm5120_devs
[i
-1]);
472 free_irq(SW_IRQ
, NULL
);
474 printk(KERN_ERR
"ADM5120 Ethernet switch init failed\n");
478 static void __exit
adm5120_sw_exit(void)
482 for (i
= 0; i
< adm5120_nrdevs
; i
++) {
483 unregister_netdev(adm5120_devs
[i
]);
484 free_netdev(adm5120_devs
[i
-1]);
487 free_irq(SW_IRQ
, NULL
);
489 for (i
= 0; i
< ADM5120_DMA_RXH
; i
++) {
490 if (!adm5120_skb_rxh
[i
])
492 kfree_skb(adm5120_skb_rxh
[i
]);
494 for (i
= 0; i
< ADM5120_DMA_RXL
; i
++) {
495 if (!adm5120_skb_rxl
[i
])
497 kfree_skb(adm5120_skb_rxl
[i
]);
501 module_init(adm5120_sw_init
);
502 module_exit(adm5120_sw_exit
);