902 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * VEML6030 Ambient Light Sensor4 *5 * Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>6 *7 * Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf8 * Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf9 */10 11#include <linux/module.h>12#include <linux/i2c.h>13#include <linux/err.h>14#include <linux/regmap.h>15#include <linux/interrupt.h>16#include <linux/pm_runtime.h>17#include <linux/iio/iio.h>18#include <linux/iio/sysfs.h>19#include <linux/iio/events.h>20 21/* Device registers */22#define VEML6030_REG_ALS_CONF 0x0023#define VEML6030_REG_ALS_WH 0x0124#define VEML6030_REG_ALS_WL 0x0225#define VEML6030_REG_ALS_PSM 0x0326#define VEML6030_REG_ALS_DATA 0x0427#define VEML6030_REG_WH_DATA 0x0528#define VEML6030_REG_ALS_INT 0x0629 30/* Bit masks for specific functionality */31#define VEML6030_ALS_IT GENMASK(9, 6)32#define VEML6030_PSM GENMASK(2, 1)33#define VEML6030_ALS_PERS GENMASK(5, 4)34#define VEML6030_ALS_GAIN GENMASK(12, 11)35#define VEML6030_PSM_EN BIT(0)36#define VEML6030_INT_TH_LOW BIT(15)37#define VEML6030_INT_TH_HIGH BIT(14)38#define VEML6030_ALS_INT_EN BIT(1)39#define VEML6030_ALS_SD BIT(0)40 41/*42 * The resolution depends on both gain and integration time. The43 * cur_resolution stores one of the resolution mentioned in the44 * table during startup and gets updated whenever integration time45 * or gain is changed.46 *47 * Table 'resolution and maximum detection range' in appnote 8436748 * is visualized as a 2D array. The cur_gain stores index of gain49 * in this table (0-3) while the cur_integration_time holds index50 * of integration time (0-5).51 */52struct veml6030_data {53 struct i2c_client *client;54 struct regmap *regmap;55 int cur_resolution;56 int cur_gain;57 int cur_integration_time;58};59 60/* Integration time available in seconds */61static IIO_CONST_ATTR(in_illuminance_integration_time_available,62 "0.025 0.05 0.1 0.2 0.4 0.8");63 64/*65 * Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is66 * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.67 */68static IIO_CONST_ATTR(in_illuminance_scale_available,69 "0.125 0.25 1.0 2.0");70 71static struct attribute *veml6030_attributes[] = {72 &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,73 &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,74 NULL75};76 77static const struct attribute_group veml6030_attr_group = {78 .attrs = veml6030_attributes,79};80 81/*82 * Persistence = 1/2/4/8 x integration time83 * Minimum time for which light readings must stay above configured84 * threshold to assert the interrupt.85 */86static const char * const period_values[] = {87 "0.1 0.2 0.4 0.8",88 "0.2 0.4 0.8 1.6",89 "0.4 0.8 1.6 3.2",90 "0.8 1.6 3.2 6.4",91 "0.05 0.1 0.2 0.4",92 "0.025 0.050 0.1 0.2"93};94 95/*96 * Return list of valid period values in seconds corresponding to97 * the currently active integration time.98 */99static ssize_t in_illuminance_period_available_show(struct device *dev,100 struct device_attribute *attr, char *buf)101{102 struct veml6030_data *data = iio_priv(dev_to_iio_dev(dev));103 int ret, reg, x;104 105 ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);106 if (ret) {107 dev_err(&data->client->dev,108 "can't read als conf register %d\n", ret);109 return ret;110 }111 112 ret = ((reg >> 6) & 0xF);113 switch (ret) {114 case 0:115 case 1:116 case 2:117 case 3:118 x = ret;119 break;120 case 8:121 x = 4;122 break;123 case 12:124 x = 5;125 break;126 default:127 return -EINVAL;128 }129 130 return sysfs_emit(buf, "%s\n", period_values[x]);131}132 133static IIO_DEVICE_ATTR_RO(in_illuminance_period_available, 0);134 135static struct attribute *veml6030_event_attributes[] = {136 &iio_dev_attr_in_illuminance_period_available.dev_attr.attr,137 NULL138};139 140static const struct attribute_group veml6030_event_attr_group = {141 .attrs = veml6030_event_attributes,142};143 144static int veml6030_als_pwr_on(struct veml6030_data *data)145{146 return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,147 VEML6030_ALS_SD);148}149 150static int veml6030_als_shut_down(struct veml6030_data *data)151{152 return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,153 VEML6030_ALS_SD, 1);154}155 156static void veml6030_als_shut_down_action(void *data)157{158 veml6030_als_shut_down(data);159}160 161static const struct iio_event_spec veml6030_event_spec[] = {162 {163 .type = IIO_EV_TYPE_THRESH,164 .dir = IIO_EV_DIR_RISING,165 .mask_separate = BIT(IIO_EV_INFO_VALUE),166 }, {167 .type = IIO_EV_TYPE_THRESH,168 .dir = IIO_EV_DIR_FALLING,169 .mask_separate = BIT(IIO_EV_INFO_VALUE),170 }, {171 .type = IIO_EV_TYPE_THRESH,172 .dir = IIO_EV_DIR_EITHER,173 .mask_separate = BIT(IIO_EV_INFO_PERIOD) |174 BIT(IIO_EV_INFO_ENABLE),175 },176};177 178/* Channel number */179enum veml6030_chan {180 CH_ALS,181 CH_WHITE,182};183 184static const struct iio_chan_spec veml6030_channels[] = {185 {186 .type = IIO_LIGHT,187 .channel = CH_ALS,188 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |189 BIT(IIO_CHAN_INFO_PROCESSED) |190 BIT(IIO_CHAN_INFO_INT_TIME) |191 BIT(IIO_CHAN_INFO_SCALE),192 .event_spec = veml6030_event_spec,193 .num_event_specs = ARRAY_SIZE(veml6030_event_spec),194 },195 {196 .type = IIO_INTENSITY,197 .channel = CH_WHITE,198 .modified = 1,199 .channel2 = IIO_MOD_LIGHT_BOTH,200 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |201 BIT(IIO_CHAN_INFO_PROCESSED),202 },203};204 205static const struct regmap_config veml6030_regmap_config = {206 .name = "veml6030_regmap",207 .reg_bits = 8,208 .val_bits = 16,209 .max_register = VEML6030_REG_ALS_INT,210 .val_format_endian = REGMAP_ENDIAN_LITTLE,211};212 213static int veml6030_get_intgrn_tm(struct iio_dev *indio_dev,214 int *val, int *val2)215{216 int ret, reg;217 struct veml6030_data *data = iio_priv(indio_dev);218 219 ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);220 if (ret) {221 dev_err(&data->client->dev,222 "can't read als conf register %d\n", ret);223 return ret;224 }225 226 switch ((reg >> 6) & 0xF) {227 case 0:228 *val2 = 100000;229 break;230 case 1:231 *val2 = 200000;232 break;233 case 2:234 *val2 = 400000;235 break;236 case 3:237 *val2 = 800000;238 break;239 case 8:240 *val2 = 50000;241 break;242 case 12:243 *val2 = 25000;244 break;245 default:246 return -EINVAL;247 }248 249 *val = 0;250 return IIO_VAL_INT_PLUS_MICRO;251}252 253static int veml6030_set_intgrn_tm(struct iio_dev *indio_dev,254 int val, int val2)255{256 int ret, new_int_time, int_idx;257 struct veml6030_data *data = iio_priv(indio_dev);258 259 if (val)260 return -EINVAL;261 262 switch (val2) {263 case 25000:264 new_int_time = 0x300;265 int_idx = 5;266 break;267 case 50000:268 new_int_time = 0x200;269 int_idx = 4;270 break;271 case 100000:272 new_int_time = 0x00;273 int_idx = 3;274 break;275 case 200000:276 new_int_time = 0x40;277 int_idx = 2;278 break;279 case 400000:280 new_int_time = 0x80;281 int_idx = 1;282 break;283 case 800000:284 new_int_time = 0xC0;285 int_idx = 0;286 break;287 default:288 return -EINVAL;289 }290 291 ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,292 VEML6030_ALS_IT, new_int_time);293 if (ret) {294 dev_err(&data->client->dev,295 "can't update als integration time %d\n", ret);296 return ret;297 }298 299 /*300 * Cache current integration time and update resolution. For every301 * increase in integration time to next level, resolution is halved302 * and vice-versa.303 */304 if (data->cur_integration_time < int_idx)305 data->cur_resolution <<= int_idx - data->cur_integration_time;306 else if (data->cur_integration_time > int_idx)307 data->cur_resolution >>= data->cur_integration_time - int_idx;308 309 data->cur_integration_time = int_idx;310 311 return ret;312}313 314static int veml6030_read_persistence(struct iio_dev *indio_dev,315 int *val, int *val2)316{317 int ret, reg, period, x, y;318 struct veml6030_data *data = iio_priv(indio_dev);319 320 ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);321 if (ret < 0)322 return ret;323 324 ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);325 if (ret) {326 dev_err(&data->client->dev,327 "can't read als conf register %d\n", ret);328 }329 330 /* integration time multiplied by 1/2/4/8 */331 period = y * (1 << ((reg >> 4) & 0x03));332 333 *val = period / 1000000;334 *val2 = period % 1000000;335 336 return IIO_VAL_INT_PLUS_MICRO;337}338 339static int veml6030_write_persistence(struct iio_dev *indio_dev,340 int val, int val2)341{342 int ret, period, x, y;343 struct veml6030_data *data = iio_priv(indio_dev);344 345 ret = veml6030_get_intgrn_tm(indio_dev, &x, &y);346 if (ret < 0)347 return ret;348 349 if (!val) {350 period = val2 / y;351 } else {352 if ((val == 1) && (val2 == 600000))353 period = 1600000 / y;354 else if ((val == 3) && (val2 == 200000))355 period = 3200000 / y;356 else if ((val == 6) && (val2 == 400000))357 period = 6400000 / y;358 else359 period = -1;360 }361 362 if (period <= 0 || period > 8 || hweight8(period) != 1)363 return -EINVAL;364 365 ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,366 VEML6030_ALS_PERS, (ffs(period) - 1) << 4);367 if (ret)368 dev_err(&data->client->dev,369 "can't set persistence value %d\n", ret);370 371 return ret;372}373 374static int veml6030_set_als_gain(struct iio_dev *indio_dev,375 int val, int val2)376{377 int ret, new_gain, gain_idx;378 struct veml6030_data *data = iio_priv(indio_dev);379 380 if (val == 0 && val2 == 125000) {381 new_gain = 0x1000; /* 0x02 << 11 */382 gain_idx = 3;383 } else if (val == 0 && val2 == 250000) {384 new_gain = 0x1800;385 gain_idx = 2;386 } else if (val == 1 && val2 == 0) {387 new_gain = 0x00;388 gain_idx = 1;389 } else if (val == 2 && val2 == 0) {390 new_gain = 0x800;391 gain_idx = 0;392 } else {393 return -EINVAL;394 }395 396 ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,397 VEML6030_ALS_GAIN, new_gain);398 if (ret) {399 dev_err(&data->client->dev,400 "can't set als gain %d\n", ret);401 return ret;402 }403 404 /*405 * Cache currently set gain & update resolution. For every406 * increase in the gain to next level, resolution is halved407 * and vice-versa.408 */409 if (data->cur_gain < gain_idx)410 data->cur_resolution <<= gain_idx - data->cur_gain;411 else if (data->cur_gain > gain_idx)412 data->cur_resolution >>= data->cur_gain - gain_idx;413 414 data->cur_gain = gain_idx;415 416 return ret;417}418 419static int veml6030_get_als_gain(struct iio_dev *indio_dev,420 int *val, int *val2)421{422 int ret, reg;423 struct veml6030_data *data = iio_priv(indio_dev);424 425 ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);426 if (ret) {427 dev_err(&data->client->dev,428 "can't read als conf register %d\n", ret);429 return ret;430 }431 432 switch ((reg >> 11) & 0x03) {433 case 0:434 *val = 1;435 *val2 = 0;436 break;437 case 1:438 *val = 2;439 *val2 = 0;440 break;441 case 2:442 *val = 0;443 *val2 = 125000;444 break;445 case 3:446 *val = 0;447 *val2 = 250000;448 break;449 default:450 return -EINVAL;451 }452 453 return IIO_VAL_INT_PLUS_MICRO;454}455 456static int veml6030_read_thresh(struct iio_dev *indio_dev,457 int *val, int *val2, int dir)458{459 int ret, reg;460 struct veml6030_data *data = iio_priv(indio_dev);461 462 if (dir == IIO_EV_DIR_RISING)463 ret = regmap_read(data->regmap, VEML6030_REG_ALS_WH, ®);464 else465 ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, ®);466 if (ret) {467 dev_err(&data->client->dev,468 "can't read als threshold value %d\n", ret);469 return ret;470 }471 472 *val = reg & 0xffff;473 return IIO_VAL_INT;474}475 476static int veml6030_write_thresh(struct iio_dev *indio_dev,477 int val, int val2, int dir)478{479 int ret;480 struct veml6030_data *data = iio_priv(indio_dev);481 482 if (val > 0xFFFF || val < 0 || val2)483 return -EINVAL;484 485 if (dir == IIO_EV_DIR_RISING) {486 ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, val);487 if (ret)488 dev_err(&data->client->dev,489 "can't set high threshold %d\n", ret);490 } else {491 ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, val);492 if (ret)493 dev_err(&data->client->dev,494 "can't set low threshold %d\n", ret);495 }496 497 return ret;498}499 500/*501 * Provide both raw as well as light reading in lux.502 * light (in lux) = resolution * raw reading503 */504static int veml6030_read_raw(struct iio_dev *indio_dev,505 struct iio_chan_spec const *chan, int *val,506 int *val2, long mask)507{508 int ret, reg;509 struct veml6030_data *data = iio_priv(indio_dev);510 struct regmap *regmap = data->regmap;511 struct device *dev = &data->client->dev;512 513 switch (mask) {514 case IIO_CHAN_INFO_RAW:515 case IIO_CHAN_INFO_PROCESSED:516 switch (chan->type) {517 case IIO_LIGHT:518 ret = regmap_read(regmap, VEML6030_REG_ALS_DATA, ®);519 if (ret < 0) {520 dev_err(dev, "can't read als data %d\n", ret);521 return ret;522 }523 if (mask == IIO_CHAN_INFO_PROCESSED) {524 *val = (reg * data->cur_resolution) / 10000;525 *val2 = (reg * data->cur_resolution) % 10000 * 100;526 return IIO_VAL_INT_PLUS_MICRO;527 }528 *val = reg;529 return IIO_VAL_INT;530 case IIO_INTENSITY:531 ret = regmap_read(regmap, VEML6030_REG_WH_DATA, ®);532 if (ret < 0) {533 dev_err(dev, "can't read white data %d\n", ret);534 return ret;535 }536 if (mask == IIO_CHAN_INFO_PROCESSED) {537 *val = (reg * data->cur_resolution) / 10000;538 *val2 = (reg * data->cur_resolution) % 10000;539 return IIO_VAL_INT_PLUS_MICRO;540 }541 *val = reg;542 return IIO_VAL_INT;543 default:544 return -EINVAL;545 }546 case IIO_CHAN_INFO_INT_TIME:547 if (chan->type == IIO_LIGHT)548 return veml6030_get_intgrn_tm(indio_dev, val, val2);549 return -EINVAL;550 case IIO_CHAN_INFO_SCALE:551 if (chan->type == IIO_LIGHT)552 return veml6030_get_als_gain(indio_dev, val, val2);553 return -EINVAL;554 default:555 return -EINVAL;556 }557}558 559static int veml6030_write_raw(struct iio_dev *indio_dev,560 struct iio_chan_spec const *chan,561 int val, int val2, long mask)562{563 switch (mask) {564 case IIO_CHAN_INFO_INT_TIME:565 switch (chan->type) {566 case IIO_LIGHT:567 return veml6030_set_intgrn_tm(indio_dev, val, val2);568 default:569 return -EINVAL;570 }571 case IIO_CHAN_INFO_SCALE:572 switch (chan->type) {573 case IIO_LIGHT:574 return veml6030_set_als_gain(indio_dev, val, val2);575 default:576 return -EINVAL;577 }578 default:579 return -EINVAL;580 }581}582 583static int veml6030_read_event_val(struct iio_dev *indio_dev,584 const struct iio_chan_spec *chan, enum iio_event_type type,585 enum iio_event_direction dir, enum iio_event_info info,586 int *val, int *val2)587{588 switch (info) {589 case IIO_EV_INFO_VALUE:590 switch (dir) {591 case IIO_EV_DIR_RISING:592 case IIO_EV_DIR_FALLING:593 return veml6030_read_thresh(indio_dev, val, val2, dir);594 default:595 return -EINVAL;596 }597 break;598 case IIO_EV_INFO_PERIOD:599 return veml6030_read_persistence(indio_dev, val, val2);600 default:601 return -EINVAL;602 }603}604 605static int veml6030_write_event_val(struct iio_dev *indio_dev,606 const struct iio_chan_spec *chan, enum iio_event_type type,607 enum iio_event_direction dir, enum iio_event_info info,608 int val, int val2)609{610 switch (info) {611 case IIO_EV_INFO_VALUE:612 return veml6030_write_thresh(indio_dev, val, val2, dir);613 case IIO_EV_INFO_PERIOD:614 return veml6030_write_persistence(indio_dev, val, val2);615 default:616 return -EINVAL;617 }618}619 620static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,621 const struct iio_chan_spec *chan, enum iio_event_type type,622 enum iio_event_direction dir)623{624 int ret, reg;625 struct veml6030_data *data = iio_priv(indio_dev);626 627 ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, ®);628 if (ret) {629 dev_err(&data->client->dev,630 "can't read als conf register %d\n", ret);631 return ret;632 }633 634 if (reg & VEML6030_ALS_INT_EN)635 return 1;636 else637 return 0;638}639 640/*641 * Sensor should not be measuring light when interrupt is configured.642 * Therefore correct sequence to configure interrupt functionality is:643 * shut down -> enable/disable interrupt -> power on644 *645 * state = 1 enables interrupt, state = 0 disables interrupt646 */647static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,648 const struct iio_chan_spec *chan, enum iio_event_type type,649 enum iio_event_direction dir, int state)650{651 int ret;652 struct veml6030_data *data = iio_priv(indio_dev);653 654 if (state < 0 || state > 1)655 return -EINVAL;656 657 ret = veml6030_als_shut_down(data);658 if (ret < 0) {659 dev_err(&data->client->dev,660 "can't disable als to configure interrupt %d\n", ret);661 return ret;662 }663 664 /* enable interrupt + power on */665 ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,666 VEML6030_ALS_INT_EN | VEML6030_ALS_SD, state << 1);667 if (ret)668 dev_err(&data->client->dev,669 "can't enable interrupt & poweron als %d\n", ret);670 671 return ret;672}673 674static const struct iio_info veml6030_info = {675 .read_raw = veml6030_read_raw,676 .write_raw = veml6030_write_raw,677 .read_event_value = veml6030_read_event_val,678 .write_event_value = veml6030_write_event_val,679 .read_event_config = veml6030_read_interrupt_config,680 .write_event_config = veml6030_write_interrupt_config,681 .attrs = &veml6030_attr_group,682 .event_attrs = &veml6030_event_attr_group,683};684 685static const struct iio_info veml6030_info_no_irq = {686 .read_raw = veml6030_read_raw,687 .write_raw = veml6030_write_raw,688 .attrs = &veml6030_attr_group,689};690 691static irqreturn_t veml6030_event_handler(int irq, void *private)692{693 int ret, reg, evtdir;694 struct iio_dev *indio_dev = private;695 struct veml6030_data *data = iio_priv(indio_dev);696 697 ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, ®);698 if (ret) {699 dev_err(&data->client->dev,700 "can't read als interrupt register %d\n", ret);701 return IRQ_HANDLED;702 }703 704 /* Spurious interrupt handling */705 if (!(reg & (VEML6030_INT_TH_HIGH | VEML6030_INT_TH_LOW)))706 return IRQ_NONE;707 708 if (reg & VEML6030_INT_TH_HIGH)709 evtdir = IIO_EV_DIR_RISING;710 else711 evtdir = IIO_EV_DIR_FALLING;712 713 iio_push_event(indio_dev, IIO_UNMOD_EVENT_CODE(IIO_INTENSITY,714 0, IIO_EV_TYPE_THRESH, evtdir),715 iio_get_time_ns(indio_dev));716 717 return IRQ_HANDLED;718}719 720/*721 * Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,722 * persistence to 1 x integration time and the threshold723 * interrupt disabled by default. First shutdown the sensor,724 * update registers and then power on the sensor.725 */726static int veml6030_hw_init(struct iio_dev *indio_dev)727{728 int ret, val;729 struct veml6030_data *data = iio_priv(indio_dev);730 struct i2c_client *client = data->client;731 732 ret = veml6030_als_shut_down(data);733 if (ret) {734 dev_err(&client->dev, "can't shutdown als %d\n", ret);735 return ret;736 }737 738 ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);739 if (ret) {740 dev_err(&client->dev, "can't setup als configs %d\n", ret);741 return ret;742 }743 744 ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,745 VEML6030_PSM | VEML6030_PSM_EN, 0x03);746 if (ret) {747 dev_err(&client->dev, "can't setup default PSM %d\n", ret);748 return ret;749 }750 751 ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);752 if (ret) {753 dev_err(&client->dev, "can't setup high threshold %d\n", ret);754 return ret;755 }756 757 ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);758 if (ret) {759 dev_err(&client->dev, "can't setup low threshold %d\n", ret);760 return ret;761 }762 763 ret = veml6030_als_pwr_on(data);764 if (ret) {765 dev_err(&client->dev, "can't poweron als %d\n", ret);766 return ret;767 }768 769 /* Wait 4 ms to let processor & oscillator start correctly */770 usleep_range(4000, 4002);771 772 /* Clear stale interrupt status bits if any during start */773 ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);774 if (ret < 0) {775 dev_err(&client->dev,776 "can't clear als interrupt status %d\n", ret);777 return ret;778 }779 780 /* Cache currently active measurement parameters */781 data->cur_gain = 3;782 data->cur_resolution = 5376;783 data->cur_integration_time = 3;784 785 return ret;786}787 788static int veml6030_probe(struct i2c_client *client)789{790 int ret;791 struct veml6030_data *data;792 struct iio_dev *indio_dev;793 struct regmap *regmap;794 795 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {796 dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");797 return -EOPNOTSUPP;798 }799 800 regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);801 if (IS_ERR(regmap)) {802 dev_err(&client->dev, "can't setup regmap\n");803 return PTR_ERR(regmap);804 }805 806 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));807 if (!indio_dev)808 return -ENOMEM;809 810 data = iio_priv(indio_dev);811 i2c_set_clientdata(client, indio_dev);812 data->client = client;813 data->regmap = regmap;814 815 indio_dev->name = "veml6030";816 indio_dev->channels = veml6030_channels;817 indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);818 indio_dev->modes = INDIO_DIRECT_MODE;819 820 if (client->irq) {821 ret = devm_request_threaded_irq(&client->dev, client->irq,822 NULL, veml6030_event_handler,823 IRQF_TRIGGER_LOW | IRQF_ONESHOT,824 "veml6030", indio_dev);825 if (ret < 0) {826 dev_err(&client->dev,827 "irq %d request failed\n", client->irq);828 return ret;829 }830 indio_dev->info = &veml6030_info;831 } else {832 indio_dev->info = &veml6030_info_no_irq;833 }834 835 ret = veml6030_hw_init(indio_dev);836 if (ret < 0)837 return ret;838 839 ret = devm_add_action_or_reset(&client->dev,840 veml6030_als_shut_down_action, data);841 if (ret < 0)842 return ret;843 844 return devm_iio_device_register(&client->dev, indio_dev);845}846 847static int veml6030_runtime_suspend(struct device *dev)848{849 int ret;850 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));851 struct veml6030_data *data = iio_priv(indio_dev);852 853 ret = veml6030_als_shut_down(data);854 if (ret < 0)855 dev_err(&data->client->dev, "can't suspend als %d\n", ret);856 857 return ret;858}859 860static int veml6030_runtime_resume(struct device *dev)861{862 int ret;863 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));864 struct veml6030_data *data = iio_priv(indio_dev);865 866 ret = veml6030_als_pwr_on(data);867 if (ret < 0)868 dev_err(&data->client->dev, "can't resume als %d\n", ret);869 870 return ret;871}872 873static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,874 veml6030_runtime_resume, NULL);875 876static const struct of_device_id veml6030_of_match[] = {877 { .compatible = "vishay,veml6030" },878 { }879};880MODULE_DEVICE_TABLE(of, veml6030_of_match);881 882static const struct i2c_device_id veml6030_id[] = {883 { "veml6030" },884 { }885};886MODULE_DEVICE_TABLE(i2c, veml6030_id);887 888static struct i2c_driver veml6030_driver = {889 .driver = {890 .name = "veml6030",891 .of_match_table = veml6030_of_match,892 .pm = pm_ptr(&veml6030_pm_ops),893 },894 .probe = veml6030_probe,895 .id_table = veml6030_id,896};897module_i2c_driver(veml6030_driver);898 899MODULE_AUTHOR("Rishi Gupta <gupt21@gmail.com>");900MODULE_DESCRIPTION("VEML6030 Ambient Light Sensor");901MODULE_LICENSE("GPL v2");902