Skip to content

Commit

Permalink
driver/sensors: lis2dh: Fix I2C and SPI bus communication
Browse files Browse the repository at this point in the history
Add I2C and SPI bus communication routines in separate files,
and register one or the other as read/write callbacks based
on bus selection in DTS.

This commit is fixing issue #22348 as well, as the SPI part
is handling in the proper way the CS GPIO part.

Signed-off-by: Armando Visconti <[email protected]>
  • Loading branch information
avisconti authored and jhedberg committed Mar 10, 2020
1 parent 86087f2 commit 1ebb708
Show file tree
Hide file tree
Showing 6 changed files with 428 additions and 254 deletions.
2 changes: 2 additions & 0 deletions drivers/sensor/lis2dh/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@
zephyr_library()

zephyr_library_sources_ifdef(CONFIG_LIS2DH lis2dh.c)
zephyr_library_sources_ifdef(CONFIG_LIS2DH lis2dh_i2c.c)
zephyr_library_sources_ifdef(CONFIG_LIS2DH lis2dh_spi.c)
zephyr_library_sources_ifdef(CONFIG_LIS2DH_TRIGGER lis2dh_trigger.c)
149 changes: 67 additions & 82 deletions drivers/sensor/lis2dh/lis2dh.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,56 +34,6 @@ static const u32_t lis2dh_reg_val_to_scale[] = {
#endif
};

#if defined(DT_ST_LIS2DH_BUS_SPI)
int lis2dh_spi_access(struct lis2dh_data *ctx, u8_t cmd,
void *data, size_t length)
{
const struct spi_buf buf[2] = {
{
.buf = &cmd,
.len = 1
},
{
.buf = data,
.len = length
}
};
const struct spi_buf_set tx = {
.buffers = buf,
.count = 2
};

if (cmd & LIS2DH_SPI_READ_BIT) {
const struct spi_buf_set rx = {
.buffers = buf,
.count = 2
};

return spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx);
}

return spi_write(ctx->spi, &ctx->spi_cfg, &tx);
}
#endif

int lis2dh_reg_field_update(struct device *dev, u8_t reg_addr,
u8_t pos, u8_t mask, u8_t val)
{
int status;
u8_t old_val;

/* just to remove gcc warning */
old_val = 0U;

status = lis2dh_reg_read_byte(dev, reg_addr, &old_val);
if (status < 0) {
return status;
}

return lis2dh_reg_write_byte(dev, reg_addr,
(old_val & ~mask) | ((val << pos) & mask));
}

static void lis2dh_convert(s16_t raw_val, u32_t scale,
struct sensor_value *val)
{
Expand Down Expand Up @@ -146,9 +96,9 @@ static int lis2dh_sample_fetch(struct device *dev, enum sensor_channel chan)
* since status and all accel data register addresses are consecutive,
* a burst read can be used to read all the samples
*/
status = lis2dh_burst_read(dev, LIS2DH_REG_STATUS,
lis2dh->sample.raw,
sizeof(lis2dh->sample.raw));
status = lis2dh->hw_tf->read_data(dev, LIS2DH_REG_STATUS,
lis2dh->sample.raw,
sizeof(lis2dh->sample.raw));
if (status < 0) {
LOG_WRN("Could not read accel axis data");
return status;
Expand All @@ -161,13 +111,7 @@ static int lis2dh_sample_fetch(struct device *dev, enum sensor_channel chan)
*sample = sys_le16_to_cpu(*sample);
}

LOG_INF("status=0x%x x=%d y=%d z=%d", lis2dh->sample.status,
lis2dh->sample.xyz[0], lis2dh->sample.xyz[1],
lis2dh->sample.xyz[2]);

if (lis2dh->sample.status & LIS2DH_STATUS_OVR_MASK) {
return -EBADMSG;
} else if (lis2dh->sample.status & LIS2DH_STATUS_DRDY_MASK) {
if (lis2dh->sample.status & LIS2DH_STATUS_DRDY_MASK) {
return 0;
}

Expand Down Expand Up @@ -202,13 +146,14 @@ static int lis2dh_acc_odr_set(struct device *dev, u16_t freq)
int odr;
int status;
u8_t value;
struct lis2dh_data *data = dev->driver_data;

odr = lis2dh_freq_to_odr_val(freq);
if (odr < 0) {
return odr;
}

status = lis2dh_reg_read_byte(dev, LIS2DH_REG_CTRL1, &value);
status = data->hw_tf->read_reg(dev, LIS2DH_REG_CTRL1, &value);
if (status < 0) {
return status;
}
Expand All @@ -224,9 +169,9 @@ static int lis2dh_acc_odr_set(struct device *dev, u16_t freq)
odr--;
}

return lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1,
(value & ~LIS2DH_ODR_MASK) |
LIS2DH_ODR_RATE(odr));
return data->hw_tf->write_reg(dev, LIS2DH_REG_CTRL1,
(value & ~LIS2DH_ODR_MASK) |
LIS2DH_ODR_RATE(odr));
}
#endif

Expand Down Expand Up @@ -260,10 +205,9 @@ static int lis2dh_acc_range_set(struct device *dev, s32_t range)

lis2dh->scale = lis2dh_reg_val_to_scale[fs];

