sensors: ist8310: New driver
Adds support for the Isentek IST8310 3-axis magnetic sensor Signed-off-by: Peter van der Perk <peter.vanderperk@nxp.com>
This commit is contained in:
parent
b2af5e87de
commit
86812b1551
|
@ -54,6 +54,7 @@ add_subdirectory_ifdef(CONFIG_IIS3DHHC iis3dhhc)
|
|||
add_subdirectory_ifdef(CONFIG_INA219 ina219)
|
||||
add_subdirectory_ifdef(CONFIG_INA23X ina23x)
|
||||
add_subdirectory_ifdef(CONFIG_INA3221 ina3221)
|
||||
add_subdirectory_ifdef(CONFIG_IST8310 ist8310)
|
||||
add_subdirectory_ifdef(CONFIG_ISL29035 isl29035)
|
||||
add_subdirectory_ifdef(CONFIG_ISM330DHCX ism330dhcx)
|
||||
add_subdirectory_ifdef(CONFIG_ITDS wsen_itds)
|
||||
|
|
|
@ -110,6 +110,7 @@ source "drivers/sensor/ina219/Kconfig"
|
|||
source "drivers/sensor/ina23x/Kconfig"
|
||||
source "drivers/sensor/ina3221/Kconfig"
|
||||
source "drivers/sensor/isl29035/Kconfig"
|
||||
source "drivers/sensor/ist8310/Kconfig"
|
||||
source "drivers/sensor/ism330dhcx/Kconfig"
|
||||
source "drivers/sensor/ite_tach_it8xxx2/Kconfig"
|
||||
source "drivers/sensor/ite_vcmp_it8xxx2/Kconfig"
|
||||
|
|
4
drivers/sensor/ist8310/CMakeLists.txt
Normal file
4
drivers/sensor/ist8310/CMakeLists.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
zephyr_library()
|
||||
zephyr_library_sources(ist8310.c ist8310_i2c.c)
|
13
drivers/sensor/ist8310/Kconfig
Normal file
13
drivers/sensor/ist8310/Kconfig
Normal file
|
@ -0,0 +1,13 @@
|
|||
# IST8310 Geomagnetic sensor configuration options
|
||||
|
||||
# Copyright (c) 2023 NXP Semiconductors
|
||||
# Copyright (c) 2023 Cognipilot Foundation
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config IST8310
|
||||
bool "IST8310 I2C Geomagnetic Chip"
|
||||
default y
|
||||
depends on DT_HAS_ISENTEK_IST8310_ENABLED
|
||||
select I2C
|
||||
help
|
||||
Enable driver for IST8310 I2C-based Geomagnetic sensor.
|
221
drivers/sensor/ist8310/ist8310.c
Normal file
221
drivers/sensor/ist8310/ist8310.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/* ist8310.c - Driver for Isentek IST8310 Geomagnetic Sensor */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2023 NXP Semiconductors
|
||||
* Copyright (c) 2023 Cognipilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include "ist8310.h"
|
||||
|
||||
LOG_MODULE_REGISTER(IST8310, CONFIG_SENSOR_LOG_LEVEL);
|
||||
|
||||
static inline int ist8310_bus_check(const struct device *dev)
|
||||
{
|
||||
const struct ist8310_config *cfg = dev->config;
|
||||
|
||||
return cfg->bus_io->check(&cfg->bus);
|
||||
}
|
||||
|
||||
static inline int ist8310_reg_read(const struct device *dev, uint8_t start, uint8_t *buf, int size)
|
||||
{
|
||||
const struct ist8310_config *cfg = dev->config;
|
||||
|
||||
return cfg->bus_io->read(&cfg->bus, start, buf, size);
|
||||
}
|
||||
|
||||
static inline int ist8310_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
|
||||
{
|
||||
const struct ist8310_config *cfg = dev->config;
|
||||
|
||||
return cfg->bus_io->write(&cfg->bus, reg, val);
|
||||
}
|
||||
|
||||
static int ist8310_sample_fetch(const struct device *dev, enum sensor_channel chan)
|
||||
{
|
||||
|
||||
struct ist8310_data *drv_data = dev->data;
|
||||
uint8_t buff[6];
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_STATUS_REGISTER1, (uint8_t *)buff, 1) < 0) {
|
||||
LOG_ERR("failed to read status register 1");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((buff[0] & STAT1_DRDY) == 0) {
|
||||
LOG_ERR("Data not ready");
|
||||
if (ist8310_reg_write(dev, IST8310_CONTROL_REGISTER1, CTRL1_MODE_SINGLE) < 0) {
|
||||
LOG_ERR("failed to set single");
|
||||
return -EIO;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_OUTPUT_VALUE_X_L, (uint8_t *)buff, 6) < 0) {
|
||||
LOG_ERR("failed to read mag values");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
drv_data->sample_x = (sys_le16_to_cpu(*(uint16_t *)&buff[0]));
|
||||
drv_data->sample_y = (sys_le16_to_cpu(*(uint16_t *)&buff[2]));
|
||||
drv_data->sample_z = (sys_le16_to_cpu(*(uint16_t *)&buff[4]));
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_CONTROL_REGISTER1, CTRL1_MODE_SINGLE) < 0) {
|
||||
LOG_ERR("failed to set single");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ist8310_channel_get(const struct device *dev, enum sensor_channel chan,
|
||||
struct sensor_value *val)
|
||||
{
|
||||
struct ist8310_data *drv_data = dev->data;
|
||||
|
||||
switch (chan) {
|
||||
case SENSOR_CHAN_MAGN_X:
|
||||
sensor_value_from_float(val, drv_data->sample_x * (1.0f / 1320));
|
||||
break;
|
||||
case SENSOR_CHAN_MAGN_Y:
|
||||
sensor_value_from_float(val, drv_data->sample_y * (1.0f / 1320));
|
||||
break;
|
||||
case SENSOR_CHAN_MAGN_Z:
|
||||
sensor_value_from_float(val, drv_data->sample_z * (1.0f / 1320));
|
||||
break;
|
||||
case SENSOR_CHAN_MAGN_XYZ:
|
||||
sensor_value_from_float(val, drv_data->sample_x * (1.0f / 1320));
|
||||
sensor_value_from_float(val + 1, drv_data->sample_y * (1.0f / 1320));
|
||||
sensor_value_from_float(val + 2, drv_data->sample_z * (1.0f / 1320));
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sensor_driver_api ist8310_api_funcs = {
|
||||
.sample_fetch = ist8310_sample_fetch,
|
||||
.channel_get = ist8310_channel_get,
|
||||
};
|
||||
|
||||
static int ist8310_init_chip(const struct device *dev)
|
||||
{
|
||||
uint8_t reg;
|
||||
|
||||
/* Read chip ID (can only be read in sleep mode)*/
|
||||
if (ist8310_reg_read(dev, IST8310_WHO_AM_I, ®, 1) < 0) {
|
||||
LOG_ERR("failed reading chip id");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_WHO_AM_I, ®, 1) < 0) {
|
||||
LOG_ERR("failed reading chip id");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_WHO_AM_I, ®, 1) < 0) {
|
||||
LOG_ERR("failed reading chip id");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (reg != IST8310_WHO_AM_I_VALUE) {
|
||||
LOG_ERR("invalid chip id 0x%x", reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_CONTROL_REGISTER2, ®, 1) < 0) {
|
||||
LOG_ERR("failed reading chip reg2");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
reg &= ~CTRL2_SRST;
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_CONTROL_REGISTER2, reg) < 0) {
|
||||
LOG_ERR("failed to set REG2 to %d", reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_sleep(K_MSEC(3));
|
||||
|
||||
if (ist8310_reg_read(dev, IST8310_CONTROL_REGISTER3, ®, 1) < 0) {
|
||||
LOG_ERR("failed reading chip reg3");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
reg |= X_16BIT | Y_16BIT | Z_16BIT;
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_CONTROL_REGISTER3, reg) < 0) {
|
||||
LOG_ERR("failed to set REG3 to %d", reg);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_AVG_REGISTER, XZ_16TIMES_CLEAR | Y_16TIMES_CLEAR) < 0) {
|
||||
LOG_ERR("failed to set AVG");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_AVG_REGISTER, XZ_16TIMES_SET | Y_16TIMES_SET) < 0) {
|
||||
LOG_ERR("failed to set AVG");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_PDCNTL_REGISTER, PULSE_NORMAL) < 0) {
|
||||
LOG_ERR("failed to set AVG");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
k_sleep(K_MSEC(3));
|
||||
|
||||
if (ist8310_reg_write(dev, IST8310_CONTROL_REGISTER1, CTRL1_MODE_SINGLE) < 0) {
|
||||
LOG_ERR("failed to set single");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ist8310_init(const struct device *dev)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
err = ist8310_bus_check(dev);
|
||||
if (err < 0) {
|
||||
LOG_DBG("bus check failed: %d", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
if (ist8310_init_chip(dev) < 0) {
|
||||
LOG_ERR("failed to initialize chip");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Initializes a struct ist8310_config for an instance on an I2C bus. */
|
||||
#define IST8310_CONFIG_I2C(inst) \
|
||||
.bus.i2c = I2C_DT_SPEC_INST_GET(inst), .bus_io = &ist8310_bus_io_i2c,
|
||||
|
||||
#define IST8310_BUS_CFG(inst) \
|
||||
COND_CODE_1(DT_INST_ON_BUS(inst, i2c), (IST8310_CONFIG_I2C(inst)), \
|
||||
(IST8310_CONFIG_SPI(inst)))
|
||||
|
||||
/*
|
||||
* Main instantiation macro, which selects the correct bus-specific
|
||||
* instantiation macros for the instance.
|
||||
*/
|
||||
#define IST8310_DEFINE(inst) \
|
||||
static struct ist8310_data ist8310_data_##inst; \
|
||||
static const struct ist8310_config ist8310_config_##inst = {IST8310_BUS_CFG(inst)}; \
|
||||
\
|
||||
SENSOR_DEVICE_DT_INST_DEFINE(inst, ist8310_init, NULL, &ist8310_data_##inst, \
|
||||
&ist8310_config_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &ist8310_api_funcs);
|
||||
|
||||
/* Create the struct device for every status "okay" node in the devicetree. */
|
||||
DT_INST_FOREACH_STATUS_OKAY(IST8310_DEFINE)
|
99
drivers/sensor/ist8310/ist8310.h
Normal file
99
drivers/sensor/ist8310/ist8310.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/* ist8310.h - header file for IST8310 Geomagnetic sensor driver */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2023 NXP Semiconductors
|
||||
* Copyright (c) 2023 Cognipilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_DRIVERS_SENSOR_IST8310_IST8310_H_
|
||||
#define ZEPHYR_DRIVERS_SENSOR_IST8310_IST8310_H_
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
#include <zephyr/drivers/i2c.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/sensor.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
#include <zephyr/drivers/gpio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define DT_DRV_COMPAT isentek_ist8310
|
||||
|
||||
#define IST8310_BUS_I2C DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c)
|
||||
|
||||
union ist8310_bus {
|
||||
struct i2c_dt_spec i2c;
|
||||
};
|
||||
|
||||
typedef int (*ist8310_bus_check_fn)(const union ist8310_bus *bus);
|
||||
typedef int (*ist8310_reg_read_fn)(const union ist8310_bus *bus,
|
||||
uint8_t start, uint8_t *buf, int size);
|
||||
typedef int (*ist8310_reg_write_fn)(const union ist8310_bus *bus,
|
||||
uint8_t reg, uint8_t val);
|
||||
|
||||
struct ist8310_bus_io {
|
||||
ist8310_bus_check_fn check;
|
||||
ist8310_reg_read_fn read;
|
||||
ist8310_reg_write_fn write;
|
||||
};
|
||||
|
||||
extern const struct ist8310_bus_io ist8310_bus_io_i2c;
|
||||
|
||||
#define IST8310_WHO_AM_I 0x00
|
||||
#define IST8310_WHO_AM_I_VALUE 0x10
|
||||
|
||||
#define IST8310_STATUS_REGISTER1 0x02
|
||||
#define STAT1_DRDY 0x01
|
||||
#define STAT1_DRO 0x02
|
||||
|
||||
#define IST8310_OUTPUT_VALUE_X_L 0x03
|
||||
#define IST8310_OUTPUT_VALUE_X_H 0x04
|
||||
#define IST8310_OUTPUT_VALUE_Y_L 0x05
|
||||
#define IST8310_OUTPUT_VALUE_Y_H 0x06
|
||||
#define IST8310_OUTPUT_VALUE_Z_L 0x07
|
||||
#define IST8310_OUTPUT_VALUE_Z_H 0x08
|
||||
|
||||
#define IST8310_CONTROL_REGISTER1 0x0A
|
||||
#define CTRL1_MODE_SINGLE 0x1
|
||||
|
||||
#define IST8310_CONTROL_REGISTER2 0x0B
|
||||
#define CTRL2_SRST 0x01
|
||||
|
||||
#define IST8310_OUTPUT_VALUE_T_L 0x1C
|
||||
#define IST8310_OUTPUT_VALUE_T_H 0x1D
|
||||
|
||||
#define IST8310_CONTROL_REGISTER3 0x0d
|
||||
#define Z_16BIT 0x40
|
||||
#define Y_16BIT 0x20
|
||||
#define X_16BIT 0x10
|
||||
|
||||
#define IST8310_AVG_REGISTER 0x41
|
||||
#define Y_16TIMES_SET 0x20
|
||||
#define Y_16TIMES_CLEAR 0x18
|
||||
#define XZ_16TIMES_SET 0x04
|
||||
#define XZ_16TIMES_CLEAR 0x03
|
||||
|
||||
#define IST8310_PDCNTL_REGISTER 0x42
|
||||
#define PULSE_NORMAL 0xC0
|
||||
|
||||
|
||||
struct ist8310_config {
|
||||
union ist8310_bus bus;
|
||||
const struct ist8310_bus_io *bus_io;
|
||||
};
|
||||
|
||||
struct ist8310_data {
|
||||
struct k_sem sem;
|
||||
int16_t sample_x, sample_y, sample_z;
|
||||
};
|
||||
|
||||
int ist8310_reg_update_byte(const struct device *dev, uint8_t reg,
|
||||
uint8_t mask, uint8_t value);
|
||||
|
||||
#endif /* __SENSOR_IST8310_H__ */
|
33
drivers/sensor/ist8310/ist8310_i2c.c
Normal file
33
drivers/sensor/ist8310/ist8310_i2c.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2023 NXP Semiconductors
|
||||
* Copyright (c) 2023 Cognipilot Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*
|
||||
* Bus-specific functionality for IST8310 accessed via I2C.
|
||||
*/
|
||||
|
||||
#include "ist8310.h"
|
||||
|
||||
static int ist8310_bus_check_i2c(const union ist8310_bus *bus)
|
||||
{
|
||||
return i2c_is_ready_dt(&bus->i2c) ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
static int ist8310_reg_read_i2c(const union ist8310_bus *bus, uint8_t start, uint8_t *buf, int size)
|
||||
{
|
||||
return i2c_burst_read_dt(&bus->i2c, start, buf, size);
|
||||
}
|
||||
|
||||
static int ist8310_reg_write_i2c(const union ist8310_bus *bus, uint8_t reg, uint8_t val)
|
||||
{
|
||||
return i2c_reg_write_byte_dt(&bus->i2c, reg, val);
|
||||
}
|
||||
|
||||
const struct ist8310_bus_io ist8310_bus_io_i2c = {
|
||||
.check = ist8310_bus_check_i2c,
|
||||
.read = ist8310_reg_read_i2c,
|
||||
.write = ist8310_reg_write_i2c,
|
||||
};
|
10
dts/bindings/sensor/istentek,ist8310.yaml
Normal file
10
dts/bindings/sensor/istentek,ist8310.yaml
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Copyright (c) 2019, Linaro Limited
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
description: |
|
||||
Istentek ist8310 Geomagnetic sensor. See more info at:
|
||||
https://isentek.com/products_view.php?PID=10&sn=13
|
||||
|
||||
compatible: "isentek,ist8310"
|
||||
|
||||
include: ["i2c-device.yaml", "sensor-device.yaml"]
|
|
@ -292,6 +292,7 @@ invensense InvenSense Inc.
|
|||
inversepath Inverse Path
|
||||
iom Iomega Corporation
|
||||
isee ISEE 2007 S.L.
|
||||
isentek Isentek Inc.
|
||||
isil Intersil
|
||||
issi Integrated Silicon Solutions Inc.
|
||||
ite ITE Tech. Inc.
|
||||
|
|
|
@ -738,3 +738,9 @@ test_i2c_bmi08x_gyro: bmi08x@6e {
|
|||
gyro-hz = "1000_116";
|
||||
gyro-fs = <1000>;
|
||||
};
|
||||
|
||||
test_i2c_ist8310@6f {
|
||||
compatible = "isentek,ist8310";
|
||||
reg = <0x6f>;
|
||||
status = "okay";
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue