xref: /openbmc/linux/drivers/iio/magnetometer/yamaha-yas530.c (revision 278002edb19bce2c628fafb0af936e77000f3a5b)
1de8860b1SLinus Walleij // SPDX-License-Identifier: GPL-2.0-only
2de8860b1SLinus Walleij /*
3de8860b1SLinus Walleij  * Driver for the Yamaha YAS magnetic sensors, often used in Samsung
4de8860b1SLinus Walleij  * mobile phones. While all are not yet handled because of lacking
5de8860b1SLinus Walleij  * hardware, expand this driver to handle the different variants:
6de8860b1SLinus Walleij  *
7de8860b1SLinus Walleij  * YAS530 MS-3E (2011 Samsung Galaxy S Advance)
8de8860b1SLinus Walleij  * YAS532 MS-3R (2011 Samsung Galaxy S4)
9de8860b1SLinus Walleij  * YAS533 MS-3F (Vivo 1633, 1707, V3, Y21L)
10de8860b1SLinus Walleij  * (YAS534 is a magnetic switch, not handled)
11de8860b1SLinus Walleij  * YAS535 MS-6C
12de8860b1SLinus Walleij  * YAS536 MS-3W
1392d9c05cSJakob Hauser  * YAS537 MS-3T (2015 Samsung Galaxy S6, Note 5, Galaxy S7)
14de8860b1SLinus Walleij  * YAS539 MS-3S (2018 Samsung Galaxy A7 SM-A750FN)
15de8860b1SLinus Walleij  *
16de8860b1SLinus Walleij  * Code functions found in the MPU3050 YAS530 and YAS532 drivers
17de8860b1SLinus Walleij  * named "inv_compass" in the Tegra Android kernel tree.
18de8860b1SLinus Walleij  * Copyright (C) 2012 InvenSense Corporation
19de8860b1SLinus Walleij  *
2065f79b50SJakob Hauser  * Code functions for YAS537 based on Yamaha Android kernel driver.
2165f79b50SJakob Hauser  * Copyright (c) 2014 Yamaha Corporation
2265f79b50SJakob Hauser  *
23de8860b1SLinus Walleij  * Author: Linus Walleij <linus.walleij@linaro.org>
24de8860b1SLinus Walleij  */
25de8860b1SLinus Walleij #include <linux/bitfield.h>
26de8860b1SLinus Walleij #include <linux/bitops.h>
27de8860b1SLinus Walleij #include <linux/delay.h>
28de8860b1SLinus Walleij #include <linux/err.h>
29de8860b1SLinus Walleij #include <linux/gpio/consumer.h>
30de8860b1SLinus Walleij #include <linux/i2c.h>
31de8860b1SLinus Walleij #include <linux/module.h>
32de8860b1SLinus Walleij #include <linux/mod_devicetable.h>
33de8860b1SLinus Walleij #include <linux/mutex.h>
34de8860b1SLinus Walleij #include <linux/pm_runtime.h>
35741d1e37SAndy Shevchenko #include <linux/property.h>
36de8860b1SLinus Walleij #include <linux/regmap.h>
37de8860b1SLinus Walleij #include <linux/regulator/consumer.h>
38de8860b1SLinus Walleij #include <linux/random.h>
3965f79b50SJakob Hauser #include <linux/units.h>
40de8860b1SLinus Walleij 
41de8860b1SLinus Walleij #include <linux/iio/buffer.h>
42de8860b1SLinus Walleij #include <linux/iio/iio.h>
43de8860b1SLinus Walleij #include <linux/iio/trigger_consumer.h>
44de8860b1SLinus Walleij #include <linux/iio/triggered_buffer.h>
45de8860b1SLinus Walleij 
46bb354aebSLinus Walleij #include <asm/unaligned.h>
47bb354aebSLinus Walleij 
486e3bfa97SJakob Hauser /* Commonly used registers */
49de8860b1SLinus Walleij #define YAS5XX_DEVICE_ID		0x80
50de8860b1SLinus Walleij #define YAS5XX_MEASURE_DATA		0xB0
51de8860b1SLinus Walleij 
526e3bfa97SJakob Hauser /* These registers are used by YAS530, YAS532 and YAS533 */
536e3bfa97SJakob Hauser #define YAS530_ACTUATE_INIT_COIL	0x81
546e3bfa97SJakob Hauser #define YAS530_MEASURE			0x82
556e3bfa97SJakob Hauser #define YAS530_CONFIG			0x83
566e3bfa97SJakob Hauser #define YAS530_MEASURE_INTERVAL		0x84
576e3bfa97SJakob Hauser #define YAS530_OFFSET_X			0x85 /* [-31 .. 31] */
586e3bfa97SJakob Hauser #define YAS530_OFFSET_Y1		0x86 /* [-31 .. 31] */
596e3bfa97SJakob Hauser #define YAS530_OFFSET_Y2		0x87 /* [-31 .. 31] */
606e3bfa97SJakob Hauser #define YAS530_TEST1			0x88
616e3bfa97SJakob Hauser #define YAS530_TEST2			0x89
626e3bfa97SJakob Hauser #define YAS530_CAL			0x90
636e3bfa97SJakob Hauser 
6465f79b50SJakob Hauser /* Registers used by YAS537 */
6565f79b50SJakob Hauser #define YAS537_MEASURE			0x81 /* Originally YAS537_REG_CMDR */
6665f79b50SJakob Hauser #define YAS537_CONFIG			0x82 /* Originally YAS537_REG_CONFR */
6765f79b50SJakob Hauser #define YAS537_MEASURE_INTERVAL		0x83 /* Originally YAS537_REG_INTRVLR */
6865f79b50SJakob Hauser #define YAS537_OFFSET_X			0x84 /* Originally YAS537_REG_OXR */
6965f79b50SJakob Hauser #define YAS537_OFFSET_Y1		0x85 /* Originally YAS537_REG_OY1R */
7065f79b50SJakob Hauser #define YAS537_OFFSET_Y2		0x86 /* Originally YAS537_REG_OY2R */
7165f79b50SJakob Hauser #define YAS537_AVR			0x87
7265f79b50SJakob Hauser #define YAS537_HCK			0x88
7365f79b50SJakob Hauser #define YAS537_LCK			0x89
7465f79b50SJakob Hauser #define YAS537_SRST			0x90
7565f79b50SJakob Hauser #define YAS537_ADCCAL			0x91
7665f79b50SJakob Hauser #define YAS537_MTC			0x93
7765f79b50SJakob Hauser #define YAS537_OC			0x9E
7865f79b50SJakob Hauser #define YAS537_TRM			0x9F
7965f79b50SJakob Hauser #define YAS537_CAL			0xC0
8065f79b50SJakob Hauser 
81de8860b1SLinus Walleij /* Bits in the YAS5xx config register */
82de8860b1SLinus Walleij #define YAS5XX_CONFIG_INTON		BIT(0) /* Interrupt on? */
83de8860b1SLinus Walleij #define YAS5XX_CONFIG_INTHACT		BIT(1) /* Interrupt active high? */
84de8860b1SLinus Walleij #define YAS5XX_CONFIG_CCK_MASK		GENMASK(4, 2)
85de8860b1SLinus Walleij #define YAS5XX_CONFIG_CCK_SHIFT		2
86de8860b1SLinus Walleij 
87de8860b1SLinus Walleij /* Bits in the measure command register */
88de8860b1SLinus Walleij #define YAS5XX_MEASURE_START		BIT(0)
89de8860b1SLinus Walleij #define YAS5XX_MEASURE_LDTC		BIT(1)
90de8860b1SLinus Walleij #define YAS5XX_MEASURE_FORS		BIT(2)
91de8860b1SLinus Walleij #define YAS5XX_MEASURE_DLYMES		BIT(4)
9265f79b50SJakob Hauser #define YAS5XX_MEASURE_CONT		BIT(5)
93de8860b1SLinus Walleij 
94de8860b1SLinus Walleij /* Bits in the measure data register */
95de8860b1SLinus Walleij #define YAS5XX_MEASURE_DATA_BUSY	BIT(7)
96de8860b1SLinus Walleij 
97de8860b1SLinus Walleij #define YAS530_DEVICE_ID		0x01 /* YAS530 (MS-3E) */
98de8860b1SLinus Walleij #define YAS530_VERSION_A		0 /* YAS530 (MS-3E A) */
99de8860b1SLinus Walleij #define YAS530_VERSION_B		1 /* YAS530B (MS-3E B) */
100de8860b1SLinus Walleij #define YAS530_VERSION_A_COEF		380
101de8860b1SLinus Walleij #define YAS530_VERSION_B_COEF		550
102de8860b1SLinus Walleij #define YAS530_DATA_BITS		12
103de8860b1SLinus Walleij #define YAS530_DATA_CENTER		BIT(YAS530_DATA_BITS - 1)
104de8860b1SLinus Walleij #define YAS530_DATA_OVERFLOW		(BIT(YAS530_DATA_BITS) - 1)
105de8860b1SLinus Walleij 
106de8860b1SLinus Walleij #define YAS532_DEVICE_ID		0x02 /* YAS532/YAS533 (MS-3R/F) */
107de8860b1SLinus Walleij #define YAS532_VERSION_AB		0 /* YAS532/533 AB (MS-3R/F AB) */
108de8860b1SLinus Walleij #define YAS532_VERSION_AC		1 /* YAS532/533 AC (MS-3R/F AC) */
109de8860b1SLinus Walleij #define YAS532_VERSION_AB_COEF		1800
110de8860b1SLinus Walleij #define YAS532_VERSION_AC_COEF_X	850
111de8860b1SLinus Walleij #define YAS532_VERSION_AC_COEF_Y1	750
112de8860b1SLinus Walleij #define YAS532_VERSION_AC_COEF_Y2	750
113de8860b1SLinus Walleij #define YAS532_DATA_BITS		13
114de8860b1SLinus Walleij #define YAS532_DATA_CENTER		BIT(YAS532_DATA_BITS - 1)
115de8860b1SLinus Walleij #define YAS532_DATA_OVERFLOW		(BIT(YAS532_DATA_BITS) - 1)
116de8860b1SLinus Walleij 
117de8860b1SLinus Walleij #define YAS537_DEVICE_ID		0x07 /* YAS537 (MS-3T) */
11865f79b50SJakob Hauser #define YAS537_VERSION_0		0 /* Version naming unknown */
11965f79b50SJakob Hauser #define YAS537_VERSION_1		1 /* Version naming unknown */
12065f79b50SJakob Hauser #define YAS537_MAG_AVERAGE_32_MASK	GENMASK(6, 4)
12165f79b50SJakob Hauser #define YAS537_MEASURE_TIME_WORST_US	1500
12265f79b50SJakob Hauser #define YAS537_DEFAULT_SENSOR_DELAY_MS	50
12365f79b50SJakob Hauser #define YAS537_MAG_RCOIL_TIME_US	65
12465f79b50SJakob Hauser #define YAS537_MTC3_MASK_PREP		GENMASK(7, 0)
12565f79b50SJakob Hauser #define YAS537_MTC3_MASK_GET		GENMASK(7, 5)
12665f79b50SJakob Hauser #define YAS537_MTC3_ADD_BIT		BIT(4)
12765f79b50SJakob Hauser #define YAS537_HCK_MASK_PREP		GENMASK(4, 0)
12865f79b50SJakob Hauser #define YAS537_HCK_MASK_GET		GENMASK(7, 4)
12965f79b50SJakob Hauser #define YAS537_LCK_MASK_PREP		GENMASK(4, 0)
13065f79b50SJakob Hauser #define YAS537_LCK_MASK_GET		GENMASK(3, 0)
13165f79b50SJakob Hauser #define YAS537_OC_MASK_GET		GENMASK(5, 0)
132de8860b1SLinus Walleij 
133de8860b1SLinus Walleij /* Turn off device regulators etc after 5 seconds of inactivity */
134de8860b1SLinus Walleij #define YAS5XX_AUTOSUSPEND_DELAY_MS	5000
135de8860b1SLinus Walleij 
136a70f60e5SJakob Hauser enum chip_ids {
137a70f60e5SJakob Hauser 	yas530,
138a70f60e5SJakob Hauser 	yas532,
139a70f60e5SJakob Hauser 	yas533,
14065f79b50SJakob Hauser 	yas537,
141a70f60e5SJakob Hauser };
142a70f60e5SJakob Hauser 
143dd9bd44fSJakob Hauser static const int yas530_volatile_reg[] = {
144dd9bd44fSJakob Hauser 	YAS530_ACTUATE_INIT_COIL,
145dd9bd44fSJakob Hauser 	YAS530_MEASURE,
146dd9bd44fSJakob Hauser };
147dd9bd44fSJakob Hauser 
14865f79b50SJakob Hauser static const int yas537_volatile_reg[] = {
14965f79b50SJakob Hauser 	YAS537_MEASURE,
15065f79b50SJakob Hauser };
15165f79b50SJakob Hauser 
152de8860b1SLinus Walleij struct yas5xx_calibration {
153de8860b1SLinus Walleij 	/* Linearization calibration x, y1, y2 */
154de8860b1SLinus Walleij 	s32 r[3];
155de8860b1SLinus Walleij 	u32 f[3];
156de8860b1SLinus Walleij 	/* Temperature compensation calibration */
1570ca09faaSJakob Hauser 	s16 Cx, Cy1, Cy2;
158de8860b1SLinus Walleij 	/* Misc calibration coefficients */
1590ca09faaSJakob Hauser 	s8  a2, a3, a4, a6, a7, a8;
1600ca09faaSJakob Hauser 	s16 a5, a9;
1610ca09faaSJakob Hauser 	u8  k;
162de8860b1SLinus Walleij 	/* clock divider */
163de8860b1SLinus Walleij 	u8 dck;
164de8860b1SLinus Walleij };
165de8860b1SLinus Walleij 
166a70f60e5SJakob Hauser struct yas5xx;
167a70f60e5SJakob Hauser 
168a70f60e5SJakob Hauser /**
169a70f60e5SJakob Hauser  * struct yas5xx_chip_info - device-specific data and function pointers
170a70f60e5SJakob Hauser  * @devid: device ID number
171a70f60e5SJakob Hauser  * @product_name: product name of the YAS variant
172a70f60e5SJakob Hauser  * @version_names: version letters or namings
173dd9bd44fSJakob Hauser  * @volatile_reg: device-specific volatile registers
174dd9bd44fSJakob Hauser  * @volatile_reg_qty: quantity of device-specific volatile registers
175913fd409SJakob Hauser  * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE
1762d6676ecSJakob Hauser  * @t_ref: number of counts at reference temperature 20 °C
1772d6676ecSJakob Hauser  * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius
178059ff0f9SJakob Hauser  * @get_measure: function pointer to get a measurement
179059ff0f9SJakob Hauser  * @get_calibration_data: function pointer to get calibration data
180059ff0f9SJakob Hauser  * @dump_calibration: function pointer to dump calibration for debugging
181059ff0f9SJakob Hauser  * @measure_offsets: function pointer to measure the offsets
182059ff0f9SJakob Hauser  * @power_on: function pointer to power-on procedure
1832d6676ecSJakob Hauser  *
1842d6676ecSJakob Hauser  * The "t_ref" value for YAS532/533 is known from the Android driver.
18565f79b50SJakob Hauser  * For YAS530 and YAS537 it was approximately measured.
1862d6676ecSJakob Hauser  *
1872d6676ecSJakob Hauser  * The temperatures "min_temp_x10" are derived from the temperature resolutions
1882d6676ecSJakob Hauser  * given in the data sheets.
189a70f60e5SJakob Hauser  */
190a70f60e5SJakob Hauser struct yas5xx_chip_info {
191a70f60e5SJakob Hauser 	unsigned int devid;
192ff1c17e9SAndy Shevchenko 	const char *product_name;
193ff1c17e9SAndy Shevchenko 	const char *version_names[2];
194dd9bd44fSJakob Hauser 	const int *volatile_reg;
195dd9bd44fSJakob Hauser 	int volatile_reg_qty;
196913fd409SJakob Hauser 	u32 scaling_val2;
1972d6676ecSJakob Hauser 	u16 t_ref;
1982d6676ecSJakob Hauser 	s16 min_temp_x10;
199059ff0f9SJakob Hauser 	int (*get_measure)(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo);
200059ff0f9SJakob Hauser 	int (*get_calibration_data)(struct yas5xx *yas5xx);
201059ff0f9SJakob Hauser 	void (*dump_calibration)(struct yas5xx *yas5xx);
202059ff0f9SJakob Hauser 	int (*measure_offsets)(struct yas5xx *yas5xx);
203059ff0f9SJakob Hauser 	int (*power_on)(struct yas5xx *yas5xx);
204a70f60e5SJakob Hauser };
205a70f60e5SJakob Hauser 
206de8860b1SLinus Walleij /**
207de8860b1SLinus Walleij  * struct yas5xx - state container for the YAS5xx driver
208de8860b1SLinus Walleij  * @dev: parent device pointer
209059ff0f9SJakob Hauser  * @chip_info: device-specific data and function pointers
210de8860b1SLinus Walleij  * @version: device version
211de8860b1SLinus Walleij  * @calibration: calibration settings from the OTP storage
212de8860b1SLinus Walleij  * @hard_offsets: offsets for each axis measured with initcoil actuated
213de8860b1SLinus Walleij  * @orientation: mounting matrix, flipped axis etc
214de8860b1SLinus Walleij  * @map: regmap to access the YAX5xx registers over I2C
215de8860b1SLinus Walleij  * @regs: the vdd and vddio power regulators
216de8860b1SLinus Walleij  * @reset: optional GPIO line used for handling RESET
217de8860b1SLinus Walleij  * @lock: locks the magnetometer for exclusive use during a measurement (which
218de8860b1SLinus Walleij  * involves several register transactions so the regmap lock is not enough)
219de8860b1SLinus Walleij  * so that measurements get serialized in a first-come-first serve manner
220de8860b1SLinus Walleij  * @scan: naturally aligned measurements
221de8860b1SLinus Walleij  */
222de8860b1SLinus Walleij struct yas5xx {
223de8860b1SLinus Walleij 	struct device *dev;
224a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *chip_info;
225de8860b1SLinus Walleij 	unsigned int version;
226de8860b1SLinus Walleij 	struct yas5xx_calibration calibration;
227e137fafcSJakob Hauser 	s8 hard_offsets[3];
228de8860b1SLinus Walleij 	struct iio_mount_matrix orientation;
229de8860b1SLinus Walleij 	struct regmap *map;
230de8860b1SLinus Walleij 	struct regulator_bulk_data regs[2];
231de8860b1SLinus Walleij 	struct gpio_desc *reset;
232de8860b1SLinus Walleij 	struct mutex lock;
233de8860b1SLinus Walleij 	/*
234de8860b1SLinus Walleij 	 * The scanout is 4 x 32 bits in CPU endianness.
235de8860b1SLinus Walleij 	 * Ensure timestamp is naturally aligned
236de8860b1SLinus Walleij 	 */
237de8860b1SLinus Walleij 	struct {
238de8860b1SLinus Walleij 		s32 channels[4];
239de8860b1SLinus Walleij 		s64 ts __aligned(8);
240de8860b1SLinus Walleij 	} scan;
241de8860b1SLinus Walleij };
242de8860b1SLinus Walleij 
243de8860b1SLinus Walleij /* On YAS530 the x, y1 and y2 values are 12 bits */
yas530_extract_axis(u8 * data)244de8860b1SLinus Walleij static u16 yas530_extract_axis(u8 *data)
245de8860b1SLinus Walleij {
246de8860b1SLinus Walleij 	u16 val;
247de8860b1SLinus Walleij 
248de8860b1SLinus Walleij 	/*
249de8860b1SLinus Walleij 	 * These are the bits used in a 16bit word:
250de8860b1SLinus Walleij 	 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
251de8860b1SLinus Walleij 	 *    x  x  x  x  x  x  x  x  x  x  x  x
252de8860b1SLinus Walleij 	 */
253de8860b1SLinus Walleij 	val = get_unaligned_be16(&data[0]);
254de8860b1SLinus Walleij 	val = FIELD_GET(GENMASK(14, 3), val);
255de8860b1SLinus Walleij 	return val;
256de8860b1SLinus Walleij }
257de8860b1SLinus Walleij 
258de8860b1SLinus Walleij /* On YAS532 the x, y1 and y2 values are 13 bits */
yas532_extract_axis(u8 * data)259de8860b1SLinus Walleij static u16 yas532_extract_axis(u8 *data)
260de8860b1SLinus Walleij {
261de8860b1SLinus Walleij 	u16 val;
262de8860b1SLinus Walleij 
263de8860b1SLinus Walleij 	/*
264de8860b1SLinus Walleij 	 * These are the bits used in a 16bit word:
265de8860b1SLinus Walleij 	 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
266de8860b1SLinus Walleij 	 *    x  x  x  x  x  x  x  x  x  x  x  x  x
267de8860b1SLinus Walleij 	 */
268de8860b1SLinus Walleij 	val = get_unaligned_be16(&data[0]);
269de8860b1SLinus Walleij 	val = FIELD_GET(GENMASK(14, 2), val);
270de8860b1SLinus Walleij 	return val;
271de8860b1SLinus Walleij }
272de8860b1SLinus Walleij 
273de8860b1SLinus Walleij /**
2746e3bfa97SJakob Hauser  * yas530_measure() - Make a measure from the hardware
275de8860b1SLinus Walleij  * @yas5xx: The device state
276de8860b1SLinus Walleij  * @t: the raw temperature measurement
277de8860b1SLinus Walleij  * @x: the raw x axis measurement
278de8860b1SLinus Walleij  * @y1: the y1 axis measurement
279de8860b1SLinus Walleij  * @y2: the y2 axis measurement
280de8860b1SLinus Walleij  * @return: 0 on success or error code
2816e3bfa97SJakob Hauser  *
2826e3bfa97SJakob Hauser  * Used by YAS530, YAS532 and YAS533.
283de8860b1SLinus Walleij  */
yas530_measure(struct yas5xx * yas5xx,u16 * t,u16 * x,u16 * y1,u16 * y2)2846e3bfa97SJakob Hauser static int yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
285de8860b1SLinus Walleij {
286a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
287de8860b1SLinus Walleij 	unsigned int busy;
288de8860b1SLinus Walleij 	u8 data[8];
289de8860b1SLinus Walleij 	int ret;
290de8860b1SLinus Walleij 	u16 val;
291de8860b1SLinus Walleij 
292de8860b1SLinus Walleij 	mutex_lock(&yas5xx->lock);
2936e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_MEASURE, YAS5XX_MEASURE_START);
294de8860b1SLinus Walleij 	if (ret < 0)
295de8860b1SLinus Walleij 		goto out_unlock;
296de8860b1SLinus Walleij 
297de8860b1SLinus Walleij 	/*
298de8860b1SLinus Walleij 	 * Typical time to measure 1500 us, max 2000 us so wait min 500 us
299de8860b1SLinus Walleij 	 * and at most 20000 us (one magnitude more than the datsheet max)
300de8860b1SLinus Walleij 	 * before timeout.
301de8860b1SLinus Walleij 	 */
302de8860b1SLinus Walleij 	ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA, busy,
303de8860b1SLinus Walleij 				       !(busy & YAS5XX_MEASURE_DATA_BUSY),
304de8860b1SLinus Walleij 				       500, 20000);
305de8860b1SLinus Walleij 	if (ret) {
306de8860b1SLinus Walleij 		dev_err(yas5xx->dev, "timeout waiting for measurement\n");
307de8860b1SLinus Walleij 		goto out_unlock;
308de8860b1SLinus Walleij 	}
309de8860b1SLinus Walleij 
310de8860b1SLinus Walleij 	ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA,
311de8860b1SLinus Walleij 			       data, sizeof(data));
312de8860b1SLinus Walleij 	if (ret)
313de8860b1SLinus Walleij 		goto out_unlock;
314de8860b1SLinus Walleij 
315de8860b1SLinus Walleij 	mutex_unlock(&yas5xx->lock);
316de8860b1SLinus Walleij 
317a70f60e5SJakob Hauser 	switch (ci->devid) {
318de8860b1SLinus Walleij 	case YAS530_DEVICE_ID:
319de8860b1SLinus Walleij 		/*
320de8860b1SLinus Walleij 		 * The t value is 9 bits in big endian format
321de8860b1SLinus Walleij 		 * These are the bits used in a 16bit word:
322de8860b1SLinus Walleij 		 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
323de8860b1SLinus Walleij 		 *    x  x  x  x  x  x  x  x  x
324de8860b1SLinus Walleij 		 */
325de8860b1SLinus Walleij 		val = get_unaligned_be16(&data[0]);
326de8860b1SLinus Walleij 		val = FIELD_GET(GENMASK(14, 6), val);
327de8860b1SLinus Walleij 		*t = val;
328de8860b1SLinus Walleij 		*x = yas530_extract_axis(&data[2]);
329de8860b1SLinus Walleij 		*y1 = yas530_extract_axis(&data[4]);
330de8860b1SLinus Walleij 		*y2 = yas530_extract_axis(&data[6]);
331de8860b1SLinus Walleij 		break;
332de8860b1SLinus Walleij 	case YAS532_DEVICE_ID:
333de8860b1SLinus Walleij 		/*
334de8860b1SLinus Walleij 		 * The t value is 10 bits in big endian format
335de8860b1SLinus Walleij 		 * These are the bits used in a 16bit word:
336de8860b1SLinus Walleij 		 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0
337de8860b1SLinus Walleij 		 *    x  x  x  x  x  x  x  x  x  x
338de8860b1SLinus Walleij 		 */
339de8860b1SLinus Walleij 		val = get_unaligned_be16(&data[0]);
340de8860b1SLinus Walleij 		val = FIELD_GET(GENMASK(14, 5), val);
341de8860b1SLinus Walleij 		*t = val;
342de8860b1SLinus Walleij 		*x = yas532_extract_axis(&data[2]);
343de8860b1SLinus Walleij 		*y1 = yas532_extract_axis(&data[4]);
344de8860b1SLinus Walleij 		*y2 = yas532_extract_axis(&data[6]);
345de8860b1SLinus Walleij 		break;
346de8860b1SLinus Walleij 	default:
347de8860b1SLinus Walleij 		dev_err(yas5xx->dev, "unknown data format\n");
348de8860b1SLinus Walleij 		ret = -EINVAL;
349de8860b1SLinus Walleij 		break;
350de8860b1SLinus Walleij 	}
351de8860b1SLinus Walleij 
352de8860b1SLinus Walleij 	return ret;
353de8860b1SLinus Walleij 
354de8860b1SLinus Walleij out_unlock:
355de8860b1SLinus Walleij 	mutex_unlock(&yas5xx->lock);
356de8860b1SLinus Walleij 	return ret;
357de8860b1SLinus Walleij }
358de8860b1SLinus Walleij 
35965f79b50SJakob Hauser /**
36065f79b50SJakob Hauser  * yas537_measure() - Make a measure from the hardware
36165f79b50SJakob Hauser  * @yas5xx: The device state
36265f79b50SJakob Hauser  * @t: the raw temperature measurement
36365f79b50SJakob Hauser  * @x: the raw x axis measurement
36465f79b50SJakob Hauser  * @y1: the y1 axis measurement
36565f79b50SJakob Hauser  * @y2: the y2 axis measurement
36665f79b50SJakob Hauser  * @return: 0 on success or error code
36765f79b50SJakob Hauser  */
yas537_measure(struct yas5xx * yas5xx,u16 * t,u16 * x,u16 * y1,u16 * y2)36865f79b50SJakob Hauser static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2)
369de8860b1SLinus Walleij {
370de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
37165f79b50SJakob Hauser 	unsigned int busy;
37265f79b50SJakob Hauser 	u8 data[8];
37365f79b50SJakob Hauser 	u16 xy1y2[3];
37465f79b50SJakob Hauser 	s32 h[3], s[3];
375*67e97213SJakob Hauser 	int half_range = BIT(13);
37665f79b50SJakob Hauser 	int i, ret;
37765f79b50SJakob Hauser 
37865f79b50SJakob Hauser 	mutex_lock(&yas5xx->lock);
37965f79b50SJakob Hauser 
38065f79b50SJakob Hauser 	/* Contrary to YAS530/532, also a "cont" bit is set, meaning unknown */
38165f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_MEASURE, YAS5XX_MEASURE_START |
38265f79b50SJakob Hauser 			   YAS5XX_MEASURE_CONT);
38365f79b50SJakob Hauser 	if (ret < 0)
38465f79b50SJakob Hauser 		goto out_unlock;
38565f79b50SJakob Hauser 
38665f79b50SJakob Hauser 	/* Use same timeout like YAS530/532 but the bit is in data row 2 */
38765f79b50SJakob Hauser 	ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA + 2, busy,
38865f79b50SJakob Hauser 				       !(busy & YAS5XX_MEASURE_DATA_BUSY),
38965f79b50SJakob Hauser 				       500, 20000);
39065f79b50SJakob Hauser 	if (ret) {
39165f79b50SJakob Hauser 		dev_err(yas5xx->dev, "timeout waiting for measurement\n");
39265f79b50SJakob Hauser 		goto out_unlock;
39365f79b50SJakob Hauser 	}
39465f79b50SJakob Hauser 
39565f79b50SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA,
39665f79b50SJakob Hauser 			       data, sizeof(data));
39765f79b50SJakob Hauser 	if (ret)
39865f79b50SJakob Hauser 		goto out_unlock;
39965f79b50SJakob Hauser 
40065f79b50SJakob Hauser 	mutex_unlock(&yas5xx->lock);
40165f79b50SJakob Hauser 
40265f79b50SJakob Hauser 	*t = get_unaligned_be16(&data[0]);
40365f79b50SJakob Hauser 	xy1y2[0] = FIELD_GET(GENMASK(13, 0), get_unaligned_be16(&data[2]));
40465f79b50SJakob Hauser 	xy1y2[1] = get_unaligned_be16(&data[4]);
40565f79b50SJakob Hauser 	xy1y2[2] = get_unaligned_be16(&data[6]);
40665f79b50SJakob Hauser 
40765f79b50SJakob Hauser 	/* The second version of YAS537 needs to include calibration coefficients */
40865f79b50SJakob Hauser 	if (yas5xx->version == YAS537_VERSION_1) {
40965f79b50SJakob Hauser 		for (i = 0; i < 3; i++)
410*67e97213SJakob Hauser 			s[i] = xy1y2[i] - half_range;
411*67e97213SJakob Hauser 		h[0] = (c->k *   (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / half_range;
412*67e97213SJakob Hauser 		h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / half_range;
413*67e97213SJakob Hauser 		h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / half_range;
41465f79b50SJakob Hauser 		for (i = 0; i < 3; i++) {
415*67e97213SJakob Hauser 			h[i] = clamp(h[i], -half_range, half_range - 1);
416*67e97213SJakob Hauser 			xy1y2[i] = h[i] + half_range;
41765f79b50SJakob Hauser 		}
41865f79b50SJakob Hauser 	}
41965f79b50SJakob Hauser 
42065f79b50SJakob Hauser 	*x = xy1y2[0];
42165f79b50SJakob Hauser 	*y1 = xy1y2[1];
42265f79b50SJakob Hauser 	*y2 = xy1y2[2];
42365f79b50SJakob Hauser 
42465f79b50SJakob Hauser 	return 0;
42565f79b50SJakob Hauser 
42665f79b50SJakob Hauser out_unlock:
42765f79b50SJakob Hauser 	mutex_unlock(&yas5xx->lock);
42865f79b50SJakob Hauser 	return ret;
42965f79b50SJakob Hauser }
43065f79b50SJakob Hauser 
4316e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_linearize(struct yas5xx * yas5xx,u16 val,int axis)4326e3bfa97SJakob Hauser static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis)
433de8860b1SLinus Walleij {
434a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
435de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
436de8860b1SLinus Walleij 	static const s32 yas532ac_coef[] = {
437de8860b1SLinus Walleij 		YAS532_VERSION_AC_COEF_X,
438de8860b1SLinus Walleij 		YAS532_VERSION_AC_COEF_Y1,
439de8860b1SLinus Walleij 		YAS532_VERSION_AC_COEF_Y2,
440de8860b1SLinus Walleij 	};
441de8860b1SLinus Walleij 	s32 coef;
442de8860b1SLinus Walleij 
443de8860b1SLinus Walleij 	/* Select coefficients */
444a70f60e5SJakob Hauser 	switch (ci->devid) {
445de8860b1SLinus Walleij 	case YAS530_DEVICE_ID:
446de8860b1SLinus Walleij 		if (yas5xx->version == YAS530_VERSION_A)
447de8860b1SLinus Walleij 			coef = YAS530_VERSION_A_COEF;
448de8860b1SLinus Walleij 		else
449de8860b1SLinus Walleij 			coef = YAS530_VERSION_B_COEF;
450de8860b1SLinus Walleij 		break;
451de8860b1SLinus Walleij 	case YAS532_DEVICE_ID:
452de8860b1SLinus Walleij 		if (yas5xx->version == YAS532_VERSION_AB)
453de8860b1SLinus Walleij 			coef = YAS532_VERSION_AB_COEF;
454de8860b1SLinus Walleij 		else
455de8860b1SLinus Walleij 			/* Elaborate coefficients */
456de8860b1SLinus Walleij 			coef = yas532ac_coef[axis];
457de8860b1SLinus Walleij 		break;
458de8860b1SLinus Walleij 	default:
459de8860b1SLinus Walleij 		dev_err(yas5xx->dev, "unknown device type\n");
460de8860b1SLinus Walleij 		return val;
461de8860b1SLinus Walleij 	}
462de8860b1SLinus Walleij 	/*
463de8860b1SLinus Walleij 	 * Linearization formula:
464de8860b1SLinus Walleij 	 *
465de8860b1SLinus Walleij 	 * x' = x - (3721 + 50 * f) + (xoffset - r) * c
466de8860b1SLinus Walleij 	 *
467de8860b1SLinus Walleij 	 * Where f and r are calibration values, c is a per-device
468de8860b1SLinus Walleij 	 * and sometimes per-axis coefficient.
469de8860b1SLinus Walleij 	 */
470de8860b1SLinus Walleij 	return val - (3721 + 50 * c->f[axis]) +
471de8860b1SLinus Walleij 		(yas5xx->hard_offsets[axis] - c->r[axis]) * coef;
472de8860b1SLinus Walleij }
473de8860b1SLinus Walleij 
yas5xx_calc_temperature(struct yas5xx * yas5xx,u16 t)4742d6676ecSJakob Hauser static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t)
4752d6676ecSJakob Hauser {
4762d6676ecSJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
4772d6676ecSJakob Hauser 	s32 to;
4782d6676ecSJakob Hauser 	u16 t_ref;
4792d6676ecSJakob Hauser 	s16 min_temp_x10;
4802d6676ecSJakob Hauser 	int ref_temp_x10;
4812d6676ecSJakob Hauser 
4822d6676ecSJakob Hauser 	t_ref = ci->t_ref;
4832d6676ecSJakob Hauser 	min_temp_x10 = ci->min_temp_x10;
4842d6676ecSJakob Hauser 	ref_temp_x10 = 200;
4852d6676ecSJakob Hauser 
4862d6676ecSJakob Hauser 	to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100;
4872d6676ecSJakob Hauser 	return to;
4882d6676ecSJakob Hauser }
4892d6676ecSJakob Hauser 
490de8860b1SLinus Walleij /**
4916e3bfa97SJakob Hauser  * yas530_get_measure() - Measure a sample of all axis and process
492de8860b1SLinus Walleij  * @yas5xx: The device state
493de8860b1SLinus Walleij  * @to: Temperature out
494de8860b1SLinus Walleij  * @xo: X axis out
495de8860b1SLinus Walleij  * @yo: Y axis out
496de8860b1SLinus Walleij  * @zo: Z axis out
497de8860b1SLinus Walleij  * @return: 0 on success or error code
498de8860b1SLinus Walleij  *
4996e3bfa97SJakob Hauser  * Used by YAS530, YAS532 and YAS533.
500de8860b1SLinus Walleij  */
yas530_get_measure(struct yas5xx * yas5xx,s32 * to,s32 * xo,s32 * yo,s32 * zo)5016e3bfa97SJakob Hauser static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
502de8860b1SLinus Walleij {
503a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
504de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
5052d6676ecSJakob Hauser 	u16 t_ref, t_comp, t, x, y1, y2;
50692d9c05cSJakob Hauser 	/* These are signed x, signed y1 etc */
507de8860b1SLinus Walleij 	s32 sx, sy1, sy2, sy, sz;
508de8860b1SLinus Walleij 	int ret;
509de8860b1SLinus Walleij 
510de8860b1SLinus Walleij 	/* We first get raw data that needs to be translated to [x,y,z] */
5116e3bfa97SJakob Hauser 	ret = yas530_measure(yas5xx, &t, &x, &y1, &y2);
512de8860b1SLinus Walleij 	if (ret)
513de8860b1SLinus Walleij 		return ret;
514de8860b1SLinus Walleij 
515de8860b1SLinus Walleij 	/* Do some linearization if available */
5166e3bfa97SJakob Hauser 	sx = yas530_linearize(yas5xx, x, 0);
5176e3bfa97SJakob Hauser 	sy1 = yas530_linearize(yas5xx, y1, 1);
5186e3bfa97SJakob Hauser 	sy2 = yas530_linearize(yas5xx, y2, 2);
519de8860b1SLinus Walleij 
5202d6676ecSJakob Hauser 	/*
5212d6676ecSJakob Hauser 	 * Set the temperature for compensation (unit: counts):
5222d6676ecSJakob Hauser 	 * YAS532/YAS533 version AC uses the temperature deviation as a
5232d6676ecSJakob Hauser 	 * multiplier. YAS530 and YAS532 version AB use solely the t value.
5242d6676ecSJakob Hauser 	 */
5252d6676ecSJakob Hauser 	t_ref = ci->t_ref;
526a70f60e5SJakob Hauser 	if (ci->devid == YAS532_DEVICE_ID &&
5278239f904SJakob Hauser 	    yas5xx->version == YAS532_VERSION_AC) {
5282d6676ecSJakob Hauser 		t_comp = t - t_ref;
5298239f904SJakob Hauser 	} else {
5302d6676ecSJakob Hauser 		t_comp = t;
5312d6676ecSJakob Hauser 	}
532de8860b1SLinus Walleij 
533de8860b1SLinus Walleij 	/*
534de8860b1SLinus Walleij 	 * Temperature compensation for x, y1, y2 respectively:
535de8860b1SLinus Walleij 	 *
5362d6676ecSJakob Hauser 	 *          Cx * t_comp
5372d6676ecSJakob Hauser 	 * x' = x - -----------
538de8860b1SLinus Walleij 	 *              100
539de8860b1SLinus Walleij 	 */
5402d6676ecSJakob Hauser 	sx = sx - (c->Cx * t_comp) / 100;
5412d6676ecSJakob Hauser 	sy1 = sy1 - (c->Cy1 * t_comp) / 100;
5422d6676ecSJakob Hauser 	sy2 = sy2 - (c->Cy2 * t_comp) / 100;
543de8860b1SLinus Walleij 
544de8860b1SLinus Walleij 	/*
545de8860b1SLinus Walleij 	 * Break y1 and y2 into y and z, y1 and y2 are apparently encoding
546de8860b1SLinus Walleij 	 * y and z.
547de8860b1SLinus Walleij 	 */
548de8860b1SLinus Walleij 	sy = sy1 - sy2;
549de8860b1SLinus Walleij 	sz = -sy1 - sy2;
550de8860b1SLinus Walleij 
5512d6676ecSJakob Hauser 	/* Calculate temperature readout */
5522d6676ecSJakob Hauser 	*to = yas5xx_calc_temperature(yas5xx, t);
5538239f904SJakob Hauser 
554de8860b1SLinus Walleij 	/*
555de8860b1SLinus Walleij 	 * Calibrate [x,y,z] with some formulas like this:
556de8860b1SLinus Walleij 	 *
557de8860b1SLinus Walleij 	 *            100 * x + a_2 * y + a_3 * z
558de8860b1SLinus Walleij 	 *  x' = k *  ---------------------------
559de8860b1SLinus Walleij 	 *                        10
560de8860b1SLinus Walleij 	 *
561de8860b1SLinus Walleij 	 *           a_4 * x + a_5 * y + a_6 * z
562de8860b1SLinus Walleij 	 *  y' = k * ---------------------------
563de8860b1SLinus Walleij 	 *                        10
564de8860b1SLinus Walleij 	 *
565de8860b1SLinus Walleij 	 *           a_7 * x + a_8 * y + a_9 * z
566de8860b1SLinus Walleij 	 *  z' = k * ---------------------------
567de8860b1SLinus Walleij 	 *                        10
568de8860b1SLinus Walleij 	 */
569de8860b1SLinus Walleij 	*xo = c->k * ((100 * sx + c->a2 * sy + c->a3 * sz) / 10);
570de8860b1SLinus Walleij 	*yo = c->k * ((c->a4 * sx + c->a5 * sy + c->a6 * sz) / 10);
571de8860b1SLinus Walleij 	*zo = c->k * ((c->a7 * sx + c->a8 * sy + c->a9 * sz) / 10);
572de8860b1SLinus Walleij 
573de8860b1SLinus Walleij 	return 0;
574de8860b1SLinus Walleij }
575de8860b1SLinus Walleij 
57665f79b50SJakob Hauser /**
57765f79b50SJakob Hauser  * yas537_get_measure() - Measure a sample of all axis and process
57865f79b50SJakob Hauser  * @yas5xx: The device state
57965f79b50SJakob Hauser  * @to: Temperature out
58065f79b50SJakob Hauser  * @xo: X axis out
58165f79b50SJakob Hauser  * @yo: Y axis out
58265f79b50SJakob Hauser  * @zo: Z axis out
58365f79b50SJakob Hauser  * @return: 0 on success or error code
58465f79b50SJakob Hauser  */
yas537_get_measure(struct yas5xx * yas5xx,s32 * to,s32 * xo,s32 * yo,s32 * zo)58565f79b50SJakob Hauser static int yas537_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo)
58665f79b50SJakob Hauser {
58765f79b50SJakob Hauser 	u16 t, x, y1, y2;
58865f79b50SJakob Hauser 	int ret;
58965f79b50SJakob Hauser 
59065f79b50SJakob Hauser 	/* We first get raw data that needs to be translated to [x,y,z] */
59165f79b50SJakob Hauser 	ret = yas537_measure(yas5xx, &t, &x, &y1, &y2);
59265f79b50SJakob Hauser 	if (ret)
59365f79b50SJakob Hauser 		return ret;
59465f79b50SJakob Hauser 
59565f79b50SJakob Hauser 	/* Calculate temperature readout */
59665f79b50SJakob Hauser 	*to = yas5xx_calc_temperature(yas5xx, t);
59765f79b50SJakob Hauser 
59865f79b50SJakob Hauser 	/*
59965f79b50SJakob Hauser 	 * Unfortunately, no linearization or temperature compensation formulas
60065f79b50SJakob Hauser 	 * are known for YAS537.
60165f79b50SJakob Hauser 	 */
60265f79b50SJakob Hauser 
60365f79b50SJakob Hauser 	/* Calculate x, y, z from x, y1, y2 */
60465f79b50SJakob Hauser 	*xo = (x - BIT(13)) * 300;
60565f79b50SJakob Hauser 	*yo = (y1 - y2) * 1732 / 10;
60665f79b50SJakob Hauser 	*zo = (-y1 - y2 + BIT(14)) * 300;
60765f79b50SJakob Hauser 
60865f79b50SJakob Hauser 	return 0;
60965f79b50SJakob Hauser }
61065f79b50SJakob Hauser 
yas5xx_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long mask)611de8860b1SLinus Walleij static int yas5xx_read_raw(struct iio_dev *indio_dev,
612de8860b1SLinus Walleij 			   struct iio_chan_spec const *chan,
613de8860b1SLinus Walleij 			   int *val, int *val2,
614de8860b1SLinus Walleij 			   long mask)
615de8860b1SLinus Walleij {
616de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
617a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
618de8860b1SLinus Walleij 	s32 t, x, y, z;
619de8860b1SLinus Walleij 	int ret;
620de8860b1SLinus Walleij 
621de8860b1SLinus Walleij 	switch (mask) {
6228239f904SJakob Hauser 	case IIO_CHAN_INFO_PROCESSED:
623de8860b1SLinus Walleij 	case IIO_CHAN_INFO_RAW:
624de8860b1SLinus Walleij 		pm_runtime_get_sync(yas5xx->dev);
625059ff0f9SJakob Hauser 		ret = ci->get_measure(yas5xx, &t, &x, &y, &z);
626de8860b1SLinus Walleij 		pm_runtime_mark_last_busy(yas5xx->dev);
627de8860b1SLinus Walleij 		pm_runtime_put_autosuspend(yas5xx->dev);
628de8860b1SLinus Walleij 		if (ret)
629de8860b1SLinus Walleij 			return ret;
630de8860b1SLinus Walleij 		switch (chan->address) {
631de8860b1SLinus Walleij 		case 0:
632de8860b1SLinus Walleij 			*val = t;
633de8860b1SLinus Walleij 			break;
634de8860b1SLinus Walleij 		case 1:
635de8860b1SLinus Walleij 			*val = x;
636de8860b1SLinus Walleij 			break;
637de8860b1SLinus Walleij 		case 2:
638de8860b1SLinus Walleij 			*val = y;
639de8860b1SLinus Walleij 			break;
640de8860b1SLinus Walleij 		case 3:
641de8860b1SLinus Walleij 			*val = z;
642de8860b1SLinus Walleij 			break;
643de8860b1SLinus Walleij 		default:
644de8860b1SLinus Walleij 			dev_err(yas5xx->dev, "unknown channel\n");
645de8860b1SLinus Walleij 			return -EINVAL;
646de8860b1SLinus Walleij 		}
647de8860b1SLinus Walleij 		return IIO_VAL_INT;
648de8860b1SLinus Walleij 	case IIO_CHAN_INFO_SCALE:
649de8860b1SLinus Walleij 		*val = 1;
650913fd409SJakob Hauser 		*val2 = ci->scaling_val2;
651de8860b1SLinus Walleij 		return IIO_VAL_FRACTIONAL;
652de8860b1SLinus Walleij 	default:
653de8860b1SLinus Walleij 		/* Unknown request */
654de8860b1SLinus Walleij 		return -EINVAL;
655de8860b1SLinus Walleij 	}
656de8860b1SLinus Walleij }
657de8860b1SLinus Walleij 
yas5xx_fill_buffer(struct iio_dev * indio_dev)658de8860b1SLinus Walleij static void yas5xx_fill_buffer(struct iio_dev *indio_dev)
659de8860b1SLinus Walleij {
660de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
661059ff0f9SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
662de8860b1SLinus Walleij 	s32 t, x, y, z;
663de8860b1SLinus Walleij 	int ret;
664de8860b1SLinus Walleij 
665de8860b1SLinus Walleij 	pm_runtime_get_sync(yas5xx->dev);
666059ff0f9SJakob Hauser 	ret = ci->get_measure(yas5xx, &t, &x, &y, &z);
667de8860b1SLinus Walleij 	pm_runtime_mark_last_busy(yas5xx->dev);
668de8860b1SLinus Walleij 	pm_runtime_put_autosuspend(yas5xx->dev);
669de8860b1SLinus Walleij 	if (ret) {
670de8860b1SLinus Walleij 		dev_err(yas5xx->dev, "error refilling buffer\n");
671de8860b1SLinus Walleij 		return;
672de8860b1SLinus Walleij 	}
673de8860b1SLinus Walleij 	yas5xx->scan.channels[0] = t;
674de8860b1SLinus Walleij 	yas5xx->scan.channels[1] = x;
675de8860b1SLinus Walleij 	yas5xx->scan.channels[2] = y;
676de8860b1SLinus Walleij 	yas5xx->scan.channels[3] = z;
677de8860b1SLinus Walleij 	iio_push_to_buffers_with_timestamp(indio_dev, &yas5xx->scan,
678de8860b1SLinus Walleij 					   iio_get_time_ns(indio_dev));
679de8860b1SLinus Walleij }
680de8860b1SLinus Walleij 
yas5xx_handle_trigger(int irq,void * p)681de8860b1SLinus Walleij static irqreturn_t yas5xx_handle_trigger(int irq, void *p)
682de8860b1SLinus Walleij {
683de8860b1SLinus Walleij 	const struct iio_poll_func *pf = p;
684de8860b1SLinus Walleij 	struct iio_dev *indio_dev = pf->indio_dev;
685de8860b1SLinus Walleij 
686de8860b1SLinus Walleij 	yas5xx_fill_buffer(indio_dev);
687de8860b1SLinus Walleij 	iio_trigger_notify_done(indio_dev->trig);
688de8860b1SLinus Walleij 
689de8860b1SLinus Walleij 	return IRQ_HANDLED;
690de8860b1SLinus Walleij }
691de8860b1SLinus Walleij 
692de8860b1SLinus Walleij 
693de8860b1SLinus Walleij static const struct iio_mount_matrix *
yas5xx_get_mount_matrix(const struct iio_dev * indio_dev,const struct iio_chan_spec * chan)694de8860b1SLinus Walleij yas5xx_get_mount_matrix(const struct iio_dev *indio_dev,
695de8860b1SLinus Walleij 			const struct iio_chan_spec *chan)
696de8860b1SLinus Walleij {
697de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
698de8860b1SLinus Walleij 
699de8860b1SLinus Walleij 	return &yas5xx->orientation;
700de8860b1SLinus Walleij }
701de8860b1SLinus Walleij 
702de8860b1SLinus Walleij static const struct iio_chan_spec_ext_info yas5xx_ext_info[] = {
703de8860b1SLinus Walleij 	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, yas5xx_get_mount_matrix),
704de8860b1SLinus Walleij 	{ }
705de8860b1SLinus Walleij };
706de8860b1SLinus Walleij 
707de8860b1SLinus Walleij #define YAS5XX_AXIS_CHANNEL(axis, index)				\
708de8860b1SLinus Walleij 	{								\
709de8860b1SLinus Walleij 		.type = IIO_MAGN,					\
710de8860b1SLinus Walleij 		.modified = 1,						\
711de8860b1SLinus Walleij 		.channel2 = IIO_MOD_##axis,				\
712de8860b1SLinus Walleij 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
713de8860b1SLinus Walleij 			BIT(IIO_CHAN_INFO_SCALE),			\
714de8860b1SLinus Walleij 		.ext_info = yas5xx_ext_info,				\
715de8860b1SLinus Walleij 		.address = index,					\
716de8860b1SLinus Walleij 		.scan_index = index,					\
717de8860b1SLinus Walleij 		.scan_type = {						\
718de8860b1SLinus Walleij 			.sign = 's',					\
719de8860b1SLinus Walleij 			.realbits = 32,					\
720de8860b1SLinus Walleij 			.storagebits = 32,				\
721de8860b1SLinus Walleij 			.endianness = IIO_CPU,				\
722de8860b1SLinus Walleij 		},							\
723de8860b1SLinus Walleij 	}
724de8860b1SLinus Walleij 
725de8860b1SLinus Walleij static const struct iio_chan_spec yas5xx_channels[] = {
726de8860b1SLinus Walleij 	{
727de8860b1SLinus Walleij 		.type = IIO_TEMP,
728de8860b1SLinus Walleij 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
729de8860b1SLinus Walleij 		.address = 0,
730de8860b1SLinus Walleij 		.scan_index = 0,
731de8860b1SLinus Walleij 		.scan_type = {
7328239f904SJakob Hauser 			.sign = 's',
733de8860b1SLinus Walleij 			.realbits = 32,
734de8860b1SLinus Walleij 			.storagebits = 32,
735de8860b1SLinus Walleij 			.endianness = IIO_CPU,
736de8860b1SLinus Walleij 		},
737de8860b1SLinus Walleij 	},
738de8860b1SLinus Walleij 	YAS5XX_AXIS_CHANNEL(X, 1),
739de8860b1SLinus Walleij 	YAS5XX_AXIS_CHANNEL(Y, 2),
740de8860b1SLinus Walleij 	YAS5XX_AXIS_CHANNEL(Z, 3),
741de8860b1SLinus Walleij 	IIO_CHAN_SOFT_TIMESTAMP(4),
742de8860b1SLinus Walleij };
743de8860b1SLinus Walleij 
744de8860b1SLinus Walleij static const unsigned long yas5xx_scan_masks[] = { GENMASK(3, 0), 0 };
745de8860b1SLinus Walleij 
746de8860b1SLinus Walleij static const struct iio_info yas5xx_info = {
747de8860b1SLinus Walleij 	.read_raw = &yas5xx_read_raw,
748de8860b1SLinus Walleij };
749de8860b1SLinus Walleij 
yas5xx_volatile_reg(struct device * dev,unsigned int reg)750de8860b1SLinus Walleij static bool yas5xx_volatile_reg(struct device *dev, unsigned int reg)
751de8860b1SLinus Walleij {
752dd9bd44fSJakob Hauser 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
753dd9bd44fSJakob Hauser 	struct yas5xx *yas5xx = iio_priv(indio_dev);
754dd9bd44fSJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
755dd9bd44fSJakob Hauser 	int reg_qty;
756dd9bd44fSJakob Hauser 	int i;
757dd9bd44fSJakob Hauser 
758dd9bd44fSJakob Hauser 	if (reg >= YAS5XX_MEASURE_DATA && reg < YAS5XX_MEASURE_DATA + 8)
759dd9bd44fSJakob Hauser 		return true;
760dd9bd44fSJakob Hauser 
761dd9bd44fSJakob Hauser 	/*
762dd9bd44fSJakob Hauser 	 * YAS versions share different registers on the same address,
763dd9bd44fSJakob Hauser 	 * need to differentiate.
764dd9bd44fSJakob Hauser 	 */
765dd9bd44fSJakob Hauser 	reg_qty = ci->volatile_reg_qty;
766dd9bd44fSJakob Hauser 	for (i = 0; i < reg_qty; i++) {
767dd9bd44fSJakob Hauser 		if (reg == ci->volatile_reg[i])
768dd9bd44fSJakob Hauser 			return true;
769dd9bd44fSJakob Hauser 	}
770dd9bd44fSJakob Hauser 
771dd9bd44fSJakob Hauser 	return false;
772de8860b1SLinus Walleij }
773de8860b1SLinus Walleij 
774de8860b1SLinus Walleij /* TODO: enable regmap cache, using mark dirty and sync at runtime resume */
775de8860b1SLinus Walleij static const struct regmap_config yas5xx_regmap_config = {
776de8860b1SLinus Walleij 	.reg_bits = 8,
777de8860b1SLinus Walleij 	.val_bits = 8,
778de8860b1SLinus Walleij 	.max_register = 0xff,
779de8860b1SLinus Walleij 	.volatile_reg = yas5xx_volatile_reg,
780de8860b1SLinus Walleij };
781de8860b1SLinus Walleij 
782de8860b1SLinus Walleij /**
7836e3bfa97SJakob Hauser  * yas530_extract_calibration() - extracts the a2-a9 and k calibration
784de8860b1SLinus Walleij  * @data: the bitfield to use
785de8860b1SLinus Walleij  * @c: the calibration to populate
7866e3bfa97SJakob Hauser  *
7876e3bfa97SJakob Hauser  * Used by YAS530, YAS532 and YAS533.
788de8860b1SLinus Walleij  */
yas530_extract_calibration(u8 * data,struct yas5xx_calibration * c)7896e3bfa97SJakob Hauser static void yas530_extract_calibration(u8 *data, struct yas5xx_calibration *c)
790de8860b1SLinus Walleij {
791de8860b1SLinus Walleij 	u64 val = get_unaligned_be64(data);
792de8860b1SLinus Walleij 
793de8860b1SLinus Walleij 	/*
794de8860b1SLinus Walleij 	 * Bitfield layout for the axis calibration data, for factor
795de8860b1SLinus Walleij 	 * a2 = 2 etc, k = k, c = clock divider
796de8860b1SLinus Walleij 	 *
797de8860b1SLinus Walleij 	 * n   7 6 5 4 3 2 1 0
798de8860b1SLinus Walleij 	 * 0 [ 2 2 2 2 2 2 3 3 ] bits 63 .. 56
799de8860b1SLinus Walleij 	 * 1 [ 3 3 4 4 4 4 4 4 ] bits 55 .. 48
800de8860b1SLinus Walleij 	 * 2 [ 5 5 5 5 5 5 6 6 ] bits 47 .. 40
801de8860b1SLinus Walleij 	 * 3 [ 6 6 6 6 7 7 7 7 ] bits 39 .. 32
802de8860b1SLinus Walleij 	 * 4 [ 7 7 7 8 8 8 8 8 ] bits 31 .. 24
803de8860b1SLinus Walleij 	 * 5 [ 8 9 9 9 9 9 9 9 ] bits 23 .. 16
804de8860b1SLinus Walleij 	 * 6 [ 9 k k k k k c c ] bits 15 .. 8
805de8860b1SLinus Walleij 	 * 7 [ c x x x x x x x ] bits  7 .. 0
806de8860b1SLinus Walleij 	 */
807de8860b1SLinus Walleij 	c->a2 = FIELD_GET(GENMASK_ULL(63, 58), val) - 32;
808de8860b1SLinus Walleij 	c->a3 = FIELD_GET(GENMASK_ULL(57, 54), val) - 8;
809de8860b1SLinus Walleij 	c->a4 = FIELD_GET(GENMASK_ULL(53, 48), val) - 32;
810de8860b1SLinus Walleij 	c->a5 = FIELD_GET(GENMASK_ULL(47, 42), val) + 38;
811de8860b1SLinus Walleij 	c->a6 = FIELD_GET(GENMASK_ULL(41, 36), val) - 32;
812de8860b1SLinus Walleij 	c->a7 = FIELD_GET(GENMASK_ULL(35, 29), val) - 64;
813de8860b1SLinus Walleij 	c->a8 = FIELD_GET(GENMASK_ULL(28, 23), val) - 32;
814de8860b1SLinus Walleij 	c->a9 = FIELD_GET(GENMASK_ULL(22, 15), val);
815de8860b1SLinus Walleij 	c->k = FIELD_GET(GENMASK_ULL(14, 10), val) + 10;
816de8860b1SLinus Walleij 	c->dck = FIELD_GET(GENMASK_ULL(9, 7), val);
817de8860b1SLinus Walleij }
818de8860b1SLinus Walleij 
yas530_get_calibration_data(struct yas5xx * yas5xx)819de8860b1SLinus Walleij static int yas530_get_calibration_data(struct yas5xx *yas5xx)
820de8860b1SLinus Walleij {
821de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
822de8860b1SLinus Walleij 	u8 data[16];
823de8860b1SLinus Walleij 	u32 val;
824de8860b1SLinus Walleij 	int ret;
825de8860b1SLinus Walleij 
826de8860b1SLinus Walleij 	/* Dummy read, first read is ALWAYS wrong */
8276e3bfa97SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data));
828de8860b1SLinus Walleij 	if (ret)
829de8860b1SLinus Walleij 		return ret;
830de8860b1SLinus Walleij 
831de8860b1SLinus Walleij 	/* Actual calibration readout */
8326e3bfa97SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data));
833de8860b1SLinus Walleij 	if (ret)
834de8860b1SLinus Walleij 		return ret;
835bdef8dcfSJakob Hauser 	dev_dbg(yas5xx->dev, "calibration data: %16ph\n", data);
836de8860b1SLinus Walleij 
83792d9c05cSJakob Hauser 	/* Contribute calibration data to the input pool for kernel entropy */
838de8860b1SLinus Walleij 	add_device_randomness(data, sizeof(data));
83992d9c05cSJakob Hauser 
84092d9c05cSJakob Hauser 	/* Extract version */
841de8860b1SLinus Walleij 	yas5xx->version = data[15] & GENMASK(1, 0);
842de8860b1SLinus Walleij 
843de8860b1SLinus Walleij 	/* Extract the calibration from the bitfield */
844de8860b1SLinus Walleij 	c->Cx = data[0] * 6 - 768;
845de8860b1SLinus Walleij 	c->Cy1 = data[1] * 6 - 768;
846de8860b1SLinus Walleij 	c->Cy2 = data[2] * 6 - 768;
8476e3bfa97SJakob Hauser 	yas530_extract_calibration(&data[3], c);
848de8860b1SLinus Walleij 
849de8860b1SLinus Walleij 	/*
850de8860b1SLinus Walleij 	 * Extract linearization:
851de8860b1SLinus Walleij 	 * Linearization layout in the 32 bits at byte 11:
852de8860b1SLinus Walleij 	 * The r factors are 6 bit values where bit 5 is the sign
853de8860b1SLinus Walleij 	 *
854de8860b1SLinus Walleij 	 * n    7  6  5  4  3  2  1  0
855de8860b1SLinus Walleij 	 * 0 [ xx xx xx r0 r0 r0 r0 r0 ] bits 31 .. 24
856de8860b1SLinus Walleij 	 * 1 [ r0 f0 f0 r1 r1 r1 r1 r1 ] bits 23 .. 16
857de8860b1SLinus Walleij 	 * 2 [ r1 f1 f1 r2 r2 r2 r2 r2 ] bits 15 .. 8
858de8860b1SLinus Walleij 	 * 3 [ r2 f2 f2 xx xx xx xx xx ] bits  7 .. 0
859de8860b1SLinus Walleij 	 */
860de8860b1SLinus Walleij 	val = get_unaligned_be32(&data[11]);
861de8860b1SLinus Walleij 	c->f[0] = FIELD_GET(GENMASK(22, 21), val);
862de8860b1SLinus Walleij 	c->f[1] = FIELD_GET(GENMASK(14, 13), val);
863de8860b1SLinus Walleij 	c->f[2] = FIELD_GET(GENMASK(6, 5), val);
864de8860b1SLinus Walleij 	c->r[0] = sign_extend32(FIELD_GET(GENMASK(28, 23), val), 5);
865de8860b1SLinus Walleij 	c->r[1] = sign_extend32(FIELD_GET(GENMASK(20, 15), val), 5);
866de8860b1SLinus Walleij 	c->r[2] = sign_extend32(FIELD_GET(GENMASK(12, 7), val), 5);
86792d9c05cSJakob Hauser 
868de8860b1SLinus Walleij 	return 0;
869de8860b1SLinus Walleij }
870de8860b1SLinus Walleij 
yas532_get_calibration_data(struct yas5xx * yas5xx)871de8860b1SLinus Walleij static int yas532_get_calibration_data(struct yas5xx *yas5xx)
872de8860b1SLinus Walleij {
873de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
874de8860b1SLinus Walleij 	u8 data[14];
875de8860b1SLinus Walleij 	u32 val;
876de8860b1SLinus Walleij 	int ret;
877de8860b1SLinus Walleij 
878de8860b1SLinus Walleij 	/* Dummy read, first read is ALWAYS wrong */
8796e3bfa97SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data));
880de8860b1SLinus Walleij 	if (ret)
881de8860b1SLinus Walleij 		return ret;
882de8860b1SLinus Walleij 	/* Actual calibration readout */
8836e3bfa97SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data));
884de8860b1SLinus Walleij 	if (ret)
885de8860b1SLinus Walleij 		return ret;
886bdef8dcfSJakob Hauser 	dev_dbg(yas5xx->dev, "calibration data: %14ph\n", data);
887de8860b1SLinus Walleij 
888de8860b1SLinus Walleij 	/* Sanity check, is this all zeroes? */
88992d9c05cSJakob Hauser 	if (!memchr_inv(data, 0x00, 13) && !(data[13] & BIT(7)))
890de8860b1SLinus Walleij 		dev_warn(yas5xx->dev, "calibration is blank!\n");
891de8860b1SLinus Walleij 
89292d9c05cSJakob Hauser 	/* Contribute calibration data to the input pool for kernel entropy */
893de8860b1SLinus Walleij 	add_device_randomness(data, sizeof(data));
89492d9c05cSJakob Hauser 
895de8860b1SLinus Walleij 	/* Only one bit of version info reserved here as far as we know */
896de8860b1SLinus Walleij 	yas5xx->version = data[13] & BIT(0);
897de8860b1SLinus Walleij 
898de8860b1SLinus Walleij 	/* Extract calibration from the bitfield */
899de8860b1SLinus Walleij 	c->Cx = data[0] * 10 - 1280;
900de8860b1SLinus Walleij 	c->Cy1 = data[1] * 10 - 1280;
901de8860b1SLinus Walleij 	c->Cy2 = data[2] * 10 - 1280;
9026e3bfa97SJakob Hauser 	yas530_extract_calibration(&data[3], c);
90392d9c05cSJakob Hauser 
904de8860b1SLinus Walleij 	/*
905de8860b1SLinus Walleij 	 * Extract linearization:
906de8860b1SLinus Walleij 	 * Linearization layout in the 32 bits at byte 10:
907de8860b1SLinus Walleij 	 * The r factors are 6 bit values where bit 5 is the sign
908de8860b1SLinus Walleij 	 *
909de8860b1SLinus Walleij 	 * n    7  6  5  4  3  2  1  0
910de8860b1SLinus Walleij 	 * 0 [ xx r0 r0 r0 r0 r0 r0 f0 ] bits 31 .. 24
911de8860b1SLinus Walleij 	 * 1 [ f0 r1 r1 r1 r1 r1 r1 f1 ] bits 23 .. 16
912de8860b1SLinus Walleij 	 * 2 [ f1 r2 r2 r2 r2 r2 r2 f2 ] bits 15 .. 8
913de8860b1SLinus Walleij 	 * 3 [ f2 xx xx xx xx xx xx xx ] bits  7 .. 0
914de8860b1SLinus Walleij 	 */
915de8860b1SLinus Walleij 	val = get_unaligned_be32(&data[10]);
916de8860b1SLinus Walleij 	c->f[0] = FIELD_GET(GENMASK(24, 23), val);
917de8860b1SLinus Walleij 	c->f[1] = FIELD_GET(GENMASK(16, 15), val);
918de8860b1SLinus Walleij 	c->f[2] = FIELD_GET(GENMASK(8, 7), val);
919de8860b1SLinus Walleij 	c->r[0] = sign_extend32(FIELD_GET(GENMASK(30, 25), val), 5);
920de8860b1SLinus Walleij 	c->r[1] = sign_extend32(FIELD_GET(GENMASK(22, 17), val), 5);
921de8860b1SLinus Walleij 	c->r[2] = sign_extend32(FIELD_GET(GENMASK(14, 7), val), 5);
922de8860b1SLinus Walleij 
923de8860b1SLinus Walleij 	return 0;
924de8860b1SLinus Walleij }
925de8860b1SLinus Walleij 
yas537_get_calibration_data(struct yas5xx * yas5xx)92665f79b50SJakob Hauser static int yas537_get_calibration_data(struct yas5xx *yas5xx)
92765f79b50SJakob Hauser {
92865f79b50SJakob Hauser 	struct yas5xx_calibration *c = &yas5xx->calibration;
92965f79b50SJakob Hauser 	u8 data[17];
93065f79b50SJakob Hauser 	u32 val1, val2, val3, val4;
93165f79b50SJakob Hauser 	int i, ret;
93265f79b50SJakob Hauser 
93365f79b50SJakob Hauser 	/* Writing SRST register */
93465f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_SRST, BIT(1));
93565f79b50SJakob Hauser 	if (ret)
93665f79b50SJakob Hauser 		return ret;
93765f79b50SJakob Hauser 
93865f79b50SJakob Hauser 	/* Calibration readout, YAS537 needs one readout only */
93965f79b50SJakob Hauser 	ret = regmap_bulk_read(yas5xx->map, YAS537_CAL, data, sizeof(data));
94065f79b50SJakob Hauser 	if (ret)
94165f79b50SJakob Hauser 		return ret;
94265f79b50SJakob Hauser 	dev_dbg(yas5xx->dev, "calibration data: %17ph\n", data);
94365f79b50SJakob Hauser 
94465f79b50SJakob Hauser 	/* Sanity check, is this all zeroes? */
94565f79b50SJakob Hauser 	if (!memchr_inv(data, 0x00, 16) && !FIELD_GET(GENMASK(5, 0), data[16]))
94665f79b50SJakob Hauser 		dev_warn(yas5xx->dev, "calibration is blank!\n");
94765f79b50SJakob Hauser 
94865f79b50SJakob Hauser 	/* Contribute calibration data to the input pool for kernel entropy */
94965f79b50SJakob Hauser 	add_device_randomness(data, sizeof(data));
95065f79b50SJakob Hauser 
95165f79b50SJakob Hauser 	/* Extract version information */
95265f79b50SJakob Hauser 	yas5xx->version = FIELD_GET(GENMASK(7, 6), data[16]);
95365f79b50SJakob Hauser 
95465f79b50SJakob Hauser 	/* There are two versions of YAS537 behaving differently */
95565f79b50SJakob Hauser 	switch (yas5xx->version) {
95665f79b50SJakob Hauser 	case YAS537_VERSION_0:
95765f79b50SJakob Hauser 		/*
95865f79b50SJakob Hauser 		 * The first version simply writes data back into registers:
95965f79b50SJakob Hauser 		 *
96065f79b50SJakob Hauser 		 * data[0]  YAS537_MTC		0x93
96165f79b50SJakob Hauser 		 * data[1]			0x94
96265f79b50SJakob Hauser 		 * data[2]			0x95
96365f79b50SJakob Hauser 		 * data[3]			0x96
96465f79b50SJakob Hauser 		 * data[4]			0x97
96565f79b50SJakob Hauser 		 * data[5]			0x98
96665f79b50SJakob Hauser 		 * data[6]			0x99
96765f79b50SJakob Hauser 		 * data[7]			0x9a
96865f79b50SJakob Hauser 		 * data[8]			0x9b
96965f79b50SJakob Hauser 		 * data[9]			0x9c
97065f79b50SJakob Hauser 		 * data[10]			0x9d
97165f79b50SJakob Hauser 		 * data[11] YAS537_OC		0x9e
97265f79b50SJakob Hauser 		 *
97365f79b50SJakob Hauser 		 * data[12] YAS537_OFFSET_X	0x84
97465f79b50SJakob Hauser 		 * data[13] YAS537_OFFSET_Y1	0x85
97565f79b50SJakob Hauser 		 * data[14] YAS537_OFFSET_Y2	0x86
97665f79b50SJakob Hauser 		 *
97765f79b50SJakob Hauser 		 * data[15] YAS537_HCK		0x88
97865f79b50SJakob Hauser 		 * data[16] YAS537_LCK		0x89
97965f79b50SJakob Hauser 		 */
98065f79b50SJakob Hauser 		for (i = 0; i < 12; i++) {
98165f79b50SJakob Hauser 			ret = regmap_write(yas5xx->map, YAS537_MTC + i,
98265f79b50SJakob Hauser 					   data[i]);
98365f79b50SJakob Hauser 			if (ret)
98465f79b50SJakob Hauser 				return ret;
98565f79b50SJakob Hauser 		}
98665f79b50SJakob Hauser 		for (i = 0; i < 3; i++) {
98765f79b50SJakob Hauser 			ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i,
98865f79b50SJakob Hauser 					   data[i + 12]);
98965f79b50SJakob Hauser 			if (ret)
99065f79b50SJakob Hauser 				return ret;
99165f79b50SJakob Hauser 			yas5xx->hard_offsets[i] = data[i + 12];
99265f79b50SJakob Hauser 		}
99365f79b50SJakob Hauser 		for (i = 0; i < 2; i++) {
99465f79b50SJakob Hauser 			ret = regmap_write(yas5xx->map, YAS537_HCK + i,
99565f79b50SJakob Hauser 					   data[i + 15]);
99665f79b50SJakob Hauser 			if (ret)
99765f79b50SJakob Hauser 				return ret;
99865f79b50SJakob Hauser 		}
99965f79b50SJakob Hauser 		break;
100065f79b50SJakob Hauser 	case YAS537_VERSION_1:
100165f79b50SJakob Hauser 		/*
100265f79b50SJakob Hauser 		 * The second version writes some data into registers but also
100365f79b50SJakob Hauser 		 * extracts calibration coefficients.
100465f79b50SJakob Hauser 		 *
100565f79b50SJakob Hauser 		 * Registers being written:
100665f79b50SJakob Hauser 		 *
100765f79b50SJakob Hauser 		 * data[0]  YAS537_MTC			0x93
100865f79b50SJakob Hauser 		 * data[1]  YAS537_MTC+1		0x94
100965f79b50SJakob Hauser 		 * data[2]  YAS537_MTC+2		0x95
101065f79b50SJakob Hauser 		 * data[3]  YAS537_MTC+3 (partially)	0x96
101165f79b50SJakob Hauser 		 *
101265f79b50SJakob Hauser 		 * data[12] YAS537_OFFSET_X		0x84
101365f79b50SJakob Hauser 		 * data[13] YAS537_OFFSET_Y1		0x85
101465f79b50SJakob Hauser 		 * data[14] YAS537_OFFSET_Y2		0x86
101565f79b50SJakob Hauser 		 *
101665f79b50SJakob Hauser 		 * data[15] YAS537_HCK (partially)	0x88
101765f79b50SJakob Hauser 		 *          YAS537_LCK (partially)	0x89
101865f79b50SJakob Hauser 		 * data[16] YAS537_OC  (partially)	0x9e
101965f79b50SJakob Hauser 		 */
102065f79b50SJakob Hauser 		for (i = 0; i < 3; i++) {
102165f79b50SJakob Hauser 			ret = regmap_write(yas5xx->map, YAS537_MTC + i,
102265f79b50SJakob Hauser 					   data[i]);
102365f79b50SJakob Hauser 			if (ret)
102465f79b50SJakob Hauser 				return ret;
102565f79b50SJakob Hauser 		}
102665f79b50SJakob Hauser 		for (i = 0; i < 3; i++) {
102765f79b50SJakob Hauser 			ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i,
102865f79b50SJakob Hauser 					   data[i + 12]);
102965f79b50SJakob Hauser 			if (ret)
103065f79b50SJakob Hauser 				return ret;
103165f79b50SJakob Hauser 			yas5xx->hard_offsets[i] = data[i + 12];
103265f79b50SJakob Hauser 		}
103365f79b50SJakob Hauser 		/*
103465f79b50SJakob Hauser 		 * Visualization of partially taken data:
103565f79b50SJakob Hauser 		 *
103665f79b50SJakob Hauser 		 * data[3]       n 7 6 5 4 3 2 1 0
103765f79b50SJakob Hauser 		 * YAS537_MTC+3    x x x 1 0 0 0 0
103865f79b50SJakob Hauser 		 *
103965f79b50SJakob Hauser 		 * data[15]      n 7 6 5 4 3 2 1 0
104065f79b50SJakob Hauser 		 * YAS537_HCK      x x x x 0
104165f79b50SJakob Hauser 		 *
104265f79b50SJakob Hauser 		 * data[15]      n 7 6 5 4 3 2 1 0
104365f79b50SJakob Hauser 		 * YAS537_LCK              x x x x 0
104465f79b50SJakob Hauser 		 *
104565f79b50SJakob Hauser 		 * data[16]      n 7 6 5 4 3 2 1 0
104665f79b50SJakob Hauser 		 * YAS537_OC           x x x x x x
104765f79b50SJakob Hauser 		 */
104865f79b50SJakob Hauser 		ret = regmap_write(yas5xx->map, YAS537_MTC + 3,
104965f79b50SJakob Hauser 				   FIELD_PREP(YAS537_MTC3_MASK_PREP,
105065f79b50SJakob Hauser 				   FIELD_GET(YAS537_MTC3_MASK_GET, data[3])) |
105165f79b50SJakob Hauser 				   YAS537_MTC3_ADD_BIT);
105265f79b50SJakob Hauser 		if (ret)
105365f79b50SJakob Hauser 			return ret;
105465f79b50SJakob Hauser 		ret = regmap_write(yas5xx->map, YAS537_HCK,
105565f79b50SJakob Hauser 				   FIELD_PREP(YAS537_HCK_MASK_PREP,
105665f79b50SJakob Hauser 				   FIELD_GET(YAS537_HCK_MASK_GET, data[15])));
105765f79b50SJakob Hauser 		if (ret)
105865f79b50SJakob Hauser 			return ret;
105965f79b50SJakob Hauser 		ret = regmap_write(yas5xx->map, YAS537_LCK,
106065f79b50SJakob Hauser 				   FIELD_PREP(YAS537_LCK_MASK_PREP,
106165f79b50SJakob Hauser 				   FIELD_GET(YAS537_LCK_MASK_GET, data[15])));
106265f79b50SJakob Hauser 		if (ret)
106365f79b50SJakob Hauser 			return ret;
106465f79b50SJakob Hauser 		ret = regmap_write(yas5xx->map, YAS537_OC,
106565f79b50SJakob Hauser 				   FIELD_GET(YAS537_OC_MASK_GET, data[16]));
106665f79b50SJakob Hauser 		if (ret)
106765f79b50SJakob Hauser 			return ret;
106865f79b50SJakob Hauser 		/*
106965f79b50SJakob Hauser 		 * For data extraction, build some blocks. Four 32-bit blocks
107065f79b50SJakob Hauser 		 * look appropriate.
107165f79b50SJakob Hauser 		 *
107265f79b50SJakob Hauser 		 *            n    7  6  5  4  3  2  1  0
107365f79b50SJakob Hauser 		 *  data[0]   0 [ Cx Cx Cx Cx Cx Cx Cx Cx ] bits 31 .. 24
107465f79b50SJakob Hauser 		 *  data[1]   1 [ Cx C1 C1 C1 C1 C1 C1 C1 ] bits 23 .. 16
107565f79b50SJakob Hauser 		 *  data[2]   2 [ C1 C1 C2 C2 C2 C2 C2 C2 ] bits 15 .. 8
107665f79b50SJakob Hauser 		 *  data[3]   3 [ C2 C2 C2                ] bits  7 .. 0
107765f79b50SJakob Hauser 		 *
107865f79b50SJakob Hauser 		 *            n    7  6  5  4  3  2  1  0
107965f79b50SJakob Hauser 		 *  data[3]   0 [          a2 a2 a2 a2 a2 ] bits 31 .. 24
108065f79b50SJakob Hauser 		 *  data[4]   1 [ a2 a2 a3 a3 a3 a3 a3 a3 ] bits 23 .. 16
108165f79b50SJakob Hauser 		 *  data[5]   2 [ a3 a4 a4 a4 a4 a4 a4 a4 ] bits 15 .. 8
108265f79b50SJakob Hauser 		 *  data[6]   3 [ a4                      ] bits  7 .. 0
108365f79b50SJakob Hauser 		 *
108465f79b50SJakob Hauser 		 *            n    7  6  5  4  3  2  1  0
108565f79b50SJakob Hauser 		 *  data[6]   0 [    a5 a5 a5 a5 a5 a5 a5 ] bits 31 .. 24
108665f79b50SJakob Hauser 		 *  data[7]   1 [ a5 a5 a6 a6 a6 a6 a6 a6 ] bits 23 .. 16
108765f79b50SJakob Hauser 		 *  data[8]   2 [ a6 a7 a7 a7 a7 a7 a7 a7 ] bits 15 .. 8
108865f79b50SJakob Hauser 		 *  data[9]   3 [ a7                      ] bits  7 .. 0
108965f79b50SJakob Hauser 		 *
109065f79b50SJakob Hauser 		 *            n    7  6  5  4  3  2  1  0
109165f79b50SJakob Hauser 		 *  data[9]   0 [    a8 a8 a8 a8 a8 a8 a8 ] bits 31 .. 24
109265f79b50SJakob Hauser 		 *  data[10]  1 [ a9 a9 a9 a9 a9 a9 a9 a9 ] bits 23 .. 16
109365f79b50SJakob Hauser 		 *  data[11]  2 [ a9  k  k  k  k  k  k  k ] bits 15 .. 8
109465f79b50SJakob Hauser 		 *  data[12]  3 [                         ] bits  7 .. 0
109565f79b50SJakob Hauser 		 */
109665f79b50SJakob Hauser 		val1 = get_unaligned_be32(&data[0]);
109765f79b50SJakob Hauser 		val2 = get_unaligned_be32(&data[3]);
109865f79b50SJakob Hauser 		val3 = get_unaligned_be32(&data[6]);
109965f79b50SJakob Hauser 		val4 = get_unaligned_be32(&data[9]);
110065f79b50SJakob Hauser 		/* Extract calibration coefficients and modify */
110165f79b50SJakob Hauser 		c->Cx  = FIELD_GET(GENMASK(31, 23), val1) - 256;
110265f79b50SJakob Hauser 		c->Cy1 = FIELD_GET(GENMASK(22, 14), val1) - 256;
110365f79b50SJakob Hauser 		c->Cy2 = FIELD_GET(GENMASK(13,  5), val1) - 256;
110465f79b50SJakob Hauser 		c->a2  = FIELD_GET(GENMASK(28, 22), val2) -  64;
110565f79b50SJakob Hauser 		c->a3  = FIELD_GET(GENMASK(21, 15), val2) -  64;
110665f79b50SJakob Hauser 		c->a4  = FIELD_GET(GENMASK(14,  7), val2) - 128;
110765f79b50SJakob Hauser 		c->a5  = FIELD_GET(GENMASK(30, 22), val3) - 112;
110865f79b50SJakob Hauser 		c->a6  = FIELD_GET(GENMASK(21, 15), val3) -  64;
110965f79b50SJakob Hauser 		c->a7  = FIELD_GET(GENMASK(14,  7), val3) - 128;
111065f79b50SJakob Hauser 		c->a8  = FIELD_GET(GENMASK(30, 24), val4) -  64;
111165f79b50SJakob Hauser 		c->a9  = FIELD_GET(GENMASK(23, 15), val4) - 112;
111265f79b50SJakob Hauser 		c->k   = FIELD_GET(GENMASK(14,  8), val4);
111365f79b50SJakob Hauser 		break;
111465f79b50SJakob Hauser 	default:
111565f79b50SJakob Hauser 		dev_err(yas5xx->dev, "unknown version of YAS537\n");
111665f79b50SJakob Hauser 		return -EINVAL;
111765f79b50SJakob Hauser 	}
111865f79b50SJakob Hauser 
111965f79b50SJakob Hauser 	return 0;
112065f79b50SJakob Hauser }
112165f79b50SJakob Hauser 
11226e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_dump_calibration(struct yas5xx * yas5xx)11236e3bfa97SJakob Hauser static void yas530_dump_calibration(struct yas5xx *yas5xx)
1124de8860b1SLinus Walleij {
1125de8860b1SLinus Walleij 	struct yas5xx_calibration *c = &yas5xx->calibration;
1126de8860b1SLinus Walleij 
1127de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "f[] = [%d, %d, %d]\n",
1128de8860b1SLinus Walleij 		c->f[0], c->f[1], c->f[2]);
1129de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "r[] = [%d, %d, %d]\n",
1130de8860b1SLinus Walleij 		c->r[0], c->r[1], c->r[2]);
1131de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "Cx = %d\n", c->Cx);
1132de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "Cy1 = %d\n", c->Cy1);
1133de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "Cy2 = %d\n", c->Cy2);
1134de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a2 = %d\n", c->a2);
1135de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a3 = %d\n", c->a3);
1136de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a4 = %d\n", c->a4);
1137de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a5 = %d\n", c->a5);
1138de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a6 = %d\n", c->a6);
1139de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a7 = %d\n", c->a7);
1140de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a8 = %d\n", c->a8);
1141de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "a9 = %d\n", c->a9);
1142de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "k = %d\n", c->k);
1143de8860b1SLinus Walleij 	dev_dbg(yas5xx->dev, "dck = %d\n", c->dck);
1144de8860b1SLinus Walleij }
1145de8860b1SLinus Walleij 
yas537_dump_calibration(struct yas5xx * yas5xx)114665f79b50SJakob Hauser static void yas537_dump_calibration(struct yas5xx *yas5xx)
114765f79b50SJakob Hauser {
114865f79b50SJakob Hauser 	struct yas5xx_calibration *c = &yas5xx->calibration;
114965f79b50SJakob Hauser 
115065f79b50SJakob Hauser 	if (yas5xx->version == YAS537_VERSION_1) {
115165f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "Cx = %d\n", c->Cx);
115265f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "Cy1 = %d\n", c->Cy1);
115365f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "Cy2 = %d\n", c->Cy2);
115465f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a2 = %d\n", c->a2);
115565f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a3 = %d\n", c->a3);
115665f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a4 = %d\n", c->a4);
115765f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a5 = %d\n", c->a5);
115865f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a6 = %d\n", c->a6);
115965f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a7 = %d\n", c->a7);
116065f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a8 = %d\n", c->a8);
116165f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "a9 = %d\n", c->a9);
116265f79b50SJakob Hauser 		dev_dbg(yas5xx->dev, "k = %d\n", c->k);
116365f79b50SJakob Hauser 	}
116465f79b50SJakob Hauser }
116565f79b50SJakob Hauser 
11666e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_set_offsets(struct yas5xx * yas5xx,s8 ox,s8 oy1,s8 oy2)11676e3bfa97SJakob Hauser static int yas530_set_offsets(struct yas5xx *yas5xx, s8 ox, s8 oy1, s8 oy2)
1168de8860b1SLinus Walleij {
1169de8860b1SLinus Walleij 	int ret;
1170de8860b1SLinus Walleij 
11716e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_OFFSET_X, ox);
1172de8860b1SLinus Walleij 	if (ret)
1173de8860b1SLinus Walleij 		return ret;
11746e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_OFFSET_Y1, oy1);
1175de8860b1SLinus Walleij 	if (ret)
1176de8860b1SLinus Walleij 		return ret;
11776e3bfa97SJakob Hauser 	return regmap_write(yas5xx->map, YAS530_OFFSET_Y2, oy2);
1178de8860b1SLinus Walleij }
1179de8860b1SLinus Walleij 
11806e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_adjust_offset(s8 old,int bit,u16 center,u16 measure)11816e3bfa97SJakob Hauser static s8 yas530_adjust_offset(s8 old, int bit, u16 center, u16 measure)
1182de8860b1SLinus Walleij {
1183de8860b1SLinus Walleij 	if (measure > center)
1184de8860b1SLinus Walleij 		return old + BIT(bit);
1185de8860b1SLinus Walleij 	if (measure < center)
1186de8860b1SLinus Walleij 		return old - BIT(bit);
1187de8860b1SLinus Walleij 	return old;
1188de8860b1SLinus Walleij }
1189de8860b1SLinus Walleij 
11906e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_measure_offsets(struct yas5xx * yas5xx)11916e3bfa97SJakob Hauser static int yas530_measure_offsets(struct yas5xx *yas5xx)
1192de8860b1SLinus Walleij {
1193a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
1194de8860b1SLinus Walleij 	int ret;
1195de8860b1SLinus Walleij 	u16 center;
1196de8860b1SLinus Walleij 	u16 t, x, y1, y2;
1197de8860b1SLinus Walleij 	s8 ox, oy1, oy2;
1198de8860b1SLinus Walleij 	int i;
1199de8860b1SLinus Walleij 
1200de8860b1SLinus Walleij 	/* Actuate the init coil and measure offsets */
12016e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_ACTUATE_INIT_COIL, 0);
1202de8860b1SLinus Walleij 	if (ret)
1203de8860b1SLinus Walleij 		return ret;
1204de8860b1SLinus Walleij 
1205de8860b1SLinus Walleij 	/* When the initcoil is active this should be around the center */
1206a70f60e5SJakob Hauser 	switch (ci->devid) {
1207de8860b1SLinus Walleij 	case YAS530_DEVICE_ID:
1208de8860b1SLinus Walleij 		center = YAS530_DATA_CENTER;
1209de8860b1SLinus Walleij 		break;
1210de8860b1SLinus Walleij 	case YAS532_DEVICE_ID:
1211de8860b1SLinus Walleij 		center = YAS532_DATA_CENTER;
1212de8860b1SLinus Walleij 		break;
1213de8860b1SLinus Walleij 	default:
1214de8860b1SLinus Walleij 		dev_err(yas5xx->dev, "unknown device type\n");
1215de8860b1SLinus Walleij 		return -EINVAL;
1216de8860b1SLinus Walleij 	}
1217de8860b1SLinus Walleij 
1218de8860b1SLinus Walleij 	/*
1219de8860b1SLinus Walleij 	 * We set offsets in the interval +-31 by iterating
1220de8860b1SLinus Walleij 	 * +-16, +-8, +-4, +-2, +-1 adjusting the offsets each
1221de8860b1SLinus Walleij 	 * time, then writing the final offsets into the
1222de8860b1SLinus Walleij 	 * registers.
1223de8860b1SLinus Walleij 	 *
1224de8860b1SLinus Walleij 	 * NOTE: these offsets are NOT in the same unit or magnitude
1225de8860b1SLinus Walleij 	 * as the values for [x, y1, y2]. The value is +/-31
1226de8860b1SLinus Walleij 	 * but the effect on the raw values is much larger.
1227de8860b1SLinus Walleij 	 * The effect of the offset is to bring the measure
1228de8860b1SLinus Walleij 	 * rougly to the center.
1229de8860b1SLinus Walleij 	 */
1230de8860b1SLinus Walleij 	ox = 0;
1231de8860b1SLinus Walleij 	oy1 = 0;
1232de8860b1SLinus Walleij 	oy2 = 0;
1233de8860b1SLinus Walleij 
1234de8860b1SLinus Walleij 	for (i = 4; i >= 0; i--) {
12356e3bfa97SJakob Hauser 		ret = yas530_set_offsets(yas5xx, ox, oy1, oy2);
1236de8860b1SLinus Walleij 		if (ret)
1237de8860b1SLinus Walleij 			return ret;
1238de8860b1SLinus Walleij 
12396e3bfa97SJakob Hauser 		ret = yas530_measure(yas5xx, &t, &x, &y1, &y2);
1240de8860b1SLinus Walleij 		if (ret)
1241de8860b1SLinus Walleij 			return ret;
1242de8860b1SLinus Walleij 		dev_dbg(yas5xx->dev, "measurement %d: x=%d, y1=%d, y2=%d\n",
1243de8860b1SLinus Walleij 			5-i, x, y1, y2);
1244de8860b1SLinus Walleij 
12456e3bfa97SJakob Hauser 		ox = yas530_adjust_offset(ox, i, center, x);
12466e3bfa97SJakob Hauser 		oy1 = yas530_adjust_offset(oy1, i, center, y1);
12476e3bfa97SJakob Hauser 		oy2 = yas530_adjust_offset(oy2, i, center, y2);
1248de8860b1SLinus Walleij 	}
1249de8860b1SLinus Walleij 
1250de8860b1SLinus Walleij 	/* Needed for calibration algorithm */
1251de8860b1SLinus Walleij 	yas5xx->hard_offsets[0] = ox;
1252de8860b1SLinus Walleij 	yas5xx->hard_offsets[1] = oy1;
1253de8860b1SLinus Walleij 	yas5xx->hard_offsets[2] = oy2;
12546e3bfa97SJakob Hauser 	ret = yas530_set_offsets(yas5xx, ox, oy1, oy2);
1255de8860b1SLinus Walleij 	if (ret)
1256de8860b1SLinus Walleij 		return ret;
1257de8860b1SLinus Walleij 
1258de8860b1SLinus Walleij 	dev_info(yas5xx->dev, "discovered hard offsets: x=%d, y1=%d, y2=%d\n",
1259de8860b1SLinus Walleij 		 ox, oy1, oy2);
1260de8860b1SLinus Walleij 	return 0;
1261de8860b1SLinus Walleij }
1262de8860b1SLinus Walleij 
12636e3bfa97SJakob Hauser /* Used by YAS530, YAS532 and YAS533 */
yas530_power_on(struct yas5xx * yas5xx)12646e3bfa97SJakob Hauser static int yas530_power_on(struct yas5xx *yas5xx)
1265de8860b1SLinus Walleij {
1266de8860b1SLinus Walleij 	unsigned int val;
1267de8860b1SLinus Walleij 	int ret;
1268de8860b1SLinus Walleij 
1269de8860b1SLinus Walleij 	/* Zero the test registers */
12706e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_TEST1, 0);
1271de8860b1SLinus Walleij 	if (ret)
1272de8860b1SLinus Walleij 		return ret;
12736e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_TEST2, 0);
1274de8860b1SLinus Walleij 	if (ret)
1275de8860b1SLinus Walleij 		return ret;
1276de8860b1SLinus Walleij 
1277de8860b1SLinus Walleij 	/* Set up for no interrupts, calibrated clock divider */
1278de8860b1SLinus Walleij 	val = FIELD_PREP(YAS5XX_CONFIG_CCK_MASK, yas5xx->calibration.dck);
12796e3bfa97SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS530_CONFIG, val);
1280de8860b1SLinus Walleij 	if (ret)
1281de8860b1SLinus Walleij 		return ret;
1282de8860b1SLinus Walleij 
1283de8860b1SLinus Walleij 	/* Measure interval 0 (back-to-back?)  */
12846e3bfa97SJakob Hauser 	return regmap_write(yas5xx->map, YAS530_MEASURE_INTERVAL, 0);
1285de8860b1SLinus Walleij }
1286de8860b1SLinus Walleij 
yas537_power_on(struct yas5xx * yas5xx)128765f79b50SJakob Hauser static int yas537_power_on(struct yas5xx *yas5xx)
128865f79b50SJakob Hauser {
128965f79b50SJakob Hauser 	__be16 buf;
129065f79b50SJakob Hauser 	int ret;
129165f79b50SJakob Hauser 	u8 intrvl;
129265f79b50SJakob Hauser 
129365f79b50SJakob Hauser 	/* Writing ADCCAL and TRM registers */
129465f79b50SJakob Hauser 	buf = cpu_to_be16(GENMASK(9, 3));
129565f79b50SJakob Hauser 	ret = regmap_bulk_write(yas5xx->map, YAS537_ADCCAL, &buf, sizeof(buf));
129665f79b50SJakob Hauser 	if (ret)
129765f79b50SJakob Hauser 		return ret;
129865f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_TRM, GENMASK(7, 0));
129965f79b50SJakob Hauser 	if (ret)
130065f79b50SJakob Hauser 		return ret;
130165f79b50SJakob Hauser 
130265f79b50SJakob Hauser 	/* The interval value is static in regular operation */
130365f79b50SJakob Hauser 	intrvl = (YAS537_DEFAULT_SENSOR_DELAY_MS * MILLI
130465f79b50SJakob Hauser 		 - YAS537_MEASURE_TIME_WORST_US) / 4100;
130565f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_MEASURE_INTERVAL, intrvl);
130665f79b50SJakob Hauser 	if (ret)
130765f79b50SJakob Hauser 		return ret;
130865f79b50SJakob Hauser 
130965f79b50SJakob Hauser 	/* The average value is also static in regular operation */
131065f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_AVR, YAS537_MAG_AVERAGE_32_MASK);
131165f79b50SJakob Hauser 	if (ret)
131265f79b50SJakob Hauser 		return ret;
131365f79b50SJakob Hauser 
131465f79b50SJakob Hauser 	/* Perform the "rcoil" part but skip the "last_after_rcoil" read */
131565f79b50SJakob Hauser 	ret = regmap_write(yas5xx->map, YAS537_CONFIG, BIT(3));
131665f79b50SJakob Hauser 	if (ret)
131765f79b50SJakob Hauser 		return ret;
131865f79b50SJakob Hauser 
131965f79b50SJakob Hauser 	/* Wait until the coil has ramped up */
132065f79b50SJakob Hauser 	usleep_range(YAS537_MAG_RCOIL_TIME_US, YAS537_MAG_RCOIL_TIME_US + 100);
132165f79b50SJakob Hauser 
132265f79b50SJakob Hauser 	return 0;
132365f79b50SJakob Hauser }
132465f79b50SJakob Hauser 
1325a70f60e5SJakob Hauser static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = {
1326a70f60e5SJakob Hauser 	[yas530] = {
1327a70f60e5SJakob Hauser 		.devid = YAS530_DEVICE_ID,
1328a70f60e5SJakob Hauser 		.product_name = "YAS530 MS-3E",
1329a70f60e5SJakob Hauser 		.version_names = { "A", "B" },
1330dd9bd44fSJakob Hauser 		.volatile_reg = yas530_volatile_reg,
1331dd9bd44fSJakob Hauser 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
1332913fd409SJakob Hauser 		.scaling_val2 = 100000000, /* picotesla to Gauss */
13332d6676ecSJakob Hauser 		.t_ref = 182, /* counts */
13342d6676ecSJakob Hauser 		.min_temp_x10 = -620, /* 1/10:s degrees Celsius */
1335059ff0f9SJakob Hauser 		.get_measure = yas530_get_measure,
1336059ff0f9SJakob Hauser 		.get_calibration_data = yas530_get_calibration_data,
1337059ff0f9SJakob Hauser 		.dump_calibration = yas530_dump_calibration,
1338059ff0f9SJakob Hauser 		.measure_offsets = yas530_measure_offsets,
1339059ff0f9SJakob Hauser 		.power_on = yas530_power_on,
1340a70f60e5SJakob Hauser 	},
1341a70f60e5SJakob Hauser 	[yas532] = {
1342a70f60e5SJakob Hauser 		.devid = YAS532_DEVICE_ID,
1343a70f60e5SJakob Hauser 		.product_name = "YAS532 MS-3R",
1344a70f60e5SJakob Hauser 		.version_names = { "AB", "AC" },
1345dd9bd44fSJakob Hauser 		.volatile_reg = yas530_volatile_reg,
1346dd9bd44fSJakob Hauser 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
1347913fd409SJakob Hauser 		.scaling_val2 = 100000, /* nanotesla to Gauss */
13482d6676ecSJakob Hauser 		.t_ref = 390, /* counts */
13492d6676ecSJakob Hauser 		.min_temp_x10 = -500, /* 1/10:s degrees Celsius */
1350059ff0f9SJakob Hauser 		.get_measure = yas530_get_measure,
1351059ff0f9SJakob Hauser 		.get_calibration_data = yas532_get_calibration_data,
1352059ff0f9SJakob Hauser 		.dump_calibration = yas530_dump_calibration,
1353059ff0f9SJakob Hauser 		.measure_offsets = yas530_measure_offsets,
1354059ff0f9SJakob Hauser 		.power_on = yas530_power_on,
1355a70f60e5SJakob Hauser 	},
1356a70f60e5SJakob Hauser 	[yas533] = {
1357a70f60e5SJakob Hauser 		.devid = YAS532_DEVICE_ID,
1358a70f60e5SJakob Hauser 		.product_name = "YAS533 MS-3F",
1359a70f60e5SJakob Hauser 		.version_names = { "AB", "AC" },
1360dd9bd44fSJakob Hauser 		.volatile_reg = yas530_volatile_reg,
1361dd9bd44fSJakob Hauser 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg),
1362913fd409SJakob Hauser 		.scaling_val2 = 100000, /* nanotesla to Gauss */
13632d6676ecSJakob Hauser 		.t_ref = 390, /* counts */
13642d6676ecSJakob Hauser 		.min_temp_x10 = -500, /* 1/10:s degrees Celsius */
1365059ff0f9SJakob Hauser 		.get_measure = yas530_get_measure,
1366059ff0f9SJakob Hauser 		.get_calibration_data = yas532_get_calibration_data,
1367059ff0f9SJakob Hauser 		.dump_calibration = yas530_dump_calibration,
1368059ff0f9SJakob Hauser 		.measure_offsets = yas530_measure_offsets,
1369059ff0f9SJakob Hauser 		.power_on = yas530_power_on,
1370a70f60e5SJakob Hauser 	},
137165f79b50SJakob Hauser 	[yas537] = {
137265f79b50SJakob Hauser 		.devid = YAS537_DEVICE_ID,
137365f79b50SJakob Hauser 		.product_name = "YAS537 MS-3T",
137465f79b50SJakob Hauser 		.version_names = { "v0", "v1" }, /* version naming unknown */
137565f79b50SJakob Hauser 		.volatile_reg = yas537_volatile_reg,
137665f79b50SJakob Hauser 		.volatile_reg_qty = ARRAY_SIZE(yas537_volatile_reg),
137765f79b50SJakob Hauser 		.scaling_val2 = 100000, /* nanotesla to Gauss */
137865f79b50SJakob Hauser 		.t_ref = 8120, /* counts */
137965f79b50SJakob Hauser 		.min_temp_x10 = -3860, /* 1/10:s degrees Celsius */
138065f79b50SJakob Hauser 		.get_measure = yas537_get_measure,
138165f79b50SJakob Hauser 		.get_calibration_data = yas537_get_calibration_data,
138265f79b50SJakob Hauser 		.dump_calibration = yas537_dump_calibration,
138365f79b50SJakob Hauser 		/* .measure_offets is not needed for yas537 */
138465f79b50SJakob Hauser 		.power_on = yas537_power_on,
138565f79b50SJakob Hauser 	},
1386a70f60e5SJakob Hauser };
1387a70f60e5SJakob Hauser 
yas5xx_probe(struct i2c_client * i2c)1388fcd96967SUwe Kleine-König static int yas5xx_probe(struct i2c_client *i2c)
1389de8860b1SLinus Walleij {
1390fcd96967SUwe Kleine-König 	const struct i2c_device_id *id = i2c_client_get_device_id(i2c);
1391de8860b1SLinus Walleij 	struct iio_dev *indio_dev;
1392de8860b1SLinus Walleij 	struct device *dev = &i2c->dev;
1393de8860b1SLinus Walleij 	struct yas5xx *yas5xx;
1394a70f60e5SJakob Hauser 	const struct yas5xx_chip_info *ci;
1395a70f60e5SJakob Hauser 	int id_check;
1396de8860b1SLinus Walleij 	int ret;
1397de8860b1SLinus Walleij 
1398de8860b1SLinus Walleij 	indio_dev = devm_iio_device_alloc(dev, sizeof(*yas5xx));
1399de8860b1SLinus Walleij 	if (!indio_dev)
1400de8860b1SLinus Walleij 		return -ENOMEM;
1401de8860b1SLinus Walleij 
1402de8860b1SLinus Walleij 	yas5xx = iio_priv(indio_dev);
1403de8860b1SLinus Walleij 	i2c_set_clientdata(i2c, indio_dev);
1404de8860b1SLinus Walleij 	yas5xx->dev = dev;
1405de8860b1SLinus Walleij 	mutex_init(&yas5xx->lock);
1406de8860b1SLinus Walleij 
1407b892770aSAndy Shevchenko 	ret = iio_read_mount_matrix(dev, &yas5xx->orientation);
1408de8860b1SLinus Walleij 	if (ret)
1409de8860b1SLinus Walleij 		return ret;
1410de8860b1SLinus Walleij 
1411de8860b1SLinus Walleij 	yas5xx->regs[0].supply = "vdd";
1412de8860b1SLinus Walleij 	yas5xx->regs[1].supply = "iovdd";
1413de8860b1SLinus Walleij 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(yas5xx->regs),
1414de8860b1SLinus Walleij 				      yas5xx->regs);
1415de8860b1SLinus Walleij 	if (ret)
1416de8860b1SLinus Walleij 		return dev_err_probe(dev, ret, "cannot get regulators\n");
1417de8860b1SLinus Walleij 
1418de8860b1SLinus Walleij 	ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1419d05d7377SAndy Shevchenko 	if (ret)
1420d05d7377SAndy Shevchenko 		return dev_err_probe(dev, ret, "cannot enable regulators\n");
1421de8860b1SLinus Walleij 
1422de8860b1SLinus Walleij 	/* See comment in runtime resume callback */
1423de8860b1SLinus Walleij 	usleep_range(31000, 40000);
1424de8860b1SLinus Walleij 
1425de8860b1SLinus Walleij 	/* This will take the device out of reset if need be */
1426de8860b1SLinus Walleij 	yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
1427de8860b1SLinus Walleij 	if (IS_ERR(yas5xx->reset)) {
1428d05d7377SAndy Shevchenko 		ret = dev_err_probe(dev, PTR_ERR(yas5xx->reset), "failed to get reset line\n");
1429de8860b1SLinus Walleij 		goto reg_off;
1430de8860b1SLinus Walleij 	}
1431de8860b1SLinus Walleij 
1432de8860b1SLinus Walleij 	yas5xx->map = devm_regmap_init_i2c(i2c, &yas5xx_regmap_config);
1433de8860b1SLinus Walleij 	if (IS_ERR(yas5xx->map)) {
1434d05d7377SAndy Shevchenko 		ret = dev_err_probe(dev, PTR_ERR(yas5xx->map), "failed to allocate register map\n");
1435de8860b1SLinus Walleij 		goto assert_reset;
1436de8860b1SLinus Walleij 	}
1437de8860b1SLinus Walleij 
1438741d1e37SAndy Shevchenko 	ci = device_get_match_data(dev);
1439741d1e37SAndy Shevchenko 	if (!ci)
1440741d1e37SAndy Shevchenko 		ci = (const struct yas5xx_chip_info *)id->driver_data;
1441741d1e37SAndy Shevchenko 	yas5xx->chip_info = ci;
1442a70f60e5SJakob Hauser 
1443a70f60e5SJakob Hauser 	ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check);
1444de8860b1SLinus Walleij 	if (ret)
1445de8860b1SLinus Walleij 		goto assert_reset;
1446de8860b1SLinus Walleij 
1447a70f60e5SJakob Hauser 	if (id_check != ci->devid) {
1448a70f60e5SJakob Hauser 		ret = dev_err_probe(dev, -ENODEV,
1449a70f60e5SJakob Hauser 				    "device ID %02x doesn't match %s\n",
1450a70f60e5SJakob Hauser 				    id_check, id->name);
1451de8860b1SLinus Walleij 		goto assert_reset;
1452de8860b1SLinus Walleij 	}
1453de8860b1SLinus Walleij 
1454059ff0f9SJakob Hauser 	ret = ci->get_calibration_data(yas5xx);
1455de8860b1SLinus Walleij 	if (ret)
1456de8860b1SLinus Walleij 		goto assert_reset;
1457de8860b1SLinus Walleij 
1458a70f60e5SJakob Hauser 	dev_info(dev, "detected %s %s\n", ci->product_name,
1459a70f60e5SJakob Hauser 		 ci->version_names[yas5xx->version]);
1460a70f60e5SJakob Hauser 
1461059ff0f9SJakob Hauser 	ci->dump_calibration(yas5xx);
1462059ff0f9SJakob Hauser 
1463059ff0f9SJakob Hauser 	ret = ci->power_on(yas5xx);
1464de8860b1SLinus Walleij 	if (ret)
1465de8860b1SLinus Walleij 		goto assert_reset;
1466de8860b1SLinus Walleij 
1467059ff0f9SJakob Hauser 	if (ci->measure_offsets) {
1468059ff0f9SJakob Hauser 		ret = ci->measure_offsets(yas5xx);
1469de8860b1SLinus Walleij 		if (ret)
1470de8860b1SLinus Walleij 			goto assert_reset;
1471059ff0f9SJakob Hauser 	}
1472de8860b1SLinus Walleij 
1473de8860b1SLinus Walleij 	indio_dev->info = &yas5xx_info;
1474de8860b1SLinus Walleij 	indio_dev->available_scan_masks = yas5xx_scan_masks;
1475de8860b1SLinus Walleij 	indio_dev->modes = INDIO_DIRECT_MODE;
1476a70f60e5SJakob Hauser 	indio_dev->name = id->name;
1477de8860b1SLinus Walleij 	indio_dev->channels = yas5xx_channels;
1478de8860b1SLinus Walleij 	indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels);
1479de8860b1SLinus Walleij 
1480de8860b1SLinus Walleij 	ret = iio_triggered_buffer_setup(indio_dev, NULL,
1481de8860b1SLinus Walleij 					 yas5xx_handle_trigger,
1482de8860b1SLinus Walleij 					 NULL);
1483de8860b1SLinus Walleij 	if (ret) {
1484d05d7377SAndy Shevchenko 		dev_err_probe(dev, ret, "triggered buffer setup failed\n");
1485de8860b1SLinus Walleij 		goto assert_reset;
1486de8860b1SLinus Walleij 	}
1487de8860b1SLinus Walleij 
1488de8860b1SLinus Walleij 	ret = iio_device_register(indio_dev);
1489de8860b1SLinus Walleij 	if (ret) {
1490d05d7377SAndy Shevchenko 		dev_err_probe(dev, ret, "device register failed\n");
1491de8860b1SLinus Walleij 		goto cleanup_buffer;
1492de8860b1SLinus Walleij 	}
1493de8860b1SLinus Walleij 
1494de8860b1SLinus Walleij 	/* Take runtime PM online */
1495de8860b1SLinus Walleij 	pm_runtime_get_noresume(dev);
1496de8860b1SLinus Walleij 	pm_runtime_set_active(dev);
1497de8860b1SLinus Walleij 	pm_runtime_enable(dev);
1498de8860b1SLinus Walleij 
1499de8860b1SLinus Walleij 	pm_runtime_set_autosuspend_delay(dev, YAS5XX_AUTOSUSPEND_DELAY_MS);
1500de8860b1SLinus Walleij 	pm_runtime_use_autosuspend(dev);
1501de8860b1SLinus Walleij 	pm_runtime_put(dev);
1502de8860b1SLinus Walleij 
1503de8860b1SLinus Walleij 	return 0;
1504de8860b1SLinus Walleij 
1505de8860b1SLinus Walleij cleanup_buffer:
1506de8860b1SLinus Walleij 	iio_triggered_buffer_cleanup(indio_dev);
1507de8860b1SLinus Walleij assert_reset:
1508de8860b1SLinus Walleij 	gpiod_set_value_cansleep(yas5xx->reset, 1);
1509de8860b1SLinus Walleij reg_off:
1510de8860b1SLinus Walleij 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1511de8860b1SLinus Walleij 
1512de8860b1SLinus Walleij 	return ret;
1513de8860b1SLinus Walleij }
1514de8860b1SLinus Walleij 
yas5xx_remove(struct i2c_client * i2c)1515ed5c2f5fSUwe Kleine-König static void yas5xx_remove(struct i2c_client *i2c)
1516de8860b1SLinus Walleij {
1517de8860b1SLinus Walleij 	struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
1518de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
1519de8860b1SLinus Walleij 	struct device *dev = &i2c->dev;
1520de8860b1SLinus Walleij 
1521de8860b1SLinus Walleij 	iio_device_unregister(indio_dev);
1522de8860b1SLinus Walleij 	iio_triggered_buffer_cleanup(indio_dev);
1523de8860b1SLinus Walleij 	/*
1524de8860b1SLinus Walleij 	 * Now we can't get any more reads from the device, which would
1525de8860b1SLinus Walleij 	 * also call pm_runtime* functions and race with our disable
1526de8860b1SLinus Walleij 	 * code. Disable PM runtime in orderly fashion and power down.
1527de8860b1SLinus Walleij 	 */
1528de8860b1SLinus Walleij 	pm_runtime_get_sync(dev);
1529de8860b1SLinus Walleij 	pm_runtime_put_noidle(dev);
1530de8860b1SLinus Walleij 	pm_runtime_disable(dev);
1531de8860b1SLinus Walleij 	gpiod_set_value_cansleep(yas5xx->reset, 1);
1532de8860b1SLinus Walleij 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1533de8860b1SLinus Walleij }
1534de8860b1SLinus Walleij 
yas5xx_runtime_suspend(struct device * dev)1535e5933cf4SJonathan Cameron static int yas5xx_runtime_suspend(struct device *dev)
1536de8860b1SLinus Walleij {
1537de8860b1SLinus Walleij 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
1538de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
1539de8860b1SLinus Walleij 
1540de8860b1SLinus Walleij 	gpiod_set_value_cansleep(yas5xx->reset, 1);
1541de8860b1SLinus Walleij 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1542de8860b1SLinus Walleij 
1543de8860b1SLinus Walleij 	return 0;
1544de8860b1SLinus Walleij }
1545de8860b1SLinus Walleij 
yas5xx_runtime_resume(struct device * dev)1546e5933cf4SJonathan Cameron static int yas5xx_runtime_resume(struct device *dev)
1547de8860b1SLinus Walleij {
1548de8860b1SLinus Walleij 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
1549de8860b1SLinus Walleij 	struct yas5xx *yas5xx = iio_priv(indio_dev);
1550059ff0f9SJakob Hauser 	const struct yas5xx_chip_info *ci = yas5xx->chip_info;
1551de8860b1SLinus Walleij 	int ret;
1552de8860b1SLinus Walleij 
1553de8860b1SLinus Walleij 	ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1554de8860b1SLinus Walleij 	if (ret) {
1555de8860b1SLinus Walleij 		dev_err(dev, "cannot enable regulators\n");
1556de8860b1SLinus Walleij 		return ret;
1557de8860b1SLinus Walleij 	}
1558de8860b1SLinus Walleij 
1559de8860b1SLinus Walleij 	/*
1560de8860b1SLinus Walleij 	 * The YAS530 datasheet says TVSKW is up to 30 ms, after that 1 ms
1561de8860b1SLinus Walleij 	 * for all voltages to settle. The YAS532 is 10ms then 4ms for the
1562de8860b1SLinus Walleij 	 * I2C to come online. Let's keep it safe and put this at 31ms.
1563de8860b1SLinus Walleij 	 */
1564de8860b1SLinus Walleij 	usleep_range(31000, 40000);
1565de8860b1SLinus Walleij 	gpiod_set_value_cansleep(yas5xx->reset, 0);
1566de8860b1SLinus Walleij 
1567059ff0f9SJakob Hauser 	ret = ci->power_on(yas5xx);
1568de8860b1SLinus Walleij 	if (ret) {
1569de8860b1SLinus Walleij 		dev_err(dev, "cannot power on\n");
1570de8860b1SLinus Walleij 		goto out_reset;
1571de8860b1SLinus Walleij 	}
1572de8860b1SLinus Walleij 
1573de8860b1SLinus Walleij 	return 0;
1574de8860b1SLinus Walleij 
1575de8860b1SLinus Walleij out_reset:
1576de8860b1SLinus Walleij 	gpiod_set_value_cansleep(yas5xx->reset, 1);
1577de8860b1SLinus Walleij 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs);
1578de8860b1SLinus Walleij 
1579de8860b1SLinus Walleij 	return ret;
1580de8860b1SLinus Walleij }
1581de8860b1SLinus Walleij 
1582e5933cf4SJonathan Cameron static DEFINE_RUNTIME_DEV_PM_OPS(yas5xx_dev_pm_ops, yas5xx_runtime_suspend,
1583e5933cf4SJonathan Cameron 				 yas5xx_runtime_resume, NULL);
1584de8860b1SLinus Walleij 
1585de8860b1SLinus Walleij static const struct i2c_device_id yas5xx_id[] = {
1586741d1e37SAndy Shevchenko 	{"yas530", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas530] },
1587741d1e37SAndy Shevchenko 	{"yas532", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas532] },
1588741d1e37SAndy Shevchenko 	{"yas533", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas533] },
1589741d1e37SAndy Shevchenko 	{"yas537", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas537] },
1590de8860b1SLinus Walleij 	{}
1591de8860b1SLinus Walleij };
1592de8860b1SLinus Walleij MODULE_DEVICE_TABLE(i2c, yas5xx_id);
1593de8860b1SLinus Walleij 
1594de8860b1SLinus Walleij static const struct of_device_id yas5xx_of_match[] = {
1595741d1e37SAndy Shevchenko 	{ .compatible = "yamaha,yas530", &yas5xx_chip_info_tbl[yas530] },
1596741d1e37SAndy Shevchenko 	{ .compatible = "yamaha,yas532", &yas5xx_chip_info_tbl[yas532] },
1597741d1e37SAndy Shevchenko 	{ .compatible = "yamaha,yas533", &yas5xx_chip_info_tbl[yas533] },
1598741d1e37SAndy Shevchenko 	{ .compatible = "yamaha,yas537", &yas5xx_chip_info_tbl[yas537] },
1599de8860b1SLinus Walleij 	{}
1600de8860b1SLinus Walleij };
1601de8860b1SLinus Walleij MODULE_DEVICE_TABLE(of, yas5xx_of_match);
1602de8860b1SLinus Walleij 
1603de8860b1SLinus Walleij static struct i2c_driver yas5xx_driver = {
1604de8860b1SLinus Walleij 	.driver	 = {
1605de8860b1SLinus Walleij 		.name	= "yas5xx",
1606de8860b1SLinus Walleij 		.of_match_table = yas5xx_of_match,
1607e5933cf4SJonathan Cameron 		.pm = pm_ptr(&yas5xx_dev_pm_ops),
1608de8860b1SLinus Walleij 	},
16097cf15f42SUwe Kleine-König 	.probe = yas5xx_probe,
1610de8860b1SLinus Walleij 	.remove	  = yas5xx_remove,
1611de8860b1SLinus Walleij 	.id_table = yas5xx_id,
1612de8860b1SLinus Walleij };
1613de8860b1SLinus Walleij module_i2c_driver(yas5xx_driver);
1614de8860b1SLinus Walleij 
1615de8860b1SLinus Walleij MODULE_DESCRIPTION("Yamaha YAS53x 3-axis magnetometer driver");
1616de8860b1SLinus Walleij MODULE_AUTHOR("Linus Walleij");
1617de8860b1SLinus Walleij MODULE_LICENSE("GPL v2");
1618