return lis2dh_reg_field_update(dev, LIS2DH_REG_CTRL4,
LIS2DH_FS_SHIFT,
LIS2DH_FS_MASK,
fs);
return lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL4,
LIS2DH_FS_MASK,
(fs << LIS2DH_FS_SHIFT));
}
#endif

Expand Down Expand Up @@ -323,18 +267,34 @@ static const struct sensor_driver_api lis2dh_driver_api = {
int lis2dh_init(struct device *dev)
{
struct lis2dh_data *lis2dh = dev->driver_data;
const struct lis2dh_config *cfg = dev->config->config_info;
int status;
u8_t id;
u8_t raw[6];

status = lis2dh_bus_configure(dev);
lis2dh->bus = device_get_binding(cfg->bus_name);
if (!lis2dh->bus) {
LOG_ERR("master not found: %s", cfg->bus_name);
return -EINVAL;
}

cfg->bus_init(dev);

status = lis2dh->hw_tf->read_reg(dev, LIS2DH_REG_WAI, &id);
if (status < 0) {
LOG_ERR("Failed to read chip id.");
return status;
}

if (id != LIS2DH_CHIP_ID) {
LOG_ERR("Invalid chip ID: %02x\n", id);
return -EINVAL;
}

if (IS_ENABLED(DT_INST_0_ST_LIS2DH_DISCONNECT_SDO_SA0_PULL_UP)) {
status = lis2dh_reg_field_update(dev, LIS2DH_REG_CTRL0,
LIS2DH_SDO_PU_DISC_SHIFT,
LIS2DH_SDO_PU_DISC_MASK, 1);
status = lis2dh->hw_tf->update_reg(dev, LIS2DH_REG_CTRL0,
LIS2DH_SDO_PU_DISC_MASK,
LIS2DH_SDO_PU_DISC_MASK);
if (status < 0) {
LOG_ERR("Failed to disconnect SDO/SA0 pull-up.");
return status;
Expand All @@ -349,17 +309,18 @@ int lis2dh_init(struct device *dev)
(void)memset(raw, 0, sizeof(raw));
raw[0] = LIS2DH_ACCEL_EN_BITS;

status = lis2dh_burst_write(dev, LIS2DH_REG_CTRL1, raw,
sizeof(raw));
status = lis2dh->hw_tf->write_data(dev, LIS2DH_REG_CTRL1, raw,
sizeof(raw));

if (status < 0) {
LOG_ERR("Failed to reset ctrl registers.");
return status;
}

/* set full scale range and store it for later conversion */
lis2dh->scale = lis2dh_reg_val_to_scale[LIS2DH_FS_IDX];
status = lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL4,
LIS2DH_FS_BITS | LIS2DH_HR_BIT);
status = lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL4,
LIS2DH_FS_BITS | LIS2DH_HR_BIT);
if (status < 0) {
LOG_ERR("Failed to set full scale ctrl register.");
return status;
Expand All @@ -378,13 +339,37 @@ int lis2dh_init(struct device *dev)
LIS2DH_ODR_IDX, (u8_t)LIS2DH_LP_EN_BIT, lis2dh->scale);

/* enable accel measurements and set power mode and data rate */
return lis2dh_reg_write_byte(dev, LIS2DH_REG_CTRL1,
LIS2DH_ACCEL_EN_BITS | LIS2DH_LP_EN_BIT |
LIS2DH_ODR_BITS);
return lis2dh->hw_tf->write_reg(dev, LIS2DH_REG_CTRL1,
LIS2DH_ACCEL_EN_BITS | LIS2DH_LP_EN_BIT |
LIS2DH_ODR_BITS);
}

static struct lis2dh_data lis2dh_driver;
static struct lis2dh_data lis2dh_data;

static const struct lis2dh_config lis2dh_config = {
.bus_name = DT_INST_0_ST_LIS2DH_BUS_NAME,
#if defined(DT_ST_LIS2DH_BUS_SPI)
.bus_init = lis2dh_spi_init,
.spi_conf.frequency = DT_INST_0_ST_LIS2DH_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_LIS2DH_BASE_ADDRESS,
#if defined(DT_INST_0_ST_LIS2DH_CS_GPIOS_CONTROLLER)
.gpio_cs_port = DT_INST_0_ST_LIS2DH_CS_GPIOS_CONTROLLER,
.cs_gpio = DT_INST_0_ST_LIS2DH_CS_GPIOS_PIN,
.spi_conf.cs = &lis2dh_data.cs_ctrl,
#else
.spi_conf.cs = NULL,
#endif
#elif defined(DT_ST_LIS2DH_BUS_I2C)
.bus_init = lis2dh_i2c_init,
.i2c_slv_addr = DT_INST_0_ST_LIS2DH_BASE_ADDRESS,
#else
#error "BUS MACRO NOT DEFINED IN DTS"
#endif
};

DEVICE_AND_API_INIT(lis2dh, DT_INST_0_ST_LIS2DH_LABEL, lis2dh_init, &lis2dh_driver,
NULL, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
DEVICE_AND_API_INIT(lis2dh, DT_INST_0_ST_LIS2DH_LABEL, lis2dh_init, &lis2dh_data,
&lis2dh_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
&lis2dh_driver_api);
Loading

0 comments on commit 1ebb708

Please sign in to comment.