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