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