/*
 *  Copyright (c) Texas Instruments Incorporated 2020
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 *  \file ti_enet_soc.c
 *
 *  \brief This file contains enet soc config related functionality.
 */

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <drivers/sciclient.h>
#include <enet.h>
#include <enet_cfg.h>
#include <priv/mod/cpsw_ale_priv.h>
#include <priv/mod/cpsw_cpts_priv.h>
#include <priv/mod/cpsw_hostport_priv.h>
#include <priv/mod/cpsw_macport_priv.h>
#include <priv/mod/cpsw_stats_priv.h>
#include <priv/mod/mdio_priv.h>
#include <priv/mod/cpsw_clks.h>
#include <priv/core/enet_rm_priv.h>
#include <include/core/enet_utils.h>
#include <include/core/enet_osal.h>
#include <include/core/enet_soc.h>
#include <include/core/enet_per.h>
#include <include/per/cpsw.h>
#include <src/dma/udma/enet_udma_priv.h>
#include <soc/k3/cpsw_soc.h>
#include <priv/per/cpsw_priv.h>
#include <utils/include/enet_appsoc.h>
#include <drivers/hw_include/cslr_soc.h>
#include <networking/enet/utils/include/enet_apputils.h>
#include "ti_enet_config.h"


/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */
/* ========================================================================== */
/*                         Structure Declarations                             */
/* ========================================================================== */
/* ========================================================================== */
/*                          Function Declarations                             */
/* ========================================================================== */
static uint32_t EnetSoc_getMcuEnetControl(Enet_MacPort macPort,
                                          uint32_t *modeSel);
/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

/* -------------------------------- CPSW 3G --------------------------------- */

const CpswSoc_Cfg gEnetSoc_cpsw3gSocCfg =
{
    /* As per the clocking specification the mcu_sysclk0 is 1000MHz with
     * fixed /3 divider. */
    .cppiClkFreqHz = 320000000LLU,
    .dmscDevId = TISCI_DEV_CPSW0,
    .intrs =
    {
        {   /* EVNT_PEND - Event pending interrupt (CPTS) */
            .intrId     = CPSW_INTR_EVNT_PEND,
            .coreIntNum = CSLR_R5FSS0_CORE0_INTR_CPSW0_EVNT_PEND_0,
            .srcIdx     = ENET_SOC_DIRECT_INTR_SRCIDX_INVALID,
        },
        {   /* STATS_PEND - Statistics pending interrupt */
            .intrId     = CPSW_INTR_STATS_PEND0,
            .coreIntNum = CSLR_R5FSS0_CORE0_INTR_CPSW0_STAT_PEND_0,
            .srcIdx     = ENET_SOC_DIRECT_INTR_SRCIDX_INVALID,
        },
        {   /* MDIO_PEND - MDIO interrupt */
            .intrId     = CPSW_INTR_MDIO_PEND,
            .coreIntNum = CSLR_R5FSS0_CORE0_INTR_CPSW0_MDIO_PEND_0,
            .srcIdx     = ENET_SOC_DIRECT_INTR_SRCIDX_INVALID,
        },
    },
    .clocks =
    {
        .cppiClkId        = TISCI_DEV_CPSW0_CPPI_CLK_CLK,
        .rgmii250MHzClkId = TISCI_DEV_CPSW0_RGMII_MHZ_250_CLK,
        .rgmii50MHzClkId  = TISCI_DEV_CPSW0_RGMII_MHZ_50_CLK,
        .rgmii5MHzClkId   = TISCI_DEV_CPSW0_RGMII_MHZ_5_CLK,
    },
    .txChPeerThreadId = CSL_PSILCFG_DMSS_CPSW2_PSILD_THREAD_OFFSET,
    .rxChPeerThreadId = CSL_PSILCFG_DMSS_CPSW2_PSILS_THREAD_OFFSET,
    .txChCount        = CSL_PSILCFG_DMSS_CPSW2_PSILD_THREAD_CNT,

    /* Note- Though CPSW supports 64 distinct flow Ids, there are only
     * 8 policer/classifier so can effectively assign only 8 flow ids in CPSW3G */
    .rxFlowCount     = 8U,
};

