1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2023 Axis Communications AB |
4 | * |
5 | * Datasheet: https://www.ti.com/lit/gpn/opt4001 |
6 | * |
7 | * Device driver for the Texas Instruments OPT4001. |
8 | */ |
9 | |
10 | #include <linux/bitfield.h> |
11 | #include <linux/i2c.h> |
12 | #include <linux/iio/iio.h> |
13 | #include <linux/math64.h> |
14 | #include <linux/module.h> |
15 | #include <linux/property.h> |
16 | #include <linux/regmap.h> |
17 | #include <linux/regulator/consumer.h> |
18 | |
19 | /* OPT4001 register set */ |
20 | #define OPT4001_LIGHT1_MSB 0x00 |
21 | #define OPT4001_LIGHT1_LSB 0x01 |
22 | #define OPT4001_CTRL 0x0A |
23 | #define OPT4001_DEVICE_ID 0x11 |
24 | |
25 | /* OPT4001 register mask */ |
26 | #define OPT4001_EXPONENT_MASK GENMASK(15, 12) |
27 | #define OPT4001_MSB_MASK GENMASK(11, 0) |
28 | #define OPT4001_LSB_MASK GENMASK(15, 8) |
29 | #define OPT4001_COUNTER_MASK GENMASK(7, 4) |
30 | #define OPT4001_CRC_MASK GENMASK(3, 0) |
31 | |
32 | /* OPT4001 device id mask */ |
33 | #define OPT4001_DEVICE_ID_MASK GENMASK(11, 0) |
34 | |
35 | /* OPT4001 control registers mask */ |
36 | #define OPT4001_CTRL_QWAKE_MASK GENMASK(15, 15) |
37 | #define OPT4001_CTRL_RANGE_MASK GENMASK(13, 10) |
38 | #define OPT4001_CTRL_CONV_TIME_MASK GENMASK(9, 6) |
39 | #define OPT4001_CTRL_OPER_MODE_MASK GENMASK(5, 4) |
40 | #define OPT4001_CTRL_LATCH_MASK GENMASK(3, 3) |
41 | #define OPT4001_CTRL_INT_POL_MASK GENMASK(2, 2) |
42 | #define OPT4001_CTRL_FAULT_COUNT GENMASK(0, 1) |
43 | |
44 | /* OPT4001 constants */ |
45 | #define OPT4001_DEVICE_ID_VAL 0x121 |
46 | |
47 | /* OPT4001 operating modes */ |
48 | #define OPT4001_CTRL_OPER_MODE_OFF 0x0 |
49 | #define OPT4001_CTRL_OPER_MODE_FORCED 0x1 |
50 | #define OPT4001_CTRL_OPER_MODE_ONE_SHOT 0x2 |
51 | #define OPT4001_CTRL_OPER_MODE_CONTINUOUS 0x3 |
52 | |
53 | /* OPT4001 conversion control register definitions */ |
54 | #define OPT4001_CTRL_CONVERSION_0_6MS 0x0 |
55 | #define OPT4001_CTRL_CONVERSION_1MS 0x1 |
56 | #define OPT4001_CTRL_CONVERSION_1_8MS 0x2 |
57 | #define OPT4001_CTRL_CONVERSION_3_4MS 0x3 |
58 | #define OPT4001_CTRL_CONVERSION_6_5MS 0x4 |
59 | #define OPT4001_CTRL_CONVERSION_12_7MS 0x5 |
60 | #define OPT4001_CTRL_CONVERSION_25MS 0x6 |
61 | #define OPT4001_CTRL_CONVERSION_50MS 0x7 |
62 | #define OPT4001_CTRL_CONVERSION_100MS 0x8 |
63 | #define OPT4001_CTRL_CONVERSION_200MS 0x9 |
64 | #define OPT4001_CTRL_CONVERSION_400MS 0xa |
65 | #define OPT4001_CTRL_CONVERSION_800MS 0xb |
66 | |
67 | /* OPT4001 scale light level range definitions */ |
68 | #define OPT4001_CTRL_LIGHT_SCALE_AUTO 12 |
69 | |
70 | /* OPT4001 default values */ |
71 | #define OPT4001_DEFAULT_CONVERSION_TIME OPT4001_CTRL_CONVERSION_800MS |
72 | |
73 | /* |
74 | * The different packaging of OPT4001 has different constants used when calculating |
75 | * lux values. |
76 | */ |
77 | struct opt4001_chip_info { |
78 | int mul; |
79 | int div; |
80 | const char *name; |
81 | }; |
82 | |
83 | struct opt4001_chip { |
84 | struct regmap *regmap; |
85 | struct i2c_client *client; |
86 | u8 int_time; |
87 | const struct opt4001_chip_info *chip_info; |
88 | }; |
89 | |
90 | static const struct opt4001_chip_info opt4001_sot_5x3_info = { |
91 | .mul = 4375, |
92 | .div = 10000000, |
93 | .name = "opt4001-sot-5x3" |
94 | }; |
95 | |
96 | static const struct opt4001_chip_info opt4001_picostar_info = { |
97 | .mul = 3125, |
98 | .div = 10000000, |
99 | .name = "opt4001-picostar" |
100 | }; |
101 | |
102 | static const int opt4001_int_time_available[][2] = { |
103 | { 0, 600 }, |
104 | { 0, 1000 }, |
105 | { 0, 1800 }, |
106 | { 0, 3400 }, |
107 | { 0, 6500 }, |
108 | { 0, 12700 }, |
109 | { 0, 25000 }, |
110 | { 0, 50000 }, |
111 | { 0, 100000 }, |
112 | { 0, 200000 }, |
113 | { 0, 400000 }, |
114 | { 0, 800000 }, |
115 | }; |
116 | |
117 | /* |
118 | * Conversion time is integration time + time to set register |
119 | * this is used as integration time. |
120 | */ |
121 | static const int opt4001_int_time_reg[][2] = { |
122 | { 600, OPT4001_CTRL_CONVERSION_0_6MS }, |
123 | { 1000, OPT4001_CTRL_CONVERSION_1MS }, |
124 | { 1800, OPT4001_CTRL_CONVERSION_1_8MS }, |
125 | { 3400, OPT4001_CTRL_CONVERSION_3_4MS }, |
126 | { 6500, OPT4001_CTRL_CONVERSION_6_5MS }, |
127 | { 12700, OPT4001_CTRL_CONVERSION_12_7MS }, |
128 | { 25000, OPT4001_CTRL_CONVERSION_25MS }, |
129 | { 50000, OPT4001_CTRL_CONVERSION_50MS }, |
130 | { 100000, OPT4001_CTRL_CONVERSION_100MS }, |
131 | { 200000, OPT4001_CTRL_CONVERSION_200MS }, |
132 | { 400000, OPT4001_CTRL_CONVERSION_400MS }, |
133 | { 800000, OPT4001_CTRL_CONVERSION_800MS }, |
134 | }; |
135 | |
136 | static int opt4001_als_time_to_index(const u32 als_integration_time) |
137 | { |
138 | int i; |
139 | |
140 | for (i = 0; i < ARRAY_SIZE(opt4001_int_time_available); i++) { |
141 | if (als_integration_time == opt4001_int_time_available[i][1]) |
142 | return i; |
143 | } |
144 | |
145 | return -EINVAL; |
146 | } |
147 | |
148 | static u8 opt4001_calculate_crc(u8 exp, u32 mantissa, u8 count) |
149 | { |
150 | u8 crc; |
151 | |
152 | crc = (hweight32(mantissa) + hweight32(exp) + hweight32(count)) % 2; |
153 | crc |= ((hweight32(mantissa & 0xAAAAA) + hweight32(exp & 0xA) |
154 | + hweight32(count & 0xA)) % 2) << 1; |
155 | crc |= ((hweight32(mantissa & 0x88888) + hweight32(exp & 0x8) |
156 | + hweight32(count & 0x8)) % 2) << 2; |
157 | crc |= (hweight32(mantissa & 0x80808) % 2) << 3; |
158 | |
159 | return crc; |
160 | } |
161 | |
162 | static int opt4001_read_lux_value(struct iio_dev *indio_dev, |
163 | int *val, int *val2) |
164 | { |
165 | struct opt4001_chip *chip = iio_priv(indio_dev); |
166 | struct device *dev = &chip->client->dev; |
167 | unsigned int light1; |
168 | unsigned int light2; |
169 | u16 msb; |
170 | u16 lsb; |
171 | u8 exp; |
172 | u8 count; |
173 | u8 crc; |
174 | u8 calc_crc; |
175 | u64 lux_raw; |
176 | int ret; |
177 | |
178 | ret = regmap_read(map: chip->regmap, OPT4001_LIGHT1_MSB, val: &light1); |
179 | if (ret < 0) { |
180 | dev_err(dev, "Failed to read data bytes" ); |
181 | return ret; |
182 | } |
183 | |
184 | ret = regmap_read(map: chip->regmap, OPT4001_LIGHT1_LSB, val: &light2); |
185 | if (ret < 0) { |
186 | dev_err(dev, "Failed to read data bytes" ); |
187 | return ret; |
188 | } |
189 | |
190 | count = FIELD_GET(OPT4001_COUNTER_MASK, light2); |
191 | exp = FIELD_GET(OPT4001_EXPONENT_MASK, light1); |
192 | crc = FIELD_GET(OPT4001_CRC_MASK, light2); |
193 | msb = FIELD_GET(OPT4001_MSB_MASK, light1); |
194 | lsb = FIELD_GET(OPT4001_LSB_MASK, light2); |
195 | lux_raw = (msb << 8) + lsb; |
196 | calc_crc = opt4001_calculate_crc(exp, mantissa: lux_raw, count); |
197 | if (calc_crc != crc) |
198 | return -EIO; |
199 | |
200 | lux_raw = lux_raw << exp; |
201 | lux_raw = lux_raw * chip->chip_info->mul; |
202 | *val = div_u64_rem(dividend: lux_raw, divisor: chip->chip_info->div, remainder: val2); |
203 | *val2 = *val2 * 100; |
204 | |
205 | return IIO_VAL_INT_PLUS_NANO; |
206 | } |
207 | |
208 | static int opt4001_set_conf(struct opt4001_chip *chip) |
209 | { |
210 | struct device *dev = &chip->client->dev; |
211 | u16 reg; |
212 | int ret; |
213 | |
214 | reg = FIELD_PREP(OPT4001_CTRL_RANGE_MASK, OPT4001_CTRL_LIGHT_SCALE_AUTO); |
215 | reg |= FIELD_PREP(OPT4001_CTRL_CONV_TIME_MASK, chip->int_time); |
216 | reg |= FIELD_PREP(OPT4001_CTRL_OPER_MODE_MASK, OPT4001_CTRL_OPER_MODE_CONTINUOUS); |
217 | |
218 | ret = regmap_write(map: chip->regmap, OPT4001_CTRL, val: reg); |
219 | if (ret) |
220 | dev_err(dev, "Failed to set configuration\n" ); |
221 | |
222 | return ret; |
223 | } |
224 | |
225 | static int opt4001_power_down(struct opt4001_chip *chip) |
226 | { |
227 | struct device *dev = &chip->client->dev; |
228 | int ret; |
229 | unsigned int reg; |
230 | |
231 | ret = regmap_read(map: chip->regmap, OPT4001_DEVICE_ID, val: ®); |
232 | if (ret) { |
233 | dev_err(dev, "Failed to read configuration\n" ); |
234 | return ret; |
235 | } |
236 | |
237 | /* MODE_OFF is 0x0 so just set bits to 0 */ |
238 | reg &= ~OPT4001_CTRL_OPER_MODE_MASK; |
239 | |
240 | ret = regmap_write(map: chip->regmap, OPT4001_CTRL, val: reg); |
241 | if (ret) |
242 | dev_err(dev, "Failed to set configuration to power down\n" ); |
243 | |
244 | return ret; |
245 | } |
246 | |
247 | static void opt4001_chip_off_action(void *data) |
248 | { |
249 | struct opt4001_chip *chip = data; |
250 | |
251 | opt4001_power_down(chip); |
252 | } |
253 | |
254 | static const struct iio_chan_spec opt4001_channels[] = { |
255 | { |
256 | .type = IIO_LIGHT, |
257 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), |
258 | .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), |
259 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
260 | }, |
261 | }; |
262 | |
263 | static int opt4001_read_raw(struct iio_dev *indio_dev, |
264 | struct iio_chan_spec const *chan, |
265 | int *val, int *val2, long mask) |
266 | { |
267 | struct opt4001_chip *chip = iio_priv(indio_dev); |
268 | |
269 | switch (mask) { |
270 | case IIO_CHAN_INFO_PROCESSED: |
271 | return opt4001_read_lux_value(indio_dev, val, val2); |
272 | case IIO_CHAN_INFO_INT_TIME: |
273 | *val = 0; |
274 | *val2 = opt4001_int_time_reg[chip->int_time][0]; |
275 | return IIO_VAL_INT_PLUS_MICRO; |
276 | default: |
277 | return -EINVAL; |
278 | } |
279 | } |
280 | |
281 | static int opt4001_write_raw(struct iio_dev *indio_dev, |
282 | struct iio_chan_spec const *chan, |
283 | int val, int val2, long mask) |
284 | { |
285 | struct opt4001_chip *chip = iio_priv(indio_dev); |
286 | int int_time; |
287 | |
288 | switch (mask) { |
289 | case IIO_CHAN_INFO_INT_TIME: |
290 | int_time = opt4001_als_time_to_index(als_integration_time: val2); |
291 | if (int_time < 0) |
292 | return int_time; |
293 | chip->int_time = int_time; |
294 | return opt4001_set_conf(chip); |
295 | default: |
296 | return -EINVAL; |
297 | } |
298 | } |
299 | |
300 | static int opt4001_read_available(struct iio_dev *indio_dev, |
301 | struct iio_chan_spec const *chan, |
302 | const int **vals, int *type, int *length, |
303 | long mask) |
304 | { |
305 | switch (mask) { |
306 | case IIO_CHAN_INFO_INT_TIME: |
307 | *length = ARRAY_SIZE(opt4001_int_time_available) * 2; |
308 | *vals = (const int *)opt4001_int_time_available; |
309 | *type = IIO_VAL_INT_PLUS_MICRO; |
310 | return IIO_AVAIL_LIST; |
311 | |
312 | default: |
313 | return -EINVAL; |
314 | } |
315 | } |
316 | |
317 | static const struct iio_info opt4001_info_no_irq = { |
318 | .read_raw = opt4001_read_raw, |
319 | .write_raw = opt4001_write_raw, |
320 | .read_avail = opt4001_read_available, |
321 | }; |
322 | |
323 | static int opt4001_load_defaults(struct opt4001_chip *chip) |
324 | { |
325 | chip->int_time = OPT4001_DEFAULT_CONVERSION_TIME; |
326 | |
327 | return opt4001_set_conf(chip); |
328 | } |
329 | |
330 | static bool opt4001_readable_reg(struct device *dev, unsigned int reg) |
331 | { |
332 | switch (reg) { |
333 | case OPT4001_LIGHT1_MSB: |
334 | case OPT4001_LIGHT1_LSB: |
335 | case OPT4001_CTRL: |
336 | case OPT4001_DEVICE_ID: |
337 | return true; |
338 | default: |
339 | return false; |
340 | } |
341 | } |
342 | |
343 | static bool opt4001_writable_reg(struct device *dev, unsigned int reg) |
344 | { |
345 | switch (reg) { |
346 | case OPT4001_CTRL: |
347 | return true; |
348 | default: |
349 | return false; |
350 | } |
351 | } |
352 | |
353 | static bool opt4001_volatile_reg(struct device *dev, unsigned int reg) |
354 | { |
355 | switch (reg) { |
356 | case OPT4001_LIGHT1_MSB: |
357 | case OPT4001_LIGHT1_LSB: |
358 | return true; |
359 | default: |
360 | return false; |
361 | } |
362 | } |
363 | |
364 | static const struct regmap_config opt4001_regmap_config = { |
365 | .name = "opt4001" , |
366 | .reg_bits = 8, |
367 | .val_bits = 16, |
368 | .cache_type = REGCACHE_RBTREE, |
369 | .max_register = OPT4001_DEVICE_ID, |
370 | .readable_reg = opt4001_readable_reg, |
371 | .writeable_reg = opt4001_writable_reg, |
372 | .volatile_reg = opt4001_volatile_reg, |
373 | .val_format_endian = REGMAP_ENDIAN_BIG, |
374 | }; |
375 | |
376 | static int opt4001_probe(struct i2c_client *client) |
377 | { |
378 | struct opt4001_chip *chip; |
379 | struct iio_dev *indio_dev; |
380 | int ret; |
381 | uint dev_id; |
382 | |
383 | indio_dev = devm_iio_device_alloc(parent: &client->dev, sizeof_priv: sizeof(*chip)); |
384 | if (!indio_dev) |
385 | return -ENOMEM; |
386 | |
387 | chip = iio_priv(indio_dev); |
388 | |
389 | ret = devm_regulator_get_enable(dev: &client->dev, id: "vdd" ); |
390 | if (ret) |
391 | return dev_err_probe(dev: &client->dev, err: ret, fmt: "Failed to enable vdd supply\n" ); |
392 | |
393 | chip->regmap = devm_regmap_init_i2c(client, &opt4001_regmap_config); |
394 | if (IS_ERR(ptr: chip->regmap)) |
395 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: chip->regmap), |
396 | fmt: "regmap initialization failed\n" ); |
397 | chip->client = client; |
398 | |
399 | indio_dev->info = &opt4001_info_no_irq; |
400 | |
401 | ret = regmap_reinit_cache(map: chip->regmap, config: &opt4001_regmap_config); |
402 | if (ret) |
403 | return dev_err_probe(dev: &client->dev, err: ret, |
404 | fmt: "failed to reinit regmap cache\n" ); |
405 | |
406 | ret = regmap_read(map: chip->regmap, OPT4001_DEVICE_ID, val: &dev_id); |
407 | if (ret < 0) |
408 | return dev_err_probe(dev: &client->dev, err: ret, |
409 | fmt: "Failed to read the device ID register\n" ); |
410 | |
411 | dev_id = FIELD_GET(OPT4001_DEVICE_ID_MASK, dev_id); |
412 | if (dev_id != OPT4001_DEVICE_ID_VAL) |
413 | dev_warn(&client->dev, "Device ID: %#04x unknown\n" , dev_id); |
414 | |
415 | chip->chip_info = i2c_get_match_data(client); |
416 | |
417 | indio_dev->channels = opt4001_channels; |
418 | indio_dev->num_channels = ARRAY_SIZE(opt4001_channels); |
419 | indio_dev->modes = INDIO_DIRECT_MODE; |
420 | indio_dev->name = chip->chip_info->name; |
421 | |
422 | ret = opt4001_load_defaults(chip); |
423 | if (ret < 0) |
424 | return dev_err_probe(dev: &client->dev, err: ret, |
425 | fmt: "Failed to set sensor defaults\n" ); |
426 | |
427 | ret = devm_add_action_or_reset(&client->dev, |
428 | opt4001_chip_off_action, |
429 | chip); |
430 | if (ret < 0) |
431 | return dev_err_probe(dev: &client->dev, err: ret, |
432 | fmt: "Failed to setup power off action\n" ); |
433 | |
434 | return devm_iio_device_register(&client->dev, indio_dev); |
435 | } |
436 | |
437 | /* |
438 | * The compatible string determines which constants to use depending on |
439 | * opt4001 packaging |
440 | */ |
441 | static const struct i2c_device_id opt4001_id[] = { |
442 | { "opt4001-sot-5x3" , (kernel_ulong_t)&opt4001_sot_5x3_info }, |
443 | { "opt4001-picostar" , (kernel_ulong_t)&opt4001_picostar_info }, |
444 | { } |
445 | }; |
446 | MODULE_DEVICE_TABLE(i2c, opt4001_id); |
447 | |
448 | static const struct of_device_id opt4001_of_match[] = { |
449 | { .compatible = "ti,opt4001-sot-5x3" , .data = &opt4001_sot_5x3_info}, |
450 | { .compatible = "ti,opt4001-picostar" , .data = &opt4001_picostar_info}, |
451 | {} |
452 | }; |
453 | MODULE_DEVICE_TABLE(of, opt4001_of_match); |
454 | |
455 | static struct i2c_driver opt4001_driver = { |
456 | .driver = { |
457 | .name = "opt4001" , |
458 | .of_match_table = opt4001_of_match, |
459 | }, |
460 | .probe = opt4001_probe, |
461 | .id_table = opt4001_id, |
462 | }; |
463 | module_i2c_driver(opt4001_driver); |
464 | |
465 | MODULE_AUTHOR("Stefan Windfeldt-Prytz <stefan.windfeldt-prytz@axis.com>" ); |
466 | MODULE_DESCRIPTION("Texas Instruments opt4001 ambient light sensor driver" ); |
467 | MODULE_LICENSE("GPL" ); |
468 | |