mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	Add icssg_config.h / .c and icssg_classifier.c files. These are firmware configuration and classification related files. Add MII helper APIs and MACROs. These APIs and MACROs will be later used by ICSSG Ethernet driver. Also introduce icssg_prueth.h which has definition of prueth related structures. Signed-off-by: MD Danish Anwar <danishanwar@ti.com> Reviewed-by: Ravi Gunasekaran <r-gunasekaran@ti.com>
		
			
				
	
	
		
			377 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			377 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/* Texas Instruments ICSSG Ethernet Driver
 | 
						|
 *
 | 
						|
 * Copyright (C) 2018-2024 Texas Instruments Incorporated - https://www.ti.com/
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include <dm/ofnode.h>
 | 
						|
#include <regmap.h>
 | 
						|
 | 
						|
#define ICSSG_NUM_CLASSIFIERS	16
 | 
						|
#define ICSSG_NUM_FT1_SLOTS	8
 | 
						|
#define ICSSG_NUM_FT3_SLOTS	16
 | 
						|
 | 
						|
#define ICSSG_NUM_CLASSIFIERS_IN_USE	1
 | 
						|
 | 
						|
/* Filter 1 - FT1 */
 | 
						|
#define FT1_NUM_SLOTS	8
 | 
						|
#define FT1_SLOT_SIZE	0x10	/* bytes */
 | 
						|
 | 
						|
/* offsets from FT1 slot base i.e. slot 1 start */
 | 
						|
#define FT1_DA0		0x0
 | 
						|
#define FT1_DA1		0x4
 | 
						|
#define FT1_DA0_MASK	0x8
 | 
						|
#define FT1_DA1_MASK	0xc
 | 
						|
 | 
						|
#define FT1_N_REG(slize, n, reg)	(offs[slice].ft1_slot_base + FT1_SLOT_SIZE * (n) + (reg))
 | 
						|
 | 
						|
#define FT1_LEN_MASK	GENMASK(19, 16)
 | 
						|
#define FT1_LEN_SHIFT	16
 | 
						|
#define FT1_LEN(len)	(((len) << FT1_LEN_SHIFT) & FT1_LEN_MASK)
 | 
						|
 | 
						|
#define FT1_START_MASK	GENMASK(14, 0)
 | 
						|
#define FT1_START(start)	((start) & FT1_START_MASK)
 | 
						|
 | 
						|
#define FT1_MATCH_SLOT(n)	(GENMASK(23, 16) & (BIT(n) << 16))
 | 
						|
 | 
						|
enum ft1_cfg_type {
 | 
						|
	FT1_CFG_TYPE_DISABLED = 0,
 | 
						|
	FT1_CFG_TYPE_EQ,
 | 
						|
	FT1_CFG_TYPE_GT,
 | 
						|
	FT1_CFG_TYPE_LT,
 | 
						|
};
 | 
						|
 | 
						|
#define FT1_CFG_SHIFT(n)	(2 * (n))
 | 
						|
#define FT1_CFG_MASK(n)	(0x3 << FT1_CFG_SHIFT((n)))
 | 
						|
 | 
						|
/* Filter 3 -  FT3 */
 | 
						|
#define FT3_NUM_SLOTS	16
 | 
						|
#define FT3_SLOT_SIZE	0x20	/* bytes */
 | 
						|
 | 
						|
/* offsets from FT3 slot n's base */
 | 
						|
#define FT3_START	0
 | 
						|
#define FT3_START_AUTO	0x4
 | 
						|
#define FT3_START_OFFSET	0x8
 | 
						|
#define FT3_JUMP_OFFSET	0xc
 | 
						|
#define FT3_LEN		0x10
 | 
						|
#define FT3_CFG		0x14
 | 
						|
#define FT3_T		0x18
 | 
						|
#define FT3_T_MASK	0x1c
 | 
						|
 | 
						|
#define FT3_N_REG(slize, n, reg)	\
 | 
						|
	(offs[slice].ft3_slot_base + FT3_SLOT_SIZE * (n) + (reg))
 | 
						|
 | 
						|
/* offsets from rx_class n's base */
 | 
						|
#define RX_CLASS_AND_EN	0
 | 
						|
#define RX_CLASS_OR_EN	0x4
 | 
						|
 | 
						|
#define RX_CLASS_NUM_SLOTS	16
 | 
						|
#define RX_CLASS_EN_SIZE	0x8	/* bytes */
 | 
						|
 | 
						|
#define RX_CLASS_N_REG(slice, n, reg)	\
 | 
						|
	(offs[slice].rx_class_base + RX_CLASS_EN_SIZE * (n) + (reg))
 | 
						|
 | 
						|
/* RX Class Gates */
 | 
						|
#define RX_CLASS_GATES_SIZE	0x4	/* bytes */
 | 
						|
 | 
						|
