1 /*
2 * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT espressif_esp32_temp
8
9 #include <driver/temp_sensor.h>
10
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/devicetree.h>
14 #include <zephyr/drivers/sensor.h>
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_REGISTER(esp32_temp, CONFIG_SENSOR_LOG_LEVEL);
18
19 #if CONFIG_SOC_SERIES_ESP32
20 #error "Temperature sensor not supported on ESP32"
21 #endif /* CONFIG_SOC_SERIES_ESP32 */
22
23 struct esp32_temp_data {
24 struct k_mutex mutex;
25 temp_sensor_config_t temp_sensor;
26 float temp_out;
27 };
28
29 struct esp32_temp_config {
30 temp_sensor_dac_offset_t range;
31 };
32
esp32_temp_sample_fetch(const struct device * dev,enum sensor_channel chan)33 static int esp32_temp_sample_fetch(const struct device *dev, enum sensor_channel chan)
34 {
35 struct esp32_temp_data *data = dev->data;
36 int rc = 0;
37
38 k_mutex_lock(&data->mutex, K_FOREVER);
39
40 if (temp_sensor_read_celsius(&data->temp_out) != ESP_OK) {
41 LOG_ERR("Temperature read error!");
42 rc = -EFAULT;
43 goto unlock;
44 }
45
46 unlock:
47 k_mutex_unlock(&data->mutex);
48
49 return rc;
50 }
51
esp32_temp_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)52 static int esp32_temp_channel_get(const struct device *dev, enum sensor_channel chan,
53 struct sensor_value *val)
54 {
55 struct esp32_temp_data *data = dev->data;
56
57 if (chan != SENSOR_CHAN_DIE_TEMP) {
58 return -ENOTSUP;
59 }
60
61 return sensor_value_from_double(val, data->temp_out);
62 }
63
64 static DEVICE_API(sensor, esp32_temp_driver_api) = {
65 .sample_fetch = esp32_temp_sample_fetch,
66 .channel_get = esp32_temp_channel_get,
67 };
68
esp32_temp_init(const struct device * dev)69 static int esp32_temp_init(const struct device *dev)
70 {
71 struct esp32_temp_data *data = dev->data;
72 const struct esp32_temp_config *conf = dev->config;
73
74 k_mutex_init(&data->mutex);
75 temp_sensor_get_config(&data->temp_sensor);
76 data->temp_sensor.dac_offset = conf->range;
77 temp_sensor_set_config(data->temp_sensor);
78 temp_sensor_start();
79 LOG_DBG("Temperature sensor started. Offset %d, clk_div %d",
80 data->temp_sensor.dac_offset, data->temp_sensor.clk_div);
81
82 return 0;
83 }
84
85 #define ESP32_TEMP_DEFINE(inst) \
86 static struct esp32_temp_data esp32_temp_dev_data_##inst = { \
87 .temp_sensor = TSENS_CONFIG_DEFAULT(), \
88 }; \
89 \
90 static const struct esp32_temp_config esp32_temp_dev_config_##inst = { \
91 .range = (temp_sensor_dac_offset_t) DT_INST_PROP(inst, range), \
92 }; \
93 \
94 SENSOR_DEVICE_DT_INST_DEFINE(inst, esp32_temp_init, NULL, \
95 &esp32_temp_dev_data_##inst, &esp32_temp_dev_config_##inst, \
96 POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \
97 &esp32_temp_driver_api); \
98
99 DT_INST_FOREACH_STATUS_OKAY(ESP32_TEMP_DEFINE)
100