mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-30 23:54:04 +08:00
net: ti: icssg-prueth: Add Firmware config and classification APIs.
Add icssg_config.h / .c and icssg_classifier.c files. These are firmware configuration and classification related files. These will be used by ICSSG ethernet driver. Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: MD Danish Anwar <danishanwar@ti.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
b6ba775214
commit
e9b4ece7d7
367
drivers/net/ethernet/ti/icssg/icssg_classifier.c
Normal file
367
drivers/net/ethernet/ti/icssg/icssg_classifier.c
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* Texas Instruments ICSSG Ethernet Driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/etherdevice.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
#include "icssg_prueth.h"
|
||||||
|
|
||||||
|
#define ICSSG_NUM_CLASSIFIERS 16
|
||||||
|
#define ICSSG_NUM_FT1_SLOTS 8
|
||||||
|
#define ICSSG_NUM_FT3_SLOTS 16
|
||||||
|
|
||||||
|
#define ICSSG_NUM_CLASSIFIERS_IN_USE 5
|
||||||
|
|
||||||
|
/* 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))
|
||||||
|
|
||||||
|
/* FT1 config type */
|
||||||
|
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)
|
||||||
|
|
||||||
|
/* RX class type */
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* These are the offset values for miig_rt_offsets registers */
|
||||||
|
static const 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 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, (u32)(addr[0] | addr[1] << 8 |
|
||||||
|
addr[2] << 16 | addr[3] << 24));
|
||||||
|
offset = FT1_N_REG(slice, n, FT1_DA1);
|
||||||
|
regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
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, (u32)(addr[0] | addr[1] << 8 |
|
||||||
|
addr[2] << 16 | addr[3] << 24));
|
||||||
|
offset = FT1_N_REG(slice, n, FT1_DA1_MASK);
|
||||||
|
regmap_write(miig_rt, offset, (u32)(addr[4] | addr[5] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
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, const u8 *mac)
|
||||||
|
{
|
||||||
|
regmap_write(miig_rt, MAC_INTERFACE_0, (u32)(mac[0] | mac[1] << 8 |
|
||||||
|
mac[2] << 16 | mac[3] << 24));
|
||||||
|
regmap_write(miig_rt, MAC_INTERFACE_1, (u32)(mac[4] | mac[5] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac)
|
||||||
|
{
|
||||||
|
regmap_write(miig_rt, offs[slice].mac0, (u32)(mac[0] | mac[1] << 8 |
|
||||||
|
mac[2] << 16 | mac[3] << 24));
|
||||||
|
regmap_write(miig_rt, offs[slice].mac1, (u32)(mac[4] | mac[5] << 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable all RX traffic */
|
||||||
|
void icssg_class_disable(struct regmap *miig_rt, int slice)
|
||||||
|
{
|
||||||
|
u32 data, offset;
|
||||||
|
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++) {
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FT1 Disabled */
|
||||||
|
for (n = 0; n < ICSSG_NUM_FT1_SLOTS; n++) {
|
||||||
|
const 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 SAV check */
|
||||||
|
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr)
|
||||||
|
{
|
||||||
|
const u8 mask_addr[] = { 0, 0, 0, 0, 0, 0, };
|
||||||
|
|
||||||
|
rx_class_ft1_set_start_len(miig_rt, slice, 0, 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);
|
||||||
|
}
|
450
drivers/net/ethernet/ti/icssg/icssg_config.c
Normal file
450
drivers/net/ethernet/ti/icssg/icssg_config.c
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/* ICSSG Ethernet driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <uapi/linux/if_ether.h>
|
||||||
|
#include "icssg_config.h"
|
||||||
|
#include "icssg_prueth.h"
|
||||||
|
#include "icssg_switch_map.h"
|
||||||
|
#include "icssg_mii_rt.h"
|
||||||
|
|
||||||
|
/* TX IPG Values to be set for 100M link speed. These values are
|
||||||
|
* in ocp_clk cycles. So need change if ocp_clk is changed for a specific
|
||||||
|
* h/w design.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* IPG is in core_clk cycles */
|
||||||
|
#define MII_RT_TX_IPG_100M 0x17
|
||||||
|
#define MII_RT_TX_IPG_1G 0xb
|
||||||
|
|
||||||
|
#define ICSSG_QUEUES_MAX 64
|
||||||
|
#define ICSSG_QUEUE_OFFSET 0xd00
|
||||||
|
#define ICSSG_QUEUE_PEEK_OFFSET 0xe00
|
||||||
|
#define ICSSG_QUEUE_CNT_OFFSET 0xe40
|
||||||
|
#define ICSSG_QUEUE_RESET_OFFSET 0xf40
|
||||||
|
|
||||||
|
#define ICSSG_NUM_TX_QUEUES 8
|
||||||
|
|
||||||
|
#define RECYCLE_Q_SLICE0 16
|
||||||
|
#define RECYCLE_Q_SLICE1 17
|
||||||
|
|
||||||
|
#define ICSSG_NUM_OTHER_QUEUES 5 /* port, host and special queues */
|
||||||
|
|
||||||
|
#define PORT_HI_Q_SLICE0 32
|
||||||
|
#define PORT_LO_Q_SLICE0 33
|
||||||
|
#define HOST_HI_Q_SLICE0 34
|
||||||
|
#define HOST_LO_Q_SLICE0 35
|
||||||
|
#define HOST_SPL_Q_SLICE0 40 /* Special Queue */
|
||||||
|
|
||||||
|
#define PORT_HI_Q_SLICE1 36
|
||||||
|
#define PORT_LO_Q_SLICE1 37
|
||||||
|
#define HOST_HI_Q_SLICE1 38
|
||||||
|
#define HOST_LO_Q_SLICE1 39
|
||||||
|
#define HOST_SPL_Q_SLICE1 41 /* Special Queue */
|
||||||
|
|
||||||
|
#define MII_RXCFG_DEFAULT (PRUSS_MII_RT_RXCFG_RX_ENABLE | \
|
||||||
|
PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS | \
|
||||||
|
PRUSS_MII_RT_RXCFG_RX_L2_EN | \
|
||||||
|
PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS)
|
||||||
|
|
||||||
|
#define MII_TXCFG_DEFAULT (PRUSS_MII_RT_TXCFG_TX_ENABLE | \
|
||||||
|
PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE | \
|
||||||
|
PRUSS_MII_RT_TXCFG_TX_32_MODE_EN | \
|
||||||
|
PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN)
|
||||||
|
|
||||||
|
#define ICSSG_CFG_DEFAULT (ICSSG_CFG_TX_L1_EN | \
|
||||||
|
ICSSG_CFG_TX_L2_EN | ICSSG_CFG_RX_L2_G_EN | \
|
||||||
|
ICSSG_CFG_TX_PRU_EN | \
|
||||||
|
ICSSG_CFG_SGMII_MODE)
|
||||||
|
|
||||||
|
#define FDB_GEN_CFG1 0x60
|
||||||
|
#define SMEM_VLAN_OFFSET 8
|
||||||
|
#define SMEM_VLAN_OFFSET_MASK GENMASK(25, 8)
|
||||||
|
|
||||||
|
#define FDB_GEN_CFG2 0x64
|
||||||
|
#define FDB_VLAN_EN BIT(6)
|
||||||
|
#define FDB_HOST_EN BIT(2)
|
||||||
|
#define FDB_PRU1_EN BIT(1)
|
||||||
|
#define FDB_PRU0_EN BIT(0)
|
||||||
|
#define FDB_EN_ALL (FDB_PRU0_EN | FDB_PRU1_EN | \
|
||||||
|
FDB_HOST_EN | FDB_VLAN_EN)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct map - ICSSG Queue Map
|
||||||
|
* @queue: Queue number
|
||||||
|
* @pd_addr_start: Packet descriptor queue reserved memory
|
||||||
|
* @flags: Flags
|
||||||
|
* @special: Indicates whether this queue is a special queue or not
|
||||||
|
*/
|
||||||
|
struct map {
|
||||||
|
int queue;
|
||||||
|
u32 pd_addr_start;
|
||||||
|
u32 flags;
|
||||||
|
bool special;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Hardware queue map for ICSSG */
|
||||||
|
static const struct map hwq_map[2][ICSSG_NUM_OTHER_QUEUES] = {
|
||||||
|
{
|
||||||
|
{ PORT_HI_Q_SLICE0, PORT_DESC0_HI, 0x200000, 0 },
|
||||||
|
{ PORT_LO_Q_SLICE0, PORT_DESC0_LO, 0, 0 },
|
||||||
|
{ HOST_HI_Q_SLICE0, HOST_DESC0_HI, 0x200000, 0 },
|
||||||
|
{ HOST_LO_Q_SLICE0, HOST_DESC0_LO, 0, 0 },
|
||||||
|
{ HOST_SPL_Q_SLICE0, HOST_SPPD0, 0x400000, 1 },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{ PORT_HI_Q_SLICE1, PORT_DESC1_HI, 0xa00000, 0 },
|
||||||
|
{ PORT_LO_Q_SLICE1, PORT_DESC1_LO, 0x800000, 0 },
|
||||||
|
{ HOST_HI_Q_SLICE1, HOST_DESC1_HI, 0xa00000, 0 },
|
||||||
|
{ HOST_LO_Q_SLICE1, HOST_DESC1_LO, 0x800000, 0 },
|
||||||
|
{ HOST_SPL_Q_SLICE1, HOST_SPPD1, 0xc00000, 1 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void icssg_config_mii_init(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
u32 rxcfg, txcfg, rxcfg_reg, txcfg_reg, pcnt_reg;
|
||||||
|
struct prueth *prueth = emac->prueth;
|
||||||
|
int slice = prueth_emac_slice(emac);
|
||||||
|
struct regmap *mii_rt;
|
||||||
|
|
||||||
|
mii_rt = prueth->mii_rt;
|
||||||
|
|
||||||
|
rxcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RXCFG0 :
|
||||||
|
PRUSS_MII_RT_RXCFG1;
|
||||||
|
txcfg_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_TXCFG0 :
|
||||||
|
PRUSS_MII_RT_TXCFG1;
|
||||||
|
pcnt_reg = (slice == ICSS_MII0) ? PRUSS_MII_RT_RX_PCNT0 :
|
||||||
|
PRUSS_MII_RT_RX_PCNT1;
|
||||||
|
|
||||||
|
rxcfg = MII_RXCFG_DEFAULT;
|
||||||
|
txcfg = MII_TXCFG_DEFAULT;
|
||||||
|
|
||||||
|
if (slice == ICSS_MII1)
|
||||||
|
rxcfg |= PRUSS_MII_RT_RXCFG_RX_MUX_SEL;
|
||||||
|
|
||||||
|
/* In MII mode TX lines swapped inside ICSSG, so TX_MUX_SEL cfg need
|
||||||
|
* to be swapped also comparing to RGMII mode.
|
||||||
|
*/
|
||||||
|
if (emac->phy_if == PHY_INTERFACE_MODE_MII && slice == ICSS_MII0)
|
||||||
|
txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
|
||||||
|
else if (emac->phy_if != PHY_INTERFACE_MODE_MII && slice == ICSS_MII1)
|
||||||
|
txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
|
||||||
|
|
||||||
|
regmap_write(mii_rt, rxcfg_reg, rxcfg);
|
||||||
|
regmap_write(mii_rt, txcfg_reg, txcfg);
|
||||||
|
regmap_write(mii_rt, pcnt_reg, 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void icssg_miig_queues_init(struct prueth *prueth, int slice)
|
||||||
|
{
|
||||||
|
struct regmap *miig_rt = prueth->miig_rt;
|
||||||
|
void __iomem *smem = prueth->shram.va;
|
||||||
|
u8 pd[ICSSG_SPECIAL_PD_SIZE];
|
||||||
|
int queue = 0, i, j;
|
||||||
|
u32 *pdword;
|
||||||
|
|
||||||
|
/* reset hwqueues */
|
||||||
|
if (slice)
|
||||||
|
queue = ICSSG_NUM_TX_QUEUES;
|
||||||
|
|
||||||
|
for (i = 0; i < ICSSG_NUM_TX_QUEUES; i++) {
|
||||||
|
regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
|
||||||
|
queue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue = slice ? RECYCLE_Q_SLICE1 : RECYCLE_Q_SLICE0;
|
||||||
|
regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET, queue);
|
||||||
|
|
||||||
|
for (i = 0; i < ICSSG_NUM_OTHER_QUEUES; i++) {
|
||||||
|
regmap_write(miig_rt, ICSSG_QUEUE_RESET_OFFSET,
|
||||||
|
hwq_map[slice][i].queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize packet descriptors in SMEM */
|
||||||
|
/* push pakcet descriptors to hwqueues */
|
||||||
|
|
||||||
|
pdword = (u32 *)pd;
|
||||||
|
for (j = 0; j < ICSSG_NUM_OTHER_QUEUES; j++) {
|
||||||
|
const struct map *mp;
|
||||||
|
int pd_size, num_pds;
|
||||||
|
u32 pdaddr;
|
||||||
|
|
||||||
|
mp = &hwq_map[slice][j];
|
||||||
|
if (mp->special) {
|
||||||
|
pd_size = ICSSG_SPECIAL_PD_SIZE;
|
||||||
|
num_pds = ICSSG_NUM_SPECIAL_PDS;
|
||||||
|
} else {
|
||||||
|
pd_size = ICSSG_NORMAL_PD_SIZE;
|
||||||
|
num_pds = ICSSG_NUM_NORMAL_PDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num_pds; i++) {
|
||||||
|
memset(pd, 0, pd_size);
|
||||||
|
|
||||||
|
pdword[0] &= ICSSG_FLAG_MASK;
|
||||||
|
pdword[0] |= mp->flags;
|
||||||
|
pdaddr = mp->pd_addr_start + i * pd_size;
|
||||||
|
|
||||||
|
memcpy_toio(smem + pdaddr, pd, pd_size);
|
||||||
|
queue = mp->queue;
|
||||||
|
regmap_write(miig_rt, ICSSG_QUEUE_OFFSET + 4 * queue,
|
||||||
|
pdaddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void icssg_config_ipg(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
struct prueth *prueth = emac->prueth;
|
||||||
|
int slice = prueth_emac_slice(emac);
|
||||||
|
|
||||||
|
switch (emac->speed) {
|
||||||
|
case SPEED_1000:
|
||||||
|
icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_1G);
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Other links speeds not supported */
|
||||||
|
netdev_err(emac->ndev, "Unsupported link speed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emac_r30_cmd_init(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
struct icssg_r30_cmd __iomem *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = emac->dram.va + MGR_R30_CMD_OFFSET;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
writel(EMAC_NONE, &p->cmd[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int emac_r30_is_done(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
const struct icssg_r30_cmd __iomem *p;
|
||||||
|
u32 cmd;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = emac->dram.va + MGR_R30_CMD_OFFSET;
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++) {
|
||||||
|
cmd = readl(&p->cmd[i]);
|
||||||
|
if (cmd != EMAC_NONE)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int prueth_emac_buffer_setup(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
struct icssg_buffer_pool_cfg __iomem *bpool_cfg;
|
||||||
|
struct icssg_rxq_ctx __iomem *rxq_ctx;
|
||||||
|
struct prueth *prueth = emac->prueth;
|
||||||
|
int slice = prueth_emac_slice(emac);
|
||||||
|
u32 addr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Layout to have 64KB aligned buffer pool
|
||||||
|
* |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1|
|
||||||
|
*/
|
||||||
|
|
||||||
|
addr = lower_32_bits(prueth->msmcram.pa);
|
||||||
|
if (slice)
|
||||||
|
addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
|
||||||
|
|
||||||
|
if (addr % SZ_64K) {
|
||||||
|
dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET;
|
||||||
|
/* workaround for f/w bug. bpool 0 needs to be initilalized */
|
||||||
|
writel(addr, &bpool_cfg[0].addr);
|
||||||
|
writel(0, &bpool_cfg[0].len);
|
||||||
|
|
||||||
|
for (i = PRUETH_EMAC_BUF_POOL_START;
|
||||||
|
i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS;
|
||||||
|
i++) {
|
||||||
|
writel(addr, &bpool_cfg[i].addr);
|
||||||
|
writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len);
|
||||||
|
addr += PRUETH_EMAC_BUF_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!slice)
|
||||||
|
addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE;
|
||||||
|
else
|
||||||
|
addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2;
|
||||||
|
|
||||||
|
/* Pre-emptible RX buffer queue */
|
||||||
|
rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
writel(addr, &rxq_ctx->start[i]);
|
||||||
|
|
||||||
|
addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
|
||||||
|
writel(addr, &rxq_ctx->end);
|
||||||
|
|
||||||
|
/* Express RX buffer queue */
|
||||||
|
rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET;
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
writel(addr, &rxq_ctx->start[i]);
|
||||||
|
|
||||||
|
addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
|
||||||
|
writel(addr, &rxq_ctx->end);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void icssg_init_emac_mode(struct prueth *prueth)
|
||||||
|
{
|
||||||
|
/* When the device is configured as a bridge and it is being brought
|
||||||
|
* back to the emac mode, the host mac address has to be set as 0.
|
||||||
|
*/
|
||||||
|
u8 mac[ETH_ALEN] = { 0 };
|
||||||
|
|
||||||
|
if (prueth->emacs_initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1,
|
||||||
|
SMEM_VLAN_OFFSET_MASK, 0);
|
||||||
|
regmap_write(prueth->miig_rt, FDB_GEN_CFG2, 0);
|
||||||
|
/* Clear host MAC address */
|
||||||
|
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
|
||||||
|
}
|
||||||
|
|
||||||
|
int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
|
||||||
|
{
|
||||||
|
void __iomem *config = emac->dram.va + ICSSG_CONFIG_OFFSET;
|
||||||
|
struct icssg_flow_cfg __iomem *flow_cfg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
icssg_init_emac_mode(prueth);
|
||||||
|
|
||||||
|
memset_io(config, 0, TAS_GATE_MASK_LIST0);
|
||||||
|
icssg_miig_queues_init(prueth, slice);
|
||||||
|
|
||||||
|
emac->speed = SPEED_1000;
|
||||||
|
emac->duplex = DUPLEX_FULL;
|
||||||
|
if (!phy_interface_mode_is_rgmii(emac->phy_if)) {
|
||||||
|
emac->speed = SPEED_100;
|
||||||
|
emac->duplex = DUPLEX_FULL;
|
||||||
|
}
|
||||||
|
regmap_update_bits(prueth->miig_rt, ICSSG_CFG_OFFSET,
|
||||||
|
ICSSG_CFG_DEFAULT, ICSSG_CFG_DEFAULT);
|
||||||
|
icssg_miig_set_interface_mode(prueth->miig_rt, slice, emac->phy_if);
|
||||||
|
icssg_config_mii_init(emac);
|
||||||
|
icssg_config_ipg(emac);
|
||||||
|
icssg_update_rgmii_cfg(prueth->miig_rt, emac);
|
||||||
|
|
||||||
|
/* set GPI mode */
|
||||||
|
pruss_cfg_gpimode(prueth->pruss, prueth->pru_id[slice],
|
||||||
|
PRUSS_GPI_MODE_MII);
|
||||||
|
|
||||||
|
/* enable XFR shift for PRU and RTU */
|
||||||
|
pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_PRU, true);
|
||||||
|
pruss_cfg_xfr_enable(prueth->pruss, PRU_TYPE_RTU, true);
|
||||||
|
|
||||||
|
/* set C28 to 0x100 */
|
||||||
|
pru_rproc_set_ctable(prueth->pru[slice], PRU_C28, 0x100 << 8);
|
||||||
|
pru_rproc_set_ctable(prueth->rtu[slice], PRU_C28, 0x100 << 8);
|
||||||
|
pru_rproc_set_ctable(prueth->txpru[slice], PRU_C28, 0x100 << 8);
|
||||||
|
|
||||||
|
flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
|
||||||
|
writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow);
|
||||||
|
writew(0, &flow_cfg->mgm_base_flow);
|
||||||
|
writeb(0, config + SPL_PKT_DEFAULT_PRIORITY);
|
||||||
|
writeb(0, config + QUEUE_NUM_UNTAGGED);
|
||||||
|
|
||||||
|
ret = prueth_emac_buffer_setup(emac);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
emac_r30_cmd_init(emac);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bitmask for ICSSG r30 commands */
|
||||||
|
static const struct icssg_r30_cmd emac_r32_bitmask[] = {
|
||||||
|
{{0xffff0004, 0xffff0100, 0xffff0100, EMAC_NONE}}, /* EMAC_PORT_DISABLE */
|
||||||
|
{{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}}, /* EMAC_PORT_BLOCK */
|
||||||
|
{{0xffbb0000, 0xfcff0000, 0xdcff0000, EMAC_NONE}}, /* EMAC_PORT_FORWARD */
|
||||||
|
{{0xffbb0000, 0xfcff0000, 0xfcff2000, EMAC_NONE}}, /* EMAC_PORT_FORWARD_WO_LEARNING */
|
||||||
|
{{0xffff0001, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT ALL */
|
||||||
|
{{0xfffe0002, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT TAGGED */
|
||||||
|
{{0xfffc0000, EMAC_NONE, EMAC_NONE, EMAC_NONE}}, /* ACCEPT UNTAGGED and PRIO */
|
||||||
|
{{EMAC_NONE, 0xffff0020, EMAC_NONE, EMAC_NONE}}, /* TAS Trigger List change */
|
||||||
|
{{EMAC_NONE, 0xdfff1000, EMAC_NONE, EMAC_NONE}}, /* TAS set state ENABLE*/
|
||||||
|
{{EMAC_NONE, 0xefff2000, EMAC_NONE, EMAC_NONE}}, /* TAS set state RESET*/
|
||||||
|
{{EMAC_NONE, 0xcfff0000, EMAC_NONE, EMAC_NONE}}, /* TAS set state DISABLE*/
|
||||||
|
{{EMAC_NONE, EMAC_NONE, 0xffff0400, EMAC_NONE}}, /* UC flooding ENABLE*/
|
||||||
|
{{EMAC_NONE, EMAC_NONE, 0xfbff0000, EMAC_NONE}}, /* UC flooding DISABLE*/
|
||||||
|
{{EMAC_NONE, EMAC_NONE, 0xffff0800, EMAC_NONE}}, /* MC flooding ENABLE*/
|
||||||
|
{{EMAC_NONE, EMAC_NONE, 0xf7ff0000, EMAC_NONE}}, /* MC flooding DISABLE*/
|
||||||
|
{{EMAC_NONE, 0xffff4000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx ENABLE*/
|
||||||
|
{{EMAC_NONE, 0xbfff0000, EMAC_NONE, EMAC_NONE}}, /* Preemption on Tx DISABLE*/
|
||||||
|
{{0xffff0010, EMAC_NONE, 0xffff0010, EMAC_NONE}}, /* VLAN AWARE*/
|
||||||
|
{{0xffef0000, EMAC_NONE, 0xffef0000, EMAC_NONE}} /* VLAN UNWARE*/
|
||||||
|
};
|
||||||
|
|
||||||
|
int emac_set_port_state(struct prueth_emac *emac,
|
||||||
|
enum icssg_port_state_cmd cmd)
|
||||||
|
{
|
||||||
|
struct icssg_r30_cmd __iomem *p;
|
||||||
|
int ret = -ETIMEDOUT;
|
||||||
|
int done = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
p = emac->dram.va + MGR_R30_CMD_OFFSET;
|
||||||
|
|
||||||
|
if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) {
|
||||||
|
netdev_err(emac->ndev, "invalid port command\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only one command at a time allowed to firmware */
|
||||||
|
mutex_lock(&emac->cmd_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]);
|
||||||
|
|
||||||
|
/* wait for done */
|
||||||
|
ret = read_poll_timeout(emac_r30_is_done, done, done == 1,
|
||||||
|
1000, 10000, false, emac);
|
||||||
|
|
||||||
|
if (ret == -ETIMEDOUT)
|
||||||
|
netdev_err(emac->ndev, "timeout waiting for command done\n");
|
||||||
|
|
||||||
|
mutex_unlock(&emac->cmd_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void icssg_config_set_speed(struct prueth_emac *emac)
|
||||||
|
{
|
||||||
|
u8 fw_speed;
|
||||||
|
|
||||||
|
switch (emac->speed) {
|
||||||
|
case SPEED_1000:
|
||||||
|
fw_speed = FW_LINK_SPEED_1G;
|
||||||
|
break;
|
||||||
|
case SPEED_100:
|
||||||
|
fw_speed = FW_LINK_SPEED_100M;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Other links speeds not supported */
|
||||||
|
netdev_err(emac->ndev, "Unsupported link speed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET);
|
||||||
|
}
|
200
drivers/net/ethernet/ti/icssg/icssg_config.h
Normal file
200
drivers/net/ethernet/ti/icssg/icssg_config.h
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
/* Texas Instruments ICSSG Ethernet driver
|
||||||
|
*
|
||||||
|
* Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __NET_TI_ICSSG_CONFIG_H
|
||||||
|
#define __NET_TI_ICSSG_CONFIG_H
|
||||||
|
|
||||||
|
struct icssg_buffer_pool_cfg {
|
||||||
|
__le32 addr;
|
||||||
|
__le32 len;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct icssg_flow_cfg {
|
||||||
|
__le16 rx_base_flow;
|
||||||
|
__le16 mgm_base_flow;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define PRUETH_PKT_TYPE_CMD 0x10
|
||||||
|
#define PRUETH_NAV_PS_DATA_SIZE 16 /* Protocol specific data size */
|
||||||
|
#define PRUETH_NAV_SW_DATA_SIZE 16 /* SW related data size */
|
||||||
|
#define PRUETH_MAX_TX_DESC 512
|
||||||
|
#define PRUETH_MAX_RX_DESC 512
|
||||||
|
#define PRUETH_MAX_RX_FLOWS 1 /* excluding default flow */
|
||||||
|
#define PRUETH_RX_FLOW_DATA 0
|
||||||
|
|
||||||
|
#define PRUETH_EMAC_BUF_POOL_SIZE SZ_8K
|
||||||
|
#define PRUETH_EMAC_POOLS_PER_SLICE 24
|
||||||
|
#define PRUETH_EMAC_BUF_POOL_START 8
|
||||||
|
#define PRUETH_NUM_BUF_POOLS 8
|
||||||
|
#define PRUETH_EMAC_RX_CTX_BUF_SIZE SZ_16K /* per slice */
|
||||||
|
#define MSMC_RAM_SIZE \
|
||||||
|
(2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \
|
||||||
|
PRUETH_EMAC_RX_CTX_BUF_SIZE * 2))
|
||||||
|
|
||||||
|
struct icssg_rxq_ctx {
|
||||||
|
__le32 start[3];
|
||||||
|
__le32 end;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* Load time Fiwmware Configuration */
|
||||||
|
|
||||||
|
#define ICSSG_FW_MGMT_CMD_HEADER 0x81
|
||||||
|
#define ICSSG_FW_MGMT_FDB_CMD_TYPE 0x03
|
||||||
|
#define ICSSG_FW_MGMT_CMD_TYPE 0x04
|
||||||
|
#define ICSSG_FW_MGMT_PKT 0x80000000
|
||||||
|
|
||||||
|
struct icssg_r30_cmd {
|
||||||
|
u32 cmd[4];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
enum icssg_port_state_cmd {
|
||||||
|
ICSSG_EMAC_PORT_DISABLE = 0,
|
||||||
|
ICSSG_EMAC_PORT_BLOCK,
|
||||||
|
ICSSG_EMAC_PORT_FORWARD,
|
||||||
|
ICSSG_EMAC_PORT_FORWARD_WO_LEARNING,
|
||||||
|
ICSSG_EMAC_PORT_ACCEPT_ALL,
|
||||||
|
ICSSG_EMAC_PORT_ACCEPT_TAGGED,
|
||||||
|
ICSSG_EMAC_PORT_ACCEPT_UNTAGGED_N_PRIO,
|
||||||
|
ICSSG_EMAC_PORT_TAS_TRIGGER,
|
||||||
|
ICSSG_EMAC_PORT_TAS_ENABLE,
|
||||||
|
ICSSG_EMAC_PORT_TAS_RESET,
|
||||||
|
ICSSG_EMAC_PORT_TAS_DISABLE,
|
||||||
|
ICSSG_EMAC_PORT_UC_FLOODING_ENABLE,
|
||||||
|
ICSSG_EMAC_PORT_UC_FLOODING_DISABLE,
|
||||||
|
ICSSG_EMAC_PORT_MC_FLOODING_ENABLE,
|
||||||
|
ICSSG_EMAC_PORT_MC_FLOODING_DISABLE,
|
||||||
|
ICSSG_EMAC_PORT_PREMPT_TX_ENABLE,
|
||||||
|
ICSSG_EMAC_PORT_PREMPT_TX_DISABLE,
|
||||||
|
ICSSG_EMAC_PORT_VLAN_AWARE_ENABLE,
|
||||||
|
ICSSG_EMAC_PORT_VLAN_AWARE_DISABLE,
|
||||||
|
ICSSG_EMAC_PORT_MAX_COMMANDS
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EMAC_NONE 0xffff0000
|
||||||
|
#define EMAC_PRU0_P_DI 0xffff0004
|
||||||
|
#define EMAC_PRU1_P_DI 0xffff0040
|
||||||
|
#define EMAC_TX_P_DI 0xffff0100
|
||||||
|
|
||||||
|
#define EMAC_PRU0_P_EN 0xfffb0000
|
||||||
|
#define EMAC_PRU1_P_EN 0xffbf0000
|
||||||
|
#define EMAC_TX_P_EN 0xfeff0000
|
||||||
|
|
||||||
|
#define EMAC_P_BLOCK 0xffff0040
|
||||||
|
#define EMAC_TX_P_BLOCK 0xffff0200
|
||||||
|
#define EMAC_P_UNBLOCK 0xffbf0000
|
||||||
|
#define EMAC_TX_P_UNBLOCK 0xfdff0000
|
||||||
|
#define EMAC_LEAN_EN 0xfff70000
|
||||||
|
#define EMAC_LEAN_DI 0xffff0008
|
||||||
|
|
||||||
|
#define EMAC_ACCEPT_ALL 0xffff0001
|
||||||
|
#define EMAC_ACCEPT_TAG 0xfffe0002
|
||||||
|
#define EMAC_ACCEPT_PRIOR 0xfffc0000
|
||||||
|
|
||||||
|
/* Config area lies in DRAM */
|
||||||
|
#define ICSSG_CONFIG_OFFSET 0x0
|
||||||
|
|
||||||
|
/* Config area lies in shared RAM */
|
||||||
|
#define ICSSG_CONFIG_OFFSET_SLICE0 0
|
||||||
|
#define ICSSG_CONFIG_OFFSET_SLICE1 0x8000
|
||||||
|
|
||||||
|
#define ICSSG_NUM_NORMAL_PDS 64
|
||||||
|
#define ICSSG_NUM_SPECIAL_PDS 16
|
||||||
|
|
||||||
|
#define ICSSG_NORMAL_PD_SIZE 8
|
||||||
|
#define ICSSG_SPECIAL_PD_SIZE 20
|
||||||
|
|
||||||
|
#define ICSSG_FLAG_MASK 0xff00ffff
|
||||||
|
|
||||||
|
struct icssg_setclock_desc {
|
||||||
|
u8 request;
|
||||||
|
u8 restore;
|
||||||
|
u8 acknowledgment;
|
||||||
|
u8 cmp_status;
|
||||||
|
u32 margin;
|
||||||
|
u32 cyclecounter0_set;
|
||||||
|
u32 cyclecounter1_set;
|
||||||
|
u32 iepcount_set;
|
||||||
|
u32 rsvd1;
|
||||||
|
u32 rsvd2;
|
||||||
|
u32 CMP0_current;
|
||||||
|
u32 iepcount_current;
|
||||||
|
u32 difference;
|
||||||
|
u32 cyclecounter0_new;
|
||||||
|
u32 cyclecounter1_new;
|
||||||
|
u32 CMP0_new;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define ICSSG_CMD_POP_SLICE0 56
|
||||||
|
#define ICSSG_CMD_POP_SLICE1 60
|
||||||
|
|
||||||
|
#define ICSSG_CMD_PUSH_SLICE0 57
|
||||||
|
#define ICSSG_CMD_PUSH_SLICE1 61
|
||||||
|
|
||||||
|
#define ICSSG_RSP_POP_SLICE0 58
|
||||||
|
#define ICSSG_RSP_POP_SLICE1 62
|
||||||
|
|
||||||
|
#define ICSSG_RSP_PUSH_SLICE0 56
|
||||||
|
#define ICSSG_RSP_PUSH_SLICE1 60
|
||||||
|
|
||||||
|
#define ICSSG_TS_POP_SLICE0 59
|
||||||
|
#define ICSSG_TS_POP_SLICE1 63
|
||||||
|
|
||||||
|
#define ICSSG_TS_PUSH_SLICE0 40
|
||||||
|
#define ICSSG_TS_PUSH_SLICE1 41
|
||||||
|
|
||||||
|
/* FDB FID_C2 flag definitions */
|
||||||
|
/* Indicates host port membership.*/
|
||||||
|
#define ICSSG_FDB_ENTRY_P0_MEMBERSHIP BIT(0)
|
||||||
|
/* Indicates that MAC ID is connected to physical port 1 */
|
||||||
|
#define ICSSG_FDB_ENTRY_P1_MEMBERSHIP BIT(1)
|
||||||
|
/* Indicates that MAC ID is connected to physical port 2 */
|
||||||
|
#define ICSSG_FDB_ENTRY_P2_MEMBERSHIP BIT(2)
|
||||||
|
/* Ageable bit is set for learned entries and cleared for static entries */
|
||||||
|
#define ICSSG_FDB_ENTRY_AGEABLE BIT(3)
|
||||||
|
/* If set for DA then packet is determined to be a special packet */
|
||||||
|
#define ICSSG_FDB_ENTRY_BLOCK BIT(4)
|
||||||
|
/* If set for DA then the SA from the packet is not learned */
|
||||||
|
#define ICSSG_FDB_ENTRY_SECURE BIT(5)
|
||||||
|
/* If set, it means packet has been seen recently with source address + FID
|
||||||
|
* matching MAC address/FID of entry
|
||||||
|
*/
|
||||||
|
#define ICSSG_FDB_ENTRY_TOUCHED BIT(6)
|
||||||
|
/* Set if entry is valid */
|
||||||
|
#define ICSSG_FDB_ENTRY_VALID BIT(7)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct prueth_vlan_tbl - VLAN table entries struct in ICSSG SMEM
|
||||||
|
* @fid_c1: membership and forwarding rules flag to this table. See
|
||||||
|
* above to defines for bit definitions
|
||||||
|
* @fid: FDB index for this VID (there is 1-1 mapping b/w VID and FID)
|
||||||
|
*/
|
||||||
|
struct prueth_vlan_tbl {
|
||||||
|
u8 fid_c1;
|
||||||
|
u8 fid;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct prueth_fdb_slot - Result of FDB slot lookup
|
||||||
|
* @mac: MAC address
|
||||||
|
* @fid: fid to be associated with MAC
|
||||||
|
* @fid_c2: FID_C2 entry for this MAC
|
||||||
|
*/
|
||||||
|
struct prueth_fdb_slot {
|
||||||
|
u8 mac[ETH_ALEN];
|
||||||
|
u8 fid;
|
||||||
|
u8 fid_c2;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
enum icssg_ietfpe_verify_states {
|
||||||
|
ICSSG_IETFPE_STATE_UNKNOWN = 0,
|
||||||
|
ICSSG_IETFPE_STATE_INITIAL,
|
||||||
|
ICSSG_IETFPE_STATE_VERIFYING,
|
||||||
|
ICSSG_IETFPE_STATE_SUCCEEDED,
|
||||||
|
ICSSG_IETFPE_STATE_FAILED,
|
||||||
|
ICSSG_IETFPE_STATE_DISABLED
|
||||||
|
};
|
||||||
|
#endif /* __NET_TI_ICSSG_CONFIG_H */
|
@ -194,4 +194,19 @@ static inline int prueth_emac_slice(struct prueth_emac *emac)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Classifier helpers */
|
||||||
|
void icssg_class_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac);
|
||||||
|
void icssg_class_set_host_mac_addr(struct regmap *miig_rt, const u8 *mac);
|
||||||
|
void icssg_class_disable(struct regmap *miig_rt, int slice);
|
||||||
|
void icssg_class_default(struct regmap *miig_rt, int slice, bool allmulti);
|
||||||
|
void icssg_ft1_set_mac_addr(struct regmap *miig_rt, int slice, u8 *mac_addr);
|
||||||
|
|
||||||
|
/* config helpers */
|
||||||
|
void icssg_config_ipg(struct prueth_emac *emac);
|
||||||
|
int icssg_config(struct prueth *prueth, struct prueth_emac *emac,
|
||||||
|
int slice);
|
||||||
|
int emac_set_port_state(struct prueth_emac *emac,
|
||||||
|
enum icssg_port_state_cmd state);
|
||||||
|
void icssg_config_set_speed(struct prueth_emac *emac);
|
||||||
|
|
||||||
#endif /* __NET_TI_ICSSG_PRUETH_H */
|
#endif /* __NET_TI_ICSSG_PRUETH_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user