| // SPDX-License-Identifier: GPL-2.0-only | 
 | /* | 
 |  * Driver for the Yamaha YAS magnetic sensors, often used in Samsung | 
 |  * mobile phones. While all are not yet handled because of lacking | 
 |  * hardware, expand this driver to handle the different variants: | 
 |  * | 
 |  * YAS530 MS-3E (2011 Samsung Galaxy S Advance) | 
 |  * YAS532 MS-3R (2011 Samsung Galaxy S4) | 
 |  * YAS533 MS-3F (Vivo 1633, 1707, V3, Y21L) | 
 |  * (YAS534 is a magnetic switch, not handled) | 
 |  * YAS535 MS-6C | 
 |  * YAS536 MS-3W | 
 |  * YAS537 MS-3T (2015 Samsung Galaxy S6, Note 5, Galaxy S7) | 
 |  * YAS539 MS-3S (2018 Samsung Galaxy A7 SM-A750FN) | 
 |  * | 
 |  * Code functions found in the MPU3050 YAS530 and YAS532 drivers | 
 |  * named "inv_compass" in the Tegra Android kernel tree. | 
 |  * Copyright (C) 2012 InvenSense Corporation | 
 |  * | 
 |  * Code functions for YAS537 based on Yamaha Android kernel driver. | 
 |  * Copyright (c) 2014 Yamaha Corporation | 
 |  * | 
 |  * Author: Linus Walleij <linus.walleij@linaro.org> | 
 |  */ | 
 | #include <linux/bitfield.h> | 
 | #include <linux/bitops.h> | 
 | #include <linux/delay.h> | 
 | #include <linux/err.h> | 
 | #include <linux/gpio/consumer.h> | 
 | #include <linux/i2c.h> | 
 | #include <linux/module.h> | 
 | #include <linux/mod_devicetable.h> | 
 | #include <linux/mutex.h> | 
 | #include <linux/pm_runtime.h> | 
 | #include <linux/property.h> | 
 | #include <linux/regmap.h> | 
 | #include <linux/regulator/consumer.h> | 
 | #include <linux/random.h> | 
 | #include <linux/units.h> | 
 |  | 
 | #include <linux/iio/buffer.h> | 
 | #include <linux/iio/iio.h> | 
 | #include <linux/iio/trigger_consumer.h> | 
 | #include <linux/iio/triggered_buffer.h> | 
 |  | 
 | #include <asm/unaligned.h> | 
 |  | 
 | /* Commonly used registers */ | 
 | #define YAS5XX_DEVICE_ID		0x80 | 
 | #define YAS5XX_MEASURE_DATA		0xB0 | 
 |  | 
 | /* These registers are used by YAS530, YAS532 and YAS533 */ | 
 | #define YAS530_ACTUATE_INIT_COIL	0x81 | 
 | #define YAS530_MEASURE			0x82 | 
 | #define YAS530_CONFIG			0x83 | 
 | #define YAS530_MEASURE_INTERVAL		0x84 | 
 | #define YAS530_OFFSET_X			0x85 /* [-31 .. 31] */ | 
 | #define YAS530_OFFSET_Y1		0x86 /* [-31 .. 31] */ | 
 | #define YAS530_OFFSET_Y2		0x87 /* [-31 .. 31] */ | 
 | #define YAS530_TEST1			0x88 | 
 | #define YAS530_TEST2			0x89 | 
 | #define YAS530_CAL			0x90 | 
 |  | 
 | /* Registers used by YAS537 */ | 
 | #define YAS537_MEASURE			0x81 /* Originally YAS537_REG_CMDR */ | 
 | #define YAS537_CONFIG			0x82 /* Originally YAS537_REG_CONFR */ | 
 | #define YAS537_MEASURE_INTERVAL		0x83 /* Originally YAS537_REG_INTRVLR */ | 
 | #define YAS537_OFFSET_X			0x84 /* Originally YAS537_REG_OXR */ | 
 | #define YAS537_OFFSET_Y1		0x85 /* Originally YAS537_REG_OY1R */ | 
 | #define YAS537_OFFSET_Y2		0x86 /* Originally YAS537_REG_OY2R */ | 
 | #define YAS537_AVR			0x87 | 
 | #define YAS537_HCK			0x88 | 
 | #define YAS537_LCK			0x89 | 
 | #define YAS537_SRST			0x90 | 
 | #define YAS537_ADCCAL			0x91 | 
 | #define YAS537_MTC			0x93 | 
 | #define YAS537_OC			0x9E | 
 | #define YAS537_TRM			0x9F | 
 | #define YAS537_CAL			0xC0 | 
 |  | 
 | /* Bits in the YAS5xx config register */ | 
 | #define YAS5XX_CONFIG_INTON		BIT(0) /* Interrupt on? */ | 
 | #define YAS5XX_CONFIG_INTHACT		BIT(1) /* Interrupt active high? */ | 
 | #define YAS5XX_CONFIG_CCK_MASK		GENMASK(4, 2) | 
 | #define YAS5XX_CONFIG_CCK_SHIFT		2 | 
 |  | 
 | /* Bits in the measure command register */ | 
 | #define YAS5XX_MEASURE_START		BIT(0) | 
 | #define YAS5XX_MEASURE_LDTC		BIT(1) | 
 | #define YAS5XX_MEASURE_FORS		BIT(2) | 
 | #define YAS5XX_MEASURE_DLYMES		BIT(4) | 
 | #define YAS5XX_MEASURE_CONT		BIT(5) | 
 |  | 
 | /* Bits in the measure data register */ | 
 | #define YAS5XX_MEASURE_DATA_BUSY	BIT(7) | 
 |  | 
 | #define YAS530_DEVICE_ID		0x01 /* YAS530 (MS-3E) */ | 
 | #define YAS530_VERSION_A		0 /* YAS530 (MS-3E A) */ | 
 | #define YAS530_VERSION_B		1 /* YAS530B (MS-3E B) */ | 
 | #define YAS530_VERSION_A_COEF		380 | 
 | #define YAS530_VERSION_B_COEF		550 | 
 | #define YAS530_DATA_BITS		12 | 
 | #define YAS530_DATA_CENTER		BIT(YAS530_DATA_BITS - 1) | 
 | #define YAS530_DATA_OVERFLOW		(BIT(YAS530_DATA_BITS) - 1) | 
 |  | 
 | #define YAS532_DEVICE_ID		0x02 /* YAS532/YAS533 (MS-3R/F) */ | 
 | #define YAS532_VERSION_AB		0 /* YAS532/533 AB (MS-3R/F AB) */ | 
 | #define YAS532_VERSION_AC		1 /* YAS532/533 AC (MS-3R/F AC) */ | 
 | #define YAS532_VERSION_AB_COEF		1800 | 
 | #define YAS532_VERSION_AC_COEF_X	850 | 
 | #define YAS532_VERSION_AC_COEF_Y1	750 | 
 | #define YAS532_VERSION_AC_COEF_Y2	750 | 
 | #define YAS532_DATA_BITS		13 | 
 | #define YAS532_DATA_CENTER		BIT(YAS532_DATA_BITS - 1) | 
 | #define YAS532_DATA_OVERFLOW		(BIT(YAS532_DATA_BITS) - 1) | 
 |  | 
 | #define YAS537_DEVICE_ID		0x07 /* YAS537 (MS-3T) */ | 
 | #define YAS537_VERSION_0		0 /* Version naming unknown */ | 
 | #define YAS537_VERSION_1		1 /* Version naming unknown */ | 
 | #define YAS537_MAG_AVERAGE_32_MASK	GENMASK(6, 4) | 
 | #define YAS537_MEASURE_TIME_WORST_US	1500 | 
 | #define YAS537_DEFAULT_SENSOR_DELAY_MS	50 | 
 | #define YAS537_MAG_RCOIL_TIME_US	65 | 
 | #define YAS537_MTC3_MASK_PREP		GENMASK(7, 0) | 
 | #define YAS537_MTC3_MASK_GET		GENMASK(7, 5) | 
 | #define YAS537_MTC3_ADD_BIT		BIT(4) | 
 | #define YAS537_HCK_MASK_PREP		GENMASK(4, 0) | 
 | #define YAS537_HCK_MASK_GET		GENMASK(7, 4) | 
 | #define YAS537_LCK_MASK_PREP		GENMASK(4, 0) | 
 | #define YAS537_LCK_MASK_GET		GENMASK(3, 0) | 
 | #define YAS537_OC_MASK_GET		GENMASK(5, 0) | 
 |  | 
 | /* Turn off device regulators etc after 5 seconds of inactivity */ | 
 | #define YAS5XX_AUTOSUSPEND_DELAY_MS	5000 | 
 |  | 
 | enum chip_ids { | 
 | 	yas530, | 
 | 	yas532, | 
 | 	yas533, | 
 | 	yas537, | 
 | }; | 
 |  | 
 | static const int yas530_volatile_reg[] = { | 
 | 	YAS530_ACTUATE_INIT_COIL, | 
 | 	YAS530_MEASURE, | 
 | }; | 
 |  | 
 | static const int yas537_volatile_reg[] = { | 
 | 	YAS537_MEASURE, | 
 | }; | 
 |  | 
 | struct yas5xx_calibration { | 
 | 	/* Linearization calibration x, y1, y2 */ | 
 | 	s32 r[3]; | 
 | 	u32 f[3]; | 
 | 	/* Temperature compensation calibration */ | 
 | 	s16 Cx, Cy1, Cy2; | 
 | 	/* Misc calibration coefficients */ | 
 | 	s8  a2, a3, a4, a6, a7, a8; | 
 | 	s16 a5, a9; | 
 | 	u8  k; | 
 | 	/* clock divider */ | 
 | 	u8 dck; | 
 | }; | 
 |  | 
 | struct yas5xx; | 
 |  | 
 | /** | 
 |  * struct yas5xx_chip_info - device-specific data and function pointers | 
 |  * @devid: device ID number | 
 |  * @product_name: product name of the YAS variant | 
 |  * @version_names: version letters or namings | 
 |  * @volatile_reg: device-specific volatile registers | 
 |  * @volatile_reg_qty: quantity of device-specific volatile registers | 
 |  * @scaling_val2: scaling value for IIO_CHAN_INFO_SCALE | 
 |  * @t_ref: number of counts at reference temperature 20 °C | 
 |  * @min_temp_x10: starting point of temperature counting in 1/10:s degrees Celsius | 
 |  * @get_measure: function pointer to get a measurement | 
 |  * @get_calibration_data: function pointer to get calibration data | 
 |  * @dump_calibration: function pointer to dump calibration for debugging | 
 |  * @measure_offsets: function pointer to measure the offsets | 
 |  * @power_on: function pointer to power-on procedure | 
 |  * | 
 |  * The "t_ref" value for YAS532/533 is known from the Android driver. | 
 |  * For YAS530 and YAS537 it was approximately measured. | 
 |  * | 
 |  * The temperatures "min_temp_x10" are derived from the temperature resolutions | 
 |  * given in the data sheets. | 
 |  */ | 
 | struct yas5xx_chip_info { | 
 | 	unsigned int devid; | 
 | 	const char *product_name; | 
 | 	const char *version_names[2]; | 
 | 	const int *volatile_reg; | 
 | 	int volatile_reg_qty; | 
 | 	u32 scaling_val2; | 
 | 	u16 t_ref; | 
 | 	s16 min_temp_x10; | 
 | 	int (*get_measure)(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo); | 
 | 	int (*get_calibration_data)(struct yas5xx *yas5xx); | 
 | 	void (*dump_calibration)(struct yas5xx *yas5xx); | 
 | 	int (*measure_offsets)(struct yas5xx *yas5xx); | 
 | 	int (*power_on)(struct yas5xx *yas5xx); | 
 | }; | 
 |  | 
 | /** | 
 |  * struct yas5xx - state container for the YAS5xx driver | 
 |  * @dev: parent device pointer | 
 |  * @chip_info: device-specific data and function pointers | 
 |  * @version: device version | 
 |  * @calibration: calibration settings from the OTP storage | 
 |  * @hard_offsets: offsets for each axis measured with initcoil actuated | 
 |  * @orientation: mounting matrix, flipped axis etc | 
 |  * @map: regmap to access the YAX5xx registers over I2C | 
 |  * @regs: the vdd and vddio power regulators | 
 |  * @reset: optional GPIO line used for handling RESET | 
 |  * @lock: locks the magnetometer for exclusive use during a measurement (which | 
 |  * involves several register transactions so the regmap lock is not enough) | 
 |  * so that measurements get serialized in a first-come-first serve manner | 
 |  * @scan: naturally aligned measurements | 
 |  */ | 
 | struct yas5xx { | 
 | 	struct device *dev; | 
 | 	const struct yas5xx_chip_info *chip_info; | 
 | 	unsigned int version; | 
 | 	struct yas5xx_calibration calibration; | 
 | 	s8 hard_offsets[3]; | 
 | 	struct iio_mount_matrix orientation; | 
 | 	struct regmap *map; | 
 | 	struct regulator_bulk_data regs[2]; | 
 | 	struct gpio_desc *reset; | 
 | 	struct mutex lock; | 
 | 	/* | 
 | 	 * The scanout is 4 x 32 bits in CPU endianness. | 
 | 	 * Ensure timestamp is naturally aligned | 
 | 	 */ | 
 | 	struct { | 
 | 		s32 channels[4]; | 
 | 		s64 ts __aligned(8); | 
 | 	} scan; | 
 | }; | 
 |  | 
 | /* On YAS530 the x, y1 and y2 values are 12 bits */ | 
 | static u16 yas530_extract_axis(u8 *data) | 
 | { | 
 | 	u16 val; | 
 |  | 
 | 	/* | 
 | 	 * These are the bits used in a 16bit word: | 
 | 	 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0 | 
 | 	 *    x  x  x  x  x  x  x  x  x  x  x  x | 
 | 	 */ | 
 | 	val = get_unaligned_be16(&data[0]); | 
 | 	val = FIELD_GET(GENMASK(14, 3), val); | 
 | 	return val; | 
 | } | 
 |  | 
 | /* On YAS532 the x, y1 and y2 values are 13 bits */ | 
 | static u16 yas532_extract_axis(u8 *data) | 
 | { | 
 | 	u16 val; | 
 |  | 
 | 	/* | 
 | 	 * These are the bits used in a 16bit word: | 
 | 	 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0 | 
 | 	 *    x  x  x  x  x  x  x  x  x  x  x  x  x | 
 | 	 */ | 
 | 	val = get_unaligned_be16(&data[0]); | 
 | 	val = FIELD_GET(GENMASK(14, 2), val); | 
 | 	return val; | 
 | } | 
 |  | 
 | /** | 
 |  * yas530_measure() - Make a measure from the hardware | 
 |  * @yas5xx: The device state | 
 |  * @t: the raw temperature measurement | 
 |  * @x: the raw x axis measurement | 
 |  * @y1: the y1 axis measurement | 
 |  * @y2: the y2 axis measurement | 
 |  * @return: 0 on success or error code | 
 |  * | 
 |  * Used by YAS530, YAS532 and YAS533. | 
 |  */ | 
 | static int yas530_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2) | 
 | { | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	unsigned int busy; | 
 | 	u8 data[8]; | 
 | 	int ret; | 
 | 	u16 val; | 
 |  | 
 | 	mutex_lock(&yas5xx->lock); | 
 | 	ret = regmap_write(yas5xx->map, YAS530_MEASURE, YAS5XX_MEASURE_START); | 
 | 	if (ret < 0) | 
 | 		goto out_unlock; | 
 |  | 
 | 	/* | 
 | 	 * Typical time to measure 1500 us, max 2000 us so wait min 500 us | 
 | 	 * and at most 20000 us (one magnitude more than the datsheet max) | 
 | 	 * before timeout. | 
 | 	 */ | 
 | 	ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA, busy, | 
 | 				       !(busy & YAS5XX_MEASURE_DATA_BUSY), | 
 | 				       500, 20000); | 
 | 	if (ret) { | 
 | 		dev_err(yas5xx->dev, "timeout waiting for measurement\n"); | 
 | 		goto out_unlock; | 
 | 	} | 
 |  | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA, | 
 | 			       data, sizeof(data)); | 
 | 	if (ret) | 
 | 		goto out_unlock; | 
 |  | 
 | 	mutex_unlock(&yas5xx->lock); | 
 |  | 
 | 	switch (ci->devid) { | 
 | 	case YAS530_DEVICE_ID: | 
 | 		/* | 
 | 		 * The t value is 9 bits in big endian format | 
 | 		 * These are the bits used in a 16bit word: | 
 | 		 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0 | 
 | 		 *    x  x  x  x  x  x  x  x  x | 
 | 		 */ | 
 | 		val = get_unaligned_be16(&data[0]); | 
 | 		val = FIELD_GET(GENMASK(14, 6), val); | 
 | 		*t = val; | 
 | 		*x = yas530_extract_axis(&data[2]); | 
 | 		*y1 = yas530_extract_axis(&data[4]); | 
 | 		*y2 = yas530_extract_axis(&data[6]); | 
 | 		break; | 
 | 	case YAS532_DEVICE_ID: | 
 | 		/* | 
 | 		 * The t value is 10 bits in big endian format | 
 | 		 * These are the bits used in a 16bit word: | 
 | 		 * 15 14 13 12 11 10 9  8  7  6  5  4  3  2  1  0 | 
 | 		 *    x  x  x  x  x  x  x  x  x  x | 
 | 		 */ | 
 | 		val = get_unaligned_be16(&data[0]); | 
 | 		val = FIELD_GET(GENMASK(14, 5), val); | 
 | 		*t = val; | 
 | 		*x = yas532_extract_axis(&data[2]); | 
 | 		*y1 = yas532_extract_axis(&data[4]); | 
 | 		*y2 = yas532_extract_axis(&data[6]); | 
 | 		break; | 
 | 	default: | 
 | 		dev_err(yas5xx->dev, "unknown data format\n"); | 
 | 		ret = -EINVAL; | 
 | 		break; | 
 | 	} | 
 |  | 
 | 	return ret; | 
 |  | 
 | out_unlock: | 
 | 	mutex_unlock(&yas5xx->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | /** | 
 |  * yas537_measure() - Make a measure from the hardware | 
 |  * @yas5xx: The device state | 
 |  * @t: the raw temperature measurement | 
 |  * @x: the raw x axis measurement | 
 |  * @y1: the y1 axis measurement | 
 |  * @y2: the y2 axis measurement | 
 |  * @return: 0 on success or error code | 
 |  */ | 
 | static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y2) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	unsigned int busy; | 
 | 	u8 data[8]; | 
 | 	u16 xy1y2[3]; | 
 | 	s32 h[3], s[3]; | 
 | 	int i, ret; | 
 |  | 
 | 	mutex_lock(&yas5xx->lock); | 
 |  | 
 | 	/* Contrary to YAS530/532, also a "cont" bit is set, meaning unknown */ | 
 | 	ret = regmap_write(yas5xx->map, YAS537_MEASURE, YAS5XX_MEASURE_START | | 
 | 			   YAS5XX_MEASURE_CONT); | 
 | 	if (ret < 0) | 
 | 		goto out_unlock; | 
 |  | 
 | 	/* Use same timeout like YAS530/532 but the bit is in data row 2 */ | 
 | 	ret = regmap_read_poll_timeout(yas5xx->map, YAS5XX_MEASURE_DATA + 2, busy, | 
 | 				       !(busy & YAS5XX_MEASURE_DATA_BUSY), | 
 | 				       500, 20000); | 
 | 	if (ret) { | 
 | 		dev_err(yas5xx->dev, "timeout waiting for measurement\n"); | 
 | 		goto out_unlock; | 
 | 	} | 
 |  | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS5XX_MEASURE_DATA, | 
 | 			       data, sizeof(data)); | 
 | 	if (ret) | 
 | 		goto out_unlock; | 
 |  | 
 | 	mutex_unlock(&yas5xx->lock); | 
 |  | 
 | 	*t = get_unaligned_be16(&data[0]); | 
 | 	xy1y2[0] = FIELD_GET(GENMASK(13, 0), get_unaligned_be16(&data[2])); | 
 | 	xy1y2[1] = get_unaligned_be16(&data[4]); | 
 | 	xy1y2[2] = get_unaligned_be16(&data[6]); | 
 |  | 
 | 	/* The second version of YAS537 needs to include calibration coefficients */ | 
 | 	if (yas5xx->version == YAS537_VERSION_1) { | 
 | 		for (i = 0; i < 3; i++) | 
 | 			s[i] = xy1y2[i] - BIT(13); | 
 | 		h[0] = (c->k *   (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / BIT(13); | 
 | 		h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / BIT(13); | 
 | 		h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / BIT(13); | 
 | 		for (i = 0; i < 3; i++) { | 
 | 			clamp_val(h[i], -BIT(13), BIT(13) - 1); | 
 | 			xy1y2[i] = h[i] + BIT(13); | 
 | 		} | 
 | 	} | 
 |  | 
 | 	*x = xy1y2[0]; | 
 | 	*y1 = xy1y2[1]; | 
 | 	*y2 = xy1y2[2]; | 
 |  | 
 | 	return 0; | 
 |  | 
 | out_unlock: | 
 | 	mutex_unlock(&yas5xx->lock); | 
 | 	return ret; | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static s32 yas530_linearize(struct yas5xx *yas5xx, u16 val, int axis) | 
 | { | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	static const s32 yas532ac_coef[] = { | 
 | 		YAS532_VERSION_AC_COEF_X, | 
 | 		YAS532_VERSION_AC_COEF_Y1, | 
 | 		YAS532_VERSION_AC_COEF_Y2, | 
 | 	}; | 
 | 	s32 coef; | 
 |  | 
 | 	/* Select coefficients */ | 
 | 	switch (ci->devid) { | 
 | 	case YAS530_DEVICE_ID: | 
 | 		if (yas5xx->version == YAS530_VERSION_A) | 
 | 			coef = YAS530_VERSION_A_COEF; | 
 | 		else | 
 | 			coef = YAS530_VERSION_B_COEF; | 
 | 		break; | 
 | 	case YAS532_DEVICE_ID: | 
 | 		if (yas5xx->version == YAS532_VERSION_AB) | 
 | 			coef = YAS532_VERSION_AB_COEF; | 
 | 		else | 
 | 			/* Elaborate coefficients */ | 
 | 			coef = yas532ac_coef[axis]; | 
 | 		break; | 
 | 	default: | 
 | 		dev_err(yas5xx->dev, "unknown device type\n"); | 
 | 		return val; | 
 | 	} | 
 | 	/* | 
 | 	 * Linearization formula: | 
 | 	 * | 
 | 	 * x' = x - (3721 + 50 * f) + (xoffset - r) * c | 
 | 	 * | 
 | 	 * Where f and r are calibration values, c is a per-device | 
 | 	 * and sometimes per-axis coefficient. | 
 | 	 */ | 
 | 	return val - (3721 + 50 * c->f[axis]) + | 
 | 		(yas5xx->hard_offsets[axis] - c->r[axis]) * coef; | 
 | } | 
 |  | 
 | static s32 yas5xx_calc_temperature(struct yas5xx *yas5xx, u16 t) | 
 | { | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	s32 to; | 
 | 	u16 t_ref; | 
 | 	s16 min_temp_x10; | 
 | 	int ref_temp_x10; | 
 |  | 
 | 	t_ref = ci->t_ref; | 
 | 	min_temp_x10 = ci->min_temp_x10; | 
 | 	ref_temp_x10 = 200; | 
 |  | 
 | 	to = (min_temp_x10 + ((ref_temp_x10 - min_temp_x10) * t / t_ref)) * 100; | 
 | 	return to; | 
 | } | 
 |  | 
 | /** | 
 |  * yas530_get_measure() - Measure a sample of all axis and process | 
 |  * @yas5xx: The device state | 
 |  * @to: Temperature out | 
 |  * @xo: X axis out | 
 |  * @yo: Y axis out | 
 |  * @zo: Z axis out | 
 |  * @return: 0 on success or error code | 
 |  * | 
 |  * Used by YAS530, YAS532 and YAS533. | 
 |  */ | 
 | static int yas530_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo) | 
 | { | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	u16 t_ref, t_comp, t, x, y1, y2; | 
 | 	/* These are signed x, signed y1 etc */ | 
 | 	s32 sx, sy1, sy2, sy, sz; | 
 | 	int ret; | 
 |  | 
 | 	/* We first get raw data that needs to be translated to [x,y,z] */ | 
 | 	ret = yas530_measure(yas5xx, &t, &x, &y1, &y2); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Do some linearization if available */ | 
 | 	sx = yas530_linearize(yas5xx, x, 0); | 
 | 	sy1 = yas530_linearize(yas5xx, y1, 1); | 
 | 	sy2 = yas530_linearize(yas5xx, y2, 2); | 
 |  | 
 | 	/* | 
 | 	 * Set the temperature for compensation (unit: counts): | 
 | 	 * YAS532/YAS533 version AC uses the temperature deviation as a | 
 | 	 * multiplier. YAS530 and YAS532 version AB use solely the t value. | 
 | 	 */ | 
 | 	t_ref = ci->t_ref; | 
 | 	if (ci->devid == YAS532_DEVICE_ID && | 
 | 	    yas5xx->version == YAS532_VERSION_AC) { | 
 | 		t_comp = t - t_ref; | 
 | 	} else { | 
 | 		t_comp = t; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * Temperature compensation for x, y1, y2 respectively: | 
 | 	 * | 
 | 	 *          Cx * t_comp | 
 | 	 * x' = x - ----------- | 
 | 	 *              100 | 
 | 	 */ | 
 | 	sx = sx - (c->Cx * t_comp) / 100; | 
 | 	sy1 = sy1 - (c->Cy1 * t_comp) / 100; | 
 | 	sy2 = sy2 - (c->Cy2 * t_comp) / 100; | 
 |  | 
 | 	/* | 
 | 	 * Break y1 and y2 into y and z, y1 and y2 are apparently encoding | 
 | 	 * y and z. | 
 | 	 */ | 
 | 	sy = sy1 - sy2; | 
 | 	sz = -sy1 - sy2; | 
 |  | 
 | 	/* Calculate temperature readout */ | 
 | 	*to = yas5xx_calc_temperature(yas5xx, t); | 
 |  | 
 | 	/* | 
 | 	 * Calibrate [x,y,z] with some formulas like this: | 
 | 	 * | 
 | 	 *            100 * x + a_2 * y + a_3 * z | 
 | 	 *  x' = k *  --------------------------- | 
 | 	 *                        10 | 
 | 	 * | 
 | 	 *           a_4 * x + a_5 * y + a_6 * z | 
 | 	 *  y' = k * --------------------------- | 
 | 	 *                        10 | 
 | 	 * | 
 | 	 *           a_7 * x + a_8 * y + a_9 * z | 
 | 	 *  z' = k * --------------------------- | 
 | 	 *                        10 | 
 | 	 */ | 
 | 	*xo = c->k * ((100 * sx + c->a2 * sy + c->a3 * sz) / 10); | 
 | 	*yo = c->k * ((c->a4 * sx + c->a5 * sy + c->a6 * sz) / 10); | 
 | 	*zo = c->k * ((c->a7 * sx + c->a8 * sy + c->a9 * sz) / 10); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | /** | 
 |  * yas537_get_measure() - Measure a sample of all axis and process | 
 |  * @yas5xx: The device state | 
 |  * @to: Temperature out | 
 |  * @xo: X axis out | 
 |  * @yo: Y axis out | 
 |  * @zo: Z axis out | 
 |  * @return: 0 on success or error code | 
 |  */ | 
 | static int yas537_get_measure(struct yas5xx *yas5xx, s32 *to, s32 *xo, s32 *yo, s32 *zo) | 
 | { | 
 | 	u16 t, x, y1, y2; | 
 | 	int ret; | 
 |  | 
 | 	/* We first get raw data that needs to be translated to [x,y,z] */ | 
 | 	ret = yas537_measure(yas5xx, &t, &x, &y1, &y2); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Calculate temperature readout */ | 
 | 	*to = yas5xx_calc_temperature(yas5xx, t); | 
 |  | 
 | 	/* | 
 | 	 * Unfortunately, no linearization or temperature compensation formulas | 
 | 	 * are known for YAS537. | 
 | 	 */ | 
 |  | 
 | 	/* Calculate x, y, z from x, y1, y2 */ | 
 | 	*xo = (x - BIT(13)) * 300; | 
 | 	*yo = (y1 - y2) * 1732 / 10; | 
 | 	*zo = (-y1 - y2 + BIT(14)) * 300; | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int yas5xx_read_raw(struct iio_dev *indio_dev, | 
 | 			   struct iio_chan_spec const *chan, | 
 | 			   int *val, int *val2, | 
 | 			   long mask) | 
 | { | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	s32 t, x, y, z; | 
 | 	int ret; | 
 |  | 
 | 	switch (mask) { | 
 | 	case IIO_CHAN_INFO_PROCESSED: | 
 | 	case IIO_CHAN_INFO_RAW: | 
 | 		pm_runtime_get_sync(yas5xx->dev); | 
 | 		ret = ci->get_measure(yas5xx, &t, &x, &y, &z); | 
 | 		pm_runtime_mark_last_busy(yas5xx->dev); | 
 | 		pm_runtime_put_autosuspend(yas5xx->dev); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		switch (chan->address) { | 
 | 		case 0: | 
 | 			*val = t; | 
 | 			break; | 
 | 		case 1: | 
 | 			*val = x; | 
 | 			break; | 
 | 		case 2: | 
 | 			*val = y; | 
 | 			break; | 
 | 		case 3: | 
 | 			*val = z; | 
 | 			break; | 
 | 		default: | 
 | 			dev_err(yas5xx->dev, "unknown channel\n"); | 
 | 			return -EINVAL; | 
 | 		} | 
 | 		return IIO_VAL_INT; | 
 | 	case IIO_CHAN_INFO_SCALE: | 
 | 		*val = 1; | 
 | 		*val2 = ci->scaling_val2; | 
 | 		return IIO_VAL_FRACTIONAL; | 
 | 	default: | 
 | 		/* Unknown request */ | 
 | 		return -EINVAL; | 
 | 	} | 
 | } | 
 |  | 
 | static void yas5xx_fill_buffer(struct iio_dev *indio_dev) | 
 | { | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	s32 t, x, y, z; | 
 | 	int ret; | 
 |  | 
 | 	pm_runtime_get_sync(yas5xx->dev); | 
 | 	ret = ci->get_measure(yas5xx, &t, &x, &y, &z); | 
 | 	pm_runtime_mark_last_busy(yas5xx->dev); | 
 | 	pm_runtime_put_autosuspend(yas5xx->dev); | 
 | 	if (ret) { | 
 | 		dev_err(yas5xx->dev, "error refilling buffer\n"); | 
 | 		return; | 
 | 	} | 
 | 	yas5xx->scan.channels[0] = t; | 
 | 	yas5xx->scan.channels[1] = x; | 
 | 	yas5xx->scan.channels[2] = y; | 
 | 	yas5xx->scan.channels[3] = z; | 
 | 	iio_push_to_buffers_with_timestamp(indio_dev, &yas5xx->scan, | 
 | 					   iio_get_time_ns(indio_dev)); | 
 | } | 
 |  | 
 | static irqreturn_t yas5xx_handle_trigger(int irq, void *p) | 
 | { | 
 | 	const struct iio_poll_func *pf = p; | 
 | 	struct iio_dev *indio_dev = pf->indio_dev; | 
 |  | 
 | 	yas5xx_fill_buffer(indio_dev); | 
 | 	iio_trigger_notify_done(indio_dev->trig); | 
 |  | 
 | 	return IRQ_HANDLED; | 
 | } | 
 |  | 
 |  | 
 | static const struct iio_mount_matrix * | 
 | yas5xx_get_mount_matrix(const struct iio_dev *indio_dev, | 
 | 			const struct iio_chan_spec *chan) | 
 | { | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 |  | 
 | 	return &yas5xx->orientation; | 
 | } | 
 |  | 
 | static const struct iio_chan_spec_ext_info yas5xx_ext_info[] = { | 
 | 	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, yas5xx_get_mount_matrix), | 
 | 	{ } | 
 | }; | 
 |  | 
 | #define YAS5XX_AXIS_CHANNEL(axis, index)				\ | 
 | 	{								\ | 
 | 		.type = IIO_MAGN,					\ | 
 | 		.modified = 1,						\ | 
 | 		.channel2 = IIO_MOD_##axis,				\ | 
 | 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\ | 
 | 			BIT(IIO_CHAN_INFO_SCALE),			\ | 
 | 		.ext_info = yas5xx_ext_info,				\ | 
 | 		.address = index,					\ | 
 | 		.scan_index = index,					\ | 
 | 		.scan_type = {						\ | 
 | 			.sign = 's',					\ | 
 | 			.realbits = 32,					\ | 
 | 			.storagebits = 32,				\ | 
 | 			.endianness = IIO_CPU,				\ | 
 | 		},							\ | 
 | 	} | 
 |  | 
 | static const struct iio_chan_spec yas5xx_channels[] = { | 
 | 	{ | 
 | 		.type = IIO_TEMP, | 
 | 		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), | 
 | 		.address = 0, | 
 | 		.scan_index = 0, | 
 | 		.scan_type = { | 
 | 			.sign = 's', | 
 | 			.realbits = 32, | 
 | 			.storagebits = 32, | 
 | 			.endianness = IIO_CPU, | 
 | 		}, | 
 | 	}, | 
 | 	YAS5XX_AXIS_CHANNEL(X, 1), | 
 | 	YAS5XX_AXIS_CHANNEL(Y, 2), | 
 | 	YAS5XX_AXIS_CHANNEL(Z, 3), | 
 | 	IIO_CHAN_SOFT_TIMESTAMP(4), | 
 | }; | 
 |  | 
 | static const unsigned long yas5xx_scan_masks[] = { GENMASK(3, 0), 0 }; | 
 |  | 
 | static const struct iio_info yas5xx_info = { | 
 | 	.read_raw = &yas5xx_read_raw, | 
 | }; | 
 |  | 
 | static bool yas5xx_volatile_reg(struct device *dev, unsigned int reg) | 
 | { | 
 | 	struct iio_dev *indio_dev = dev_get_drvdata(dev); | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	int reg_qty; | 
 | 	int i; | 
 |  | 
 | 	if (reg >= YAS5XX_MEASURE_DATA && reg < YAS5XX_MEASURE_DATA + 8) | 
 | 		return true; | 
 |  | 
 | 	/* | 
 | 	 * YAS versions share different registers on the same address, | 
 | 	 * need to differentiate. | 
 | 	 */ | 
 | 	reg_qty = ci->volatile_reg_qty; | 
 | 	for (i = 0; i < reg_qty; i++) { | 
 | 		if (reg == ci->volatile_reg[i]) | 
 | 			return true; | 
 | 	} | 
 |  | 
 | 	return false; | 
 | } | 
 |  | 
 | /* TODO: enable regmap cache, using mark dirty and sync at runtime resume */ | 
 | static const struct regmap_config yas5xx_regmap_config = { | 
 | 	.reg_bits = 8, | 
 | 	.val_bits = 8, | 
 | 	.max_register = 0xff, | 
 | 	.volatile_reg = yas5xx_volatile_reg, | 
 | }; | 
 |  | 
 | /** | 
 |  * yas530_extract_calibration() - extracts the a2-a9 and k calibration | 
 |  * @data: the bitfield to use | 
 |  * @c: the calibration to populate | 
 |  * | 
 |  * Used by YAS530, YAS532 and YAS533. | 
 |  */ | 
 | static void yas530_extract_calibration(u8 *data, struct yas5xx_calibration *c) | 
 | { | 
 | 	u64 val = get_unaligned_be64(data); | 
 |  | 
 | 	/* | 
 | 	 * Bitfield layout for the axis calibration data, for factor | 
 | 	 * a2 = 2 etc, k = k, c = clock divider | 
 | 	 * | 
 | 	 * n   7 6 5 4 3 2 1 0 | 
 | 	 * 0 [ 2 2 2 2 2 2 3 3 ] bits 63 .. 56 | 
 | 	 * 1 [ 3 3 4 4 4 4 4 4 ] bits 55 .. 48 | 
 | 	 * 2 [ 5 5 5 5 5 5 6 6 ] bits 47 .. 40 | 
 | 	 * 3 [ 6 6 6 6 7 7 7 7 ] bits 39 .. 32 | 
 | 	 * 4 [ 7 7 7 8 8 8 8 8 ] bits 31 .. 24 | 
 | 	 * 5 [ 8 9 9 9 9 9 9 9 ] bits 23 .. 16 | 
 | 	 * 6 [ 9 k k k k k c c ] bits 15 .. 8 | 
 | 	 * 7 [ c x x x x x x x ] bits  7 .. 0 | 
 | 	 */ | 
 | 	c->a2 = FIELD_GET(GENMASK_ULL(63, 58), val) - 32; | 
 | 	c->a3 = FIELD_GET(GENMASK_ULL(57, 54), val) - 8; | 
 | 	c->a4 = FIELD_GET(GENMASK_ULL(53, 48), val) - 32; | 
 | 	c->a5 = FIELD_GET(GENMASK_ULL(47, 42), val) + 38; | 
 | 	c->a6 = FIELD_GET(GENMASK_ULL(41, 36), val) - 32; | 
 | 	c->a7 = FIELD_GET(GENMASK_ULL(35, 29), val) - 64; | 
 | 	c->a8 = FIELD_GET(GENMASK_ULL(28, 23), val) - 32; | 
 | 	c->a9 = FIELD_GET(GENMASK_ULL(22, 15), val); | 
 | 	c->k = FIELD_GET(GENMASK_ULL(14, 10), val) + 10; | 
 | 	c->dck = FIELD_GET(GENMASK_ULL(9, 7), val); | 
 | } | 
 |  | 
 | static int yas530_get_calibration_data(struct yas5xx *yas5xx) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	u8 data[16]; | 
 | 	u32 val; | 
 | 	int ret; | 
 |  | 
 | 	/* Dummy read, first read is ALWAYS wrong */ | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data)); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Actual calibration readout */ | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data)); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	dev_dbg(yas5xx->dev, "calibration data: %16ph\n", data); | 
 |  | 
 | 	/* Contribute calibration data to the input pool for kernel entropy */ | 
 | 	add_device_randomness(data, sizeof(data)); | 
 |  | 
 | 	/* Extract version */ | 
 | 	yas5xx->version = data[15] & GENMASK(1, 0); | 
 |  | 
 | 	/* Extract the calibration from the bitfield */ | 
 | 	c->Cx = data[0] * 6 - 768; | 
 | 	c->Cy1 = data[1] * 6 - 768; | 
 | 	c->Cy2 = data[2] * 6 - 768; | 
 | 	yas530_extract_calibration(&data[3], c); | 
 |  | 
 | 	/* | 
 | 	 * Extract linearization: | 
 | 	 * Linearization layout in the 32 bits at byte 11: | 
 | 	 * The r factors are 6 bit values where bit 5 is the sign | 
 | 	 * | 
 | 	 * n    7  6  5  4  3  2  1  0 | 
 | 	 * 0 [ xx xx xx r0 r0 r0 r0 r0 ] bits 31 .. 24 | 
 | 	 * 1 [ r0 f0 f0 r1 r1 r1 r1 r1 ] bits 23 .. 16 | 
 | 	 * 2 [ r1 f1 f1 r2 r2 r2 r2 r2 ] bits 15 .. 8 | 
 | 	 * 3 [ r2 f2 f2 xx xx xx xx xx ] bits  7 .. 0 | 
 | 	 */ | 
 | 	val = get_unaligned_be32(&data[11]); | 
 | 	c->f[0] = FIELD_GET(GENMASK(22, 21), val); | 
 | 	c->f[1] = FIELD_GET(GENMASK(14, 13), val); | 
 | 	c->f[2] = FIELD_GET(GENMASK(6, 5), val); | 
 | 	c->r[0] = sign_extend32(FIELD_GET(GENMASK(28, 23), val), 5); | 
 | 	c->r[1] = sign_extend32(FIELD_GET(GENMASK(20, 15), val), 5); | 
 | 	c->r[2] = sign_extend32(FIELD_GET(GENMASK(12, 7), val), 5); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int yas532_get_calibration_data(struct yas5xx *yas5xx) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	u8 data[14]; | 
 | 	u32 val; | 
 | 	int ret; | 
 |  | 
 | 	/* Dummy read, first read is ALWAYS wrong */ | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data)); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	/* Actual calibration readout */ | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS530_CAL, data, sizeof(data)); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	dev_dbg(yas5xx->dev, "calibration data: %14ph\n", data); | 
 |  | 
 | 	/* Sanity check, is this all zeroes? */ | 
 | 	if (!memchr_inv(data, 0x00, 13) && !(data[13] & BIT(7))) | 
 | 		dev_warn(yas5xx->dev, "calibration is blank!\n"); | 
 |  | 
 | 	/* Contribute calibration data to the input pool for kernel entropy */ | 
 | 	add_device_randomness(data, sizeof(data)); | 
 |  | 
 | 	/* Only one bit of version info reserved here as far as we know */ | 
 | 	yas5xx->version = data[13] & BIT(0); | 
 |  | 
 | 	/* Extract calibration from the bitfield */ | 
 | 	c->Cx = data[0] * 10 - 1280; | 
 | 	c->Cy1 = data[1] * 10 - 1280; | 
 | 	c->Cy2 = data[2] * 10 - 1280; | 
 | 	yas530_extract_calibration(&data[3], c); | 
 |  | 
 | 	/* | 
 | 	 * Extract linearization: | 
 | 	 * Linearization layout in the 32 bits at byte 10: | 
 | 	 * The r factors are 6 bit values where bit 5 is the sign | 
 | 	 * | 
 | 	 * n    7  6  5  4  3  2  1  0 | 
 | 	 * 0 [ xx r0 r0 r0 r0 r0 r0 f0 ] bits 31 .. 24 | 
 | 	 * 1 [ f0 r1 r1 r1 r1 r1 r1 f1 ] bits 23 .. 16 | 
 | 	 * 2 [ f1 r2 r2 r2 r2 r2 r2 f2 ] bits 15 .. 8 | 
 | 	 * 3 [ f2 xx xx xx xx xx xx xx ] bits  7 .. 0 | 
 | 	 */ | 
 | 	val = get_unaligned_be32(&data[10]); | 
 | 	c->f[0] = FIELD_GET(GENMASK(24, 23), val); | 
 | 	c->f[1] = FIELD_GET(GENMASK(16, 15), val); | 
 | 	c->f[2] = FIELD_GET(GENMASK(8, 7), val); | 
 | 	c->r[0] = sign_extend32(FIELD_GET(GENMASK(30, 25), val), 5); | 
 | 	c->r[1] = sign_extend32(FIELD_GET(GENMASK(22, 17), val), 5); | 
 | 	c->r[2] = sign_extend32(FIELD_GET(GENMASK(14, 7), val), 5); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int yas537_get_calibration_data(struct yas5xx *yas5xx) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 | 	u8 data[17]; | 
 | 	u32 val1, val2, val3, val4; | 
 | 	int i, ret; | 
 |  | 
 | 	/* Writing SRST register */ | 
 | 	ret = regmap_write(yas5xx->map, YAS537_SRST, BIT(1)); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Calibration readout, YAS537 needs one readout only */ | 
 | 	ret = regmap_bulk_read(yas5xx->map, YAS537_CAL, data, sizeof(data)); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	dev_dbg(yas5xx->dev, "calibration data: %17ph\n", data); | 
 |  | 
 | 	/* Sanity check, is this all zeroes? */ | 
 | 	if (!memchr_inv(data, 0x00, 16) && !FIELD_GET(GENMASK(5, 0), data[16])) | 
 | 		dev_warn(yas5xx->dev, "calibration is blank!\n"); | 
 |  | 
 | 	/* Contribute calibration data to the input pool for kernel entropy */ | 
 | 	add_device_randomness(data, sizeof(data)); | 
 |  | 
 | 	/* Extract version information */ | 
 | 	yas5xx->version = FIELD_GET(GENMASK(7, 6), data[16]); | 
 |  | 
 | 	/* There are two versions of YAS537 behaving differently */ | 
 | 	switch (yas5xx->version) { | 
 | 	case YAS537_VERSION_0: | 
 | 		/* | 
 | 		 * The first version simply writes data back into registers: | 
 | 		 * | 
 | 		 * data[0]  YAS537_MTC		0x93 | 
 | 		 * data[1]			0x94 | 
 | 		 * data[2]			0x95 | 
 | 		 * data[3]			0x96 | 
 | 		 * data[4]			0x97 | 
 | 		 * data[5]			0x98 | 
 | 		 * data[6]			0x99 | 
 | 		 * data[7]			0x9a | 
 | 		 * data[8]			0x9b | 
 | 		 * data[9]			0x9c | 
 | 		 * data[10]			0x9d | 
 | 		 * data[11] YAS537_OC		0x9e | 
 | 		 * | 
 | 		 * data[12] YAS537_OFFSET_X	0x84 | 
 | 		 * data[13] YAS537_OFFSET_Y1	0x85 | 
 | 		 * data[14] YAS537_OFFSET_Y2	0x86 | 
 | 		 * | 
 | 		 * data[15] YAS537_HCK		0x88 | 
 | 		 * data[16] YAS537_LCK		0x89 | 
 | 		 */ | 
 | 		for (i = 0; i < 12; i++) { | 
 | 			ret = regmap_write(yas5xx->map, YAS537_MTC + i, | 
 | 					   data[i]); | 
 | 			if (ret) | 
 | 				return ret; | 
 | 		} | 
 | 		for (i = 0; i < 3; i++) { | 
 | 			ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i, | 
 | 					   data[i + 12]); | 
 | 			if (ret) | 
 | 				return ret; | 
 | 			yas5xx->hard_offsets[i] = data[i + 12]; | 
 | 		} | 
 | 		for (i = 0; i < 2; i++) { | 
 | 			ret = regmap_write(yas5xx->map, YAS537_HCK + i, | 
 | 					   data[i + 15]); | 
 | 			if (ret) | 
 | 				return ret; | 
 | 		} | 
 | 		break; | 
 | 	case YAS537_VERSION_1: | 
 | 		/* | 
 | 		 * The second version writes some data into registers but also | 
 | 		 * extracts calibration coefficients. | 
 | 		 * | 
 | 		 * Registers being written: | 
 | 		 * | 
 | 		 * data[0]  YAS537_MTC			0x93 | 
 | 		 * data[1]  YAS537_MTC+1		0x94 | 
 | 		 * data[2]  YAS537_MTC+2		0x95 | 
 | 		 * data[3]  YAS537_MTC+3 (partially)	0x96 | 
 | 		 * | 
 | 		 * data[12] YAS537_OFFSET_X		0x84 | 
 | 		 * data[13] YAS537_OFFSET_Y1		0x85 | 
 | 		 * data[14] YAS537_OFFSET_Y2		0x86 | 
 | 		 * | 
 | 		 * data[15] YAS537_HCK (partially)	0x88 | 
 | 		 *          YAS537_LCK (partially)	0x89 | 
 | 		 * data[16] YAS537_OC  (partially)	0x9e | 
 | 		 */ | 
 | 		for (i = 0; i < 3; i++) { | 
 | 			ret = regmap_write(yas5xx->map, YAS537_MTC + i, | 
 | 					   data[i]); | 
 | 			if (ret) | 
 | 				return ret; | 
 | 		} | 
 | 		for (i = 0; i < 3; i++) { | 
 | 			ret = regmap_write(yas5xx->map, YAS537_OFFSET_X + i, | 
 | 					   data[i + 12]); | 
 | 			if (ret) | 
 | 				return ret; | 
 | 			yas5xx->hard_offsets[i] = data[i + 12]; | 
 | 		} | 
 | 		/* | 
 | 		 * Visualization of partially taken data: | 
 | 		 * | 
 | 		 * data[3]       n 7 6 5 4 3 2 1 0 | 
 | 		 * YAS537_MTC+3    x x x 1 0 0 0 0 | 
 | 		 * | 
 | 		 * data[15]      n 7 6 5 4 3 2 1 0 | 
 | 		 * YAS537_HCK      x x x x 0 | 
 | 		 * | 
 | 		 * data[15]      n 7 6 5 4 3 2 1 0 | 
 | 		 * YAS537_LCK              x x x x 0 | 
 | 		 * | 
 | 		 * data[16]      n 7 6 5 4 3 2 1 0 | 
 | 		 * YAS537_OC           x x x x x x | 
 | 		 */ | 
 | 		ret = regmap_write(yas5xx->map, YAS537_MTC + 3, | 
 | 				   FIELD_PREP(YAS537_MTC3_MASK_PREP, | 
 | 				   FIELD_GET(YAS537_MTC3_MASK_GET, data[3])) | | 
 | 				   YAS537_MTC3_ADD_BIT); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		ret = regmap_write(yas5xx->map, YAS537_HCK, | 
 | 				   FIELD_PREP(YAS537_HCK_MASK_PREP, | 
 | 				   FIELD_GET(YAS537_HCK_MASK_GET, data[15]))); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		ret = regmap_write(yas5xx->map, YAS537_LCK, | 
 | 				   FIELD_PREP(YAS537_LCK_MASK_PREP, | 
 | 				   FIELD_GET(YAS537_LCK_MASK_GET, data[15]))); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		ret = regmap_write(yas5xx->map, YAS537_OC, | 
 | 				   FIELD_GET(YAS537_OC_MASK_GET, data[16])); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		/* | 
 | 		 * For data extraction, build some blocks. Four 32-bit blocks | 
 | 		 * look appropriate. | 
 | 		 * | 
 | 		 *            n    7  6  5  4  3  2  1  0 | 
 | 		 *  data[0]   0 [ Cx Cx Cx Cx Cx Cx Cx Cx ] bits 31 .. 24 | 
 | 		 *  data[1]   1 [ Cx C1 C1 C1 C1 C1 C1 C1 ] bits 23 .. 16 | 
 | 		 *  data[2]   2 [ C1 C1 C2 C2 C2 C2 C2 C2 ] bits 15 .. 8 | 
 | 		 *  data[3]   3 [ C2 C2 C2                ] bits  7 .. 0 | 
 | 		 * | 
 | 		 *            n    7  6  5  4  3  2  1  0 | 
 | 		 *  data[3]   0 [          a2 a2 a2 a2 a2 ] bits 31 .. 24 | 
 | 		 *  data[4]   1 [ a2 a2 a3 a3 a3 a3 a3 a3 ] bits 23 .. 16 | 
 | 		 *  data[5]   2 [ a3 a4 a4 a4 a4 a4 a4 a4 ] bits 15 .. 8 | 
 | 		 *  data[6]   3 [ a4                      ] bits  7 .. 0 | 
 | 		 * | 
 | 		 *            n    7  6  5  4  3  2  1  0 | 
 | 		 *  data[6]   0 [    a5 a5 a5 a5 a5 a5 a5 ] bits 31 .. 24 | 
 | 		 *  data[7]   1 [ a5 a5 a6 a6 a6 a6 a6 a6 ] bits 23 .. 16 | 
 | 		 *  data[8]   2 [ a6 a7 a7 a7 a7 a7 a7 a7 ] bits 15 .. 8 | 
 | 		 *  data[9]   3 [ a7                      ] bits  7 .. 0 | 
 | 		 * | 
 | 		 *            n    7  6  5  4  3  2  1  0 | 
 | 		 *  data[9]   0 [    a8 a8 a8 a8 a8 a8 a8 ] bits 31 .. 24 | 
 | 		 *  data[10]  1 [ a9 a9 a9 a9 a9 a9 a9 a9 ] bits 23 .. 16 | 
 | 		 *  data[11]  2 [ a9  k  k  k  k  k  k  k ] bits 15 .. 8 | 
 | 		 *  data[12]  3 [                         ] bits  7 .. 0 | 
 | 		 */ | 
 | 		val1 = get_unaligned_be32(&data[0]); | 
 | 		val2 = get_unaligned_be32(&data[3]); | 
 | 		val3 = get_unaligned_be32(&data[6]); | 
 | 		val4 = get_unaligned_be32(&data[9]); | 
 | 		/* Extract calibration coefficients and modify */ | 
 | 		c->Cx  = FIELD_GET(GENMASK(31, 23), val1) - 256; | 
 | 		c->Cy1 = FIELD_GET(GENMASK(22, 14), val1) - 256; | 
 | 		c->Cy2 = FIELD_GET(GENMASK(13,  5), val1) - 256; | 
 | 		c->a2  = FIELD_GET(GENMASK(28, 22), val2) -  64; | 
 | 		c->a3  = FIELD_GET(GENMASK(21, 15), val2) -  64; | 
 | 		c->a4  = FIELD_GET(GENMASK(14,  7), val2) - 128; | 
 | 		c->a5  = FIELD_GET(GENMASK(30, 22), val3) - 112; | 
 | 		c->a6  = FIELD_GET(GENMASK(21, 15), val3) -  64; | 
 | 		c->a7  = FIELD_GET(GENMASK(14,  7), val3) - 128; | 
 | 		c->a8  = FIELD_GET(GENMASK(30, 24), val4) -  64; | 
 | 		c->a9  = FIELD_GET(GENMASK(23, 15), val4) - 112; | 
 | 		c->k   = FIELD_GET(GENMASK(14,  8), val4); | 
 | 		break; | 
 | 	default: | 
 | 		dev_err(yas5xx->dev, "unknown version of YAS537\n"); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static void yas530_dump_calibration(struct yas5xx *yas5xx) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 |  | 
 | 	dev_dbg(yas5xx->dev, "f[] = [%d, %d, %d]\n", | 
 | 		c->f[0], c->f[1], c->f[2]); | 
 | 	dev_dbg(yas5xx->dev, "r[] = [%d, %d, %d]\n", | 
 | 		c->r[0], c->r[1], c->r[2]); | 
 | 	dev_dbg(yas5xx->dev, "Cx = %d\n", c->Cx); | 
 | 	dev_dbg(yas5xx->dev, "Cy1 = %d\n", c->Cy1); | 
 | 	dev_dbg(yas5xx->dev, "Cy2 = %d\n", c->Cy2); | 
 | 	dev_dbg(yas5xx->dev, "a2 = %d\n", c->a2); | 
 | 	dev_dbg(yas5xx->dev, "a3 = %d\n", c->a3); | 
 | 	dev_dbg(yas5xx->dev, "a4 = %d\n", c->a4); | 
 | 	dev_dbg(yas5xx->dev, "a5 = %d\n", c->a5); | 
 | 	dev_dbg(yas5xx->dev, "a6 = %d\n", c->a6); | 
 | 	dev_dbg(yas5xx->dev, "a7 = %d\n", c->a7); | 
 | 	dev_dbg(yas5xx->dev, "a8 = %d\n", c->a8); | 
 | 	dev_dbg(yas5xx->dev, "a9 = %d\n", c->a9); | 
 | 	dev_dbg(yas5xx->dev, "k = %d\n", c->k); | 
 | 	dev_dbg(yas5xx->dev, "dck = %d\n", c->dck); | 
 | } | 
 |  | 
 | static void yas537_dump_calibration(struct yas5xx *yas5xx) | 
 | { | 
 | 	struct yas5xx_calibration *c = &yas5xx->calibration; | 
 |  | 
 | 	if (yas5xx->version == YAS537_VERSION_1) { | 
 | 		dev_dbg(yas5xx->dev, "Cx = %d\n", c->Cx); | 
 | 		dev_dbg(yas5xx->dev, "Cy1 = %d\n", c->Cy1); | 
 | 		dev_dbg(yas5xx->dev, "Cy2 = %d\n", c->Cy2); | 
 | 		dev_dbg(yas5xx->dev, "a2 = %d\n", c->a2); | 
 | 		dev_dbg(yas5xx->dev, "a3 = %d\n", c->a3); | 
 | 		dev_dbg(yas5xx->dev, "a4 = %d\n", c->a4); | 
 | 		dev_dbg(yas5xx->dev, "a5 = %d\n", c->a5); | 
 | 		dev_dbg(yas5xx->dev, "a6 = %d\n", c->a6); | 
 | 		dev_dbg(yas5xx->dev, "a7 = %d\n", c->a7); | 
 | 		dev_dbg(yas5xx->dev, "a8 = %d\n", c->a8); | 
 | 		dev_dbg(yas5xx->dev, "a9 = %d\n", c->a9); | 
 | 		dev_dbg(yas5xx->dev, "k = %d\n", c->k); | 
 | 	} | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static int yas530_set_offsets(struct yas5xx *yas5xx, s8 ox, s8 oy1, s8 oy2) | 
 | { | 
 | 	int ret; | 
 |  | 
 | 	ret = regmap_write(yas5xx->map, YAS530_OFFSET_X, ox); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	ret = regmap_write(yas5xx->map, YAS530_OFFSET_Y1, oy1); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	return regmap_write(yas5xx->map, YAS530_OFFSET_Y2, oy2); | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static s8 yas530_adjust_offset(s8 old, int bit, u16 center, u16 measure) | 
 | { | 
 | 	if (measure > center) | 
 | 		return old + BIT(bit); | 
 | 	if (measure < center) | 
 | 		return old - BIT(bit); | 
 | 	return old; | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static int yas530_measure_offsets(struct yas5xx *yas5xx) | 
 | { | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	int ret; | 
 | 	u16 center; | 
 | 	u16 t, x, y1, y2; | 
 | 	s8 ox, oy1, oy2; | 
 | 	int i; | 
 |  | 
 | 	/* Actuate the init coil and measure offsets */ | 
 | 	ret = regmap_write(yas5xx->map, YAS530_ACTUATE_INIT_COIL, 0); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* When the initcoil is active this should be around the center */ | 
 | 	switch (ci->devid) { | 
 | 	case YAS530_DEVICE_ID: | 
 | 		center = YAS530_DATA_CENTER; | 
 | 		break; | 
 | 	case YAS532_DEVICE_ID: | 
 | 		center = YAS532_DATA_CENTER; | 
 | 		break; | 
 | 	default: | 
 | 		dev_err(yas5xx->dev, "unknown device type\n"); | 
 | 		return -EINVAL; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * We set offsets in the interval +-31 by iterating | 
 | 	 * +-16, +-8, +-4, +-2, +-1 adjusting the offsets each | 
 | 	 * time, then writing the final offsets into the | 
 | 	 * registers. | 
 | 	 * | 
 | 	 * NOTE: these offsets are NOT in the same unit or magnitude | 
 | 	 * as the values for [x, y1, y2]. The value is +/-31 | 
 | 	 * but the effect on the raw values is much larger. | 
 | 	 * The effect of the offset is to bring the measure | 
 | 	 * rougly to the center. | 
 | 	 */ | 
 | 	ox = 0; | 
 | 	oy1 = 0; | 
 | 	oy2 = 0; | 
 |  | 
 | 	for (i = 4; i >= 0; i--) { | 
 | 		ret = yas530_set_offsets(yas5xx, ox, oy1, oy2); | 
 | 		if (ret) | 
 | 			return ret; | 
 |  | 
 | 		ret = yas530_measure(yas5xx, &t, &x, &y1, &y2); | 
 | 		if (ret) | 
 | 			return ret; | 
 | 		dev_dbg(yas5xx->dev, "measurement %d: x=%d, y1=%d, y2=%d\n", | 
 | 			5-i, x, y1, y2); | 
 |  | 
 | 		ox = yas530_adjust_offset(ox, i, center, x); | 
 | 		oy1 = yas530_adjust_offset(oy1, i, center, y1); | 
 | 		oy2 = yas530_adjust_offset(oy2, i, center, y2); | 
 | 	} | 
 |  | 
 | 	/* Needed for calibration algorithm */ | 
 | 	yas5xx->hard_offsets[0] = ox; | 
 | 	yas5xx->hard_offsets[1] = oy1; | 
 | 	yas5xx->hard_offsets[2] = oy2; | 
 | 	ret = yas530_set_offsets(yas5xx, ox, oy1, oy2); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	dev_info(yas5xx->dev, "discovered hard offsets: x=%d, y1=%d, y2=%d\n", | 
 | 		 ox, oy1, oy2); | 
 | 	return 0; | 
 | } | 
 |  | 
 | /* Used by YAS530, YAS532 and YAS533 */ | 
 | static int yas530_power_on(struct yas5xx *yas5xx) | 
 | { | 
 | 	unsigned int val; | 
 | 	int ret; | 
 |  | 
 | 	/* Zero the test registers */ | 
 | 	ret = regmap_write(yas5xx->map, YAS530_TEST1, 0); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	ret = regmap_write(yas5xx->map, YAS530_TEST2, 0); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Set up for no interrupts, calibrated clock divider */ | 
 | 	val = FIELD_PREP(YAS5XX_CONFIG_CCK_MASK, yas5xx->calibration.dck); | 
 | 	ret = regmap_write(yas5xx->map, YAS530_CONFIG, val); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Measure interval 0 (back-to-back?)  */ | 
 | 	return regmap_write(yas5xx->map, YAS530_MEASURE_INTERVAL, 0); | 
 | } | 
 |  | 
 | static int yas537_power_on(struct yas5xx *yas5xx) | 
 | { | 
 | 	__be16 buf; | 
 | 	int ret; | 
 | 	u8 intrvl; | 
 |  | 
 | 	/* Writing ADCCAL and TRM registers */ | 
 | 	buf = cpu_to_be16(GENMASK(9, 3)); | 
 | 	ret = regmap_bulk_write(yas5xx->map, YAS537_ADCCAL, &buf, sizeof(buf)); | 
 | 	if (ret) | 
 | 		return ret; | 
 | 	ret = regmap_write(yas5xx->map, YAS537_TRM, GENMASK(7, 0)); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* The interval value is static in regular operation */ | 
 | 	intrvl = (YAS537_DEFAULT_SENSOR_DELAY_MS * MILLI | 
 | 		 - YAS537_MEASURE_TIME_WORST_US) / 4100; | 
 | 	ret = regmap_write(yas5xx->map, YAS537_MEASURE_INTERVAL, intrvl); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* The average value is also static in regular operation */ | 
 | 	ret = regmap_write(yas5xx->map, YAS537_AVR, YAS537_MAG_AVERAGE_32_MASK); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Perform the "rcoil" part but skip the "last_after_rcoil" read */ | 
 | 	ret = regmap_write(yas5xx->map, YAS537_CONFIG, BIT(3)); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	/* Wait until the coil has ramped up */ | 
 | 	usleep_range(YAS537_MAG_RCOIL_TIME_US, YAS537_MAG_RCOIL_TIME_US + 100); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static const struct yas5xx_chip_info yas5xx_chip_info_tbl[] = { | 
 | 	[yas530] = { | 
 | 		.devid = YAS530_DEVICE_ID, | 
 | 		.product_name = "YAS530 MS-3E", | 
 | 		.version_names = { "A", "B" }, | 
 | 		.volatile_reg = yas530_volatile_reg, | 
 | 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), | 
 | 		.scaling_val2 = 100000000, /* picotesla to Gauss */ | 
 | 		.t_ref = 182, /* counts */ | 
 | 		.min_temp_x10 = -620, /* 1/10:s degrees Celsius */ | 
 | 		.get_measure = yas530_get_measure, | 
 | 		.get_calibration_data = yas530_get_calibration_data, | 
 | 		.dump_calibration = yas530_dump_calibration, | 
 | 		.measure_offsets = yas530_measure_offsets, | 
 | 		.power_on = yas530_power_on, | 
 | 	}, | 
 | 	[yas532] = { | 
 | 		.devid = YAS532_DEVICE_ID, | 
 | 		.product_name = "YAS532 MS-3R", | 
 | 		.version_names = { "AB", "AC" }, | 
 | 		.volatile_reg = yas530_volatile_reg, | 
 | 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), | 
 | 		.scaling_val2 = 100000, /* nanotesla to Gauss */ | 
 | 		.t_ref = 390, /* counts */ | 
 | 		.min_temp_x10 = -500, /* 1/10:s degrees Celsius */ | 
 | 		.get_measure = yas530_get_measure, | 
 | 		.get_calibration_data = yas532_get_calibration_data, | 
 | 		.dump_calibration = yas530_dump_calibration, | 
 | 		.measure_offsets = yas530_measure_offsets, | 
 | 		.power_on = yas530_power_on, | 
 | 	}, | 
 | 	[yas533] = { | 
 | 		.devid = YAS532_DEVICE_ID, | 
 | 		.product_name = "YAS533 MS-3F", | 
 | 		.version_names = { "AB", "AC" }, | 
 | 		.volatile_reg = yas530_volatile_reg, | 
 | 		.volatile_reg_qty = ARRAY_SIZE(yas530_volatile_reg), | 
 | 		.scaling_val2 = 100000, /* nanotesla to Gauss */ | 
 | 		.t_ref = 390, /* counts */ | 
 | 		.min_temp_x10 = -500, /* 1/10:s degrees Celsius */ | 
 | 		.get_measure = yas530_get_measure, | 
 | 		.get_calibration_data = yas532_get_calibration_data, | 
 | 		.dump_calibration = yas530_dump_calibration, | 
 | 		.measure_offsets = yas530_measure_offsets, | 
 | 		.power_on = yas530_power_on, | 
 | 	}, | 
 | 	[yas537] = { | 
 | 		.devid = YAS537_DEVICE_ID, | 
 | 		.product_name = "YAS537 MS-3T", | 
 | 		.version_names = { "v0", "v1" }, /* version naming unknown */ | 
 | 		.volatile_reg = yas537_volatile_reg, | 
 | 		.volatile_reg_qty = ARRAY_SIZE(yas537_volatile_reg), | 
 | 		.scaling_val2 = 100000, /* nanotesla to Gauss */ | 
 | 		.t_ref = 8120, /* counts */ | 
 | 		.min_temp_x10 = -3860, /* 1/10:s degrees Celsius */ | 
 | 		.get_measure = yas537_get_measure, | 
 | 		.get_calibration_data = yas537_get_calibration_data, | 
 | 		.dump_calibration = yas537_dump_calibration, | 
 | 		/* .measure_offets is not needed for yas537 */ | 
 | 		.power_on = yas537_power_on, | 
 | 	}, | 
 | }; | 
 |  | 
 | static int yas5xx_probe(struct i2c_client *i2c) | 
 | { | 
 | 	const struct i2c_device_id *id = i2c_client_get_device_id(i2c); | 
 | 	struct iio_dev *indio_dev; | 
 | 	struct device *dev = &i2c->dev; | 
 | 	struct yas5xx *yas5xx; | 
 | 	const struct yas5xx_chip_info *ci; | 
 | 	int id_check; | 
 | 	int ret; | 
 |  | 
 | 	indio_dev = devm_iio_device_alloc(dev, sizeof(*yas5xx)); | 
 | 	if (!indio_dev) | 
 | 		return -ENOMEM; | 
 |  | 
 | 	yas5xx = iio_priv(indio_dev); | 
 | 	i2c_set_clientdata(i2c, indio_dev); | 
 | 	yas5xx->dev = dev; | 
 | 	mutex_init(&yas5xx->lock); | 
 |  | 
 | 	ret = iio_read_mount_matrix(dev, &yas5xx->orientation); | 
 | 	if (ret) | 
 | 		return ret; | 
 |  | 
 | 	yas5xx->regs[0].supply = "vdd"; | 
 | 	yas5xx->regs[1].supply = "iovdd"; | 
 | 	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(yas5xx->regs), | 
 | 				      yas5xx->regs); | 
 | 	if (ret) | 
 | 		return dev_err_probe(dev, ret, "cannot get regulators\n"); | 
 |  | 
 | 	ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 | 	if (ret) | 
 | 		return dev_err_probe(dev, ret, "cannot enable regulators\n"); | 
 |  | 
 | 	/* See comment in runtime resume callback */ | 
 | 	usleep_range(31000, 40000); | 
 |  | 
 | 	/* This will take the device out of reset if need be */ | 
 | 	yas5xx->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); | 
 | 	if (IS_ERR(yas5xx->reset)) { | 
 | 		ret = dev_err_probe(dev, PTR_ERR(yas5xx->reset), "failed to get reset line\n"); | 
 | 		goto reg_off; | 
 | 	} | 
 |  | 
 | 	yas5xx->map = devm_regmap_init_i2c(i2c, &yas5xx_regmap_config); | 
 | 	if (IS_ERR(yas5xx->map)) { | 
 | 		ret = dev_err_probe(dev, PTR_ERR(yas5xx->map), "failed to allocate register map\n"); | 
 | 		goto assert_reset; | 
 | 	} | 
 |  | 
 | 	ci = i2c_get_match_data(i2c); | 
 | 	yas5xx->chip_info = ci; | 
 |  | 
 | 	ret = regmap_read(yas5xx->map, YAS5XX_DEVICE_ID, &id_check); | 
 | 	if (ret) | 
 | 		goto assert_reset; | 
 |  | 
 | 	if (id_check != ci->devid) { | 
 | 		ret = dev_err_probe(dev, -ENODEV, | 
 | 				    "device ID %02x doesn't match %s\n", | 
 | 				    id_check, id->name); | 
 | 		goto assert_reset; | 
 | 	} | 
 |  | 
 | 	ret = ci->get_calibration_data(yas5xx); | 
 | 	if (ret) | 
 | 		goto assert_reset; | 
 |  | 
 | 	dev_info(dev, "detected %s %s\n", ci->product_name, | 
 | 		 ci->version_names[yas5xx->version]); | 
 |  | 
 | 	ci->dump_calibration(yas5xx); | 
 |  | 
 | 	ret = ci->power_on(yas5xx); | 
 | 	if (ret) | 
 | 		goto assert_reset; | 
 |  | 
 | 	if (ci->measure_offsets) { | 
 | 		ret = ci->measure_offsets(yas5xx); | 
 | 		if (ret) | 
 | 			goto assert_reset; | 
 | 	} | 
 |  | 
 | 	indio_dev->info = &yas5xx_info; | 
 | 	indio_dev->available_scan_masks = yas5xx_scan_masks; | 
 | 	indio_dev->modes = INDIO_DIRECT_MODE; | 
 | 	indio_dev->name = id->name; | 
 | 	indio_dev->channels = yas5xx_channels; | 
 | 	indio_dev->num_channels = ARRAY_SIZE(yas5xx_channels); | 
 |  | 
 | 	ret = iio_triggered_buffer_setup(indio_dev, NULL, | 
 | 					 yas5xx_handle_trigger, | 
 | 					 NULL); | 
 | 	if (ret) { | 
 | 		dev_err_probe(dev, ret, "triggered buffer setup failed\n"); | 
 | 		goto assert_reset; | 
 | 	} | 
 |  | 
 | 	ret = iio_device_register(indio_dev); | 
 | 	if (ret) { | 
 | 		dev_err_probe(dev, ret, "device register failed\n"); | 
 | 		goto cleanup_buffer; | 
 | 	} | 
 |  | 
 | 	/* Take runtime PM online */ | 
 | 	pm_runtime_get_noresume(dev); | 
 | 	pm_runtime_set_active(dev); | 
 | 	pm_runtime_enable(dev); | 
 |  | 
 | 	pm_runtime_set_autosuspend_delay(dev, YAS5XX_AUTOSUSPEND_DELAY_MS); | 
 | 	pm_runtime_use_autosuspend(dev); | 
 | 	pm_runtime_put(dev); | 
 |  | 
 | 	return 0; | 
 |  | 
 | cleanup_buffer: | 
 | 	iio_triggered_buffer_cleanup(indio_dev); | 
 | assert_reset: | 
 | 	gpiod_set_value_cansleep(yas5xx->reset, 1); | 
 | reg_off: | 
 | 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | static void yas5xx_remove(struct i2c_client *i2c) | 
 | { | 
 | 	struct iio_dev *indio_dev = i2c_get_clientdata(i2c); | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 | 	struct device *dev = &i2c->dev; | 
 |  | 
 | 	iio_device_unregister(indio_dev); | 
 | 	iio_triggered_buffer_cleanup(indio_dev); | 
 | 	/* | 
 | 	 * Now we can't get any more reads from the device, which would | 
 | 	 * also call pm_runtime* functions and race with our disable | 
 | 	 * code. Disable PM runtime in orderly fashion and power down. | 
 | 	 */ | 
 | 	pm_runtime_get_sync(dev); | 
 | 	pm_runtime_put_noidle(dev); | 
 | 	pm_runtime_disable(dev); | 
 | 	gpiod_set_value_cansleep(yas5xx->reset, 1); | 
 | 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 | } | 
 |  | 
 | static int yas5xx_runtime_suspend(struct device *dev) | 
 | { | 
 | 	struct iio_dev *indio_dev = dev_get_drvdata(dev); | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 |  | 
 | 	gpiod_set_value_cansleep(yas5xx->reset, 1); | 
 | 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 |  | 
 | 	return 0; | 
 | } | 
 |  | 
 | static int yas5xx_runtime_resume(struct device *dev) | 
 | { | 
 | 	struct iio_dev *indio_dev = dev_get_drvdata(dev); | 
 | 	struct yas5xx *yas5xx = iio_priv(indio_dev); | 
 | 	const struct yas5xx_chip_info *ci = yas5xx->chip_info; | 
 | 	int ret; | 
 |  | 
 | 	ret = regulator_bulk_enable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 | 	if (ret) { | 
 | 		dev_err(dev, "cannot enable regulators\n"); | 
 | 		return ret; | 
 | 	} | 
 |  | 
 | 	/* | 
 | 	 * The YAS530 datasheet says TVSKW is up to 30 ms, after that 1 ms | 
 | 	 * for all voltages to settle. The YAS532 is 10ms then 4ms for the | 
 | 	 * I2C to come online. Let's keep it safe and put this at 31ms. | 
 | 	 */ | 
 | 	usleep_range(31000, 40000); | 
 | 	gpiod_set_value_cansleep(yas5xx->reset, 0); | 
 |  | 
 | 	ret = ci->power_on(yas5xx); | 
 | 	if (ret) { | 
 | 		dev_err(dev, "cannot power on\n"); | 
 | 		goto out_reset; | 
 | 	} | 
 |  | 
 | 	return 0; | 
 |  | 
 | out_reset: | 
 | 	gpiod_set_value_cansleep(yas5xx->reset, 1); | 
 | 	regulator_bulk_disable(ARRAY_SIZE(yas5xx->regs), yas5xx->regs); | 
 |  | 
 | 	return ret; | 
 | } | 
 |  | 
 | static DEFINE_RUNTIME_DEV_PM_OPS(yas5xx_dev_pm_ops, yas5xx_runtime_suspend, | 
 | 				 yas5xx_runtime_resume, NULL); | 
 |  | 
 | static const struct i2c_device_id yas5xx_id[] = { | 
 | 	{"yas530", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas530] }, | 
 | 	{"yas532", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas532] }, | 
 | 	{"yas533", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas533] }, | 
 | 	{"yas537", (kernel_ulong_t)&yas5xx_chip_info_tbl[yas537] }, | 
 | 	{} | 
 | }; | 
 | MODULE_DEVICE_TABLE(i2c, yas5xx_id); | 
 |  | 
 | static const struct of_device_id yas5xx_of_match[] = { | 
 | 	{ .compatible = "yamaha,yas530", &yas5xx_chip_info_tbl[yas530] }, | 
 | 	{ .compatible = "yamaha,yas532", &yas5xx_chip_info_tbl[yas532] }, | 
 | 	{ .compatible = "yamaha,yas533", &yas5xx_chip_info_tbl[yas533] }, | 
 | 	{ .compatible = "yamaha,yas537", &yas5xx_chip_info_tbl[yas537] }, | 
 | 	{} | 
 | }; | 
 | MODULE_DEVICE_TABLE(of, yas5xx_of_match); | 
 |  | 
 | static struct i2c_driver yas5xx_driver = { | 
 | 	.driver	 = { | 
 | 		.name	= "yas5xx", | 
 | 		.of_match_table = yas5xx_of_match, | 
 | 		.pm = pm_ptr(&yas5xx_dev_pm_ops), | 
 | 	}, | 
 | 	.probe = yas5xx_probe, | 
 | 	.remove	  = yas5xx_remove, | 
 | 	.id_table = yas5xx_id, | 
 | }; | 
 | module_i2c_driver(yas5xx_driver); | 
 |  | 
 | MODULE_DESCRIPTION("Yamaha YAS53x 3-axis magnetometer driver"); | 
 | MODULE_AUTHOR("Linus Walleij"); | 
 | MODULE_LICENSE("GPL v2"); |