1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * veml6070.c - Support for Vishay VEML6070 UV A light sensor 4 * 5 * Copyright 2016 Peter Meerwald-Stadler <pmeerw@pmeerw.net> 6 * 7 * IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39) 8 * 9 * TODO: ACK signal 10 */ 11 12 #include <linux/bitfield.h> 13 #include <linux/module.h> 14 #include <linux/i2c.h> 15 #include <linux/mutex.h> 16 #include <linux/err.h> 17 #include <linux/delay.h> 18 #include <linux/units.h> 19 20 #include <linux/iio/iio.h> 21 #include <linux/iio/sysfs.h> 22 23 #define VEML6070_DRV_NAME "veml6070" 24 25 #define VEML6070_ADDR_CONFIG_DATA_MSB 0x38 /* read: MSB data, write: config */ 26 #define VEML6070_ADDR_DATA_LSB 0x39 /* LSB data */ 27 28 #define VEML6070_COMMAND_ACK BIT(5) /* raise interrupt when over threshold */ 29 #define VEML6070_COMMAND_IT GENMASK(3, 2) /* bit mask integration time */ 30 #define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */ 31 #define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */ 32 33 #define VEML6070_IT_05 0x00 34 #define VEML6070_IT_10 0x01 35 #define VEML6070_IT_20 0x02 36 #define VEML6070_IT_40 0x03 37 38 #define VEML6070_MIN_RSET_KOHM 75 39 #define VEML6070_MIN_IT_US 15625 /* Rset = 75 kohm, IT = 1/2 */ 40 41 struct veml6070_data { 42 struct i2c_client *client1; 43 struct i2c_client *client2; 44 u8 config; 45 struct mutex lock; 46 u32 rset; 47 int it[4][2]; 48 }; 49 50 static int veml6070_calc_it(struct device *dev, struct veml6070_data *data) 51 { 52 int i, tmp_it; 53 54 data->rset = 270000; 55 device_property_read_u32(dev, "vishay,rset-ohms", &data->rset); 56 57 if (data->rset < 75000 || data->rset > 1200000) 58 return dev_err_probe(dev, -EINVAL, "Rset out of range\n"); 59 60 /* 61 * convert to kohm to avoid overflows and work with the same units as 62 * in the datasheet and simplify UVI operations. 63 */ 64 data->rset /= KILO; 65 66 tmp_it = VEML6070_MIN_IT_US * data->rset / VEML6070_MIN_RSET_KOHM; 67 for (i = 0; i < ARRAY_SIZE(data->it); i++) { 68 data->it[i][0] = (tmp_it << i) / MICRO; 69 data->it[i][1] = (tmp_it << i) % MICRO; 70 } 71 72 return 0; 73 } 74 75 static int veml6070_get_it(struct veml6070_data *data, int *val, int *val2) 76 { 77 int it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config); 78 79 *val = data->it[it_idx][0]; 80 *val2 = data->it[it_idx][1]; 81 82 return IIO_VAL_INT_PLUS_MICRO; 83 } 84 85 static int veml6070_set_it(struct veml6070_data *data, int val, int val2) 86 { 87 int it_idx; 88 89 for (it_idx = 0; it_idx < ARRAY_SIZE(data->it); it_idx++) { 90 if (data->it[it_idx][0] == val && data->it[it_idx][1] == val2) 91 break; 92 } 93 94 if (it_idx >= ARRAY_SIZE(data->it)) 95 return -EINVAL; 96 97 data->config = (data->config & ~VEML6070_COMMAND_IT) | 98 FIELD_PREP(VEML6070_COMMAND_IT, it_idx); 99 100 return i2c_smbus_write_byte(data->client1, data->config); 101 } 102 103 static int veml6070_read(struct veml6070_data *data) 104 { 105 int ret, it_ms, val, val2; 106 u8 msb, lsb; 107 108 guard(mutex)(&data->lock); 109 110 /* disable shutdown */ 111 ret = i2c_smbus_write_byte(data->client1, 112 data->config & ~VEML6070_COMMAND_SD); 113 if (ret < 0) 114 return ret; 115 116 veml6070_get_it(data, &val, &val2); 117 it_ms = val * MILLI + val2 / (MICRO / MILLI); 118 msleep(it_ms + 10); 119 120 ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */ 121 if (ret < 0) 122 return ret; 123 124 msb = ret; 125 126 ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */ 127 if (ret < 0) 128 return ret; 129 130 lsb = ret; 131 132 /* shutdown again */ 133 ret = i2c_smbus_write_byte(data->client1, data->config); 134 if (ret < 0) 135 return ret; 136 137 return (msb << 8) | lsb; 138 } 139 140 static const struct iio_chan_spec veml6070_channels[] = { 141 { 142 .type = IIO_INTENSITY, 143 .modified = 1, 144 .channel2 = IIO_MOD_LIGHT_UV, 145 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 146 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 147 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), 148 }, 149 { 150 .type = IIO_UVINDEX, 151 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 152 .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME), 153 .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME), 154 } 155 }; 156 157 static int veml6070_to_uv_index(struct veml6070_data *data, unsigned int val) 158 { 159 /* 160 * conversion of raw UV intensity values to UV index depends on 161 * integration time (IT) and value of the resistor connected to 162 * the RSET pin. 163 */ 164 unsigned int uvi[11] = { 165 187, 373, 560, /* low */ 166 746, 933, 1120, /* moderate */ 167 1308, 1494, /* high */ 168 1681, 1868, 2054}; /* very high */ 169 int i, it_idx; 170 171 it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config); 172 173 if (!it_idx) 174 val = (val * 270 / data->rset) << 1; 175 else 176 val = (val * 270 / data->rset) >> (it_idx - 1); 177 178 for (i = 0; i < ARRAY_SIZE(uvi); i++) 179 if (val <= uvi[i]) 180 return i; 181 182 return 11; /* extreme */ 183 } 184 185 static int veml6070_read_raw(struct iio_dev *indio_dev, 186 struct iio_chan_spec const *chan, 187 int *val, int *val2, long mask) 188 { 189 struct veml6070_data *data = iio_priv(indio_dev); 190 int ret; 191 192 switch (mask) { 193 case IIO_CHAN_INFO_RAW: 194 case IIO_CHAN_INFO_PROCESSED: 195 ret = veml6070_read(data); 196 if (ret < 0) 197 return ret; 198 if (mask == IIO_CHAN_INFO_PROCESSED) 199 *val = veml6070_to_uv_index(data, ret); 200 else 201 *val = ret; 202 return IIO_VAL_INT; 203 case IIO_CHAN_INFO_INT_TIME: 204 return veml6070_get_it(data, val, val2); 205 default: 206 return -EINVAL; 207 } 208 } 209 210 static int veml6070_read_avail(struct iio_dev *indio_dev, 211 struct iio_chan_spec const *chan, 212 const int **vals, int *type, int *length, 213 long mask) 214 { 215 struct veml6070_data *data = iio_priv(indio_dev); 216 217 switch (mask) { 218 case IIO_CHAN_INFO_INT_TIME: 219 *vals = (int *)data->it; 220 *length = 2 * ARRAY_SIZE(data->it); 221 *type = IIO_VAL_INT_PLUS_MICRO; 222 return IIO_AVAIL_LIST; 223 default: 224 return -EINVAL; 225 } 226 } 227 228 static int veml6070_write_raw(struct iio_dev *indio_dev, 229 struct iio_chan_spec const *chan, 230 int val, int val2, long mask) 231 { 232 struct veml6070_data *data = iio_priv(indio_dev); 233 234 switch (mask) { 235 case IIO_CHAN_INFO_INT_TIME: 236 return veml6070_set_it(data, val, val2); 237 default: 238 return -EINVAL; 239 } 240 } 241 242 static const struct iio_info veml6070_info = { 243 .read_raw = veml6070_read_raw, 244 .read_avail = veml6070_read_avail, 245 .write_raw = veml6070_write_raw, 246 }; 247 248 static void veml6070_i2c_unreg(void *p) 249 { 250 struct veml6070_data *data = p; 251 252 i2c_unregister_device(data->client2); 253 } 254 255 static int veml6070_probe(struct i2c_client *client) 256 { 257 struct veml6070_data *data; 258 struct iio_dev *indio_dev; 259 int ret; 260 261 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 262 if (!indio_dev) 263 return -ENOMEM; 264 265 data = iio_priv(indio_dev); 266 i2c_set_clientdata(client, indio_dev); 267 data->client1 = client; 268 mutex_init(&data->lock); 269 270 indio_dev->info = &veml6070_info; 271 indio_dev->channels = veml6070_channels; 272 indio_dev->num_channels = ARRAY_SIZE(veml6070_channels); 273 indio_dev->name = VEML6070_DRV_NAME; 274 indio_dev->modes = INDIO_DIRECT_MODE; 275 276 ret = veml6070_calc_it(&client->dev, data); 277 if (ret < 0) 278 return ret; 279 280 ret = devm_regulator_get_enable(&client->dev, "vdd"); 281 if (ret < 0) 282 return ret; 283 284 data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB); 285 if (IS_ERR(data->client2)) 286 return dev_err_probe(&client->dev, PTR_ERR(data->client2), 287 "i2c device for second chip address failed\n"); 288 289 data->config = FIELD_PREP(VEML6070_COMMAND_IT, VEML6070_IT_10) | 290 VEML6070_COMMAND_RSRVD | VEML6070_COMMAND_SD; 291 ret = i2c_smbus_write_byte(data->client1, data->config); 292 if (ret < 0) 293 return ret; 294 295 ret = devm_add_action_or_reset(&client->dev, veml6070_i2c_unreg, data); 296 if (ret < 0) 297 return ret; 298 299 return devm_iio_device_register(&client->dev, indio_dev); 300 } 301 302 static const struct i2c_device_id veml6070_id[] = { 303 { "veml6070" }, 304 { } 305 }; 306 MODULE_DEVICE_TABLE(i2c, veml6070_id); 307 308 static const struct of_device_id veml6070_of_match[] = { 309 { .compatible = "vishay,veml6070" }, 310 { } 311 }; 312 MODULE_DEVICE_TABLE(of, veml6070_of_match); 313 314 static struct i2c_driver veml6070_driver = { 315 .driver = { 316 .name = VEML6070_DRV_NAME, 317 .of_match_table = veml6070_of_match, 318 }, 319 .probe = veml6070_probe, 320 .id_table = veml6070_id, 321 }; 322 323 module_i2c_driver(veml6070_driver); 324 325 MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>"); 326 MODULE_DESCRIPTION("Vishay VEML6070 UV A light sensor driver"); 327 MODULE_LICENSE("GPL"); 328