remove support for the madwifi upstream release, it doesn't work on newer kernels...
[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 /* Keep RESET high for at least 20 ms */
792 sb_gpioout(robo->sbh, reset, reset, GPIO_DRV_PRIORITY);
793 bcm_mdelay(20);
794 } else {
795 /* In case we need it */
796 idx = sb_coreidx(robo->sbh);
797
798 if (sb_setcore(robo->sbh, SB_ROBO, 0)) {
799 /* If we have an internal robo core, reset it using sb_core_reset */
800 ET_MSG(("%s: Resetting internal robo core\n", __FUNCTION__));
801 sb_core_reset(robo->sbh, 0, 0);
802 }
803
804 sb_setcoreidx(robo->sbh, idx);
805 }
806
807 if (miird && miiwr) {
808 uint16 tmp;
809 int rc, retry_count = 0;
810
811 /* Read the PHY ID */
812 tmp = miird(h, PSEUDO_PHYAD, 2);
813 if (tmp != 0xffff) {
814 do {
815 rc = mii_rreg(robo, PAGE_MMR, REG_DEVICE_ID, \
816 &robo->devid, sizeof(uint16));
817 if (rc != 0)
818 break;
819 retry_count++;
820 } while ((robo->devid == 0) && (retry_count < 10));
821
822 ET_MSG(("%s: devid read %ssuccesfully via mii: 0x%x\n", __FUNCTION__, \
823 rc ? "un" : "", robo->devid));
824 ET_MSG(("%s: mii access to switch works\n", __FUNCTION__));
825 robo->ops = &mdcmdio;
826 if ((rc != 0) || (robo->devid == 0)) {
827 ET_MSG(("%s: error reading devid, assuming 5325e\n", __FUNCTION__));
828 robo->devid = DEVID5325;
829 }
830 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__, robo->devid));
831 }
832 }
833
834 if ((robo->devid == DEVID5395) ||
835 (robo->devid == DEVID5397) ||
836 (robo->devid == DEVID5398)) {
837 uint8 srst_ctrl;
838
839 /* If it is a 539x switch, use the soft reset register */
840 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__));
841
842 /* Reset the 539x switch core and register file */
843 srst_ctrl = 0x83;
844 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
845
846 bcm_mdelay(500);
847
848 srst_ctrl = 0x00;
849 mii_wreg(robo, PAGE_CTRL, REG_CTRL_SRST, &srst_ctrl, sizeof(uint8));
850 }
851
852 if (!robo->ops) {
853 int mosi, miso, ss, sck;
854
855 robo->ops = &spigpio;
856 robo->devid = DEVID5325;
857
858 /* Init GPIO mapping. Default 2, 3, 4, 5 */
859 ss = getgpiopin(vars, "robo_ss", 2);
860 if (ss == GPIO_PIN_NOTDEFINED) {
861 ET_ERROR(("robo_attach: robo_ss gpio fail: GPIO 2 in use"));
862 goto error;
863 }
864 robo->ss = 1 << ss;
865 sck = getgpiopin(vars, "robo_sck", 3);
866 if (sck == GPIO_PIN_NOTDEFINED) {
867 ET_ERROR(("robo_attach: robo_sck gpio fail: GPIO 3 in use"));
868 goto error;
869 }
870 robo->sck = 1 << sck;
871 mosi = getgpiopin(vars, "robo_mosi", 4);
872 if (mosi == GPIO_PIN_NOTDEFINED) {
873 ET_ERROR(("robo_attach: robo_mosi gpio fail: GPIO 4 in use"));
874 goto error;
875 }
876 robo->mosi = 1 << mosi;
877 miso = getgpiopin(vars, "robo_miso", 5);
878 if (miso == GPIO_PIN_NOTDEFINED) {
879 ET_ERROR(("robo_attach: robo_miso gpio fail: GPIO 5 in use"));
880 goto error;
881 }
882 robo->miso = 1 << miso;
883 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__,
884 ss, sck, mosi, miso));
885 }
886
887 /* sanity check */
888 ASSERT(robo->ops);
889 ASSERT(robo->ops->write_reg);
890 ASSERT(robo->ops->read_reg);
891 ASSERT((robo->devid == DEVID5325) ||
892 (robo->devid == DEVID5395) ||
893 (robo->devid == DEVID5397) ||
894 (robo->devid == DEVID5398));
895
896 bcm_robo_reset(robo);
897 config_attach(robo);
898
899 return robo;
900
901 error:
902 MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
903 return NULL;
904 }
905
906 /* Release access to the RoboSwitch */
907 void
908 bcm_robo_detach(robo_info_t *robo)
909 {
910 config_detach(robo);
911 MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
912 }
913
914 /* Enable the device and set it to a known good state */
915 int
916 bcm_robo_enable_device(robo_info_t *robo)
917 {
918 uint8 reg_offset, reg_val;
919 int ret = 0;
920
921 /* Enable management interface access */
922 if (robo->ops->enable_mgmtif)
923 robo->ops->enable_mgmtif(robo);
924
925 if (robo->devid == DEVID5398) {
926 /* Disable unused ports: port 6 and 7 */
927 for (reg_offset = REG_CTRL_PORT6; reg_offset <= REG_CTRL_PORT7; reg_offset ++) {
928 /* Set bits [1:0] to disable RX and TX */
929 reg_val = 0x03;
930 robo->ops->write_reg(robo, PAGE_CTRL, reg_offset, &reg_val,
931 sizeof(reg_val));
932 }
933 }
934
935 if (robo->devid == DEVID5325) {
936 /* Must put the switch into Reverse MII mode! */
937
938 /* MII port state override (page 0 register 14) */
939 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val, sizeof(reg_val));
940
941 /* Bit 4 enables reverse MII mode */
942 if (!(reg_val & (1 << 4))) {
943 /* Enable RvMII */
944 reg_val |= (1 << 4);
945 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
946 sizeof(reg_val));
947
948 /* Read back */
949 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MIIPO, &reg_val,
950 sizeof(reg_val));
951 if (!(reg_val & (1 << 4))) {
952 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
953 ret = -1;
954 }
955 }
956 }
957
958 /* Disable management interface access */
959 if (robo->ops->disable_mgmtif)
960 robo->ops->disable_mgmtif(robo);
961
962 return ret;
963 }
964
965
966 void bcm_robo_set_macaddr(robo_info_t *robo, char *mac_addr)
967 {
968 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
969
970 if (mac_addr != NULL)
971 memcpy(robo->macaddr, mac_addr, 6);
972
973 mac_addr = robo->macaddr;
974
975 /* setup mac address */
976 arl_entry[0] = mac_addr[5];
977 arl_entry[1] = mac_addr[4];
978 arl_entry[2] = mac_addr[3];
979 arl_entry[3] = mac_addr[2];
980 arl_entry[4] = mac_addr[1];
981 arl_entry[5] = mac_addr[0];
982
983 if (robo->devid == DEVID5325) {
984 /* Init the entry 1 of the bin */
985 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
986 arl_entry1, sizeof(arl_entry1));
987 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
988 arl_entry1, 1);
989
990 /* Init the entry 0 of the bin */
991 arl_entry[6] = 0x8; /* Port Id: MII */
992 arl_entry[7] = 0xc0; /* Static Entry, Valid */
993
994 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
995 arl_entry, sizeof(arl_entry));
996 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
997 arl_entry, ETHER_ADDR_LEN);
998
999 } else {
1000 /* Initialize the MAC Addr Index Register */
1001 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1002 arl_entry, ETHER_ADDR_LEN);
1003 }
1004 }
1005
1006 static int handle_reset(void *driver, char *buf, int nr)
1007 {
1008 ROBO_START(driver);
1009 bcm_robo_reset(robo);
1010 ROBO_END(driver);
1011
1012 return 0;
1013 }
1014
1015
1016 static int handle_enable_read(void *driver, char *buf, int nr)
1017 {
1018 int ret;
1019 uint8 val8;
1020
1021 ROBO_START(driver);
1022 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1023 ret = sprintf(buf, "%d\n", !!(val8 & (1 << 1)));
1024 ROBO_END(driver);
1025
1026 return ret;
1027 }
1028
1029 static int handle_enable_write(void *driver, char *buf, int nr)
1030 {
1031 uint8 val8;
1032
1033 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_write\n"); */
1034
1035 ROBO_START(driver);
1036 robo->ops->read_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1037 val8 &= ~(1 << 1);
1038 val8 |= ((buf[0] == '1') << 1);
1039 robo->ops->write_reg(robo, PAGE_CTRL, REG_CTRL_MODE, &val8, sizeof(val8));
1040 ROBO_END(driver);
1041
1042 return 0;
1043 }
1044
1045 static int handle_enable_vlan_read(void *driver, char *buf, int nr)
1046 {
1047 uint8 val8;
1048
1049 ROBO_START(driver);
1050 robo->ops->read_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1051 ROBO_END(driver);
1052
1053 return sprintf(buf, "%d\n", (((val8 & (1 << 7)) == (1 << 7)) ? 1 : 0));
1054 }
1055 static int handle_enable_vlan_write(void *driver, char *buf, int nr)
1056 {
1057 int disable = ((buf[0] != '1') ? 1 : 0);
1058
1059 uint8 val8;
1060 uint16 val16;
1061 pdesc_t *pdesc;
1062 int pdescsz;
1063 uint16 vid;
1064 uint8 arl_entry[8] = { 0 }, arl_entry1[8] = { 0 };
1065
1066 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_vlan_write\n"); */
1067
1068 ROBO_START(driver);
1069
1070 /* setup global vlan configuration */
1071 /* VLAN Control 0 Register (Page 0x34, Address 0) */
1072 val8 = disable ? 0 :
1073 ((1 << 7) | /* enable/disable 802.1Q VLAN */
1074 (3 << 5)); /* individual VLAN learning mode */
1075 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL0, &val8, sizeof(val8));
1076
1077 /* VLAN Control 1 Register (Page 0x34, Address 1) */
1078 val8 = disable ? 0 :
1079 ((1 << 2) | /* enable/disable RSV multicast V Fwdmap */
1080 (1 << 3)); /* enable/disable RSV multicast V Untagmap */
1081 if (robo->devid == DEVID5325)
1082 val8 |= disable ? 0 : (1 << 1); /* enable/disable RSV multicast V Tagging */
1083 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL1, &val8, sizeof(val8));
1084
1085 if ( disable == 0 ) { /* FIXME: ok to stop here when disabling? */
1086 arl_entry[0] = robo->macaddr[5];
1087 arl_entry[1] = robo->macaddr[4];
1088 arl_entry[2] = robo->macaddr[3];
1089 arl_entry[3] = robo->macaddr[2];
1090 arl_entry[4] = robo->macaddr[1];
1091 arl_entry[5] = robo->macaddr[0];
1092
1093 if (robo->devid == DEVID5325) {
1094 /* Init the entry 1 of the bin */
1095 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E1, \
1096 arl_entry1, sizeof(arl_entry1));
1097 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E1, \
1098 arl_entry1, 1);
1099
1100 /* Init the entry 0 of the bin */
1101 arl_entry[6] = 0x8; /* Port Id: MII */
1102 arl_entry[7] = 0xc0; /* Static Entry, Valid */
1103
1104 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1105 arl_entry, sizeof(arl_entry));
1106 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1107 arl_entry, ETHER_ADDR_LEN);
1108
1109 /* VLAN Control 4 Register (Page 0x34, Address 4) */
1110 val8 = (1 << 6); /* drop frame with VID violation */
1111 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL4, &val8, sizeof(val8));
1112
1113 /* VLAN Control 5 Register (Page 0x34, Address 5) */
1114 val8 = (1 << 3); /* drop frame when miss V table */
1115 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_CTRL5, &val8, sizeof(val8));
1116
1117 pdesc = pdesc25;
1118 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1119 } else {
1120 /* Initialize the MAC Addr Index Register */
1121 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_MINDX, \
1122 arl_entry, ETHER_ADDR_LEN);
1123
1124 pdesc = pdesc97;
1125 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1126 }
1127
1128 /* setup each vlan. max. 16 vlans. */
1129 /* force vlan id to be equal to vlan number */
1130 for (vid = 0; vid < VLAN_NUMVLANS; vid ++) {
1131
1132 /* Add static ARL entries */
1133 if (robo->devid == DEVID5325) {
1134 val8 = vid;
1135 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VID_E0, \
1136 &val8, sizeof(val8));
1137 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1138 &val8, sizeof(val8));
1139
1140 /* Write the entry */
1141 val8 = 0x80;
1142 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1143 &val8, sizeof(val8));
1144 /* Wait for write to complete */
1145 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1146 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1147 100 /* usec */);
1148 } else {
1149 /* Set the VLAN Id in VLAN ID Index Register */
1150 val8 = vid;
1151 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_VINDX, \
1152 &val8, sizeof(val8));
1153
1154 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1155 * Register.
1156 */
1157 arl_entry[6] = vid;
1158 arl_entry[7] = 0x0;
1159 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_ARL_E0, \
1160 arl_entry, sizeof(arl_entry));
1161
1162 /* Set the Static bit , Valid bit and Port ID fields in
1163 * ARL Table Data Entry 0 Register
1164 */
1165 val16 = 0xc008;
1166 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_DAT_E0, \
1167 &val16, sizeof(val16));
1168
1169 /* Clear the ARL_R/W bit and set the START/DONE bit in
1170 * the ARL Read/Write Control Register.
1171 */
1172 val8 = 0x80;
1173 robo->ops->write_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1174 &val8, sizeof(val8));
1175 /* Wait for write to complete */
1176 SPINWAIT((robo->ops->read_reg(robo, PAGE_VTBL, REG_VTBL_CTRL, \
1177 &val8, sizeof(val8)), ((val8 & 0x80) != 0)),
1178 100 /* usec */);
1179 }
1180 }
1181 }
1182
1183 ROBO_END(driver);
1184 return 0;
1185 }
1186
1187 static int handle_vlan_port_read(void *driver, char *buf, int nr)
1188 {
1189 /* FIXME: yeah, some work is missing here */
1190 return sprintf(buf, "bcmrobo.c: handle_vlan_port_read unimplimented\n");
1191 }
1192
1193 static int handle_vlan_port_write(void *driver, char *buf, int nr)
1194 {
1195
1196 switch_driver *d = (switch_driver *) driver;
1197 switch_vlan_config *c = switch_parse_vlan(d, buf);
1198
1199 uint8 val8;
1200 uint16 val16;
1201 uint32 val32;
1202 int j;
1203 pdesc_t *pdesc;
1204 int pdescsz;
1205
1206 /* printk(KERN_WARNING "bcmrobo.c: handle_vlan_port_write, nr %d\n", nr); */
1207
1208 if (c == NULL)
1209 return -EINVAL;
1210
1211 ROBO_START(driver);
1212
1213 if (robo->devid == DEVID5325) {
1214 pdesc = pdesc25;
1215 pdescsz = sizeof(pdesc25) / sizeof(pdesc_t);
1216 } else {
1217 pdesc = pdesc97;
1218 pdescsz = sizeof(pdesc97) / sizeof(pdesc_t);
1219 }
1220
1221
1222 for (j = 0; j < d->ports; j++) {
1223 if ((c->untag | c->pvid) & (1 << j))
1224 if ((j != d->cpuport) || (c->untag & (1 << j))) {
1225
1226 /* change default vlan tag */
1227
1228 /* printk(KERN_WARNING "bcmrobo.c: set default vlan tag, port %d -> vlan %d\n", j, nr); */
1229
1230 val16 = ((0 << 13) | /* priority - always 0 */
1231 nr); /* vlan id */
1232 robo->ops->write_reg(robo, PAGE_VLAN, pdesc[j].ptagr, &val16, sizeof(val16));
1233 }
1234 }
1235
1236
1237 if (robo->devid == DEVID5325) {
1238 val32 = ((c->untag << 6) | /* untag enable */
1239 c->port); /* vlan members */
1240 val32 |= ((1 << 20) | /* valid write */
1241 ((nr >> 4) << 12)); /* vlan id bit[11:4] */
1242 /* VLAN Write Register (Page 0x34, Address 0x08-0x0B) */
1243 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_WRITE, &val32,
1244 sizeof(val32));
1245 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1246 val16 = ((1 << 13) | /* start command */
1247 (1 << 12) | /* write state */
1248 nr); /* vlan id */
1249 robo->ops->write_reg(robo, PAGE_VLAN, REG_VLAN_ACCESS, &val16,
1250 sizeof(val16));
1251 } else {
1252 uint8 vtble, vtbli, vtbla;
1253 val32 = ((c->untag << 9) | /* untag enable */
1254 c->port); /* vlan members */
1255
1256 if (robo->devid == DEVID5395) {
1257 vtble = REG_VTBL_ENTRY_5395;
1258 vtbli = REG_VTBL_INDX_5395;
1259 vtbla = REG_VTBL_ACCESS_5395;
1260 } else {
1261 vtble = REG_VTBL_ENTRY;
1262 vtbli = REG_VTBL_INDX;
1263 vtbla = REG_VTBL_ACCESS;
1264 }
1265
1266 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1267 robo->ops->write_reg(robo, PAGE_VTBL, vtble, &val32,
1268 sizeof(val32));
1269 /* VLAN Table Address Index Reg (Page 0x05, Address 0x61-0x62/0x81-0x82) */
1270 val16 = nr; /* vlan id */
1271 robo->ops->write_reg(robo, PAGE_VTBL, vtbli, &val16,
1272 sizeof(val16));
1273
1274 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1275 val8 = ((1 << 7) | /* start command */
1276 0); /* write */
1277 robo->ops->write_reg(robo, PAGE_VTBL, vtbla, &val8,
1278 sizeof(val8));
1279 }
1280
1281 ROBO_END(driver);
1282 return 0;
1283 }
1284
1285 static int __init config_attach(robo_info_t *robo)
1286 {
1287 switch_config cfg[] = {
1288 {"enable", handle_enable_read, handle_enable_write},
1289 {"reset", NULL, handle_reset},
1290 {"enable_vlan", handle_enable_vlan_read, handle_enable_vlan_write},
1291 {NULL, NULL, NULL}
1292 };
1293 switch_config vlan[] = {
1294 {"ports", handle_vlan_port_read, handle_vlan_port_write},
1295 {NULL, NULL, NULL}
1296 };
1297 switch_driver driver = {
1298 name: DRIVER_NAME,
1299 version: DRIVER_VERSION,
1300 interface: robo->name,
1301 cpuport: 8,
1302 ports: 9,
1303 vlans: 16,
1304 driver_handlers: cfg,
1305 port_handlers: NULL,
1306 vlan_handlers: vlan,
1307 };
1308 if (robo->devid == DEVID5325) {
1309 driver.ports = 6;
1310 driver.cpuport = 5;
1311 }
1312 driver.priv = (void *) robo;
1313
1314 return switch_register_driver(&driver);
1315 }
1316
1317 static void __exit config_detach(robo_info_t *robo)
1318 {
1319 switch_unregister_driver(DRIVER_NAME);
1320 }
1321
1322
This page took 0.122109 seconds and 5 git commands to generate.