/* * Copyright 2023 Daniel DeGrasse * * SPDX-License-Identifier: Apache-2.0 */ #define DT_DRV_COMPAT microchip_tcn75a #include LOG_MODULE_REGISTER(tcn75a, CONFIG_SENSOR_LOG_LEVEL); #include "tcn75a.h" int tcn75a_sample_fetch(const struct device *dev, enum sensor_channel chan) { const struct tcn75a_config *config = dev->config; struct tcn75a_data *data = dev->data; int ret; uint8_t temp_reg = TCN75A_TEMP_REG; uint8_t rx_buf[2]; uint8_t adc_conf[2] = {TCN75A_CONFIG_REG, 0x0}; /* This sensor only supports ambient temperature */ if ((chan != SENSOR_CHAN_ALL) && (chan != SENSOR_CHAN_AMBIENT_TEMP)) { return -ENOTSUP; } if (config->oneshot_mode) { /* Oneshot mode, requires one shot bit to be set in config register */ adc_conf[1] = TCN75A_CONFIG_ONEDOWN; ret = i2c_write_dt(&config->i2c_spec, adc_conf, 2); if (ret < 0) { return ret; } } /* Fetch a sample from the 2 byte ambient temperature register */ ret = i2c_write_read_dt(&config->i2c_spec, &temp_reg, sizeof(temp_reg), rx_buf, sizeof(rx_buf)); if (ret < 0) { return ret; } data->temp_sample = sys_get_be16(rx_buf); LOG_DBG("Raw sample: 0x%04x", data->temp_sample); return ret; } static int tcn75a_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct tcn75a_data *data = dev->data; uint32_t temp_lsb; if (chan != SENSOR_CHAN_AMBIENT_TEMP) { return -ENOTSUP; } /* Convert fixed point to sensor value */ val->val1 = data->temp_sample >> TCN75A_TEMP_MSB_POS; temp_lsb = (data->temp_sample & TCN75A_TEMP_LSB_MASK); val->val2 = TCN75A_FIXED_PT_TO_SENSOR(temp_lsb); return 0; } static DEVICE_API(sensor, tcn75a_api) = { .sample_fetch = &tcn75a_sample_fetch, .channel_get = &tcn75a_channel_get, #ifdef CONFIG_TCN75A_TRIGGER .attr_get = &tcn75a_attr_get, .attr_set = &tcn75a_attr_set, .trigger_set = &tcn75a_trigger_set, #endif }; static int tcn75a_init(const struct device *dev) { const struct tcn75a_config *config = dev->config; uint8_t adc_conf[2] = {TCN75A_CONFIG_REG, 0x0}; if (!i2c_is_ready_dt(&config->i2c_spec)) { LOG_ERR("I2C bus is not ready"); return -ENODEV; } /* Set user selected resolution */ adc_conf[1] |= TCN75A_CONFIG_RES(config->resolution); if (config->oneshot_mode) { if (adc_conf[1] != 0) { /* Oneshot mode only supports 9 bit resolution */ LOG_ERR("Oneshot mode requires 9 bit resolution"); return -ENODEV; } adc_conf[1] |= TCN75A_CONFIG_SHUTDOWN; } #ifdef CONFIG_TCN75A_TRIGGER /* If user supplies an ALERT gpio, assume they want trigger support. */ if (config->alert_gpios.port != NULL) { int ret; if (config->oneshot_mode) { LOG_ERR("Oneshot mode not supported with trigger"); return -ENODEV; } ret = tcn75a_trigger_init(dev); if (ret < 0) { return ret; } } #endif return i2c_write_dt(&config->i2c_spec, adc_conf, 2); } #ifdef CONFIG_TCN75A_TRIGGER #define TCN75A_TRIGGER(n) .alert_gpios = GPIO_DT_SPEC_INST_GET_OR(n, alert_gpios, {}), #else #define TCN75A_TRIGGER(n) #endif #define TCN75A_INIT(n) \ static struct tcn75a_data tcn75a_data_##n; \ static const struct tcn75a_config tcn75a_config_##n = { \ .i2c_spec = I2C_DT_SPEC_INST_GET(n), \ .resolution = DT_INST_ENUM_IDX(n, resolution), \ .oneshot_mode = DT_INST_PROP(n, oneshot_mode), \ TCN75A_TRIGGER(n) \ }; \ SENSOR_DEVICE_DT_INST_DEFINE(n, &tcn75a_init, NULL, &tcn75a_data_##n, &tcn75a_config_##n, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &tcn75a_api); DT_INST_FOREACH_STATUS_OKAY(TCN75A_INIT)