Do not register more than 2 ethernet porst for CFE based devices (i.e : Compex WP54G...
[librecmc/librecmc.git] / target / linux / adm5120-2.6 / files / drivers / net / adm5120sw.c
1 /*
2  *      ADM5120 built in ethernet switch driver
3  *
4  *      Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005
5  *
6  *      Inspiration for this driver came from the original ADMtek 2.4 
7  *      driver, Copyright ADMtek Inc.
8  */
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>
19 #include <asm/irq.h>
20 #include <asm/io.h>
21 #include "adm5120sw.h"
22
23 MODULE_AUTHOR("Jeroen Vreeken (pe1rxq@amsat.org)");
24 MODULE_DESCRIPTION("ADM5120 ethernet switch driver");
25 MODULE_LICENSE("GPL");
26
27 /*
28  *      The ADM5120 uses an internal matrix to determine which ports
29  *      belong to which VLAN.
30  *      The default generates a VLAN (and device) for each port 
31  *      (including MII port) and the CPU port is part of all of them.
32  *
33  *      Another example, one big switch and everything mapped to eth0:
34  *      0x7f, 0x00, 0x00, 0x00, 0x00, 0x00
35  */
36 static unsigned char vlan_matrix[SW_DEVS] = {
37         0x41, 0x42, 0x44, 0x48, 0x50, 0x60
38 };
39
40 static int adm5120_nrdevs;
41
42 static struct net_device *adm5120_devs[SW_DEVS];
43 static struct adm5120_dma 
44     adm5120_dma_txh_v[ADM5120_DMA_TXH] __attribute__((aligned(16))),
45     adm5120_dma_txl_v[ADM5120_DMA_TXL] __attribute__((aligned(16))),
46     adm5120_dma_rxh_v[ADM5120_DMA_RXH] __attribute__((aligned(16))),
47     adm5120_dma_rxl_v[ADM5120_DMA_RXL] __attribute__((aligned(16))),
48     *adm5120_dma_txh,
49     *adm5120_dma_txl,
50     *adm5120_dma_rxh,
51     *adm5120_dma_rxl;
52 static struct sk_buff
53     *adm5120_skb_rxh[ADM5120_DMA_RXH],
54     *adm5120_skb_rxl[ADM5120_DMA_RXL],
55     *adm5120_skb_txh[ADM5120_DMA_TXH],
56     *adm5120_skb_txl[ADM5120_DMA_TXL];
57 static int adm5120_rxhi = 0;
58 static int adm5120_rxli = 0;
59 /* We don't use high priority tx for now */
60 /*static int adm5120_txhi = 0;*/
61 static int adm5120_txli = 0;
62 static int adm5120_txhit = 0;
63 static int adm5120_txlit = 0;
64 static int adm5120_if_open = 0;
65
66 static inline void adm5120_set_reg(unsigned int reg, unsigned long val)
67 {
68         *(volatile unsigned long*)(SW_BASE+reg) = val;
69 }
70
71 static inline unsigned long adm5120_get_reg(unsigned int reg)
72 {
73         return *(volatile unsigned long*)(SW_BASE+reg);
74 }
75
76 static inline void adm5120_rxfixup(struct adm5120_dma *dma,
77     struct sk_buff **skbl, int num)
78 {
79         int i;
80
81         /* Resubmit the entire ring */
82         for (i=0; i<num; i++) {
83                 dma[i].status = 0;
84                 dma[i].cntl = 0;
85                 dma[i].len = ADM5120_DMA_RXSIZE;
86                 dma[i].data = ADM5120_DMA_ADDR(skbl[i]->data) |
87                      ADM5120_DMA_OWN | (i==num-1 ? ADM5120_DMA_RINGEND : 0);
88         }
89 }
90
91 static inline void adm5120_rx(struct adm5120_dma *dma, struct sk_buff **skbl,
92     int *index, int num)
93 {
94         struct sk_buff *skb, *skbn;
95         struct adm5120_sw *priv;
96         struct net_device *dev;
97         int port, vlan, len;
98
99         while (!(dma[*index].data & ADM5120_DMA_OWN)) {
100                 port = (dma[*index].status & ADM5120_DMA_PORTID);
101                 port >>= ADM5120_DMA_PORTSHIFT;
102                 for (vlan = 0; vlan < adm5120_nrdevs; vlan++) {
103                         if ((1<<port) & vlan_matrix[vlan])
104                                 break;
105                 }
106                 if (vlan == adm5120_nrdevs)
107                         vlan = 0;
108                 dev = adm5120_devs[vlan];
109                 skb = skbl[*index];
110                 len = (dma[*index].status & ADM5120_DMA_LEN);
111                 len >>= ADM5120_DMA_LENSHIFT;
112                 len -= ETH_FCS;
113
114                 priv = netdev_priv(dev);
115                 if (len <= 0 || len > ADM5120_DMA_RXSIZE ||
116                     dma[*index].status & ADM5120_DMA_FCSERR) {
117                         priv->stats.rx_errors++;
118                         skbn = NULL;
119                 } else {
120                         skbn = dev_alloc_skb(ADM5120_DMA_RXSIZE+16);
121                         if (skbn) {
122                                 skb_put(skb, len);
123                                 skb->dev = dev;
124                                 skb->protocol = eth_type_trans(skb, dev);
125                                 skb->ip_summed = CHECKSUM_UNNECESSARY;
126                                 dev->last_rx = jiffies;
127                                 priv->stats.rx_packets++;
128                                 priv->stats.rx_bytes+=len;
129                                 skb_reserve(skbn, 2);
130                                 skbl[*index] = skbn;
131                         } else {
132                                 printk(KERN_INFO "%s recycling!\n", dev->name);
133                         }
134                 }
135
136                 dma[*index].status = 0;
137                 dma[*index].cntl = 0;
138                 dma[*index].len = ADM5120_DMA_RXSIZE;
139                 dma[*index].data = ADM5120_DMA_ADDR(skbl[*index]->data) |
140                      ADM5120_DMA_OWN |
141                      (num-1==*index ? ADM5120_DMA_RINGEND : 0);
142                 if (num == ++*index)
143                         *index = 0;
144                 if (skbn)
145                         netif_rx(skb);
146         }
147 }
148
149 static inline void adm5120_tx(struct adm5120_dma *dma, struct sk_buff **skbl,
150     int *index, int num)
151 {
152         while((dma[*index].data & ADM5120_DMA_OWN) == 0 && skbl[*index]) {
153                 dev_kfree_skb_irq(skbl[*index]);
154                 skbl[*index] = NULL;
155                 if (++*index == num)
156                         *index = 0;
157         }
158 }
159
160 irqreturn_t adm5120_sw_irq(int irq, void *dev_id, struct pt_regs *regs)
161 {
162         unsigned long intreg;
163
164         adm5120_set_reg(ADM5120_INT_MASK,
165             adm5120_get_reg(ADM5120_INT_MASK) | ADM5120_INTHANDLE);
166
167         intreg = adm5120_get_reg(ADM5120_INT_ST);
168         adm5120_set_reg(ADM5120_INT_ST, intreg);
169
170         if (intreg & ADM5120_INT_RXH)
171                 adm5120_rx(adm5120_dma_rxh, adm5120_skb_rxh, &adm5120_rxhi,
172                 ADM5120_DMA_RXH);
173         if (intreg & ADM5120_INT_HFULL)
174                 adm5120_rxfixup(adm5120_dma_rxh, adm5120_skb_rxh,
175                 ADM5120_DMA_RXH);
176         if (intreg & ADM5120_INT_RXL)
177                 adm5120_rx(adm5120_dma_rxl, adm5120_skb_rxl, &adm5120_rxli,
178                     ADM5120_DMA_RXL);
179         if (intreg & ADM5120_INT_LFULL)
180                 adm5120_rxfixup(adm5120_dma_rxl, adm5120_skb_rxl,
181                 ADM5120_DMA_RXL);
182         if (intreg & ADM5120_INT_TXH)
183                 adm5120_tx(adm5120_dma_txh, adm5120_skb_txh, &adm5120_txhit,
184                 ADM5120_DMA_TXH);
185         if (intreg & ADM5120_INT_TXL)
186                 adm5120_tx(adm5120_dma_txl, adm5120_skb_txl, &adm5120_txlit,
187                 ADM5120_DMA_TXL);
188
189         adm5120_set_reg(ADM5120_INT_MASK,
190             adm5120_get_reg(ADM5120_INT_MASK) & ~ADM5120_INTHANDLE);
191
192         return IRQ_HANDLED;
193 }
194
195 static void adm5120_set_vlan(char *matrix)
196 {
197         unsigned long val;
198
199         val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24);
200         adm5120_set_reg(ADM5120_VLAN_GI, val);
201         val = matrix[4] + (matrix[5]<<8);
202         adm5120_set_reg(ADM5120_VLAN_GII, val);
203 }
204
205 static int adm5120_sw_open(struct net_device *dev)
206 {
207         if (!adm5120_if_open++)
208                 adm5120_set_reg(ADM5120_INT_MASK,
209                     adm5120_get_reg(ADM5120_INT_MASK) & ~ADM5120_INTHANDLE);
210         netif_start_queue(dev);
211         return 0;
212 }
213
214 static int adm5120_sw_stop(struct net_device *dev)
215 {
216         netif_stop_queue(dev);
217         if (!--adm5120_if_open)
218                 adm5120_set_reg(ADM5120_INT_MASK,
219                     adm5120_get_reg(ADM5120_INT_MASK) | ADM5120_INTMASKALL);
220         return 0;
221 }
222
223 static int adm5120_sw_tx(struct sk_buff *skb, struct net_device *dev)
224 {
225         struct adm5120_dma *dma = adm5120_dma_txl;
226         struct sk_buff **skbl = adm5120_skb_txl;
227         struct adm5120_sw *priv = netdev_priv(dev);
228         int *index = &adm5120_txli;
229         int num = ADM5120_DMA_TXL;
230         int trigger = ADM5120_SEND_TRIG_L;
231
232         dev->trans_start = jiffies;
233         if (dma[*index].data & ADM5120_DMA_OWN) {
234                 dev_kfree_skb(skb);
235                 priv->stats.tx_dropped++;
236                 return 0;
237         }
238
239         dma[*index].data = ADM5120_DMA_ADDR(skb->data) | ADM5120_DMA_OWN;
240         if (*index == num-1)
241                 dma[*index].data |= ADM5120_DMA_RINGEND;
242         dma[*index].status =
243             ((skb->len<ETH_ZLEN?ETH_ZLEN:skb->len) << ADM5120_DMA_LENSHIFT) |
244             (0x1 << priv->port);
245         dma[*index].len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
246         priv->stats.tx_packets++;
247         priv->stats.tx_bytes += skb->len;
248         skbl[*index]=skb;
249
250         if (++*index == num)
251                 *index = 0;
252         adm5120_set_reg(ADM5120_SEND_TRIG, trigger);
253
254         return 0;
255 }
256
257 static void adm5120_tx_timeout(struct net_device *dev)
258 {
259         netif_wake_queue(dev);
260 }
261
262 static struct net_device_stats *adm5120_sw_stats(struct net_device *dev)
263 {
264         return &((struct adm5120_sw *)netdev_priv(dev))->stats;
265 }
266
267 static void adm5120_set_multicast_list(struct net_device *dev)
268 {
269         struct adm5120_sw *priv = netdev_priv(dev);
270         int portmask;
271
272         portmask = vlan_matrix[priv->port] & 0x3f;
273
274         if (dev->flags & IFF_PROMISC)
275                 adm5120_set_reg(ADM5120_CPUP_CONF,
276                     adm5120_get_reg(ADM5120_CPUP_CONF) &
277                     ~((portmask << ADM5120_DISUNSHIFT) & ADM5120_DISUNALL));
278         else
279                 adm5120_set_reg(ADM5120_CPUP_CONF,
280                     adm5120_get_reg(ADM5120_CPUP_CONF) |
281                     (portmask << ADM5120_DISUNSHIFT));
282
283         if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI ||
284             dev->mc_count)
285                 adm5120_set_reg(ADM5120_CPUP_CONF,
286                     adm5120_get_reg(ADM5120_CPUP_CONF) &
287                     ~((portmask << ADM5120_DISMCSHIFT) & ADM5120_DISMCALL));
288         else
289                 adm5120_set_reg(ADM5120_CPUP_CONF,
290                     adm5120_get_reg(ADM5120_CPUP_CONF) |
291                     (portmask << ADM5120_DISMCSHIFT));
292 }
293
294 static void adm5120_write_mac(struct net_device *dev)
295 {
296         struct adm5120_sw *priv = netdev_priv(dev);
297         unsigned char *mac = dev->dev_addr;
298
299         adm5120_set_reg(ADM5120_MAC_WT1,
300             mac[2] | (mac[3]<<8) | (mac[4]<<16) | (mac[5]<<24));
301         adm5120_set_reg(ADM5120_MAC_WT0, (priv->port<<3) |
302             (mac[0]<<16) | (mac[1]<<24) | ADM5120_MAC_WRITE | ADM5120_VLAN_EN);
303
304         while (!(adm5120_get_reg(ADM5120_MAC_WT0) & ADM5120_MAC_WRITE_DONE));
305 }
306
307 static int adm5120_sw_set_mac_address(struct net_device *dev, void *p)
308 {
309         struct sockaddr *addr = p;
310
311         memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
312         adm5120_write_mac(dev);
313         return 0;
314 }
315
316 static int adm5120_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
317 {
318         int err;
319         struct adm5120_info info;
320         struct adm5120_sw *priv = netdev_priv(dev);
321
322         switch(cmd) {
323                 case SIOCGADMINFO:
324                         info.magic = 0x5120;
325                         info.ports = adm5120_nrdevs;
326                         info.vlan = priv->port;
327                         err = copy_to_user(rq->ifr_data, &info, sizeof(info));
328                         if (err)
329                                 return -EFAULT;
330                         break;
331                 case SIOCSMATRIX:
332                         if (!capable(CAP_NET_ADMIN))
333                                 return -EPERM;
334                         err = copy_from_user(vlan_matrix, rq->ifr_data,
335                             sizeof(vlan_matrix));
336                         if (err)
337                                 return -EFAULT;
338                         adm5120_set_vlan(vlan_matrix);
339                         break;
340                 case SIOCGMATRIX:
341                         err = copy_to_user(rq->ifr_data, vlan_matrix,
342                             sizeof(vlan_matrix));
343                         if (err)
344                                 return -EFAULT;
345                         break;
346                 default:
347                         return -EOPNOTSUPP;
348         }
349         return 0;
350 }
351
352 static void adm5120_dma_tx_init(struct adm5120_dma *dma, struct sk_buff **skb,
353     int num)
354 {
355         memset(dma, 0, sizeof(struct adm5120_dma)*num);
356         dma[num-1].data |= ADM5120_DMA_RINGEND;
357         memset(skb, 0, sizeof(struct skb*)*num);
358 }
359
360 static void adm5120_dma_rx_init(struct adm5120_dma *dma, struct sk_buff **skb,
361     int num)
362 {
363         int i;
364
365         memset(dma, 0, sizeof(struct adm5120_dma)*num);
366         for (i=0; i<num; i++) {
367                 skb[i] = dev_alloc_skb(ADM5120_DMA_RXSIZE+16);
368                 if (!skb[i]) {
369                         i=num;
370                         break;
371                 }
372                 skb_reserve(skb[i], 2);
373                 dma[i].data = ADM5120_DMA_ADDR(skb[i]->data) | ADM5120_DMA_OWN;
374                 dma[i].cntl = 0;
375                 dma[i].len = ADM5120_DMA_RXSIZE;
376                 dma[i].status = 0;
377         }
378         dma[i-1].data |= ADM5120_DMA_RINGEND;
379 }
380
381 static int __init adm5120_sw_init(void)
382 {
383         int i, err;
384         struct net_device *dev;
385
386         err = request_irq(SW_IRQ, adm5120_sw_irq, 0, "ethernet switch", NULL);
387         if (err)
388                 goto out;
389
390         /* MII port? */
391         if (adm5120_get_reg(ADM5120_CODE) & ADM5120_CODE_PQFP)
392                 adm5120_nrdevs = 5;
393         /* CFE based devices only have two enet ports */
394         else if (boot_loader_type == CFE)
395                 adm5120_nrdevs = 2
396         else
397                 adm5120_nrdevs = 6;
398
399         adm5120_set_reg(ADM5120_CPUP_CONF,
400             ADM5120_DISCCPUPORT | ADM5120_CRC_PADDING |
401             ADM5120_DISUNALL | ADM5120_DISMCALL);
402         adm5120_set_reg(ADM5120_PORT_CONF0, ADM5120_ENMC | ADM5120_ENBP);
403
404         adm5120_set_reg(ADM5120_PHY_CNTL2, adm5120_get_reg(ADM5120_PHY_CNTL2) |
405             ADM5120_AUTONEG | ADM5120_NORMAL | ADM5120_AUTOMDIX);
406         adm5120_set_reg(ADM5120_PHY_CNTL3, adm5120_get_reg(ADM5120_PHY_CNTL3) |
407             ADM5120_PHY_NTH);
408
409         adm5120_set_reg(ADM5120_INT_MASK, ADM5120_INTMASKALL);
410         adm5120_set_reg(ADM5120_INT_ST, ADM5120_INTMASKALL);
411
412         adm5120_dma_txh = (void *)KSEG1ADDR((u32)adm5120_dma_txh_v);
413         adm5120_dma_txl = (void *)KSEG1ADDR((u32)adm5120_dma_txl_v);
414         adm5120_dma_rxh = (void *)KSEG1ADDR((u32)adm5120_dma_rxh_v);
415         adm5120_dma_rxl = (void *)KSEG1ADDR((u32)adm5120_dma_rxl_v);
416
417         adm5120_dma_tx_init(adm5120_dma_txh, adm5120_skb_txh, ADM5120_DMA_TXH);
418         adm5120_dma_tx_init(adm5120_dma_txl, adm5120_skb_txl, ADM5120_DMA_TXL);
419         adm5120_dma_rx_init(adm5120_dma_rxh, adm5120_skb_rxh, ADM5120_DMA_RXH);
420         adm5120_dma_rx_init(adm5120_dma_rxl, adm5120_skb_rxl, ADM5120_DMA_RXL);
421         adm5120_set_reg(ADM5120_SEND_HBADDR, KSEG1ADDR(adm5120_dma_txh));
422         adm5120_set_reg(ADM5120_SEND_LBADDR, KSEG1ADDR(adm5120_dma_txl));
423         adm5120_set_reg(ADM5120_RECEIVE_HBADDR, KSEG1ADDR(adm5120_dma_rxh));
424         adm5120_set_reg(ADM5120_RECEIVE_LBADDR, KSEG1ADDR(adm5120_dma_rxl));
425
426         adm5120_set_vlan(vlan_matrix);
427         
428         for (i=0; i<adm5120_nrdevs; i++) {
429                 adm5120_devs[i] = alloc_etherdev(sizeof(struct adm5120_sw));
430                 if (!adm5120_devs[i]) {
431                         err = -ENOMEM;
432                         goto out_int;
433                 }
434                 
435                 dev = adm5120_devs[i];
436                 SET_MODULE_OWNER(dev);
437                 memset(netdev_priv(dev), 0, sizeof(struct adm5120_sw));
438                 ((struct adm5120_sw*)netdev_priv(dev))->port = i;
439                 dev->base_addr = SW_BASE;
440                 dev->irq = SW_IRQ;
441                 dev->open = adm5120_sw_open;
442                 dev->hard_start_xmit = adm5120_sw_tx;
443                 dev->stop = adm5120_sw_stop;
444                 dev->get_stats = adm5120_sw_stats;
445                 dev->set_multicast_list = adm5120_set_multicast_list;
446                 dev->do_ioctl = adm5120_do_ioctl;
447                 dev->tx_timeout = adm5120_tx_timeout;
448                 dev->watchdog_timeo = ETH_TX_TIMEOUT;
449                 dev->set_mac_address = adm5120_sw_set_mac_address;
450                 /* HACK alert!!!  In the original admtek driver it is asumed
451                    that you can read the MAC addressess from flash, but edimax
452                    decided to leave that space intentionally blank...
453                  */
454                 memcpy(dev->dev_addr, "\x00\x50\xfc\x11\x22\x01", 6);
455                 dev->dev_addr[5] += i;
456                 adm5120_write_mac(dev);
457                 
458                 if ((err = register_netdev(dev))) {
459                         free_netdev(dev);
460                         goto out_int;
461                 }
462                 printk(KERN_INFO "%s: ADM5120 switch port%d\n", dev->name, i);
463         }
464         adm5120_set_reg(ADM5120_CPUP_CONF,
465             ADM5120_CRC_PADDING | ADM5120_DISUNALL | ADM5120_DISMCALL);
466
467         return 0;
468
469 out_int:
470         /* Undo everything that did succeed */
471         for (; i; i--) {
472                 unregister_netdev(adm5120_devs[i-1]);
473                 free_netdev(adm5120_devs[i-1]);
474         }
475         free_irq(SW_IRQ, NULL);
476 out:
477         printk(KERN_ERR "ADM5120 Ethernet switch init failed\n");
478         return err;
479 }
480
481 static void __exit adm5120_sw_exit(void)
482 {
483         int i;
484
485         for (i = 0; i < adm5120_nrdevs; i++) {
486                 unregister_netdev(adm5120_devs[i]);
487                 free_netdev(adm5120_devs[i-1]);
488         }
489
490         free_irq(SW_IRQ, NULL);
491
492         for (i = 0; i < ADM5120_DMA_RXH; i++) {
493                 if (!adm5120_skb_rxh[i])
494                         break;
495                 kfree_skb(adm5120_skb_rxh[i]);
496         }
497         for (i = 0; i < ADM5120_DMA_RXL; i++) {
498                 if (!adm5120_skb_rxl[i])
499                         break;
500                 kfree_skb(adm5120_skb_rxl[i]);
501         }
502 }
503
504 module_init(adm5120_sw_init);
505 module_exit(adm5120_sw_exit);