linux/drivers/net/ethernet/ti/cpsw_ale.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Texas Instruments N-Port Ethernet Switch Address Lookup Engine
   4 *
   5 * Copyright (C) 2012 Texas Instruments
   6 *
   7 */
   8#include <linux/bitmap.h>
   9#include <linux/if_vlan.h>
  10#include <linux/kernel.h>
  11#include <linux/module.h>
  12#include <linux/platform_device.h>
  13#include <linux/seq_file.h>
  14#include <linux/slab.h>
  15#include <linux/err.h>
  16#include <linux/io.h>
  17#include <linux/stat.h>
  18#include <linux/sysfs.h>
  19#include <linux/etherdevice.h>
  20
  21#include "cpsw_ale.h"
  22
  23#define BITMASK(bits)           (BIT(bits) - 1)
  24
  25#define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
  26#define ALE_VERSION_MINOR(rev)  (rev & 0xff)
  27#define ALE_VERSION_1R3         0x0103
  28#define ALE_VERSION_1R4         0x0104
  29
  30/* ALE Registers */
  31#define ALE_IDVER               0x00
  32#define ALE_STATUS              0x04
  33#define ALE_CONTROL             0x08
  34#define ALE_PRESCALE            0x10
  35#define ALE_AGING_TIMER         0x14
  36#define ALE_UNKNOWNVLAN         0x18
  37#define ALE_TABLE_CONTROL       0x20
  38#define ALE_TABLE               0x34
  39#define ALE_PORTCTL             0x40
  40
  41/* ALE NetCP NU switch specific Registers */
  42#define ALE_UNKNOWNVLAN_MEMBER                  0x90
  43#define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD       0x94
  44#define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD         0x98
  45#define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS      0x9C
  46#define ALE_VLAN_MASK_MUX(reg)                  (0xc0 + (0x4 * (reg)))
  47
  48#define AM65_CPSW_ALE_THREAD_DEF_REG 0x134
  49
  50/* ALE_AGING_TIMER */
  51#define ALE_AGING_TIMER_MASK    GENMASK(23, 0)
  52
  53/**
  54 * struct ale_entry_fld - The ALE tbl entry field description
  55 * @start_bit: field start bit
  56 * @num_bits: field bit length
  57 * @flags: field flags
  58 */
  59struct ale_entry_fld {
  60        u8 start_bit;
  61        u8 num_bits;
  62        u8 flags;
  63};
  64
  65enum {
  66        CPSW_ALE_F_STATUS_REG = BIT(0), /* Status register present */
  67        CPSW_ALE_F_HW_AUTOAGING = BIT(1), /* HW auto aging */
  68
  69        CPSW_ALE_F_COUNT
  70};
  71
  72/**
  73 * struct cpsw_ale_dev_id - The ALE version/SoC specific configuration
  74 * @dev_id: ALE version/SoC id
  75 * @features: features supported by ALE
  76 * @tbl_entries: number of ALE entries
  77 * @major_ver_mask: mask of ALE Major Version Value in ALE_IDVER reg.
  78 * @nu_switch_ale: NU Switch ALE
  79 * @vlan_entry_tbl: ALE vlan entry fields description tbl
  80 */
  81struct cpsw_ale_dev_id {
  82        const char *dev_id;
  83        u32 features;
  84        u32 tbl_entries;
  85        u32 major_ver_mask;
  86        bool nu_switch_ale;
  87        const struct ale_entry_fld *vlan_entry_tbl;
  88};
  89
  90#define ALE_TABLE_WRITE         BIT(31)
  91
  92#define ALE_TYPE_FREE                   0
  93#define ALE_TYPE_ADDR                   1
  94#define ALE_TYPE_VLAN                   2
  95#define ALE_TYPE_VLAN_ADDR              3
  96
  97#define ALE_UCAST_PERSISTANT            0
  98#define ALE_UCAST_UNTOUCHED             1
  99#define ALE_UCAST_OUI                   2
 100#define ALE_UCAST_TOUCHED               3
 101
 102#define ALE_TABLE_SIZE_MULTIPLIER       1024
 103#define ALE_STATUS_SIZE_MASK            0x1f
 104
 105static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 106{
 107        int idx;
 108
 109        idx    = start / 32;
 110        start -= idx * 32;
 111        idx    = 2 - idx; /* flip */
 112        return (ale_entry[idx] >> start) & BITMASK(bits);
 113}
 114
 115static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
 116                                      u32 value)
 117{
 118        int idx;
 119
 120        value &= BITMASK(bits);
 121        idx    = start / 32;
 122        start -= idx * 32;
 123        idx    = 2 - idx; /* flip */
 124        ale_entry[idx] &= ~(BITMASK(bits) << start);
 125        ale_entry[idx] |=  (value << start);
 126}
 127
 128#define DEFINE_ALE_FIELD(name, start, bits)                             \
 129static inline int cpsw_ale_get_##name(u32 *ale_entry)                   \
 130{                                                                       \
 131        return cpsw_ale_get_field(ale_entry, start, bits);              \
 132}                                                                       \
 133static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)       \
 134{                                                                       \
 135        cpsw_ale_set_field(ale_entry, start, bits, value);              \
 136}
 137
 138#define DEFINE_ALE_FIELD1(name, start)                                  \
 139static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits)         \
 140{                                                                       \
 141        return cpsw_ale_get_field(ale_entry, start, bits);              \
 142}                                                                       \
 143static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value,       \
 144                u32 bits)                                               \
 145{                                                                       \
 146        cpsw_ale_set_field(ale_entry, start, bits, value);              \
 147}
 148
 149enum {
 150        ALE_ENT_VID_MEMBER_LIST = 0,
 151        ALE_ENT_VID_UNREG_MCAST_MSK,
 152        ALE_ENT_VID_REG_MCAST_MSK,
 153        ALE_ENT_VID_FORCE_UNTAGGED_MSK,
 154        ALE_ENT_VID_UNREG_MCAST_IDX,
 155        ALE_ENT_VID_REG_MCAST_IDX,
 156        ALE_ENT_VID_LAST,
 157};
 158
 159#define ALE_FLD_ALLOWED                 BIT(0)
 160#define ALE_FLD_SIZE_PORT_MASK_BITS     BIT(1)
 161#define ALE_FLD_SIZE_PORT_NUM_BITS      BIT(2)
 162
 163#define ALE_ENTRY_FLD(id, start, bits)  \
 164[id] = {                                \
 165        .start_bit = start,             \
 166        .num_bits = bits,               \
 167        .flags = ALE_FLD_ALLOWED,       \
 168}
 169
 170#define ALE_ENTRY_FLD_DYN_MSK_SIZE(id, start)   \
 171[id] = {                                        \
 172        .start_bit = start,                     \
 173        .num_bits = 0,                          \
 174        .flags = ALE_FLD_ALLOWED |              \
 175                 ALE_FLD_SIZE_PORT_MASK_BITS,   \
 176}
 177
 178/* dm814x, am3/am4/am5, k2hk */
 179static const struct ale_entry_fld vlan_entry_cpsw[ALE_ENT_VID_LAST] = {
 180        ALE_ENTRY_FLD(ALE_ENT_VID_MEMBER_LIST, 0, 3),
 181        ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_MSK, 8, 3),
 182        ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_MSK, 16, 3),
 183        ALE_ENTRY_FLD(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24, 3),
 184};
 185
 186/* k2e/k2l, k3 am65/j721e cpsw2g  */
 187static const struct ale_entry_fld vlan_entry_nu[ALE_ENT_VID_LAST] = {
 188        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),
 189        ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_IDX, 20, 3),
 190        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),
 191        ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_IDX, 44, 3),
 192};
 193
 194/* K3 j721e/j7200 cpsw9g/5g, am64x cpsw3g  */
 195static const struct ale_entry_fld vlan_entry_k3_cpswxg[] = {
 196        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),
 197        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_UNREG_MCAST_MSK, 12),
 198        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),
 199        ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_REG_MCAST_MSK, 36),
 200};
 201
 202DEFINE_ALE_FIELD(entry_type,            60,     2)
 203DEFINE_ALE_FIELD(vlan_id,               48,     12)
 204DEFINE_ALE_FIELD(mcast_state,           62,     2)
 205DEFINE_ALE_FIELD1(port_mask,            66)
 206DEFINE_ALE_FIELD(super,                 65,     1)
 207DEFINE_ALE_FIELD(ucast_type,            62,     2)
 208DEFINE_ALE_FIELD1(port_num,             66)
 209DEFINE_ALE_FIELD(blocked,               65,     1)
 210DEFINE_ALE_FIELD(secure,                64,     1)
 211DEFINE_ALE_FIELD(mcast,                 40,     1)
 212
 213#define NU_VLAN_UNREG_MCAST_IDX 1
 214
 215static int cpsw_ale_entry_get_fld(struct cpsw_ale *ale,
 216                                  u32 *ale_entry,
 217                                  const struct ale_entry_fld *entry_tbl,
 218                                  int fld_id)
 219{
 220        const struct ale_entry_fld *entry_fld;
 221        u32 bits;
 222
 223        if (!ale || !ale_entry)
 224                return -EINVAL;
 225
 226        entry_fld = &entry_tbl[fld_id];
 227        if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
 228                dev_err(ale->params.dev, "get: wrong ale fld id %d\n", fld_id);
 229                return -ENOENT;
 230        }
 231
 232        bits = entry_fld->num_bits;
 233        if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
 234                bits = ale->port_mask_bits;
 235
 236        return cpsw_ale_get_field(ale_entry, entry_fld->start_bit, bits);
 237}
 238
 239static void cpsw_ale_entry_set_fld(struct cpsw_ale *ale,
 240                                   u32 *ale_entry,
 241                                   const struct ale_entry_fld *entry_tbl,
 242                                   int fld_id,
 243                                   u32 value)
 244{
 245        const struct ale_entry_fld *entry_fld;
 246        u32 bits;
 247
 248        if (!ale || !ale_entry)
 249                return;
 250
 251        entry_fld = &entry_tbl[fld_id];
 252        if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {
 253                dev_err(ale->params.dev, "set: wrong ale fld id %d\n", fld_id);
 254                return;
 255        }
 256
 257        bits = entry_fld->num_bits;
 258        if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)
 259                bits = ale->port_mask_bits;
 260
 261        cpsw_ale_set_field(ale_entry, entry_fld->start_bit, bits, value);
 262}
 263
 264static int cpsw_ale_vlan_get_fld(struct cpsw_ale *ale,
 265                                 u32 *ale_entry,
 266                                 int fld_id)
 267{
 268        return cpsw_ale_entry_get_fld(ale, ale_entry,
 269                                      ale->vlan_entry_tbl, fld_id);
 270}
 271
 272static void cpsw_ale_vlan_set_fld(struct cpsw_ale *ale,
 273                                  u32 *ale_entry,
 274                                  int fld_id,
 275                                  u32 value)
 276{
 277        cpsw_ale_entry_set_fld(ale, ale_entry,
 278                               ale->vlan_entry_tbl, fld_id, value);
 279}
 280
 281/* The MAC address field in the ALE entry cannot be macroized as above */
 282static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
 283{
 284        int i;
 285
 286        for (i = 0; i < 6; i++)
 287                addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
 288}
 289
 290static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
 291{
 292        int i;
 293
 294        for (i = 0; i < 6; i++)
 295                cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
 296}
 297
 298static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 299{
 300        int i;
 301
 302        WARN_ON(idx > ale->params.ale_entries);
 303
 304        writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
 305
 306        for (i = 0; i < ALE_ENTRY_WORDS; i++)
 307                ale_entry[i] = readl_relaxed(ale->params.ale_regs +
 308                                             ALE_TABLE + 4 * i);
 309
 310        return idx;
 311}
 312
 313static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 314{
 315        int i;
 316
 317        WARN_ON(idx > ale->params.ale_entries);
 318
 319        for (i = 0; i < ALE_ENTRY_WORDS; i++)
 320                writel_relaxed(ale_entry[i], ale->params.ale_regs +
 321                               ALE_TABLE + 4 * i);
 322
 323        writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
 324                       ALE_TABLE_CONTROL);
 325
 326        return idx;
 327}
 328
 329static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
 330{
 331        u32 ale_entry[ALE_ENTRY_WORDS];
 332        int type, idx;
 333
 334        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 335                u8 entry_addr[6];
 336
 337                cpsw_ale_read(ale, idx, ale_entry);
 338                type = cpsw_ale_get_entry_type(ale_entry);
 339                if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 340                        continue;
 341                if (cpsw_ale_get_vlan_id(ale_entry) != vid)
 342                        continue;
 343                cpsw_ale_get_addr(ale_entry, entry_addr);
 344                if (ether_addr_equal(entry_addr, addr))
 345                        return idx;
 346        }
 347        return -ENOENT;
 348}
 349
 350static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
 351{
 352        u32 ale_entry[ALE_ENTRY_WORDS];
 353        int type, idx;
 354
 355        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 356                cpsw_ale_read(ale, idx, ale_entry);
 357                type = cpsw_ale_get_entry_type(ale_entry);
 358                if (type != ALE_TYPE_VLAN)
 359                        continue;
 360                if (cpsw_ale_get_vlan_id(ale_entry) == vid)
 361                        return idx;
 362        }
 363        return -ENOENT;
 364}
 365
 366static int cpsw_ale_match_free(struct cpsw_ale *ale)
 367{
 368        u32 ale_entry[ALE_ENTRY_WORDS];
 369        int type, idx;
 370
 371        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 372                cpsw_ale_read(ale, idx, ale_entry);
 373                type = cpsw_ale_get_entry_type(ale_entry);
 374                if (type == ALE_TYPE_FREE)
 375                        return idx;
 376        }
 377        return -ENOENT;
 378}
 379
 380static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
 381{
 382        u32 ale_entry[ALE_ENTRY_WORDS];
 383        int type, idx;
 384
 385        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 386                cpsw_ale_read(ale, idx, ale_entry);
 387                type = cpsw_ale_get_entry_type(ale_entry);
 388                if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 389                        continue;
 390                if (cpsw_ale_get_mcast(ale_entry))
 391                        continue;
 392                type = cpsw_ale_get_ucast_type(ale_entry);
 393                if (type != ALE_UCAST_PERSISTANT &&
 394                    type != ALE_UCAST_OUI)
 395                        return idx;
 396        }
 397        return -ENOENT;
 398}
 399
 400static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 401                                 int port_mask)
 402{
 403        int mask;
 404
 405        mask = cpsw_ale_get_port_mask(ale_entry,
 406                                      ale->port_mask_bits);
 407        if ((mask & port_mask) == 0)
 408                return; /* ports dont intersect, not interested */
 409        mask &= ~port_mask;
 410
 411        /* free if only remaining port is host port */
 412        if (mask)
 413                cpsw_ale_set_port_mask(ale_entry, mask,
 414                                       ale->port_mask_bits);
 415        else
 416                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 417}
 418
 419int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
 420{
 421        u32 ale_entry[ALE_ENTRY_WORDS];
 422        int ret, idx;
 423
 424        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 425                cpsw_ale_read(ale, idx, ale_entry);
 426                ret = cpsw_ale_get_entry_type(ale_entry);
 427                if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
 428                        continue;
 429
 430                /* if vid passed is -1 then remove all multicast entry from
 431                 * the table irrespective of vlan id, if a valid vlan id is
 432                 * passed then remove only multicast added to that vlan id.
 433                 * if vlan id doesn't match then move on to next entry.
 434                 */
 435                if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
 436                        continue;
 437
 438                if (cpsw_ale_get_mcast(ale_entry)) {
 439                        u8 addr[6];
 440
 441                        if (cpsw_ale_get_super(ale_entry))
 442                                continue;
 443
 444                        cpsw_ale_get_addr(ale_entry, addr);
 445                        if (!is_broadcast_ether_addr(addr))
 446                                cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
 447                }
 448
 449                cpsw_ale_write(ale, idx, ale_entry);
 450        }
 451        return 0;
 452}
 453
 454static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
 455                                                int flags, u16 vid)
 456{
 457        if (flags & ALE_VLAN) {
 458                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
 459                cpsw_ale_set_vlan_id(ale_entry, vid);
 460        } else {
 461                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
 462        }
 463}
 464
 465int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 466                       int flags, u16 vid)
 467{
 468        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 469        int idx;
 470
 471        cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 472
 473        cpsw_ale_set_addr(ale_entry, addr);
 474        cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
 475        cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
 476        cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
 477        cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
 478
 479        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 480        if (idx < 0)
 481                idx = cpsw_ale_match_free(ale);
 482        if (idx < 0)
 483                idx = cpsw_ale_find_ageable(ale);
 484        if (idx < 0)
 485                return -ENOMEM;
 486
 487        cpsw_ale_write(ale, idx, ale_entry);
 488        return 0;
 489}
 490
 491int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 492                       int flags, u16 vid)
 493{
 494        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 495        int idx;
 496
 497        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 498        if (idx < 0)
 499                return -ENOENT;
 500
 501        cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 502        cpsw_ale_write(ale, idx, ale_entry);
 503        return 0;
 504}
 505
 506int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 507                       int flags, u16 vid, int mcast_state)
 508{
 509        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 510        int idx, mask;
 511
 512        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 513        if (idx >= 0)
 514                cpsw_ale_read(ale, idx, ale_entry);
 515
 516        cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 517
 518        cpsw_ale_set_addr(ale_entry, addr);
 519        cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);
 520        cpsw_ale_set_mcast_state(ale_entry, mcast_state);
 521
 522        mask = cpsw_ale_get_port_mask(ale_entry,
 523                                      ale->port_mask_bits);
 524        port_mask |= mask;
 525        cpsw_ale_set_port_mask(ale_entry, port_mask,
 526                               ale->port_mask_bits);
 527
 528        if (idx < 0)
 529                idx = cpsw_ale_match_free(ale);
 530        if (idx < 0)
 531                idx = cpsw_ale_find_ageable(ale);
 532        if (idx < 0)
 533                return -ENOMEM;
 534
 535        cpsw_ale_write(ale, idx, ale_entry);
 536        return 0;
 537}
 538
 539int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 540                       int flags, u16 vid)
 541{
 542        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 543        int mcast_members = 0;
 544        int idx;
 545
 546        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 547        if (idx < 0)
 548                return -ENOENT;
 549
 550        cpsw_ale_read(ale, idx, ale_entry);
 551
 552        if (port_mask) {
 553                mcast_members = cpsw_ale_get_port_mask(ale_entry,
 554                                                       ale->port_mask_bits);
 555                mcast_members &= ~port_mask;
 556        }
 557
 558        if (mcast_members)
 559                cpsw_ale_set_port_mask(ale_entry, mcast_members,
 560                                       ale->port_mask_bits);
 561        else
 562                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 563
 564        cpsw_ale_write(ale, idx, ale_entry);
 565        return 0;
 566}
 567
 568/* ALE NetCP NU switch specific vlan functions */
 569static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 570                                    int reg_mcast, int unreg_mcast)
 571{
 572        int idx;
 573
 574        /* Set VLAN registered multicast flood mask */
 575        idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
 576                                    ALE_ENT_VID_REG_MCAST_IDX);
 577        writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 578
 579        /* Set VLAN unregistered multicast flood mask */
 580        idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
 581                                    ALE_ENT_VID_UNREG_MCAST_IDX);
 582        writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 583}
 584
 585static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry,
 586                                    u16 vid, int untag_mask)
 587{
 588        cpsw_ale_vlan_set_fld(ale, ale_entry,
 589                              ALE_ENT_VID_FORCE_UNTAGGED_MSK,
 590                              untag_mask);
 591        if (untag_mask & ALE_PORT_HOST)
 592                bitmap_set(ale->p0_untag_vid_mask, vid, 1);
 593        else
 594                bitmap_clear(ale->p0_untag_vid_mask, vid, 1);
 595}
 596
 597int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
 598                      int reg_mcast, int unreg_mcast)
 599{
 600        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 601        int idx;
 602
 603        idx = cpsw_ale_match_vlan(ale, vid);
 604        if (idx >= 0)
 605                cpsw_ale_read(ale, idx, ale_entry);
 606
 607        cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
 608        cpsw_ale_set_vlan_id(ale_entry, vid);
 609        cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
 610
 611        if (!ale->params.nu_switch_ale) {
 612                cpsw_ale_vlan_set_fld(ale, ale_entry,
 613                                      ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
 614                cpsw_ale_vlan_set_fld(ale, ale_entry,
 615                                      ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
 616        } else {
 617                cpsw_ale_vlan_set_fld(ale, ale_entry,
 618                                      ALE_ENT_VID_UNREG_MCAST_IDX,
 619                                      NU_VLAN_UNREG_MCAST_IDX);
 620                cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
 621        }
 622
 623        cpsw_ale_vlan_set_fld(ale, ale_entry,
 624                              ALE_ENT_VID_MEMBER_LIST, port_mask);
 625
 626        if (idx < 0)
 627                idx = cpsw_ale_match_free(ale);
 628        if (idx < 0)
 629                idx = cpsw_ale_find_ageable(ale);
 630        if (idx < 0)
 631                return -ENOMEM;
 632
 633        cpsw_ale_write(ale, idx, ale_entry);
 634        return 0;
 635}
 636
 637static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale,  u32 *ale_entry,
 638                                         u16 vid, int port_mask)
 639{
 640        int reg_mcast, unreg_mcast;
 641        int members, untag;
 642
 643        members = cpsw_ale_vlan_get_fld(ale, ale_entry,
 644                                        ALE_ENT_VID_MEMBER_LIST);
 645        members &= ~port_mask;
 646        if (!members) {
 647                cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
 648                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 649                return;
 650        }
 651
 652        untag = cpsw_ale_vlan_get_fld(ale, ale_entry,
 653                                      ALE_ENT_VID_FORCE_UNTAGGED_MSK);
 654        reg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
 655                                          ALE_ENT_VID_REG_MCAST_MSK);
 656        unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
 657                                            ALE_ENT_VID_UNREG_MCAST_MSK);
 658        untag &= members;
 659        reg_mcast &= members;
 660        unreg_mcast &= members;
 661
 662        cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);
 663
 664        if (!ale->params.nu_switch_ale) {
 665                cpsw_ale_vlan_set_fld(ale, ale_entry,
 666                                      ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);
 667                cpsw_ale_vlan_set_fld(ale, ale_entry,
 668                                      ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
 669        } else {
 670                cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast,
 671                                        unreg_mcast);
 672        }
 673        cpsw_ale_vlan_set_fld(ale, ale_entry,
 674                              ALE_ENT_VID_MEMBER_LIST, members);
 675}
 676
 677int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)
 678{
 679        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 680        int idx;
 681
 682        idx = cpsw_ale_match_vlan(ale, vid);
 683        if (idx < 0)
 684                return -ENOENT;
 685
 686        cpsw_ale_read(ale, idx, ale_entry);
 687
 688        cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
 689        cpsw_ale_write(ale, idx, ale_entry);
 690
 691        return 0;
 692}
 693
 694int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
 695{
 696        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 697        int members, idx;
 698
 699        idx = cpsw_ale_match_vlan(ale, vid);
 700        if (idx < 0)
 701                return -ENOENT;
 702
 703        cpsw_ale_read(ale, idx, ale_entry);
 704
 705        /* if !port_mask - force remove VLAN (legacy).
 706         * Check if there are other VLAN members ports
 707         * if no - remove VLAN.
 708         * if yes it means same VLAN was added to >1 port in multi port mode, so
 709         * remove port_mask ports from VLAN ALE entry excluding Host port.
 710         */
 711        members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST);
 712        members &= ~port_mask;
 713
 714        if (!port_mask || !members) {
 715                /* last port or force remove - remove VLAN */
 716                cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);
 717                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 718        } else {
 719                port_mask &= ~ALE_PORT_HOST;
 720                cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);
 721        }
 722
 723        cpsw_ale_write(ale, idx, ale_entry);
 724
 725        return 0;
 726}
 727
 728int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
 729                             int untag_mask, int reg_mask, int unreg_mask)
 730{
 731        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 732        int reg_mcast_members, unreg_mcast_members;
 733        int vlan_members, untag_members;
 734        int idx, ret = 0;
 735
 736        idx = cpsw_ale_match_vlan(ale, vid);
 737        if (idx >= 0)
 738                cpsw_ale_read(ale, idx, ale_entry);
 739
 740        vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
 741                                             ALE_ENT_VID_MEMBER_LIST);
 742        reg_mcast_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
 743                                                  ALE_ENT_VID_REG_MCAST_MSK);
 744        unreg_mcast_members =
 745                cpsw_ale_vlan_get_fld(ale, ale_entry,
 746                                      ALE_ENT_VID_UNREG_MCAST_MSK);
 747        untag_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
 748                                              ALE_ENT_VID_FORCE_UNTAGGED_MSK);
 749
 750        vlan_members |= port_mask;
 751        untag_members = (untag_members & ~port_mask) | untag_mask;
 752        reg_mcast_members = (reg_mcast_members & ~port_mask) | reg_mask;
 753        unreg_mcast_members = (unreg_mcast_members & ~port_mask) | unreg_mask;
 754
 755        ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
 756                                reg_mcast_members, unreg_mcast_members);
 757        if (ret) {
 758                dev_err(ale->params.dev, "Unable to add vlan\n");
 759                return ret;
 760        }
 761        dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,
 762                untag_mask);
 763
 764        return ret;
 765}
 766
 767void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
 768                              bool add)
 769{
 770        u32 ale_entry[ALE_ENTRY_WORDS];
 771        int unreg_members = 0;
 772        int type, idx;
 773
 774        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 775                cpsw_ale_read(ale, idx, ale_entry);
 776                type = cpsw_ale_get_entry_type(ale_entry);
 777                if (type != ALE_TYPE_VLAN)
 778                        continue;
 779
 780                unreg_members =
 781                        cpsw_ale_vlan_get_fld(ale, ale_entry,
 782                                              ALE_ENT_VID_UNREG_MCAST_MSK);
 783                if (add)
 784                        unreg_members |= unreg_mcast_mask;
 785                else
 786                        unreg_members &= ~unreg_mcast_mask;
 787                cpsw_ale_vlan_set_fld(ale, ale_entry,
 788                                      ALE_ENT_VID_UNREG_MCAST_MSK,
 789                                      unreg_members);
 790                cpsw_ale_write(ale, idx, ale_entry);
 791        }
 792}
 793
 794static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 795                                          int allmulti)
 796{
 797        int unreg_mcast;
 798
 799        unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,
 800                                            ALE_ENT_VID_UNREG_MCAST_MSK);
 801        if (allmulti)
 802                unreg_mcast |= ALE_PORT_HOST;
 803        else
 804                unreg_mcast &= ~ALE_PORT_HOST;
 805
 806        cpsw_ale_vlan_set_fld(ale, ale_entry,
 807                              ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);
 808}
 809
 810static void
 811cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale *ale, u32 *ale_entry,
 812                                  int allmulti)
 813{
 814        int unreg_mcast;
 815        int idx;
 816
 817        idx = cpsw_ale_vlan_get_fld(ale, ale_entry,
 818                                    ALE_ENT_VID_UNREG_MCAST_IDX);
 819
 820        unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 821
 822        if (allmulti)
 823                unreg_mcast |= ALE_PORT_HOST;
 824        else
 825                unreg_mcast &= ~ALE_PORT_HOST;
 826
 827        writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 828}
 829
 830void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
 831{
 832        u32 ale_entry[ALE_ENTRY_WORDS];
 833        int type, idx;
 834
 835        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 836                int vlan_members;
 837
 838                cpsw_ale_read(ale, idx, ale_entry);
 839                type = cpsw_ale_get_entry_type(ale_entry);
 840                if (type != ALE_TYPE_VLAN)
 841                        continue;
 842
 843                vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,
 844                                                     ALE_ENT_VID_MEMBER_LIST);
 845
 846                if (port != -1 && !(vlan_members & BIT(port)))
 847                        continue;
 848
 849                if (!ale->params.nu_switch_ale)
 850                        cpsw_ale_vlan_set_unreg_mcast(ale, ale_entry, allmulti);
 851                else
 852                        cpsw_ale_vlan_set_unreg_mcast_idx(ale, ale_entry,
 853                                                          allmulti);
 854
 855                cpsw_ale_write(ale, idx, ale_entry);
 856        }
 857}
 858
 859struct ale_control_info {
 860        const char      *name;
 861        int             offset, port_offset;
 862        int             shift, port_shift;
 863        int             bits;
 864};
 865
 866static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
 867        [ALE_ENABLE]            = {
 868                .name           = "enable",
 869                .offset         = ALE_CONTROL,
 870                .port_offset    = 0,
 871                .shift          = 31,
 872                .port_shift     = 0,
 873                .bits           = 1,
 874        },
 875        [ALE_CLEAR]             = {
 876                .name           = "clear",
 877                .offset         = ALE_CONTROL,
 878                .port_offset    = 0,
 879                .shift          = 30,
 880                .port_shift     = 0,
 881                .bits           = 1,
 882        },
 883        [ALE_AGEOUT]            = {
 884                .name           = "ageout",
 885                .offset         = ALE_CONTROL,
 886                .port_offset    = 0,
 887                .shift          = 29,
 888                .port_shift     = 0,
 889                .bits           = 1,
 890        },
 891        [ALE_P0_UNI_FLOOD]      = {
 892                .name           = "port0_unicast_flood",
 893                .offset         = ALE_CONTROL,
 894                .port_offset    = 0,
 895                .shift          = 8,
 896                .port_shift     = 0,
 897                .bits           = 1,
 898        },
 899        [ALE_VLAN_NOLEARN]      = {
 900                .name           = "vlan_nolearn",
 901                .offset         = ALE_CONTROL,
 902                .port_offset    = 0,
 903                .shift          = 7,
 904                .port_shift     = 0,
 905                .bits           = 1,
 906        },
 907        [ALE_NO_PORT_VLAN]      = {
 908                .name           = "no_port_vlan",
 909                .offset         = ALE_CONTROL,
 910                .port_offset    = 0,
 911                .shift          = 6,
 912                .port_shift     = 0,
 913                .bits           = 1,
 914        },
 915        [ALE_OUI_DENY]          = {
 916                .name           = "oui_deny",
 917                .offset         = ALE_CONTROL,
 918                .port_offset    = 0,
 919                .shift          = 5,
 920                .port_shift     = 0,
 921                .bits           = 1,
 922        },
 923        [ALE_BYPASS]            = {
 924                .name           = "bypass",
 925                .offset         = ALE_CONTROL,
 926                .port_offset    = 0,
 927                .shift          = 4,
 928                .port_shift     = 0,
 929                .bits           = 1,
 930        },
 931        [ALE_RATE_LIMIT_TX]     = {
 932                .name           = "rate_limit_tx",
 933                .offset         = ALE_CONTROL,
 934                .port_offset    = 0,
 935                .shift          = 3,
 936                .port_shift     = 0,
 937                .bits           = 1,
 938        },
 939        [ALE_VLAN_AWARE]        = {
 940                .name           = "vlan_aware",
 941                .offset         = ALE_CONTROL,
 942                .port_offset    = 0,
 943                .shift          = 2,
 944                .port_shift     = 0,
 945                .bits           = 1,
 946        },
 947        [ALE_AUTH_ENABLE]       = {
 948                .name           = "auth_enable",
 949                .offset         = ALE_CONTROL,
 950                .port_offset    = 0,
 951                .shift          = 1,
 952                .port_shift     = 0,
 953                .bits           = 1,
 954        },
 955        [ALE_RATE_LIMIT]        = {
 956                .name           = "rate_limit",
 957                .offset         = ALE_CONTROL,
 958                .port_offset    = 0,
 959                .shift          = 0,
 960                .port_shift     = 0,
 961                .bits           = 1,
 962        },
 963        [ALE_PORT_STATE]        = {
 964                .name           = "port_state",
 965                .offset         = ALE_PORTCTL,
 966                .port_offset    = 4,
 967                .shift          = 0,
 968                .port_shift     = 0,
 969                .bits           = 2,
 970        },
 971        [ALE_PORT_DROP_UNTAGGED] = {
 972                .name           = "drop_untagged",
 973                .offset         = ALE_PORTCTL,
 974                .port_offset    = 4,
 975                .shift          = 2,
 976                .port_shift     = 0,
 977                .bits           = 1,
 978        },
 979        [ALE_PORT_DROP_UNKNOWN_VLAN] = {
 980                .name           = "drop_unknown",
 981                .offset         = ALE_PORTCTL,
 982                .port_offset    = 4,
 983                .shift          = 3,
 984                .port_shift     = 0,
 985                .bits           = 1,
 986        },
 987        [ALE_PORT_NOLEARN]      = {
 988                .name           = "nolearn",
 989                .offset         = ALE_PORTCTL,
 990                .port_offset    = 4,
 991                .shift          = 4,
 992                .port_shift     = 0,
 993                .bits           = 1,
 994        },
 995        [ALE_PORT_NO_SA_UPDATE] = {
 996                .name           = "no_source_update",
 997                .offset         = ALE_PORTCTL,
 998                .port_offset    = 4,
 999                .shift          = 5,
1000                .port_shift     = 0,
1001                .bits           = 1,
1002        },
1003        [ALE_PORT_MACONLY]      = {
1004                .name           = "mac_only_port_mode",
1005                .offset         = ALE_PORTCTL,
1006                .port_offset    = 4,
1007                .shift          = 11,
1008                .port_shift     = 0,
1009                .bits           = 1,
1010        },
1011        [ALE_PORT_MACONLY_CAF]  = {
1012                .name           = "mac_only_port_caf",
1013                .offset         = ALE_PORTCTL,
1014                .port_offset    = 4,
1015                .shift          = 13,
1016                .port_shift     = 0,
1017                .bits           = 1,
1018        },
1019        [ALE_PORT_MCAST_LIMIT]  = {
1020                .name           = "mcast_limit",
1021                .offset         = ALE_PORTCTL,
1022                .port_offset    = 4,
1023                .shift          = 16,
1024                .port_shift     = 0,
1025                .bits           = 8,
1026        },
1027        [ALE_PORT_BCAST_LIMIT]  = {
1028                .name           = "bcast_limit",
1029                .offset         = ALE_PORTCTL,
1030                .port_offset    = 4,
1031                .shift          = 24,
1032                .port_shift     = 0,
1033                .bits           = 8,
1034        },
1035        [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
1036                .name           = "unknown_vlan_member",
1037                .offset         = ALE_UNKNOWNVLAN,
1038                .port_offset    = 0,
1039                .shift          = 0,
1040                .port_shift     = 0,
1041                .bits           = 6,
1042        },
1043        [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
1044                .name           = "unknown_mcast_flood",
1045                .offset         = ALE_UNKNOWNVLAN,
1046                .port_offset    = 0,
1047                .shift          = 8,
1048                .port_shift     = 0,
1049                .bits           = 6,
1050        },
1051        [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
1052                .name           = "unknown_reg_flood",
1053                .offset         = ALE_UNKNOWNVLAN,
1054                .port_offset    = 0,
1055                .shift          = 16,
1056                .port_shift     = 0,
1057                .bits           = 6,
1058        },
1059        [ALE_PORT_UNTAGGED_EGRESS] = {
1060                .name           = "untagged_egress",
1061                .offset         = ALE_UNKNOWNVLAN,
1062                .port_offset    = 0,
1063                .shift          = 24,
1064                .port_shift     = 0,
1065                .bits           = 6,
1066        },
1067        [ALE_DEFAULT_THREAD_ID] = {
1068                .name           = "default_thread_id",
1069                .offset         = AM65_CPSW_ALE_THREAD_DEF_REG,
1070                .port_offset    = 0,
1071                .shift          = 0,
1072                .port_shift     = 0,
1073                .bits           = 6,
1074        },
1075        [ALE_DEFAULT_THREAD_ENABLE] = {
1076                .name           = "default_thread_id_enable",
1077                .offset         = AM65_CPSW_ALE_THREAD_DEF_REG,
1078                .port_offset    = 0,
1079                .shift          = 15,
1080                .port_shift     = 0,
1081                .bits           = 1,
1082        },
1083};
1084
1085int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
1086                         int value)
1087{
1088        const struct ale_control_info *info;
1089        int offset, shift;
1090        u32 tmp, mask;
1091
1092        if (control < 0 || control >= ARRAY_SIZE(ale_controls))
1093                return -EINVAL;
1094
1095        info = &ale_controls[control];
1096        if (info->port_offset == 0 && info->port_shift == 0)
1097                port = 0; /* global, port is a dont care */
1098
1099        if (port < 0 || port >= ale->params.ale_ports)
1100                return -EINVAL;
1101
1102        mask = BITMASK(info->bits);
1103        if (value & ~mask)
1104                return -EINVAL;
1105
1106        offset = info->offset + (port * info->port_offset);
1107        shift  = info->shift  + (port * info->port_shift);
1108
1109        tmp = readl_relaxed(ale->params.ale_regs + offset);
1110        tmp = (tmp & ~(mask << shift)) | (value << shift);
1111        writel_relaxed(tmp, ale->params.ale_regs + offset);
1112
1113        return 0;
1114}
1115
1116int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
1117{
1118        const struct ale_control_info *info;
1119        int offset, shift;
1120        u32 tmp;
1121
1122        if (control < 0 || control >= ARRAY_SIZE(ale_controls))
1123                return -EINVAL;
1124
1125        info = &ale_controls[control];
1126        if (info->port_offset == 0 && info->port_shift == 0)
1127                port = 0; /* global, port is a dont care */
1128
1129        if (port < 0 || port >= ale->params.ale_ports)
1130                return -EINVAL;
1131
1132        offset = info->offset + (port * info->port_offset);
1133        shift  = info->shift  + (port * info->port_shift);
1134
1135        tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
1136        return tmp & BITMASK(info->bits);
1137}
1138
1139static void cpsw_ale_timer(struct timer_list *t)
1140{
1141        struct cpsw_ale *ale = from_timer(ale, t, timer);
1142
1143        cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
1144
1145        if (ale->ageout) {
1146                ale->timer.expires = jiffies + ale->ageout;
1147                add_timer(&ale->timer);
1148        }
1149}
1150
1151static void cpsw_ale_hw_aging_timer_start(struct cpsw_ale *ale)
1152{
1153        u32 aging_timer;
1154
1155        aging_timer = ale->params.bus_freq / 1000000;
1156        aging_timer *= ale->params.ale_ageout;
1157
1158        if (aging_timer & ~ALE_AGING_TIMER_MASK) {
1159                aging_timer = ALE_AGING_TIMER_MASK;
1160                dev_warn(ale->params.dev,
1161                         "ALE aging timer overflow, set to max\n");
1162        }
1163
1164        writel(aging_timer, ale->params.ale_regs + ALE_AGING_TIMER);
1165}
1166
1167static void cpsw_ale_hw_aging_timer_stop(struct cpsw_ale *ale)
1168{
1169        writel(0, ale->params.ale_regs + ALE_AGING_TIMER);
1170}
1171
1172static void cpsw_ale_aging_start(struct cpsw_ale *ale)
1173{
1174        if (!ale->params.ale_ageout)
1175                return;
1176
1177        if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {
1178                cpsw_ale_hw_aging_timer_start(ale);
1179                return;
1180        }
1181
1182        timer_setup(&ale->timer, cpsw_ale_timer, 0);
1183        ale->timer.expires = jiffies + ale->ageout;
1184        add_timer(&ale->timer);
1185}
1186
1187static void cpsw_ale_aging_stop(struct cpsw_ale *ale)
1188{
1189        if (!ale->params.ale_ageout)
1190                return;
1191
1192        if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {
1193                cpsw_ale_hw_aging_timer_stop(ale);
1194                return;
1195        }
1196
1197        del_timer_sync(&ale->timer);
1198}
1199
1200void cpsw_ale_start(struct cpsw_ale *ale)
1201{
1202        cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
1203        cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1204
1205        cpsw_ale_aging_start(ale);
1206}
1207
1208void cpsw_ale_stop(struct cpsw_ale *ale)
1209{
1210        cpsw_ale_aging_stop(ale);
1211        cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1212        cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
1213}
1214
1215static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {
1216        {
1217                /* am3/4/5, dra7. dm814x, 66ak2hk-gbe */
1218                .dev_id = "cpsw",
1219                .tbl_entries = 1024,
1220                .major_ver_mask = 0xff,
1221                .vlan_entry_tbl = vlan_entry_cpsw,
1222        },
1223        {
1224                /* 66ak2h_xgbe */
1225                .dev_id = "66ak2h-xgbe",
1226                .tbl_entries = 2048,
1227                .major_ver_mask = 0xff,
1228                .vlan_entry_tbl = vlan_entry_cpsw,
1229        },
1230        {
1231                .dev_id = "66ak2el",
1232                .features = CPSW_ALE_F_STATUS_REG,
1233                .major_ver_mask = 0x7,
1234                .nu_switch_ale = true,
1235                .vlan_entry_tbl = vlan_entry_nu,
1236        },
1237        {
1238                .dev_id = "66ak2g",
1239                .features = CPSW_ALE_F_STATUS_REG,
1240                .tbl_entries = 64,
1241                .major_ver_mask = 0x7,
1242                .nu_switch_ale = true,
1243                .vlan_entry_tbl = vlan_entry_nu,
1244        },
1245        {
1246                .dev_id = "am65x-cpsw2g",
1247                .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1248                .tbl_entries = 64,
1249                .major_ver_mask = 0x7,
1250                .nu_switch_ale = true,
1251                .vlan_entry_tbl = vlan_entry_nu,
1252        },
1253        {
1254                .dev_id = "j721e-cpswxg",
1255                .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1256                .major_ver_mask = 0x7,
1257                .vlan_entry_tbl = vlan_entry_k3_cpswxg,
1258        },
1259        {
1260                .dev_id = "am64-cpswxg",
1261                .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,
1262                .major_ver_mask = 0x7,
1263                .vlan_entry_tbl = vlan_entry_k3_cpswxg,
1264                .tbl_entries = 512,
1265        },
1266        { },
1267};
1268
1269static const struct
1270cpsw_ale_dev_id *cpsw_ale_match_id(const struct cpsw_ale_dev_id *id,
1271                                   const char *dev_id)
1272{
1273        if (!dev_id)
1274                return NULL;
1275
1276        while (id->dev_id) {
1277                if (strcmp(dev_id, id->dev_id) == 0)
1278                        return id;
1279                id++;
1280        }
1281        return NULL;
1282}
1283
1284struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
1285{
1286        const struct cpsw_ale_dev_id *ale_dev_id;
1287        struct cpsw_ale *ale;
1288        u32 rev, ale_entries;
1289
1290        ale_dev_id = cpsw_ale_match_id(cpsw_ale_id_match, params->dev_id);
1291        if (!ale_dev_id)
1292                return ERR_PTR(-EINVAL);
1293
1294        params->ale_entries = ale_dev_id->tbl_entries;
1295        params->major_ver_mask = ale_dev_id->major_ver_mask;
1296        params->nu_switch_ale = ale_dev_id->nu_switch_ale;
1297
1298        ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);
1299        if (!ale)
1300                return ERR_PTR(-ENOMEM);
1301
1302        ale->p0_untag_vid_mask =
1303                devm_kmalloc_array(params->dev, BITS_TO_LONGS(VLAN_N_VID),
1304                                   sizeof(unsigned long),
1305                                   GFP_KERNEL);
1306        if (!ale->p0_untag_vid_mask)
1307                return ERR_PTR(-ENOMEM);
1308
1309        ale->params = *params;
1310        ale->ageout = ale->params.ale_ageout * HZ;
1311        ale->features = ale_dev_id->features;
1312        ale->vlan_entry_tbl = ale_dev_id->vlan_entry_tbl;
1313
1314        rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
1315        ale->version =
1316                (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
1317                 ALE_VERSION_MINOR(rev);
1318        dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
1319                 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
1320                 ALE_VERSION_MINOR(rev));
1321
1322        if (ale->features & CPSW_ALE_F_STATUS_REG &&
1323            !ale->params.ale_entries) {
1324                ale_entries =
1325                        readl_relaxed(ale->params.ale_regs + ALE_STATUS) &
1326                        ALE_STATUS_SIZE_MASK;
1327                /* ALE available on newer NetCP switches has introduced
1328                 * a register, ALE_STATUS, to indicate the size of ALE
1329                 * table which shows the size as a multiple of 1024 entries.
1330                 * For these, params.ale_entries will be set to zero. So
1331                 * read the register and update the value of ale_entries.
1332                 * return error if ale_entries is zero in ALE_STATUS.
1333                 */
1334                if (!ale_entries)
1335                        return ERR_PTR(-EINVAL);
1336
1337                ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
1338                ale->params.ale_entries = ale_entries;
1339        }
1340        dev_info(ale->params.dev,
1341                 "ALE Table size %ld\n", ale->params.ale_entries);
1342
1343        /* set default bits for existing h/w */
1344        ale->port_mask_bits = ale->params.ale_ports;
1345        ale->port_num_bits = order_base_2(ale->params.ale_ports);
1346        ale->vlan_field_bits = ale->params.ale_ports;
1347
1348        /* Set defaults override for ALE on NetCP NU switch and for version
1349         * 1R3
1350         */
1351        if (ale->params.nu_switch_ale) {
1352                /* Separate registers for unknown vlan configuration.
1353                 * Also there are N bits, where N is number of ale
1354                 * ports and shift value should be 0
1355                 */
1356                ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
1357                                        ale->params.ale_ports;
1358                ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
1359                                        ALE_UNKNOWNVLAN_MEMBER;
1360                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
1361                                        ale->params.ale_ports;
1362                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
1363                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
1364                                        ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
1365                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
1366                                        ale->params.ale_ports;
1367                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
1368                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
1369                                        ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
1370                ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
1371                                        ale->params.ale_ports;
1372                ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
1373                ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
1374                                        ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
1375        }
1376
1377        cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
1378        return ale;
1379}
1380
1381void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
1382{
1383        int i;
1384
1385        for (i = 0; i < ale->params.ale_entries; i++) {
1386                cpsw_ale_read(ale, i, data);
1387                data += ALE_ENTRY_WORDS;
1388        }
1389}
1390
1391u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)
1392{
1393        return ale ? ale->params.ale_entries : 0;
1394}
1395