/* CPSW_3G MAC port template */
#define ENET_SOC_CPSW3G_MACPORT(n)                                    \
{                                                                     \
    .enetMod =                                                        \
    {                                                                 \
        .name       = "cpsw3G.macport" #n,                            \
        .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_NU_OFFSET),         \
        .physAddr2  = (CSL_CPSW0_NUSS_BASE + CPSW_SGMII0_OFFSET(0U)), \
        .features   = (ENET_FEAT_BASE |                               \
                       CPSW_MACPORT_FEATURE_EST |                     \
                       CPSW_MACPORT_FEATURE_SGMII |                   \
                       CPSW_MACPORT_FEATURE_INTERVLAN),               \
        .errata     = ENET_ERRATA_NONE,                               \
        .open       = &CpswMacPort_open,                              \
        .rejoin     = &CpswMacPort_rejoin,                            \
        .ioctl      = &CpswMacPort_ioctl,                             \
        .close      = &CpswMacPort_close,                             \
    },                                                                \
    .macPort = ENET_MAC_PORT_ ## n,                                   \
}

/* CPSW_3G MAC ports */
CpswMacPort_Obj gEnetSoc_cpsw3gMacObj[] =
{
    ENET_SOC_CPSW3G_MACPORT(1),
    ENET_SOC_CPSW3G_MACPORT(2),
};


/* CPSW 3G Peripheral */
Cpsw_Obj gEnetSoc_cpsw3g =
{
    .enetPer =
    {
        .name         = "cpsw3g",
        .enetType     = ENET_CPSW_3G,
        .instId       = 0U,
        .magic        = ENET_NO_MAGIC,
        .physAddr     = (CSL_CPSW0_NUSS_BASE + CPSW_NU_OFFSET),
        .physAddr2    = (CSL_CPSW0_NUSS_BASE + CPSW_NUSS_OFFSET),
        .features     = (ENET_FEAT_BASE |
                         CPSW_FEATURE_EST |
                         CPSW_FEATURE_INTERVLAN |
                         CPSW_FEATURE_CUTTHRU ),
        .errata       = ENET_ERRATA_NONE,
        .initCfg      = &Cpsw_initCfg,
        .open         = &Cpsw_open,
        .rejoin       = &Cpsw_rejoin,
        .ioctl        = &Cpsw_ioctl,
        .poll         = &Cpsw_poll,
        .convertTs    = NULL,
        .periodicTick = &Cpsw_periodicTick,
        .registerEventCb = NULL,
        .unregisterEventCb = NULL,
        .close        = &Cpsw_close,
    },

    /* Host port module object */
    .hostPortObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.hostport",
            .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_NU_OFFSET),
            .features   = ENET_FEAT_BASE,
            .errata     = ENET_ERRATA_NONE,
            .open       = &CpswHostPort_open,
            .rejoin     = &CpswHostPort_rejoin,
            .ioctl      = &CpswHostPort_ioctl,
            .close      = &CpswHostPort_close,
        }
    },

    /* MAC port module objects */
    .macPortObj = gEnetSoc_cpsw3gMacObj,
    .macPortNum = ENET_ARRAYSIZE(gEnetSoc_cpsw3gMacObj),

    /* ALE module object */
    .aleObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.ale",
            .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_ALE_OFFSET),
            .features   = (ENET_FEAT_BASE |
                           CPSW_ALE_FEATURE_FLOW_PRIORITY |
                           CPSW_ALE_FEATURE_IP_HDR_WHITELIST),
            .errata     = ENET_ERRATA_NONE,
            .open       = &CpswAle_open,
            .rejoin     = &CpswAle_rejoin,
            .ioctl      = &CpswAle_ioctl,
            .close      = &CpswAle_close,
        },
    },

    /* CPTS module object */
    .cptsObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.cpts",
            .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_CPTS_OFFSET),
            .features   = ENET_FEAT_BASE,
            .errata     = ENET_ERRATA_NONE,
            .open       = &CpswCpts_open,
            .rejoin     = &CpswCpts_rejoin,
            .ioctl      = &CpswCpts_ioctl,
            .close      = &CpswCpts_close,
        },
        .hwPushCnt      = 8U,
    },

    /* MDIO module object */
    .mdioObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.mdio",
            .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_MDIO_OFFSET),
            .features   = (ENET_FEAT_BASE |
                           MDIO_FEATURE_CLAUSE45),
            .errata     = ENET_ERRATA_NONE,
            .open       = &Mdio_open,
            .rejoin     = &Mdio_rejoin,
            .ioctl      = &Mdio_ioctl,
            .close      = &Mdio_close,
        },
    },

    /* Statistics module object */
    .statsObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.stats",
            .physAddr   = (CSL_CPSW0_NUSS_BASE + CPSW_NU_OFFSET),
            .features   = ENET_FEAT_BASE,
            .errata     = ENET_ERRATA_NONE,
            .open       = &CpswStats_open,
            .rejoin     = &CpswStats_rejoin,
            .ioctl      = &CpswStats_ioctl,
            .close      = &CpswStats_close,
        },
    },

    /* RM module object */
    .rmObj =
    {
        .enetMod =
        {
            .name       = "cpsw3g.rm",
            .physAddr   = 0U,
            .features   = ENET_FEAT_BASE,
            .errata     = ENET_ERRATA_NONE,
            .open       = &EnetRm_open,
            .rejoin     = &EnetRm_rejoin,
            .ioctl      = &EnetRm_ioctl,
            .close      = &EnetRm_close,
        },
    },
};

