linux/drivers/net/dsa/mv88e6xxx/global1.c
<<
>>
Prefs
   1/*
   2 * Marvell 88E6xxx Switch Global (1) Registers support
   3 *
   4 * Copyright (c) 2008 Marvell Semiconductor
   5 *
   6 * Copyright (c) 2016-2017 Savoir-faire Linux Inc.
   7 *      Vivien Didelot <vivien.didelot@savoirfairelinux.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 */
  14
  15#include <linux/bitfield.h>
  16
  17#include "chip.h"
  18#include "global1.h"
  19
  20int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val)
  21{
  22        int addr = chip->info->global1_addr;
  23
  24        return mv88e6xxx_read(chip, addr, reg, val);
  25}
  26
  27int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val)
  28{
  29        int addr = chip->info->global1_addr;
  30
  31        return mv88e6xxx_write(chip, addr, reg, val);
  32}
  33
  34int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
  35{
  36        return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
  37}
  38
  39/* Offset 0x00: Switch Global Status Register */
  40
  41static int mv88e6185_g1_wait_ppu_disabled(struct mv88e6xxx_chip *chip)
  42{
  43        u16 state;
  44        int i, err;
  45
  46        for (i = 0; i < 16; i++) {
  47                err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  48                if (err)
  49                        return err;
  50
  51                /* Check the value of the PPUState bits 15:14 */
  52                state &= MV88E6185_G1_STS_PPU_STATE_MASK;
  53                if (state != MV88E6185_G1_STS_PPU_STATE_POLLING)
  54                        return 0;
  55
  56                usleep_range(1000, 2000);
  57        }
  58
  59        return -ETIMEDOUT;
  60}
  61
  62static int mv88e6185_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  63{
  64        u16 state;
  65        int i, err;
  66
  67        for (i = 0; i < 16; ++i) {
  68                err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  69                if (err)
  70                        return err;
  71
  72                /* Check the value of the PPUState bits 15:14 */
  73                state &= MV88E6185_G1_STS_PPU_STATE_MASK;
  74                if (state == MV88E6185_G1_STS_PPU_STATE_POLLING)
  75                        return 0;
  76
  77                usleep_range(1000, 2000);
  78        }
  79
  80        return -ETIMEDOUT;
  81}
  82
  83static int mv88e6352_g1_wait_ppu_polling(struct mv88e6xxx_chip *chip)
  84{
  85        u16 state;
  86        int i, err;
  87
  88        for (i = 0; i < 16; ++i) {
  89                err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &state);
  90                if (err)
  91                        return err;
  92
  93                /* Check the value of the PPUState (or InitState) bit 15 */
  94                if (state & MV88E6352_G1_STS_PPU_STATE)
  95                        return 0;
  96
  97                usleep_range(1000, 2000);
  98        }
  99
 100        return -ETIMEDOUT;
 101}
 102
 103static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip)
 104{
 105        const unsigned long timeout = jiffies + 1 * HZ;
 106        u16 val;
 107        int err;
 108
 109        /* Wait up to 1 second for the switch to be ready. The InitReady bit 11
 110         * is set to a one when all units inside the device (ATU, VTU, etc.)
 111         * have finished their initialization and are ready to accept frames.
 112         */
 113        while (time_before(jiffies, timeout)) {
 114                err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val);
 115                if (err)
 116                        return err;
 117
 118                if (val & MV88E6XXX_G1_STS_INIT_READY)
 119                        break;
 120
 121                usleep_range(1000, 2000);
 122        }
 123
 124        if (time_after(jiffies, timeout))
 125                return -ETIMEDOUT;
 126
 127        return 0;
 128}
 129
 130/* Offset 0x01: Switch MAC Address Register Bytes 0 & 1
 131 * Offset 0x02: Switch MAC Address Register Bytes 2 & 3
 132 * Offset 0x03: Switch MAC Address Register Bytes 4 & 5
 133 */
 134int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr)
 135{
 136        u16 reg;
 137        int err;
 138
 139        reg = (addr[0] << 8) | addr[1];
 140        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_01, reg);
 141        if (err)
 142                return err;
 143
 144        reg = (addr[2] << 8) | addr[3];
 145        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_23, reg);
 146        if (err)
 147                return err;
 148
 149        reg = (addr[4] << 8) | addr[5];
 150        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_MAC_45, reg);
 151        if (err)
 152                return err;
 153
 154        return 0;
 155}
 156
 157/* Offset 0x04: Switch Global Control Register */
 158
 159int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
 160{
 161        u16 val;
 162        int err;
 163
 164        /* Set the SWReset bit 15 along with the PPUEn bit 14, to also restart
 165         * the PPU, including re-doing PHY detection and initialization
 166         */
 167        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
 168        if (err)
 169                return err;
 170
 171        val |= MV88E6XXX_G1_CTL1_SW_RESET;
 172        val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
 173
 174        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
 175        if (err)
 176                return err;
 177
 178        err = mv88e6xxx_g1_wait_init_ready(chip);
 179        if (err)
 180                return err;
 181
 182        return mv88e6185_g1_wait_ppu_polling(chip);
 183}
 184
 185int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
 186{
 187        u16 val;
 188        int err;
 189
 190        /* Set the SWReset bit 15 */
 191        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
 192        if (err)
 193                return err;
 194
 195        val |= MV88E6XXX_G1_CTL1_SW_RESET;
 196
 197        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
 198        if (err)
 199                return err;
 200
 201        err = mv88e6xxx_g1_wait_init_ready(chip);
 202        if (err)
 203                return err;
 204
 205        return mv88e6352_g1_wait_ppu_polling(chip);
 206}
 207
 208int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip)
 209{
 210        u16 val;
 211        int err;
 212
 213        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
 214        if (err)
 215                return err;
 216
 217        val |= MV88E6XXX_G1_CTL1_PPU_ENABLE;
 218
 219        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
 220        if (err)
 221                return err;
 222
 223        return mv88e6185_g1_wait_ppu_polling(chip);
 224}
 225
 226int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip)
 227{
 228        u16 val;
 229        int err;
 230
 231        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
 232        if (err)
 233                return err;
 234
 235        val &= ~MV88E6XXX_G1_CTL1_PPU_ENABLE;
 236
 237        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
 238        if (err)
 239                return err;
 240
 241        return mv88e6185_g1_wait_ppu_disabled(chip);
 242}
 243
 244/* Offset 0x1a: Monitor Control */
 245/* Offset 0x1a: Monitor & MGMT Control on some devices */
 246
 247int mv88e6095_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
 248{
 249        u16 reg;
 250        int err;
 251
 252        err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
 253        if (err)
 254                return err;
 255
 256        reg &= ~(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK |
 257                 MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
 258
 259        reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_INGRESS_DEST_MASK) |
 260                port << __bf_shf(MV88E6185_G1_MONITOR_CTL_EGRESS_DEST_MASK);
 261
 262        return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
 263}
 264
 265/* Older generations also call this the ARP destination. It has been
 266 * generalized in more modern devices such that more than ARP can
 267 * egress it
 268 */
 269int mv88e6095_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
 270{
 271        u16 reg;
 272        int err;
 273
 274        err = mv88e6xxx_g1_read(chip, MV88E6185_G1_MONITOR_CTL, &reg);
 275        if (err)
 276                return err;
 277
 278        reg &= ~MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK;
 279        reg |= port << __bf_shf(MV88E6185_G1_MONITOR_CTL_ARP_DEST_MASK);
 280
 281        return mv88e6xxx_g1_write(chip, MV88E6185_G1_MONITOR_CTL, reg);
 282}
 283
 284static int mv88e6390_g1_monitor_write(struct mv88e6xxx_chip *chip,
 285                                      u16 pointer, u8 data)
 286{
 287        u16 reg;
 288
 289        reg = MV88E6390_G1_MONITOR_MGMT_CTL_UPDATE | pointer | data;
 290
 291        return mv88e6xxx_g1_write(chip, MV88E6390_G1_MONITOR_MGMT_CTL, reg);
 292}
 293
 294int mv88e6390_g1_set_egress_port(struct mv88e6xxx_chip *chip, int port)
 295{
 296        u16 ptr;
 297        int err;
 298
 299        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST;
 300        err = mv88e6390_g1_monitor_write(chip, ptr, port);
 301        if (err)
 302                return err;
 303
 304        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST;
 305        err = mv88e6390_g1_monitor_write(chip, ptr, port);
 306        if (err)
 307                return err;
 308
 309        return 0;
 310}
 311
 312int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
 313{
 314        u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
 315
 316        return mv88e6390_g1_monitor_write(chip, ptr, port);
 317}
 318
 319int mv88e6390_g1_mgmt_rsvd2cpu(struct mv88e6xxx_chip *chip)
 320{
 321        u16 ptr;
 322        int err;
 323
 324        /* 01:c2:80:00:00:00:00-01:c2:80:00:00:00:07 are Management */
 325        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XLO;
 326        err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
 327        if (err)
 328                return err;
 329
 330        /* 01:c2:80:00:00:00:08-01:c2:80:00:00:00:0f are Management */
 331        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000000XHI;
 332        err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
 333        if (err)
 334                return err;
 335
 336        /* 01:c2:80:00:00:00:20-01:c2:80:00:00:00:27 are Management */
 337        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XLO;
 338        err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
 339        if (err)
 340                return err;
 341
 342        /* 01:c2:80:00:00:00:28-01:c2:80:00:00:00:2f are Management */
 343        ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_0180C280000002XHI;
 344        err = mv88e6390_g1_monitor_write(chip, ptr, 0xff);
 345        if (err)
 346                return err;
 347
 348        return 0;
 349}
 350
 351/* Offset 0x1c: Global Control 2 */
 352
 353int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
 354{
 355        u16 val;
 356        int err;
 357
 358        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL2, &val);
 359        if (err)
 360                return err;
 361
 362        val |= MV88E6XXX_G1_CTL2_HIST_RX_TX;
 363
 364        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL2, val);
 365
 366        return err;
 367}
 368
 369/* Offset 0x1d: Statistics Operation 2 */
 370
 371int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
 372{
 373        return mv88e6xxx_g1_wait(chip, MV88E6XXX_G1_STATS_OP,
 374                                 MV88E6XXX_G1_STATS_OP_BUSY);
 375}
 376
 377int mv88e6095_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
 378{
 379        u16 val;
 380        int err;
 381
 382        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
 383        if (err)
 384                return err;
 385
 386        val |= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;
 387
 388        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
 389
 390        return err;
 391}
 392
 393int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
 394{
 395        int err;
 396
 397        /* Snapshot the hardware statistics counters for this port. */
 398        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
 399                                 MV88E6XXX_G1_STATS_OP_BUSY |
 400                                 MV88E6XXX_G1_STATS_OP_CAPTURE_PORT |
 401                                 MV88E6XXX_G1_STATS_OP_HIST_RX_TX | port);
 402        if (err)
 403                return err;
 404
 405        /* Wait for the snapshotting to complete. */
 406        return mv88e6xxx_g1_stats_wait(chip);
 407}
 408
 409int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
 410{
 411        port = (port + 1) << 5;
 412
 413        return mv88e6xxx_g1_stats_snapshot(chip, port);
 414}
 415
 416int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
 417{
 418        int err;
 419
 420        port = (port + 1) << 5;
 421
 422        /* Snapshot the hardware statistics counters for this port. */
 423        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
 424                                 MV88E6XXX_G1_STATS_OP_BUSY |
 425                                 MV88E6XXX_G1_STATS_OP_CAPTURE_PORT | port);
 426        if (err)
 427                return err;
 428
 429        /* Wait for the snapshotting to complete. */
 430        return mv88e6xxx_g1_stats_wait(chip);
 431}
 432
 433void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
 434{
 435        u32 value;
 436        u16 reg;
 437        int err;
 438
 439        *val = 0;
 440
 441        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP,
 442                                 MV88E6XXX_G1_STATS_OP_BUSY |
 443                                 MV88E6XXX_G1_STATS_OP_READ_CAPTURED | stat);
 444        if (err)
 445                return;
 446
 447        err = mv88e6xxx_g1_stats_wait(chip);
 448        if (err)
 449                return;
 450
 451        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_32, &reg);
 452        if (err)
 453                return;
 454
 455        value = reg << 16;
 456
 457        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_COUNTER_01, &reg);
 458        if (err)
 459                return;
 460
 461        *val = value | reg;
 462}
 463
 464int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)
 465{
 466        int err;
 467        u16 val;
 468
 469        err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STATS_OP, &val);
 470        if (err)
 471                return err;
 472
 473        val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;
 474
 475        err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val);
 476        if (err)
 477                return err;
 478
 479        /* Wait for the flush to complete. */
 480        return mv88e6xxx_g1_stats_wait(chip);
 481}
 482