driver/sensor: lis2mdl: make use of STdC definitions

Port the lis2mdl sensor driver on top of the lis2mdl_StdC
HAL interface (in modules/hal/st/sensor/stmemsc/).

Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
Armando Visconti 2019-09-25 11:28:50 +02:00 committed by Maureen Helm
commit 44f373e806
8 changed files with 343 additions and 223 deletions

View file

@ -1,9 +1,11 @@
#
# Copyright (c) 2018 STMicroelectronics
# Copyright (c) 2018-2019 STMicroelectronics
#
# SPDX-License-Identifier: Apache-2.0
#
zephyr_library()
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl.c)
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl_i2c.c)
zephyr_library_sources_ifdef(CONFIG_LIS2MDL lis2mdl_spi.c)
zephyr_library_sources_ifdef(CONFIG_LIS2MDL_TRIGGER lis2mdl_trigger.c)

View file

@ -1,11 +1,13 @@
# Copyright (c) 2018 STMicroelectronics
# Copyright (c) 2018-2019 STMicroelectronics
#
# SPDX-License-Identifier: Apache-2.0
#
menuconfig LIS2MDL
bool "LIS2MDL Magnetometer"
depends on (I2C && HAS_DTS_I2C)
depends on (I2C && HAS_DTS_I2C) || SPI
select HAS_STMEMSC
select USE_STDC_LIS2MDL
help
Enable driver for LIS2MDL I2C-based magnetometer sensor.

View file

