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; 199 200 ret = regmap_read(data->regmap, VEML6075_CMD_CONF, &conf); 201 if (ret < 0) 202 return ret; 203 204 return FIELD_GET(VEML6075_CONF_IT, conf); 205 } 206 207 static int veml6075_read_int_time_ms(struct veml6075_data *data, int *val) 208 { 209 int int_index; 210 211 guard(mutex)(&data->lock); 212 int_index = veml6075_read_int_time_index(data); 213 if (int_index < 0) 214 return int_index; 215 216 *val = veml6075_it_ms[int_index]; 217 218 return IIO_VAL_INT; 219 } 220 221 static int veml6075_get_uvi_micro(struct veml6075_data *data, int uva_comp, 222 int uvb_comp) 223 { 224 int uvia_micro = uva_comp * VEML6075_UVA_RESP; 225 int uvib_micro = uvb_comp * VEML6075_UVB_RESP; 226 int int_index; 227 228 int_index = veml6075_read_int_time_index(data); 229 if (int_index < 0) 230 return int_index; 231 232 switch (int_index) { 233 case VEML6075_IT_50_MS: 234 return uvia_micro + uvib_micro; 235 case VEML6075_IT_100_MS: 236 case VEML6075_IT_200_MS: 237 case VEML6075_IT_400_MS: 238 case VEML6075_IT_800_MS: 239 return (uvia_micro + uvib_micro) / (2 << int_index); 240 default: 241 return -EINVAL; 242 } 243 } 244 245 static int veml6075_read_uvi(struct veml6075_data *data, int *val, int *val2) 246 { 247 int ret, c1, c2, uva, uvb, uvi_micro; 248 249 guard(mutex)(&data->lock); 250 251 ret = veml6075_request_measurement(data); 252 if (ret < 0) 253 return ret; 254 255 ret = veml6075_read_comp(data, &c1, &c2); 256 if (ret < 0) 257 return ret; 258 259 ret = regmap_read(data->regmap, VEML6075_CMD_UVA, &uva); 260 if (ret < 0) 261 return ret; 262 263 ret = regmap_read(data->regmap, VEML6075_CMD_UVB, &uvb); 264 if (ret < 0) 265 return ret; 266 267 uvi_micro = veml6075_get_uvi_micro(data, veml6075_uva_comp(uva, c1, c2), 268 veml6075_uvb_comp(uvb, c1, c2)); 269 if (uvi_micro < 0) 270 return uvi_micro; 271 272 *val = uvi_micro / MICRO; 273 *val2 = uvi_micro % MICRO; 274 275 return IIO_VAL_INT_PLUS_MICRO; 276 } 277 278 static int veml6075_read_responsivity(int chan, int *val, int *val2) 279 { 280 /* scale = 1 / resp */ 281 switch (chan) { 282 case CH_UVA: 283 /* resp = 0.93 c/uW/cm2: scale = 1.75268817 */ 284 *val = 1; 285 *val2 = 75268817; 286 return IIO_VAL_INT_PLUS_NANO; 287 case CH_UVB: 288 /* resp = 2.1 c/uW/cm2: scale = 0.476190476 */ 289 *val = 0; 290 *val2 = 476190476; 291 return IIO_VAL_INT_PLUS_NANO; 292 default: 293 return -EINVAL; 294 } 295 } 296 297 static int veml6075_read_avail(struct iio_dev *indio_dev, 298 struct iio_chan_spec const *chan, 299 const int **vals, int *type, int *length, 300 long mask) 301 { 302 switch (mask) { 303 case IIO_CHAN_INFO_INT_TIME: 304 *length = ARRAY_SIZE(veml6075_it_ms); 305 *vals = veml6075_it_ms; 306 *type = IIO_VAL_INT; 307 return IIO_AVAIL_LIST; 308 309 default: 310 return -EINVAL; 311 } 312 } 313 314 static int veml6075_read_raw(struct iio_dev *indio_dev, 315 struct iio_chan_spec const *chan, 316 int *val, int *val2, long mask) 317 { 318 struct veml6075_data *data = iio_priv(indio_dev); 319 320 switch (mask) { 321 case IIO_CHAN_INFO_RAW: 322 return veml6075_read_uv_direct(data, chan->channel, val); 323 case IIO_CHAN_INFO_PROCESSED: 324 return veml6075_read_uvi(data, val, val2); 325 case IIO_CHAN_INFO_INT_TIME: 326 return veml6075_read_int_time_ms(data, val); 327 case IIO_CHAN_INFO_SCALE: 328 return veml6075_read_responsivity(chan->channel, val, val2); 329 default: 330 return -EINVAL; 331 } 332 } 333 334 static int veml6075_write_int_time_ms(struct veml6075_data *data, int val) 335 { 336 int i = ARRAY_SIZE(veml6075_it_ms); 337 338 guard(mutex)(&data->lock); 339 340 while (i-- > 0) { 341 if (val == veml6075_it_ms[i]) 342 break; 343 } 344 if (i < 0) 345 return -EINVAL; 346 347 return regmap_update_bits(data->regmap, VEML6075_CMD_CONF, 348 VEML6075_CONF_IT, 349 FIELD_PREP(VEML6075_CONF_IT, i)); 350 } 351 352 static int veml6075_write_raw(struct iio_dev *indio_dev, 353 struct iio_chan_spec const *chan, 354 int val, int val2, long mask) 355 { 356 struct veml6075_data *data = iio_priv(indio_dev); 357 358 switch (mask) { 359 case IIO_CHAN_INFO_INT_TIME: 360 return veml6075_write_int_time_ms(data, val); 361 default: 362 return -EINVAL; 363 } 364 } 365 366 static const struct iio_info veml6075_info = { 367 .read_avail = veml6075_read_avail, 368 .read_raw = veml6075_read_raw, 369 .write_raw = veml6075_write_raw, 370 }; 371 372 static bool veml6075_readable_reg(struct device *dev, unsigned int reg) 373 { 374 switch (reg) { 375 case VEML6075_CMD_CONF: 376 case VEML6075_CMD_UVA: 377 case VEML6075_CMD_UVB: 378 case VEML6075_CMD_COMP1: 379 case VEML6075_CMD_COMP2: 380 case VEML6075_CMD_ID: 381 return true; 382 default: 383 return false; 384 } 385 } 386 387 static bool veml6075_writable_reg(struct device *dev, unsigned int reg) 388 { 389 switch (reg) { 390 case VEML6075_CMD_CONF: 391 return true; 392 default: 393 return false; 394 } 395 } 396 397 static const struct regmap_config veml6075_regmap_config = { 398 .name = "veml6075", 399 .reg_bits = 8, 400 .val_bits = 16, 401 .max_register = VEML6075_CMD_ID, 402 .readable_reg = veml6075_readable_reg, 403 .writeable_reg = veml6075_writable_reg, 404 .val_format_endian = REGMAP_ENDIAN_LITTLE, 405 }; 406 407 static int veml6075_probe(struct i2c_client *client) 408 { 409 struct veml6075_data *data; 410 struct iio_dev *indio_dev; 411 struct regmap *regmap; 412 int config, ret; 413 414 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 415 if (!indio_dev) 416 return -ENOMEM; 417 418 regmap = devm_regmap_init_i2c(client, &veml6075_regmap_config); 419 if (IS_ERR(regmap)) 420 return PTR_ERR(regmap); 421 422 data = iio_priv(indio_dev); 423 data->client = client; 424 data->regmap = regmap; 425 426 mutex_init(&data->lock); 427 428 indio_dev->name = "veml6075"; 429 indio_dev->info = &veml6075_info; 430 indio_dev->channels = veml6075_channels; 431 indio_dev->num_channels = ARRAY_SIZE(veml6075_channels); 432 indio_dev->modes = INDIO_DIRECT_MODE; 433 434 ret = devm_regulator_get_enable(&client->dev, "vdd"); 435 if (ret < 0) 436 return ret; 437 438 /* default: 100ms integration time, active force enable, shutdown */ 439 config = FIELD_PREP(VEML6075_CONF_IT, VEML6075_IT_100_MS) | 440 FIELD_PREP(VEML6075_CONF_AF, VEML6075_AF_ENABLE) | 441 FIELD_PREP(VEML6075_CONF_SD, VEML6075_SD_ENABLE); 442 ret = regmap_write(data->regmap, VEML6075_CMD_CONF, config); 443 if (ret < 0) 444 return ret; 445 446 return devm_iio_device_register(&client->dev, indio_dev); 447 } 448 449 static const struct i2c_device_id veml6075_id[] = { 450 { "veml6075" }, 451 { } 452 }; 453 MODULE_DEVICE_TABLE(i2c, veml6075_id); 454 455 static const struct of_device_id veml6075_of_match[] = { 456 { .compatible = "vishay,veml6075" }, 457 {} 458 }; 459 MODULE_DEVICE_TABLE(of, veml6075_of_match); 460 461 static struct i2c_driver veml6075_driver = { 462 .driver = { 463 .name = "veml6075", 464 .of_match_table = veml6075_of_match, 465 }, 466 .probe = veml6075_probe, 467 .id_table = veml6075_id, 468 }; 469 470 module_i2c_driver(veml6075_driver); 471 472 MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>"); 473 MODULE_DESCRIPTION("Vishay VEML6075 UVA and UVB light sensor driver"); 474 MODULE_LICENSE("GPL"); 475