1 /*
2 * Copyright (c) 2021 Eug Krashtan
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <device.h>
8 #include <drivers/sensor.h>
9 #include <drivers/adc.h>
10 #include <logging/log.h>
11
12 LOG_MODULE_REGISTER(stm32_temp, CONFIG_SENSOR_LOG_LEVEL);
13
14 #define DT_DRV_COMPAT st_stm32_temp
15
16 struct stm32_temp_data {
17 const struct device *adc;
18 uint8_t channel;
19 struct adc_channel_cfg adc_cfg;
20 struct adc_sequence adc_seq;
21 struct k_mutex mutex;
22 int16_t sample_buffer;
23 int32_t mv; /* Sensor value in millivolts */
24 };
25
26 struct stm32_temp_config {
27 int avgslope;
28 int v25_mv;
29 int tsv_mv;
30 bool is_ntc;
31 };
32
stm32_temp_sample_fetch(const struct device * dev,enum sensor_channel chan)33 static int stm32_temp_sample_fetch(const struct device *dev,
34 enum sensor_channel chan)
35 {
36 const struct stm32_temp_config *cfg = dev->config;
37 struct stm32_temp_data *data = dev->data;
38 struct adc_sequence *sp = &data->adc_seq;
39 int rc;
40
41 if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
42 return -ENOTSUP;
43 }
44
45 k_mutex_lock(&data->mutex, K_FOREVER);
46
47 rc = adc_read(data->adc, sp);
48 sp->calibrate = false;
49 if (rc == 0) {
50 data->mv = data->sample_buffer * cfg->tsv_mv / 0x0FFF;
51 }
52
53 k_mutex_unlock(&data->mutex);
54
55 return 0;
56 }
57
stm32_temp_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)58 static int stm32_temp_channel_get(const struct device *dev,
59 enum sensor_channel chan,
60 struct sensor_value *val)
61 {
62 struct stm32_temp_data *data = dev->data;
63 const struct stm32_temp_config *cfg = dev->config;
64 float temp;
65
66 if (chan != SENSOR_CHAN_DIE_TEMP) {
67 return -ENOTSUP;
68 }
69
70 if (cfg->is_ntc) {
71 temp = (float)(cfg->v25_mv - data->mv);
72 } else {
73 temp = (float)(data->mv - cfg->v25_mv);
74 }
75 temp = (temp/cfg->avgslope)*10;
76 temp += 25;
77 sensor_value_from_double(val, temp);
78
79 return 0;
80 }
81
82 static const struct sensor_driver_api stm32_temp_driver_api = {
83 .sample_fetch = stm32_temp_sample_fetch,
84 .channel_get = stm32_temp_channel_get,
85 };
86
stm32_temp_init(const struct device * dev)87 static int stm32_temp_init(const struct device *dev)
88 {
89 struct stm32_temp_data *data = dev->data;
90 struct adc_channel_cfg *accp = &data->adc_cfg;
91 struct adc_sequence *asp = &data->adc_seq;
92 int rc;
93
94 k_mutex_init(&data->mutex);
95
96 if (!device_is_ready(data->adc)) {
97 LOG_ERR("Device %s is not ready", data->adc->name);
98 return -ENODEV;
99 }
100
101 *accp = (struct adc_channel_cfg){
102 .gain = ADC_GAIN_1,
103 .reference = ADC_REF_INTERNAL,
104 .acquisition_time = ADC_ACQ_TIME_MAX,
105 .channel_id = data->channel,
106 .differential = 0
107 };
108 rc = adc_channel_setup(data->adc, accp);
109 LOG_DBG("Setup AIN%u got %d", data->channel, rc);
110
111 *asp = (struct adc_sequence){
112 .channels = BIT(data->channel),
113 .buffer = &data->sample_buffer,
114 .buffer_size = sizeof(data->sample_buffer),
115 .resolution = 12,
116 .calibrate = true,
117 };
118
119 return 0;
120 }
121
122 #define STM32_TEMP_INST(idx) \
123 static struct stm32_temp_data inst_##idx##_data = { \
124 .adc = DEVICE_DT_GET(DT_IO_CHANNELS_CTLR( \
125 DT_INST(idx, st_stm32_temp))), \
126 .channel = DT_IO_CHANNELS_INPUT( \
127 DT_INST(idx, st_stm32_temp)) \
128 }; \
129 static const struct stm32_temp_config inst_##idx##_config = { \
130 .avgslope = DT_INST_PROP(idx, avgslope), \
131 .v25_mv = DT_INST_PROP(idx, v25), \
132 .tsv_mv = DT_INST_PROP(idx, ts_voltage_mv), \
133 .is_ntc = DT_INST_PROP(idx, ntc) \
134 }; \
135 DEVICE_DT_INST_DEFINE(idx, \
136 stm32_temp_init, \
137 NULL, \
138 &inst_##idx##_data, \
139 &inst_##idx##_config, \
140 POST_KERNEL, \
141 CONFIG_SENSOR_INIT_PRIORITY, \
142 &stm32_temp_driver_api);
143
144 DT_INST_FOREACH_STATUS_OKAY(STM32_TEMP_INST)
145