106 lines
2.4 KiB
C
106 lines
2.4 KiB
C
|
/* LLTC LTC2451 ADC
|
||
|
*
|
||
|
* Copyright (c) 2023 Brill Power Ltd.
|
||
|
*
|
||
|
* SPDX-License-Identifier: Apache-2.0
|
||
|
*/
|
||
|
|
||
|
#include <zephyr/device.h>
|
||
|
#include <zephyr/drivers/adc.h>
|
||
|
#include <zephyr/drivers/i2c.h>
|
||
|
#include <zephyr/logging/log.h>
|
||
|
#include <zephyr/sys/byteorder.h>
|
||
|
|
||
|
LOG_MODULE_REGISTER(ltc2451, CONFIG_ADC_LOG_LEVEL);
|
||
|
|
||
|
#define DT_DRV_COMPAT lltc_ltc2451
|
||
|
|
||
|
struct ltc2451_config {
|
||
|
struct i2c_dt_spec i2c;
|
||
|
uint8_t conversion_speed;
|
||
|
};
|
||
|
|
||
|
static int ltc2451_channel_setup(const struct device *dev,
|
||
|
const struct adc_channel_cfg *channel_cfg)
|
||
|
{
|
||
|
ARG_UNUSED(dev);
|
||
|
|
||
|
if (channel_cfg->channel_id != 0) {
|
||
|
LOG_ERR("Invalid channel id '%d'", channel_cfg->channel_id);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int ltc2451_set_conversion_speed(const struct device *dev, uint8_t conversion_speed)
|
||
|
{
|
||
|
const struct ltc2451_config *config = dev->config;
|
||
|
uint8_t wr_buf[1];
|
||
|
int err;
|
||
|
|
||
|
if (conversion_speed == 60) {
|
||
|
wr_buf[0] = 0;
|
||
|
} else if (conversion_speed == 30) {
|
||
|
wr_buf[0] = 1;
|
||
|
} else {
|
||
|
LOG_ERR("Invalid conversion speed selected");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
err = i2c_write_dt(&config->i2c, wr_buf, sizeof(wr_buf));
|
||
|
|
||
|
if (err != 0) {
|
||
|
LOG_ERR("LTC write failed (err %d)", err);
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
static int ltc2451_read_latest_conversion(const struct device *dev,
|
||
|
const struct adc_sequence *sequence)
|
||
|
{
|
||
|
const struct ltc2451_config *config = dev->config;
|
||
|
uint8_t rd_buf[2];
|
||
|
uint16_t *value_buf;
|
||
|
int err = i2c_read_dt(&config->i2c, rd_buf, sizeof(rd_buf));
|
||
|
|
||
|
if (err == 0) {
|
||
|
value_buf = (uint16_t *)sequence->buffer;
|
||
|
value_buf[0] = sys_get_be16(rd_buf);
|
||
|
} else {
|
||
|
LOG_ERR("LTC read failed (err %d)", err);
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
static int ltc2451_init(const struct device *dev)
|
||
|
{
|
||
|
const struct ltc2451_config *config = dev->config;
|
||
|
|
||
|
if (!device_is_ready(config->i2c.bus)) {
|
||
|
LOG_ERR("I2C device not ready");
|
||
|
return -ENODEV;
|
||
|
}
|
||
|
|
||
|
return ltc2451_set_conversion_speed(dev, config->conversion_speed);
|
||
|
}
|
||
|
|
||
|
static const struct adc_driver_api ltc2451_api = {
|
||
|
.channel_setup = ltc2451_channel_setup,
|
||
|
.read = ltc2451_read_latest_conversion,
|
||
|
};
|
||
|
|
||
|
#define LTC2451_DEFINE(index) \
|
||
|
static const struct ltc2451_config ltc2451_cfg_##index = { \
|
||
|
.i2c = I2C_DT_SPEC_INST_GET(index), \
|
||
|
.conversion_speed = DT_INST_PROP(index, conversion_speed), \
|
||
|
}; \
|
||
|
\
|
||
|
DEVICE_DT_INST_DEFINE(index, <c2451_init, NULL, NULL, \
|
||
|
<c2451_cfg_##index, POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \
|
||
|
<c2451_api);
|
||
|
|
||
|
DT_INST_FOREACH_STATUS_OKAY(LTC2451_DEFINE)
|