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