diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index fbab21039c8..ba346d851df 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -74,6 +74,7 @@ add_subdirectory_ifdef(CONFIG_MAX31865 max31865) add_subdirectory_ifdef(CONFIG_MAX31875 max31875) add_subdirectory_ifdef(CONFIG_MAX44009 max44009) add_subdirectory_ifdef(CONFIG_MAX6675 max6675) +add_subdirectory_ifdef(CONFIG_MCP970X mcp970x) add_subdirectory_ifdef(CONFIG_MCP9808 mcp9808) add_subdirectory_ifdef(CONFIG_MHZ19B mhz19b) add_subdirectory_ifdef(CONFIG_MPR mpr) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 85612088455..2e186c8bf5c 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -191,6 +191,8 @@ source "drivers/sensor/max6675/Kconfig" source "drivers/sensor/mchp_tach_xec/Kconfig" +source "drivers/sensor/mcp970x/Kconfig" + source "drivers/sensor/mcp9808/Kconfig" source "drivers/sensor/mhz19b/Kconfig" diff --git a/drivers/sensor/mcp970x/CMakeLists.txt b/drivers/sensor/mcp970x/CMakeLists.txt new file mode 100644 index 00000000000..54ad90fcb84 --- /dev/null +++ b/drivers/sensor/mcp970x/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(mcp970x.c) diff --git a/drivers/sensor/mcp970x/Kconfig b/drivers/sensor/mcp970x/Kconfig new file mode 100644 index 00000000000..3a5f0a0531b --- /dev/null +++ b/drivers/sensor/mcp970x/Kconfig @@ -0,0 +1,13 @@ +# Microchip MCP970X ADC driver +# +# Copyright (c) 2023 FTP Technologies +# +# SPDX-License-Identifier: Apache-2.0 + +config MCP970X + bool "MCP9700/9700A and MCP9701/9701A sensor" + default y + depends on DT_HAS_MICROCHIP_MCP970X_ENABLED + select ADC + help + Enables Low-Power Linear Active Thermistor IC driver. diff --git a/drivers/sensor/mcp970x/mcp970x.c b/drivers/sensor/mcp970x/mcp970x.c new file mode 100644 index 00000000000..143dadc6671 --- /dev/null +++ b/drivers/sensor/mcp970x/mcp970x.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2023 FTP Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microchip_mcp970x + +#include +#include + +#include +LOG_MODULE_REGISTER(mcp970x, CONFIG_SENSOR_LOG_LEVEL); + +enum ic_family { + FAMILY_MCP9700_9700A, + FAMILY_MCP9701_9701A +}; + +/* Milli degrees C per degree C */ +#define MC_PER_C 1000 + +#define MV_AT_0C_MCP9700_9700A 500 +#define MV_AT_0C_MCP9701_9701A 400 + +#define T_COEFF_MCP9700_9700A 10 +#define T_COEFF_MCP9701_9701A 19.5 + +struct mcp970x_config { + struct adc_dt_spec adc; + enum ic_family family; +}; + +struct mcp970x_data { + struct adc_sequence sequence; + int16_t raw; +}; + +static int fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct mcp970x_config *config = dev->config; + struct mcp970x_data *data = dev->data; + int ret; + + if ((chan != SENSOR_CHAN_AMBIENT_TEMP) && (chan != SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + ret = adc_read(config->adc.dev, &data->sequence); + if (ret != 0) { + LOG_ERR("adc_read: %d", ret); + } + + return ret; +} + +static int get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + const struct mcp970x_config *config = dev->config; + struct mcp970x_data *data = dev->data; + int32_t raw_val = data->raw; + int32_t t; + int ret; + + __ASSERT_NO_MSG(val != NULL); + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + LOG_ERR("chan %d not supported", chan); + return -ENOTSUP; + } + + ret = adc_raw_to_millivolts_dt(&config->adc, &raw_val); + if (ret != 0) { + LOG_ERR("to_mv: %d", ret); + return ret; + } + + if (config->family == FAMILY_MCP9700_9700A) { + t = (MC_PER_C * (raw_val - MV_AT_0C_MCP9700_9700A)) / T_COEFF_MCP9700_9700A; + } else { + int32_t t_coeff = 10 * T_COEFF_MCP9701_9701A; /* float to int */ + + t = (MC_PER_C * 10 * (raw_val - MV_AT_0C_MCP9701_9701A)) / t_coeff; + } + + val->val1 = t / MC_PER_C; + val->val2 = t % (1000000 / MC_PER_C); + + LOG_DBG("%d of %d, %dmV, %dmC", data->raw, (1 << data->sequence.resolution) - 1, raw_val, + t); + + return 0; +} + +static const struct sensor_driver_api mcp970x_api = { + .sample_fetch = fetch, + .channel_get = get, +}; + +static int init(const struct device *dev) +{ + const struct mcp970x_config *config = dev->config; + struct mcp970x_data *data = dev->data; + int ret; + + if (!device_is_ready(config->adc.dev)) { + LOG_ERR("ADC is not ready"); + return -ENODEV; + } + + ret = adc_channel_setup_dt(&config->adc); + if (ret != 0) { + LOG_ERR("setup: %d", ret); + return ret; + } + + ret = adc_sequence_init_dt(&config->adc, &data->sequence); + if (ret != 0) { + LOG_ERR("sequence: %d", ret); + return ret; + } + + data->sequence.buffer = &data->raw; + data->sequence.buffer_size = sizeof(data->raw); + + return 0; +} + +#define MCP970X_INIT(inst) \ + static struct mcp970x_data mcp970x_##inst##_data = {0}; \ + \ + static const struct mcp970x_config mcp970x_##inst##_config = { \ + .adc = ADC_DT_SPEC_INST_GET(inst), \ + .family = DT_INST_ENUM_IDX(inst, family), \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, &init, NULL, &mcp970x_##inst##_data, \ + &mcp970x_##inst##_config, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &mcp970x_api); + +DT_INST_FOREACH_STATUS_OKAY(MCP970X_INIT) diff --git a/dts/bindings/sensor/microchip,mcp970x.yaml b/dts/bindings/sensor/microchip,mcp970x.yaml new file mode 100644 index 00000000000..22445f4666f --- /dev/null +++ b/dts/bindings/sensor/microchip,mcp970x.yaml @@ -0,0 +1,28 @@ +# +# Copyright (c) 2023 FTP Technologies +# + +description: | + Microchip MCP9700/9700A MCP9701/9701A + Low-Power Linear Active Thermistor IC + +compatible: "microchip,mcp970x" + +include: sensor-device.yaml + +properties: + io-channels: + required: true + description: | + Channels available with this divider configuration. + + family: + type: string + required: true + description: | + Family Temperature Coefficient + MCP9700/9700A - 10.0mV + MCP9701/9701A - 19.5mV + enum: + - "MCP9700/9700A" + - "MCP9701/9701A"