1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d62e5feeSJonathan Cameron /* 3d62e5feeSJonathan Cameron * sca3000_core.c -- support VTI sca3000 series accelerometers via SPI 4d62e5feeSJonathan Cameron * 5d62e5feeSJonathan Cameron * Copyright (c) 2009 Jonathan Cameron <jic23@kernel.org> 6d62e5feeSJonathan Cameron * 7d62e5feeSJonathan Cameron * See industrialio/accels/sca3000.h for comments. 8d62e5feeSJonathan Cameron */ 9d62e5feeSJonathan Cameron 10d62e5feeSJonathan Cameron #include <linux/interrupt.h> 11d62e5feeSJonathan Cameron #include <linux/fs.h> 12d62e5feeSJonathan Cameron #include <linux/device.h> 13d62e5feeSJonathan Cameron #include <linux/slab.h> 14d62e5feeSJonathan Cameron #include <linux/kernel.h> 15d62e5feeSJonathan Cameron #include <linux/spi/spi.h> 16d62e5feeSJonathan Cameron #include <linux/sysfs.h> 17d62e5feeSJonathan Cameron #include <linux/module.h> 18d62e5feeSJonathan Cameron #include <linux/uaccess.h> 19d62e5feeSJonathan Cameron #include <linux/iio/iio.h> 20d62e5feeSJonathan Cameron #include <linux/iio/sysfs.h> 21d62e5feeSJonathan Cameron #include <linux/iio/events.h> 22d62e5feeSJonathan Cameron #include <linux/iio/buffer.h> 23d62e5feeSJonathan Cameron #include <linux/iio/kfifo_buf.h> 24d62e5feeSJonathan Cameron 25d62e5feeSJonathan Cameron #define SCA3000_WRITE_REG(a) (((a) << 2) | 0x02) 26d62e5feeSJonathan Cameron #define SCA3000_READ_REG(a) ((a) << 2) 27d62e5feeSJonathan Cameron 28d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_ADDR 0x00 29d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_MAJOR_MASK GENMASK(8, 4) 30d62e5feeSJonathan Cameron #define SCA3000_REG_REVID_MINOR_MASK GENMASK(3, 0) 31d62e5feeSJonathan Cameron 32d62e5feeSJonathan Cameron #define SCA3000_REG_STATUS_ADDR 0x02 33d62e5feeSJonathan Cameron #define SCA3000_LOCKED BIT(5) 34d62e5feeSJonathan Cameron #define SCA3000_EEPROM_CS_ERROR BIT(1) 35d62e5feeSJonathan Cameron #define SCA3000_SPI_FRAME_ERROR BIT(0) 36d62e5feeSJonathan Cameron 37d62e5feeSJonathan Cameron /* All reads done using register decrement so no need to directly access LSBs */ 38d62e5feeSJonathan Cameron #define SCA3000_REG_X_MSB_ADDR 0x05 39d62e5feeSJonathan Cameron #define SCA3000_REG_Y_MSB_ADDR 0x07 40d62e5feeSJonathan Cameron #define SCA3000_REG_Z_MSB_ADDR 0x09 41d62e5feeSJonathan Cameron 42d62e5feeSJonathan Cameron #define SCA3000_REG_RING_OUT_ADDR 0x0f 43d62e5feeSJonathan Cameron 44d62e5feeSJonathan Cameron /* Temp read untested - the e05 doesn't have the sensor */ 45d62e5feeSJonathan Cameron #define SCA3000_REG_TEMP_MSB_ADDR 0x13 46d62e5feeSJonathan Cameron 47d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_ADDR 0x14 48d62e5feeSJonathan Cameron #define SCA3000_MODE_PROT_MASK 0x28 49d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_RING_BUF_ENABLE BIT(7) 50d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_RING_BUF_8BIT BIT(6) 51d62e5feeSJonathan Cameron 52d62e5feeSJonathan Cameron /* 53d62e5feeSJonathan Cameron * Free fall detection triggers an interrupt if the acceleration 54d62e5feeSJonathan Cameron * is below a threshold for equivalent of 25cm drop 55d62e5feeSJonathan Cameron */ 56d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_FREE_FALL_DETECT BIT(4) 57d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_NORMAL 0x00 58d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_OP_1 0x01 59d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_OP_2 0x02 60d62e5feeSJonathan Cameron 61d62e5feeSJonathan Cameron /* 62d62e5feeSJonathan Cameron * In motion detection mode the accelerations are band pass filtered 63d62e5feeSJonathan Cameron * (approx 1 - 25Hz) and then a programmable threshold used to trigger 64d62e5feeSJonathan Cameron * and interrupt. 65d62e5feeSJonathan Cameron */ 66d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MEAS_MODE_MOT_DET 0x03 67d62e5feeSJonathan Cameron #define SCA3000_REG_MODE_MODE_MASK 0x03 68d62e5feeSJonathan Cameron 69d62e5feeSJonathan Cameron #define SCA3000_REG_BUF_COUNT_ADDR 0x15 70d62e5feeSJonathan Cameron 71d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_ADDR 0x16 72d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_THREE_QUARTERS BIT(7) 73d62e5feeSJonathan Cameron #define SCA3000_REG_INT_STATUS_HALF BIT(6) 74d62e5feeSJonathan Cameron 75d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_FREE_FALL BIT(3) 76d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_Y_TRIGGER BIT(2) 77d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_X_TRIGGER BIT(1) 78d62e5feeSJonathan Cameron #define SCA3000_INT_STATUS_Z_TRIGGER BIT(0) 79d62e5feeSJonathan Cameron 80d62e5feeSJonathan Cameron /* Used to allow access to multiplexed registers */ 81d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_ADDR 0x18 82d62e5feeSJonathan Cameron /* Only available for SCA3000-D03 and SCA3000-D01 */ 83d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_I2C_DISABLE 0x01 84d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_CTRL 0x02 85d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_Y_TH 0x03 86d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_X_TH 0x04 87d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_MD_Z_TH 0x05 88d62e5feeSJonathan Cameron /* 89d62e5feeSJonathan Cameron * BE VERY CAREFUL WITH THIS, IF 3 BITS ARE NOT SET the device 90d62e5feeSJonathan Cameron * will not function 91d62e5feeSJonathan Cameron */ 92d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_SEL_OUT_CTRL 0x0B 93d62e5feeSJonathan Cameron 94d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_PROT_MASK 0xE0 95d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_X_EN 0x10 96d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_Y_EN 0x08 97d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_Z_EN 0x04 98d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_MASK 0x03 99d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_4 0x02 100d62e5feeSJonathan Cameron #define SCA3000_REG_OUT_CTRL_BUF_DIV_2 0x01 101d62e5feeSJonathan Cameron 102d62e5feeSJonathan Cameron 103d62e5feeSJonathan Cameron /* 104d62e5feeSJonathan Cameron * Control which motion detector interrupts are on. 105d62e5feeSJonathan Cameron * For now only OR combinations are supported. 106d62e5feeSJonathan Cameron */ 107d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_PROT_MASK 0xC0 108d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_Y BIT(0) 109d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_X BIT(1) 110d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_OR_Z BIT(2) 111d62e5feeSJonathan Cameron /* Currently unsupported */ 112d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_AND_Y BIT(3) 113d62e5feeSJonathan Cameron #define SCA3000_MD_CTRL_AND_X BIT(4) 11480343f5bSChristophe JAILLET #define SCA3000_MD_CTRL_AND_Z BIT(5) 115d62e5feeSJonathan Cameron 116d62e5feeSJonathan Cameron /* 117d62e5feeSJonathan Cameron * Some control registers of complex access methods requiring this register to 118d62e5feeSJonathan Cameron * be used to remove a lock. 119d62e5feeSJonathan Cameron */ 120d62e5feeSJonathan Cameron #define SCA3000_REG_UNLOCK_ADDR 0x1e 121d62e5feeSJonathan Cameron 122d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ADDR 0x21 123d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_PROT_MASK 0x1C 124d62e5feeSJonathan Cameron 125d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_RING_THREE_QUARTER BIT(7) 126d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_RING_HALF BIT(6) 127d62e5feeSJonathan Cameron 128d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ALL_INTS 0x02 129d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ACTIVE_HIGH 0x01 130d62e5feeSJonathan Cameron #define SCA3000_REG_INT_MASK_ACTIVE_LOW 0x00 131d62e5feeSJonathan Cameron /* Values of multiplexed registers (write to ctrl_data after select) */ 132d62e5feeSJonathan Cameron #define SCA3000_REG_CTRL_DATA_ADDR 0x22 133d62e5feeSJonathan Cameron 134d62e5feeSJonathan Cameron /* 135d62e5feeSJonathan Cameron * Measurement modes available on some sca3000 series chips. Code assumes others 136d62e5feeSJonathan Cameron * may become available in the future. 137d62e5feeSJonathan Cameron * 138d62e5feeSJonathan Cameron * Bypass - Bypass the low-pass filter in the signal channel so as to increase 139d62e5feeSJonathan Cameron * signal bandwidth. 140d62e5feeSJonathan Cameron * 141d62e5feeSJonathan Cameron * Narrow - Narrow low-pass filtering of the signal channel and half output 142d62e5feeSJonathan Cameron * data rate by decimation. 143d62e5feeSJonathan Cameron * 144d62e5feeSJonathan Cameron * Wide - Widen low-pass filtering of signal channel to increase bandwidth 145d62e5feeSJonathan Cameron */ 146d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_BYPASS 0x01 147d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_NARROW 0x02 148d62e5feeSJonathan Cameron #define SCA3000_OP_MODE_WIDE 0x04 149d62e5feeSJonathan Cameron #define SCA3000_MAX_TX 6 150d62e5feeSJonathan Cameron #define SCA3000_MAX_RX 2 151d62e5feeSJonathan Cameron 152d62e5feeSJonathan Cameron /** 153d62e5feeSJonathan Cameron * struct sca3000_state - device instance state information 154d62e5feeSJonathan Cameron * @us: the associated spi device 155d62e5feeSJonathan Cameron * @info: chip variant information 156d62e5feeSJonathan Cameron * @last_timestamp: the timestamp of the last event 157d62e5feeSJonathan Cameron * @mo_det_use_count: reference counter for the motion detection unit 158d62e5feeSJonathan Cameron * @lock: lock used to protect elements of sca3000_state 159d62e5feeSJonathan Cameron * and the underlying device state. 160d62e5feeSJonathan Cameron * @tx: dma-able transmit buffer 161d62e5feeSJonathan Cameron * @rx: dma-able receive buffer 162d62e5feeSJonathan Cameron **/ 163d62e5feeSJonathan Cameron struct sca3000_state { 164d62e5feeSJonathan Cameron struct spi_device *us; 165d62e5feeSJonathan Cameron const struct sca3000_chip_info *info; 166d62e5feeSJonathan Cameron s64 last_timestamp; 167d62e5feeSJonathan Cameron int mo_det_use_count; 168d62e5feeSJonathan Cameron struct mutex lock; 169d62e5feeSJonathan Cameron /* Can these share a cacheline ? */ 170d62e5feeSJonathan Cameron u8 rx[384] ____cacheline_aligned; 171d62e5feeSJonathan Cameron u8 tx[6] ____cacheline_aligned; 172d62e5feeSJonathan Cameron }; 173d62e5feeSJonathan Cameron 174d62e5feeSJonathan Cameron /** 175d62e5feeSJonathan Cameron * struct sca3000_chip_info - model dependent parameters 176d62e5feeSJonathan Cameron * @scale: scale * 10^-6 177d62e5feeSJonathan Cameron * @temp_output: some devices have temperature sensors. 178d62e5feeSJonathan Cameron * @measurement_mode_freq: normal mode sampling frequency 179d62e5feeSJonathan Cameron * @measurement_mode_3db_freq: 3db cutoff frequency of the low pass filter for 180d62e5feeSJonathan Cameron * the normal measurement mode. 181d62e5feeSJonathan Cameron * @option_mode_1: first optional mode. Not all models have one 182d62e5feeSJonathan Cameron * @option_mode_1_freq: option mode 1 sampling frequency 183d62e5feeSJonathan Cameron * @option_mode_1_3db_freq: 3db cutoff frequency of the low pass filter for 184d62e5feeSJonathan Cameron * the first option mode. 185d62e5feeSJonathan Cameron * @option_mode_2: second optional mode. Not all chips have one 186d62e5feeSJonathan Cameron * @option_mode_2_freq: option mode 2 sampling frequency 187d62e5feeSJonathan Cameron * @option_mode_2_3db_freq: 3db cutoff frequency of the low pass filter for 188d62e5feeSJonathan Cameron * the second option mode. 189d62e5feeSJonathan Cameron * @mod_det_mult_xz: Bit wise multipliers to calculate the threshold 190d62e5feeSJonathan Cameron * for motion detection in the x and z axis. 191d62e5feeSJonathan Cameron * @mod_det_mult_y: Bit wise multipliers to calculate the threshold 192d62e5feeSJonathan Cameron * for motion detection in the y axis. 193d62e5feeSJonathan Cameron * 194d62e5feeSJonathan Cameron * This structure is used to hold information about the functionality of a given 195d62e5feeSJonathan Cameron * sca3000 variant. 196d62e5feeSJonathan Cameron **/ 197d62e5feeSJonathan Cameron struct sca3000_chip_info { 198d62e5feeSJonathan Cameron unsigned int scale; 199d62e5feeSJonathan Cameron bool temp_output; 200d62e5feeSJonathan Cameron int measurement_mode_freq; 201d62e5feeSJonathan Cameron int measurement_mode_3db_freq; 202d62e5feeSJonathan Cameron int option_mode_1; 203d62e5feeSJonathan Cameron int option_mode_1_freq; 204d62e5feeSJonathan Cameron int option_mode_1_3db_freq; 205d62e5feeSJonathan Cameron int option_mode_2; 206d62e5feeSJonathan Cameron int option_mode_2_freq; 207d62e5feeSJonathan Cameron int option_mode_2_3db_freq; 208d62e5feeSJonathan Cameron int mot_det_mult_xz[6]; 209d62e5feeSJonathan Cameron int mot_det_mult_y[7]; 210d62e5feeSJonathan Cameron }; 211d62e5feeSJonathan Cameron 212d62e5feeSJonathan Cameron enum sca3000_variant { 213d62e5feeSJonathan Cameron d01, 214d62e5feeSJonathan Cameron e02, 215d62e5feeSJonathan Cameron e04, 216d62e5feeSJonathan Cameron e05, 217d62e5feeSJonathan Cameron }; 218d62e5feeSJonathan Cameron 219d62e5feeSJonathan Cameron /* 220d62e5feeSJonathan Cameron * Note where option modes are not defined, the chip simply does not 221d62e5feeSJonathan Cameron * support any. 222d62e5feeSJonathan Cameron * Other chips in the sca3000 series use i2c and are not included here. 223d62e5feeSJonathan Cameron * 224d62e5feeSJonathan Cameron * Some of these devices are only listed in the family data sheet and 225d62e5feeSJonathan Cameron * do not actually appear to be available. 226d62e5feeSJonathan Cameron */ 227d62e5feeSJonathan Cameron static const struct sca3000_chip_info sca3000_spi_chip_info_tbl[] = { 228d62e5feeSJonathan Cameron [d01] = { 229d62e5feeSJonathan Cameron .scale = 7357, 230d62e5feeSJonathan Cameron .temp_output = true, 231d62e5feeSJonathan Cameron .measurement_mode_freq = 250, 232d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 45, 233d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_BYPASS, 234d62e5feeSJonathan Cameron .option_mode_1_freq = 250, 235d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 70, 236d62e5feeSJonathan Cameron .mot_det_mult_xz = {50, 100, 200, 350, 650, 1300}, 237d62e5feeSJonathan Cameron .mot_det_mult_y = {50, 100, 150, 250, 450, 850, 1750}, 238d62e5feeSJonathan Cameron }, 239d62e5feeSJonathan Cameron [e02] = { 240d62e5feeSJonathan Cameron .scale = 9810, 241d62e5feeSJonathan Cameron .measurement_mode_freq = 125, 242d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 40, 243d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW, 244d62e5feeSJonathan Cameron .option_mode_1_freq = 63, 245d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 11, 246d62e5feeSJonathan Cameron .mot_det_mult_xz = {100, 150, 300, 550, 1050, 2050}, 247d62e5feeSJonathan Cameron .mot_det_mult_y = {50, 100, 200, 350, 700, 1350, 2700}, 248d62e5feeSJonathan Cameron }, 249d62e5feeSJonathan Cameron [e04] = { 250d62e5feeSJonathan Cameron .scale = 19620, 251d62e5feeSJonathan Cameron .measurement_mode_freq = 100, 252d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 38, 253d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW, 254d62e5feeSJonathan Cameron .option_mode_1_freq = 50, 255d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 9, 256d62e5feeSJonathan Cameron .option_mode_2 = SCA3000_OP_MODE_WIDE, 257d62e5feeSJonathan Cameron .option_mode_2_freq = 400, 258d62e5feeSJonathan Cameron .option_mode_2_3db_freq = 70, 259d62e5feeSJonathan Cameron .mot_det_mult_xz = {200, 300, 600, 1100, 2100, 4100}, 260d62e5feeSJonathan Cameron .mot_det_mult_y = {100, 200, 400, 7000, 1400, 2700, 54000}, 261d62e5feeSJonathan Cameron }, 262d62e5feeSJonathan Cameron [e05] = { 263d62e5feeSJonathan Cameron .scale = 61313, 264d62e5feeSJonathan Cameron .measurement_mode_freq = 200, 265d62e5feeSJonathan Cameron .measurement_mode_3db_freq = 60, 266d62e5feeSJonathan Cameron .option_mode_1 = SCA3000_OP_MODE_NARROW, 267d62e5feeSJonathan Cameron .option_mode_1_freq = 50, 268d62e5feeSJonathan Cameron .option_mode_1_3db_freq = 9, 269d62e5feeSJonathan Cameron .option_mode_2 = SCA3000_OP_MODE_WIDE, 270d62e5feeSJonathan Cameron .option_mode_2_freq = 400, 271d62e5feeSJonathan Cameron .option_mode_2_3db_freq = 75, 272d62e5feeSJonathan Cameron .mot_det_mult_xz = {600, 900, 1700, 3200, 6100, 11900}, 273d62e5feeSJonathan Cameron .mot_det_mult_y = {300, 600, 1200, 2000, 4100, 7800, 15600}, 274d62e5feeSJonathan Cameron }, 275d62e5feeSJonathan Cameron }; 276d62e5feeSJonathan Cameron 277d62e5feeSJonathan Cameron static int sca3000_write_reg(struct sca3000_state *st, u8 address, u8 val) 278d62e5feeSJonathan Cameron { 279d62e5feeSJonathan Cameron st->tx[0] = SCA3000_WRITE_REG(address); 280d62e5feeSJonathan Cameron st->tx[1] = val; 281d62e5feeSJonathan Cameron return spi_write(st->us, st->tx, 2); 282d62e5feeSJonathan Cameron } 283d62e5feeSJonathan Cameron 284d62e5feeSJonathan Cameron static int sca3000_read_data_short(struct sca3000_state *st, 285d62e5feeSJonathan Cameron u8 reg_address_high, 286d62e5feeSJonathan Cameron int len) 287d62e5feeSJonathan Cameron { 288d62e5feeSJonathan Cameron struct spi_transfer xfer[2] = { 289d62e5feeSJonathan Cameron { 290d62e5feeSJonathan Cameron .len = 1, 291d62e5feeSJonathan Cameron .tx_buf = st->tx, 292d62e5feeSJonathan Cameron }, { 293d62e5feeSJonathan Cameron .len = len, 294d62e5feeSJonathan Cameron .rx_buf = st->rx, 295d62e5feeSJonathan Cameron } 296d62e5feeSJonathan Cameron }; 297d62e5feeSJonathan Cameron st->tx[0] = SCA3000_READ_REG(reg_address_high); 298d62e5feeSJonathan Cameron 299d62e5feeSJonathan Cameron return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); 300d62e5feeSJonathan Cameron } 301d62e5feeSJonathan Cameron 302d62e5feeSJonathan Cameron /** 303d62e5feeSJonathan Cameron * sca3000_reg_lock_on() - test if the ctrl register lock is on 304d62e5feeSJonathan Cameron * @st: Driver specific device instance data. 305d62e5feeSJonathan Cameron * 306d62e5feeSJonathan Cameron * Lock must be held. 307d62e5feeSJonathan Cameron **/ 308d62e5feeSJonathan Cameron static int sca3000_reg_lock_on(struct sca3000_state *st) 309d62e5feeSJonathan Cameron { 310d62e5feeSJonathan Cameron int ret; 311d62e5feeSJonathan Cameron 312d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_STATUS_ADDR, 1); 313d62e5feeSJonathan Cameron if (ret < 0) 314d62e5feeSJonathan Cameron return ret; 315d62e5feeSJonathan Cameron 316d62e5feeSJonathan Cameron return !(st->rx[0] & SCA3000_LOCKED); 317d62e5feeSJonathan Cameron } 318d62e5feeSJonathan Cameron 319d62e5feeSJonathan Cameron /** 320d62e5feeSJonathan Cameron * __sca3000_unlock_reg_lock() - unlock the control registers 321d62e5feeSJonathan Cameron * @st: Driver specific device instance data. 322d62e5feeSJonathan Cameron * 323d62e5feeSJonathan Cameron * Note the device does not appear to support doing this in a single transfer. 324d62e5feeSJonathan Cameron * This should only ever be used as part of ctrl reg read. 325d62e5feeSJonathan Cameron * Lock must be held before calling this 326d62e5feeSJonathan Cameron */ 327d62e5feeSJonathan Cameron static int __sca3000_unlock_reg_lock(struct sca3000_state *st) 328d62e5feeSJonathan Cameron { 329d62e5feeSJonathan Cameron struct spi_transfer xfer[3] = { 330d62e5feeSJonathan Cameron { 331d62e5feeSJonathan Cameron .len = 2, 332d62e5feeSJonathan Cameron .cs_change = 1, 333d62e5feeSJonathan Cameron .tx_buf = st->tx, 334d62e5feeSJonathan Cameron }, { 335d62e5feeSJonathan Cameron .len = 2, 336d62e5feeSJonathan Cameron .cs_change = 1, 337d62e5feeSJonathan Cameron .tx_buf = st->tx + 2, 338d62e5feeSJonathan Cameron }, { 339d62e5feeSJonathan Cameron .len = 2, 340d62e5feeSJonathan Cameron .tx_buf = st->tx + 4, 341d62e5feeSJonathan Cameron }, 342d62e5feeSJonathan Cameron }; 343d62e5feeSJonathan Cameron st->tx[0] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); 344d62e5feeSJonathan Cameron st->tx[1] = 0x00; 345d62e5feeSJonathan Cameron st->tx[2] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); 346d62e5feeSJonathan Cameron st->tx[3] = 0x50; 347d62e5feeSJonathan Cameron st->tx[4] = SCA3000_WRITE_REG(SCA3000_REG_UNLOCK_ADDR); 348d62e5feeSJonathan Cameron st->tx[5] = 0xA0; 349d62e5feeSJonathan Cameron 350d62e5feeSJonathan Cameron return spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); 351d62e5feeSJonathan Cameron } 352d62e5feeSJonathan Cameron 353d62e5feeSJonathan Cameron /** 354d62e5feeSJonathan Cameron * sca3000_write_ctrl_reg() write to a lock protect ctrl register 355d62e5feeSJonathan Cameron * @st: Driver specific device instance data. 356d62e5feeSJonathan Cameron * @sel: selects which registers we wish to write to 357d62e5feeSJonathan Cameron * @val: the value to be written 358d62e5feeSJonathan Cameron * 359d62e5feeSJonathan Cameron * Certain control registers are protected against overwriting by the lock 360d62e5feeSJonathan Cameron * register and use a shared write address. This function allows writing of 361d62e5feeSJonathan Cameron * these registers. 362d62e5feeSJonathan Cameron * Lock must be held. 363d62e5feeSJonathan Cameron */ 364d62e5feeSJonathan Cameron static int sca3000_write_ctrl_reg(struct sca3000_state *st, 365d62e5feeSJonathan Cameron u8 sel, 366d62e5feeSJonathan Cameron uint8_t val) 367d62e5feeSJonathan Cameron { 368d62e5feeSJonathan Cameron int ret; 369d62e5feeSJonathan Cameron 370d62e5feeSJonathan Cameron ret = sca3000_reg_lock_on(st); 371d62e5feeSJonathan Cameron if (ret < 0) 372d62e5feeSJonathan Cameron goto error_ret; 373d62e5feeSJonathan Cameron if (ret) { 374d62e5feeSJonathan Cameron ret = __sca3000_unlock_reg_lock(st); 375d62e5feeSJonathan Cameron if (ret) 376d62e5feeSJonathan Cameron goto error_ret; 377d62e5feeSJonathan Cameron } 378d62e5feeSJonathan Cameron 379d62e5feeSJonathan Cameron /* Set the control select register */ 380d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, sel); 381d62e5feeSJonathan Cameron if (ret) 382d62e5feeSJonathan Cameron goto error_ret; 383d62e5feeSJonathan Cameron 384d62e5feeSJonathan Cameron /* Write the actual value into the register */ 385d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_DATA_ADDR, val); 386d62e5feeSJonathan Cameron 387d62e5feeSJonathan Cameron error_ret: 388d62e5feeSJonathan Cameron return ret; 389d62e5feeSJonathan Cameron } 390d62e5feeSJonathan Cameron 391d62e5feeSJonathan Cameron /** 392d62e5feeSJonathan Cameron * sca3000_read_ctrl_reg() read from lock protected control register. 393d62e5feeSJonathan Cameron * @st: Driver specific device instance data. 394d62e5feeSJonathan Cameron * @ctrl_reg: Which ctrl register do we want to read. 395d62e5feeSJonathan Cameron * 396d62e5feeSJonathan Cameron * Lock must be held. 397d62e5feeSJonathan Cameron */ 398d62e5feeSJonathan Cameron static int sca3000_read_ctrl_reg(struct sca3000_state *st, 399d62e5feeSJonathan Cameron u8 ctrl_reg) 400d62e5feeSJonathan Cameron { 401d62e5feeSJonathan Cameron int ret; 402d62e5feeSJonathan Cameron 403d62e5feeSJonathan Cameron ret = sca3000_reg_lock_on(st); 404d62e5feeSJonathan Cameron if (ret < 0) 405d62e5feeSJonathan Cameron goto error_ret; 406d62e5feeSJonathan Cameron if (ret) { 407d62e5feeSJonathan Cameron ret = __sca3000_unlock_reg_lock(st); 408d62e5feeSJonathan Cameron if (ret) 409d62e5feeSJonathan Cameron goto error_ret; 410d62e5feeSJonathan Cameron } 411d62e5feeSJonathan Cameron /* Set the control select register */ 412d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_CTRL_SEL_ADDR, ctrl_reg); 413d62e5feeSJonathan Cameron if (ret) 414d62e5feeSJonathan Cameron goto error_ret; 415d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_CTRL_DATA_ADDR, 1); 416d62e5feeSJonathan Cameron if (ret) 417d62e5feeSJonathan Cameron goto error_ret; 418d62e5feeSJonathan Cameron return st->rx[0]; 419d62e5feeSJonathan Cameron error_ret: 420d62e5feeSJonathan Cameron return ret; 421d62e5feeSJonathan Cameron } 422d62e5feeSJonathan Cameron 423d62e5feeSJonathan Cameron /** 424d62e5feeSJonathan Cameron * sca3000_show_rev() - sysfs interface to read the chip revision number 425d62e5feeSJonathan Cameron * @indio_dev: Device instance specific generic IIO data. 426d62e5feeSJonathan Cameron * Driver specific device instance data can be obtained via 427d62e5feeSJonathan Cameron * via iio_priv(indio_dev) 428d62e5feeSJonathan Cameron */ 429d62e5feeSJonathan Cameron static int sca3000_print_rev(struct iio_dev *indio_dev) 430d62e5feeSJonathan Cameron { 431d62e5feeSJonathan Cameron int ret; 432d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 433d62e5feeSJonathan Cameron 434d62e5feeSJonathan Cameron mutex_lock(&st->lock); 435d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_REVID_ADDR, 1); 436d62e5feeSJonathan Cameron if (ret < 0) 437d62e5feeSJonathan Cameron goto error_ret; 438d62e5feeSJonathan Cameron dev_info(&indio_dev->dev, 439d62e5feeSJonathan Cameron "sca3000 revision major=%lu, minor=%lu\n", 440d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_REVID_MAJOR_MASK, 441d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_REVID_MINOR_MASK); 442d62e5feeSJonathan Cameron error_ret: 443d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 444d62e5feeSJonathan Cameron 445d62e5feeSJonathan Cameron return ret; 446d62e5feeSJonathan Cameron } 447d62e5feeSJonathan Cameron 448d62e5feeSJonathan Cameron static ssize_t 449d62e5feeSJonathan Cameron sca3000_show_available_3db_freqs(struct device *dev, 450d62e5feeSJonathan Cameron struct device_attribute *attr, 451d62e5feeSJonathan Cameron char *buf) 452d62e5feeSJonathan Cameron { 453d62e5feeSJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev); 454d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 455d62e5feeSJonathan Cameron int len; 456d62e5feeSJonathan Cameron 457d62e5feeSJonathan Cameron len = sprintf(buf, "%d", st->info->measurement_mode_3db_freq); 458d62e5feeSJonathan Cameron if (st->info->option_mode_1) 459d62e5feeSJonathan Cameron len += sprintf(buf + len, " %d", 460d62e5feeSJonathan Cameron st->info->option_mode_1_3db_freq); 461d62e5feeSJonathan Cameron if (st->info->option_mode_2) 462d62e5feeSJonathan Cameron len += sprintf(buf + len, " %d", 463d62e5feeSJonathan Cameron st->info->option_mode_2_3db_freq); 464d62e5feeSJonathan Cameron len += sprintf(buf + len, "\n"); 465d62e5feeSJonathan Cameron 466d62e5feeSJonathan Cameron return len; 467d62e5feeSJonathan Cameron } 468d62e5feeSJonathan Cameron 469d62e5feeSJonathan Cameron static IIO_DEVICE_ATTR(in_accel_filter_low_pass_3db_frequency_available, 470d62e5feeSJonathan Cameron S_IRUGO, sca3000_show_available_3db_freqs, 471d62e5feeSJonathan Cameron NULL, 0); 472d62e5feeSJonathan Cameron 473d62e5feeSJonathan Cameron static const struct iio_event_spec sca3000_event = { 474d62e5feeSJonathan Cameron .type = IIO_EV_TYPE_MAG, 475d62e5feeSJonathan Cameron .dir = IIO_EV_DIR_RISING, 476d62e5feeSJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_VALUE) | BIT(IIO_EV_INFO_ENABLE), 477d62e5feeSJonathan Cameron }; 478d62e5feeSJonathan Cameron 479d62e5feeSJonathan Cameron /* 480d62e5feeSJonathan Cameron * Note the hack in the number of bits to pretend we have 2 more than 481d62e5feeSJonathan Cameron * we do in the fifo. 482d62e5feeSJonathan Cameron */ 483d62e5feeSJonathan Cameron #define SCA3000_CHAN(index, mod) \ 484d62e5feeSJonathan Cameron { \ 485d62e5feeSJonathan Cameron .type = IIO_ACCEL, \ 486d62e5feeSJonathan Cameron .modified = 1, \ 487d62e5feeSJonathan Cameron .channel2 = mod, \ 488d62e5feeSJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ 489d62e5feeSJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |\ 490d62e5feeSJonathan Cameron BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),\ 491d62e5feeSJonathan Cameron .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\ 492d62e5feeSJonathan Cameron .address = index, \ 493d62e5feeSJonathan Cameron .scan_index = index, \ 494d62e5feeSJonathan Cameron .scan_type = { \ 495d62e5feeSJonathan Cameron .sign = 's', \ 496d62e5feeSJonathan Cameron .realbits = 13, \ 497d62e5feeSJonathan Cameron .storagebits = 16, \ 498d62e5feeSJonathan Cameron .shift = 3, \ 499d62e5feeSJonathan Cameron .endianness = IIO_BE, \ 500d62e5feeSJonathan Cameron }, \ 501d62e5feeSJonathan Cameron .event_spec = &sca3000_event, \ 502d62e5feeSJonathan Cameron .num_event_specs = 1, \ 503d62e5feeSJonathan Cameron } 504d62e5feeSJonathan Cameron 505d62e5feeSJonathan Cameron static const struct iio_event_spec sca3000_freefall_event_spec = { 506d62e5feeSJonathan Cameron .type = IIO_EV_TYPE_MAG, 507d62e5feeSJonathan Cameron .dir = IIO_EV_DIR_FALLING, 508d62e5feeSJonathan Cameron .mask_separate = BIT(IIO_EV_INFO_ENABLE) | 509d62e5feeSJonathan Cameron BIT(IIO_EV_INFO_PERIOD), 510d62e5feeSJonathan Cameron }; 511d62e5feeSJonathan Cameron 512d62e5feeSJonathan Cameron static const struct iio_chan_spec sca3000_channels[] = { 513d62e5feeSJonathan Cameron SCA3000_CHAN(0, IIO_MOD_X), 514d62e5feeSJonathan Cameron SCA3000_CHAN(1, IIO_MOD_Y), 515d62e5feeSJonathan Cameron SCA3000_CHAN(2, IIO_MOD_Z), 516d62e5feeSJonathan Cameron { 517d62e5feeSJonathan Cameron .type = IIO_ACCEL, 518d62e5feeSJonathan Cameron .modified = 1, 519d62e5feeSJonathan Cameron .channel2 = IIO_MOD_X_AND_Y_AND_Z, 520d62e5feeSJonathan Cameron .scan_index = -1, /* Fake channel */ 521d62e5feeSJonathan Cameron .event_spec = &sca3000_freefall_event_spec, 522d62e5feeSJonathan Cameron .num_event_specs = 1, 523d62e5feeSJonathan Cameron }, 524d62e5feeSJonathan Cameron }; 525d62e5feeSJonathan Cameron 526d62e5feeSJonathan Cameron static const struct iio_chan_spec sca3000_channels_with_temp[] = { 527d62e5feeSJonathan Cameron SCA3000_CHAN(0, IIO_MOD_X), 528d62e5feeSJonathan Cameron SCA3000_CHAN(1, IIO_MOD_Y), 529d62e5feeSJonathan Cameron SCA3000_CHAN(2, IIO_MOD_Z), 530d62e5feeSJonathan Cameron { 531d62e5feeSJonathan Cameron .type = IIO_TEMP, 532d62e5feeSJonathan Cameron .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 533d62e5feeSJonathan Cameron .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | 534d62e5feeSJonathan Cameron BIT(IIO_CHAN_INFO_OFFSET), 535d62e5feeSJonathan Cameron /* No buffer support */ 536d62e5feeSJonathan Cameron .scan_index = -1, 537d62e5feeSJonathan Cameron }, 538d62e5feeSJonathan Cameron { 539d62e5feeSJonathan Cameron .type = IIO_ACCEL, 540d62e5feeSJonathan Cameron .modified = 1, 541d62e5feeSJonathan Cameron .channel2 = IIO_MOD_X_AND_Y_AND_Z, 542d62e5feeSJonathan Cameron .scan_index = -1, /* Fake channel */ 543d62e5feeSJonathan Cameron .event_spec = &sca3000_freefall_event_spec, 544d62e5feeSJonathan Cameron .num_event_specs = 1, 545d62e5feeSJonathan Cameron }, 546d62e5feeSJonathan Cameron }; 547d62e5feeSJonathan Cameron 548d62e5feeSJonathan Cameron static u8 sca3000_addresses[3][3] = { 549d62e5feeSJonathan Cameron [0] = {SCA3000_REG_X_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_X_TH, 550d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_X}, 551d62e5feeSJonathan Cameron [1] = {SCA3000_REG_Y_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Y_TH, 552d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_Y}, 553d62e5feeSJonathan Cameron [2] = {SCA3000_REG_Z_MSB_ADDR, SCA3000_REG_CTRL_SEL_MD_Z_TH, 554d62e5feeSJonathan Cameron SCA3000_MD_CTRL_OR_Z}, 555d62e5feeSJonathan Cameron }; 556d62e5feeSJonathan Cameron 557d62e5feeSJonathan Cameron /** 558d62e5feeSJonathan Cameron * __sca3000_get_base_freq() - obtain mode specific base frequency 559d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state. 560d62e5feeSJonathan Cameron * @info: chip type specific information. 561d62e5feeSJonathan Cameron * @base_freq: Base frequency for the current measurement mode. 562d62e5feeSJonathan Cameron * 563d62e5feeSJonathan Cameron * lock must be held 564d62e5feeSJonathan Cameron */ 565d62e5feeSJonathan Cameron static inline int __sca3000_get_base_freq(struct sca3000_state *st, 566d62e5feeSJonathan Cameron const struct sca3000_chip_info *info, 567d62e5feeSJonathan Cameron int *base_freq) 568d62e5feeSJonathan Cameron { 569d62e5feeSJonathan Cameron int ret; 570d62e5feeSJonathan Cameron 571d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 572d62e5feeSJonathan Cameron if (ret) 573d62e5feeSJonathan Cameron goto error_ret; 574d62e5feeSJonathan Cameron switch (SCA3000_REG_MODE_MODE_MASK & st->rx[0]) { 575d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL: 576d62e5feeSJonathan Cameron *base_freq = info->measurement_mode_freq; 577d62e5feeSJonathan Cameron break; 578d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1: 579d62e5feeSJonathan Cameron *base_freq = info->option_mode_1_freq; 580d62e5feeSJonathan Cameron break; 581d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2: 582d62e5feeSJonathan Cameron *base_freq = info->option_mode_2_freq; 583d62e5feeSJonathan Cameron break; 584d62e5feeSJonathan Cameron default: 585d62e5feeSJonathan Cameron ret = -EINVAL; 586d62e5feeSJonathan Cameron } 587d62e5feeSJonathan Cameron error_ret: 588d62e5feeSJonathan Cameron return ret; 589d62e5feeSJonathan Cameron } 590d62e5feeSJonathan Cameron 591d62e5feeSJonathan Cameron /** 592d62e5feeSJonathan Cameron * sca3000_read_raw_samp_freq() - read_raw handler for IIO_CHAN_INFO_SAMP_FREQ 593d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state. 594d62e5feeSJonathan Cameron * @val: The frequency read back. 595d62e5feeSJonathan Cameron * 596d62e5feeSJonathan Cameron * lock must be held 597d62e5feeSJonathan Cameron **/ 598d62e5feeSJonathan Cameron static int sca3000_read_raw_samp_freq(struct sca3000_state *st, int *val) 599d62e5feeSJonathan Cameron { 600d62e5feeSJonathan Cameron int ret; 601d62e5feeSJonathan Cameron 602d62e5feeSJonathan Cameron ret = __sca3000_get_base_freq(st, st->info, val); 603d62e5feeSJonathan Cameron if (ret) 604d62e5feeSJonathan Cameron return ret; 605d62e5feeSJonathan Cameron 606d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); 607d62e5feeSJonathan Cameron if (ret < 0) 608d62e5feeSJonathan Cameron return ret; 609d62e5feeSJonathan Cameron 610d62e5feeSJonathan Cameron if (*val > 0) { 611d62e5feeSJonathan Cameron ret &= SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; 612d62e5feeSJonathan Cameron switch (ret) { 613d62e5feeSJonathan Cameron case SCA3000_REG_OUT_CTRL_BUF_DIV_2: 614d62e5feeSJonathan Cameron *val /= 2; 615d62e5feeSJonathan Cameron break; 616d62e5feeSJonathan Cameron case SCA3000_REG_OUT_CTRL_BUF_DIV_4: 617d62e5feeSJonathan Cameron *val /= 4; 618d62e5feeSJonathan Cameron break; 619d62e5feeSJonathan Cameron } 620d62e5feeSJonathan Cameron } 621d62e5feeSJonathan Cameron 622d62e5feeSJonathan Cameron return 0; 623d62e5feeSJonathan Cameron } 624d62e5feeSJonathan Cameron 625d62e5feeSJonathan Cameron /** 626d62e5feeSJonathan Cameron * sca3000_write_raw_samp_freq() - write_raw handler for IIO_CHAN_INFO_SAMP_FREQ 627d62e5feeSJonathan Cameron * @st: Private driver specific device instance specific state. 628d62e5feeSJonathan Cameron * @val: The frequency desired. 629d62e5feeSJonathan Cameron * 630d62e5feeSJonathan Cameron * lock must be held 631d62e5feeSJonathan Cameron */ 632d62e5feeSJonathan Cameron static int sca3000_write_raw_samp_freq(struct sca3000_state *st, int val) 633d62e5feeSJonathan Cameron { 634d62e5feeSJonathan Cameron int ret, base_freq, ctrlval; 635d62e5feeSJonathan Cameron 636d62e5feeSJonathan Cameron ret = __sca3000_get_base_freq(st, st->info, &base_freq); 637d62e5feeSJonathan Cameron if (ret) 638d62e5feeSJonathan Cameron return ret; 639d62e5feeSJonathan Cameron 640d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); 641d62e5feeSJonathan Cameron if (ret < 0) 642d62e5feeSJonathan Cameron return ret; 643d62e5feeSJonathan Cameron 644d62e5feeSJonathan Cameron ctrlval = ret & ~SCA3000_REG_OUT_CTRL_BUF_DIV_MASK; 645d62e5feeSJonathan Cameron 646d62e5feeSJonathan Cameron if (val == base_freq / 2) 647d62e5feeSJonathan Cameron ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_2; 648d62e5feeSJonathan Cameron if (val == base_freq / 4) 649d62e5feeSJonathan Cameron ctrlval |= SCA3000_REG_OUT_CTRL_BUF_DIV_4; 650d62e5feeSJonathan Cameron else if (val != base_freq) 651d62e5feeSJonathan Cameron return -EINVAL; 652d62e5feeSJonathan Cameron 653d62e5feeSJonathan Cameron return sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, 654d62e5feeSJonathan Cameron ctrlval); 655d62e5feeSJonathan Cameron } 656d62e5feeSJonathan Cameron 657d62e5feeSJonathan Cameron static int sca3000_read_3db_freq(struct sca3000_state *st, int *val) 658d62e5feeSJonathan Cameron { 659d62e5feeSJonathan Cameron int ret; 660d62e5feeSJonathan Cameron 661d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 662d62e5feeSJonathan Cameron if (ret) 663d62e5feeSJonathan Cameron return ret; 664d62e5feeSJonathan Cameron 665d62e5feeSJonathan Cameron /* mask bottom 2 bits - only ones that are relevant */ 666d62e5feeSJonathan Cameron st->rx[0] &= SCA3000_REG_MODE_MODE_MASK; 667d62e5feeSJonathan Cameron switch (st->rx[0]) { 668d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL: 669d62e5feeSJonathan Cameron *val = st->info->measurement_mode_3db_freq; 670d62e5feeSJonathan Cameron return IIO_VAL_INT; 671d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_MOT_DET: 672d62e5feeSJonathan Cameron return -EBUSY; 673d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1: 674d62e5feeSJonathan Cameron *val = st->info->option_mode_1_3db_freq; 675d62e5feeSJonathan Cameron return IIO_VAL_INT; 676d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2: 677d62e5feeSJonathan Cameron *val = st->info->option_mode_2_3db_freq; 678d62e5feeSJonathan Cameron return IIO_VAL_INT; 679d62e5feeSJonathan Cameron default: 680d62e5feeSJonathan Cameron return -EINVAL; 681d62e5feeSJonathan Cameron } 682d62e5feeSJonathan Cameron } 683d62e5feeSJonathan Cameron 684d62e5feeSJonathan Cameron static int sca3000_write_3db_freq(struct sca3000_state *st, int val) 685d62e5feeSJonathan Cameron { 686d62e5feeSJonathan Cameron int ret; 687d62e5feeSJonathan Cameron int mode; 688d62e5feeSJonathan Cameron 689d62e5feeSJonathan Cameron if (val == st->info->measurement_mode_3db_freq) 690d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_NORMAL; 691d62e5feeSJonathan Cameron else if (st->info->option_mode_1 && 692d62e5feeSJonathan Cameron (val == st->info->option_mode_1_3db_freq)) 693d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_OP_1; 694d62e5feeSJonathan Cameron else if (st->info->option_mode_2 && 695d62e5feeSJonathan Cameron (val == st->info->option_mode_2_3db_freq)) 696d62e5feeSJonathan Cameron mode = SCA3000_REG_MODE_MEAS_MODE_OP_2; 697d62e5feeSJonathan Cameron else 698d62e5feeSJonathan Cameron return -EINVAL; 699d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 700d62e5feeSJonathan Cameron if (ret) 701d62e5feeSJonathan Cameron return ret; 702d62e5feeSJonathan Cameron 703d62e5feeSJonathan Cameron st->rx[0] &= ~SCA3000_REG_MODE_MODE_MASK; 704d62e5feeSJonathan Cameron st->rx[0] |= (mode & SCA3000_REG_MODE_MODE_MASK); 705d62e5feeSJonathan Cameron 706d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, st->rx[0]); 707d62e5feeSJonathan Cameron } 708d62e5feeSJonathan Cameron 709d62e5feeSJonathan Cameron static int sca3000_read_raw(struct iio_dev *indio_dev, 710d62e5feeSJonathan Cameron struct iio_chan_spec const *chan, 711d62e5feeSJonathan Cameron int *val, 712d62e5feeSJonathan Cameron int *val2, 713d62e5feeSJonathan Cameron long mask) 714d62e5feeSJonathan Cameron { 715d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 716d62e5feeSJonathan Cameron int ret; 717d62e5feeSJonathan Cameron u8 address; 718d62e5feeSJonathan Cameron 719d62e5feeSJonathan Cameron switch (mask) { 720d62e5feeSJonathan Cameron case IIO_CHAN_INFO_RAW: 721d62e5feeSJonathan Cameron mutex_lock(&st->lock); 722d62e5feeSJonathan Cameron if (chan->type == IIO_ACCEL) { 723d62e5feeSJonathan Cameron if (st->mo_det_use_count) { 724d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 725d62e5feeSJonathan Cameron return -EBUSY; 726d62e5feeSJonathan Cameron } 727d62e5feeSJonathan Cameron address = sca3000_addresses[chan->address][0]; 728d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, address, 2); 729d62e5feeSJonathan Cameron if (ret < 0) { 730d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 731d62e5feeSJonathan Cameron return ret; 732d62e5feeSJonathan Cameron } 733d62e5feeSJonathan Cameron *val = (be16_to_cpup((__be16 *)st->rx) >> 3) & 0x1FFF; 734d62e5feeSJonathan Cameron *val = ((*val) << (sizeof(*val) * 8 - 13)) >> 735d62e5feeSJonathan Cameron (sizeof(*val) * 8 - 13); 736d62e5feeSJonathan Cameron } else { 737d62e5feeSJonathan Cameron /* get the temperature when available */ 738d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, 739d62e5feeSJonathan Cameron SCA3000_REG_TEMP_MSB_ADDR, 740d62e5feeSJonathan Cameron 2); 741d62e5feeSJonathan Cameron if (ret < 0) { 742d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 743d62e5feeSJonathan Cameron return ret; 744d62e5feeSJonathan Cameron } 745d62e5feeSJonathan Cameron *val = ((st->rx[0] & 0x3F) << 3) | 746d62e5feeSJonathan Cameron ((st->rx[1] & 0xE0) >> 5); 747d62e5feeSJonathan Cameron } 748d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 749d62e5feeSJonathan Cameron return IIO_VAL_INT; 750d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SCALE: 751d62e5feeSJonathan Cameron *val = 0; 752d62e5feeSJonathan Cameron if (chan->type == IIO_ACCEL) 753d62e5feeSJonathan Cameron *val2 = st->info->scale; 754d62e5feeSJonathan Cameron else /* temperature */ 755d62e5feeSJonathan Cameron *val2 = 555556; 756d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO; 757d62e5feeSJonathan Cameron case IIO_CHAN_INFO_OFFSET: 758d62e5feeSJonathan Cameron *val = -214; 759d62e5feeSJonathan Cameron *val2 = 600000; 760d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO; 761d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SAMP_FREQ: 762d62e5feeSJonathan Cameron mutex_lock(&st->lock); 763d62e5feeSJonathan Cameron ret = sca3000_read_raw_samp_freq(st, val); 764d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 765d62e5feeSJonathan Cameron return ret ? ret : IIO_VAL_INT; 766d62e5feeSJonathan Cameron case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 767d62e5feeSJonathan Cameron mutex_lock(&st->lock); 768d62e5feeSJonathan Cameron ret = sca3000_read_3db_freq(st, val); 769d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 770d62e5feeSJonathan Cameron return ret; 771d62e5feeSJonathan Cameron default: 772d62e5feeSJonathan Cameron return -EINVAL; 773d62e5feeSJonathan Cameron } 774d62e5feeSJonathan Cameron } 775d62e5feeSJonathan Cameron 776d62e5feeSJonathan Cameron static int sca3000_write_raw(struct iio_dev *indio_dev, 777d62e5feeSJonathan Cameron struct iio_chan_spec const *chan, 778d62e5feeSJonathan Cameron int val, int val2, long mask) 779d62e5feeSJonathan Cameron { 780d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 781d62e5feeSJonathan Cameron int ret; 782d62e5feeSJonathan Cameron 783d62e5feeSJonathan Cameron switch (mask) { 784d62e5feeSJonathan Cameron case IIO_CHAN_INFO_SAMP_FREQ: 785d62e5feeSJonathan Cameron if (val2) 786d62e5feeSJonathan Cameron return -EINVAL; 787d62e5feeSJonathan Cameron mutex_lock(&st->lock); 788d62e5feeSJonathan Cameron ret = sca3000_write_raw_samp_freq(st, val); 789d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 790d62e5feeSJonathan Cameron return ret; 791d62e5feeSJonathan Cameron case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 792d62e5feeSJonathan Cameron if (val2) 793d62e5feeSJonathan Cameron return -EINVAL; 794d62e5feeSJonathan Cameron mutex_lock(&st->lock); 795d62e5feeSJonathan Cameron ret = sca3000_write_3db_freq(st, val); 796d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 797c5b974beSGustavo A. R. Silva return ret; 798d62e5feeSJonathan Cameron default: 799d62e5feeSJonathan Cameron return -EINVAL; 800d62e5feeSJonathan Cameron } 801d62e5feeSJonathan Cameron 802d62e5feeSJonathan Cameron return ret; 803d62e5feeSJonathan Cameron } 804d62e5feeSJonathan Cameron 805d62e5feeSJonathan Cameron /** 806d62e5feeSJonathan Cameron * sca3000_read_av_freq() - sysfs function to get available frequencies 807d62e5feeSJonathan Cameron * @dev: Device structure for this device. 808d62e5feeSJonathan Cameron * @attr: Description of the attribute. 809d62e5feeSJonathan Cameron * @buf: Incoming string 810d62e5feeSJonathan Cameron * 811d62e5feeSJonathan Cameron * The later modes are only relevant to the ring buffer - and depend on current 812d62e5feeSJonathan Cameron * mode. Note that data sheet gives rather wide tolerances for these so integer 813d62e5feeSJonathan Cameron * division will give good enough answer and not all chips have them specified 814d62e5feeSJonathan Cameron * at all. 815d62e5feeSJonathan Cameron **/ 816d62e5feeSJonathan Cameron static ssize_t sca3000_read_av_freq(struct device *dev, 817d62e5feeSJonathan Cameron struct device_attribute *attr, 818d62e5feeSJonathan Cameron char *buf) 819d62e5feeSJonathan Cameron { 820d62e5feeSJonathan Cameron struct iio_dev *indio_dev = dev_to_iio_dev(dev); 821d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 822d62e5feeSJonathan Cameron int len = 0, ret, val; 823d62e5feeSJonathan Cameron 824d62e5feeSJonathan Cameron mutex_lock(&st->lock); 825d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 826d62e5feeSJonathan Cameron val = st->rx[0]; 827d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 828d62e5feeSJonathan Cameron if (ret) 829d62e5feeSJonathan Cameron goto error_ret; 830d62e5feeSJonathan Cameron 831d62e5feeSJonathan Cameron switch (val & SCA3000_REG_MODE_MODE_MASK) { 832d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_NORMAL: 833d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n", 834d62e5feeSJonathan Cameron st->info->measurement_mode_freq, 835d62e5feeSJonathan Cameron st->info->measurement_mode_freq / 2, 836d62e5feeSJonathan Cameron st->info->measurement_mode_freq / 4); 837d62e5feeSJonathan Cameron break; 838d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_1: 839d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n", 840d62e5feeSJonathan Cameron st->info->option_mode_1_freq, 841d62e5feeSJonathan Cameron st->info->option_mode_1_freq / 2, 842d62e5feeSJonathan Cameron st->info->option_mode_1_freq / 4); 843d62e5feeSJonathan Cameron break; 844d62e5feeSJonathan Cameron case SCA3000_REG_MODE_MEAS_MODE_OP_2: 845d62e5feeSJonathan Cameron len += sprintf(buf + len, "%d %d %d\n", 846d62e5feeSJonathan Cameron st->info->option_mode_2_freq, 847d62e5feeSJonathan Cameron st->info->option_mode_2_freq / 2, 848d62e5feeSJonathan Cameron st->info->option_mode_2_freq / 4); 849d62e5feeSJonathan Cameron break; 850d62e5feeSJonathan Cameron } 851d62e5feeSJonathan Cameron return len; 852d62e5feeSJonathan Cameron error_ret: 853d62e5feeSJonathan Cameron return ret; 854d62e5feeSJonathan Cameron } 855d62e5feeSJonathan Cameron 856d62e5feeSJonathan Cameron /* 857d62e5feeSJonathan Cameron * Should only really be registered if ring buffer support is compiled in. 858d62e5feeSJonathan Cameron * Does no harm however and doing it right would add a fair bit of complexity 859d62e5feeSJonathan Cameron */ 860d62e5feeSJonathan Cameron static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(sca3000_read_av_freq); 861d62e5feeSJonathan Cameron 862d62e5feeSJonathan Cameron /** 863d62e5feeSJonathan Cameron * sca3000_read_event_value() - query of a threshold or period 864d62e5feeSJonathan Cameron **/ 865d62e5feeSJonathan Cameron static int sca3000_read_event_value(struct iio_dev *indio_dev, 866d62e5feeSJonathan Cameron const struct iio_chan_spec *chan, 867d62e5feeSJonathan Cameron enum iio_event_type type, 868d62e5feeSJonathan Cameron enum iio_event_direction dir, 869d62e5feeSJonathan Cameron enum iio_event_info info, 870d62e5feeSJonathan Cameron int *val, int *val2) 871d62e5feeSJonathan Cameron { 872d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 873aabcbfe8SDan Carpenter long ret; 874aabcbfe8SDan Carpenter int i; 875d62e5feeSJonathan Cameron 876d62e5feeSJonathan Cameron switch (info) { 877d62e5feeSJonathan Cameron case IIO_EV_INFO_VALUE: 878d62e5feeSJonathan Cameron mutex_lock(&st->lock); 879d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, 880d62e5feeSJonathan Cameron sca3000_addresses[chan->address][1]); 881d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 882d62e5feeSJonathan Cameron if (ret < 0) 883d62e5feeSJonathan Cameron return ret; 884d62e5feeSJonathan Cameron *val = 0; 885d62e5feeSJonathan Cameron if (chan->channel2 == IIO_MOD_Y) 886aabcbfe8SDan Carpenter for_each_set_bit(i, &ret, 887d62e5feeSJonathan Cameron ARRAY_SIZE(st->info->mot_det_mult_y)) 888d62e5feeSJonathan Cameron *val += st->info->mot_det_mult_y[i]; 889d62e5feeSJonathan Cameron else 890aabcbfe8SDan Carpenter for_each_set_bit(i, &ret, 891d62e5feeSJonathan Cameron ARRAY_SIZE(st->info->mot_det_mult_xz)) 892d62e5feeSJonathan Cameron *val += st->info->mot_det_mult_xz[i]; 893d62e5feeSJonathan Cameron 894d62e5feeSJonathan Cameron return IIO_VAL_INT; 895d62e5feeSJonathan Cameron case IIO_EV_INFO_PERIOD: 896d62e5feeSJonathan Cameron *val = 0; 897d62e5feeSJonathan Cameron *val2 = 226000; 898d62e5feeSJonathan Cameron return IIO_VAL_INT_PLUS_MICRO; 899d62e5feeSJonathan Cameron default: 900d62e5feeSJonathan Cameron return -EINVAL; 901d62e5feeSJonathan Cameron } 902d62e5feeSJonathan Cameron } 903d62e5feeSJonathan Cameron 904d62e5feeSJonathan Cameron /** 905d62e5feeSJonathan Cameron * sca3000_write_value() - control of threshold and period 906d62e5feeSJonathan Cameron * @indio_dev: Device instance specific IIO information. 907d62e5feeSJonathan Cameron * @chan: Description of the channel for which the event is being 908d62e5feeSJonathan Cameron * configured. 909d62e5feeSJonathan Cameron * @type: The type of event being configured, here magnitude rising 910d62e5feeSJonathan Cameron * as everything else is read only. 911d62e5feeSJonathan Cameron * @dir: Direction of the event (here rising) 912d62e5feeSJonathan Cameron * @info: What information about the event are we configuring. 913d62e5feeSJonathan Cameron * Here the threshold only. 914d62e5feeSJonathan Cameron * @val: Integer part of the value being written.. 915d62e5feeSJonathan Cameron * @val2: Non integer part of the value being written. Here always 0. 916d62e5feeSJonathan Cameron */ 917d62e5feeSJonathan Cameron static int sca3000_write_event_value(struct iio_dev *indio_dev, 918d62e5feeSJonathan Cameron const struct iio_chan_spec *chan, 919d62e5feeSJonathan Cameron enum iio_event_type type, 920d62e5feeSJonathan Cameron enum iio_event_direction dir, 921d62e5feeSJonathan Cameron enum iio_event_info info, 922d62e5feeSJonathan Cameron int val, int val2) 923d62e5feeSJonathan Cameron { 924d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 925d62e5feeSJonathan Cameron int ret; 926d62e5feeSJonathan Cameron int i; 927d62e5feeSJonathan Cameron u8 nonlinear = 0; 928d62e5feeSJonathan Cameron 929d62e5feeSJonathan Cameron if (chan->channel2 == IIO_MOD_Y) { 930d62e5feeSJonathan Cameron i = ARRAY_SIZE(st->info->mot_det_mult_y); 931d62e5feeSJonathan Cameron while (i > 0) 932d62e5feeSJonathan Cameron if (val >= st->info->mot_det_mult_y[--i]) { 933d62e5feeSJonathan Cameron nonlinear |= (1 << i); 934d62e5feeSJonathan Cameron val -= st->info->mot_det_mult_y[i]; 935d62e5feeSJonathan Cameron } 936d62e5feeSJonathan Cameron } else { 937d62e5feeSJonathan Cameron i = ARRAY_SIZE(st->info->mot_det_mult_xz); 938d62e5feeSJonathan Cameron while (i > 0) 939d62e5feeSJonathan Cameron if (val >= st->info->mot_det_mult_xz[--i]) { 940d62e5feeSJonathan Cameron nonlinear |= (1 << i); 941d62e5feeSJonathan Cameron val -= st->info->mot_det_mult_xz[i]; 942d62e5feeSJonathan Cameron } 943d62e5feeSJonathan Cameron } 944d62e5feeSJonathan Cameron 945d62e5feeSJonathan Cameron mutex_lock(&st->lock); 946d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, 947d62e5feeSJonathan Cameron sca3000_addresses[chan->address][1], 948d62e5feeSJonathan Cameron nonlinear); 949d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 950d62e5feeSJonathan Cameron 951d62e5feeSJonathan Cameron return ret; 952d62e5feeSJonathan Cameron } 953d62e5feeSJonathan Cameron 954d62e5feeSJonathan Cameron static struct attribute *sca3000_attributes[] = { 955d62e5feeSJonathan Cameron &iio_dev_attr_in_accel_filter_low_pass_3db_frequency_available.dev_attr.attr, 956d62e5feeSJonathan Cameron &iio_dev_attr_sampling_frequency_available.dev_attr.attr, 957d62e5feeSJonathan Cameron NULL, 958d62e5feeSJonathan Cameron }; 959d62e5feeSJonathan Cameron 960d62e5feeSJonathan Cameron static const struct attribute_group sca3000_attribute_group = { 961d62e5feeSJonathan Cameron .attrs = sca3000_attributes, 962d62e5feeSJonathan Cameron }; 963d62e5feeSJonathan Cameron 964d62e5feeSJonathan Cameron static int sca3000_read_data(struct sca3000_state *st, 965d62e5feeSJonathan Cameron u8 reg_address_high, 966d62e5feeSJonathan Cameron u8 *rx, 967d62e5feeSJonathan Cameron int len) 968d62e5feeSJonathan Cameron { 969d62e5feeSJonathan Cameron int ret; 970d62e5feeSJonathan Cameron struct spi_transfer xfer[2] = { 971d62e5feeSJonathan Cameron { 972d62e5feeSJonathan Cameron .len = 1, 973d62e5feeSJonathan Cameron .tx_buf = st->tx, 974d62e5feeSJonathan Cameron }, { 975d62e5feeSJonathan Cameron .len = len, 976d62e5feeSJonathan Cameron .rx_buf = rx, 977d62e5feeSJonathan Cameron } 978d62e5feeSJonathan Cameron }; 979d62e5feeSJonathan Cameron 980d62e5feeSJonathan Cameron st->tx[0] = SCA3000_READ_REG(reg_address_high); 981d62e5feeSJonathan Cameron ret = spi_sync_transfer(st->us, xfer, ARRAY_SIZE(xfer)); 982d62e5feeSJonathan Cameron if (ret) { 983d62e5feeSJonathan Cameron dev_err(get_device(&st->us->dev), "problem reading register"); 984d62e5feeSJonathan Cameron return ret; 985d62e5feeSJonathan Cameron } 986d62e5feeSJonathan Cameron 987d62e5feeSJonathan Cameron return 0; 988d62e5feeSJonathan Cameron } 989d62e5feeSJonathan Cameron 990d62e5feeSJonathan Cameron /** 991d62e5feeSJonathan Cameron * sca3000_ring_int_process() - ring specific interrupt handling. 992d62e5feeSJonathan Cameron * @val: Value of the interrupt status register. 993d62e5feeSJonathan Cameron * @indio_dev: Device instance specific IIO device structure. 994d62e5feeSJonathan Cameron */ 995d62e5feeSJonathan Cameron static void sca3000_ring_int_process(u8 val, struct iio_dev *indio_dev) 996d62e5feeSJonathan Cameron { 997d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 998d62e5feeSJonathan Cameron int ret, i, num_available; 999d62e5feeSJonathan Cameron 1000d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1001d62e5feeSJonathan Cameron 1002d62e5feeSJonathan Cameron if (val & SCA3000_REG_INT_STATUS_HALF) { 1003d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_BUF_COUNT_ADDR, 1004d62e5feeSJonathan Cameron 1); 1005d62e5feeSJonathan Cameron if (ret) 1006d62e5feeSJonathan Cameron goto error_ret; 1007d62e5feeSJonathan Cameron num_available = st->rx[0]; 1008d62e5feeSJonathan Cameron /* 1009d62e5feeSJonathan Cameron * num_available is the total number of samples available 1010d62e5feeSJonathan Cameron * i.e. number of time points * number of channels. 1011d62e5feeSJonathan Cameron */ 1012d62e5feeSJonathan Cameron ret = sca3000_read_data(st, SCA3000_REG_RING_OUT_ADDR, st->rx, 1013d62e5feeSJonathan Cameron num_available * 2); 1014d62e5feeSJonathan Cameron if (ret) 1015d62e5feeSJonathan Cameron goto error_ret; 1016d62e5feeSJonathan Cameron for (i = 0; i < num_available / 3; i++) { 1017d62e5feeSJonathan Cameron /* 1018d62e5feeSJonathan Cameron * Dirty hack to cover for 11 bit in fifo, 13 bit 1019d62e5feeSJonathan Cameron * direct reading. 1020d62e5feeSJonathan Cameron * 1021d62e5feeSJonathan Cameron * In theory the bottom two bits are undefined. 1022d62e5feeSJonathan Cameron * In reality they appear to always be 0. 1023d62e5feeSJonathan Cameron */ 1024d62e5feeSJonathan Cameron iio_push_to_buffers(indio_dev, st->rx + i * 3 * 2); 1025d62e5feeSJonathan Cameron } 1026d62e5feeSJonathan Cameron } 1027d62e5feeSJonathan Cameron error_ret: 1028d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1029d62e5feeSJonathan Cameron } 1030d62e5feeSJonathan Cameron 1031d62e5feeSJonathan Cameron /** 1032d62e5feeSJonathan Cameron * sca3000_event_handler() - handling ring and non ring events 1033d62e5feeSJonathan Cameron * @irq: The irq being handled. 1034d62e5feeSJonathan Cameron * @private: struct iio_device pointer for the device. 1035d62e5feeSJonathan Cameron * 1036d62e5feeSJonathan Cameron * Ring related interrupt handler. Depending on event, push to 1037d62e5feeSJonathan Cameron * the ring buffer event chrdev or the event one. 1038d62e5feeSJonathan Cameron * 1039d62e5feeSJonathan Cameron * This function is complicated by the fact that the devices can signify ring 1040d62e5feeSJonathan Cameron * and non ring events via the same interrupt line and they can only 1041d62e5feeSJonathan Cameron * be distinguished via a read of the relevant status register. 1042d62e5feeSJonathan Cameron */ 1043d62e5feeSJonathan Cameron static irqreturn_t sca3000_event_handler(int irq, void *private) 1044d62e5feeSJonathan Cameron { 1045d62e5feeSJonathan Cameron struct iio_dev *indio_dev = private; 1046d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1047d62e5feeSJonathan Cameron int ret, val; 1048d62e5feeSJonathan Cameron s64 last_timestamp = iio_get_time_ns(indio_dev); 1049d62e5feeSJonathan Cameron 1050d62e5feeSJonathan Cameron /* 1051d62e5feeSJonathan Cameron * Could lead if badly timed to an extra read of status reg, 1052d62e5feeSJonathan Cameron * but ensures no interrupt is missed. 1053d62e5feeSJonathan Cameron */ 1054d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1055d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); 1056d62e5feeSJonathan Cameron val = st->rx[0]; 1057d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1058d62e5feeSJonathan Cameron if (ret) 1059d62e5feeSJonathan Cameron goto done; 1060d62e5feeSJonathan Cameron 1061d62e5feeSJonathan Cameron sca3000_ring_int_process(val, indio_dev); 1062d62e5feeSJonathan Cameron 1063d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_FREE_FALL) 1064d62e5feeSJonathan Cameron iio_push_event(indio_dev, 1065d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL, 1066d62e5feeSJonathan Cameron 0, 1067d62e5feeSJonathan Cameron IIO_MOD_X_AND_Y_AND_Z, 1068d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG, 1069d62e5feeSJonathan Cameron IIO_EV_DIR_FALLING), 1070d62e5feeSJonathan Cameron last_timestamp); 1071d62e5feeSJonathan Cameron 1072d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_Y_TRIGGER) 1073d62e5feeSJonathan Cameron iio_push_event(indio_dev, 1074d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL, 1075d62e5feeSJonathan Cameron 0, 1076d62e5feeSJonathan Cameron IIO_MOD_Y, 1077d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG, 1078d62e5feeSJonathan Cameron IIO_EV_DIR_RISING), 1079d62e5feeSJonathan Cameron last_timestamp); 1080d62e5feeSJonathan Cameron 1081d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_X_TRIGGER) 1082d62e5feeSJonathan Cameron iio_push_event(indio_dev, 1083d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL, 1084d62e5feeSJonathan Cameron 0, 1085d62e5feeSJonathan Cameron IIO_MOD_X, 1086d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG, 1087d62e5feeSJonathan Cameron IIO_EV_DIR_RISING), 1088d62e5feeSJonathan Cameron last_timestamp); 1089d62e5feeSJonathan Cameron 1090d62e5feeSJonathan Cameron if (val & SCA3000_INT_STATUS_Z_TRIGGER) 1091d62e5feeSJonathan Cameron iio_push_event(indio_dev, 1092d62e5feeSJonathan Cameron IIO_MOD_EVENT_CODE(IIO_ACCEL, 1093d62e5feeSJonathan Cameron 0, 1094d62e5feeSJonathan Cameron IIO_MOD_Z, 1095d62e5feeSJonathan Cameron IIO_EV_TYPE_MAG, 1096d62e5feeSJonathan Cameron IIO_EV_DIR_RISING), 1097d62e5feeSJonathan Cameron last_timestamp); 1098d62e5feeSJonathan Cameron 1099d62e5feeSJonathan Cameron done: 1100d62e5feeSJonathan Cameron return IRQ_HANDLED; 1101d62e5feeSJonathan Cameron } 1102d62e5feeSJonathan Cameron 1103d62e5feeSJonathan Cameron /** 1104d62e5feeSJonathan Cameron * sca3000_read_event_config() what events are enabled 1105d62e5feeSJonathan Cameron **/ 1106d62e5feeSJonathan Cameron static int sca3000_read_event_config(struct iio_dev *indio_dev, 1107d62e5feeSJonathan Cameron const struct iio_chan_spec *chan, 1108d62e5feeSJonathan Cameron enum iio_event_type type, 1109d62e5feeSJonathan Cameron enum iio_event_direction dir) 1110d62e5feeSJonathan Cameron { 1111d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1112d62e5feeSJonathan Cameron int ret; 1113d62e5feeSJonathan Cameron /* read current value of mode register */ 1114d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1115d62e5feeSJonathan Cameron 1116d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 1117d62e5feeSJonathan Cameron if (ret) 1118d62e5feeSJonathan Cameron goto error_ret; 1119d62e5feeSJonathan Cameron 1120d62e5feeSJonathan Cameron switch (chan->channel2) { 1121d62e5feeSJonathan Cameron case IIO_MOD_X_AND_Y_AND_Z: 1122d62e5feeSJonathan Cameron ret = !!(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT); 1123d62e5feeSJonathan Cameron break; 1124d62e5feeSJonathan Cameron case IIO_MOD_X: 1125d62e5feeSJonathan Cameron case IIO_MOD_Y: 1126d62e5feeSJonathan Cameron case IIO_MOD_Z: 1127d62e5feeSJonathan Cameron /* 1128d62e5feeSJonathan Cameron * Motion detection mode cannot run at the same time as 1129d62e5feeSJonathan Cameron * acceleration data being read. 1130d62e5feeSJonathan Cameron */ 1131d62e5feeSJonathan Cameron if ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) 1132d62e5feeSJonathan Cameron != SCA3000_REG_MODE_MEAS_MODE_MOT_DET) { 1133d62e5feeSJonathan Cameron ret = 0; 1134d62e5feeSJonathan Cameron } else { 1135d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, 1136d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL); 1137d62e5feeSJonathan Cameron if (ret < 0) 1138d62e5feeSJonathan Cameron goto error_ret; 1139d62e5feeSJonathan Cameron /* only supporting logical or's for now */ 1140d62e5feeSJonathan Cameron ret = !!(ret & sca3000_addresses[chan->address][2]); 1141d62e5feeSJonathan Cameron } 1142d62e5feeSJonathan Cameron break; 1143d62e5feeSJonathan Cameron default: 1144d62e5feeSJonathan Cameron ret = -EINVAL; 1145d62e5feeSJonathan Cameron } 1146d62e5feeSJonathan Cameron 1147d62e5feeSJonathan Cameron error_ret: 1148d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1149d62e5feeSJonathan Cameron 1150d62e5feeSJonathan Cameron return ret; 1151d62e5feeSJonathan Cameron } 1152d62e5feeSJonathan Cameron 1153d62e5feeSJonathan Cameron static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state) 1154d62e5feeSJonathan Cameron { 1155d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1156d62e5feeSJonathan Cameron int ret; 1157d62e5feeSJonathan Cameron 1158d62e5feeSJonathan Cameron /* read current value of mode register */ 1159d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 1160d62e5feeSJonathan Cameron if (ret) 1161d62e5feeSJonathan Cameron return ret; 1162d62e5feeSJonathan Cameron 1163d62e5feeSJonathan Cameron /* if off and should be on */ 1164d62e5feeSJonathan Cameron if (state && !(st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) 1165d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, 1166d62e5feeSJonathan Cameron st->rx[0] | SCA3000_REG_MODE_FREE_FALL_DETECT); 1167d62e5feeSJonathan Cameron /* if on and should be off */ 1168d62e5feeSJonathan Cameron else if (!state && (st->rx[0] & SCA3000_REG_MODE_FREE_FALL_DETECT)) 1169d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, 1170d62e5feeSJonathan Cameron st->rx[0] & ~SCA3000_REG_MODE_FREE_FALL_DETECT); 1171d62e5feeSJonathan Cameron else 1172d62e5feeSJonathan Cameron return 0; 1173d62e5feeSJonathan Cameron } 1174d62e5feeSJonathan Cameron 1175d62e5feeSJonathan Cameron static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis, 1176d62e5feeSJonathan Cameron int state) 1177d62e5feeSJonathan Cameron { 1178d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1179d62e5feeSJonathan Cameron int ret, ctrlval; 1180d62e5feeSJonathan Cameron 1181d62e5feeSJonathan Cameron /* 1182d62e5feeSJonathan Cameron * First read the motion detector config to find out if 1183d62e5feeSJonathan Cameron * this axis is on 1184d62e5feeSJonathan Cameron */ 1185d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); 1186d62e5feeSJonathan Cameron if (ret < 0) 1187d62e5feeSJonathan Cameron return ret; 1188d62e5feeSJonathan Cameron ctrlval = ret; 1189d62e5feeSJonathan Cameron /* if off and should be on */ 1190d62e5feeSJonathan Cameron if (state && !(ctrlval & sca3000_addresses[axis][2])) { 1191d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, 1192d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL, 1193d62e5feeSJonathan Cameron ctrlval | 1194d62e5feeSJonathan Cameron sca3000_addresses[axis][2]); 1195d62e5feeSJonathan Cameron if (ret) 1196d62e5feeSJonathan Cameron return ret; 1197d62e5feeSJonathan Cameron st->mo_det_use_count++; 1198d62e5feeSJonathan Cameron } else if (!state && (ctrlval & sca3000_addresses[axis][2])) { 1199d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, 1200d62e5feeSJonathan Cameron SCA3000_REG_CTRL_SEL_MD_CTRL, 1201d62e5feeSJonathan Cameron ctrlval & 1202d62e5feeSJonathan Cameron ~(sca3000_addresses[axis][2])); 1203d62e5feeSJonathan Cameron if (ret) 1204d62e5feeSJonathan Cameron return ret; 1205d62e5feeSJonathan Cameron st->mo_det_use_count--; 1206d62e5feeSJonathan Cameron } 1207d62e5feeSJonathan Cameron 1208d62e5feeSJonathan Cameron /* read current value of mode register */ 1209d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 1210d62e5feeSJonathan Cameron if (ret) 1211d62e5feeSJonathan Cameron return ret; 1212d62e5feeSJonathan Cameron /* if off and should be on */ 1213d62e5feeSJonathan Cameron if ((st->mo_det_use_count) && 1214d62e5feeSJonathan Cameron ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) 1215d62e5feeSJonathan Cameron != SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) 1216d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, 1217d62e5feeSJonathan Cameron (st->rx[0] & ~SCA3000_REG_MODE_MODE_MASK) 1218d62e5feeSJonathan Cameron | SCA3000_REG_MODE_MEAS_MODE_MOT_DET); 1219d62e5feeSJonathan Cameron /* if on and should be off */ 1220d62e5feeSJonathan Cameron else if (!(st->mo_det_use_count) && 1221d62e5feeSJonathan Cameron ((st->rx[0] & SCA3000_REG_MODE_MODE_MASK) 1222d62e5feeSJonathan Cameron == SCA3000_REG_MODE_MEAS_MODE_MOT_DET)) 1223d62e5feeSJonathan Cameron return sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, 1224d62e5feeSJonathan Cameron st->rx[0] & SCA3000_REG_MODE_MODE_MASK); 1225d62e5feeSJonathan Cameron else 1226d62e5feeSJonathan Cameron return 0; 1227d62e5feeSJonathan Cameron } 1228d62e5feeSJonathan Cameron 1229d62e5feeSJonathan Cameron /** 1230d62e5feeSJonathan Cameron * sca3000_write_event_config() - simple on off control for motion detector 1231d62e5feeSJonathan Cameron * @indio_dev: IIO device instance specific structure. Data specific to this 1232d62e5feeSJonathan Cameron * particular driver may be accessed via iio_priv(indio_dev). 1233d62e5feeSJonathan Cameron * @chan: Description of the channel whose event we are configuring. 1234d62e5feeSJonathan Cameron * @type: The type of event. 1235d62e5feeSJonathan Cameron * @dir: The direction of the event. 1236d62e5feeSJonathan Cameron * @state: Desired state of event being configured. 1237d62e5feeSJonathan Cameron * 1238d62e5feeSJonathan Cameron * This is a per axis control, but enabling any will result in the 1239d62e5feeSJonathan Cameron * motion detector unit being enabled. 1240d62e5feeSJonathan Cameron * N.B. enabling motion detector stops normal data acquisition. 1241d62e5feeSJonathan Cameron * There is a complexity in knowing which mode to return to when 1242d62e5feeSJonathan Cameron * this mode is disabled. Currently normal mode is assumed. 1243d62e5feeSJonathan Cameron **/ 1244d62e5feeSJonathan Cameron static int sca3000_write_event_config(struct iio_dev *indio_dev, 1245d62e5feeSJonathan Cameron const struct iio_chan_spec *chan, 1246d62e5feeSJonathan Cameron enum iio_event_type type, 1247d62e5feeSJonathan Cameron enum iio_event_direction dir, 1248d62e5feeSJonathan Cameron int state) 1249d62e5feeSJonathan Cameron { 1250d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1251d62e5feeSJonathan Cameron int ret; 1252d62e5feeSJonathan Cameron 1253d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1254d62e5feeSJonathan Cameron switch (chan->channel2) { 1255d62e5feeSJonathan Cameron case IIO_MOD_X_AND_Y_AND_Z: 1256d62e5feeSJonathan Cameron ret = sca3000_freefall_set_state(indio_dev, state); 1257d62e5feeSJonathan Cameron break; 1258d62e5feeSJonathan Cameron 1259d62e5feeSJonathan Cameron case IIO_MOD_X: 1260d62e5feeSJonathan Cameron case IIO_MOD_Y: 1261d62e5feeSJonathan Cameron case IIO_MOD_Z: 1262d62e5feeSJonathan Cameron ret = sca3000_motion_detect_set_state(indio_dev, 1263d62e5feeSJonathan Cameron chan->address, 1264d62e5feeSJonathan Cameron state); 1265d62e5feeSJonathan Cameron break; 1266d62e5feeSJonathan Cameron default: 1267d62e5feeSJonathan Cameron ret = -EINVAL; 1268d62e5feeSJonathan Cameron break; 1269d62e5feeSJonathan Cameron } 1270d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1271d62e5feeSJonathan Cameron 1272d62e5feeSJonathan Cameron return ret; 1273d62e5feeSJonathan Cameron } 1274d62e5feeSJonathan Cameron 1275d62e5feeSJonathan Cameron static int sca3000_configure_ring(struct iio_dev *indio_dev) 1276d62e5feeSJonathan Cameron { 1277d62e5feeSJonathan Cameron struct iio_buffer *buffer; 1278d62e5feeSJonathan Cameron 12794a5b4538SChristophe JAILLET buffer = devm_iio_kfifo_allocate(&indio_dev->dev); 1280d62e5feeSJonathan Cameron if (!buffer) 1281d62e5feeSJonathan Cameron return -ENOMEM; 1282d62e5feeSJonathan Cameron 1283d62e5feeSJonathan Cameron iio_device_attach_buffer(indio_dev, buffer); 1284d62e5feeSJonathan Cameron indio_dev->modes |= INDIO_BUFFER_SOFTWARE; 1285d62e5feeSJonathan Cameron 1286d62e5feeSJonathan Cameron return 0; 1287d62e5feeSJonathan Cameron } 1288d62e5feeSJonathan Cameron 1289d62e5feeSJonathan Cameron static inline 1290d62e5feeSJonathan Cameron int __sca3000_hw_ring_state_set(struct iio_dev *indio_dev, bool state) 1291d62e5feeSJonathan Cameron { 1292d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1293d62e5feeSJonathan Cameron int ret; 1294d62e5feeSJonathan Cameron 1295d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1296d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 1297d62e5feeSJonathan Cameron if (ret) 1298d62e5feeSJonathan Cameron goto error_ret; 1299d62e5feeSJonathan Cameron if (state) { 1300d62e5feeSJonathan Cameron dev_info(&indio_dev->dev, "supposedly enabling ring buffer\n"); 1301d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, 1302d62e5feeSJonathan Cameron SCA3000_REG_MODE_ADDR, 1303d62e5feeSJonathan Cameron (st->rx[0] | SCA3000_REG_MODE_RING_BUF_ENABLE)); 1304d62e5feeSJonathan Cameron } else 1305d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, 1306d62e5feeSJonathan Cameron SCA3000_REG_MODE_ADDR, 1307d62e5feeSJonathan Cameron (st->rx[0] & ~SCA3000_REG_MODE_RING_BUF_ENABLE)); 1308d62e5feeSJonathan Cameron error_ret: 1309d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1310d62e5feeSJonathan Cameron 1311d62e5feeSJonathan Cameron return ret; 1312d62e5feeSJonathan Cameron } 1313d62e5feeSJonathan Cameron 1314d62e5feeSJonathan Cameron /** 1315d62e5feeSJonathan Cameron * sca3000_hw_ring_preenable() - hw ring buffer preenable function 1316d62e5feeSJonathan Cameron * @indio_dev: structure representing the IIO device. Device instance 1317d62e5feeSJonathan Cameron * specific state can be accessed via iio_priv(indio_dev). 1318d62e5feeSJonathan Cameron * 1319d62e5feeSJonathan Cameron * Very simple enable function as the chip will allows normal reads 1320d62e5feeSJonathan Cameron * during ring buffer operation so as long as it is indeed running 1321d62e5feeSJonathan Cameron * before we notify the core, the precise ordering does not matter. 1322d62e5feeSJonathan Cameron */ 1323d62e5feeSJonathan Cameron static int sca3000_hw_ring_preenable(struct iio_dev *indio_dev) 1324d62e5feeSJonathan Cameron { 1325d62e5feeSJonathan Cameron int ret; 1326d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1327d62e5feeSJonathan Cameron 1328d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1329d62e5feeSJonathan Cameron 1330d62e5feeSJonathan Cameron /* Enable the 50% full interrupt */ 1331d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); 1332d62e5feeSJonathan Cameron if (ret) 1333d62e5feeSJonathan Cameron goto error_unlock; 1334d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, 1335d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR, 1336d62e5feeSJonathan Cameron st->rx[0] | SCA3000_REG_INT_MASK_RING_HALF); 1337d62e5feeSJonathan Cameron if (ret) 1338d62e5feeSJonathan Cameron goto error_unlock; 1339d62e5feeSJonathan Cameron 1340d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1341d62e5feeSJonathan Cameron 1342d62e5feeSJonathan Cameron return __sca3000_hw_ring_state_set(indio_dev, 1); 1343d62e5feeSJonathan Cameron 1344d62e5feeSJonathan Cameron error_unlock: 1345d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1346d62e5feeSJonathan Cameron 1347d62e5feeSJonathan Cameron return ret; 1348d62e5feeSJonathan Cameron } 1349d62e5feeSJonathan Cameron 1350d62e5feeSJonathan Cameron static int sca3000_hw_ring_postdisable(struct iio_dev *indio_dev) 1351d62e5feeSJonathan Cameron { 1352d62e5feeSJonathan Cameron int ret; 1353d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1354d62e5feeSJonathan Cameron 1355d62e5feeSJonathan Cameron ret = __sca3000_hw_ring_state_set(indio_dev, 0); 1356d62e5feeSJonathan Cameron if (ret) 1357d62e5feeSJonathan Cameron return ret; 1358d62e5feeSJonathan Cameron 1359d62e5feeSJonathan Cameron /* Disable the 50% full interrupt */ 1360d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1361d62e5feeSJonathan Cameron 1362d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); 1363d62e5feeSJonathan Cameron if (ret) 1364d62e5feeSJonathan Cameron goto unlock; 1365d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, 1366d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR, 1367d62e5feeSJonathan Cameron st->rx[0] & ~SCA3000_REG_INT_MASK_RING_HALF); 1368d62e5feeSJonathan Cameron unlock: 1369d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1370d62e5feeSJonathan Cameron return ret; 1371d62e5feeSJonathan Cameron } 1372d62e5feeSJonathan Cameron 1373d62e5feeSJonathan Cameron static const struct iio_buffer_setup_ops sca3000_ring_setup_ops = { 1374d62e5feeSJonathan Cameron .preenable = &sca3000_hw_ring_preenable, 1375d62e5feeSJonathan Cameron .postdisable = &sca3000_hw_ring_postdisable, 1376d62e5feeSJonathan Cameron }; 1377d62e5feeSJonathan Cameron 1378d62e5feeSJonathan Cameron /** 1379d62e5feeSJonathan Cameron * sca3000_clean_setup() - get the device into a predictable state 1380d62e5feeSJonathan Cameron * @st: Device instance specific private data structure 1381d62e5feeSJonathan Cameron * 1382d62e5feeSJonathan Cameron * Devices use flash memory to store many of the register values 1383d62e5feeSJonathan Cameron * and hence can come up in somewhat unpredictable states. 1384d62e5feeSJonathan Cameron * Hence reset everything on driver load. 1385d62e5feeSJonathan Cameron */ 1386d62e5feeSJonathan Cameron static int sca3000_clean_setup(struct sca3000_state *st) 1387d62e5feeSJonathan Cameron { 1388d62e5feeSJonathan Cameron int ret; 1389d62e5feeSJonathan Cameron 1390d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1391d62e5feeSJonathan Cameron /* Ensure all interrupts have been acknowledged */ 1392d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_STATUS_ADDR, 1); 1393d62e5feeSJonathan Cameron if (ret) 1394d62e5feeSJonathan Cameron goto error_ret; 1395d62e5feeSJonathan Cameron 1396d62e5feeSJonathan Cameron /* Turn off all motion detection channels */ 1397d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL); 1398d62e5feeSJonathan Cameron if (ret < 0) 1399d62e5feeSJonathan Cameron goto error_ret; 1400d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_MD_CTRL, 1401d62e5feeSJonathan Cameron ret & SCA3000_MD_CTRL_PROT_MASK); 1402d62e5feeSJonathan Cameron if (ret) 1403d62e5feeSJonathan Cameron goto error_ret; 1404d62e5feeSJonathan Cameron 1405d62e5feeSJonathan Cameron /* Disable ring buffer */ 1406d62e5feeSJonathan Cameron ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL); 1407d62e5feeSJonathan Cameron if (ret < 0) 1408d62e5feeSJonathan Cameron goto error_ret; 1409d62e5feeSJonathan Cameron ret = sca3000_write_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL, 1410d62e5feeSJonathan Cameron (ret & SCA3000_REG_OUT_CTRL_PROT_MASK) 1411d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_X_EN 1412d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_Y_EN 1413d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_Z_EN 1414d62e5feeSJonathan Cameron | SCA3000_REG_OUT_CTRL_BUF_DIV_4); 1415d62e5feeSJonathan Cameron if (ret) 1416d62e5feeSJonathan Cameron goto error_ret; 1417d62e5feeSJonathan Cameron /* Enable interrupts, relevant to mode and set up as active low */ 1418d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); 1419d62e5feeSJonathan Cameron if (ret) 1420d62e5feeSJonathan Cameron goto error_ret; 1421d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, 1422d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ADDR, 1423d62e5feeSJonathan Cameron (ret & SCA3000_REG_INT_MASK_PROT_MASK) 1424d62e5feeSJonathan Cameron | SCA3000_REG_INT_MASK_ACTIVE_LOW); 1425d62e5feeSJonathan Cameron if (ret) 1426d62e5feeSJonathan Cameron goto error_ret; 1427d62e5feeSJonathan Cameron /* 1428d62e5feeSJonathan Cameron * Select normal measurement mode, free fall off, ring off 1429d62e5feeSJonathan Cameron * Ring in 12 bit mode - it is fine to overwrite reserved bits 3,5 1430d62e5feeSJonathan Cameron * as that occurs in one of the example on the datasheet 1431d62e5feeSJonathan Cameron */ 1432d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_MODE_ADDR, 1); 1433d62e5feeSJonathan Cameron if (ret) 1434d62e5feeSJonathan Cameron goto error_ret; 1435d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_MODE_ADDR, 1436d62e5feeSJonathan Cameron (st->rx[0] & SCA3000_MODE_PROT_MASK)); 1437d62e5feeSJonathan Cameron 1438d62e5feeSJonathan Cameron error_ret: 1439d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1440d62e5feeSJonathan Cameron return ret; 1441d62e5feeSJonathan Cameron } 1442d62e5feeSJonathan Cameron 1443d62e5feeSJonathan Cameron static const struct iio_info sca3000_info = { 1444d62e5feeSJonathan Cameron .attrs = &sca3000_attribute_group, 1445d62e5feeSJonathan Cameron .read_raw = &sca3000_read_raw, 1446d62e5feeSJonathan Cameron .write_raw = &sca3000_write_raw, 1447d62e5feeSJonathan Cameron .read_event_value = &sca3000_read_event_value, 1448d62e5feeSJonathan Cameron .write_event_value = &sca3000_write_event_value, 1449d62e5feeSJonathan Cameron .read_event_config = &sca3000_read_event_config, 1450d62e5feeSJonathan Cameron .write_event_config = &sca3000_write_event_config, 1451d62e5feeSJonathan Cameron }; 1452d62e5feeSJonathan Cameron 1453d62e5feeSJonathan Cameron static int sca3000_probe(struct spi_device *spi) 1454d62e5feeSJonathan Cameron { 1455d62e5feeSJonathan Cameron int ret; 1456d62e5feeSJonathan Cameron struct sca3000_state *st; 1457d62e5feeSJonathan Cameron struct iio_dev *indio_dev; 1458d62e5feeSJonathan Cameron 1459d62e5feeSJonathan Cameron indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 1460d62e5feeSJonathan Cameron if (!indio_dev) 1461d62e5feeSJonathan Cameron return -ENOMEM; 1462d62e5feeSJonathan Cameron 1463d62e5feeSJonathan Cameron st = iio_priv(indio_dev); 1464d62e5feeSJonathan Cameron spi_set_drvdata(spi, indio_dev); 1465d62e5feeSJonathan Cameron st->us = spi; 1466d62e5feeSJonathan Cameron mutex_init(&st->lock); 1467d62e5feeSJonathan Cameron st->info = &sca3000_spi_chip_info_tbl[spi_get_device_id(spi) 1468d62e5feeSJonathan Cameron ->driver_data]; 1469d62e5feeSJonathan Cameron 1470d62e5feeSJonathan Cameron indio_dev->dev.parent = &spi->dev; 1471d62e5feeSJonathan Cameron indio_dev->name = spi_get_device_id(spi)->name; 1472d62e5feeSJonathan Cameron indio_dev->info = &sca3000_info; 1473d62e5feeSJonathan Cameron if (st->info->temp_output) { 1474d62e5feeSJonathan Cameron indio_dev->channels = sca3000_channels_with_temp; 1475d62e5feeSJonathan Cameron indio_dev->num_channels = 1476d62e5feeSJonathan Cameron ARRAY_SIZE(sca3000_channels_with_temp); 1477d62e5feeSJonathan Cameron } else { 1478d62e5feeSJonathan Cameron indio_dev->channels = sca3000_channels; 1479d62e5feeSJonathan Cameron indio_dev->num_channels = ARRAY_SIZE(sca3000_channels); 1480d62e5feeSJonathan Cameron } 1481d62e5feeSJonathan Cameron indio_dev->modes = INDIO_DIRECT_MODE; 1482d62e5feeSJonathan Cameron 1483da2d5449SChristophe JAILLET ret = sca3000_configure_ring(indio_dev); 1484da2d5449SChristophe JAILLET if (ret) 1485da2d5449SChristophe JAILLET return ret; 1486d62e5feeSJonathan Cameron 1487d62e5feeSJonathan Cameron if (spi->irq) { 1488d62e5feeSJonathan Cameron ret = request_threaded_irq(spi->irq, 1489d62e5feeSJonathan Cameron NULL, 1490d62e5feeSJonathan Cameron &sca3000_event_handler, 1491d62e5feeSJonathan Cameron IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 1492d62e5feeSJonathan Cameron "sca3000", 1493d62e5feeSJonathan Cameron indio_dev); 1494d62e5feeSJonathan Cameron if (ret) 1495d62e5feeSJonathan Cameron return ret; 1496d62e5feeSJonathan Cameron } 1497d62e5feeSJonathan Cameron indio_dev->setup_ops = &sca3000_ring_setup_ops; 1498d62e5feeSJonathan Cameron ret = sca3000_clean_setup(st); 1499d62e5feeSJonathan Cameron if (ret) 1500d62e5feeSJonathan Cameron goto error_free_irq; 1501d62e5feeSJonathan Cameron 1502d62e5feeSJonathan Cameron ret = sca3000_print_rev(indio_dev); 1503d62e5feeSJonathan Cameron if (ret) 1504d62e5feeSJonathan Cameron goto error_free_irq; 1505d62e5feeSJonathan Cameron 1506d62e5feeSJonathan Cameron return iio_device_register(indio_dev); 1507d62e5feeSJonathan Cameron 1508d62e5feeSJonathan Cameron error_free_irq: 1509d62e5feeSJonathan Cameron if (spi->irq) 1510d62e5feeSJonathan Cameron free_irq(spi->irq, indio_dev); 1511d62e5feeSJonathan Cameron 1512d62e5feeSJonathan Cameron return ret; 1513d62e5feeSJonathan Cameron } 1514d62e5feeSJonathan Cameron 1515d62e5feeSJonathan Cameron static int sca3000_stop_all_interrupts(struct sca3000_state *st) 1516d62e5feeSJonathan Cameron { 1517d62e5feeSJonathan Cameron int ret; 1518d62e5feeSJonathan Cameron 1519d62e5feeSJonathan Cameron mutex_lock(&st->lock); 1520d62e5feeSJonathan Cameron ret = sca3000_read_data_short(st, SCA3000_REG_INT_MASK_ADDR, 1); 1521d62e5feeSJonathan Cameron if (ret) 1522d62e5feeSJonathan Cameron goto error_ret; 1523d62e5feeSJonathan Cameron ret = sca3000_write_reg(st, SCA3000_REG_INT_MASK_ADDR, 1524d62e5feeSJonathan Cameron (st->rx[0] & 1525d62e5feeSJonathan Cameron ~(SCA3000_REG_INT_MASK_RING_THREE_QUARTER | 1526d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_RING_HALF | 1527d62e5feeSJonathan Cameron SCA3000_REG_INT_MASK_ALL_INTS))); 1528d62e5feeSJonathan Cameron error_ret: 1529d62e5feeSJonathan Cameron mutex_unlock(&st->lock); 1530d62e5feeSJonathan Cameron return ret; 1531d62e5feeSJonathan Cameron } 1532d62e5feeSJonathan Cameron 1533d62e5feeSJonathan Cameron static int sca3000_remove(struct spi_device *spi) 1534d62e5feeSJonathan Cameron { 1535d62e5feeSJonathan Cameron struct iio_dev *indio_dev = spi_get_drvdata(spi); 1536d62e5feeSJonathan Cameron struct sca3000_state *st = iio_priv(indio_dev); 1537d62e5feeSJonathan Cameron 1538d62e5feeSJonathan Cameron iio_device_unregister(indio_dev); 1539d62e5feeSJonathan Cameron 1540d62e5feeSJonathan Cameron /* Must ensure no interrupts can be generated after this! */ 1541d62e5feeSJonathan Cameron sca3000_stop_all_interrupts(st); 1542d62e5feeSJonathan Cameron if (spi->irq) 1543d62e5feeSJonathan Cameron free_irq(spi->irq, indio_dev); 1544d62e5feeSJonathan Cameron 1545d62e5feeSJonathan Cameron return 0; 1546d62e5feeSJonathan Cameron } 1547d62e5feeSJonathan Cameron 1548d62e5feeSJonathan Cameron static const struct spi_device_id sca3000_id[] = { 1549d62e5feeSJonathan Cameron {"sca3000_d01", d01}, 1550d62e5feeSJonathan Cameron {"sca3000_e02", e02}, 1551d62e5feeSJonathan Cameron {"sca3000_e04", e04}, 1552d62e5feeSJonathan Cameron {"sca3000_e05", e05}, 1553d62e5feeSJonathan Cameron {} 1554d62e5feeSJonathan Cameron }; 1555d62e5feeSJonathan Cameron MODULE_DEVICE_TABLE(spi, sca3000_id); 1556d62e5feeSJonathan Cameron 1557d62e5feeSJonathan Cameron static struct spi_driver sca3000_driver = { 1558d62e5feeSJonathan Cameron .driver = { 1559d62e5feeSJonathan Cameron .name = "sca3000", 1560d62e5feeSJonathan Cameron }, 1561d62e5feeSJonathan Cameron .probe = sca3000_probe, 1562d62e5feeSJonathan Cameron .remove = sca3000_remove, 1563d62e5feeSJonathan Cameron .id_table = sca3000_id, 1564d62e5feeSJonathan Cameron }; 1565d62e5feeSJonathan Cameron module_spi_driver(sca3000_driver); 1566d62e5feeSJonathan Cameron 1567d62e5feeSJonathan Cameron MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>"); 1568d62e5feeSJonathan Cameron MODULE_DESCRIPTION("VTI SCA3000 Series Accelerometers SPI driver"); 1569d62e5feeSJonathan Cameron MODULE_LICENSE("GPL v2"); 1570