ASR_BASE
Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/marvell/services/dxslic/api_lib/src/dxs_init.c b/marvell/services/dxslic/api_lib/src/dxs_init.c
new file mode 100644
index 0000000..e5ab2eb
--- /dev/null
+++ b/marvell/services/dxslic/api_lib/src/dxs_init.c
@@ -0,0 +1,1241 @@
+/******************************************************************************
+
+ Copyright (c) 2014-2015 Lantiq Deutschland GmbH
+ Copyright (c) 2015-2016 Lantiq Beteiligungs-GmbH & Co.KG
+ Copyright 2016, Intel Corporation.
+
+ For licensing information, see the file 'LICENSE' in the root folder of
+ this software module.
+
+******************************************************************************/
+
+/**
+ \file dxs_init.c
+ Implementation of initialization functions.
+*/
+
+/* ========================================================================== */
+/* Includes */
+/* ========================================================================== */
+#include <stdlib.h>
+
+#include "dxs_config.h"
+#include "dxs_version.h"
+#include "dxs_init.h"
+#include "dxs_errno.h"
+#include "dxs_error.h"
+#include "dxs_fw_cmd.h"
+#include "dxs_pcm.h"
+#include "dxs_sdd.h"
+#include "dxs_sig.h"
+#include "dxs_gpio.h"
+#include "dxs_access.h"
+#include "dxs_cid.h"
+#include "dxs_pollint.h"
+#include "dxs_outbox.h"
+#include "dxs_event.h"
+#include "dxs_spi.h"
+#include "dxs_dcdc_hw.h"
+#include "dxs_ring.h"
+#ifdef EVENT_LOGGER_DEBUG
+#include <sys/ioctl.h>
+#endif
+
+const char DXS_WHATVERSION[] = DXS_WHAT_STR;
+
+/* ========================================================================== */
+/* Macro definitions */
+/* ========================================================================== */
+
+/* ========================================================================== */
+/* Type definitions */
+/* ========================================================================== */
+/** Data structure for DXS_FW_SYS_VERS_ECMD firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ CMD_HEAD_BE;
+ /** Device Number */
+ uint32_t DEVNR : 11;
+ /** Calender Week */
+ uint32_t CW : 6;
+ /** Production Year */
+ uint32_t YEAR : 6;
+ /** Channel */
+ uint32_t CH : 1;
+ /** Device ID Representing PEB Number */
+ uint32_t DEV : 8;
+ /** Major */
+ uint32_t MAJ : 8;
+ /** Minor */
+ uint32_t MIN : 8;
+ /** Hotfix */
+ uint32_t HF : 8 ;
+ /** Reserved */
+ uint32_t Res02 : 8;
+ /** Time Stamp */
+ uint32_t TIME;
+#else
+ CMD_HEAD_LE;
+ /** Device ID Representing PEB Number */
+ uint32_t DEV : 8;
+ /** Channel */
+ uint32_t CH : 1;
+ /** Production Year */
+ uint32_t YEAR : 6;
+ /** Calender Week */
+ uint32_t CW : 6;
+ /** Device Number */
+ uint32_t DEVNR : 11;
+ /** Reserved */
+ uint32_t Res02 : 8;
+ /** Hotfix */
+ uint32_t HF : 8 ;
+ /** Minor */
+ uint32_t MIN : 8;
+ /** Major */
+ uint32_t MAJ : 8;
+ /** Time Stamp */
+ uint32_t TIME;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_VERS_t;
+#define DXS_FW_SYS_VERS_ECMD 6
+#define DXS_FW_SYS_VERS_LENGTH 12
+
+/** Data structure for system capabilities firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ CMD_HEAD_BE;
+ /* Reserved */
+ uint32_t Res02 : 25;
+ /* Howler Support Available */
+ uint32_t HOWLER : 1;
+ /* Caller ID Available */
+ uint32_t CID : 1;
+ /* Universal Tone Detector Available */
+ uint32_t UTD : 1;
+ /* Teletax Support Available */
+ uint32_t TTX : 1;
+ /* Reserved */
+ uint32_t Res03 : 1;
+ /* AC Level Meter Support Available */
+ uint32_t ACLM : 1;
+ /* GR909 available */
+ uint32_t GR909 : 1;
+#else
+ CMD_HEAD_LE;
+ /* GR909 available */
+ uint32_t GR909 : 1;
+ /* AC Level Meter Support Available */
+ uint32_t ACLM : 1;
+ /* Reserved */
+ uint32_t Res03 : 1;
+ /* Teletax Support Available */
+ uint32_t TTX : 1;
+ /* Universal Tone Detector Available */
+ uint32_t UTD : 1;
+ /* Caller ID Available */
+ uint32_t CID : 1;
+ /* Howler Support Available */
+ uint32_t HOWLER : 1;
+ /* Reserved */
+ uint32_t Res02 : 25;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_CAPS_t;
+#define DXS_FW_SYS_CAPS_ECMD 7
+#define DXS_FW_SYS_CAPS_LENGTH 4
+
+/** Data structure for DXS_FW_SYS_Control_ECMD firmware command */
+typedef struct
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ CMD_HEAD_BE;
+ /* Reserved */
+ uint32_t Res02 : 25;
+ /* Sync-Fail/ Clock-Fail Handling Enable */
+ uint32_t SYCLKE : 1;
+ /* PLL Limiter Enable */
+ uint32_t PLIM : 1;
+ /* Charge Pump Voltage Level */
+ uint32_t CP_VOLT : 3;
+ /* Charge Pump Enable */
+ uint32_t CP_EN : 1;
+ /* Sleep Enable */
+ uint32_t SE : 1;
+#else
+ CMD_HEAD_LE;
+ /* Sleep Enable */
+ uint32_t SE : 1;
+ /* Charge Pump Enable */
+ uint32_t CP_EN : 1;
+ /* Charge Pump Voltage Level */
+ uint32_t CP_VOLT : 3;
+ /* PLL Limiter Enable */
+ uint32_t PLIM : 1;
+ /* Sync-Fail/ Clock-Fail Handling Enable */
+ uint32_t SYCLKE : 1;
+ /* Reserved */
+ uint32_t Res02 : 25;
+#endif
+} __attribute__ ((packed)) DXS_FW_SYS_Control_t;
+#define DXS_FW_SYS_Control_ECMD 8
+#define DXS_FW_SYS_Control_LENGTH 4
+#define DXS_FW_SYS_Control_CP_VOLT_5_0V 3
+
+/** Device capabilities */
+typedef struct
+{
+ /* status flag */
+ uint32_t flag;
+#define DXS_DEV_CAPS_INITIALIZED 1
+#define DXS_DEV_CAPS_UPDATED 2
+#define DXS_DEV_SYS_CTRL_UPDATED 4
+ /* device version */
+ DXS_Dev_t dev;
+ /* device package */
+ DXS_Package_t pack;
+ /* firmware version */
+ DXS_FW_SYS_VERS_t fw_vers;
+ /* firmware capabilities */
+ DXS_FW_SYS_CAPS_t fw_caps;
+ /* firmware system control */
+ DXS_FW_SYS_Control_t fw_sys_ctrl;
+} DXS_Dev_Caps_t;
+
+/* ========================================================================== */
+/* Global variables */
+/* ========================================================================== */
+/* static data */
+static DXS_DEVICE_t dxs_devices[DXS_MAX_DEVICES] = {0};
+static DXS_Dev_Caps_t dxs_caps[DXS_MAX_DEVICES] = {0};
+
+/* ========================================================================== */
+/* Function prototypes */
+/* ========================================================================== */
+static int32_t dxs_controller_reset(DXS_DEVICE_t *pDev);
+
+/* ========================================================================== */
+/* Function implementation */
+/* ========================================================================== */
+#ifdef EVENT_LOGGER_DEBUG
+static void dxs_el_register(DXS_DEVICE_t *pDev)
+{
+ EL_IoctlRegister_t el_reg;
+ int ret;
+
+ pDev->el_fd = open(EL_DEVICE_NAME, 2, 0644);
+ if (pDev->el_fd < 0)
+ {
+ return;
+ }
+ else
+ {
+ snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
+
+ el_reg.nType = DXS_LIB_DEV_TYPE;
+ el_reg.nDevNum = pDev->nDevNum;
+
+ ret = ioctl(pDev->el_fd, EL_REGISTER, (int32_t)&el_reg);
+ if (ret == IFX_SUCCESS)
+ {
+ IFX_char_t *pCmd ="echo \"*\" > /proc/driver/el/logs/all";
+ FILE *el_pipe_fd;
+
+ el_pipe_fd = popen(pCmd, "r");
+ if (!el_pipe_fd)
+ {
+ return;
+ }
+ pclose(el_pipe_fd);
+ }
+ }
+}
+
+static void dxs_el_unregister(DXS_DEVICE_t *pDev)
+{
+ EL_IoctlRegister_t el_reg;
+
+ snprintf(el_reg.sName, sizeof(el_reg.sName), "dxs_lib");
+ el_reg.nType = DXS_LIB_DEV_TYPE;
+ el_reg.nDevNum = pDev->nDevNum;
+
+ if (pDev->el_fd > 0)
+ {
+ ioctl(pDev->el_fd, EL_UNREGISTER, (int32_t)&el_reg);
+ }
+}
+#endif
+
+/**
+ Function dxs_caps_init
+
+ \param dev - device number
+
+*/
+static void *dxs_caps_init(uint8_t dev)
+{
+ DXS_Dev_Caps_t *p;
+
+ if (dev >= DXS_MAX_DEVICES)
+ return (void *)NULL;
+
+ p = &dxs_caps[dev];
+
+ p->flag = 0;
+
+ p->fw_vers.CMD = CMD_EOP;
+ p->fw_vers.MOD = MOD_SYS;
+ p->fw_vers.ECMD = DXS_FW_SYS_VERS_ECMD;
+ p->fw_vers.LENGTH = DXS_FW_SYS_VERS_LENGTH;
+
+ p->fw_caps.CMD = CMD_EOP;
+ p->fw_caps.MOD = MOD_SYS;
+ p->fw_caps.ECMD = DXS_FW_SYS_CAPS_ECMD;
+ p->fw_caps.LENGTH = DXS_FW_SYS_CAPS_LENGTH;
+
+ p->fw_sys_ctrl.CMD = CMD_EOP;
+ p->fw_sys_ctrl.MOD = MOD_SYS;
+ p->fw_sys_ctrl.ECMD = DXS_FW_SYS_Control_ECMD;
+ p->fw_sys_ctrl.LENGTH = DXS_FW_SYS_Control_LENGTH;
+
+ p->flag |= DXS_DEV_CAPS_INITIALIZED;
+
+ return (void *)p;
+}
+
+/**
+ Function dxs_caps_vers_update
+
+ \param pDev - pointer to DXS device structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_caps_vers_update(DXS_DEVICE_t *pDev)
+{
+ DXS_Dev_Caps_t *p;
+ int32_t err;
+
+ if (pDev == NULL)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+ p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+ {
+ DXS_RETURN(DXS_statusNotInitResource);
+ }
+
+ if (!(p->flag & DXS_DEV_CAPS_UPDATED))
+ {
+ err = CmdRead(pDev, (uint32_t *)&p->fw_caps, (uint32_t *)&p->fw_caps);
+ if (err)
+ {
+ DXS_RETURN(DXS_statusCapVersUpdateError);
+ }
+ err = CmdRead(pDev, (uint32_t *)&p->fw_vers, (uint32_t *)&p->fw_vers);
+ if (err)
+ {
+ DXS_RETURN(DXS_statusCapVersUpdateError);
+ }
+ /* update device ROM version */
+ pDev->rom_mask_ver = p->fw_vers.MAJ & 0x7F;
+
+ if (p->fw_vers.DEV == 0x9)
+ {
+ /* XS_VQFN-68_ES DXS Engineering Sample (A11 design)
+ in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ if (p->fw_vers.CH == 0)
+ {
+ p->dev = DXS_DEV_PEF32002_A11;
+ pDev->nChannels = 2;
+ }
+ else
+ {
+ p->dev = DXS_DEV_PEF32001_A11;
+ pDev->nChannels = 1;
+ }
+ }
+ else if (p->fw_vers.DEV == 0xA)
+ {
+ /* XS_VQFN-68_V11 DXS V1.1 (A12 design)
+ in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ if (p->fw_vers.CH == 0)
+ {
+ p->dev = DXS_DEV_PEF32002_A12;
+ pDev->nChannels = 2;
+ }
+ else
+ {
+ p->dev = DXS_DEV_PEF32001_A12;
+ pDev->nChannels = 1;
+ }
+ }
+ else if (p->fw_vers.DEV == 0x2A)
+ {
+ /* XC_VQFN-68_V11 DXC2 V1.1 (A12 design)
+ in PG-VQFN-68 package, only 2 channel version */
+ p->pack = DXS_PACKAGE_VQFN68;
+ p->dev = DXC_DEV_PEF31002_A12;
+ pDev->nChannels = 2;
+ }
+ else if (p->fw_vers.DEV == 0x49)
+ {
+ /* XS_VQFN-48_ES DXS1 Engineering Sample (A11 design)
+ in PG-VQFN-48 package */
+ p->pack = DXS_PACKAGE_VQFN48;
+ p->dev = DXS_DEV_PEF32001_A11;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x4A)
+ {
+ /* XS_VQFN-48_V11 DXS1 V1.1 (A12 design)
+ in PG-VQFN-48 package */
+ p->pack = DXS_PACKAGE_VQFN48;
+ p->dev = DXS_DEV_PEF32001_A12;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x6A)
+ {
+ /* XC_VQFN-48_V11 DXC1 V1.1 (A12 design)
+ in PG-VQFN-48 package */
+ p->pack = DXS_PACKAGE_VQFN48;
+ p->dev = DXC_DEV_PEF31001_A12;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x0B)
+ {
+ /* XS_VQFN-68_V12 DXS2 V1.2 (A13 design)
+ in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ p->dev = DXS_DEV_PEF32002_V12_A13;
+ pDev->nChannels = 2;
+ }
+ else if (p->fw_vers.DEV == 0x2B)
+ {
+ /* XC_VQFN-68_V12 DXC2 V1.2 (A13 design)
+ in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ p->dev = DXC_DEV_PEF31002_V12_A13;
+ pDev->nChannels = 2;
+ }
+ else if (p->fw_vers.DEV == 0x8C)
+ {
+ /* XS_VQFN-44_V12 DXS1 V1.2
+ (A11 new codec design) in PG-VQFN-44 package */
+ p->pack = DXS_PACKAGE_VQFN44;
+ p->dev = DXS_DEV_PEF32001_V12_A11;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0xAC)
+ {
+ /* XC_VQFN-44_V12 DXC1 V1.2
+ (A11 new codec design) in PG-VQFN-44 package */
+ p->pack = DXS_PACKAGE_VQFN44;
+ p->dev = DXC_DEV_PEF31001_V12_A11;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x4C)
+ {
+ /* XS_VQFN-48_V12 DXS1 V1.2
+ (A11 new codec design) in PG-VQFN-48 package */
+ p->pack = DXS_PACKAGE_VQFN48;
+ p->dev = DXS_DEV_PEF32001_V12_A11;
+ pDev->nChannels = 1;
+
+ }
+ else if (p->fw_vers.DEV == 0x6C)
+ {
+ /* XC_VQFN-48_V12 DXC1 V1.2
+ (A11 new codec design) in PG-VQFN-48 package */
+ p->pack = DXS_PACKAGE_VQFN48;
+ p->dev = DXC_DEV_PEF31001_V12_A11;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x0C)
+ {
+ /* XS_VQFN-68_V12 DXS1 V1.2
+ (A11 new codec design) in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ p->dev = DXS_DEV_PEF32001_V12_A11;
+ pDev->nChannels = 1;
+ }
+ else if (p->fw_vers.DEV == 0x2C)
+ {
+ /* XC_VQFN-68_V12 DXC1 V1.2
+ (A11 new codec design) in PG-VQFN-68 package */
+ p->pack = DXS_PACKAGE_VQFN68;
+ p->dev = DXC_DEV_PEF31001_V12_A11;
+ pDev->nChannels = 1;
+ }
+ else
+ {
+ p->pack = DXS_PACKAGE_UNKNOWN;
+ p->dev = DXS_DEV_UNKNOWN;
+ /* default for unfused device */
+ pDev->nChannels = 1;
+ }
+
+ p->flag |= DXS_DEV_CAPS_UPDATED;
+ }
+
+ return DXS_statusOk;
+}
+
+/**
+ Function dxs_caps_vers_forget
+
+ \param pDev - pointer to DXS device structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_caps_vers_forget(DXS_DEVICE_t *pDev)
+{
+ DXS_Dev_Caps_t *p;
+
+ if (pDev == NULL)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+ p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ p->flag &= ~DXS_DEV_CAPS_UPDATED;
+
+ return DXS_statusOk;
+}
+
+/**
+ Function dxs_get_dev
+
+ \param dxs - device number
+
+ \return
+ - pointer to DxS device structure
+*/
+DXS_DEVICE_t *dxs_get_dev (uint8_t dxs)
+{
+ if (dxs >= DXS_MAX_DEVICES)
+ return NULL;
+
+ return &dxs_devices[dxs];
+}
+
+
+/**
+ Calculate CRC-8-CCITT. POLYNOMIAL = 0x07
+
+ \param pData Pointer to data for CRC calculation
+ \param nLength Length of data buffer
+
+ \return
+ Calculated CRC value.
+*/
+uint8_t dxs_CRC_8_CCITT(uint8_t *pData, uint32_t nLength)
+{
+ uint8_t nCRC = 0;
+ int32_t i, j;
+
+ /* Perform modulo-2 division, a byte at a time. */
+ for (i = 0; i < nLength; i++)
+ {
+ /* Bring the next byte into the nCRC. */
+ nCRC ^= pData[i];
+
+ /* Perform modulo-2 division, a bit at a time. */
+ for (j = 8; j > 0; j--)
+ {
+ /* Try to divide the current data bit. */
+ if (nCRC & 0x80)
+ nCRC = (nCRC << 1) ^ 0x07;
+ else
+ nCRC = (nCRC << 1);
+ }
+ }
+ return nCRC;
+}
+
+
+/**
+ Function dxs_exit
+
+ \param pDev - pointer to DXS device structure
+
+*/
+int32_t dxs_exit(DXS_DEVICE_t *pDev)
+{
+ uint8_t ch;
+ int32_t ret = DXS_statusOk;
+
+ if (pDev->flags & DXS_DEV_INITIALIZED)
+ {
+ /* DCDC HW specific deinit */
+ DXS_DCDC_HW_Exit(pDev);
+
+ if (pDev->irqNumber == -1)
+ {
+ /* stop polling */
+ dxs_polling_timer_stop();
+ }
+ else
+ {
+ /* uninstall interrupt handler */
+ dxs_interrupt_exit();
+ }
+
+ /* stop obx handling thread */
+ dxs_outbox_handler_exit(pDev);
+ pDev->flags &= ~DXS_DEV_OBX_HND_INITIALIZED;
+
+ /* uninitialize event memory pool */
+ dxs_event_pool_exit(pDev);
+
+ /* uninitialize message queues */
+ fifo_destroy(pDev->event_queue);
+ fifo_destroy(pDev->cmd_obx_queue);
+
+ /* close SPI interface */
+ dxs_spi_linux_exit(pDev->spidev);
+ pDev->flags &= ~DXS_DEV_ACCESS_INITIALIZED;
+
+ /* delete mbx access mutex */
+ ret = pthread_mutex_unlock(&pDev->mtxMbxAcc);
+ if (ret != 0)
+ DXS_ERROR_PUSH(ret);
+ ret = pthread_mutex_destroy(&pDev->mtxMbxAcc);
+ if (ret != 0)
+ DXS_ERROR_PUSH(ret);
+
+ sem_destroy(&pDev->mtxPatchDwld);
+
+#ifdef DXS_FEAT_UTD
+ /* delete UTD mutex */
+ dxs_sig_utd_mtx_destroy();
+#endif /* DXS_FEAT_UTD */
+
+ /* close channel resources */
+ for (ch = 0; ch < pDev->nChannels; ch++)
+ {
+ DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
+
+#ifdef DXS_FEAT_HSM
+ DXS_Dial_Cleanup(pCh);
+#endif
+ /* cleanup only for SDD resource */
+ ret = DXS_SDD_ChExit(pCh);
+ if (ret != DXS_statusOk)
+ DXS_ERROR_PUSH(ret);
+ }
+
+#ifdef EVENT_LOGGER_DEBUG
+ dxs_el_unregister(pDev);
+#endif /* EVENT_LOGGER_DEBUG */
+
+ pDev->flags &= ~DXS_DEV_INITIALIZED;
+ }
+ DXS_RETURN(ret);
+}
+
+/**
+ Default initialization of DXS registers.
+
+ Enable the required interrupts in the register interface.
+
+ \param pDev pointer to the device structure
+
+ \return
+ - DXS_statusOk
+ - DXS_statusSpiAccError
+*/
+static int32_t dxs_default_reg_init(DXS_DEVICE_t *pDev)
+{
+ int32_t ret = DXS_statusOk;
+ uint16_t nRegHostIen1, nRegHostIen2;
+
+ /*
+ Enable the interrupts OBX_RDY and ERR.
+ */
+ nRegHostIen1 = DXS_REG_IEN1_RESET;
+ nRegHostIen1 |= DXS_REG_IEN1_OBX_RDY;
+ nRegHostIen1 |= DXS_REG_IEN1_ERR;
+ ret = DXS_RegWrite(pDev, DXS_REG_IEN1, nRegHostIen1);
+ if (ret != DXS_statusOk)
+ DXS_RETURN(ret);
+
+ /*
+ Enable the interrupts OBX_UFL and IBX_OFL.
+ */
+ nRegHostIen2 = DXS_REG_IEN2_RESET;
+ nRegHostIen2 |= DXS_REG_IEN2_OBX_UFL;
+ nRegHostIen2 |= DXS_REG_IEN2_IBX_OFL;
+ ret = DXS_RegWrite(pDev, DXS_REG_IEN2, nRegHostIen2);
+
+ DXS_RETURN(ret);
+}
+
+/**
+ Function dxs_init
+
+ \param pDev - pointer to DXS device structure
+ \param chipSelect - CS number
+ \param irqNumber - IRQ line number
+ \param dcdcType - DCDC variant handled by DXS_DCDC_Var_t type
+ \param dev - device number
+
+ \return
+ - DXS_status_t
+*/
+/*
+ * should return either 0 or -1
+ */
+int32_t dxs_init(DXS_DEVICE_t *pDev, uint8_t chipSelect, int32_t irqNumber,
+ uint8_t dcdcType, uint8_t access, uint8_t dev)
+{
+ int32_t ret = DXS_statusOk, i;
+#ifdef DXS_FEAT_HSM
+ DXS_status_t status;
+#endif
+ uint8_t ch;
+
+ if (access >= DXS_ACCESS_LAST)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+
+ if (dev >= DXS_MAX_DEVICES)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+
+ for (i=0; i<DXS_MAX_DEVICES; i++)
+ {
+ DXS_DEVICE_t *pdev = dxs_get_dev(i);
+
+ if (pdev->flags & DXS_DEV_INITIALIZED && pdev->dcdcType != dcdcType)
+ {
+ /* provided dcdcType does not match
+ with previously initialized devices */
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+ }
+
+ ret = dxs_exit(pDev);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(DXS_statusDevInitFailed);
+ }
+
+ pDev->nDevNum = dev;
+ pDev->chipSelect = chipSelect;
+ pDev->irqNumber = irqNumber;
+ pDev->dcdcType = dcdcType;
+ pDev->access = access;
+
+ pthread_mutex_init(&pDev->mtxMbxAcc, NULL);
+ pDev->nMbxCachedCbiLen = 0;
+
+#ifdef EVENT_LOGGER_DEBUG
+ dxs_el_register(pDev);
+#endif
+
+ /* open SPI interface */
+ pDev->spidev = dxs_spi_linux_init(chipSelect, access);
+ if (pDev->spidev > 0)
+ {
+ pDev->flags |= DXS_DEV_ACCESS_INITIALIZED;
+ }
+ else
+ {
+ DXS_RETURN(DXS_statusSpiOpenError);
+ }
+
+ /* TODO: light chip access test + error code if failed */
+
+ /* Reset the DXS controller to bring the chip into the default state.
+ The data structures of the driver will be initialized to the same
+ known default state.*/
+ dxs_controller_reset(pDev);
+
+ /* initialize message queues */
+ pDev->event_queue = fifo_init (20);
+ if (NULL == pDev->event_queue)
+ {
+ DXS_RETURN(DXS_statusMsgQueueCreatError);
+ }
+ pDev->cmd_obx_queue = fifo_init (64);
+ if (NULL == pDev->cmd_obx_queue)
+ {
+ DXS_RETURN(DXS_statusMsgQueueCreatError);
+ }
+
+ /* initialize event memory pool */
+ if (DXS_statusOk != dxs_event_pool_init(pDev))
+ {
+ DXS_RETURN(DXS_statusMpoolInitError);
+ }
+
+ /* start obx handling thread */
+ ret = dxs_outbox_handler_init(pDev);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(DXS_statusObxHandlerStartError);
+ }
+ pDev->flags |= DXS_DEV_OBX_HND_INITIALIZED;
+
+ /* initialize device resources */
+ pDev->caps = dxs_caps_init(dev);
+ pDev->pcm = dxs_pcm_dev_init(dev);
+
+ if (pDev->access == DXS_ACCESS_CSI)
+ {
+ /* default configuration of CSI Master */
+ uint16_t nCSIMasterCFG =
+ (DXS_REG_CSI_M_CFG_PAUSE_DEFAULT | DXS_REG_CSI_M_CFG_PDEMUX);
+ ret = DXS_RegWrite(pDev, DXS_REG_CSI_M_CFG, nCSIMasterCFG);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(ret);
+ }
+ }
+
+#ifdef DXS_FEAT_GPIO
+ pDev->gpio = DXS_GPIO_DevInit(dev);
+#endif
+
+ /* start device polling */
+ if (pDev->irqNumber != 255 &&
+ (pDev->irqNumber == -1 || dxs_interrupt_init(pDev) != DXS_statusOk))
+ {
+ dxs_polling_timer_start();
+ }
+
+ /* In IRQ as well as polling mode set the interrupt masks. */
+ ret = dxs_default_reg_init(pDev);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(ret);
+ }
+
+ /* read capabilities and version from device -
+ must be after polling start or interrupt enable */
+ dxs_caps_vers_update(pDev);
+
+#ifdef DXS_FEAT_UTD
+ /* initialize UTD mutex */
+ dxs_sig_utd_mtx_init();
+#endif /* DXS_FEAT_UTD */
+
+ /* initialize channel resources -
+ must be after capabilities read */
+ for (ch = 0; ch < pDev->nChannels; ch++)
+ {
+ DXS_CHANNEL_t *pCh = &pDev->pChannel[ch];
+
+ pCh->pParent = pDev;
+ pCh->nCh = ch;
+ pCh->pcm = dxs_pcm_ch_init(pDev->nDevNum, ch);
+ pCh->sdd = DXS_SDD_ChInit(pDev->nDevNum, ch);
+ pCh->sig = dxs_sig_ch_init(pDev->nDevNum, ch);
+#ifdef DXS_FEAT_HSM
+ status = DXS_Dial_Initialise_Unprot(pCh);
+ if (status != DXS_statusOk)
+ {
+ DXS_RETURN(status);
+ }
+#endif
+#ifdef DXS_FEAT_CID
+ /* cleanup static data */
+ DXS_CID_Cleanup(pCh);
+#endif
+ pCh->ring = DXS_Ring_ResInit(pCh);
+ DXS_EventMaskSetDefault(pCh);
+ }
+
+ /* From now on process all events. */
+ dxs_outbox_handler_enable(pDev);
+
+ /* patch download sync sem */
+ sem_init(&pDev->mtxPatchDwld, 0, 0);
+ pDev->bWaitingInPatchDwld = 0;
+
+ /* DCDC HW specific init */
+ DXS_DCDC_HW_Init(pDev);
+
+ pDev->flags |= DXS_DEV_INITIALIZED;
+
+ return DXS_statusOk;
+}
+
+/**
+ Function dxs_controller_reset
+
+ \param pDev - pointer to DXS device structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_controller_reset(DXS_DEVICE_t *pDev)
+{
+ int32_t ret = DXS_statusOk;
+ uint16_t nDxsRegBootCfg = 0,
+ nDxsRegBootInfo = 0,
+ nDxsRegCfg = 0;
+
+ /* Set the controller startup configuration in the Boot Configuration
+ Register to boot from ROM. */
+ nDxsRegBootCfg = DXS_REG_BCFG_ASC_ROM;
+ ret = DXS_RegWrite(pDev, DXS_REG_BCFG, nDxsRegBootCfg);
+ if (ret != DXS_statusOk)
+ {
+ /* errmsg: Setting of boot configuration register failed. */
+ ret = DXS_statusSetBootCfgErr;
+ }
+
+ /* Reset controller to start the boot. */
+ if (ret == DXS_statusOk)
+ {
+ nDxsRegCfg = DXS_REG_CFG_RST_RSTCORE|DXS_REG_CFG_8BIT_EN;
+ ret = DXS_RegWrite(pDev, DXS_REG_CFG, nDxsRegCfg);
+ if (ret != DXS_statusOk)
+ {
+ /* errmsg: Controller reset failed. */
+ ret = DXS_statusCtrlResErr;
+ }
+ }
+
+ /* Check success of the reset by reading the boot info register. */
+ if (ret == DXS_statusOk)
+ {
+ uint8_t loop = 10;
+
+ while (loop > 0)
+ {
+ struct timespec ts = {0, 2000000}; /* 2 ms */
+
+ nanosleep(&ts, NULL);
+
+ /* read the boot state indication */
+ ret = DXS_RegRead(pDev, DXS_REG_BINF, &nDxsRegBootInfo);
+
+ if ((ret == DXS_statusOk) &&
+ ((nDxsRegBootInfo & DXS_REG_BINF_BOOTSTATE_MASK) >= 0x10))
+ {
+ break;
+ }
+
+ loop--;
+ }
+
+ if (loop == 0)
+ {
+ /* errmsg: Firmware download timeout. */
+ ret = DXS_statusFwDwldTimeout;
+ }
+ }
+
+ DXS_RETURN(ret);
+}
+
+/**
+ Function dxs_caps_read
+
+ \param pDev - pointer to DXS device structure
+ \param pCap - pointer to DXS_Caps_t structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_caps_read(DXS_DEVICE_t *pDev, DXS_Caps_t *pCap)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ if (DXS_statusOk == dxs_caps_vers_update(pDev))
+ {
+ pCap->nChannels = pDev->nChannels;
+ pCap->nGR909 = p->fw_caps.GR909;
+ pCap->nACLM = p->fw_caps.ACLM;
+ pCap->nTTX = p->fw_caps.TTX;
+ pCap->nUTD = p->fw_caps.UTD;
+ pCap->nCID = p->fw_caps.CID;
+ pCap->nHowler = p->fw_caps.HOWLER;
+ }
+ else
+ {
+ DXS_RETURN(DXS_statusCapVersUpdateError);
+ }
+
+ return DXS_statusOk;
+}
+
+/**
+ Function dxs_vers_read
+
+ \param pDev - pointer to DXS device structure
+ \param pVersion - pointer to DXS_Version_t structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_vers_read(DXS_DEVICE_t *pDev, DXS_Version_t *pVersion)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ if (DXS_statusOk == dxs_caps_vers_update(pDev))
+ {
+ pVersion->device = p->dev;
+ pVersion->package = p->pack;
+
+ pVersion->fw_maj = p->fw_vers.MAJ;
+ pVersion->fw_min = p->fw_vers.MIN;
+ pVersion->fw_hfix = p->fw_vers.HF;
+ pVersion->fw_time = p->fw_vers.TIME;
+
+ pVersion->lib_ver = DXS_LIB_VERSION;
+ pVersion->api_ver = DXS_API_VERSION;
+ }
+ else
+ {
+ DXS_RETURN(DXS_statusCapVersUpdateError);
+ }
+
+ return DXS_statusOk;
+}
+
+/**
+ Function dxs_sleep
+
+ \param pDev - pointer to DXS device structure
+ \param enable - enable
+
+ \return
+ - DXS_status_t
+*/
+int32_t dxs_sleep(DXS_DEVICE_t *pDev, uint8_t enable)
+{
+ DXS_Dev_Caps_t *p;
+ int32_t ret = DXS_statusOk;
+
+ if (pDev == NULL || enable > 1)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+ p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+ {
+ DXS_RETURN(DXS_statusNotInitResource);
+ }
+
+ if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
+ {
+ ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(ret);
+ }
+ p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
+ }
+
+ /* sleep mode is not allowed for shared DCDC */
+ if (pDev->dcdcType == DXS_DCDC_IFB12CH8 && enable)
+ {
+ DXS_RETURN(DXS_statusSleepModeNotAllowed);
+ }
+
+ /* update command */
+ if (enable != p->fw_sys_ctrl.SE)
+ {
+ p->fw_sys_ctrl.SE = enable;
+ ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
+ }
+
+ DXS_RETURN(ret);
+}
+
+/**
+ Check if a particular feature is supported by the device
+
+ \param pDev - pointer to DXS device structure
+ \param cap - feature enumerator \ref e_DXS_DevCaps
+
+ \return
+ - 1 if a featire is supported, 0 if not
+*/
+int32_t DXS_IsFeatureSupported(DXS_DEVICE_t *pDev, enum e_DXS_DevCaps cap)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+ DXS_FW_SYS_CAPS_t *pCap = &p->fw_caps;
+ uint32_t sys_read_caps_I1 = *((uint32_t *)pCap + 1);
+
+ if (sys_read_caps_I1 & (1 << cap))
+ return 1;
+
+ return 0;
+}
+
+/**
+ Switch on the Charge Pump
+
+ \param pDev - pointer to DXS device structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t DXS_ChargePumpSwitchOn(DXS_DEVICE_t *pDev)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+ DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
+ int32_t ret = DXS_statusOk;
+
+ /* for IFB12CH8 apply the configuration only for the device
+ that owns a master channel */
+ if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+ {
+ DXS_CHANNEL_t *pCh, *pChMaster;
+ uint8_t i = 0, master_found = 0;
+
+ if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
+ {
+ for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
+ {
+ if (pCh == pChMaster)
+ {
+ master_found = 1;
+ break;
+ }
+ }
+
+ if (!master_found)
+ return DXS_statusOk;
+ }
+ }
+
+ if (pSysCtrl->CP_EN != 1)
+ {
+ pSysCtrl->CP_VOLT = DXS_FW_SYS_Control_CP_VOLT_5_0V;
+ pSysCtrl->CP_EN = 1;
+ ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
+ }
+
+ DXS_RETURN(ret);
+}
+
+#if 0
+/**
+ Switch off the Charge Pump
+
+ \param pDev - pointer to DXS device structure
+
+ \return
+ - DXS_status_t
+*/
+int32_t DXS_ChargePumpSwitchOff(DXS_DEVICE_t *pDev)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+ DXS_FW_SYS_Control_t *pSysCtrl = &p->fw_sys_ctrl;
+ int32_t ret = DXS_statusOk;
+
+ /* for IFB12CH8 apply the configuration only for the device
+ that owns a master channel */
+ if (pDev->dcdcType == DXS_DCDC_IFB12CH8)
+ {
+ DXS_CHANNEL_t *pCh, *pChMaster;
+ uint8_t i = 0, master_found = 0;
+
+ if ((pChMaster=DXS_DCDC_HW_SharedDcDcMasterChGetInt(pDev)) != NULL)
+ {
+ for (pCh=&pDev->pChannel[0],i=0; i < pDev->nChannels; i++, pCh++)
+ {
+ if (pCh == pChMaster)
+ {
+ master_found = 1;
+ break;
+ }
+ }
+
+ if (!master_found)
+ return DXS_statusOk;
+ }
+ }
+
+ if (pSysCtrl->CP_EN != 0)
+ {
+ pSysCtrl->CP_EN = 0;
+ ret = CmdWrite(pDev, (uint32_t *)pSysCtrl);
+ }
+
+ DXS_RETURN(ret);
+}
+#endif /* 0 */
+
+/**
+ Switch on/off Clock Failure handling
+
+ \param pDev - pointer to DXS device structure
+ \param enable - 0 or 1
+
+ \return
+ - DXS_status_t
+*/
+int32_t DXS_CfEsdSwitch (DXS_DEVICE_t *pDev, uint8_t enable)
+{
+ DXS_Dev_Caps_t *p;
+ int32_t ret = DXS_statusOk;
+ uint8_t plim;
+
+ if (pDev == NULL || enable > 1)
+ {
+ DXS_RETURN(DXS_statusInvalidParam);
+ }
+
+ p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ if (!(p->flag & DXS_DEV_CAPS_INITIALIZED))
+ {
+ DXS_RETURN(DXS_statusNotInitResource);
+ }
+
+ if (!(p->flag & DXS_DEV_SYS_CTRL_UPDATED))
+ {
+ ret = CmdRead(pDev, (uint32_t *)&p->fw_sys_ctrl, (uint32_t *)&p->fw_sys_ctrl);
+ if (ret != DXS_statusOk)
+ {
+ DXS_RETURN(ret);
+ }
+ p->flag |= DXS_DEV_SYS_CTRL_UPDATED;
+ }
+
+ plim = enable ? 0 : 1;
+
+ if (p->fw_sys_ctrl.PLIM != plim || p->fw_sys_ctrl.SYCLKE != enable)
+ {
+ p->fw_sys_ctrl.PLIM = plim;
+ p->fw_sys_ctrl.SYCLKE = enable;
+ ret = CmdWrite(pDev, (uint32_t *)&p->fw_sys_ctrl);
+ }
+
+ DXS_RETURN(ret);
+}
+
+/**
+ Get device info
+
+ \param pDev - pointer to DXS device structure
+ \param pROM_id - ROM mask ID (output)
+ \param pChannels - number of channels (output)
+
+ \return
+ - DXS_status_t
+*/
+void DXS_DevInfoGet (DXS_DEVICE_t *pDev, uint8_t *pROM_id,
+ uint8_t *pChannels)
+{
+ DXS_Dev_Caps_t *p = (DXS_Dev_Caps_t *)pDev->caps;
+
+ *pROM_id = p->fw_vers.MAJ & 0x7f;
+ *pChannels = p->fw_vers.CH ? 1 : 2;
+}