2 * Broadcom BCM5325E/536x switch configuration module
4 * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
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.
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.
17 * Broadcom 53xx RoboSwitch device driver.
19 * Copyright 2007, Broadcom Corporation
20 * All Rights Reserved.
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.
29 #include <linux/autoconf.h>
30 #include <linux/module.h>
31 #include <linux/init.h>
32 #include <asm/uaccess.h>
38 #include <bcmendian.h>
39 #include "bcmparams.h"
43 #include "proto/ethernet.h"
44 #include <switch-core.h>
46 #define DRIVER_NAME "bcm57xx"
47 #define DRIVER_VERSION "0.1"
49 #ifndef GPIO_PIN_NOTDEFINED
50 #define GPIO_PIN_NOTDEFINED 0x20
54 #define ET_ERROR(args) printk args
56 #define ET_ERROR(args)
61 * Switch can be programmed through SPI interface, which
62 * has a rreg and a wreg functions to read from and write to
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 */
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 */
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 */
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 */
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 */
120 #define VLAN_NUMVLANS 16 /* # of VLANs */
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 */
145 #define REG_SPI_PAGE 0xff /* SPI Page register */
147 /* Access switch registers through GPIO/SPI */
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 */
154 /* misc. constants */
155 #define SPI_MAX_RETRY 100
157 static int config_attach(robo_info_t
*robo
);
158 static void config_detach(robo_info_t
*robo
);
160 /* Enable GPIO access to the chip */
162 gpio_enable(robo_info_t
*robo
)
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
);
170 /* Disable GPIO access to the chip */
172 gpio_disable(robo_info_t
*robo
)
174 /* Disable GPIO outputs with all their current values */
175 sb_gpioouten(robo
->sbh
, robo
->ss
| robo
->sck
| robo
->mosi
, 0, GPIO_DRV_PRIORITY
);
178 /* Write a byte stream to the chip thru SPI */
180 spi_write(robo_info_t
*robo
, uint8
*buf
, uint len
)
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) {
190 sb_gpioout(robo
->sbh
, robo
->sck
, 0, GPIO_DRV_PRIORITY
);
191 OSL_DELAY(SCK_EDGE_TIME
);
193 /* Sample on rising edge */
195 sb_gpioout(robo
->sbh
, robo
->mosi
, robo
->mosi
, GPIO_DRV_PRIORITY
);
197 sb_gpioout(robo
->sbh
, robo
->mosi
, 0, GPIO_DRV_PRIORITY
);
198 OSL_DELAY(MOSI_SETUP_TIME
);
201 sb_gpioout(robo
->sbh
, robo
->sck
, robo
->sck
, GPIO_DRV_PRIORITY
);
202 OSL_DELAY(SCK_EDGE_TIME
);
209 /* Read a byte stream from the chip thru SPI */
211 spi_read(robo_info_t
*robo
, uint8
*buf
, uint len
)
214 uint8 rack
, mask
, byte
;
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) {
221 sb_gpioout(robo
->sbh
, robo
->sck
, 0, GPIO_DRV_PRIORITY
);
222 OSL_DELAY(SCK_EDGE_TIME
);
224 /* Sample on falling edge */
225 if (sb_gpioin(robo
->sbh
) & robo
->miso
)
229 sb_gpioout(robo
->sbh
, robo
->sck
, robo
->sck
, GPIO_DRV_PRIORITY
);
230 OSL_DELAY(SCK_EDGE_TIME
);
232 /* RACK when bit 0 is high */
238 /* Byte bang from LSB to MSB */
244 ET_ERROR(("spi_read: timeout"));
251 /* Enable/disable SPI access */
253 spi_select(robo_info_t
*robo
, uint8 spi
)
256 /* Enable SPI access */
257 sb_gpioout(robo
->sbh
, robo
->ss
, 0, GPIO_DRV_PRIORITY
);
259 /* Disable SPI access */
260 sb_gpioout(robo
->sbh
, robo
->ss
, robo
->ss
, GPIO_DRV_PRIORITY
);
262 OSL_DELAY(SS_SETUP_TIME
);
266 /* Select chip and page */
268 spi_goto(robo_info_t
*robo
, uint8 page
)
270 uint8 reg8
= REG_SPI_PAGE
; /* page select register */
273 /* Issue the command only when we are on a different page */
274 if (robo
->page
== page
)
279 /* Enable SPI access */
282 /* Select new page with CID 0 */
283 cmd8
= ((6 << 4) | /* normal SPI */
285 spi_write(robo
, &cmd8
, 1);
286 spi_write(robo
, ®8
, 1);
287 spi_write(robo
, &page
, 1);
289 /* Disable SPI access */
293 /* Write register thru SPI */
295 spi_wreg(robo_info_t
*robo
, uint8 page
, uint8 addr
, void *val
, int len
)
305 /* validate value length and buffer address */
306 ASSERT(len
== 1 || (len
== 2 && !((int)val
& 1)) ||
307 (len
== 4 && !((int)val
& 3)));
309 /* Select chip and page */
310 spi_goto(robo
, page
);
312 /* Enable SPI access */
315 /* Write with CID 0 */
316 cmd8
= ((6 << 4) | /* normal SPI */
318 spi_write(robo
, &cmd8
, 1);
319 spi_write(robo
, &addr
, 1);
322 bytes
.val8
= *(uint8
*)val
;
325 bytes
.val16
= htol16(*(uint16
*)val
);
328 bytes
.val32
= htol32(*(uint32
*)val
);
331 spi_write(robo
, (uint8
*)val
, len
);
333 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__
, page
, addr
,
334 *(uint16
*)val
, len
));
335 /* Disable SPI access */
340 /* Read register thru SPI in fast SPI mode */
342 spi_rreg(robo_info_t
*robo
, uint8 page
, uint8 addr
, void *val
, int len
)
352 /* validate value length and buffer address */
353 ASSERT(len
== 1 || (len
== 2 && !((int)val
& 1)) ||
354 (len
== 4 && !((int)val
& 3)));
356 /* Select chip and page */
357 spi_goto(robo
, page
);
359 /* Enable SPI access */
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
);
369 *(uint8
*)val
= bytes
.val8
;
372 *(uint16
*)val
= ltoh16(bytes
.val16
);
375 *(uint32
*)val
= ltoh32(bytes
.val32
);
379 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__
, page
, addr
,
380 *(uint16
*)val
, len
));
382 /* Disable SPI access */
387 /* SPI/gpio interface functions */
388 static dev_ops_t spigpio
= {
397 /* Access switch registers through MII (MDC/MDIO) */
399 #define MII_MAX_RETRY 100
401 /* Write register thru MDC/MDIO */
403 mii_wreg(robo_info_t
*robo
, uint8 page
, uint8 reg
, void *val
, int len
)
405 uint16 cmd16
, val16
,val48
[3];
411 uint8
*ptr
= (uint8
*)val
;
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)));
417 ET_MSG(("%s: [0x%x-0x%x] := 0x%x (len %d)\n", __FUNCTION__
, page
, reg
,
418 *(uint16
*)val
, len
));
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
);
431 val16
= ((val16
<< 8) | ptr
[6]);
432 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA3
, val16
);
437 val16
= ((val16
<< 8) | ptr
[4]);
438 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA2
, val16
);
440 val16
= ((val16
<< 8) | ptr
[2]);
441 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA1
, val16
);
443 val16
= ((val16
<< 8) | ptr
[0]);
444 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA0
, val16
);
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
);
455 val16
= *(uint16
*)val
;
456 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA0
, val16
);
460 val16
= *(uint8
*)val
;
461 robo
->miiwr(h
, PSEUDO_PHYAD
, REG_MII_DATA0
, val16
);
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
);
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)
479 ET_ERROR(("mii_wreg: timeout"));
485 /* Read register thru MDC/MDIO */
487 mii_rreg(robo_info_t
*robo
, uint8 page
, uint8 reg
, void *val
, int len
)
492 uint8
*ptr
= (uint8
*)val
;
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)));
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
);
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
);
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)
519 ET_ERROR(("mii_rreg: timeout"));
523 ET_MSG(("%s: [0x%x-0x%x] => 0x%x (len %d)\n", __FUNCTION__
, page
, reg
, val16
, len
));
527 val16
= robo
->miird(h
, PSEUDO_PHYAD
, REG_MII_DATA3
);
528 ptr
[7] = (val16
>> 8);
529 ptr
[6] = (val16
& 0xff);
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);
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
;
552 val16
= robo
->miird(h
, PSEUDO_PHYAD
, REG_MII_DATA0
);
553 *(uint16
*)val
= val16
;
556 val16
= robo
->miird(h
, PSEUDO_PHYAD
, REG_MII_DATA0
);
557 *(uint8
*)val
= (uint8
)(val16
& 0xff);
564 /* MII interface functions */
565 static dev_ops_t mdcmdio
= {
573 /* High level switch configuration functions. */
576 findmatch(char *string
, char *name
)
583 while ((c
= strchr(string
, ',')) != NULL
) {
584 if (len
== (uint
)(c
- string
) && !strncmp(string
, name
, len
))
589 return (!strcmp(string
, name
));
593 getgpiopin(char *vars
, char *pin_name
, uint def_pin
)
595 char name
[] = "gpioXXXX";
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
))
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
;
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 */
624 /* port descriptor */
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? */
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},
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},
655 #define to_robo(driver) ((robo_info_t *) ((switch_driver *) driver)->priv)
656 #define ROBO_START(driver) \
658 robo_info_t *robo = to_robo(driver); \
659 if (robo->ops->enable_mgmtif) \
660 robo->ops->enable_mgmtif(robo)
662 #define ROBO_END(driver) \
663 if (robo->ops->disable_mgmtif) \
664 robo->ops->disable_mgmtif(robo); \
668 bcm_robo_reset(robo_info_t
*robo
)
677 /* printk(KERN_WARNING "bcmrobo.c: bcm_robo_reset\n"); */
679 if (robo
->ops
->enable_mgmtif
)
680 robo
->ops
->enable_mgmtif(robo
);
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
));
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
));
696 bcm_robo_set_macaddr(robo
, NULL
);
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
));
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
));
708 pdescsz
= sizeof(pdesc25
) / sizeof(pdesc_t
);
711 pdescsz
= sizeof(pdesc97
) / sizeof(pdesc_t
);
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
));
729 /* Set unmanaged mode */
730 robo
->ops
->read_reg(robo
, PAGE_CTRL
, REG_CTRL_MODE
, &val8
, sizeof(val8
));
732 robo
->ops
->write_reg(robo
, PAGE_CTRL
, REG_CTRL_MODE
, &val8
, sizeof(val8
));
734 /* No spanning tree for unmanaged mode */
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
));
743 robo
->ops
->write_reg(robo
, PAGE_CTRL
, 0x16, &val16
, 2);
745 if (robo
->ops
->enable_mgmtif
)
746 robo
->ops
->disable_mgmtif(robo
);
751 /* Get access to the RoboSwitch */
753 bcm_robo_attach(sb_t
*sbh
, void *h
, char *name
, char *vars
, miird_f miird
, miiwr_f miiwr
)
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
))));
765 bzero(robo
, sizeof(robo_info_t
));
775 /* Trigger external reset by nvram variable existance */
776 if ((reset
= getgpiopin(robo
->vars
, "robo_reset", GPIO_PIN_NOTDEFINED
)) !=
777 GPIO_PIN_NOTDEFINED
) {
779 * Reset sequence: RESET low(50ms)->high(20ms)
781 * We have to perform a full sequence for we don't know how long
782 * it has been from power on till now.
784 ET_MSG(("%s: Using external reset in gpio pin %d\n", __FUNCTION__
, reset
));
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
);
792 /* Keep RESET high for at least 20 ms */
793 sb_gpioout(robo
->sbh
, reset
, reset
, GPIO_DRV_PRIORITY
);
796 /* In case we need it */
797 idx
= sb_coreidx(robo
->sbh
);
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);
805 sb_setcoreidx(robo
->sbh
, idx
);
808 if (miird
&& miiwr
) {
810 int rc
, retry_count
= 0;
812 /* Read the PHY ID */
813 tmp
= miird(h
, PSEUDO_PHYAD
, 2);
816 rc
= mii_rreg(robo
, PAGE_MMR
, REG_DEVICE_ID
, \
817 &robo
->devid
, sizeof(uint16
));
821 } while ((robo
->devid
== 0) && (retry_count
< 10));
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
;
831 ET_MSG(("%s: devid: 0x%x\n", __FUNCTION__
, robo
->devid
));
835 if ((robo
->devid
== DEVID5395
) ||
836 (robo
->devid
== DEVID5397
) ||
837 (robo
->devid
== DEVID5398
)) {
840 /* If it is a 539x switch, use the soft reset register */
841 ET_MSG(("%s: Resetting 539x robo switch\n", __FUNCTION__
));
843 /* Reset the 539x switch core and register file */
845 mii_wreg(robo
, PAGE_CTRL
, REG_CTRL_SRST
, &srst_ctrl
, sizeof(uint8
));
850 mii_wreg(robo
, PAGE_CTRL
, REG_CTRL_SRST
, &srst_ctrl
, sizeof(uint8
));
854 int mosi
, miso
, ss
, sck
;
856 robo
->ops
= &spigpio
;
857 robo
->devid
= DEVID5325
;
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"));
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"));
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"));
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"));
883 robo
->miso
= 1 << miso
;
884 ET_MSG(("%s: ss %d sck %d mosi %d miso %d\n", __FUNCTION__
,
885 ss
, sck
, mosi
, miso
));
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
));
898 bcm_robo_reset(robo
);
904 MFREE(sb_osh(robo
->sbh
), robo
, sizeof(robo_info_t
));
908 /* Release access to the RoboSwitch */
910 bcm_robo_detach(robo_info_t
*robo
)
913 MFREE(sb_osh(robo
->sbh
), robo
, sizeof(robo_info_t
));
916 /* Enable the device and set it to a known good state */
918 bcm_robo_enable_device(robo_info_t
*robo
)
920 uint8 reg_offset
, reg_val
;
923 /* Enable management interface access */
924 if (robo
->ops
->enable_mgmtif
)
925 robo
->ops
->enable_mgmtif(robo
);
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 */
932 robo
->ops
->write_reg(robo
, PAGE_CTRL
, reg_offset
, ®_val
,
937 if (robo
->devid
== DEVID5325
) {
938 /* Must put the switch into Reverse MII mode! */
940 /* MII port state override (page 0 register 14) */
941 robo
->ops
->read_reg(robo
, PAGE_CTRL
, REG_CTRL_MIIPO
, ®_val
, sizeof(reg_val
));
943 /* Bit 4 enables reverse MII mode */
944 if (!(reg_val
& (1 << 4))) {
947 robo
->ops
->write_reg(robo
, PAGE_CTRL
, REG_CTRL_MIIPO
, ®_val
,
951 robo
->ops
->read_reg(robo
, PAGE_CTRL
, REG_CTRL_MIIPO
, ®_val
,
953 if (!(reg_val
& (1 << 4))) {
954 ET_ERROR(("robo_enable_device: enabling RvMII mode failed\n"));
960 /* Disable management interface access */
961 if (robo
->ops
->disable_mgmtif
)
962 robo
->ops
->disable_mgmtif(robo
);
968 void bcm_robo_set_macaddr(robo_info_t
*robo
, char *mac_addr
)
970 uint8 arl_entry
[8] = { 0 }, arl_entry1
[8] = { 0 };
972 if (mac_addr
!= NULL
)
973 memcpy(robo
->macaddr
, mac_addr
, 6);
975 mac_addr
= robo
->macaddr
;
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];
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
, \
992 /* Init the entry 0 of the bin */
993 arl_entry
[6] = 0x8; /* Port Id: MII */
994 arl_entry
[7] = 0xc0; /* Static Entry, Valid */
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
);
1002 /* Initialize the MAC Addr Index Register */
1003 robo
->ops
->write_reg(robo
, PAGE_VTBL
, REG_VTBL_MINDX
, \
1004 arl_entry
, ETHER_ADDR_LEN
);
1008 static int handle_reset(void *driver
, char *buf
, int nr
)
1011 bcm_robo_reset(robo
);
1018 static int handle_enable_read(void *driver
, char *buf
, int nr
)
1024 robo
->ops
->read_reg(robo
, PAGE_CTRL
, REG_CTRL_MODE
, &val8
, sizeof(val8
));
1025 ret
= sprintf(buf
, "%d\n", !!(val8
& (1 << 1)));
1031 static int handle_enable_write(void *driver
, char *buf
, int nr
)
1035 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_write\n"); */
1038 robo
->ops
->read_reg(robo
, PAGE_CTRL
, REG_CTRL_MODE
, &val8
, sizeof(val8
));
1040 val8
|= ((buf
[0] == '1') << 1);
1041 robo
->ops
->write_reg(robo
, PAGE_CTRL
, REG_CTRL_MODE
, &val8
, sizeof(val8
));
1047 static int handle_enable_vlan_read(void *driver
, char *buf
, int nr
)
1052 robo
->ops
->read_reg(robo
, PAGE_VLAN
, REG_VLAN_CTRL0
, &val8
, sizeof(val8
));
1055 return sprintf(buf
, "%d\n", (((val8
& (1 << 7)) == (1 << 7)) ? 1 : 0));
1057 static int handle_enable_vlan_write(void *driver
, char *buf
, int nr
)
1059 int disable
= ((buf
[0] != '1') ? 1 : 0);
1066 uint8 arl_entry
[8] = { 0 }, arl_entry1
[8] = { 0 };
1068 /* printk(KERN_WARNING "bcmrobo.c: handle_enable_vlan_write\n"); */
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
));
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
));
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];
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
, \
1102 /* Init the entry 0 of the bin */
1103 arl_entry
[6] = 0x8; /* Port Id: MII */
1104 arl_entry
[7] = 0xc0; /* Static Entry, Valid */
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
);
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
));
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
));
1120 pdescsz
= sizeof(pdesc25
) / sizeof(pdesc_t
);
1122 /* Initialize the MAC Addr Index Register */
1123 robo
->ops
->write_reg(robo
, PAGE_VTBL
, REG_VTBL_MINDX
, \
1124 arl_entry
, ETHER_ADDR_LEN
);
1127 pdescsz
= sizeof(pdesc97
) / sizeof(pdesc_t
);
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
++) {
1134 /* Add static ARL entries */
1135 if (robo
->devid
== DEVID5325
) {
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
));
1142 /* Write the entry */
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)),
1151 /* Set the VLAN Id in VLAN ID Index Register */
1153 robo
->ops
->write_reg(robo
, PAGE_VTBL
, REG_VTBL_VINDX
, \
1154 &val8
, sizeof(val8
));
1156 /* Set the MAC addr and VLAN Id in ARL Table MAC/VID Entry 0
1161 robo
->ops
->write_reg(robo
, PAGE_VTBL
, REG_VTBL_ARL_E0
, \
1162 arl_entry
, sizeof(arl_entry
));
1164 /* Set the Static bit , Valid bit and Port ID fields in
1165 * ARL Table Data Entry 0 Register
1168 robo
->ops
->write_reg(robo
, PAGE_VTBL
, REG_VTBL_DAT_E0
, \
1169 &val16
, sizeof(val16
));
1171 /* Clear the ARL_R/W bit and set the START/DONE bit in
1172 * the ARL Read/Write Control Register.
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)),
1189 static int handle_vlan_port_read(void *driver
, char *buf
, int nr
)
1191 /* FIXME: yeah, some work is missing here */
1192 return sprintf(buf
, "bcmrobo.c: handle_vlan_port_read unimplimented\n");
1195 static int handle_vlan_port_write(void *driver
, char *buf
, int nr
)
1198 switch_driver
*d
= (switch_driver
*) driver
;
1199 switch_vlan_config
*c
= switch_parse_vlan(d
, buf
);
1208 /* printk(KERN_WARNING "bcmrobo.c: handle_vlan_port_write, nr %d\n", nr); */
1215 if (robo
->devid
== DEVID5325
) {
1217 pdescsz
= sizeof(pdesc25
) / sizeof(pdesc_t
);
1220 pdescsz
= sizeof(pdesc97
) / sizeof(pdesc_t
);
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
))) {
1228 /* change default vlan tag */
1230 /* printk(KERN_WARNING "bcmrobo.c: set default vlan tag, port %d -> vlan %d\n", j, nr); */
1232 val16
= ((0 << 13) | /* priority - always 0 */
1234 robo
->ops
->write_reg(robo
, PAGE_VLAN
, pdesc
[j
].ptagr
, &val16
, sizeof(val16
));
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
,
1247 /* VLAN Table Access Register (Page 0x34, Address 0x06-0x07) */
1248 val16
= ((1 << 13) | /* start command */
1249 (1 << 12) | /* write state */
1251 robo
->ops
->write_reg(robo
, PAGE_VLAN
, REG_VLAN_ACCESS
, &val16
,
1254 uint8 vtble
, vtbli
, vtbla
;
1255 val32
= ((c
->untag
<< 9) | /* untag enable */
1256 c
->port
); /* vlan members */
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
;
1263 vtble
= REG_VTBL_ENTRY
;
1264 vtbli
= REG_VTBL_INDX
;
1265 vtbla
= REG_VTBL_ACCESS
;
1268 /* VLAN Table Entry Register (Page 0x05, Address 0x63-0x66/0x83-0x86) */
1269 robo
->ops
->write_reg(robo
, PAGE_VTBL
, vtble
, &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
,
1276 /* VLAN Table Access Register (Page 0x34, Address 0x60/0x80) */
1277 val8
= ((1 << 7) | /* start command */
1279 robo
->ops
->write_reg(robo
, PAGE_VTBL
, vtbla
, &val8
,
1287 static int __init
config_attach(robo_info_t
*robo
)
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
},
1295 switch_config vlan
[] = {
1296 {"ports", handle_vlan_port_read
, handle_vlan_port_write
},
1299 switch_driver driver
= {
1301 version
: DRIVER_VERSION
,
1302 interface
: robo
->name
,
1306 driver_handlers
: cfg
,
1307 port_handlers
: NULL
,
1308 vlan_handlers
: vlan
,
1310 if (robo
->devid
== DEVID5325
) {
1314 driver
.priv
= (void *) robo
;
1316 return switch_register_driver(&driver
);
1319 static void __exit
config_detach(robo_info_t
*robo
)
1321 switch_unregister_driver(DRIVER_NAME
);
This page took 0.141218 seconds and 5 git commands to generate.