linux/net/dsa/mv88e6xxx.c
<<
>>
Prefs
   1/*
   2 * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
   3 * Copyright (c) 2008 Marvell Semiconductor
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 */
  10
  11#include <linux/list.h>
  12#include <linux/netdevice.h>
  13#include <linux/phy.h>
  14#include "dsa_priv.h"
  15#include "mv88e6xxx.h"
  16
  17/*
  18 * If the switch's ADDR[4:0] strap pins are strapped to zero, it will
  19 * use all 32 SMI bus addresses on its SMI bus, and all switch registers
  20 * will be directly accessible on some {device address,register address}
  21 * pair.  If the ADDR[4:0] pins are not strapped to zero, the switch
  22 * will only respond to SMI transactions to that specific address, and
  23 * an indirect addressing mechanism needs to be used to access its
  24 * registers.
  25 */
  26static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
  27{
  28        int ret;
  29        int i;
  30
  31        for (i = 0; i < 16; i++) {
  32                ret = mdiobus_read(bus, sw_addr, 0);
  33                if (ret < 0)
  34                        return ret;
  35
  36                if ((ret & 0x8000) == 0)
  37                        return 0;
  38        }
  39
  40        return -ETIMEDOUT;
  41}
  42
  43int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
  44{
  45        int ret;
  46
  47        if (sw_addr == 0)
  48                return mdiobus_read(bus, addr, reg);
  49
  50        /*
  51         * Wait for the bus to become free.
  52         */
  53        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
  54        if (ret < 0)
  55                return ret;
  56
  57        /*
  58         * Transmit the read command.
  59         */
  60        ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg);
  61        if (ret < 0)
  62                return ret;
  63
  64        /*
  65         * Wait for the read command to complete.
  66         */
  67        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
  68        if (ret < 0)
  69                return ret;
  70
  71        /*
  72         * Read the data.
  73         */
  74        ret = mdiobus_read(bus, sw_addr, 1);
  75        if (ret < 0)
  76                return ret;
  77
  78        return ret & 0xffff;
  79}
  80
  81int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
  82{
  83        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
  84        int ret;
  85
  86        mutex_lock(&ps->smi_mutex);
  87        ret = __mv88e6xxx_reg_read(ds->master_mii_bus,
  88                                   ds->pd->sw_addr, addr, reg);
  89        mutex_unlock(&ps->smi_mutex);
  90
  91        return ret;
  92}
  93
  94int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
  95                          int reg, u16 val)
  96{
  97        int ret;
  98
  99        if (sw_addr == 0)
 100                return mdiobus_write(bus, addr, reg, val);
 101
 102        /*
 103         * Wait for the bus to become free.
 104         */
 105        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
 106        if (ret < 0)
 107                return ret;
 108
 109        /*
 110         * Transmit the data to write.
 111         */
 112        ret = mdiobus_write(bus, sw_addr, 1, val);
 113        if (ret < 0)
 114                return ret;
 115
 116        /*
 117         * Transmit the write command.
 118         */
 119        ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg);
 120        if (ret < 0)
 121                return ret;
 122
 123        /*
 124         * Wait for the write command to complete.
 125         */
 126        ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
 127        if (ret < 0)
 128                return ret;
 129
 130        return 0;
 131}
 132
 133int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
 134{
 135        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 136        int ret;
 137
 138        mutex_lock(&ps->smi_mutex);
 139        ret = __mv88e6xxx_reg_write(ds->master_mii_bus,
 140                                    ds->pd->sw_addr, addr, reg, val);
 141        mutex_unlock(&ps->smi_mutex);
 142
 143        return ret;
 144}
 145
 146int mv88e6xxx_config_prio(struct dsa_switch *ds)
 147{
 148        /*
 149         * Configure the IP ToS mapping registers.
 150         */
 151        REG_WRITE(REG_GLOBAL, 0x10, 0x0000);
 152        REG_WRITE(REG_GLOBAL, 0x11, 0x0000);
 153        REG_WRITE(REG_GLOBAL, 0x12, 0x5555);
 154        REG_WRITE(REG_GLOBAL, 0x13, 0x5555);
 155        REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa);
 156        REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa);
 157        REG_WRITE(REG_GLOBAL, 0x16, 0xffff);
 158        REG_WRITE(REG_GLOBAL, 0x17, 0xffff);
 159
 160        /*
 161         * Configure the IEEE 802.1p priority mapping register.
 162         */
 163        REG_WRITE(REG_GLOBAL, 0x18, 0xfa41);
 164
 165        return 0;
 166}
 167
 168int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
 169{
 170        REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
 171        REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
 172        REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
 173
 174        return 0;
 175}
 176
 177int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
 178{
 179        int i;
 180        int ret;
 181
 182        for (i = 0; i < 6; i++) {
 183                int j;
 184
 185                /*
 186                 * Write the MAC address byte.
 187                 */
 188                REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]);
 189
 190                /*
 191                 * Wait for the write to complete.
 192                 */
 193                for (j = 0; j < 16; j++) {
 194                        ret = REG_READ(REG_GLOBAL2, 0x0d);
 195                        if ((ret & 0x8000) == 0)
 196                                break;
 197                }
 198                if (j == 16)
 199                        return -ETIMEDOUT;
 200        }
 201
 202        return 0;
 203}
 204
 205int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
 206{
 207        if (addr >= 0)
 208                return mv88e6xxx_reg_read(ds, addr, regnum);
 209        return 0xffff;
 210}
 211
 212int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val)
 213{
 214        if (addr >= 0)
 215                return mv88e6xxx_reg_write(ds, addr, regnum, val);
 216        return 0;
 217}
 218
 219#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
 220static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
 221{
 222        int ret;
 223        int i;
 224
 225        ret = REG_READ(REG_GLOBAL, 0x04);
 226        REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
 227
 228        for (i = 0; i < 1000; i++) {
 229                ret = REG_READ(REG_GLOBAL, 0x00);
 230                msleep(1);
 231                if ((ret & 0xc000) != 0xc000)
 232                        return 0;
 233        }
 234
 235        return -ETIMEDOUT;
 236}
 237
 238static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
 239{
 240        int ret;
 241        int i;
 242
 243        ret = REG_READ(REG_GLOBAL, 0x04);
 244        REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
 245
 246        for (i = 0; i < 1000; i++) {
 247                ret = REG_READ(REG_GLOBAL, 0x00);
 248                msleep(1);
 249                if ((ret & 0xc000) == 0xc000)
 250                        return 0;
 251        }
 252
 253        return -ETIMEDOUT;
 254}
 255
 256static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
 257{
 258        struct mv88e6xxx_priv_state *ps;
 259
 260        ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
 261        if (mutex_trylock(&ps->ppu_mutex)) {
 262                struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
 263
 264                if (mv88e6xxx_ppu_enable(ds) == 0)
 265                        ps->ppu_disabled = 0;
 266                mutex_unlock(&ps->ppu_mutex);
 267        }
 268}
 269
 270static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
 271{
 272        struct mv88e6xxx_priv_state *ps = (void *)_ps;
 273
 274        schedule_work(&ps->ppu_work);
 275}
 276
 277static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
 278{
 279        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 280        int ret;
 281
 282        mutex_lock(&ps->ppu_mutex);
 283
 284        /*
 285         * If the PHY polling unit is enabled, disable it so that
 286         * we can access the PHY registers.  If it was already
 287         * disabled, cancel the timer that is going to re-enable
 288         * it.
 289         */
 290        if (!ps->ppu_disabled) {
 291                ret = mv88e6xxx_ppu_disable(ds);
 292                if (ret < 0) {
 293                        mutex_unlock(&ps->ppu_mutex);
 294                        return ret;
 295                }
 296                ps->ppu_disabled = 1;
 297        } else {
 298                del_timer(&ps->ppu_timer);
 299                ret = 0;
 300        }
 301
 302        return ret;
 303}
 304
 305static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
 306{
 307        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 308
 309        /*
 310         * Schedule a timer to re-enable the PHY polling unit.
 311         */
 312        mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
 313        mutex_unlock(&ps->ppu_mutex);
 314}
 315
 316void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
 317{
 318        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 319
 320        mutex_init(&ps->ppu_mutex);
 321        INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
 322        init_timer(&ps->ppu_timer);
 323        ps->ppu_timer.data = (unsigned long)ps;
 324        ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
 325}
 326
 327int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
 328{
 329        int ret;
 330
 331        ret = mv88e6xxx_ppu_access_get(ds);
 332        if (ret >= 0) {
 333                ret = mv88e6xxx_reg_read(ds, addr, regnum);
 334                mv88e6xxx_ppu_access_put(ds);
 335        }
 336
 337        return ret;
 338}
 339
 340int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
 341                            int regnum, u16 val)
 342{
 343        int ret;
 344
 345        ret = mv88e6xxx_ppu_access_get(ds);
 346        if (ret >= 0) {
 347                ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
 348                mv88e6xxx_ppu_access_put(ds);
 349        }
 350
 351        return ret;
 352}
 353#endif
 354
 355void mv88e6xxx_poll_link(struct dsa_switch *ds)
 356{
 357        int i;
 358
 359        for (i = 0; i < DSA_MAX_PORTS; i++) {
 360                struct net_device *dev;
 361                int uninitialized_var(port_status);
 362                int link;
 363                int speed;
 364                int duplex;
 365                int fc;
 366
 367                dev = ds->ports[i];
 368                if (dev == NULL)
 369                        continue;
 370
 371                link = 0;
 372                if (dev->flags & IFF_UP) {
 373                        port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
 374                        if (port_status < 0)
 375                                continue;
 376
 377                        link = !!(port_status & 0x0800);
 378                }
 379
 380                if (!link) {
 381                        if (netif_carrier_ok(dev)) {
 382                                printk(KERN_INFO "%s: link down\n", dev->name);
 383                                netif_carrier_off(dev);
 384                        }
 385                        continue;
 386                }
 387
 388                switch (port_status & 0x0300) {
 389                case 0x0000:
 390                        speed = 10;
 391                        break;
 392                case 0x0100:
 393                        speed = 100;
 394                        break;
 395                case 0x0200:
 396                        speed = 1000;
 397                        break;
 398                default:
 399                        speed = -1;
 400                        break;
 401                }
 402                duplex = (port_status & 0x0400) ? 1 : 0;
 403                fc = (port_status & 0x8000) ? 1 : 0;
 404
 405                if (!netif_carrier_ok(dev)) {
 406                        printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
 407                                         "flow control %sabled\n", dev->name,
 408                                         speed, duplex ? "full" : "half",
 409                                         fc ? "en" : "dis");
 410                        netif_carrier_on(dev);
 411                }
 412        }
 413}
 414
 415static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
 416{
 417        int ret;
 418        int i;
 419
 420        for (i = 0; i < 10; i++) {
 421                ret = REG_READ(REG_GLOBAL, 0x1d);
 422                if ((ret & 0x8000) == 0)
 423                        return 0;
 424        }
 425
 426        return -ETIMEDOUT;
 427}
 428
 429static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
 430{
 431        int ret;
 432
 433        /*
 434         * Snapshot the hardware statistics counters for this port.
 435         */
 436        REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
 437
 438        /*
 439         * Wait for the snapshotting to complete.
 440         */
 441        ret = mv88e6xxx_stats_wait(ds);
 442        if (ret < 0)
 443                return ret;
 444
 445        return 0;
 446}
 447
 448static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
 449{
 450        u32 _val;
 451        int ret;
 452
 453        *val = 0;
 454
 455        ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
 456        if (ret < 0)
 457                return;
 458
 459        ret = mv88e6xxx_stats_wait(ds);
 460        if (ret < 0)
 461                return;
 462
 463        ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
 464        if (ret < 0)
 465                return;
 466
 467        _val = ret << 16;
 468
 469        ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
 470        if (ret < 0)
 471                return;
 472
 473        *val = _val | ret;
 474}
 475
 476void mv88e6xxx_get_strings(struct dsa_switch *ds,
 477                           int nr_stats, struct mv88e6xxx_hw_stat *stats,
 478                           int port, uint8_t *data)
 479{
 480        int i;
 481
 482        for (i = 0; i < nr_stats; i++) {
 483                memcpy(data + i * ETH_GSTRING_LEN,
 484                       stats[i].string, ETH_GSTRING_LEN);
 485        }
 486}
 487
 488void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
 489                                 int nr_stats, struct mv88e6xxx_hw_stat *stats,
 490                                 int port, uint64_t *data)
 491{
 492        struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
 493        int ret;
 494        int i;
 495
 496        mutex_lock(&ps->stats_mutex);
 497
 498        ret = mv88e6xxx_stats_snapshot(ds, port);
 499        if (ret < 0) {
 500                mutex_unlock(&ps->stats_mutex);
 501                return;
 502        }
 503
 504        /*
 505         * Read each of the counters.
 506         */
 507        for (i = 0; i < nr_stats; i++) {
 508                struct mv88e6xxx_hw_stat *s = stats + i;
 509                u32 low;
 510                u32 high;
 511
 512                mv88e6xxx_stats_read(ds, s->reg, &low);
 513                if (s->sizeof_stat == 8)
 514                        mv88e6xxx_stats_read(ds, s->reg + 1, &high);
 515                else
 516                        high = 0;
 517
 518                data[i] = (((u64)high) << 32) | low;
 519        }
 520
 521        mutex_unlock(&ps->stats_mutex);
 522}
 523