Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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");