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