Skip to content

Commit c01ea8c

Browse files
mranostayRobertCNelson
authored andcommitted
iio: imu: inv_mpu6050: add icm20948 support to driver
Needs rework to upstreamble Signed-off-by: Matt Ranostay <[email protected]>
1 parent cdfcf9d commit c01ea8c

File tree

4 files changed

+198
-40
lines changed

4 files changed

+198
-40
lines changed

drivers/iio/imu/inv_mpu6050/inv_mpu_core.c

Lines changed: 96 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,29 @@ static const int gyro_scale_6050[] = {133090, 266181, 532362, 1064724};
3737
*/
3838
static const int accel_scale[] = {598, 1196, 2392, 4785};
3939

40+
static const struct inv_mpu6050_reg_map reg_set_icm20948 = {
41+
.sample_rate_div = INV_ICM20948_REG_SAMPLE_RATE_DIV,
42+
.lpf = INV_ICM20948_REG_GYRO_CONFIG,
43+
.accel_lpf = INV_ICM20948_REG_ACCEL_CONFIG,
44+
.user_ctrl = INV_ICM20948_REG_USER_CTRL,
45+
.fifo_en = INV_ICM20948_REG_FIFO_EN,
46+
.gyro_config = INV_ICM20948_REG_GYRO_CONFIG,
47+
.accl_config = INV_ICM20948_REG_ACCEL_CONFIG,
48+
.fifo_count_h = INV_ICM20948_REG_FIFO_COUNT_H,
49+
.fifo_r_w = INV_ICM20948_REG_FIFO_R_W,
50+
.raw_gyro = INV_ICM20948_REG_RAW_GYRO,
51+
.raw_accl = INV_ICM20948_REG_RAW_ACCEL,
52+
.temperature = INV_ICM20948_REG_TEMPERATURE,
53+
.int_enable = INV_ICM20948_REG_INT_ENABLE,
54+
.int_status = INV_ICM20948_REG_INT_STATUS,
55+
.pwr_mgmt_1 = INV_ICM20948_REG_PWR_MGMT_1,
56+
.pwr_mgmt_2 = INV_ICM20948_REG_PWR_MGMT_2,
57+
.int_pin_cfg = INV_ICM20948_REG_INT_PIN_CFG,
58+
.accl_offset = INV_ICM20948_REG_ACCEL_OFFSET,
59+
.gyro_offset = INV_ICM20948_REG_GYRO_OFFSET,
60+
.i2c_if = 0,
61+
};
62+
4063
static const struct inv_mpu6050_reg_map reg_set_icm20602 = {
4164
.sample_rate_div = INV_MPU6050_REG_SAMPLE_RATE_DIV,
4265
.lpf = INV_MPU6050_REG_CONFIG,
@@ -108,8 +131,8 @@ static const struct inv_mpu6050_chip_config chip_config_6050 = {
108131
.fsr = INV_MPU6050_FSR_2000DPS,
109132
.lpf = INV_MPU6050_FILTER_20HZ,
110133
.divider = INV_MPU6050_FIFO_RATE_TO_DIVIDER(INV_MPU6050_INIT_FIFO_RATE),
111-
.gyro_fifo_enable = false,
112-
.accl_fifo_enable = false,
134+
.gyro_fifo_enable = true,
135+
.accl_fifo_enable = true,
113136
.accl_fs = INV_MPU6050_FS_02G,
114137
.user_ctrl = 0,
115138
};
@@ -188,6 +211,14 @@ static const struct inv_mpu6050_hw hw_info[] = {
188211
.fifo_size = 1008,
189212
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
190213
},
214+
{
215+
.whoami = 0,
216+
.name = "ICM20948",
217+
.reg = &reg_set_icm20948,
218+
.config = &chip_config_6050,
219+
.fifo_size = 4 * 1024,
220+
.temp = {INV_ICM20948_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
221+
}
191222
};
192223

193224
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
@@ -286,7 +317,13 @@ static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
286317
{
287318
int result;
288319

289-
result = regmap_write(st->map, st->reg->lpf, val);
320+
switch (st->chip_type) {
321+
case INV_ICM20948:
322+
result = regmap_update_bits(st->map, st->reg->lpf, 0x7 << 3, val << 3);
323+
break;
324+
default:
325+
result = regmap_write(st->map, st->reg->lpf, val);
326+
}
290327
if (result)
291328
return result;
292329

@@ -297,6 +334,9 @@ static int inv_mpu6050_set_lpf_regs(struct inv_mpu6050_state *st,
297334
/* old chips, nothing to do */
298335
result = 0;
299336
break;
337+
case INV_ICM20948:
338+
result = regmap_update_bits(st->map, st->reg->accel_lpf, 0x7 << 3, val << 3);
339+
break;
300340
default:
301341
/* set accel lpf */
302342
result = regmap_write(st->map, st->reg->accel_lpf, val);
@@ -324,8 +364,16 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
324364
result = inv_mpu6050_set_power_itg(st, true);
325365
if (result)
326366
return result;
327-
d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
328-
result = regmap_write(st->map, st->reg->gyro_config, d);
367+
368+
switch (st->chip_type) {
369+
case INV_ICM20948:
370+
d = (INV_MPU6050_FSR_2000DPS << 1);
371+
result = regmap_update_bits(st->map, st->reg->gyro_config, 0xf, d | 1);
372+
break;
373+
default:
374+
d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
375+
result = regmap_write(st->map, st->reg->gyro_config, d);
376+
}
329377
if (result)
330378
goto error_power_off;
331379

@@ -338,8 +386,21 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
338386
if (result)
339387
goto error_power_off;
340388

341-
d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
342-
result = regmap_write(st->map, st->reg->accl_config, d);
389+
if (st->chip_type == INV_ICM20948) {
390+
result = regmap_write(st->map, INV_ICM20948_REG_ACCEL_SAMPLE_RATE_DIV2, d);
391+
if (result)
392+
goto error_power_off;
393+
}
394+
395+
switch (st->chip_type) {
396+
case INV_ICM20948:
397+
d = (INV_MPU6050_FS_02G << 1);
398+
result = regmap_update_bits(st->map, st->reg->accl_config, 0x7 << 1, d);
399+
break;
400+
default:
401+
d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
402+
result = regmap_write(st->map, st->reg->accl_config, d);
403+
}
343404
if (result)
344405
goto error_power_off;
345406

@@ -531,8 +592,15 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val)
531592

532593
for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) {
533594
if (gyro_scale_6050[i] == val) {
534-
d = (i << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
535-
result = regmap_write(st->map, st->reg->gyro_config, d);
595+
switch (st->chip_type) {
596+
case INV_ICM20948:
597+
d = (INV_MPU6050_FSR_2000DPS << 1);
598+
result = regmap_update_bits(st->map, st->reg->gyro_config, 0x7 << 1, d);
599+
break;
600+
default:
601+
d = (i << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
602+
result = regmap_write(st->map, st->reg->gyro_config, d);
603+
}
536604
if (result)
537605
return result;
538606

@@ -569,8 +637,15 @@ static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val)
569637

570638
for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) {
571639
if (accel_scale[i] == val) {
572-
d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
573-
result = regmap_write(st->map, st->reg->accl_config, d);
640+
switch (st->chip_type) {
641+
case INV_ICM20948:
642+
d = (i << 1);
643+
result = regmap_update_bits(st->map, st->reg->accl_config, 0xf, d | 1);
644+
break;
645+
default:
646+
d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
647+
result = regmap_write(st->map, st->reg->accl_config, d);
648+
}
574649
if (result)
575650
return result;
576651

@@ -721,6 +796,12 @@ inv_mpu6050_fifo_rate_store(struct device *dev, struct device_attribute *attr,
721796
result = regmap_write(st->map, st->reg->sample_rate_div, d);
722797
if (result)
723798
goto fifo_rate_fail_power_off;
799+
800+
if (st->chip_type == INV_ICM20948) {
801+
result = regmap_write(st->map, INV_ICM20948_REG_ACCEL_SAMPLE_RATE_DIV2, d);
802+
if (result)
803+
goto fifo_rate_fail_power_off;
804+
}
724805
st->chip_config.divider = d;
725806

726807
result = inv_mpu6050_set_lpf(st, fifo_rate);
@@ -976,15 +1057,16 @@ static const struct iio_info mpu_info = {
9761057
*/
9771058
static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
9781059
{
979-
int result;
980-
unsigned int regval;
1060+
int result = 0;
1061+
unsigned int regval = 0;
9811062
int i;
9821063

9831064
st->hw = &hw_info[st->chip_type];
9841065
st->reg = hw_info[st->chip_type].reg;
9851066

9861067
/* check chip self-identification */
987-
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
1068+
if (st->hw->whoami)
1069+
result = regmap_read(st->map, INV_MPU6050_REG_WHOAMI, &regval);
9881070
if (result)
9891071
return result;
9901072
if (regval != st->hw->whoami) {

drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,35 @@
2020
#include <linux/of_device.h>
2121
#include "inv_mpu_iio.h"
2222

23+
#define INV_ICM20948_REG_BANK_SEL 0x7F
24+
#define INV_ICM20948_BANK_SEL_MASK GENMASK(5,4)
25+
26+
static const struct regmap_range_cfg inv_icm20948_regmap_ranges[] = {
27+
{
28+
.name = "user banks",
29+
.range_min = 0x0000,
30+
.range_max = 0x4FFF,
31+
.selector_reg = INV_ICM20948_REG_BANK_SEL,
32+
.selector_mask = INV_ICM20948_BANK_SEL_MASK,
33+
.selector_shift = 4,
34+
.window_start = 0,
35+
.window_len = 0x1000,
36+
},
37+
};
38+
2339
static const struct regmap_config inv_mpu_regmap_config = {
2440
.reg_bits = 8,
2541
.val_bits = 8,
2642
};
2743

44+
static const struct regmap_config inv_icm20948_regmap_config = {
45+
.reg_bits = 8,
46+
.val_bits = 8,
47+
.max_register = 0x4FFF,
48+
.ranges = inv_icm20948_regmap_ranges,
49+
.num_ranges = ARRAY_SIZE(inv_icm20948_regmap_ranges),
50+
};
51+
2852
static int inv_mpu6050_select_bypass(struct i2c_mux_core *muxc, u32 chan_id)
2953
{
3054
struct iio_dev *indio_dev = i2c_mux_priv(muxc);
@@ -88,7 +112,7 @@ static int inv_mpu_probe(struct i2c_client *client,
88112
{
89113
struct inv_mpu6050_state *st;
90114
int result;
91-
enum inv_devices chip_type;
115+
enum inv_devices chip_type = 0;
92116
struct regmap *regmap;
93117
const char *name;
94118

@@ -112,7 +136,14 @@ static int inv_mpu_probe(struct i2c_client *client,
112136
return -ENOSYS;
113137
}
114138

115-
regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
139+
switch (chip_type) {
140+
case INV_ICM20948:
141+
regmap = devm_regmap_init_i2c(client, &inv_icm20948_regmap_config);
142+
break;
143+
default:
144+
regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
145+
}
146+
116147
if (IS_ERR(regmap)) {
117148
dev_err(&client->dev, "Failed to register i2c regmap %d\n",
118149
(int)PTR_ERR(regmap));
@@ -128,6 +159,7 @@ static int inv_mpu_probe(struct i2c_client *client,
128159
switch (st->chip_type) {
129160
case INV_ICM20608:
130161
case INV_ICM20602:
162+
//case INV_ICM20948:
131163
/* no i2c auxiliary bus on the chip */
132164
break;
133165
default:
@@ -181,6 +213,7 @@ static const struct i2c_device_id inv_mpu_id[] = {
181213
{"mpu9255", INV_MPU9255},
182214
{"icm20608", INV_ICM20608},
183215
{"icm20602", INV_ICM20602},
216+
{"icm20948", INV_ICM20948},
184217
{}
185218
};
186219

@@ -219,6 +252,10 @@ static const struct of_device_id inv_of_match[] = {
219252
.compatible = "invensense,icm20602",
220253
.data = (void *)INV_ICM20602
221254
},
255+
{
256+
.compatible = "invensense,icm20948",
257+
.data = (void *)INV_ICM20948
258+
},
222259
{ }
223260
};
224261
MODULE_DEVICE_TABLE(of, inv_of_match);

drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,26 @@
4747
* @i2c_if: Controls the i2c interface
4848
*/
4949
struct inv_mpu6050_reg_map {
50-
u8 sample_rate_div;
51-
u8 lpf;
52-
u8 accel_lpf;
53-
u8 user_ctrl;
54-
u8 fifo_en;
55-
u8 gyro_config;
56-
u8 accl_config;
57-
u8 fifo_count_h;
58-
u8 fifo_r_w;
59-
u8 raw_gyro;
60-
u8 raw_accl;
61-
u8 temperature;
62-
u8 int_enable;
63-
u8 int_status;
64-
u8 pwr_mgmt_1;
65-
u8 pwr_mgmt_2;
66-
u8 int_pin_cfg;
67-
u8 accl_offset;
68-
u8 gyro_offset;
69-
u8 i2c_if;
50+
u16 sample_rate_div;
51+
u16 lpf;
52+
u16 accel_lpf;
53+
u16 user_ctrl;
54+
u16 fifo_en;
55+
u16 gyro_config;
56+
u16 accl_config;
57+
u16 fifo_count_h;
58+
u16 fifo_r_w;
59+
u16 raw_gyro;
60+
u16 raw_accl;
61+
u16 temperature;
62+
u16 int_enable;
63+
u16 int_status;
64+
u16 pwr_mgmt_1;
65+
u16 pwr_mgmt_2;
66+
u16 int_pin_cfg;
67+
u16 accl_offset;
68+
u16 gyro_offset;
69+
u16 i2c_if;
7070
};
7171

7272
/*device enum */
@@ -80,6 +80,7 @@ enum inv_devices {
8080
INV_MPU9255,
8181
INV_ICM20608,
8282
INV_ICM20602,
83+
INV_ICM20948,
8384
INV_NUM_PARTS
8485
};
8586

@@ -243,6 +244,8 @@ struct inv_mpu6050_state {
243244
#define INV_ICM20608_TEMP_OFFSET 8170
244245
#define INV_ICM20608_TEMP_SCALE 3059976
245246

247+
#define INV_ICM20948_TEMP_OFFSET 6863
248+
246249
/* 6 + 6 round up and plus 8 */
247250
#define INV_MPU6050_OUTPUT_DATA_SIZE 24
248251

@@ -284,6 +287,32 @@ struct inv_mpu6050_state {
284287
#define INV_ICM20608_WHOAMI_VALUE 0xAF
285288
#define INV_ICM20602_WHOAMI_VALUE 0x12
286289

290+
291+
#define INV_ICM20948_REG_SAMPLE_RATE_DIV 0x2000
292+
#define INV_ICM20948_REG_ACCEL_SAMPLE_RATE_DIV2 0x2011
293+
#define INV_ICM20948_REG_CONFIG 0x2001
294+
#define INV_ICM20948_REG_ACCEL_CONFIG_2 0x2015
295+
#define INV_ICM20948_REG_USER_CTRL 0x0003
296+
297+
#define INV_ICM20948_REG_FIFO_EN 0x0067
298+
#define INV_ICM20948_BIT_ACCEL_OUT 0x0010
299+
#define INV_ICM20948_BITS_GYRO_OUT 0x000e
300+
301+
#define INV_ICM20948_REG_GYRO_CONFIG 0x2001
302+
#define INV_ICM20948_REG_ACCEL_CONFIG 0x2014
303+
#define INV_ICM20948_REG_FIFO_COUNT_H 0x0070
304+
#define INV_ICM20948_REG_FIFO_R_W 0x0072
305+
#define INV_ICM20948_REG_RAW_GYRO 0x0033
306+
#define INV_ICM20948_REG_RAW_ACCEL 0x002d
307+
#define INV_ICM20948_REG_TEMPERATURE 0x0039
308+
#define INV_ICM20948_REG_INT_ENABLE 0x0011
309+
#define INV_ICM20948_REG_INT_STATUS 0x001a
310+
#define INV_ICM20948_REG_PWR_MGMT_1 0x0006
311+
#define INV_ICM20948_REG_PWR_MGMT_2 0x0007
312+
#define INV_ICM20948_REG_INT_PIN_CFG 0x000f
313+
#define INV_ICM20948_REG_ACCEL_OFFSET 0x1014
314+
#define INV_ICM20948_REG_GYRO_OFFSET 0x2003
315+
287316
/* scan element definition for generic MPU6xxx devices */
288317
enum inv_mpu6050_scan {
289318
INV_MPU6050_SCAN_ACCL_X,

0 commit comments

Comments
 (0)