@ -1,9 +1,11 @@
/*
* Copyright (c) 2018 STMicroelectronics
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
*
* LIS2MDL mag driver
* Copyright (c) 2018-2019 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
*/
#include <init.h>
@ -14,73 +16,40 @@
#include "lis2mdl.h"
struct lis2mdl_data lis2mdl_device_data;
struct lis2mdl_data lis2mdl_data;
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
#include <logging/log.h>
LOG_MODULE_REGISTER(LIS2MDL);
#ifdef CONFIG_LIS2MDL_MAG_ODR_RUNTIME
static const struct {
u16_t odr;
u8_t regval;
} lis2mdl_odr_reg[] = {
{
.odr = 10,
.regval = LIS2MDL_ODR10_HZ,
},
{
.odr = 20,
.regval = LIS2MDL_ODR20_HZ,
},
{
.odr = 50,
.regval = LIS2MDL_ODR50_HZ,
},
{
.odr = 100,
.regval = LIS2MDL_ODR100_HZ,
},
};
static int lis2mdl_freq_to_odr_val(u16_t odr)
static int lis2mdl_set_odr(struct device *dev, const struct sensor_value *val)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(lis2mdl_odr_reg); i++) {
if (odr == lis2mdl_odr_reg[i].odr) {
return i;
}
}
return -EINVAL;
}
static int lis2mdl_set_odr(struct device *dev, u16_t odr)
{
int odr_idx;
struct lis2mdl_data *lis2mdl = dev->driver_data;
lis2mdl_odr_t odr;
/* check if power off */
if (odr == 0U) {
/* power off mag */
return i2c_reg_update_byte(lis2mdl->i2c,
lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_A,
LIS2MDL_MAG_MODE_MASK,
LIS2MDL_MD_IDLE1_MODE);
switch (val->val1) {
case 10:
odr = LIS2MDL_ODR_10Hz;
break;
case 20:
odr = LIS2MDL_ODR_20Hz;
break;
case 50:
odr = LIS2MDL_ODR_50Hz;
break;
case 100:
odr = LIS2MDL_ODR_100Hz;
break;
default:
return -EINVAL;
}
odr_idx = lis2mdl_freq_to_odr_val(odr);
if (odr_idx < 0) {
return odr_idx;
if (lis2mdl_data_rate_set(lis2mdl->ctx, odr)) {
return -EIO;
}
return i2c_reg_update_byte(lis2mdl->i2c,
lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_A,
LIS2MDL_ODR_MASK,
lis2mdl_odr_reg[odr_idx].regval);
return 0;
}
#endif /* CONFIG_LIS2MDL_MAG_ODR_RUNTIME */
@ -88,24 +57,15 @@ static int lis2mdl_set_hard_iron(struct device *dev, enum sensor_channel chan,
const struct sensor_value *val)
{
struct lis2mdl_data *lis2mdl = dev->driver_data;
u8_t regs = LIS2MDL_OFFSET_X_REG_L;
u8_t i;
s16_t offs;
int ret;
axis3bit16_t offset;
for (i = 0U; i < LIS2MDL_NUM_AXIS; i++) {
offs = sys_cpu_to_le16(val->val1);
ret = i2c_burst_write(lis2mdl->i2c, lis2mdl->i2c_addr,
regs, (u8_t *)&offs, sizeof(offs));
if (ret < 0) {
return ret;
}
regs += sizeof(offs);
for (i = 0U; i < 3; i++) {
offset.i16bit[i] = sys_cpu_to_le16(val->val1);
val++;
}
return 0;
return lis2mdl_mag_user_offset_set(lis2mdl->ctx, offset.u8bit);
}
static void lis2mdl_channel_get_mag(struct device *dev,
@ -179,7 +139,7 @@ static int lis2mdl_config(struct device *dev, enum sensor_channel chan,
switch (attr) {
#ifdef CONFIG_LIS2MDL_MAG_ODR_RUNTIME
case SENSOR_ATTR_SAMPLING_FREQUENCY:
return lis2mdl_set_odr(dev, val->val1);
return lis2mdl_set_odr(dev, val);
#endif /* CONFIG_LIS2MDL_MAG_ODR_RUNTIME */
case SENSOR_ATTR_OFFSET:
return lis2mdl_set_hard_iron(dev, chan, val);
@ -197,6 +157,7 @@ static int lis2mdl_attr_set(struct device *dev,
const struct sensor_value *val)
{
switch (chan) {
case SENSOR_CHAN_ALL:
case SENSOR_CHAN_MAGN_X:
case SENSOR_CHAN_MAGN_Y:
case SENSOR_CHAN_MAGN_Z:
@ -213,25 +174,17 @@ static int lis2mdl_attr_set(struct device *dev,
static int lis2mdl_sample_fetch_mag(struct device *dev)
{
struct lis2mdl_data *lis2mdl = dev->driver_data;
union {
u8_t raw[LIS2MDL_OUT_REG_SIZE];
struct {
s16_t m_axis[3];
};
} buf __aligned(2);
axis3bit16_t raw_mag;
/* fetch raw data sample */
if (i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_OUT_REG, buf.raw,
sizeof(buf)) < 0) {
LOG_DBG("Failed to fetch raw mag sample");
if (lis2mdl_magnetic_raw_get(lis2mdl->ctx, raw_mag.u8bit) < 0) {
LOG_DBG("Failed to read sample");
return -EIO;
}
lis2mdl->mag[0] = sys_le16_to_cpu(buf.m_axis[0]);
lis2mdl->mag[1] = sys_le16_to_cpu(buf.m_axis[1]);
lis2mdl->mag[2] = sys_le16_to_cpu(buf.m_axis[2]);
lis2mdl->mag[0] = sys_le16_to_cpu(raw_mag.i16bit[0]);
lis2mdl->mag[1] = sys_le16_to_cpu(raw_mag.i16bit[1]);
lis2mdl->mag[2] = sys_le16_to_cpu(raw_mag.i16bit[2]);
return 0;
}
@ -239,21 +192,17 @@ static int lis2mdl_sample_fetch_mag(struct device *dev)
static int lis2mdl_sample_fetch_temp(struct device *dev)
{
struct lis2mdl_data *lis2mdl = dev->driver_data;
u16_t temp_raw;
axis1bit16_t raw_temp;
s32_t temp;
int ret;
/* fetch raw temperature sample */
ret = i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_TEMP_OUT_L_REG,
(u8_t *)&temp_raw, sizeof(temp_raw));
if (ret < 0) {
LOG_DBG("Failed to fetch raw temp sample");
if (lis2mdl_temperature_raw_get(lis2mdl->ctx, raw_temp.u8bit) < 0) {
LOG_DBG("Failed to read sample");
return -EIO;
}
/* formula is temp = 25 + (temp / 8) C */
temp = (sys_le16_to_cpu(temp_raw) & 0x8FFF);
temp = (sys_le16_to_cpu(raw_temp.i16bit) & 0x8FFF);
lis2mdl->temp_sample = 2500 + (temp * 100) / 8;
return 0;
@ -293,29 +242,47 @@ static const struct sensor_driver_api lis2mdl_driver_api = {
static int lis2mdl_init_interface(struct device *dev)
{
const struct lis2mdl_device_config *const config =
const struct lis2mdl_config *const config =
dev->config->config_info;
struct lis2mdl_data *lis2mdl = dev->driver_data;
lis2mdl->i2c = device_get_binding(config->master_dev_name);
if (!lis2mdl->i2c) {
lis2mdl->bus = device_get_binding(config->master_dev_name);
if (!lis2mdl->bus) {
LOG_DBG("Could not get pointer to %s device",
config->master_dev_name);
return -EINVAL;
}
lis2mdl->i2c_addr = config->i2c_addr_config;
return 0;
return config->bus_init(dev);
}
static const struct lis2mdl_device_config lis2mdl_dev_config = {
static const struct lis2mdl_config lis2mdl_dev_config = {
.master_dev_name = DT_INST_0_ST_LIS2MDL_BUS_NAME,
#ifdef CONFIG_LIS2MDL_TRIGGER
.gpio_name = DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER,
.gpio_pin = DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN,
#endif /* CONFIG_LIS2MDL_TRIGGER */
.i2c_addr_config = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
#if defined(DT_ST_LIS2MDL_BUS_SPI)
.bus_init = lis2mdl_spi_init,
.spi_conf.frequency = DT_INST_0_ST_LIS2MDL_SPI_MAX_FREQUENCY,
.spi_conf.operation = (SPI_OP_MODE_MASTER | SPI_MODE_CPOL |
SPI_MODE_CPHA | SPI_WORD_SET(8) |
SPI_LINES_SINGLE),
.spi_conf.slave = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
.gpio_cs_port = DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER,
.cs_gpio = DT_INST_0_ST_LIS2MDL_CS_GPIOS_PIN,
.spi_conf.cs = &lis2mdl_data.cs_ctrl,
#else
.spi_conf.cs = NULL,
#endif
#elif defined(DT_ST_LIS2MDL_BUS_I2C)
.bus_init = lis2mdl_i2c_init,
.i2c_slv_addr = DT_INST_0_ST_LIS2MDL_BASE_ADDRESS,
#else
#error "BUS MACRO NOT DEFINED IN DTS"
#endif
};
static int lis2mdl_init(struct device *dev)
@ -328,41 +295,53 @@ static int lis2mdl_init(struct device *dev)
}
/* check chip ID */
if (i2c_reg_read_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_WHO_AM_I_REG, &wai) < 0) {
LOG_DBG("Failed to read chip ID");
if (lis2mdl_device_id_get(lis2mdl->ctx, &wai) < 0) {
return -EIO;
}
if (wai != LIS2MDL_WHOAMI_VAL) {
LOG_DBG("Invalid chip ID");
if (wai != LIS2MDL_ID) {
LOG_DBG("Invalid chip ID: %02x\n", wai);
return -EINVAL;
}
/* reset sensor configuration */
if (i2c_reg_write_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_A, LIS2MDL_SOFT_RST)) {
if (lis2mdl_reset_set(lis2mdl->ctx, PROPERTY_ENABLE) < 0) {
LOG_DBG("s/w reset failed\n");
return -EIO;
}
k_busy_wait(100);
/* enable BDU */
if (i2c_reg_update_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_C, LIS2MDL_BDU_MASK,
LIS2MDL_BDU_BIT)) {
if (lis2mdl_block_data_update_set(lis2mdl->ctx, PROPERTY_ENABLE) < 0) {
LOG_DBG("setting bdu failed\n");
return -EIO;
}
/* set continuous MODE in default ODR, enable temperature comp. */
if (i2c_reg_write_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_A,
LIS2MDL_MD_CONT_MODE | LIS2MDL_DEFAULT_ODR |
LIS2MDL_COMP_TEMP_MASK)) {
/* Set Output Data Rate */
if (lis2mdl_data_rate_set(lis2mdl->ctx, LIS2MDL_ODR_10Hz)) {
LOG_DBG("set odr failed\n");
return -EIO;
}
lis2mdl->mag_fs_sensitivity = LIS2MDL_SENSITIVITY;
/* Set / Reset sensor mode */
if (lis2mdl_set_rst_mode_set(lis2mdl->ctx,
LIS2MDL_SENS_OFF_CANC_EVERY_ODR)) {
LOG_DBG("reset sensor mode failed\n");
return -EIO;
}
/* Enable temperature compensation */
if (lis2mdl_offset_temp_comp_set(lis2mdl->ctx, PROPERTY_ENABLE)) {
LOG_DBG("enable temp compensation failed\n");
return -EIO;
}
/* Set device in continuous mode */
if (lis2mdl_operating_mode_set(lis2mdl->ctx, LIS2MDL_CONTINUOUS_MODE)) {
LOG_DBG("set continuos mode failed\n");
return -EIO;
}
#ifdef CONFIG_LIS2MDL_TRIGGER
if (lis2mdl_init_interrupt(dev) < 0) {
@ -375,5 +354,5 @@ static int lis2mdl_init(struct device *dev)
}
DEVICE_AND_API_INIT(lis2mdl, DT_INST_0_ST_LIS2MDL_LABEL, lis2mdl_init,
&lis2mdl_device_data, &lis2mdl_dev_config, POST_KERNEL,
&lis2mdl_data, &lis2mdl_dev_config, POST_KERNEL,
CONFIG_SENSOR_INIT_PRIORITY, &lis2mdl_driver_api);

View file

@ -1,114 +1,58 @@
/*
* Copyright (c) 2018 STMicroelectronics
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
*
* LIS2MDL mag header file
* Copyright (c) 2018-2019 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
*/
#ifndef __MAG_LIS2MDL_H
#define __MAG_LIS2MDL_H
#include <drivers/spi.h>
#include <drivers/gpio.h>
#include <drivers/sensor.h>
#include <sys/util.h>
#include <drivers/i2c.h>
#define LIS2MDL_EN_BIT 1
#define LIS2MDL_DIS_BIT 0
#define LIS2MDL_I2C_ADDR(__x) (__x << 1)
#define LIS2MDL_AUTO_INCREMENT 0x80
/* Registers */
#define LIS2MDL_WHO_AM_I_REG 0x4f
#define LIS2MDL_WHOAMI_VAL 0x40
#define LIS2MDL_CFG_REG_A 0x60
/* Device supported modes */
#define LIS2MDL_MD_CONT_MODE 0x00
#define LIS2MDL_MD_SINGLE_MODE 0x01
#define LIS2MDL_MD_IDLE1_MODE 0x02
#define LIS2MDL_MD_IDLE2_MODE 0x03
#define LIS2MDL_MAG_MODE_MASK 0x03
/* Device supported ODRs */
#define LIS2MDL_ODR10_HZ 0x00
#define LIS2MDL_ODR20_HZ 0x04
#define LIS2MDL_ODR50_HZ 0x08
#define LIS2MDL_ODR100_HZ 0x0c
#define LIS2MDL_ODR_MASK 0x0c
#if defined(CONFIG_LIS2MDL_MAG_ODR_10) || \
defined(CONFIG_LIS2MDL_MAG_ODR_RUNTIME)
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR10_HZ
#elif defined(CONFIG_LIS2MDL_MAG_ODR_20)
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR20_HZ
#elif defined(CONFIG_LIS2MDL_MAG_ODR_50)
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR50_HZ
#elif defined(CONFIG_LIS2MDL_MAG_ODR_100)
#define LIS2MDL_DEFAULT_ODR LIS2MDL_ODR100_HZ
#endif
/* Sensors registers */
#define LIS2MDL_OFFSET_X_REG_L 0x45
#define LIS2MDL_OFFSET_X_REG_H 0x46
#define LIS2MDL_OFFSET_Y_REG_L 0x47
#define LIS2MDL_OFFSET_Y_REG_H 0x48
#define LIS2MDL_OFFSET_Z_REG_L 0x49
#define LIS2MDL_OFFSET_Z_REG_H 0x4A
#define LIS2MDL_CFG_REG_B 0x61
#define LIS2MDL_CFG_REG_C 0x62
#define LIS2MDL_INT_CTRL_REG 0x63
#define LIS2MDL_STATUS_REG 0x67
#define LIS2MDL_OUT_REG 0x68
#define LIS2MDL_TEMP_OUT_L_REG 0x6E
#define LIS2MDL_TEMP_OUT_H_REG 0x6F
/* Registers bitmask */
#define LIS2MDL_STS_MDA_UP 0x08
#define LIS2MDL_REBOOT 0x40
#define LIS2MDL_SOFT_RST 0x20
#define LIS2MDL_BDU_MASK 0x10
#define LIS2MDL_BDU_BIT 0x10
#define LIS2MDL_INT_MAG_PIN 0x40
#define LIS2MDL_INT_MAG_PIN_MASK 0x40
#define LIS2MDL_INT_MAG 0x01
#define LIS2MDL_INT_MAG_MASK 0x01
#define LIS2MDL_MODE_MASK 0x03
#define LIS2MDL_LP_MASK 0x10
#define LIS2MDL_IEA 0x04
#define LIS2MDL_IEL 0x02
#define LIS2MDL_IEN 0x01
#define LIS2MDL_COMP_TEMP_MASK 0x80
/* Output data size */
#define LIS2MDL_OUT_REG_SIZE 6
#define LIS2MDL_NUM_AXIS 3
/* Define ODR supported range */
#define LIS2MDL_MAX_ODR 100
#define LIS2MDL_MIN_ODR 10
#include "lis2mdl_reg.h"
/* Sensor sensitivity in uGa/LSB */
#define LIS2MDL_SENSITIVITY 1500
struct lis2mdl_device_config {
struct lis2mdl_config {
char *master_dev_name;
int (*bus_init)(struct device *dev);
#ifdef CONFIG_LIS2MDL_TRIGGER
char *gpio_name;
u32_t gpio_pin;
#endif /* CONFIG_LIS2MDL_TRIGGER */
u16_t i2c_addr_config;
#ifdef DT_ST_LIS2MDL_BUS_I2C
u16_t i2c_slv_addr;
#elif DT_ST_LIS2MDL_BUS_SPI
struct spi_config spi_conf;
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
const char *gpio_cs_port;
u8_t cs_gpio;
#endif /* DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER */
#endif /* DT_ST_LIS2MDL_BUS_SPI */
};
/* Sensor data */
struct lis2mdl_data {
struct device *i2c;
struct device *bus;
u16_t i2c_addr;
s16_t mag[3];
s32_t temp_sample;
/* save sensitivity */
u16_t mag_fs_sensitivity;
lis2mdl_ctx_t *ctx;
#ifdef DT_ST_LIS2MDL_BUS_I2C
lis2mdl_ctx_t ctx_i2c;
#elif DT_ST_LIS2MDL_BUS_SPI
lis2mdl_ctx_t ctx_spi;
#endif
#ifdef CONFIG_LIS2MDL_TRIGGER
struct device *gpio;
@ -125,8 +69,14 @@ struct lis2mdl_data {
struct device *dev;
#endif /* CONFIG_LIS2MDL_TRIGGER_GLOBAL_THREAD */
#endif /* CONFIG_LIS2MDL_TRIGGER */
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
struct spi_cs_control cs_ctrl;
#endif /* DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER */
};
int lis2mdl_spi_init(struct device *dev);
int lis2mdl_i2c_init(struct device *dev);
#ifdef CONFIG_LIS2MDL_TRIGGER
int lis2mdl_init_interrupt(struct device *dev);
int lis2mdl_trigger_set(struct device *dev,

View file

@ -0,0 +1,54 @@
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
*
* Copyright (c) 2019 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
*/
#include <string.h>
#include <drivers/i2c.h>
#include <logging/log.h>
#include "lis2mdl.h"
#ifdef DT_ST_LIS2MDL_BUS_I2C
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
LOG_MODULE_DECLARE(LIS2MDL);
static int lis2mdl_i2c_read(struct device *dev, u8_t reg_addr,
u8_t *value, u16_t len)
{
struct lis2mdl_data *data = dev->driver_data;
const struct lis2mdl_config *cfg = dev->config->config_info;
return i2c_burst_read(data->bus, cfg->i2c_slv_addr,
reg_addr, value, len);
}
static int lis2mdl_i2c_write(struct device *dev, u8_t reg_addr,
u8_t *value, u16_t len)
{
struct lis2mdl_data *data = dev->driver_data;
const struct lis2mdl_config *cfg = dev->config->config_info;
return i2c_burst_write(data->bus, cfg->i2c_slv_addr,
reg_addr, value, len);
}
int lis2mdl_i2c_init(struct device *dev)
{
struct lis2mdl_data *data = dev->driver_data;
data->ctx_i2c.read_reg = (lis2mdl_read_ptr) lis2mdl_i2c_read;
data->ctx_i2c.write_reg = (lis2mdl_write_ptr) lis2mdl_i2c_write;
data->ctx = &data->ctx_i2c;
data->ctx->handle = dev;
return 0;
}
#endif /* DT_ST_LIS2MDL_BUS_I2C */

View file

@ -0,0 +1,127 @@
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
*
* Copyright (c) 2019 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
*/
#include <string.h>
#include "lis2mdl.h"
#include <logging/log.h>
#ifdef DT_ST_LIS2MDL_BUS_SPI
#define LIS2MDL_SPI_READ (1 << 7)
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
LOG_MODULE_DECLARE(LIS2MDL);
static int lis2mdl_spi_read(struct device *dev, u8_t reg_addr,
u8_t *value, u8_t len)
{
struct lis2mdl_data *data = dev->driver_data;
const struct lis2mdl_config *cfg = dev->config->config_info;
const struct spi_config *spi_cfg = &cfg->spi_conf;
u8_t buffer_tx[2] = { reg_addr | LIS2MDL_SPI_READ, 0 };
const struct spi_buf tx_buf = {
.buf = buffer_tx,
.len = 2,
};
const struct spi_buf_set tx = {
.buffers = &tx_buf,
.count = 1
};
const struct spi_buf rx_buf[2] = {
{
.buf = NULL,
.len = 1,
},
{
.buf = value,
.len = len,
}
};
const struct spi_buf_set rx = {
.buffers = rx_buf,
.count = 2
};
if (len > 64) {
return -EIO;
}
if (spi_transceive(data->bus, spi_cfg, &tx, &rx)) {
return -EIO;
}
return 0;
}
static int lis2mdl_spi_write(struct device *dev, u8_t reg_addr,
u8_t *value, u8_t len)
{
struct lis2mdl_data *data = dev->driver_data;
const struct lis2mdl_config *cfg = dev->config->config_info;
const struct spi_config *spi_cfg = &cfg->spi_conf;
u8_t buffer_tx[1] = { reg_addr & ~LIS2MDL_SPI_READ };
const struct spi_buf tx_buf[2] = {
{
.buf = buffer_tx,
.len = 1,
},
{
.buf = value,
.len = len,
}
};
const struct spi_buf_set tx = {
.buffers = tx_buf,
.count = 2
};
if (len > 64) {
return -EIO;
}
if (spi_write(data->bus, spi_cfg, &tx)) {
return -EIO;
}
return 0;
}
int lis2mdl_spi_init(struct device *dev)
{
struct lis2mdl_data *data = dev->driver_data;
data->ctx_spi.read_reg = (lis2mdl_read_ptr) lis2mdl_spi_read;
data->ctx_spi.write_reg = (lis2mdl_write_ptr) lis2mdl_spi_write;
data->ctx = &data->ctx_spi;
data->ctx->handle = dev;
#if defined(DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER)
const struct lis2mdl_config *cfg = dev->config->config_info;
/* handle SPI CS thru GPIO if it is the case */
data->cs_ctrl.gpio_dev = device_get_binding(cfg->gpio_cs_port);
if (!data->cs_ctrl.gpio_dev) {
LOG_ERR("Unable to get GPIO SPI CS device");
return -ENODEV;
}
data->cs_ctrl.gpio_pin = cfg->cs_gpio;
data->cs_ctrl.delay = 0;
LOG_DBG("SPI GPIO CS configured on %s:%u",
cfg->gpio_cs_port, cfg->cs_gpio);
#endif
return 0;
}
#endif /* DT_ST_LIS2MDL_BUS_SPI */

View file

@ -1,9 +1,11 @@
/*
* Copyright (c) 2018 STMicroelectronics
/* ST Microelectronics LIS2MDL 3-axis magnetometer sensor
*
* LIS2MDL mag interrupt configuration and management
* Copyright (c) 2018-2019 STMicroelectronics
*
* SPDX-License-Identifier: Apache-2.0
*
* Datasheet:
* https://www.st.com/resource/en/datasheet/lis2mdl.pdf
*/
#include <kernel.h>
@ -21,10 +23,7 @@ static int lis2mdl_enable_int(struct device *dev, int enable)
struct lis2mdl_data *lis2mdl = dev->driver_data;
/* set interrupt on mag */
return i2c_reg_update_byte(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_CFG_REG_C,
LIS2MDL_INT_MAG_MASK,
enable ? LIS2MDL_INT_MAG : 0);
return lis2mdl_drdy_on_pin_set(lis2mdl->ctx, enable);
}
/* link external trigger to event data ready */
@ -33,18 +32,14 @@ int lis2mdl_trigger_set(struct device *dev,
sensor_trigger_handler_t handler)
{
struct lis2mdl_data *lis2mdl = dev->driver_data;
u8_t raw[LIS2MDL_OUT_REG_SIZE];
axis3bit16_t raw;
if (trig->chan == SENSOR_CHAN_MAGN_XYZ) {
lis2mdl->handler_drdy = handler;
if (handler) {
/* fetch raw data sample: re-trigger lost interrupt */
if (i2c_burst_read(lis2mdl->i2c, lis2mdl->i2c_addr,
LIS2MDL_OUT_REG, raw,
sizeof(raw)) < 0) {
LOG_ERR("Failed to fetch raw data sample.");
return -EIO;
}
lis2mdl_magnetic_raw_get(lis2mdl->ctx, raw.u8bit);
return lis2mdl_enable_int(dev, 1);
} else {
return lis2mdl_enable_int(dev, 0);
@ -59,7 +54,7 @@ static void lis2mdl_handle_interrupt(void *arg)
{
struct device *dev = arg;
struct lis2mdl_data *lis2mdl = dev->driver_data;
const struct lis2mdl_device_config *const config =
const struct lis2mdl_config *const config =
dev->config->config_info;
struct sensor_trigger drdy_trigger = {
.type = SENSOR_TRIG_DATA_READY,
@ -77,8 +72,7 @@ static void lis2mdl_gpio_callback(struct device *dev,
{
struct lis2mdl_data *lis2mdl =
CONTAINER_OF(cb, struct lis2mdl_data, gpio_cb);
const struct lis2mdl_device_config *const config =
dev->config->config_info;
const struct lis2mdl_config *const config = dev->config->config_info;
ARG_UNUSED(pins);
@ -119,8 +113,7 @@ static void lis2mdl_work_cb(struct k_work *work)
int lis2mdl_init_interrupt(struct device *dev)
{
struct lis2mdl_data *lis2mdl = dev->driver_data;
const struct lis2mdl_device_config *const config =
dev->config->config_info;
const struct lis2mdl_config *const config = dev->config->config_info;
/* setup data ready gpio interrupt */
lis2mdl->gpio = device_get_binding(config->gpio_name);

View file

@ -195,6 +195,7 @@
#define DT_INST_0_ST_LIS2MDL_BASE_ADDRESS 0x19
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER ""
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN 0
#define DT_ST_LIS2MDL_BUS_I2C 1
#endif
#ifndef DT_INST_0_ST_LIS2DW12_LABEL
@ -336,6 +337,18 @@
#define DT_ST_LIS2DW12_BUS_SPI 1
#endif
#ifndef DT_INST_0_ST_LIS2MDL_LABEL
#define DT_INST_0_ST_LIS2MDL_LABEL ""
#define DT_INST_0_ST_LIS2MDL_BUS_NAME ""
#define DT_INST_0_ST_LIS2MDL_SPI_MAX_FREQUENCY 100000
#define DT_INST_0_ST_LIS2MDL_BASE_ADDRESS 1
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_CONTROLLER ""
#define DT_INST_0_ST_LIS2MDL_IRQ_GPIOS_PIN 0
#define DT_INST_0_ST_LIS2MDL_CS_GPIOS_CONTROLLER 0
#define DT_INST_0_ST_LIS2MDL_CS_GPIOS_PIN 0
#define DT_ST_LIS2MDL_BUS_SPI 1
#endif
#ifndef DT_INST_0_ST_LPS22HH_LABEL
#define DT_INST_0_ST_LPS22HH_LABEL ""
#define DT_INST_0_ST_LPS22HH_BUS_NAME ""