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>
24 #include <asm/mach-adm5120/adm5120_irq.h>
26 MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)");
27 MODULE_DESCRIPTION("ADM5120 ethernet switch driver");
28 MODULE_LICENSE("GPL");
31 * The ADM5120 uses an internal matrix to determine which ports
32 * belong to which VLAN.
33 * The default generates a VLAN (and device) for each port
34 * (including MII port) and the CPU port is part of all of them.
36 * Another example, one big switch and everything mapped to eth0:
37 * 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00
39 static unsigned char vlan_matrix
[SW_DEVS
] = {
40 0x41, 0x42, 0x44, 0x48, 0x50, 0x60
43 static int adm5120_nrdevs
;
45 static struct net_device
*adm5120_devs
[SW_DEVS
];
46 static struct adm5120_dma
47 adm5120_dma_txh_v
[ADM5120_DMA_TXH
] __attribute__((aligned(16))),
48 adm5120_dma_txl_v
[ADM5120_DMA_TXL
] __attribute__((aligned(16))),
49 adm5120_dma_rxh_v
[ADM5120_DMA_RXH
] __attribute__((aligned(16))),
50 adm5120_dma_rxl_v
[ADM5120_DMA_RXL
] __attribute__((aligned(16))),
56 *adm5120_skb_rxh
[ADM5120_DMA_RXH
],
57 *adm5120_skb_rxl
[ADM5120_DMA_RXL
],
58 *adm5120_skb_txh
[ADM5120_DMA_TXH
],
59 *adm5120_skb_txl
[ADM5120_DMA_TXL
];
60 static int adm5120_rxhi
= 0;
61 static int adm5120_rxli
= 0;
62 /* We don't use high priority tx for now */
63 /*static int adm5120_txhi = 0;*/
64 static int adm5120_txli
= 0;
65 static int adm5120_txhit
= 0;
66 static int adm5120_txlit
= 0;
67 static int adm5120_if_open
= 0;
69 static inline void adm5120_set_reg(unsigned int reg
, unsigned long val
)
71 *(volatile unsigned long*)(SW_BASE
+reg
) = val
;
74 static inline unsigned long adm5120_get_reg(unsigned int reg
)
76 return *(volatile unsigned long*)(SW_BASE
+reg
);
79 static inline void adm5120_rxfixup(struct adm5120_dma
*dma
,
80 struct sk_buff
**skbl
, int num
)
84 /* Resubmit the entire ring */
85 for (i
=0; i
<num
; i
++) {
88 dma
[i
].len
= ADM5120_DMA_RXSIZE
;
89 dma
[i
].data
= ADM5120_DMA_ADDR(skbl
[i
]->data
) |
90 ADM5120_DMA_OWN
| (i
==num
-1 ? ADM5120_DMA_RINGEND
: 0);
94 static inline void adm5120_rx(struct adm5120_dma
*dma
, struct sk_buff
**skbl
,
97 struct sk_buff
*skb
, *skbn
;
98 struct adm5120_sw
*priv
;
99 struct net_device
*dev
;
102 while (!(dma
[*index
].data
& ADM5120_DMA_OWN
)) {
103 port
= (dma
[*index
].status
& ADM5120_DMA_PORTID
);
104 port
>>= ADM5120_DMA_PORTSHIFT
;
105 for (vlan
= 0; vlan
< adm5120_nrdevs
; vlan
++) {
106 if ((1<<port
) & vlan_matrix
[vlan
])
109 if (vlan
== adm5120_nrdevs
)
111 dev
= adm5120_devs
[vlan
];
113 len
= (dma
[*index
].status
& ADM5120_DMA_LEN
);
114 len
>>= ADM5120_DMA_LENSHIFT
;
117 priv
= netdev_priv(dev
);
118 if (len
<= 0 || len
> ADM5120_DMA_RXSIZE
||
119 dma
[*index
].status
& ADM5120_DMA_FCSERR
) {
120 priv
->stats
.rx_errors
++;
123 skbn
= dev_alloc_skb(ADM5120_DMA_RXSIZE
+16);
127 skb
->protocol
= eth_type_trans(skb
, dev
);
128 skb
->ip_summed
= CHECKSUM_UNNECESSARY
;
129 dev
->last_rx
= jiffies
;
130 priv
->stats
.rx_packets
++;
131 priv
->stats
.rx_bytes
+=len
;
132 skb_reserve(skbn
, 2);
135 printk(KERN_INFO
"%s recycling!\n", dev
->name
);
139 dma
[*index
].status
= 0;
140 dma
[*index
].cntl
= 0;
141 dma
[*index
].len
= ADM5120_DMA_RXSIZE
;
142 dma
[*index
].data
= ADM5120_DMA_ADDR(skbl
[*index
]->data
) |
144 (num
-1==*index
? ADM5120_DMA_RINGEND
: 0);
152 static inline void adm5120_tx(struct adm5120_dma
*dma
, struct sk_buff
**skbl
,
155 while((dma
[*index
].data
& ADM5120_DMA_OWN
) == 0 && skbl
[*index
]) {
156 dev_kfree_skb_irq(skbl
[*index
]);
163 static irqreturn_t
adm5120_sw_irq(int irq
, void *dev_id
)
165 unsigned long intreg
;
167 adm5120_set_reg(ADM5120_INT_MASK
,
168 adm5120_get_reg(ADM5120_INT_MASK
) | ADM5120_INTHANDLE
);
170 intreg
= adm5120_get_reg(ADM5120_INT_ST
);
171 adm5120_set_reg(ADM5120_INT_ST
, intreg
);
173 if (intreg
& ADM5120_INT_RXH
)
174 adm5120_rx(adm5120_dma_rxh
, adm5120_skb_rxh
, &adm5120_rxhi
,
176 if (intreg
& ADM5120_INT_HFULL
)
177 adm5120_rxfixup(adm5120_dma_rxh
, adm5120_skb_rxh
,
179 if (intreg
& ADM5120_INT_RXL
)
180 adm5120_rx(adm5120_dma_rxl
, adm5120_skb_rxl
, &adm5120_rxli
,
182 if (intreg
& ADM5120_INT_LFULL
)
183 adm5120_rxfixup(adm5120_dma_rxl
, adm5120_skb_rxl
,
185 if (intreg
& ADM5120_INT_TXH
)
186 adm5120_tx(adm5120_dma_txh
, adm5120_skb_txh
, &adm5120_txhit
,
188 if (intreg
& ADM5120_INT_TXL
)
189 adm5120_tx(adm5120_dma_txl
, adm5120_skb_txl
, &adm5120_txlit
,
192 adm5120_set_reg(ADM5120_INT_MASK
,
193 adm5120_get_reg(ADM5120_INT_MASK
) & ~ADM5120_INTHANDLE
);
198 static void adm5120_set_vlan(char *matrix
)
202 val
= matrix
[0] + (matrix
[1]<<8) + (matrix
[2]<<16) + (matrix
[3]<<24);
203 adm5120_set_reg(ADM5120_VLAN_GI
, val
);
204 val
= matrix
[4] + (matrix
[5]<<8);
205 adm5120_set_reg(ADM5120_VLAN_GII
, val
);
208 static int adm5120_sw_open(struct net_device
*dev
)
210 if (!adm5120_if_open
++)
211 adm5120_set_reg(ADM5120_INT_MASK
,
212 adm5120_get_reg(ADM5120_INT_MASK
) & ~ADM5120_INTHANDLE
);
213 netif_start_queue(dev
);
217 static int adm5120_sw_stop(struct net_device
*dev
)
219 netif_stop_queue(dev
);
220 if (!--adm5120_if_open
)
221 adm5120_set_reg(ADM5120_INT_MASK
,
222 adm5120_get_reg(ADM5120_INT_MASK
) | ADM5120_INTMASKALL
);
226 static int adm5120_sw_tx(struct sk_buff
*skb
, struct net_device
*dev
)
228 struct adm5120_dma
*dma
= adm5120_dma_txl
;
229 struct sk_buff
**skbl
= adm5120_skb_txl
;
230 struct adm5120_sw
*priv
= netdev_priv(dev
);
231 int *index
= &adm5120_txli
;
232 int num
= ADM5120_DMA_TXL
;
233 int trigger
= ADM5120_SEND_TRIG_L
;
235 dev
->trans_start
= jiffies
;
236 if (dma
[*index
].data
& ADM5120_DMA_OWN
) {
238 priv
->stats
.tx_dropped
++;
242 dma
[*index
].data
= ADM5120_DMA_ADDR(skb
->data
) | ADM5120_DMA_OWN
;
244 dma
[*index
].data
|= ADM5120_DMA_RINGEND
;
246 ((skb
->len
<ETH_ZLEN
?ETH_ZLEN
:skb
->len
) << ADM5120_DMA_LENSHIFT
) |
248 dma
[*index
].len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
249 priv
->stats
.tx_packets
++;
250 priv
->stats
.tx_bytes
+= skb
->len
;
255 adm5120_set_reg(ADM5120_SEND_TRIG
, trigger
);
260 static void adm5120_tx_timeout(struct net_device
*dev
)
262 netif_wake_queue(dev
);
265 static struct net_device_stats
*adm5120_sw_stats(struct net_device
*dev
)
267 return &((struct adm5120_sw
*)netdev_priv(dev
))->stats
;
270 static void adm5120_set_multicast_list(struct net_device
*dev
)
272 struct adm5120_sw
*priv
= netdev_priv(dev
);
275 portmask
= vlan_matrix
[priv
->port
] & 0x3f;
277 if (dev
->flags
& IFF_PROMISC
)
278 adm5120_set_reg(ADM5120_CPUP_CONF
,
279 adm5120_get_reg(ADM5120_CPUP_CONF
) &
280 ~((portmask
<< ADM5120_DISUNSHIFT
) & ADM5120_DISUNALL
));
282 adm5120_set_reg(ADM5120_CPUP_CONF
,
283 adm5120_get_reg(ADM5120_CPUP_CONF
) |
284 (portmask
<< ADM5120_DISUNSHIFT
));
286 if (dev
->flags
& IFF_PROMISC
|| dev
->flags
& IFF_ALLMULTI
||
288 adm5120_set_reg(ADM5120_CPUP_CONF
,
289 adm5120_get_reg(ADM5120_CPUP_CONF
) &
290 ~((portmask
<< ADM5120_DISMCSHIFT
) & ADM5120_DISMCALL
));
292 adm5120_set_reg(ADM5120_CPUP_CONF
,
293 adm5120_get_reg(ADM5120_CPUP_CONF
) |
294 (portmask
<< ADM5120_DISMCSHIFT
));
297 static void adm5120_write_mac(struct net_device
*dev
)
299 struct adm5120_sw
*priv
= netdev_priv(dev
);
300 unsigned char *mac
= dev
->dev_addr
;
302 adm5120_set_reg(ADM5120_MAC_WT1
,
303 mac
[2] | (mac
[3]<<8) | (mac
[4]<<16) | (mac
[5]<<24));
304 adm5120_set_reg(ADM5120_MAC_WT0
, (priv
->port
<<3) |
305 (mac
[0]<<16) | (mac
[1]<<24) | ADM5120_MAC_WRITE
| ADM5120_VLAN_EN
);
307 while (!(adm5120_get_reg(ADM5120_MAC_WT0
) & ADM5120_MAC_WRITE_DONE
));
310 static int adm5120_sw_set_mac_address(struct net_device
*dev
, void *p
)
312 struct sockaddr
*addr
= p
;
314 memcpy(dev
->dev_addr
, addr
->sa_data
, dev
->addr_len
);
315 adm5120_write_mac(dev
);
319 static int adm5120_do_ioctl(struct net_device
*dev
, struct ifreq
*rq
, int cmd
)
322 struct adm5120_sw_info info
;
323 struct adm5120_sw
*priv
= netdev_priv(dev
);
328 info
.ports
= adm5120_nrdevs
;
329 info
.vlan
= priv
->port
;
330 err
= copy_to_user(rq
->ifr_data
, &info
, sizeof(info
));
335 if (!capable(CAP_NET_ADMIN
))
337 err
= copy_from_user(vlan_matrix
, rq
->ifr_data
,
338 sizeof(vlan_matrix
));
341 adm5120_set_vlan(vlan_matrix
);
344 err
= copy_to_user(rq
->ifr_data
, vlan_matrix
,
345 sizeof(vlan_matrix
));
355 static void adm5120_dma_tx_init(struct adm5120_dma
*dma
, struct sk_buff
**skb
,
358 memset(dma
, 0, sizeof(struct adm5120_dma
)*num
);
359 dma
[num
-1].data
|= ADM5120_DMA_RINGEND
;
360 memset(skb
, 0, sizeof(struct skb
*)*num
);
363 static void adm5120_dma_rx_init(struct adm5120_dma
*dma
, struct sk_buff
**skb
,
368 memset(dma
, 0, sizeof(struct adm5120_dma
)*num
);
369 for (i
=0; i
<num
; i
++) {
370 skb
[i
] = dev_alloc_skb(ADM5120_DMA_RXSIZE
+16);
375 skb_reserve(skb
[i
], 2);
376 dma
[i
].data
= ADM5120_DMA_ADDR(skb
[i
]->data
) | ADM5120_DMA_OWN
;
378 dma
[i
].len
= ADM5120_DMA_RXSIZE
;
381 dma
[i
-1].data
|= ADM5120_DMA_RINGEND
;
384 static int __init
adm5120_sw_init(void)
387 struct net_device
*dev
;
389 err
= request_irq(ADM5120_IRQ_SWITCH
, adm5120_sw_irq
, 0, "ethernet switch", NULL
);
393 adm5120_nrdevs
= adm5120_board
.iface_num
;
394 if (adm5120_nrdevs
> 5 && !adm5120_has_gmii())
397 adm5120_set_reg(ADM5120_CPUP_CONF
,
398 ADM5120_DISCCPUPORT
| ADM5120_CRC_PADDING
|
399 ADM5120_DISUNALL
| ADM5120_DISMCALL
);
400 adm5120_set_reg(ADM5120_PORT_CONF0
, ADM5120_ENMC
| ADM5120_ENBP
);
402 adm5120_set_reg(ADM5120_PHY_CNTL2
, adm5120_get_reg(ADM5120_PHY_CNTL2
) |
403 ADM5120_AUTONEG
| ADM5120_NORMAL
| ADM5120_AUTOMDIX
);
404 adm5120_set_reg(ADM5120_PHY_CNTL3
, adm5120_get_reg(ADM5120_PHY_CNTL3
) |
407 adm5120_set_reg(ADM5120_INT_MASK
, ADM5120_INTMASKALL
);
408 adm5120_set_reg(ADM5120_INT_ST
, ADM5120_INTMASKALL
);
410 adm5120_dma_txh
= (void *)KSEG1ADDR((u32
)adm5120_dma_txh_v
);
411 adm5120_dma_txl
= (void *)KSEG1ADDR((u32
)adm5120_dma_txl_v
);
412 adm5120_dma_rxh
= (void *)KSEG1ADDR((u32
)adm5120_dma_rxh_v
);
413 adm5120_dma_rxl
= (void *)KSEG1ADDR((u32
)adm5120_dma_rxl_v
);
415 adm5120_dma_tx_init(adm5120_dma_txh
, adm5120_skb_txh
, ADM5120_DMA_TXH
);
416 adm5120_dma_tx_init(adm5120_dma_txl
, adm5120_skb_txl
, ADM5120_DMA_TXL
);
417 adm5120_dma_rx_init(adm5120_dma_rxh
, adm5120_skb_rxh
, ADM5120_DMA_RXH
);
418 adm5120_dma_rx_init(adm5120_dma_rxl
, adm5120_skb_rxl
, ADM5120_DMA_RXL
);
419 adm5120_set_reg(ADM5120_SEND_HBADDR
, KSEG1ADDR(adm5120_dma_txh
));
420 adm5120_set_reg(ADM5120_SEND_LBADDR
, KSEG1ADDR(adm5120_dma_txl
));
421 adm5120_set_reg(ADM5120_RECEIVE_HBADDR
, KSEG1ADDR(adm5120_dma_rxh
));
422 adm5120_set_reg(ADM5120_RECEIVE_LBADDR
, KSEG1ADDR(adm5120_dma_rxl
));
424 adm5120_set_vlan(vlan_matrix
);
426 for (i
=0; i
<adm5120_nrdevs
; i
++) {
427 adm5120_devs
[i
] = alloc_etherdev(sizeof(struct adm5120_sw
));
428 if (!adm5120_devs
[i
]) {
433 dev
= adm5120_devs
[i
];
434 SET_MODULE_OWNER(dev
);
435 memset(netdev_priv(dev
), 0, sizeof(struct adm5120_sw
));
436 ((struct adm5120_sw
*)netdev_priv(dev
))->port
= i
;
437 dev
->base_addr
= SW_BASE
;
438 dev
->irq
= ADM5120_IRQ_SWITCH
;
439 dev
->open
= adm5120_sw_open
;
440 dev
->hard_start_xmit
= adm5120_sw_tx
;
441 dev
->stop
= adm5120_sw_stop
;
442 dev
->get_stats
= adm5120_sw_stats
;
443 dev
->set_multicast_list
= adm5120_set_multicast_list
;
444 dev
->do_ioctl
= adm5120_do_ioctl
;
445 dev
->tx_timeout
= adm5120_tx_timeout
;
446 dev
->watchdog_timeo
= ETH_TX_TIMEOUT
;
447 dev
->set_mac_address
= adm5120_sw_set_mac_address
;
448 /* HACK alert!!! In the original admtek driver it is asumed
449 that you can read the MAC addressess from flash, but edimax
450 decided to leave that space intentionally blank...
452 memcpy(dev
->dev_addr
, "\x00\x50\xfc\x11\x22\x01", 6);
453 dev
->dev_addr
[5] += i
;
454 adm5120_write_mac(dev
);
456 if ((err
= register_netdev(dev
))) {
460 printk(KERN_INFO
"%s: ADM5120 switch port%d\n", dev
->name
, i
);
462 adm5120_set_reg(ADM5120_CPUP_CONF
,
463 ADM5120_CRC_PADDING
| ADM5120_DISUNALL
| ADM5120_DISMCALL
);
468 /* Undo everything that did succeed */
470 unregister_netdev(adm5120_devs
[i
-1]);
471 free_netdev(adm5120_devs
[i
-1]);
473 free_irq(ADM5120_IRQ_SWITCH
, NULL
);
475 printk(KERN_ERR
"ADM5120 Ethernet switch init failed\n");
479 static void __exit
adm5120_sw_exit(void)
483 for (i
= 0; i
< adm5120_nrdevs
; i
++) {
484 unregister_netdev(adm5120_devs
[i
]);
485 free_netdev(adm5120_devs
[i
-1]);
488 free_irq(ADM5120_IRQ_SWITCH
, NULL
);
490 for (i
= 0; i
< ADM5120_DMA_RXH
; i
++) {
491 if (!adm5120_skb_rxh
[i
])
493 kfree_skb(adm5120_skb_rxh
[i
]);
495 for (i
= 0; i
< ADM5120_DMA_RXL
; i
++) {
496 if (!adm5120_skb_rxl
[i
])
498 kfree_skb(adm5120_skb_rxl
[i
]);
502 module_init(adm5120_sw_init
);
503 module_exit(adm5120_sw_exit
);