1 /*
2  * Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /**
10  * @file fxls8471q_drv.c
11  * @brief The fxls8471q_drv.c file implements the FXLS8471Q sensor driver interfaces.
12  */
13 
14 //-----------------------------------------------------------------------
15 // ISSDK Includes
16 //-----------------------------------------------------------------------
17 #include "gpio_driver.h"
18 #include "fxls8471q_drv.h"
19 
20 //-----------------------------------------------------------------------
21 // Global Variables
22 //-----------------------------------------------------------------------
23 uint8_t fxls8471q_spiRead_CmdBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
24 uint8_t fxls8471q_spiRead_DataBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
25 uint8_t fxls8471q_spiWrite_CmdDataBuffer[FXLS8471Q_SPI_MAX_MSG_SIZE] = {0};
26 
27 //-----------------------------------------------------------------------
28 // Functions
29 //-----------------------------------------------------------------------
FXLS8471Q_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)30 void FXLS8471Q_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
31 {
32     spiCmdParams_t *pSlaveCmd = pCmdOut;
33 
34     uint8_t *pWBuff = fxls8471q_spiRead_CmdBuffer;
35     uint8_t *pRBuff = fxls8471q_spiRead_DataBuffer;
36 
37     /* Formatting for Read command of FXLS8471Q SENSOR. */
38     *(pWBuff) = offset & 0x7F; /* offset is the internal register address of the sensor at which write is performed. */
39     *(pWBuff + 1) = offset & 0x80;
40 
41     // Create the slave read command.
42     pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
43     pSlaveCmd->pWriteBuffer = pWBuff;
44     pSlaveCmd->pReadBuffer = pRBuff;
45 }
46 
FXLS8471Q_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)47 void FXLS8471Q_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
48 {
49     spiCmdParams_t *pSlaveCmd = pCmdOut;
50 
51     uint8_t *pWBuff = fxls8471q_spiWrite_CmdDataBuffer;
52     uint8_t *pRBuff = fxls8471q_spiWrite_CmdDataBuffer + size + FXLS8471Q_SPI_CMD_LEN;
53 
54     /* Formatting for Write command of FXLS8471Q SENSOR. */
55     *(pWBuff) = offset | 0x80; /* offset is the internal register address of the sensor at which write is performed. */
56     *(pWBuff + 1) = offset & 0x80;
57 
58     /* Copy the slave write command */
59     memcpy(pWBuff + FXLS8471Q_SPI_CMD_LEN, pWritebuffer, size);
60 
61     /* Create the slave command. */
62     pSlaveCmd->size = size + FXLS8471Q_SPI_CMD_LEN;
63     pSlaveCmd->pWriteBuffer = pWBuff;
64     pSlaveCmd->pReadBuffer = pRBuff;
65 }
66 
FXLS8471Q_SPI_Initialize(fxls8471q_spi_sensorhandle_t * pSensorHandle,ARM_DRIVER_SPI * pBus,uint8_t index,void * pSlaveSelect,uint8_t whoAmi)67 int32_t FXLS8471Q_SPI_Initialize(fxls8471q_spi_sensorhandle_t *pSensorHandle,
68                                  ARM_DRIVER_SPI *pBus,
69                                  uint8_t index,
70                                  void *pSlaveSelect,
71                                  uint8_t whoAmi)
72 {
73     int32_t status;
74     uint8_t reg;
75     GENERIC_DRIVER_GPIO *pGPIODriver = &Driver_GPIO_KSDK;
76 
77     /*! Check the input parameters. */
78     if ((pSensorHandle == NULL) || (pBus == NULL) || (pSlaveSelect == NULL))
79     {
80         return SENSOR_ERROR_INVALID_PARAM;
81     }
82 
83     /*! Initialize the sensor handle. */
84     pSensorHandle->pCommDrv = pBus;
85     pSensorHandle->slaveParams.pReadPreprocessFN = FXLS8471Q_SPI_ReadPreprocess;
86     pSensorHandle->slaveParams.pWritePreprocessFN = FXLS8471Q_SPI_WritePreprocess;
87     pSensorHandle->slaveParams.pTargetSlavePinID = pSlaveSelect;
88     pSensorHandle->slaveParams.spiCmdLen = FXLS8471Q_SPI_CMD_LEN;
89     pSensorHandle->slaveParams.ssActiveValue = FXLS8471Q_SS_ACTIVE_VALUE;
90 
91     pSensorHandle->deviceInfo.deviceInstance = index;
92     pSensorHandle->deviceInfo.functionParam = NULL;
93     pSensorHandle->deviceInfo.idleFunction = NULL;
94 
95     /* Initialize the Slave Select Pin. */
96     pGPIODriver->pin_init(pSlaveSelect, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
97     if (pSensorHandle->slaveParams.ssActiveValue == SPI_SS_ACTIVE_LOW)
98     {
99         pGPIODriver->set_pin(pSlaveSelect);
100     }
101     else
102     {
103         pGPIODriver->clr_pin(pSlaveSelect);
104     }
105 
106     /*!  Read and store the device's WHO_AM_I.*/
107     status = Register_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
108                                FXLS8471Q_WHO_AM_I, 1, &reg);
109     if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
110     {
111         pSensorHandle->isInitialized = false;
112         return SENSOR_ERROR_INIT;
113     }
114 
115     pSensorHandle->isInitialized = true;
116     return SENSOR_ERROR_NONE;
117 }
118 
FXLS8471Q_SPI_SetIdleTask(fxls8471q_spi_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)119 void FXLS8471Q_SPI_SetIdleTask(fxls8471q_spi_sensorhandle_t *pSensorHandle,
120                                registeridlefunction_t idleTask,
121                                void *userParam)
122 {
123     pSensorHandle->deviceInfo.functionParam = userParam;
124     pSensorHandle->deviceInfo.idleFunction = idleTask;
125 }
126 
FXLS8471Q_SPI_Configure(fxls8471q_spi_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)127 int32_t FXLS8471Q_SPI_Configure(fxls8471q_spi_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
128 {
129     int32_t status;
130 
131     /*! Validate for the correct handle and register write list.*/
132     if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
133     {
134         return SENSOR_ERROR_INVALID_PARAM;
135     }
136 
137     /*! Check whether sensor handle is initialized before applying configuration.*/
138     if (pSensorHandle->isInitialized != true)
139     {
140         return SENSOR_ERROR_INIT;
141     }
142 
143     /*! Put the device into standby mode so that configuration can be applied.*/
144     status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
145                                 FXLS8471Q_CTRL_REG1, FXLS8471Q_CTRL_REG1_MODE_STANDBY, FXLS8471Q_CTRL_REG1_MODE_MASK);
146     if (ARM_DRIVER_OK != status)
147     {
148         return SENSOR_ERROR_WRITE;
149     }
150 
151     /*! Apply the Sensor Configuration based on the Register Write List */
152     status = Sensor_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
153                               pRegWriteList);
154     if (ARM_DRIVER_OK != status)
155     {
156         return SENSOR_ERROR_WRITE;
157     }
158 
159     /*! Put the device into active mode and ready for reading data.*/
160     status = Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
161                                 FXLS8471Q_CTRL_REG1, FXLS8471Q_CTRL_REG1_MODE_ACTIVE, FXLS8471Q_CTRL_REG1_MODE_MASK);
162     if (ARM_DRIVER_OK != status)
163     {
164         return SENSOR_ERROR_WRITE;
165     }
166 
167     return SENSOR_ERROR_NONE;
168 }
169 
FXLS8471Q_SPI_ReadData(fxls8471q_spi_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)170 int32_t FXLS8471Q_SPI_ReadData(fxls8471q_spi_sensorhandle_t *pSensorHandle,
171                                const registerreadlist_t *pReadList,
172                                uint8_t *pBuffer)
173 {
174     int32_t status;
175 
176     /*! Validate for the correct handle and register read list.*/
177     if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
178     {
179         return SENSOR_ERROR_INVALID_PARAM;
180     }
181 
182     /*! Check whether sensor handle is initialized before reading sensor data.*/
183     if (pSensorHandle->isInitialized != true)
184     {
185         return SENSOR_ERROR_INIT;
186     }
187 
188     /*! Parse through the read list and read the data one by one. */
189     status = Sensor_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
190                              pReadList, pBuffer);
191     if (ARM_DRIVER_OK != status)
192     {
193         return SENSOR_ERROR_READ;
194     }
195 
196     return SENSOR_ERROR_NONE;
197 }
198 
FXLS8471Q_SPI_Deinit(fxls8471q_spi_sensorhandle_t * pSensorHandle)199 int32_t FXLS8471Q_SPI_Deinit(fxls8471q_spi_sensorhandle_t *pSensorHandle)
200 {
201     if (pSensorHandle == NULL)
202     {
203         return SENSOR_ERROR_INVALID_PARAM;
204     }
205 
206     /*! Check whether sensor handle is initialized before triggering sensor reset.*/
207     if (pSensorHandle->isInitialized != true)
208     {
209         return SENSOR_ERROR_INIT;
210     }
211 
212     /* Note:
213      * There is a Errata described in the data sheet for soft reset with SPI,
214      * which says device specific paratameters do not get updated correctly from NVM,
215      * causing inaccurate data output once the soft-reset command issued in SPI mode.
216      * The work around is hard reset, which cannot be handled in sensor driver software.
217      * So software reset command wont be issued until this issue is fixed in the silicon.
218      */
219 
220     /*! De-initialize sensor handle. */
221     pSensorHandle->isInitialized = false;
222 
223     return SENSOR_ERROR_NONE;
224 }
225