1 /*
2  * Copyright (c) 2016 ARM Ltd.
3  * Copyright (c) 2019 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #define DT_DRV_COMPAT nordic_nrf_temp
9 
10 #include <device.h>
11 #include <drivers/sensor.h>
12 #include <drivers/clock_control.h>
13 #include <drivers/clock_control/nrf_clock_control.h>
14 #include <logging/log.h>
15 #include <hal/nrf_temp.h>
16 
17 LOG_MODULE_REGISTER(temp_nrf5, CONFIG_SENSOR_LOG_LEVEL);
18 
19 
20 /* The nRF5 temperature device returns measurements in 0.25C
21  * increments.  Scale to mDegrees C.
22  */
23 #define TEMP_NRF5_TEMP_SCALE (1000000 / 4)
24 
25 struct temp_nrf5_data {
26 	struct k_sem device_sync_sem;
27 	struct k_mutex mutex;
28 	int32_t sample;
29 	struct onoff_manager *clk_mgr;
30 };
31 
hfclk_on_callback(struct onoff_manager * mgr,struct onoff_client * cli,uint32_t state,int res)32 static void hfclk_on_callback(struct onoff_manager *mgr,
33 			      struct onoff_client *cli,
34 			      uint32_t state,
35 			      int res)
36 {
37 	nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_START);
38 }
39 
temp_nrf5_sample_fetch(const struct device * dev,enum sensor_channel chan)40 static int temp_nrf5_sample_fetch(const struct device *dev,
41 				  enum sensor_channel chan)
42 {
43 	struct temp_nrf5_data *data = dev->data;
44 	struct onoff_client cli;
45 	int r;
46 
47 	/* Error if before sensor initialized */
48 	if (data->clk_mgr == NULL) {
49 		return -EAGAIN;
50 	}
51 
52 	if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) {
53 		return -ENOTSUP;
54 	}
55 
56 	k_mutex_lock(&data->mutex, K_FOREVER);
57 
58 	sys_notify_init_callback(&cli.notify, hfclk_on_callback);
59 	r = onoff_request(data->clk_mgr, &cli);
60 	__ASSERT_NO_MSG(r >= 0);
61 
62 	k_sem_take(&data->device_sync_sem, K_FOREVER);
63 
64 	r = onoff_release(data->clk_mgr);
65 	__ASSERT_NO_MSG(r >= 0);
66 
67 	data->sample = nrf_temp_result_get(NRF_TEMP);
68 	LOG_DBG("sample: %d", data->sample);
69 	nrf_temp_task_trigger(NRF_TEMP, NRF_TEMP_TASK_STOP);
70 
71 	k_mutex_unlock(&data->mutex);
72 
73 	return 0;
74 }
75 
temp_nrf5_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)76 static int temp_nrf5_channel_get(const struct device *dev,
77 				 enum sensor_channel chan,
78 				 struct sensor_value *val)
79 {
80 	struct temp_nrf5_data *data = dev->data;
81 	int32_t uval;
82 
83 
84 	if (chan != SENSOR_CHAN_DIE_TEMP) {
85 		return -ENOTSUP;
86 	}
87 
88 	uval = data->sample * TEMP_NRF5_TEMP_SCALE;
89 	val->val1 = uval / 1000000;
90 	val->val2 = uval % 1000000;
91 
92 	LOG_DBG("Temperature:%d,%d", val->val1, val->val2);
93 
94 	return 0;
95 }
96 
temp_nrf5_isr(void * arg)97 static void temp_nrf5_isr(void *arg)
98 {
99 	const struct device *dev = (const struct device *)arg;
100 	struct temp_nrf5_data *data = dev->data;
101 
102 	nrf_temp_event_clear(NRF_TEMP, NRF_TEMP_EVENT_DATARDY);
103 	k_sem_give(&data->device_sync_sem);
104 }
105 
106 static const struct sensor_driver_api temp_nrf5_driver_api = {
107 	.sample_fetch = temp_nrf5_sample_fetch,
108 	.channel_get = temp_nrf5_channel_get,
109 };
110 
temp_nrf5_init(const struct device * dev)111 static int temp_nrf5_init(const struct device *dev)
112 {
113 	struct temp_nrf5_data *data = dev->data;
114 
115 	LOG_DBG("");
116 
117 	/* A null clk_mgr indicates sensor has not been initialized */
118 	data->clk_mgr =
119 		z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_HF);
120 	__ASSERT_NO_MSG(data->clk_mgr);
121 
122 	k_sem_init(&data->device_sync_sem, 0, K_SEM_MAX_LIMIT);
123 	k_mutex_init(&data->mutex);
124 
125 	IRQ_CONNECT(
126 		DT_INST_IRQN(0),
127 		DT_INST_IRQ(0, priority),
128 		temp_nrf5_isr,
129 		DEVICE_DT_INST_GET(0),
130 		0);
131 	irq_enable(DT_INST_IRQN(0));
132 
133 	nrf_temp_int_enable(NRF_TEMP, NRF_TEMP_INT_DATARDY_MASK);
134 
135 	return 0;
136 }
137 
138 static struct temp_nrf5_data temp_nrf5_driver;
139 
140 DEVICE_DT_INST_DEFINE(0,
141 		    temp_nrf5_init,
142 		    NULL,
143 		    &temp_nrf5_driver,
144 		    NULL,
145 		    POST_KERNEL,
146 		    CONFIG_SENSOR_INIT_PRIORITY,
147 		    &temp_nrf5_driver_api);
148