| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Core IIO driver for Bosch BMA400 triaxial acceleration sensor.
- *
- * Copyright 2019 Dan Robertson <dan@dlrobertson.com>
- *
- * TODO:
- * - Support for power management
- * - Support events and interrupts
- * - Create channel for step count
- * - Create channel for sensor time
- */
- #include <linux/bitfield.h>
- #include <linux/bitops.h>
- #include <linux/cleanup.h>
- #include <linux/device.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/mutex.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- #include <linux/slab.h>
- #include <linux/unaligned.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/buffer.h>
- #include <linux/iio/events.h>
- #include <linux/iio/sysfs.h>
- #include <linux/iio/trigger.h>
- #include <linux/iio/trigger_consumer.h>
- #include <linux/iio/triggered_buffer.h>
- #include "bma400.h"
- /*
- * The G-range selection may be one of 2g, 4g, 8, or 16g. The scale may
- * be selected with the acc_range bits of the ACC_CONFIG1 register.
- * NB: This buffer is populated in the device init.
- */
- static int bma400_scales[8];
- /*
- * See the ACC_CONFIG1 section of the datasheet.
- * NB: This buffer is populated in the device init.
- */
- static int bma400_sample_freqs[14];
- static const int bma400_osr_range[] = { 0, 1, 3 };
- static int tap_reset_timeout[BMA400_TAP_TIM_LIST_LEN] = {
- 300000,
- 400000,
- 500000,
- 600000
- };
- static int tap_max2min_time[BMA400_TAP_TIM_LIST_LEN] = {
- 30000,
- 45000,
- 60000,
- 90000
- };
- static int double_tap2_min_delay[BMA400_TAP_TIM_LIST_LEN] = {
- 20000,
- 40000,
- 60000,
- 80000
- };
- /* See the ACC_CONFIG0 section of the datasheet */
- enum bma400_power_mode {
- POWER_MODE_SLEEP = 0x00,
- POWER_MODE_LOW = 0x01,
- POWER_MODE_NORMAL = 0x02,
- POWER_MODE_INVALID = 0x03,
- };
- enum bma400_scan {
- BMA400_ACCL_X,
- BMA400_ACCL_Y,
- BMA400_ACCL_Z,
- BMA400_TEMP,
- };
- struct bma400_sample_freq {
- int hz;
- int uhz;
- };
- enum bma400_activity {
- BMA400_STILL,
- BMA400_WALKING,
- BMA400_RUNNING,
- };
- struct bma400_data {
- struct device *dev;
- struct regmap *regmap;
- struct mutex mutex; /* data register lock */
- struct iio_mount_matrix orientation;
- enum bma400_power_mode power_mode;
- struct bma400_sample_freq sample_freq;
- int oversampling_ratio;
- int scale;
- struct iio_trigger *trig;
- int steps_enabled;
- bool step_event_en;
- bool activity_event_en;
- unsigned int generic_event_en;
- unsigned int tap_event_en_bitmask;
- /* Correct time stamp alignment */
- struct {
- __le16 buff[3];
- u8 temperature;
- aligned_s64 ts;
- } buffer __aligned(IIO_DMA_MINALIGN);
- __le16 status;
- __be16 duration;
- };
- struct bma400_genintr_info {
- enum bma400_generic_intr genintr;
- unsigned int intrmask;
- enum iio_event_direction dir;
- enum bma400_detect_criterion detect_mode;
- };
- /* Lookup struct for determining GEN1/GEN2 based on dir */
- static const struct bma400_genintr_info bma400_genintrs[] = {
- [IIO_EV_DIR_RISING] = {
- .genintr = BMA400_GEN1_INTR,
- .intrmask = BMA400_INT_CONFIG0_GEN1_MASK,
- .dir = IIO_EV_DIR_RISING,
- .detect_mode = BMA400_DETECT_ACTIVITY,
- },
- [IIO_EV_DIR_FALLING] = {
- .genintr = BMA400_GEN2_INTR,
- .intrmask = BMA400_INT_CONFIG0_GEN2_MASK,
- .dir = IIO_EV_DIR_FALLING,
- .detect_mode = BMA400_DETECT_INACTIVITY,
- }
- };
- static inline const struct bma400_genintr_info *
- get_bma400_genintr_info(enum iio_event_direction dir)
- {
- switch (dir) {
- case IIO_EV_DIR_RISING:
- case IIO_EV_DIR_FALLING:
- return &bma400_genintrs[dir];
- default:
- return NULL;
- };
- }
- static bool bma400_is_writable_reg(struct device *dev, unsigned int reg)
- {
- switch (reg) {
- case BMA400_CHIP_ID_REG:
- case BMA400_ERR_REG:
- case BMA400_STATUS_REG:
- case BMA400_ACC_X_LSB_REG:
- case BMA400_ACC_X_MSB_REG:
- case BMA400_ACC_Y_LSB_REG:
- case BMA400_ACC_Y_MSB_REG:
- case BMA400_ACC_Z_LSB_REG:
- case BMA400_ACC_Z_MSB_REG:
- case BMA400_SENSOR_TIME0_REG:
- case BMA400_SENSOR_TIME1_REG:
- case BMA400_SENSOR_TIME2_REG:
- case BMA400_EVENT_REG:
- case BMA400_INT_STAT0_REG:
- case BMA400_INT_STAT1_REG:
- case BMA400_INT_STAT2_REG:
- case BMA400_TEMP_DATA_REG:
- case BMA400_FIFO_LENGTH0_REG:
- case BMA400_FIFO_LENGTH1_REG:
- case BMA400_FIFO_DATA_REG:
- case BMA400_STEP_CNT0_REG:
- case BMA400_STEP_CNT1_REG:
- case BMA400_STEP_CNT3_REG:
- case BMA400_STEP_STAT_REG:
- return false;
- default:
- return true;
- }
- }
- static bool bma400_is_volatile_reg(struct device *dev, unsigned int reg)
- {
- switch (reg) {
- case BMA400_ERR_REG:
- case BMA400_STATUS_REG:
- case BMA400_ACC_X_LSB_REG:
- case BMA400_ACC_X_MSB_REG:
- case BMA400_ACC_Y_LSB_REG:
- case BMA400_ACC_Y_MSB_REG:
- case BMA400_ACC_Z_LSB_REG:
- case BMA400_ACC_Z_MSB_REG:
- case BMA400_SENSOR_TIME0_REG:
- case BMA400_SENSOR_TIME1_REG:
- case BMA400_SENSOR_TIME2_REG:
- case BMA400_EVENT_REG:
- case BMA400_INT_STAT0_REG:
- case BMA400_INT_STAT1_REG:
- case BMA400_INT_STAT2_REG:
- case BMA400_TEMP_DATA_REG:
- case BMA400_FIFO_LENGTH0_REG:
- case BMA400_FIFO_LENGTH1_REG:
- case BMA400_FIFO_DATA_REG:
- case BMA400_STEP_CNT0_REG:
- case BMA400_STEP_CNT1_REG:
- case BMA400_STEP_CNT3_REG:
- case BMA400_STEP_STAT_REG:
- return true;
- default:
- return false;
- }
- }
- const struct regmap_config bma400_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- .max_register = BMA400_CMD_REG,
- .cache_type = REGCACHE_MAPLE,
- .writeable_reg = bma400_is_writable_reg,
- .volatile_reg = bma400_is_volatile_reg,
- };
- EXPORT_SYMBOL_NS(bma400_regmap_config, "IIO_BMA400");
- static const struct iio_mount_matrix *
- bma400_accel_get_mount_matrix(const struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- return &data->orientation;
- }
- static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
- IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma400_accel_get_mount_matrix),
- { }
- };
- static const struct iio_event_spec bma400_step_detect_event = {
- .type = IIO_EV_TYPE_CHANGE,
- .dir = IIO_EV_DIR_NONE,
- .mask_separate = BIT(IIO_EV_INFO_ENABLE),
- };
- static const struct iio_event_spec bma400_activity_event = {
- .type = IIO_EV_TYPE_CHANGE,
- .dir = IIO_EV_DIR_NONE,
- .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE),
- };
- static const struct iio_event_spec bma400_accel_event[] = {
- {
- .type = IIO_EV_TYPE_MAG,
- .dir = IIO_EV_DIR_FALLING,
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_PERIOD) |
- BIT(IIO_EV_INFO_HYSTERESIS) |
- BIT(IIO_EV_INFO_ENABLE),
- },
- {
- .type = IIO_EV_TYPE_MAG,
- .dir = IIO_EV_DIR_RISING,
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_PERIOD) |
- BIT(IIO_EV_INFO_HYSTERESIS) |
- BIT(IIO_EV_INFO_ENABLE),
- },
- {
- .type = IIO_EV_TYPE_GESTURE,
- .dir = IIO_EV_DIR_SINGLETAP,
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_ENABLE) |
- BIT(IIO_EV_INFO_RESET_TIMEOUT),
- },
- {
- .type = IIO_EV_TYPE_GESTURE,
- .dir = IIO_EV_DIR_DOUBLETAP,
- .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
- BIT(IIO_EV_INFO_ENABLE) |
- BIT(IIO_EV_INFO_RESET_TIMEOUT) |
- BIT(IIO_EV_INFO_TAP2_MIN_DELAY),
- },
- };
- static int usec_to_tapreg_raw(int usec, const int *time_list)
- {
- int index;
- for (index = 0; index < BMA400_TAP_TIM_LIST_LEN; index++) {
- if (usec == time_list[index])
- return index;
- }
- return -EINVAL;
- }
- static ssize_t in_accel_gesture_tap_maxtomin_time_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct bma400_data *data = iio_priv(indio_dev);
- int ret, reg_val, raw, vals[2];
- ret = regmap_read(data->regmap, BMA400_TAP_CONFIG1_REG, ®_val);
- if (ret)
- return ret;
- raw = FIELD_GET(BMA400_TAP_CONFIG1_TICSTH_MASK, reg_val);
- vals[0] = 0;
- vals[1] = tap_max2min_time[raw];
- return iio_format_value(buf, IIO_VAL_INT_PLUS_MICRO, 2, vals);
- }
- static ssize_t in_accel_gesture_tap_maxtomin_time_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
- {
- struct iio_dev *indio_dev = dev_to_iio_dev(dev);
- struct bma400_data *data = iio_priv(indio_dev);
- int ret, val_int, val_fract, raw;
- ret = iio_str_to_fixpoint(buf, 100000, &val_int, &val_fract);
- if (ret)
- return ret;
- raw = usec_to_tapreg_raw(val_fract, tap_max2min_time);
- if (raw < 0)
- return -EINVAL;
- ret = regmap_update_bits(data->regmap, BMA400_TAP_CONFIG1_REG,
- BMA400_TAP_CONFIG1_TICSTH_MASK,
- FIELD_PREP(BMA400_TAP_CONFIG1_TICSTH_MASK, raw));
- if (ret)
- return ret;
- return len;
- }
- static IIO_DEVICE_ATTR_RW(in_accel_gesture_tap_maxtomin_time, 0);
- /*
- * Tap interrupts works with 200 Hz input data rate and the time based tap
- * controls are in the terms of data samples so the below calculation is
- * used to convert the configuration values into seconds.
- * e.g.:
- * 60 data samples * 0.005 ms = 0.3 seconds.
- * 80 data samples * 0.005 ms = 0.4 seconds.
- */
- /* quiet configuration values in seconds */
- static IIO_CONST_ATTR(in_accel_gesture_tap_reset_timeout_available,
- "0.3 0.4 0.5 0.6");
- /* tics_th configuration values in seconds */
- static IIO_CONST_ATTR(in_accel_gesture_tap_maxtomin_time_available,
- "0.03 0.045 0.06 0.09");
- /* quiet_dt configuration values in seconds */
- static IIO_CONST_ATTR(in_accel_gesture_doubletap_tap2_min_delay_available,
- "0.02 0.04 0.06 0.08");
- /* List of sensitivity values available to configure tap interrupts */
- static IIO_CONST_ATTR(in_accel_gesture_tap_value_available, "0 1 2 3 4 5 6 7");
- static struct attribute *bma400_event_attributes[] = {
- &iio_const_attr_in_accel_gesture_tap_value_available.dev_attr.attr,
- &iio_const_attr_in_accel_gesture_tap_reset_timeout_available.dev_attr.attr,
- &iio_const_attr_in_accel_gesture_tap_maxtomin_time_available.dev_attr.attr,
- &iio_const_attr_in_accel_gesture_doubletap_tap2_min_delay_available.dev_attr.attr,
- &iio_dev_attr_in_accel_gesture_tap_maxtomin_time.dev_attr.attr,
- NULL
- };
- static const struct attribute_group bma400_event_attribute_group = {
- .attrs = bma400_event_attributes,
- };
- #define BMA400_ACC_CHANNEL(_index, _axis) { \
- .type = IIO_ACCEL, \
- .modified = 1, \
- .channel2 = IIO_MOD_##_axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
- .ext_info = bma400_ext_info, \
- .scan_index = _index, \
- .scan_type = { \
- .sign = 's', \
- .realbits = 12, \
- .storagebits = 16, \
- .endianness = IIO_LE, \
- }, \
- .event_spec = bma400_accel_event, \
- .num_event_specs = ARRAY_SIZE(bma400_accel_event) \
- }
- #define BMA400_ACTIVITY_CHANNEL(_chan2) { \
- .type = IIO_ACTIVITY, \
- .modified = 1, \
- .channel2 = _chan2, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
- .scan_index = -1, /* No buffer support */ \
- .event_spec = &bma400_activity_event, \
- .num_event_specs = 1, \
- }
- static const struct iio_chan_spec bma400_channels[] = {
- BMA400_ACC_CHANNEL(0, X),
- BMA400_ACC_CHANNEL(1, Y),
- BMA400_ACC_CHANNEL(2, Z),
- {
- .type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- .scan_index = 3,
- .scan_type = {
- .sign = 's',
- .realbits = 8,
- .storagebits = 8,
- .endianness = IIO_LE,
- },
- },
- {
- .type = IIO_STEPS,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
- BIT(IIO_CHAN_INFO_ENABLE),
- .scan_index = -1, /* No buffer support */
- .event_spec = &bma400_step_detect_event,
- .num_event_specs = 1,
- },
- BMA400_ACTIVITY_CHANNEL(IIO_MOD_STILL),
- BMA400_ACTIVITY_CHANNEL(IIO_MOD_WALKING),
- BMA400_ACTIVITY_CHANNEL(IIO_MOD_RUNNING),
- IIO_CHAN_SOFT_TIMESTAMP(4),
- };
- static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
- {
- unsigned int raw_temp;
- int host_temp;
- int ret;
- if (data->power_mode == POWER_MODE_SLEEP)
- return -EBUSY;
- ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &raw_temp);
- if (ret)
- return ret;
- host_temp = sign_extend32(raw_temp, 7);
- /*
- * The formula for the TEMP_DATA register in the datasheet
- * is: x * 0.5 + 23
- */
- *val = (host_temp >> 1) + 23;
- *val2 = (host_temp & 0x1) * 500000;
- return IIO_VAL_INT_PLUS_MICRO;
- }
- static int bma400_get_accel_reg(struct bma400_data *data,
- const struct iio_chan_spec *chan,
- int *val)
- {
- __le16 raw_accel;
- int lsb_reg;
- int ret;
- if (data->power_mode == POWER_MODE_SLEEP)
- return -EBUSY;
- switch (chan->channel2) {
- case IIO_MOD_X:
- lsb_reg = BMA400_ACC_X_LSB_REG;
- break;
- case IIO_MOD_Y:
- lsb_reg = BMA400_ACC_Y_LSB_REG;
- break;
- case IIO_MOD_Z:
- lsb_reg = BMA400_ACC_Z_LSB_REG;
- break;
- default:
- dev_err(data->dev, "invalid axis channel modifier\n");
- return -EINVAL;
- }
- /* bulk read two registers, with the base being the LSB register */
- ret = regmap_bulk_read(data->regmap, lsb_reg, &raw_accel,
- sizeof(raw_accel));
- if (ret)
- return ret;
- *val = sign_extend32(le16_to_cpu(raw_accel), 11);
- return IIO_VAL_INT;
- }
- static void bma400_output_data_rate_from_raw(int raw, unsigned int *val,
- unsigned int *val2)
- {
- *val = BMA400_ACC_CONFIG1_ODR_MAX_HZ >> (BMA400_ACC_CONFIG1_ODR_MAX_RAW - raw);
- if (raw > BMA400_ACC_CONFIG1_ODR_MIN_RAW)
- *val2 = 0;
- else
- *val2 = 500000;
- }
- static int bma400_get_accel_output_data_rate(struct bma400_data *data)
- {
- unsigned int val;
- unsigned int odr;
- int ret;
- switch (data->power_mode) {
- case POWER_MODE_LOW:
- /*
- * Runs at a fixed rate in low-power mode. See section 4.3
- * in the datasheet.
- */
- bma400_output_data_rate_from_raw(BMA400_ACC_CONFIG1_ODR_LP_RAW,
- &data->sample_freq.hz,
- &data->sample_freq.uhz);
- return 0;
- case POWER_MODE_NORMAL:
- /*
- * In normal mode the ODR can be found in the ACC_CONFIG1
- * register.
- */
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val);
- if (ret)
- goto error;
- odr = val & BMA400_ACC_CONFIG1_ODR_MASK;
- if (odr < BMA400_ACC_CONFIG1_ODR_MIN_RAW ||
- odr > BMA400_ACC_CONFIG1_ODR_MAX_RAW) {
- ret = -EINVAL;
- goto error;
- }
- bma400_output_data_rate_from_raw(odr, &data->sample_freq.hz,
- &data->sample_freq.uhz);
- return 0;
- case POWER_MODE_SLEEP:
- data->sample_freq.hz = 0;
- data->sample_freq.uhz = 0;
- return 0;
- default:
- ret = 0;
- goto error;
- }
- error:
- data->sample_freq.hz = -1;
- data->sample_freq.uhz = -1;
- return ret;
- }
- static int bma400_set_accel_output_data_rate(struct bma400_data *data,
- int hz, int uhz)
- {
- unsigned int idx;
- unsigned int odr;
- unsigned int val;
- int ret;
- if (hz >= BMA400_ACC_CONFIG1_ODR_MIN_WHOLE_HZ) {
- if (uhz || hz > BMA400_ACC_CONFIG1_ODR_MAX_HZ)
- return -EINVAL;
- /* Note this works because MIN_WHOLE_HZ is odd */
- idx = __ffs(hz);
- if (hz >> idx != BMA400_ACC_CONFIG1_ODR_MIN_WHOLE_HZ)
- return -EINVAL;
- idx += BMA400_ACC_CONFIG1_ODR_MIN_RAW + 1;
- } else if (hz == BMA400_ACC_CONFIG1_ODR_MIN_HZ && uhz == 500000) {
- idx = BMA400_ACC_CONFIG1_ODR_MIN_RAW;
- } else {
- return -EINVAL;
- }
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val);
- if (ret)
- return ret;
- /* preserve the range and normal mode osr */
- odr = (~BMA400_ACC_CONFIG1_ODR_MASK & val) | idx;
- ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG, odr);
- if (ret)
- return ret;
- bma400_output_data_rate_from_raw(idx, &data->sample_freq.hz,
- &data->sample_freq.uhz);
- return 0;
- }
- static int bma400_get_accel_oversampling_ratio(struct bma400_data *data)
- {
- unsigned int val;
- unsigned int osr;
- int ret;
- /*
- * The oversampling ratio is stored in a different register
- * based on the power-mode. In normal mode the OSR is stored
- * in ACC_CONFIG1. In low-power mode it is stored in
- * ACC_CONFIG0.
- */
- switch (data->power_mode) {
- case POWER_MODE_LOW:
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG, &val);
- if (ret) {
- data->oversampling_ratio = -1;
- return ret;
- }
- osr = FIELD_GET(BMA400_ACC_CONFIG0_LP_OSR_MASK, val);
- data->oversampling_ratio = osr;
- return 0;
- case POWER_MODE_NORMAL:
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val);
- if (ret) {
- data->oversampling_ratio = -1;
- return ret;
- }
- osr = FIELD_GET(BMA400_ACC_CONFIG1_NP_OSR_MASK, val);
- data->oversampling_ratio = osr;
- return 0;
- case POWER_MODE_SLEEP:
- data->oversampling_ratio = 0;
- return 0;
- default:
- data->oversampling_ratio = -1;
- return -EINVAL;
- }
- }
- static int bma400_set_accel_oversampling_ratio(struct bma400_data *data,
- int val)
- {
- unsigned int acc_config;
- int ret;
- if (val & ~BMA400_TWO_BITS_MASK)
- return -EINVAL;
- /*
- * The oversampling ratio is stored in a different register
- * based on the power-mode.
- */
- switch (data->power_mode) {
- case POWER_MODE_LOW:
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG,
- &acc_config);
- if (ret)
- return ret;
- ret = regmap_write(data->regmap, BMA400_ACC_CONFIG0_REG,
- (acc_config & ~BMA400_ACC_CONFIG0_LP_OSR_MASK) |
- FIELD_PREP(BMA400_ACC_CONFIG0_LP_OSR_MASK, val));
- if (ret) {
- dev_err(data->dev, "Failed to write out OSR\n");
- return ret;
- }
- data->oversampling_ratio = val;
- return 0;
- case POWER_MODE_NORMAL:
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG,
- &acc_config);
- if (ret)
- return ret;
- ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG,
- (acc_config & ~BMA400_ACC_CONFIG1_NP_OSR_MASK) |
- FIELD_PREP(BMA400_ACC_CONFIG1_NP_OSR_MASK, val));
- if (ret) {
- dev_err(data->dev, "Failed to write out OSR\n");
- return ret;
- }
- data->oversampling_ratio = val;
- return 0;
- default:
- return -EINVAL;
- }
- return ret;
- }
- static int bma400_accel_scale_to_raw(struct bma400_data *data,
- unsigned int val)
- {
- int raw;
- if (val == 0)
- return -EINVAL;
- /* Note this works because BMA400_SCALE_MIN is odd */
- raw = __ffs(val);
- if (val >> raw != BMA400_ACC_SCALE_MIN)
- return -EINVAL;
- return raw;
- }
- static int bma400_get_accel_scale(struct bma400_data *data)
- {
- unsigned int raw_scale;
- unsigned int val;
- int ret;
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &val);
- if (ret)
- return ret;
- raw_scale = FIELD_GET(BMA400_ACC_CONFIG1_ACC_RANGE_MASK, val);
- if (raw_scale > BMA400_TWO_BITS_MASK)
- return -EINVAL;
- data->scale = BMA400_ACC_SCALE_MIN << raw_scale;
- return 0;
- }
- static int bma400_set_accel_scale(struct bma400_data *data, unsigned int val)
- {
- unsigned int acc_config;
- int raw;
- int ret;
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG1_REG, &acc_config);
- if (ret)
- return ret;
- raw = bma400_accel_scale_to_raw(data, val);
- if (raw < 0)
- return raw;
- ret = regmap_write(data->regmap, BMA400_ACC_CONFIG1_REG,
- (acc_config & ~BMA400_ACC_CONFIG1_ACC_RANGE_MASK) |
- FIELD_PREP(BMA400_ACC_CONFIG1_ACC_RANGE_MASK, raw));
- if (ret)
- return ret;
- data->scale = val;
- return 0;
- }
- static int bma400_get_power_mode(struct bma400_data *data)
- {
- unsigned int val;
- int ret;
- ret = regmap_read(data->regmap, BMA400_STATUS_REG, &val);
- if (ret) {
- dev_err(data->dev, "Failed to read status register\n");
- return ret;
- }
- data->power_mode = (val >> 1) & BMA400_TWO_BITS_MASK;
- return 0;
- }
- static int bma400_set_power_mode(struct bma400_data *data,
- enum bma400_power_mode mode)
- {
- unsigned int val;
- int ret;
- ret = regmap_read(data->regmap, BMA400_ACC_CONFIG0_REG, &val);
- if (ret)
- return ret;
- if (data->power_mode == mode)
- return 0;
- if (mode == POWER_MODE_INVALID)
- return -EINVAL;
- /* Preserve the low-power oversample ratio etc */
- ret = regmap_write(data->regmap, BMA400_ACC_CONFIG0_REG,
- mode | (val & ~BMA400_TWO_BITS_MASK));
- if (ret) {
- dev_err(data->dev, "Failed to write to power-mode\n");
- return ret;
- }
- data->power_mode = mode;
- /*
- * Update our cached osr and odr based on the new
- * power-mode.
- */
- bma400_get_accel_output_data_rate(data);
- bma400_get_accel_oversampling_ratio(data);
- return 0;
- }
- static int bma400_enable_steps(struct bma400_data *data, int val)
- {
- int ret;
- if (data->steps_enabled == val)
- return 0;
- ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG,
- BMA400_INT_CONFIG1_STEP_INT_MASK,
- FIELD_PREP(BMA400_INT_CONFIG1_STEP_INT_MASK, val ? 1 : 0));
- if (ret)
- return ret;
- data->steps_enabled = val;
- return ret;
- }
- static int bma400_get_steps_reg(struct bma400_data *data, int *val)
- {
- int ret;
- u8 *steps_raw __free(kfree) = kmalloc(BMA400_STEP_RAW_LEN, GFP_KERNEL);
- if (!steps_raw)
- return -ENOMEM;
- ret = regmap_bulk_read(data->regmap, BMA400_STEP_CNT0_REG,
- steps_raw, BMA400_STEP_RAW_LEN);
- if (ret)
- return ret;
- *val = get_unaligned_le24(steps_raw);
- return IIO_VAL_INT;
- }
- static void bma400_init_tables(void)
- {
- int raw;
- int i;
- for (i = 0; i + 1 < ARRAY_SIZE(bma400_sample_freqs); i += 2) {
- raw = (i / 2) + 5;
- bma400_output_data_rate_from_raw(raw, &bma400_sample_freqs[i],
- &bma400_sample_freqs[i + 1]);
- }
- for (i = 0; i + 1 < ARRAY_SIZE(bma400_scales); i += 2) {
- raw = i / 2;
- bma400_scales[i] = 0;
- bma400_scales[i + 1] = BMA400_ACC_SCALE_MIN << raw;
- }
- }
- static void bma400_power_disable(void *data_ptr)
- {
- struct bma400_data *data = data_ptr;
- int ret;
- mutex_lock(&data->mutex);
- ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
- mutex_unlock(&data->mutex);
- if (ret)
- dev_warn(data->dev, "Failed to put device into sleep mode (%pe)\n",
- ERR_PTR(ret));
- }
- static enum iio_modifier bma400_act_to_mod(enum bma400_activity activity)
- {
- switch (activity) {
- case BMA400_STILL:
- return IIO_MOD_STILL;
- case BMA400_WALKING:
- return IIO_MOD_WALKING;
- case BMA400_RUNNING:
- return IIO_MOD_RUNNING;
- default:
- return IIO_NO_MOD;
- }
- }
- static int bma400_init(struct bma400_data *data)
- {
- static const char * const regulator_names[] = { "vdd", "vddio" };
- unsigned int val;
- int ret;
- ret = devm_regulator_bulk_get_enable(data->dev,
- ARRAY_SIZE(regulator_names),
- regulator_names);
- if (ret)
- return dev_err_probe(data->dev, ret, "Failed to get regulators\n");
- /* Try to read chip_id register. It must return 0x90. */
- ret = regmap_read(data->regmap, BMA400_CHIP_ID_REG, &val);
- if (ret) {
- dev_err(data->dev, "Failed to read chip id register\n");
- return ret;
- }
- if (val != BMA400_ID_REG_VAL) {
- dev_err(data->dev, "Chip ID mismatch\n");
- return -ENODEV;
- }
- ret = bma400_get_power_mode(data);
- if (ret) {
- dev_err(data->dev, "Failed to get the initial power-mode\n");
- return ret;
- }
- if (data->power_mode != POWER_MODE_NORMAL) {
- ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
- if (ret) {
- dev_err(data->dev, "Failed to wake up the device\n");
- return ret;
- }
- /*
- * TODO: The datasheet waits 1500us here in the example, but
- * lists 2/ODR as the wakeup time.
- */
- usleep_range(1500, 2000);
- }
- ret = devm_add_action_or_reset(data->dev, bma400_power_disable, data);
- if (ret)
- return ret;
- bma400_init_tables();
- ret = bma400_get_accel_output_data_rate(data);
- if (ret)
- return ret;
- ret = bma400_get_accel_oversampling_ratio(data);
- if (ret)
- return ret;
- ret = bma400_get_accel_scale(data);
- if (ret)
- return ret;
- /* Configure INT1 pin to open drain */
- ret = regmap_write(data->regmap, BMA400_INT_IO_CTRL_REG, 0x06);
- if (ret)
- return ret;
- /*
- * Once the interrupt engine is supported we might use the
- * data_src_reg, but for now ensure this is set to the
- * variable ODR filter selectable by the sample frequency
- * channel.
- */
- return regmap_write(data->regmap, BMA400_ACC_CONFIG2_REG, 0x00);
- }
- static int bma400_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, int *val,
- int *val2, long mask)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- unsigned int activity;
- int ret;
- switch (mask) {
- case IIO_CHAN_INFO_PROCESSED:
- switch (chan->type) {
- case IIO_TEMP:
- mutex_lock(&data->mutex);
- ret = bma400_get_temp_reg(data, val, val2);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_STEPS:
- return bma400_get_steps_reg(data, val);
- case IIO_ACTIVITY:
- ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
- &activity);
- if (ret)
- return ret;
- /*
- * The device does not support confidence value levels,
- * so we will always have 100% for current activity and
- * 0% for the others.
- */
- if (chan->channel2 == bma400_act_to_mod(activity))
- *val = 100;
- else
- *val = 0;
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- case IIO_CHAN_INFO_RAW:
- mutex_lock(&data->mutex);
- ret = bma400_get_accel_reg(data, chan, val);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_CHAN_INFO_SAMP_FREQ:
- switch (chan->type) {
- case IIO_ACCEL:
- if (data->sample_freq.hz < 0)
- return -EINVAL;
- *val = data->sample_freq.hz;
- *val2 = data->sample_freq.uhz;
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_TEMP:
- /*
- * Runs at a fixed sampling frequency. See Section 4.4
- * of the datasheet.
- */
- *val = 6;
- *val2 = 250000;
- return IIO_VAL_INT_PLUS_MICRO;
- default:
- return -EINVAL;
- }
- case IIO_CHAN_INFO_SCALE:
- *val = 0;
- *val2 = data->scale;
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- /*
- * TODO: We could avoid this logic and returning -EINVAL here if
- * we set both the low-power and normal mode OSR registers when
- * we configure the device.
- */
- if (data->oversampling_ratio < 0)
- return -EINVAL;
- *val = data->oversampling_ratio;
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_ENABLE:
- *val = data->steps_enabled;
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- }
- static int bma400_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- const int **vals, int *type, int *length,
- long mask)
- {
- switch (mask) {
- case IIO_CHAN_INFO_SCALE:
- *type = IIO_VAL_INT_PLUS_MICRO;
- *vals = bma400_scales;
- *length = ARRAY_SIZE(bma400_scales);
- return IIO_AVAIL_LIST;
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- *type = IIO_VAL_INT;
- *vals = bma400_osr_range;
- *length = ARRAY_SIZE(bma400_osr_range);
- return IIO_AVAIL_RANGE;
- case IIO_CHAN_INFO_SAMP_FREQ:
- *type = IIO_VAL_INT_PLUS_MICRO;
- *vals = bma400_sample_freqs;
- *length = ARRAY_SIZE(bma400_sample_freqs);
- return IIO_AVAIL_LIST;
- default:
- return -EINVAL;
- }
- }
- static int bma400_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan, int val, int val2,
- long mask)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- int ret;
- switch (mask) {
- case IIO_CHAN_INFO_SAMP_FREQ:
- /*
- * The sample frequency is readonly for the temperature
- * register and a fixed value in low-power mode.
- */
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
- mutex_lock(&data->mutex);
- ret = bma400_set_accel_output_data_rate(data, val, val2);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_CHAN_INFO_SCALE:
- if (val != 0 ||
- val2 < BMA400_ACC_SCALE_MIN || val2 > BMA400_ACC_SCALE_MAX)
- return -EINVAL;
- mutex_lock(&data->mutex);
- ret = bma400_set_accel_scale(data, val2);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- mutex_lock(&data->mutex);
- ret = bma400_set_accel_oversampling_ratio(data, val);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_CHAN_INFO_ENABLE:
- mutex_lock(&data->mutex);
- ret = bma400_enable_steps(data, val);
- mutex_unlock(&data->mutex);
- return ret;
- default:
- return -EINVAL;
- }
- }
- static int bma400_write_raw_get_fmt(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- long mask)
- {
- switch (mask) {
- case IIO_CHAN_INFO_SAMP_FREQ:
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_CHAN_INFO_SCALE:
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_ENABLE:
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- }
- static int bma400_read_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- switch (chan->type) {
- case IIO_ACCEL:
- switch (dir) {
- case IIO_EV_DIR_RISING:
- return FIELD_GET(BMA400_INT_CONFIG0_GEN1_MASK,
- data->generic_event_en);
- case IIO_EV_DIR_FALLING:
- return FIELD_GET(BMA400_INT_CONFIG0_GEN2_MASK,
- data->generic_event_en);
- case IIO_EV_DIR_SINGLETAP:
- return FIELD_GET(BMA400_INT_CONFIG1_S_TAP_MASK,
- data->tap_event_en_bitmask);
- case IIO_EV_DIR_DOUBLETAP:
- return FIELD_GET(BMA400_INT_CONFIG1_D_TAP_MASK,
- data->tap_event_en_bitmask);
- default:
- return -EINVAL;
- }
- case IIO_STEPS:
- return data->step_event_en;
- case IIO_ACTIVITY:
- return data->activity_event_en;
- default:
- return -EINVAL;
- }
- }
- static int bma400_steps_event_enable(struct bma400_data *data, int state)
- {
- int ret;
- ret = bma400_enable_steps(data, 1);
- if (ret)
- return ret;
- ret = regmap_update_bits(data->regmap, BMA400_INT12_MAP_REG,
- BMA400_INT_CONFIG1_STEP_INT_MASK,
- FIELD_PREP(BMA400_INT_CONFIG1_STEP_INT_MASK,
- state));
- if (ret)
- return ret;
- data->step_event_en = state;
- return 0;
- }
- static int bma400_generic_event_en(struct bma400_data *data,
- enum iio_event_direction dir,
- int state)
- {
- int ret;
- unsigned int intrmask, regval;
- enum bma400_generic_intr genintr;
- enum bma400_detect_criterion detect_criterion;
- const struct bma400_genintr_info *bma400_genintr;
- bma400_genintr = get_bma400_genintr_info(dir);
- if (!bma400_genintr)
- return -EINVAL;
- genintr = bma400_genintr->genintr;
- detect_criterion = bma400_genintr->detect_mode;
- intrmask = bma400_genintr->intrmask;
- /*
- * Enabling all axis for interrupt evaluation
- * Acc_filt2 is recommended as data source in datasheet (Section 4.7)
- */
- ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr, 0),
- BMA400_GENINT_CONFIG0_X_EN_MASK |
- BMA400_GENINT_CONFIG0_Y_EN_MASK |
- BMA400_GENINT_CONFIG0_Z_EN_MASK|
- FIELD_PREP(BMA400_GENINT_CONFIG0_DATA_SRC_MASK, ACCEL_FILT2)|
- FIELD_PREP(BMA400_GENINT_CONFIG0_REF_UPD_MODE_MASK,
- BMA400_REF_EVERYTIME_UPDT_MODE));
- if (ret)
- return ret;
- /* OR combination of all axis for interrupt evaluation */
- regval = FIELD_PREP(BMA400_GENINT_CONFIG1_AXES_COMB_MASK, BMA400_EVAL_X_OR_Y_OR_Z) |
- FIELD_PREP(BMA400_GENINT_CONFIG1_DETCT_CRIT_MASK, detect_criterion);
- ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr, 1), regval);
- if (ret)
- return ret;
- /*
- * Initial value to avoid interrupts while enabling
- * Value is in units of 8mg/lsb, i.e. effective val is val * 8mg/lsb
- */
- ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr, 2), 0x0A);
- if (ret)
- return ret;
- /* Initial duration value to avoid interrupts while enabling*/
- ret = regmap_write(data->regmap, BMA400_GENINT_CONFIG_REG(genintr, 4), 0x0F);
- if (ret)
- return ret;
- regval = state ? intrmask : 0;
- ret = regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG, intrmask, regval);
- if (ret)
- return ret;
- ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG, intrmask, regval);
- if (ret)
- return ret;
- set_mask_bits(&data->generic_event_en, intrmask, regval);
- return 0;
- }
- static int bma400_tap_event_en(struct bma400_data *data,
- enum iio_event_direction dir, int state)
- {
- unsigned int mask;
- unsigned int field_value = 0;
- int ret;
- /*
- * Tap interrupts can be configured only in normal mode.
- * See table in section 4.3 "Power modes - performance modes" of
- * datasheet v1.2.
- */
- if (data->power_mode != POWER_MODE_NORMAL)
- return -EINVAL;
- /*
- * Tap interrupts are operating with a data rate of 200Hz.
- * See section 4.7 "Tap sensing interrupt" in datasheet v1.2.
- */
- if (data->sample_freq.hz != 200 && state) {
- dev_err(data->dev, "Invalid data rate for tap interrupts.\n");
- return -EINVAL;
- }
- ret = regmap_update_bits(data->regmap, BMA400_INT12_MAP_REG,
- BMA400_INT_CONFIG1_S_TAP_MASK,
- FIELD_PREP(BMA400_INT_CONFIG1_S_TAP_MASK, state));
- if (ret)
- return ret;
- switch (dir) {
- case IIO_EV_DIR_SINGLETAP:
- mask = BMA400_INT_CONFIG1_S_TAP_MASK;
- set_mask_bits(&field_value, BMA400_INT_CONFIG1_S_TAP_MASK,
- FIELD_PREP(BMA400_INT_CONFIG1_S_TAP_MASK, state));
- break;
- case IIO_EV_DIR_DOUBLETAP:
- mask = BMA400_INT_CONFIG1_D_TAP_MASK;
- set_mask_bits(&field_value, BMA400_INT_CONFIG1_D_TAP_MASK,
- FIELD_PREP(BMA400_INT_CONFIG1_D_TAP_MASK, state));
- break;
- default:
- return -EINVAL;
- }
- ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG1_REG, mask,
- field_value);
- if (ret)
- return ret;
- set_mask_bits(&data->tap_event_en_bitmask, mask, field_value);
- return 0;
- }
- static int bma400_disable_adv_interrupt(struct bma400_data *data)
- {
- int ret;
- ret = regmap_write(data->regmap, BMA400_INT_CONFIG0_REG, 0);
- if (ret)
- return ret;
- ret = regmap_write(data->regmap, BMA400_INT_CONFIG1_REG, 0);
- if (ret)
- return ret;
- data->tap_event_en_bitmask = 0;
- data->generic_event_en = 0;
- data->step_event_en = false;
- data->activity_event_en = false;
- return 0;
- }
- static int bma400_write_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir, bool state)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- int ret;
- switch (chan->type) {
- case IIO_ACCEL:
- switch (type) {
- case IIO_EV_TYPE_MAG:
- mutex_lock(&data->mutex);
- ret = bma400_generic_event_en(data, dir, state);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_EV_TYPE_GESTURE:
- mutex_lock(&data->mutex);
- ret = bma400_tap_event_en(data, dir, state);
- mutex_unlock(&data->mutex);
- return ret;
- default:
- return -EINVAL;
- }
- case IIO_STEPS:
- mutex_lock(&data->mutex);
- ret = bma400_steps_event_enable(data, state);
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_ACTIVITY:
- mutex_lock(&data->mutex);
- if (!data->step_event_en) {
- ret = bma400_steps_event_enable(data, true);
- if (ret) {
- mutex_unlock(&data->mutex);
- return ret;
- }
- }
- data->activity_event_en = state;
- mutex_unlock(&data->mutex);
- return 0;
- default:
- return -EINVAL;
- }
- }
- static int bma400_read_event_value(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info,
- int *val, int *val2)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- int ret, reg_val, raw;
- enum bma400_generic_intr genintr;
- const struct bma400_genintr_info *bma400_genintr;
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
- switch (type) {
- case IIO_EV_TYPE_MAG:
- bma400_genintr = get_bma400_genintr_info(dir);
- if (!bma400_genintr)
- return -EINVAL;
- genintr = bma400_genintr->genintr;
- *val2 = 0;
- switch (info) {
- case IIO_EV_INFO_VALUE:
- ret = regmap_read(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 2),
- val);
- if (ret)
- return ret;
- return IIO_VAL_INT;
- case IIO_EV_INFO_PERIOD:
- mutex_lock(&data->mutex);
- ret = regmap_bulk_read(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 3),
- &data->duration,
- sizeof(data->duration));
- if (ret) {
- mutex_unlock(&data->mutex);
- return ret;
- }
- *val = be16_to_cpu(data->duration);
- mutex_unlock(&data->mutex);
- return IIO_VAL_INT;
- case IIO_EV_INFO_HYSTERESIS:
- ret = regmap_read(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 0),
- val);
- if (ret)
- return ret;
- *val = FIELD_GET(BMA400_GENINT_CONFIG0_HYST_MASK, *val);
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- case IIO_EV_TYPE_GESTURE:
- switch (info) {
- case IIO_EV_INFO_VALUE:
- ret = regmap_read(data->regmap, BMA400_TAP_CONFIG_REG,
- ®_val);
- if (ret)
- return ret;
- *val = FIELD_GET(BMA400_TAP_CONFIG_SEN_MASK, reg_val);
- return IIO_VAL_INT;
- case IIO_EV_INFO_RESET_TIMEOUT:
- ret = regmap_read(data->regmap, BMA400_TAP_CONFIG1_REG,
- ®_val);
- if (ret)
- return ret;
- raw = FIELD_GET(BMA400_TAP_CONFIG1_QUIET_MASK, reg_val);
- *val = 0;
- *val2 = tap_reset_timeout[raw];
- return IIO_VAL_INT_PLUS_MICRO;
- case IIO_EV_INFO_TAP2_MIN_DELAY:
- ret = regmap_read(data->regmap, BMA400_TAP_CONFIG1_REG,
- ®_val);
- if (ret)
- return ret;
- raw = FIELD_GET(BMA400_TAP_CONFIG1_QUIETDT_MASK, reg_val);
- *val = 0;
- *val2 = double_tap2_min_delay[raw];
- return IIO_VAL_INT_PLUS_MICRO;
- default:
- return -EINVAL;
- }
- default:
- return -EINVAL;
- }
- }
- static int bma400_write_event_value(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- enum iio_event_info info,
- int val, int val2)
- {
- struct bma400_data *data = iio_priv(indio_dev);
- int ret, raw;
- enum bma400_generic_intr genintr;
- const struct bma400_genintr_info *bma400_genintr;
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
- switch (type) {
- case IIO_EV_TYPE_MAG:
- bma400_genintr = get_bma400_genintr_info(dir);
- if (!bma400_genintr)
- return -EINVAL;
- genintr = bma400_genintr->genintr;
- switch (info) {
- case IIO_EV_INFO_VALUE:
- if (val < 1 || val > 255)
- return -EINVAL;
- return regmap_write(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 2),
- val);
- case IIO_EV_INFO_PERIOD:
- if (val < 1 || val > 65535)
- return -EINVAL;
- mutex_lock(&data->mutex);
- put_unaligned_be16(val, &data->duration);
- ret = regmap_bulk_write(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 3),
- &data->duration,
- sizeof(data->duration));
- mutex_unlock(&data->mutex);
- return ret;
- case IIO_EV_INFO_HYSTERESIS:
- if (val < 0 || val > 3)
- return -EINVAL;
- return regmap_update_bits(data->regmap,
- BMA400_GENINT_CONFIG_REG(genintr, 0),
- BMA400_GENINT_CONFIG0_HYST_MASK,
- FIELD_PREP(BMA400_GENINT_CONFIG0_HYST_MASK,
- val));
- default:
- return -EINVAL;
- }
- case IIO_EV_TYPE_GESTURE:
- switch (info) {
- case IIO_EV_INFO_VALUE:
- if (val < 0 || val > 7)
- return -EINVAL;
- return regmap_update_bits(data->regmap,
- BMA400_TAP_CONFIG_REG,
- BMA400_TAP_CONFIG_SEN_MASK,
- FIELD_PREP(BMA400_TAP_CONFIG_SEN_MASK,
- val));
- case IIO_EV_INFO_RESET_TIMEOUT:
- raw = usec_to_tapreg_raw(val2, tap_reset_timeout);
- if (raw < 0)
- return -EINVAL;
- return regmap_update_bits(data->regmap,
- BMA400_TAP_CONFIG1_REG,
- BMA400_TAP_CONFIG1_QUIET_MASK,
- FIELD_PREP(BMA400_TAP_CONFIG1_QUIET_MASK,
- raw));
- case IIO_EV_INFO_TAP2_MIN_DELAY:
- raw = usec_to_tapreg_raw(val2, double_tap2_min_delay);
- if (raw < 0)
- return -EINVAL;
- return regmap_update_bits(data->regmap,
- BMA400_TAP_CONFIG1_REG,
- BMA400_TAP_CONFIG1_QUIETDT_MASK,
- FIELD_PREP(BMA400_TAP_CONFIG1_QUIETDT_MASK,
- raw));
- default:
- return -EINVAL;
- }
- default:
- return -EINVAL;
- }
- }
- static int bma400_data_rdy_trigger_set_state(struct iio_trigger *trig,
- bool state)
- {
- struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
- struct bma400_data *data = iio_priv(indio_dev);
- int ret;
- ret = regmap_update_bits(data->regmap, BMA400_INT_CONFIG0_REG,
- BMA400_INT_CONFIG0_DRDY_MASK,
- FIELD_PREP(BMA400_INT_CONFIG0_DRDY_MASK, state));
- if (ret)
- return ret;
- return regmap_update_bits(data->regmap, BMA400_INT1_MAP_REG,
- BMA400_INT_CONFIG0_DRDY_MASK,
- FIELD_PREP(BMA400_INT_CONFIG0_DRDY_MASK, state));
- }
- static const unsigned long bma400_avail_scan_masks[] = {
- BIT(BMA400_ACCL_X) | BIT(BMA400_ACCL_Y) | BIT(BMA400_ACCL_Z),
- BIT(BMA400_ACCL_X) | BIT(BMA400_ACCL_Y) | BIT(BMA400_ACCL_Z)
- | BIT(BMA400_TEMP),
- 0
- };
- static const struct iio_info bma400_info = {
- .read_raw = bma400_read_raw,
- .read_avail = bma400_read_avail,
- .write_raw = bma400_write_raw,
- .write_raw_get_fmt = bma400_write_raw_get_fmt,
- .read_event_config = bma400_read_event_config,
- .write_event_config = bma400_write_event_config,
- .write_event_value = bma400_write_event_value,
- .read_event_value = bma400_read_event_value,
- .event_attrs = &bma400_event_attribute_group,
- };
- static const struct iio_trigger_ops bma400_trigger_ops = {
- .set_trigger_state = &bma400_data_rdy_trigger_set_state,
- .validate_device = &iio_trigger_validate_own_device,
- };
- static irqreturn_t bma400_trigger_handler(int irq, void *p)
- {
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
- struct bma400_data *data = iio_priv(indio_dev);
- int ret, temp;
- /* Lock to protect the data->buffer */
- mutex_lock(&data->mutex);
- /* bulk read six registers, with the base being the LSB register */
- ret = regmap_bulk_read(data->regmap, BMA400_ACC_X_LSB_REG,
- &data->buffer.buff, sizeof(data->buffer.buff));
- if (ret)
- goto unlock_err;
- if (test_bit(BMA400_TEMP, indio_dev->active_scan_mask)) {
- ret = regmap_read(data->regmap, BMA400_TEMP_DATA_REG, &temp);
- if (ret)
- goto unlock_err;
- data->buffer.temperature = temp;
- }
- iio_push_to_buffers_with_ts(indio_dev, &data->buffer,
- sizeof(data->buffer),
- iio_get_time_ns(indio_dev));
- mutex_unlock(&data->mutex);
- iio_trigger_notify_done(indio_dev->trig);
- return IRQ_HANDLED;
- unlock_err:
- mutex_unlock(&data->mutex);
- return IRQ_NONE;
- }
- static irqreturn_t bma400_interrupt(int irq, void *private)
- {
- struct iio_dev *indio_dev = private;
- struct bma400_data *data = iio_priv(indio_dev);
- s64 timestamp = iio_get_time_ns(indio_dev);
- unsigned int act, ev_dir = IIO_EV_DIR_NONE;
- int ret;
- /* Lock to protect the data->status */
- mutex_lock(&data->mutex);
- ret = regmap_bulk_read(data->regmap, BMA400_INT_STAT0_REG,
- &data->status,
- sizeof(data->status));
- /*
- * if none of the bit is set in the status register then it is
- * spurious interrupt.
- */
- if (ret || !data->status)
- goto unlock_err;
- /*
- * Disable all advance interrupts if interrupt engine overrun occurs.
- * See section 4.7 "Interrupt engine overrun" in datasheet v1.2.
- */
- if (FIELD_GET(BMA400_INT_STAT_ENG_OVRRUN_MASK, le16_to_cpu(data->status))) {
- bma400_disable_adv_interrupt(data);
- dev_err(data->dev, "Interrupt engine overrun\n");
- goto unlock_err;
- }
- if (FIELD_GET(BMA400_INT_STAT1_S_TAP_MASK, le16_to_cpu(data->status)))
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
- IIO_MOD_X_OR_Y_OR_Z,
- IIO_EV_TYPE_GESTURE,
- IIO_EV_DIR_SINGLETAP),
- timestamp);
- if (FIELD_GET(BMA400_INT_STAT1_D_TAP_MASK, le16_to_cpu(data->status)))
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
- IIO_MOD_X_OR_Y_OR_Z,
- IIO_EV_TYPE_GESTURE,
- IIO_EV_DIR_DOUBLETAP),
- timestamp);
- if (FIELD_GET(BMA400_INT_STAT0_GEN1_MASK, le16_to_cpu(data->status)))
- ev_dir = IIO_EV_DIR_RISING;
- if (FIELD_GET(BMA400_INT_STAT0_GEN2_MASK, le16_to_cpu(data->status)))
- ev_dir = IIO_EV_DIR_FALLING;
- if (ev_dir != IIO_EV_DIR_NONE) {
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL, 0,
- IIO_MOD_X_OR_Y_OR_Z,
- IIO_EV_TYPE_MAG, ev_dir),
- timestamp);
- }
- if (FIELD_GET(BMA400_INT_STAT1_STEP_INT_MASK, le16_to_cpu(data->status))) {
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_TYPE_CHANGE,
- IIO_EV_DIR_NONE),
- timestamp);
- if (data->activity_event_en) {
- ret = regmap_read(data->regmap, BMA400_STEP_STAT_REG,
- &act);
- if (ret)
- goto unlock_err;
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
- bma400_act_to_mod(act),
- IIO_EV_TYPE_CHANGE,
- IIO_EV_DIR_NONE),
- timestamp);
- }
- }
- if (FIELD_GET(BMA400_INT_STAT0_DRDY_MASK, le16_to_cpu(data->status))) {
- mutex_unlock(&data->mutex);
- iio_trigger_poll_nested(data->trig);
- return IRQ_HANDLED;
- }
- mutex_unlock(&data->mutex);
- return IRQ_HANDLED;
- unlock_err:
- mutex_unlock(&data->mutex);
- return IRQ_NONE;
- }
- int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
- const char *name)
- {
- struct iio_dev *indio_dev;
- struct bma400_data *data;
- int ret;
- indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
- if (!indio_dev)
- return -ENOMEM;
- data = iio_priv(indio_dev);
- data->regmap = regmap;
- data->dev = dev;
- ret = bma400_init(data);
- if (ret)
- return ret;
- ret = iio_read_mount_matrix(dev, &data->orientation);
- if (ret)
- return ret;
- mutex_init(&data->mutex);
- indio_dev->name = name;
- indio_dev->info = &bma400_info;
- indio_dev->channels = bma400_channels;
- indio_dev->num_channels = ARRAY_SIZE(bma400_channels);
- indio_dev->available_scan_masks = bma400_avail_scan_masks;
- indio_dev->modes = INDIO_DIRECT_MODE;
- if (irq > 0) {
- data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!data->trig)
- return -ENOMEM;
- data->trig->ops = &bma400_trigger_ops;
- iio_trigger_set_drvdata(data->trig, indio_dev);
- ret = devm_iio_trigger_register(data->dev, data->trig);
- if (ret)
- return dev_err_probe(data->dev, ret,
- "iio trigger register fail\n");
- indio_dev->trig = iio_trigger_get(data->trig);
- ret = devm_request_threaded_irq(dev, irq, NULL,
- &bma400_interrupt,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- indio_dev->name, indio_dev);
- if (ret)
- return dev_err_probe(data->dev, ret,
- "request irq %d failed\n", irq);
- }
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
- &bma400_trigger_handler, NULL);
- if (ret)
- return dev_err_probe(data->dev, ret,
- "iio triggered buffer setup failed\n");
- return devm_iio_device_register(dev, indio_dev);
- }
- EXPORT_SYMBOL_NS(bma400_probe, "IIO_BMA400");
- MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
- MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
- MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core");
- MODULE_LICENSE("GPL");
|