/* * Copyright 2008-2012 Freescale Semiconductor Inc. * * 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 Freescale Semiconductor nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * * ALTERNATIVELY, this software may be distributed under the terms of the * GNU General Public License ("GPL") as published by the Free Software * Foundation, either version 2 of that License or (at your option) any * later version. * * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``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 Freescale Semiconductor 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 fm.c @Description FM driver routines implementation. *//***************************************************************************/ #include "std_ext.h" #include "error_ext.h" #include "xx_ext.h" #include "string_ext.h" #include "sprint_ext.h" #include "debug_ext.h" #include "fm_muram_ext.h" #include "fm_common.h" #include "fm_ipc.h" #include "fm.h" #include #include "fsl_fman.h" /****************************************/ /* static functions */ /****************************************/ static volatile bool blockingFlag = FALSE; static void IpcMsgCompletionCB(t_Handle h_Fm, uint8_t *p_Msg, uint8_t *p_Reply, uint32_t replyLength, t_Error status) { UNUSED(h_Fm);UNUSED(p_Msg);UNUSED(p_Reply);UNUSED(replyLength);UNUSED(status); blockingFlag = FALSE; } static void FreeInitResources(t_Fm *p_Fm) { if (p_Fm->camBaseAddr) FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); if (p_Fm->fifoBaseAddr) FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->fifoBaseAddr)); if (p_Fm->resAddr) FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->resAddr)); } static bool IsFmanCtrlCodeLoaded(t_Fm *p_Fm) { t_FMIramRegs *p_Iram; ASSERT_COND(p_Fm); p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); return (bool)!!(GET_UINT32(p_Iram->iready) & IRAM_READY); } static t_Error CheckFmParameters(t_Fm *p_Fm) { if (IsFmanCtrlCodeLoaded(p_Fm) && !p_Fm->resetOnInit) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Old FMan CTRL code is loaded; FM must be reset!")); #if (DPAA_VERSION < 11) if (!p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats || (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats > DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("axiDbgNumOfBeats has to be in the range 1 - %d", DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)); #endif /* (DPAA_VERSION < 11) */ if (p_Fm->p_FmDriverParam->dma_cam_num_of_entries % DMA_CAM_UNITS) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be divisble by %d", DMA_CAM_UNITS)); // if (!p_Fm->p_FmDriverParam->dma_cam_num_of_entries || (p_Fm->p_FmDriverParam->dma_cam_num_of_entries > DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)) // RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_cam_num_of_entries has to be in the range 1 - %d", DMA_MODE_MAX_CAM_NUM_OF_ENTRIES)); if (p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer > DMA_THRESH_MAX_COMMQ) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ)); if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer > DMA_THRESH_MAX_COMMQ) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_COMMQ)); if (p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer >= p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_comm_qtsh_clr_emer must be smaller than dma_comm_qtsh_asrt_emer")); #if (DPAA_VERSION < 11) if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); if (p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_read_buf_tsh_clr_emer must be smaller than dma_read_buf_tsh_asrt_emer")); if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer > DMA_THRESH_MAX_BUF) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_asrt_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer > DMA_THRESH_MAX_BUF) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer can not be larger than %d", DMA_THRESH_MAX_BUF)); if (p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer >= p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_write_buf_tsh_clr_emer must be smaller than dma_write_buf_tsh_asrt_emer")); #else /* (DPAA_VERSION >= 11) */ if ((p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_READ_EM)|| (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_INT_WRITE_EM) || (p_Fm->p_FmDriverParam->dma_dbg_cnt_mode == E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_dbg_cnt_mode value not supported by this integration.")); if ((p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_READ_EMERGENCY)|| (p_Fm->p_FmDriverParam->dma_emergency_bus_select == FM_DMA_MURAM_WRITE_EMERGENCY)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("emergencyBusSelect value not supported by this integration.")); if (p_Fm->p_FmDriverParam->dma_stop_on_bus_error) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_stop_on_bus_error not supported by this integration.")); #ifdef FM_AID_MODE_NO_TNUM_SW005 if (p_Fm->p_FmDriverParam->dma_aid_mode != E_FMAN_DMA_AID_OUT_PORT_ID) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_aid_mode not supported by this integration.")); #endif /* FM_AID_MODE_NO_TNUM_SW005 */ if (p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_axi_dbg_num_of_beats not supported by this integration.")); #endif /* (DPAA_VERSION < 11) */ if (!p_Fm->p_FmStateStruct->fmClkFreq) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("fmClkFreq must be set.")); if (USEC_TO_CLK(p_Fm->p_FmDriverParam->dma_watchdog, p_Fm->p_FmStateStruct->fmClkFreq) > DMA_MAX_WATCHDOG) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("dma_watchdog depends on FM clock. dma_watchdog(in microseconds) * clk (in Mhz), may not exceed 0x08x", DMA_MAX_WATCHDOG)); #if (DPAA_VERSION >= 11) if ((p_Fm->partVSPBase + p_Fm->partNumOfVSPs) > FM_VSP_MAX_NUM_OF_ENTRIES) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("partVSPBase+partNumOfVSPs out of range!!!")); #endif /* (DPAA_VERSION >= 11) */ if (p_Fm->p_FmStateStruct->totalFifoSize % BMI_FIFO_UNITS) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize number has to be divisible by %d", BMI_FIFO_UNITS)); if (!p_Fm->p_FmStateStruct->totalFifoSize || (p_Fm->p_FmStateStruct->totalFifoSize > BMI_MAX_FIFO_SIZE)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalFifoSize (currently defined as %d) has to be in the range of 256 to %d", p_Fm->p_FmStateStruct->totalFifoSize, BMI_MAX_FIFO_SIZE)); if (!p_Fm->p_FmStateStruct->totalNumOfTasks || (p_Fm->p_FmStateStruct->totalNumOfTasks > BMI_MAX_NUM_OF_TASKS)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("totalNumOfTasks number has to be in the range 1 - %d", BMI_MAX_NUM_OF_TASKS)); #ifdef FM_HAS_TOTAL_DMAS if (!p_Fm->p_FmStateStruct->maxNumOfOpenDmas || (p_Fm->p_FmStateStruct->maxNumOfOpenDmas > BMI_MAX_NUM_OF_DMAS)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("maxNumOfOpenDmas number has to be in the range 1 - %d", BMI_MAX_NUM_OF_DMAS)); #endif /* FM_HAS_TOTAL_DMAS */ if (p_Fm->p_FmDriverParam->disp_limit_tsh > FPM_MAX_DISP_LIMIT) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("disp_limit_tsh can't be greater than %d", FPM_MAX_DISP_LIMIT)); if (!p_Fm->f_Exception) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); if (!p_Fm->f_BusError) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Exceptions callback not provided")); #ifdef FM_NO_WATCHDOG if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 2) && (p_Fm->p_FmDriverParam->dma_watchdog)) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("watchdog!")); #endif /* FM_NO_WATCHDOG */ #ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && (p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err)) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("HaltOnEccError!")); #endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */ #ifdef FM_NO_TNUM_AGING if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) if (p_Fm->p_FmDriverParam->tnum_aging_period) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("Tnum aging!")); #endif /* FM_NO_TNUM_AGING */ /* check that user did not set revision-dependent exceptions */ #ifdef FM_NO_DISPATCH_RAM_ECC if ((p_Fm->p_FmStateStruct->revInfo.majorRev != 4) && (p_Fm->p_FmStateStruct->revInfo.majorRev < 6)) if (p_Fm->userSetExceptions & FM_EX_BMI_DISPATCH_RAM_ECC) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_BMI_DISPATCH_RAM_ECC!")); #endif /* FM_NO_DISPATCH_RAM_ECC */ #ifdef FM_QMI_NO_ECC_EXCEPTIONS if (p_Fm->p_FmStateStruct->revInfo.majorRev == 4) if (p_Fm->userSetExceptions & (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC)) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC/e_FM_EX_QMI_DOUBLE_ECC!")); #endif /* FM_QMI_NO_ECC_EXCEPTIONS */ #ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) if (p_Fm->userSetExceptions & FM_EX_QMI_SINGLE_ECC) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("exception e_FM_EX_QMI_SINGLE_ECC!")); #endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ return E_OK; } static void SendIpcIsr(t_Fm *p_Fm, uint32_t macEvent, uint32_t pendingReg) { ASSERT_COND(p_Fm->guestId == NCSW_MASTER_ID); if (p_Fm->intrMng[macEvent].guestId == NCSW_MASTER_ID) p_Fm->intrMng[macEvent].f_Isr(p_Fm->intrMng[macEvent].h_SrcHandle); /* If the MAC is running on guest-partition and we have IPC session with it, we inform him about the event through IPC; otherwise, we ignore the event. */ else if (p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId]) { t_Error err; t_FmIpcIsr fmIpcIsr; t_FmIpcMsg msg; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_GUEST_ISR; fmIpcIsr.pendingReg = pendingReg; fmIpcIsr.boolErr = FALSE; memcpy(msg.msgBody, &fmIpcIsr, sizeof(fmIpcIsr)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[p_Fm->intrMng[macEvent].guestId], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(fmIpcIsr), NULL, NULL, NULL, NULL); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); } else DBG(TRACE, ("FM Guest mode, without IPC - can't call ISR!")); } static void BmiErrEvent(t_Fm *p_Fm) { uint32_t event; struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; event = fman_get_bmi_err_event(bmi_rg); if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STORAGE_PROFILE_ECC); if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_LIST_RAM_ECC); if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_STATISTICS_RAM_ECC); if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_BMI_DISPATCH_RAM_ECC); } static void QmiErrEvent(t_Fm *p_Fm) { uint32_t event; struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; event = fman_get_qmi_err_event(qmi_rg); if (event & QMI_ERR_INTR_EN_DOUBLE_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DOUBLE_ECC); if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID); } static void DmaErrEvent(t_Fm *p_Fm) { uint32_t status, com_id; uint8_t tnum; uint8_t hardwarePortId; uint8_t relativePortId; uint16_t liodn; struct fman_dma_regs *dma_rg = p_Fm->p_FmDmaRegs; status = fman_get_dma_err_event(dma_rg); if (status & DMA_STATUS_BUS_ERR) { com_id = fman_get_dma_com_id(dma_rg); hardwarePortId = (uint8_t)(((com_id & DMA_TRANSFER_PORTID_MASK) >> DMA_TRANSFER_PORTID_SHIFT)); ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); HW_PORT_ID_TO_SW_PORT_ID(relativePortId, hardwarePortId); tnum = (uint8_t)((com_id & DMA_TRANSFER_TNUM_MASK) >> DMA_TRANSFER_TNUM_SHIFT); liodn = (uint16_t)(com_id & DMA_TRANSFER_LIODN_MASK); ASSERT_COND(p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] != e_FM_PORT_TYPE_DUMMY); p_Fm->f_BusError(p_Fm->h_App, p_Fm->p_FmStateStruct->portsTypes[hardwarePortId], relativePortId, fman_get_dma_addr(dma_rg), tnum, liodn); } if (status & DMA_STATUS_FM_SPDAT_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SINGLE_PORT_ECC); if (status & DMA_STATUS_READ_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_READ_ECC); if (status & DMA_STATUS_SYSTEM_WRITE_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_SYSTEM_WRITE_ECC); if (status & DMA_STATUS_FM_WRITE_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_DMA_FM_WRITE_ECC); } static void FpmErrEvent(t_Fm *p_Fm) { uint32_t event; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; event = fman_get_fpm_err_event(fpm_rg); if ((event & FPM_EV_MASK_DOUBLE_ECC) && (event & FPM_EV_MASK_DOUBLE_ECC_EN)) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_DOUBLE_ECC); if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN)) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_STALL_ON_TASKS); if ((event & FPM_EV_MASK_SINGLE_ECC) && (event & FPM_EV_MASK_SINGLE_ECC_EN)) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_FPM_SINGLE_ECC); } static void MuramErrIntr(t_Fm *p_Fm) { uint32_t event; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; event = fman_get_muram_err_event(fpm_rg); if (event & FPM_RAM_MURAM_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_MURAM_ECC); } static void IramErrIntr(t_Fm *p_Fm) { uint32_t event; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; event = fman_get_iram_err_event(fpm_rg); if (event & FPM_RAM_IRAM_ECC) p_Fm->f_Exception(p_Fm->h_App, e_FM_EX_IRAM_ECC); } static void QmiEvent(t_Fm *p_Fm) { uint32_t event; struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; event = fman_get_qmi_event(qmi_rg); if (event & QMI_INTR_EN_SINGLE_ECC) p_Fm->f_Exception(p_Fm->h_App,e_FM_EX_QMI_SINGLE_ECC); } static void UnimplementedIsr(t_Handle h_Arg) { UNUSED(h_Arg); REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented ISR!")); } static void UnimplementedFmanCtrlIsr(t_Handle h_Arg, uint32_t event) { UNUSED(h_Arg); UNUSED(event); REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Unimplemented FmCtl ISR!")); } static void EnableTimeStamp(t_Fm *p_Fm) { struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; ASSERT_COND(p_Fm->p_FmStateStruct); ASSERT_COND(p_Fm->p_FmStateStruct->count1MicroBit); fman_enable_time_stamp(fpm_rg, p_Fm->p_FmStateStruct->count1MicroBit, p_Fm->p_FmStateStruct->fmClkFreq); p_Fm->p_FmStateStruct->enabledTimeStamp = TRUE; } static t_Error ClearIRam(t_Fm *p_Fm) { t_FMIramRegs *p_Iram; int i; int iram_size; ASSERT_COND(p_Fm); p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); iram_size = FM_IRAM_SIZE(p_Fm->p_FmStateStruct->revInfo.majorRev,p_Fm->p_FmStateStruct->revInfo.minorRev); /* Enable the auto-increment */ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; for (i=0; i < (iram_size/4); i++) WRITE_UINT32(p_Iram->idata, 0xffffffff); WRITE_UINT32(p_Iram->iadd, iram_size - 4); CORE_MemoryBarrier(); while (GET_UINT32(p_Iram->idata) != 0xffffffff) ; return E_OK; } static t_Error LoadFmanCtrlCode(t_Fm *p_Fm) { t_FMIramRegs *p_Iram; int i; uint32_t tmp; uint8_t compTo16; ASSERT_COND(p_Fm); p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); /* Enable the auto-increment */ WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; for (i=0; i < (p_Fm->firmware.size / 4); i++) WRITE_UINT32(p_Iram->idata, p_Fm->firmware.p_Code[i]); compTo16 = (uint8_t)(p_Fm->firmware.size % 16); if (compTo16) for (i=0; i < ((16-compTo16) / 4); i++) WRITE_UINT32(p_Iram->idata, 0xffffffff); WRITE_UINT32(p_Iram->iadd,p_Fm->firmware.size-4); while (GET_UINT32(p_Iram->iadd) != (p_Fm->firmware.size-4)) ; /* verify that writing has completed */ while (GET_UINT32(p_Iram->idata) != p_Fm->firmware.p_Code[(p_Fm->firmware.size / 4)-1]) ; if (p_Fm->fwVerify) { WRITE_UINT32(p_Iram->iadd, IRAM_IADD_AIE); while (GET_UINT32(p_Iram->iadd) != IRAM_IADD_AIE) ; for (i=0; i < (p_Fm->firmware.size / 4); i++) { tmp = GET_UINT32(p_Iram->idata); if (tmp != p_Fm->firmware.p_Code[i]) RETURN_ERROR(MAJOR, E_WRITE_FAILED, ("UCode write error : write 0x%x, read 0x%x", p_Fm->firmware.p_Code[i],tmp)); } WRITE_UINT32(p_Iram->iadd, 0x0); } /* Enable patch from IRAM */ WRITE_UINT32(p_Iram->iready, IRAM_READY); XX_UDelay(1000); DBG(INFO, ("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.", ((uint16_t *)p_Fm->firmware.p_Code)[2], ((uint8_t *)p_Fm->firmware.p_Code)[6], ((uint8_t *)p_Fm->firmware.p_Code)[7])); return E_OK; } #ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 static t_Error FwNotResetErratumBugzilla6173WA(t_Fm *p_Fm) { t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); uint32_t tmpReg; uint32_t savedSpliodn[63]; /* write to IRAM first location the debug instruction */ WRITE_UINT32(p_Iram->iadd, 0); while (GET_UINT32(p_Iram->iadd) != 0) ; WRITE_UINT32(p_Iram->idata, FM_FW_DEBUG_INSTRUCTION); WRITE_UINT32(p_Iram->iadd, 0); while (GET_UINT32(p_Iram->iadd) != 0) ; while (GET_UINT32(p_Iram->idata) != FM_FW_DEBUG_INSTRUCTION) ; /* Enable patch from IRAM */ WRITE_UINT32(p_Iram->iready, IRAM_READY); CORE_MemoryBarrier(); XX_UDelay(100); IO2MemCpy32((uint8_t *)savedSpliodn, (uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn, 63*sizeof(uint32_t)); /* reset FMAN */ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); CORE_MemoryBarrier(); XX_UDelay(100); /* verify breakpoint debug status register */ tmpReg = GET_UINT32(*(uint32_t *)UINT_TO_PTR(p_Fm->baseAddr + FM_DEBUG_STATUS_REGISTER_OFFSET)); if (!tmpReg) REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Invalid debug status register value is '0'")); /*************************************/ /* Load FMan-Controller code to IRAM */ /*************************************/ ClearIRam(p_Fm); if (p_Fm->firmware.p_Code && (LoadFmanCtrlCode(p_Fm) != E_OK)) RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); XX_UDelay(100); /* reset FMAN again to start the microcode */ WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); CORE_MemoryBarrier(); XX_UDelay(100); Mem2IOCpy32((uint8_t *)p_Fm->p_FmBmiRegs->fmbm_spliodn, (uint8_t *)savedSpliodn, 63*sizeof(uint32_t)); if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs)) { fman_resume(p_Fm->p_FmFpmRegs); CORE_MemoryBarrier(); XX_UDelay(100); } return E_OK; } #endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ static void GuestErrorIsr(t_Fm *p_Fm, uint32_t pending) { #define FM_G_CALL_1G_MAC_ERR_ISR(_id) \ do { \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ } while (0) #define FM_G_CALL_10G_MAC_ERR_ISR(_id) \ do { \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ } while (0) /* error interrupts */ if (pending & ERR_INTR_EN_1G_MAC0) FM_G_CALL_1G_MAC_ERR_ISR(0); if (pending & ERR_INTR_EN_1G_MAC1) FM_G_CALL_1G_MAC_ERR_ISR(1); if (pending & ERR_INTR_EN_1G_MAC2) FM_G_CALL_1G_MAC_ERR_ISR(2); if (pending & ERR_INTR_EN_1G_MAC3) FM_G_CALL_1G_MAC_ERR_ISR(3); if (pending & ERR_INTR_EN_1G_MAC4) FM_G_CALL_1G_MAC_ERR_ISR(4); if (pending & ERR_INTR_EN_1G_MAC5) FM_G_CALL_1G_MAC_ERR_ISR(5); if (pending & ERR_INTR_EN_1G_MAC6) FM_G_CALL_1G_MAC_ERR_ISR(6); if (pending & ERR_INTR_EN_1G_MAC7) FM_G_CALL_1G_MAC_ERR_ISR(7); if (pending & ERR_INTR_EN_10G_MAC0) FM_G_CALL_10G_MAC_ERR_ISR(0); if (pending & ERR_INTR_EN_10G_MAC1) FM_G_CALL_10G_MAC_ERR_ISR(1); } static void GuestEventIsr(t_Fm *p_Fm, uint32_t pending) { #define FM_G_CALL_1G_MAC_ISR(_id) \ do { \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ } while (0) #define FM_G_CALL_10G_MAC_ISR(_id) \ do { \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ } while (0) if (pending & INTR_EN_1G_MAC0) FM_G_CALL_1G_MAC_ISR(0); if (pending & INTR_EN_1G_MAC1) FM_G_CALL_1G_MAC_ISR(1); if (pending & INTR_EN_1G_MAC2) FM_G_CALL_1G_MAC_ISR(2); if (pending & INTR_EN_1G_MAC3) FM_G_CALL_1G_MAC_ISR(3); if (pending & INTR_EN_1G_MAC4) FM_G_CALL_1G_MAC_ISR(4); if (pending & INTR_EN_1G_MAC5) FM_G_CALL_1G_MAC_ISR(5); if (pending & INTR_EN_1G_MAC6) FM_G_CALL_1G_MAC_ISR(6); if (pending & INTR_EN_1G_MAC7) FM_G_CALL_1G_MAC_ISR(7); if (pending & INTR_EN_10G_MAC0) FM_G_CALL_10G_MAC_ISR(0); if (pending & INTR_EN_10G_MAC1) FM_G_CALL_10G_MAC_ISR(1); if (pending & INTR_EN_TMR) p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); } #if (DPAA_VERSION >= 11) static t_Error SetVSPWindow(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t baseStorageProfile, uint8_t log2NumOfProfiles) { t_Fm *p_Fm = (t_Fm *)h_Fm; ASSERT_COND(h_Fm); ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->p_FmBmiRegs && p_Fm->h_IpcSessions[0]) { t_FmIpcVspSetPortWindow fmIpcVspSetPortWindow; t_FmIpcMsg msg; t_Error err = E_OK; memset(&msg, 0, sizeof(msg)); memset(&fmIpcVspSetPortWindow, 0, sizeof(t_FmIpcVspSetPortWindow)); fmIpcVspSetPortWindow.hardwarePortId = hardwarePortId; fmIpcVspSetPortWindow.baseStorageProfile = baseStorageProfile; fmIpcVspSetPortWindow.log2NumOfProfiles = log2NumOfProfiles; msg.msgId = FM_VSP_SET_PORT_WINDOW; memcpy(msg.msgBody, &fmIpcVspSetPortWindow, sizeof(t_FmIpcVspSetPortWindow)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), NULL, NULL, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); return E_OK; } else if (!p_Fm->p_FmBmiRegs) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); fman_set_vsp_window(p_Fm->p_FmBmiRegs, hardwarePortId, baseStorageProfile, log2NumOfProfiles); return E_OK; } static uint8_t AllocVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) { t_Fm *p_Fm = (t_Fm *)h_Fm; uint8_t profilesFound = 0; int i = 0; uint32_t intFlags; if (!numOfProfiles) return E_OK; if ((numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES) || (base + numOfProfiles > FM_VSP_MAX_NUM_OF_ENTRIES)) return (uint8_t)ILLEGAL_BASE; if (p_Fm->h_IpcSessions[0]) { t_FmIpcResourceAllocParams ipcAllocParams; t_FmIpcMsg msg; t_FmIpcReply reply; t_Error err; uint32_t replyLength; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ipcAllocParams.guestId = p_Fm->guestId; ipcAllocParams.num = p_Fm->partNumOfVSPs; ipcAllocParams.base = p_Fm->partVSPBase; msg.msgId = FM_VSP_ALLOC; memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); replyLength = sizeof(uint32_t) + sizeof(uint8_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), (uint8_t*)&reply, &replyLength, NULL, NULL); if ((err != E_OK) || (replyLength != (sizeof(uint32_t) + sizeof(uint8_t)))) RETURN_ERROR(MAJOR, err, NO_MSG); else memcpy((uint8_t*)&p_Fm->partVSPBase, reply.replyBody, sizeof(uint8_t)); if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) RETURN_ERROR(MAJOR, err, NO_MSG); } if (p_Fm->guestId != NCSW_MASTER_ID) { DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); return (uint8_t)ILLEGAL_BASE; } intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); for (i = base; i < base + numOfProfiles; i++) if (p_Fm->p_FmSp->profiles[i].profilesMng.ownerId == (uint8_t)ILLEGAL_BASE) profilesFound++; else break; if (profilesFound == numOfProfiles) for (i = base; ip_FmSp->profiles[i].profilesMng.ownerId = guestId; else { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); return (uint8_t)ILLEGAL_BASE; } XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); return base; } static void FreeVSPsForPartition(t_Handle h_Fm, uint8_t base, uint8_t numOfProfiles, uint8_t guestId) { t_Fm *p_Fm = (t_Fm *)h_Fm; int i = 0; ASSERT_COND(p_Fm); if (p_Fm->h_IpcSessions[0]) { t_FmIpcResourceAllocParams ipcAllocParams; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; t_Error err; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); memset(&ipcAllocParams, 0, sizeof(t_FmIpcResourceAllocParams)); ipcAllocParams.guestId = p_Fm->guestId; ipcAllocParams.num = p_Fm->partNumOfVSPs; ipcAllocParams.base = p_Fm->partVSPBase; msg.msgId = FM_VSP_FREE; memcpy(msg.msgBody, &ipcAllocParams, sizeof(t_FmIpcResourceAllocParams)); replyLength = sizeof(uint32_t) + sizeof(uint8_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(t_FmIpcResourceAllocParams), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) REPORT_ERROR(MAJOR, err, NO_MSG); return; } if (p_Fm->guestId != NCSW_MASTER_ID) { DBG(WARNING, ("FM Guest mode, without IPC - can't validate VSP range!")); return; } ASSERT_COND(p_Fm->p_FmSp); for (i=base; ip_FmSp->profiles[i].profilesMng.ownerId == guestId) p_Fm->p_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; else DBG(WARNING, ("Request for freeing storage profile window which wasn't allocated to this partition")); } } #endif /* (DPAA_VERSION >= 11) */ static t_Error FmGuestHandleIpcMsgCB(t_Handle h_Fm, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; UNUSED(p_Reply); SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((msgLength > sizeof(uint32_t)), E_INVALID_VALUE); #ifdef DISABLE_SANITY_CHECKS UNUSED(msgLength); #endif /* DISABLE_SANITY_CHECKS */ ASSERT_COND(p_Msg); *p_ReplyLength = 0; switch (p_IpcMsg->msgId) { case (FM_GUEST_ISR): { t_FmIpcIsr ipcIsr; memcpy((uint8_t*)&ipcIsr, p_IpcMsg->msgBody, sizeof(t_FmIpcIsr)); if (ipcIsr.boolErr) GuestErrorIsr(p_Fm, ipcIsr.pendingReg); else GuestEventIsr(p_Fm, ipcIsr.pendingReg); break; } default: *p_ReplyLength = 0; RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); } return E_OK; } static t_Error FmHandleIpcMsgCB(t_Handle h_Fm, uint8_t *p_Msg, uint32_t msgLength, uint8_t *p_Reply, uint32_t *p_ReplyLength) { t_Error err; t_Fm *p_Fm = (t_Fm*)h_Fm; t_FmIpcMsg *p_IpcMsg = (t_FmIpcMsg*)p_Msg; t_FmIpcReply *p_IpcReply = (t_FmIpcReply*)p_Reply; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((msgLength >= sizeof(uint32_t)), E_INVALID_VALUE); #ifdef DISABLE_SANITY_CHECKS UNUSED(msgLength); #endif /* DISABLE_SANITY_CHECKS */ ASSERT_COND(p_IpcMsg); memset(p_IpcReply, 0, (sizeof(uint8_t) * FM_IPC_MAX_REPLY_SIZE)); *p_ReplyLength = 0; switch (p_IpcMsg->msgId) { case (FM_GET_SET_PORT_PARAMS): { t_FmIpcPortInInitParams ipcInitParams; t_FmInterModulePortInitParams initParams; t_FmIpcPortOutInitParams ipcOutInitParams; memcpy((uint8_t*)&ipcInitParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortInInitParams)); initParams.hardwarePortId = ipcInitParams.hardwarePortId; initParams.portType = (e_FmPortType)ipcInitParams.enumPortType; initParams.independentMode = (bool)(ipcInitParams.boolIndependentMode); initParams.liodnOffset = ipcInitParams.liodnOffset; initParams.numOfTasks = ipcInitParams.numOfTasks; initParams.numOfExtraTasks = ipcInitParams.numOfExtraTasks; initParams.numOfOpenDmas = ipcInitParams.numOfOpenDmas; initParams.numOfExtraOpenDmas = ipcInitParams.numOfExtraOpenDmas; initParams.sizeOfFifo = ipcInitParams.sizeOfFifo; initParams.extraSizeOfFifo = ipcInitParams.extraSizeOfFifo; initParams.deqPipelineDepth = ipcInitParams.deqPipelineDepth; initParams.maxFrameLength = ipcInitParams.maxFrameLength; initParams.liodnBase = ipcInitParams.liodnBase; p_IpcReply->error = (uint32_t)FmGetSetPortParams(h_Fm, &initParams); ipcOutInitParams.ipcPhysAddr.high = initParams.fmMuramPhysBaseAddr.high; ipcOutInitParams.ipcPhysAddr.low = initParams.fmMuramPhysBaseAddr.low; ipcOutInitParams.sizeOfFifo = initParams.sizeOfFifo; ipcOutInitParams.extraSizeOfFifo = initParams.extraSizeOfFifo; ipcOutInitParams.numOfTasks = initParams.numOfTasks; ipcOutInitParams.numOfExtraTasks = initParams.numOfExtraTasks; ipcOutInitParams.numOfOpenDmas = initParams.numOfOpenDmas; ipcOutInitParams.numOfExtraOpenDmas = initParams.numOfExtraOpenDmas; memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcOutInitParams, sizeof(ipcOutInitParams)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams); break; } case (FM_SET_SIZE_OF_FIFO): { t_FmIpcPortRsrcParams ipcPortRsrcParams; memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); p_IpcReply->error = (uint32_t)FmSetSizeOfFifo(h_Fm, ipcPortRsrcParams.hardwarePortId, &ipcPortRsrcParams.val, &ipcPortRsrcParams.extra, (bool)ipcPortRsrcParams.boolInitialConfig); *p_ReplyLength = sizeof(uint32_t); break; } case (FM_SET_NUM_OF_TASKS): { t_FmIpcPortRsrcParams ipcPortRsrcParams; memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); p_IpcReply->error = (uint32_t)FmSetNumOfTasks(h_Fm, ipcPortRsrcParams.hardwarePortId, (uint8_t*)&ipcPortRsrcParams.val, (uint8_t*)&ipcPortRsrcParams.extra, (bool)ipcPortRsrcParams.boolInitialConfig); *p_ReplyLength = sizeof(uint32_t); break; } case (FM_SET_NUM_OF_OPEN_DMAS): { t_FmIpcPortRsrcParams ipcPortRsrcParams; memcpy((uint8_t*)&ipcPortRsrcParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortRsrcParams)); p_IpcReply->error = (uint32_t)FmSetNumOfOpenDmas(h_Fm, ipcPortRsrcParams.hardwarePortId, (uint8_t*)&ipcPortRsrcParams.val, (uint8_t*)&ipcPortRsrcParams.extra, (bool)ipcPortRsrcParams.boolInitialConfig); *p_ReplyLength = sizeof(uint32_t); break; } case (FM_RESUME_STALLED_PORT): *p_ReplyLength = sizeof(uint32_t); p_IpcReply->error = (uint32_t)FmResumeStalledPort(h_Fm, p_IpcMsg->msgBody[0]); break; case (FM_MASTER_IS_ALIVE): { uint8_t guestId = p_IpcMsg->msgBody[0]; /* build the FM master partition IPC address */ memset(p_Fm->fmIpcHandlerModuleName[guestId], 0, (sizeof(char)) * MODULE_NAME_SIZE); if (Sprint (p_Fm->fmIpcHandlerModuleName[guestId], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, guestId) != (guestId<10 ? 6:7)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); p_Fm->h_IpcSessions[guestId] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[guestId], p_Fm->fmModuleName); if (p_Fm->h_IpcSessions[guestId] == NULL) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("FM Master IPC session for guest %d", guestId)); *(uint8_t*)(p_IpcReply->replyBody) = 1; *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); break; } case (FM_IS_PORT_STALLED): { bool tmp; p_IpcReply->error = (uint32_t)FmIsPortStalled(h_Fm, p_IpcMsg->msgBody[0], &tmp); *(uint8_t*)(p_IpcReply->replyBody) = (uint8_t)tmp; *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); break; } case (FM_RESET_MAC): { t_FmIpcMacParams ipcMacParams; memcpy((uint8_t*)&ipcMacParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacParams)); p_IpcReply->error = (uint32_t)FmResetMac(p_Fm, (e_FmMacType)(ipcMacParams.enumType), ipcMacParams.id); *p_ReplyLength = sizeof(uint32_t); break; } case (FM_SET_MAC_MAX_FRAME): { t_FmIpcMacMaxFrameParams ipcMacMaxFrameParams; memcpy((uint8_t*)&ipcMacMaxFrameParams, p_IpcMsg->msgBody, sizeof(t_FmIpcMacMaxFrameParams)); err = FmSetMacMaxFrame(p_Fm, (e_FmMacType)(ipcMacMaxFrameParams.macParams.enumType), ipcMacMaxFrameParams.macParams.id, ipcMacMaxFrameParams.maxFrameLength); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); break; } #if (DPAA_VERSION >= 11) case (FM_VSP_ALLOC) : { t_FmIpcResourceAllocParams ipcAllocParams; uint8_t vspBase; memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); vspBase = AllocVSPsForPartition(h_Fm, (uint8_t)ipcAllocParams.base, (uint8_t)ipcAllocParams.num, ipcAllocParams.guestId); memcpy(p_IpcReply->replyBody, (uint8_t*)&vspBase, sizeof(uint8_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); break; } case (FM_VSP_FREE) : { t_FmIpcResourceAllocParams ipcAllocParams; memcpy(&ipcAllocParams, p_IpcMsg->msgBody, sizeof(t_FmIpcResourceAllocParams)); FreeVSPsForPartition(h_Fm, (uint8_t)ipcAllocParams.base, (uint8_t)ipcAllocParams.num, ipcAllocParams.guestId); break; } case (FM_VSP_SET_PORT_WINDOW) : { t_FmIpcVspSetPortWindow ipcVspSetPortWindow; memcpy(&ipcVspSetPortWindow, p_IpcMsg->msgBody, sizeof(t_FmIpcVspSetPortWindow)); err = SetVSPWindow(h_Fm, ipcVspSetPortWindow.hardwarePortId, ipcVspSetPortWindow.baseStorageProfile, ipcVspSetPortWindow.log2NumOfProfiles); return err; } case (FM_SET_CONG_GRP_PFC_PRIO) : { t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; memcpy(&fmIpcSetCongestionGroupPfcPriority, p_IpcMsg->msgBody, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); err = FmSetCongestionGroupPFCpriority(h_Fm, fmIpcSetCongestionGroupPfcPriority.congestionGroupId, fmIpcSetCongestionGroupPfcPriority.priorityBitMap); return err; } #endif /* (DPAA_VERSION >= 11) */ case (FM_FREE_PORT): { t_FmInterModulePortFreeParams portParams; t_FmIpcPortFreeParams ipcPortParams; memcpy((uint8_t*)&ipcPortParams, p_IpcMsg->msgBody, sizeof(t_FmIpcPortFreeParams)); portParams.hardwarePortId = ipcPortParams.hardwarePortId; portParams.portType = (e_FmPortType)(ipcPortParams.enumPortType); portParams.deqPipelineDepth = ipcPortParams.deqPipelineDepth; FmFreePortParams(h_Fm, &portParams); break; } case (FM_REGISTER_INTR): { t_FmIpcRegisterIntr ipcRegIntr; memcpy((uint8_t*)&ipcRegIntr, p_IpcMsg->msgBody, sizeof(ipcRegIntr)); p_Fm->intrMng[ipcRegIntr.event].guestId = ipcRegIntr.guestId; break; } case (FM_GET_PARAMS): { t_FmIpcParams ipcParams; /* Get clock frequency */ ipcParams.fmClkFreq = p_Fm->p_FmStateStruct->fmClkFreq; ipcParams.fmMacClkFreq = p_Fm->p_FmStateStruct->fmMacClkFreq; fman_get_revision(p_Fm->p_FmFpmRegs,&ipcParams.majorRev,&ipcParams.minorRev); memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcParams, sizeof(t_FmIpcParams)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); break; } case (FM_GET_FMAN_CTRL_CODE_REV): { t_FmCtrlCodeRevisionInfo fmanCtrlRevInfo; t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; p_IpcReply->error = (uint32_t)FM_GetFmanCtrlCodeRevision(h_Fm, &fmanCtrlRevInfo); ipcRevInfo.packageRev = fmanCtrlRevInfo.packageRev; ipcRevInfo.majorRev = fmanCtrlRevInfo.majorRev; ipcRevInfo.minorRev = fmanCtrlRevInfo.minorRev; memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcRevInfo, sizeof(t_FmIpcFmanCtrlCodeRevisionInfo)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcFmanCtrlCodeRevisionInfo); break; } case (FM_DMA_STAT): { t_FmDmaStatus dmaStatus; t_FmIpcDmaStatus ipcDmaStatus; FM_GetDmaStatus(h_Fm, &dmaStatus); ipcDmaStatus.boolCmqNotEmpty = (uint8_t)dmaStatus.cmqNotEmpty; ipcDmaStatus.boolBusError = (uint8_t)dmaStatus.busError; ipcDmaStatus.boolReadBufEccError = (uint8_t)dmaStatus.readBufEccError; ipcDmaStatus.boolWriteBufEccSysError = (uint8_t)dmaStatus.writeBufEccSysError; ipcDmaStatus.boolWriteBufEccFmError = (uint8_t)dmaStatus.writeBufEccFmError; ipcDmaStatus.boolSinglePortEccError = (uint8_t)dmaStatus.singlePortEccError; memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcDmaStatus, sizeof(t_FmIpcDmaStatus)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); break; } case (FM_ALLOC_FMAN_CTRL_EVENT_REG): p_IpcReply->error = (uint32_t)FmAllocFmanCtrlEventReg(h_Fm, (uint8_t*)p_IpcReply->replyBody); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint8_t); break; case (FM_FREE_FMAN_CTRL_EVENT_REG): FmFreeFmanCtrlEventReg(h_Fm, p_IpcMsg->msgBody[0]); break; case (FM_GET_TIMESTAMP_SCALE): { uint32_t timeStamp = FmGetTimeStampScale(h_Fm); memcpy(p_IpcReply->replyBody, (uint8_t*)&timeStamp, sizeof(uint32_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); break; } case (FM_GET_COUNTER): { e_FmCounters inCounter; uint32_t outCounter; memcpy((uint8_t*)&inCounter, p_IpcMsg->msgBody, sizeof(uint32_t)); outCounter = FM_GetCounter(h_Fm, inCounter); memcpy(p_IpcReply->replyBody, (uint8_t*)&outCounter, sizeof(uint32_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); break; } case (FM_SET_FMAN_CTRL_EVENTS_ENABLE): { t_FmIpcFmanEvents ipcFmanEvents; memcpy((uint8_t*)&ipcFmanEvents, p_IpcMsg->msgBody, sizeof(t_FmIpcFmanEvents)); FmSetFmanCtrlIntr(h_Fm, ipcFmanEvents.eventRegId, ipcFmanEvents.enableEvents); break; } case (FM_GET_FMAN_CTRL_EVENTS_ENABLE): { uint32_t tmp = FmGetFmanCtrlIntr(h_Fm, p_IpcMsg->msgBody[0]); memcpy(p_IpcReply->replyBody, (uint8_t*)&tmp, sizeof(uint32_t)); *p_ReplyLength = sizeof(uint32_t) + sizeof(uint32_t); break; } case (FM_GET_PHYS_MURAM_BASE): { t_FmPhysAddr physAddr; t_FmIpcPhysAddr ipcPhysAddr; FmGetPhysicalMuramBase(h_Fm, &physAddr); ipcPhysAddr.high = physAddr.high; ipcPhysAddr.low = physAddr.low; memcpy(p_IpcReply->replyBody, (uint8_t*)&ipcPhysAddr, sizeof(t_FmIpcPhysAddr)); *p_ReplyLength = sizeof(uint32_t) + sizeof(t_FmIpcPhysAddr); break; } case (FM_ENABLE_RAM_ECC): { if (((err = FM_EnableRamsEcc(h_Fm)) != E_OK) || ((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, TRUE)) != E_OK) || ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, TRUE)) != E_OK)) #if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) UNUSED(err); #else REPORT_ERROR(MINOR, err, NO_MSG); #endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ break; } case (FM_DISABLE_RAM_ECC): { if (((err = FM_SetException(h_Fm, e_FM_EX_IRAM_ECC, FALSE)) != E_OK) || ((err = FM_SetException(h_Fm, e_FM_EX_MURAM_ECC, FALSE)) != E_OK) || ((err = FM_DisableRamsEcc(h_Fm)) != E_OK)) #if (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) UNUSED(err); #else REPORT_ERROR(MINOR, err, NO_MSG); #endif /* (!(defined(DEBUG_ERRORS)) || (DEBUG_ERRORS == 0)) */ break; } case (FM_SET_NUM_OF_FMAN_CTRL): { t_FmIpcPortNumOfFmanCtrls ipcPortNumOfFmanCtrls; memcpy((uint8_t*)&ipcPortNumOfFmanCtrls, p_IpcMsg->msgBody, sizeof(t_FmIpcPortNumOfFmanCtrls)); err = FmSetNumOfRiscsPerPort(h_Fm, ipcPortNumOfFmanCtrls.hardwarePortId, ipcPortNumOfFmanCtrls.numOfFmanCtrls, ipcPortNumOfFmanCtrls.orFmanCtrl); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); break; } #ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 case (FM_10G_TX_ECC_WA): p_IpcReply->error = (uint32_t)Fm10GTxEccWorkaround(h_Fm, p_IpcMsg->msgBody[0]); *p_ReplyLength = sizeof(uint32_t); break; #endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ default: *p_ReplyLength = 0; RETURN_ERROR(MINOR, E_INVALID_SELECTION, ("command not found!!!")); } return E_OK; } /****************************************/ /* Inter-Module functions */ /****************************************/ #ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 t_Error Fm10GTxEccWorkaround(t_Handle h_Fm, uint8_t macId) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err = E_OK; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; uint8_t rxHardwarePortId, txHardwarePortId; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_10G_TX_ECC_WA; msg.msgBody[0] = macId; replyLength = sizeof(uint32_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(macId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } SANITY_CHECK_RETURN_ERROR((macId == 0), E_NOT_SUPPORTED); SANITY_CHECK_RETURN_ERROR(IsFmanCtrlCodeLoaded(p_Fm), E_INVALID_STATE); rxHardwarePortId = SwPortIdToHwPortId(e_FM_PORT_TYPE_RX_10G, macId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); txHardwarePortId = SwPortIdToHwPortId(e_FM_PORT_TYPE_TX_10G, macId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); if ((p_Fm->p_FmStateStruct->portsTypes[rxHardwarePortId] != e_FM_PORT_TYPE_DUMMY) || (p_Fm->p_FmStateStruct->portsTypes[txHardwarePortId] != e_FM_PORT_TYPE_DUMMY)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("MAC should be initialized prior to Rx and Tx ports!")); return fman_set_erratum_10gmac_a004_wa(fpm_rg); } #endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */ uint16_t FmGetTnumAgingPeriod(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm *)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0); return p_Fm->tnumAgingPeriod; } t_Error FmSetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool preFetchConfigured) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); p_Fm->portsPreFetchConfigured[portNum] = TRUE; p_Fm->portsPreFetchValue[portNum] = preFetchConfigured; return E_OK; } t_Error FmGetPortPreFetchConfiguration(t_Handle h_Fm, uint8_t portNum, bool *p_PortConfigured, bool *p_PreFetchConfigured) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); /* If the prefetch wasn't configured yet (not enable or disabled) we return the value TRUE as it was already configured */ if (!p_Fm->portsPreFetchConfigured[portNum]) { *p_PortConfigured = FALSE; *p_PreFetchConfigured = FALSE; } else { *p_PortConfigured = TRUE; *p_PreFetchConfigured = (p_Fm->portsPreFetchConfigured[portNum]); } return E_OK; } t_Error FmSetCongestionGroupPFCpriority(t_Handle h_Fm, uint32_t congestionGroupId, uint8_t priorityBitMap) { t_Fm *p_Fm = (t_Fm *)h_Fm; ASSERT_COND(h_Fm); if (congestionGroupId > FM_PORT_NUM_OF_CONGESTION_GRPS) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Congestion group ID bigger than %d", FM_PORT_NUM_OF_CONGESTION_GRPS)); if (p_Fm->guestId == NCSW_MASTER_ID) { ASSERT_COND(p_Fm->baseAddr); fman_set_congestion_group_pfc_priority((uint32_t *)((p_Fm->baseAddr+FM_MM_CGP)), congestionGroupId, priorityBitMap); } else if (p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcSetCongestionGroupPfcPriority fmIpcSetCongestionGroupPfcPriority; memset(&msg, 0, sizeof(msg)); memset(&fmIpcSetCongestionGroupPfcPriority, 0, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); fmIpcSetCongestionGroupPfcPriority.congestionGroupId = congestionGroupId; fmIpcSetCongestionGroupPfcPriority.priorityBitMap = priorityBitMap; msg.msgId = FM_SET_CONG_GRP_PFC_PRIO; memcpy(msg.msgBody, &fmIpcSetCongestionGroupPfcPriority, sizeof(t_FmIpcSetCongestionGroupPfcPriority)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), NULL, NULL, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); } else RETURN_ERROR(MAJOR, E_INVALID_STATE, ("guest without IPC!")); return E_OK; } uintptr_t FmGetPcdPrsBaseAddr(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); if (!p_Fm->baseAddr) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No base-addr; probably Guest with IPC!")); return 0; } return (p_Fm->baseAddr + FM_MM_PRS); } uintptr_t FmGetPcdKgBaseAddr(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); if (!p_Fm->baseAddr) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No base-addr; probably Guest with IPC!")); return 0; } return (p_Fm->baseAddr + FM_MM_KG); } uintptr_t FmGetPcdPlcrBaseAddr(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); if (!p_Fm->baseAddr) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("No base-addr; probably Guest with IPC!")); return 0; } return (p_Fm->baseAddr + FM_MM_PLCR); } #if (DPAA_VERSION >= 11) uintptr_t FmGetVSPBaseAddr(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); return p_Fm->vspBaseAddr; } #endif /* (DPAA_VERSION >= 11) */ t_Handle FmGetMuramHandle(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, NULL); return (p_Fm->h_FmMuram); } void FmGetPhysicalMuramBase(t_Handle h_Fm, t_FmPhysAddr *p_FmPhysAddr) { t_Fm *p_Fm = (t_Fm*)h_Fm; if (p_Fm->fmMuramPhysBaseAddr) { /* General FM driver initialization */ p_FmPhysAddr->low = (uint32_t)p_Fm->fmMuramPhysBaseAddr; p_FmPhysAddr->high = (uint8_t)((p_Fm->fmMuramPhysBaseAddr & 0x000000ff00000000LL) >> 32); return; } ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); if (p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; t_FmIpcPhysAddr ipcPhysAddr; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_PHYS_MURAM_BASE; replyLength = sizeof(uint32_t) + sizeof(t_FmPhysAddr); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) { REPORT_ERROR(MINOR, err, NO_MSG); return; } if (replyLength != (sizeof(uint32_t) + sizeof(t_FmPhysAddr))) { REPORT_ERROR(MINOR, E_INVALID_VALUE,("IPC reply length mismatch")); return; } memcpy((uint8_t*)&ipcPhysAddr, reply.replyBody, sizeof(t_FmIpcPhysAddr)); p_FmPhysAddr->high = ipcPhysAddr.high; p_FmPhysAddr->low = ipcPhysAddr.low; } else REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without neither IPC nor mapped register!")); } #if (DPAA_VERSION >= 11) t_Error FmVSPAllocForPort (t_Handle h_Fm, e_FmPortType portType, uint8_t portId, uint8_t numOfVSPs) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_Error err = E_OK; uint32_t profilesFound, intFlags; uint8_t first, i; uint8_t log2Num; uint8_t swPortIndex=0, hardwarePortId; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); if (!numOfVSPs) return E_OK; if (numOfVSPs > FM_VSP_MAX_NUM_OF_ENTRIES) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("numProfiles can not be bigger than %d.",FM_VSP_MAX_NUM_OF_ENTRIES)); if (!POWER_OF_2(numOfVSPs)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("numProfiles must be a power of 2.")); LOG2((uint64_t)numOfVSPs, log2Num); if ((log2Num == 0) || (p_Fm->partVSPBase == 0)) first = 0; else first = 1< (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); if (first < p_Fm->partVSPBase) while (first < p_Fm->partVSPBase) first = first + numOfVSPs; if ((first + numOfVSPs) > (p_Fm->partVSPBase + p_Fm->partNumOfVSPs)) RETURN_ERROR(MINOR, E_INVALID_VALUE, ("can not allocate storage profile port window")); intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); profilesFound = 0; for (i=first; i < p_Fm->partVSPBase + p_Fm->partNumOfVSPs; ) { if (!p_Fm->p_FmSp->profiles[i].profilesMng.allocated) { profilesFound++; i++; if (profilesFound == numOfVSPs) break; } else { profilesFound = 0; /* advance i to the next aligned address */ first = i = (uint8_t)(first + numOfVSPs); } } if (profilesFound == numOfVSPs) for (i = first; ip_FmSp->profiles[i].profilesMng.allocated = TRUE; else { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MINOR, E_FULL, ("No profiles.")); } hardwarePortId = SwPortIdToHwPortId(portType, portId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = numOfVSPs; p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = first; if ((err = SetVSPWindow(h_Fm,hardwarePortId, first,log2Num)) != E_OK) for (i = first; i < first + numOfVSPs; i++) p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); return err; } t_Error FmVSPFreeForPort(t_Handle h_Fm, e_FmPortType portType, uint8_t portId) { t_Fm *p_Fm = (t_Fm *)h_Fm; uint8_t swPortIndex=0, hardwarePortId, first, numOfVSPs, i; uint32_t intFlags; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); hardwarePortId = SwPortIdToHwPortId(portType, portId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); numOfVSPs = (uint8_t)p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles; first = (uint8_t)p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase; intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); for (i = first; i < first + numOfVSPs; i++) p_Fm->p_FmSp->profiles[i].profilesMng.allocated = FALSE; XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); p_Fm->p_FmSp->portsMapping[swPortIndex].numOfProfiles = 0; p_Fm->p_FmSp->portsMapping[swPortIndex].profilesBase = 0; return E_OK; } #endif /* (DPAA_VERSION >= 11) */ t_Error FmAllocFmanCtrlEventReg(t_Handle h_Fm, uint8_t *p_EventId) { t_Fm *p_Fm = (t_Fm*)h_Fm; uint8_t i; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_ALLOC_FMAN_CTRL_EVENT_REG; replyLength = sizeof(uint32_t) + sizeof(uint8_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); *p_EventId = *(uint8_t*)(reply.replyBody); return (t_Error)(reply.error); } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); for (i=0;iusedEventRegs[i]) { p_Fm->usedEventRegs[i] = TRUE; *p_EventId = i; break; } if (i==FM_NUM_OF_FMAN_CTRL_EVENT_REGS) RETURN_ERROR(MAJOR, E_BUSY, ("No resource - FMan controller event register.")); return E_OK; } void FmFreeFmanCtrlEventReg(t_Handle h_Fm, uint8_t eventId) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_FREE_FMAN_CTRL_EVENT_REG; msg.msgBody[0] = eventId; err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(eventId), NULL, NULL, NULL, NULL); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); return; } else if (p_Fm->guestId != NCSW_MASTER_ID) { REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); return; } ((t_Fm*)h_Fm)->usedEventRegs[eventId] = FALSE; } void FmSetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, uint32_t enableEvents) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->p_FmFpmRegs && p_Fm->h_IpcSessions[0]) { t_FmIpcFmanEvents fmanCtrl; t_Error err; t_FmIpcMsg msg; fmanCtrl.eventRegId = eventRegId; fmanCtrl.enableEvents = enableEvents; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_SET_FMAN_CTRL_EVENTS_ENABLE; memcpy(msg.msgBody, &fmanCtrl, sizeof(fmanCtrl)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(fmanCtrl), NULL, NULL, NULL, NULL); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); return; } else if (!p_Fm->p_FmFpmRegs) { REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); return; } ASSERT_COND(eventRegId < FM_NUM_OF_FMAN_CTRL_EVENT_REGS); fman_set_ctrl_intr(fpm_rg, eventRegId, enableEvents); } uint32_t FmGetFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->p_FmFpmRegs && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength, ctrlIntr; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_FMAN_CTRL_EVENTS_ENABLE; msg.msgBody[0] = eventRegId; replyLength = sizeof(uint32_t) + sizeof(uint32_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(eventRegId), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) { REPORT_ERROR(MINOR, err, NO_MSG); return 0; } if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) { REPORT_ERROR(MINOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return 0; } memcpy((uint8_t*)&ctrlIntr, reply.replyBody, sizeof(uint32_t)); return ctrlIntr; } else if (!p_Fm->p_FmFpmRegs) { REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); return 0; } return fman_get_ctrl_intr(fpm_rg, eventRegId); } void FmRegisterIntr(t_Handle h_Fm, e_FmEventModules module, uint8_t modId, e_FmIntrType intrType, void (*f_Isr) (t_Handle h_Arg), t_Handle h_Arg) { t_Fm *p_Fm = (t_Fm*)h_Fm; int event = 0; ASSERT_COND(h_Fm); GET_FM_MODULE_EVENT(module, modId, intrType, event); ASSERT_COND(event < e_FM_EV_DUMMY_LAST); /* register in local FM structure */ p_Fm->intrMng[event].f_Isr = f_Isr; p_Fm->intrMng[event].h_SrcHandle = h_Arg; if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->h_IpcSessions[0]) { t_FmIpcRegisterIntr fmIpcRegisterIntr; t_Error err; t_FmIpcMsg msg; /* register in Master FM structure */ fmIpcRegisterIntr.event = (uint32_t)event; fmIpcRegisterIntr.guestId = p_Fm->guestId; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_REGISTER_INTR; memcpy(msg.msgBody, &fmIpcRegisterIntr, sizeof(fmIpcRegisterIntr)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(fmIpcRegisterIntr), NULL, NULL, NULL, NULL); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); } else if (p_Fm->guestId != NCSW_MASTER_ID) REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); } void FmUnregisterIntr(t_Handle h_Fm, e_FmEventModules module, uint8_t modId, e_FmIntrType intrType) { t_Fm *p_Fm = (t_Fm*)h_Fm; int event = 0; ASSERT_COND(h_Fm); GET_FM_MODULE_EVENT(module, modId,intrType, event); ASSERT_COND(event < e_FM_EV_DUMMY_LAST); p_Fm->intrMng[event].f_Isr = UnimplementedIsr; p_Fm->intrMng[event].h_SrcHandle = NULL; } void FmRegisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId, void (*f_Isr) (t_Handle h_Arg, uint32_t event), t_Handle h_Arg) { t_Fm *p_Fm = (t_Fm*)h_Fm; ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) { REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); return; } p_Fm->fmanCtrlIntr[eventRegId].f_Isr = f_Isr; p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = h_Arg; } void FmUnregisterFmanCtrlIntr(t_Handle h_Fm, uint8_t eventRegId) { t_Fm *p_Fm = (t_Fm*)h_Fm; ASSERT_COND(eventRegIdguestId != NCSW_MASTER_ID) { REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("FM in guest-mode")); return; } p_Fm->fmanCtrlIntr[eventRegId].f_Isr = UnimplementedFmanCtrlIsr; p_Fm->fmanCtrlIntr[eventRegId].h_SrcHandle = NULL; } void FmRegisterPcd(t_Handle h_Fm, t_Handle h_FmPcd) { t_Fm *p_Fm = (t_Fm*)h_Fm; if (p_Fm->h_Pcd) REPORT_ERROR(MAJOR, E_ALREADY_EXISTS, ("PCD already set")); p_Fm->h_Pcd = h_FmPcd; } void FmUnregisterPcd(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; if (!p_Fm->h_Pcd) REPORT_ERROR(MAJOR, E_NOT_FOUND, ("PCD handle!")); p_Fm->h_Pcd = NULL; } t_Handle FmGetPcdHandle(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; return p_Fm->h_Pcd; } uint8_t FmGetId(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0xff); return p_Fm->p_FmStateStruct->fmId; } t_Error FmSetNumOfRiscsPerPort(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t numOfFmanCtrls, t_FmFmanCtrl orFmanCtrl) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((numOfFmanCtrls > 0) && (numOfFmanCtrls < 3)) , E_INVALID_HANDLE); fpm_rg = p_Fm->p_FmFpmRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->p_FmFpmRegs && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcPortNumOfFmanCtrls params; t_FmIpcMsg msg; memset(&msg, 0, sizeof(msg)); params.hardwarePortId = hardwarePortId; params.numOfFmanCtrls = numOfFmanCtrls; params.orFmanCtrl = orFmanCtrl; msg.msgId = FM_SET_NUM_OF_FMAN_CTRL; memcpy(msg.msgBody, ¶ms, sizeof(params)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) +sizeof(params), NULL, NULL, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); return E_OK; } else if (!p_Fm->p_FmFpmRegs) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); fman_set_num_of_riscs_per_port(fpm_rg, hardwarePortId, numOfFmanCtrls, orFmanCtrl); return E_OK; } t_Error FmGetSetPortParams(t_Handle h_Fm, t_FmInterModulePortInitParams *p_PortParams) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err; uint32_t intFlags; uint8_t hardwarePortId = p_PortParams->hardwarePortId, macId; struct fman_rg fman_rg; fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { t_FmIpcPortInInitParams portInParams; t_FmIpcPortOutInitParams portOutParams; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; portInParams.hardwarePortId = p_PortParams->hardwarePortId; portInParams.enumPortType = (uint32_t)p_PortParams->portType; portInParams.boolIndependentMode= (uint8_t)p_PortParams->independentMode; portInParams.liodnOffset = p_PortParams->liodnOffset; portInParams.numOfTasks = p_PortParams->numOfTasks; portInParams.numOfExtraTasks = p_PortParams->numOfExtraTasks; portInParams.numOfOpenDmas = p_PortParams->numOfOpenDmas; portInParams.numOfExtraOpenDmas = p_PortParams->numOfExtraOpenDmas; portInParams.sizeOfFifo = p_PortParams->sizeOfFifo; portInParams.extraSizeOfFifo = p_PortParams->extraSizeOfFifo; portInParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; portInParams.maxFrameLength = p_PortParams->maxFrameLength; portInParams.liodnBase = p_PortParams->liodnBase; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_SET_PORT_PARAMS; memcpy(msg.msgBody, &portInParams, sizeof(portInParams)); replyLength = (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams)); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) +sizeof(portInParams), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcPortOutInitParams))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); memcpy((uint8_t*)&portOutParams, reply.replyBody, sizeof(t_FmIpcPortOutInitParams)); p_PortParams->fmMuramPhysBaseAddr.high = portOutParams.ipcPhysAddr.high; p_PortParams->fmMuramPhysBaseAddr.low = portOutParams.ipcPhysAddr.low; p_PortParams->numOfTasks = portOutParams.numOfTasks; p_PortParams->numOfExtraTasks = portOutParams.numOfExtraTasks; p_PortParams->numOfOpenDmas = portOutParams.numOfOpenDmas; p_PortParams->numOfExtraOpenDmas = portOutParams.numOfExtraOpenDmas; p_PortParams->sizeOfFifo = portOutParams.sizeOfFifo; p_PortParams->extraSizeOfFifo = portOutParams.extraSizeOfFifo; return (t_Error)(reply.error); } ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); if (p_PortParams->independentMode) { /* set port parameters */ p_Fm->independentMode = p_PortParams->independentMode; /* disable dispatch limit */ fman_qmi_disable_dispatch_limit(fman_rg.fpm_rg); } if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) { if (p_Fm->hcPortInitialized) { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Only one host command port is allowed.")); } else p_Fm->hcPortInitialized = TRUE; } p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = p_PortParams->portType; err = FmSetNumOfTasks(p_Fm, hardwarePortId, &p_PortParams->numOfTasks, &p_PortParams->numOfExtraTasks, TRUE); if (err) { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MAJOR, err, NO_MSG); } #ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) #endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) /* for transmit & O/H ports */ { uint8_t enqTh; uint8_t deqTh; /* update qmi ENQ/DEQ threshold */ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums += p_PortParams->deqPipelineDepth; enqTh = fman_get_qmi_enq_th(fman_rg.qmi_rg); /* if enqTh is too big, we reduce it to the max value that is still OK */ if (enqTh >= (QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums)) { enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); fman_set_qmi_enq_th(fman_rg.qmi_rg, enqTh); } deqTh = fman_get_qmi_deq_th(fman_rg.qmi_rg); /* if deqTh is too small, we enlarge it to the min value that is still OK. deqTh may not be larger than 63 (QMI_MAX_NUM_OF_TNUMS-1). */ if ((deqTh <= p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums) && (deqTh < QMI_MAX_NUM_OF_TNUMS-1)) { deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); fman_set_qmi_deq_th(fman_rg.qmi_rg, deqTh); } } #ifdef FM_LOW_END_RESTRICTION if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) { if (p_Fm->p_FmStateStruct->lowEndRestriction) { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("OP #0 cannot work with Tx Port #1.")); } else p_Fm->p_FmStateStruct->lowEndRestriction = TRUE; } #endif /* FM_LOW_END_RESTRICTION */ err = FmSetSizeOfFifo(p_Fm, hardwarePortId, &p_PortParams->sizeOfFifo, &p_PortParams->extraSizeOfFifo, TRUE); if (err) { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MAJOR, err, NO_MSG); } err = FmSetNumOfOpenDmas(p_Fm, hardwarePortId, &p_PortParams->numOfOpenDmas, &p_PortParams->numOfExtraOpenDmas, TRUE); if (err) { XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); RETURN_ERROR(MAJOR, err, NO_MSG); } fman_set_liodn_per_port(&fman_rg, hardwarePortId, p_PortParams->liodnBase, p_PortParams->liodnOffset); if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) fman_set_order_restoration_per_port(fman_rg.fpm_rg, hardwarePortId, p_PortParams->independentMode, !!((p_PortParams->portType==e_FM_PORT_TYPE_RX) || (p_PortParams->portType==e_FM_PORT_TYPE_RX_10G))); HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); #if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) { ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId]) p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = p_PortParams->maxFrameLength; else RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); } else #endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || (p_PortParams->portType == e_FM_PORT_TYPE_RX)) { ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); if (p_PortParams->maxFrameLength >= p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId]) p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = p_PortParams->maxFrameLength; else RETURN_ERROR(MINOR, E_INVALID_VALUE, ("Port maxFrameLength is smaller than MAC current MTU")); } FmGetPhysicalMuramBase(p_Fm, &p_PortParams->fmMuramPhysBaseAddr); XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); return E_OK; } void FmFreePortParams(t_Handle h_Fm,t_FmInterModulePortFreeParams *p_PortParams) { t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t intFlags; uint8_t hardwarePortId = p_PortParams->hardwarePortId; uint8_t numOfTasks, numOfDmas, macId; uint16_t sizeOfFifo; t_Error err; t_FmIpcPortFreeParams portParams; t_FmIpcMsg msg; struct fman_qmi_regs *qmi_rg = p_Fm->p_FmQmiRegs; struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { portParams.hardwarePortId = p_PortParams->hardwarePortId; portParams.enumPortType = (uint32_t)p_PortParams->portType; portParams.deqPipelineDepth = p_PortParams->deqPipelineDepth; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_FREE_PORT; memcpy(msg.msgBody, &portParams, sizeof(portParams)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(portParams), NULL, NULL, NULL, NULL); if (err != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); return; } ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); intFlags = XX_LockIntrSpinlock(p_Fm->h_Spinlock); if (p_PortParams->portType == e_FM_PORT_TYPE_OH_HOST_COMMAND) { ASSERT_COND(p_Fm->hcPortInitialized); p_Fm->hcPortInitialized = FALSE; } p_Fm->p_FmStateStruct->portsTypes[hardwarePortId] = e_FM_PORT_TYPE_DUMMY; /* free numOfTasks */ numOfTasks = fman_get_num_of_tasks(bmi_rg, hardwarePortId); ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= numOfTasks); p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= numOfTasks; /* free numOfOpenDmas */ numOfDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId); ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= numOfDmas); p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= numOfDmas; #ifdef FM_HAS_TOTAL_DMAS if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) { /* update total num of DMA's with committed number of open DMAS, and max uncommitted pool. */ fman_set_num_of_open_dmas(bmi_rg, hardwarePortId, 1, 0, (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize)); } #endif /* FM_HAS_TOTAL_DMAS */ /* free sizeOfFifo */ sizeOfFifo = fman_get_size_of_fifo(bmi_rg, hardwarePortId); ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= (sizeOfFifo * BMI_FIFO_UNITS)); p_Fm->p_FmStateStruct->accumulatedFifoSize -= (sizeOfFifo * BMI_FIFO_UNITS); #ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) #endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ if ((p_PortParams->portType != e_FM_PORT_TYPE_RX) && (p_PortParams->portType != e_FM_PORT_TYPE_RX_10G)) /* for transmit & O/H ports */ { uint8_t enqTh; uint8_t deqTh; /* update qmi ENQ/DEQ threshold */ p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums -= p_PortParams->deqPipelineDepth; /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, so we can enlarge enqTh */ enqTh = (uint8_t)(QMI_MAX_NUM_OF_TNUMS - p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums - 1); /* p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums is now smaller, so we can reduce deqTh */ deqTh = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfDeqTnums + 1); fman_set_qmi_enq_th(qmi_rg, enqTh); fman_set_qmi_deq_th(qmi_rg, deqTh); } HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); #if defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS) if ((p_PortParams->portType == e_FM_PORT_TYPE_TX_10G) || (p_PortParams->portType == e_FM_PORT_TYPE_RX_10G)) { ASSERT_COND(macId < FM_MAX_NUM_OF_10G_MACS); p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] = 0; } else #endif /* defined(FM_MAX_NUM_OF_10G_MACS) && ... */ if ((p_PortParams->portType == e_FM_PORT_TYPE_TX) || (p_PortParams->portType == e_FM_PORT_TYPE_RX)) { ASSERT_COND(macId < FM_MAX_NUM_OF_1G_MACS); p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] = 0; } #ifdef FM_LOW_END_RESTRICTION if ((hardwarePortId==0x1) || (hardwarePortId==0x29)) p_Fm->p_FmStateStruct->lowEndRestriction = FALSE; #endif /* FM_LOW_END_RESTRICTION */ XX_UnlockIntrSpinlock(p_Fm->h_Spinlock, intFlags); } t_Error FmIsPortStalled(t_Handle h_Fm, uint8_t hardwarePortId, bool *p_IsStalled) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_IS_PORT_STALLED; msg.msgBody[0] = hardwarePortId; replyLength = sizeof(uint32_t) + sizeof(uint8_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(hardwarePortId), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); *p_IsStalled = (bool)!!(*(uint8_t*)(reply.replyBody)); return (t_Error)(reply.error); } else if (!p_Fm->baseAddr) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); *p_IsStalled = fman_is_port_stalled(fpm_rg, hardwarePortId); return E_OK; } t_Error FmResumeStalledPort(t_Handle h_Fm, uint8_t hardwarePortId) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err; bool isStalled; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_RESUME_STALLED_PORT; msg.msgBody[0] = hardwarePortId; replyLength = sizeof(uint32_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(hardwarePortId), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } else if (!p_Fm->baseAddr) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MINOR, E_NOT_AVAILABLE, ("Not available for this FM revision!")); /* Get port status */ err = FmIsPortStalled(h_Fm, hardwarePortId, &isStalled); if (err) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Can't get port status")); if (!isStalled) return E_OK; fman_resume_stalled_port(fpm_rg, hardwarePortId); return E_OK; } t_Error FmResetMac(t_Handle h_Fm, e_FmMacType type, uint8_t macId) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err; struct fman_fpm_regs *fpm_rg = p_Fm->p_FmFpmRegs; #if (DPAA_VERSION >= 11) if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("FMan MAC reset!")); #endif /*(DPAA_VERSION >= 11)*/ if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcMacParams macParams; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); macParams.id = macId; macParams.enumType = (uint32_t)type; msg.msgId = FM_RESET_MAC; memcpy(msg.msgBody, &macParams, sizeof(macParams)); replyLength = sizeof(uint32_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(macParams), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } else if (!p_Fm->baseAddr) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); err = (t_Error)fman_reset_mac(fpm_rg, macId, !!(type == e_FM_MAC_10G)); if (err == -EBUSY) return ERROR_CODE(E_TIMEOUT); else if (err) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal MAC ID")); return E_OK; } t_Error FmSetMacMaxFrame(t_Handle h_Fm, e_FmMacType type, uint8_t macId, uint16_t mtu) { t_Fm *p_Fm = (t_Fm*)h_Fm; if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->h_IpcSessions[0]) { t_FmIpcMacMaxFrameParams macMaxFrameLengthParams; t_Error err; t_FmIpcMsg msg; memset(&msg, 0, sizeof(msg)); macMaxFrameLengthParams.macParams.id = macId; macMaxFrameLengthParams.macParams.enumType = (uint32_t)type; macMaxFrameLengthParams.maxFrameLength = (uint16_t)mtu; msg.msgId = FM_SET_MAC_MAX_FRAME; memcpy(msg.msgBody, &macMaxFrameLengthParams, sizeof(macMaxFrameLengthParams)); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(macMaxFrameLengthParams), NULL, NULL, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); return E_OK; } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); /* if port is already initialized, check that MaxFrameLength is smaller * or equal to the port's max */ #if (defined(FM_MAX_NUM_OF_10G_MACS) && (FM_MAX_NUM_OF_10G_MACS)) if (type == e_FM_MAC_10G) { if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]) || (p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId] && (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths10G[macId]))) p_Fm->p_FmStateStruct->macMaxFrameLengths10G[macId] = mtu; else RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); } else #else UNUSED(type); #endif /* (defined(FM_MAX_NUM_OF_10G_MACS) && ... */ if ((!p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]) || (p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId] && (mtu <= p_Fm->p_FmStateStruct->portMaxFrameLengths1G[macId]))) p_Fm->p_FmStateStruct->macMaxFrameLengths1G[macId] = mtu; else RETURN_ERROR(MINOR, E_INVALID_VALUE, ("MAC maxFrameLength is larger than Port maxFrameLength")); return E_OK; } uint16_t FmGetClockFreq(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; /* for multicore environment: this depends on the * fact that fmClkFreq was properly initialized at "init". */ return p_Fm->p_FmStateStruct->fmClkFreq; } uint16_t FmGetMacClockFreq(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; return p_Fm->p_FmStateStruct->fmMacClkFreq; } uint32_t FmGetTimeStampScale(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength, timeStamp; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_TIMESTAMP_SCALE; replyLength = sizeof(uint32_t) + sizeof(uint32_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); memcpy((uint8_t*)&timeStamp, reply.replyBody, sizeof(uint32_t)); return timeStamp; } else if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->baseAddr) { if (!(GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_tsc1) & FPM_TS_CTL_EN)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("timestamp is not enabled!")); } else if (p_Fm->guestId != NCSW_MASTER_ID) DBG(WARNING, ("No IPC - can't validate FM if timestamp enabled.")); return p_Fm->p_FmStateStruct->count1MicroBit; } t_Error FmEnableRamsEcc(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); p_Fm->p_FmStateStruct->ramsEccOwners++; p_Fm->p_FmStateStruct->internalCall = TRUE; return FM_EnableRamsEcc(p_Fm); } t_Error FmDisableRamsEcc(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); ASSERT_COND(p_Fm->p_FmStateStruct->ramsEccOwners); p_Fm->p_FmStateStruct->ramsEccOwners--; if (p_Fm->p_FmStateStruct->ramsEccOwners==0) { p_Fm->p_FmStateStruct->internalCall = TRUE; return FM_DisableRamsEcc(p_Fm); } return E_OK; } uint8_t FmGetGuestId(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; return p_Fm->guestId; } bool FmIsMaster(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; return (p_Fm->guestId == NCSW_MASTER_ID); } t_Error FmSetSizeOfFifo(t_Handle h_Fm, uint8_t hardwarePortId, uint32_t *p_SizeOfFifo, uint32_t *p_ExtraSizeOfFifo, bool initialConfig) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_FmIpcPortRsrcParams rsrcParams; t_Error err; struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; uint32_t sizeOfFifo = *p_SizeOfFifo, extraSizeOfFifo = *p_ExtraSizeOfFifo; uint16_t currentVal = 0, currentExtraVal = 0; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; rsrcParams.hardwarePortId = hardwarePortId; rsrcParams.val = sizeOfFifo; rsrcParams.extra = extraSizeOfFifo; rsrcParams.boolInitialConfig = (uint8_t)initialConfig; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_SET_SIZE_OF_FIFO; memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); replyLength = sizeof(uint32_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(rsrcParams), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } else if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->baseAddr) { DBG(WARNING, ("No IPC - can't validate FM total-fifo size.")); fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo); } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("running in guest-mode without neither IPC nor mapped register!")); if (!initialConfig) { /* !initialConfig - runtime change of existing value. * - read the current FIFO and extra FIFO size */ currentExtraVal = fman_get_size_of_extra_fifo(bmi_rg, hardwarePortId); currentVal = fman_get_size_of_fifo(bmi_rg, hardwarePortId); } if (extraSizeOfFifo > currentExtraVal) { if (extraSizeOfFifo && !p_Fm->p_FmStateStruct->extraFifoPoolSize) /* if this is the first time a port requires extraFifoPoolSize, the total extraFifoPoolSize * must be initialized to 1 buffer per port */ p_Fm->p_FmStateStruct->extraFifoPoolSize = FM_MAX_NUM_OF_RX_PORTS*BMI_FIFO_UNITS; p_Fm->p_FmStateStruct->extraFifoPoolSize = MAX(p_Fm->p_FmStateStruct->extraFifoPoolSize, extraSizeOfFifo); } /* check that there are enough uncommitted fifo size */ if ((p_Fm->p_FmStateStruct->accumulatedFifoSize - currentVal + sizeOfFifo) > (p_Fm->p_FmStateStruct->totalFifoSize - p_Fm->p_FmStateStruct->extraFifoPoolSize)){ REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Port request fifo size + accumulated size > total FIFO size:")); RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("port 0x%x requested %d bytes, extra size = %d, accumulated size = %d total size = %d", hardwarePortId, sizeOfFifo, p_Fm->p_FmStateStruct->extraFifoPoolSize, p_Fm->p_FmStateStruct->accumulatedFifoSize, p_Fm->p_FmStateStruct->totalFifoSize)); } else { /* update accumulated */ ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedFifoSize >= currentVal); p_Fm->p_FmStateStruct->accumulatedFifoSize -= currentVal; p_Fm->p_FmStateStruct->accumulatedFifoSize += sizeOfFifo; fman_set_size_of_fifo(bmi_rg, hardwarePortId, sizeOfFifo, extraSizeOfFifo); } return E_OK; } t_Error FmSetNumOfTasks(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t *p_NumOfTasks, uint8_t *p_NumOfExtraTasks, bool initialConfig) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_Error err; struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; uint8_t currentVal = 0, currentExtraVal = 0, numOfTasks = *p_NumOfTasks, numOfExtraTasks = *p_NumOfExtraTasks; ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcPortRsrcParams rsrcParams; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; rsrcParams.hardwarePortId = hardwarePortId; rsrcParams.val = numOfTasks; rsrcParams.extra = numOfExtraTasks; rsrcParams.boolInitialConfig = (uint8_t)initialConfig; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_SET_NUM_OF_TASKS; memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); replyLength = sizeof(uint32_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(rsrcParams), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } else if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->baseAddr) { DBG(WARNING, ("No IPC - can't validate FM total-num-of-tasks.")); fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks); } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("running in guest-mode without neither IPC nor mapped register!")); if (!initialConfig) { /* !initialConfig - runtime change of existing value. * - read the current number of tasks */ currentVal = fman_get_num_of_tasks(bmi_rg, hardwarePortId); currentExtraVal = fman_get_num_extra_tasks(bmi_rg, hardwarePortId); } if (numOfExtraTasks > currentExtraVal) p_Fm->p_FmStateStruct->extraTasksPoolSize = (uint8_t)MAX(p_Fm->p_FmStateStruct->extraTasksPoolSize, numOfExtraTasks); /* check that there are enough uncommitted tasks */ if ((p_Fm->p_FmStateStruct->accumulatedNumOfTasks - currentVal + numOfTasks) > (p_Fm->p_FmStateStruct->totalNumOfTasks - p_Fm->p_FmStateStruct->extraTasksPoolSize)) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested numOfTasks and extra tasks pool for fm%d exceed total numOfTasks.", p_Fm->p_FmStateStruct->fmId)); else { ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfTasks >= currentVal); /* update accumulated */ p_Fm->p_FmStateStruct->accumulatedNumOfTasks -= currentVal; p_Fm->p_FmStateStruct->accumulatedNumOfTasks += numOfTasks; fman_set_num_of_tasks(bmi_rg, hardwarePortId, numOfTasks, numOfExtraTasks); } return E_OK; } t_Error FmSetNumOfOpenDmas(t_Handle h_Fm, uint8_t hardwarePortId, uint8_t *p_NumOfOpenDmas, uint8_t *p_NumOfExtraOpenDmas, bool initialConfig) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_Error err; struct fman_bmi_regs *bmi_rg = p_Fm->p_FmBmiRegs; uint8_t numOfOpenDmas = *p_NumOfOpenDmas, numOfExtraOpenDmas = *p_NumOfExtraOpenDmas; uint8_t totalNumDmas = 0, currentVal = 0, currentExtraVal = 0; ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcPortRsrcParams rsrcParams; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; rsrcParams.hardwarePortId = hardwarePortId; rsrcParams.val = numOfOpenDmas; rsrcParams.extra = numOfExtraOpenDmas; rsrcParams.boolInitialConfig = (uint8_t)initialConfig; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_SET_NUM_OF_OPEN_DMAS; memcpy(msg.msgBody, &rsrcParams, sizeof(rsrcParams)); replyLength = sizeof(uint32_t); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) + sizeof(rsrcParams), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != sizeof(uint32_t)) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return (t_Error)(reply.error); } #ifdef FM_HAS_TOTAL_DMAS else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); #else else if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->baseAddr && (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) { /*DBG(WARNING, ("No IPC - can't validate FM total-num-of-dmas."));*/ if (!numOfOpenDmas) { /* first config without explic it value: Do Nothing - reset value shouldn't be changed, read register for port save */ *p_NumOfOpenDmas = fman_get_num_of_dmas(bmi_rg, hardwarePortId); *p_NumOfExtraOpenDmas = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); } else /* whether it is the first time with explicit value, or runtime "set" - write register */ fman_set_num_of_open_dmas(bmi_rg, hardwarePortId, numOfOpenDmas, numOfExtraOpenDmas, p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize); } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("running in guest-mode without neither IPC nor mapped register!")); #endif /* FM_HAS_TOTAL_DMAS */ if (!initialConfig) { /* !initialConfig - runtime change of existing value. * - read the current number of open Dma's */ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId); } #ifdef FM_NO_GUARANTEED_RESET_VALUES /* it's illegal to be in a state where this is not the first set and no value is specified */ ASSERT_COND(initialConfig || numOfOpenDmas); if (!numOfOpenDmas) { /* !numOfOpenDmas - first configuration according to values in regs. * - read the current number of open Dma's */ currentExtraVal = fman_get_num_extra_dmas(bmi_rg, hardwarePortId); currentVal = fman_get_num_of_dmas(bmi_rg, hardwarePortId); /* This is the first configuration and user did not specify value (!numOfOpenDmas), * reset values will be used and we just save these values for resource management */ p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, currentExtraVal); p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += currentVal; *p_NumOfOpenDmas = currentVal; *p_NumOfExtraOpenDmas = currentExtraVal; return E_OK; } #endif /* FM_NO_GUARANTEED_RESET_VALUES */ if (numOfExtraOpenDmas > currentExtraVal) p_Fm->p_FmStateStruct->extraOpenDmasPoolSize = (uint8_t)MAX(p_Fm->p_FmStateStruct->extraOpenDmasPoolSize, numOfExtraOpenDmas); #ifdef FM_HAS_TOTAL_DMAS if ((p_Fm->p_FmStateStruct->revInfo.majorRev < 6) && (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > p_Fm->p_FmStateStruct->maxNumOfOpenDmas)) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested numOfOpenDmas for fm%d exceeds total numOfOpenDmas.", p_Fm->p_FmStateStruct->fmId)); #else if ((p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) && #ifdef FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 !((p_Fm->p_FmStateStruct->revInfo.majorRev == 6) && (p_Fm->p_FmStateStruct->revInfo.minorRev == 0)) && #endif /* FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 */ (p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas - currentVal + numOfOpenDmas > DMA_THRESH_MAX_COMMQ + 1)) RETURN_ERROR(MAJOR, E_NOT_AVAILABLE, ("Requested numOfOpenDmas for fm%d exceeds DMA Command queue (%d)", p_Fm->p_FmStateStruct->fmId, DMA_THRESH_MAX_COMMQ+1)); #endif /* FM_HAS_TOTAL_DMAS */ else { ASSERT_COND(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas >= currentVal); /* update acummulated */ p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas -= currentVal; p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas += numOfOpenDmas; #ifdef FM_HAS_TOTAL_DMAS if (p_Fm->p_FmStateStruct->revInfo.majorRev < 6) totalNumDmas = (uint8_t)(p_Fm->p_FmStateStruct->accumulatedNumOfOpenDmas + p_Fm->p_FmStateStruct->extraOpenDmasPoolSize); #endif /* FM_HAS_TOTAL_DMAS */ fman_set_num_of_open_dmas(bmi_rg, hardwarePortId, numOfOpenDmas, numOfExtraOpenDmas, totalNumDmas); } return E_OK; } #if (DPAA_VERSION >= 11) t_Error FmVSPCheckRelativeProfile(t_Handle h_Fm, e_FmPortType portType, uint8_t portId, uint16_t relativeProfile) { t_Fm *p_Fm; t_FmSp *p_FmPcdSp; uint8_t swPortIndex=0, hardwarePortId; ASSERT_COND(h_Fm); p_Fm = (t_Fm*)h_Fm; hardwarePortId = SwPortIdToHwPortId(portType, portId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); ASSERT_COND(hardwarePortId); HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); p_FmPcdSp = p_Fm->p_FmSp; ASSERT_COND(p_FmPcdSp); if (!p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) RETURN_ERROR(MAJOR, E_INVALID_STATE , ("Port has no allocated profiles")); if (relativeProfile >= p_FmPcdSp->portsMapping[swPortIndex].numOfProfiles) RETURN_ERROR(MAJOR, E_NOT_IN_RANGE , ("Profile id is out of range")); return E_OK; } t_Error FmVSPGetAbsoluteProfileId(t_Handle h_Fm, e_FmPortType portType, uint8_t portId, uint16_t relativeProfile, uint16_t *p_AbsoluteId) { t_Fm *p_Fm; t_FmSp *p_FmPcdSp; uint8_t swPortIndex=0, hardwarePortId; t_Error err; ASSERT_COND(h_Fm); p_Fm = (t_Fm*)h_Fm; err = FmVSPCheckRelativeProfile(h_Fm, portType, portId, relativeProfile); if (err != E_OK) return err; hardwarePortId = SwPortIdToHwPortId(portType, portId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); ASSERT_COND(hardwarePortId); HW_PORT_ID_TO_SW_PORT_INDX(swPortIndex, hardwarePortId); p_FmPcdSp = p_Fm->p_FmSp; ASSERT_COND(p_FmPcdSp); *p_AbsoluteId = (uint16_t)(p_FmPcdSp->portsMapping[swPortIndex].profilesBase + relativeProfile); return E_OK; } #endif /* (DPAA_VERSION >= 11) */ static t_Error InitFmDma(t_Fm *p_Fm) { t_Error err; err = (t_Error)fman_dma_init(p_Fm->p_FmDmaRegs, p_Fm->p_FmDriverParam); if (err != E_OK) return err; /* Allocate MURAM for CAM */ p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY), DMA_CAM_ALIGN)); if (!p_Fm->camBaseAddr) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), 0, (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*DMA_CAM_SIZEOF_ENTRY)); if (p_Fm->p_FmStateStruct->revInfo.majorRev == 2) { FM_MURAM_FreeMem(p_Fm->h_FmMuram, UINT_TO_PTR(p_Fm->camBaseAddr)); p_Fm->camBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128), 64)); if (!p_Fm->camBaseAddr) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for DMA CAM failed")); WRITE_BLOCK(UINT_TO_PTR(p_Fm->camBaseAddr), 0, (uint32_t)(p_Fm->p_FmDriverParam->dma_cam_num_of_entries*72 + 128)); switch(p_Fm->p_FmDriverParam->dma_cam_num_of_entries) { case (8): WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xff000000); break; case (16): WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffff0000); break; case (24): WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffff00); break; case (32): WRITE_UINT32(*(uint32_t*)p_Fm->camBaseAddr, 0xffffffff); break; default: RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("wrong dma_cam_num_of_entries")); } } p_Fm->p_FmDriverParam->cam_base_addr = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->camBaseAddr)) - p_Fm->fmMuramPhysBaseAddr); return E_OK; } static t_Error InitFmFpm(t_Fm *p_Fm) { return (t_Error)fman_fpm_init(p_Fm->p_FmFpmRegs, p_Fm->p_FmDriverParam); } static t_Error InitFmBmi(t_Fm *p_Fm) { return (t_Error)fman_bmi_init(p_Fm->p_FmBmiRegs, p_Fm->p_FmDriverParam); } static t_Error InitFmQmi(t_Fm *p_Fm) { return (t_Error)fman_qmi_init(p_Fm->p_FmQmiRegs, p_Fm->p_FmDriverParam); } static t_Error InitGuestMode(t_Fm *p_Fm) { t_Error err = E_OK; int i; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; ASSERT_COND(p_Fm); ASSERT_COND(p_Fm->guestId != NCSW_MASTER_ID); /* build the FM guest partition IPC address */ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, p_Fm->guestId) != (p_Fm->guestId<10 ? 6:7)) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); /* build the FM master partition IPC address */ memset(p_Fm->fmIpcHandlerModuleName, 0, (sizeof(char)) * MODULE_NAME_SIZE); if (Sprint (p_Fm->fmIpcHandlerModuleName[0], "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; p_Fm->h_IpcSessions[0] = XX_IpcInitSession(p_Fm->fmIpcHandlerModuleName[0], p_Fm->fmModuleName); if (p_Fm->h_IpcSessions[0]) { uint8_t isMasterAlive; t_FmIpcParams ipcParams; err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmGuestHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); if (err) RETURN_ERROR(MAJOR, err, NO_MSG); memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_MASTER_IS_ALIVE; msg.msgBody[0] = p_Fm->guestId; replyLength = sizeof(uint32_t) + sizeof(uint8_t); do { blockingFlag = TRUE; if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId)+sizeof(p_Fm->guestId), (uint8_t*)&reply, &replyLength, IpcMsgCompletionCB, p_Fm)) != E_OK) REPORT_ERROR(MINOR, err, NO_MSG); while (blockingFlag) ; if (replyLength != (sizeof(uint32_t) + sizeof(uint8_t))) REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); isMasterAlive = *(uint8_t*)(reply.replyBody); } while (!isMasterAlive); /* read FM parameters and save */ memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_PARAMS; replyLength = sizeof(uint32_t) + sizeof(t_FmIpcParams); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcParams))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); memcpy((uint8_t*)&ipcParams, reply.replyBody, sizeof(t_FmIpcParams)); p_Fm->p_FmStateStruct->fmClkFreq = ipcParams.fmClkFreq; p_Fm->p_FmStateStruct->fmMacClkFreq = ipcParams.fmMacClkFreq; p_Fm->p_FmStateStruct->revInfo.majorRev = ipcParams.majorRev; p_Fm->p_FmStateStruct->revInfo.minorRev = ipcParams.minorRev; } else { DBG(WARNING, ("FM Guest mode - without IPC")); if (!p_Fm->p_FmStateStruct->fmClkFreq) RETURN_ERROR(MAJOR, E_INVALID_STATE, ("No fmClkFreq configured for guest without IPC")); if (p_Fm->baseAddr) { fman_get_revision(p_Fm->p_FmFpmRegs, &p_Fm->p_FmStateStruct->revInfo.majorRev, &p_Fm->p_FmStateStruct->revInfo.minorRev); } } #if (DPAA_VERSION >= 11) p_Fm->partVSPBase = AllocVSPsForPartition(p_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) DBG(WARNING, ("partition VSPs allocation is FAILED")); #endif /* (DPAA_VERSION >= 11) */ /* General FM driver initialization */ if (p_Fm->baseAddr) p_Fm->fmMuramPhysBaseAddr = (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); XX_Free(p_Fm->p_FmDriverParam); p_Fm->p_FmDriverParam = NULL; if ((p_Fm->guestId == NCSW_MASTER_ID) || (p_Fm->h_IpcSessions[0])) { FM_DisableRamsEcc(p_Fm); FmMuramClear(p_Fm->h_FmMuram); FM_EnableRamsEcc(p_Fm); } return E_OK; } static __inline__ enum fman_exceptions FmanExceptionTrans(e_FmExceptions exception) { switch (exception) { case e_FM_EX_DMA_BUS_ERROR: return E_FMAN_EX_DMA_BUS_ERROR; case e_FM_EX_DMA_READ_ECC: return E_FMAN_EX_DMA_READ_ECC; case e_FM_EX_DMA_SYSTEM_WRITE_ECC: return E_FMAN_EX_DMA_SYSTEM_WRITE_ECC; case e_FM_EX_DMA_FM_WRITE_ECC: return E_FMAN_EX_DMA_FM_WRITE_ECC; case e_FM_EX_FPM_STALL_ON_TASKS: return E_FMAN_EX_FPM_STALL_ON_TASKS; case e_FM_EX_FPM_SINGLE_ECC: return E_FMAN_EX_FPM_SINGLE_ECC; case e_FM_EX_FPM_DOUBLE_ECC: return E_FMAN_EX_FPM_DOUBLE_ECC; case e_FM_EX_QMI_SINGLE_ECC: return E_FMAN_EX_QMI_SINGLE_ECC; case e_FM_EX_QMI_DOUBLE_ECC: return E_FMAN_EX_QMI_DOUBLE_ECC; case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: return E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; case e_FM_EX_BMI_LIST_RAM_ECC: return E_FMAN_EX_BMI_LIST_RAM_ECC; case e_FM_EX_BMI_STORAGE_PROFILE_ECC: return E_FMAN_EX_BMI_STORAGE_PROFILE_ECC; case e_FM_EX_BMI_STATISTICS_RAM_ECC: return E_FMAN_EX_BMI_STATISTICS_RAM_ECC; case e_FM_EX_BMI_DISPATCH_RAM_ECC: return E_FMAN_EX_BMI_DISPATCH_RAM_ECC; case e_FM_EX_IRAM_ECC: return E_FMAN_EX_IRAM_ECC; case e_FM_EX_MURAM_ECC: return E_FMAN_EX_MURAM_ECC; default: return E_FMAN_EX_DMA_BUS_ERROR; } } uint8_t SwPortIdToHwPortId(e_FmPortType type, uint8_t relativePortId, uint8_t majorRev, uint8_t minorRev) { switch (type) { case (e_FM_PORT_TYPE_OH_OFFLINE_PARSING): case (e_FM_PORT_TYPE_OH_HOST_COMMAND): CHECK_PORT_ID_OH_PORTS(relativePortId); return (uint8_t)(BASE_OH_PORTID + (relativePortId)); case (e_FM_PORT_TYPE_RX): CHECK_PORT_ID_1G_RX_PORTS(relativePortId); return (uint8_t)(BASE_1G_RX_PORTID + (relativePortId)); case (e_FM_PORT_TYPE_RX_10G): /* The 10G port in T1024 (FMan Version 6.4) is the first port. * This is the reason why the 1G port offset is used. */ if (majorRev == 6 && minorRev == 4) { CHECK_PORT_ID_1G_RX_PORTS(relativePortId); return (uint8_t)(BASE_1G_RX_PORTID + (relativePortId)); } else { CHECK_PORT_ID_10G_RX_PORTS(relativePortId); return (uint8_t)(BASE_10G_RX_PORTID + (relativePortId)); } case (e_FM_PORT_TYPE_TX): CHECK_PORT_ID_1G_TX_PORTS(relativePortId); return (uint8_t)(BASE_1G_TX_PORTID + (relativePortId)); case (e_FM_PORT_TYPE_TX_10G): /* The 10G port in T1024 (FMan Version 6.4) is the first port. * This is the reason why the 1G port offset is used. */ if (majorRev == 6 && minorRev == 4) { CHECK_PORT_ID_1G_TX_PORTS(relativePortId); return (uint8_t)(BASE_1G_TX_PORTID + (relativePortId)); } else { CHECK_PORT_ID_10G_TX_PORTS(relativePortId); return (uint8_t)(BASE_10G_TX_PORTID + (relativePortId)); } default: REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("Illegal port type")); return 0; } } #if (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) t_Error FmDumpPortRegs (t_Handle h_Fm, uint8_t hardwarePortId) { t_Fm *p_Fm = (t_Fm *)h_Fm; DECLARE_DUMP; ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) || p_Fm->baseAddr), E_INVALID_OPERATION); DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], ("fmbm_pp for port %u", (hardwarePortId))); DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pp[hardwarePortId-1], sizeof(uint32_t)); DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], ("fmbm_pfs for port %u", (hardwarePortId ))); DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_pfs[hardwarePortId-1], sizeof(uint32_t)); DUMP_TITLE(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], ("fmbm_spliodn for port %u", (hardwarePortId))); DUMP_MEMORY(&p_Fm->p_FmBmiRegs->fmbm_spliodn[hardwarePortId-1], sizeof(uint32_t)); DUMP_TITLE(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], ("fmfp_ps for port %u", (hardwarePortId))); DUMP_MEMORY(&p_Fm->p_FmFpmRegs->fmfp_ps[hardwarePortId], sizeof(uint32_t)); DUMP_TITLE(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], ("fmdmplr for port %u", (hardwarePortId))); DUMP_MEMORY(&p_Fm->p_FmDmaRegs->fmdmplr[hardwarePortId/2], sizeof(uint32_t)); return E_OK; } #endif /* (defined(DEBUG_ERRORS) && (DEBUG_ERRORS > 0)) */ /*****************************************************************************/ /* API Init unit functions */ /*****************************************************************************/ t_Handle FM_Config(t_FmParams *p_FmParam) { t_Fm *p_Fm; uint8_t i; uintptr_t baseAddr; SANITY_CHECK_RETURN_VALUE(p_FmParam, E_NULL_POINTER, NULL); SANITY_CHECK_RETURN_VALUE(((p_FmParam->firmware.p_Code && p_FmParam->firmware.size) || (!p_FmParam->firmware.p_Code && !p_FmParam->firmware.size)), E_INVALID_VALUE, NULL); baseAddr = p_FmParam->baseAddr; /* Allocate FM structure */ p_Fm = (t_Fm *) XX_Malloc(sizeof(t_Fm)); if (!p_Fm) { REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver structure")); return NULL; } memset(p_Fm, 0, sizeof(t_Fm)); p_Fm->p_FmStateStruct = (t_FmStateStruct *) XX_Malloc(sizeof(t_FmStateStruct)); if (!p_Fm->p_FmStateStruct) { XX_Free(p_Fm); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM Status structure")); return NULL; } memset(p_Fm->p_FmStateStruct, 0, sizeof(t_FmStateStruct)); /* Initialize FM parameters which will be kept by the driver */ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; p_Fm->guestId = p_FmParam->guestId; for (i=0; ip_FmStateStruct->portsTypes[i] = e_FM_PORT_TYPE_DUMMY; /* Allocate the FM driver's parameters structure */ p_Fm->p_FmDriverParam = (struct fman_cfg *)XX_Malloc(sizeof(struct fman_cfg)); if (!p_Fm->p_FmDriverParam) { XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM driver parameters")); return NULL; } memset(p_Fm->p_FmDriverParam, 0, sizeof(struct fman_cfg)); #if (DPAA_VERSION >= 11) p_Fm->p_FmSp = (t_FmSp *)XX_Malloc(sizeof(t_FmSp)); if (!p_Fm->p_FmSp) { XX_Free(p_Fm->p_FmDriverParam); XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("allocation for internal data structure failed")); return NULL; } memset(p_Fm->p_FmSp, 0, sizeof(t_FmSp)); for (i=0; ip_FmSp->profiles[i].profilesMng.ownerId = (uint8_t)ILLEGAL_BASE; #endif /* (DPAA_VERSION >= 11) */ /* Initialize FM parameters which will be kept by the driver */ p_Fm->p_FmStateStruct->fmId = p_FmParam->fmId; p_Fm->h_FmMuram = p_FmParam->h_FmMuram; p_Fm->h_App = p_FmParam->h_App; p_Fm->p_FmStateStruct->fmClkFreq = p_FmParam->fmClkFreq; p_Fm->p_FmStateStruct->fmMacClkFreq = p_FmParam->fmClkFreq / ((!p_FmParam->fmMacClkRatio)? 2: p_FmParam->fmMacClkRatio); p_Fm->f_Exception = p_FmParam->f_Exception; p_Fm->f_BusError = p_FmParam->f_BusError; p_Fm->p_FmFpmRegs = (struct fman_fpm_regs *)UINT_TO_PTR(baseAddr + FM_MM_FPM); p_Fm->p_FmBmiRegs = (struct fman_bmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI); p_Fm->p_FmQmiRegs = (struct fman_qmi_regs *)UINT_TO_PTR(baseAddr + FM_MM_QMI); p_Fm->p_FmDmaRegs = (struct fman_dma_regs *)UINT_TO_PTR(baseAddr + FM_MM_DMA); p_Fm->p_FmRegs = (struct fman_regs *)UINT_TO_PTR(baseAddr + FM_MM_BMI); p_Fm->baseAddr = baseAddr; p_Fm->p_FmStateStruct->irq = p_FmParam->irq; p_Fm->p_FmStateStruct->errIrq = p_FmParam->errIrq; p_Fm->hcPortInitialized = FALSE; p_Fm->independentMode = FALSE; p_Fm->h_Spinlock = XX_InitSpinlock(); if (!p_Fm->h_Spinlock) { XX_Free(p_Fm->p_FmDriverParam); XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm); REPORT_ERROR(MAJOR, E_INVALID_STATE, ("can't allocate spinlock!")); return NULL; } #if (DPAA_VERSION >= 11) p_Fm->partVSPBase = p_FmParam->partVSPBase; p_Fm->partNumOfVSPs = p_FmParam->partNumOfVSPs; p_Fm->vspBaseAddr = p_FmParam->vspBaseAddr; #endif /* (DPAA_VERSION >= 11) */ fman_defconfig(p_Fm->p_FmDriverParam, !!(p_Fm->guestId == NCSW_MASTER_ID)); /* overide macros dependent parameters */ #ifdef FM_PEDANTIC_DMA p_Fm->p_FmDriverParam->pedantic_dma = TRUE; p_Fm->p_FmDriverParam->dma_aid_override = TRUE; #endif /* FM_PEDANTIC_DMA */ #ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT p_Fm->p_FmDriverParam->qmi_deq_option_support = TRUE; #endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; p_Fm->p_FmStateStruct->extraFifoPoolSize = 0; p_Fm->p_FmStateStruct->exceptions = DEFAULT_exceptions; p_Fm->resetOnInit = DEFAULT_resetOnInit; p_Fm->fwVerify = DEFAULT_VerifyUcode; p_Fm->firmware.size = p_FmParam->firmware.size; if (p_Fm->firmware.size) { p_Fm->firmware.p_Code = (uint32_t *)XX_Malloc(p_Fm->firmware.size); if (!p_Fm->firmware.p_Code) { XX_FreeSpinlock(p_Fm->h_Spinlock); XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm->p_FmDriverParam); XX_Free(p_Fm); REPORT_ERROR(MAJOR, E_NO_MEMORY, ("FM firmware code")); return NULL; } memcpy(p_Fm->firmware.p_Code, p_FmParam->firmware.p_Code ,p_Fm->firmware.size); } if (p_Fm->guestId != NCSW_MASTER_ID) return p_Fm; /* read revision */ /* Chip dependent, will be configured in Init */ fman_get_revision(p_Fm->p_FmFpmRegs, &p_Fm->p_FmStateStruct->revInfo.majorRev, &p_Fm->p_FmStateStruct->revInfo.minorRev); #ifdef FM_AID_MODE_NO_TNUM_SW005 if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) p_Fm->p_FmDriverParam->dma_aid_mode = e_FM_DMA_AID_OUT_PORT_ID; #endif /* FM_AID_MODE_NO_TNUM_SW005 */ #ifndef FM_QMI_NO_DEQ_OPTIONS_SUPPORT if (p_Fm->p_FmStateStruct->revInfo.majorRev != 4) p_Fm->p_FmDriverParam->qmi_def_tnums_thresh = QMI_DEF_TNUMS_THRESH; #endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */ p_Fm->p_FmStateStruct->totalFifoSize = 0; p_Fm->p_FmStateStruct->totalNumOfTasks = DEFAULT_totalNumOfTasks(p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); #ifdef FM_HAS_TOTAL_DMAS p_Fm->p_FmStateStruct->maxNumOfOpenDmas = BMI_MAX_NUM_OF_DMAS; #endif /* FM_HAS_TOTAL_DMAS */ #if (DPAA_VERSION < 11) p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = DEFAULT_dmaCommQLow; p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = DEFAULT_dmaCommQHigh; p_Fm->p_FmDriverParam->dma_cam_num_of_entries = DEFAULT_dmaCamNumOfEntries; p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = DEFAULT_dmaReadIntBufLow; p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = DEFAULT_dmaReadIntBufHigh; p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = DEFAULT_dmaWriteIntBufLow; p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = DEFAULT_dmaWriteIntBufHigh; p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = DEFAULT_axiDbgNumOfBeats; #endif /* (DPAA_VERSION < 11) */ #ifdef FM_NO_TNUM_AGING p_Fm->p_FmDriverParam->tnum_aging_period = 0; #endif p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period; return p_Fm; } /**************************************************************************//** @Function FM_Init @Description Initializes the FM module @Param[in] h_Fm - FM module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error FM_Init(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_cfg *p_FmDriverParam = NULL; t_Error err = E_OK; int i; t_FmRevisionInfo revInfo; struct fman_rg fman_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; p_Fm->p_FmStateStruct->count1MicroBit = FM_TIMESTAMP_1_USEC_BIT; p_Fm->p_FmDriverParam->num_of_fman_ctrl_evnt_regs = FM_NUM_OF_FMAN_CTRL_EVENT_REGS; if (p_Fm->guestId != NCSW_MASTER_ID) return InitGuestMode(p_Fm); /* if user didn't configured totalFifoSize - (totalFifoSize=0) we configure default * according to chip. otherwise, we use user's configuration. */ if (p_Fm->p_FmStateStruct->totalFifoSize == 0) p_Fm->p_FmStateStruct->totalFifoSize = DEFAULT_totalFifoSize(p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); CHECK_INIT_PARAMETERS(p_Fm, CheckFmParameters); p_FmDriverParam = p_Fm->p_FmDriverParam; FM_GetRevision(p_Fm, &revInfo); /* clear revision-dependent non existing exception */ #ifdef FM_NO_DISPATCH_RAM_ECC if ((revInfo.majorRev != 4) && (revInfo.majorRev < 6)) p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_BMI_DISPATCH_RAM_ECC; #endif /* FM_NO_DISPATCH_RAM_ECC */ #ifdef FM_QMI_NO_ECC_EXCEPTIONS if (revInfo.majorRev == 4) p_Fm->p_FmStateStruct->exceptions &= ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC); #endif /* FM_QMI_NO_ECC_EXCEPTIONS */ #ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION if (revInfo.majorRev >= 6) p_Fm->p_FmStateStruct->exceptions &= ~FM_EX_QMI_SINGLE_ECC; #endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */ FmMuramClear(p_Fm->h_FmMuram); /* clear CPG */ IOMemSet32(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_CGP), 0, FM_PORT_NUM_OF_CONGESTION_GRPS); /* add to the default exceptions the user's definitions */ p_Fm->p_FmStateStruct->exceptions |= p_Fm->userSetExceptions; /* Reset the FM if required */ if (p_Fm->resetOnInit) { #ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 if ((err = FwNotResetErratumBugzilla6173WA(p_Fm)) != E_OK) RETURN_ERROR(MAJOR, err, NO_MSG); #else /* not FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ { u32 svr = mfspr(SPRN_SVR); if (((SVR_SOC_VER(svr) == SVR_T4240 && SVR_REV(svr) > 0x10)) || ((SVR_SOC_VER(svr) == SVR_T4160 && SVR_REV(svr) > 0x10)) || ((SVR_SOC_VER(svr) == SVR_T4080 && SVR_REV(svr) > 0x10)) || (SVR_SOC_VER(svr) == SVR_T1024) || (SVR_SOC_VER(svr) == SVR_T1023) || (SVR_SOC_VER(svr) == SVR_T2080) || (SVR_SOC_VER(svr) == SVR_T2081)) { DBG(WARNING, ("Hack: No FM reset!\n")); } else { WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rstc, FPM_RSTC_FM_RESET); CORE_MemoryBarrier(); XX_UDelay(100); } } if (fman_is_qmi_halt_not_busy_state(p_Fm->p_FmQmiRegs)) { fman_resume(p_Fm->p_FmFpmRegs); XX_UDelay(100); } #endif /* not FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ } #ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 if (!p_Fm->resetOnInit) /* Skip operations done in errata workaround */ { #endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ /* Load FMan-Controller code to IRAM */ ClearIRam(p_Fm); if (p_Fm->firmware.p_Code && (LoadFmanCtrlCode(p_Fm) != E_OK)) RETURN_ERROR(MAJOR, E_INVALID_STATE, NO_MSG); #ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 } #endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */ #ifdef FM_CAPWAP_SUPPORT /* save first 256 byte in MURAM */ p_Fm->resAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, 256, 0)); if (!p_Fm->resAddr) RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for reserved Area failed")); WRITE_BLOCK(UINT_TO_PTR(p_Fm->resAddr), 0, 256); #endif /* FM_CAPWAP_SUPPORT */ #if (DPAA_VERSION >= 11) p_Fm->partVSPBase = AllocVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); if (p_Fm->partVSPBase == (uint8_t)(ILLEGAL_BASE)) DBG(WARNING, ("partition VSPs allocation is FAILED")); #endif /* (DPAA_VERSION >= 11) */ /* General FM driver initialization */ p_Fm->fmMuramPhysBaseAddr = (uint64_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->baseAddr + FM_MM_MURAM))); for (i=0;iintrMng[i].f_Isr = UnimplementedIsr; for (i=0;ifmanCtrlIntr[i].f_Isr = UnimplementedFmanCtrlIsr; p_FmDriverParam->exceptions = p_Fm->p_FmStateStruct->exceptions; /**********************/ /* Init DMA Registers */ /**********************/ err = InitFmDma(p_Fm); if (err != E_OK) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, err, NO_MSG); } /**********************/ /* Init FPM Registers */ /**********************/ err = InitFmFpm(p_Fm); if (err != E_OK) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, err, NO_MSG); } /* define common resources */ /* allocate MURAM for FIFO according to total size */ p_Fm->fifoBaseAddr = PTR_TO_UINT(FM_MURAM_AllocMem(p_Fm->h_FmMuram, p_Fm->p_FmStateStruct->totalFifoSize, BMI_FIFO_ALIGN)); if (!p_Fm->fifoBaseAddr) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, E_NO_MEMORY, ("MURAM alloc for BMI FIFO failed")); } p_FmDriverParam->fifo_base_addr = (uint32_t)(XX_VirtToPhys(UINT_TO_PTR(p_Fm->fifoBaseAddr)) - p_Fm->fmMuramPhysBaseAddr); p_FmDriverParam->total_fifo_size = p_Fm->p_FmStateStruct->totalFifoSize; p_FmDriverParam->total_num_of_tasks = p_Fm->p_FmStateStruct->totalNumOfTasks; p_FmDriverParam->clk_freq = p_Fm->p_FmStateStruct->fmClkFreq; /**********************/ /* Init BMI Registers */ /**********************/ err = InitFmBmi(p_Fm); if (err != E_OK) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, err, NO_MSG); } /**********************/ /* Init QMI Registers */ /**********************/ err = InitFmQmi(p_Fm); if (err != E_OK) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, err, NO_MSG); } /* build the FM master partition IPC address */ if (Sprint (p_Fm->fmModuleName, "FM_%d_%d",p_Fm->p_FmStateStruct->fmId, NCSW_MASTER_ID) != 6) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, E_INVALID_STATE, ("Sprint failed")); } err = XX_IpcRegisterMsgHandler(p_Fm->fmModuleName, FmHandleIpcMsgCB, p_Fm, FM_IPC_MAX_REPLY_SIZE); if (err) { FreeInitResources(p_Fm); RETURN_ERROR(MAJOR, err, NO_MSG); } /* Register the FM interrupts handlers */ if (p_Fm->p_FmStateStruct->irq != NO_IRQ) { XX_SetIntr(p_Fm->p_FmStateStruct->irq, FM_EventIsr, p_Fm); XX_EnableIntr(p_Fm->p_FmStateStruct->irq); } if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) { XX_SetIntr(p_Fm->p_FmStateStruct->errIrq, (void (*) (t_Handle))FM_ErrorIsr, p_Fm); XX_EnableIntr(p_Fm->p_FmStateStruct->errIrq); } err = (t_Error)fman_enable(&fman_rg , p_FmDriverParam); if (err != E_OK) return err; /* FIXME */ EnableTimeStamp(p_Fm); if (p_Fm->firmware.p_Code) { XX_Free(p_Fm->firmware.p_Code); p_Fm->firmware.p_Code = NULL; } XX_Free(p_Fm->p_FmDriverParam); p_Fm->p_FmDriverParam = NULL; return E_OK; } /**************************************************************************//** @Function FM_Free @Description Frees all resources that were assigned to FM module. Calling this routine invalidates the descriptor. @Param[in] h_Fm - FM module descriptor @Return E_OK on success; Error code otherwise. *//***************************************************************************/ t_Error FM_Free(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_rg fman_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { #if (DPAA_VERSION >= 11) FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); if (p_Fm->p_FmSp) { XX_Free(p_Fm->p_FmSp); p_Fm->p_FmSp = NULL; } #endif /* (DPAA_VERSION >= 11) */ if (p_Fm->fmModuleName) XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); if (!p_Fm->recoveryMode) XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm); return E_OK; } fman_free_resources(&fman_rg); if ((p_Fm->guestId == NCSW_MASTER_ID) && (p_Fm->fmModuleName[0] != 0)) XX_IpcUnregisterMsgHandler(p_Fm->fmModuleName); if (p_Fm->p_FmStateStruct) { if (p_Fm->p_FmStateStruct->irq != NO_IRQ) { XX_DisableIntr(p_Fm->p_FmStateStruct->irq); XX_FreeIntr(p_Fm->p_FmStateStruct->irq); } if (p_Fm->p_FmStateStruct->errIrq != NO_IRQ) { XX_DisableIntr(p_Fm->p_FmStateStruct->errIrq); XX_FreeIntr(p_Fm->p_FmStateStruct->errIrq); } } #if (DPAA_VERSION >= 11) FreeVSPsForPartition(h_Fm, p_Fm->partVSPBase, p_Fm->partNumOfVSPs, p_Fm->guestId); if (p_Fm->p_FmSp) { XX_Free(p_Fm->p_FmSp); p_Fm->p_FmSp = NULL; } #endif /* (DPAA_VERSION >= 11) */ if (p_Fm->h_Spinlock) XX_FreeSpinlock(p_Fm->h_Spinlock); if (p_Fm->p_FmDriverParam) { if (p_Fm->firmware.p_Code) XX_Free(p_Fm->firmware.p_Code); XX_Free(p_Fm->p_FmDriverParam); p_Fm->p_FmDriverParam = NULL; } FreeInitResources(p_Fm); if (!p_Fm->recoveryMode && p_Fm->p_FmStateStruct) XX_Free(p_Fm->p_FmStateStruct); XX_Free(p_Fm); return E_OK; } /*************************************************/ /* API Advanced Init unit functions */ /*************************************************/ t_Error FM_ConfigResetOnInit(t_Handle h_Fm, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->resetOnInit = enable; return E_OK; } t_Error FM_ConfigTotalFifoSize(t_Handle h_Fm, uint32_t totalFifoSize) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmStateStruct->totalFifoSize = totalFifoSize; return E_OK; } t_Error FM_ConfigDmaCacheOverride(t_Handle h_Fm, e_FmDmaCacheOverride cacheOverride) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_dma_cache_override fsl_cache_override; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_CACHE_OVERRIDE_TRANS(fsl_cache_override, cacheOverride) p_Fm->p_FmDriverParam->dma_cache_override = fsl_cache_override; return E_OK; } t_Error FM_ConfigDmaAidOverride(t_Handle h_Fm, bool aidOverride) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_aid_override = aidOverride; return E_OK; } t_Error FM_ConfigDmaAidMode(t_Handle h_Fm, e_FmDmaAidMode aidMode) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_dma_aid_mode fsl_aid_mode; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_AID_MODE_TRANS(fsl_aid_mode, aidMode); p_Fm->p_FmDriverParam->dma_aid_mode = fsl_aid_mode; return E_OK; } t_Error FM_ConfigDmaAxiDbgNumOfBeats(t_Handle h_Fm, uint8_t axiDbgNumOfBeats) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); #if (DPAA_VERSION >= 11) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); #else p_Fm->p_FmDriverParam->dma_axi_dbg_num_of_beats = axiDbgNumOfBeats; return E_OK; #endif /* (DPAA_VERSION >= 11) */ } t_Error FM_ConfigDmaCamNumOfEntries(t_Handle h_Fm, uint8_t numOfEntries) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_cam_num_of_entries = numOfEntries; return E_OK; } t_Error FM_ConfigDmaDbgCounter(t_Handle h_Fm, e_FmDmaDbgCntMode fmDmaDbgCntMode) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_dma_dbg_cnt_mode fsl_dma_dbg_cnt; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_DMA_DBG_CNT_TRANS(fsl_dma_dbg_cnt, fmDmaDbgCntMode); p_Fm->p_FmDriverParam->dma_dbg_cnt_mode = fsl_dma_dbg_cnt; return E_OK; } t_Error FM_ConfigDmaStopOnBusErr(t_Handle h_Fm, bool stop) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_stop_on_bus_error = stop; return E_OK; } t_Error FM_ConfigDmaEmergency(t_Handle h_Fm, t_FmDmaEmergency *p_Emergency) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_dma_emergency_level fsl_dma_emer; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_DMA_EMER_TRANS(fsl_dma_emer, p_Emergency->emergencyLevel); p_Fm->p_FmDriverParam->dma_en_emergency = TRUE; p_Fm->p_FmDriverParam->dma_emergency_bus_select = (uint32_t)p_Emergency->emergencyBusSelect; p_Fm->p_FmDriverParam->dma_emergency_level = fsl_dma_emer; return E_OK; } t_Error FM_ConfigDmaEmergencySmoother(t_Handle h_Fm, uint32_t emergencyCnt) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_en_emergency_smoother = TRUE; p_Fm->p_FmDriverParam->dma_emergency_switch_counter = emergencyCnt; return E_OK; } t_Error FM_ConfigDmaErr(t_Handle h_Fm, e_FmDmaErr dmaErr) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_dma_err fsl_dma_err; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_DMA_ERR_TRANS(fsl_dma_err, dmaErr); p_Fm->p_FmDriverParam->dma_err = fsl_dma_err; return E_OK; } t_Error FM_ConfigCatastrophicErr(t_Handle h_Fm, e_FmCatastrophicErr catastrophicErr) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_catastrophic_err fsl_catastrophic_err; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); FMAN_CATASTROPHIC_ERR_TRANS(fsl_catastrophic_err, catastrophicErr); p_Fm->p_FmDriverParam->catastrophic_err = fsl_catastrophic_err; return E_OK; } t_Error FM_ConfigEnableMuramTestMode(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); p_Fm->p_FmDriverParam->en_muram_test_mode = TRUE; return E_OK; } t_Error FM_ConfigEnableIramTestMode(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE ); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); p_Fm->p_FmDriverParam->en_iram_test_mode = TRUE; return E_OK; } t_Error FM_ConfigHaltOnExternalActivation(t_Handle h_Fm, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->halt_on_external_activ = enable; return E_OK; } t_Error FM_ConfigHaltOnUnrecoverableEccError(t_Handle h_Fm, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); p_Fm->p_FmDriverParam->halt_on_unrecov_ecc_err = enable; return E_OK; } t_Error FM_ConfigException(t_Handle h_Fm, e_FmExceptions exception, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t bitMask = 0; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); GET_EXCEPTION_FLAG(bitMask, exception); if (bitMask) { if (enable) p_Fm->userSetExceptions |= bitMask; else p_Fm->p_FmStateStruct->exceptions &= ~bitMask; } else RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); return E_OK; } t_Error FM_ConfigExternalEccRamsEnable(t_Handle h_Fm, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->external_ecc_rams_enable = enable; return E_OK; } t_Error FM_ConfigTnumAgingPeriod(t_Handle h_Fm, uint16_t tnumAgingPeriod) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->tnum_aging_period = tnumAgingPeriod; p_Fm->tnumAgingPeriod = p_Fm->p_FmDriverParam->tnum_aging_period; return E_OK; } /****************************************************/ /* Hidden-DEBUG Only API */ /****************************************************/ t_Error FM_ConfigThresholds(t_Handle h_Fm, t_FmThresholds *p_FmThresholds) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->disp_limit_tsh = p_FmThresholds->dispLimit; p_Fm->p_FmDriverParam->prs_disp_tsh = p_FmThresholds->prsDispTh; p_Fm->p_FmDriverParam->plcr_disp_tsh = p_FmThresholds->plcrDispTh; p_Fm->p_FmDriverParam->kg_disp_tsh = p_FmThresholds->kgDispTh; p_Fm->p_FmDriverParam->bmi_disp_tsh = p_FmThresholds->bmiDispTh; p_Fm->p_FmDriverParam->qmi_enq_disp_tsh = p_FmThresholds->qmiEnqDispTh; p_Fm->p_FmDriverParam->qmi_deq_disp_tsh = p_FmThresholds->qmiDeqDispTh; p_Fm->p_FmDriverParam->fm_ctl1_disp_tsh = p_FmThresholds->fmCtl1DispTh; p_Fm->p_FmDriverParam->fm_ctl2_disp_tsh = p_FmThresholds->fmCtl2DispTh; return E_OK; } t_Error FM_ConfigDmaSosEmergencyThreshold(t_Handle h_Fm, uint32_t dmaSosEmergency) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_sos_emergency = dmaSosEmergency; return E_OK; } t_Error FM_ConfigDmaWriteBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); #if (DPAA_VERSION >= 11) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); #else p_Fm->p_FmDriverParam->dma_write_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency; p_Fm->p_FmDriverParam->dma_write_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency; return E_OK; #endif } t_Error FM_ConfigDmaCommQThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_comm_qtsh_asrt_emer = p_FmDmaThresholds->assertEmergency; p_Fm->p_FmDriverParam->dma_comm_qtsh_clr_emer = p_FmDmaThresholds->clearEmergency; return E_OK; } t_Error FM_ConfigDmaReadBufThresholds(t_Handle h_Fm, t_FmDmaThresholds *p_FmDmaThresholds) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); #if (DPAA_VERSION >= 11) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Not available for this FM revision!")); #else p_Fm->p_FmDriverParam->dma_read_buf_tsh_clr_emer = p_FmDmaThresholds->clearEmergency; p_Fm->p_FmDriverParam->dma_read_buf_tsh_asrt_emer = p_FmDmaThresholds->assertEmergency; return E_OK; #endif } t_Error FM_ConfigDmaWatchdog(t_Handle h_Fm, uint32_t watchdogValue) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); p_Fm->p_FmDriverParam->dma_watchdog = watchdogValue; return E_OK; } t_Error FM_ConfigEnableCounters(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Fm->p_FmDriverParam, E_INVALID_HANDLE); UNUSED(p_Fm); return E_OK; } t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params) { t_Fm* p_Fm = (t_Fm*)h_Fm; if (p_Params->setParams.type & UPDATE_FM_CLD) { WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_cld, GET_UINT32( p_Fm->p_FmFpmRegs->fm_cld) | 0x00000800); } if (p_Params->setParams.type & CLEAR_IRAM_READY) { t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); WRITE_UINT32(p_Iram->iready,GET_UINT32(p_Iram->iready) & ~IRAM_READY); } if (p_Params->setParams.type & UPDATE_FPM_EXTC) WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x80000000); if (p_Params->setParams.type & UPDATE_FPM_EXTC_CLEAR) WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x00800000); if (p_Params->setParams.type & UPDATE_FPM_BRKC_SLP) { if (p_Params->setParams.sleep) WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_SLP); else WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_SLP); } if (p_Params->getParams.type & GET_FM_CLD) p_Params->getParams.fm_cld = GET_UINT32(p_Fm->p_FmFpmRegs->fm_cld); if (p_Params->getParams.type & GET_FMQM_GS) p_Params->getParams.fmqm_gs = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs); if (p_Params->getParams.type & GET_FM_NPI) p_Params->getParams.fm_npi = GET_UINT32(p_Fm->p_FmFpmRegs->fm_npi); if (p_Params->getParams.type & GET_FMFP_EXTC) p_Params->getParams.fmfp_extc = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc); return E_OK; } /****************************************************/ /* API Run-time Control uint functions */ /****************************************************/ void FM_EventIsr(t_Handle h_Fm) { #define FM_M_CALL_1G_MAC_ISR(_id) \ { \ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].guestId) \ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id), pending); \ else \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_1G_MAC0+_id)].h_SrcHandle);\ } #define FM_M_CALL_10G_MAC_ISR(_id) \ { \ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].guestId) \ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id), pending); \ else \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_10G_MAC0+_id)].h_SrcHandle);\ } t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t pending, event; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); fpm_rg = p_Fm->p_FmFpmRegs; /* normal interrupts */ pending = fman_get_normal_pending(fpm_rg); if (!pending) return; if (pending & INTR_EN_WAKEUP) // this is a wake up from sleep interrupt { t_FmGetSetParams fmGetSetParams; memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; fmGetSetParams.setParams.sleep = 0; FmGetSetParams(h_Fm, &fmGetSetParams); } if (pending & INTR_EN_QMI) QmiEvent(p_Fm); if (pending & INTR_EN_PRS) p_Fm->intrMng[e_FM_EV_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_PRS].h_SrcHandle); if (pending & INTR_EN_PLCR) p_Fm->intrMng[e_FM_EV_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_PLCR].h_SrcHandle); if (pending & INTR_EN_TMR) p_Fm->intrMng[e_FM_EV_TMR].f_Isr(p_Fm->intrMng[e_FM_EV_TMR].h_SrcHandle); /* MAC events may belong to different partitions */ if (pending & INTR_EN_1G_MAC0) FM_M_CALL_1G_MAC_ISR(0); if (pending & INTR_EN_1G_MAC1) FM_M_CALL_1G_MAC_ISR(1); if (pending & INTR_EN_1G_MAC2) FM_M_CALL_1G_MAC_ISR(2); if (pending & INTR_EN_1G_MAC3) FM_M_CALL_1G_MAC_ISR(3); if (pending & INTR_EN_1G_MAC4) FM_M_CALL_1G_MAC_ISR(4); if (pending & INTR_EN_1G_MAC5) FM_M_CALL_1G_MAC_ISR(5); if (pending & INTR_EN_1G_MAC6) FM_M_CALL_1G_MAC_ISR(6); if (pending & INTR_EN_1G_MAC7) FM_M_CALL_1G_MAC_ISR(7); if (pending & INTR_EN_10G_MAC0) FM_M_CALL_10G_MAC_ISR(0); if (pending & INTR_EN_10G_MAC1) FM_M_CALL_10G_MAC_ISR(1); /* IM port events may belong to different partitions */ if (pending & INTR_EN_REV0) { event = fman_get_controller_event(fpm_rg, 0); if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_0].guestId) /*TODO IPC ISR For Fman Ctrl */ ASSERT_COND(0); /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_0, pending); */ else p_Fm->fmanCtrlIntr[0].f_Isr(p_Fm->fmanCtrlIntr[0].h_SrcHandle, event); } if (pending & INTR_EN_REV1) { event = fman_get_controller_event(fpm_rg, 1); if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_1].guestId) /*TODO IPC ISR For Fman Ctrl */ ASSERT_COND(0); /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_1, pending); */ else p_Fm->fmanCtrlIntr[1].f_Isr(p_Fm->fmanCtrlIntr[1].h_SrcHandle, event); } if (pending & INTR_EN_REV2) { event = fman_get_controller_event(fpm_rg, 2); if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_2].guestId) /*TODO IPC ISR For Fman Ctrl */ ASSERT_COND(0); /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pending); */ else p_Fm->fmanCtrlIntr[2].f_Isr(p_Fm->fmanCtrlIntr[2].h_SrcHandle, event); } if (pending & INTR_EN_REV3) { event = fman_get_controller_event(fpm_rg, 3); if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_FMAN_CTRL_3].guestId) /*TODO IPC ISR For Fman Ctrl */ ASSERT_COND(0); /* SendIpcIsr(p_Fm, e_FM_EV_FMAN_CTRL_2, pendin3); */ else p_Fm->fmanCtrlIntr[3].f_Isr(p_Fm->fmanCtrlIntr[3].h_SrcHandle, event); } #ifdef FM_MACSEC_SUPPORT if (pending & INTR_EN_MACSEC_MAC0) { if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].guestId) SendIpcIsr(p_Fm, e_FM_EV_MACSEC_MAC0, pending); else p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_MACSEC_MAC0].h_SrcHandle); } #endif /* FM_MACSEC_SUPPORT */ } t_Error FM_ErrorIsr(t_Handle h_Fm) { #define FM_M_CALL_1G_MAC_ERR_ISR(_id) \ { \ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].guestId) \ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id), pending); \ else \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_1G_MAC0+_id)].h_SrcHandle);\ } #define FM_M_CALL_10G_MAC_ERR_ISR(_id) \ { \ if (p_Fm->guestId != p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].guestId) \ SendIpcIsr(p_Fm, (e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id), pending); \ else \ p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].f_Isr(p_Fm->intrMng[(e_FmInterModuleEvent)(e_FM_EV_ERR_10G_MAC0+_id)].h_SrcHandle);\ } t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t pending; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN_ERROR(h_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); fpm_rg = p_Fm->p_FmFpmRegs; /* error interrupts */ pending = fman_get_fpm_error_interrupts(fpm_rg); if (!pending) return ERROR_CODE(E_EMPTY); if (pending & ERR_INTR_EN_BMI) BmiErrEvent(p_Fm); if (pending & ERR_INTR_EN_QMI) QmiErrEvent(p_Fm); if (pending & ERR_INTR_EN_FPM) FpmErrEvent(p_Fm); if (pending & ERR_INTR_EN_DMA) DmaErrEvent(p_Fm); if (pending & ERR_INTR_EN_IRAM) IramErrIntr(p_Fm); if (pending & ERR_INTR_EN_MURAM) MuramErrIntr(p_Fm); if (pending & ERR_INTR_EN_PRS) p_Fm->intrMng[e_FM_EV_ERR_PRS].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PRS].h_SrcHandle); if (pending & ERR_INTR_EN_PLCR) p_Fm->intrMng[e_FM_EV_ERR_PLCR].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_PLCR].h_SrcHandle); if (pending & ERR_INTR_EN_KG) p_Fm->intrMng[e_FM_EV_ERR_KG].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_KG].h_SrcHandle); /* MAC events may belong to different partitions */ if (pending & ERR_INTR_EN_1G_MAC0) FM_M_CALL_1G_MAC_ERR_ISR(0); if (pending & ERR_INTR_EN_1G_MAC1) FM_M_CALL_1G_MAC_ERR_ISR(1); if (pending & ERR_INTR_EN_1G_MAC2) FM_M_CALL_1G_MAC_ERR_ISR(2); if (pending & ERR_INTR_EN_1G_MAC3) FM_M_CALL_1G_MAC_ERR_ISR(3); if (pending & ERR_INTR_EN_1G_MAC4) FM_M_CALL_1G_MAC_ERR_ISR(4); if (pending & ERR_INTR_EN_1G_MAC5) FM_M_CALL_1G_MAC_ERR_ISR(5); if (pending & ERR_INTR_EN_1G_MAC6) FM_M_CALL_1G_MAC_ERR_ISR(6); if (pending & ERR_INTR_EN_1G_MAC7) FM_M_CALL_1G_MAC_ERR_ISR(7); if (pending & ERR_INTR_EN_10G_MAC0) FM_M_CALL_10G_MAC_ERR_ISR(0); if (pending & ERR_INTR_EN_10G_MAC1) FM_M_CALL_10G_MAC_ERR_ISR(1); #ifdef FM_MACSEC_SUPPORT if (pending & ERR_INTR_EN_MACSEC_MAC0) { if (p_Fm->guestId != p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].guestId) SendIpcIsr(p_Fm, e_FM_EV_ERR_MACSEC_MAC0, pending); else p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].f_Isr(p_Fm->intrMng[e_FM_EV_ERR_MACSEC_MAC0].h_SrcHandle); } #endif /* FM_MACSEC_SUPPORT */ return E_OK; } t_Error FM_SetPortsBandwidth(t_Handle h_Fm, t_FmPortsBandwidthParams *p_PortsBandwidth) { t_Fm *p_Fm = (t_Fm*)h_Fm; int i; uint8_t sum; uint8_t hardwarePortId; uint8_t weights[64]; uint8_t weight, maxPercent = 0; struct fman_bmi_regs *bmi_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); bmi_rg = p_Fm->p_FmBmiRegs; memset(weights, 0, (sizeof(uint8_t) * 64)); /* check that all ports add up to 100% */ sum = 0; for (i=0; i < p_PortsBandwidth->numOfPorts; i++) sum +=p_PortsBandwidth->portsBandwidths[i].bandwidth; if (sum != 100) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Sum of ports bandwidth differ from 100%")); /* find highest percent */ for (i=0; i < p_PortsBandwidth->numOfPorts; i++) { if (p_PortsBandwidth->portsBandwidths[i].bandwidth > maxPercent) maxPercent = p_PortsBandwidth->portsBandwidths[i].bandwidth; } ASSERT_COND(maxPercent > 0); /* guaranteed by sum = 100 */ /* calculate weight for each port */ for (i=0; i < p_PortsBandwidth->numOfPorts; i++) { weight = (uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) / maxPercent); /* we want even division between 1-to-PORT_MAX_WEIGHT. so if exact division is not reached, we round up so that: 0 until maxPercent/PORT_MAX_WEIGHT get "1" maxPercent/PORT_MAX_WEIGHT+1 until (maxPercent/PORT_MAX_WEIGHT)*2 get "2" ... maxPercent - maxPercent/PORT_MAX_WEIGHT until maxPercent get "PORT_MAX_WEIGHT: */ if ((uint8_t)((p_PortsBandwidth->portsBandwidths[i].bandwidth * PORT_MAX_WEIGHT ) % maxPercent)) weight++; /* find the location of this port within the register */ hardwarePortId = SwPortIdToHwPortId(p_PortsBandwidth->portsBandwidths[i].type, p_PortsBandwidth->portsBandwidths[i].relativePortId, p_Fm->p_FmStateStruct->revInfo.majorRev, p_Fm->p_FmStateStruct->revInfo.minorRev); ASSERT_COND(IN_RANGE(1, hardwarePortId, 63)); weights[hardwarePortId] = weight; } fman_set_ports_bandwidth(bmi_rg, weights); return E_OK; } t_Error FM_EnableRamsEcc(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); fpm_rg = p_Fm->p_FmFpmRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { t_FmIpcMsg msg; t_Error err; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_ENABLE_RAM_ECC; err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), NULL, NULL, NULL, NULL); if (err != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); return E_OK; } if (!p_Fm->p_FmStateStruct->internalCall) p_Fm->p_FmStateStruct->explicitEnable = TRUE; p_Fm->p_FmStateStruct->internalCall = FALSE; if (p_Fm->p_FmStateStruct->ramsEccEnable) return E_OK; else { fman_enable_rams_ecc(fpm_rg); p_Fm->p_FmStateStruct->ramsEccEnable = TRUE; } return E_OK; } t_Error FM_DisableRamsEcc(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; bool explicitDisable = FALSE; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_HANDLE); fpm_rg = p_Fm->p_FmFpmRegs; if (p_Fm->guestId != NCSW_MASTER_ID) { t_Error err; t_FmIpcMsg msg; memset(&msg, 0, sizeof(msg)); msg.msgId = FM_DISABLE_RAM_ECC; if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), NULL, NULL, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); return E_OK; } if (!p_Fm->p_FmStateStruct->internalCall) explicitDisable = TRUE; p_Fm->p_FmStateStruct->internalCall = FALSE; /* if rams are already disabled, or if rams were explicitly enabled and are currently called indirectly (not explicitly), ignore this call. */ if (!p_Fm->p_FmStateStruct->ramsEccEnable || (p_Fm->p_FmStateStruct->explicitEnable && !explicitDisable)) return E_OK; else { if (p_Fm->p_FmStateStruct->explicitEnable) /* This is the case were both explicit are TRUE. Turn off this flag for cases were following ramsEnable routines are called */ p_Fm->p_FmStateStruct->explicitEnable = FALSE; fman_enable_rams_ecc(fpm_rg); p_Fm->p_FmStateStruct->ramsEccEnable = FALSE; } return E_OK; } t_Error FM_SetException(t_Handle h_Fm, e_FmExceptions exception, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t bitMask = 0; enum fman_exceptions fslException; struct fman_rg fman_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; GET_EXCEPTION_FLAG(bitMask, exception); if (bitMask) { if (enable) p_Fm->p_FmStateStruct->exceptions |= bitMask; else p_Fm->p_FmStateStruct->exceptions &= ~bitMask; fslException = FmanExceptionTrans(exception); return (t_Error)fman_set_exception(&fman_rg, fslException, enable); } else RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("Undefined exception")); return E_OK; } t_Error FM_GetRevision(t_Handle h_Fm, t_FmRevisionInfo *p_FmRevisionInfo) { t_Fm *p_Fm = (t_Fm*)h_Fm; p_FmRevisionInfo->majorRev = p_Fm->p_FmStateStruct->revInfo.majorRev; p_FmRevisionInfo->minorRev = p_Fm->p_FmStateStruct->revInfo.minorRev; return E_OK; } t_Error FM_GetFmanCtrlCodeRevision(t_Handle h_Fm, t_FmCtrlCodeRevisionInfo *p_RevisionInfo) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_FMIramRegs *p_Iram; uint32_t revInfo; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_RevisionInfo, E_NULL_POINTER); if ((p_Fm->guestId != NCSW_MASTER_ID) && p_Fm->h_IpcSessions[0]) { t_Error err; t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength; t_FmIpcFmanCtrlCodeRevisionInfo ipcRevInfo; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_FMAN_CTRL_CODE_REV; replyLength = sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo); if ((err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL)) != E_OK) RETURN_ERROR(MINOR, err, NO_MSG); if (replyLength != (sizeof(uint32_t) + sizeof(t_FmCtrlCodeRevisionInfo))) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); memcpy((uint8_t*)&ipcRevInfo, reply.replyBody, sizeof(t_FmCtrlCodeRevisionInfo)); p_RevisionInfo->packageRev = ipcRevInfo.packageRev; p_RevisionInfo->majorRev = ipcRevInfo.majorRev; p_RevisionInfo->minorRev = ipcRevInfo.minorRev; return (t_Error)(reply.error); } else if (p_Fm->guestId != NCSW_MASTER_ID) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("running in guest-mode without IPC!")); p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); WRITE_UINT32(p_Iram->iadd, 0x4); while (GET_UINT32(p_Iram->iadd) != 0x4) ; revInfo = GET_UINT32(p_Iram->idata); p_RevisionInfo->packageRev = (uint16_t)((revInfo & 0xFFFF0000) >> 16); p_RevisionInfo->majorRev = (uint8_t)((revInfo & 0x0000FF00) >> 8); p_RevisionInfo->minorRev = (uint8_t)(revInfo & 0x000000FF); return E_OK; } uint32_t FM_GetCounter(t_Handle h_Fm, e_FmCounters counter) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_Error err; uint32_t counterValue; struct fman_rg fman_rg; enum fman_counters fsl_counter; SANITY_CHECK_RETURN_VALUE(p_Fm, E_INVALID_HANDLE, 0); SANITY_CHECK_RETURN_VALUE(!p_Fm->p_FmDriverParam, E_INVALID_STATE, 0); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcMsg msg; t_FmIpcReply reply; uint32_t replyLength, outCounter; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_GET_COUNTER; memcpy(msg.msgBody, (uint8_t *)&counter, sizeof(uint32_t)); replyLength = sizeof(uint32_t) + sizeof(uint32_t); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId) +sizeof(counterValue), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) { REPORT_ERROR(MAJOR, err, NO_MSG); return 0; } if (replyLength != (sizeof(uint32_t) + sizeof(uint32_t))) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return 0; } memcpy((uint8_t*)&outCounter, reply.replyBody, sizeof(uint32_t)); return outCounter; } else if (!p_Fm->baseAddr) { REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); return 0; } /* When applicable (when there is an 'enable counters' bit, check that counters are enabled */ switch (counter) { case (e_FM_COUNTERS_DEQ_1): case (e_FM_COUNTERS_DEQ_2): case (e_FM_COUNTERS_DEQ_3): if ((p_Fm->p_FmStateStruct->revInfo.majorRev == 4) || (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6)) { REPORT_ERROR(MAJOR, E_NOT_SUPPORTED, ("Requested counter not supported")); return 0; } case (e_FM_COUNTERS_ENQ_TOTAL_FRAME): case (e_FM_COUNTERS_DEQ_TOTAL_FRAME): case (e_FM_COUNTERS_DEQ_0): case (e_FM_COUNTERS_DEQ_FROM_DEFAULT): case (e_FM_COUNTERS_DEQ_FROM_CONTEXT): case (e_FM_COUNTERS_DEQ_FROM_FD): case (e_FM_COUNTERS_DEQ_CONFIRM): if (!(GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gc) & QMI_CFG_EN_COUNTERS)) { REPORT_ERROR(MAJOR, E_INVALID_STATE, ("Requested counter was not enabled")); return 0; } break; default: break; } FMAN_COUNTERS_TRANS(fsl_counter, counter); return fman_get_counter(&fman_rg, fsl_counter); } t_Error FM_ModifyCounter(t_Handle h_Fm, e_FmCounters counter, uint32_t val) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_rg fman_rg; enum fman_counters fsl_counter; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; FMAN_COUNTERS_TRANS(fsl_counter, counter); return (t_Error)fman_modify_counter(&fman_rg, fsl_counter, val); } void FM_SetDmaEmergency(t_Handle h_Fm, e_FmDmaMuramPort muramPort, bool enable) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_dma_regs *dma_rg; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); dma_rg = p_Fm->p_FmDmaRegs; fman_set_dma_emergency(dma_rg, !!(muramPort==e_FM_DMA_MURAM_PORT_WRITE), enable); } void FM_SetDmaExtBusPri(t_Handle h_Fm, e_FmDmaExtBusPri pri) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_dma_regs *dma_rg; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); dma_rg = p_Fm->p_FmDmaRegs; fman_set_dma_ext_bus_pri(dma_rg, pri); } void FM_GetDmaStatus(t_Handle h_Fm, t_FmDmaStatus *p_FmDmaStatus) { t_Fm *p_Fm = (t_Fm*)h_Fm; uint32_t dmaStatus; struct fman_dma_regs *dma_rg; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); dma_rg = p_Fm->p_FmDmaRegs; if ((p_Fm->guestId != NCSW_MASTER_ID) && !p_Fm->baseAddr && p_Fm->h_IpcSessions[0]) { t_FmIpcDmaStatus ipcDmaStatus; t_FmIpcMsg msg; t_FmIpcReply reply; t_Error err; uint32_t replyLength; memset(&msg, 0, sizeof(msg)); memset(&reply, 0, sizeof(reply)); msg.msgId = FM_DMA_STAT; replyLength = sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus); err = XX_IpcSendMessage(p_Fm->h_IpcSessions[0], (uint8_t*)&msg, sizeof(msg.msgId), (uint8_t*)&reply, &replyLength, NULL, NULL); if (err != E_OK) { REPORT_ERROR(MINOR, err, NO_MSG); return; } if (replyLength != (sizeof(uint32_t) + sizeof(t_FmIpcDmaStatus))) { REPORT_ERROR(MAJOR, E_INVALID_VALUE, ("IPC reply length mismatch")); return; } memcpy((uint8_t*)&ipcDmaStatus, reply.replyBody, sizeof(t_FmIpcDmaStatus)); p_FmDmaStatus->cmqNotEmpty = (bool)ipcDmaStatus.boolCmqNotEmpty; /**< Command queue is not empty */ p_FmDmaStatus->busError = (bool)ipcDmaStatus.boolBusError; /**< Bus error occurred */ p_FmDmaStatus->readBufEccError = (bool)ipcDmaStatus.boolReadBufEccError; /**< Double ECC error on buffer Read */ p_FmDmaStatus->writeBufEccSysError =(bool)ipcDmaStatus.boolWriteBufEccSysError; /**< Double ECC error on buffer write from system side */ p_FmDmaStatus->writeBufEccFmError = (bool)ipcDmaStatus.boolWriteBufEccFmError; /**< Double ECC error on buffer write from FM side */ p_FmDmaStatus->singlePortEccError = (bool)ipcDmaStatus.boolSinglePortEccError; /**< Double ECC error on buffer write from FM side */ return; } else if (!p_Fm->baseAddr) { REPORT_ERROR(MINOR, E_NOT_SUPPORTED, ("Either IPC or 'baseAddress' is required!")); return; } dmaStatus = fman_get_dma_status(dma_rg); p_FmDmaStatus->cmqNotEmpty = (bool)(dmaStatus & DMA_STATUS_CMD_QUEUE_NOT_EMPTY); p_FmDmaStatus->busError = (bool)(dmaStatus & DMA_STATUS_BUS_ERR); if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) p_FmDmaStatus->singlePortEccError = (bool)(dmaStatus & DMA_STATUS_FM_SPDAT_ECC); else { p_FmDmaStatus->readBufEccError = (bool)(dmaStatus & DMA_STATUS_READ_ECC); p_FmDmaStatus->writeBufEccSysError = (bool)(dmaStatus & DMA_STATUS_SYSTEM_WRITE_ECC); p_FmDmaStatus->writeBufEccFmError = (bool)(dmaStatus & DMA_STATUS_FM_WRITE_ECC); } } void FM_Resume(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm*)h_Fm; struct fman_fpm_regs *fpm_rg; SANITY_CHECK_RETURN(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); fpm_rg = p_Fm->p_FmFpmRegs; fman_resume(fpm_rg); } t_Error FM_GetSpecialOperationCoding(t_Handle h_Fm, fmSpecialOperations_t spOper, uint8_t *p_SpOperCoding) { t_Fm *p_Fm = (t_Fm*)h_Fm; t_FmCtrlCodeRevisionInfo revInfo; t_Error err; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(p_SpOperCoding, E_NULL_POINTER); if (!spOper) { *p_SpOperCoding = 0; return E_OK; } if ((err = FM_GetFmanCtrlCodeRevision(p_Fm, &revInfo)) != E_OK) { DBG(WARNING, ("FM in guest-mode without IPC, can't validate firmware revision.")); revInfo.packageRev = IP_OFFLOAD_PACKAGE_NUMBER; } else if (revInfo.packageRev != IP_OFFLOAD_PACKAGE_NUMBER) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("Fman ctrl code package")); if (revInfo.packageRev == IP_OFFLOAD_PACKAGE_NUMBER) { switch (spOper) { case (FM_SP_OP_CAPWAP_DTLS_DEC): *p_SpOperCoding = 9; break; case (FM_SP_OP_CAPWAP_DTLS_ENC): *p_SpOperCoding = 10; break; case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP): case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): *p_SpOperCoding = 5; break; case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP): case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_MANIP|FM_SP_OP_RPD): *p_SpOperCoding = 6; break; case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN|FM_SP_OP_RPD): *p_SpOperCoding = 3; break; case (FM_SP_OP_IPSEC|FM_SP_OP_IPSEC_UPDATE_UDP_LEN): *p_SpOperCoding = 1; break; case (FM_SP_OP_IPSEC|FM_SP_OP_RPD): *p_SpOperCoding = 4; break; case (FM_SP_OP_IPSEC): *p_SpOperCoding = 2; break; case (FM_SP_OP_DCL4C): *p_SpOperCoding = 7; break; case (FM_SP_OP_CLEAR_RPD): *p_SpOperCoding = 8; break; default: RETURN_ERROR(MINOR, E_INVALID_VALUE, NO_MSG); } } return E_OK; } t_Error FM_CtrlMonStart(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_FmTrbRegs *p_MonRegs; uint8_t i; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_RDBG); for (i = 0; i < FM_NUM_OF_CTRL; i++) { p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); /* Reset control registers */ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_RESET); WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET); /* Configure: counter #1 counts all stalls in risc - ldsched stall counter #2 counts all stalls in risc - other stall*/ WRITE_UINT32(p_MonRegs->tcrl, TRB_TCRL_RESET | TRB_TCRL_UTIL); /* Enable monitoring */ WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_ENABLE_COUNTERS); } return E_OK; } t_Error FM_CtrlMonStop(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_FmTrbRegs *p_MonRegs; uint8_t i; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); for (i = 0; i < FM_NUM_OF_CTRL; i++) { p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(i)); WRITE_UINT32(p_MonRegs->tcrh, TRB_TCRH_DISABLE_COUNTERS); } WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_RDBG); return E_OK; } t_Error FM_CtrlMonGetCounters(t_Handle h_Fm, uint8_t fmCtrlIndex, t_FmCtrlMon *p_Mon) { t_Fm *p_Fm = (t_Fm *)h_Fm; t_FmTrbRegs *p_MonRegs; uint64_t clkCnt, utilValue, effValue; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR((p_Fm->guestId == NCSW_MASTER_ID), E_NOT_SUPPORTED); SANITY_CHECK_RETURN_ERROR(p_Mon, E_NULL_POINTER); if (fmCtrlIndex >= FM_NUM_OF_CTRL) RETURN_ERROR(MAJOR, E_INVALID_VALUE, ("FM Controller index")); p_MonRegs = (t_FmTrbRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_TRB(fmCtrlIndex)); clkCnt = (uint64_t) ((uint64_t)GET_UINT32(p_MonRegs->tpcch) << 32 | GET_UINT32(p_MonRegs->tpccl)); utilValue = (uint64_t) ((uint64_t)GET_UINT32(p_MonRegs->tpc1h) << 32 | GET_UINT32(p_MonRegs->tpc1l)); effValue = (uint64_t) ((uint64_t)GET_UINT32(p_MonRegs->tpc2h) << 32 | GET_UINT32(p_MonRegs->tpc2l)); p_Mon->percentCnt[0] = (uint8_t)((clkCnt - utilValue) * 100 / clkCnt); if (clkCnt != utilValue) p_Mon->percentCnt[1] = (uint8_t)(((clkCnt - utilValue) - effValue) * 100 / (clkCnt - utilValue)); else p_Mon->percentCnt[1] = 0; return E_OK; } /****************************************************/ /* Hidden-DEBUG Only API */ /****************************************************/ t_Error FM_ForceIntr (t_Handle h_Fm, e_FmExceptions exception) { t_Fm *p_Fm = (t_Fm*)h_Fm; enum fman_exceptions fslException; struct fman_rg fman_rg; SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); fman_rg.bmi_rg = p_Fm->p_FmBmiRegs; fman_rg.qmi_rg = p_Fm->p_FmQmiRegs; fman_rg.fpm_rg = p_Fm->p_FmFpmRegs; fman_rg.dma_rg = p_Fm->p_FmDmaRegs; switch (exception) { case e_FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_QMI_SINGLE_ECC: if (p_Fm->p_FmStateStruct->revInfo.majorRev >= 6) RETURN_ERROR(MAJOR, E_NOT_SUPPORTED, ("e_FM_EX_QMI_SINGLE_ECC not supported on this integration.")); if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_SINGLE_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_QMI_DOUBLE_ECC: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_QMI_DOUBLE_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_BMI_LIST_RAM_ECC: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_LIST_RAM_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_BMI_STORAGE_PROFILE_ECC: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STORAGE_PROFILE_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_BMI_STATISTICS_RAM_ECC: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_STATISTICS_RAM_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; case e_FM_EX_BMI_DISPATCH_RAM_ECC: if (!(p_Fm->p_FmStateStruct->exceptions & FM_EX_BMI_DISPATCH_RAM_ECC)) RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception is masked")); break; default: RETURN_ERROR(MINOR, E_NOT_SUPPORTED, ("The selected exception may not be forced")); } fslException = FmanExceptionTrans(exception); fman_force_intr (&fman_rg, fslException); return E_OK; } t_Handle FmGetPcd(t_Handle h_Fm) { return ((t_Fm*)h_Fm)->h_Pcd; } #if (DPAA_VERSION >= 11) extern void *g_MemacRegs; void fm_clk_down(void); uint32_t fman_memac_get_event(void *regs, uint32_t ev_mask); void FM_ChangeClock(t_Handle h_Fm, int hardwarePortId) { int macId; uint32_t event, rcr; t_Fm *p_Fm = (t_Fm*)h_Fm; rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); rcr |= 0x04000000; WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); do { event = fman_memac_get_event(g_MemacRegs, 0xFFFFFFFF); } while ((event & 0x00000020) == 0); fm_clk_down(); rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); rcr &= ~0x04000000; WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); } #endif