1 /*
2 * Copyright (c) 2019 Actinius
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #define DT_DRV_COMPAT ti_opt3001
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 #include <zephyr/sys/__assert.h>
14
15 #include "opt3001.h"
16
17 LOG_MODULE_REGISTER(opt3001, CONFIG_SENSOR_LOG_LEVEL);
18
opt3001_reg_read(const struct device * dev,uint8_t reg,uint16_t * val)19 static int opt3001_reg_read(const struct device *dev, uint8_t reg,
20 uint16_t *val)
21 {
22 const struct opt3001_config *config = dev->config;
23 uint8_t value[2];
24
25 if (i2c_burst_read_dt(&config->i2c, reg, value, 2) != 0) {
26 return -EIO;
27 }
28
29 *val = ((uint16_t)value[0] << 8) + value[1];
30
31 return 0;
32 }
33
opt3001_reg_write(const struct device * dev,uint8_t reg,uint16_t val)34 static int opt3001_reg_write(const struct device *dev, uint8_t reg,
35 uint16_t val)
36 {
37 const struct opt3001_config *config = dev->config;
38 uint8_t new_value[2];
39
40 new_value[0] = val >> 8;
41 new_value[1] = val & 0xff;
42
43 uint8_t tx_buf[3] = { reg, new_value[0], new_value[1] };
44
45 return i2c_write_dt(&config->i2c, tx_buf, sizeof(tx_buf));
46 }
47
opt3001_reg_update(const struct device * dev,uint8_t reg,uint16_t mask,uint16_t val)48 static int opt3001_reg_update(const struct device *dev, uint8_t reg,
49 uint16_t mask, uint16_t val)
50 {
51 uint16_t old_val;
52 uint16_t new_val;
53
54 if (opt3001_reg_read(dev, reg, &old_val) != 0) {
55 return -EIO;
56 }
57
58 new_val = old_val & ~mask;
59 new_val |= val & mask;
60
61 return opt3001_reg_write(dev, reg, new_val);
62 }
63
opt3001_sample_fetch(const struct device * dev,enum sensor_channel chan)64 static int opt3001_sample_fetch(const struct device *dev,
65 enum sensor_channel chan)
66 {
67 struct opt3001_data *drv_data = dev->data;
68 uint16_t value;
69
70 __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_LIGHT);
71
72 drv_data->sample = 0U;
73
74 if (opt3001_reg_read(dev, OPT3001_REG_RESULT, &value) != 0) {
75 return -EIO;
76 }
77
78 drv_data->sample = value;
79
80 return 0;
81 }
82
opt3001_channel_get(const struct device * dev,enum sensor_channel chan,struct sensor_value * val)83 static int opt3001_channel_get(const struct device *dev,
84 enum sensor_channel chan,
85 struct sensor_value *val)
86 {
87 struct opt3001_data *drv_data = dev->data;
88 int32_t uval;
89
90 if (chan != SENSOR_CHAN_LIGHT) {
91 return -ENOTSUP;
92 }
93
94 /**
95 * sample consists of 4 bits of exponent and 12 bits of mantissa
96 * bits 15 to 12 are exponent bits
97 * bits 11 to 0 are the mantissa bits
98 *
99 * lux is the integer obtained using the following formula:
100 * (2^(exponent value)) * 0.01 * mantissa value
101 */
102 uval = (1 << (drv_data->sample >> OPT3001_SAMPLE_EXPONENT_SHIFT))
103 * (drv_data->sample & OPT3001_MANTISSA_MASK);
104 val->val1 = uval / 100;
105 val->val2 = (uval % 100) * 10000;
106
107 return 0;
108 }
109
110 static DEVICE_API(sensor, opt3001_driver_api) = {
111 .sample_fetch = opt3001_sample_fetch,
112 .channel_get = opt3001_channel_get,
113 };
114
opt3001_chip_init(const struct device * dev)115 static int opt3001_chip_init(const struct device *dev)
116 {
117 const struct opt3001_config *config = dev->config;
118 uint16_t value;
119
120 if (!device_is_ready(config->i2c.bus)) {
121 LOG_ERR("Bus device is not ready");
122 return -ENODEV;
123 }
124
125 if (opt3001_reg_read(dev, OPT3001_REG_MANUFACTURER_ID, &value) != 0) {
126 return -EIO;
127 }
128
129 if (value != OPT3001_MANUFACTURER_ID_VALUE) {
130 LOG_ERR("Bad manufacturer id 0x%x", value);
131 return -ENOTSUP;
132 }
133
134 if (opt3001_reg_read(dev, OPT3001_REG_DEVICE_ID, &value) != 0) {
135 return -EIO;
136 }
137
138 if (value != OPT3001_DEVICE_ID_VALUE) {
139 LOG_ERR("Bad device id 0x%x", value);
140 return -ENOTSUP;
141 }
142
143 if (opt3001_reg_update(dev, OPT3001_REG_CONFIG,
144 OPT3001_CONVERSION_MODE_MASK,
145 OPT3001_CONVERSION_MODE_CONTINUOUS) != 0) {
146 LOG_ERR("Failed to set mode to continuous conversion");
147 return -EIO;
148 }
149
150 return 0;
151 }
152
opt3001_init(const struct device * dev)153 int opt3001_init(const struct device *dev)
154 {
155 if (opt3001_chip_init(dev) < 0) {
156 return -EINVAL;
157 }
158
159 return 0;
160 }
161
162 #define OPT3001_DEFINE(inst) \
163 static struct opt3001_data opt3001_data_##inst; \
164 \
165 static const struct opt3001_config opt3001_config_##inst = { \
166 .i2c = I2C_DT_SPEC_INST_GET(inst), \
167 }; \
168 \
169 SENSOR_DEVICE_DT_INST_DEFINE(inst, opt3001_init, NULL, \
170 &opt3001_data_##inst, &opt3001_config_##inst, POST_KERNEL, \
171 CONFIG_SENSOR_INIT_PRIORITY, &opt3001_driver_api); \
172
173 DT_INST_FOREACH_STATUS_OKAY(OPT3001_DEFINE)
174