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/kernel.h>
   9#include <linux/module.h>
  10#include <linux/platform_device.h>
  11#include <linux/seq_file.h>
  12#include <linux/slab.h>
  13#include <linux/err.h>
  14#include <linux/io.h>
  15#include <linux/stat.h>
  16#include <linux/sysfs.h>
  17#include <linux/etherdevice.h>
  18
  19#include "cpsw_ale.h"
  20
  21#define BITMASK(bits)           (BIT(bits) - 1)
  22
  23#define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))
  24#define ALE_VERSION_MINOR(rev)  (rev & 0xff)
  25#define ALE_VERSION_1R3         0x0103
  26#define ALE_VERSION_1R4         0x0104
  27
  28/* ALE Registers */
  29#define ALE_IDVER               0x00
  30#define ALE_STATUS              0x04
  31#define ALE_CONTROL             0x08
  32#define ALE_PRESCALE            0x10
  33#define ALE_UNKNOWNVLAN         0x18
  34#define ALE_TABLE_CONTROL       0x20
  35#define ALE_TABLE               0x34
  36#define ALE_PORTCTL             0x40
  37
  38/* ALE NetCP NU switch specific Registers */
  39#define ALE_UNKNOWNVLAN_MEMBER                  0x90
  40#define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD       0x94
  41#define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD         0x98
  42#define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS      0x9C
  43#define ALE_VLAN_MASK_MUX(reg)                  (0xc0 + (0x4 * (reg)))
  44
  45#define ALE_TABLE_WRITE         BIT(31)
  46
  47#define ALE_TYPE_FREE                   0
  48#define ALE_TYPE_ADDR                   1
  49#define ALE_TYPE_VLAN                   2
  50#define ALE_TYPE_VLAN_ADDR              3
  51
  52#define ALE_UCAST_PERSISTANT            0
  53#define ALE_UCAST_UNTOUCHED             1
  54#define ALE_UCAST_OUI                   2
  55#define ALE_UCAST_TOUCHED               3
  56
  57#define ALE_TABLE_SIZE_MULTIPLIER       1024
  58#define ALE_STATUS_SIZE_MASK            0x1f
  59#define ALE_TABLE_SIZE_DEFAULT          64
  60
  61static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
  62{
  63        int idx;
  64
  65        idx    = start / 32;
  66        start -= idx * 32;
  67        idx    = 2 - idx; /* flip */
  68        return (ale_entry[idx] >> start) & BITMASK(bits);
  69}
  70
  71static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
  72                                      u32 value)
  73{
  74        int idx;
  75
  76        value &= BITMASK(bits);
  77        idx    = start / 32;
  78        start -= idx * 32;
  79        idx    = 2 - idx; /* flip */
  80        ale_entry[idx] &= ~(BITMASK(bits) << start);
  81        ale_entry[idx] |=  (value << start);
  82}
  83
  84#define DEFINE_ALE_FIELD(name, start, bits)                             \
  85static inline int cpsw_ale_get_##name(u32 *ale_entry)                   \
  86{                                                                       \
  87        return cpsw_ale_get_field(ale_entry, start, bits);              \
  88}                                                                       \
  89static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value)       \
  90{                                                                       \
  91        cpsw_ale_set_field(ale_entry, start, bits, value);              \
  92}
  93
  94#define DEFINE_ALE_FIELD1(name, start)                                  \
  95static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits)         \
  96{                                                                       \
  97        return cpsw_ale_get_field(ale_entry, start, bits);              \
  98}                                                                       \
  99static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value,       \
 100                u32 bits)                                               \
 101{                                                                       \
 102        cpsw_ale_set_field(ale_entry, start, bits, value);              \
 103}
 104
 105DEFINE_ALE_FIELD(entry_type,            60,     2)
 106DEFINE_ALE_FIELD(vlan_id,               48,     12)
 107DEFINE_ALE_FIELD(mcast_state,           62,     2)
 108DEFINE_ALE_FIELD1(port_mask,            66)
 109DEFINE_ALE_FIELD(super,                 65,     1)
 110DEFINE_ALE_FIELD(ucast_type,            62,     2)
 111DEFINE_ALE_FIELD1(port_num,             66)
 112DEFINE_ALE_FIELD(blocked,               65,     1)
 113DEFINE_ALE_FIELD(secure,                64,     1)
 114DEFINE_ALE_FIELD1(vlan_untag_force,     24)
 115DEFINE_ALE_FIELD1(vlan_reg_mcast,       16)
 116DEFINE_ALE_FIELD1(vlan_unreg_mcast,     8)
 117DEFINE_ALE_FIELD1(vlan_member_list,     0)
 118DEFINE_ALE_FIELD(mcast,                 40,     1)
 119/* ALE NetCP nu switch specific */
 120DEFINE_ALE_FIELD(vlan_unreg_mcast_idx,  20,     3)
 121DEFINE_ALE_FIELD(vlan_reg_mcast_idx,    44,     3)
 122
 123/* The MAC address field in the ALE entry cannot be macroized as above */
 124static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)
 125{
 126        int i;
 127
 128        for (i = 0; i < 6; i++)
 129                addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);
 130}
 131
 132static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)
 133{
 134        int i;
 135
 136        for (i = 0; i < 6; i++)
 137                cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);
 138}
 139
 140static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 141{
 142        int i;
 143
 144        WARN_ON(idx > ale->params.ale_entries);
 145
 146        writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);
 147
 148        for (i = 0; i < ALE_ENTRY_WORDS; i++)
 149                ale_entry[i] = readl_relaxed(ale->params.ale_regs +
 150                                             ALE_TABLE + 4 * i);
 151
 152        return idx;
 153}
 154
 155static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)
 156{
 157        int i;
 158
 159        WARN_ON(idx > ale->params.ale_entries);
 160
 161        for (i = 0; i < ALE_ENTRY_WORDS; i++)
 162                writel_relaxed(ale_entry[i], ale->params.ale_regs +
 163                               ALE_TABLE + 4 * i);
 164
 165        writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +
 166                       ALE_TABLE_CONTROL);
 167
 168        return idx;
 169}
 170
 171static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)
 172{
 173        u32 ale_entry[ALE_ENTRY_WORDS];
 174        int type, idx;
 175
 176        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 177                u8 entry_addr[6];
 178
 179                cpsw_ale_read(ale, idx, ale_entry);
 180                type = cpsw_ale_get_entry_type(ale_entry);
 181                if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 182                        continue;
 183                if (cpsw_ale_get_vlan_id(ale_entry) != vid)
 184                        continue;
 185                cpsw_ale_get_addr(ale_entry, entry_addr);
 186                if (ether_addr_equal(entry_addr, addr))
 187                        return idx;
 188        }
 189        return -ENOENT;
 190}
 191
 192static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)
 193{
 194        u32 ale_entry[ALE_ENTRY_WORDS];
 195        int type, idx;
 196
 197        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 198                cpsw_ale_read(ale, idx, ale_entry);
 199                type = cpsw_ale_get_entry_type(ale_entry);
 200                if (type != ALE_TYPE_VLAN)
 201                        continue;
 202                if (cpsw_ale_get_vlan_id(ale_entry) == vid)
 203                        return idx;
 204        }
 205        return -ENOENT;
 206}
 207
 208static int cpsw_ale_match_free(struct cpsw_ale *ale)
 209{
 210        u32 ale_entry[ALE_ENTRY_WORDS];
 211        int type, idx;
 212
 213        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 214                cpsw_ale_read(ale, idx, ale_entry);
 215                type = cpsw_ale_get_entry_type(ale_entry);
 216                if (type == ALE_TYPE_FREE)
 217                        return idx;
 218        }
 219        return -ENOENT;
 220}
 221
 222static int cpsw_ale_find_ageable(struct cpsw_ale *ale)
 223{
 224        u32 ale_entry[ALE_ENTRY_WORDS];
 225        int type, idx;
 226
 227        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 228                cpsw_ale_read(ale, idx, ale_entry);
 229                type = cpsw_ale_get_entry_type(ale_entry);
 230                if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)
 231                        continue;
 232                if (cpsw_ale_get_mcast(ale_entry))
 233                        continue;
 234                type = cpsw_ale_get_ucast_type(ale_entry);
 235                if (type != ALE_UCAST_PERSISTANT &&
 236                    type != ALE_UCAST_OUI)
 237                        return idx;
 238        }
 239        return -ENOENT;
 240}
 241
 242static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 243                                 int port_mask)
 244{
 245        int mask;
 246
 247        mask = cpsw_ale_get_port_mask(ale_entry,
 248                                      ale->port_mask_bits);
 249        if ((mask & port_mask) == 0)
 250                return; /* ports dont intersect, not interested */
 251        mask &= ~port_mask;
 252
 253        /* free if only remaining port is host port */
 254        if (mask)
 255                cpsw_ale_set_port_mask(ale_entry, mask,
 256                                       ale->port_mask_bits);
 257        else
 258                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 259}
 260
 261int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)
 262{
 263        u32 ale_entry[ALE_ENTRY_WORDS];
 264        int ret, idx;
 265
 266        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 267                cpsw_ale_read(ale, idx, ale_entry);
 268                ret = cpsw_ale_get_entry_type(ale_entry);
 269                if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
 270                        continue;
 271
 272                /* if vid passed is -1 then remove all multicast entry from
 273                 * the table irrespective of vlan id, if a valid vlan id is
 274                 * passed then remove only multicast added to that vlan id.
 275                 * if vlan id doesn't match then move on to next entry.
 276                 */
 277                if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)
 278                        continue;
 279
 280                if (cpsw_ale_get_mcast(ale_entry)) {
 281                        u8 addr[6];
 282
 283                        if (cpsw_ale_get_super(ale_entry))
 284                                continue;
 285
 286                        cpsw_ale_get_addr(ale_entry, addr);
 287                        if (!is_broadcast_ether_addr(addr))
 288                                cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
 289                }
 290
 291                cpsw_ale_write(ale, idx, ale_entry);
 292        }
 293        return 0;
 294}
 295
 296static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,
 297                                                int flags, u16 vid)
 298{
 299        if (flags & ALE_VLAN) {
 300                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);
 301                cpsw_ale_set_vlan_id(ale_entry, vid);
 302        } else {
 303                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);
 304        }
 305}
 306
 307int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 308                       int flags, u16 vid)
 309{
 310        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 311        int idx;
 312
 313        cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 314
 315        cpsw_ale_set_addr(ale_entry, addr);
 316        cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);
 317        cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);
 318        cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);
 319        cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);
 320
 321        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 322        if (idx < 0)
 323                idx = cpsw_ale_match_free(ale);
 324        if (idx < 0)
 325                idx = cpsw_ale_find_ageable(ale);
 326        if (idx < 0)
 327                return -ENOMEM;
 328
 329        cpsw_ale_write(ale, idx, ale_entry);
 330        return 0;
 331}
 332
 333int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 334                       int flags, u16 vid)
 335{
 336        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 337        int idx;
 338
 339        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 340        if (idx < 0)
 341                return -ENOENT;
 342
 343        cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 344        cpsw_ale_write(ale, idx, ale_entry);
 345        return 0;
 346}
 347
 348int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 349                       int flags, u16 vid, int mcast_state)
 350{
 351        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 352        int idx, mask;
 353
 354        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 355        if (idx >= 0)
 356                cpsw_ale_read(ale, idx, ale_entry);
 357
 358        cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);
 359
 360        cpsw_ale_set_addr(ale_entry, addr);
 361        cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);
 362        cpsw_ale_set_mcast_state(ale_entry, mcast_state);
 363
 364        mask = cpsw_ale_get_port_mask(ale_entry,
 365                                      ale->port_mask_bits);
 366        port_mask |= mask;
 367        cpsw_ale_set_port_mask(ale_entry, port_mask,
 368                               ale->port_mask_bits);
 369
 370        if (idx < 0)
 371                idx = cpsw_ale_match_free(ale);
 372        if (idx < 0)
 373                idx = cpsw_ale_find_ageable(ale);
 374        if (idx < 0)
 375                return -ENOMEM;
 376
 377        cpsw_ale_write(ale, idx, ale_entry);
 378        return 0;
 379}
 380
 381int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,
 382                       int flags, u16 vid)
 383{
 384        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 385        int idx;
 386
 387        idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);
 388        if (idx < 0)
 389                return -ENOENT;
 390
 391        cpsw_ale_read(ale, idx, ale_entry);
 392
 393        if (port_mask)
 394                cpsw_ale_set_port_mask(ale_entry, port_mask,
 395                                       ale->port_mask_bits);
 396        else
 397                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 398
 399        cpsw_ale_write(ale, idx, ale_entry);
 400        return 0;
 401}
 402
 403/* ALE NetCP NU switch specific vlan functions */
 404static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,
 405                                    int reg_mcast, int unreg_mcast)
 406{
 407        int idx;
 408
 409        /* Set VLAN registered multicast flood mask */
 410        idx = cpsw_ale_get_vlan_reg_mcast_idx(ale_entry);
 411        writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 412
 413        /* Set VLAN unregistered multicast flood mask */
 414        idx = cpsw_ale_get_vlan_unreg_mcast_idx(ale_entry);
 415        writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));
 416}
 417
 418int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port, int untag,
 419                      int reg_mcast, int unreg_mcast)
 420{
 421        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 422        int idx;
 423
 424        idx = cpsw_ale_match_vlan(ale, vid);
 425        if (idx >= 0)
 426                cpsw_ale_read(ale, idx, ale_entry);
 427
 428        cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);
 429        cpsw_ale_set_vlan_id(ale_entry, vid);
 430
 431        cpsw_ale_set_vlan_untag_force(ale_entry, untag, ale->vlan_field_bits);
 432        if (!ale->params.nu_switch_ale) {
 433                cpsw_ale_set_vlan_reg_mcast(ale_entry, reg_mcast,
 434                                            ale->vlan_field_bits);
 435                cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
 436                                              ale->vlan_field_bits);
 437        } else {
 438                cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);
 439        }
 440        cpsw_ale_set_vlan_member_list(ale_entry, port, ale->vlan_field_bits);
 441
 442        if (idx < 0)
 443                idx = cpsw_ale_match_free(ale);
 444        if (idx < 0)
 445                idx = cpsw_ale_find_ageable(ale);
 446        if (idx < 0)
 447                return -ENOMEM;
 448
 449        cpsw_ale_write(ale, idx, ale_entry);
 450        return 0;
 451}
 452
 453int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)
 454{
 455        u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 456        int idx;
 457
 458        idx = cpsw_ale_match_vlan(ale, vid);
 459        if (idx < 0)
 460                return -ENOENT;
 461
 462        cpsw_ale_read(ale, idx, ale_entry);
 463
 464        if (port_mask)
 465                cpsw_ale_set_vlan_member_list(ale_entry, port_mask,
 466                                              ale->vlan_field_bits);
 467        else
 468                cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
 469
 470        cpsw_ale_write(ale, idx, ale_entry);
 471        return 0;
 472}
 473
 474void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)
 475{
 476        u32 ale_entry[ALE_ENTRY_WORDS];
 477        int unreg_mcast = 0;
 478        int type, idx;
 479
 480        for (idx = 0; idx < ale->params.ale_entries; idx++) {
 481                int vlan_members;
 482
 483                cpsw_ale_read(ale, idx, ale_entry);
 484                type = cpsw_ale_get_entry_type(ale_entry);
 485                if (type != ALE_TYPE_VLAN)
 486                        continue;
 487                vlan_members =
 488                        cpsw_ale_get_vlan_member_list(ale_entry,
 489                                                      ale->vlan_field_bits);
 490
 491                if (port != -1 && !(vlan_members & BIT(port)))
 492                        continue;
 493
 494                unreg_mcast =
 495                        cpsw_ale_get_vlan_unreg_mcast(ale_entry,
 496                                                      ale->vlan_field_bits);
 497                if (allmulti)
 498                        unreg_mcast |= ALE_PORT_HOST;
 499                else
 500                        unreg_mcast &= ~ALE_PORT_HOST;
 501                cpsw_ale_set_vlan_unreg_mcast(ale_entry, unreg_mcast,
 502                                              ale->vlan_field_bits);
 503                cpsw_ale_write(ale, idx, ale_entry);
 504        }
 505}
 506
 507struct ale_control_info {
 508        const char      *name;
 509        int             offset, port_offset;
 510        int             shift, port_shift;
 511        int             bits;
 512};
 513
 514static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {
 515        [ALE_ENABLE]            = {
 516                .name           = "enable",
 517                .offset         = ALE_CONTROL,
 518                .port_offset    = 0,
 519                .shift          = 31,
 520                .port_shift     = 0,
 521                .bits           = 1,
 522        },
 523        [ALE_CLEAR]             = {
 524                .name           = "clear",
 525                .offset         = ALE_CONTROL,
 526                .port_offset    = 0,
 527                .shift          = 30,
 528                .port_shift     = 0,
 529                .bits           = 1,
 530        },
 531        [ALE_AGEOUT]            = {
 532                .name           = "ageout",
 533                .offset         = ALE_CONTROL,
 534                .port_offset    = 0,
 535                .shift          = 29,
 536                .port_shift     = 0,
 537                .bits           = 1,
 538        },
 539        [ALE_P0_UNI_FLOOD]      = {
 540                .name           = "port0_unicast_flood",
 541                .offset         = ALE_CONTROL,
 542                .port_offset    = 0,
 543                .shift          = 8,
 544                .port_shift     = 0,
 545                .bits           = 1,
 546        },
 547        [ALE_VLAN_NOLEARN]      = {
 548                .name           = "vlan_nolearn",
 549                .offset         = ALE_CONTROL,
 550                .port_offset    = 0,
 551                .shift          = 7,
 552                .port_shift     = 0,
 553                .bits           = 1,
 554        },
 555        [ALE_NO_PORT_VLAN]      = {
 556                .name           = "no_port_vlan",
 557                .offset         = ALE_CONTROL,
 558                .port_offset    = 0,
 559                .shift          = 6,
 560                .port_shift     = 0,
 561                .bits           = 1,
 562        },
 563        [ALE_OUI_DENY]          = {
 564                .name           = "oui_deny",
 565                .offset         = ALE_CONTROL,
 566                .port_offset    = 0,
 567                .shift          = 5,
 568                .port_shift     = 0,
 569                .bits           = 1,
 570        },
 571        [ALE_BYPASS]            = {
 572                .name           = "bypass",
 573                .offset         = ALE_CONTROL,
 574                .port_offset    = 0,
 575                .shift          = 4,
 576                .port_shift     = 0,
 577                .bits           = 1,
 578        },
 579        [ALE_RATE_LIMIT_TX]     = {
 580                .name           = "rate_limit_tx",
 581                .offset         = ALE_CONTROL,
 582                .port_offset    = 0,
 583                .shift          = 3,
 584                .port_shift     = 0,
 585                .bits           = 1,
 586        },
 587        [ALE_VLAN_AWARE]        = {
 588                .name           = "vlan_aware",
 589                .offset         = ALE_CONTROL,
 590                .port_offset    = 0,
 591                .shift          = 2,
 592                .port_shift     = 0,
 593                .bits           = 1,
 594        },
 595        [ALE_AUTH_ENABLE]       = {
 596                .name           = "auth_enable",
 597                .offset         = ALE_CONTROL,
 598                .port_offset    = 0,
 599                .shift          = 1,
 600                .port_shift     = 0,
 601                .bits           = 1,
 602        },
 603        [ALE_RATE_LIMIT]        = {
 604                .name           = "rate_limit",
 605                .offset         = ALE_CONTROL,
 606                .port_offset    = 0,
 607                .shift          = 0,
 608                .port_shift     = 0,
 609                .bits           = 1,
 610        },
 611        [ALE_PORT_STATE]        = {
 612                .name           = "port_state",
 613                .offset         = ALE_PORTCTL,
 614                .port_offset    = 4,
 615                .shift          = 0,
 616                .port_shift     = 0,
 617                .bits           = 2,
 618        },
 619        [ALE_PORT_DROP_UNTAGGED] = {
 620                .name           = "drop_untagged",
 621                .offset         = ALE_PORTCTL,
 622                .port_offset    = 4,
 623                .shift          = 2,
 624                .port_shift     = 0,
 625                .bits           = 1,
 626        },
 627        [ALE_PORT_DROP_UNKNOWN_VLAN] = {
 628                .name           = "drop_unknown",
 629                .offset         = ALE_PORTCTL,
 630                .port_offset    = 4,
 631                .shift          = 3,
 632                .port_shift     = 0,
 633                .bits           = 1,
 634        },
 635        [ALE_PORT_NOLEARN]      = {
 636                .name           = "nolearn",
 637                .offset         = ALE_PORTCTL,
 638                .port_offset    = 4,
 639                .shift          = 4,
 640                .port_shift     = 0,
 641                .bits           = 1,
 642        },
 643        [ALE_PORT_NO_SA_UPDATE] = {
 644                .name           = "no_source_update",
 645                .offset         = ALE_PORTCTL,
 646                .port_offset    = 4,
 647                .shift          = 5,
 648                .port_shift     = 0,
 649                .bits           = 1,
 650        },
 651        [ALE_PORT_MCAST_LIMIT]  = {
 652                .name           = "mcast_limit",
 653                .offset         = ALE_PORTCTL,
 654                .port_offset    = 4,
 655                .shift          = 16,
 656                .port_shift     = 0,
 657                .bits           = 8,
 658        },
 659        [ALE_PORT_BCAST_LIMIT]  = {
 660                .name           = "bcast_limit",
 661                .offset         = ALE_PORTCTL,
 662                .port_offset    = 4,
 663                .shift          = 24,
 664                .port_shift     = 0,
 665                .bits           = 8,
 666        },
 667        [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {
 668                .name           = "unknown_vlan_member",
 669                .offset         = ALE_UNKNOWNVLAN,
 670                .port_offset    = 0,
 671                .shift          = 0,
 672                .port_shift     = 0,
 673                .bits           = 6,
 674        },
 675        [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {
 676                .name           = "unknown_mcast_flood",
 677                .offset         = ALE_UNKNOWNVLAN,
 678                .port_offset    = 0,
 679                .shift          = 8,
 680                .port_shift     = 0,
 681                .bits           = 6,
 682        },
 683        [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {
 684                .name           = "unknown_reg_flood",
 685                .offset         = ALE_UNKNOWNVLAN,
 686                .port_offset    = 0,
 687                .shift          = 16,
 688                .port_shift     = 0,
 689                .bits           = 6,
 690        },
 691        [ALE_PORT_UNTAGGED_EGRESS] = {
 692                .name           = "untagged_egress",
 693                .offset         = ALE_UNKNOWNVLAN,
 694                .port_offset    = 0,
 695                .shift          = 24,
 696                .port_shift     = 0,
 697                .bits           = 6,
 698        },
 699};
 700
 701int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,
 702                         int value)
 703{
 704        const struct ale_control_info *info;
 705        int offset, shift;
 706        u32 tmp, mask;
 707
 708        if (control < 0 || control >= ARRAY_SIZE(ale_controls))
 709                return -EINVAL;
 710
 711        info = &ale_controls[control];
 712        if (info->port_offset == 0 && info->port_shift == 0)
 713                port = 0; /* global, port is a dont care */
 714
 715        if (port < 0 || port >= ale->params.ale_ports)
 716                return -EINVAL;
 717
 718        mask = BITMASK(info->bits);
 719        if (value & ~mask)
 720                return -EINVAL;
 721
 722        offset = info->offset + (port * info->port_offset);
 723        shift  = info->shift  + (port * info->port_shift);
 724
 725        tmp = readl_relaxed(ale->params.ale_regs + offset);
 726        tmp = (tmp & ~(mask << shift)) | (value << shift);
 727        writel_relaxed(tmp, ale->params.ale_regs + offset);
 728
 729        return 0;
 730}
 731
 732int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)
 733{
 734        const struct ale_control_info *info;
 735        int offset, shift;
 736        u32 tmp;
 737
 738        if (control < 0 || control >= ARRAY_SIZE(ale_controls))
 739                return -EINVAL;
 740
 741        info = &ale_controls[control];
 742        if (info->port_offset == 0 && info->port_shift == 0)
 743                port = 0; /* global, port is a dont care */
 744
 745        if (port < 0 || port >= ale->params.ale_ports)
 746                return -EINVAL;
 747
 748        offset = info->offset + (port * info->port_offset);
 749        shift  = info->shift  + (port * info->port_shift);
 750
 751        tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;
 752        return tmp & BITMASK(info->bits);
 753}
 754
 755static void cpsw_ale_timer(struct timer_list *t)
 756{
 757        struct cpsw_ale *ale = from_timer(ale, t, timer);
 758
 759        cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);
 760
 761        if (ale->ageout) {
 762                ale->timer.expires = jiffies + ale->ageout;
 763                add_timer(&ale->timer);
 764        }
 765}
 766
 767void cpsw_ale_start(struct cpsw_ale *ale)
 768{
 769        cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);
 770        cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);
 771
 772        timer_setup(&ale->timer, cpsw_ale_timer, 0);
 773        if (ale->ageout) {
 774                ale->timer.expires = jiffies + ale->ageout;
 775                add_timer(&ale->timer);
 776        }
 777}
 778
 779void cpsw_ale_stop(struct cpsw_ale *ale)
 780{
 781        del_timer_sync(&ale->timer);
 782        cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);
 783}
 784
 785struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)
 786{
 787        struct cpsw_ale *ale;
 788        u32 rev, ale_entries;
 789
 790        ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);
 791        if (!ale)
 792                return NULL;
 793
 794        ale->params = *params;
 795        ale->ageout = ale->params.ale_ageout * HZ;
 796
 797        rev = readl_relaxed(ale->params.ale_regs + ALE_IDVER);
 798        if (!ale->params.major_ver_mask)
 799                ale->params.major_ver_mask = 0xff;
 800        ale->version =
 801                (ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask) << 8) |
 802                 ALE_VERSION_MINOR(rev);
 803        dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",
 804                 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
 805                 ALE_VERSION_MINOR(rev));
 806
 807        if (!ale->params.ale_entries) {
 808                ale_entries =
 809                        readl_relaxed(ale->params.ale_regs + ALE_STATUS) &
 810                        ALE_STATUS_SIZE_MASK;
 811                /* ALE available on newer NetCP switches has introduced
 812                 * a register, ALE_STATUS, to indicate the size of ALE
 813                 * table which shows the size as a multiple of 1024 entries.
 814                 * For these, params.ale_entries will be set to zero. So
 815                 * read the register and update the value of ale_entries.
 816                 * ALE table on NetCP lite, is much smaller and is indicated
 817                 * by a value of zero in ALE_STATUS. So use a default value
 818                 * of ALE_TABLE_SIZE_DEFAULT for this. Caller is expected
 819                 * to set the value of ale_entries for all other versions
 820                 * of ALE.
 821                 */
 822                if (!ale_entries)
 823                        ale_entries = ALE_TABLE_SIZE_DEFAULT;
 824                else
 825                        ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
 826                ale->params.ale_entries = ale_entries;
 827        }
 828        dev_info(ale->params.dev,
 829                 "ALE Table size %ld\n", ale->params.ale_entries);
 830
 831        /* set default bits for existing h/w */
 832        ale->port_mask_bits = ale->params.ale_ports;
 833        ale->port_num_bits = order_base_2(ale->params.ale_ports);
 834        ale->vlan_field_bits = ale->params.ale_ports;
 835
 836        /* Set defaults override for ALE on NetCP NU switch and for version
 837         * 1R3
 838         */
 839        if (ale->params.nu_switch_ale) {
 840                /* Separate registers for unknown vlan configuration.
 841                 * Also there are N bits, where N is number of ale
 842                 * ports and shift value should be 0
 843                 */
 844                ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =
 845                                        ale->params.ale_ports;
 846                ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =
 847                                        ALE_UNKNOWNVLAN_MEMBER;
 848                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =
 849                                        ale->params.ale_ports;
 850                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;
 851                ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =
 852                                        ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;
 853                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =
 854                                        ale->params.ale_ports;
 855                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;
 856                ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =
 857                                        ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;
 858                ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =
 859                                        ale->params.ale_ports;
 860                ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;
 861                ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =
 862                                        ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;
 863        }
 864
 865        return ale;
 866}
 867
 868void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
 869{
 870        int i;
 871
 872        for (i = 0; i < ale->params.ale_entries; i++) {
 873                cpsw_ale_read(ale, i, data);
 874                data += ALE_ENTRY_WORDS;
 875        }
 876}
 877