123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright (C) 2021 Analog Devices, Inc.
- * Author: Cosmin Tanislav <[email protected]>
- */
- #include <linux/bitfield.h>
- #include <linux/bitops.h>
- #include <linux/iio/buffer.h>
- #include <linux/iio/events.h>
- #include <linux/iio/iio.h>
- #include <linux/iio/kfifo_buf.h>
- #include <linux/iio/sysfs.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/mod_devicetable.h>
- #include <linux/regmap.h>
- #include <linux/regulator/consumer.h>
- #include <asm/unaligned.h>
- #include "adxl367.h"
- #define ADXL367_REG_DEVID 0x00
- #define ADXL367_DEVID_AD 0xAD
- #define ADXL367_REG_STATUS 0x0B
- #define ADXL367_STATUS_INACT_MASK BIT(5)
- #define ADXL367_STATUS_ACT_MASK BIT(4)
- #define ADXL367_STATUS_FIFO_FULL_MASK BIT(2)
- #define ADXL367_FIFO_ENT_H_MASK GENMASK(1, 0)
- #define ADXL367_REG_X_DATA_H 0x0E
- #define ADXL367_REG_Y_DATA_H 0x10
- #define ADXL367_REG_Z_DATA_H 0x12
- #define ADXL367_REG_TEMP_DATA_H 0x14
- #define ADXL367_REG_EX_ADC_DATA_H 0x16
- #define ADXL367_DATA_MASK GENMASK(15, 2)
- #define ADXL367_TEMP_25C 165
- #define ADXL367_TEMP_PER_C 54
- #define ADXL367_VOLTAGE_OFFSET 8192
- #define ADXL367_VOLTAGE_MAX_MV 1000
- #define ADXL367_VOLTAGE_MAX_RAW GENMASK(13, 0)
- #define ADXL367_REG_RESET 0x1F
- #define ADXL367_RESET_CODE 0x52
- #define ADXL367_REG_THRESH_ACT_H 0x20
- #define ADXL367_REG_THRESH_INACT_H 0x23
- #define ADXL367_THRESH_MAX GENMASK(12, 0)
- #define ADXL367_THRESH_VAL_H_MASK GENMASK(12, 6)
- #define ADXL367_THRESH_H_MASK GENMASK(6, 0)
- #define ADXL367_THRESH_VAL_L_MASK GENMASK(5, 0)
- #define ADXL367_THRESH_L_MASK GENMASK(7, 2)
- #define ADXL367_REG_TIME_ACT 0x22
- #define ADXL367_REG_TIME_INACT_H 0x25
- #define ADXL367_TIME_ACT_MAX GENMASK(7, 0)
- #define ADXL367_TIME_INACT_MAX GENMASK(15, 0)
- #define ADXL367_TIME_INACT_VAL_H_MASK GENMASK(15, 8)
- #define ADXL367_TIME_INACT_H_MASK GENMASK(7, 0)
- #define ADXL367_TIME_INACT_VAL_L_MASK GENMASK(7, 0)
- #define ADXL367_TIME_INACT_L_MASK GENMASK(7, 0)
- #define ADXL367_REG_ACT_INACT_CTL 0x27
- #define ADXL367_ACT_EN_MASK GENMASK(1, 0)
- #define ADXL367_ACT_LINKLOOP_MASK GENMASK(5, 4)
- #define ADXL367_REG_FIFO_CTL 0x28
- #define ADXL367_FIFO_CTL_FORMAT_MASK GENMASK(6, 3)
- #define ADXL367_FIFO_CTL_MODE_MASK GENMASK(1, 0)
- #define ADXL367_REG_FIFO_SAMPLES 0x29
- #define ADXL367_FIFO_SIZE 512
- #define ADXL367_FIFO_MAX_WATERMARK 511
- #define ADXL367_SAMPLES_VAL_H_MASK BIT(8)
- #define ADXL367_SAMPLES_H_MASK BIT(2)
- #define ADXL367_SAMPLES_VAL_L_MASK GENMASK(7, 0)
- #define ADXL367_SAMPLES_L_MASK GENMASK(7, 0)
- #define ADXL367_REG_INT1_MAP 0x2A
- #define ADXL367_INT_INACT_MASK BIT(5)
- #define ADXL367_INT_ACT_MASK BIT(4)
- #define ADXL367_INT_FIFO_WATERMARK_MASK BIT(2)
- #define ADXL367_REG_FILTER_CTL 0x2C
- #define ADXL367_FILTER_CTL_RANGE_MASK GENMASK(7, 6)
- #define ADXL367_2G_RANGE_1G 4095
- #define ADXL367_2G_RANGE_100MG 409
- #define ADXL367_FILTER_CTL_ODR_MASK GENMASK(2, 0)
- #define ADXL367_REG_POWER_CTL 0x2D
- #define ADXL367_POWER_CTL_MODE_MASK GENMASK(1, 0)
- #define ADXL367_REG_ADC_CTL 0x3C
- #define ADXL367_REG_TEMP_CTL 0x3D
- #define ADXL367_ADC_EN_MASK BIT(0)
- enum adxl367_range {
- ADXL367_2G_RANGE,
- ADXL367_4G_RANGE,
- ADXL367_8G_RANGE,
- };
- enum adxl367_fifo_mode {
- ADXL367_FIFO_MODE_DISABLED = 0b00,
- ADXL367_FIFO_MODE_STREAM = 0b10,
- };
- enum adxl367_fifo_format {
- ADXL367_FIFO_FORMAT_XYZ,
- ADXL367_FIFO_FORMAT_X,
- ADXL367_FIFO_FORMAT_Y,
- ADXL367_FIFO_FORMAT_Z,
- ADXL367_FIFO_FORMAT_XYZT,
- ADXL367_FIFO_FORMAT_XT,
- ADXL367_FIFO_FORMAT_YT,
- ADXL367_FIFO_FORMAT_ZT,
- ADXL367_FIFO_FORMAT_XYZA,
- ADXL367_FIFO_FORMAT_XA,
- ADXL367_FIFO_FORMAT_YA,
- ADXL367_FIFO_FORMAT_ZA,
- };
- enum adxl367_op_mode {
- ADXL367_OP_STANDBY = 0b00,
- ADXL367_OP_MEASURE = 0b10,
- };
- enum adxl367_act_proc_mode {
- ADXL367_LOOPED = 0b11,
- };
- enum adxl367_act_en_mode {
- ADXL367_ACT_DISABLED = 0b00,
- ADCL367_ACT_REF_ENABLED = 0b11,
- };
- enum adxl367_activity_type {
- ADXL367_ACTIVITY,
- ADXL367_INACTIVITY,
- };
- enum adxl367_odr {
- ADXL367_ODR_12P5HZ,
- ADXL367_ODR_25HZ,
- ADXL367_ODR_50HZ,
- ADXL367_ODR_100HZ,
- ADXL367_ODR_200HZ,
- ADXL367_ODR_400HZ,
- };
- struct adxl367_state {
- const struct adxl367_ops *ops;
- void *context;
- struct device *dev;
- struct regmap *regmap;
- struct regulator_bulk_data regulators[2];
- /*
- * Synchronize access to members of driver state, and ensure atomicity
- * of consecutive regmap operations.
- */
- struct mutex lock;
- enum adxl367_odr odr;
- enum adxl367_range range;
- unsigned int act_threshold;
- unsigned int act_time_ms;
- unsigned int inact_threshold;
- unsigned int inact_time_ms;
- unsigned int fifo_set_size;
- unsigned int fifo_watermark;
- __be16 fifo_buf[ADXL367_FIFO_SIZE] __aligned(IIO_DMA_MINALIGN);
- __be16 sample_buf;
- u8 act_threshold_buf[2];
- u8 inact_time_buf[2];
- u8 status_buf[3];
- };
- static const unsigned int adxl367_threshold_h_reg_tbl[] = {
- [ADXL367_ACTIVITY] = ADXL367_REG_THRESH_ACT_H,
- [ADXL367_INACTIVITY] = ADXL367_REG_THRESH_INACT_H,
- };
- static const unsigned int adxl367_act_en_shift_tbl[] = {
- [ADXL367_ACTIVITY] = 0,
- [ADXL367_INACTIVITY] = 2,
- };
- static const unsigned int adxl367_act_int_mask_tbl[] = {
- [ADXL367_ACTIVITY] = ADXL367_INT_ACT_MASK,
- [ADXL367_INACTIVITY] = ADXL367_INT_INACT_MASK,
- };
- static const int adxl367_samp_freq_tbl[][2] = {
- [ADXL367_ODR_12P5HZ] = {12, 500000},
- [ADXL367_ODR_25HZ] = {25, 0},
- [ADXL367_ODR_50HZ] = {50, 0},
- [ADXL367_ODR_100HZ] = {100, 0},
- [ADXL367_ODR_200HZ] = {200, 0},
- [ADXL367_ODR_400HZ] = {400, 0},
- };
- /* (g * 2) * 9.80665 * 1000000 / (2^14 - 1) */
- static const int adxl367_range_scale_tbl[][2] = {
- [ADXL367_2G_RANGE] = {0, 2394347},
- [ADXL367_4G_RANGE] = {0, 4788695},
- [ADXL367_8G_RANGE] = {0, 9577391},
- };
- static const int adxl367_range_scale_factor_tbl[] = {
- [ADXL367_2G_RANGE] = 1,
- [ADXL367_4G_RANGE] = 2,
- [ADXL367_8G_RANGE] = 4,
- };
- enum {
- ADXL367_X_CHANNEL_INDEX,
- ADXL367_Y_CHANNEL_INDEX,
- ADXL367_Z_CHANNEL_INDEX,
- ADXL367_TEMP_CHANNEL_INDEX,
- ADXL367_EX_ADC_CHANNEL_INDEX
- };
- #define ADXL367_X_CHANNEL_MASK BIT(ADXL367_X_CHANNEL_INDEX)
- #define ADXL367_Y_CHANNEL_MASK BIT(ADXL367_Y_CHANNEL_INDEX)
- #define ADXL367_Z_CHANNEL_MASK BIT(ADXL367_Z_CHANNEL_INDEX)
- #define ADXL367_TEMP_CHANNEL_MASK BIT(ADXL367_TEMP_CHANNEL_INDEX)
- #define ADXL367_EX_ADC_CHANNEL_MASK BIT(ADXL367_EX_ADC_CHANNEL_INDEX)
- static const enum adxl367_fifo_format adxl367_fifo_formats[] = {
- ADXL367_FIFO_FORMAT_X,
- ADXL367_FIFO_FORMAT_Y,
- ADXL367_FIFO_FORMAT_Z,
- ADXL367_FIFO_FORMAT_XT,
- ADXL367_FIFO_FORMAT_YT,
- ADXL367_FIFO_FORMAT_ZT,
- ADXL367_FIFO_FORMAT_XA,
- ADXL367_FIFO_FORMAT_YA,
- ADXL367_FIFO_FORMAT_ZA,
- ADXL367_FIFO_FORMAT_XYZ,
- ADXL367_FIFO_FORMAT_XYZT,
- ADXL367_FIFO_FORMAT_XYZA,
- };
- static const unsigned long adxl367_channel_masks[] = {
- ADXL367_X_CHANNEL_MASK,
- ADXL367_Y_CHANNEL_MASK,
- ADXL367_Z_CHANNEL_MASK,
- ADXL367_X_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK,
- ADXL367_Y_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK,
- ADXL367_Z_CHANNEL_MASK | ADXL367_TEMP_CHANNEL_MASK,
- ADXL367_X_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK,
- ADXL367_Y_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK,
- ADXL367_Z_CHANNEL_MASK | ADXL367_EX_ADC_CHANNEL_MASK,
- ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK,
- ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK |
- ADXL367_TEMP_CHANNEL_MASK,
- ADXL367_X_CHANNEL_MASK | ADXL367_Y_CHANNEL_MASK | ADXL367_Z_CHANNEL_MASK |
- ADXL367_EX_ADC_CHANNEL_MASK,
- 0,
- };
- static int adxl367_set_measure_en(struct adxl367_state *st, bool en)
- {
- enum adxl367_op_mode op_mode = en ? ADXL367_OP_MEASURE
- : ADXL367_OP_STANDBY;
- int ret;
- ret = regmap_update_bits(st->regmap, ADXL367_REG_POWER_CTL,
- ADXL367_POWER_CTL_MODE_MASK,
- FIELD_PREP(ADXL367_POWER_CTL_MODE_MASK,
- op_mode));
- if (ret)
- return ret;
- /*
- * Wait for acceleration output to settle after entering
- * measure mode.
- */
- if (en)
- msleep(100);
- return 0;
- }
- static void adxl367_scale_act_thresholds(struct adxl367_state *st,
- enum adxl367_range old_range,
- enum adxl367_range new_range)
- {
- st->act_threshold = st->act_threshold
- * adxl367_range_scale_factor_tbl[old_range]
- / adxl367_range_scale_factor_tbl[new_range];
- st->inact_threshold = st->inact_threshold
- * adxl367_range_scale_factor_tbl[old_range]
- / adxl367_range_scale_factor_tbl[new_range];
- }
- static int _adxl367_set_act_threshold(struct adxl367_state *st,
- enum adxl367_activity_type act,
- unsigned int threshold)
- {
- u8 reg = adxl367_threshold_h_reg_tbl[act];
- int ret;
- if (threshold > ADXL367_THRESH_MAX)
- return -EINVAL;
- st->act_threshold_buf[0] = FIELD_PREP(ADXL367_THRESH_H_MASK,
- FIELD_GET(ADXL367_THRESH_VAL_H_MASK,
- threshold));
- st->act_threshold_buf[1] = FIELD_PREP(ADXL367_THRESH_L_MASK,
- FIELD_GET(ADXL367_THRESH_VAL_L_MASK,
- threshold));
- ret = regmap_bulk_write(st->regmap, reg, st->act_threshold_buf,
- sizeof(st->act_threshold_buf));
- if (ret)
- return ret;
- if (act == ADXL367_ACTIVITY)
- st->act_threshold = threshold;
- else
- st->inact_threshold = threshold;
- return 0;
- }
- static int adxl367_set_act_threshold(struct adxl367_state *st,
- enum adxl367_activity_type act,
- unsigned int threshold)
- {
- int ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = _adxl367_set_act_threshold(st, act, threshold);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static int adxl367_set_act_proc_mode(struct adxl367_state *st,
- enum adxl367_act_proc_mode mode)
- {
- return regmap_update_bits(st->regmap, ADXL367_REG_ACT_INACT_CTL,
- ADXL367_ACT_LINKLOOP_MASK,
- FIELD_PREP(ADXL367_ACT_LINKLOOP_MASK,
- mode));
- }
- static int adxl367_set_act_interrupt_en(struct adxl367_state *st,
- enum adxl367_activity_type act,
- bool en)
- {
- unsigned int mask = adxl367_act_int_mask_tbl[act];
- return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP,
- mask, en ? mask : 0);
- }
- static int adxl367_get_act_interrupt_en(struct adxl367_state *st,
- enum adxl367_activity_type act,
- bool *en)
- {
- unsigned int mask = adxl367_act_int_mask_tbl[act];
- unsigned int val;
- int ret;
- ret = regmap_read(st->regmap, ADXL367_REG_INT1_MAP, &val);
- if (ret)
- return ret;
- *en = !!(val & mask);
- return 0;
- }
- static int adxl367_set_act_en(struct adxl367_state *st,
- enum adxl367_activity_type act,
- enum adxl367_act_en_mode en)
- {
- unsigned int ctl_shift = adxl367_act_en_shift_tbl[act];
- return regmap_update_bits(st->regmap, ADXL367_REG_ACT_INACT_CTL,
- ADXL367_ACT_EN_MASK << ctl_shift,
- en << ctl_shift);
- }
- static int adxl367_set_fifo_watermark_interrupt_en(struct adxl367_state *st,
- bool en)
- {
- return regmap_update_bits(st->regmap, ADXL367_REG_INT1_MAP,
- ADXL367_INT_FIFO_WATERMARK_MASK,
- en ? ADXL367_INT_FIFO_WATERMARK_MASK : 0);
- }
- static int adxl367_get_fifo_mode(struct adxl367_state *st,
- enum adxl367_fifo_mode *fifo_mode)
- {
- unsigned int val;
- int ret;
- ret = regmap_read(st->regmap, ADXL367_REG_FIFO_CTL, &val);
- if (ret)
- return ret;
- *fifo_mode = FIELD_GET(ADXL367_FIFO_CTL_MODE_MASK, val);
- return 0;
- }
- static int adxl367_set_fifo_mode(struct adxl367_state *st,
- enum adxl367_fifo_mode fifo_mode)
- {
- return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL,
- ADXL367_FIFO_CTL_MODE_MASK,
- FIELD_PREP(ADXL367_FIFO_CTL_MODE_MASK,
- fifo_mode));
- }
- static int adxl367_set_fifo_format(struct adxl367_state *st,
- enum adxl367_fifo_format fifo_format)
- {
- return regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL,
- ADXL367_FIFO_CTL_FORMAT_MASK,
- FIELD_PREP(ADXL367_FIFO_CTL_FORMAT_MASK,
- fifo_format));
- }
- static int adxl367_set_fifo_watermark(struct adxl367_state *st,
- unsigned int fifo_watermark)
- {
- unsigned int fifo_samples = fifo_watermark * st->fifo_set_size;
- unsigned int fifo_samples_h, fifo_samples_l;
- int ret;
- if (fifo_samples > ADXL367_FIFO_MAX_WATERMARK)
- fifo_samples = ADXL367_FIFO_MAX_WATERMARK;
- fifo_samples /= st->fifo_set_size;
- fifo_samples_h = FIELD_PREP(ADXL367_SAMPLES_H_MASK,
- FIELD_GET(ADXL367_SAMPLES_VAL_H_MASK,
- fifo_samples));
- fifo_samples_l = FIELD_PREP(ADXL367_SAMPLES_L_MASK,
- FIELD_GET(ADXL367_SAMPLES_VAL_L_MASK,
- fifo_samples));
- ret = regmap_update_bits(st->regmap, ADXL367_REG_FIFO_CTL,
- ADXL367_SAMPLES_H_MASK, fifo_samples_h);
- if (ret)
- return ret;
- ret = regmap_update_bits(st->regmap, ADXL367_REG_FIFO_SAMPLES,
- ADXL367_SAMPLES_L_MASK, fifo_samples_l);
- if (ret)
- return ret;
- st->fifo_watermark = fifo_watermark;
- return 0;
- }
- static int adxl367_set_range(struct iio_dev *indio_dev,
- enum adxl367_range range)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL,
- ADXL367_FILTER_CTL_RANGE_MASK,
- FIELD_PREP(ADXL367_FILTER_CTL_RANGE_MASK,
- range));
- if (ret)
- goto out;
- adxl367_scale_act_thresholds(st, st->range, range);
- /* Activity thresholds depend on range */
- ret = _adxl367_set_act_threshold(st, ADXL367_ACTIVITY,
- st->act_threshold);
- if (ret)
- goto out;
- ret = _adxl367_set_act_threshold(st, ADXL367_INACTIVITY,
- st->inact_threshold);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- if (ret)
- goto out;
- st->range = range;
- out:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret;
- }
- static int adxl367_time_ms_to_samples(struct adxl367_state *st, unsigned int ms)
- {
- int freq_hz = adxl367_samp_freq_tbl[st->odr][0];
- int freq_microhz = adxl367_samp_freq_tbl[st->odr][1];
- /* Scale to decihertz to prevent precision loss in 12.5Hz case. */
- int freq_dhz = freq_hz * 10 + freq_microhz / 100000;
- return DIV_ROUND_CLOSEST(ms * freq_dhz, 10000);
- }
- static int _adxl367_set_act_time_ms(struct adxl367_state *st, unsigned int ms)
- {
- unsigned int val = adxl367_time_ms_to_samples(st, ms);
- int ret;
- if (val > ADXL367_TIME_ACT_MAX)
- val = ADXL367_TIME_ACT_MAX;
- ret = regmap_write(st->regmap, ADXL367_REG_TIME_ACT, val);
- if (ret)
- return ret;
- st->act_time_ms = ms;
- return 0;
- }
- static int _adxl367_set_inact_time_ms(struct adxl367_state *st, unsigned int ms)
- {
- unsigned int val = adxl367_time_ms_to_samples(st, ms);
- int ret;
- if (val > ADXL367_TIME_INACT_MAX)
- val = ADXL367_TIME_INACT_MAX;
- st->inact_time_buf[0] = FIELD_PREP(ADXL367_TIME_INACT_H_MASK,
- FIELD_GET(ADXL367_TIME_INACT_VAL_H_MASK,
- val));
- st->inact_time_buf[1] = FIELD_PREP(ADXL367_TIME_INACT_L_MASK,
- FIELD_GET(ADXL367_TIME_INACT_VAL_L_MASK,
- val));
- ret = regmap_bulk_write(st->regmap, ADXL367_REG_TIME_INACT_H,
- st->inact_time_buf, sizeof(st->inact_time_buf));
- if (ret)
- return ret;
- st->inact_time_ms = ms;
- return 0;
- }
- static int adxl367_set_act_time_ms(struct adxl367_state *st,
- enum adxl367_activity_type act,
- unsigned int ms)
- {
- int ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- if (act == ADXL367_ACTIVITY)
- ret = _adxl367_set_act_time_ms(st, ms);
- else
- ret = _adxl367_set_inact_time_ms(st, ms);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr)
- {
- int ret;
- ret = regmap_update_bits(st->regmap, ADXL367_REG_FILTER_CTL,
- ADXL367_FILTER_CTL_ODR_MASK,
- FIELD_PREP(ADXL367_FILTER_CTL_ODR_MASK,
- odr));
- if (ret)
- return ret;
- /* Activity timers depend on ODR */
- ret = _adxl367_set_act_time_ms(st, st->act_time_ms);
- if (ret)
- return ret;
- ret = _adxl367_set_inact_time_ms(st, st->inact_time_ms);
- if (ret)
- return ret;
- st->odr = odr;
- return 0;
- }
- static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = _adxl367_set_odr(st, odr);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret;
- }
- static int adxl367_set_temp_adc_en(struct adxl367_state *st, unsigned int reg,
- bool en)
- {
- return regmap_update_bits(st->regmap, reg, ADXL367_ADC_EN_MASK,
- en ? ADXL367_ADC_EN_MASK : 0);
- }
- static int adxl367_set_temp_adc_reg_en(struct adxl367_state *st,
- unsigned int reg, bool en)
- {
- int ret;
- switch (reg) {
- case ADXL367_REG_TEMP_DATA_H:
- ret = adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en);
- break;
- case ADXL367_REG_EX_ADC_DATA_H:
- ret = adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en);
- break;
- default:
- return 0;
- }
- if (ret)
- return ret;
- if (en)
- msleep(100);
- return 0;
- }
- static int adxl367_set_temp_adc_mask_en(struct adxl367_state *st,
- const unsigned long *active_scan_mask,
- bool en)
- {
- if (*active_scan_mask & ADXL367_TEMP_CHANNEL_MASK)
- return adxl367_set_temp_adc_en(st, ADXL367_REG_TEMP_CTL, en);
- else if (*active_scan_mask & ADXL367_EX_ADC_CHANNEL_MASK)
- return adxl367_set_temp_adc_en(st, ADXL367_REG_ADC_CTL, en);
- return 0;
- }
- static int adxl367_find_odr(struct adxl367_state *st, int val, int val2,
- enum adxl367_odr *odr)
- {
- size_t size = ARRAY_SIZE(adxl367_samp_freq_tbl);
- int i;
- for (i = 0; i < size; i++)
- if (val == adxl367_samp_freq_tbl[i][0] &&
- val2 == adxl367_samp_freq_tbl[i][1])
- break;
- if (i == size)
- return -EINVAL;
- *odr = i;
- return 0;
- }
- static int adxl367_find_range(struct adxl367_state *st, int val, int val2,
- enum adxl367_range *range)
- {
- size_t size = ARRAY_SIZE(adxl367_range_scale_tbl);
- int i;
- for (i = 0; i < size; i++)
- if (val == adxl367_range_scale_tbl[i][0] &&
- val2 == adxl367_range_scale_tbl[i][1])
- break;
- if (i == size)
- return -EINVAL;
- *range = i;
- return 0;
- }
- static int adxl367_read_sample(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- u16 sample;
- int ret;
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_temp_adc_reg_en(st, chan->address, true);
- if (ret)
- goto out;
- ret = regmap_bulk_read(st->regmap, chan->address, &st->sample_buf,
- sizeof(st->sample_buf));
- if (ret)
- goto out;
- sample = FIELD_GET(ADXL367_DATA_MASK, be16_to_cpu(st->sample_buf));
- *val = sign_extend32(sample, chan->scan_type.realbits - 1);
- ret = adxl367_set_temp_adc_reg_en(st, chan->address, false);
- out:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret ?: IIO_VAL_INT;
- }
- static int adxl367_get_status(struct adxl367_state *st, u8 *status,
- u16 *fifo_entries)
- {
- int ret;
- /* Read STATUS, FIFO_ENT_L and FIFO_ENT_H */
- ret = regmap_bulk_read(st->regmap, ADXL367_REG_STATUS,
- st->status_buf, sizeof(st->status_buf));
- if (ret)
- return ret;
- st->status_buf[2] &= ADXL367_FIFO_ENT_H_MASK;
- *status = st->status_buf[0];
- *fifo_entries = get_unaligned_le16(&st->status_buf[1]);
- return 0;
- }
- static bool adxl367_push_event(struct iio_dev *indio_dev, u8 status)
- {
- unsigned int ev_dir;
- if (FIELD_GET(ADXL367_STATUS_ACT_MASK, status))
- ev_dir = IIO_EV_DIR_RISING;
- else if (FIELD_GET(ADXL367_STATUS_INACT_MASK, status))
- ev_dir = IIO_EV_DIR_FALLING;
- else
- return false;
- iio_push_event(indio_dev,
- IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X_OR_Y_OR_Z,
- IIO_EV_TYPE_THRESH, ev_dir),
- iio_get_time_ns(indio_dev));
- return true;
- }
- static bool adxl367_push_fifo_data(struct iio_dev *indio_dev, u8 status,
- u16 fifo_entries)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- int i;
- if (!FIELD_GET(ADXL367_STATUS_FIFO_FULL_MASK, status))
- return false;
- fifo_entries -= fifo_entries % st->fifo_set_size;
- ret = st->ops->read_fifo(st->context, st->fifo_buf, fifo_entries);
- if (ret) {
- dev_err(st->dev, "Failed to read FIFO: %d\n", ret);
- return true;
- }
- for (i = 0; i < fifo_entries; i += st->fifo_set_size)
- iio_push_to_buffers(indio_dev, &st->fifo_buf[i]);
- return true;
- }
- static irqreturn_t adxl367_irq_handler(int irq, void *private)
- {
- struct iio_dev *indio_dev = private;
- struct adxl367_state *st = iio_priv(indio_dev);
- u16 fifo_entries;
- bool handled;
- u8 status;
- int ret;
- ret = adxl367_get_status(st, &status, &fifo_entries);
- if (ret)
- return IRQ_NONE;
- handled = adxl367_push_event(indio_dev, status);
- handled |= adxl367_push_fifo_data(indio_dev, status, fifo_entries);
- return handled ? IRQ_HANDLED : IRQ_NONE;
- }
- static int adxl367_reg_access(struct iio_dev *indio_dev,
- unsigned int reg,
- unsigned int writeval,
- unsigned int *readval)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- if (readval)
- return regmap_read(st->regmap, reg, readval);
- else
- return regmap_write(st->regmap, reg, writeval);
- }
- static int adxl367_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long info)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- switch (info) {
- case IIO_CHAN_INFO_RAW:
- return adxl367_read_sample(indio_dev, chan, val);
- case IIO_CHAN_INFO_SCALE:
- switch (chan->type) {
- case IIO_ACCEL:
- mutex_lock(&st->lock);
- *val = adxl367_range_scale_tbl[st->range][0];
- *val2 = adxl367_range_scale_tbl[st->range][1];
- mutex_unlock(&st->lock);
- return IIO_VAL_INT_PLUS_NANO;
- case IIO_TEMP:
- *val = 1000;
- *val2 = ADXL367_TEMP_PER_C;
- return IIO_VAL_FRACTIONAL;
- case IIO_VOLTAGE:
- *val = ADXL367_VOLTAGE_MAX_MV;
- *val2 = ADXL367_VOLTAGE_MAX_RAW;
- return IIO_VAL_FRACTIONAL;
- default:
- return -EINVAL;
- }
- case IIO_CHAN_INFO_OFFSET:
- switch (chan->type) {
- case IIO_TEMP:
- *val = 25 * ADXL367_TEMP_PER_C - ADXL367_TEMP_25C;
- return IIO_VAL_INT;
- case IIO_VOLTAGE:
- *val = ADXL367_VOLTAGE_OFFSET;
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- case IIO_CHAN_INFO_SAMP_FREQ:
- mutex_lock(&st->lock);
- *val = adxl367_samp_freq_tbl[st->odr][0];
- *val2 = adxl367_samp_freq_tbl[st->odr][1];
- mutex_unlock(&st->lock);
- return IIO_VAL_INT_PLUS_MICRO;
- default:
- return -EINVAL;
- }
- }
- static int adxl367_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long info)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- switch (info) {
- case IIO_CHAN_INFO_SAMP_FREQ: {
- enum adxl367_odr odr;
- ret = adxl367_find_odr(st, val, val2, &odr);
- if (ret)
- return ret;
- return adxl367_set_odr(indio_dev, odr);
- }
- case IIO_CHAN_INFO_SCALE: {
- enum adxl367_range range;
- ret = adxl367_find_range(st, val, val2, &range);
- if (ret)
- return ret;
- return adxl367_set_range(indio_dev, range);
- }
- default:
- return -EINVAL;
- }
- }
- static int adxl367_write_raw_get_fmt(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- long info)
- {
- switch (info) {
- case IIO_CHAN_INFO_SCALE:
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
- return IIO_VAL_INT_PLUS_NANO;
- default:
- return IIO_VAL_INT_PLUS_MICRO;
- }
- }
- static int adxl367_read_avail(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- const int **vals, int *type, int *length,
- long info)
- {
- switch (info) {
- case IIO_CHAN_INFO_SCALE:
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
- *vals = (int *)adxl367_range_scale_tbl;
- *type = IIO_VAL_INT_PLUS_NANO;
- *length = ARRAY_SIZE(adxl367_range_scale_tbl) * 2;
- return IIO_AVAIL_LIST;
- case IIO_CHAN_INFO_SAMP_FREQ:
- *vals = (int *)adxl367_samp_freq_tbl;
- *type = IIO_VAL_INT_PLUS_MICRO;
- *length = ARRAY_SIZE(adxl367_samp_freq_tbl) * 2;
- return IIO_AVAIL_LIST;
- default:
- return -EINVAL;
- }
- }
- static int adxl367_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 adxl367_state *st = iio_priv(indio_dev);
- switch (info) {
- case IIO_EV_INFO_VALUE: {
- switch (dir) {
- case IIO_EV_DIR_RISING:
- mutex_lock(&st->lock);
- *val = st->act_threshold;
- mutex_unlock(&st->lock);
- return IIO_VAL_INT;
- case IIO_EV_DIR_FALLING:
- mutex_lock(&st->lock);
- *val = st->inact_threshold;
- mutex_unlock(&st->lock);
- return IIO_VAL_INT;
- default:
- return -EINVAL;
- }
- }
- case IIO_EV_INFO_PERIOD:
- switch (dir) {
- case IIO_EV_DIR_RISING:
- mutex_lock(&st->lock);
- *val = st->act_time_ms;
- mutex_unlock(&st->lock);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
- case IIO_EV_DIR_FALLING:
- mutex_lock(&st->lock);
- *val = st->inact_time_ms;
- mutex_unlock(&st->lock);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
- default:
- return -EINVAL;
- }
- default:
- return -EINVAL;
- }
- }
- static int adxl367_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 adxl367_state *st = iio_priv(indio_dev);
- switch (info) {
- case IIO_EV_INFO_VALUE:
- if (val < 0)
- return -EINVAL;
- switch (dir) {
- case IIO_EV_DIR_RISING:
- return adxl367_set_act_threshold(st, ADXL367_ACTIVITY, val);
- case IIO_EV_DIR_FALLING:
- return adxl367_set_act_threshold(st, ADXL367_INACTIVITY, val);
- default:
- return -EINVAL;
- }
- case IIO_EV_INFO_PERIOD:
- if (val < 0)
- return -EINVAL;
- val = val * 1000 + DIV_ROUND_UP(val2, 1000);
- switch (dir) {
- case IIO_EV_DIR_RISING:
- return adxl367_set_act_time_ms(st, ADXL367_ACTIVITY, val);
- case IIO_EV_DIR_FALLING:
- return adxl367_set_act_time_ms(st, ADXL367_INACTIVITY, val);
- default:
- return -EINVAL;
- }
- default:
- return -EINVAL;
- }
- }
- static int adxl367_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 adxl367_state *st = iio_priv(indio_dev);
- bool en;
- int ret;
- switch (dir) {
- case IIO_EV_DIR_RISING:
- ret = adxl367_get_act_interrupt_en(st, ADXL367_ACTIVITY, &en);
- return ret ?: en;
- case IIO_EV_DIR_FALLING:
- ret = adxl367_get_act_interrupt_en(st, ADXL367_INACTIVITY, &en);
- return ret ?: en;
- default:
- return -EINVAL;
- }
- }
- static int adxl367_write_event_config(struct iio_dev *indio_dev,
- const struct iio_chan_spec *chan,
- enum iio_event_type type,
- enum iio_event_direction dir,
- int state)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- enum adxl367_activity_type act;
- int ret;
- switch (dir) {
- case IIO_EV_DIR_RISING:
- act = ADXL367_ACTIVITY;
- break;
- case IIO_EV_DIR_FALLING:
- act = ADXL367_INACTIVITY;
- break;
- default:
- return -EINVAL;
- }
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_act_interrupt_en(st, act, state);
- if (ret)
- goto out;
- ret = adxl367_set_act_en(st, act, state ? ADCL367_ACT_REF_ENABLED
- : ADXL367_ACT_DISABLED);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- iio_device_release_direct_mode(indio_dev);
- return ret;
- }
- static ssize_t adxl367_get_fifo_enabled(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- struct adxl367_state *st = iio_priv(dev_to_iio_dev(dev));
- enum adxl367_fifo_mode fifo_mode;
- int ret;
- ret = adxl367_get_fifo_mode(st, &fifo_mode);
- if (ret)
- return ret;
- return sysfs_emit(buf, "%d\n", fifo_mode != ADXL367_FIFO_MODE_DISABLED);
- }
- static ssize_t adxl367_get_fifo_watermark(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- struct adxl367_state *st = iio_priv(dev_to_iio_dev(dev));
- unsigned int fifo_watermark;
- mutex_lock(&st->lock);
- fifo_watermark = st->fifo_watermark;
- mutex_unlock(&st->lock);
- return sysfs_emit(buf, "%d\n", fifo_watermark);
- }
- static ssize_t hwfifo_watermark_min_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- return sysfs_emit(buf, "%s\n", "1");
- }
- static ssize_t hwfifo_watermark_max_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
- {
- return sysfs_emit(buf, "%s\n", __stringify(ADXL367_FIFO_MAX_WATERMARK));
- }
- static IIO_DEVICE_ATTR_RO(hwfifo_watermark_min, 0);
- static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
- static IIO_DEVICE_ATTR(hwfifo_watermark, 0444,
- adxl367_get_fifo_watermark, NULL, 0);
- static IIO_DEVICE_ATTR(hwfifo_enabled, 0444,
- adxl367_get_fifo_enabled, NULL, 0);
- static const struct attribute *adxl367_fifo_attributes[] = {
- &iio_dev_attr_hwfifo_watermark_min.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
- &iio_dev_attr_hwfifo_watermark.dev_attr.attr,
- &iio_dev_attr_hwfifo_enabled.dev_attr.attr,
- NULL,
- };
- static int adxl367_set_watermark(struct iio_dev *indio_dev, unsigned int val)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- if (val > ADXL367_FIFO_MAX_WATERMARK)
- return -EINVAL;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_watermark(st, val);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static bool adxl367_find_mask_fifo_format(const unsigned long *scan_mask,
- enum adxl367_fifo_format *fifo_format)
- {
- size_t size = ARRAY_SIZE(adxl367_fifo_formats);
- int i;
- for (i = 0; i < size; i++)
- if (*scan_mask == adxl367_channel_masks[i])
- break;
- if (i == size)
- return false;
- *fifo_format = adxl367_fifo_formats[i];
- return true;
- }
- static int adxl367_update_scan_mode(struct iio_dev *indio_dev,
- const unsigned long *active_scan_mask)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- enum adxl367_fifo_format fifo_format;
- int ret;
- if (!adxl367_find_mask_fifo_format(active_scan_mask, &fifo_format))
- return -EINVAL;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_format(st, fifo_format);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- if (ret)
- goto out;
- st->fifo_set_size = bitmap_weight(active_scan_mask,
- indio_dev->masklength);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static int adxl367_buffer_postenable(struct iio_dev *indio_dev)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,
- true);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_watermark_interrupt_en(st, true);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_STREAM);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static int adxl367_buffer_predisable(struct iio_dev *indio_dev)
- {
- struct adxl367_state *st = iio_priv(indio_dev);
- int ret;
- mutex_lock(&st->lock);
- ret = adxl367_set_measure_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_mode(st, ADXL367_FIFO_MODE_DISABLED);
- if (ret)
- goto out;
- ret = adxl367_set_fifo_watermark_interrupt_en(st, false);
- if (ret)
- goto out;
- ret = adxl367_set_measure_en(st, true);
- if (ret)
- goto out;
- ret = adxl367_set_temp_adc_mask_en(st, indio_dev->active_scan_mask,
- false);
- out:
- mutex_unlock(&st->lock);
- return ret;
- }
- static const struct iio_buffer_setup_ops adxl367_buffer_ops = {
- .postenable = adxl367_buffer_postenable,
- .predisable = adxl367_buffer_predisable,
- };
- static const struct iio_info adxl367_info = {
- .read_raw = adxl367_read_raw,
- .write_raw = adxl367_write_raw,
- .write_raw_get_fmt = adxl367_write_raw_get_fmt,
- .read_avail = adxl367_read_avail,
- .read_event_config = adxl367_read_event_config,
- .write_event_config = adxl367_write_event_config,
- .read_event_value = adxl367_read_event_value,
- .write_event_value = adxl367_write_event_value,
- .debugfs_reg_access = adxl367_reg_access,
- .hwfifo_set_watermark = adxl367_set_watermark,
- .update_scan_mode = adxl367_update_scan_mode,
- };
- static const struct iio_event_spec adxl367_events[] = {
- {
- .type = IIO_EV_TYPE_MAG_REFERENCED,
- .dir = IIO_EV_DIR_RISING,
- .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
- BIT(IIO_EV_INFO_PERIOD) |
- BIT(IIO_EV_INFO_VALUE),
- },
- {
- .type = IIO_EV_TYPE_MAG_REFERENCED,
- .dir = IIO_EV_DIR_FALLING,
- .mask_shared_by_type = BIT(IIO_EV_INFO_ENABLE) |
- BIT(IIO_EV_INFO_PERIOD) |
- BIT(IIO_EV_INFO_VALUE),
- },
- };
- #define ADXL367_ACCEL_CHANNEL(index, reg, axis) { \
- .type = IIO_ACCEL, \
- .address = (reg), \
- .modified = 1, \
- .channel2 = IIO_MOD_##axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
- .info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE), \
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .info_mask_shared_by_all_available = \
- BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .event_spec = adxl367_events, \
- .num_event_specs = ARRAY_SIZE(adxl367_events), \
- .scan_index = (index), \
- .scan_type = { \
- .sign = 's', \
- .realbits = 14, \
- .storagebits = 16, \
- .endianness = IIO_BE, \
- }, \
- }
- #define ADXL367_CHANNEL(index, reg, _type) { \
- .type = (_type), \
- .address = (reg), \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_OFFSET) | \
- BIT(IIO_CHAN_INFO_SCALE), \
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
- .scan_index = (index), \
- .scan_type = { \
- .sign = 's', \
- .realbits = 14, \
- .storagebits = 16, \
- .endianness = IIO_BE, \
- }, \
- }
- static const struct iio_chan_spec adxl367_channels[] = {
- ADXL367_ACCEL_CHANNEL(ADXL367_X_CHANNEL_INDEX, ADXL367_REG_X_DATA_H, X),
- ADXL367_ACCEL_CHANNEL(ADXL367_Y_CHANNEL_INDEX, ADXL367_REG_Y_DATA_H, Y),
- ADXL367_ACCEL_CHANNEL(ADXL367_Z_CHANNEL_INDEX, ADXL367_REG_Z_DATA_H, Z),
- ADXL367_CHANNEL(ADXL367_TEMP_CHANNEL_INDEX, ADXL367_REG_TEMP_DATA_H,
- IIO_TEMP),
- ADXL367_CHANNEL(ADXL367_EX_ADC_CHANNEL_INDEX, ADXL367_REG_EX_ADC_DATA_H,
- IIO_VOLTAGE),
- };
- static int adxl367_verify_devid(struct adxl367_state *st)
- {
- unsigned int val;
- int ret;
- ret = regmap_read_poll_timeout(st->regmap, ADXL367_REG_DEVID, val,
- val == ADXL367_DEVID_AD, 1000, 10000);
- if (ret)
- return dev_err_probe(st->dev, -ENODEV,
- "Invalid dev id 0x%02X, expected 0x%02X\n",
- val, ADXL367_DEVID_AD);
- return 0;
- }
- static int adxl367_setup(struct adxl367_state *st)
- {
- int ret;
- ret = _adxl367_set_act_threshold(st, ADXL367_ACTIVITY,
- ADXL367_2G_RANGE_1G);
- if (ret)
- return ret;
- ret = _adxl367_set_act_threshold(st, ADXL367_INACTIVITY,
- ADXL367_2G_RANGE_100MG);
- if (ret)
- return ret;
- ret = adxl367_set_act_proc_mode(st, ADXL367_LOOPED);
- if (ret)
- return ret;
- ret = _adxl367_set_odr(st, ADXL367_ODR_400HZ);
- if (ret)
- return ret;
- ret = _adxl367_set_act_time_ms(st, 10);
- if (ret)
- return ret;
- ret = _adxl367_set_inact_time_ms(st, 10000);
- if (ret)
- return ret;
- return adxl367_set_measure_en(st, true);
- }
- static void adxl367_disable_regulators(void *data)
- {
- struct adxl367_state *st = data;
- regulator_bulk_disable(ARRAY_SIZE(st->regulators), st->regulators);
- }
- int adxl367_probe(struct device *dev, const struct adxl367_ops *ops,
- void *context, struct regmap *regmap, int irq)
- {
- struct iio_dev *indio_dev;
- struct adxl367_state *st;
- int ret;
- indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
- if (!indio_dev)
- return -ENOMEM;
- st = iio_priv(indio_dev);
- st->dev = dev;
- st->regmap = regmap;
- st->context = context;
- st->ops = ops;
- mutex_init(&st->lock);
- indio_dev->channels = adxl367_channels;
- indio_dev->num_channels = ARRAY_SIZE(adxl367_channels);
- indio_dev->available_scan_masks = adxl367_channel_masks;
- indio_dev->name = "adxl367";
- indio_dev->info = &adxl367_info;
- indio_dev->modes = INDIO_DIRECT_MODE;
- st->regulators[0].supply = "vdd";
- st->regulators[1].supply = "vddio";
- ret = devm_regulator_bulk_get(st->dev, ARRAY_SIZE(st->regulators),
- st->regulators);
- if (ret)
- return dev_err_probe(st->dev, ret,
- "Failed to get regulators\n");
- ret = regulator_bulk_enable(ARRAY_SIZE(st->regulators), st->regulators);
- if (ret)
- return dev_err_probe(st->dev, ret,
- "Failed to enable regulators\n");
- ret = devm_add_action_or_reset(st->dev, adxl367_disable_regulators, st);
- if (ret)
- return dev_err_probe(st->dev, ret,
- "Failed to add regulators disable action\n");
- ret = regmap_write(st->regmap, ADXL367_REG_RESET, ADXL367_RESET_CODE);
- if (ret)
- return ret;
- ret = adxl367_verify_devid(st);
- if (ret)
- return ret;
- ret = adxl367_setup(st);
- if (ret)
- return ret;
- ret = devm_iio_kfifo_buffer_setup_ext(st->dev, indio_dev,
- &adxl367_buffer_ops,
- adxl367_fifo_attributes);
- if (ret)
- return ret;
- ret = devm_request_threaded_irq(st->dev, irq, NULL,
- adxl367_irq_handler, IRQF_ONESHOT,
- indio_dev->name, indio_dev);
- if (ret)
- return dev_err_probe(st->dev, ret, "Failed to request irq\n");
- return devm_iio_device_register(dev, indio_dev);
- }
- EXPORT_SYMBOL_NS_GPL(adxl367_probe, IIO_ADXL367);
- MODULE_AUTHOR("Cosmin Tanislav <[email protected]>");
- MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer driver");
- MODULE_LICENSE("GPL");
|