brintos

brintos / linux-shallow public Read only

0
0
Text · 21.5 KiB · 6214288 Raw
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, &reg);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, &reg);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, &reg);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, &reg);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, &reg);464	else465		ret = regmap_read(data->regmap, VEML6030_REG_ALS_WL, &reg);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, &reg);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, &reg);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, &reg);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, &reg);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