drivers/sensor: add support to IIS2MDC magnetometer sensor
The IIS2MDC is a 3D digital magnetometer ultra-low power sensor for industrial applications, which can be interfaced through either I2C or SPI bus. https://www.st.com/resource/en/datasheet/iis2mdc.pdf This driver is based on stmemsc i/f v1.02. Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
parent
6dc7b40da9
commit
a302786e9b
14 changed files with 933 additions and 0 deletions
|
@ -26,6 +26,7 @@ add_subdirectory_ifdef(CONFIG_HMC5883L hmc5883l)
|
|||
add_subdirectory_ifdef(CONFIG_HP206C hp206c)
|
||||
add_subdirectory_ifdef(CONFIG_HTS221 hts221)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2DLPC iis2dlpc)
|
||||
add_subdirectory_ifdef(CONFIG_IIS2MDC iis2mdc)
|
||||
add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc)
|
||||
add_subdirectory_ifdef(CONFIG_ISL29035 isl29035)
|
||||
add_subdirectory_ifdef(CONFIG_ISM330DHCX ism330dhcx)
|
||||
|
|
|
@ -81,6 +81,8 @@ source "drivers/sensor/hts221/Kconfig"
|
|||
|
||||
source "drivers/sensor/iis2dlpc/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis2mdc/Kconfig"
|
||||
|
||||
source "drivers/sensor/iis3dhhc/Kconfig"
|
||||
|
||||
source "drivers/sensor/isl29035/Kconfig"
|
||||
|
|
11
drivers/sensor/iis2mdc/CMakeLists.txt
Normal file
11
drivers/sensor/iis2mdc/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Copyright (c) 2020 STMicroelectronics
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
zephyr_library()
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2MDC iis2mdc.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2MDC iis2mdc_i2c.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2MDC iis2mdc_spi.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_IIS2MDC_TRIGGER iis2mdc_trigger.c)
|
60
drivers/sensor/iis2mdc/Kconfig
Normal file
60
drivers/sensor/iis2mdc/Kconfig
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Copyright (c) 2020 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
menuconfig IIS2MDC
|
||||
bool "IIS2MDC Magnetometer"
|
||||
depends on (I2C && HAS_DTS_I2C) || SPI
|
||||
select HAS_STMEMSC
|
||||
select USE_STDC_IIS2MDC
|
||||
help
|
||||
Enable driver for IIS2MDC I2C-based magnetometer sensor.
|
||||
|
||||
if IIS2MDC
|
||||
|
||||
choice IIS2MDC_TRIGGER_MODE
|
||||
prompt "Trigger mode"
|
||||
default IIS2MDC_TRIGGER_GLOBAL_THREAD
|
||||
help
|
||||
Specify the type of triggering to be used by the driver.
|
||||
|
||||
config IIS2MDC_TRIGGER_NONE
|
||||
bool "No trigger"
|
||||
|
||||
config IIS2MDC_TRIGGER_GLOBAL_THREAD
|
||||
bool "Use global thread"
|
||||
depends on GPIO
|
||||
select IIS2MDC_TRIGGER
|
||||
|
||||
config IIS2MDC_TRIGGER_OWN_THREAD
|
||||
bool "Use own thread"
|
||||
depends on GPIO
|
||||
select IIS2MDC_TRIGGER
|
||||
|
||||
endchoice # IIS2MDC_TRIGGER_MODE
|
||||
|
||||
config IIS2MDC_TRIGGER
|
||||
bool
|
||||
|
||||
config IIS2MDC_THREAD_PRIORITY
|
||||
int "Thread priority"
|
||||
depends on IIS2MDC_TRIGGER_OWN_THREAD
|
||||
default 10
|
||||
help
|
||||
Priority of thread used by the driver to handle interrupts.
|
||||
|
||||
config IIS2MDC_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
depends on IIS2MDC_TRIGGER_OWN_THREAD
|
||||
default 1024
|
||||
help
|
||||
Stack size of thread used by the driver to handle interrupts.
|
||||
|
||||
config IIS2MDC_MAG_ODR_RUNTIME
|
||||
bool "Set magnetometer sampling frequency (ODR) at runtime (default: 10 Hz)"
|
||||
default y
|
||||
|
||||
config IIS2MDC_SPI_FULL_DUPLEX
|
||||
bool "Enable SPI 4wire mode (separated MISO and MOSI lines)"
|
||||
depends on SPI
|
||||
|
||||
endif # IIS2MDC
|
364
drivers/sensor/iis2mdc/iis2mdc.c
Normal file
364
drivers/sensor/iis2mdc/iis2mdc.c
Normal file
|
@ -0,0 +1,364 @@
|
|||
/* ST Microelectronics IIS2MDC 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
|
||||
*/
|
||||
|
||||
#include <init.h>
|
||||
#include <sys/__assert.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <string.h>
|
||||
#include <logging/log.h>
|
||||
#include "iis2mdc.h"
|
||||
|
||||
struct iis2mdc_data iis2mdc_data;
|
||||
|
||||
LOG_MODULE_REGISTER(IIS2MDC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_MAG_ODR_RUNTIME
|
||||
static int iis2mdc_set_odr(struct device *dev, const struct sensor_value *val)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
iis2mdc_odr_t odr;
|
||||
|
||||
switch (val->val1) {
|
||||
case 10:
|
||||
odr = IIS2MDC_ODR_10Hz;
|
||||
break;
|
||||
case 20:
|
||||
odr = IIS2MDC_ODR_20Hz;
|
||||
break;
|
||||
case 50:
|
||||
odr = IIS2MDC_ODR_50Hz;
|
||||
break;
|
||||
case 100:
|
||||
odr = IIS2MDC_ODR_100Hz;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (iis2mdc_data_rate_set(iis2mdc->ctx, odr)) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IIS2MDC_MAG_ODR_RUNTIME */
|
||||
|
||||
static int iis2mdc_set_hard_iron(struct device *dev, enum sensor_channel chan,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
u8_t i;
|
||||
union axis3bit16_t offset;
|
||||
|
||||
for (i = 0U; i < 3; i++) {
|
||||
offset.i16bit[i] = sys_cpu_to_le16(val->val1);
|
||||
val++;
|
||||
}
|
||||
|
||||
return iis2mdc_mag_user_offset_set(iis2mdc->ctx, offset.u8bit);
|
||||
}
|
||||
|
||||
static void iis2mdc_channel_get_mag(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
s32_t cval;
|
||||
int i;
|
||||
u8_t ofs_start, ofs_stop;
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
struct sensor_value *pval = val;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
ofs_start = ofs_stop = 0U;
|
||||
break;
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
ofs_start = ofs_stop = 1U;
|
||||
break;
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
ofs_start = ofs_stop = 2U;
|
||||
break;
|
||||
default:
|
||||
ofs_start = 0U; ofs_stop = 2U;
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = ofs_start; i <= ofs_stop; i++) {
|
||||
cval = iis2mdc->mag[i] * 1500;
|
||||
pval->val1 = cval / 1000000;
|
||||
pval->val2 = cval % 1000000;
|
||||
pval++;
|
||||
}
|
||||
}
|
||||
|
||||
/* read internal temperature */
|
||||
static void iis2mdc_channel_get_temp(struct device *dev,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct iis2mdc_data *drv_data = dev->driver_data;
|
||||
|
||||
val->val1 = drv_data->temp_sample / 100;
|
||||
val->val2 = (drv_data->temp_sample % 100) * 10000;
|
||||
}
|
||||
|
||||
static int iis2mdc_channel_get(struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
case SENSOR_CHAN_MAGN_XYZ:
|
||||
iis2mdc_channel_get_mag(dev, chan, val);
|
||||
break;
|
||||
case SENSOR_CHAN_DIE_TEMP:
|
||||
iis2mdc_channel_get_temp(dev, val);
|
||||
break;
|
||||
default:
|
||||
LOG_DBG("Channel not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2mdc_config(struct device *dev, enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
const struct sensor_value *val)
|
||||
{
|
||||
switch (attr) {
|
||||
#ifdef CONFIG_IIS2MDC_MAG_ODR_RUNTIME
|
||||
case SENSOR_ATTR_SAMPLING_FREQUENCY:
|
||||
return iis2mdc_set_odr(dev, val);
|
||||
#endif /* CONFIG_IIS2MDC_MAG_ODR_RUNTIME */
|
||||
case SENSOR_ATTR_OFFSET:
|
||||
return iis2mdc_set_hard_iron(dev, chan, val);
|
||||
default:
|
||||
LOG_DBG("Mag attribute not supported");
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2mdc_attr_set(struct device *dev,
|
||||
enum sensor_channel chan,
|
||||
enum sensor_attribute attr,
|
||||
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:
|
||||
case SENSOR_CHAN_MAGN_XYZ:
|
||||
return iis2mdc_config(dev, chan, attr, val);
|
||||
default:
|
||||
LOG_DBG("attr_set() not supported on %d channel", chan);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2mdc_sample_fetch_mag(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
union axis3bit16_t raw_mag;
|
||||
|
||||
/* fetch raw data sample */
|
||||
if (iis2mdc_magnetic_raw_get(iis2mdc->ctx, raw_mag.u8bit) < 0) {
|
||||
LOG_DBG("Failed to read sample");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
iis2mdc->mag[0] = sys_le16_to_cpu(raw_mag.i16bit[0]);
|
||||
iis2mdc->mag[1] = sys_le16_to_cpu(raw_mag.i16bit[1]);
|
||||
iis2mdc->mag[2] = sys_le16_to_cpu(raw_mag.i16bit[2]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2mdc_sample_fetch_temp(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
union axis1bit16_t raw_temp;
|
||||
s32_t temp;
|
||||
|
||||
/* fetch raw temperature sample */
|
||||
if (iis2mdc_temperature_raw_get(iis2mdc->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(raw_temp.i16bit) & 0x8FFF);
|
||||
iis2mdc->temp_sample = 2500 + (temp * 100) / 8;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iis2mdc_sample_fetch(struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
case SENSOR_CHAN_MAGN_XYZ:
|
||||
iis2mdc_sample_fetch_mag(dev);
|
||||
break;
|
||||
case SENSOR_CHAN_DIE_TEMP:
|
||||
iis2mdc_sample_fetch_temp(dev);
|
||||
break;
|
||||
case SENSOR_CHAN_ALL:
|
||||
iis2mdc_sample_fetch_mag(dev);
|
||||
iis2mdc_sample_fetch_temp(dev);
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api iis2mdc_driver_api = {
|
||||
.attr_set = iis2mdc_attr_set,
|
||||
#if CONFIG_IIS2MDC_TRIGGER
|
||||
.trigger_set = iis2mdc_trigger_set,
|
||||
#endif
|
||||
.sample_fetch = iis2mdc_sample_fetch,
|
||||
.channel_get = iis2mdc_channel_get,
|
||||
};
|
||||
|
||||
static int iis2mdc_init_interface(struct device *dev)
|
||||
{
|
||||
const struct iis2mdc_config *const config =
|
||||
dev->config->config_info;
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
|
||||
iis2mdc->bus = device_get_binding(config->master_dev_name);
|
||||
if (!iis2mdc->bus) {
|
||||
LOG_DBG("Could not get pointer to %s device",
|
||||
config->master_dev_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return config->bus_init(dev);
|
||||
}
|
||||
|
||||
static const struct iis2mdc_config iis2mdc_dev_config = {
|
||||
.master_dev_name = DT_INST_0_ST_IIS2MDC_BUS_NAME,
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER
|
||||
.drdy_port = DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_CONTROLLER,
|
||||
.drdy_pin = DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_PIN,
|
||||
.drdy_flags = DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_FLAGS,
|
||||
#endif /* CONFIG_IIS2MDC_TRIGGER */
|
||||
#if defined(DT_ST_IIS2MDC_BUS_SPI)
|
||||
.bus_init = iis2mdc_spi_init,
|
||||
.spi_conf.frequency = DT_INST_0_ST_IIS2MDC_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_IIS2MDC_BASE_ADDRESS,
|
||||
#if defined(DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER)
|
||||
.gpio_cs_port = DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER,
|
||||
.cs_gpio = DT_INST_0_ST_IIS2MDC_CS_GPIOS_PIN,
|
||||
|
||||
.spi_conf.cs = &iis2mdc_data.cs_ctrl,
|
||||
#else
|
||||
.spi_conf.cs = NULL,
|
||||
#endif
|
||||
#elif defined(DT_ST_IIS2MDC_BUS_I2C)
|
||||
.bus_init = iis2mdc_i2c_init,
|
||||
.i2c_slv_addr = DT_INST_0_ST_IIS2MDC_BASE_ADDRESS,
|
||||
#else
|
||||
#error "BUS MACRO NOT DEFINED IN DTS"
|
||||
#endif
|
||||
};
|
||||
|
||||
static int iis2mdc_init(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
u8_t wai;
|
||||
|
||||
if (iis2mdc_init_interface(dev)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* check chip ID */
|
||||
if (iis2mdc_device_id_get(iis2mdc->ctx, &wai) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wai != IIS2MDC_ID) {
|
||||
LOG_DBG("Invalid chip ID: %02x\n", wai);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* reset sensor configuration */
|
||||
if (iis2mdc_reset_set(iis2mdc->ctx, PROPERTY_ENABLE) < 0) {
|
||||
LOG_DBG("s/w reset failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_busy_wait(100);
|
||||
|
||||
#if CONFIG_IIS2MDC_SPI_FULL_DUPLEX
|
||||
/* After s/w reset set SPI 4wires again if the case */
|
||||
if (iis2mdc_spi_mode_set(iis2mdc->ctx, IIS2MDC_SPI_4_WIRE) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* enable BDU */
|
||||
if (iis2mdc_block_data_update_set(iis2mdc->ctx, PROPERTY_ENABLE) < 0) {
|
||||
LOG_DBG("setting bdu failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set Output Data Rate */
|
||||
if (iis2mdc_data_rate_set(iis2mdc->ctx, IIS2MDC_ODR_10Hz)) {
|
||||
LOG_DBG("set odr failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set / Reset sensor mode */
|
||||
if (iis2mdc_set_rst_mode_set(iis2mdc->ctx,
|
||||
IIS2MDC_SENS_OFF_CANC_EVERY_ODR)) {
|
||||
LOG_DBG("reset sensor mode failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Enable temperature compensation */
|
||||
if (iis2mdc_offset_temp_comp_set(iis2mdc->ctx, PROPERTY_ENABLE)) {
|
||||
LOG_DBG("enable temp compensation failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* Set device in continuous mode */
|
||||
if (iis2mdc_operating_mode_set(iis2mdc->ctx, IIS2MDC_CONTINUOUS_MODE)) {
|
||||
LOG_DBG("set continuos mode failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER
|
||||
if (iis2mdc_init_interrupt(dev) < 0) {
|
||||
LOG_DBG("Failed to initialize interrupts");
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEVICE_AND_API_INIT(iis2mdc, DT_INST_0_ST_IIS2MDC_LABEL, iis2mdc_init,
|
||||
&iis2mdc_data, &iis2mdc_dev_config, POST_KERNEL,
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &iis2mdc_driver_api);
|
94
drivers/sensor/iis2mdc/iis2mdc.h
Normal file
94
drivers/sensor/iis2mdc/iis2mdc.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* ST Microelectronics IIS2MDC 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
|
||||
*/
|
||||
|
||||
#ifndef __MAG_IIS2MDC_H
|
||||
#define __MAG_IIS2MDC_H
|
||||
|
||||
#include <drivers/spi.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <sys/util.h>
|
||||
#include "iis2mdc_reg.h"
|
||||
|
||||
union axis3bit16_t {
|
||||
s16_t i16bit[3];
|
||||
u8_t u8bit[6];
|
||||
};
|
||||
|
||||
union axis1bit16_t {
|
||||
s16_t i16bit;
|
||||
u8_t u8bit[2];
|
||||
};
|
||||
|
||||
struct iis2mdc_config {
|
||||
char *master_dev_name;
|
||||
int (*bus_init)(struct device *dev);
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER
|
||||
const char *drdy_port;
|
||||
gpio_pin_t drdy_pin;
|
||||
gpio_dt_flags_t drdy_flags;
|
||||
#endif /* CONFIG_IIS2MDC_TRIGGER */
|
||||
#ifdef DT_ST_IIS2MDC_BUS_I2C
|
||||
u16_t i2c_slv_addr;
|
||||
#elif DT_ST_IIS2MDC_BUS_SPI
|
||||
struct spi_config spi_conf;
|
||||
#if defined(DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER)
|
||||
const char *gpio_cs_port;
|
||||
u8_t cs_gpio;
|
||||
#endif /* DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER */
|
||||
#endif /* DT_ST_IIS2MDC_BUS_SPI */
|
||||
};
|
||||
|
||||
/* Sensor data */
|
||||
struct iis2mdc_data {
|
||||
struct device *bus;
|
||||
u16_t i2c_addr;
|
||||
s16_t mag[3];
|
||||
s32_t temp_sample;
|
||||
|
||||
stmdev_ctx_t *ctx;
|
||||
|
||||
#ifdef DT_ST_IIS2MDC_BUS_I2C
|
||||
stmdev_ctx_t ctx_i2c;
|
||||
#elif DT_ST_IIS2MDC_BUS_SPI
|
||||
stmdev_ctx_t ctx_spi;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER
|
||||
struct device *gpio;
|
||||
struct gpio_callback gpio_cb;
|
||||
|
||||
sensor_trigger_handler_t handler_drdy;
|
||||
|
||||
#if defined(CONFIG_IIS2MDC_TRIGGER_OWN_THREAD)
|
||||
K_THREAD_STACK_MEMBER(thread_stack, CONFIG_IIS2MDC_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem gpio_sem;
|
||||
#elif defined(CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
struct device *dev;
|
||||
#endif /* CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD */
|
||||
#endif /* CONFIG_IIS2MDC_TRIGGER */
|
||||
#if defined(DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER)
|
||||
struct spi_cs_control cs_ctrl;
|
||||
#endif /* DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER */
|
||||
};
|
||||
|
||||
int iis2mdc_spi_init(struct device *dev);
|
||||
int iis2mdc_i2c_init(struct device *dev);
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER
|
||||
int iis2mdc_init_interrupt(struct device *dev);
|
||||
int iis2mdc_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler);
|
||||
#endif /* CONFIG_IIS2MDC_TRIGGER */
|
||||
|
||||
#endif /* __MAG_IIS2MDC_H */
|
54
drivers/sensor/iis2mdc/iis2mdc_i2c.c
Normal file
54
drivers/sensor/iis2mdc/iis2mdc_i2c.c
Normal file
|
@ -0,0 +1,54 @@
|
|||
/* ST Microelectronics IIS2MDC 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <drivers/i2c.h>
|
||||
#include <logging/log.h>
|
||||
|
||||
#include "iis2mdc.h"
|
||||
|
||||
#ifdef DT_ST_IIS2MDC_BUS_I2C
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
LOG_MODULE_DECLARE(IIS2MDC);
|
||||
|
||||
static int iis2mdc_i2c_read(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
const struct iis2mdc_config *cfg = dev->config->config_info;
|
||||
|
||||
return i2c_burst_read(data->bus, cfg->i2c_slv_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
static int iis2mdc_i2c_write(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u16_t len)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
const struct iis2mdc_config *cfg = dev->config->config_info;
|
||||
|
||||
return i2c_burst_write(data->bus, cfg->i2c_slv_addr,
|
||||
reg_addr, value, len);
|
||||
}
|
||||
|
||||
int iis2mdc_i2c_init(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
|
||||
data->ctx_i2c.read_reg = (stmdev_read_ptr) iis2mdc_i2c_read;
|
||||
data->ctx_i2c.write_reg = (stmdev_write_ptr) iis2mdc_i2c_write;
|
||||
|
||||
data->ctx = &data->ctx_i2c;
|
||||
data->ctx->handle = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_IIS2MDC_BUS_I2C */
|
134
drivers/sensor/iis2mdc/iis2mdc_spi.c
Normal file
134
drivers/sensor/iis2mdc/iis2mdc_spi.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* ST Microelectronics IIS2MDC 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "iis2mdc.h"
|
||||
#include <logging/log.h>
|
||||
|
||||
#ifdef DT_ST_IIS2MDC_BUS_SPI
|
||||
|
||||
#define IIS2MDC_SPI_READ (1 << 7)
|
||||
|
||||
#define LOG_LEVEL CONFIG_SENSOR_LOG_LEVEL
|
||||
LOG_MODULE_DECLARE(IIS2MDC);
|
||||
|
||||
static int iis2mdc_spi_read(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u8_t len)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
const struct iis2mdc_config *cfg = dev->config->config_info;
|
||||
const struct spi_config *spi_cfg = &cfg->spi_conf;
|
||||
u8_t buffer_tx[2] = { reg_addr | IIS2MDC_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 iis2mdc_spi_write(struct device *dev, u8_t reg_addr,
|
||||
u8_t *value, u8_t len)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
const struct iis2mdc_config *cfg = dev->config->config_info;
|
||||
const struct spi_config *spi_cfg = &cfg->spi_conf;
|
||||
u8_t buffer_tx[1] = { reg_addr & ~IIS2MDC_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 iis2mdc_spi_init(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *data = dev->driver_data;
|
||||
|
||||
data->ctx_spi.read_reg = (stmdev_read_ptr) iis2mdc_spi_read;
|
||||
data->ctx_spi.write_reg = (stmdev_write_ptr) iis2mdc_spi_write;
|
||||
|
||||
data->ctx = &data->ctx_spi;
|
||||
data->ctx->handle = dev;
|
||||
|
||||
#if defined(DT_INST_0_ST_IIS2MDC_CS_GPIOS_CONTROLLER)
|
||||
const struct iis2mdc_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
|
||||
|
||||
#if CONFIG_IIS2MDC_SPI_FULL_DUPLEX
|
||||
/* Set SPI 4wires */
|
||||
if (iis2mdc_spi_mode_set(data->ctx, IIS2MDC_SPI_4_WIRE) < 0) {
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* DT_ST_IIS2MDC_BUS_SPI */
|
151
drivers/sensor/iis2mdc/iis2mdc_trigger.c
Normal file
151
drivers/sensor/iis2mdc/iis2mdc_trigger.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
/* ST Microelectronics IIS2MDC 3-axis magnetometer sensor
|
||||
*
|
||||
* Copyright (c) 2020 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Datasheet:
|
||||
* https://www.st.com/resource/en/datasheet/iis2mdc.pdf
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <drivers/sensor.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <logging/log.h>
|
||||
#include "iis2mdc.h"
|
||||
|
||||
LOG_MODULE_DECLARE(IIS2MDC, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static int iis2mdc_enable_int(struct device *dev, int enable)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
|
||||
/* set interrupt on mag */
|
||||
return iis2mdc_drdy_on_pin_set(iis2mdc->ctx, enable);
|
||||
}
|
||||
|
||||
/* link external trigger to event data ready */
|
||||
int iis2mdc_trigger_set(struct device *dev,
|
||||
const struct sensor_trigger *trig,
|
||||
sensor_trigger_handler_t handler)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
union axis3bit16_t raw;
|
||||
|
||||
if (trig->chan == SENSOR_CHAN_MAGN_XYZ) {
|
||||
iis2mdc->handler_drdy = handler;
|
||||
if (handler) {
|
||||
/* fetch raw data sample: re-trigger lost interrupt */
|
||||
iis2mdc_magnetic_raw_get(iis2mdc->ctx, raw.u8bit);
|
||||
|
||||
return iis2mdc_enable_int(dev, 1);
|
||||
} else {
|
||||
return iis2mdc_enable_int(dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* handle the drdy event: read data and call handler if registered any */
|
||||
static void iis2mdc_handle_interrupt(void *arg)
|
||||
{
|
||||
struct device *dev = arg;
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
const struct iis2mdc_config *const config =
|
||||
dev->config->config_info;
|
||||
struct sensor_trigger drdy_trigger = {
|
||||
.type = SENSOR_TRIG_DATA_READY,
|
||||
};
|
||||
|
||||
if (iis2mdc->handler_drdy != NULL) {
|
||||
iis2mdc->handler_drdy(dev, &drdy_trigger);
|
||||
}
|
||||
|
||||
gpio_pin_interrupt_configure(iis2mdc->gpio, config->drdy_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
||||
|
||||
static void iis2mdc_gpio_callback(struct device *dev,
|
||||
struct gpio_callback *cb, u32_t pins)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc =
|
||||
CONTAINER_OF(cb, struct iis2mdc_data, gpio_cb);
|
||||
const struct iis2mdc_config *const config = dev->config->config_info;
|
||||
|
||||
ARG_UNUSED(pins);
|
||||
|
||||
gpio_pin_interrupt_configure(dev, config->drdy_pin, GPIO_INT_DISABLE);
|
||||
|
||||
#if defined(CONFIG_IIS2MDC_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&iis2mdc->gpio_sem);
|
||||
#elif defined(CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&iis2mdc->work);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER_OWN_THREAD
|
||||
static void iis2mdc_thread(int dev_ptr, int unused)
|
||||
{
|
||||
struct device *dev = INT_TO_POINTER(dev_ptr);
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
|
||||
ARG_UNUSED(unused);
|
||||
|
||||
while (1) {
|
||||
k_sem_take(&iis2mdc->gpio_sem, K_FOREVER);
|
||||
iis2mdc_handle_interrupt(dev);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD
|
||||
static void iis2mdc_work_cb(struct k_work *work)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc =
|
||||
CONTAINER_OF(work, struct iis2mdc_data, work);
|
||||
|
||||
iis2mdc_handle_interrupt(iis2mdc->dev);
|
||||
}
|
||||
#endif
|
||||
|
||||
int iis2mdc_init_interrupt(struct device *dev)
|
||||
{
|
||||
struct iis2mdc_data *iis2mdc = dev->driver_data;
|
||||
const struct iis2mdc_config *const config = dev->config->config_info;
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
iis2mdc->gpio = device_get_binding(config->drdy_port);
|
||||
if (iis2mdc->gpio == NULL) {
|
||||
LOG_DBG("Cannot get pointer to %s device",
|
||||
config->drdy_port);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IIS2MDC_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&iis2mdc->gpio_sem, 0, UINT_MAX);
|
||||
k_thread_create(&iis2mdc->thread, iis2mdc->thread_stack,
|
||||
CONFIG_IIS2MDC_THREAD_STACK_SIZE,
|
||||
(k_thread_entry_t)iis2mdc_thread, dev,
|
||||
0, NULL, K_PRIO_COOP(CONFIG_IIS2MDC_THREAD_PRIORITY),
|
||||
0, K_NO_WAIT);
|
||||
#elif defined(CONFIG_IIS2MDC_TRIGGER_GLOBAL_THREAD)
|
||||
iis2mdc->work.handler = iis2mdc_work_cb;
|
||||
iis2mdc->dev = dev;
|
||||
#endif
|
||||
|
||||
gpio_pin_configure(iis2mdc->gpio, config->drdy_pin,
|
||||
GPIO_INPUT | config->drdy_flags);
|
||||
|
||||
gpio_init_callback(&iis2mdc->gpio_cb,
|
||||
iis2mdc_gpio_callback,
|
||||
BIT(config->drdy_pin));
|
||||
|
||||
if (gpio_add_callback(iis2mdc->gpio, &iis2mdc->gpio_cb) < 0) {
|
||||
LOG_DBG("Could not set gpio callback");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return gpio_pin_interrupt_configure(iis2mdc->gpio, config->drdy_pin,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
19
dts/bindings/sensor/st,iis2mdc-i2c.yaml
Normal file
19
dts/bindings/sensor/st,iis2mdc-i2c.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2018 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2MDC magnetometer accessed through I2C bus
|
||||
|
||||
compatible: "st,iis2mdc"
|
||||
|
||||
include: i2c-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
19
dts/bindings/sensor/st,iis2mdc-spi.yaml
Normal file
19
dts/bindings/sensor/st,iis2mdc-spi.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Copyright (c) 2019 STMicroelectronics
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
STMicroelectronics IIS2MDC magnetometer accessed through SPI bus
|
||||
|
||||
compatible: "st,iis2mdc"
|
||||
|
||||
include: spi-device.yaml
|
||||
|
||||
properties:
|
||||
drdy-gpios:
|
||||
type: phandle-array
|
||||
required: false
|
||||
description: DRDY pin
|
||||
|
||||
This pin defaults to active high when produced by the sensor.
|
||||
The property value should ensure the flags properly describe
|
||||
the signal that is presented to the driver.
|
|
@ -139,6 +139,16 @@
|
|||
#define DT_ST_IIS2DLPC_BUS_I2C 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS2MDC_LABEL
|
||||
#define DT_INST_0_ST_IIS2MDC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS2MDC_BUS_NAME ""
|
||||
#define DT_INST_0_ST_IIS2MDC_BASE_ADDRESS 0
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_FLAGS 0
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_PIN 0
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_CONTROLLER ""
|
||||
#define DT_ST_IIS2MDC_BUS_I2C 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_LIS3MDL_MAGN_LABEL
|
||||
#define DT_INST_0_ST_LIS3MDL_MAGN_LABEL ""
|
||||
#define DT_INST_0_ST_LIS3MDL_MAGN_BUS_NAME ""
|
||||
|
@ -527,6 +537,17 @@
|
|||
#define DT_ST_ISM330DHCX_BUS_SPI 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS2MDC_LABEL
|
||||
#define DT_INST_0_ST_IIS2MDC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS2MDC_BUS_NAME ""
|
||||
#define DT_INST_0_ST_IIS2MDC_SPI_MAX_FREQUENCY 100000
|
||||
#define DT_INST_0_ST_IIS2MDC_BASE_ADDRESS 1
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_CONTROLLER ""
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_FLAGS 0
|
||||
#define DT_INST_0_ST_IIS2MDC_DRDY_GPIOS_PIN 0
|
||||
#define DT_ST_IIS2MDC_BUS_SPI 1
|
||||
#endif
|
||||
|
||||
#ifndef DT_INST_0_ST_IIS3DHHC_LABEL
|
||||
#define DT_INST_0_ST_IIS3DHHC_LABEL ""
|
||||
#define DT_INST_0_ST_IIS3DHHC_BASE_ADDRESS 0
|
||||
|
|
|
@ -9,3 +9,4 @@ CONFIG_IIS2DLPC=y
|
|||
CONFIG_LIS2DW12=y
|
||||
CONFIG_STTS751=y
|
||||
CONFIG_ISM330DHCX=y
|
||||
CONFIG_IIS2MDC=y
|
||||
|
|
|
@ -13,3 +13,5 @@ CONFIG_STTS751=y
|
|||
CONFIG_STTS751_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_ISM330DHCX=y
|
||||
CONFIG_ISM330DHCX_TRIGGER_OWN_THREAD=y
|
||||
CONFIG_IIS2MDC=y
|
||||
CONFIG_IIS2MDC_TRIGGER_OWN_THREAD=y
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue