1734 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Texas Instruments N-Port Ethernet Switch Address Lookup Engine4 *5 * Copyright (C) 2012 Texas Instruments6 *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/regmap.h>14#include <linux/seq_file.h>15#include <linux/slab.h>16#include <linux/err.h>17#include <linux/io.h>18#include <linux/stat.h>19#include <linux/sysfs.h>20#include <linux/etherdevice.h>21 22#include "cpsw_ale.h"23 24#define BITMASK(bits) (BIT(bits) - 1)25 26#define ALE_VERSION_MAJOR(rev, mask) (((rev) >> 8) & (mask))27#define ALE_VERSION_MINOR(rev) (rev & 0xff)28#define ALE_VERSION_1R3 0x010329#define ALE_VERSION_1R4 0x010430 31/* ALE Registers */32#define ALE_IDVER 0x0033#define ALE_STATUS 0x0434#define ALE_CONTROL 0x0835#define ALE_PRESCALE 0x1036#define ALE_AGING_TIMER 0x1437#define ALE_UNKNOWNVLAN 0x1838#define ALE_TABLE_CONTROL 0x2039#define ALE_TABLE 0x3440#define ALE_PORTCTL 0x4041 42/* ALE NetCP NU switch specific Registers */43#define ALE_UNKNOWNVLAN_MEMBER 0x9044#define ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD 0x9445#define ALE_UNKNOWNVLAN_REG_MCAST_FLOOD 0x9846#define ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS 0x9C47#define ALE_VLAN_MASK_MUX(reg) (0xc0 + (0x4 * (reg)))48 49#define ALE_POLICER_PORT_OUI 0x10050#define ALE_POLICER_DA_SA 0x10451#define ALE_POLICER_VLAN 0x10852#define ALE_POLICER_ETHERTYPE_IPSA 0x10c53#define ALE_POLICER_IPDA 0x11054#define ALE_POLICER_PIR 0x11855#define ALE_POLICER_CIR 0x11c56#define ALE_POLICER_TBL_CTL 0x12057#define ALE_POLICER_CTL 0x12458#define ALE_POLICER_TEST_CTL 0x12859#define ALE_POLICER_HIT_STATUS 0x12c60#define ALE_THREAD_DEF 0x13461#define ALE_THREAD_CTL 0x13862#define ALE_THREAD_VAL 0x13c63 64#define ALE_POLICER_TBL_WRITE_ENABLE BIT(31)65#define ALE_POLICER_TBL_INDEX_MASK GENMASK(4, 0)66 67#define AM65_CPSW_ALE_THREAD_DEF_REG 0x13468 69/* ALE_AGING_TIMER */70#define ALE_AGING_TIMER_MASK GENMASK(23, 0)71 72#define ALE_RATE_LIMIT_MIN_PPS 100073 74/**75 * struct ale_entry_fld - The ALE tbl entry field description76 * @start_bit: field start bit77 * @num_bits: field bit length78 * @flags: field flags79 */80struct ale_entry_fld {81 u8 start_bit;82 u8 num_bits;83 u8 flags;84};85 86enum {87 CPSW_ALE_F_STATUS_REG = BIT(0), /* Status register present */88 CPSW_ALE_F_HW_AUTOAGING = BIT(1), /* HW auto aging */89 90 CPSW_ALE_F_COUNT91};92 93/**94 * struct cpsw_ale_dev_id - The ALE version/SoC specific configuration95 * @dev_id: ALE version/SoC id96 * @features: features supported by ALE97 * @tbl_entries: number of ALE entries98 * @reg_fields: pointer to array of register field configuration99 * @num_fields: number of fields in the reg_fields array100 * @nu_switch_ale: NU Switch ALE101 * @vlan_entry_tbl: ALE vlan entry fields description tbl102 */103struct cpsw_ale_dev_id {104 const char *dev_id;105 u32 features;106 u32 tbl_entries;107 const struct reg_field *reg_fields;108 int num_fields;109 bool nu_switch_ale;110 const struct ale_entry_fld *vlan_entry_tbl;111};112 113#define ALE_TABLE_WRITE BIT(31)114 115#define ALE_TYPE_FREE 0116#define ALE_TYPE_ADDR 1117#define ALE_TYPE_VLAN 2118#define ALE_TYPE_VLAN_ADDR 3119 120#define ALE_UCAST_PERSISTANT 0121#define ALE_UCAST_UNTOUCHED 1122#define ALE_UCAST_OUI 2123#define ALE_UCAST_TOUCHED 3124 125#define ALE_TABLE_SIZE_MULTIPLIER 1024126#define ALE_POLICER_SIZE_MULTIPLIER 8127 128static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)129{130 int idx, idx2;131 u32 hi_val = 0;132 133 idx = start / 32;134 idx2 = (start + bits - 1) / 32;135 /* Check if bits to be fetched exceed a word */136 if (idx != idx2) {137 idx2 = 2 - idx2; /* flip */138 hi_val = ale_entry[idx2] << ((idx2 * 32) - start);139 }140 start -= idx * 32;141 idx = 2 - idx; /* flip */142 return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);143}144 145static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,146 u32 value)147{148 int idx, idx2;149 150 value &= BITMASK(bits);151 idx = start / 32;152 idx2 = (start + bits - 1) / 32;153 /* Check if bits to be set exceed a word */154 if (idx != idx2) {155 idx2 = 2 - idx2; /* flip */156 ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));157 ale_entry[idx2] |= (value >> ((idx2 * 32) - start));158 }159 start -= idx * 32;160 idx = 2 - idx; /* flip */161 ale_entry[idx] &= ~(BITMASK(bits) << start);162 ale_entry[idx] |= (value << start);163}164 165#define DEFINE_ALE_FIELD(name, start, bits) \166static inline int cpsw_ale_get_##name(u32 *ale_entry) \167{ \168 return cpsw_ale_get_field(ale_entry, start, bits); \169} \170static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value) \171{ \172 cpsw_ale_set_field(ale_entry, start, bits, value); \173}174 175#define DEFINE_ALE_FIELD1(name, start) \176static inline int cpsw_ale_get_##name(u32 *ale_entry, u32 bits) \177{ \178 return cpsw_ale_get_field(ale_entry, start, bits); \179} \180static inline void cpsw_ale_set_##name(u32 *ale_entry, u32 value, \181 u32 bits) \182{ \183 cpsw_ale_set_field(ale_entry, start, bits, value); \184}185 186enum {187 ALE_ENT_VID_MEMBER_LIST = 0,188 ALE_ENT_VID_UNREG_MCAST_MSK,189 ALE_ENT_VID_REG_MCAST_MSK,190 ALE_ENT_VID_FORCE_UNTAGGED_MSK,191 ALE_ENT_VID_UNREG_MCAST_IDX,192 ALE_ENT_VID_REG_MCAST_IDX,193 ALE_ENT_VID_LAST,194};195 196#define ALE_FLD_ALLOWED BIT(0)197#define ALE_FLD_SIZE_PORT_MASK_BITS BIT(1)198#define ALE_FLD_SIZE_PORT_NUM_BITS BIT(2)199 200#define ALE_ENTRY_FLD(id, start, bits) \201[id] = { \202 .start_bit = start, \203 .num_bits = bits, \204 .flags = ALE_FLD_ALLOWED, \205}206 207#define ALE_ENTRY_FLD_DYN_MSK_SIZE(id, start) \208[id] = { \209 .start_bit = start, \210 .num_bits = 0, \211 .flags = ALE_FLD_ALLOWED | \212 ALE_FLD_SIZE_PORT_MASK_BITS, \213}214 215/* dm814x, am3/am4/am5, k2hk */216static const struct ale_entry_fld vlan_entry_cpsw[ALE_ENT_VID_LAST] = {217 ALE_ENTRY_FLD(ALE_ENT_VID_MEMBER_LIST, 0, 3),218 ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_MSK, 8, 3),219 ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_MSK, 16, 3),220 ALE_ENTRY_FLD(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24, 3),221};222 223/* k2e/k2l, k3 am65/j721e cpsw2g */224static const struct ale_entry_fld vlan_entry_nu[ALE_ENT_VID_LAST] = {225 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),226 ALE_ENTRY_FLD(ALE_ENT_VID_UNREG_MCAST_IDX, 20, 3),227 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),228 ALE_ENTRY_FLD(ALE_ENT_VID_REG_MCAST_IDX, 44, 3),229};230 231/* K3 j721e/j7200 cpsw9g/5g, am64x cpsw3g */232static const struct ale_entry_fld vlan_entry_k3_cpswxg[] = {233 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_MEMBER_LIST, 0),234 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_UNREG_MCAST_MSK, 12),235 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_FORCE_UNTAGGED_MSK, 24),236 ALE_ENTRY_FLD_DYN_MSK_SIZE(ALE_ENT_VID_REG_MCAST_MSK, 36),237};238 239DEFINE_ALE_FIELD(entry_type, 60, 2)240DEFINE_ALE_FIELD(vlan_id, 48, 12)241DEFINE_ALE_FIELD(mcast_state, 62, 2)242DEFINE_ALE_FIELD1(port_mask, 66)243DEFINE_ALE_FIELD(super, 65, 1)244DEFINE_ALE_FIELD(ucast_type, 62, 2)245DEFINE_ALE_FIELD1(port_num, 66)246DEFINE_ALE_FIELD(blocked, 65, 1)247DEFINE_ALE_FIELD(secure, 64, 1)248DEFINE_ALE_FIELD(mcast, 40, 1)249 250#define NU_VLAN_UNREG_MCAST_IDX 1251 252static int cpsw_ale_entry_get_fld(struct cpsw_ale *ale,253 u32 *ale_entry,254 const struct ale_entry_fld *entry_tbl,255 int fld_id)256{257 const struct ale_entry_fld *entry_fld;258 u32 bits;259 260 if (!ale || !ale_entry)261 return -EINVAL;262 263 entry_fld = &entry_tbl[fld_id];264 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {265 dev_err(ale->params.dev, "get: wrong ale fld id %d\n", fld_id);266 return -ENOENT;267 }268 269 bits = entry_fld->num_bits;270 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)271 bits = ale->port_mask_bits;272 273 return cpsw_ale_get_field(ale_entry, entry_fld->start_bit, bits);274}275 276static void cpsw_ale_entry_set_fld(struct cpsw_ale *ale,277 u32 *ale_entry,278 const struct ale_entry_fld *entry_tbl,279 int fld_id,280 u32 value)281{282 const struct ale_entry_fld *entry_fld;283 u32 bits;284 285 if (!ale || !ale_entry)286 return;287 288 entry_fld = &entry_tbl[fld_id];289 if (!(entry_fld->flags & ALE_FLD_ALLOWED)) {290 dev_err(ale->params.dev, "set: wrong ale fld id %d\n", fld_id);291 return;292 }293 294 bits = entry_fld->num_bits;295 if (entry_fld->flags & ALE_FLD_SIZE_PORT_MASK_BITS)296 bits = ale->port_mask_bits;297 298 cpsw_ale_set_field(ale_entry, entry_fld->start_bit, bits, value);299}300 301static int cpsw_ale_vlan_get_fld(struct cpsw_ale *ale,302 u32 *ale_entry,303 int fld_id)304{305 return cpsw_ale_entry_get_fld(ale, ale_entry,306 ale->vlan_entry_tbl, fld_id);307}308 309static void cpsw_ale_vlan_set_fld(struct cpsw_ale *ale,310 u32 *ale_entry,311 int fld_id,312 u32 value)313{314 cpsw_ale_entry_set_fld(ale, ale_entry,315 ale->vlan_entry_tbl, fld_id, value);316}317 318/* The MAC address field in the ALE entry cannot be macroized as above */319static inline void cpsw_ale_get_addr(u32 *ale_entry, u8 *addr)320{321 int i;322 323 for (i = 0; i < 6; i++)324 addr[i] = cpsw_ale_get_field(ale_entry, 40 - 8*i, 8);325}326 327static inline void cpsw_ale_set_addr(u32 *ale_entry, const u8 *addr)328{329 int i;330 331 for (i = 0; i < 6; i++)332 cpsw_ale_set_field(ale_entry, 40 - 8*i, 8, addr[i]);333}334 335static int cpsw_ale_read(struct cpsw_ale *ale, int idx, u32 *ale_entry)336{337 int i;338 339 WARN_ON(idx > ale->params.ale_entries);340 341 writel_relaxed(idx, ale->params.ale_regs + ALE_TABLE_CONTROL);342 343 for (i = 0; i < ALE_ENTRY_WORDS; i++)344 ale_entry[i] = readl_relaxed(ale->params.ale_regs +345 ALE_TABLE + 4 * i);346 347 return idx;348}349 350static int cpsw_ale_write(struct cpsw_ale *ale, int idx, u32 *ale_entry)351{352 int i;353 354 WARN_ON(idx > ale->params.ale_entries);355 356 for (i = 0; i < ALE_ENTRY_WORDS; i++)357 writel_relaxed(ale_entry[i], ale->params.ale_regs +358 ALE_TABLE + 4 * i);359 360 writel_relaxed(idx | ALE_TABLE_WRITE, ale->params.ale_regs +361 ALE_TABLE_CONTROL);362 363 return idx;364}365 366static int cpsw_ale_match_addr(struct cpsw_ale *ale, const u8 *addr, u16 vid)367{368 u32 ale_entry[ALE_ENTRY_WORDS];369 int type, idx;370 371 for (idx = 0; idx < ale->params.ale_entries; idx++) {372 u8 entry_addr[6];373 374 cpsw_ale_read(ale, idx, ale_entry);375 type = cpsw_ale_get_entry_type(ale_entry);376 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)377 continue;378 if (cpsw_ale_get_vlan_id(ale_entry) != vid)379 continue;380 cpsw_ale_get_addr(ale_entry, entry_addr);381 if (ether_addr_equal(entry_addr, addr))382 return idx;383 }384 return -ENOENT;385}386 387static int cpsw_ale_match_vlan(struct cpsw_ale *ale, u16 vid)388{389 u32 ale_entry[ALE_ENTRY_WORDS];390 int type, idx;391 392 for (idx = 0; idx < ale->params.ale_entries; idx++) {393 cpsw_ale_read(ale, idx, ale_entry);394 type = cpsw_ale_get_entry_type(ale_entry);395 if (type != ALE_TYPE_VLAN)396 continue;397 if (cpsw_ale_get_vlan_id(ale_entry) == vid)398 return idx;399 }400 return -ENOENT;401}402 403static int cpsw_ale_match_free(struct cpsw_ale *ale)404{405 u32 ale_entry[ALE_ENTRY_WORDS];406 int type, idx;407 408 for (idx = 0; idx < ale->params.ale_entries; idx++) {409 cpsw_ale_read(ale, idx, ale_entry);410 type = cpsw_ale_get_entry_type(ale_entry);411 if (type == ALE_TYPE_FREE)412 return idx;413 }414 return -ENOENT;415}416 417static int cpsw_ale_find_ageable(struct cpsw_ale *ale)418{419 u32 ale_entry[ALE_ENTRY_WORDS];420 int type, idx;421 422 for (idx = 0; idx < ale->params.ale_entries; idx++) {423 cpsw_ale_read(ale, idx, ale_entry);424 type = cpsw_ale_get_entry_type(ale_entry);425 if (type != ALE_TYPE_ADDR && type != ALE_TYPE_VLAN_ADDR)426 continue;427 if (cpsw_ale_get_mcast(ale_entry))428 continue;429 type = cpsw_ale_get_ucast_type(ale_entry);430 if (type != ALE_UCAST_PERSISTANT &&431 type != ALE_UCAST_OUI)432 return idx;433 }434 return -ENOENT;435}436 437static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,438 int port_mask)439{440 int mask;441 442 mask = cpsw_ale_get_port_mask(ale_entry,443 ale->port_mask_bits);444 if ((mask & port_mask) == 0)445 return; /* ports dont intersect, not interested */446 mask &= ~port_mask;447 448 /* free if only remaining port is host port */449 if (mask)450 cpsw_ale_set_port_mask(ale_entry, mask,451 ale->port_mask_bits);452 else453 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);454}455 456int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask, int vid)457{458 u32 ale_entry[ALE_ENTRY_WORDS];459 int ret, idx;460 461 for (idx = 0; idx < ale->params.ale_entries; idx++) {462 cpsw_ale_read(ale, idx, ale_entry);463 ret = cpsw_ale_get_entry_type(ale_entry);464 if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)465 continue;466 467 /* if vid passed is -1 then remove all multicast entry from468 * the table irrespective of vlan id, if a valid vlan id is469 * passed then remove only multicast added to that vlan id.470 * if vlan id doesn't match then move on to next entry.471 */472 if (vid != -1 && cpsw_ale_get_vlan_id(ale_entry) != vid)473 continue;474 475 if (cpsw_ale_get_mcast(ale_entry)) {476 u8 addr[6];477 478 if (cpsw_ale_get_super(ale_entry))479 continue;480 481 cpsw_ale_get_addr(ale_entry, addr);482 if (!is_broadcast_ether_addr(addr))483 cpsw_ale_flush_mcast(ale, ale_entry, port_mask);484 }485 486 cpsw_ale_write(ale, idx, ale_entry);487 }488 return 0;489}490 491static inline void cpsw_ale_set_vlan_entry_type(u32 *ale_entry,492 int flags, u16 vid)493{494 if (flags & ALE_VLAN) {495 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN_ADDR);496 cpsw_ale_set_vlan_id(ale_entry, vid);497 } else {498 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_ADDR);499 }500}501 502int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,503 int flags, u16 vid)504{505 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};506 int idx;507 508 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);509 510 cpsw_ale_set_addr(ale_entry, addr);511 cpsw_ale_set_ucast_type(ale_entry, ALE_UCAST_PERSISTANT);512 cpsw_ale_set_secure(ale_entry, (flags & ALE_SECURE) ? 1 : 0);513 cpsw_ale_set_blocked(ale_entry, (flags & ALE_BLOCKED) ? 1 : 0);514 cpsw_ale_set_port_num(ale_entry, port, ale->port_num_bits);515 516 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);517 if (idx < 0)518 idx = cpsw_ale_match_free(ale);519 if (idx < 0)520 idx = cpsw_ale_find_ageable(ale);521 if (idx < 0)522 return -ENOMEM;523 524 cpsw_ale_write(ale, idx, ale_entry);525 return 0;526}527 528int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,529 int flags, u16 vid)530{531 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};532 int idx;533 534 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);535 if (idx < 0)536 return -ENOENT;537 538 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);539 cpsw_ale_write(ale, idx, ale_entry);540 return 0;541}542 543int cpsw_ale_add_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,544 int flags, u16 vid, int mcast_state)545{546 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};547 int idx, mask;548 549 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);550 if (idx >= 0)551 cpsw_ale_read(ale, idx, ale_entry);552 553 cpsw_ale_set_vlan_entry_type(ale_entry, flags, vid);554 555 cpsw_ale_set_addr(ale_entry, addr);556 cpsw_ale_set_super(ale_entry, (flags & ALE_SUPER) ? 1 : 0);557 cpsw_ale_set_mcast_state(ale_entry, mcast_state);558 559 mask = cpsw_ale_get_port_mask(ale_entry,560 ale->port_mask_bits);561 port_mask |= mask;562 cpsw_ale_set_port_mask(ale_entry, port_mask,563 ale->port_mask_bits);564 565 if (idx < 0)566 idx = cpsw_ale_match_free(ale);567 if (idx < 0)568 idx = cpsw_ale_find_ageable(ale);569 if (idx < 0)570 return -ENOMEM;571 572 cpsw_ale_write(ale, idx, ale_entry);573 return 0;574}575 576int cpsw_ale_del_mcast(struct cpsw_ale *ale, const u8 *addr, int port_mask,577 int flags, u16 vid)578{579 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};580 int mcast_members = 0;581 int idx;582 583 idx = cpsw_ale_match_addr(ale, addr, (flags & ALE_VLAN) ? vid : 0);584 if (idx < 0)585 return -ENOENT;586 587 cpsw_ale_read(ale, idx, ale_entry);588 589 if (port_mask) {590 mcast_members = cpsw_ale_get_port_mask(ale_entry,591 ale->port_mask_bits);592 mcast_members &= ~port_mask;593 }594 595 if (mcast_members)596 cpsw_ale_set_port_mask(ale_entry, mcast_members,597 ale->port_mask_bits);598 else599 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);600 601 cpsw_ale_write(ale, idx, ale_entry);602 return 0;603}604 605/* ALE NetCP NU switch specific vlan functions */606static void cpsw_ale_set_vlan_mcast(struct cpsw_ale *ale, u32 *ale_entry,607 int reg_mcast, int unreg_mcast)608{609 int idx;610 611 /* Set VLAN registered multicast flood mask */612 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,613 ALE_ENT_VID_REG_MCAST_IDX);614 writel(reg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));615 616 /* Set VLAN unregistered multicast flood mask */617 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,618 ALE_ENT_VID_UNREG_MCAST_IDX);619 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));620}621 622static void cpsw_ale_set_vlan_untag(struct cpsw_ale *ale, u32 *ale_entry,623 u16 vid, int untag_mask)624{625 cpsw_ale_vlan_set_fld(ale, ale_entry,626 ALE_ENT_VID_FORCE_UNTAGGED_MSK,627 untag_mask);628 if (untag_mask & ALE_PORT_HOST)629 bitmap_set(ale->p0_untag_vid_mask, vid, 1);630 else631 bitmap_clear(ale->p0_untag_vid_mask, vid, 1);632}633 634int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,635 int reg_mcast, int unreg_mcast)636{637 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};638 int idx;639 640 idx = cpsw_ale_match_vlan(ale, vid);641 if (idx >= 0)642 cpsw_ale_read(ale, idx, ale_entry);643 644 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_VLAN);645 cpsw_ale_set_vlan_id(ale_entry, vid);646 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);647 648 if (!ale->params.nu_switch_ale) {649 cpsw_ale_vlan_set_fld(ale, ale_entry,650 ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);651 cpsw_ale_vlan_set_fld(ale, ale_entry,652 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);653 } else {654 cpsw_ale_vlan_set_fld(ale, ale_entry,655 ALE_ENT_VID_UNREG_MCAST_IDX,656 NU_VLAN_UNREG_MCAST_IDX);657 cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast, unreg_mcast);658 }659 660 cpsw_ale_vlan_set_fld(ale, ale_entry,661 ALE_ENT_VID_MEMBER_LIST, port_mask);662 663 if (idx < 0)664 idx = cpsw_ale_match_free(ale);665 if (idx < 0)666 idx = cpsw_ale_find_ageable(ale);667 if (idx < 0)668 return -ENOMEM;669 670 cpsw_ale_write(ale, idx, ale_entry);671 return 0;672}673 674static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale, u32 *ale_entry,675 u16 vid, int port_mask)676{677 int reg_mcast, unreg_mcast;678 int members, untag;679 680 members = cpsw_ale_vlan_get_fld(ale, ale_entry,681 ALE_ENT_VID_MEMBER_LIST);682 members &= ~port_mask;683 if (!members) {684 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);685 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);686 return;687 }688 689 untag = cpsw_ale_vlan_get_fld(ale, ale_entry,690 ALE_ENT_VID_FORCE_UNTAGGED_MSK);691 reg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,692 ALE_ENT_VID_REG_MCAST_MSK);693 unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,694 ALE_ENT_VID_UNREG_MCAST_MSK);695 untag &= members;696 reg_mcast &= members;697 unreg_mcast &= members;698 699 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, untag);700 701 if (!ale->params.nu_switch_ale) {702 cpsw_ale_vlan_set_fld(ale, ale_entry,703 ALE_ENT_VID_REG_MCAST_MSK, reg_mcast);704 cpsw_ale_vlan_set_fld(ale, ale_entry,705 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);706 } else {707 cpsw_ale_set_vlan_mcast(ale, ale_entry, reg_mcast,708 unreg_mcast);709 }710 cpsw_ale_vlan_set_fld(ale, ale_entry,711 ALE_ENT_VID_MEMBER_LIST, members);712}713 714int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask)715{716 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};717 int idx;718 719 idx = cpsw_ale_match_vlan(ale, vid);720 if (idx < 0)721 return -ENOENT;722 723 cpsw_ale_read(ale, idx, ale_entry);724 725 cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);726 cpsw_ale_write(ale, idx, ale_entry);727 728 return 0;729}730 731int cpsw_ale_del_vlan(struct cpsw_ale *ale, u16 vid, int port_mask)732{733 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};734 int members, idx;735 736 idx = cpsw_ale_match_vlan(ale, vid);737 if (idx < 0)738 return -ENOENT;739 740 cpsw_ale_read(ale, idx, ale_entry);741 742 /* if !port_mask - force remove VLAN (legacy).743 * Check if there are other VLAN members ports744 * if no - remove VLAN.745 * if yes it means same VLAN was added to >1 port in multi port mode, so746 * remove port_mask ports from VLAN ALE entry excluding Host port.747 */748 members = cpsw_ale_vlan_get_fld(ale, ale_entry, ALE_ENT_VID_MEMBER_LIST);749 members &= ~port_mask;750 751 if (!port_mask || !members) {752 /* last port or force remove - remove VLAN */753 cpsw_ale_set_vlan_untag(ale, ale_entry, vid, 0);754 cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);755 } else {756 port_mask &= ~ALE_PORT_HOST;757 cpsw_ale_vlan_del_modify_int(ale, ale_entry, vid, port_mask);758 }759 760 cpsw_ale_write(ale, idx, ale_entry);761 762 return 0;763}764 765int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,766 int untag_mask, int reg_mask, int unreg_mask)767{768 u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};769 int reg_mcast_members, unreg_mcast_members;770 int vlan_members, untag_members;771 int idx, ret = 0;772 773 idx = cpsw_ale_match_vlan(ale, vid);774 if (idx >= 0)775 cpsw_ale_read(ale, idx, ale_entry);776 777 vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,778 ALE_ENT_VID_MEMBER_LIST);779 reg_mcast_members = cpsw_ale_vlan_get_fld(ale, ale_entry,780 ALE_ENT_VID_REG_MCAST_MSK);781 unreg_mcast_members =782 cpsw_ale_vlan_get_fld(ale, ale_entry,783 ALE_ENT_VID_UNREG_MCAST_MSK);784 untag_members = cpsw_ale_vlan_get_fld(ale, ale_entry,785 ALE_ENT_VID_FORCE_UNTAGGED_MSK);786 787 vlan_members |= port_mask;788 untag_members = (untag_members & ~port_mask) | untag_mask;789 reg_mcast_members = (reg_mcast_members & ~port_mask) | reg_mask;790 unreg_mcast_members = (unreg_mcast_members & ~port_mask) | unreg_mask;791 792 ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,793 reg_mcast_members, unreg_mcast_members);794 if (ret) {795 dev_err(ale->params.dev, "Unable to add vlan\n");796 return ret;797 }798 dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,799 untag_mask);800 801 return ret;802}803 804void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,805 bool add)806{807 u32 ale_entry[ALE_ENTRY_WORDS];808 int unreg_members = 0;809 int type, idx;810 811 for (idx = 0; idx < ale->params.ale_entries; idx++) {812 cpsw_ale_read(ale, idx, ale_entry);813 type = cpsw_ale_get_entry_type(ale_entry);814 if (type != ALE_TYPE_VLAN)815 continue;816 817 unreg_members =818 cpsw_ale_vlan_get_fld(ale, ale_entry,819 ALE_ENT_VID_UNREG_MCAST_MSK);820 if (add)821 unreg_members |= unreg_mcast_mask;822 else823 unreg_members &= ~unreg_mcast_mask;824 cpsw_ale_vlan_set_fld(ale, ale_entry,825 ALE_ENT_VID_UNREG_MCAST_MSK,826 unreg_members);827 cpsw_ale_write(ale, idx, ale_entry);828 }829}830 831static void cpsw_ale_vlan_set_unreg_mcast(struct cpsw_ale *ale, u32 *ale_entry,832 int allmulti)833{834 int unreg_mcast;835 836 unreg_mcast = cpsw_ale_vlan_get_fld(ale, ale_entry,837 ALE_ENT_VID_UNREG_MCAST_MSK);838 if (allmulti)839 unreg_mcast |= ALE_PORT_HOST;840 else841 unreg_mcast &= ~ALE_PORT_HOST;842 843 cpsw_ale_vlan_set_fld(ale, ale_entry,844 ALE_ENT_VID_UNREG_MCAST_MSK, unreg_mcast);845}846 847static void848cpsw_ale_vlan_set_unreg_mcast_idx(struct cpsw_ale *ale, u32 *ale_entry,849 int allmulti)850{851 int unreg_mcast;852 int idx;853 854 idx = cpsw_ale_vlan_get_fld(ale, ale_entry,855 ALE_ENT_VID_UNREG_MCAST_IDX);856 857 unreg_mcast = readl(ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));858 859 if (allmulti)860 unreg_mcast |= ALE_PORT_HOST;861 else862 unreg_mcast &= ~ALE_PORT_HOST;863 864 writel(unreg_mcast, ale->params.ale_regs + ALE_VLAN_MASK_MUX(idx));865}866 867void cpsw_ale_set_allmulti(struct cpsw_ale *ale, int allmulti, int port)868{869 u32 ale_entry[ALE_ENTRY_WORDS];870 int type, idx;871 872 for (idx = 0; idx < ale->params.ale_entries; idx++) {873 int vlan_members;874 875 cpsw_ale_read(ale, idx, ale_entry);876 type = cpsw_ale_get_entry_type(ale_entry);877 if (type != ALE_TYPE_VLAN)878 continue;879 880 vlan_members = cpsw_ale_vlan_get_fld(ale, ale_entry,881 ALE_ENT_VID_MEMBER_LIST);882 883 if (port != -1 && !(vlan_members & BIT(port)))884 continue;885 886 if (!ale->params.nu_switch_ale)887 cpsw_ale_vlan_set_unreg_mcast(ale, ale_entry, allmulti);888 else889 cpsw_ale_vlan_set_unreg_mcast_idx(ale, ale_entry,890 allmulti);891 892 cpsw_ale_write(ale, idx, ale_entry);893 }894}895 896struct ale_control_info {897 const char *name;898 int offset, port_offset;899 int shift, port_shift;900 int bits;901};902 903static struct ale_control_info ale_controls[ALE_NUM_CONTROLS] = {904 [ALE_ENABLE] = {905 .name = "enable",906 .offset = ALE_CONTROL,907 .port_offset = 0,908 .shift = 31,909 .port_shift = 0,910 .bits = 1,911 },912 [ALE_CLEAR] = {913 .name = "clear",914 .offset = ALE_CONTROL,915 .port_offset = 0,916 .shift = 30,917 .port_shift = 0,918 .bits = 1,919 },920 [ALE_AGEOUT] = {921 .name = "ageout",922 .offset = ALE_CONTROL,923 .port_offset = 0,924 .shift = 29,925 .port_shift = 0,926 .bits = 1,927 },928 [ALE_P0_UNI_FLOOD] = {929 .name = "port0_unicast_flood",930 .offset = ALE_CONTROL,931 .port_offset = 0,932 .shift = 8,933 .port_shift = 0,934 .bits = 1,935 },936 [ALE_VLAN_NOLEARN] = {937 .name = "vlan_nolearn",938 .offset = ALE_CONTROL,939 .port_offset = 0,940 .shift = 7,941 .port_shift = 0,942 .bits = 1,943 },944 [ALE_NO_PORT_VLAN] = {945 .name = "no_port_vlan",946 .offset = ALE_CONTROL,947 .port_offset = 0,948 .shift = 6,949 .port_shift = 0,950 .bits = 1,951 },952 [ALE_OUI_DENY] = {953 .name = "oui_deny",954 .offset = ALE_CONTROL,955 .port_offset = 0,956 .shift = 5,957 .port_shift = 0,958 .bits = 1,959 },960 [ALE_BYPASS] = {961 .name = "bypass",962 .offset = ALE_CONTROL,963 .port_offset = 0,964 .shift = 4,965 .port_shift = 0,966 .bits = 1,967 },968 [ALE_RATE_LIMIT_TX] = {969 .name = "rate_limit_tx",970 .offset = ALE_CONTROL,971 .port_offset = 0,972 .shift = 3,973 .port_shift = 0,974 .bits = 1,975 },976 [ALE_VLAN_AWARE] = {977 .name = "vlan_aware",978 .offset = ALE_CONTROL,979 .port_offset = 0,980 .shift = 2,981 .port_shift = 0,982 .bits = 1,983 },984 [ALE_AUTH_ENABLE] = {985 .name = "auth_enable",986 .offset = ALE_CONTROL,987 .port_offset = 0,988 .shift = 1,989 .port_shift = 0,990 .bits = 1,991 },992 [ALE_RATE_LIMIT] = {993 .name = "rate_limit",994 .offset = ALE_CONTROL,995 .port_offset = 0,996 .shift = 0,997 .port_shift = 0,998 .bits = 1,999 },1000 [ALE_PORT_STATE] = {1001 .name = "port_state",1002 .offset = ALE_PORTCTL,1003 .port_offset = 4,1004 .shift = 0,1005 .port_shift = 0,1006 .bits = 2,1007 },1008 [ALE_PORT_DROP_UNTAGGED] = {1009 .name = "drop_untagged",1010 .offset = ALE_PORTCTL,1011 .port_offset = 4,1012 .shift = 2,1013 .port_shift = 0,1014 .bits = 1,1015 },1016 [ALE_PORT_DROP_UNKNOWN_VLAN] = {1017 .name = "drop_unknown",1018 .offset = ALE_PORTCTL,1019 .port_offset = 4,1020 .shift = 3,1021 .port_shift = 0,1022 .bits = 1,1023 },1024 [ALE_PORT_NOLEARN] = {1025 .name = "nolearn",1026 .offset = ALE_PORTCTL,1027 .port_offset = 4,1028 .shift = 4,1029 .port_shift = 0,1030 .bits = 1,1031 },1032 [ALE_PORT_NO_SA_UPDATE] = {1033 .name = "no_source_update",1034 .offset = ALE_PORTCTL,1035 .port_offset = 4,1036 .shift = 5,1037 .port_shift = 0,1038 .bits = 1,1039 },1040 [ALE_PORT_MACONLY] = {1041 .name = "mac_only_port_mode",1042 .offset = ALE_PORTCTL,1043 .port_offset = 4,1044 .shift = 11,1045 .port_shift = 0,1046 .bits = 1,1047 },1048 [ALE_PORT_MACONLY_CAF] = {1049 .name = "mac_only_port_caf",1050 .offset = ALE_PORTCTL,1051 .port_offset = 4,1052 .shift = 13,1053 .port_shift = 0,1054 .bits = 1,1055 },1056 [ALE_PORT_MCAST_LIMIT] = {1057 .name = "mcast_limit",1058 .offset = ALE_PORTCTL,1059 .port_offset = 4,1060 .shift = 16,1061 .port_shift = 0,1062 .bits = 8,1063 },1064 [ALE_PORT_BCAST_LIMIT] = {1065 .name = "bcast_limit",1066 .offset = ALE_PORTCTL,1067 .port_offset = 4,1068 .shift = 24,1069 .port_shift = 0,1070 .bits = 8,1071 },1072 [ALE_PORT_UNKNOWN_VLAN_MEMBER] = {1073 .name = "unknown_vlan_member",1074 .offset = ALE_UNKNOWNVLAN,1075 .port_offset = 0,1076 .shift = 0,1077 .port_shift = 0,1078 .bits = 6,1079 },1080 [ALE_PORT_UNKNOWN_MCAST_FLOOD] = {1081 .name = "unknown_mcast_flood",1082 .offset = ALE_UNKNOWNVLAN,1083 .port_offset = 0,1084 .shift = 8,1085 .port_shift = 0,1086 .bits = 6,1087 },1088 [ALE_PORT_UNKNOWN_REG_MCAST_FLOOD] = {1089 .name = "unknown_reg_flood",1090 .offset = ALE_UNKNOWNVLAN,1091 .port_offset = 0,1092 .shift = 16,1093 .port_shift = 0,1094 .bits = 6,1095 },1096 [ALE_PORT_UNTAGGED_EGRESS] = {1097 .name = "untagged_egress",1098 .offset = ALE_UNKNOWNVLAN,1099 .port_offset = 0,1100 .shift = 24,1101 .port_shift = 0,1102 .bits = 6,1103 },1104 [ALE_DEFAULT_THREAD_ID] = {1105 .name = "default_thread_id",1106 .offset = AM65_CPSW_ALE_THREAD_DEF_REG,1107 .port_offset = 0,1108 .shift = 0,1109 .port_shift = 0,1110 .bits = 6,1111 },1112 [ALE_DEFAULT_THREAD_ENABLE] = {1113 .name = "default_thread_id_enable",1114 .offset = AM65_CPSW_ALE_THREAD_DEF_REG,1115 .port_offset = 0,1116 .shift = 15,1117 .port_shift = 0,1118 .bits = 1,1119 },1120};1121 1122int cpsw_ale_control_set(struct cpsw_ale *ale, int port, int control,1123 int value)1124{1125 const struct ale_control_info *info;1126 int offset, shift;1127 u32 tmp, mask;1128 1129 if (control < 0 || control >= ARRAY_SIZE(ale_controls))1130 return -EINVAL;1131 1132 info = &ale_controls[control];1133 if (info->port_offset == 0 && info->port_shift == 0)1134 port = 0; /* global, port is a dont care */1135 1136 if (port < 0 || port >= ale->params.ale_ports)1137 return -EINVAL;1138 1139 mask = BITMASK(info->bits);1140 if (value & ~mask)1141 return -EINVAL;1142 1143 offset = info->offset + (port * info->port_offset);1144 shift = info->shift + (port * info->port_shift);1145 1146 tmp = readl_relaxed(ale->params.ale_regs + offset);1147 tmp = (tmp & ~(mask << shift)) | (value << shift);1148 writel_relaxed(tmp, ale->params.ale_regs + offset);1149 1150 return 0;1151}1152 1153int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control)1154{1155 const struct ale_control_info *info;1156 int offset, shift;1157 u32 tmp;1158 1159 if (control < 0 || control >= ARRAY_SIZE(ale_controls))1160 return -EINVAL;1161 1162 info = &ale_controls[control];1163 if (info->port_offset == 0 && info->port_shift == 0)1164 port = 0; /* global, port is a dont care */1165 1166 if (port < 0 || port >= ale->params.ale_ports)1167 return -EINVAL;1168 1169 offset = info->offset + (port * info->port_offset);1170 shift = info->shift + (port * info->port_shift);1171 1172 tmp = readl_relaxed(ale->params.ale_regs + offset) >> shift;1173 return tmp & BITMASK(info->bits);1174}1175 1176int cpsw_ale_rx_ratelimit_mc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)1177 1178{1179 int val = ratelimit_pps / ALE_RATE_LIMIT_MIN_PPS;1180 u32 remainder = ratelimit_pps % ALE_RATE_LIMIT_MIN_PPS;1181 1182 if (ratelimit_pps && !val) {1183 dev_err(ale->params.dev, "ALE MC port:%d ratelimit min value 1000pps\n", port);1184 return -EINVAL;1185 }1186 1187 if (remainder)1188 dev_info(ale->params.dev, "ALE port:%d MC ratelimit set to %dpps (requested %d)\n",1189 port, ratelimit_pps - remainder, ratelimit_pps);1190 1191 cpsw_ale_control_set(ale, port, ALE_PORT_MCAST_LIMIT, val);1192 1193 dev_dbg(ale->params.dev, "ALE port:%d MC ratelimit set %d\n",1194 port, val * ALE_RATE_LIMIT_MIN_PPS);1195 return 0;1196}1197 1198int cpsw_ale_rx_ratelimit_bc(struct cpsw_ale *ale, int port, unsigned int ratelimit_pps)1199 1200{1201 int val = ratelimit_pps / ALE_RATE_LIMIT_MIN_PPS;1202 u32 remainder = ratelimit_pps % ALE_RATE_LIMIT_MIN_PPS;1203 1204 if (ratelimit_pps && !val) {1205 dev_err(ale->params.dev, "ALE port:%d BC ratelimit min value 1000pps\n", port);1206 return -EINVAL;1207 }1208 1209 if (remainder)1210 dev_info(ale->params.dev, "ALE port:%d BC ratelimit set to %dpps (requested %d)\n",1211 port, ratelimit_pps - remainder, ratelimit_pps);1212 1213 cpsw_ale_control_set(ale, port, ALE_PORT_BCAST_LIMIT, val);1214 1215 dev_dbg(ale->params.dev, "ALE port:%d BC ratelimit set %d\n",1216 port, val * ALE_RATE_LIMIT_MIN_PPS);1217 return 0;1218}1219 1220static void cpsw_ale_timer(struct timer_list *t)1221{1222 struct cpsw_ale *ale = from_timer(ale, t, timer);1223 1224 cpsw_ale_control_set(ale, 0, ALE_AGEOUT, 1);1225 1226 if (ale->ageout) {1227 ale->timer.expires = jiffies + ale->ageout;1228 add_timer(&ale->timer);1229 }1230}1231 1232static void cpsw_ale_hw_aging_timer_start(struct cpsw_ale *ale)1233{1234 u32 aging_timer;1235 1236 aging_timer = ale->params.bus_freq / 1000000;1237 aging_timer *= ale->params.ale_ageout;1238 1239 if (aging_timer & ~ALE_AGING_TIMER_MASK) {1240 aging_timer = ALE_AGING_TIMER_MASK;1241 dev_warn(ale->params.dev,1242 "ALE aging timer overflow, set to max\n");1243 }1244 1245 writel(aging_timer, ale->params.ale_regs + ALE_AGING_TIMER);1246}1247 1248static void cpsw_ale_hw_aging_timer_stop(struct cpsw_ale *ale)1249{1250 writel(0, ale->params.ale_regs + ALE_AGING_TIMER);1251}1252 1253static void cpsw_ale_aging_start(struct cpsw_ale *ale)1254{1255 if (!ale->params.ale_ageout)1256 return;1257 1258 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {1259 cpsw_ale_hw_aging_timer_start(ale);1260 return;1261 }1262 1263 timer_setup(&ale->timer, cpsw_ale_timer, 0);1264 ale->timer.expires = jiffies + ale->ageout;1265 add_timer(&ale->timer);1266}1267 1268static void cpsw_ale_aging_stop(struct cpsw_ale *ale)1269{1270 if (!ale->params.ale_ageout)1271 return;1272 1273 if (ale->features & CPSW_ALE_F_HW_AUTOAGING) {1274 cpsw_ale_hw_aging_timer_stop(ale);1275 return;1276 }1277 1278 del_timer_sync(&ale->timer);1279}1280 1281void cpsw_ale_start(struct cpsw_ale *ale)1282{1283 unsigned long ale_prescale;1284 1285 /* configure Broadcast and Multicast Rate Limit1286 * number_of_packets = (Fclk / ALE_PRESCALE) * port.BCAST/MCAST_LIMIT1287 * ALE_PRESCALE width is 19bit and min value 0x101288 * port.BCAST/MCAST_LIMIT is 8bit1289 *1290 * For multi port configuration support the ALE_PRESCALE is configured to 1ms interval,1291 * which allows to configure port.BCAST/MCAST_LIMIT per port and achieve:1292 * min number_of_packets = 1000 when port.BCAST/MCAST_LIMIT = 11293 * max number_of_packets = 1000 * 255 = 255000 when port.BCAST/MCAST_LIMIT = 0xFF1294 */1295 ale_prescale = ale->params.bus_freq / ALE_RATE_LIMIT_MIN_PPS;1296 writel((u32)ale_prescale, ale->params.ale_regs + ALE_PRESCALE);1297 1298 /* Allow MC/BC rate limiting globally.1299 * The actual Rate Limit cfg enabled per-port by port.BCAST/MCAST_LIMIT1300 */1301 cpsw_ale_control_set(ale, 0, ALE_RATE_LIMIT, 1);1302 1303 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 1);1304 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);1305 1306 cpsw_ale_aging_start(ale);1307}1308 1309void cpsw_ale_stop(struct cpsw_ale *ale)1310{1311 cpsw_ale_aging_stop(ale);1312 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);1313 cpsw_ale_control_set(ale, 0, ALE_ENABLE, 0);1314}1315 1316static const struct reg_field ale_fields_cpsw[] = {1317 /* CPSW_ALE_IDVER_REG */1318 [MINOR_VER] = REG_FIELD(ALE_IDVER, 0, 7),1319 [MAJOR_VER] = REG_FIELD(ALE_IDVER, 8, 15),1320};1321 1322static const struct reg_field ale_fields_cpsw_nu[] = {1323 /* CPSW_ALE_IDVER_REG */1324 [MINOR_VER] = REG_FIELD(ALE_IDVER, 0, 7),1325 [MAJOR_VER] = REG_FIELD(ALE_IDVER, 8, 10),1326 /* CPSW_ALE_STATUS_REG */1327 [ALE_ENTRIES] = REG_FIELD(ALE_STATUS, 0, 7),1328 [ALE_POLICERS] = REG_FIELD(ALE_STATUS, 8, 15),1329 /* CPSW_ALE_POLICER_PORT_OUI_REG */1330 [POL_PORT_MEN] = REG_FIELD(ALE_POLICER_PORT_OUI, 31, 31),1331 [POL_TRUNK_ID] = REG_FIELD(ALE_POLICER_PORT_OUI, 30, 30),1332 [POL_PORT_NUM] = REG_FIELD(ALE_POLICER_PORT_OUI, 25, 25),1333 [POL_PRI_MEN] = REG_FIELD(ALE_POLICER_PORT_OUI, 19, 19),1334 [POL_PRI_VAL] = REG_FIELD(ALE_POLICER_PORT_OUI, 16, 18),1335 [POL_OUI_MEN] = REG_FIELD(ALE_POLICER_PORT_OUI, 15, 15),1336 [POL_OUI_INDEX] = REG_FIELD(ALE_POLICER_PORT_OUI, 0, 5),1337 1338 /* CPSW_ALE_POLICER_DA_SA_REG */1339 [POL_DST_MEN] = REG_FIELD(ALE_POLICER_DA_SA, 31, 31),1340 [POL_DST_INDEX] = REG_FIELD(ALE_POLICER_DA_SA, 16, 21),1341 [POL_SRC_MEN] = REG_FIELD(ALE_POLICER_DA_SA, 15, 15),1342 [POL_SRC_INDEX] = REG_FIELD(ALE_POLICER_DA_SA, 0, 5),1343 1344 /* CPSW_ALE_POLICER_VLAN_REG */1345 [POL_OVLAN_MEN] = REG_FIELD(ALE_POLICER_VLAN, 31, 31),1346 [POL_OVLAN_INDEX] = REG_FIELD(ALE_POLICER_VLAN, 16, 21),1347 [POL_IVLAN_MEN] = REG_FIELD(ALE_POLICER_VLAN, 15, 15),1348 [POL_IVLAN_INDEX] = REG_FIELD(ALE_POLICER_VLAN, 0, 5),1349 1350 /* CPSW_ALE_POLICER_ETHERTYPE_IPSA_REG */1351 [POL_ETHERTYPE_MEN] = REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 31, 31),1352 [POL_ETHERTYPE_INDEX] = REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 16, 21),1353 [POL_IPSRC_MEN] = REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 15, 15),1354 [POL_IPSRC_INDEX] = REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 0, 5),1355 1356 /* CPSW_ALE_POLICER_IPDA_REG */1357 [POL_IPDST_MEN] = REG_FIELD(ALE_POLICER_IPDA, 31, 31),1358 [POL_IPDST_INDEX] = REG_FIELD(ALE_POLICER_IPDA, 16, 21),1359 1360 /* CPSW_ALE_POLICER_TBL_CTL_REG */1361 /**1362 * REG_FIELDS not defined for this as fields cannot be correctly1363 * used independently1364 */1365 1366 /* CPSW_ALE_POLICER_CTL_REG */1367 [POL_EN] = REG_FIELD(ALE_POLICER_CTL, 31, 31),1368 [POL_RED_DROP_EN] = REG_FIELD(ALE_POLICER_CTL, 29, 29),1369 [POL_YELLOW_DROP_EN] = REG_FIELD(ALE_POLICER_CTL, 28, 28),1370 [POL_YELLOW_THRESH] = REG_FIELD(ALE_POLICER_CTL, 24, 26),1371 [POL_POL_MATCH_MODE] = REG_FIELD(ALE_POLICER_CTL, 22, 23),1372 [POL_PRIORITY_THREAD_EN] = REG_FIELD(ALE_POLICER_CTL, 21, 21),1373 [POL_MAC_ONLY_DEF_DIS] = REG_FIELD(ALE_POLICER_CTL, 20, 20),1374 1375 /* CPSW_ALE_POLICER_TEST_CTL_REG */1376 [POL_TEST_CLR] = REG_FIELD(ALE_POLICER_TEST_CTL, 31, 31),1377 [POL_TEST_CLR_RED] = REG_FIELD(ALE_POLICER_TEST_CTL, 30, 30),1378 [POL_TEST_CLR_YELLOW] = REG_FIELD(ALE_POLICER_TEST_CTL, 29, 29),1379 [POL_TEST_CLR_SELECTED] = REG_FIELD(ALE_POLICER_TEST_CTL, 28, 28),1380 [POL_TEST_ENTRY] = REG_FIELD(ALE_POLICER_TEST_CTL, 0, 4),1381 1382 /* CPSW_ALE_POLICER_HIT_STATUS_REG */1383 [POL_STATUS_HIT] = REG_FIELD(ALE_POLICER_HIT_STATUS, 31, 31),1384 [POL_STATUS_HIT_RED] = REG_FIELD(ALE_POLICER_HIT_STATUS, 30, 30),1385 [POL_STATUS_HIT_YELLOW] = REG_FIELD(ALE_POLICER_HIT_STATUS, 29, 29),1386 1387 /* CPSW_ALE_THREAD_DEF_REG */1388 [ALE_DEFAULT_THREAD_EN] = REG_FIELD(ALE_THREAD_DEF, 15, 15),1389 [ALE_DEFAULT_THREAD_VAL] = REG_FIELD(ALE_THREAD_DEF, 0, 5),1390 1391 /* CPSW_ALE_THREAD_CTL_REG */1392 [ALE_THREAD_CLASS_INDEX] = REG_FIELD(ALE_THREAD_CTL, 0, 4),1393 1394 /* CPSW_ALE_THREAD_VAL_REG */1395 [ALE_THREAD_ENABLE] = REG_FIELD(ALE_THREAD_VAL, 15, 15),1396 [ALE_THREAD_VALUE] = REG_FIELD(ALE_THREAD_VAL, 0, 5),1397};1398 1399static const struct cpsw_ale_dev_id cpsw_ale_id_match[] = {1400 {1401 /* am3/4/5, dra7. dm814x, 66ak2hk-gbe */1402 .dev_id = "cpsw",1403 .tbl_entries = 1024,1404 .reg_fields = ale_fields_cpsw,1405 .num_fields = ARRAY_SIZE(ale_fields_cpsw),1406 .vlan_entry_tbl = vlan_entry_cpsw,1407 },1408 {1409 /* 66ak2h_xgbe */1410 .dev_id = "66ak2h-xgbe",1411 .tbl_entries = 2048,1412 .reg_fields = ale_fields_cpsw,1413 .num_fields = ARRAY_SIZE(ale_fields_cpsw),1414 .vlan_entry_tbl = vlan_entry_cpsw,1415 },1416 {1417 .dev_id = "66ak2el",1418 .features = CPSW_ALE_F_STATUS_REG,1419 .reg_fields = ale_fields_cpsw_nu,1420 .num_fields = ARRAY_SIZE(ale_fields_cpsw_nu),1421 .nu_switch_ale = true,1422 .vlan_entry_tbl = vlan_entry_nu,1423 },1424 {1425 .dev_id = "66ak2g",1426 .features = CPSW_ALE_F_STATUS_REG,1427 .tbl_entries = 64,1428 .reg_fields = ale_fields_cpsw_nu,1429 .num_fields = ARRAY_SIZE(ale_fields_cpsw_nu),1430 .nu_switch_ale = true,1431 .vlan_entry_tbl = vlan_entry_nu,1432 },1433 {1434 .dev_id = "am65x-cpsw2g",1435 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,1436 .tbl_entries = 64,1437 .reg_fields = ale_fields_cpsw_nu,1438 .num_fields = ARRAY_SIZE(ale_fields_cpsw_nu),1439 .nu_switch_ale = true,1440 .vlan_entry_tbl = vlan_entry_nu,1441 },1442 {1443 .dev_id = "j721e-cpswxg",1444 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,1445 .reg_fields = ale_fields_cpsw_nu,1446 .num_fields = ARRAY_SIZE(ale_fields_cpsw_nu),1447 .vlan_entry_tbl = vlan_entry_k3_cpswxg,1448 },1449 {1450 .dev_id = "am64-cpswxg",1451 .features = CPSW_ALE_F_STATUS_REG | CPSW_ALE_F_HW_AUTOAGING,1452 .reg_fields = ale_fields_cpsw_nu,1453 .num_fields = ARRAY_SIZE(ale_fields_cpsw_nu),1454 .vlan_entry_tbl = vlan_entry_k3_cpswxg,1455 .tbl_entries = 512,1456 },1457 { },1458};1459 1460static const struct1461cpsw_ale_dev_id *cpsw_ale_match_id(const struct cpsw_ale_dev_id *id,1462 const char *dev_id)1463{1464 if (!dev_id)1465 return NULL;1466 1467 while (id->dev_id) {1468 if (strcmp(dev_id, id->dev_id) == 0)1469 return id;1470 id++;1471 }1472 return NULL;1473}1474 1475static const struct regmap_config ale_regmap_cfg = {1476 .reg_bits = 32,1477 .val_bits = 32,1478 .reg_stride = 4,1479 .name = "cpsw-ale",1480};1481 1482static int cpsw_ale_regfield_init(struct cpsw_ale *ale)1483{1484 const struct reg_field *reg_fields = ale->params.reg_fields;1485 struct device *dev = ale->params.dev;1486 struct regmap *regmap = ale->regmap;1487 int i;1488 1489 for (i = 0; i < ale->params.num_fields; i++) {1490 ale->fields[i] = devm_regmap_field_alloc(dev, regmap,1491 reg_fields[i]);1492 if (IS_ERR(ale->fields[i])) {1493 dev_err(dev, "Unable to allocate regmap field %d\n", i);1494 return PTR_ERR(ale->fields[i]);1495 }1496 }1497 1498 return 0;1499}1500 1501struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params)1502{1503 u32 ale_entries, rev_major, rev_minor, policers;1504 const struct cpsw_ale_dev_id *ale_dev_id;1505 struct cpsw_ale *ale;1506 int ret;1507 1508 ale_dev_id = cpsw_ale_match_id(cpsw_ale_id_match, params->dev_id);1509 if (!ale_dev_id)1510 return ERR_PTR(-EINVAL);1511 1512 params->ale_entries = ale_dev_id->tbl_entries;1513 params->nu_switch_ale = ale_dev_id->nu_switch_ale;1514 params->reg_fields = ale_dev_id->reg_fields;1515 params->num_fields = ale_dev_id->num_fields;1516 1517 ale = devm_kzalloc(params->dev, sizeof(*ale), GFP_KERNEL);1518 if (!ale)1519 return ERR_PTR(-ENOMEM);1520 ale->regmap = devm_regmap_init_mmio(params->dev, params->ale_regs,1521 &ale_regmap_cfg);1522 if (IS_ERR(ale->regmap)) {1523 dev_err(params->dev, "Couldn't create CPSW ALE regmap\n");1524 return ERR_PTR(-ENOMEM);1525 }1526 1527 ale->params = *params;1528 ret = cpsw_ale_regfield_init(ale);1529 if (ret)1530 return ERR_PTR(ret);1531 1532 ale->p0_untag_vid_mask = devm_bitmap_zalloc(params->dev, VLAN_N_VID,1533 GFP_KERNEL);1534 if (!ale->p0_untag_vid_mask)1535 return ERR_PTR(-ENOMEM);1536 1537 ale->ageout = ale->params.ale_ageout * HZ;1538 ale->features = ale_dev_id->features;1539 ale->vlan_entry_tbl = ale_dev_id->vlan_entry_tbl;1540 1541 regmap_field_read(ale->fields[MINOR_VER], &rev_minor);1542 regmap_field_read(ale->fields[MAJOR_VER], &rev_major);1543 ale->version = rev_major << 8 | rev_minor;1544 dev_info(ale->params.dev, "initialized cpsw ale version %d.%d\n",1545 rev_major, rev_minor);1546 1547 if (ale->features & CPSW_ALE_F_STATUS_REG &&1548 !ale->params.ale_entries) {1549 regmap_field_read(ale->fields[ALE_ENTRIES], &ale_entries);1550 /* ALE available on newer NetCP switches has introduced1551 * a register, ALE_STATUS, to indicate the size of ALE1552 * table which shows the size as a multiple of 1024 entries.1553 * For these, params.ale_entries will be set to zero. So1554 * read the register and update the value of ale_entries.1555 * return error if ale_entries is zero in ALE_STATUS.1556 */1557 if (!ale_entries)1558 return ERR_PTR(-EINVAL);1559 1560 ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;1561 ale->params.ale_entries = ale_entries;1562 }1563 1564 if (ale->features & CPSW_ALE_F_STATUS_REG &&1565 !ale->params.num_policers) {1566 regmap_field_read(ale->fields[ALE_POLICERS], &policers);1567 if (!policers)1568 return ERR_PTR(-EINVAL);1569 1570 policers *= ALE_POLICER_SIZE_MULTIPLIER;1571 ale->params.num_policers = policers;1572 }1573 1574 dev_info(ale->params.dev,1575 "ALE Table size %ld, Policers %ld\n", ale->params.ale_entries,1576 ale->params.num_policers);1577 1578 /* set default bits for existing h/w */1579 ale->port_mask_bits = ale->params.ale_ports;1580 ale->port_num_bits = order_base_2(ale->params.ale_ports);1581 ale->vlan_field_bits = ale->params.ale_ports;1582 1583 /* Set defaults override for ALE on NetCP NU switch and for version1584 * 1R31585 */1586 if (ale->params.nu_switch_ale) {1587 /* Separate registers for unknown vlan configuration.1588 * Also there are N bits, where N is number of ale1589 * ports and shift value should be 01590 */1591 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].bits =1592 ale->params.ale_ports;1593 ale_controls[ALE_PORT_UNKNOWN_VLAN_MEMBER].offset =1594 ALE_UNKNOWNVLAN_MEMBER;1595 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].bits =1596 ale->params.ale_ports;1597 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].shift = 0;1598 ale_controls[ALE_PORT_UNKNOWN_MCAST_FLOOD].offset =1599 ALE_UNKNOWNVLAN_UNREG_MCAST_FLOOD;1600 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].bits =1601 ale->params.ale_ports;1602 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].shift = 0;1603 ale_controls[ALE_PORT_UNKNOWN_REG_MCAST_FLOOD].offset =1604 ALE_UNKNOWNVLAN_REG_MCAST_FLOOD;1605 ale_controls[ALE_PORT_UNTAGGED_EGRESS].bits =1606 ale->params.ale_ports;1607 ale_controls[ALE_PORT_UNTAGGED_EGRESS].shift = 0;1608 ale_controls[ALE_PORT_UNTAGGED_EGRESS].offset =1609 ALE_UNKNOWNVLAN_FORCE_UNTAG_EGRESS;1610 }1611 1612 cpsw_ale_control_set(ale, 0, ALE_CLEAR, 1);1613 return ale;1614}1615 1616void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)1617{1618 int i;1619 1620 for (i = 0; i < ale->params.ale_entries; i++) {1621 cpsw_ale_read(ale, i, data);1622 data += ALE_ENTRY_WORDS;1623 }1624}1625 1626void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data)1627{1628 int i;1629 1630 for (i = 0; i < ale->params.ale_entries; i++) {1631 cpsw_ale_write(ale, i, data);1632 data += ALE_ENTRY_WORDS;1633 }1634}1635 1636u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)1637{1638 return ale ? ale->params.ale_entries : 0;1639}1640 1641/* Reads the specified policer index into ALE POLICER registers */1642static void cpsw_ale_policer_read_idx(struct cpsw_ale *ale, u32 idx)1643{1644 idx &= ALE_POLICER_TBL_INDEX_MASK;1645 writel_relaxed(idx, ale->params.ale_regs + ALE_POLICER_TBL_CTL);1646}1647 1648/* Writes the ALE POLICER registers into the specified policer index */1649static void cpsw_ale_policer_write_idx(struct cpsw_ale *ale, u32 idx)1650{1651 idx &= ALE_POLICER_TBL_INDEX_MASK;1652 idx |= ALE_POLICER_TBL_WRITE_ENABLE;1653 writel_relaxed(idx, ale->params.ale_regs + ALE_POLICER_TBL_CTL);1654}1655 1656/* enables/disables the custom thread value for the specified policer index */1657static void cpsw_ale_policer_thread_idx_enable(struct cpsw_ale *ale, u32 idx,1658 u32 thread_id, bool enable)1659{1660 regmap_field_write(ale->fields[ALE_THREAD_CLASS_INDEX], idx);1661 regmap_field_write(ale->fields[ALE_THREAD_VALUE], thread_id);1662 regmap_field_write(ale->fields[ALE_THREAD_ENABLE], enable ? 1 : 0);1663}1664 1665/* Disable all policer entries and thread mappings */1666static void cpsw_ale_policer_reset(struct cpsw_ale *ale)1667{1668 int i;1669 1670 for (i = 0; i < ale->params.num_policers ; i++) {1671 cpsw_ale_policer_read_idx(ale, i);1672 regmap_field_write(ale->fields[POL_PORT_MEN], 0);1673 regmap_field_write(ale->fields[POL_PRI_MEN], 0);1674 regmap_field_write(ale->fields[POL_OUI_MEN], 0);1675 regmap_field_write(ale->fields[POL_DST_MEN], 0);1676 regmap_field_write(ale->fields[POL_SRC_MEN], 0);1677 regmap_field_write(ale->fields[POL_OVLAN_MEN], 0);1678 regmap_field_write(ale->fields[POL_IVLAN_MEN], 0);1679 regmap_field_write(ale->fields[POL_ETHERTYPE_MEN], 0);1680 regmap_field_write(ale->fields[POL_IPSRC_MEN], 0);1681 regmap_field_write(ale->fields[POL_IPDST_MEN], 0);1682 regmap_field_write(ale->fields[POL_EN], 0);1683 regmap_field_write(ale->fields[POL_RED_DROP_EN], 0);1684 regmap_field_write(ale->fields[POL_YELLOW_DROP_EN], 0);1685 regmap_field_write(ale->fields[POL_PRIORITY_THREAD_EN], 0);1686 1687 cpsw_ale_policer_thread_idx_enable(ale, i, 0, 0);1688 }1689}1690 1691/* Default classifier is to map 8 user priorities to N receive channels */1692void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch)1693{1694 int pri, idx;1695 /* IEEE802.1D-2004, Standard for Local and metropolitan area networks1696 * Table G-2 - Traffic type acronyms1697 * Table G-3 - Defining traffic types1698 * User priority values 1 and 2 effectively communicate a lower1699 * priority than 0. In the below table 0 is assigned to higher priority1700 * thread than 1 and 2 wherever possible.1701 * The below table maps which thread the user priority needs to be1702 * sent to for a given number of threads (RX channels). Upper threads1703 * have higher priority.1704 * e.g. if number of threads is 8 then user priority 0 will map to1705 * pri_thread_map[8-1][0] i.e. thread 21706 */1707 int pri_thread_map[8][8] = { { 0, 0, 0, 0, 0, 0, 0, 0, },1708 { 0, 0, 0, 0, 1, 1, 1, 1, },1709 { 0, 0, 0, 0, 1, 1, 2, 2, },1710 { 1, 0, 0, 1, 2, 2, 3, 3, },1711 { 1, 0, 0, 1, 2, 3, 4, 4, },1712 { 1, 0, 0, 2, 3, 4, 5, 5, },1713 { 1, 0, 0, 2, 3, 4, 5, 6, },1714 { 2, 0, 1, 3, 4, 5, 6, 7, } };1715 1716 cpsw_ale_policer_reset(ale);1717 1718 /* use first 8 classifiers to map 8 (DSCP/PCP) priorities to channels */1719 for (pri = 0; pri < 8; pri++) {1720 idx = pri;1721 1722 /* Classifier 'idx' match on priority 'pri' */1723 cpsw_ale_policer_read_idx(ale, idx);1724 regmap_field_write(ale->fields[POL_PRI_VAL], pri);1725 regmap_field_write(ale->fields[POL_PRI_MEN], 1);1726 cpsw_ale_policer_write_idx(ale, idx);1727 1728 /* Map Classifier 'idx' to thread provided by the map */1729 cpsw_ale_policer_thread_idx_enable(ale, idx,1730 pri_thread_map[num_rx_ch - 1][pri],1731 1);1732 }1733}1734