On 3/27/24 10:58 AM, MD Danish Anwar wrote:
> 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 <danishan...@ti.com>
> ---
>  drivers/net/ti/icss_mii_rt.h      | 192 ++++++++++++++
>  drivers/net/ti/icssg_classifier.c | 376 +++++++++++++++++++++++++++
>  drivers/net/ti/icssg_config.c     | 406 ++++++++++++++++++++++++++++++
>  drivers/net/ti/icssg_config.h     | 177 +++++++++++++
>  drivers/net/ti/icssg_prueth.h     |  83 ++++++
>  5 files changed, 1234 insertions(+)
>  create mode 100644 drivers/net/ti/icss_mii_rt.h
>  create mode 100644 drivers/net/ti/icssg_classifier.c
>  create mode 100644 drivers/net/ti/icssg_config.c
>  create mode 100644 drivers/net/ti/icssg_config.h
>  create mode 100644 drivers/net/ti/icssg_prueth.h
> 
> diff --git a/drivers/net/ti/icss_mii_rt.h b/drivers/net/ti/icss_mii_rt.h
> new file mode 100644
> index 0000000000..4a78394701
> --- /dev/null
> +++ b/drivers/net/ti/icss_mii_rt.h
> @@ -0,0 +1,192 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +/* PRU-ICSS MII_RT register definitions
> + *
> + * Copyright (C) 2015-2024 Texas Instruments Incorporated - http://www.ti.com

In this and other patches, please fix the URL
s/http/https


> + */
> +
> +#ifndef __NET_PRUSS_MII_RT_H__
> +#define __NET_PRUSS_MII_RT_H__
> +
> +#include <regmap.h>
> +
> +/* PRUSS_MII_RT Registers */
> +#define PRUSS_MII_RT_RXCFG0          0x0
> +#define PRUSS_MII_RT_RXCFG1          0x4
> +#define PRUSS_MII_RT_TXCFG0          0x10
> +#define PRUSS_MII_RT_TXCFG1          0x14
> +#define PRUSS_MII_RT_TX_CRC0         0x20
> +#define PRUSS_MII_RT_TX_CRC1         0x24
> +#define PRUSS_MII_RT_TX_IPG0         0x30
> +#define PRUSS_MII_RT_TX_IPG1         0x34
> +#define PRUSS_MII_RT_PRS0            0x38
> +#define PRUSS_MII_RT_PRS1            0x3c
> +#define PRUSS_MII_RT_RX_FRMS0                0x40
> +#define PRUSS_MII_RT_RX_FRMS1                0x44
> +#define PRUSS_MII_RT_RX_PCNT0                0x48
> +#define PRUSS_MII_RT_RX_PCNT1                0x4c
> +#define PRUSS_MII_RT_RX_ERR0         0x50
> +#define PRUSS_MII_RT_RX_ERR1         0x54
> +
> +/* PRUSS_MII_RT_RXCFG0/1 bits */
> +#define PRUSS_MII_RT_RXCFG_RX_ENABLE         BIT(0)
> +#define PRUSS_MII_RT_RXCFG_RX_DATA_RDY_MODE_DIS      BIT(1)
> +#define PRUSS_MII_RT_RXCFG_RX_CUT_PREAMBLE   BIT(2)
> +#define PRUSS_MII_RT_RXCFG_RX_MUX_SEL                BIT(3)
> +#define PRUSS_MII_RT_RXCFG_RX_L2_EN          BIT(4)
> +#define PRUSS_MII_RT_RXCFG_RX_BYTE_SWAP              BIT(5)
> +#define PRUSS_MII_RT_RXCFG_RX_AUTO_FWD_PRE   BIT(6)
> +#define PRUSS_MII_RT_RXCFG_RX_L2_EOF_SCLR_DIS        BIT(9)
> +
> +/* PRUSS_MII_RT_TXCFG0/1 bits */
> +#define PRUSS_MII_RT_TXCFG_TX_ENABLE         BIT(0)
> +#define PRUSS_MII_RT_TXCFG_TX_AUTO_PREAMBLE  BIT(1)
> +#define PRUSS_MII_RT_TXCFG_TX_EN_MODE                BIT(2)
> +#define PRUSS_MII_RT_TXCFG_TX_BYTE_SWAP              BIT(3)
> +#define PRUSS_MII_RT_TXCFG_TX_MUX_SEL                BIT(8)
> +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_SEQUENCE      BIT(9)
> +#define PRUSS_MII_RT_TXCFG_PRE_TX_AUTO_ESC_ERR       BIT(10)
> +#define PRUSS_MII_RT_TXCFG_TX_32_MODE_EN     BIT(11)
> +#define PRUSS_MII_RT_TXCFG_TX_IPG_WIRE_CLK_EN        BIT(12) /* SR2.0 
> onwards */
> +
> +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_SHIFT      16
> +#define PRUSS_MII_RT_TXCFG_TX_START_DELAY_MASK       GENMASK(25, 16)
> +
> +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_SHIFT        28
> +#define PRUSS_MII_RT_TXCFG_TX_CLK_DELAY_MASK GENMASK(30, 28)
> +
> +/* PRUSS_MII_RT_TX_IPG0/1 bits */
> +#define PRUSS_MII_RT_TX_IPG_IPG_SHIFT        0
> +#define PRUSS_MII_RT_TX_IPG_IPG_MASK GENMASK(9, 0)
> +
> +/* PRUSS_MII_RT_PRS0/1 bits */
> +#define PRUSS_MII_RT_PRS_COL BIT(0)
> +#define PRUSS_MII_RT_PRS_CRS BIT(1)
> +
> +/* PRUSS_MII_RT_RX_FRMS0/1 bits */
> +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_SHIFT   0
> +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM_MASK    GENMASK(15, 0)
> +
> +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_SHIFT   16
> +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_MASK    GENMASK(31, 16)
> +
> +/* Min/Max in MII_RT_RX_FRMS */
> +/* For EMAC and Switch */
> +#define PRUSS_MII_RT_RX_FRMS_MAX     (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)
> +#define PRUSS_MII_RT_RX_FRMS_MIN_FRM (64)
> +
> +/* for HSR and PRP */
> +#define PRUSS_MII_RT_RX_FRMS_MAX_FRM_LRE     (PRUSS_MII_RT_RX_FRMS_MAX + \
> +                                              ICSS_LRE_TAG_RCT_SIZE)
> +/* PRUSS_MII_RT_RX_PCNT0/1 bits */
> +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_SHIFT  0
> +#define PRUSS_MII_RT_RX_PCNT_MIN_PCNT_MASK   GENMASK(3, 0)
> +
> +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_SHIFT  4
> +#define PRUSS_MII_RT_RX_PCNT_MAX_PCNT_MASK   GENMASK(7, 4)
> +
> +/* PRUSS_MII_RT_RX_ERR0/1 bits */
> +#define PRUSS_MII_RT_RX_ERR_MIN_PCNT_ERR     BIT(0)
> +#define PRUSS_MII_RT_RX_ERR_MAX_PCNT_ERR     BIT(1)
> +#define PRUSS_MII_RT_RX_ERR_MIN_FRM_ERR              BIT(2)
> +#define PRUSS_MII_RT_RX_ERR_MAX_FRM_ERR              BIT(3)
> +
> +#define ICSSG_CFG_OFFSET     0
> +#define RGMII_CFG_OFFSET     4
> +
> +/* Constant to choose between MII0 and MII1 */
> +#define ICSS_MII0    0
> +#define ICSS_MII1    1
> +
> +/* ICSSG_CFG Register bits */
> +#define ICSSG_CFG_SGMII_MODE BIT(16)
> +#define ICSSG_CFG_TX_PRU_EN  BIT(11)
> +#define ICSSG_CFG_RX_SFD_TX_SOF_EN   BIT(10)
> +#define ICSSG_CFG_RTU_PRU_PSI_SHARE_EN       BIT(9)
> +#define ICSSG_CFG_IEP1_TX_EN BIT(8)
> +#define ICSSG_CFG_MII1_MODE  GENMASK(6, 5)
> +#define ICSSG_CFG_MII1_MODE_SHIFT    5
> +#define ICSSG_CFG_MII0_MODE  GENMASK(4, 3)
> +#define ICSSG_CFG_MII0_MODE_SHIFT    3
> +#define ICSSG_CFG_RX_L2_G_EN BIT(2)
> +#define ICSSG_CFG_TX_L2_EN   BIT(1)
> +#define ICSSG_CFG_TX_L1_EN   BIT(0)
> +
> +enum mii_mode { MII_MODE_MII = 0, MII_MODE_RGMII, MII_MODE_SGMII };
> +
> +/* RGMII CFG Register bits */
> +#define RGMII_CFG_INBAND_EN_MII0     BIT(16)
> +#define RGMII_CFG_GIG_EN_MII0        BIT(17)
> +#define RGMII_CFG_INBAND_EN_MII1     BIT(20)
> +#define RGMII_CFG_GIG_EN_MII1        BIT(21)
> +#define RGMII_CFG_FULL_DUPLEX_MII0   BIT(18)
> +#define RGMII_CFG_FULL_DUPLEX_MII1   BIT(22)
> +#define RGMII_CFG_SPEED_MII0 GENMASK(2, 1)
> +#define RGMII_CFG_SPEED_MII1 GENMASK(6, 5)
> +#define RGMII_CFG_SPEED_MII0_SHIFT   1
> +#define RGMII_CFG_SPEED_MII1_SHIFT   5
> +#define RGMII_CFG_FULLDUPLEX_MII0    BIT(3)
> +#define RGMII_CFG_FULLDUPLEX_MII1    BIT(7)
> +#define RGMII_CFG_FULLDUPLEX_MII0_SHIFT      3
> +#define RGMII_CFG_FULLDUPLEX_MII1_SHIFT      7
> +#define RGMII_CFG_SPEED_10M  0
> +#define RGMII_CFG_SPEED_100M 1
> +#define RGMII_CFG_SPEED_1G   2
> +
> +static inline void icssg_mii_update_ipg(struct regmap *mii_rt, int mii, u32 
> ipg)
> +{
> +     u32 val;
> +
> +     if (mii == ICSS_MII0) {
> +             regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, ipg);
> +     } else {
> +             /* Errata workaround: IEP1 is not read by h/w unless IEP0 is 
> written */
> +             regmap_read(mii_rt, PRUSS_MII_RT_TX_IPG0, &val);
> +             regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG1, ipg);
> +             regmap_write(mii_rt, PRUSS_MII_RT_TX_IPG0, val);
> +     }
> +}
> +
> +static inline void icssg_update_rgmii_cfg(struct regmap *miig_rt, int speed,
> +                                       bool full_duplex, int slice, struct 
> prueth_priv *priv)
> +{
> +     u32 gig_en_mask, gig_val = 0, full_duplex_mask, full_duplex_val = 0;
> +     u32 inband_en_mask, inband_val = 0;
> +
> +     gig_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_GIG_EN_MII0 :
> +                                     RGMII_CFG_GIG_EN_MII1;
> +     if (speed == SPEED_1000)
> +             gig_val = gig_en_mask;
> +     regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, gig_en_mask, gig_val);
> +
> +     inband_en_mask = (slice == ICSS_MII0) ? RGMII_CFG_INBAND_EN_MII0 :
> +                                     RGMII_CFG_INBAND_EN_MII1;
> +     if (speed == SPEED_10 && phy_interface_is_rgmii(priv->phydev))
> +             inband_val = inband_en_mask;
> +     regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, inband_en_mask, 
> inband_val);
> +
> +     full_duplex_mask = (slice == ICSS_MII0) ? RGMII_CFG_FULL_DUPLEX_MII0 :
> +                                        RGMII_CFG_FULL_DUPLEX_MII1;
> +     if (full_duplex)
> +             full_duplex_val = full_duplex_mask;
> +     regmap_update_bits(miig_rt, RGMII_CFG_OFFSET, full_duplex_mask,
> +                        full_duplex_val);
> +}
> +
> +static inline void icssg_miig_set_interface_mode(struct regmap *miig_rt, int 
> mii, int phy_if)
> +{
> +     u32 val, mask, shift;
> +
> +     mask = mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE : ICSSG_CFG_MII1_MODE;
> +     shift =  mii == ICSS_MII0 ? ICSSG_CFG_MII0_MODE_SHIFT : 
> ICSSG_CFG_MII1_MODE_SHIFT;
> +
> +     val = MII_MODE_RGMII;
> +     if (phy_if == PHY_INTERFACE_MODE_MII)
> +             val = MII_MODE_MII;
> +
> +     val <<= shift;
> +     regmap_update_bits(miig_rt, ICSSG_CFG_OFFSET, mask, val);
> +     regmap_read(miig_rt, ICSSG_CFG_OFFSET, &val);
> +}
> +
> +#endif /* __NET_PRUSS_MII_RT_H__ */
> diff --git a/drivers/net/ti/icssg_classifier.c 
> b/drivers/net/ti/icssg_classifier.c
> new file mode 100644
> index 0000000000..df7383f1fa
> --- /dev/null
> +++ b/drivers/net/ti/icssg_classifier.c
> @@ -0,0 +1,376 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Texas Instruments ICSSG Ethernet Driver
> + *
> + * Copyright (C) 2018-2024 Texas Instruments Incorporated - 
> http://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);
> +}
> diff --git a/drivers/net/ti/icssg_config.c b/drivers/net/ti/icssg_config.c
> new file mode 100644
> index 0000000000..b0ba870189
> --- /dev/null
> +++ b/drivers/net/ti/icssg_config.c
> @@ -0,0 +1,406 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* ICSSG Ethernet driver
> + *
> + * Copyright (C) 2018-2024 Texas Instruments Incorporated - http://www.ti.com
> + */
> +
> +#include <phy.h>
> +#include "icssg_prueth.h"
> +#include "icssg_switch_map.h"
> +#include "icss_mii_rt.h"
> +#include <dm/device_compat.h>
> +
> +/* TX IPG Values to be set for 100M and 1G link speeds.  These values are
> + * in ocp_clk cycles. So need change if ocp_clk is changed for a specific
> + * h/w design.
> + */
> +
> +/* SR2.0 IPG is in rgmii_clk (125MHz) clock cycles + 1 */
> +#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 | /* SR2.0 only */ \
> +                              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 {
> +     int queue;
> +     u32 pd_addr_start;
> +     u32 flags;
> +     bool special;
> +};
> +
> +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_priv *priv, int slice)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     struct regmap *mii_rt = prueth->mii_rt;
> +     u32 txcfg_reg, pcnt_reg;
> +     u32 txcfg;
> +
> +     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;
> +
> +     txcfg = MII_TXCFG_DEFAULT;
> +
> +     if (prueth->phy_interface == PHY_INTERFACE_MODE_MII && slice == 
> ICSS_MII0)
> +             txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
> +     else if (prueth->phy_interface != PHY_INTERFACE_MODE_MII && slice == 
> ICSS_MII1)
> +             txcfg |= PRUSS_MII_RT_TXCFG_TX_MUX_SEL;
> +
> +     regmap_write(mii_rt, txcfg_reg, txcfg);
> +     regmap_write(mii_rt, pcnt_reg, 0x1);
> +}
> +
> +static void icssg_miig_queues_init(struct prueth_priv *priv, int slice)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     void __iomem *smem = (void __iomem *)prueth->shram.pa;
> +     struct regmap *miig_rt = prueth->miig_rt;
> +     int queue = 0, i, j;
> +     u8 pd[ICSSG_SPECIAL_PD_SIZE];
> +     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++) {
> +             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] &= cpu_to_le32(ICSSG_FLAG_MASK);
> +                     pdword[0] |= cpu_to_le32(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_priv *priv, int speed, int mii)
> +{
> +     struct prueth *prueth = priv->prueth;
> +
> +     switch (speed) {
> +     case SPEED_1000:
> +             icssg_mii_update_ipg(prueth->mii_rt, mii, MII_RT_TX_IPG_1G);
> +             break;
> +     case SPEED_100:
> +             icssg_mii_update_ipg(prueth->mii_rt, mii, MII_RT_TX_IPG_100M);
> +             break;
> +     default:
> +             /* Other links speeds not supported */
> +             pr_err("Unsupported link speed\n");
> +             return;
> +     }
> +}
> +
> +static void emac_r30_cmd_init(struct prueth_priv *priv)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     struct icssg_r30_cmd *p;
> +     int i;
> +
> +     p = (struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + 
> MGR_R30_CMD_OFFSET);
> +
> +     for (i = 0; i < 4; i++)
> +             writel(EMAC_NONE, &p->cmd[i]);
> +}
> +
> +static int emac_r30_is_done(struct prueth_priv *priv)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     const struct icssg_r30_cmd *p;
> +     int i;
> +     u32 cmd;
> +
> +     p = (const struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + 
> 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_priv *priv)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     struct icssg_buffer_pool_cfg *bpool_cfg;
> +     struct icssg_rxq_ctx *rxq_ctx;
> +     int slice = priv->port_id;
> +     u32 addr;
> +     int i;
> +
> +     /* Layout to have 64KB aligned buffer pool
> +      * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1|
> +      */
> +
> +     addr = lower_32_bits(prueth->sram_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 = (struct icssg_buffer_pool_cfg 
> *)(prueth->dram[priv->port_id].pa + BUFFER_POOL_0_ADDR_OFFSET);
> +     /* workaround for f/w bug. bpool 0 needs to be initilalized */
> +     bpool_cfg[0].addr = cpu_to_le32(addr);
> +     bpool_cfg[0].len = 0;
> +
> +     for (i = PRUETH_EMAC_BUF_POOL_START;
> +          i < (PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS);
> +          i++) {
> +             bpool_cfg[i].addr = cpu_to_le32(addr);
> +             bpool_cfg[i].len = cpu_to_le32(PRUETH_EMAC_BUF_POOL_SIZE);
> +             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;
> +
> +     rxq_ctx = (struct icssg_rxq_ctx *)(prueth->dram[priv->port_id].pa + 
> HOST_RX_Q_PRE_CONTEXT_OFFSET);
> +
> +     for (i = 0; i < 3; i++)
> +             rxq_ctx->start[i] = cpu_to_le32(addr);
> +
> +     addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
> +     rxq_ctx->end = cpu_to_le32(addr);
> +
> +     /* Express RX buffer queue */
> +     rxq_ctx = (struct icssg_rxq_ctx *)(prueth->dram[priv->port_id].pa + 
> HOST_RX_Q_EXP_CONTEXT_OFFSET);
> +     for (i = 0; i < 3; i++)
> +             rxq_ctx->start[i] = cpu_to_le32(addr);
> +
> +     addr += PRUETH_EMAC_RX_CTX_BUF_SIZE;
> +     rxq_ctx->end = cpu_to_le32(addr);
> +
> +     return 0;
> +}
> +
> +static void icssg_init_emac_mode(struct prueth *prueth)
> +{
> +     u8 mac[6] = { 0 };
> +
> +     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_priv *priv)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     void *config = (void *)(prueth->dram[priv->port_id].pa + 
> ICSSG_CONFIG_OFFSET);
> +     u8 *cfg_byte_ptr = config;
> +     struct icssg_flow_cfg *flow_cfg;
> +     u32 mask;
> +     int ret;
> +
> +     int slice = priv->port_id;
> +
> +     icssg_init_emac_mode(prueth);
> +
> +     memset_io(config, 0, TAS_GATE_MASK_LIST0);
> +     icssg_miig_queues_init(priv, slice);
> +
> +     prueth->speed = SPEED_1000;
> +     prueth->duplex = DUPLEX_FULL;
> +     if (!phy_interface_is_rgmii(priv->phydev)) {
> +             prueth->speed = SPEED_100;
> +             prueth->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, ICSS_MII0, 
> prueth->phy_interface);
> +     icssg_miig_set_interface_mode(prueth->miig_rt, ICSS_MII1, 
> prueth->phy_interface);
> +     icssg_config_mii_init(priv, slice);
> +
> +     icssg_config_ipg(priv, SPEED_1000, slice);
> +     icssg_update_rgmii_cfg(prueth->miig_rt, SPEED_1000, true, slice, priv);
> +
> +     /* set GPI mode */
> +     pruss_cfg_gpimode(prueth->pruss, slice, PRUSS_GPI_MODE_MII);
> +
> +     /* enable XFR shift for PRU and RTU */
> +     mask = PRUSS_SPP_XFER_SHIFT_EN | PRUSS_SPP_RTU_XFR_SHIFT_EN;
> +     pruss_cfg_update(prueth->pruss, PRUSS_CFG_SPP, mask, mask);
> +
> +     flow_cfg = config + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
> +     flow_cfg->rx_base_flow = prueth->dma_rx.id;
> +     flow_cfg->mgm_base_flow = 0;
> +     *(cfg_byte_ptr + SPL_PKT_DEFAULT_PRIORITY) = 0;
> +     *(cfg_byte_ptr + QUEUE_NUM_UNTAGGED) = 0x0;
> +
> +     ret = prueth_emac_buffer_setup(priv);
> +
> +     if (ret)
> +             return ret;
> +
> +     emac_r30_cmd_init(priv);
> +     return 0;
> +}
> +
> +/* commands to program ICSSG R30 registers */
> +static struct icssg_r30_cmd emac_r32_bitmask[] = {
> +     {{0xffff0004, 0xffff0100, 0xffff0004, EMAC_NONE}},      /* 
> EMAC_PORT_DISABLE */
> +     {{0xfffb0040, 0xfeff0200, 0xfeff0200, EMAC_NONE}},      /* 
> EMAC_PORT_BLOCK */
> +     {{0xffbb0000, 0xfcff0000, 0xdcfb0000, 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*/
> +};
> +
> +int emac_set_port_state(struct prueth_priv *priv,
> +                     enum icssg_port_state_cmd cmd)
> +{
> +     struct prueth *prueth = priv->prueth;
> +     struct icssg_r30_cmd *p;
> +     int ret = -ETIMEDOUT;
> +     int timeout = 10;
> +     int i;
> +
> +     p = (struct icssg_r30_cmd *)(prueth->dram[priv->port_id].pa + 
> MGR_R30_CMD_OFFSET);
> +
> +     if (cmd >= ICSSG_EMAC_PORT_MAX_COMMANDS) {
> +             dev_err(prueth->dev, "invalid port command\n");
> +             return -EINVAL;
> +     }
> +
> +     for (i = 0; i < 4; i++)
> +             writel(emac_r32_bitmask[cmd].cmd[i], &p->cmd[i]);
> +
> +     /* wait for done */
> +     while (timeout) {
> +             if (emac_r30_is_done(priv)) {
> +                     ret = 0;
> +                     break;
> +             }
> +
> +             udelay(2000);
> +             timeout--;
> +     }
> +
> +     if (ret == -ETIMEDOUT)
> +             dev_err(prueth->dev, "timeout waiting for command done\n");
> +
> +     return ret;
> +}
> diff --git a/drivers/net/ti/icssg_config.h b/drivers/net/ti/icssg_config.h
> new file mode 100644
> index 0000000000..412dbf51c7
> --- /dev/null
> +++ b/drivers/net/ti/icssg_config.h
> @@ -0,0 +1,177 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Texas Instruments ICSSG Ethernet driver
> + *
> + * Copyright (C) 2018-2024 Texas Instruments Incorporated - 
> http://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;
> +
> +/* Config area lies in shared RAM */
> +#define ICSSG_CONFIG_OFFSET_SLICE0   0
> +#define ICSSG_CONFIG_OFFSET_SLICE1   0x8000
> +
> +/* pstate speed/duplex command to set speed and duplex settings
> + * in firmware.
> + * Command format : 0x8102ssPN. ss - sequence number: currently not
> + * used by driver, P - port number: For switch, N - Speed/Duplex state
> + * - Possible values of N:
> + * 0x0 - 10Mbps/Half duplex ;
> + * 0x8 - 10Mbps/Full duplex ;
> + * 0x2 - 100Mbps/Half duplex;
> + * 0xa - 100Mbps/Full duplex;
> + * 0xc - 1Gbps/Full duplex;
> + * NOTE: The above are same as bits [3..1](slice 0) or bits [8..6](slice 1) 
> of
> + * RGMII CFG register. So suggested to read the register to populate the 
> command
> + * bits.
> + */
> +#define ICSSG_PSTATE_SPEED_DUPLEX_CMD        0x81020000
> +#define ICSSG_PSTATE_FULL_DUPLEX     BIT(3)
> +#define ICSSG_PSTATE_SPEED_100               BIT(1)
> +#define ICSSG_PSTATE_SPEED_1000              BIT(2)
> +
> +/* Flow IDs used in config structure to firmware. Should match with
> + * flow_id in struct dma for rx channels.
> + */
> +#define ICSSG_RX_CHAN_FLOW_ID                0 /* flow id for host port */
> +#define ICSSG_RX_MGM_CHAN_FLOW_ID    1 /* flow id for command response */
> +
> +/* Used to notify the FW of the current link speed */
> +#define PORT_LINK_SPEED_OFFSET                          0x00A8
> +
> +#define FW_LINK_SPEED_1G                           (0x00)
> +#define FW_LINK_SPEED_100M                         (0x01)
> +#define FW_LINK_SPEED_10M                          (0x02)
> +#define FW_LINK_SPEED_HD                           (0x80)
> +
> +#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_RX_FLOWS  1       /* excluding default flow */
> +#define PRUETH_RX_FLOW_DATA  0       /* FIXME: f/w bug to change to highest 
> priority flow */
> +
> +#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))
> +
> +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_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
> +
> +#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
> +
> +#endif /* __NET_TI_ICSSG_CONFIG_H */
> diff --git a/drivers/net/ti/icssg_prueth.h b/drivers/net/ti/icssg_prueth.h
> new file mode 100644
> index 0000000000..a7627a77d8
> --- /dev/null
> +++ b/drivers/net/ti/icssg_prueth.h
> @@ -0,0 +1,83 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/* Texas Instruments K3 AM65 Ethernet Switch SubSystem Driver
> + *
> + * Copyright (C) 2018-2024 Texas Instruments Incorporated - 
> http://www.ti.com/
> + *
> + */
> +
> +#ifndef __NET_TI_ICSSG_PRUETH_H
> +#define __NET_TI_ICSSG_PRUETH_H
> +
> +#include <asm/io.h>
> +#include <clk.h>
> +#include <dm/lists.h>
> +#include <dm/ofnode.h>
> +#include <dm/device.h>
> +#include <dma-uclass.h>
> +#include <regmap.h>
> +#include <linux/sizes.h>
> +#include <linux/pruss_driver.h>
> +#include "icssg_config.h"
> +#include "icssg_switch_map.h"
> +
> +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, 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);
> +
> +enum prueth_mac {
> +     PRUETH_MAC0 = 0,
> +     PRUETH_MAC1,
> +     PRUETH_NUM_MACS,
> +};
> +
> +enum prueth_port {
> +     PRUETH_PORT_HOST = 0,   /* host side port */
> +     PRUETH_PORT_MII0,       /* physical port MII 0 */
> +     PRUETH_PORT_MII1,       /* physical port MII 1 */
> +};
> +
> +struct prueth {
> +     struct udevice          *dev;
> +     struct udevice          *pruss;
> +     struct regmap           *miig_rt;
> +     struct regmap           *mii_rt;
> +     fdt_addr_t              mdio_base;
> +     struct pruss_mem_region shram;
> +     struct pruss_mem_region dram[PRUETH_NUM_MACS];
> +     phys_addr_t             tmaddr;
> +     struct mii_dev          *bus;
> +     u32                     sram_pa;
> +     ofnode                  eth_node[PRUETH_NUM_MACS];
> +     u32                     mdio_freq;
> +     int                     phy_interface;
> +     struct                  clk mdiofck;
> +     struct dma              dma_tx;
> +     struct dma              dma_rx;
> +     struct dma              dma_rx_mgm;
> +     u32                     rx_next;
> +     u32                     rx_pend;
> +     int                     slice;
> +     bool                    mdio_manual_mode;
> +     int                     speed;
> +     int                     duplex;
> +};
> +
> +struct prueth_priv {
> +     struct udevice          *dev;
> +     struct prueth           *prueth;
> +     u32                     port_id;
> +     struct phy_device       *phydev;
> +     bool                    has_phy;
> +     ofnode                  phy_node;
> +     u32                     phy_addr;
> +     int                     phy_interface;
> +};
> +
> +/* config helpers */
> +void icssg_config_ipg(struct prueth_priv *priv, int speed, int mii);
> +int icssg_config(struct prueth_priv *priv);
> +int emac_set_port_state(struct prueth_priv *priv, enum icssg_port_state_cmd 
> cmd);
> +
> +#endif /* __NET_TI_ICSSG_PRUETH_H */

-- 
Regards,
Ravi

Reply via email to