Use the openwrt.org mirror, others are offline
[openwrt.git] / package / broadcom-57xx / src / bcmrobo.c
1 /*
2  * Broadcom BCM5325E/536x switch configuration module
3  *
4  * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * Based on:
17  *   Broadcom 53xx RoboSwitch device driver.
18  *
19  *   Copyright 2007, Broadcom Corporation
20  *   All Rights Reserved.
21  * 
22  *   THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
23  *   KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
24  *   SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
25  *   FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
26  */
27
28
29 #include <linux/autoconf.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <asm/uaccess.h>
33
34 #include <typedefs.h>
35 #include <osl.h>
36 #include <sbutils.h>
37 #include <sbconfig.h>
38 #include <bcmendian.h>
39 #include "bcmparams.h"
40 #include <bcmnvram.h>
41 #include <bcmdevs.h>
42 #include "bcmrobo.h"
43 #include "proto/ethernet.h"
44 #include <switch-core.h>
45
46 #define DRIVER_NAME             "bcm57xx"
47 #define DRIVER_VERSION  "0.1"
48
49 #ifndef GPIO_PIN_NOTDEFINED
50 #define GPIO_PIN_NOTDEFINED     0x20
51 #endif
52
53 #ifdef  BCMDBG
54 #define ET_ERROR(args)  printk args
55 #else   /* BCMDBG */
56 #define ET_ERROR(args)
57 #endif  /* BCMDBG */
58 #define ET_MSG(args)
59
60 /*
61  * Switch can be programmed through SPI interface, which
62  * has a rreg and a wreg functions to read from and write to
63  * registers.
64  */
65
66 /* MII access registers */
67 #define PSEUDO_PHYAD    0x1E    /* MII Pseudo PHY address */
68 #define REG_MII_PAGE    0x10    /* MII Page register */
69 #define REG_MII_ADDR    0x11    /* MII Address register */
70 #define REG_MII_DATA0   0x18    /* MII Data register 0 */
71 #define REG_MII_DATA1   0x19    /* MII Data register 1 */
72 #define REG_MII_DATA2   0x1a    /* MII Data register 2 */
73 #define REG_MII_DATA3   0x1b    /* MII Data register 3 */
74
75 /* Page numbers */
76 #define PAGE_CTRL       0x00    /* Control page */
77 #define PAGE_MMR        0x02    /* 5397 Management/Mirroring page */
78 #define PAGE_VTBL       0x05    /* ARL/VLAN Table access page */
79 #define PAGE_VLAN       0x34    /* VLAN page */
80
81 /* Control page registers */
82 #define REG_CTRL_PORT0  0x00    /* Port 0 traffic control register */
83 #define REG_CTRL_PORT1  0x01    /* Port 1 traffic control register */
84 #define REG_CTRL_PORT2  0x02    /* Port 2 traffic control register */
85 #define REG_CTRL_PORT3  0x03    /* Port 3 traffic control register */
86 #define REG_CTRL_PORT4  0x04    /* Port 4 traffic control register */
87 #define REG_CTRL_PORT5  0x05    /* Port 5 traffic control register */
88 #define REG_CTRL_PORT6  0x06    /* Port 6 traffic control register */
89 #define REG_CTRL_PORT7  0x07    /* Port 7 traffic control register */
90 #define REG_CTRL_MODE   0x0B    /* Switch Mode register */
91 #define REG_CTRL_MIIPO  0x0E    /* 5325: MII Port Override register */
92 #define REG_CTRL_SRST   0x79    /* Software reset control register */
93
94 #define REG_DEVICE_ID   0x30    /* 539x Device id: */
95 #define DEVID5325       0x25    /*  5325 (Not really be we fake it) */
96 #define DEVID5395       0x95    /*  5395 */
97 #define DEVID5397       0x97    /*  5397 */
98 #define DEVID5398       0x98    /*  5398 */
99
100 /* VLAN page registers */
101 #define REG_VLAN_CTRL0  0x00    /* VLAN Control 0 register */
102 #define REG_VLAN_CTRL1  0x01    /* VLAN Control 1 register */
103 #define REG_VLAN_CTRL4  0x04    /* VLAN Control 4 register */
104 #define REG_VLAN_CTRL5  0x05    /* VLAN Control 5 register */
105 #define REG_VLAN_ACCESS 0x06    /* VLAN Table Access register */
106 #define REG_VLAN_WRITE  0x08    /* VLAN Write register */
107 #define REG_VLAN_READ   0x0C    /* VLAN Read register */
108 #define REG_VLAN_PTAG0  0x10    /* VLAN Default Port Tag register - port 0 */
109 #define REG_VLAN_PTAG1  0x12    /* VLAN Default Port Tag register - port 1 */
110 #define REG_VLAN_PTAG2  0x14    /* VLAN Default Port Tag register - port 2 */
111 #define REG_VLAN_PTAG3  0x16    /* VLAN Default Port Tag register - port 3 */
112 #define REG_VLAN_PTAG4  0x18    /* VLAN Default Port Tag register - port 4 */
113 #define REG_VLAN_PTAG5  0x1a    /* VLAN Default Port Tag register - port 5 */
114 #define REG_VLAN_PTAG6  0x1c    /* VLAN Default Port Tag register - port 6 */
115 #define REG_VLAN_PTAG7  0x1e    /* VLAN Default Port Tag register - port 7 */
116 #define REG_VLAN_PTAG8  0x20    /* 539x: VLAN Default Port Tag register - IMP port */
117 #define REG_VLAN_PMAP   0x20    /* 5325: VLAN Priority Re-map register */
118
119 #define VLAN_NUMVLANS   16      /* # of VLANs */
120
121
122 /* ARL/VLAN Table Access page registers */
123 #define REG_VTBL_CTRL           0x00    /* ARL Read/Write Control */
124 #define REG_VTBL_MINDX          0x02    /* MAC Address Index */
125 #define REG_VTBL_VINDX          0x08    /* VID Table Index */
126 #define REG_VTBL_ARL_E0         0x10    /* ARL Entry 0 */
127 #define REG_VTBL_ARL_E1         0x18    /* ARL Entry 1 */
128 #define REG_VTBL_DAT_E0         0x18    /* ARL Table Data Entry 0 */
129 #define REG_VTBL_SCTRL          0x20    /* ARL Search Control */
130 #define REG_VTBL_SADDR          0x22    /* ARL Search Address */
131 #define REG_VTBL_SRES           0x24    /* ARL Search Result */
132 #define REG_VTBL_SREXT          0x2c    /* ARL Search Result */
133 #define REG_VTBL_VID_E0         0x30    /* VID Entry 0 */
134 #define REG_VTBL_VID_E1         0x32    /* VID Entry 1 */
135 #define REG_VTBL_PREG           0xFF    /* Page Register */
136 #define REG_VTBL_ACCESS         0x60    /* VLAN table access register */
137 #define REG_VTBL_INDX           0x61    /* VLAN table address index register */
138 #define REG_VTBL_ENTRY          0x63    /* VLAN table entry register */
139 #define REG_VTBL_ACCESS_5395    0x80    /* VLAN table access register */
140 #define REG_VTBL_INDX_5395      0x81    /* VLAN table address index register */
141 #define REG_VTBL_ENTRY_5395     0x83    /* VLAN table entry register */
142
143 /* SPI registers */
144 #define REG_SPI_PAGE    0xff    /* SPI Page register */
145
146 /* Access switch registers through GPIO/SPI */
147
148 /* Minimum timing constants */
149 #define SCK_EDGE_TIME   2       /* clock edge duration - 2us */
150 #define MOSI_SETUP_TIME 1       /* input setup duration - 1us */
151 #define SS_SETUP_TIME   1       /* select setup duration - 1us */
152
153 /* misc. constants */
154 #define SPI_MAX_RETRY   100
155
156 static int config_attach(robo_info_t *robo);
157 static void config_detach(robo_info_t *robo);
158
159 /* Enable GPIO access to the chip */
160 static void
161 gpio_enable(robo_info_t *robo)
162 {
163         /* Enable GPIO outputs with SCK and MOSI low, SS high */
164         sb_gpioout(robo->sbh, robo->ss | robo->sck | robo->mosi, robo->ss, GPIO_DRV_PRIORITY);
165         sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi,
166                      robo->ss | robo->sck | robo->mosi, GPIO_DRV_PRIORITY);
167 }
168
169 /* Disable GPIO access to the chip */
170 static void
171 gpio_disable(robo_info_t *robo)
172 {
173         /* Disable GPIO outputs with all their current values */
174         sb_gpioouten(robo->sbh, robo->ss | robo->sck | robo->mosi, 0, GPIO_DRV_PRIORITY);
175 }
176
177 /* Write a byte stream to the chip thru SPI */
178 static int
179 spi_write(robo_info_t *robo, uint8 *buf, uint len)
180 {
181         uint i;
182         uint8 mask;
183
184         /* Byte bang from LSB to MSB */
185         for (i = 0; i < len; i++) {
186                 /* Bit bang from MSB to LSB */
187                 for (mask = 0x80; mask; mask >>= 1) {
188                         /* Clock low */
189                         sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
190                         OSL_DELAY(SCK_EDGE_TIME);
191
192                         /* Sample on rising edge */
193                         if (mask & buf[i])
194                                 sb_gpioout(robo->sbh, robo->mosi, robo->mosi, GPIO_DRV_PRIORITY);
195                         else
196                                 sb_gpioout(robo->sbh, robo->mosi, 0, GPIO_DRV_PRIORITY);
197                         OSL_DELAY(MOSI_SETUP_TIME);
198
199                         /* Clock high */
200                         sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
201                         OSL_DELAY(SCK_EDGE_TIME);
202                 }
203         }
204
205         return 0;
206 }
207
208 /* Read a byte stream from the chip thru SPI */
209 static int
210 spi_read(robo_info_t *robo, uint8 *buf, uint len)
211 {
212         uint i, timeout;
213         uint8 rack, mask, byte;
214
215         /* Timeout after 100 tries without RACK */
216         for (i = 0, rack = 0, timeout = SPI_MAX_RETRY; i < len && timeout;) {
217                 /* Bit bang from MSB to LSB */
218                 for (mask = 0x80, byte = 0; mask; mask >>= 1) {
219                         /* Clock low */
220                         sb_gpioout(robo->sbh, robo->sck, 0, GPIO_DRV_PRIORITY);
221                         OSL_DELAY(SCK_EDGE_TIME);
222
223                         /* Sample on falling edge */
224                         if (sb_gpioin(robo->sbh) & robo->miso)
225                                 byte |= mask;
226
227                         /* Clock high */
228                         sb_gpioout(robo->sbh, robo->sck, robo->sck, GPIO_DRV_PRIORITY);
229                         OSL_DELAY(SCK_EDGE_TIME);
230                 }
231                 /* RACK when bit 0 is high */
232                 if (!rack) {
233                         rack = (byte & 1);
234                         timeout--;
235                         continue;
236                 }
237                 /* Byte bang from LSB to MSB */
238                 buf[i] = byte;
239                 i++;
240         }
241
242         if (timeout == 0) {
243                 ET_ERROR(("spi_read: timeout"));
244                 return -1;
245         }
246
247         return 0;
248 }
249
250 /* Enable/disable SPI access */
251 static void
252 spi_select(robo_info_t *robo, uint8 spi)
253 {
254         if (spi) {
255                 /* Enable SPI access */
256                 sb_gpioout(robo->sbh, robo->ss, 0, GPIO_DRV_PRIORITY);
257         } else {
258                 /* Disable SPI access */
259                 sb_gpioout(robo->sbh, robo->ss, robo->ss, GPIO_DRV_PRIORITY);
260         }
261         OSL_DELAY(SS_SETUP_TIME);
262 }
263
264
265 /* Select chip and page */
266 static void
267 spi_goto(robo_info_t *robo, uint8 page)
268 {
269         uint8 reg8 = REG_SPI_PAGE;      /* page select register */
270         uint8 cmd8;
271
272         /* Issue the command only when we are on a different page */
273         if (robo->page == page)
274                 return;
275
276         robo->page = page;
277
278         /* Enable SPI access */
279         spi_select(robo, 1);
280
281         /* Select new page with CID 0 */
282         cmd8 = ((6 << 4) |              /* normal SPI */
283                 1);                     /* write */
284         spi_write(robo, &cmd8, 1);
285         spi_write(robo, &reg8, 1);
286         spi_write(robo, &page, 1);
287
288         /* Disable SPI access */
289         spi_select(robo, 0);
290 }
291
292 /* Write register thru SPI */
293 static int
294 spi_wreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
295 {
296         int status = 0;
297         uint8 cmd8;
298         union {
299                 uint8 val8;
300                 uint16 val16;
301                 uint32 val32;
302         } bytes;
303
304         /* validate value length and buffer address */
305         ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
306                (len == 4 && !((int)val & 3)));
307
308         /* Select chip and page */
309         spi_goto(robo, page);
310
311         /* Enable SPI access */
312         spi_select(robo, 1);
313
314         /* Write with CID 0 */
315         cmd8 = ((6 << 4) |              /* normal SPI */
316                 1);                     /* write */
317         spi_write(robo, &cmd8, 1);
318         spi_write(robo, &addr, 1);
319         switch (len) {
320         case 1:
321                 bytes.val8 = *(uint8 *)val;
322                 break;
323         case 2:
324                 bytes.val16 = htol16(*(uint16 *)val);
325                 break;
326         case 4:
327                 bytes.val32 = htol32(*(uint32 *)val);
328                 break;
329         }
330         spi_write(robo, (uint8 *)val, len);
331
332         ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, addr,
333                 *(uint16 *)val, len));
334         /* Disable SPI access */
335         spi_select(robo, 0);
336         return status;
337 }
338
339 /* Read register thru SPI in fast SPI mode */
340 static int
341 spi_rreg(robo_info_t *robo, uint8 page, uint8 addr, void *val, int len)
342 {
343         int status = 0;
344         uint8 cmd8;
345         union {
346                 uint8 val8;
347                 uint16 val16;
348                 uint32 val32;
349         } bytes;
350
351         /* validate value length and buffer address */
352         ASSERT(len == 1 || (len == 2 && !((int)val & 1)) ||
353                (len == 4 && !((int)val & 3)));
354
355         /* Select chip and page */
356         spi_goto(robo, page);
357
358         /* Enable SPI access */
359         spi_select(robo, 1);
360
361         /* Fast SPI read with CID 0 and byte offset 0 */
362         cmd8 = (1 << 4);                /* fast SPI */
363         spi_write(robo, &cmd8, 1);
364         spi_write(robo, &addr, 1);
365         status = spi_read(robo, (uint8 *)&bytes, len);
366         switch (len) {
367         case 1:
368                 *(uint8 *)val = bytes.val8;
369                 break;
370         case 2:
371                 *(uint16 *)val = ltoh16(bytes.val16);
372                 break;
373         case 4:
374                 *(uint32 *)val = ltoh32(bytes.val32);
375                 break;
376         }
377
378         ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, addr,
379                 *(uint16 *)val, len));
380
381         /* Disable SPI access */
382         spi_select(robo, 0);
383         return status;
384 }
385
386 /* SPI/gpio interface functions */
387 static dev_ops_t spigpio = {
388         gpio_enable,
389         gpio_disable,
390         spi_wreg,
391         spi_rreg,
392         "SPI (GPIO)"
393 };
394
395
396 /* Access switch registers through MII (MDC/MDIO) */
397
398 #define MII_MAX_RETRY   100
399
400 /* Write register thru MDC/MDIO */
401 static  int
402 mii_wreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
403 {
404         uint16 cmd16, val16,val48[3];
405         void *h = robo->h;
406     uint32 val64[2];
407         memset(val48,0,6);
408         memset(val64,0,8);
409         int i;
410         uint8 *ptr = (uint8 *)val;
411
412         /* validate value length and buffer address */
413         ASSERT(len == 1 || len == 6 || len == 8 ||
414                ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
415
416         ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__, page, reg,
417                   *(uint16 *)val, len));
418
419         /* set page number - MII register 0x10 */
420         if (robo->page != page) {
421                 cmd16 = ((page << 8) |          /* page number */
422                          1);                    /* mdc/mdio access enable */
423                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
424                 robo->page = page;
425         }
426
427         switch (len) {
428         case 8:
429                 val16 = ptr[7];
430                 val16 = ((val16 << 8) | ptr[6]);
431                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA3, val16);
432                 /* FALLTHRU */
433
434         case 6:
435                 val16 = ptr[5];
436                 val16 = ((val16 << 8) | ptr[4]);
437                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA2, val16);
438                 val16 = ptr[3];
439                 val16 = ((val16 << 8) | ptr[2]);
440                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
441                 val16 = ptr[1];
442                 val16 = ((val16 << 8) | ptr[0]);
443                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
444                 break;
445
446         case 4:
447                 val16 = (uint16)((*(uint32 *)val) >> 16);
448                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA1, val16);
449                 val16 = (uint16)(*(uint32 *)val);
450                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
451                 break;
452
453         case 2:
454                 val16 = *(uint16 *)val;
455                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
456                 break;
457
458         case 1:
459                 val16 = *(uint8 *)val;
460                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_DATA0, val16);
461                 break;
462         }
463
464         /* set register address - MII register 0x11 */
465         cmd16 = ((reg << 8) |           /* register address */
466                  1);            /* opcode write */
467         robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
468
469         /* is operation finished? */
470         for (i = MII_MAX_RETRY; i > 0; i --) {
471                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
472                 if ((val16 & 3) == 0)
473                         break;
474         }
475
476         /* timed out */
477         if (!i) {
478                 ET_ERROR(("mii_wreg: timeout"));
479                 return -1;
480         }
481         return 0;
482 }
483
484 /* Read register thru MDC/MDIO */
485 static  int
486 mii_rreg(robo_info_t *robo, uint8 page, uint8 reg, void *val, int len)
487 {
488         uint16 cmd16, val16;
489         void *h = robo->h;
490         int i;
491         uint8 *ptr = (uint8 *)val;
492
493         /* validate value length and buffer address */
494         ASSERT(len == 1 || len == 6 || len == 8 ||
495                ((len == 2) && !((int)val & 1)) || ((len == 4) && !((int)val & 3)));
496
497         /* set page number - MII register 0x10 */
498         if (robo->page != page) {
499                 cmd16 = ((page << 8) |          /* page number */
500                          1);                    /* mdc/mdio access enable */
501                 robo->miiwr(h, PSEUDO_PHYAD, REG_MII_PAGE, cmd16);
502                 robo->page = page;
503         }
504
505         /* set register address - MII register 0x11 */
506         cmd16 = ((reg << 8) |           /* register address */
507                  2);                    /* opcode read */
508         robo->miiwr(h, PSEUDO_PHYAD, REG_MII_ADDR, cmd16);
509
510         /* is operation finished? */
511         for (i = MII_MAX_RETRY; i > 0; i --) {
512                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_ADDR);
513                 if ((val16 & 3) == 0)
514                         break;
515         }
516         /* timed out */
517         if (!i) {
518                 ET_ERROR(("mii_rreg: timeout"));
519                 return -1;
520         }
521
522         ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__, page, reg, val16, len));
523
524         switch (len) {
525         case 8:
526                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA3);
527                 ptr[7] = (val16 >> 8);
528                 ptr[6] = (val16 & 0xff);
529                 /* FALLTHRU */
530
531         case 6:
532                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA2);
533                 ptr[5] = (val16 >> 8);
534                 ptr[4] = (val16 & 0xff);
535                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
536                 ptr[3] = (val16 >> 8);
537                 ptr[2] = (val16 & 0xff);
538                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
539                 ptr[1] = (val16 >> 8);
540                 ptr[0] = (val16 & 0xff);
541                 break;
542
543         case 4:
544                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA1);
545                 *(uint32 *)val = (((uint32)val16) << 16);
546                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
547                 *(uint32 *)val |= val16;
548                 break;
549
550         case 2:
551                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
552                 *(uint16 *)val = val16;
553                 break;
554         case 1:
555                 val16 = robo->miird(h, PSEUDO_PHYAD, REG_MII_DATA0);
556                 *(uint8 *)val = (uint8)(val16 & 0xff);
557                 break;
558         }
559
560         return 0;
561 }
562
563 /* MII interface functions */
564 static dev_ops_t mdcmdio = {
565         NULL,
566         NULL,
567         mii_wreg,
568         mii_rreg,
569         "MII (MDC/MDIO)"
570 };
571
572 /* High level switch configuration functions. */
573
574 static int
575 findmatch(char *string, char *name)
576 {
577         uint len;
578         char *c;
579
580         len = strlen(name);
581         /* CSTYLED */
582         while ((c = strchr(string, ',')) != NULL) {
583                 if (len == (uint)(c - string) && !strncmp(string, name, len))
584                         return 1;
585                 string = c + 1;
586         }
587
588         return (!strcmp(string, name));
589 }
590
591 static uint
592 getgpiopin(char *vars, char *pin_name, uint def_pin)
593 {
594         char name[] = "gpioXXXX";
595         char *val;
596         uint pin;
597
598         /* Go thru all possibilities till a match in pin name */
599         for (pin = 0; pin < GPIO_NUMPINS; pin ++) {
600                 snprintf(name, sizeof(name), "gpio%d", pin);
601                 val = getvar(vars, name);
602                 if (val && findmatch(val, pin_name))
603                         return pin;
604         }
605
606         if (def_pin != GPIO_PIN_NOTDEFINED) {
607                 /* make sure the default pin is not used by someone else */
608                 snprintf(name, sizeof(name), "gpio%d", def_pin);
609                 if (getvar(vars, name)) {
610                         def_pin =  GPIO_PIN_NOTDEFINED;
611                 }
612         }
613
614         return def_pin;
615 }
616
617
618 /* Port flags */
619 #define FLAG_TAGGED     't'     /* output tagged (external ports only) */
620 #define FLAG_UNTAG      'u'     /* input & output untagged (CPU port only, for OS (linux, ...) */
621 #define FLAG_LAN        '*'     /* input & output untagged (CPU port only, for CFE */
622
623 /* port descriptor */
624 typedef struct {
625         uint32 untag;   /* untag enable bit (Page 0x05 Address 0x63-0x66 Bit[17:9]) */
626         uint32 member;  /* vlan member bit (Page 0x05 Address 0x63-0x66 Bit[7:0]) */
627         uint8 ptagr;    /* port tag register address (Page 0x34 Address 0x10-0x1F) */
628         uint8 cpu;      /* is this cpu port? */
629 } pdesc_t;
630
631 pdesc_t pdesc97[] = {
632         /* 5395/5397/5398 is 0 ~ 7.  port 8 is IMP port. */
633         /* port 0 */ {1 << 9, 1 << 0, REG_VLAN_PTAG0, 0},
634         /* port 1 */ {1 << 10, 1 << 1, REG_VLAN_PTAG1, 0},
635         /* port 2 */ {1 << 11, 1 << 2, REG_VLAN_PTAG2, 0},
636         /* port 3 */ {1 << 12, 1 << 3, REG_VLAN_PTAG3, 0},
637         /* port 4 */ {1 << 13, 1 << 4, REG_VLAN_PTAG4, 0},
638         /* port 5 */ {1 << 14, 1 << 5, REG_VLAN_PTAG5, 0},
639         /* port 6 */ {1 << 15, 1 << 6, REG_VLAN_PTAG6, 0},
640         /* port 7 */ {1 << 16, 1 << 7, REG_VLAN_PTAG7, 0},
641         /* mii port */ {1 << 17, 1 << 8, REG_VLAN_PTAG8, 1},
642 };
643
644 pdesc_t pdesc25[] = {
645         /* port 0 */ {1 << 6, 1 << 0, REG_VLAN_PTAG0, 0},
646         /* port 1 */ {1 << 7, 1 << 1, REG_VLAN_PTAG1, 0},
647         /* port 2 */ {1 << 8, 1 << 2, REG_VLAN_PTAG2, 0},
648         /* port 3 */ {1 << 9, 1 << 3, REG_VLAN_PTAG3, 0},
649         /* port 4 */ {1 << 10, 1 << 4, REG_VLAN_PTAG4, 0},
650         /* mii port */ {1 << 11, 1 << 5, REG_VLAN_PTAG5, 1},
651 };
652
653
654 #define to_robo(driver) ((robo_info_t *) ((switch_driver *) driver)->priv)
655 #define ROBO_START(driver) \
656         do { \
657                 robo_info_t *robo = to_robo(driver); \
658                 if (robo->ops->enable_mgmtif) \
659                         robo->ops->enable_mgmtif(robo)
660
661 #define ROBO_END(driver) \
662                 if (robo->ops->disable_mgmtif) \
663                         robo->ops->disable_mgmtif(robo); \
664         } while (0)
665
666 int
667 bcm_robo_reset(robo_info_t *robo)
668 {
669         int i, max_port_ind;
670         uint8 val8;
671         uint16 val16;
672         uint32 val32;
673         pdesc_t *pdesc;
674         int pdescsz;
675
676 /* printk(KERN_WARNING "bcmrobo.c: bcm_robo_reset\n"); */
677
678         if (robo->ops->enable_mgmtif)
679                 robo->ops->enable_mgmtif(robo);
680
681         /* setup global vlan configuration, FIXME: necessary? */
682         /* VLAN Control 0 Register (Page 0x34, Address 0) */
683         val8 = ((1 << 7) |              /* enable 802.1Q VLAN */
684                 (3 << 5));              /* individual VLAN learning mode */
685         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
686
687         /* VLAN Control 1 Register (Page 0x34, Address 1) */
688         robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
689         val8 |= ((1 << 2) |             /* enable RSV multicast V Fwdmap */
690                 (1 << 3));              /* enable RSV multicast V Untagmap */
691         if (robo->devid == DEVID5325)
692                 val8 |= (1 << 1);       /* enable RSV multicast V Tagging */
693         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
694
695         bcm_robo_set_macaddr(robo, NULL);
696
697         if (robo->devid == DEVID5325) {
698                 /* VLAN Control 4 Register (Page 0x34, Address 4) */
699                 val8 = (1 << 6);                /* drop frame with VID violation */
700                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
701
702                 /* VLAN Control 5 Register (Page 0x34, Address 5) */
703                 val8 = (1 << 3);                /* drop frame when miss V table */
704                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
705
706                 pdesc = pdesc25;
707                 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
708         } else {
709                 pdesc = pdesc97;
710                 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
711         }
712
713         if (robo->devid == DEVID5325) {
714                 /* setup priority mapping - applies to tagged ingress frames */
715                 /* Priority Re-map Register (Page 0x34, Address 0x20-0x23) */
716                 /* FIXME: un-hardcode */
717                 val32 = ((0 << 0) |     /* 0 -> 0 */
718                          (1 << 3) |     /* 1 -> 1 */
719                          (2 << 6) |     /* 2 -> 2 */
720                          (3 << 9) |     /* 3 -> 3 */
721                          (4 << 12) |    /* 4 -> 4 */
722                          (5 << 15) |    /* 5 -> 5 */
723                          (6 << 18) |    /* 6 -> 6 */
724                          (7 << 21));    /* 7 -> 7 */
725                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_PMAP, &val32, sizeof(val32));
726         }
727
728         /* Set unmanaged mode */
729         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
730         val8 &= (~(1 << 0));
731         robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
732
733         /* No spanning tree for unmanaged mode */
734         val8 = 0;
735         max_port_ind = ((robo->devid == DEVID5398) ? REG_CTRL_PORT7 : REG_CTRL_PORT4);
736         for (i = REG_CTRL_PORT0; i <= max_port_ind; i++) {
737                 robo->ops->write_reg(robo, PAGE_CTRL, i, &val8, sizeof(val8));
738         }
739
740         /* WAN port LED */
741         val16 = 0x1f;
742         robo->ops->write_reg(robo, PAGE_CTRL, 0x16, &val16, 2);
743
744         if (robo->ops->enable_mgmtif)
745                 robo->ops->disable_mgmtif(robo);
746
747         return 0;
748 }
749
750 /* Get access to the RoboSwitch */
751 robo_info_t *
752 bcm_robo_attach(sb_t *sbh, void *h, char *name, char *vars, miird_f miird, miiwr_f miiwr)
753 {
754         robo_info_t *robo;
755         uint32 reset, idx;
756         uint8 val8;
757         uint16 val16;
758
759         /* Allocate and init private state */
760         if (!(robo = MALLOC(sb_osh(sbh), sizeof(robo_info_t)))) {
761                 ET_ERROR(("robo_attach: out of memory, malloced %d bytes", MALLOCED(sb_osh(sbh))));
762                 return NULL;
763         }
764         bzero(robo, sizeof(robo_info_t));
765
766         robo->h = h;
767         robo->sbh = sbh;
768         robo->vars = vars;
769         robo->miird = miird;
770         robo->miiwr = miiwr;
771         robo->page = -1;
772         robo->name = name;
773
774         /* Trigger external reset by nvram variable existance */
775         if ((reset = getgpiopin(robo->vars, "robo_reset", GPIO_PIN_NOTDEFINED)) !=
776             GPIO_PIN_NOTDEFINED) {
777                 /*
778                  * Reset sequence: RESET low(50ms)->high(20ms)
779                  *
780                  * We have to perform a full sequence for we don't know how long
781                  * it has been from power on till now.
782                  */
783                 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__, reset));
784                 reset = 1 << reset;
785
786                 /* Keep RESET low for 50 ms */
787                 sb_gpioout(robo->sbh, reset, 0, GPIO_DRV_PRIORITY);
788                 sb_gpioouten(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
789                 bcm_mdelay(50);
790
791                 if (robo->devid == DEVID5395)
792                         nvram_set("switch_type", "BCM5395");
793                 else if(robo->devid == DEVID5397)
794                         nvram_set("switch_type", "BCM5397");
795                 else
796                         nvram_set("switch_type", "unknown");
797
798                 /* Keep RESET high for at least 20 ms */
799                 sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
800                 bcm_mdelay(20);
801         } else {
802                 /* In case we need it */
803                 idx = sb_coreidx(robo->sbh);
804
805                 if (sb_setcore(robo->sbh, SB_ROBO, 0)) {
806                         /* If we have an internal robo core, reset it using sb_core_reset */
807                         ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
808                         sb_core_reset(robo->sbh, 0, 0);
809                 }
810
811                 sb_setcoreidx(robo->sbh, idx);
812         }
813
814         if (miird && miiwr) {
815                 uint16 tmp;
816                 int rc, retry_count = 0;
817
818                 /* Read the PHY ID */
819                 tmp = miird(h, PSEUDO_PHYAD, 2);
820                 if (tmp != 0xffff) {
821                         do {
822                                 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
823                                                           &robo->devid, sizeof(uint16));
824                                 if (rc != 0)
825                                         break;
826                                 retry_count++;
827                         } while ((robo->devid == 0) && (retry_count < 10));
828
829                         ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
830                                 rc ? "un" : "", robo->devid));
831                         ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
832                         robo->ops = &mdcmdio;
833                         if ((rc != 0) || (robo->devid == 0)) {
834                                 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
835                                 robo->devid = DEVID5325;
836                         }
837                         ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
838                 }
839         }
840
841         if ((robo->devid == DEVID5395) ||
842             (robo->devid == DEVID5397) ||
843             (robo->devid == DEVID5398)) {
844                 uint8 srst_ctrl;
845
846                 /* If it is a 539x switch, use the soft reset register */
847                 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
848
849                 /* Reset the 539x switch core and register file */
850                 srst_ctrl = 0x83;
851                 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
852
853                 bcm_mdelay(500);
854
855                 srst_ctrl = 0x00;
856                 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
857         }
858
859         if (!robo->ops) {
860                 int mosi, miso, ss, sck;
861
862                 robo->ops = &spigpio;
863                 robo->devid = DEVID5325;
864
865                 /* Init GPIO mapping. Default 2, 3, 4, 5 */
866                 ss = getgpiopin(vars, "robo_ss", 2);
867                 if (ss == GPIO_PIN_NOTDEFINED) {
868                         ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
869                         goto error;
870                 }
871                 robo->ss = 1 << ss;
872                 sck = getgpiopin(vars, "robo_sck", 3);
873                 if (sck == GPIO_PIN_NOTDEFINED) {
874                         ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
875                         goto error;
876                 }
877                 robo->sck = 1 << sck;
878                 mosi = getgpiopin(vars, "robo_mosi", 4);
879                 if (mosi == GPIO_PIN_NOTDEFINED) {
880                         ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
881                         goto error;
882                 }
883                 robo->mosi = 1 << mosi;
884                 miso = getgpiopin(vars, "robo_miso", 5);
885                 if (miso == GPIO_PIN_NOTDEFINED) {
886                         ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
887                         goto error;
888                 }
889                 robo->miso = 1 << miso;
890                 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
891                         ss, sck, mosi, miso));
892         }
893
894         /* sanity check */
895         ASSERT(robo->ops);
896         ASSERT(robo->ops->write_reg);
897         ASSERT(robo->ops->read_reg);
898         ASSERT((robo->devid == DEVID5325) ||
899                (robo->devid == DEVID5395) ||
900                (robo->devid == DEVID5397) ||
901                (robo->devid == DEVID5398));
902
903         bcm_robo_reset(robo);
904         config_attach(robo);
905
906         return robo;
907
908 error:
909         MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
910         return NULL;
911 }
912
913 /* Release access to the RoboSwitch */
914 void
915 bcm_robo_detach(robo_info_t *robo)
916 {
917         config_detach(robo);
918         MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
919 }
920
921 /* Enable the device and set it to a known good state */
922 int
923 bcm_robo_enable_device(robo_info_t *robo)
924 {
925         uint8 reg_offset, reg_val;
926         int ret = 0;
927
928         /* Enable management interface access */
929         if (robo->ops->enable_mgmtif)
930                 robo->ops->enable_mgmtif(robo);
931
932         if (robo->devid == DEVID5398) {
933                 /* Disable unused ports: port 6 and 7 */
934                 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
935                         /* Set bits [1:0] to disable RX and TX */
936                         reg_val = 0x03;
937                         robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
938                                              sizeof(reg_val));
939                 }
940         }
941
942         if (robo->devid == DEVID5325) {
943                 /* Must put the switch into Reverse MII mode! */
944
945                 /* MII port state override (page 0 register 14) */
946                 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
947
948                 /* Bit 4 enables reverse MII mode */
949                 if (!(reg_val & (1 << 4))) {
950                         /* Enable RvMII */
951                         reg_val |= (1 << 4);
952                         robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
953                                              sizeof(reg_val));
954
955                         /* Read back */
956                         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
957                                             sizeof(reg_val));
958                         if (!(reg_val & (1 << 4))) {
959                                 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
960                                 ret = -1;
961                         }
962                 }
963         }
964
965         /* Disable management interface access */
966         if (robo->ops->disable_mgmtif)
967                 robo->ops->disable_mgmtif(robo);
968
969         return ret;
970 }
971
972
973 void bcm_robo_set_macaddr(robo_info_t *robo, char *mac_addr)
974 {
975         uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
976
977         if (mac_addr != NULL)
978                 memcpy(robo->macaddr, mac_addr, 6);
979
980         mac_addr = robo->macaddr;
981
982         /* setup mac address */
983         arl_entry[0] = mac_addr[5];
984         arl_entry[1] = mac_addr[4];
985         arl_entry[2] = mac_addr[3];
986         arl_entry[3] = mac_addr[2];
987         arl_entry[4] = mac_addr[1];
988         arl_entry[5] = mac_addr[0];
989
990         if (robo->devid == DEVID5325) {
991                 /* Init the entry 1 of the bin */
992                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
993                                      arl_entry1, sizeof(arl_entry1));
994                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
995                                      arl_entry1, 1);
996
997                 /* Init the entry 0 of the bin */
998                 arl_entry[6] = 0x8;             /* Port Id: MII */
999                 arl_entry[7] = 0xc0;    /* Static Entry, Valid */
1000
1001                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1002                                      arl_entry, sizeof(arl_entry));
1003                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1004                                      arl_entry, ETHER_ADDR_LEN);
1005
1006         } else {
1007                 /* Initialize the MAC Addr Index Register */
1008                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1009                                      arl_entry, ETHER_ADDR_LEN);
1010         }
1011 }
1012
1013 static int handle_reset(void *driver, char *buf, int nr)
1014 {
1015         ROBO_START(driver);
1016         bcm_robo_reset(robo);
1017         ROBO_END(driver);
1018
1019         return 0;
1020 }
1021
1022
1023 static int handle_enable_read(void *driver, char *buf, int nr)
1024 {
1025         int ret;
1026         uint8 val8;
1027
1028         ROBO_START(driver);
1029         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1030         ret = sprintf(buf, "%d\n", !!(val8 & (1 << 1)));
1031         ROBO_END(driver);
1032
1033         return ret;
1034 }
1035
1036 static int handle_enable_write(void *driver, char *buf, int nr)
1037 {
1038         uint8 val8;
1039
1040 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_write\n"); */
1041
1042         ROBO_START(driver);
1043         robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1044         val8 &= ~(1 << 1);
1045         val8 |= ((buf[0] == '1') << 1);
1046         robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1047         ROBO_END(driver);
1048
1049         return 0;
1050 }
1051
1052 static int handle_enable_vlan_read(void *driver, char *buf, int nr)
1053 {
1054         uint8 val8;
1055
1056         ROBO_START(driver);
1057         robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1058         ROBO_END(driver);
1059
1060         return sprintf(buf, "%d\n", (((val8 & (1 << 7)) == (1 << 7)) ? 1 : 0));
1061 }
1062 static int handle_enable_vlan_write(void *driver, char *buf, int nr)
1063 {
1064         int disable = ((buf[0] != '1') ? 1 : 0);
1065
1066         uint8 val8;
1067         uint16 val16;
1068         pdesc_t *pdesc;
1069         int pdescsz;
1070         uint16 vid;
1071         uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
1072
1073 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_vlan_write\n"); */
1074
1075         ROBO_START(driver);
1076
1077         /* setup global vlan configuration */
1078         /* VLAN Control 0 Register (Page 0x34, Address 0) */
1079         val8 = disable ? 0 : 
1080                 ((1 << 7) |             /* enable/disable 802.1Q VLAN */
1081                 (3 << 5));              /* individual VLAN learning mode */
1082         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1083
1084         /* VLAN Control 1 Register (Page 0x34, Address 1) */
1085         val8 = disable ? 0 : 
1086                 ((1 << 2) |             /* enable/disable RSV multicast V Fwdmap */
1087                 (1 << 3));              /* enable/disable RSV multicast V Untagmap */
1088         if (robo->devid == DEVID5325)
1089                 val8 |= disable ? 0 : (1 << 1);         /* enable/disable RSV multicast V Tagging */
1090         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1091
1092         if ( disable == 0 ) {           /* FIXME: ok to stop here when disabling? */
1093                 arl_entry[0] = robo->macaddr[5];
1094                 arl_entry[1] = robo->macaddr[4];
1095                 arl_entry[2] = robo->macaddr[3];
1096                 arl_entry[3] = robo->macaddr[2];
1097                 arl_entry[4] = robo->macaddr[1];
1098                 arl_entry[5] = robo->macaddr[0];
1099
1100                 if (robo->devid == DEVID5325) {
1101                         /* Init the entry 1 of the bin */
1102                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
1103                                              arl_entry1, sizeof(arl_entry1));
1104                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
1105                                              arl_entry1, 1);
1106
1107                         /* Init the entry 0 of the bin */
1108                         arl_entry[6] = 0x8;             /* Port Id: MII */
1109                         arl_entry[7] = 0xc0;    /* Static Entry, Valid */
1110
1111                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1112                                              arl_entry, sizeof(arl_entry));
1113                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1114                                              arl_entry, ETHER_ADDR_LEN);
1115
1116                         /* VLAN Control 4 Register (Page 0x34, Address 4) */
1117                         val8 = (1 << 6);                /* drop frame with VID violation */
1118                         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1119
1120                         /* VLAN Control 5 Register (Page 0x34, Address 5) */
1121                         val8 = (1 << 3);                /* drop frame when miss V table */
1122                         robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1123
1124                         pdesc = pdesc25;
1125                         pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1126                 } else {
1127                         /* Initialize the MAC Addr Index Register */
1128                         robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1129                                              arl_entry, ETHER_ADDR_LEN);
1130
1131                         pdesc = pdesc97;
1132                         pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1133                 }
1134
1135                 /* setup each vlan. max. 16 vlans. */
1136                 /* force vlan id to be equal to vlan number */
1137                 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1138
1139                         /* Add static ARL entries */
1140                         if (robo->devid == DEVID5325) {
1141                                 val8 = vid;
1142                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
1143                                                      &val8, sizeof(val8));
1144                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1145                                                      &val8, sizeof(val8));
1146
1147                                 /* Write the entry */
1148                                 val8 = 0x80;
1149                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1150                                                      &val8, sizeof(val8));
1151                                 /* Wait for write to complete */
1152                                 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1153                                          &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1154                                          100 /* usec */);
1155                         } else {
1156                                 /* Set the VLAN Id in VLAN ID Index Register */
1157                                 val8 = vid;
1158                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1159                                                      &val8, sizeof(val8));
1160
1161                                 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1162                                  * Register.
1163                                  */
1164                                 arl_entry[6] = vid;
1165                                 arl_entry[7] = 0x0;
1166                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1167                                                      arl_entry, sizeof(arl_entry));
1168
1169                                 /* Set the Static bit , Valid bit and Port ID fields in
1170                                  * ARL Table Data Entry 0 Register
1171                                  */
1172                                 val16 = 0xc008;
1173                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
1174                                                      &val16, sizeof(val16));
1175
1176                                 /* Clear the ARL_R/W bit and set the START/DONE bit in
1177                                  * the ARL Read/Write Control Register.
1178                                  */
1179                                 val8 = 0x80;
1180                                 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1181                                                      &val8, sizeof(val8));
1182                                 /* Wait for write to complete */
1183                                 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1184                                          &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1185                                          100 /* usec */);
1186                         }
1187                 }
1188         }
1189
1190         ROBO_END(driver);
1191         return 0;
1192 }
1193
1194 static int handle_vlan_port_read(void *driver, char *buf, int nr)
1195 {
1196         /* FIXME: yeah, some work is missing here */
1197         return sprintf(buf, "bcmrobo.c: handle_vlan_port_read unimplimented\n");
1198 }
1199
1200 static int handle_vlan_port_write(void *driver, char *buf, int nr)
1201 {
1202
1203         switch_driver *d = (switch_driver *) driver;
1204         switch_vlan_config *c = switch_parse_vlan(d, buf);
1205
1206         uint8 val8;
1207         uint16 val16;
1208         uint32 val32;
1209         int j;
1210         pdesc_t *pdesc;
1211         int pdescsz;
1212
1213 /* printk(KERN_WARNING "bcmrobo.c: handle_vlan_port_write, nr %d\n", nr); */
1214
1215         if (c == NULL)
1216                 return -EINVAL;
1217
1218         ROBO_START(driver);
1219
1220         if (robo->devid == DEVID5325) {
1221                 pdesc = pdesc25;
1222                 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1223         } else {
1224                 pdesc = pdesc97;
1225                 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1226         }
1227
1228
1229         for (j = 0; j < d->ports; j++) {
1230                 if ((c->untag | c->pvid) & (1 << j))
1231                         if ((j != d->cpuport) || (c->untag & (1 << j))) {
1232
1233                                 /* change default vlan tag */
1234
1235 /* printk(KERN_WARNING "bcmrobo.c: set default vlan tag, port %d -> vlan %d\n", j, nr); */
1236
1237                                 val16 = ((0 << 13) |            /* priority - always 0 */
1238                                         nr);                    /* vlan id */
1239                                 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[j].ptagr, &val16, sizeof(val16));
1240                         }
1241         }
1242
1243
1244         if (robo->devid == DEVID5325) {
1245                 val32 = ((c->untag << 6) |              /* untag enable */
1246                          c->port);                      /* vlan members */
1247                 val32 |= ((1 << 20) |           /* valid write */
1248                           ((nr >> 4) << 12));  /* vlan id bit[11:4] */
1249                 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1250                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1251                                      sizeof(val32));
1252                 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1253                 val16 = ((1 << 13) |    /* start command */
1254                          (1 << 12) |    /* write state */
1255                          nr);          /* vlan id */
1256                 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1257                                      sizeof(val16));
1258         } else {
1259                 uint8 vtble, vtbli, vtbla;
1260                 val32 = ((c->untag << 9) |              /* untag enable */
1261                          c->port);                      /* vlan members */
1262
1263                 if (robo->devid == DEVID5395) {
1264                         vtble = REG_VTBL_ENTRY_5395;
1265                         vtbli = REG_VTBL_INDX_5395;
1266                         vtbla = REG_VTBL_ACCESS_5395;
1267                 } else {
1268                         vtble = REG_VTBL_ENTRY;
1269                         vtbli = REG_VTBL_INDX;
1270                         vtbla = REG_VTBL_ACCESS;
1271                 }
1272
1273                 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1274                 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1275                                      sizeof(val32));
1276                 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1277                 val16 = nr;        /* vlan id */
1278                 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1279                                      sizeof(val16));
1280
1281                 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1282                 val8 = ((1 << 7) |      /* start command */
1283                         0);             /* write */
1284                 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1285                                      sizeof(val8));
1286         }
1287
1288         ROBO_END(driver);
1289         return 0;
1290 }
1291
1292 static int __init config_attach(robo_info_t *robo)
1293 {
1294         switch_config cfg[] = {
1295                 {"enable", handle_enable_read, handle_enable_write},
1296                 {"reset", NULL, handle_reset},
1297                 {"enable_vlan", handle_enable_vlan_read, handle_enable_vlan_write},
1298                 {NULL, NULL, NULL}
1299         };
1300         switch_config vlan[] = {
1301                 {"ports", handle_vlan_port_read, handle_vlan_port_write},
1302                 {NULL, NULL, NULL}
1303         };
1304         switch_driver driver = {
1305                 name: DRIVER_NAME,
1306                 version: DRIVER_VERSION,
1307                 interface: robo->name,
1308                 cpuport: 8,
1309                 ports: 9,
1310                 vlans: 16,
1311                 driver_handlers: cfg,
1312                 port_handlers: NULL,
1313                 vlan_handlers: vlan,
1314         };
1315         if (robo->devid == DEVID5325) {
1316                 driver.ports = 6;
1317                 driver.cpuport = 5;
1318         }
1319         driver.priv = (void *) robo;
1320
1321         return switch_register_driver(&driver);
1322 }
1323
1324 static void __exit config_detach(robo_info_t *robo)
1325 {
1326         switch_unregister_driver(DRIVER_NAME);
1327 }
1328
1329