162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * MEMSensing digital 3-Axis accelerometer
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * MSA311 is a tri-axial, low-g accelerometer with I2C digital output for
662306a36Sopenharmony_ci * sensitivity consumer applications. It has dynamic user-selectable full
762306a36Sopenharmony_ci * scales range of +-2g/+-4g/+-8g/+-16g and allows acceleration measurements
862306a36Sopenharmony_ci * with output data rates from 1Hz to 1000Hz.
962306a36Sopenharmony_ci *
1062306a36Sopenharmony_ci * MSA311 is available in an ultra small (2mm x 2mm, height 0.95mm) LGA package
1162306a36Sopenharmony_ci * and is guaranteed to operate over -40C to +85C.
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * This driver supports following MSA311 features:
1462306a36Sopenharmony_ci *     - IIO interface
1562306a36Sopenharmony_ci *     - Different power modes: NORMAL, SUSPEND
1662306a36Sopenharmony_ci *     - ODR (Output Data Rate) selection
1762306a36Sopenharmony_ci *     - Scale selection
1862306a36Sopenharmony_ci *     - IIO triggered buffer
1962306a36Sopenharmony_ci *     - NEW_DATA interrupt + trigger
2062306a36Sopenharmony_ci *
2162306a36Sopenharmony_ci * Below features to be done:
2262306a36Sopenharmony_ci *     - Motion Events: ACTIVE, TAP, ORIENT, FREEFALL
2362306a36Sopenharmony_ci *     - Low Power mode
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * Copyright (c) 2022, SberDevices. All Rights Reserved.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
2862306a36Sopenharmony_ci */
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include <linux/i2c.h>
3162306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
3262306a36Sopenharmony_ci#include <linux/module.h>
3362306a36Sopenharmony_ci#include <linux/pm.h>
3462306a36Sopenharmony_ci#include <linux/pm_runtime.h>
3562306a36Sopenharmony_ci#include <linux/regmap.h>
3662306a36Sopenharmony_ci#include <linux/string_helpers.h>
3762306a36Sopenharmony_ci#include <linux/units.h>
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#include <linux/iio/buffer.h>
4062306a36Sopenharmony_ci#include <linux/iio/iio.h>
4162306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
4262306a36Sopenharmony_ci#include <linux/iio/trigger.h>
4362306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
4462306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci#define MSA311_SOFT_RESET_REG     0x00
4762306a36Sopenharmony_ci#define MSA311_PARTID_REG         0x01
4862306a36Sopenharmony_ci#define MSA311_ACC_X_REG          0x02
4962306a36Sopenharmony_ci#define MSA311_ACC_Y_REG          0x04
5062306a36Sopenharmony_ci#define MSA311_ACC_Z_REG          0x06
5162306a36Sopenharmony_ci#define MSA311_MOTION_INT_REG     0x09
5262306a36Sopenharmony_ci#define MSA311_DATA_INT_REG       0x0A
5362306a36Sopenharmony_ci#define MSA311_TAP_ACTIVE_STS_REG 0x0B
5462306a36Sopenharmony_ci#define MSA311_ORIENT_STS_REG     0x0C
5562306a36Sopenharmony_ci#define MSA311_RANGE_REG          0x0F
5662306a36Sopenharmony_ci#define MSA311_ODR_REG            0x10
5762306a36Sopenharmony_ci#define MSA311_PWR_MODE_REG       0x11
5862306a36Sopenharmony_ci#define MSA311_SWAP_POLARITY_REG  0x12
5962306a36Sopenharmony_ci#define MSA311_INT_SET_0_REG      0x16
6062306a36Sopenharmony_ci#define MSA311_INT_SET_1_REG      0x17
6162306a36Sopenharmony_ci#define MSA311_INT_MAP_0_REG      0x19
6262306a36Sopenharmony_ci#define MSA311_INT_MAP_1_REG      0x1A
6362306a36Sopenharmony_ci#define MSA311_INT_CONFIG_REG     0x20
6462306a36Sopenharmony_ci#define MSA311_INT_LATCH_REG      0x21
6562306a36Sopenharmony_ci#define MSA311_FREEFALL_DUR_REG   0x22
6662306a36Sopenharmony_ci#define MSA311_FREEFALL_TH_REG    0x23
6762306a36Sopenharmony_ci#define MSA311_FREEFALL_HY_REG    0x24
6862306a36Sopenharmony_ci#define MSA311_ACTIVE_DUR_REG     0x27
6962306a36Sopenharmony_ci#define MSA311_ACTIVE_TH_REG      0x28
7062306a36Sopenharmony_ci#define MSA311_TAP_DUR_REG        0x2A
7162306a36Sopenharmony_ci#define MSA311_TAP_TH_REG         0x2B
7262306a36Sopenharmony_ci#define MSA311_ORIENT_HY_REG      0x2C
7362306a36Sopenharmony_ci#define MSA311_Z_BLOCK_REG        0x2D
7462306a36Sopenharmony_ci#define MSA311_OFFSET_X_REG       0x38
7562306a36Sopenharmony_ci#define MSA311_OFFSET_Y_REG       0x39
7662306a36Sopenharmony_ci#define MSA311_OFFSET_Z_REG       0x3A
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cienum msa311_fields {
7962306a36Sopenharmony_ci	/* Soft_Reset */
8062306a36Sopenharmony_ci	F_SOFT_RESET_I2C, F_SOFT_RESET_SPI,
8162306a36Sopenharmony_ci	/* Motion_Interrupt */
8262306a36Sopenharmony_ci	F_ORIENT_INT, F_S_TAP_INT, F_D_TAP_INT, F_ACTIVE_INT, F_FREEFALL_INT,
8362306a36Sopenharmony_ci	/* Data_Interrupt */
8462306a36Sopenharmony_ci	F_NEW_DATA_INT,
8562306a36Sopenharmony_ci	/* Tap_Active_Status */
8662306a36Sopenharmony_ci	F_TAP_SIGN, F_TAP_FIRST_X, F_TAP_FIRST_Y, F_TAP_FIRST_Z, F_ACTV_SIGN,
8762306a36Sopenharmony_ci	F_ACTV_FIRST_X, F_ACTV_FIRST_Y, F_ACTV_FIRST_Z,
8862306a36Sopenharmony_ci	/* Orientation_Status */
8962306a36Sopenharmony_ci	F_ORIENT_Z, F_ORIENT_X_Y,
9062306a36Sopenharmony_ci	/* Range */
9162306a36Sopenharmony_ci	F_FS,
9262306a36Sopenharmony_ci	/* ODR */
9362306a36Sopenharmony_ci	F_X_AXIS_DIS, F_Y_AXIS_DIS, F_Z_AXIS_DIS, F_ODR,
9462306a36Sopenharmony_ci	/* Power Mode/Bandwidth */
9562306a36Sopenharmony_ci	F_PWR_MODE, F_LOW_POWER_BW,
9662306a36Sopenharmony_ci	/* Swap_Polarity */
9762306a36Sopenharmony_ci	F_X_POLARITY, F_Y_POLARITY, F_Z_POLARITY, F_X_Y_SWAP,
9862306a36Sopenharmony_ci	/* Int_Set_0 */
9962306a36Sopenharmony_ci	F_ORIENT_INT_EN, F_S_TAP_INT_EN, F_D_TAP_INT_EN, F_ACTIVE_INT_EN_Z,
10062306a36Sopenharmony_ci	F_ACTIVE_INT_EN_Y, F_ACTIVE_INT_EN_X,
10162306a36Sopenharmony_ci	/* Int_Set_1 */
10262306a36Sopenharmony_ci	F_NEW_DATA_INT_EN, F_FREEFALL_INT_EN,
10362306a36Sopenharmony_ci	/* Int_Map_0 */
10462306a36Sopenharmony_ci	F_INT1_ORIENT, F_INT1_S_TAP, F_INT1_D_TAP, F_INT1_ACTIVE,
10562306a36Sopenharmony_ci	F_INT1_FREEFALL,
10662306a36Sopenharmony_ci	/* Int_Map_1 */
10762306a36Sopenharmony_ci	F_INT1_NEW_DATA,
10862306a36Sopenharmony_ci	/* Int_Config */
10962306a36Sopenharmony_ci	F_INT1_OD, F_INT1_LVL,
11062306a36Sopenharmony_ci	/* Int_Latch */
11162306a36Sopenharmony_ci	F_RESET_INT, F_LATCH_INT,
11262306a36Sopenharmony_ci	/* Freefall_Hy */
11362306a36Sopenharmony_ci	F_FREEFALL_MODE, F_FREEFALL_HY,
11462306a36Sopenharmony_ci	/* Active_Dur */
11562306a36Sopenharmony_ci	F_ACTIVE_DUR,
11662306a36Sopenharmony_ci	/* Tap_Dur */
11762306a36Sopenharmony_ci	F_TAP_QUIET, F_TAP_SHOCK, F_TAP_DUR,
11862306a36Sopenharmony_ci	/* Tap_Th */
11962306a36Sopenharmony_ci	F_TAP_TH,
12062306a36Sopenharmony_ci	/* Orient_Hy */
12162306a36Sopenharmony_ci	F_ORIENT_HYST, F_ORIENT_BLOCKING, F_ORIENT_MODE,
12262306a36Sopenharmony_ci	/* Z_Block */
12362306a36Sopenharmony_ci	F_Z_BLOCKING,
12462306a36Sopenharmony_ci	/* End of register map */
12562306a36Sopenharmony_ci	F_MAX_FIELDS,
12662306a36Sopenharmony_ci};
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic const struct reg_field msa311_reg_fields[] = {
12962306a36Sopenharmony_ci	/* Soft_Reset */
13062306a36Sopenharmony_ci	[F_SOFT_RESET_I2C] = REG_FIELD(MSA311_SOFT_RESET_REG, 2, 2),
13162306a36Sopenharmony_ci	[F_SOFT_RESET_SPI] = REG_FIELD(MSA311_SOFT_RESET_REG, 5, 5),
13262306a36Sopenharmony_ci	/* Motion_Interrupt */
13362306a36Sopenharmony_ci	[F_ORIENT_INT] = REG_FIELD(MSA311_MOTION_INT_REG, 6, 6),
13462306a36Sopenharmony_ci	[F_S_TAP_INT] = REG_FIELD(MSA311_MOTION_INT_REG, 5, 5),
13562306a36Sopenharmony_ci	[F_D_TAP_INT] = REG_FIELD(MSA311_MOTION_INT_REG, 4, 4),
13662306a36Sopenharmony_ci	[F_ACTIVE_INT] = REG_FIELD(MSA311_MOTION_INT_REG, 2, 2),
13762306a36Sopenharmony_ci	[F_FREEFALL_INT] = REG_FIELD(MSA311_MOTION_INT_REG, 0, 0),
13862306a36Sopenharmony_ci	/* Data_Interrupt */
13962306a36Sopenharmony_ci	[F_NEW_DATA_INT] = REG_FIELD(MSA311_DATA_INT_REG, 0, 0),
14062306a36Sopenharmony_ci	/* Tap_Active_Status */
14162306a36Sopenharmony_ci	[F_TAP_SIGN] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 7, 7),
14262306a36Sopenharmony_ci	[F_TAP_FIRST_X] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 6, 6),
14362306a36Sopenharmony_ci	[F_TAP_FIRST_Y] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 5, 5),
14462306a36Sopenharmony_ci	[F_TAP_FIRST_Z] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 4, 4),
14562306a36Sopenharmony_ci	[F_ACTV_SIGN] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 3, 3),
14662306a36Sopenharmony_ci	[F_ACTV_FIRST_X] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 2, 2),
14762306a36Sopenharmony_ci	[F_ACTV_FIRST_Y] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 1, 1),
14862306a36Sopenharmony_ci	[F_ACTV_FIRST_Z] = REG_FIELD(MSA311_TAP_ACTIVE_STS_REG, 0, 0),
14962306a36Sopenharmony_ci	/* Orientation_Status */
15062306a36Sopenharmony_ci	[F_ORIENT_Z] = REG_FIELD(MSA311_ORIENT_STS_REG, 6, 6),
15162306a36Sopenharmony_ci	[F_ORIENT_X_Y] = REG_FIELD(MSA311_ORIENT_STS_REG, 4, 5),
15262306a36Sopenharmony_ci	/* Range */
15362306a36Sopenharmony_ci	[F_FS] = REG_FIELD(MSA311_RANGE_REG, 0, 1),
15462306a36Sopenharmony_ci	/* ODR */
15562306a36Sopenharmony_ci	[F_X_AXIS_DIS] = REG_FIELD(MSA311_ODR_REG, 7, 7),
15662306a36Sopenharmony_ci	[F_Y_AXIS_DIS] = REG_FIELD(MSA311_ODR_REG, 6, 6),
15762306a36Sopenharmony_ci	[F_Z_AXIS_DIS] = REG_FIELD(MSA311_ODR_REG, 5, 5),
15862306a36Sopenharmony_ci	[F_ODR] = REG_FIELD(MSA311_ODR_REG, 0, 3),
15962306a36Sopenharmony_ci	/* Power Mode/Bandwidth */
16062306a36Sopenharmony_ci	[F_PWR_MODE] = REG_FIELD(MSA311_PWR_MODE_REG, 6, 7),
16162306a36Sopenharmony_ci	[F_LOW_POWER_BW] = REG_FIELD(MSA311_PWR_MODE_REG, 1, 4),
16262306a36Sopenharmony_ci	/* Swap_Polarity */
16362306a36Sopenharmony_ci	[F_X_POLARITY] = REG_FIELD(MSA311_SWAP_POLARITY_REG, 3, 3),
16462306a36Sopenharmony_ci	[F_Y_POLARITY] = REG_FIELD(MSA311_SWAP_POLARITY_REG, 2, 2),
16562306a36Sopenharmony_ci	[F_Z_POLARITY] = REG_FIELD(MSA311_SWAP_POLARITY_REG, 1, 1),
16662306a36Sopenharmony_ci	[F_X_Y_SWAP] = REG_FIELD(MSA311_SWAP_POLARITY_REG, 0, 0),
16762306a36Sopenharmony_ci	/* Int_Set_0 */
16862306a36Sopenharmony_ci	[F_ORIENT_INT_EN] = REG_FIELD(MSA311_INT_SET_0_REG, 6, 6),
16962306a36Sopenharmony_ci	[F_S_TAP_INT_EN] = REG_FIELD(MSA311_INT_SET_0_REG, 5, 5),
17062306a36Sopenharmony_ci	[F_D_TAP_INT_EN] = REG_FIELD(MSA311_INT_SET_0_REG, 4, 4),
17162306a36Sopenharmony_ci	[F_ACTIVE_INT_EN_Z] = REG_FIELD(MSA311_INT_SET_0_REG, 2, 2),
17262306a36Sopenharmony_ci	[F_ACTIVE_INT_EN_Y] = REG_FIELD(MSA311_INT_SET_0_REG, 1, 1),
17362306a36Sopenharmony_ci	[F_ACTIVE_INT_EN_X] = REG_FIELD(MSA311_INT_SET_0_REG, 0, 0),
17462306a36Sopenharmony_ci	/* Int_Set_1 */
17562306a36Sopenharmony_ci	[F_NEW_DATA_INT_EN] = REG_FIELD(MSA311_INT_SET_1_REG, 4, 4),
17662306a36Sopenharmony_ci	[F_FREEFALL_INT_EN] = REG_FIELD(MSA311_INT_SET_1_REG, 3, 3),
17762306a36Sopenharmony_ci	/* Int_Map_0 */
17862306a36Sopenharmony_ci	[F_INT1_ORIENT] = REG_FIELD(MSA311_INT_MAP_0_REG, 6, 6),
17962306a36Sopenharmony_ci	[F_INT1_S_TAP] = REG_FIELD(MSA311_INT_MAP_0_REG, 5, 5),
18062306a36Sopenharmony_ci	[F_INT1_D_TAP] = REG_FIELD(MSA311_INT_MAP_0_REG, 4, 4),
18162306a36Sopenharmony_ci	[F_INT1_ACTIVE] = REG_FIELD(MSA311_INT_MAP_0_REG, 2, 2),
18262306a36Sopenharmony_ci	[F_INT1_FREEFALL] = REG_FIELD(MSA311_INT_MAP_0_REG, 0, 0),
18362306a36Sopenharmony_ci	/* Int_Map_1 */
18462306a36Sopenharmony_ci	[F_INT1_NEW_DATA] = REG_FIELD(MSA311_INT_MAP_1_REG, 0, 0),
18562306a36Sopenharmony_ci	/* Int_Config */
18662306a36Sopenharmony_ci	[F_INT1_OD] = REG_FIELD(MSA311_INT_CONFIG_REG, 1, 1),
18762306a36Sopenharmony_ci	[F_INT1_LVL] = REG_FIELD(MSA311_INT_CONFIG_REG, 0, 0),
18862306a36Sopenharmony_ci	/* Int_Latch */
18962306a36Sopenharmony_ci	[F_RESET_INT] = REG_FIELD(MSA311_INT_LATCH_REG, 7, 7),
19062306a36Sopenharmony_ci	[F_LATCH_INT] = REG_FIELD(MSA311_INT_LATCH_REG, 0, 3),
19162306a36Sopenharmony_ci	/* Freefall_Hy */
19262306a36Sopenharmony_ci	[F_FREEFALL_MODE] = REG_FIELD(MSA311_FREEFALL_HY_REG, 2, 2),
19362306a36Sopenharmony_ci	[F_FREEFALL_HY] = REG_FIELD(MSA311_FREEFALL_HY_REG, 0, 1),
19462306a36Sopenharmony_ci	/* Active_Dur */
19562306a36Sopenharmony_ci	[F_ACTIVE_DUR] = REG_FIELD(MSA311_ACTIVE_DUR_REG, 0, 1),
19662306a36Sopenharmony_ci	/* Tap_Dur */
19762306a36Sopenharmony_ci	[F_TAP_QUIET] = REG_FIELD(MSA311_TAP_DUR_REG, 7, 7),
19862306a36Sopenharmony_ci	[F_TAP_SHOCK] = REG_FIELD(MSA311_TAP_DUR_REG, 6, 6),
19962306a36Sopenharmony_ci	[F_TAP_DUR] = REG_FIELD(MSA311_TAP_DUR_REG, 0, 2),
20062306a36Sopenharmony_ci	/* Tap_Th */
20162306a36Sopenharmony_ci	[F_TAP_TH] = REG_FIELD(MSA311_TAP_TH_REG, 0, 4),
20262306a36Sopenharmony_ci	/* Orient_Hy */
20362306a36Sopenharmony_ci	[F_ORIENT_HYST] = REG_FIELD(MSA311_ORIENT_HY_REG, 4, 6),
20462306a36Sopenharmony_ci	[F_ORIENT_BLOCKING] = REG_FIELD(MSA311_ORIENT_HY_REG, 2, 3),
20562306a36Sopenharmony_ci	[F_ORIENT_MODE] = REG_FIELD(MSA311_ORIENT_HY_REG, 0, 1),
20662306a36Sopenharmony_ci	/* Z_Block */
20762306a36Sopenharmony_ci	[F_Z_BLOCKING] = REG_FIELD(MSA311_Z_BLOCK_REG, 0, 3),
20862306a36Sopenharmony_ci};
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci#define MSA311_WHO_AM_I 0x13
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/*
21362306a36Sopenharmony_ci * Possible Full Scale ranges
21462306a36Sopenharmony_ci *
21562306a36Sopenharmony_ci * Axis data is 12-bit signed value, so
21662306a36Sopenharmony_ci *
21762306a36Sopenharmony_ci * fs0 = (2 + 2) * 9.81 / (2^11) = 0.009580
21862306a36Sopenharmony_ci * fs1 = (4 + 4) * 9.81 / (2^11) = 0.019160
21962306a36Sopenharmony_ci * fs2 = (8 + 8) * 9.81 / (2^11) = 0.038320
22062306a36Sopenharmony_ci * fs3 = (16 + 16) * 9.81 / (2^11) = 0.076641
22162306a36Sopenharmony_ci */
22262306a36Sopenharmony_cienum {
22362306a36Sopenharmony_ci	MSA311_FS_2G,
22462306a36Sopenharmony_ci	MSA311_FS_4G,
22562306a36Sopenharmony_ci	MSA311_FS_8G,
22662306a36Sopenharmony_ci	MSA311_FS_16G,
22762306a36Sopenharmony_ci};
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistruct iio_decimal_fract {
23062306a36Sopenharmony_ci	int integral;
23162306a36Sopenharmony_ci	int microfract;
23262306a36Sopenharmony_ci};
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_cistatic const struct iio_decimal_fract msa311_fs_table[] = {
23562306a36Sopenharmony_ci	{0, 9580}, {0, 19160}, {0, 38320}, {0, 76641},
23662306a36Sopenharmony_ci};
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/* Possible Output Data Rate values */
23962306a36Sopenharmony_cienum {
24062306a36Sopenharmony_ci	MSA311_ODR_1_HZ,
24162306a36Sopenharmony_ci	MSA311_ODR_1_95_HZ,
24262306a36Sopenharmony_ci	MSA311_ODR_3_9_HZ,
24362306a36Sopenharmony_ci	MSA311_ODR_7_81_HZ,
24462306a36Sopenharmony_ci	MSA311_ODR_15_63_HZ,
24562306a36Sopenharmony_ci	MSA311_ODR_31_25_HZ,
24662306a36Sopenharmony_ci	MSA311_ODR_62_5_HZ,
24762306a36Sopenharmony_ci	MSA311_ODR_125_HZ,
24862306a36Sopenharmony_ci	MSA311_ODR_250_HZ,
24962306a36Sopenharmony_ci	MSA311_ODR_500_HZ,
25062306a36Sopenharmony_ci	MSA311_ODR_1000_HZ,
25162306a36Sopenharmony_ci};
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_cistatic const struct iio_decimal_fract msa311_odr_table[] = {
25462306a36Sopenharmony_ci	{1, 0}, {1, 950000}, {3, 900000}, {7, 810000}, {15, 630000},
25562306a36Sopenharmony_ci	{31, 250000}, {62, 500000}, {125, 0}, {250, 0}, {500, 0}, {1000, 0},
25662306a36Sopenharmony_ci};
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci/* All supported power modes */
25962306a36Sopenharmony_ci#define MSA311_PWR_MODE_NORMAL  0b00
26062306a36Sopenharmony_ci#define MSA311_PWR_MODE_LOW     0b01
26162306a36Sopenharmony_ci#define MSA311_PWR_MODE_UNKNOWN 0b10
26262306a36Sopenharmony_ci#define MSA311_PWR_MODE_SUSPEND 0b11
26362306a36Sopenharmony_cistatic const char * const msa311_pwr_modes[] = {
26462306a36Sopenharmony_ci	[MSA311_PWR_MODE_NORMAL] = "normal",
26562306a36Sopenharmony_ci	[MSA311_PWR_MODE_LOW] = "low",
26662306a36Sopenharmony_ci	[MSA311_PWR_MODE_UNKNOWN] = "unknown",
26762306a36Sopenharmony_ci	[MSA311_PWR_MODE_SUSPEND] = "suspend",
26862306a36Sopenharmony_ci};
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/* Autosuspend delay */
27162306a36Sopenharmony_ci#define MSA311_PWR_SLEEP_DELAY_MS 2000
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/* Possible INT1 types and levels */
27462306a36Sopenharmony_cienum {
27562306a36Sopenharmony_ci	MSA311_INT1_OD_PUSH_PULL,
27662306a36Sopenharmony_ci	MSA311_INT1_OD_OPEN_DRAIN,
27762306a36Sopenharmony_ci};
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_cienum {
28062306a36Sopenharmony_ci	MSA311_INT1_LVL_LOW,
28162306a36Sopenharmony_ci	MSA311_INT1_LVL_HIGH,
28262306a36Sopenharmony_ci};
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci/* Latch INT modes */
28562306a36Sopenharmony_ci#define MSA311_LATCH_INT_NOT_LATCHED 0b0000
28662306a36Sopenharmony_ci#define MSA311_LATCH_INT_250MS       0b0001
28762306a36Sopenharmony_ci#define MSA311_LATCH_INT_500MS       0b0010
28862306a36Sopenharmony_ci#define MSA311_LATCH_INT_1S          0b0011
28962306a36Sopenharmony_ci#define MSA311_LATCH_INT_2S          0b0100
29062306a36Sopenharmony_ci#define MSA311_LATCH_INT_4S          0b0101
29162306a36Sopenharmony_ci#define MSA311_LATCH_INT_8S          0b0110
29262306a36Sopenharmony_ci#define MSA311_LATCH_INT_1MS         0b1010
29362306a36Sopenharmony_ci#define MSA311_LATCH_INT_2MS         0b1011
29462306a36Sopenharmony_ci#define MSA311_LATCH_INT_25MS        0b1100
29562306a36Sopenharmony_ci#define MSA311_LATCH_INT_50MS        0b1101
29662306a36Sopenharmony_ci#define MSA311_LATCH_INT_100MS       0b1110
29762306a36Sopenharmony_ci#define MSA311_LATCH_INT_LATCHED     0b0111
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic const struct regmap_range msa311_readonly_registers[] = {
30062306a36Sopenharmony_ci	regmap_reg_range(MSA311_PARTID_REG, MSA311_ORIENT_STS_REG),
30162306a36Sopenharmony_ci};
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_cistatic const struct regmap_access_table msa311_writeable_table = {
30462306a36Sopenharmony_ci	.no_ranges = msa311_readonly_registers,
30562306a36Sopenharmony_ci	.n_no_ranges = ARRAY_SIZE(msa311_readonly_registers),
30662306a36Sopenharmony_ci};
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_cistatic const struct regmap_range msa311_writeonly_registers[] = {
30962306a36Sopenharmony_ci	regmap_reg_range(MSA311_SOFT_RESET_REG, MSA311_SOFT_RESET_REG),
31062306a36Sopenharmony_ci};
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_cistatic const struct regmap_access_table msa311_readable_table = {
31362306a36Sopenharmony_ci	.no_ranges = msa311_writeonly_registers,
31462306a36Sopenharmony_ci	.n_no_ranges = ARRAY_SIZE(msa311_writeonly_registers),
31562306a36Sopenharmony_ci};
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic const struct regmap_range msa311_volatile_registers[] = {
31862306a36Sopenharmony_ci	regmap_reg_range(MSA311_ACC_X_REG, MSA311_ORIENT_STS_REG),
31962306a36Sopenharmony_ci};
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_cistatic const struct regmap_access_table msa311_volatile_table = {
32262306a36Sopenharmony_ci	.yes_ranges = msa311_volatile_registers,
32362306a36Sopenharmony_ci	.n_yes_ranges = ARRAY_SIZE(msa311_volatile_registers),
32462306a36Sopenharmony_ci};
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic const struct regmap_config msa311_regmap_config = {
32762306a36Sopenharmony_ci	.name = "msa311",
32862306a36Sopenharmony_ci	.reg_bits = 8,
32962306a36Sopenharmony_ci	.val_bits = 8,
33062306a36Sopenharmony_ci	.max_register = MSA311_OFFSET_Z_REG,
33162306a36Sopenharmony_ci	.wr_table = &msa311_writeable_table,
33262306a36Sopenharmony_ci	.rd_table = &msa311_readable_table,
33362306a36Sopenharmony_ci	.volatile_table = &msa311_volatile_table,
33462306a36Sopenharmony_ci	.cache_type = REGCACHE_RBTREE,
33562306a36Sopenharmony_ci};
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci#define MSA311_GENMASK(field) ({                \
33862306a36Sopenharmony_ci	typeof(&(msa311_reg_fields)[0]) _field; \
33962306a36Sopenharmony_ci	_field = &msa311_reg_fields[(field)];   \
34062306a36Sopenharmony_ci	GENMASK(_field->msb, _field->lsb);      \
34162306a36Sopenharmony_ci})
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci/**
34462306a36Sopenharmony_ci * struct msa311_priv - MSA311 internal private state
34562306a36Sopenharmony_ci * @regs: Underlying I2C bus adapter used to abstract slave
34662306a36Sopenharmony_ci *        register accesses
34762306a36Sopenharmony_ci * @fields: Abstract objects for each registers fields access
34862306a36Sopenharmony_ci * @dev: Device handler associated with appropriate bus client
34962306a36Sopenharmony_ci * @lock: Protects msa311 device state between setup and data access routines
35062306a36Sopenharmony_ci *        (power transitions, samp_freq/scale tune, retrieving axes data, etc)
35162306a36Sopenharmony_ci * @chip_name: Chip name in the format "msa311-%02x" % partid
35262306a36Sopenharmony_ci * @new_data_trig: Optional NEW_DATA interrupt driven trigger used
35362306a36Sopenharmony_ci *                 to notify external consumers a new sample is ready
35462306a36Sopenharmony_ci */
35562306a36Sopenharmony_cistruct msa311_priv {
35662306a36Sopenharmony_ci	struct regmap *regs;
35762306a36Sopenharmony_ci	struct regmap_field *fields[F_MAX_FIELDS];
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	struct device *dev;
36062306a36Sopenharmony_ci	struct mutex lock;
36162306a36Sopenharmony_ci	char *chip_name;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	struct iio_trigger *new_data_trig;
36462306a36Sopenharmony_ci};
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cienum msa311_si {
36762306a36Sopenharmony_ci	MSA311_SI_X,
36862306a36Sopenharmony_ci	MSA311_SI_Y,
36962306a36Sopenharmony_ci	MSA311_SI_Z,
37062306a36Sopenharmony_ci	MSA311_SI_TIMESTAMP,
37162306a36Sopenharmony_ci};
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci#define MSA311_ACCEL_CHANNEL(axis) {                                        \
37462306a36Sopenharmony_ci	.type = IIO_ACCEL,                                                  \
37562306a36Sopenharmony_ci	.modified = 1,                                                      \
37662306a36Sopenharmony_ci	.channel2 = IIO_MOD_##axis,                                         \
37762306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),                       \
37862306a36Sopenharmony_ci	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |              \
37962306a36Sopenharmony_ci				    BIT(IIO_CHAN_INFO_SAMP_FREQ),           \
38062306a36Sopenharmony_ci	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) |    \
38162306a36Sopenharmony_ci					      BIT(IIO_CHAN_INFO_SAMP_FREQ), \
38262306a36Sopenharmony_ci	.scan_index = MSA311_SI_##axis,                                     \
38362306a36Sopenharmony_ci	.scan_type = {                                                      \
38462306a36Sopenharmony_ci		.sign = 's',                                                \
38562306a36Sopenharmony_ci		.realbits = 12,                                             \
38662306a36Sopenharmony_ci		.storagebits = 16,                                          \
38762306a36Sopenharmony_ci		.shift = 4,                                                 \
38862306a36Sopenharmony_ci		.endianness = IIO_LE,                                       \
38962306a36Sopenharmony_ci	},                                                                  \
39062306a36Sopenharmony_ci	.datasheet_name = "ACC_"#axis,                                      \
39162306a36Sopenharmony_ci}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_cistatic const struct iio_chan_spec msa311_channels[] = {
39462306a36Sopenharmony_ci	MSA311_ACCEL_CHANNEL(X),
39562306a36Sopenharmony_ci	MSA311_ACCEL_CHANNEL(Y),
39662306a36Sopenharmony_ci	MSA311_ACCEL_CHANNEL(Z),
39762306a36Sopenharmony_ci	IIO_CHAN_SOFT_TIMESTAMP(MSA311_SI_TIMESTAMP),
39862306a36Sopenharmony_ci};
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci/**
40162306a36Sopenharmony_ci * msa311_get_odr() - Read Output Data Rate (ODR) value from MSA311 accel
40262306a36Sopenharmony_ci * @msa311: MSA311 internal private state
40362306a36Sopenharmony_ci * @odr: output ODR value
40462306a36Sopenharmony_ci *
40562306a36Sopenharmony_ci * This function should be called under msa311->lock.
40662306a36Sopenharmony_ci *
40762306a36Sopenharmony_ci * Return: 0 on success, -ERRNO in other failures
40862306a36Sopenharmony_ci */
40962306a36Sopenharmony_cistatic int msa311_get_odr(struct msa311_priv *msa311, unsigned int *odr)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	int err;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	err = regmap_field_read(msa311->fields[F_ODR], odr);
41462306a36Sopenharmony_ci	if (err)
41562306a36Sopenharmony_ci		return err;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	/*
41862306a36Sopenharmony_ci	 * Filter the same 1000Hz ODR register values based on datasheet info.
41962306a36Sopenharmony_ci	 * ODR can be equal to 1010-1111 for 1000Hz, but function returns 1010
42062306a36Sopenharmony_ci	 * all the time.
42162306a36Sopenharmony_ci	 */
42262306a36Sopenharmony_ci	if (*odr > MSA311_ODR_1000_HZ)
42362306a36Sopenharmony_ci		*odr = MSA311_ODR_1000_HZ;
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	return 0;
42662306a36Sopenharmony_ci}
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci/**
42962306a36Sopenharmony_ci * msa311_set_odr() - Setup Output Data Rate (ODR) value for MSA311 accel
43062306a36Sopenharmony_ci * @msa311: MSA311 internal private state
43162306a36Sopenharmony_ci * @odr: requested ODR value
43262306a36Sopenharmony_ci *
43362306a36Sopenharmony_ci * This function should be called under msa311->lock. Possible ODR values:
43462306a36Sopenharmony_ci *     - 1Hz (not available in normal mode)
43562306a36Sopenharmony_ci *     - 1.95Hz (not available in normal mode)
43662306a36Sopenharmony_ci *     - 3.9Hz
43762306a36Sopenharmony_ci *     - 7.81Hz
43862306a36Sopenharmony_ci *     - 15.63Hz
43962306a36Sopenharmony_ci *     - 31.25Hz
44062306a36Sopenharmony_ci *     - 62.5Hz
44162306a36Sopenharmony_ci *     - 125Hz
44262306a36Sopenharmony_ci *     - 250Hz
44362306a36Sopenharmony_ci *     - 500Hz
44462306a36Sopenharmony_ci *     - 1000Hz
44562306a36Sopenharmony_ci *
44662306a36Sopenharmony_ci * Return: 0 on success, -EINVAL for bad ODR value in the certain power mode,
44762306a36Sopenharmony_ci *         -ERRNO in other failures
44862306a36Sopenharmony_ci */
44962306a36Sopenharmony_cistatic int msa311_set_odr(struct msa311_priv *msa311, unsigned int odr)
45062306a36Sopenharmony_ci{
45162306a36Sopenharmony_ci	struct device *dev = msa311->dev;
45262306a36Sopenharmony_ci	unsigned int pwr_mode;
45362306a36Sopenharmony_ci	bool good_odr;
45462306a36Sopenharmony_ci	int err;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_ci	err = regmap_field_read(msa311->fields[F_PWR_MODE], &pwr_mode);
45762306a36Sopenharmony_ci	if (err)
45862306a36Sopenharmony_ci		return err;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	/* Filter bad ODR values */
46162306a36Sopenharmony_ci	if (pwr_mode == MSA311_PWR_MODE_NORMAL)
46262306a36Sopenharmony_ci		good_odr = (odr > MSA311_ODR_1_95_HZ);
46362306a36Sopenharmony_ci	else
46462306a36Sopenharmony_ci		good_odr = false;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (!good_odr) {
46762306a36Sopenharmony_ci		dev_err(dev,
46862306a36Sopenharmony_ci			"can't set odr %u.%06uHz, not available in %s mode\n",
46962306a36Sopenharmony_ci			msa311_odr_table[odr].integral,
47062306a36Sopenharmony_ci			msa311_odr_table[odr].microfract,
47162306a36Sopenharmony_ci			msa311_pwr_modes[pwr_mode]);
47262306a36Sopenharmony_ci		return -EINVAL;
47362306a36Sopenharmony_ci	}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	return regmap_field_write(msa311->fields[F_ODR], odr);
47662306a36Sopenharmony_ci}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci/**
47962306a36Sopenharmony_ci * msa311_wait_for_next_data() - Wait next accel data available after resume
48062306a36Sopenharmony_ci * @msa311: MSA311 internal private state
48162306a36Sopenharmony_ci *
48262306a36Sopenharmony_ci * Return: 0 on success, -EINTR if msleep() was interrupted,
48362306a36Sopenharmony_ci *         -ERRNO in other failures
48462306a36Sopenharmony_ci */
48562306a36Sopenharmony_cistatic int msa311_wait_for_next_data(struct msa311_priv *msa311)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	static const unsigned int unintr_thresh_ms = 20;
48862306a36Sopenharmony_ci	struct device *dev = msa311->dev;
48962306a36Sopenharmony_ci	unsigned long freq_uhz;
49062306a36Sopenharmony_ci	unsigned long wait_ms;
49162306a36Sopenharmony_ci	unsigned int odr;
49262306a36Sopenharmony_ci	int err;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	err = msa311_get_odr(msa311, &odr);
49562306a36Sopenharmony_ci	if (err) {
49662306a36Sopenharmony_ci		dev_err(dev, "can't get actual frequency (%pe)\n",
49762306a36Sopenharmony_ci			ERR_PTR(err));
49862306a36Sopenharmony_ci		return err;
49962306a36Sopenharmony_ci	}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	/*
50262306a36Sopenharmony_ci	 * After msa311 resuming is done, we need to wait for data
50362306a36Sopenharmony_ci	 * to be refreshed by accel logic.
50462306a36Sopenharmony_ci	 * A certain timeout is calculated based on the current ODR value.
50562306a36Sopenharmony_ci	 * If requested timeout isn't so long (let's assume 20ms),
50662306a36Sopenharmony_ci	 * we can wait for next data in uninterruptible sleep.
50762306a36Sopenharmony_ci	 */
50862306a36Sopenharmony_ci	freq_uhz = msa311_odr_table[odr].integral * MICROHZ_PER_HZ +
50962306a36Sopenharmony_ci		   msa311_odr_table[odr].microfract;
51062306a36Sopenharmony_ci	wait_ms = (MICROHZ_PER_HZ / freq_uhz) * MSEC_PER_SEC;
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci	if (wait_ms < unintr_thresh_ms)
51362306a36Sopenharmony_ci		usleep_range(wait_ms * USEC_PER_MSEC,
51462306a36Sopenharmony_ci			     unintr_thresh_ms * USEC_PER_MSEC);
51562306a36Sopenharmony_ci	else if (msleep_interruptible(wait_ms))
51662306a36Sopenharmony_ci		return -EINTR;
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	return 0;
51962306a36Sopenharmony_ci}
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci/**
52262306a36Sopenharmony_ci * msa311_set_pwr_mode() - Install certain MSA311 power mode
52362306a36Sopenharmony_ci * @msa311: MSA311 internal private state
52462306a36Sopenharmony_ci * @mode: Power mode can be equal to NORMAL or SUSPEND
52562306a36Sopenharmony_ci *
52662306a36Sopenharmony_ci * This function should be called under msa311->lock.
52762306a36Sopenharmony_ci *
52862306a36Sopenharmony_ci * Return: 0 on success, -ERRNO on failure
52962306a36Sopenharmony_ci */
53062306a36Sopenharmony_cistatic int msa311_set_pwr_mode(struct msa311_priv *msa311, unsigned int mode)
53162306a36Sopenharmony_ci{
53262306a36Sopenharmony_ci	struct device *dev = msa311->dev;
53362306a36Sopenharmony_ci	unsigned int prev_mode;
53462306a36Sopenharmony_ci	int err;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (mode >= ARRAY_SIZE(msa311_pwr_modes))
53762306a36Sopenharmony_ci		return -EINVAL;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	dev_dbg(dev, "transition to %s mode\n", msa311_pwr_modes[mode]);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	err = regmap_field_read(msa311->fields[F_PWR_MODE], &prev_mode);
54262306a36Sopenharmony_ci	if (err)
54362306a36Sopenharmony_ci		return err;
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_PWR_MODE], mode);
54662306a36Sopenharmony_ci	if (err)
54762306a36Sopenharmony_ci		return err;
54862306a36Sopenharmony_ci
54962306a36Sopenharmony_ci	/* Wait actual data if we wake up */
55062306a36Sopenharmony_ci	if (prev_mode == MSA311_PWR_MODE_SUSPEND &&
55162306a36Sopenharmony_ci	    mode == MSA311_PWR_MODE_NORMAL)
55262306a36Sopenharmony_ci		return msa311_wait_for_next_data(msa311);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	return 0;
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci/**
55862306a36Sopenharmony_ci * msa311_get_axis() - Read MSA311 accel data for certain IIO channel axis spec
55962306a36Sopenharmony_ci * @msa311: MSA311 internal private state
56062306a36Sopenharmony_ci * @chan: IIO channel specification
56162306a36Sopenharmony_ci * @axis: Output accel axis data for requested IIO channel spec
56262306a36Sopenharmony_ci *
56362306a36Sopenharmony_ci * This function should be called under msa311->lock.
56462306a36Sopenharmony_ci *
56562306a36Sopenharmony_ci * Return: 0 on success, -EINVAL for unknown IIO channel specification,
56662306a36Sopenharmony_ci *         -ERRNO in other failures
56762306a36Sopenharmony_ci */
56862306a36Sopenharmony_cistatic int msa311_get_axis(struct msa311_priv *msa311,
56962306a36Sopenharmony_ci			   const struct iio_chan_spec * const chan,
57062306a36Sopenharmony_ci			   __le16 *axis)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	struct device *dev = msa311->dev;
57362306a36Sopenharmony_ci	unsigned int axis_reg;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	if (chan->scan_index < MSA311_SI_X || chan->scan_index > MSA311_SI_Z) {
57662306a36Sopenharmony_ci		dev_err(dev, "invalid scan_index value [%d]\n",
57762306a36Sopenharmony_ci			chan->scan_index);
57862306a36Sopenharmony_ci		return -EINVAL;
57962306a36Sopenharmony_ci	}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	/* Axes data layout has 2 byte gap for each axis starting from X axis */
58262306a36Sopenharmony_ci	axis_reg = MSA311_ACC_X_REG + (chan->scan_index << 1);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	return regmap_bulk_read(msa311->regs, axis_reg, axis, sizeof(*axis));
58562306a36Sopenharmony_ci}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_cistatic int msa311_read_raw_data(struct iio_dev *indio_dev,
58862306a36Sopenharmony_ci				struct iio_chan_spec const *chan,
58962306a36Sopenharmony_ci				int *val, int *val2)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
59262306a36Sopenharmony_ci	struct device *dev = msa311->dev;
59362306a36Sopenharmony_ci	__le16 axis;
59462306a36Sopenharmony_ci	int err;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	err = pm_runtime_resume_and_get(dev);
59762306a36Sopenharmony_ci	if (err)
59862306a36Sopenharmony_ci		return err;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	err = iio_device_claim_direct_mode(indio_dev);
60162306a36Sopenharmony_ci	if (err)
60262306a36Sopenharmony_ci		return err;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
60562306a36Sopenharmony_ci	err = msa311_get_axis(msa311, chan, &axis);
60662306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
60962306a36Sopenharmony_ci
61062306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
61162306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	if (err) {
61462306a36Sopenharmony_ci		dev_err(dev, "can't get axis %s (%pe)\n",
61562306a36Sopenharmony_ci			chan->datasheet_name, ERR_PTR(err));
61662306a36Sopenharmony_ci		return err;
61762306a36Sopenharmony_ci	}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/*
62062306a36Sopenharmony_ci	 * Axis data format is:
62162306a36Sopenharmony_ci	 * ACC_X = (ACC_X_MSB[7:0] << 4) | ACC_X_LSB[7:4]
62262306a36Sopenharmony_ci	 */
62362306a36Sopenharmony_ci	*val = sign_extend32(le16_to_cpu(axis) >> chan->scan_type.shift,
62462306a36Sopenharmony_ci			     chan->scan_type.realbits - 1);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	return IIO_VAL_INT;
62762306a36Sopenharmony_ci}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_cistatic int msa311_read_scale(struct iio_dev *indio_dev, int *val, int *val2)
63062306a36Sopenharmony_ci{
63162306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
63262306a36Sopenharmony_ci	struct device *dev = msa311->dev;
63362306a36Sopenharmony_ci	unsigned int fs;
63462306a36Sopenharmony_ci	int err;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
63762306a36Sopenharmony_ci	err = regmap_field_read(msa311->fields[F_FS], &fs);
63862306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
63962306a36Sopenharmony_ci	if (err) {
64062306a36Sopenharmony_ci		dev_err(dev, "can't get actual scale (%pe)\n", ERR_PTR(err));
64162306a36Sopenharmony_ci		return err;
64262306a36Sopenharmony_ci	}
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	*val = msa311_fs_table[fs].integral;
64562306a36Sopenharmony_ci	*val2 = msa311_fs_table[fs].microfract;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci	return IIO_VAL_INT_PLUS_MICRO;
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_cistatic int msa311_read_samp_freq(struct iio_dev *indio_dev,
65162306a36Sopenharmony_ci				 int *val, int *val2)
65262306a36Sopenharmony_ci{
65362306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
65462306a36Sopenharmony_ci	struct device *dev = msa311->dev;
65562306a36Sopenharmony_ci	unsigned int odr;
65662306a36Sopenharmony_ci	int err;
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
65962306a36Sopenharmony_ci	err = msa311_get_odr(msa311, &odr);
66062306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
66162306a36Sopenharmony_ci	if (err) {
66262306a36Sopenharmony_ci		dev_err(dev, "can't get actual frequency (%pe)\n",
66362306a36Sopenharmony_ci			ERR_PTR(err));
66462306a36Sopenharmony_ci		return err;
66562306a36Sopenharmony_ci	}
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	*val = msa311_odr_table[odr].integral;
66862306a36Sopenharmony_ci	*val2 = msa311_odr_table[odr].microfract;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	return IIO_VAL_INT_PLUS_MICRO;
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_cistatic int msa311_read_raw(struct iio_dev *indio_dev,
67462306a36Sopenharmony_ci			   struct iio_chan_spec const *chan,
67562306a36Sopenharmony_ci			   int *val, int *val2, long mask)
67662306a36Sopenharmony_ci{
67762306a36Sopenharmony_ci	switch (mask) {
67862306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
67962306a36Sopenharmony_ci		return msa311_read_raw_data(indio_dev, chan, val, val2);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
68262306a36Sopenharmony_ci		return msa311_read_scale(indio_dev, val, val2);
68362306a36Sopenharmony_ci
68462306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
68562306a36Sopenharmony_ci		return msa311_read_samp_freq(indio_dev, val, val2);
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci	default:
68862306a36Sopenharmony_ci		return -EINVAL;
68962306a36Sopenharmony_ci	}
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic int msa311_read_avail(struct iio_dev *indio_dev,
69362306a36Sopenharmony_ci			     struct iio_chan_spec const *chan,
69462306a36Sopenharmony_ci			     const int **vals, int *type,
69562306a36Sopenharmony_ci			     int *length, long mask)
69662306a36Sopenharmony_ci{
69762306a36Sopenharmony_ci	switch (mask) {
69862306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
69962306a36Sopenharmony_ci		*vals = (int *)msa311_odr_table;
70062306a36Sopenharmony_ci		*type = IIO_VAL_INT_PLUS_MICRO;
70162306a36Sopenharmony_ci		/* ODR value has 2 ints (integer and fractional parts) */
70262306a36Sopenharmony_ci		*length = ARRAY_SIZE(msa311_odr_table) * 2;
70362306a36Sopenharmony_ci		return IIO_AVAIL_LIST;
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
70662306a36Sopenharmony_ci		*vals = (int *)msa311_fs_table;
70762306a36Sopenharmony_ci		*type = IIO_VAL_INT_PLUS_MICRO;
70862306a36Sopenharmony_ci		/* FS value has 2 ints (integer and fractional parts) */
70962306a36Sopenharmony_ci		*length = ARRAY_SIZE(msa311_fs_table) * 2;
71062306a36Sopenharmony_ci		return IIO_AVAIL_LIST;
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci	default:
71362306a36Sopenharmony_ci		return -EINVAL;
71462306a36Sopenharmony_ci	}
71562306a36Sopenharmony_ci}
71662306a36Sopenharmony_ci
71762306a36Sopenharmony_cistatic int msa311_write_scale(struct iio_dev *indio_dev, int val, int val2)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
72062306a36Sopenharmony_ci	struct device *dev = msa311->dev;
72162306a36Sopenharmony_ci	unsigned int fs;
72262306a36Sopenharmony_ci	int err;
72362306a36Sopenharmony_ci
72462306a36Sopenharmony_ci	/* We do not have fs >= 1, so skip such values */
72562306a36Sopenharmony_ci	if (val)
72662306a36Sopenharmony_ci		return 0;
72762306a36Sopenharmony_ci
72862306a36Sopenharmony_ci	err = pm_runtime_resume_and_get(dev);
72962306a36Sopenharmony_ci	if (err)
73062306a36Sopenharmony_ci		return err;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	err = -EINVAL;
73362306a36Sopenharmony_ci	for (fs = 0; fs < ARRAY_SIZE(msa311_fs_table); fs++)
73462306a36Sopenharmony_ci		/* Do not check msa311_fs_table[fs].integral, it's always 0 */
73562306a36Sopenharmony_ci		if (val2 == msa311_fs_table[fs].microfract) {
73662306a36Sopenharmony_ci			mutex_lock(&msa311->lock);
73762306a36Sopenharmony_ci			err = regmap_field_write(msa311->fields[F_FS], fs);
73862306a36Sopenharmony_ci			mutex_unlock(&msa311->lock);
73962306a36Sopenharmony_ci			break;
74062306a36Sopenharmony_ci		}
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
74362306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	if (err)
74662306a36Sopenharmony_ci		dev_err(dev, "can't update scale (%pe)\n", ERR_PTR(err));
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_ci	return err;
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic int msa311_write_samp_freq(struct iio_dev *indio_dev, int val, int val2)
75262306a36Sopenharmony_ci{
75362306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
75462306a36Sopenharmony_ci	struct device *dev = msa311->dev;
75562306a36Sopenharmony_ci	unsigned int odr;
75662306a36Sopenharmony_ci	int err;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	err = pm_runtime_resume_and_get(dev);
75962306a36Sopenharmony_ci	if (err)
76062306a36Sopenharmony_ci		return err;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	/*
76362306a36Sopenharmony_ci	 * Sampling frequency changing is prohibited when buffer mode is
76462306a36Sopenharmony_ci	 * enabled, because sometimes MSA311 chip returns outliers during
76562306a36Sopenharmony_ci	 * frequency values growing up in the read operation moment.
76662306a36Sopenharmony_ci	 */
76762306a36Sopenharmony_ci	err = iio_device_claim_direct_mode(indio_dev);
76862306a36Sopenharmony_ci	if (err)
76962306a36Sopenharmony_ci		return err;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	err = -EINVAL;
77262306a36Sopenharmony_ci	for (odr = 0; odr < ARRAY_SIZE(msa311_odr_table); odr++)
77362306a36Sopenharmony_ci		if (val == msa311_odr_table[odr].integral &&
77462306a36Sopenharmony_ci		    val2 == msa311_odr_table[odr].microfract) {
77562306a36Sopenharmony_ci			mutex_lock(&msa311->lock);
77662306a36Sopenharmony_ci			err = msa311_set_odr(msa311, odr);
77762306a36Sopenharmony_ci			mutex_unlock(&msa311->lock);
77862306a36Sopenharmony_ci			break;
77962306a36Sopenharmony_ci		}
78062306a36Sopenharmony_ci
78162306a36Sopenharmony_ci	iio_device_release_direct_mode(indio_dev);
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
78462306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	if (err)
78762306a36Sopenharmony_ci		dev_err(dev, "can't update frequency (%pe)\n", ERR_PTR(err));
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	return err;
79062306a36Sopenharmony_ci}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_cistatic int msa311_write_raw(struct iio_dev *indio_dev,
79362306a36Sopenharmony_ci			    struct iio_chan_spec const *chan,
79462306a36Sopenharmony_ci			    int val, int val2, long mask)
79562306a36Sopenharmony_ci{
79662306a36Sopenharmony_ci	switch (mask) {
79762306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
79862306a36Sopenharmony_ci		return msa311_write_scale(indio_dev, val, val2);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	case IIO_CHAN_INFO_SAMP_FREQ:
80162306a36Sopenharmony_ci		return msa311_write_samp_freq(indio_dev, val, val2);
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	default:
80462306a36Sopenharmony_ci		return -EINVAL;
80562306a36Sopenharmony_ci	}
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_cistatic int msa311_debugfs_reg_access(struct iio_dev *indio_dev,
80962306a36Sopenharmony_ci				     unsigned int reg, unsigned int writeval,
81062306a36Sopenharmony_ci				     unsigned int *readval)
81162306a36Sopenharmony_ci{
81262306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
81362306a36Sopenharmony_ci	struct device *dev = msa311->dev;
81462306a36Sopenharmony_ci	int err;
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	if (reg > regmap_get_max_register(msa311->regs))
81762306a36Sopenharmony_ci		return -EINVAL;
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ci	err = pm_runtime_resume_and_get(dev);
82062306a36Sopenharmony_ci	if (err)
82162306a36Sopenharmony_ci		return err;
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
82462306a36Sopenharmony_ci
82562306a36Sopenharmony_ci	if (readval)
82662306a36Sopenharmony_ci		err = regmap_read(msa311->regs, reg, readval);
82762306a36Sopenharmony_ci	else
82862306a36Sopenharmony_ci		err = regmap_write(msa311->regs, reg, writeval);
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
83362306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	if (err)
83662306a36Sopenharmony_ci		dev_err(dev, "can't %s register %u from debugfs (%pe)\n",
83762306a36Sopenharmony_ci			str_read_write(readval), reg, ERR_PTR(err));
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	return err;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic int msa311_buffer_preenable(struct iio_dev *indio_dev)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
84562306a36Sopenharmony_ci	struct device *dev = msa311->dev;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	return pm_runtime_resume_and_get(dev);
84862306a36Sopenharmony_ci}
84962306a36Sopenharmony_ci
85062306a36Sopenharmony_cistatic int msa311_buffer_postdisable(struct iio_dev *indio_dev)
85162306a36Sopenharmony_ci{
85262306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
85362306a36Sopenharmony_ci	struct device *dev = msa311->dev;
85462306a36Sopenharmony_ci
85562306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
85662306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	return 0;
85962306a36Sopenharmony_ci}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_cistatic int msa311_set_new_data_trig_state(struct iio_trigger *trig, bool state)
86262306a36Sopenharmony_ci{
86362306a36Sopenharmony_ci	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
86462306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
86562306a36Sopenharmony_ci	struct device *dev = msa311->dev;
86662306a36Sopenharmony_ci	int err;
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
86962306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_NEW_DATA_INT_EN], state);
87062306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
87162306a36Sopenharmony_ci	if (err)
87262306a36Sopenharmony_ci		dev_err(dev,
87362306a36Sopenharmony_ci			"can't %s buffer due to new_data_int failure (%pe)\n",
87462306a36Sopenharmony_ci			str_enable_disable(state), ERR_PTR(err));
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	return err;
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic int msa311_validate_device(struct iio_trigger *trig,
88062306a36Sopenharmony_ci				  struct iio_dev *indio_dev)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci	return iio_trigger_get_drvdata(trig) == indio_dev ? 0 : -EINVAL;
88362306a36Sopenharmony_ci}
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_cistatic irqreturn_t msa311_buffer_thread(int irq, void *p)
88662306a36Sopenharmony_ci{
88762306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
88862306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(pf->indio_dev);
88962306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
89062306a36Sopenharmony_ci	const struct iio_chan_spec *chan;
89162306a36Sopenharmony_ci	struct device *dev = msa311->dev;
89262306a36Sopenharmony_ci	int bit, err, i = 0;
89362306a36Sopenharmony_ci	__le16 axis;
89462306a36Sopenharmony_ci	struct {
89562306a36Sopenharmony_ci		__le16 channels[MSA311_SI_Z + 1];
89662306a36Sopenharmony_ci		s64 ts __aligned(8);
89762306a36Sopenharmony_ci	} buf;
89862306a36Sopenharmony_ci
89962306a36Sopenharmony_ci	memset(&buf, 0, sizeof(buf));
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
90262306a36Sopenharmony_ci
90362306a36Sopenharmony_ci	for_each_set_bit(bit, indio_dev->active_scan_mask,
90462306a36Sopenharmony_ci			 indio_dev->masklength) {
90562306a36Sopenharmony_ci		chan = &msa311_channels[bit];
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci		err = msa311_get_axis(msa311, chan, &axis);
90862306a36Sopenharmony_ci		if (err) {
90962306a36Sopenharmony_ci			mutex_unlock(&msa311->lock);
91062306a36Sopenharmony_ci			dev_err(dev, "can't get axis %s (%pe)\n",
91162306a36Sopenharmony_ci				chan->datasheet_name, ERR_PTR(err));
91262306a36Sopenharmony_ci			goto notify_done;
91362306a36Sopenharmony_ci		}
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci		buf.channels[i++] = axis;
91662306a36Sopenharmony_ci	}
91762306a36Sopenharmony_ci
91862306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	iio_push_to_buffers_with_timestamp(indio_dev, &buf,
92162306a36Sopenharmony_ci					   iio_get_time_ns(indio_dev));
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cinotify_done:
92462306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	return IRQ_HANDLED;
92762306a36Sopenharmony_ci}
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_cistatic irqreturn_t msa311_irq_thread(int irq, void *p)
93062306a36Sopenharmony_ci{
93162306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(p);
93262306a36Sopenharmony_ci	unsigned int new_data_int_enabled;
93362306a36Sopenharmony_ci	struct device *dev = msa311->dev;
93462306a36Sopenharmony_ci	int err;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	/*
93962306a36Sopenharmony_ci	 * We do not check NEW_DATA int status, because based on the
94062306a36Sopenharmony_ci	 * specification it's cleared automatically after a fixed time.
94162306a36Sopenharmony_ci	 * So just check that is enabled by driver logic.
94262306a36Sopenharmony_ci	 */
94362306a36Sopenharmony_ci	err = regmap_field_read(msa311->fields[F_NEW_DATA_INT_EN],
94462306a36Sopenharmony_ci				&new_data_int_enabled);
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
94762306a36Sopenharmony_ci	if (err) {
94862306a36Sopenharmony_ci		dev_err(dev, "can't read new_data interrupt state (%pe)\n",
94962306a36Sopenharmony_ci			ERR_PTR(err));
95062306a36Sopenharmony_ci		return IRQ_NONE;
95162306a36Sopenharmony_ci	}
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	if (new_data_int_enabled)
95462306a36Sopenharmony_ci		iio_trigger_poll_nested(msa311->new_data_trig);
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	return IRQ_HANDLED;
95762306a36Sopenharmony_ci}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_cistatic const struct iio_info msa311_info = {
96062306a36Sopenharmony_ci	.read_raw = msa311_read_raw,
96162306a36Sopenharmony_ci	.read_avail = msa311_read_avail,
96262306a36Sopenharmony_ci	.write_raw = msa311_write_raw,
96362306a36Sopenharmony_ci	.debugfs_reg_access = msa311_debugfs_reg_access,
96462306a36Sopenharmony_ci};
96562306a36Sopenharmony_ci
96662306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops msa311_buffer_setup_ops = {
96762306a36Sopenharmony_ci	.preenable = msa311_buffer_preenable,
96862306a36Sopenharmony_ci	.postdisable = msa311_buffer_postdisable,
96962306a36Sopenharmony_ci};
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_cistatic const struct iio_trigger_ops msa311_new_data_trig_ops = {
97262306a36Sopenharmony_ci	.set_trigger_state = msa311_set_new_data_trig_state,
97362306a36Sopenharmony_ci	.validate_device = msa311_validate_device,
97462306a36Sopenharmony_ci};
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_cistatic int msa311_check_partid(struct msa311_priv *msa311)
97762306a36Sopenharmony_ci{
97862306a36Sopenharmony_ci	struct device *dev = msa311->dev;
97962306a36Sopenharmony_ci	unsigned int partid;
98062306a36Sopenharmony_ci	int err;
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	err = regmap_read(msa311->regs, MSA311_PARTID_REG, &partid);
98362306a36Sopenharmony_ci	if (err)
98462306a36Sopenharmony_ci		return dev_err_probe(dev, err, "failed to read partid\n");
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	if (partid != MSA311_WHO_AM_I)
98762306a36Sopenharmony_ci		dev_warn(dev, "invalid partid (%#x), expected (%#x)\n",
98862306a36Sopenharmony_ci			 partid, MSA311_WHO_AM_I);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	msa311->chip_name = devm_kasprintf(dev, GFP_KERNEL,
99162306a36Sopenharmony_ci					   "msa311-%02x", partid);
99262306a36Sopenharmony_ci	if (!msa311->chip_name)
99362306a36Sopenharmony_ci		return dev_err_probe(dev, -ENOMEM, "can't alloc chip name\n");
99462306a36Sopenharmony_ci
99562306a36Sopenharmony_ci	return 0;
99662306a36Sopenharmony_ci}
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_cistatic int msa311_soft_reset(struct msa311_priv *msa311)
99962306a36Sopenharmony_ci{
100062306a36Sopenharmony_ci	struct device *dev = msa311->dev;
100162306a36Sopenharmony_ci	int err;
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci	err = regmap_write(msa311->regs, MSA311_SOFT_RESET_REG,
100462306a36Sopenharmony_ci			   MSA311_GENMASK(F_SOFT_RESET_I2C) |
100562306a36Sopenharmony_ci			   MSA311_GENMASK(F_SOFT_RESET_SPI));
100662306a36Sopenharmony_ci	if (err)
100762306a36Sopenharmony_ci		return dev_err_probe(dev, err, "can't soft reset all logic\n");
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	return 0;
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic int msa311_chip_init(struct msa311_priv *msa311)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	struct device *dev = msa311->dev;
101562306a36Sopenharmony_ci	const char zero_bulk[2] = { };
101662306a36Sopenharmony_ci	int err;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci	err = regmap_write(msa311->regs, MSA311_RANGE_REG, MSA311_FS_16G);
101962306a36Sopenharmony_ci	if (err)
102062306a36Sopenharmony_ci		return dev_err_probe(dev, err, "failed to setup accel range\n");
102162306a36Sopenharmony_ci
102262306a36Sopenharmony_ci	/* Disable all interrupts by default */
102362306a36Sopenharmony_ci	err = regmap_bulk_write(msa311->regs, MSA311_INT_SET_0_REG,
102462306a36Sopenharmony_ci				zero_bulk, sizeof(zero_bulk));
102562306a36Sopenharmony_ci	if (err)
102662306a36Sopenharmony_ci		return dev_err_probe(dev, err,
102762306a36Sopenharmony_ci				     "can't disable set0/set1 interrupts\n");
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci	/* Unmap all INT1 interrupts by default */
103062306a36Sopenharmony_ci	err = regmap_bulk_write(msa311->regs, MSA311_INT_MAP_0_REG,
103162306a36Sopenharmony_ci				zero_bulk, sizeof(zero_bulk));
103262306a36Sopenharmony_ci	if (err)
103362306a36Sopenharmony_ci		return dev_err_probe(dev, err,
103462306a36Sopenharmony_ci				     "failed to unmap map0/map1 interrupts\n");
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	/* Disable all axes by default */
103762306a36Sopenharmony_ci	err = regmap_update_bits(msa311->regs, MSA311_ODR_REG,
103862306a36Sopenharmony_ci				 MSA311_GENMASK(F_X_AXIS_DIS) |
103962306a36Sopenharmony_ci				 MSA311_GENMASK(F_Y_AXIS_DIS) |
104062306a36Sopenharmony_ci				 MSA311_GENMASK(F_Z_AXIS_DIS), 0);
104162306a36Sopenharmony_ci	if (err)
104262306a36Sopenharmony_ci		return dev_err_probe(dev, err, "can't enable all axes\n");
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	err = msa311_set_odr(msa311, MSA311_ODR_125_HZ);
104562306a36Sopenharmony_ci	if (err)
104662306a36Sopenharmony_ci		return dev_err_probe(dev, err,
104762306a36Sopenharmony_ci				     "failed to set accel frequency\n");
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	return 0;
105062306a36Sopenharmony_ci}
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic int msa311_setup_interrupts(struct msa311_priv *msa311)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	struct device *dev = msa311->dev;
105562306a36Sopenharmony_ci	struct i2c_client *i2c = to_i2c_client(dev);
105662306a36Sopenharmony_ci	struct iio_dev *indio_dev = i2c_get_clientdata(i2c);
105762306a36Sopenharmony_ci	struct iio_trigger *trig;
105862306a36Sopenharmony_ci	int err;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/* Keep going without interrupts if no initialized I2C IRQ */
106162306a36Sopenharmony_ci	if (i2c->irq <= 0)
106262306a36Sopenharmony_ci		return 0;
106362306a36Sopenharmony_ci
106462306a36Sopenharmony_ci	err = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
106562306a36Sopenharmony_ci					msa311_irq_thread, IRQF_ONESHOT,
106662306a36Sopenharmony_ci					msa311->chip_name, indio_dev);
106762306a36Sopenharmony_ci	if (err)
106862306a36Sopenharmony_ci		return dev_err_probe(dev, err, "failed to request IRQ\n");
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	trig = devm_iio_trigger_alloc(dev, "%s-new-data", msa311->chip_name);
107162306a36Sopenharmony_ci	if (!trig)
107262306a36Sopenharmony_ci		return dev_err_probe(dev, -ENOMEM,
107362306a36Sopenharmony_ci				     "can't allocate newdata trigger\n");
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	msa311->new_data_trig = trig;
107662306a36Sopenharmony_ci	msa311->new_data_trig->ops = &msa311_new_data_trig_ops;
107762306a36Sopenharmony_ci	iio_trigger_set_drvdata(msa311->new_data_trig, indio_dev);
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	err = devm_iio_trigger_register(dev, msa311->new_data_trig);
108062306a36Sopenharmony_ci	if (err)
108162306a36Sopenharmony_ci		return dev_err_probe(dev, err,
108262306a36Sopenharmony_ci				     "can't register newdata trigger\n");
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_INT1_OD],
108562306a36Sopenharmony_ci				 MSA311_INT1_OD_PUSH_PULL);
108662306a36Sopenharmony_ci	if (err)
108762306a36Sopenharmony_ci		return dev_err_probe(dev, err,
108862306a36Sopenharmony_ci				     "can't enable push-pull interrupt\n");
108962306a36Sopenharmony_ci
109062306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_INT1_LVL],
109162306a36Sopenharmony_ci				 MSA311_INT1_LVL_HIGH);
109262306a36Sopenharmony_ci	if (err)
109362306a36Sopenharmony_ci		return dev_err_probe(dev, err,
109462306a36Sopenharmony_ci				     "can't set active interrupt level\n");
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_LATCH_INT],
109762306a36Sopenharmony_ci				 MSA311_LATCH_INT_LATCHED);
109862306a36Sopenharmony_ci	if (err)
109962306a36Sopenharmony_ci		return dev_err_probe(dev, err,
110062306a36Sopenharmony_ci				     "can't latch interrupt\n");
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_RESET_INT], 1);
110362306a36Sopenharmony_ci	if (err)
110462306a36Sopenharmony_ci		return dev_err_probe(dev, err,
110562306a36Sopenharmony_ci				     "can't reset interrupt\n");
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	err = regmap_field_write(msa311->fields[F_INT1_NEW_DATA], 1);
110862306a36Sopenharmony_ci	if (err)
110962306a36Sopenharmony_ci		return dev_err_probe(dev, err,
111062306a36Sopenharmony_ci				     "can't map new data interrupt\n");
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	return 0;
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic int msa311_regmap_init(struct msa311_priv *msa311)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	struct regmap_field **fields = msa311->fields;
111862306a36Sopenharmony_ci	struct device *dev = msa311->dev;
111962306a36Sopenharmony_ci	struct i2c_client *i2c = to_i2c_client(dev);
112062306a36Sopenharmony_ci	struct regmap *regmap;
112162306a36Sopenharmony_ci	int i;
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	regmap = devm_regmap_init_i2c(i2c, &msa311_regmap_config);
112462306a36Sopenharmony_ci	if (IS_ERR(regmap))
112562306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(regmap),
112662306a36Sopenharmony_ci				     "failed to register i2c regmap\n");
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	msa311->regs = regmap;
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	for (i = 0; i < F_MAX_FIELDS; i++) {
113162306a36Sopenharmony_ci		fields[i] = devm_regmap_field_alloc(dev,
113262306a36Sopenharmony_ci						    msa311->regs,
113362306a36Sopenharmony_ci						    msa311_reg_fields[i]);
113462306a36Sopenharmony_ci		if (IS_ERR(msa311->fields[i]))
113562306a36Sopenharmony_ci			return dev_err_probe(dev, PTR_ERR(msa311->fields[i]),
113662306a36Sopenharmony_ci					     "can't alloc field[%d]\n", i);
113762306a36Sopenharmony_ci	}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	return 0;
114062306a36Sopenharmony_ci}
114162306a36Sopenharmony_ci
114262306a36Sopenharmony_cistatic void msa311_powerdown(void *msa311)
114362306a36Sopenharmony_ci{
114462306a36Sopenharmony_ci	msa311_set_pwr_mode(msa311, MSA311_PWR_MODE_SUSPEND);
114562306a36Sopenharmony_ci}
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_cistatic int msa311_probe(struct i2c_client *i2c)
114862306a36Sopenharmony_ci{
114962306a36Sopenharmony_ci	struct device *dev = &i2c->dev;
115062306a36Sopenharmony_ci	struct msa311_priv *msa311;
115162306a36Sopenharmony_ci	struct iio_dev *indio_dev;
115262306a36Sopenharmony_ci	int err;
115362306a36Sopenharmony_ci
115462306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*msa311));
115562306a36Sopenharmony_ci	if (!indio_dev)
115662306a36Sopenharmony_ci		return dev_err_probe(dev, -ENOMEM,
115762306a36Sopenharmony_ci				     "IIO device allocation failed\n");
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	msa311 = iio_priv(indio_dev);
116062306a36Sopenharmony_ci	msa311->dev = dev;
116162306a36Sopenharmony_ci	i2c_set_clientdata(i2c, indio_dev);
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	err = msa311_regmap_init(msa311);
116462306a36Sopenharmony_ci	if (err)
116562306a36Sopenharmony_ci		return err;
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	mutex_init(&msa311->lock);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	err = devm_regulator_get_enable(dev, "vdd");
117062306a36Sopenharmony_ci	if (err)
117162306a36Sopenharmony_ci		return dev_err_probe(dev, err, "can't get vdd supply\n");
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	err = msa311_check_partid(msa311);
117462306a36Sopenharmony_ci	if (err)
117562306a36Sopenharmony_ci		return err;
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci	err = msa311_soft_reset(msa311);
117862306a36Sopenharmony_ci	if (err)
117962306a36Sopenharmony_ci		return err;
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ci	err = msa311_set_pwr_mode(msa311, MSA311_PWR_MODE_NORMAL);
118262306a36Sopenharmony_ci	if (err)
118362306a36Sopenharmony_ci		return dev_err_probe(dev, err, "failed to power on device\n");
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	/*
118662306a36Sopenharmony_ci	 * Register powerdown deferred callback which suspends the chip
118762306a36Sopenharmony_ci	 * after module unloaded.
118862306a36Sopenharmony_ci	 *
118962306a36Sopenharmony_ci	 * MSA311 should be in SUSPEND mode in the two cases:
119062306a36Sopenharmony_ci	 * 1) When driver is loaded, but we do not have any data or
119162306a36Sopenharmony_ci	 *    configuration requests to it (we are solving it using
119262306a36Sopenharmony_ci	 *    autosuspend feature).
119362306a36Sopenharmony_ci	 * 2) When driver is unloaded and device is not used (devm action is
119462306a36Sopenharmony_ci	 *    used in this case).
119562306a36Sopenharmony_ci	 */
119662306a36Sopenharmony_ci	err = devm_add_action_or_reset(dev, msa311_powerdown, msa311);
119762306a36Sopenharmony_ci	if (err)
119862306a36Sopenharmony_ci		return dev_err_probe(dev, err, "can't add powerdown action\n");
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	err = pm_runtime_set_active(dev);
120162306a36Sopenharmony_ci	if (err)
120262306a36Sopenharmony_ci		return err;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	err = devm_pm_runtime_enable(dev);
120562306a36Sopenharmony_ci	if (err)
120662306a36Sopenharmony_ci		return err;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	pm_runtime_get_noresume(dev);
120962306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, MSA311_PWR_SLEEP_DELAY_MS);
121062306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	err = msa311_chip_init(msa311);
121362306a36Sopenharmony_ci	if (err)
121462306a36Sopenharmony_ci		return err;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
121762306a36Sopenharmony_ci	indio_dev->channels = msa311_channels;
121862306a36Sopenharmony_ci	indio_dev->num_channels = ARRAY_SIZE(msa311_channels);
121962306a36Sopenharmony_ci	indio_dev->name = msa311->chip_name;
122062306a36Sopenharmony_ci	indio_dev->info = &msa311_info;
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	err = devm_iio_triggered_buffer_setup(dev, indio_dev,
122362306a36Sopenharmony_ci					      iio_pollfunc_store_time,
122462306a36Sopenharmony_ci					      msa311_buffer_thread,
122562306a36Sopenharmony_ci					      &msa311_buffer_setup_ops);
122662306a36Sopenharmony_ci	if (err)
122762306a36Sopenharmony_ci		return dev_err_probe(dev, err,
122862306a36Sopenharmony_ci				     "can't setup IIO trigger buffer\n");
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	err = msa311_setup_interrupts(msa311);
123162306a36Sopenharmony_ci	if (err)
123262306a36Sopenharmony_ci		return err;
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
123562306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
123662306a36Sopenharmony_ci
123762306a36Sopenharmony_ci	err = devm_iio_device_register(dev, indio_dev);
123862306a36Sopenharmony_ci	if (err)
123962306a36Sopenharmony_ci		return dev_err_probe(dev, err, "IIO device register failed\n");
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	return 0;
124262306a36Sopenharmony_ci}
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_cistatic int msa311_runtime_suspend(struct device *dev)
124562306a36Sopenharmony_ci{
124662306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
124762306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
124862306a36Sopenharmony_ci	int err;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
125162306a36Sopenharmony_ci	err = msa311_set_pwr_mode(msa311, MSA311_PWR_MODE_SUSPEND);
125262306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
125362306a36Sopenharmony_ci	if (err)
125462306a36Sopenharmony_ci		dev_err(dev, "failed to power off device (%pe)\n",
125562306a36Sopenharmony_ci			ERR_PTR(err));
125662306a36Sopenharmony_ci
125762306a36Sopenharmony_ci	return err;
125862306a36Sopenharmony_ci}
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_cistatic int msa311_runtime_resume(struct device *dev)
126162306a36Sopenharmony_ci{
126262306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
126362306a36Sopenharmony_ci	struct msa311_priv *msa311 = iio_priv(indio_dev);
126462306a36Sopenharmony_ci	int err;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	mutex_lock(&msa311->lock);
126762306a36Sopenharmony_ci	err = msa311_set_pwr_mode(msa311, MSA311_PWR_MODE_NORMAL);
126862306a36Sopenharmony_ci	mutex_unlock(&msa311->lock);
126962306a36Sopenharmony_ci	if (err)
127062306a36Sopenharmony_ci		dev_err(dev, "failed to power on device (%pe)\n",
127162306a36Sopenharmony_ci			ERR_PTR(err));
127262306a36Sopenharmony_ci
127362306a36Sopenharmony_ci	return err;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_cistatic DEFINE_RUNTIME_DEV_PM_OPS(msa311_pm_ops, msa311_runtime_suspend,
127762306a36Sopenharmony_ci				 msa311_runtime_resume, NULL);
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_cistatic const struct i2c_device_id msa311_i2c_id[] = {
128062306a36Sopenharmony_ci	{ .name = "msa311" },
128162306a36Sopenharmony_ci	{ }
128262306a36Sopenharmony_ci};
128362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, msa311_i2c_id);
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_cistatic const struct of_device_id msa311_of_match[] = {
128662306a36Sopenharmony_ci	{ .compatible = "memsensing,msa311" },
128762306a36Sopenharmony_ci	{ }
128862306a36Sopenharmony_ci};
128962306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, msa311_of_match);
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_cistatic struct i2c_driver msa311_driver = {
129262306a36Sopenharmony_ci	.driver = {
129362306a36Sopenharmony_ci		.name = "msa311",
129462306a36Sopenharmony_ci		.of_match_table = msa311_of_match,
129562306a36Sopenharmony_ci		.pm = pm_ptr(&msa311_pm_ops),
129662306a36Sopenharmony_ci	},
129762306a36Sopenharmony_ci	.probe		= msa311_probe,
129862306a36Sopenharmony_ci	.id_table	= msa311_i2c_id,
129962306a36Sopenharmony_ci};
130062306a36Sopenharmony_cimodule_i2c_driver(msa311_driver);
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ciMODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
130362306a36Sopenharmony_ciMODULE_DESCRIPTION("MEMSensing MSA311 3-axis accelerometer driver");
130462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
1305