blob: edc4b5c8c3eff30f017c284e757d5f15e0790fdd [file] [log] [blame]
/*
* vl53l0x_i2c_platform.c - Linux kernel modules for
* STM VL53L0 FlightSense TOF sensor
*
* Copyright (C) 2016 STMicroelectronics Imaging Division.
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/*!
* \file VL_platform.c
* \brief Code function definitions for EWOK Platform Layer
*
*/
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/delay.h>
#include "stmvl53l0x-i2c.h"
#include "stmvl53l0x-cci.h"
#include "vl53l0x_platform.h"
#include "vl53l0x_i2c_platform.h"
#include "vl53l0x_def.h"
#include "vl53l0x_platform_log.h"
#ifdef VL_LOG_ENABLE
#define trace_print(level, ...) \
trace_print_module_function(TRACE_MODULE_PLATFORM, level,\
TRACE_FUNCTION_NONE, ##__VA_ARGS__)
#define trace_i2c(...) \
trace_print_module_function(TRACE_MODULE_NONE, \
TRACE_LEVEL_NONE, TRACE_FUNCTION_I2C, ##__VA_ARGS__)
#endif
/**
* @def I2C_BUFFER_CONFIG
*
* @brief Configure Device register I2C access
*
* @li 0 : one GLOBAL buffer \n
* Use one global buffer of MAX_I2C_XFER_SIZE byte in data space \n
* This solution is not multi-Device compliant nor multi-thread cpu safe \n
* It can be the best option for small 8/16 bit MCU without stack and limited
* ram (STM8s, 80C51 ...)
*
* @li 1 : ON_STACK/local \n
* Use local variable (on stack) buffer \n
* This solution is multi-thread with use of i2c resource lock or mutex see
* VL6180x_GetI2CAccess() \n
*
* @li 2 : User defined \n
* Per Device potentially dynamic allocated. Requires VL6180x_GetI2cBuffer()
* to be implemented.
* @ingroup Configuration
*/
#define I2C_BUFFER_CONFIG 1
#if I2C_BUFFER_CONFIG == 0
/* GLOBAL config buffer */
uint8_t i2c_global_buffer[VL_MAX_I2C_XFER_SIZE];
#define DECL_I2C_BUFFER
#define VL_GetLocalBuffer(Dev, n_byte) i2c_global_buffer
#elif I2C_BUFFER_CONFIG == 1
/* ON STACK */
uint8_t LocBuffer[VL_MAX_I2C_XFER_SIZE];
#define VL_GetLocalBuffer(Dev, n_byte) LocBuffer
#elif I2C_BUFFER_CONFIG == 2
/* user define buffer type declare DECL_I2C_BUFFER as access via */
/* VL_GetLocalBuffer */
#define DECL_I2C_BUFFER
#else
#error "invalid I2C_BUFFER_CONFIG "
#endif
#define VL_I2C_USER_VAR /* none but could be for a flag var to */
/* get/pass to mutex interruptible return flags and try again */
#define VL_GetI2CAccess(Dev) /* todo mutex acquire */
#define VL_DoneI2CAcces(Dev) /* todo mutex release */
char debug_string[VL_MAX_STRING_LENGTH_PLT];
#define MIN_COMMS_VERSION_MAJOR 1
#define MIN_COMMS_VERSION_MINOR 8
#define MIN_COMMS_VERSION_BUILD 1
#define MIN_COMMS_VERSION_REVISION 0
#define STATUS_OK 0x00
#define STATUS_FAIL 0x01
bool _check_min_version(void)
{
bool min_version_comms_dll = false;
min_version_comms_dll = true;
return min_version_comms_dll;
}
int32_t VL_comms_initialise(uint8_t comms_type, uint16_t comms_speed_khz)
{
int32_t status = STATUS_OK;
return status;
}
int32_t VL_comms_close(void)
{
int32_t status = STATUS_OK;
return status;
}
int32_t VL_set_page(struct vl_data *dev, uint8_t page_data)
{
int32_t status = STATUS_OK;
uint16_t page_index = 0xFF;
uint8_t *buffer;
buffer = VL_GetLocalBuffer(dev, 3);
buffer[0] = page_index >> 8;
buffer[1] = page_index & 0xff;
buffer[2] = page_data;
status = VL_I2CWrite(dev, buffer, (uint8_t) 3);
return status;
}
int32_t VL_write_multi(struct vl_data *dev, uint8_t index, uint8_t *pdata,
int32_t count)
{
int32_t status = STATUS_OK;
uint8_t *buffer;
#ifdef VL_LOG_ENABLE
int32_t i = 0;
char value_as_str[VL_MAX_STRING_LENGTH_PLT];
char *pvalue_as_str;
pvalue_as_str = value_as_str;
for (i = 0 ; i < count ; i++) {
snprintf(pvalue_as_str, sizeof(pvalue_as_str),
"%02X", *(pdata + i));
pvalue_as_str += 2;
}
trace_i2c("Write reg : 0x%04X, Val : 0x%s\n", index, value_as_str);
#endif
if ((count + 1) > VL_MAX_I2C_XFER_SIZE)
return STATUS_FAIL;
buffer = VL_GetLocalBuffer(dev, (count+1));
buffer[0] = index;
memcpy(&buffer[1], pdata, count);
status = VL_I2CWrite(dev, buffer, (count+1));
return status;
}
int32_t VL_read_multi(struct vl_data *dev, uint8_t index, uint8_t *pdata,
int32_t count)
{
int32_t status = STATUS_OK;
uint8_t *buffer;
#ifdef VL_LOG_ENABLE
int32_t i = 0;
char value_as_str[VL_MAX_STRING_LENGTH_PLT];
char *pvalue_as_str;
#endif
if ((count + 1) > VL_MAX_I2C_XFER_SIZE)
return STATUS_FAIL;
buffer = VL_GetLocalBuffer(dev, 1);
buffer[0] = index;
status = VL_I2CWrite(dev, (uint8_t *)buffer, (uint8_t)1);
if (!status) {
pdata[0] = index;
status = VL_I2CRead(dev, pdata, count);
}
#ifdef VL_LOG_ENABLE
pvalue_as_str = value_as_str;
for (i = 0 ; i < count ; i++) {
snprintf(pvalue_as_str, sizeof(value_as_str),
"%02X", *(pdata+i));
pvalue_as_str += 2;
}
trace_i2c("Read reg : 0x%04X, Val : 0x%s\n", index, value_as_str);
#endif
return status;
}
int32_t VL_write_byte(struct vl_data *dev, uint8_t index, uint8_t data)
{
int32_t status = STATUS_OK;
const int32_t cbyte_count = 1;
status = VL_write_multi(dev, index, &data, cbyte_count);
return status;
}
int32_t VL_write_word(struct vl_data *dev, uint8_t index, uint16_t data)
{
int32_t status = STATUS_OK;
uint8_t buffer[BYTES_PER_WORD];
/* Split 16-bit word into MS and LS uint8_t */
buffer[0] = (uint8_t)(data >> 8);
buffer[1] = (uint8_t)(data & 0x00FF);
status = VL_write_multi(dev, index, buffer, BYTES_PER_WORD);
return status;
}
int32_t VL_write_dword(struct vl_data *dev, uint8_t index, uint32_t data)
{
int32_t status = STATUS_OK;
uint8_t buffer[BYTES_PER_DWORD];
/* Split 32-bit word into MS ... LS bytes */
buffer[0] = (uint8_t) (data >> 24);
buffer[1] = (uint8_t)((data & 0x00FF0000) >> 16);
buffer[2] = (uint8_t)((data & 0x0000FF00) >> 8);
buffer[3] = (uint8_t) (data & 0x000000FF);
status = VL_write_multi(dev, index, buffer, BYTES_PER_DWORD);
return status;
}
int32_t VL_read_byte(struct vl_data *dev, uint8_t index, uint8_t *pdata)
{
int32_t status = STATUS_OK;
int32_t cbyte_count = 1;
status = VL_read_multi(dev, index, pdata, cbyte_count);
return status;
}
int32_t VL_read_word(struct vl_data *dev, uint8_t index, uint16_t *pdata)
{
int32_t status = STATUS_OK;
uint8_t buffer[BYTES_PER_WORD];
status = VL_read_multi(dev, index, buffer, BYTES_PER_WORD);
*pdata = ((uint16_t)buffer[0]<<8) + (uint16_t)buffer[1];
return status;
}
int32_t VL_read_dword(struct vl_data *dev, uint8_t index, uint32_t *pdata)
{
int32_t status = STATUS_OK;
uint8_t buffer[BYTES_PER_DWORD];
status = VL_read_multi(dev, index, buffer, BYTES_PER_DWORD);
*pdata = ((uint32_t)buffer[0]<<24) + ((uint32_t)buffer[1]<<16) +
((uint32_t)buffer[2]<<8) + (uint32_t)buffer[3];
return status;
}
int32_t VL_platform_wait_us(int32_t wait_us)
{
int32_t status = STATUS_OK;
msleep((wait_us/1000));
#ifdef VL_LOG_ENABLE
trace_i2c("Wait us : %6d\n", wait_us);
#endif
return status;
}
int32_t VL_wait_ms(int32_t wait_ms)
{
int32_t status = STATUS_OK;
msleep(wait_ms);
#ifdef VL_LOG_ENABLE
trace_i2c("Wait ms : %6d\n", wait_ms);
#endif
return status;
}
int32_t VL_set_gpio(uint8_t level)
{
int32_t status = STATUS_OK;
#ifdef VL_LOG_ENABLE
trace_i2c("// Set GPIO = %d;\n", level);
#endif
return status;
}
int32_t VL_get_gpio(uint8_t *plevel)
{
int32_t status = STATUS_OK;
#ifdef VL_LOG_ENABLE
trace_i2c("// Get GPIO = %d;\n", *plevel);
#endif
return status;
}
int32_t VL_release_gpio(void)
{
int32_t status = STATUS_OK;
#ifdef VL_LOG_ENABLE
trace_i2c("// Releasing force on GPIO\n");
#endif
return status;
}
int32_t VL_cycle_power(void)
{
int32_t status = STATUS_OK;
#ifdef VL_LOG_ENABLE
trace_i2c("// cycle sensor power\n");
#endif
return status;
}
int32_t VL_get_timer_frequency(int32_t *ptimer_freq_hz)
{
*ptimer_freq_hz = 0;
return STATUS_FAIL;
}
int32_t VL_get_timer_value(int32_t *ptimer_count)
{
*ptimer_count = 0;
return STATUS_FAIL;
}