Changeset 40542


Ignore:
Timestamp:
2014-04-22T10:08:02+02:00 (4 years ago)
Author:
blogic
Message:

linux/generic: add MIB counters and port status to ADM6996 switch

This patch adds port status information and MIB counters to the ADM6996
switch driver.

The driver supports also the older ADM6996L-variant, but I'm not able to
test this patch on that chip. According to the datasheet the same
registers exist there as well, so I think it should work, but any
feedback is appreciated.

Signed-off-by: Matti Laakso <malaakso at elisanet.fi>

Location:
trunk/target/linux/generic/files/drivers/net/phy
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic/files/drivers/net/phy/adm6996.c

    r38698 r40542  
    77 * VLAN support Copyright (c) 2010, 2011 Peter Lebbing <peter@digitalbrains.com> 
    88 * Copyright (c) 2013 Hauke Mehrtens <hauke@hauke-m.de> 
     9 * Copyright (c) 2014 Matti Laakso <malaakso@elisanet.fi> 
    910 * 
    1011 * This program is free software; you can redistribute  it and/or modify it 
     
    5556}; 
    5657 
     58struct adm6996_mib_desc { 
     59        unsigned int offset; 
     60        const char *name; 
     61}; 
     62 
    5763struct adm6996_priv { 
    5864        struct switch_dev dev; 
     
    7985        u8 vlan_table[ADM_NUM_VLANS];   /* bitmap, 1 = port is member */ 
    8086        u8 vlan_tagged[ADM_NUM_VLANS];  /* bitmap, 1 = tagged member */ 
     87         
     88        struct mutex mib_lock; 
     89        char buf[2048]; 
    8190 
    8291        struct mutex reg_mutex; 
     
    8998#define to_adm(_dev) container_of(_dev, struct adm6996_priv, dev) 
    9099#define phy_to_adm(_phy) ((struct adm6996_priv *) (_phy)->priv) 
     100 
     101#define MIB_DESC(_o, _n)        \ 
     102        {                       \ 
     103                .offset = (_o), \ 
     104                .name = (_n),   \ 
     105        } 
     106 
     107static const struct adm6996_mib_desc adm6996_mibs[] = { 
     108        MIB_DESC(ADM_CL0, "RxPacket"), 
     109        MIB_DESC(ADM_CL6, "RxByte"), 
     110        MIB_DESC(ADM_CL12, "TxPacket"), 
     111        MIB_DESC(ADM_CL18, "TxByte"), 
     112        MIB_DESC(ADM_CL24, "Collision"), 
     113        MIB_DESC(ADM_CL30, "Error"), 
     114}; 
    91115 
    92116static inline u16 
     
    771795        adm6996_perform_reset (priv); 
    772796        mutex_unlock(&priv->reg_mutex); 
     797        return 0; 
     798} 
     799 
     800static int 
     801adm6996_get_port_link(struct switch_dev *dev, int port, 
     802                struct switch_port_link *link) 
     803{ 
     804        struct adm6996_priv *priv = to_adm(dev); 
     805         
     806        u16 reg = 0; 
     807        u32 speed; 
     808         
     809        if (port >= ADM_NUM_PORTS) 
     810                return -EINVAL; 
     811         
     812        switch (port) { 
     813        case 0: 
     814                reg = r16(priv, ADM_PS0); 
     815                break; 
     816        case 1: 
     817                reg = r16(priv, ADM_PS0); 
     818                reg = reg >> 8; 
     819                break; 
     820        case 2: 
     821                reg = r16(priv, ADM_PS1); 
     822                break; 
     823        case 3: 
     824                reg = r16(priv, ADM_PS1); 
     825                reg = reg >> 8; 
     826                break; 
     827        case 4: 
     828                reg = r16(priv, ADM_PS1); 
     829                reg = reg >> 12; 
     830                break; 
     831        case 5: 
     832                reg = r16(priv, ADM_PS2); 
     833                /* Bits 0, 1, 3 and 4. */ 
     834                reg = (reg & 3) | ((reg & 24) >> 1); 
     835                break; 
     836        default: 
     837                return -EINVAL; 
     838        } 
     839         
     840        link->link = reg & ADM_PS_LS; 
     841        if (!link->link) 
     842                return 0; 
     843        link->aneg = true; 
     844        link->duplex = reg & ADM_PS_DS; 
     845        link->tx_flow = reg & ADM_PS_FCS; 
     846        link->rx_flow = reg & ADM_PS_FCS; 
     847        if (reg & ADM_PS_SS) 
     848                link->speed = SWITCH_PORT_SPEED_100; 
     849        else 
     850                link->speed = SWITCH_PORT_SPEED_10; 
     851 
     852        return 0; 
     853} 
     854 
     855static int 
     856adm6996_sw_get_port_mib(struct switch_dev *dev, 
     857                       const struct switch_attr *attr, 
     858                       struct switch_val *val) 
     859{ 
     860        struct adm6996_priv *priv = to_adm(dev); 
     861        int port; 
     862        char *buf = priv->buf; 
     863        int i, len = 0; 
     864        u32 reg = 0; 
     865 
     866        port = val->port_vlan; 
     867        if (port >= ADM_NUM_PORTS) 
     868                return -EINVAL; 
     869 
     870        mutex_lock(&priv->mib_lock); 
     871 
     872        len += snprintf(buf + len, sizeof(priv->buf) - len, 
     873                        "Port %d MIB counters\n", 
     874                        port); 
     875 
     876        for (i = 0; i < ARRAY_SIZE(adm6996_mibs); i++) { 
     877                reg = r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port)); 
     878                reg += r16(priv, adm6996_mibs[i].offset + ADM_OFFSET_PORT(port) + 1) << 16; 
     879                len += snprintf(buf + len, sizeof(priv->buf) - len, 
     880                                "%-12s: %lu\n", 
     881                                adm6996_mibs[i].name, 
     882                                reg); 
     883        } 
     884 
     885        mutex_unlock(&priv->mib_lock); 
     886 
     887        val->value.s = buf; 
     888        val->len = len; 
     889 
    773890        return 0; 
    774891} 
     
    803920 
    804921static struct switch_attr adm6996_port[] = { 
     922        { 
     923         .type = SWITCH_TYPE_STRING, 
     924         .name = "mib", 
     925         .description = "Get port's MIB counters", 
     926         .set = NULL, 
     927         .get = adm6996_sw_get_port_mib, 
     928        }, 
    805929}; 
    806930 
     
    834958        .apply_config = adm6996_hw_apply, 
    835959        .reset_switch = adm6996_reset_switch, 
     960        .get_port_link = adm6996_get_port_link, 
    836961}; 
    837962 
     
    9001025 
    9011026        mutex_init(&priv->reg_mutex); 
     1027        mutex_init(&priv->mib_lock); 
    9021028        priv->priv = pdev; 
    9031029        priv->read = adm6996_read_mii_reg; 
  • trunk/target/linux/generic/files/drivers/net/phy/adm6996.h

    r38698 r40542  
    5151                ADM_SIG0                = ADM_COUNTER_BASE + 0, 
    5252                ADM_SIG1                = ADM_COUNTER_BASE + 1, 
     53                ADM_PS0         = ADM_COUNTER_BASE + 2, 
     54                ADM_PS1         = ADM_COUNTER_BASE + 3, 
     55                ADM_PS2         = ADM_COUNTER_BASE + 4, 
     56                ADM_CL0         = ADM_COUNTER_BASE + 8, /* RxPacket */ 
     57                ADM_CL6         = ADM_COUNTER_BASE + 0x1a, /* RxByte */ 
     58                ADM_CL12                = ADM_COUNTER_BASE + 0x2c, /* TxPacket */ 
     59                ADM_CL18                = ADM_COUNTER_BASE + 0x3e, /* TxByte */ 
     60                ADM_CL24                = ADM_COUNTER_BASE + 0x50, /* Coll */ 
     61                ADM_CL30                = ADM_COUNTER_BASE + 0x62, /* Err */ 
     62#define ADM_OFFSET_PORT(n) ((n * 4) - (n / 4) * 2 - (n / 5) * 2) 
    5363        ADM_PHY_BASE            = 0x200, 
    5464#define ADM_PHY_PORT(n) (ADM_PHY_BASE + (0x20 * n)) 
     
    160170                        ((ports & 0x10) << 3) | ((ports & 0x20) << 3)) 
    161171 
     172/* Port status register */ 
     173enum { 
     174        ADM_PS_LS = (1 << 0),   /* Link status */ 
     175        ADM_PS_SS = (1 << 1),   /* Speed status */ 
     176        ADM_PS_DS = (1 << 2),   /* Duplex status */ 
     177        ADM_PS_FCS = (1 << 3)   /* Flow control status */ 
     178}; 
     179 
    162180/* 
    163181 * Split the register address in phy id and register 
Note: See TracChangeset for help on using the changeset viewer.