^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Support for AMS AS73211 JENCOLOR(R) Digital XYZ Sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Author: Christian Eggers <ceggers@arri.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2020 ARRI Lighting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Color light sensor with 16-bit channels for x, y, z and temperature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 7-bit I2C slave address 0x74 .. 0x77.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Datasheet: https://ams.com/documents/20143/36005/AS73211_DS000556_3-01.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/bitfield.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/iio/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define HZ_PER_KHZ 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define AS73211_DRV_NAME "as73211"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* AS73211 configuration registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define AS73211_REG_OSR 0x0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define AS73211_REG_AGEN 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define AS73211_REG_CREG1 0x6
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define AS73211_REG_CREG2 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define AS73211_REG_CREG3 0x8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* AS73211 output register bank */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define AS73211_OUT_OSR_STATUS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define AS73211_OUT_TEMP 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define AS73211_OUT_MRES1 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define AS73211_OUT_MRES2 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define AS73211_OUT_MRES3 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define AS73211_OSR_SS BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define AS73211_OSR_PD BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define AS73211_OSR_SW_RES BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define AS73211_OSR_DOS_MASK GENMASK(2, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define AS73211_OSR_DOS_CONFIG FIELD_PREP(AS73211_OSR_DOS_MASK, 0x2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define AS73211_OSR_DOS_MEASURE FIELD_PREP(AS73211_OSR_DOS_MASK, 0x3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define AS73211_AGEN_DEVID_MASK GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define AS73211_AGEN_DEVID(x) FIELD_PREP(AS73211_AGEN_DEVID_MASK, (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define AS73211_AGEN_MUT_MASK GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define AS73211_AGEN_MUT(x) FIELD_PREP(AS73211_AGEN_MUT_MASK, (x))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define AS73211_CREG1_GAIN_MASK GENMASK(7, 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define AS73211_CREG1_GAIN_1 11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define AS73211_CREG1_TIME_MASK GENMASK(3, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define AS73211_CREG3_CCLK_MASK GENMASK(1, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define AS73211_OSR_STATUS_OUTCONVOF BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define AS73211_OSR_STATUS_MRESOF BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define AS73211_OSR_STATUS_ADCOF BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define AS73211_OSR_STATUS_LDATA BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define AS73211_OSR_STATUS_NDATA BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define AS73211_OSR_STATUS_NOTREADY BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define AS73211_SAMPLE_FREQ_BASE 1024000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define AS73211_SAMPLE_TIME_NUM 15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define AS73211_SAMPLE_TIME_MAX_MS BIT(AS73211_SAMPLE_TIME_NUM - 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) /* Available sample frequencies are 1.024MHz multiplied by powers of two. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static const int as73211_samp_freq_avail[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) AS73211_SAMPLE_FREQ_BASE * 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) AS73211_SAMPLE_FREQ_BASE * 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) AS73211_SAMPLE_FREQ_BASE * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) AS73211_SAMPLE_FREQ_BASE * 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) static const int as73211_hardwaregain_avail[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * struct as73211_data - Instance data for one AS73211
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @client: I2C client.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * @osr: Cached Operational State Register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * @creg1: Cached Configuration Register 1.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * @creg2: Cached Configuration Register 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * @creg3: Cached Configuration Register 3.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * @mutex: Keeps cached registers in sync with the device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @completion: Completion to wait for interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * @int_time_avail: Available integration times (depend on sampling frequency).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct as73211_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) u8 osr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) u8 creg1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) u8 creg2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) u8 creg3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) struct completion completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int int_time_avail[AS73211_SAMPLE_TIME_NUM * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) #define AS73211_COLOR_CHANNEL(_color, _si, _addr) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) .type = IIO_INTENSITY, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) .modified = 1, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .info_mask_shared_by_type = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) BIT(IIO_CHAN_INFO_INT_TIME), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .info_mask_shared_by_type_available = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) BIT(IIO_CHAN_INFO_HARDWAREGAIN) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) BIT(IIO_CHAN_INFO_INT_TIME), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .channel2 = IIO_MOD_##_color, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .address = _addr, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .scan_index = _si, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .scan_type = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .sign = 'u', \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .realbits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .storagebits = 16, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) .endianness = IIO_LE, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }, \
^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) #define AS73211_OFFSET_TEMP_INT (-66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) #define AS73211_OFFSET_TEMP_MICRO 900000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #define AS73211_SCALE_TEMP_INT 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) #define AS73211_SCALE_TEMP_MICRO 50000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) #define AS73211_SCALE_X 277071108 /* nW/m^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #define AS73211_SCALE_Y 298384270 /* nW/m^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) #define AS73211_SCALE_Z 160241927 /* nW/m^2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* Channel order MUST match devices result register order */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #define AS73211_SCAN_INDEX_TEMP 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #define AS73211_SCAN_INDEX_X 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #define AS73211_SCAN_INDEX_Y 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #define AS73211_SCAN_INDEX_Z 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #define AS73211_SCAN_INDEX_TS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #define AS73211_SCAN_MASK_COLOR ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) BIT(AS73211_SCAN_INDEX_X) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) BIT(AS73211_SCAN_INDEX_Y) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) BIT(AS73211_SCAN_INDEX_Z))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #define AS73211_SCAN_MASK_ALL ( \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) BIT(AS73211_SCAN_INDEX_TEMP) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) AS73211_SCAN_MASK_COLOR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static const struct iio_chan_spec as73211_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) .info_mask_separate =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) BIT(IIO_CHAN_INFO_OFFSET) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) .address = AS73211_OUT_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) .scan_index = AS73211_SCAN_INDEX_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) .realbits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) .storagebits = 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) .endianness = IIO_LE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) AS73211_COLOR_CHANNEL(X, AS73211_SCAN_INDEX_X, AS73211_OUT_MRES1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) AS73211_COLOR_CHANNEL(Y, AS73211_SCAN_INDEX_Y, AS73211_OUT_MRES2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) AS73211_COLOR_CHANNEL(Z, AS73211_SCAN_INDEX_Z, AS73211_OUT_MRES3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) IIO_CHAN_SOFT_TIMESTAMP(AS73211_SCAN_INDEX_TS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) static unsigned int as73211_integration_time_1024cyc(struct as73211_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) * Return integration time in units of 1024 clock cycles. Integration time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * in CREG1 is in powers of 2 (x 1024 cycles).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) return BIT(FIELD_GET(AS73211_CREG1_TIME_MASK, data->creg1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) static unsigned int as73211_integration_time_us(struct as73211_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) unsigned int integration_time_1024cyc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) * t_cycl is configured in CREG1 in powers of 2 (x 1024 cycles)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * t_int_us = 1 / (f_samp) * t_cycl * US_PER_SEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * = 1 / (2^CREG3_CCLK * 1,024,000) * 2^CREG1_CYCLES * 1,024 * US_PER_SEC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * = 2^(-CREG3_CCLK) * 2^CREG1_CYCLES * 1,000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * In order to get rid of negative exponents, we extend the "fraction"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) * by 2^3 (CREG3_CCLK,max = 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * t_int_us = 2^(3-CREG3_CCLK) * 2^CREG1_CYCLES * 125
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return BIT(3 - FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3)) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) integration_time_1024cyc * 125;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) static void as73211_integration_time_calc_avail(struct as73211_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) for (i = 0; i < ARRAY_SIZE(data->int_time_avail) / 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned int time_us = as73211_integration_time_us(data, BIT(i));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) data->int_time_avail[i * 2 + 0] = time_us / USEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) data->int_time_avail[i * 2 + 1] = time_us % USEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) static unsigned int as73211_gain(struct as73211_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* gain can be calculated from CREG1 as 2^(11 - CREG1_GAIN) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return BIT(AS73211_CREG1_GAIN_1 - FIELD_GET(AS73211_CREG1_GAIN_MASK, data->creg1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /* must be called with as73211_data::mutex held. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static int as73211_req_data(struct as73211_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) unsigned int time_us = as73211_integration_time_us(data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) as73211_integration_time_1024cyc(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct device *dev = &data->client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) union i2c_smbus_data smbus_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) u16 osr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) if (data->client->irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) reinit_completion(&data->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * During measurement, there should be no traffic on the i2c bus as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * electrical noise would disturb the measurement process.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) i2c_lock_bus(data->client->adapter, I2C_LOCK_SEGMENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) data->osr &= ~AS73211_OSR_DOS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) data->osr |= AS73211_OSR_DOS_MEASURE | AS73211_OSR_SS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) smbus_data.byte = data->osr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) ret = __i2c_smbus_xfer(data->client->adapter, data->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) data->client->flags, I2C_SMBUS_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) AS73211_REG_OSR, I2C_SMBUS_BYTE_DATA, &smbus_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * Reset AS73211_OSR_SS (is self clearing) in order to avoid unintentional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * triggering of further measurements later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) data->osr &= ~AS73211_OSR_SS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * Add 33% extra margin for the timeout. fclk,min = fclk,typ - 27%.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) time_us += time_us / 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (data->client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = wait_for_completion_timeout(&data->completion, usecs_to_jiffies(time_us));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) dev_err(dev, "timeout waiting for READY IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /* Wait integration time */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) usleep_range(time_us, 2 * time_us);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) i2c_unlock_bus(data->client->adapter, I2C_LOCK_SEGMENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ret = i2c_smbus_read_word_data(data->client, AS73211_OUT_OSR_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) osr_status = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (osr_status != (AS73211_OSR_DOS_MEASURE | AS73211_OSR_STATUS_NDATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (osr_status & AS73211_OSR_SS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) dev_err(dev, "%s() Measurement has not stopped\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (osr_status & AS73211_OSR_STATUS_NOTREADY) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) dev_err(dev, "%s() Data is not ready\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!(osr_status & AS73211_OSR_STATUS_NDATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) dev_err(dev, "%s() No new data available\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return -ENODATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (osr_status & AS73211_OSR_STATUS_LDATA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) dev_err(dev, "%s() Result buffer overrun\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return -ENOBUFS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (osr_status & AS73211_OSR_STATUS_ADCOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_err(dev, "%s() ADC overflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (osr_status & AS73211_OSR_STATUS_MRESOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) dev_err(dev, "%s() Measurement result overflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (osr_status & AS73211_OSR_STATUS_OUTCONVOF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dev_err(dev, "%s() Timer overflow\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return -EOVERFLOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) dev_err(dev, "%s() Unexpected status value\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int as73211_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) case IIO_CHAN_INFO_RAW: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = as73211_req_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) ret = i2c_smbus_read_word_data(data->client, chan->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case IIO_CHAN_INFO_OFFSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) *val = AS73211_OFFSET_TEMP_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) *val2 = AS73211_OFFSET_TEMP_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) switch (chan->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) case IIO_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) *val = AS73211_SCALE_TEMP_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) *val2 = AS73211_SCALE_TEMP_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case IIO_INTENSITY: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) unsigned int scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) switch (chan->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) case IIO_MOD_X:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) scale = AS73211_SCALE_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case IIO_MOD_Y:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) scale = AS73211_SCALE_Y;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case IIO_MOD_Z:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) scale = AS73211_SCALE_Z;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) scale /= as73211_gain(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) scale /= as73211_integration_time_1024cyc(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) *val = scale;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) *val = BIT(FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3)) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) AS73211_SAMPLE_FREQ_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) case IIO_CHAN_INFO_HARDWAREGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) *val = as73211_gain(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) case IIO_CHAN_INFO_INT_TIME: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned int time_us;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) mutex_lock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) time_us = as73211_integration_time_us(data, as73211_integration_time_1024cyc(data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) mutex_unlock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) *val = time_us / USEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) *val2 = time_us % USEC_PER_SEC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) }}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) static int as73211_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) const int **vals, int *type, int *length, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *length = ARRAY_SIZE(as73211_samp_freq_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) *vals = as73211_samp_freq_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) *type = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return IIO_AVAIL_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) case IIO_CHAN_INFO_HARDWAREGAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) *length = ARRAY_SIZE(as73211_hardwaregain_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) *vals = as73211_hardwaregain_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) *type = IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return IIO_AVAIL_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) case IIO_CHAN_INFO_INT_TIME:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) *length = ARRAY_SIZE(data->int_time_avail);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) *vals = data->int_time_avail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) *type = IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) return IIO_AVAIL_LIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EINVAL;
^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) static int _as73211_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct iio_chan_spec const *chan __always_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) case IIO_CHAN_INFO_SAMP_FREQ: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int reg_bits, freq_kHz = val / HZ_PER_KHZ; /* 1024, 2048, ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /* val must be 1024 * 2^x */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (val < 0 || (freq_kHz * HZ_PER_KHZ) != val ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) !is_power_of_2(freq_kHz) || val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz (=2^10)) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) reg_bits = ilog2(freq_kHz) - 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (!FIELD_FIT(AS73211_CREG3_CCLK_MASK, reg_bits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) data->creg3 &= ~AS73211_CREG3_CCLK_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) data->creg3 |= FIELD_PREP(AS73211_CREG3_CCLK_MASK, reg_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) as73211_integration_time_calc_avail(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG3, data->creg3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case IIO_CHAN_INFO_HARDWAREGAIN: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) unsigned int reg_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (val < 0 || !is_power_of_2(val) || val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /* gain can be calculated from CREG1 as 2^(11 - CREG1_GAIN) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) reg_bits = AS73211_CREG1_GAIN_1 - ilog2(val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!FIELD_FIT(AS73211_CREG1_GAIN_MASK, reg_bits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) data->creg1 &= ~AS73211_CREG1_GAIN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) data->creg1 |= FIELD_PREP(AS73211_CREG1_GAIN_MASK, reg_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG1, data->creg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) case IIO_CHAN_INFO_INT_TIME: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) int val_us = val * USEC_PER_SEC + val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) int time_ms;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) int reg_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* f_samp is configured in CREG3 in powers of 2 (x 1.024 MHz) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) int f_samp_1_024mhz = BIT(FIELD_GET(AS73211_CREG3_CCLK_MASK, data->creg3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * time_ms = time_us * US_PER_MS * f_samp_1_024mhz / MHZ_PER_HZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * = time_us * f_samp_1_024mhz / 1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) time_ms = (val_us * f_samp_1_024mhz) / 1000; /* 1 ms, 2 ms, ... (power of two) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) if (time_ms < 0 || !is_power_of_2(time_ms) || time_ms > AS73211_SAMPLE_TIME_MAX_MS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) reg_bits = ilog2(time_ms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) if (!FIELD_FIT(AS73211_CREG1_TIME_MASK, reg_bits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return -EINVAL; /* not possible due to previous tests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) data->creg1 &= ~AS73211_CREG1_TIME_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) data->creg1 |= FIELD_PREP(AS73211_CREG1_TIME_MASK, reg_bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_CREG1, data->creg1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return -EINVAL;
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static int as73211_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) int val, int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) mutex_lock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) goto error_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* Need to switch to config mode ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) if ((data->osr & AS73211_OSR_DOS_MASK) != AS73211_OSR_DOS_CONFIG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) data->osr &= ~AS73211_OSR_DOS_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) data->osr |= AS73211_OSR_DOS_CONFIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) goto error_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) ret = _as73211_write_raw(indio_dev, chan, val, val2, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) error_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) error_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_unlock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static irqreturn_t as73211_ready_handler(int irq __always_unused, void *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct as73211_data *data = iio_priv(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) complete(&data->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static irqreturn_t as73211_trigger_handler(int irq __always_unused, void *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) struct iio_poll_func *pf = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) __le16 chan[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) s64 ts __aligned(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) } scan;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int data_result, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mutex_lock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) data_result = as73211_req_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (data_result < 0 && data_result != -EOVERFLOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) goto done; /* don't push any data for errors other than EOVERFLOW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (*indio_dev->active_scan_mask == AS73211_SCAN_MASK_ALL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* Optimization for reading all (color + temperature) channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u8 addr = as73211_channels[0].address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct i2c_msg msgs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .addr = data->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .flags = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) .len = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) .buf = &addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) .addr = data->client->addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) .flags = I2C_M_RD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) .len = sizeof(scan.chan),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) .buf = (u8 *)&scan.chan,
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) ret = i2c_transfer(data->client->adapter, msgs, ARRAY_SIZE(msgs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) /* Optimization for reading only color channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* AS73211 starts reading at address 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) ret = i2c_master_recv(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) (char *)&scan.chan[1], 3 * sizeof(scan.chan[1]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) if (data_result) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * Saturate all channels (in case of overflows). Temperature channel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * is not affected by overflows.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) scan.chan[1] = cpu_to_le16(U16_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) scan.chan[2] = cpu_to_le16(U16_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) scan.chan[3] = cpu_to_le16(U16_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) mutex_unlock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) static const struct iio_info as73211_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) .read_raw = as73211_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) .read_avail = as73211_read_avail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) .write_raw = as73211_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) static int as73211_power(struct iio_dev *indio_dev, bool state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct as73211_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) mutex_lock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) data->osr &= ~AS73211_OSR_PD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) data->osr |= AS73211_OSR_PD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) mutex_unlock(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static void as73211_power_disable(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct iio_dev *indio_dev = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) as73211_power(indio_dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) static int as73211_probe(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) struct device *dev = &client->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct as73211_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) mutex_init(&data->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) init_completion(&data->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) indio_dev->info = &as73211_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) indio_dev->name = AS73211_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) indio_dev->channels = as73211_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) indio_dev->num_channels = ARRAY_SIZE(as73211_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) data->osr = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) /* reset device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) data->osr |= AS73211_OSR_SW_RES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) ret = i2c_smbus_write_byte_data(data->client, AS73211_REG_OSR, data->osr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_OSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) data->osr = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * Reading AGEN is only possible after reset (AGEN is not available if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) * device is in measurement mode).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_AGEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) /* At the time of writing this driver, only DEVID 2 and MUT 1 are known. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) if ((ret & AS73211_AGEN_DEVID_MASK) != AS73211_AGEN_DEVID(2) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) (ret & AS73211_AGEN_MUT_MASK) != AS73211_AGEN_MUT(1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) data->creg1 = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) data->creg2 = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) ret = i2c_smbus_read_byte_data(data->client, AS73211_REG_CREG3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) data->creg3 = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) as73211_integration_time_calc_avail(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) ret = as73211_power(indio_dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) ret = devm_add_action_or_reset(dev, as73211_power_disable, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, as73211_trigger_handler, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) ret = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) as73211_ready_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) client->name, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) return devm_iio_device_register(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static int __maybe_unused as73211_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return as73211_power(indio_dev, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static int __maybe_unused as73211_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return as73211_power(indio_dev, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) static SIMPLE_DEV_PM_OPS(as73211_pm_ops, as73211_suspend, as73211_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static const struct of_device_id as73211_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) { .compatible = "ams,as73211" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) MODULE_DEVICE_TABLE(of, as73211_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) static const struct i2c_device_id as73211_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) { "as73211", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) MODULE_DEVICE_TABLE(i2c, as73211_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) static struct i2c_driver as73211_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .name = AS73211_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) .of_match_table = as73211_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) .pm = &as73211_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) .probe_new = as73211_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) .id_table = as73211_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) module_i2c_driver(as73211_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) MODULE_AUTHOR("Christian Eggers <ceggers@arri.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) MODULE_DESCRIPTION("AS73211 XYZ True Color Sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) MODULE_LICENSE("GPL");