1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nordic_nrf_temp_nrfs
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/drivers/sensor.h>
11 #include <zephyr/logging/log.h>
12 #include <zephyr/sys/__assert.h>
13 
14 #include <nrfs_temp.h>
15 
16 LOG_MODULE_REGISTER(temp_nrfs, CONFIG_SENSOR_LOG_LEVEL);
17 
18 struct temp_nrfs_data {
19 	struct k_sem measure_sem;
20 	struct k_mutex mutex;
21 	int32_t raw_temp;
22 
23 #ifdef CONFIG_TEMP_NRFS_TRIGGER
24 	struct sensor_trigger trigger;
25 	sensor_trigger_handler_t handler;
26 	const struct device *dev;
27 	struct sensor_value sampling_freq;
28 	struct sensor_value up_threshold;
29 	struct sensor_value low_threshold;
30 #endif
31 #if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD)
32 	K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TEMP_NRFS_THREAD_STACK_SIZE);
33 	struct k_thread thread;
34 	struct k_sem event_sem;
35 #elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD)
36 	struct k_work work;
37 #endif
38 };
39 
40 #ifdef CONFIG_TEMP_NRFS_TRIGGER
41 
42 #define DEFAULT_SAMPLING_FREQ {  1, 0 }
43 #define DEFAULT_UP_THRESHOLD  { 25, 0 }
44 #define DEFAULT_LOW_THRESHOLD {  0, 0 }
45 
temp_nrfs_handle_event(const struct device * dev)46 static void temp_nrfs_handle_event(const struct device *dev)
47 {
48 	struct temp_nrfs_data *data = dev->data;
49 	struct sensor_trigger trigger;
50 	sensor_trigger_handler_t handler;
51 
52 	k_mutex_lock(&data->mutex, K_FOREVER);
53 	trigger = data->trigger;
54 	handler = data->handler;
55 	k_mutex_unlock(&data->mutex);
56 
57 	if (handler) {
58 		handler(dev, &trigger);
59 	}
60 }
61 
62 #if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD)
temp_nrfs_thread(void * p1,void * p2,void * p3)63 static void temp_nrfs_thread(void *p1, void *p2, void *p3)
64 {
65 	ARG_UNUSED(p2);
66 	ARG_UNUSED(p3);
67 
68 	struct temp_nrfs_data *data = p1;
69 
70 	while (1) {
71 		k_sem_take(&data->event_sem, K_FOREVER);
72 		temp_nrfs_handle_event(data->dev);
73 	}
74 }
75 #elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD)
temp_nrfs_work_handler(struct k_work * work)76 static void temp_nrfs_work_handler(struct k_work *work)
77 {
78 	struct temp_nrfs_data *data =
79 		CONTAINER_OF(work, struct temp_nrfs_data, work);
80 
81 	temp_nrfs_handle_event(data->dev);
82 }
83 #endif
84 
to_measure_rate_ms(const struct sensor_value * freq_val)85 static uint16_t to_measure_rate_ms(const struct sensor_value *freq_val)
86 {
87 	uint32_t measure_rate_ms = (MSEC_PER_SEC * 1000) /
88 		(uint32_t)sensor_value_to_milli(freq_val);
89 
90 	return (uint16_t)MIN(measure_rate_ms, UINT16_MAX);
91 }
92 
to_raw_temp(const struct sensor_value * temp_val)93 static int32_t to_raw_temp(const struct sensor_value *temp_val)
94 {
95 	int32_t temp_mul_100 = (int32_t)(sensor_value_to_milli(temp_val) / 10);
96 
97 	return nrfs_temp_to_raw(temp_mul_100);
98 }
99 
api_sensor_trigger_set(const struct device * dev,const struct sensor_trigger * trig,sensor_trigger_handler_t handler)100 static int api_sensor_trigger_set(const struct device *dev,
101 				  const struct sensor_trigger *trig,
102 				  sensor_trigger_handler_t handler)
103 {
104 	struct temp_nrfs_data *data = dev->data;
105 	nrfs_err_t err;
106 
107 	if (trig->chan != SENSOR_CHAN_ALL &&
108 	    trig->chan != SENSOR_CHAN_DIE_TEMP) {
109 		return -ENOTSUP;
110 	}
111 
112 	switch (trig->type) {
113 	case SENSOR_TRIG_THRESHOLD:
114 		k_mutex_lock(&data->mutex, K_FOREVER);
115 		data->trigger = *trig;
116 		data->handler = handler;
117 		k_mutex_unlock(&data->mutex);
118 
119 		if (handler) {
120 			err = nrfs_temp_subscribe(
121 				to_measure_rate_ms(&data->sampling_freq),
122 				to_raw_temp(&data->low_threshold),
123 				to_raw_temp(&data->up_threshold),
124 				data);
125 		} else {
126 			err = nrfs_temp_unsubscribe();
127 		}
128 
129 		switch (err) {
130 		case NRFS_SUCCESS:
131 			break;
132 		case NRFS_ERR_INVALID_STATE:
133 			return -EAGAIN;
134 		default:
135 			return -EIO;
136 		}
137 		break;
138 
139 	default:
140 		return -ENOTSUP;
141 	}
142 
143 	return 0;
144 }
145 
api_sensor_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)146 static int api_sensor_attr_set(const struct device *dev,
147 			       enum sensor_channel chan,
148 			       enum sensor_attribute attr,
149 			       const struct sensor_value *val)
150 {
151 	struct temp_nrfs_data *data = dev->data;
152 
153 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
154 		return -ENOTSUP;
155 	}
156 
157 	switch (attr) {
158 	case SENSOR_ATTR_SAMPLING_FREQUENCY:
159 		if (sensor_value_to_milli(val) <= 0) {
160 			return -EINVAL;
161 		}
162 		data->sampling_freq = *val;
163 		break;
164 	case SENSOR_ATTR_UPPER_THRESH:
165 		data->up_threshold = *val;
166 		break;
167 	case SENSOR_ATTR_LOWER_THRESH:
168 		data->low_threshold = *val;
169 		break;
170 	default:
171 		return -ENOTSUP;
172 	}
173 	return 0;
174 }
175 
176 #endif /* CONFIG_TEMP_NRFS_TRIGGER */
177 
sensor_handler(nrfs_temp_evt_t const * p_evt,void * context)178 static void sensor_handler(nrfs_temp_evt_t const *p_evt, void *context)
179 {
180 	ARG_UNUSED(context);
181 
182 	struct temp_nrfs_data *data = context;
183 
184 	switch (p_evt->type) {
185 	case NRFS_TEMP_EVT_MEASURE_DONE:
186 		data->raw_temp = p_evt->raw_temp;
187 		k_sem_give(&data->measure_sem);
188 		break;
189 
190 #ifdef CONFIG_TEMP_NRFS_TRIGGER
191 	case NRFS_TEMP_EVT_CHANGE:
192 		data->raw_temp = p_evt->raw_temp;
193 #if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD)
194 		k_sem_give(&data->event_sem);
195 #elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD)
196 		k_work_submit(&data->work);
197 #endif
198 		break;
199 #endif /* CONFIG_TEMP_NRFS_TRIGGER */
200 
201 	default:
202 		LOG_DBG("Temperature handler - unsupported event: 0x%x",
203 			p_evt->type);
204 		break;
205 	}
206 }
207 
api_sample_fetch(const struct device * dev,enum sensor_channel chan)208 static int api_sample_fetch(const struct device *dev,
209 			    enum sensor_channel chan)
210 {
211 	struct temp_nrfs_data *data = dev->data;
212 	int nrfs_rc;
213 	int rc = 0;
214 
215 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
216 		return -ENOTSUP;
217 	}
218 
219 	k_mutex_lock(&data->mutex, K_FOREVER);
220 	nrfs_rc = nrfs_temp_measure_request(data);
221 	switch (nrfs_rc) {
222 	case NRFS_SUCCESS:
223 		k_sem_take(&data->measure_sem, K_FOREVER);
224 		LOG_DBG("Temperature sample: %d", data->raw_temp);
225 		break;
226 	case NRFS_ERR_INVALID_STATE:
227 		LOG_DBG("Backend is not ready, try again.");
228 		rc = -EAGAIN;
229 		break;
230 	default:
231 		LOG_DBG("Measure request failed: %d", nrfs_rc);
232 		rc = -EIO;
233 		break;
234 	}
235 	k_mutex_unlock(&data->mutex);
236 
237 	return rc;
238 }
239 
api_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)240 static int api_channel_get(const struct device *dev,
241 			   enum sensor_channel chan,
242 			   struct sensor_value *val)
243 {
244 	struct temp_nrfs_data *data = dev->data;
245 
246 	if (chan != SENSOR_CHAN_DIE_TEMP) {
247 		return -ENOTSUP;
248 	}
249 
250 	int32_t uval = nrfs_temp_from_raw(data->raw_temp);
251 
252 	val->val1 = uval / 100;
253 	val->val2 = (abs(uval) % 100) * 10000;
254 
255 	LOG_DBG("Temperature: %d.%02u[C]", uval / 100, abs(uval) % 100);
256 
257 	return 0;
258 }
259 
temp_nrfs_init(const struct device * dev)260 static int temp_nrfs_init(const struct device *dev)
261 {
262 	int rc;
263 
264 	rc = nrfs_temp_init(sensor_handler);
265 	if (rc < 0) {
266 		return rc;
267 	}
268 
269 #if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD)
270 	struct temp_nrfs_data *data = dev->data;
271 
272 	k_thread_create(&data->thread, data->thread_stack,
273 			CONFIG_TEMP_NRFS_THREAD_STACK_SIZE,
274 			temp_nrfs_thread,
275 			data, NULL, NULL,
276 			K_PRIO_COOP(CONFIG_TEMP_NRFS_THREAD_PRIORITY),
277 			0, K_NO_WAIT);
278 	k_thread_name_set(&data->thread, dev->name);
279 #endif
280 
281 	return 0;
282 }
283 
284 static DEVICE_API(sensor, temp_nrfs_drv_api) = {
285 #ifdef CONFIG_TEMP_NRFS_TRIGGER
286 	.attr_set = api_sensor_attr_set,
287 	.trigger_set = api_sensor_trigger_set,
288 #endif
289 	.sample_fetch = api_sample_fetch,
290 	.channel_get = api_channel_get
291 };
292 
293 static struct temp_nrfs_data temp_nrfs_drv_data = {
294 	.mutex = Z_MUTEX_INITIALIZER(temp_nrfs_drv_data.mutex),
295 	.measure_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.measure_sem, 0, 1),
296 #ifdef CONFIG_TEMP_NRFS_TRIGGER
297 	.dev = DEVICE_DT_INST_GET(0),
298 	.sampling_freq = DEFAULT_SAMPLING_FREQ,
299 	.up_threshold  = DEFAULT_UP_THRESHOLD,
300 	.low_threshold = DEFAULT_LOW_THRESHOLD,
301 #endif
302 #if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD)
303 	.event_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.event_sem, 0, 1),
304 #elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD)
305 	.work = Z_WORK_INITIALIZER(temp_nrfs_work_handler),
306 #endif
307 };
308 
309 DEVICE_DT_INST_DEFINE(0, temp_nrfs_init, NULL,
310 		      &temp_nrfs_drv_data, NULL,
311 		      POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY,
312 		      &temp_nrfs_drv_api);
313