aboutsummaryrefslogtreecommitdiffstats
path: root/mpm/lib/rfdc/xrfdc_sinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'mpm/lib/rfdc/xrfdc_sinit.c')
-rw-r--r--mpm/lib/rfdc/xrfdc_sinit.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/mpm/lib/rfdc/xrfdc_sinit.c b/mpm/lib/rfdc/xrfdc_sinit.c
new file mode 100644
index 000000000..0fb907859
--- /dev/null
+++ b/mpm/lib/rfdc/xrfdc_sinit.c
@@ -0,0 +1,272 @@
+/******************************************************************************
+*
+* Copyright (C) 2017-2019 Xilinx, Inc. All rights reserved.
+*
+* Permission is hereby granted, free of charge, to any person obtaining a copy
+* of this software and associated documentation files (the "Software"), to deal
+* in the Software without restriction, including without limitation the rights
+* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the Software is
+* furnished to do so, subject to the following conditions:
+*
+* The above copyright notice and this permission notice shall be included in
+* all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+* SOFTWARE.
+*
+* Except as contained in this notice, the name of the Xilinx shall not be used
+* in advertising or otherwise to promote the sale, use or other dealings in
+* this Software without prior written authorization from Xilinx.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xrfdc_sinit.c
+* @addtogroup rfdc_v6_0
+* @{
+*
+* The implementation of the XRFdc component's static initialization
+* functionality.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- --- -------- -----------------------------------------------
+* 1.0 sk 05/16/17 Initial release
+* 5.0 mus 08/17/18 Updated XRFdc_LookupConfig to make use of device
+* tree instead of xrfdc_g.c, to obtain
+* XRFdc_Config for provided device id.It is being
+* achieved through "param-list" property in RFDC
+* device node, it will be having 1:1 mapping with
+* the XRFdc_Config structure. Said changes
+* have been done, to remove the xparameters.h
+* dependency from RFDC Linux user space driver.
+*
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+#define METAL_INTERNAL
+#include "mpm/rfdc/xrfdc.h"
+#ifdef __BAREMETAL__
+#include "xparameters.h"
+#else
+#include <dirent.h>
+#include <arpa/inet.h>
+#endif
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+#ifdef __BAREMETAL__
+extern XRFdc_Config XRFdc_ConfigTable[];
+#else
+static XRFdc_Config *XRFdc_ConfigTablePtr=NULL;
+#endif
+
+#ifndef __BAREMETAL__
+/*****************************************************************************/
+/**
+*
+* Compare two strings in the reversed order.This function compares only
+* the last "Count" number of characters of Str1Ptr and Str2Ptr.
+*
+* @param Str1Ptr is base address of first string
+* @param Str2Ptr is base address of second string
+* @param Count is number of last characters to be compared between
+* Str1Ptr and Str2Ptr
+*
+* @return
+* 0 if last "Count" number of bytes matches between Str1Ptr and
+* Str2Ptr, else differnce in unmatched character.
+*
+*@note None.
+*
+******************************************************************************/
+static s32 XRFdc_Strrncmp(const char *Str1Ptr, const char *Str2Ptr, size_t Count)
+{
+ u16 Len1 = strlen(Str1Ptr);
+ u16 Len2 = strlen(Str2Ptr);
+ u8 Diff;
+
+ for (; Len1 && Len2; Len1--, Len2--) {
+ if ((Diff = Str1Ptr[Len1 - 1] - Str2Ptr[Len2 - 1]) != 0) {
+ return Diff;
+ }
+ if (--Count == 0) {
+ return 0;
+ }
+ }
+
+ return (Len1 - Len2);
+}
+
+/*****************************************************************************/
+/**
+*
+* Traverse "/sys/bus/platform/device" directory, to find RFDC device entry,
+* corresponding to provided device id. If device entry corresponding to said
+* device id is found, store it in output buffer DevNamePtr.
+*
+* @param DevNamePtr is base address of char array, where device name
+* will be stored
+* @param DevId contains the ID of the device to look up the
+* RFDC device name entry in "/sys/bus/platform/device"
+*
+* @return
+ * - XRFDC_SUCCESS if successful.
+ * - XRFDC_FAILURE if device entry not found for given device id.
+ *
+ *@note None.
+*
+******************************************************************************/
+s32 XRFdc_GetDeviceNameByDeviceId(char *DevNamePtr, u16 DevId)
+{
+ s32 Status = XRFDC_FAILURE;
+ u32 Data = 0;
+ char CompatibleString[NAME_MAX];
+ struct metal_device *DevicePtr;
+ DIR *DirPtr;
+ struct dirent *DirentPtr;
+ char Len = strlen(XRFDC_COMPATIBLE_STRING);
+ char SignLen = strlen(XRFDC_SIGNATURE);
+
+ DirPtr = opendir(XRFDC_PLATFORM_DEVICE_DIR);
+ if (DirPtr) {
+ while ((DirentPtr = readdir(DirPtr)) != NULL) {
+ if (XRFdc_Strrncmp(DirentPtr->d_name,
+ XRFDC_SIGNATURE, SignLen) == 0) {
+ Status = metal_device_open("platform",DirentPtr->d_name,
+ &DevicePtr);
+ if (Status) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to open device %s", DirentPtr->d_name);
+ continue;
+ }
+ Status = metal_linux_get_device_property(DevicePtr,
+ XRFDC_COMPATIBLE_PROPERTY, CompatibleString ,
+ Len);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property");
+ } else if (strncmp(CompatibleString, \
+ XRFDC_COMPATIBLE_STRING, Len) == 0) {
+ Status = metal_linux_get_device_property(DevicePtr,
+ XRFDC_CONFIG_DATA_PROPERTY,
+ &Data, XRFDC_DEVICE_ID_SIZE);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property");
+ } else if ( Data == DevId ) {
+ strcpy(DevNamePtr, DirentPtr->d_name);
+ Status = XRFDC_SUCCESS;
+ metal_device_close(DevicePtr);
+ break;
+ }
+ }
+ metal_device_close(DevicePtr);
+ }
+ }
+ closedir(DirPtr);
+ }
+ return Status;
+}
+#endif
+/*****************************************************************************/
+/**
+*
+* Looks up the device configuration based on the unique device ID. A table
+* contains the configuration info for each device in the system.
+*
+* @param DeviceId contains the ID of the device to look up the
+* configuration for.
+*
+* @return
+*
+* A pointer to the configuration found or NULL if the specified device ID was
+* not found. See xrfdc.h for the definition of XRFdc_Config.
+*
+* @note None.
+*
+******************************************************************************/
+XRFdc_Config *XRFdc_LookupConfig(u16 DeviceId)
+{
+ XRFdc_Config *CfgPtr = NULL;
+#ifndef __BAREMETAL__
+ s32 Status=0;
+ u32 NumInstances;
+ struct metal_device *Deviceptr;
+ char DeviceName[NAME_MAX];
+
+ Status = XRFdc_GetDeviceNameByDeviceId(DeviceName, DeviceId);
+ if (Status != XRFDC_SUCCESS) {
+ metal_log(METAL_LOG_ERROR, "\n Invalid device id %d", DeviceId);
+ goto RETURN_PATH2;
+ }
+
+ Status = metal_device_open(XRFDC_BUS_NAME, DeviceName, &Deviceptr);
+ if (Status) {
+ metal_log(METAL_LOG_ERROR, "\n Failed to open device %s", DeviceName);
+ goto RETURN_PATH2;
+ }
+
+ if (XRFdc_ConfigTablePtr == NULL) {
+ Status = metal_linux_get_device_property(Deviceptr,
+ XRFDC_NUM_INSTANCES_PROPERTY,
+ &NumInstances, XRFDC_NUM_INST_SIZE);
+ if (Status < 0) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property %s",
+ XRFDC_NUM_INSTANCES_PROPERTY);
+ goto RETURN_PATH1;
+ }
+ XRFdc_ConfigTablePtr = (XRFdc_Config*) malloc(ntohl(NumInstances) * \
+ XRFDC_CONFIG_DATA_SIZE);
+ if (XRFdc_ConfigTablePtr == NULL) {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to allocate memory for XRFdc_ConfigTablePtr");
+ goto RETURN_PATH1;
+ }
+ }
+ Status = metal_linux_get_device_property(Deviceptr,
+ XRFDC_CONFIG_DATA_PROPERTY,
+ &XRFdc_ConfigTablePtr[DeviceId],
+ XRFDC_CONFIG_DATA_SIZE);
+ if (Status == XRFDC_SUCCESS) {
+ CfgPtr = &XRFdc_ConfigTablePtr[DeviceId];
+ } else {
+ metal_log(METAL_LOG_ERROR,
+ "\n Failed to read device tree property %s",
+ XRFDC_CONFIG_DATA_PROPERTY);
+
+ }
+RETURN_PATH1:
+ metal_device_close(Deviceptr);
+RETURN_PATH2:
+#else
+ u32 Index;
+
+ for (Index = 0U; Index < (u32)XPAR_XRFDC_NUM_INSTANCES; Index++) {
+ if (XRFdc_ConfigTable[Index].DeviceId == DeviceId) {
+ CfgPtr = &XRFdc_ConfigTable[Index];
+ break;
+ }
+ }
+#endif
+ return (XRFdc_Config *)CfgPtr;
+}
+/** @} */