#define RX_CLASS_GATES_N_REG(slice, n)	\
 | 
						|
	(offs[slice].rx_class_gates_base + RX_CLASS_GATES_SIZE * (n))
 | 
						|
 | 
						|
#define RX_CLASS_GATES_ALLOW_MASK	BIT(6)
 | 
						|
#define RX_CLASS_GATES_RAW_MASK		BIT(5)
 | 
						|
#define RX_CLASS_GATES_PHASE_MASK	BIT(4)
 | 
						|
 | 
						|
/* RX Class traffic data matching bits */
 | 
						|
#define RX_CLASS_FT_UC		BIT(31)
 | 
						|
#define RX_CLASS_FT_MC		BIT(30)
 | 
						|
#define RX_CLASS_FT_BC		BIT(29)
 | 
						|
#define RX_CLASS_FT_FW		BIT(28)
 | 
						|
#define RX_CLASS_FT_RCV		BIT(27)
 | 
						|
#define RX_CLASS_FT_VLAN	BIT(26)
 | 
						|
#define RX_CLASS_FT_DA_P	BIT(25)
 | 
						|
#define RX_CLASS_FT_DA_I	BIT(24)
 | 
						|
#define RX_CLASS_FT_FT1_MATCH_MASK	GENMASK(23, 16)
 | 
						|
#define RX_CLASS_FT_FT1_MATCH_SHIFT	16
 | 
						|
#define RX_CLASS_FT_FT3_MATCH_MASK	GENMASK(15, 0)
 | 
						|
#define RX_CLASS_FT_FT3_MATCH_SHIFT	0
 | 
						|
 | 
						|
#define RX_CLASS_FT_FT1_MATCH(slot)	\
 | 
						|
	((BIT(slot) << RX_CLASS_FT_FT1_MATCH_SHIFT) & \
 | 
						|
	RX_CLASS_FT_FT1_MATCH_MASK)
 | 
						|
 | 
						|
enum rx_class_sel_type {
 | 
						|
	RX_CLASS_SEL_TYPE_OR = 0,
 | 
						|
	RX_CLASS_SEL_TYPE_AND = 1,
 | 
						|
	RX_CLASS_SEL_TYPE_OR_AND_AND = 2,
 | 
						|
	RX_CLASS_SEL_TYPE_OR_OR_AND = 3,
 | 
						|
};
 | 
						|
 | 
						|
#define FT1_CFG_SHIFT(n)	(2 * (n))
 | 
						|
#define FT1_CFG_MASK(n)		(0x3 << FT1_CFG_SHIFT((n)))
 | 
						|
 | 
						|
#define RX_CLASS_SEL_SHIFT(n)	(2 * (n))
 | 
						|
#define RX_CLASS_SEL_MASK(n)	(0x3 << RX_CLASS_SEL_SHIFT((n)))
 | 
						|
 | 
						|
#define ICSSG_CFG_OFFSET	0
 | 
						|
#define MAC_INTERFACE_0		0x18
 | 
						|
#define MAC_INTERFACE_1		0x1c
 | 
						|
 | 
						|
#define ICSSG_CFG_RX_L2_G_EN	BIT(2)
 | 
						|
 | 
						|
/* these are register offsets per PRU */
 | 
						|
struct miig_rt_offsets {
 | 
						|
	u32 mac0;
 | 
						|
	u32 mac1;
 | 
						|
	u32 ft1_start_len;
 | 
						|
	u32 ft1_cfg;
 | 
						|
	u32 ft1_slot_base;
 | 
						|
	u32 ft3_slot_base;
 | 
						|
	u32 ft3_p_base;
 | 
						|
	u32 ft_rx_ptr;
 | 
						|
	u32 rx_class_base;
 | 
						|
	u32 rx_class_cfg1;
 | 
						|
	u32 rx_class_cfg2;
 | 
						|
	u32 rx_class_gates_base;
 | 
						|
	u32 rx_green;
 | 
						|
	u32 rx_rate_cfg_base;
 | 
						|
	u32 rx_rate_src_sel0;
 | 
						|
	u32 rx_rate_src_sel1;
 | 
						|
	u32 tx_rate_cfg_base;
 | 
						|
	u32 stat_base;
 | 
						|
	u32 tx_hsr_tag;
 | 
						|
	u32 tx_hsr_seq;
 | 
						|
	u32 tx_vlan_type;
 | 
						|
	u32 tx_vlan_ins;
 | 
						|
};
 | 
						|
 | 
						|
