brintos

brintos / linux-shallow public Read only

0
0
Text · 22.5 KiB · de6967a Raw
987 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2015 Intel Corporation4 *5 * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor.6 *7 * To do: Interrupt support.8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/mod_devicetable.h>13#include <linux/delay.h>14#include <linux/i2c.h>15#include <linux/iio/events.h>16#include <linux/iio/iio.h>17#include <linux/interrupt.h>18#include <linux/irq.h>19#include <linux/iio/sysfs.h>20#include <linux/mutex.h>21#include <linux/pm.h>22#include <linux/pm_runtime.h>23 24#define US5182D_REG_CFG0				0x0025#define US5182D_CFG0_ONESHOT_EN				BIT(6)26#define US5182D_CFG0_SHUTDOWN_EN			BIT(7)27#define US5182D_CFG0_WORD_ENABLE			BIT(0)28#define US5182D_CFG0_PROX				BIT(3)29#define US5182D_CFG0_PX_IRQ				BIT(2)30 31#define US5182D_REG_CFG1				0x0132#define US5182D_CFG1_ALS_RES16				BIT(4)33#define US5182D_CFG1_AGAIN_DEFAULT			0x0034 35#define US5182D_REG_CFG2				0x0236#define US5182D_CFG2_PX_RES16				BIT(4)37#define US5182D_CFG2_PXGAIN_DEFAULT			BIT(2)38 39#define US5182D_REG_CFG3				0x0340#define US5182D_CFG3_LED_CURRENT100			(BIT(4) | BIT(5))41#define US5182D_CFG3_INT_SOURCE_PX			BIT(3)42 43#define US5182D_REG_CFG4				0x1044 45/*46 * Registers for tuning the auto dark current cancelling feature.47 * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling.48 * when ALS  > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark49 * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark50 */51#define US5182D_REG_UDARK_TH			0x2752#define US5182D_REG_DARK_AUTO_EN		0x2b53#define US5182D_REG_AUTO_LDARK_GAIN		0x2954#define US5182D_REG_AUTO_HDARK_GAIN		0x2a55 56/* Thresholds for events: px low (0x08-l, 0x09-h), px high (0x0a-l 0x0b-h) */57#define US5182D_REG_PXL_TH			0x0858#define US5182D_REG_PXH_TH			0x0a59 60#define US5182D_REG_PXL_TH_DEFAULT		100061#define US5182D_REG_PXH_TH_DEFAULT		3000062 63#define US5182D_OPMODE_ALS			0x0164#define US5182D_OPMODE_PX			0x0265#define US5182D_OPMODE_SHIFT			466 67#define US5182D_REG_DARK_AUTO_EN_DEFAULT	0x8068#define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT	0x1669#define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT	0x0070 71#define US5182D_REG_ADL				0x0c72#define US5182D_REG_PDL				0x0e73 74#define US5182D_REG_MODE_STORE			0x2175#define US5182D_STORE_MODE			0x0176 77#define US5182D_REG_CHIPID			0xb278 79#define US5182D_OPMODE_MASK			GENMASK(5, 4)80#define US5182D_AGAIN_MASK			0x0781#define US5182D_RESET_CHIP			0x0182 83#define US5182D_CHIPID				0x2684#define US5182D_DRV_NAME			"us5182d"85 86#define US5182D_GA_RESOLUTION			100087 88#define US5182D_READ_BYTE			189#define US5182D_READ_WORD			290#define US5182D_OPSTORE_SLEEP_TIME		20 /* ms */91#define US5182D_SLEEP_MS			3000 /* ms */92#define US5182D_PXH_TH_DISABLE			0xffff93#define US5182D_PXL_TH_DISABLE			0x000094 95/* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */96static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600,97				     3900, 2100};98 99/*100 * Experimental thresholds that work with US5182D sensor on evaluation board101 * roughly between 12-32 lux102 */103static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000,104				      8000};105 106enum mode {107	US5182D_ALS_PX,108	US5182D_ALS_ONLY,109	US5182D_PX_ONLY110};111 112enum pmode {113	US5182D_CONTINUOUS,114	US5182D_ONESHOT115};116 117struct us5182d_data {118	struct i2c_client *client;119	struct mutex lock;120 121	/* Glass attenuation factor */122	u32 ga;123 124	/* Dark gain tuning */125	u8 lower_dark_gain;126	u8 upper_dark_gain;127	u16 *us5182d_dark_ths;128 129	u16 px_low_th;130	u16 px_high_th;131 132	int rising_en;133	int falling_en;134 135	u8 opmode;136	u8 power_mode;137 138	bool als_enabled;139	bool px_enabled;140 141	bool default_continuous;142};143 144static IIO_CONST_ATTR(in_illuminance_scale_available,145		      "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885");146 147static struct attribute *us5182d_attrs[] = {148	&iio_const_attr_in_illuminance_scale_available.dev_attr.attr,149	NULL150};151 152static const struct attribute_group us5182d_attr_group = {153	.attrs = us5182d_attrs,154};155 156static const struct {157	u8 reg;158	u8 val;159} us5182d_regvals[] = {160	{US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE},161	{US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16},162	{US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 |163			    US5182D_CFG2_PXGAIN_DEFAULT)},164	{US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100 |165			   US5182D_CFG3_INT_SOURCE_PX},166	{US5182D_REG_CFG4, 0x00},167};168 169static const struct iio_event_spec us5182d_events[] = {170	{171		.type = IIO_EV_TYPE_THRESH,172		.dir = IIO_EV_DIR_RISING,173		.mask_separate = BIT(IIO_EV_INFO_VALUE) |174				BIT(IIO_EV_INFO_ENABLE),175	},176	{177		.type = IIO_EV_TYPE_THRESH,178		.dir = IIO_EV_DIR_FALLING,179		.mask_separate = BIT(IIO_EV_INFO_VALUE) |180				BIT(IIO_EV_INFO_ENABLE),181	},182};183 184static const struct iio_chan_spec us5182d_channels[] = {185	{186		.type = IIO_LIGHT,187		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |188				      BIT(IIO_CHAN_INFO_SCALE),189	},190	{191		.type = IIO_PROXIMITY,192		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),193		.event_spec = us5182d_events,194		.num_event_specs = ARRAY_SIZE(us5182d_events),195	}196};197 198static int us5182d_oneshot_en(struct us5182d_data *data)199{200	int ret;201 202	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);203	if (ret < 0)204		return ret;205 206	/*207	 * In oneshot mode the chip will power itself down after taking the208	 * required measurement.209	 */210	ret = ret | US5182D_CFG0_ONESHOT_EN;211 212	return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);213}214 215static int us5182d_set_opmode(struct us5182d_data *data, u8 mode)216{217	int ret;218 219	if (mode == data->opmode)220		return 0;221 222	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);223	if (ret < 0)224		return ret;225 226	/* update mode */227	ret = ret & ~US5182D_OPMODE_MASK;228	ret = ret | (mode << US5182D_OPMODE_SHIFT);229 230	/*231	 * After updating the operating mode, the chip requires that232	 * the operation is stored, by writing 1 in the STORE_MODE233	 * register (auto-clearing).234	 */235	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);236	if (ret < 0)237		return ret;238 239	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE,240					US5182D_STORE_MODE);241	if (ret < 0)242		return ret;243 244	data->opmode = mode;245	msleep(US5182D_OPSTORE_SLEEP_TIME);246 247	return 0;248}249 250static int us5182d_als_enable(struct us5182d_data *data)251{252	int ret;253	u8 mode;254 255	if (data->power_mode == US5182D_ONESHOT) {256		ret = us5182d_set_opmode(data, US5182D_ALS_ONLY);257		if (ret < 0)258			return ret;259		data->px_enabled = false;260	}261 262	if (data->als_enabled)263		return 0;264 265	mode = data->px_enabled ? US5182D_ALS_PX : US5182D_ALS_ONLY;266 267	ret = us5182d_set_opmode(data, mode);268	if (ret < 0)269		return ret;270 271	data->als_enabled = true;272 273	return 0;274}275 276static int us5182d_px_enable(struct us5182d_data *data)277{278	int ret;279	u8 mode;280 281	if (data->power_mode == US5182D_ONESHOT) {282		ret = us5182d_set_opmode(data, US5182D_PX_ONLY);283		if (ret < 0)284			return ret;285		data->als_enabled = false;286	}287 288	if (data->px_enabled)289		return 0;290 291	mode = data->als_enabled ? US5182D_ALS_PX : US5182D_PX_ONLY;292 293	ret = us5182d_set_opmode(data, mode);294	if (ret < 0)295		return ret;296 297	data->px_enabled = true;298 299	return 0;300}301 302static int us5182d_get_als(struct us5182d_data *data)303{304	int ret;305	unsigned long result;306 307	ret = us5182d_als_enable(data);308	if (ret < 0)309		return ret;310 311	ret = i2c_smbus_read_word_data(data->client,312				       US5182D_REG_ADL);313	if (ret < 0)314		return ret;315 316	result = ret * data->ga / US5182D_GA_RESOLUTION;317	if (result > 0xffff)318		result = 0xffff;319 320	return result;321}322 323static int us5182d_get_px(struct us5182d_data *data)324{325	int ret;326 327	ret = us5182d_px_enable(data);328	if (ret < 0)329		return ret;330 331	return i2c_smbus_read_word_data(data->client,332					US5182D_REG_PDL);333}334 335static int us5182d_shutdown_en(struct us5182d_data *data, u8 state)336{337	int ret;338 339	if (data->power_mode == US5182D_ONESHOT)340		return 0;341 342	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);343	if (ret < 0)344		return ret;345 346	ret = ret & ~US5182D_CFG0_SHUTDOWN_EN;347	ret = ret | state;348 349	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret);350	if (ret < 0)351		return ret;352 353	if (state & US5182D_CFG0_SHUTDOWN_EN) {354		data->als_enabled = false;355		data->px_enabled = false;356	}357 358	return ret;359}360 361 362static int us5182d_set_power_state(struct us5182d_data *data, bool on)363{364	int ret;365 366	if (data->power_mode == US5182D_ONESHOT)367		return 0;368 369	if (on) {370		ret = pm_runtime_resume_and_get(&data->client->dev);371	} else {372		pm_runtime_mark_last_busy(&data->client->dev);373		ret = pm_runtime_put_autosuspend(&data->client->dev);374	}375 376	return ret;377}378 379static int us5182d_read_value(struct us5182d_data *data,380			      struct iio_chan_spec const *chan)381{382	int ret, value;383 384	mutex_lock(&data->lock);385 386	if (data->power_mode == US5182D_ONESHOT) {387		ret = us5182d_oneshot_en(data);388		if (ret < 0)389			goto out_err;390	}391 392	ret = us5182d_set_power_state(data, true);393	if (ret < 0)394		goto out_err;395 396	if (chan->type == IIO_LIGHT)397		ret = us5182d_get_als(data);398	else399		ret = us5182d_get_px(data);400	if (ret < 0)401		goto out_poweroff;402 403	value = ret;404 405	ret = us5182d_set_power_state(data, false);406	if (ret < 0)407		goto out_err;408 409	mutex_unlock(&data->lock);410	return value;411 412out_poweroff:413	us5182d_set_power_state(data, false);414out_err:415	mutex_unlock(&data->lock);416	return ret;417}418 419static int us5182d_read_raw(struct iio_dev *indio_dev,420			    struct iio_chan_spec const *chan, int *val,421			    int *val2, long mask)422{423	struct us5182d_data *data = iio_priv(indio_dev);424	int ret;425 426	switch (mask) {427	case IIO_CHAN_INFO_RAW:428		ret = us5182d_read_value(data, chan);429		if (ret < 0)430			return ret;431		*val = ret;432		return IIO_VAL_INT;433	case IIO_CHAN_INFO_SCALE:434		ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);435		if (ret < 0)436			return ret;437		*val = 0;438		*val2 = us5182d_scales[ret & US5182D_AGAIN_MASK];439		return IIO_VAL_INT_PLUS_MICRO;440	default:441		return -EINVAL;442	}443}444 445/**446 * us5182d_update_dark_th - update Darh_Th registers447 * @data:	us5182d_data structure448 * @index:	index in us5182d_dark_ths array to use for the updated value449 *450 * Function needs to be called with a lock held because it needs two i2c write451 * byte operations as these registers (0x27 0x28) don't work in word mode452 * accessing.453 */454static int us5182d_update_dark_th(struct us5182d_data *data, int index)455{456	__be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]);457	int ret;458 459	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH,460					((u8 *)&dark_th)[0]);461	if (ret < 0)462		return ret;463 464	return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1,465					((u8 *)&dark_th)[1]);466}467 468/**469 * us5182d_apply_scale - update the ALS scale470 * @data:	us5182d_data structure471 * @index:	index in us5182d_scales array to use for the updated value472 *473 * Function needs to be called with a lock held as we're having more than one474 * i2c operation.475 */476static int us5182d_apply_scale(struct us5182d_data *data, int index)477{478	int ret;479 480	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1);481	if (ret < 0)482		return ret;483 484	ret = ret & (~US5182D_AGAIN_MASK);485	ret |= index;486 487	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret);488	if (ret < 0)489		return ret;490 491	return us5182d_update_dark_th(data, index);492}493 494static int us5182d_write_raw(struct iio_dev *indio_dev,495			     struct iio_chan_spec const *chan, int val,496			     int val2, long mask)497{498	struct us5182d_data *data = iio_priv(indio_dev);499	int ret, i;500 501	switch (mask) {502	case IIO_CHAN_INFO_SCALE:503		if (val != 0)504			return -EINVAL;505		for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++)506			if (val2 == us5182d_scales[i]) {507				mutex_lock(&data->lock);508				ret = us5182d_apply_scale(data, i);509				mutex_unlock(&data->lock);510				return ret;511			}512		break;513	default:514		return -EINVAL;515	}516 517	return -EINVAL;518}519 520static int us5182d_setup_prox(struct iio_dev *indio_dev,521			      enum iio_event_direction dir, u16 val)522{523	struct us5182d_data *data = iio_priv(indio_dev);524 525	if (dir == IIO_EV_DIR_FALLING)526		return i2c_smbus_write_word_data(data->client,527						 US5182D_REG_PXL_TH, val);528	else if (dir == IIO_EV_DIR_RISING)529		return i2c_smbus_write_word_data(data->client,530						 US5182D_REG_PXH_TH, val);531 532	return 0;533}534 535static int us5182d_read_thresh(struct iio_dev *indio_dev,536	const struct iio_chan_spec *chan, enum iio_event_type type,537	enum iio_event_direction dir, enum iio_event_info info, int *val,538	int *val2)539{540	struct us5182d_data *data = iio_priv(indio_dev);541 542	switch (dir) {543	case IIO_EV_DIR_RISING:544		mutex_lock(&data->lock);545		*val = data->px_high_th;546		mutex_unlock(&data->lock);547		break;548	case IIO_EV_DIR_FALLING:549		mutex_lock(&data->lock);550		*val = data->px_low_th;551		mutex_unlock(&data->lock);552		break;553	default:554		return -EINVAL;555	}556 557	return IIO_VAL_INT;558}559 560static int us5182d_write_thresh(struct iio_dev *indio_dev,561	const struct iio_chan_spec *chan, enum iio_event_type type,562	enum iio_event_direction dir, enum iio_event_info info, int val,563	int val2)564{565	struct us5182d_data *data = iio_priv(indio_dev);566	int ret;567 568	if (val < 0 || val > USHRT_MAX || val2 != 0)569		return -EINVAL;570 571	switch (dir) {572	case IIO_EV_DIR_RISING:573		mutex_lock(&data->lock);574		if (data->rising_en) {575			ret = us5182d_setup_prox(indio_dev, dir, val);576			if (ret < 0)577				goto err;578		}579		data->px_high_th = val;580		mutex_unlock(&data->lock);581		break;582	case IIO_EV_DIR_FALLING:583		mutex_lock(&data->lock);584		if (data->falling_en) {585			ret = us5182d_setup_prox(indio_dev, dir, val);586			if (ret < 0)587				goto err;588		}589		data->px_low_th = val;590		mutex_unlock(&data->lock);591		break;592	default:593		return -EINVAL;594	}595 596	return 0;597err:598	mutex_unlock(&data->lock);599	return ret;600}601 602static int us5182d_read_event_config(struct iio_dev *indio_dev,603	const struct iio_chan_spec *chan, enum iio_event_type type,604	enum iio_event_direction dir)605{606	struct us5182d_data *data = iio_priv(indio_dev);607	int ret;608 609	switch (dir) {610	case IIO_EV_DIR_RISING:611		mutex_lock(&data->lock);612		ret = data->rising_en;613		mutex_unlock(&data->lock);614		break;615	case IIO_EV_DIR_FALLING:616		mutex_lock(&data->lock);617		ret = data->falling_en;618		mutex_unlock(&data->lock);619		break;620	default:621		ret = -EINVAL;622		break;623	}624 625	return ret;626}627 628static int us5182d_write_event_config(struct iio_dev *indio_dev,629	const struct iio_chan_spec *chan, enum iio_event_type type,630	enum iio_event_direction dir, int state)631{632	struct us5182d_data *data = iio_priv(indio_dev);633	int ret;634	u16 new_th;635 636	mutex_lock(&data->lock);637 638	switch (dir) {639	case IIO_EV_DIR_RISING:640		if (data->rising_en == state) {641			mutex_unlock(&data->lock);642			return 0;643		}644		new_th = US5182D_PXH_TH_DISABLE;645		if (state) {646			data->power_mode = US5182D_CONTINUOUS;647			ret = us5182d_set_power_state(data, true);648			if (ret < 0)649				goto err;650			ret = us5182d_px_enable(data);651			if (ret < 0)652				goto err_poweroff;653			new_th = data->px_high_th;654		}655		ret = us5182d_setup_prox(indio_dev, dir, new_th);656		if (ret < 0)657			goto err_poweroff;658		data->rising_en = state;659		break;660	case IIO_EV_DIR_FALLING:661		if (data->falling_en == state) {662			mutex_unlock(&data->lock);663			return 0;664		}665		new_th =  US5182D_PXL_TH_DISABLE;666		if (state) {667			data->power_mode = US5182D_CONTINUOUS;668			ret = us5182d_set_power_state(data, true);669			if (ret < 0)670				goto err;671			ret = us5182d_px_enable(data);672			if (ret < 0)673				goto err_poweroff;674			new_th = data->px_low_th;675		}676		ret = us5182d_setup_prox(indio_dev, dir, new_th);677		if (ret < 0)678			goto err_poweroff;679		data->falling_en = state;680		break;681	default:682		ret = -EINVAL;683		goto err;684	}685 686	if (!state) {687		ret = us5182d_set_power_state(data, false);688		if (ret < 0)689			goto err;690	}691 692	if (!data->falling_en && !data->rising_en && !data->default_continuous)693		data->power_mode = US5182D_ONESHOT;694 695	mutex_unlock(&data->lock);696	return 0;697 698err_poweroff:699	if (state)700		us5182d_set_power_state(data, false);701err:702	mutex_unlock(&data->lock);703	return ret;704}705 706static const struct iio_info us5182d_info = {707	.read_raw = us5182d_read_raw,708	.write_raw = us5182d_write_raw,709	.attrs = &us5182d_attr_group,710	.read_event_value = &us5182d_read_thresh,711	.write_event_value = &us5182d_write_thresh,712	.read_event_config = &us5182d_read_event_config,713	.write_event_config = &us5182d_write_event_config,714};715 716static int us5182d_reset(struct iio_dev *indio_dev)717{718	struct us5182d_data *data = iio_priv(indio_dev);719 720	return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3,721					 US5182D_RESET_CHIP);722}723 724static int us5182d_init(struct iio_dev *indio_dev)725{726	struct us5182d_data *data = iio_priv(indio_dev);727	int i, ret;728 729	ret = us5182d_reset(indio_dev);730	if (ret < 0)731		return ret;732 733	data->opmode = 0;734	data->power_mode = US5182D_CONTINUOUS;735	data->px_low_th = US5182D_REG_PXL_TH_DEFAULT;736	data->px_high_th = US5182D_REG_PXH_TH_DEFAULT;737 738	for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) {739		ret = i2c_smbus_write_byte_data(data->client,740						us5182d_regvals[i].reg,741						us5182d_regvals[i].val);742		if (ret < 0)743			return ret;744	}745 746	data->als_enabled = true;747	data->px_enabled = true;748 749	if (!data->default_continuous) {750		ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);751		if (ret < 0)752			return ret;753		data->power_mode = US5182D_ONESHOT;754	}755 756	return ret;757}758 759static void us5182d_get_platform_data(struct iio_dev *indio_dev)760{761	struct us5182d_data *data = iio_priv(indio_dev);762 763	if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef",764				     &data->ga))765		data->ga = US5182D_GA_RESOLUTION;766	if (device_property_read_u16_array(&data->client->dev,767					   "upisemi,dark-ths",768					   data->us5182d_dark_ths,769					   ARRAY_SIZE(us5182d_dark_ths_vals)))770		data->us5182d_dark_ths = us5182d_dark_ths_vals;771	if (device_property_read_u8(&data->client->dev,772				    "upisemi,upper-dark-gain",773				    &data->upper_dark_gain))774		data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT;775	if (device_property_read_u8(&data->client->dev,776				    "upisemi,lower-dark-gain",777				    &data->lower_dark_gain))778		data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT;779	data->default_continuous = device_property_read_bool(&data->client->dev,780							     "upisemi,continuous");781}782 783static int  us5182d_dark_gain_config(struct iio_dev *indio_dev)784{785	struct us5182d_data *data = iio_priv(indio_dev);786	int ret;787 788	ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT);789	if (ret < 0)790		return ret;791 792	ret = i2c_smbus_write_byte_data(data->client,793					US5182D_REG_AUTO_LDARK_GAIN,794					data->lower_dark_gain);795	if (ret < 0)796		return ret;797 798	ret = i2c_smbus_write_byte_data(data->client,799					US5182D_REG_AUTO_HDARK_GAIN,800					data->upper_dark_gain);801	if (ret < 0)802		return ret;803 804	return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN,805					 US5182D_REG_DARK_AUTO_EN_DEFAULT);806}807 808static irqreturn_t us5182d_irq_thread_handler(int irq, void *private)809{810	struct iio_dev *indio_dev = private;811	struct us5182d_data *data = iio_priv(indio_dev);812	enum iio_event_direction dir;813	int ret;814	u64 ev;815 816	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0);817	if (ret < 0) {818		dev_err(&data->client->dev, "i2c transfer error in irq\n");819		return IRQ_HANDLED;820	}821 822	dir = ret & US5182D_CFG0_PROX ? IIO_EV_DIR_RISING : IIO_EV_DIR_FALLING;823	ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 1, IIO_EV_TYPE_THRESH, dir);824 825	iio_push_event(indio_dev, ev, iio_get_time_ns(indio_dev));826 827	ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0,828					ret & ~US5182D_CFG0_PX_IRQ);829	if (ret < 0)830		dev_err(&data->client->dev, "i2c transfer error in irq\n");831 832	return IRQ_HANDLED;833}834 835static int us5182d_probe(struct i2c_client *client)836{837	struct us5182d_data *data;838	struct iio_dev *indio_dev;839	int ret;840 841	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));842	if (!indio_dev)843		return -ENOMEM;844 845	data = iio_priv(indio_dev);846	i2c_set_clientdata(client, indio_dev);847	data->client = client;848 849	mutex_init(&data->lock);850 851	indio_dev->info = &us5182d_info;852	indio_dev->name = US5182D_DRV_NAME;853	indio_dev->channels = us5182d_channels;854	indio_dev->num_channels = ARRAY_SIZE(us5182d_channels);855	indio_dev->modes = INDIO_DIRECT_MODE;856 857	ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID);858	if (ret != US5182D_CHIPID) {859		dev_err(&data->client->dev,860			"Failed to detect US5182 light chip\n");861		return (ret < 0) ? ret : -ENODEV;862	}863 864	if (client->irq > 0) {865		ret = devm_request_threaded_irq(&client->dev, client->irq, NULL,866						us5182d_irq_thread_handler,867						IRQF_TRIGGER_LOW | IRQF_ONESHOT,868						"us5182d-irq", indio_dev);869		if (ret < 0)870			return ret;871	} else872		dev_warn(&client->dev, "no valid irq found\n");873 874	us5182d_get_platform_data(indio_dev);875	ret = us5182d_init(indio_dev);876	if (ret < 0)877		return ret;878 879	ret = us5182d_dark_gain_config(indio_dev);880	if (ret < 0)881		goto out_err;882 883	if (data->default_continuous) {884		ret = pm_runtime_set_active(&client->dev);885		if (ret < 0)886			goto out_err;887	}888 889	pm_runtime_enable(&client->dev);890	pm_runtime_set_autosuspend_delay(&client->dev,891					 US5182D_SLEEP_MS);892	pm_runtime_use_autosuspend(&client->dev);893 894	ret = iio_device_register(indio_dev);895	if (ret < 0)896		goto out_err;897 898	return 0;899 900out_err:901	us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);902	return ret;903 904}905 906static void us5182d_remove(struct i2c_client *client)907{908	struct us5182d_data *data = iio_priv(i2c_get_clientdata(client));909	int ret;910 911	iio_device_unregister(i2c_get_clientdata(client));912 913	pm_runtime_disable(&client->dev);914	pm_runtime_set_suspended(&client->dev);915 916	ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);917	if (ret)918		dev_warn(&client->dev, "Failed to shut down (%pe)\n",919			 ERR_PTR(ret));920}921 922static int us5182d_suspend(struct device *dev)923{924	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));925	struct us5182d_data *data = iio_priv(indio_dev);926 927	if (data->power_mode == US5182D_CONTINUOUS)928		return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN);929 930	return 0;931}932 933static int us5182d_resume(struct device *dev)934{935	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));936	struct us5182d_data *data = iio_priv(indio_dev);937 938	if (data->power_mode == US5182D_CONTINUOUS)939		return us5182d_shutdown_en(data,940					   ~US5182D_CFG0_SHUTDOWN_EN & 0xff);941 942	return 0;943}944 945static const struct dev_pm_ops us5182d_pm_ops = {946	SYSTEM_SLEEP_PM_OPS(us5182d_suspend, us5182d_resume)947	RUNTIME_PM_OPS(us5182d_suspend, us5182d_resume, NULL)948};949 950static const struct acpi_device_id us5182d_acpi_match[] = {951	{ "USD5182", 0 },952	{}953};954 955MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match);956 957static const struct i2c_device_id us5182d_id[] = {958	{ "usd5182" },959	{}960};961 962MODULE_DEVICE_TABLE(i2c, us5182d_id);963 964static const struct of_device_id us5182d_of_match[] = {965	{ .compatible = "upisemi,usd5182" },966	{}967};968MODULE_DEVICE_TABLE(of, us5182d_of_match);969 970static struct i2c_driver us5182d_driver = {971	.driver = {972		.name = US5182D_DRV_NAME,973		.pm = pm_ptr(&us5182d_pm_ops),974		.of_match_table = us5182d_of_match,975		.acpi_match_table = us5182d_acpi_match,976	},977	.probe = us5182d_probe,978	.remove = us5182d_remove,979	.id_table = us5182d_id,980 981};982module_i2c_driver(us5182d_driver);983 984MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");985MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor");986MODULE_LICENSE("GPL v2");987