/****************************************************************************** * * 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. * *
* 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.
*
* 
* ******************************************************************************/ /***************************** Include Files *********************************/ #define METAL_INTERNAL #include "mpm/rfdc/xrfdc.h" #ifdef __BAREMETAL__ #include "xparameters.h" #else #include #include #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; } /** @} */