static struct miig_rt_offsets offs[] = {
 | 
						|
	/* PRU0 */
 | 
						|
	{
 | 
						|
		0x8,
 | 
						|
		0xc,
 | 
						|
		0x80,
 | 
						|
		0x84,
 | 
						|
		0x88,
 | 
						|
		0x108,
 | 
						|
		0x308,
 | 
						|
		0x408,
 | 
						|
		0x40c,
 | 
						|
		0x48c,
 | 
						|
		0x490,
 | 
						|
		0x494,
 | 
						|
		0x4d4,
 | 
						|
		0x4e4,
 | 
						|
		0x504,
 | 
						|
		0x508,
 | 
						|
		0x50c,
 | 
						|
		0x54c,
 | 
						|
		0x63c,
 | 
						|
		0x640,
 | 
						|
		0x644,
 | 
						|
		0x648,
 | 
						|
	},
 | 
						|
	/* PRU1 */
 | 
						|
	{
 | 
						|
		0x10,
 | 
						|
		0x14,
 | 
						|
		0x64c,
 | 
						|
		0x650,
 | 
						|
		0x654,
 | 
						|
		0x6d4,
 | 
						|
		0x8d4,
 | 
						|
		0x9d4,
 | 
						|
		0x9d8,
 | 
						|
		0xa58,
 | 
						|
		0xa5c,
 | 
						|
		0xa60,
 | 
						|
		0xaa0,
 | 
						|
		0xab0,
 | 
						|
		0xad0,
 | 
						|
		0xad4,
 | 
						|
		0xad8,
 | 
						|
		0xb18,
 | 
						|
		0xc08,
 | 
						|
		0xc0c,
 | 
						|
		0xc10,
 | 
						|
		0xc14,
 | 
						|
	},
 | 
						|
};
 | 
						|
 | 
						|
static inline u32 addr_to_da0(const u8 *addr)
 | 
						|
{
 | 
						|
	return (u32)(addr[0] | addr[1] << 8 |
 | 
						|
		addr[2] << 16 | addr[3] << 24);
 | 
						|
};
 | 
						|
 | 
						|
static inline u32 addr_to_da1(const u8 *addr)
 | 
						|
{
 | 
						|
	return (u32)(addr[4] | addr[5] << 8);
 | 
						|
};
 | 
						|
 | 
						|
static void rx_class_ft1_set_start_len(struct regmap *miig_rt, int slice,
 | 
						|
				       u16 start, u8 len)
 | 
						|
{
 | 
						|
	u32 offset, val;
 | 
						|
 | 
						|
	offset = offs[slice].ft1_start_len;
 | 
						|
	val = FT1_LEN(len) | FT1_START(start);
 | 
						|
	regmap_write(miig_rt, offset, val);
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_set_da(struct regmap *miig_rt, int slice,
 | 
						|
				int n, const u8 *addr)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA0);
 | 
						|
	regmap_write(miig_rt, offset, addr_to_da0(addr));
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA1);
 | 
						|
	regmap_write(miig_rt, offset, addr_to_da1(addr));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_set_da_mask(struct regmap *miig_rt, int slice,
 | 
						|
				     int n, const u8 *addr)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA0_MASK);
 | 
						|
	regmap_write(miig_rt, offset, addr_to_da0(addr));
 | 
						|
	offset = FT1_N_REG(slice, n, FT1_DA1_MASK);
 | 
						|
	regmap_write(miig_rt, offset, addr_to_da1(addr));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_ft1_cfg_set_type(struct regmap *miig_rt, int slice, int n,
 | 
						|
				      enum ft1_cfg_type type)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = offs[slice].ft1_cfg;
 | 
						|
	regmap_update_bits(miig_rt, offset, FT1_CFG_MASK(n),
 | 
						|
			   type << FT1_CFG_SHIFT(n));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_sel_set_type(struct regmap *miig_rt, int slice, int n,
 | 
						|
				  enum rx_class_sel_type type)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = offs[slice].rx_class_cfg1;
 | 
						|
	regmap_update_bits(miig_rt, offset, RX_CLASS_SEL_MASK(n),
 | 
						|
			   type << RX_CLASS_SEL_SHIFT(n));
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_set_and(struct regmap *miig_rt, int slice, int n,
 | 
						|
			     u32 data)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_AND_EN);
 | 
						|
	regmap_write(miig_rt, offset, data);
 | 
						|
}
 | 
						|
 | 
						|
static void rx_class_set_or(struct regmap *miig_rt, int slice, int n,
 | 
						|
			    u32 data)
 | 
						|
{
 | 
						|
	u32 offset;
 | 
						|
 | 
						|
	offset = RX_CLASS_N_REG(slice, n, RX_CLASS_OR_EN);
 | 
						|
	regmap_write(miig_rt, offset, data);
 | 
						|
}
 | 
						|
 | 
						|
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, u8 *mac)
 | 
						|
{
 | 
						|
	regmap_write(miig_rt, MAC_INTERFACE_0, addr_to_da0(mac));
 | 
						|
	regmap_write(miig_rt, MAC_INTERFACE_1, addr_to_da1(mac));
 | 
						|
}
 | 
						|
 | 
						|
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
 | 
						|
{
 | 
						|
	regmap_write(miig_rt, offs[slice].mac0, addr_to_da0(mac));
 | 
						|
	regmap_write(miig_rt, offs[slice].mac1, addr_to_da1(mac));
 | 
						|
}
 | 
						|
 | 
						|
