Changeset 33299 for trunk


Ignore:
Timestamp:
2012-08-29T12:37:36+02:00 (4 years ago)
Author:
juhosg
Message:

ramips: Add swconfig support to ramips_esw.c

Add swconfig support to ramips_esw.c

This patch adds swconfig support for ramips_esw:

Tested on both D-LINK DIR-300 B1 and Sitecom WL-351 (external
rtl8366rb on internal port 5).
I've made sure that in the enable_vlan=0 case it behaves like a dumb
switch, so external switches should work fine with vlans and
verified this on the WL-351.

The current state shown by swconfig is always read directly from HW
registers, new settings only show after 'swconfig dev rt305x set apply'.

Signed-off-by: Tobias Diedrich <ranma+openwrt@…>

Location:
trunk/target/linux/ramips/files/drivers/net/ethernet/ramips
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/ramips/files/drivers/net/ethernet/ramips/Kconfig

    r30680 r33299  
    33       depends on MIPS_RALINK 
    44       select PHYLIB if (SOC_RT288X || SOC_RT3883) 
     5       select SWCONFIG if SOC_RT305X 
    56       help 
    67         This driver supports the etehrnet mac inside the ralink wisocs 
  • trunk/target/linux/ramips/files/drivers/net/ethernet/ramips/ramips_esw.c

    r33298 r33299  
    11#include <linux/ioport.h> 
     2#include <linux/switch.h> 
    23 
    34#include <rt305x_regs.h> 
    45#include <rt305x_esw_platform.h> 
    56 
     7/* 
     8 * HW limitations for this switch: 
     9 * - No large frame support (PKT_MAX_LEN at most 1536) 
     10 * - Can't have untagged vlan and tagged vlan on one port at the same time, 
     11 *   though this might be possible using the undocumented PPE. 
     12 */ 
     13 
    614#define RT305X_ESW_REG_FCT0             0x08 
    715#define RT305X_ESW_REG_PFC1             0x14 
     16#define RT305X_ESW_REG_ATS              0x24 
     17#define RT305X_ESW_REG_ATS0             0x28 
     18#define RT305X_ESW_REG_ATS1             0x2c 
     19#define RT305X_ESW_REG_ATS2             0x30 
    820#define RT305X_ESW_REG_PVIDC(_n)        (0x40 + 4 * (_n)) 
    921#define RT305X_ESW_REG_VLANI(_n)        (0x50 + 4 * (_n)) 
    1022#define RT305X_ESW_REG_VMSC(_n)         (0x70 + 4 * (_n)) 
     23#define RT305X_ESW_REG_POA              0x80 
    1124#define RT305X_ESW_REG_FPA              0x84 
    1225#define RT305X_ESW_REG_SOCPC            0x8c 
     
    1528#define RT305X_ESW_REG_POC3             0x98 
    1629#define RT305X_ESW_REG_SGC              0x9c 
     30#define RT305X_ESW_REG_STRT             0xa0 
    1731#define RT305X_ESW_REG_PCR0             0xc0 
    1832#define RT305X_ESW_REG_PCR1             0xc4 
     
    2539#define RT305X_ESW_REG_P3LED            0xb0 
    2640#define RT305X_ESW_REG_P4LED            0xb4 
     41#define RT305X_ESW_REG_P0PC             0xe8 
     42#define RT305X_ESW_REG_P1PC             0xec 
     43#define RT305X_ESW_REG_P2PC             0xf0 
     44#define RT305X_ESW_REG_P3PC             0xf4 
     45#define RT305X_ESW_REG_P4PC             0xf8 
     46#define RT305X_ESW_REG_P5PC             0xfc 
     47 
     48#define RT305X_ESW_LED_LINK             0 
     49#define RT305X_ESW_LED_100M             1 
     50#define RT305X_ESW_LED_DUPLEX           2 
     51#define RT305X_ESW_LED_ACTIVITY         3 
     52#define RT305X_ESW_LED_COLLISION        4 
     53#define RT305X_ESW_LED_LINKACT          5 
     54#define RT305X_ESW_LED_DUPLCOLL         6 
     55#define RT305X_ESW_LED_10MACT           7 
     56#define RT305X_ESW_LED_100MACT          8 
     57/* Additional led states not in datasheet: */ 
     58#define RT305X_ESW_LED_BLINK            10 
     59#define RT305X_ESW_LED_ON               12 
     60 
     61#define RT305X_ESW_LINK_S               25 
     62#define RT305X_ESW_DUPLEX_S             9 
     63#define RT305X_ESW_SPD_S                0 
    2764 
    2865#define RT305X_ESW_PCR0_WT_NWAY_DATA_S  16 
     
    3269#define RT305X_ESW_PCR1_WT_DONE         BIT(0) 
    3370 
     71#define RT305X_ESW_ATS_TIMEOUT          (5 * HZ) 
    3472#define RT305X_ESW_PHY_TIMEOUT          (5 * HZ) 
    3573 
     
    5189#define RT305X_ESW_POC1_EN_FC_S         8 
    5290#define RT305X_ESW_POC1_DIS_RMC2CPU_S   16 
     91#define RT305X_ESW_POC1_DIS_PORT_M      0x7f 
    5392#define RT305X_ESW_POC1_DIS_PORT_S      23 
    5493 
     94#define RT305X_ESW_POC3_UNTAG_EN_M      0xff 
    5595#define RT305X_ESW_POC3_UNTAG_EN_S      0 
    5696#define RT305X_ESW_POC3_ENAGING_S       8 
    5797#define RT305X_ESW_POC3_DIS_UC_PAUSE_S  16 
     98 
     99#define RT305X_ESW_SGC2_DOUBLE_TAG_M    0x7f 
     100#define RT305X_ESW_SGC2_DOUBLE_TAG_S    0 
     101#define RT305X_ESW_SGC2_LAN_PMAP_M      0x3f 
     102#define RT305X_ESW_SGC2_LAN_PMAP_S      24 
     103 
     104#define RT305X_ESW_PFC1_EN_VLAN_M       0xff 
     105#define RT305X_ESW_PFC1_EN_VLAN_S       16 
     106#define RT305X_ESW_PFC1_EN_TOS_S        24 
     107 
     108#define RT305X_ESW_VLAN_NONE            0xfff 
    58109 
    59110#define RT305X_ESW_PORT0                0 
     
    65116#define RT305X_ESW_PORT6                6 
    66117 
     118#define RT305X_ESW_PORTS_NONE           0 
     119 
     120#define RT305X_ESW_PMAP_LLLLLL          0x3f 
     121#define RT305X_ESW_PMAP_LLLLWL          0x2f 
     122#define RT305X_ESW_PMAP_WLLLLL          0x3e 
     123 
    67124#define RT305X_ESW_PORTS_INTERNAL                                       \ 
    68125                (BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) |        \ 
     
    79136 
    80137#define RT305X_ESW_NUM_VLANS            16 
     138#define RT305X_ESW_NUM_VIDS             4096 
    81139#define RT305X_ESW_NUM_PORTS            7 
     140#define RT305X_ESW_NUM_LANWAN           6 
     141#define RT305X_ESW_NUM_LEDS             5 
     142 
     143enum { 
     144        /* Global attributes. */ 
     145        RT305X_ESW_ATTR_ENABLE_VLAN, 
     146        RT305X_ESW_ATTR_ALT_VLAN_DISABLE, 
     147        /* Port attributes. */ 
     148        RT305X_ESW_ATTR_PORT_DISABLE, 
     149        RT305X_ESW_ATTR_PORT_DOUBLETAG, 
     150        RT305X_ESW_ATTR_PORT_EN_VLAN, 
     151        RT305X_ESW_ATTR_PORT_UNTAG, 
     152        RT305X_ESW_ATTR_PORT_LED, 
     153        RT305X_ESW_ATTR_PORT_LAN, 
     154        RT305X_ESW_ATTR_PORT_RECV_BAD, 
     155        RT305X_ESW_ATTR_PORT_RECV_GOOD, 
     156}; 
     157 
     158struct rt305x_esw_port { 
     159        bool    disable; 
     160        bool    doubletag; 
     161        bool    untag; 
     162        bool    en_vlan; 
     163        u8      led; 
     164        u16     pvid; 
     165}; 
     166 
     167struct rt305x_esw_vlan { 
     168        u8      ports; 
     169        u16     vid; 
     170}; 
    82171 
    83172struct rt305x_esw { 
    84173        void __iomem            *base; 
    85174        struct rt305x_esw_platform_data *pdata; 
     175        /* Protects against concurrent register rmw operations. */ 
    86176        spinlock_t              reg_rw_lock; 
     177 
     178        struct switch_dev       swdev; 
     179        bool                    global_vlan_enable; 
     180        bool                    alt_vlan_disable; 
     181        struct rt305x_esw_vlan vlans[RT305X_ESW_NUM_VLANS]; 
     182        struct rt305x_esw_port ports[RT305X_ESW_NUM_PORTS]; 
     183 
    87184}; 
    88185 
     
    161258} 
    162259 
     260static unsigned 
     261rt305x_esw_get_vlan_id(struct rt305x_esw *esw, unsigned vlan) 
     262{ 
     263        unsigned s; 
     264        unsigned val; 
     265 
     266        s = RT305X_ESW_VLANI_VID_S * (vlan % 2); 
     267        val = rt305x_esw_rr(esw, RT305X_ESW_REG_VLANI(vlan / 2)); 
     268        val = (val >> s) & RT305X_ESW_VLANI_VID_M; 
     269 
     270        return val; 
     271} 
     272 
    163273static void 
    164274rt305x_esw_set_vlan_id(struct rt305x_esw *esw, unsigned vlan, unsigned vid) 
     
    173283} 
    174284 
     285static unsigned 
     286rt305x_esw_get_pvid(struct rt305x_esw *esw, unsigned port) 
     287{ 
     288        unsigned s, val; 
     289 
     290        s = RT305X_ESW_PVIDC_PVID_S * (port % 2); 
     291        val = rt305x_esw_rr(esw, RT305X_ESW_REG_PVIDC(port / 2)); 
     292        return (val >> s) & RT305X_ESW_PVIDC_PVID_M; 
     293} 
     294 
    175295static void 
    176296rt305x_esw_set_pvid(struct rt305x_esw *esw, unsigned port, unsigned pvid) 
     
    185305} 
    186306 
     307static unsigned 
     308rt305x_esw_get_vmsc(struct rt305x_esw *esw, unsigned vlan) 
     309{ 
     310        unsigned s, val; 
     311 
     312        s = RT305X_ESW_VMSC_MSC_S * (vlan % 4); 
     313        val = rt305x_esw_rr(esw, RT305X_ESW_REG_VMSC(vlan / 4)); 
     314        val = (val >> s) & RT305X_ESW_VMSC_MSC_M; 
     315 
     316        return val; 
     317} 
     318 
    187319static void 
    188320rt305x_esw_set_vmsc(struct rt305x_esw *esw, unsigned vlan, unsigned msc) 
     
    197329} 
    198330 
     331static int 
     332rt305x_esw_apply_config(struct switch_dev *dev); 
     333 
    199334static void 
    200335rt305x_esw_hw_init(struct rt305x_esw *esw) 
    201336{ 
    202337        int i; 
     338        u8 port_map = 0; 
    203339 
    204340        /* vodoo from original driver */ 
    205341        rt305x_esw_wr(esw, 0xC8A07850, RT305X_ESW_REG_FCT0); 
    206342        rt305x_esw_wr(esw, 0x00000000, RT305X_ESW_REG_SGC2); 
    207         rt305x_esw_wr(esw, 0x00405555, RT305X_ESW_REG_PFC1); 
     343        /* Port priority 1 for all ports, vlan enabled. */ 
     344        rt305x_esw_wr(esw, 0x00005555 | 
     345                      (RT305X_ESW_PORTS_ALL << RT305X_ESW_PFC1_EN_VLAN_S), 
     346                      RT305X_ESW_REG_PFC1); 
    208347 
    209348        /* Enable Back Pressure, and Flow Control */ 
     
    220359 
    221360        rt305x_esw_wr(esw, esw->pdata->reg_initval_fct2, RT305X_ESW_REG_FCT2); 
     361 
     362        /* 
     363         * 300s aging timer, max packet len 1536, broadcast storm prevention 
     364         * disabled, disable collision abort, mac xor48 hash, 10 packet back 
     365         * pressure jam, GMII disable was_transmit, back pressure disabled, 
     366         * 30ms led flash, unmatched IGMP as broadcast, rmc tb fault to all 
     367         * ports. 
     368         */ 
    222369        rt305x_esw_wr(esw, 0x0008a301, RT305X_ESW_REG_SGC); 
    223370 
     
    266413        rt305x_mii_write(esw, 0, 31, 0x8000); 
    267414 
     415        /* Set up logical config and apply. */ 
    268416        for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { 
    269                 rt305x_esw_set_vlan_id(esw, i, 0); 
    270                 rt305x_esw_set_vmsc(esw, i, 0); 
    271         } 
    272  
    273         for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) 
    274                 rt305x_esw_set_pvid(esw, i, 1); 
     417                esw->vlans[i].vid = RT305X_ESW_VLAN_NONE; 
     418                esw->vlans[i].ports = RT305X_ESW_PORTS_NONE; 
     419        } 
     420 
     421        for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { 
     422                esw->ports[i].pvid = 1; 
     423                esw->ports[i].en_vlan = 1; 
     424                esw->ports[i].untag = i != RT305X_ESW_PORT6; 
     425        } 
    275426 
    276427        switch (esw->pdata->vlan_config) { 
     428        case RT305X_ESW_VLAN_CONFIG_BYPASS: 
    277429        case RT305X_ESW_VLAN_CONFIG_NONE: 
    278                 break; 
    279  
    280         case RT305X_ESW_VLAN_CONFIG_BYPASS: 
    281                 /* Pass all vlan tags to all ports */ 
    282                 for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { 
    283                         rt305x_esw_set_vlan_id(esw, i, i+1); 
    284                         rt305x_esw_set_vmsc(esw, i, RT305X_ESW_PORTS_ALL); 
    285                 } 
    286                 /* Disable VLAN TAG removal, keep aging on. */ 
    287                 rt305x_esw_wr(esw, 
    288                               RT305X_ESW_PORTS_ALL << RT305X_ESW_POC3_ENAGING_S, 
    289                               RT305X_ESW_REG_POC3); 
     430                port_map = RT305X_ESW_PMAP_LLLLLL; 
     431                esw->global_vlan_enable = 0; 
    290432                break; 
    291433 
    292434        case RT305X_ESW_VLAN_CONFIG_LLLLW: 
    293                 rt305x_esw_set_vlan_id(esw, 0, 1); 
    294                 rt305x_esw_set_vlan_id(esw, 1, 2); 
    295                 rt305x_esw_set_pvid(esw, RT305X_ESW_PORT4, 2); 
    296  
    297                 rt305x_esw_set_vmsc(esw, 0, 
     435                port_map = RT305X_ESW_PMAP_LLLLWL; 
     436                esw->global_vlan_enable = 1; 
     437                esw->vlans[0].vid = 1; 
     438                esw->vlans[1].vid = 2; 
     439                esw->ports[4].pvid = 2; 
     440                esw->ports[5].disable = 1; 
     441                esw->vlans[0].ports = 
    298442                                BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT1) | 
    299443                                BIT(RT305X_ESW_PORT2) | BIT(RT305X_ESW_PORT3) | 
    300                                 BIT(RT305X_ESW_PORT6)); 
    301                 rt305x_esw_set_vmsc(esw, 1, 
    302                                 BIT(RT305X_ESW_PORT4) | BIT(RT305X_ESW_PORT6)); 
     444                                BIT(RT305X_ESW_PORT6); 
     445                esw->vlans[1].ports = 
     446                                BIT(RT305X_ESW_PORT4) | BIT(RT305X_ESW_PORT6); 
    303447                break; 
    304448 
    305449        case RT305X_ESW_VLAN_CONFIG_WLLLL: 
    306                 rt305x_esw_set_vlan_id(esw, 0, 1); 
    307                 rt305x_esw_set_vlan_id(esw, 1, 2); 
    308                 rt305x_esw_set_pvid(esw, RT305X_ESW_PORT0, 2); 
    309  
    310                 rt305x_esw_set_vmsc(esw, 0, 
    311                                 BIT(RT305X_ESW_PORT1) | BIT(RT305X_ESW_PORT2) | 
    312                                 BIT(RT305X_ESW_PORT3) | BIT(RT305X_ESW_PORT4) | 
    313                                 BIT(RT305X_ESW_PORT6)); 
    314                 rt305x_esw_set_vmsc(esw, 1, 
    315                                 BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT6)); 
     450                port_map = RT305X_ESW_PMAP_WLLLLL; 
     451                esw->global_vlan_enable = 1; 
     452                esw->vlans[0].vid = 1; 
     453                esw->vlans[1].vid = 2; 
     454                esw->ports[0].pvid = 2; 
     455                esw->ports[5].disable = 1; 
     456                esw->vlans[0].ports = 
     457                        BIT(RT305X_ESW_PORT1) | BIT(RT305X_ESW_PORT2) | 
     458                        BIT(RT305X_ESW_PORT3) | BIT(RT305X_ESW_PORT4) | 
     459                        BIT(RT305X_ESW_PORT6); 
     460                esw->vlans[1].ports = 
     461                                BIT(RT305X_ESW_PORT0) | BIT(RT305X_ESW_PORT6); 
    316462                break; 
    317463 
     
    319465                BUG(); 
    320466        } 
    321 } 
     467 
     468        /* 
     469         * Unused HW feature, but still nice to be consistent here... 
     470         * This is also exported to userspace ('lan' attribute) so it's 
     471         * conveniently usable to decide which ports go into the wan vlan by 
     472         * default. 
     473         */ 
     474        rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2, 
     475                       RT305X_ESW_SGC2_LAN_PMAP_M << RT305X_ESW_SGC2_LAN_PMAP_S, 
     476                       port_map << RT305X_ESW_SGC2_LAN_PMAP_S); 
     477 
     478        rt305x_esw_apply_config(&esw->swdev); 
     479} 
     480 
     481static int 
     482rt305x_esw_apply_config(struct switch_dev *dev) 
     483{ 
     484        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     485        int i; 
     486        u8 disable = 0; 
     487        u8 doubletag = 0; 
     488        u8 en_vlan = 0; 
     489        u8 untag = 0; 
     490 
     491        for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { 
     492                u32 vid, vmsc; 
     493                if (esw->global_vlan_enable) { 
     494                        vid = esw->vlans[i].vid; 
     495                        vmsc = esw->vlans[i].ports; 
     496                } else { 
     497                        vid = RT305X_ESW_VLAN_NONE; 
     498                        vmsc = RT305X_ESW_PORTS_NONE; 
     499                } 
     500                rt305x_esw_set_vlan_id(esw, i, vid); 
     501                rt305x_esw_set_vmsc(esw, i, vmsc); 
     502        } 
     503 
     504        for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { 
     505                u32 pvid; 
     506                disable |= esw->ports[i].disable << i; 
     507                if (esw->global_vlan_enable) { 
     508                        doubletag |= esw->ports[i].doubletag << i; 
     509                        en_vlan   |= esw->ports[i].en_vlan   << i; 
     510                        untag     |= esw->ports[i].untag     << i; 
     511                        pvid       = esw->ports[i].pvid; 
     512                } else { 
     513                        int x = esw->alt_vlan_disable ? 1 : 0; 
     514                        doubletag |= x << i; 
     515                        en_vlan   |= x << i; 
     516                        untag     |= x << i; 
     517                        pvid       = 0; 
     518                } 
     519                rt305x_esw_set_pvid(esw, i, pvid); 
     520                if (i < RT305X_ESW_NUM_LEDS) 
     521                        rt305x_esw_wr(esw, esw->ports[i].led, 
     522                                      RT305X_ESW_REG_P0LED + 4*i); 
     523        } 
     524 
     525        rt305x_esw_rmw(esw, RT305X_ESW_REG_POC1, 
     526                       RT305X_ESW_POC1_DIS_PORT_M << RT305X_ESW_POC1_DIS_PORT_S, 
     527                       disable << RT305X_ESW_POC1_DIS_PORT_S); 
     528        rt305x_esw_rmw(esw, RT305X_ESW_REG_SGC2, 
     529                       (RT305X_ESW_SGC2_DOUBLE_TAG_M << 
     530                        RT305X_ESW_SGC2_DOUBLE_TAG_S), 
     531                       doubletag << RT305X_ESW_SGC2_DOUBLE_TAG_S); 
     532        rt305x_esw_rmw(esw, RT305X_ESW_REG_PFC1, 
     533                       RT305X_ESW_PFC1_EN_VLAN_M << RT305X_ESW_PFC1_EN_VLAN_S, 
     534                       en_vlan << RT305X_ESW_PFC1_EN_VLAN_S); 
     535        rt305x_esw_rmw(esw, RT305X_ESW_REG_POC3, 
     536                       RT305X_ESW_POC3_UNTAG_EN_M << RT305X_ESW_POC3_UNTAG_EN_S, 
     537                       untag << RT305X_ESW_POC3_UNTAG_EN_S); 
     538 
     539        if (!esw->global_vlan_enable) { 
     540                /* 
     541                 * Still need to put all ports into vlan 0 or they'll be 
     542                 * isolated. 
     543                 * NOTE: vlan 0 is special, no vlan tag is prepended 
     544                 */ 
     545                rt305x_esw_set_vlan_id(esw, 0, 0); 
     546                rt305x_esw_set_vmsc(esw, 0, RT305X_ESW_PORTS_ALL); 
     547        } 
     548 
     549        return 0; 
     550} 
     551 
     552static int 
     553rt305x_esw_reset_switch(struct switch_dev *dev) 
     554{ 
     555        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     556        esw->global_vlan_enable = 0; 
     557        memset(esw->ports, 0, sizeof(esw->ports)); 
     558        memset(esw->vlans, 0, sizeof(esw->vlans)); 
     559        rt305x_esw_hw_init(esw); 
     560 
     561        return 0; 
     562} 
     563 
     564static int 
     565rt305x_esw_get_vlan_enable(struct switch_dev *dev, 
     566                           const struct switch_attr *attr, 
     567                           struct switch_val *val) 
     568{ 
     569        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     570 
     571        val->value.i = esw->global_vlan_enable; 
     572 
     573        return 0; 
     574} 
     575 
     576static int 
     577rt305x_esw_set_vlan_enable(struct switch_dev *dev, 
     578                           const struct switch_attr *attr, 
     579                           struct switch_val *val) 
     580{ 
     581        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     582 
     583        esw->global_vlan_enable = val->value.i != 0; 
     584 
     585        return 0; 
     586} 
     587 
     588static int 
     589rt305x_esw_get_alt_vlan_disable(struct switch_dev *dev, 
     590                                const struct switch_attr *attr, 
     591                                struct switch_val *val) 
     592{ 
     593        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     594 
     595        val->value.i = esw->alt_vlan_disable; 
     596 
     597        return 0; 
     598} 
     599 
     600static int 
     601rt305x_esw_set_alt_vlan_disable(struct switch_dev *dev, 
     602                                const struct switch_attr *attr, 
     603                                struct switch_val *val) 
     604{ 
     605        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     606 
     607        esw->alt_vlan_disable = val->value.i != 0; 
     608 
     609        return 0; 
     610} 
     611 
     612static int 
     613rt305x_esw_get_port_link(struct switch_dev *dev, 
     614                         int port, 
     615                         struct switch_port_link *link) 
     616{ 
     617        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     618        u32 speed, poa; 
     619 
     620        if (port < 0 || port >= RT305X_ESW_NUM_PORTS) 
     621                return -EINVAL; 
     622 
     623        poa = rt305x_esw_rr(esw, RT305X_ESW_REG_POA) >> port; 
     624 
     625        link->link = (poa >> RT305X_ESW_LINK_S) & 1; 
     626        link->duplex = (poa >> RT305X_ESW_DUPLEX_S) & 1; 
     627        if (port < RT305X_ESW_NUM_LEDS) { 
     628                speed = (poa >> RT305X_ESW_SPD_S) & 1; 
     629        } else { 
     630                if (port == RT305X_ESW_NUM_PORTS - 1) 
     631                        poa >>= 1; 
     632                speed = (poa >> RT305X_ESW_SPD_S) & 3; 
     633        } 
     634        switch (speed) { 
     635        case 0: 
     636                link->speed = SWITCH_PORT_SPEED_10; 
     637                break; 
     638        case 1: 
     639                link->speed = SWITCH_PORT_SPEED_100; 
     640                break; 
     641        case 2: 
     642        case 3: /* forced gige speed can be 2 or 3 */ 
     643                link->speed = SWITCH_PORT_SPEED_1000; 
     644                break; 
     645        default: 
     646                link->speed = SWITCH_PORT_SPEED_UNKNOWN; 
     647                break; 
     648        } 
     649 
     650        return 0; 
     651} 
     652 
     653static int 
     654rt305x_esw_get_port_bool(struct switch_dev *dev, 
     655                         const struct switch_attr *attr, 
     656                         struct switch_val *val) 
     657{ 
     658        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     659        int idx = val->port_vlan; 
     660        u32 x, reg, shift; 
     661 
     662        if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS) 
     663                return -EINVAL; 
     664 
     665        switch (attr->id) { 
     666        case RT305X_ESW_ATTR_PORT_DISABLE: 
     667                reg = RT305X_ESW_REG_POC1; 
     668                shift = RT305X_ESW_POC1_DIS_PORT_S; 
     669                break; 
     670        case RT305X_ESW_ATTR_PORT_DOUBLETAG: 
     671                reg = RT305X_ESW_REG_SGC2; 
     672                shift = RT305X_ESW_SGC2_DOUBLE_TAG_S; 
     673                break; 
     674        case RT305X_ESW_ATTR_PORT_EN_VLAN: 
     675                reg = RT305X_ESW_REG_PFC1; 
     676                shift = RT305X_ESW_PFC1_EN_VLAN_S; 
     677                break; 
     678        case RT305X_ESW_ATTR_PORT_UNTAG: 
     679                reg = RT305X_ESW_REG_POC3; 
     680                shift = RT305X_ESW_POC3_UNTAG_EN_S; 
     681                break; 
     682        case RT305X_ESW_ATTR_PORT_LAN: 
     683                reg = RT305X_ESW_REG_SGC2; 
     684                shift = RT305X_ESW_SGC2_LAN_PMAP_S; 
     685                if (idx >= RT305X_ESW_NUM_LANWAN) 
     686                        return -EINVAL; 
     687                break; 
     688        default: 
     689                return -EINVAL; 
     690        } 
     691 
     692        x = rt305x_esw_rr(esw, reg); 
     693        val->value.i = (x >> (idx + shift)) & 1; 
     694 
     695        return 0; 
     696} 
     697 
     698static int 
     699rt305x_esw_set_port_bool(struct switch_dev *dev, 
     700                         const struct switch_attr *attr, 
     701                         struct switch_val *val) 
     702{ 
     703        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     704        int idx = val->port_vlan; 
     705 
     706        if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || 
     707            val->value.i < 0 || val->value.i > 1) 
     708                return -EINVAL; 
     709 
     710        switch (attr->id) { 
     711        case RT305X_ESW_ATTR_PORT_DISABLE: 
     712                esw->ports[idx].disable = val->value.i; 
     713                break; 
     714        case RT305X_ESW_ATTR_PORT_DOUBLETAG: 
     715                esw->ports[idx].doubletag = val->value.i; 
     716                break; 
     717        case RT305X_ESW_ATTR_PORT_EN_VLAN: 
     718                esw->ports[idx].en_vlan = val->value.i; 
     719                break; 
     720        case RT305X_ESW_ATTR_PORT_UNTAG: 
     721                esw->ports[idx].untag = val->value.i; 
     722                break; 
     723        default: 
     724                return -EINVAL; 
     725        } 
     726 
     727        return 0; 
     728} 
     729 
     730static int 
     731rt305x_esw_get_port_recv_badgood(struct switch_dev *dev, 
     732                                 const struct switch_attr *attr, 
     733                                 struct switch_val *val) 
     734{ 
     735        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     736        int idx = val->port_vlan; 
     737        int shift = attr->id == RT305X_ESW_ATTR_PORT_RECV_GOOD ? 0 : 16; 
     738 
     739        if (idx < 0 || idx >= RT305X_ESW_NUM_LANWAN) 
     740                return -EINVAL; 
     741 
     742        val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0PC + 4*idx) >> shift; 
     743 
     744        return 0; 
     745} 
     746 
     747static int 
     748rt305x_esw_get_port_led(struct switch_dev *dev, 
     749                        const struct switch_attr *attr, 
     750                        struct switch_val *val) 
     751{ 
     752        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     753        int idx = val->port_vlan; 
     754 
     755        if (idx < 0 || idx >= RT305X_ESW_NUM_PORTS || 
     756            idx >= RT305X_ESW_NUM_LEDS) 
     757                return -EINVAL; 
     758 
     759        val->value.i = rt305x_esw_rr(esw, RT305X_ESW_REG_P0LED + 4*idx); 
     760 
     761        return 0; 
     762} 
     763 
     764static int 
     765rt305x_esw_set_port_led(struct switch_dev *dev, 
     766                        const struct switch_attr *attr, 
     767                        struct switch_val *val) 
     768{ 
     769        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     770        int idx = val->port_vlan; 
     771 
     772        if (idx < 0 || idx >= RT305X_ESW_NUM_LEDS) 
     773                return -EINVAL; 
     774 
     775        esw->ports[idx].led = val->value.i; 
     776 
     777        return 0; 
     778} 
     779 
     780static int 
     781rt305x_esw_get_port_pvid(struct switch_dev *dev, int port, int *val) 
     782{ 
     783        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     784 
     785        if (port >= RT305X_ESW_NUM_PORTS) 
     786                return -EINVAL; 
     787 
     788        *val = rt305x_esw_get_pvid(esw, port); 
     789 
     790        return 0; 
     791} 
     792 
     793static int 
     794rt305x_esw_set_port_pvid(struct switch_dev *dev, int port, int val) 
     795{ 
     796        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     797 
     798        if (port >= RT305X_ESW_NUM_PORTS) 
     799                return -EINVAL; 
     800 
     801        esw->ports[port].pvid = val; 
     802 
     803        return 0; 
     804} 
     805 
     806static int 
     807rt305x_esw_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) 
     808{ 
     809        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     810        u32 vmsc, poc3; 
     811        int vlan_idx = -1; 
     812        int i; 
     813 
     814        val->len = 0; 
     815 
     816        if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS) 
     817                return -EINVAL; 
     818 
     819        /* valid vlan? */ 
     820        for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { 
     821                if (rt305x_esw_get_vlan_id(esw, i) == val->port_vlan && 
     822                    rt305x_esw_get_vmsc(esw, i) != RT305X_ESW_PORTS_NONE) { 
     823                        vlan_idx = i; 
     824                        break; 
     825                } 
     826        } 
     827 
     828        if (vlan_idx == -1) 
     829                return -EINVAL; 
     830 
     831        vmsc = rt305x_esw_get_vmsc(esw, vlan_idx); 
     832        poc3 = rt305x_esw_rr(esw, RT305X_ESW_REG_POC3); 
     833 
     834        for (i = 0; i < RT305X_ESW_NUM_PORTS; i++) { 
     835                struct switch_port *p; 
     836                int port_mask = 1 << i; 
     837 
     838                if (!(vmsc & port_mask)) 
     839                        continue; 
     840 
     841                p = &val->value.ports[val->len++]; 
     842                p->id = i; 
     843                if (poc3 & (port_mask << RT305X_ESW_POC3_UNTAG_EN_S)) 
     844                        p->flags = 0; 
     845                else 
     846                        p->flags = 1 << SWITCH_PORT_FLAG_TAGGED; 
     847        } 
     848 
     849        return 0; 
     850} 
     851 
     852static int 
     853rt305x_esw_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) 
     854{ 
     855        struct rt305x_esw *esw = container_of(dev, struct rt305x_esw, swdev); 
     856        int ports; 
     857        int vlan_idx = -1; 
     858        int i; 
     859 
     860        if (val->port_vlan < 0 || val->port_vlan >= RT305X_ESW_NUM_VIDS || 
     861            val->len > RT305X_ESW_NUM_PORTS) 
     862                return -EINVAL; 
     863 
     864        /* one of the already defined vlans? */ 
     865        for (i = 0; i < RT305X_ESW_NUM_VLANS; i++) { 
     866                if (esw->vlans[i].vid == val->port_vlan && 
     867                    esw->vlans[i].ports != RT305X_ESW_PORTS_NONE) { 
     868                        vlan_idx = i; 
     869                        break; 
     870                } 
     871        } 
     872 
     873        /* select a free slot */ 
     874        for (i = 0; vlan_idx == -1 && i < RT305X_ESW_NUM_VLANS; i++) { 
     875                if (esw->vlans[i].ports == RT305X_ESW_PORTS_NONE) 
     876                        vlan_idx = i; 
     877        } 
     878 
     879        /* bail if all slots are in use */ 
     880        if (vlan_idx == -1) 
     881                return -EINVAL; 
     882 
     883        ports = RT305X_ESW_PORTS_NONE; 
     884        for (i = 0; i < val->len; i++) { 
     885                struct switch_port *p = &val->value.ports[i]; 
     886                int port_mask = 1 << p->id; 
     887                bool untagged = !(p->flags & (1 << SWITCH_PORT_FLAG_TAGGED)); 
     888 
     889                if (p->id >= RT305X_ESW_NUM_PORTS) 
     890                        return -EINVAL; 
     891 
     892                ports |= port_mask; 
     893                esw->ports[p->id].untag = untagged; 
     894        } 
     895        esw->vlans[vlan_idx].ports = ports; 
     896        if (ports == RT305X_ESW_PORTS_NONE) 
     897                esw->vlans[vlan_idx].vid = RT305X_ESW_VLAN_NONE; 
     898        else 
     899                esw->vlans[vlan_idx].vid = val->port_vlan; 
     900 
     901        return 0; 
     902} 
     903 
     904static const struct switch_attr rt305x_esw_global[] = { 
     905        { 
     906                .type = SWITCH_TYPE_INT, 
     907                .name = "enable_vlan", 
     908                .description = "VLAN mode (1:enabled)", 
     909                .max = 1, 
     910                .id = RT305X_ESW_ATTR_ENABLE_VLAN, 
     911                .get = rt305x_esw_get_vlan_enable, 
     912                .set = rt305x_esw_set_vlan_enable, 
     913        }, 
     914        { 
     915                .type = SWITCH_TYPE_INT, 
     916                .name = "alternate_vlan_disable", 
     917                .description = "Use en_vlan instead of doubletag to disable" 
     918                                " VLAN mode", 
     919                .max = 1, 
     920                .id = RT305X_ESW_ATTR_ALT_VLAN_DISABLE, 
     921                .get = rt305x_esw_get_alt_vlan_disable, 
     922                .set = rt305x_esw_set_alt_vlan_disable, 
     923        }, 
     924}; 
     925 
     926static const struct switch_attr rt305x_esw_port[] = { 
     927        { 
     928                .type = SWITCH_TYPE_INT, 
     929                .name = "disable", 
     930                .description = "Port state (1:disabled)", 
     931                .max = 1, 
     932                .id = RT305X_ESW_ATTR_PORT_DISABLE, 
     933                .get = rt305x_esw_get_port_bool, 
     934                .set = rt305x_esw_set_port_bool, 
     935        }, 
     936        { 
     937                .type = SWITCH_TYPE_INT, 
     938                .name = "doubletag", 
     939                .description = "Double tagging for incoming vlan packets " 
     940                                "(1:enabled)", 
     941                .max = 1, 
     942                .id = RT305X_ESW_ATTR_PORT_DOUBLETAG, 
     943                .get = rt305x_esw_get_port_bool, 
     944                .set = rt305x_esw_set_port_bool, 
     945        }, 
     946        { 
     947                .type = SWITCH_TYPE_INT, 
     948                .name = "en_vlan", 
     949                .description = "VLAN enabled (1:enabled)", 
     950                .max = 1, 
     951                .id = RT305X_ESW_ATTR_PORT_EN_VLAN, 
     952                .get = rt305x_esw_get_port_bool, 
     953                .set = rt305x_esw_set_port_bool, 
     954        }, 
     955        { 
     956                .type = SWITCH_TYPE_INT, 
     957                .name = "untag", 
     958                .description = "Untag (1:strip outgoing vlan tag)", 
     959                .max = 1, 
     960                .id = RT305X_ESW_ATTR_PORT_UNTAG, 
     961                .get = rt305x_esw_get_port_bool, 
     962                .set = rt305x_esw_set_port_bool, 
     963        }, 
     964        { 
     965                .type = SWITCH_TYPE_INT, 
     966                .name = "led", 
     967                .description = "LED mode (0:link, 1:100m, 2:duplex, 3:activity," 
     968                                " 4:collision, 5:linkact, 6:duplcoll, 7:10mact," 
     969                                " 8:100mact, 10:blink, 12:on)", 
     970                .max = 15, 
     971                .id = RT305X_ESW_ATTR_PORT_LED, 
     972                .get = rt305x_esw_get_port_led, 
     973                .set = rt305x_esw_set_port_led, 
     974        }, 
     975        { 
     976                .type = SWITCH_TYPE_INT, 
     977                .name = "lan", 
     978                .description = "HW port group (0:wan, 1:lan)", 
     979                .max = 1, 
     980                .id = RT305X_ESW_ATTR_PORT_LAN, 
     981                .get = rt305x_esw_get_port_bool, 
     982        }, 
     983        { 
     984                .type = SWITCH_TYPE_INT, 
     985                .name = "recv_bad", 
     986                .description = "Receive bad packet counter", 
     987                .id = RT305X_ESW_ATTR_PORT_RECV_BAD, 
     988                .get = rt305x_esw_get_port_recv_badgood, 
     989        }, 
     990        { 
     991                .type = SWITCH_TYPE_INT, 
     992                .name = "recv_good", 
     993                .description = "Receive good packet counter", 
     994                .id = RT305X_ESW_ATTR_PORT_RECV_GOOD, 
     995                .get = rt305x_esw_get_port_recv_badgood, 
     996        }, 
     997}; 
     998 
     999static const struct switch_attr rt305x_esw_vlan[] = { 
     1000}; 
     1001 
     1002static const struct switch_dev_ops rt305x_esw_ops = { 
     1003        .attr_global = { 
     1004                .attr = rt305x_esw_global, 
     1005                .n_attr = ARRAY_SIZE(rt305x_esw_global), 
     1006        }, 
     1007        .attr_port = { 
     1008                .attr = rt305x_esw_port, 
     1009                .n_attr = ARRAY_SIZE(rt305x_esw_port), 
     1010        }, 
     1011        .attr_vlan = { 
     1012                .attr = rt305x_esw_vlan, 
     1013                .n_attr = ARRAY_SIZE(rt305x_esw_vlan), 
     1014        }, 
     1015        .get_vlan_ports = rt305x_esw_get_vlan_ports, 
     1016        .set_vlan_ports = rt305x_esw_set_vlan_ports, 
     1017        .get_port_pvid = rt305x_esw_get_port_pvid, 
     1018        .set_port_pvid = rt305x_esw_set_port_pvid, 
     1019        .get_port_link = rt305x_esw_get_port_link, 
     1020        .apply_config = rt305x_esw_apply_config, 
     1021        .reset_switch = rt305x_esw_reset_switch, 
     1022}; 
    3221023 
    3231024static int 
     
    3261027        struct rt305x_esw_platform_data *pdata; 
    3271028        struct rt305x_esw *esw; 
     1029        struct switch_dev *swdev; 
    3281030        struct resource *res; 
    3291031        int err; 
     
    3521054        } 
    3531055 
     1056        swdev = &esw->swdev; 
     1057        swdev->name = "rt305x-esw"; 
     1058        swdev->alias = "rt305x"; 
     1059        swdev->cpu_port = RT305X_ESW_PORT6; 
     1060        swdev->ports = RT305X_ESW_NUM_PORTS; 
     1061        swdev->vlans = RT305X_ESW_NUM_VIDS; 
     1062        swdev->ops = &rt305x_esw_ops; 
     1063 
     1064        err = register_switch(swdev, NULL); 
     1065        if (err < 0) { 
     1066                dev_err(&pdev->dev, "register_switch failed\n"); 
     1067                goto unmap_base; 
     1068        } 
     1069 
    3541070        platform_set_drvdata(pdev, esw); 
    3551071 
     
    3601076        return 0; 
    3611077 
     1078unmap_base: 
     1079        iounmap(esw->base); 
    3621080free_esw: 
    3631081        kfree(esw); 
     
    3721090        esw = platform_get_drvdata(pdev); 
    3731091        if (esw) { 
     1092                unregister_switch(&esw->swdev); 
    3741093                platform_set_drvdata(pdev, NULL); 
    3751094                iounmap(esw->base); 
Note: See TracChangeset for help on using the changeset viewer.