summaryrefslogtreecommitdiff
path: root/drivers/staging/iio/imu/adis16400_core.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:59:44 (GMT)
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-11 21:59:44 (GMT)
commit8966961b31c251b854169e9886394c2a20f2cea7 (patch)
tree248a625b23335acbd5ca4b55eb136fe0dc8ba0aa /drivers/staging/iio/imu/adis16400_core.c
parent6a5971d8fea1f4a8c33dfe0cec6a1c490f0c9cde (diff)
parent7bcb57cde66c19df378f3468ea342166a8a4504d (diff)
downloadlinux-fsl-qoriq-8966961b31c251b854169e9886394c2a20f2cea7.tar.xz
Merge tag 'staging-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging driver tree merge from Greg Kroah-Hartman: "Here's the big staging tree merge for 3.8-rc1 There's a lot of patches in here, the majority being the comedi rework/cleanup that has been ongoing and is causing a huge reduction in overall code size, which is amazing to watch. We also removed some older drivers (telephony and rts_pstor), and added a new one (fwserial which also came in through the tty tree due to tty api changes, take that one if you get merge conflicts.) The iio and ipack drivers are moving out of the staging area into their own part of the kernel as they have been cleaned up sufficiently and are working well. Overall, again a reduction of code: 768 files changed, 31887 insertions(+), 82166 deletions(-) All of this has been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" * tag 'staging-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1298 commits) iio: imu: adis16480: remove duplicated include from adis16480.c iio: gyro: adis16136: remove duplicated include from adis16136.c iio:imu: adis16480: show_firmware() buffer too small iio:gyro: adis16136: divide by zero in write_frequency() iio: adc: Add Texas Instruments ADC081C021/027 support iio:ad7793: Add support for the ad7796 and ad7797 iio:ad7793: Add support for the ad7798 and ad7799 staging:iio: Move ad7793 driver out of staging staging:iio:ad7793: Implement stricter id checking staging:iio:ad7793: Move register definitions from header to source staging:iio:ad7793: Rework regulator handling staging:iio:ad7793: Rework platform data staging:iio:ad7793: Use kstrtol instead of strict_strtol staging:iio:ad7793: Use usleep_range instead of msleep staging:iio:ad7793: Fix temperature scale staging:iio:ad7793: Fix VDD monitor scale staging: gdm72xx: unlock on error in init_usb() staging: panel: pass correct lengths to keypad_send_key() staging: comedi: addi_apci_2032: fix interrupt support staging: comedi: addi_apci_2032: move i_APCI2032_ConfigDigitalOutput() ...
Diffstat (limited to 'drivers/staging/iio/imu/adis16400_core.c')
-rw-r--r--drivers/staging/iio/imu/adis16400_core.c161
1 files changed, 105 insertions, 56 deletions
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 3144a7b..9c8f5ab 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -38,7 +38,6 @@ enum adis16400_chip_variant {
ADIS16360,
ADIS16362,
ADIS16364,
- ADIS16365,
ADIS16400,
};
@@ -161,10 +160,39 @@ error_ret:
return ret;
}
-static int adis16400_get_freq(struct iio_dev *indio_dev)
+static int adis16334_get_freq(struct iio_dev *indio_dev)
{
+ int ret;
u16 t;
+
+ ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
+ if (ret < 0)
+ return ret;
+
+ t >>= ADIS16334_RATE_DIV_SHIFT;
+
+ return (8192 >> t) / 10;
+}
+
+static int adis16334_set_freq(struct iio_dev *indio_dev, unsigned int freq)
+{
+ unsigned int t;
+
+ t = ilog2(8192 / (freq * 10));
+
+ if (t > 0x31)
+ t = 0x31;
+
+ t <<= ADIS16334_RATE_DIV_SHIFT;
+ t |= ADIS16334_RATE_INT_CLK;
+
+ return adis16400_spi_write_reg_16(indio_dev, ADIS16400_SMPL_PRD, t);
+}
+
+static int adis16400_get_freq(struct iio_dev *indio_dev)
+{
int sps, ret;
+ u16 t;
ret = adis16400_spi_read_reg_16(indio_dev, ADIS16400_SMPL_PRD, &t);
if (ret < 0)
@@ -175,13 +203,33 @@ static int adis16400_get_freq(struct iio_dev *indio_dev)
return sps;
}
+static int adis16400_set_freq(struct iio_dev *indio_dev, unsigned int freq)
+{
+ struct adis16400_state *st = iio_priv(indio_dev);
+ unsigned int t;
+
+ t = 1638 / freq;
+ if (t > 0)
+ t--;
+ t &= ADIS16400_SMPL_PRD_DIV_MASK;
+ if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
+ st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+ else
+ st->us->max_speed_hz = ADIS16400_SPI_FAST;
+
+ return adis16400_spi_write_reg_8(indio_dev,
+ ADIS16400_SMPL_PRD, t);
+}
+
static ssize_t adis16400_read_frequency(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct adis16400_state *st = iio_priv(indio_dev);
int ret, len = 0;
- ret = adis16400_get_freq(indio_dev);
+
+ ret = st->variant->get_freq(indio_dev);
if (ret < 0)
return ret;
len = sprintf(buf, "%d SPS\n", ret);
@@ -229,7 +277,6 @@ static ssize_t adis16400_write_frequency(struct device *dev,
struct adis16400_state *st = iio_priv(indio_dev);
long val;
int ret;
- u8 t;
ret = strict_strtol(buf, 10, &val);
if (ret)
@@ -239,18 +286,7 @@ static ssize_t adis16400_write_frequency(struct device *dev,
mutex_lock(&indio_dev->mlock);
- t = (1638 / val);
- if (t > 0)
- t--;
- t &= ADIS16400_SMPL_PRD_DIV_MASK;
- if ((t & ADIS16400_SMPL_PRD_DIV_MASK) >= 0x0A)
- st->us->max_speed_hz = ADIS16400_SPI_SLOW;
- else
- st->us->max_speed_hz = ADIS16400_SPI_FAST;
-
- ret = adis16400_spi_write_reg_8(indio_dev,
- ADIS16400_SMPL_PRD,
- t);
+ st->variant->set_freq(indio_dev, val);
/* Also update the filter */
mutex_unlock(&indio_dev->mlock);
@@ -378,10 +414,14 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
{
int ret;
u16 prod_id, smp_prd;
+ unsigned int device_id;
struct adis16400_state *st = iio_priv(indio_dev);
- /* use low spi speed for init */
- st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+ /* use low spi speed for init if the device has a slow mode */
+ if (st->variant->flags & ADIS16400_HAS_SLOW_MODE)
+ st->us->max_speed_hz = ADIS16400_SPI_SLOW;
+ else
+ st->us->max_speed_hz = ADIS16400_SPI_FAST;
st->us->mode = SPI_MODE_3;
spi_setup(st->us);
@@ -414,19 +454,27 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
if (ret)
goto err_ret;
- if ((prod_id & 0xF000) != st->variant->product_id)
- dev_warn(&indio_dev->dev, "incorrect id");
+ 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->us->chip_select, st->us->irq);
}
/* use high spi speed if possible */
- ret = adis16400_spi_read_reg_16(indio_dev,
- ADIS16400_SMPL_PRD, &smp_prd);
- if (!ret && (smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
- st->us->max_speed_hz = ADIS16400_SPI_SLOW;
- spi_setup(st->us);
+ if (st->variant->flags & ADIS16400_HAS_SLOW_MODE) {
+ ret = adis16400_spi_read_reg_16(indio_dev,
+ ADIS16400_SMPL_PRD, &smp_prd);
+ if (ret)
+ goto err_ret;
+
+ if ((smp_prd & ADIS16400_SMPL_PRD_DIV_MASK) < 0x0A) {
+ st->us->max_speed_hz = ADIS16400_SPI_FAST;
+ spi_setup(st->us);
+ }
}
err_ret:
@@ -503,7 +551,7 @@ static int adis16400_write_raw(struct iio_dev *indio_dev,
mutex_lock(&indio_dev->mlock);
st->filt_int = val;
/* Work out update to current value */
- sps = adis16400_get_freq(indio_dev);
+ sps = st->variant->get_freq(indio_dev);
if (sps < 0) {
mutex_unlock(&indio_dev->mlock);
return sps;
@@ -601,7 +649,7 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
mutex_unlock(&indio_dev->mlock);
return ret;
}
- ret = adis16400_get_freq(indio_dev);
+ val16 = st->variant->get_freq(indio_dev);
if (ret > 0)
*val = ret/adis16400_3db_divisors[val16 & 0x03];
*val2 = 0;
@@ -624,7 +672,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
- .scan_type = IIO_ST('u', 14, 16, 0)
+ .scan_type = IIO_ST('u', 14, 16, 0),
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
@@ -635,7 +683,7 @@ static const struct iio_chan_spec adis16400_channels[] = {
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
- .scan_type = IIO_ST('s', 14, 16, 0)
+ .scan_type = IIO_ST('s', 14, 16, 0),
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
@@ -754,7 +802,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
- .scan_type = IIO_ST('u', 12, 16, 0)
+ .scan_type = IIO_ST('u', 12, 16, 0),
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
@@ -765,7 +813,7 @@ static const struct iio_chan_spec adis16350_channels[] = {
IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY_SHARED_BIT,
.address = gyro_x,
.scan_index = ADIS16400_SCAN_GYRO_X,
- .scan_type = IIO_ST('s', 14, 16, 0)
+ .scan_type = IIO_ST('s', 14, 16, 0),
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
@@ -879,7 +927,7 @@ static const struct iio_chan_spec adis16300_channels[] = {
IIO_CHAN_INFO_SCALE_SEPARATE_BIT,
.address = in_supply,
.scan_index = ADIS16400_SCAN_SUPPLY,
- .scan_type = IIO_ST('u', 12, 16, 0)
+ .scan_type = IIO_ST('u', 12, 16, 0),
}, {
.type = IIO_ANGL_VEL,
.modified = 1,
@@ -1060,6 +1108,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
[ADIS16300] = {
.channels = adis16300_channels,
.num_channels = ARRAY_SIZE(adis16300_channels),
+ .flags = ADIS16400_HAS_SLOW_MODE,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = 5884,
.temp_scale_nano = 140000000, /* 0.14 C */
@@ -1070,10 +1119,13 @@ static struct adis16400_chip_info adis16400_chips[] = {
(1 << ADIS16400_SCAN_TEMP) | (1 << ADIS16400_SCAN_ADC_0) |
(1 << ADIS16300_SCAN_INCLI_X) | (1 << ADIS16300_SCAN_INCLI_Y) |
(1 << 14),
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16334] = {
.channels = adis16334_channels,
.num_channels = ARRAY_SIZE(adis16334_channels),
+ .flags = ADIS16400_HAS_PROD_ID,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
.temp_scale_nano = 67850000, /* 0.06785 C */
@@ -1082,6 +1134,8 @@ static struct adis16400_chip_info adis16400_chips[] = {
(1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
(1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
(1 << ADIS16400_SCAN_ACC_Z),
+ .set_freq = adis16334_set_freq,
+ .get_freq = adis16334_get_freq,
},
[ADIS16350] = {
.channels = adis16350_channels,
@@ -1091,62 +1145,57 @@ static struct adis16400_chip_info adis16400_chips[] = {
.temp_scale_nano = 145300000, /* 0.1453 C */
.temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
.default_scan_mask = 0x7FF,
- .flags = ADIS16400_NO_BURST,
+ .flags = ADIS16400_NO_BURST | ADIS16400_HAS_SLOW_MODE,
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16360] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
- .flags = ADIS16400_HAS_PROD_ID,
- .product_id = 0x3FE8,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
.temp_scale_nano = 136000000, /* 0.136 C */
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.default_scan_mask = 0x7FF,
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16362] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
- .flags = ADIS16400_HAS_PROD_ID,
- .product_id = 0x3FEA,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
.temp_scale_nano = 136000000, /* 0.136 C */
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.default_scan_mask = 0x7FF,
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16364] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
- .flags = ADIS16400_HAS_PROD_ID,
- .product_id = 0x3FEC,
- .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
- .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
- .temp_scale_nano = 136000000, /* 0.136 C */
- .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
- .default_scan_mask = 0x7FF,
- },
- [ADIS16365] = {
- .channels = adis16350_channels,
- .num_channels = ARRAY_SIZE(adis16350_channels),
- .flags = ADIS16400_HAS_PROD_ID,
- .product_id = 0x3FED,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
.temp_scale_nano = 136000000, /* 0.136 C */
.temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
.default_scan_mask = 0x7FF,
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16400] = {
.channels = adis16400_channels,
.num_channels = ARRAY_SIZE(adis16400_channels),
- .flags = ADIS16400_HAS_PROD_ID,
- .product_id = 0x4015,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
.default_scan_mask = 0xFFF,
.temp_scale_nano = 140000000, /* 0.14 C */
.temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
}
};
@@ -1157,7 +1206,7 @@ static const struct iio_info adis16400_info = {
.attrs = &adis16400_attribute_group,
};
-static int __devinit adis16400_probe(struct spi_device *spi)
+static int adis16400_probe(struct spi_device *spi)
{
int ret;
struct adis16400_state *st;
@@ -1224,7 +1273,7 @@ error_ret:
}
/* fixme, confirm ordering in this function */
-static int __devexit adis16400_remove(struct spi_device *spi)
+static int adis16400_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
@@ -1248,7 +1297,7 @@ static const struct spi_device_id adis16400_id[] = {
{"adis16360", ADIS16360},
{"adis16362", ADIS16362},
{"adis16364", ADIS16364},
- {"adis16365", ADIS16365},
+ {"adis16365", ADIS16360},
{"adis16400", ADIS16400},
{"adis16405", ADIS16400},
{}
@@ -1262,7 +1311,7 @@ static struct spi_driver adis16400_driver = {
},
.id_table = adis16400_id,
.probe = adis16400_probe,
- .remove = __devexit_p(adis16400_remove),
+ .remove = adis16400_remove,
};
module_spi_driver(adis16400_driver);