1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2019 TDK-InvenSense, Inc.
6 #include <linux/kernel.h>
7 #include <linux/device.h>
8 #include <linux/string.h>
10 #include "inv_mpu_aux.h"
11 #include "inv_mpu_iio.h"
12 #include "inv_mpu_magn.h"
15 * MPU9xxx magnetometer are AKM chips on I2C aux bus
19 #define INV_MPU_MAGN_I2C_ADDR 0x0C
21 #define INV_MPU_MAGN_REG_WIA 0x00
22 #define INV_MPU_MAGN_BITS_WIA 0x48
24 #define INV_MPU_MAGN_REG_ST1 0x02
25 #define INV_MPU_MAGN_BIT_DRDY 0x01
26 #define INV_MPU_MAGN_BIT_DOR 0x02
28 #define INV_MPU_MAGN_REG_DATA 0x03
30 #define INV_MPU_MAGN_REG_ST2 0x09
31 #define INV_MPU_MAGN_BIT_HOFL 0x08
32 #define INV_MPU_MAGN_BIT_BITM 0x10
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
40 #define INV_MPU9250_MAGN_REG_CNTL2 0x0B
41 #define INV_MPU9250_MAGN_BIT_SRST 0x01
43 #define INV_MPU_MAGN_REG_ASAX 0x10
44 #define INV_MPU_MAGN_REG_ASAY 0x11
45 #define INV_MPU_MAGN_REG_ASAZ 0x12
47 /* Magnetometer maximum frequency */
48 #define INV_MPU_MAGN_FREQ_HZ_MAX 50
50 static bool inv_magn_supported(const struct inv_mpu6050_state
*st
)
52 switch (st
->chip_type
) {
62 /* init magnetometer chip */
63 static int inv_magn_init(struct inv_mpu6050_state
*st
)
71 ret
= inv_mpu_aux_read(st
, INV_MPU_MAGN_I2C_ADDR
, INV_MPU_MAGN_REG_WIA
,
75 if (val
!= INV_MPU_MAGN_BITS_WIA
)
78 /* software reset for MPU925x only */
79 switch (st
->chip_type
) {
82 ret
= inv_mpu_aux_write(st
, INV_MPU_MAGN_I2C_ADDR
,
83 INV_MPU9250_MAGN_REG_CNTL2
,
84 INV_MPU9250_MAGN_BIT_SRST
);
92 /* read fuse ROM data */
93 ret
= inv_mpu_aux_write(st
, INV_MPU_MAGN_I2C_ADDR
,
94 INV_MPU_MAGN_REG_CNTL1
,
95 INV_MPU_MAGN_BITS_MODE_FUSE
);
99 ret
= inv_mpu_aux_read(st
, INV_MPU_MAGN_I2C_ADDR
, INV_MPU_MAGN_REG_ASAX
,
104 /* switch back to power-down */
105 ret
= inv_mpu_aux_write(st
, INV_MPU_MAGN_I2C_ADDR
,
106 INV_MPU_MAGN_REG_CNTL1
,
107 INV_MPU_MAGN_BITS_MODE_PWDN
);
113 * 1 uT = 0.01 G and value is in micron (1e6)
114 * sensitvity = x uT * 0.01 * 1e6
116 switch (st
->chip_type
) {
118 /* sensor sensitivity is 0.3 uT */
123 /* sensor sensitivity in 16 bits mode: 0.15 uT */
131 * Sensitivity adjustement and scale to Gauss
133 * Hadj = H * (((ASA - 128) * 0.5 / 128) + 1)
134 * Factor simplification:
135 * Hadj = H * ((ASA + 128) / 256)
137 * raw_to_gauss = Hadj * sensitivity
139 st
->magn_raw_to_gauss
[0] = (((int32_t)asa
[0] + 128) * sensitivity
) / 256;
140 st
->magn_raw_to_gauss
[1] = (((int32_t)asa
[1] + 128) * sensitivity
) / 256;
141 st
->magn_raw_to_gauss
[2] = (((int32_t)asa
[2] + 128) * sensitivity
) / 256;
147 * inv_mpu_magn_probe() - probe and setup magnetometer chip
148 * @st: driver internal state
150 * Returns 0 on success, a negative error code otherwise
152 * It is probing the chip and setting up all needed i2c transfers.
153 * Noop if there is no magnetometer in the chip.
155 int inv_mpu_magn_probe(struct inv_mpu6050_state
*st
)
160 /* quit if chip is not supported */
161 if (!inv_magn_supported(st
))
164 /* configure i2c master aux port */
165 ret
= inv_mpu_aux_init(st
);
169 /* check and init mag chip */
170 ret
= inv_magn_init(st
);
175 * configure mpu i2c master accesses
176 * i2c SLV0: read sensor data, 7 bytes data(6)-ST2
177 * Byte swap data to store them in big-endian in impair address groups
179 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_ADDR(0),
180 INV_MPU6050_BIT_I2C_SLV_RNW
| INV_MPU_MAGN_I2C_ADDR
);
184 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_REG(0),
185 INV_MPU_MAGN_REG_DATA
);
189 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_CTRL(0),
190 INV_MPU6050_BIT_SLV_EN
|
191 INV_MPU6050_BIT_SLV_BYTE_SW
|
192 INV_MPU6050_BIT_SLV_GRP
|
193 INV_MPU9X50_BYTES_MAGN
);
197 /* i2c SLV1: launch single measurement */
198 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_ADDR(1),
199 INV_MPU_MAGN_I2C_ADDR
);
203 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_REG(1),
204 INV_MPU_MAGN_REG_CNTL1
);
208 /* add 16 bits mode for MPU925x */
209 val
= INV_MPU_MAGN_BITS_MODE_SINGLE
;
210 switch (st
->chip_type
) {
213 val
|= INV_MPU9250_MAGN_BIT_OUTPUT_BIT
;
218 ret
= regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_DO(1), val
);
222 return regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV_CTRL(1),
223 INV_MPU6050_BIT_SLV_EN
| 1);
227 * inv_mpu_magn_set_rate() - set magnetometer sampling rate
228 * @st: driver internal state
229 * @fifo_rate: mpu set fifo rate
231 * Returns 0 on success, a negative error code otherwise
233 * Limit sampling frequency to the maximum value supported by the
234 * magnetometer chip. Resulting in duplicated data for higher frequencies.
235 * Noop if there is no magnetometer in the chip.
237 int inv_mpu_magn_set_rate(const struct inv_mpu6050_state
*st
, int fifo_rate
)
241 /* quit if chip is not supported */
242 if (!inv_magn_supported(st
))
246 * update i2c master delay to limit mag sampling to max frequency
247 * compute fifo_rate divider d: rate = fifo_rate / (d + 1)
249 if (fifo_rate
> INV_MPU_MAGN_FREQ_HZ_MAX
)
250 d
= fifo_rate
/ INV_MPU_MAGN_FREQ_HZ_MAX
- 1;
254 return regmap_write(st
->map
, INV_MPU6050_REG_I2C_SLV4_CTRL
, d
);
258 * inv_mpu_magn_set_orient() - fill magnetometer mounting matrix
259 * @st: driver internal state
261 * Returns 0 on success, a negative error code otherwise
263 * Fill magnetometer mounting matrix using the provided chip matrix.
265 int inv_mpu_magn_set_orient(struct inv_mpu6050_state
*st
)
271 /* fill magnetometer orientation */
272 switch (st
->chip_type
) {
277 st
->magn_orient
.rotation
[0] = st
->orientation
.rotation
[3];
278 st
->magn_orient
.rotation
[1] = st
->orientation
.rotation
[4];
279 st
->magn_orient
.rotation
[2] = st
->orientation
.rotation
[5];
281 st
->magn_orient
.rotation
[3] = st
->orientation
.rotation
[0];
282 st
->magn_orient
.rotation
[4] = st
->orientation
.rotation
[1];
283 st
->magn_orient
.rotation
[5] = st
->orientation
.rotation
[2];
285 for (i
= 0; i
< 3; ++i
) {
286 orient
= st
->orientation
.rotation
[6 + i
];
287 /* use length + 2 for adding minus sign if needed */
288 str
= devm_kzalloc(regmap_get_device(st
->map
),
289 strlen(orient
) + 2, GFP_KERNEL
);
292 if (strcmp(orient
, "0") == 0) {
294 } else if (orient
[0] == '-') {
295 strcpy(str
, &orient
[1]);
298 strcpy(&str
[1], orient
);
300 st
->magn_orient
.rotation
[6 + i
] = str
;
304 st
->magn_orient
= st
->orientation
;
312 * inv_mpu_magn_read() - read magnetometer data
313 * @st: driver internal state
314 * @axis: IIO modifier axis value
315 * @val: store corresponding axis value
317 * Returns 0 on success, a negative error code otherwise
319 int inv_mpu_magn_read(const struct inv_mpu6050_state
*st
, int axis
, int *val
)
321 unsigned int user_ctrl
, status
;
325 unsigned int period_ms
;
328 /* quit if chip is not supported */
329 if (!inv_magn_supported(st
))
332 /* Mag data: X - Y - Z */
347 /* set sample rate to max mag freq */
348 d
= INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU_MAGN_FREQ_HZ_MAX
);
349 ret
= regmap_write(st
->map
, st
->reg
->sample_rate_div
, d
);
353 /* start i2c master, wait for xfer, stop */
354 user_ctrl
= st
->chip_config
.user_ctrl
| INV_MPU6050_BIT_I2C_MST_EN
;
355 ret
= regmap_write(st
->map
, st
->reg
->user_ctrl
, user_ctrl
);
359 /* need to wait 2 periods + half-period margin */
360 period_ms
= 1000 / INV_MPU_MAGN_FREQ_HZ_MAX
;
361 msleep(period_ms
* 2 + period_ms
/ 2);
362 user_ctrl
= st
->chip_config
.user_ctrl
;
363 ret
= regmap_write(st
->map
, st
->reg
->user_ctrl
, user_ctrl
);
367 /* restore sample rate */
368 d
= st
->chip_config
.divider
;
369 ret
= regmap_write(st
->map
, st
->reg
->sample_rate_div
, d
);
373 /* check i2c status and read raw data */
374 ret
= regmap_read(st
->map
, INV_MPU6050_REG_I2C_MST_STATUS
, &status
);
378 if (status
& INV_MPU6050_BIT_I2C_SLV0_NACK
||
379 status
& INV_MPU6050_BIT_I2C_SLV1_NACK
)
382 ret
= regmap_bulk_read(st
->map
, INV_MPU6050_REG_EXT_SENS_DATA
,
387 *val
= (int16_t)be16_to_cpu(data
[addr
]);