1 /*
2 * Copyright (c) 2019 Actinius
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT silabs_si7060
8
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/i2c.h>
11 #include <zephyr/drivers/sensor.h>
12 #include <zephyr/logging/log.h>
13
14 #include "si7060.h"
15
16 #define SIGN_BIT_MASK 0x7F
17
18 LOG_MODULE_REGISTER(si7060, CONFIG_SENSOR_LOG_LEVEL);
19
20 struct si7060_data {
21 uint16_t temperature;
22 };
23
24 struct si7060_config {
25 struct i2c_dt_spec i2c;
26 };
27
si7060_reg_read(const struct device * dev,uint8_t reg,uint8_t * val)28 static int si7060_reg_read(const struct device *dev, uint8_t reg, uint8_t *val)
29 {
30 const struct si7060_config *config = dev->config;
31
32 if (i2c_reg_read_byte_dt(&config->i2c, reg, val)) {
33 return -EIO;
34 }
35
36 return 0;
37 }
38
si7060_reg_write(const struct device * dev,uint8_t reg,uint8_t val)39 static int si7060_reg_write(const struct device *dev, uint8_t reg, uint8_t val)
40 {
41 const struct si7060_config *config = dev->config;
42
43 return i2c_reg_write_byte_dt(&config->i2c, reg, val);
44 }
45
si7060_sample_fetch(const struct device * dev,enum sensor_channel chan)46 static int si7060_sample_fetch(const struct device *dev,
47 enum sensor_channel chan)
48 {
49 struct si7060_data *drv_data = dev->data;
50
51 if (si7060_reg_write(dev, SI7060_REG_CONFIG,
52 SI7060_ONE_BURST_VALUE) != 0) {
53 return -EIO;
54 }
55
56 int retval;
57 uint8_t dspsigm;
58 uint8_t dspsigl;
59
60 retval = si7060_reg_read(dev, SI7060_REG_TEMP_HIGH, &dspsigm);
61 retval += si7060_reg_read(dev, SI7060_REG_TEMP_LOW, &dspsigl);
62
63 if (retval == 0) {
64 drv_data->temperature = (256 * (dspsigm & SIGN_BIT_MASK))
65 + dspsigl;
66 } else {
67 LOG_ERR("Read register err");
68 }
69
70 LOG_DBG("Sample_fetch retval: %d", retval);
71
72 return retval;
73 }
74
si7060_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)75 static int si7060_channel_get(const struct device *dev,
76 enum sensor_channel chan,
77 struct sensor_value *val)
78 {
79 struct si7060_data *drv_data = dev->data;
80 int32_t uval;
81
82 if (chan == SENSOR_CHAN_AMBIENT_TEMP) {
83 uval = ((55 * 160) + (drv_data->temperature - 16384)) >> 4;
84 val->val1 = uval / 10;
85 val->val2 = (uval % 10) * 100000;
86
87 LOG_DBG("Temperature = val1:%d, val2:%d", val->val1, val->val2);
88
89 return 0;
90 } else {
91 return -ENOTSUP;
92 }
93 }
94
95 static DEVICE_API(sensor, si7060_api) = {
96 .sample_fetch = &si7060_sample_fetch,
97 .channel_get = &si7060_channel_get,
98 };
99
si7060_chip_init(const struct device * dev)100 static int si7060_chip_init(const struct device *dev)
101 {
102 const struct si7060_config *config = dev->config;
103 uint8_t value;
104
105 if (!device_is_ready(config->i2c.bus)) {
106 LOG_ERR("Bus device is not ready");
107 return -ENODEV;
108 }
109
110 if (si7060_reg_read(dev, SI7060_REG_CHIP_INFO, &value) != 0) {
111 return -EIO;
112 }
113
114 if ((value >> 4) != SI7060_CHIP_ID_VALUE) {
115 LOG_ERR("Bad chip id 0x%x", value);
116 return -ENOTSUP;
117 }
118
119 return 0;
120 }
121
si7060_init(const struct device * dev)122 static int si7060_init(const struct device *dev)
123 {
124 if (si7060_chip_init(dev) < 0) {
125 return -EINVAL;
126 }
127
128 return 0;
129 }
130
131 #define SI7060_DEFINE(inst) \
132 static struct si7060_data si7060_data_##inst; \
133 \
134 static const struct si7060_config si7060_config_##inst = { \
135 .i2c = I2C_DT_SPEC_INST_GET(inst), \
136 }; \
137 \
138 SENSOR_DEVICE_DT_INST_DEFINE(inst, si7060_init, NULL, \
139 &si7060_data_##inst, &si7060_config_##inst, POST_KERNEL, \
140 CONFIG_SENSOR_INIT_PRIORITY, &si7060_api); \
141
142 DT_INST_FOREACH_STATUS_OKAY(SI7060_DEFINE)
143