1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Vishay VEML6075 UVA and UVB light sensor 4 * 5 * Copyright 2023 Javier Carrasco <javier.carrasco.cruz@gmail.com> 6 * 7 * 7-bit I2C slave, address 0x10 8 */ 9 10 #include <linux/bitfield.h> 11 #include <linux/delay.h> 12 #include <linux/err.h> 13 #include <linux/i2c.h> 14 #include <linux/module.h> 15 #include <linux/mutex.h> 16 #include <linux/regmap.h> 17 #include <linux/units.h> 18 19 #include <linux/iio/iio.h> 20 21 #define VEML6075_CMD_CONF 0x00 /* configuration register */ 22 #define VEML6075_CMD_UVA 0x07 /* UVA channel */ 23 #define VEML6075_CMD_UVB 0x09 /* UVB channel */ 24 #define VEML6075_CMD_COMP1 0x0A /* visible light compensation */ 25 #define VEML6075_CMD_COMP2 0x0B /* infrarred light compensation */ 26 #define VEML6075_CMD_ID 0x0C /* device ID */ 27 28 #define VEML6075_CONF_IT GENMASK(6, 4) /* intregration time */ 29 #define VEML6075_CONF_HD BIT(3) /* dynamic setting */ 30 #define VEML6075_CONF_TRIG BIT(2) /* trigger */ 31 #define VEML6075_CONF_AF BIT(1) /* active force enable */ 32 #define VEML6075_CONF_SD BIT(0) /* shutdown */ 33 34 #define VEML6075_IT_50_MS 0x00 35 #define VEML6075_IT_100_MS 0x01 36 #define VEML6075_IT_200_MS 0x02 37 #define VEML6075_IT_400_MS 0x03 38 #define VEML6075_IT_800_MS 0x04 39 40 #define VEML6075_AF_DISABLE 0x00 41 #define VEML6075_AF_ENABLE 0x01 42 43 #define VEML6075_SD_DISABLE 0x00 44 #define VEML6075_SD_ENABLE 0x01 45 46 /* Open-air coefficients and responsivity */ 47 #define VEML6075_A_COEF 2220 48 #define VEML6075_B_COEF 1330 49 #define VEML6075_C_COEF 2950 50 #define VEML6075_D_COEF 1740 51 #define VEML6075_UVA_RESP 1461 52 #define VEML6075_UVB_RESP 2591 53 54 static const int veml6075_it_ms[] = { 50, 100, 200, 400, 800 }; 55 56 struct veml6075_data { 57 struct i2c_client *client; 58 struct regmap *regmap; 59 /* 60 * prevent integration time modification and triggering 61 * measurements while a measurement is underway. 62 */ 63 struct mutex lock; 64 }; 65 66 /* channel number */ 67 enum veml6075_chan { 68 CH_UVA, 69 CH_UVB, 70 }; 71 72 static const struct iio_chan_spec veml6075_channels[] = { 73 { 74 .type = IIO_INTENSITY, 75 .channel = CH_UVA, 76 .modified = 1, 77 .channel2 = IIO_MOD_LIGHT_UVA, 78 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 79 BIT(IIO_CHAN_INFO_SCALE), 80 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 81 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), 82 }, 83 { 84 .type = IIO_INTENSITY, 85 .channel = CH_UVB, 86 .modified = 1, 87 .channel2 = IIO_MOD_LIGHT_UVB, 88 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 89 BIT(IIO_CHAN_INFO_SCALE), 90 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 91 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), 92 }, 93 { 94 .type = IIO_UVINDEX, 95 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 96 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 97 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), 98 }, 99 }; 100 101 static int veml6075_request_measurement(struct veml6075_data *data) 102 { 103 int ret, conf, int_time; 104 105 ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); 106 if (ret < 0) 107 return ret; 108 109 /* disable shutdown and trigger measurement */ 110 ret = regmap_write(data->regmap, VEML6075_CMD_CONF, 111 (conf | VEML6075_CONF_TRIG) & ~VEML6075_CONF_SD); 112 if (ret < 0) 113 return ret; 114 115 /* 116 * A measurement requires between 1.30 and 1.40 times the integration 117 * time for all possible configurations. Using a 1.50 factor simplifies 118 * operations and ensures reliability under all circumstances. 119 */ 120 int_time = veml6075_it_ms[FIELD_GET(VEML6075_CONF_IT, conf)]; 121 msleep(int_time + (int_time / 2)); 122 123 /* shutdown again, data registers are still accessible */ 124 return regmap_update_bits(data->regmap, VEML6075_CMD_CONF, 125 VEML6075_CONF_SD, VEML6075_CONF_SD); 126 } 127 128 static int veml6075_uva_comp(int raw_uva, int comp1, int comp2) 129 { 130 int comp1a_c, comp2a_c, uva_comp; 131 132 comp1a_c = (comp1 * VEML6075_A_COEF) / 1000U; 133 comp2a_c = (comp2 * VEML6075_B_COEF) / 1000U; 134 uva_comp = raw_uva - comp1a_c - comp2a_c; 135 136 return clamp_val(uva_comp, 0, U16_MAX); 137 } 138 139 static int veml6075_uvb_comp(int raw_uvb, int comp1, int comp2) 140 { 141 int comp1b_c, comp2b_c, uvb_comp; 142 143 comp1b_c = (comp1 * VEML6075_C_COEF) / 1000U; 144 comp2b_c = (comp2 * VEML6075_D_COEF) / 1000U; 145 uvb_comp = raw_uvb - comp1b_c - comp2b_c; 146 147 return clamp_val(uvb_comp, 0, U16_MAX); 148 } 149 150 static int veml6075_read_comp(struct veml6075_data *data, int *c1, int *c2) 151 { 152 int ret; 153 154 ret = regmap_read(data->regmap, VEML6075_CMD_COMP1, c1); 155 if (ret < 0) 156 return ret; 157 158 return regmap_read(data->regmap, VEML6075_CMD_COMP2, c2); 159 } 160 161 static int veml6075_read_uv_direct(struct veml6075_data *data, int chan, 162 int *val) 163 { 164 int c1, c2, ret; 165 166 guard(mutex)(&data->lock); 167 168 ret = veml6075_request_measurement(data); 169 if (ret < 0) 170 return ret; 171 172 ret = veml6075_read_comp(data, &c1, &c2); 173 if (ret < 0) 174 return ret; 175 176 switch (chan) { 177 case CH_UVA: 178 ret = regmap_read(data->regmap, VEML6075_CMD_UVA, val); 179 if (ret < 0) 180 return ret; 181 182 *val = veml6075_uva_comp(*val, c1, c2); 183 return IIO_VAL_INT; 184 case CH_UVB: 185 ret = regmap_read(data->regmap, VEML6075_CMD_UVB, val); 186 if (ret < 0) 187 return ret; 188 189 *val = veml6075_uvb_comp(*val, c1, c2); 190 return IIO_VAL_INT; 191 default: 192 return -EINVAL; 193 } 194 } 195 196 static int veml6075_read_int_time_index(struct veml6075_data *data) 197 { 198 int ret, conf, int_index; 199 200 ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); 201 if (ret < 0) 202 return ret; 203 204 int_index = FIELD_GET(VEML6075_CONF_IT, conf); 205 if (int_index >= ARRAY_SIZE(veml6075_it_ms)) 206 return -EINVAL; 207 208 return int_index; 209 } 210 211 static int veml6075_read_int_time_ms(struct veml6075_data *data, int *val) 212 { 213 int int_index; 214 215 guard(mutex)(&data->lock); 216 int_index = veml6075_read_int_time_index(data); 217 if (int_index < 0) 218 return int_index; 219 220 *val = veml6075_it_ms[int_index]; 221 222 return IIO_VAL_INT; 223 } 224 225 static int veml6075_get_uvi_micro(struct veml6075_data *data, int uva_comp, 226 int uvb_comp) 227 { 228 int uvia_micro = uva_comp * VEML6075_UVA_RESP; 229 int uvib_micro = uvb_comp * VEML6075_UVB_RESP; 230 int int_index; 231 232 int_index = veml6075_read_int_time_index(data); 233 if (int_index < 0) 234 return int_index; 235 236 switch (int_index) { 237 case VEML6075_IT_50_MS: 238 return uvia_micro + uvib_micro; 239 case VEML6075_IT_100_MS: 240 case VEML6075_IT_200_MS: 241 case VEML6075_IT_400_MS: 242 case VEML6075_IT_800_MS: 243 return (uvia_micro + uvib_micro) / (2 << int_index); 244 default: 245 return -EINVAL; 246 } 247 } 248 249 static int veml6075_read_uvi(struct veml6075_data *data, int *val, int *val2) 250 { 251 int ret, c1, c2, uva, uvb, uvi_micro; 252 253 guard(mutex)(&data->lock); 254 255 ret = veml6075_request_measurement(data); 256 if (ret < 0) 257 return ret; 258 259 ret = veml6075_read_comp(data, &c1, &c2); 260 if (ret < 0) 261 return ret; 262 263 ret = regmap_read(data->regmap, VEML6075_CMD_UVA, &uva); 264 if (ret < 0) 265 return ret; 266 267 ret = regmap_read(data->regmap, VEML6075_CMD_UVB, &uvb); 268 if (ret < 0) 269 return ret; 270 271 uvi_micro = veml6075_get_uvi_micro(data, veml6075_uva_comp(uva, c1, c2), 272 veml6075_uvb_comp(uvb, c1, c2)); 273 if (uvi_micro < 0) 274 return uvi_micro; 275 276 *val = uvi_micro / MICRO; 277 *val2 = uvi_micro % MICRO; 278 279 return IIO_VAL_INT_PLUS_MICRO; 280 } 281 282 static int veml6075_read_responsivity(int chan, int *val, int *val2) 283 { 284 /* scale = 1 / resp */ 285 switch (chan) { 286 case CH_UVA: 287 /* resp = 0.93 c/uW/cm2: scale = 1.75268817 */ 288 *val = 1; 289 *val2 = 75268817; 290 return IIO_VAL_INT_PLUS_NANO; 291 case CH_UVB: 292 /* resp = 2.1 c/uW/cm2: scale = 0.476190476 */ 293 *val = 0; 294 *val2 = 476190476; 295 return IIO_VAL_INT_PLUS_NANO; 296 default: 297 return -EINVAL; 298 } 299 } 300 301 static int veml6075_read_avail(struct iio_dev *indio_dev, 302 struct iio_chan_spec const *chan, 303 const int **vals, int *type, int *length, 304 long mask) 305 { 306 switch (mask) { 307 case IIO_CHAN_INFO_INT_TIME: 308 *length = ARRAY_SIZE(veml6075_it_ms); 309 *vals = veml6075_it_ms; 310 *type = IIO_VAL_INT; 311 return IIO_AVAIL_LIST; 312 313 default: 314 return -EINVAL; 315 } 316 } 317 318 static int veml6075_read_raw(struct iio_dev *indio_dev, 319 struct iio_chan_spec const *chan, 320 int *val, int *val2, long mask) 321 { 322 struct veml6075_data *data = iio_priv(indio_dev); 323 324 switch (mask) { 325 case IIO_CHAN_INFO_RAW: 326 return veml6075_read_uv_direct(data, chan->channel, val); 327 case IIO_CHAN_INFO_PROCESSED: 328 return veml6075_read_uvi(data, val, val2); 329 case IIO_CHAN_INFO_INT_TIME: 330 return veml6075_read_int_time_ms(data, val); 331 case IIO_CHAN_INFO_SCALE: 332 return veml6075_read_responsivity(chan->channel, val, val2); 333 default: 334 return -EINVAL; 335 } 336 } 337 338 static int veml6075_write_int_time_ms(struct veml6075_data *data, int val) 339 { 340 int i = ARRAY_SIZE(veml6075_it_ms); 341 342 guard(mutex)(&data->lock); 343 344 while (i-- > 0) { 345 if (val == veml6075_it_ms[i]) 346 break; 347 } 348 if (i < 0) 349 return -EINVAL; 350 351 return regmap_update_bits(data->regmap, VEML6075_CMD_CONF, 352 VEML6075_CONF_IT, 353 FIELD_PREP(VEML6075_CONF_IT, i)); 354 } 355 356 static int veml6075_write_raw(struct iio_dev *indio_dev, 357 struct iio_chan_spec const *chan, 358 int val, int val2, long mask) 359 { 360 struct veml6075_data *data = iio_priv(indio_dev); 361 362 switch (mask) { 363 case IIO_CHAN_INFO_INT_TIME: 364 return veml6075_write_int_time_ms(data, val); 365 default: 366 return -EINVAL; 367 } 368 } 369 370 static const struct iio_info veml6075_info = { 371 .read_avail = veml6075_read_avail, 372 .read_raw = veml6075_read_raw, 373 .write_raw = veml6075_write_raw, 374 }; 375 376 static bool veml6075_readable_reg(struct device *dev, unsigned int reg) 377 { 378 switch (reg) { 379 case VEML6075_CMD_CONF: 380 case VEML6075_CMD_UVA: 381 case VEML6075_CMD_UVB: 382 case VEML6075_CMD_COMP1: 383 case VEML6075_CMD_COMP2: 384 case VEML6075_CMD_ID: 385 return true; 386 default: 387 return false; 388 } 389 } 390 391 static bool veml6075_writable_reg(struct device *dev, unsigned int reg) 392 { 393 switch (reg) { 394 case VEML6075_CMD_CONF: 395 return true; 396 default: 397 return false; 398 } 399 } 400 401 static const struct regmap_config veml6075_regmap_config = { 402 .name = "veml6075", 403 .reg_bits = 8, 404 .val_bits = 16, 405 .max_register = VEML6075_CMD_ID, 406 .readable_reg = veml6075_readable_reg, 407 .writeable_reg = veml6075_writable_reg, 408 .val_format_endian = REGMAP_ENDIAN_LITTLE, 409 }; 410 411 static int veml6075_probe(struct i2c_client *client) 412 { 413 struct veml6075_data *data; 414 struct iio_dev *indio_dev; 415 struct regmap *regmap; 416 int config, ret; 417 418 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 419 if (!indio_dev) 420 return -ENOMEM; 421 422 regmap = devm_regmap_init_i2c(client, &veml6075_regmap_config); 423 if (IS_ERR(regmap)) 424 return PTR_ERR(regmap); 425 426 data = iio_priv(indio_dev); 427 data->client = client; 428 data->regmap = regmap; 429 430 mutex_init(&data->lock); 431 432 indio_dev->name = "veml6075"; 433 indio_dev->info = &veml6075_info; 434 indio_dev->channels = veml6075_channels; 435 indio_dev->num_channels = ARRAY_SIZE(veml6075_channels); 436 indio_dev->modes = INDIO_DIRECT_MODE; 437 438 ret = devm_regulator_get_enable(&client->dev, "vdd"); 439 if (ret < 0) 440 return ret; 441 442 /* default: 100ms integration time, active force enable, shutdown */ 443 config = FIELD_PREP(VEML6075_CONF_IT, VEML6075_IT_100_MS) | 444 FIELD_PREP(VEML6075_CONF_AF, VEML6075_AF_ENABLE) | 445 FIELD_PREP(VEML6075_CONF_SD, VEML6075_SD_ENABLE); 446 ret = regmap_write(data->regmap, VEML6075_CMD_CONF, config); 447 if (ret < 0) 448 return ret; 449 450 return devm_iio_device_register(&client->dev, indio_dev); 451 } 452 453 static const struct i2c_device_id veml6075_id[] = { 454 { "veml6075" }, 455 { } 456 }; 457 MODULE_DEVICE_TABLE(i2c, veml6075_id); 458 459 static const struct of_device_id veml6075_of_match[] = { 460 { .compatible = "vishay,veml6075" }, 461 { } 462 }; 463 MODULE_DEVICE_TABLE(of, veml6075_of_match); 464 465 static struct i2c_driver veml6075_driver = { 466 .driver = { 467 .name = "veml6075", 468 .of_match_table = veml6075_of_match, 469 }, 470 .probe = veml6075_probe, 471 .id_table = veml6075_id, 472 }; 473 474 module_i2c_driver(veml6075_driver); 475 476 MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>"); 477 MODULE_DESCRIPTION("Vishay VEML6075 UVA and UVB light sensor driver"); 478 MODULE_LICENSE("GPL"); 479