static ssize_t adis16400_show_serial_number(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct adis16400_state *st = file->private_data; u16 lot1, lot2, serial_number; char buf[16]; size_t len; int ret; ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID1, &lot1); if (ret < 0) return ret; ret = adis_read_reg_16(&st->adis, ADIS16334_LOT_ID2, &lot2); if (ret < 0) return ret; ret = adis_read_reg_16(&st->adis, ADIS16334_SERIAL_NUMBER, &serial_number); if (ret < 0) return ret; len = snprintf(buf, sizeof(buf), "%.4x-%.4x-%.4x\n", lot1, lot2, serial_number); return simple_read_from_buffer(userbuf, count, ppos, buf, len); }
static ssize_t adis16136_show_serial(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct adis16136 *adis16136 = file->private_data; uint16_t lot1, lot2, lot3, serial; char buf[20]; size_t len; int ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SERIAL_NUM, &serial); if (ret < 0) return ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT1, &lot1); if (ret < 0) return ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT2, &lot2); if (ret < 0) return ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_LOT3, &lot3); if (ret < 0) return ret; len = snprintf(buf, sizeof(buf), "%.4x%.4x%.4x-%.4x\n", lot1, lot2, lot3, serial); return simple_read_from_buffer(userbuf, count, ppos, buf, len); }
static int adis16400_initial_setup(struct iio_dev *indio_dev) { struct adis16400_state *st = iio_priv(indio_dev); uint16_t prod_id, smp_prd; unsigned int device_id; int ret; /* use low spi speed for init if the device has a slow mode */ if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) st->adis.spi->max_speed_hz = ADIS16400_SPI_SLOW; else st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; st->adis.spi->mode = SPI_MODE_3; spi_setup(st->adis.spi); ret = adis_initial_startup(&st->adis); if (ret) return ret; if (st->variant->flags & ADIS16400_HAS_PROD_ID) { ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id); if (ret) goto err_ret; sscanf(indio_dev->name, "adis%u\n", &device_id); if (prod_id != device_id) dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", device_id, prod_id); dev_info(&indio_dev->dev, "%s: prod_id 0x%04x at CS%d (irq %d)\n", indio_dev->name, prod_id, st->adis.spi->chip_select, st->adis.spi->irq); } /* use high spi speed if possible */ if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) { ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &smp_prd); if (ret) goto err_ret; if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) { st->adis.spi->max_speed_hz = ADIS16400_SPI_FAST; spi_setup(st->adis.spi); } } err_ret: return ret; }
static int adis16334_get_freq(struct adis16400_state *st) { int ret; uint16_t t; ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret < 0) return ret; t >>= ADIS16334_RATE_DIV_SHIFT; return 819200 >> t; }
static int adis16136_get_freq(struct adis16136 *adis16136, unsigned int *freq) { uint16_t t; int ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_SMPL_PRD, &t); if (ret < 0) return ret; *freq = 32768 / (t + 1); return 0; }
static int adis16400_show_flash_count(void *arg, u64 *val) { struct adis16400_state *st = arg; uint16_t flash_count; int ret; ret = adis_read_reg_16(&st->adis, ADIS16400_FLASH_CNT, &flash_count); if (ret < 0) return ret; *val = flash_count; return 0; }
static int adis16400_show_product_id(void *arg, u64 *val) { struct adis16400_state *st = arg; uint16_t prod_id; int ret; ret = adis_read_reg_16(&st->adis, ADIS16400_PRODUCT_ID, &prod_id); if (ret < 0) return ret; *val = prod_id; return 0; }
static int adis16400_get_freq(struct adis16400_state *st) { int sps, ret; uint16_t t; ret = adis_read_reg_16(&st->adis, ADIS16400_SMPL_PRD, &t); if (ret < 0) return ret; sps = (t & ADIS16400_SMPL_PRD_TIME_BASE) ? 52851 : 1638404; sps /= (t & ADIS16400_SMPL_PRD_DIV_MASK) + 1; return sps; }
static int adis16136_show_flash_count(void *arg, u64 *val) { struct adis16136 *adis16136 = arg; uint16_t flash_count; int ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_FLASH_CNT, &flash_count); if (ret < 0) return ret; *val = flash_count; return 0; }
static int adis16136_show_product_id(void *arg, u64 *val) { struct adis16136 *adis16136 = arg; u16 prod_id; int ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, &prod_id); if (ret < 0) return ret; *val = prod_id; return 0; }
static int adis16400_set_filter(struct iio_dev *indio_dev, int sps, int val) { struct adis16400_state *st = iio_priv(indio_dev); uint16_t val16; int i, ret; for (i = ARRAY_SIZE(adis16400_3db_divisors) - 1; i >= 1; i--) { if (sps / adis16400_3db_divisors[i] >= val) break; } ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret < 0) return ret; ret = adis_write_reg_16(&st->adis, ADIS16400_SENS_AVG, (val16 & ~0x07) | i); return ret; }
static int adis16136_initial_setup(struct iio_dev *indio_dev) { struct adis16136 *adis16136 = iio_priv(indio_dev); unsigned int device_id; uint16_t prod_id; int ret; ret = adis_initial_startup(&adis16136->adis); if (ret) return ret; ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_PROD_ID, &prod_id); if (ret) return ret; sscanf(indio_dev->name, "adis%u\n", &device_id); if (prod_id != device_id) dev_warn(&indio_dev->dev, "Device ID(%u) and product ID(%u) do not match.", device_id, prod_id); return 0; }
static int adis16136_get_filter(struct iio_dev *indio_dev, int *val) { struct adis16136 *adis16136 = iio_priv(indio_dev); unsigned int freq; uint16_t val16; int ret; mutex_lock(&indio_dev->mlock); ret = adis_read_reg_16(&adis16136->adis, ADIS16136_REG_AVG_CNT, &val16); if (ret < 0) goto err_unlock; ret = adis16136_get_freq(adis16136, &freq); if (ret < 0) goto err_unlock; *val = freq / adis16136_3db_divisors[val16 & 0x07]; err_unlock: mutex_unlock(&indio_dev->mlock); return ret ? ret : IIO_VAL_INT; }
static int adis16400_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct adis16400_state *st = iio_priv(indio_dev); int16_t val16; int ret; switch (info) { case IIO_CHAN_INFO_RAW: return adis_single_conversion(indio_dev, chan, 0, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; *val2 = st->variant->gyro_scale_micro; return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: *val = 0; if (chan->channel == 0) { *val = 2; *val2 = 418000; /* 2.418 mV */ } else { *val = 0; *val2 = 805800; /* 805.8 uV */ } return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: *val = 0; *val2 = st->variant->accel_scale_micro; return IIO_VAL_INT_PLUS_MICRO; case IIO_MAGN: *val = 0; *val2 = 500; /* 0.5 mgauss */ return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: *val = st->variant->temp_scale_nano / 1000000; *val2 = (st->variant->temp_scale_nano % 1000000); return IIO_VAL_INT_PLUS_MICRO; case IIO_PRESSURE: /* 20 uBar = 0.002kPascal */ *val = 0; *val2 = 2000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } case IIO_CHAN_INFO_CALIBBIAS: mutex_lock(&indio_dev->mlock); ret = adis_read_reg_16(&st->adis, adis16400_addresses[chan->scan_index], &val16); mutex_unlock(&indio_dev->mlock); if (ret) return ret; val16 = sign_extend32(val16, 11); *val = val16; return IIO_VAL_INT; case IIO_CHAN_INFO_OFFSET: /* currently only temperature */ *val = st->variant->temp_offset; return IIO_VAL_INT; case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: mutex_lock(&indio_dev->mlock); /* Need both the number of taps and the sampling frequency */ ret = adis_read_reg_16(&st->adis, ADIS16400_SENS_AVG, &val16); if (ret < 0) { mutex_unlock(&indio_dev->mlock); return ret; } ret = st->variant->get_freq(st); if (ret >= 0) { ret /= adis16400_3db_divisors[val16 & 0x07]; *val = ret / 1000; *val2 = (ret % 1000) * 1000; } mutex_unlock(&indio_dev->mlock); if (ret < 0) return ret; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SAMP_FREQ: ret = st->variant->get_freq(st); if (ret < 0) return ret; *val = ret / 1000; *val2 = (ret % 1000) * 1000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } }
static int adis16209_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct adis *st = iio_priv(indio_dev); int ret; int bits; u8 addr; s16 val16; switch (mask) { case IIO_CHAN_INFO_RAW: return adis_single_conversion(indio_dev, chan, ADIS16209_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_VOLTAGE: *val = 0; switch (chan->channel) { case 0: *val2 = 305180; /* 0.30518 mV */ break; case 1: *val2 = 610500; /* 0.6105 mV */ break; default: return -EINVAL; } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: *val = -470; *val2 = 0; return IIO_VAL_INT_PLUS_MICRO; case IIO_ACCEL: /* * IIO base unit for sensitivity of accelerometer * is milli g. * 1 LSB represents 0.244 mg. */ *val = 0; *val2 = IIO_G_TO_M_S_2(244140); return IIO_VAL_INT_PLUS_NANO; case IIO_INCLI: case IIO_ROT: /* * IIO base units for rotation are degrees. * 1 LSB represents 0.025 milli degrees. */ *val = 0; *val2 = 25000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } break; case IIO_CHAN_INFO_OFFSET: /* * The raw ADC value is 0x4FE when the temperature * is 25 degrees and the scale factor per milli * degree celcius is -470. */ *val = 25000 / -470 - 0x4FE; return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: switch (chan->type) { case IIO_ACCEL: bits = 14; break; default: return -EINVAL; } addr = adis16209_addresses[chan->scan_index][0]; ret = adis_read_reg_16(st, addr, &val16); if (ret) return ret; *val = sign_extend32(val16, bits - 1); return IIO_VAL_INT; } return -EINVAL; }
static int adis16260_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long mask) { struct adis *adis = iio_priv(indio_dev); int ret; u8 addr; s16 val16; switch (mask) { case IIO_CHAN_INFO_RAW: return adis_single_conversion(indio_dev, chan, ADIS16260_ERROR_ACTIVE, val); case IIO_CHAN_INFO_SCALE: switch (chan->type) { case IIO_ANGL_VEL: *val = 0; if (spi_get_device_id(adis->spi)->driver_data) { /* 0.01832 degree / sec */ *val2 = IIO_DEGREE_TO_RAD(18320); } else { /* 0.07326 degree / sec */ *val2 = IIO_DEGREE_TO_RAD(73260); } return IIO_VAL_INT_PLUS_MICRO; case IIO_INCLI: *val = 0; *val2 = IIO_DEGREE_TO_RAD(36630); return IIO_VAL_INT_PLUS_MICRO; case IIO_VOLTAGE: if (chan->channel == 0) { *val = 1; *val2 = 831500; /* 1.8315 mV */ } else { *val = 0; *val2 = 610500; /* 610.5 uV */ } return IIO_VAL_INT_PLUS_MICRO; case IIO_TEMP: *val = 145; *val2 = 300000; /* 0.1453 C */ return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; } case IIO_CHAN_INFO_OFFSET: *val = 250000 / 1453; /* 25 C = 0x00 */ return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBBIAS: addr = adis16260_addresses[chan->scan_index][0]; ret = adis_read_reg_16(adis, addr, &val16); if (ret) return ret; *val = sign_extend32(val16, 11); return IIO_VAL_INT; case IIO_CHAN_INFO_CALIBSCALE: addr = adis16260_addresses[chan->scan_index][1]; ret = adis_read_reg_16(adis, addr, &val16); if (ret) return ret; *val = val16; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16); if (ret) return ret; if (spi_get_device_id(adis->spi)->driver_data) /* If an adis16251 */ *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ? 8 : 256; else *val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ? 66 : 2048; *val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1; return IIO_VAL_INT; } return -EINVAL; }