drivers/sensor: iis2iclx: Fix shub for multi-instance case

In case of multi-instance the driver tries to discover whether
there are devices attached to SDx/SCx sensorhub bus. If not it
just turns the shub_inited variable (inside data structure) to false
and skips doing any further sensorhub related action for that
particular IIS2ICLX device instance, regardless the fact that the
macro CONFIG_IIS2ICLC_SENSORHUB is enabled.

Moreover, the info found during the enumeration process for a
particular instance (number and types of attached devices) must be
saved inside the per-instance data structure, so that more than one
IIS2ICLX device can be used as a sensorhub without interfering with
the others.

Signed-off-by: Armando Visconti <armando.visconti@st.com>
This commit is contained in:
Armando Visconti 2021-05-10 17:36:30 +02:00 committed by Kumar Gala
commit b430b8d6a6
3 changed files with 42 additions and 42 deletions

View file

@ -230,13 +230,6 @@ static int iis2iclx_sample_fetch_temp(const struct device *dev)
#if defined(CONFIG_IIS2ICLX_SENSORHUB) #if defined(CONFIG_IIS2ICLX_SENSORHUB)
static int iis2iclx_sample_fetch_shub(const struct device *dev) static int iis2iclx_sample_fetch_shub(const struct device *dev)
{ {
struct iis2iclx_data *data = dev->data;
if (!data->shub_inited) {
LOG_WRN("attr_set() shub not inited.");
return 0;
}
if (iis2iclx_shub_fetch_external_devs(dev) < 0) { if (iis2iclx_shub_fetch_external_devs(dev) < 0) {
LOG_ERR("failed to read ext shub devices"); LOG_ERR("failed to read ext shub devices");
return -EIO; return -EIO;
@ -249,13 +242,13 @@ static int iis2iclx_sample_fetch_shub(const struct device *dev)
static int iis2iclx_sample_fetch(const struct device *dev, static int iis2iclx_sample_fetch(const struct device *dev,
enum sensor_channel chan) enum sensor_channel chan)
{ {
#if defined(CONFIG_IIS2ICLX_SENSORHUB)
struct iis2iclx_data *data = dev->data;
#endif /* CONFIG_IIS2ICLX_SENSORHUB */
switch (chan) { switch (chan) {
case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_ACCEL_XYZ:
iis2iclx_sample_fetch_accel(dev); iis2iclx_sample_fetch_accel(dev);
#if defined(CONFIG_IIS2ICLX_SENSORHUB)
iis2iclx_sample_fetch_shub(dev);
#endif
break; break;
#if defined(CONFIG_IIS2ICLX_ENABLE_TEMP) #if defined(CONFIG_IIS2ICLX_ENABLE_TEMP)
case SENSOR_CHAN_DIE_TEMP: case SENSOR_CHAN_DIE_TEMP:
@ -268,7 +261,9 @@ static int iis2iclx_sample_fetch(const struct device *dev,
iis2iclx_sample_fetch_temp(dev); iis2iclx_sample_fetch_temp(dev);
#endif #endif
#if defined(CONFIG_IIS2ICLX_SENSORHUB) #if defined(CONFIG_IIS2ICLX_SENSORHUB)
iis2iclx_sample_fetch_shub(dev); if (data->shub_inited) {
iis2iclx_sample_fetch_shub(dev);
}
#endif #endif
break; break;
default: default:
@ -353,7 +348,7 @@ static inline int iis2iclx_magn_get_channel(enum sensor_channel chan,
int16_t sample[3]; int16_t sample[3];
int idx; int idx;
idx = iis2iclx_shub_get_idx(SENSOR_CHAN_MAGN_XYZ); idx = iis2iclx_shub_get_idx(data->dev, SENSOR_CHAN_MAGN_XYZ);
if (idx < 0) { if (idx < 0) {
LOG_ERR("external magn not supported"); LOG_ERR("external magn not supported");
return -ENOTSUP; return -ENOTSUP;
@ -397,7 +392,7 @@ static inline void iis2iclx_hum_convert(struct sensor_value *val,
struct hts221_data *ht = &data->hts221; struct hts221_data *ht = &data->hts221;
int idx; int idx;
idx = iis2iclx_shub_get_idx(SENSOR_CHAN_HUMIDITY); idx = iis2iclx_shub_get_idx(data->dev, SENSOR_CHAN_HUMIDITY);
if (idx < 0) { if (idx < 0) {
LOG_DBG("external press/temp not supported"); LOG_DBG("external press/temp not supported");
return; return;
@ -421,7 +416,7 @@ static inline void iis2iclx_press_convert(struct sensor_value *val,
int32_t raw_val; int32_t raw_val;
int idx; int idx;
idx = iis2iclx_shub_get_idx(SENSOR_CHAN_PRESS); idx = iis2iclx_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
if (idx < 0) { if (idx < 0) {
LOG_DBG("external press/temp not supported"); LOG_DBG("external press/temp not supported");
return; return;
@ -444,7 +439,7 @@ static inline void iis2iclx_temp_convert(struct sensor_value *val,
int16_t raw_val; int16_t raw_val;
int idx; int idx;
idx = iis2iclx_shub_get_idx(SENSOR_CHAN_PRESS); idx = iis2iclx_shub_get_idx(data->dev, SENSOR_CHAN_PRESS);
if (idx < 0) { if (idx < 0) {
LOG_DBG("external press/temp not supported"); LOG_DBG("external press/temp not supported");
return; return;
@ -483,7 +478,7 @@ static int iis2iclx_channel_get(const struct device *dev,
case SENSOR_CHAN_MAGN_Z: case SENSOR_CHAN_MAGN_Z:
case SENSOR_CHAN_MAGN_XYZ: case SENSOR_CHAN_MAGN_XYZ:
if (!data->shub_inited) { if (!data->shub_inited) {
LOG_ERR("shub not inited."); LOG_ERR("attr_set() shub not inited.");
return -ENOTSUP; return -ENOTSUP;
} }
@ -492,7 +487,7 @@ static int iis2iclx_channel_get(const struct device *dev,
case SENSOR_CHAN_HUMIDITY: case SENSOR_CHAN_HUMIDITY:
if (!data->shub_inited) { if (!data->shub_inited) {
LOG_ERR("shub not inited."); LOG_ERR("attr_set() shub not inited.");
return -ENOTSUP; return -ENOTSUP;
} }
@ -501,7 +496,7 @@ static int iis2iclx_channel_get(const struct device *dev,
case SENSOR_CHAN_PRESS: case SENSOR_CHAN_PRESS:
if (!data->shub_inited) { if (!data->shub_inited) {
LOG_ERR("shub not inited."); LOG_ERR("attr_set() shub not inited.");
return -ENOTSUP; return -ENOTSUP;
} }
@ -592,10 +587,10 @@ static int iis2iclx_init_chip(const struct device *dev)
static int iis2iclx_init(const struct device *dev) static int iis2iclx_init(const struct device *dev)
{ {
#if defined(CONFIG_IIS2ICLX_SENSORHUB)
struct iis2iclx_data *data = dev->data; struct iis2iclx_data *data = dev->data;
#endif /* CONFIG_IIS2ICLX_SENSORHUB */
LOG_INF("Initialize device %s", dev->name);
data->dev = dev;
if (iis2iclx_init_chip(dev) < 0) { if (iis2iclx_init_chip(dev) < 0) {
LOG_ERR("failed to initialize chip"); LOG_ERR("failed to initialize chip");
return -EIO; return -EIO;
@ -609,11 +604,11 @@ static int iis2iclx_init(const struct device *dev)
#endif #endif
#ifdef CONFIG_IIS2ICLX_SENSORHUB #ifdef CONFIG_IIS2ICLX_SENSORHUB
data->shub_inited = true;
if (iis2iclx_shub_init(dev) < 0) { if (iis2iclx_shub_init(dev) < 0) {
LOG_INF("failed to initialize external chips"); LOG_INF("shub: no external chips found");
data->shub_inited = false; data->shub_inited = false;
} }
data->shub_inited = true;
#endif #endif
return 0; return 0;

View file

@ -75,6 +75,8 @@ struct iis2iclx_data {
} hts221; } hts221;
bool shub_inited; bool shub_inited;
uint8_t num_ext_dev;
uint8_t shub_ext[IIS2ICLX_SHUB_MAX_NUM_SLVS];
#endif /* CONFIG_IIS2ICLX_SENSORHUB */ #endif /* CONFIG_IIS2ICLX_SENSORHUB */
uint16_t accel_freq; uint16_t accel_freq;
@ -98,7 +100,7 @@ struct iis2iclx_data {
#if defined(CONFIG_IIS2ICLX_SENSORHUB) #if defined(CONFIG_IIS2ICLX_SENSORHUB)
int iis2iclx_shub_init(const struct device *dev); int iis2iclx_shub_init(const struct device *dev);
int iis2iclx_shub_fetch_external_devs(const struct device *dev); int iis2iclx_shub_fetch_external_devs(const struct device *dev);
int iis2iclx_shub_get_idx(enum sensor_channel type); int iis2iclx_shub_get_idx(const struct device *dev, enum sensor_channel type);
int iis2iclx_shub_config(const struct device *dev, enum sensor_channel chan, int iis2iclx_shub_config(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, enum sensor_attribute attr,
const struct sensor_value *val); const struct sensor_value *val);

View file

@ -46,9 +46,6 @@ LOG_MODULE_DECLARE(IIS2ICLX, CONFIG_SENSOR_LOG_LEVEL);
#define IIS2ICLX_SHUB_SLVX_WRITE 0x0 #define IIS2ICLX_SHUB_SLVX_WRITE 0x0
#define IIS2ICLX_SHUB_SLVX_READ 0x1 #define IIS2ICLX_SHUB_SLVX_READ 0x1
static uint8_t num_ext_dev;
static uint8_t shub_ext[IIS2ICLX_SHUB_MAX_NUM_SLVS];
static int iis2iclx_shub_write_slave_reg(const struct device *dev, static int iis2iclx_shub_write_slave_reg(const struct device *dev,
uint8_t slv_addr, uint8_t slv_reg, uint8_t slv_addr, uint8_t slv_reg,
uint8_t *value, uint16_t len); uint8_t *value, uint16_t len);
@ -634,13 +631,14 @@ static int iis2iclx_shub_write_slave_reg(const struct device *dev,
*/ */
static int iis2iclx_shub_set_data_channel(const struct device *dev) static int iis2iclx_shub_set_data_channel(const struct device *dev)
{ {
struct iis2iclx_data *data = dev->data;
const struct iis2iclx_config *cfg = dev->config; const struct iis2iclx_config *cfg = dev->config;
uint8_t n, i, slv_cfg[6]; uint8_t n, i, slv_cfg[6];
struct iis2iclx_shub_slist *sp; struct iis2iclx_shub_slist *sp;
/* Set data channel for slave devices */ /* Set data channel for slave devices */
for (n = 0; n < num_ext_dev; n++) { for (n = 0; n < data->num_ext_dev; n++) {
sp = &iis2iclx_shub_slist[shub_ext[n]]; sp = &iis2iclx_shub_slist[data->shub_ext[n]];
i = n * 3; i = n * 3;
slv_cfg[i] = (sp->ext_i2c_addr << 1) | IIS2ICLX_SHUB_SLVX_READ; slv_cfg[i] = (sp->ext_i2c_addr << 1) | IIS2ICLX_SHUB_SLVX_READ;
@ -678,13 +676,14 @@ static int iis2iclx_shub_set_data_channel(const struct device *dev)
return 0; return 0;
} }
int iis2iclx_shub_get_idx(enum sensor_channel type) int iis2iclx_shub_get_idx(const struct device *dev, enum sensor_channel type)
{ {
uint8_t n; uint8_t n;
struct iis2iclx_shub_slist *sp; struct iis2iclx_shub_slist *sp;
struct iis2iclx_data *data = dev->data;
for (n = 0; n < num_ext_dev; n++) { for (n = 0; n < data->num_ext_dev; n++) {
sp = &iis2iclx_shub_slist[shub_ext[n]]; sp = &iis2iclx_shub_slist[data->shub_ext[n]];
if (sp->type == type) if (sp->type == type)
return n; return n;
@ -703,8 +702,8 @@ int iis2iclx_shub_fetch_external_devs(const struct device *dev)
/* read data from external slave */ /* read data from external slave */
iis2iclx_shub_embedded_en(cfg, true); iis2iclx_shub_embedded_en(cfg, true);
for (n = 0; n < num_ext_dev; n++) { for (n = 0; n < data->num_ext_dev; n++) {
sp = &iis2iclx_shub_slist[shub_ext[n]]; sp = &iis2iclx_shub_slist[data->shub_ext[n]];
if (iis2iclx_read_reg((stmdev_ctx_t *)&cfg->ctx, sp->sh_out_reg, if (iis2iclx_read_reg((stmdev_ctx_t *)&cfg->ctx, sp->sh_out_reg,
data->ext_data[n], sp->out_data_len) < 0) { data->ext_data[n], sp->out_data_len) < 0) {
@ -723,17 +722,18 @@ int iis2iclx_shub_config(const struct device *dev, enum sensor_channel chan,
enum sensor_attribute attr, enum sensor_attribute attr,
const struct sensor_value *val) const struct sensor_value *val)
{ {
struct iis2iclx_data *data = dev->data;
struct iis2iclx_shub_slist *sp = NULL; struct iis2iclx_shub_slist *sp = NULL;
uint8_t n; uint8_t n;
for (n = 0; n < num_ext_dev; n++) { for (n = 0; n < data->num_ext_dev; n++) {
sp = &iis2iclx_shub_slist[shub_ext[n]]; sp = &iis2iclx_shub_slist[data->shub_ext[n]];
if (sp->type == chan) if (sp->type == chan)
break; break;
} }
if (n == num_ext_dev) { if (n == data->num_ext_dev) {
LOG_ERR("shub: chan not supported"); LOG_ERR("shub: chan not supported");
return -ENOTSUP; return -ENOTSUP;
} }
@ -751,9 +751,11 @@ int iis2iclx_shub_init(const struct device *dev)
uint8_t i, n = 0, regn; uint8_t i, n = 0, regn;
uint8_t chip_id; uint8_t chip_id;
struct iis2iclx_shub_slist *sp; struct iis2iclx_shub_slist *sp;
struct iis2iclx_data *data = dev->data;
LOG_INF("shub: start sensorhub for %s", dev->name);
for (n = 0; n < ARRAY_SIZE(iis2iclx_shub_slist); n++) { for (n = 0; n < ARRAY_SIZE(iis2iclx_shub_slist); n++) {
if (num_ext_dev >= IIS2ICLX_SHUB_MAX_NUM_SLVS) if (data->num_ext_dev >= IIS2ICLX_SHUB_MAX_NUM_SLVS)
break; break;
chip_id = 0; chip_id = 0;
@ -783,17 +785,18 @@ int iis2iclx_shub_init(const struct device *dev)
LOG_INF("shub: Ext Device Chip Id: 0x%02x", chip_id); LOG_INF("shub: Ext Device Chip Id: 0x%02x", chip_id);
sp->ext_i2c_addr = sp->i2c_addr[i]; sp->ext_i2c_addr = sp->i2c_addr[i];
shub_ext[num_ext_dev++] = n; data->shub_ext[data->num_ext_dev++] = n;
} }
if (num_ext_dev == 0) { LOG_DBG("shub: dev %s - num_ext_dev %d", dev->name, data->num_ext_dev);
if (data->num_ext_dev == 0) {
LOG_WRN("shub: no slave devices found"); LOG_WRN("shub: no slave devices found");
return -ENOTSUP; return -ENOTSUP;
} }
/* init external devices */ /* init external devices */
for (n = 0, regn = 0; n < num_ext_dev; n++) { for (n = 0, regn = 0; n < data->num_ext_dev; n++) {
sp = &iis2iclx_shub_slist[shub_ext[n]]; sp = &iis2iclx_shub_slist[data->shub_ext[n]];
sp->sh_out_reg = IIS2ICLX_SHUB_DATA_OUT + regn; sp->sh_out_reg = IIS2ICLX_SHUB_DATA_OUT + regn;
regn += sp->out_data_len; regn += sp->out_data_len;
sp->dev_init(dev, sp->ext_i2c_addr); sp->dev_init(dev, sp->ext_i2c_addr);