linux/drivers/net/dsa/bcm_sf2.c
<<
>>
Prefs
   1/*
   2 * Broadcom Starfighter 2 DSA switch driver
   3 *
   4 * Copyright (C) 2014, Broadcom Corporation
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation; either version 2 of the License, or
   9 * (at your option) any later version.
  10 */
  11
  12#include <linux/list.h>
  13#include <linux/module.h>
  14#include <linux/netdevice.h>
  15#include <linux/interrupt.h>
  16#include <linux/platform_device.h>
  17#include <linux/of.h>
  18#include <linux/phy.h>
  19#include <linux/phy_fixed.h>
  20#include <linux/mii.h>
  21#include <linux/of.h>
  22#include <linux/of_irq.h>
  23#include <linux/of_address.h>
  24#include <net/dsa.h>
  25#include <linux/ethtool.h>
  26
  27#include "bcm_sf2.h"
  28#include "bcm_sf2_regs.h"
  29
  30/* String, offset, and register size in bytes if different from 4 bytes */
  31static const struct bcm_sf2_hw_stats bcm_sf2_mib[] = {
  32        { "TxOctets",           0x000, 8        },
  33        { "TxDropPkts",         0x020           },
  34        { "TxQPKTQ0",           0x030           },
  35        { "TxBroadcastPkts",    0x040           },
  36        { "TxMulticastPkts",    0x050           },
  37        { "TxUnicastPKts",      0x060           },
  38        { "TxCollisions",       0x070           },
  39        { "TxSingleCollision",  0x080           },
  40        { "TxMultipleCollision", 0x090          },
  41        { "TxDeferredCollision", 0x0a0          },
  42        { "TxLateCollision",    0x0b0           },
  43        { "TxExcessiveCollision", 0x0c0         },
  44        { "TxFrameInDisc",      0x0d0           },
  45        { "TxPausePkts",        0x0e0           },
  46        { "TxQPKTQ1",           0x0f0           },
  47        { "TxQPKTQ2",           0x100           },
  48        { "TxQPKTQ3",           0x110           },
  49        { "TxQPKTQ4",           0x120           },
  50        { "TxQPKTQ5",           0x130           },
  51        { "RxOctets",           0x140, 8        },
  52        { "RxUndersizePkts",    0x160           },
  53        { "RxPausePkts",        0x170           },
  54        { "RxPkts64Octets",     0x180           },
  55        { "RxPkts65to127Octets", 0x190          },
  56        { "RxPkts128to255Octets", 0x1a0         },
  57        { "RxPkts256to511Octets", 0x1b0         },
  58        { "RxPkts512to1023Octets", 0x1c0        },
  59        { "RxPkts1024toMaxPktsOctets", 0x1d0    },
  60        { "RxOversizePkts",     0x1e0           },
  61        { "RxJabbers",          0x1f0           },
  62        { "RxAlignmentErrors",  0x200           },
  63        { "RxFCSErrors",        0x210           },
  64        { "RxGoodOctets",       0x220, 8        },
  65        { "RxDropPkts",         0x240           },
  66        { "RxUnicastPkts",      0x250           },
  67        { "RxMulticastPkts",    0x260           },
  68        { "RxBroadcastPkts",    0x270           },
  69        { "RxSAChanges",        0x280           },
  70        { "RxFragments",        0x290           },
  71        { "RxJumboPkt",         0x2a0           },
  72        { "RxSymblErr",         0x2b0           },
  73        { "InRangeErrCount",    0x2c0           },
  74        { "OutRangeErrCount",   0x2d0           },
  75        { "EEELpiEvent",        0x2e0           },
  76        { "EEELpiDuration",     0x2f0           },
  77        { "RxDiscard",          0x300, 8        },
  78        { "TxQPKTQ6",           0x320           },
  79        { "TxQPKTQ7",           0x330           },
  80        { "TxPkts64Octets",     0x340           },
  81        { "TxPkts65to127Octets", 0x350          },
  82        { "TxPkts128to255Octets", 0x360         },
  83        { "TxPkts256to511Ocets", 0x370          },
  84        { "TxPkts512to1023Ocets", 0x380         },
  85        { "TxPkts1024toMaxPktOcets", 0x390      },
  86};
  87
  88#define BCM_SF2_STATS_SIZE      ARRAY_SIZE(bcm_sf2_mib)
  89
  90static void bcm_sf2_sw_get_strings(struct dsa_switch *ds,
  91                                   int port, uint8_t *data)
  92{
  93        unsigned int i;
  94
  95        for (i = 0; i < BCM_SF2_STATS_SIZE; i++)
  96                memcpy(data + i * ETH_GSTRING_LEN,
  97                       bcm_sf2_mib[i].string, ETH_GSTRING_LEN);
  98}
  99
 100static void bcm_sf2_sw_get_ethtool_stats(struct dsa_switch *ds,
 101                                         int port, uint64_t *data)
 102{
 103        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 104        const struct bcm_sf2_hw_stats *s;
 105        unsigned int i;
 106        u64 val = 0;
 107        u32 offset;
 108
 109        mutex_lock(&priv->stats_mutex);
 110
 111        /* Now fetch the per-port counters */
 112        for (i = 0; i < BCM_SF2_STATS_SIZE; i++) {
 113                s = &bcm_sf2_mib[i];
 114
 115                /* Do a latched 64-bit read if needed */
 116                offset = s->reg + CORE_P_MIB_OFFSET(port);
 117                if (s->sizeof_stat == 8)
 118                        val = core_readq(priv, offset);
 119                else
 120                        val = core_readl(priv, offset);
 121
 122                data[i] = (u64)val;
 123        }
 124
 125        mutex_unlock(&priv->stats_mutex);
 126}
 127
 128static int bcm_sf2_sw_get_sset_count(struct dsa_switch *ds)
 129{
 130        return BCM_SF2_STATS_SIZE;
 131}
 132
 133static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr)
 134{
 135        return "Broadcom Starfighter 2";
 136}
 137
 138static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
 139{
 140        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 141        unsigned int i;
 142        u32 reg;
 143
 144        /* Enable the IMP Port to be in the same VLAN as the other ports
 145         * on a per-port basis such that we only have Port i and IMP in
 146         * the same VLAN.
 147         */
 148        for (i = 0; i < priv->hw_params.num_ports; i++) {
 149                if (!((1 << i) & ds->phys_port_mask))
 150                        continue;
 151
 152                reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
 153                reg |= (1 << cpu_port);
 154                core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(i));
 155        }
 156}
 157
 158static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 159{
 160        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 161        u32 reg, val;
 162
 163        /* Enable the port memories */
 164        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
 165        reg &= ~P_TXQ_PSM_VDD(port);
 166        core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 167
 168        /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
 169        reg = core_readl(priv, CORE_IMP_CTL);
 170        reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
 171        reg &= ~(RX_DIS | TX_DIS);
 172        core_writel(priv, reg, CORE_IMP_CTL);
 173
 174        /* Enable forwarding */
 175        core_writel(priv, SW_FWDG_EN, CORE_SWMODE);
 176
 177        /* Enable IMP port in dumb mode */
 178        reg = core_readl(priv, CORE_SWITCH_CTRL);
 179        reg |= MII_DUMB_FWDG_EN;
 180        core_writel(priv, reg, CORE_SWITCH_CTRL);
 181
 182        /* Resolve which bit controls the Broadcom tag */
 183        switch (port) {
 184        case 8:
 185                val = BRCM_HDR_EN_P8;
 186                break;
 187        case 7:
 188                val = BRCM_HDR_EN_P7;
 189                break;
 190        case 5:
 191                val = BRCM_HDR_EN_P5;
 192                break;
 193        default:
 194                val = 0;
 195                break;
 196        }
 197
 198        /* Enable Broadcom tags for IMP port */
 199        reg = core_readl(priv, CORE_BRCM_HDR_CTRL);
 200        reg |= val;
 201        core_writel(priv, reg, CORE_BRCM_HDR_CTRL);
 202
 203        /* Enable reception Broadcom tag for CPU TX (switch RX) to
 204         * allow us to tag outgoing frames
 205         */
 206        reg = core_readl(priv, CORE_BRCM_HDR_RX_DIS);
 207        reg &= ~(1 << port);
 208        core_writel(priv, reg, CORE_BRCM_HDR_RX_DIS);
 209
 210        /* Enable transmission of Broadcom tags from the switch (CPU RX) to
 211         * allow delivering frames to the per-port net_devices
 212         */
 213        reg = core_readl(priv, CORE_BRCM_HDR_TX_DIS);
 214        reg &= ~(1 << port);
 215        core_writel(priv, reg, CORE_BRCM_HDR_TX_DIS);
 216
 217        /* Force link status for IMP port */
 218        reg = core_readl(priv, CORE_STS_OVERRIDE_IMP);
 219        reg |= (MII_SW_OR | LINK_STS);
 220        core_writel(priv, reg, CORE_STS_OVERRIDE_IMP);
 221}
 222
 223static void bcm_sf2_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
 224{
 225        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 226        u32 reg;
 227
 228        reg = core_readl(priv, CORE_EEE_EN_CTRL);
 229        if (enable)
 230                reg |= 1 << port;
 231        else
 232                reg &= ~(1 << port);
 233        core_writel(priv, reg, CORE_EEE_EN_CTRL);
 234}
 235
 236static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
 237                              struct phy_device *phy)
 238{
 239        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 240        s8 cpu_port = ds->dst[ds->index].cpu_port;
 241        u32 reg;
 242
 243        /* Clear the memory power down */
 244        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
 245        reg &= ~P_TXQ_PSM_VDD(port);
 246        core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 247
 248        /* Clear the Rx and Tx disable bits and set to no spanning tree */
 249        core_writel(priv, 0, CORE_G_PCTL_PORT(port));
 250
 251        /* Enable port 7 interrupts to get notified */
 252        if (port == 7)
 253                intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF));
 254
 255        /* Set this port, and only this one to be in the default VLAN */
 256        reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(port));
 257        reg &= ~PORT_VLAN_CTRL_MASK;
 258        reg |= (1 << port);
 259        core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(port));
 260
 261        bcm_sf2_imp_vlan_setup(ds, cpu_port);
 262
 263        /* If EEE was enabled, restore it */
 264        if (priv->port_sts[port].eee.eee_enabled)
 265                bcm_sf2_eee_enable_set(ds, port, true);
 266
 267        return 0;
 268}
 269
 270static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
 271                                 struct phy_device *phy)
 272{
 273        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 274        u32 off, reg;
 275
 276        if (priv->wol_ports_mask & (1 << port))
 277                return;
 278
 279        if (port == 7) {
 280                intrl2_1_mask_set(priv, P_IRQ_MASK(P7_IRQ_OFF));
 281                intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR);
 282        }
 283
 284        if (dsa_is_cpu_port(ds, port))
 285                off = CORE_IMP_CTL;
 286        else
 287                off = CORE_G_PCTL_PORT(port);
 288
 289        reg = core_readl(priv, off);
 290        reg |= RX_DIS | TX_DIS;
 291        core_writel(priv, reg, off);
 292
 293        /* Power down the port memory */
 294        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
 295        reg |= P_TXQ_PSM_VDD(port);
 296        core_writel(priv, reg, CORE_MEM_PSM_VDD_CTRL);
 297}
 298
 299/* Returns 0 if EEE was not enabled, or 1 otherwise
 300 */
 301static int bcm_sf2_eee_init(struct dsa_switch *ds, int port,
 302                            struct phy_device *phy)
 303{
 304        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 305        struct ethtool_eee *p = &priv->port_sts[port].eee;
 306        int ret;
 307
 308        p->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full);
 309
 310        ret = phy_init_eee(phy, 0);
 311        if (ret)
 312                return 0;
 313
 314        bcm_sf2_eee_enable_set(ds, port, true);
 315
 316        return 1;
 317}
 318
 319static int bcm_sf2_sw_get_eee(struct dsa_switch *ds, int port,
 320                              struct ethtool_eee *e)
 321{
 322        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 323        struct ethtool_eee *p = &priv->port_sts[port].eee;
 324        u32 reg;
 325
 326        reg = core_readl(priv, CORE_EEE_LPI_INDICATE);
 327        e->eee_enabled = p->eee_enabled;
 328        e->eee_active = !!(reg & (1 << port));
 329
 330        return 0;
 331}
 332
 333static int bcm_sf2_sw_set_eee(struct dsa_switch *ds, int port,
 334                              struct phy_device *phydev,
 335                              struct ethtool_eee *e)
 336{
 337        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 338        struct ethtool_eee *p = &priv->port_sts[port].eee;
 339
 340        p->eee_enabled = e->eee_enabled;
 341
 342        if (!p->eee_enabled) {
 343                bcm_sf2_eee_enable_set(ds, port, false);
 344        } else {
 345                p->eee_enabled = bcm_sf2_eee_init(ds, port, phydev);
 346                if (!p->eee_enabled)
 347                        return -EOPNOTSUPP;
 348        }
 349
 350        return 0;
 351}
 352
 353static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
 354{
 355        struct bcm_sf2_priv *priv = dev_id;
 356
 357        priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) &
 358                                ~priv->irq0_mask;
 359        intrl2_0_writel(priv, priv->irq0_stat, INTRL2_CPU_CLEAR);
 360
 361        return IRQ_HANDLED;
 362}
 363
 364static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id)
 365{
 366        struct bcm_sf2_priv *priv = dev_id;
 367
 368        priv->irq1_stat = intrl2_1_readl(priv, INTRL2_CPU_STATUS) &
 369                                ~priv->irq1_mask;
 370        intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
 371
 372        if (priv->irq1_stat & P_LINK_UP_IRQ(P7_IRQ_OFF))
 373                priv->port_sts[7].link = 1;
 374        if (priv->irq1_stat & P_LINK_DOWN_IRQ(P7_IRQ_OFF))
 375                priv->port_sts[7].link = 0;
 376
 377        return IRQ_HANDLED;
 378}
 379
 380static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
 381{
 382        unsigned int timeout = 1000;
 383        u32 reg;
 384
 385        reg = core_readl(priv, CORE_WATCHDOG_CTRL);
 386        reg |= SOFTWARE_RESET | EN_CHIP_RST | EN_SW_RESET;
 387        core_writel(priv, reg, CORE_WATCHDOG_CTRL);
 388
 389        do {
 390                reg = core_readl(priv, CORE_WATCHDOG_CTRL);
 391                if (!(reg & SOFTWARE_RESET))
 392                        break;
 393
 394                usleep_range(1000, 2000);
 395        } while (timeout-- > 0);
 396
 397        if (timeout == 0)
 398                return -ETIMEDOUT;
 399
 400        return 0;
 401}
 402
 403static int bcm_sf2_sw_setup(struct dsa_switch *ds)
 404{
 405        const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
 406        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 407        struct device_node *dn;
 408        void __iomem **base;
 409        unsigned int port;
 410        unsigned int i;
 411        u32 reg, rev;
 412        int ret;
 413
 414        spin_lock_init(&priv->indir_lock);
 415        mutex_init(&priv->stats_mutex);
 416
 417        /* All the interesting properties are at the parent device_node
 418         * level
 419         */
 420        dn = ds->pd->of_node->parent;
 421
 422        priv->irq0 = irq_of_parse_and_map(dn, 0);
 423        priv->irq1 = irq_of_parse_and_map(dn, 1);
 424
 425        base = &priv->core;
 426        for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
 427                *base = of_iomap(dn, i);
 428                if (*base == NULL) {
 429                        pr_err("unable to find register: %s\n", reg_names[i]);
 430                        ret = -ENOMEM;
 431                        goto out_unmap;
 432                }
 433                base++;
 434        }
 435
 436        ret = bcm_sf2_sw_rst(priv);
 437        if (ret) {
 438                pr_err("unable to software reset switch: %d\n", ret);
 439                goto out_unmap;
 440        }
 441
 442        /* Disable all interrupts and request them */
 443        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
 444        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
 445        intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 446        intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
 447        intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
 448        intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 449
 450        ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
 451                          "switch_0", priv);
 452        if (ret < 0) {
 453                pr_err("failed to request switch_0 IRQ\n");
 454                goto out_unmap;
 455        }
 456
 457        ret = request_irq(priv->irq1, bcm_sf2_switch_1_isr, 0,
 458                          "switch_1", priv);
 459        if (ret < 0) {
 460                pr_err("failed to request switch_1 IRQ\n");
 461                goto out_free_irq0;
 462        }
 463
 464        /* Reset the MIB counters */
 465        reg = core_readl(priv, CORE_GMNCFGCFG);
 466        reg |= RST_MIB_CNT;
 467        core_writel(priv, reg, CORE_GMNCFGCFG);
 468        reg &= ~RST_MIB_CNT;
 469        core_writel(priv, reg, CORE_GMNCFGCFG);
 470
 471        /* Get the maximum number of ports for this switch */
 472        priv->hw_params.num_ports = core_readl(priv, CORE_IMP0_PRT_ID) + 1;
 473        if (priv->hw_params.num_ports > DSA_MAX_PORTS)
 474                priv->hw_params.num_ports = DSA_MAX_PORTS;
 475
 476        /* Assume a single GPHY setup if we can't read that property */
 477        if (of_property_read_u32(dn, "brcm,num-gphy",
 478                                 &priv->hw_params.num_gphy))
 479                priv->hw_params.num_gphy = 1;
 480
 481        /* Enable all valid ports and disable those unused */
 482        for (port = 0; port < priv->hw_params.num_ports; port++) {
 483                /* IMP port receives special treatment */
 484                if ((1 << port) & ds->phys_port_mask)
 485                        bcm_sf2_port_setup(ds, port, NULL);
 486                else if (dsa_is_cpu_port(ds, port))
 487                        bcm_sf2_imp_setup(ds, port);
 488                else
 489                        bcm_sf2_port_disable(ds, port, NULL);
 490        }
 491
 492        /* Include the pseudo-PHY address and the broadcast PHY address to
 493         * divert reads towards our workaround
 494         */
 495        ds->phys_mii_mask |= ((1 << 30) | (1 << 0));
 496
 497        rev = reg_readl(priv, REG_SWITCH_REVISION);
 498        priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
 499                                        SWITCH_TOP_REV_MASK;
 500        priv->hw_params.core_rev = (rev & SF2_REV_MASK);
 501
 502        rev = reg_readl(priv, REG_PHY_REVISION);
 503        priv->hw_params.gphy_rev = rev & PHY_REVISION_MASK;
 504
 505        pr_info("Starfighter 2 top: %x.%02x, core: %x.%02x base: 0x%p, IRQs: %d, %d\n",
 506                priv->hw_params.top_rev >> 8, priv->hw_params.top_rev & 0xff,
 507                priv->hw_params.core_rev >> 8, priv->hw_params.core_rev & 0xff,
 508                priv->core, priv->irq0, priv->irq1);
 509
 510        return 0;
 511
 512out_free_irq0:
 513        free_irq(priv->irq0, priv);
 514out_unmap:
 515        base = &priv->core;
 516        for (i = 0; i < BCM_SF2_REGS_NUM; i++) {
 517                if (*base)
 518                        iounmap(*base);
 519                base++;
 520        }
 521        return ret;
 522}
 523
 524static int bcm_sf2_sw_set_addr(struct dsa_switch *ds, u8 *addr)
 525{
 526        return 0;
 527}
 528
 529static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, int port)
 530{
 531        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 532
 533        /* The BCM7xxx PHY driver expects to find the integrated PHY revision
 534         * in bits 15:8 and the patch level in bits 7:0 which is exactly what
 535         * the REG_PHY_REVISION register layout is.
 536         */
 537
 538        return priv->hw_params.gphy_rev;
 539}
 540
 541static int bcm_sf2_sw_indir_rw(struct dsa_switch *ds, int op, int addr,
 542                               int regnum, u16 val)
 543{
 544        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 545        int ret = 0;
 546        u32 reg;
 547
 548        reg = reg_readl(priv, REG_SWITCH_CNTRL);
 549        reg |= MDIO_MASTER_SEL;
 550        reg_writel(priv, reg, REG_SWITCH_CNTRL);
 551
 552        /* Page << 8 | offset */
 553        reg = 0x70;
 554        reg <<= 2;
 555        core_writel(priv, addr, reg);
 556
 557        /* Page << 8 | offset */
 558        reg = 0x80 << 8 | regnum << 1;
 559        reg <<= 2;
 560
 561        if (op)
 562                ret = core_readl(priv, reg);
 563        else
 564                core_writel(priv, val, reg);
 565
 566        reg = reg_readl(priv, REG_SWITCH_CNTRL);
 567        reg &= ~MDIO_MASTER_SEL;
 568        reg_writel(priv, reg, REG_SWITCH_CNTRL);
 569
 570        return ret & 0xffff;
 571}
 572
 573static int bcm_sf2_sw_phy_read(struct dsa_switch *ds, int addr, int regnum)
 574{
 575        /* Intercept reads from the MDIO broadcast address or Broadcom
 576         * pseudo-PHY address
 577         */
 578        switch (addr) {
 579        case 0:
 580        case 30:
 581                return bcm_sf2_sw_indir_rw(ds, 1, addr, regnum, 0);
 582        default:
 583                return 0xffff;
 584        }
 585}
 586
 587static int bcm_sf2_sw_phy_write(struct dsa_switch *ds, int addr, int regnum,
 588                                u16 val)
 589{
 590        /* Intercept writes to the MDIO broadcast address or Broadcom
 591         * pseudo-PHY address
 592         */
 593        switch (addr) {
 594        case 0:
 595        case 30:
 596                bcm_sf2_sw_indir_rw(ds, 0, addr, regnum, val);
 597                break;
 598        }
 599
 600        return 0;
 601}
 602
 603static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
 604                                   struct phy_device *phydev)
 605{
 606        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 607        u32 id_mode_dis = 0, port_mode;
 608        const char *str = NULL;
 609        u32 reg;
 610
 611        switch (phydev->interface) {
 612        case PHY_INTERFACE_MODE_RGMII:
 613                str = "RGMII (no delay)";
 614                id_mode_dis = 1;
 615        case PHY_INTERFACE_MODE_RGMII_TXID:
 616                if (!str)
 617                        str = "RGMII (TX delay)";
 618                port_mode = EXT_GPHY;
 619                break;
 620        case PHY_INTERFACE_MODE_MII:
 621                str = "MII";
 622                port_mode = EXT_EPHY;
 623                break;
 624        case PHY_INTERFACE_MODE_REVMII:
 625                str = "Reverse MII";
 626                port_mode = EXT_REVMII;
 627                break;
 628        default:
 629                /* All other PHYs: internal and MoCA */
 630                goto force_link;
 631        }
 632
 633        /* If the link is down, just disable the interface to conserve power */
 634        if (!phydev->link) {
 635                reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
 636                reg &= ~RGMII_MODE_EN;
 637                reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
 638                goto force_link;
 639        }
 640
 641        /* Clear id_mode_dis bit, and the existing port mode, but
 642         * make sure we enable the RGMII block for data to pass
 643         */
 644        reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
 645        reg &= ~ID_MODE_DIS;
 646        reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT);
 647        reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
 648
 649        reg |= port_mode | RGMII_MODE_EN;
 650        if (id_mode_dis)
 651                reg |= ID_MODE_DIS;
 652
 653        if (phydev->pause) {
 654                if (phydev->asym_pause)
 655                        reg |= TX_PAUSE_EN;
 656                reg |= RX_PAUSE_EN;
 657        }
 658
 659        reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
 660
 661        pr_info("Port %d configured for %s\n", port, str);
 662
 663force_link:
 664        /* Force link settings detected from the PHY */
 665        reg = SW_OVERRIDE;
 666        switch (phydev->speed) {
 667        case SPEED_1000:
 668                reg |= SPDSTS_1000 << SPEED_SHIFT;
 669                break;
 670        case SPEED_100:
 671                reg |= SPDSTS_100 << SPEED_SHIFT;
 672                break;
 673        }
 674
 675        if (phydev->link)
 676                reg |= LINK_STS;
 677        if (phydev->duplex == DUPLEX_FULL)
 678                reg |= DUPLX_MODE;
 679
 680        core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
 681}
 682
 683static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
 684                                         struct fixed_phy_status *status)
 685{
 686        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 687        u32 duplex, pause, speed;
 688        u32 reg;
 689
 690        duplex = core_readl(priv, CORE_DUPSTS);
 691        pause = core_readl(priv, CORE_PAUSESTS);
 692        speed = core_readl(priv, CORE_SPDSTS);
 693
 694        speed >>= (port * SPDSTS_SHIFT);
 695        speed &= SPDSTS_MASK;
 696
 697        status->link = 0;
 698
 699        /* Port 7 is special as we do not get link status from CORE_LNKSTS,
 700         * which means that we need to force the link at the port override
 701         * level to get the data to flow. We do use what the interrupt handler
 702         * did determine before.
 703         *
 704         * For the other ports, we just force the link status, since this is
 705         * a fixed PHY device.
 706         */
 707        if (port == 7) {
 708                status->link = priv->port_sts[port].link;
 709                status->duplex = 1;
 710        } else {
 711                status->link = 1;
 712                status->duplex = !!(duplex & (1 << port));
 713        }
 714
 715        reg = core_readl(priv, CORE_STS_OVERRIDE_GMIIP_PORT(port));
 716        reg |= SW_OVERRIDE;
 717        if (status->link)
 718                reg |= LINK_STS;
 719        else
 720                reg &= ~LINK_STS;
 721        core_writel(priv, reg, CORE_STS_OVERRIDE_GMIIP_PORT(port));
 722
 723        switch (speed) {
 724        case SPDSTS_10:
 725                status->speed = SPEED_10;
 726                break;
 727        case SPDSTS_100:
 728                status->speed = SPEED_100;
 729                break;
 730        case SPDSTS_1000:
 731                status->speed = SPEED_1000;
 732                break;
 733        }
 734
 735        if ((pause & (1 << port)) &&
 736            (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) {
 737                status->asym_pause = 1;
 738                status->pause = 1;
 739        }
 740
 741        if (pause & (1 << port))
 742                status->pause = 1;
 743}
 744
 745static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
 746{
 747        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 748        unsigned int port;
 749
 750        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
 751        intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
 752        intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 753        intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
 754        intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
 755        intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
 756
 757        /* Disable all ports physically present including the IMP
 758         * port, the other ones have already been disabled during
 759         * bcm_sf2_sw_setup
 760         */
 761        for (port = 0; port < DSA_MAX_PORTS; port++) {
 762                if ((1 << port) & ds->phys_port_mask ||
 763                    dsa_is_cpu_port(ds, port))
 764                        bcm_sf2_port_disable(ds, port, NULL);
 765        }
 766
 767        return 0;
 768}
 769
 770static int bcm_sf2_sw_resume(struct dsa_switch *ds)
 771{
 772        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 773        unsigned int port;
 774        u32 reg;
 775        int ret;
 776
 777        ret = bcm_sf2_sw_rst(priv);
 778        if (ret) {
 779                pr_err("%s: failed to software reset switch\n", __func__);
 780                return ret;
 781        }
 782
 783        /* Reinitialize the single GPHY */
 784        if (priv->hw_params.num_gphy == 1) {
 785                reg = reg_readl(priv, REG_SPHY_CNTRL);
 786                reg |= PHY_RESET;
 787                reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS);
 788                reg_writel(priv, reg, REG_SPHY_CNTRL);
 789                udelay(21);
 790                reg = reg_readl(priv, REG_SPHY_CNTRL);
 791                reg &= ~PHY_RESET;
 792                reg_writel(priv, reg, REG_SPHY_CNTRL);
 793        }
 794
 795        for (port = 0; port < DSA_MAX_PORTS; port++) {
 796                if ((1 << port) & ds->phys_port_mask)
 797                        bcm_sf2_port_setup(ds, port, NULL);
 798                else if (dsa_is_cpu_port(ds, port))
 799                        bcm_sf2_imp_setup(ds, port);
 800        }
 801
 802        return 0;
 803}
 804
 805static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 806                               struct ethtool_wolinfo *wol)
 807{
 808        struct net_device *p = ds->dst[ds->index].master_netdev;
 809        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 810        struct ethtool_wolinfo pwol;
 811
 812        /* Get the parent device WoL settings */
 813        p->ethtool_ops->get_wol(p, &pwol);
 814
 815        /* Advertise the parent device supported settings */
 816        wol->supported = pwol.supported;
 817        memset(&wol->sopass, 0, sizeof(wol->sopass));
 818
 819        if (pwol.wolopts & WAKE_MAGICSECURE)
 820                memcpy(&wol->sopass, pwol.sopass, sizeof(wol->sopass));
 821
 822        if (priv->wol_ports_mask & (1 << port))
 823                wol->wolopts = pwol.wolopts;
 824        else
 825                wol->wolopts = 0;
 826}
 827
 828static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
 829                              struct ethtool_wolinfo *wol)
 830{
 831        struct net_device *p = ds->dst[ds->index].master_netdev;
 832        struct bcm_sf2_priv *priv = ds_to_priv(ds);
 833        s8 cpu_port = ds->dst[ds->index].cpu_port;
 834        struct ethtool_wolinfo pwol;
 835
 836        p->ethtool_ops->get_wol(p, &pwol);
 837        if (wol->wolopts & ~pwol.supported)
 838                return -EINVAL;
 839
 840        if (wol->wolopts)
 841                priv->wol_ports_mask |= (1 << port);
 842        else
 843                priv->wol_ports_mask &= ~(1 << port);
 844
 845        /* If we have at least one port enabled, make sure the CPU port
 846         * is also enabled. If the CPU port is the last one enabled, we disable
 847         * it since this configuration does not make sense.
 848         */
 849        if (priv->wol_ports_mask && priv->wol_ports_mask != (1 << cpu_port))
 850                priv->wol_ports_mask |= (1 << cpu_port);
 851        else
 852                priv->wol_ports_mask &= ~(1 << cpu_port);
 853
 854        return p->ethtool_ops->set_wol(p, wol);
 855}
 856
 857static struct dsa_switch_driver bcm_sf2_switch_driver = {
 858        .tag_protocol           = DSA_TAG_PROTO_BRCM,
 859        .priv_size              = sizeof(struct bcm_sf2_priv),
 860        .probe                  = bcm_sf2_sw_probe,
 861        .setup                  = bcm_sf2_sw_setup,
 862        .set_addr               = bcm_sf2_sw_set_addr,
 863        .get_phy_flags          = bcm_sf2_sw_get_phy_flags,
 864        .phy_read               = bcm_sf2_sw_phy_read,
 865        .phy_write              = bcm_sf2_sw_phy_write,
 866        .get_strings            = bcm_sf2_sw_get_strings,
 867        .get_ethtool_stats      = bcm_sf2_sw_get_ethtool_stats,
 868        .get_sset_count         = bcm_sf2_sw_get_sset_count,
 869        .adjust_link            = bcm_sf2_sw_adjust_link,
 870        .fixed_link_update      = bcm_sf2_sw_fixed_link_update,
 871        .suspend                = bcm_sf2_sw_suspend,
 872        .resume                 = bcm_sf2_sw_resume,
 873        .get_wol                = bcm_sf2_sw_get_wol,
 874        .set_wol                = bcm_sf2_sw_set_wol,
 875        .port_enable            = bcm_sf2_port_setup,
 876        .port_disable           = bcm_sf2_port_disable,
 877        .get_eee                = bcm_sf2_sw_get_eee,
 878        .set_eee                = bcm_sf2_sw_set_eee,
 879};
 880
 881static int __init bcm_sf2_init(void)
 882{
 883        register_switch_driver(&bcm_sf2_switch_driver);
 884
 885        return 0;
 886}
 887module_init(bcm_sf2_init);
 888
 889static void __exit bcm_sf2_exit(void)
 890{
 891        unregister_switch_driver(&bcm_sf2_switch_driver);
 892}
 893module_exit(bcm_sf2_exit);
 894
 895MODULE_AUTHOR("Broadcom Corporation");
 896MODULE_DESCRIPTION("Driver for Broadcom Starfighter 2 ethernet switch chip");
 897MODULE_LICENSE("GPL");
 898MODULE_ALIAS("platform:brcm-sf2");
 899