/* ---------------------------- Enet Peripherals ---------------------------- */

Enet_Obj gEnetSoc_perObj[] =
{
    /* CPSW_3G Enet driver/peripheral */
    {
        .enetPer = &gEnetSoc_cpsw3g.enetPer,
    },
};

EnetUdma_DrvObj gEnetSoc_dmaObj[ENET_ARRAYSIZE(gEnetSoc_perObj)];

EnetUdma_DrvObjMemInfo gEnetSoc_dmaObjMemInfo =
{
    .numObjs = ENET_ARRAYSIZE(gEnetSoc_dmaObj),
    .drvObjMem = &gEnetSoc_dmaObj[0],
};

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

int32_t EnetSoc_init(void)
{
    return ENET_SOK;
}

void EnetSoc_deinit(void)
{

}

EnetDma_Handle EnetSoc_getDmaHandle(Enet_Type enetType,
                                    uint32_t instId)
{
    EnetDma_Handle hDma = NULL;

    switch (enetType)
    {
        case ENET_CPSW_3G:
            if (instId == 0U)
            {
                hDma = &gEnetSoc_dmaObjMemInfo.drvObjMem[0U];
            }
            break;
        default:
            break;
    }

    EnetSoc_assert(hDma != NULL, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
    return hDma;

}

Enet_Handle EnetSoc_getEnetHandleByIdx(uint32_t idx)
{
    Enet_Handle hEnet = NULL;

    if (idx < ENET_ARRAYSIZE(gEnetSoc_perObj))
    {
        hEnet = &gEnetSoc_perObj[idx];
    }

    EnetSoc_assert((hEnet != NULL), "Unsupported  peripheral index (index=%u )\n", idx);
    return hEnet;
}

Enet_Handle EnetSoc_getEnetHandle(Enet_Type enetType,
                                  uint32_t instId)
{
    Enet_Handle hEnet = NULL;

    switch (enetType)
    {
        case ENET_CPSW_3G:
            if (instId == 0U)
            {
                hEnet = &gEnetSoc_perObj[0U];
            }
            break;

        default:
            {
                EnetSoc_assert(false, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
            }
            break;
    }
    EnetSoc_assert((hEnet != NULL), "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
    return hEnet;
}

static bool  EnetSoc_isValidEnetType(Enet_Type enetType)
{
    bool validInstanceType = false;

    if (enetType == ENET_CPSW_3G)
    {
        validInstanceType = true;
    }
    return validInstanceType;
}

uint32_t EnetSoc_getEnetNum(void)
{
    return ENET_ARRAYSIZE(gEnetSoc_perObj);
}

uint32_t EnetSoc_getMacPortMax(Enet_Type enetType,
                               uint32_t instId)
{
    uint32_t numPorts = 0U;

    if ((enetType == ENET_CPSW_3G) && (instId == 0U))
    {
        numPorts = 2;
    }
    else
    {
        EnetSoc_assert(false, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
    }

    return numPorts;
}

uint32_t EnetSoc_isIpSupported(Enet_Type enetType,
                               uint32_t instId)
{
    bool supported = false;

    if ((enetType == ENET_CPSW_3G) && (0U == instId))
    {
        supported = true;
    }

    EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet & instId type %d, %d\n", enetType, instId);

    return supported;
}

uint32_t EnetSoc_getCoreId(void)
{
    uint32_t coreId = CSL_CORE_ID_R5FSS0_0;

    return coreId;
}

static uint32_t EnetSoc_getCoreDevId(void)
{
    uint32_t coreDevId;
    coreDevId = TISCI_DEV_R5FSS0_CORE0;
    return coreDevId;
}




uint32_t EnetSoc_getClkFreq(Enet_Type enetType,
                            uint32_t instId,
                            uint32_t clkId)
{
    uint32_t freq = 0U;

    if (clkId == CPSW_CPPI_CLK)
    {
        if ((enetType == ENET_CPSW_3G) && (instId == 0U))
        {
            freq = gEnetSoc_cpsw3gSocCfg.cppiClkFreqHz;
        }
        EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet type %d\n", enetType);
    }
    else
    {
        EnetSoc_assert(false, "Invalid clk id %u\n", clkId);
    }

    return freq;
}

int32_t EnetSoc_setupIntrCfg(Enet_Type enetType,
                             uint32_t instId,
                             uint32_t intrId)
{
    const EnetSoc_IntrConnCfg *socIntrs = NULL;
    uint32_t numSocIntrs = 0U;
    uint16_t coreDevId = EnetSoc_getCoreDevId();
    uint16_t perDevId = 0U;
    int32_t status = ENET_SOK;


    if ((enetType == ENET_CPSW_3G) && (instId == 0U))
    {
        perDevId    = gEnetSoc_cpsw3gSocCfg.dmscDevId;
        socIntrs    = gEnetSoc_cpsw3gSocCfg.intrs;
        numSocIntrs = ENET_ARRAYSIZE(gEnetSoc_cpsw3gSocCfg.intrs);
    }
    else
    {
        EnetSoc_assert(false, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
        status = ENET_EINVALIDPARAMS;
    }

    if (status == ENET_SOK)
    {
        status = EnetSocJ7x_setupIntrCfg(intrId, coreDevId, perDevId, socIntrs, numSocIntrs);
    }

    return status;
}

int32_t EnetSoc_releaseIntrCfg(Enet_Type enetType,
                               uint32_t instId,
                               uint32_t intrId)
{
    const EnetSoc_IntrConnCfg *socIntrs = NULL;
    uint32_t numSocIntrs = 0U;
    uint16_t coreDevId = EnetSoc_getCoreDevId();
    uint16_t perDevId = 0U;
    int32_t status = ENET_SOK;

    if ((enetType == ENET_CPSW_3G) && (instId == 0U))
    {
        perDevId    = gEnetSoc_cpsw3gSocCfg.dmscDevId;
        socIntrs    = gEnetSoc_cpsw3gSocCfg.intrs;
        numSocIntrs = ENET_ARRAYSIZE(gEnetSoc_cpsw3gSocCfg.intrs);
    }
    else
    {
        EnetSoc_assert(false, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
        status = ENET_EINVALIDPARAMS;
    }

    if (status == ENET_SOK)
    {
        status = EnetSocJ7x_releaseIntrCfg(intrId, coreDevId, perDevId, socIntrs, numSocIntrs);
    }

    return status;
}

uint32_t EnetSoc_getIntrNum(Enet_Type enetType,
                            uint32_t instId,
                            uint32_t intrId)
{
    const EnetSoc_IntrConnCfg *socIntrs = NULL;
    uint32_t numSocIntrs = 0U;
    uint32_t intrNum = 0U;
    int32_t status = ENET_SOK;

    if ((enetType == ENET_CPSW_3G) && (instId == 0U))
    {
        socIntrs    = gEnetSoc_cpsw3gSocCfg.intrs;
        numSocIntrs = ENET_ARRAYSIZE(gEnetSoc_cpsw3gSocCfg.intrs);
    }
    else
    {
        EnetSoc_assert(false, "Invalid peripheral (eneType=%u instId=%u)\n", enetType, instId);
        status = ENET_EINVALIDPARAMS;
    }

    if (status == ENET_SOK)
    {
        intrNum = EnetSocJ7x_getIntrNum(intrId, socIntrs, numSocIntrs);
    }

    return intrNum;
}
uint32_t EnetSoc_getIntrTriggerType(Enet_Type enetType,
                                    uint32_t instId,
                                    uint32_t intrId)
{
    return ENETOSAL_ARM_GIC_TRIG_TYPE_LEVEL;
}

/* Stupid hack to workaround FAE board issues */
#define ENET_MAC_ADDR_HACK (false)
int32_t EnetSoc_getEFusedMacAddrs(uint8_t macAddr[][ENET_MAC_ADDR_LEN],
                                  uint32_t *num)
{
#if (!ENET_MAC_ADDR_HACK)
    CSL_main_ctrl_mmr_cfg0Regs *mmrRegs;
    uint32_t val;

    if (*num >= 1U)
    {
        mmrRegs = (CSL_main_ctrl_mmr_cfg0Regs *)(uintptr_t)CSL_CTRL_MMR0_CFG0_BASE;

        val = CSL_REG32_RD(&mmrRegs->MAC_ID0);
        macAddr[0][5] = (uint8_t)((val & 0x000000FFU) >> 0U);
        macAddr[0][4] = (uint8_t)((val & 0x0000FF00U) >> 8U);
        macAddr[0][3] = (uint8_t)((val & 0x00FF0000U) >> 16U);
        macAddr[0][2] = (uint8_t)((val & 0xFF000000U) >> 24U);

        val = CSL_REG32_RD(&mmrRegs->MAC_ID1);
        macAddr[0][1] = (uint8_t)((val & 0x000000FFU) >> 0U);
        macAddr[0][0] = (uint8_t)((val & 0x0000FF00U) >> 8U);

        *num = 1U;
    }
#else
    //70:ff:76:1e:9c:50
    macAddr[0][0] = 0x70;
    macAddr[0][1] = 0xFF;
    macAddr[0][2] = 0x76;
    macAddr[0][3] = 0x1E;
    macAddr[0][4] = 0x9C;
    macAddr[0][5] = 0x51;
    *num = 1U;
#endif
    return ENET_SOK;
}

uint32_t EnetSoc_getMacPortCaps(Enet_Type enetType,
                                uint32_t instId,
                                Enet_MacPort macPort)
{
    uint32_t linkCaps = 0U;

    switch (enetType)
    {
        case ENET_CPSW_3G:
            if (macPort <= ENET_MAC_PORT_2)
            {
                linkCaps = (ENETPHY_LINK_CAP_HD10 | ENETPHY_LINK_CAP_FD10 |
                            ENETPHY_LINK_CAP_HD100 | ENETPHY_LINK_CAP_FD100 |
                            ENETPHY_LINK_CAP_FD1000);
            }
            break;

        default:
            EnetSoc_assert(false, "Invalid peripheral type: %u\n", enetType);
            break;
    }

    return linkCaps;
}

int32_t EnetSoc_getMacPortMii(Enet_Type enetType,
                              uint32_t instId,
                              Enet_MacPort macPort,
                              EnetMacPort_Interface *mii)
{
    EnetMac_LayerType *enetLayer = &mii->layerType;
    EnetMac_SublayerType *enetSublayer = &mii->sublayerType;
    uint32_t modeSel = CPSW_ENET_CTRL_MODE_RGMII;
    int32_t status = ENET_EFAIL;

    switch (enetType)
    {
        case ENET_CPSW_3G:
            status = EnetSoc_getMcuEnetControl(macPort, &modeSel);
            break;

        default:
            EnetSoc_assert(false, "Invalid peripheral type: %u\n", enetType);
            break;
    }

    if (status == ENET_SOK)
    {
        switch (modeSel)
        {
            /* RMII */
            case CPSW_ENET_CTRL_MODE_RMII:
                *enetLayer    = ENET_MAC_LAYER_MII;
                *enetSublayer = ENET_MAC_SUBLAYER_REDUCED;
                break;

            /* RGMII */
            case CPSW_ENET_CTRL_MODE_RGMII:
                *enetLayer    = ENET_MAC_LAYER_GMII;
                *enetSublayer = ENET_MAC_SUBLAYER_REDUCED;
                break;

            default:
                status = ENET_EINVALIDPARAMS;
                break;
        }
    }

    return status;
}

static uint32_t EnetSoc_getMcuEnetControl(Enet_MacPort macPort,
                                          uint32_t *modeSel)
{
    CSL_main_ctrl_mmr_cfg0Regs *regs =
        (CSL_main_ctrl_mmr_cfg0Regs *)(uintptr_t)CSL_CTRL_MMR0_CFG0_BASE;
    int32_t status = ENET_SOK;

    switch (macPort)
    {
        case ENET_MAC_PORT_1:
            *modeSel = CSL_FEXT(regs->ENET1_CTRL, MAIN_CTRL_MMR_CFG0_ENET1_CTRL_PORT_MODE_SEL);
            break;

        case ENET_MAC_PORT_2:
            *modeSel = CSL_FEXT(regs->ENET2_CTRL, MAIN_CTRL_MMR_CFG0_ENET2_CTRL_PORT_MODE_SEL);
            break;

        default:
            status = ENET_EINVALIDPARAMS;
            break;
    }

    if (status == ENET_SOK)
    {
        switch (*modeSel)
        {
            case CPSW_ENET_CTRL_MODE_RMII:
            case CPSW_ENET_CTRL_MODE_RGMII:
                break;

            default:
                status = ENET_EINVALIDPARAMS;
                break;
        }
    }

    return status;
}

int32_t EnetSoc_validateQsgmiiCfg(Enet_Type enetType,
                                  uint32_t instId)
{
    return ENET_ENOTSUPPORTED;
}

int32_t EnetSoc_mapPort2QsgmiiId(Enet_Type enetType,
                                 uint32_t instId,
                                 Enet_MacPort portNum,
                                 uint32_t *qsgmiiId)
{
    return ENET_ENOTSUPPORTED;
}

uint32_t EnetSoc_getRxFlowCount(Enet_Type enetType,
                                uint32_t instId)
{
    uint32_t rxFlowCount = 0U;
    /* Get SoC array index */
    if (enetType == ENET_CPSW_3G)
    {
        rxFlowCount = gEnetSoc_cpsw3gSocCfg.rxFlowCount;
    }
    EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet type %d\n", enetType);

    return rxFlowCount;
}

uint32_t EnetSoc_getTxChPeerId(Enet_Type enetType,
                               uint32_t instId,
                               uint32_t chNum)
{
    uint32_t peerChNum = 0U;

    /* Get SoC array index */
    if (enetType == ENET_CPSW_3G)
    {
        peerChNum = gEnetSoc_cpsw3gSocCfg.txChPeerThreadId;
    }
    EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet type %d\n", enetType);

    /* Get PSI-L destination thread offset for Tx channel */
    peerChNum = (peerChNum + chNum);

    return peerChNum;
}

uint32_t EnetSoc_getRxChPeerId(Enet_Type enetType,
                               uint32_t instId,
                               uint32_t chIdx)
{
    uint32_t peerChNum = 0U;

    /* Get SoC array index */
    if (enetType == ENET_CPSW_3G)
    {

        peerChNum = gEnetSoc_cpsw3gSocCfg.rxChPeerThreadId;
    }
    EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet type %d\n", enetType);

    return peerChNum;
}

uint32_t EnetSoc_getTxChCount(Enet_Type enetType,
                              uint32_t instId)
{
    uint32_t txChCount = 0U;
    /* Get SoC array index */
    if (enetType == ENET_CPSW_3G)
    {
        txChCount = gEnetSoc_cpsw3gSocCfg.txChCount;
    }
    EnetSoc_assert((EnetSoc_isValidEnetType(enetType) == true), "Invalid Enet type %d\n", enetType);

    return txChCount;

}
/*!
 *  \brief CPSW3G default configuration
 *
 *   Note: If user wishes to change the Resource Partition the following
 *   things must be considered:
 *   1. Sum of numTxCh allocated to each core should not exceed 8.
 *   2. Sum of numRxFlows allocated to each core should not exceed 7 (not 8),
 *      as one Rx flow is reserved to the master core.
 *
 */
static EnetRm_ResPrms gEnetAppRmDefCfg_3G =
{
    .coreDmaResInfo =
    {
        [0] =
        {
            .coreId        = CSL_CORE_ID_R5FSS0_0,
            .numTxCh       = ENET_SYSCFG_TX_CHANNELS_NUM,    /* numTxCh */
            .numRxFlows    = (ENET_SYSCFG_RX_FLOWS_NUM + 1),    /* numRxFlows. Need one additional flow for reserved flow  */
            .numMacAddress = 4U,    /* numMacAddress */
        },
    },
    .numCores = 1U,
};

const EnetRm_ResPrms *EnetAppRm_getResPartInfo(Enet_Type enetType)
{
    const EnetRm_ResPrms *rmInitPrms = NULL;

    switch (enetType)
    {
        case ENET_CPSW_3G:
        {
            rmInitPrms = &gEnetAppRmDefCfg_3G;
            break;
        }
        default:
        {
            rmInitPrms = NULL;
        }
    }

    return(rmInitPrms);
}
/* Cores IOCTL Privileges */
static const EnetRm_IoctlPermissionTable gEnetAppIoctlPermission_3G =
{
    .defaultPermittedCoreMask = (ENET_BIT(CSL_CORE_ID_A53SS0_0) |
                                 ENET_BIT(CSL_CORE_ID_R5FSS0_0) |
                                 ENET_BIT(CSL_CORE_ID_R5FSS0_1) |
                                 ENET_BIT(CSL_CORE_ID_R5FSS1_0) |
                                 ENET_BIT(CSL_CORE_ID_R5FSS1_1)),
    .numEntries = 0,
};

const EnetRm_IoctlPermissionTable *EnetAppRm_getIoctlPermissionInfo(Enet_Type enetType)
{
    const EnetRm_IoctlPermissionTable *ioctlPerm = NULL;

    switch (enetType)
    {
        case ENET_CPSW_3G:
        {
            ioctlPerm = &gEnetAppIoctlPermission_3G;
            break;
        }

        default:
        {
            ioctlPerm = NULL;
            break;
        }
    }

    return(ioctlPerm);
}

void EnetSoC_toggleCPSWResetBit(void *pArg)
{
    EnetAppUtils_print("CPSW Reset is not supported in this platform");
}

