1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2019 TDK-InvenSense, Inc.
4 */
5
6#include <linux/kernel.h>
7#include <linux/device.h>
8#include <linux/string.h>
9
10#include "inv_mpu_aux.h"
11#include "inv_mpu_iio.h"
12#include "inv_mpu_magn.h"
13
14/*
15 * MPU9xxx magnetometer are AKM chips on I2C aux bus
16 * MPU9150 is AK8975
17 * MPU9250 is AK8963
18 */
19#define INV_MPU_MAGN_I2C_ADDR		0x0C
20
21#define INV_MPU_MAGN_REG_WIA		0x00
22#define INV_MPU_MAGN_BITS_WIA		0x48
23
24#define INV_MPU_MAGN_REG_ST1		0x02
25#define INV_MPU_MAGN_BIT_DRDY		0x01
26#define INV_MPU_MAGN_BIT_DOR		0x02
27
28#define INV_MPU_MAGN_REG_DATA		0x03
29
30#define INV_MPU_MAGN_REG_ST2		0x09
31#define INV_MPU_MAGN_BIT_HOFL		0x08
32#define INV_MPU_MAGN_BIT_BITM		0x10
33
34#define INV_MPU_MAGN_REG_CNTL1		0x0A
35#define INV_MPU_MAGN_BITS_MODE_PWDN	0x00
36#define INV_MPU_MAGN_BITS_MODE_SINGLE	0x01
37#define INV_MPU_MAGN_BITS_MODE_FUSE	0x0F
38#define INV_MPU9250_MAGN_BIT_OUTPUT_BIT	0x10
39
40#define INV_MPU9250_MAGN_REG_CNTL2	0x0B
41#define INV_MPU9250_MAGN_BIT_SRST	0x01
42
43#define INV_MPU_MAGN_REG_ASAX		0x10
44#define INV_MPU_MAGN_REG_ASAY		0x11
45#define INV_MPU_MAGN_REG_ASAZ		0x12
46
47static bool inv_magn_supported(const struct inv_mpu6050_state *st)
48{
49	switch (st->chip_type) {
50	case INV_MPU9150:
51	case INV_MPU9250:
52	case INV_MPU9255:
53		return true;
54	default:
55		return false;
56	}
57}
58
59/* init magnetometer chip */
60static int inv_magn_init(struct inv_mpu6050_state *st)
61{
62	uint8_t val;
63	uint8_t asa[3];
64	int32_t sensitivity;
65	int ret;
66
67	/* check whoami */
68	ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_WIA,
69			       &val, sizeof(val));
70	if (ret)
71		return ret;
72	if (val != INV_MPU_MAGN_BITS_WIA)
73		return -ENODEV;
74
75	/* software reset for MPU925x only */
76	switch (st->chip_type) {
77	case INV_MPU9250:
78	case INV_MPU9255:
79		ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
80					INV_MPU9250_MAGN_REG_CNTL2,
81					INV_MPU9250_MAGN_BIT_SRST);
82		if (ret)
83			return ret;
84		break;
85	default:
86		break;
87	}
88
89	/* read fuse ROM data */
90	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
91				INV_MPU_MAGN_REG_CNTL1,
92				INV_MPU_MAGN_BITS_MODE_FUSE);
93	if (ret)
94		return ret;
95
96	ret = inv_mpu_aux_read(st, INV_MPU_MAGN_I2C_ADDR, INV_MPU_MAGN_REG_ASAX,
97			       asa, sizeof(asa));
98	if (ret)
99		return ret;
100
101	/* switch back to power-down */
102	ret = inv_mpu_aux_write(st, INV_MPU_MAGN_I2C_ADDR,
103				INV_MPU_MAGN_REG_CNTL1,
104				INV_MPU_MAGN_BITS_MODE_PWDN);
105	if (ret)
106		return ret;
107
108	/*
109	 * Sensor sentivity
110	 * 1 uT = 0.01 G and value is in micron (1e6)
111	 * sensitvity = x uT * 0.01 * 1e6
112	 */
113	switch (st->chip_type) {
114	case INV_MPU9150:
115		/* sensor sensitivity is 0.3 uT */
116		sensitivity = 3000;
117		break;
118	case INV_MPU9250:
119	case INV_MPU9255:
120		/* sensor sensitivity in 16 bits mode: 0.15 uT */
121		sensitivity = 1500;
122		break;
123	default:
124		return -EINVAL;
125	}
126
127	/*
128	 * Sensitivity adjustement and scale to Gauss
129	 *
130	 * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1)
131	 * Factor simplification:
132	 * Hadj = H * ((ASA + 128) / 256)
133	 *
134	 * raw_to_gauss = Hadj * sensitivity
135	 */
136	st->magn_raw_to_gauss[0] = (((int32_t)asa[0] + 128) * sensitivity) / 256;
137	st->magn_raw_to_gauss[1] = (((int32_t)asa[1] + 128) * sensitivity) / 256;
138	st->magn_raw_to_gauss[2] = (((int32_t)asa[2] + 128) * sensitivity) / 256;
139
140	return 0;
141}
142
143/**
144 * inv_mpu_magn_probe() - probe and setup magnetometer chip
145 * @st: driver internal state
146 *
147 * Returns 0 on success, a negative error code otherwise
148 *
149 * It is probing the chip and setting up all needed i2c transfers.
150 * Noop if there is no magnetometer in the chip.
151 */
152int inv_mpu_magn_probe(struct inv_mpu6050_state *st)
153{
154	uint8_t val;
155	int ret;
156
157	/* quit if chip is not supported */
158	if (!inv_magn_supported(st))
159		return 0;
160
161	/* configure i2c master aux port */
162	ret = inv_mpu_aux_init(st);
163	if (ret)
164		return ret;
165
166	/* check and init mag chip */
167	ret = inv_magn_init(st);
168	if (ret)
169		return ret;
170
171	/*
172	 * configure mpu i2c master accesses
173	 * i2c SLV0: read sensor data, 7 bytes data(6)-ST2
174	 * Byte swap data to store them in big-endian in impair address groups
175	 */
176	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(0),
177			   INV_MPU6050_BIT_I2C_SLV_RNW | INV_MPU_MAGN_I2C_ADDR);
178	if (ret)
179		return ret;
180
181	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(0),
182			   INV_MPU_MAGN_REG_DATA);
183	if (ret)
184		return ret;
185
186	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(0),
187			   INV_MPU6050_BIT_SLV_EN |
188			   INV_MPU6050_BIT_SLV_BYTE_SW |
189			   INV_MPU6050_BIT_SLV_GRP |
190			   INV_MPU9X50_BYTES_MAGN);
191	if (ret)
192		return ret;
193
194	/* i2c SLV1: launch single measurement */
195	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_ADDR(1),
196			   INV_MPU_MAGN_I2C_ADDR);
197	if (ret)
198		return ret;
199
200	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_REG(1),
201			   INV_MPU_MAGN_REG_CNTL1);
202	if (ret)
203		return ret;
204
205	/* add 16 bits mode for MPU925x */
206	val = INV_MPU_MAGN_BITS_MODE_SINGLE;
207	switch (st->chip_type) {
208	case INV_MPU9250:
209	case INV_MPU9255:
210		val |= INV_MPU9250_MAGN_BIT_OUTPUT_BIT;
211		break;
212	default:
213		break;
214	}
215	ret = regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_DO(1), val);
216	if (ret)
217		return ret;
218
219	return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV_CTRL(1),
220			    INV_MPU6050_BIT_SLV_EN | 1);
221}
222
223/**
224 * inv_mpu_magn_set_rate() - set magnetometer sampling rate
225 * @st: driver internal state
226 * @fifo_rate: mpu set fifo rate
227 *
228 * Returns 0 on success, a negative error code otherwise
229 *
230 * Limit sampling frequency to the maximum value supported by the
231 * magnetometer chip. Resulting in duplicated data for higher frequencies.
232 * Noop if there is no magnetometer in the chip.
233 */
234int inv_mpu_magn_set_rate(const struct inv_mpu6050_state *st, int fifo_rate)
235{
236	uint8_t d;
237
238	/* quit if chip is not supported */
239	if (!inv_magn_supported(st))
240		return 0;
241
242	/*
243	 * update i2c master delay to limit mag sampling to max frequency
244	 * compute fifo_rate divider d: rate = fifo_rate / (d + 1)
245	 */
246	if (fifo_rate > INV_MPU_MAGN_FREQ_HZ_MAX)
247		d = fifo_rate / INV_MPU_MAGN_FREQ_HZ_MAX - 1;
248	else
249		d = 0;
250
251	return regmap_write(st->map, INV_MPU6050_REG_I2C_SLV4_CTRL, d);
252}
253
254/**
255 * inv_mpu_magn_set_orient() - fill magnetometer mounting matrix
256 * @st: driver internal state
257 *
258 * Returns 0 on success, a negative error code otherwise
259 *
260 * Fill magnetometer mounting matrix using the provided chip matrix.
261 */
262int inv_mpu_magn_set_orient(struct inv_mpu6050_state *st)
263{
264	struct device *dev = regmap_get_device(st->map);
265	const char *orient;
266	char *str;
267	int i;
268
269	/* fill magnetometer orientation */
270	switch (st->chip_type) {
271	case INV_MPU9150:
272	case INV_MPU9250:
273	case INV_MPU9255:
274		/* x <- y */
275		st->magn_orient.rotation[0] = st->orientation.rotation[3];
276		st->magn_orient.rotation[1] = st->orientation.rotation[4];
277		st->magn_orient.rotation[2] = st->orientation.rotation[5];
278		/* y <- x */
279		st->magn_orient.rotation[3] = st->orientation.rotation[0];
280		st->magn_orient.rotation[4] = st->orientation.rotation[1];
281		st->magn_orient.rotation[5] = st->orientation.rotation[2];
282		/* z <- -z */
283		for (i = 6; i < 9; ++i) {
284			orient = st->orientation.rotation[i];
285
286			/*
287			 * The value is negated according to one of the following
288			 * rules:
289			 *
290			 * 1) Drop leading minus.
291			 * 2) Leave 0 as is.
292			 * 3) Add leading minus.
293			 */
294			if (orient[0] == '-')
295				str = devm_kstrdup(dev, orient + 1, GFP_KERNEL);
296			else if (!strcmp(orient, "0"))
297				str = devm_kstrdup(dev, orient, GFP_KERNEL);
298			else
299				str = devm_kasprintf(dev, GFP_KERNEL, "-%s", orient);
300			if (!str)
301				return -ENOMEM;
302
303			st->magn_orient.rotation[i] = str;
304		}
305		break;
306	default:
307		st->magn_orient = st->orientation;
308		break;
309	}
310
311	return 0;
312}
313
314/**
315 * inv_mpu_magn_read() - read magnetometer data
316 * @st: driver internal state
317 * @axis: IIO modifier axis value
318 * @val: store corresponding axis value
319 *
320 * Returns 0 on success, a negative error code otherwise
321 */
322int inv_mpu_magn_read(struct inv_mpu6050_state *st, int axis, int *val)
323{
324	unsigned int status;
325	__be16 data;
326	uint8_t addr;
327	int ret;
328
329	/* quit if chip is not supported */
330	if (!inv_magn_supported(st))
331		return -ENODEV;
332
333	/* Mag data: XH,XL,YH,YL,ZH,ZL */
334	switch (axis) {
335	case IIO_MOD_X:
336		addr = 0;
337		break;
338	case IIO_MOD_Y:
339		addr = 2;
340		break;
341	case IIO_MOD_Z:
342		addr = 4;
343		break;
344	default:
345		return -EINVAL;
346	}
347	addr += INV_MPU6050_REG_EXT_SENS_DATA;
348
349	/* check i2c status and read raw data */
350	ret = regmap_read(st->map, INV_MPU6050_REG_I2C_MST_STATUS, &status);
351	if (ret)
352		return ret;
353
354	if (status & INV_MPU6050_BIT_I2C_SLV0_NACK ||
355			status & INV_MPU6050_BIT_I2C_SLV1_NACK)
356		return -EIO;
357
358	ret = regmap_bulk_read(st->map, addr, &data, sizeof(data));
359	if (ret)
360		return ret;
361
362	*val = (int16_t)be16_to_cpu(data);
363
364	return IIO_VAL_INT;
365}
366