Root/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
157static int config_attach(robo_info_t *robo);
158static void config_detach(robo_info_t *robo);
159
160/* Enable GPIO access to the chip */
161static void
162gpio_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 */
171static void
172gpio_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 */
179static int
180spi_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 */
210static int
211spi_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 */
252static void
253spi_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 */
267static void
268spi_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 */
294static int
295spi_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 */
341static int
342spi_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 */
388static 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 */
402static int
403mii_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 */
486static int
487mii_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 */
565static 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
575static int
576findmatch(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
592static uint
593getgpiopin(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 */
625typedef 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
632pdesc_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
645pdesc_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
667int
668bcm_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 */
752robo_info_t *
753bcm_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
903error:
904    MFREE(sb_osh(robo->sbh), robo, sizeof(robo_info_t));
905    return NULL;
906}
907
908/* Release access to the RoboSwitch */
909void
910bcm_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 */
917int
918bcm_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
968void 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
1008static 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
1018static 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
1031static 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
1047static 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}
1057static 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
1189static 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
1195static 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
1287static 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
1319static void __exit config_detach(robo_info_t *robo)
1320{
1321    switch_unregister_driver(DRIVER_NAME);
1322}
1323
1324
1325

Archive Download this file



interactive