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 fxos8700_drv.c
11  * @brief The fxos8700_drv.c file implements the fxos8700 sensor driver functional interfaces.
12  */
13 
14 //-----------------------------------------------------------------------
15 // ISSDK Includes
16 //-----------------------------------------------------------------------
17 #include "gpio_driver.h"
18 #include "fxos8700_drv.h"
19 
20 //-----------------------------------------------------------------------
21 // Global Variables
22 //-----------------------------------------------------------------------
23 uint8_t fxos8700_spiRead_CmdBuffer[FXOS8700_SPI_MAX_MSG_SIZE] = {0};
24 uint8_t fxos8700_spiRead_DataBuffer[FXOS8700_SPI_MAX_MSG_SIZE] = {0};
25 uint8_t fxos8700_spiWrite_CmdDataBuffer[FXOS8700_SPI_MAX_MSG_SIZE] = {0};
26 
27 //-----------------------------------------------------------------------
28 // Functions
29 //-----------------------------------------------------------------------
FXOS8700_SPI_ReadPreprocess(void * pCmdOut,uint32_t offset,uint32_t size)30 void FXOS8700_SPI_ReadPreprocess(void *pCmdOut, uint32_t offset, uint32_t size)
31 {
32     spiCmdParams_t *pSlaveCmd = pCmdOut;
33 
34     uint8_t *pWBuff = fxos8700_spiRead_CmdBuffer;
35     uint8_t *pRBuff = fxos8700_spiRead_DataBuffer;
36 
37     /* Formatting for Read command of FXOS8700 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 + FXOS8700_SPI_CMD_LEN;
43     pSlaveCmd->pWriteBuffer = pWBuff;
44     pSlaveCmd->pReadBuffer = pRBuff;
45 }
46 
FXOS8700_SPI_WritePreprocess(void * pCmdOut,uint32_t offset,uint32_t size,void * pWritebuffer)47 void FXOS8700_SPI_WritePreprocess(void *pCmdOut, uint32_t offset, uint32_t size, void *pWritebuffer)
48 {
49     spiCmdParams_t *pSlaveCmd = pCmdOut;
50 
51     uint8_t *pWBuff = fxos8700_spiWrite_CmdDataBuffer;
52     uint8_t *pRBuff = fxos8700_spiWrite_CmdDataBuffer + size + FXOS8700_SPI_CMD_LEN;
53 
54     /* Formatting for Write command of FXOS8700 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 + FXOS8700_SPI_CMD_LEN, pWritebuffer, size);
60 
61     /* Create the slave command. */
62     pSlaveCmd->size = size + FXOS8700_SPI_CMD_LEN;
63     pSlaveCmd->pWriteBuffer = pWBuff;
64     pSlaveCmd->pReadBuffer = pRBuff;
65 }
66 
FXOS8700_SPI_Initialize(fxos8700_spi_sensorhandle_t * pSensorHandle,ARM_DRIVER_SPI * pBus,uint8_t index,void * pSlaveSelect,uint8_t whoAmi)67 int32_t FXOS8700_SPI_Initialize(
68     fxos8700_spi_sensorhandle_t *pSensorHandle, ARM_DRIVER_SPI *pBus, uint8_t index, void *pSlaveSelect, uint8_t whoAmi)
69 {
70     int32_t status;
71     FXOS8700_WHO_AM_I_t reg;
72     GENERIC_DRIVER_GPIO *pGPIODriver = &Driver_GPIO_KSDK;
73 
74     /*! Check the input parameters. */
75     if ((pSensorHandle == NULL) || (pBus == NULL) || (pSlaveSelect == NULL))
76     {
77         return SENSOR_ERROR_INVALID_PARAM;
78     }
79 
80     /*! Initialize the sensor handle. */
81     pSensorHandle->pCommDrv = pBus;
82     pSensorHandle->slaveParams.pReadPreprocessFN = FXOS8700_SPI_ReadPreprocess;
83     pSensorHandle->slaveParams.pWritePreprocessFN = FXOS8700_SPI_WritePreprocess;
84     pSensorHandle->slaveParams.pTargetSlavePinID = pSlaveSelect;
85     pSensorHandle->slaveParams.spiCmdLen = FXOS8700_SPI_CMD_LEN;
86     pSensorHandle->slaveParams.ssActiveValue = FXOS8700_SS_ACTIVE_VALUE;
87 
88     pSensorHandle->deviceInfo.deviceInstance = index;
89     pSensorHandle->deviceInfo.functionParam = NULL;
90     pSensorHandle->deviceInfo.idleFunction = NULL;
91 
92     /* Initialize the Slave Select Pin. */
93     pGPIODriver->pin_init(pSlaveSelect, GPIO_DIRECTION_OUT, NULL, NULL, NULL);
94     if (pSensorHandle->slaveParams.ssActiveValue == SPI_SS_ACTIVE_LOW)
95     {
96         pGPIODriver->set_pin(pSlaveSelect);
97     }
98     else
99     {
100         pGPIODriver->clr_pin(pSlaveSelect);
101     }
102 
103     /*!  Read and store the device's WHO_AM_I.*/
104     status = Register_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
105                                FXOS8700_WHO_AM_I, 1, &reg);
106     if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
107     {
108         pSensorHandle->isInitialized = false;
109         return SENSOR_ERROR_INIT;
110     }
111 
112     pSensorHandle->isInitialized = true;
113     return SENSOR_ERROR_NONE;
114 }
115 
FXOS8700_SPI_SetIdleTask(fxos8700_spi_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)116 void FXOS8700_SPI_SetIdleTask(fxos8700_spi_sensorhandle_t *pSensorHandle,
117                               registeridlefunction_t idleTask,
118                               void *userParam)
119 {
120     pSensorHandle->deviceInfo.functionParam = userParam;
121     pSensorHandle->deviceInfo.idleFunction = idleTask;
122 }
123 
FXOS8700_SPI_Configure(fxos8700_spi_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)124 int32_t FXOS8700_SPI_Configure(fxos8700_spi_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
125 {
126     int32_t status;
127 
128     /*! Validate for the correct handle and register write list.*/
129     if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
130     {
131         return SENSOR_ERROR_INVALID_PARAM;
132     }
133 
134     /*! Check whether sensor handle is initialized before applying configuration.*/
135     if (pSensorHandle->isInitialized != true)
136     {
137         return SENSOR_ERROR_INIT;
138     }
139 
140     /*! Put the device into standby mode so that configuration can be applied.*/
141     status =
142         Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
143                            FXOS8700_CTRL_REG1, FXOS8700_CTRL_REG1_ACTIVE_STANDBY_MODE, FXOS8700_CTRL_REG1_ACTIVE_MASK);
144     if (ARM_DRIVER_OK != status)
145     {
146         return SENSOR_ERROR_WRITE;
147     }
148 
149     /*! Apply the Sensor Configuration based on the Register Write List */
150     status = Sensor_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
151                               pRegWriteList);
152     if (ARM_DRIVER_OK != status)
153     {
154         return SENSOR_ERROR_WRITE;
155     }
156 
157     /*! Put the device into active mode and ready for reading data.*/
158     status =
159         Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
160                            FXOS8700_CTRL_REG1, FXOS8700_CTRL_REG1_ACTIVE_ACTIVE_MODE, FXOS8700_CTRL_REG1_ACTIVE_MASK);
161     if (ARM_DRIVER_OK != status)
162     {
163         return SENSOR_ERROR_WRITE;
164     }
165 
166     return SENSOR_ERROR_NONE;
167 }
168 
FXOS8700_SPI_ReadData(fxos8700_spi_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)169 int32_t FXOS8700_SPI_ReadData(fxos8700_spi_sensorhandle_t *pSensorHandle,
170                               const registerreadlist_t *pReadList,
171                               uint8_t *pBuffer)
172 {
173     int32_t status;
174 
175     /*! Validate for the correct handle and register read list.*/
176     if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
177     {
178         return SENSOR_ERROR_INVALID_PARAM;
179     }
180 
181     /*! Check whether sensor handle is initialized before reading sensor data.*/
182     if (pSensorHandle->isInitialized != true)
183     {
184         return SENSOR_ERROR_INIT;
185     }
186 
187     /*! Parse through the read list and read the data one by one. */
188     status = Sensor_SPI_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
189                              pReadList, pBuffer);
190     if (ARM_DRIVER_OK != status)
191     {
192         return SENSOR_ERROR_READ;
193     }
194 
195     return SENSOR_ERROR_NONE;
196 }
197 
FXOS8700_SPI_Deinit(fxos8700_spi_sensorhandle_t * pSensorHandle)198 int32_t FXOS8700_SPI_Deinit(fxos8700_spi_sensorhandle_t *pSensorHandle)
199 {
200     if (pSensorHandle == NULL)
201     {
202         return SENSOR_ERROR_INVALID_PARAM;
203     }
204 
205     /*! Check whether sensor handle is initialized before triggering sensor reset.*/
206     if (pSensorHandle->isInitialized != true)
207     {
208         return SENSOR_ERROR_INIT;
209     }
210 
211     /*! Trigger sensor device reset.*/
212     Register_SPI_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, &pSensorHandle->slaveParams,
213                        FXOS8700_CTRL_REG2, FXOS8700_CTRL_REG2_RST_EN, FXOS8700_CTRL_REG2_RST_MASK);
214 
215     /*! De-initialize sensor handle.
216      *  We do not validate write success since 8700 reset before sensing ack for the transaction. */
217     pSensorHandle->isInitialized = false;
218 
219     return SENSOR_ERROR_NONE;
220 }
221 
FXOS8700_I2C_Initialize(fxos8700_i2c_sensorhandle_t * pSensorHandle,ARM_DRIVER_I2C * pBus,uint8_t index,uint16_t sAddress,uint8_t whoAmi)222 int32_t FXOS8700_I2C_Initialize(
223     fxos8700_i2c_sensorhandle_t *pSensorHandle, ARM_DRIVER_I2C *pBus, uint8_t index, uint16_t sAddress, uint8_t whoAmi)
224 {
225     int32_t status;
226     FXOS8700_WHO_AM_I_t reg;
227 
228     if ((pSensorHandle == NULL) || (pBus == NULL))
229     {
230         return SENSOR_ERROR_INVALID_PARAM;
231     }
232 
233     pSensorHandle->deviceInfo.deviceInstance = index;
234     pSensorHandle->deviceInfo.functionParam = NULL;
235     pSensorHandle->deviceInfo.idleFunction = NULL;
236 
237     /*!  Read and store the device's WHO_AM_I.*/
238     status = Register_I2C_Read(pBus, &pSensorHandle->deviceInfo, sAddress, FXOS8700_WHO_AM_I, 1, &reg);
239     if ((ARM_DRIVER_OK != status) || (whoAmi != reg))
240     {
241         pSensorHandle->isInitialized = false;
242         return SENSOR_ERROR_INIT;
243     }
244 
245     /*! Initialize the sensor handle. */
246     pSensorHandle->pCommDrv = pBus;
247     pSensorHandle->slaveAddress = sAddress;
248     pSensorHandle->isInitialized = true;
249     return SENSOR_ERROR_NONE;
250 }
251 
FXOS8700_I2C_SetIdleTask(fxos8700_i2c_sensorhandle_t * pSensorHandle,registeridlefunction_t idleTask,void * userParam)252 void FXOS8700_I2C_SetIdleTask(fxos8700_i2c_sensorhandle_t *pSensorHandle,
253                               registeridlefunction_t idleTask,
254                               void *userParam)
255 {
256     pSensorHandle->deviceInfo.functionParam = userParam;
257     pSensorHandle->deviceInfo.idleFunction = idleTask;
258 }
259 
FXOS8700_I2C_Configure(fxos8700_i2c_sensorhandle_t * pSensorHandle,const registerwritelist_t * pRegWriteList)260 int32_t FXOS8700_I2C_Configure(fxos8700_i2c_sensorhandle_t *pSensorHandle, const registerwritelist_t *pRegWriteList)
261 {
262     int32_t status;
263 
264     /*! Validate for the correct handle and register write list.*/
265     if ((pSensorHandle == NULL) || (pRegWriteList == NULL))
266     {
267         return SENSOR_ERROR_INVALID_PARAM;
268     }
269 
270     /*! Check whether sensor handle is initialized before applying configuration.*/
271     if (pSensorHandle->isInitialized != true)
272     {
273         return SENSOR_ERROR_INIT;
274     }
275 
276     /* Put the device into standby mode so that configuration can be applied.*/
277     status = Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
278                                 FXOS8700_CTRL_REG1, FXOS8700_CTRL_REG1_ACTIVE_STANDBY_MODE,
279                                 FXOS8700_CTRL_REG1_ACTIVE_MASK, false);
280     if (ARM_DRIVER_OK != status)
281     {
282         return SENSOR_ERROR_WRITE;
283     }
284 
285     /* Appy the Sensor Configuration based on the Register List */
286     status = Sensor_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
287                               pRegWriteList);
288     if (ARM_DRIVER_OK != status)
289     {
290         return SENSOR_ERROR_WRITE;
291     }
292 
293     /* Put the device into active mode and ready for reading data.*/
294     status = Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
295                                 FXOS8700_CTRL_REG1, FXOS8700_CTRL_REG1_ACTIVE_ACTIVE_MODE,
296                                 FXOS8700_CTRL_REG1_ACTIVE_MASK, false);
297     if (ARM_DRIVER_OK != status)
298     {
299         return SENSOR_ERROR_WRITE;
300     }
301 
302     return SENSOR_ERROR_NONE;
303 }
304 
FXOS8700_I2C_ReadData(fxos8700_i2c_sensorhandle_t * pSensorHandle,const registerreadlist_t * pReadList,uint8_t * pBuffer)305 int32_t FXOS8700_I2C_ReadData(fxos8700_i2c_sensorhandle_t *pSensorHandle,
306                               const registerreadlist_t *pReadList,
307                               uint8_t *pBuffer)
308 {
309     int32_t status;
310 
311     /*! Validate for the correct handle and register read list.*/
312     if ((pSensorHandle == NULL) || (pReadList == NULL) || (pBuffer == NULL))
313     {
314         return SENSOR_ERROR_INVALID_PARAM;
315     }
316 
317     /*! Check whether sensor handle is initialized before reading sensor data.*/
318     if (pSensorHandle->isInitialized != true)
319     {
320         return SENSOR_ERROR_INIT;
321     }
322 
323     /*!  Parse through the read list and read the data one by one*/
324     status = Sensor_I2C_Read(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
325                              pReadList, pBuffer);
326     if (ARM_DRIVER_OK != status)
327     {
328         return SENSOR_ERROR_READ;
329     }
330 
331     return SENSOR_ERROR_NONE;
332 }
333 
FXOS8700_I2C_Deinit(fxos8700_i2c_sensorhandle_t * pSensorHandle)334 int32_t FXOS8700_I2C_Deinit(fxos8700_i2c_sensorhandle_t *pSensorHandle)
335 {
336     if (pSensorHandle == NULL)
337     {
338         return SENSOR_ERROR_INVALID_PARAM;
339     }
340 
341     /*! Check whether sensor handle is initialized before triggering sensor reset.*/
342     if (pSensorHandle->isInitialized != true)
343     {
344         return SENSOR_ERROR_INIT;
345     }
346 
347     /*! Trigger sensor device reset.*/
348     Register_I2C_Write(pSensorHandle->pCommDrv, &pSensorHandle->deviceInfo, pSensorHandle->slaveAddress,
349                        FXOS8700_CTRL_REG2, FXOS8700_CTRL_REG2_RST_EN, FXOS8700_CTRL_REG2_RST_MASK, false);
350     pSensorHandle->isInitialized = false;
351     return SENSOR_ERROR_NONE;
352 }
353