cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

isl29501.c (23880B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * isl29501.c: ISL29501 Time of Flight sensor driver.
      4 *
      5 * Copyright (C) 2018
      6 * Author: Mathieu Othacehe <m.othacehe@gmail.com>
      7 *
      8 * 7-bit I2C slave address: 0x57
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/i2c.h>
     14#include <linux/err.h>
     15#include <linux/of_device.h>
     16#include <linux/iio/iio.h>
     17#include <linux/iio/sysfs.h>
     18
     19#include <linux/iio/trigger_consumer.h>
     20#include <linux/iio/buffer.h>
     21#include <linux/iio/triggered_buffer.h>
     22
     23/* Control, setting and status registers */
     24#define ISL29501_DEVICE_ID			0x00
     25#define ISL29501_ID				0x0A
     26
     27/* Sampling control registers */
     28#define ISL29501_INTEGRATION_PERIOD		0x10
     29#define ISL29501_SAMPLE_PERIOD			0x11
     30
     31/* Closed loop calibration registers */
     32#define ISL29501_CROSSTALK_I_MSB		0x24
     33#define ISL29501_CROSSTALK_I_LSB		0x25
     34#define ISL29501_CROSSTALK_I_EXPONENT		0x26
     35#define ISL29501_CROSSTALK_Q_MSB		0x27
     36#define ISL29501_CROSSTALK_Q_LSB		0x28
     37#define ISL29501_CROSSTALK_Q_EXPONENT		0x29
     38#define ISL29501_CROSSTALK_GAIN_MSB		0x2A
     39#define ISL29501_CROSSTALK_GAIN_LSB		0x2B
     40#define ISL29501_MAGNITUDE_REF_EXP		0x2C
     41#define ISL29501_MAGNITUDE_REF_MSB		0x2D
     42#define ISL29501_MAGNITUDE_REF_LSB		0x2E
     43#define ISL29501_PHASE_OFFSET_MSB		0x2F
     44#define ISL29501_PHASE_OFFSET_LSB		0x30
     45
     46/* Analog control registers */
     47#define ISL29501_DRIVER_RANGE			0x90
     48#define ISL29501_EMITTER_DAC			0x91
     49
     50#define ISL29501_COMMAND_REGISTER		0xB0
     51
     52/* Commands */
     53#define ISL29501_EMUL_SAMPLE_START_PIN		0x49
     54#define ISL29501_RESET_ALL_REGISTERS		0xD7
     55#define ISL29501_RESET_INT_SM			0xD1
     56
     57/* Ambiant light and temperature corrections */
     58#define ISL29501_TEMP_REFERENCE			0x31
     59#define ISL29501_PHASE_EXPONENT			0x33
     60#define ISL29501_TEMP_COEFF_A			0x34
     61#define ISL29501_TEMP_COEFF_B			0x39
     62#define ISL29501_AMBIANT_COEFF_A		0x36
     63#define ISL29501_AMBIANT_COEFF_B		0x3B
     64
     65/* Data output registers */
     66#define ISL29501_DISTANCE_MSB_DATA		0xD1
     67#define ISL29501_DISTANCE_LSB_DATA		0xD2
     68#define ISL29501_PRECISION_MSB			0xD3
     69#define ISL29501_PRECISION_LSB			0xD4
     70#define ISL29501_MAGNITUDE_EXPONENT		0xD5
     71#define ISL29501_MAGNITUDE_MSB			0xD6
     72#define ISL29501_MAGNITUDE_LSB			0xD7
     73#define ISL29501_PHASE_MSB			0xD8
     74#define ISL29501_PHASE_LSB			0xD9
     75#define ISL29501_I_RAW_EXPONENT			0xDA
     76#define ISL29501_I_RAW_MSB			0xDB
     77#define ISL29501_I_RAW_LSB			0xDC
     78#define ISL29501_Q_RAW_EXPONENT			0xDD
     79#define ISL29501_Q_RAW_MSB			0xDE
     80#define ISL29501_Q_RAW_LSB			0xDF
     81#define ISL29501_DIE_TEMPERATURE		0xE2
     82#define ISL29501_AMBIENT_LIGHT			0xE3
     83#define ISL29501_GAIN_MSB			0xE6
     84#define ISL29501_GAIN_LSB			0xE7
     85
     86#define ISL29501_MAX_EXP_VAL 15
     87
     88#define ISL29501_INT_TIME_AVAILABLE \
     89	"0.00007 0.00014 0.00028 0.00057 0.00114 " \
     90	"0.00228 0.00455 0.00910 0.01820 0.03640 " \
     91	"0.07281 0.14561"
     92
     93#define ISL29501_CURRENT_SCALE_AVAILABLE \
     94	"0.0039 0.0078 0.0118 0.0157 0.0196 " \
     95	"0.0235 0.0275 0.0314 0.0352 0.0392 " \
     96	"0.0431 0.0471 0.0510 0.0549 0.0588"
     97
     98enum isl29501_correction_coeff {
     99	COEFF_TEMP_A,
    100	COEFF_TEMP_B,
    101	COEFF_LIGHT_A,
    102	COEFF_LIGHT_B,
    103	COEFF_MAX,
    104};
    105
    106struct isl29501_private {
    107	struct i2c_client *client;
    108	struct mutex lock;
    109	/* Exact representation of correction coefficients. */
    110	unsigned int shadow_coeffs[COEFF_MAX];
    111};
    112
    113enum isl29501_register_name {
    114	REG_DISTANCE,
    115	REG_PHASE,
    116	REG_TEMPERATURE,
    117	REG_AMBIENT_LIGHT,
    118	REG_GAIN,
    119	REG_GAIN_BIAS,
    120	REG_PHASE_EXP,
    121	REG_CALIB_PHASE_TEMP_A,
    122	REG_CALIB_PHASE_TEMP_B,
    123	REG_CALIB_PHASE_LIGHT_A,
    124	REG_CALIB_PHASE_LIGHT_B,
    125	REG_DISTANCE_BIAS,
    126	REG_TEMPERATURE_BIAS,
    127	REG_INT_TIME,
    128	REG_SAMPLE_TIME,
    129	REG_DRIVER_RANGE,
    130	REG_EMITTER_DAC,
    131};
    132
    133struct isl29501_register_desc {
    134	u8 msb;
    135	u8 lsb;
    136};
    137
    138static const struct isl29501_register_desc isl29501_registers[] = {
    139	[REG_DISTANCE] = {
    140		.msb = ISL29501_DISTANCE_MSB_DATA,
    141		.lsb = ISL29501_DISTANCE_LSB_DATA,
    142	},
    143	[REG_PHASE] = {
    144		.msb = ISL29501_PHASE_MSB,
    145		.lsb = ISL29501_PHASE_LSB,
    146	},
    147	[REG_TEMPERATURE] = {
    148		.lsb = ISL29501_DIE_TEMPERATURE,
    149	},
    150	[REG_AMBIENT_LIGHT] = {
    151		.lsb = ISL29501_AMBIENT_LIGHT,
    152	},
    153	[REG_GAIN] = {
    154		.msb = ISL29501_GAIN_MSB,
    155		.lsb = ISL29501_GAIN_LSB,
    156	},
    157	[REG_GAIN_BIAS] = {
    158		.msb = ISL29501_CROSSTALK_GAIN_MSB,
    159		.lsb = ISL29501_CROSSTALK_GAIN_LSB,
    160	},
    161	[REG_PHASE_EXP] = {
    162		.lsb = ISL29501_PHASE_EXPONENT,
    163	},
    164	[REG_CALIB_PHASE_TEMP_A] = {
    165		.lsb = ISL29501_TEMP_COEFF_A,
    166	},
    167	[REG_CALIB_PHASE_TEMP_B] = {
    168		.lsb = ISL29501_TEMP_COEFF_B,
    169	},
    170	[REG_CALIB_PHASE_LIGHT_A] = {
    171		.lsb = ISL29501_AMBIANT_COEFF_A,
    172	},
    173	[REG_CALIB_PHASE_LIGHT_B] = {
    174		.lsb = ISL29501_AMBIANT_COEFF_B,
    175	},
    176	[REG_DISTANCE_BIAS] = {
    177		.msb = ISL29501_PHASE_OFFSET_MSB,
    178		.lsb = ISL29501_PHASE_OFFSET_LSB,
    179	},
    180	[REG_TEMPERATURE_BIAS] = {
    181		.lsb = ISL29501_TEMP_REFERENCE,
    182	},
    183	[REG_INT_TIME] = {
    184		.lsb = ISL29501_INTEGRATION_PERIOD,
    185	},
    186	[REG_SAMPLE_TIME] = {
    187		.lsb = ISL29501_SAMPLE_PERIOD,
    188	},
    189	[REG_DRIVER_RANGE] = {
    190		.lsb = ISL29501_DRIVER_RANGE,
    191	},
    192	[REG_EMITTER_DAC] = {
    193		.lsb = ISL29501_EMITTER_DAC,
    194	},
    195};
    196
    197static int isl29501_register_read(struct isl29501_private *isl29501,
    198				  enum isl29501_register_name name,
    199				  u32 *val)
    200{
    201	const struct isl29501_register_desc *reg = &isl29501_registers[name];
    202	u8 msb = 0, lsb = 0;
    203	s32 ret;
    204
    205	mutex_lock(&isl29501->lock);
    206	if (reg->msb) {
    207		ret = i2c_smbus_read_byte_data(isl29501->client, reg->msb);
    208		if (ret < 0)
    209			goto err;
    210		msb = ret;
    211	}
    212
    213	if (reg->lsb) {
    214		ret = i2c_smbus_read_byte_data(isl29501->client, reg->lsb);
    215		if (ret < 0)
    216			goto err;
    217		lsb = ret;
    218	}
    219	mutex_unlock(&isl29501->lock);
    220
    221	*val = (msb << 8) + lsb;
    222
    223	return 0;
    224err:
    225	mutex_unlock(&isl29501->lock);
    226
    227	return ret;
    228}
    229
    230static u32 isl29501_register_write(struct isl29501_private *isl29501,
    231				   enum isl29501_register_name name,
    232				   u32 value)
    233{
    234	const struct isl29501_register_desc *reg = &isl29501_registers[name];
    235	int ret;
    236
    237	if (!reg->msb && value > U8_MAX)
    238		return -ERANGE;
    239
    240	if (value > U16_MAX)
    241		return -ERANGE;
    242
    243	mutex_lock(&isl29501->lock);
    244	if (reg->msb) {
    245		ret = i2c_smbus_write_byte_data(isl29501->client,
    246						reg->msb, value >> 8);
    247		if (ret < 0)
    248			goto err;
    249	}
    250
    251	ret = i2c_smbus_write_byte_data(isl29501->client, reg->lsb, value);
    252
    253err:
    254	mutex_unlock(&isl29501->lock);
    255	return ret;
    256}
    257
    258static ssize_t isl29501_read_ext(struct iio_dev *indio_dev,
    259				 uintptr_t private,
    260				 const struct iio_chan_spec *chan,
    261				 char *buf)
    262{
    263	struct isl29501_private *isl29501 = iio_priv(indio_dev);
    264	enum isl29501_register_name reg = private;
    265	int ret;
    266	u32 value, gain, coeff, exp;
    267
    268	switch (reg) {
    269	case REG_GAIN:
    270	case REG_GAIN_BIAS:
    271		ret = isl29501_register_read(isl29501, reg, &gain);
    272		if (ret < 0)
    273			return ret;
    274
    275		value = gain;
    276		break;
    277	case REG_CALIB_PHASE_TEMP_A:
    278	case REG_CALIB_PHASE_TEMP_B:
    279	case REG_CALIB_PHASE_LIGHT_A:
    280	case REG_CALIB_PHASE_LIGHT_B:
    281		ret = isl29501_register_read(isl29501, REG_PHASE_EXP, &exp);
    282		if (ret < 0)
    283			return ret;
    284
    285		ret = isl29501_register_read(isl29501, reg, &coeff);
    286		if (ret < 0)
    287			return ret;
    288
    289		value = coeff << exp;
    290		break;
    291	default:
    292		return -EINVAL;
    293	}
    294
    295	return sprintf(buf, "%u\n", value);
    296}
    297
    298static int isl29501_set_shadow_coeff(struct isl29501_private *isl29501,
    299				     enum isl29501_register_name reg,
    300				     unsigned int val)
    301{
    302	enum isl29501_correction_coeff coeff;
    303
    304	switch (reg) {
    305	case REG_CALIB_PHASE_TEMP_A:
    306		coeff = COEFF_TEMP_A;
    307		break;
    308	case REG_CALIB_PHASE_TEMP_B:
    309		coeff = COEFF_TEMP_B;
    310		break;
    311	case REG_CALIB_PHASE_LIGHT_A:
    312		coeff = COEFF_LIGHT_A;
    313		break;
    314	case REG_CALIB_PHASE_LIGHT_B:
    315		coeff = COEFF_LIGHT_B;
    316		break;
    317	default:
    318		return -EINVAL;
    319	}
    320	isl29501->shadow_coeffs[coeff] = val;
    321
    322	return 0;
    323}
    324
    325static int isl29501_write_coeff(struct isl29501_private *isl29501,
    326				enum isl29501_correction_coeff coeff,
    327				int val)
    328{
    329	enum isl29501_register_name reg;
    330
    331	switch (coeff) {
    332	case COEFF_TEMP_A:
    333		reg = REG_CALIB_PHASE_TEMP_A;
    334		break;
    335	case COEFF_TEMP_B:
    336		reg = REG_CALIB_PHASE_TEMP_B;
    337		break;
    338	case COEFF_LIGHT_A:
    339		reg = REG_CALIB_PHASE_LIGHT_A;
    340		break;
    341	case COEFF_LIGHT_B:
    342		reg = REG_CALIB_PHASE_LIGHT_B;
    343		break;
    344	default:
    345		return -EINVAL;
    346	}
    347
    348	return isl29501_register_write(isl29501, reg, val);
    349}
    350
    351static unsigned int isl29501_find_corr_exp(unsigned int val,
    352					   unsigned int max_exp,
    353					   unsigned int max_mantissa)
    354{
    355	unsigned int exp = 1;
    356
    357	/*
    358	 * Correction coefficients are represented under
    359	 * mantissa * 2^exponent form, where mantissa and exponent
    360	 * are stored in two separate registers of the sensor.
    361	 *
    362	 * Compute and return the lowest exponent such as:
    363	 *	     mantissa = value / 2^exponent
    364	 *
    365	 *  where mantissa < max_mantissa.
    366	 */
    367	if (val <= max_mantissa)
    368		return 0;
    369
    370	while ((val >> exp) > max_mantissa) {
    371		exp++;
    372
    373		if (exp > max_exp)
    374			return max_exp;
    375	}
    376
    377	return exp;
    378}
    379
    380static ssize_t isl29501_write_ext(struct iio_dev *indio_dev,
    381				  uintptr_t private,
    382				  const struct iio_chan_spec *chan,
    383				  const char *buf, size_t len)
    384{
    385	struct isl29501_private *isl29501 = iio_priv(indio_dev);
    386	enum isl29501_register_name reg = private;
    387	unsigned int val;
    388	int max_exp = 0;
    389	int ret;
    390	int i;
    391
    392	ret = kstrtouint(buf, 10, &val);
    393	if (ret)
    394		return ret;
    395
    396	switch (reg) {
    397	case REG_GAIN_BIAS:
    398		if (val > U16_MAX)
    399			return -ERANGE;
    400
    401		ret = isl29501_register_write(isl29501, reg, val);
    402		if (ret < 0)
    403			return ret;
    404
    405		break;
    406	case REG_CALIB_PHASE_TEMP_A:
    407	case REG_CALIB_PHASE_TEMP_B:
    408	case REG_CALIB_PHASE_LIGHT_A:
    409	case REG_CALIB_PHASE_LIGHT_B:
    410
    411		if (val > (U8_MAX << ISL29501_MAX_EXP_VAL))
    412			return -ERANGE;
    413
    414		/* Store the correction coefficient under its exact form. */
    415		ret = isl29501_set_shadow_coeff(isl29501, reg, val);
    416		if (ret < 0)
    417			return ret;
    418
    419		/*
    420		 * Find the highest exponent needed to represent
    421		 * correction coefficients.
    422		 */
    423		for (i = 0; i < COEFF_MAX; i++) {
    424			int corr;
    425			int corr_exp;
    426
    427			corr = isl29501->shadow_coeffs[i];
    428			corr_exp = isl29501_find_corr_exp(corr,
    429							  ISL29501_MAX_EXP_VAL,
    430							  U8_MAX / 2);
    431			dev_dbg(&isl29501->client->dev,
    432				"found exp of corr(%d) = %d\n", corr, corr_exp);
    433
    434			max_exp = max(max_exp, corr_exp);
    435		}
    436
    437		/*
    438		 * Represent every correction coefficient under
    439		 * mantissa * 2^max_exponent form and force the
    440		 * writing of those coefficients on the sensor.
    441		 */
    442		for (i = 0; i < COEFF_MAX; i++) {
    443			int corr;
    444			int mantissa;
    445
    446			corr = isl29501->shadow_coeffs[i];
    447			if (!corr)
    448				continue;
    449
    450			mantissa = corr >> max_exp;
    451
    452			ret = isl29501_write_coeff(isl29501, i, mantissa);
    453			if (ret < 0)
    454				return ret;
    455		}
    456
    457		ret = isl29501_register_write(isl29501, REG_PHASE_EXP, max_exp);
    458		if (ret < 0)
    459			return ret;
    460
    461		break;
    462	default:
    463		return -EINVAL;
    464	}
    465
    466	return len;
    467}
    468
    469#define _ISL29501_EXT_INFO(_name, _ident) { \
    470	.name = _name, \
    471	.read = isl29501_read_ext, \
    472	.write = isl29501_write_ext, \
    473	.private = _ident, \
    474	.shared = IIO_SEPARATE, \
    475}
    476
    477static const struct iio_chan_spec_ext_info isl29501_ext_info[] = {
    478	_ISL29501_EXT_INFO("agc_gain", REG_GAIN),
    479	_ISL29501_EXT_INFO("agc_gain_bias", REG_GAIN_BIAS),
    480	_ISL29501_EXT_INFO("calib_phase_temp_a", REG_CALIB_PHASE_TEMP_A),
    481	_ISL29501_EXT_INFO("calib_phase_temp_b", REG_CALIB_PHASE_TEMP_B),
    482	_ISL29501_EXT_INFO("calib_phase_light_a", REG_CALIB_PHASE_LIGHT_A),
    483	_ISL29501_EXT_INFO("calib_phase_light_b", REG_CALIB_PHASE_LIGHT_B),
    484	{ },
    485};
    486
    487#define ISL29501_DISTANCE_SCAN_INDEX 0
    488#define ISL29501_TIMESTAMP_SCAN_INDEX 1
    489
    490static const struct iio_chan_spec isl29501_channels[] = {
    491	{
    492		.type = IIO_PROXIMITY,
    493		.scan_index = ISL29501_DISTANCE_SCAN_INDEX,
    494		.info_mask_separate =
    495			BIT(IIO_CHAN_INFO_RAW)   |
    496			BIT(IIO_CHAN_INFO_SCALE) |
    497			BIT(IIO_CHAN_INFO_CALIBBIAS),
    498		.scan_type = {
    499			.sign = 'u',
    500			.realbits = 16,
    501			.storagebits = 16,
    502			.endianness = IIO_CPU,
    503		},
    504		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
    505				BIT(IIO_CHAN_INFO_SAMP_FREQ),
    506		.ext_info = isl29501_ext_info,
    507	},
    508	{
    509		.type = IIO_PHASE,
    510		.scan_index = -1,
    511		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    512				BIT(IIO_CHAN_INFO_SCALE),
    513	},
    514	{
    515		.type = IIO_CURRENT,
    516		.scan_index = -1,
    517		.output = 1,
    518		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    519				BIT(IIO_CHAN_INFO_SCALE),
    520	},
    521	{
    522		.type = IIO_TEMP,
    523		.scan_index = -1,
    524		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    525				BIT(IIO_CHAN_INFO_SCALE)     |
    526				BIT(IIO_CHAN_INFO_CALIBBIAS),
    527	},
    528	{
    529		.type = IIO_INTENSITY,
    530		.scan_index = -1,
    531		.modified = 1,
    532		.channel2 = IIO_MOD_LIGHT_CLEAR,
    533		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    534				BIT(IIO_CHAN_INFO_SCALE),
    535	},
    536	IIO_CHAN_SOFT_TIMESTAMP(ISL29501_TIMESTAMP_SCAN_INDEX),
    537};
    538
    539static int isl29501_reset_registers(struct isl29501_private *isl29501)
    540{
    541	int ret;
    542
    543	ret = i2c_smbus_write_byte_data(isl29501->client,
    544					ISL29501_COMMAND_REGISTER,
    545					ISL29501_RESET_ALL_REGISTERS);
    546	if (ret < 0) {
    547		dev_err(&isl29501->client->dev,
    548			"cannot reset registers %d\n", ret);
    549		return ret;
    550	}
    551
    552	ret = i2c_smbus_write_byte_data(isl29501->client,
    553					ISL29501_COMMAND_REGISTER,
    554					ISL29501_RESET_INT_SM);
    555	if (ret < 0)
    556		dev_err(&isl29501->client->dev,
    557			"cannot reset state machine %d\n", ret);
    558
    559	return ret;
    560}
    561
    562static int isl29501_begin_acquisition(struct isl29501_private *isl29501)
    563{
    564	int ret;
    565
    566	ret = i2c_smbus_write_byte_data(isl29501->client,
    567					ISL29501_COMMAND_REGISTER,
    568					ISL29501_EMUL_SAMPLE_START_PIN);
    569	if (ret < 0)
    570		dev_err(&isl29501->client->dev,
    571			"cannot begin acquisition %d\n", ret);
    572
    573	return ret;
    574}
    575
    576static IIO_CONST_ATTR_INT_TIME_AVAIL(ISL29501_INT_TIME_AVAILABLE);
    577static IIO_CONST_ATTR(out_current_scale_available,
    578		      ISL29501_CURRENT_SCALE_AVAILABLE);
    579
    580static struct attribute *isl29501_attributes[] = {
    581	&iio_const_attr_integration_time_available.dev_attr.attr,
    582	&iio_const_attr_out_current_scale_available.dev_attr.attr,
    583	NULL
    584};
    585
    586static const struct attribute_group isl29501_attribute_group = {
    587	.attrs = isl29501_attributes,
    588};
    589
    590static const int isl29501_current_scale_table[][2] = {
    591	{0, 3900}, {0, 7800}, {0, 11800}, {0, 15700},
    592	{0, 19600}, {0, 23500}, {0, 27500}, {0, 31400},
    593	{0, 35200}, {0, 39200}, {0, 43100}, {0, 47100},
    594	{0, 51000}, {0, 54900}, {0, 58800},
    595};
    596
    597static const int isl29501_int_time[][2] = {
    598	{0, 70},    /* 0.07 ms */
    599	{0, 140},   /* 0.14 ms */
    600	{0, 280},   /* 0.28 ms */
    601	{0, 570},   /* 0.57 ms */
    602	{0, 1140},  /* 1.14 ms */
    603	{0, 2280},  /* 2.28 ms */
    604	{0, 4550},  /* 4.55 ms */
    605	{0, 9100},  /* 9.11 ms */
    606	{0, 18200}, /* 18.2 ms */
    607	{0, 36400}, /* 36.4 ms */
    608	{0, 72810}, /* 72.81 ms */
    609	{0, 145610} /* 145.28 ms */
    610};
    611
    612static int isl29501_get_raw(struct isl29501_private *isl29501,
    613			    const struct iio_chan_spec *chan,
    614			    int *raw)
    615{
    616	int ret;
    617
    618	switch (chan->type) {
    619	case IIO_PROXIMITY:
    620		ret = isl29501_register_read(isl29501, REG_DISTANCE, raw);
    621		if (ret < 0)
    622			return ret;
    623
    624		return IIO_VAL_INT;
    625	case IIO_INTENSITY:
    626		ret = isl29501_register_read(isl29501,
    627					     REG_AMBIENT_LIGHT,
    628					     raw);
    629		if (ret < 0)
    630			return ret;
    631
    632		return IIO_VAL_INT;
    633	case IIO_PHASE:
    634		ret = isl29501_register_read(isl29501, REG_PHASE, raw);
    635		if (ret < 0)
    636			return ret;
    637
    638		return IIO_VAL_INT;
    639	case IIO_CURRENT:
    640		ret = isl29501_register_read(isl29501, REG_EMITTER_DAC, raw);
    641		if (ret < 0)
    642			return ret;
    643
    644		return IIO_VAL_INT;
    645	case IIO_TEMP:
    646		ret = isl29501_register_read(isl29501, REG_TEMPERATURE, raw);
    647		if (ret < 0)
    648			return ret;
    649
    650		return IIO_VAL_INT;
    651	default:
    652		return -EINVAL;
    653	}
    654}
    655
    656static int isl29501_get_scale(struct isl29501_private *isl29501,
    657			      const struct iio_chan_spec *chan,
    658			      int *val, int *val2)
    659{
    660	int ret;
    661	u32 current_scale;
    662
    663	switch (chan->type) {
    664	case IIO_PROXIMITY:
    665		/* distance = raw_distance * 33.31 / 65536 (m) */
    666		*val = 3331;
    667		*val2 = 6553600;
    668
    669		return IIO_VAL_FRACTIONAL;
    670	case IIO_PHASE:
    671		/* phase = raw_phase * 2pi / 65536 (rad) */
    672		*val = 0;
    673		*val2 = 95874;
    674
    675		return IIO_VAL_INT_PLUS_NANO;
    676	case IIO_INTENSITY:
    677		/* light = raw_light * 35 / 10000 (mA) */
    678		*val = 35;
    679		*val2 = 10000;
    680
    681		return IIO_VAL_FRACTIONAL;
    682	case IIO_CURRENT:
    683		ret = isl29501_register_read(isl29501,
    684					     REG_DRIVER_RANGE,
    685					     &current_scale);
    686		if (ret < 0)
    687			return ret;
    688
    689		if (current_scale > ARRAY_SIZE(isl29501_current_scale_table))
    690			return -EINVAL;
    691
    692		if (!current_scale) {
    693			*val = 0;
    694			*val2 = 0;
    695			return IIO_VAL_INT;
    696		}
    697
    698		*val = isl29501_current_scale_table[current_scale - 1][0];
    699		*val2 = isl29501_current_scale_table[current_scale - 1][1];
    700
    701		return IIO_VAL_INT_PLUS_MICRO;
    702	case IIO_TEMP:
    703		/* temperature = raw_temperature * 125 / 100000 (milli °C) */
    704		*val = 125;
    705		*val2 = 100000;
    706
    707		return IIO_VAL_FRACTIONAL;
    708	default:
    709		return -EINVAL;
    710	}
    711}
    712
    713static int isl29501_get_calibbias(struct isl29501_private *isl29501,
    714				  const struct iio_chan_spec *chan,
    715				  int *bias)
    716{
    717	switch (chan->type) {
    718	case IIO_PROXIMITY:
    719		return isl29501_register_read(isl29501,
    720					      REG_DISTANCE_BIAS,
    721					      bias);
    722	case IIO_TEMP:
    723		return isl29501_register_read(isl29501,
    724					      REG_TEMPERATURE_BIAS,
    725					      bias);
    726	default:
    727		return -EINVAL;
    728	}
    729}
    730
    731static int isl29501_get_inttime(struct isl29501_private *isl29501,
    732				int *val, int *val2)
    733{
    734	int ret;
    735	u32 inttime;
    736
    737	ret = isl29501_register_read(isl29501, REG_INT_TIME, &inttime);
    738	if (ret < 0)
    739		return ret;
    740
    741	if (inttime >= ARRAY_SIZE(isl29501_int_time))
    742		return -EINVAL;
    743
    744	*val = isl29501_int_time[inttime][0];
    745	*val2 = isl29501_int_time[inttime][1];
    746
    747	return IIO_VAL_INT_PLUS_MICRO;
    748}
    749
    750static int isl29501_get_freq(struct isl29501_private *isl29501,
    751			     int *val, int *val2)
    752{
    753	int ret;
    754	int sample_time;
    755	unsigned long long freq;
    756	u32 temp;
    757
    758	ret = isl29501_register_read(isl29501, REG_SAMPLE_TIME, &sample_time);
    759	if (ret < 0)
    760		return ret;
    761
    762	/* freq = 1 / (0.000450 * (sample_time + 1) * 10^-6) */
    763	freq = 1000000ULL * 1000000ULL;
    764
    765	do_div(freq, 450 * (sample_time + 1));
    766
    767	temp = do_div(freq, 1000000);
    768	*val = freq;
    769	*val2 = temp;
    770
    771	return IIO_VAL_INT_PLUS_MICRO;
    772}
    773
    774static int isl29501_read_raw(struct iio_dev *indio_dev,
    775			     struct iio_chan_spec const *chan, int *val,
    776			     int *val2, long mask)
    777{
    778	struct isl29501_private *isl29501 = iio_priv(indio_dev);
    779
    780	switch (mask) {
    781	case IIO_CHAN_INFO_RAW:
    782		return isl29501_get_raw(isl29501, chan, val);
    783	case IIO_CHAN_INFO_SCALE:
    784		return isl29501_get_scale(isl29501, chan, val, val2);
    785	case IIO_CHAN_INFO_INT_TIME:
    786		return isl29501_get_inttime(isl29501, val, val2);
    787	case IIO_CHAN_INFO_SAMP_FREQ:
    788		return isl29501_get_freq(isl29501, val, val2);
    789	case IIO_CHAN_INFO_CALIBBIAS:
    790		return isl29501_get_calibbias(isl29501, chan, val);
    791	default:
    792		return -EINVAL;
    793	}
    794}
    795
    796static int isl29501_set_raw(struct isl29501_private *isl29501,
    797			    const struct iio_chan_spec *chan,
    798			    int raw)
    799{
    800	switch (chan->type) {
    801	case IIO_CURRENT:
    802		return isl29501_register_write(isl29501, REG_EMITTER_DAC, raw);
    803	default:
    804		return -EINVAL;
    805	}
    806}
    807
    808static int isl29501_set_inttime(struct isl29501_private *isl29501,
    809				int val, int val2)
    810{
    811	int i;
    812
    813	for (i = 0; i < ARRAY_SIZE(isl29501_int_time); i++) {
    814		if (isl29501_int_time[i][0] == val &&
    815		    isl29501_int_time[i][1] == val2) {
    816			return isl29501_register_write(isl29501,
    817						       REG_INT_TIME,
    818						       i);
    819		}
    820	}
    821
    822	return -EINVAL;
    823}
    824
    825static int isl29501_set_scale(struct isl29501_private *isl29501,
    826			      const struct iio_chan_spec *chan,
    827			      int val, int val2)
    828{
    829	int i;
    830
    831	if (chan->type != IIO_CURRENT)
    832		return -EINVAL;
    833
    834	for (i = 0; i < ARRAY_SIZE(isl29501_current_scale_table); i++) {
    835		if (isl29501_current_scale_table[i][0] == val &&
    836		    isl29501_current_scale_table[i][1] == val2) {
    837			return isl29501_register_write(isl29501,
    838						       REG_DRIVER_RANGE,
    839						       i + 1);
    840		}
    841	}
    842
    843	return -EINVAL;
    844}
    845
    846static int isl29501_set_calibbias(struct isl29501_private *isl29501,
    847				  const struct iio_chan_spec *chan,
    848				  int bias)
    849{
    850	switch (chan->type) {
    851	case IIO_PROXIMITY:
    852		return isl29501_register_write(isl29501,
    853					      REG_DISTANCE_BIAS,
    854					      bias);
    855	case IIO_TEMP:
    856		return isl29501_register_write(isl29501,
    857					       REG_TEMPERATURE_BIAS,
    858					       bias);
    859	default:
    860		return -EINVAL;
    861	}
    862}
    863
    864static int isl29501_set_freq(struct isl29501_private *isl29501,
    865			     int val, int val2)
    866{
    867	int freq;
    868	unsigned long long sample_time;
    869
    870	/* sample_freq = 1 / (0.000450 * (sample_time + 1) * 10^-6) */
    871	freq = val * 1000000 + val2 % 1000000;
    872	sample_time = 2222ULL * 1000000ULL;
    873	do_div(sample_time, freq);
    874
    875	sample_time -= 1;
    876
    877	if (sample_time > 255)
    878		return -ERANGE;
    879
    880	return isl29501_register_write(isl29501, REG_SAMPLE_TIME, sample_time);
    881}
    882
    883static int isl29501_write_raw(struct iio_dev *indio_dev,
    884			      struct iio_chan_spec const *chan,
    885			      int val, int val2, long mask)
    886{
    887	struct isl29501_private *isl29501 = iio_priv(indio_dev);
    888
    889	switch (mask) {
    890	case IIO_CHAN_INFO_RAW:
    891		return isl29501_set_raw(isl29501, chan, val);
    892	case IIO_CHAN_INFO_INT_TIME:
    893		return isl29501_set_inttime(isl29501, val, val2);
    894	case IIO_CHAN_INFO_SAMP_FREQ:
    895		return isl29501_set_freq(isl29501, val, val2);
    896	case IIO_CHAN_INFO_SCALE:
    897		return isl29501_set_scale(isl29501, chan, val, val2);
    898	case IIO_CHAN_INFO_CALIBBIAS:
    899		return isl29501_set_calibbias(isl29501, chan, val);
    900	default:
    901		return -EINVAL;
    902	}
    903}
    904
    905static const struct iio_info isl29501_info = {
    906	.read_raw = &isl29501_read_raw,
    907	.write_raw = &isl29501_write_raw,
    908	.attrs = &isl29501_attribute_group,
    909};
    910
    911static int isl29501_init_chip(struct isl29501_private *isl29501)
    912{
    913	int ret;
    914
    915	ret = i2c_smbus_read_byte_data(isl29501->client, ISL29501_DEVICE_ID);
    916	if (ret < 0) {
    917		dev_err(&isl29501->client->dev, "Error reading device id\n");
    918		return ret;
    919	}
    920
    921	if (ret != ISL29501_ID) {
    922		dev_err(&isl29501->client->dev,
    923			"Wrong chip id, got %x expected %x\n",
    924			ret, ISL29501_DEVICE_ID);
    925		return -ENODEV;
    926	}
    927
    928	ret = isl29501_reset_registers(isl29501);
    929	if (ret < 0)
    930		return ret;
    931
    932	return isl29501_begin_acquisition(isl29501);
    933}
    934
    935static irqreturn_t isl29501_trigger_handler(int irq, void *p)
    936{
    937	struct iio_poll_func *pf = p;
    938	struct iio_dev *indio_dev = pf->indio_dev;
    939	struct isl29501_private *isl29501 = iio_priv(indio_dev);
    940	const unsigned long *active_mask = indio_dev->active_scan_mask;
    941	u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */
    942
    943	if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask))
    944		isl29501_register_read(isl29501, REG_DISTANCE, buffer);
    945
    946	iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp);
    947	iio_trigger_notify_done(indio_dev->trig);
    948
    949	return IRQ_HANDLED;
    950}
    951
    952static int isl29501_probe(struct i2c_client *client,
    953			  const struct i2c_device_id *id)
    954{
    955	struct iio_dev *indio_dev;
    956	struct isl29501_private *isl29501;
    957	int ret;
    958
    959	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*isl29501));
    960	if (!indio_dev)
    961		return -ENOMEM;
    962
    963	isl29501 = iio_priv(indio_dev);
    964
    965	i2c_set_clientdata(client, indio_dev);
    966	isl29501->client = client;
    967
    968	mutex_init(&isl29501->lock);
    969
    970	ret = isl29501_init_chip(isl29501);
    971	if (ret < 0)
    972		return ret;
    973
    974	indio_dev->modes = INDIO_DIRECT_MODE;
    975	indio_dev->channels = isl29501_channels;
    976	indio_dev->num_channels = ARRAY_SIZE(isl29501_channels);
    977	indio_dev->name = client->name;
    978	indio_dev->info = &isl29501_info;
    979
    980	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
    981					      iio_pollfunc_store_time,
    982					      isl29501_trigger_handler,
    983					      NULL);
    984	if (ret < 0) {
    985		dev_err(&client->dev, "unable to setup iio triggered buffer\n");
    986		return ret;
    987	}
    988
    989	return devm_iio_device_register(&client->dev, indio_dev);
    990}
    991
    992static const struct i2c_device_id isl29501_id[] = {
    993	{"isl29501", 0},
    994	{}
    995};
    996
    997MODULE_DEVICE_TABLE(i2c, isl29501_id);
    998
    999#if defined(CONFIG_OF)
   1000static const struct of_device_id isl29501_i2c_matches[] = {
   1001	{ .compatible = "renesas,isl29501" },
   1002	{ }
   1003};
   1004MODULE_DEVICE_TABLE(of, isl29501_i2c_matches);
   1005#endif
   1006
   1007static struct i2c_driver isl29501_driver = {
   1008	.driver = {
   1009		.name	= "isl29501",
   1010	},
   1011	.id_table	= isl29501_id,
   1012	.probe		= isl29501_probe,
   1013};
   1014module_i2c_driver(isl29501_driver);
   1015
   1016MODULE_AUTHOR("Mathieu Othacehe <m.othacehe@gmail.com>");
   1017MODULE_DESCRIPTION("ISL29501 Time of Flight sensor driver");
   1018MODULE_LICENSE("GPL v2");