/*
* Copyright (C) 2015-2018 Texas Instruments Incorporated - http://www.ti.com/
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** ============================================================================
* @file pruicss_drv.c
*
* @brief This file contains device abstraction layer APIs for the
* PRU Subsystem. There are APIs here to enable/disable the
* PRU instance, Load program to PRU and Write to PRU memory.
============================================================================*/
#include <stdint.h>
#include <string.h>
#include <ti/drv/pruss/pruicss.h>
#include <ti/drv/pruss/soc/pruicss_v1.h>
#include <ti/drv/pruss/src/pruicss_osal.h>
#include <ti/csl/cslr.h>
#include <ti/csl/src/ip/icss/V1/cslr_icss_pru_ctrl.h>
#include <ti/csl/src/ip/icss/V1/cslr_icss_intc.h>
#include <ti/csl/src/ip/icss/V1/cslr_icss_cfg.h>
#include <ti/csl/hw_types.h>
#include <ti/osal/SemaphoreP.h>
/*****************************************************************************/
/* INTERNAL MACRO DEFINITIONS */
/*****************************************************************************/
/* Value that needs to be written to bit 0 of PRU_ICSS CTRL register to soft reset PRU*/
#define PRUICSS_PRU_SOFT_RESET_VAL ((uint32_t)0U)
static uintptr_t pruicss_get_ctrl_addr (PRUICSS_HwAttrs const *hwAttrs,
int32_t instance,
uint8_t pruNum);
static uintptr_t pruicss_get_ctrl_addr (PRUICSS_HwAttrs const *hwAttrs,
int32_t instance,
uint8_t pruNum)
{
uintptr_t baseaddr = 0;
if ((instance >= PRUICCSS_INSTANCE_ONE) && (instance < PRUICCSS_INSTANCE_MAX))
{
switch (pruNum) {
case PRUICCSS_PRU0: baseaddr = hwAttrs->prussPru0CtrlRegBase;
break;
case PRUICCSS_PRU1: baseaddr = hwAttrs->prussPru1CtrlRegBase;
break;
case PRUICCSS_RTU0: baseaddr = hwAttrs->prussRtu0CtrlRegBase;
break;
case PRUICCSS_RTU1: baseaddr = hwAttrs->prussRtu1CtrlRegBase;
break;
}
}
return baseaddr;
}
/**************************************************************************/
/* API FUNCTION DEFINITIONS */
/**************************************************************************/
/**
* @brief This function creates the handle for the PRUICSS instance \n
*
* @param config configuration structure of PRUICSS.
* @param instance PRUICSS instance no.
*
* @return PRUICSS handle. \n
*/
PRUICSS_Handle PRUICSS_create(PRUICSS_Config *config, int32_t instance)
{
PRUICSS_Handle handle;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
uintptr_t temp_addr = 0U;
uint32_t temp_val;
handle = (PRUICSS_Config *)&config[instance-1];
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
object = (PRUICSS_V1_Object*)handle->object;
object->instance = instance;
temp_addr = (hwAttrs->prussCfgRegBase + CSL_ICSSCFG_REVID);
temp_val = CSL_REG32_RD(temp_addr) & 0xFFFFU;
object->pruicss_version = temp_val;
return(&config[instance-1]);
}
/**
* @brief This function sets the buffer pointer for PRU. The contents of this buffer will be \n
* loaded to IRAM.\n
*
* @param handle Pruss's driver handle
* @param pruNum The PRU number.\n
* @param buffer Pointer to buffer.\n
* @param numBytes Number of bytes in the buffer.\n
*
* @return 0 in case of successful transition, -1 otherwise. \n
*/
int32_t PRUICSS_setPRUBuffer( PRUICSS_Handle handle,
uint32_t pruNum,
void *buffer,
uint32_t numBytes
)
{
PRUICSS_V1_Object *object;
int32_t ret_val = 0;
object = (PRUICSS_V1_Object *)handle->object;
if((pruNum >= PRUICSS_MAX_PRU ) || (buffer == 0))
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
object->pruBinBuff[pruNum] = buffer;
object->buffLen[pruNum] = numBytes;
ret_val = PRUICSS_RETURN_SUCCESS;
}
return ret_val;
}
/**
* @brief Resets PRU: \n
*
* @param handle Pruss's driver handle
* @param pruNum PRU instance number[0 or 1].
*
* @return 0 in case of successful reset, -1 otherwise.
*/
int32_t PRUICSS_pruReset(PRUICSS_Handle handle, uint8_t pruNum)
{
uintptr_t baseaddr;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_FAILURE;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if(pruNum < PRUICSS_MAX_PRU) {
baseaddr = pruicss_get_ctrl_addr (hwAttrs, object->instance, pruNum);
if(baseaddr != 0) {
HW_WR_REG32((baseaddr) + CSL_ICSSPRUCTRL_CONTROL, 0);
ret_val = PRUICSS_RETURN_SUCCESS;
}
}
return ret_val;
}
/**
* @brief Disables PRU: \n
*
* @param handle Pruss's driver handle
* @param pruNum PRU instance number[0 or 1].
*
* @return 0 in case of successful disable, -1 otherwise.
**/
int32_t PRUICSS_pruDisable(PRUICSS_Handle handle, uint8_t pruNum)
{
uintptr_t baseaddr = 0;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_FAILURE;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if(pruNum < PRUICSS_MAX_PRU) {
baseaddr = pruicss_get_ctrl_addr (hwAttrs, object->instance, pruNum);
if(baseaddr != 0) {
HW_WR_FIELD32((baseaddr), CSL_ICSSPRUCTRL_CONTROL_ENABLE, CSL_ICSSPRUCTRL_CONTROL_ENABLE_RESETVAL);
ret_val = PRUICSS_RETURN_SUCCESS;
}
}
return ret_val;
}
/**
* @brief Enables PRU: \n
*
* @param handle Pruss's driver handle
* @param pruNum PRU instance number[0 or 1].
*
* @return 0 in case of successful enable, -1 otherwise.
**/
int32_t PRUICSS_pruEnable(PRUICSS_Handle handle,uint8_t pruNum)
{
uintptr_t baseaddr;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_FAILURE;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if(pruNum < PRUICSS_MAX_PRU) {
baseaddr = pruicss_get_ctrl_addr (hwAttrs, object->instance, pruNum);
if(baseaddr != 0) {
HW_WR_FIELD32((baseaddr), CSL_ICSSPRUCTRL_CONTROL_ENABLE, CSL_ICSSPRUCTRL_CONTROL_ENABLE_MAX);
ret_val = PRUICSS_RETURN_SUCCESS;
}
}
return ret_val;
}
/**
* @brief Enables PRU Cycle Counter: \n
*
* @param handle Pruss's driver handle
* @param pruNum PRU instance number[0 or 1].
*
* @return 0 in case of successful enable, -1 otherwise.
**/
int32_t PRUICSS_pruCounterEnable(PRUICSS_Handle handle, uint8_t pruNum)
{
uintptr_t baseaddr;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (const PRUICSS_HwAttrs *)handle->hwAttrs;
if(pruNum >= PRUICSS_MAX_PRU)
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
baseaddr = pruicss_get_ctrl_addr (hwAttrs, object->instance, pruNum);
if(baseaddr != 0)
{
HW_WR_FIELD32((baseaddr), CSL_ICSSPRUCTRL_CONTROL_COUNTER_ENABLE, CSL_ICSSPRUCTRL_CONTROL_COUNTER_ENABLE_MAX);
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
}
return ret_val;
}
/**
*
* @brief This function writes the given data to PRU memory
*
* @param handle Pruss's driver handle
* @param pruMem PRU Memory Macro [DATARAM0_PHYS_BASE
* @param wordoffset Offset at which the write will happen.
* @param source_mem Source memory[ Array of uint32_tegers ]
* @param bytelength Total number of bytes to be writen
*
* pruMem can have values
* PRU0_DATARAM\n
* PRU0_IRAM\n
* PRU1_DATARAM\n
* PRU1_IRAM\n
* PRUICSS_SHARED_DATARAM
* @return word length written or 0 on error.
*
**/
int32_t PRUICSS_pruWriteMemory(
PRUICSS_Handle handle,
uint32_t pruMem,
uint32_t wordoffset,
const uint32_t *source_mem,
uint32_t bytelength
)
{
uintptr_t addr;
PRUICSS_HwAttrs const *hwAttrs;
uintptr_t temp_addr = 0U;
uint32_t i, wordlength;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
int32_t ret = 0;
wordlength = (bytelength + 3U) >> 2U;
if (pruMem == PRU_ICSS_DATARAM(0U)) {
addr = hwAttrs->prussPru0DramBase;
} else if (pruMem == PRU_ICSS_IRAM(0U)) {
addr = hwAttrs->prussPru0IramBase;
} else if (pruMem == PRU_ICSS_DATARAM(1U)) {
addr = hwAttrs->prussPru1DramBase;
} else if (pruMem == PRU_ICSS_IRAM(1U)) {
addr = hwAttrs->prussPru1IramBase;
} else if (pruMem == PRU_ICSS_SHARED_RAM) {
addr = hwAttrs->prussSharedDramBase;
} else if (pruMem == PRU_ICSS_IRAM(2U)) {
addr = hwAttrs->prussRtu0IramBase;
} else if (pruMem == PRU_ICSS_IRAM(3U)) {
addr = hwAttrs->prussRtu1IramBase;
} else {
ret = PRUICSS_RETURN_FAILURE;
wordlength = 0U;
}
if (ret != PRUICSS_RETURN_FAILURE)
{
for (i = 0; i < wordlength; i++)
{
temp_addr = (addr + (i << 2) + wordoffset);
CSL_REG32_WR(temp_addr, source_mem[i]);
}
}
return (int32_t)wordlength;
}
/**
*
* @brief This function intialize the PRU memory to zero
*
* @param handle Pruss's driver handle
* @param pruMem PRU Memory Macro [DATARAM0_PHYS_BASE
*
* pruMem can have values
* PRU0_DATARAM\n
* PRU0_IRAM\n
* PRU1_DATARAM\n
* PRU1_IRAM\n
* PRUICSS_SHARED_DATARAM
* @return word length written or 0 on error.
*
**/
int32_t PRUICSS_pruInitMemory(
PRUICSS_Handle handle,
uint32_t pruMem
)
{
uint32_t addr = 0U;
PRUICSS_HwAttrs const *hwAttrs;
uintptr_t temp_addr = 0U;
int32_t size = 0;
int32_t i = 0;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if (pruMem == PRU_ICSS_DATARAM(0U)) {
addr = hwAttrs->prussPru0DramBase;
size = hwAttrs->prussPru0DramSize;
} else if (pruMem == PRU_ICSS_IRAM(0U)) {
addr = hwAttrs->prussPru0IramBase;
size = hwAttrs->prussPru0IramSize;
} else if (pruMem == PRU_ICSS_DATARAM(1U)) {
addr = hwAttrs->prussPru1DramBase;
size = hwAttrs->prussPru1DramSize;
} else if (pruMem == PRU_ICSS_IRAM(1U)) {
addr = hwAttrs->prussPru1IramBase;
size = hwAttrs->prussPru1IramSize;
} else if (pruMem == PRU_ICSS_SHARED_RAM) {
addr = hwAttrs->prussSharedDramBase;
size = hwAttrs->prussSharedDramSize;
} else {
size = 0;
}
if(size > 0)
{
for (i = 0; i < size; i = i+4) {
temp_addr = (addr + (uint32_t)i);
HW_WR_REG32(temp_addr,(uint32_t)0x00000000U);
//HWREG(temp_addr) = (uint32_t)0x00000000U;
}
}
return size;
}
/**
*
* @brief This function reads from PRU memory and stores in block of memory
*
* @param handle Pruss's driver handle
* @param pruMem PRU Memory Macro
* @param wordoffset Offset at which the read will happen.
* @param dest_mem Destination memory[ Array of uint32_tegers ]
* @param bytelength Total number of bytes to be read
*
* pruMem can have values
* PRU0_DATARAM\n
* PRU0_IRAM\n
* PRU1_DATARAM\n
* PRU1_IRAM\n
* PRUICSS_SHARED_DATARAM
* @return word length read or 0 on error.
*
**/
int32_t PRUICSS_pruReadMemory(
PRUICSS_Handle handle,
uint32_t pruMem,
uint32_t wordoffset,
uint32_t *dest_mem,
uint32_t bytelength
)
{
uintptr_t addr;
PRUICSS_HwAttrs const *hwAttrs;
uintptr_t temp_addr = 0U;
hwAttrs = (const PRUICSS_HwAttrs *)handle->hwAttrs;
uint32_t i, wordlength;
wordlength = (bytelength + 3U) >> 2U;
if (pruMem == PRU_ICSS_DATARAM(0U)) {
addr = hwAttrs->prussPru0DramBase;
} else if (pruMem == PRU_ICSS_IRAM(0U)) {
addr = hwAttrs->prussPru0IramBase;
} else if (pruMem == PRU_ICSS_DATARAM(1U)) {
addr = hwAttrs->prussPru1DramBase;
} else if (pruMem == PRU_ICSS_IRAM(1U)) {
addr = hwAttrs->prussPru1IramBase;
} else if (pruMem == PRUICSS_SHARED_DATARAM) {
addr = hwAttrs->prussSharedDramBase;
} else if (pruMem == PRU_ICSS_IRAM(2U)) {
addr = hwAttrs->prussRtu0IramBase;
} else if (pruMem == PRU_ICSS_IRAM(3U)) {
addr = hwAttrs->prussRtu1IramBase;
} else {
return -1;
}
for (i = 0; i < wordlength; i++)
{
temp_addr = (addr + (i << 2) + wordoffset);
dest_mem[i] = CSL_REG32_RD(temp_addr);
}
return wordlength;
}
/**
* @brief This function Generates an INTC event \n
*
* @param handle Pruss's driver handle
* @param eventnum The INTC Event number.\n
*
* @return 0 in case of successful transition, -1 otherwise. \n
**/
int32_t PRUICSS_pruSendEvent(PRUICSS_Handle handle,uint32_t eventnum)
{
uintptr_t baseaddr;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
uintptr_t temp_addr = 0U;
uint32_t temp_var = 0U;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if ((object->instance >= PRUICCSS_INSTANCE_ONE) &&
(object->instance < PRUICCSS_INSTANCE_MAX))
{
baseaddr = hwAttrs->prussIntcRegBase;
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
if(ret_val == PRUICSS_RETURN_SUCCESS)
{
if(eventnum < 32U)
{
temp_addr = (baseaddr + CSL_ICSSINTC_SRSR0);
temp_var = (((uint32_t)1U) << eventnum);
HW_WR_FIELD32(temp_addr, CSL_ICSSINTC_SRSR0_RAW_STATUS_31_0, temp_var);
}
else
{
temp_addr = (baseaddr + CSL_ICSSINTC_SRSR1);
temp_var = (((uint32_t)1U) << (eventnum - 32U));
HW_WR_FIELD32(temp_addr, CSL_ICSSINTC_SRSR1_RAW_STATUS_63_32, temp_var);
}
}
return ret_val;
}
/**
* @brief This function clears an INTC event \n
*
* @param handle Pruss's driver handle
* @param eventnum The INTC Event number.\n
*
* @return 0 in case of successful transition, -1 otherwise. \n
**/
int32_t PRUICSS_pruClearEvent(PRUICSS_Handle handle,uint32_t eventnum)
{
uintptr_t baseaddr;
PRUICSS_HwAttrs const *hwAttrs;
PRUICSS_V1_Object *object;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
baseaddr = hwAttrs->baseAddr;
if ((object->instance >= PRUICCSS_INSTANCE_ONE) &&
(object->instance < PRUICCSS_INSTANCE_MAX))
{
baseaddr = hwAttrs->prussIntcRegBase;
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
if(ret_val == PRUICSS_RETURN_SUCCESS)
{
HW_WR_FIELD32((baseaddr + CSL_ICSSINTC_SICR), CSL_ICSSINTC_SICR_STATUS_CLR_INDEX, eventnum);
}
return ret_val;
}
/**
* @brief This function waits for a Syatem event to happen \n
*
* @param handle Pruss's driver handle
* @param pruEvtoutNum The AINTC Event number.\n
*
* @return 0 in case of successful transition, -1 otherwise. \n
*/
int32_t PRUICSS_pruWaitEvent(PRUICSS_Handle handle,uint32_t pruEvtoutNum )
{
PRUICSS_V1_Object *object;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
object = (PRUICSS_V1_Object *)handle->object;
if(pruEvtoutNum >= PRUICSS_MAX_WAIT_EVENTS)
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
if(object->pruEvntOutFnMapArray[pruEvtoutNum].semHandle != NULL)
{
PRUICSS_osalPendLock(object->pruEvntOutFnMapArray[pruEvtoutNum].semHandle,PRUICSS_WAIT_FOREVER);
}
ret_val = PRUICSS_RETURN_SUCCESS;
}
return(ret_val);
}
/**
* @brief This function returns the address of PRU components.
*
* @param handle Pruss's driver handle
* @param pru_ram_id PRU components' Id. \n
* @param address Memory to which address to be copied. \n
*
* @return 0 in case of success, -1 otherwise. \n
**/
int32_t PRUICSS_mapPruMem(PRUICSS_Handle handle,uint32_t pru_ram_id, void **address)
{
uintptr_t baseaddr;
PRUICSS_HwAttrs const *hwAttrs;
uintptr_t temp_addr = 0U;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
baseaddr = hwAttrs->baseAddr;
switch (pru_ram_id) {
case PRUICSS_PRU0_DATARAM:
temp_addr = (baseaddr + PRU_ICSS_DATARAM(0U));
*address = (void*)(temp_addr);
break;
case PRUICSS_PRU1_DATARAM:
temp_addr = (baseaddr + PRU_ICSS_DATARAM(1U));
*address = (void*)(temp_addr);
break;
case PRUICSS_SHARED_DATARAM:
temp_addr = (baseaddr + PRU_ICSS_SHARED_RAM);
*address = (void*)(temp_addr);
break;
default:
*address = 0;
ret_val = PRUICSS_RETURN_FAILURE;
break;
}
return ret_val;
}
/**
* @brief This function returns the base address of peripheral IO modules.
*
* @param handle Pruss's driver handle
* @param per_id Peripheral Module's Id.
* @param address Memory to which address to be copied. \n
*
*
* @return 0 in case of success, -1 otherwise. \n
**/
int32_t PRUICSS_mapPeripheralIO(PRUICSS_Handle handle,uint32_t per_id,
void **address)
{
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if ((object->instance >= PRUICCSS_INSTANCE_ONE) &&
(object->instance < PRUICCSS_INSTANCE_MAX))
{
switch (per_id)
{
case PRUICSS_CFG:
*address = (void*)(hwAttrs->prussCfgRegBase);
break;
case PRUICSS_UART:
*address = (void*)(hwAttrs->prussUartRegBase);
break;
case PRUICSS_IEP:
*address = (void*)(hwAttrs->prussIepRegBase);
break;
case PRUICSS_ECAP:
*address = (void*)(hwAttrs->prussEcapRegBase);
break;
case PRUICSS_MII_RT:
*address = (void*)( hwAttrs->prussMiiRtCfgRegBase);
break;
case PRUICSS_MDIO:
*address = (void*)(hwAttrs->prussMiiMdioRegBase);
break;
default:
*address = 0;
ret_val = PRUICSS_RETURN_FAILURE;
break;
}
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
return ret_val;
}
void PRUICSS_enableOCPMasterAccess(PRUICSS_Handle handle )
{
uintptr_t baseaddr =0U;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if ((object->instance >= PRUICCSS_INSTANCE_ONE) &&
(object->instance < PRUICCSS_INSTANCE_MAX))
{
baseaddr = hwAttrs->prussCfgRegBase;
}
HW_WR_FIELD32((baseaddr + CSL_ICSSCFG_SYSCFG),CSL_ICSSCFG_SYSCFG_STANDBY_INIT, 0);
}
/**
* @brief Detects the Chip Type \n
*
* @return 0
*/
uint32_t PRUICSS_detectHWVersion(void)
{
return 0U;
}
/**
* @brief Get PRU ICSS version : \n
*
* @param handle Pruss's driver handle
*
* @return ICSS HW version
**/
uint32_t PRUICSS_getICSSVersion(PRUICSS_Handle handle)
{
PRUICSS_V1_Object *object;
object = (PRUICSS_V1_Object *)handle->object;
return object->pruicss_version;
}
/**
* @brief This function Executes the program in the specified PRU \n
*
* @param handle Pruss's driver handle
* @param pruNum PRU instance number.\n
*
* @return 0 in case of successful transition, -1 otherwise. \n
*/
int32_t PRUICSS_pruExecProgram(PRUICSS_Handle handle,int32_t pruNum)
{
PRUICSS_V1_Object *object;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
object = (PRUICSS_V1_Object *)handle->object;
if((pruNum >= PRUICSS_MAX_PRU) || (object->pruBinBuff[pruNum] == 0) || (object->buffLen[pruNum] == 0))
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
PRUICSS_pruDisable(handle,(uint8_t)pruNum);
PRUICSS_pruInitMemory(handle,PRU_ICSS_IRAM((uint32_t)pruNum));
PRUICSS_pruWriteMemory(handle,PRU_ICSS_IRAM((uint32_t)pruNum),0U,(uint32_t *) object->pruBinBuff[pruNum],object->buffLen[pruNum]);
PRUICSS_pruReset(handle,(uint8_t)pruNum);
PRUICSS_pruEnable(handle,(uint8_t)pruNum);
ret_val = PRUICSS_RETURN_SUCCESS;
}
return(ret_val);
}
/**
* \brief This function generates and INTC event, waits for AINTC event and
* clears an INTC event \n
*
* @param handle Pruss's driver handle
* @param sendEventNum Event number.\n
* @param pruEvtoutNum PRU Event number.\n
* @param ackEventNum Acknowlodegement event number.\n
*
* \return 0 in case of successful transition, -1 otherwise. \n
*/
int32_t PRUICSS_pruSendWaitCearEvent( PRUICSS_Handle handle,
uint32_t sendEventNum,
uint32_t pruEvtoutNum,
uint32_t ackEventNum
)
{
PRUICSS_pruSendEvent(handle,sendEventNum);
PRUICSS_pruWaitEvent(handle,pruEvtoutNum);
PRUICSS_pruClearEvent(handle,ackEventNum);
return PRUICSS_RETURN_SUCCESS;
}
/**
* @brief Configure PIN_MUX_SEL
*
* @param handle Pruss's driver handle
* @param regVal value to be written
*
* @return None.
*
**/
void PRUICSS_pinMuxConfig(PRUICSS_Handle handle, uint64_t regVal)
{
uintptr_t baseaddr = 0U;
PRUICSS_V1_Object *object;
PRUICSS_HwAttrs const *hwAttrs;
object = (PRUICSS_V1_Object *)handle->object;
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if ((object->instance >= PRUICCSS_INSTANCE_ONE) &&
(object->instance < PRUICCSS_INSTANCE_MAX))
{
baseaddr = hwAttrs->prussCfgRegBase;
}
HW_WR_FIELD32((baseaddr + CSL_ICSSCFG_PIN_MX),CSL_ICSSCFG_PIN_MX_PIN_MUX_SEL, regVal);
}
/**
* \brief This API gets the SoC level of PRUICSS intial configuration
*
* \param cfg Pointer to PRUICSS SOC initial config.
*
* \return 0 success
*
*/
int32_t PRUICSS_socGetInitCfg( PRUICSS_Config **cfg)
{
#ifndef __LINUX_USER_SPACE
*cfg = &pruss_config[0];
#endif
return PRUICSS_RETURN_SUCCESS;
}
/**
* \brief This API sets the SoC level of PRUICSS intial configuration
*
* \param cfg Pointer to PRUICSS SOC initial config.
*
* \return 0 success
*
*/
int32_t PRUICSS_socSetInitCfg(PRUICSS_Config const *cfg)
{
#ifndef __LINUX_USER_SPACE
uint32_t len = sizeof(PRUICSS_Config) * (PRUICCSS_INSTANCE_MAX -1U);
memcpy(&pruss_config, cfg, len);
#endif
return PRUICSS_RETURN_SUCCESS;
}
/**
* \brief This API updates the constant table for specified constant table entry
which have write permissions.
*
* @param handle Pruss's driver handle
* @param pruNum PRU number[0 or 1] for which constant table is being updated.
* @param constantTblEntry contant table entry being updated
* @param constantTblVal contant table value to be written
*
* \return 0 success, -1 on error
*
*/
int32_t PRUICSS_setConstantTblEntry(PRUICSS_Handle handle, uint8_t pruNum, int32_t constantTblEntry, uint32_t constantTblVal)
{
PRUICSS_HwAttrs const *hwAttrs = NULL;
uint32_t baseaddr = 0U;
uintptr_t tempaddr = 0U;
uint32_t tempval = 0U;
uint32_t currentval = 0U;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
static uint32_t pruicssConstantIndex[PRUICCSS_ConstTblEntryMax] =
{
CSL_ICSSPRUCTRL_CTBIR0, /*For enry 24, PRU-ICSS PRU0 Data RAM */
CSL_ICSSPRUCTRL_CTBIR0, /*For enry 25, PRU-ICSS PRU1 Data RAM */
CSL_ICSSPRUCTRL_CTBIR1, /*For enry 26, PRU-ICSS IEP */
CSL_ICSSPRUCTRL_CTBIR1, /*For enry 27, PRU-ICSS MII_RT*/
CSL_ICSSPRUCTRL_CTPPR0, /*For enry 28, PRU-ICSS Shared RAM*/
CSL_ICSSPRUCTRL_CTPPR0, /*For enry 29, TPCC*/
CSL_ICSSPRUCTRL_CTPPR1, /*For enry 30, L3 OCMC0 */
CSL_ICSSPRUCTRL_CTPPR1 /*For enry 31, EMIF0 DDR Base */
};
/* verify constant table index is within valid range */
if (((constantTblEntry < 0) || (constantTblEntry >= PRUICCSS_ConstTblEntryMax)) || (pruNum > PRUICSS_MAX_PRU))
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if(PRUICCSS_PRU0 == pruNum)
{
baseaddr = hwAttrs->prussPru0CtrlRegBase;
}
else if(PRUICCSS_PRU1 == pruNum)
{
baseaddr = hwAttrs->prussPru1CtrlRegBase;
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
if (ret_val == PRUICSS_RETURN_SUCCESS)
{
tempaddr = baseaddr + pruicssConstantIndex[constantTblEntry];
switch (constantTblEntry)
{
case PRUICCSS_ConstTblEntryC24:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTBIR0_C24_BLK_INDEX_MASK));
tempval = CSL_ICSSPRUCTRL_CTBIR0_C24_BLK_INDEX_MASK & constantTblVal;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC25:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTBIR0_C25_BLK_INDEX_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTBIR0_C25_BLK_INDEX_SHIFT;
tempval = CSL_ICSSPRUCTRL_CTBIR0_C25_BLK_INDEX_MASK & tempval;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC26:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTBIR1_C26_BLK_INDEX_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTBIR1_C26_BLK_INDEX_SHIFT;
tempval = CSL_ICSSPRUCTRL_CTBIR1_C26_BLK_INDEX_MASK & tempval;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC27:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTBIR1_C27_BLK_INDEX_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTBIR1_C27_BLK_INDEX_SHIFT;
tempval = CSL_ICSSPRUCTRL_CTBIR1_C27_BLK_INDEX_MASK & tempval;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC28:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTPPR0_C28_POINTER_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTPPR0_C28_POINTER_SHIFT;
tempval &= CSL_ICSSPRUCTRL_CTPPR0_C28_POINTER_MASK;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC29:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTPPR0_C29_POINTER_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTPPR0_C29_POINTER_SHIFT;
tempval &= CSL_ICSSPRUCTRL_CTPPR0_C29_POINTER_MASK;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC30:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTPPR1_C30_POINTER_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTPPR1_C30_POINTER_SHIFT;
tempval &= CSL_ICSSPRUCTRL_CTPPR1_C30_POINTER_MASK;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
case PRUICCSS_ConstTblEntryC31:
{
currentval = HW_RD_REG32(tempaddr);
currentval &= (~((uint32_t)CSL_ICSSPRUCTRL_CTPPR1_C31_POINTER_MASK));
tempval = constantTblVal << CSL_ICSSPRUCTRL_CTPPR1_C31_POINTER_SHIFT;
tempval &= CSL_ICSSPRUCTRL_CTPPR1_C31_POINTER_MASK;
//HWREG(tempaddr) =currentval |tempval;
HW_WR_REG32(tempaddr,(uint32_t)(currentval |tempval));
break;
}
default:
{
break;
}
}
}
}
return ret_val;
}
/**
* \brief This API configures the General Purpose Mux Selector field of
* the General Purpose Config Register (PRUSS_GPCFG)
*
* @param handle Pruss's driver handle
* @param pruNum PRU number[0 or 1].
* @param mode PRU-ICSS wrap mux selection
*
* \return 0 success, -1 on error
*
*/
int32_t PRUICSS_setGpMuxSel(PRUICSS_Handle handle, uint8_t pruNum, uint32_t mode)
{
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
if((handle == NULL) || (pruNum >= PRUICSS_MAX_PRU))
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
if(PRUICCSS_PRU0 == pruNum)
{
HW_WR_FIELD32((hwAttrs->prussCfgRegBase+CSL_ICSSCFG_GPCFG0), CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL, mode);
}
else if(PRUICCSS_PRU1 == pruNum)
{
HW_WR_FIELD32((hwAttrs->prussCfgRegBase+CSL_ICSSCFG_GPCFG1), CSL_ICSSCFG_GPCFG0_PRU0_GP_MUX_SEL, mode);
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
}
return ret_val;
}
/**
* \brief This API configures the source of the IEP clock to be either
* IEP CLK as the source or Interface Bus CLK as the source (such as OCP/ICLK/VCLK)
* This is accomplished by updating the IEP clock field of the General Purpose Config
* Register (PRUSS_GPCFG)
*
* @param handle Pruss's driver handle
* @param source source of the IEP clock (0 == IEP CLK, 1 == OCP/ICLK/VCLK)
*
* \return 0 success, -1 on error
*
*/
int32_t PRUICSS_setIepClkSrc(PRUICSS_Handle handle, uint32_t source)
{
PRUICSS_HwAttrs const *hwAttrs;
int32_t ret_val = PRUICSS_RETURN_SUCCESS;
if(handle == NULL)
{
ret_val = PRUICSS_RETURN_FAILURE;
}
else
{
/* validate the clk source */
if ((source == 1U) || (source == 0U))
{
hwAttrs = (PRUICSS_HwAttrs const *)handle->hwAttrs;
HW_WR_FIELD32((hwAttrs->prussCfgRegBase+CSL_ICSSCFG_IEPCLK), CSL_ICSSCFG_IEPCLK_OCP_EN, source);
}
else
{
ret_val = PRUICSS_RETURN_FAILURE;
}
}
return ret_val;
}
/*****************************END OF FILE************************************/