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