Root/target/linux/ubicom32/files/arch/ubicom32/mach-common/switch-bcm539x.c

1/*
2 * arch/ubicom32/mach-common/switch-bcm539x.c
3 * BCM539X switch driver, SPI mode
4 *
5 * (C) Copyright 2009, Ubicom, Inc.
6 *
7 * This file is part of the Ubicom32 Linux Kernel Port.
8 *
9 * The Ubicom32 Linux Kernel Port is free software: you can redistribute
10 * it and/or modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation, either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * The Ubicom32 Linux Kernel Port is distributed in the hope that it
15 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
16 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
17 * the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with the Ubicom32 Linux Kernel Port. If not,
21 * see <http://www.gnu.org/licenses/>.
22 *
23 * Ubicom32 implementation derived from (with many thanks):
24 * arch/m68knommu
25 * arch/blackfin
26 * arch/parisc
27 */
28
29#include <linux/platform_device.h>
30#include <linux/spi/spi.h>
31#include <linux/gpio.h>
32#include <linux/delay.h>
33#include <linux/mii.h>
34
35#include <asm/switch-dev.h>
36#include <asm/ubicom32-spi-gpio.h>
37#include "switch-core.h"
38#include "switch-bcm539x-reg.h"
39
40#define DRIVER_NAME "bcm539x-spi"
41#define DRIVER_VERSION "1.0"
42
43#undef BCM539X_DEBUG
44#define BCM539X_SPI_RETRIES 100
45
46struct bcm539x_data {
47    struct switch_device *switch_dev;
48
49    /*
50     * Our private data
51     */
52    struct spi_device *spi;
53    struct switch_core_platform_data *pdata;
54
55    /*
56     * Last page we accessed
57     */
58    u8_t last_page;
59
60    /*
61     * 539x Device ID
62     */
63    u8_t device_id;
64};
65
66/*
67 * bcm539x_wait_status
68 * Waits for the specified bit in the status register to be set/cleared.
69 */
70static int bcm539x_wait_status(struct bcm539x_data *bd, u8_t mask, int set)
71{
72    u8_t txbuf[2];
73    u8_t rxbuf;
74    int i;
75    int ret;
76
77    txbuf[0] = BCM539X_CMD_READ;
78    txbuf[1] = BCM539X_GLOBAL_SPI_STATUS;
79    for (i = 0; i < BCM539X_SPI_RETRIES; i++) {
80        ret = spi_write_then_read(bd->spi, txbuf, 2, &rxbuf, 1);
81        rxbuf &= mask;
82        if ((set && rxbuf) || (!set && !rxbuf)) {
83            return 0;
84        }
85        udelay(1);
86    }
87
88    return -EIO;
89}
90
91/*
92 * bcm539x_set_page
93 * Sets the register page for access (only if necessary)
94 */
95static int bcm539x_set_page(struct bcm539x_data *bd, u8_t page)
96{
97    u8_t txbuf[3];
98
99    if (page == bd->last_page) {
100        return 0;
101    }
102
103    bd->last_page = page;
104
105    txbuf[0] = BCM539X_CMD_WRITE;
106    txbuf[1] = BCM539X_GLOBAL_PAGE;
107    txbuf[2] = page;
108
109    return spi_write(bd->spi, txbuf, 3);
110}
111
112/*
113 * bcm539x_write_bytes
114 * Writes a number of bytes to a given page and register
115 */
116static int bcm539x_write_bytes(struct bcm539x_data *bd, u8_t page,
117                   u8_t reg, void *buf, u8_t len)
118{
119    int ret;
120    u8_t *txbuf;
121
122    txbuf = kmalloc(2 + len, GFP_KERNEL);
123    if (!txbuf) {
124        return -ENOMEM;
125    }
126
127    /*
128     * Make sure the chip has finished processing our previous request
129     */
130    ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
131    if (ret) {
132        goto done;
133    }
134
135    /*
136     * Set the page
137     */
138    ret = bcm539x_set_page(bd, page);
139    if (ret) {
140        goto done;
141    }
142
143    /*
144     * Read the data
145     */
146    txbuf[0] = BCM539X_CMD_WRITE;
147    txbuf[1] = reg;
148    memcpy(&txbuf[2], buf, len);
149
150#ifdef BCM539X_DEBUG
151    {
152        int i;
153        printk("write page %02x reg %02x len=%d buf=", page, reg, len);
154        for (i = 0; i < len + 2; i++) {
155            printk("%02x ", txbuf[i]);
156        }
157        printk("\n");
158    }
159#endif
160
161    ret = spi_write(bd->spi, txbuf, 2 + len);
162
163done:
164    kfree(txbuf);
165    return ret;
166}
167
168/*
169 * bcm539x_write_32
170 * Writes 32 bits of data to the given page and register
171 */
172static inline int bcm539x_write_32(struct bcm539x_data *bd, u8_t page,
173                   u8_t reg, u32_t data)
174{
175    data = cpu_to_le32(data);
176    return bcm539x_write_bytes(bd, page, reg, &data, 4);
177}
178
179/*
180 * bcm539x_write_16
181 * Writes 16 bits of data to the given page and register
182 */
183static inline int bcm539x_write_16(struct bcm539x_data *bd, u8_t page,
184                   u8_t reg, u16_t data)
185{
186    data = cpu_to_le16(data);
187    return bcm539x_write_bytes(bd, page, reg, &data, 2);
188}
189
190/*
191 * bcm539x_write_8
192 * Writes 8 bits of data to the given page and register
193 */
194static inline int bcm539x_write_8(struct bcm539x_data *bd, u8_t page,
195                  u8_t reg, u8_t data)
196{
197    return bcm539x_write_bytes(bd, page, reg, &data, 1);
198}
199
200/*
201 * bcm539x_read_bytes
202 * Reads a number of bytes from a given page and register
203 */
204static int bcm539x_read_bytes(struct bcm539x_data *bd, u8_t page,
205                  u8_t reg, void *buf, u8_t len)
206{
207    u8_t txbuf[2];
208    int ret;
209
210    /*
211     * (1) Make sure the chip has finished processing our previous request
212     */
213    ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_SPIF, 0);
214    if (ret) {
215        return ret;
216    }
217
218    /*
219     * (2) Set the page
220     */
221    ret = bcm539x_set_page(bd, page);
222    if (ret) {
223        return ret;
224    }
225
226    /*
227     * (3) Kick off the register read
228     */
229    txbuf[0] = BCM539X_CMD_READ;
230    txbuf[1] = reg;
231    ret = spi_write_then_read(bd->spi, txbuf, 2, txbuf, 1);
232    if (ret) {
233        return ret;
234    }
235
236    /*
237     * (4) Wait for RACK
238     */
239    ret = bcm539x_wait_status(bd, BCM539X_GLOBAL_SPI_ST_RACK, 1);
240    if (ret) {
241        return ret;
242    }
243
244    /*
245     * (5) Read the data
246     */
247    txbuf[0] = BCM539X_CMD_READ;
248    txbuf[1] = BCM539X_GLOBAL_SPI_DATA0;
249
250    ret = spi_write_then_read(bd->spi, txbuf, 2, buf, len);
251
252#ifdef BCM539X_DEBUG
253    {
254        int i;
255        printk("read page %02x reg %02x len=%d rxbuf=",
256               page, reg, len);
257        for (i = 0; i < len; i++) {
258            printk("%02x ", ((u8_t *)buf)[i]);
259        }
260        printk("\n");
261    }
262#endif
263
264    return ret;
265}
266
267/*
268 * bcm539x_read_32
269 * Reads an 32 bit number from a given page and register
270 */
271static int bcm539x_read_32(struct bcm539x_data *bd, u8_t page,
272               u8_t reg, u32_t *buf)
273{
274    int ret = bcm539x_read_bytes(bd, page, reg, buf, 4);
275    *buf = le32_to_cpu(*buf);
276    return ret;
277}
278
279/*
280 * bcm539x_read_16
281 * Reads an 16 bit number from a given page and register
282 */
283static int bcm539x_read_16(struct bcm539x_data *bd, u8_t page,
284               u8_t reg, u16_t *buf)
285{
286    int ret = bcm539x_read_bytes(bd, page, reg, buf, 2);
287    *buf = le16_to_cpu(*buf);
288    return ret;
289}
290
291/*
292 * bcm539x_read_8
293 * Reads an 8 bit number from a given page and register
294 */
295static int bcm539x_read_8(struct bcm539x_data *bd, u8_t page,
296              u8_t reg, u8_t *buf)
297{
298    return bcm539x_read_bytes(bd, page, reg, buf, 1);
299}
300
301/*
302 * bcm539x_set_mode
303 */
304static int bcm539x_set_mode(struct bcm539x_data *bd, int state)
305{
306    u8_t buf;
307    int ret;
308
309    ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &buf);
310    if (ret) {
311        return ret;
312    }
313
314    buf &= ~(1 << 1);
315    buf |= state ? (1 << 1) : 0;
316
317    ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, buf);
318    return ret;
319}
320
321/*
322 * bcm539x_handle_reset
323 */
324static int bcm539x_handle_reset(struct switch_device *dev, char *buf, int inst)
325{
326    struct bcm539x_data *bd =
327        (struct bcm539x_data *)switch_get_drvdata(dev);
328    int ret;
329
330    ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST,
331                  (1 << 7) | (1 << 4));
332    if (ret) {
333        return ret;
334    }
335
336    udelay(20);
337
338    ret = bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_SRST, 0);
339    return ret;
340}
341
342/*
343 * bcm539x_handle_vlan_ports_read
344 */
345static int bcm539x_handle_vlan_ports_read(struct switch_device *dev,
346                      char *buf, int inst)
347{
348    struct bcm539x_data *bd =
349        (struct bcm539x_data *)switch_get_drvdata(dev);
350    int j;
351    int len = 0;
352    u8_t rxbuf8;
353    u32_t rxbuf32;
354    int ret;
355
356    ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
357    if (ret) {
358        return ret;
359    }
360
361    ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
362                  (1 << 7) | 1);
363    if (ret) {
364        return ret;
365    }
366
367    /*
368     * Wait for completion
369     */
370    for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
371        ret = bcm539x_read_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
372                     &rxbuf8);
373        if (ret) {
374            return ret;
375        }
376        if (!(rxbuf8 & (1 << 7))) {
377            break;
378        }
379    }
380
381    if (j == BCM539X_SPI_RETRIES) {
382        return -EIO;
383    }
384
385    /*
386     * Read the table entry
387     */
388    ret = bcm539x_read_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, &rxbuf32);
389    if (ret) {
390        return ret;
391    }
392
393    for (j = 0; j < 9; j++) {
394        if (rxbuf32 & (1 << j)) {
395            u16_t rxbuf16;
396            len += sprintf(buf + len, "%d", j);
397            if (rxbuf32 & (1 << (j + 9))) {
398                buf[len++] = 'u';
399            } else {
400                buf[len++] = 't';
401            }
402            ret = bcm539x_read_16(bd, PAGE_VLAN,
403                          REG_VLAN_PTAG0 + (j << 1),
404                          &rxbuf16);
405            if (ret) {
406                return ret;
407            }
408            if (rxbuf16 == inst) {
409                buf[len++] = '*';
410            }
411            buf[len++] = '\t';
412        }
413    }
414
415    len += sprintf(buf + len, "\n");
416    buf[len] = '\0';
417
418    return len;
419}
420
421/*
422 * bcm539x_handle_vlan_ports_write
423 */
424static int bcm539x_handle_vlan_ports_write(struct switch_device *dev,
425                       char *buf, int inst)
426{
427    struct bcm539x_data *bd =
428        (struct bcm539x_data *)switch_get_drvdata(dev);
429    int j;
430    u32_t untag;
431    u32_t ports;
432    u32_t def;
433
434    u8_t rxbuf8;
435    u16_t rxbuf16;
436    int ret;
437
438    switch_parse_vlan_ports(dev, buf, &untag, &ports, &def);
439
440#ifdef BCM539X_DEBUG
441    printk(KERN_DEBUG "'%s' inst=%d untag=%08x ports=%08x def=%08x\n",
442        buf, inst, untag, ports, def);
443#endif
444
445    if (!ports) {
446        return 0;
447    }
448
449    /*
450     * Change default vlan tag
451     */
452    for (j = 0; j < 9; j++) {
453        if ((untag | def) & (1 << j)) {
454            ret = bcm539x_write_16(bd, PAGE_VLAN,
455                           REG_VLAN_PTAG0 + (j << 1),
456                           inst);
457            if (ret) {
458                return ret;
459            }
460            continue;
461        }
462
463        if (!(dev->port_mask[0] & (1 << j))) {
464            continue;
465        }
466
467        /*
468         * Remove any ports which are not listed anymore as members of
469         * this vlan
470         */
471        ret = bcm539x_read_16(bd, PAGE_VLAN,
472                      REG_VLAN_PTAG0 + (j << 1), &rxbuf16);
473        if (ret) {
474            return ret;
475        }
476        if (rxbuf16 == inst) {
477            ret = bcm539x_write_16(bd, PAGE_VLAN,
478                           REG_VLAN_PTAG0 + (j << 1), 0);
479            if (ret) {
480                return ret;
481            }
482        }
483    }
484
485    /*
486     * Write the VLAN table
487     */
488    ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, inst);
489    if (ret) {
490        return ret;
491    }
492
493    ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395,
494                   (untag << 9) | ports);
495    if (ret) {
496        return ret;
497    }
498
499    ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
500                  (1 << 7) | 0);
501    if (ret) {
502        return ret;
503    }
504
505    /*
506     * Wait for completion
507     */
508    for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
509        ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
510                     &rxbuf8, 1);
511        if (ret) {
512            return ret;
513        }
514        if (!(rxbuf8 & (1 << 7))) {
515            break;
516        }
517    }
518
519    return (j < BCM539X_SPI_RETRIES) ? 0 : -EIO;
520}
521
522/*
523 * Handlers for <this_driver>/vlan/<vlan_id>
524 */
525static const struct switch_handler bcm539x_switch_handlers_vlan_dir[] = {
526    {
527        .name = "ports",
528        .read = bcm539x_handle_vlan_ports_read,
529        .write = bcm539x_handle_vlan_ports_write,
530    },
531    {
532    },
533};
534
535/*
536 * bcm539x_handle_vlan_delete_write
537 */
538static int bcm539x_handle_vlan_delete_write(struct switch_device *dev,
539                        char *buf, int inst)
540{
541    struct bcm539x_data *bd =
542        (struct bcm539x_data *)switch_get_drvdata(dev);
543    int vid;
544    u8_t rxbuf8;
545    u32_t txbuf;
546    int j;
547    int ret;
548
549    vid = simple_strtoul(buf, NULL, 0);
550    if (!vid) {
551        return -EINVAL;
552    }
553
554    /*
555     * Disable this VLAN
556     *
557     * Go through the port-based vlan registers and clear the appropriate
558     * ones out
559     */
560    for (j = 0; j < 9; j++) {
561        u16_t rxbuf16;
562        ret = bcm539x_read_16(bd, PAGE_VLAN, REG_VLAN_PTAG0 + (j << 1),
563                      &rxbuf16);
564        if (ret) {
565            return ret;
566        }
567        if (rxbuf16 == vid) {
568            txbuf = 0;
569            ret = bcm539x_write_16(bd, PAGE_VLAN,
570                           REG_VLAN_PTAG0 + (j << 1),
571                           txbuf);
572            if (ret) {
573                return ret;
574            }
575        }
576    }
577
578    /*
579     * Write the VLAN table
580     */
581    txbuf = vid;
582    ret = bcm539x_write_16(bd, PAGE_VTBL, REG_VTBL_INDX_5395, txbuf);
583    if (ret) {
584        return ret;
585    }
586
587    txbuf = 0;
588    ret = bcm539x_write_32(bd, PAGE_VTBL, REG_VTBL_ENTRY_5395, txbuf);
589    if (ret) {
590        return ret;
591    }
592
593    txbuf = (1 << 7) | (0);
594    ret = bcm539x_write_8(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395, txbuf);
595    if (ret) {
596        return ret;
597    }
598
599    /*
600     * Wait for completion
601     */
602    for (j = 0; j < BCM539X_SPI_RETRIES; j++) {
603        ret = bcm539x_read_bytes(bd, PAGE_VTBL, REG_VTBL_ACCESS_5395,
604                     &rxbuf8, 1);
605        if (ret) {
606            return ret;
607        }
608        if (!(rxbuf8 & (1 << 7))) {
609            break;
610        }
611    }
612
613    if (j == BCM539X_SPI_RETRIES) {
614        return -EIO;
615    }
616
617    return switch_remove_vlan_dir(dev, vid);
618}
619
620/*
621 * bcm539x_handle_vlan_create_write
622 */
623static int bcm539x_handle_vlan_create_write(struct switch_device *dev,
624                        char *buf, int inst)
625{
626    int vid;
627
628    vid = simple_strtoul(buf, NULL, 0);
629    if (!vid) {
630        return -EINVAL;
631    }
632
633    return switch_create_vlan_dir(dev, vid,
634                      bcm539x_switch_handlers_vlan_dir);
635}
636
637/*
638 * bcm539x_handle_enable_read
639 */
640static int bcm539x_handle_enable_read(struct switch_device *dev,
641                      char *buf, int inst)
642{
643    struct bcm539x_data *bd =
644        (struct bcm539x_data *)switch_get_drvdata(dev);
645    u8_t rxbuf;
646    int ret;
647
648    ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MODE, &rxbuf);
649    if (ret) {
650        return ret;
651    }
652    rxbuf = (rxbuf & (1 << 1)) ? 1 : 0;
653
654    return sprintf(buf, "%d\n", rxbuf);
655}
656
657/*
658 * bcm539x_handle_enable_write
659 */
660static int bcm539x_handle_enable_write(struct switch_device *dev,
661                       char *buf, int inst)
662{
663    struct bcm539x_data *bd =
664        (struct bcm539x_data *)switch_get_drvdata(dev);
665
666    return bcm539x_set_mode(bd, buf[0] == '1');
667}
668
669/*
670 * bcm539x_handle_enable_vlan_read
671 */
672static int bcm539x_handle_enable_vlan_read(struct switch_device *dev,
673                       char *buf, int inst)
674{
675    struct bcm539x_data *bd =
676        (struct bcm539x_data *)switch_get_drvdata(dev);
677    u8_t rxbuf;
678    int ret;
679
680    ret = bcm539x_read_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, &rxbuf);
681    if (ret) {
682        return ret;
683    }
684    rxbuf = (rxbuf & (1 << 7)) ? 1 : 0;
685
686    return sprintf(buf, "%d\n", rxbuf);
687}
688
689/*
690 * bcm539x_handle_enable_vlan_write
691 */
692static int bcm539x_handle_enable_vlan_write(struct switch_device *dev,
693                        char *buf, int inst)
694{
695    struct bcm539x_data *bd =
696        (struct bcm539x_data *)switch_get_drvdata(dev);
697    int ret;
698
699    /*
700     * disable 802.1Q VLANs
701     */
702    if (buf[0] != '1') {
703        ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0, 0);
704        return ret;
705    }
706
707    /*
708     * enable 802.1Q VLANs
709     *
710     * Enable 802.1Q | IVL learning
711     */
712    ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL0,
713                  (1 << 7) | (3 << 5));
714    if (ret) {
715        return ret;
716    }
717
718    /*
719     * RSV multicast fwd | RSV multicast chk
720     */
721    ret = bcm539x_write_8(bd, PAGE_VLAN, REG_VLAN_CTRL1,
722                  (1 << 2) | (1 << 3));
723    if (ret) {
724        return ret;
725    }
726#if 0
727    /*
728     * Drop invalid VID
729     */
730    ret = bcm539x_write_16(bd, PAGE_VLAN, REG_VLAN_CTRL3, 0x00FF);
731    if (ret) {
732        return ret;
733    }
734#endif
735    return 0;
736}
737
738/*
739 * bcm539x_handle_port_enable_read
740 */
741static int bcm539x_handle_port_enable_read(struct switch_device *dev,
742                       char *buf, int inst)
743{
744    return sprintf(buf, "%d\n", 1);
745}
746
747/*
748 * bcm539x_handle_port_enable_write
749 */
750static int bcm539x_handle_port_enable_write(struct switch_device *dev,
751                        char *buf, int inst)
752{
753    /*
754     * validate port
755     */
756    if (!(dev->port_mask[0] & (1 << inst))) {
757        return -EIO;
758    }
759
760    if (buf[0] != '1') {
761        printk(KERN_WARNING "switch port[%d] disabling is not supported\n", inst);
762    }
763    return 0;
764}
765
766/*
767 * bcm539x_handle_port_state_read
768 */
769static int bcm539x_handle_port_state_read(struct switch_device *dev,
770                       char *buf, int inst)
771{
772    struct bcm539x_data *bd =
773        (struct bcm539x_data *)switch_get_drvdata(dev);
774    int ret;
775    u16_t link;
776
777    /*
778     * validate port
779     */
780    if (!(dev->port_mask[0] & (1 << inst))) {
781        return -EIO;
782    }
783
784    /*
785     * check PHY link state - CPU port (port 8) is always up
786     */
787    ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
788    if (ret) {
789        return ret;
790    }
791    link |= (1 << 8);
792
793    return sprintf(buf, "%d\n", (link & (1 << inst)) ? 1 : 0);
794}
795
796/*
797 * bcm539x_handle_port_media_read
798 */
799static int bcm539x_handle_port_media_read(struct switch_device *dev,
800                       char *buf, int inst)
801{
802    struct bcm539x_data *bd =
803        (struct bcm539x_data *)switch_get_drvdata(dev);
804    int ret;
805    u16_t link, duplex;
806    u32_t speed;
807
808    /*
809     * validate port
810     */
811    if (!(dev->port_mask[0] & (1 << inst))) {
812        return -EIO;
813    }
814
815    /*
816     * check PHY link state first - CPU port (port 8) is always up
817     */
818    ret = bcm539x_read_16(bd, PAGE_STATUS, REG_LINK_STATUS, &link);
819    if (ret) {
820        return ret;
821    }
822    link |= (1 << 8);
823
824    if (!(link & (1 << inst))) {
825        return sprintf(buf, "UNKNOWN\n");
826    }
827
828    /*
829     * get link speeda dn duplex - CPU port (port 8) is 1000/full
830     */
831    ret = bcm539x_read_32(bd, PAGE_STATUS, 4, &speed);
832    if (ret) {
833        return ret;
834    }
835    speed |= (2 << 16);
836    speed = (speed >> (2 * inst)) & 3;
837
838    ret = bcm539x_read_16(bd, PAGE_STATUS, 8, &duplex);
839    if (ret) {
840        return ret;
841    }
842    duplex |= (1 << 8);
843    duplex = (duplex >> inst) & 1;
844
845    return sprintf(buf, "%d%cD\n",
846        (speed == 0) ? 10 : ((speed == 1) ? 100 : 1000),
847        duplex ? 'F' : 'H');
848}
849
850/*
851 * bcm539x_handle_port_meida_write
852 */
853static int bcm539x_handle_port_meida_write(struct switch_device *dev,
854                        char *buf, int inst)
855{
856    struct bcm539x_data *bd =
857        (struct bcm539x_data *)switch_get_drvdata(dev);
858    int ret;
859    u16_t ctrl_word, local_cap, local_giga_cap;
860
861    /*
862     * validate port (not for CPU port)
863     */
864    if (!(dev->port_mask[0] & (1 << inst) & ~(1 << 8))) {
865        return -EIO;
866    }
867
868    /*
869     * Get the maximum capability from status
870     * SPI reg[0x00] = PHY[0x0] --- MII control
871     * SPI reg[0x08] = PHY[0x4] --- MII local capability
872     * SPI reg[0x12] = PHY[0x9] --- GMII control
873     */
874    ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), &local_cap);
875    if (ret) {
876        return ret;
877    }
878    ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), &local_giga_cap);
879    if (ret) {
880        return ret;
881    }
882
883    /* Configure to the requested speed */
884    if (strncmp(buf, "1000FD", 6) == 0) {
885        /* speed */
886        local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
887        local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
888        local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
889        /* duplex */
890    } else if (strncmp(buf, "100FD", 5) == 0) {
891        /* speed */
892        local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
893        local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
894        local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
895        /* duplex */
896        local_cap &= ~(ADVERTISE_100HALF);
897    } else if (strncmp(buf, "100HD", 5) == 0) {
898        /* speed */
899        local_cap &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL);
900        local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
901        local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
902        /* duplex */
903        local_cap &= ~(ADVERTISE_100FULL);
904    } else if (strncmp(buf, "10FD", 4) == 0) {
905        /* speed */
906        local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
907        local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
908        local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
909        /* duplex */
910        local_cap &= ~(ADVERTISE_10HALF);
911    } else if (strncmp(buf, "10HD", 4) == 0) {
912        /* speed */
913        local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
914        local_cap &= ~(ADVERTISE_100HALF | ADVERTISE_100FULL);
915        local_giga_cap &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
916        /* duplex */
917        local_cap &= ~(ADVERTISE_10FULL);
918    } else if (strncmp(buf, "AUTO", 4) == 0) {
919        /* speed */
920        local_cap |= (ADVERTISE_10HALF | ADVERTISE_10FULL);
921        local_cap |= (ADVERTISE_100HALF | ADVERTISE_100FULL);
922        local_giga_cap |= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
923    } else {
924        return -EINVAL;
925    }
926
927    /* Active PHY with the requested speed for auto-negotiation */
928    ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_ADVERTISE << 1), local_cap);
929    if (ret) {
930        return ret;
931    }
932    ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_CTRL1000 << 1), local_giga_cap);
933    if (ret) {
934        return ret;
935    }
936
937    ret = bcm539x_read_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), &ctrl_word);
938    if (ret) {
939        return ret;
940    }
941    ctrl_word |= (BMCR_ANENABLE | BMCR_ANRESTART);
942    ret = bcm539x_write_16(bd, REG_MII_PAGE + inst, (MII_BMCR << 1), ctrl_word);
943    if (ret) {
944        return ret;
945    }
946
947    return 0;
948}
949
950/*
951 * proc_fs entries for this switch
952 */
953static const struct switch_handler bcm539x_switch_handlers[] = {
954    {
955        .name = "enable",
956        .read = bcm539x_handle_enable_read,
957        .write = bcm539x_handle_enable_write,
958    },
959    {
960        .name = "enable_vlan",
961        .read = bcm539x_handle_enable_vlan_read,
962        .write = bcm539x_handle_enable_vlan_write,
963    },
964    {
965        .name = "reset",
966        .write = bcm539x_handle_reset,
967    },
968    {
969    },
970};
971
972/*
973 * Handlers for <this_driver>/vlan
974 */
975static const struct switch_handler bcm539x_switch_handlers_vlan[] = {
976    {
977        .name = "delete",
978        .write = bcm539x_handle_vlan_delete_write,
979    },
980    {
981        .name = "create",
982        .write = bcm539x_handle_vlan_create_write,
983    },
984    {
985    },
986};
987
988/*
989 * Handlers for <this_driver>/port/<port number>
990 */
991static const struct switch_handler bcm539x_switch_handlers_port[] = {
992    {
993        .name = "enable",
994        .read = bcm539x_handle_port_enable_read,
995        .write = bcm539x_handle_port_enable_write,
996    },
997    {
998        .name = "state",
999        .read = bcm539x_handle_port_state_read,
1000    },
1001    {
1002        .name = "media",
1003        .read = bcm539x_handle_port_media_read,
1004        .write = bcm539x_handle_port_meida_write,
1005    },
1006    {
1007    },
1008};
1009
1010/*
1011 * bcm539x_probe
1012 */
1013static int __devinit bcm539x_probe(struct spi_device *spi)
1014{
1015    struct bcm539x_data *bd;
1016    struct switch_core_platform_data *pdata;
1017    struct switch_device *switch_dev = NULL;
1018    int i, ret;
1019    u8_t txbuf[2];
1020
1021    pdata = spi->dev.platform_data;
1022    if (!pdata) {
1023        return -EINVAL;
1024    }
1025
1026    ret = spi_setup(spi);
1027    if (ret < 0) {
1028        return ret;
1029    }
1030
1031    /*
1032     * Reset the chip if requested
1033     */
1034    if (pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
1035        ret = gpio_request(pdata->pin_reset, "switch-bcm539x-reset");
1036        if (ret) {
1037            printk(KERN_WARNING "Could not request reset\n");
1038            return -EINVAL;
1039        }
1040
1041        gpio_direction_output(pdata->pin_reset, 0);
1042        udelay(10);
1043        gpio_set_value(pdata->pin_reset, 1);
1044        udelay(20);
1045    }
1046
1047    /*
1048     * Allocate our private data structure
1049     */
1050    bd = kzalloc(sizeof(struct bcm539x_data), GFP_KERNEL);
1051    if (!bd) {
1052        return -ENOMEM;
1053    }
1054
1055    dev_set_drvdata(&spi->dev, bd);
1056    bd->pdata = pdata;
1057    bd->spi = spi;
1058    bd->last_page = 0xFF;
1059
1060    /*
1061     * First perform SW reset if needed
1062     */
1063    if (pdata->flags & SWITCH_DEV_FLAG_SW_RESET) {
1064        txbuf[0] = (1 << 7) | (1 << 4);
1065        ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
1066                      REG_CTRL_SRST, txbuf, 1);
1067        if (ret) {
1068            goto fail;
1069        }
1070
1071        udelay(20);
1072
1073        txbuf[0] = 0;
1074        ret = bcm539x_write_bytes(bd, PAGE_PORT_TC,
1075                      REG_CTRL_SRST, txbuf, 1);
1076        if (ret) {
1077            goto fail;
1078        }
1079    }
1080
1081    /*
1082     * See if we can see the chip
1083     */
1084    for (i = 0; i < 10; i++) {
1085        ret = bcm539x_read_bytes(bd, PAGE_MMR, REG_DEVICE_ID,
1086                     &bd->device_id, 1);
1087        if (!ret) {
1088            break;
1089        }
1090    }
1091    if (ret) {
1092        goto fail;
1093    }
1094
1095    /*
1096     * We only support 5395, 5397, 5398
1097     */
1098    if ((bd->device_id != 0x95) && (bd->device_id != 0x97) &&
1099        (bd->device_id != 0x98)) {
1100        ret = -ENODEV;
1101        goto fail;
1102    }
1103
1104    /*
1105     * Override CPU port config: fixed link @1000 with flow control
1106     */
1107    ret = bcm539x_read_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, txbuf);
1108    bcm539x_write_8(bd, PAGE_PORT_TC, REG_CTRL_MIIPO, 0xbb); // Override IMP port config
1109    printk("Broadcom SW CPU port setting: 0x%x -> 0xbb\n", txbuf[0]);
1110
1111    /*
1112     * Setup the switch driver structure
1113     */
1114    switch_dev = switch_alloc();
1115    if (!switch_dev) {
1116        ret = -ENOMEM;
1117        goto fail;
1118    }
1119    switch_dev->name = pdata->name;
1120
1121    switch_dev->ports = (bd->device_id == 0x98) ? 9 : 6;
1122    switch_dev->port_mask[0] = (bd->device_id == 0x98) ? 0x1FF : 0x11F;
1123    switch_dev->driver_handlers = bcm539x_switch_handlers;
1124    switch_dev->reg_handlers = NULL;
1125    switch_dev->vlan_handlers = bcm539x_switch_handlers_vlan;
1126    switch_dev->port_handlers = bcm539x_switch_handlers_port;
1127
1128    bd->switch_dev = switch_dev;
1129    switch_set_drvdata(switch_dev, (void *)bd);
1130
1131    ret = switch_register(bd->switch_dev);
1132    if (ret < 0) {
1133        goto fail;
1134    }
1135
1136    printk(KERN_INFO "bcm53%02x switch chip initialized\n", bd->device_id);
1137
1138    return ret;
1139
1140fail:
1141    if (switch_dev) {
1142        switch_release(switch_dev);
1143    }
1144    dev_set_drvdata(&spi->dev, NULL);
1145    kfree(bd);
1146    return ret;
1147}
1148
1149static int __attribute__((unused)) bcm539x_remove(struct spi_device *spi)
1150{
1151    struct bcm539x_data *bd;
1152
1153    bd = dev_get_drvdata(&spi->dev);
1154
1155    if (bd->pdata->flags & SWITCH_DEV_FLAG_HW_RESET) {
1156        gpio_free(bd->pdata->pin_reset);
1157    }
1158
1159    if (bd->switch_dev) {
1160        switch_unregister(bd->switch_dev);
1161        switch_release(bd->switch_dev);
1162    }
1163
1164    dev_set_drvdata(&spi->dev, NULL);
1165
1166    kfree(bd);
1167
1168    return 0;
1169}
1170
1171static struct spi_driver bcm539x_driver = {
1172    .driver = {
1173        .name = DRIVER_NAME,
1174        .owner = THIS_MODULE,
1175    },
1176    .probe = bcm539x_probe,
1177    .remove = __devexit_p(bcm539x_remove),
1178};
1179
1180static int __init bcm539x_init(void)
1181{
1182    return spi_register_driver(&bcm539x_driver);
1183}
1184
1185module_init(bcm539x_init);
1186
1187static void __exit bcm539x_exit(void)
1188{
1189    spi_unregister_driver(&bcm539x_driver);
1190}
1191module_exit(bcm539x_exit);
1192
1193MODULE_AUTHOR("Pat Tjin");
1194MODULE_LICENSE("GPL v2");
1195MODULE_DESCRIPTION("bcm539x SPI switch chip driver");
1196

Archive Download this file



interactive