* [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control
@ 2012-10-30 10:26 Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 2/4] staging:iio:adis16400: Fix product id check Lars-Peter Clausen
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-10-30 10:26 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
Setting the sampling frequency for the adis16334 differs from the other devices.
This patch introduces two new callback functions to the adis16400 chip_info
struct which are used to specify how to read and write the current sample rate.
The patch also introduces the proper implementations for these callbacks for the
adis16334.
Related to this is that the adis16334 has no slow mode and so we do not limit
the SPI clock rate to 300kHz during initialization. The patch adds a new flag
for devices which do have a slow mode.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/imu/adis16400.h | 11 ++-
drivers/staging/iio/imu/adis16400_core.c | 122 +++++++++++++++++++++++--------
2 files changed, 101 insertions(+), 32 deletions(-)
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index 77c601d..07a6aea 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -123,6 +123,9 @@
/* SLP_CNT */
#define ADIS16400_SLP_CNT_POWER_OFF (1<<8)
+#define ADIS16334_RATE_DIV_SHIFT 8
+#define ADIS16334_RATE_INT_CLK BIT(0)
+
#define ADIS16400_MAX_TX 24
#define ADIS16400_MAX_RX 24
@@ -130,8 +133,10 @@
#define ADIS16400_SPI_BURST (u32)(1000 * 1000)
#define ADIS16400_SPI_FAST (u32)(2000 * 1000)
-#define ADIS16400_HAS_PROD_ID 1
-#define ADIS16400_NO_BURST 2
+#define ADIS16400_HAS_PROD_ID BIT(0)
+#define ADIS16400_NO_BURST BIT(1)
+#define ADIS16400_HAS_SLOW_MODE BIT(2)
+
struct adis16400_chip_info {
const struct iio_chan_spec *channels;
const int num_channels;
@@ -142,6 +147,8 @@ struct adis16400_chip_info {
int temp_scale_nano;
int temp_offset;
unsigned long default_scan_mask;
+ int (*set_freq)(struct iio_dev *indio_dev, unsigned int freq);
+ int (*get_freq)(struct iio_dev *indio_dev);
};
/**
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 3144a7b..4d03bdc 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -161,10 +161,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 +204,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 +278,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 +287,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);
@@ -380,8 +417,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
u16 prod_id, smp_prd;
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);
@@ -422,11 +462,16 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
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 +548,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 +646,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;
@@ -1060,6 +1105,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,6 +1116,8 @@ 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,
@@ -1082,6 +1130,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 +1141,74 @@ 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,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.product_id = 0x3FE8,
.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,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.product_id = 0x3FEA,
.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,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.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,
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
},
[ADIS16365] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
- .flags = ADIS16400_HAS_PROD_ID,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.product_id = 0x3FED,
.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,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
.product_id = 0x4015,
.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,
}
};
--
1.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] staging:iio:adis16400: Fix product id check
2012-10-30 10:26 [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Lars-Peter Clausen
@ 2012-10-30 10:26 ` Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 3/4] staging:iio:adis16400: Remove now duplicated chip_table entry Lars-Peter Clausen
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-10-30 10:26 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The product id check currently ANDs the read id with 0xF000 and compares the
result to the product id from the chip info. Since none of the product ids in
the chip info table end in 0x000 the check will always fail. Furthermore it is
also wrong, the product id in the PROD_ID register will always match the part
number of the device.
Some of the ADIS16XXX devices are identical from a software point of
view with the product id register having a different content. If we keep the
current scheme of storing the product id in the chip info table this would
require us to have multiple almost identical chip info table entries. So instead
this patch changes the code to parse the product id from the device name.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/imu/adis16400.h | 1 -
drivers/staging/iio/imu/adis16400_core.c | 13 ++++++-------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
index 07a6aea..7a105e9 100644
--- a/drivers/staging/iio/imu/adis16400.h
+++ b/drivers/staging/iio/imu/adis16400.h
@@ -140,7 +140,6 @@
struct adis16400_chip_info {
const struct iio_chan_spec *channels;
const int num_channels;
- const int product_id;
const long flags;
unsigned int gyro_scale_micro;
unsigned int accel_scale_micro;
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 4d03bdc..608bb69 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -415,6 +415,7 @@ 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 if the device has a slow mode */
@@ -454,8 +455,11 @@ 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,
@@ -1149,7 +1153,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
- .product_id = 0x3FE8,
.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 */
@@ -1162,7 +1165,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
- .product_id = 0x3FEA,
.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 */
@@ -1175,7 +1177,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
- .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 */
@@ -1188,7 +1189,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16350_channels,
.num_channels = ARRAY_SIZE(adis16350_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
- .product_id = 0x3FED,
.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 */
@@ -1201,7 +1201,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.channels = adis16400_channels,
.num_channels = ARRAY_SIZE(adis16400_channels),
.flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
- .product_id = 0x4015,
.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,
--
1.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] staging:iio:adis16400: Remove now duplicated chip_table entry
2012-10-30 10:26 [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 2/4] staging:iio:adis16400: Fix product id check Lars-Peter Clausen
@ 2012-10-30 10:26 ` Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 4/4] staging:iio:adis16400: Set the PROD_ID flag for the adis16334 Lars-Peter Clausen
2012-10-31 11:06 ` [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Jonathan Cameron
3 siblings, 0 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-10-30 10:26 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The ADIS1360 and ADIS13605 are very similar and do have the same software
interface. The only difference is the contents of the PROD_ID register. Since we
now read the product id from the device name instead of the chip_info struct we
can use the same chip_table entry for both the ADIS1360 and ADIS13605.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/imu/adis16400_core.c | 15 +--------------
1 file changed, 1 insertion(+), 14 deletions(-)
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index 608bb69..b49858e 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,
};
@@ -1185,18 +1184,6 @@ static struct adis16400_chip_info adis16400_chips[] = {
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
- [ADIS16365] = {
- .channels = adis16350_channels,
- .num_channels = ARRAY_SIZE(adis16350_channels),
- .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),
@@ -1309,7 +1296,7 @@ static const struct spi_device_id adis16400_id[] = {
{"adis16360", ADIS16360},
{"adis16362", ADIS16362},
{"adis16364", ADIS16364},
- {"adis16365", ADIS16365},
+ {"adis16365", ADIS16360},
{"adis16400", ADIS16400},
{"adis16405", ADIS16400},
{}
--
1.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] staging:iio:adis16400: Set the PROD_ID flag for the adis16334
2012-10-30 10:26 [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 2/4] staging:iio:adis16400: Fix product id check Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 3/4] staging:iio:adis16400: Remove now duplicated chip_table entry Lars-Peter Clausen
@ 2012-10-30 10:26 ` Lars-Peter Clausen
2012-10-31 11:06 ` [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Jonathan Cameron
3 siblings, 0 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-10-30 10:26 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, drivers, Lars-Peter Clausen
The adis16334 has the PROD_ID register so set the PROD_ID flag in its chip info.
Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
---
drivers/staging/iio/imu/adis16400_core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
index b49858e..abcdc61 100644
--- a/drivers/staging/iio/imu/adis16400_core.c
+++ b/drivers/staging/iio/imu/adis16400_core.c
@@ -1125,6 +1125,7 @@ static struct adis16400_chip_info adis16400_chips[] = {
[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 */
--
1.8.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control
2012-10-30 10:26 [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Lars-Peter Clausen
` (2 preceding siblings ...)
2012-10-30 10:26 ` [PATCH 4/4] staging:iio:adis16400: Set the PROD_ID flag for the adis16334 Lars-Peter Clausen
@ 2012-10-31 11:06 ` Jonathan Cameron
3 siblings, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2012-10-31 11:06 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: Jonathan Cameron, linux-iio, drivers
On 10/30/2012 10:26 AM, Lars-Peter Clausen wrote:
> Setting the sampling frequency for the adis16334 differs from the other devices.
> This patch introduces two new callback functions to the adis16400 chip_info
> struct which are used to specify how to read and write the current sample rate.
> The patch also introduces the proper implementations for these callbacks for the
> adis16334.
>
> Related to this is that the adis16334 has no slow mode and so we do not limit
> the SPI clock rate to 300kHz during initialization. The patch adds a new flag
> for devices which do have a slow mode.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
All 4 added to fixes-togreg branch of iio.git
They are a little more invasive that I'd normally like, but they
are fixing real problems that could cause the new driver not to work
(other than the duplicate entry removal and I could not be bothered
to separate that one out)
> ---
> drivers/staging/iio/imu/adis16400.h | 11 ++-
> drivers/staging/iio/imu/adis16400_core.c | 122 +++++++++++++++++++++++--------
> 2 files changed, 101 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
> index 77c601d..07a6aea 100644
> --- a/drivers/staging/iio/imu/adis16400.h
> +++ b/drivers/staging/iio/imu/adis16400.h
> @@ -123,6 +123,9 @@
> /* SLP_CNT */
> #define ADIS16400_SLP_CNT_POWER_OFF (1<<8)
>
> +#define ADIS16334_RATE_DIV_SHIFT 8
> +#define ADIS16334_RATE_INT_CLK BIT(0)
> +
> #define ADIS16400_MAX_TX 24
> #define ADIS16400_MAX_RX 24
>
> @@ -130,8 +133,10 @@
> #define ADIS16400_SPI_BURST (u32)(1000 * 1000)
> #define ADIS16400_SPI_FAST (u32)(2000 * 1000)
>
> -#define ADIS16400_HAS_PROD_ID 1
> -#define ADIS16400_NO_BURST 2
> +#define ADIS16400_HAS_PROD_ID BIT(0)
> +#define ADIS16400_NO_BURST BIT(1)
> +#define ADIS16400_HAS_SLOW_MODE BIT(2)
> +
> struct adis16400_chip_info {
> const struct iio_chan_spec *channels;
> const int num_channels;
> @@ -142,6 +147,8 @@ struct adis16400_chip_info {
> int temp_scale_nano;
> int temp_offset;
> unsigned long default_scan_mask;
> + int (*set_freq)(struct iio_dev *indio_dev, unsigned int freq);
> + int (*get_freq)(struct iio_dev *indio_dev);
> };
>
> /**
> diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
> index 3144a7b..4d03bdc 100644
> --- a/drivers/staging/iio/imu/adis16400_core.c
> +++ b/drivers/staging/iio/imu/adis16400_core.c
> @@ -161,10 +161,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 +204,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 +278,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 +287,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);
> @@ -380,8 +417,11 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
> u16 prod_id, smp_prd;
> 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);
>
> @@ -422,11 +462,16 @@ static int adis16400_initial_setup(struct iio_dev *indio_dev)
> 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 +548,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 +646,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;
> @@ -1060,6 +1105,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,6 +1116,8 @@ 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,
> @@ -1082,6 +1130,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 +1141,74 @@ 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,
> + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
> .product_id = 0x3FE8,
> .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,
> + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
> .product_id = 0x3FEA,
> .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,
> + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
> .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,
> + .set_freq = adis16400_set_freq,
> + .get_freq = adis16400_get_freq,
> },
> [ADIS16365] = {
> .channels = adis16350_channels,
> .num_channels = ARRAY_SIZE(adis16350_channels),
> - .flags = ADIS16400_HAS_PROD_ID,
> + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
> .product_id = 0x3FED,
> .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,
> + .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE,
> .product_id = 0x4015,
> .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,
> }
> };
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-10-31 11:06 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-30 10:26 [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 2/4] staging:iio:adis16400: Fix product id check Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 3/4] staging:iio:adis16400: Remove now duplicated chip_table entry Lars-Peter Clausen
2012-10-30 10:26 ` [PATCH 4/4] staging:iio:adis16400: Set the PROD_ID flag for the adis16334 Lars-Peter Clausen
2012-10-31 11:06 ` [PATCH 1/4] staging:iio:adis16400: Fix adis16334 sampling frequency control Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).