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