1 /*
2 * Copyright (c) 2024 Fredrik Gihl
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ti_tmp114
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/dt-bindings/sensor/tmp114.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/__assert.h>
15 #include <zephyr/logging/log.h>
16 #include <zephyr/kernel.h>
17
18 LOG_MODULE_REGISTER(TMP114, CONFIG_SENSOR_LOG_LEVEL);
19
20 #define TMP114_REG_TEMP 0x0
21 #define TMP114_REG_ALERT 0x2
22 #define TMP114_REG_CFGR 0x3
23 #define TMP114_REG_DEVICE_ID 0xb
24
25 #define TMP114_RESOLUTION 78125 /* in tens of uCelsius*/
26 #define TMP114_RESOLUTION_DIV 10000000
27
28 #define TMP114_DEVICE_ID 0x1114
29
30 #define TMP114_ALERT_DATA_READY BIT(0)
31 #define TMP114_CFGR_AVG BIT(7)
32 #define TMP114_AVG BIT(7)
33 #define TMP114_CFGR_CONV (BIT(0) | BIT(1) | BIT(2))
34
35 struct tmp114_data {
36 uint16_t sample;
37 uint16_t id;
38 };
39
40 struct tmp114_dev_config {
41 struct i2c_dt_spec bus;
42 uint16_t odr;
43 bool oversampling;
44 };
45
tmp114_reg_read(const struct device * dev,uint8_t reg,uint16_t * val)46 static int tmp114_reg_read(const struct device *dev, uint8_t reg, uint16_t *val)
47 {
48 const struct tmp114_dev_config *cfg = dev->config;
49
50 if (i2c_burst_read_dt(&cfg->bus, reg, (uint8_t *)val, 2) < 0) {
51 return -EIO;
52 }
53
54 *val = sys_be16_to_cpu(*val);
55
56 return 0;
57 }
58
tmp114_reg_write(const struct device * dev,uint8_t reg,uint16_t val)59 static int tmp114_reg_write(const struct device *dev, uint8_t reg, uint16_t val)
60 {
61 const struct tmp114_dev_config *cfg = dev->config;
62 uint8_t tx_buf[3] = {reg, val >> 8, val & 0xFF};
63
64 return i2c_write_dt(&cfg->bus, tx_buf, sizeof(tx_buf));
65 }
66
tmp114_write_config(const struct device * dev,uint16_t mask,uint16_t conf)67 static int tmp114_write_config(const struct device *dev, uint16_t mask, uint16_t conf)
68 {
69 uint16_t config = 0;
70 int result;
71
72 result = tmp114_reg_read(dev, TMP114_REG_CFGR, &config);
73
74 if (result < 0) {
75 return result;
76 }
77
78 config &= ~mask;
79 config |= conf;
80
81 result = tmp114_reg_write(dev, TMP114_REG_CFGR, config);
82
83 if (result < 0) {
84 return result;
85 }
86
87 return 0;
88 }
89
tmp114_device_id_check(const struct device * dev,uint16_t * id)90 static inline int tmp114_device_id_check(const struct device *dev, uint16_t *id)
91 {
92 if (tmp114_reg_read(dev, TMP114_REG_DEVICE_ID, id) != 0) {
93 LOG_ERR("%s: Failed to get Device ID register!", dev->name);
94 return -EIO;
95 }
96
97 if (*id != TMP114_DEVICE_ID) {
98 LOG_ERR("%s: Failed to match the device ID!", dev->name);
99 return -EINVAL;
100 }
101
102 return 0;
103 }
104
tmp114_sample_fetch(const struct device * dev,enum sensor_channel chan)105 static int tmp114_sample_fetch(const struct device *dev,
106 enum sensor_channel chan)
107 {
108 struct tmp114_data *drv_data = dev->data;
109 uint16_t value;
110 uint16_t cfg_reg = 0;
111 int rc;
112
113 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL ||
114 chan == SENSOR_CHAN_AMBIENT_TEMP);
115
116 /* clear sensor values */
117 drv_data->sample = 0U;
118
119 /* Check alert register to make sure that a data is available */
120 rc = tmp114_reg_read(dev, TMP114_REG_ALERT, &cfg_reg);
121 if (rc < 0) {
122 LOG_ERR("%s, Failed to read from CFGR register", dev->name);
123 return rc;
124 }
125
126 if ((cfg_reg & TMP114_ALERT_DATA_READY) == 0) {
127 LOG_DBG("%s: no data ready", dev->name);
128 return -EBUSY;
129 }
130
131 /* Get the most recent temperature measurement */
132 rc = tmp114_reg_read(dev, TMP114_REG_TEMP, &value);
133 if (rc < 0) {
134 LOG_ERR("%s: Failed to read from TEMP register!", dev->name);
135 return rc;
136 }
137
138 /* store measurements to the driver */
139 drv_data->sample = (int16_t)value;
140
141 return 0;
142 }
143
tmp114_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)144 static int tmp114_channel_get(const struct device *dev, enum sensor_channel chan,
145 struct sensor_value *val)
146 {
147 struct tmp114_data *drv_data = dev->data;
148 int32_t tmp;
149
150 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
151 return -ENOTSUP;
152 }
153
154 /*
155 * See datasheet for tmp114, section 'Temp_Result Register' section
156 * for more details on processing sample data.
157 */
158 tmp = ((int16_t)drv_data->sample * (int32_t)TMP114_RESOLUTION) / 10;
159 val->val1 = tmp / 1000000; /* uCelsius */
160 val->val2 = tmp % 1000000;
161
162 return 0;
163 }
164
tmp114_attr_get(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,struct sensor_value * val)165 static int tmp114_attr_get(const struct device *dev, enum sensor_channel chan,
166 enum sensor_attribute attr, struct sensor_value *val)
167 {
168 uint16_t data;
169 int rc;
170
171 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
172 return -ENOTSUP;
173 }
174
175 switch (attr) {
176 case SENSOR_ATTR_CONFIGURATION:
177 rc = tmp114_reg_read(dev, TMP114_REG_CFGR, &data);
178 if (rc < 0) {
179 return rc;
180 }
181 break;
182 default:
183 return -ENOTSUP;
184 }
185
186 val->val1 = data;
187 val->val2 = 0;
188
189 return 0;
190 }
191
tmp114_odr_value(const struct sensor_value * frequency,uint16_t * config_value)192 static int tmp114_odr_value(const struct sensor_value *frequency, uint16_t *config_value)
193 {
194 const uint32_t freq_micro = sensor_value_to_micro(frequency);
195
196 if (freq_micro <= 500000) {
197 *config_value = TMP114_DT_ODR_2000_MS; /* 2 s */
198 } else if (freq_micro <= 1000000) {
199 *config_value = TMP114_DT_ODR_1000_MS; /* 1 s */
200 } else if (freq_micro <= 2000000) {
201 *config_value = TMP114_DT_ODR_500_MS; /* 500 ms */
202 } else if (freq_micro <= 4000000) {
203 *config_value = TMP114_DT_ODR_250_MS; /* 250 ms */
204 } else if (freq_micro <= 8000000) {
205 *config_value = TMP114_DT_ODR_125_MS; /* 125 ms */
206 } else if (freq_micro <= 16000000) {
207 *config_value = TMP114_DT_ODR_62_5_MS; /* 62.5 ms */
208 } else if (freq_micro <= 32000000) {
209 *config_value = TMP114_DT_ODR_31_25_MS; /* 32.25 ms */
210 } else if (freq_micro <= 156250000) {
211 *config_value = TMP114_DT_ODR_6_4_MS; /* 6.4 ms */
212 } else {
213 return -ENOTSUP;
214 }
215
216 return 0;
217 }
218
tmp114_attr_set(const struct device * dev,enum sensor_channel chan,enum sensor_attribute attr,const struct sensor_value * val)219 static int tmp114_attr_set(const struct device *dev, enum sensor_channel chan,
220 enum sensor_attribute attr, const struct sensor_value *val)
221 {
222 uint16_t value = 0;
223 int rc = 0;
224
225 if (chan != SENSOR_CHAN_AMBIENT_TEMP) {
226 return -ENOTSUP;
227 }
228
229 switch (attr) {
230 case SENSOR_ATTR_OVERSAMPLING:
231 /* Enable the AVG in tmp114. The chip will do 8 avg of 8 samples
232 * to get a more accurate value.
233 */
234
235 if (val->val1) {
236 value = TMP114_AVG;
237 }
238
239 return tmp114_write_config(dev, TMP114_CFGR_AVG, value);
240 case SENSOR_ATTR_SAMPLING_FREQUENCY:
241 /* Set the output data rate tmp114. */
242 rc = tmp114_odr_value(val, &value);
243 if (rc < 0) {
244 return rc;
245 }
246
247 return tmp114_write_config(dev, TMP114_CFGR_CONV, value);
248 default:
249 return -ENOTSUP;
250 }
251 }
252
253 static DEVICE_API(sensor, tmp114_driver_api) = {
254 .attr_get = tmp114_attr_get,
255 .attr_set = tmp114_attr_set,
256 .sample_fetch = tmp114_sample_fetch,
257 .channel_get = tmp114_channel_get
258 };
259
tmp114_init(const struct device * dev)260 static int tmp114_init(const struct device *dev)
261 {
262 struct tmp114_data *drv_data = dev->data;
263 const struct tmp114_dev_config *cfg = dev->config;
264 int rc;
265 uint16_t id;
266 struct sensor_value val;
267
268 if (!i2c_is_ready_dt(&cfg->bus)) {
269 LOG_ERR("I2C dev %s not ready", cfg->bus.bus->name);
270 return -EINVAL;
271 }
272
273 /* Check the Device ID */
274 rc = tmp114_device_id_check(dev, &id);
275 if (rc < 0) {
276 return rc;
277 }
278 LOG_INF("Got device ID: %x", id);
279 drv_data->id = id;
280
281 rc = tmp114_write_config(dev, TMP114_CFGR_CONV, cfg->odr);
282 if (rc < 0) {
283 return rc;
284 }
285
286 val.val1 = cfg->oversampling ? 1 : 0;
287 val.val2 = 0;
288
289 rc = tmp114_attr_set(dev, SENSOR_CHAN_AMBIENT_TEMP, SENSOR_ATTR_OVERSAMPLING, &val);
290 if (rc < 0) {
291 return rc;
292 }
293
294 return 0;
295 }
296
297 #define DEFINE_TMP114(_num) \
298 static struct tmp114_data tmp114_data_##_num; \
299 static const struct tmp114_dev_config tmp114_config_##_num = { \
300 .bus = I2C_DT_SPEC_INST_GET(_num), \
301 .odr = DT_INST_PROP(_num, odr), \
302 .oversampling = DT_INST_PROP(_num, oversampling), \
303 }; \
304 SENSOR_DEVICE_DT_INST_DEFINE(_num, tmp114_init, NULL, \
305 &tmp114_data_##_num, &tmp114_config_##_num, POST_KERNEL, \
306 CONFIG_SENSOR_INIT_PRIORITY, &tmp114_driver_api);
307
308 DT_INST_FOREACH_STATUS_OKAY(DEFINE_TMP114)
309