brintos

brintos / linux-shallow public Read only

0
0
Text · 46.2 KiB · 8d02d2b Raw
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