void icssg_class_disable_n(struct regmap *miig_rt, int slice, int n)
 | 
						|
{
 | 
						|
	u32 data, offset;
 | 
						|
 | 
						|
	/* AND_EN = 0 */
 | 
						|
	rx_class_set_and(miig_rt, slice, n, 0);
 | 
						|
	/* OR_EN = 0 */
 | 
						|
	rx_class_set_or(miig_rt, slice, n, 0);
 | 
						|
 | 
						|
	/* set CFG1 to OR */
 | 
						|
	rx_class_sel_set_type(miig_rt, slice, n, RX_CLASS_SEL_TYPE_OR);
 | 
						|
 | 
						|
	/* configure gate */
 | 
						|
	offset = RX_CLASS_GATES_N_REG(slice, n);
 | 
						|
	regmap_read(miig_rt, offset, &data);
 | 
						|
	/* clear class_raw so we go through filters */
 | 
						|
	data &= ~RX_CLASS_GATES_RAW_MASK;
 | 
						|
	/* set allow and phase mask */
 | 
						|
	data |= RX_CLASS_GATES_ALLOW_MASK | RX_CLASS_GATES_PHASE_MASK;
 | 
						|
	regmap_write(miig_rt, offset, data);
 | 
						|
}
 | 
						|
 | 
						|
/* disable all RX traffic */
 | 
						|
void icssg_class_disable(struct regmap *miig_rt, int slice)
 | 
						|
{
 | 
						|
	int n;
 | 
						|
 | 
						|
	/* Enable RX_L2_G */
 | 
						|
	regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, ICSSG_CFG_RX_L2_G_EN,
 | 
						|
			   ICSSG_CFG_RX_L2_G_EN);
 | 
						|
 | 
						|
	for (n = 0; n < ICSSG_NUM_CLASSIFIERS; n++)
 | 
						|
		icssg_class_disable_n(miig_rt, slice, n);
 | 
						|
 | 
						|
	/* FT1 Disabled */
 | 
						|
	for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
 | 
						|
		u8 addr[] = { 0, 0, 0, 0, 0, 0, };
 | 
						|
 | 
						|
		rx_class_ft1_cfg_set_type(miig_rt, slice, n,
 | 
						|
					  FT1_CFG_TYPE_DISABLED);
 | 
						|
		rx_class_ft1_set_da(miig_rt, slice, n, addr);
 | 
						|
		rx_class_ft1_set_da_mask(miig_rt, slice, n, addr);
 | 
						|
	}
 | 
						|
 | 
						|
	/* clear CFG2 */
 | 
						|
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
 | 
						|
}
 | 
						|
 | 
						|
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti)
 | 
						|
{
 | 
						|
	u32 data;
 | 
						|
 | 
						|
	/* defaults */
 | 
						|
	icssg_class_disable(miig_rt, slice);
 | 
						|
 | 
						|
	/* Setup Classifier */
 | 
						|
	/* match on Broadcast or MAC_PRU address */
 | 
						|
	data = RX_CLASS_FT_BC | RX_CLASS_FT_DA_P;
 | 
						|
 | 
						|
	/* multicast? */
 | 
						|
	if (allmulti)
 | 
						|
		data |= RX_CLASS_FT_MC;
 | 
						|
 | 
						|
	rx_class_set_or(miig_rt, slice, 0, data);
 | 
						|
 | 
						|
	/* set CFG1 for OR_OR_AND for classifier */
 | 
						|
	rx_class_sel_set_type(miig_rt, slice, 0,
 | 
						|
			      RX_CLASS_SEL_TYPE_OR_OR_AND);
 | 
						|
 | 
						|
	/* clear CFG2 */
 | 
						|
	regmap_write(miig_rt, offs[slice].rx_class_cfg2, 0);
 | 
						|
}
 | 
						|
 | 
						|
/* required for SR2 for SAV check */
 | 
						|
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
 | 
						|
{
 | 
						|
	u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
 | 
						|
 | 
						|
	rx_class_ft1_set_start_len(miig_rt, slice, 6, 6);
 | 
						|
	rx_class_ft1_set_da(miig_rt, slice, 0, mac_addr);
 | 
						|
	rx_class_ft1_set_da_mask(miig_rt, slice, 0, mask_addr);
 | 
						|
	rx_class_ft1_cfg_set_type(miig_rt, slice, 0, FT1_CFG_TYPE_EQ);
 | 
						|
}
 |