sensor: lps22hh: extend to support being on I3C bus
This extends the lps22hh driver to support being on I3C bus. Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
6034714909
commit
34ccd88c12
4 changed files with 164 additions and 24 deletions
|
@ -8,6 +8,7 @@ menuconfig LPS22HH
|
|||
default y
|
||||
depends on DT_HAS_ST_LPS22HH_ENABLED
|
||||
select I2C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22HH),i2c)
|
||||
select I3C if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22HH),i3c)
|
||||
select SPI if $(dt_compat_on_bus,$(DT_COMPAT_ST_LPS22HH),spi)
|
||||
select HAS_STMEMSC
|
||||
select USE_STDC_LPS22HH
|
||||
|
|
|
@ -155,10 +155,25 @@ static const struct sensor_driver_api lps22hh_driver_api = {
|
|||
static int lps22hh_init_chip(const struct device *dev)
|
||||
{
|
||||
const struct lps22hh_config * const cfg = dev->config;
|
||||
struct lps22hh_data *data = dev->data;
|
||||
stmdev_ctx_t *ctx = (stmdev_ctx_t *)&cfg->ctx;
|
||||
uint8_t chip_id;
|
||||
int ret;
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
if (cfg->i3c.bus != NULL) {
|
||||
/*
|
||||
* Need to grab the pointer to the I3C device descriptor
|
||||
* before we can talk to the sensor.
|
||||
*/
|
||||
data->i3c_dev = i3c_device_find(cfg->i3c.bus, &cfg->i3c.dev_id);
|
||||
if (data->i3c_dev == NULL) {
|
||||
LOG_ERR("Cannot find I3C device descriptor");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (lps22hh_device_id_get(ctx, &chip_id) < 0) {
|
||||
LOG_ERR("%s: Not able to read dev id", dev->name);
|
||||
return -EIO;
|
||||
|
@ -171,6 +186,30 @@ static int lps22hh_init_chip(const struct device *dev)
|
|||
|
||||
LOG_DBG("%s: chip id 0x%x", dev->name, chip_id);
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
if (cfg->i3c.bus != NULL) {
|
||||
/*
|
||||
* Enabling I3C and disabling I2C are required
|
||||
* for I3C IBI to work, or else the sensor will not
|
||||
* send any IBIs.
|
||||
*/
|
||||
|
||||
ret = lps22hh_i3c_interface_set(ctx, LPS22HH_I3C_ENABLE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Cannot enable I3C interface");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lps22hh_i2c_interface_set(ctx, LPS22HH_I2C_DISABLE);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Cannot disable I2C interface");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ARG_UNUSED(data);
|
||||
#endif
|
||||
|
||||
/* set sensor default odr */
|
||||
LOG_DBG("%s: odr: %d", dev->name, cfg->odr);
|
||||
ret = lps22hh_set_odr_raw(dev, cfg->odr);
|
||||
|
@ -266,6 +305,33 @@ static int lps22hh_init(const struct device *dev)
|
|||
(LPS22HH_CFG_IRQ(inst)), ()) \
|
||||
}
|
||||
|
||||
/*
|
||||
* Instantiation macros used when a device is on an I#C bus.
|
||||
*/
|
||||
|
||||
#define LPS22HH_CONFIG_I3C(inst) \
|
||||
{ \
|
||||
.ctx = { \
|
||||
.read_reg = \
|
||||
(stmdev_read_ptr) stmemsc_i3c_read, \
|
||||
.write_reg = \
|
||||
(stmdev_write_ptr) stmemsc_i3c_write, \
|
||||
.handle = \
|
||||
(void *)&lps22hh_config_##inst.stmemsc_cfg, \
|
||||
}, \
|
||||
.stmemsc_cfg = { \
|
||||
.i3c = &lps22hh_data_##inst.i3c_dev, \
|
||||
}, \
|
||||
.odr = DT_INST_PROP(inst, odr), \
|
||||
.i3c.bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \
|
||||
.i3c.dev_id = I3C_DEVICE_ID_DT_INST(inst), \
|
||||
}
|
||||
|
||||
#define LPS22HH_CONFIG_I3C_OR_I2C(inst) \
|
||||
COND_CODE_0(DT_INST_PROP_BY_IDX(inst, reg, 1), \
|
||||
(LPS22HH_CONFIG_I2C(inst)), \
|
||||
(LPS22HH_CONFIG_I3C(inst)))
|
||||
|
||||
/*
|
||||
* Main instantiation macro. Use of COND_CODE_1() selects the right
|
||||
* bus-specific macro at preprocessor time.
|
||||
|
@ -276,7 +342,9 @@ static int lps22hh_init(const struct device *dev)
|
|||
static const struct lps22hh_config lps22hh_config_##inst = \
|
||||
COND_CODE_1(DT_INST_ON_BUS(inst, spi), \
|
||||
(LPS22HH_CONFIG_SPI(inst)), \
|
||||
(LPS22HH_CONFIG_I2C(inst))); \
|
||||
(COND_CODE_1(DT_INST_ON_BUS(inst, i3c), \
|
||||
(LPS22HH_CONFIG_I3C_OR_I2C(inst)), \
|
||||
(LPS22HH_CONFIG_I2C(inst))))); \
|
||||
DEVICE_DT_INST_DEFINE(inst, lps22hh_init, NULL, &lps22hh_data_##inst, \
|
||||
&lps22hh_config_##inst, POST_KERNEL, \
|
||||
CONFIG_SENSOR_INIT_PRIORITY, &lps22hh_driver_api);
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include <zephyr/drivers/i2c.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i2c) */
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
#include <zephyr/drivers/i3c.h>
|
||||
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c) */
|
||||
|
||||
struct lps22hh_config {
|
||||
stmdev_ctx_t ctx;
|
||||
union {
|
||||
|
@ -31,12 +35,22 @@ struct lps22hh_config {
|
|||
#endif
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(spi)
|
||||
const struct spi_dt_spec spi;
|
||||
#endif
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
struct i3c_device_desc **i3c;
|
||||
#endif
|
||||
} stmemsc_cfg;
|
||||
uint8_t odr;
|
||||
#ifdef CONFIG_LPS22HH_TRIGGER
|
||||
struct gpio_dt_spec gpio_int;
|
||||
#endif
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
struct {
|
||||
const struct device *bus;
|
||||
const struct i3c_device_id dev_id;
|
||||
} i3c;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct lps22hh_data {
|
||||
|
@ -53,12 +67,16 @@ struct lps22hh_data {
|
|||
#if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
|
||||
K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_LPS22HH_THREAD_STACK_SIZE);
|
||||
struct k_thread thread;
|
||||
struct k_sem gpio_sem;
|
||||
struct k_sem intr_sem;
|
||||
#elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD)
|
||||
struct k_work work;
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_LPS22HH_TRIGGER */
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
struct i3c_device_desc *i3c_dev;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LPS22HH_TRIGGER
|
||||
|
|
|
@ -80,6 +80,16 @@ static void lps22hh_handle_interrupt(const struct device *dev)
|
|||
lps22hh->handler_drdy(dev, &drdy_trigger);
|
||||
}
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
if (cfg->i3c.bus != NULL) {
|
||||
/*
|
||||
* I3C IBI does not rely on GPIO.
|
||||
* So no need to enable GPIO pin for interrupt trigger.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (ret < 0) {
|
||||
|
@ -87,6 +97,15 @@ static void lps22hh_handle_interrupt(const struct device *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void lps22hh_intr_callback(struct lps22hh_data *lps22hh)
|
||||
{
|
||||
#if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&lps22hh->intr_sem);
|
||||
#elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&lps22hh->work);
|
||||
#endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
|
||||
}
|
||||
|
||||
static void lps22hh_gpio_callback(const struct device *dev,
|
||||
struct gpio_callback *cb, uint32_t pins)
|
||||
{
|
||||
|
@ -102,18 +121,14 @@ static void lps22hh_gpio_callback(const struct device *dev,
|
|||
LOG_ERR("%s: Not able to configure pin_int", dev->name);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
|
||||
k_sem_give(&lps22hh->gpio_sem);
|
||||
#elif defined(CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD)
|
||||
k_work_submit(&lps22hh->work);
|
||||
#endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
|
||||
lps22hh_intr_callback(lps22hh);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LPS22HH_TRIGGER_OWN_THREAD
|
||||
static void lps22hh_thread(struct lps22hh_data *lps22hh)
|
||||
{
|
||||
while (1) {
|
||||
k_sem_take(&lps22hh->gpio_sem, K_FOREVER);
|
||||
k_sem_take(&lps22hh->intr_sem, K_FOREVER);
|
||||
lps22hh_handle_interrupt(lps22hh->dev);
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +144,21 @@ static void lps22hh_work_cb(struct k_work *work)
|
|||
}
|
||||
#endif /* CONFIG_LPS22HH_TRIGGER_GLOBAL_THREAD */
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
static int lps22hh_ibi_cb(struct i3c_device_desc *target,
|
||||
struct i3c_ibi_payload *payload)
|
||||
{
|
||||
const struct device *dev = target->dev;
|
||||
struct lps22hh_data *lps22hh = dev->data;
|
||||
|
||||
ARG_UNUSED(payload);
|
||||
|
||||
lps22hh_intr_callback(lps22hh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int lps22hh_init_interrupt(const struct device *dev)
|
||||
{
|
||||
struct lps22hh_data *lps22hh = dev->data;
|
||||
|
@ -137,7 +167,11 @@ int lps22hh_init_interrupt(const struct device *dev)
|
|||
int ret;
|
||||
|
||||
/* setup data ready gpio interrupt */
|
||||
if (!device_is_ready(cfg->gpio_int.port)) {
|
||||
if (!device_is_ready(cfg->gpio_int.port)
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
&& (cfg->i3c.bus == NULL)
|
||||
#endif
|
||||
) {
|
||||
if (cfg->gpio_int.port) {
|
||||
LOG_ERR("%s: device %s is not ready", dev->name,
|
||||
cfg->gpio_int.port->name);
|
||||
|
@ -151,7 +185,7 @@ int lps22hh_init_interrupt(const struct device *dev)
|
|||
lps22hh->dev = dev;
|
||||
|
||||
#if defined(CONFIG_LPS22HH_TRIGGER_OWN_THREAD)
|
||||
k_sem_init(&lps22hh->gpio_sem, 0, K_SEM_MAX_LIMIT);
|
||||
k_sem_init(&lps22hh->intr_sem, 0, K_SEM_MAX_LIMIT);
|
||||
|
||||
k_thread_create(&lps22hh->thread, lps22hh->thread_stack,
|
||||
CONFIG_LPS22HH_THREAD_STACK_SIZE,
|
||||
|
@ -162,23 +196,28 @@ int lps22hh_init_interrupt(const struct device *dev)
|
|||
lps22hh->work.handler = lps22hh_work_cb;
|
||||
#endif /* CONFIG_LPS22HH_TRIGGER_OWN_THREAD */
|
||||
|
||||
ret = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not configure gpio");
|
||||
return ret;
|
||||
}
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
if (cfg->i3c.bus == NULL)
|
||||
#endif
|
||||
{
|
||||
ret = gpio_pin_configure_dt(&cfg->gpio_int, GPIO_INPUT);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not configure gpio");
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_INF("%s: int on %s.%02u", dev->name, cfg->gpio_int.port->name,
|
||||
cfg->gpio_int.pin);
|
||||
LOG_INF("%s: int on %s.%02u", dev->name, cfg->gpio_int.port->name,
|
||||
cfg->gpio_int.pin);
|
||||
|
||||
gpio_init_callback(&lps22hh->gpio_cb,
|
||||
lps22hh_gpio_callback,
|
||||
BIT(cfg->gpio_int.pin));
|
||||
gpio_init_callback(&lps22hh->gpio_cb,
|
||||
lps22hh_gpio_callback,
|
||||
BIT(cfg->gpio_int.pin));
|
||||
|
||||
ret = gpio_add_callback(cfg->gpio_int.port, &lps22hh->gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not set gpio callback");
|
||||
return ret;
|
||||
ret = gpio_add_callback(cfg->gpio_int.port, &lps22hh->gpio_cb);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Could not set gpio callback");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* enable interrupt in pulse mode */
|
||||
|
@ -186,6 +225,20 @@ int lps22hh_init_interrupt(const struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(i3c)
|
||||
if (cfg->i3c.bus != NULL) {
|
||||
/* I3C IBI does not utilize GPIO interrupt. */
|
||||
lps22hh->i3c_dev->ibi_cb = lps22hh_ibi_cb;
|
||||
|
||||
if (i3c_ibi_enable(lps22hh->i3c_dev) != 0) {
|
||||
LOG_DBG("Could not enable I3C IBI");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return gpio_pin_interrupt_configure_dt(&cfg->gpio_int,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue